From 00ccc8da546733dbdbf1363b2a8d2eed2e29c596 Mon Sep 17 00:00:00 2001 From: Antoine Grondin Date: Tue, 17 Mar 2026 14:27:21 +0900 Subject: [PATCH] refactor!: strip platform features, keep core parse/pretty-print/OTLP/self-update Remove all cloud and platform features (systray, background service, auth, orgs, environments, projects, queries, streaming, onboarding, demo, cloud ingestion, localhost server) to return humanlog to its core mission: a Unix CLI that reads structured logs from stdin, pretty-prints them to stdout, and optionally forwards them to an OTLP endpoint. Kept: - Core stdin parsing and stdout pretty-printing - Self-update (version check/update) infrastructure - Config management (show, show-defaults, reset-to-defaults, set) - New --otlp-endpoint / OTEL_EXPORTER_OTLP_ENDPOINT flag for log forwarding Removed cmd/humanlog files: auth, onboarding, demo, service, systray, api, state, organization, environment, project, query, stream, genny, ingest, helper, localhost Removed internal directories: localserver, localproject, localstate, localalert, localsvc, compat, pkg/iterapi, pkg/absfs, embeds, errutil Removed pkg directories: localstorage, validate, retry, sink/logsvcsink Also: cleaned CI workflows (removed HUMANLOG_GOTAGS), fixed build.sh ldflags variable names, removed connectrpc dependency from otlpsink. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release-dev.yml | 1 - .github/workflows/release.yml | 1 - cmd/humanlog/api.go | 347 - cmd/humanlog/auth.go | 108 - cmd/humanlog/config.go | 151 - cmd/humanlog/demo.go | 220 - cmd/humanlog/environment.go | 457 - cmd/humanlog/genny.go | 403 - cmd/humanlog/helper.go | 494 - cmd/humanlog/ingest.go | 304 - cmd/humanlog/localhost.go | 39 - cmd/humanlog/main.go | 382 +- cmd/humanlog/onboarding.go | 356 - cmd/humanlog/organization.go | 246 - cmd/humanlog/project.go | 333 - cmd/humanlog/query.go | 512 - cmd/humanlog/query_test.go | 69 - cmd/humanlog/service.go | 918 - cmd/humanlog/service_darwin.go | 183 - cmd/humanlog/service_other.go | 13 - cmd/humanlog/state.go | 88 - cmd/humanlog/stream.go | 244 - cmd/humanlog/systray_darwin.go | 477 - cmd/humanlog/systray_other.go | 44 - docs/alert-architecture-summary.md | 424 + docs/dashboard-authoring-proposal.md | 1146 ++ go.mod | 119 +- go.sum | 353 - internal/compat/alertmanager/parse.go | 109 - .../embeds/assets/icon/systray/humanlog.icns | Bin 1597129 -> 0 bytes .../icon/systray/humanlog_icon_512x512.png | Bin 73576 -> 0 bytes internal/embeds/embed.go | 12 - internal/errutil/errors.go | 26 - internal/errutil/errors_unix.go | 13 - internal/errutil/errors_windows.go | 13 - internal/errutil/errutil_test.go | 24 - internal/localalert/alert.go | 248 - internal/localalert/alert_test.go | 487 - .../alert_group_lifecycle_test.go | 1077 -- .../localproject/dashboard_lifecycle_test.go | 2345 --- internal/localproject/db.go | 123 - internal/localproject/errors.go | 29 - internal/localproject/fs.go | 1319 -- internal/localproject/fs_test.go | 54 - internal/localproject/git.go | 401 - internal/localproject/git_test.go | 130 - internal/localproject/storage_test_suite.go | 1169 -- internal/localproject/watch.go | 879 - internal/localproject/watch_test.go | 665 - internal/localserver/alert_scheduler.go | 443 - internal/localserver/alert_scheduler_test.go | 798 - internal/localserver/alert_status_test.go | 264 - internal/localserver/server.go | 295 - internal/localstate/inmem.go | 757 - internal/localstate/localstate.go | 37 - internal/localsvc/otlp.go | 182 - internal/localsvc/otlp_codec.go | 317 - internal/localsvc/svc.go | 844 - internal/pkg/absfs/fs.go | 21 - internal/pkg/config/config.go | 112 +- internal/pkg/iterapi/iter.go | 71 - pkg/localstorage/queryable.go | 152 - pkg/localstorage/test_suite.go | 335 - pkg/retry/retry.go | 114 - pkg/retry/retry_test.go | 44 - pkg/sink/logsvcsink/stream_sink.go | 242 - pkg/sink/logsvcsink/unary_sink.go | 209 - pkg/sink/otlpsink/otlp_sink.go | 9 +- pkg/validate/validate.go | 37 - script/build.sh | 13 +- vendor/connectrpc.com/cors/.gitignore | 4 - vendor/connectrpc.com/cors/.golangci.yml | 54 - vendor/connectrpc.com/cors/LICENSE | 201 - vendor/connectrpc.com/cors/MAINTAINERS.md | 7 - vendor/connectrpc.com/cors/Makefile | 73 - vendor/connectrpc.com/cors/README.md | 85 - vendor/connectrpc.com/cors/SECURITY.md | 5 - vendor/connectrpc.com/cors/cors.go | 66 - vendor/connectrpc.com/otelconnect/.gitignore | 4 - .../connectrpc.com/otelconnect/.golangci.yml | 66 - vendor/connectrpc.com/otelconnect/LICENSE | 201 - .../connectrpc.com/otelconnect/MAINTAINERS.md | 10 - vendor/connectrpc.com/otelconnect/Makefile | 98 - vendor/connectrpc.com/otelconnect/README.md | 144 - vendor/connectrpc.com/otelconnect/SECURITY.md | 5 - .../connectrpc.com/otelconnect/attributes.go | 137 - .../connectrpc.com/otelconnect/buf.gen.yaml | 13 - vendor/connectrpc.com/otelconnect/buf.yaml | 15 - vendor/connectrpc.com/otelconnect/doc.go | 24 - .../connectrpc.com/otelconnect/instruments.go | 106 - .../connectrpc.com/otelconnect/interceptor.go | 402 - vendor/connectrpc.com/otelconnect/option.go | 213 - .../connectrpc.com/otelconnect/otelconnect.go | 49 - .../otelconnect/payloadinterceptor.go | 56 - .../connectrpc.com/otelconnect/streaming.go | 143 - .../Microsoft/go-winio/.gitattributes | 1 - .../github.com/Microsoft/go-winio/.gitignore | 10 - .../Microsoft/go-winio/.golangci.yml | 147 - .../github.com/Microsoft/go-winio/CODEOWNERS | 1 - vendor/github.com/Microsoft/go-winio/LICENSE | 22 - .../github.com/Microsoft/go-winio/README.md | 89 - .../github.com/Microsoft/go-winio/SECURITY.md | 41 - .../github.com/Microsoft/go-winio/backup.go | 287 - vendor/github.com/Microsoft/go-winio/doc.go | 22 - vendor/github.com/Microsoft/go-winio/ea.go | 137 - vendor/github.com/Microsoft/go-winio/file.go | 320 - .../github.com/Microsoft/go-winio/fileinfo.go | 106 - .../github.com/Microsoft/go-winio/hvsock.go | 582 - .../Microsoft/go-winio/internal/fs/doc.go | 2 - .../Microsoft/go-winio/internal/fs/fs.go | 262 - .../go-winio/internal/fs/security.go | 12 - .../go-winio/internal/fs/zsyscall_windows.go | 61 - .../go-winio/internal/socket/rawaddr.go | 20 - .../go-winio/internal/socket/socket.go | 177 - .../internal/socket/zsyscall_windows.go | 69 - .../go-winio/internal/stringbuffer/wstring.go | 132 - vendor/github.com/Microsoft/go-winio/pipe.go | 586 - .../Microsoft/go-winio/pkg/guid/guid.go | 232 - .../go-winio/pkg/guid/guid_nonwindows.go | 16 - .../go-winio/pkg/guid/guid_windows.go | 13 - .../go-winio/pkg/guid/variant_string.go | 27 - .../Microsoft/go-winio/privilege.go | 196 - .../github.com/Microsoft/go-winio/reparse.go | 131 - vendor/github.com/Microsoft/go-winio/sd.go | 133 - .../github.com/Microsoft/go-winio/syscall.go | 5 - .../Microsoft/go-winio/zsyscall_windows.go | 378 - .../NimbleMarkets/ntcharts/LICENSE.txt | 21 - .../ntcharts/canvas/buffer/buffer.go | 342 - .../NimbleMarkets/ntcharts/canvas/canvas.go | 514 - .../ntcharts/canvas/graph/graph.go | 737 - .../NimbleMarkets/ntcharts/canvas/options.go | 86 - .../ntcharts/canvas/runes/runes.go | 457 - .../ntcharts/canvas/updatehandler.go | 155 - .../ntcharts/linechart/linechart.go | 733 - .../ntcharts/linechart/options.go | 103 - .../linechart/timeserieslinechart/options.go | 139 - .../timeserieslinechart.go | 450 - .../timeserieslinechart/updatehandler.go | 77 - .../ntcharts/linechart/updatehandler.go | 361 - .../github.com/ProtonMail/go-crypto/AUTHORS | 3 - .../ProtonMail/go-crypto/CONTRIBUTORS | 3 - .../github.com/ProtonMail/go-crypto/LICENSE | 27 - .../github.com/ProtonMail/go-crypto/PATENTS | 22 - .../go-crypto/bitcurves/bitcurve.go | 381 - .../go-crypto/brainpool/brainpool.go | 134 - .../ProtonMail/go-crypto/brainpool/rcurve.go | 83 - .../ProtonMail/go-crypto/eax/eax.go | 162 - .../go-crypto/eax/eax_test_vectors.go | 58 - .../go-crypto/eax/random_vectors.go | 131 - .../go-crypto/internal/byteutil/byteutil.go | 90 - .../ProtonMail/go-crypto/ocb/ocb.go | 313 - .../go-crypto/ocb/random_vectors.go | 136 - .../ocb/rfc7253_test_vectors_suite_a.go | 78 - .../ocb/rfc7253_test_vectors_suite_b.go | 25 - .../go-crypto/openpgp/aes/keywrap/keywrap.go | 153 - .../go-crypto/openpgp/armor/armor.go | 183 - .../go-crypto/openpgp/armor/encode.go | 206 - .../go-crypto/openpgp/canonical_text.go | 71 - .../ProtonMail/go-crypto/openpgp/ecdh/ecdh.go | 206 - .../go-crypto/openpgp/ecdsa/ecdsa.go | 80 - .../go-crypto/openpgp/ed25519/ed25519.go | 115 - .../go-crypto/openpgp/ed448/ed448.go | 119 - .../go-crypto/openpgp/eddsa/eddsa.go | 91 - .../go-crypto/openpgp/elgamal/elgamal.go | 124 - .../go-crypto/openpgp/errors/errors.go | 210 - .../ProtonMail/go-crypto/openpgp/hash.go | 24 - .../openpgp/internal/algorithm/aead.go | 65 - .../openpgp/internal/algorithm/cipher.go | 97 - .../openpgp/internal/algorithm/hash.go | 143 - .../openpgp/internal/ecc/curve25519.go | 171 - .../openpgp/internal/ecc/curve_info.go | 143 - .../go-crypto/openpgp/internal/ecc/curves.go | 48 - .../go-crypto/openpgp/internal/ecc/ed25519.go | 120 - .../go-crypto/openpgp/internal/ecc/ed448.go | 119 - .../go-crypto/openpgp/internal/ecc/generic.go | 149 - .../go-crypto/openpgp/internal/ecc/x448.go | 107 - .../openpgp/internal/encoding/encoding.go | 27 - .../openpgp/internal/encoding/mpi.go | 91 - .../openpgp/internal/encoding/oid.go | 88 - .../go-crypto/openpgp/key_generation.go | 456 - .../ProtonMail/go-crypto/openpgp/keys.go | 901 - .../go-crypto/openpgp/keys_test_data.go | 538 - .../go-crypto/openpgp/packet/aead_config.go | 67 - .../go-crypto/openpgp/packet/aead_crypter.go | 250 - .../openpgp/packet/aead_encrypted.go | 100 - .../go-crypto/openpgp/packet/compressed.go | 192 - .../go-crypto/openpgp/packet/config.go | 434 - .../go-crypto/openpgp/packet/config_v5.go | 7 - .../go-crypto/openpgp/packet/encrypted_key.go | 584 - .../go-crypto/openpgp/packet/literal.go | 91 - .../go-crypto/openpgp/packet/marker.go | 33 - .../go-crypto/openpgp/packet/notation.go | 29 - .../go-crypto/openpgp/packet/ocfb.go | 137 - .../openpgp/packet/one_pass_signature.go | 157 - .../go-crypto/openpgp/packet/opaque.go | 170 - .../go-crypto/openpgp/packet/packet.go | 675 - .../openpgp/packet/packet_sequence.go | 222 - .../openpgp/packet/packet_unsupported.go | 24 - .../go-crypto/openpgp/packet/padding.go | 26 - .../go-crypto/openpgp/packet/private_key.go | 1191 -- .../openpgp/packet/private_key_test_data.go | 12 - .../go-crypto/openpgp/packet/public_key.go | 1125 -- .../openpgp/packet/public_key_test_data.go | 24 - .../go-crypto/openpgp/packet/reader.go | 209 - .../go-crypto/openpgp/packet/recipient.go | 15 - .../go-crypto/openpgp/packet/signature.go | 1511 -- .../openpgp/packet/symmetric_key_encrypted.go | 331 - .../openpgp/packet/symmetrically_encrypted.go | 94 - .../packet/symmetrically_encrypted_aead.go | 168 - .../packet/symmetrically_encrypted_mdc.go | 256 - .../go-crypto/openpgp/packet/userattribute.go | 100 - .../go-crypto/openpgp/packet/userid.go | 166 - .../ProtonMail/go-crypto/openpgp/read.go | 619 - .../go-crypto/openpgp/read_write_test_data.go | 457 - .../ProtonMail/go-crypto/openpgp/s2k/s2k.go | 436 - .../go-crypto/openpgp/s2k/s2k_cache.go | 26 - .../go-crypto/openpgp/s2k/s2k_config.go | 129 - .../ProtonMail/go-crypto/openpgp/write.go | 690 - .../go-crypto/openpgp/x25519/x25519.go | 221 - .../ProtonMail/go-crypto/openpgp/x448/x448.go | 229 - .../alecthomas/chroma/v2/.editorconfig | 17 - .../alecthomas/chroma/v2/.gitignore | 25 - .../alecthomas/chroma/v2/.golangci.yml | 92 - .../alecthomas/chroma/v2/.goreleaser.yml | 37 - .../github.com/alecthomas/chroma/v2/Bitfile | 24 - .../github.com/alecthomas/chroma/v2/COPYING | 19 - .../github.com/alecthomas/chroma/v2/Makefile | 23 - .../github.com/alecthomas/chroma/v2/README.md | 297 - .../alecthomas/chroma/v2/coalesce.go | 35 - .../github.com/alecthomas/chroma/v2/colour.go | 192 - .../alecthomas/chroma/v2/delegate.go | 152 - vendor/github.com/alecthomas/chroma/v2/doc.go | 7 - .../alecthomas/chroma/v2/emitters.go | 218 - .../alecthomas/chroma/v2/formatter.go | 43 - .../alecthomas/chroma/v2/formatters/api.go | 57 - .../chroma/v2/formatters/html/html.go | 623 - .../alecthomas/chroma/v2/formatters/json.go | 31 - .../v2/formatters/svg/font_liberation_mono.go | 51 - .../chroma/v2/formatters/svg/svg.go | 222 - .../alecthomas/chroma/v2/formatters/tokens.go | 18 - .../chroma/v2/formatters/tty_indexed.go | 291 - .../chroma/v2/formatters/tty_truecolour.go | 42 - .../alecthomas/chroma/v2/iterator.go | 76 - .../github.com/alecthomas/chroma/v2/lexer.go | 162 - .../alecthomas/chroma/v2/lexers/README.md | 46 - .../alecthomas/chroma/v2/lexers/caddyfile.go | 275 - .../alecthomas/chroma/v2/lexers/cl.go | 243 - .../alecthomas/chroma/v2/lexers/dns.go | 17 - .../alecthomas/chroma/v2/lexers/emacs.go | 533 - .../chroma/v2/lexers/embedded/abap.xml | 154 - .../chroma/v2/lexers/embedded/abnf.xml | 66 - .../v2/lexers/embedded/actionscript.xml | 68 - .../v2/lexers/embedded/actionscript_3.xml | 163 - .../chroma/v2/lexers/embedded/ada.xml | 321 - .../chroma/v2/lexers/embedded/agda.xml | 66 - .../chroma/v2/lexers/embedded/al.xml | 75 - .../chroma/v2/lexers/embedded/alloy.xml | 58 - .../chroma/v2/lexers/embedded/angular2.xml | 108 - .../chroma/v2/lexers/embedded/antlr.xml | 317 - .../chroma/v2/lexers/embedded/apacheconf.xml | 74 - .../chroma/v2/lexers/embedded/apl.xml | 59 - .../chroma/v2/lexers/embedded/applescript.xml | 130 - .../v2/lexers/embedded/arangodb_aql.xml | 174 - .../chroma/v2/lexers/embedded/arduino.xml | 309 - .../chroma/v2/lexers/embedded/armasm.xml | 126 - .../chroma/v2/lexers/embedded/autohotkey.xml | 78 - .../chroma/v2/lexers/embedded/autoit.xml | 70 - .../chroma/v2/lexers/embedded/awk.xml | 95 - .../chroma/v2/lexers/embedded/ballerina.xml | 97 - .../chroma/v2/lexers/embedded/bash.xml | 220 - .../v2/lexers/embedded/bash_session.xml | 25 - .../chroma/v2/lexers/embedded/batchfile.xml | 660 - .../chroma/v2/lexers/embedded/bibtex.xml | 152 - .../chroma/v2/lexers/embedded/bicep.xml | 84 - .../chroma/v2/lexers/embedded/blitzbasic.xml | 141 - .../chroma/v2/lexers/embedded/bnf.xml | 28 - .../chroma/v2/lexers/embedded/bqn.xml | 83 - .../chroma/v2/lexers/embedded/brainfuck.xml | 51 - .../chroma/v2/lexers/embedded/c#.xml | 121 - .../chroma/v2/lexers/embedded/c++.xml | 331 - .../chroma/v2/lexers/embedded/c.xml | 260 - .../chroma/v2/lexers/embedded/cap_n_proto.xml | 122 - .../v2/lexers/embedded/cassandra_cql.xml | 137 - .../chroma/v2/lexers/embedded/ceylon.xml | 151 - .../chroma/v2/lexers/embedded/cfengine3.xml | 197 - .../chroma/v2/lexers/embedded/cfstatement.xml | 92 - .../chroma/v2/lexers/embedded/chaiscript.xml | 134 - .../chroma/v2/lexers/embedded/chapel.xml | 143 - .../chroma/v2/lexers/embedded/cheetah.xml | 55 - .../chroma/v2/lexers/embedded/clojure.xml | 71 - .../chroma/v2/lexers/embedded/cmake.xml | 90 - .../chroma/v2/lexers/embedded/cobol.xml | 90 - .../v2/lexers/embedded/coffeescript.xml | 210 - .../chroma/v2/lexers/embedded/common_lisp.xml | 184 - .../chroma/v2/lexers/embedded/coq.xml | 136 - .../chroma/v2/lexers/embedded/crystal.xml | 762 - .../chroma/v2/lexers/embedded/css.xml | 323 - .../chroma/v2/lexers/embedded/cue.xml | 85 - .../chroma/v2/lexers/embedded/cython.xml | 372 - .../chroma/v2/lexers/embedded/d.xml | 133 - .../chroma/v2/lexers/embedded/dart.xml | 213 - .../chroma/v2/lexers/embedded/dax.xml | 39 - .../v2/lexers/embedded/desktop_entry.xml | 17 - .../chroma/v2/lexers/embedded/diff.xml | 52 - .../v2/lexers/embedded/django_jinja.xml | 153 - .../chroma/v2/lexers/embedded/dns.xml | 44 - .../chroma/v2/lexers/embedded/docker.xml | 57 - .../chroma/v2/lexers/embedded/dtd.xml | 168 - .../chroma/v2/lexers/embedded/dylan.xml | 176 - .../chroma/v2/lexers/embedded/ebnf.xml | 90 - .../chroma/v2/lexers/embedded/elixir.xml | 744 - .../chroma/v2/lexers/embedded/elm.xml | 119 - .../chroma/v2/lexers/embedded/emacslisp.xml | 132 - .../chroma/v2/lexers/embedded/erlang.xml | 166 - .../chroma/v2/lexers/embedded/factor.xml | 412 - .../chroma/v2/lexers/embedded/fennel.xml | 68 - .../chroma/v2/lexers/embedded/fish.xml | 159 - .../chroma/v2/lexers/embedded/forth.xml | 78 - .../chroma/v2/lexers/embedded/fortran.xml | 102 - .../v2/lexers/embedded/fortranfixed.xml | 71 - .../chroma/v2/lexers/embedded/fsharp.xml | 245 - .../chroma/v2/lexers/embedded/gas.xml | 150 - .../chroma/v2/lexers/embedded/gdscript.xml | 259 - .../chroma/v2/lexers/embedded/gdscript3.xml | 270 - .../chroma/v2/lexers/embedded/gherkin.xml | 263 - .../chroma/v2/lexers/embedded/gleam.xml | 117 - .../chroma/v2/lexers/embedded/glsl.xml | 65 - .../chroma/v2/lexers/embedded/gnuplot.xml | 289 - .../chroma/v2/lexers/embedded/go_template.xml | 114 - .../chroma/v2/lexers/embedded/graphql.xml | 88 - .../chroma/v2/lexers/embedded/groff.xml | 90 - .../chroma/v2/lexers/embedded/groovy.xml | 135 - .../chroma/v2/lexers/embedded/handlebars.xml | 147 - .../chroma/v2/lexers/embedded/hare.xml | 98 - .../chroma/v2/lexers/embedded/haskell.xml | 272 - .../chroma/v2/lexers/embedded/hcl.xml | 143 - .../chroma/v2/lexers/embedded/hexdump.xml | 189 - .../chroma/v2/lexers/embedded/hlb.xml | 149 - .../chroma/v2/lexers/embedded/hlsl.xml | 110 - .../chroma/v2/lexers/embedded/holyc.xml | 252 - .../chroma/v2/lexers/embedded/html.xml | 159 - .../chroma/v2/lexers/embedded/hy.xml | 104 - .../chroma/v2/lexers/embedded/idris.xml | 216 - .../chroma/v2/lexers/embedded/igor.xml | 47 - .../chroma/v2/lexers/embedded/ini.xml | 45 - .../chroma/v2/lexers/embedded/io.xml | 71 - .../chroma/v2/lexers/embedded/iscdhcpd.xml | 96 - .../chroma/v2/lexers/embedded/j.xml | 157 - .../chroma/v2/lexers/embedded/java.xml | 193 - .../chroma/v2/lexers/embedded/javascript.xml | 160 - .../chroma/v2/lexers/embedded/json.xml | 111 - .../chroma/v2/lexers/embedded/julia.xml | 400 - .../chroma/v2/lexers/embedded/jungle.xml | 98 - .../chroma/v2/lexers/embedded/kotlin.xml | 223 - .../embedded/lighttpd_configuration_file.xml | 42 - .../chroma/v2/lexers/embedded/llvm.xml | 73 - .../chroma/v2/lexers/embedded/lua.xml | 158 - .../chroma/v2/lexers/embedded/makefile.xml | 131 - .../chroma/v2/lexers/embedded/mako.xml | 120 - .../chroma/v2/lexers/embedded/mason.xml | 89 - .../embedded/materialize_sql_dialect.xml | 155 - .../chroma/v2/lexers/embedded/mathematica.xml | 60 - .../chroma/v2/lexers/embedded/matlab.xml | 114 - .../chroma/v2/lexers/embedded/mcfunction.xml | 182 - .../chroma/v2/lexers/embedded/meson.xml | 85 - .../chroma/v2/lexers/embedded/metal.xml | 270 - .../chroma/v2/lexers/embedded/minizinc.xml | 82 - .../chroma/v2/lexers/embedded/mlir.xml | 73 - .../chroma/v2/lexers/embedded/modula-2.xml | 245 - .../chroma/v2/lexers/embedded/monkeyc.xml | 153 - .../v2/lexers/embedded/morrowindscript.xml | 90 - .../chroma/v2/lexers/embedded/myghty.xml | 77 - .../chroma/v2/lexers/embedded/mysql.xml | 121 - .../chroma/v2/lexers/embedded/nasm.xml | 126 - .../chroma/v2/lexers/embedded/natural.xml | 143 - .../chroma/v2/lexers/embedded/ndisasm.xml | 123 - .../chroma/v2/lexers/embedded/newspeak.xml | 121 - .../embedded/nginx_configuration_file.xml | 98 - .../chroma/v2/lexers/embedded/nim.xml | 211 - .../chroma/v2/lexers/embedded/nix.xml | 258 - .../chroma/v2/lexers/embedded/objective-c.xml | 510 - .../v2/lexers/embedded/objectpascal.xml | 145 - .../chroma/v2/lexers/embedded/ocaml.xml | 145 - .../chroma/v2/lexers/embedded/octave.xml | 101 - .../chroma/v2/lexers/embedded/odin.xml | 113 - .../v2/lexers/embedded/onesenterprise.xml | 92 - .../v2/lexers/embedded/openedge_abl.xml | 101 - .../chroma/v2/lexers/embedded/openscad.xml | 96 - .../chroma/v2/lexers/embedded/org_mode.xml | 329 - .../chroma/v2/lexers/embedded/pacmanconf.xml | 37 - .../chroma/v2/lexers/embedded/perl.xml | 400 - .../chroma/v2/lexers/embedded/php.xml | 212 - .../chroma/v2/lexers/embedded/pig.xml | 105 - .../chroma/v2/lexers/embedded/pkgconfig.xml | 73 - .../chroma/v2/lexers/embedded/pl_pgsql.xml | 119 - .../chroma/v2/lexers/embedded/plaintext.xml | 21 - .../chroma/v2/lexers/embedded/plutus_core.xml | 105 - .../chroma/v2/lexers/embedded/pony.xml | 135 - .../embedded/postgresql_sql_dialect.xml | 155 - .../chroma/v2/lexers/embedded/postscript.xml | 89 - .../chroma/v2/lexers/embedded/povray.xml | 58 - .../chroma/v2/lexers/embedded/powerquery.xml | 51 - .../chroma/v2/lexers/embedded/powershell.xml | 230 - .../chroma/v2/lexers/embedded/prolog.xml | 115 - .../chroma/v2/lexers/embedded/promela.xml | 119 - .../chroma/v2/lexers/embedded/promql.xml | 123 - .../chroma/v2/lexers/embedded/properties.xml | 45 - .../v2/lexers/embedded/protocol_buffer.xml | 118 - .../chroma/v2/lexers/embedded/prql.xml | 161 - .../chroma/v2/lexers/embedded/psl.xml | 213 - .../chroma/v2/lexers/embedded/puppet.xml | 100 - .../chroma/v2/lexers/embedded/python.xml | 593 - .../chroma/v2/lexers/embedded/python_2.xml | 356 - .../chroma/v2/lexers/embedded/qbasic.xml | 173 - .../chroma/v2/lexers/embedded/qml.xml | 113 - .../chroma/v2/lexers/embedded/r.xml | 128 - .../chroma/v2/lexers/embedded/racket.xml | 260 - .../chroma/v2/lexers/embedded/ragel.xml | 149 - .../chroma/v2/lexers/embedded/react.xml | 236 - .../chroma/v2/lexers/embedded/reasonml.xml | 147 - .../chroma/v2/lexers/embedded/reg.xml | 68 - .../chroma/v2/lexers/embedded/rego.xml | 94 - .../chroma/v2/lexers/embedded/rexx.xml | 127 - .../chroma/v2/lexers/embedded/rpm_spec.xml | 58 - .../chroma/v2/lexers/embedded/ruby.xml | 724 - .../chroma/v2/lexers/embedded/rust.xml | 375 - .../chroma/v2/lexers/embedded/sas.xml | 191 - .../chroma/v2/lexers/embedded/sass.xml | 362 - .../chroma/v2/lexers/embedded/scala.xml | 274 - .../chroma/v2/lexers/embedded/scheme.xml | 106 - .../chroma/v2/lexers/embedded/scilab.xml | 98 - .../chroma/v2/lexers/embedded/scss.xml | 373 - .../chroma/v2/lexers/embedded/sed.xml | 28 - .../chroma/v2/lexers/embedded/sieve.xml | 61 - .../chroma/v2/lexers/embedded/smali.xml | 73 - .../chroma/v2/lexers/embedded/smalltalk.xml | 294 - .../chroma/v2/lexers/embedded/smarty.xml | 79 - .../chroma/v2/lexers/embedded/snobol.xml | 95 - .../chroma/v2/lexers/embedded/solidity.xml | 279 - .../chroma/v2/lexers/embedded/sourcepawn.xml | 59 - .../chroma/v2/lexers/embedded/sparql.xml | 160 - .../chroma/v2/lexers/embedded/sql.xml | 90 - .../chroma/v2/lexers/embedded/squidconf.xml | 63 - .../chroma/v2/lexers/embedded/standard_ml.xml | 548 - .../chroma/v2/lexers/embedded/stas.xml | 85 - .../chroma/v2/lexers/embedded/stylus.xml | 132 - .../chroma/v2/lexers/embedded/swift.xml | 207 - .../chroma/v2/lexers/embedded/systemd.xml | 63 - .../v2/lexers/embedded/systemverilog.xml | 181 - .../chroma/v2/lexers/embedded/tablegen.xml | 69 - .../chroma/v2/lexers/embedded/tal.xml | 43 - .../chroma/v2/lexers/embedded/tasm.xml | 135 - .../chroma/v2/lexers/embedded/tcl.xml | 272 - .../chroma/v2/lexers/embedded/tcsh.xml | 121 - .../chroma/v2/lexers/embedded/termcap.xml | 75 - .../chroma/v2/lexers/embedded/terminfo.xml | 84 - .../chroma/v2/lexers/embedded/terraform.xml | 140 - .../chroma/v2/lexers/embedded/tex.xml | 113 - .../chroma/v2/lexers/embedded/thrift.xml | 154 - .../chroma/v2/lexers/embedded/toml.xml | 44 - .../chroma/v2/lexers/embedded/tradingview.xml | 81 - .../v2/lexers/embedded/transact-sql.xml | 137 - .../chroma/v2/lexers/embedded/turing.xml | 82 - .../chroma/v2/lexers/embedded/turtle.xml | 170 - .../chroma/v2/lexers/embedded/twig.xml | 155 - .../chroma/v2/lexers/embedded/typescript.xml | 279 - .../chroma/v2/lexers/embedded/typoscript.xml | 178 - .../v2/lexers/embedded/typoscriptcssdata.xml | 52 - .../v2/lexers/embedded/typoscripthtmldata.xml | 52 - .../chroma/v2/lexers/embedded/ucode.xml | 147 - .../chroma/v2/lexers/embedded/v.xml | 355 - .../chroma/v2/lexers/embedded/v_shell.xml | 365 - .../chroma/v2/lexers/embedded/vala.xml | 72 - .../chroma/v2/lexers/embedded/vb_net.xml | 162 - .../chroma/v2/lexers/embedded/verilog.xml | 158 - .../chroma/v2/lexers/embedded/vhdl.xml | 171 - .../chroma/v2/lexers/embedded/vhs.xml | 48 - .../chroma/v2/lexers/embedded/viml.xml | 85 - .../chroma/v2/lexers/embedded/vue.xml | 307 - .../chroma/v2/lexers/embedded/wdte.xml | 43 - .../embedded/webgpu_shading_language.xml | 142 - .../chroma/v2/lexers/embedded/whiley.xml | 57 - .../chroma/v2/lexers/embedded/xml.xml | 95 - .../chroma/v2/lexers/embedded/xorg.xml | 35 - .../chroma/v2/lexers/embedded/yaml.xml | 122 - .../chroma/v2/lexers/embedded/yang.xml | 99 - .../v2/lexers/embedded/z80_assembly.xml | 74 - .../chroma/v2/lexers/embedded/zed.xml | 51 - .../chroma/v2/lexers/embedded/zig.xml | 112 - .../alecthomas/chroma/v2/lexers/genshi.go | 118 - .../alecthomas/chroma/v2/lexers/go.go | 82 - .../alecthomas/chroma/v2/lexers/haxe.go | 647 - .../alecthomas/chroma/v2/lexers/html.go | 8 - .../alecthomas/chroma/v2/lexers/http.go | 131 - .../alecthomas/chroma/v2/lexers/lexers.go | 79 - .../alecthomas/chroma/v2/lexers/markdown.go | 47 - .../alecthomas/chroma/v2/lexers/mysql.go | 33 - .../alecthomas/chroma/v2/lexers/php.go | 37 - .../alecthomas/chroma/v2/lexers/raku.go | 1721 -- .../alecthomas/chroma/v2/lexers/rst.go | 89 - .../alecthomas/chroma/v2/lexers/svelte.go | 70 - .../alecthomas/chroma/v2/lexers/typoscript.go | 85 - .../alecthomas/chroma/v2/lexers/zed.go | 24 - .../alecthomas/chroma/v2/mutators.go | 201 - .../alecthomas/chroma/v2/pygments-lexers.txt | 322 - .../alecthomas/chroma/v2/quick/quick.go | 44 - .../github.com/alecthomas/chroma/v2/regexp.go | 483 - .../alecthomas/chroma/v2/registry.go | 210 - .../github.com/alecthomas/chroma/v2/remap.go | 94 - .../alecthomas/chroma/v2/renovate.json5 | 18 - .../alecthomas/chroma/v2/serialise.go | 479 - .../github.com/alecthomas/chroma/v2/style.go | 481 - .../alecthomas/chroma/v2/styles/abap.xml | 11 - .../alecthomas/chroma/v2/styles/algol.xml | 18 - .../alecthomas/chroma/v2/styles/algol_nu.xml | 18 - .../alecthomas/chroma/v2/styles/api.go | 65 - .../alecthomas/chroma/v2/styles/arduino.xml | 18 - .../alecthomas/chroma/v2/styles/autumn.xml | 36 - .../alecthomas/chroma/v2/styles/average.xml | 74 - .../chroma/v2/styles/base16-snazzy.xml | 74 - .../alecthomas/chroma/v2/styles/borland.xml | 26 - .../alecthomas/chroma/v2/styles/bw.xml | 23 - .../chroma/v2/styles/catppuccin-frappe.xml | 83 - .../chroma/v2/styles/catppuccin-latte.xml | 83 - .../chroma/v2/styles/catppuccin-macchiato.xml | 83 - .../chroma/v2/styles/catppuccin-mocha.xml | 83 - .../alecthomas/chroma/v2/styles/colorful.xml | 52 - .../alecthomas/chroma/v2/styles/compat.go | 66 - .../alecthomas/chroma/v2/styles/doom-one.xml | 51 - .../alecthomas/chroma/v2/styles/doom-one2.xml | 64 - .../alecthomas/chroma/v2/styles/dracula.xml | 74 - .../alecthomas/chroma/v2/styles/emacs.xml | 44 - .../alecthomas/chroma/v2/styles/friendly.xml | 44 - .../alecthomas/chroma/v2/styles/fruity.xml | 19 - .../chroma/v2/styles/github-dark.xml | 45 - .../alecthomas/chroma/v2/styles/github.xml | 44 - .../chroma/v2/styles/gruvbox-light.xml | 33 - .../alecthomas/chroma/v2/styles/gruvbox.xml | 33 - .../chroma/v2/styles/hr_high_contrast.xml | 12 - .../alecthomas/chroma/v2/styles/hrdark.xml | 10 - .../alecthomas/chroma/v2/styles/igor.xml | 9 - .../alecthomas/chroma/v2/styles/lovelace.xml | 53 - .../alecthomas/chroma/v2/styles/manni.xml | 44 - .../chroma/v2/styles/modus-operandi.xml | 13 - .../chroma/v2/styles/modus-vivendi.xml | 13 - .../alecthomas/chroma/v2/styles/monokai.xml | 29 - .../chroma/v2/styles/monokailight.xml | 26 - .../alecthomas/chroma/v2/styles/murphy.xml | 52 - .../alecthomas/chroma/v2/styles/native.xml | 35 - .../alecthomas/chroma/v2/styles/nord.xml | 46 - .../alecthomas/chroma/v2/styles/onedark.xml | 25 - .../chroma/v2/styles/onesenterprise.xml | 10 - .../chroma/v2/styles/paraiso-dark.xml | 37 - .../chroma/v2/styles/paraiso-light.xml | 37 - .../alecthomas/chroma/v2/styles/pastie.xml | 45 - .../alecthomas/chroma/v2/styles/perldoc.xml | 37 - .../alecthomas/chroma/v2/styles/pygments.xml | 42 - .../chroma/v2/styles/rainbow_dash.xml | 40 - .../chroma/v2/styles/rose-pine-dawn.xml | 29 - .../chroma/v2/styles/rose-pine-moon.xml | 29 - .../alecthomas/chroma/v2/styles/rose-pine.xml | 29 - .../alecthomas/chroma/v2/styles/rrt.xml | 13 - .../chroma/v2/styles/solarized-dark.xml | 39 - .../chroma/v2/styles/solarized-dark256.xml | 41 - .../chroma/v2/styles/solarized-light.xml | 17 - .../alecthomas/chroma/v2/styles/swapoff.xml | 18 - .../alecthomas/chroma/v2/styles/tango.xml | 72 - .../chroma/v2/styles/tokyonight-day.xml | 83 - .../chroma/v2/styles/tokyonight-moon.xml | 83 - .../chroma/v2/styles/tokyonight-night.xml | 83 - .../chroma/v2/styles/tokyonight-storm.xml | 83 - .../alecthomas/chroma/v2/styles/trac.xml | 35 - .../alecthomas/chroma/v2/styles/vim.xml | 29 - .../alecthomas/chroma/v2/styles/vs.xml | 16 - .../alecthomas/chroma/v2/styles/vulcan.xml | 74 - .../chroma/v2/styles/witchhazel.xml | 31 - .../chroma/v2/styles/xcode-dark.xml | 31 - .../alecthomas/chroma/v2/styles/xcode.xml | 22 - .../github.com/alecthomas/chroma/v2/table.py | 31 - .../alecthomas/chroma/v2/tokentype_enumer.go | 573 - .../github.com/alecthomas/chroma/v2/types.go | 340 - .../github.com/atotto/clipboard/.travis.yml | 22 - vendor/github.com/atotto/clipboard/LICENSE | 27 - vendor/github.com/atotto/clipboard/README.md | 48 - .../github.com/atotto/clipboard/clipboard.go | 20 - .../atotto/clipboard/clipboard_darwin.go | 52 - .../atotto/clipboard/clipboard_plan9.go | 42 - .../atotto/clipboard/clipboard_unix.go | 149 - .../atotto/clipboard/clipboard_windows.go | 157 - vendor/github.com/aymerick/douceur/LICENSE | 22 - .../aymerick/douceur/css/declaration.go | 60 - .../github.com/aymerick/douceur/css/rule.go | 230 - .../aymerick/douceur/css/stylesheet.go | 25 - .../aymerick/douceur/parser/parser.go | 409 - vendor/github.com/beorn7/perks/LICENSE | 20 - .../beorn7/perks/quantile/exampledata.txt | 2388 --- .../beorn7/perks/quantile/stream.go | 316 - vendor/github.com/catppuccin/go/.editorconfig | 34 - vendor/github.com/catppuccin/go/.gitignore | 4 - .../github.com/catppuccin/go/.goreleaser.yaml | 11 - vendor/github.com/catppuccin/go/LICENSE | 21 - vendor/github.com/catppuccin/go/README.md | 48 - vendor/github.com/catppuccin/go/flake.lock | 95 - vendor/github.com/catppuccin/go/flake.nix | 35 - vendor/github.com/catppuccin/go/frappe.go | 244 - vendor/github.com/catppuccin/go/go.tera | 28 - vendor/github.com/catppuccin/go/latte.go | 244 - vendor/github.com/catppuccin/go/macchiato.go | 244 - vendor/github.com/catppuccin/go/main.go | 81 - vendor/github.com/catppuccin/go/mocha.go | 244 - vendor/github.com/catppuccin/go/renovate.json | 6 - .../github.com/cenkalti/backoff/v4/.gitignore | 25 - vendor/github.com/cenkalti/backoff/v4/LICENSE | 20 - .../github.com/cenkalti/backoff/v4/README.md | 30 - .../github.com/cenkalti/backoff/v4/backoff.go | 66 - .../github.com/cenkalti/backoff/v4/context.go | 62 - .../cenkalti/backoff/v4/exponential.go | 216 - .../github.com/cenkalti/backoff/v4/retry.go | 146 - .../github.com/cenkalti/backoff/v4/ticker.go | 97 - .../github.com/cenkalti/backoff/v4/timer.go | 35 - .../github.com/cenkalti/backoff/v4/tries.go | 38 - .../github.com/cenkalti/backoff/v5/.gitignore | 25 - .../cenkalti/backoff/v5/CHANGELOG.md | 29 - vendor/github.com/cenkalti/backoff/v5/LICENSE | 20 - .../github.com/cenkalti/backoff/v5/README.md | 31 - .../github.com/cenkalti/backoff/v5/backoff.go | 66 - .../github.com/cenkalti/backoff/v5/error.go | 46 - .../cenkalti/backoff/v5/exponential.go | 118 - .../github.com/cenkalti/backoff/v5/retry.go | 139 - .../github.com/cenkalti/backoff/v5/ticker.go | 83 - .../github.com/cenkalti/backoff/v5/timer.go | 35 - .../github.com/cespare/xxhash/v2/LICENSE.txt | 22 - vendor/github.com/cespare/xxhash/v2/README.md | 74 - .../github.com/cespare/xxhash/v2/testall.sh | 10 - vendor/github.com/cespare/xxhash/v2/xxhash.go | 243 - .../cespare/xxhash/v2/xxhash_amd64.s | 209 - .../cespare/xxhash/v2/xxhash_arm64.s | 183 - .../cespare/xxhash/v2/xxhash_asm.go | 15 - .../cespare/xxhash/v2/xxhash_other.go | 76 - .../cespare/xxhash/v2/xxhash_safe.go | 16 - .../cespare/xxhash/v2/xxhash_unsafe.go | 58 - .../github.com/charmbracelet/bubbles/LICENSE | 21 - .../charmbracelet/bubbles/cursor/cursor.go | 219 - .../bubbles/filepicker/filepicker.go | 522 - .../bubbles/filepicker/hidden_unix.go | 11 - .../bubbles/filepicker/hidden_windows.go | 21 - .../charmbracelet/bubbles/help/help.go | 240 - .../charmbracelet/bubbles/key/key.go | 140 - .../bubbles/runeutil/runeutil.go | 102 - .../charmbracelet/bubbles/spinner/spinner.go | 224 - .../textarea/memoization/memoization.go | 125 - .../bubbles/textarea/textarea.go | 1472 -- .../bubbles/textinput/textinput.go | 898 - .../charmbracelet/bubbles/viewport/keymap.go | 60 - .../bubbles/viewport/viewport.go | 544 - .../charmbracelet/bubbletea/.gitattributes | 1 - .../charmbracelet/bubbletea/.gitignore | 23 - .../bubbletea/.golangci-soft.yml | 40 - .../charmbracelet/bubbletea/.golangci.yml | 28 - .../charmbracelet/bubbletea/.goreleaser.yml | 5 - .../charmbracelet/bubbletea/LICENSE | 21 - .../charmbracelet/bubbletea/README.md | 396 - .../charmbracelet/bubbletea/commands.go | 216 - .../charmbracelet/bubbletea/exec.go | 129 - .../charmbracelet/bubbletea/focus.go | 9 - .../bubbletea/inputreader_other.go | 14 - .../bubbletea/inputreader_windows.go | 127 - .../github.com/charmbracelet/bubbletea/key.go | 715 - .../charmbracelet/bubbletea/key_other.go | 13 - .../charmbracelet/bubbletea/key_sequences.go | 131 - .../charmbracelet/bubbletea/key_windows.go | 360 - .../charmbracelet/bubbletea/logging.go | 53 - .../charmbracelet/bubbletea/mouse.go | 308 - .../charmbracelet/bubbletea/nil_renderer.go | 28 - .../charmbracelet/bubbletea/options.go | 252 - .../charmbracelet/bubbletea/renderer.go | 85 - .../charmbracelet/bubbletea/screen.go | 248 - .../charmbracelet/bubbletea/signals_unix.go | 33 - .../bubbletea/signals_windows.go | 10 - .../bubbletea/standard_renderer.go | 786 - .../github.com/charmbracelet/bubbletea/tea.go | 841 - .../charmbracelet/bubbletea/tea_init.go | 22 - .../github.com/charmbracelet/bubbletea/tty.go | 141 - .../charmbracelet/bubbletea/tty_unix.go | 49 - .../charmbracelet/bubbletea/tty_windows.go | 68 - .../charmbracelet/glamour/.editorconfig | 18 - .../charmbracelet/glamour/.gitattributes | 2 - .../charmbracelet/glamour/.gitignore | 2 - .../charmbracelet/glamour/.golangci.yml | 49 - .../charmbracelet/glamour/.goreleaser.yml | 6 - .../charmbracelet/glamour/CONTRIBUTING.md | 23 - .../github.com/charmbracelet/glamour/LICENSE | 21 - .../charmbracelet/glamour/README.md | 96 - .../charmbracelet/glamour/Taskfile.yml | 25 - .../charmbracelet/glamour/ansi/ansi.go | 3 - .../charmbracelet/glamour/ansi/baseelement.go | 151 - .../glamour/ansi/blockelement.go | 65 - .../charmbracelet/glamour/ansi/blockstack.go | 95 - .../charmbracelet/glamour/ansi/codeblock.go | 152 - .../charmbracelet/glamour/ansi/codespan.go | 15 - .../charmbracelet/glamour/ansi/context.go | 38 - .../charmbracelet/glamour/ansi/elements.go | 479 - .../charmbracelet/glamour/ansi/emphasis.go | 47 - .../charmbracelet/glamour/ansi/heading.go | 87 - .../charmbracelet/glamour/ansi/image.go | 52 - .../charmbracelet/glamour/ansi/link.go | 76 - .../charmbracelet/glamour/ansi/listitem.go | 29 - .../charmbracelet/glamour/ansi/margin.go | 57 - .../charmbracelet/glamour/ansi/paragraph.go | 63 - .../charmbracelet/glamour/ansi/renderer.go | 168 - .../charmbracelet/glamour/ansi/style.go | 257 - .../charmbracelet/glamour/ansi/table.go | 199 - .../charmbracelet/glamour/ansi/table_links.go | 235 - .../charmbracelet/glamour/ansi/task.go | 27 - .../glamour/ansi/templatehelper.go | 86 - .../charmbracelet/glamour/examples.sh | 19 - .../charmbracelet/glamour/gallery.sh | 23 - .../charmbracelet/glamour/glamour.go | 322 - .../glamour/internal/autolink/autolink.go | 55 - .../charmbracelet/glamour/styles/README.md | 565 - .../charmbracelet/glamour/styles/ascii.json | 83 - .../charmbracelet/glamour/styles/dark.json | 191 - .../charmbracelet/glamour/styles/dracula.go | 216 - .../charmbracelet/glamour/styles/dracula.json | 188 - .../charmbracelet/glamour/styles/light.json | 190 - .../charmbracelet/glamour/styles/notty.json | 83 - .../charmbracelet/glamour/styles/pink.json | 90 - .../charmbracelet/glamour/styles/styles.go | 681 - .../glamour/styles/tokyo-night.go | 209 - .../glamour/styles/tokyo_night.json | 182 - .../charmbracelet/huh/.gitattributes | 2 - .../github.com/charmbracelet/huh/.gitignore | 24 - .../charmbracelet/huh/.golangci.yml | 49 - vendor/github.com/charmbracelet/huh/LICENSE | 21 - vendor/github.com/charmbracelet/huh/Makefile | 17 - vendor/github.com/charmbracelet/huh/README.md | 512 - .../github.com/charmbracelet/huh/accessor.go | 44 - vendor/github.com/charmbracelet/huh/clamp.go | 8 - vendor/github.com/charmbracelet/huh/eval.go | 84 - .../charmbracelet/huh/field_confirm.go | 385 - .../charmbracelet/huh/field_filepicker.go | 450 - .../charmbracelet/huh/field_input.go | 524 - .../charmbracelet/huh/field_multiselect.go | 819 - .../charmbracelet/huh/field_note.go | 371 - .../charmbracelet/huh/field_select.go | 800 - .../charmbracelet/huh/field_text.go | 498 - vendor/github.com/charmbracelet/huh/form.go | 720 - vendor/github.com/charmbracelet/huh/group.go | 399 - vendor/github.com/charmbracelet/huh/huh.go | 2 - .../internal/accessibility/accessibility.go | 169 - .../huh/internal/selector/selector.go | 97 - vendor/github.com/charmbracelet/huh/keymap.go | 186 - vendor/github.com/charmbracelet/huh/layout.go | 170 - vendor/github.com/charmbracelet/huh/option.go | 38 - vendor/github.com/charmbracelet/huh/run.go | 8 - vendor/github.com/charmbracelet/huh/theme.go | 329 - .../github.com/charmbracelet/huh/validate.go | 61 - vendor/github.com/charmbracelet/huh/wrap.go | 7 - .../charmbracelet/lipgloss/table/resizing.go | 429 - .../charmbracelet/lipgloss/table/rows.go | 129 - .../charmbracelet/lipgloss/table/table.go | 503 - .../charmbracelet/lipgloss/table/util.go | 52 - .../charmbracelet/x/exp/slice/LICENSE | 21 - .../charmbracelet/x/exp/slice/slice.go | 37 - .../charmbracelet/x/exp/strings/LICENSE | 21 - .../charmbracelet/x/exp/strings/join.go | 133 - vendor/github.com/cloudflare/circl/LICENSE | 57 - .../cloudflare/circl/dh/x25519/curve.go | 96 - .../cloudflare/circl/dh/x25519/curve_amd64.go | 30 - .../cloudflare/circl/dh/x25519/curve_amd64.h | 111 - .../cloudflare/circl/dh/x25519/curve_amd64.s | 157 - .../circl/dh/x25519/curve_generic.go | 85 - .../cloudflare/circl/dh/x25519/curve_noasm.go | 11 - .../cloudflare/circl/dh/x25519/doc.go | 19 - .../cloudflare/circl/dh/x25519/key.go | 47 - .../cloudflare/circl/dh/x25519/table.go | 268 - .../cloudflare/circl/dh/x448/curve.go | 104 - .../cloudflare/circl/dh/x448/curve_amd64.go | 30 - .../cloudflare/circl/dh/x448/curve_amd64.h | 111 - .../cloudflare/circl/dh/x448/curve_amd64.s | 194 - .../cloudflare/circl/dh/x448/curve_generic.go | 100 - .../cloudflare/circl/dh/x448/curve_noasm.go | 11 - .../cloudflare/circl/dh/x448/doc.go | 19 - .../cloudflare/circl/dh/x448/key.go | 46 - .../cloudflare/circl/dh/x448/table.go | 460 - .../circl/ecc/goldilocks/constants.go | 71 - .../cloudflare/circl/ecc/goldilocks/curve.go | 84 - .../circl/ecc/goldilocks/isogeny.go | 52 - .../cloudflare/circl/ecc/goldilocks/point.go | 171 - .../cloudflare/circl/ecc/goldilocks/scalar.go | 203 - .../cloudflare/circl/ecc/goldilocks/twist.go | 138 - .../circl/ecc/goldilocks/twistPoint.go | 135 - .../circl/ecc/goldilocks/twistTables.go | 216 - .../circl/ecc/goldilocks/twist_basemult.go | 62 - .../cloudflare/circl/internal/conv/conv.go | 173 - .../cloudflare/circl/internal/sha3/doc.go | 62 - .../cloudflare/circl/internal/sha3/hashes.go | 69 - .../cloudflare/circl/internal/sha3/keccakf.go | 391 - .../cloudflare/circl/internal/sha3/rc.go | 29 - .../cloudflare/circl/internal/sha3/sha3.go | 200 - .../circl/internal/sha3/sha3_s390x.s | 33 - .../cloudflare/circl/internal/sha3/shake.go | 119 - .../cloudflare/circl/internal/sha3/xor.go | 15 - .../circl/internal/sha3/xor_generic.go | 33 - .../circl/internal/sha3/xor_unaligned.go | 61 - .../cloudflare/circl/math/fp25519/fp.go | 205 - .../cloudflare/circl/math/fp25519/fp_amd64.go | 45 - .../cloudflare/circl/math/fp25519/fp_amd64.h | 351 - .../cloudflare/circl/math/fp25519/fp_amd64.s | 112 - .../circl/math/fp25519/fp_generic.go | 317 - .../cloudflare/circl/math/fp25519/fp_noasm.go | 13 - .../cloudflare/circl/math/fp448/fp.go | 164 - .../cloudflare/circl/math/fp448/fp_amd64.go | 43 - .../cloudflare/circl/math/fp448/fp_amd64.h | 591 - .../cloudflare/circl/math/fp448/fp_amd64.s | 75 - .../cloudflare/circl/math/fp448/fp_generic.go | 339 - .../cloudflare/circl/math/fp448/fp_noasm.go | 12 - .../cloudflare/circl/math/fp448/fuzzer.go | 75 - .../cloudflare/circl/math/integer.go | 16 - .../cloudflare/circl/math/mlsbset/mlsbset.go | 122 - .../cloudflare/circl/math/mlsbset/power.go | 64 - .../cloudflare/circl/math/primes.go | 34 - .../github.com/cloudflare/circl/math/wnaf.go | 84 - .../cloudflare/circl/sign/ed25519/ed25519.go | 453 - .../cloudflare/circl/sign/ed25519/modular.go | 175 - .../cloudflare/circl/sign/ed25519/mult.go | 180 - .../cloudflare/circl/sign/ed25519/point.go | 195 - .../cloudflare/circl/sign/ed25519/pubkey.go | 9 - .../circl/sign/ed25519/pubkey112.go | 7 - .../cloudflare/circl/sign/ed25519/signapi.go | 87 - .../cloudflare/circl/sign/ed25519/tables.go | 213 - .../cloudflare/circl/sign/ed448/ed448.go | 411 - .../cloudflare/circl/sign/ed448/signapi.go | 87 - .../github.com/cloudflare/circl/sign/sign.go | 113 - vendor/github.com/crazy3lf/colorconv/LICENSE | 21 - .../github.com/crazy3lf/colorconv/README.md | 8 - .../crazy3lf/colorconv/colorconv.go | 272 - .../cyphar/filepath-securejoin/CHANGELOG.md | 256 - .../cyphar/filepath-securejoin/LICENSE | 28 - .../cyphar/filepath-securejoin/README.md | 169 - .../cyphar/filepath-securejoin/VERSION | 1 - .../cyphar/filepath-securejoin/doc.go | 39 - .../gocompat_errors_go120.go | 18 - .../gocompat_errors_unsupported.go | 38 - .../gocompat_generics_go121.go | 32 - .../gocompat_generics_unsupported.go | 124 - .../cyphar/filepath-securejoin/join.go | 166 - .../filepath-securejoin/lookup_linux.go | 388 - .../cyphar/filepath-securejoin/mkdir_linux.go | 236 - .../cyphar/filepath-securejoin/open_linux.go | 103 - .../filepath-securejoin/openat2_linux.go | 127 - .../filepath-securejoin/openat_linux.go | 59 - .../filepath-securejoin/procfs_linux.go | 452 - .../cyphar/filepath-securejoin/vfs.go | 35 - vendor/github.com/dennwc/varint/.gitignore | 2 - vendor/github.com/dennwc/varint/.travis.yml | 7 - vendor/github.com/dennwc/varint/LICENSE | 21 - vendor/github.com/dennwc/varint/README.md | 47 - vendor/github.com/dennwc/varint/proto.go | 244 - vendor/github.com/dennwc/varint/varint.go | 270 - vendor/github.com/dlclark/regexp2/.gitignore | 27 - vendor/github.com/dlclark/regexp2/.travis.yml | 7 - vendor/github.com/dlclark/regexp2/ATTRIB | 133 - vendor/github.com/dlclark/regexp2/LICENSE | 21 - vendor/github.com/dlclark/regexp2/README.md | 167 - .../github.com/dlclark/regexp2/fastclock.go | 129 - vendor/github.com/dlclark/regexp2/match.go | 347 - vendor/github.com/dlclark/regexp2/regexp.go | 395 - vendor/github.com/dlclark/regexp2/replace.go | 177 - vendor/github.com/dlclark/regexp2/runner.go | 1609 -- .../dlclark/regexp2/syntax/charclass.go | 865 - .../github.com/dlclark/regexp2/syntax/code.go | 274 - .../dlclark/regexp2/syntax/escape.go | 94 - .../github.com/dlclark/regexp2/syntax/fuzz.go | 20 - .../dlclark/regexp2/syntax/parser.go | 2262 --- .../dlclark/regexp2/syntax/prefix.go | 896 - .../dlclark/regexp2/syntax/replacerdata.go | 87 - .../github.com/dlclark/regexp2/syntax/tree.go | 654 - .../dlclark/regexp2/syntax/writer.go | 500 - vendor/github.com/dlclark/regexp2/testoutput1 | 7061 ------- .../github.com/dustin/go-humanize/.travis.yml | 21 - vendor/github.com/dustin/go-humanize/LICENSE | 21 - .../dustin/go-humanize/README.markdown | 124 - vendor/github.com/dustin/go-humanize/big.go | 31 - .../github.com/dustin/go-humanize/bigbytes.go | 189 - vendor/github.com/dustin/go-humanize/bytes.go | 143 - vendor/github.com/dustin/go-humanize/comma.go | 116 - .../github.com/dustin/go-humanize/commaf.go | 41 - vendor/github.com/dustin/go-humanize/ftoa.go | 49 - .../github.com/dustin/go-humanize/humanize.go | 8 - .../github.com/dustin/go-humanize/number.go | 192 - .../github.com/dustin/go-humanize/ordinals.go | 25 - vendor/github.com/dustin/go-humanize/si.go | 127 - vendor/github.com/dustin/go-humanize/times.go | 117 - vendor/github.com/edsrzf/mmap-go/.gitignore | 11 - vendor/github.com/edsrzf/mmap-go/LICENSE | 25 - vendor/github.com/edsrzf/mmap-go/README.md | 14 - vendor/github.com/edsrzf/mmap-go/mmap.go | 117 - .../github.com/edsrzf/mmap-go/mmap_plan9.go | 27 - vendor/github.com/edsrzf/mmap-go/mmap_unix.go | 51 - vendor/github.com/edsrzf/mmap-go/mmap_wasm.go | 27 - .../github.com/edsrzf/mmap-go/mmap_windows.go | 154 - vendor/github.com/emirpasic/gods/LICENSE | 41 - .../emirpasic/gods/containers/containers.go | 36 - .../emirpasic/gods/containers/enumerable.go | 57 - .../emirpasic/gods/containers/iterator.go | 133 - .../gods/containers/serialization.go | 21 - .../gods/lists/arraylist/arraylist.go | 227 - .../gods/lists/arraylist/enumerable.go | 78 - .../gods/lists/arraylist/iterator.go | 110 - .../gods/lists/arraylist/serialization.go | 38 - .../github.com/emirpasic/gods/lists/lists.go | 34 - .../gods/trees/binaryheap/binaryheap.go | 166 - .../gods/trees/binaryheap/iterator.go | 143 - .../gods/trees/binaryheap/serialization.go | 33 - .../github.com/emirpasic/gods/trees/trees.go | 22 - .../emirpasic/gods/utils/comparator.go | 251 - .../github.com/emirpasic/gods/utils/sort.go | 29 - .../github.com/emirpasic/gods/utils/utils.go | 47 - .../github.com/erikgeiser/coninput/.gitignore | 15 - .../erikgeiser/coninput/.golangci.yml | 24 - vendor/github.com/erikgeiser/coninput/LICENSE | 21 - .../github.com/erikgeiser/coninput/README.md | 2 - .../erikgeiser/coninput/keycodes.go | 205 - vendor/github.com/erikgeiser/coninput/mode.go | 82 - vendor/github.com/erikgeiser/coninput/read.go | 154 - .../github.com/erikgeiser/coninput/records.go | 486 - vendor/github.com/facette/natsort/LICENSE | 29 - vendor/github.com/facette/natsort/README.md | 104 - vendor/github.com/facette/natsort/natsort.go | 85 - .../github.com/felixge/httpsnoop/.gitignore | 0 .../github.com/felixge/httpsnoop/LICENSE.txt | 19 - vendor/github.com/felixge/httpsnoop/Makefile | 10 - vendor/github.com/felixge/httpsnoop/README.md | 95 - .../felixge/httpsnoop/capture_metrics.go | 86 - vendor/github.com/felixge/httpsnoop/docs.go | 10 - .../httpsnoop/wrap_generated_gteq_1.8.go | 436 - .../httpsnoop/wrap_generated_lt_1.8.go | 278 - vendor/github.com/gen2brain/beeep/LICENSE | 23 - vendor/github.com/gen2brain/beeep/README.md | 37 - .../gen2brain/beeep/alert_darwin.go | 21 - vendor/github.com/gen2brain/beeep/alert_js.go | 12 - .../github.com/gen2brain/beeep/alert_unix.go | 12 - .../gen2brain/beeep/alert_unsupported.go | 9 - .../gen2brain/beeep/alert_windows.go | 22 - vendor/github.com/gen2brain/beeep/beeep.go | 27 - .../github.com/gen2brain/beeep/beep_darwin.go | 29 - vendor/github.com/gen2brain/beeep/beep_js.go | 38 - .../github.com/gen2brain/beeep/beep_unix.go | 139 - .../gen2brain/beeep/beep_unsupported.go | 16 - .../gen2brain/beeep/beep_windows.go | 42 - .../gen2brain/beeep/notify_darwin.go | 23 - .../github.com/gen2brain/beeep/notify_js.go | 51 - .../github.com/gen2brain/beeep/notify_unix.go | 59 - .../gen2brain/beeep/notify_unix_nodbus.go | 46 - .../gen2brain/beeep/notify_unsupported.go | 9 - .../gen2brain/beeep/notify_windows.go | 127 - .../github.com/getlantern/context/.travis.yml | 15 - vendor/github.com/getlantern/context/LICENSE | 202 - .../github.com/getlantern/context/README.md | 6 - .../github.com/getlantern/context/context.go | 309 - .../github.com/getlantern/context/gotrack.go | 130 - vendor/github.com/getlantern/errors/LICENSE | 202 - vendor/github.com/getlantern/errors/errors.go | 566 - vendor/github.com/getlantern/errors/hide.go | 50 - .../github.com/getlantern/golog/.travis.yml | 14 - vendor/github.com/getlantern/golog/LICENSE | 202 - vendor/github.com/getlantern/golog/README.md | 6 - vendor/github.com/getlantern/golog/golog.go | 473 - vendor/github.com/getlantern/hex/LICENSE | 29 - vendor/github.com/getlantern/hex/hex.go | 110 - vendor/github.com/getlantern/hidden/LICENSE | 202 - vendor/github.com/getlantern/hidden/hidden.go | 66 - vendor/github.com/getlantern/ops/LICENSE | 202 - vendor/github.com/getlantern/ops/ops.go | 154 - .../github.com/getlantern/systray/.gitignore | 12 - .../getlantern/systray/CHANGELOG.md | 137 - vendor/github.com/getlantern/systray/LICENSE | 202 - vendor/github.com/getlantern/systray/Makefile | 18 - .../github.com/getlantern/systray/README.md | 129 - .../github.com/getlantern/systray/systray.go | 236 - .../github.com/getlantern/systray/systray.h | 17 - .../getlantern/systray/systray_darwin.go | 38 - .../getlantern/systray/systray_darwin.m | 293 - .../getlantern/systray/systray_linux.c | 275 - .../getlantern/systray/systray_linux.go | 21 - .../systray/systray_linux_appindicator.go | 12 - .../systray/systray_linux_ayatana.go | 11 - .../getlantern/systray/systray_nonwindows.go | 101 - .../getlantern/systray/systray_windows.go | 944 - .../systray/webview_example/webview.h | 3 - vendor/github.com/go-git/gcfg/v2/.gitignore | 1 - vendor/github.com/go-git/gcfg/v2/LICENSE | 28 - vendor/github.com/go-git/gcfg/v2/Makefile | 17 - vendor/github.com/go-git/gcfg/v2/README | 4 - vendor/github.com/go-git/gcfg/v2/doc.go | 142 - vendor/github.com/go-git/gcfg/v2/errors.go | 50 - vendor/github.com/go-git/gcfg/v2/read.go | 301 - .../go-git/gcfg/v2/scanner/errors.go | 115 - .../go-git/gcfg/v2/scanner/scanner.go | 394 - vendor/github.com/go-git/gcfg/v2/set.go | 337 - .../go-git/gcfg/v2/token/position.go | 430 - .../go-git/gcfg/v2/token/serialize.go | 56 - .../github.com/go-git/gcfg/v2/token/token.go | 79 - .../github.com/go-git/gcfg/v2/types/bool.go | 23 - vendor/github.com/go-git/gcfg/v2/types/doc.go | 4 - .../github.com/go-git/gcfg/v2/types/enum.go | 44 - vendor/github.com/go-git/gcfg/v2/types/int.go | 90 - .../github.com/go-git/gcfg/v2/types/scan.go | 23 - .../github.com/go-git/go-billy/v6/.gitignore | 3 - .../go-git/go-billy/v6/.golangci.yaml | 75 - vendor/github.com/go-git/go-billy/v6/LICENSE | 201 - vendor/github.com/go-git/go-billy/v6/Makefile | 48 - .../github.com/go-git/go-billy/v6/README.md | 73 - vendor/github.com/go-git/go-billy/v6/fs.go | 205 - .../go-billy/v6/helper/chroot/chroot.go | 243 - .../go-billy/v6/helper/polyfill/polyfill.go | 106 - .../go-git/go-billy/v6/memfs/file.go | 243 - .../go-git/go-billy/v6/memfs/memory.go | 263 - .../go-git/go-billy/v6/memfs/memory_option.go | 6 - .../go-git/go-billy/v6/memfs/storage.go | 225 - .../github.com/go-git/go-billy/v6/osfs/os.go | 127 - .../go-git/go-billy/v6/osfs/os_bound.go | 298 - .../go-git/go-billy/v6/osfs/os_chroot.go | 118 - .../go-git/go-billy/v6/osfs/os_js.go | 25 - .../go-git/go-billy/v6/osfs/os_options.go | 3 - .../go-git/go-billy/v6/osfs/os_plan9.go | 91 - .../go-git/go-billy/v6/osfs/os_posix.go | 38 - .../go-git/go-billy/v6/osfs/os_wasip1.go | 34 - .../go-git/go-billy/v6/osfs/os_windows.go | 58 - .../go-git/go-billy/v6/util/glob.go | 111 - .../go-git/go-billy/v6/util/util.go | 291 - .../go-git/go-billy/v6/util/walk.go | 73 - vendor/github.com/go-git/go-git/v6/.gitignore | 7 - .../go-git/go-git/v6/CODE_OF_CONDUCT.md | 74 - .../go-git/go-git/v6/COMPATIBILITY.md | 234 - .../go-git/go-git/v6/CONTRIBUTING.md | 84 - .../github.com/go-git/go-git/v6/EXTENDING.md | 78 - vendor/github.com/go-git/go-git/v6/LICENSE | 201 - vendor/github.com/go-git/go-git/v6/Makefile | 48 - vendor/github.com/go-git/go-git/v6/README.md | 131 - .../github.com/go-git/go-git/v6/SECURITY.md | 38 - vendor/github.com/go-git/go-git/v6/blame.go | 584 - vendor/github.com/go-git/go-git/v6/common.go | 20 - .../go-git/go-git/v6/config/branch.go | 123 - .../go-git/go-git/v6/config/config.go | 833 - .../go-git/go-git/v6/config/modules.go | 139 - .../go-git/go-git/v6/config/refspec.go | 155 - .../github.com/go-git/go-git/v6/config/url.go | 90 - vendor/github.com/go-git/go-git/v6/crypto.go | 7 - vendor/github.com/go-git/go-git/v6/doc.go | 10 - .../go-git/v6/internal/path_util/path_util.go | 29 - .../go-git/v6/internal/reference/refs.go | 33 - .../go-git/v6/internal/reference/sort.go | 14 - .../go-git/v6/internal/repository/refs.go | 103 - .../go-git/v6/internal/revision/parser.go | 626 - .../go-git/v6/internal/revision/scanner.go | 122 - .../go-git/v6/internal/revision/token.go | 28 - .../go-git/go-git/v6/internal/url/url.go | 39 - .../go-git/go-git/v6/object_walker.go | 104 - vendor/github.com/go-git/go-git/v6/options.go | 819 - .../go-git/v6/plumbing/cache/buffer_lru.go | 98 - .../go-git/go-git/v6/plumbing/cache/common.go | 39 - .../go-git/v6/plumbing/cache/object_lru.go | 101 - .../go-git/go-git/v6/plumbing/color/color.go | 38 - .../go-git/go-git/v6/plumbing/error.go | 35 - .../go-git/v6/plumbing/filemode/filemode.go | 188 - .../v6/plumbing/format/config/common.go | 109 - .../v6/plumbing/format/config/decoder.go | 37 - .../go-git/v6/plumbing/format/config/doc.go | 122 - .../v6/plumbing/format/config/encoder.go | 82 - .../v6/plumbing/format/config/format.go | 105 - .../v6/plumbing/format/config/option.go | 127 - .../v6/plumbing/format/config/section.go | 181 - .../v6/plumbing/format/diff/colorconfig.go | 97 - .../go-git/v6/plumbing/format/diff/patch.go | 58 - .../plumbing/format/diff/unified_encoder.go | 395 - .../v6/plumbing/format/gitignore/dir.go | 148 - .../v6/plumbing/format/gitignore/doc.go | 70 - .../v6/plumbing/format/gitignore/matcher.go | 30 - .../v6/plumbing/format/gitignore/pattern.go | 159 - .../v6/plumbing/format/idxfile/decoder.go | 178 - .../go-git/v6/plumbing/format/idxfile/doc.go | 128 - .../v6/plumbing/format/idxfile/encoder.go | 148 - .../v6/plumbing/format/idxfile/idxfile.go | 366 - .../v6/plumbing/format/idxfile/writer.go | 193 - .../v6/plumbing/format/index/decoder.go | 511 - .../go-git/v6/plumbing/format/index/doc.go | 360 - .../v6/plumbing/format/index/encoder.go | 240 - .../go-git/v6/plumbing/format/index/index.go | 231 - .../go-git/v6/plumbing/format/index/match.go | 186 - .../go-git/v6/plumbing/format/objfile/doc.go | 2 - .../v6/plumbing/format/objfile/reader.go | 123 - .../v6/plumbing/format/objfile/writer.go | 121 - .../v6/plumbing/format/packfile/common.go | 63 - .../plumbing/format/packfile/delta_index.go | 295 - .../format/packfile/delta_selector.go | 369 - .../v6/plumbing/format/packfile/diff_delta.go | 204 - .../go-git/v6/plumbing/format/packfile/doc.go | 39 - .../v6/plumbing/format/packfile/encoder.go | 225 - .../v6/plumbing/format/packfile/error.go | 30 - .../v6/plumbing/format/packfile/fsobject.go | 138 - .../plumbing/format/packfile/object_pack.go | 164 - .../v6/plumbing/format/packfile/packfile.go | 350 - .../plumbing/format/packfile/packfile_iter.go | 90 - .../format/packfile/packfile_options.go | 42 - .../v6/plumbing/format/packfile/parser.go | 404 - .../plumbing/format/packfile/parser_cache.go | 41 - .../format/packfile/parser_options.go | 47 - .../plumbing/format/packfile/parser_types.go | 19 - .../plumbing/format/packfile/patch_delta.go | 548 - .../v6/plumbing/format/packfile/scanner.go | 517 - .../format/packfile/scanner_options.go | 17 - .../format/packfile/scanner_reader.go | 99 - .../v6/plumbing/format/packfile/types.go | 82 - .../v6/plumbing/format/pktline/common.go | 58 - .../v6/plumbing/format/pktline/error.go | 51 - .../v6/plumbing/format/pktline/length.go | 89 - .../v6/plumbing/format/pktline/pktline.go | 234 - .../v6/plumbing/format/pktline/scanner.go | 75 - .../go-git/v6/plumbing/format/pktline/sync.go | 25 - .../go-git/go-git/v6/plumbing/hash.go | 93 - .../go-git/go-git/v6/plumbing/hash/hash.go | 80 - .../go-git/go-git/v6/plumbing/hasher.go | 109 - .../go-git/go-git/v6/plumbing/memory.go | 78 - .../go-git/go-git/v6/plumbing/object.go | 111 - .../go-git/go-git/v6/plumbing/object/blob.go | 144 - .../go-git/v6/plumbing/object/change.go | 159 - .../v6/plumbing/object/change_adaptor.go | 61 - .../go-git/v6/plumbing/object/commit.go | 579 - .../v6/plumbing/object/commit_walker.go | 349 - .../v6/plumbing/object/commit_walker_bfs.go | 100 - .../object/commit_walker_bfs_filtered.go | 175 - .../v6/plumbing/object/commit_walker_ctime.go | 103 - .../v6/plumbing/object/commit_walker_limit.go | 70 - .../v6/plumbing/object/commit_walker_path.go | 167 - .../go-git/v6/plumbing/object/difftree.go | 98 - .../go-git/go-git/v6/plumbing/object/file.go | 137 - .../go-git/v6/plumbing/object/merge_base.go | 210 - .../go-git/v6/plumbing/object/object.go | 239 - .../go-git/go-git/v6/plumbing/object/patch.go | 337 - .../go-git/v6/plumbing/object/rename.go | 816 - .../go-git/v6/plumbing/object/signature.go | 102 - .../go-git/go-git/v6/plumbing/object/tag.go | 330 - .../go-git/go-git/v6/plumbing/object/tree.go | 558 - .../go-git/v6/plumbing/object/treenoder.go | 142 - .../go-git/go-git/v6/plumbing/objectid.go | 154 - .../v6/plumbing/protocol/packp/advrefs.go | 225 - .../plumbing/protocol/packp/advrefs_decode.go | 263 - .../plumbing/protocol/packp/advrefs_encode.go | 163 - .../protocol/packp/capability/capability.go | 279 - .../protocol/packp/capability/list.go | 195 - .../v6/plumbing/protocol/packp/common.go | 74 - .../go-git/v6/plumbing/protocol/packp/doc.go | 724 - .../v6/plumbing/protocol/packp/filter.go | 77 - .../v6/plumbing/protocol/packp/gitproto.go | 117 - .../v6/plumbing/protocol/packp/inforefs.go | 67 - .../v6/plumbing/protocol/packp/packp.go | 15 - .../v6/plumbing/protocol/packp/pushopts.go | 50 - .../plumbing/protocol/packp/report_status.go | 203 - .../v6/plumbing/protocol/packp/shallowupd.go | 101 - .../protocol/packp/sideband/common.go | 33 - .../plumbing/protocol/packp/sideband/demux.go | 148 - .../plumbing/protocol/packp/sideband/doc.go | 31 - .../plumbing/protocol/packp/sideband/muxer.go | 66 - .../v6/plumbing/protocol/packp/smart.go | 60 - .../v6/plumbing/protocol/packp/srvresp.go | 150 - .../v6/plumbing/protocol/packp/ulreq.go | 81 - .../plumbing/protocol/packp/ulreq_decode.go | 257 - .../plumbing/protocol/packp/ulreq_encode.go | 154 - .../v6/plumbing/protocol/packp/updreq.go | 83 - .../plumbing/protocol/packp/updreq_decode.go | 252 - .../plumbing/protocol/packp/updreq_encode.go | 62 - .../v6/plumbing/protocol/packp/uphav.go | 83 - .../go-git/v6/plumbing/protocol/version.go | 52 - .../go-git/go-git/v6/plumbing/reference.go | 315 - .../go-git/go-git/v6/plumbing/revision.go | 11 - .../go-git/v6/plumbing/revlist/revlist.go | 254 - .../go-git/go-git/v6/plumbing/storer/doc.go | 2 - .../go-git/go-git/v6/plumbing/storer/index.go | 9 - .../go-git/v6/plumbing/storer/object.go | 292 - .../go-git/v6/plumbing/storer/reference.go | 243 - .../go-git/v6/plumbing/storer/shallow.go | 10 - .../go-git/v6/plumbing/storer/storer.go | 23 - .../go-git/go-git/v6/plumbing/tag.go | 17 - .../go-git/v6/plumbing/transport/common.go | 215 - .../go-git/v6/plumbing/transport/fetch.go | 87 - .../v6/plumbing/transport/file/client.go | 165 - .../v6/plumbing/transport/git/common.go | 112 - .../v6/plumbing/transport/http/common.go | 741 - .../go-git/v6/plumbing/transport/http/dumb.go | 476 - .../v6/plumbing/transport/http/transport.go | 40 - .../go-git/v6/plumbing/transport/loader.go | 83 - .../go-git/v6/plumbing/transport/mocks.go | 45 - .../go-git/v6/plumbing/transport/negotiate.go | 267 - .../go-git/v6/plumbing/transport/pack.go | 213 - .../go-git/v6/plumbing/transport/push.go | 158 - .../v6/plumbing/transport/receive_pack.go | 256 - .../go-git/v6/plumbing/transport/registry.go | 42 - .../go-git/v6/plumbing/transport/serve.go | 119 - .../v6/plumbing/transport/serverinfo.go | 53 - .../go-git/v6/plumbing/transport/service.go | 24 - .../v6/plumbing/transport/ssh/auth_method.go | 353 - .../v6/plumbing/transport/ssh/common.go | 295 - .../transport/ssh/knownhosts/knownhosts.go | 470 - .../transport/ssh/sshagent/pageant_windows.go | 152 - .../transport/ssh/sshagent/sshagent.go | 54 - .../ssh/sshagent/sshagent_windows.go | 110 - .../go-git/v6/plumbing/transport/transport.go | 279 - .../v6/plumbing/transport/upload_pack.go | 358 - .../go-git/v6/plumbing/transport/version.go | 47 - vendor/github.com/go-git/go-git/v6/prune.go | 66 - vendor/github.com/go-git/go-git/v6/remote.go | 1384 -- .../github.com/go-git/go-git/v6/repository.go | 1911 -- vendor/github.com/go-git/go-git/v6/signer.go | 33 - vendor/github.com/go-git/go-git/v6/status.go | 148 - .../go-git/v6/storage/filesystem/config.go | 48 - .../v6/storage/filesystem/deltaobject.go | 37 - .../v6/storage/filesystem/dotgit/dotgit.go | 1279 -- .../dotgit/dotgit_rewrite_packed_refs.go | 81 - .../filesystem/dotgit/dotgit_setref.go | 90 - .../v6/storage/filesystem/dotgit/reader.go | 79 - .../dotgit/repository_filesystem.go | 111 - .../v6/storage/filesystem/dotgit/writers.go | 281 - .../go-git/v6/storage/filesystem/index.go | 54 - .../go-git/v6/storage/filesystem/module.go | 20 - .../go-git/v6/storage/filesystem/object.go | 709 - .../v6/storage/filesystem/object_iter.go | 208 - .../go-git/v6/storage/filesystem/reference.go | 44 - .../go-git/v6/storage/filesystem/shallow.go | 54 - .../go-git/v6/storage/filesystem/storage.go | 98 - .../go-git/v6/storage/memory/storage.go | 359 - .../go-git/go-git/v6/storage/storer.go | 30 - .../github.com/go-git/go-git/v6/submodule.go | 398 - .../github.com/go-git/go-git/v6/transport.go | 9 - .../go-git/go-git/v6/utils/binary/read.go | 167 - .../go-git/go-git/v6/utils/binary/write.go | 50 - .../go-git/go-git/v6/utils/convert/eol.go | 108 - .../go-git/go-git/v6/utils/convert/stat.go | 85 - .../go-git/go-git/v6/utils/diff/diff.go | 61 - .../go-git/go-git/v6/utils/ioutil/common.go | 211 - .../go-git/go-git/v6/utils/ioutil/context.go | 123 - .../go-git/go-git/v6/utils/ioutil/sync.go | 18 - .../go-git/v6/utils/merkletrie/change.go | 160 - .../go-git/v6/utils/merkletrie/difftree.go | 450 - .../go-git/go-git/v6/utils/merkletrie/doc.go | 34 - .../go-git/v6/utils/merkletrie/doubleiter.go | 187 - .../v6/utils/merkletrie/filesystem/node.go | 250 - .../go-git/v6/utils/merkletrie/index/node.go | 103 - .../utils/merkletrie/internal/frame/frame.go | 92 - .../go-git/go-git/v6/utils/merkletrie/iter.go | 215 - .../go-git/v6/utils/merkletrie/noder/noder.go | 60 - .../go-git/v6/utils/merkletrie/noder/path.go | 98 - .../go-git/go-git/v6/utils/sync/bufio.go | 29 - .../go-git/go-git/v6/utils/sync/bytes.go | 70 - .../go-git/go-git/v6/utils/sync/zlib.go | 87 - .../go-git/go-git/v6/utils/trace/trace.go | 75 - .../github.com/go-git/go-git/v6/worktree.go | 1312 -- .../go-git/go-git/v6/worktree_bsd.go | 27 - .../go-git/go-git/v6/worktree_commit.go | 293 - .../go-git/go-git/v6/worktree_js.go | 27 - .../go-git/go-git/v6/worktree_linux.go | 27 - .../go-git/go-git/v6/worktree_plan9.go | 31 - .../go-git/go-git/v6/worktree_status.go | 764 - .../go-git/go-git/v6/worktree_unix_other.go | 27 - .../go-git/go-git/v6/worktree_windows.go | 36 - .../github.com/go-jose/go-jose/v4/.gitignore | 2 - .../go-jose/go-jose/v4/.golangci.yml | 53 - .../github.com/go-jose/go-jose/v4/.travis.yml | 33 - .../go-jose/go-jose/v4/CHANGELOG.md | 101 - .../go-jose/go-jose/v4/CONTRIBUTING.md | 9 - vendor/github.com/go-jose/go-jose/v4/LICENSE | 202 - .../github.com/go-jose/go-jose/v4/README.md | 106 - .../github.com/go-jose/go-jose/v4/SECURITY.md | 13 - .../go-jose/go-jose/v4/asymmetric.go | 595 - .../go-jose/go-jose/v4/cipher/cbc_hmac.go | 196 - .../go-jose/go-jose/v4/cipher/concat_kdf.go | 75 - .../go-jose/go-jose/v4/cipher/ecdh_es.go | 86 - .../go-jose/go-jose/v4/cipher/key_wrap.go | 109 - .../github.com/go-jose/go-jose/v4/crypter.go | 599 - vendor/github.com/go-jose/go-jose/v4/doc.go | 25 - .../github.com/go-jose/go-jose/v4/encoding.go | 228 - .../go-jose/go-jose/v4/json/LICENSE | 27 - .../go-jose/go-jose/v4/json/README.md | 13 - .../go-jose/go-jose/v4/json/decode.go | 1216 -- .../go-jose/go-jose/v4/json/encode.go | 1197 -- .../go-jose/go-jose/v4/json/indent.go | 141 - .../go-jose/go-jose/v4/json/scanner.go | 623 - .../go-jose/go-jose/v4/json/stream.go | 484 - .../go-jose/go-jose/v4/json/tags.go | 44 - vendor/github.com/go-jose/go-jose/v4/jwe.go | 391 - vendor/github.com/go-jose/go-jose/v4/jwk.go | 823 - vendor/github.com/go-jose/go-jose/v4/jws.go | 470 - .../github.com/go-jose/go-jose/v4/opaque.go | 147 - .../github.com/go-jose/go-jose/v4/shared.go | 531 - .../github.com/go-jose/go-jose/v4/signing.go | 505 - .../go-jose/go-jose/v4/symmetric.go | 521 - .../go-jose/go-jose/v4/symmetric_go124.go | 28 - .../go-jose/go-jose/v4/symmetric_legacy.go | 29 - vendor/github.com/go-logr/logr/.golangci.yaml | 28 - vendor/github.com/go-logr/logr/CHANGELOG.md | 6 - .../github.com/go-logr/logr/CONTRIBUTING.md | 17 - vendor/github.com/go-logr/logr/LICENSE | 201 - vendor/github.com/go-logr/logr/README.md | 407 - vendor/github.com/go-logr/logr/SECURITY.md | 18 - vendor/github.com/go-logr/logr/context.go | 33 - .../github.com/go-logr/logr/context_noslog.go | 49 - .../github.com/go-logr/logr/context_slog.go | 83 - vendor/github.com/go-logr/logr/discard.go | 24 - vendor/github.com/go-logr/logr/funcr/funcr.go | 914 - .../github.com/go-logr/logr/funcr/slogsink.go | 105 - vendor/github.com/go-logr/logr/logr.go | 520 - vendor/github.com/go-logr/logr/sloghandler.go | 192 - vendor/github.com/go-logr/logr/slogr.go | 100 - vendor/github.com/go-logr/logr/slogsink.go | 120 - vendor/github.com/go-logr/stdr/LICENSE | 201 - vendor/github.com/go-logr/stdr/README.md | 6 - vendor/github.com/go-logr/stdr/stdr.go | 170 - vendor/github.com/go-stack/stack/.travis.yml | 15 - vendor/github.com/go-stack/stack/LICENSE.md | 21 - vendor/github.com/go-stack/stack/README.md | 38 - vendor/github.com/go-stack/stack/stack.go | 400 - vendor/github.com/go-toast/toast/.gitignore | 3 - vendor/github.com/go-toast/toast/LICENSE | 7 - vendor/github.com/go-toast/toast/readme.md | 61 - .../toast/screenshot-action-centre.png | Bin 85126 -> 0 bytes .../go-toast/toast/screenshot-cli.png | Bin 62466 -> 0 bytes .../go-toast/toast/screenshot-toast.png | Bin 62644 -> 0 bytes vendor/github.com/go-toast/toast/toast.go | 359 - .../github.com/godbus/dbus/v5/CONTRIBUTING.md | 50 - vendor/github.com/godbus/dbus/v5/LICENSE | 25 - vendor/github.com/godbus/dbus/v5/MAINTAINERS | 3 - vendor/github.com/godbus/dbus/v5/README.md | 46 - vendor/github.com/godbus/dbus/v5/auth.go | 257 - .../godbus/dbus/v5/auth_anonymous.go | 16 - .../godbus/dbus/v5/auth_external.go | 26 - vendor/github.com/godbus/dbus/v5/auth_sha1.go | 102 - vendor/github.com/godbus/dbus/v5/call.go | 69 - vendor/github.com/godbus/dbus/v5/conn.go | 996 - .../github.com/godbus/dbus/v5/conn_darwin.go | 37 - .../github.com/godbus/dbus/v5/conn_other.go | 90 - vendor/github.com/godbus/dbus/v5/conn_unix.go | 17 - .../github.com/godbus/dbus/v5/conn_windows.go | 15 - vendor/github.com/godbus/dbus/v5/dbus.go | 430 - vendor/github.com/godbus/dbus/v5/decoder.go | 292 - .../godbus/dbus/v5/default_handler.go | 342 - vendor/github.com/godbus/dbus/v5/doc.go | 71 - vendor/github.com/godbus/dbus/v5/encoder.go | 235 - vendor/github.com/godbus/dbus/v5/escape.go | 84 - vendor/github.com/godbus/dbus/v5/export.go | 463 - vendor/github.com/godbus/dbus/v5/homedir.go | 25 - vendor/github.com/godbus/dbus/v5/match.go | 89 - vendor/github.com/godbus/dbus/v5/message.go | 390 - vendor/github.com/godbus/dbus/v5/object.go | 174 - vendor/github.com/godbus/dbus/v5/sequence.go | 24 - .../godbus/dbus/v5/sequential_handler.go | 125 - .../godbus/dbus/v5/server_interfaces.go | 107 - vendor/github.com/godbus/dbus/v5/sig.go | 293 - .../godbus/dbus/v5/transport_darwin.go | 6 - .../godbus/dbus/v5/transport_generic.go | 52 - .../godbus/dbus/v5/transport_nonce_tcp.go | 39 - .../godbus/dbus/v5/transport_tcp.go | 41 - .../godbus/dbus/v5/transport_unix.go | 212 - .../dbus/v5/transport_unixcred_dragonfly.go | 95 - .../dbus/v5/transport_unixcred_freebsd.go | 92 - .../dbus/v5/transport_unixcred_linux.go | 25 - .../dbus/v5/transport_unixcred_netbsd.go | 14 - .../dbus/v5/transport_unixcred_openbsd.go | 14 - .../godbus/dbus/v5/transport_zos.go | 6 - vendor/github.com/godbus/dbus/v5/variant.go | 150 - .../godbus/dbus/v5/variant_lexer.go | 284 - .../godbus/dbus/v5/variant_parser.go | 817 - vendor/github.com/gogo/protobuf/AUTHORS | 15 - vendor/github.com/gogo/protobuf/CONTRIBUTORS | 23 - vendor/github.com/gogo/protobuf/LICENSE | 35 - .../gogo/protobuf/gogoproto/Makefile | 37 - .../github.com/gogo/protobuf/gogoproto/doc.go | 169 - .../gogo/protobuf/gogoproto/gogo.pb.go | 874 - .../gogo/protobuf/gogoproto/gogo.pb.golden | 45 - .../gogo/protobuf/gogoproto/gogo.proto | 144 - .../gogo/protobuf/gogoproto/helper.go | 415 - .../github.com/gogo/protobuf/proto/Makefile | 43 - .../github.com/gogo/protobuf/proto/clone.go | 258 - .../gogo/protobuf/proto/custom_gogo.go | 39 - .../github.com/gogo/protobuf/proto/decode.go | 427 - .../gogo/protobuf/proto/deprecated.go | 63 - .../github.com/gogo/protobuf/proto/discard.go | 350 - .../gogo/protobuf/proto/duration.go | 100 - .../gogo/protobuf/proto/duration_gogo.go | 49 - .../github.com/gogo/protobuf/proto/encode.go | 205 - .../gogo/protobuf/proto/encode_gogo.go | 33 - .../github.com/gogo/protobuf/proto/equal.go | 300 - .../gogo/protobuf/proto/extensions.go | 605 - .../gogo/protobuf/proto/extensions_gogo.go | 389 - vendor/github.com/gogo/protobuf/proto/lib.go | 973 - .../gogo/protobuf/proto/lib_gogo.go | 50 - .../gogo/protobuf/proto/message_set.go | 181 - .../gogo/protobuf/proto/pointer_reflect.go | 357 - .../protobuf/proto/pointer_reflect_gogo.go | 59 - .../gogo/protobuf/proto/pointer_unsafe.go | 308 - .../protobuf/proto/pointer_unsafe_gogo.go | 56 - .../gogo/protobuf/proto/properties.go | 610 - .../gogo/protobuf/proto/properties_gogo.go | 36 - .../gogo/protobuf/proto/skip_gogo.go | 119 - .../gogo/protobuf/proto/table_marshal.go | 3009 --- .../gogo/protobuf/proto/table_marshal_gogo.go | 388 - .../gogo/protobuf/proto/table_merge.go | 676 - .../gogo/protobuf/proto/table_unmarshal.go | 2249 --- .../protobuf/proto/table_unmarshal_gogo.go | 385 - vendor/github.com/gogo/protobuf/proto/text.go | 930 - .../gogo/protobuf/proto/text_gogo.go | 57 - .../gogo/protobuf/proto/text_parser.go | 1018 -- .../gogo/protobuf/proto/timestamp.go | 113 - .../gogo/protobuf/proto/timestamp_gogo.go | 49 - .../gogo/protobuf/proto/wrappers.go | 1888 -- .../gogo/protobuf/proto/wrappers_gogo.go | 113 - .../protoc-gen-gogo/descriptor/Makefile | 36 - .../protoc-gen-gogo/descriptor/descriptor.go | 118 - .../descriptor/descriptor.pb.go | 2865 --- .../descriptor/descriptor_gostring.gen.go | 752 - .../protoc-gen-gogo/descriptor/helper.go | 390 - .../gogo/protobuf/sortkeys/sortkeys.go | 101 - vendor/github.com/gogo/protobuf/types/any.go | 140 - .../github.com/gogo/protobuf/types/any.pb.go | 694 - .../github.com/gogo/protobuf/types/api.pb.go | 2134 --- vendor/github.com/gogo/protobuf/types/doc.go | 35 - .../gogo/protobuf/types/duration.go | 100 - .../gogo/protobuf/types/duration.pb.go | 517 - .../gogo/protobuf/types/duration_gogo.go | 100 - .../gogo/protobuf/types/empty.pb.go | 462 - .../gogo/protobuf/types/field_mask.pb.go | 738 - .../gogo/protobuf/types/protosize.go | 34 - .../gogo/protobuf/types/source_context.pb.go | 524 - .../gogo/protobuf/types/struct.pb.go | 2271 --- .../gogo/protobuf/types/timestamp.go | 130 - .../gogo/protobuf/types/timestamp.pb.go | 539 - .../gogo/protobuf/types/timestamp_gogo.go | 94 - .../github.com/gogo/protobuf/types/type.pb.go | 3355 ---- .../gogo/protobuf/types/wrappers.pb.go | 2703 --- .../gogo/protobuf/types/wrappers_gogo.go | 300 - vendor/github.com/golang/groupcache/LICENSE | 191 - .../github.com/golang/groupcache/lru/lru.go | 133 - vendor/github.com/google/uuid/CHANGELOG.md | 41 - vendor/github.com/google/uuid/CONTRIBUTING.md | 26 - vendor/github.com/google/uuid/CONTRIBUTORS | 9 - vendor/github.com/google/uuid/LICENSE | 27 - vendor/github.com/google/uuid/README.md | 21 - vendor/github.com/google/uuid/dce.go | 80 - vendor/github.com/google/uuid/doc.go | 12 - vendor/github.com/google/uuid/hash.go | 59 - vendor/github.com/google/uuid/marshal.go | 38 - vendor/github.com/google/uuid/node.go | 90 - vendor/github.com/google/uuid/node_js.go | 12 - vendor/github.com/google/uuid/node_net.go | 33 - vendor/github.com/google/uuid/null.go | 118 - vendor/github.com/google/uuid/sql.go | 59 - vendor/github.com/google/uuid/time.go | 134 - vendor/github.com/google/uuid/util.go | 43 - vendor/github.com/google/uuid/uuid.go | 365 - vendor/github.com/google/uuid/version1.go | 44 - vendor/github.com/google/uuid/version4.go | 76 - vendor/github.com/google/uuid/version6.go | 56 - vendor/github.com/google/uuid/version7.go | 104 - vendor/github.com/gorilla/css/LICENSE | 28 - vendor/github.com/gorilla/css/scanner/doc.go | 33 - .../github.com/gorilla/css/scanner/scanner.go | 360 - vendor/github.com/grafana/regexp/.gitignore | 15 - vendor/github.com/grafana/regexp/LICENSE | 27 - vendor/github.com/grafana/regexp/README.md | 12 - vendor/github.com/grafana/regexp/backtrack.go | 365 - vendor/github.com/grafana/regexp/exec.go | 554 - vendor/github.com/grafana/regexp/onepass.go | 500 - vendor/github.com/grafana/regexp/regexp.go | 1304 -- .../grafana/regexp/syntax/compile.go | 296 - .../github.com/grafana/regexp/syntax/doc.go | 142 - .../grafana/regexp/syntax/make_perl_groups.pl | 113 - .../grafana/regexp/syntax/op_string.go | 52 - .../github.com/grafana/regexp/syntax/parse.go | 2136 --- .../grafana/regexp/syntax/perl_groups.go | 134 - .../github.com/grafana/regexp/syntax/prog.go | 349 - .../grafana/regexp/syntax/regexp.go | 464 - .../grafana/regexp/syntax/simplify.go | 151 - vendor/github.com/jpillora/backoff/LICENSE | 21 - vendor/github.com/jpillora/backoff/README.md | 119 - vendor/github.com/jpillora/backoff/backoff.go | 100 - .../github.com/kardianos/service/.gitignore | 1 - .../github.com/kardianos/service/.travis.yml | 20 - vendor/github.com/kardianos/service/LICENSE | 20 - vendor/github.com/kardianos/service/README.md | 14 - .../github.com/kardianos/service/appveyor.yml | 21 - .../github.com/kardianos/service/console.go | 48 - .../kardianos/service/linux-test-su.sh | 15 - .../github.com/kardianos/service/service.go | 442 - .../kardianos/service/service_aix.go | 281 - .../kardianos/service/service_darwin.go | 347 - .../kardianos/service/service_freebsd.go | 220 - .../kardianos/service/service_go1.8.go | 15 - .../kardianos/service/service_linux.go | 143 - .../kardianos/service/service_openrc_linux.go | 243 - .../kardianos/service/service_solaris.go | 308 - .../service/service_systemd_linux.go | 328 - .../kardianos/service/service_sysv_linux.go | 287 - .../kardianos/service/service_unix.go | 142 - .../service/service_upstart_linux.go | 271 - .../kardianos/service/service_windows.go | 558 - .../github.com/kardianos/service/version.go | 57 - .../kevinburke/ssh_config/.gitignore | 0 .../github.com/kevinburke/ssh_config/.mailmap | 1 - .../kevinburke/ssh_config/AUTHORS.txt | 10 - .../kevinburke/ssh_config/CHANGELOG.md | 32 - .../github.com/kevinburke/ssh_config/LICENSE | 49 - .../github.com/kevinburke/ssh_config/Makefile | 29 - .../kevinburke/ssh_config/README.md | 92 - .../kevinburke/ssh_config/config.go | 840 - .../github.com/kevinburke/ssh_config/lexer.go | 240 - .../kevinburke/ssh_config/parser.go | 200 - .../kevinburke/ssh_config/position.go | 25 - .../github.com/kevinburke/ssh_config/token.go | 49 - .../kevinburke/ssh_config/validators.go | 186 - .../github.com/klauspost/cpuid/v2/.gitignore | 24 - .../klauspost/cpuid/v2/.goreleaser.yml | 57 - .../klauspost/cpuid/v2/CONTRIBUTING.txt | 35 - vendor/github.com/klauspost/cpuid/v2/LICENSE | 22 - .../github.com/klauspost/cpuid/v2/README.md | 512 - vendor/github.com/klauspost/cpuid/v2/cpuid.go | 1679 -- .../github.com/klauspost/cpuid/v2/cpuid_386.s | 47 - .../klauspost/cpuid/v2/cpuid_amd64.s | 72 - .../klauspost/cpuid/v2/cpuid_arm64.s | 36 - .../klauspost/cpuid/v2/detect_arm64.go | 250 - .../klauspost/cpuid/v2/detect_ref.go | 17 - .../klauspost/cpuid/v2/detect_x86.go | 45 - .../klauspost/cpuid/v2/featureid_string.go | 308 - .../klauspost/cpuid/v2/os_darwin_arm64.go | 129 - .../klauspost/cpuid/v2/os_linux_arm64.go | 208 - .../klauspost/cpuid/v2/os_other_arm64.go | 16 - .../klauspost/cpuid/v2/os_safe_linux_arm64.go | 8 - .../cpuid/v2/os_unsafe_linux_arm64.go | 11 - .../klauspost/cpuid/v2/test-architectures.sh | 15 - .../lrstanley/bubblezone/.editorconfig | 53 - .../lrstanley/bubblezone/.gitignore | 12 - .../lrstanley/bubblezone/.golangci.yml | 228 - .../github.com/lrstanley/bubblezone/LICENSE | 21 - .../github.com/lrstanley/bubblezone/Makefile | 24 - .../github.com/lrstanley/bubblezone/README.md | 350 - .../lrstanley/bubblezone/manager.go | 248 - .../lrstanley/bubblezone/manager_global.go | 156 - .../lrstanley/bubblezone/messages.go | 70 - .../lrstanley/bubblezone/scanner.go | 160 - .../lrstanley/bubblezone/zoneinfo.go | 63 - .../github.com/matoous/go-nanoid/.gitignore | 1 - .../matoous/go-nanoid/.goreleaser.yml | 28 - vendor/github.com/matoous/go-nanoid/LICENSE | 21 - vendor/github.com/matoous/go-nanoid/Makefile | 16 - vendor/github.com/matoous/go-nanoid/README.md | 61 - .../github.com/matoous/go-nanoid/gonanoid.go | 131 - .../github.com/mattn/go-localereader/LICENSE | 21 - .../mattn/go-localereader/README.md | 23 - .../mattn/go-localereader/localereader.go | 19 - .../go-localereader/localereader_unix.go | 11 - .../go-localereader/localereader_windows.go | 85 - .../microcosm-cc/bluemonday/CONTRIBUTING.md | 50 - .../microcosm-cc/bluemonday/CREDITS.md | 8 - .../microcosm-cc/bluemonday/LICENSE.md | 28 - .../microcosm-cc/bluemonday/README.md | 386 - .../microcosm-cc/bluemonday/SECURITY.md | 13 - .../microcosm-cc/bluemonday/css/handlers.go | 2016 -- .../github.com/microcosm-cc/bluemonday/doc.go | 104 - .../microcosm-cc/bluemonday/helpers.go | 300 - .../microcosm-cc/bluemonday/policies.go | 253 - .../microcosm-cc/bluemonday/policy.go | 990 - .../microcosm-cc/bluemonday/sanitize.go | 1096 -- .../v1/alertv1connect/service.connect.go | 370 - .../api/go/svc/alert/v1/service.pb.go | 1485 -- .../auth/v1/authv1connect/service.connect.go | 195 - .../minitape/api/go/svc/auth/v1/service.pb.go | 748 - .../v1/dashboardv1connect/service.connect.go | 225 - .../api/go/svc/dashboard/v1/service.pb.go | 740 - .../v1/featurev1connect/service.connect.go | 167 - .../api/go/svc/feature/v1/service.pb.go | 411 - .../v1/ingestv1connect/service.connect.go | 137 - .../api/go/svc/ingest/v1/service.pb.go | 302 - .../v1/localhostv1connect/service.connect.go | 340 - .../api/go/svc/localhost/v1/service.pb.go | 889 - .../organizationv1connect/service.connect.go | 432 - .../api/go/svc/organization/v1/service.pb.go | 2075 --- .../v1/productv1connect/service.connect.go | 138 - .../api/go/svc/product/v1/service.pb.go | 400 - .../v1/projectv1connect/service.connect.go | 287 - .../api/go/svc/project/v1/service.pb.go | 927 - .../v1/queryv1connect/service.connect.go | 250 - .../queryv1connect/trace_service.connect.go | 136 - .../api/go/svc/query/v1/service.pb.go | 1021 -- .../api/go/svc/query/v1/trace_service.pb.go | 338 - .../api/go/svc/token/v1/service.pb.go | 581 - .../v1/tokenv1connect/service.connect.go | 196 - .../api/go/svc/user/v1/service_private.pb.go | 1635 -- .../api/go/svc/user/v1/service_public.pb.go | 462 - .../userv1connect/service_private.connect.go | 456 - .../userv1connect/service_public.connect.go | 167 - .../mitchellh/hashstructure/v2/LICENSE | 21 - .../mitchellh/hashstructure/v2/README.md | 76 - .../mitchellh/hashstructure/v2/errors.go | 22 - .../hashstructure/v2/hashstructure.go | 482 - .../mitchellh/hashstructure/v2/include.go | 22 - vendor/github.com/muesli/ansi/.gitignore | 15 - vendor/github.com/muesli/ansi/.golangci.yml | 27 - vendor/github.com/muesli/ansi/LICENSE | 21 - vendor/github.com/muesli/ansi/README.md | 31 - vendor/github.com/muesli/ansi/ansi.go | 7 - vendor/github.com/muesli/ansi/buffer.go | 40 - .../muesli/ansi/compressor/writer.go | 132 - vendor/github.com/muesli/ansi/writer.go | 76 - .../github.com/muesli/cancelreader/.gitignore | 15 - .../muesli/cancelreader/.golangci-soft.yml | 47 - .../muesli/cancelreader/.golangci.yml | 29 - vendor/github.com/muesli/cancelreader/LICENSE | 21 - .../github.com/muesli/cancelreader/README.md | 64 - .../muesli/cancelreader/cancelreader.go | 93 - .../muesli/cancelreader/cancelreader_bsd.go | 146 - .../cancelreader/cancelreader_default.go | 12 - .../muesli/cancelreader/cancelreader_linux.go | 154 - .../cancelreader/cancelreader_select.go | 136 - .../muesli/cancelreader/cancelreader_unix.go | 18 - .../cancelreader/cancelreader_windows.go | 244 - vendor/github.com/muesli/reflow/LICENSE | 21 - vendor/github.com/muesli/reflow/ansi/ansi.go | 7 - .../github.com/muesli/reflow/ansi/buffer.go | 40 - .../github.com/muesli/reflow/ansi/writer.go | 76 - .../github.com/muesli/reflow/indent/indent.go | 111 - .../muesli/reflow/padding/padding.go | 143 - .../muesli/reflow/wordwrap/wordwrap.go | 167 - vendor/github.com/muhlemmer/gu/LICENSE | 24 - vendor/github.com/muhlemmer/gu/README.md | 46 - vendor/github.com/muhlemmer/gu/gu.go | 4 - vendor/github.com/muhlemmer/gu/map.go | 78 - vendor/github.com/muhlemmer/gu/pointer.go | 32 - vendor/github.com/muhlemmer/gu/slice.go | 92 - vendor/github.com/munnerz/goautoneg/LICENSE | 31 - vendor/github.com/munnerz/goautoneg/Makefile | 13 - .../github.com/munnerz/goautoneg/README.txt | 67 - .../github.com/munnerz/goautoneg/autoneg.go | 189 - .../mwitkow/go-conntrack/.gitignore | 163 - .../mwitkow/go-conntrack/.travis.yml | 17 - .../github.com/mwitkow/go-conntrack/LICENSE | 201 - .../github.com/mwitkow/go-conntrack/README.md | 88 - .../mwitkow/go-conntrack/dialer_reporter.go | 108 - .../mwitkow/go-conntrack/dialer_wrapper.go | 166 - .../mwitkow/go-conntrack/listener_reporter.go | 43 - .../mwitkow/go-conntrack/listener_wrapper.go | 158 - vendor/github.com/nu7hatch/gouuid/.gitignore | 11 - vendor/github.com/nu7hatch/gouuid/COPYING | 19 - vendor/github.com/nu7hatch/gouuid/README.md | 21 - vendor/github.com/nu7hatch/gouuid/uuid.go | 173 - vendor/github.com/oxtoacart/bpool/LICENSE | 202 - vendor/github.com/oxtoacart/bpool/README.md | 65 - vendor/github.com/oxtoacart/bpool/bpool.go | 6 - .../github.com/oxtoacart/bpool/bufferpool.go | 45 - vendor/github.com/oxtoacart/bpool/bytepool.go | 56 - .../github.com/oxtoacart/bpool/byteslice.go | 81 - .../oxtoacart/bpool/sizedbufferpool.go | 60 - vendor/github.com/perses/perses/LICENSE | 201 - .../perses/perses/pkg/model/api/auth.go | 152 - .../perses/perses/pkg/model/api/entity.go | 25 - .../perses/perses/pkg/model/api/migrate.go | 44 - .../perses/pkg/model/api/v1/common/display.go | 19 - .../pkg/model/api/v1/common/duration.go | 203 - .../perses/pkg/model/api/v1/common/jsonref.go | 77 - .../perses/pkg/model/api/v1/common/plugin.go | 63 - .../perses/pkg/model/api/v1/common/reflect.go | 23 - .../perses/pkg/model/api/v1/common/regexp.go | 83 - .../perses/pkg/model/api/v1/common/url.go | 126 - .../pkg/model/api/v1/common/validate.go | 39 - .../perses/pkg/model/api/v1/dashboard.go | 239 - .../pkg/model/api/v1/dashboard/layout.go | 143 - .../pkg/model/api/v1/dashboard/variable.go | 172 - .../perses/pkg/model/api/v1/datasource.go | 169 - .../pkg/model/api/v1/ephemeraldashboard.go | 147 - .../perses/perses/pkg/model/api/v1/folder.go | 146 - .../perses/perses/pkg/model/api/v1/health.go | 22 - .../perses/perses/pkg/model/api/v1/kind.go | 198 - .../perses/pkg/model/api/v1/metadata.go | 195 - .../perses/perses/pkg/model/api/v1/partial.go | 52 - .../perses/perses/pkg/model/api/v1/plugin.go | 81 - .../perses/pkg/model/api/v1/plugin/plugin.go | 131 - .../perses/perses/pkg/model/api/v1/project.go | 77 - .../perses/pkg/model/api/v1/public_secret.go | 96 - .../perses/pkg/model/api/v1/public_user.go | 70 - .../perses/perses/pkg/model/api/v1/role.go | 156 - .../perses/pkg/model/api/v1/role/action.go | 89 - .../pkg/model/api/v1/role/permission.go | 63 - .../perses/pkg/model/api/v1/role/scope.go | 144 - .../perses/pkg/model/api/v1/rolebinding.go | 234 - .../perses/perses/pkg/model/api/v1/secret.go | 101 - .../pkg/model/api/v1/secret/authorization.go | 102 - .../pkg/model/api/v1/secret/basic_auth.go | 93 - .../perses/pkg/model/api/v1/secret/oauth.go | 113 - .../perses/pkg/model/api/v1/secret/secret.go | 51 - .../pkg/model/api/v1/secret/tls_config.go | 123 - .../perses/perses/pkg/model/api/v1/user.go | 76 - .../perses/pkg/model/api/v1/variable.go | 127 - .../perses/pkg/model/api/v1/variable/list.go | 153 - .../perses/pkg/model/api/v1/variable/text.go | 31 - .../pkg/model/api/v1/variable/variable.go | 73 - .../perses/perses/pkg/model/api/v1/view.go | 79 - vendor/github.com/pjbgf/sha1cd/Dockerfile.arm | 22 - .../github.com/pjbgf/sha1cd/Dockerfile.arm64 | 23 - vendor/github.com/pjbgf/sha1cd/LICENSE | 201 - vendor/github.com/pjbgf/sha1cd/Makefile | 36 - vendor/github.com/pjbgf/sha1cd/README.md | 57 - vendor/github.com/pjbgf/sha1cd/cgo/sha1.h | 114 - .../github.com/pjbgf/sha1cd/cgo/ubc_check.h | 64 - vendor/github.com/pjbgf/sha1cd/detection.go | 11 - .../github.com/pjbgf/sha1cd/internal/const.go | 42 - vendor/github.com/pjbgf/sha1cd/sha1cd.go | 217 - .../pjbgf/sha1cd/sha1cdblock_amd64.go | 52 - .../pjbgf/sha1cd/sha1cdblock_amd64.s | 274 - .../pjbgf/sha1cd/sha1cdblock_arm64.go | 48 - .../pjbgf/sha1cd/sha1cdblock_arm64.s | 249 - .../pjbgf/sha1cd/sha1cdblock_generic.go | 311 - .../pjbgf/sha1cd/sha1cdblock_noasm.go | 7 - vendor/github.com/pjbgf/sha1cd/ubc/const.go | 624 - vendor/github.com/pjbgf/sha1cd/ubc/ubc.go | 373 - vendor/github.com/pkg/browser/LICENSE | 23 - vendor/github.com/pkg/browser/README.md | 55 - vendor/github.com/pkg/browser/browser.go | 57 - .../github.com/pkg/browser/browser_darwin.go | 5 - .../github.com/pkg/browser/browser_freebsd.go | 14 - .../github.com/pkg/browser/browser_linux.go | 21 - .../github.com/pkg/browser/browser_netbsd.go | 14 - .../github.com/pkg/browser/browser_openbsd.go | 14 - .../pkg/browser/browser_unsupported.go | 12 - .../github.com/pkg/browser/browser_windows.go | 7 - .../prometheus/client_golang/LICENSE | 201 - .../prometheus/client_golang/NOTICE | 18 - .../client_golang/prometheus/.gitignore | 1 - .../client_golang/prometheus/README.md | 1 - .../prometheus/build_info_collector.go | 38 - .../client_golang/prometheus/collector.go | 128 - .../client_golang/prometheus/collectorfunc.go | 30 - .../client_golang/prometheus/counter.go | 358 - .../client_golang/prometheus/desc.go | 210 - .../client_golang/prometheus/doc.go | 210 - .../prometheus/expvar_collector.go | 86 - .../client_golang/prometheus/fnv.go | 42 - .../client_golang/prometheus/gauge.go | 311 - .../client_golang/prometheus/get_pid.go | 26 - .../prometheus/get_pid_gopherjs.go | 23 - .../client_golang/prometheus/go_collector.go | 274 - .../prometheus/go_collector_go116.go | 122 - .../prometheus/go_collector_latest.go | 574 - .../client_golang/prometheus/histogram.go | 2056 --- .../prometheus/internal/almost_equal.go | 60 - .../prometheus/internal/difflib.go | 655 - .../internal/go_collector_options.go | 34 - .../prometheus/internal/go_runtime_metrics.go | 143 - .../prometheus/internal/metric.go | 101 - .../client_golang/prometheus/labels.go | 188 - .../client_golang/prometheus/metric.go | 265 - .../client_golang/prometheus/num_threads.go | 25 - .../prometheus/num_threads_gopherjs.go | 22 - .../client_golang/prometheus/observer.go | 64 - .../prometheus/process_collector.go | 180 - .../prometheus/process_collector_darwin.go | 130 - .../process_collector_mem_cgo_darwin.c | 84 - .../process_collector_mem_cgo_darwin.go | 51 - .../process_collector_mem_nocgo_darwin.go | 39 - .../process_collector_not_supported.go | 33 - .../process_collector_procfsenabled.go | 96 - .../prometheus/process_collector_windows.go | 125 - .../client_golang/prometheus/registry.go | 1076 -- .../client_golang/prometheus/summary.go | 830 - .../client_golang/prometheus/timer.go | 81 - .../client_golang/prometheus/untyped.go | 42 - .../client_golang/prometheus/value.go | 274 - .../client_golang/prometheus/vec.go | 709 - .../client_golang/prometheus/vnext.go | 23 - .../client_golang/prometheus/wrap.go | 214 - .../prometheus/client_model/LICENSE | 201 - .../github.com/prometheus/client_model/NOTICE | 5 - .../prometheus/client_model/go/metrics.pb.go | 1399 -- vendor/github.com/prometheus/common/LICENSE | 201 - vendor/github.com/prometheus/common/NOTICE | 5 - .../prometheus/common/config/config.go | 101 - .../prometheus/common/config/headers.go | 139 - .../prometheus/common/config/http_config.go | 1532 -- .../prometheus/common/expfmt/decode.go | 431 - .../prometheus/common/expfmt/encode.go | 198 - .../prometheus/common/expfmt/expfmt.go | 207 - .../prometheus/common/expfmt/fuzz.go | 37 - .../common/expfmt/openmetrics_create.go | 696 - .../prometheus/common/expfmt/text_create.go | 520 - .../prometheus/common/expfmt/text_parse.go | 901 - .../common/helpers/templates/time.go | 123 - .../prometheus/common/model/alert.go | 162 - .../prometheus/common/model/fingerprinting.go | 105 - .../github.com/prometheus/common/model/fnv.go | 42 - .../prometheus/common/model/labels.go | 236 - .../prometheus/common/model/labelset.go | 158 - .../common/model/labelset_string.go | 43 - .../prometheus/common/model/metadata.go | 28 - .../prometheus/common/model/metric.go | 465 - .../prometheus/common/model/model.go | 16 - .../prometheus/common/model/signature.go | 142 - .../prometheus/common/model/silence.go | 107 - .../prometheus/common/model/time.go | 359 - .../prometheus/common/model/value.go | 364 - .../prometheus/common/model/value_float.go | 99 - .../common/model/value_histogram.go | 179 - .../prometheus/common/model/value_type.go | 83 - .../prometheus/common/promslog/slog.go | 275 - .../github.com/prometheus/procfs/.gitignore | 2 - .../prometheus/procfs/.golangci.yml | 22 - .../prometheus/procfs/CODE_OF_CONDUCT.md | 3 - .../prometheus/procfs/CONTRIBUTING.md | 121 - vendor/github.com/prometheus/procfs/LICENSE | 201 - .../prometheus/procfs/MAINTAINERS.md | 3 - vendor/github.com/prometheus/procfs/Makefile | 31 - .../prometheus/procfs/Makefile.common | 277 - vendor/github.com/prometheus/procfs/NOTICE | 7 - vendor/github.com/prometheus/procfs/README.md | 61 - .../github.com/prometheus/procfs/SECURITY.md | 6 - vendor/github.com/prometheus/procfs/arp.go | 116 - .../github.com/prometheus/procfs/buddyinfo.go | 85 - .../github.com/prometheus/procfs/cmdline.go | 30 - .../github.com/prometheus/procfs/cpuinfo.go | 519 - .../prometheus/procfs/cpuinfo_armx.go | 20 - .../prometheus/procfs/cpuinfo_loong64.go | 19 - .../prometheus/procfs/cpuinfo_mipsx.go | 20 - .../prometheus/procfs/cpuinfo_others.go | 19 - .../prometheus/procfs/cpuinfo_ppcx.go | 20 - .../prometheus/procfs/cpuinfo_riscvx.go | 20 - .../prometheus/procfs/cpuinfo_s390x.go | 19 - .../prometheus/procfs/cpuinfo_x86.go | 20 - vendor/github.com/prometheus/procfs/crypto.go | 154 - vendor/github.com/prometheus/procfs/doc.go | 44 - vendor/github.com/prometheus/procfs/fs.go | 50 - .../prometheus/procfs/fs_statfs_notype.go | 23 - .../prometheus/procfs/fs_statfs_type.go | 33 - .../github.com/prometheus/procfs/fscache.go | 422 - .../prometheus/procfs/internal/fs/fs.go | 55 - .../prometheus/procfs/internal/util/parse.go | 112 - .../procfs/internal/util/readfile.go | 37 - .../procfs/internal/util/sysreadfile.go | 50 - .../internal/util/sysreadfile_compat.go | 27 - .../procfs/internal/util/valueparser.go | 91 - vendor/github.com/prometheus/procfs/ipvs.go | 241 - .../prometheus/procfs/kernel_random.go | 63 - .../github.com/prometheus/procfs/loadavg.go | 62 - vendor/github.com/prometheus/procfs/mdstat.go | 276 - .../github.com/prometheus/procfs/meminfo.go | 389 - .../github.com/prometheus/procfs/mountinfo.go | 180 - .../prometheus/procfs/mountstats.go | 707 - .../prometheus/procfs/net_conntrackstat.go | 118 - .../github.com/prometheus/procfs/net_dev.go | 205 - .../prometheus/procfs/net_ip_socket.go | 248 - .../prometheus/procfs/net_protocols.go | 180 - .../github.com/prometheus/procfs/net_route.go | 143 - .../prometheus/procfs/net_sockstat.go | 162 - .../prometheus/procfs/net_softnet.go | 155 - .../github.com/prometheus/procfs/net_tcp.go | 64 - .../prometheus/procfs/net_tls_stat.go | 119 - .../github.com/prometheus/procfs/net_udp.go | 64 - .../github.com/prometheus/procfs/net_unix.go | 257 - .../prometheus/procfs/net_wireless.go | 182 - .../github.com/prometheus/procfs/net_xfrm.go | 189 - .../github.com/prometheus/procfs/netstat.go | 82 - vendor/github.com/prometheus/procfs/proc.go | 338 - .../prometheus/procfs/proc_cgroup.go | 98 - .../prometheus/procfs/proc_cgroups.go | 98 - .../prometheus/procfs/proc_environ.go | 37 - .../prometheus/procfs/proc_fdinfo.go | 138 - .../prometheus/procfs/proc_interrupts.go | 98 - .../github.com/prometheus/procfs/proc_io.go | 59 - .../prometheus/procfs/proc_limits.go | 160 - .../github.com/prometheus/procfs/proc_maps.go | 211 - .../prometheus/procfs/proc_netstat.go | 443 - .../github.com/prometheus/procfs/proc_ns.go | 68 - .../github.com/prometheus/procfs/proc_psi.go | 102 - .../prometheus/procfs/proc_smaps.go | 166 - .../github.com/prometheus/procfs/proc_snmp.go | 353 - .../prometheus/procfs/proc_snmp6.go | 381 - .../github.com/prometheus/procfs/proc_stat.go | 229 - .../prometheus/procfs/proc_status.go | 238 - .../github.com/prometheus/procfs/proc_sys.go | 51 - .../github.com/prometheus/procfs/schedstat.go | 121 - vendor/github.com/prometheus/procfs/slab.go | 151 - .../github.com/prometheus/procfs/softirqs.go | 160 - vendor/github.com/prometheus/procfs/stat.go | 258 - vendor/github.com/prometheus/procfs/swaps.go | 89 - vendor/github.com/prometheus/procfs/thread.go | 80 - vendor/github.com/prometheus/procfs/ttar | 413 - vendor/github.com/prometheus/procfs/vm.go | 212 - .../github.com/prometheus/procfs/zoneinfo.go | 196 - .../github.com/prometheus/prometheus/LICENSE | 201 - .../github.com/prometheus/prometheus/NOTICE | 108 - .../prometheus/model/exemplar/exemplar.go | 67 - .../model/histogram/float_histogram.go | 1358 -- .../prometheus/model/histogram/generic.go | 786 - .../prometheus/model/histogram/histogram.go | 630 - .../prometheus/model/histogram/test_utils.go | 52 - .../prometheus/model/labels/labels.go | 501 - .../prometheus/model/labels/labels_common.go | 238 - .../model/labels/labels_dedupelabels.go | 829 - .../model/labels/labels_stringlabels.go | 679 - .../prometheus/model/labels/matcher.go | 170 - .../prometheus/model/labels/regexp.go | 1100 -- .../prometheus/model/labels/sharding.go | 47 - .../model/labels/sharding_dedupelabels.go | 52 - .../model/labels/sharding_stringlabels.go | 54 - .../prometheus/model/labels/test_utils.go | 87 - .../prometheus/model/metadata/metadata.go | 23 - .../prometheus/model/rulefmt/rulefmt.go | 375 - .../prometheus/model/textparse/README.md | 6 - .../prometheus/model/textparse/interface.go | 163 - .../prometheus/model/textparse/nhcbparse.go | 389 - .../model/textparse/openmetricslex.l | 84 - .../model/textparse/openmetricslex.l.go | 904 - .../model/textparse/openmetricsparse.go | 783 - .../prometheus/model/textparse/promlex.l | 106 - .../prometheus/model/textparse/promlex.l.go | 656 - .../prometheus/model/textparse/promparse.go | 535 - .../model/textparse/protobufparse.go | 692 - .../prometheus/model/timestamp/timestamp.go | 34 - .../prometheus/model/value/value.go | 34 - .../prompb/io/prometheus/client/decoder.go | 782 - .../prompb/io/prometheus/client/metrics.pb.go | 4300 ----- .../prompb/io/prometheus/client/metrics.proto | 160 - .../prometheus/prometheus/promql/durations.go | 136 - .../prometheus/prometheus/promql/engine.go | 4015 ---- .../prometheus/prometheus/promql/functions.go | 1952 -- .../prometheus/prometheus/promql/fuzz.go | 125 - .../promql/histogram_stats_iterator.go | 176 - .../prometheus/prometheus/promql/info.go | 454 - .../prometheus/promql/parser/ast.go | 521 - .../prometheus/promql/parser/functions.go | 458 - .../promql/parser/generated_parser.y | 1182 -- .../promql/parser/generated_parser.y.go | 2172 --- .../prometheus/promql/parser/lex.go | 1143 -- .../prometheus/promql/parser/parse.go | 1133 -- .../promql/parser/posrange/posrange.go | 54 - .../prometheus/promql/parser/prettier.go | 182 - .../promql/parser/prettier_rules.md | 16 - .../prometheus/promql/parser/printer.go | 333 - .../prometheus/promql/parser/value.go | 45 - .../prometheus/prometheus/promql/quantile.go | 686 - .../prometheus/promql/query_logger.go | 236 - .../prometheus/prometheus/promql/value.go | 601 - .../prometheus/prometheus/schema/labels.go | 157 - .../prometheus/prometheus/storage/buffer.go | 823 - .../prometheus/prometheus/storage/errors.go | 62 - .../prometheus/prometheus/storage/fanout.go | 272 - .../prometheus/prometheus/storage/generic.go | 143 - .../prometheus/storage/interface.go | 509 - .../prometheus/prometheus/storage/lazy.go | 71 - .../prometheus/storage/memoized_iterator.go | 147 - .../prometheus/prometheus/storage/merge.go | 915 - .../prometheus/prometheus/storage/noop.go | 97 - .../prometheus/storage/secondary.go | 109 - .../prometheus/prometheus/storage/series.go | 485 - .../prometheus/template/template.go | 404 - .../prometheus/tsdb/chunkenc/bstream.go | 263 - .../prometheus/tsdb/chunkenc/chunk.go | 379 - .../tsdb/chunkenc/float_histogram.go | 1165 -- .../prometheus/tsdb/chunkenc/histogram.go | 1328 -- .../tsdb/chunkenc/histogram_meta.go | 635 - .../prometheus/tsdb/chunkenc/varbit.go | 231 - .../prometheus/tsdb/chunkenc/xor.go | 510 - .../tsdb/chunks/chunk_write_queue.go | 261 - .../prometheus/tsdb/chunks/chunks.go | 776 - .../prometheus/tsdb/chunks/head_chunks.go | 1141 -- .../tsdb/chunks/head_chunks_other.go | 21 - .../tsdb/chunks/head_chunks_windows.go | 18 - .../prometheus/tsdb/chunks/queue.go | 141 - .../prometheus/tsdb/chunks/samples.go | 101 - .../prometheus/tsdb/errors/errors.go | 109 - .../prometheus/tsdb/fileutil/dir.go | 33 - .../prometheus/tsdb/fileutil/dir_unix.go | 22 - .../prometheus/tsdb/fileutil/dir_windows.go | 46 - .../prometheus/tsdb/fileutil/direct_io.go | 39 - .../tsdb/fileutil/direct_io_force.go | 28 - .../tsdb/fileutil/direct_io_linux.go | 29 - .../tsdb/fileutil/direct_io_unsupported.go | 29 - .../tsdb/fileutil/direct_io_writer.go | 409 - .../prometheus/tsdb/fileutil/fileutil.go | 128 - .../prometheus/tsdb/fileutil/flock.go | 41 - .../prometheus/tsdb/fileutil/flock_js.go | 32 - .../prometheus/tsdb/fileutil/flock_plan9.go | 32 - .../prometheus/tsdb/fileutil/flock_solaris.go | 59 - .../prometheus/tsdb/fileutil/flock_unix.go | 54 - .../prometheus/tsdb/fileutil/flock_windows.go | 36 - .../prometheus/tsdb/fileutil/mmap.go | 72 - .../prometheus/tsdb/fileutil/mmap_386.go | 18 - .../prometheus/tsdb/fileutil/mmap_amd64.go | 18 - .../prometheus/tsdb/fileutil/mmap_arm64.go | 18 - .../prometheus/tsdb/fileutil/mmap_js.go | 29 - .../prometheus/tsdb/fileutil/mmap_unix.go | 30 - .../prometheus/tsdb/fileutil/mmap_windows.go | 46 - .../prometheus/tsdb/fileutil/preallocate.go | 54 - .../tsdb/fileutil/preallocate_darwin.go | 41 - .../tsdb/fileutil/preallocate_linux.go | 48 - .../tsdb/fileutil/preallocate_other.go | 25 - .../prometheus/tsdb/fileutil/sync.go | 24 - .../prometheus/tsdb/fileutil/sync_darwin.go | 27 - .../prometheus/tsdb/fileutil/sync_linux.go | 29 - .../prometheus/util/almost/almost.go | 51 - .../util/annotations/annotations.go | 350 - .../util/convertnhcb/convertnhcb.go | 262 - .../prometheus/util/logging/dedupe.go | 136 - .../prometheus/util/logging/file.go | 94 - .../prometheus/util/stats/query_stats.go | 332 - .../prometheus/prometheus/util/stats/timer.go | 93 - .../prometheus/util/strutil/quote.go | 255 - .../prometheus/util/strutil/strconv.go | 64 - .../prometheus/util/zeropool/pool.go | 77 - vendor/github.com/rs/cors/LICENSE | 19 - vendor/github.com/rs/cors/README.md | 125 - vendor/github.com/rs/cors/cors.go | 500 - .../github.com/rs/cors/internal/sortedset.go | 201 - vendor/github.com/rs/cors/utils.go | 25 - vendor/github.com/sergi/go-diff/AUTHORS | 25 - vendor/github.com/sergi/go-diff/CONTRIBUTORS | 32 - vendor/github.com/sergi/go-diff/LICENSE | 20 - .../sergi/go-diff/diffmatchpatch/diff.go | 1360 -- .../go-diff/diffmatchpatch/diffmatchpatch.go | 46 - .../sergi/go-diff/diffmatchpatch/index.go | 32 - .../sergi/go-diff/diffmatchpatch/match.go | 160 - .../sergi/go-diff/diffmatchpatch/mathutil.go | 23 - .../diffmatchpatch/operation_string.go | 17 - .../sergi/go-diff/diffmatchpatch/patch.go | 556 - .../go-diff/diffmatchpatch/stringutil.go | 190 - vendor/github.com/tadvi/systray/.gitignore | 12 - vendor/github.com/tadvi/systray/AUTHORS | 12 - vendor/github.com/tadvi/systray/LICENSE | 21 - vendor/github.com/tadvi/systray/README.md | 52 - .../github.com/tadvi/systray/systray_linux.go | 5 - .../tadvi/systray/systray_windows.go | 630 - .../github.com/yuin/goldmark-emoji/.gitignore | 15 - vendor/github.com/yuin/goldmark-emoji/LICENSE | 21 - .../github.com/yuin/goldmark-emoji/README.md | 70 - .../yuin/goldmark-emoji/ast/emoji.go | 42 - .../goldmark-emoji/definition/definition.go | 106 - .../yuin/goldmark-emoji/definition/github.go | 1889 -- .../github.com/yuin/goldmark-emoji/emoji.go | 360 - vendor/github.com/yuin/goldmark/.gitignore | 19 - vendor/github.com/yuin/goldmark/.golangci.yml | 105 - vendor/github.com/yuin/goldmark/LICENSE | 21 - vendor/github.com/yuin/goldmark/Makefile | 13 - vendor/github.com/yuin/goldmark/README.md | 568 - vendor/github.com/yuin/goldmark/ast/ast.go | 521 - vendor/github.com/yuin/goldmark/ast/block.go | 547 - vendor/github.com/yuin/goldmark/ast/inline.go | 573 - .../goldmark/extension/ast/definition_list.go | 83 - .../yuin/goldmark/extension/ast/footnote.go | 138 - .../goldmark/extension/ast/strikethrough.go | 29 - .../yuin/goldmark/extension/ast/table.go | 158 - .../yuin/goldmark/extension/ast/tasklist.go | 35 - .../github.com/yuin/goldmark/extension/cjk.go | 72 - .../goldmark/extension/definition_list.go | 274 - .../yuin/goldmark/extension/footnote.go | 691 - .../github.com/yuin/goldmark/extension/gfm.go | 18 - .../yuin/goldmark/extension/linkify.go | 322 - .../yuin/goldmark/extension/package.go | 2 - .../yuin/goldmark/extension/strikethrough.go | 118 - .../yuin/goldmark/extension/table.go | 564 - .../yuin/goldmark/extension/tasklist.go | 120 - .../yuin/goldmark/extension/typographer.go | 348 - vendor/github.com/yuin/goldmark/markdown.go | 141 - .../yuin/goldmark/parser/attribute.go | 329 - .../yuin/goldmark/parser/atx_heading.go | 248 - .../yuin/goldmark/parser/auto_link.go | 42 - .../yuin/goldmark/parser/blockquote.go | 70 - .../yuin/goldmark/parser/code_block.go | 102 - .../yuin/goldmark/parser/code_span.go | 84 - .../yuin/goldmark/parser/delimiter.go | 238 - .../yuin/goldmark/parser/emphasis.go | 50 - .../yuin/goldmark/parser/fcode_block.go | 122 - .../yuin/goldmark/parser/html_block.go | 229 - .../github.com/yuin/goldmark/parser/link.go | 449 - .../yuin/goldmark/parser/link_ref.go | 152 - .../github.com/yuin/goldmark/parser/list.go | 287 - .../yuin/goldmark/parser/list_item.go | 90 - .../yuin/goldmark/parser/paragraph.go | 72 - .../github.com/yuin/goldmark/parser/parser.go | 1261 -- .../yuin/goldmark/parser/raw_html.go | 153 - .../yuin/goldmark/parser/setext_headings.go | 126 - .../yuin/goldmark/parser/thematic_break.go | 75 - .../yuin/goldmark/renderer/html/html.go | 1021 -- .../yuin/goldmark/renderer/renderer.go | 174 - .../github.com/yuin/goldmark/text/package.go | 2 - .../github.com/yuin/goldmark/text/reader.go | 660 - .../github.com/yuin/goldmark/text/segment.go | 239 - .../yuin/goldmark/util/html5entities.go | 2155 --- .../goldmark/util/unicode_case_folding.go | 1535 -- vendor/github.com/yuin/goldmark/util/util.go | 988 - .../github.com/yuin/goldmark/util/util_cjk.go | 469 - .../yuin/goldmark/util/util_safe.go | 14 - .../yuin/goldmark/util/util_unsafe_go120.go | 24 - .../yuin/goldmark/util/util_unsafe_go121.go | 18 - vendor/github.com/zeebo/blake3/.gitignore | 7 - vendor/github.com/zeebo/blake3/LICENSE | 125 - vendor/github.com/zeebo/blake3/Makefile | 31 - vendor/github.com/zeebo/blake3/README.md | 77 - vendor/github.com/zeebo/blake3/api.go | 165 - vendor/github.com/zeebo/blake3/blake3.go | 285 - vendor/github.com/zeebo/blake3/digest.go | 100 - .../zeebo/blake3/internal/alg/alg.go | 18 - .../blake3/internal/alg/compress/compress.go | 15 - .../alg/compress/compress_pure/compress.go | 135 - .../alg/compress/compress_sse41/impl_amd64.s | 560 - .../alg/compress/compress_sse41/impl_other.go | 10 - .../alg/compress/compress_sse41/stubs.go | 7 - .../zeebo/blake3/internal/alg/hash/hash.go | 23 - .../internal/alg/hash/hash_avx2/impl_amd64.s | 2561 --- .../internal/alg/hash/hash_avx2/impl_other.go | 14 - .../internal/alg/hash/hash_avx2/stubs.go | 10 - .../internal/alg/hash/hash_pure/hashf.go | 56 - .../internal/alg/hash/hash_pure/hashp.go | 38 - .../zeebo/blake3/internal/consts/consts.go | 29 - .../zeebo/blake3/internal/consts/cpu.go | 19 - .../blake3/internal/consts/cpu_little.go | 6 - .../zeebo/blake3/internal/consts/cpu_other.go | 6 - .../blake3/internal/consts/cpu_purego.go | 8 - .../zeebo/blake3/internal/utils/utils.go | 60 - vendor/github.com/zitadel/oidc/v3/LICENSE | 201 - vendor/github.com/zitadel/oidc/v3/NOTICE | 1 - .../zitadel/oidc/v3/pkg/crypto/crypto.go | 69 - .../zitadel/oidc/v3/pkg/crypto/hash.go | 49 - .../zitadel/oidc/v3/pkg/crypto/key.go | 45 - .../zitadel/oidc/v3/pkg/crypto/sign.go | 27 - .../zitadel/oidc/v3/pkg/oidc/authorization.go | 121 - .../oidc/v3/pkg/oidc/code_challenge.go | 33 - .../oidc/v3/pkg/oidc/device_authorization.go | 51 - .../zitadel/oidc/v3/pkg/oidc/discovery.go | 169 - .../zitadel/oidc/v3/pkg/oidc/error.go | 256 - .../zitadel/oidc/v3/pkg/oidc/introspection.go | 79 - .../zitadel/oidc/v3/pkg/oidc/jwt_profile.go | 18 - .../zitadel/oidc/v3/pkg/oidc/keyset.go | 109 - .../zitadel/oidc/v3/pkg/oidc/revocation.go | 6 - .../zitadel/oidc/v3/pkg/oidc/session.go | 10 - .../zitadel/oidc/v3/pkg/oidc/token.go | 422 - .../zitadel/oidc/v3/pkg/oidc/token_request.go | 245 - .../zitadel/oidc/v3/pkg/oidc/types.go | 291 - .../zitadel/oidc/v3/pkg/oidc/userinfo.go | 99 - .../zitadel/oidc/v3/pkg/oidc/util.go | 54 - .../zitadel/oidc/v3/pkg/oidc/verifier.go | 250 - .../github.com/zitadel/schema/.releaserc.js | 11 - vendor/github.com/zitadel/schema/LICENSE | 27 - vendor/github.com/zitadel/schema/README.md | 94 - vendor/github.com/zitadel/schema/cache.go | 305 - vendor/github.com/zitadel/schema/converter.go | 145 - vendor/github.com/zitadel/schema/decoder.go | 521 - vendor/github.com/zitadel/schema/doc.go | 148 - vendor/github.com/zitadel/schema/encoder.go | 207 - .../auto/sdk/CONTRIBUTING.md | 27 - vendor/go.opentelemetry.io/auto/sdk/LICENSE | 201 - .../auto/sdk/VERSIONING.md | 15 - vendor/go.opentelemetry.io/auto/sdk/doc.go | 14 - .../auto/sdk/internal/telemetry/attr.go | 58 - .../auto/sdk/internal/telemetry/doc.go | 8 - .../auto/sdk/internal/telemetry/id.go | 103 - .../auto/sdk/internal/telemetry/number.go | 67 - .../auto/sdk/internal/telemetry/resource.go | 66 - .../auto/sdk/internal/telemetry/scope.go | 67 - .../auto/sdk/internal/telemetry/span.go | 456 - .../auto/sdk/internal/telemetry/status.go | 40 - .../auto/sdk/internal/telemetry/traces.go | 189 - .../auto/sdk/internal/telemetry/value.go | 452 - vendor/go.opentelemetry.io/auto/sdk/limit.go | 94 - vendor/go.opentelemetry.io/auto/sdk/span.go | 432 - vendor/go.opentelemetry.io/auto/sdk/tracer.go | 124 - .../auto/sdk/tracer_provider.go | 33 - .../google.golang.org/grpc/otelgrpc/LICENSE | 201 - .../google.golang.org/grpc/otelgrpc/config.go | 305 - .../google.golang.org/grpc/otelgrpc/doc.go | 11 - .../grpc/otelgrpc/filters/filters.go | 128 - .../grpc/otelgrpc/interceptor.go | 530 - .../grpc/otelgrpc/interceptorinfo.go | 39 - .../grpc/otelgrpc/internal/parse.go | 40 - .../grpc/otelgrpc/metadata_supplier.go | 87 - .../grpc/otelgrpc/semconv.go | 41 - .../grpc/otelgrpc/stats_handler.go | 234 - .../grpc/otelgrpc/version.go | 17 - .../instrumentation/net/http/otelhttp/LICENSE | 201 - .../net/http/otelhttp/client.go | 50 - .../net/http/otelhttp/common.go | 27 - .../net/http/otelhttp/config.go | 211 - .../instrumentation/net/http/otelhttp/doc.go | 7 - .../net/http/otelhttp/handler.go | 238 - .../otelhttp/internal/request/body_wrapper.go | 80 - .../net/http/otelhttp/internal/request/gen.go | 10 - .../internal/request/resp_writer_wrapper.go | 122 - .../net/http/otelhttp/internal/semconv/env.go | 323 - .../net/http/otelhttp/internal/semconv/gen.go | 14 - .../otelhttp/internal/semconv/httpconv.go | 573 - .../http/otelhttp/internal/semconv/util.go | 127 - .../http/otelhttp/internal/semconv/v1.20.0.go | 273 - .../http/otelhttp/internal/semconvutil/gen.go | 10 - .../otelhttp/internal/semconvutil/httpconv.go | 594 - .../otelhttp/internal/semconvutil/netconv.go | 214 - .../net/http/otelhttp/labeler.go | 58 - .../net/http/otelhttp/start_time_context.go | 29 - .../net/http/otelhttp/transport.go | 265 - .../net/http/otelhttp/version.go | 10 - .../contrib/propagators/b3/LICENSE | 201 - .../contrib/propagators/b3/b3_config.go | 68 - .../contrib/propagators/b3/b3_propagator.go | 334 - .../contrib/propagators/b3/context.go | 49 - .../contrib/propagators/b3/doc.go | 6 - .../contrib/propagators/b3/version.go | 17 - .../contrib/propagators/ot/LICENSE | 201 - .../contrib/propagators/ot/doc.go | 6 - .../contrib/propagators/ot/ot_propagator.go | 167 - .../contrib/propagators/ot/version.go | 17 - .../go.opentelemetry.io/otel/.clomonitor.yml | 3 - .../go.opentelemetry.io/otel/.codespellignore | 10 - vendor/go.opentelemetry.io/otel/.codespellrc | 10 - .../go.opentelemetry.io/otel/.gitattributes | 3 - vendor/go.opentelemetry.io/otel/.gitignore | 15 - vendor/go.opentelemetry.io/otel/.golangci.yml | 260 - vendor/go.opentelemetry.io/otel/.lycheeignore | 9 - .../otel/.markdownlint.yaml | 29 - vendor/go.opentelemetry.io/otel/CHANGELOG.md | 3543 ---- vendor/go.opentelemetry.io/otel/CODEOWNERS | 17 - .../go.opentelemetry.io/otel/CONTRIBUTING.md | 723 - vendor/go.opentelemetry.io/otel/Makefile | 326 - vendor/go.opentelemetry.io/otel/README.md | 122 - vendor/go.opentelemetry.io/otel/RELEASING.md | 173 - .../otel/SECURITY-INSIGHTS.yml | 203 - vendor/go.opentelemetry.io/otel/VERSIONING.md | 224 - .../otel/baggage/README.md | 3 - .../otel/baggage/baggage.go | 1018 -- .../otel/baggage/context.go | 28 - .../go.opentelemetry.io/otel/baggage/doc.go | 9 - .../go.opentelemetry.io/otel/codes/README.md | 3 - .../go.opentelemetry.io/otel/codes/codes.go | 106 - vendor/go.opentelemetry.io/otel/codes/doc.go | 10 - .../otel/dependencies.Dockerfile | 4 - vendor/go.opentelemetry.io/otel/doc.go | 25 - .../go.opentelemetry.io/otel/error_handler.go | 27 - .../otlp/otlpmetric/otlpmetricgrpc/LICENSE | 201 - .../otlp/otlpmetric/otlpmetricgrpc/README.md | 3 - .../otlp/otlpmetric/otlpmetricgrpc/client.go | 205 - .../otlp/otlpmetric/otlpmetricgrpc/config.go | 266 - .../otlp/otlpmetric/otlpmetricgrpc/doc.go | 84 - .../otlpmetric/otlpmetricgrpc/exporter.go | 157 - .../internal/envconfig/envconfig.go | 215 - .../otlpmetric/otlpmetricgrpc/internal/gen.go | 31 - .../internal/oconf/envconfig.go | 210 - .../otlpmetricgrpc/internal/oconf/options.go | 374 - .../internal/oconf/optiontypes.go | 47 - .../otlpmetricgrpc/internal/oconf/tls.go | 38 - .../otlpmetricgrpc/internal/partialsuccess.go | 56 - .../otlpmetricgrpc/internal/retry/retry.go | 145 - .../internal/transform/attribute.go | 144 - .../internal/transform/error.go | 103 - .../internal/transform/metricdata.go | 350 - .../otlp/otlpmetric/otlpmetricgrpc/version.go | 9 - .../otel/exporters/otlp/otlptrace/LICENSE | 201 - .../otel/exporters/otlp/otlptrace/README.md | 3 - .../otel/exporters/otlp/otlptrace/clients.go | 43 - .../otel/exporters/otlp/otlptrace/doc.go | 10 - .../otel/exporters/otlp/otlptrace/exporter.go | 105 - .../internal/tracetransform/attribute.go | 149 - .../tracetransform/instrumentation.go | 20 - .../internal/tracetransform/resource.go | 17 - .../otlptrace/internal/tracetransform/span.go | 219 - .../otlp/otlptrace/otlptracegrpc/LICENSE | 201 - .../otlp/otlptrace/otlptracegrpc/README.md | 3 - .../otlp/otlptrace/otlptracegrpc/client.go | 300 - .../otlp/otlptrace/otlptracegrpc/doc.go | 65 - .../otlp/otlptrace/otlptracegrpc/exporter.go | 20 - .../internal/envconfig/envconfig.go | 217 - .../otlptrace/otlptracegrpc/internal/gen.go | 25 - .../internal/otlpconfig/envconfig.go | 150 - .../internal/otlpconfig/options.go | 361 - .../internal/otlpconfig/optiontypes.go | 40 - .../otlptracegrpc/internal/otlpconfig/tls.go | 26 - .../otlptracegrpc/internal/partialsuccess.go | 56 - .../otlptracegrpc/internal/retry/retry.go | 141 - .../otlp/otlptrace/otlptracegrpc/options.go | 211 - .../otel/exporters/otlp/otlptrace/version.go | 9 - vendor/go.opentelemetry.io/otel/handler.go | 33 - .../otel/internal/baggage/baggage.go | 32 - .../otel/internal/baggage/context.go | 81 - .../otel/internal/global/handler.go | 37 - .../otel/internal/global/instruments.go | 412 - .../otel/internal/global/internal_logging.go | 62 - .../otel/internal/global/meter.go | 625 - .../otel/internal/global/propagator.go | 71 - .../otel/internal/global/state.go | 199 - .../otel/internal/global/trace.go | 232 - .../otel/internal_logging.go | 15 - vendor/go.opentelemetry.io/otel/metric.go | 42 - .../go.opentelemetry.io/otel/metric/LICENSE | 231 - .../go.opentelemetry.io/otel/metric/README.md | 3 - .../otel/metric/asyncfloat64.go | 266 - .../otel/metric/asyncint64.go | 262 - .../go.opentelemetry.io/otel/metric/config.go | 81 - vendor/go.opentelemetry.io/otel/metric/doc.go | 177 - .../otel/metric/embedded/README.md | 3 - .../otel/metric/embedded/embedded.go | 243 - .../otel/metric/instrument.go | 376 - .../go.opentelemetry.io/otel/metric/meter.go | 284 - .../otel/metric/noop/README.md | 3 - .../otel/metric/noop/noop.go | 296 - .../otel/metric/syncfloat64.go | 226 - .../otel/metric/syncint64.go | 226 - .../go.opentelemetry.io/otel/propagation.go | 20 - .../otel/propagation/README.md | 3 - .../otel/propagation/baggage.go | 77 - .../otel/propagation/doc.go | 13 - .../otel/propagation/propagation.go | 168 - .../otel/propagation/trace_context.go | 156 - vendor/go.opentelemetry.io/otel/renovate.json | 35 - .../go.opentelemetry.io/otel/requirements.txt | 1 - vendor/go.opentelemetry.io/otel/sdk/LICENSE | 231 - vendor/go.opentelemetry.io/otel/sdk/README.md | 3 - .../otel/sdk/instrumentation/README.md | 3 - .../otel/sdk/instrumentation/doc.go | 13 - .../otel/sdk/instrumentation/library.go | 9 - .../otel/sdk/instrumentation/scope.go | 19 - .../otel/sdk/internal/env/env.go | 168 - .../otel/sdk/internal/x/README.md | 46 - .../otel/sdk/internal/x/x.go | 66 - .../otel/sdk/metric/LICENSE | 231 - .../otel/sdk/metric/README.md | 3 - .../otel/sdk/metric/aggregation.go | 189 - .../otel/sdk/metric/cache.go | 83 - .../otel/sdk/metric/config.go | 206 - .../otel/sdk/metric/doc.go | 71 - .../otel/sdk/metric/env.go | 39 - .../otel/sdk/metric/exemplar.go | 77 - .../otel/sdk/metric/exemplar/README.md | 3 - .../otel/sdk/metric/exemplar/doc.go | 6 - .../otel/sdk/metric/exemplar/exemplar.go | 29 - .../otel/sdk/metric/exemplar/filter.go | 34 - .../metric/exemplar/fixed_size_reservoir.go | 197 - .../metric/exemplar/histogram_reservoir.go | 70 - .../otel/sdk/metric/exemplar/reservoir.go | 40 - .../otel/sdk/metric/exemplar/storage.go | 95 - .../otel/sdk/metric/exemplar/value.go | 59 - .../otel/sdk/metric/exporter.go | 77 - .../otel/sdk/metric/instrument.go | 368 - .../otel/sdk/metric/instrumentkind_string.go | 30 - .../metric/internal/aggregate/aggregate.go | 159 - .../otel/sdk/metric/internal/aggregate/doc.go | 7 - .../sdk/metric/internal/aggregate/drop.go | 27 - .../sdk/metric/internal/aggregate/exemplar.go | 43 - .../aggregate/exponential_histogram.go | 478 - .../internal/aggregate/filtered_reservoir.go | 53 - .../metric/internal/aggregate/histogram.go | 251 - .../metric/internal/aggregate/lastvalue.go | 172 - .../sdk/metric/internal/aggregate/limit.go | 42 - .../otel/sdk/metric/internal/aggregate/sum.go | 249 - .../otel/sdk/metric/internal/reuse_slice.go | 14 - .../otel/sdk/metric/internal/x/README.md | 100 - .../otel/sdk/metric/internal/x/x.go | 65 - .../otel/sdk/metric/manual_reader.go | 204 - .../otel/sdk/metric/meter.go | 773 - .../otel/sdk/metric/metricdata/README.md | 3 - .../otel/sdk/metric/metricdata/data.go | 297 - .../otel/sdk/metric/metricdata/temporality.go | 30 - .../metric/metricdata/temporality_string.go | 25 - .../otel/sdk/metric/periodic_reader.go | 371 - .../otel/sdk/metric/pipeline.go | 678 - .../otel/sdk/metric/provider.go | 145 - .../otel/sdk/metric/reader.go | 192 - .../otel/sdk/metric/version.go | 9 - .../otel/sdk/metric/view.go | 118 - .../otel/sdk/resource/README.md | 3 - .../otel/sdk/resource/auto.go | 92 - .../otel/sdk/resource/builtin.go | 116 - .../otel/sdk/resource/config.go | 195 - .../otel/sdk/resource/container.go | 89 - .../otel/sdk/resource/doc.go | 20 - .../otel/sdk/resource/env.go | 95 - .../otel/sdk/resource/host_id.go | 109 - .../otel/sdk/resource/host_id_bsd.go | 12 - .../otel/sdk/resource/host_id_darwin.go | 8 - .../otel/sdk/resource/host_id_exec.go | 18 - .../otel/sdk/resource/host_id_linux.go | 11 - .../otel/sdk/resource/host_id_readfile.go | 17 - .../otel/sdk/resource/host_id_unsupported.go | 19 - .../otel/sdk/resource/host_id_windows.go | 36 - .../otel/sdk/resource/os.go | 89 - .../otel/sdk/resource/os_release_darwin.go | 92 - .../otel/sdk/resource/os_release_unix.go | 143 - .../otel/sdk/resource/os_unix.go | 79 - .../otel/sdk/resource/os_unsupported.go | 15 - .../otel/sdk/resource/os_windows.go | 89 - .../otel/sdk/resource/process.go | 173 - .../otel/sdk/resource/resource.go | 309 - .../otel/sdk/trace/README.md | 3 - .../otel/sdk/trace/batch_span_processor.go | 514 - .../go.opentelemetry.io/otel/sdk/trace/doc.go | 13 - .../otel/sdk/trace/event.go | 26 - .../otel/sdk/trace/evictedqueue.go | 64 - .../otel/sdk/trace/id_generator.go | 69 - .../otel/sdk/trace/internal/x/README.md | 35 - .../otel/sdk/trace/internal/x/x.go | 63 - .../otel/sdk/trace/link.go | 23 - .../otel/sdk/trace/provider.go | 538 - .../otel/sdk/trace/sampler_env.go | 96 - .../otel/sdk/trace/sampling.go | 282 - .../otel/sdk/trace/simple_span_processor.go | 121 - .../otel/sdk/trace/snapshot.go | 133 - .../otel/sdk/trace/span.go | 948 - .../otel/sdk/trace/span_exporter.go | 36 - .../otel/sdk/trace/span_limits.go | 114 - .../otel/sdk/trace/span_processor.go | 61 - .../otel/sdk/trace/tracer.go | 294 - .../go.opentelemetry.io/otel/sdk/version.go | 10 - .../otel/semconv/v1.17.0/README.md | 3 - .../otel/semconv/v1.17.0/doc.go | 9 - .../otel/semconv/v1.17.0/event.go | 188 - .../otel/semconv/v1.17.0/exception.go | 9 - .../otel/semconv/v1.17.0/http.go | 10 - .../otel/semconv/v1.17.0/resource.go | 1999 -- .../otel/semconv/v1.17.0/schema.go | 9 - .../otel/semconv/v1.17.0/trace.go | 3364 ---- .../otel/semconv/v1.20.0/README.md | 3 - .../otel/semconv/v1.20.0/attribute_group.go | 1198 -- .../otel/semconv/v1.20.0/doc.go | 9 - .../otel/semconv/v1.20.0/event.go | 188 - .../otel/semconv/v1.20.0/exception.go | 9 - .../otel/semconv/v1.20.0/http.go | 10 - .../otel/semconv/v1.20.0/resource.go | 2060 --- .../otel/semconv/v1.20.0/schema.go | 9 - .../otel/semconv/v1.20.0/trace.go | 2599 --- .../otel/semconv/v1.21.0/README.md | 3 - .../otel/semconv/v1.21.0/attribute_group.go | 1866 -- .../otel/semconv/v1.21.0/doc.go | 9 - .../otel/semconv/v1.21.0/event.go | 188 - .../otel/semconv/v1.21.0/exception.go | 9 - .../otel/semconv/v1.21.0/resource.go | 2299 --- .../otel/semconv/v1.21.0/schema.go | 9 - .../otel/semconv/v1.21.0/trace.go | 2484 --- .../otel/semconv/v1.26.0/README.md | 3 - .../otel/semconv/v1.26.0/attribute_group.go | 8996 --------- .../otel/semconv/v1.26.0/doc.go | 9 - .../otel/semconv/v1.26.0/exception.go | 9 - .../otel/semconv/v1.26.0/metric.go | 1307 -- .../otel/semconv/v1.26.0/schema.go | 9 - .../otel/semconv/v1.37.0/MIGRATION.md | 41 - .../otel/semconv/v1.37.0/README.md | 3 - .../otel/semconv/v1.37.0/attribute_group.go | 15193 ---------------- .../otel/semconv/v1.37.0/doc.go | 9 - .../otel/semconv/v1.37.0/error_type.go | 31 - .../otel/semconv/v1.37.0/exception.go | 9 - .../otel/semconv/v1.37.0/otelconv/metric.go | 2126 --- .../otel/semconv/v1.37.0/schema.go | 9 - vendor/go.opentelemetry.io/otel/trace.go | 36 - vendor/go.opentelemetry.io/otel/trace/LICENSE | 231 - .../go.opentelemetry.io/otel/trace/README.md | 3 - vendor/go.opentelemetry.io/otel/trace/auto.go | 662 - .../go.opentelemetry.io/otel/trace/config.go | 323 - .../go.opentelemetry.io/otel/trace/context.go | 50 - vendor/go.opentelemetry.io/otel/trace/doc.go | 119 - .../otel/trace/embedded/README.md | 3 - .../otel/trace/embedded/embedded.go | 45 - vendor/go.opentelemetry.io/otel/trace/hex.go | 38 - .../otel/trace/internal/telemetry/attr.go | 58 - .../otel/trace/internal/telemetry/doc.go | 8 - .../otel/trace/internal/telemetry/id.go | 103 - .../otel/trace/internal/telemetry/number.go | 67 - .../otel/trace/internal/telemetry/resource.go | 66 - .../otel/trace/internal/telemetry/scope.go | 67 - .../otel/trace/internal/telemetry/span.go | 472 - .../otel/trace/internal/telemetry/status.go | 42 - .../otel/trace/internal/telemetry/traces.go | 189 - .../otel/trace/internal/telemetry/value.go | 453 - .../otel/trace/nonrecording.go | 16 - vendor/go.opentelemetry.io/otel/trace/noop.go | 105 - .../otel/trace/noop/README.md | 3 - .../otel/trace/noop/noop.go | 112 - .../otel/trace/provider.go | 59 - vendor/go.opentelemetry.io/otel/trace/span.go | 177 - .../go.opentelemetry.io/otel/trace/trace.go | 365 - .../go.opentelemetry.io/otel/trace/tracer.go | 37 - .../otel/trace/tracestate.go | 330 - .../otel/verify_released_changelog.sh | 42 - vendor/go.opentelemetry.io/otel/version.go | 9 - vendor/go.opentelemetry.io/otel/versions.yaml | 44 - .../metrics/v1/metrics_service.pb.go | 371 - .../metrics/v1/metrics_service.pb.gw.go | 171 - .../metrics/v1/metrics_service_grpc.pb.go | 105 - .../collector/profiles/v1development/LICENSE | 201 - .../v1development/profiles_service.pb.go | 396 - .../v1development/profiles_service.pb.gw.go | 171 - .../v1development/profiles_service_grpc.pb.go | 105 - .../collector/trace/v1/trace_service.pb.go | 367 - .../collector/trace/v1/trace_service.pb.gw.go | 171 - .../trace/v1/trace_service_grpc.pb.go | 105 - .../proto/otlp/metrics/v1/metrics.pb.go | 2583 --- .../proto/otlp/profiles/v1development/LICENSE | 201 - .../profiles/v1development/profiles.pb.go | 1848 -- .../proto/otlp/trace/v1/trace.pb.go | 1311 -- vendor/go.uber.org/atomic/.codecov.yml | 19 - vendor/go.uber.org/atomic/.gitignore | 15 - vendor/go.uber.org/atomic/CHANGELOG.md | 127 - vendor/go.uber.org/atomic/LICENSE.txt | 19 - vendor/go.uber.org/atomic/Makefile | 79 - vendor/go.uber.org/atomic/README.md | 63 - vendor/go.uber.org/atomic/bool.go | 88 - vendor/go.uber.org/atomic/bool_ext.go | 53 - vendor/go.uber.org/atomic/doc.go | 23 - vendor/go.uber.org/atomic/duration.go | 89 - vendor/go.uber.org/atomic/duration_ext.go | 40 - vendor/go.uber.org/atomic/error.go | 72 - vendor/go.uber.org/atomic/error_ext.go | 39 - vendor/go.uber.org/atomic/float32.go | 77 - vendor/go.uber.org/atomic/float32_ext.go | 76 - vendor/go.uber.org/atomic/float64.go | 77 - vendor/go.uber.org/atomic/float64_ext.go | 76 - vendor/go.uber.org/atomic/gen.go | 27 - vendor/go.uber.org/atomic/int32.go | 109 - vendor/go.uber.org/atomic/int64.go | 109 - vendor/go.uber.org/atomic/nocmp.go | 35 - vendor/go.uber.org/atomic/pointer_go118.go | 31 - .../atomic/pointer_go118_pre119.go | 60 - vendor/go.uber.org/atomic/pointer_go119.go | 61 - vendor/go.uber.org/atomic/string.go | 72 - vendor/go.uber.org/atomic/string_ext.go | 54 - vendor/go.uber.org/atomic/time.go | 55 - vendor/go.uber.org/atomic/time_ext.go | 36 - vendor/go.uber.org/atomic/uint32.go | 109 - vendor/go.uber.org/atomic/uint64.go | 109 - vendor/go.uber.org/atomic/uintptr.go | 109 - vendor/go.uber.org/atomic/unsafe_pointer.go | 65 - vendor/go.uber.org/atomic/value.go | 31 - vendor/go.uber.org/multierr/.codecov.yml | 15 - vendor/go.uber.org/multierr/.gitignore | 4 - vendor/go.uber.org/multierr/CHANGELOG.md | 95 - vendor/go.uber.org/multierr/LICENSE.txt | 19 - vendor/go.uber.org/multierr/Makefile | 38 - vendor/go.uber.org/multierr/README.md | 43 - vendor/go.uber.org/multierr/error.go | 646 - .../go.uber.org/multierr/error_post_go120.go | 48 - .../go.uber.org/multierr/error_pre_go120.go | 79 - vendor/golang.org/x/crypto/LICENSE | 27 - vendor/golang.org/x/crypto/PATENTS | 22 - vendor/golang.org/x/crypto/argon2/argon2.go | 283 - vendor/golang.org/x/crypto/argon2/blake2b.go | 53 - .../x/crypto/argon2/blamka_amd64.go | 60 - .../golang.org/x/crypto/argon2/blamka_amd64.s | 2791 --- .../x/crypto/argon2/blamka_generic.go | 163 - .../golang.org/x/crypto/argon2/blamka_ref.go | 15 - vendor/golang.org/x/crypto/blake2b/blake2b.go | 291 - .../x/crypto/blake2b/blake2bAVX2_amd64.go | 37 - .../x/crypto/blake2b/blake2bAVX2_amd64.s | 4559 ----- .../x/crypto/blake2b/blake2b_amd64.s | 1441 -- .../x/crypto/blake2b/blake2b_generic.go | 182 - .../x/crypto/blake2b/blake2b_ref.go | 11 - vendor/golang.org/x/crypto/blake2b/blake2x.go | 185 - vendor/golang.org/x/crypto/blake2b/go125.go | 11 - .../golang.org/x/crypto/blake2b/register.go | 30 - vendor/golang.org/x/crypto/blowfish/block.go | 159 - vendor/golang.org/x/crypto/blowfish/cipher.go | 99 - vendor/golang.org/x/crypto/blowfish/const.go | 199 - vendor/golang.org/x/crypto/cast5/cast5.go | 536 - .../x/crypto/chacha20/chacha_arm64.go | 16 - .../x/crypto/chacha20/chacha_arm64.s | 307 - .../x/crypto/chacha20/chacha_generic.go | 398 - .../x/crypto/chacha20/chacha_noasm.go | 13 - .../x/crypto/chacha20/chacha_ppc64x.go | 16 - .../x/crypto/chacha20/chacha_ppc64x.s | 501 - .../x/crypto/chacha20/chacha_s390x.go | 27 - .../x/crypto/chacha20/chacha_s390x.s | 224 - vendor/golang.org/x/crypto/chacha20/xor.go | 42 - vendor/golang.org/x/crypto/cryptobyte/asn1.go | 825 - .../x/crypto/cryptobyte/asn1/asn1.go | 46 - .../golang.org/x/crypto/cryptobyte/builder.go | 350 - .../golang.org/x/crypto/cryptobyte/string.go | 183 - .../x/crypto/curve25519/curve25519.go | 90 - vendor/golang.org/x/crypto/hkdf/hkdf.go | 95 - .../x/crypto/internal/alias/alias.go | 31 - .../x/crypto/internal/alias/alias_purego.go | 34 - .../x/crypto/internal/poly1305/mac_noasm.go | 9 - .../x/crypto/internal/poly1305/poly1305.go | 99 - .../x/crypto/internal/poly1305/sum_amd64.s | 93 - .../x/crypto/internal/poly1305/sum_asm.go | 47 - .../x/crypto/internal/poly1305/sum_generic.go | 312 - .../x/crypto/internal/poly1305/sum_loong64.s | 123 - .../x/crypto/internal/poly1305/sum_ppc64x.s | 187 - .../x/crypto/internal/poly1305/sum_s390x.go | 76 - .../x/crypto/internal/poly1305/sum_s390x.s | 503 - vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go | 77 - vendor/golang.org/x/crypto/sha3/doc.go | 66 - vendor/golang.org/x/crypto/sha3/hashes.go | 128 - .../golang.org/x/crypto/sha3/hashes_noasm.go | 23 - vendor/golang.org/x/crypto/sha3/keccakf.go | 414 - .../golang.org/x/crypto/sha3/keccakf_amd64.go | 13 - .../golang.org/x/crypto/sha3/keccakf_amd64.s | 5419 ------ vendor/golang.org/x/crypto/sha3/sha3.go | 244 - vendor/golang.org/x/crypto/sha3/sha3_s390x.go | 303 - vendor/golang.org/x/crypto/sha3/sha3_s390x.s | 33 - vendor/golang.org/x/crypto/sha3/shake.go | 193 - .../golang.org/x/crypto/sha3/shake_noasm.go | 15 - .../golang.org/x/crypto/ssh/agent/client.go | 854 - .../golang.org/x/crypto/ssh/agent/forward.go | 103 - .../golang.org/x/crypto/ssh/agent/keyring.go | 250 - .../golang.org/x/crypto/ssh/agent/server.go | 570 - vendor/golang.org/x/crypto/ssh/buffer.go | 97 - vendor/golang.org/x/crypto/ssh/certs.go | 624 - vendor/golang.org/x/crypto/ssh/channel.go | 645 - vendor/golang.org/x/crypto/ssh/cipher.go | 787 - vendor/golang.org/x/crypto/ssh/client.go | 283 - vendor/golang.org/x/crypto/ssh/client_auth.go | 796 - vendor/golang.org/x/crypto/ssh/common.go | 676 - vendor/golang.org/x/crypto/ssh/connection.go | 155 - vendor/golang.org/x/crypto/ssh/doc.go | 24 - vendor/golang.org/x/crypto/ssh/handshake.go | 846 - .../ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go | 93 - vendor/golang.org/x/crypto/ssh/kex.go | 793 - vendor/golang.org/x/crypto/ssh/keys.go | 1783 -- .../x/crypto/ssh/knownhosts/knownhosts.go | 526 - vendor/golang.org/x/crypto/ssh/mac.go | 68 - vendor/golang.org/x/crypto/ssh/messages.go | 893 - vendor/golang.org/x/crypto/ssh/mlkem.go | 183 - vendor/golang.org/x/crypto/ssh/mux.go | 357 - vendor/golang.org/x/crypto/ssh/server.go | 927 - vendor/golang.org/x/crypto/ssh/session.go | 647 - vendor/golang.org/x/crypto/ssh/ssh_gss.go | 139 - vendor/golang.org/x/crypto/ssh/streamlocal.go | 116 - vendor/golang.org/x/crypto/ssh/tcpip.go | 509 - vendor/golang.org/x/crypto/ssh/transport.go | 373 - vendor/golang.org/x/exp/rand/exp.go | 221 - vendor/golang.org/x/exp/rand/normal.go | 156 - vendor/golang.org/x/exp/rand/rand.go | 366 - vendor/golang.org/x/exp/rand/rng.go | 91 - vendor/golang.org/x/exp/rand/zipf.go | 77 - vendor/golang.org/x/net/html/atom/atom.go | 78 - vendor/golang.org/x/net/html/atom/table.go | 785 - vendor/golang.org/x/net/html/const.go | 111 - vendor/golang.org/x/net/html/doc.go | 122 - vendor/golang.org/x/net/html/doctype.go | 156 - vendor/golang.org/x/net/html/entity.go | 2253 --- vendor/golang.org/x/net/html/escape.go | 339 - vendor/golang.org/x/net/html/foreign.go | 221 - vendor/golang.org/x/net/html/iter.go | 56 - vendor/golang.org/x/net/html/node.go | 229 - vendor/golang.org/x/net/html/parse.go | 2464 --- vendor/golang.org/x/net/html/render.go | 293 - vendor/golang.org/x/net/html/token.go | 1286 -- .../golang.org/x/net/http/httpproxy/proxy.go | 373 - vendor/golang.org/x/net/http2/h2c/h2c.go | 234 - .../golang.org/x/net/internal/socks/client.go | 168 - .../golang.org/x/net/internal/socks/socks.go | 317 - vendor/golang.org/x/net/proxy/dial.go | 54 - vendor/golang.org/x/net/proxy/direct.go | 31 - vendor/golang.org/x/net/proxy/per_host.go | 153 - vendor/golang.org/x/net/proxy/proxy.go | 149 - vendor/golang.org/x/net/proxy/socks5.go | 42 - vendor/golang.org/x/oauth2/.travis.yml | 13 - vendor/golang.org/x/oauth2/CONTRIBUTING.md | 26 - vendor/golang.org/x/oauth2/LICENSE | 27 - vendor/golang.org/x/oauth2/README.md | 35 - .../clientcredentials/clientcredentials.go | 124 - vendor/golang.org/x/oauth2/deviceauth.go | 198 - vendor/golang.org/x/oauth2/internal/doc.go | 6 - vendor/golang.org/x/oauth2/internal/oauth2.go | 37 - vendor/golang.org/x/oauth2/internal/token.go | 356 - .../golang.org/x/oauth2/internal/transport.go | 28 - vendor/golang.org/x/oauth2/oauth2.go | 424 - vendor/golang.org/x/oauth2/pkce.go | 69 - vendor/golang.org/x/oauth2/token.go | 213 - vendor/golang.org/x/oauth2/transport.go | 75 - vendor/golang.org/x/sync/LICENSE | 27 - vendor/golang.org/x/sync/PATENTS | 22 - vendor/golang.org/x/sync/errgroup/errgroup.go | 151 - .../x/sync/singleflight/singleflight.go | 214 - vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s | 17 - .../golang.org/x/sys/cpu/asm_darwin_x86_gc.s | 17 - vendor/golang.org/x/sys/cpu/byteorder.go | 66 - vendor/golang.org/x/sys/cpu/cpu.go | 338 - vendor/golang.org/x/sys/cpu/cpu_aix.go | 33 - vendor/golang.org/x/sys/cpu/cpu_arm.go | 73 - vendor/golang.org/x/sys/cpu/cpu_arm64.go | 194 - vendor/golang.org/x/sys/cpu/cpu_arm64.s | 39 - vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go | 61 - vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go | 12 - vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go | 21 - vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 15 - vendor/golang.org/x/sys/cpu/cpu_gc_x86.s | 26 - .../golang.org/x/sys/cpu/cpu_gccgo_arm64.go | 11 - .../golang.org/x/sys/cpu/cpu_gccgo_s390x.go | 22 - vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c | 37 - vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go | 25 - vendor/golang.org/x/sys/cpu/cpu_linux.go | 15 - vendor/golang.org/x/sys/cpu/cpu_linux_arm.go | 39 - .../golang.org/x/sys/cpu/cpu_linux_arm64.go | 120 - .../golang.org/x/sys/cpu/cpu_linux_loong64.go | 22 - .../golang.org/x/sys/cpu/cpu_linux_mips64x.go | 22 - .../golang.org/x/sys/cpu/cpu_linux_noinit.go | 9 - .../golang.org/x/sys/cpu/cpu_linux_ppc64x.go | 30 - .../golang.org/x/sys/cpu/cpu_linux_riscv64.go | 160 - .../golang.org/x/sys/cpu/cpu_linux_s390x.go | 40 - vendor/golang.org/x/sys/cpu/cpu_loong64.go | 50 - vendor/golang.org/x/sys/cpu/cpu_loong64.s | 13 - vendor/golang.org/x/sys/cpu/cpu_mips64x.go | 15 - vendor/golang.org/x/sys/cpu/cpu_mipsx.go | 11 - .../golang.org/x/sys/cpu/cpu_netbsd_arm64.go | 173 - .../golang.org/x/sys/cpu/cpu_openbsd_arm64.go | 65 - .../golang.org/x/sys/cpu/cpu_openbsd_arm64.s | 11 - vendor/golang.org/x/sys/cpu/cpu_other_arm.go | 9 - .../golang.org/x/sys/cpu/cpu_other_arm64.go | 9 - .../golang.org/x/sys/cpu/cpu_other_mips64x.go | 11 - .../golang.org/x/sys/cpu/cpu_other_ppc64x.go | 12 - .../golang.org/x/sys/cpu/cpu_other_riscv64.go | 11 - vendor/golang.org/x/sys/cpu/cpu_other_x86.go | 11 - vendor/golang.org/x/sys/cpu/cpu_ppc64x.go | 16 - vendor/golang.org/x/sys/cpu/cpu_riscv64.go | 32 - vendor/golang.org/x/sys/cpu/cpu_s390x.go | 172 - vendor/golang.org/x/sys/cpu/cpu_s390x.s | 57 - vendor/golang.org/x/sys/cpu/cpu_wasm.go | 17 - vendor/golang.org/x/sys/cpu/cpu_x86.go | 162 - vendor/golang.org/x/sys/cpu/cpu_zos.go | 10 - vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go | 25 - vendor/golang.org/x/sys/cpu/endian_big.go | 10 - vendor/golang.org/x/sys/cpu/endian_little.go | 10 - vendor/golang.org/x/sys/cpu/hwcap_linux.go | 71 - vendor/golang.org/x/sys/cpu/parse.go | 43 - .../x/sys/cpu/proc_cpuinfo_linux.go | 53 - vendor/golang.org/x/sys/cpu/runtime_auxv.go | 16 - .../x/sys/cpu/runtime_auxv_go121.go | 18 - .../golang.org/x/sys/cpu/syscall_aix_gccgo.go | 26 - .../x/sys/cpu/syscall_aix_ppc64_gc.go | 35 - .../x/sys/cpu/syscall_darwin_x86_gc.go | 98 - vendor/golang.org/x/sys/execabs/execabs.go | 102 - .../golang.org/x/sys/execabs/execabs_go118.go | 17 - .../golang.org/x/sys/execabs/execabs_go119.go | 20 - .../golang.org/x/sys/windows/registry/key.go | 214 - .../x/sys/windows/registry/mksyscall.go | 9 - .../x/sys/windows/registry/syscall.go | 32 - .../x/sys/windows/registry/value.go | 390 - .../sys/windows/registry/zsyscall_windows.go | 117 - .../x/sys/windows/svc/eventlog/install.go | 80 - .../x/sys/windows/svc/eventlog/log.go | 81 - .../x/sys/windows/svc/mgr/config.go | 204 - .../golang.org/x/sys/windows/svc/mgr/mgr.go | 241 - .../x/sys/windows/svc/mgr/recovery.go | 172 - .../x/sys/windows/svc/mgr/service.go | 128 - .../golang.org/x/sys/windows/svc/security.go | 100 - .../golang.org/x/sys/windows/svc/service.go | 321 - vendor/golang.org/x/text/cases/cases.go | 162 - vendor/golang.org/x/text/cases/context.go | 376 - vendor/golang.org/x/text/cases/fold.go | 34 - vendor/golang.org/x/text/cases/icu.go | 61 - vendor/golang.org/x/text/cases/info.go | 82 - vendor/golang.org/x/text/cases/map.go | 816 - .../golang.org/x/text/cases/tables10.0.0.go | 2255 --- .../golang.org/x/text/cases/tables11.0.0.go | 2316 --- .../golang.org/x/text/cases/tables12.0.0.go | 2359 --- .../golang.org/x/text/cases/tables13.0.0.go | 2399 --- .../golang.org/x/text/cases/tables15.0.0.go | 2527 --- vendor/golang.org/x/text/cases/tables9.0.0.go | 2215 --- vendor/golang.org/x/text/cases/trieval.go | 217 - vendor/golang.org/x/text/internal/internal.go | 49 - .../x/text/internal/language/common.go | 16 - .../x/text/internal/language/compact.go | 29 - .../text/internal/language/compact/compact.go | 61 - .../internal/language/compact/language.go | 260 - .../text/internal/language/compact/parents.go | 120 - .../text/internal/language/compact/tables.go | 1015 -- .../x/text/internal/language/compact/tags.go | 91 - .../x/text/internal/language/compose.go | 167 - .../x/text/internal/language/coverage.go | 28 - .../x/text/internal/language/language.go | 627 - .../x/text/internal/language/lookup.go | 412 - .../x/text/internal/language/match.go | 226 - .../x/text/internal/language/parse.go | 608 - .../x/text/internal/language/tables.go | 3494 ---- .../x/text/internal/language/tags.go | 48 - vendor/golang.org/x/text/internal/match.go | 67 - vendor/golang.org/x/text/internal/tag/tag.go | 100 - vendor/golang.org/x/text/language/coverage.go | 187 - vendor/golang.org/x/text/language/doc.go | 98 - vendor/golang.org/x/text/language/language.go | 605 - vendor/golang.org/x/text/language/match.go | 735 - vendor/golang.org/x/text/language/parse.go | 256 - vendor/golang.org/x/text/language/tables.go | 298 - vendor/golang.org/x/text/language/tags.go | 145 - vendor/gonum.org/v1/gonum/AUTHORS | 141 - vendor/gonum.org/v1/gonum/CONTRIBUTORS | 144 - vendor/gonum.org/v1/gonum/LICENSE | 23 - vendor/gonum.org/v1/gonum/blas/README.md | 51 - vendor/gonum.org/v1/gonum/blas/blas.go | 283 - .../gonum.org/v1/gonum/blas/blas64/blas64.go | 533 - vendor/gonum.org/v1/gonum/blas/blas64/conv.go | 263 - .../v1/gonum/blas/blas64/conv_symmetric.go | 153 - vendor/gonum.org/v1/gonum/blas/blas64/doc.go | 6 - .../v1/gonum/blas/cblas128/cblas128.go | 600 - .../gonum.org/v1/gonum/blas/cblas128/conv.go | 265 - .../v1/gonum/blas/cblas128/conv_hermitian.go | 155 - .../v1/gonum/blas/cblas128/conv_symmetric.go | 155 - .../gonum.org/v1/gonum/blas/cblas128/doc.go | 6 - .../gonum.org/v1/gonum/blas/conversions.bash | 159 - vendor/gonum.org/v1/gonum/blas/doc.go | 108 - vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go | 297 - vendor/gonum.org/v1/gonum/blas/gonum/doc.go | 99 - .../gonum.org/v1/gonum/blas/gonum/errors.go | 35 - vendor/gonum.org/v1/gonum/blas/gonum/gonum.go | 38 - .../v1/gonum/blas/gonum/level1cmplx128.go | 454 - .../v1/gonum/blas/gonum/level1cmplx64.go | 476 - .../v1/gonum/blas/gonum/level1float32.go | 653 - .../gonum/blas/gonum/level1float32_dsdot.go | 54 - .../v1/gonum/blas/gonum/level1float32_sdot.go | 54 - .../gonum/blas/gonum/level1float32_sdsdot.go | 54 - .../v1/gonum/blas/gonum/level1float64.go | 629 - .../v1/gonum/blas/gonum/level1float64_ddot.go | 50 - .../v1/gonum/blas/gonum/level2cmplx128.go | 2940 --- .../v1/gonum/blas/gonum/level2cmplx64.go | 2976 --- .../v1/gonum/blas/gonum/level2float32.go | 2400 --- .../v1/gonum/blas/gonum/level2float64.go | 2366 --- .../v1/gonum/blas/gonum/level3cmplx128.go | 1751 -- .../v1/gonum/blas/gonum/level3cmplx64.go | 1771 -- .../v1/gonum/blas/gonum/level3float32.go | 925 - .../v1/gonum/blas/gonum/level3float64.go | 913 - vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go | 301 - .../v1/gonum/blas/gonum/single_precision.bash | 224 - vendor/gonum.org/v1/gonum/floats/README.md | 7 - vendor/gonum.org/v1/gonum/floats/doc.go | 11 - vendor/gonum.org/v1/gonum/floats/floats.go | 808 - .../gonum.org/v1/gonum/floats/scalar/doc.go | 6 - .../v1/gonum/floats/scalar/scalar.go | 171 - .../gonum/internal/asm/c128/axpyinc_amd64.s | 134 - .../gonum/internal/asm/c128/axpyincto_amd64.s | 141 - .../internal/asm/c128/axpyunitary_amd64.s | 122 - .../internal/asm/c128/axpyunitaryto_amd64.s | 123 - .../v1/gonum/internal/asm/c128/doc.go | 6 - .../gonum/internal/asm/c128/dotcinc_amd64.s | 153 - .../internal/asm/c128/dotcunitary_amd64.s | 143 - .../gonum/internal/asm/c128/dotuinc_amd64.s | 141 - .../internal/asm/c128/dotuunitary_amd64.s | 130 - .../gonum/internal/asm/c128/dscalinc_amd64.s | 69 - .../internal/asm/c128/dscalunitary_amd64.s | 66 - .../v1/gonum/internal/asm/c128/scal.go | 33 - .../internal/asm/c128/scalUnitary_amd64.s | 116 - .../gonum/internal/asm/c128/scalinc_amd64.s | 121 - .../v1/gonum/internal/asm/c128/stubs.go | 180 - .../v1/gonum/internal/asm/c128/stubs_amd64.go | 109 - .../v1/gonum/internal/asm/c128/stubs_noasm.go | 176 - .../v1/gonum/internal/asm/c64/axpyinc_amd64.s | 151 - .../gonum/internal/asm/c64/axpyincto_amd64.s | 156 - .../internal/asm/c64/axpyunitary_amd64.s | 160 - .../internal/asm/c64/axpyunitaryto_amd64.s | 157 - .../v1/gonum/internal/asm/c64/conj.go | 7 - .../v1/gonum/internal/asm/c64/doc.go | 6 - .../v1/gonum/internal/asm/c64/dotcinc_amd64.s | 160 - .../internal/asm/c64/dotcunitary_amd64.s | 208 - .../v1/gonum/internal/asm/c64/dotuinc_amd64.s | 148 - .../internal/asm/c64/dotuunitary_amd64.s | 197 - .../v1/gonum/internal/asm/c64/scal.go | 85 - .../v1/gonum/internal/asm/c64/stubs.go | 180 - .../v1/gonum/internal/asm/c64/stubs_amd64.go | 77 - .../v1/gonum/internal/asm/c64/stubs_noasm.go | 122 - .../v1/gonum/internal/asm/f32/axpyinc_amd64.s | 73 - .../gonum/internal/asm/f32/axpyincto_amd64.s | 78 - .../internal/asm/f32/axpyunitary_amd64.s | 97 - .../internal/asm/f32/axpyunitaryto_amd64.s | 98 - .../v1/gonum/internal/asm/f32/ddotinc_amd64.s | 91 - .../internal/asm/f32/ddotunitary_amd64.s | 110 - .../v1/gonum/internal/asm/f32/doc.go | 6 - .../v1/gonum/internal/asm/f32/dotinc_amd64.s | 85 - .../gonum/internal/asm/f32/dotunitary_amd64.s | 106 - .../v1/gonum/internal/asm/f32/ge_amd64.go | 18 - .../v1/gonum/internal/asm/f32/ge_amd64.s | 757 - .../v1/gonum/internal/asm/f32/ge_noasm.go | 39 - .../v1/gonum/internal/asm/f32/gemv.go | 92 - .../v1/gonum/internal/asm/f32/l2norm.go | 90 - .../v1/gonum/internal/asm/f32/scal.go | 59 - .../v1/gonum/internal/asm/f32/stubs_amd64.go | 86 - .../v1/gonum/internal/asm/f32/stubs_noasm.go | 137 - .../v1/gonum/internal/asm/f32/sum_amd64.s | 100 - .../v1/gonum/internal/asm/f64/abssum_amd64.s | 82 - .../gonum/internal/asm/f64/abssuminc_amd64.s | 90 - .../v1/gonum/internal/asm/f64/add_amd64.s | 66 - .../gonum/internal/asm/f64/addconst_amd64.s | 53 - .../v1/gonum/internal/asm/f64/axpy.go | 62 - .../v1/gonum/internal/asm/f64/axpyinc_amd64.s | 142 - .../gonum/internal/asm/f64/axpyincto_amd64.s | 148 - .../internal/asm/f64/axpyunitary_amd64.s | 134 - .../internal/asm/f64/axpyunitaryto_amd64.s | 140 - .../v1/gonum/internal/asm/f64/cumprod_amd64.s | 71 - .../v1/gonum/internal/asm/f64/cumsum_amd64.s | 64 - .../v1/gonum/internal/asm/f64/div_amd64.s | 67 - .../v1/gonum/internal/asm/f64/divto_amd64.s | 73 - .../v1/gonum/internal/asm/f64/doc.go | 6 - .../v1/gonum/internal/asm/f64/dot.go | 38 - .../v1/gonum/internal/asm/f64/dot_amd64.s | 145 - .../v1/gonum/internal/asm/f64/ge_amd64.go | 29 - .../v1/gonum/internal/asm/f64/ge_noasm.go | 125 - .../v1/gonum/internal/asm/f64/gemvN_amd64.s | 685 - .../v1/gonum/internal/asm/f64/gemvT_amd64.s | 745 - .../v1/gonum/internal/asm/f64/ger_amd64.s | 591 - .../v1/gonum/internal/asm/f64/l1norm_amd64.s | 58 - .../v1/gonum/internal/asm/f64/l2norm_amd64.s | 109 - .../v1/gonum/internal/asm/f64/l2norm_noasm.go | 93 - .../gonum/internal/asm/f64/l2normdist_amd64.s | 115 - .../gonum/internal/asm/f64/l2norminc_amd64.s | 110 - .../gonum/internal/asm/f64/linfnorm_amd64.s | 57 - .../v1/gonum/internal/asm/f64/scal.go | 62 - .../v1/gonum/internal/asm/f64/scalinc_amd64.s | 113 - .../gonum/internal/asm/f64/scalincto_amd64.s | 122 - .../internal/asm/f64/scalunitary_amd64.s | 112 - .../internal/asm/f64/scalunitaryto_amd64.s | 113 - .../v1/gonum/internal/asm/f64/stubs_amd64.go | 277 - .../v1/gonum/internal/asm/f64/stubs_noasm.go | 182 - .../v1/gonum/internal/asm/f64/sum_amd64.s | 99 - .../v1/gonum/internal/cmplx64/abs.go | 14 - .../v1/gonum/internal/cmplx64/conj.go | 12 - .../v1/gonum/internal/cmplx64/doc.go | 7 - .../v1/gonum/internal/cmplx64/isinf.go | 25 - .../v1/gonum/internal/cmplx64/isnan.go | 29 - .../v1/gonum/internal/cmplx64/sqrt.go | 108 - .../gonum.org/v1/gonum/internal/math32/doc.go | 7 - .../v1/gonum/internal/math32/math.go | 166 - .../v1/gonum/internal/math32/signbit.go | 16 - .../v1/gonum/internal/math32/sqrt.go | 26 - .../v1/gonum/internal/math32/sqrt_amd64.go | 22 - .../v1/gonum/internal/math32/sqrt_amd64.s | 17 - .../v1/gonum/internal/math32/sqrt_arm64.go | 22 - .../v1/gonum/internal/math32/sqrt_arm64.s | 18 - vendor/gonum.org/v1/gonum/lapack/.gitignore | 0 vendor/gonum.org/v1/gonum/lapack/README.md | 29 - vendor/gonum.org/v1/gonum/lapack/doc.go | 6 - .../gonum.org/v1/gonum/lapack/gonum/dbdsqr.go | 506 - .../gonum.org/v1/gonum/lapack/gonum/dgebak.go | 91 - .../gonum.org/v1/gonum/lapack/gonum/dgebal.go | 248 - .../gonum.org/v1/gonum/lapack/gonum/dgebd2.go | 88 - .../gonum.org/v1/gonum/lapack/gonum/dgebrd.go | 169 - .../gonum.org/v1/gonum/lapack/gonum/dgecon.go | 106 - .../gonum.org/v1/gonum/lapack/gonum/dgeev.go | 287 - .../gonum.org/v1/gonum/lapack/gonum/dgehd2.go | 105 - .../gonum.org/v1/gonum/lapack/gonum/dgehrd.go | 202 - .../gonum.org/v1/gonum/lapack/gonum/dgelq2.go | 65 - .../gonum.org/v1/gonum/lapack/gonum/dgelqf.go | 97 - .../gonum.org/v1/gonum/lapack/gonum/dgels.go | 220 - .../gonum.org/v1/gonum/lapack/gonum/dgeql2.go | 67 - .../gonum.org/v1/gonum/lapack/gonum/dgeqp3.go | 195 - .../gonum.org/v1/gonum/lapack/gonum/dgeqr2.go | 78 - .../gonum.org/v1/gonum/lapack/gonum/dgeqrf.go | 108 - .../gonum.org/v1/gonum/lapack/gonum/dgerq2.go | 74 - .../gonum.org/v1/gonum/lapack/gonum/dgerqf.go | 135 - .../gonum.org/v1/gonum/lapack/gonum/dgesc2.go | 93 - .../gonum.org/v1/gonum/lapack/gonum/dgesv.go | 60 - .../gonum.org/v1/gonum/lapack/gonum/dgesvd.go | 1378 -- .../gonum.org/v1/gonum/lapack/gonum/dgetc2.go | 125 - .../gonum.org/v1/gonum/lapack/gonum/dgetf2.go | 90 - .../gonum.org/v1/gonum/lapack/gonum/dgetrf.go | 89 - .../gonum.org/v1/gonum/lapack/gonum/dgetri.go | 116 - .../gonum.org/v1/gonum/lapack/gonum/dgetrs.go | 74 - .../gonum.org/v1/gonum/lapack/gonum/dgghrd.go | 125 - .../v1/gonum/lapack/gonum/dggsvd3.go | 258 - .../v1/gonum/lapack/gonum/dggsvp3.go | 286 - .../gonum.org/v1/gonum/lapack/gonum/dgtsv.go | 101 - .../gonum.org/v1/gonum/lapack/gonum/dhseqr.go | 272 - .../gonum.org/v1/gonum/lapack/gonum/dlabrd.go | 183 - .../gonum.org/v1/gonum/lapack/gonum/dlacn2.go | 136 - .../gonum.org/v1/gonum/lapack/gonum/dlacpy.go | 59 - .../gonum.org/v1/gonum/lapack/gonum/dlae2.go | 51 - .../gonum.org/v1/gonum/lapack/gonum/dlaev2.go | 85 - .../gonum.org/v1/gonum/lapack/gonum/dlaexc.go | 269 - .../gonum.org/v1/gonum/lapack/gonum/dlag2.go | 237 - .../gonum.org/v1/gonum/lapack/gonum/dlags2.go | 186 - .../gonum.org/v1/gonum/lapack/gonum/dlagtm.go | 111 - .../gonum.org/v1/gonum/lapack/gonum/dlahqr.go | 449 - .../gonum.org/v1/gonum/lapack/gonum/dlahr2.go | 202 - .../gonum.org/v1/gonum/lapack/gonum/dlaln2.go | 407 - .../gonum.org/v1/gonum/lapack/gonum/dlangb.go | 87 - .../gonum.org/v1/gonum/lapack/gonum/dlange.go | 89 - .../gonum.org/v1/gonum/lapack/gonum/dlangt.go | 115 - .../gonum.org/v1/gonum/lapack/gonum/dlanhs.go | 78 - .../gonum.org/v1/gonum/lapack/gonum/dlansb.go | 131 - .../gonum.org/v1/gonum/lapack/gonum/dlanst.go | 75 - .../gonum.org/v1/gonum/lapack/gonum/dlansy.go | 125 - .../gonum.org/v1/gonum/lapack/gonum/dlantb.go | 209 - .../gonum.org/v1/gonum/lapack/gonum/dlantr.go | 252 - .../gonum.org/v1/gonum/lapack/gonum/dlanv2.go | 151 - .../gonum.org/v1/gonum/lapack/gonum/dlapll.go | 55 - .../gonum.org/v1/gonum/lapack/gonum/dlapmr.go | 88 - .../gonum.org/v1/gonum/lapack/gonum/dlapmt.go | 89 - .../gonum.org/v1/gonum/lapack/gonum/dlapy2.go | 14 - .../gonum.org/v1/gonum/lapack/gonum/dlaqp2.go | 127 - .../gonum.org/v1/gonum/lapack/gonum/dlaqps.go | 244 - .../v1/gonum/lapack/gonum/dlaqr04.go | 493 - .../gonum.org/v1/gonum/lapack/gonum/dlaqr1.go | 61 - .../v1/gonum/lapack/gonum/dlaqr23.go | 423 - .../gonum.org/v1/gonum/lapack/gonum/dlaqr5.go | 560 - .../gonum.org/v1/gonum/lapack/gonum/dlarf.go | 102 - .../gonum.org/v1/gonum/lapack/gonum/dlarfb.go | 461 - .../gonum.org/v1/gonum/lapack/gonum/dlarfg.go | 75 - .../gonum.org/v1/gonum/lapack/gonum/dlarft.go | 169 - .../gonum.org/v1/gonum/lapack/gonum/dlarfx.go | 552 - .../gonum.org/v1/gonum/lapack/gonum/dlartg.go | 73 - .../gonum.org/v1/gonum/lapack/gonum/dlas2.go | 45 - .../gonum.org/v1/gonum/lapack/gonum/dlascl.go | 111 - .../gonum.org/v1/gonum/lapack/gonum/dlaset.go | 58 - .../gonum.org/v1/gonum/lapack/gonum/dlasq1.go | 100 - .../gonum.org/v1/gonum/lapack/gonum/dlasq2.go | 370 - .../gonum.org/v1/gonum/lapack/gonum/dlasq3.go | 172 - .../gonum.org/v1/gonum/lapack/gonum/dlasq4.go | 249 - .../gonum.org/v1/gonum/lapack/gonum/dlasq5.go | 140 - .../gonum.org/v1/gonum/lapack/gonum/dlasq6.go | 118 - .../gonum.org/v1/gonum/lapack/gonum/dlasr.go | 287 - .../gonum.org/v1/gonum/lapack/gonum/dlasrt.go | 36 - .../gonum.org/v1/gonum/lapack/gonum/dlassq.go | 131 - .../gonum.org/v1/gonum/lapack/gonum/dlasv2.go | 117 - .../gonum.org/v1/gonum/lapack/gonum/dlaswp.go | 58 - .../gonum.org/v1/gonum/lapack/gonum/dlasy2.go | 292 - .../gonum.org/v1/gonum/lapack/gonum/dlatbs.go | 454 - .../gonum.org/v1/gonum/lapack/gonum/dlatdf.go | 175 - .../gonum.org/v1/gonum/lapack/gonum/dlatrd.go | 176 - .../gonum.org/v1/gonum/lapack/gonum/dlatrs.go | 410 - .../gonum.org/v1/gonum/lapack/gonum/dlauu2.go | 66 - .../gonum.org/v1/gonum/lapack/gonum/dlauum.go | 83 - vendor/gonum.org/v1/gonum/lapack/gonum/doc.go | 28 - .../gonum.org/v1/gonum/lapack/gonum/dorg2l.go | 78 - .../gonum.org/v1/gonum/lapack/gonum/dorg2r.go | 77 - .../gonum.org/v1/gonum/lapack/gonum/dorgbr.go | 138 - .../gonum.org/v1/gonum/lapack/gonum/dorghr.go | 103 - .../gonum.org/v1/gonum/lapack/gonum/dorgl2.go | 79 - .../gonum.org/v1/gonum/lapack/gonum/dorglq.go | 125 - .../gonum.org/v1/gonum/lapack/gonum/dorgql.go | 139 - .../gonum.org/v1/gonum/lapack/gonum/dorgqr.go | 136 - .../gonum.org/v1/gonum/lapack/gonum/dorgr2.go | 83 - .../gonum.org/v1/gonum/lapack/gonum/dorgtr.go | 106 - .../gonum.org/v1/gonum/lapack/gonum/dorm2r.go | 103 - .../gonum.org/v1/gonum/lapack/gonum/dormbr.go | 180 - .../gonum.org/v1/gonum/lapack/gonum/dormhr.go | 134 - .../gonum.org/v1/gonum/lapack/gonum/dorml2.go | 104 - .../gonum.org/v1/gonum/lapack/gonum/dormlq.go | 176 - .../gonum.org/v1/gonum/lapack/gonum/dormqr.go | 180 - .../gonum.org/v1/gonum/lapack/gonum/dormr2.go | 105 - .../gonum.org/v1/gonum/lapack/gonum/dpbcon.go | 111 - .../gonum.org/v1/gonum/lapack/gonum/dpbtf2.go | 114 - .../gonum.org/v1/gonum/lapack/gonum/dpbtrf.go | 216 - .../gonum.org/v1/gonum/lapack/gonum/dpbtrs.go | 69 - .../gonum.org/v1/gonum/lapack/gonum/dpocon.go | 90 - .../gonum.org/v1/gonum/lapack/gonum/dpotf2.go | 82 - .../gonum.org/v1/gonum/lapack/gonum/dpotrf.go | 81 - .../gonum.org/v1/gonum/lapack/gonum/dpotri.go | 44 - .../gonum.org/v1/gonum/lapack/gonum/dpotrs.go | 64 - .../gonum.org/v1/gonum/lapack/gonum/dpstf2.go | 202 - .../gonum.org/v1/gonum/lapack/gonum/dpstrf.go | 233 - .../gonum.org/v1/gonum/lapack/gonum/dptcon.go | 99 - .../gonum.org/v1/gonum/lapack/gonum/dptsv.go | 49 - .../gonum.org/v1/gonum/lapack/gonum/dpttrf.go | 80 - .../gonum.org/v1/gonum/lapack/gonum/dpttrs.go | 51 - .../gonum.org/v1/gonum/lapack/gonum/dptts2.go | 39 - .../gonum.org/v1/gonum/lapack/gonum/drscl.go | 63 - .../gonum.org/v1/gonum/lapack/gonum/dsteqr.go | 376 - .../gonum.org/v1/gonum/lapack/gonum/dsterf.go | 285 - .../gonum.org/v1/gonum/lapack/gonum/dsyev.go | 130 - .../gonum.org/v1/gonum/lapack/gonum/dsytd2.go | 147 - .../gonum.org/v1/gonum/lapack/gonum/dsytrd.go | 184 - .../gonum.org/v1/gonum/lapack/gonum/dtbtrs.go | 77 - .../gonum.org/v1/gonum/lapack/gonum/dtgsja.go | 389 - .../gonum.org/v1/gonum/lapack/gonum/dtrcon.go | 90 - .../v1/gonum/lapack/gonum/dtrevc3.go | 894 - .../gonum.org/v1/gonum/lapack/gonum/dtrexc.go | 230 - .../gonum.org/v1/gonum/lapack/gonum/dtrti2.go | 69 - .../gonum.org/v1/gonum/lapack/gonum/dtrtri.go | 72 - .../gonum.org/v1/gonum/lapack/gonum/dtrtrs.go | 55 - .../gonum.org/v1/gonum/lapack/gonum/errors.go | 183 - .../gonum.org/v1/gonum/lapack/gonum/iladlc.go | 45 - .../gonum.org/v1/gonum/lapack/gonum/iladlr.go | 41 - .../gonum.org/v1/gonum/lapack/gonum/ilaenv.go | 395 - .../gonum.org/v1/gonum/lapack/gonum/iparmq.go | 117 - .../gonum.org/v1/gonum/lapack/gonum/lapack.go | 64 - vendor/gonum.org/v1/gonum/lapack/lapack.go | 240 - .../gonum.org/v1/gonum/lapack/lapack64/doc.go | 20 - .../v1/gonum/lapack/lapack64/lapack64.go | 908 - vendor/gonum.org/v1/gonum/mat/README.md | 6 - vendor/gonum.org/v1/gonum/mat/band.go | 368 - vendor/gonum.org/v1/gonum/mat/cdense.go | 368 - vendor/gonum.org/v1/gonum/mat/cholesky.go | 1203 -- vendor/gonum.org/v1/gonum/mat/cmatrix.go | 314 - vendor/gonum.org/v1/gonum/mat/consts.go | 15 - vendor/gonum.org/v1/gonum/mat/dense.go | 670 - .../v1/gonum/mat/dense_arithmetic.go | 877 - vendor/gonum.org/v1/gonum/mat/diagonal.go | 342 - vendor/gonum.org/v1/gonum/mat/doc.go | 200 - vendor/gonum.org/v1/gonum/mat/eigen.go | 450 - vendor/gonum.org/v1/gonum/mat/errors.go | 154 - vendor/gonum.org/v1/gonum/mat/format.go | 516 - vendor/gonum.org/v1/gonum/mat/gsvd.go | 436 - vendor/gonum.org/v1/gonum/mat/hogsvd.go | 239 - .../v1/gonum/mat/index_bound_checks.go | 398 - .../v1/gonum/mat/index_no_bound_checks.go | 400 - vendor/gonum.org/v1/gonum/mat/inner.go | 126 - vendor/gonum.org/v1/gonum/mat/io.go | 495 - vendor/gonum.org/v1/gonum/mat/lq.go | 305 - vendor/gonum.org/v1/gonum/mat/lu.go | 487 - vendor/gonum.org/v1/gonum/mat/matrix.go | 1000 - vendor/gonum.org/v1/gonum/mat/offset.go | 32 - .../v1/gonum/mat/offset_appengine.go | 40 - vendor/gonum.org/v1/gonum/mat/pool.go | 260 - vendor/gonum.org/v1/gonum/mat/product.go | 193 - vendor/gonum.org/v1/gonum/mat/qr.go | 349 - vendor/gonum.org/v1/gonum/mat/shadow.go | 243 - .../gonum.org/v1/gonum/mat/shadow_common.go | 54 - .../gonum.org/v1/gonum/mat/shadow_complex.go | 72 - vendor/gonum.org/v1/gonum/mat/solve.go | 124 - vendor/gonum.org/v1/gonum/mat/svd.go | 425 - vendor/gonum.org/v1/gonum/mat/symband.go | 312 - vendor/gonum.org/v1/gonum/mat/symmetric.go | 698 - vendor/gonum.org/v1/gonum/mat/triangular.go | 832 - vendor/gonum.org/v1/gonum/mat/triband.go | 694 - vendor/gonum.org/v1/gonum/mat/tridiag.go | 417 - vendor/gonum.org/v1/gonum/mat/vector.go | 855 - vendor/gonum.org/v1/gonum/mathext/README.md | 6 - vendor/gonum.org/v1/gonum/mathext/airy.go | 41 - vendor/gonum.org/v1/gonum/mathext/beta.go | 40 - vendor/gonum.org/v1/gonum/mathext/betainc.go | 33 - vendor/gonum.org/v1/gonum/mathext/digamma.go | 45 - vendor/gonum.org/v1/gonum/mathext/doc.go | 7 - .../gonum.org/v1/gonum/mathext/ell_carlson.go | 168 - .../v1/gonum/mathext/ell_complete.go | 355 - vendor/gonum.org/v1/gonum/mathext/erf.go | 91 - .../gonum.org/v1/gonum/mathext/gamma_inc.go | 58 - .../v1/gonum/mathext/gamma_inc_inv.go | 58 - .../v1/gonum/mathext/internal/amos/amos.go | 2136 --- .../v1/gonum/mathext/internal/amos/doc.go | 6 - .../mathext/internal/amos/staticcheck.conf | 1 - .../gonum/mathext/internal/cephes/cephes.go | 28 - .../v1/gonum/mathext/internal/cephes/doc.go | 6 - .../v1/gonum/mathext/internal/cephes/igam.go | 320 - .../v1/gonum/mathext/internal/cephes/igami.go | 155 - .../gonum/mathext/internal/cephes/incbeta.go | 312 - .../v1/gonum/mathext/internal/cephes/incbi.go | 247 - .../gonum/mathext/internal/cephes/lanczos.go | 153 - .../v1/gonum/mathext/internal/cephes/ndtri.go | 150 - .../gonum/mathext/internal/cephes/polevl.go | 84 - .../mathext/internal/cephes/staticcheck.conf | 1 - .../v1/gonum/mathext/internal/cephes/unity.go | 184 - .../v1/gonum/mathext/internal/cephes/zeta.go | 117 - .../v1/gonum/mathext/internal/gonum/beta.go | 58 - .../v1/gonum/mathext/internal/gonum/doc.go | 7 - .../v1/gonum/mathext/internal/gonum/gonum.go | 5 - vendor/gonum.org/v1/gonum/mathext/mvgamma.go | 32 - vendor/gonum.org/v1/gonum/mathext/roots.go | 181 - vendor/gonum.org/v1/gonum/mathext/zeta.go | 22 - vendor/gonum.org/v1/gonum/stat/README.md | 6 - .../gonum.org/v1/gonum/stat/combin/combin.go | 683 - vendor/gonum.org/v1/gonum/stat/combin/doc.go | 7 - .../v1/gonum/stat/distuv/alphastable.go | 112 - .../v1/gonum/stat/distuv/bernoulli.go | 140 - vendor/gonum.org/v1/gonum/stat/distuv/beta.go | 151 - .../v1/gonum/stat/distuv/binomial.go | 189 - .../v1/gonum/stat/distuv/categorical.go | 184 - vendor/gonum.org/v1/gonum/stat/distuv/chi.go | 124 - .../v1/gonum/stat/distuv/chisquared.go | 101 - .../v1/gonum/stat/distuv/constants.go | 28 - vendor/gonum.org/v1/gonum/stat/distuv/doc.go | 6 - .../v1/gonum/stat/distuv/exponential.go | 266 - vendor/gonum.org/v1/gonum/stat/distuv/f.go | 134 - .../gonum.org/v1/gonum/stat/distuv/gamma.go | 203 - .../gonum.org/v1/gonum/stat/distuv/general.go | 24 - .../gonum.org/v1/gonum/stat/distuv/gumbel.go | 118 - .../v1/gonum/stat/distuv/interfaces.go | 32 - .../v1/gonum/stat/distuv/inversegamma.go | 123 - .../gonum.org/v1/gonum/stat/distuv/laplace.go | 267 - .../v1/gonum/stat/distuv/logistic.go | 98 - .../v1/gonum/stat/distuv/lognormal.go | 113 - vendor/gonum.org/v1/gonum/stat/distuv/norm.go | 263 - .../gonum.org/v1/gonum/stat/distuv/pareto.go | 130 - .../gonum.org/v1/gonum/stat/distuv/poisson.go | 144 - .../v1/gonum/stat/distuv/statdist.go | 142 - .../v1/gonum/stat/distuv/studentst.go | 161 - .../v1/gonum/stat/distuv/triangle.go | 278 - .../gonum.org/v1/gonum/stat/distuv/uniform.go | 210 - .../gonum.org/v1/gonum/stat/distuv/weibull.go | 231 - vendor/gonum.org/v1/gonum/stat/doc.go | 6 - vendor/gonum.org/v1/gonum/stat/pca_cca.go | 317 - vendor/gonum.org/v1/gonum/stat/roc.go | 198 - vendor/gonum.org/v1/gonum/stat/stat.go | 1400 -- vendor/gonum.org/v1/gonum/stat/statmat.go | 142 - .../rpc/errdetails/error_details.pb.go | 1473 -- .../grpc/encoding/gzip/gzip.go | 132 - .../grpc/reflection/README.md | 18 - .../grpc/reflection/adapt.go | 57 - .../grpc_reflection_v1/reflection.pb.go | 777 - .../grpc_reflection_v1/reflection_grpc.pb.go | 138 - .../grpc_reflection_v1alpha/reflection.pb.go | 847 - .../reflection_grpc.pb.go | 135 - .../grpc/reflection/internal/internal.go | 436 - .../grpc/reflection/serverreflection.go | 160 - .../encoding/protodelim/protodelim.go | 160 - .../internal/editionssupport/editions.go | 18 - .../protobuf/reflect/protodesc/desc.go | 308 - .../protobuf/reflect/protodesc/desc_init.go | 290 - .../reflect/protodesc/desc_resolve.go | 291 - .../reflect/protodesc/desc_validate.go | 359 - .../protobuf/reflect/protodesc/editions.go | 181 - .../protobuf/reflect/protodesc/proto.go | 298 - .../types/gofeaturespb/go_features.pb.go | 311 - vendor/gopkg.in/yaml.v2/.travis.yml | 17 - vendor/gopkg.in/yaml.v2/LICENSE | 201 - vendor/gopkg.in/yaml.v2/LICENSE.libyaml | 31 - vendor/gopkg.in/yaml.v2/NOTICE | 13 - vendor/gopkg.in/yaml.v2/README.md | 133 - vendor/gopkg.in/yaml.v2/apic.go | 744 - vendor/gopkg.in/yaml.v2/decode.go | 815 - vendor/gopkg.in/yaml.v2/emitterc.go | 1685 -- vendor/gopkg.in/yaml.v2/encode.go | 390 - vendor/gopkg.in/yaml.v2/parserc.go | 1095 -- vendor/gopkg.in/yaml.v2/readerc.go | 412 - vendor/gopkg.in/yaml.v2/resolve.go | 258 - vendor/gopkg.in/yaml.v2/scannerc.go | 2711 --- vendor/gopkg.in/yaml.v2/sorter.go | 113 - vendor/gopkg.in/yaml.v2/writerc.go | 26 - vendor/gopkg.in/yaml.v2/yaml.go | 478 - vendor/gopkg.in/yaml.v2/yamlh.go | 739 - vendor/gopkg.in/yaml.v2/yamlprivateh.go | 173 - vendor/modules.txt | 662 +- 3216 files changed, 1655 insertions(+), 724257 deletions(-) delete mode 100644 cmd/humanlog/api.go delete mode 100644 cmd/humanlog/auth.go delete mode 100644 cmd/humanlog/demo.go delete mode 100644 cmd/humanlog/environment.go delete mode 100644 cmd/humanlog/genny.go delete mode 100644 cmd/humanlog/helper.go delete mode 100644 cmd/humanlog/ingest.go delete mode 100644 cmd/humanlog/localhost.go delete mode 100644 cmd/humanlog/onboarding.go delete mode 100644 cmd/humanlog/organization.go delete mode 100644 cmd/humanlog/project.go delete mode 100644 cmd/humanlog/query.go delete mode 100644 cmd/humanlog/query_test.go delete mode 100644 cmd/humanlog/service.go delete mode 100644 cmd/humanlog/service_darwin.go delete mode 100644 cmd/humanlog/service_other.go delete mode 100644 cmd/humanlog/state.go delete mode 100644 cmd/humanlog/stream.go delete mode 100644 cmd/humanlog/systray_darwin.go delete mode 100644 cmd/humanlog/systray_other.go create mode 100644 docs/alert-architecture-summary.md create mode 100644 docs/dashboard-authoring-proposal.md delete mode 100644 internal/compat/alertmanager/parse.go delete mode 100644 internal/embeds/assets/icon/systray/humanlog.icns delete mode 100644 internal/embeds/assets/icon/systray/humanlog_icon_512x512.png delete mode 100644 internal/embeds/embed.go delete mode 100644 internal/errutil/errors.go delete mode 100644 internal/errutil/errors_unix.go delete mode 100644 internal/errutil/errors_windows.go delete mode 100644 internal/errutil/errutil_test.go delete mode 100644 internal/localalert/alert.go delete mode 100644 internal/localalert/alert_test.go delete mode 100644 internal/localproject/alert_group_lifecycle_test.go delete mode 100644 internal/localproject/dashboard_lifecycle_test.go delete mode 100644 internal/localproject/db.go delete mode 100644 internal/localproject/errors.go delete mode 100644 internal/localproject/fs.go delete mode 100644 internal/localproject/fs_test.go delete mode 100644 internal/localproject/git.go delete mode 100644 internal/localproject/git_test.go delete mode 100644 internal/localproject/storage_test_suite.go delete mode 100644 internal/localproject/watch.go delete mode 100644 internal/localproject/watch_test.go delete mode 100644 internal/localserver/alert_scheduler.go delete mode 100644 internal/localserver/alert_scheduler_test.go delete mode 100644 internal/localserver/alert_status_test.go delete mode 100644 internal/localserver/server.go delete mode 100644 internal/localstate/inmem.go delete mode 100644 internal/localstate/localstate.go delete mode 100644 internal/localsvc/otlp.go delete mode 100644 internal/localsvc/otlp_codec.go delete mode 100644 internal/localsvc/svc.go delete mode 100644 internal/pkg/absfs/fs.go delete mode 100644 internal/pkg/iterapi/iter.go delete mode 100644 pkg/localstorage/queryable.go delete mode 100644 pkg/localstorage/test_suite.go delete mode 100644 pkg/retry/retry.go delete mode 100644 pkg/retry/retry_test.go delete mode 100644 pkg/sink/logsvcsink/stream_sink.go delete mode 100644 pkg/sink/logsvcsink/unary_sink.go delete mode 100644 pkg/validate/validate.go delete mode 100644 vendor/connectrpc.com/cors/.gitignore delete mode 100644 vendor/connectrpc.com/cors/.golangci.yml delete mode 100644 vendor/connectrpc.com/cors/LICENSE delete mode 100644 vendor/connectrpc.com/cors/MAINTAINERS.md delete mode 100644 vendor/connectrpc.com/cors/Makefile delete mode 100644 vendor/connectrpc.com/cors/README.md delete mode 100644 vendor/connectrpc.com/cors/SECURITY.md delete mode 100644 vendor/connectrpc.com/cors/cors.go delete mode 100644 vendor/connectrpc.com/otelconnect/.gitignore delete mode 100644 vendor/connectrpc.com/otelconnect/.golangci.yml delete mode 100644 vendor/connectrpc.com/otelconnect/LICENSE delete mode 100644 vendor/connectrpc.com/otelconnect/MAINTAINERS.md delete mode 100644 vendor/connectrpc.com/otelconnect/Makefile delete mode 100644 vendor/connectrpc.com/otelconnect/README.md delete mode 100644 vendor/connectrpc.com/otelconnect/SECURITY.md delete mode 100644 vendor/connectrpc.com/otelconnect/attributes.go delete mode 100644 vendor/connectrpc.com/otelconnect/buf.gen.yaml delete mode 100644 vendor/connectrpc.com/otelconnect/buf.yaml delete mode 100644 vendor/connectrpc.com/otelconnect/doc.go delete mode 100644 vendor/connectrpc.com/otelconnect/instruments.go delete mode 100644 vendor/connectrpc.com/otelconnect/interceptor.go delete mode 100644 vendor/connectrpc.com/otelconnect/option.go delete mode 100644 vendor/connectrpc.com/otelconnect/otelconnect.go delete mode 100644 vendor/connectrpc.com/otelconnect/payloadinterceptor.go delete mode 100644 vendor/connectrpc.com/otelconnect/streaming.go delete mode 100644 vendor/github.com/Microsoft/go-winio/.gitattributes delete mode 100644 vendor/github.com/Microsoft/go-winio/.gitignore delete mode 100644 vendor/github.com/Microsoft/go-winio/.golangci.yml delete mode 100644 vendor/github.com/Microsoft/go-winio/CODEOWNERS delete mode 100644 vendor/github.com/Microsoft/go-winio/LICENSE delete mode 100644 vendor/github.com/Microsoft/go-winio/README.md delete mode 100644 vendor/github.com/Microsoft/go-winio/SECURITY.md delete mode 100644 vendor/github.com/Microsoft/go-winio/backup.go delete mode 100644 vendor/github.com/Microsoft/go-winio/doc.go delete mode 100644 vendor/github.com/Microsoft/go-winio/ea.go delete mode 100644 vendor/github.com/Microsoft/go-winio/file.go delete mode 100644 vendor/github.com/Microsoft/go-winio/fileinfo.go delete mode 100644 vendor/github.com/Microsoft/go-winio/hvsock.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/fs/doc.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/fs/fs.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/fs/security.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/socket/socket.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go delete mode 100644 vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go delete mode 100644 vendor/github.com/Microsoft/go-winio/pipe.go delete mode 100644 vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go delete mode 100644 vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go delete mode 100644 vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go delete mode 100644 vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go delete mode 100644 vendor/github.com/Microsoft/go-winio/privilege.go delete mode 100644 vendor/github.com/Microsoft/go-winio/reparse.go delete mode 100644 vendor/github.com/Microsoft/go-winio/sd.go delete mode 100644 vendor/github.com/Microsoft/go-winio/syscall.go delete mode 100644 vendor/github.com/Microsoft/go-winio/zsyscall_windows.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/LICENSE.txt delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/canvas/buffer/buffer.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/canvas/canvas.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/canvas/graph/graph.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/canvas/options.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/canvas/runes/runes.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/canvas/updatehandler.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/linechart/linechart.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/linechart/options.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/options.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/timeserieslinechart.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/updatehandler.go delete mode 100644 vendor/github.com/NimbleMarkets/ntcharts/linechart/updatehandler.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/AUTHORS delete mode 100644 vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS delete mode 100644 vendor/github.com/ProtonMail/go-crypto/LICENSE delete mode 100644 vendor/github.com/ProtonMail/go-crypto/PATENTS delete mode 100644 vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/eax/eax.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/ecdsa/ecdsa.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/eddsa/eddsa.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curves.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/notation.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/read.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/write.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go delete mode 100644 vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/.editorconfig delete mode 100644 vendor/github.com/alecthomas/chroma/v2/.gitignore delete mode 100644 vendor/github.com/alecthomas/chroma/v2/.golangci.yml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/Bitfile delete mode 100644 vendor/github.com/alecthomas/chroma/v2/COPYING delete mode 100644 vendor/github.com/alecthomas/chroma/v2/Makefile delete mode 100644 vendor/github.com/alecthomas/chroma/v2/README.md delete mode 100644 vendor/github.com/alecthomas/chroma/v2/coalesce.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/colour.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/delegate.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/doc.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/emitters.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatter.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/api.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/json.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/svg/svg.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/tokens.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/iterator.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexer.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/README.md delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/cl.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/dns.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/emacs.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abap.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abnf.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript_3.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ada.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/agda.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/al.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/alloy.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/antlr.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apacheconf.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autohotkey.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autoit.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/awk.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ballerina.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash_session.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/batchfile.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bibtex.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bicep.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/blitzbasic.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bnf.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bqn.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/brainfuck.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c#.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c++.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cap_n_proto.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cassandra_cql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ceylon.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfstatement.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chaiscript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chapel.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cheetah.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/clojure.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cmake.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cobol.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coffeescript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/common_lisp.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coq.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/crystal.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cue.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cython.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/d.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dax.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/desktop_entry.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/diff.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/django_jinja.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dtd.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dylan.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ebnf.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elixir.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elm.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/emacslisp.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erlang.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/factor.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fennel.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fish.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/forth.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortranfixed.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fsharp.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript3.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gherkin.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gleam.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/glsl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gnuplot.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/go_template.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groff.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groovy.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/handlebars.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hare.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/haskell.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hcl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hexdump.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlsl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/holyc.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/html.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hy.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/idris.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/igor.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ini.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/io.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/iscdhcpd.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/j.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/julia.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jungle.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lighttpd_configuration_file.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/llvm.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/makefile.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mako.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mason.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mathematica.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/matlab.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/metal.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/minizinc.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mlir.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modula-2.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/monkeyc.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/morrowindscript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/myghty.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nasm.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/natural.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ndisasm.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/newspeak.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nginx_configuration_file.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nim.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nix.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objective-c.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ocaml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/octave.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/odin.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/onesenterprise.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openedge_abl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openscad.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/org_mode.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pacmanconf.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/perl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pig.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pkgconfig.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pl_pgsql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plaintext.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plutus_core.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pony.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postgresql_sql_dialect.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/povray.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powerquery.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powershell.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prolog.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promela.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/psl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/puppet.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python_2.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qbasic.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/r.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/racket.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ragel.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/react.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reasonml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reg.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rego.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rexx.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpm_spec.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rust.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sas.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sass.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scala.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scheme.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scilab.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scss.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sieve.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smali.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smalltalk.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smarty.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snobol.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/solidity.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sourcepawn.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sparql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/squidconf.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/standard_ml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stas.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stylus.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/swift.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemd.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemverilog.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tablegen.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tal.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tasm.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcsh.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/termcap.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terminfo.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tex.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/thrift.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tradingview.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turing.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turtle.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/twig.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscript.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscriptcssdata.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscripthtmldata.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ucode.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v_shell.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vala.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vb_net.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/verilog.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhdl.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhs.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/viml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vue.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wdte.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webgpu_shading_language.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/whiley.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xorg.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yang.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/z80_assembly.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zed.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/genshi.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/go.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/haxe.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/html.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/http.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/lexers.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/mysql.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/php.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/raku.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/rst.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/svelte.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/typoscript.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/lexers/zed.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/mutators.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/pygments-lexers.txt delete mode 100644 vendor/github.com/alecthomas/chroma/v2/quick/quick.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/regexp.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/registry.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/remap.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/renovate.json5 delete mode 100644 vendor/github.com/alecthomas/chroma/v2/serialise.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/style.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/abap.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/algol.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/algol_nu.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/api.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/arduino.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/autumn.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/average.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/base16-snazzy.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/borland.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/bw.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/colorful.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/compat.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/doom-one.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/doom-one2.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/dracula.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/emacs.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/friendly.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/fruity.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/github.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/gruvbox.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/hr_high_contrast.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/hrdark.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/igor.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/lovelace.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/manni.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/modus-vivendi.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/monokai.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/monokailight.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/murphy.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/native.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/nord.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/onedark.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/onesenterprise.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/paraiso-dark.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/paraiso-light.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/pastie.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/perldoc.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/pygments.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/rainbow_dash.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-dawn.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-moon.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/rose-pine.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/rrt.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark256.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/swapoff.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/tango.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-day.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-moon.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-night.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-storm.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/trac.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/vim.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/vs.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/vulcan.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/witchhazel.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/xcode-dark.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/styles/xcode.xml delete mode 100644 vendor/github.com/alecthomas/chroma/v2/table.py delete mode 100644 vendor/github.com/alecthomas/chroma/v2/tokentype_enumer.go delete mode 100644 vendor/github.com/alecthomas/chroma/v2/types.go delete mode 100644 vendor/github.com/atotto/clipboard/.travis.yml delete mode 100644 vendor/github.com/atotto/clipboard/LICENSE delete mode 100644 vendor/github.com/atotto/clipboard/README.md delete mode 100644 vendor/github.com/atotto/clipboard/clipboard.go delete mode 100644 vendor/github.com/atotto/clipboard/clipboard_darwin.go delete mode 100644 vendor/github.com/atotto/clipboard/clipboard_plan9.go delete mode 100644 vendor/github.com/atotto/clipboard/clipboard_unix.go delete mode 100644 vendor/github.com/atotto/clipboard/clipboard_windows.go delete mode 100644 vendor/github.com/aymerick/douceur/LICENSE delete mode 100644 vendor/github.com/aymerick/douceur/css/declaration.go delete mode 100644 vendor/github.com/aymerick/douceur/css/rule.go delete mode 100644 vendor/github.com/aymerick/douceur/css/stylesheet.go delete mode 100644 vendor/github.com/aymerick/douceur/parser/parser.go delete mode 100644 vendor/github.com/beorn7/perks/LICENSE delete mode 100644 vendor/github.com/beorn7/perks/quantile/exampledata.txt delete mode 100644 vendor/github.com/beorn7/perks/quantile/stream.go delete mode 100644 vendor/github.com/catppuccin/go/.editorconfig delete mode 100644 vendor/github.com/catppuccin/go/.gitignore delete mode 100644 vendor/github.com/catppuccin/go/.goreleaser.yaml delete mode 100644 vendor/github.com/catppuccin/go/LICENSE delete mode 100644 vendor/github.com/catppuccin/go/README.md delete mode 100644 vendor/github.com/catppuccin/go/flake.lock delete mode 100644 vendor/github.com/catppuccin/go/flake.nix delete mode 100644 vendor/github.com/catppuccin/go/frappe.go delete mode 100644 vendor/github.com/catppuccin/go/go.tera delete mode 100644 vendor/github.com/catppuccin/go/latte.go delete mode 100644 vendor/github.com/catppuccin/go/macchiato.go delete mode 100644 vendor/github.com/catppuccin/go/main.go delete mode 100644 vendor/github.com/catppuccin/go/mocha.go delete mode 100644 vendor/github.com/catppuccin/go/renovate.json delete mode 100644 vendor/github.com/cenkalti/backoff/v4/.gitignore delete mode 100644 vendor/github.com/cenkalti/backoff/v4/LICENSE delete mode 100644 vendor/github.com/cenkalti/backoff/v4/README.md delete mode 100644 vendor/github.com/cenkalti/backoff/v4/backoff.go delete mode 100644 vendor/github.com/cenkalti/backoff/v4/context.go delete mode 100644 vendor/github.com/cenkalti/backoff/v4/exponential.go delete mode 100644 vendor/github.com/cenkalti/backoff/v4/retry.go delete mode 100644 vendor/github.com/cenkalti/backoff/v4/ticker.go delete mode 100644 vendor/github.com/cenkalti/backoff/v4/timer.go delete mode 100644 vendor/github.com/cenkalti/backoff/v4/tries.go delete mode 100644 vendor/github.com/cenkalti/backoff/v5/.gitignore delete mode 100644 vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md delete mode 100644 vendor/github.com/cenkalti/backoff/v5/LICENSE delete mode 100644 vendor/github.com/cenkalti/backoff/v5/README.md delete mode 100644 vendor/github.com/cenkalti/backoff/v5/backoff.go delete mode 100644 vendor/github.com/cenkalti/backoff/v5/error.go delete mode 100644 vendor/github.com/cenkalti/backoff/v5/exponential.go delete mode 100644 vendor/github.com/cenkalti/backoff/v5/retry.go delete mode 100644 vendor/github.com/cenkalti/backoff/v5/ticker.go delete mode 100644 vendor/github.com/cenkalti/backoff/v5/timer.go delete mode 100644 vendor/github.com/cespare/xxhash/v2/LICENSE.txt delete mode 100644 vendor/github.com/cespare/xxhash/v2/README.md delete mode 100644 vendor/github.com/cespare/xxhash/v2/testall.sh delete mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash.go delete mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s delete mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s delete mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash_asm.go delete mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash_other.go delete mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash_safe.go delete mode 100644 vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/LICENSE delete mode 100644 vendor/github.com/charmbracelet/bubbles/cursor/cursor.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/filepicker/filepicker.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/filepicker/hidden_unix.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/filepicker/hidden_windows.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/help/help.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/key/key.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/spinner/spinner.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/textarea/memoization/memoization.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/textarea/textarea.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/textinput/textinput.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/viewport/keymap.go delete mode 100644 vendor/github.com/charmbracelet/bubbles/viewport/viewport.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/.gitattributes delete mode 100644 vendor/github.com/charmbracelet/bubbletea/.gitignore delete mode 100644 vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml delete mode 100644 vendor/github.com/charmbracelet/bubbletea/.golangci.yml delete mode 100644 vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml delete mode 100644 vendor/github.com/charmbracelet/bubbletea/LICENSE delete mode 100644 vendor/github.com/charmbracelet/bubbletea/README.md delete mode 100644 vendor/github.com/charmbracelet/bubbletea/commands.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/exec.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/focus.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/inputreader_other.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/key.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/key_other.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/key_sequences.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/key_windows.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/logging.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/mouse.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/nil_renderer.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/options.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/renderer.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/screen.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/signals_unix.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/signals_windows.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/standard_renderer.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/tea.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/tea_init.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/tty.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/tty_unix.go delete mode 100644 vendor/github.com/charmbracelet/bubbletea/tty_windows.go delete mode 100644 vendor/github.com/charmbracelet/glamour/.editorconfig delete mode 100644 vendor/github.com/charmbracelet/glamour/.gitattributes delete mode 100644 vendor/github.com/charmbracelet/glamour/.gitignore delete mode 100644 vendor/github.com/charmbracelet/glamour/.golangci.yml delete mode 100644 vendor/github.com/charmbracelet/glamour/.goreleaser.yml delete mode 100644 vendor/github.com/charmbracelet/glamour/CONTRIBUTING.md delete mode 100644 vendor/github.com/charmbracelet/glamour/LICENSE delete mode 100644 vendor/github.com/charmbracelet/glamour/README.md delete mode 100644 vendor/github.com/charmbracelet/glamour/Taskfile.yml delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/ansi.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/baseelement.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/blockelement.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/blockstack.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/codeblock.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/codespan.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/context.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/elements.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/emphasis.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/heading.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/image.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/link.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/listitem.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/margin.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/paragraph.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/renderer.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/style.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/table.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/table_links.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/task.go delete mode 100644 vendor/github.com/charmbracelet/glamour/ansi/templatehelper.go delete mode 100644 vendor/github.com/charmbracelet/glamour/examples.sh delete mode 100644 vendor/github.com/charmbracelet/glamour/gallery.sh delete mode 100644 vendor/github.com/charmbracelet/glamour/glamour.go delete mode 100644 vendor/github.com/charmbracelet/glamour/internal/autolink/autolink.go delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/README.md delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/ascii.json delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/dark.json delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/dracula.go delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/dracula.json delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/light.json delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/notty.json delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/pink.json delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/styles.go delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/tokyo-night.go delete mode 100644 vendor/github.com/charmbracelet/glamour/styles/tokyo_night.json delete mode 100644 vendor/github.com/charmbracelet/huh/.gitattributes delete mode 100644 vendor/github.com/charmbracelet/huh/.gitignore delete mode 100644 vendor/github.com/charmbracelet/huh/.golangci.yml delete mode 100644 vendor/github.com/charmbracelet/huh/LICENSE delete mode 100644 vendor/github.com/charmbracelet/huh/Makefile delete mode 100644 vendor/github.com/charmbracelet/huh/README.md delete mode 100644 vendor/github.com/charmbracelet/huh/accessor.go delete mode 100644 vendor/github.com/charmbracelet/huh/clamp.go delete mode 100644 vendor/github.com/charmbracelet/huh/eval.go delete mode 100644 vendor/github.com/charmbracelet/huh/field_confirm.go delete mode 100644 vendor/github.com/charmbracelet/huh/field_filepicker.go delete mode 100644 vendor/github.com/charmbracelet/huh/field_input.go delete mode 100644 vendor/github.com/charmbracelet/huh/field_multiselect.go delete mode 100644 vendor/github.com/charmbracelet/huh/field_note.go delete mode 100644 vendor/github.com/charmbracelet/huh/field_select.go delete mode 100644 vendor/github.com/charmbracelet/huh/field_text.go delete mode 100644 vendor/github.com/charmbracelet/huh/form.go delete mode 100644 vendor/github.com/charmbracelet/huh/group.go delete mode 100644 vendor/github.com/charmbracelet/huh/huh.go delete mode 100644 vendor/github.com/charmbracelet/huh/internal/accessibility/accessibility.go delete mode 100644 vendor/github.com/charmbracelet/huh/internal/selector/selector.go delete mode 100644 vendor/github.com/charmbracelet/huh/keymap.go delete mode 100644 vendor/github.com/charmbracelet/huh/layout.go delete mode 100644 vendor/github.com/charmbracelet/huh/option.go delete mode 100644 vendor/github.com/charmbracelet/huh/run.go delete mode 100644 vendor/github.com/charmbracelet/huh/theme.go delete mode 100644 vendor/github.com/charmbracelet/huh/validate.go delete mode 100644 vendor/github.com/charmbracelet/huh/wrap.go delete mode 100644 vendor/github.com/charmbracelet/lipgloss/table/resizing.go delete mode 100644 vendor/github.com/charmbracelet/lipgloss/table/rows.go delete mode 100644 vendor/github.com/charmbracelet/lipgloss/table/table.go delete mode 100644 vendor/github.com/charmbracelet/lipgloss/table/util.go delete mode 100644 vendor/github.com/charmbracelet/x/exp/slice/LICENSE delete mode 100644 vendor/github.com/charmbracelet/x/exp/slice/slice.go delete mode 100644 vendor/github.com/charmbracelet/x/exp/strings/LICENSE delete mode 100644 vendor/github.com/charmbracelet/x/exp/strings/join.go delete mode 100644 vendor/github.com/cloudflare/circl/LICENSE delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/curve.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/doc.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/key.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x25519/table.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/curve.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/doc.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/key.go delete mode 100644 vendor/github.com/cloudflare/circl/dh/x448/table.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go delete mode 100644 vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/conv/conv.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/doc.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/hashes.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/rc.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/sha3.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/shake.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/xor.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go delete mode 100644 vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp25519/fp.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h delete mode 100644 vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.s delete mode 100644 vendor/github.com/cloudflare/circl/math/fp25519/fp_generic.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp448/fp.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h delete mode 100644 vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s delete mode 100644 vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go delete mode 100644 vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go delete mode 100644 vendor/github.com/cloudflare/circl/math/integer.go delete mode 100644 vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go delete mode 100644 vendor/github.com/cloudflare/circl/math/mlsbset/power.go delete mode 100644 vendor/github.com/cloudflare/circl/math/primes.go delete mode 100644 vendor/github.com/cloudflare/circl/math/wnaf.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/modular.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/mult.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/point.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed25519/tables.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed448/ed448.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/ed448/signapi.go delete mode 100644 vendor/github.com/cloudflare/circl/sign/sign.go delete mode 100644 vendor/github.com/crazy3lf/colorconv/LICENSE delete mode 100644 vendor/github.com/crazy3lf/colorconv/README.md delete mode 100644 vendor/github.com/crazy3lf/colorconv/colorconv.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/LICENSE delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/README.md delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/VERSION delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/doc.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/join.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/open_linux.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/openat_linux.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go delete mode 100644 vendor/github.com/cyphar/filepath-securejoin/vfs.go delete mode 100644 vendor/github.com/dennwc/varint/.gitignore delete mode 100644 vendor/github.com/dennwc/varint/.travis.yml delete mode 100644 vendor/github.com/dennwc/varint/LICENSE delete mode 100644 vendor/github.com/dennwc/varint/README.md delete mode 100644 vendor/github.com/dennwc/varint/proto.go delete mode 100644 vendor/github.com/dennwc/varint/varint.go delete mode 100644 vendor/github.com/dlclark/regexp2/.gitignore delete mode 100644 vendor/github.com/dlclark/regexp2/.travis.yml delete mode 100644 vendor/github.com/dlclark/regexp2/ATTRIB delete mode 100644 vendor/github.com/dlclark/regexp2/LICENSE delete mode 100644 vendor/github.com/dlclark/regexp2/README.md delete mode 100644 vendor/github.com/dlclark/regexp2/fastclock.go delete mode 100644 vendor/github.com/dlclark/regexp2/match.go delete mode 100644 vendor/github.com/dlclark/regexp2/regexp.go delete mode 100644 vendor/github.com/dlclark/regexp2/replace.go delete mode 100644 vendor/github.com/dlclark/regexp2/runner.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/charclass.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/code.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/escape.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/fuzz.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/parser.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/prefix.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/replacerdata.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/tree.go delete mode 100644 vendor/github.com/dlclark/regexp2/syntax/writer.go delete mode 100644 vendor/github.com/dlclark/regexp2/testoutput1 delete mode 100644 vendor/github.com/dustin/go-humanize/.travis.yml delete mode 100644 vendor/github.com/dustin/go-humanize/LICENSE delete mode 100644 vendor/github.com/dustin/go-humanize/README.markdown delete mode 100644 vendor/github.com/dustin/go-humanize/big.go delete mode 100644 vendor/github.com/dustin/go-humanize/bigbytes.go delete mode 100644 vendor/github.com/dustin/go-humanize/bytes.go delete mode 100644 vendor/github.com/dustin/go-humanize/comma.go delete mode 100644 vendor/github.com/dustin/go-humanize/commaf.go delete mode 100644 vendor/github.com/dustin/go-humanize/ftoa.go delete mode 100644 vendor/github.com/dustin/go-humanize/humanize.go delete mode 100644 vendor/github.com/dustin/go-humanize/number.go delete mode 100644 vendor/github.com/dustin/go-humanize/ordinals.go delete mode 100644 vendor/github.com/dustin/go-humanize/si.go delete mode 100644 vendor/github.com/dustin/go-humanize/times.go delete mode 100644 vendor/github.com/edsrzf/mmap-go/.gitignore delete mode 100644 vendor/github.com/edsrzf/mmap-go/LICENSE delete mode 100644 vendor/github.com/edsrzf/mmap-go/README.md delete mode 100644 vendor/github.com/edsrzf/mmap-go/mmap.go delete mode 100644 vendor/github.com/edsrzf/mmap-go/mmap_plan9.go delete mode 100644 vendor/github.com/edsrzf/mmap-go/mmap_unix.go delete mode 100644 vendor/github.com/edsrzf/mmap-go/mmap_wasm.go delete mode 100644 vendor/github.com/edsrzf/mmap-go/mmap_windows.go delete mode 100644 vendor/github.com/emirpasic/gods/LICENSE delete mode 100644 vendor/github.com/emirpasic/gods/containers/containers.go delete mode 100644 vendor/github.com/emirpasic/gods/containers/enumerable.go delete mode 100644 vendor/github.com/emirpasic/gods/containers/iterator.go delete mode 100644 vendor/github.com/emirpasic/gods/containers/serialization.go delete mode 100644 vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go delete mode 100644 vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go delete mode 100644 vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go delete mode 100644 vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go delete mode 100644 vendor/github.com/emirpasic/gods/lists/lists.go delete mode 100644 vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap.go delete mode 100644 vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go delete mode 100644 vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go delete mode 100644 vendor/github.com/emirpasic/gods/trees/trees.go delete mode 100644 vendor/github.com/emirpasic/gods/utils/comparator.go delete mode 100644 vendor/github.com/emirpasic/gods/utils/sort.go delete mode 100644 vendor/github.com/emirpasic/gods/utils/utils.go delete mode 100644 vendor/github.com/erikgeiser/coninput/.gitignore delete mode 100644 vendor/github.com/erikgeiser/coninput/.golangci.yml delete mode 100644 vendor/github.com/erikgeiser/coninput/LICENSE delete mode 100644 vendor/github.com/erikgeiser/coninput/README.md delete mode 100644 vendor/github.com/erikgeiser/coninput/keycodes.go delete mode 100644 vendor/github.com/erikgeiser/coninput/mode.go delete mode 100644 vendor/github.com/erikgeiser/coninput/read.go delete mode 100644 vendor/github.com/erikgeiser/coninput/records.go delete mode 100644 vendor/github.com/facette/natsort/LICENSE delete mode 100644 vendor/github.com/facette/natsort/README.md delete mode 100644 vendor/github.com/facette/natsort/natsort.go delete mode 100644 vendor/github.com/felixge/httpsnoop/.gitignore delete mode 100644 vendor/github.com/felixge/httpsnoop/LICENSE.txt delete mode 100644 vendor/github.com/felixge/httpsnoop/Makefile delete mode 100644 vendor/github.com/felixge/httpsnoop/README.md delete mode 100644 vendor/github.com/felixge/httpsnoop/capture_metrics.go delete mode 100644 vendor/github.com/felixge/httpsnoop/docs.go delete mode 100644 vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go delete mode 100644 vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go delete mode 100644 vendor/github.com/gen2brain/beeep/LICENSE delete mode 100644 vendor/github.com/gen2brain/beeep/README.md delete mode 100644 vendor/github.com/gen2brain/beeep/alert_darwin.go delete mode 100644 vendor/github.com/gen2brain/beeep/alert_js.go delete mode 100644 vendor/github.com/gen2brain/beeep/alert_unix.go delete mode 100644 vendor/github.com/gen2brain/beeep/alert_unsupported.go delete mode 100644 vendor/github.com/gen2brain/beeep/alert_windows.go delete mode 100644 vendor/github.com/gen2brain/beeep/beeep.go delete mode 100644 vendor/github.com/gen2brain/beeep/beep_darwin.go delete mode 100644 vendor/github.com/gen2brain/beeep/beep_js.go delete mode 100644 vendor/github.com/gen2brain/beeep/beep_unix.go delete mode 100644 vendor/github.com/gen2brain/beeep/beep_unsupported.go delete mode 100644 vendor/github.com/gen2brain/beeep/beep_windows.go delete mode 100644 vendor/github.com/gen2brain/beeep/notify_darwin.go delete mode 100644 vendor/github.com/gen2brain/beeep/notify_js.go delete mode 100644 vendor/github.com/gen2brain/beeep/notify_unix.go delete mode 100644 vendor/github.com/gen2brain/beeep/notify_unix_nodbus.go delete mode 100644 vendor/github.com/gen2brain/beeep/notify_unsupported.go delete mode 100644 vendor/github.com/gen2brain/beeep/notify_windows.go delete mode 100644 vendor/github.com/getlantern/context/.travis.yml delete mode 100644 vendor/github.com/getlantern/context/LICENSE delete mode 100644 vendor/github.com/getlantern/context/README.md delete mode 100644 vendor/github.com/getlantern/context/context.go delete mode 100644 vendor/github.com/getlantern/context/gotrack.go delete mode 100644 vendor/github.com/getlantern/errors/LICENSE delete mode 100644 vendor/github.com/getlantern/errors/errors.go delete mode 100644 vendor/github.com/getlantern/errors/hide.go delete mode 100644 vendor/github.com/getlantern/golog/.travis.yml delete mode 100644 vendor/github.com/getlantern/golog/LICENSE delete mode 100644 vendor/github.com/getlantern/golog/README.md delete mode 100644 vendor/github.com/getlantern/golog/golog.go delete mode 100644 vendor/github.com/getlantern/hex/LICENSE delete mode 100644 vendor/github.com/getlantern/hex/hex.go delete mode 100644 vendor/github.com/getlantern/hidden/LICENSE delete mode 100644 vendor/github.com/getlantern/hidden/hidden.go delete mode 100644 vendor/github.com/getlantern/ops/LICENSE delete mode 100644 vendor/github.com/getlantern/ops/ops.go delete mode 100644 vendor/github.com/getlantern/systray/.gitignore delete mode 100644 vendor/github.com/getlantern/systray/CHANGELOG.md delete mode 100644 vendor/github.com/getlantern/systray/LICENSE delete mode 100644 vendor/github.com/getlantern/systray/Makefile delete mode 100644 vendor/github.com/getlantern/systray/README.md delete mode 100644 vendor/github.com/getlantern/systray/systray.go delete mode 100644 vendor/github.com/getlantern/systray/systray.h delete mode 100644 vendor/github.com/getlantern/systray/systray_darwin.go delete mode 100644 vendor/github.com/getlantern/systray/systray_darwin.m delete mode 100644 vendor/github.com/getlantern/systray/systray_linux.c delete mode 100644 vendor/github.com/getlantern/systray/systray_linux.go delete mode 100644 vendor/github.com/getlantern/systray/systray_linux_appindicator.go delete mode 100644 vendor/github.com/getlantern/systray/systray_linux_ayatana.go delete mode 100644 vendor/github.com/getlantern/systray/systray_nonwindows.go delete mode 100644 vendor/github.com/getlantern/systray/systray_windows.go delete mode 100644 vendor/github.com/getlantern/systray/webview_example/webview.h delete mode 100644 vendor/github.com/go-git/gcfg/v2/.gitignore delete mode 100644 vendor/github.com/go-git/gcfg/v2/LICENSE delete mode 100644 vendor/github.com/go-git/gcfg/v2/Makefile delete mode 100644 vendor/github.com/go-git/gcfg/v2/README delete mode 100644 vendor/github.com/go-git/gcfg/v2/doc.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/errors.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/read.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/scanner/errors.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/scanner/scanner.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/set.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/token/position.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/token/serialize.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/token/token.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/types/bool.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/types/doc.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/types/enum.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/types/int.go delete mode 100644 vendor/github.com/go-git/gcfg/v2/types/scan.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/.gitignore delete mode 100644 vendor/github.com/go-git/go-billy/v6/.golangci.yaml delete mode 100644 vendor/github.com/go-git/go-billy/v6/LICENSE delete mode 100644 vendor/github.com/go-git/go-billy/v6/Makefile delete mode 100644 vendor/github.com/go-git/go-billy/v6/README.md delete mode 100644 vendor/github.com/go-git/go-billy/v6/fs.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/helper/chroot/chroot.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/helper/polyfill/polyfill.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/memfs/file.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/memfs/memory.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/memfs/memory_option.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/memfs/storage.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_bound.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_chroot.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_js.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_options.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_plan9.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_posix.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_wasip1.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/osfs/os_windows.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/util/glob.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/util/util.go delete mode 100644 vendor/github.com/go-git/go-billy/v6/util/walk.go delete mode 100644 vendor/github.com/go-git/go-git/v6/.gitignore delete mode 100644 vendor/github.com/go-git/go-git/v6/CODE_OF_CONDUCT.md delete mode 100644 vendor/github.com/go-git/go-git/v6/COMPATIBILITY.md delete mode 100644 vendor/github.com/go-git/go-git/v6/CONTRIBUTING.md delete mode 100644 vendor/github.com/go-git/go-git/v6/EXTENDING.md delete mode 100644 vendor/github.com/go-git/go-git/v6/LICENSE delete mode 100644 vendor/github.com/go-git/go-git/v6/Makefile delete mode 100644 vendor/github.com/go-git/go-git/v6/README.md delete mode 100644 vendor/github.com/go-git/go-git/v6/SECURITY.md delete mode 100644 vendor/github.com/go-git/go-git/v6/blame.go delete mode 100644 vendor/github.com/go-git/go-git/v6/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/config/branch.go delete mode 100644 vendor/github.com/go-git/go-git/v6/config/config.go delete mode 100644 vendor/github.com/go-git/go-git/v6/config/modules.go delete mode 100644 vendor/github.com/go-git/go-git/v6/config/refspec.go delete mode 100644 vendor/github.com/go-git/go-git/v6/config/url.go delete mode 100644 vendor/github.com/go-git/go-git/v6/crypto.go delete mode 100644 vendor/github.com/go-git/go-git/v6/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/path_util/path_util.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/reference/refs.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/reference/sort.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/repository/refs.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/revision/parser.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/revision/scanner.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/revision/token.go delete mode 100644 vendor/github.com/go-git/go-git/v6/internal/url/url.go delete mode 100644 vendor/github.com/go-git/go-git/v6/object_walker.go delete mode 100644 vendor/github.com/go-git/go-git/v6/options.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/cache/buffer_lru.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/cache/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/cache/object_lru.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/color/color.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/error.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/filemode/filemode.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/config/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/config/decoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/config/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/config/encoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/config/format.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/config/option.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/config/section.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/diff/colorconfig.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/diff/patch.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/diff/unified_encoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/dir.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/matcher.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/pattern.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/decoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/encoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/idxfile.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/writer.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/index/decoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/index/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/index/encoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/index/index.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/index/match.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/reader.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/writer.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_index.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_selector.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/diff_delta.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/encoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/error.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/fsobject.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/object_pack.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_iter.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_options.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_cache.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_options.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_types.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/patch_delta.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_options.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_reader.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/types.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/error.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/length.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/pktline.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/scanner.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/sync.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/hash.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/hash/hash.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/hasher.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/memory.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/blob.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/change.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/change_adaptor.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/commit.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs_filtered.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_ctime.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_limit.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_path.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/difftree.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/file.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/merge_base.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/object.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/patch.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/rename.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/signature.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/tag.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/tree.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/object/treenoder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/objectid.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_decode.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_encode.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/capability.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/list.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/filter.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/gitproto.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/inforefs.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/packp.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/pushopts.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/report_status.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/shallowupd.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/demux.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/muxer.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/smart.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/srvresp.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_decode.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_encode.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_decode.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_encode.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/uphav.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/protocol/version.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/reference.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/revision.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/revlist/revlist.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/storer/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/storer/index.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/storer/object.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/storer/reference.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/storer/shallow.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/storer/storer.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/tag.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/fetch.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/file/client.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/git/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/http/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/http/dumb.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/http/transport.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/loader.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/mocks.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/negotiate.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/pack.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/push.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/receive_pack.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/registry.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/serve.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/serverinfo.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/service.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/auth_method.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/knownhosts/knownhosts.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/pageant_windows.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent_windows.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/transport.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/upload_pack.go delete mode 100644 vendor/github.com/go-git/go-git/v6/plumbing/transport/version.go delete mode 100644 vendor/github.com/go-git/go-git/v6/prune.go delete mode 100644 vendor/github.com/go-git/go-git/v6/remote.go delete mode 100644 vendor/github.com/go-git/go-git/v6/repository.go delete mode 100644 vendor/github.com/go-git/go-git/v6/signer.go delete mode 100644 vendor/github.com/go-git/go-git/v6/status.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/config.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/deltaobject.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_setref.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/reader.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/repository_filesystem.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/writers.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/index.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/module.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/object.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/object_iter.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/reference.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/shallow.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/filesystem/storage.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/memory/storage.go delete mode 100644 vendor/github.com/go-git/go-git/v6/storage/storer.go delete mode 100644 vendor/github.com/go-git/go-git/v6/submodule.go delete mode 100644 vendor/github.com/go-git/go-git/v6/transport.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/binary/read.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/binary/write.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/convert/eol.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/convert/stat.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/diff/diff.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/ioutil/common.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/ioutil/context.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/ioutil/sync.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/change.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/difftree.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/doc.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/doubleiter.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/filesystem/node.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/index/node.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/internal/frame/frame.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/iter.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/noder.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/path.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/sync/bufio.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/sync/bytes.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/sync/zlib.go delete mode 100644 vendor/github.com/go-git/go-git/v6/utils/trace/trace.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_bsd.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_commit.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_js.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_linux.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_plan9.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_status.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_unix_other.go delete mode 100644 vendor/github.com/go-git/go-git/v6/worktree_windows.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/.gitignore delete mode 100644 vendor/github.com/go-jose/go-jose/v4/.golangci.yml delete mode 100644 vendor/github.com/go-jose/go-jose/v4/.travis.yml delete mode 100644 vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md delete mode 100644 vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md delete mode 100644 vendor/github.com/go-jose/go-jose/v4/LICENSE delete mode 100644 vendor/github.com/go-jose/go-jose/v4/README.md delete mode 100644 vendor/github.com/go-jose/go-jose/v4/SECURITY.md delete mode 100644 vendor/github.com/go-jose/go-jose/v4/asymmetric.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/crypter.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/doc.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/encoding.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/LICENSE delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/README.md delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/decode.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/encode.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/indent.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/scanner.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/stream.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/json/tags.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/jwe.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/jwk.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/jws.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/opaque.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/shared.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/signing.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/symmetric.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/symmetric_go124.go delete mode 100644 vendor/github.com/go-jose/go-jose/v4/symmetric_legacy.go delete mode 100644 vendor/github.com/go-logr/logr/.golangci.yaml delete mode 100644 vendor/github.com/go-logr/logr/CHANGELOG.md delete mode 100644 vendor/github.com/go-logr/logr/CONTRIBUTING.md delete mode 100644 vendor/github.com/go-logr/logr/LICENSE delete mode 100644 vendor/github.com/go-logr/logr/README.md delete mode 100644 vendor/github.com/go-logr/logr/SECURITY.md delete mode 100644 vendor/github.com/go-logr/logr/context.go delete mode 100644 vendor/github.com/go-logr/logr/context_noslog.go delete mode 100644 vendor/github.com/go-logr/logr/context_slog.go delete mode 100644 vendor/github.com/go-logr/logr/discard.go delete mode 100644 vendor/github.com/go-logr/logr/funcr/funcr.go delete mode 100644 vendor/github.com/go-logr/logr/funcr/slogsink.go delete mode 100644 vendor/github.com/go-logr/logr/logr.go delete mode 100644 vendor/github.com/go-logr/logr/sloghandler.go delete mode 100644 vendor/github.com/go-logr/logr/slogr.go delete mode 100644 vendor/github.com/go-logr/logr/slogsink.go delete mode 100644 vendor/github.com/go-logr/stdr/LICENSE delete mode 100644 vendor/github.com/go-logr/stdr/README.md delete mode 100644 vendor/github.com/go-logr/stdr/stdr.go delete mode 100644 vendor/github.com/go-stack/stack/.travis.yml delete mode 100644 vendor/github.com/go-stack/stack/LICENSE.md delete mode 100644 vendor/github.com/go-stack/stack/README.md delete mode 100644 vendor/github.com/go-stack/stack/stack.go delete mode 100644 vendor/github.com/go-toast/toast/.gitignore delete mode 100644 vendor/github.com/go-toast/toast/LICENSE delete mode 100644 vendor/github.com/go-toast/toast/readme.md delete mode 100644 vendor/github.com/go-toast/toast/screenshot-action-centre.png delete mode 100644 vendor/github.com/go-toast/toast/screenshot-cli.png delete mode 100644 vendor/github.com/go-toast/toast/screenshot-toast.png delete mode 100644 vendor/github.com/go-toast/toast/toast.go delete mode 100644 vendor/github.com/godbus/dbus/v5/CONTRIBUTING.md delete mode 100644 vendor/github.com/godbus/dbus/v5/LICENSE delete mode 100644 vendor/github.com/godbus/dbus/v5/MAINTAINERS delete mode 100644 vendor/github.com/godbus/dbus/v5/README.md delete mode 100644 vendor/github.com/godbus/dbus/v5/auth.go delete mode 100644 vendor/github.com/godbus/dbus/v5/auth_anonymous.go delete mode 100644 vendor/github.com/godbus/dbus/v5/auth_external.go delete mode 100644 vendor/github.com/godbus/dbus/v5/auth_sha1.go delete mode 100644 vendor/github.com/godbus/dbus/v5/call.go delete mode 100644 vendor/github.com/godbus/dbus/v5/conn.go delete mode 100644 vendor/github.com/godbus/dbus/v5/conn_darwin.go delete mode 100644 vendor/github.com/godbus/dbus/v5/conn_other.go delete mode 100644 vendor/github.com/godbus/dbus/v5/conn_unix.go delete mode 100644 vendor/github.com/godbus/dbus/v5/conn_windows.go delete mode 100644 vendor/github.com/godbus/dbus/v5/dbus.go delete mode 100644 vendor/github.com/godbus/dbus/v5/decoder.go delete mode 100644 vendor/github.com/godbus/dbus/v5/default_handler.go delete mode 100644 vendor/github.com/godbus/dbus/v5/doc.go delete mode 100644 vendor/github.com/godbus/dbus/v5/encoder.go delete mode 100644 vendor/github.com/godbus/dbus/v5/escape.go delete mode 100644 vendor/github.com/godbus/dbus/v5/export.go delete mode 100644 vendor/github.com/godbus/dbus/v5/homedir.go delete mode 100644 vendor/github.com/godbus/dbus/v5/match.go delete mode 100644 vendor/github.com/godbus/dbus/v5/message.go delete mode 100644 vendor/github.com/godbus/dbus/v5/object.go delete mode 100644 vendor/github.com/godbus/dbus/v5/sequence.go delete mode 100644 vendor/github.com/godbus/dbus/v5/sequential_handler.go delete mode 100644 vendor/github.com/godbus/dbus/v5/server_interfaces.go delete mode 100644 vendor/github.com/godbus/dbus/v5/sig.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_darwin.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_generic.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_tcp.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_unix.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_dragonfly.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_linux.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_openbsd.go delete mode 100644 vendor/github.com/godbus/dbus/v5/transport_zos.go delete mode 100644 vendor/github.com/godbus/dbus/v5/variant.go delete mode 100644 vendor/github.com/godbus/dbus/v5/variant_lexer.go delete mode 100644 vendor/github.com/godbus/dbus/v5/variant_parser.go delete mode 100644 vendor/github.com/gogo/protobuf/AUTHORS delete mode 100644 vendor/github.com/gogo/protobuf/CONTRIBUTORS delete mode 100644 vendor/github.com/gogo/protobuf/LICENSE delete mode 100644 vendor/github.com/gogo/protobuf/gogoproto/Makefile delete mode 100644 vendor/github.com/gogo/protobuf/gogoproto/doc.go delete mode 100644 vendor/github.com/gogo/protobuf/gogoproto/gogo.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/gogoproto/gogo.pb.golden delete mode 100644 vendor/github.com/gogo/protobuf/gogoproto/gogo.proto delete mode 100644 vendor/github.com/gogo/protobuf/gogoproto/helper.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/Makefile delete mode 100644 vendor/github.com/gogo/protobuf/proto/clone.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/custom_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/decode.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/deprecated.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/discard.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/duration.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/duration_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/encode.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/encode_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/equal.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/extensions.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/extensions_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/lib.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/lib_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/message_set.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_reflect.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_reflect_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_unsafe.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/pointer_unsafe_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/properties.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/properties_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/skip_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/table_marshal.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/table_marshal_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/table_merge.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/table_unmarshal.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/table_unmarshal_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/text.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/text_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/text_parser.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/timestamp.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/timestamp_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/wrappers.go delete mode 100644 vendor/github.com/gogo/protobuf/proto/wrappers_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/Makefile delete mode 100644 vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.go delete mode 100644 vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/descriptor_gostring.gen.go delete mode 100644 vendor/github.com/gogo/protobuf/protoc-gen-gogo/descriptor/helper.go delete mode 100644 vendor/github.com/gogo/protobuf/sortkeys/sortkeys.go delete mode 100644 vendor/github.com/gogo/protobuf/types/any.go delete mode 100644 vendor/github.com/gogo/protobuf/types/any.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/api.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/doc.go delete mode 100644 vendor/github.com/gogo/protobuf/types/duration.go delete mode 100644 vendor/github.com/gogo/protobuf/types/duration.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/duration_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/types/empty.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/field_mask.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/protosize.go delete mode 100644 vendor/github.com/gogo/protobuf/types/source_context.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/struct.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/timestamp.go delete mode 100644 vendor/github.com/gogo/protobuf/types/timestamp.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/timestamp_gogo.go delete mode 100644 vendor/github.com/gogo/protobuf/types/type.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/wrappers.pb.go delete mode 100644 vendor/github.com/gogo/protobuf/types/wrappers_gogo.go delete mode 100644 vendor/github.com/golang/groupcache/LICENSE delete mode 100644 vendor/github.com/golang/groupcache/lru/lru.go delete mode 100644 vendor/github.com/google/uuid/CHANGELOG.md delete mode 100644 vendor/github.com/google/uuid/CONTRIBUTING.md delete mode 100644 vendor/github.com/google/uuid/CONTRIBUTORS delete mode 100644 vendor/github.com/google/uuid/LICENSE delete mode 100644 vendor/github.com/google/uuid/README.md delete mode 100644 vendor/github.com/google/uuid/dce.go delete mode 100644 vendor/github.com/google/uuid/doc.go delete mode 100644 vendor/github.com/google/uuid/hash.go delete mode 100644 vendor/github.com/google/uuid/marshal.go delete mode 100644 vendor/github.com/google/uuid/node.go delete mode 100644 vendor/github.com/google/uuid/node_js.go delete mode 100644 vendor/github.com/google/uuid/node_net.go delete mode 100644 vendor/github.com/google/uuid/null.go delete mode 100644 vendor/github.com/google/uuid/sql.go delete mode 100644 vendor/github.com/google/uuid/time.go delete mode 100644 vendor/github.com/google/uuid/util.go delete mode 100644 vendor/github.com/google/uuid/uuid.go delete mode 100644 vendor/github.com/google/uuid/version1.go delete mode 100644 vendor/github.com/google/uuid/version4.go delete mode 100644 vendor/github.com/google/uuid/version6.go delete mode 100644 vendor/github.com/google/uuid/version7.go delete mode 100644 vendor/github.com/gorilla/css/LICENSE delete mode 100644 vendor/github.com/gorilla/css/scanner/doc.go delete mode 100644 vendor/github.com/gorilla/css/scanner/scanner.go delete mode 100644 vendor/github.com/grafana/regexp/.gitignore delete mode 100644 vendor/github.com/grafana/regexp/LICENSE delete mode 100644 vendor/github.com/grafana/regexp/README.md delete mode 100644 vendor/github.com/grafana/regexp/backtrack.go delete mode 100644 vendor/github.com/grafana/regexp/exec.go delete mode 100644 vendor/github.com/grafana/regexp/onepass.go delete mode 100644 vendor/github.com/grafana/regexp/regexp.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/compile.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/doc.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/make_perl_groups.pl delete mode 100644 vendor/github.com/grafana/regexp/syntax/op_string.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/parse.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/perl_groups.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/prog.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/regexp.go delete mode 100644 vendor/github.com/grafana/regexp/syntax/simplify.go delete mode 100644 vendor/github.com/jpillora/backoff/LICENSE delete mode 100644 vendor/github.com/jpillora/backoff/README.md delete mode 100644 vendor/github.com/jpillora/backoff/backoff.go delete mode 100644 vendor/github.com/kardianos/service/.gitignore delete mode 100644 vendor/github.com/kardianos/service/.travis.yml delete mode 100644 vendor/github.com/kardianos/service/LICENSE delete mode 100644 vendor/github.com/kardianos/service/README.md delete mode 100644 vendor/github.com/kardianos/service/appveyor.yml delete mode 100644 vendor/github.com/kardianos/service/console.go delete mode 100644 vendor/github.com/kardianos/service/linux-test-su.sh delete mode 100644 vendor/github.com/kardianos/service/service.go delete mode 100644 vendor/github.com/kardianos/service/service_aix.go delete mode 100644 vendor/github.com/kardianos/service/service_darwin.go delete mode 100644 vendor/github.com/kardianos/service/service_freebsd.go delete mode 100644 vendor/github.com/kardianos/service/service_go1.8.go delete mode 100644 vendor/github.com/kardianos/service/service_linux.go delete mode 100644 vendor/github.com/kardianos/service/service_openrc_linux.go delete mode 100644 vendor/github.com/kardianos/service/service_solaris.go delete mode 100644 vendor/github.com/kardianos/service/service_systemd_linux.go delete mode 100644 vendor/github.com/kardianos/service/service_sysv_linux.go delete mode 100644 vendor/github.com/kardianos/service/service_unix.go delete mode 100644 vendor/github.com/kardianos/service/service_upstart_linux.go delete mode 100644 vendor/github.com/kardianos/service/service_windows.go delete mode 100644 vendor/github.com/kardianos/service/version.go delete mode 100644 vendor/github.com/kevinburke/ssh_config/.gitignore delete mode 100644 vendor/github.com/kevinburke/ssh_config/.mailmap delete mode 100644 vendor/github.com/kevinburke/ssh_config/AUTHORS.txt delete mode 100644 vendor/github.com/kevinburke/ssh_config/CHANGELOG.md delete mode 100644 vendor/github.com/kevinburke/ssh_config/LICENSE delete mode 100644 vendor/github.com/kevinburke/ssh_config/Makefile delete mode 100644 vendor/github.com/kevinburke/ssh_config/README.md delete mode 100644 vendor/github.com/kevinburke/ssh_config/config.go delete mode 100644 vendor/github.com/kevinburke/ssh_config/lexer.go delete mode 100644 vendor/github.com/kevinburke/ssh_config/parser.go delete mode 100644 vendor/github.com/kevinburke/ssh_config/position.go delete mode 100644 vendor/github.com/kevinburke/ssh_config/token.go delete mode 100644 vendor/github.com/kevinburke/ssh_config/validators.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/.gitignore delete mode 100644 vendor/github.com/klauspost/cpuid/v2/.goreleaser.yml delete mode 100644 vendor/github.com/klauspost/cpuid/v2/CONTRIBUTING.txt delete mode 100644 vendor/github.com/klauspost/cpuid/v2/LICENSE delete mode 100644 vendor/github.com/klauspost/cpuid/v2/README.md delete mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_386.s delete mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_amd64.s delete mode 100644 vendor/github.com/klauspost/cpuid/v2/cpuid_arm64.s delete mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_arm64.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_ref.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/detect_x86.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/featureid_string.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/os_darwin_arm64.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/os_linux_arm64.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/os_other_arm64.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/os_safe_linux_arm64.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/os_unsafe_linux_arm64.go delete mode 100644 vendor/github.com/klauspost/cpuid/v2/test-architectures.sh delete mode 100644 vendor/github.com/lrstanley/bubblezone/.editorconfig delete mode 100644 vendor/github.com/lrstanley/bubblezone/.gitignore delete mode 100644 vendor/github.com/lrstanley/bubblezone/.golangci.yml delete mode 100644 vendor/github.com/lrstanley/bubblezone/LICENSE delete mode 100644 vendor/github.com/lrstanley/bubblezone/Makefile delete mode 100644 vendor/github.com/lrstanley/bubblezone/README.md delete mode 100644 vendor/github.com/lrstanley/bubblezone/manager.go delete mode 100644 vendor/github.com/lrstanley/bubblezone/manager_global.go delete mode 100644 vendor/github.com/lrstanley/bubblezone/messages.go delete mode 100644 vendor/github.com/lrstanley/bubblezone/scanner.go delete mode 100644 vendor/github.com/lrstanley/bubblezone/zoneinfo.go delete mode 100644 vendor/github.com/matoous/go-nanoid/.gitignore delete mode 100644 vendor/github.com/matoous/go-nanoid/.goreleaser.yml delete mode 100644 vendor/github.com/matoous/go-nanoid/LICENSE delete mode 100644 vendor/github.com/matoous/go-nanoid/Makefile delete mode 100644 vendor/github.com/matoous/go-nanoid/README.md delete mode 100644 vendor/github.com/matoous/go-nanoid/gonanoid.go delete mode 100644 vendor/github.com/mattn/go-localereader/LICENSE delete mode 100644 vendor/github.com/mattn/go-localereader/README.md delete mode 100644 vendor/github.com/mattn/go-localereader/localereader.go delete mode 100644 vendor/github.com/mattn/go-localereader/localereader_unix.go delete mode 100644 vendor/github.com/mattn/go-localereader/localereader_windows.go delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/CONTRIBUTING.md delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/CREDITS.md delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/LICENSE.md delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/README.md delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/SECURITY.md delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/css/handlers.go delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/doc.go delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/helpers.go delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/policies.go delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/policy.go delete mode 100644 vendor/github.com/microcosm-cc/bluemonday/sanitize.go delete mode 100644 vendor/github.com/minitape/api/go/svc/alert/v1/alertv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/alert/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/auth/v1/authv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/auth/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/dashboard/v1/dashboardv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/dashboard/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/feature/v1/featurev1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/feature/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/ingest/v1/ingestv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/ingest/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/localhost/v1/localhostv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/localhost/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/organization/v1/organizationv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/organization/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/product/v1/productv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/product/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/project/v1/projectv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/project/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/query/v1/queryv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/query/v1/queryv1connect/trace_service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/query/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/query/v1/trace_service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/token/v1/service.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/token/v1/tokenv1connect/service.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/user/v1/service_private.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/user/v1/service_public.pb.go delete mode 100644 vendor/github.com/minitape/api/go/svc/user/v1/userv1connect/service_private.connect.go delete mode 100644 vendor/github.com/minitape/api/go/svc/user/v1/userv1connect/service_public.connect.go delete mode 100644 vendor/github.com/mitchellh/hashstructure/v2/LICENSE delete mode 100644 vendor/github.com/mitchellh/hashstructure/v2/README.md delete mode 100644 vendor/github.com/mitchellh/hashstructure/v2/errors.go delete mode 100644 vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go delete mode 100644 vendor/github.com/mitchellh/hashstructure/v2/include.go delete mode 100644 vendor/github.com/muesli/ansi/.gitignore delete mode 100644 vendor/github.com/muesli/ansi/.golangci.yml delete mode 100644 vendor/github.com/muesli/ansi/LICENSE delete mode 100644 vendor/github.com/muesli/ansi/README.md delete mode 100644 vendor/github.com/muesli/ansi/ansi.go delete mode 100644 vendor/github.com/muesli/ansi/buffer.go delete mode 100644 vendor/github.com/muesli/ansi/compressor/writer.go delete mode 100644 vendor/github.com/muesli/ansi/writer.go delete mode 100644 vendor/github.com/muesli/cancelreader/.gitignore delete mode 100644 vendor/github.com/muesli/cancelreader/.golangci-soft.yml delete mode 100644 vendor/github.com/muesli/cancelreader/.golangci.yml delete mode 100644 vendor/github.com/muesli/cancelreader/LICENSE delete mode 100644 vendor/github.com/muesli/cancelreader/README.md delete mode 100644 vendor/github.com/muesli/cancelreader/cancelreader.go delete mode 100644 vendor/github.com/muesli/cancelreader/cancelreader_bsd.go delete mode 100644 vendor/github.com/muesli/cancelreader/cancelreader_default.go delete mode 100644 vendor/github.com/muesli/cancelreader/cancelreader_linux.go delete mode 100644 vendor/github.com/muesli/cancelreader/cancelreader_select.go delete mode 100644 vendor/github.com/muesli/cancelreader/cancelreader_unix.go delete mode 100644 vendor/github.com/muesli/cancelreader/cancelreader_windows.go delete mode 100644 vendor/github.com/muesli/reflow/LICENSE delete mode 100644 vendor/github.com/muesli/reflow/ansi/ansi.go delete mode 100644 vendor/github.com/muesli/reflow/ansi/buffer.go delete mode 100644 vendor/github.com/muesli/reflow/ansi/writer.go delete mode 100644 vendor/github.com/muesli/reflow/indent/indent.go delete mode 100644 vendor/github.com/muesli/reflow/padding/padding.go delete mode 100644 vendor/github.com/muesli/reflow/wordwrap/wordwrap.go delete mode 100644 vendor/github.com/muhlemmer/gu/LICENSE delete mode 100644 vendor/github.com/muhlemmer/gu/README.md delete mode 100644 vendor/github.com/muhlemmer/gu/gu.go delete mode 100644 vendor/github.com/muhlemmer/gu/map.go delete mode 100644 vendor/github.com/muhlemmer/gu/pointer.go delete mode 100644 vendor/github.com/muhlemmer/gu/slice.go delete mode 100644 vendor/github.com/munnerz/goautoneg/LICENSE delete mode 100644 vendor/github.com/munnerz/goautoneg/Makefile delete mode 100644 vendor/github.com/munnerz/goautoneg/README.txt delete mode 100644 vendor/github.com/munnerz/goautoneg/autoneg.go delete mode 100644 vendor/github.com/mwitkow/go-conntrack/.gitignore delete mode 100644 vendor/github.com/mwitkow/go-conntrack/.travis.yml delete mode 100644 vendor/github.com/mwitkow/go-conntrack/LICENSE delete mode 100644 vendor/github.com/mwitkow/go-conntrack/README.md delete mode 100644 vendor/github.com/mwitkow/go-conntrack/dialer_reporter.go delete mode 100644 vendor/github.com/mwitkow/go-conntrack/dialer_wrapper.go delete mode 100644 vendor/github.com/mwitkow/go-conntrack/listener_reporter.go delete mode 100644 vendor/github.com/mwitkow/go-conntrack/listener_wrapper.go delete mode 100644 vendor/github.com/nu7hatch/gouuid/.gitignore delete mode 100644 vendor/github.com/nu7hatch/gouuid/COPYING delete mode 100644 vendor/github.com/nu7hatch/gouuid/README.md delete mode 100644 vendor/github.com/nu7hatch/gouuid/uuid.go delete mode 100644 vendor/github.com/oxtoacart/bpool/LICENSE delete mode 100644 vendor/github.com/oxtoacart/bpool/README.md delete mode 100644 vendor/github.com/oxtoacart/bpool/bpool.go delete mode 100644 vendor/github.com/oxtoacart/bpool/bufferpool.go delete mode 100644 vendor/github.com/oxtoacart/bpool/bytepool.go delete mode 100644 vendor/github.com/oxtoacart/bpool/byteslice.go delete mode 100644 vendor/github.com/oxtoacart/bpool/sizedbufferpool.go delete mode 100644 vendor/github.com/perses/perses/LICENSE delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/auth.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/entity.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/migrate.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/display.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/duration.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/jsonref.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/plugin.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/reflect.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/regexp.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/url.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/common/validate.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/dashboard.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/dashboard/layout.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/dashboard/variable.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/datasource.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/ephemeraldashboard.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/folder.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/health.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/kind.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/metadata.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/partial.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/plugin.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/plugin/plugin.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/project.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/public_secret.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/public_user.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/role.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/role/action.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/role/permission.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/role/scope.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/rolebinding.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/secret.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/secret/authorization.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/secret/basic_auth.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/secret/oauth.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/secret/secret.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/secret/tls_config.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/user.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/variable.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/variable/list.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/variable/text.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/variable/variable.go delete mode 100644 vendor/github.com/perses/perses/pkg/model/api/v1/view.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/Dockerfile.arm delete mode 100644 vendor/github.com/pjbgf/sha1cd/Dockerfile.arm64 delete mode 100644 vendor/github.com/pjbgf/sha1cd/LICENSE delete mode 100644 vendor/github.com/pjbgf/sha1cd/Makefile delete mode 100644 vendor/github.com/pjbgf/sha1cd/README.md delete mode 100644 vendor/github.com/pjbgf/sha1cd/cgo/sha1.h delete mode 100644 vendor/github.com/pjbgf/sha1cd/cgo/ubc_check.h delete mode 100644 vendor/github.com/pjbgf/sha1cd/detection.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/internal/const.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/sha1cd.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/sha1cdblock_amd64.s delete mode 100644 vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/sha1cdblock_arm64.s delete mode 100644 vendor/github.com/pjbgf/sha1cd/sha1cdblock_generic.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/sha1cdblock_noasm.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/ubc/const.go delete mode 100644 vendor/github.com/pjbgf/sha1cd/ubc/ubc.go delete mode 100644 vendor/github.com/pkg/browser/LICENSE delete mode 100644 vendor/github.com/pkg/browser/README.md delete mode 100644 vendor/github.com/pkg/browser/browser.go delete mode 100644 vendor/github.com/pkg/browser/browser_darwin.go delete mode 100644 vendor/github.com/pkg/browser/browser_freebsd.go delete mode 100644 vendor/github.com/pkg/browser/browser_linux.go delete mode 100644 vendor/github.com/pkg/browser/browser_netbsd.go delete mode 100644 vendor/github.com/pkg/browser/browser_openbsd.go delete mode 100644 vendor/github.com/pkg/browser/browser_unsupported.go delete mode 100644 vendor/github.com/pkg/browser/browser_windows.go delete mode 100644 vendor/github.com/prometheus/client_golang/LICENSE delete mode 100644 vendor/github.com/prometheus/client_golang/NOTICE delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/.gitignore delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/README.md delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/build_info_collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/collectorfunc.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/counter.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/desc.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/doc.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/fnv.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/gauge.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/get_pid.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/histogram.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/labels.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/metric.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/num_threads.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/observer.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_darwin.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.c delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_cgo_darwin.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_mem_nocgo_darwin.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_not_supported.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_procfsenabled.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/registry.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/summary.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/timer.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/untyped.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/value.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/vec.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/vnext.go delete mode 100644 vendor/github.com/prometheus/client_golang/prometheus/wrap.go delete mode 100644 vendor/github.com/prometheus/client_model/LICENSE delete mode 100644 vendor/github.com/prometheus/client_model/NOTICE delete mode 100644 vendor/github.com/prometheus/client_model/go/metrics.pb.go delete mode 100644 vendor/github.com/prometheus/common/LICENSE delete mode 100644 vendor/github.com/prometheus/common/NOTICE delete mode 100644 vendor/github.com/prometheus/common/config/config.go delete mode 100644 vendor/github.com/prometheus/common/config/headers.go delete mode 100644 vendor/github.com/prometheus/common/config/http_config.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/decode.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/encode.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/expfmt.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/fuzz.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/openmetrics_create.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/text_create.go delete mode 100644 vendor/github.com/prometheus/common/expfmt/text_parse.go delete mode 100644 vendor/github.com/prometheus/common/helpers/templates/time.go delete mode 100644 vendor/github.com/prometheus/common/model/alert.go delete mode 100644 vendor/github.com/prometheus/common/model/fingerprinting.go delete mode 100644 vendor/github.com/prometheus/common/model/fnv.go delete mode 100644 vendor/github.com/prometheus/common/model/labels.go delete mode 100644 vendor/github.com/prometheus/common/model/labelset.go delete mode 100644 vendor/github.com/prometheus/common/model/labelset_string.go delete mode 100644 vendor/github.com/prometheus/common/model/metadata.go delete mode 100644 vendor/github.com/prometheus/common/model/metric.go delete mode 100644 vendor/github.com/prometheus/common/model/model.go delete mode 100644 vendor/github.com/prometheus/common/model/signature.go delete mode 100644 vendor/github.com/prometheus/common/model/silence.go delete mode 100644 vendor/github.com/prometheus/common/model/time.go delete mode 100644 vendor/github.com/prometheus/common/model/value.go delete mode 100644 vendor/github.com/prometheus/common/model/value_float.go delete mode 100644 vendor/github.com/prometheus/common/model/value_histogram.go delete mode 100644 vendor/github.com/prometheus/common/model/value_type.go delete mode 100644 vendor/github.com/prometheus/common/promslog/slog.go delete mode 100644 vendor/github.com/prometheus/procfs/.gitignore delete mode 100644 vendor/github.com/prometheus/procfs/.golangci.yml delete mode 100644 vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md delete mode 100644 vendor/github.com/prometheus/procfs/CONTRIBUTING.md delete mode 100644 vendor/github.com/prometheus/procfs/LICENSE delete mode 100644 vendor/github.com/prometheus/procfs/MAINTAINERS.md delete mode 100644 vendor/github.com/prometheus/procfs/Makefile delete mode 100644 vendor/github.com/prometheus/procfs/Makefile.common delete mode 100644 vendor/github.com/prometheus/procfs/NOTICE delete mode 100644 vendor/github.com/prometheus/procfs/README.md delete mode 100644 vendor/github.com/prometheus/procfs/SECURITY.md delete mode 100644 vendor/github.com/prometheus/procfs/arp.go delete mode 100644 vendor/github.com/prometheus/procfs/buddyinfo.go delete mode 100644 vendor/github.com/prometheus/procfs/cmdline.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_armx.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_loong64.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_others.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_s390x.go delete mode 100644 vendor/github.com/prometheus/procfs/cpuinfo_x86.go delete mode 100644 vendor/github.com/prometheus/procfs/crypto.go delete mode 100644 vendor/github.com/prometheus/procfs/doc.go delete mode 100644 vendor/github.com/prometheus/procfs/fs.go delete mode 100644 vendor/github.com/prometheus/procfs/fs_statfs_notype.go delete mode 100644 vendor/github.com/prometheus/procfs/fs_statfs_type.go delete mode 100644 vendor/github.com/prometheus/procfs/fscache.go delete mode 100644 vendor/github.com/prometheus/procfs/internal/fs/fs.go delete mode 100644 vendor/github.com/prometheus/procfs/internal/util/parse.go delete mode 100644 vendor/github.com/prometheus/procfs/internal/util/readfile.go delete mode 100644 vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go delete mode 100644 vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go delete mode 100644 vendor/github.com/prometheus/procfs/internal/util/valueparser.go delete mode 100644 vendor/github.com/prometheus/procfs/ipvs.go delete mode 100644 vendor/github.com/prometheus/procfs/kernel_random.go delete mode 100644 vendor/github.com/prometheus/procfs/loadavg.go delete mode 100644 vendor/github.com/prometheus/procfs/mdstat.go delete mode 100644 vendor/github.com/prometheus/procfs/meminfo.go delete mode 100644 vendor/github.com/prometheus/procfs/mountinfo.go delete mode 100644 vendor/github.com/prometheus/procfs/mountstats.go delete mode 100644 vendor/github.com/prometheus/procfs/net_conntrackstat.go delete mode 100644 vendor/github.com/prometheus/procfs/net_dev.go delete mode 100644 vendor/github.com/prometheus/procfs/net_ip_socket.go delete mode 100644 vendor/github.com/prometheus/procfs/net_protocols.go delete mode 100644 vendor/github.com/prometheus/procfs/net_route.go delete mode 100644 vendor/github.com/prometheus/procfs/net_sockstat.go delete mode 100644 vendor/github.com/prometheus/procfs/net_softnet.go delete mode 100644 vendor/github.com/prometheus/procfs/net_tcp.go delete mode 100644 vendor/github.com/prometheus/procfs/net_tls_stat.go delete mode 100644 vendor/github.com/prometheus/procfs/net_udp.go delete mode 100644 vendor/github.com/prometheus/procfs/net_unix.go delete mode 100644 vendor/github.com/prometheus/procfs/net_wireless.go delete mode 100644 vendor/github.com/prometheus/procfs/net_xfrm.go delete mode 100644 vendor/github.com/prometheus/procfs/netstat.go delete mode 100644 vendor/github.com/prometheus/procfs/proc.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_cgroup.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_cgroups.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_environ.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_fdinfo.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_interrupts.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_io.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_limits.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_maps.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_netstat.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_ns.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_psi.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_smaps.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_snmp.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_snmp6.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_stat.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_status.go delete mode 100644 vendor/github.com/prometheus/procfs/proc_sys.go delete mode 100644 vendor/github.com/prometheus/procfs/schedstat.go delete mode 100644 vendor/github.com/prometheus/procfs/slab.go delete mode 100644 vendor/github.com/prometheus/procfs/softirqs.go delete mode 100644 vendor/github.com/prometheus/procfs/stat.go delete mode 100644 vendor/github.com/prometheus/procfs/swaps.go delete mode 100644 vendor/github.com/prometheus/procfs/thread.go delete mode 100644 vendor/github.com/prometheus/procfs/ttar delete mode 100644 vendor/github.com/prometheus/procfs/vm.go delete mode 100644 vendor/github.com/prometheus/procfs/zoneinfo.go delete mode 100644 vendor/github.com/prometheus/prometheus/LICENSE delete mode 100644 vendor/github.com/prometheus/prometheus/NOTICE delete mode 100644 vendor/github.com/prometheus/prometheus/model/exemplar/exemplar.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/histogram/float_histogram.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/histogram/generic.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/histogram/histogram.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/histogram/test_utils.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/labels.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/labels_common.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/labels_dedupelabels.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/matcher.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/regexp.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/sharding.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/sharding_dedupelabels.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/sharding_stringlabels.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/labels/test_utils.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/metadata/metadata.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/rulefmt/rulefmt.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/README.md delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/interface.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/nhcbparse.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/openmetricslex.l delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/openmetricslex.l.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/openmetricsparse.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/promlex.l delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/promlex.l.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/promparse.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/textparse/protobufparse.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/timestamp/timestamp.go delete mode 100644 vendor/github.com/prometheus/prometheus/model/value/value.go delete mode 100644 vendor/github.com/prometheus/prometheus/prompb/io/prometheus/client/decoder.go delete mode 100644 vendor/github.com/prometheus/prometheus/prompb/io/prometheus/client/metrics.pb.go delete mode 100644 vendor/github.com/prometheus/prometheus/prompb/io/prometheus/client/metrics.proto delete mode 100644 vendor/github.com/prometheus/prometheus/promql/durations.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/engine.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/functions.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/fuzz.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/histogram_stats_iterator.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/info.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/ast.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/functions.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/generated_parser.y delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/generated_parser.y.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/lex.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/parse.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/posrange/posrange.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/prettier.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/prettier_rules.md delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/printer.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/parser/value.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/quantile.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/query_logger.go delete mode 100644 vendor/github.com/prometheus/prometheus/promql/value.go delete mode 100644 vendor/github.com/prometheus/prometheus/schema/labels.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/buffer.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/errors.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/fanout.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/generic.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/interface.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/lazy.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/memoized_iterator.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/merge.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/noop.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/secondary.go delete mode 100644 vendor/github.com/prometheus/prometheus/storage/series.go delete mode 100644 vendor/github.com/prometheus/prometheus/template/template.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunkenc/bstream.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunkenc/chunk.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunkenc/float_histogram.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunkenc/histogram.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunkenc/histogram_meta.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunkenc/varbit.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunkenc/xor.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunks/chunk_write_queue.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunks/chunks.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunks/head_chunks.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunks/head_chunks_other.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunks/head_chunks_windows.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunks/queue.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/chunks/samples.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/errors/errors.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/dir.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/dir_unix.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/dir_windows.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/direct_io.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/direct_io_force.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/direct_io_linux.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/direct_io_unsupported.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/direct_io_writer.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/fileutil.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/flock.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/flock_js.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/flock_plan9.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/flock_solaris.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/flock_unix.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/flock_windows.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/mmap.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/mmap_386.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/mmap_amd64.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/mmap_arm64.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/mmap_js.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/mmap_unix.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/mmap_windows.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/preallocate.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/preallocate_darwin.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/preallocate_linux.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/preallocate_other.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/sync.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/sync_darwin.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/fileutil/sync_linux.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/almost/almost.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/annotations/annotations.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/convertnhcb/convertnhcb.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/logging/dedupe.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/logging/file.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/stats/query_stats.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/stats/timer.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/strutil/quote.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/strutil/strconv.go delete mode 100644 vendor/github.com/prometheus/prometheus/util/zeropool/pool.go delete mode 100644 vendor/github.com/rs/cors/LICENSE delete mode 100644 vendor/github.com/rs/cors/README.md delete mode 100644 vendor/github.com/rs/cors/cors.go delete mode 100644 vendor/github.com/rs/cors/internal/sortedset.go delete mode 100644 vendor/github.com/rs/cors/utils.go delete mode 100644 vendor/github.com/sergi/go-diff/AUTHORS delete mode 100644 vendor/github.com/sergi/go-diff/CONTRIBUTORS delete mode 100644 vendor/github.com/sergi/go-diff/LICENSE delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/diffmatchpatch.go delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/index.go delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/match.go delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/mathutil.go delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/operation_string.go delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/patch.go delete mode 100644 vendor/github.com/sergi/go-diff/diffmatchpatch/stringutil.go delete mode 100644 vendor/github.com/tadvi/systray/.gitignore delete mode 100644 vendor/github.com/tadvi/systray/AUTHORS delete mode 100644 vendor/github.com/tadvi/systray/LICENSE delete mode 100644 vendor/github.com/tadvi/systray/README.md delete mode 100644 vendor/github.com/tadvi/systray/systray_linux.go delete mode 100644 vendor/github.com/tadvi/systray/systray_windows.go delete mode 100644 vendor/github.com/yuin/goldmark-emoji/.gitignore delete mode 100644 vendor/github.com/yuin/goldmark-emoji/LICENSE delete mode 100644 vendor/github.com/yuin/goldmark-emoji/README.md delete mode 100644 vendor/github.com/yuin/goldmark-emoji/ast/emoji.go delete mode 100644 vendor/github.com/yuin/goldmark-emoji/definition/definition.go delete mode 100644 vendor/github.com/yuin/goldmark-emoji/definition/github.go delete mode 100644 vendor/github.com/yuin/goldmark-emoji/emoji.go delete mode 100644 vendor/github.com/yuin/goldmark/.gitignore delete mode 100644 vendor/github.com/yuin/goldmark/.golangci.yml delete mode 100644 vendor/github.com/yuin/goldmark/LICENSE delete mode 100644 vendor/github.com/yuin/goldmark/Makefile delete mode 100644 vendor/github.com/yuin/goldmark/README.md delete mode 100644 vendor/github.com/yuin/goldmark/ast/ast.go delete mode 100644 vendor/github.com/yuin/goldmark/ast/block.go delete mode 100644 vendor/github.com/yuin/goldmark/ast/inline.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/ast/definition_list.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/ast/footnote.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/ast/strikethrough.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/ast/table.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/ast/tasklist.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/cjk.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/definition_list.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/footnote.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/gfm.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/linkify.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/package.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/strikethrough.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/table.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/tasklist.go delete mode 100644 vendor/github.com/yuin/goldmark/extension/typographer.go delete mode 100644 vendor/github.com/yuin/goldmark/markdown.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/attribute.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/atx_heading.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/auto_link.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/blockquote.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/code_block.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/code_span.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/delimiter.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/emphasis.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/fcode_block.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/html_block.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/link.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/link_ref.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/list.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/list_item.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/paragraph.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/parser.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/raw_html.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/setext_headings.go delete mode 100644 vendor/github.com/yuin/goldmark/parser/thematic_break.go delete mode 100644 vendor/github.com/yuin/goldmark/renderer/html/html.go delete mode 100644 vendor/github.com/yuin/goldmark/renderer/renderer.go delete mode 100644 vendor/github.com/yuin/goldmark/text/package.go delete mode 100644 vendor/github.com/yuin/goldmark/text/reader.go delete mode 100644 vendor/github.com/yuin/goldmark/text/segment.go delete mode 100644 vendor/github.com/yuin/goldmark/util/html5entities.go delete mode 100644 vendor/github.com/yuin/goldmark/util/unicode_case_folding.go delete mode 100644 vendor/github.com/yuin/goldmark/util/util.go delete mode 100644 vendor/github.com/yuin/goldmark/util/util_cjk.go delete mode 100644 vendor/github.com/yuin/goldmark/util/util_safe.go delete mode 100644 vendor/github.com/yuin/goldmark/util/util_unsafe_go120.go delete mode 100644 vendor/github.com/yuin/goldmark/util/util_unsafe_go121.go delete mode 100644 vendor/github.com/zeebo/blake3/.gitignore delete mode 100644 vendor/github.com/zeebo/blake3/LICENSE delete mode 100644 vendor/github.com/zeebo/blake3/Makefile delete mode 100644 vendor/github.com/zeebo/blake3/README.md delete mode 100644 vendor/github.com/zeebo/blake3/api.go delete mode 100644 vendor/github.com/zeebo/blake3/blake3.go delete mode 100644 vendor/github.com/zeebo/blake3/digest.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/alg.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/compress/compress.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/compress/compress_pure/compress.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/compress/compress_sse41/impl_amd64.s delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/compress/compress_sse41/impl_other.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/compress/compress_sse41/stubs.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/hash/hash.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/hash/hash_avx2/impl_amd64.s delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/hash/hash_avx2/impl_other.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/hash/hash_avx2/stubs.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/hash/hash_pure/hashf.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/alg/hash/hash_pure/hashp.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/consts/consts.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/consts/cpu.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/consts/cpu_little.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/consts/cpu_other.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/consts/cpu_purego.go delete mode 100644 vendor/github.com/zeebo/blake3/internal/utils/utils.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/LICENSE delete mode 100644 vendor/github.com/zitadel/oidc/v3/NOTICE delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/crypto/crypto.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/crypto/hash.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/crypto/key.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/crypto/sign.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/authorization.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/code_challenge.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/device_authorization.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/discovery.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/error.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/introspection.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/jwt_profile.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/keyset.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/revocation.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/session.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/token.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/token_request.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/types.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/userinfo.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/util.go delete mode 100644 vendor/github.com/zitadel/oidc/v3/pkg/oidc/verifier.go delete mode 100644 vendor/github.com/zitadel/schema/.releaserc.js delete mode 100644 vendor/github.com/zitadel/schema/LICENSE delete mode 100644 vendor/github.com/zitadel/schema/README.md delete mode 100644 vendor/github.com/zitadel/schema/cache.go delete mode 100644 vendor/github.com/zitadel/schema/converter.go delete mode 100644 vendor/github.com/zitadel/schema/decoder.go delete mode 100644 vendor/github.com/zitadel/schema/doc.go delete mode 100644 vendor/github.com/zitadel/schema/encoder.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/CONTRIBUTING.md delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/LICENSE delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/VERSIONING.md delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/doc.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/attr.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/doc.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/id.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/number.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/resource.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/scope.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/span.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/status.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/traces.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/internal/telemetry/value.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/limit.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/span.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/tracer.go delete mode 100644 vendor/go.opentelemetry.io/auto/sdk/tracer_provider.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/LICENSE delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/doc.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters/filters.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptor.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/interceptorinfo.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal/parse.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/metadata_supplier.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/semconv.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/version.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/LICENSE delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/client.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/config.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/doc.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/body_wrapper.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/gen.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request/resp_writer_wrapper.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/env.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/gen.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/httpconv.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/util.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv/v1.20.0.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/gen.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/labeler.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/start_time_context.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go delete mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/b3/LICENSE delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/b3/b3_config.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/b3/b3_propagator.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/b3/context.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/b3/doc.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/b3/version.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/ot/LICENSE delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/ot/doc.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/ot/ot_propagator.go delete mode 100644 vendor/go.opentelemetry.io/contrib/propagators/ot/version.go delete mode 100644 vendor/go.opentelemetry.io/otel/.clomonitor.yml delete mode 100644 vendor/go.opentelemetry.io/otel/.codespellignore delete mode 100644 vendor/go.opentelemetry.io/otel/.codespellrc delete mode 100644 vendor/go.opentelemetry.io/otel/.gitattributes delete mode 100644 vendor/go.opentelemetry.io/otel/.gitignore delete mode 100644 vendor/go.opentelemetry.io/otel/.golangci.yml delete mode 100644 vendor/go.opentelemetry.io/otel/.lycheeignore delete mode 100644 vendor/go.opentelemetry.io/otel/.markdownlint.yaml delete mode 100644 vendor/go.opentelemetry.io/otel/CHANGELOG.md delete mode 100644 vendor/go.opentelemetry.io/otel/CODEOWNERS delete mode 100644 vendor/go.opentelemetry.io/otel/CONTRIBUTING.md delete mode 100644 vendor/go.opentelemetry.io/otel/Makefile delete mode 100644 vendor/go.opentelemetry.io/otel/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/RELEASING.md delete mode 100644 vendor/go.opentelemetry.io/otel/SECURITY-INSIGHTS.yml delete mode 100644 vendor/go.opentelemetry.io/otel/VERSIONING.md delete mode 100644 vendor/go.opentelemetry.io/otel/baggage/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/baggage/baggage.go delete mode 100644 vendor/go.opentelemetry.io/otel/baggage/context.go delete mode 100644 vendor/go.opentelemetry.io/otel/baggage/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/codes/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/codes/codes.go delete mode 100644 vendor/go.opentelemetry.io/otel/codes/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/dependencies.Dockerfile delete mode 100644 vendor/go.opentelemetry.io/otel/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/error_handler.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/LICENSE delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/client.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/config.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/exporter.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig/envconfig.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/gen.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/envconfig.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/options.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/optiontypes.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf/tls.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/partialsuccess.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/retry/retry.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform/attribute.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform/error.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform/metricdata.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/version.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/LICENSE delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/clients.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/exporter.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/attribute.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/instrumentation.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/resource.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/span.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/LICENSE delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/exporter.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig/envconfig.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/gen.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/envconfig.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/optiontypes.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/tls.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/partialsuccess.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry/retry.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/options.go delete mode 100644 vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go delete mode 100644 vendor/go.opentelemetry.io/otel/handler.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/baggage/baggage.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/baggage/context.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/global/handler.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/global/instruments.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/global/internal_logging.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/global/meter.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/global/propagator.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/global/state.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal/global/trace.go delete mode 100644 vendor/go.opentelemetry.io/otel/internal_logging.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/LICENSE delete mode 100644 vendor/go.opentelemetry.io/otel/metric/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/asyncint64.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/config.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/embedded/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/metric/embedded/embedded.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/instrument.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/meter.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/noop/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/metric/noop/noop.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/syncfloat64.go delete mode 100644 vendor/go.opentelemetry.io/otel/metric/syncint64.go delete mode 100644 vendor/go.opentelemetry.io/otel/propagation.go delete mode 100644 vendor/go.opentelemetry.io/otel/propagation/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/propagation/baggage.go delete mode 100644 vendor/go.opentelemetry.io/otel/propagation/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/propagation/propagation.go delete mode 100644 vendor/go.opentelemetry.io/otel/propagation/trace_context.go delete mode 100644 vendor/go.opentelemetry.io/otel/renovate.json delete mode 100644 vendor/go.opentelemetry.io/otel/requirements.txt delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/LICENSE delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/instrumentation/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/instrumentation/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/instrumentation/library.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/internal/env/env.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/internal/x/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/internal/x/x.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/LICENSE delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/aggregation.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/cache.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/config.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/env.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/exemplar.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/filter.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/fixed_size_reservoir.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/reservoir.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/storage.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/value.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/exporter.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/instrumentkind_string.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/limit.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/reuse_slice.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/meter.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/metricdata/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/metricdata/data.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/metricdata/temporality.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/metricdata/temporality_string.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/provider.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/reader.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/version.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/metric/view.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/auto.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/config.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/container.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/env.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id_bsd.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id_darwin.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id_exec.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id_linux.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id_readfile.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id_unsupported.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/os.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/os_release_darwin.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/os_release_unix.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/os_unix.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/os_unsupported.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/process.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/resource/resource.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/event.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/id_generator.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/internal/x/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/internal/x/x.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/link.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/provider.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/sampler_env.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/sampling.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/simple_span_processor.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/snapshot.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/span.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/span_exporter.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/span_limits.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/span_processor.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/trace/tracer.go delete mode 100644 vendor/go.opentelemetry.io/otel/sdk/version.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/event.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/exception.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/http.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/resource.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/schema.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.17.0/trace.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/attribute_group.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/event.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/exception.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/http.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/resource.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/schema.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.20.0/trace.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/attribute_group.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/event.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/exception.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/resource.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/schema.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.21.0/trace.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.26.0/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.26.0/attribute_group.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.26.0/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.26.0/exception.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.26.0/metric.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.26.0/schema.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/MIGRATION.md delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/attribute_group.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/error_type.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/exception.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/otelconv/metric.go delete mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.37.0/schema.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/LICENSE delete mode 100644 vendor/go.opentelemetry.io/otel/trace/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/trace/auto.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/config.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/context.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/embedded/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/trace/embedded/embedded.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/hex.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/attr.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/doc.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/id.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/number.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/resource.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/scope.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/span.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/status.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/traces.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/internal/telemetry/value.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/nonrecording.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/noop.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/noop/README.md delete mode 100644 vendor/go.opentelemetry.io/otel/trace/noop/noop.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/provider.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/span.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/trace.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/tracer.go delete mode 100644 vendor/go.opentelemetry.io/otel/trace/tracestate.go delete mode 100644 vendor/go.opentelemetry.io/otel/verify_released_changelog.sh delete mode 100644 vendor/go.opentelemetry.io/otel/version.go delete mode 100644 vendor/go.opentelemetry.io/otel/versions.yaml delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/metrics/v1/metrics_service.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/metrics/v1/metrics_service.pb.gw.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/metrics/v1/metrics_service_grpc.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/profiles/v1development/LICENSE delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/profiles/v1development/profiles_service.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/profiles/v1development/profiles_service.pb.gw.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/profiles/v1development/profiles_service_grpc.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/trace/v1/trace_service.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/trace/v1/trace_service.pb.gw.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/collector/trace/v1/trace_service_grpc.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/metrics/v1/metrics.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/profiles/v1development/LICENSE delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/profiles/v1development/profiles.pb.go delete mode 100644 vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go delete mode 100644 vendor/go.uber.org/atomic/.codecov.yml delete mode 100644 vendor/go.uber.org/atomic/.gitignore delete mode 100644 vendor/go.uber.org/atomic/CHANGELOG.md delete mode 100644 vendor/go.uber.org/atomic/LICENSE.txt delete mode 100644 vendor/go.uber.org/atomic/Makefile delete mode 100644 vendor/go.uber.org/atomic/README.md delete mode 100644 vendor/go.uber.org/atomic/bool.go delete mode 100644 vendor/go.uber.org/atomic/bool_ext.go delete mode 100644 vendor/go.uber.org/atomic/doc.go delete mode 100644 vendor/go.uber.org/atomic/duration.go delete mode 100644 vendor/go.uber.org/atomic/duration_ext.go delete mode 100644 vendor/go.uber.org/atomic/error.go delete mode 100644 vendor/go.uber.org/atomic/error_ext.go delete mode 100644 vendor/go.uber.org/atomic/float32.go delete mode 100644 vendor/go.uber.org/atomic/float32_ext.go delete mode 100644 vendor/go.uber.org/atomic/float64.go delete mode 100644 vendor/go.uber.org/atomic/float64_ext.go delete mode 100644 vendor/go.uber.org/atomic/gen.go delete mode 100644 vendor/go.uber.org/atomic/int32.go delete mode 100644 vendor/go.uber.org/atomic/int64.go delete mode 100644 vendor/go.uber.org/atomic/nocmp.go delete mode 100644 vendor/go.uber.org/atomic/pointer_go118.go delete mode 100644 vendor/go.uber.org/atomic/pointer_go118_pre119.go delete mode 100644 vendor/go.uber.org/atomic/pointer_go119.go delete mode 100644 vendor/go.uber.org/atomic/string.go delete mode 100644 vendor/go.uber.org/atomic/string_ext.go delete mode 100644 vendor/go.uber.org/atomic/time.go delete mode 100644 vendor/go.uber.org/atomic/time_ext.go delete mode 100644 vendor/go.uber.org/atomic/uint32.go delete mode 100644 vendor/go.uber.org/atomic/uint64.go delete mode 100644 vendor/go.uber.org/atomic/uintptr.go delete mode 100644 vendor/go.uber.org/atomic/unsafe_pointer.go delete mode 100644 vendor/go.uber.org/atomic/value.go delete mode 100644 vendor/go.uber.org/multierr/.codecov.yml delete mode 100644 vendor/go.uber.org/multierr/.gitignore delete mode 100644 vendor/go.uber.org/multierr/CHANGELOG.md delete mode 100644 vendor/go.uber.org/multierr/LICENSE.txt delete mode 100644 vendor/go.uber.org/multierr/Makefile delete mode 100644 vendor/go.uber.org/multierr/README.md delete mode 100644 vendor/go.uber.org/multierr/error.go delete mode 100644 vendor/go.uber.org/multierr/error_post_go120.go delete mode 100644 vendor/go.uber.org/multierr/error_pre_go120.go delete mode 100644 vendor/golang.org/x/crypto/LICENSE delete mode 100644 vendor/golang.org/x/crypto/PATENTS delete mode 100644 vendor/golang.org/x/crypto/argon2/argon2.go delete mode 100644 vendor/golang.org/x/crypto/argon2/blake2b.go delete mode 100644 vendor/golang.org/x/crypto/argon2/blamka_amd64.go delete mode 100644 vendor/golang.org/x/crypto/argon2/blamka_amd64.s delete mode 100644 vendor/golang.org/x/crypto/argon2/blamka_generic.go delete mode 100644 vendor/golang.org/x/crypto/argon2/blamka_ref.go delete mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b.go delete mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go delete mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s delete mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s delete mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_generic.go delete mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_ref.go delete mode 100644 vendor/golang.org/x/crypto/blake2b/blake2x.go delete mode 100644 vendor/golang.org/x/crypto/blake2b/go125.go delete mode 100644 vendor/golang.org/x/crypto/blake2b/register.go delete mode 100644 vendor/golang.org/x/crypto/blowfish/block.go delete mode 100644 vendor/golang.org/x/crypto/blowfish/cipher.go delete mode 100644 vendor/golang.org/x/crypto/blowfish/const.go delete mode 100644 vendor/golang.org/x/crypto/cast5/cast5.go delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_arm64.go delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_arm64.s delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_generic.go delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_noasm.go delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_s390x.go delete mode 100644 vendor/golang.org/x/crypto/chacha20/chacha_s390x.s delete mode 100644 vendor/golang.org/x/crypto/chacha20/xor.go delete mode 100644 vendor/golang.org/x/crypto/cryptobyte/asn1.go delete mode 100644 vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go delete mode 100644 vendor/golang.org/x/crypto/cryptobyte/builder.go delete mode 100644 vendor/golang.org/x/crypto/cryptobyte/string.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519.go delete mode 100644 vendor/golang.org/x/crypto/hkdf/hkdf.go delete mode 100644 vendor/golang.org/x/crypto/internal/alias/alias.go delete mode 100644 vendor/golang.org/x/crypto/internal/alias/alias_purego.go delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/poly1305.go delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_loong64.s delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go delete mode 100644 vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s delete mode 100644 vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go delete mode 100644 vendor/golang.org/x/crypto/sha3/doc.go delete mode 100644 vendor/golang.org/x/crypto/sha3/hashes.go delete mode 100644 vendor/golang.org/x/crypto/sha3/hashes_noasm.go delete mode 100644 vendor/golang.org/x/crypto/sha3/keccakf.go delete mode 100644 vendor/golang.org/x/crypto/sha3/keccakf_amd64.go delete mode 100644 vendor/golang.org/x/crypto/sha3/keccakf_amd64.s delete mode 100644 vendor/golang.org/x/crypto/sha3/sha3.go delete mode 100644 vendor/golang.org/x/crypto/sha3/sha3_s390x.go delete mode 100644 vendor/golang.org/x/crypto/sha3/sha3_s390x.s delete mode 100644 vendor/golang.org/x/crypto/sha3/shake.go delete mode 100644 vendor/golang.org/x/crypto/sha3/shake_noasm.go delete mode 100644 vendor/golang.org/x/crypto/ssh/agent/client.go delete mode 100644 vendor/golang.org/x/crypto/ssh/agent/forward.go delete mode 100644 vendor/golang.org/x/crypto/ssh/agent/keyring.go delete mode 100644 vendor/golang.org/x/crypto/ssh/agent/server.go delete mode 100644 vendor/golang.org/x/crypto/ssh/buffer.go delete mode 100644 vendor/golang.org/x/crypto/ssh/certs.go delete mode 100644 vendor/golang.org/x/crypto/ssh/channel.go delete mode 100644 vendor/golang.org/x/crypto/ssh/cipher.go delete mode 100644 vendor/golang.org/x/crypto/ssh/client.go delete mode 100644 vendor/golang.org/x/crypto/ssh/client_auth.go delete mode 100644 vendor/golang.org/x/crypto/ssh/common.go delete mode 100644 vendor/golang.org/x/crypto/ssh/connection.go delete mode 100644 vendor/golang.org/x/crypto/ssh/doc.go delete mode 100644 vendor/golang.org/x/crypto/ssh/handshake.go delete mode 100644 vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go delete mode 100644 vendor/golang.org/x/crypto/ssh/kex.go delete mode 100644 vendor/golang.org/x/crypto/ssh/keys.go delete mode 100644 vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go delete mode 100644 vendor/golang.org/x/crypto/ssh/mac.go delete mode 100644 vendor/golang.org/x/crypto/ssh/messages.go delete mode 100644 vendor/golang.org/x/crypto/ssh/mlkem.go delete mode 100644 vendor/golang.org/x/crypto/ssh/mux.go delete mode 100644 vendor/golang.org/x/crypto/ssh/server.go delete mode 100644 vendor/golang.org/x/crypto/ssh/session.go delete mode 100644 vendor/golang.org/x/crypto/ssh/ssh_gss.go delete mode 100644 vendor/golang.org/x/crypto/ssh/streamlocal.go delete mode 100644 vendor/golang.org/x/crypto/ssh/tcpip.go delete mode 100644 vendor/golang.org/x/crypto/ssh/transport.go delete mode 100644 vendor/golang.org/x/exp/rand/exp.go delete mode 100644 vendor/golang.org/x/exp/rand/normal.go delete mode 100644 vendor/golang.org/x/exp/rand/rand.go delete mode 100644 vendor/golang.org/x/exp/rand/rng.go delete mode 100644 vendor/golang.org/x/exp/rand/zipf.go delete mode 100644 vendor/golang.org/x/net/html/atom/atom.go delete mode 100644 vendor/golang.org/x/net/html/atom/table.go delete mode 100644 vendor/golang.org/x/net/html/const.go delete mode 100644 vendor/golang.org/x/net/html/doc.go delete mode 100644 vendor/golang.org/x/net/html/doctype.go delete mode 100644 vendor/golang.org/x/net/html/entity.go delete mode 100644 vendor/golang.org/x/net/html/escape.go delete mode 100644 vendor/golang.org/x/net/html/foreign.go delete mode 100644 vendor/golang.org/x/net/html/iter.go delete mode 100644 vendor/golang.org/x/net/html/node.go delete mode 100644 vendor/golang.org/x/net/html/parse.go delete mode 100644 vendor/golang.org/x/net/html/render.go delete mode 100644 vendor/golang.org/x/net/html/token.go delete mode 100644 vendor/golang.org/x/net/http/httpproxy/proxy.go delete mode 100644 vendor/golang.org/x/net/http2/h2c/h2c.go delete mode 100644 vendor/golang.org/x/net/internal/socks/client.go delete mode 100644 vendor/golang.org/x/net/internal/socks/socks.go delete mode 100644 vendor/golang.org/x/net/proxy/dial.go delete mode 100644 vendor/golang.org/x/net/proxy/direct.go delete mode 100644 vendor/golang.org/x/net/proxy/per_host.go delete mode 100644 vendor/golang.org/x/net/proxy/proxy.go delete mode 100644 vendor/golang.org/x/net/proxy/socks5.go delete mode 100644 vendor/golang.org/x/oauth2/.travis.yml delete mode 100644 vendor/golang.org/x/oauth2/CONTRIBUTING.md delete mode 100644 vendor/golang.org/x/oauth2/LICENSE delete mode 100644 vendor/golang.org/x/oauth2/README.md delete mode 100644 vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go delete mode 100644 vendor/golang.org/x/oauth2/deviceauth.go delete mode 100644 vendor/golang.org/x/oauth2/internal/doc.go delete mode 100644 vendor/golang.org/x/oauth2/internal/oauth2.go delete mode 100644 vendor/golang.org/x/oauth2/internal/token.go delete mode 100644 vendor/golang.org/x/oauth2/internal/transport.go delete mode 100644 vendor/golang.org/x/oauth2/oauth2.go delete mode 100644 vendor/golang.org/x/oauth2/pkce.go delete mode 100644 vendor/golang.org/x/oauth2/token.go delete mode 100644 vendor/golang.org/x/oauth2/transport.go delete mode 100644 vendor/golang.org/x/sync/LICENSE delete mode 100644 vendor/golang.org/x/sync/PATENTS delete mode 100644 vendor/golang.org/x/sync/errgroup/errgroup.go delete mode 100644 vendor/golang.org/x/sync/singleflight/singleflight.go delete mode 100644 vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s delete mode 100644 vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s delete mode 100644 vendor/golang.org/x/sys/cpu/byteorder.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_aix.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm64.s delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_x86.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_x86.s delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_loong64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_loong64.s delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_mips64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_mipsx.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_arm.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_arm64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_x86.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_ppc64x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_riscv64.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_s390x.s delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_wasm.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_zos.go delete mode 100644 vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go delete mode 100644 vendor/golang.org/x/sys/cpu/endian_big.go delete mode 100644 vendor/golang.org/x/sys/cpu/endian_little.go delete mode 100644 vendor/golang.org/x/sys/cpu/hwcap_linux.go delete mode 100644 vendor/golang.org/x/sys/cpu/parse.go delete mode 100644 vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go delete mode 100644 vendor/golang.org/x/sys/cpu/runtime_auxv.go delete mode 100644 vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go delete mode 100644 vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go delete mode 100644 vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go delete mode 100644 vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go delete mode 100644 vendor/golang.org/x/sys/execabs/execabs.go delete mode 100644 vendor/golang.org/x/sys/execabs/execabs_go118.go delete mode 100644 vendor/golang.org/x/sys/execabs/execabs_go119.go delete mode 100644 vendor/golang.org/x/sys/windows/registry/key.go delete mode 100644 vendor/golang.org/x/sys/windows/registry/mksyscall.go delete mode 100644 vendor/golang.org/x/sys/windows/registry/syscall.go delete mode 100644 vendor/golang.org/x/sys/windows/registry/value.go delete mode 100644 vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/eventlog/install.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/eventlog/log.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/config.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/mgr.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/recovery.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/service.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/security.go delete mode 100644 vendor/golang.org/x/sys/windows/svc/service.go delete mode 100644 vendor/golang.org/x/text/cases/cases.go delete mode 100644 vendor/golang.org/x/text/cases/context.go delete mode 100644 vendor/golang.org/x/text/cases/fold.go delete mode 100644 vendor/golang.org/x/text/cases/icu.go delete mode 100644 vendor/golang.org/x/text/cases/info.go delete mode 100644 vendor/golang.org/x/text/cases/map.go delete mode 100644 vendor/golang.org/x/text/cases/tables10.0.0.go delete mode 100644 vendor/golang.org/x/text/cases/tables11.0.0.go delete mode 100644 vendor/golang.org/x/text/cases/tables12.0.0.go delete mode 100644 vendor/golang.org/x/text/cases/tables13.0.0.go delete mode 100644 vendor/golang.org/x/text/cases/tables15.0.0.go delete mode 100644 vendor/golang.org/x/text/cases/tables9.0.0.go delete mode 100644 vendor/golang.org/x/text/cases/trieval.go delete mode 100644 vendor/golang.org/x/text/internal/internal.go delete mode 100644 vendor/golang.org/x/text/internal/language/common.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/compact.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/language.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/parents.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/tables.go delete mode 100644 vendor/golang.org/x/text/internal/language/compact/tags.go delete mode 100644 vendor/golang.org/x/text/internal/language/compose.go delete mode 100644 vendor/golang.org/x/text/internal/language/coverage.go delete mode 100644 vendor/golang.org/x/text/internal/language/language.go delete mode 100644 vendor/golang.org/x/text/internal/language/lookup.go delete mode 100644 vendor/golang.org/x/text/internal/language/match.go delete mode 100644 vendor/golang.org/x/text/internal/language/parse.go delete mode 100644 vendor/golang.org/x/text/internal/language/tables.go delete mode 100644 vendor/golang.org/x/text/internal/language/tags.go delete mode 100644 vendor/golang.org/x/text/internal/match.go delete mode 100644 vendor/golang.org/x/text/internal/tag/tag.go delete mode 100644 vendor/golang.org/x/text/language/coverage.go delete mode 100644 vendor/golang.org/x/text/language/doc.go delete mode 100644 vendor/golang.org/x/text/language/language.go delete mode 100644 vendor/golang.org/x/text/language/match.go delete mode 100644 vendor/golang.org/x/text/language/parse.go delete mode 100644 vendor/golang.org/x/text/language/tables.go delete mode 100644 vendor/golang.org/x/text/language/tags.go delete mode 100644 vendor/gonum.org/v1/gonum/AUTHORS delete mode 100644 vendor/gonum.org/v1/gonum/CONTRIBUTORS delete mode 100644 vendor/gonum.org/v1/gonum/LICENSE delete mode 100644 vendor/gonum.org/v1/gonum/blas/README.md delete mode 100644 vendor/gonum.org/v1/gonum/blas/blas.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/blas64.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/conv.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/blas64/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/conversions.bash delete mode 100644 vendor/gonum.org/v1/gonum/blas/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/errors.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/gonum.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1float32.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1float32_dsdot.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdot.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdsdot.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1float64.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1float64_ddot.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2float32.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2float64.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3float32.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3float64.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash delete mode 100644 vendor/gonum.org/v1/gonum/floats/README.md delete mode 100644 vendor/gonum.org/v1/gonum/floats/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/floats/floats.go delete mode 100644 vendor/gonum.org/v1/gonum/floats/scalar/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/floats/scalar/scalar.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dotcinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dotcunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dotuinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dotuunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/stubs.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/ddotinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/ddotunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/dotinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/dotunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/ge_noasm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/gemv.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/l2norm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f32/sum_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/ge_amd64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/ger_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_noasm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/l2normdist_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/l2norminc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/math.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/signbit.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.s delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.go delete mode 100644 vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.s delete mode 100644 vendor/gonum.org/v1/gonum/lapack/.gitignore delete mode 100644 vendor/gonum.org/v1/gonum/lapack/README.md delete mode 100644 vendor/gonum.org/v1/gonum/lapack/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgesc2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgesv.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetc2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgghrd.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dgtsv.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlag2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlagtm.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlangb.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlangt.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlanhs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlansb.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlantb.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlapmr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlatbs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlatdf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgr2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpbcon.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpstf2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpstrf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dptcon.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dptsv.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpttrf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpttrs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dptts2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtbtrs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/errors.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/lapack.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/lapack.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/README.md delete mode 100644 vendor/gonum.org/v1/gonum/mat/band.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/cdense.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/cholesky.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/cmatrix.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/consts.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/dense.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/diagonal.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/eigen.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/errors.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/format.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/gsvd.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/hogsvd.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/index_bound_checks.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/inner.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/io.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/lq.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/lu.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/matrix.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/offset.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/offset_appengine.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/pool.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/product.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/qr.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/shadow.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/shadow_common.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/shadow_complex.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/solve.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/svd.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/symband.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/symmetric.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/triangular.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/triband.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/tridiag.go delete mode 100644 vendor/gonum.org/v1/gonum/mat/vector.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/README.md delete mode 100644 vendor/gonum.org/v1/gonum/mathext/airy.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/beta.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/betainc.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/digamma.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/ell_carlson.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/ell_complete.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/erf.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/gamma_inc.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/amos/staticcheck.conf delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/staticcheck.conf delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/mvgamma.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/roots.go delete mode 100644 vendor/gonum.org/v1/gonum/mathext/zeta.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/README.md delete mode 100644 vendor/gonum.org/v1/gonum/stat/combin/combin.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/combin/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/alphastable.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/beta.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/binomial.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/categorical.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/chi.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/constants.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/exponential.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/f.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/gamma.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/general.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/gumbel.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/inversegamma.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/laplace.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/logistic.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/norm.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/pareto.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/poisson.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/statdist.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/studentst.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/triangle.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/uniform.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/distuv/weibull.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/pca_cca.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/roc.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/stat.go delete mode 100644 vendor/gonum.org/v1/gonum/stat/statmat.go delete mode 100644 vendor/google.golang.org/genproto/googleapis/rpc/errdetails/error_details.pb.go delete mode 100644 vendor/google.golang.org/grpc/encoding/gzip/gzip.go delete mode 100644 vendor/google.golang.org/grpc/reflection/README.md delete mode 100644 vendor/google.golang.org/grpc/reflection/adapt.go delete mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go delete mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go delete mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go delete mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go delete mode 100644 vendor/google.golang.org/grpc/reflection/internal/internal.go delete mode 100644 vendor/google.golang.org/grpc/reflection/serverreflection.go delete mode 100644 vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go delete mode 100644 vendor/google.golang.org/protobuf/internal/editionssupport/editions.go delete mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc.go delete mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go delete mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go delete mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go delete mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/editions.go delete mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/proto.go delete mode 100644 vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go delete mode 100644 vendor/gopkg.in/yaml.v2/.travis.yml delete mode 100644 vendor/gopkg.in/yaml.v2/LICENSE delete mode 100644 vendor/gopkg.in/yaml.v2/LICENSE.libyaml delete mode 100644 vendor/gopkg.in/yaml.v2/NOTICE delete mode 100644 vendor/gopkg.in/yaml.v2/README.md delete mode 100644 vendor/gopkg.in/yaml.v2/apic.go delete mode 100644 vendor/gopkg.in/yaml.v2/decode.go delete mode 100644 vendor/gopkg.in/yaml.v2/emitterc.go delete mode 100644 vendor/gopkg.in/yaml.v2/encode.go delete mode 100644 vendor/gopkg.in/yaml.v2/parserc.go delete mode 100644 vendor/gopkg.in/yaml.v2/readerc.go delete mode 100644 vendor/gopkg.in/yaml.v2/resolve.go delete mode 100644 vendor/gopkg.in/yaml.v2/scannerc.go delete mode 100644 vendor/gopkg.in/yaml.v2/sorter.go delete mode 100644 vendor/gopkg.in/yaml.v2/writerc.go delete mode 100644 vendor/gopkg.in/yaml.v2/yaml.go delete mode 100644 vendor/gopkg.in/yaml.v2/yamlh.go delete mode 100644 vendor/gopkg.in/yaml.v2/yamlprivateh.go diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml index b9da0613..bedf669d 100644 --- a/.github/workflows/release-dev.yml +++ b/.github/workflows/release-dev.yml @@ -78,7 +78,6 @@ jobs: - run: mkdir -p dist/${{ matrix.targets.goos }}-${{ matrix.targets.goarch }} - run: ${{ matrix.targets.goenvs }} ./script/build.sh env: - HUMANLOG_GOTAGS: ${{ matrix.targets.tags }} GOOS: ${{ matrix.targets.goos }} GOARCH: ${{ matrix.targets.goarch }} - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2339aad..3e3d01a9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -98,7 +98,6 @@ jobs: - run: mkdir -p dist/${{ matrix.targets.goos }}-${{ matrix.targets.goarch }} - run: ${{ matrix.targets.goenvs }} ./script/build.sh env: - HUMANLOG_GOTAGS: ${{ matrix.targets.tags }} GOOS: ${{ matrix.targets.goos }} GOARCH: ${{ matrix.targets.goarch }} HUMANLOG_IS_PROD_BUILD: 'true' diff --git a/cmd/humanlog/api.go b/cmd/humanlog/api.go deleted file mode 100644 index 88de0522..00000000 --- a/cmd/humanlog/api.go +++ /dev/null @@ -1,347 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "log/slog" - "net" - "net/http" - "net/url" - "os" - "strconv" - - "connectrpc.com/connect" - featurev1 "github.com/minitape/api/go/svc/feature/v1" - "github.com/minitape/api/go/svc/feature/v1/featurev1connect" - localhostv1 "github.com/minitape/api/go/svc/localhost/v1" - "github.com/minitape/api/go/svc/localhost/v1/localhostv1connect" - projectv1 "github.com/minitape/api/go/svc/project/v1" - "github.com/minitape/api/go/svc/project/v1/projectv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/iterapi" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/urfave/cli" - "google.golang.org/protobuf/encoding/protojson" -) - -const ( - apiCmdName = "api" -) - -func apiCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getLocalhostHTTPClient func(cctx *cli.Context) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - return cli.Command{ - Name: apiCmdName, - Usage: "Raw interactions with the API", - Hidden: true, - Subcommands: []cli.Command{ - apiLocalhost( - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getLocalhostHTTPClient, - getConnectOpts, - ), - apiFeature( - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getHTTPClient, - getConnectOpts, - ), - apiProject( - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getLocalhostHTTPClient, - getConnectOpts, - ), - }, - } -} - -func apiLocalhost( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getLocalhostHTTPClient func(cctx *cli.Context) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - - getLocalhostClient := func(cctx *cli.Context) localhostv1connect.LocalhostServiceClient { - - cfg := getCfg(cctx) - port := cfg.GetRuntime().GetExperimentalFeatures().GetServeLocalhost().GetPort() - - localhostAddr := net.JoinHostPort("localhost", strconv.FormatInt(port, 10)) - addr, err := url.Parse("http://" + localhostAddr) - if err != nil { - panic(err) - } - httpClient := getLocalhostHTTPClient(cctx) - client := localhostv1connect.NewLocalhostServiceClient(httpClient, addr.String()) - return client - } - - return cli.Command{ - Name: "localhost", - Subcommands: []cli.Command{ - { - Name: "stats", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - client := getLocalhostClient(cctx) - ll.InfoContext(ctx, "looking localhost stats") - req := &localhostv1.GetStatsRequest{} - res, err := client.GetStats(ctx, connect.NewRequest(req)) - if err != nil { - return err - } - _, err = os.Stdout.WriteString(protojson.Format(res.Msg)) - return err - }, - }, - }, - } -} - -func apiFeature( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - - getFeatureClient := func(cctx *cli.Context) featurev1connect.FeatureServiceClient { - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - authedClOpts := connect.WithInterceptors(auth.Interceptors(ll, tokenSource)...) - client := featurev1connect.NewFeatureServiceClient(httpClient, apiURL, authedClOpts) - return client - } - - return cli.Command{ - Name: "feature", - Subcommands: []cli.Command{ - { - Name: "has", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - client := getFeatureClient(cctx) - - feature := cctx.Args()[0] - ll.InfoContext(ctx, "looking up feature access", slog.String("feature", feature)) - req := &featurev1.HasFeatureRequest{Feature: feature} - res, err := client.HasFeature(ctx, connect.NewRequest(req)) - if err != nil { - return err - } - _, err = os.Stdout.WriteString(protojson.Format(res.Msg)) - return err - }, - }, - { - Name: "list", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - client := getFeatureClient(cctx) - req := &featurev1.ListFeatureRequest{} - res, err := client.ListFeature(ctx, connect.NewRequest(req)) - if err != nil { - return err - } - _, err = os.Stdout.WriteString(protojson.Format(res.Msg)) - return err - }, - }, - { - Name: "allowed-usage", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - client := getFeatureClient(cctx) - req := &featurev1.AllowedUsageRequest{} - res, err := client.AllowedUsage(ctx, connect.NewRequest(req)) - if err != nil { - return err - } - // _, err = os.Stdout.WriteString(protojson.Format(res.Msg)) - // return err - usage := featurev1.AllowedUsageResponse_LocalhostUsage_name[int32(res.Msg.LocalhostUsage)] - return json.NewEncoder(os.Stdout).Encode(usage) - }, - }, - }, - } -} - -func apiProject( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getLocalhostHTTPClient func(cctx *cli.Context) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - - getProjectClient := func(cctx *cli.Context) projectv1connect.ProjectServiceClient { - cfg := getCfg(cctx) - port := cfg.GetRuntime().GetExperimentalFeatures().GetServeLocalhost().GetPort() - - localhostAddr := net.JoinHostPort("localhost", strconv.FormatInt(port, 10)) - addr, err := url.Parse("http://" + localhostAddr) - if err != nil { - panic(err) - } - httpClient := getLocalhostHTTPClient(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - authedClOpts := connect.WithInterceptors(auth.Interceptors(ll, tokenSource)...) - client := projectv1connect.NewProjectServiceClient(httpClient, addr.String(), authedClOpts) - return client - } - - var ( - projectName = cli.StringFlag{Name: "name", Usage: "name of the project"} - projectPath = cli.StringFlag{Name: "path", Usage: "where the project's base path starts"} - projectDashboardDir = cli.StringFlag{Name: "dashboards", Usage: "where the project's dashboards are found (a directory)"} - projectAlertDir = cli.StringFlag{Name: "alerts", Usage: "where the project's alerts are found (a directory)"} - ) - - return cli.Command{ - Name: "project", - Subcommands: []cli.Command{ - { - Name: "create", - Flags: []cli.Flag{ - projectName, projectPath, projectDashboardDir, projectAlertDir, - }, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - client := getProjectClient(cctx) - - req := &projectv1.CreateProjectRequest{ - Spec: &typesv1.ProjectSpec{ - Name: cctx.String(projectName.Name), - Pointer: &typesv1.ProjectPointer{ - Scheme: &typesv1.ProjectPointer_Localhost{ - Localhost: &typesv1.ProjectPointer_LocalGit{ - Path: cctx.String(projectPath.Name), - DashboardDir: cctx.String(projectDashboardDir.Name), - AlertDir: cctx.String(projectAlertDir.Name), - }, - }, - }, - }, - } - - ll.InfoContext(ctx, "creating project", slog.Any("pointer", req.Spec.Pointer.GetLocalhost())) - res, err := client.CreateProject(ctx, connect.NewRequest(req)) - if err != nil { - return err - } - _, err = os.Stdout.WriteString(protojson.Format(res.Msg)) - return err - }, - }, - { - Name: "get", - Flags: []cli.Flag{ - projectName, - }, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - client := getProjectClient(cctx) - - req := &projectv1.GetProjectRequest{ - Name: cctx.String(projectName.Name), - } - - ll.InfoContext(ctx, "getting project", slog.Any("name", req.Name)) - res, err := client.GetProject(ctx, connect.NewRequest(req)) - if err != nil { - return err - } - _, err = os.Stdout.WriteString(protojson.Format(res.Msg)) - return err - }, - }, - { - Name: "list", - Flags: []cli.Flag{}, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - client := getProjectClient(cctx) - - projects := iterapi.New(ctx, 10, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*projectv1.ListProjectResponse_ListItem, *typesv1.Cursor, error) { - req := &projectv1.ListProjectRequest{Cursor: cursor, Limit: limit} - res, err := client.ListProject(ctx, connect.NewRequest(req)) - if err != nil { - return nil, nil, err - } - return res.Msg.Items, res.Msg.Next, nil - }) - - ll.InfoContext(ctx, "listing projects") - enc := protojson.MarshalOptions{Multiline: false} - os.Stdout.WriteString("[\n") - first := true - for projects.Next() { - if first { - first = false - } else { - os.Stdout.WriteString(",\n") - } - os.Stdout.WriteString("\t") - st := projects.Current() - _, err := os.Stdout.WriteString(enc.Format(st)) - if err != nil { - return err - } - } - os.Stdout.WriteString("\n") - os.Stdout.WriteString("]\n") - if err := projects.Err(); err != nil { - return err - } - - return nil - }, - }, - }, - } -} diff --git a/cmd/humanlog/auth.go b/cmd/humanlog/auth.go deleted file mode 100644 index 6e3e0b99..00000000 --- a/cmd/humanlog/auth.go +++ /dev/null @@ -1,108 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log/slog" - "net/http" - "os" - - "connectrpc.com/connect" - userpb "github.com/minitape/api/go/svc/user/v1" - "github.com/minitape/api/go/svc/user/v1/userv1connect" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/urfave/cli" -) - -const ( - authCmdName = "auth" -) - -func authCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - return cli.Command{ - Name: authCmdName, - Usage: "Login with humanlog.io", - Subcommands: cli.Commands{ - { - Name: "login", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, getConnectOpts(cctx)) - return err - }, - }, - { - Name: "whoami", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - apiURL := getAPIUrl(cctx) - state := getState(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - tokenSource := getTokenSource(cctx) - userToken, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return fmt.Errorf("looking up local user state: %v", err) - } - - ll := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})) - clOpts = append(clOpts, - connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - ), - ) - - printFact("token user ID", userToken.UserId) - - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - res, err := userClient.Whoami(ctx, connect.NewRequest(&userpb.WhoamiRequest{})) - if err != nil { - return fmt.Errorf("looking up who you are: %v", err) - } - - printFact("username", res.Msg.User.Username) - printFact("email", res.Msg.User.Email) - printFact("verified", res.Msg.User.EmailVerified) - printFact("name", res.Msg.User.Name) - printFact("registered since", res.Msg.User.CreatedAt.AsTime()) - printFact("logged into org", res.Msg.CurrentOrganization.Name) - - return nil - }, - }, - { - Name: "logout", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - tokenSource := getTokenSource(cctx) - - ll := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})) - clOpts := append(getConnectOpts(cctx), connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - - return performLogoutFlow(ctx, userClient, tokenSource, "") - }, - }, - }, - } -} diff --git a/cmd/humanlog/config.go b/cmd/humanlog/config.go index 8670215a..0a743e89 100644 --- a/cmd/humanlog/config.go +++ b/cmd/humanlog/config.go @@ -1,21 +1,12 @@ package main import ( - "context" "encoding/json" "fmt" - "log/slog" - "net/http" - "net/url" "os" "strings" - "connectrpc.com/connect" - typesv1 "github.com/minitape/api/go/types/v1" "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/pkg/browser" "github.com/urfave/cli" ) @@ -24,15 +15,7 @@ const ( ) func configCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, ) cli.Command { return cli.Command{ @@ -58,17 +41,6 @@ func configCmd( return nil }, }, - { - Name: "edit", - Action: func(cctx *cli.Context) error { - baseSiteU, err := url.Parse(getBaseSiteURL(cctx)) - if err != nil { - return fmt.Errorf("parsing base site URL: %v", err) - } - editConfigPath := baseSiteU.JoinPath("/settings/localhost").String() - return browser.OpenURL(editConfigPath) - }, - }, { Name: "show", Action: func(cctx *cli.Context) error { @@ -109,129 +81,6 @@ func configCmd( return cfg.WriteBack() }, }, - { - Name: "enable", - Subcommands: []cli.Command{ - { - Name: "query-engine", - Usage: "(experimental) enables the localhost query engine", - Description: "(experimental) enables the localhost query engine", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - cfg := getCfg(cctx) - if cfg.Runtime == nil { - cfg.Runtime = &typesv1.RuntimeConfig{} - } - if cfg.Runtime.ExperimentalFeatures == nil { - cfg.Runtime.ExperimentalFeatures = &typesv1.RuntimeConfig_ExperimentalFeatures{} - } - localhostCfg, err := config.GetDefaultLocalhostConfig() - if err != nil { - return fmt.Errorf("getting default localhost config: %v", err) - } - cfg.Runtime.ExperimentalFeatures.ServeLocalhost = localhostCfg - if err := cfg.WriteBack(); err != nil { - return fmt.Errorf("enabling localhost feature: %v", err) - } - svc, err := prepareServiceCmd(cctx, - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getBaseSiteURL, - getHTTPClient, - ) - if err != nil { - return fmt.Errorf("failed to get humanlog service details: %v", err) - } - // in case it already ran - if err = svc.Stop(ctx); err != nil { - logdebug("failed to stop if already started: %v", err) - } - if err := svc.Uninstall(); err != nil { - logdebug("failed to uninstall service if already installed: %v", err) - } - if err := svc.Install(); err != nil { - return fmt.Errorf("installing humanlog service: %v", err) - } - if err := svc.Start(ctx); err != nil { - return fmt.Errorf("installing humanlog service: %v", err) - } - loginfo("localhost query engine enabled") - return nil - }, - }, - }, - }, - { - Name: "disable", - Subcommands: []cli.Command{ - { - Name: "query-engine", - Usage: "(experimental) disables the localhost query engine", - Description: "(experimental) disables the localhost query engine", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - cfg := getCfg(cctx) - - svc, err := prepareServiceCmd(cctx, - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getBaseSiteURL, - getHTTPClient, - ) - if err != nil { - return fmt.Errorf("failed to get humanlog service details: %v", err) - } - - // in case it already ran - if err = svc.Stop(ctx); err != nil { - logdebug("failed to stop if already started: %v", err) - } - if err := svc.Uninstall(); err != nil { - logdebug("failed to uninstall service if already installed: %v", err) - } - - if cfg.Runtime != nil && cfg.Runtime.ExperimentalFeatures != nil && cfg.Runtime.ExperimentalFeatures.ServeLocalhost != nil { - cfg.Runtime.ExperimentalFeatures.ServeLocalhost = nil - if err := cfg.WriteBack(); err != nil { - return fmt.Errorf("enabling localhost feature: %v", err) - } - } - - loginfo("localhost query engine disabled") - return nil - }, - }, - }, - }, - { - Name: "hack", - Subcommands: []cli.Command{ - { - Name: "for-netskope", - Description: "hacks to make netskope happy: http2 -> http1", - Action: func(cctx *cli.Context) error { - cfg := getCfg(cctx) - if cfg.Runtime == nil { - cfg.Runtime = &typesv1.RuntimeConfig{} - } - if cfg.Runtime.ApiClient == nil { - cfg.Runtime.ApiClient = &typesv1.RuntimeConfig_ClientConfig{} - } - httpProtocol := typesv1.RuntimeConfig_ClientConfig_HTTP1 - cfg.Runtime.ApiClient.HttpProtocol = &httpProtocol - return cfg.WriteBack() - }, - }, - }, - }, }, } } diff --git a/cmd/humanlog/demo.go b/cmd/humanlog/demo.go deleted file mode 100644 index 4f5d712c..00000000 --- a/cmd/humanlog/demo.go +++ /dev/null @@ -1,220 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - "log/slog" - "net/http" - "net/url" - "os" - "time" - - "connectrpc.com/connect" - "github.com/charmbracelet/log" - "github.com/minitape/api/go/svc/auth/v1/authv1connect" - userv1 "github.com/minitape/api/go/svc/user/v1" - "github.com/minitape/api/go/svc/user/v1/userv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/localserver" - "github.com/humanlogio/humanlog/internal/localstate" - "github.com/humanlogio/humanlog/internal/logqleval" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/humanlogio/humanlog/pkg/localstorage" - "github.com/pkg/browser" - "github.com/urfave/cli" - "google.golang.org/protobuf/types/known/structpb" - - otlplogssvcpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" - otlpmetricssvcpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - otlptracesvcpb "go.opentelemetry.io/proto/otlp/collector/trace/v1" -) - -const ( - demoCmdName = "demo" -) - -func demoCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - return cli.Command{ - Name: demoCmdName, - Usage: "Run humanlog in demo mode.", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - // ll := getLogger(cctx) - - handler := log.New(os.Stderr) - handler.SetReportTimestamp(true) - ll := slog.New(handler) - - cfg := getCfg(cctx) - state := getState(cctx) - ownVersion := version - app := &localstorage.AppCtx{ - EnsureLoggedIn: func(ctx context.Context) error { - return fmt.Errorf("please via `humanlog auth login`") - }, - Features: nil, - Config: cfg, - State: state, - } - engineConfig, err := structpb.NewStruct(map[string]any{ - "path": "", // in-memory - }) - if err != nil { - return err - } - localhostCfg, err := config.GetDefaultLocalhostConfig() - if err != nil { - return err - } - port := localhostCfg.Port - localhostCfg.Port = port + 1000 // use a higher port - localhostCfg.EngineConfig = engineConfig // use the in-memory storage engine - localhostCfg.Otlp = nil // don't ingest OTLP - - openStorage := func(ctx context.Context) (localstorage.Storage, error) { - storage, err := localstorage.Open( - ctx, - localhostCfg.Engine, - ll.WithGroup("storage"), - localhostCfg.EngineConfig.AsMap(), - app, - ) - if err != nil { - return nil, err - } - - // seed demo data - _, err = storage.ExportTraces(ctx, &demoTraceData) - if err != nil { - return nil, err - } - - _, err = storage.ExportMetrics(ctx, &demoMetricsData) - if err != nil { - return nil, err - } - - _, err = storage.ExportLogs(ctx, &demoLogsData) - if err != nil { - return nil, err - } - - return storage, nil - } - openState := func(ctx context.Context, db localstorage.Storage) (localstate.DB, error) { - return localstate.NewMemory(), nil - } - - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - - publicClOpts := connect.WithInterceptors(auth.NewRefreshedUserAuthInterceptor(ll, tokenSource)) - authedClOpts := connect.WithInterceptors(auth.Interceptors(ll, tokenSource)...) - - authSvc := authv1connect.NewAuthServiceClient(httpClient, apiURL, publicClOpts) - userSvc := userv1connect.NewUserServiceClient(httpClient, apiURL, authedClOpts) - - baseSiteURL, _ := url.Parse(getBaseSiteURL(cctx)) - demoURL := baseSiteURL.JoinPath("/localhost/query") - q := demoURL.Query() - q.Add("demo_port", fmt.Sprintf("%d", localhostCfg.Port)) - demoURL.RawQuery = q.Encode() - - registerOnCloseServer := func(srv *http.Server) { - // use this hook to open the browser - time.AfterFunc(time.Second, func() { - if err := browser.OpenURL(demoURL.String()); err != nil { - loginfo("open your browser to interact with the demo:\n\n\t%s\n\n", demoURL.String()) - } - }) - - <-ctx.Done() - loginfo("requesting for demo to shutdown") - if err := srv.Close(); err != nil { - logerror("unclean shutdown for demo server: %v", err) - } - } - - return localserver.ServeLocalhost(ctx, ll, localhostCfg, ownVersion, app, openStorage, openState, registerOnCloseServer, - func(ctx context.Context, returnToURL string) error { - if _, err := performLoginFlow(ctx, state, authSvc, tokenSource, "", 0, returnToURL); err != nil { - return err - } - return nil - }, - func(ctx context.Context, returnToURL string) error { - if err := performLogoutFlow(ctx, userSvc, tokenSource, returnToURL); err != nil { - return err - } - return nil - }, - func(ctx context.Context) error { - return fmt.Errorf("self-update not enabled in demo mode") - }, - func(ctx context.Context) error { - return fmt.Errorf("self-restart not enabled in demo mode") - }, - func(ctx context.Context) (*typesv1.LocalhostConfig, error) { - return cfg.CurrentConfig, nil - }, - func(ctx context.Context, newCfg *typesv1.LocalhostConfig) error { - cfg.CurrentConfig = newCfg - return cfg.WriteBack() - }, - func(ctx context.Context) (*userv1.WhoamiResponse, error) { - cerr := new(connect.Error) - res, err := userSvc.Whoami(ctx, connect.NewRequest(&userv1.WhoamiRequest{})) - if errors.As(err, &cerr) && cerr.Code() == connect.CodeUnauthenticated { - return &userv1.WhoamiResponse{ - User: &typesv1.User{Username: "demouser"}, - }, nil - } else if err != nil { - return nil, fmt.Errorf("looking up user authentication status: %v", err) - } - return res.Msg, nil - }, - func(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error { - args := []any{slog.String("name", ar.Spec.Name)} - if o != nil { - for _, kv := range o.Kvs { - v, err := logqleval.ResolveVal(kv.Value, logqleval.MakeFlatGoMap, logqleval.MakeFlatGoSlice) - if err != nil { - panic(err) - } - args = append(args, slog.Any(kv.Key, v)) - } - } - switch ar.Status.Status.(type) { - case *typesv1.AlertRuleStatus_Unknown: - ll.InfoContext(ctx, "alert in unknown status", args...) - case *typesv1.AlertRuleStatus_Ok: - ll.InfoContext(ctx, "alert in ok status", args...) - case *typesv1.AlertRuleStatus_Pending: - ll.WarnContext(ctx, "alert in pending status", args...) - case *typesv1.AlertRuleStatus_Firing: - ll.ErrorContext(ctx, "alert is firing!", args...) - } - return nil - }, - ) - }, - } -} - -var demoLogsData = otlplogssvcpb.ExportLogsServiceRequest{} -var demoMetricsData = otlpmetricssvcpb.ExportMetricsServiceRequest{} -var demoTraceData = otlptracesvcpb.ExportTraceServiceRequest{} diff --git a/cmd/humanlog/environment.go b/cmd/humanlog/environment.go deleted file mode 100644 index 8d8f317f..00000000 --- a/cmd/humanlog/environment.go +++ /dev/null @@ -1,457 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log" - "log/slog" - "net/http" - "strconv" - - "connectrpc.com/connect" - "github.com/charmbracelet/huh" - organizationv1 "github.com/minitape/api/go/svc/organization/v1" - "github.com/minitape/api/go/svc/organization/v1/organizationv1connect" - "github.com/minitape/api/go/svc/product/v1/productv1connect" - tokenv1 "github.com/minitape/api/go/svc/token/v1" - "github.com/minitape/api/go/svc/token/v1/tokenv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/iterapi" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/urfave/cli" - "google.golang.org/protobuf/types/known/timestamppb" -) - -const ( - environmentCmdName = "environment" -) - -func environmentCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - return cli.Command{ - Hidden: hideUnreleasedFeatures == "true", - Name: environmentCmdName, - ShortName: "env", - Usage: "Manage environments for the current user or org.", - Before: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - return nil - }, - Subcommands: []cli.Command{ - { - Name: "set-current", - ArgsUsage: "", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - - environmentName := cctx.Args().First() - if environmentName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - - // lookup `environmentName` and set its ID in `state` - _ = ctx - _ = state - _ = tokenSource - _ = apiURL - _ = httpClient - _ = environmentName - - return nil - }, - }, - { - Name: "get-current", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - environmentID, err := ensureEnvironmentSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - orgClient := organizationv1connect.NewOrganizationServiceClient(httpClient, apiURL, clOpts...) - iter := ListEnvironments(ctx, orgClient) - a, ok, err := iterapi.Find(iter, func(el *organizationv1.ListEnvironmentResponse_ListItem) bool { - return el.Environment.Id == environmentID - }) - if err != nil { - return err - } - if !ok { - logwarn("environment with id %d doesn't exist anymore, select another one", environmentID) - state.CurrentEnvironmentID = nil - return state.WriteBack() - } - printFact("id", a.Environment.Id) - printFact("name", a.Environment.Name) - return nil - }, - }, - { - Name: "create", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - productClient := productv1connect.NewProductServiceClient(httpClient, apiURL, clOpts...) - orgClient := organizationv1connect.NewOrganizationServiceClient(httpClient, apiURL, clOpts...) - - var ( - confirmToken string - ) - - _, prices, err := huhSelectProduct(ctx, "", typesv1.Product_Environment.Enum(), productClient, "Select a plan for the environment") - if err != nil { - return err - } - price, err := huhSelectPrice(ctx, prices, "Select a price for that plan") - if err != nil { - return err - } - - payment := &organizationv1.CreateEnvironmentRequest_Stripe_{ - Stripe: &organizationv1.CreateEnvironmentRequest_Stripe{ - ConfirmationToken: confirmToken, - PriceId: price.StripeId, - }, - } - req := &organizationv1.CreateEnvironmentRequest{Payment: payment} - if err := huh.NewForm( - huh.NewGroup( - huh.NewInput().Title("Pick a name").Value(&req.EnvironmentName), - ), - ).RunWithContext(ctx); err != nil { - return err - } - - res, err := orgClient.CreateEnvironment(ctx, connect.NewRequest(req)) - if err != nil { - return err - } - environment := res.Msg.Environment - printFact("created id", environment.Id) - printFact("created name", environment.Name) - return nil - }, - }, - { - Name: "get", - ArgsUsage: "", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - - environmentName := cctx.Args().First() - if environmentName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - clOpts := getConnectOpts(cctx) - _, err := ensureOrgSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - orgClient := organizationv1connect.NewOrganizationServiceClient(httpClient, apiURL, clOpts...) - - el, ok, err := iterapi.Find(ListEnvironments(ctx, orgClient), func(el *organizationv1.ListEnvironmentResponse_ListItem) bool { - return el.Environment.Name == environmentName - }) - if err != nil { - return err - } - if !ok { - return fmt.Errorf("no environment with name %q", environmentName) - } - printFact("id", el.Environment.Id) - printFact("name", el.Environment.Name) - return nil - }, - }, - { - Name: "list", - Usage: "list the environments for the current user or org", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - orgClient := organizationv1connect.NewOrganizationServiceClient(httpClient, apiURL, clOpts...) - - iter := ListEnvironments(ctx, orgClient) - - count := 0 - for iter.Next() { - count++ - li := iter.Current() - environment := li.Environment - printFact("environment name", environment.Name) - } - if err := iter.Err(); err != nil { - return err - } - log.Printf("%d environments", count) - return nil - }, - }, - { - Name: "generate-token", - Usage: "generate an API token for the current environment", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - environmentID, err := ensureEnvironmentSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - expiresAt, err := hubAskTokenExpiry("Creating an environment token") - if err != nil { - return err - } - roles, err := hubAskTokenRoles("Creating an environment token") - if err != nil { - return err - } - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - - tokenClient := tokenv1connect.NewTokenServiceClient(httpClient, apiURL, clOpts...) - - res, err := tokenClient.GenerateEnvironmentToken(ctx, connect.NewRequest(&tokenv1.GenerateEnvironmentTokenRequest{ - EnvironmentId: environmentID, - ExpiresAt: timestamppb.New(expiresAt), - Roles: roles, - })) - if err != nil { - return fmt.Errorf("generating environment token: %v", err) - } - token := res.Msg.Token - printFact("id", token.TokenId) - printFact("environment id", token.EnvironmentId) - printFact("expires at", token.ExpiresAt.AsTime()) - printFact("roles", token.Roles) - printFact("token (secret! do not lose)", token.Token) - return nil - }, - }, - { - Name: "revoke-token", - Usage: "revoke an API token for the current environment", - ArgsUsage: "", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - environmentID, err := ensureEnvironmentSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - - tokenIdStr := cctx.Args().First() - if tokenIdStr == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - tokenID, err := strconv.ParseInt(tokenIdStr, 10, 64) - if err != nil { - logerror("invalid argument: ") - return err - } - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - - tokenClient := tokenv1connect.NewTokenServiceClient(httpClient, apiURL, clOpts...) - - loginfo("revoking token %d on environment %d", tokenID, environmentID) - res, err := tokenClient.RevokeEnvironmentToken(ctx, connect.NewRequest(&tokenv1.RevokeEnvironmentTokenRequest{ - EnvironmentId: environmentID, - TokenId: tokenID, - })) - if err != nil { - return fmt.Errorf("revoking environment token: %v", err) - } - _ = res - loginfo("token revoked") - return nil - }, - }, - { - Name: "view-token", - Usage: "view the details of an API token for the current environment", - ArgsUsage: "", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - environmentID, err := ensureEnvironmentSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - - tokenIdStr := cctx.Args().First() - if tokenIdStr == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - tokenID, err := strconv.ParseInt(tokenIdStr, 10, 64) - if err != nil { - logerror("invalid argument: ") - return err - } - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - - tokenClient := tokenv1connect.NewTokenServiceClient(httpClient, apiURL, clOpts...) - - res, err := tokenClient.GetEnvironmentToken(ctx, connect.NewRequest(&tokenv1.GetEnvironmentTokenRequest{ - EnvironmentId: environmentID, - TokenId: tokenID, - })) - if err != nil { - return fmt.Errorf("revoking environment token: %v", err) - } - token := res.Msg.Token - printFact("id", token.TokenId) - printFact("environment id", token.EnvironmentId) - printFact("roles", token.Roles) - printFact("expires at", token.ExpiresAt.AsTime()) - if token.LastUsedAt != nil { - printFact("last used at", token.LastUsedAt.AsTime()) - } else { - printFact("last used at", "never") - } - if token.RevokedAt != nil { - printFact("revoked at", token.RevokedAt.AsTime()) - } else { - printFact("revoked at", "never") - } - return nil - }, - }, - { - Name: "list-tokens", - Usage: "list the API tokens for the current environment", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - environmentID, err := ensureEnvironmentSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - - tokenClient := tokenv1connect.NewTokenServiceClient(httpClient, apiURL, clOpts...) - - hasAny := false - iter := ListEnvironmentTokens(ctx, environmentID, tokenClient) - for iter.Next() { - hasAny = true - token := iter.Current().Token - printFact("id", token.TokenId) - } - if err := iter.Err(); err != nil { - return fmt.Errorf("listing tokens: %v", err) - } - if !hasAny { - loginfo("no environment token found") - } - - return nil - }, - }, - }, - } -} - -func promptCreateEnvironment(ctx context.Context, - ll *slog.Logger, - cctx *cli.Context, - state *state.State, - tokenSource *auth.UserRefreshableTokenSource, - apiURL string, - httpClient *http.Client, -) (int64, error) { - panic("todo") -} diff --git a/cmd/humanlog/genny.go b/cmd/humanlog/genny.go deleted file mode 100644 index 8a1eddc0..00000000 --- a/cmd/humanlog/genny.go +++ /dev/null @@ -1,403 +0,0 @@ -package main - -import ( - "context" - "fmt" - "io" - "log/slog" - "os" - "strconv" - "strings" - "time" - - "github.com/google/uuid" - gonanoid "github.com/matoous/go-nanoid" - "golang.org/x/exp/rand" - - "github.com/humanlogio/humanlog" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/urfave/cli" - - "gonum.org/v1/gonum/stat/distuv" -) - -// note: all the randomness clamping with % leads to not -// really random and it's all not correct and it's not meant -// to be, this is just written real fast to get it going. feel -// free to make this better and fancier! - -const ( - gennyCmdName = "genny" -) - -func gennyCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, -) cli.Command { - - seedFlag := cli.Uint64Flag{ - Name: "seed", - Value: uint64(time.Now().UnixNano()), - } - startAtFlag := cli.StringFlag{ - Name: "start_at", - Value: time.Now().Format(time.RFC3339), - } - averagePerInternalFlag := cli.Float64Flag{ - Name: "logs_per_s", - Value: 50, - } - - return cli.Command{ - Name: gennyCmdName, - Usage: "Generate fake logs", - Hidden: true, - Flags: []cli.Flag{ - seedFlag, - startAtFlag, - averagePerInternalFlag, - }, - - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - seed := cctx.Uint64(seedFlag.Name) - start, err := time.Parse(time.RFC3339, cctx.String(startAtFlag.Name)) - if err != nil { - return fmt.Errorf("invalid start: %v", err) - } - averagePerInternal := cctx.Float64(averagePerInternalFlag.Name) - return genny(ctx, seed, start, time.Second, averagePerInternal, os.Stdout) - }, - } -} - -func genny( - ctx context.Context, - seed uint64, - start time.Time, - interval time.Duration, - averagePerInterval float64, - out io.Writer, -) error { - src := rand.NewSource(seed) - arrivalRateDist := distuv.Poisson{ - Src: src, - Lambda: averagePerInterval, - } - - now := start - for { - if err := emitMessage(out, now, src); err != nil { - return err - } - nextArrival := arrivalRateDist.Rand() - nextMsgIn := time.Duration(float64(interval) / nextArrival) - select { - case <-ctx.Done(): - return nil - case <-time.After(nextMsgIn): - now = now.Add(nextMsgIn) - } - } -} - -func emitMessage(out io.Writer, now time.Time, src rand.Source) error { - t := ts(now, src) - l := lvl(src) - m := msg(src) - k := kvs(src) - _, err := fmt.Fprintln(out, t+l+m+k) - return err -} - -var opts = humanlog.DefaultOptions() - -func ts(now time.Time, src rand.Source) string { - if src.Uint64()%20 == 0 { // 1/20 times, no timestamp - return "" - } - key := randel(src, opts.TimeFields) - format := randel(src, humanlog.TimeFormats) - return key + "=" + now.Format(format) -} - -func kvs(src rand.Source) string { - keyCount := src.Uint64() % 20 - if keyCount > 20 { - panic(keyCount) - } - if keyCount == 0 { - return "" - } - buf := strings.Builder{} - for range keyCount { - buf.WriteString(" ") - buf.WriteString(genKey(src)) - buf.WriteString("=") - buf.WriteString(genVal(src)) - } - return buf.String() -} - -func genKey(src rand.Source) string { - i := src.Uint64() - dice := int(i % 100) - switch { - case dice >= 0 && dice < 4: - return []string{ - "request_id", - "trace_id", - "RequestID", - "req.id", - }[dice] - case dice >= 4 && dice < 6: - return "user" - case dice >= 6 && dice < 8: - return "org" - case dice >= 8 && dice < 12: - keys := []string{ - "index", - "project", - "car", - "idk", - } - return keys[dice%len(keys)] - default: - return genString(src, false) - } -} - -var bases = []int{2, 8, 10, 16} -var fmtbytes = []byte{'b', 'e', 'E', 'f', 'g', 'G', 'x', 'X'} -var bools = []string{"true", "True", "false", "False"} -var bitsizes = []int{32, 64} - -func genVal(src rand.Source) string { - i := src.Uint64() - switch i % 4 { - case 0: - base := randel(src, bases) - return strconv.FormatUint(i, base) - case 1: - f := (distuv.Normal{ - Mu: float64(i), - Src: src, - }).Rand() - fmt := randel(src, fmtbytes) - prec := int(src.Uint64()) % 10 - if prec == 0 { - prec = -1 - } - bitsize := randel(src, bitsizes) - return strconv.FormatFloat(f, - fmt, - prec, - bitsize, - ) - case 2: - return randel(src, bools) - case 3: - return genString(src, true) - } - panic("missing case") -} - -func randel[T any](src rand.Source, sl []T) T { - i := src.Uint64() % uint64(len(sl)) - return sl[i] -} - -func lvl(src rand.Source) string { - key := " " + randel(src, opts.LevelFields) - switch src.Uint64() % 5 { - case 0: - return key + "=DEBUG" - case 1: - return key + "=INFO" - case 2: - return key + "=WARN" - case 3: - return key + "=ERROR" - case 4: - return "" - } - panic("missing case") -} - -func msg(src rand.Source) string { - words := (src.Uint64() % 10) - if words > 10 { - panic(words) - } - if words == 0 { - return "" - } - key := " " + randel(src, opts.MessageFields) + "=" - buf := strings.Builder{} - buf.WriteString(genString(src, false)) - for range words { - buf.WriteRune(' ') - buf.WriteString(genString(src, false)) - } - return key + strconv.Quote(buf.String()) -} - -func genString(src rand.Source, genIDs bool) string { - if !genIDs { - switch i := src.Uint64() % 3; i { - case 0, 1: - return randel(src, nouns) - case 2: - return randel(src, adjectives) - } - } - switch i := src.Uint64() % 4; i { - case 0, 1: - return randel(src, nouns) - case 2: - return randel(src, adjectives) - case 3: - return uuid.NewString() - case 4: - return gonanoid.MustID(int(src.Uint64() % 20)) - default: - panic(i) - } -} - -var adjectives = []string{ - "aged", - "ancient", - "billowing", - "black", - "blue", - "cold", - "cool", - "crimson", - "damp", - "dawn", - "delicate", - "divine", - "falling", - "floral", - "fragrant", - "frosty", - "green", - "holy", - "late", - "lingering", - "little", - "lively", - "long", - "morning", - "muddy", - "nameless", - "old", - "patient", - "polished", - "proud", - "purple", - "quiet", - "red", - "rough", - "shy", - "small", - "snowy", - "solitary", - "spring", - "still", - "throbbing", - "wandering", - "weathered", - "white", - "wild", - "winter", - "wispy", - "withered", - "bold", - "broken", - "icy", - "restless", - "sparkling", - "twilight", - "young", - "bitter", - "dark", - "dry", - "empty", - "hidden", - "misty", - "silent", - "summer", - "autumn", -} - -var nouns = []string{ - "bird", - "breeze", - "brook", - "bush", - "butterfly", - "cherry", - "cloud", - "darkness", - "dawn", - "dew", - "dream", - "dust", - "feather", - "field", - "fire", - "firefly", - "flower", - "fog", - "forest", - "frog", - "frost", - "glade", - "glitter", - "grass", - "haze", - "hill", - "lake", - "leaf", - "meadow", - "moon", - "morning", - "mountain", - "night", - "paper", - "pine", - "pond", - "rain", - "resonance", - "river", - "sea", - "shadow", - "shape", - "silence", - "sky", - "smoke", - "snow", - "snowflake", - "sound", - "star", - "sun", - "sun", - "sunset", - "surf", - "thunder", - "tree", - "violet", - "voice", - "water", - "water", - "waterfall", - "wave", - "wildflower", - "wind", - "wood", -} diff --git a/cmd/humanlog/helper.go b/cmd/humanlog/helper.go deleted file mode 100644 index aaf05e17..00000000 --- a/cmd/humanlog/helper.go +++ /dev/null @@ -1,494 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - "log" - "log/slog" - "net/http" - "os" - "runtime" - "time" - - "connectrpc.com/connect" - "github.com/charmbracelet/huh" - "github.com/fatih/color" - authv1 "github.com/minitape/api/go/svc/auth/v1" - "github.com/minitape/api/go/svc/auth/v1/authv1connect" - organizationv1 "github.com/minitape/api/go/svc/organization/v1" - "github.com/minitape/api/go/svc/organization/v1/organizationv1connect" - productv1 "github.com/minitape/api/go/svc/product/v1" - "github.com/minitape/api/go/svc/product/v1/productv1connect" - projectv1 "github.com/minitape/api/go/svc/project/v1" - "github.com/minitape/api/go/svc/project/v1/projectv1connect" - tokenv1 "github.com/minitape/api/go/svc/token/v1" - "github.com/minitape/api/go/svc/token/v1/tokenv1connect" - userv1 "github.com/minitape/api/go/svc/user/v1" - "github.com/minitape/api/go/svc/user/v1/userv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/iterapi" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/pkg/browser" - "github.com/urfave/cli" -) - -func ensureLoggedIn( - ctx context.Context, - cctx *cli.Context, - state *state.State, - tokenSource *auth.UserRefreshableTokenSource, - apiURL string, - httpClient *http.Client, - clOpts []connect.ClientOption, -) (*typesv1.UserToken, error) { - userToken, err := tokenSource.GetUserToken(ctx) - if err != nil { - return nil, fmt.Errorf("looking up local user state: %v", err) - } - authClient := authv1connect.NewAuthServiceClient(httpClient, apiURL, clOpts...) - if userToken == nil { - confirms := false - err := huh.NewConfirm(). - Title("You're logged out. Would you like to login?"). - Affirmative("Yes!"). - Negative("No."). - Value(&confirms). - WithTheme(huhTheme). - Run() - if err != nil { - return nil, err - } - if !confirms { - return nil, fmt.Errorf("aborting") - } - - // no user auth, perform login flow - t, err := performLoginFlow(ctx, state, authClient, tokenSource, "", 0, "") - if err != nil { - return nil, fmt.Errorf("performing login: %v", err) - } - userToken = t - } else { - // check that the token is valid - ll := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})) - user, err := checkUserLoggedIn(ctx, ll, httpClient, apiURL, tokenSource, clOpts) - if err != nil { - return nil, fmt.Errorf("requesting whoami: %v", err) - } - if user == nil { - // token isn't valid anymore, login again - confirms := true - err := huh.NewConfirm(). - Title("Your session has expired. Would you like to login again?"). - Affirmative("Yes!"). - Negative("No."). - Value(&confirms). - WithTheme(huhTheme). - Run() - if err != nil { - return nil, err - } - if !confirms { - return nil, fmt.Errorf("aborting") - } - - t, err := performLoginFlow(ctx, state, authClient, tokenSource, "", 0, "") - if err != nil { - return nil, fmt.Errorf("performing login: %v", err) - } - userToken = t - } - } - return userToken, nil -} - -func checkUserLoggedIn(ctx context.Context, ll *slog.Logger, httpClient *http.Client, apiURL string, tokenSource *auth.UserRefreshableTokenSource, clOpts []connect.ClientOption) (*typesv1.User, error) { - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - cerr := new(connect.Error) - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - res, err := userClient.Whoami(ctx, connect.NewRequest(&userv1.WhoamiRequest{})) - if errors.As(err, &cerr) && cerr.Code() == connect.CodeUnauthenticated { - return nil, nil - } - if err != nil { - return nil, err - } - return res.Msg.User, nil -} - -func performLoginFlow( - ctx context.Context, - state *state.State, - authClient authv1connect.AuthServiceClient, - tokenSource *auth.UserRefreshableTokenSource, - username string, - organizationID int64, - returnToURL string, -) (*typesv1.UserToken, error) { - - username, err := ensureUsername(ctx, state, tokenSource, username) - if err != nil { - return nil, fmt.Errorf("ensuring a username is specified") - } - - req := &authv1.BeginDeviceAuthRequest{ - ReturnToUrl: returnToURL, - Username: username, - } - if organizationID != 0 { - req.Organization = &authv1.BeginDeviceAuthRequest_ById{ById: organizationID} - } - res, err := authClient.BeginDeviceAuth(ctx, connect.NewRequest(req)) - if err != nil { - return nil, fmt.Errorf("requesting auth URL: %v", err) - } - - url := res.Msg.Url - deviceCode := res.Msg.DeviceCode - userCode := res.Msg.UserCode - pollUntil := res.Msg.ExpiresAt - pollInterval := res.Msg.PollInterval.AsDuration() - if err := browser.OpenURL(url); err != nil { - logwarn("unable to detect browser on system, falling back to manual: %v", err) - loginfo("please open this URL in your browser:\n\n\t%s\n\n", url) - } else { - loginfo("opening signup link") - } - - ctx, cancel := context.WithDeadline(ctx, pollUntil.AsTime()) - defer cancel() - - ticker := time.NewTicker(pollInterval) - defer ticker.Stop() - - var ( - userToken *typesv1.UserToken - ) -poll_for_tokens: - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-ticker.C: - } - - res, err := authClient.CompleteDeviceAuth(ctx, connect.NewRequest(&authv1.CompleteDeviceAuthRequest{ - DeviceCode: deviceCode, - UserCode: userCode, - - Architecture: runtime.GOARCH, - OperatingSystem: runtime.GOOS, - })) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - switch cerr.Code() { - case connect.CodeFailedPrecondition: - continue poll_for_tokens - } - } - return nil, fmt.Errorf("waiting for user to be authenticated: %v", err) - } - - userToken = res.Msg.Token - break poll_for_tokens - } - - err = tokenSource.SetUserToken(ctx, userToken) - if err != nil { - return nil, fmt.Errorf("saving credentials to keyring: %v", err) - } - state.LoggedInUsername = &userToken.Username - state.LoggedInOrgID = &userToken.OrgId - if err := state.WriteBack(); err != nil { - return nil, fmt.Errorf("saving user info: %v", err) - } - return userToken, nil -} - -func performLogoutFlow(ctx context.Context, userSvc userv1connect.UserServiceClient, tokenSource *auth.UserRefreshableTokenSource, returnToURL string) error { - return tokenSource.ClearToken(ctx) -} - -func ensureOrgSelected( - ctx context.Context, - ll *slog.Logger, - cctx *cli.Context, - state *state.State, - tokenSource *auth.UserRefreshableTokenSource, - apiURL string, - httpClient *http.Client, - clOpts []connect.ClientOption, -) (int64, error) { - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - - client := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - orgID, err := huhSelectOrganizations(ctx, client, "You belong to many orgs. Which one would you like to use?") - if err != nil { - return -1, err - } - return orgID, state.WriteBack() -} - -func ensureUsername(ctx context.Context, state *state.State, tokenSource *auth.UserRefreshableTokenSource, hintedUsername string) (string, error) { - ut, err := tokenSource.GetUserToken(ctx) - if err != nil { - return "", nil - } - var username string - switch { - case ut != nil && state.LoggedInUsername == nil: - username = ut.Username - state.LoggedInUsername = &username - err = state.WriteBack() - case state.LoggedInUsername != nil: - username = *state.LoggedInUsername - default: - username = hintedUsername - } - if username == "" { - username, err = huhPickUsername(ctx) - } - return username, err -} - -func huhPickUsername(ctx context.Context) (string, error) { - var username string - return username, huh.NewInput().Title("Pick a username").Value(&username).Run() -} - -func huhSelectOrganizations(ctx context.Context, client userv1connect.UserServiceClient, title string) (int64, error) { - var options []huh.Option[*typesv1.Organization] - iter := ListOrganizations(ctx, client) - for iter.Next() { - org := iter.Current().Organization - options = append(options, huh.NewOption(org.Name, org)) - } - if err := iter.Err(); err != nil { - return -1, fmt.Errorf("no org selected and couldn't list user orgs: %v", err) - } - if len(options) == 0 { - return -1, fmt.Errorf("no org is attached to your user, this is a bug. please contact support at hi@humanlog.io") - } - if len(options) == 1 { - return options[0].Value.Id, nil - } - var selected *typesv1.Organization - err := huh.NewSelect[*typesv1.Organization](). - Title(title). - Options(options...). - Value(&selected). - WithTheme(huhTheme). - Run() - if err != nil { - return -1, fmt.Errorf("prompting for org selection: %v", err) - } - return selected.Id, nil -} - -func huhSelectProduct(ctx context.Context, category string, scope *typesv1.Product_Scope, client productv1connect.ProductServiceClient, title string) (*typesv1.Product, []*typesv1.Price, error) { - var options []huh.Option[*productv1.ListProductResponse_ListItem] - iter := ListProduct(ctx, category, scope, client) - for iter.Next() { - item := iter.Current() - options = append(options, huh.NewOption(item.Product.Name, item)) - } - if err := iter.Err(); err != nil { - return nil, nil, fmt.Errorf("couldn't list products: %v", err) - } - if len(options) == 0 { - return nil, nil, fmt.Errorf("no product exists, this is a bug. please contact support at hi@humanlog.io") - } - if len(options) == 1 { - return options[0].Value.Product, options[0].Value.Prices, nil - } - var selected *productv1.ListProductResponse_ListItem - err := huh.NewSelect[*productv1.ListProductResponse_ListItem](). - Title(title). - Options(options...). - Value(&selected). - WithTheme(huhTheme). - Run() - if err != nil { - return nil, nil, fmt.Errorf("prompting for product selection: %v", err) - } - return selected.Product, selected.Prices, nil -} - -func huhSelectPrice(ctx context.Context, prices []*typesv1.Price, title string) (*typesv1.Price, error) { - var options []huh.Option[*typesv1.Price] - for _, price := range prices { - options = append(options, huh.NewOption(price.Recurring.Interval, price)) - } - if len(options) == 0 { - return nil, fmt.Errorf("no price exists, this is a bug. please contact support at hi@humanlog.io") - } - if len(options) == 1 { - return options[0].Value, nil - } - var selected *typesv1.Price - err := huh.NewSelect[*typesv1.Price](). - Title(title). - Options(options...). - Value(&selected). - WithTheme(huhTheme). - Run() - if err != nil { - return nil, fmt.Errorf("prompting for price selection: %v", err) - } - return selected, nil -} - -func ensureEnvironmentSelected( - ctx context.Context, - ll *slog.Logger, - cctx *cli.Context, - state *state.State, - tokenSource *auth.UserRefreshableTokenSource, - apiURL string, - httpClient *http.Client, - clOpts []connect.ClientOption, -) (int64, error) { - if state.CurrentEnvironmentID != nil { - return *state.CurrentEnvironmentID, nil - } - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - - var options []huh.Option[*typesv1.Environment] - client := organizationv1connect.NewOrganizationServiceClient(httpClient, apiURL, clOpts...) - iter := ListEnvironments(ctx, client) - for iter.Next() { - item := iter.Current().Environment - options = append(options, huh.NewOption(item.Name, item)) - } - if err := iter.Err(); err != nil { - return -1, fmt.Errorf("no environment selected and couldn't list user environments: %v", err) - } - - if len(options) == 0 { - environmentID, err := promptCreateEnvironment(ctx, ll, cctx, state, tokenSource, apiURL, httpClient) - if err != nil { - return -1, err - } - state.CurrentEnvironmentID = &environmentID - return environmentID, state.WriteBack() - } - if len(options) == 1 { - state.CurrentEnvironmentID = &options[0].Value.Id - return *state.CurrentEnvironmentID, state.WriteBack() - } - - var ( - selected *typesv1.Environment - ) - err := huh.NewSelect[*typesv1.Environment](). - Title("You have access to multiple environments. Which one would you like to use?"). - Options(options...). - Value(&selected). - WithTheme(huhTheme). - Run() - if err != nil { - return -1, fmt.Errorf("prompting for environment selection: %v", err) - } - - state.CurrentEnvironmentID = &selected.Id - return *state.CurrentEnvironmentID, state.WriteBack() -} - -func ListOrganizations(ctx context.Context, client userv1connect.UserServiceClient) *iterapi.Iter[*userv1.ListOrganizationResponse_ListItem] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*userv1.ListOrganizationResponse_ListItem, *typesv1.Cursor, error) { - list, err := client.ListOrganization(ctx, connect.NewRequest(&userv1.ListOrganizationRequest{ - Cursor: cursor, - Limit: limit, - })) - if err != nil { - return nil, nil, err - } - return list.Msg.Items, list.Msg.Next, nil - }) -} - -func ListOrgUser(ctx context.Context, client organizationv1connect.OrganizationServiceClient) *iterapi.Iter[*organizationv1.ListUserResponse_ListItem] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*organizationv1.ListUserResponse_ListItem, *typesv1.Cursor, error) { - list, err := client.ListUser(ctx, connect.NewRequest(&organizationv1.ListUserRequest{ - Cursor: cursor, - Limit: limit, - })) - if err != nil { - return nil, nil, err - } - return list.Msg.Items, list.Msg.Next, nil - }) -} - -func ListEnvironments(ctx context.Context, client organizationv1connect.OrganizationServiceClient) *iterapi.Iter[*organizationv1.ListEnvironmentResponse_ListItem] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*organizationv1.ListEnvironmentResponse_ListItem, *typesv1.Cursor, error) { - list, err := client.ListEnvironment(ctx, connect.NewRequest(&organizationv1.ListEnvironmentRequest{ - Cursor: cursor, - Limit: limit, - })) - if err != nil { - return nil, nil, err - } - return list.Msg.Items, list.Msg.Next, nil - }) -} - -func ListEnvironmentTokens(ctx context.Context, environmentID int64, client tokenv1connect.TokenServiceClient) *iterapi.Iter[*tokenv1.ListEnvironmentTokenResponse_ListItem] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*tokenv1.ListEnvironmentTokenResponse_ListItem, *typesv1.Cursor, error) { - list, err := client.ListEnvironmentToken(ctx, connect.NewRequest(&tokenv1.ListEnvironmentTokenRequest{ - Cursor: cursor, - Limit: limit, - EnvironmentId: environmentID, - })) - if err != nil { - return nil, nil, err - } - return list.Msg.Items, list.Msg.Next, nil - }) -} - -func ListProduct(ctx context.Context, category string, scope *typesv1.Product_Scope, client productv1connect.ProductServiceClient) *iterapi.Iter[*productv1.ListProductResponse_ListItem] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*productv1.ListProductResponse_ListItem, *typesv1.Cursor, error) { - list, err := client.ListProduct(ctx, connect.NewRequest(&productv1.ListProductRequest{ - Cursor: cursor, - Limit: limit, - Category: category, - Scope: scope, - })) - if err != nil { - return nil, nil, err - } - return list.Msg.Items, list.Msg.Next, nil - }) -} - -func ListProjects(ctx context.Context, environmentID int64, client projectv1connect.ProjectServiceClient) *iterapi.Iter[*projectv1.ListProjectResponse_ListItem] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*projectv1.ListProjectResponse_ListItem, *typesv1.Cursor, error) { - list, err := client.ListProject(ctx, connect.NewRequest(&projectv1.ListProjectRequest{ - Cursor: cursor, - Limit: limit, - EnvironmentId: environmentID, - })) - if err != nil { - return nil, nil, err - } - return list.Msg.Items, list.Msg.Next, nil - }) -} - -func printFact(key string, fact any) { - log.Printf( - "- %s: %s", - color.YellowString(key), - color.CyanString(fmt.Sprintf("%v", fact)), - ) -} diff --git a/cmd/humanlog/ingest.go b/cmd/humanlog/ingest.go deleted file mode 100644 index 10881b43..00000000 --- a/cmd/humanlog/ingest.go +++ /dev/null @@ -1,304 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log/slog" - "net/http" - "net/url" - "os" - "time" - - "connectrpc.com/connect" - "github.com/charmbracelet/huh" - "github.com/minitape/api/go/svc/ingest/v1/ingestv1connect" - tokenv1 "github.com/minitape/api/go/svc/token/v1" - "github.com/minitape/api/go/svc/token/v1/tokenv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/humanlogio/humanlog/pkg/sink" - "github.com/humanlogio/humanlog/pkg/sink/logsvcsink" - otlpsink "github.com/humanlogio/humanlog/pkg/sink/otlpsink" - "github.com/mattn/go-isatty" - "github.com/urfave/cli" - collogpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/protobuf/types/known/timestamppb" -) - -func ingestCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getOTLPGRPCAPIUrl func(cctx *cli.Context) string, - getOTLPHTTPAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, - getResource func(cctx *cli.Context) *typesv1.Resource, - getScope func(*cli.Context) *typesv1.Scope, -) cli.Command { - return cli.Command{ - Hidden: hideUnreleasedFeatures == "true", - Name: environmentCmdName, - ShortName: "ingest", - Usage: "Ingest logs into an environments.", - Before: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - return nil - }, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - apiURL := getAPIUrl(cctx) - cfg := getCfg(cctx) - - flushTimeout := 1 * time.Second - ingestctx, ingestcancel := context.WithCancel(context.WithoutCancel(ctx)) - go func() { - <-ctx.Done() - time.Sleep(2 * flushTimeout) // give it 2x timeout to flush before nipping the ctx entirely - ingestcancel() - }() - notifyUnableToIngest := func(err error) { - logerror("unable to ingest: %v", err) - ingestcancel() - } - remotesink, err := ingest(ingestctx, ll, cctx, apiURL, getOTLPGRPCAPIUrl, getOTLPHTTPAPIUrl, getCfg, getState, getResource, getScope, getTokenSource, getHTTPClient, getConnectOpts, notifyUnableToIngest) - if err != nil { - return fmt.Errorf("can't send logs: %v", err) - } - defer func() { - ctx, cancel := context.WithTimeout(context.Background(), flushTimeout) - defer cancel() - ll.DebugContext(ctx, "flushing remote ingestion sink for up to "+flushTimeout.String()) - if err := remotesink.Close(ctx); err != nil { - ll.ErrorContext(ctx, "couldn't flush buffered log", slog.Any("err", err)) - } else { - ll.DebugContext(ctx, "done sending all logs") - } - }() - loginfo("saving to %s", apiURL) - - in := os.Stdin - if isatty.IsTerminal(in.Fd()) { - loginfo("reading stdin...") - } - go func() { - <-ctx.Done() - logdebug("requested to stop scanning") - time.Sleep(500 * time.Millisecond) - if isatty.IsTerminal(in.Fd()) { - loginfo("Patiently waiting for stdin to send EOF (Ctrl+D). This is you! I'm reading from a TTY!") - } else { - // forcibly stop scanning if stuck on stdin - logdebug("forcibly closing stdin") - in.Close() - } - }() - - handlerOpts := humanlog.HandlerOptionsFrom(cfg.Parser) - if err := humanlog.Scan(ctx, in, remotesink, handlerOpts); err != nil { - logerror("scanning caught an error: %v", err) - } - - return nil - }, - } -} - -func ingest( - ctx context.Context, - ll *slog.Logger, - cctx *cli.Context, - apiURL string, - getOTLPGRPCAPIAddr func(cctx *cli.Context) string, - getOTLPHTTPAPIUrl func(cctx *cli.Context) string, - getCfg func(*cli.Context) *config.Config, - getState func(*cli.Context) *state.State, - getResource func(*cli.Context) *typesv1.Resource, - getScope func(*cli.Context) *typesv1.Scope, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getHTTPClient func(*cli.Context, string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, - notifyUnableToIngest func(error), -) (sink.Sink, error) { - state := getState(cctx) - tokenSource := getTokenSource(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - if state.IngestionToken == nil || time.Now().After(state.IngestionToken.ExpiresAt.AsTime()) { - // we need to create an environment token - environmentToken, err := createIngestionToken(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return nil, fmt.Errorf("no ingestion token configured, and couldn't generate one: %v", err) - } - state.IngestionToken = environmentToken - if err := state.WriteBack(); err != nil { - return nil, fmt.Errorf("writing back generated ingestion token: %v", err) - } - } - - getIngestClient := func() ingestv1connect.IngestServiceClient { - clOpts = append(clOpts, - connect.WithInterceptors(auth.NewEnvironmentAuthInterceptor(ll, state.IngestionToken)), - connect.WithGRPC(), - ) - return ingestv1connect.NewIngestServiceClient(httpClient, apiURL, clOpts...) - } - getOTLPGRPCClient := func() (collogpb.LogsServiceClient, error) { - addr := getOTLPGRPCAPIAddr(cctx) - isLocalhost := false - if u, err := url.Parse(addr); err == nil { - isLocalhost = u.Host == "localhost" || u.Host == "127.0.0.1" - } - userAgent := "humanlog OTLP GRPC logs exporter/" + semverVersion.String() - dialOpts := []grpc.DialOption{ - grpc.WithUserAgent(userAgent), - grpc.WithTransportCredentials(credentials.NewTLS(nil)), - grpc.WithPerRPCCredentials(newBearerPerRPCCreds(state.IngestionToken.Token, isLocalhost)), - } - ll.DebugContext(ctx, "dialing otlp-grpc", slog.String("target", addr)) - conn, err := grpc.NewClient(addr, dialOpts...) - if err != nil { - return nil, err - } - return collogpb.NewLogsServiceClient(conn), nil - } - - resource := getResource(cctx) - scope := getScope(cctx) - - var snk sink.Sink - switch sinkType := os.Getenv("HUMANLOG_SINK_TYPE"); sinkType { - case "otlp-grpc": - client, err := getOTLPGRPCClient() - if err != nil { - return nil, err - } - snk = otlpsink.StartOTLPSink(ctx, ll, client, "api", resource, scope, 1_000, 100*time.Millisecond, false, notifyUnableToIngest) - case "unary": - client := getIngestClient() - snk = logsvcsink.StartUnarySink(ctx, ll, client, "api", resource, scope, 10_000, 100*time.Millisecond, false, notifyUnableToIngest) - case "stream": - fallthrough // use the stream sink as default, it's the best tradeoff for performance and compatibility - default: - client := getIngestClient() - snk = logsvcsink.StartStreamSink(ctx, ll, client, "api", resource, scope, 10_000, 100*time.Millisecond, false, notifyUnableToIngest) - } - - return snk, nil -} - -func createIngestionToken( - ctx context.Context, - ll *slog.Logger, - cctx *cli.Context, - state *state.State, - tokenSource *auth.UserRefreshableTokenSource, - apiURL string, - httpClient *http.Client, - clOpts []connect.ClientOption, -) (*typesv1.EnvironmentToken, error) { - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return nil, fmt.Errorf("ensuring you're logged in: %v", err) - } - envID, err := ensureEnvironmentSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return nil, fmt.Errorf("ensuring you've selected an environment: %v", err) - } - - // userToken is most likely valid and unexpired, use it - // to generate an environment token with the right roles - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - tokenClient := tokenv1connect.NewTokenServiceClient(httpClient, apiURL, clOpts...) - - expiresAt, err := hubAskTokenExpiry("Creating an ingestion token.") - if err != nil { - return nil, err - } - req := &tokenv1.GenerateEnvironmentTokenRequest{ - EnvironmentId: envID, - ExpiresAt: timestamppb.New(expiresAt), - Roles: []typesv1.EnvironmentRole{typesv1.EnvironmentRole_EnvironmentRole_Ingestor}, - } - res, err := tokenClient.GenerateEnvironmentToken(ctx, connect.NewRequest(req)) - if err != nil { - return nil, fmt.Errorf("generating environment token for ingestion: %v", err) - } - return res.Msg.Token, nil -} - -func hubAskTokenExpiry(title string) (time.Time, error) { - var ( - now = time.Now() - expiresAt time.Time - ) - err := huh.NewSelect[time.Time](). - Title(title). - Description("When should this token expire?"). - Options( - huh.NewOption("in 24h", now.AddDate(0, 0, 1)), - huh.NewOption("in a week", now.AddDate(0, 0, 7)), - huh.NewOption("in a month", now.AddDate(0, 1, 0)), - huh.NewOption("in 6 months", now.AddDate(0, 6, 0)), - huh.NewOption("in a year", now.AddDate(1, 0, 0)), - ). - Value(&expiresAt). - Run() - if err != nil { - return expiresAt, fmt.Errorf("prompting for expiry duration: %v", err) - } - return expiresAt, nil -} - -func hubAskTokenRoles(title string) ([]typesv1.EnvironmentRole, error) { - var roles []typesv1.EnvironmentRole - err := huh.NewMultiSelect[typesv1.EnvironmentRole](). - Title(title). - Description("What roles should be granted to this token?"). - Options( - huh.NewOption("ingestor", typesv1.EnvironmentRole_EnvironmentRole_Ingestor), - ). - Value(&roles). - Run() - if err != nil { - return roles, fmt.Errorf("prompting for roles: %v", err) - } - return roles, nil -} - -type BearerPerRPCCreds struct { - headers map[string]string - allowInsecure bool -} - -func newBearerPerRPCCreds(token string, allowInsecure bool) credentials.PerRPCCredentials { - headers := map[string]string{"authorization": "Bearer " + token} - return &BearerPerRPCCreds{headers: headers, allowInsecure: allowInsecure} -} - -func (bpr *BearerPerRPCCreds) GetRequestMetadata(ctx context.Context, _ ...string) (map[string]string, error) { - return bpr.headers, nil -} - -func (c *BearerPerRPCCreds) RequireTransportSecurity() bool { return !c.allowInsecure } diff --git a/cmd/humanlog/localhost.go b/cmd/humanlog/localhost.go deleted file mode 100644 index b0f4ecab..00000000 --- a/cmd/humanlog/localhost.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "context" - "log/slog" - "net" - "net/http" - "net/url" - "strconv" - "time" - - "github.com/minitape/api/go/svc/ingest/v1/ingestv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/pkg/sink" - "github.com/humanlogio/humanlog/pkg/sink/logsvcsink" -) - -func dialLocalhostServer( - ctx context.Context, - ll *slog.Logger, - resource *typesv1.Resource, - scope *typesv1.Scope, - port int, - localhostHttpClient *http.Client, - notifyUnableToIngest func(err error), -) (localsink sink.Sink, done func(context.Context) error, err error) { - localhostAddr := net.JoinHostPort("localhost", strconv.Itoa(port)) - addr, err := url.Parse("http://" + localhostAddr) - if err != nil { - panic(err) - } - logdebug("sending logs to localhost forwarder") - client := ingestv1connect.NewIngestServiceClient(localhostHttpClient, addr.String()) - localhostSink := logsvcsink.StartStreamSink(ctx, ll, client, "local", resource, scope, 1<<20, 100*time.Millisecond, true, notifyUnableToIngest) - return localhostSink, func(ctx context.Context) error { - logdebug("flushing localhost sink") - return localhostSink.Close(ctx) - }, nil -} diff --git a/cmd/humanlog/main.go b/cmd/humanlog/main.go index 01ba9d62..bc0e21c7 100644 --- a/cmd/humanlog/main.go +++ b/cmd/humanlog/main.go @@ -3,7 +3,6 @@ package main import ( "context" "crypto/tls" - "errors" "fmt" "log" "log/slog" @@ -12,33 +11,31 @@ import ( "net/url" "os" "os/signal" - "path/filepath" "strconv" "strings" "time" - otelresource "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.34.0" - "connectrpc.com/connect" "github.com/99designs/keyring" "github.com/aybabtme/rgbterm" "github.com/blang/semver" - "github.com/charmbracelet/glamour" - "github.com/charmbracelet/huh" - "github.com/gen2brain/beeep" types "github.com/minitape/api/go/types/v1" "github.com/humanlogio/humanlog" "github.com/humanlogio/humanlog/internal/pkg/config" "github.com/humanlogio/humanlog/internal/pkg/state" "github.com/humanlogio/humanlog/pkg/auth" "github.com/humanlogio/humanlog/pkg/sink" + otlpsink "github.com/humanlogio/humanlog/pkg/sink/otlpsink" "github.com/humanlogio/humanlog/pkg/sink/stdiosink" "github.com/humanlogio/humanlog/pkg/sink/teesink" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" "github.com/urfave/cli" "golang.org/x/net/http2" + collogpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" ) var ( @@ -71,21 +68,9 @@ var ( } return v }() - defaultApiURL = "https://api.humanlog.io" - defaultBaseSiteURL = "https://humanlog.io" - defaultOtlpGrpcApiAddr = "otlp-grpc.humanlog.io:443" - defaultOtlpHttpApiURL = "https://otlp-http.humanlog.io" - defaultReleaseChannel = "main" - hideUnreleasedFeatures = "" - - huhTheme = func() *huh.Theme { - base := huh.ThemeCatppuccin() - base.Focused.FocusedButton = base.Focused.FocusedButton.Bold(true).Underline(true) - base.Focused.BlurredButton = base.Focused.BlurredButton.Bold(false).Underline(false).Strikethrough(true) - base.Blurred.FocusedButton = base.Focused.FocusedButton.Bold(true).Underline(true) - base.Blurred.BlurredButton = base.Focused.BlurredButton.Bold(false).Underline(false).Strikethrough(true) - return base - }() + defaultApiURL = "https://api.humanlog.io" + defaultBaseSiteURL = "https://humanlog.io" + defaultReleaseChannel = "main" ) func fatalf(c *cli.Context, format string, args ...interface{}) { @@ -207,20 +192,6 @@ func newApp() *cli.App { EnvVar: "HUMANLOG_BASE_SITE_URL", Hidden: true, } - otlpGrpcApiServerAddr := cli.StringFlag{ - Name: "otlp.grpc", - Value: defaultOtlpGrpcApiAddr, - Usage: "address of the OTLP GRPC server", - EnvVar: "HUMANLOG_OTLP_GRPC_ADDR", - Hidden: true, - } - otlpHttpApiServerURL := cli.StringFlag{ - Name: "otlp.http", - Value: defaultOtlpHttpApiURL, - Usage: "address of the OTLP HTTP server", - EnvVar: "HUMANLOG_OTLP_HTTP_URL", - Hidden: true, - } debug := cli.BoolFlag{ Name: "debug", @@ -239,87 +210,18 @@ func newApp() *cli.App { Hidden: true, } + otlpEndpoint := cli.StringFlag{ + Name: "otlp-endpoint", + Usage: "OTLP gRPC endpoint to forward logs to (e.g. localhost:4317)", + EnvVar: "OTEL_EXPORTER_OTLP_ENDPOINT", + } + app := cli.NewApp() app.Author = "humanlog.io" app.Email = defaultBaseSiteURL + `/support` app.Name = "humanlog" app.Version = semverVersion.String() - app.Usage = "reads logs from stdin (and traces!), makes them pretty on stdout!" - app.Description = renderDescription(` -# humanlog -> an observability tool on your machine. - -Ingests logs and distributed tracing spans and makes them searchable and readable. - -When invoked with no argument, consumes stdin and parses it, attempting to make detected logs prettier on stdout. - -## Logging - -You can search the logs that were parsed. Run a query with: - -` + "```" + `bash -humanlog query 'summarize count() by msg' -` + "```" + ` - -You can also watch streams of logs being ingested with streaming -queries. - -` + "```" + `bash -humanlog stream 'filter lvl == "ERROR"' -` + "```" + ` - -## Tracing - -Similarly for distributed tracing, point your application to - -` + "```" + `bash -export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 -` + "```" + ` - -Then query your spans and visualize them in traces. - -` + "```" + `bash -humanlog query 'traces | where time > ago(30s) | take 1' -` + "```" + ` - -And like logs, you can watch your stream of spans: - -` + "```" + `bash -humanlog stream 'traces | where service_name == "my_service"' -` + "```" + ` - -More complex queries are possible, same as for logs: - -` + "```" + `bash -humanlog query 'traces | where time > ago(30s) | summarize span_count=count() by trace_id | sort by span_count desc | take 1' -` + "```" + ` - - -## Ingesting data - -Ingestion of logs is typically done by invoking ` + "`" + `humanlog` + "`" + ` with no argument and feeding it via stdin. - -` + "```" + `bash -# Feed it via stdin -your_app | humanlog - -# Or replay log files -humanlog < /var/log/yourlogfile - -# pull from elsewhere for quick debugging session -kubectl logs -l app=yourapp -f | humanlog -` + "```" + ` - -If your application integrates twith **OpenTelemetry** you can point it to: -- OTLP/gRPC: ` + "`" + `localhost:4317` + "`" + ` -- OTLP/json: ` + "`" + `localhost:4318` + "`" + ` - -## Getting more help - -For more details: -- read [our documentation](` + defaultBaseSiteURL + `/docs/get-started/introduction). -- join [our community](` + defaultBaseSiteURL + `/link/discord). - `) + app.Usage = "reads structured logs from stdin, makes them pretty on stdout!" var ( closers []func() @@ -339,52 +241,18 @@ For more details: httpClient = &http.Client{ Transport: httpTransport, } - localhostHttpTransport = &http2.Transport{ - AllowHTTP: true, - DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) { - return dialer.Dial(network, addr) - }, - } - localhostHttpClient = &http.Client{ - Transport: localhostHttpTransport, - } clOpts []connect.ClientOption promptedToUpdate *semver.Version updateRes <-chan *checkForUpdateRes apiURL = "" baseSiteURL = "" - otlpGrpcApiAddr = "" - otlpHttpApiURL = "" keyringName = "humanlog" - resource = &types.Resource{} - scope = &types.Scope{} - getCtx = func(*cli.Context) context.Context { return ctx } getCfg = func(*cli.Context) *config.Config { return cfg } getState = func(*cli.Context) *state.State { return statefile } - getResource = func(cctx *cli.Context) *types.Resource { return resource } - getScope = func(*cli.Context) *types.Scope { return scope } logOutput = os.Stderr - usesLogFile = false getLogger = func(cctx *cli.Context) *slog.Logger { - if cctx.Command.Name == app.Name && !usesLogFile { - usesLogFile = true - logdir, err := defaultLogDir(getCfg(cctx), getState(cctx)) - if err != nil { - panic(fmt.Sprintf("looking up log dir: %v", err)) - } - if err := os.MkdirAll(logdir, 0700); err != nil { - panic(fmt.Sprintf("ensuring log dir exists: %v", err)) - } - logfile := filepath.Join(logdir, "logs.json") - - logOutput, err = os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_SYNC, 0640) - if err != nil { - panic(fmt.Sprintf("creating log file: %v", err)) - } - closers = append(closers, func() { _ = logOutput.Close() }) - } return slog.New(slog.NewJSONHandler(logOutput, &slog.HandlerOptions{ AddSource: true, Level: slogLevel(), @@ -416,20 +284,6 @@ For more details: logdebug("using api at %q", apiURL) return apiURL } - getOTLPGRPCAPIAddr = func(*cli.Context) string { - if otlpGrpcApiAddr == "" { - otlpGrpcApiAddr = defaultOtlpGrpcApiAddr - } - logdebug("using otlp grpc at %q", otlpGrpcApiAddr) - return otlpGrpcApiAddr - } - getOTLPHTTPAPIUrl = func(*cli.Context) string { - if otlpHttpApiURL == "" { - otlpHttpApiURL = defaultOtlpHttpApiURL - } - logdebug("using otlp http at %q", otlpHttpApiURL) - return otlpHttpApiURL - } getBaseSiteURL = func(*cli.Context) string { if baseSiteURL == "" { baseSiteURL = defaultBaseSiteURL @@ -440,14 +294,11 @@ For more details: getHTTPClient = func(cctx *cli.Context, apiURL string) *http.Client { u, _ := url.Parse(apiURL) if host, _, _ := net.SplitHostPort(u.Host); host == "localhost" { - getLogger(cctx).Debug("using localhost client") - return localhostHttpClient + getLogger(cctx).Debug("using plain HTTP client for localhost") + return &http.Client{Transport: &http.Transport{}} } return httpClient } - getLocalhostHTTPClient = func(*cli.Context) *http.Client { - return localhostHttpClient - } getConnectOpts = func(cctx *cli.Context) []connect.ClientOption { return clOpts } @@ -484,14 +335,6 @@ For more details: apiURL = c.String(apiServerURL.Name) logdebug("api URL set to %q (due to --%s flag or $%s env var)", apiURL, apiServerURL.Name, apiServerURL.EnvVar) } - if c.String(otlpGrpcApiServerAddr.Name) != "" { - otlpGrpcApiAddr = c.String(otlpGrpcApiServerAddr.Name) - logdebug("otlp grpc addr set to %q (due to --%s flag or $%s env var)", otlpGrpcApiAddr, otlpGrpcApiServerAddr.Name, otlpGrpcApiServerAddr.EnvVar) - } - if c.String(otlpHttpApiServerURL.Name) != "" { - otlpHttpApiURL = c.String(otlpHttpApiServerURL.Name) - logdebug("otlp http URL set to %q (due to --%s flag or $%s env var)", otlpHttpApiURL, otlpHttpApiServerURL.Name, otlpHttpApiServerURL.EnvVar) - } if c.String(baseSiteServerURL.Name) != "" { baseSiteURL = c.String(baseSiteServerURL.Name) logdebug("base site URL set to %q (due to --%s flag or $%s env var)", baseSiteURL, baseSiteServerURL.Name, baseSiteServerURL.EnvVar) @@ -571,31 +414,6 @@ For more details: return fmt.Errorf("reading default config file: %v", err) } - res, err := otelresource.New(ctx, - otelresource.WithAttributes( - semconv.ServiceName("humanlog"), - ), - otelresource.WithHost(), - otelresource.WithFromEnv(), - otelresource.WithOS(), - otelresource.WithProcess(), - otelresource.WithContainer(), - otelresource.WithTelemetrySDK(), - ) - if err != nil { - return fmt.Errorf("detecting resource: %v", err) - } - resource = types.NewResource( - "", - types.FromOTELAttributes(res.Attributes()), - ) - scope = types.NewScope( - "", - "humanlog", - semverVersion.String(), - nil, - ) - if shouldCheckForUpdate(c, cfg, statefile) { if statefile.LatestKnownVersion != nil && statefile.LatestKnownVersion.GT(semverVersion) { promptedToUpdate = statefile.LatestKnownVersion @@ -640,23 +458,10 @@ For more details: } app.Commands = append( app.Commands, - onboardingCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), - demoCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), versionCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), - authCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getHTTPClient, getConnectOpts), - apiCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getLocalhostHTTPClient, getConnectOpts), - serviceCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), - configCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), - stateCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), - organizationCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getHTTPClient, getConnectOpts), - environmentCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getHTTPClient, getConnectOpts), - ingestCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getOTLPGRPCAPIAddr, getOTLPHTTPAPIUrl, getHTTPClient, getConnectOpts, getResource, getScope), - queryCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), - projectCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getHTTPClient, getConnectOpts), - streamCmd(getCtx, getLogger, getCfg, getState, getTokenSource, getAPIUrl, getBaseSiteURL, getHTTPClient, getConnectOpts), - gennyCmd(getCtx, getLogger, getCfg, getState), + configCmd(getCfg), ) - app.Flags = []cli.Flag{configFlag, skipFlag, keepFlag, sortLongest, skipUnchanged, truncates, truncateLength, colorFlag, timeFormat, ignoreInterrupts, messageFieldsFlag, timeFieldsFlag, levelFieldsFlag, apiServerURL, otlpGrpcApiServerAddr, otlpHttpApiServerURL, baseSiteServerURL, debug, useHTTP1, useProtocol} + app.Flags = []cli.Flag{configFlag, skipFlag, keepFlag, sortLongest, skipUnchanged, truncates, truncateLength, colorFlag, timeFormat, ignoreInterrupts, messageFieldsFlag, timeFieldsFlag, levelFieldsFlag, otlpEndpoint, apiServerURL, baseSiteServerURL, debug, useHTTP1, useProtocol} app.Action = func(cctx *cli.Context) error { if len(cctx.Args()) > 0 { return fmt.Errorf("unknown command: %s", strings.Join(cctx.Args(), " ")) @@ -751,100 +556,64 @@ For more details: } } var ( - sink sink.Sink - err error + snk sink.Sink + err error ) - sink, err = stdiosink.NewStdio(colorable.NewColorableStdout(), sinkOpts) + snk, err = stdiosink.NewStdio(colorable.NewColorableStdout(), sinkOpts) if err != nil { return fmt.Errorf("preparing stdio printer: %v", err) } handlerOpts := humanlog.HandlerOptionsFrom(cfg.Parser) - rtcfg := cfg.Runtime - if rtcfg != nil && rtcfg.ExperimentalFeatures != nil { - expcfg := rtcfg.ExperimentalFeatures - if expcfg.SendLogsToCloud != nil && *expcfg.SendLogsToCloud { - ll := getLogger(cctx) - apiURL := getAPIUrl(cctx) - notifyUnableToIngest := func(err error) { - // TODO: notify using system notification? - logerror("configured to ingest, but unable to do so: %v", err) - msg := "Your logs are not being sent!" - var cerr *connect.Error - if errors.As(err, &cerr) { - if cerr.Code() == connect.CodeResourceExhausted { - msg += "\n\n- " + cerr.Message() - } else { - msg += "\n\n- " + cerr.Error() - } - } else { - msg += "\n\n" + "An unexpected error occurred while trying to ingest your logs, see your terminal for details." - logerror("err=%T", err) - } - - if err := beeep.Alert("humanlog has problems!", msg, ""); err != nil { - logerror("couldn't send desktop notification: %v", err) - if err := beeep.Beep(3000, 1); err != nil { - logerror("can't even beeep :'( -> %v", err) - } - os.Exit(1) - } - } + // OTLP forwarding + if cctx.IsSet(otlpEndpoint.Name) { + endpoint := cctx.String(otlpEndpoint.Name) + ll := getLogger(cctx) - flushTimeout := 300 * time.Millisecond - ingestctx, ingestcancel := context.WithCancel(context.WithoutCancel(ctx)) - go func() { - <-ctx.Done() - time.Sleep(2 * flushTimeout) // give it 2x timeout to flush before nipping the ctx entirely - ingestcancel() - }() - remotesink, err := ingest(ingestctx, ll, cctx, apiURL, getOTLPGRPCAPIAddr, getOTLPHTTPAPIUrl, getCfg, getState, getResource, getScope, getTokenSource, getHTTPClient, getConnectOpts, notifyUnableToIngest) - if err != nil { - return fmt.Errorf("can't send logs: %v", err) - } - defer func() { - ctx, cancel := context.WithTimeout(context.Background(), flushTimeout) - defer cancel() - ll.DebugContext(ctx, "flushing remote ingestion sink for up to 300ms") - if err := remotesink.Close(ctx); err != nil { - ll.ErrorContext(ctx, "couldn't flush buffered log", slog.Any("err", err)) - } else { - ll.DebugContext(ctx, "done sending all logs") - } - }() - loginfo("saving to %s", apiURL) - sink = teesink.NewTeeSink(sink, remotesink) + var transportCreds grpc.DialOption + if u, err := url.Parse(endpoint); err == nil && u.Scheme == "http" { + transportCreds = grpc.WithTransportCredentials(insecure.NewCredentials()) + // strip scheme for gRPC dial + endpoint = u.Host + } else { + transportCreds = grpc.WithTransportCredentials(credentials.NewTLS(nil)) } - if expcfg != nil && expcfg.ServeLocalhost != nil { - localhostCfg := expcfg.ServeLocalhost - // TODO(antoine): all logs to a single location, right now there's code logging - // randomly everywhere - ll := getLogger(cctx) - - localhostSink, done, err := dialLocalhostServer( - ctx, ll, resource, scope, int(localhostCfg.Port), - getLocalhostHTTPClient(cctx), - func(err error) { - logerror("unable to ingest logs with localhost: %v", err) - }, - ) - if err != nil { - logerror("failed to start localhost service: %v", err) - } else { - sink = teesink.NewTeeSink(sink, localhostSink) - defer func() { - ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond) - defer cancel() - ll.DebugContext(ctx, "flushing localhost ingestion sink for up to 300ms") - if err := done(ctx); err != nil { - ll.DebugContext(ctx, "couldn't flush buffered log (localhost)", slog.Any("err", err)) - } else { - ll.DebugContext(ctx, "done sending all logs") - } - }() - } + userAgent := "humanlog OTLP exporter/" + semverVersion.String() + conn, err := grpc.NewClient(endpoint, + grpc.WithUserAgent(userAgent), + transportCreds, + ) + if err != nil { + return fmt.Errorf("connecting to OTLP endpoint %q: %v", endpoint, err) } + closers = append(closers, func() { _ = conn.Close() }) + + client := collogpb.NewLogsServiceClient(conn) + resource := types.NewResource("", nil) + scope := types.NewScope("", "humanlog", semverVersion.String(), nil) + + flushTimeout := 300 * time.Millisecond + otlpctx, otlpcancel := context.WithCancel(context.WithoutCancel(ctx)) + go func() { + <-ctx.Done() + time.Sleep(2 * flushTimeout) + otlpcancel() + }() + + otlpSink := otlpsink.StartOTLPSink(otlpctx, ll, client, "otlp", resource, scope, 1_000, 100*time.Millisecond, false, func(err error) { + logerror("unable to send logs to OTLP endpoint: %v", err) + }) + defer func() { + fctx, fcancel := context.WithTimeout(context.Background(), flushTimeout) + defer fcancel() + ll.DebugContext(fctx, "flushing OTLP sink") + if err := otlpSink.Close(fctx); err != nil { + ll.ErrorContext(fctx, "couldn't flush OTLP sink", slog.Any("err", err)) + } + }() + loginfo("forwarding logs to OTLP endpoint %s", endpoint) + snk = teesink.NewTeeSink(snk, otlpSink) } in := os.Stdin @@ -864,7 +633,7 @@ For more details: } }() - if err := humanlog.Scan(ctx, in, sink, handlerOpts); err != nil { + if err := humanlog.Scan(ctx, in, snk, handlerOpts); err != nil { logerror("scanning caught an error: %v", err) } @@ -884,18 +653,3 @@ func mustatoi(a string) int { } return i } - -func renderDescription(in string) string { - r, err := glamour.NewTermRenderer( - glamour.WithAutoStyle(), - glamour.WithWordWrap(120), - ) - if err != nil { - panic(err) - } - out, err := r.Render(in) - if err != nil { - panic(err) - } - return out -} diff --git a/cmd/humanlog/onboarding.go b/cmd/humanlog/onboarding.go deleted file mode 100644 index b0ee43b9..00000000 --- a/cmd/humanlog/onboarding.go +++ /dev/null @@ -1,356 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "fmt" - "log/slog" - "net/http" - "net/url" - "os" - "time" - - "connectrpc.com/connect" - "github.com/charmbracelet/glamour" - "github.com/charmbracelet/huh" - "github.com/minitape/api/go/svc/auth/v1/authv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/urfave/cli" -) - -const onboardingCmdName = "onboarding" - -func onboardingCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(*cli.Context, string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - - runsAsService := func(cfg *config.Config) bool { - if cfg == nil { - return false - } - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg == nil { - return false - } - if expcfg.ServeLocalhost != nil { - return true - } - return false - } - - ensureServiceEnabled := func(cctx *cli.Context) error { - ctx := getCtx(cctx) - svc, err := prepareServiceCmd(cctx, - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getBaseSiteURL, - getHTTPClient, - ) - if err != nil { - return fmt.Errorf("failed to get humanlog service details: %v", err) - } - loginfo("uninstalling service if it existed") - if err := svc.Uninstall(); err != nil { - logdebug("failed to uninstall service (was it installed?): %v", err) - } else { - loginfo("uninstalled service") - } - loginfo("installing humanlog service") - if err := svc.Install(); err != nil { - return fmt.Errorf("can't install service: %v", err) - } - loginfo("service installed") - if os.Getenv("INSIDE_HUMANLOG_SELF_UPDATE") == "" { - // we're not self-updating, so we need to restart the service - - loginfo("stopping service if it was running") - if err = svc.Stop(ctx); err != nil { - logwarn("failed to stop: %v", err) - } - loginfo("starting service") - if err := svc.Start(ctx); err != nil { - return fmt.Errorf("failed to start service: %v", err) - } - } - return nil - } - - var ( - forceNonInteractiveFlag = cli.BoolFlag{Name: "force-non-interactive"} - ) - - return cli.Command{ - Name: onboardingCmdName, - Usage: "Onboarding humanlog after installs or updates", - Hidden: true, - Flags: []cli.Flag{forceNonInteractiveFlag}, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - cfg := getCfg(cctx) - state := getState(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - baseURL, err := url.Parse(getBaseSiteURL(cctx)) - if err != nil { - return fmt.Errorf("compilation error, invalid base site URL built into binary: %v", err) - } - userToken, err := tokenSource.GetUserToken(ctx) - if err != nil { - return fmt.Errorf("looking up user credentials: %v", err) - } - - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - // clOpts := connect.WithClientOptions(connect.WithInterceptors(auth.Interceptors(ll, tokenSource)...)) - // userSvc := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - - logdebug("checking logged in status") - user, err := checkUserLoggedIn(ctx, ll, httpClient, apiURL, tokenSource, clOpts) - if err != nil { - logwarn("unable to check if you're logged in: %v", err) - } - - defer func() { - logdebug("checking if should run humanlog as a service") - if !runsAsService(cfg) { - logdebug("humanlog should not run as a servive") - return - } - logdebug("humanlog should run as a servive, enabling it (due to config)") - if err := ensureServiceEnabled(cctx); err != nil { - logerror("unable to configure humanlog service: %v", err) - } else { - logdebug("humanlog service is configured") - } - }() - - if !isTerminal(os.Stdout) || cctx.Bool(forceNonInteractiveFlag.Name) { - logdebug("stdout isn't a terminal, disabling interactive prompts") - in := `# humanlog updates - -Hey there! - -Thanks for installing this version of humanlog. If this is your first time around, try this out: - -` + "```bash" + ` -humanlog onboarding -` + "```" + ` - -This will help you get started and learn everything that humanlog has to offer. - -Bye! <3` - - out, err := glamour.Render(in, "dark") - if err != nil { - return err - } - fmt.Print(out) - - return nil - } - - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - - if err := setReleaseChannel(cfg); err != nil { - logdebug("can't write back config to set release channel: %v", err) - } - - now := time.Now() - askAgainAfter := 24 * time.Hour - - // by default: - // - we always turn on the query engine - // - we always want the user to signup if they're not signed up and - var ( - hasQueryEngine = (expcfg != nil && expcfg.ServeLocalhost != nil) - isSignedUp = (userToken != nil) - isLoggedIn = (user != nil) - isSignedUpButNotLoggedIn = isSignedUp && !isLoggedIn - wantsQueryEngine = !hasQueryEngine - wantsSignup = !isSignedUp - askedAboutQueryEngine = state != nil && state.LastPromptedToEnableLocalhostAt != nil - askedAboutSignup = state != nil && state.LastPromptedToSignupAt != nil - - username string - ) - - if userToken != nil { - username = userToken.Username - } - - // we only prompt about the query engine if a user previously refused it. - // new installs get the query engine by default - promptQueryEngine := false - if askedAboutQueryEngine { - // we assume no until told otherwise - wantsQueryEngine = false - if wasMoreThanTimeAgo(now, state.LastPromptedToEnableLocalhostAt, askAgainAfter) { - logdebug("prompting for query-engine because it's been a while since asking") - promptQueryEngine = true - } else { - // we asked recently and they apparently refused, so wait later for another update - logdebug("not prompting for query-engine because we asked too recently and were denied") - promptQueryEngine = false - } - } - // we only prompt about signup if a user previously refused it. - // new installs sign up by default - promptSignup := false - if askedAboutSignup { - // we assume no until told otherwise - wantsSignup = false - if wasMoreThanTimeAgo(now, state.LastPromptedToSignupAt, askAgainAfter) { - logdebug("prompting for signup because it's been a while since asking") - promptSignup = true - } else { - logdebug("not prompting for signup because we asked too recently and were denied") - promptSignup = false - } - } - - var fields []huh.Field - if promptQueryEngine { - logdebug("prompting about query engine") - var titleSignupExtra, titleDescriptionExtra string - if wantsSignup { - titleSignupExtra = "\nAnd since you are not logged in, this will also prompt you to log in.\n" - titleDescriptionExtra = " and signin" - } - fields = append(fields, - huh.NewConfirm(). - Title("Humanlog now includes a log query engine, right here in your pocket.\n\n"+ - "You can use it to query your logs, plot graphs and do general log observability stuff. All on your machine!\n\n"+ - "To enable this feature, humanlog needs to run a background service.\n"+titleSignupExtra). - Description("Do you want to enable the log query engine"+titleDescriptionExtra+"?"). - Affirmative("Yes!").Negative("No."). - Value(&wantsQueryEngine), - ) - state.LastPromptedToEnableLocalhostAt = ptr(time.Now()) - } else { - logdebug("not prompting about query engine") - } - if promptSignup && !promptQueryEngine { - logdebug("prompting about signing up") - fields = append(fields, - huh.NewConfirm(). - Title("New features are coming soon. Sign in to learn more."). - Description("Sign up to learn about upcoming releases?"). - Affirmative("Yes!").Negative("No").Value(&wantsSignup), - ) - state.LastPromptedToSignupAt = ptr(time.Now()) - } else { - logdebug("not prompting about signing up") - } - - if username == "" { - fields = append(fields, - huh.NewInput(). - Title("Select a username"). - Description("It should match the regexp `^[a-zA-Z0-9][a-zA-Z0-9-]+$`"). - Value(&username), - ) - } - - if len(fields) > 0 { - err := huh.NewForm(huh.NewGroup(fields...)).WithTheme(huhTheme).Run() - if err != nil { - return err - } - if state.LoggedInUsername == nil { - state.LoggedInUsername = &username - } else if state.LoggedInUsername != nil && len(username) > 0 { - state.LoggedInUsername = &username - } - if err := state.WriteBack(); err != nil { - logwarn("failed to record your answer: %v", err) - } - } - - if wantsQueryEngine { - if expcfg == nil { - expcfg = &typesv1.RuntimeConfig_ExperimentalFeatures{} - } - serveLocalhost, err := config.GetDefaultLocalhostConfig() - if err != nil { - logerror("getting default value for localhost log engine config: %v", err) - } else { - expcfg.ServeLocalhost = serveLocalhost - if err := cfg.WriteBack(); err != nil { - logerror("failed to update config file: %v", err) - } - } - } - - if wantsSignup || isSignedUpButNotLoggedIn { - authClient := authv1connect.NewAuthServiceClient(httpClient, apiURL) - - var redirectURL string - if isSignedUpButNotLoggedIn { - redirectURL = baseURL.JoinPath("/cli/login/success").String() - } else { - redirectURL = baseURL.JoinPath("/onboarding").String() - } - - _, err := performLoginFlow(ctx, state, authClient, tokenSource, username, 0, redirectURL) - if err != nil { - logerror("failed to sign up or sign in: %v", err) - } - } - - loginfo("keep an eye on `%s` for more updates!", baseURL.String()) - - return nil - }, - } -} -func setReleaseChannel(cfg *config.Config) error { - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg == nil { - return nil - } - releaseChannel := os.Getenv("HUMANLOG_CHANNEL") - if releaseChannel == "" { - return nil - } - if releaseChannel == defaultReleaseChannel { - return nil - } - - if expcfg.ReleaseChannel != nil && *expcfg.ReleaseChannel == releaseChannel { - return nil - } - expcfg.ReleaseChannel = ptr(releaseChannel) - return cfg.WriteBack() -} - -func wasMoreThanTimeAgo(now time.Time, t *time.Time, ago time.Duration) bool { - if t == nil { - return true - } - lastAgo := now.Sub(*t) - return lastAgo > ago -} - -func pjson(v any) string { - out, err := json.MarshalIndent(v, "", " ") - if err != nil { - panic(err) - } - return string(out) -} diff --git a/cmd/humanlog/organization.go b/cmd/humanlog/organization.go deleted file mode 100644 index cfdad2f6..00000000 --- a/cmd/humanlog/organization.go +++ /dev/null @@ -1,246 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log/slog" - "net/http" - - "connectrpc.com/connect" - "github.com/minitape/api/go/svc/auth/v1/authv1connect" - "github.com/minitape/api/go/svc/organization/v1/organizationv1connect" - userv1 "github.com/minitape/api/go/svc/user/v1" - "github.com/minitape/api/go/svc/user/v1/userv1connect" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/iterapi" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/urfave/cli" -) - -const ( - organizationCmdName = "organization" -) - -func organizationCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - - return cli.Command{ - Hidden: hideUnreleasedFeatures == "true", - Name: organizationCmdName, - ShortName: "org", - Usage: "Manage organizations for the current user.", - Before: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - return nil - }, - Subcommands: []cli.Command{ - { - Name: "set-current", - Usage: "set the org currently configured in the CLI", - ArgsUsage: "", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - organizationName := cctx.Args().First() - if organizationName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - authClient := authv1connect.NewAuthServiceClient(httpClient, apiURL, getConnectOpts(cctx)...) - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - - iter := ListOrganizations(ctx, userClient) - - for iter.Next() { - li := iter.Current() - if li.Organization.Name != organizationName { - continue - } - _, err := performLoginFlow(ctx, state, authClient, tokenSource, "", li.Organization.Id, "") - return err - } - if err := iter.Err(); err != nil { - return err - } - return fmt.Errorf("you're not part of any org with name %q", organizationName) - }, - }, - { - Name: "get-current", - Usage: "get the org currently configured in the CLI", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - whoamiRes, err := userClient.Whoami(ctx, connect.NewRequest(&userv1.WhoamiRequest{})) - if err != nil { - return fmt.Errorf("unable to check who you are: %v", err) - } - org := whoamiRes.Msg.CurrentOrganization - - printFact("org id", org.Id) - printFact("org name", org.Name) - printFact("created on", org.CreatedAt.AsTime()) - return nil - - }, - }, - { - Name: "switch", - Usage: "switch to a different org. like `set-current` but with a prompt", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - authClient := authv1connect.NewAuthServiceClient(httpClient, apiURL, clOpts...) - - orgID, err := huhSelectOrganizations(ctx, userClient, "Which org do you want to switch to?") - if err != nil { - return err - } - - _, err = performLoginFlow(ctx, state, authClient, tokenSource, "", orgID, "") - - return err - }, - }, - { - Name: "get", - Usage: "get an org's details", - ArgsUsage: "", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - organizationName := cctx.Args().First() - if organizationName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - - el, ok, err := iterapi.Find(ListOrganizations(ctx, userClient), func(el *userv1.ListOrganizationResponse_ListItem) bool { - return el.Organization.Name == organizationName - }) - if err != nil { - return err - } - if !ok { - return fmt.Errorf("no org with name %q", organizationName) - } - printFact("id", el.Organization.Id) - printFact("name", el.Organization.Name) - printFact("created at", el.Organization.CreatedAt.AsTime()) - return nil - }, - }, - { - Name: "list", - Usage: "list the orgs you belong to", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - userClient := userv1connect.NewUserServiceClient(httpClient, apiURL, clOpts...) - - iter := ListOrganizations(ctx, userClient) - - for iter.Next() { - li := iter.Current() - org := li.Organization - printFact("name", org.Name) - return nil - } - if err := iter.Err(); err != nil { - return err - } - return nil - }, - }, - { - Name: "list-users", - Usage: "list the users in an org you belong to", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - organizationClient := organizationv1connect.NewOrganizationServiceClient(httpClient, apiURL, clOpts...) - iter := ListOrgUser(ctx, organizationClient) - for iter.Next() { - u := iter.Current().User - printFact("id", u.Id) - printFact("email", u.Email) - } - if err := iter.Err(); err != nil { - return err - } - - return nil - }, - }, - }, - } -} diff --git a/cmd/humanlog/project.go b/cmd/humanlog/project.go deleted file mode 100644 index 4d651584..00000000 --- a/cmd/humanlog/project.go +++ /dev/null @@ -1,333 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log/slog" - "net/http" - "os" - - "connectrpc.com/connect" - projectv1 "github.com/minitape/api/go/svc/project/v1" - "github.com/minitape/api/go/svc/project/v1/projectv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/urfave/cli" -) - -const ( - projectCmdName = "project" -) - -func projectCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - - var ( - localhostFlag = cli.BoolFlag{Name: "localhost"} - dashboardsDirFlag = cli.StringFlag{Name: "dashboards", Value: "tel/dashboards"} - alertsDirFlag = cli.StringFlag{Name: "alerts", Value: "tel/alerts"} - ) - getProjectClient := func(cctx *cli.Context, useLocalhost bool) (_ projectv1connect.ProjectServiceClient, envID int64, _ error) { - ctx := getCtx(cctx) - ll := getLogger(cctx) - state := getState(cctx) - clOpts := getConnectOpts(cctx) - ll.InfoContext(ctx, "localhost value", slog.Bool("localhost", useLocalhost)) - var ( - apiURL string - httpClient *http.Client - ) - if !useLocalhost { - tokenSource := getTokenSource(cctx) - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - apiURL = getAPIUrl(cctx) - httpClient = getHTTPClient(cctx, apiURL) - environmentID, err := ensureEnvironmentSelected(ctx, ll, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return nil, 0, fmt.Errorf("selecting environment to interact with") - } - envID = environmentID - } else { - cfg := getCfg(cctx) - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg == nil || expcfg.ServeLocalhost == nil { - return nil, 0, fmt.Errorf("localhost feature is not enabled or not configured, can't dial localhost") - } - apiURL = fmt.Sprintf("http://localhost:%d", expcfg.ServeLocalhost.Port) - httpClient = getHTTPClient(cctx, apiURL) - } - - return projectv1connect.NewProjectServiceClient(httpClient, apiURL, clOpts...), envID, nil - } - - return cli.Command{ - Hidden: hideUnreleasedFeatures == "true", - Name: projectCmdName, - Usage: "Manage projects.", - Flags: []cli.Flag{localhostFlag}, - Subcommands: []cli.Command{ - { - Name: "init", - Usage: "initialize a local project in the current directory", - ArgsUsage: " ", - Flags: []cli.Flag{dashboardsDirFlag, alertsDirFlag}, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - - projectName := cctx.Args().First() - if projectName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - path := cctx.Args().Get(1) - if path == "" || path == "." { - cwd, err := os.Getwd() - if err != nil { - return err - } - path = cwd - } - dashboardDir := cctx.String(dashboardsDirFlag.Name) - alertDir := cctx.String(alertsDirFlag.Name) - projectClient, envID, err := getProjectClient(cctx, true) - if err != nil { - return fmt.Errorf("preparing project client: %v", err) - } - - pointer := &typesv1.ProjectPointer{} - - pointer.Scheme = &typesv1.ProjectPointer_Localhost{ - Localhost: &typesv1.ProjectPointer_LocalGit{ - Path: path, - DashboardDir: dashboardDir, - AlertDir: alertDir, - ReadOnly: false, - }, - } - - createRes, err := projectClient.CreateProject(ctx, connect.NewRequest(&projectv1.CreateProjectRequest{ - EnvironmentId: envID, - Spec: &typesv1.ProjectSpec{ - Name: projectName, - Pointer: pointer, - }, - })) - if err != nil { - return fmt.Errorf("creating project: %v", err) - } - project := createRes.Msg.Project - printProject(project) - - return nil - }, - }, - { - Name: "track-remote", - Usage: "track a remote project", - ArgsUsage: " ", - Flags: []cli.Flag{dashboardsDirFlag, alertsDirFlag}, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - - projectName := cctx.Args().First() - if projectName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - url := cctx.Args().Get(1) - if url == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - ref := cctx.Args().Get(2) - if ref == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - - dashboardDir := cctx.String(dashboardsDirFlag.Name) - alertDir := cctx.String(alertsDirFlag.Name) - projectClient, envID, err := getProjectClient(cctx, true) - if err != nil { - return fmt.Errorf("preparing project client: %v", err) - } - - pointer := &typesv1.ProjectPointer{} - - pointer.Scheme = &typesv1.ProjectPointer_Remote{ - Remote: &typesv1.ProjectPointer_RemoteGit{ - RemoteUrl: url, - Ref: ref, - DashboardDir: dashboardDir, - AlertDir: alertDir, - }, - } - - createRes, err := projectClient.CreateProject(ctx, connect.NewRequest(&projectv1.CreateProjectRequest{ - EnvironmentId: envID, - Spec: &typesv1.ProjectSpec{ - Name: projectName, - Pointer: pointer, - }, - })) - if err != nil { - return fmt.Errorf("creating project: %v", err) - } - project := createRes.Msg.Project - printProject(project) - - return nil - }, - }, - { - Name: "get", - Usage: "get a specific project in an environment", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - projectName := cctx.Args().First() - if projectName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - projectClient, envID, err := getProjectClient(cctx, cctx.GlobalBool(localhostFlag.Name)) - if err != nil { - return fmt.Errorf("preparing project client: %v", err) - } - - getRes, err := projectClient.GetProject(ctx, connect.NewRequest(&projectv1.GetProjectRequest{ - EnvironmentId: envID, - Name: projectName, - })) - if err != nil { - return fmt.Errorf("retrieving project: %v", err) - } - msg := getRes.Msg - printProject(msg.Project) - for _, db := range msg.Dashboards { - printDashboard(db) - } - for _, ag := range msg.AlertGroups { - printAlertGroup(ag) - } - return nil - }, - }, - { - Name: "delete", - Usage: "delete a specific project in an environment", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - projectName := cctx.Args().First() - if projectName == "" { - logerror("missing argument: ") - return cli.ShowSubcommandHelp(cctx) - } - projectClient, envID, err := getProjectClient(cctx, cctx.GlobalBool(localhostFlag.Name)) - if err != nil { - return fmt.Errorf("preparing project client: %v", err) - } - - deleteRes, err := projectClient.DeleteProject(ctx, connect.NewRequest(&projectv1.DeleteProjectRequest{ - EnvironmentId: envID, - Name: projectName, - })) - if err != nil { - return fmt.Errorf("retrieving project: %v", err) - } - _ = deleteRes - loginfo("project %q was deleted", projectName) - return nil - }, - }, - { - Name: "list", - Usage: "list the projects in an environment", - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - - projectClient, envID, err := getProjectClient(cctx, cctx.GlobalBool(localhostFlag.Name)) - if err != nil { - return fmt.Errorf("preparing project client: %v", err) - } - - anyProject := false - iter := ListProjects(ctx, envID, projectClient) - for iter.Next() { - anyProject = true - project := iter.Current().Project - printProject(project) - } - if err := iter.Err(); err != nil { - return fmt.Errorf("listing projects: %v", err) - } - if !anyProject { - loginfo("no project found") - } - return nil - }, - }, - }, - } -} - -func printProject(project *typesv1.Project) { - printFact("name", project.Spec.Name) - switch scheme := project.Spec.Pointer.Scheme.(type) { - case *typesv1.ProjectPointer_Remote: - printFact("type", "remote") - printFact("type.remote.ref", scheme.Remote.Ref) - printFact("type.remote.url", scheme.Remote.RemoteUrl) - printFact("type.remote.dashboards", scheme.Remote.DashboardDir) - printFact("type.remote.alerts", scheme.Remote.AlertDir) - case *typesv1.ProjectPointer_Localhost: - printFact("type", "local") - printFact("type.local.path", scheme.Localhost.Path) - printFact("type.local.readonly", scheme.Localhost.ReadOnly) - printFact("type.local.dashboards", scheme.Localhost.DashboardDir) - printFact("type.local.alerts", scheme.Localhost.AlertDir) - case *typesv1.ProjectPointer_Db: - printFact("type", "db") - printFact("type.db.uri", scheme.Db.Uri) - default: - logerror("unexpected project pointer type: %T. this is a bug in humanlog, please report it", scheme) - } -} - -func printDashboard(dashboard *typesv1.Dashboard) { - printFact("id", dashboard.Meta.Id) - printFact("name", dashboard.Spec.Name) - printFact("description", dashboard.Spec.Description) - printFact("is_readonly", dashboard.Spec.IsReadonly) - printFact("created_at", dashboard.Status.CreatedAt) - printFact("updated_at", dashboard.Status.UpdatedAt) -} - -func printAlertGroup(alertGroup *typesv1.AlertGroup) { - printFact("name", alertGroup.Spec.Name) - if alertGroup.Spec.Interval == nil { - printFact("interval", "") - } else { - printFact("interval", alertGroup.Spec.Interval.AsDuration()) - } - if alertGroup.Spec.QueryOffset == nil { - printFact("query_offset", "") - } else { - printFact("query_offset", alertGroup.Spec.QueryOffset.AsDuration()) - } - - printFact("limit", alertGroup.Spec.Limit) - printFact("len(rules)", len(alertGroup.Spec.Rules)) - printFact("labels", alertGroup.Spec.Labels) -} diff --git a/cmd/humanlog/query.go b/cmd/humanlog/query.go deleted file mode 100644 index bcf92a61..00000000 --- a/cmd/humanlog/query.go +++ /dev/null @@ -1,512 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "fmt" - "log" - "log/slog" - "net/http" - "net/url" - "os" - "strconv" - "strings" - "time" - - "connectrpc.com/connect" - "github.com/NimbleMarkets/ntcharts/canvas/runes" - "github.com/NimbleMarkets/ntcharts/linechart" - "github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart" - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/x/term" - "github.com/crazy3lf/colorconv" - queryv1 "github.com/minitape/api/go/svc/query/v1" - "github.com/minitape/api/go/svc/query/v1/queryv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/humanlogio/humanlog/pkg/sink/stdiosink" - "github.com/pkg/browser" - "github.com/urfave/cli" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/types/known/timestamppb" -) - -const ( - queryCmdName = "query" -) - -func queryCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - return cli.Command{ - Name: queryCmdName, - Usage: "Query your logs", - - Subcommands: []cli.Command{ - { - Hidden: hideUnreleasedFeatures == "true", - Name: "api", - Subcommands: []cli.Command{ - queryApiSummarizeCmd( - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getHTTPClient, - getConnectOpts, - ), - queryApiRunCmd( - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getHTTPClient, - getConnectOpts, - ), - }, - }, - }, - - Action: func(cctx *cli.Context) error { - // ctx := getCtx(cctx) - q := strings.Join(cctx.Args(), " ") - log.Printf("query=%q", q) - baseSiteURL := getBaseSiteURL(cctx) - - baseSiteU, err := url.Parse(baseSiteURL) - if err != nil { - return fmt.Errorf("parsing base url: %v", err) - } - queryu := baseSiteU.JoinPath("/localhost/query") - v := queryu.Query() - v.Set("query", q) - queryu.RawQuery = v.Encode() - return browser.OpenURL(queryu.String()) - }, - } -} - -func queryApiSummarizeCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - bucket := cli.IntFlag{Name: "buckets", Value: 20} - fromFlag := cli.DurationFlag{Name: "since", Value: 365 * 24 * time.Hour} - toFlag := cli.DurationFlag{Name: "to", Value: 0} - localhost := cli.BoolFlag{Name: "localhost"} - return cli.Command{ - Name: "summarize", - Flags: []cli.Flag{localhost, fromFlag, toFlag, bucket}, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - state := getState(cctx) - - var queryClient queryv1connect.QueryServiceClient - if !cctx.Bool(localhost.Name) { - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - queryClient = queryv1connect.NewQueryServiceClient(httpClient, apiURL, clOpts...) - } else { - cfg := getCfg(cctx) - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg == nil || expcfg.ServeLocalhost == nil { - return fmt.Errorf("localhost feature is not enabled or not configured, can't dial localhost") - } - apiURL := fmt.Sprintf("http://localhost:%d", expcfg.ServeLocalhost.Port) - httpClient := getHTTPClient(cctx, apiURL) - queryClient = queryv1connect.NewQueryServiceClient(httpClient, apiURL) - } - - termWidth, termHeight, err := term.GetSize(os.Stdout.Fd()) - if err != nil { - return fmt.Errorf("getting term size: %v", err) - } - now := time.Now() - var ( - from *timestamppb.Timestamp - to *timestamppb.Timestamp - ) - if cctx.Duration(fromFlag.Name) != 0 { - from = timestamppb.New(now.Add(-cctx.Duration(fromFlag.Name))) - } - if cctx.Duration(toFlag.Name) != 0 { - to = timestamppb.New(now.Add(-cctx.Duration(toFlag.Name))) - } - - res, err := queryClient.SummarizeEvents(ctx, connect.NewRequest(&queryv1.SummarizeEventsRequest{ - // EnvironmentId: *state.CurrentEnvironmentID, - BucketCount: uint32(cctx.Int(bucket.Name)), - From: from, - To: to, - })) - if err != nil { - return fmt.Errorf("querying summary data: %v", err) - } - - buckets := res.Msg.Buckets - - firstTimeformat := "'06 01/02 15:04:05" - width := res.Msg.BucketWidth.AsDuration() - if width < time.Microsecond { - firstTimeformat = "'06 01/02 15:04:05.000000000" - } else if width < time.Millisecond { - firstTimeformat = "'06 01/02 15:04:05.000000" - } else if width < time.Second { - firstTimeformat = "'06 01/02 15:04:05.000" - } else if width > 24*time.Hour { - firstTimeformat = "'06 01/02" - } - lastTimeFormat := "'06 01/02 15:04:05" - window := to.AsTime().Sub(from.AsTime()) - if window < time.Microsecond { - lastTimeFormat = ".000000000" - } else if window < time.Millisecond { - lastTimeFormat = ".000000" - } else if window < time.Second { - lastTimeFormat = ".000" - } else if window < time.Minute { - lastTimeFormat = "05s" - } else if window < time.Hour { - lastTimeFormat = "15:04:05" - } else if window < 24*time.Hour { - lastTimeFormat = "15:04" - } else if window > 24*time.Hour { - lastTimeFormat = "'06 01/02" - } - stepTimeFormat := "'06 01/02 15:04:05" - if width < time.Microsecond { - stepTimeFormat = ".000000000" - } else if width < time.Millisecond { - stepTimeFormat = ".000000" - } else if width < time.Second { - stepTimeFormat = ".000" - } else if width < time.Minute { - stepTimeFormat = "05s" - } else if width < time.Hour { - stepTimeFormat = "15:04:05" - } else if width < 24*time.Hour { - stepTimeFormat = "15:04" - } else if width > 24*time.Hour { - stepTimeFormat = "'06 01/02" - } - - tslc := timeserieslinechart.New(termWidth, termHeight-3, - timeserieslinechart.WithTimeRange(from.AsTime(), to.AsTime()), - ) - tslc.XLabelFormatter = linechart.LabelFormatter(func(i int, f float64) string { - t := time.Unix(int64(f), 0).UTC() - var ts string - if i == 0 { - ts = t.Format(firstTimeformat) - } else if i == len(buckets)-1 { - ts = t.Format(lastTimeFormat) - } else { - ts = t.Format(stepTimeFormat) - } - loginfo("label: ts=%v", ts) - return ts - }) - for _, bucket := range buckets { - loginfo("ts=%v ev=%d", bucket.Ts.AsTime().Format(time.RFC3339Nano), bucket.GetEventCount()) - tslc.Push(timeserieslinechart.TimePoint{ - Time: bucket.Ts.AsTime(), - Value: float64(bucket.GetEventCount()), - }) - } - tslc.SetLineStyle(runes.ThinLineStyle) - tslc.Draw() - - fmt.Fprint(os.Stdout, tslc.View()) - - return nil - }, - } -} - -func queryApiRunCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - fromFlag := cli.DurationFlag{Name: "since", Value: 365 * 24 * time.Hour} - toFlag := cli.DurationFlag{Name: "to", Value: 0} - localhost := cli.BoolFlag{Name: "localhost"} - format := cli.StringFlag{Name: "format", Value: "humanlog"} - limit := cli.IntFlag{Name: "limit", Value: 10} - return cli.Command{ - Name: "run", - Flags: []cli.Flag{localhost, fromFlag, toFlag, format, limit}, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - cfg := getCfg(cctx) - state := getState(cctx) - var queryClient queryv1connect.QueryServiceClient - if !cctx.Bool(localhost.Name) { - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - queryClient = queryv1connect.NewQueryServiceClient(httpClient, apiURL, clOpts...) - } else { - cfg := getCfg(cctx) - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg == nil || expcfg.ServeLocalhost == nil { - return fmt.Errorf("localhost feature is not enabled or not configured, can't dial localhost") - } - apiURL := fmt.Sprintf("http://localhost:%d", expcfg.ServeLocalhost.Port) - httpClient := getHTTPClient(cctx, apiURL) - queryClient = queryv1connect.NewQueryServiceClient(httpClient, apiURL) - } - now := time.Now() - var ( - from *timestamppb.Timestamp - to *timestamppb.Timestamp - query = strings.Join(cctx.Args(), " ") - ) - if cctx.Duration(fromFlag.Name) != 0 { - from = timestamppb.New(now.Add(-cctx.Duration(fromFlag.Name))) - } - if cctx.Duration(toFlag.Name) != 0 { - to = timestamppb.New(now.Add(-cctx.Duration(toFlag.Name))) - } - sinkOpts, errs := stdiosink.StdioOptsFrom(cfg.GetFormatter()) - if len(errs) > 0 { - for _, err := range errs { - logerror("config error: %v", err) - } - } - - loginfo("from=%s", from) - loginfo("to=%s", to) - loginfo("query=%s", query) - - var environmentID int64 - if state.CurrentEnvironmentID != nil { - environmentID = *state.CurrentEnvironmentID - } - - start := time.Now() - parseRes, err := queryClient.Parse(ctx, connect.NewRequest(&queryv1.ParseRequest{Query: query})) - if err != nil { - return fmt.Errorf("parsing query: %v", err) - } - parsedIn := time.Since(start) - lq := parseRes.Msg.Query - - if lq.Timerange == nil { - lq.Timerange = new(typesv1.Timerange) - } - if lq.Timerange.From == nil && from != nil { - lq.Timerange.From = typesv1.ExprLiteral(typesv1.ValTimestamp(from)) - } - if lq.Timerange.To == nil && to != nil { - lq.Timerange.To = typesv1.ExprLiteral(typesv1.ValTimestamp(to)) - } - - var printer func(*typesv1.Data) error - switch cctx.String(format.Name) { - case "json": - - printer = func(data *typesv1.Data) error { - b, err := protojson.Marshal(data) - if err != nil { - return fmt.Errorf("marshaling: %v", err) - } - _, err = os.Stdout.Write(b) - _, _ = os.Stdout.WriteString("\n") - return err - } - case "humanlog": - - sink, err := stdiosink.NewStdio(os.Stdout, sinkOpts) - if err != nil { - return fmt.Errorf("preparing stdio printer: %v", err) - } - printer = func(data *typesv1.Data) error { - var events []*typesv1.Log - switch shape := data.Shape.(type) { - case *typesv1.Data_Logs: - events = shape.Logs.Logs - default: - return fmt.Errorf("todo: handle data shape %T", shape) - } - - for _, ev := range events { - if err := sink.Receive(ctx, ev); err != nil { - return fmt.Errorf("printing log: %v", err) - } - } - return nil - } - default: - return fmt.Errorf("unsupported format: %q", cctx.String(format.Name)) - } - - var ( - limit = int32(cctx.Int(limit.Name)) - req = &queryv1.QueryRequest{ - EnvironmentId: environmentID, - Query: lq, - Cursor: nil, - Limit: limit, - } - ) - var ( - totalQueryTime time.Duration - queriedInAll []time.Duration - ) - for { - - start := time.Now() - res, err := queryClient.Query(ctx, connect.NewRequest(req)) - if err != nil { - return fmt.Errorf("calling Query: %v", err) - } - queriedIn := time.Since(start) - totalQueryTime += queriedIn - queriedInAll = append(queriedInAll, queriedIn) - data := res.Msg.Data - if err := printer(data); err != nil { - return fmt.Errorf("printing data: %v", err) - } - if res.Msg.Next == nil { - break - } - req.Cursor = res.Msg.Next - } - - var queriedAllDur []string - for _, queriedIn := range queriedInAll { - queriedAllDur = append(queriedAllDur, queriedIn.String()) - } - - _ = json.NewEncoder(os.Stderr).Encode(map[string]any{ - "parsed_in": parsedIn.String(), - "pages": len(queriedInAll), - "total_query_time": totalQueryTime.String(), - "all_query_times": queriedAllDur, - }) - - return nil - }, - } -} - -type tuple struct{ m, s int64 } - -var colorPrefixes = map[tuple]string{} - -func getPrefix(machine, session int64) string { - prefix, ok := colorPrefixes[tuple{m: machine, s: session}] - if ok { - return prefix - } - s := lipgloss.NewStyle(). - BorderStyle(lipgloss.DoubleBorder()).BorderRight(true) - - mPrefix := s.Background(lipgloss.AdaptiveColor{ - Light: int64toLightRGB(machine), - Dark: int64toDarkRGB(machine), - }).Render(strconv.FormatInt(machine, 10)) - sPrefix := s.Background(lipgloss.AdaptiveColor{ - Light: int64toLightRGB(session), - Dark: int64toDarkRGB(session), - }).Render(strconv.FormatInt(session, 10)) - - prefix = lipgloss.JoinHorizontal(lipgloss.Left, mPrefix, sPrefix) - colorPrefixes[tuple{m: machine, s: session}] = prefix - return prefix -} - -func int64toDarkRGB(n int64) string { - // modified from https://stackoverflow.com/a/52746259 - n = (374761397 + n*3266489917) & 0xffffffff - n = ((n ^ n>>15) * 2246822519) & 0xffffffff - n = ((n ^ n>>13) * 3266489917) & 0xffffffff - n = (n ^ n>>16) >> 8 - - hex := fmt.Sprintf("#%06x", n) - - // clamp the brightness - r, g, b, err := colorconv.HexToRGB(hex) - if err != nil { - panic(err) - } - h, s, v := colorconv.RGBToHSV(r, g, b) - if v > 0.5 { - v -= 0.5 - } - r, g, b, err = colorconv.HSVToRGB(h, s, v) - if err != nil { - panic(err) - } - return fmt.Sprintf("#%02x%02x%02x", r, g, b) -} - -func int64toLightRGB(n int64) string { - // modified from https://stackoverflow.com/a/52746259 - n = (374761397 + n*3266489917) & 0xffffffff - n = ((n ^ n>>15) * 2246822519) & 0xffffffff - n = ((n ^ n>>13) * 3266489917) & 0xffffffff - n = (n ^ n>>16) >> 8 - - hex := fmt.Sprintf("#%06x", n) - - // clamp the brightness - r, g, b, err := colorconv.HexToRGB(hex) - if err != nil { - panic(err) - } - h, s, v := colorconv.RGBToHSV(r, g, b) - if v < 0.5 { - v += 0.5 - } - r, g, b, err = colorconv.HSVToRGB(h, s, v) - if err != nil { - panic(err) - } - return fmt.Sprintf("#%02x%02x%02x", r, g, b) -} diff --git a/cmd/humanlog/query_test.go b/cmd/humanlog/query_test.go deleted file mode 100644 index 846c898d..00000000 --- a/cmd/humanlog/query_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_int64toLightRGB(t *testing.T) { - tests := []struct { - name string - in int64 - want string - }{ - { - in: 62, - want: "#3aef45", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := int64toLightRGB(tt.in) - require.Equal(t, tt.want, got) - }) - } -} - -func Test_int64toDarkRGB(t *testing.T) { - tests := []struct { - name string - in int64 - want string - }{ - { - in: 62, - want: "#1b6f20", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := int64toDarkRGB(tt.in) - require.Equal(t, tt.want, got) - }) - } -} - -func Test_getPrefix(t *testing.T) { - type args struct { - machine int64 - session int64 - } - tests := []struct { - name string - args args - want string - }{ - { - args: args{machine: 1, session: 2}, - want: "1║2║", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := getPrefix(tt.args.machine, tt.args.session); got != tt.want { - t.Errorf("getPrefix() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/cmd/humanlog/service.go b/cmd/humanlog/service.go deleted file mode 100644 index f73db701..00000000 --- a/cmd/humanlog/service.go +++ /dev/null @@ -1,918 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - "log/slog" - "net/http" - "os" - "os/user" - "path/filepath" - "runtime" - "slices" - "sync" - "time" - - "connectrpc.com/connect" - "google.golang.org/protobuf/types/known/timestamppb" - - connectcors "connectrpc.com/cors" - otelconnect "connectrpc.com/otelconnect" - "github.com/blang/semver" - "github.com/go-git/go-billy/v6/osfs" - "github.com/minitape/api/go/svc/auth/v1/authv1connect" - cliupdatepb "github.com/minitape/api/go/svc/cliupdate/v1" - "github.com/minitape/api/go/svc/cliupdate/v1/cliupdatev1connect" - "github.com/minitape/api/go/svc/feature/v1/featurev1connect" - userv1 "github.com/minitape/api/go/svc/user/v1" - "github.com/minitape/api/go/svc/user/v1/userv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/localproject" - "github.com/humanlogio/humanlog/internal/localserver" - "github.com/humanlogio/humanlog/internal/localstate" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/selfupdate" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/humanlogio/humanlog/pkg/localstorage" - ksvc "github.com/kardianos/service" - "github.com/mitchellh/go-homedir" - "github.com/rs/cors" - "github.com/urfave/cli" - "go.opentelemetry.io/contrib/propagators/b3" - "go.opentelemetry.io/contrib/propagators/ot" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/propagation" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.34.0" - "golang.org/x/sync/errgroup" -) - -const ( - serviceCmdName = "service" -) - -func serviceCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - var svcHandler *serviceHandler - return cli.Command{ - Hidden: hideUnreleasedFeatures == "true", - Name: serviceCmdName, - ShortName: "svc", - Usage: "Run humanlog as a background service, with a systray and all.", - Before: func(cctx *cli.Context) error { - var err error - svcHandler, err = prepareServiceCmd(cctx, - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getBaseSiteURL, - getHTTPClient, - ) - return err - }, - After: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) - defer cancel() - - if svcHandler == nil { - return nil // service was never started - } - return svcHandler.close(ctx) - }, - Subcommands: []cli.Command{ - { - Name: "install", - Action: func(cctx *cli.Context) error { - return svcHandler.Install() - }, - }, - { - Name: "uninstall", - Action: func(cctx *cli.Context) error { - return svcHandler.Uninstall() - }, - }, - { - Name: "reinstall", - Action: func(cctx *cli.Context) error { - if err := svcHandler.Uninstall(); err != nil { - logerror("will install, but couldn't uninstall first: %v", err) - } - return svcHandler.Install() - }, - }, - { - Name: "start", - Action: func(cctx *cli.Context) error { - return svcHandler.Start(svcHandler.ctx) - }, - }, - { - Name: "stop", - Action: func(cctx *cli.Context) error { - return svcHandler.Stop(svcHandler.ctx) - }, - }, - { - Name: "restart", - Action: func(cctx *cli.Context) error { - if err := svcHandler.Stop(svcHandler.ctx); err != nil { - logwarn("failed to stop: %v", err) - } - return svcHandler.Start(svcHandler.ctx) - }, - }, - { - Name: "run", - Action: func(cctx *cli.Context) error { - // don't use `svc.Run` because it doesn't do anything useful - // and it prevents control over running systray running on the - // main thread, which it requires. - ctx := getCtx(cctx) - cfg := getCfg(cctx) - ll := getLogger(cctx) - baseSiteURL := getBaseSiteURL(cctx) - ll.InfoContext(ctx, "service preparing to start") - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - eg, ctx := errgroup.WithContext(ctx) - - eg.Go(func() error { - err := svcHandler.run(ctx, cancel) - if err != nil { - ll.ErrorContext(ctx, "service stopped running with an error", slog.Any("err", err)) - return err - } - ll.InfoContext(ctx, "service stopped running without problems") - return err - }) - - go func() { - defer cancel() - ll.InfoContext(ctx, "service started, all command groups are on") - if err := eg.Wait(); err != nil { - ll.ErrorContext(ctx, "service command group had an error", slog.Any("err", err)) - - } else { - ll.InfoContext(ctx, "service command group is done") - } - // schedule a hard kill in 1s if something is blocking - go time.AfterFunc(time.Second, func() { - ll.ErrorContext(ctx, "service shutdown stuck, resorting to hard exit. sorry fam") - os.Exit(1) - }) - }() - - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg != nil && expcfg.ServeLocalhost != nil && expcfg.ServeLocalhost.ShowInSystray != nil && *expcfg.ServeLocalhost.ShowInSystray { - trayll := ll.WithGroup("systray") - if err := runSystray(ctx, trayll, svcHandler, version, baseSiteURL); err != nil { - trayll.ErrorContext(ctx, "systray stopped in error", slog.Any("err", err)) - cancel() - } - } else { - // wait for cancellation - <-ctx.Done() - } - - return nil - }, - }, - }, - } -} - -func prepareServiceCmd( - cctx *cli.Context, - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, -) ( - svcHandler *serviceHandler, - err error, -) { - u, err := user.Current() - if err != nil { - return nil, fmt.Errorf("looking up current user: %v", err) - } - ctx := getCtx(cctx) - ll := getLogger(cctx) - config := getCfg(cctx) - state := getState(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - baseSiteURL := getBaseSiteURL(cctx) - httpClient := getHTTPClient(cctx, apiURL) - - authCheckFrequency := time.Minute - updateCheckFrequency := time.Hour - - doneOtel := func(ctx context.Context) error { return nil } - expcfg := config.GetRuntime().GetExperimentalFeatures() - if expcfg != nil { - // check for updates more often if you use - // experimental features - updateCheckFrequency = 10 * time.Minute - if expcfg.ReleaseChannel != nil { - // and even more frequently if using a non-default channel - updateCheckFrequency = time.Minute - } - - shouldEmitOtel := expcfg.GetServeLocalhost().GetOtlp() != nil - isDevMode := expcfg.GetReleaseChannel() == "dev" - if shouldEmitOtel && isDevMode { - ll.DebugContext(ctx, "setting up self-monitoring with otel") - doneOtel, err = setupOtel(ctx, ll) - if err != nil { - ll.ErrorContext(ctx, "can't setup self-monitoring with otel", slog.Any("err", err)) - } - } - } - - otelIctpr, err := otelconnect.NewInterceptor() - if err != nil { - doneOtel(ctx) - return nil, fmt.Errorf("can't create otel interceptors for clients: %v", err) - } - baseIcptrs := []connect.Interceptor{otelIctpr} - - publicIcptrs := append(baseIcptrs, auth.NewRefreshedUserAuthInterceptor(ll, tokenSource)) - authedIcptrs := append(baseIcptrs, auth.Interceptors(ll, tokenSource)...) - - publicClOpts := connect.WithInterceptors(publicIcptrs...) - authedClOpts := connect.WithInterceptors(authedIcptrs...) - - svcCfg := &ksvc.Config{ - Name: "io.humanlog.humanlogd", - DisplayName: "humanlog.io", - Description: "humanlog runs a service on your machine so that you can send it data and then query it back", - UserName: u.Name, - Arguments: []string{serviceCmdName, "run"}, - Option: ksvc.KeyValue{ - // darwin stuff - "KeepAlive": true, - "RunAtLoad": true, - "UserService": true, - "SessionCreate": true, - }, - } - svcHandler, err = newServiceHandler( - ctx, - ll, - config, - state, - svcCfg, - baseSiteURL, - tokenSource, - authCheckFrequency, - updateCheckFrequency, - cliupdatev1connect.NewUpdateServiceClient(httpClient, apiURL, publicClOpts), - authv1connect.NewAuthServiceClient(httpClient, apiURL, publicClOpts), - userv1connect.NewUserServiceClient(httpClient, apiURL, authedClOpts), - featurev1connect.NewFeatureServiceClient(httpClient, apiURL, authedClOpts), - doneOtel, - ) - if err != nil { - return nil, fmt.Errorf("preparing service: %v", err) - } - return svcHandler, nil -} - -type systrayClient interface { - NotifyError(ctx context.Context, err error) error - NotifyUnauthenticated(ctx context.Context) error - NotifyAuthenticated(ctx context.Context, user *typesv1.User, defaultOrg, currentOrg *typesv1.Organization) error - NotifyUpdateAvailable(ctx context.Context, oldV, newV *typesv1.Version) error - NotifyAlert(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error -} - -type serviceClient interface { - DoLogout(ctx context.Context, returnToURL string) error - DoLogin(ctx context.Context, returnToURL string) error - DoUpdate(ctx context.Context) error - DoRestart(ctx context.Context) error - CheckUpdate(ctx context.Context) error - - LastUpdateCheck(ctx context.Context) (*timestamppb.Timestamp, error) - CurrentConfig(ctx context.Context) (*config.CurrentConfig, error) -} - -var _ serviceClient = (*serviceHandler)(nil) - -type serviceHandler struct { - ctx context.Context - ll *slog.Logger - config *config.Config - localhostCfg *typesv1.ServeLocalhostConfig - state *state.State - svcCfg *ksvc.Config - baseSiteURL string - tokenSource *auth.UserRefreshableTokenSource - authCheckFrequency time.Duration - updateCheckFrequency time.Duration - - updateSvc cliupdatev1connect.UpdateServiceClient - authSvc authv1connect.AuthServiceClient - userSvc userv1connect.UserServiceClient - featureSvc featurev1connect.FeatureServiceClient - - clientMu sync.Mutex - client systrayClient - - cancel context.CancelFunc - onCloseMu sync.Mutex - onClose []func(context.Context) error -} - -func newServiceHandler( - ctx context.Context, - ll *slog.Logger, - cfg *config.Config, - state *state.State, - svcCfg *ksvc.Config, - baseSiteURL string, - tokenSource *auth.UserRefreshableTokenSource, - authCheckFrequency time.Duration, - updateCheckFrequency time.Duration, - updateSvc cliupdatev1connect.UpdateServiceClient, - authSvc authv1connect.AuthServiceClient, - userSvc userv1connect.UserServiceClient, - featureSvc featurev1connect.FeatureServiceClient, - doneOtel func(context.Context) error, -) (*serviceHandler, error) { - if authCheckFrequency < time.Minute { - authCheckFrequency = time.Minute - } - if updateCheckFrequency < time.Minute { - updateCheckFrequency = time.Minute - } - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg == nil || expcfg.ServeLocalhost == nil { - return nil, fmt.Errorf("experimental localhost features is not enabled") - } - - hdl := &serviceHandler{ - ctx: ctx, - ll: ll, - config: cfg, - localhostCfg: expcfg.ServeLocalhost, - state: state, - svcCfg: svcCfg, - baseSiteURL: baseSiteURL, - tokenSource: tokenSource, - authCheckFrequency: time.Minute, - updateCheckFrequency: time.Hour, - updateSvc: updateSvc, - authSvc: authSvc, - userSvc: userSvc, - featureSvc: featureSvc, - onClose: []func(context.Context) error{doneOtel}, - } - - return hdl, nil -} - -func (hdl *serviceHandler) run(ctx context.Context, cancel context.CancelFunc) error { - cfg := hdl.config.GetRuntime() - hdl.cancel = cancel - - hdl.ll.InfoContext(ctx, "service handler starting", slog.Any("runtime_config", cfg)) - - eg, ctx := errgroup.WithContext(ctx) - - if cfg != nil && cfg.ExperimentalFeatures != nil && cfg.ExperimentalFeatures.ServeLocalhost != nil { - localhostCfg := cfg.ExperimentalFeatures.ServeLocalhost - ll := hdl.ll.WithGroup("localhost") - app := &localstorage.AppCtx{ - Version: semverVersion.String(), - EnsureLoggedIn: func(ctx context.Context) error { - return fmt.Errorf("please sign in with the systray button, or via `humanlog auth login`") - }, - Features: hdl.featureSvc, - Config: hdl.config, - State: hdl.state, - } - registerOnCloseServer := func(srv *http.Server) { - hdl.onCloseMu.Lock() - defer hdl.onCloseMu.Unlock() - hdl.onClose = append(hdl.onClose, func(ctx context.Context) error { - ll.InfoContext(ctx, "requesting to close server") - return srv.Close() - }) - } - eg.Go(func() error { - if err := hdl.runLocalhost(ctx, ll, hdl.config, localhostCfg, version, app, registerOnCloseServer); err != nil { - ll.ErrorContext(ctx, "unable to run localhost", slog.Any("err", err)) - return err - } - ll.InfoContext(ctx, "stopped running localhost") - cancel() - return nil - }) - } else { - hdl.ll.InfoContext(ctx, "not running with localhost") - } - - eg.Go(func() error { - if err := hdl.maintainState(ctx); err != nil { - hdl.ll.ErrorContext(ctx, "unable to maintain state", slog.Any("err", err)) - return err - } - hdl.ll.InfoContext(ctx, "stopped maintaining state") - cancel() - return nil - }) - - if err := eg.Wait(); err != nil { - hdl.ll.ErrorContext(ctx, "done waiting", slog.Any("err", err)) - return err - } - hdl.ll.InfoContext(ctx, "shutting down") - - return nil -} - -func (hdl *serviceHandler) close(ctx context.Context) error { - for _, onClose := range hdl.onClose { - if err := onClose(ctx); err != nil { - return err - } - } - return nil -} - -func (hdl *serviceHandler) shutdown(ctx context.Context) error { - ll := hdl.ll - ll.InfoContext(ctx, "stopping service") - tr := time.AfterFunc(10*time.Second, func() { - ll.InfoContext(ctx, "trying harder to stop service cleanly...") - hdl.cancel() - }) // give a stronger hint to quit after 10s - defer tr.Stop() - - dirtyExit := time.AfterFunc(15*time.Second, func() { - ll.InfoContext(ctx, "took too long to exit cleanly, shutting down the hard way") - os.Exit(1) - }) // just die violently after 15s - defer dirtyExit.Stop() - if err := hdl.close(ctx); err != nil { - ll.ErrorContext(ctx, "error closing service handler", slog.Any("err", err)) - } - ll.InfoContext(ctx, "service done") - return nil -} - -func (hdl *serviceHandler) runLocalhost( - ctx context.Context, - ll *slog.Logger, - cfg *config.Config, - localhostCfg *typesv1.ServeLocalhostConfig, - ownVersion *typesv1.Version, - app *localstorage.AppCtx, - registerOnCloseServer func(srv *http.Server), -) error { - openState := func(ctx context.Context, db localstorage.Storage) (localstate.DB, error) { - fs := osfs.New("/") - return localproject.Watch(ctx, fs, cfg, db, func(s string) (*typesv1.Query, error) { - return db.Parse(ctx, s) - }) - } - openStorage := func(ctx context.Context) (localstorage.Storage, error) { - return localstorage.Open( - ctx, - localhostCfg.Engine, - ll.WithGroup("storage"), - localhostCfg.EngineConfig.AsMap(), - app, - ) - } - - return localserver.ServeLocalhost(ctx, ll, localhostCfg, ownVersion, app, openStorage, openState, registerOnCloseServer, - hdl.DoLogin, - hdl.DoLogout, - hdl.DoUpdate, - hdl.DoRestart, - hdl.GetConfig, - hdl.SetConfig, - hdl.whoami, - hdl.notifyAlert, - ) -} - -func (hdl *serviceHandler) primeState(ctx context.Context) { - ll := hdl.ll - expcfg := hdl.config.GetRuntime().GetExperimentalFeatures() - var channelName *string - if hdl.config != nil && expcfg != nil && expcfg.ReleaseChannel != nil { - channelName = expcfg.ReleaseChannel - ll = ll.With(slog.String("channel", *channelName)) - } - ll.InfoContext(ctx, "doing auth check") - if err := hdl.checkAuth(ctx); err != nil { - if err := hdl.notifyError(ctx, err); err != nil { - ll.ErrorContext(ctx, "notifying client of auth check error", slog.Any("err", err)) - } - } - - ll.InfoContext(ctx, "doing update check") - if err := hdl.checkUpdate(ctx, channelName); err != nil { - if err := hdl.notifyError(ctx, err); err != nil { - ll.ErrorContext(ctx, "notifying client of update check error", slog.Any("err", err)) - } - } -} - -func (hdl *serviceHandler) maintainState(ctx context.Context) error { - ll := hdl.ll - expcfg := hdl.config.GetRuntime().GetExperimentalFeatures() - var channelName *string - if hdl.config != nil && expcfg != nil && expcfg.ReleaseChannel != nil { - channelName = expcfg.ReleaseChannel - ll = ll.With(slog.String("channel", *channelName)) - } - - ll.InfoContext(ctx, "priming initial background state") - hdl.primeState(ctx) - ll.InfoContext(ctx, "starting to maintain background state") - - checkAuth := time.NewTicker(hdl.authCheckFrequency) - defer checkAuth.Stop() - checkUpdate := time.NewTicker(hdl.updateCheckFrequency) - defer checkUpdate.Stop() - for { - select { - case <-ctx.Done(): - return nil - case <-checkAuth.C: - ll.InfoContext(ctx, "checking auth status") - if err := hdl.checkAuth(ctx); err != nil { - if err := hdl.notifyError(ctx, err); err != nil { - ll.ErrorContext(ctx, "notifying client of auth check error", slog.Any("err", err)) - } - } - case <-checkUpdate.C: - ll.InfoContext(ctx, "checking update status") - if err := hdl.checkUpdate(ctx, channelName); err != nil { - if err := hdl.notifyError(ctx, err); err != nil { - ll.ErrorContext(ctx, "notifying client of update check error", slog.Any("err", err)) - } - } - } - } -} - -func (hdl *serviceHandler) checkAuth(ctx context.Context) error { - ll := hdl.ll - ll.InfoContext(ctx, "checking auth") - whoami, err := hdl.whoami(ctx) - if err != nil { - return fmt.Errorf("looking up user authentication status: %v", err) - } - if whoami == nil { - return hdl.notifyUnauthenticated(ctx) - } - return hdl.notifyAuthenticated(ctx, whoami.User, whoami.DefaultOrganization, whoami.CurrentOrganization) -} - -func (hdl *serviceHandler) whoami(ctx context.Context) (*userv1.WhoamiResponse, error) { - ll := hdl.ll - ll.InfoContext(ctx, "checking whoami") - cerr := new(connect.Error) - res, err := hdl.userSvc.Whoami(ctx, connect.NewRequest(&userv1.WhoamiRequest{})) - if errors.As(err, &cerr) && cerr.Code() == connect.CodeUnauthenticated { - return nil, nil - } else if err != nil { - return nil, fmt.Errorf("looking up user authentication status: %v", err) - } - return res.Msg, nil -} - -func (hdl *serviceHandler) checkUpdate(ctx context.Context, channel *string) error { - ll := hdl.ll - ll.InfoContext(ctx, "checking for updates") - res, err := hdl.updateSvc.GetNextUpdate(ctx, connect.NewRequest(&cliupdatepb.GetNextUpdateRequest{ - ProjectName: "humanlog", - CurrentVersion: version, - MachineArchitecture: runtime.GOARCH, - MachineOperatingSystem: runtime.GOOS, - Meta: reqMeta(hdl.state), - ReleaseChannelName: channel, - })) - if err != nil { - return fmt.Errorf("looking up next update: %v", err) - } - msg := res.Msg - - lastCheckAt := time.Now() - nextSV, err := msg.NextVersion.AsSemver() - if err != nil { - return fmt.Errorf("parsing next version: %v", err) - } - if err := updateFromResMeta(hdl.state, msg.Meta, &nextSV, &lastCheckAt); err != nil { - ll.ErrorContext(ctx, "failed to persist internal state", slog.Any("err", err)) - } - return hdl.notifyUpdateAvailable(ctx, version, msg.NextVersion) -} - -func (hdl *serviceHandler) DoLogout(ctx context.Context, returnToURL string) error { - hdl.ll.InfoContext(ctx, "DoLogout", slog.String("return_to_url", returnToURL)) - if err := performLogoutFlow(ctx, hdl.userSvc, hdl.tokenSource, returnToURL); err != nil { - return err - } - return hdl.checkAuth(ctx) -} - -func (hdl *serviceHandler) DoLogin(ctx context.Context, returnToURL string) error { - hdl.ll.InfoContext(ctx, "DoLogin", slog.String("return_to_url", returnToURL)) - if _, err := performLoginFlow(ctx, hdl.state, hdl.authSvc, hdl.tokenSource, *hdl.state.LoggedInUsername, 0, returnToURL); err != nil { - return err - } - return hdl.checkAuth(ctx) -} - -func (hdl *serviceHandler) DoUpdate(ctx context.Context) error { - ll := hdl.ll - expcfg := hdl.config.GetRuntime().GetExperimentalFeatures() - baseSiteURL := hdl.baseSiteURL - var channelName *string - if expcfg != nil { - channelName = expcfg.ReleaseChannel - } - ll.InfoContext(ctx, "starting upgrade in place") - sv, err := version.AsSemver() - if err != nil { - ll.ErrorContext(ctx, "getting current version", "error", err) - sv = semver.Version{} - } - if err := selfupdate.UpgradeInPlace(ctx, sv, baseSiteURL, channelName, nil, nil, nil); err != nil { - return fmt.Errorf("applying self-update: %v", err) - } - // triggering self-shutdown - go func() { - time.Sleep(100 * time.Millisecond) - ll.InfoContext(ctx, "triggering self-shutdown, hoping the service manager will restart us") - if err := hdl.shutdown(ctx); err != nil { - ll.ErrorContext(ctx, "shutting down serviceHandler", "error", err) - } else { - ll.InfoContext(ctx, "serviceHandler shut downed") - } - }() - return nil -} - -func (hdl *serviceHandler) DoRestart(ctx context.Context) error { - ll := hdl.ll - // triggering self-shutdown - go func() { - time.Sleep(100 * time.Millisecond) - ll.InfoContext(ctx, "triggering self-shutdown, hoping the service manager will restart us") - if err := hdl.shutdown(ctx); err != nil { - ll.ErrorContext(ctx, "shutting down serviceHandler", "error", err) - } else { - ll.InfoContext(ctx, "serviceHandler shut downed") - } - }() - return nil -} - -func (hdl *serviceHandler) GetConfig(ctx context.Context) (*typesv1.LocalhostConfig, error) { - ll := hdl.ll - // triggering self-shutdown - ll.InfoContext(ctx, "serving localhost config") - return hdl.config.CurrentConfig, nil -} - -func (hdl *serviceHandler) SetConfig(ctx context.Context, cfg *typesv1.LocalhostConfig) error { - ll := hdl.ll - // triggering self-shutdown - ll.InfoContext(ctx, "serving localhost config") - hdl.config.CurrentConfig = cfg - return hdl.config.WriteBack() -} - -func (hdl *serviceHandler) CheckUpdate(ctx context.Context) error { - ll := hdl.ll - var channelName *string - expcfg := hdl.config.GetRuntime().GetExperimentalFeatures() - if expcfg != nil { - channelName = expcfg.ReleaseChannel - } - ll.InfoContext(ctx, "checking for update", slog.String("release_channel", *channelName)) - return hdl.checkUpdate(ctx, channelName) -} - -func (hdl *serviceHandler) LastUpdateCheck(ctx context.Context) (*timestamppb.Timestamp, error) { - updateCheckedAt := hdl.state.LastestKnownVersionUpdatedAt - if updateCheckedAt == nil { - return nil, nil - } - return timestamppb.New(*updateCheckedAt), nil -} - -func (hdl *serviceHandler) CurrentConfig(ctx context.Context) (*config.CurrentConfig, error) { - return hdl.config.CurrentConfig, nil -} - -func (hdl *serviceHandler) registerClient(client systrayClient) { - ctx := hdl.ctx - ll := hdl.ll - ll.InfoContext(ctx, "systray client received") - hdl.clientMu.Lock() - hdl.client = client - hdl.clientMu.Unlock() - ll.InfoContext(ctx, "systray client set, priming it") - hdl.primeState(ctx) - ll.InfoContext(ctx, "systray client primed") -} - -func (hdl *serviceHandler) notifyAlert(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error { - hdl.ll.InfoContext(ctx, "calling notifyAlert") - hdl.clientMu.Lock() - defer hdl.clientMu.Unlock() - if hdl.client == nil { - return nil - } - return hdl.client.NotifyAlert(ctx, ar, o) -} - -func (hdl *serviceHandler) notifyError(ctx context.Context, err error) error { - hdl.ll.InfoContext(ctx, "calling notifyError", slog.Any("err", err)) - hdl.clientMu.Lock() - defer hdl.clientMu.Unlock() - if hdl.client == nil { - return nil - } - return hdl.client.NotifyError(ctx, err) -} - -func (hdl *serviceHandler) notifyUnauthenticated(ctx context.Context) error { - hdl.ll.InfoContext(ctx, "calling notifyUnauthenticated") - hdl.clientMu.Lock() - defer hdl.clientMu.Unlock() - if hdl.client == nil { - return nil - } - return hdl.client.NotifyUnauthenticated(ctx) -} - -func (hdl *serviceHandler) notifyAuthenticated(ctx context.Context, user *typesv1.User, defaultOrg, currentOrg *typesv1.Organization) error { - hdl.ll.InfoContext(ctx, "calling notifyAuthenticated", slog.Any("user", user), slog.Any("defaultOrg", defaultOrg), slog.Any("currentOrg", currentOrg)) - hdl.clientMu.Lock() - defer hdl.clientMu.Unlock() - if hdl.client == nil { - return nil - } - return hdl.client.NotifyAuthenticated(ctx, user, defaultOrg, currentOrg) -} - -func (hdl *serviceHandler) notifyUpdateAvailable(ctx context.Context, oldV, newV *typesv1.Version) error { - hdl.ll.InfoContext(ctx, "calling notifyUpdateAvailable", slog.Any("oldV", oldV), slog.Any("newV", newV)) - hdl.clientMu.Lock() - defer hdl.clientMu.Unlock() - if hdl.client == nil { - return nil - } - return hdl.client.NotifyUpdateAvailable(ctx, oldV, newV) -} - -func withCORS(hdl http.Handler) http.Handler { - c := cors.New(cors.Options{ - // Debug: true, - AllowedOrigins: []string{ - "https://humanlog.io", - "https://humanlog.dev", - "https://app.humanlog.dev", - "https://app.humanlog.dev:3000", - "https://humanlog.sh", - "http://localhost:3000", - "https://humanlog.test:3000", - }, - AllowedMethods: connectcors.AllowedMethods(), - AllowedHeaders: slices.Concat( - connectcors.AllowedHeaders(), - []string{"Browser-Authorization", "Request-Id"}, - ot.OT{}.Fields(), - b3.New(b3.WithInjectEncoding(b3.B3SingleHeader)).Fields(), - b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader)).Fields(), - ), - ExposedHeaders: slices.Concat( - connectcors.ExposedHeaders(), - []string{"Browser-Authorization", "Request-Id"}, - ot.OT{}.Fields(), - b3.New(b3.WithInjectEncoding(b3.B3SingleHeader)).Fields(), - b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader)).Fields(), - ), - MaxAge: 7200, // 2 hours in seconds - }) - return c.Handler(hdl) -} - -func setupOtel(ctx context.Context, ll *slog.Logger) (done func(context.Context) error, _ error) { - var toClose []func(context.Context) error - done = func(context.Context) error { - var lastErr error - for _, closer := range toClose { - if err := closer(ctx); err != nil { - lastErr = err - } - } - return lastErr - } - - // trace and monitor yourself with... yourself in dev mode - res, err := resource.Merge(resource.Default(), resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceName("humanlog.localhost"), - semconv.ServiceVersion(semverVersion.String()), - )) - if err != nil { - return done, fmt.Errorf("merging otel resource: %v", err) - } - - metricExp, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithInsecure()) - if err != nil { - return done, fmt.Errorf("creating otel metrics exporter: %v", err) - } - meterProvider := sdkmetric.NewMeterProvider( - sdkmetric.WithResource(res), - sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExp)), - ) - - toClose = append(toClose, func(ctx context.Context) error { - ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) - defer cancel() - if err := meterProvider.Shutdown(ctx); err != nil { - ll.DebugContext(ctx, "shutting down otel metrics provider", slog.Any("err", err)) - } - return nil - }) - traceClient := otlptracegrpc.NewClient(otlptracegrpc.WithInsecure()) - traceExp, err := otlptrace.New(ctx, traceClient) - if err != nil { - return done, fmt.Errorf("creating otel trace exporter: %v", err) - } - - traceProvider := trace.NewTracerProvider( - trace.WithBatcher(traceExp), - trace.WithResource(res), - ) - toClose = append(toClose, func(ctx context.Context) error { - ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) - defer cancel() - if err := traceProvider.Shutdown(ctx); err != nil { - ll.DebugContext(ctx, "shutting down otel traces provider", slog.Any("err", err)) - } - return nil - }) - - otel.SetTracerProvider(traceProvider) - otel.SetMeterProvider(meterProvider) - otel.SetTextMapPropagator( - propagation.NewCompositeTextMapPropagator( - propagation.TraceContext{}, - propagation.Baggage{}, - b3.New(), - ot.OT{}, - ), - ) - - return done, nil -} - -func defaultLogDir(cfg *config.Config, st *state.State) (string, error) { - logdir := cfg.GetRuntime().GetExperimentalFeatures().GetServeLocalhost().GetLogDir() - if logdir == "" { - stateDir, err := state.GetDefaultStateDirpath() - if err != nil { - return "", fmt.Errorf("looking up default state dir: %v", err) - } - logdir = filepath.Join(stateDir, "logs") - } - return homedir.Expand(logdir) -} diff --git a/cmd/humanlog/service_darwin.go b/cmd/humanlog/service_darwin.go deleted file mode 100644 index a5dc6937..00000000 --- a/cmd/humanlog/service_darwin.go +++ /dev/null @@ -1,183 +0,0 @@ -//go:build darwin - -package main - -import ( - "context" - "errors" - "fmt" - "os" - "os/user" - "path/filepath" - "text/template" - - "golang.org/x/sys/execabs" -) - -func (hdl *serviceHandler) Stop(ctx context.Context) error { - confPath, err := hdl.getServiceFilePath() - if err != nil { - return err - } - cmd := execabs.CommandContext(ctx, "launchctl", "unload", confPath) - return cmd.Run() -} - -func (hdl *serviceHandler) Start(ctx context.Context) error { - confPath, err := hdl.getServiceFilePath() - if err != nil { - return err - } - cmd := execabs.CommandContext(ctx, "launchctl", "load", confPath) - return cmd.Run() -} - -func (hdl *serviceHandler) Uninstall() error { - confPath, err := hdl.getServiceFilePath() - if err != nil { - return err - } - if err := os.Remove(confPath); !errors.Is(err, os.ErrNotExist) { - return err - } - - return nil -} - -func (hdl *serviceHandler) Install() error { - confPath, err := hdl.getServiceFilePath() - if err != nil { - return err - } - // Ensure that ~/Library/LaunchAgents exists. - err = os.MkdirAll(filepath.Dir(confPath), 0700) - if err != nil { - return fmt.Errorf("ensuring service directory exists: %v", err) - } - f, err := os.Create(confPath) - if err != nil { - return fmt.Errorf("creating service file: %v", err) - } - defer f.Close() - - path, err := os.Executable() - if err != nil { - return fmt.Errorf("looking up own executable path: %v", err) - } - - logdir, err := defaultLogDir(hdl.config, hdl.state) - if err != nil { - return fmt.Errorf("looking up log dir: %v", err) - } - if err := os.MkdirAll(logdir, 0700); err != nil { - return fmt.Errorf("ensuring log dir exists: %v", err) - } - - var to = &struct { - Name string - Path string - Arguments []string - EnvVars map[string]string - UserName string - - KeepAlive, RunAtLoad bool - SessionCreate bool - StandardOutPath string - StandardErrorPath string - }{ - Name: hdl.svcCfg.Name, - Path: path, - Arguments: hdl.svcCfg.Arguments, - EnvVars: nil, - UserName: hdl.svcCfg.UserName, - KeepAlive: true, - RunAtLoad: true, - SessionCreate: true, - StandardOutPath: filepath.Join(logdir, "log.out"), - StandardErrorPath: filepath.Join(logdir, "log.err"), - } - return hdl.template().Execute(f, to) -} - -func (hdl *serviceHandler) getHomeDir() (string, error) { - u, err := user.Current() - if err == nil { - return u.HomeDir, nil - } - - // alternate methods - homeDir := os.Getenv("HOME") // *nix - if homeDir == "" { - return "", errors.New("User home directory not found.") - } - return homeDir, nil -} - -func (hdl *serviceHandler) getServiceFilePath() (string, error) { - name := hdl.svcCfg.Name - homeDir, err := hdl.getHomeDir() - if err != nil { - return "", err - } - return homeDir + "/Library/LaunchAgents/" + name + ".plist", nil -} - -func (hdl *serviceHandler) template() *template.Template { - functions := template.FuncMap{ - "bool": func(v bool) string { - if v { - return "true" - } - return "false" - }, - } - return template.Must(template.New("").Funcs(functions).Parse(launchdConfig)) -} - -var launchdConfig = ` - - - - Disabled - - {{- if .EnvVars}} - EnvironmentVariables - - {{- range $k, $v := .EnvVars}} - {{html $k}} - {{html $v}} - {{- end}} - - {{- end}} - KeepAlive - <{{bool .KeepAlive}}/> - Label - {{html .Name}} - ProgramArguments - - {{html .Path}} - {{- if .Arguments}} - {{- range .Arguments}} - {{html .}} - {{- end}} - {{- end}} - - RunAtLoad - <{{bool .RunAtLoad}}/> - SessionCreate - <{{bool .SessionCreate}}/> - {{- if .StandardErrorPath}} - StandardErrorPath - {{html .StandardErrorPath}} - {{- end}} - {{- if .StandardOutPath}} - StandardOutPath - {{html .StandardOutPath}} - {{- end}} - {{- if .UserName}} - UserName - {{html .UserName}} - {{- end}} - - -` diff --git a/cmd/humanlog/service_other.go b/cmd/humanlog/service_other.go deleted file mode 100644 index 326ed032..00000000 --- a/cmd/humanlog/service_other.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !darwin - -package main - -import ( - "context" - "fmt" -) - -func (hdl *serviceHandler) Stop(ctx context.Context) error { return fmt.Errorf("TODO") } -func (hdl *serviceHandler) Start(ctx context.Context) error { return fmt.Errorf("TODO") } -func (hdl *serviceHandler) Uninstall() error { return fmt.Errorf("TODO") } -func (hdl *serviceHandler) Install() error { return fmt.Errorf("TODO") } diff --git a/cmd/humanlog/state.go b/cmd/humanlog/state.go deleted file mode 100644 index 2ef9f7dd..00000000 --- a/cmd/humanlog/state.go +++ /dev/null @@ -1,88 +0,0 @@ -package main - -import ( - "context" - "log/slog" - "net/http" - "time" - - "connectrpc.com/connect" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/urfave/cli" -) - -const ( - stateCmdName = "state" -) - -func stateCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(cctx *cli.Context) []connect.ClientOption, -) cli.Command { - - return cli.Command{ - Name: stateCmdName, - Hidden: hideUnreleasedFeatures == "true", - Usage: "Manipulate humanlog's state.", - Subcommands: []cli.Command{ - { - Name: "hack", - Subcommands: []cli.Command{ - { - Name: "ensure-exists", - Action: func(cctx *cli.Context) error { - state := getState(cctx) - loginfo("ensuring state file exists") - return state.WriteBack() - }, - }, - { - Name: "record-last-prompted-to-enable-localhost-now", - Action: func(cctx *cli.Context) error { - state := getState(cctx) - state.LastPromptedToEnableLocalhostAt = ptr(time.Now()) - loginfo("recording LastPromptedToEnableLocalhostAt=%q", state.LastPromptedToEnableLocalhostAt.String()) - return state.WriteBack() - }, - }, - { - Name: "record-last-prompted-to-enable-localhost-lastyear", - Action: func(cctx *cli.Context) error { - state := getState(cctx) - state.LastPromptedToEnableLocalhostAt = ptr(time.Now().AddDate(-1, 0, 0)) - loginfo("recording LastPromptedToEnableLocalhostAt=%q", state.LastPromptedToEnableLocalhostAt.String()) - return state.WriteBack() - }, - }, - { - Name: "record-last-prompted-to-signup-now", - Action: func(cctx *cli.Context) error { - state := getState(cctx) - state.LastPromptedToSignupAt = ptr(time.Now()) - loginfo("recording LastPromptedToSignupAt=%q", state.LastPromptedToSignupAt.String()) - return state.WriteBack() - }, - }, - { - Name: "record-last-prompted-to-signup-lastyear", - Action: func(cctx *cli.Context) error { - state := getState(cctx) - state.LastPromptedToSignupAt = ptr(time.Now().AddDate(-1, 0, 0)) - loginfo("recording LastPromptedToSignupAt=%q", state.LastPromptedToSignupAt.String()) - return state.WriteBack() - }, - }, - }, - }, - }, - } -} diff --git a/cmd/humanlog/stream.go b/cmd/humanlog/stream.go deleted file mode 100644 index b47f8cd0..00000000 --- a/cmd/humanlog/stream.go +++ /dev/null @@ -1,244 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log" - "log/slog" - "net/http" - "net/url" - "os" - "strings" - "time" - - "connectrpc.com/connect" - queryv1 "github.com/minitape/api/go/svc/query/v1" - "github.com/minitape/api/go/svc/query/v1/queryv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/auth" - "github.com/humanlogio/humanlog/pkg/sink/stdiosink" - "github.com/pkg/browser" - "github.com/urfave/cli" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/types/known/durationpb" -) - -const ( - streamCmdName = "stream" -) - -func streamCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getBaseSiteURL func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - return cli.Command{ - Name: streamCmdName, - Usage: "Follow a stream that matches a query", - - Subcommands: []cli.Command{ - { - Hidden: hideUnreleasedFeatures == "true", - Name: "api", - Subcommands: []cli.Command{ - streamApiRunCmd( - getCtx, - getLogger, - getCfg, - getState, - getTokenSource, - getAPIUrl, - getHTTPClient, - getConnectOpts, - ), - }, - }, - }, - - Action: func(cctx *cli.Context) error { - // ctx := getCtx(cctx) - q := strings.Join(cctx.Args(), " ") - log.Printf("query=%q", q) - baseSiteURL := getBaseSiteURL(cctx) - - baseSiteU, err := url.Parse(baseSiteURL) - if err != nil { - return fmt.Errorf("parsing base url: %v", err) - } - queryu := baseSiteU.JoinPath("/localhost/stream") - v := queryu.Query() - v.Set("query", q) - queryu.RawQuery = v.Encode() - return browser.OpenURL(queryu.String()) - }, - } -} - -func streamApiRunCmd( - getCtx func(cctx *cli.Context) context.Context, - getLogger func(cctx *cli.Context) *slog.Logger, - getCfg func(cctx *cli.Context) *config.Config, - getState func(cctx *cli.Context) *state.State, - getTokenSource func(cctx *cli.Context) *auth.UserRefreshableTokenSource, - getAPIUrl func(cctx *cli.Context) string, - getHTTPClient func(cctx *cli.Context, apiURL string) *http.Client, - getConnectOpts func(*cli.Context) []connect.ClientOption, -) cli.Command { - localhost := cli.BoolFlag{Name: "localhost"} - format := cli.StringFlag{Name: "format", Value: "humanlog"} - - return cli.Command{ - Name: "run", - Flags: []cli.Flag{localhost, format}, - Action: func(cctx *cli.Context) error { - ctx := getCtx(cctx) - cfg := getCfg(cctx) - state := getState(cctx) - var queryClient queryv1connect.QueryServiceClient - if !cctx.Bool(localhost.Name) { - ll := getLogger(cctx) - tokenSource := getTokenSource(cctx) - apiURL := getAPIUrl(cctx) - httpClient := getHTTPClient(cctx, apiURL) - clOpts := getConnectOpts(cctx) - _, err := ensureLoggedIn(ctx, cctx, state, tokenSource, apiURL, httpClient, clOpts) - if err != nil { - return err - } - clOpts = append(clOpts, connect.WithInterceptors( - auth.Interceptors(ll, tokenSource)..., - )) - queryClient = queryv1connect.NewQueryServiceClient(httpClient, apiURL, clOpts...) - } else { - cfg := getCfg(cctx) - expcfg := cfg.GetRuntime().GetExperimentalFeatures() - if expcfg == nil || expcfg.ServeLocalhost == nil { - return fmt.Errorf("localhost feature is not enabled or not configured, can't dial localhost") - } - apiURL := fmt.Sprintf("http://localhost:%d", expcfg.ServeLocalhost.Port) - httpClient := getHTTPClient(cctx, apiURL) - queryClient = queryv1connect.NewQueryServiceClient(httpClient, apiURL) - } - var ( - query = strings.Join(cctx.Args(), " ") - ) - - sinkOpts, errs := stdiosink.StdioOptsFrom(cfg.GetFormatter()) - if len(errs) > 0 { - for _, err := range errs { - logerror("config error: %v", err) - } - } - - loginfo("query=%s", query) - - var environmentID int64 - if state.CurrentEnvironmentID != nil { - environmentID = *state.CurrentEnvironmentID - } - - parseRes, err := queryClient.Parse(ctx, connect.NewRequest(&queryv1.ParseRequest{Query: query})) - if err != nil { - return fmt.Errorf("parsing query: %v", err) - } - lq := parseRes.Msg.Query - - var printer func(*typesv1.Data) error - switch cctx.String(format.Name) { - case "json": - - printer = func(data *typesv1.Data) error { - b, err := protojson.Marshal(data) - if err != nil { - return fmt.Errorf("marshaling: %v", err) - } - _, err = os.Stdout.Write(b) - _, _ = os.Stdout.WriteString("\n") - return err - } - case "humanlog": - - sink, err := stdiosink.NewStdio(os.Stdout, sinkOpts) - if err != nil { - return fmt.Errorf("preparing stdio printer: %v", err) - } - printLogEvents := func(logs []*typesv1.Log) error { - for _, ev := range logs { - if err := sink.Receive(ctx, ev); err != nil { - return fmt.Errorf("printing log: %v", err) - } - } - return nil - } - printSpans := func(spans []*typesv1.Span) error { - for _, sp := range spans { - if err := sink.ReceiveSpan(ctx, sp); err != nil { - return fmt.Errorf("printing span: %v", err) - } - } - return nil - } - printTable := func(table *typesv1.Table) error { - if err := sink.ReceiveTable(ctx, table); err != nil { - return fmt.Errorf("printing table: %v", err) - } - return nil - } - printer = func(data *typesv1.Data) error { - switch shape := data.Shape.(type) { - - case *typesv1.Data_Logs: - return printLogEvents(shape.Logs.Logs) - case *typesv1.Data_Spans: - return printSpans(shape.Spans.Spans) - case *typesv1.Data_FreeForm: - return printTable(shape.FreeForm) - default: - return fmt.Errorf("todo: handle data shape %T", shape) - } - } - default: - return fmt.Errorf("unsupported format: %q", cctx.String(format.Name)) - } - - var ( - req = &queryv1.StreamRequest{ - EnvironmentId: environmentID, - Query: lq, - MaxBatchingFor: durationpb.New(100 * time.Millisecond), - } - ) - - loginfo("starting to stream query=%q", query) - streamCtx, streamCancel := context.WithCancel(ctx) - res, err := queryClient.Stream(streamCtx, connect.NewRequest(req)) - if err != nil { - return fmt.Errorf("calling Query: %v", err) - } - defer func() { - streamCancel() - res.Close() - }() - - loginfo("waiting for data...") - for res.Receive() { - data := res.Msg().GetData() - if err := printer(data); err != nil { - return fmt.Errorf("printing data: %v", err) - } - } - if err := res.Err(); err != nil { - return fmt.Errorf("receiving streaming results: %v", err) - } - return nil - }, - } -} diff --git a/cmd/humanlog/systray_darwin.go b/cmd/humanlog/systray_darwin.go deleted file mode 100644 index 430e25c5..00000000 --- a/cmd/humanlog/systray_darwin.go +++ /dev/null @@ -1,477 +0,0 @@ -//go:build darwin - -package main - -import ( - "context" - "fmt" - "log/slog" - "net/url" - "sync" - - "github.com/blang/semver" - "github.com/gen2brain/beeep" - "github.com/getlantern/systray" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/logqleval" - "github.com/pkg/browser" -) - -func runSystray(ctx context.Context, ll *slog.Logger, svcHandler *serviceHandler, version *typesv1.Version, baseSiteURL string) error { - onReady := func() { - sysctrl, err := newSystrayController(ctx, ll, svcHandler, version, baseSiteURL) - if err != nil { - ll.ErrorContext(ctx, "running humanlog systray controller", slog.Any("err", err)) - } else { - ll.InfoContext(ctx, "humanlog systray controller started") - svcHandler.registerClient(sysctrl) - } - } - onExit := func() { - ll.WarnContext(ctx, "exiting...") - } - ll.InfoContext(ctx, "enabling systray menu") - go func() { - <-ctx.Done() - ll.Warn("signal received, sending quit to systray...") - systray.Quit() - }() - systray.Run(onReady, onExit) // systray must run on `main` goroutine - return nil -} - -var _ systrayClient = (*systrayController)(nil) - -type systrayController struct { - ll *slog.Logger - - client serviceClient - baseSiteURL *url.URL - - mu sync.Mutex - - model *systrayModel - - mTitle *systray.MenuItem - mQuery *systray.MenuItem - mStream *systray.MenuItem - mUserMenuItem *systray.MenuItem - mUserMenuItem_Sub_Settings *systray.MenuItem - mUserMenuItem_Sub_Login *systray.MenuItem - mUserMenuItem_Sub_Logout *systray.MenuItem - - mSettings *systray.MenuItem - mUpdate *systray.MenuItem - mRestart *systray.MenuItem -} - -type systrayModel struct { - currentVersion *typesv1.Version - currentVersionSV semver.Version - nextVersion *typesv1.Version - nextVersionSV semver.Version - hasUpdate bool - lastNotifiedVersion semver.Version - requestedUpdateCheck bool - - user *typesv1.User - userOrg *typesv1.Organization - curOrg *typesv1.Organization -} - -func newSystrayController(ctx context.Context, ll *slog.Logger, client serviceClient, currentVersion *typesv1.Version, baseSiteURL string) (*systrayController, error) { - - baseSiteU, err := url.Parse(baseSiteURL) - if err != nil { - return nil, fmt.Errorf("parsing base site URL: %v", err) - } - - mdl := &systrayModel{currentVersion: currentVersion} - - currentSV, err := mdl.currentVersion.AsSemver() - if err != nil { - return nil, fmt.Errorf("parsing current version: %v", err) - } - mdl.lastNotifiedVersion = currentSV - - ll.InfoContext(ctx, "creating systray menu") - systray.SetTitle("log") - // systray.SetIcon(embeds.HumanlogIcon512x512) - // systray.SetTemplateIcon(embeds.HumanlogIconset, embeds.HumanlogIcon512x512) - systray.SetTooltip("logs for humans to eat. miam miam") - mTitle := systray.AddMenuItem( - fmt.Sprintf("humanlog (%s)", currentSV.String()), - "logs for humans to eat. miam miam", - ) - systray.AddSeparator() - mUserMenuItem := systray.AddMenuItem("Account", "log into humanlog.io") - mUserMenuItem_Sub_Settings := mUserMenuItem.AddSubMenuItem("Settings...", "edit your account settings") - mUserMenuItem_Sub_Login := mUserMenuItem.AddSubMenuItem("Login", "log in with humanlog") - mUserMenuItem_Sub_Logout := mUserMenuItem.AddSubMenuItem("Logout", "log out of humanlog") - - mQuery := systray.AddMenuItem("Query", "Query your logs") - mStream := systray.AddMenuItem("Stream", "Watch a stream of your logs") - - systray.AddSeparator() - - mSettings := systray.AddMenuItem("Settings...", "Configure humanlog on your machine") - mUpdate := systray.AddMenuItem( - fmt.Sprintf("%s (latest, click to check)", currentSV.String()), - fmt.Sprintf("Currently running humanlog version %s", currentSV.String()), - ) - mRestart := systray.AddMenuItem( - "Restart", - "Cause humanlog's service to restart, for whatever reason", - ) - - mQuit := systray.AddMenuItem("Quit", "Quit the whole app") - _ = onClick(ctx, mQuit, func(ctx context.Context) { - ll.InfoContext(ctx, "quitting the app") - systray.Quit() - }) - - ll.InfoContext(ctx, "registering systray clickers and stuff") - ctrl := &systrayController{ - ll: ll, - client: client, - baseSiteURL: baseSiteU, - model: mdl, - mTitle: mTitle, - mUserMenuItem: mUserMenuItem, - mUserMenuItem_Sub_Settings: mUserMenuItem_Sub_Settings, - mUserMenuItem_Sub_Login: mUserMenuItem_Sub_Login, - mUserMenuItem_Sub_Logout: mUserMenuItem_Sub_Logout, - mQuery: mQuery, - mStream: mStream, - mSettings: mSettings, - mUpdate: mUpdate, - mRestart: mRestart, - } - ctrl.registerClickUserSettings(ctx, mUserMenuItem_Sub_Settings) - ctrl.registerClickUserLogin(ctx, mUserMenuItem_Sub_Login) - ctrl.registerClickUserLogout(ctx, mUserMenuItem_Sub_Logout) - ctrl.registerClickQuery(ctx, mQuery) - ctrl.registerClickStream(ctx, mStream) - ctrl.registerClickUpdate(ctx, mUpdate) - ctrl.registryClickRestart(ctx, mRestart) - ctrl.registerClickLocalhostSettings(ctx, mSettings) - - return ctrl, nil -} - -func (ctrl *systrayController) NotifyAlert(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error { - ctrl.mu.Lock() - defer ctrl.mu.Unlock() - args := []any{slog.String("name", ar.Spec.Name)} - if o != nil { - for _, kv := range o.Kvs { - v, err := logqleval.ResolveVal(kv.Value, logqleval.MakeFlatGoMap, logqleval.MakeFlatGoSlice) - if err != nil { - panic(err) - } - args = append(args, slog.Any(kv.Key, v)) - } - } - ll := ctrl.ll - switch ar.Status.Status.(type) { - case *typesv1.AlertRuleStatus_Unknown: - ll.InfoContext(ctx, "alert in unknown status", args...) - case *typesv1.AlertRuleStatus_Ok: - ll.InfoContext(ctx, "alert in ok status", args...) - beeep.Alert("✅ humanlog: alert resolved", - fmt.Sprintf("alert resolved: %q", ar.Spec.Name), - "", - ) - case *typesv1.AlertRuleStatus_Pending: - ll.WarnContext(ctx, "alert in pending status", args...) - beeep.Alert("⚠️ humanlog: an alert is pending", - fmt.Sprintf("alert pending: %q", ar.Spec.Name), - "", - ) - case *typesv1.AlertRuleStatus_Firing: - ll.ErrorContext(ctx, "alert is firing!", args...) - beeep.Alert("🚨 humanlog: an alert is firing", - fmt.Sprintf("alert firing: %q", ar.Spec.Name), - "", - ) - } - return nil -} - -func (ctrl *systrayController) NotifyError(ctx context.Context, err error) error { - ctrl.mu.Lock() - defer ctrl.mu.Unlock() - if err := beeep.Alert("humanlog has problems!", err.Error(), ""); err != nil { - return err - } - return nil -} - -func (ctrl *systrayController) NotifyUnauthenticated(ctx context.Context) error { - ctrl.mu.Lock() - defer ctrl.mu.Unlock() - wasSignedIn := ctrl.model.user != nil - ctrl.model.user = nil - ctrl.model.userOrg = nil - ctrl.model.curOrg = nil - - if wasSignedIn { - err := beeep.Notify( - "humanlog: signed out", - "successfully signed out of humanlog", - "", - ) - if err != nil { - ctrl.ll.ErrorContext(ctx, "can't notify desktop", slog.Any("err", err)) - } - } - return ctrl.renderLoginMenuItem(ctx) -} - -func (ctrl *systrayController) NotifyAuthenticated(ctx context.Context, user *typesv1.User, defaultOrg, currentOrg *typesv1.Organization) error { - ctrl.mu.Lock() - defer ctrl.mu.Unlock() - wasSignedOff := ctrl.model.user == nil - ctrl.model.user = user - ctrl.model.userOrg = defaultOrg - ctrl.model.curOrg = currentOrg - if wasSignedOff { - err := beeep.Notify( - "humanlog: signed in", - fmt.Sprintf("humanlog is signed in as %s (%s)", user.Name, user.Email), - "", - ) - if err != nil { - ctrl.ll.ErrorContext(ctx, "can't notify desktop", slog.Any("err", err)) - } - } - return ctrl.renderLoginMenuItem(ctx) -} - -func (ctrl *systrayController) NotifyUpdateAvailable(ctx context.Context, currentV, nextV *typesv1.Version) error { - ctrl.mu.Lock() - defer ctrl.mu.Unlock() - ctrl.ll.InfoContext(ctx, "notified of an update being available") - currentSV, err := currentV.AsSemver() - if err != nil { - return fmt.Errorf("converting current version into semver: %v", err) - } - ctrl.model.currentVersion = currentV - ctrl.model.currentVersionSV = currentSV - nextSV, err := nextV.AsSemver() - if err != nil { - return fmt.Errorf("converting next version into semver: %v", err) - } - ctrl.model.nextVersion = nextV - ctrl.model.nextVersionSV = nextSV - hasUpdate := ctrl.model.currentVersionSV.LT(ctrl.model.nextVersionSV) - ctrl.model.hasUpdate = hasUpdate - - if !ctrl.model.lastNotifiedVersion.EQ(nextSV) { - err = beeep.Notify( - "humanlog update available", - fmt.Sprintf("version %s is available, you can update now", nextSV.String()), - "", - ) - if err != nil { - ctrl.ll.ErrorContext(ctx, "can't notify desktop", slog.Any("err", err)) - } else { - ctrl.model.lastNotifiedVersion = nextSV - } - } - if ctrl.model.requestedUpdateCheck { - - if hasUpdate { - err = beeep.Notify( - "humanlog update available", - fmt.Sprintf("version %s is available, you can update now", nextSV.String()), - "", - ) - if err != nil { - ctrl.ll.ErrorContext(ctx, "can't notify desktop", slog.Any("err", err)) - } - } else { - err = beeep.Notify( - "humanlog is up to date", - fmt.Sprintf("you're running the latest version (%s)", currentSV.String()), - "", - ) - if err != nil { - ctrl.ll.ErrorContext(ctx, "can't notify desktop", slog.Any("err", err)) - } - } - - ctrl.model.requestedUpdateCheck = false - } - - return ctrl.renderUpdateMenuItem(ctx) -} - -func (ctrl *systrayController) renderLoginMenuItem(ctx context.Context) error { - mdl := ctrl.model - mi := ctrl.mUserMenuItem - if mdl.user != nil { - ctrl.ll.InfoContext(ctx, "rendering as authenticated") - mi.SetTitle(fmt.Sprintf("%s (%s)", mdl.user.Name, mdl.user.Email)) - ctrl.mUserMenuItem_Sub_Settings.Show() - ctrl.mUserMenuItem_Sub_Login.Hide() - ctrl.mUserMenuItem_Sub_Logout.Show() - } else { - ctrl.ll.InfoContext(ctx, "rendering as unauthenticated") - mi.SetTitle("Click to login") - ctrl.mUserMenuItem_Sub_Settings.Hide() - ctrl.mUserMenuItem_Sub_Login.Show() - ctrl.mUserMenuItem_Sub_Logout.Hide() - } - return nil -} - -func (ctrl *systrayController) renderUpdateMenuItem(ctx context.Context) error { - hasUpdate := ctrl.model.hasUpdate - mi := ctrl.mUpdate - if !hasUpdate { - mi.SetTitle("running latest version ✨") - } else { - cfg, err := ctrl.client.CurrentConfig(ctx) - if err != nil { - return err - } - releaseChannel := cfg.GetRuntime().GetExperimentalFeatures().GetReleaseChannel() - if releaseChannel == "" { - releaseChannel = defaultReleaseChannel - } - nextVersion := ctrl.model.nextVersionSV - mi.SetTitle(fmt.Sprintf("Update to %s", nextVersion.String())) - mi.SetTooltip(fmt.Sprintf("Click to update (tracking %q release channel)", releaseChannel)) - mi.Enable() - } - return nil -} - -func (ctrl *systrayController) registerClickUserSettings(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - userSettingsPath := ctrl.baseSiteURL.JoinPath("/settings/users") - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked user settings, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked user settings") - browser.OpenURL(userSettingsPath.String()) - }) -} - -func (ctrl *systrayController) registerClickUserLogin(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - queryPath := ctrl.baseSiteURL.JoinPath("/localhost") - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked user login, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked user login") - - if err := ctrl.client.DoLogin(ctx, queryPath.String()); err != nil { - ctrl.NotifyError(ctx, err) - } - }) -} - -func (ctrl *systrayController) registerClickUserLogout(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - homepage := ctrl.baseSiteURL - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked user logout, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked user logout") - if err := ctrl.client.DoLogout(ctx, homepage.String()); err != nil { - ctrl.NotifyError(ctx, err) - } - }) -} - -func (ctrl *systrayController) registerClickUpdate(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked update, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked update") - if ctrl.model.hasUpdate { - if err := ctrl.client.DoUpdate(ctx); err != nil { - ctrl.NotifyError(ctx, err) - } - } else { - ctrl.ll.InfoContext(ctx, "starting a manually requested update check") - ctrl.mu.Lock() - ctrl.model.requestedUpdateCheck = true - ctrl.mu.Unlock() - if err := ctrl.client.CheckUpdate(ctx); err != nil { - ctrl.NotifyError(ctx, err) - } - } - }) -} - -func (ctrl *systrayController) registryClickRestart(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked restart, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked restart") - if err := ctrl.client.DoRestart(ctx); err != nil { - ctrl.NotifyError(ctx, err) - } - }) -} - -func (ctrl *systrayController) registerClickQuery(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - queryPath := ctrl.baseSiteURL.JoinPath("/localhost/query") - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked query, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked query") - browser.OpenURL(queryPath.String()) - }) -} - -func (ctrl *systrayController) registerClickStream(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - streamPath := ctrl.baseSiteURL.JoinPath("/localhost/stream") - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked stream, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked stream") - browser.OpenURL(streamPath.String()) - }) -} - -func (ctrl *systrayController) registerClickLocalhostSettings(ctx context.Context, mi *systray.MenuItem) context.CancelFunc { - settingsPath := ctrl.baseSiteURL.JoinPath("/settings/localhost") - return onClick(ctx, mi, func(ctx context.Context) { - if mi.Disabled() { - ctrl.ll.DebugContext(ctx, "clicked settings, but button disabled") - return - } - ctrl.ll.DebugContext(ctx, "clicked settings") - browser.OpenURL(settingsPath.String()) - }) -} - -func onClick(ctx context.Context, mi *systray.MenuItem, do func(ctx context.Context)) context.CancelFunc { - ctx, cancel := context.WithCancel(ctx) - go func() { - for { - select { - case <-ctx.Done(): - return - case <-mi.ClickedCh: - do(ctx) - } - } - }() - return cancel -} diff --git a/cmd/humanlog/systray_other.go b/cmd/humanlog/systray_other.go deleted file mode 100644 index 1b2c0c10..00000000 --- a/cmd/humanlog/systray_other.go +++ /dev/null @@ -1,44 +0,0 @@ -//go:build !darwin - -package main - -import ( - "context" - "log/slog" - - typesv1 "github.com/minitape/api/go/types/v1" -) - -func runSystray(ctx context.Context, ll *slog.Logger, svcHandler *serviceHandler, version *typesv1.Version, baseSiteURL string) error { - <-ctx.Done() - return nil -} - -var _ systrayClient = (*systrayController)(nil) - -type systrayController struct{ ll *slog.Logger } - -func newSystrayController(ctx context.Context, ll *slog.Logger, client serviceClient, currentVersion *typesv1.Version, baseSiteURL string) (*systrayController, error) { - return &systrayController{ll: ll}, nil -} - -func (ctrl *systrayController) NotifyAlert(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error { - ctrl.ll.WarnContext(ctx, "systray: not implemented on this platform: NotifyError") - return nil -} -func (ctrl *systrayController) NotifyError(ctx context.Context, err error) error { - ctrl.ll.WarnContext(ctx, "systray: not implemented on this platform: NotifyError") - return nil -} -func (ctrl *systrayController) NotifyUnauthenticated(ctx context.Context) error { - ctrl.ll.WarnContext(ctx, "systray: not implemented on this platform: NotifyUnauthenticated") - return nil -} -func (ctrl *systrayController) NotifyAuthenticated(ctx context.Context, user *typesv1.User, defaultOrg, currentOrg *typesv1.Organization) error { - ctrl.ll.WarnContext(ctx, "systray: not implemented on this platform: NotifyAuthenticated") - return nil -} -func (ctrl *systrayController) NotifyUpdateAvailable(ctx context.Context, oldV, newV *typesv1.Version) error { - ctrl.ll.WarnContext(ctx, "systray: not implemented on this platform: NotifyUpdateAvailable") - return nil -} diff --git a/docs/alert-architecture-summary.md b/docs/alert-architecture-summary.md new file mode 100644 index 00000000..fecc5d38 --- /dev/null +++ b/docs/alert-architecture-summary.md @@ -0,0 +1,424 @@ +# Alert Architecture - Complete Analysis + +## Overview + +The alert system follows a **separation of concerns** pattern where: +- **Spec** (configuration) is stored in filesystem YAML files +- **Status** (runtime state) is stored separately in a state storage layer +- These are **merged at read time** when serving API responses + +## Component Architecture + +### 1. AlertScheduler (`internal/localserver/alert_scheduler.go`) + +**Responsibility**: Orchestrates alert evaluation across all projects + +**Key behaviors**: +- Reconciles every N seconds (discovers new/changed/deleted alert groups) +- Spawns one goroutine per alert group +- Each goroutine evaluates rules at the group's configured interval +- Uses singleflight for debounced reconciliation + +**Dependencies**: +```go +type AlertScheduler struct { + state projectService // Query projects/alert groups + storage localstorage.Storage // Persist alert status + timeNow func() time.Time // Injected for testing + getReconcileTrigger func() <-chan time.Time // Injected for testing + getEvalTrigger func(...) <-chan time.Time // Injected for testing + onStateTransition localalert.OnStateTransition // Fire alerts +} + +type projectService interface { + ListProject(...) + GetProject(...) + ListAlertGroup(...) + GetAlertGroup(...) +} +``` + +**Reconciliation flow**: +1. List all projects +2. For each project, list all alert groups +3. Compare discovered groups to running evaluators +4. Stop evaluators for deleted/changed groups +5. Start evaluators for new groups + +### 2. Evaluator (`internal/localalert/alert.go`) + +**Responsibility**: Evaluates rules within an alert group + +**Evaluation flow** (for each rule): +```go +func (ev *Evaluator) EvaluateRules(...) error { + for each rule: + // 1. Get current status from storage + status := ev.db.AlertGetOrCreate(ctx, projectName, groupName, ruleID, ...) + + // 2. Record evaluation timestamp + status.LastEvaluatedAt = timestamppb.New(ev.timeNow()) + + // 3. Evaluate the alert condition + err := check(ctx, rule, ev.db, ev.timeNow(), onStateTransition, status) + + // 4. Persist updated status + ev.db.AlertUpdateState(ctx, projectName, groupName, ruleID, status) + + // 5. Clean up deleted rules + ev.db.AlertDeleteStateNotInList(ctx, projectName, groupName, keeplist) +} +``` + +### 3. Storage Layer (`pkg/localstorage/localstorage.go`) + +**Alertable interface**: +```go +type Alertable interface { + // Get or lazily create alert status + AlertGetOrCreate( + ctx context.Context, + projectName, groupName, ruleID string, + create func() *typesv1.AlertRuleStatus, + ) (*typesv1.AlertRuleStatus, error) + + // Update alert status (called after evaluation) + AlertUpdateState( + ctx context.Context, + projectName, groupName, ruleID string, + status *typesv1.AlertRuleStatus, + ) error + + // Delete orphaned alert status (cleanup) + AlertDeleteStateNotInList( + ctx context.Context, + projectName, groupName string, + keeplist []string, + ) error +} +``` + +**Implementations**: +- `DuckDB`: Persists to database +- `mockStorage` (tests): In-memory map + +### 4. Project/AlertGroup Discovery (`internal/localproject/`) + +**watch.go** (`localstate.DB` implementation): +```go +func (wt *watch) GetAlertGroup(ctx, req) { + // 1. Get alert group from storage (filesystem) + storage.getAlertGroup(ctx, wt.alertState, projectName, ptr, groupName, ...) + + // In the callback from storage: + // 2. Status is already hydrated by storage layer + out = alertGroup // Contains spec + status +} +``` + +**fs.go** (`localGitStorage` - filesystem storage): +```go +func (store *localGitStorage) getAlertGroup(..., alertState, ...) { + // 1. Parse alert group YAML from filesystem (spec only) + alertGroups := parseProjectAlertGroups(ctx, store.fs, ...) + + // 2. Hydrate status for each rule + ag.Status.Rules = make(...) + for each rule: + status := alertState.AlertGetOrCreate(ctx, projectName, groupName, ruleID, ...) + ag.Status.Rules = append(..., status) + + // 3. Return complete alert group (spec + status) + return onAlertGroup(ag) +} +``` + +## Data Flow Diagram + +``` +┌─────────────────────────────────────────────────────────┐ +│ AlertScheduler │ +│ ┌────────────┐ ┌────────────────┐ │ +│ │ Reconcile │──────>│ Per-Group │ │ +│ │ Loop │ │ Evaluators │ │ +│ │ (60s) │ │ (interval) │ │ +│ └────────────┘ └────────┬───────┘ │ +└─────────────────────────────────┼────────────────────────┘ + │ + ┌─────────▼──────────┐ + │ Evaluator │ + │ EvaluateRules() │ + └─┬──────────────┬───┘ + │ │ + ┌─────────────────▼─┐ ┌──▼──────────────────┐ + │ projectService │ │ localstorage │ + │ (localstate.DB) │ │ (Alertable) │ + │ │ │ │ + │ GetAlertGroup() │ │ AlertGetOrCreate() │ + │ │ │ │ AlertUpdateState() │ + │ │ │ └──────────────────────┘ + │ ▼ │ + │ localGitStorage │ + │ │ │ + │ ▼ │ + │ Filesystem YAML │ + │ (spec only) │ + │ │ │ + │ ├──────────┐ │ + │ │ ▼ │ + │ │ Hydrate │────> Uses alertState to get status + │ │ Status │ + │ │ │ │ + │ └──────────┘ │ + └───────────────────┘ +``` + +## Key Patterns + +### 1. Spec/Status Separation + +**Why?** +- Spec (configuration) changes infrequently → stored in git +- Status (runtime state) changes every evaluation → stored in database +- Keeps git history clean (no status churn) + +**How?** +- Filesystem YAML contains only spec +- Status fetched from alertState storage +- Merged at read time in storage layer + +### 2. Lazy Status Initialization + +```go +AlertGetOrCreate(ctx, projectName, groupName, ruleID, func() *typesv1.AlertRuleStatus { + return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{}} +}) +``` + +- Status created on first access +- Default state: Unknown +- Avoids need to pre-create status for all rules + +### 3. Status Hydration in Storage Layer + +**Not in watch layer**: +```go +// ❌ Bad: watch.go hydrating status +func (wt *watch) GetAlertGroup(...) { + storage.getAlertGroup(...) // Get spec + for each rule: + status := wt.alertState.AlertGetOrCreate(...) // Hydrate status +} +``` + +**In storage layer**: +```go +// ✅ Good: storage layer hydrates status +func (store *localGitStorage) getAlertGroup(..., alertState, ...) { + ag := parseFromFilesystem() // Get spec + for each rule: + status := alertState.AlertGetOrCreate(...) // Hydrate status + return ag // Complete alert group +} +``` + +**Why?** +- Storage layer knows the data structure +- Keeps hydration logic close to data source +- watch layer just routes requests + +### 4. Constructor Injection for Testing + +**Production**: +```go +scheduler := NewAlertScheduler( + logger, + state, // Real DB + storage, // Real DuckDB + time.Now, + onStateTransition, + 60*time.Second, +) +``` + +**Testing**: +```go +scheduler := newAlertScheduler( + logger, + mockProjectService, // Test mock + mockStorage, // In-memory storage + func() time.Time { return fixedTime }, // Deterministic time + func() <-chan time.Time { return testChan }, // Controlled triggers + func(...) <-chan time.Time { return testChan }, + onStateTransition, +) +``` + +### 5. Callback-Based Storage Interface + +```go +type projectStorage interface { + getAlertGroup( + ctx context.Context, + alertState localstorage.Alertable, + projectName string, + ptr *typesv1.ProjectPointer, + groupName string, + onAlertGroup func(*typesv1.AlertGroup) error, // Callback! + ) error +} +``` + +**Why callbacks?** +- Storage layer controls data loading +- Consumer extracts what they need via callback +- No need to expose internal types +- Follows existing codebase pattern + +## Testing Patterns + +### Test Structure (from `alert_scheduler_test.go`) + +```go +type tick struct { + at time.Duration + reconcile bool + evals []string // "project/group" + addGroups map[string][]*typesv1.AlertGroup + removeGroups map[string][]string + updateGroups map[string][]*typesv1.AlertGroup +} + +tests := []struct { + name string + init schedulerState // Initial state + ticks []tick // State transitions + check func(t *testing.T, events []event) // Verify outcomes +} +``` + +### Event Recording via Hooks + +```go +var events []event + +scheduler := newAlertScheduler( + ..., + withOnReconcileComplete(func() { + recordEvent("reconcile-complete", ...) + }), + withOnEvaluationComplete(func(project, group string) { + recordEvent("eval-complete", project, group, ...) + }), + withOnEvaluatorStarted(func(project, group string) { + recordEvent("evaluator-started", project, group, ...) + }), +) + +// Later: verify events +require.Equal(t, 2, countEvals(events, "proj1", "group1")) +require.True(t, hasEvent(events, "evaluator-stopped", "proj1", "group2")) +``` + +### Mock Storage with Alert State + +```go +type mockStorage struct { + mu sync.Mutex + alerts map[string]map[string]map[string]*typesv1.AlertRuleStatus +} + +func (m *mockStorage) AlertGetOrCreate(...) (*typesv1.AlertRuleStatus, error) { + m.mu.Lock() + defer m.mu.Unlock() + + // Lazy init + if status, ok := m.alerts[projectName][groupName][ruleID]; ok { + return status, nil + } + + status := create() + m.alerts[projectName][groupName][ruleID] = status + return status, nil +} +``` + +## Implications for Dashboard Implementation + +### Pattern to Follow + +Dashboards should **NOT** follow the spec/status separation pattern because: +1. Dashboards don't have runtime status (no evaluation loop) +2. Dashboard metadata (management, codegen markers) is **part of the spec** +3. All dashboard data should be in one place (YAML file) + +### Correct Pattern for Dashboards + +```go +// Dashboard YAML contains EVERYTHING +# managed-by: humanlog +kind: Dashboard +metadata: + name: my-dashboard +spec: + display: + name: My Dashboard + # ... dashboard config + +// No separate status storage needed +``` + +### Discovery Pattern (Similar to Alerts) + +```go +func (store *localGitStorage) getDashboard(...) { + // 1. Read YAML from filesystem + dashboard := parseProjectDashboard(ctx, store.fs, ...) + + // 2. Detect management markers (in the parsing step) + managedBy, _ := extractManagedByMarker(yamlData) + codegenMarkers := detectCodegenMarkers(yamlData) + + // 3. Build complete dashboard proto + dashboard.Spec.Management = &typesv1.DashboardManagement{ + Origin: origin, + CodegenMarkers: codegenMarkers, + } + + // 4. Return via callback (same pattern as alerts) + return onDashboard(dashboard) +} +``` + +### Testing Pattern (Same as Alerts) + +```go +type transition struct { + name string + at time.Duration + operation func(context.Context, *testing.T, localstate.DB) error + expectFile *fileExpectation + expectDashboard *dashboardExpectation +} + +tests := []struct { + name string + initFS fsState + initProject *typesv1.ProjectsConfig_Project + transitions []transition +} +``` + +## Key Takeaways + +1. **Alert Status**: Separate storage layer (DuckDB), hydrated at read time +2. **Dashboard Metadata**: Stored in YAML comments, parsed at read time +3. **Storage Interface**: Callback-based, follows existing pattern +4. **Testing**: Declarative state machines, externalized non-determinism +5. **Constructor Injection**: All dependencies via `newXxx()`, no setters + +This architecture enables: +- Clean git history (no runtime state in YAML) +- Testable components (inject mocks) +- Flexible storage backends (filesystem, git, database) +- GitOps workflows (everything in version control) diff --git a/docs/dashboard-authoring-proposal.md b/docs/dashboard-authoring-proposal.md new file mode 100644 index 00000000..d31dfb6b --- /dev/null +++ b/docs/dashboard-authoring-proposal.md @@ -0,0 +1,1146 @@ +# Dashboard Authoring for Localhost Projects - Detailed Proposal + +## Problem Statement + +Currently, `CreateDashboard` fails for localhost projects with error: +``` +"localhost dashboard are created on the filesystem" +``` + +Users want to: +1. **View** filesystem dashboards locally (already works) +2. **Create** new dashboards via UI that persist to filesystem YAML files +3. **Edit** existing dashboards (both discovered and managed) +4. **Compare** local work to remote before pushing to git +5. **Use GitOps workflow**: create locally → commit → PR → merge to prod + +### Key Constraint +We need to distinguish between: +- **Discovered dashboards**: Found on filesystem, potentially code-generated → should be read-only by default +- **Managed dashboards**: Created/edited via humanlog → should be writable +- **Converted dashboards**: User explicitly made a discovered dashboard editable + +## Design Principles (from Codebase Analysis) + +### Testing Philosophy +1. **Test-first development**: Write declarative tests encoding user behavior before implementation +2. **State machine testing**: Model as transitions with happens-before relationships +3. **Externalized non-determinism**: Inject time, filesystem via constructors +4. **Event-based verification**: Use function hooks to record state transitions +5. **API-only testing**: Test through public `localstate.DB` interface, not internals +6. **Constructor injection**: All dependencies via `newXxx()`, no setters/getters + +### Test Pattern Example (from `alert_scheduler_test.go`) +```go +type transition struct { + name string + at time.Duration + operation func(context.Context, *testing.T, localstate.DB) error + expect *expectation +} + +tests := []struct { + name string + init initialState + transitions []transition + verify func(*testing.T, state) +} +``` + +## Proposed Solution + +### 1. Data Model: Dashboard Management Metadata + +**Proto Schema** (`proto/types/v1/dashboard.proto`): +```proto +message DashboardSpec { + string name = 1; + string description = 2; + bool is_readonly = 3; + oneof source { + string file = 401; + } + bytes perses_json = 5; + + // NEW: Dashboard management metadata + DashboardManagement management = 6; +} + +message DashboardManagement { + // How dashboard was created/managed + DashboardOrigin origin = 1; + + // Code generation markers detected in file (e.g., "# Generated by CUE SDK") + repeated string codegen_markers = 2; + + // Whether user confirmed editing despite codegen warnings + bool override_codegen_protection = 3; +} + +enum DashboardOrigin { + ORIGIN_UNSPECIFIED = 0; + + // Found on filesystem, no humanlog marker + ORIGIN_DISCOVERED = 1; + + // Created via humanlog API/UI + ORIGIN_HUMANLOG_MANAGED = 2; + + // Discovered dashboard that user made editable + ORIGIN_USER_CONVERTED = 3; +} +``` + +**Rationale**: +- Proto stores the domain model (state) +- YAML comments are the serialization format (implementation detail) +- Allows us to track provenance and protect users from losing work + +### 2. File Format: YAML with Management Marker + +**Managed dashboard** (created via humanlog): +```yaml +# managed-by: humanlog +# This dashboard is managed by humanlog. +# You can edit via humanlog UI or modify this file directly. +kind: Dashboard +metadata: + name: my-dashboard + project: default +spec: + display: + name: My Dashboard + description: A test dashboard + # ... rest of Perses dashboard spec +``` + +**Discovered dashboard** (found on filesystem): +```yaml +kind: Dashboard +metadata: + name: existing-dashboard + project: default +spec: + # ... no managed-by marker +``` + +**Code-generated dashboard** (detected automatically): +```yaml +# Generated by Perses CUE SDK +# DO NOT EDIT - changes will be overwritten +kind: Dashboard +# ... +``` + +### 3. State Machine: Dashboard Lifecycle + +``` +┌─────────────────┐ +│ Filesystem │ +│ (no marker) │ +└────────┬────────┘ + │ Discovery + ▼ + ┌────────────────────────┐ + │ ORIGIN_DISCOVERED │ + │ is_readonly = true │ + │ codegen_markers = [..] │ + └──────┬────────┬────────┘ + │ │ + │ │ CreateDashboard API + │ │ (new dashboard) + │ ▼ + │ ┌────────────────────────┐ + │ │ ORIGIN_HUMANLOG_MANAGED│ + │ │ is_readonly = false │ + │ │ File: "# managed-by: │ + │ │ humanlog" │ + │ └───────┬────────────────┘ + │ │ + │ │ UpdateDashboard + │ │ DeleteDashboard + │ ▼ + │ (File updated/deleted) + │ + │ MakeDashboardEditable + │ (override_codegen=true) + ▼ + ┌────────────────────────┐ + │ ORIGIN_USER_CONVERTED │ + │ is_readonly = false │ + │ override_codegen=true │ + │ File: "# managed-by: │ + │ humanlog" │ + └────────────────────────┘ +``` + +### 4. Storage Interface Extension + +**File**: `internal/localproject/watch.go` + +```go +type projectStorage interface { + // ... existing methods ... + + // Create a new dashboard in the project + createDashboard( + ctx context.Context, + projectName string, + ptr *typesv1.ProjectPointer, + spec *typesv1.DashboardSpec, + onCreate func(*typesv1.Dashboard) error, + ) error + + // Update an existing dashboard + updateDashboard( + ctx context.Context, + projectName string, + ptr *typesv1.ProjectPointer, + dashID string, + spec *typesv1.DashboardSpec, + onUpdate func(*typesv1.Dashboard) error, + ) error + + // Delete a dashboard + deleteDashboard( + ctx context.Context, + projectName string, + ptr *typesv1.ProjectPointer, + dashID string, + ) error + + // Make a discovered dashboard editable + makeDashboardEditable( + ctx context.Context, + projectName string, + ptr *typesv1.ProjectPointer, + dashID string, + overrideCodegenProtection bool, + onMakeEditable func(*typesv1.Dashboard, []string) error, + ) error +} +``` + +**Design rationale**: +- Follows existing pattern: callback-based (see `getOrCreateProject`) +- Storage layer handles filesystem operations +- Callbacks allow `watch` layer to extract results without exposing internals + +### 5. Implementation Components + +#### 5.1 Watch Layer (`watch.go`) + +**Replace CreateDashboard error** (line 344): +```go +func (wt *watch) CreateDashboard( + ctx context.Context, + req *dashboardv1.CreateDashboardRequest, +) (*dashboardv1.CreateDashboardResponse, error) { + var out *typesv1.Dashboard + + err := wt.lockedWithProjectByName(ctx, req.ProjectName, + func(ptr *typesv1.ProjectsConfig_Project) error { + + // Check if project is writable + if lh, ok := ptr.Pointer.Scheme.(*typesv1.ProjectPointer_Localhost); ok { + if lh.Localhost.ReadOnly { + return errInvalid("project %q is read-only; cannot create dashboards", req.ProjectName) + } + } + + storage, err := wt.storageForPointer(ptr.Pointer) + if err != nil { + return err + } + + return storage.createDashboard( + ctx, + req.ProjectName, + ptr.Pointer, + req.Spec, + func(d *typesv1.Dashboard) error { + out = d + return nil + }, + ) + }) + + if err != nil { + return nil, err + } + + return &dashboardv1.CreateDashboardResponse{Dashboard: out}, nil +} +``` + +**Similarly implement**: +- `UpdateDashboard` (line 347) +- `DeleteDashboard` (line 350) +- New: `MakeDashboardEditable` + +#### 5.2 Storage Layer (`fs.go`) + +**Helper functions**: +```go +// detectCodegenMarkers scans first 20 lines for generation markers +func detectCodegenMarkers(data []byte) []string { + markers := []string{ + "# Generated by", + "# DO NOT EDIT", + "# Auto-generated", + "// Code generated", + "CUE SDK", + "Perses SDK", + } + + var found []string + lines := bytes.Split(data, []byte("\n")) + limit := min(20, len(lines)) + + for _, line := range lines[:limit] { + lineStr := strings.TrimSpace(string(line)) + for _, marker := range markers { + if strings.Contains(lineStr, marker) { + found = append(found, lineStr) + break + } + } + } + + return slices.Compact(found) // Remove duplicates +} + +// extractManagedByMarker checks for "# managed-by: humanlog" in first 5 lines +func extractManagedByMarker(data []byte) (managedBy string, hasMarker bool) { + lines := bytes.Split(data, []byte("\n")) + limit := min(5, len(lines)) + + for _, line := range lines[:limit] { + trimmed := bytes.TrimSpace(line) + if bytes.HasPrefix(trimmed, []byte("# managed-by:")) { + parts := bytes.SplitN(trimmed, []byte(":"), 2) + if len(parts) == 2 { + return string(bytes.TrimSpace(parts[1])), true + } + } + } + return "", false +} + +// sanitizeFilename converts dashboard name to safe filename +func sanitizeFilename(name string) string { + // Convert to lowercase + // Replace spaces and special chars with hyphens + // Remove consecutive hyphens + // Trim hyphens from start/end + + name = strings.ToLower(name) + name = regexp.MustCompile(`[^a-z0-9-]+`).ReplaceAllString(name, "-") + name = regexp.MustCompile(`-+`).ReplaceAllString(name, "-") + name = strings.Trim(name, "-") + + if name == "" { + name = "dashboard" + } + + return name +} + +// prependManagedByMarker adds humanlog management comment to YAML +func prependManagedByMarker(yamlData []byte) []byte { + var buf bytes.Buffer + buf.WriteString("# managed-by: humanlog\n") + buf.WriteString("# This dashboard is managed by humanlog.\n") + buf.WriteString("# You can edit via humanlog UI or modify this file directly.\n") + buf.Write(yamlData) + return buf.Bytes() +} +``` + +**Storage implementation**: +```go +func (store *localGitStorage) createDashboard( + ctx context.Context, + projectName string, + ptr *typesv1.ProjectPointer, + spec *typesv1.DashboardSpec, + onCreate func(*typesv1.Dashboard) error, +) error { + sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) + if !ok { + return errInvalid("local git can only operate with localhost projects") + } + lh := sch.Localhost + + // 1. Unmarshal provided PersesJson to Perses dashboard + persesDash := new(persesv1.Dashboard) + if err := yaml.Unmarshal(spec.PersesJson, persesDash); err != nil { + return errInvalid("invalid Perses dashboard JSON: %v", err) + } + + // 2. Set timestamps + persesDash.Metadata.CreatedAt = store.timeNow() + persesDash.Metadata.UpdatedAt = store.timeNow() + + // 3. Marshal to YAML + yamlData, err := yaml.Marshal(persesDash) + if err != nil { + return errInternal("marshaling dashboard to YAML: %v", err) + } + + // 4. Prepend managed-by marker + finalYAML := prependManagedByMarker(yamlData) + + // 5. Determine filename + filename := sanitizeFilename(spec.Name) + ".yaml" + dashboardDir := path.Join(lh.Path, lh.DashboardDir) + filepath := path.Join(dashboardDir, filename) + + // 6. Check if file already exists + if _, err := store.fs.Stat(filepath); err == nil { + return errInvalid("dashboard file already exists: %q", filename) + } + + // 7. Write to filesystem + f, err := store.fs.Create(filepath) + if err != nil { + return errInternal("creating dashboard file %q: %v", filepath, err) + } + defer f.Close() + + if _, err := f.Write(finalYAML); err != nil { + return errInternal("writing dashboard file %q: %v", filepath, err) + } + + // 8. Build response dashboard + dashboard := &typesv1.Dashboard{ + Meta: &typesv1.DashboardMeta{ + Id: dashboardID(projectName, persesDash.Metadata.Project, persesDash.Metadata.Name), + }, + Spec: &typesv1.DashboardSpec{ + Name: spec.Name, + Description: spec.Description, + IsReadonly: false, + PersesJson: finalYAML, + Source: &typesv1.DashboardSpec_File{File: filepath}, + Management: &typesv1.DashboardManagement{ + Origin: typesv1.DashboardOrigin_ORIGIN_HUMANLOG_MANAGED, + }, + }, + Status: &typesv1.DashboardStatus{ + CreatedAt: timestamppb.New(persesDash.Metadata.CreatedAt), + UpdatedAt: timestamppb.New(persesDash.Metadata.UpdatedAt), + }, + } + + return onCreate(dashboard) +} + +// Similar implementations for: +// - updateDashboard +// - deleteDashboard +// - makeDashboardEditable +``` + +#### 5.3 Discovery Update (`fs.go:parseProjectDashboard`) + +**Modify line 316**: +```go +func parseProjectDashboard( + ctx context.Context, + ffs billy.Filesystem, + projectName, dashboardPath, filename string, +) (*typesv1.Dashboard, error) { + // ... existing file reading code ... + + // Parse Perses dashboard + pout, err := parser(ctx, data) + if err != nil { + out.Status.Errors = append(out.Status.Errors, + fmt.Sprintf("invalid dashboard at path %q: %v", fpath, err)) + return out, nil + } + + // NEW: Detect management and codegen markers + managedBy, isManagedByHumanlog := extractManagedByMarker(data) + codegenMarkers := detectCodegenMarkers(data) + + // Determine origin and readonly status + origin := typesv1.DashboardOrigin_ORIGIN_DISCOVERED + isReadonly := true + + if isManagedByHumanlog { + origin = typesv1.DashboardOrigin_ORIGIN_HUMANLOG_MANAGED + isReadonly = false + } + + return &typesv1.Dashboard{ + Meta: &typesv1.DashboardMeta{ + Id: dashboardID(projectName, pout.Metadata.Project, pout.Metadata.Name), + }, + Spec: &typesv1.DashboardSpec{ + Name: pout.Spec.Display.Name, + Description: pout.Spec.Display.Description, + IsReadonly: isReadonly, + Source: &typesv1.DashboardSpec_File{File: fpath}, + PersesJson: data, + Management: &typesv1.DashboardManagement{ + Origin: origin, + CodegenMarkers: codegenMarkers, + }, + }, + Status: &typesv1.DashboardStatus{ + CreatedAt: timestamppb.New(pout.Metadata.CreatedAt), + UpdatedAt: timestamppb.New(pout.Metadata.UpdatedAt), + }, + }, nil +} +``` + +### 6. Testing Strategy + +#### 6.1 Test Infrastructure (`dashboard_lifecycle_test.go`) + +**Test structure** (following `watch_test.go` pattern): +```go +func TestDashboardLifecycle(t *testing.T) { + now := time.Date(2025, 10, 20, 10, 0, 0, 0, time.UTC) + timeNow := func() time.Time { return now } + + cmpOpts := []cmp.Option{ + protocmp.Transform(), + protocmp.IgnoreFields(&typesv1.DashboardStatus{}, "created_at", "updated_at"), + } + + type fsState struct { + files map[string]*fstest.MapFile + } + + type transition struct { + name string + at time.Duration + operation func(context.Context, *testing.T, localstate.DB) error + expectFile *fileExpectation + expectDashboard *dashboardExpectation + expectError *errorExpectation + } + + tests := []struct { + name string + initFS fsState + initProject *typesv1.ProjectsConfig_Project + transitions []transition + verify func(*testing.T, billy.Filesystem, localstate.DB) + }{ + // Test cases... + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := t.Context() + + // Setup filesystem + fs := memfs.New() + for name, file := range tt.initFS.files { + f, err := fs.Create(name) + require.NoError(t, err) + _, err = f.Write(file.Data) + require.NoError(t, err) + f.Close() + } + + // Setup config + cfg := &config.Config{ + CurrentConfig: &typesv1.LocalhostConfig{ + Runtime: &typesv1.RuntimeConfig{ + ExperimentalFeatures: &typesv1.RuntimeConfig_ExperimentalFeatures{ + Projects: &typesv1.ProjectsConfig{ + Projects: []*typesv1.ProjectsConfig_Project{tt.initProject}, + }, + }, + }, + }, + } + + // Create DB + alertState := localstate.NewMemory().AlertRuleStatusStorage() + db, err := internalWatch(ctx, fs, cfg, alertState, parseQuery, timeNow) + require.NoError(t, err) + + // Execute transitions + currentTime := now + for _, trans := range tt.transitions { + t.Run(trans.name, func(t *testing.T) { + currentTime = now.Add(trans.at) + + err := trans.operation(ctx, t, db) + + if trans.expectError != nil { + requireError(t, err, trans.expectError) + } else { + require.NoError(t, err) + } + + if trans.expectFile != nil { + verifyFile(t, fs, trans.expectFile) + } + + if trans.expectDashboard != nil { + verifyDashboard(t, ctx, db, tt.initProject.Name, trans.expectDashboard) + } + }) + } + + // Final verification + if tt.verify != nil { + tt.verify(t, fs, db) + } + }) + } +} +``` + +#### 6.2 Test Cases + +**Test 1: Create dashboard in writable project** +```go +{ + name: "create_dashboard_in_writable_project", + initFS: fsState{ + files: map[string]*fstest.MapFile{ + "project/dashboards/.keep": {}, + }, + }, + initProject: projectConfig("proj1", + localProjectPointer("project", "dashboards", "alerts", false)), // writable + transitions: []transition{ + { + name: "create dashboard via API", + operation: createDashboardOp( + "proj1", + mkDashboardSpec("my-dash", "A test dashboard"), + ), + expectFile: &fileExpectation{ + path: "project/dashboards/my-dash.yaml", + contains: []string{ + "# managed-by: humanlog", + "kind: Dashboard", + "name: my-dash", + }, + notContains: []string{"# Generated", "# DO NOT EDIT"}, + }, + expectDashboard: &dashboardExpectation{ + name: "my-dash", + isReadonly: false, + origin: typesv1.DashboardOrigin_ORIGIN_HUMANLOG_MANAGED, + }, + }, + { + name: "update managed dashboard", + at: 5 * time.Second, + operation: updateDashboardOp( + "proj1", + "my-dash", + withDescription("Updated description"), + ), + expectFile: &fileExpectation{ + path: "project/dashboards/my-dash.yaml", + contains: []string{"Updated description", "# managed-by: humanlog"}, + }, + }, + { + name: "delete managed dashboard", + at: 10 * time.Second, + operation: deleteDashboardOp("proj1", "my-dash"), + expectFile: &fileExpectation{ + path: "project/dashboards/my-dash.yaml", + shouldNotExist: true, + }, + }, + }, +} +``` + +**Test 2: Discover then convert to editable** +```go +{ + name: "discover_then_convert_to_editable", + initFS: fsState{ + files: map[string]*fstest.MapFile{ + "project/dashboards/existing.yaml": { + Data: mkPersesDashboardYAML("existing", "Existing dashboard"), + }, + }, + }, + initProject: projectConfig("proj1", + localProjectPointer("project", "dashboards", "alerts", false)), + transitions: []transition{ + { + name: "discovered dashboard is readonly", + operation: getDashboardOp("proj1", "existing"), + expectDashboard: &dashboardExpectation{ + name: "existing", + isReadonly: true, + origin: typesv1.DashboardOrigin_ORIGIN_DISCOVERED, + }, + }, + { + name: "convert to editable", + operation: makeEditableOp("proj1", "existing"), + expectFile: &fileExpectation{ + path: "project/dashboards/existing.yaml", + contains: []string{"# managed-by: humanlog"}, + }, + expectDashboard: &dashboardExpectation{ + name: "existing", + isReadonly: false, + origin: typesv1.DashboardOrigin_ORIGIN_USER_CONVERTED, + }, + }, + }, +} +``` + +**Test 3: Detect codegen and warn** +```go +{ + name: "detect_codegen_and_warn", + initFS: fsState{ + files: map[string]*fstest.MapFile{ + "project/dashboards/generated.yaml": { + Data: []byte(`# Generated by Perses CUE SDK +# DO NOT EDIT - changes will be overwritten +kind: Dashboard +metadata: + name: generated +spec: + display: + name: Generated Dashboard`), + }, + }, + }, + initProject: projectConfig("proj1", + localProjectPointer("project", "dashboards", "alerts", false)), + transitions: []transition{ + { + name: "discover detects codegen markers", + operation: getDashboardOp("proj1", "generated"), + expectDashboard: &dashboardExpectation{ + name: "generated", + isReadonly: true, + codegenMarkers: []string{ + "# Generated by Perses CUE SDK", + "# DO NOT EDIT - changes will be overwritten", + }, + }, + }, + { + name: "attempt edit without override fails", + operation: makeEditableOp("proj1", "generated"), + expectError: &errorExpectation{ + code: connect.CodeFailedPrecondition, + message: "appears to be code-generated", + }, + }, + { + name: "edit with override succeeds with warnings", + operation: makeEditableOp("proj1", "generated", + withOverrideCodegen(true)), + expectDashboard: &dashboardExpectation{ + isReadonly: false, + overrideCodegen: true, + }, + expectWarnings: []string{ + "Dashboard contains code generation markers", + }, + }, + }, +} +``` + +**Test 4: Readonly project blocks creation** +```go +{ + name: "readonly_project_blocks_creation", + initProject: projectConfig("proj1", + localProjectPointer("project", "dashboards", "alerts", true)), // readonly + transitions: []transition{ + { + name: "create in readonly project fails", + operation: createDashboardOp("proj1", + mkDashboardSpec("dash", "desc")), + expectError: &errorExpectation{ + code: connect.CodeFailedPrecondition, + message: "read-only", + }, + }, + }, +} +``` + +#### 6.3 Builder Functions + +```go +// Operation builders +func createDashboardOp(project string, spec *typesv1.DashboardSpec) + func(context.Context, *testing.T, localstate.DB) error { + return func(ctx context.Context, t *testing.T, db localstate.DB) error { + _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ + ProjectName: project, + Spec: spec, + }) + return err + } +} + +func updateDashboardOp(project, dashID string, opts ...dashboardOption) + func(context.Context, *testing.T, localstate.DB) error { + return func(ctx context.Context, t *testing.T, db localstate.DB) error { + // Get existing dashboard first + resp, err := db.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ + ProjectName: project, + Id: dashID, + }) + if err != nil { + return err + } + + spec := resp.Dashboard.Spec + for _, opt := range opts { + opt(spec) + } + + _, err = db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ + ProjectName: project, + Id: dashID, + Spec: spec, + }) + return err + } +} + +func deleteDashboardOp(project, dashID string) + func(context.Context, *testing.T, localstate.DB) error { + return func(ctx context.Context, t *testing.T, db localstate.DB) error { + _, err := db.DeleteDashboard(ctx, &dashboardv1.DeleteDashboardRequest{ + ProjectName: project, + Id: dashID, + }) + return err + } +} + +func getDashboardOp(project, dashID string) + func(context.Context, *testing.T, localstate.DB) error { + return func(ctx context.Context, t *testing.T, db localstate.DB) error { + _, err := db.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ + ProjectName: project, + Id: dashID, + }) + return err + } +} + +func makeEditableOp(project, dashID string, opts ...makeEditableOption) + func(context.Context, *testing.T, localstate.DB) error { + return func(ctx context.Context, t *testing.T, db localstate.DB) error { + req := &dashboardv1.MakeDashboardEditableRequest{ + ProjectName: project, + Id: dashID, + } + for _, opt := range opts { + opt(req) + } + _, err := db.MakeDashboardEditable(ctx, req) + return err + } +} + +// Spec builders +func mkDashboardSpec(name, desc string, opts ...dashboardOption) *typesv1.DashboardSpec { + // Create minimal Perses dashboard + persesDash := &persesv1.Dashboard{ + Kind: "Dashboard", + Metadata: persesv1.ProjectMetadata{ + Metadata: persesv1.Metadata{Name: name}, + }, + Spec: persesv1.DashboardSpec{ + Display: persesv1.Display{ + Name: name, + Description: desc, + }, + }, + } + + persesJSON, _ := yaml.Marshal(persesDash) + + spec := &typesv1.DashboardSpec{ + Name: name, + Description: desc, + PersesJson: persesJSON, + } + + for _, opt := range opts { + opt(spec) + } + + return spec +} + +// Options +type dashboardOption func(*typesv1.DashboardSpec) +type makeEditableOption func(*dashboardv1.MakeDashboardEditableRequest) + +func withDescription(desc string) dashboardOption { + return func(spec *typesv1.DashboardSpec) { + spec.Description = desc + } +} + +func withOverrideCodegen(override bool) makeEditableOption { + return func(req *dashboardv1.MakeDashboardEditableRequest) { + req.OverrideCodegenProtection = override + } +} + +// Expectation types +type fileExpectation struct { + path string + contains []string + notContains []string + shouldNotExist bool +} + +type dashboardExpectation struct { + name string + isReadonly bool + origin typesv1.DashboardOrigin + codegenMarkers []string + overrideCodegen bool +} + +type errorExpectation struct { + code connect.Code + message string +} + +// Verification helpers +func verifyFile(t *testing.T, fs billy.Filesystem, expect *fileExpectation) { + if expect.shouldNotExist { + _, err := fs.Stat(expect.path) + require.True(t, errors.Is(err, os.ErrNotExist), + "file should not exist: %s", expect.path) + return + } + + f, err := fs.Open(expect.path) + require.NoError(t, err, "failed to open file: %s", expect.path) + defer f.Close() + + content, err := io.ReadAll(f) + require.NoError(t, err, "failed to read file: %s", expect.path) + + contentStr := string(content) + for _, substr := range expect.contains { + require.Contains(t, contentStr, substr, + "file %s should contain %q", expect.path, substr) + } + for _, substr := range expect.notContains { + require.NotContains(t, contentStr, substr, + "file %s should not contain %q", expect.path, substr) + } +} + +func verifyDashboard( + t *testing.T, + ctx context.Context, + db localstate.DB, + project string, + expect *dashboardExpectation, +) { + // List dashboards and find by name + resp, err := db.ListDashboard(ctx, &dashboardv1.ListDashboardRequest{ + ProjectName: project, + }) + require.NoError(t, err) + + var dashboard *typesv1.Dashboard + for _, item := range resp.Items { + if item.Dashboard.Spec.Name == expect.name { + dashboard = item.Dashboard + break + } + } + require.NotNil(t, dashboard, "dashboard %q not found", expect.name) + + require.Equal(t, expect.isReadonly, dashboard.Spec.IsReadonly) + require.Equal(t, expect.origin, dashboard.Spec.Management.Origin) + + if len(expect.codegenMarkers) > 0 { + require.ElementsMatch(t, expect.codegenMarkers, + dashboard.Spec.Management.CodegenMarkers) + } + + if expect.overrideCodegen { + require.True(t, dashboard.Spec.Management.OverrideCodegenProtection) + } +} + +func requireError(t *testing.T, err error, expect *errorExpectation) { + require.Error(t, err) + + var connectErr *connect.Error + require.True(t, errors.As(err, &connectErr), "error should be connect.Error") + require.Equal(t, expect.code, connectErr.Code()) + require.Contains(t, connectErr.Message(), expect.message) +} +``` + +### 7. New RPC: MakeDashboardEditable + +**Proto** (`proto/svc/dashboard/v1/service.proto`): +```proto +service DashboardService { + // ... existing RPCs ... + + rpc MakeDashboardEditable(MakeDashboardEditableRequest) + returns (MakeDashboardEditableResponse); +} + +message MakeDashboardEditableRequest { + int64 environment_id = 101; + string project_name = 102 [(buf.validate.field).required = true]; + string id = 1 [(buf.validate.field).required = true]; + + // Allow editing even if code generation markers detected + bool override_codegen_protection = 2; +} + +message MakeDashboardEditableResponse { + types.v1.Dashboard dashboard = 1; + + // Warnings about code generation (if any) + repeated string warnings = 2; +} +``` + +### 8. Implementation Phases + +#### Phase 1: Proto & Codegen +1. Add proto changes to API repo +2. Run `make generate` +3. Bump API version in humanlog `go.mod` +4. Run `go mod tidy` and `make generate` in humanlog + +#### Phase 2: Test Infrastructure +1. Create `dashboard_lifecycle_test.go` +2. Implement builder functions +3. Implement verification helpers +4. Write all test cases (should FAIL - RED state) + +#### Phase 3: Implementation +1. Add helper functions to `fs.go` +2. Extend `projectStorage` interface in `watch.go` +3. Implement `CreateDashboard` in `watch.go` (remove error) +4. Implement `createDashboard` in `localGitStorage` (fs.go) +5. Run tests → should pass for Create (GREEN) +6. Implement `UpdateDashboard` in `watch.go` +7. Implement `updateDashboard` in `localGitStorage` +8. Run tests → should pass for Update (GREEN) +9. Implement `DeleteDashboard` in `watch.go` +10. Implement `deleteDashboard` in `localGitStorage` +11. Run tests → should pass for Delete (GREEN) +12. Update `parseProjectDashboard` to detect markers +13. Run tests → should pass for Discovery (GREEN) +14. Implement `MakeDashboardEditable` RPC +15. Run tests → all pass (GREEN) + +#### Phase 4: Refactoring +1. Review code for duplication +2. Extract common patterns +3. Add comments and documentation + +### 9. Testing Checklist + +- [ ] Create in writable project → file created with marker +- [ ] Create in readonly project → FailedPrecondition error +- [ ] Create with duplicate name → InvalidArgument error +- [ ] Discovered dashboards → readonly, ORIGIN_DISCOVERED +- [ ] Managed dashboards → writable, ORIGIN_HUMANLOG_MANAGED +- [ ] Update managed dashboard → file modified, marker preserved +- [ ] Update readonly dashboard → FailedPrecondition error +- [ ] Delete managed dashboard → file removed +- [ ] Delete readonly dashboard → FailedPrecondition error +- [ ] Codegen detection → markers identified correctly +- [ ] MakeEditable without override → FailedPrecondition if codegen detected +- [ ] MakeEditable with override → success + warnings +- [ ] MakeEditable on already editable → no-op, returns dashboard +- [ ] Filename sanitization → safe filenames +- [ ] Timestamps use injected timeNow → deterministic tests +- [ ] Concurrent operations safe → mutex in watch +- [ ] Invalid Perses JSON → InvalidArgument error +- [ ] Dashboard ID stable and URL-safe → verified +- [ ] Git diff shows clean YAML → human-readable +- [ ] Round-trip: create → read → update → read → preserves data + +### 10. Open Questions + +1. **Dashboard ID collision**: What if two dashboards have same sanitized filename? + - **Proposal**: Check for existing file, append counter: `my-dash-2.yaml` + +2. **Concurrent edits**: What if file changed on disk between read and write? + - **Proposal**: Accept last-write-wins for v1, add file hash check in v2 + +3. **Git conflicts**: How to handle merge conflicts in dashboard YAML? + - **Proposal**: Document that standard git conflict resolution applies + +4. **Project name mismatch**: What if Perses `metadata.project` differs from humanlog project name? + - **Proposal**: Override Perses project name with humanlog project name + +5. **Dashboard deletion**: Should we soft-delete (move to `.trash/`) or hard-delete? + - **Proposal**: Hard-delete for v1, add trash in v2 if requested + +6. **Large dashboards**: What if dashboard YAML is >1MB? + - **Proposal**: No size limit for v1, add validation in v2 if issues arise + +### 11. Future Enhancements (Out of Scope for v1) + +1. **Dashboard templates**: Library of common dashboard patterns +2. **Dashboard versioning**: Track changes over time +3. **Dashboard comparison**: Visual diff between local and remote +4. **Dashboard import**: Import from other Perses instances +5. **Dashboard export**: Export to other formats (Grafana, etc.) +6. **Dashboard validation**: Lint dashboards for common issues +7. **Dashboard preview**: Render dashboard before saving + +### 12. Migration Path + +**Existing users with filesystem dashboards**: +- All existing dashboards will be discovered as `ORIGIN_DISCOVERED` (readonly) +- Users can explicitly convert to editable via `MakeDashboardEditable` +- No breaking changes - discovery continues to work as before + +**New users**: +- Create projects pointing to git repos +- Create dashboards via UI +- Commit and push to git +- Open PR for review + +## Summary + +This proposal provides a complete GitOps workflow for dashboard authoring: + +1. **Discover** existing dashboards (read-only by default) +2. **Create** new dashboards via API → written as YAML with `# managed-by: humanlog` +3. **Edit** managed dashboards → updates preserved +4. **Protect** against editing code-generated dashboards → warnings and override +5. **Commit** changes to git → clean, human-readable diffs +6. **Compare** local vs remote → standard git tooling + +The implementation follows codebase patterns: +- Test-first with declarative state machines +- Constructor injection for testability +- Callback-based storage interface +- Externalized non-determinism (time, filesystem) + +Next steps: Review, iterate on proposal, then implement. diff --git a/go.mod b/go.mod index 97875218..6ed55dcb 100644 --- a/go.mod +++ b/go.mod @@ -4,171 +4,66 @@ go 1.25.0 require ( connectrpc.com/connect v1.17.0 - connectrpc.com/cors v0.1.0 - connectrpc.com/otelconnect v0.7.2 github.com/99designs/keyring v1.2.2 - github.com/NimbleMarkets/ntcharts v0.1.2 github.com/aybabtme/flatjson v0.1.3-0.20250507081407-dfee75a600e6 github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 github.com/blang/semver v3.5.1+incompatible - github.com/charmbracelet/glamour v0.10.0 - github.com/charmbracelet/huh v0.7.0 github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 github.com/charmbracelet/log v0.4.2 - github.com/charmbracelet/x/term v0.2.1 github.com/cli/safeexec v1.0.1 - github.com/crazy3lf/colorconv v1.2.0 github.com/fatih/color v1.18.0 - github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4 - github.com/getlantern/systray v1.2.2 - github.com/go-git/go-billy/v6 v6.0.0-20250627091229-31e2a16eef30 - github.com/go-git/go-git/v6 v6.0.0-20250923192830-1ad5b9c7da82 github.com/go-logfmt/logfmt v0.6.1 github.com/google/go-cmp v0.7.0 - github.com/google/uuid v1.6.0 - github.com/kardianos/service v1.2.2 github.com/kr/logfmt v0.0.0-20210122060352-19f9bcb100e6 github.com/lucasb-eyer/go-colorful v1.3.0 - github.com/matoous/go-nanoid v1.5.0 github.com/mattn/go-colorable v0.1.14 github.com/mattn/go-isatty v0.0.20 github.com/minitape/api/go v0.0.0-20260314053553-971e5e26bafc github.com/mitchellh/go-homedir v1.1.0 github.com/oklog/ulid/v2 v2.1.1 - github.com/perses/perses v0.51.1 - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c - github.com/prometheus/prometheus v0.305.0 - github.com/rs/cors v1.11.1 github.com/ryanuber/go-glob v1.0.0 github.com/stretchr/testify v1.11.1 github.com/urfave/cli v1.22.14 - github.com/zeebo/blake3 v0.2.4 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 - go.opentelemetry.io/contrib/propagators/b3 v1.35.0 - go.opentelemetry.io/contrib/propagators/ot v1.35.0 go.opentelemetry.io/otel v1.38.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 - go.opentelemetry.io/otel/sdk v1.38.0 - go.opentelemetry.io/otel/sdk/metric v1.38.0 - go.opentelemetry.io/otel/trace v1.38.0 go.opentelemetry.io/proto/otlp v1.8.0 - go.opentelemetry.io/proto/otlp/collector/profiles/v1development v0.1.0 - golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 golang.org/x/net v0.43.0 - golang.org/x/sync v0.16.0 - golang.org/x/sys v0.37.0 - gonum.org/v1/gonum v0.16.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 google.golang.org/grpc v1.75.0 google.golang.org/protobuf v1.36.10 - gopkg.in/yaml.v3 v3.0.1 ) require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/alecthomas/chroma/v2 v2.14.0 // indirect - github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/aymerick/douceur v0.2.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/catppuccin/go v0.3.0 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/charmbracelet/bubbles v0.21.0 // indirect - github.com/charmbracelet/bubbletea v1.3.4 // indirect github.com/charmbracelet/colorprofile v0.3.2 // indirect github.com/charmbracelet/x/ansi v0.10.2 // indirect github.com/charmbracelet/x/cellbuf v0.0.13 // indirect - github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect - github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect github.com/clipperhouse/uax29/v2 v2.2.0 // indirect - github.com/cloudflare/circl v1.6.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect - github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/danieljoos/wincred v1.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dennwc/varint v1.0.0 // indirect - github.com/dlclark/regexp2 v1.11.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect - github.com/edsrzf/mmap-go v1.2.0 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect - github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect - github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect - github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 // indirect - github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 // indirect - github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 // indirect - github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f // indirect - github.com/go-git/gcfg/v2 v2.0.2 // indirect - github.com/go-jose/go-jose/v4 v4.1.1 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-stack/stack v1.8.0 // indirect - github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/gorilla/css v1.0.1 // indirect - github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect - github.com/jpillora/backoff v1.0.0 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/lrstanley/bubblezone v0.0.0-20240914071701-b48c55a5e78e // indirect - github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect - github.com/microcosm-cc/bluemonday v1.0.27 // indirect - github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/mtibben/percent v0.2.1 // indirect - github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect - github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.16.0 // indirect - github.com/muhlemmer/gu v0.3.1 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect - github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.65.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - github.com/yuin/goldmark v1.7.8 // indirect - github.com/yuin/goldmark-emoji v1.0.5 // indirect - github.com/zeebo/assert v1.3.0 // indirect - github.com/zitadel/oidc/v3 v3.38.1 // indirect - github.com/zitadel/schema v1.3.1 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/metric v1.38.0 // indirect - go.opentelemetry.io/proto/otlp/profiles/v1development v0.0.0-20250721084824-6f76ca90124d // indirect - go.uber.org/atomic v1.11.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect + golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect + golang.org/x/sys v0.37.0 // indirect golang.org/x/term v0.34.0 // indirect golang.org/x/text v0.28.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) // replace github.com/minitape/api/go => ../../minitape/api/go diff --git a/go.sum b/go.sum index 19284c89..cdf58ac9 100644 --- a/go.sum +++ b/go.sum @@ -1,118 +1,28 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1 h1:31on4W/yPcV4nZHL4+UCiCvLPsMqe/vJcNg8Rci0scc= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250912141014-52f32327d4b0.1/go.mod h1:fUl8CEN/6ZAMk6bP8ahBJPUJw7rbp+j4x+wCcYi2IG4= -cloud.google.com/go/auth v0.16.2 h1:QvBAGFPLrDeoiNjyfVunhQ10HKNYuOwZ5noee0M5df4= -cloud.google.com/go/auth v0.16.2/go.mod h1:sRBas2Y1fB1vZTdurouM0AzuYQBMZinrUYL8EufhtEA= -cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= -cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= -cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= -cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= -connectrpc.com/cors v0.1.0 h1:f3gTXJyDZPrDIZCQ567jxfD9PAIpopHiRDnJRt3QuOQ= -connectrpc.com/cors v0.1.0/go.mod h1:v8SJZCPfHtGH1zsm+Ttajpozd4cYIUryl4dFB6QEpfg= -connectrpc.com/otelconnect v0.7.2 h1:WlnwFzaW64dN06JXU+hREPUGeEzpz3Acz2ACOmN8cMI= -connectrpc.com/otelconnect v0.7.2/go.mod h1:JS7XUKfuJs2adhCnXhNHPHLz6oAaZniCJdSF00OZSew= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= -github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/NimbleMarkets/ntcharts v0.1.2 h1:iW1aiOif/Dm74sQd18opi10RMED5589cVhy9SGp98Tw= -github.com/NimbleMarkets/ntcharts v0.1.2/go.mod h1:WcHS7kc8oQctN1543DeV9a+gOrS4DDVfKp1N9RZFUqc= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE= -github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E= -github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -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/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= -github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= -github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= -github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= -github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= -github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= -github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= -github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/aybabtme/flatjson v0.1.3-0.20250507081407-dfee75a600e6 h1:4JHpUkY9oQmGE6Psn/edDH5BPgMr0CFIxc1OXI/oWwQ= github.com/aybabtme/flatjson v0.1.3-0.20250507081407-dfee75a600e6/go.mod h1:ypXkt2csM4h/q1NqWPu2GbIwLqeM/tN+E6Vg3u5wwGI= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= -github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= -github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= -github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= -github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= -github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= -github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= -github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= -github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI= -github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo= github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI= github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI= -github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY= -github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk= -github.com/charmbracelet/huh v0.7.0 h1:W8S1uyGETgj9Tuda3/JdVkc3x7DBLZYPZc4c+/rnRdc= -github.com/charmbracelet/huh v0.7.0/go.mod h1:UGC3DZHlgOKHvHC07a5vHag41zzhpPFj34U92sOmyuk= github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE= github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA= github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig= @@ -121,248 +31,82 @@ github.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvA github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8= github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= -github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U= -github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ= -github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA= -github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= -github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI= -github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU= -github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4= -github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= -github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= -github.com/charmbracelet/x/xpty v0.1.2 h1:Pqmu4TEJ8KeA9uSkISKMU3f+C1F6OGBn8ABuGlqCbtI= -github.com/charmbracelet/x/xpty v0.1.2/go.mod h1:XK2Z0id5rtLWcpeNiMYBccNNBrP2IJnzHI0Lq13Xzq4= github.com/cli/safeexec v1.0.1 h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00= github.com/cli/safeexec v1.0.1/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q= github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY= github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= -github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/crazy3lf/colorconv v1.2.0 h1:UM7kSZWnwFMGiC+PpYrjxQSOd6sEyWb+dRKKTd3KslA= -github.com/crazy3lf/colorconv v1.2.0/go.mod h1:2jTJ7QCWCj2sSLOhF4Gzi0J5/hoX8/VY8VzNvXAlD1I= -github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= -github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= -github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= -github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= -github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= -github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= -github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84= -github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= -github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM= -github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4 h1:ygs9POGDQpQGLJPlq4+0LBUmMBNox1N4JSpw+OETcvI= -github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4/go.mod h1:0W7dI87PvXJ1Sjs0QPvWXKcQmNERY77e8l7GFhZB/s4= -github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4= -github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY= -github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 h1:6uJ+sZ/e03gkbqZ0kUG6mfKoqDb4XMAzMIwlajq19So= -github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A= -github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 h1:guBYzEaLz0Vfc/jv0czrr2z7qyzTOGC9hiQ0VC+hKjk= -github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7/go.mod h1:zx/1xUUeYPy3Pcmet8OSXLbF47l+3y6hIPpyLWoR9oc= -github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0= -github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o= -github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc= -github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA= -github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA= -github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA= -github.com/getlantern/systray v1.2.2 h1:dCEHtfmvkJG7HZ8lS/sLklTH4RKUcIsKrAD9sThoEBE= -github.com/getlantern/systray v1.2.2/go.mod h1:pXFOI1wwqwYXEhLPm9ZGjS2u/vVELeIgNMY5HvhHhcE= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg/v2 v2.0.2 h1:MY5SIIfTGGEMhdA7d7JePuVVxtKL7Hp+ApGDJAJ7dpo= -github.com/go-git/gcfg/v2 v2.0.2/go.mod h1:/lv2NsxvhepuMrldsFilrgct6pxzpGdSRC13ydTLSLs= -github.com/go-git/go-billy/v6 v6.0.0-20250627091229-31e2a16eef30 h1:4KqVJTL5eanN8Sgg3BV6f2/QzfZEFbCd+rTak1fGRRA= -github.com/go-git/go-billy/v6 v6.0.0-20250627091229-31e2a16eef30/go.mod h1:snwvGrbywVFy2d6KJdQ132zapq4aLyzLMgpo79XdEfM= -github.com/go-git/go-git-fixtures/v5 v5.1.0 h1:b8cWxDLTk0s09Ihm9x1HvNGUzxUVlRwIH7EAM0gGDKg= -github.com/go-git/go-git-fixtures/v5 v5.1.0/go.mod h1:CdmU0oQeDuy4Xh8V0i9Ym+vsTkgDDPKEiofBFEVT+aE= -github.com/go-git/go-git/v6 v6.0.0-20250923192830-1ad5b9c7da82 h1:UkmsHb3Lw70N9CrPwJQ7vz6qFt1b2DTNflceIYqvYLk= -github.com/go-git/go-git/v6 v6.0.0-20250923192830-1ad5b9c7da82/go.mod h1:Y0VMP4A1sh7BXZQFQBM5DJVRetrmT8//SYXtFYwCKf4= -github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= -github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE= -github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= -github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= -github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= -github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= -github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0= -github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w= -github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= -github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= -github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= -github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60= -github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/logfmt v0.0.0-20210122060352-19f9bcb100e6 h1:ZK1mH67KVyVW/zOLu0xLva+f6xJ8vt+LGrkQq5FJYLY= github.com/kr/logfmt v0.0.0-20210122060352-19f9bcb100e6/go.mod h1:JIiJcj9TX57tEvCXjm6eaHd2ce4pZZf9wzYuThq45u8= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lrstanley/bubblezone v0.0.0-20240914071701-b48c55a5e78e h1:OLwZ8xVaeVrru0xyeuOX+fne0gQTFEGlzfNjipCbxlU= -github.com/lrstanley/bubblezone v0.0.0-20240914071701-b48c55a5e78e/go.mod h1:NQ34EGeu8FAYGBMDzwhfNJL8YQYoWZP5xYJPRDAwN3E= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= -github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= -github.com/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= -github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZMYDR+NGImiFvErt6VWfIRPuGM+vyjiEdkmIw= -github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= -github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/minitape/api/go v0.0.0-20260314053553-971e5e26bafc h1:6/7Nfvqr75/Bty38S2glh0PIceU+QNABW0gHW3S1W5s= github.com/minitape/api/go v0.0.0-20260314053553-971e5e26bafc/go.mod h1:g09nd/95pyUgLAPKZKd9/IwvnNpZQn8sVQVnyMKev6k= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= -github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= -github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= -github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nexucis/lamenv v0.5.2 h1:tK/u3XGhCq9qIoVNcXsK9LZb8fKopm0A5weqSRvHd7M= -github.com/nexucis/lamenv v0.5.2/go.mod h1:HusJm6ltmmT7FMG8A750mOLuME6SHCsr2iFYxp5fFi0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= -github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= -github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= -github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/perses/perses v0.51.1 h1:3M/D0FHDMAofVLyVwQoADZL6b2L5MqeXdlIxgjfi7S0= -github.com/perses/perses v0.51.1/go.mod h1:DrGiL+itTLl2mwEvNa0wGokELfZTsqOc3TEg+2B0uwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= -github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/prometheus/prometheus v0.305.0 h1:UO/LsM32/E9yBDtvQj8tN+WwhbyWKR10lO35vmFLx0U= -github.com/prometheus/prometheus v0.305.0/go.mod h1:JG+jKIDUJ9Bn97anZiCjwCxRyAx+lpcEQ0QnZlUlbwY= -github.com/prometheus/sigv4 v0.2.0 h1:qDFKnHYFswJxdzGeRP63c4HlH3Vbn1Yf/Ao2zabtVXk= -github.com/prometheus/sigv4 v0.2.0/go.mod h1:D04rqmAaPPEUkjRQxGqjoxdyJuyCh6E0M18fZr0zBiE= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= -github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -370,56 +114,21 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk= -github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= -github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk= -github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= -github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= -github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= -github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= -github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -github.com/zitadel/oidc/v3 v3.38.1 h1:VTf1Bv/33UbSwJnIWbfEIdpUGYKfoHetuBNIqVTcjvA= -github.com/zitadel/oidc/v3 v3.38.1/go.mod h1:muukzAasaWmn3vBwEVMglJfuTE0PKCvLJGombPwXIRw= -github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU= -github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU= 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/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/contrib/propagators/b3 v1.35.0 h1:DpwKW04LkdFRFCIgM3sqwTJA/QREHMeMHYPWP1WeaPQ= -go.opentelemetry.io/contrib/propagators/b3 v1.35.0/go.mod h1:9+SNxwqvCWo1qQwUpACBY5YKNVxFJn5mlbXg/4+uKBg= -go.opentelemetry.io/contrib/propagators/ot v1.35.0 h1:ZsgYijVvOpju4mq3g4QyqCwLKs2vKenlCpZHbKu50OA= -go.opentelemetry.io/contrib/propagators/ot v1.35.0/go.mod h1:t1ZwtgjEtDH9uW6OlCRVLL2wOgsTJmp0pJwNouUq+HE= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= @@ -430,68 +139,19 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/proto/otlp v1.8.0 h1:fRAZQDcAFHySxpJ1TwlA1cJ4tvcrw7nXl9xWWC8N5CE= go.opentelemetry.io/proto/otlp v1.8.0/go.mod h1:tIeYOeNBU4cvmPqpaji1P+KbB4Oloai8wN4rWzRrFF0= -go.opentelemetry.io/proto/otlp/collector/profiles/v1development v0.1.0 h1:oHR8pwK4RbMMTIyu/mp+1ZaolOXMTN1/t9oGvLpd74A= -go.opentelemetry.io/proto/otlp/collector/profiles/v1development v0.1.0/go.mod h1:1UkO7x4pJaCJvncsIuEIVOTtlqIoYJ//bYHdyUpqmRs= -go.opentelemetry.io/proto/otlp/profiles/v1development v0.0.0-20250721084824-6f76ca90124d h1:NBrIfMZqdsv8nVS9yLkAfdKyVlZIk9OxerzS+V5FMck= -go.opentelemetry.io/proto/otlp/profiles/v1development v0.0.0-20250721084824-6f76ca90124d/go.mod h1:/wV1Wyg3wdh0FngILo+M7A948iLfldMCMOEqXyVWsr4= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/api v0.238.0 h1:+EldkglWIg/pWjkq97sd+XxH7PxakNYoe/rkSTbnvOs= -google.golang.org/api v0.238.0/go.mod h1:cOVEm2TpdAGHL2z+UwyS+kmlGr3bVWQQ6sYEqkKje50= google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY= google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= @@ -500,24 +160,11 @@ google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4= -k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4= -k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= diff --git a/internal/compat/alertmanager/parse.go b/internal/compat/alertmanager/parse.go deleted file mode 100644 index 79850efc..00000000 --- a/internal/compat/alertmanager/parse.go +++ /dev/null @@ -1,109 +0,0 @@ -package alertmanager - -import ( - "fmt" - "io" - "slices" - "strings" - "time" - - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/prometheus/prometheus/model/rulefmt" - "google.golang.org/protobuf/types/known/durationpb" - "gopkg.in/yaml.v3" -) - -func ParseRules(r io.Reader, logQlParser func(string) (*typesv1.Query, error)) ([]*typesv1.AlertGroup, error) { - var groups rulefmt.RuleGroups - decoder := yaml.NewDecoder(r) - decoder.KnownFields(true) - if err := decoder.Decode(&groups); err != nil { - return nil, fmt.Errorf("parsing alert rules: %v", err) - } - return ToGroups(groups.Groups, logQlParser) -} - -func ToGroups(groups []rulefmt.RuleGroup, parser func(string) (*typesv1.Query, error)) ([]*typesv1.AlertGroup, error) { - out := make([]*typesv1.AlertGroup, 0, len(groups)) - for _, g := range groups { - ag, err := ToGroup(g, parser) - if err != nil { - return nil, fmt.Errorf("group %q: %v", g.Name, err) - } - out = append(out, ag) - } - return out, nil -} - -func ToGroup(g rulefmt.RuleGroup, parser func(string) (*typesv1.Query, error)) (*typesv1.AlertGroup, error) { - spec := &typesv1.AlertGroupSpec{ - Name: g.Name, - Interval: durationpb.New(time.Duration(g.Interval)), - Limit: int32(g.Limit), - Labels: mapToObj(g.Labels), - Rules: make([]*typesv1.AlertGroupSpec_NamedAlertRuleSpec, 0, len(g.Rules)), - } - status := &typesv1.AlertGroupStatus{} - out := &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{}, - Spec: spec, - Status: status, - } - if g.QueryOffset != nil { - spec.QueryOffset = durationpb.New(time.Duration(*g.QueryOffset)) - } - for _, a := range g.Rules { - ar, err := ToAlert(a, parser) - if err != nil { - status.Errors = append(status.Errors, fmt.Sprintf("alert %q: %v", a.Alert, err)) - } - spec.Rules = append(spec.Rules, &typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - Id: ar.Spec.Name, - Spec: ar.Spec, - }) - } - return out, nil -} - -func ToAlert(ar rulefmt.Rule, parser func(string) (*typesv1.Query, error)) (*typesv1.AlertRule, error) { - q, err := parser(ar.Expr) - if err != nil { - return nil, err - } - meta := &typesv1.AlertRuleMeta{ - Id: ar.Alert, - } - spec := &typesv1.AlertRuleSpec{ - Name: ar.Alert, - Expr: q, - For: durationpb.New(time.Duration(ar.For)), - Labels: mapToObj(ar.Labels), - Annotations: mapToObj(ar.Annotations), - } - if ar.KeepFiringFor != 0 { - spec.KeepFiringFor = durationpb.New(time.Duration(ar.KeepFiringFor)) - } - status := &typesv1.AlertRuleStatus{} - out := &typesv1.AlertRule{ - Meta: meta, - Spec: spec, - Status: status, - } - return out, nil -} - -func mapToObj(m map[string]string) *typesv1.Obj { - if len(m) == 0 { - return nil - } - out := make([]*typesv1.KV, 0, len(m)) - for k, v := range m { - out = append(out, typesv1.KeyVal( - k, typesv1.ValStr(v), - )) - } - slices.SortFunc(out, func(a, b *typesv1.KV) int { - return strings.Compare(a.Key, b.Key) - }) - return &typesv1.Obj{Kvs: out} -} diff --git a/internal/embeds/assets/icon/systray/humanlog.icns b/internal/embeds/assets/icon/systray/humanlog.icns deleted file mode 100644 index e9b18232bb18354b6ff7dc6fe3a3f5d385fafcbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1597129 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

v@qp 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.cL) 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

x*ZpH9Gk`IbJzyebtVS{vtycw9htc#lLD2yU#1> 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≻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�>2Ig_!Aj za~|eyj4t@70c!0H(E1N~;*7HdAqHry+yH-H4zDt-I6<}yT>|~Am)||%*{Y|yYT!gb zVL6C%RbG9p1u?eKJxv4ONvO^~MLS&q168*_svCO$2_KcoKg!GxOOdOyRtnd+=bs&T z{U=>3N9*@7C3NWq5IX^%i|-4(3i@vYT_?9xkk#8j=bNxIa3w@`1RPlQ(#rQ#9N#2o z1Rizn7&?EW7LA2Plyg@rEn}peQR{(&XyWTsbITGF2Q-0<*3`Fj)^Ws)%hG2)^^NsgKF{B-+sbdf_BZ5*xA^-gpDRb+YeB3=3`#bW%81aOr0|ARYHxdJtM- zK3A?j#jnX{oRBb1`C^BQ1!aAzfr^N-(7B*$teouFy1~tAb_f`bcc8#O zjD0s9YwgGGgXyX5sB+D%2LqiV^fjyC(?C-2E_*dD}P9`G1^z09T z_1LiZjs7fu-|i~24Q&mcF3jx{rNV*Nr{K%QBx7GyO);n}ho8ZGFf(+pJUacN?xo1| zB!?*NOwtrZkC;BX2BN!bUWaWlzfN{7i+cQ6?)P zFM(#Oy1w0&G3WWm2FZj+qdh#zfQ!kTH9Z^c$^qvY!7m#sefhDx-vMt4K&P$GfsiJr z)`=l*?|KD7Zp)9XV}73ORGW38(ICAMV!=s6Lr){Z-2ygnpi-^?yG#!FUhY(l{5A!Z zRlKL!WRGrMB|&0r+pipe6HsRO6bd;9S#}Z%(A0i7!Qy|8&v02r2!zLmSnq3tK#~F@ zA+-XV($F{>arGs%0!;zR7-!uBA6m=#OJ44%N+Z4$uyW`qJnLMY4V6BxVD4a&As=94 zwK`Y>%)r|bS}y)YWIc2+APejn?m(cFzNZ~WdPgoyB`-4=6sT`w5T^G*jWA-j zNu&i@p87V36F~aY9T_@zs5!N}5{S7XCy8wvGQa`wbZ|^?NA z&EK4NhK$8pwG3@7kfyOHJx93cwzF878vgI(l5ok+nhi~S4dd(eo~BKm!K*X))H$n~ z_kNst2ejuoP7rPs=uFqp-A)RZZmSR}zyTY}NoEbdi&a<4ubc`T)2lTv&wDm5vT6c5 z9YB(#3FBIc=t6FGVJ>J#mCV3fTG|=)0xKKF-wOq2E4fqv`V}d(CdqpelEox$DcQfL3DE%-j23HKmOEfk)7*7yQ|Q-i_1x$}eW&Q-UB?Aw;F_$MdHpGmz`_}d>} zDA^Ssw32O!<0nH-NPwp^Plt@0Fwp^PrVKkv#-7bT+{avfX>8jGHTUqY0P)OoDDQVB zgiBt$wVdTYPaN%%4-@@WLey9MolFN`$rZ>+*HA(ji+eDtrHBKOrdel?*T0Rt+eQpl zm6Lq14k7`l=R#!AstXZbh3$DM(I~`}#{%1EJN#5@CDD@g?EH)Yway#jhjF)C=EXz~+l+U(=go^E_?WPeo45D<&;F zdtwYYKER%3Vy-aZ!cE?khU~|5l0Yq9Al1~4ownrIS2{ipY4P>HiuAj#A@-sT7c>0V zTTyN?cMxq^Cj+~#uwVAa4{a!c>W-%+Umvyt$Yj~Na2viC82xp*)4%q=ChFs=tHvj( zIcntsocCMOfyUV4J^SFKYmOLgT=T0PtmVCJ`g$^dVKiEwQGzeUi0GUA8s})`E7(59 zmWaO6O!+OM4TS>f_9^SNk~Ox0z1A(PgjaAD^xwq>MZCs($2Cbliy}9+bzzq=SPwIn zjQ#N=I`s(RgZ3tS9}H;Ynslv!Ds@$gFYYFpIRWahvu{MP8FlwGbkN>|f=qeht?I{-CV z>>40&y4jvtN4yDYd+<`(Z~&YMP~u$y$~3Y&par}HI_Fm+tf+PCK@Z^eWb8~>L#5Y) ze&__Y9air_LYQD|FfdN61M&c~0kfhszLxMD2T;ubX`te%etdGzd_2GlnIwhHF zWXiT5lfcG?sir~v-f^-QN1}5d|5y#K!Co7ZzK6l;*tRY?@U68?+kzR&R7lbdp2};b z*1i|+_J`hcojyJjg9Uu*NF#jACl;Oph#~Fkq|pRzd}Rfn@dJ6bo^^12|30r-thN(% zU|rA0+jeB^2gz(b9bELc%X{8Tb5L(gRi)tbW)-_vdRlwQqhBZ{M_<|5OhxapnZ>v! zvUcqx7VrTSmLJhA*sQ&|b1v<#zJAS#EGIHFR4UHA^dh?8N$VC*B|n|2y^$}#lbKuk zTT;wR{EP|J5^8+`!2b5pfVVLlHkZbfN{)v__U!O zx~;=U29bAb%~yfTCVB`d>czIik)S0{ z6HPX{+;uuW@sS_p85srMjK!m%9UZVtFvw5`h0i0;rYQfq1>_dzz%^>!3?bS`UIt0^ z_jbV6n46Ba@8%7fwu?7Q=PkF>2|K#7eURauSttq2AkkuHN?x0kGWIoj187ko5F?Ie zBUBQ~B6;M#t=oy78H=!>qWLL}_*30SuVcXHA(F!ftj~Xp*o2SI%mjVQ;tg&l5VtSA z@MGs}P!m5exa|xv9Jc5^QjIC{AsA!&5&wZY_D}EdAvW+b*%Vp7=zeg{#d}A082kG9 z#GFRcR|@dl>?5Xa%gS;TX-8}P9N2bg72U!8TuU8^8{4)=F7QPwPLQ&F_@K)cFhRG< zhvln!Cs9-bmawlj>8bIH`Oi(k#P-|8uwY0e$M}QDZ+-vz-cQXh%0jUSYvn4vo`U8; zqv88jcc7s+j-*NO$I&kUFK`bM981`}YJ%%>T(#j?#ZxHWmx5&2R$L z5*;V*9?#~UYlS8ceB0UJmubXxeNO9D0MG~kR)}Z;IqQB>fFo?4<%H{dF|dfUfZAOb zwJ~P}jTHVKZ)@5z&c)nmxxr=ZxDyUOhv_N*9Vw_RC;%eC=eB77w@O&oLMgEaFzu;$E8vh-_;0k;knp zHs}OmAK4jNqA*FT*p2zUhbGbB-wCuNW31pND>Qoi0nBnlY}{ezyq4Vilm55wNtO<; z2;ip8c1+6fOFyfGYb&uNNid7;NLhZ$I&MrLU8b5YEG|`R+9*8F$fkd^afZevi`$aN z_Mju*A3=Qi#sty;s9Aro%5yl(XYD^AYyH>$9YFQPInQTHE^4(vn1AAnj7G!}lzrzU zCNLkHb=H39FR@GGX(!5TL2N&egklmp4O3{6(S=+)W+e`P^+dZpHY1b|CDZ-Yo@bH= zWMChlUJAiDCgXtQO|f%BR}MAnb$xHxjl#-R^sK+3DzUGLLw_VS$P3i~7S$~O{O`(m zTFV@uwJR{?cs7BEXD(R(=jvS>DQQ;?1}_ST-9rmLYV7IVz^3(m428AMExG@ANr-11 zZ50H@_X!=08bx&7ij7 zTCfizV^C7sWV!c#+>S7~IJZ^}CQd?PSI>6_;Ns%kita6q$59f?*cSh^Yw$hq9Q?|j zy7N9Kt-MasP|t$eCussxu(zYO^3Eh8opRJ8bAnT0k_S(oCWq2C%_6P_&qMb#lZ2e9M^F7b90g?qv|X> zuFSt55=bGylqcv5x@%kV->a}-Mw)c7jk3?XkubJl*>c!NyU5jv!cp2~+rYV|@S^7y z@x`C$Q#(=Z#J<=(q+E7%t8y&c$VDxY*arAE@GOfF{4Za{yNqvrKyZfbY1v|^0Aijq zi^F<(%^H%`Ku-se(hygZy8+BqO%2qhS~Vw4H;ssmW2+Cu?H05No<|_b_A1J4eWQqe z3;nSY5FYGl!F2>!P!Q9@ypB*dcpv@EppUeuR3Yc5N`LQ0hG(5ok}*L}lytC!ZFy$` zH9s@!*Lua6UIAGFfCdewOTmC0&>QLD=X{0E+NXFCGbv-wHJs2B7JmplcK%@TZ_{kcwDixey*)-&BKLZvgige?40nOmz4qh$dpTeQ zpwE&wv%i$6iOw#DTGqfI;3>RhabrJ>Xn z<9?!(--$r~a|7(YWupci4B_IOsPyjTQXK&b#s&{3usI^qwxY<|{z}?O&fKl*ym4@30t2 zwOCI7?c50Q-o{Lx?5H=)OSenj>>#?Ipr~$wGdkkFE>X~Z*)r{8{Uo|>Khlwdqvu8j zP3twArwjStB$xfa9vLlfB8aQCv(|Maw;lwg59X7n+;v&2dd*~n6O=O>iNCu5XBT*n zvKL!FyqXNgliVB2yhpsUDdqR}I`vVp$G2wy9B-sJQ89OobW??{XlohXVDqRz#Q(1) zx$?-m;K^USl5MbJ51NW^Sp07EM5N&N27>?|3v6NA_P5*-u@j!;2MtoH#XzvRul^Uu ziJ!5k3?2_oHwx!GvUQc27w*>d=dG{CSpVK2c+(cDB+P;4>XhU|L3w!8a~#utvg|r~ z0&CmWco3%|6AYr1xKNccST4FBXg-()vk{x?pjj>@3MbD;HD1h7+yr=6r_8HzY|?L} zA6oGfTYHEOpyO|ozZMEaCZ*{a`t6;MeN@uhL4!41F-u{-WB;xEeLz_CnPhbr#jF*h zE0S?r52-EZf!RjNc8wnj70f`{K85i?;E2%fSh}tbN1ZQiWt;f zpAplza?X0*LGe1Tpt=pO{v=^P{y`lIq}oENAAEK~w5>2aAjG(q^MQ%hdzuwQpPhM+ zpgY3}q!VFUlMx!_9B3EP5~W=SfMq0IsRHB#R%>ux2{4Lh%(aiJ&!!TCnszUY;}ZiC zQq)Ha&Hi`BbDo0&&xg#tmlJ@p(sh$;NY?TogSc$SxYwOdBfYPQp{%tPHgeHyKi@nn z8-O|lkE`xJMDx1^1$FBQ7xuGGkLBh{v5Eu4v`-8`s%(MOJ4 z_Xk~gb)Ov=>1|mzmwtJTO8RkP{|)Y>AS9ixd-0<1?eV+RJ|>=?;%QV5(n=8Licf$$ ziiMAgw((2V2N(mik6MiXEc!WlXu2W#-&;`ptWgv&@lbILEaDDsPY6XlImP1$F7Hxm z$XQc#SHP^_e78DB?$sG#<+eRf!(~?|Iw1m1J~6!q@Zx9YY8x zqkfkj6ySkY(NoW*wsiVl|S86@ytgG`_D8DZIm1L}0zo1M(*C14gdo1YroG3`>Z8oB+j+CBHS zrvR({pRYec#nnLrCgR(If=y62uNh&L?%-gmcKATh55ddK4fV}=YdB{nIy)2Z}>(E z*jK~wp+321+_ulvBG25`)UkIob3=oHzFnEL-Y?_Y7>BQcv}ue$rSf-WhYx51>ya!k z%q4x?nc!el&vD?MIM+Ha8XsY8%MZCXM=W2cATX<%Hzcv!vd00+c{iL`Ax)i-s2-lc z`maUbSfd93eV$h`FgB7h@CvWnx{&1d@Ge*<319(Lzt3m4M=#$2IyMUz)@Hr8M_0%m z>p>fV2*#PV)8{O1|G2K{(1Ebyvke>49S6>X^1&sO zu8^M(hW96Z^*s7LqCxEP$Z}?vb;U=vZA#}}l9j*&_U4E1qMH@?JcKRsu700m$QMS* z4vft+Uq?R2%hCYaw4y9uBiJ_n2IB=6=q9>4-j(GkP*R}u%0`L0@p+PYgN_Ut*KB`f zr>>6q1h4EI(1!77LgiMg!V1D`Zs&ozipzA-XU6te21anov={HJ-bU>E5wy47$vyV-S^^R0UcI_9q+cx}nd{u}ZTQ===x+7_30Bo^w z7IrCh40aEU>>(Vmk{I@?2D}{*;GuBzl1SvkOdXU`Oj=jjV#;#S_>J*;p>25^~l%g zU15eqDsdDe&-ECD2-e|X)|AeZ2GU-oGkHg6@UV2Q4f1dBV{idqs=N$p$WbZ$b+-7z%yUS@0rz`v)Jd;kv*av<; zaYshSQ~53RY@?G5f`LcB&BUIJs+l!M5_TBX*{Aoxc)j6PVYj@aF9WOP{7Z#wNryDFoY(o^L@(!YO)Lw0@qJGe& z2M<2ZZWe|&DsBY(K?3z5&+0-~Vy$;-eHo-DFY-RpjvgK?k%}EFJhDrZgg~A>818m@ zd{B`A!xVE62Xnz2{SD9Ik^H^FvvUytZR~;ZMS;j|oM)$BYkK7^0P!&;6Fqyqi<@K6 z@EMqe4~;qxGZG;{!=l^;oZA`FMR^;{vJ=md58|8T>b+mWR~G@s6a-5P44yAj05%~r zo<@F?K7Vi$EQkT(uZuRs+6S#;9uow6C}mVn&*ki?yXe}3qg7B1A3p1zWOa*wv3V<% zs`VB}nJ00UB9}`dF<2cw`e+mYwP4@H8rt&ua8~B?s%lJKO0tt%trm-;^)>PnObt94 zU|a#PK2UzT3QrYYfI%x-ooz$}*L$qDetu)wZPCQ$%HTPF{1Gi}$qFvA^33|kB~Z(E zv%FDfd=$=RvQN*gXGwk_`M_6uO2%UTv%S2~6%0to3=WuJD%sAJMQm4r zoUMVgnln+^tQdg73e}#aM+=jQpJ(&xCvZth8C4(*kfD8I zQtSBqLarq#RIaKspDhZ@hVP_WI4Els<#ts%=l#qABUf=R1|RQW95iRrxb6gw75kDk z8`!54W}AP&4(?`=&uzQgVw9pjobG~wWXYo6pX%i@`vU%)CG@(MgYG3$oC|O(o}b)E zw$d5xu=XRsF@PNO{f@T^Py6&Hr{c=&@O{bvf7UyBueLDsrIt@=e zKcy~=4+oRa97lj)&FSG{WQ~5!EfI+EaW@B`U~b8D^sfsZRGJ$)0H~}o(Ev6Rjcc`z zOH}Rxwr#IED^m@0vb4_f0VN%5@iJ%1%KVa3Q9d_HT9_ z9I>?yu5l`JCF5tqZ~6JqTha5wKv^9$JA)Xx)EDcYt=GmO^r(kqVy11^YU_kxRZhyS z=`gUe#1h-7R^7d{hoxWIbac0#NooO=IUuOjb<&ivoYhm1Plt$!!)pvKWWb{rX$%?J z5caZ%9Cg`Y#ZD(xS)ItJAJ(@MZ%SZtev0UDF*9zA+sk?1fq5;<XM%A=Nb=YWlGUapbo43#7 zV@sd5#Wu_e$Uw0l1*K)b0ONpn=jM!0i*9+cDXtkW^R~K2X7P)n+hk$fP~$@h-;GuJ zeIqpI@JpZ9?vDyS*Km{|>?Pym&wdxJ0%>#WU7eVcsdIqWT5(tLs&VRxZG~-W9tw4RhNIiex;_U6(9JGyFf7XcM_}e3{lhXs3q6=#wNV&Ey4lY#$bX1s@q6HstP#I z!F_ovK!F9HB#-hI^#RuSWF?z;PwA!`V${9jcO51!mK-igL;Pvsto^GRq1K)(S=M3U zsQAW0Q&IYx;|N`wtUEs3m|W27Z2x4eV7UnLI| z-^9ON*tq8m(Vu`S=%Pt+&dq7suPsAe*zs!#d)Ldh&eTA^sc4Yu2CS6g-u?^Zu(6^+81xo}&b3yIad@ zB;}lmLc?M0x%hyfG#bcJ6O`mdiI+sBJotRLH1E!W+tCxJGy5u6aB1j@czX(Qcd_po#QK3 zVv0&bY&fLXJ}x)#z7iS>yp7L933uX5#O4b6rX{>{S2FFqn!c$b%71AG-~;9f_*nb7EHz*YQTh&tuHEx&vhPgEYX1!=t=b-KbpPM#qqhlC4*zVZ&71SA$ zEJ-Ih_hHYM|4|Yk+ZbZbgUrYf{_Q|$c^6vSs_fzbHF(SA)q2O4=N_!E4Jhqx>3Zy* z)XF|dp4gzDU^5`OA_+PVV4}iRRiHIA?&fpE%X1Fi@85y*prK^S{h9?x*8?026DFqa z*g2ka_AMwkGV8rsY}`wElvIWEFtZoRw#B$;9&aDhoe46nHHsY6uq zzAI)ZB#tRSIJII0$8zX|9Z3yYzGwAdSE+GsJ$KRAK1C8dF|M+=%O2$I@zJCMWj_Zj zGWb@!oxJj~)(PHeLTz*EpuX-`KRro=WNnldnkn)<8^JHA4@jkcfJ4|yGT`%S@;|A=?q#21QK*yj~G6B_BfHxVSRqTU9=Z`>n9R(n; zSkZ0*fYQJ0;2Z_trnBAHI0RN;?PFSklz}yn?sY6akQ@f7g}=jqD9W7Yk~3_<(AqxF zz^`Xv&VWvfB}ApnqaQ)=Yq6c}&t>i9SvhmxL=!YzVKp+hx>xwMyQ-?S43H8W%h+X_ zya96yqhvYVeGTA|q6skO*){T8g?nGjOzl`7?JuyCBoE-KjM+CCL$C8kM<#sH`@g>b ztjVt5IDF{AlW*d`l8JhFjnYvy0Z=AYZLN0h9rQlsHb7skvH~H=F98`b)~<@3%3UFxk4Imc%N}2`ILVMTZcKxVthLx;ju>(`(&j5*aDk-3}%tz>RFP4R~Ob zc$|4LrlA5q)3Fr<0K|lP+&XW$veVJ<`FnSsr0ov{-%HMgu2#+jV*^|^U6VwqoSSx% z*;B_;B?qDdZY@SVsM<+6KC@48@aO?%n4@)`k7HWxpk0-w7SblK4;Gl<6VRa1!iZWJ zTq{_>9I=aRp0q%>`QgYkNfzljnxI)vG?e+*T?OO%u9GC$+exA@?uP6*VXq@mYx)0q$A?i7BOx_WgB#5t-aUD>Ro>Dd0P^nuT5 zU?l+fI?i*5i0D_#chhIi;QRWyWoeR<+vYfNY1;uMzr=F~CzK4?1s~55r`p)q*?WO< z?D;-U25q+_?r4$)dPngc2jDL|qD*3sRk=x$4A;AITBn|-J9L|x-ED$)DLA<2+hI$jf%GIWmwe7PG zHr0IiGdbkWEdb{f-fR2e&szYBWB8q;_mPI011{4kBmB`m4-PvB`o*{BCt}NCN5T2_ z*yzC`Rp!ry^h&yT4lCi^^s!#^abduql}{9s~-l7HMIr)@oH%BOE)nCbYVNeTIr1sap&Zuwnv zJF<6Vqa@B45O2qJSxJ5;5zY6l0olB<1C!V*&mRNhGjaJjNQ*xtQ#&?EGDNa=%WGRs z6h6Q`ex741%Vh!SVnfg8kUdP-x|4mq=sXywWQl;%c7gn9?SHuf7Ry$FL4J;0=kPlO zJz!VT!JtLYDlMNaJt%cURsEoo7a8Ih40nZX`HGp#W#S$Ap!e&0!$OI1a6bd;o@}oj zlT;KiK)bcne<`eNlLd1aCy5Ao{m?Od%wlmUATz#;v)h_WKx+wYY7nG{0ivDJBB77h zwXc!U;+Z)!cv$i%Jr0^|0JamcMA(Z&7QDH=9JUVA$9(EOqY>d_L$n^N=UPGC(#o&O zfmxt19TXwK1P4n#DKz4FvR1>|<>|*!fN5dnmg44~VF$8k?DMms_^*)Z)1CM*U@gE- zKvZsD;on%K99~wdim7B%04Y134F*a4=k-o~&JI>(zm<%;vnu(!Xu(!v8oRy;gKJn({lY&Ngzlz1Bp>Pxn6i zEzXq3fpP%)dHo$$0OI{q9BiPaUxnz0ouN=qj`WAcT`oiW-*I$)Y=;vM$Xq_ct){Vz zKhS)Zt2L7zy!YC6N>$`!6$e!2kv|y!Ub11^Rv#}5{r$@%6Bp9^50M!s2V!d`NNROC zP|p-d$(hf2MEr=825$X1dpP;EFN2&!{fKtDAOHaX07*naRHEG`4*@tr?xCHGplqWoZyR#1uj#)SykkJVNV0B>LP`=s!eG@ZqxPq24&;vAMJ4EGlHzmt{n$h9hwA|9zTe~TdmS4WRy>u5FcY0b+cL1N z!4cyGTWMYKD)mvg<-F_Q_?+aHSMRBuF?ZHCTvq%yl_Z?0JOEaTPvdK2N$2mnG!es^ zm){zS2UL{-{z1?~xJcka>DDL3>|;CR^o{oupGHcRETSuIT75rEh^$QH%x)MV>IUj* z+;?Te&wh{PS=s*v_8>*BRmQkK71G&!4>GCQ!nRdWR$$H_ehkVCz$_l=yE}NYEVL2^ z{*jY9dq%({DS9eKzw%FKz)xEywp<}%K|VLDa=xx6&V?fGIJ#pp3G$Cy%L?7^w5auZ zpX6@ZnMr@1<>H*+_r7#=y7BE7ztEak+5Vlc-^Ks=|MY*vU;2xG1^@Ry{}<3`yt)$Q z7vFvzz;_fLeBD=kXy9I)=bDxElw}B%W zIEDMwcy#{z?U%;85l1iA-V{ON`l?fv?LEC1{if>ooCoi{yrxjH^WN!o@%`bR7f^01 zEPl7|OFkB_cGBUQOn|mjUw!v6JmBI*GqAny=*3aX-@~<3u_F88#e;9DeB?alIc!%3 z6G>0$nydEdHR=klI68O^(D$;lLHdsd`5&|1Y{v#z$tfC0r<2{b{9YSxsH1?g+yH*< z*M8C@^GC|ZQ>P7}F7P}Dw+r9SgRlO=eXounXm57lyOi`YwA89vFI?zmf*ud*0FR91 zO9jIY>JE;&QLbd<2P+J=P#+Ixv*Yo$?m?D|ae?O>t7Dvhz{C~0@QSBUOR(`CkYifF z`9=(SZ?jeZc~B@k4|S5wGKX|2R;4-K!*<$sVN(3hIl{9S_r8PUx(el~!y`fEfmOo3 zRw7dOb^6#5`sxS~WVcVSGKtN5bp?bH?Xr!I&09E&Dm-Z5`G)&`QEsKMr!*L|fahTa zm|a7xv{Eh_2TyzhJCqJ!YXG*uE6VLQYX=gZk*?gZZ`0~U&6de_OGFwn8x?(zhTpTxgc?c;zGM?j{h*Mq0;bO6+4 zcT4Q)VM{q0&+`+myP9Ngj+1qV^7g*$il}qq(-?EhdzNnnT`7HE*>Kqz2cb_rTKl@? z;`+u9`v*r5c-7|Z&OHT;P5kUS>~OQoAjGAg!p|M3+n@j+AF6J=4SaiaCw#t3`rY>n z-=2ai*7p@Y8HcO!?R=yB-Np-bC#qwtFYwd1pHTA83~%QVJ@17JU|-)UE5GsUzk$ZZ zpZZgO3V-a6|9$xVzwhr#66O>K91^1+3(88e$VJZWPNLOv8t0hG3ig!|fBE`J65f z`Gm_0Z0Iu#VqvW8>->o1#DDf5b^wlfhwy8Q(XV*OS9V)_%>J|;4!&f^XJ$F=H}(`A zmCez*Cy3rfT6XuQM4?2=`ix_r_LCg5jZsgoM>l@_0Ca1E-i?wOCBDc`eaeLYT*LEW z9-LH(EG4e#a|G?6TNlR06P-ysl|a8>>dxc$Wr z#L0&FcRS$2@StxW=5*Tn4A#wcaZFa+Zge z%EvZw^+3b2U`4I~{60Tu$7-4qHoBT2{&O@Ci<_{)^i**JgWGs4#=d%N1|=f$5e!|D z8eLpQXsAMnwd#f&aMr>a=fTZ6t{fbmRH<;C{Wl2|;Z@|H8lU&*8uK zPyY|_fB4`38$Y1;=RY6V_y6U8e)Zk|&#vZg7Vf|P-+cdn z)b~HCqrcbh@t-97|C1Lk26X)&`!&DkivE9C2mYh}`TvvVKjr`Yr<_6mpIF{G2R}Uz z{^Z~PpTj@$U;Rh$kNso+E&RUU|97AOeEeohZFn4Aa`6TVKg z7kTXn-2`V5ptO2eZkNEQji>XRiRMO#rDB$QYugEH0qEMI1h#Iw^e{JO3Egt#$61RK zuPTFc?iQZOD1K^q+W$dtY2y>{(KcTO zn}FWXH)lHik7Yywdb4DXWV|fr+Vl*6X*gpII9Witoa^&YMB(I{5JBPdX95*j;cn#5 z7gOlFrZr~?Ugk;Y-Te46P_a^tQqR>uI2HUT5iqS^o2bC#TiqGq;!{o1tO2%SGVA|5 zPvqr)_|N<^_$U9#|1RDyPU8RdU;hpK{y*^haL!=`z278>B3@M-dQ#-0&-QIYaa+l^ zC3Lhu>F4TiSXAAk{gtAlu5xz(Be(bPNfs(7vh$joCw8yh`f+Ua~<$gUqXdhC{w> zo%%tZ^;2Kjb`8#Omx&FA@}m!{K*=G-&?2pzfD$>$N=NHIFmMNTxq9^2X&8O;glk@* zG(^vtGa04aFc4#RQ{7@m)syMV8#TOt(;uxCKd(cHT7Z?WkHJ9eDQ)b#pnPMhY15@y z>5`5KSdvai;Jz}L$sf2I8>FCRd743>Z9PJ-ikvE??Ps=J5ui@v+@lU=rIS~ZI6i_5 z=-31gd<-xn*Ux!p!8!Q~c206#mi1?5Ba~>_Dh(P=bo05MKeZUY|9}<1{9Nm3=@hFb z86lR}r#jS)^G&lURt3obT0o`0J)@pkV%tBJr-j3XIC}sGG@T)V)^p@Hz1ZjUDenle z*cPm-17&EQZ$&JPmvwNC2g8}|JviQ&Ss~@FckAY0wTC8E^vQn2RaLU{yExRrPUD45 z^XPqNFNjYNd9dD?A9}#eI$C^JH(6oqn0^-?pg;IKg$=Luhk=TEl&9ubNWMO6wg!J}Ssb42JI1$uxpg{NQd78q^uiL`^-7Nmo`vFeA=?n2^Y!3H z;}BFihb;08x^s8l2Ulj1ut+IriOfU-@+tdsZ9;3q?r8E=B6J^sDs@QP zNRD|~9@U`$W4JmOEVA2gQH}LOPg3S7J^2>8-pEA*=_WFLuJuE+VbG*KuXp~2(#Zes z?~D8WJAV27JAUVH{!RSy=kK`p;=zMI{SW;^_@DnT{%830-}pQ5e*Y!DzFz$Fi(ib4 z+Kw(hkY~dk(p!3gq784^)9AtYyUQySO@xWQavI>XPNQF9b!kXnW+G*Qkd9W4i^^n9 z0ZX5|ciR>db&J-vhyl|S#pY{5?F4)y$1C#@#_#wdx8XF1&F$xXh&X?*&yCMEW1N?! z&WdYyKh0iesGRiJG*S0oZm`iBBeP&q;4Yt$Yigi0E8{jhJUyj9^pU0MljEdT`xzMM zt^{kK@LE3hM`RUWYvGvUiL{K`R|&RAw^hicE^i#)MDLFxr$jITd>~{o$~I^}CiWb_ zHp+gb2dtV$wp(uN-?)_$|5{Vs_q(v!h@#i#JdM1&v~aErnJdZ>L=2||Zk{69ZBUYd z!k$7erDzN|en@Z!?CSu~z1JqhU0ERh*#bkQrE;(m>mh};CRsD{GGg8#CE~c+$4fFn zADHTUmddxMYa*ohR7e3_hBQc+m1>Cdy1^pH1`ben5(_3(YWB9`cdGBs-o?kRwFlA9 zPGf?gHvRUQlFnq;@bZd73Cj7q1F-3A0U6ieDfJBA&z;{5iM$9VU2gfLQYVY*j3*r| zinswR5)dpLB@3cUdD5cVjbuQU0?wK|yu}X38d}v}!=C(EF+yWE{D&iMFURT-!0-Fw z{Pf`a_b>e7C${|m$^Y!1!2jj{`seWc;urYCfA`;wU;OkFzJLFY`}JL|!T3C{?nI27 zMEO^sk1^N0*b(`$n}SY=rrBE+JYPcriIb&E@Op^-k=$$Tzlzt*soM)PsBK|EFC%JmU_7A}9Uki|Z1W{fo|cQd zg86-LWhgS&5E2_oGH2NrExgYNiO^RvnxsN7w?{6EGV*a4L0w1l(V79a#;zR8ko;U^ zm>lt|98tnal1$j&LNEJ>h0hCUa=p{ei+61s(Zim8?G*sD`Z5iHmF^d#|jE{nFy66xh&8edQi8hASrZR`T+@^mX?W4PTuc?y{npS`>>KVR=*?! zMNa1PSMnfBwO-mE0A|3eC|k3yMX3lCZvxVBgI*}>jU*x9+dGs{!>=YLESh%(|4bT} z5-LV1!(O5K;zeoti+P6O%gq+&pHyD`dxP~PCoFrj7sO8NYryt)dBMvhvwjSM%;Vr} z_vfsXk@yb_#p_I|Umg^B1ph8zK)U9%>xWb8uF2SzgXcMTzWt;VafR={{2lz2zxr2j z@5R6M=YJc2?C<@f`1zM#`03k0)xj(Ka%5{r<~fB8$z9hCA%qiQ3Nit4~%ObRt8%w6Nmow@fUx(OHAMohkO%ZMI zmFqi7j!x_ryZ~50^o|>eAugZ`794jr9v$77!dqwMF$J~ORLE7`E!(tQ_26`LE;hPU zwBUn+#VLF`y;qnn6XTbQ9W6U8+tk9Q;KwBRdvS0a3G(qQlS`4mI-21mRiVlQQt89x z=)2?IYSjDny?1t-#2=u~R7Z@X%m2SpA36{-T~-QbJ{%H`e&#lIRytv5FXul^4o zzzdy=k;GeI`_O1&y}RxRaStJLmOPn!6JE;tjDXn?7O;k+Ma;LDjk0Kaxey^qh#Aaa zye>1!l@kXjpfs+eU^3&W5?Xn%70tqlBsGTSfGhqS5Y2USU|=l;vJx-Hs038~qagb| zYx^I;#1DpK4be(+v&4@(hHi+rmC=x8=fTxWu5%z`(^uc@;`!}lJ%c!MluF=yl_aSc zosn;@b6?3}WN8IEnRu?>mA3bBZ+Vm*0h8?Vg{smo&bM!taPu-B z=F4!$qHtvxGBC+bTEa)3Q?7h##6MYOKf4jbcVfgaiAM)~*6|M!3hX6u@NqLihChi} zq1+hc86=2RF_580hsR!QW&o_Jwnf`H4TuVPw~R%Qwm8Zy-B4!NU04k}x;>PSj$+}# zTnN)l>?eqX0vJyoBG(Be%9c*$zI73uSTEoFr`MR_4cYN{2+EY z-_^sh_7&``sTS*(nWtjAe2^C4+%2LT6QrQRf;N2TpJ2nj9w7Fe`eec0NB^kC!cF6q zB+rSO8AirurNhRy0ai5!5)L=V{_VDASF93>%C?hMg(Plj6#(Mct+3H_aWc>Qx=So- z;eI1J{Pf}Z`!QzG40ppYFg6VCR$pVcv2n>^6|2koY*s5f@4xbF`l~IR5B~@lx_*fMhyKw~xD^-pktnAcmS})iLFq3*UbIC;a6<|J(Rpg`a=q@U;w`C&(j~gq{H!GGqRKai8L?F8dHdHrF7titPAA-)CA6yG0_>=qigd>es2 zdux5v3!7(tJXtz1-9?xL(Rww_qbK$&;jmU`0=SR>C6Z!TF@?YsT(E2-m?+A6g}F!^ zj3J_T5W$ob^r9~uzxf&WgRk-6dY(VG>wIi|lkSrT{-e9jakO{TICV~ulz_83|APkT zaBrKSmA5nwuAVnu}D3<`8uB+KsLQtB_lBJjBlzb5){wcq=TzL9-uQDN3>{AY~2h@2KT$T zX)tk{d>>{07HD3*KgQu95B$sv^FZ(~p|n8{5Ifq}^XnYo9=OGJVr2u(mNqZQZAPWP zE%d#YYn6fW87TtUOIkGLq_iH>Z{);G>5<4Lh~`;wx^1NOgnMCU9c8Db;WIebPwk5x zKD)}uz@Qk6f!WZ*5_hf*$yu%flHqrf0OZ|y_?)X`!@u+|{fqcBf98LKzvmDAA>aaE zUoXCYedmC|=izsSh7>b9X`)Nnp|#wd6$)8vDQLHAjKmct+^cJnr2hh`7VQRLybH;+ zeo=+c%R%u~Vs3-h^)zoe0oOoi*>aLZMysoI`-Ax9E)GkwWO|&V3A$5#>4pb^HR#OT zD}C8_1L=?fH{X4-7{^jj{{I=yFN`{?5(MBxb zbw!9@6@BI4;xLTjm3Al2H-|A=wkvqgfplDO2Hi+LjRRMDXG}kj{%*R2T?d{YlIix6 zPqIP-FWb5$dl}tRH`k>;-YfofgZC)&GttAG6P!xCuN>tXXxAujd|vLshHU1Yrq0pI z;dL}qGO??X7jLQ^4ObE_>bO_$B10oJAlCfyph135FAx^HGl>i85t2uHE-@VJWJ$s@ zH~v`RIu%QQV{9f;o#HxempkUGQ5q;X_Ml9q_ewV|fH&_n&2C#CxrdUlvwLAp{ccI! zaU1nu4eS9(j@~BioeW@to%%!>5bj>;I7NZq`>@g797x!)Bxn~Skq>6jA_x=sY8h4i zye*%i8T}xRMGC-IfB`Nx6m7@qxS(j<$Y@8xMwZ{ks;=ojhcY$8 zJ{ue^i;rQEJm%^OUkAo2KMPP%pV~BFa_iQVS1eWzka0T6K|IJ)(N3xAXKjqJU0d(< z>XuxYu02~uV>%;X+Q7CBvBx(_DEh}opj*P3^NbJe?%ozI&XGIo3}S;UE9lYdRz}Ln zky{t<`{L^Wf8#&+8~EdY^6$sj*NcDRzw=LIm}O=&*|w`QxUy!9y_aFgkh#*DL4lwz zD?7COn~Q>5{tYpMpUV#18@ioqmA0PBOE?w#fh6@zKZ#Ba4JY`o@QJj`LY5!qN64Bv zRw-dMT6(R$90OH_hB+=8zRdcZgs%d8#;r^g+Z)w=Sf5>;tnoE^Xs`E{_;y!9EVeg) zjK!hOM{A_}hrQp`4csSmPq^qf)X}|t7RjcM+PFidKtB++f1)9(c|6bi?(we@Xy-o@ zdzBfK#N|X>#%f8i*e$BL^TV=NJFyxF9^G4=AO>@Vff^8u(75KwT$B7&C-==?ch{XI zWL!(sSE}#6&xiNh;`hJ1fec*IL9VWGK)zSrQjWFK~|yk^+m$+|e*7gWZm* zR1S8!CgW`2?ap-nk4dGOUO!U0SDf?W`@PxRWRBB*l#Gw)s@~dt?7`lUrwM;t<0c+j zB<%bEEgFsE0?{|O3v8a6`Bkj)99`!VBZ&pp2JSp@wS($dL6nf~L}GnD59mszVn)pY z;C1rg17uvSX(SU-re|k8BPpMJEX$pToUC^hTqW~=S7N0HxZ-?4RsA~nd;iFP27mD{ z{bl^gKlvx|@BVxLK7M+>akBk+6iwbZFQZ>Ix(bViz~9rHZIJ!$ceb`=O)P;8l{3pT z_+)=_y+>>>%M_H=EI+5Tt`2C8A=CN&YF>c|%WT7*OD5Ge2#9U|cO21(DHxW!P5xtl zr8VdW?gXh1HdnIz({1TwiQ(7bd_|^m{!n~2Eh2V%C3fVo9EDLfIUK(JsTTB~Y*yH48_TMM6X}IvZx~8oy@6dDla|ij>Qx%#TBipzF#Cf$Ho{k(pVX%?g zTlYElR2&`q(>cAusGg^JPj0C_z6x=@3RCegV=C(sJsO%b;-etM=$2D|`az%jL5K<- zpYUn1Bzjli1a9jW<@;z($x4Fi$WZyHOm)s?cYxWD#n%1iSWD#XurM@Olhmwv%%OJQ*y zM$e$6F5u}_;3}C>7nlP<;1gS>7e+jcaF7lcs{BNj?2B+8?gTS$rO}u0N8KyKB;OIJvP3!?VOH@ zo)s`zcbr(}d)%EeTkiXLZKs1j+s?S1p`kx}MZ1T9`3N$bmBxck^48cjW?X;&k@lix zuWNG4SY$h4tOeo}4NZn0VZ+(qg{cXE!Ml?b={}LIuqT^$n?|SMGH7*a$Z%)I2D@RT zlt=3g4e6(JA3W9L8a9S+Sto*X)Ei@!^ubA-`o<2EuP^-K*M9?l^{@UVyx%YWgTL|D z@YA<%`2O`B&vQ(8#OFMiw=LYYKV`bxzZ{JfG8|pi8-mYwMoy%@P8wi%Y270~@nNR| zsCkwP7xEQ*WWa2*U)Akv4aF~S4w7yCj~L6FLy+H_j3IU8i3PTp3)^=Xk4v(l zgvXN4Ny25xS$@qM;KYRg{c&r!`Ij!vp;eb{krM5)`DdFZDAUxfHfTWETP?iA__FzI z7vGf$jM|JK)e=tdb2ISk3VgJD?YeYjO|RAYjM7nNj6)qfAdNrkQl+-^tQ^LS7Q+=m z@?zF&XR-mM1$#hS(dncWl#Lf-+n-q(?b5(QM|aMijl>&p3b`hxFwTg<;s*vh!*I=)JuHmH~)4zA^MI={Q*^nRe8-vCa1C(fSGr{)rKilA~ujWGu--x2~K6ZcoFt zZw5)SW&-)Rl=yJYhSA?BTmdI6;!RYul9H&n-%$#9=eKUscSjg zA644X&2Y8s2-q0*ILg*t2g?wx%h7ilc$_*Bec%=f;qAHE?^OU@^_jG0(5f{a**+Ay-q=eK7Oql_ zV=yWf=R+0OP-`VgeNCX@Ho?*9ad7>7&{6c!7(nOhMMFR`tZLA)Lv$&Wr28Z1tOiC4 z%f2uvXFi%|PU4ShkRNU*b#jRxn52;%$96Ij`z~rX%UUStz#KWgc1}tA2RR01X%;R~ z7KKgiV^GpD%NfoGze@V)ce0Dc)zc^DGy~?e7duUn|DS)%o)&;73MUCFD)Kc(I+r1L^ER-@@glgC?JI6!ifz#l%*P< zjBq2D|1{V|vfIEFD4=oc4YK-tIJ(u1tAs}?T7yYZB-M%^9fx0{=Sp4uSrZ)PyU>fNFIm zN_Se%cGHw~-YLzx+wbEWPULC2hvE}rWV!n48cPM01~~f~xq5G|3}(mD8nO#wE$zp| zX=Ac#%#D+sR~joHW+EHNe71DQKHb=vajY22o?yoENAq#-#dso&E8(|)k_3RPZuTWV zuf~EgdE#&zt0N4NkdwRGg<>!KB@2Yu+P@`xPkm`6c)nIFn zgM?-~uiF-JI~le~B8>w+t)m7dvljerH~O7St^b+4le2?zYH;DZuJau+e;y#w>dRIs zWpGEt%=7kwvvHugIx7-fW0))G?jgPvfZz0w59gz6ltuygyA=WP}{5{zgxKm>W zjo7$q&Dx{eW?~TikmQ%YdH4s~rtm3mA^F&uFO4D#8%){y5rT z))_ultxpP)fGQ4;FoAishFhxY=-7k4b^%gN$`8z=E}A_=0xJqw0m-@R>Pgauui-w}zCr3rhY9P$87JrM z9A*e!xdq71tYlO6qM^IwQz_x*xC0FZjPy>+I*b041Nt{~y}KrvUJq$fR>x&)Gq)fu z_DXHXL6MHzXrkxurG#f8HaI2R_;;eS{H1eVqz~A?mHd?K>pA|tWK;=N998Qj!#OS{ z-CwigY6u4=P{=b7K)wZ-qt9z@&;|#g9hUxD|`eYQflr(0ly^US$VIfJ# zw$0E{oL#Abh5JXHg8fP_{F{bD9XN7xVAF7krlS9}`%b!e$1CZh|0WI?HPa8q zmS5@2g?(Dm@=6Z~SG&t)DwcyoCEGq!j4iOw2#`+qpq|F_FhTeBMc+62@jv|^{g2To zeEs~Lx>lMWf;Vf0*D`+<7M;9{7%q9!dL}m@pU;1m9<&FxnYO``m{Ig~`+LXFmh>wD zh$O;*S~5XddhHOlI4FPB!zLrEG{p!@ntrU?>91uk28}*@Eni{cqjnyUJh!^{bgjkq z`<)K_^nuXBNa}=?iCU91?ymUM;|~^+h;6UwMz<`>W>iZa?f<%1xP9dAzKYj{?bxdA8}!ExUii@J=( zcUAgVDh`65#SRXDQ!s~i7p$BYR+mSfWtr$bLkOtCQ-#;kvYgL=d^Ea85o(UE@Mqdj z?oNnrDVrg!cz~r4u0#m{#D7z%d2;!1Fw1- z3G50GFD+X44CZV_4qZAgtjb?4ucGDD-V3~1XUs#y=D^O4f6D@8ufa6~p!QU3PFQ6DD6Rc{-M+pY66<}ZGdBFU^f*b%?^zbDbd?(`tUIRFfgO>7;7pHx zZD1=L=(Ym`%`0d;E!uVM*pzFybN1eWh8?4dFt}2%TKk0KS673!lbkZ_S3vEArsLwB zJil=UM8&RYUAJ99<(bm_ zETUOgihHR}ItmOu+l8-mRoXdaz4H){lK8gnSQY3ETqo2^vJ+hrV?m6K9grNJY7NK) zrkLY@6=t|6X1~JGJ3smpU;supvmFB^3Tz`wE+cHD_klJ{e5T}l3SL5Onh+b|sMx)s+(q=X-@F!X^cpIyOUV`)d`D~|tB z(ToY3n$H=h!9cAnN<}=6Msw|ZNv1gOM^fVW z)^sWtOh#5LPbg1~8DGRQHStCWEbdA9`l{$Q_Axf7n1F5Tgj!Bb-##@7Ar!lD?1(!9 zj@Q{YE00Bi*$1}3Iqy9T8_6EQKmMIIMS?0YchFg0(8ZipF%f3qjC4#^P3KB)$B9WM z90YUU-wi;{-&Tm>N)#u`q0i~hM~;j6#I`o%Y>tIB4rN=A<|>n_nlqPN>=Gn9%LW_; z!FnejF~I>`5d zUA>A9uRa%NpW;e?Xbo31XkCkXtB@$s^)VDx@lJ+;Ax^r(r8z%jpgAL+r;O&5<6D{B z9;3pjpYjmdWR=#oI5?7taBH_pkqr z$naA~MIzJ9^yT7x-@I?OcpN;y2{@pxho|Xha!@=wBbBpSL|NuK*Xp$@j4`O=EZ{tm zRm)?tldvJRv4_1GIRU$^+K!n9$@p#Y|cL_qa}BHPbF~3 zZ2_iAfyv&yMW0JzuCqqRtLxjJ$yjeJYpaC?HfzFKS39av&2y(`KT8Js=rf;Qndz-$ z)@j<%p4V1n$U#N^CA)Lsqe>9{{XYP4kc=&s1_o6_7i~tEG0qy_B!^tVw^oAJfHL>DX2MQecP2+PQ`r2t5evxi7ywp6i9gN5pa(hsSyM7mbx-x`U zxHR-CaJ{X2!sm6ub|pOH+W><@@>iIQ6-L8YIuLxH z?|YqumW$i(O8Tzig!b<~mn5FiV5gX5{g@7gg60F8h)4~ zh>8$C3L?5`!37;azfX0vQ|RcU1g^Q%+;`?Xb>q!4*Zd4X13aa@*DO~WM~x#)aDLi` zu?OB)r2=}kBKDXKe!PLh!0L!U)kkw9UKLcFon@C73hKgDa8#sARi=+)5Am~-9?OSy zCI-N^#(vA_$`M8pTNiF>=kEBL0f;&l5huFAjwtWWkf&~trqk^;>?)2^svL|qsT z=Dq%H!!2TL@U2O3XR7!7oBC}XQIX~VK7*X$*xuQ)amJ^e#7H+VT1N&(o;IdkCBQwe zCWx8a0p{46egD7;bOho`j>BhPKPXHD@2+u@ZEhhdhd`6;2`?x42=P5=qNEkObSQUK zj9tmf^AGZaj;^xGlmS-JJE5bJmFCNujMsCH1Q^DDO&H8~_pU zoz+v;Icr(oh7=Lbq8c1?Edz-^lholPEot1-;@f~a3v^%RtBs=<;VMqO_iFj>dOxzC zC=G`Ya<{TT<3>#CeYdX1muQQtAJKzvfHLaFgcH(0aKP-AD;V$_mA&nuD{LStAVVk0 zKX;Xk)`NF0vzp%0V6J2FWd*r)pteKru_s_R&`RorU+`5wXC);nf-YCy*=aq89gCC+ zpHuGJX>nt9PCSJ7PA^TTC-r-*)_iv?bYvz4pIb&UzUyGJxaNh7M4y|=-7#39@e0_l zvuProJ5)L}1=#v7xb_SM{qC3Fzf0$2Oy8>xRyir6sd)keUU5=%HXz-YK+vxch=d>d zUAsz`@*V#tkiKv`I^Z+%lDAo839yxiGC|py6|u3+rM0ob;vl z-+njyERpHJ-AR4{6~6k4D%HRy@Ne3TN@dHA3WBqdC0BWRW|g?3B*XFwS>wm&gg@h6 z=uc%?uw!XVkz=w{*`K%5l7RS!=inV$ZM(NC^i1I1<#5QzwcWN)8(@R)v$f`5q3t7jFKR%1A zju14KPkw``)IF~ID3C44h6yJK{nS6x+}hc46#ZUq-JMnyXMa?EIo3TkWhWPX1B$Q3 zvyXOl^N3w>I54{x^{ONBCGY&1d&iN^x^0BI(8fm$X+0>}MId8qMOd5!RCmK&`N;hK ztOUgQut7VRaMG-={5|`{!rjS{_h7u@U;lEDDi8(O^fq z^O?Dxpc6cz*)@j(GlouL)-{>b;V0`CU%LmFfYAf%p>b1s#}NrC))nAtdj^-9zDbB( z8!A0Zi3AMa?F+nWe=6_>j+^BvzF77s|BDO&8NX|+kw5RQsy#nt57l&0guW1I*OB+J z8BVd%mzx9w{jJB+MVqp_+oBuGe4#&+e8(yM>Dn=gN;2L6&Mg(DIx@leQN9!&DNI7^ zY+xm}Fp28Ax+MY3gvY)Ta4qzfXdHJ!$m593hTsdt^v{C!ceur42l^v-Y9^bPD|i+Oi`6Yh4&M% zj_4QaPEBE;S4tKjDX^huh<9tiIM>w3BC-{XOpbm#3F1eh)4AY81Q*eBuB`Qp1<D396tGmp@RM4nsUW}bt z8@mo~5)z|ucrUI15vqhxj63U!tIe6m`-}YU9sM5ZlObGsJN^)~Rer26x>?A65Mxp3v;y~sKL;CPG*)Q>zMf~~ z4!Tp^0lkt@ZTVaDup-)6dS`Or8-TB4%lf5PB=yiW4xWQHTQSSIk-K-O=aSc1f=BD4*3*pHpBHC zWvrJ=N6c_*hIn#n5_4nty;}SDazL-HSk-$R1b$-8oYzFLi$J+^IH_WMoM2c<4LRsX zcxL%+xPq0qy*NoLENp~GDx(n|uph_NEKI{VkED$6yV|(D`#Ic;@_P#BLkFV%f{FiFXY>sSV z?40QV{UxP7?)6w=j+%e-4hJ@-rEMA}IM=Uyi$n=KlOS36ttO92&MzbEYOC>q|IxcJ z0ZEqN7SkRZQ0UAf0D$+%$rYFeTjkt38AU%v&U;^Ec7;W+oV-=>p)HTiKr|R&Avvp% zVlFlMzN?Zt_#aO7rkF8s{Ja#%+WIYGWRhE>F86FKidgnMb*|g9OtlI$!;IL3?|X3fb*RnlFUr|5yH(bdvC8V?>O20W8+oZvOCl7bdK8IeszfQ9rJs zjV1QO71`XSzkYW6&69Sn9vQ0|-?_8O*6;Nlo%v(pwlUXKE~*=zKX?GiS^;jo4 zE!`X3VlZ4VWU3n$0Ow#;AS;81;Q-h4D0RU|AFk~*e}BqdBcgBS0f~41v+aQs1$VZF zo^Y1RS-q0EK!bcVM)xSi+N1Pq}Ow19!DOL{j8e!aVpsQw;l-W21#{g}5 ztYcoH|Fz$yYkw!yQIfallayn&-L5Euq*)a+9rlzQy|LSI)G{Ud8Zd0sfDCey0dl(q zdOGj`%>A`6fM`vcR63#$qk%+Qfs(+|=LHd-U;UmhySGE;60#%{qAw8^PTIA_+f-wz zzHZxkrUFsJRMLQZDV4D1o_VajK+lQpXeD&SEM5c>E1Q<37duPmEnHQH(o!uDFFpJT zleD$gTCc%Z0JMI_fBAYjRiPrmV>D7ti?iQyemeB^=Zp|`kSAEsdXMDC8Ml^pCTUK& zGMxuNxYtxUT=|u(*kLKmfF1{;xw!(9@ac%g&QGc`DQPM5JD{!*qg~O9$rYfuV}**~ zA#IaCT=lZH5nBV&o)KA2PA@#E=0cfqWAcD=+bDQ{s4M-0m%yu-rc-*Qs+Z=Y*fc|7-w4#tq{eX z7kYVtI%%gN2C~P%l=auLD>J76HEoD(yXy6|;;RauENiqEPE^`>``yNd8{J5%px4?l z#|^r%l6)1J0VJ<=RDr1&^>u|ty6c8rBi6A#n zCqq2TavUgRBZF2j|qGfwj;i}c2o7I%xu9vL5;d|Gbs0y_TJQ_by+ zrj0XReM=VTFi&FKy!BiZ>m~o}g!%+Po%i2sx=Y^NYMR7?lA0>*C1JPdRcBS${I%O` z|JCs=SL5P?#SSc=pnxPC7j93xDu5)qwY~Uav&YhvW|=^1kqzz*bgCXUi6Kq-D_|C3H_YL$u(z9&3Wfx9}_XMT2XuJci^8WPf z&a-qJy6@yNt;BXaMuGoqkGb=;M)y?#%H8| zP6yRvV-f)4CK-t}09V-x>4^6>7>dH0+b|oMxhamXX1y6E=wj2hwV|`_PvL9*lU~IDCmxA6+kDhXQj_bzu zwT?pQojJhpt{LG28F58PYe_kISDY!K;IsS|3| z;SDG!OrnA*z;d=;+3#^-eU9Z*sYZwpAZ8ZnPX3}M)SYmY^P>>&QPLuS)_uL4dd` z1$r9FhKZ(5QUT$ilRv;w_OS-Mj`^zqUJBJ390p!m$i61~%isH+=S-V*fFBvL191aDxsTO+)aP~p z9F*un_e;iI@lLI z*!j)3m$O-Q)~EFuF~>;HS$4af`BRS^V z5J>)x?DL406Qe+!;ozMAJ2-Z8Yl5oA9uQZQC|75?!MPfk1d`>W!pDxo!lTmWqu=Tg zjHKt|B$RZ(*SeX%7nj#zJGyA&7_T6l_l^&cv+nx5I}c84%FWehf+;|br#Lw8&cM5y z%FHAR6Zo~RNR8}H@`(wPvpOHBU$qu|KK?s;yocTSNLpm04j#*!>?W#az^2cX3sZ7k z(6!9?))3i&T268Sj2z`UQ~|I4TjamRDmrDXX(jV>Q;_A>atGRXE%(21?hHcgMqPEEbs<-jS}v8;32m`;f;2m~7zCUM9r@j! z2w$@_h|VHhOF6FayZu`6vB2Xx7U1h<4kgV?4i!5-;t^n+%A@_AysxDQ`HT%*js2Mf zQpe7EFR(0ljcdlmeI~`oc}yqYIS0sjwPi=@YA|MOCy7ZAN|>!LrY0BHg+|G|lK z+ZD=?0}lH!D5RJ(^B9so0X*C*{v-EQS`d$>K8T-ae3?fYI!Xn< zPf58reP!Rx-?a~4DcVuLEJH|u+%^1wWwY-Jyn5Nc4jx;so#?+P*|^mZ0jw(`$(WTN zz+5Y==Vh>n^hCaVWDTvNQHAC#1Ps=+yS8+V__)HtN73(S$YZrJyz_t69E84dX~M7_ z_jHcJLZX(yunkAH3H71t8CbWZ+dm2JI=Rr$IeB=1d;)o1Z;Fp(&Ln#zyT{ha>(ClR zcNT*bSM3{mq<`m3(%O4Rc|fPd#&}Tj$CVtKA#Ks6b1>EQk#b^jiVuLDoD8)LA9@wj zq-2lxZ(dBYYmT(rPIc_UM_$0Ih`N0IlAW>%rdxUfIH9tjUQFACGKBvrZ$xAZxsEat z!G5c;9R-s#Fe{rfF^hO~>|@oUuD{difTHG{_0qyeo557;O2&>_?c=z2~}b?ALLicd?yO#P~ZwGxUeV7SZ<|lu4GZ42eHme5bE+Dgld8w+p%p z-to7R9aq`IOT|I^9KF0Y8Df9GC3`cFOb&{4d|*!@LoY2%vO=^ktN`b=$7B)Pa0!FYzQSBs!MV+!gN7g-$8+ z$TA$r4Fsms05fT8XQ{o4vu*}K_-1^*qSK&8=b27~nxC<+(uWLAzvN)9E<+5Ca9Q$x zgn=cQwWw`$cfzV=K+$BR0|7vWWd0PrkQVr4DYRRBv-mvbe&8+Pc5N0ii+l3Q1V$I~+)%8M@6iCi7^APyuRuE-d(EyTsd$*I^ikaNzp z5;@UJ{qNd6GE*lJWM%lo-V#SdFYmWIl^iGdJ<=ncrjkxp-1F32A6{Q4kLBxn|o84^d_(T_baQ z8u_kQs8lsYW<688)$=<<@f33=cbgDlfv_I-5_ZhlZU}q#2AbKqezI)C%7XGOM_=+k2?|Ho<#$6_{w$30$93NeBqHcno zvH88|pR3dw@DT0zHPN*htnI}N|GY;EnrEkY&!LrAdf^0{sVx~xydi$wPwASZo#}YI z5hSU%6Jg}GBY@BdvEkAw^ z-tK?;5lvL6$PuP?qO1~bxF9l*n7DBEQE>b;*RC$P5;g`GTr{{V>Ax{7%GK*zGe8=> zijvi+t0Z+>_kih!Mf^wZqrGj^qHEi)l+K>H)=dg~CmR&gpL6~qtOtM82m=YwA1#BF z>?`BvMc5*auycPLP#0k~W3@TzZ_Ai0QM8fk1yUAn3(+zf!7Ia40kxh1O$LT4H*wtC z!$HKbR=}b)OeRT`RGK9MWoHS_&>$JJIa8)AuE0FkNMyZISMN_nDpxX@1V~@hWWeCe znhhe*{o=U7>coh^cLpY%0R||Lb#^$zX*%?c1Fz>K8jQMc|VpVl11#vstc;Mhb z&JN7O!X$zqL)mS$rW0`d{aQNaziSAm?s%na754BhXs}c{n_rD~OP=<{GkiBj$N@I@ z;{jy)zFVQtAI>)VO!mL$jIx?nC&DtVnGUYb4qhViWtmCvZ{o)@k_4QY z=~Dha^V^Zx&iaOnvyP5j)`4l)DQ@#n;gI$Cz7NSzPtS-!R_kM53+DN zNw?T<@u$Kw%b)Nc&>8E&dn_368PmCvN$m#0&UC5)!1Y1Nl8%V)%RZU@BWYO>X5eBe zK$(EI(ZD&YI|*qruzk&w{O-F^iRD2Cbb51nC6h?8I3+l?-AJRvRR2y{?zDaTQMGv> zjI5KD@XJ~^6o{dKTu)mH0IZ%@rn9igZT=d!9JE9p>8yw!<4@U-aIwTVtCeCXsrUO% z?zN(bd_&dePJm{fdH)ULqHKBrGb?GRf8+zvdube1JTemxgSjN3?9j0**%7nTNjqa& zhUKHk*LL!=vmw*YMmk~{+w`GVrngCQ!w&x4@9pvH4fkB56WAxu^3dDZ@FM-yz%aSz z1UVOdFS}iUtlhk>qj0H#kHKkS9{+oHG6q9CJ~L^BkwFJ^=w+fLXTkCk$DD%2C{n-l z>lF*#_RKE(v?{z@#1DLopOWpuMICC7hd|@?_gxw1S_gi59-{eB?!K_yPGU>8yYzc^ z40gM)J3*`c)m&}6>;~P88rd+wSTAgE+S6kieOecvC^6EV?{EguU9sRKL968n$M#61 z@7Oc?5t5}>d}^TY6WAE!oU1?`696up_?84FhetmfBg7paA4;^04b+v1;M&+-cQc1= zlD5b`ERWP(Cq0C@!k^;=U5)8+cVw57u;APzbOuIJJU`R6j4T9;H(J%GentUiDeymT z0n6r^N=!u_r=c8-wH*O6uHmeyrj>W;4#@$m1ZRG899kr+LCRc|x{Li@`Kg$m9D%97 z-U_NL^kO<{8C5T!4R&hKU>!O zwUsHg>(m%Dy?5Df%wIa-V8Aj^2?a4#l3iA@JWU@>&u{a6@7+fa5?C9cBa@9B6;V1e zVVY#ZO&6ijk$$KGBeL?l#}Zu;)bmV@$ohAZta@-0$s&m=--FOlVhQwdCS_njKS_Fc zz#cz-rzz+-3km>FK(N0he4N;Gx*(QB;1@_DC?E9-IPqd)xJ#s`3xF6@D+uHN+U;ja zQWnrtv21HVht1juueZx2X$xmXNa6Ik9eaX4k2%3D^A7G>G)66a;V*Ku$c|`RBO|<| zS#!^pHCMNa%%SMo85S;YthNq0WBY{(G{gu-7HX~!Vom>Ho zL)VUm?ed)~ZbDvTUAI9tN>d|Xu+IBi5xz{3BySviC+lr}FYo259hZ)b=fp%teg3&k z-wuuG_%6#PqZ?fDsza#Cb7lrcvrA_s@v#1WEyuAB4E52LS+8eZeJUL@FFZ$}y49_w z;Lb;%3UaPMC&TZBJH3RPS3}A0>e;L!UI6VYrUq5ZduIj&rzAV_t*5grO@DN; z!TY!D$sSHOBBl_62{Z+o;(3hJ1UJ@2@1<`N&&CSBbUKOnJ32l=MFle$`GRy-Xa+YawDx!YG_Xyj(yJfH~#0q=eLh-qwK^juWcsOY#)8pt43_kg!Lb^_cMLwddZuUtU(HQC#bT0 zTK>F+XquBM0eR9Ye7^(iCftS;|ee~HrRl{vNafc8K(%G@uh0e$2whb z@xeA&f{;R+q@dQp=aq@`fLzW)=w*NTj!8N!^4Naq>OeTj>xJtGVzz3%P(s+kl_XS2 zYfD99ti4FSY&)WZX!_d8!8e^z(cxR1(OC z^f>@LGiv`c!!BcK^uG2Z^i%(SW8#p!Ez30tekQOB8KiAq8@8LtS^M9a?$14u>1CxX zO!dbBB=ocQpdKpMQ-1N`jGP>B;#tlvbqI!quA;hm%m%;W-0$NE$3k2KXh5Mg+4Okw zq$^3~yJD%-ZcjO-IgX1Twy7bWD7J&%R4AMnaE9wx`Bvq^f`X9|U+W-gkJRWSs}x0R zzOD1G+I+77u{)KWR>ps__~LYARg^v$2WO}qqgMdiMtyq&Fw>Q_2@2VQla&|*oEC~uJ>e#Zmvme9-ZjDuGw-V^;4E6nZc&yAc-+hC(#D=yM<3MpiUR9+FM z3UwYc4wb9jOs>g9BH7Y0AqJ}|n`&3|7m;P~PxGb#8)TR2A{#H?d%u54HW}!gq7!i* z0`rk3?$%-7v+M2|pAkFVsoYlGB!g&Rln4@kb3NvVoR-cjYORqAwRo0UH((Al@6RY6 z!B~&VI$FU^M`lUS^1-(D^(VFDpd&WE!NFqhOtz;H%oW>ZsftmK^J|GK8~oPId=+D0 zovT{FZFuWKPNY~C7O1xtN9>S11WT2V7}<4ogEFp;gMyqiRW*ZVUcVDYGUDZ|dls+%(<`geD$XRsS-h}r8`Q=D znQjaRQ?tiOS~<;TFbAv0!Xq?;`QCe%Q_4grrseY#p7YEa0nLLbb&%+Nb>l2|c5Qwm zIW&e+YhW#04Z#FZv8j9~ll-m-v%?Pe=I(U-C^KW^lVFRBTdlmf^=;WA+d}Ms@Zk1? z8!t_~)BD1*a|X+dnGV#8Hg6KdNCJY_S+=@HYylA4?bHnPeE|o2%~zhk96O-XcuhOjJL4O-E|Z9^j+dy#6(jrUcUUt+OKO1AzSsWF_^PD86JeF0CxswI z54C9$;VBh9yjRPztpfjduhN{?Sl?M3pIgXX^F8()DqMKY`uaf5ooV}FD(#{v~IwNeIrhC3x~+Z;8D8V8Cs zu4FUs<#SHWlG{fF6X;g>!~dJE+DZY}^P9-i8QiV^T9-_7EI1Lin>6(b7s~dXf~uTE zz~Ep5!(dacA9SJMc8VoK`J^+oq+V+(FlhnVVz0U2Zk^9z+ch!GQ`tMB20_Ho_=uko z|LR~Dd43erb*|#AV?H%bgjxjGB_?7&bZ@=mIQpF4oOh9-?8#i@eobqe6v>$o z(H`SqOR4T+;*=joKMsxa(YpvTta4JPTP-&PKnD+Gl8o<#s!b9A1@<(u{2^DWeXYSR z%UAhe)?T}$G(V5H8I+o9bj#DnfWmUXZs*ycixC=tKRh?Dn(G`{{YWzLp3xi&)3Mpo zS_HHx=gx_;~nV7Z>hn zShP#z3of_Hx$*^++Bym!vrhj_Ih(i;^&7+jfF{Fk$ky};g2KzqM3%uSg~m9QGu zZIXw^?(2R@NR9x>2Cwq-1wG*dFn~-^ai-iIF*R*dOD>uDcPpLV2?rb)+CqF47UcPh zM6E8CB*yeC>znBrXWkCACE+S5aG7{GYKfbdlv$DI(BQUxZt^Kr=#4K9JcSEgc}9Yj zZFq$@9?Sz(ahcuKI+8S0RyhGeQ4WI#)Iqm`rC3+d;KjpvCiGvU5RC=bc-zUO%DNqQ zUh$$#x7Kq~eb7D&sKYk7?E?@7#zn}qU8B(*XC(YD9Iiab_VHa>LQx4vgm}@gZ zJPP|uMYeczH|ZEu>uWC zN_U=Bw*6gcpEj1BQ#|Ji$XP$|teue?3P+BoNrnm)naMd_962T@NuPoOUt^7Z67$%B zVK4!y_IvG8QuypNW$4V*<9PX#zK_B9&kT)NKq@VD5GI-b4gkFO+Sjzul2pzUe3d z$_vvwdo>N}L)QG%mOYzmEonQT!Xiai(TDwaGhFt|v7QIud7ma*;*JPadwzCe(7Boq zqno|f+7*3urxv#CaCYOh3%d9R`^XE!ir5Ssgl1KWBt6BtqiX0 z8%p>+c5%|y`68a<>u|0W z^?@h&PKvMs5@Q0iPY3M7!pZ8{Nw7RbK=pgy2VFqDV^kvVb~N)`y?q(h25`!i#hcqrUlH)bb?=QH`NE1uEP zSc7b;m0d6E9N<>R$x%{=uCIToqu8u+L<&87o%Id((z#QECA`CxRB{k2 z!vWGfnE{aZR4BX(=0@H)AiCg6|JZRe&w4j&PK3M_CyCEv6-rXbsTazwpILye;)%ai zfGvKy)#UgT8fK(PmBc^-9~u161=EJEV@Uj{hgo(Ed++xc7M8uqFvaEc&0P^k-_`Ih zCEL(&8w;>7V)+`8%Syhs^Lu_@NfCP;?dLH;d&@_6+zZDfzk^@4ChO?Sax<(eyBp1Ckx43d8(5mA)@fE@K2#Fd}5e|C5*%i~O=d8cDC6arNR!>zCps(qIOFDp8QpdBz!n2}{ZE%p8)Tv)% zK0n*-gqrsz?@sjf$+p}ZuV))77{HCC%%940R&IQMHc=|kijG`3sktlU#+>lS-gpGQ z(jC~accC9R&^B$`&uaM=dOtJ-Je|J4ykPuAcCGjum7?JJph=I6X-H}-fi{Uy?W?B4 zfT7^><&|V8(Scsd2?6`jq7-C1Va64cXNH37A)Drpd>kJ$FZso7jFtZ|Jzu6-jSOgw zCHlIEgd}myRKKT~tg#PKEDk4ubG$Cc51kwGrX~0!E@t9z_PpZ`V+j{m&h3uv&^t00 zps984+;JD{b?2WThGszW65!WjOuQ|swjMhvI~nzga9#@oVVEI8lHgMeg;N3%YT;T9BI$<7!-Esm7z|A>p20jkx&CS#$;4sQG>V=dSikUlpX5XzR89T?ZuMms~Q3Tzx@P$F4sdlHj$L4y^-64T^Bn7%%O<0DBe$3l5P zK0;M*wtUwlHMM)ohArA0n!#8&+c5!GblOkxyZjTwC%`0bnHE4gAEaZEK_#nLZD{nN za|>6idaY>L8=td2>hyZ`*|Ck1N#jI$Xsd&+f|IhwH2}QcN;1x)LDFvlk8Pt{g=K0c zIaB5fm5|qe0ev1Mp`A%gm8DuKW^MY2lP6RJ%m6zQkb9QXznip_uuR3xzKGtHYbyy# zW9$lUW@WRPMb_)k`mVBaIr^ma85fh_u|w|Xd-8lsBOK?nEmcETBZ=N8y$bGPu%q3D zg)b1c$=Vj+WZQ@D0pWQ2`C8IlczY(qNXxTDTtq%V+JS7-tpKUnIU0%`;NPpQ7X>@< zjvcP#iy#0@!t&@jgQFraobU}aMMB!Z70iT_UY6%;`BgYvHEizrvqT%fvgvhD?QTZ} zY*h-gByXmT{3l;!yvo|}?Liz?_j*?rJluOz#PE4+jtZQLralZOJ%c?C%1657vde~F zC+teTs`wiIOUBT1WK4L4suhTMc$<$QOi`eHonJerMhtz|y6c=tVCe1bZVV+#(lMN* zAAZ0z+U0bYok`GnRs%&sC7RmrvzLm0eEy_T`k>i%O#lW_cda~)DJ(z9BT2nR|AQVjIcN|dZh6u}lM|ib8>xN8DBWv{Vmz@xDLW!C|U_H1D$Sj-L zFc+NtHb%a#9S!N>9mAP!o`t0-%=uFpM?cGBQew1@)@6JtS3xGB(z6wEj-ru(lMfBl z2TSdYFp+a-jkz>?u01U&f$3s7I}JRxLD}NqBl+S4+M>adGzYwIHTnhm2V8cw!94Ge zXBd)XWeae^*40oZQ1$&n-s!5ejkYUHcJ?RQ9UBuAP1R+v#k9SydfMTaE_Z9RNnpFs zTQ<@Rwf3)s@M+5v@al61z)h!ul`gN8WpO~mUmRR@IgIcm!8K?Roys7o$cCt4r`Dh8 zyJjeit)t`5YI}51kT(v4-#@)qKB{AWj1CB8L{q-c*Q(J{99=6_qP22bkwMdZuhUM@ zV7KmPa1hqeal#f|=Z*;m#4Q~%1Evxd2rk7Y&bpMuZAJ^~ORX&D{=FeB{zcvh9 zA5CMy)jJ1;D0P9ULxH${;A3zkjb_`lGG^FaWcb%k9dUqCATgd$meyCT z>cIpNYfYmU#)FL#XX8x1)6usC)TUibwld3 zb>^ap#~wcI+9!RWl8&4J-;;3=Id*ZWdmaIjQuyyioasF z$e0(jg1UeFY3sO9vm1MXS&?FtqXb)Nb`fJ+46gIl(+TRgxWJ=0jE^6?*&y!PPGoI@94hNqzTZ9E5C2fntY-0(CoJ^i-I5oN9>FF)TZfG+aBS7^1+F zAWI~fY*yBgOgev(VI_XP9jyY|=cMBRj56|1nx@`G17fy|!v=3pv(51WAjyNdyW9qV z8Ks>OhZGcMYSAgX1q?GXIGktX@QDVV}VN!ca z{<>{{v1*rnZlOwWWx&R?-+_+G00e;6otALmk2p9-&#+U=phYf}-xVVvI<_-{(h@ny zr+cQc%7|B%%Yl4T)j4A{{T|q%txR7|tFV5Hk`m%DiKB|7D-Jupaq=Z+v4D@ng&=RF zxv3L34vicV1#r$v?hNdNzIuZb8yZSOk(hZ2R3{rcCE+Zp7NI0_V1E-kN^qd+Vu6=` ztw7qx!e7!aprhw>!@+}%Y00>>5xP26iq|Ml+(3>!<(_$AO}Dx?(Bs^|t#)IaI($K_nS-AgO|P|EcB+H5Tv&guPl}H$Xjj$mE0^@jNYx-`lItg!AgE7k~(h?yA*j(j31dT%bh?u zzq8X)t2*m|cjLX^>Hh+Jj=M7yReH!O?V#E$nR(jF z-s^ywRt)r3hgS`em)#;(H73!?eYO^DT{&Y{3P^`hY=h}B0g8KkxK!GJOu|^n`~4)s7c*QA=qHGF+zQd@15X#PVEK-oTdzrcR>U9asfN2s7JTE==|UZMCO+xrkvlN6 zIjmDQX)gR>oNxZmRbK7&&e2or^31Zr*dVm*OD*29g+4<^KPI6|FGmK>7Ut=k_>V7SRug8KAOy*C=~CQ(B9} zC2%EJ^6)?hTu*>rw7^)WoO6TYTDz4c&(8qVM-9=18B7dKIrhdANj_}%l+B3!gZ7%{ zHidQz-tD2!_p&apiQ-X9y7x~qs#nhJgM6jPc#A|!{p@Kf?iQftYQVh;u@Ep3c+UE- zv&%_jSw_0-$Mn%;s7dx$@NT8!L`ViZ*B_|934TL?-gMjFt8aH}j;EeDXX-{3I}(0& z@3U)`OV?s<3#rkSj@()&yMwuORJ4zdsa-8Lt==Now90$c@#$~kp~wXtlONg7T4l_& z#}^BLP*wC10GcDC9iJU|qS1t;1R{ z^R`qpC{_Y_oM7NI*)!Hez|6g=I7K}#``NpFK{C)hAHx_S6!d$uRQ(G&U77eTDJ|~< zz&No_f}*5El731{R#rTM!gCW@MhxVGx2YWFeumD1BeMf6TghXcWZwLmdEiBC)-a?c zy?bUWqO5TuXEh&^S*^6msm>e~xc*>T>rHR;u8^yfh2R{hrdkUfZW0`{Ki9K2Db6I7 zbhVP%%lS`(e_@=svv-XZX9Y1HGuh9UU#k2N9$`P9?-D4!Igy9eN zDF2;c%orH={h`-ZGAjQ}!Rf(TcmPIaro+=c6PV|j$?~sJPDDlGf%ly}cms~E&?mZN z@S&=Ui+j{NJNb?}pfaBCKRNYp$D8v^EAv*%~2SP5TU_}C-?6P35UiC;@2VY>|RcCPRoU^XS-ujk<+2lN*0Mu04Zn>KyAVa4a zl=!596maUNhR~Yij@N&?pPLHS2E((a0*5q$UFf9or^u^9Ev8)8q_+m;+G{~?mVR?g z!Bs?Fzl9E204&GGk>2Demi!p6GIPk-*j7O7-lo^3+|2TvsfJjEz3IW#J+f5hMp2ow%H;1xr2|&8?$82EobIF> zy~-~W+%<~Z*K>pRzZu}Q$%XdUIev!ZZNVgiKE25HyBazPMpo)U>XV7%x$#EG($G(> zBy{LRLvn-FIgf@e=tmy%ord}q^6^gIYY~2IAH@SDna4v8BrZ~+W9 z;k7?QqX|^k&akh?et~mH6SzuJyObo_+L+N++P?ZZ2S1hX8ESc&p`>W{*~Qho>w3-% z-Dux3ra4#|JcDM^hpFoZ>!QjU=VZK*33L{tGBmPYd7T7i@LZ3bd#)CSF1Z~E=jfr^ zUlMaJdyX&LkvvC0Md<7b@D9@S5idU@_r1>|RP6zBPVy}e`M$Q8)c#KFlJ|llXyj_g z1ez{%l&T|(#2}G@n-uBL_)Otb7u&aSP5d=eX$ttp8}KJh!Lt@@DU3JriO$y~d8OF& zvQ1#G@!ch*6M`Le{h3qsB>Sv~NkkP1ICH#|^?dQKN|v#DbYYI>P6yM{RQ@jO7`tWO z(3lQBA?J|~uYyVch+4n&u^e>0^P-iE0R_;9Cv+?PcFZU1rx3nP)XD~Hl*mGyGcJ#U z5V&CA5Sl$hYZ<6gU7y7xV+yleF=mVj)H1Ik@NwOOddt*~QCX)C2Q>HjN}Gfzx(SvB zwES3Yf@2>X11>BijIT(Z)4=ZsZb1E4*vC9Nl5I|Gzm z=%vBThPR@qUOSZcKL|EuM;h;m4Bk*OBc*o#-ba~N8S11Hy7L6u!S;V66ls-qCW{#r zZ?g`6N**k!sjN`sN~RHos?5L6&nwwE+JR->##;HK{Bq%cgW=)v?dxmq!q}XVovY=B zmUSHD_1{3G#&JS_yv)zXS=R(_?PCL`Sbx`n^S6_u=#@L%l=fLhc^yNaT$mTy+;;nG z2wl111MbVgB_0yzi0Rw6L?a>3u1In~;swU>xtFd01%sZNW!A_A0YpDWU+wuK-wo<8 z@|+`{Va|jXUXPP8Xh{rgvc0R*=oBh63ulX#?UeA=0qJUAjf3P{Bkm*_8yPwz+^kV| zW%h@bjeZr&+JT0WD-0xWNKiTeV_O$F_?q0u$G;%|?parV5|bVA>eghFO-trmAXf~~ zQERave}58qmeoz5)}znAgWVdV?)Jcep~0%_cW2P3b#Z9*B+Z&C{X2=+^3=YfPLFeO zS4;bjymx7j!Gy*u@y(RrI1>BIe6AaH7G{<~uqhD|&6dZ;%m#ak16-Q+9YhYIPlsNe4Hn9!>kpb|88ulU(;*-*lb5_925I zB_~*&+_|N%>3w>Wrno4#rH zM&K6^Fxvj5OAJ%17mwq^dc-~GEbV=Bqw7J7MejPCv3_6j;7aVJ>Lwb}$72Q7ru)a==9<3#z@ttNFnQ^pO&gOf#!FzW{{}yIQ%Nf>N&Hi2K7sQ^oTF3l zOzv)p=Nbo6DI^>-4av`d!vuDBjNd)Gw)%=BC`mNrZ~a&B^=|RR@;sRG_@Z9)z2K5I z@geO%=>yYtxSs3(E7$Q)+xBy=%S0z(5Zwjq3U`X99Oc;KdKEkZ_mcpHx2VA5TZaeQ zA(R}0T$~@DVy@_QGV}~X4~(+D5f~G1Q4HCA0Nk>@0Pl{fze8j5Z(>Aj#@d~4lCys1 zgGI9LWhNaN-N%XGRsp&i*D7HgKvU1PdE_j|+Mtz)hg?jF&fwUT)ZM!GtA&{o*Gb(} zG5y7FC+Lry-l<%+Y)8X*2XQR0AU(p~PF!@DH45w@f_H$S9JsW6*EPwCPMDUgH%c=| zF$<>!W{n8{`$SO!$fzGx9UIbnclsrNNMrzd1Rwx=r}#a_dFV!Fz2{Evu+mSd5w{gZW(s`c47RixX0NZ&o83isTOWPjy!qHeeqmE`m6{oBw?DvM zrpIh}c(X@U18XFL&oUuML@kBMwc#q*gp1Av!Y^&}PdB|g#it<+yn6zw>`F&tJ0T?Ef)QMWp z*}XPj+P*E|>$I79eV!zY0dD1!vz$EK`?-2_d6pptXwmPOJcJ+n<=x%dN#`kxt;H!42QrfX*OZZ_4u&SRBw_D=Q5bxfnH zz02en&69P{*?Nq7q#q2E2dXV*9zDbG7_cgB!0e+arBWZS^L74Dtc~p$YY(Bd9Z+HZ z^0Um-JNkBCI)qRbS!kOo+P;DgGyY6V?!GV86oGZpj|J%VfUOPPwO?Zk4umQaS!H=Jz58A7Vhy(VR%w5Af)P|mp2pAo$B&hi_8@MhZsctSgpV#Q=Oajq*Bk$@w?QEyP8TUG_UYr1A`PZi!WYtvV zi|eVue{{Z;&WIXXl8}P0dbPIPB_uiF?KSq&9Xq?%p4#RU{2MdcKEh0Re-c&#F)j4n zlYD{W8KArNe=*`CcfE^|-{<_JLq~DhSHCUk>wUru)-A#6pi;e8m@1#YUfacAtOt8- zd(oMJrqbuOU+eqG$=iWz9h)=g(>nii6w%M& zm7An!ZQyIGg|8v0zE>FnOjjiFND4<`a4;yv4+2lwUiR*UjgZ5UO5g5yM~&<~bKNjT z6bpi0#{0R3R3efi3yUr|-5`$mUTj0~b9Aw=$N1k=)s0)3k}u<6NhEk?z#{8&$B}LC zCT5LRU2|N!uP8LQiGDr-MB!_o>(x(T>nUicx5N8Tobc0FKU9mneLWkeytb7$n_rzf z#f#Qa$$e`H(PYnnUzA=Fv!F5Xl z#$){fwZ5Y;PMFQGGDG{_vkcMIcd$;|z@PvI*HpzxN?fViz|^jkjl_=HJp($bTjw9z zYL>(!Ck{k1p?ebnbr4*JkaaTO13m`Zaw5WDgF`gOHK-t*D1rLPPHS3_NkvrX&{BP! z;ByxKtb$;0sTM4zRe7y8J`(Ae!VJ&yVgRV-1_i2n)_ zqR1`ftP=knFyaqMC4jY~AgNw|00X~Mn6sPfrU)X*T?|e+c!(jaReDDxUu^tkeFnDv ziaYLS|4b3RB6_;6z}hp4GaCo5TJ_n$3PTloxeC)BNO(#)M@i+4?@>wXra@=qap*M4 zcJ3N|mi6@ zs77H(P%JF~n_oYb4)_yEX)(!uV&4VWl}mdJ@BZaPM)Sc+;4?|gw(;r#eH?3p{ygeY zJ{!?2vmZWp>zu0$U&DcWoRCk;xH(^PLLr6(J!1W*Qy`IbhtI()fF4=Qb!*)jz`X&m`S_D?K|V)0I5w5Lu)WqB zzE{3SYaenqbTz-RdvEEGe;piyBL;r<7}R_&iz8mw_JyGq&rZgRF1Xa7bvG zbjhe|W2H8|z*>r3+>R1@=sH<6a?!0MOm|QA^}BqVgItgpxzMu~JgW1`Gh*=YY{=m6 z8WVnIYq* zfMLEOa~7AGZ2w zioQeWkmJUdE?A7dJx)3N2{86JOd8K z#Sp>6#$1{F{jde?4(eLJg>!b-vB>}&-eX!tpPZCH7o`MQ^51WEXk&TEoTCG#r}Dw6 zygtDK&q_<1Qs;^b!o9S8uk$%u)r5M<&sPO^hGm-o1#_XD8kq&}3C`wsBwfdDvs=^z zhjCSd-(fiCKy7QPN)FWV#K8KQy_!=gL0} z2FAiocRtRmjnz2Vz0Zq1Sp8UUX?+GTb+E})FrI+Zt=^l63c4GYGVL5$Qr7#k*6`bM zj#CGpj->kfn1_NNkwI%wpg%Xf487+OGsEGK%p>?9U1Mb(-M_I59NofkeEGKuKKqaL zCWsZh8T=oXfTN1D)q0aGt7j`Sga33^j!igE@}0`0eFk-c??P7U?zvy>21fK&78q=J zE(MUq-naE$RpK1e+02&!mw6Qo_qq5pK`dcw>27dod7ZoAzhZ#usg;KxE8qNI@&Jy< z{w<2pLO%|6J^Qg-N3oHK&Ucd-`(uB`Pc7});XVF_{al5;q9eDyte(IH>@=S2@T{{AD87XsFf~P=9=y?U9CwgK4T!`Pw?#;D)( z@PH-9&+s2l)+^&x>oYRSjWIn%-Ba=v*!2Y26+d7TvP!bBEW0PeqS={ou!nZc@kwCJ z+9T_W|HH4dTf;8(bE{Z7EfiaWC`BebGh>IHa6!-RNaU2fOCH|j6vzTX8?jT zOjoy_KrTm=&JDKHma6l@c7NJW>cMhBw3U zVl|#75aa|phVUzwY-Y|00SM9(Qrcdy&QlQ|&h-aK3}_>FOaSe$VIEtyBa;u;#RWsY z<})kp2J~VujDGGJBNI5m<~JP#V-#w;Yclj}lO1FHYZD4_oagZ!S)RlJdpsDO>Ny)Y zuS_+Kt^z%@!Zy zkk^v9yo*>Q)Dnl4Hk_V!AIoI>^JQ9Pzz!&XYn+@^y`4^Y>}rw7LXE+p+Vw&14_~AI z`Y`F)i9Ln_JxR&%>Dp-ffw|@|8gcXAlb9nB`)jB=Eb0VZ^Vkz3O(26qlRu`Jb6Cj* zsGlwd%{qBE4uW&2EC`oPd0_bY$fPRmwYX`mPGV44y?z`Fl3}XQxFZ~8^Wmq(Irt6_ z4r_526)xzdx}@;`oZ1_D7FPWp+r)F0z7DpEv!6$)T+Hrnk|eZ16E-#cZ#_Kf?EiIi zPCc|x1xF{?cIngsK}SyI&Nw?}7L>lUBbFP<0JsxA%k~PJXDc6_!1mvo?!_c{v+uQ| z0;{`>-Q0XKS&>6vE=ih6;A6A=uGrKU!`qddtMj1vivjo`8JOz8G|svtZepSJx=K4} z7ayUp|DEp!YWu=174nblH0v@AIXZJz5AmbG;^naMC_g&Jz>Xh7A!w3AC!Im#pMBIh zwq`xW2|o+1;Mn>B{+W}FbL``h!S3g~BNvy_-1EI=dX_s6Icl|#zR9Kpu(GZ2dg0NL zZ(KoUO3KxxWmzb9>ov*S$Co){j}j!dCP9y!NNNu{j3til6C{KGmP5&vL*s$zc<_hW z1M4;xWPcC+=eZAU7{+J4$yE0vpCcaG_a!FrQ`FZ-SZ4hxGTrfcNUpz07O`4i6M656 ze?Iav8~|(lU%|Knzr1f*F7L2>Tgkh2Xmx4khn)0e1naM)`heEH!K-e9s?2M^ud*MT zB$>Wqs3qUm(W4i8ZaW2)l9L`2Uu5_zt>OV=lF!bQ9bz8aTmMY?B$lIMSJCNr=xXFw z#&0W1>$O4n3s)pCYlUn+bdk)qdkOy9=Aol~q_Y>BpO+S2(=&Eln?MyYQ4#hz;6QL| zlHMu4Xk%4)7Jl+^td?RO+Ux}+N=^pTHm~X_Qd?N_vMzm?STD_)u(QTzK7yIB4Ha*x! zNM!@|RrhCwvE}LNv`;OVb+2)2D@(x3jJx6p0>-fHd{qKX$uY5?Hv(6xZzFC(r#Rz@ zq!F-M>P89UP`HHBdK|onrH!~bRs-&2hF`uZO&D3`OL0*&#{?i7QS*)BQ4^!e8z-aJ?Gqdlxg@iiu!H&uGo@v=S)@r;sq)j z-bWq@5Rv1wIurb>m9v6E$ty&jy~Pu@3?W~SENUGPr*I!b-*L36o+;co{BZ=HWra%- zWYZAC*)b6Rs(+@v=6~&GK#W;{t9Ag2X*2ESAGOcP16Z^_b?qRLc1HPbOczNci=2c$ z;Ay8T3T_#?j$CraiO$4+3{MgZV=&{GYW4nYLkk@W;kHqHrZn|!?KyRGI+kjk!+ZZG z(RK^)bgE&K9sPy_d*om`k(?#Rh}d8*4opYFI4tO_0lrs$E;8H5$908jWgxA}&DN}M zkiUBqhY!gxo@IHABf(|~WI}6n+4KQJuyO=E4G-R+ZW9%Arf`L2w(+qe($Tq+QoQ9@ zL7Z=|h9pU$6IR^}VKqL54OcmGaDQl_>}96(Qtr1?Q6qHSlQ_AeVu!3j+FtCD9!CR0 zM{`EbE{O~C=Xh7~tlhUpa;6^W2t2n|of*&Ng1oOohjH@>nFzXu=a#QmA!}rOMWh2<=8)~$etyUcnvOU4q<7}gU@iK`;#$Y zF*rV$X$25Voo@1OvbxX$2jKxyIUAgSaFl5iF)N^4p90O6z!n+2`9xw--)*;hGEh8) zY5O_r!6Tw%``s}h1Ax&M2#@3L;Xr$aT?V;b5A-4H3v%@3tntv9Ry>&|Np853)(42ebzw=16X3cr9q)gJ)5!b{t+a%5K^kez~F*D5_0osJY zkoOa(z^Rge4Qn{syNpl7@1#3JVABBrOlIU;t&2nNfLU=qNaBoKevp&8PaBtk#0jh1 zIie@9e`G?Bya|exO@kd_CKj)3d(!JGGr|D01Em*4Y;K%LxF1)3q_M>3sg!w2cZQNm z?mU4BI9>*C8?BH^5(zh)p6W9h>b7I}3_==50h#CwJXL+Xht*O#qrliP;KP&A8;0L4 znder3XD=i*h+yjN8QG<*dG&vha4J-C@nGJ!?as(@sTSib%PJf}S`{$9qi-DlW`Gpa zrAJN~O}2)=z9sI>m5m#V+JT?zpa$Jd#Oa!F0A1QPyXebeL?Z$xE=mFxaQOOt*4lh$ zX`&=far_ISNXmW7PrGEYrnDqiy?a#7q zIjFf6ahO5BOS{2}sf^__w^gn_;)uo$e7HrYMNmRAK}Wd}BrB)~YR-HP*`|P^XDuWp zNF*m2B|dYE554$v7RC?H!36hl(5B_R`L+gQuyztAXKf9-?gu7Nd-D4NlT>pw50m0& zr^;w-xNR)b&21igB(vg={az`)q8daQrO;stoFKn~q2enjRuwdwvxByulPr$=1 zT|{{db%}({6W%$QnB)zLswa@E&YS{{uyP4_+#gkD+K{YOZT^`Kgj*iai`=o<9$Lnq z=D`BPhI!#fr}mxL>I1Hr$b$i<9Y?1RzRXR9zI;p~f~hBvC-{z2)G*C|oxf0EXe$Xd z7S$#XuRBWU!aLcbee-IyK9RBbmx4}rKkxUx>6(eHB#LL)>z_o4*H~w}JR+35F5lhX zPm=g<^3=2_k*6#BLYtI~jQR1g=|Z-Z7h&f|XB~f%^n5QYF4dEjM&S)uE_L4eDpk`` zCUD+6m6LIrX`QgKxd6V>E)pT~Zpy;aV}&HHO6!jQTOe$&fR7+OJ-m+tL@QyNsc*uf zyg$t0Rwlikg8050xt=QsZIHR!GFO5umOG{%4$pa;<0OIKgY!t{MmL#g1bzO+v*+_v z*V=2FcoxIdrtv(HsqAfMoLdL>ytX$)X5WtX{mEdNIToSzJRnS;v1OewXPoTMsRKU?yhIEwp6HRM=~(PNopw-=B^(HJFjWQ$R}B%o=Pv(gqE0gyh;S>kW~Ye zYh@U@!>f1W6>eo$)dX5Rtel$zw2Wf2K1yx7UsPe(>3XeP7v6%y@6nc#kQjO7-+0-rRoqP zk^jkS7~?x?y#xLDO0ZMV3pwVjKKQYQXb5!k^K_dSA4=|SsOM@TomBWz?Z8mh4V~ar zhz@^JqF`@VxjiIp$0I`@o_p>%gT^a{(2)edw$2**dA|vdx@F-eYCJyw#F$6GfWGW( zX`JGD&N(ql`xqM>eBiiw-I=&7OV@n7o)t``df)_EP?C0Dj%^!B2k*HY^Nz8NO$G-z zE>Mxtm9PhP6k^%wIL7*woNeQbCOq>3W@wtZ{+6B83Cxn9t;J%FNtP>l$gqCa7gRNk zOlupL_Djd{o3$0T3!0vhgO)PWC;RYUr%15@cZSKe_s<9WI#}H~Ic<7?BbSH=(U7da zo^-BBFmY92MW>NZ^Z&zZd&v$bo#szWLkBj%nnp#48V105e8dT;jgemWoV18hgj{_8yG zsU)^F0v;TRYQE8Lo=HzMdily&6HI8IYmk0BRY-oT*FVU*YWQI@W7q)8!7U3f(iI6l=vd3$gbG5&FUjnP! zG;k(I`7i-C5a1{jUdU?72%fukW}Mg z_+_RiHYUCV$)xo;k9jyaF*ir-iO^mhm-Yysq_^W^NOH#}SuW$H^Q9PsDl?+i@aW7r zVkriVtTCj_o<%FoBPgfz`BbJyo+mNHITK>QRNs&0w)gUx{bXInXtxJS4MDA%T`ITD zwLR$f>}IpSs;vq%!HwyG;F3YsO_ZBy`?2W+C0%{R)ZE(`ExFM1D8ng{L5@K% zAum8=L&_>=`S4=T-6CMq8fc-tJ*}~LwxPMSlXmTp71=V@=gipI@B9FpCV2XSMdi%6 z_YsGZ$Nl`3^Lz_xOz$OI+6gF^_i5k3dX(Hk!}(F|OZ5Cl$ZDg`z$P2C?mg?7Keaj# zo&nyvb8fh$9i9^0@y`jyr6_(a7yxVw)X1^)`TURg#B_E{HU1bR@l!~yjaetrww<5d>Oj#3`G-vI(#WRE)jso z=^&Xpm0$8SI`xVaa1SZByT?aDm6q>;@t5e>0Vwl1(H6kr;mzZM|<&RW8e?@mqONT4b=s@?iCdjDS zYiuT%-_m>iS$u^&nGIh5vw}%csYcfKhzmMEpf9+8UFz`nAV@IH$41YSL>-7*|7QxJ z#$gZene+Z&MP z+}b}6ZzN@yDS42t(#P=$NxAKFyLQ7)@HsL?~4M&JMt^4z`PTLcO?A>3tau}i>IIj=rl2xRq;a0Og5xjH`R2zQKzGs359 z&N~%?Fu`#jt#Kpkb8*BeKUK(DQ6d0U+j7d&PjS{j8>3>Rh5*P$MN(E~S?)N|QuKJ4k z8a@FzbE&-d#vyMiHtpxMw#^v5$fYD2@Z+v=>jU&EuI#B85wfVa6+^~T_QH$V3l6Dd z9Z~D6o@+2=c`P!OC61I##fxWX@y35A+mFaN9!=m0*MB~c;K&tK5(nElprgH${26WK zeNV78GWXnH?EN-8*JkR=)vXa@ho&WEf^A9LqI~or$Mvi!7%Ih4$DxvCy$fkn0`vj< zk%4KCG$4w)Ng? zEDT~1Tv%@cO~Z5A(}S|U=8T{RP9-_e8hfH^$8ThuYAwldfM6cH9vlRpAEqhj;wt8XLF2CzJgJ+A8u4>DaqVR zf@ix@*6lT(`b(|O+=ei_tRJC;F|-C7py6?nFc<*tzSuxAvyFx3Rl`q>juvuxPPSdx zYmM{y6wk#L-YyF|#FE^FxM`_0+Aq*a<$;~v_#P8k*>An?wLP@BrAuEDgCI%RC(+3F zkuwSoh(-B2F6@k&ivc1x<3m{HqpK7`Oiu@2v#n+re^x(T9^mOiB775+fC6XzA2Z-J^T6=m_%T(R()p z_tptLmG1WYL~J6cnWIzfM2Q~X^aoDu3l4uPKkFnD=Y!w7WUu%W_$2e5y^3?*10TRJ z5`6Jr(f7zcM@qms`>2nfFI{&?o=0~DLmvHA{D-|3Qc{YdrglTK?OsyV-u~%e1~ho6|UUcb%0@2&CY9lUd7lOVaQkob7m z^$DH_v_8=AEY!^Y>H*1)uIH#ArWWR&M>hR)Zk*%j%fOUnvCs=}M4LqQqx;@;V{tX; z6LGq8WnP%kL?lhsqRte5;I{50=naN|9l~#gyHwXeaDG0fQk$844K&}dn_W9Vp&dAu z4fXBoEdD6S(GFK3xQ?RQa3`B}6sJUz9k;v2iU1@jE$4%%EFlc{S(`s!C4Jt01_S{^ zRa33r^fmJeIs=)mCOZr`j-f-)&BEiPK)JcDzR^<*@6xn1{i*YTYw%zw77khNw~P~F zLxAzSo#0OOR9Z9+KyhT?4v|Znxm!a!&)pW*GWb4~j?Svx`PH#U9CuJD16LBb82E@P zbuo#W*5jrejz#D;@_uj=?!T0&WO*ewX41_%nZEyw@>YI6J z4d9>o92MDh;@}z2@qQ)sEnOd-;iyP|A{|ONR@>Hm8~AKZ+iF^i`F}sM z0ce#}KHJVY)Zt~N-D!N_0bhnj{+#z~s&Y4<-%8G_mz}{VbKcRxhp~o%pK&dIgj zMs)UndfQp66+@%olE~FWwgKr$NG%w@!VRw|yp@L;y+h~%%)uC@P|L&2I&v$HV>lsF z(Yp%HsIT<(z#eC?D$Yf%{>Rw(;lWcUMf<@AS8&0n{qq>O?pdFOVSNho!VY8-b=B#r z%JpKV80$;r@c5_&Dt>x z&Z5Jv)TnpQBH_EOs9YsWFwSKCq?WMXa&j=iEhf;; zU(upmwgW>0+CoFb7wY2~cl?8OmKDrSlcXUFG25a-&zVoj$)wl!s9*Yd()GKhvD@I* z{OqTb>>@=g!yIL4NgVW^tsi6N*ow?;FrPy`^T*K>S|jBMsp}NjrEK`Pih; z6cvoEa?o~bg3I^2vi-lUz9;&iLO$E?-vE7cF#$>?Xu%HVsthmDx`67X$YuN6M{``x zSp3S|U{X^S4OXDP+wR*dmkp1O9qyw~ji1837r|g;&bmuil#u>1Qw#f{*uHAkWZFDY zAaZiMrSBu>z3Faj1xLX0UHl`AzQ_-%WZQ>qTmkn=fa(ZjE^ zzSzjn6JRH?tfh0UpB9TzL(JHZ-j@5(3;$g=^h5T>|DS!3TukRxBZHr;=Snl|9XWnF zV3Yi~3QdN^H~xe0JKV{m_`*AzBzr2Z>t>?9R+jD_YhoXBecniHjzxUOrci&xCEDa} zc@OB?=*-P~Z{nYbzUil|=Sk-EP3H%a!wekozK!>fr(qk>djE8fPn&l;`(J$)1N3U~ zE-)Q)#9S$i5VN9Po1EC>7>RnXSI4naa|7V!+`1f`I(4_*jd0RJn>A2f=nazBg2up7 z39DGE-sf5gf3mS}3yB@G`Pf?V2#|UllXHAlzm!EvVvrAvNwpzLS1T+(*&kTmi5X*f zyTv{2Dw=co-uVf@b^@^UP9cvI%r$Y6=DLM-Bl;Wv&NvO#t;YuD;s7+zC8=U71QieR`}OZ9CVq7&yeH;1GuASdgXlxi%A zV|%dt!lj`4q#{6lk0!0GKod#MuaQ&(+erGYY;-y~Izr#A=Q_vv`hA?b@GZ`1Z6Hf` z&m%Kv=uVO5x+Uw~-9S7T>;wvd>EH`4)(GLK$$j*E7R!`pUE-DH?UD3NDB`TVD;FyR z?PSFcR;qO&ew-XP?(-Y9uIJO(7$$>ciAHXb%Qiib%CHK)mUd+=0wjKgBaHKL@A7tp z;6(1wg(|5I6)4N`lLT0KHFg$v55sTjDUW`>Vpf*pXVSDEENo^M$#3(p)+1Kj?h*Dew`DoB-Z+bR8sB31h;#?X2pW9^kYk^5;uEC7 zvq=1`{mkIgdspIO2B2w?u9h0B@lh|$%bh1G(D}mOn3Ey>r;_cbjqY= z+xr(khl+R+C>yWoD9h{}k@VVR;>f_+;}htK4d=?t+7EE<`tvGf=EF+PIG5$1@LJZQ z8r$O$e}Im#XgvndynoNRR`d*_vAU{@sDgstK<0ni63we5CjSm$1%W-Eg9N!oYzSeuWI1P z)|ud0FTz#!h?RQr6TRJ;UN0Wb^KYZ0>=^wY;?y1ba?{Yb5B89|^46WR@x%t$!f69k z29X+1WxkAU8@{Hv*n8YgvTs?ekHi9o2RVIO$gnxE`WXAvWPf9u<1HpphV}Gn4m#Az zK<7vHH#RX(YSzNB)stu2#@5OTP@SZ1RL1uG{%JR+Yw5qiUfUeAb{CP@q{BMiNZQVR z>-Yd9f?G!%A50fGD0g9wWCMm_L110Av$g$pw)=e6&$~OD`g$>K*%=xq}a*gc!kb{;H>;sFfG)*LVGa?%8vtPd4^Xlmn+oRSxcQ(M#Zjd zWbGsZNt~_~R`(^p6Xa2t7l?!~lX2@>{BYblD| z3)b}-N%Np;W#!>Tw1e!buLn9pmReN?*x86wiH-dn!}47NL5ul$0r2@#-8+nbt)+I^ zo#60bAmu;{*)2jUzvFzwFvt$ooo;KWv?U5PeE4qSgacJeifWA_OpDD%@M4J6}x@Yd!G_Z}i>ReU&p5>-u!P*1X z!N~HSzqy$r%jGj*^W&hgylK0x)yaPDT$aX(HX?8<4#S_|xg}bA-?trEV_9KPKzdzxj*2`ezK^JQI3|~o-6mtFOx^d|9U?xU=M~!ZG zLPI0uPwk^A#{6gyTAGl>nF8~_CaylN0)r?ex11I?fq032C;8-V=xRBg6&XJ|om=p2 zZ;X*Y30~};!64PHf3V4TiOdmj2K#GSWj!X1$jcrTQ)U3ElZY%Eo<6h*KS`~0UwJL< zyhEK_kg|$SckT5HgWt5DzlR^TScOc>`lPDZ^DTH-N7ScIz<>IA@}%VW@P!>e1EUcCUNlivR&ymn}Lf@V*Jsi zlD1RH4$|xEs(O#Y_$Gt#y$9p&S**;hSufJPbi}3vGKi%rg1T1p&IrrbU%y}~HdvOW z6WSwplT_IwTqBcCj*;jkKB*@$X}_c`ClZ*+8lRqJ=x>KHCQ+?6O`e>yK80K>a&xu% zkDY0Y>@oscZh~=iqm6C$A4t0T-&JP|paQ?2{dUJ^+|KyBN$grI;=j)ZB^K<7W|gZ1 zsz+(h60MA&fZ=PA7|O?_PzJ(bP9$Y8AT1uF5WLs0fYBx^Wr7?_ax$@*jQBOvpFk!C zmCZ}^{Q$p`!=K)&-?rb(yGkY9$2o04%iPcX=le>sPB45{_XLx*-GHh?;oX9_*W+B% zqE=jFIDlKVt+?I3cItW$s|d#F`KA*X zw2|(f%LqNPam+xB4T_xBa`SfGlQ~9_q_jbXcI~O2a!UiKxBsFV+l>;J$eRMP7!wsn zuCupt)&E+Ds=qOiGfgOT9P9MenQ&LzUH? zmQn#=9R(e1@H}i$92;u%jjx<^wvZS}7Q0F)S^~JkT8nU}Yy3pF{@wgo9aG(?IUFT1SwJ zpdE)@v& zo(B_RyKPwu@ilKr{<36>b&~CTkL~P8fcDO3|91#p`y6byc|;K2hKl$^MX)goP4b^L z=(#i$`{sfNT~0YeYPsm!kLsJh=xJiKz?QENXj;F8M?+JKX3Zu3a>;dmQHP%Z=Y@-fur{0_)I=uc55rVgzmY4q|sCFDaoS>M)bi| zAn-HJAxA&@|9qq+y?$XopB<$X$q7k54tqj-5)cA&;foVCobwO3J^}R4Ye@J+NZVHh za|Pf2Hn-r!GChp zZqK!F{PGNOmj1O&tD;3|6+uw3-IAs(7noP`&}+E?@1WC+H9v#Q~}T z^EoPTv`iiFwo`R>f1bklBxELWl542AHszM8j|+sQZ`&F6cRKfH`$pO4%C$mN9>s#; zgk(5kR9D}LL6yIZbF_mjHtUO%zO@&FLS)RMV8=}Np@RXle1^I7p1awE&;-NGW2k+u z1F~zCZ_9j|nqH^lF{>DJDHkZ|$kneZ8-e;+L&bo3ZC&H^V;FEaj*?l?;DHe3(bVwecp!dvwY+EP95FRy0}+!$mhENTWj9cRxE1b)b| zhOV4I<$m8ypo~+shS-s~y3SNWd!H4WnV$*{^6F^OV1upt_`uVySWZS5eFyKK!Hip# z02$G1FU}4JKSLi6)~h#x$Tg}@IAU7zUOqVTN^m@~w>l)%=rQeM(b?e-ZMN)ta9QiK z_;XdR{yB&)9dR#rJ@S%(8~c@BsmDG&)W*5K*ocSiI7qXnEXWQLiIa-M`zDjyNV`Yi z9+_?4g`MafnC3P3&BHIS0!IK0HrvW7t-j(KSWM_~LiUQg)-g7%dvBie-e5hG(dWS( zmQ8XH8jUl%ijtdmZlzUsbfuka-Q<#r;ljoT9AWUMsh=&M8rdtiNp|J)g{`xEO=t>E zVrM6CnZ;kkT}=K~w}^-Hvp>Bue5Cwtx(e?xU7081;?kka4)$DdZq~Ps zFa~nHu14-Ga|C8d{K`L)2ojgJp&C%`l8W}pa=i!P6R^Lj97$+5E5-u(LIc4H2EKrbfAg85L2J?x1B zgp;lh4vyBDmRcKz{_ZuB56x3>B_YvHAgyd~+^{|j^zG*Zue^|K>nviPaUNaXqu%AA z@1|Ryte^S$i3cNVt5@%hYLTNNxeYBAr&q=+>t}|6R~Ft63Mch5|GH3~#Q^RN03iGm zG}p26`Lo@$n-=?2eVxhc%Ds(?d~L(BLG=U}k1#zMkQpkr#L2ZQ9DcD7ogQP5OJ1B- z+^O>z*PS&0(w3$o!}Tr!Xclo11~cNW;=~U{u2K;=+w*86I==VNuU)nq#X*1_koGg_ zI?CP2>SsX4c7S>y;;w17=1k=WC3zjmd4KE1kMAC!swInYmAEr z5RTvXje-M;r;vBDZDTBd?m;!p)6o#sV{Ien$q!j3@1|#CRAz~lHPQ+_!?{p?98!h$ ztNhy*^ayxN(m#chyg+#Fufslny#d`L);2Oz&-0EGch~K%+_%g*E{>q&YL?gFTYWOg znU!|incPt9cwj+QOJ5tvv)@@`iO39XtEIjkX7A)PP%shZ(@j1PdE znuWiRv(aIdEve5`1^Q`|uFWQo zfrVxj#{sOzasnu2Ji0~C}u&j~YUGBvpOpyZ+_zv%yL#I~<)k#<@99 zI9HAyXyzBK!`rEz=;5ufkLG`$uQFKp-80EM^daBohXgrxU^#Qz@TGz$BsX&dK+;qs z^>=lp4)%0^lmr%u8)s}csba~kc@NA-npCU5$mY1mb`a0#zh=ub*C>9-Gb}5_7)SkM zyMt2>jgj97YFnxt{B4V=G5B_>PeQ~jYw%qpg&tEdokYJ5HX8@Gr|KnF_({?%t)4m> zG3H{Z>6-K9$W%T0)f!vfbiZhweDJlwXR68GcY?arRys{<-$ z9eJrA@@ydn+CMn%!M&B~<6|hwpCR#qz8z#tn=C=E6wP*!=y#k)SJSGVgqOS88a$b2 zy|cPV7==cHM}BTSsrxs(=vF}38XWC~1LU2qWA??*&ih&XR?VYRJo0Rlby-L(Rq*Ea z&~+NXOF8Zd?HD#iym#y$`e(W8*>`$Rj)f?}ANt#D? zdjGENtSpNkzD-LT3;P|3WqOiKNuoPh9_+GROh>#sZ{I{kh48i+rc;Ip2KUzw?8oM_ zscyOrCgnO0OS=Jj*Vsj&MgKLJY9n!t!|40xg=`zZHeu^U6@Q7KT!U6VXyc#O{5U)P z;ss(o{wPd?+UN#Bkwv5$5?bTDe z7UVR<&{i!rwF{NTz_f?ZAeeIpE!P3n18@%=$~=8&FAIEIN~>FQ?d;R$yka{^C!8jp z^CVJG`Drb)!kM2J6jVp%Q?|gV;&+kj-}w^9&wJ0eB}w)1er~xEcS7$dr+M)O_>zdI z{Qid@pd4)mBRp9zQ^RjRm4TX$j9j^e6*Ap&Wz%bT-TR7jd8KgzpxK$kOlCHOUW#+A z=eug|%YCeogV7Qdt5wSwWgEntFO4(A=Sa**_qaV?Qt4xcuG2@Np-Y~JVC(=ipXV|# zru;pW|83ukMdrTcejFH?PUhbgNfRbrtgfmF5od2;770eN2968#2I;q@PghztXGreS zGC650$gCf}-LNwQ#=P!s=^t^~=iPnv83(Z!c?a{*l7v1go31W8X1vF0_3i1Kaz}&A z$7A}Ie7$8Ux<%XR*d!9kPpHyzdnfpm8f%PkJ-j4w38s~B%ts~&ZjgmW*Km5&qRPE9 zPW0ncpwFqN-mOHXJ=folWM^`GW$kqx5lHW%U^Wt`~ z0H@rvd9QHoasu@r*~SfQd|{I?_)h>@qq|Cg{|r7pw8P>fK6+hz#rOezs>F~+*FH=? z+YKECeuvhvI}OI!Z-HmFBcnHS_Pk1NRqp3^(43#+3n6DlK5Tstwp>y#o|L|UtL@c2 zEMaY@%7fXSj<$nSPBLmMvoRXt=g_^MD=u5PVpu*3rIDrMK%66c72E3PM%Apd7Xg(h z00s4$nJyI->V}sl1>Iwkbk7_K0aMSu^4PyUMG?=a$KIpL6~zX#d?ChSVEq1Ao!_)dMDX2Pfp(k4zi=74WHs zSYbY(O+EWH=vlCn&C3w1ijXK(!39h%fY^+dy^e0IS9?*GijrBm{XB~Yb~X{ z3BjnW-BoGz1`Kfq*AXd+DC~igdK@+~((TH&9n<3HC*VOYvU1(a1B~NAY(>z|J^m@v zypLQls{!z_GwT?i7>5!8-vO-bEWC!NrLDTjlf}72*#B&__Hx~bCEOpVGXOl;y!30d zwCFYnX6<)1*=gn~1QKuz+5dkcVINT7tIFObIjTrEv7OO|mKHdt?TOJIM} zLGi!;=YLIOg|?5a7abilgr9v-aq8Xw!i17ZHBkz5HP`{{WI+OD->ry0YG5Gr`LcfP z+a|p3yM|@HGxpcASCOq@=?nvtI@PCn=SgA_cfVN|0PW{*F3<@U9Bz1D$}mRNbPY|= z`R*TmT0`^;!5zC7et zuAaL84(I%|^sVK;>cPDSpkZ4u#ll6UdV)O~w?+rA&RhZ8%I{^p&65k1d1%*4M_qPV3DHIgPVB$Bu{ z0vuX2DqGUIPeNt!e;gnNdx4K0ddGL0t}-dDN!lddEDh(E#0dDIO-zHm)=wKvv>|qE z%!Y00H?T7p;zXelh>oGfC#6F+AS$aJ!`<|xhZc#@(wKGSP!7qB03P?+WUB73tl zgs9LaX-DaFY;j_y0aat+T|3qNV89jvMn!Dnz`FiD@7j5+b>&T3ckhu>FE>S65ztMy zNRp5KY@TcTz#+6fEfj6S z^Lj*);Jn6f)@DTwD2tDZc<*izSXLV`RpV|v7WoKdv9xI0}YR64uU(6 zyyUfK@oL4fv7OUl`cyx~h{xUnrsU+%#lL$cALM#zlSIezXF|uMHo9 zkana7PZm6;O9~!YR>)wZX;$LJI3-EHT?hUI6&jG~R{Yh@-K3_6 zlx#eJbO}bwRY;>Kn$!tK0k(BSQl*nrTvvF+%_}iR9oj01C6YxrNdnMadBHi)_n5dyCU+wV%L%ADWZKhxa~T`5n13(Lq)2SiQBgFiyK83A`9=!0-e( z1E)+uHpk1nGF&}2F%F^rUe97WjpNqi441?#i5=ExAu6Wy%FZjYIdVugJnbc}>ikqA zV()5=3kzva3Yo>uk9up0>el+an>k0WcF$-Rzh6ghY$EF;3qPnfk2t{+p4a*3eb(OM zXh%tz*sq8-vP#v%VfF}@s8r(28Hy1|I^!Yy*fPa!uK54Hx_zz--MfE zhkGo9-SXq_vrgYWhj)#s9$>k;Fz<{CRifO-Zxa zs*)1!<>MqW-s>(AF9&NXFT93fD#7r2f=kEba_*QZf^a1Q76e`2sr;BLgfVqO)T?*HU zvkU`#!N0_{iuj(yg5kk^FtM+yKVks-Q5i0xU^D0%r~lMB@w} z1H=T$^Ksg(M?M`v#^7v5(bh8HBa7mGpfoL|4o=PkU`>SJC6K^bO+j0EJ_=O+OcdB}ZJ35J?4>Y!cyC2o%3>?n6%}?#E3jNG+kgGT9N_(j= zTaSaE7OrK;rI zBEvw>6UWDK_&}$SEsU!=|$oJ-%5>CDFM$Kw|McI;`NyJD3F-jDxRr zMnJ1s`MUe>0P4~42UBYnnd^0S1LE}RItmCJ3Z_T*9*tk{NR>Ry0G6JQy+@R$f_bOb&45`UwnKr(AbU(tvYM~}P8*N1xeikhGfukVte zeC=kr!(o=RlfVJ=oLgsGF{JmAc@wRBLBINkRCKj&|VAXKj|(x;4akbB-j)Ny+Ea)$2d) zz&WSYF;2gN3^vN8?pDFlqH^j$lGwj5`Lo*N8>Qv?RlNgCW-QhNDLY~;2m zprY;Ww$i;<@a(s+#ZUG8S3z_esW!&ulO-1#9~c62@sazLk6xWR3byH`yXB*p9bso- zI$4nixo~DIaxxJ3PNC$7fxDL^OGCe_^A2F$jP_>+@O^&pNbxixC3{#C6^W#X#G##2+cf@?~(^9c;C$ zV^)X%OFPpA&3s}4cqrbZ^$nhDRJn;sDj&%Lr^mlBH^R%YQ%+2R+qE{krRQ2v|Gn>hJ(0CWK6!X{A}T{Ka#WqsO%g>5eIPlw9es@?fGDmL}Y_i#vf?90Ixy}gytaHPY%{-gtJ?Fqmm1DiHpn_)bzff45v68dvFaO);<_4^29h>CNBeP|i zsMfEDb5c=IOR<%~M)s^BN-$z1t)BV7uiXYb=D9a=J7O?a`sDV7hpt}1_%=hY(An29 z>2Vg2(+M(3P;AW7AjvBQrO-LGa^nMn;@ehi=uudOH}Bx7bQzpBU(VC^ zH}ddlOUPY-Vo2e%j5*{Azi?`ubnAL1%+J-7HoMyP{D-zAv&i`Jf6HLe{u`RCmB~=g z>WDuEB6ntoDOzkuv^dm7wg4PX1qDkb5&gVL4B0>pE_gP@d6JGL(UAh*F+vi9D6=!; zDX>IRca1AJ_j6>z`x{-dzDqWWZbfAq*5jNS>1RD`Re=s`E&l< z0d6|EyJ~KNSf8SK&}W_9<1R6dS1eCDI>X$QtRsGbve(ntQh%;1TZI)-2LB!mhpcm2 zj9Xw_kyZz0o>aBgp2_yXy1LPVb#6N_*2R4=(v(i{=f%E>@=-M(72)Oq0#&s;-77Ze z^_wPbKmtp#C(|8z^3I{@*~E=zyjIf7Rgd1tcEtWplM?t0FRGmw!4CiKKeTkxp|Fw4 zFDE%KJ;@Vr^P?TII*i)et7^@`eQa7kctGbGeuTeAH!_ZF$x?jL!P-4>Txew3?dMr- zC-I!m3OYz!8L1>GC1$YT`*d%7bsuxx?5E{mQz8jA{sz{KK))6kZJ}jET*!i9iLu)!&

m?W*sMqz-SHr1_}gwG5m?T7xZ>Rlks`dS$@|ToqSfi51ceUiW4#)L&&7LbKcpW zQ&N2s=upi4O;SuPC%}{Q+#z5-Kbf^}WJ|oeoqWI$TSFSUI8!Vsg2oky19JA@Y=mUP z1J92-_YNmmd1XJ91uA@V)kg{@GiA&)+3dBvHh2u(0rqNU3sla{g*C`a4eW+=Z8~w? zkOAW4nM$?hH_vAfG>~3^RR*pCY|-eCzvm|OGC;s5@wi2-1UNa{)fyCSCr}_jtM3(^ zVJcZ4?Foo#sKVP*C9ZZUyA`QGJYeW9u?Y|iaEOewl^sNDfXfxbsLRl|)UnHShgFh> z1lKkN_6yaMt6l4Nz1(!mivCTUztijH-)q~ngL=QcEcXf5x=My)9p1- zB_&NVhUz{bBFitIaQf)BN*@QAbiN>>rp@tBlMx+#v`4!<_zCoS9Tpog)PcmPE@z(6 zk@;|()3iI{aMfa`lf-k)o7YiWeQHZ(0ymPD#&>isQ~Dv(*?r%J*2?iL4CBznK?Zpt z8)LPrl9%?)tvK>;&h|sQwMQc>$H^&G`DoY6$02e(mE}@-a=Wpcc{5I+$7Iw}=clu% zm1J1ur_R>awNG^*y%(AV$GHvKv<1Hj>fgN@w@RrFfw|lz-%7z4wk)2;=9mt#O|@&k zwikyL*}rinqtxmzLCSM3SLQ#s#6Rme$p{Zi=y~LZXBcP#Pf1LI=kphe0A;@5l#d84 zrW}Ho?xi(+W7SvbSQ=R}_IIi7HNFFtv#<=AL;p(eB~8LtjIF@#KfFE;48Pzc9BXhJ zi{=iW*u{$6C#ZmS=mR{91jy?~W>(g^&~5+5y0Me#(J?T&vd+y6bk4GeERVi-OFA4$ zm^04bpZBl4g6&(3n$Q0n*WojA@cO>3>BO_FwsK~_FV$Qp&67BlNY>)pwe4huJ_kdQ zHLH7r$Q0$d%FWtJBGU5)5)|r;nQ@U}Y(U3%DgO-q=8DdiD|+q-G=L_BA6wbssmfiU z?PrxdSWYXyGGw{M{VXug?`vmR#2aIsrfHFkHyJY{xoq7Yv$I8kpcWBMb^`ygzVAD34LGQ z?~lTaR;jLUVhXw2e4OOup@YJ-L05-8rh|h)k~rfJ`!n{9tEGX4Q4_OGSAKA_@N7Cv63E+G%MLgwKDL>-^-$X z#`79b^)VM6|AM+yt zx~}I$OpE##lshAzVCB#4LTN#_Q(3@YCvj5<`+W_8$q0;FcNpd+uV1Zc4>Y*bZf1O5 zo_Yb>Ui_SO)$FYhB)@Ntv^pSibt8{G&qs^>)y8P`Izg)@7<*|l#c>LjB53>iSvcW(zPAaHk?(7xiY3_D z^cbu)e%JJ$;WE37=|r)N*fVZuX-8_-KmVKjS^Z4um35#W-NejbJV|`coRP`4aA*7M z5f|Bp0f`NymG{W!r+V`m)975*VMoq-#PciEly&XdG>>es_{rG&J-4XlYyUjaZs17J zwtPh%GFJN`|A~{u``)0vk)uuK+42QqS{D6lmtx~~&rD69;b^J(L|*gGk{Fb= z3OsoHGzA(tsI->b2OqF^Hv-lxbV|M`B9w}f|?V*uFW3T9({C#hx z0Bi6UYh4-3?fMD4#5%}6@9wvJu6{ah9L)P+pBlM~eg}qKeBm7}S4%hPvPyH8M#hVH z=l2I!cg4_ep z^G@Q9SQYyg-&!9acEBW=<9_xH>S&Im883yOice>ZHs5tT5E&a%Ym4x2cO8=I^P5GFDdyJR%a&2gYA zP0@yc93C%!LO(R5uwQ&1aV|Bp&}O%>bLBNAIl})Pe-Y|R^3k%6P0vj_D0Q!Wl2wL8 zH%})4k|W2GRNtBNTF_Q2Xt|r7nH1#}k^O8;_(PccJluadnkx9w20pDd=ql}W^AXqd zloH#G&FFdlGbMFuQk6ip#n3yL2EbSVW26^gsr1fA9rOjLhuA~w0f%A8^kh!Ax3{u0HXO*O>lXgF-QGexckeOFLyNtyhA+WYWCe3J=%WxL2yLL83Q1 zp3uEI+2!}FHN$ke<~`9Pl3U#l#+3JEYk%Y$V^yK&ebBsPD1OeUsUHxm>~8|-)v3f& zxjSiSaEdOO8=hm>hF1VftLlhhAS?XsC2|#tK{*MW{Syb$MB=jzK*gxk1UFZ{3J6|1 zcVy!zz|uUE&B!hgCoyIvz&ZD$m(t!5V3)? z=40A*xpkZNs^w&8b?&22xqqk4o~`t~*s!%7#Oqp@J30}h^IgTGx8MZAzDde;uwP34 z*bXJL#qzh z^eLV>oo56e$b5$aXki;~Ht{-lnai!qy{eoHDtA=h$H}y<12604_G1>p>GSZ|cfI&~ z-PlZ=1mlr)dNM%!_u}TAc-p^-a}|jJ#U0p}yJ~fx4k#y(Ne1i)UoD>Fv|+Qslj<4h zWM>(ty}?$$e=ueOmV-<^NtDI9a)7tGy((f&z!5L(V;hJ3^Vm2i9-n4E-d)4i%Xpc*QWn!A|U8nI{P}`$>*O&&*F?EXnM(cgfvJ;_6HP$I>Z|>e|!qYkTX( zl=;_oB^YPVthc5V7*pm6&7UDMX!A@2>dw>3#C`q@EuC8f$ zf`27l4#p|2RP)qhVE&Zup?NdxsuS_KUf8Wox1f+1^@i`L6b-) z8*QWa0QCHooo|M4DosyT#!dqQ+O4z=@+Xs!6TFouCy%l8d&p{;nCCn#ybov=0%(O? zH1~BmfE{nk#M>33Cwz&3zq6Q*D(7Ygof#4~U|?2jot$`>7O+2z-U^=?-1cNvi%%EUs zT5Ox2pYPH}pY<9e^n3xSOroZ;|1yq)CBZX|Lw6+~{b_w0t03~gx%uYao0h?8VYL13 zKqD~BJhttgpB*~i zU@i1q-?^Tjb5{2_-d){^V?enP`O1TLf$NiW{+Vm8o`rybuzLPpwu>j9%e3h)#9vuB zkN&)5x!zzB2>24{L|Z@K9GDagZYPi6^&WZXiO;>qE6w?Ln6pr@1qLZR%!}IJ=9kz* z+qAwXeNIBB!ectdmZzt$ho{Z&p=An+M@dGiZRf7{i+mUQ>%%tjDXtC`I6I%2A>kw( zvPA3jV~l4Wl(66W)r(rWc{x!JGao97Zq_#u92qfaqK}^tPftf&h0m;KRL=I#zD5d6 zD&aJg6XD24U+F$aRqPb)TG#@%^eHIdkEyGl3gJWu)?vAm>xgD2KW{oDE_1 zP_E;1L60NRR>bw~dU?u!7g>pl)35KtJe)PY$@O=dj5fEAkT8v@>)dx}EcJTL;L9MM zvU6X@Ni)#?og_WKgP8>7QcZS7Fs3x{X4oO9xDy;C#Q-f+B!q>|o}Jz-y3Y%xVL2J1 zUFSQvZG;(v?H@VVZr#VHKupNA^}P3)ice*J@NRpc3fyj*(;l%g&WR-&t5mQcTo6`GdA~1y4J~>$>;JjyH1#!_PGl$liHi# zork~qQ)RJ^Mca;Q7pbx-6VTbTuh~&11l>WhO1S zI3Q!SX2u0ywxj2B4ci?x#8NAvUJP;R>VO+|g4Wp`d^u(3p>hh)v|ia58Zht^nm=+} zmP^$JNe2_mGZ`Fs65yLvqTQB9Exu1>uJ7ttv7SG2%{e|W>1Zn$asoWuhlC!S$MvZa zGIQcYM9yrp`fM^%P9~rGCcL;#&mVzSPICR|R)T_gNf~o+hL0`xdz?UWQhp3pWT5%H zNnEN4jIL>qEg(24jcv$73))yJ`4+- zHJ|f&#PWDe$m7TU<=83`iF0oMq&w~1(z2>om)HxRGuy8;ou|A%c%s<%^1h)H(t0E( z2>gBub@3wr$C`l2`zmiU?=emc#2ytL$LENnUIdZt0miB+Xr1_RWAoYk(fqD*UFP`2 zIqt{%RUS6pq4^HL>&0(kwOLs7;Dr-`@6EM=C9b(V_+g0HX`S9+Rhr?>u|JP(I$q2C z`;iX~(U1L#3Y{z?CYYgHpxYRl} z#(m^L0wvn~KHqV8+t*B}@5C_Q$~8T-_N`-I>JXO7=T>r>!DP8aadhj3m>Oj{7&!O0r~!yv6N(AOazubY{iacJwZ%s2vrQ}0R!R1e~F?{qDBw1gr60(%qWI%hK!tK>BOBM|n z$#P}_0LFZ~!E_m}xZ+}ibcg@#prhV76O;Lj78@H^-M8O!gB5Ndd!TWMg?YxSfGV9#Cn`O2RQg#a&aGJ?}H)OaZEh z48!fbpq~yFjU$jiQOm0V?#{b*01)y+OX04$+WJl+#BF5)VsfS!n*zG%F^-iWg`hGO zDSwgcnNsZ(e2U$)gUq>S>s;>y`JAyQFae}%lN%&+2!awWwVe%~7c1sZVdvma`~A;# zH^&ayw9B!^H_%h`97h5Tx{4taLDtnXmBs;!^aRwb@%y!H+I_b)!}hQP(G&2e6ZFJ> zG3-q3)?(#P6ZE*Ur5+hib+&d64$Hb!*IIKB%Kb8CEX^7i9vx{?%nd0!np4}-9Up6vq;w>tNbqt}C} z*~OZ#TAhQo@fQOq^{n=aTP@OZANj*Jm8di`_iANIkq-jmbVFt#wY>AHTHgtj&qL>~ zBrIP(AWz`TdF8C2jrTvADHzrDZg-N-hhRreu57EFs8`VC(mla!x=`9>mnR7R?UmEPRwjb2jAK(byJr?WMWQO{+v}eM6P&2P zr>$ezzK&P)B$Wx=y42r?9(N0Mfq<6>b|kK@ht1x6rq%Hw)4{2V&HnK*u|s;s!lF09 z+rh*dLK+)8e8GnZAI2wPH6OL=fCYI*{=T1$ZGS*$wAroyYF7?hhXac za*8JCe_*rGsW$rt2QK#3G^jk@xL7+x7oD5muZ>U&!sfHy*b<&@ypp4z=%ass{rt?x z>y%&2#|}SO=g}>narIej0gN^fv|l<{B=f0qz^E1nYPM2s?jHH7K>Rk$qy+?UtWE~z zQ;%?f_ySB*09&SkH*ug0(u!2>yImCnw#OK_B0`p_HGvDyY6_1ZsitjcCbZ&gZB=5Y zni`N}FT4khQ>G^2F-j5uqw+`Q=H#^00zY7#*#tdFjpwF=;V$RShQ4L*D_6HQ>Nx6r z>P&W4%f|p;ysJ*u6S}KT6z*w2S?4{O`+a|c0B1&hpgMtB?(IaD$kMkv4%p&jl&`xL z_Uu!uzs}@0P&a=+{_kY<3IJ%69T~KdK2CGsbi-GJJn}^4OZ5@cRzr)T@k*il2f6H< zguowjBu7=)9z~rF1`!UgJe- zZMJcKUNIroIwRvu84TD9pKV!s-Wpw{z4R$g#%V@kxFO)>B}Zh27X(P~l;buha&mj# zOfq6qH&j661l7>LI5+AWH4*lNkl(6U&c)zBPwW{^b@VlLWc;30Y&flu8yA>EX=Va^gGvS^8ZP#2XlKHPJ4{o2rXVBsSw1%&Tbi2b$ zZsO4!GQ7!=R%ez9JMiDDpT8^5#BNp$*dlJ3AETd;$j_Ny=CjBkJ_vpT*%kIm)mY+s zMUF4b8=u!meKS`nO?+o%1>4ED8ao{fU70G`-|45Ipo;!Ta!V;&BMD!jg#}Hxp68)+ zj)%n4@t;hr@`@WrSD7UR5GJ`Cz8SZIM`z#Dcm2CspX0)ou5=Ks%Wd7|y=6+^Xy-iy zs$R?8Juafv;-mEe`jZ40{l)Ggd#l^iY5VbydTl5M&>S#;|0KS~@31dw|IqzV!vAUS zW#0H%8-;j1mLJVJA{9FyYImpbuIQ#7OzyBp40)BFUr3s(_SOc3BiPX_xKe$OKE zG=@J_n$A9zXO`F(J~!QUnW12xnK%h;ocdK+#++CTzVs$+hV@CD4{Zj^bBsGOWrOqn zx60j~Z&YCG*htSf8C5Q_<`ZG6`DgvB=`IZ_#67OnBl8W?rzW=9u%s19kTitnLi5D+|q5 z1YkW`p{>}->t3+-(=A^YrB5ZRv_aHncXH0FYAV*+Y@8xL6{o)$Duwa$bH0r{Y{_us zEMYr35mg98}}ohwFb6|wn_Fb ze2MTysLcCtK4iWy)Wz&tMX|DXvnLN9le;bcv_Fn@vD}i*?_JbZ>1b;N#8)BbE42o< zRu3>5YoXZ9#lyr_n!iae306f^x>Wk;J$qWua!Gvgjjb3yOi4l^X4`VH4&r?M$c=;H z#|FEY8t`Bp8L8}GbXX?2S!yyVF(`YLRwZ#0zSn$*S+Ge2J`%pi1YK4TWE_QH0MRbuR(H99`Crj}BHTAJ!mewZO7k2__vq>GmYarfC zt)@$7Pu9yjkCAGLia|rEDt$5)-Zl<<3=bcyMHF*wYn2Ykjwds*q21YcKK4!pttM$Y z>pq*L##gXXzxTCk;YM>b$=x-%2Ji&;lZWX?_8z~3>tc5Hhkw5rn9w=Ly9kcpCxKA> z0_^vDwJa624m+yP9z`JlqfDBWxZV7fKkLWw%!ynVd>Me+f})Y=*yeKE^Cvv&mWOlE zw=gow`B-oU_L8Km3y(I@EaT=Yw-HyLbrNbxYH-i3zw_;2(yVf; zSKsz=9OLIY)Ajgli>)NN64+QTujnG$q$|~Kursn8$8PN#Ggflk1*_JJHNpMpX^Uh? zf(d+D>)Ex=5C3lL&g^lLdP_%X2Y!~X5)F*TuIFm*=MTOt*M)5n$&%8;pWlJS_HQgF z8+n?3ws~OkzZboolv$nM+c^a7)sv(m5w+X1Uw_4o7ZU{ScIXbcMeuL`7h}}t`CO^o zN>4?&EQX<@@L8s~_Rb)RW%7Q(d~Aap?C&3hQ%UCGn{sT>e>Dq{4JidA^OHF)If||I zowE=0q3H-i{?}L88&%vyWGVyvW+(-K_8Y zVpp&_DmD~+=xOPD_W6q`^E>agZU3!H+^&EM6Qg1O-nkN4lb-(uGx4Q+D2Se7n^2=w z!3vWPG-@TOQPw4nuU-2IkKly%BrDp_t9r4(8tuf$Ckd`2n)B&Lmq=oxa9(j)QE)0^ zNUW5pj$IfvUs}M~D#0lPH{rOH)9o8@G({E0&$jZb%R6uP32lC!O3e*hu{Tf>5+ z9C3h4L*$aGeT(=5D#K?hm^kxW5lqe`wbAz0fW@gj;|Nfena#Cpad3mXfq7iPrjn#i5D%$@I#=b{s4rU;bFPrrW{6C5m3^y;8^s zl;Q2QpW@6h*W6^#3g?FAhhAG};=80V+Kz0OPc zyt(7V2aTM;Cd)rgHIXlJvdS9usaU-?uiK(>a>0sQxr%+eK1?#Na=YPXy@ioe%~hbe zuBrmsbui-NB;6R?N`M{M?xv6yxkCSt6#g}9x^p(It%ETx0CE`Vv)H>{@o!_>5kA5O zpV9kU(%Ehj0&^O+ioN6me6F?E9N96TJ7T*HEg#0j+U$6)k24-K3#CIJsp>fA!%!fT zsOpigmBB;8OA_tcN!~rOv}c2jb0oET9HXh4&7dWskuiu%_v7!Zt?C4{BxCbN(%(86 zJO~B}eG}=g`Db*4B&m}iNpv|A&%iV=3_F)(rrgm6_BXt_wqvf|;ko&H+~Z6zGCLo~ z_u@QRzG8^NpuN!pWr+o7|NN;W@Tc?{S)$X}x=NQ+bK8OG$DSIYdu_jeNf3lUUb0~S zn9h1WpYOOsz&VYPfUihIM_=1m*qwoM9Cw&iPNJby?moZ~X8o3nC#jldPy0R0ojK-t zi6n*n7`(_;j$j-K6^KvLvRghfvidVa-<~<<4p3&j#)pF_lU$j!*T;L3F-FMtbwert zt^O%=a5NFj&RmU_9ZEa>2RnuQQ@z?}4GUY>6T{Xb3^qqBs-^loei8U!npLZNCuQ>v ziG4#z>j+(t&k>#$?1U$Go!)NUOKWhg>}fEK+aYwQAfsQO$iALLGxm@j2Ng*saAXFI zF@{xL(ba(4u(I$ZxwCuYu?W@HWuK*#s4kDMblv^d^6;Kb9vp1F-p!=;!emd|TecCo_0x?-%n86iUdy_Y;#JImnV`OXgS$CUH z!KJDjy~*{VN76?rmR%*IGhaSq(fN3WbP^vt&>-)5_`AI7W{)k>BLw8F(Zf3UGX$4T zHN%HrSPd`Q&*~3raQp=6?_B2WCHv&pd@(Nq03YNiXVe z{b0YpJMoZx+W4L;cX{Ju?h*?-c;-k4vi){pCzi54FJd<-qNSyEx(Z8#t%BHydtiVLq0ZV&qgM9NBthv0&u53(mjUo1F79;8=^Fc@y}deX zA1AZz*3T+Y(U|~tvsA_Ojz=i5g;X3)hT^>-rZLKIaE@e|(X=yGvMR6ow>~I-?Y|j- z_f|B7FqXvGJV|!COEk}_#Z}s>`aTRS{u*f`gCsd~9!xVq^^L%d(6}$+sVGS8ikGHk z2Y`5lk_o5d08xt^1|{pL%8&`kVB}0f2V4}SsFH^xww;M}l$BlWf1I;zQk=P-=ast# z2)3;t2tWXbFnM{k*9(>oRdOd9a6HD}z>OoA!x5F`aNd7H6SBNa@We^7vbsbxKO2QS zQU(VFSRO!M6h|6xrf@!1UfV`3@{)=d3RmlV3!`|Rb&s=`tHJjS&HRfS4wO>Y=wycO zY?lU3UXxH@e^&HbOX#zuN2eyq)9qm@<}vMudNSgG-Z(ZBq}@ND{%KB!l^p^*4)>w4 zXj#IjIU(n5*RiY|oWq?*pw=X=0z;3SSW-9eWdD8_hW40lwZFF}4gIIj*gU+VrIqY8 zvVZyF+5IQ!*zTL+JgWZ*5Rcqj4wOP=g3a!`*C#CpOryJaAc+BoKi#qg6z&G;3_@6^ z#d_ps+k;1bkDt3n|12#rZoKnx7?9J~VV`aYYxSyDzT6J5#?!tDK!mtzyA;wU-B3;n zh*-WEK&p?FVOk|+$YWFq%JRrX+#q&_@cBpo@ZWIIBm0~L< z7;J5<#UitGT3;u#MS+1aYgqhnMkH=K6+OVde=P3@7aq?ld}HIt+k{Ya0X4% zoF8*{U_D6^PxmJP++fTy#QxDVI(VGCtGaHFbOQH~$gOp-5eYLEN7{wK#pZtGOcQ`k zCgDC;*YzgWV39iVsK)1?)W0hmzU8a(^T8b*o`X^*;X#B5$)H4 zKLvi^7d>1eaqj)M`saoeJ&CK}#%-y;wjsOc{p?;pPUqaTeRB(zmfkg$w5}hh96DH5 zPj!Os>3+2>dtRND1c!~+^$B0_U6HjU1cMv|os!bZ1a#D<@R2J;zv) z)!j!np%?FceO=SgA!HIoV|ky%v^hp~*jqjPSM2|&z;P$l#vE9i2~Amd}^yIIbP zO7f#3aGYgnfXHub1j2@lD$T6ZpEtl#P-7{j&LBj+#y{&ky0^0LBtM)r`f2ADdx%@| z=rzP(D*rltw6&3KJf~dw!SQIrhd+uWMcUc9VaK=gf08zp64kydwXS@-99x^ z8z&s!N!rn|_DsdbIf?Ty>-b#sa%^FepCBn{=OmHa{oPNO6SnVNao}q3QlXcs9!&6{%d}nY zvAB8e79<(~Gk=SK&wBqLgfciV{C+wn$}&^@VE#M9p6aXZsv~^O_}wII)@SM1fL2>> z#^D*C;jD@G8c_uj>R7YV4rhJw3=>k4POc4u6rI?Qp{UrHYXg3|jH~POY@3~)y}m9z z0rg2jOX~OzvkznO(a1V74Kqsa#Iru;NJMRduzq=y<4+H~ufslPr9Cy(Y^R& zh+jDdFT9SAO0WTm3BP*Wg)_WJ)K~Vt{MOw)fw{ zCwP;J75h5w%SlqXZTIMa0kT+9<>%(j1q&_5{m4+9kjjyXS!(BaguE|i3{9MHR`!$7 z8f~Sxal<$7$F>byOBWKn<8!;HO!FW6*}|}rkxgM8#&}|SfH($B3#0&3#gYXyqW^ZbAV3*- zj*Vmnrc}g2c!h6fkxbb9XHe6_&y@dWu+@uI8L)}spmk;jL7xA$wyXiHeO6WJ@sCsy z(S62%;ElkvGeA@j#t658dq4vJ3)Lqvz8%-$7pYx~j(rK6DIK zy{7rVd92hDdV^wRQ4J!$prcL^qau=*A>?{VRPtok&@_)gVvhv2_n!Z5X&_!7y}0g zn`Fcoc}+Ms@^z8%IOp@hlweRjiCN2~_nc%k&yUfq;L12_pGgI^9a8m72G$rj&h*|* zO>YR)B#9rrfcWWNvJGJy(8H{)C)pg?7Y8}^*H7mt$QpZ7&p3Zw z-H*;ZzbCyF=hX7rSSSx)w&JETcL*p7j2mF;8h!3ohN(?*)w5NuF(2WH zF%;jRFZr2YoKCX;N*3tj5xJDJ2^`(N{#EfT~B zkP91FnkN}e-jBq{$n#B-V|^EYPrD!VH&}NS2R@}VXmdC9Oknw&yeGI-1`(13=$C$$ zF+jhQNLn)ab@?+nlH>VWbQYZ?z}tczlnCHHYNS#UD6O;~gC^<$k4TE3Lb$*0=ennh`Vd7c{^7XvC;u&y$iD5tn~zVoIDyU( zh)OEv$bd3yrW=0tVsy@;BZ3pVN5}C8x#@z3WoVt0*$#C3COKd2tC?j?WT<05wwIYk zk4%a}6Mp6pb$m1mQ|RB&Y;FWB*z>1YDf`=I@agwA`CR59umD>L=Dv7Xl(^|2zBW40 z_UQ#7Q9f@u7;pYNex7Gs7YJKbADuJj_|eVb*v!RQSY3NP?7WflI(tpw$oS5V;U=C# zPzBXW^1vYzu`O5|K`+D^g>ZyXy0mhSZQ941Fr3pEC+*`b$N)rw4hDi;;GGpM%Q|gG zv083{x^FE-v_^d7z}HVa{XDX;hh)$OgvmVSGwk0)o|oKAD$Utk8;2-rf`w%q29`54 zQ+Yx`?S8e~rrp^mr#)M|0}y(J?vXGQjm)MM@Ss^qnn=1FF__Qi%w!ql9KhyW8~3_i zuc{5iI25wbKS`2#oXcTAm8UR zs|PGNT`35>3VSj}tr*Jp5p0?aEP+Pv{yZ&qDx`bu8qe&$`u2C$elaR-MKrJEF;HF` z_AL&f-*tE{Ylz%oWZa5IXG~Affx7Sc!V|#%#Q{$h_vg1|;q3E|#sI)i%L9LIcd901 zAQib@-)Td4mhRd?&g+r$M!tmn`$N4$d7xR56%NS zdCoKS(E6%YzDnAP6SN$I8AJJe{%0b22xorXPIa}aRQK3tTPLVVTFe)cT*VPWCo?X` z&yt>?KZ#3ZV>J`Zhr)d}d67!??eLzf6I+gpnNDj1(vRGx`{kfdmi?og+b#C>>>C>? z%f#*83Jn2q5B=tn3fm#1BxRs)f>Utl)w?l3?|(l5tBJFnRLE8($#ebLTtix>xOv_W z)-TBkD(DkQsG$6D@~Vty@9{#+00CgxR(HXBrB!~8#Mzb+)Hb5NceT%-n}PqxU=o9G zpeq9En*zxp8Fi4i`3HQ`V`tg_8vvDq%XNk=OJKCdy%V43XC&f|9*6x+Z2OhBCx8T3 zT&WM{IQZ$Bu9;j-*~)ED;A3}5_bW8CtmEK1*H}%$(_5+1y_EPjIm6EIk?_ys%LF?l z0=eZM*tUPCP%_Wz1cROLzv*^l&pL}&=}xD1>25o=(wO_;(;`W~Oodg*1J)8~)(6j9>HM`sX`;qc;)VQ{-uzvVp?J3ah^@ z-Rp$7q7OeZ(4C+hZ94{BHO%#b(7w8KK9&Q7$go^G zbG0IxhWcEHWvT4t$RRQ2;)IgwbO$yHB;!@r>X+rPwEIGCRP$QdKi>qCHQ9-^_=|{- zpZ%$t#A>lllHcaP%9xb4mOLcaOgpbq<=*N(qQelqArTJVB0B=3jCF5J5*%Vp#(sfk zx;*GfbT9V2@xytFE)-|>w-qu)BL2eTuuRkWjy%xKtw{{Dr0;dd*K}f> z`T#6Eqhlze4HuAYi@|vU8UoT1-r3{|{=4FF|Q{On{&bFfjYiYe!gOR;# zrQJAW^?Qr+;n&XemClVZ99pasLbfZMxITZiJc>Z&Uw+nH4``t5ey{>Z=>6_$&pV_8 zWm|`6l=R@lYi~P%{uq#Cm!6>Pr+S%hjWX;NY6e_M`nlez?Z_buD-)%UHXtcGRCbtZ z_d>u{a@*kJq%v46ZfRLk9;b2wiI2NX+W6k#&nV?JuzK&@li3Dat)qdFZG$jv{U~J@ z6$!tilS3WSC8cghk_5wTOMQ!^Q%a&?)*7%|mCWci+R^Ge@BBKOcMgdt9J-@#jP33S<5Te6IqR^|8YyKtgknS|bBBc?)xOv1kkE#IpB*p)Tb!!w_ew=AEY zDi6C{Biy?dNu)RisoF6OG%XkuM-!(7oQ^Am?hoUa_Wbd8kAKgQhn9>rFuk>HlBUm( zb@cn~G@5~-+lk#98PMlG&x*!xWkgh!D~?Y0c~rwPexCL7or1$VP%#dY%kqQYo;XZE zZuqP7u^hftE`HxzC9)J8|7~x$0G}=U*6X`MAI)kyib`&8Z7Fkp5Mn*0mz6#7IzN-n zhoG(7E!)3efzc!q3MYD=+213s4MtvI5|!`ReAPI0#=)E=_ist2OyXqrda$AG;)cI7 zGvKfp@@*ZXTQlUWwG}dH`qwuQ!+tdhK& zoDnw!1xmkbD-p}qCL6%f)?>?fPw`v|0r=(53hzzAzOmifB0;|xhYW&4_R}VL--}yd zKNx2}EOsOD#NgJ+b7v;T6ch&_&T|y)r}&Wg6tYbEDu87=A+zFB+qDXQ z!8g-mWTP`j4!MejY^0=6lgPym4dgRx-;qlPXq&vgH^2XRE>H20cu~?YPN}9iH7;$d zk2}+ROy=Zz5Ibkd2HJbB=V8hGVLXueL3&k>UW*n5u(&nniK;wsp)Bk+PNpJ18-XL+ zQ_3}J^;V8dscV89iJ@s3wALkk{cbxtqilYev)zgJB++Ykz0dMc!?DY*sS=!O_c%gc z4>msH<*IL2ll&H~R6DKnPwm8yRO8muYF5!UIj z%U2Fk3A_X%&Z==vy`3CNb~J=qr;=(-5pdaQ!R-+a04+`(D?M^+{puK9fO1nmx^8dx zpa1bapY05_H=)uFAEN>0)Q`kjP6wPx7>%R20nq?>P-!g_2DLke=#`lL&z3G=cMP0L z!ihw|$O1U(JzozSvNHw5;&fyR`8mnjkHhj9DHdEa8nRkbJr@DW>n!{E=1W67z_y=+ zp!L7rAv7g}=Q`g&ImxO~mFsiC{w#)3JRI$twRGryEt+n5I-8h#GtmVOlqT>J*o1Mn zoR~>txS7*oFxEQj=_`X+4y#zSh|};S+(MC-iWUxd1-_Z!I40H%3ps znxSOj6U2-GG%W$t3+=W1upDv)-=dI}hmRmf%45Z#(Yh5`$Rqrhq;yIyhlH>0sU}X6!40j2+iHH=GQ1J_@k>p6`62qnw~35n9NK zCwxzHLBh*oU+$oaK8l1~nOB|RS9}Dyj}k~JzCb5S?j!e$#e+*Nju^cIU-jTe84Jn( zWCeC^!#7`1YtF__s`YEHO4?h2#`cmJ91)w(R*_QgOx~V--pJ3kE^jJw{FqIY0IjHW zx(u$1DI~HJ`It9xDkhLm$AF>oP4*y~sZjenM;_#9s!Z~S&VbT4voAWBFn(isz1SQr z?ezX`|Jc&*)!g~T_#UsVoaCeRq4ED(w2_8#3^fZKW^ZNO#s|j8Robr?qthKl(Gnqk zj$+8tt{Qv7jSdW8OG1Q1zn{I6_hF1X{XDNGt8h`{^zp#+ve=?fwsn}+(j>N24#bzB zqn?$0m+jpQ{qyfgh95AXrZ3#Dq@#sfsZih6-+xcVm;m}oXRCr6etz>Dt{P^U#)4A( znu+OsBt$*Fz+@a(1!R8;a&u(JlZaU7txl$|kRyPMBhj8SFx!~IsJtGAi-Xg%H@bFQ zFltG)1=V*(%p|*wX_2qBoqKbK#5Jn;xO04??3=CBmfCR(F<^fB%zk)|2*&XdnlbM` zBs8FEQ!UJ!^c=I12XdZrGPq|A$FfUT!Rd!uh0@xPqk>@ORcWpxkn|`^uGu-txtw`m zt?{D&rVa1_-z`-FeT0FmrSFNf1eVjmfLi`Ej73tF%FLY4v!kLSv0^)Y102cb{y2pj z?96%qKVWSuKYThJCnD>QVeAMIbj{g9=2 zv<0eUo+oR1UH#!~R9e<8R3!@?88r{|s|SSF(Hi5+^z*W_xUI%MyK1BTD%ei%tz^?x zU_O)C6-6OX>xa)o^W8J07A%DZ%#bjNrz+1csiXu^QD6h8fhZ0tK$WZ3XkR&g-2D7F z+qr@0C_jN^hIBkKRbevksRTJ8St7}i^}?d4H*tq^khT$w*%-hxhpt8zLXTeOK55cf z&|&Iy)pXXBHb6g17v4_mx!Q?9a^&cV&EsG%lhD1FGXRFOmutD;6~V+Exe{sbB8j=w z`tirSKVXpmV-zC_{!UC5$w5(laKI1%z%lkT^oF0c^gPeAB+Gh*^J68Pr%0fNEVZ%d zIH|fBZ7lDs?O1l*z0~J^&^#_zSlM_Xhc)IML-lBwkkHCcw~_$Q z&l$d5l4T=VmT8c#%||via&W!pLjqc7_8TY7odw>%G>Ibh>e!EqbmkKxQD<50$035V z;~;R`%X8K)!e!ntiabfXtu`D3(rd?;$1#>_%V;X=_yA90;8?F?$Do`mjw|Pt>$;Ng zuq-KZHSc)PC2T$a#p9uEJ^SasFA0K@rZj-@bD-Z?mJKaa1hC|M2*zvt0o{{srEjEh zb%D0q(%D;Vcu%by^s@~xKf#ErK27IFrbPGR2HgYCkwSc;lFe)Nd^nv3w)OS#)CSVUU2K^CHdoIOlyM| zX#!|hm6J5{npgN6sfbMW^UU<&xJ8#6f*QZcz9@r@gR0m?V_E#av(Hz#(I~gtbQEXA zWCGS>0l(7trm7VEz(*44$p?6|pVsottIMn`_Svya(y7>5uI1zAv+&9l)=Z?JXceim zFBJ;Y5%s1KSbzP{yp3UR!jCIqb49mGJM0)!^Z0u%9E{C8?kF;z$3EHf^1F9HXdzvZ z!_if+&Bn@!7!rA98F&jV;9@;?B#GuEOc-7cfN5k+9s74!3hVMwiM}-nZ_ycW#tSKF z3u`U{03Ok6WdAQ_uTqwesgT6ktBSo>J4Pc;Tey;o7sQs`<>AQvC|`wd;Qp@4Jn{hg z(;a)4_jMR2;?YQSYuf&;lewnwflOWQ6bQ5f z(^@k$uVUFlE5*0mi{$s?@En1;wGtH-86U&RKcL^@~=pao)9#MQz|j zRpmUTi;X3ofn(@lc4kLA_ZmZ*=eor3=RN*l!{+~zy9w42SxIhWWKdoNXN5AGo}46iIa8R#)s9RD!Ciej#>G+CPHh$uZ37v0;9L0K9!?-lvtuV>BmMU z`O-|ur^~08cIEFPLXWY;h?bupjqSX2aYlUB_{9J(K+wPa^xD8b6^p#aXxVo3RK~TD zt%I?|Nr`aU$-bncR=&D-(mqD0HC;CZc%gN8={D4~anGh_9l3-tP62}ZI+g>q720n| zUsIhp64wt7l-0;{5~+)bqmx>E$kRG!VFw%9>m1uMLy79K2g{sIT*6Nbi@y4g1 zjDySmo5hUNaR`C;*M8Sk<*Xixk}E-}M1ZLb)r$VSh9#++{ERLvCOuc*pX<6_HK0d? zFesQ*#sJ{6yWhkHF?ci~i0%Bv`3n#^Ve03!iP7SYY;7lv^yv7*d&KA!2m2x;d^?Ixu7F*%(CYjLMDk#tS@xf{pF-bG;Lq4B<2SIS}Bv0#)>`L6G6}*1*u=p%` z)%y;fdlK>BpCE=~3m*$QN8zHxFRpj!GfAz8ociA7OJD27CRxy166I65KRTh0_1M8| zl2w{Dq|5U8Ol8QReFXMp{;b=&m!6_$K`Ed`<13zQw$y#}p52#|n^Ppa9%h#?cmqi% z-oa3v>57~IZMA+tmuE9tjxIDCp;~_mdAAKocZPBJM<3unKQn!hm&_P~2I$iUkrjQz zwhTrCtTQWVo^jlzm1`JzzuTDXPUIMMz4|V65cw+2ESa@-6C1c|h+DC0WtKsXLsSpj z>d$suO3rbTWVei;n&3RgzWAs0sjcWO`5OBO zp_s?j-RVY{+na_FSB{Unjb~VuTD#ZMxwIDbV?ecv#UEN^vZ+$Y?_9+a1Z^k#+_)wZ z8EwFk?8zjd#=u9pdWEkp#3#GxXPi=6m1T*-(YN#=K>eBL1*CU(+MQV;Y9+2L;KDda zGsV;aoQ{(oy#r4sPqE5H&LorBF)Vg4nN$zWcc@XDKLb3soK-XO9=|Iq?-KVd4;Z=a z14rJ@8HRS8)B)Ig#@U`W5!z+X26{z8W9cwgCC2(B6U*7D?RMNx4G>(kBKw7}BphfO zk(KjGYA2yyWoi175G(?BjCz~yTzO~yU(*5L=04nd>CT$JWH@)o2IuPLwRR4RMOOm$ z(GKh}Ewm@#{5smIonj%h;SF3ddZ88VNN$~KWDETrXN<&2)zu7pG7U8JlI;iW>oTD0 z92e4O_P_+$-o+E}4(~qEV=}nc>*YoflxDr8162g{Cd=c6e67ZlgwLsWCd$azZa5Knz%tT7l3f3NWw98H_sj z>LT=fjINMbbeMmh8%!&6j|t+5V_J-CaN1c7Z@KG)G+eMLtc$2#BxiHR`XvM9A%YA4yV z)1hmQ;?{gO=jo5s?%W#r!aj1l0MwORKsSBa>c`ewPTf^TVj(xrpr`F=#65H{3G$Az zEYIy1i>Yk0AKzkRuYLWIp3ahreqsYh9j6^4VCvMSvsxY1iM$tpyFjsLh@bKL+fvwKKQV2;@Ucy&KrY2Hk$D^ zr^-H_3u5Vd&?Yo*(VQUlbDgk1e-XfmP7+MFqav;=OgE!S-^=X)1hK=*v`q`KEi#NF z&%B1423iyN#s`Kc9=on~cgI;9z!A@8H9dUW#@;-Kqs80?#cT=Hv`EKXgLjS_l4uJE zOqcTJH8kGvtgr^y76DbZ##ARfg3YYx~lfo5w3dcUiNsW&qI%AMiX4r@q>}Tjirf zV8thHLdB0rM|pW4lBCb*X}_`0JYoC6fIzV7WbawNdSl_J?KT@h481|Qy`voQ<<4Zvg!BJzk?eA1N}XUY zclb)$E(F->r>7Bph&>k*69T&d-=dgFU%e#W8XvRb5vz?L2ocP+qCd$FgH$-jl3$THJ9Q zgD_H}3)x|4$&u*lRn^*)=v{|TIB^1FP=Fr!{sc2f1RgsBma(oFb?{-0rS-WL!&fP^ zblR^cLyd(#`F?pXFK_(B=nDo6hp$?jNf$V!@N>1dqazqLvdBMIH70C^45R^SgYZBk z0fliGL##d0go9HJ&s@QXZFoPq!K%8I%D!mlf3aDiRV7MlC&+0+@A51cjr#fb!OB*B)&`dCP$7S{d?E2vQW65433@|| z8@dl3%q>0*D~9g}Y93?%YbTP%482&~+fscCTmIMw0wi>~Y-{0clc4O(;!rUYMoC=f zO2!PHBe_HZU-9?e6bu*@%3Nzk20PqN5ynEoAH9n90N5;6}Y-G3z7<73+V9Wr~p$ zx|YrE_MEHxBqJ@)Tw$kQ4u|10G^&IKWVP?N~{K8EdeZ%u}R-0!X z*Gs=1hWWOZ8}kIcRtM4hk++*Yaa%>z*;!TR81Gwh)jvsN+Zx?Fcgvsg9jB^)BJ*mF z#*mae9+o(eL)*T!QbJGElf}Tk*zcH+l=tLTaQi|@`symjjxN6W6eY%9W23M3I>MFX z8Op!5W#GOOr!;N)H&T(rH}ZX8;w90b{JECx#4P^k;wGOBpf4# z9Xpx<$Y%#Xf-kdnf_v1aqojBLI=`u#xTJdv!u7Eq!SM0kSsrTA6t+@F+2a&&$yV8p zfGIVW(5+VU0}s1@fn@&E1ip0Ecwx6a$NVC++xE3t|5!xfF*Gd|&!B~e#MXiNudkHs zS$Tj9m07+qD{Z~^?PlnVHJ8??AB-vsHj|d~%o6~{+2Q&J*Yn+iU&-X8ZKyFIrR(#m zt-apJn&TDVR7m}u_wGbnfU0dsZKxVY)&}&6DN$af!d?3ubNzKrHaT;iY^1X1pCAK+ zjX0d0gpa_cYI9lkWV>gw#CJ1JUh@ZL{1`eriU84>B=iZ-0ooI%W0cYl)>lUKai$LY zCorAQe^s*woT2NI0=bltPZAAE6E4WP2q~}m1&j%O<=hd?p17$TTnvP>);VE!zgHhzk5HQGj-TV z@8@Ztp3meckdPV~f0ZGXBZvudaqkDboe?IjghouAenM!Kn)4e8pCnw zo14hUyMcj<4w zl;nG7ZLIv{Bq|@{4$mPNd#P9z|MNZrBS-m+_$%M%oC*IN2p#)Y!wBE4yOvv7tX3~K z2Jg+d%X*kk4vp8@!PWSzjQQ~=SxDnco&QgAq-Nk8zdO)+XxvwOMzxRXs~Id*oy03Q zt;ksILBYW*l7>G4t`n;l6FL#12nb0W_3^P8l5Q<=wdvR&=PhF^w&hO%~kt>h(~YVGxi<>y%!r%-D7>E{+DbR^(qyTQ+Jg1TeB z%KRq54AyKC)_bmE;RFo2`2tKAObUbrmjR z)clU%_7-2}p?e)INkH&A^GdLJ0A3?*050~IBwaws@@^RoUL3?jRYxBW`;L?XrR6H? zMzfLk{%qif&!DcHQ&vgmLXXl(WqmOMxtn;zyTIRJ&p4~_NoiQnt&dRcsA1&9F@)d0 z9bf(E_53!sJjekZ*b3O6yEl3v8~9@&cy4Fj zy5&xQyq-2a&CG+ArZ0SGSrLPp9IR!Iz4fuY7T9BK4Xs)qo^Lr=1gjrEBY}AEr1rQT z1KyL|nF1ommW1!vV=r^dn>d!Y0Y85xRz^u8e8xF&s~ns8#uY!KwYN$DN;{sdEaon3 zJa{k(J7Ng0!e=joWZ3F)QpM4bs47WDO%egxa&;n5x;nVn{B0*^N~*d#4E0E>T1)5L z1v~{3k|mk*K|V)(QC!Zk&x;0&fm5^MY68bE!Q%@u2s(yX`5DT6@1YyWp#D{zvv*NF|C{EpTPiA-+`XZsgGr#f@*W)1tfn|#uz_ZcuU zS?GBu&#fne%Fi9v5vVz{HiB`GFRAYk``#Ff*vpGE?dP;j%q8ek9B)RQB;(wgdq?fR z=_-ai_p_RZSz;4>_Q=Y;dj`^pXY zkvDKKf4RY80-(tj=S>8EQFu0}tPdkOPjPl!v=Vj#z5z-H`geetvpiJgB&oj)NvZvw z;wNp;QvOULlQ9Nd@s~y7d;z=()-1Q@1Hu}|(EHC8T5I>1b9({)haQokm7N-odn#uB zIqj1BgIY?OFDp!yYE9ass-i2?GTS*8q}^H^C)UP%kYlD$89??})lF8G4Rr$4F%;G( zU!Pf=!Su|DpX8e~iIDCXuQ(l{gZ0I&sw7?rq6e$znQ4tPo$Ji`==RkRwA4-Y+ggTW z^FixwBpCg8^Q-Cbc+B>( zb8=lpWbJL|e-k}BZ)Kd6sRAcg(Yuqa_2bM#jO9~Vm?vY8fJr%r3wC%l@x78k@BF{I z)!z|=^Sx{T{JEunEAuz7FOuqmvRS?kI?0c}wuwWwRM^?OZC3@0m)>)|T%{VuK(V8n z_Ih>cn>Cw8PF4rAv11IvZTF8vxZOSQcrD%EB*=qL=t;51(mN5klc2x};=0wgzd})w zgfsfRRm-iJdHqh#Bm?y5F<5ZnC;p=`WK63uxsWOL*ocZq%BjAaoq-FMnahwou%H%K zgMrc%DC~>G8E5I{&uMI6OKwvg2i}@UKwONbUEgMsK}d)Kf}2n7xItrM*ry#;>)>`~ z$jSZQL|QG4OCLM_HxBKXEGKd5isK|F!tt#4cwHsq#mHOQzx4(S;gIp{W0X=>k=Px{`Fm*@XI=~vi4*;xK)$)#@@C0hs^l1qL?tTi;DU-KBn#2*Lp~@ z13k4as3*3X!H6r{6G9#1CpVqR7&Y%cC}UlKaGFBc$eS@?qr#VYGDLzDI9-6Rj^>U_ zpRJvP2mZXjXC=ziMc!w?b(APvHL@hA?KwDnr8pnSiYiq|T97$rl%Uf9J3#HqJ*~Z^ zRBrqwQC$|w-zYa4=ntnOW0D8CR;62gP8h|RnoRgFg8ZAw)C7~I%C&;YVpNR-QHYfk z>vuF2>BkUp9uA788eqYKa92w!wzMJNIxFK$*BU7d1qSg_QP>ll(>6ALPhF4TzFWyG z<13JzP@9f>MPC|{G0+HW?Tw&u;BJI<26ohZf)-&}c1lO*1Bk;{EB;e4J zkKy2)lV$U{UhA2rV>&u<(n>H@njnJnyaeJTzHp3kC24P#n7II(kCzM#Ybc~RlSAX3 zp+JECSOk%9NX@uf1Uubuo9B;1^5O>>SgtZ18V>za*kYya;b*=UhL*dd7M)Ya!KKhu zX&l`ghHbsaDdI@*7LGDCw=9o{np3t%U4*f`8`qT!a$y;_G$kBrEzo6z@q#>6Ms z@ZvFg4^|dNFsk^?J~9voTnipKDeVDvWA|F6Puz=&GhqF>quJ+!?%J{RmTY~<2|EALBdhKi0-NODpx&WD2%ABevWEWP@C7b|qC zCow{x3>L%!^x9fpsovn(x+T?KN9!N4q~e+0#_>UzA+phleE0Hro@1wH0H zS8*kh>>iu3<~O$h9I#TZ*jk6|Q<46Fc6&q-Nb6t{zc16Yj7uXo9lasozmeDe`OM|m zP;AS*`<{`fIwWJQ=fX!Y-Aa;-tJ(W&Q;=qOiwM@UuL@=p-HqA7hn9;875g=^^i`62 zb@jpTbmC)R@>LXvs z-D77-&fT5t=n3{pqB8*~PmjOdKJUMYR2|QysCF^3v|K$-Kzon&F>|e_lddfv@9mCV zn3w`wp(uRQ`OZ~%Bb{CkGvsQAe}i8zo9;OqDr!qWdGvmdHti8S{Kd>*vdXt_&BK2R zoLJ^_Z1N+~k;OL~tVAXBYi z;h-YG{_Grs_~SWMd^=_y%~pfTqPy|#WGqIeVg`8NHhM?3U8nzN2Oh)OYXB+zi|niV|! z5V9@Baf=?QrSF>jwBJ?`ZNByg6K*1~dID50yWP#;{Z0VxZ$1f*&QYzqyn3rHU}jBX zI5HRkrY&=1~h?YIHj(T5Zpd@xlgI!bt`45a7$R{!aE^3A%G;{`uE43ZRWj@~7%^v5ySDo<4pEy{qeM!} zc$X7VJfj|(@4u!??z@3Qbii8H6*^o8ZR0a7jxvyQ0&6^p4G=pE?d%PB-y2b`Zaj<= z8R+LOrVJRB?J3Du9Mcuua&^MGcTsXTXavt=RPAp5%`x@3LeDYXv=s@R)XB)(Mm2z~${3!@fyNj&waqbZ*F~R3nr0Z@15PxtNA5 zEDvV@G<=}ySeP0G)Rv{uu?FnGNAaKdQ{UhYH$7}2XK1XdUmw`Vhq9_s`bpp*Ctbti zhAXaG+Gl9v^2f52LRyu(-6jz4WG$40PqB$dFVM+YyQiA7^KvX79v&wtM>4sgrCluO zzT0IMem*wgkUZ`1Tku;oXTnWYaBbA@JaTf@4hECw9d&lyUf3(BqKlV7u;8Qh1G7;n7**Z!(~YB0{+KBtq~dUjJz57kqfwgw(utHh)TD z-hi6$tc5R;nFo1h2RA8NWd?z;C#CL_LeR_?w%%WhOJgW;{IcL)L^`glBm!|YzD@w+ z%B@$;Cf8{wk*VHOPV0rte;hl-RHgu@WuVWZ`mtA?soV)1yxwG+lSt@%Z}?UrQb%4E z>JdX6C$e{3ueI452?NX1TRn*?8=7%2YzRbP=!f!mDij7uy>D?ac~x20=o491uiUu{ zvi0?>jP<^w4pHhiqbxfK7`fLtY^A5cBIVcxbU0sm@VvO921CR^t$B7SgF4`q;4MKK z=Meq-4oojxkzq<;#Lq1|wL`?}$(&V5UqIPl2yl$E)S(A$WF#L;6$1bk_LEf=yRp7> z%QGSXI!(3|=frJh-}~L?!3$SF-}|5eSeb@-X5_CXAP8t_X=Q%?+z{a)VJp$Rimd+t z#&pwEOhZ|QW7^8{X3GyiW6FFWe$XA- zsiDby_Uf!XDc=)7(nBQNOas=yZ6y69X4{E(D_7@;&0y@t3imNFPoS%@aY@$0=ZF6* z)5quY&2*KM?gSg!bK<@^>{vW^QQZg1i>P zvxWq-=?qsoPe6D()#=3oYZuovqByi6`-c;l9#P|ZQfX4rF8vHct#z==!xmCm;x%V< zGdH+I`n8`?&!BYn5a+xSdDZq-2dy->PJ%Jm_@<@wmCCW!c zZ_!cc&+fop5~HJMx8!TH9{F(gom*6@&T~fJEAR0el0dQ?4SZljz}odbsyhV{k*qO! z5%1Pl%w*wRu}792_N{*0dx9K!P0i0{Kk-ja#m}6C;$EwqgcC_U=vdOU^UqpRWz}Hz z)*wuCu-mTCa+~K`N{b*}S@%wchpxs?@)7@!tv_4Yep|MDp%(oabI!GLrF*+`TVRP; zqo9I{wMQ0M-+^?;F~0YGp8vo1=n*X@X@cL^2y}U z5Yy;=)Hgb|O;G23>+d(Yd@C`8e+fR#!#b5>^Sm-!-|RT&#aZYjU?4mtdADq#BrdmX zs}Wgz#k+aemWL{C3vu}m1g&j+hhzVEEC>I%r1Pog`BZXw-mNt18*_f}^zqiazDD2& z2i`s!xL9fQj%z_%R2uAq(6^D+H@f=(h+0(7Y)+Kn5zJYpKZ$v-K=*Edy%PZvpOx$9 zL*d=pYiC=SJnu&SU6#`Ev5sen2C7fwtm@byIbiyRXyb{gEV`mvV8n*s|Ezo^;4LRH4rCS@oHtqas$!Av6LnV@GHOaS6KY2FfHTkod^bXcz?hCClJYwJ*+53 zI66z zK1=<YHaXu6+~blfe{N zc^iMOo(U7qThBOJC-w)7JJSfbnl94&s%4Bzw43HA++Gj)%)if+=mkU1jx&C0e?Ec5 zG(+12ZER*{Kcp)5-=L@iv=q-0FvpSFW*K2YGLD|N*@~2&+D;~zHHz3)d1QP%SIF7s zRdUalpG4HC8Anx+()@EyLc}8&9>MAsC`LZt#)E3*dZ-g3`S}AejToxZMflLK=7}b- z7xeKYfK*b)v5Bb=`sit-$efZ)Pu0^ksmU2@lC%0D#98iUm%i*?D*Ntw_LIE^8#E+o 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%0ADP4Ra?!4sFEG3sczt%i?}p^o|Jj5mUWBjAdGK z!eA8iF_?Pn=)_gyPOs;}914-DqZn#3Jy`Lk_r~~EaI~{apC2*gj3Am7+~r>BYIKm{ zwzxHC`=bqZ-G1UC-r=M$%~<<6#+h#n78beM*!5w|p7T^aN)$F}6U+Ey_9p!YVSV>eEY z_Y(`^(;wYsIl_nqWeB<+HyXWQ$7{YYcLARmV>eXXu9X(hIiFivi#6(aawey!#uDs4 zFrhze7VtX`fmgv&^rOVk-9e9uhnD^EigYWDAuQd6GuSw=9$lYw=}tuQtX0Mks&O1u znh^nX1V&U<3@+G&5Dd@3Z*jf|#+mU^PC0^9>!8B~#@H%C&w3N62?J{>;vAOR41emx za-LFyeV^»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
UW;acW0Fg=nSRTiJ6k-|@zYBKYhVu(0B2c0 zaXegdclfKho$k)4L(a#rc9eSbvz3-4Nf^S%z=`9KRMfQwHO$IA%`rYhus)wa*{l`6)Shkdrr1oFzn=bNn#Fo##q*AQw2x+QUI0Z!ALv9)jsqOVi2 zpwb|LI9kBdQz%n!cF%VeR>{utT!c9C`1pLXLBk-;5r73pfMlNj>L-;aNU{!f{FIS_ zM`a2@-?6bJu6r34PMbTEMcZwaFYW9NFdp-8He9WMd5mwSo+kCM#;R;EgZjU9XslZ~ zujK$^vf6g0Oq5_I|AkhCF+0Xu(9`l`-Cvr{53cU02|S02#m~wKDa*+K4#oxNVYK+3 zH?7E@SMzkvKklHc%KDPYq$|a8=sO}N0nr*Bznl6A|KHJ_!AR@QvxW;`Yt!q^>wPs< zrnwr}&hV&V{qpbz>GR(w^!?=c)G2dBz z;nPEh0**sR{zG(Qx4P5Xe8I7-Aw#Q2N!%ct@bMXkYWDI*7vfC2Y8^STVa}1Lg3m4P zvGrzyaUp+ekC0e4>(DXBzPjVIwV75_rEkZ@D;3wob}7zSD|-j)si?g5H;ENHIpMe5 zDh`)I=egFD1dFUU^Z1q?>(#q}MRJ7XN2Q#wa&%Pz!%5;GiKl*oGq*T4_^T-0=7> zmc|rjiUgk&_2F-M?jxD;w%q_;!&RjU8ku<>YfIY~7~6fGXu_bqem4JQo`>=9$sCX6 zRcu*T65i2?T3eV`8IGz?Cy%FYwP^(gJ?=(XDpcON$8nChdH;`noSpIUTLH72Vzb|7 z5pVpDH`Ewg@F2HZTl6GZ)RE65D|(oHKq&o@Ky|OJ;W@(&s6fVB43u&zlSe^>z?hRX;1j~L2nLg9jOXq4_g*z-uxqNA9~N{nvhm<#~ZF>y~`iW<(1L&Jn33yrF+VrTVY2+j+KNLPS(qoAO*A5=m%XgfJ#*lRH`yOMy zaX-OtEgsz~#hFDRJ<4^{>fjju#T+X%=G~;fpUb|gEqC~e#yZ2d=r+bKSPXu@`b^H%iI>OsIoInwbVR=e-{UMVki7PxlC;+O{0D)pSKz=eA}HqB ziGud~>Jz^|H3L}jQOmcDsa3!K{-^cynao=T$GvA8r-R^%gm~8L#ZT4|0Ra5^2wWXu zX1e8WlFa)US*oDv+YpJI$7hZ)q{`=5p68AobTl!}$ z^SxvUyVZXvWe

9dY}r@oWkYtmKAcUGMB~Xh+i!qkXE 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%0D0rO^%rvyG3yY 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Þ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

B0eRC8vOLZYqU__IoZtdPmx5%A#h=9Ym(jgx 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

BtS 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

yJOaMPA(XB14ZpSYaeX7~F6)I~ zYm8&O1rFyuoU%9R+1LP&y53? z?ptjgb9LRW@1tT{*HX04oAkMh=vSNQuCT9K!@eWy?`nM;1>=b`>~uK6>LQFL&2q}J z9wkYFG$CYJkFvZ+S(*n47Gh?g-xI@((VqMDoOv>e8Lrj;aAfpKGr4bXJjSl^BoQth zPSIhCjmG(ownw=x>AtTuc;J!t@my0MqMod}WL~Q@Io$F{N`oVzZHpKgqUBh2bnWTS5EZdE|aMEW- zzV8T5cHEiuFvHfE#*FZha?{Z5#~M)_EwmPI{U4>ETMul;X+=k(&Iu=p?{iYr@7Kr*fqFIaUMsF)pL*OcT{z z!&uj&2>@sX_^;OA! 80", - labels: map[string]string{"severity": "warning"}, - annotations: map[string]string{"summary": "CPU usage is high"}, - }, - ), - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/cpu-alerts.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "name: cpu-alerts", "interval: 1m"}, - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "cpu-alerts", - expected: managedAlertGroup( - "cpu-alerts", - "cpu-alerts", - false, - 1*time.Minute, - "test-project/alerts/cpu-alerts.yaml", - now, - now, - &typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - Id: "HighCPU", - Spec: &typesv1.AlertRuleSpec{ - Name: "HighCPU", - Expr: mkQuery("cpu_usage > 80"), - Labels: mkObj(map[string]string{"severity": "warning"}), - Annotations: mkObj(map[string]string{"summary": "CPU usage is high"}), - For: durationpb.New(5 * time.Minute), - }, - }, - ), - }, - }, - }, - }, - { - name: "update managed alert group preserves marker", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "create managed alert group", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("cpu-alerts", 1*time.Minute), - }) - return err - }, - }, - { - name: "update alert group", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateAlertGroup(ctx, &alertv1.UpdateAlertGroupRequest{ - ProjectName: "test-project", - Name: "cpu-alerts", - Spec: mkAlertGroupSpec("cpu-alerts", 2*time.Minute), - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/cpu-alerts.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "interval: 2m"}, - }, - }, - }, - }, - { - name: "discover external alert group as readonly", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "write external alert group file", - at: 0, - fileOperation: &fileOperation{ - action: "write", - path: "test-project/alerts/external.yaml", - data: []byte(`groups: - - name: external - interval: 30s - rules: - - alert: ExternalAlert - expr: 'up == 0' -`), - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "external", - expected: discoveredAlertGroup( - "external", - "external", - true, - 30*time.Second, - "test-project/alerts/external.yaml", - now, - now, - &typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - Id: "ExternalAlert", - Spec: &typesv1.AlertRuleSpec{ - Name: "ExternalAlert", - Expr: mkQuery("up == 0"), - For: durationpb.New(0), - }, - }, - ), - }, - }, - }, - }, - { - name: "adopt discovered alert group via update with is_readonly=false", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "write external alert group", - at: 0, - fileOperation: &fileOperation{ - action: "write", - path: "test-project/alerts/external.yaml", - data: []byte(`groups: - - name: external - interval: 30s - rules: - - alert: ExternalAlert - expr: 'up == 0' -`), - }, - }, - { - name: "adopt via update with is_readonly=false", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateAlertGroup(ctx, &alertv1.UpdateAlertGroupRequest{ - ProjectName: "test-project", - Name: "external", - Spec: &typesv1.AlertGroupSpec{ - Name: "external", - Interval: durationpb.New(30 * time.Second), - IsReadonly: false, - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/external.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "# humanlog.is_readonly: false"}, - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "external", - expected: managedAlertGroup( - "external", - "external", - false, - 30*time.Second, - "test-project/alerts/external.yaml", - now, - now.Add(1*time.Second), - ), - }, - }, - }, - }, - { - name: "detect generated alert groups", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "write file with generation marker", - at: 0, - fileOperation: &fileOperation{ - action: "write", - path: "test-project/alerts/generated.yaml", - data: []byte(`# generated-by: some-tool -groups: - - name: generated - interval: 1m - rules: - - alert: GeneratedAlert - expr: 'metric > 100' -`), - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "generated", - expected: generatedAlertGroup( - "generated", - "generated", - true, - 1*time.Minute, - "test-project/alerts/generated.yaml", - "file contains '# generated-by' marker", - now, - now, - &typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - Id: "GeneratedAlert", - Spec: &typesv1.AlertRuleSpec{ - Name: "GeneratedAlert", - Expr: mkQuery("metric > 100"), - For: durationpb.New(0), - }, - }, - ), - }, - }, - }, - }, - { - name: "lock managed alert group (set readonly=true)", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "create editable alert group", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("cpu-alerts", 1*time.Minute), - }) - return err - }, - }, - { - name: "lock via update with is_readonly=true", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateAlertGroup(ctx, &alertv1.UpdateAlertGroupRequest{ - ProjectName: "test-project", - Name: "cpu-alerts", - Spec: &typesv1.AlertGroupSpec{ - Name: "cpu-alerts", - Interval: durationpb.New(1 * time.Minute), - IsReadonly: true, - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/cpu-alerts.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: true"}, - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "cpu-alerts", - expected: managedAlertGroup( - "cpu-alerts", - "cpu-alerts", - true, - 1*time.Minute, - "test-project/alerts/cpu-alerts.yaml", - now, - now.Add(1*time.Second), - ), - }, - }, - }, - }, - { - name: "delete managed alert group", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "create alert group", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("cpu-alerts", 1*time.Minute), - }) - return err - }, - }, - { - name: "delete alert group", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.DeleteAlertGroup(ctx, &alertv1.DeleteAlertGroupRequest{ - ProjectName: "test-project", - Name: "cpu-alerts", - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/cpu-alerts.yaml", - shouldExist: false, - }, - }, - }, - }, - { - name: "cannot delete readonly alert group", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "write external alert group", - at: 0, - fileOperation: &fileOperation{ - action: "write", - path: "test-project/alerts/external.yaml", - data: []byte(`groups: - - name: external - interval: 30s - rules: - - alert: ExternalAlert - expr: 'up == 0' -`), - }, - }, - { - name: "attempt to delete readonly group", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.DeleteAlertGroup(ctx, &alertv1.DeleteAlertGroupRequest{ - ProjectName: "test-project", - Name: "external", - }) - return err - }, - expectError: &errorExpectation{ - shouldFail: true, - contains: "readonly", - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/external.yaml", - shouldExist: true, - }, - }, - }, - }, - { - name: "create alert group with multiple rules", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "create group with 3 rules", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("system-alerts", 1*time.Minute, - struct { - id string - name string - expr string - labels map[string]string - annotations map[string]string - }{"high-cpu", "HighCPU", "cpu > 80", map[string]string{"severity": "warning"}, nil}, - struct { - id string - name string - expr string - labels map[string]string - annotations map[string]string - }{"high-memory", "HighMemory", "memory > 90", map[string]string{"severity": "critical"}, nil}, - struct { - id string - name string - expr string - labels map[string]string - annotations map[string]string - }{"disk-full", "DiskFull", "disk_usage > 95", map[string]string{"severity": "critical"}, nil}, - ), - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/system-alerts.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "HighCPU", "HighMemory", "DiskFull"}, - }, - }, - }, - }, - { - name: "update alert group interval", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "create with 1m interval", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("cpu-alerts", 1*time.Minute), - }) - return err - }, - }, - { - name: "update to 30s interval", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateAlertGroup(ctx, &alertv1.UpdateAlertGroupRequest{ - ProjectName: "test-project", - Name: "cpu-alerts", - Spec: mkAlertGroupSpec("cpu-alerts", 30*time.Second), - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/cpu-alerts.yaml", - shouldExist: true, - contains: []string{"interval: 30s"}, - }, - }, - }, - }, - { - name: "cannot create alert group in readonly project", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", true)), - }, - }, - transitions: []transition{ - { - name: "attempt to create in readonly project", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("cpu-alerts", 1*time.Minute), - }) - return err - }, - expectError: &errorExpectation{ - shouldFail: true, - contains: "readonly", - }, - }, - }, - }, - { - name: "delete and recreate alert group", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "create alert group", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("cpu-alerts", 1*time.Minute), - }) - return err - }, - }, - { - name: "delete alert group", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.DeleteAlertGroup(ctx, &alertv1.DeleteAlertGroupRequest{ - ProjectName: "test-project", - Name: "cpu-alerts", - }) - return err - }, - }, - { - name: "recreate with different interval", - at: 2 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: mkAlertGroupSpec("cpu-alerts", 2*time.Minute), - }) - return err - }, - expectFile: &fileExpectation{ - path: "test-project/alerts/cpu-alerts.yaml", - shouldExist: true, - contains: []string{"interval: 2m"}, - }, - }, - }, - }, - { - name: "round-trip alert group lifecycle", - cfg: &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("test-project", "dashboards", "alerts", false)), - }, - }, - transitions: []transition{ - { - name: "create as editable", - at: 0, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateAlertGroup(ctx, &alertv1.CreateAlertGroupRequest{ - ProjectName: "test-project", - Spec: &typesv1.AlertGroupSpec{ - Name: "cpu-alerts", - Interval: durationpb.New(1 * time.Minute), - IsReadonly: false, - }, - }) - return err - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "cpu-alerts", - expected: managedAlertGroup( - "cpu-alerts", - "cpu-alerts", - false, - 1*time.Minute, - "test-project/alerts/cpu-alerts.yaml", - now, - now, - ), - }, - }, - { - name: "lock it", - at: 1 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateAlertGroup(ctx, &alertv1.UpdateAlertGroupRequest{ - ProjectName: "test-project", - Name: "cpu-alerts", - Spec: &typesv1.AlertGroupSpec{ - Name: "cpu-alerts", - Interval: durationpb.New(1 * time.Minute), - IsReadonly: true, - }, - }) - return err - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "cpu-alerts", - expected: managedAlertGroup( - "cpu-alerts", - "cpu-alerts", - true, - 1*time.Minute, - "test-project/alerts/cpu-alerts.yaml", - now, - now.Add(1*time.Second), - ), - }, - }, - { - name: "unlock it", - at: 2 * time.Second, - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateAlertGroup(ctx, &alertv1.UpdateAlertGroupRequest{ - ProjectName: "test-project", - Name: "cpu-alerts", - Spec: &typesv1.AlertGroupSpec{ - Name: "cpu-alerts", - Interval: durationpb.New(1 * time.Minute), - IsReadonly: false, - }, - }) - return err - }, - expectAlertGroup: &alertGroupExpectation{ - projectName: "test-project", - groupName: "cpu-alerts", - expected: managedAlertGroup( - "cpu-alerts", - "cpu-alerts", - false, - 1*time.Minute, - "test-project/alerts/cpu-alerts.yaml", - now, - now.Add(2*time.Second), - ), - }, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - fs := memfs.New() - - // Create project directory structure - for _, proj := range tt.cfg.Projects { - require.NoError(t, fs.MkdirAll(filepath.Join(proj.Pointer.GetLocalhost().Path, "alerts"), 0755)) - } - - var db localstate.DB - var currentTime time.Time = now - - for _, tr := range tt.transitions { - // Advance time - currentTime = now.Add(tr.at) - timeNowAtTransition := func() time.Time { return currentTime } - - // Recreate watch with new time - db = newWatch(ctx, t, tt.cfg, fs, timeNowAtTransition) - - // Ensure project is synced (which registers it in alert state) - for _, proj := range tt.cfg.Projects { - _, err := db.SyncProject(ctx, &projectv1.SyncProjectRequest{ - Name: proj.Name, - }) - require.NoError(t, err, "failed to sync project %q", proj.Name) - } - - // Execute file operation if specified - if tr.fileOperation != nil { - switch tr.fileOperation.action { - case "write": - err := writeFile(fs, tr.fileOperation.path, tr.fileOperation.data) - require.NoError(t, err, "transition %q: failed to write file", tr.name) - // Re-create watch to pick up file changes - db = newWatch(ctx, t, tt.cfg, fs, timeNowAtTransition) - case "delete": - err := fs.Remove(tr.fileOperation.path) - require.NoError(t, err, "transition %q: failed to delete file", tr.name) - // Re-create watch to pick up file changes - db = newWatch(ctx, t, tt.cfg, fs, timeNowAtTransition) - } - } - - // Execute operation if specified - if tr.operation != nil { - err := tr.operation(ctx, t, db, fs) - if tr.expectError != nil { - if tr.expectError.shouldFail { - require.Error(t, err, "transition %q: expected error but got none", tr.name) - if tr.expectError.contains != "" { - require.Contains(t, err.Error(), tr.expectError.contains, - "transition %q: error message mismatch", tr.name) - } - } else { - require.NoError(t, err, "transition %q: unexpected error", tr.name) - } - } else { - require.NoError(t, err, "transition %q: unexpected error", tr.name) - } - } - - // Check file expectations - if tr.expectFile != nil { - if tr.expectFile.shouldExist { - data, err := readFile(fs, tr.expectFile.path) - require.NoError(t, err, "transition %q: expected file to exist at %s", tr.name, tr.expectFile.path) - content := string(data) - for _, substr := range tr.expectFile.contains { - require.Contains(t, content, substr, - "transition %q: file %s missing expected content", tr.name, tr.expectFile.path) - } - } else { - _, err := fs.Stat(tr.expectFile.path) - require.True(t, os.IsNotExist(err), - "transition %q: file %s should not exist", tr.name, tr.expectFile.path) - } - } - - // Check alert group expectations - if tr.expectAlertGroup != nil { - resp, err := db.GetAlertGroup(ctx, &alertv1.GetAlertGroupRequest{ - ProjectName: tr.expectAlertGroup.projectName, - Name: tr.expectAlertGroup.groupName, - }) - require.NoError(t, err, "transition %q: failed to get alert group", tr.name) - - if diff := cmp.Diff(tr.expectAlertGroup.expected, resp.AlertGroup, cmpOpts...); diff != "" { - t.Errorf("transition %q: alert group mismatch (-want +got):\n%s", tr.name, diff) - } - } - } - }) - } -} - -func managedAlertGroup( - id string, - name string, - isReadonly bool, - interval time.Duration, - path string, - createdAt, updatedAt time.Time, - rules ...*typesv1.AlertGroupSpec_NamedAlertRuleSpec, -) *typesv1.AlertGroup { - return managedAlertGroupWithStatuses(id, name, isReadonly, interval, path, createdAt, updatedAt, nil, rules...) -} - -func managedAlertGroupWithStatuses( - id string, - name string, - isReadonly bool, - interval time.Duration, - path string, - createdAt, updatedAt time.Time, - customStatuses map[string]*typesv1.AlertRuleStatus, - rules ...*typesv1.AlertGroupSpec_NamedAlertRuleSpec, -) *typesv1.AlertGroup { - // Build rule statuses from rule specs - ruleStatuses := make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, len(rules)) - for i, rule := range rules { - status := customStatuses[rule.Id] - if status == nil { - status = &typesv1.AlertRuleStatus{ - Status: &typesv1.AlertRuleStatus_Unknown{ - Unknown: &typesv1.AlertUnknown{}, - }, - } - } - ruleStatuses[i] = &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: rule.Id, - Status: status, - } - } - - return &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{ - Id: id, - }, - Spec: &typesv1.AlertGroupSpec{ - Name: name, - Interval: durationpb.New(interval), - IsReadonly: isReadonly, - Rules: rules, - }, - Status: &typesv1.AlertGroupStatus{ - CreatedAt: timestamppb.New(createdAt), - UpdatedAt: timestamppb.New(updatedAt), - Rules: ruleStatuses, - Origin: &typesv1.AlertGroupStatus_Managed{ - Managed: &typesv1.AlertGroupStatus_ManagedAlertGroup{ - Path: path, - }, - }, - }, - } -} - -func discoveredAlertGroup( - id string, - name string, - isReadonly bool, - interval time.Duration, - path string, - createdAt, updatedAt time.Time, - rules ...*typesv1.AlertGroupSpec_NamedAlertRuleSpec, -) *typesv1.AlertGroup { - return discoveredAlertGroupWithStatuses(id, name, isReadonly, interval, path, createdAt, updatedAt, nil, rules...) -} - -func discoveredAlertGroupWithStatuses( - id string, - name string, - isReadonly bool, - interval time.Duration, - path string, - createdAt, updatedAt time.Time, - customStatuses map[string]*typesv1.AlertRuleStatus, - rules ...*typesv1.AlertGroupSpec_NamedAlertRuleSpec, -) *typesv1.AlertGroup { - // Build rule statuses from rule specs - ruleStatuses := make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, len(rules)) - for i, rule := range rules { - status := customStatuses[rule.Id] - if status == nil { - status = &typesv1.AlertRuleStatus{ - Status: &typesv1.AlertRuleStatus_Unknown{ - Unknown: &typesv1.AlertUnknown{}, - }, - } - } - ruleStatuses[i] = &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: rule.Id, - Status: status, - } - } - - return &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{ - Id: id, - }, - Spec: &typesv1.AlertGroupSpec{ - Name: name, - Interval: durationpb.New(interval), - IsReadonly: isReadonly, - Rules: rules, - }, - Status: &typesv1.AlertGroupStatus{ - CreatedAt: timestamppb.New(createdAt), - UpdatedAt: timestamppb.New(updatedAt), - Rules: ruleStatuses, - Origin: &typesv1.AlertGroupStatus_Discovered{ - Discovered: &typesv1.AlertGroupStatus_DiscoveredAlertGroup{ - Path: path, - }, - }, - }, - } -} - -func generatedAlertGroup( - id string, - name string, - isReadonly bool, - interval time.Duration, - path string, - detectionReason string, - createdAt, updatedAt time.Time, - rules ...*typesv1.AlertGroupSpec_NamedAlertRuleSpec, -) *typesv1.AlertGroup { - return generatedAlertGroupWithStatuses(id, name, isReadonly, interval, path, detectionReason, createdAt, updatedAt, nil, rules...) -} - -func generatedAlertGroupWithStatuses( - id string, - name string, - isReadonly bool, - interval time.Duration, - path string, - detectionReason string, - createdAt, updatedAt time.Time, - customStatuses map[string]*typesv1.AlertRuleStatus, - rules ...*typesv1.AlertGroupSpec_NamedAlertRuleSpec, -) *typesv1.AlertGroup { - // Build rule statuses from rule specs - ruleStatuses := make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, len(rules)) - for i, rule := range rules { - status := customStatuses[rule.Id] - if status == nil { - status = &typesv1.AlertRuleStatus{ - Status: &typesv1.AlertRuleStatus_Unknown{ - Unknown: &typesv1.AlertUnknown{}, - }, - } - } - ruleStatuses[i] = &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: rule.Id, - Status: status, - } - } - - return &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{ - Id: id, - }, - Spec: &typesv1.AlertGroupSpec{ - Name: name, - Interval: durationpb.New(interval), - IsReadonly: isReadonly, - Rules: rules, - }, - Status: &typesv1.AlertGroupStatus{ - CreatedAt: timestamppb.New(createdAt), - UpdatedAt: timestamppb.New(updatedAt), - Rules: ruleStatuses, - Origin: &typesv1.AlertGroupStatus_Generated{ - Generated: &typesv1.AlertGroupStatus_GeneratedAlertGroup{ - Path: path, - DetectionReason: detectionReason, - }, - }, - }, - } -} diff --git a/internal/localproject/dashboard_lifecycle_test.go b/internal/localproject/dashboard_lifecycle_test.go deleted file mode 100644 index f55d7b15..00000000 --- a/internal/localproject/dashboard_lifecycle_test.go +++ /dev/null @@ -1,2345 +0,0 @@ -package localproject - -import ( - "context" - "fmt" - "os" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/memfs" - "github.com/google/go-cmp/cmp" - dashboardv1 "github.com/minitape/api/go/svc/dashboard/v1" - projectv1 "github.com/minitape/api/go/svc/project/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/localstate" - "github.com/humanlogio/humanlog/internal/pkg/config" - persesv1 "github.com/perses/perses/pkg/model/api/v1" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/testing/protocmp" - "google.golang.org/protobuf/types/known/timestamppb" -) - -func TestDashboardLifecycle(t *testing.T) { - now := time.Date(2025, 10, 21, 10, 56, 42, 123456, time.UTC) - timeNow := func() time.Time { return now } - - cmpOpts := []cmp.Option{ - protocmp.Transform(), - protocmp.IgnoreFields(&typesv1.DashboardStatus{}, "created_at", "updated_at"), - protocmp.IgnoreFields(&typesv1.ProjectStatus{}, "created_at", "updated_at"), - protocmp.IgnoreFields(&typesv1.DashboardSpec{}, "perses_json"), - } - - mkPersesJSON := func() []byte { - return []byte(`{ - "kind": "Dashboard", - "metadata": { - "project": "test-project", - "name": "test-dashboard" - }, - "spec": { - "display": { - "name": "Test Dashboard" - } - } - }`) - } - - mkPersesJSONWithName := func(name, displayName string) []byte { - return []byte(fmt.Sprintf(`{ - "kind": "Dashboard", - "metadata": { - "project": "test-project", - "name": "%s" - }, - "spec": { - "display": { - "name": "%s" - } - } - }`, name, displayName)) - } - - type fileExpectation struct { - path string - shouldExist bool - contains []string - } - - type dashboardExpectation struct { - projectName string - id string - expected *typesv1.Dashboard - } - - type errorExpectation struct { - shouldFail bool - contains string // substring of expected error message - } - - type fileOperation struct { - action string // "write", "delete" - path string - data []byte - } - - type transition struct { - name string - at time.Duration - operation func(context.Context, *testing.T, localstate.DB, billy.Filesystem) error - fileOperation *fileOperation - expectError *errorExpectation - expectFile *fileExpectation - expectDashboard *dashboardExpectation - } - - tests := []struct { - name string - initFS fsState - initProject *typesv1.ProjectsConfig_Project - transitions []transition - }{ - { - name: "create managed dashboard writes marker", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - transitions: []transition{ - { - name: "create dashboard", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "Test Dashboard", - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog"}, - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "test-dashboard"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "test-dashboard"), - "Test Dashboard", - "", - false, - mkPersesJSON(), - "project1/dashboards/test-dashboard.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "update managed dashboard preserves marker", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/test-dashboard.yaml": []byte(`# managed-by: humanlog -kind: Dashboard -metadata: - project: test-project - name: test-dashboard -spec: - display: - name: Original Name - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "update dashboard", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Updated Name", - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "Updated Name"}, - }, - }, - }, - }, - { - name: "user can edit generated dashboard by setting is_readonly=false", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/generated.yaml": []byte(`# Generated by Terraform -# DO NOT EDIT -kind: Dashboard -metadata: - project: test-project - name: generated -spec: - display: - name: Generated Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "update with is_readonly=false succeeds", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "generated"), - Spec: &typesv1.DashboardSpec{ - Name: "Modified", - IsReadonly: false, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/generated.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "# humanlog.is_readonly: false", "Modified"}, - }, - }, - }, - }, - { - name: "delete managed dashboard removes file", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/test-dashboard.yaml": []byte(`# managed-by: humanlog -kind: Dashboard -metadata: - project: test-project - name: test-dashboard -spec: - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "delete dashboard", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.DeleteDashboard(ctx, &dashboardv1.DeleteDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: false, - }, - }, - }, - }, - { - name: "discover managed dashboard has managed origin", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/managed.yaml": []byte(`# managed-by: humanlog -kind: Dashboard -metadata: - project: test-project - name: managed -spec: - display: - name: Managed Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "list dashboards", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "managed"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "managed"), - "Managed Dashboard", - "", - false, - nil, - "project1/dashboards/managed.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "discover generated dashboard with Generated by marker", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", true), - ), - initFS: fsState{ - "project1/dashboards/terraform.yaml": []byte(`# Generated by Terraform -kind: Dashboard -metadata: - project: test-project - name: terraform -spec: - display: - name: Terraform Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "list dashboards", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "terraform"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "terraform"), - "Terraform Dashboard", - "", - true, - nil, - "project1/dashboards/terraform.yaml", - `Contains "# Generated by Terraform"`, - now, - now, - ), - }, - }, - }, - }, - { - name: "discover generated dashboard with DO NOT EDIT marker", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", true), - ), - initFS: fsState{ - "project1/dashboards/codegen.yaml": []byte(`# DO NOT EDIT -kind: Dashboard -metadata: - project: test-project - name: codegen -spec: - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "list dashboards", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "codegen"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "codegen"), - "codegen", - "", - true, - nil, - "project1/dashboards/codegen.yaml", - `Contains "# DO NOT EDIT"`, - now, - now, - ), - }, - }, - }, - }, - { - name: "discover generated dashboard with @generated marker", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", true), - ), - initFS: fsState{ - "project1/dashboards/auto.yaml": []byte(`# @generated -kind: Dashboard -metadata: - project: test-project - name: auto -spec: - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "list dashboards", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "auto"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "auto"), - "auto", - "", - true, - nil, - "project1/dashboards/auto.yaml", - `Contains "# @generated"`, - now, - now, - ), - }, - }, - }, - }, - { - name: "managed dashboard defaults to writable", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/managed.yaml": []byte(`# managed-by: humanlog -kind: Dashboard -metadata: - project: test-project - name: managed -spec: - display: - name: Managed Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "get dashboard", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "managed"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "managed"), - "Managed Dashboard", - "", - false, - nil, - "project1/dashboards/managed.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "generated dashboard defaults to readonly", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/generated.yaml": []byte(`# Generated by tool -kind: Dashboard -metadata: - project: test-project - name: generated -spec: - display: - name: Generated Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "get dashboard", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "generated"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "generated"), - "Generated Dashboard", - "", - true, - nil, - "project1/dashboards/generated.yaml", - `Contains "# Generated by tool"`, - now, - now, - ), - }, - }, - }, - }, - { - name: "managed dashboard with explicit is_readonly=true", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/readonly.yaml": []byte(`# managed-by: humanlog -# humanlog.is_readonly: true -kind: Dashboard -metadata: - project: test-project - name: readonly -spec: - display: - name: Readonly Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "get dashboard", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "readonly"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "readonly"), - "Readonly Dashboard", - "", - true, - nil, - "project1/dashboards/readonly.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "managed dashboard with explicit is_readonly=false", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/writable.yaml": []byte(`# managed-by: humanlog -# humanlog.is_readonly: false -kind: Dashboard -metadata: - project: test-project - name: writable -spec: - display: - name: Writable Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "get dashboard", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "writable"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "writable"), - "Writable Dashboard", - "", - false, - nil, - "project1/dashboards/writable.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "dashboard with unrelated comments ignored", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/commented.yaml": []byte(`# This is an awesome dashboard -# Created by the team -# Version 1.0 -kind: Dashboard -metadata: - project: test-project - name: commented -spec: - display: - name: Commented Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "get dashboard", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "commented"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "commented"), - "Commented Dashboard", - "", - true, - nil, - "project1/dashboards/commented.yaml", - "No humanlog metadata or generation markers found", - now, - now, - ), - }, - }, - }, - }, - { - name: "dashboard with both humanlog and unrelated comments", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/mixed.yaml": []byte(`# This dashboard is maintained by our team -# managed-by: humanlog -# humanlog.is_readonly: false -# Last updated: 2025-01-15 -kind: Dashboard -metadata: - project: test-project - name: mixed -spec: - display: - name: Mixed Comments Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "get dashboard", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "mixed"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "mixed"), - "Mixed Comments Dashboard", - "", - false, - nil, - "project1/dashboards/mixed.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "lifecycle: generated → adopted as writable", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/external.yaml": []byte(`# Generated by Terraform -# DO NOT EDIT -kind: Dashboard -metadata: - project: test-project - name: external -spec: - display: - name: External Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "initially generated and readonly", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "external"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "external"), - "External Dashboard", - "", - true, - nil, - "project1/dashboards/external.yaml", - `Contains "# Generated by Terraform\n# DO NOT EDIT"`, - now, - now, - ), - }, - }, - { - name: "user adopts dashboard, becomes managed and writable", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "external"), - Spec: &typesv1.DashboardSpec{ - Name: "Adopted Dashboard", - IsReadonly: false, - PersesJson: mkPersesJSONWithName("external", "Adopted Dashboard"), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/external.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "# humanlog.is_readonly: false", "Adopted Dashboard"}, - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "external"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "external"), - "Adopted Dashboard", - "", - false, - nil, - "project1/dashboards/external.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "lifecycle: generated → adopted → locked down", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/evolving.yaml": []byte(`# Generated by automation -kind: Dashboard -metadata: - project: test-project - name: evolving -spec: - display: - name: Evolving Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "initially generated and readonly", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "evolving"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "evolving"), - "Evolving Dashboard", - "", - true, - nil, - "project1/dashboards/evolving.yaml", - `Contains "# Generated by automation"`, - now, - now, - ), - }, - }, - { - name: "adopt as writable", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "evolving"), - Spec: &typesv1.DashboardSpec{ - Name: "Now Managed", - IsReadonly: false, - PersesJson: mkPersesJSONWithName("evolving", "Now Managed"), - }, - }) - return err - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "evolving"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "evolving"), - "Now Managed", - "", - false, - nil, - "project1/dashboards/evolving.yaml", - now, - now, - ), - }, - }, - { - name: "lock down by setting readonly", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "evolving"), - Spec: &typesv1.DashboardSpec{ - Name: "Now Locked", - IsReadonly: true, - PersesJson: mkPersesJSONWithName("evolving", "Now Locked"), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/evolving.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "# humanlog.is_readonly: true", "Now Locked"}, - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "evolving"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "evolving"), - "Now Locked", - "", - true, - nil, - "project1/dashboards/evolving.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "lifecycle: create readonly → edit fails → unlock → edit succeeds", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - transitions: []transition{ - { - name: "create dashboard with is_readonly=true", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "Locked Template", - IsReadonly: true, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# managed-by: humanlog", "# humanlog.is_readonly: true", "Locked Template"}, - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "test-dashboard"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "test-dashboard"), - "Locked Template", - "", - true, - nil, - "project1/dashboards/test-dashboard.yaml", - now, - now, - ), - }, - }, - { - name: "attempt to edit fails", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Should Not Work", - IsReadonly: true, // Trying to edit while keeping readonly - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectError: &errorExpectation{ - shouldFail: true, - contains: "readonly", - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"Locked Template"}, // unchanged - }, - }, - { - name: "unlock via API", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Unlocking", - IsReadonly: false, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: false", "Unlocking"}, - }, - }, - { - name: "edit succeeds after unlock", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Successfully Edited", - IsReadonly: false, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"Successfully Edited"}, - }, - }, - }, - }, - { - name: "lifecycle: generated stays readonly when not adopted", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/protected.yaml": []byte(`# DO NOT EDIT -kind: Dashboard -metadata: - project: test-project - name: protected -spec: - display: - name: Protected Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "initially readonly", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "protected"), - expected: generatedDashboard( - dashboardID("test-project", "test-project", "protected"), - "Protected Dashboard", - "", - true, - nil, - "project1/dashboards/protected.yaml", - `Contains "# DO NOT EDIT"`, - now, - now, - ), - }, - }, - { - name: "attempt update without adopting fails", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "protected"), - Spec: &typesv1.DashboardSpec{ - Name: "Should Fail", - IsReadonly: true, // Trying to update while still readonly - PersesJson: mkPersesJSONWithName("protected", "Should Fail"), - }, - }) - return err - }, - expectError: &errorExpectation{ - shouldFail: true, - contains: "generated", // Different error message for generated dashboards - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/protected.yaml", - shouldExist: true, - contains: []string{"Protected Dashboard"}, // unchanged - }, - }, - }, - }, - { - name: "lifecycle: writable → lock → cannot edit → unlock → can edit", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/toggle.yaml": []byte(`# managed-by: humanlog -# humanlog.is_readonly: false -kind: Dashboard -metadata: - project: test-project - name: toggle -spec: - display: - name: Toggle Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "initially writable", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "toggle"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "toggle"), - "Toggle Dashboard", - "", - false, - nil, - "project1/dashboards/toggle.yaml", - now, - now, - ), - }, - }, - { - name: "lock it", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "toggle"), - Spec: &typesv1.DashboardSpec{ - Name: "Now Locked", - IsReadonly: true, - PersesJson: mkPersesJSONWithName("toggle", "Now Locked"), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/toggle.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: true", "Now Locked"}, - }, - }, - { - name: "cannot edit while locked", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "toggle"), - Spec: &typesv1.DashboardSpec{ - Name: "Should Fail", - IsReadonly: true, // Explicitly keeping it readonly - PersesJson: mkPersesJSONWithName("toggle", "Should Fail"), - }, - }) - return err - }, - expectError: &errorExpectation{ - shouldFail: true, - contains: "readonly", - }, - }, - { - name: "unlock via API", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "toggle"), - Spec: &typesv1.DashboardSpec{ - Name: "Unlocking", - IsReadonly: false, - PersesJson: mkPersesJSONWithName("toggle", "Unlocking"), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/toggle.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: false", "Unlocking"}, - }, - }, - { - name: "can edit again after unlock", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "toggle"), - Spec: &typesv1.DashboardSpec{ - Name: "Final Edit", - IsReadonly: false, - PersesJson: mkPersesJSONWithName("toggle", "Final Edit"), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/toggle.yaml", - shouldExist: true, - contains: []string{"Final Edit"}, - }, - }, - }, - }, - { - name: "lifecycle: manual YAML edit changes state", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/manual.yaml": []byte(`# managed-by: humanlog -# humanlog.is_readonly: true -kind: Dashboard -metadata: - project: test-project - name: manual -spec: - display: - name: Manually Edited - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "initially readonly", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "manual"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "manual"), - "Manually Edited", - "", - true, - nil, - "project1/dashboards/manual.yaml", - now, - now, - ), - }, - }, - { - name: "user manually changes is_readonly to false in YAML", - fileOperation: &fileOperation{ - action: "write", - path: "project1/dashboards/manual.yaml", - data: []byte(`# managed-by: humanlog -# humanlog.is_readonly: false -kind: Dashboard -metadata: - project: test-project - name: manual -spec: - display: - name: Manually Edited - panels: {} - layouts: [] - duration: 0s -`), - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "manual"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "manual"), - "Manually Edited", - "", - false, - nil, - "project1/dashboards/manual.yaml", - now, - now, - ), - }, - }, - { - name: "user can now edit via API", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "manual"), - Spec: &typesv1.DashboardSpec{ - Name: "Updated via API", - IsReadonly: false, - PersesJson: mkPersesJSONWithName("manual", "Updated via API"), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/manual.yaml", - shouldExist: true, - contains: []string{"Updated via API"}, - }, - }, - }, - }, - { - name: "lifecycle: create → edit → edit → delete", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - transitions: []transition{ - { - name: "create dashboard", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "Normal Dashboard", - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"Normal Dashboard"}, - }, - }, - { - name: "first edit", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "First Edit", - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"First Edit"}, - }, - }, - { - name: "second edit", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Second Edit", - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"Second Edit"}, - }, - }, - { - name: "delete dashboard", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.DeleteDashboard(ctx, &dashboardv1.DeleteDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: false, - }, - }, - }, - }, - { - name: "lifecycle: explicit is_readonly overrides defaults", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - transitions: []transition{ - { - name: "create managed with explicit is_readonly=true", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "Explicitly Readonly", - IsReadonly: true, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: true"}, - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "test-dashboard"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "test-dashboard"), - "Explicitly Readonly", - "", - true, - nil, - "project1/dashboards/test-dashboard.yaml", - now, - now, - ), - }, - }, - { - name: "change to explicit is_readonly=false", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Explicitly Writable", - IsReadonly: false, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: false"}, - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "test-dashboard"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "test-dashboard"), - "Explicitly Writable", - "", - false, - nil, - "project1/dashboards/test-dashboard.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "lifecycle: deletion and recreation with same name", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/reusable.yaml": []byte(`# managed-by: humanlog -kind: Dashboard -metadata: - project: test-project - name: reusable -spec: - display: - name: Original Dashboard - panels: {} - layouts: [] - duration: 0s -`), - }, - transitions: []transition{ - { - name: "verify original exists", - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "reusable"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "reusable"), - "Original Dashboard", - "", - false, - nil, - "project1/dashboards/reusable.yaml", - now, - now, - ), - }, - }, - { - name: "delete dashboard", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.DeleteDashboard(ctx, &dashboardv1.DeleteDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "reusable"), - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/reusable.yaml", - shouldExist: false, - }, - }, - { - name: "recreate with same name", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "New Dashboard", - PersesJson: []byte(`{ - "kind": "Dashboard", - "metadata": { - "project": "test-project", - "name": "reusable" - }, - "spec": { - "display": { - "name": "New Dashboard" - } - } - }`), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/reusable.yaml", - shouldExist: true, - contains: []string{"New Dashboard"}, - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "reusable"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "reusable"), - "New Dashboard", - "", - false, - nil, - "project1/dashboards/reusable.yaml", - now, - now, - ), - }, - }, - }, - }, - { - name: "lifecycle: preserve is_readonly through multiple edits", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - transitions: []transition{ - { - name: "create as readonly", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "Locked Dashboard", - IsReadonly: true, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectDashboard: &dashboardExpectation{ - projectName: "test-project", - id: dashboardID("test-project", "test-project", "test-dashboard"), - expected: managedDashboard( - dashboardID("test-project", "test-project", "test-dashboard"), - "Locked Dashboard", - "", - true, - nil, - "project1/dashboards/test-dashboard.yaml", - now, - now, - ), - }, - }, - { - name: "unlock and update in one request", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Updated Content", - IsReadonly: false, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: false", "Updated Content"}, - }, - }, - { - name: "lock it again", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - _, err := db.UpdateDashboard(ctx, &dashboardv1.UpdateDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "test-dashboard"), - Spec: &typesv1.DashboardSpec{ - Name: "Final Content", - IsReadonly: true, - PersesJson: mkPersesJSON(), - }, - }) - return err - }, - expectFile: &fileExpectation{ - path: "project1/dashboards/test-dashboard.yaml", - shouldExist: true, - contains: []string{"# humanlog.is_readonly: true", "Final Content"}, - }, - }, - }, - }, - { - name: "persesJson is always JSON regardless of file format", - initProject: projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - initFS: fsState{ - "project1/dashboards/yaml-dashboard.yaml": []byte(`# managed-by: humanlog -kind: Dashboard -metadata: - name: yaml-dashboard - project: test-project - createdAt: 0001-01-01T00:00:00Z - updatedAt: 0001-01-01T00:00:00Z - version: 0 -spec: - display: - name: YAML Dashboard - description: This dashboard is stored as YAML - datasources: - prometheus: - default: true - plugin: - kind: PrometheusDatasource - spec: - directUrl: http://localhost:9090 - panels: {} - layouts: - - kind: Grid - spec: - display: - title: Test Section - collapse: - open: true - items: [] - duration: 1h - refreshInterval: 30s -`), - "project1/dashboards/json-dashboard.json": []byte(`{ - "kind": "Dashboard", - "metadata": { - "name": "json-dashboard", - "project": "test-project", - "createdAt": "0001-01-01T00:00:00Z", - "updatedAt": "0001-01-01T00:00:00Z", - "version": 0 - }, - "spec": { - "display": { - "name": "JSON Dashboard", - "description": "This dashboard is stored as JSON" - }, - "datasources": { - "prometheus": { - "default": true, - "plugin": { - "kind": "PrometheusDatasource", - "spec": { - "directUrl": "http://localhost:9090" - } - } - } - }, - "panels": {}, - "layouts": [ - { - "kind": "Grid", - "spec": { - "display": { - "title": "Test Section", - "collapse": { - "open": true - } - }, - "items": [] - } - } - ], - "duration": "1h", - "refreshInterval": "30s" - } -}`), - }, - transitions: []transition{ - { - name: "YAML file persesJson field contains valid JSON", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - resp, err := db.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "yaml-dashboard"), - }) - require.NoError(t, err) - require.NotNil(t, resp.Dashboard) - - // Verify persesJson is valid JSON (not YAML) - persesJSON := resp.Dashboard.Spec.PersesJson - require.NotEmpty(t, persesJSON, "persesJson should not be empty") - - var persesDash persesv1.Dashboard - err = persesDash.UnmarshalJSON(persesJSON) - require.NoError(t, err, "persesJson must be valid JSON even when source file is YAML") - - // Verify content is correct - require.Equal(t, "yaml-dashboard", persesDash.Metadata.Name) - require.Equal(t, "YAML Dashboard", persesDash.Spec.Display.Name) - require.Equal(t, "This dashboard is stored as YAML", persesDash.Spec.Display.Description) - - return nil - }, - }, - { - name: "JSON file persesJson field contains valid JSON", - operation: func(ctx context.Context, t *testing.T, db localstate.DB, fs billy.Filesystem) error { - resp, err := db.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ - ProjectName: "test-project", - Id: dashboardID("test-project", "test-project", "json-dashboard"), - }) - require.NoError(t, err) - require.NotNil(t, resp.Dashboard) - - // Verify persesJson is valid JSON - persesJSON := resp.Dashboard.Spec.PersesJson - require.NotEmpty(t, persesJSON, "persesJson should not be empty") - - var persesDash persesv1.Dashboard - err = persesDash.UnmarshalJSON(persesJSON) - require.NoError(t, err, "persesJson must be valid JSON") - - // Verify content is correct - require.Equal(t, "json-dashboard", persesDash.Metadata.Name) - require.Equal(t, "JSON Dashboard", persesDash.Spec.Display.Name) - require.Equal(t, "This dashboard is stored as JSON", persesDash.Spec.Display.Description) - - return nil - }, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - fs := memfs.New() - - // Initialize filesystem - if tt.initFS != nil { - for path, data := range tt.initFS { - require.NoError(t, writeFile(fs, path, data)) - } - } - - // Create config - cfg := &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{tt.initProject}, - } - - // Create watch - db := newWatch(ctx, t, cfg, fs, timeNow) - - // Execute transitions - for _, trans := range tt.transitions { - t.Run(trans.name, func(t *testing.T) { - // Advance time if specified - if trans.at > 0 { - now = now.Add(trans.at) - timeNow = func() time.Time { return now } - } - - // Execute file operation if specified - if trans.fileOperation != nil { - switch trans.fileOperation.action { - case "write": - err := writeFile(fs, trans.fileOperation.path, trans.fileOperation.data) - require.NoError(t, err) - case "delete": - err := fs.Remove(trans.fileOperation.path) - require.NoError(t, err) - default: - t.Fatalf("unknown file operation: %s", trans.fileOperation.action) - } - } - - // Execute API operation if specified - if trans.operation != nil { - err := trans.operation(ctx, t, db, fs) - - // Check error expectation - if trans.expectError != nil && trans.expectError.shouldFail { - require.Error(t, err) - if trans.expectError.contains != "" { - require.Contains(t, err.Error(), trans.expectError.contains) - } - } else { - require.NoError(t, err) - } - } - - // Verify file expectations - if trans.expectFile != nil { - exists, err := fileExists(fs, trans.expectFile.path) - require.NoError(t, err) - require.Equal(t, trans.expectFile.shouldExist, exists) - - if trans.expectFile.shouldExist && len(trans.expectFile.contains) > 0 { - data, err := readFile(fs, trans.expectFile.path) - require.NoError(t, err) - for _, substr := range trans.expectFile.contains { - require.Contains(t, string(data), substr) - } - } - } - - // Verify dashboard expectations - if trans.expectDashboard != nil { - resp, err := db.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ - ProjectName: trans.expectDashboard.projectName, - Id: trans.expectDashboard.id, - }) - require.NoError(t, err) - require.NotNil(t, resp, "GetDashboard response should not be nil") - require.NotNil(t, resp.Dashboard, "Dashboard in response should not be nil") - require.Empty(t, cmp.Diff(trans.expectDashboard.expected, resp.Dashboard, cmpOpts...)) - } - }) - } - }) - } -} - -type fsState map[string][]byte - -// Helper functions - -func managedDashboard( - id string, - name, desc string, - isReadonly bool, - persesJSON []byte, - path string, - createdAt, updatedAt time.Time, -) *typesv1.Dashboard { - return &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{ - Id: id, - }, - Spec: &typesv1.DashboardSpec{ - Name: name, - Description: desc, - IsReadonly: isReadonly, - PersesJson: persesJSON, - }, - Status: &typesv1.DashboardStatus{ - CreatedAt: timestamppb.New(createdAt), - UpdatedAt: timestamppb.New(updatedAt), - Origin: &typesv1.DashboardStatus_Managed{ - Managed: &typesv1.DashboardStatus_ManagedDashboard{ - Path: path, - }, - }, - }, - } -} - -func generatedDashboard( - id string, - name, desc string, - isReadonly bool, - persesJSON []byte, - path string, - detectionReason string, - createdAt, updatedAt time.Time, -) *typesv1.Dashboard { - return &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{ - Id: id, - }, - Spec: &typesv1.DashboardSpec{ - Name: name, - Description: desc, - IsReadonly: isReadonly, - PersesJson: persesJSON, - }, - Status: &typesv1.DashboardStatus{ - CreatedAt: timestamppb.New(createdAt), - UpdatedAt: timestamppb.New(updatedAt), - Origin: &typesv1.DashboardStatus_Generated{ - Generated: &typesv1.DashboardStatus_GeneratedDashboard{ - Path: path, - DetectionReason: detectionReason, - }, - }, - }, - } -} - -func newWatch(ctx context.Context, t *testing.T, cfg *typesv1.ProjectsConfig, fs billy.Filesystem, timeNow func() time.Time) localstate.DB { - alertState := localstate.NewMemory().AlertRuleStatusStorage() - fullCfg := &config.Config{CurrentConfig: &typesv1.LocalhostConfig{ - Runtime: &typesv1.RuntimeConfig{ - ExperimentalFeatures: &typesv1.RuntimeConfig_ExperimentalFeatures{ - Projects: cfg, - }, - }, - }} - db, err := internalWatch(ctx, fs, fullCfg, alertState, parseQuery, timeNow) - require.NoError(t, err) - return db -} - -func writeFile(fs billy.Filesystem, path string, data []byte) error { - // Create parent directories - dir := filepath.Dir(path) - if dir != "." && dir != "/" { - parts := strings.Split(dir, string(filepath.Separator)) - current := "" - for _, part := range parts { - if part == "" { - continue - } - if current == "" { - current = part - } else { - current = filepath.Join(current, part) - } - _ = fs.MkdirAll(current, 0755) - } - } - - f, err := fs.Create(path) - if err != nil { - return err - } - defer f.Close() - _, err = f.Write(data) - return err -} - -func readFile(fs billy.Filesystem, path string) ([]byte, error) { - f, err := fs.Open(path) - if err != nil { - return nil, err - } - defer f.Close() - - stat, err := f.Stat() - if err != nil { - return nil, err - } - - buf := make([]byte, stat.Size()) - _, err = f.Read(buf) - if err != nil { - return nil, err - } - return buf, nil -} - -func fileExists(fs billy.Filesystem, path string) (bool, error) { - _, err := fs.Stat(path) - if err != nil { - if os.IsNotExist(err) { - return false, nil - } - return false, err - } - return true, nil -} - -func TestDashboardIsolationBetweenProjects(t *testing.T) { - now := time.Date(2025, 10, 21, 10, 56, 42, 123456, time.UTC) - timeNow := func() time.Time { return now } - - tests := []struct { - name string - initProjects []*typesv1.ProjectsConfig_Project - createInProject string - dashboardName string - dashboardSlug string - verifyProjects map[string]int // project name -> expected dashboard count - }{ - { - name: "dashboard created in one project does not leak to others", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("project-a", localProjectPointer("project-a-dir", "dashboards", "alerts", false)), - projectConfig("project-b", localProjectPointer("project-b-dir", "dashboards", "alerts", false)), - }, - createInProject: "project-a", - dashboardName: "Project A Dashboard", - dashboardSlug: "dashboard-a", - verifyProjects: map[string]int{ - "project-a": 1, - "project-b": 0, - }, - }, - { - name: "dashboard created in second project does not leak to first", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("project-x", localProjectPointer("project-x-dir", "dashboards", "alerts", false)), - projectConfig("project-y", localProjectPointer("project-y-dir", "dashboards", "alerts", false)), - }, - createInProject: "project-y", - dashboardName: "Project Y Dashboard", - dashboardSlug: "dashboard-y", - verifyProjects: map[string]int{ - "project-x": 0, - "project-y": 1, - }, - }, - { - name: "dashboard isolation with three projects", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("alpha", localProjectPointer("alpha-dir", "dashboards", "alerts", false)), - projectConfig("beta", localProjectPointer("beta-dir", "dashboards", "alerts", false)), - projectConfig("gamma", localProjectPointer("gamma-dir", "dashboards", "alerts", false)), - }, - createInProject: "beta", - dashboardName: "Beta Dashboard", - dashboardSlug: "beta-dash", - verifyProjects: map[string]int{ - "alpha": 0, - "beta": 1, - "gamma": 0, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - fs := memfs.New() - - // Create project directories - for _, proj := range tt.initProjects { - ptr := proj.Pointer.GetLocalhost() - require.NoError(t, fs.MkdirAll(filepath.Join(ptr.Path, ptr.DashboardDir), 0755)) - require.NoError(t, fs.MkdirAll(filepath.Join(ptr.Path, ptr.AlertDir), 0755)) - } - - cfg := &typesv1.ProjectsConfig{ - Projects: tt.initProjects, - } - - db := newWatch(ctx, t, cfg, fs, timeNow) - - // Create a dashboard in the specified project - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: tt.createInProject, - Spec: &typesv1.DashboardSpec{ - Name: tt.dashboardName, - PersesJson: []byte(fmt.Sprintf(`{ - "kind": "Dashboard", - "metadata": { - "project": "%s", - "name": "%s" - }, - "spec": { - "display": { - "name": "%s" - }, - "panels": {}, - "layouts": [], - "duration": "0s" - } - }`, tt.createInProject, tt.dashboardSlug, tt.dashboardName)), - }, - }) - require.NoError(t, err) - - // Verify dashboard counts in all projects - for projectName, expectedCount := range tt.verifyProjects { - resp, err := db.GetProject(ctx, &projectv1.GetProjectRequest{Name: projectName}) - require.NoError(t, err) - require.Len(t, resp.Dashboards, expectedCount, - "project %q should have exactly %d dashboards", projectName, expectedCount) - - if expectedCount == 1 { - require.Equal(t, tt.dashboardName, resp.Dashboards[0].Spec.Name) - } - } - - // Verify file was only created in the correct project directory - for _, proj := range tt.initProjects { - ptr := proj.Pointer.GetLocalhost() - dashPath := filepath.Join(ptr.Path, ptr.DashboardDir, tt.dashboardSlug+".yaml") - exists, err := fileExists(fs, dashPath) - require.NoError(t, err) - - if proj.Name == tt.createInProject { - require.True(t, exists, "dashboard file should exist in %s", proj.Name) - } else { - require.False(t, exists, "dashboard file should NOT exist in %s", proj.Name) - } - } - }) - } -} - -func TestProjectDirectoryConflictWarnings(t *testing.T) { - now := time.Date(2025, 10, 21, 10, 56, 42, 123456, time.UTC) - timeNow := func() time.Time { return now } - - type operation string - const ( - opGet operation = "GetProject" - opCreate operation = "CreateProject" - opValidate operation = "ValidateProject" - opUpdate operation = "UpdateProject" - opList operation = "ListProject" - ) - - tests := []struct { - name string - initProjects []*typesv1.ProjectsConfig_Project - checkProject string - expectWarnings int - warningContains []string - }{ - { - name: "no warnings when projects have separate directories", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("project-a", localProjectPointer("/project-a-dir", "dashboards", "alerts", false)), - projectConfig("project-b", localProjectPointer("/project-b-dir", "dashboards", "alerts", false)), - }, - checkProject: "project-a", - expectWarnings: 0, - }, - { - name: "warning when projects share dashboard directory", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("project-a", localProjectPointer("/shared", "dashboards", "alerts-a", false)), - projectConfig("project-b", localProjectPointer("/shared", "dashboards", "alerts-b", false)), - }, - checkProject: "project-a", - expectWarnings: 1, - warningContains: []string{sharedDashboardDirWarning("project-b", filepath.Join("/shared", "dashboards"))}, - }, - { - name: "warning when projects share alert directory", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("project-x", localProjectPointer("/shared", "dashboards-x", "alerts", false)), - projectConfig("project-y", localProjectPointer("/shared", "dashboards-y", "alerts", false)), - }, - checkProject: "project-x", - expectWarnings: 1, - warningContains: []string{sharedAlertDirWarning("project-y", filepath.Join("/shared", "alerts"))}, - }, - { - name: "multiple warnings when projects share both directories", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("proj-1", localProjectPointer("/shared", "dashboards", "alerts", false)), - projectConfig("proj-2", localProjectPointer("/shared", "dashboards", "alerts", false)), - }, - checkProject: "proj-1", - expectWarnings: 2, - warningContains: []string{ - sharedDashboardDirWarning("proj-2", filepath.Join("/shared", "dashboards")), - sharedAlertDirWarning("proj-2", filepath.Join("/shared", "alerts")), - }, - }, - { - name: "warnings for multiple conflicting projects", - initProjects: []*typesv1.ProjectsConfig_Project{ - projectConfig("main", localProjectPointer("/dir", "dashboards", "alerts", false)), - projectConfig("clone-1", localProjectPointer("/dir", "dashboards", "alerts", false)), - projectConfig("clone-2", localProjectPointer("/dir", "dashboards", "alerts", false)), - }, - checkProject: "main", - expectWarnings: 4, // 2 warnings per conflicting project (dashboard + alert) - warningContains: []string{ - sharedDashboardDirWarning("clone-1", filepath.Join("/dir", "dashboards")), - sharedAlertDirWarning("clone-1", filepath.Join("/dir", "alerts")), - sharedDashboardDirWarning("clone-2", filepath.Join("/dir", "dashboards")), - sharedAlertDirWarning("clone-2", filepath.Join("/dir", "alerts")), - }, - }, - } - - operations := []operation{opGet, opCreate, opValidate, opUpdate, opList} - - for _, tt := range tests { - for _, op := range operations { - testName := fmt.Sprintf("%s/%s", tt.name, op) - t.Run(testName, func(t *testing.T) { - ctx := context.Background() - fs := memfs.New() - - // For CreateProject and ValidateProject, we need one less project in the initial config - initProjects := tt.initProjects - if op == opCreate || op == opValidate { - // Find the project we're going to create/validate and exclude it from init - var filtered []*typesv1.ProjectsConfig_Project - for _, proj := range tt.initProjects { - if proj.Name != tt.checkProject { - filtered = append(filtered, proj) - } - } - initProjects = filtered - } - - // Create project directories - for _, proj := range tt.initProjects { - ptr := proj.Pointer.GetLocalhost() - require.NoError(t, fs.MkdirAll(filepath.Join(ptr.Path, ptr.DashboardDir), 0755)) - require.NoError(t, fs.MkdirAll(filepath.Join(ptr.Path, ptr.AlertDir), 0755)) - } - - cfg := &typesv1.ProjectsConfig{ - Projects: initProjects, - } - - db := newWatch(ctx, t, cfg, fs, timeNow) - - var project *typesv1.Project - - switch op { - case opGet: - resp, err := db.GetProject(ctx, &projectv1.GetProjectRequest{Name: tt.checkProject}) - require.NoError(t, err) - require.NotNil(t, resp.Project) - project = resp.Project - - case opCreate: - // Find the project spec we're creating - var projectToCreate *typesv1.ProjectsConfig_Project - for _, proj := range tt.initProjects { - if proj.Name == tt.checkProject { - projectToCreate = proj - break - } - } - require.NotNil(t, projectToCreate, "test case must include the project being created") - - resp, err := db.CreateProject(ctx, &projectv1.CreateProjectRequest{ - Spec: &typesv1.ProjectSpec{ - Name: projectToCreate.Name, - Pointer: projectToCreate.Pointer, - }, - }) - require.NoError(t, err) - require.NotNil(t, resp.Project) - project = resp.Project - - case opValidate: - // Find the project spec we're validating - var projectToValidate *typesv1.ProjectsConfig_Project - for _, proj := range tt.initProjects { - if proj.Name == tt.checkProject { - projectToValidate = proj - break - } - } - require.NotNil(t, projectToValidate, "test case must include the project being validated") - - resp, err := db.ValidateProject(ctx, &projectv1.ValidateProjectRequest{ - Spec: &typesv1.ProjectSpec{ - Name: projectToValidate.Name, - Pointer: projectToValidate.Pointer, - }, - }) - require.NoError(t, err) - require.NotNil(t, resp.Status) - // Create a dummy project with the returned status for consistent assertion logic - project = &typesv1.Project{ - Status: resp.Status, - } - - case opUpdate: - // Find the project spec to update - var projectToUpdate *typesv1.ProjectsConfig_Project - for _, proj := range tt.initProjects { - if proj.Name == tt.checkProject { - projectToUpdate = proj - break - } - } - require.NotNil(t, projectToUpdate, "test case must include the project being updated") - - // Update the project (keeping same pointer to test warnings are populated) - resp, err := db.UpdateProject(ctx, &projectv1.UpdateProjectRequest{ - Name: tt.checkProject, - Spec: &typesv1.ProjectSpec{ - Name: projectToUpdate.Name, - Pointer: projectToUpdate.Pointer, - }, - }) - require.NoError(t, err) - require.NotNil(t, resp.Project) - project = resp.Project - - case opList: - resp, err := db.ListProject(ctx, &projectv1.ListProjectRequest{}) - require.NoError(t, err) - require.NotEmpty(t, resp.Items) - - // Find the project we're checking - for _, item := range resp.Items { - if item.Project.Spec.Name == tt.checkProject { - project = item.Project - break - } - } - require.NotNil(t, project, "project %q not found in list", tt.checkProject) - } - - // Verify warning count - require.Len(t, project.Status.Warnings, tt.expectWarnings, - "expected %d warnings but got %d: %v", tt.expectWarnings, len(project.Status.Warnings), project.Status.Warnings) - - // Verify warning content - if len(tt.warningContains) > 0 { - allWarnings := strings.Join(project.Status.Warnings, " ") - for _, expectedSubstr := range tt.warningContains { - require.Contains(t, allWarnings, expectedSubstr, - "warning should contain %q", expectedSubstr) - } - } - }) - } - } -} - -func TestDashboardSlugValidation(t *testing.T) { - ctx := context.Background() - fs := memfs.New() - - cfg := &typesv1.ProjectsConfig{ - Projects: []*typesv1.ProjectsConfig_Project{ - projectConfig("test-project", - localProjectPointer("project1", "dashboards", "alerts", false), - ), - }, - } - - db := newWatch(ctx, t, cfg, fs, func() time.Time { return time.Now() }) - - // Test that invalid names with dots are rejected - _, err := db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "Test Dashboard", - PersesJson: []byte(`{ - "kind": "Dashboard", - "metadata": { - "project": "test-project", - "name": "my.test.dashboard" - }, - "spec": { - "display": { - "name": "Test Dashboard" - }, - "panels": {}, - "layouts": [], - "duration": "0s" - } - }`), - }, - }) - require.Error(t, err) - require.Contains(t, err.Error(), "must only contain alphanumeric characters, underscores, and hyphens") - - // Test that valid names work - _, err = db.CreateDashboard(ctx, &dashboardv1.CreateDashboardRequest{ - ProjectName: "test-project", - Spec: &typesv1.DashboardSpec{ - Name: "Test Dashboard", - PersesJson: []byte(`{ - "kind": "Dashboard", - "metadata": { - "project": "test-project", - "name": "my-test-dashboard" - }, - "spec": { - "display": { - "name": "Test Dashboard" - }, - "panels": {}, - "layouts": [], - "duration": "0s" - } - }`), - }, - }) - require.NoError(t, err) - - // Verify the file was created - exists, err := fileExists(fs, "project1/dashboards/my-test-dashboard.yaml") - require.NoError(t, err) - require.True(t, exists, "dashboard file should exist") - - // Verify we can retrieve it by the hash-based ID - expectedID := dashboardID("test-project", "test-project", "my-test-dashboard") - resp, err := db.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ - ProjectName: "test-project", - Id: expectedID, - }) - require.NoError(t, err) - require.NotNil(t, resp.Dashboard) - require.Equal(t, expectedID, resp.Dashboard.Meta.Id) -} \ No newline at end of file diff --git a/internal/localproject/db.go b/internal/localproject/db.go deleted file mode 100644 index 8ad299f7..00000000 --- a/internal/localproject/db.go +++ /dev/null @@ -1,123 +0,0 @@ -package localproject - -import ( - "context" - "io/fs" - "time" - - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/pkg/localstorage" -) - -type dbStorage struct { - fs fs.FS - logQlParser func(string) (*typesv1.Query, error) - timeNow func() time.Time -} - -func newDBStorage(projectSource ProjectSource, fs fs.FS, logQlParser func(string) (*typesv1.Query, error), timeNow func() time.Time) *dbStorage { - return &dbStorage{fs: fs, logQlParser: logQlParser, timeNow: timeNow} -} -func (store *dbStorage) getOrCreateProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onCreate CreateProjectFn, onGetProject GetProjectFn) error { - panic("todo") - // sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - // if !ok { - // return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - // } - // lh := sch.Localhost - // st, err := parseProjectPointer(ctx, store.fs, name, lh) - // if err != nil { - // return errInternal("parsing project pointer: %v", err) - // } - // dashboards, err := parseProjectDashboards(ctx, store.fs, name, lh.Path, lh.DashboardDir) - // if err != nil { - // return errInternal("parsing project dashboards: %v", err) - // } - // alertGroups, err := parseProjectAlertGroups(ctx, store.fs, name, lh.Path, lh.AlertDir, store.logQlParser) - // if err != nil { - // return errInternal("parsing project alert groups: %v", err) - // } - // return onProject(st, dashboards, alertGroups) -} - -func (store *dbStorage) getProjectHydrated(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectHydratedFn) error { - panic("todo") -} - -func (store *dbStorage) getProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error { - panic("todo") -} - -func (store *dbStorage) syncProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error { - return store.getProject(ctx, name, ptr, onGetProject) -} - -func (store *dbStorage) getDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, onDashboard GetDashboardFn) error { - panic("todo") - // sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - // if !ok { - // return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - // } - // lh := sch.Localhost - // dashboards, err := parseProjectDashboards(ctx, store.fs, projectName, lh.Path, lh.DashboardDir) - // if err != nil { - // return errInternal("parsing project dashboards: %v", err) - // } - // for _, item := range dashboards { - // if item.Id == id { - // return onDashboard(item) - // } - // } - // return nil -} - -func (store *dbStorage) createDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, dashboard *typesv1.Dashboard, onCreated CreateDashboardFn) error { - panic("todo") -} - -func (store *dbStorage) updateDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, dashboard *typesv1.Dashboard, onUpdated UpdateDashboardFn) error { - panic("todo") -} - -func (store *dbStorage) deleteDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, onDeleted DeleteDashboardFn) error { - panic("todo") -} - -func (store *dbStorage) getAlertGroup(ctx context.Context, alertState localstorage.Alertable, projectName string, ptr *typesv1.ProjectPointer, groupName string, onAlertGroup GetAlertGroupFn) error { - panic("todo") - // sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - // if !ok { - // return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - // } - // lh := sch.Localhost - // items, err := parseProjectAlertGroups(ctx, store.fs, projectName, lh.Path, lh.AlertDir, store.logQlParser) - // if err != nil { - // return errInternal("parsing project alert groups: %v", err) - // } - // for _, item := range items { - // if item.Name == groupName { - // return onAlertGroup(item) - // } - // } - // return nil -} - -func (store *dbStorage) getAlertRule(ctx context.Context, alertState localstorage.Alertable, projectName string, ptr *typesv1.ProjectPointer, groupName, ruleName string, onAlertRule GetAlertRuleFn) error { - panic("todo") -} - -func (store *dbStorage) createAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, alertGroup *typesv1.AlertGroup, onCreated CreateAlertGroupFn) error { - panic("todo") -} - -func (store *dbStorage) updateAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, alertGroup *typesv1.AlertGroup, onUpdated UpdateAlertGroupFn) error { - panic("todo") -} - -func (store *dbStorage) deleteAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, onDeleted DeleteAlertGroupFn) error { - panic("todo") -} - -func (store *dbStorage) validateProjectPointer(ctx context.Context, ptr *typesv1.ProjectPointer) error { - panic("todo") -} diff --git a/internal/localproject/errors.go b/internal/localproject/errors.go deleted file mode 100644 index 7b18e88d..00000000 --- a/internal/localproject/errors.go +++ /dev/null @@ -1,29 +0,0 @@ -package localproject - -func errDashboardNotFound(projectName, id string) error { - return errInvalid("project %q has no dashboard with ID %q", projectName, id) -} - -func errAlertGroupNotFound(projectName, groupName string) error { - return errInvalid("project %q has no alert group with name %q", projectName, groupName) -} - -func errAlertRuleNotFound(projectName, groupName, ruleName string) error { - return errInvalid("project %q has no alert rule in group %q with name %q", projectName, groupName, ruleName) -} - -func errProjectDashboardDirMissing(path string) error { - return errInvalid("project doesn't contain a dashboard directory at %q", path) -} - -func errProjectAlertDirMissing(path string) error { - return errInvalid("project doesn't contain an alert directory at %q", path) -} - -func errDashboardParse(filename string, err error) error { - return errInvalid("failed to parse dashboard %q: %v", filename, err) -} - -func errAlertGroupParse(filename string, err error) error { - return errInvalid("failed to parse alert group file %q: %v", filename, err) -} diff --git a/internal/localproject/fs.go b/internal/localproject/fs.go deleted file mode 100644 index d50a3b45..00000000 --- a/internal/localproject/fs.go +++ /dev/null @@ -1,1319 +0,0 @@ -package localproject - -import ( - "bufio" - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "os" - "path" - "path/filepath" - "regexp" - "strings" - "time" - - "connectrpc.com/connect" - "github.com/go-git/go-billy/v6" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/compat/alertmanager" - "github.com/humanlogio/humanlog/pkg/localstorage" - persesv1 "github.com/perses/perses/pkg/model/api/v1" - persescommon "github.com/perses/perses/pkg/model/api/v1/common" - "google.golang.org/protobuf/types/known/timestamppb" - "gopkg.in/yaml.v3" -) - -var ( - // dashboardSlugRegexp defines valid characters for dashboard slugs used as filenames - // Based on Perses' idRegexp (^[a-zA-Z0-9_.-]+$) but excluding dots to avoid file extension confusion - dashboardSlugRegexp = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`) - dashboardSlugMaxLen = 75 -) - -const humanlogPreamble = "managed-by: humanlog" - -type HumanlogMetadata struct { - IsReadonly *bool `yaml:"humanlog.is_readonly,omitempty"` -} - -type localGitStorage struct { - fs billy.Filesystem - logQlParser func(string) (*typesv1.Query, error) - timeNow func() time.Time -} - -func newLocalGitStorage(projectSource ProjectSource, fs billy.Filesystem, logQlParser func(string) (*typesv1.Query, error), timeNow func() time.Time) *localGitStorage { - return &localGitStorage{fs: fs, logQlParser: logQlParser, timeNow: timeNow} -} - -func (store *localGitStorage) getOrCreateProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onCreate CreateProjectFn, onGetProject GetProjectFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - st, exists, err := parseProjectPointer(ctx, store.fs, name, lh) - if err != nil { - return errInternal("parsing project pointer: %v", err) - } - if !exists { - if lh.ReadOnly { - return errInvalid("project doesn't already exist on the filesystem, and is specified as read-only. can't create it") - } - if onCreate == nil { - return errInvalid("no project with this name exists on the filesystem") - } - st = onCreate() - if err := createProjectFromPointer(ctx, store.fs, name, st, lh); err != nil { - return errInternal("creating new project: %v", err) - } - } - - return onGetProject(st) -} - -func (store *localGitStorage) syncProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error { - return store.getProject(ctx, name, ptr, onGetProject) -} - -func (store *localGitStorage) getProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - st, exists, err := parseProjectPointer(ctx, store.fs, name, lh) - if err != nil { - return errInternal("parsing project pointer: %v", err) - } - if !exists { - return errInvalid("no such project: %q", name) - } - return onGetProject(st) -} - -func (store *localGitStorage) getProjectHydrated(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectHydratedFn) error { - return store.getProject(ctx, name, ptr, func(p *typesv1.Project) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - dashboards, err := parseProjectDashboards(ctx, store.fs, name, lh.Path, lh.DashboardDir, lh.ReadOnly) - if err != nil { - var connectErr *connect.Error - if errors.As(err, &connectErr) && connectErr.Code() == connect.CodeInvalidArgument { - // User config error - add to status, continue - p.Status.Errors = append(p.Status.Errors, err.Error()) - } else { - // System error - fail immediately - return err - } - } - alertGroups, err := parseProjectAlertGroups(ctx, store.fs, name, lh.Path, lh.AlertDir, store.logQlParser) - if err != nil { - var connectErr *connect.Error - if errors.As(err, &connectErr) && connectErr.Code() == connect.CodeInvalidArgument { - // User config error - add to status, continue - p.Status.Errors = append(p.Status.Errors, err.Error()) - } else { - // System error - fail immediately - return err - } - } - return onGetProject(p, dashboards, alertGroups) - }) -} - -func (store *localGitStorage) getDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, onDashboard GetDashboardFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - dashboardPath := path.Join(lh.Path, lh.DashboardDir) - if _, err := store.fs.Stat(dashboardPath); err != nil { - if errors.Is(err, os.ErrNotExist) { - return errInvalid("project %q has no dashboard directory at %q", projectName, lh.DashboardDir) - } - return errInternal("checking dashboard directory: %v", err) - } - dashboards, err := parseProjectDashboards(ctx, store.fs, projectName, lh.Path, lh.DashboardDir, lh.ReadOnly) - if err != nil { - return errInternal("parsing project dashboards: %v", err) - } - for _, item := range dashboards { - if item.Meta.Id == id { - return onDashboard(item) - } - } - return errDashboardNotFound(projectName, id) -} - -func (store *localGitStorage) createDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, dashboard *typesv1.Dashboard, onCreated CreateDashboardFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - if lh.ReadOnly { - return errInvalid("cannot create dashboard in read-only project") - } - - var persesDash persesv1.Dashboard - if err := persesDash.UnmarshalJSON(dashboard.Spec.PersesJson); err != nil { - return errInvalid("invalid Perses dashboard JSON: %v", err) - } - - // Override display name and description from Spec if provided - if dashboard.Spec.Name != "" { - if persesDash.Spec.Display == nil { - persesDash.Spec.Display = &persescommon.Display{} - } - persesDash.Spec.Display.Name = dashboard.Spec.Name - } - if dashboard.Spec.Description != "" { - if persesDash.Spec.Display == nil { - persesDash.Spec.Display = &persescommon.Display{} - } - persesDash.Spec.Display.Description = dashboard.Spec.Description - } - - filename, err := extractFilenameFromDashboard(&persesDash) - if err != nil { - return errInvalid("invalid dashboard slug: %v", err) - } - - dashboardPath := path.Join(lh.Path, lh.DashboardDir) - fpath := path.Join(dashboardPath, filename) - - if _, err := store.fs.Stat(fpath); err == nil { - return errInvalid("a dashboard already exists at path %q, use another name to avoid conflicts", fpath) - } - - if err := store.fs.MkdirAll(dashboardPath, 0755); err != nil { - return errInternal("creating dashboard directory: %v", err) - } - - f, err := store.fs.Create(fpath) - if err != nil { - return errInternal("creating dashboard file: %v", err) - } - success := false - defer func() { - if !success { - _ = f.Close() - _ = os.Remove(f.Name()) - } - }() - - yamlData, err := yaml.Marshal(&persesDash) - if err != nil { - return errInternal("marshaling dashboard to YAML: %v", err) - } - meta := &HumanlogMetadata{ - IsReadonly: nil, - } - if dashboard.Spec.IsReadonly { - meta.IsReadonly = &dashboard.Spec.IsReadonly - } - headerData, err := encodeHeadComment(meta) - if err != nil { - return errInternal("encoding dashboard metadata: %v", err) - } - fileData := append(headerData, yamlData...) - if _, err := f.Write(fileData); err != nil { - return errInternal("writing dashboard data: %v", err) - } - if err := f.Close(); err != nil { - return errInternal("closing dashboard file: %v", err) - } - success = true - - created, err := parseProjectDashboard(ctx, store.fs, projectName, dashboardPath, filename, false) - if err != nil { - return errInternal("parsing created dashboard: %v", err) - } - - return onCreated(created) -} - -func (store *localGitStorage) updateDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, dashboard *typesv1.Dashboard, onUpdated UpdateDashboardFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - if lh.ReadOnly { - return errInvalid("cannot update dashboard in read-only project") - } - - // Get existing dashboard - var existing *typesv1.Dashboard - err := store.getDashboard(ctx, projectName, ptr, id, func(d *typesv1.Dashboard) error { - existing = d - return nil - }) - if err != nil { - return err - } - if existing == nil { - return errInvalid("dashboard %q not found", id) - } - - var fpath string - switch origin := existing.Status.Origin.(type) { - case *typesv1.DashboardStatus_Managed: - if existing.Spec.IsReadonly && dashboard.Spec.IsReadonly { - return errInvalid("cannot update readonly dashboard (set is_readonly=false to make it writable)") - } - fpath = origin.Managed.Path - case *typesv1.DashboardStatus_Generated: - if dashboard.Spec.IsReadonly { - return errInvalid("can't update dashboard that appears to be generated unless `is_readonly=false` is provided. detected as possibly generted because of: %s", origin.Generated.DetectionReason) - } - fpath = origin.Generated.Path - case *typesv1.DashboardStatus_Builtin: - return errInvalid("cannot update built-in dashboard %q", id) - case *typesv1.DashboardStatus_Remote: - return errInvalid("cannot update remote dashboard %q", id) - default: - return errInvalid("dashboard %q has unknown origin type", id) - } - - var persesDash persesv1.Dashboard - if err := persesDash.UnmarshalJSON(dashboard.Spec.PersesJson); err != nil { - return errInvalid("invalid Perses dashboard JSON: %v", err) - } - if dashboard.Spec.Name != "" { - if persesDash.Spec.Display == nil { - persesDash.Spec.Display = &persescommon.Display{} - } - persesDash.Spec.Display.Name = dashboard.Spec.Name - } - if dashboard.Spec.Description != "" { - if persesDash.Spec.Display == nil { - persesDash.Spec.Display = &persescommon.Display{} - } - persesDash.Spec.Display.Description = dashboard.Spec.Description - } - - f, err := store.fs.Create(fpath) - if err != nil { - return errInternal("opening dashboard file for write: %v", err) - } - defer f.Close() - - meta := &HumanlogMetadata{ - IsReadonly: &dashboard.Spec.IsReadonly, - } - headerData, err := encodeHeadComment(meta) - if err != nil { - return errInternal("encoding dashboard metadata: %v", err) - } - if _, err := f.Write(headerData); err != nil { - return errInternal("writing dashboard metadata: %v", err) - } - - yamlData, err := yaml.Marshal(&persesDash) - if err != nil { - return errInternal("marshaling dashboard to YAML: %v", err) - } - if _, err := f.Write(yamlData); err != nil { - return errInternal("writing dashboard data: %v", err) - } - - filename := filepath.Base(fpath) - dashboardPath := filepath.Dir(fpath) - updated, err := parseProjectDashboard(ctx, store.fs, projectName, dashboardPath, filename, existing.Spec.IsReadonly) - if err != nil { - return errInternal("parsing updated dashboard: %v", err) - } - - return onUpdated(updated) -} - -func (store *localGitStorage) deleteDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, onDeleted DeleteDashboardFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - if lh.ReadOnly { - return errInvalid("cannot delete dashboard in read-only project") - } - - var existing *typesv1.Dashboard - err := store.getDashboard(ctx, projectName, ptr, id, func(d *typesv1.Dashboard) error { - existing = d - return nil - }) - if err != nil { - return err - } - if existing == nil { - return errInvalid("dashboard %q not found", id) - } - - if existing.Status.Origin == nil { - return errInvalid("dashboard %q has no origin information", id) - } - if _, ok := existing.Status.Origin.(*typesv1.DashboardStatus_Managed); !ok { - return errInvalid("cannot delete generated or built-in dashboard %q", id) - } - - managedOrigin := existing.Status.Origin.(*typesv1.DashboardStatus_Managed) - fpath := managedOrigin.Managed.Path - - if err := store.fs.Remove(fpath); err != nil { - return errInternal("deleting dashboard file: %v", err) - } - - return onDeleted() -} - -func (store *localGitStorage) createAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, alertGroup *typesv1.AlertGroup, onCreated CreateAlertGroupFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - if lh.ReadOnly { - return errInvalid("cannot create alert group in readonly project") - } - - groupName := alertGroup.Spec.Name - filename := groupName + ".yaml" - alertGroupPath := path.Join(lh.Path, lh.AlertDir) - fpath := path.Join(alertGroupPath, filename) - - if _, err := store.fs.Stat(fpath); err == nil { - return errInvalid("an alert group already exists at path %q, use another name to avoid conflicts", fpath) - } - - if err := store.fs.MkdirAll(alertGroupPath, 0755); err != nil { - return errInternal("creating alert directory: %v", err) - } - - f, err := store.fs.Create(fpath) - if err != nil { - return errInternal("creating alert group file: %v", err) - } - success := false - defer func() { - if !success { - _ = f.Close() - _ = os.Remove(f.Name()) - } - }() - - // Convert to Prometheus format and marshal to YAML - ruleGroup := alertGroupToRulefmt(alertGroup.Spec) - groups := struct { - Groups []interface{} `yaml:"groups"` - }{ - Groups: []interface{}{ruleGroup}, - } - - yamlData, err := yaml.Marshal(&groups) - if err != nil { - return errInternal("marshaling alert group to YAML: %v", err) - } - - // Add humanlog metadata header - meta := &HumanlogMetadata{ - IsReadonly: &alertGroup.Spec.IsReadonly, - } - headerData, err := encodeHeadComment(meta) - if err != nil { - return errInternal("encoding alert group metadata: %v", err) - } - - fileData := append(headerData, yamlData...) - if _, err := f.Write(fileData); err != nil { - return errInternal("writing alert group data: %v", err) - } - if err := f.Close(); err != nil { - return errInternal("closing alert group file: %v", err) - } - success = true - - // Parse back to get the created group with proper status - created, err := parseProjectAlertGroupFromFile(ctx, store.fs, alertGroupPath, filename, store.logQlParser) - if err != nil { - return errInternal("parsing created alert group: %v", err) - } - - return onCreated(created) -} - -func (store *localGitStorage) updateAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, alertGroup *typesv1.AlertGroup, onUpdated UpdateAlertGroupFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - if lh.ReadOnly { - return errInvalid("cannot update alert group in read-only project") - } - - // Get existing alert group (without hydrating rule statuses) - items, err := parseProjectAlertGroups(ctx, store.fs, projectName, lh.Path, lh.AlertDir, store.logQlParser) - if err != nil { - return errInternal("parsing project alert groups: %v", err) - } - - var existing *typesv1.AlertGroup - for _, ag := range items { - if ag.Spec.Name == groupName { - existing = ag - break - } - } - if existing == nil { - return errInvalid("alert group %q not found", groupName) - } - - // Check if it's readonly - if existing.Spec.IsReadonly && !alertGroup.Spec.IsReadonly { - // Adopting a readonly group - this is allowed - } else if existing.Spec.IsReadonly { - return errInvalid("cannot update readonly alert group %q", groupName) - } - - // Get the file path from existing status - var fpath string - switch origin := existing.Status.Origin.(type) { - case *typesv1.AlertGroupStatus_Managed: - fpath = origin.Managed.Path - case *typesv1.AlertGroupStatus_Discovered: - fpath = origin.Discovered.Path - case *typesv1.AlertGroupStatus_Generated: - return errInvalid("cannot update generated alert group %q", groupName) - default: - return errInvalid("alert group %q has no origin information", groupName) - } - - // Convert to Prometheus format and marshal to YAML - ruleGroup := alertGroupToRulefmt(alertGroup.Spec) - groups := struct { - Groups []interface{} `yaml:"groups"` - }{ - Groups: []interface{}{ruleGroup}, - } - - yamlData, err := yaml.Marshal(&groups) - if err != nil { - return errInternal("marshaling alert group to YAML: %v", err) - } - - // Add humanlog metadata header - meta := &HumanlogMetadata{ - IsReadonly: &alertGroup.Spec.IsReadonly, - } - headerData, err := encodeHeadComment(meta) - if err != nil { - return errInternal("encoding alert group metadata: %v", err) - } - - f, err := store.fs.Create(fpath) - if err != nil { - return errInternal("opening alert group file for write: %v", err) - } - defer f.Close() - - fileData := append(headerData, yamlData...) - if _, err := f.Write(fileData); err != nil { - return errInternal("writing alert group data: %v", err) - } - - // Parse back to get the updated group with proper status - alertGroupPath := path.Dir(fpath) - filename := path.Base(fpath) - updated, err := parseProjectAlertGroupFromFile(ctx, store.fs, alertGroupPath, filename, store.logQlParser) - if err != nil { - return errInternal("parsing updated alert group: %v", err) - } - - return onUpdated(updated) -} - -func (store *localGitStorage) deleteAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, onDeleted DeleteAlertGroupFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - if lh.ReadOnly { - return errInvalid("cannot delete alert group in read-only project") - } - - // Get existing alert group (without hydrating rule statuses) - items, err := parseProjectAlertGroups(ctx, store.fs, projectName, lh.Path, lh.AlertDir, store.logQlParser) - if err != nil { - return errInternal("parsing project alert groups: %v", err) - } - - var existing *typesv1.AlertGroup - for _, ag := range items { - if ag.Spec.Name == groupName { - existing = ag - break - } - } - if existing == nil { - return errInvalid("alert group %q not found", groupName) - } - - if existing.Status.Origin == nil { - return errInvalid("alert group %q has no origin information", groupName) - } - if _, ok := existing.Status.Origin.(*typesv1.AlertGroupStatus_Managed); !ok { - return errInvalid("cannot delete readonly alert group %q", groupName) - } - - managedOrigin := existing.Status.Origin.(*typesv1.AlertGroupStatus_Managed) - fpath := managedOrigin.Managed.Path - - if err := store.fs.Remove(fpath); err != nil { - return errInternal("deleting alert group file: %v", err) - } - - return onDeleted() -} - -// Helper function to convert AlertGroupSpec to Prometheus rulefmt format -func alertGroupToRulefmt(spec *typesv1.AlertGroupSpec) map[string]interface{} { - group := map[string]interface{}{ - "name": spec.Name, - "interval": spec.Interval.AsDuration().String(), - } - - if spec.QueryOffset != nil && spec.QueryOffset.AsDuration() > 0 { - group["query_offset"] = spec.QueryOffset.AsDuration().String() - } - - if spec.Limit > 0 { - group["limit"] = spec.Limit - } - - if spec.Labels != nil && len(spec.Labels.Kvs) > 0 { - labels := make(map[string]string) - for _, kv := range spec.Labels.Kvs { - if strVal, ok := kv.Value.Kind.(*typesv1.Val_Str); ok { - labels[kv.Key] = strVal.Str - } - } - // Only add labels if we have any - if len(labels) > 0 { - group["labels"] = labels - } - } - // Note: Do not add empty labels map to avoid YAML output like "labels: {}" - - rules := make([]map[string]interface{}, 0, len(spec.Rules)) - for _, namedRule := range spec.Rules { - rule := alertRuleToRulefmt(namedRule.Spec) - rules = append(rules, rule) - } - group["rules"] = rules - - return group -} - -// Helper function to extract expression string from Query (simplified for test compatibility) -func queryToString(q *typesv1.Query) string { - if q == nil || q.Query == nil { - return "" - } - // Extract the expression string from the first statement - if len(q.Query.Statements) > 0 { - stmt := q.Query.Statements[0] - if filter, ok := stmt.Stmt.(*typesv1.Statement_Filter); ok && filter.Filter != nil && filter.Filter.Expr != nil { - // Try identifier first (used by test parseQuery) - if ident, ok := filter.Filter.Expr.Expr.(*typesv1.Expr_Identifier); ok && ident.Identifier != nil { - return ident.Identifier.Name - } - // Fall back to literal (for backward compatibility) - if lit, ok := filter.Filter.Expr.Expr.(*typesv1.Expr_Literal); ok && lit.Literal != nil { - if strVal, ok := lit.Literal.Kind.(*typesv1.Val_Str); ok { - return strVal.Str - } - } - } - } - return "unknown" -} - -// Helper function to convert AlertRuleSpec to Prometheus rulefmt format -func alertRuleToRulefmt(spec *typesv1.AlertRuleSpec) map[string]interface{} { - rule := map[string]interface{}{ - "alert": spec.Name, - "expr": queryToString(spec.Expr), - } - - if spec.For != nil && spec.For.AsDuration() > 0 { - rule["for"] = spec.For.AsDuration().String() - } - - if spec.KeepFiringFor != nil && spec.KeepFiringFor.AsDuration() > 0 { - rule["keep_firing_for"] = spec.KeepFiringFor.AsDuration().String() - } - - if spec.Labels != nil && len(spec.Labels.Kvs) > 0 { - labels := make(map[string]string) - for _, kv := range spec.Labels.Kvs { - if strVal, ok := kv.Value.Kind.(*typesv1.Val_Str); ok { - labels[kv.Key] = strVal.Str - } - } - if len(labels) > 0 { - rule["labels"] = labels - } - } - - if spec.Annotations != nil && len(spec.Annotations.Kvs) > 0 { - annotations := make(map[string]string) - for _, kv := range spec.Annotations.Kvs { - if strVal, ok := kv.Value.Kind.(*typesv1.Val_Str); ok { - annotations[kv.Key] = strVal.Str - } - } - if len(annotations) > 0 { - rule["annotations"] = annotations - } - } - - return rule -} - -// Helper function to parse a single alert group file -func parseProjectAlertGroupFromFile(ctx context.Context, ffs billy.Filesystem, alertGroupPath, filename string, logQlParser func(string) (*typesv1.Query, error)) (*typesv1.AlertGroup, error) { - groups, err := parseProjectAlertGroupsFromFile(ctx, ffs, alertGroupPath, filename, logQlParser) - if err != nil { - return nil, err - } - if len(groups) == 0 { - return nil, errInvalid("no alert groups found in file %q", filename) - } - if len(groups) > 1 { - return nil, errInvalid("expected exactly one alert group in file %q, found %d", filename, len(groups)) - } - return groups[0], nil -} - -func (store *localGitStorage) getAlertGroup(ctx context.Context, alertState localstorage.Alertable, projectName string, ptr *typesv1.ProjectPointer, groupName string, onAlertGroup GetAlertGroupFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - alertPath := path.Join(lh.Path, lh.AlertDir) - if _, err := store.fs.Stat(alertPath); err != nil { - if errors.Is(err, os.ErrNotExist) { - return errInvalid("project %q has no alert directory at %q", projectName, lh.AlertDir) - } - return errInternal("checking alert directory: %v", err) - } - items, err := parseProjectAlertGroups(ctx, store.fs, projectName, lh.Path, lh.AlertDir, store.logQlParser) - if err != nil { - return errInternal("parsing project alert groups: %v", err) - } - for _, ag := range items { - if ag.Spec.Name == groupName { - // Hydrate status for all rules in group - ag.Status.Rules = make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, 0, len(ag.Spec.Rules)) - for _, named := range ag.Spec.Rules { - state, err := alertState.AlertGetOrCreate(ctx, projectName, groupName, named.Id, func() *typesv1.AlertRuleStatus { - return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - }) - if err != nil { - // If project doesn't exist in alert state yet, use default unknown status - state = &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - } - ag.Status.Rules = append(ag.Status.Rules, &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: named.Id, - Status: state, - }) - } - return onAlertGroup(ag) - } - } - return errAlertGroupNotFound(projectName, groupName) -} - -func (store *localGitStorage) getAlertRule(ctx context.Context, alertState localstorage.Alertable, projectName string, ptr *typesv1.ProjectPointer, groupName, ruleName string, onAlertRule GetAlertRuleFn) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - alertPath := path.Join(lh.Path, lh.AlertDir) - if _, err := store.fs.Stat(alertPath); err != nil { - if errors.Is(err, os.ErrNotExist) { - return errInvalid("project %q has no alert directory at %q", projectName, lh.AlertDir) - } - return errInternal("checking alert directory: %v", err) - } - items, err := parseProjectAlertGroups(ctx, store.fs, projectName, lh.Path, lh.AlertDir, store.logQlParser) - if err != nil { - return errInternal("parsing project alert groups: %v", err) - } - onGroup := func(group *typesv1.AlertGroup) error { - for _, named := range group.Spec.Rules { - if named.Id == ruleName { - // Fetch actual runtime status from storage - state, err := alertState.AlertGetOrCreate(ctx, projectName, groupName, named.Id, func() *typesv1.AlertRuleStatus { - return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - }) - if err != nil { - // If project doesn't exist in alert state yet, use default unknown status - state = &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - } - - // Construct full AlertRule with hydrated status - rule := &typesv1.AlertRule{ - Meta: &typesv1.AlertRuleMeta{ - Id: named.Id, - }, - Spec: named.Spec, - Status: state, - } - return onAlertRule(rule) - } - } - return errAlertRuleNotFound(projectName, groupName, ruleName) - } - - for _, item := range items { - if item.Spec.Name == groupName { - return onGroup(item) - } - } - return errAlertRuleNotFound(projectName, groupName, ruleName) -} - -func createProjectFromPointer(ctx context.Context, ffs billy.Filesystem, projectName string, project *typesv1.Project, ptr *typesv1.ProjectPointer_LocalGit) error { - panic("todo") -} - -func (store *localGitStorage) validateProjectPointer(ctx context.Context, ptr *typesv1.ProjectPointer) error { - sch, ok := ptr.Scheme.(*typesv1.ProjectPointer_Localhost) - if !ok { - return errInvalid("local git can only operate with projectpointers for localhost, but got %T", ptr.Scheme) - } - lh := sch.Localhost - ensureIsDir := func(path string) error { - fi, err := store.fs.Stat(path) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("the path %q doesn't exist", path)) - } - return err - } - if !fi.IsDir() { - return connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("the path %q is not a directory", path)) - } - return nil - } - ensureIsSubdir := func(dir, path string) error { - if path == "" { - return fmt.Errorf("expecting a sub directory of %q, but no path was specified", dir) - } - if filepath.IsAbs(path) { - return fmt.Errorf("expecting a sub directory of %q, but was an absolute path: %q", dir, path) - } - path = filepath.Join(dir, path) - if err := ensureIsDir(path); err != nil { - return err - } - return nil - } - if !path.IsAbs(lh.Path) { - return fmt.Errorf("pointer's path must be absolute, but was relative: %q", lh.Path) - } - if err := ensureIsDir(lh.Path); err != nil { - return fmt.Errorf("path is invalid: %v", err) - } - if err := ensureIsSubdir(lh.Path, lh.DashboardDir); err != nil { - return fmt.Errorf("dashboard dir is invalid: %v", err) - } - if err := ensureIsSubdir(lh.Path, lh.AlertDir); err != nil { - return fmt.Errorf("alert dir is invalid: %v", err) - } - return nil -} - -func parseProjectPointer(ctx context.Context, ffs billy.Filesystem, projectName string, ptr *typesv1.ProjectPointer_LocalGit) (*typesv1.Project, bool, error) { - st := &typesv1.Project{ - Meta: &typesv1.ProjectMeta{}, - Spec: &typesv1.ProjectSpec{}, - Status: &typesv1.ProjectStatus{}, - } - projectDir, err := ffs.Stat(ptr.Path) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - st.Status.Errors = append(st.Status.Errors, fmt.Sprintf("no directory exists at path %q", ptr.Path)) - return st, false, nil - } - return nil, false, fmt.Errorf("looking up project directory %q on filesystem: %v", ptr.Path, err) - } - st.Spec = &typesv1.ProjectSpec{ - Name: projectName, - Pointer: &typesv1.ProjectPointer{Scheme: &typesv1.ProjectPointer_Localhost{Localhost: &typesv1.ProjectPointer_LocalGit{ - Path: ptr.Path, - DashboardDir: ptr.DashboardDir, - AlertDir: ptr.AlertDir, - ReadOnly: ptr.ReadOnly, - }}}, - } - st.Status = &typesv1.ProjectStatus{ - CreatedAt: timestamppb.New(projectDir.ModTime()), - UpdatedAt: timestamppb.New(projectDir.ModTime()), - } - return st, true, nil -} - -func parseProjectDashboards(ctx context.Context, ffs billy.Filesystem, projectName, projectPath, dashboardDir string, projectIsReadOnly bool) ([]*typesv1.Dashboard, error) { - dashboardPath := path.Join(projectPath, dashboardDir) - files, err := ffs.ReadDir(dashboardPath) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return nil, errProjectDashboardDirMissing(dashboardDir) - } - return nil, errInternal("reading dashboard directory: %v", err) - } - var out []*typesv1.Dashboard - for _, file := range files { - if file.IsDir() { - continue - } - filename := file.Name() - fileext := filepath.Ext(filename) - switch fileext { - case ".json", ".yaml", ".yml": - item, err := parseProjectDashboard(ctx, ffs, projectName, dashboardPath, filename, projectIsReadOnly) - if err != nil { - out = append(out, &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{}, - Spec: &typesv1.DashboardSpec{}, - Status: &typesv1.DashboardStatus{ - Errors: []string{errDashboardParse(filename, err).Error()}, - }, - }) - } else { - out = append(out, item) - } - default: - continue - } - } - return out, nil -} - -func parseProjectDashboard(ctx context.Context, ffs billy.Filesystem, projectName, dashboardPath, filename string, projectIsReadOnly bool) (*typesv1.Dashboard, error) { - persesToProto := func(in *persesv1.Dashboard, projectName, filepath string, data []byte, out *typesv1.Dashboard) (*typesv1.Dashboard, error) { - out.Meta.Id = dashboardID(projectName, in.Metadata.Project, in.Metadata.Name) - - out.Spec.Name = in.Metadata.Name - // Always store as JSON, even if source file is YAML - jsonData, err := json.Marshal(in) - if err != nil { - return nil, fmt.Errorf("marshaling dashboard to JSON: %w", err) - } - out.Spec.PersesJson = jsonData - if in.Spec.Display != nil { - out.Spec.Name = in.Spec.Display.Name - out.Spec.Description = in.Spec.Display.Description - } - - out.Status.CreatedAt = timestamppb.New(in.Metadata.CreatedAt) - out.Status.UpdatedAt = timestamppb.New(in.Metadata.UpdatedAt) - - return out, nil - } - parseFile := func(ctx context.Context, ffs billy.Filesystem, projectName, dirpath, filename string, parser func(ctx context.Context, data []byte, out *typesv1.Dashboard, path string) (*persesv1.Dashboard, error)) (*typesv1.Dashboard, error) { - out := &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{}, - Spec: &typesv1.DashboardSpec{}, - Status: &typesv1.DashboardStatus{}, - } - fpath := path.Join(dirpath, filename) - f, err := ffs.Open(fpath) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - out.Status.Errors = append(out.Status.Errors, fmt.Sprintf("no dashboard found at path %q", fpath)) - return out, nil - } - return nil, fmt.Errorf("opening dashboard file at %q: %v", fpath, err) - } - defer f.Close() - - rawData, err := io.ReadAll(f) - if err != nil { - return nil, fmt.Errorf("reading dashboard file at %q: %v", fpath, err) - } - pout, err := parser(ctx, rawData, out, fpath) - if err != nil { - out.Status.Errors = append(out.Status.Errors, fmt.Sprintf("invalid dashboard found at path %q: %v", fpath, err)) - return out, nil - } - return persesToProto(pout, projectName, fpath, rawData, out) - } - parseJSONDashboard := func(ctx context.Context, data []byte, out *typesv1.Dashboard, path string) (*persesv1.Dashboard, error) { - perses := new(persesv1.Dashboard) - if err := perses.UnmarshalJSON(data); err != nil { - return nil, err - } - - out.Spec.IsReadonly = true - out.Status.Origin = &typesv1.DashboardStatus_Generated{ - Generated: &typesv1.DashboardStatus_GeneratedDashboard{ - Path: path, - DetectionReason: "JSON files are never managed by humanlog", - }, - } - - return perses, nil - } - parseYAMLDashboard := func(ctx context.Context, data []byte, out *typesv1.Dashboard, path string) (*persesv1.Dashboard, error) { - meta, isManaged, err := decodeHeadComment(data) - if err != nil { - return nil, fmt.Errorf("parsing humanlog metadata: %w", err) - } - - if meta != nil && meta.IsReadonly != nil { - out.Spec.IsReadonly = *meta.IsReadonly - } else if isManaged { - out.Spec.IsReadonly = false - } else { - out.Spec.IsReadonly = true - } - - if isManaged { - out.Status.Origin = &typesv1.DashboardStatus_Managed{ - Managed: &typesv1.DashboardStatus_ManagedDashboard{ - Path: path, - }, - } - } else { - var node yaml.Node - if err := yaml.Unmarshal(data, &node); err != nil { - return nil, err - } - out.Status = detectGeneratedDashboard(node, out.Status, path) - } - - perses := new(persesv1.Dashboard) - if err := yaml.Unmarshal(data, &perses); err != nil { - return nil, err - } - - return perses, nil - } - - fileext := filepath.Ext(filename) - switch strings.ToLower(fileext) { - case ".json": - return parseFile(ctx, ffs, projectName, dashboardPath, filename, parseJSONDashboard) - case ".yaml", ".yml": - return parseFile(ctx, ffs, projectName, dashboardPath, filename, parseYAMLDashboard) - default: - return nil, fmt.Errorf("invalid file extension for a dashboard: expecting .yaml, .yml or .json, got %q", fileext) - } -} - -func extractFilenameFromDashboard(dashboard *persesv1.Dashboard) (string, error) { - if dashboard.Metadata.Name == "" { - return "", fmt.Errorf("dashboard metadata.name is required") - } - name := dashboard.Metadata.Name - if len(name) > dashboardSlugMaxLen { - return "", fmt.Errorf("name cannot exceed %d characters (got %d)", dashboardSlugMaxLen, len(name)) - } - if !dashboardSlugRegexp.MatchString(name) { - return "", fmt.Errorf("name must only contain alphanumeric characters, underscores, and hyphens (got %q)", name) - } - return name + ".yaml", nil -} - -func encodeHeadComment(meta *HumanlogMetadata) ([]byte, error) { - var buf bytes.Buffer - - buf.WriteString("# " + humanlogPreamble + "\n") - - if meta == nil || meta.IsReadonly == nil { - return buf.Bytes(), nil - } - - yamlData, err := yaml.Marshal(meta) - if err != nil { - return nil, fmt.Errorf("marshaling humanlog metadata: %w", err) - } - - scanner := bufio.NewScanner(bytes.NewReader(yamlData)) - scanner.Split(bufio.ScanLines) - for scanner.Scan() { - line := scanner.Text() - if strings.TrimSpace(line) != "" { - buf.WriteString("# " + line + "\n") - } - } - - return buf.Bytes(), scanner.Err() -} - -func decodeHeadComment(data []byte) (*HumanlogMetadata, bool, error) { - scanner := bufio.NewScanner(bytes.NewReader(data)) - scanner.Split(bufio.ScanLines) - var foundPreamble bool - var metadataLines []string - - for scanner.Scan() { - line := scanner.Text() - trimmed := strings.TrimSpace(line) - - if !strings.HasPrefix(trimmed, "#") { - break - } - - if strings.Contains(trimmed, humanlogPreamble) { - foundPreamble = true - continue - } - - if foundPreamble && strings.HasPrefix(trimmed, "# humanlog.") { - metadataLines = append(metadataLines, strings.TrimPrefix(trimmed, "# ")) - } - } - - if !foundPreamble { - return nil, false, nil - } - - if len(metadataLines) == 0 { - return &HumanlogMetadata{}, true, nil - } - - yamlData := []byte(strings.Join(metadataLines, "\n")) - var meta HumanlogMetadata - if err := yaml.Unmarshal(yamlData, &meta); err != nil { - return nil, true, fmt.Errorf("parsing humanlog metadata: %w", err) - } - - return &meta, true, nil -} - -func detectGeneratedDashboard(node yaml.Node, status *typesv1.DashboardStatus, path string) *typesv1.DashboardStatus { - comments := extractYAMLComments(&node) - codegenMarkers := []string{ - "Generated by ", - "DO NOT EDIT", - "@generated", - "Code generated", - "This file is automatically generated", - } - - for _, comment := range comments { - for _, marker := range codegenMarkers { - if strings.Contains(comment, marker) { - status.Origin = &typesv1.DashboardStatus_Generated{ - Generated: &typesv1.DashboardStatus_GeneratedDashboard{ - Path: path, - DetectionReason: fmt.Sprintf("Contains %q", strings.TrimSpace(comment)), - }, - } - return status - } - } - } - - status.Origin = &typesv1.DashboardStatus_Generated{ - Generated: &typesv1.DashboardStatus_GeneratedDashboard{ - Path: path, - DetectionReason: "No humanlog metadata or generation markers found", - }, - } - return status -} - -func extractYAMLComments(node *yaml.Node) []string { - var comments []string - if node.HeadComment != "" { - comments = append(comments, node.HeadComment) - } - if node.LineComment != "" { - comments = append(comments, node.LineComment) - } - if node.FootComment != "" { - comments = append(comments, node.FootComment) - } - for _, child := range node.Content { - comments = append(comments, extractYAMLComments(child)...) - } - return comments -} - -// detectGenerationMarker checks for common code generation markers in file content -func detectGenerationMarker(data []byte) string { - scanner := bufio.NewScanner(bytes.NewReader(data)) - codegenMarkers := []string{ - "generated-by", - "Generated by", - "DO NOT EDIT", - "@generated", - "Code generated", - "This file is automatically generated", - } - - for scanner.Scan() { - line := scanner.Text() - trimmed := strings.TrimSpace(line) - - // Only check comment lines - if !strings.HasPrefix(trimmed, "#") { - continue - } - - for _, marker := range codegenMarkers { - if strings.Contains(line, marker) { - return fmt.Sprintf("file contains '# %s' marker", marker) - } - } - } - - return "" -} - -func parseProjectAlertGroups(ctx context.Context, ffs billy.Filesystem, projectName, projectPath, alertGroupDir string, logQlParser func(string) (*typesv1.Query, error)) ([]*typesv1.AlertGroup, error) { - alertGroupPath := path.Join(projectPath, alertGroupDir) - files, err := ffs.ReadDir(alertGroupPath) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return nil, errProjectAlertDirMissing(alertGroupDir) - } - return nil, errInternal("reading alert directory: %v", err) - } - var out []*typesv1.AlertGroup - for _, file := range files { - if file.IsDir() { - continue - } - filename := file.Name() - fileext := filepath.Ext(filename) - switch fileext { - case ".yaml", ".yml": - items, err := parseProjectAlertGroupsFromFile(ctx, ffs, alertGroupPath, filename, logQlParser) - if err != nil { - out = append(out, &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{}, - Spec: &typesv1.AlertGroupSpec{}, - Status: &typesv1.AlertGroupStatus{ - Errors: []string{errAlertGroupParse(filename, err).Error()}, - }, - }) - } else { - out = append(out, items...) - } - default: - continue - } - } - return out, nil -} - -func parseProjectAlertGroupsFromFile(ctx context.Context, ffs billy.Filesystem, alertGroupPath, filename string, logQlParser func(string) (*typesv1.Query, error)) ([]*typesv1.AlertGroup, error) { - filepath := path.Join(alertGroupPath, filename) - file, err := ffs.Open(filepath) - if err != nil { - return nil, errInternal("opening alert group file at %q: %v", filepath, err) - } - defer file.Close() - - // Read raw data to check for humanlog markers - rawData, err := io.ReadAll(file) - if err != nil { - return nil, errInternal("reading alert group file at %q: %v", filepath, err) - } - - // Check for humanlog metadata markers - meta, isManaged, err := decodeHeadComment(rawData) - if err != nil { - return nil, errInternal("parsing humanlog metadata from %q: %v", filepath, err) - } - - // Parse the alert groups - out, err := alertmanager.ParseRules(bytes.NewReader(rawData), logQlParser) - if err != nil { - // Parse errors are user config errors - return partial result with error in status - // Don't fail the operation, allow reconciliation to continue - out = append(out, &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{}, - Spec: &typesv1.AlertGroupSpec{}, - Status: &typesv1.AlertGroupStatus{ - Errors: []string{errAlertGroupParse(filename, err).Error()}, - }, - }) - return out, nil - } - - // Get file stat for timestamps - fileInfo, err := ffs.Stat(filepath) - var modTime time.Time - if err == nil { - modTime = fileInfo.ModTime() - } else { - modTime = time.Now() - } - - // Apply humanlog metadata to all groups in the file - for _, group := range out { - // Set ID from group name - group.Meta.Id = group.Spec.Name - - // Set is_readonly based on metadata - if meta != nil && meta.IsReadonly != nil { - group.Spec.IsReadonly = *meta.IsReadonly - } else if isManaged { - group.Spec.IsReadonly = false - } else { - group.Spec.IsReadonly = true - } - - // Set timestamps - group.Status.CreatedAt = timestamppb.New(modTime) - group.Status.UpdatedAt = timestamppb.New(modTime) - - // Set origin based on markers - if isManaged { - group.Status.Origin = &typesv1.AlertGroupStatus_Managed{ - Managed: &typesv1.AlertGroupStatus_ManagedAlertGroup{ - Path: filepath, - }, - } - } else { - // Check for generation markers - detectionReason := detectGenerationMarker(rawData) - if detectionReason != "" { - group.Status.Origin = &typesv1.AlertGroupStatus_Generated{ - Generated: &typesv1.AlertGroupStatus_GeneratedAlertGroup{ - Path: filepath, - DetectionReason: detectionReason, - }, - } - } else { - // Detected as discovered/external - group.Status.Origin = &typesv1.AlertGroupStatus_Discovered{ - Discovered: &typesv1.AlertGroupStatus_DiscoveredAlertGroup{ - Path: filepath, - }, - } - } - } - } - - return out, nil -} diff --git a/internal/localproject/fs_test.go b/internal/localproject/fs_test.go deleted file mode 100644 index c7555455..00000000 --- a/internal/localproject/fs_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package localproject - -import ( - "testing" - "time" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/memfs" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/stretchr/testify/require" -) - -func TestLocalStorage(t *testing.T) { - constructor := func(t *testing.T, files map[string]string, dashboardDir, alertDir string) (projectStorage, *typesv1.ProjectPointer, func()) { - fs := setupLocalFilesystem(t, files) - store := setupLocalStorage(t, fs) - ptr := mkLocalProjectPointer(dashboardDir, alertDir) - return store, ptr, func() {} - } - - runStorageTestSuite(t, constructor) -} - -func setupLocalFilesystem(t *testing.T, files map[string]string) billy.Filesystem { - t.Helper() - fs := memfs.New() - - for path, content := range files { - err := writeFile(fs, path, []byte(content)) - require.NoError(t, err) - } - - return fs -} - -func setupLocalStorage(t *testing.T, fs billy.Filesystem) *localGitStorage { - t.Helper() - now := time.Date(2025, 10, 22, 10, 0, 0, 0, time.UTC) - timeNow := func() time.Time { return now } - return newLocalGitStorage(nil, fs, parseQuery, timeNow) -} - -func mkLocalProjectPointer(dashboardDir, alertDir string) *typesv1.ProjectPointer { - return &typesv1.ProjectPointer{ - Scheme: &typesv1.ProjectPointer_Localhost{ - Localhost: &typesv1.ProjectPointer_LocalGit{ - Path: "", - DashboardDir: dashboardDir, - AlertDir: alertDir, - ReadOnly: false, - }, - }, - } -} diff --git a/internal/localproject/git.go b/internal/localproject/git.go deleted file mode 100644 index 4423be79..00000000 --- a/internal/localproject/git.go +++ /dev/null @@ -1,401 +0,0 @@ -package localproject - -import ( - "context" - "errors" - "fmt" - "os" - "path/filepath" - "strings" - "sync" - "time" - - "connectrpc.com/connect" - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/transport" - "github.com/go-git/go-git/v6/plumbing/transport/ssh" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/storage/memory" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/pkg/localstorage" - "github.com/mitchellh/go-homedir" - "google.golang.org/protobuf/types/known/timestamppb" -) - -type remoteGitStorage struct { - fs billy.Filesystem - logQlParser func(string) (*typesv1.Query, error) - timeNow func() time.Time - - mu sync.Mutex - repos map[string]*remoteGit -} - -type remoteGit struct { - mu sync.Mutex - project *typesv1.Project - ptr *typesv1.ProjectPointer_RemoteGit - storage storage.Storer - r *git.Repository - w *git.Worktree -} - -func newRemoteGitStorage(projectSource ProjectSource, fs billy.Filesystem, logQlParser func(string) (*typesv1.Query, error), timeNow func() time.Time) (*remoteGitStorage, error) { - return &remoteGitStorage{ - fs: fs, - logQlParser: logQlParser, - timeNow: timeNow, - repos: make(map[string]*remoteGit), - }, nil -} - -func (store *remoteGitStorage) getAuth(url string) (transport.AuthMethod, error) { - if strings.HasPrefix(url, "git@") || strings.HasPrefix(url, "ssh://") { - // Try SSH agent first, fall back to SSH keys - if auth, err := ssh.NewSSHAgentAuth("git"); err == nil { - return auth, nil - } - home, err := homedir.Dir() - if err != nil { - return nil, fmt.Errorf("looking up home dir: %v", err) - } - sshAuth, err := ssh.NewPublicKeysFromFile("git", filepath.Join(home, ".ssh", "id_rsa"), "") - if err != nil { - return nil, fmt.Errorf("no SSH authentication available: %v", err) - } - return sshAuth, nil - } - return nil, nil -} - -func (store *remoteGitStorage) checkout(ctx context.Context, name string, ptr *typesv1.ProjectPointer_RemoteGit) (*remoteGit, error) { - store.mu.Lock() - rem, ok := store.repos[name] - if ok { - store.mu.Unlock() - return rem, nil - } - rem = &remoteGit{ - project: &typesv1.Project{ - Meta: &typesv1.ProjectMeta{}, - Spec: &typesv1.ProjectSpec{ - Name: name, - Pointer: &typesv1.ProjectPointer{ - Scheme: &typesv1.ProjectPointer_Remote{ - Remote: ptr, - }, - }, - }, - Status: &typesv1.ProjectStatus{ - CreatedAt: timestamppb.New(store.timeNow()), - UpdatedAt: timestamppb.New(store.timeNow()), - }, - }, - ptr: ptr, - storage: memory.NewStorage(), - } - rem.mu.Lock() - defer rem.mu.Unlock() - store.repos[name] = rem - store.mu.Unlock() - - auth, err := store.getAuth(ptr.RemoteUrl) - if err != nil { - return nil, err - } - - r, err := git.CloneContext(ctx, rem.storage, store.fs, &git.CloneOptions{ - Auth: auth, - URL: ptr.RemoteUrl, - Depth: 1, - NoCheckout: true, - SingleBranch: false, // to resolve the ref - Tags: git.NoTags, - }) - if err != nil { - return nil, fmt.Errorf("cloning repository: %v", err) - } - rem.r = r - return store.syncWithLock(ctx, name, ptr, rem) -} - -func (store *remoteGitStorage) sync(ctx context.Context, name string, ptr *typesv1.ProjectPointer_RemoteGit) (*remoteGit, error) { - store.mu.Lock() - rem, ok := store.repos[name] - if !ok { - store.mu.Unlock() - return nil, fmt.Errorf("can't sync unknown project named %q", name) - } - rem.mu.Lock() - defer rem.mu.Unlock() - return store.syncWithLock(ctx, name, ptr, rem) -} - -func (store *remoteGitStorage) syncWithLock(ctx context.Context, name string, ptr *typesv1.ProjectPointer_RemoteGit, rem *remoteGit) (*remoteGit, error) { - commit, err := rem.r.ResolveRevision(plumbing.Revision(ptr.Ref)) - if err != nil { - return nil, fmt.Errorf("resolving revision %q in repository: %v", ptr.Ref, err) - } - r := rem.r - w, err := r.Worktree() - if err != nil { - return nil, fmt.Errorf("obtaining repository worktree: %v", err) - } - rem.w = w - rem.project.Status.UpdatedAt = timestamppb.New(store.timeNow()) - err = w.Checkout(&git.CheckoutOptions{ - Hash: *commit, - SparseCheckoutDirectories: []string{ - ptr.DashboardDir, - ptr.AlertDir, - }, - }) - if err != nil && !errors.Is(err, git.ErrSparseResetDirectoryNotFound) { - return nil, fmt.Errorf("doing sparse checkout of dashboards and alerts dir: %v", err) - } - - if _, err := rem.w.Filesystem.Stat(ptr.DashboardDir); errors.Is(err, os.ErrNotExist) { - rem.project.Status.Errors = append(rem.project.Status.Errors, errProjectDashboardDirMissing(ptr.DashboardDir).Error()) - } - if _, err := rem.w.Filesystem.Stat(ptr.AlertDir); errors.Is(err, os.ErrNotExist) { - rem.project.Status.Errors = append(rem.project.Status.Errors, errProjectAlertDirMissing(ptr.AlertDir).Error()) - } - - return rem, nil -} - -func (store *remoteGitStorage) getOrCreateProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onCreate CreateProjectFn, onGetProject GetProjectFn) error { - if err := store.validateProjectPointer(ctx, ptr); err != nil { - return err - } - gitptr := ptr.GetRemote() - rem, err := store.checkout(ctx, name, gitptr) - if err != nil { - return fmt.Errorf("looking up git remote: %v", err) - } - if !rem.mu.TryLock() { - return fmt.Errorf("local checkout is busy, please wait: %v", err) - } - defer rem.mu.Unlock() - return onGetProject(rem.project) - -} - -func (store *remoteGitStorage) getProjectHydrated(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectHydratedFn) error { - rem, err := store.checkout(ctx, name, ptr.GetRemote()) - if err != nil { - return fmt.Errorf("looking up git remote: %v", err) - } - if !rem.mu.TryLock() { - return fmt.Errorf("local checkout is busy, please wait: %v", err) - } - defer rem.mu.Unlock() - - gitptr := rem.ptr - dashboards := []*typesv1.Dashboard{} - if _, err := rem.w.Filesystem.Stat(gitptr.DashboardDir); err == nil { - dashboards, err = parseProjectDashboards(ctx, rem.w.Filesystem, name, "", gitptr.DashboardDir, true) - if err != nil { - var connectErr *connect.Error - if errors.As(err, &connectErr) && connectErr.Code() == connect.CodeInvalidArgument { - rem.project.Status.Errors = append(rem.project.Status.Errors, err.Error()) - } else { - return err - } - } - } - - alertGroups := []*typesv1.AlertGroup{} - if _, err := rem.w.Filesystem.Stat(gitptr.AlertDir); err == nil { - alertGroups, err = parseProjectAlertGroups(ctx, rem.w.Filesystem, name, "", gitptr.AlertDir, store.logQlParser) - if err != nil { - var connectErr *connect.Error - if errors.As(err, &connectErr) && connectErr.Code() == connect.CodeInvalidArgument { - rem.project.Status.Errors = append(rem.project.Status.Errors, err.Error()) - } else { - return err - } - } - } - - return onGetProject(rem.project, dashboards, alertGroups) -} - -func (store *remoteGitStorage) syncProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error { - rem, err := store.checkout(ctx, name, ptr.GetRemote()) - if err != nil { - return fmt.Errorf("looking up git remote: %v", err) - } - if !rem.mu.TryLock() { - return fmt.Errorf("local checkout is busy, please wait: %v", err) - } - defer rem.mu.Unlock() - return onGetProject(rem.project) -} - -func (store *remoteGitStorage) getProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error { - rem, err := store.checkout(ctx, name, ptr.GetRemote()) - if err != nil { - return fmt.Errorf("looking up git remote: %v", err) - } - if !rem.mu.TryLock() { - return fmt.Errorf("local checkout is busy, please wait: %v", err) - } - defer rem.mu.Unlock() - return onGetProject(rem.project) -} - -func (store *remoteGitStorage) getDashboard(ctx context.Context, name string, ptr *typesv1.ProjectPointer, id string, onDashboard GetDashboardFn) error { - rem, err := store.checkout(ctx, name, ptr.GetRemote()) - if err != nil { - return fmt.Errorf("looking up git remote: %v", err) - } - if !rem.mu.TryLock() { - return fmt.Errorf("local checkout is busy, please wait: %v", err) - } - defer rem.mu.Unlock() - gitptr := rem.ptr - if _, err := rem.w.Filesystem.Stat(gitptr.DashboardDir); err != nil { - return errInvalid("project %q has no dashboard directory at %q", name, gitptr.DashboardDir) - } - dashboards, err := parseProjectDashboards(ctx, rem.w.Filesystem, name, "", gitptr.DashboardDir, true) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return errInvalid("dashboard directory %q not found in remote repository", gitptr.DashboardDir) - } - return errInvalid("cannot parse dashboards: %v", err) - } - for _, d := range dashboards { - if d.Meta.Id == id { - return onDashboard(d) - } - } - return errDashboardNotFound(name, id) -} - -func (store *remoteGitStorage) createDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, dashboard *typesv1.Dashboard, onCreated CreateDashboardFn) error { - return errInvalid("cannot create dashboard in remote project") -} - -func (store *remoteGitStorage) updateDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, dashboard *typesv1.Dashboard, onUpdated UpdateDashboardFn) error { - return errInvalid("cannot update dashboard in remote project") -} - -func (store *remoteGitStorage) deleteDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, onDeleted DeleteDashboardFn) error { - return errInvalid("cannot delete dashboard in remote project") -} - -func (store *remoteGitStorage) getAlertGroup(ctx context.Context, alertState localstorage.Alertable, name string, ptr *typesv1.ProjectPointer, groupName string, onAlertGroup GetAlertGroupFn) error { - rem, err := store.checkout(ctx, name, ptr.GetRemote()) - if err != nil { - return fmt.Errorf("looking up git remote: %v", err) - } - if !rem.mu.TryLock() { - return fmt.Errorf("local checkout is busy, please wait: %v", err) - } - defer rem.mu.Unlock() - gitptr := rem.ptr - if _, err := rem.w.Filesystem.Stat(gitptr.AlertDir); err != nil { - return errInvalid("project %q has no alert directory at %q", name, gitptr.AlertDir) - } - alertGroups, err := parseProjectAlertGroups(ctx, rem.w.Filesystem, name, "", gitptr.AlertDir, store.logQlParser) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return errInvalid("alert directory %q not found in remote repository", gitptr.AlertDir) - } - return errInvalid("cannot parse alert groups: %v", err) - } - for _, ag := range alertGroups { - if ag.Spec.Name == groupName { - // Hydrate status for all rules in group - ag.Status.Rules = make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, 0, len(ag.Spec.Rules)) - for _, named := range ag.Spec.Rules { - state, err := alertState.AlertGetOrCreate(ctx, name, groupName, named.Id, func() *typesv1.AlertRuleStatus { - return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - }) - if err != nil { - // If project doesn't exist in alert state yet, use default unknown status - state = &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - } - ag.Status.Rules = append(ag.Status.Rules, &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: named.Id, - Status: state, - }) - } - return onAlertGroup(ag) - } - } - return errAlertGroupNotFound(name, groupName) -} - -func (store *remoteGitStorage) getAlertRule(ctx context.Context, alertState localstorage.Alertable, name string, ptr *typesv1.ProjectPointer, groupName, ruleName string, onAlertRule GetAlertRuleFn) error { - rem, err := store.checkout(ctx, name, ptr.GetRemote()) - if err != nil { - return fmt.Errorf("looking up git remote: %v", err) - } - if !rem.mu.TryLock() { - return fmt.Errorf("local checkout is busy, please wait: %v", err) - } - defer rem.mu.Unlock() - gitptr := rem.ptr - if _, err := rem.w.Filesystem.Stat(gitptr.AlertDir); err != nil { - return errInvalid("project %q has no alert directory at %q", name, gitptr.AlertDir) - } - alertGroups, err := parseProjectAlertGroups(ctx, rem.w.Filesystem, name, "", gitptr.AlertDir, store.logQlParser) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return errInvalid("alert directory %q not found in remote repository", gitptr.AlertDir) - } - return errInvalid("cannot parse alert groups: %v", err) - } - for _, ag := range alertGroups { - if ag.Spec.Name == groupName { - for _, named := range ag.Spec.Rules { - if named.Id == ruleName { - // Fetch actual runtime status from storage - state, err := alertState.AlertGetOrCreate(ctx, name, groupName, named.Id, func() *typesv1.AlertRuleStatus { - return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - }) - if err != nil { - // If project doesn't exist in alert state yet, use default unknown status - state = &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - } - - // Construct full AlertRule with hydrated status - rule := &typesv1.AlertRule{ - Meta: &typesv1.AlertRuleMeta{ - Id: named.Id, - }, - Spec: named.Spec, - Status: state, - } - return onAlertRule(rule) - } - } - - } - } - return errAlertRuleNotFound(name, groupName, ruleName) -} - -func (store *remoteGitStorage) createAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, alertGroup *typesv1.AlertGroup, onCreated CreateAlertGroupFn) error { - return errInvalid("cannot create alert group in remote project") -} - -func (store *remoteGitStorage) updateAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, alertGroup *typesv1.AlertGroup, onUpdated UpdateAlertGroupFn) error { - return errInvalid("cannot update alert group in remote project") -} - -func (store *remoteGitStorage) deleteAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, onDeleted DeleteAlertGroupFn) error { - return errInvalid("cannot delete alert group in remote project") -} - -func (store *remoteGitStorage) validateProjectPointer(ctx context.Context, ptr *typesv1.ProjectPointer) error { - gitptr := ptr.GetRemote() - if gitptr == nil { - return fmt.Errorf("expecting a Git remote pointer, got a %T", ptr.Scheme) - } - return nil -} diff --git a/internal/localproject/git_test.go b/internal/localproject/git_test.go deleted file mode 100644 index 8a9f4fcf..00000000 --- a/internal/localproject/git_test.go +++ /dev/null @@ -1,130 +0,0 @@ -package localproject - -import ( - "errors" - "os" - "testing" - "time" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/memfs" - "github.com/go-git/go-git/v6" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/storage/memory" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/timestamppb" -) - -func TestRemoteGitStorage(t *testing.T) { - constructor := func(t *testing.T, files map[string]string, dashboardDir, alertDir string) (projectStorage, *typesv1.ProjectPointer, func()) { - r, _ := mkGitRepoWithFiles(t, files) - store := setupRemoteGitStorage(t, r, dashboardDir, alertDir) - ptr := mkProjectPointer(dashboardDir, alertDir) - return store, ptr, func() {} - } - - runStorageTestSuite(t, constructor) -} - -func mkGitRepoWithFiles(t *testing.T, files map[string]string) (*git.Repository, billy.Filesystem) { - t.Helper() - - fs := memfs.New() - stor := memory.NewStorage() - - r, err := git.Init(stor, git.WithWorkTree(fs)) - require.NoError(t, err) - - w, err := r.Worktree() - require.NoError(t, err) - - for path, content := range files { - err := writeFile(fs, path, []byte(content)) - require.NoError(t, err) - } - - for path := range files { - _, err := w.Add(path) - require.NoError(t, err) - } - - _, err = w.Commit("initial commit", &git.CommitOptions{ - Author: &object.Signature{ - Name: "Test", - Email: "test@example.com", - When: time.Now(), - }, - }) - require.NoError(t, err) - - return r, fs -} - -func setupRemoteGitStorage(t *testing.T, r *git.Repository, dashboardDir, alertDir string) *remoteGitStorage { - t.Helper() - - now := time.Date(2025, 10, 22, 10, 0, 0, 0, time.UTC) - timeNow := func() time.Time { return now } - - store, err := newRemoteGitStorage(nil, memfs.New(), parseQuery, timeNow) - require.NoError(t, err) - - w, err := r.Worktree() - require.NoError(t, err) - - ptr := &typesv1.ProjectPointer_RemoteGit{ - RemoteUrl: "memory://test", - Ref: "refs/heads/master", - DashboardDir: dashboardDir, - AlertDir: alertDir, - } - - // Simulate what syncWithLock does: check for missing directories and add errors to status - projectStatus := &typesv1.ProjectStatus{ - CreatedAt: timestamppb.New(timeNow()), - UpdatedAt: timestamppb.New(timeNow()), - } - if _, err := w.Filesystem.Stat(ptr.DashboardDir); errors.Is(err, os.ErrNotExist) { - projectStatus.Errors = append(projectStatus.Errors, errProjectDashboardDirMissing(ptr.DashboardDir).Error()) - } - if _, err := w.Filesystem.Stat(ptr.AlertDir); errors.Is(err, os.ErrNotExist) { - projectStatus.Errors = append(projectStatus.Errors, errProjectAlertDirMissing(ptr.AlertDir).Error()) - } - - store.mu.Lock() - store.repos["test-project"] = &remoteGit{ - project: &typesv1.Project{ - Meta: &typesv1.ProjectMeta{}, - Spec: &typesv1.ProjectSpec{ - Name: "test-project", - Pointer: &typesv1.ProjectPointer{ - Scheme: &typesv1.ProjectPointer_Remote{ - Remote: ptr, - }, - }, - }, - Status: projectStatus, - }, - ptr: ptr, - storage: r.Storer, - r: r, - w: w, - } - store.mu.Unlock() - - return store -} - -func mkProjectPointer(dashboardDir, alertDir string) *typesv1.ProjectPointer { - return &typesv1.ProjectPointer{ - Scheme: &typesv1.ProjectPointer_Remote{ - Remote: &typesv1.ProjectPointer_RemoteGit{ - RemoteUrl: "memory://test", - Ref: "refs/heads/master", - DashboardDir: dashboardDir, - AlertDir: alertDir, - }, - }, - } -} diff --git a/internal/localproject/storage_test_suite.go b/internal/localproject/storage_test_suite.go deleted file mode 100644 index 08a3ec97..00000000 --- a/internal/localproject/storage_test_suite.go +++ /dev/null @@ -1,1169 +0,0 @@ -package localproject - -import ( - "context" - "fmt" - "testing" - - "connectrpc.com/connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/stretchr/testify/require" -) - -type storageConstructorFn func( - t *testing.T, - files map[string]string, - dashboardDir, alertDir string, -) (projectStorage, *typesv1.ProjectPointer, func()) - -func runStorageTestSuite(t *testing.T, constructor storageConstructorFn) { - t.Run("get_project_hydrated", func(t *testing.T) { - runGetProjectHydratedTests(t, constructor) - }) - t.Run("get_dashboard", func(t *testing.T) { - runGetDashboardTests(t, constructor) - }) - t.Run("get_alert_group", func(t *testing.T) { - runGetAlertGroupTests(t, constructor) - }) - t.Run("get_alert_rule", func(t *testing.T) { - runGetAlertRuleTests(t, constructor) - }) -} - -func runGetProjectHydratedTests(t *testing.T, constructor storageConstructorFn) { - tests := []struct { - name string - files map[string]string - dashboardDir string - alertDir string - wantDashboards []suiteExpectedDashboard - wantAlertGroups []suiteExpectedAlertGroup - wantStatusErrCount int - validate func(*testing.T, []*typesv1.Dashboard, []*typesv1.AlertGroup) - }{ - { - name: "both_directories_missing", - files: map[string]string{"README.md": "# Test"}, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 2, - }, - { - name: "only_dashboard_dir_missing", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{{name: "group-1"}}, - wantStatusErrCount: 1, - }, - { - name: "only_alert_dir_missing", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 1, - }, - { - name: "both_dirs_exist_both_populated", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "both_dirs_exist_both_empty", - files: map[string]string{ - "dashboards/.gitkeep": "", - "alerts/.gitkeep": "", - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 0, - }, - { - name: "multiple_dashboards", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - "dashboards/d3.yaml": suiteMkDashboardYAML("d-3", "Dashboard 3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - {displayName: "Dashboard 2"}, - {displayName: "Dashboard 3"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 1, - }, - { - name: "multiple_alert_groups", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - "alerts/g2.yaml": suiteMkAlertGroupYAML("group-2", "rule-2"), - "alerts/g3.yaml": suiteMkAlertGroupYAML("group-3", "rule-3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - {name: "group-2"}, - {name: "group-3"}, - }, - wantStatusErrCount: 1, - }, - { - name: "invalid_yaml_doesnt_crash", - files: map[string]string{ - "dashboards/bad.yaml": "this is not valid yaml: [[[", - "alerts/also-bad.yaml": "invalid: {{{", - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: ""}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: ""}, - }, - wantStatusErrCount: 0, - }, - { - name: "partial_results_mix_of_valid_and_invalid", - files: map[string]string{ - "dashboards/good1.yaml": suiteMkDashboardYAML("good-1", "Good Dashboard 1"), - "dashboards/bad.yaml": "this is not valid yaml: [[[", - "dashboards/good2.yaml": suiteMkDashboardYAML("good-2", "Good Dashboard 2"), - "alerts/good-group.yaml": suiteMkAlertGroupYAML("good-group", "rule-1"), - "alerts/bad-group.yaml": "invalid: {{{", - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Good Dashboard 1"}, - {displayName: ""}, - {displayName: "Good Dashboard 2"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "good-group"}, - {name: ""}, - }, - wantStatusErrCount: 0, - validate: func(t *testing.T, dashboards []*typesv1.Dashboard, alertGroups []*typesv1.AlertGroup) { - for _, d := range dashboards { - if d.Spec.Name == "" { - require.NotEmpty(t, d.Status.Errors, "corrupt dashboard should have errors") - } else { - require.Empty(t, d.Status.Errors, "valid dashboard should not have errors") - } - } - for _, ag := range alertGroups { - if ag.Spec.Name == "" { - require.NotEmpty(t, ag.Status.Errors, "corrupt alert group should have errors") - } else { - require.Empty(t, ag.Status.Errors, "valid alert group should not have errors") - } - } - }, - }, - { - name: "non_yaml_files_ignored", - files: map[string]string{ - "dashboards/README.md": "# Docs", - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/notes.txt": "Some notes", - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "subdirectories_ignored", - files: map[string]string{ - "dashboards/subdir/d1.yaml": suiteMkDashboardYAML("d-1", "Nested"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 2"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 1, - }, - { - name: "yml_extension_supported", - files: map[string]string{ - "dashboards/d1.yml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/g1.yml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "mixed_yaml_yml_extensions", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - "alerts/g2.yml": suiteMkAlertGroupYAML("group-2", "rule-2"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - {displayName: "Dashboard 2"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - {name: "group-2"}, - }, - wantStatusErrCount: 0, - }, - { - name: "uppercase_extension_ignored", - files: map[string]string{ - "dashboards/d1.YAML": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 2"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 1, - }, - { - name: "mixed_case_extension_ignored", - files: map[string]string{ - "dashboards/d1.Yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/g1.YML": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 0, - }, - { - name: "no_extension_yaml_content_ignored", - files: map[string]string{ - "dashboards/dashboard": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/alertgroup": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 0, - }, - { - name: "backup_extensions_ignored", - files: map[string]string{ - "dashboards/d1.yaml.bak": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yaml.tmp": suiteMkDashboardYAML("d-2", "Dashboard 2"), - "alerts/g1.yaml.old": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{}, - wantStatusErrCount: 0, - }, - { - name: "spaces_in_filename", - files: map[string]string{ - "dashboards/my dashboard.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/alert group.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "unicode_in_filename", - files: map[string]string{ - "dashboards/dashboard-🚀.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/alert-⚡️.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "special_chars_in_filename", - files: map[string]string{ - "dashboards/dashboard@#$.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/alert-v1.0.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "leading_dot_hidden_files", - files: map[string]string{ - "dashboards/.hidden-dashboard.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/.hidden-alert.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - {displayName: "Dashboard 2"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "trailing_slash_in_paths", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards/", - alertDir: "alerts/", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "leading_slash_in_paths", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "/dashboards", - alertDir: "/alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "relative_path_with_dot", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "./dashboards", - alertDir: "./alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "same_directory_for_both", - files: map[string]string{ - "shared/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "shared/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "shared", - alertDir: "shared", - wantDashboards: []suiteExpectedDashboard{ - {displayName: ""}, - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: ""}, - {name: "group-1"}, - }, - wantStatusErrCount: 0, - validate: func(t *testing.T, dashboards []*typesv1.Dashboard, alertGroups []*typesv1.AlertGroup) { - var corruptDashCount, corruptAlertCount int - for _, d := range dashboards { - if d.Spec.Name == "" { - corruptDashCount++ - require.NotEmpty(t, d.Status.Errors, "corrupt dashboard from alert file should have errors") - } - } - for _, ag := range alertGroups { - if ag.Spec.Name == "" { - corruptAlertCount++ - require.NotEmpty(t, ag.Status.Errors, "corrupt alert group from dashboard file should have errors") - } - } - require.Equal(t, 1, corruptDashCount, "should have 1 corrupt dashboard from alert file") - require.Equal(t, 1, corruptAlertCount, "should have 1 corrupt alert group from dashboard file") - }, - }, - { - name: "empty_string_directory_path", - files: map[string]string{ - "d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "", - alertDir: "", - wantDashboards: []suiteExpectedDashboard{ - {displayName: ""}, - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: ""}, - {name: "group-1"}, - }, - wantStatusErrCount: 0, - validate: func(t *testing.T, dashboards []*typesv1.Dashboard, alertGroups []*typesv1.AlertGroup) { - var corruptDashCount, corruptAlertCount int - for _, d := range dashboards { - if d.Spec.Name == "" { - corruptDashCount++ - require.NotEmpty(t, d.Status.Errors, "corrupt dashboard from alert file should have errors") - } - } - for _, ag := range alertGroups { - if ag.Spec.Name == "" { - corruptAlertCount++ - require.NotEmpty(t, ag.Status.Errors, "corrupt alert group from dashboard file should have errors") - } - } - require.Equal(t, 1, corruptDashCount, "should have 1 corrupt dashboard from alert file") - require.Equal(t, 1, corruptAlertCount, "should have 1 corrupt alert group from dashboard file") - }, - }, - { - name: "dot_as_directory_path", - files: map[string]string{ - "d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: ".", - alertDir: ".", - wantDashboards: []suiteExpectedDashboard{ - {displayName: ""}, - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: ""}, - {name: "group-1"}, - }, - wantStatusErrCount: 0, - validate: func(t *testing.T, dashboards []*typesv1.Dashboard, alertGroups []*typesv1.AlertGroup) { - var corruptDashCount, corruptAlertCount int - for _, d := range dashboards { - if d.Spec.Name == "" { - corruptDashCount++ - require.NotEmpty(t, d.Status.Errors, "corrupt dashboard from alert file should have errors") - } - } - for _, ag := range alertGroups { - if ag.Spec.Name == "" { - corruptAlertCount++ - require.NotEmpty(t, ag.Status.Errors, "corrupt alert group from dashboard file should have errors") - } - } - require.Equal(t, 1, corruptDashCount, "should have 1 corrupt dashboard from alert file") - require.Equal(t, 1, corruptAlertCount, "should have 1 corrupt alert group from dashboard file") - }, - }, - { - name: "nested_alert_dir_in_dashboard_dir", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "dashboards/alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "group-1"}, - }, - wantStatusErrCount: 0, - }, - { - name: "empty_file_zero_bytes", - files: map[string]string{ - "dashboards/empty.yaml": "", - "alerts/also-empty.yaml": "", - "dashboards/good.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: ""}, - {displayName: "Dashboard 1"}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: ""}, - }, - wantStatusErrCount: 0, - }, - { - name: "whitespace_only_file", - files: map[string]string{ - "dashboards/whitespace.yaml": " \n\t\n ", - "alerts/spaces.yaml": " \n ", - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: ""}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: ""}, - }, - wantStatusErrCount: 0, - }, - { - name: "comments_only_file", - files: map[string]string{ - "dashboards/comments.yaml": "# This is a comment\n# Another comment\n", - "alerts/more-comments.yaml": "# Comments only\n", - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{ - {displayName: ""}, - }, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: ""}, - }, - wantStatusErrCount: 0, - }, - { - name: "alert_group_with_many_rules", - files: map[string]string{ - "alerts/massive-group.yaml": suiteMkAlertGroupYAML("massive", suiteGenerateRuleNames(100)...), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - wantDashboards: []suiteExpectedDashboard{}, - wantAlertGroups: []suiteExpectedAlertGroup{ - {name: "massive"}, - }, - wantStatusErrCount: 1, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - store, ptr, cleanup := constructor(t, tt.files, tt.dashboardDir, tt.alertDir) - defer cleanup() - - var gotProject *typesv1.Project - var gotDashboards []*typesv1.Dashboard - var gotAlertGroups []*typesv1.AlertGroup - - err := store.getProjectHydrated(ctx, "test-project", ptr, - func(p *typesv1.Project, dashboards []*typesv1.Dashboard, alertGroups []*typesv1.AlertGroup) error { - gotProject = p - gotDashboards = dashboards - gotAlertGroups = alertGroups - return nil - }) - - require.NoError(t, err) - require.NotNil(t, gotProject) - require.Len(t, gotProject.Status.Errors, tt.wantStatusErrCount, - "project.Status.Errors count, got: %v", gotProject.Status.Errors) - - gotDashboardList := suiteExtractDashboards(gotDashboards) - require.ElementsMatch(t, tt.wantDashboards, gotDashboardList) - - gotAlertGroupList := suiteExtractAlertGroups(gotAlertGroups) - require.ElementsMatch(t, tt.wantAlertGroups, gotAlertGroupList) - - if tt.validate != nil { - tt.validate(t, gotDashboards, gotAlertGroups) - } - }) - } -} - -type suiteExpectedDashboard struct { - displayName string -} - -type suiteExpectedAlertGroup struct { - name string -} - -func suiteExtractDashboards(dashboards []*typesv1.Dashboard) []suiteExpectedDashboard { - out := make([]suiteExpectedDashboard, len(dashboards)) - for i, d := range dashboards { - out[i] = suiteExpectedDashboard{displayName: d.Spec.Name} - } - return out -} - -func suiteExtractAlertGroups(alertGroups []*typesv1.AlertGroup) []suiteExpectedAlertGroup { - out := make([]suiteExpectedAlertGroup, len(alertGroups)) - for i, ag := range alertGroups { - out[i] = suiteExpectedAlertGroup{name: ag.Spec.Name} - } - return out -} - -func suiteMkDashboardYAML(name, displayName string) string { - return fmt.Sprintf(`kind: Dashboard -metadata: - project: test-project - name: %s -spec: - display: - name: %s - panels: {} - layouts: [] - duration: 0s -`, name, displayName) -} - -func suiteMkAlertGroupYAML(groupName string, ruleNames ...string) string { - rules := "" - for _, ruleName := range ruleNames { - rules += fmt.Sprintf(` - alert: %s - expr: "true" - for: 1m - annotations: - summary: Test alert -`, ruleName) - } - return fmt.Sprintf(`groups: - - name: %s - rules: -%s`, groupName, rules) -} - -func suiteGenerateRuleNames(count int) []string { - names := make([]string, count) - for i := range count { - names[i] = fmt.Sprintf("rule-%d", i) - } - return names -} - -func runGetDashboardTests(t *testing.T, constructor storageConstructorFn) { - tests := []struct { - name string - files map[string]string - dashboardDir string - alertDir string - metadataName string - wantDisplayName string - wantErr string - wantErrCode connect.Code - }{ - { - name: "directory_missing", - files: map[string]string{"README.md": "# Test"}, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "any-id", - wantDisplayName: "", - wantErr: errInvalid("project %q has no dashboard directory at %q", "test-project", "dashboards").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "directory_empty", - files: map[string]string{"dashboards/.gitkeep": ""}, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "any-id", - wantDisplayName: "", - wantErr: errDashboardNotFound("test-project", dashboardID("test-project", "test-project", "any-id")).Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "dashboard_found", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "d-1", - wantDisplayName: "Dashboard 1", - wantErr: "", - }, - { - name: "dashboard_not_found_wrong_id", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "non-existent", - wantDisplayName: "", - wantErr: errDashboardNotFound("test-project", dashboardID("test-project", "test-project", "non-existent")).Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "dashboard_not_found_empty_id", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "", - wantDisplayName: "", - wantErr: errDashboardNotFound("test-project", dashboardID("test-project", "test-project", "")).Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "find_first_of_many", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - "dashboards/d3.yaml": suiteMkDashboardYAML("d-3", "Dashboard 3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "d-1", - wantDisplayName: "Dashboard 1", - wantErr: "", - }, - { - name: "find_middle_of_many", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - "dashboards/d3.yaml": suiteMkDashboardYAML("d-3", "Dashboard 3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "d-2", - wantDisplayName: "Dashboard 2", - wantErr: "", - }, - { - name: "find_last_of_many", - files: map[string]string{ - "dashboards/d1.yaml": suiteMkDashboardYAML("d-1", "Dashboard 1"), - "dashboards/d2.yaml": suiteMkDashboardYAML("d-2", "Dashboard 2"), - "dashboards/d3.yaml": suiteMkDashboardYAML("d-3", "Dashboard 3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - metadataName: "d-3", - wantDisplayName: "Dashboard 3", - wantErr: "", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - store, ptr, cleanup := constructor(t, tt.files, tt.dashboardDir, tt.alertDir) - defer cleanup() - - dashID := dashboardID("test-project", "test-project", tt.metadataName) - - var gotDashboard *typesv1.Dashboard - err := store.getDashboard(ctx, "test-project", ptr, dashID, - func(d *typesv1.Dashboard) error { - gotDashboard = d - return nil - }) - - if tt.wantErr != "" { - require.Error(t, err) - require.Equal(t, tt.wantErr, err.Error(), "error message mismatch") - require.Equal(t, tt.wantErrCode, connect.CodeOf(err), "error code mismatch") - } else { - require.NoError(t, err) - require.NotNil(t, gotDashboard) - require.Equal(t, dashID, gotDashboard.Meta.Id) - require.Equal(t, tt.wantDisplayName, gotDashboard.Spec.Name) - } - }) - } -} - -func runGetAlertGroupTests(t *testing.T, constructor storageConstructorFn) { - tests := []struct { - name string - files map[string]string - dashboardDir string - alertDir string - groupName string - wantAlertGroup *suiteExpectedAlertGroup // nil if expecting error - wantErr string - wantErrCode connect.Code - }{ - { - name: "directory_missing", - files: map[string]string{"README.md": "# Test"}, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "any-group", - wantAlertGroup: nil, - wantErr: errInvalid("project %q has no alert directory at %q", "test-project", "alerts").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "directory_empty", - files: map[string]string{"alerts/.gitkeep": ""}, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "any-group", - wantAlertGroup: nil, - wantErr: errAlertGroupNotFound("test-project", "any-group").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "alert_group_found", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - "alerts/g2.yaml": suiteMkAlertGroupYAML("group-2", "rule-2"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "group-1", - wantAlertGroup: &suiteExpectedAlertGroup{name: "group-1"}, - wantErr: "", - }, - { - name: "alert_group_not_found_wrong_name", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "non-existent", - wantAlertGroup: nil, - wantErr: errAlertGroupNotFound("test-project", "non-existent").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "alert_group_not_found_empty_name", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "", - wantAlertGroup: nil, - wantErr: errAlertGroupNotFound("test-project", "").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "alert_group_with_multiple_rules", - files: map[string]string{ - "alerts/multi.yaml": suiteMkAlertGroupYAML("multi-group", "r1", "r2", "r3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "multi-group", - wantAlertGroup: &suiteExpectedAlertGroup{name: "multi-group"}, - wantErr: "", - }, - { - name: "find_first_of_many", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - "alerts/g2.yaml": suiteMkAlertGroupYAML("group-2", "rule-2"), - "alerts/g3.yaml": suiteMkAlertGroupYAML("group-3", "rule-3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "group-1", - wantAlertGroup: &suiteExpectedAlertGroup{name: "group-1"}, - wantErr: "", - }, - { - name: "find_middle_of_many", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - "alerts/g2.yaml": suiteMkAlertGroupYAML("group-2", "rule-2"), - "alerts/g3.yaml": suiteMkAlertGroupYAML("group-3", "rule-3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "group-2", - wantAlertGroup: &suiteExpectedAlertGroup{name: "group-2"}, - wantErr: "", - }, - { - name: "find_last_of_many", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - "alerts/g2.yaml": suiteMkAlertGroupYAML("group-2", "rule-2"), - "alerts/g3.yaml": suiteMkAlertGroupYAML("group-3", "rule-3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "group-3", - wantAlertGroup: &suiteExpectedAlertGroup{name: "group-3"}, - wantErr: "", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - store, ptr, cleanup := constructor(t, tt.files, tt.dashboardDir, tt.alertDir) - defer cleanup() - alertState := &suiteMockAlertStorage{} - - var gotAlertGroup *typesv1.AlertGroup - err := store.getAlertGroup(ctx, alertState, "test-project", ptr, tt.groupName, - func(ag *typesv1.AlertGroup) error { - gotAlertGroup = ag - return nil - }) - - if tt.wantErr != "" { - require.Error(t, err) - require.Equal(t, tt.wantErr, err.Error()) - require.Equal(t, tt.wantErrCode, connect.CodeOf(err)) - } else { - require.NoError(t, err) - require.NotNil(t, gotAlertGroup) - require.Equal(t, tt.wantAlertGroup.name, gotAlertGroup.Spec.Name) - } - }) - } -} - -type suiteMockAlertStorage struct{} - -func (m *suiteMockAlertStorage) AlertGetOrCreate(ctx context.Context, projectName, groupName, alertName string, create func() *typesv1.AlertRuleStatus) (*typesv1.AlertRuleStatus, error) { - return create(), nil -} - -func (m *suiteMockAlertStorage) AlertUpdateState(ctx context.Context, stackName, groupName, alertName string, state *typesv1.AlertRuleStatus) error { - return nil -} - -func (m *suiteMockAlertStorage) AlertDeleteStateNotInList(ctx context.Context, stackName, groupName string, keeplist []string) error { - return nil -} - -func runGetAlertRuleTests(t *testing.T, constructor storageConstructorFn) { - tests := []struct { - name string - files map[string]string - dashboardDir string - alertDir string - groupName string - ruleName string - wantRuleID string - wantErr string - wantErrCode connect.Code - }{ - { - name: "directory_missing", - files: map[string]string{"README.md": "# Test"}, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "any-group", - ruleName: "any-rule", - wantRuleID: "", - wantErr: errInvalid("project %q has no alert directory at %q", "test-project", "alerts").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "directory_empty", - files: map[string]string{"alerts/.gitkeep": ""}, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "any-group", - ruleName: "any-rule", - wantRuleID: "", - wantErr: errAlertRuleNotFound("test-project", "any-group", "any-rule").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "group_not_found", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "non-existent", - ruleName: "rule-1", - wantRuleID: "", - wantErr: errAlertRuleNotFound("test-project", "non-existent", "rule-1").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "rule_not_found", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "group-1", - ruleName: "non-existent", - wantRuleID: "", - wantErr: errAlertRuleNotFound("test-project", "group-1", "non-existent").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "rule_found", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "group-1", - ruleName: "rule-1", - wantRuleID: "rule-1", - wantErr: "", - }, - { - name: "find_first_rule_in_multi_rule_group", - files: map[string]string{ - "alerts/multi.yaml": suiteMkAlertGroupYAML("multi-group", "r1", "r2", "r3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "multi-group", - ruleName: "r1", - wantRuleID: "r1", - wantErr: "", - }, - { - name: "find_middle_rule_in_multi_rule_group", - files: map[string]string{ - "alerts/multi.yaml": suiteMkAlertGroupYAML("multi-group", "r1", "r2", "r3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "multi-group", - ruleName: "r2", - wantRuleID: "r2", - wantErr: "", - }, - { - name: "find_last_rule_in_multi_rule_group", - files: map[string]string{ - "alerts/multi.yaml": suiteMkAlertGroupYAML("multi-group", "r1", "r2", "r3"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "multi-group", - ruleName: "r3", - wantRuleID: "r3", - wantErr: "", - }, - { - name: "empty_group_name", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "", - ruleName: "rule-1", - wantRuleID: "", - wantErr: errAlertRuleNotFound("test-project", "", "rule-1").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - { - name: "empty_rule_name", - files: map[string]string{ - "alerts/g1.yaml": suiteMkAlertGroupYAML("group-1", "rule-1"), - }, - dashboardDir: "dashboards", - alertDir: "alerts", - groupName: "group-1", - ruleName: "", - wantRuleID: "", - wantErr: errAlertRuleNotFound("test-project", "group-1", "").Error(), - wantErrCode: connect.CodeInvalidArgument, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - store, ptr, cleanup := constructor(t, tt.files, tt.dashboardDir, tt.alertDir) - defer cleanup() - alertState := &suiteMockAlertStorage{} - - var gotAlertRule *typesv1.AlertRule - err := store.getAlertRule(ctx, alertState, "test-project", ptr, tt.groupName, tt.ruleName, - func(ar *typesv1.AlertRule) error { - gotAlertRule = ar - return nil - }) - - if tt.wantErr != "" { - require.Error(t, err) - require.Equal(t, tt.wantErr, err.Error()) - require.Equal(t, tt.wantErrCode, connect.CodeOf(err)) - } else { - require.NoError(t, err) - require.NotNil(t, gotAlertRule) - require.Equal(t, tt.wantRuleID, gotAlertRule.Meta.Id) - } - }) - } -} diff --git a/internal/localproject/watch.go b/internal/localproject/watch.go deleted file mode 100644 index 6748c880..00000000 --- a/internal/localproject/watch.go +++ /dev/null @@ -1,879 +0,0 @@ -package localproject - -import ( - "context" - "encoding/base32" - "encoding/json" - "fmt" - "path/filepath" - "slices" - "strings" - "sync" - "time" - - "connectrpc.com/connect" - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/memfs" - alertv1 "github.com/minitape/api/go/svc/alert/v1" - dashboardv1 "github.com/minitape/api/go/svc/dashboard/v1" - projectv1 "github.com/minitape/api/go/svc/project/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/localstate" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/pkg/localstorage" - "github.com/zeebo/blake3" - "google.golang.org/protobuf/proto" -) - -type ProjectSource interface { - GetProject() -} - -type CreateProjectFn func() *typesv1.Project - -type GetProjectFn func( - *typesv1.Project, -) error - -type GetProjectHydratedFn func( - *typesv1.Project, - []*typesv1.Dashboard, - []*typesv1.AlertGroup, -) error -type GetDashboardFn func(*typesv1.Dashboard) error -type CreateDashboardFn func(*typesv1.Dashboard) error -type UpdateDashboardFn func(*typesv1.Dashboard) error -type DeleteDashboardFn func() error -type GetAlertGroupFn func(*typesv1.AlertGroup) error -type CreateAlertGroupFn func(*typesv1.AlertGroup) error -type UpdateAlertGroupFn func(*typesv1.AlertGroup) error -type DeleteAlertGroupFn func() error -type GetAlertRuleFn func(*typesv1.AlertRule) error - -type projectStorage interface { - getOrCreateProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onCreate CreateProjectFn, onGetProject GetProjectFn) error - getProjectHydrated(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectHydratedFn) error - getProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error - syncProject(ctx context.Context, name string, ptr *typesv1.ProjectPointer, onGetProject GetProjectFn) error - getDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, onDashboard GetDashboardFn) error - createDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, dashboard *typesv1.Dashboard, onCreated CreateDashboardFn) error - updateDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, dashboard *typesv1.Dashboard, onUpdated UpdateDashboardFn) error - deleteDashboard(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, id string, onDeleted DeleteDashboardFn) error - getAlertGroup(ctx context.Context, alertState localstorage.Alertable, projectName string, ptr *typesv1.ProjectPointer, groupName string, onAlertGroup GetAlertGroupFn) error - createAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, alertGroup *typesv1.AlertGroup, onCreated CreateAlertGroupFn) error - updateAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, alertGroup *typesv1.AlertGroup, onUpdated UpdateAlertGroupFn) error - deleteAlertGroup(ctx context.Context, projectName string, ptr *typesv1.ProjectPointer, groupName string, onDeleted DeleteAlertGroupFn) error - getAlertRule(ctx context.Context, alertState localstorage.Alertable, projectName string, ptr *typesv1.ProjectPointer, groupName, ruleName string, onAlertRule GetAlertRuleFn) error - validateProjectPointer(ctx context.Context, ptr *typesv1.ProjectPointer) error -} - -func errInvalid(msg string, args ...any) error { - return connect.NewError(connect.CodeInvalidArgument, fmt.Errorf(msg, args...)) -} - -func errInternal(msg string, args ...any) error { - return connect.NewError(connect.CodeInternal, fmt.Errorf(msg, args...)) -} - -func errNotFound(msg string, args ...any) error { - return connect.NewError(connect.CodeNotFound, fmt.Errorf(msg, args...)) -} - -type watch struct { - db *dbStorage - remote *remoteGitStorage - local *localGitStorage - - mu sync.Mutex - cfg *config.Config - alertState localstorage.Alertable - logQlParser func(string) (*typesv1.Query, error) - - timeNow func() time.Time -} - -func Watch( - ctx context.Context, - fs billy.Filesystem, - cfg *config.Config, - alertState localstorage.Alertable, - logQlParser func(string) (*typesv1.Query, error), -) (localstate.DB, error) { - return internalWatch(ctx, fs, cfg, alertState, logQlParser, time.Now) -} - -func internalWatch( - ctx context.Context, - fs billy.Filesystem, - cfg *config.Config, - alertState localstorage.Alertable, - logQlParser func(string) (*typesv1.Query, error), - timeNow func() time.Time, -) (localstate.DB, error) { - gitfs := memfs.New() - remote, err := newRemoteGitStorage(nil, gitfs, logQlParser, timeNow) - if err != nil { - return nil, err - } - return &watch{ - db: newDBStorage(nil, nil, logQlParser, timeNow), - remote: remote, - local: newLocalGitStorage(nil, fs, logQlParser, timeNow), - cfg: cfg, - alertState: alertState, - logQlParser: logQlParser, - timeNow: timeNow, - }, nil -} - -func (wt *watch) storageForPointer(ptr *typesv1.ProjectPointer) (projectStorage, error) { - switch ptr.Scheme.(type) { - case *typesv1.ProjectPointer_Remote: - return wt.remote, nil - case *typesv1.ProjectPointer_Localhost: - return wt.local, nil - case *typesv1.ProjectPointer_Db: - return wt.db, nil - } - return nil, errInvalid("unknown project pointer type: %T", ptr.Scheme) -} - -func (wt *watch) CreateProject(ctx context.Context, req *projectv1.CreateProjectRequest) (*projectv1.CreateProjectResponse, error) { - name := req.Spec.Name - - err := func() error { - wt.mu.Lock() - defer wt.mu.Unlock() - cfg, err := wt.cfg.Reload() - if err != nil { - return fmt.Errorf("reading config file: %v", err) - } - wt.cfg = cfg - if cfg.Runtime == nil { - cfg.Runtime = &typesv1.RuntimeConfig{} - } - if cfg.Runtime.ExperimentalFeatures == nil { - cfg.Runtime.ExperimentalFeatures = &typesv1.RuntimeConfig_ExperimentalFeatures{} - } - if cfg.Runtime.ExperimentalFeatures.Projects == nil { - cfg.Runtime.ExperimentalFeatures.Projects = &typesv1.ProjectsConfig{} - } - projects := cfg.Runtime.ExperimentalFeatures.Projects - - sp := &typesv1.ProjectsConfig_Project{ - Name: name, - Pointer: req.Spec.Pointer, - } - - onCreate := func() *typesv1.Project { panic("todo") } - - var toStoreInConfig *typesv1.ProjectsConfig_Project - onGet := func(p *typesv1.Project) error { - toStoreInConfig = &typesv1.ProjectsConfig_Project{ - Name: p.Spec.Name, - Pointer: p.Spec.Pointer, - } - return nil - } - - storage, err := wt.storageForPointer(req.Spec.Pointer) - if err != nil { - return err - } - if err := wt.validateProjectPointer(ctx, projects.Projects, name, sp, storage); err != nil { - return err - } - if err := storage.getOrCreateProject(ctx, name, req.Spec.Pointer, onCreate, onGet); err != nil { - return err - } - - projects.Projects = append(projects.Projects, toStoreInConfig) - cfg.Runtime.ExperimentalFeatures.Projects = projects - if err := cfg.WriteBack(); err != nil { - return connect.NewError(connect.CodeInternal, fmt.Errorf("writing back configuration: %v", err)) - } - return nil - }() - if err != nil { - return nil, err - } - var out *typesv1.Project - err = wt.lockedWithProjectByName(ctx, req.Spec.Name, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.getProject(ctx, ptr.Name, ptr.Pointer, func(p *typesv1.Project) error { - out = p - // Enrich project with all warnings - wt.enrichProjectWithWarnings(p.Status, ptr) - return nil - }) - }) - return &projectv1.CreateProjectResponse{Project: out}, err -} - -func (wt *watch) ValidateProject(ctx context.Context, req *projectv1.ValidateProjectRequest) (*projectv1.ValidateProjectResponse, error) { - name := req.Spec.Name - - var status *typesv1.ProjectStatus - err := func() error { - wt.mu.Lock() - defer wt.mu.Unlock() - cfg, err := wt.cfg.Reload() - if err != nil { - return fmt.Errorf("reading config file: %v", err) - } - wt.cfg = cfg - if cfg.Runtime == nil { - cfg.Runtime = &typesv1.RuntimeConfig{} - } - if cfg.Runtime.ExperimentalFeatures == nil { - cfg.Runtime.ExperimentalFeatures = &typesv1.RuntimeConfig_ExperimentalFeatures{} - } - if cfg.Runtime.ExperimentalFeatures.Projects == nil { - cfg.Runtime.ExperimentalFeatures.Projects = &typesv1.ProjectsConfig{} - } - projects := cfg.Runtime.ExperimentalFeatures.Projects - - sp := &typesv1.ProjectsConfig_Project{ - Name: name, - Pointer: req.Spec.Pointer, - } - - storage, err := wt.storageForPointer(req.Spec.Pointer) - if err != nil { - return err - } - // Run the same validation as CreateProject - if err := wt.validateProjectPointer(ctx, projects.Projects, name, sp, storage); err != nil { - return err - } - - // Create a status object to compute warnings using the same code path - status = &typesv1.ProjectStatus{} - wt.enrichProjectWithWarnings(status, sp) - return nil - }() - if err != nil { - return nil, err - } - - return &projectv1.ValidateProjectResponse{Status: status}, nil -} - -func (wt *watch) validateProjectPointer(ctx context.Context, projects []*typesv1.ProjectsConfig_Project, name string, sp *typesv1.ProjectsConfig_Project, storage projectStorage) error { - if name == "" { - return connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("project name cannot be empty")) - } - for _, project := range projects { - if project.Name == name { - return errInvalid("a project with this name already exists") - } - } - return storage.validateProjectPointer(ctx, sp.Pointer) -} - -func (wt *watch) UpdateProject(ctx context.Context, req *projectv1.UpdateProjectRequest) (*projectv1.UpdateProjectResponse, error) { - err := wt.lockedWithProjectByName(ctx, req.Name, func(sc *typesv1.ProjectsConfig_Project) error { - candidate := proto.Clone(sc).(*typesv1.ProjectsConfig_Project) - candidate.Name = req.Spec.Name - candidate.Pointer = req.Spec.Pointer - storage, err := wt.storageForPointer(candidate.Pointer) - if err != nil { - return err - } - projects := wt.cfg.GetRuntime().GetExperimentalFeatures().GetProjects() - // Filter out the project being updated to avoid false conflicts when keeping the same name - otherProjects := make([]*typesv1.ProjectsConfig_Project, 0, len(projects.Projects)-1) - for _, p := range projects.Projects { - if p.Name != req.Name { // req.Name is the OLD name - otherProjects = append(otherProjects, p) - } - } - if err := wt.validateProjectPointer(ctx, otherProjects, candidate.Name, candidate, storage); err != nil { - return err - } - wt.cfg.GetRuntime().GetExperimentalFeatures().Projects = projects - if err := wt.cfg.WriteBack(); err != nil { - return connect.NewError(connect.CodeInternal, fmt.Errorf("updating project on disk: %v", err)) - } - return nil - }) - if err != nil { - return nil, err - } - // return an updated version of the project - var out *typesv1.Project - - err = wt.lockedWithProjectByName(ctx, req.Name, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.getProject(ctx, ptr.Name, ptr.Pointer, func(p *typesv1.Project) error { - out = p - // Enrich project with all warnings - wt.enrichProjectWithWarnings(p.Status, ptr) - return nil - }) - }) - return &projectv1.UpdateProjectResponse{Project: out}, err -} - -func (wt *watch) DeleteProject(ctx context.Context, req *projectv1.DeleteProjectRequest) (*projectv1.DeleteProjectResponse, error) { - // return an updated version of the project - err := wt.lockedWithProjectConfig(ctx, func(s *typesv1.ProjectsConfig) error { - found := false - s.Projects = slices.DeleteFunc(s.Projects, func(e *typesv1.ProjectsConfig_Project) bool { - found = true - return e.Name == req.Name - }) - if !found { - return nil - } - wt.cfg.GetRuntime().GetExperimentalFeatures().Projects = s - if err := wt.cfg.WriteBack(); err != nil { - return connect.NewError(connect.CodeInternal, fmt.Errorf("deleting project on disk: %v", err)) - } - return nil - }) - return &projectv1.DeleteProjectResponse{}, err -} - -func (wt *watch) GetProject(ctx context.Context, req *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) { - var ( - project *typesv1.Project - dashboards []*typesv1.Dashboard - alertGroups []*typesv1.AlertGroup - err error - ) - err = wt.lockedWithProjectByName(ctx, req.Name, func(ptr *typesv1.ProjectsConfig_Project) error { - - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.getProjectHydrated(ctx, ptr.Name, ptr.Pointer, func(p *typesv1.Project, d []*typesv1.Dashboard, ag []*typesv1.AlertGroup) error { - project = p - dashboards = d - alertGroups = ag - - // Enrich project with all warnings - wt.enrichProjectWithWarnings(p.Status, ptr) - - return nil - }) - }) - if err != nil { - return nil, err - } - return &projectv1.GetProjectResponse{Project: project, Dashboards: dashboards, AlertGroups: alertGroups}, nil -} - -func (wt *watch) SyncProject(ctx context.Context, req *projectv1.SyncProjectRequest) (*projectv1.SyncProjectResponse, error) { - var ( - project *typesv1.Project - err error - ) - err = wt.lockedWithProjectByName(ctx, req.Name, func(ptr *typesv1.ProjectsConfig_Project) error { - - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.getProjectHydrated(ctx, ptr.Name, ptr.Pointer, func(p *typesv1.Project, d []*typesv1.Dashboard, ag []*typesv1.AlertGroup) error { - project = p - return nil - }) - }) - if err != nil { - return nil, err - } - return &projectv1.SyncProjectResponse{Project: project}, nil -} - -func (wt *watch) ListProject(ctx context.Context, req *projectv1.ListProjectRequest) (*projectv1.ListProjectResponse, error) { - var ( - out []*projectv1.ListProjectResponse_ListItem - next *typesv1.Cursor - err error - ) - err = wt.lockedWithProjectConfig(ctx, func(sc *typesv1.ProjectsConfig) error { - next, err = cursorForSlice(sc.Projects, req.Cursor, req.Limit, 10, 100, - func(sp *typesv1.ProjectsConfig_Project) string { return sp.Name }, - func(sp *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(sp.Pointer) - if err != nil { - return err - } - return storage.getProject(ctx, sp.Name, sp.Pointer, func(p *typesv1.Project) error { - // Enrich project with all warnings - wt.enrichProjectWithWarnings(p.Status, sp) - out = append(out, &projectv1.ListProjectResponse_ListItem{Project: p}) - return nil - }) - }, - ) - return err - }) - return &projectv1.ListProjectResponse{Items: out, Next: next}, err -} - -func (wt *watch) CreateDashboard(ctx context.Context, req *dashboardv1.CreateDashboardRequest) (*dashboardv1.CreateDashboardResponse, error) { - var out *typesv1.Dashboard - err := wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - // ID will be extracted from Perses dashboard metadata.name (slug) in storage layer - dashboard := &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{}, // ID set by storage layer - Spec: req.Spec, - Status: &typesv1.DashboardStatus{}, - } - return storage.createDashboard(ctx, ptr.Name, ptr.Pointer, dashboard, func(dashboard *typesv1.Dashboard) error { - out = dashboard - return nil - }) - }) - return &dashboardv1.CreateDashboardResponse{Dashboard: out}, err -} - -func (wt *watch) UpdateDashboard(ctx context.Context, req *dashboardv1.UpdateDashboardRequest) (*dashboardv1.UpdateDashboardResponse, error) { - var out *typesv1.Dashboard - err := wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - dashboard := &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{Id: req.Id}, - Spec: req.Spec, - Status: &typesv1.DashboardStatus{}, - } - return storage.updateDashboard(ctx, ptr.Name, ptr.Pointer, req.Id, dashboard, func(dashboard *typesv1.Dashboard) error { - out = dashboard - return nil - }) - }) - return &dashboardv1.UpdateDashboardResponse{Dashboard: out}, err -} - -func (wt *watch) DeleteDashboard(ctx context.Context, req *dashboardv1.DeleteDashboardRequest) (*dashboardv1.DeleteDashboardResponse, error) { - err := wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.deleteDashboard(ctx, ptr.Name, ptr.Pointer, req.Id, func() error { - return nil - }) - }) - return &dashboardv1.DeleteDashboardResponse{}, err -} -func (wt *watch) GetDashboard(ctx context.Context, req *dashboardv1.GetDashboardRequest) (*dashboardv1.GetDashboardResponse, error) { - var ( - out *typesv1.Dashboard - err error - ) - err = wt.lockedWithDashboardByID(ctx, req.ProjectName, req.Id, func(s *typesv1.Dashboard) error { - out = s - return nil - }) - return &dashboardv1.GetDashboardResponse{Dashboard: out}, err -} -func (wt *watch) ListDashboard(ctx context.Context, req *dashboardv1.ListDashboardRequest) (*dashboardv1.ListDashboardResponse, error) { - var ( - out []*dashboardv1.ListDashboardResponse_ListItem - next *typesv1.Cursor - err error - ) - err = wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.getProjectHydrated(ctx, ptr.Name, ptr.Pointer, func(p *typesv1.Project, items []*typesv1.Dashboard, ag []*typesv1.AlertGroup) error { - next, err = cursorForSlice(items, req.Cursor, req.Limit, 10, 100, - func(sp *typesv1.Dashboard) string { return sp.Meta.Id }, - func(sp *typesv1.Dashboard) error { - out = append(out, &dashboardv1.ListDashboardResponse_ListItem{Dashboard: sp}) - return nil - }, - ) - return nil - }) - }) - return &dashboardv1.ListDashboardResponse{Items: out, Next: next}, err -} - -func (wt *watch) CreateAlertGroup(ctx context.Context, req *alertv1.CreateAlertGroupRequest) (*alertv1.CreateAlertGroupResponse, error) { - var out *typesv1.AlertGroup - err := wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - alertGroup := &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{Id: req.Spec.Name}, // ID from group name - Spec: req.Spec, - Status: &typesv1.AlertGroupStatus{}, - } - return storage.createAlertGroup(ctx, ptr.Name, ptr.Pointer, alertGroup, func(alertGroup *typesv1.AlertGroup) error { - out = alertGroup - return nil - }) - }) - return &alertv1.CreateAlertGroupResponse{AlertGroup: out}, err -} - -func (wt *watch) UpdateAlertGroup(ctx context.Context, req *alertv1.UpdateAlertGroupRequest) (*alertv1.UpdateAlertGroupResponse, error) { - var out *typesv1.AlertGroup - err := wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - alertGroup := &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{Id: req.Name}, - Spec: req.Spec, - Status: &typesv1.AlertGroupStatus{}, - } - return storage.updateAlertGroup(ctx, ptr.Name, ptr.Pointer, req.Name, alertGroup, func(alertGroup *typesv1.AlertGroup) error { - out = alertGroup - return nil - }) - }) - return &alertv1.UpdateAlertGroupResponse{AlertGroup: out}, err -} -func (wt *watch) DeleteAlertGroup(ctx context.Context, req *alertv1.DeleteAlertGroupRequest) (*alertv1.DeleteAlertGroupResponse, error) { - err := wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.deleteAlertGroup(ctx, ptr.Name, ptr.Pointer, req.Name, func() error { - return nil - }) - }) - return &alertv1.DeleteAlertGroupResponse{}, err -} -func (wt *watch) GetAlertGroup(ctx context.Context, req *alertv1.GetAlertGroupRequest) (*alertv1.GetAlertGroupResponse, error) { - var out *typesv1.AlertGroup - err := wt.lockedWithAlertGroupByName(ctx, req.ProjectName, req.Name, func(_ *typesv1.ProjectsConfig_Project, s *typesv1.AlertGroup) error { - out = s - return nil - }) - if err != nil { - return nil, err - } - - // Populate status from alertState storage - if out.Status == nil { - out.Status = &typesv1.AlertGroupStatus{} - } - if out.Status.Rules == nil { - out.Status.Rules = make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, 0, len(out.Spec.Rules)) - } - - // Query status for each rule from storage - for _, namedRule := range out.Spec.Rules { - status, err := wt.alertState.AlertGetOrCreate(ctx, req.ProjectName, req.Name, namedRule.Id, func() *typesv1.AlertRuleStatus { - return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{}} - }) - if err != nil { - // If project doesn't exist in alert state yet, use default unknown status - status = &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{}} - } - - // Check if status already exists in the array - found := false - for _, namedStatus := range out.Status.Rules { - if namedStatus.Id == namedRule.Id { - namedStatus.Status = status - found = true - break - } - } - if !found { - out.Status.Rules = append(out.Status.Rules, &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: namedRule.Id, - Status: status, - }) - } - } - - return &alertv1.GetAlertGroupResponse{AlertGroup: out}, nil -} - -func (wt *watch) ListAlertGroup(ctx context.Context, req *alertv1.ListAlertGroupRequest) (*alertv1.ListAlertGroupResponse, error) { - var ( - out []*alertv1.ListAlertGroupResponse_ListItem - next *typesv1.Cursor - err error - ) - err = wt.lockedWithProjectByName(ctx, req.ProjectName, func(ptr *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(ptr.Pointer) - if err != nil { - return err - } - return storage.getProjectHydrated(ctx, ptr.Name, ptr.Pointer, func(p *typesv1.Project, d []*typesv1.Dashboard, items []*typesv1.AlertGroup) error { - next, err = cursorForSlice(items, req.Cursor, req.Limit, 10, 100, - func(sp *typesv1.AlertGroup) string { return sp.Spec.Name }, - func(sp *typesv1.AlertGroup) error { - out = append(out, &alertv1.ListAlertGroupResponse_ListItem{AlertGroup: sp}) - return nil - }, - ) - return nil - }) - }) - if err != nil { - return nil, err - } - - return &alertv1.ListAlertGroupResponse{Items: out, Next: next}, nil -} - -func (wt *watch) CreateAlertRule(ctx context.Context, req *alertv1.CreateAlertRuleRequest) (*alertv1.CreateAlertRuleResponse, error) { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("localhost alerts are created on the filesystem")) -} -func (wt *watch) UpdateAlertRule(ctx context.Context, req *alertv1.UpdateAlertRuleRequest) (*alertv1.UpdateAlertRuleResponse, error) { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("localhost alerts are updated on the filesystem")) -} -func (wt *watch) DeleteAlertRule(ctx context.Context, req *alertv1.DeleteAlertRuleRequest) (*alertv1.DeleteAlertRuleResponse, error) { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("localhost alerts are deleted on the filesystem")) -} -func (wt *watch) GetAlertRule(ctx context.Context, req *alertv1.GetAlertRuleRequest) (*alertv1.GetAlertRuleResponse, error) { - var ( - out *typesv1.AlertRule - err error - ) - err = wt.lockedWithAlertByName(ctx, req.ProjectName, req.GroupName, req.Name, func(ar *typesv1.AlertRule) error { - out = ar - return nil - }) - return &alertv1.GetAlertRuleResponse{AlertRule: out}, err -} -func (wt *watch) ListAlertRule(ctx context.Context, req *alertv1.ListAlertRuleRequest) (*alertv1.ListAlertRuleResponse, error) { - var ( - out []*alertv1.ListAlertRuleResponse_ListItem - next *typesv1.Cursor - err error - ) - err = wt.lockedWithAlertGroupByName(ctx, req.ProjectName, req.GroupName, func(_ *typesv1.ProjectsConfig_Project, ag *typesv1.AlertGroup) error { - // Note: ag.Status.Rules is already hydrated by lockedWithAlertGroupByName - // Create a map for quick lookup by id - stateById := make(map[string]*typesv1.AlertRuleStatus) - for _, namedStatus := range ag.Status.Rules { - stateById[namedStatus.Id] = namedStatus.Status - } - - next, err = cursorForSlice(ag.Spec.Rules, req.Cursor, req.Limit, 10, 100, - func(named *typesv1.AlertGroupSpec_NamedAlertRuleSpec) string { return named.Id }, - func(named *typesv1.AlertGroupSpec_NamedAlertRuleSpec) error { - // Get the actual runtime state for this rule - state, ok := stateById[named.Id] - if !ok { - state = &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}} - } - - // Construct full AlertRule from spec + state - rule := &typesv1.AlertRule{ - Meta: &typesv1.AlertRuleMeta{ - Id: named.Id, - }, - Spec: named.Spec, - Status: state, - } - out = append(out, &alertv1.ListAlertRuleResponse_ListItem{AlertRule: rule}) - return nil - }, - ) - return err - }) - return &alertv1.ListAlertRuleResponse{Items: out, Next: next}, err -} - -func (wt *watch) lockedWithProjectConfig(ctx context.Context, fn func(*typesv1.ProjectsConfig) error) error { - wt.mu.Lock() - defer wt.mu.Unlock() - // make sure we load the latest data - cfg, err := wt.cfg.Reload() - if err != nil { - return connect.NewError(connect.CodeInternal, fmt.Errorf("reloading config file: %v", err)) - } - wt.cfg = cfg - - projects := cfg.GetRuntime().GetExperimentalFeatures().GetProjects() - if projects == nil { - return connect.NewError(connect.CodeNotFound, fmt.Errorf("localhost projects are not enabled, set them up in your config file")) - } - return fn(projects) -} - -func (wt *watch) lockedWithProjectByName(ctx context.Context, name string, fn func(*typesv1.ProjectsConfig_Project) error) error { - return wt.lockedWithProjectConfig(ctx, func(sc *typesv1.ProjectsConfig) error { - - for _, pointer := range sc.Projects { - if pointer.Name == name { - return fn(pointer) - } - } - return connect.NewError(connect.CodeNotFound, fmt.Errorf("localhost doesn't have a project named %q in its config file", name)) - }) -} - -func (wt *watch) lockedWithDashboardByID(ctx context.Context, projectName, id string, fn func(*typesv1.Dashboard) error) error { - return wt.lockedWithProjectByName(ctx, projectName, func(sc *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(sc.Pointer) - if err != nil { - return err - } - return storage.getDashboard(ctx, projectName, sc.Pointer, id, fn) - }) -} - -func (wt *watch) lockedWithAlertGroupByName(ctx context.Context, projectName, groupName string, fn func(*typesv1.ProjectsConfig_Project, *typesv1.AlertGroup) error) error { - return wt.lockedWithProjectByName(ctx, projectName, func(sc *typesv1.ProjectsConfig_Project) error { - storage, err := wt.storageForPointer(sc.Pointer) - if err != nil { - return err - } - return storage.getAlertGroup(ctx, wt.alertState, projectName, sc.Pointer, groupName, func(ag *typesv1.AlertGroup) error { - return fn(sc, ag) - }) - }) -} - -func (wt *watch) lockedWithAlertByName(ctx context.Context, projectName, groupName, name string, fn func(*typesv1.AlertRule) error) error { - return wt.lockedWithAlertGroupByName(ctx, projectName, groupName, func(sc *typesv1.ProjectsConfig_Project, ag *typesv1.AlertGroup) error { - storage, err := wt.storageForPointer(sc.Pointer) - if err != nil { - return err - } - - return storage.getAlertRule(ctx, wt.alertState, projectName, sc.Pointer, groupName, name, fn) - }) -} - -// sharedDashboardDirWarning returns a warning message for projects sharing the same dashboard directory -func sharedDashboardDirWarning(otherProjectName, dirPath string) string { - return fmt.Sprintf("Project %q shares the same dashboard directory (%s). Changes in one project will affect the other.", otherProjectName, dirPath) -} - -// sharedAlertDirWarning returns a warning message for projects sharing the same alert directory -func sharedAlertDirWarning(otherProjectName, dirPath string) string { - return fmt.Sprintf("Project %q shares the same alert directory (%s). Changes in one project will affect the other.", otherProjectName, dirPath) -} - -// enrichProjectWithWarnings populates all warnings for a project status -// This should be called whenever returning a project to ensure warnings are up-to-date -func (wt *watch) enrichProjectWithWarnings(status *typesv1.ProjectStatus, ptr *typesv1.ProjectsConfig_Project) { - wt.addDirectoryConflictWarnings(status, ptr) - // Future warning checks can be added here -} - -// computeProjectWarnings computes warnings for a project without modifying it -// Used by ValidateProject to preview warnings before creating the project -func (wt *watch) computeProjectWarnings(currentPtr *typesv1.ProjectsConfig_Project, allProjects []*typesv1.ProjectsConfig_Project) []string { - // Only check for localhost projects - localhost := currentPtr.Pointer.GetLocalhost() - if localhost == nil { - return nil - } - - var conflicts []string - for _, otherProj := range allProjects { - if otherProj.Name == currentPtr.Name { - continue // Skip self - } - - otherLocalhost := otherProj.Pointer.GetLocalhost() - if otherLocalhost == nil { - continue // Only check localhost projects - } - - // Check if dashboard directories match - currentDashDir := filepath.Join(localhost.Path, localhost.DashboardDir) - otherDashDir := filepath.Join(otherLocalhost.Path, otherLocalhost.DashboardDir) - if currentDashDir == otherDashDir { - conflicts = append(conflicts, sharedDashboardDirWarning(otherProj.Name, currentDashDir)) - } - - // Check if alert directories match - currentAlertDir := filepath.Join(localhost.Path, localhost.AlertDir) - otherAlertDir := filepath.Join(otherLocalhost.Path, otherLocalhost.AlertDir) - if currentAlertDir == otherAlertDir { - conflicts = append(conflicts, sharedAlertDirWarning(otherProj.Name, currentAlertDir)) - } - } - - return conflicts -} - -// addDirectoryConflictWarnings checks if this project shares directories with other projects -// and adds warnings to the project status if conflicts are found -func (wt *watch) addDirectoryConflictWarnings(status *typesv1.ProjectStatus, currentPtr *typesv1.ProjectsConfig_Project) { - cfg, err := wt.cfg.Reload() - if err != nil { - return // Can't check, skip - } - - if cfg.Runtime == nil || cfg.Runtime.ExperimentalFeatures == nil || cfg.Runtime.ExperimentalFeatures.Projects == nil { - return - } - - conflicts := wt.computeProjectWarnings(currentPtr, cfg.Runtime.ExperimentalFeatures.Projects.Projects) - if len(conflicts) > 0 { - status.Warnings = append(status.Warnings, conflicts...) - } -} - -func dashboardID(projectName, persesProjectName, dashboardName string) string { - h := blake3.New() - h.WriteString(projectName) - h.WriteString(persesProjectName) - h.WriteString(dashboardName) - return "hdash_" + strings.ToLower(base32.HexEncoding.WithPadding(base32.NoPadding).EncodeToString(h.Sum(nil))) -} - -type stringPage struct { - LastID string `json:"lastID"` -} - -func cursorForSlice[E any](sl []E, cursor *typesv1.Cursor, limit, minLimit, maxLimit int32, toStringID func(E) string, forEach func(E) error) (next *typesv1.Cursor, err error) { - limit = max(limit, maxLimit) - limit = min(limit, minLimit) - var fromID string - if cursor != nil { - var p stringPage - if err := json.Unmarshal(cursor.Opaque, &p); err != nil { - return nil, err - } - fromID = p.LastID - } - var i int - if fromID != "" { - i = slices.IndexFunc(sl, func(e E) bool { return toStringID(e) == fromID }) + 1 - } - from := i - to := min(i+int(limit), len(sl)) - out := sl[from:to] - for _, el := range out { - if err := forEach(el); err != nil { - return nil, err - } - } - if len(out) == int(limit) && limit != 0 { - next = new(typesv1.Cursor) - p := stringPage{LastID: toStringID(out[len(out)-1])} - next.Opaque, err = json.Marshal(p) - if err != nil { - return nil, err - } - } - return next, nil -} diff --git a/internal/localproject/watch_test.go b/internal/localproject/watch_test.go deleted file mode 100644 index 393e06e9..00000000 --- a/internal/localproject/watch_test.go +++ /dev/null @@ -1,665 +0,0 @@ -package localproject - -import ( - "context" - "encoding/json" - "net/url" - "slices" - "strings" - "testing" - "testing/fstest" - "time" - - "github.com/go-git/go-billy/v6/memfs" - "github.com/google/go-cmp/cmp" - dashboardv1 "github.com/minitape/api/go/svc/dashboard/v1" - projectv1 "github.com/minitape/api/go/svc/project/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/localstate" - "github.com/humanlogio/humanlog/internal/pkg/config" - persesv1 "github.com/perses/perses/pkg/model/api/v1" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/testing/protocmp" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/timestamppb" -) - -func TestWatch(t *testing.T) { - mkDashboardDataJSON := func() []byte { - return []byte(`{ - "kind": "Dashboard", - "metadata": { - "project": "my project", - "name": "my_dashboard" - }, - "spec": { - "display": { - "name": "my dashboard", - "description": "it's a nice dashboard" - } - } - }`) - } - mkDashboardDataYAML := func() []byte { - return []byte(`kind: Dashboard -metadata: - project: "my project" - name: "my_dashboard" -spec: - display: - name: "my dashboard" - description: "it's a nice dashboard"`) - } - mkExpectedPersesJSON := func() []byte { - dash := &persesv1.Dashboard{} - if err := dash.UnmarshalJSON(mkDashboardDataJSON()); err != nil { - t.Fatalf("failed to unmarshal dashboard: %v", err) - } - data, err := json.Marshal(dash) - if err != nil { - t.Fatalf("failed to marshal dashboard: %v", err) - } - return data - } - mkAlertGroupData1 := func() []byte { - return []byte(`groups: - - name: my-group-name - interval: 30s # defaults to global interval - rules: - - alert: HighErrors - expr: filter severity_text == "error" - for: 5m - labels: - severity: critical - annotations: - description: "stuff's happening with {{ $.labels.service }}" -`) - } - mkAlertGroupData2 := func() []byte { - return []byte(`groups: - - name: my-another-name - interval: 30s # defaults to global interval - rules: - - alert: HighErrors - expr: filter severity_text == "error" - for: 5m - labels: - severity: critical -`) - } - mkAlertGroupDataBoth := func() []byte { - return []byte(alertGroupYAML) - } - now := time.Date(2025, 9, 25, 17, 24, 19, 0, time.UTC) - timeNow := func() time.Time { return now } - - cmpOpts := []cmp.Option{ - protocmp.Transform(), - protocmp.IgnoreFields(&typesv1.DashboardStatus{}, "created_at", "updated_at"), - protocmp.IgnoreFields(&typesv1.ProjectStatus{}, "created_at", "updated_at"), - protocmp.IgnoreFields(&typesv1.AlertGroupStatus{}, "created_at", "updated_at"), - } - - type subtest struct { - name string - check func(context.Context, *testing.T, localstate.DB) - } - - tests := []struct { - name string - fs fstest.MapFS - cfg *typesv1.ProjectsConfig - subtest []subtest - }{ - { - name: "some projects", - fs: fstest.MapFS{ - "project1dir/dashdir/dash1.json": &fstest.MapFile{Data: mkDashboardDataJSON()}, - "project1dir/dashdir/dash2.yaml": &fstest.MapFile{Data: mkDashboardDataYAML()}, - "project1dir/dashdir/dash3.yml": &fstest.MapFile{Data: mkDashboardDataYAML()}, - "project1dir/dashdir/ignored": &fstest.MapFile{}, - "project1dir/alertdir/alert1.yaml": &fstest.MapFile{Data: mkAlertGroupData1()}, - "project1dir/alertdir/alert2.yml": &fstest.MapFile{Data: mkAlertGroupData2()}, - "project1dir/alertdir/ignored": &fstest.MapFile{}, - "project1dir/ignored": &fstest.MapFile{}, - - "project2dir/nested/dashdir/dash1.json": &fstest.MapFile{}, - "project2dir/nested/dashdir/dash2.yaml": &fstest.MapFile{}, - "project2dir/nested/dashdir/dash3.yml": &fstest.MapFile{}, - "project2dir/nested/dashdir/ignored": &fstest.MapFile{}, - "project2dir/nested/alertdir/alert1.yaml": &fstest.MapFile{}, - "project2dir/nested/alertdir/alert2.yml": &fstest.MapFile{}, - "project2dir/nested/alertdir/ignored": &fstest.MapFile{}, - "project2dir/nested/ignored": &fstest.MapFile{}, - }, - cfg: &typesv1.ProjectsConfig{ - Projects: projectConfigs( - projectConfig("my project", - localProjectPointer("project1dir", "dashdir", "alertdir", true), - ), - projectConfig("my other project", - localProjectPointer("project2dir", "nested/dashdir", "nested/alertdir", true), - ), - ), - }, - subtest: []subtest{ - { - name: "list projects", - check: func(ctx context.Context, t *testing.T, d localstate.DB) { - want := []*projectv1.ListProjectResponse_ListItem{ - {Project: &typesv1.Project{ - Meta: &typesv1.ProjectMeta{}, - Spec: &typesv1.ProjectSpec{ - Name: "my project", - Pointer: &typesv1.ProjectPointer{Scheme: &typesv1.ProjectPointer_Localhost{ - Localhost: &typesv1.ProjectPointer_LocalGit{ - Path: "project1dir", - AlertDir: "alertdir", - DashboardDir: "dashdir", - ReadOnly: true, - }, - }}, - }, - Status: &typesv1.ProjectStatus{ - CreatedAt: timestamppb.New(now), - UpdatedAt: timestamppb.New(now), - }, - }}, - {Project: &typesv1.Project{ - Meta: &typesv1.ProjectMeta{}, - Spec: &typesv1.ProjectSpec{ - Name: "my other project", - Pointer: &typesv1.ProjectPointer{Scheme: &typesv1.ProjectPointer_Localhost{ - Localhost: &typesv1.ProjectPointer_LocalGit{ - Path: "project2dir", - AlertDir: "nested/alertdir", - DashboardDir: "nested/dashdir", - ReadOnly: true, - }, - }}, - }, - Status: &typesv1.ProjectStatus{ - CreatedAt: timestamppb.New(now), - UpdatedAt: timestamppb.New(now), - }, - }}, - } - res, err := d.ListProject(ctx, &projectv1.ListProjectRequest{}) - require.NoError(t, err) - got := res.Items - - diff := cmp.Diff(want, got, cmpOpts...) - require.Empty(t, diff) - }, - }, - { - name: "get project and details", - check: func(ctx context.Context, t *testing.T, d localstate.DB) { - want := &projectv1.GetProjectResponse{ - Project: project( - "my project", - localProjectPointer("project1dir", "dashdir", "alertdir", true), - now, now, - ), - Dashboards: dashboards( - dashboard( - dashboardID("my project", "my project", "my_dashboard"), - "my dashboard", - "it's a nice dashboard", - true, - mkExpectedPersesJSON(), - "project1dir/dashdir/dash1.json", - now, now, - ), - dashboard( - dashboardID("my project", "my project", "my_dashboard"), - "my dashboard", - "it's a nice dashboard", - true, - mkExpectedPersesJSON(), - "project1dir/dashdir/dash2.yaml", - now, - now, - ), - dashboard( - dashboardID("my project", "my project", "my_dashboard"), - "my dashboard", - "it's a nice dashboard", - true, - mkExpectedPersesJSON(), - "project1dir/dashdir/dash3.yml", - now, - now, - ), - ), - AlertGroups: alertGroups( - alertGroupWithPath( - "my-group-name", - 30*time.Second, - &typesv1.Obj{}, - "project1dir/alertdir/alert1.yaml", - alertRules( - alertRule( - "HighErrors", - mustParseQuery(`filter severity_text == "error"`), - withFor(5*time.Minute), - withLabels(&typesv1.Obj{ - Kvs: []*typesv1.KV{ - typesv1.KeyVal("severity", typesv1.ValStr("critical")), - }, - }), - withAnnotations(&typesv1.Obj{Kvs: []*typesv1.KV{ - typesv1.KeyVal("description", typesv1.ValStr("stuff's happening with {{ $.labels.service }}")), - }}), - ), - ), - ), - alertGroupWithPath( - "my-another-name", - 30*time.Second, - &typesv1.Obj{}, - "project1dir/alertdir/alert2.yml", - alertRules( - alertRule( - "HighErrors", - mustParseQuery(`filter severity_text == "error"`), - withFor(5*time.Minute), - withLabels(&typesv1.Obj{Kvs: []*typesv1.KV{ - typesv1.KeyVal("severity", typesv1.ValStr("critical")), - }}), - withAnnotations(&typesv1.Obj{}), - ), - ), - ), - ), - } - got, err := d.GetProject(ctx, &projectv1.GetProjectRequest{Name: "my project"}) - require.NoError(t, err) - diff := cmp.Diff(want, got, cmpOpts...) - require.Empty(t, diff) - }, - }, - { - name: "get dashboard by id", - check: func(ctx context.Context, t *testing.T, d localstate.DB) { - want := dashboard( - dashboardID("my project", "my project", "my_dashboard"), - "my dashboard", - "it's a nice dashboard", - true, - mkExpectedPersesJSON(), - "project1dir/dashdir/dash1.json", - now, - now, - ) - res, err := d.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ - EnvironmentId: 0, - ProjectName: "my project", - Id: dashboardID("my project", "my project", "my_dashboard"), - }) - require.NoError(t, err) - got := res.Dashboard - diff := cmp.Diff(want, got, cmpOpts...) - require.Empty(t, diff) - }, - }, - { - name: "get dashboard by id, via project's dashboard list", - check: func(ctx context.Context, t *testing.T, d localstate.DB) { - gotProject, err := d.GetProject(ctx, &projectv1.GetProjectRequest{Name: "my project"}) - require.NoError(t, err) - // gotProject.Dashboards - i := slices.IndexFunc(gotProject.Dashboards, func(d *typesv1.Dashboard) bool { - return d.Spec.Name == "my dashboard" - }) - require.NotEqual(t, -1, i) - - db := gotProject.Dashboards[i] - - want := dashboard( - dashboardID("my project", "my project", "my_dashboard"), - "my dashboard", - "it's a nice dashboard", - true, - mkExpectedPersesJSON(), - "project1dir/dashdir/dash1.json", - now, - now, - ) - res, err := d.GetDashboard(ctx, &dashboardv1.GetDashboardRequest{ - EnvironmentId: 0, - ProjectName: gotProject.Project.Spec.Name, - Id: db.Meta.Id, - }) - require.NoError(t, err) - got := res.Dashboard - - diff := cmp.Diff(want, got, cmpOpts...) - require.Empty(t, diff) - }, - }, - }, - }, - { - name: "partial results with corrupt files", - fs: fstest.MapFS{ - "project1dir/dashdir/good1.json": &fstest.MapFile{Data: mkDashboardDataJSON()}, - "project1dir/dashdir/corrupt.yaml": &fstest.MapFile{Data: []byte("this is not valid yaml: [[[")}, - "project1dir/dashdir/good2.yaml": &fstest.MapFile{Data: mkDashboardDataYAML()}, - "project1dir/alertdir/good-alert.yaml": &fstest.MapFile{Data: mkAlertGroupDataBoth()}, - "project1dir/alertdir/corrupt-alert.yml": &fstest.MapFile{Data: []byte("invalid: {{{")}, - }, - cfg: &typesv1.ProjectsConfig{ - Projects: projectConfigs( - projectConfig("test-project", - localProjectPointer("project1dir", "dashdir", "alertdir", true), - ), - ), - }, - subtest: []subtest{ - { - name: "get project returns both valid and corrupt items", - check: func(ctx context.Context, t *testing.T, d localstate.DB) { - got, err := d.GetProject(ctx, &projectv1.GetProjectRequest{Name: "test-project"}) - require.NoError(t, err) - - require.Len(t, got.Dashboards, 3, "should return all dashboards including corrupt one") - require.Len(t, got.AlertGroups, 3, "should return all alert groups including corrupt one") - - var validDashboards int - var corruptDashboards int - for _, db := range got.Dashboards { - if len(db.Status.Errors) > 0 { - corruptDashboards++ - require.Empty(t, db.Spec.Name, "corrupt dashboard should have empty name") - } else { - validDashboards++ - require.NotEmpty(t, db.Spec.Name, "valid dashboard should have non-empty name") - } - } - require.Equal(t, 2, validDashboards, "should have 2 valid dashboards") - require.Equal(t, 1, corruptDashboards, "should have 1 corrupt dashboard") - - var validAlertGroups int - var corruptAlertGroups int - for _, ag := range got.AlertGroups { - if len(ag.Status.Errors) > 0 { - corruptAlertGroups++ - require.Empty(t, ag.Spec.Name, "corrupt alert group should have empty name") - } else { - validAlertGroups++ - require.NotEmpty(t, ag.Spec.Name, "valid alert group should have non-empty name") - } - } - require.Equal(t, 2, validAlertGroups, "should have 2 valid alert groups") - require.Equal(t, 1, corruptAlertGroups, "should have 1 corrupt alert group") - }, - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := t.Context() - alertState := localstate.NewMemory().AlertRuleStatusStorage() - cfg := &config.Config{CurrentConfig: &typesv1.LocalhostConfig{ - Runtime: &typesv1.RuntimeConfig{ - ExperimentalFeatures: &typesv1.RuntimeConfig_ExperimentalFeatures{ - Projects: tt.cfg, - }, - }, - }} - - fs := memfs.New() - for name, f := range tt.fs { - ff, err := fs.Create(name) - require.NoError(t, err) - _, err = ff.Write(f.Data) - require.NoError(t, err) - err = ff.Close() - - require.NoError(t, err) - - } - - db, err := internalWatch(ctx, fs, cfg, alertState, parseQuery, timeNow) - require.NoError(t, err) - for _, tt := range tt.subtest { - t.Run(tt.name, func(t *testing.T) { - tt.check(t.Context(), t, db) - }) - } - }) - } -} - -func TestDashboardIDIsURLSafe(t *testing.T) { - want := dashboardID("hello world", "i love potatoes", "my garden dashboards, potato focused") - got := url.QueryEscape(want) - require.Equal(t, want, got, "should not require escaping") -} - -func mustParseQuery(s string) *typesv1.Query { - q, err := parseQuery(s) - if err != nil { - panic(err) - } - return q -} - -func parseQuery(s string) (*typesv1.Query, error) { - return &typesv1.Query{Query: &typesv1.Statements{ - Statements: []*typesv1.Statement{ - {Stmt: &typesv1.Statement_Filter{ - Filter: &typesv1.FilterOperator{ - Expr: &typesv1.Expr{ - Expr: &typesv1.Expr_Identifier{ - Identifier: &typesv1.Identifier{Name: s}, - }, - }, - }, - }}, - }, - }}, nil -} - -const alertGroupYAML = `groups: - - name: my-group-name - interval: 30s # defaults to global interval - rules: - - alert: HighErrors - expr: filter severity_text == "error" - for: 5m - labels: - severity: critical - annotations: - description: "stuff's happening with {{ $.labels.service }}" - - - name: my-another-name - interval: 30s # defaults to global interval - rules: - - alert: HighErrors - expr: filter severity_text == "error" - for: 5m - labels: - severity: critical -` - -func projectConfigs(in ...*typesv1.ProjectsConfig_Project) []*typesv1.ProjectsConfig_Project { - return in -} - -func projectConfig(projectName string, ptr *typesv1.ProjectPointer) *typesv1.ProjectsConfig_Project { - return &typesv1.ProjectsConfig_Project{ - Name: projectName, - Pointer: ptr, - } -} - -func localProjectPointer(path, dashboard, alert string, readOnly bool) *typesv1.ProjectPointer { - return &typesv1.ProjectPointer{ - Scheme: &typesv1.ProjectPointer_Localhost{ - Localhost: &typesv1.ProjectPointer_LocalGit{ - Path: path, - DashboardDir: dashboard, - AlertDir: alert, - ReadOnly: readOnly, - }, - }, - } -} - -func remoteProjectPointer(remoteURL, ref, dashboard, alert string) *typesv1.ProjectPointer { - return &typesv1.ProjectPointer{ - Scheme: &typesv1.ProjectPointer_Remote{ - Remote: &typesv1.ProjectPointer_RemoteGit{ - RemoteUrl: remoteURL, - Ref: ref, - DashboardDir: dashboard, - - AlertDir: alert, - }, - }, - } -} - -func project( - name string, - ptr *typesv1.ProjectPointer, - createdAt, updatedAt time.Time, -) *typesv1.Project { - return &typesv1.Project{ - Meta: &typesv1.ProjectMeta{}, - Spec: &typesv1.ProjectSpec{ - Name: name, - Pointer: ptr, - }, - Status: &typesv1.ProjectStatus{ - CreatedAt: timestamppb.New(createdAt), - UpdatedAt: timestamppb.New(updatedAt), - }, - } -} - -func dashboards(in ...*typesv1.Dashboard) []*typesv1.Dashboard { - return in -} - -func dashboard( - id string, - name, desc string, isReadonly bool, - persesJSON []byte, - file string, - createdAt, updatedAt time.Time, -) *typesv1.Dashboard { - // Determine detection reason based on file extension - detectionReason := "No humanlog metadata or generation markers found" - if strings.HasSuffix(file, ".json") { - detectionReason = "JSON files are never managed by humanlog" - } - - return &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{ - Id: id, - }, - Spec: &typesv1.DashboardSpec{ - Name: name, - Description: desc, - IsReadonly: isReadonly, - PersesJson: persesJSON, - }, - Status: &typesv1.DashboardStatus{ - CreatedAt: timestamppb.New(createdAt), - UpdatedAt: timestamppb.New(updatedAt), - Origin: &typesv1.DashboardStatus_Generated{ - Generated: &typesv1.DashboardStatus_GeneratedDashboard{ - Path: file, - DetectionReason: detectionReason, - }, - }, - }, - } -} - -func alertGroups(in ...*typesv1.AlertGroup) []*typesv1.AlertGroup { - return in -} - -func alertGroup(name string, interval time.Duration, labels *typesv1.Obj, rules []*typesv1.AlertRuleSpec) *typesv1.AlertGroup { - return alertGroupWithPath(name, interval, labels, "", rules) -} - -func alertGroupWithPath(name string, interval time.Duration, labels *typesv1.Obj, path string, rules []*typesv1.AlertRuleSpec) *typesv1.AlertGroup { - // Wrap specs in NamedAlertRuleSpec and normalize empty annotations to nil - namedRules := make([]*typesv1.AlertGroupSpec_NamedAlertRuleSpec, len(rules)) - for i, spec := range rules { - // Normalize empty annotations to nil (matching parser behavior) - if spec.Annotations != nil && len(spec.Annotations.Kvs) == 0 { - spec.Annotations = nil - } - namedRules[i] = &typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - Id: spec.Name, - Spec: spec, - } - } - - // Normalize empty labels to nil (matching parse behavior) - if labels != nil && len(labels.Kvs) == 0 { - labels = nil - } - - return &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{ - Id: name, - }, - Spec: &typesv1.AlertGroupSpec{ - Name: name, - Interval: durationpb.New(interval), - IsReadonly: true, // Discovered groups are readonly - Labels: labels, - Rules: namedRules, - }, - Status: &typesv1.AlertGroupStatus{ - // Note: Rules statuses are NOT populated for GetProject list responses - // They are only hydrated in GetAlertGroup individual fetches - Origin: &typesv1.AlertGroupStatus_Discovered{ - Discovered: &typesv1.AlertGroupStatus_DiscoveredAlertGroup{ - Path: path, - }, - }, - }, - } -} - -func alertRules(in ...*typesv1.AlertRuleSpec) []*typesv1.AlertRuleSpec { - return in -} - -func alertRule(name string, expr *typesv1.Query, opts ...func(*typesv1.AlertRuleSpec)) *typesv1.AlertRuleSpec { - rule := &typesv1.AlertRuleSpec{ - Name: name, - Expr: expr, - } - for _, opt := range opts { - opt(rule) - } - return rule -} - -func withFor(d time.Duration) func(*typesv1.AlertRuleSpec) { - return func(r *typesv1.AlertRuleSpec) { - r.For = durationpb.New(d) - } -} - -func withLabels(labels *typesv1.Obj) func(*typesv1.AlertRuleSpec) { - return func(r *typesv1.AlertRuleSpec) { - r.Labels = labels - } -} - -func withAnnotations(annotations *typesv1.Obj) func(*typesv1.AlertRuleSpec) { - return func(r *typesv1.AlertRuleSpec) { - r.Annotations = annotations - } -} diff --git a/internal/localserver/alert_scheduler.go b/internal/localserver/alert_scheduler.go deleted file mode 100644 index df2e71d2..00000000 --- a/internal/localserver/alert_scheduler.go +++ /dev/null @@ -1,443 +0,0 @@ -package localserver - -import ( - "context" - "fmt" - "log/slog" - "sync" - "time" - - alertv1 "github.com/minitape/api/go/svc/alert/v1" - projectv1 "github.com/minitape/api/go/svc/project/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/localalert" - "github.com/humanlogio/humanlog/internal/pkg/iterapi" - "github.com/humanlogio/humanlog/pkg/localstorage" - "golang.org/x/sync/singleflight" -) - -// AlertScheduler manages per-alert-group goroutines that evaluate rules -// at their specified intervals, plus a reconciliation loop that discovers -// new/changed/deleted alert groups. -// -// Error handling philosophy: -// - System errors (corrupted DB, unrecoverable state) cause Start() to return error -// - User errors (bad alert config, temporary API failures) are logged but don't kill the service -// - Reconciliation is debounced via singleflight to handle concurrent triggers -type AlertScheduler struct { - ll *slog.Logger - state projectService - storage localstorage.Storage - timeNow func() time.Time - getReconcileTrigger func() <-chan time.Time - getEvalTrigger func(projectName, groupName string, interval time.Duration) <-chan time.Time - onStateTransition localalert.OnStateTransition - - // Hooks for observability and user feedback - onReconcileComplete func() - onReconcileError func(err error) - onEvaluationComplete func(projectName, groupName string) - onEvaluationError func(projectName, groupName string, err error, errorCount int) - onEvaluatorWillStart func(projectName, groupName string) - onEvaluatorStarted func(projectName, groupName string) - onEvaluatorStopped func(projectName, groupName string) - - reconcileSF singleflight.Group - - mu sync.Mutex - evaluators map[string]*alertGroupEvaluator // key: "projectName/groupName" - cancel context.CancelFunc - done chan struct{} -} - -type projectService interface { - ListProject(context.Context, *projectv1.ListProjectRequest) (*projectv1.ListProjectResponse, error) - GetProject(context.Context, *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) - ListAlertGroup(context.Context, *alertv1.ListAlertGroupRequest) (*alertv1.ListAlertGroupResponse, error) - GetAlertGroup(context.Context, *alertv1.GetAlertGroupRequest) (*alertv1.GetAlertGroupResponse, error) -} - -type alertGroupEvaluator struct { - projectName string - groupName string - interval time.Duration - - cancel context.CancelFunc - done chan struct{} -} - -type alertSchedulerOption func(*AlertScheduler) - -func withOnReconcileComplete(fn func()) alertSchedulerOption { - return func(s *AlertScheduler) { - s.onReconcileComplete = fn - } -} - -func withOnReconcileError(fn func(err error)) alertSchedulerOption { - return func(s *AlertScheduler) { - s.onReconcileError = fn - } -} - -func withOnEvaluationComplete(fn func(projectName, groupName string)) alertSchedulerOption { - return func(s *AlertScheduler) { - s.onEvaluationComplete = fn - } -} - -func withOnEvaluationError(fn func(projectName, groupName string, err error, errorCount int)) alertSchedulerOption { - return func(s *AlertScheduler) { - s.onEvaluationError = fn - } -} - -func withOnEvaluatorWillStart(fn func(projectName, groupName string)) alertSchedulerOption { - return func(s *AlertScheduler) { - s.onEvaluatorWillStart = fn - } -} - -func withOnEvaluatorStarted(fn func(projectName, groupName string)) alertSchedulerOption { - return func(s *AlertScheduler) { - s.onEvaluatorStarted = fn - } -} - -func withOnEvaluatorStopped(fn func(projectName, groupName string)) alertSchedulerOption { - return func(s *AlertScheduler) { - s.onEvaluatorStopped = fn - } -} - -// newAlertScheduler creates a scheduler with explicit trigger functions. -// This is the private constructor used by tests. -func newAlertScheduler( - ll *slog.Logger, - state projectService, - storage localstorage.Storage, - timeNow func() time.Time, - getReconcileTrigger func() <-chan time.Time, - getEvalTrigger func(projectName, groupName string, interval time.Duration) <-chan time.Time, - onStateTransition localalert.OnStateTransition, - opts ...alertSchedulerOption, -) *AlertScheduler { - s := &AlertScheduler{ - ll: ll, - state: state, - storage: storage, - timeNow: timeNow, - getReconcileTrigger: getReconcileTrigger, - getEvalTrigger: getEvalTrigger, - onStateTransition: onStateTransition, - evaluators: make(map[string]*alertGroupEvaluator), - done: make(chan struct{}), - } - for _, opt := range opts { - opt(s) - } - return s -} - -// NewAlertScheduler creates a scheduler that: -// - Reconciles alert groups every `reconcileEvery` (e.g., 60s) -// - Launches per-group goroutines that evaluate rules at AlertGroup.interval -func NewAlertScheduler( - ll *slog.Logger, - state projectService, - storage localstorage.Storage, - timeNow func() time.Time, - onStateTransition localalert.OnStateTransition, - reconcileEvery time.Duration, - opts ...alertSchedulerOption, -) *AlertScheduler { - return newAlertScheduler( - ll, - state, - storage, - timeNow, - func() <-chan time.Time { return time.After(reconcileEvery) }, - func(projectName, groupName string, interval time.Duration) <-chan time.Time { - return time.After(interval) - }, - onStateTransition, - opts..., - ) -} - -// Start begins the scheduler. Blocks until context is cancelled. -// Returns error only for system-level failures that should kill the background service. -// User configuration errors are logged but don't stop the scheduler. -func (s *AlertScheduler) Start(ctx context.Context, state projectService) error { - s.mu.Lock() - s.state = state - s.mu.Unlock() - ctx, cancel := context.WithCancel(ctx) - s.cancel = cancel - defer close(s.done) - - s.ll.InfoContext(ctx, "alert scheduler starting") - - // Initial reconciliation - if err := s.doReconcile(ctx); err != nil { - s.ll.ErrorContext(ctx, "initial reconciliation failed", slog.Any("err", err)) - } - - for { - reconcileTrigger := s.getReconcileTrigger() - select { - case <-ctx.Done(): - // Create detached context for shutdown: inherit values but not cancellation - shutdownCtx, shutdownCancel := context.WithTimeout(context.WithoutCancel(ctx), 5*time.Second) - defer shutdownCancel() - s.stopAll(shutdownCtx) - s.ll.InfoContext(ctx, "alert scheduler stopped") - return nil - case <-reconcileTrigger: - if err := s.doReconcile(ctx); err != nil { - s.ll.ErrorContext(ctx, "reconciliation failed", slog.Any("err", err)) - } - } - } -} - -// TriggerReconcile forces an immediate reconciliation (used when user calls SyncProject). -// Concurrent calls are deduplicated via singleflight. -func (s *AlertScheduler) TriggerReconcile(ctx context.Context) error { - return s.doReconcile(ctx) -} - -// doReconcile wraps reconcile with singleflight for deduplication -func (s *AlertScheduler) doReconcile(ctx context.Context) error { - _, err, _ := s.reconcileSF.Do("reconcile", func() (interface{}, error) { - err := s.reconcile(ctx) - if err != nil && s.onReconcileError != nil { - s.onReconcileError(err) - } - return nil, err - }) - return err -} - -func (s *AlertScheduler) reconcile(ctx context.Context) error { - s.ll.DebugContext(ctx, "reconciling alert groups") - - discovered := make(map[string]*alertGroupConfig) - - projectIter := s.iteratorForProject(ctx) - for projectIter.Next() { - project := projectIter.Current() - - alertGroupIter := s.iteratorForAlertGroup(ctx, project.Spec.Name) - for alertGroupIter.Next() { - alertGroup := alertGroupIter.Current() - key := alertGroupKey(project.Spec.Name, alertGroup.Spec.Name) - - interval := alertGroup.Spec.Interval.AsDuration() - if interval == 0 { - interval = 60 * time.Second // default - } - - discovered[key] = &alertGroupConfig{ - projectName: project.Spec.Name, - groupName: alertGroup.Spec.Name, - interval: interval, - } - } - if err := alertGroupIter.Err(); err != nil { - return fmt.Errorf("iterating alert groups for project %q: %v", project.Spec.Name, err) - } - } - if err := projectIter.Err(); err != nil { - return fmt.Errorf("iterating projects: %v", err) - } - - s.mu.Lock() - defer s.mu.Unlock() - - for key, eval := range s.evaluators { - cfg, exists := discovered[key] - if exists && cfg.interval == eval.interval { - continue - } - - ll := s.ll.With( - slog.String("project", eval.projectName), - slog.String("group", eval.groupName), - ) - - reason := "interval changed" - if !exists { - reason = "deleted" - } - - ll.InfoContext(ctx, "stopping alert group evaluator", slog.String("reason", reason)) - eval.cancel() - select { - case <-eval.done: - case <-ctx.Done(): - ll.WarnContext(ctx, "context cancelled while waiting for evaluator to stop") - } - delete(s.evaluators, key) - - if s.onEvaluatorStopped != nil { - s.onEvaluatorStopped(eval.projectName, eval.groupName) - } - } - - for key, cfg := range discovered { - if _, exists := s.evaluators[key]; exists { - continue - } - - ll := s.ll.With( - slog.String("project", cfg.projectName), - slog.String("group", cfg.groupName), - ) - - ll.InfoContext(ctx, "starting alert group evaluator", - slog.Duration("interval", cfg.interval), - ) - eval := s.startEvaluator(ctx, cfg) - s.evaluators[key] = eval - if s.onEvaluatorStarted != nil { - s.onEvaluatorStarted(cfg.projectName, cfg.groupName) - } - } - - if s.onReconcileComplete != nil { - s.onReconcileComplete() - } - - return nil -} - -type alertGroupConfig struct { - projectName string - groupName string - interval time.Duration -} - -func alertGroupKey(projectName, groupName string) string { - return projectName + "/" + groupName -} - -func (s *AlertScheduler) startEvaluator(parentCtx context.Context, cfg *alertGroupConfig) *alertGroupEvaluator { - ctx, cancel := context.WithCancel(parentCtx) - eval := &alertGroupEvaluator{ - projectName: cfg.projectName, - groupName: cfg.groupName, - interval: cfg.interval, - cancel: cancel, - done: make(chan struct{}), - } - - if s.onEvaluatorWillStart != nil { - s.onEvaluatorWillStart(cfg.projectName, cfg.groupName) - } - - go func() { - defer close(eval.done) - - ll := s.ll.With( - slog.String("project", eval.projectName), - slog.String("group", eval.groupName), - ) - - errorCount := 0 - for { - trigger := s.getEvalTrigger(eval.projectName, eval.groupName, eval.interval) - select { - case <-ctx.Done(): - return - case <-trigger: - err := s.evaluateGroup(ctx, eval) - - if err != nil { - errorCount++ - ll.ErrorContext(ctx, "failed to evaluate alert group", - slog.Any("err", err), - slog.Int("error_count", errorCount), - ) - - if s.onEvaluationError != nil { - s.onEvaluationError(eval.projectName, eval.groupName, err, errorCount) - } - } else { - errorCount = 0 - } - - if s.onEvaluationComplete != nil { - s.onEvaluationComplete(eval.projectName, eval.groupName) - } - } - } - }() - - return eval -} - -func (s *AlertScheduler) evaluateGroup(ctx context.Context, eval *alertGroupEvaluator) error { - projectResp, err := s.state.GetProject(ctx, &projectv1.GetProjectRequest{Name: eval.projectName}) - if err != nil { - return fmt.Errorf("getting project %q: %v", eval.projectName, err) - } - - alertGroupResp, err := s.state.GetAlertGroup(ctx, &alertv1.GetAlertGroupRequest{ - ProjectName: eval.projectName, - Name: eval.groupName, - }) - if err != nil { - return fmt.Errorf("getting alert group %q: %v", eval.groupName, err) - } - - evaluator := localalert.NewEvaluator(s.storage, s.timeNow) - return evaluator.EvaluateRules(ctx, projectResp.Project, alertGroupResp.AlertGroup, s.onStateTransition) -} - -func (s *AlertScheduler) stopAll(ctx context.Context) { - s.mu.Lock() - evals := make([]*alertGroupEvaluator, 0, len(s.evaluators)) - for _, eval := range s.evaluators { - evals = append(evals, eval) - eval.cancel() - } - s.evaluators = make(map[string]*alertGroupEvaluator) - s.mu.Unlock() - - for _, eval := range evals { - select { - case <-eval.done: - case <-ctx.Done(): - return - } - } -} - -func (s *AlertScheduler) iteratorForProject(ctx context.Context) *iterapi.Iter[*typesv1.Project] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*typesv1.Project, *typesv1.Cursor, error) { - out, err := s.state.ListProject(ctx, &projectv1.ListProjectRequest{Cursor: cursor, Limit: limit}) - if err != nil { - return nil, nil, err - } - var items []*typesv1.Project - for _, el := range out.Items { - items = append(items, el.Project) - } - return items, out.Next, nil - }) -} - -func (s *AlertScheduler) iteratorForAlertGroup(ctx context.Context, projectName string) *iterapi.Iter[*typesv1.AlertGroup] { - return iterapi.New(ctx, 100, func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]*typesv1.AlertGroup, *typesv1.Cursor, error) { - out, err := s.state.ListAlertGroup(ctx, &alertv1.ListAlertGroupRequest{ProjectName: projectName, Cursor: cursor, Limit: limit}) - if err != nil { - return nil, nil, err - } - var items []*typesv1.AlertGroup - for _, el := range out.Items { - items = append(items, el.AlertGroup) - } - return items, out.Next, nil - }) -} diff --git a/internal/localserver/alert_scheduler_test.go b/internal/localserver/alert_scheduler_test.go deleted file mode 100644 index 4059615f..00000000 --- a/internal/localserver/alert_scheduler_test.go +++ /dev/null @@ -1,798 +0,0 @@ -package localserver - -import ( - "context" - "fmt" - "log/slog" - "os" - "strings" - "sync" - "testing" - "time" - - alertv1 "github.com/minitape/api/go/svc/alert/v1" - projectv1 "github.com/minitape/api/go/svc/project/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/pkg/localstorage" - "github.com/humanlogio/humanlog/pkg/sink" - otlplogssvcpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" - otlpmetricssvcpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - otlptracesvcpb "go.opentelemetry.io/proto/otlp/collector/trace/v1" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" -) - -type schedulerState struct { - projects []*typesv1.Project - alertGroups map[string][]*typesv1.AlertGroup -} - -type tick struct { - at time.Duration - reconcile bool - evals []string // "project/group" - addGroups map[string][]*typesv1.AlertGroup - removeGroups map[string][]string - updateGroups map[string][]*typesv1.AlertGroup -} - -func TestAlertScheduler(t *testing.T) { - start := time.Date(2025, 10, 19, 10, 0, 0, 0, time.UTC) - - tests := []struct { - name string - init schedulerState - ticks []tick - check func(t *testing.T, events []event) - }{ - { - name: "single group evaluates at interval", - init: schedulerState{ - projects: []*typesv1.Project{mkproject("proj1")}, - alertGroups: map[string][]*typesv1.AlertGroup{"proj1": {mkalertgroup("group1", setInterval(60 * time.Second))}}, - }, - ticks: []tick{ - {at: 60 * time.Second, evals: []string{"proj1/group1"}}, - {at: 120 * time.Second, evals: []string{"proj1/group1"}}, - }, - check: func(t *testing.T, events []event) { - require.Equal(t, 2, countEvals(events, "proj1", "group1")) - }, - }, - { - name: "multiple groups evaluate at different intervals", - init: schedulerState{ - projects: []*typesv1.Project{mkproject("proj1")}, - alertGroups: map[string][]*typesv1.AlertGroup{"proj1": { - mkalertgroup("group1", setInterval(60*time.Second)), - mkalertgroup("group2", setInterval(30*time.Second)), - }}, - }, - ticks: []tick{ - {at: 30 * time.Second, evals: []string{"proj1/group2"}}, - {at: 60 * time.Second, evals: []string{"proj1/group1", "proj1/group2"}}, - {at: 90 * time.Second, evals: []string{"proj1/group2"}}, - }, - check: func(t *testing.T, events []event) { - require.Equal(t, 1, countEvals(events, "proj1", "group1")) - require.Equal(t, 3, countEvals(events, "proj1", "group2")) - }, - }, - { - name: "reconcile discovers new group", - init: schedulerState{ - projects: []*typesv1.Project{mkproject("proj1")}, - alertGroups: map[string][]*typesv1.AlertGroup{"proj1": {mkalertgroup("group1", setInterval(60 * time.Second))}}, - }, - ticks: []tick{ - {at: 60 * time.Second, evals: []string{"proj1/group1"}}, - {at: 60 * time.Second, reconcile: true, addGroups: map[string][]*typesv1.AlertGroup{ - "proj1": {mkalertgroup("group2", setInterval(30 * time.Second))}, - }}, - {at: 90 * time.Second, evals: []string{"proj1/group2"}}, - {at: 120 * time.Second, evals: []string{"proj1/group1", "proj1/group2"}}, - }, - check: func(t *testing.T, events []event) { - require.Equal(t, 2, countEvals(events, "proj1", "group1")) - require.Equal(t, 2, countEvals(events, "proj1", "group2")) - }, - }, - { - name: "reconcile removes deleted group", - init: schedulerState{ - projects: []*typesv1.Project{mkproject("proj1")}, - alertGroups: map[string][]*typesv1.AlertGroup{"proj1": { - mkalertgroup("group1", setInterval(30*time.Second)), - mkalertgroup("group2", setInterval(30*time.Second)), - }}, - }, - ticks: []tick{ - {at: 30 * time.Second, evals: []string{"proj1/group1", "proj1/group2"}}, - {at: 30 * time.Second, reconcile: true, removeGroups: map[string][]string{"proj1": {"group2"}}}, - {at: 60 * time.Second, evals: []string{"proj1/group1"}}, - }, - check: func(t *testing.T, events []event) { - require.Equal(t, 2, countEvals(events, "proj1", "group1")) - require.Equal(t, 1, countEvals(events, "proj1", "group2")) - require.True(t, hasEvent(events, "evaluator-stopped", "proj1", "group2")) - }, - }, - { - name: "reconcile detects interval change and restarts evaluator", - init: schedulerState{ - projects: []*typesv1.Project{mkproject("proj1")}, - alertGroups: map[string][]*typesv1.AlertGroup{"proj1": {mkalertgroup("group1", setInterval(60 * time.Second))}}, - }, - ticks: []tick{ - {at: 60 * time.Second, evals: []string{"proj1/group1"}}, - {at: 60 * time.Second, reconcile: true, updateGroups: map[string][]*typesv1.AlertGroup{ - "proj1": {mkalertgroup("group1", setInterval(30 * time.Second))}, - }}, - {at: 90 * time.Second, evals: []string{"proj1/group1"}}, - {at: 120 * time.Second, evals: []string{"proj1/group1"}}, - }, - check: func(t *testing.T, events []event) { - require.Equal(t, 3, countEvals(events, "proj1", "group1")) - require.True(t, hasEvent(events, "evaluator-stopped", "proj1", "group1")) - }, - }, - { - name: "multiple projects with alert groups", - init: schedulerState{ - projects: []*typesv1.Project{mkproject("proj1"), mkproject("proj2")}, - alertGroups: map[string][]*typesv1.AlertGroup{ - "proj1": {mkalertgroup("group1", setInterval(30 * time.Second))}, - "proj2": {mkalertgroup("group1", setInterval(30 * time.Second))}, - }, - }, - ticks: []tick{ - {at: 30 * time.Second, evals: []string{"proj1/group1", "proj2/group1"}}, - {at: 60 * time.Second, evals: []string{"proj1/group1", "proj2/group1"}}, - }, - check: func(t *testing.T, events []event) { - require.Equal(t, 2, countEvals(events, "proj1", "group1")) - require.Equal(t, 2, countEvals(events, "proj2", "group1")) - }, - }, - { - name: "default interval used when not specified", - init: schedulerState{ - projects: []*typesv1.Project{mkproject("proj1")}, - alertGroups: map[string][]*typesv1.AlertGroup{"proj1": {mkalertgroup("group1")}}, - }, - ticks: []tick{ - {at: 60 * time.Second, evals: []string{"proj1/group1"}}, - }, - check: func(t *testing.T, events []event) { - require.Equal(t, 1, countEvals(events, "proj1", "group1")) - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - var mu sync.Mutex - now := start - timeNow := func() time.Time { - mu.Lock() - defer mu.Unlock() - return now - } - setTime := func(t time.Time) { - mu.Lock() - defer mu.Unlock() - now = t - } - - reconcileCh := make(chan time.Time, 10) - evalChans := make(map[string]chan time.Time) - - var events []event - var reconcileDone, evalDone sync.WaitGroup - - recordEvent := func(typ, project, group string, t time.Time) { - mu.Lock() - defer mu.Unlock() - events = append(events, event{typ: typ, project: project, group: group, time: t}) - } - - onReconcileComplete := func() { - recordEvent("reconcile-complete", "", "", timeNow()) - reconcileDone.Done() - } - - onEvaluationComplete := func(project, group string) { - recordEvent("eval-complete", project, group, timeNow()) - evalDone.Done() - } - - onEvaluatorWillStart := func(project, group string) { - // Create channel immediately when evaluator will start - key := alertGroupKey(project, group) - mu.Lock() - evalChans[key] = make(chan time.Time, 10) - mu.Unlock() - } - - onEvaluatorStarted := func(project, group string) { - recordEvent("evaluator-started", project, group, timeNow()) - } - - onEvaluatorStopped := func(project, group string) { - recordEvent("evaluator-stopped", project, group, timeNow()) - } - - getReconcileTrigger := func() <-chan time.Time { - return reconcileCh - } - - getEvalTrigger := func(project, group string, interval time.Duration) <-chan time.Time { - key := alertGroupKey(project, group) - mu.Lock() - defer mu.Unlock() - return evalChans[key] - } - - state := newTestState(tt.init.projects, tt.init.alertGroups) - storage := &mockStorage{} - - reconcileDone.Add(1) // initial reconcile - - scheduler := newAlertScheduler( - slog.Default(), - state.asProjectService(), - storage, - timeNow, - getReconcileTrigger, - getEvalTrigger, - func(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error { return nil }, - withOnReconcileComplete(onReconcileComplete), - withOnEvaluationComplete(onEvaluationComplete), - withOnEvaluatorWillStart(onEvaluatorWillStart), - withOnEvaluatorStarted(onEvaluatorStarted), - withOnEvaluatorStopped(onEvaluatorStopped), - ) - - go scheduler.Start(ctx, state.asProjectService()) - - // Wait for initial reconcile - t.Log("Waiting for initial reconcile") - reconcileDone.Wait() - t.Log("Initial reconcile done") - - // Process ticks - for _, tick := range tt.ticks { - setTime(start.Add(tick.at)) - - if tick.addGroups != nil { - state.add(tick.addGroups) - } - if tick.removeGroups != nil { - state.remove(tick.removeGroups) - } - if tick.updateGroups != nil { - state.update(tick.updateGroups) - } - - if tick.reconcile { - reconcileDone.Add(1) - reconcileCh <- timeNow() - reconcileDone.Wait() - } - - if len(tick.evals) > 0 { - evalDone.Add(len(tick.evals)) - for _, key := range tick.evals { - parts := strings.Split(key, "/") - mu.Lock() - ch := evalChans[alertGroupKey(parts[0], parts[1])] - mu.Unlock() - ch <- timeNow() - } - evalDone.Wait() - } - } - - cancel() - tt.check(t, events) - }) - } -} - -// ============================================================================ -// Helpers -// ============================================================================ - -type event struct { - typ string - project string - group string - time time.Time -} - -func countEvals(events []event, project, group string) int { - count := 0 - for _, e := range events { - if e.typ == "eval-complete" && e.project == project && e.group == group { - count++ - } - } - return count -} - -func hasEvent(events []event, typ, project, group string) bool { - for _, e := range events { - if e.typ == typ && e.project == project && e.group == group { - return true - } - } - return false -} - -func mkproject(name string) *typesv1.Project { - return &typesv1.Project{Spec: &typesv1.ProjectSpec{Name: name}} -} - -func mkalertgroup(name string, opts ...func(*typesv1.AlertGroupSpec)) *typesv1.AlertGroup { - spec := &typesv1.AlertGroupSpec{Name: name, Rules: []*typesv1.AlertGroupSpec_NamedAlertRuleSpec{}} - for _, opt := range opts { - opt(spec) - } - return &typesv1.AlertGroup{Spec: spec} -} - -func setInterval(d time.Duration) func(*typesv1.AlertGroupSpec) { - return func(spec *typesv1.AlertGroupSpec) { - spec.Interval = durationpb.New(d) - } -} - -type alertStorage interface { - AlertGetOrCreate(context.Context, string, string, string, func() *typesv1.AlertRuleStatus) (*typesv1.AlertRuleStatus, error) - AlertUpdateState(context.Context, string, string, string, *typesv1.AlertRuleStatus) error - AlertDeleteStateNotInList(context.Context, string, string, []string) error -} - -type mockProjectService struct { - listProject func(context.Context, *projectv1.ListProjectRequest) (*projectv1.ListProjectResponse, error) - getProject func(context.Context, *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) - listAlertGroup func(context.Context, *alertv1.ListAlertGroupRequest) (*alertv1.ListAlertGroupResponse, error) - getAlertGroup func(context.Context, *alertv1.GetAlertGroupRequest) (*alertv1.GetAlertGroupResponse, error) - - projects []*typesv1.Project - alertGroups map[string][]*typesv1.AlertGroup - storage alertStorage - mu sync.Mutex -} - -func (m *mockProjectService) ListProject(ctx context.Context, req *projectv1.ListProjectRequest) (*projectv1.ListProjectResponse, error) { - return m.listProject(ctx, req) -} -func (m *mockProjectService) GetProject(ctx context.Context, req *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) { - if m.getProject != nil { - return m.getProject(ctx, req) - } - - for _, p := range m.projects { - if p.Spec.Name == req.Name { - return &projectv1.GetProjectResponse{Project: p}, nil - } - } - - return nil, fmt.Errorf("project %q not found", req.Name) -} -func (m *mockProjectService) ListAlertGroup(ctx context.Context, req *alertv1.ListAlertGroupRequest) (*alertv1.ListAlertGroupResponse, error) { - if m.listAlertGroup != nil { - return m.listAlertGroup(ctx, req) - } - - groups, ok := m.alertGroups[req.ProjectName] - if !ok { - return &alertv1.ListAlertGroupResponse{}, nil - } - - var items []*alertv1.ListAlertGroupResponse_ListItem - for _, g := range groups { - items = append(items, &alertv1.ListAlertGroupResponse_ListItem{AlertGroup: g}) - } - - return &alertv1.ListAlertGroupResponse{Items: items}, nil -} -func (m *mockProjectService) GetAlertGroup(ctx context.Context, req *alertv1.GetAlertGroupRequest) (*alertv1.GetAlertGroupResponse, error) { - if m.getAlertGroup != nil { - return m.getAlertGroup(ctx, req) - } - - groups, ok := m.alertGroups[req.ProjectName] - if !ok { - return nil, fmt.Errorf("project %q not found", req.ProjectName) - } - - for _, ag := range groups { - if ag.Spec.Name == req.Name { - // Populate status from storage - if ag.Status == nil { - ag.Status = &typesv1.AlertGroupStatus{} - } - if ag.Status.Rules == nil { - ag.Status.Rules = make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, 0, len(ag.Spec.Rules)) - } - - // Query status for each rule from storage - if m.storage != nil { - for _, namedRule := range ag.Spec.Rules { - status, err := m.storage.AlertGetOrCreate(ctx, req.ProjectName, req.Name, namedRule.Id, func() *typesv1.AlertRuleStatus { - return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{}} - }) - if err != nil { - return nil, fmt.Errorf("getting alert status for rule %q: %w", namedRule.Id, err) - } - - // Check if status already exists in array and merge - found := false - for _, namedStatus := range ag.Status.Rules { - if namedStatus.Id == namedRule.Id { - namedStatus.Status = status - found = true - break - } - } - if !found { - ag.Status.Rules = append(ag.Status.Rules, &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: namedRule.Id, - Status: status, - }) - } - } - } - - return &alertv1.GetAlertGroupResponse{AlertGroup: ag}, nil - } - } - - return nil, fmt.Errorf("alert group %q not found in project %q", req.Name, req.ProjectName) -} - -type mockStorage struct { - mu sync.Mutex - alerts map[string]map[string]map[string]*typesv1.AlertRuleStatus // [projectName][groupName][ruleID] -} - -func (m *mockStorage) Query(context.Context, *typesv1.Query, *typesv1.Cursor, int, ...localstorage.QueryOption) (*typesv1.Data, *typesv1.Cursor, *typesv1.QueryMetrics, error) { - return &typesv1.Data{Shape: &typesv1.Data_FreeForm{FreeForm: &typesv1.Table{Type: &typesv1.TableType{}, Rows: []*typesv1.Arr{}}}}, nil, nil, nil -} -func (m *mockStorage) AlertGetOrCreate(ctx context.Context, projectName, groupName, ruleID string, create func() *typesv1.AlertRuleStatus) (*typesv1.AlertRuleStatus, error) { - m.mu.Lock() - defer m.mu.Unlock() - - if m.alerts == nil { - m.alerts = make(map[string]map[string]map[string]*typesv1.AlertRuleStatus) - } - if m.alerts[projectName] == nil { - m.alerts[projectName] = make(map[string]map[string]*typesv1.AlertRuleStatus) - } - if m.alerts[projectName][groupName] == nil { - m.alerts[projectName][groupName] = make(map[string]*typesv1.AlertRuleStatus) - } - - if status, ok := m.alerts[projectName][groupName][ruleID]; ok { - return status, nil - } - - status := create() - m.alerts[projectName][groupName][ruleID] = status - return status, nil -} -func (m *mockStorage) AlertUpdateState(ctx context.Context, projectName, groupName, ruleID string, status *typesv1.AlertRuleStatus) error { - m.mu.Lock() - defer m.mu.Unlock() - - if m.alerts == nil { - m.alerts = make(map[string]map[string]map[string]*typesv1.AlertRuleStatus) - } - if m.alerts[projectName] == nil { - m.alerts[projectName] = make(map[string]map[string]*typesv1.AlertRuleStatus) - } - if m.alerts[projectName][groupName] == nil { - m.alerts[projectName][groupName] = make(map[string]*typesv1.AlertRuleStatus) - } - - m.alerts[projectName][groupName][ruleID] = status - return nil -} -func (m *mockStorage) AlertDeleteStateNotInList(ctx context.Context, projectName, groupName string, keeplist []string) error { - m.mu.Lock() - defer m.mu.Unlock() - - if m.alerts == nil || m.alerts[projectName] == nil || m.alerts[projectName][groupName] == nil { - return nil - } - - keep := make(map[string]bool) - for _, ruleID := range keeplist { - keep[ruleID] = true - } - - for ruleID := range m.alerts[projectName][groupName] { - if !keep[ruleID] { - delete(m.alerts[projectName][groupName], ruleID) - } - } - - return nil -} -func (m *mockStorage) ExportLogs(context.Context, *otlplogssvcpb.ExportLogsServiceRequest) (*otlplogssvcpb.ExportLogsServiceResponse, error) { - return &otlplogssvcpb.ExportLogsServiceResponse{}, nil -} -func (m *mockStorage) ExportTraces(context.Context, *otlptracesvcpb.ExportTraceServiceRequest) (*otlptracesvcpb.ExportTraceServiceResponse, error) { - return &otlptracesvcpb.ExportTraceServiceResponse{}, nil -} -func (m *mockStorage) ExportMetrics(context.Context, *otlpmetricssvcpb.ExportMetricsServiceRequest) (*otlpmetricssvcpb.ExportMetricsServiceResponse, error) { - return &otlpmetricssvcpb.ExportMetricsServiceResponse{}, nil -} -func (m *mockStorage) SinkFor(context.Context, *typesv1.Resource, *typesv1.Scope) (sink.Sink, error) { return nil, nil } -func (m *mockStorage) ReportMetrics(context.Context, localstorage.MetricsReporterFunc) error { return nil } -func (m *mockStorage) Format(context.Context, *typesv1.Query) (string, error) { return "", nil } -func (m *mockStorage) Parse(context.Context, string) (*typesv1.Query, error) { return nil, nil } -func (m *mockStorage) ResolveQueryType(context.Context, *typesv1.Query) (*typesv1.DataStreamType, error) { - return nil, nil -} -func (m *mockStorage) ListSymbols(context.Context, *typesv1.Query, *typesv1.Cursor, int) ([]*typesv1.Symbol, *typesv1.Cursor, error) { - return nil, nil, nil -} -func (m *mockStorage) Stream(context.Context, *typesv1.Query, func(context.Context, *typesv1.Data) (bool, error), *localstorage.StreamOption) error { - return nil -} -func (m *mockStorage) GetTraceByID(context.Context, *typesv1.TraceID) (*typesv1.Trace, error) { return nil, nil } -func (m *mockStorage) GetTraceBySpanID(context.Context, *typesv1.SpanID) (*typesv1.Trace, error) { return nil, nil } -func (m *mockStorage) GetSpanByID(context.Context, *typesv1.SpanID) (*typesv1.Span, error) { return nil, nil } -func (m *mockStorage) Close() error { return nil } - -type testState struct { - mu sync.Mutex - projects []*typesv1.Project - alertGroups map[string][]*typesv1.AlertGroup -} - -func newTestState(projects []*typesv1.Project, alertGroups map[string][]*typesv1.AlertGroup) *testState { - return &testState{projects: projects, alertGroups: alertGroups} -} - -func (s *testState) add(groups map[string][]*typesv1.AlertGroup) { - s.mu.Lock() - defer s.mu.Unlock() - for projectName, newGroups := range groups { - s.alertGroups[projectName] = append(s.alertGroups[projectName], newGroups...) - } -} - -func (s *testState) remove(groups map[string][]string) { - s.mu.Lock() - defer s.mu.Unlock() - for projectName, groupNames := range groups { - existing := s.alertGroups[projectName] - var filtered []*typesv1.AlertGroup - for _, g := range existing { - keep := true - for _, name := range groupNames { - if g.Spec.Name == name { - keep = false - break - } - } - if keep { - filtered = append(filtered, g) - } - } - s.alertGroups[projectName] = filtered - } -} - -func (s *testState) update(groups map[string][]*typesv1.AlertGroup) { - s.mu.Lock() - defer s.mu.Unlock() - for projectName, updatedGroups := range groups { - existing := s.alertGroups[projectName] - for i, g := range existing { - for _, updated := range updatedGroups { - if g.Spec.Name == updated.Spec.Name { - existing[i] = updated - } - } - } - } -} - -func (s *testState) asProjectService() *mockProjectService { - return s.asProjectServiceWithStorage(nil) -} - -func (s *testState) asProjectServiceWithStorage(storage alertStorage) *mockProjectService { - return &mockProjectService{ - listProject: func(ctx context.Context, req *projectv1.ListProjectRequest) (*projectv1.ListProjectResponse, error) { - s.mu.Lock() - defer s.mu.Unlock() - var items []*projectv1.ListProjectResponse_ListItem - for _, p := range s.projects { - items = append(items, &projectv1.ListProjectResponse_ListItem{Project: p}) - } - return &projectv1.ListProjectResponse{Items: items}, nil - }, - getProject: func(ctx context.Context, req *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) { - s.mu.Lock() - defer s.mu.Unlock() - for _, p := range s.projects { - if p.Spec.Name == req.Name { - return &projectv1.GetProjectResponse{Project: p}, nil - } - } - return nil, nil - }, - listAlertGroup: func(ctx context.Context, req *alertv1.ListAlertGroupRequest) (*alertv1.ListAlertGroupResponse, error) { - s.mu.Lock() - defer s.mu.Unlock() - groups := s.alertGroups[req.ProjectName] - var items []*alertv1.ListAlertGroupResponse_ListItem - for _, g := range groups { - items = append(items, &alertv1.ListAlertGroupResponse_ListItem{AlertGroup: g}) - } - return &alertv1.ListAlertGroupResponse{Items: items}, nil - }, - getAlertGroup: func(ctx context.Context, req *alertv1.GetAlertGroupRequest) (*alertv1.GetAlertGroupResponse, error) { - s.mu.Lock() - defer s.mu.Unlock() - groups := s.alertGroups[req.ProjectName] - for _, g := range groups { - if g.Spec.Name == req.Name { - return &alertv1.GetAlertGroupResponse{AlertGroup: g}, nil - } - } - return nil, nil - }, - storage: storage, - projects: s.projects, - alertGroups: s.alertGroups, - } -} - -// TestAlertSchedulerIntegration tests the full path from evaluation to status injection -func TestAlertSchedulerIntegration(t *testing.T) { - now := time.Date(2025, 10, 20, 10, 15, 30, 123456789, time.UTC) - ctx := context.Background() - - // Create alert group with a real rule - group := &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{Id: "test-group"}, - Spec: &typesv1.AlertGroupSpec{ - Name: "test-group", - Interval: durationpb.New(60 * time.Second), - Rules: []*typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - { - Id: "cpu_high", - Spec: &typesv1.AlertRuleSpec{ - Name: "cpu_high", - Expr: &typesv1.Query{}, - }, - }, - }, - }, - Status: &typesv1.AlertGroupStatus{}, - } - - project := &typesv1.Project{ - Spec: &typesv1.ProjectSpec{Name: "test-proj"}, - } - - // Create mock storage that returns test data with metrics - storage := &mockStorageWithMetrics{ - queryMetrics: &typesv1.QueryMetrics{ - RowsScanned: 1000, - RowsReturned: 5, - TotalLatency: durationpb.New(50 * time.Millisecond), - }, - } - - // Create mock state with runtime status support - state := &mockProjectService{ - projects: []*typesv1.Project{project}, - alertGroups: map[string][]*typesv1.AlertGroup{"test-proj": {group}}, - storage: storage, - } - - // Create scheduler - scheduler := newAlertScheduler( - slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError})), - state, - storage, - func() time.Time { return now }, - func() <-chan time.Time { return nil }, - func(projectName, groupName string, interval time.Duration) <-chan time.Time { - ch := make(chan time.Time, 1) - return ch - }, - func(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error { return nil }, - ) - - // Create evaluator and register it - eval := &alertGroupEvaluator{ - projectName: "test-proj", - groupName: "test-group", - } - scheduler.mu.Lock() - scheduler.evaluators[alertGroupKey("test-proj", "test-group")] = eval - scheduler.mu.Unlock() - - // Manually trigger evaluation (this will call UpdateAlertRuleRuntimeStatus on state) - err := scheduler.evaluateGroup(ctx, eval) - require.NoError(t, err, "evaluateGroup should succeed") - - // Now fetch the alert group via GetAlertGroup - this should return the runtime status - resp, err := state.GetAlertGroup(ctx, &alertv1.GetAlertGroupRequest{ - ProjectName: "test-proj", - Name: "test-group", - }) - require.NoError(t, err, "GetAlertGroup should succeed") - require.NotNil(t, resp, "response should not be nil") - require.NotNil(t, resp.AlertGroup, "alert group should not be nil") - - // Verify runtime status was injected - require.NotNil(t, resp.AlertGroup.Status, "status should be populated") - require.NotEmpty(t, resp.AlertGroup.Status.Rules, "status should have rules") - - // Find our rule status - var ruleStatus *typesv1.AlertRuleStatus - for _, namedStatus := range resp.AlertGroup.Status.Rules { - if namedStatus.Id == "cpu_high" { - ruleStatus = namedStatus.Status - break - } - } - require.NotNil(t, ruleStatus, "cpu_high rule should have status") - - // Verify the injected runtime metrics - require.NotNil(t, ruleStatus.LastEvaluatedAt, "should have evaluation timestamp") - assert.Equal(t, now, ruleStatus.LastEvaluatedAt.AsTime(), "evaluation timestamp should match") - - require.NotNil(t, ruleStatus.LastEvaluationMetrics, "should have evaluation metrics") - assert.Equal(t, int64(1000), ruleStatus.LastEvaluationMetrics.RowsScanned, "rows scanned should be injected") - assert.Equal(t, int64(5), ruleStatus.LastEvaluationMetrics.RowsReturned, "rows returned should be injected") - assert.Equal(t, 50*time.Millisecond, ruleStatus.LastEvaluationMetrics.TotalLatency.AsDuration(), "latency should be injected") - - assert.Nil(t, ruleStatus.Error, "should not have error") -} - -// mockStorageWithMetrics returns predefined metrics -type mockStorageWithMetrics struct { - mockStorage - queryMetrics *typesv1.QueryMetrics -} - -func (m *mockStorageWithMetrics) Query(ctx context.Context, q *typesv1.Query, cursor *typesv1.Cursor, limit int, opts ...localstorage.QueryOption) (*typesv1.Data, *typesv1.Cursor, *typesv1.QueryMetrics, error) { - // Return empty table (no rows firing) - data := &typesv1.Data{ - Shape: &typesv1.Data_FreeForm{ - FreeForm: &typesv1.Table{ - Type: &typesv1.TableType{ - Columns: []*typesv1.TableType_Column{ - { - Name: "firing", - Type: &typesv1.VarType{Type: &typesv1.VarType_Scalar{Scalar: typesv1.ScalarType_bool}}, - }, - }, - }, - Rows: []*typesv1.Arr{ - { - Items: []*typesv1.Val{ - {Kind: &typesv1.Val_Bool{Bool: false}}, - }, - }, - }, - }, - }, - } - return data, nil, m.queryMetrics, nil -} diff --git a/internal/localserver/alert_status_test.go b/internal/localserver/alert_status_test.go deleted file mode 100644 index cf3cfbf9..00000000 --- a/internal/localserver/alert_status_test.go +++ /dev/null @@ -1,264 +0,0 @@ -package localserver - -import ( - "context" - "log/slog" - "os" - "testing" - "time" - - alertv1 "github.com/minitape/api/go/svc/alert/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/durationpb" - "google.golang.org/protobuf/types/known/timestamppb" -) - -type ruleStatusExpectation struct { - hasEvaluated bool - rowsScanned int64 - rowsReturned int64 - latencyMs int64 - hasError bool - errorContains string -} - -func TestAlertGroupStatusUserView(t *testing.T) { - start := time.Date(2025, 10, 20, 14, 37, 42, 123456789, time.UTC) - - tests := []struct { - name string - alertGroup *typesv1.AlertGroup - simulate func(ctx context.Context, t *testing.T, s *AlertScheduler, storage *mockStorage, now time.Time) - wantStatus map[string]ruleStatusExpectation - wantGroupErrors []string - }{ - { - name: "user sees query metrics after successful evaluation", - alertGroup: mkalertgroup("group1", - withAlertRule("cpu_high", "cpu > 80"), - ), - simulate: func(ctx context.Context, t *testing.T, s *AlertScheduler, storage *mockStorage, now time.Time) { - triggerEvaluation(ctx, t, s, storage, "proj1", "group1", now, map[string]evaluationOutcome{ - "cpu_high": { - metrics: &typesv1.QueryMetrics{ - RowsScanned: 1000, - RowsReturned: 5, - TotalLatency: durationpb.New(50 * time.Millisecond), - }, - }, - }) - }, - wantStatus: map[string]ruleStatusExpectation{ - "cpu_high": { - hasEvaluated: true, - rowsScanned: 1000, - rowsReturned: 5, - latencyMs: 50, - hasError: false, - }, - }, - }, - { - name: "user sees error when query fails", - alertGroup: mkalertgroup("group1", - withAlertRule("bad_query", "invalid syntax"), - ), - simulate: func(ctx context.Context, t *testing.T, s *AlertScheduler, storage *mockStorage, now time.Time) { - triggerEvaluation(ctx, t, s, storage, "proj1", "group1", now, map[string]evaluationOutcome{ - "bad_query": { - error: "syntax error: unexpected token", - }, - }) - }, - wantStatus: map[string]ruleStatusExpectation{ - "bad_query": { - hasEvaluated: true, - hasError: true, - errorContains: "syntax error", - }, - }, - }, - { - name: "user sees mixed success and failure across rules", - alertGroup: mkalertgroup("group1", - withAlertRule("rule1", "query1"), - withAlertRule("rule2", "query2"), - withAlertRule("rule3", "query3"), - ), - simulate: func(ctx context.Context, t *testing.T, s *AlertScheduler, storage *mockStorage, now time.Time) { - triggerEvaluation(ctx, t, s, storage, "proj1", "group1", now, map[string]evaluationOutcome{ - "rule1": { - metrics: &typesv1.QueryMetrics{RowsScanned: 100}, - }, - "rule2": { - error: "timeout", - }, - "rule3": { - metrics: &typesv1.QueryMetrics{RowsScanned: 50000}, - }, - }) - }, - wantStatus: map[string]ruleStatusExpectation{ - "rule1": {hasEvaluated: true, rowsScanned: 100, hasError: false}, - "rule2": {hasEvaluated: true, hasError: true, errorContains: "timeout"}, - "rule3": {hasEvaluated: true, rowsScanned: 50000, hasError: false}, - }, - }, - { - name: "user sees nothing before first evaluation", - alertGroup: mkalertgroup("group1", - withAlertRule("rule1", "query1"), - ), - simulate: func(ctx context.Context, t *testing.T, s *AlertScheduler, storage *mockStorage, now time.Time) { - // Don't trigger any evaluation - }, - wantStatus: map[string]ruleStatusExpectation{ - "rule1": {hasEvaluated: false}, - }, - }, - { - name: "group-level errors appear separately", - alertGroup: mkalertgroup("group1", - withAlertRule("rule1", "query1"), - ), - simulate: func(ctx context.Context, t *testing.T, s *AlertScheduler, storage *mockStorage, now time.Time) { - t.Skip("Group-level errors are no longer tracked in the evaluator") - }, - wantStatus: map[string]ruleStatusExpectation{ - "rule1": {hasEvaluated: false}, - }, - wantGroupErrors: []string{"failed to fetch alert group"}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := context.Background() - - state, storage, scheduler := createTestEnvironment(t, start, "proj1", tt.alertGroup) - - tt.simulate(ctx, t, scheduler, storage, start) - - resp, err := state.GetAlertGroup(ctx, &alertv1.GetAlertGroupRequest{ - ProjectName: "proj1", - Name: tt.alertGroup.Spec.Name, - }) - require.NoError(t, err) - - if len(tt.wantGroupErrors) > 0 { - require.Equal(t, tt.wantGroupErrors, resp.AlertGroup.Status.Errors, "group-level errors") - } - - for ruleID, want := range tt.wantStatus { - ruleStatus := findRuleStatus(resp.AlertGroup.Status.Rules, ruleID) - require.NotNil(t, ruleStatus, "rule %s should have status entry", ruleID) - - if !want.hasEvaluated { - assert.Nil(t, ruleStatus.LastEvaluatedAt, "rule %s should not be evaluated yet", ruleID) - assert.Nil(t, ruleStatus.LastEvaluationMetrics, "rule %s should not have metrics", ruleID) - continue - } - - require.NotNil(t, ruleStatus.LastEvaluatedAt, "rule %s should have evaluation timestamp", ruleID) - - if want.hasError { - require.NotNil(t, ruleStatus.Error, "rule %s should have error", ruleID) - assert.Contains(t, *ruleStatus.Error, want.errorContains, "rule %s error message", ruleID) - assert.Nil(t, ruleStatus.LastEvaluationMetrics, "rule %s shouldn't have metrics when failed", ruleID) - } else { - assert.Nil(t, ruleStatus.Error, "rule %s should not have error", ruleID) - require.NotNil(t, ruleStatus.LastEvaluationMetrics, "rule %s should have metrics", ruleID) - assert.Equal(t, want.rowsScanned, ruleStatus.LastEvaluationMetrics.RowsScanned, "rule %s rows scanned", ruleID) - if want.rowsReturned > 0 { - assert.Equal(t, want.rowsReturned, ruleStatus.LastEvaluationMetrics.RowsReturned, "rule %s rows returned", ruleID) - } - if want.latencyMs > 0 { - assert.Equal(t, want.latencyMs, ruleStatus.LastEvaluationMetrics.TotalLatency.AsDuration().Milliseconds(), "rule %s latency", ruleID) - } - } - } - - }) - } -} - -type evaluationOutcome struct { - metrics *typesv1.QueryMetrics - error string -} - -func findRuleStatus(rules []*typesv1.AlertGroupStatus_NamedAlertRuleStatus, ruleID string) *typesv1.AlertRuleStatus { - for _, r := range rules { - if r.Id == ruleID { - return r.Status - } - } - return nil -} - -func withAlertRule(id, query string) func(*typesv1.AlertGroupSpec) { - return func(spec *typesv1.AlertGroupSpec) { - spec.Rules = append(spec.Rules, &typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - Id: id, - Spec: &typesv1.AlertRuleSpec{ - Name: id, - Expr: &typesv1.Query{}, - }, - }) - } -} - -func createTestEnvironment(t *testing.T, now time.Time, projectName string, group *typesv1.AlertGroup) (*mockProjectService, *mockStorage, *AlertScheduler) { - project := mkproject(projectName) - - storage := &mockStorage{} - - state := &mockProjectService{ - projects: []*typesv1.Project{project}, - alertGroups: map[string][]*typesv1.AlertGroup{projectName: {group}}, - storage: storage, - } - - scheduler := newAlertScheduler( - slog.New(slog.NewTextHandler(os.Stderr, nil)), - state, - storage, - func() time.Time { return now }, - func() <-chan time.Time { return nil }, // Won't actually reconcile in these tests - func(projectName, groupName string, interval time.Duration) <-chan time.Time { return nil }, - func(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error { return nil }, - ) - - return state, storage, scheduler -} - -func triggerEvaluation(ctx context.Context, t *testing.T, s *AlertScheduler, storage *mockStorage, projectName, groupName string, now time.Time, outcomes map[string]evaluationOutcome) { - s.mu.Lock() - _, exists := s.evaluators[alertGroupKey(projectName, groupName)] - if !exists { - eval := &alertGroupEvaluator{ - projectName: projectName, - groupName: groupName, - done: make(chan struct{}), - } - s.evaluators[alertGroupKey(projectName, groupName)] = eval - } - s.mu.Unlock() - - for ruleID, outcome := range outcomes { - status := &typesv1.AlertRuleStatus{ - LastEvaluatedAt: timestamppb.New(now), - } - - if outcome.error != "" { - status.Error = &outcome.error - } else { - status.LastEvaluationMetrics = outcome.metrics - } - - err := storage.AlertUpdateState(ctx, projectName, groupName, ruleID, status) - require.NoError(t, err) - } -} diff --git a/internal/localserver/server.go b/internal/localserver/server.go deleted file mode 100644 index 54f98b46..00000000 --- a/internal/localserver/server.go +++ /dev/null @@ -1,295 +0,0 @@ -package localserver - -import ( - "context" - "errors" - "fmt" - "log/slog" - "net" - "net/http" - "runtime/debug" - "slices" - "strconv" - "time" - - "connectrpc.com/connect" - - connectcors "connectrpc.com/cors" - "connectrpc.com/otelconnect" - "github.com/minitape/api/go/svc/alert/v1/alertv1connect" - "github.com/minitape/api/go/svc/dashboard/v1/dashboardv1connect" - "github.com/minitape/api/go/svc/ingest/v1/ingestv1connect" - "github.com/minitape/api/go/svc/localhost/v1/localhostv1connect" - "github.com/minitape/api/go/svc/project/v1/projectv1connect" - "github.com/minitape/api/go/svc/query/v1/queryv1connect" - userv1 "github.com/minitape/api/go/svc/user/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/errutil" - "github.com/humanlogio/humanlog/internal/localstate" - "github.com/humanlogio/humanlog/internal/localsvc" - "github.com/humanlogio/humanlog/pkg/localstorage" - "github.com/humanlogio/humanlog/pkg/retry" - "github.com/rs/cors" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" - "go.opentelemetry.io/contrib/propagators/b3" - "go.opentelemetry.io/contrib/propagators/ot" - otlplogssvcpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" - otlpmetricssvcpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - otlptracesvcpb "go.opentelemetry.io/proto/otlp/collector/trace/v1" - "golang.org/x/net/http2" - "golang.org/x/net/http2/h2c" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc" - "google.golang.org/grpc/reflection" -) - -func ServeLocalhost( - ctx context.Context, - ll *slog.Logger, - localhostCfg *typesv1.ServeLocalhostConfig, - ownVersion *typesv1.Version, - app *localstorage.AppCtx, - openStorage func(ctx context.Context) (localstorage.Storage, error), - openState func(ctx context.Context, db localstorage.Storage) (localstate.DB, error), - registerOnCloseServer func(srv *http.Server), - doLogin func(ctx context.Context, returnToURL string) error, - doLogout func(ctx context.Context, returnToURL string) error, - doUpdate func(ctx context.Context) error, - doRestart func(ctx context.Context) error, - getConfig func(ctx context.Context) (*typesv1.LocalhostConfig, error), - setConfig func(ctx context.Context, cfg *typesv1.LocalhostConfig) error, - whoami func(ctx context.Context) (*userv1.WhoamiResponse, error), - notifyAlert func(ctx context.Context, ar *typesv1.AlertRule, o *typesv1.Obj) error, -) error { - port := int(localhostCfg.Port) - - // obtaining the listener is our way of also getting an exclusive lock on the storage engine - // although if someone was independently using the DB before we started, we'll be holding the listener - // lock while failing to open the storage... this will cause the service to exit - localhostAddr := net.JoinHostPort("localhost", strconv.Itoa(port)) - var ( - l net.Listener - err error - attemptLeft = 10 - ) - err = retry.Do(ctx, func(ctx context.Context) (bool, error) { - ll.InfoContext(ctx, "requesting listener for address", slog.String("addr", localhostAddr)) - l, err = net.Listen("tcp", localhostAddr) - if err != nil && !errutil.IsEADDRINUSE(err) { - return false, fmt.Errorf("listening on host/port: %v", err) - } - if errutil.IsEADDRINUSE(err) { - // try again - ll.InfoContext(ctx, "address in use, retrying later", slog.Int("attempts", attemptLeft)) - attemptLeft-- - return attemptLeft > 0, nil - } - return false, nil - }, retry.UseBaseSleep(20*time.Millisecond), retry.UseCapSleep(time.Second)) - if err != nil { - return fmt.Errorf("unable to obtain localhost listener: %v", err) - } - if l == nil { - return fmt.Errorf("never obtained listener, giving up") - } - defer l.Close() - ll.InfoContext(ctx, "obtained listener") - - var otlpGrpcL net.Listener - if localhostCfg.Otlp != nil { - otlpGrpcPort := int(localhostCfg.Otlp.GrpcPort) - localhostOtlpAddr := net.JoinHostPort("localhost", strconv.Itoa(otlpGrpcPort)) - ll.InfoContext(ctx, "requesting listener for address (OTLP gRPC service)", slog.String("addr", localhostOtlpAddr)) - otlpGrpcL, err = net.Listen("tcp", localhostOtlpAddr) - if err != nil { - return fmt.Errorf("listening on OTLP gRPC port: %v", err) - } - defer otlpGrpcL.Close() - ll.InfoContext(ctx, "obtained OTLP gRPC listener") - } - - var otlpHttpL net.Listener - if localhostCfg.Otlp != nil && localhostCfg.Otlp.HttpPort != localhostCfg.Port { - otlpHttpPort := int(localhostCfg.Otlp.HttpPort) - localhostOtlpAddr := net.JoinHostPort("localhost", strconv.Itoa(otlpHttpPort)) - ll.InfoContext(ctx, "requesting listener for address (OTLP HTTP service)", slog.String("addr", localhostOtlpAddr)) - otlpHttpL, err = net.Listen("tcp", localhostOtlpAddr) - if err != nil { - return fmt.Errorf("listening on OTLP HTTP port: %v", err) - } - defer otlpHttpL.Close() - ll.InfoContext(ctx, "obtained OTLP HTTP listener") - } - - ll.InfoContext(ctx, "opening storage engine") - storage, err := openStorage(ctx) - if err != nil { - return fmt.Errorf("opening localstorage %q: %v", localhostCfg.Engine, err) - } - defer func() { - ll.InfoContext(ctx, "closing storage engine") - if err := storage.Close(); err != nil { - ll.ErrorContext(ctx, "unable to cleanly close storage engine", slog.Any("err", err)) - } else { - ll.InfoContext(ctx, "storage engine closed cleanly") - } - }() - ll.InfoContext(ctx, "preparing localhost services") - - mux := http.NewServeMux() - - ll.InfoContext(ctx, "opening state engine") - state, err := openState(ctx, storage) - if err != nil { - return fmt.Errorf("opening localstorage %q: %v", localhostCfg.Engine, err) - } - - // Create alert scheduler (started later in errgroup) - scheduler := NewAlertScheduler(ll, state, storage, time.Now, notifyAlert, 60*time.Second) - - localhostsvc := localsvc.New(ll, ownVersion, storage, state, - doLogin, - doLogout, - doUpdate, - doRestart, - getConfig, - setConfig, - scheduler.TriggerReconcile, - ) - - otelIctpr, err := otelconnect.NewInterceptor() - if err != nil { - return fmt.Errorf("setting up otel interceptors: %v", err) - } - - mux.Handle(localhostv1connect.NewLocalhostServiceHandler(localhostsvc, connect.WithInterceptors(otelIctpr))) - mux.Handle(ingestv1connect.NewIngestServiceHandler(localhostsvc, connect.WithInterceptors(otelIctpr))) - mux.Handle(queryv1connect.NewQueryServiceHandler(localhostsvc, connect.WithInterceptors(otelIctpr))) - mux.Handle(queryv1connect.NewTraceServiceHandler(localhostsvc, connect.WithInterceptors(otelIctpr))) - mux.Handle(projectv1connect.NewProjectServiceHandler(localhostsvc, connect.WithInterceptors(otelIctpr))) - mux.Handle(dashboardv1connect.NewDashboardServiceHandler(localhostsvc, connect.WithInterceptors(otelIctpr))) - mux.Handle(alertv1connect.NewAlertServiceHandler(localhostsvc, connect.WithInterceptors(otelIctpr))) - - httphdl := h2c.NewHandler(mux, &http2.Server{}) - httphdl = otelhttp.NewHandler(httphdl, "humanlog.ConnectRPC") - httphdl = withCORS(httphdl) - - srv := &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer func() { - if r := recover(); r != nil { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "oh noes the sky is falling\n\n%s", string(debug.Stack())) - panic(r) - } - }() - httphdl.ServeHTTP(w, r) - })} - - registerOnCloseServer(srv) - - ll.InfoContext(ctx, "serving localhost services") - - eg, ctx := errgroup.WithContext(ctx) - if otlpGrpcL != nil { - - stats := otelgrpc.NewServerHandler( - otelgrpc.WithMessageEvents(otelgrpc.ReceivedEvents, otelgrpc.SentEvents), - otelgrpc.WithFilter( - filters.Any( - filters.Not( - filters.ServiceName(otlptracesvcpb.TraceService_ServiceDesc.ServiceName), - ), - filters.Not( - filters.ServiceName(otlpmetricssvcpb.MetricsService_ServiceDesc.ServiceName), - ), - ), - ), - ) - - // otel gRPC receiver handlers - gsrv := grpc.NewServer(grpc.StatsHandler(stats)) - otlplogssvcpb.RegisterLogsServiceServer(gsrv, localhostsvc.AsLoggingOTLP()) - otlpmetricssvcpb.RegisterMetricsServiceServer(gsrv, localhostsvc.AsMetricsOTLP()) - otlptracesvcpb.RegisterTraceServiceServer(gsrv, localhostsvc.AsTracingOTLP()) - reflection.Register(gsrv) - eg.Go(func() error { - ll.InfoContext(ctx, "OTLP gRPC server starting") - if err := gsrv.Serve(otlpGrpcL); err != nil { - ll.ErrorContext(ctx, "otlp gRPC server errored", slog.Any("err", err)) - return err - } - return nil - }) - } - if otlpHttpL != nil { - mux := http.NewServeMux() - mux.HandleFunc("/v1/traces", localhostsvc.AsTracingOTLP().ExportHTTP) - mux.HandleFunc("/v1/metrics", localhostsvc.AsMetricsOTLP().ExportHTTP) - mux.HandleFunc("/v1/logs", localhostsvc.AsLoggingOTLP().ExportHTTP) - // mux.HandleFunc("/v1development/profiles", localhostsvc.AsProfileOTLP().ExportHTTP) - - srv := http.Server{Handler: withCORS(mux)} - eg.Go(func() error { - ll.InfoContext(ctx, "OTLP HTTP server starting") - if err := srv.Serve(otlpHttpL); err != nil { - ll.ErrorContext(ctx, "otlp HTTP server errored", slog.Any("err", err)) - return err - } - return nil - }) - } - eg.Go(func() error { - ll.InfoContext(ctx, "humanlog localhost server starting") - if err := srv.Serve(l); err != nil && !errors.Is(err, http.ErrServerClosed) { - ll.ErrorContext(ctx, "query engine server errored", slog.Any("err", err)) - return err - } - return nil - }) - - eg.Go(func() error { - // Alert scheduler: evaluates each alert group at its specified interval - return scheduler.Start(ctx, state) - }) - - if err := eg.Wait(); err != nil { - return err - } - ll.InfoContext(ctx, "stopped serving localhost services") - - return nil -} - -func withCORS(hdl http.Handler) http.Handler { - c := cors.New(cors.Options{ - // Debug: true, - AllowedOrigins: []string{ - "https://humanlog.io", - "https://humanlog.dev", - "https://app.humanlog.dev", - "https://app.humanlog.dev:3000", - "https://humanlog.sh", - "http://localhost:3000", - "https://humanlog.test:3000", - }, - AllowedMethods: connectcors.AllowedMethods(), - AllowedHeaders: slices.Concat( - connectcors.AllowedHeaders(), - []string{"Browser-Authorization", "Request-Id"}, - ot.OT{}.Fields(), - b3.New(b3.WithInjectEncoding(b3.B3SingleHeader)).Fields(), - b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader)).Fields(), - ), - ExposedHeaders: slices.Concat( - connectcors.ExposedHeaders(), - []string{"Browser-Authorization", "Request-Id"}, - ot.OT{}.Fields(), - b3.New(b3.WithInjectEncoding(b3.B3SingleHeader)).Fields(), - b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader)).Fields(), - ), - MaxAge: 7200, // 2 hours in seconds - }) - return c.Handler(hdl) -} diff --git a/internal/localstate/inmem.go b/internal/localstate/inmem.go deleted file mode 100644 index d8be3b96..00000000 --- a/internal/localstate/inmem.go +++ /dev/null @@ -1,757 +0,0 @@ -package localstate - -import ( - "context" - "encoding/json" - "fmt" - "slices" - "sync" - - "connectrpc.com/connect" - alertv1 "github.com/minitape/api/go/svc/alert/v1" - dashboardv1 "github.com/minitape/api/go/svc/dashboard/v1" - projectv1 "github.com/minitape/api/go/svc/project/v1" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/pkg/localstorage" - "github.com/oklog/ulid/v2" - persesv1 "github.com/perses/perses/pkg/model/api/v1" - "google.golang.org/protobuf/types/known/timestamppb" -) - -var _ DB = (*Mem)(nil) - -type Mem struct { - mu sync.Mutex - - projectlist []string - projects map[string]*project -} - -type project struct { - project *typesv1.Project - - dashboardlist []string - dashboards map[string]*typesv1.Dashboard - - alertGroupList []string - alertGroups map[string]*alertGroup -} - -type alertGroup struct { - group *typesv1.AlertGroup - - // Full alert rules (Meta+Spec+Status), keyed by name - rules map[string]*typesv1.AlertRule -} - -func NewMemory() *Mem { - db := &Mem{ - projects: make(map[string]*project), - } - projectRes, err := db.CreateProject(context.Background(), &projectv1.CreateProjectRequest{ - Spec: &typesv1.ProjectSpec{ - Name: "test-ephemeral-project", - Pointer: &typesv1.ProjectPointer{Scheme: &typesv1.ProjectPointer_Db{ - Db: &typesv1.ProjectPointer_Virtual{ - Uri: "db://localhost/test-ephemeral-project", - }, - }}, - }, - }) - if err != nil { - panic(err) - } - project := projectRes.Project - _, err = db.CreateDashboard(context.Background(), &dashboardv1.CreateDashboardRequest{ - ProjectName: project.Spec.Name, - Spec: defaultDashboard.Spec, - }) - if err != nil { - panic(err) - } - return db -} - -func (db *Mem) withProject(name string, fn func(st *project) error) error { - db.mu.Lock() - defer db.mu.Unlock() - for _, project := range db.projects { - if project.project.Spec.Name == name { - return fn(project) - } - } - return connect.NewError(connect.CodeNotFound, fmt.Errorf("no project with name %q exists", name)) -} - -func (db *Mem) withAlertGroup(projectName, alertGroupName string, fn func(st *project, group *alertGroup) error) error { - return db.withProject(projectName, func(st *project) error { - group, ok := st.alertGroups[alertGroupName] - if !ok { - return connect.NewError(connect.CodeNotFound, fmt.Errorf("no alert group with name %q exists", alertGroupName)) - } - return fn(st, group) - }) -} - -func (db *Mem) CreateProject(ctx context.Context, req *projectv1.CreateProjectRequest) (*projectv1.CreateProjectResponse, error) { - out := &typesv1.Project{ - Meta: &typesv1.ProjectMeta{ - Id: ulid.Make().String(), - }, - Spec: req.Spec, - Status: &typesv1.ProjectStatus{ - CreatedAt: timestamppb.Now(), - UpdatedAt: timestamppb.Now(), - }, - } - db.mu.Lock() - defer db.mu.Unlock() - for _, project := range db.projects { - if project.project.Spec.Name == req.Spec.Name { - return nil, connect.NewError(connect.CodeAlreadyExists, fmt.Errorf("project %q already uses the name %q", project.project.Meta.Id, req.Spec.Name)) - } - } - db.projectlist = append(db.projectlist, out.Meta.Id) - db.projects[out.Meta.Id] = &project{ - project: out, - dashboards: make(map[string]*typesv1.Dashboard), - alertGroups: make(map[string]*alertGroup), - } - return &projectv1.CreateProjectResponse{Project: out}, nil -} - -func (db *Mem) ValidateProject(ctx context.Context, req *projectv1.ValidateProjectRequest) (*projectv1.ValidateProjectResponse, error) { - db.mu.Lock() - defer db.mu.Unlock() - - // Run the same validation as CreateProject - for _, project := range db.projects { - if project.project.Spec.Name == req.Spec.Name { - return nil, connect.NewError(connect.CodeAlreadyExists, fmt.Errorf("project %q already uses the name %q", project.project.Meta.Id, req.Spec.Name)) - } - } - - // In-memory projects don't have directory conflicts, so return empty status - return &projectv1.ValidateProjectResponse{ - Status: &typesv1.ProjectStatus{}, - }, nil -} - -func (db *Mem) SyncProject(ctx context.Context, req *projectv1.SyncProjectRequest) (*projectv1.SyncProjectResponse, error) { - var ( - out *typesv1.Project - dashboards []*typesv1.Dashboard - alertGroups []*typesv1.AlertGroup - ) - err := db.withProject(req.Name, func(st *project) error { - out = st.project - for _, key := range st.dashboardlist { - dashboards = append(dashboards, st.dashboards[key]) - } - for _, key := range st.alertGroupList { - alertGroups = append(alertGroups, st.alertGroups[key].group) - } - return nil - }) - return &projectv1.SyncProjectResponse{Project: out}, err -} - -func (db *Mem) GetProject(ctx context.Context, req *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) { - var ( - out *typesv1.Project - dashboards []*typesv1.Dashboard - alertGroups []*typesv1.AlertGroup - ) - err := db.withProject(req.Name, func(st *project) error { - out = st.project - for _, key := range st.dashboardlist { - dashboards = append(dashboards, st.dashboards[key]) - } - for _, key := range st.alertGroupList { - alertGroups = append(alertGroups, st.alertGroups[key].group) - } - return nil - }) - return &projectv1.GetProjectResponse{Project: out, Dashboards: dashboards, AlertGroups: alertGroups}, err -} - -func (db *Mem) UpdateProject(ctx context.Context, req *projectv1.UpdateProjectRequest) (*projectv1.UpdateProjectResponse, error) { - var out *typesv1.Project - err := db.withProject(req.Name, func(st *project) error { - out = st.project - out.Spec = req.Spec - out.Status.UpdatedAt = timestamppb.Now() - return nil - }) - return &projectv1.UpdateProjectResponse{Project: out}, err -} - -func (db *Mem) DeleteProject(ctx context.Context, req *projectv1.DeleteProjectRequest) (*projectv1.DeleteProjectResponse, error) { - db.mu.Lock() - defer db.mu.Unlock() - for _, project := range db.projects { - if project.project.Spec.Name == req.Name { - delete(db.projects, project.project.Meta.Id) - db.projectlist = slices.DeleteFunc(db.projectlist, func(e string) bool { return e == project.project.Meta.Id }) - - return nil, nil - } - } - return nil, nil -} - -func (db *Mem) ListProject(ctx context.Context, req *projectv1.ListProjectRequest) (*projectv1.ListProjectResponse, error) { - db.mu.Lock() - defer db.mu.Unlock() - - cursor := req.Cursor - limit := req.Limit - limit = max(limit, 100) - limit = min(limit, 10) - - var ( - out []*projectv1.ListProjectResponse_ListItem - next *typesv1.Cursor - err error - ) - - var fromID string - if cursor != nil { - var p stringPage - if err := json.Unmarshal(cursor.Opaque, &p); err != nil { - return nil, err - } - fromID = p.LastID - } - var i int - if fromID != "" { - i = slices.IndexFunc(db.projectlist, func(e string) bool { return e == fromID }) + 1 - } - if i > len(db.projectlist) { - return &projectv1.ListProjectResponse{}, nil - } - from := i - to := min(i+int(limit), len(db.projectlist)) - - for _, id := range db.projectlist[from:to] { - st := db.projects[id] - out = append(out, &projectv1.ListProjectResponse_ListItem{Project: st.project}) - } - if len(out) == int(limit) && limit != 0 { - next = new(typesv1.Cursor) - p := stringPage{LastID: out[len(out)-1].Project.Meta.Id} - next.Opaque, err = json.Marshal(p) - if err != nil { - return nil, err - } - } - return &projectv1.ListProjectResponse{}, nil -} - -func (db *Mem) CreateDashboard(ctx context.Context, req *dashboardv1.CreateDashboardRequest) (*dashboardv1.CreateDashboardResponse, error) { - var out *typesv1.Dashboard - err := db.withProject(req.ProjectName, func(st *project) error { - id := ulid.Make() - out = &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{ - Id: id.String(), - }, - Spec: req.Spec, - Status: &typesv1.DashboardStatus{ - CreatedAt: timestamppb.Now(), - UpdatedAt: timestamppb.Now(), - }, - } - - st.dashboards[out.Meta.Id] = out - st.dashboardlist = append(st.dashboardlist, out.Meta.Id) - return nil - }) - return &dashboardv1.CreateDashboardResponse{Dashboard: out}, err -} - -func (db *Mem) GetDashboard(ctx context.Context, req *dashboardv1.GetDashboardRequest) (*dashboardv1.GetDashboardResponse, error) { - var out *typesv1.Dashboard - err := db.withProject(req.ProjectName, func(st *project) error { - var ok bool - out, ok = st.dashboards[req.Id] - - if !ok { - return connect.NewError(connect.CodeNotFound, fmt.Errorf("no such dashboard")) - } - return nil - }) - return &dashboardv1.GetDashboardResponse{Dashboard: out}, err -} - -func (db *Mem) UpdateDashboard(ctx context.Context, req *dashboardv1.UpdateDashboardRequest) (*dashboardv1.UpdateDashboardResponse, error) { - var out *typesv1.Dashboard - err := db.withProject(req.ProjectName, func(st *project) error { - var ok bool - out, ok = st.dashboards[req.Id] - if !ok { - return connect.NewError(connect.CodeNotFound, fmt.Errorf("no such dashboard")) - } - out.Spec = req.Spec - out.Status.UpdatedAt = timestamppb.Now() - st.dashboards[out.Meta.Id] = out - return nil - }) - return &dashboardv1.UpdateDashboardResponse{Dashboard: out}, err -} - -func (db *Mem) DeleteDashboard(ctx context.Context, req *dashboardv1.DeleteDashboardRequest) (*dashboardv1.DeleteDashboardResponse, error) { - err := db.withProject(req.ProjectName, func(st *project) error { - delete(st.dashboards, req.Id) - st.dashboardlist = slices.DeleteFunc(st.dashboardlist, func(e string) bool { return e == req.Id }) - return nil - }) - return &dashboardv1.DeleteDashboardResponse{}, err -} - -type stringPage struct { - LastID string `json:"lastID"` -} - -func (db *Mem) ListDashboard(ctx context.Context, req *dashboardv1.ListDashboardRequest) (*dashboardv1.ListDashboardResponse, error) { - cursor := req.Cursor - limit := req.Limit - limit = max(limit, 100) - limit = min(limit, 10) - - var ( - out []*dashboardv1.ListDashboardResponse_ListItem - next *typesv1.Cursor - err error - ) - err = db.withProject(req.ProjectName, func(st *project) error { - var fromID string - if cursor != nil { - var p stringPage - if err := json.Unmarshal(cursor.Opaque, &p); err != nil { - return err - } - fromID = p.LastID - } - var i int - if fromID != "" { - i = slices.IndexFunc(st.dashboardlist, func(e string) bool { return e == fromID }) + 1 - } - if i > len(st.dashboardlist) { - return nil - } - from := i - to := min(i+int(limit), len(st.dashboardlist)) - - for _, id := range st.dashboardlist[from:to] { - d := st.dashboards[id] - out = append(out, &dashboardv1.ListDashboardResponse_ListItem{Dashboard: d}) - } - if len(out) == int(limit) && limit != 0 { - next = new(typesv1.Cursor) - p := stringPage{LastID: out[len(out)-1].Dashboard.Meta.Id} - next.Opaque, err = json.Marshal(p) - if err != nil { - return err - } - } - return nil - }) - return &dashboardv1.ListDashboardResponse{Items: out, Next: next}, err -} - -func (db *Mem) CreateAlertGroup(ctx context.Context, req *alertv1.CreateAlertGroupRequest) (*alertv1.CreateAlertGroupResponse, error) { - var out *typesv1.AlertGroup - err := db.withProject(req.ProjectName, func(st *project) error { - out = &typesv1.AlertGroup{ - Meta: &typesv1.AlertGroupMeta{ - Id: ulid.Make().String(), - }, - Spec: req.Spec, - Status: &typesv1.AlertGroupStatus{}, - } - for _, el := range st.alertGroups { - if el.group.Spec.Name == req.Spec.Name { - return connect.NewError(connect.CodeAlreadyExists, fmt.Errorf("an alert group with name %q already exists", req.Spec.Name)) - } - } - st.alertGroupList = append(st.alertGroupList, out.Meta.Id) - st.alertGroups[out.Meta.Id] = &alertGroup{ - group: out, - rules: make(map[string]*typesv1.AlertRule), - } - return nil - }) - return &alertv1.CreateAlertGroupResponse{AlertGroup: out}, err -} - -func (db *Mem) GetAlertGroup(ctx context.Context, req *alertv1.GetAlertGroupRequest) (*alertv1.GetAlertGroupResponse, error) { - var out *typesv1.AlertGroup - err := db.withAlertGroup(req.ProjectName, req.Name, func(st *project, ag *alertGroup) error { - out = ag.group - - // Populate status from AlertRuleStatusStorage - if out.Status == nil { - out.Status = &typesv1.AlertGroupStatus{} - } - if out.Status.Rules == nil { - out.Status.Rules = make([]*typesv1.AlertGroupStatus_NamedAlertRuleStatus, 0, len(out.Spec.Rules)) - } - - // Query status for each rule from storage - alertStorage := db.AlertRuleStatusStorage() - for _, namedRule := range out.Spec.Rules { - status, err := alertStorage.AlertGetOrCreate(ctx, req.ProjectName, req.Name, namedRule.Id, func() *typesv1.AlertRuleStatus { - return &typesv1.AlertRuleStatus{Status: &typesv1.AlertRuleStatus_Unknown{}} - }) - if err != nil { - return fmt.Errorf("getting alert status for rule %q: %w", namedRule.Id, err) - } - - // Check if status already exists in the array - found := false - for _, namedStatus := range out.Status.Rules { - if namedStatus.Id == namedRule.Id { - namedStatus.Status = status - found = true - break - } - } - if !found { - out.Status.Rules = append(out.Status.Rules, &typesv1.AlertGroupStatus_NamedAlertRuleStatus{ - Id: namedRule.Id, - Status: status, - }) - } - } - - return nil - }) - if err != nil { - return nil, err - } - - return &alertv1.GetAlertGroupResponse{AlertGroup: out}, nil -} - -func (db *Mem) UpdateAlertGroup(ctx context.Context, req *alertv1.UpdateAlertGroupRequest) (*alertv1.UpdateAlertGroupResponse, error) { - var out *typesv1.AlertGroup - err := db.withProject(req.ProjectName, func(st *project) error { - for _, ag := range st.alertGroups { - if ag.group.Spec.Name == req.Name { - out := ag.group - out.Spec = req.Spec - ag.group = out - st.alertGroups[out.Meta.Id] = ag - return nil - } - } - return connect.NewError(connect.CodeNotFound, fmt.Errorf("no such alert group")) - }) - return &alertv1.UpdateAlertGroupResponse{AlertGroup: out}, err -} - -func (db *Mem) DeleteAlertGroup(ctx context.Context, req *alertv1.DeleteAlertGroupRequest) (*alertv1.DeleteAlertGroupResponse, error) { - err := db.withProject(req.ProjectName, func(st *project) error { - for _, ag := range st.alertGroups { - if ag.group.Spec.Name == req.Name { - delete(st.alertGroups, ag.group.Meta.Id) - st.alertGroupList = slices.DeleteFunc(st.alertGroupList, func(e string) bool { return e == ag.group.Meta.Id }) - return nil - } - } - return nil - }) - return &alertv1.DeleteAlertGroupResponse{}, err -} - -func (db *Mem) ListAlertGroup(ctx context.Context, req *alertv1.ListAlertGroupRequest) (*alertv1.ListAlertGroupResponse, error) { - cursor := req.Cursor - limit := req.Limit - limit = max(limit, 100) - limit = min(limit, 10) - - var ( - out []*alertv1.ListAlertGroupResponse_ListItem - next *typesv1.Cursor - err error - ) - err = db.withProject(req.ProjectName, func(st *project) error { - var fromID string - if cursor != nil { - var p stringPage - if err := json.Unmarshal(cursor.Opaque, &p); err != nil { - return err - } - fromID = p.LastID - } - var i int - if fromID != "" { - i = slices.IndexFunc(st.alertGroupList, func(e string) bool { return e == fromID }) + 1 - } - if i > len(st.alertGroupList) { - return nil - } - from := i - to := min(i+int(limit), len(st.alertGroupList)) - - for _, id := range st.alertGroupList[from:to] { - el := st.alertGroups[id] - out = append(out, &alertv1.ListAlertGroupResponse_ListItem{AlertGroup: el.group}) - } - if len(out) == int(limit) && limit != 0 { - next = new(typesv1.Cursor) - p := stringPage{LastID: out[len(out)-1].AlertGroup.Meta.Id} - next.Opaque, err = json.Marshal(p) - if err != nil { - return err - } - } - return nil - }) - - return &alertv1.ListAlertGroupResponse{Items: out, Next: next}, err -} - -func (db *Mem) CreateAlertRule(ctx context.Context, req *alertv1.CreateAlertRuleRequest) (*alertv1.CreateAlertRuleResponse, error) { - var out *typesv1.AlertRule - db.withAlertGroup(req.ProjectName, req.GroupName, func(st *project, group *alertGroup) error { - // Check if rule already exists - if _, exists := group.rules[req.Name]; exists { - return connect.NewError(connect.CodeAlreadyExists, fmt.Errorf("an alert with name %q already exists in this group", req.Name)) - } - - // Create the full AlertRule - item := &typesv1.AlertRule{ - Meta: &typesv1.AlertRuleMeta{ - Id: req.Name, - }, - Spec: &typesv1.AlertRuleSpec{ - Name: req.Name, - Expr: req.Expr, - Labels: req.Labels, - Annotations: req.Annotations, - For: req.For, - KeepFiringFor: req.KeepFiringFor, - }, - Status: &typesv1.AlertRuleStatus{ - Status: &typesv1.AlertRuleStatus_Unknown{Unknown: &typesv1.AlertUnknown{}}, - }, - } - - // Store in rules map - group.rules[req.Name] = item - - // Also add to group.Spec.Rules slice - group.group.Spec.Rules = append(group.group.Spec.Rules, &typesv1.AlertGroupSpec_NamedAlertRuleSpec{ - Id: req.Name, - Spec: item.Spec, - }) - - out = item - return nil - }) - return &alertv1.CreateAlertRuleResponse{AlertRule: out}, nil - -} - -func (db *Mem) GetAlertRule(ctx context.Context, req *alertv1.GetAlertRuleRequest) (*alertv1.GetAlertRuleResponse, error) { - var out *typesv1.AlertRule - err := db.withAlertGroup(req.ProjectName, req.GroupName, func(st *project, group *alertGroup) error { - rule, ok := group.rules[req.Name] - if !ok { - return connect.NewError(connect.CodeNotFound, fmt.Errorf("no such alert")) - } - out = rule - return nil - }) - return &alertv1.GetAlertRuleResponse{AlertRule: out}, err -} - -func (db *Mem) UpdateAlertRule(ctx context.Context, req *alertv1.UpdateAlertRuleRequest) (*alertv1.UpdateAlertRuleResponse, error) { - var out *typesv1.AlertRule - err := db.withAlertGroup(req.ProjectName, req.GroupName, func(st *project, group *alertGroup) error { - rule, ok := group.rules[req.Spec.Name] - if !ok { - return connect.NewError(connect.CodeNotFound, fmt.Errorf("no such alert")) - } - - // Update the spec - rule.Spec = req.Spec - - // Update in rules map - group.rules[req.Spec.Name] = rule - - // Update in group.Spec.Rules slice - for i, named := range group.group.Spec.Rules { - if named.Id == req.Spec.Name { - group.group.Spec.Rules[i].Spec = rule.Spec - break - } - } - - out = rule - return nil - }) - return &alertv1.UpdateAlertRuleResponse{AlertRule: out}, err -} - -func (db *Mem) DeleteAlertRule(ctx context.Context, req *alertv1.DeleteAlertRuleRequest) (*alertv1.DeleteAlertRuleResponse, error) { - err := db.withAlertGroup(req.ProjectName, req.GroupName, func(st *project, group *alertGroup) error { - // Delete from rules map - delete(group.rules, req.Name) - - // Delete from group.Spec.Rules slice - group.group.Spec.Rules = slices.DeleteFunc(group.group.Spec.Rules, func(e *typesv1.AlertGroupSpec_NamedAlertRuleSpec) bool { - return e.Id == req.Name - }) - return nil - }) - return &alertv1.DeleteAlertRuleResponse{}, err -} - -func (db *Mem) ListAlertRule(ctx context.Context, req *alertv1.ListAlertRuleRequest) (*alertv1.ListAlertRuleResponse, error) { - cursor := req.Cursor - limit := req.Limit - limit = max(limit, 100) - limit = min(limit, 10) - - var ( - out []*alertv1.ListAlertRuleResponse_ListItem - next *typesv1.Cursor - err error - ) - err = db.withAlertGroup(req.ProjectName, req.GroupName, func(st *project, group *alertGroup) error { - // Iterate Spec.Rules in order (preserves YAML order) - var fromName string - if cursor != nil { - var p stringPage - if err := json.Unmarshal(cursor.Opaque, &p); err != nil { - return err - } - fromName = p.LastID - } - var i int - if fromName != "" { - i = slices.IndexFunc(group.group.Spec.Rules, func(e *typesv1.AlertGroupSpec_NamedAlertRuleSpec) bool { - return e.Id == fromName - }) + 1 - } - if i >= len(group.group.Spec.Rules) { - return nil - } - from := i - to := min(i+int(limit), len(group.group.Spec.Rules)) - - for _, named := range group.group.Spec.Rules[from:to] { - rule := group.rules[named.Id] - out = append(out, &alertv1.ListAlertRuleResponse_ListItem{ - AlertRule: rule, - }) - } - if len(out) == int(limit) && limit != 0 { - next = new(typesv1.Cursor) - p := stringPage{LastID: out[len(out)-1].AlertRule.Spec.Name} - next.Opaque, err = json.Marshal(p) - if err != nil { - return err - } - } - return nil - }) - - return &alertv1.ListAlertRuleResponse{Items: out, Next: next}, err -} - -func (db *Mem) AlertRuleStatusStorage() localstorage.Alertable { - return &alertStorageMem{db: db} -} - -type alertStorageMem struct { - db *Mem -} - -func (as *alertStorageMem) AlertGetOrCreate(ctx context.Context, projectName, groupName, alertName string, create func() *typesv1.AlertRuleStatus) (*typesv1.AlertRuleStatus, error) { - var out *typesv1.AlertRuleStatus - err := as.db.withAlertGroup(projectName, groupName, func(st *project, group *alertGroup) error { - rule, ok := group.rules[alertName] - if !ok { - return fmt.Errorf("no alert named %q", alertName) - } - - // If status is nil, create it - if rule.Status == nil { - rule.Status = create() - group.rules[alertName] = rule - } - - out = rule.Status - return nil - }) - return out, err -} - -func (as *alertStorageMem) AlertUpdateState(ctx context.Context, projectName, groupName, alertName string, state *typesv1.AlertRuleStatus) error { - err := as.db.withAlertGroup(projectName, groupName, func(st *project, group *alertGroup) error { - rule, ok := group.rules[alertName] - if !ok { - return fmt.Errorf("no alert named %q", alertName) - } - - rule.Status = state - group.rules[alertName] = rule - return nil - }) - return err -} - -func (as *alertStorageMem) AlertDeleteStateNotInList(ctx context.Context, projectName, groupName string, keeplist []string) error { - err := as.db.withAlertGroup(projectName, groupName, func(st *project, group *alertGroup) error { - keepset := make(map[string]struct{}) - for _, keep := range keeplist { - keepset[keep] = struct{}{} - } - - var toDelete []string - for key := range group.rules { - if _, ok := keepset[key]; !ok { - toDelete = append(toDelete, key) - } - } - - for _, key := range toDelete { - delete(group.rules, key) - // Also remove from group.Spec.Rules - group.group.Spec.Rules = slices.DeleteFunc(group.group.Spec.Rules, func(e *typesv1.AlertGroupSpec_NamedAlertRuleSpec) bool { - return e.Id == key - }) - } - return nil - }) - return err -} - -var defaultDashboard = func() *typesv1.Dashboard { - var d persesv1.Dashboard - if err := json.Unmarshal([]byte(testdashboard), &d); err != nil { - panic(err) - } - out := &typesv1.Dashboard{ - Meta: &typesv1.DashboardMeta{ - Id: ulid.Make().String(), - }, - Spec: &typesv1.DashboardSpec{ - Name: d.Spec.Display.Name, - Description: d.Spec.Display.Description, - IsReadonly: true, - PersesJson: []byte(testdashboard), - }, - Status: &typesv1.DashboardStatus{ - CreatedAt: timestamppb.New(d.Metadata.CreatedAt), - UpdatedAt: timestamppb.New(d.Metadata.UpdatedAt), - }, - } - return out -}() - -const testdashboard = `{"kind":"Dashboard","metadata":{"name":"monitoring-dashboard","project":"default"},"spec":{"display":{"name":"Monitoring Dashboard","description":"System monitoring dashboard with memory, status, and CPU metrics"},"datasources":{"prometheus":{"default":true,"plugin":{"kind":"PrometheusDatasource","spec":{"directUrl":"http://localhost:9090"}}}},"duration":"1h","refreshInterval":"30s","variables":[],"panels":{"memory-panel":{"kind":"Panel","spec":{"display":{"name":"Memory Usage","description":"Go memory allocation in bytes"},"plugin":{"kind":"TimeSeriesChart","spec":{"legend":{"position":"bottom","size":"small"},"yAxis":{"show":true,"label":"Bytes"}}},"queries":[{"kind":"PrometheusTimeSeriesQuery","spec":{"plugin":{"kind":"PrometheusTimeSeriesQuery","spec":{"query":"go_memstats_alloc_bytes","datasource":{"kind":"PrometheusDatasource","name":"prometheus"}}}}}]}},"status-panel":{"kind":"Panel","spec":{"display":{"name":"Service Status","description":"Service availability status"},"plugin":{"kind":"TimeSeriesChart","spec":{"legend":{"position":"bottom","size":"small"},"yAxis":{"show":true,"label":"Status"}}},"queries":[{"kind":"PrometheusTimeSeriesQuery","spec":{"plugin":{"kind":"PrometheusTimeSeriesQuery","spec":{"query":"up","datasource":{"kind":"PrometheusDatasource","name":"prometheus"}}}}}]}},"cpu-panel":{"kind":"Panel","spec":{"display":{"name":"CPU Usage","description":"CPU garbage collection duration rate"},"plugin":{"kind":"TimeSeriesChart","spec":{"legend":{"position":"bottom","size":"small"},"yAxis":{"show":true,"label":"Rate"}}},"queries":[{"kind":"PrometheusTimeSeriesQuery","spec":{"plugin":{"kind":"PrometheusTimeSeriesQuery","spec":{"query":"rate(go_gc_duration_seconds_sum[5m])","datasource":{"kind":"PrometheusDatasource","name":"prometheus"}}}}}]}}},"layouts":[{"kind":"Grid","spec":{"display":{"title":"System Metrics","collapse":{"open":true}},"items":[{"x":0,"y":0,"width":12,"height":8,"content":{"$ref":"#/spec/panels/memory-panel"}},{"x":0,"y":8,"width":12,"height":8,"content":{"$ref":"#/spec/panels/status-panel"}},{"x":0,"y":16,"width":12,"height":8,"content":{"$ref":"#/spec/panels/cpu-panel"}}]}}]}}` diff --git a/internal/localstate/localstate.go b/internal/localstate/localstate.go deleted file mode 100644 index 7b32fe1e..00000000 --- a/internal/localstate/localstate.go +++ /dev/null @@ -1,37 +0,0 @@ -package localstate - -import ( - "context" - - alertv1 "github.com/minitape/api/go/svc/alert/v1" - dashboardv1 "github.com/minitape/api/go/svc/dashboard/v1" - projectv1 "github.com/minitape/api/go/svc/project/v1" -) - -type DB interface { - CreateProject(context.Context, *projectv1.CreateProjectRequest) (*projectv1.CreateProjectResponse, error) - ValidateProject(context.Context, *projectv1.ValidateProjectRequest) (*projectv1.ValidateProjectResponse, error) - GetProject(context.Context, *projectv1.GetProjectRequest) (*projectv1.GetProjectResponse, error) - SyncProject(context.Context, *projectv1.SyncProjectRequest) (*projectv1.SyncProjectResponse, error) - UpdateProject(context.Context, *projectv1.UpdateProjectRequest) (*projectv1.UpdateProjectResponse, error) - DeleteProject(context.Context, *projectv1.DeleteProjectRequest) (*projectv1.DeleteProjectResponse, error) - ListProject(context.Context, *projectv1.ListProjectRequest) (*projectv1.ListProjectResponse, error) - - CreateDashboard(ctx context.Context, req *dashboardv1.CreateDashboardRequest) (*dashboardv1.CreateDashboardResponse, error) - GetDashboard(ctx context.Context, req *dashboardv1.GetDashboardRequest) (*dashboardv1.GetDashboardResponse, error) - UpdateDashboard(ctx context.Context, req *dashboardv1.UpdateDashboardRequest) (*dashboardv1.UpdateDashboardResponse, error) - DeleteDashboard(ctx context.Context, req *dashboardv1.DeleteDashboardRequest) (*dashboardv1.DeleteDashboardResponse, error) - ListDashboard(ctx context.Context, req *dashboardv1.ListDashboardRequest) (*dashboardv1.ListDashboardResponse, error) - - CreateAlertGroup(ctx context.Context, req *alertv1.CreateAlertGroupRequest) (*alertv1.CreateAlertGroupResponse, error) - GetAlertGroup(ctx context.Context, req *alertv1.GetAlertGroupRequest) (*alertv1.GetAlertGroupResponse, error) - UpdateAlertGroup(ctx context.Context, req *alertv1.UpdateAlertGroupRequest) (*alertv1.UpdateAlertGroupResponse, error) - DeleteAlertGroup(ctx context.Context, req *alertv1.DeleteAlertGroupRequest) (*alertv1.DeleteAlertGroupResponse, error) - ListAlertGroup(ctx context.Context, req *alertv1.ListAlertGroupRequest) (*alertv1.ListAlertGroupResponse, error) - - CreateAlertRule(ctx context.Context, req *alertv1.CreateAlertRuleRequest) (*alertv1.CreateAlertRuleResponse, error) - GetAlertRule(ctx context.Context, req *alertv1.GetAlertRuleRequest) (*alertv1.GetAlertRuleResponse, error) - UpdateAlertRule(ctx context.Context, req *alertv1.UpdateAlertRuleRequest) (*alertv1.UpdateAlertRuleResponse, error) - DeleteAlertRule(ctx context.Context, req *alertv1.DeleteAlertRuleRequest) (*alertv1.DeleteAlertRuleResponse, error) - ListAlertRule(ctx context.Context, req *alertv1.ListAlertRuleRequest) (*alertv1.ListAlertRuleResponse, error) -} diff --git a/internal/localsvc/otlp.go b/internal/localsvc/otlp.go deleted file mode 100644 index 25c4ebcc..00000000 --- a/internal/localsvc/otlp.go +++ /dev/null @@ -1,182 +0,0 @@ -package localsvc - -import ( - "context" - "log/slog" - "net/http" - "time" - - otlplogssvcpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" - otlpmetricssvcpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - otlptracesvcpb "go.opentelemetry.io/proto/otlp/collector/trace/v1" -) - -var ( - // otlp compatibility - _ otlplogssvcpb.LogsServiceServer = (*LoggingOTLP)(nil) - _ otlptracesvcpb.TraceServiceServer = (*TracingOTLP)(nil) - _ otlpmetricssvcpb.MetricsServiceServer = (*MetricsOTLP)(nil) -) - -type LoggingOTLP struct { - svc *Service - otlplogssvcpb.UnimplementedLogsServiceServer -} - -func newLoggingOTLP(svc *Service) *LoggingOTLP { - return &LoggingOTLP{svc: svc} -} - -func (otlp *LoggingOTLP) Export(ctx context.Context, req *otlplogssvcpb.ExportLogsServiceRequest) (*otlplogssvcpb.ExportLogsServiceResponse, error) { - ll := otlp.svc.ll.WithGroup("OTLP.Logging.Export") - ll.InfoContext(ctx, "starting") - start := time.Now() - defer func() { ll.InfoContext(ctx, "done", slog.Duration("duration", time.Since(start))) }() - return otlp.svc.storage.ExportLogs(ctx, req) -} - -func (otlp *LoggingOTLP) ExportHTTP(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - ll := otlp.svc.ll.WithGroup("OTLP.Logging.ExportHTTP") - ll.InfoContext(ctx, "starting") - start := time.Now() - defer func() { ll.InfoContext(ctx, "done", slog.Duration("duration", time.Since(start))) }() - - enc, ok := readContentType(w, r) - if !ok { - return - } - - body, ok := readAndCloseBody(w, r, enc) - if !ok { - return - } - - otlpReq, err := enc.unmarshalLogsRequest(body) - if err != nil { - writeError(w, enc, err, http.StatusBadRequest) - return - } - - otlpResp, err := otlp.svc.storage.ExportLogs(ctx, otlpReq) - if err != nil { - writeError(w, enc, err, http.StatusInternalServerError) - return - } - - msg, err := enc.marshalLogsResponse(otlpResp) - if err != nil { - writeError(w, enc, err, http.StatusInternalServerError) - return - } - writeResponse(w, enc.contentType(), http.StatusOK, msg) - -} - -type MetricsOTLP struct { - svc *Service - otlpmetricssvcpb.UnimplementedMetricsServiceServer -} - -func newMetricsOTLP(svc *Service) *MetricsOTLP { - return &MetricsOTLP{svc: svc} -} - -func (otlp *MetricsOTLP) Export(ctx context.Context, req *otlpmetricssvcpb.ExportMetricsServiceRequest) (*otlpmetricssvcpb.ExportMetricsServiceResponse, error) { - ll := otlp.svc.ll.WithGroup("OTLP.Metrics.Export") - ll.InfoContext(ctx, "starting") - start := time.Now() - defer func() { ll.InfoContext(ctx, "done", slog.Duration("duration", time.Since(start))) }() - return otlp.svc.storage.ExportMetrics(ctx, req) -} - -func (otlp *MetricsOTLP) ExportHTTP(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - ll := otlp.svc.ll.WithGroup("OTLP.Metrics.ExportHTTP") - ll.InfoContext(ctx, "starting") - start := time.Now() - defer func() { ll.InfoContext(ctx, "done", slog.Duration("duration", time.Since(start))) }() - - enc, ok := readContentType(w, r) - if !ok { - return - } - - body, ok := readAndCloseBody(w, r, enc) - if !ok { - return - } - - otlpReq, err := enc.unmarshalMetricsRequest(body) - if err != nil { - writeError(w, enc, err, http.StatusBadRequest) - return - } - - otlpResp, err := otlp.svc.storage.ExportMetrics(ctx, otlpReq) - if err != nil { - writeError(w, enc, err, http.StatusInternalServerError) - return - } - - msg, err := enc.marshalMetricsResponse(otlpResp) - if err != nil { - writeError(w, enc, err, http.StatusInternalServerError) - return - } - writeResponse(w, enc.contentType(), http.StatusOK, msg) -} - -type TracingOTLP struct { - svc *Service - otlptracesvcpb.UnimplementedTraceServiceServer -} - -func newTracingOTLP(svc *Service) *TracingOTLP { - return &TracingOTLP{svc: svc} -} - -func (otlp *TracingOTLP) Export(ctx context.Context, req *otlptracesvcpb.ExportTraceServiceRequest) (*otlptracesvcpb.ExportTraceServiceResponse, error) { - ll := otlp.svc.ll.WithGroup("OTLP.Tracing.Export") - ll.InfoContext(ctx, "starting") - start := time.Now() - defer func() { ll.InfoContext(ctx, "done", slog.Duration("duration", time.Since(start))) }() - return otlp.svc.storage.ExportTraces(ctx, req) -} - -func (otlp *TracingOTLP) ExportHTTP(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - ll := otlp.svc.ll.WithGroup("OTLP.Tracing.ExportHTTP") - ll.InfoContext(ctx, "starting") - start := time.Now() - defer func() { ll.InfoContext(ctx, "done", slog.Duration("duration", time.Since(start))) }() - - enc, ok := readContentType(w, r) - if !ok { - return - } - - body, ok := readAndCloseBody(w, r, enc) - if !ok { - return - } - - otlpReq, err := enc.unmarshalTracesRequest(body) - if err != nil { - writeError(w, enc, err, http.StatusBadRequest) - return - } - - otlpResp, err := otlp.svc.storage.ExportTraces(ctx, otlpReq) - if err != nil { - writeError(w, enc, err, http.StatusInternalServerError) - return - } - - msg, err := enc.marshalTracesResponse(otlpResp) - if err != nil { - writeError(w, enc, err, http.StatusInternalServerError) - return - } - writeResponse(w, enc.contentType(), http.StatusOK, msg) -} diff --git a/internal/localsvc/otlp_codec.go b/internal/localsvc/otlp_codec.go deleted file mode 100644 index ebb33ae5..00000000 --- a/internal/localsvc/otlp_codec.go +++ /dev/null @@ -1,317 +0,0 @@ -package localsvc - -import ( - "fmt" - "io" - "mime" - "net/http" - "strconv" - "time" - - otlplogssvcpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" - otlpmetricssvcpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - otlpprofilevcpb "go.opentelemetry.io/proto/otlp/collector/profiles/v1development" - otlptracesvcpb "go.opentelemetry.io/proto/otlp/collector/trace/v1" - "google.golang.org/genproto/googleapis/rpc/errdetails" - spb "google.golang.org/genproto/googleapis/rpc/status" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" -) - -// everything that follows is largely lifted from: -// - github.com/open-telemetry/opentelemetry-collector/receiver/otlpreceiver - -var fallbackMsg = []byte(`{"code": 13, "message": "failed to marshal error message"}`) - -const fallbackContentType = "application/json" - -func readContentType(resp http.ResponseWriter, req *http.Request) (encoder, bool) { - if req.Method != http.MethodPost { - handleUnmatchedMethod(resp) - return nil, false - } - - switch getMimeTypeFromContentType(req.Header.Get("Content-Type")) { - case pbContentType: - return pbEncoder, true - case jsonContentType: - return jsEncoder, true - default: - handleUnmatchedContentType(resp) - return nil, false - } -} - -func readAndCloseBody(resp http.ResponseWriter, req *http.Request, enc encoder) ([]byte, bool) { - body, err := io.ReadAll(req.Body) - if err != nil { - writeError(resp, enc, err, http.StatusBadRequest) - return nil, false - } - if err = req.Body.Close(); err != nil { - writeError(resp, enc, err, http.StatusBadRequest) - return nil, false - } - return body, true -} - -// writeError encodes the HTTP error inside a rpc.Status message as required by the OTLP protocol. -func writeError(w http.ResponseWriter, encoder encoder, err error, statusCode int) { - s, ok := status.FromError(err) - if ok { - statusCode = getHTTPStatusCodeFromStatus(s) - } else { - s = newStatusFromMsgAndHTTPCode(err.Error(), statusCode) - } - writeStatusResponse(w, encoder, statusCode, s) -} - -// errorHandler encodes the HTTP error message inside a rpc.Status message as required -// by the OTLP protocol. -func errorHandler(w http.ResponseWriter, r *http.Request, errMsg string, statusCode int) { - s := newStatusFromMsgAndHTTPCode(errMsg, statusCode) - switch getMimeTypeFromContentType(r.Header.Get("Content-Type")) { - case pbContentType: - writeStatusResponse(w, pbEncoder, statusCode, s) - return - case jsonContentType: - writeStatusResponse(w, jsEncoder, statusCode, s) - return - } - writeResponse(w, fallbackContentType, http.StatusInternalServerError, fallbackMsg) -} - -func writeStatusResponse(w http.ResponseWriter, enc encoder, statusCode int, st *status.Status) { - // https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#otlphttp-throttling - if statusCode == http.StatusTooManyRequests || statusCode == http.StatusServiceUnavailable { - retryInfo := getRetryInfo(st) - // Check if server returned throttling information. - if retryInfo != nil { - // We are throttled. Wait before retrying as requested by the server. - // The value of Retry-After field can be either an HTTP-date or a number of - // seconds to delay after the response is received. See https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.3 - // - // Retry-After = HTTP-date / delay-seconds - // - // Use delay-seconds since is easier to format as well as does not require clock synchronization. - w.Header().Set("Retry-After", strconv.FormatInt(int64(retryInfo.GetRetryDelay().AsDuration()/time.Second), 10)) - } - } - msg, err := enc.marshalStatus(st.Proto()) - if err != nil { - writeResponse(w, fallbackContentType, http.StatusInternalServerError, fallbackMsg) - return - } - - writeResponse(w, enc.contentType(), statusCode, msg) -} - -func handleUnmatchedContentType(resp http.ResponseWriter) { - hst := http.StatusUnsupportedMediaType - writeResponse(resp, "text/plain", hst, []byte(fmt.Sprintf("%v unsupported media type, supported: [%s, %s]", hst, jsonContentType, pbContentType))) -} - -func writeResponse(w http.ResponseWriter, contentType string, statusCode int, msg []byte) { - w.Header().Set("Content-Type", contentType) - w.WriteHeader(statusCode) - // Nothing we can do with the error if we cannot write to the response. - _, _ = w.Write(msg) -} - -func getMimeTypeFromContentType(contentType string) string { - mediatype, _, err := mime.ParseMediaType(contentType) - if err != nil { - return "" - } - return mediatype -} - -func handleUnmatchedMethod(resp http.ResponseWriter) { - hst := http.StatusMethodNotAllowed - writeResponse(resp, "text/plain", hst, []byte(fmt.Sprintf("%v method not allowed, supported: [POST]", hst))) -} - -// newStatusFromMsgAndHTTPCode returns a gRPC status based on an error message string and a http status code. -// This function is shared between the http receiver and http exporter for error propagation. -func newStatusFromMsgAndHTTPCode(errMsg string, statusCode int) *status.Status { - var c codes.Code - // Mapping based on https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md - // 429 mapping to ResourceExhausted and 400 mapping to StatusBadRequest are exceptions. - switch statusCode { - case http.StatusBadRequest: - c = codes.InvalidArgument - case http.StatusUnauthorized: - c = codes.Unauthenticated - case http.StatusForbidden: - c = codes.PermissionDenied - case http.StatusNotFound: - c = codes.Unimplemented - case http.StatusTooManyRequests: - c = codes.ResourceExhausted - case http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout: - c = codes.Unavailable - default: - c = codes.Unknown - } - return status.New(c, errMsg) -} - -func getHTTPStatusCodeFromStatus(s *status.Status) int { - // See https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#failures - // to see if a code is retryable. - // See https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#failures-1 - // to see a list of retryable http status codes. - switch s.Code() { - // Retryable - case codes.Canceled, codes.DeadlineExceeded, codes.Aborted, codes.OutOfRange, codes.Unavailable, codes.DataLoss: - return http.StatusServiceUnavailable - // Retryable - case codes.ResourceExhausted: - return http.StatusTooManyRequests - // Not Retryable - case codes.InvalidArgument: - return http.StatusBadRequest - // Not Retryable - case codes.Unauthenticated: - return http.StatusUnauthorized - // Not Retryable - case codes.PermissionDenied: - return http.StatusForbidden - // Not Retryable - case codes.Unimplemented: - return http.StatusNotFound - // Not Retryable - default: - return http.StatusInternalServerError - } -} - -func getRetryInfo(status *status.Status) *errdetails.RetryInfo { - for _, detail := range status.Details() { - if t, ok := detail.(*errdetails.RetryInfo); ok { - return t - } - } - return nil -} - -const ( - pbContentType = "application/x-protobuf" - jsonContentType = "application/json" -) - -type encoder interface { - unmarshalTracesRequest(buf []byte) (*otlptracesvcpb.ExportTraceServiceRequest, error) - unmarshalMetricsRequest(buf []byte) (*otlpmetricssvcpb.ExportMetricsServiceRequest, error) - unmarshalLogsRequest(buf []byte) (*otlplogssvcpb.ExportLogsServiceRequest, error) - unmarshalProfilesRequest(buf []byte) (*otlpprofilevcpb.ExportProfilesServiceRequest, error) - - marshalTracesResponse(*otlptracesvcpb.ExportTraceServiceResponse) ([]byte, error) - marshalMetricsResponse(*otlpmetricssvcpb.ExportMetricsServiceResponse) ([]byte, error) - marshalLogsResponse(*otlplogssvcpb.ExportLogsServiceResponse) ([]byte, error) - marshalProfilesResponse(*otlpprofilevcpb.ExportProfilesServiceResponse) ([]byte, error) - - marshalStatus(rsp *spb.Status) ([]byte, error) - - contentType() string -} - -var ( - pbEncoder = &protoEncoder{} - jsEncoder = &jsonEncoder{} - jsonPbMarshaler = &protojson.MarshalOptions{} -) - -type protoEncoder struct{} - -func (protoEncoder) unmarshalTracesRequest(buf []byte) (*otlptracesvcpb.ExportTraceServiceRequest, error) { - req := new(otlptracesvcpb.ExportTraceServiceRequest) - return req, proto.Unmarshal(buf, req) -} - -func (protoEncoder) unmarshalMetricsRequest(buf []byte) (*otlpmetricssvcpb.ExportMetricsServiceRequest, error) { - req := new(otlpmetricssvcpb.ExportMetricsServiceRequest) - return req, proto.Unmarshal(buf, req) -} - -func (protoEncoder) unmarshalLogsRequest(buf []byte) (*otlplogssvcpb.ExportLogsServiceRequest, error) { - req := new(otlplogssvcpb.ExportLogsServiceRequest) - return req, proto.Unmarshal(buf, req) -} - -func (protoEncoder) unmarshalProfilesRequest(buf []byte) (*otlpprofilevcpb.ExportProfilesServiceRequest, error) { - req := new(otlpprofilevcpb.ExportProfilesServiceRequest) - return req, proto.Unmarshal(buf, req) -} - -func (protoEncoder) marshalTracesResponse(resp *otlptracesvcpb.ExportTraceServiceResponse) ([]byte, error) { - return proto.Marshal(resp) -} - -func (protoEncoder) marshalMetricsResponse(resp *otlpmetricssvcpb.ExportMetricsServiceResponse) ([]byte, error) { - return proto.Marshal(resp) -} - -func (protoEncoder) marshalLogsResponse(resp *otlplogssvcpb.ExportLogsServiceResponse) ([]byte, error) { - return proto.Marshal(resp) -} - -func (protoEncoder) marshalProfilesResponse(resp *otlpprofilevcpb.ExportProfilesServiceResponse) ([]byte, error) { - return proto.Marshal(resp) -} - -func (protoEncoder) marshalStatus(resp *spb.Status) ([]byte, error) { - return proto.Marshal(resp) -} - -func (protoEncoder) contentType() string { - return pbContentType -} - -type jsonEncoder struct{} - -func (jsonEncoder) unmarshalTracesRequest(buf []byte) (*otlptracesvcpb.ExportTraceServiceRequest, error) { - req := new(otlptracesvcpb.ExportTraceServiceRequest) - return req, protojson.Unmarshal(buf, req) -} - -func (jsonEncoder) unmarshalMetricsRequest(buf []byte) (*otlpmetricssvcpb.ExportMetricsServiceRequest, error) { - req := new(otlpmetricssvcpb.ExportMetricsServiceRequest) - return req, protojson.Unmarshal(buf, req) -} - -func (jsonEncoder) unmarshalLogsRequest(buf []byte) (*otlplogssvcpb.ExportLogsServiceRequest, error) { - req := new(otlplogssvcpb.ExportLogsServiceRequest) - return req, protojson.Unmarshal(buf, req) -} - -func (jsonEncoder) unmarshalProfilesRequest(buf []byte) (*otlpprofilevcpb.ExportProfilesServiceRequest, error) { - req := new(otlpprofilevcpb.ExportProfilesServiceRequest) - return req, protojson.Unmarshal(buf, req) -} - -func (jsonEncoder) marshalTracesResponse(resp *otlptracesvcpb.ExportTraceServiceResponse) ([]byte, error) { - return jsonPbMarshaler.Marshal(resp) -} - -func (jsonEncoder) marshalMetricsResponse(resp *otlpmetricssvcpb.ExportMetricsServiceResponse) ([]byte, error) { - return jsonPbMarshaler.Marshal(resp) -} - -func (jsonEncoder) marshalLogsResponse(resp *otlplogssvcpb.ExportLogsServiceResponse) ([]byte, error) { - return jsonPbMarshaler.Marshal(resp) -} - -func (jsonEncoder) marshalProfilesResponse(resp *otlpprofilevcpb.ExportProfilesServiceResponse) ([]byte, error) { - return jsonPbMarshaler.Marshal(resp) -} - -func (jsonEncoder) marshalStatus(resp *spb.Status) ([]byte, error) { - return jsonPbMarshaler.Marshal(resp) -} - -func (jsonEncoder) contentType() string { - return jsonContentType -} diff --git a/internal/localsvc/svc.go b/internal/localsvc/svc.go deleted file mode 100644 index 76d4285f..00000000 --- a/internal/localsvc/svc.go +++ /dev/null @@ -1,844 +0,0 @@ -package localsvc - -import ( - "context" - "fmt" - "log/slog" - "runtime" - "time" - - "connectrpc.com/connect" - alertv1 "github.com/minitape/api/go/svc/alert/v1" - alertpb "github.com/minitape/api/go/svc/alert/v1/alertv1connect" - dashboardv1 "github.com/minitape/api/go/svc/dashboard/v1" - dashboardpb "github.com/minitape/api/go/svc/dashboard/v1/dashboardv1connect" - igv1 "github.com/minitape/api/go/svc/ingest/v1" - igsvcpb "github.com/minitape/api/go/svc/ingest/v1/ingestv1connect" - lhv1 "github.com/minitape/api/go/svc/localhost/v1" - lhsvcpb "github.com/minitape/api/go/svc/localhost/v1/localhostv1connect" - projectv1 "github.com/minitape/api/go/svc/project/v1" - projectpb "github.com/minitape/api/go/svc/project/v1/projectv1connect" - qrv1 "github.com/minitape/api/go/svc/query/v1" - qrsvcpb "github.com/minitape/api/go/svc/query/v1/queryv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/localstate" - "github.com/humanlogio/humanlog/pkg/localstorage" - "github.com/humanlogio/humanlog/pkg/sink" - "github.com/humanlogio/humanlog/pkg/validate" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/trace" - - "google.golang.org/protobuf/types/known/timestamppb" -) - -type Service struct { - ll *slog.Logger - tracer trace.Tracer - ownVersion *typesv1.Version - storage localstorage.Storage - doLogin func(ctx context.Context, returnToURL string) error - doLogout func(ctx context.Context, returnToURL string) error - doUpdate func(ctx context.Context) error - doRestart func(ctx context.Context) error - getConfig func(ctx context.Context) (*typesv1.LocalhostConfig, error) - setConfig func(ctx context.Context, cfg *typesv1.LocalhostConfig) error - doSyncProject func(ctx context.Context) error - - db localstate.DB -} - -func New( - ll *slog.Logger, - ownVersion *typesv1.Version, - storage localstorage.Storage, - state localstate.DB, - doLogin func(ctx context.Context, returnToURL string) error, - doLogout func(ctx context.Context, returnToURL string) error, - doUpdate func(ctx context.Context) error, - doRestart func(ctx context.Context) error, - getConfig func(ctx context.Context) (*typesv1.LocalhostConfig, error), - setConfig func(ctx context.Context, cfg *typesv1.LocalhostConfig) error, - doSyncProject func(ctx context.Context) error, -) *Service { - return &Service{ - ll: ll, - tracer: otel.GetTracerProvider().Tracer("humanlog-localhost"), - ownVersion: ownVersion, - storage: storage, - doLogin: doLogin, - doLogout: doLogout, - doUpdate: doUpdate, - doRestart: doRestart, - getConfig: getConfig, - setConfig: setConfig, - db: state, - doSyncProject: doSyncProject, - } -} - -var ( - _ lhsvcpb.LocalhostServiceHandler = (*Service)(nil) - _ igsvcpb.IngestServiceHandler = (*Service)(nil) - _ qrsvcpb.QueryServiceHandler = (*Service)(nil) - _ qrsvcpb.TraceServiceHandler = (*Service)(nil) - _ projectpb.ProjectServiceHandler = (*Service)(nil) - _ dashboardpb.DashboardServiceHandler = (*Service)(nil) - _ alertpb.AlertServiceHandler = (*Service)(nil) -) - -func (svc *Service) AsLoggingOTLP() *LoggingOTLP { return newLoggingOTLP(svc) } -func (svc *Service) AsTracingOTLP() *TracingOTLP { return newTracingOTLP(svc) } -func (svc *Service) AsMetricsOTLP() *MetricsOTLP { return newMetricsOTLP(svc) } - -func (svc *Service) Ping(ctx context.Context, req *connect.Request[lhv1.PingRequest]) (*connect.Response[lhv1.PingResponse], error) { - res := &lhv1.PingResponse{ - ClientVersion: svc.ownVersion, - Architecture: runtime.GOARCH, - OperatingSystem: runtime.GOOS, - Meta: &typesv1.ResMeta{}, - } - return connect.NewResponse(res), nil -} - -func (svc *Service) PingStream(ctx context.Context, req *connect.Request[lhv1.PingRequest], srv *connect.ServerStream[lhv1.PingResponse]) error { - res := &lhv1.PingResponse{ - ClientVersion: svc.ownVersion, - Architecture: runtime.GOARCH, - OperatingSystem: runtime.GOOS, - Meta: &typesv1.ResMeta{}, - } - - ticker := time.NewTicker(5 * time.Second) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return nil - case <-ticker.C: - if err := srv.Send(res); err != nil { - return connect.NewError(connect.CodeInternal, fmt.Errorf("can't sent to client: %v", err)) - } - } - } -} - -func (svc *Service) DoLogin(ctx context.Context, req *connect.Request[lhv1.DoLoginRequest]) (*connect.Response[lhv1.DoLoginResponse], error) { - err := svc.doLogin(ctx, req.Msg.ReturnToURL) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to login: %v", err)) - } - out := &lhv1.DoLoginResponse{} - return connect.NewResponse(out), nil -} - -func (svc *Service) DoLogout(ctx context.Context, req *connect.Request[lhv1.DoLogoutRequest]) (*connect.Response[lhv1.DoLogoutResponse], error) { - err := svc.doLogout(ctx, req.Msg.ReturnToURL) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to logout: %v", err)) - } - out := &lhv1.DoLogoutResponse{} - return connect.NewResponse(out), nil -} - -func (svc *Service) DoUpdate(ctx context.Context, req *connect.Request[lhv1.DoUpdateRequest]) (*connect.Response[lhv1.DoUpdateResponse], error) { - err := svc.doUpdate(ctx) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to update: %v", err)) - } - out := &lhv1.DoUpdateResponse{} - return connect.NewResponse(out), nil -} - -func (svc *Service) DoRestart(ctx context.Context, req *connect.Request[lhv1.DoRestartRequest]) (*connect.Response[lhv1.DoRestartResponse], error) { - err := svc.doRestart(ctx) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to restart: %v", err)) - } - out := &lhv1.DoRestartResponse{} - return connect.NewResponse(out), nil -} - -func (svc *Service) GetConfig(ctx context.Context, req *connect.Request[lhv1.GetConfigRequest]) (*connect.Response[lhv1.GetConfigResponse], error) { - cfg, err := svc.getConfig(ctx) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to get config: %v", err)) - } - out := &lhv1.GetConfigResponse{Config: cfg} - return connect.NewResponse(out), nil -} - -func (svc *Service) SetConfig(ctx context.Context, req *connect.Request[lhv1.SetConfigRequest]) (*connect.Response[lhv1.SetConfigResponse], error) { - if err := svc.setConfig(ctx, req.Msg.Config); err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to set config: %v", err)) - } - out := &lhv1.SetConfigResponse{} - return connect.NewResponse(out), nil -} - -func (svc *Service) GetStats(ctx context.Context, req *connect.Request[lhv1.GetStatsRequest]) (*connect.Response[lhv1.GetStatsResponse], error) { - var databaseStats *typesv1.DatabaseStats - err := svc.storage.ReportMetrics(ctx, func(ctx context.Context, public *typesv1.DatabaseStats, internal *localstorage.InternalMetrics, details any) error { - databaseStats = public - return nil - }) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to get database stats: %v", err)) - } - out := &lhv1.GetStatsResponse{DatabaseStats: databaseStats} - return connect.NewResponse(out), nil -} - -func (svc *Service) Ingest(ctx context.Context, req *connect.Request[igv1.IngestRequest]) (*connect.Response[igv1.IngestResponse], error) { - ll := svc.ll - msg := req.Msg - resource := msg.Resource - scope := msg.Scope - msg.Logs = fixEventsTimestamps(ctx, ll, msg.Logs) - - snk, err := svc.storage.SinkFor(ctx, resource, scope) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, err) - } - success := false - defer func() { - if success { - return - } - err = snk.Close(ctx) - if err != nil { - ll.ErrorContext(ctx, "closing sink", slog.Any("err", err)) - } - }() - - if bsnk, ok := snk.(sink.BatchSink); ok { - if err := bsnk.ReceiveBatch(ctx, msg.Logs); err != nil { - ll.ErrorContext(ctx, "ingesting log batch", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("ingesting log batch: %v", err)) - } - } else { - for _, ev := range msg.Logs { - if err := snk.Receive(ctx, ev); err != nil { - ll.ErrorContext(ctx, "ingesting log", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("ingesting log: %v", err)) - } - } - } - if err = snk.Close(ctx); err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("closing sink log: %v", err)) - } - out := &igv1.IngestResponse{} - return connect.NewResponse(out), nil -} - -func fixEventsTimestamps(ctx context.Context, ll *slog.Logger, evs []*typesv1.Log) []*typesv1.Log { - for i, ev := range evs { - evs[i] = fixEventTimestamps(ctx, ll, ev) - } - return evs -} - -func fixEventTimestamps(ctx context.Context, ll *slog.Logger, ev *typesv1.Log) *typesv1.Log { - if ev.ObservedTimestamp != nil && ev.ObservedTimestamp.Seconds < 0 { - ev.ObservedTimestamp = timestamppb.Now() - ll.ErrorContext(ctx, "client is sending invalid parsedat") - } - if ev.Timestamp != nil && ev.Timestamp.Seconds < 0 { - ev.Timestamp = ev.ObservedTimestamp - ll.ErrorContext(ctx, "client is sending invalid timestamp") - } - return ev -} - -func (svc *Service) IngestStream(ctx context.Context, req *connect.ClientStream[igv1.IngestStreamRequest]) (*connect.Response[igv1.IngestStreamResponse], error) { - ll := svc.ll - - var ( - resource *typesv1.Resource - scope *typesv1.Scope - ) - - // get the first message which has the metadata to start ingesting - if !req.Receive() { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("must contain at least a first request")) - } - msg := req.Msg() - resource = msg.Resource - scope = msg.Scope - ll.DebugContext(ctx, "receiving data from stream") - snk, err := svc.storage.SinkFor(ctx, resource, scope) - if err != nil { - ll.ErrorContext(ctx, "obtaining sink for stream", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("obtaining sink for stream: %v", err)) - } - defer func() { - if ferr := snk.Close(ctx); ferr != nil { - if err == nil { - err = ferr - } else { - ll.ErrorContext(ctx, "erroneous exit and also failed to flush", slog.Any("err", err)) - } - } - }() - - if bsnk, ok := snk.(sink.BatchSink); ok { - // ingest the first message - msg.Logs = fixEventsTimestamps(ctx, ll, msg.Logs) - if err := bsnk.ReceiveBatch(ctx, msg.Logs); err != nil { - ll.ErrorContext(ctx, "ingesting log batch", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("ingesting log batch: %v", err)) - } - // then wait for more - for req.Receive() { - msg := req.Msg() - msg.Logs = fixEventsTimestamps(ctx, ll, msg.Logs) - if err := bsnk.ReceiveBatch(ctx, msg.Logs); err != nil { - ll.ErrorContext(ctx, "ingesting log batch", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("ingesting log batch: %v", err)) - } - } - } else { - // ingest the first message - msg.Logs = fixEventsTimestamps(ctx, ll, msg.Logs) - for _, ev := range msg.Logs { - if err := snk.Receive(ctx, ev); err != nil { - ll.ErrorContext(ctx, "ingesting log", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("ingesting log: %v", err)) - } - } - // then wait for more - for req.Receive() { - msg := req.Msg() - msg.Logs = fixEventsTimestamps(ctx, ll, msg.Logs) - for _, ev := range msg.Logs { - if ev.ObservedTimestamp != nil && ev.ObservedTimestamp.Seconds < 0 { - ev.ObservedTimestamp = timestamppb.Now() - ll.ErrorContext(ctx, "client is sending invalid parsedat", slog.Any("err", err)) - } - if ev != nil && ev.Timestamp != nil && ev.Timestamp.Seconds < 0 { - ev.Timestamp = ev.ObservedTimestamp - ll.ErrorContext(ctx, "client is sending invalid timestamp", slog.Any("err", err)) - } - if err := snk.Receive(ctx, ev); err != nil { - ll.ErrorContext(ctx, "ingesting log", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("ingesting log: %v", err)) - } - } - } - } - if err := req.Err(); err != nil { - ll.ErrorContext(ctx, "ingesting localhost stream", slog.Any("err", err)) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("ingesting localhost stream: %v", err)) - } - res := &igv1.IngestStreamResponse{} - return connect.NewResponse(res), nil -} - -func (svc *Service) SummarizeEvents(ctx context.Context, req *connect.Request[qrv1.SummarizeEventsRequest]) (*connect.Response[qrv1.SummarizeEventsResponse], error) { - if req.Msg.From == nil { - req.Msg.From = timestamppb.New(time.Now().Add(-time.Minute)) - } - if req.Msg.To == nil { - req.Msg.To = timestamppb.Now() - } - if req.Msg.BucketCount < 1 { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("bucket count must be greater than 1")) - } - ll := svc.ll.With( - slog.Time("from", req.Msg.From.AsTime()), - slog.Time("to", req.Msg.From.AsTime()), - slog.Int("bucket_count", int(req.Msg.BucketCount)), - slog.Int("environment_id", int(req.Msg.EnvironmentId)), - ) - - period := req.Msg.To.AsTime().Sub(req.Msg.From.AsTime()) - bucketWidth := period / time.Duration(req.Msg.BucketCount) - - data, _, _, err := svc.storage.Query(ctx, &typesv1.Query{ - Timerange: &typesv1.Timerange{ - From: typesv1.ExprLiteral(typesv1.ValTimestamp(req.Msg.From)), - To: typesv1.ExprLiteral(typesv1.ValTimestamp(req.Msg.To)), - }, - Query: &typesv1.Statements{ - Statements: []*typesv1.Statement{ - { - Stmt: &typesv1.Statement_Summarize{ - Summarize: &typesv1.SummarizeOperator{ - Parameters: &typesv1.SummarizeOperator_Parameters{ - Parameters: []*typesv1.SummarizeOperator_Parameter{ - {AggregateFunction: &typesv1.FuncCall{Name: "count"}}, - }, - }, - ByGroupExpressions: &typesv1.SummarizeOperator_ByGroupExpressions{ - Groups: []*typesv1.SummarizeOperator_ByGroupExpression{ - { - Scalar: typesv1.ExprFuncCall("bin", - typesv1.ExprIdentifier("_indextime"), - typesv1.ExprLiteral(typesv1.ValDuration(bucketWidth)), - ), - }, - }, - }, - }, - }, - }, - }, - }, - }, nil, int(req.Msg.BucketCount)) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("summarizing local storage: %v", err)) - } - ll.DebugContext(ctx, "queried") - - freeform, ok := data.Shape.(*typesv1.Data_FreeForm) - if !ok { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("expected table data, got %T", data.Shape)) - } - table := freeform.FreeForm - header := table.Type - if len(header.Columns) != 2 { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("expected 2 columns in table, got %d", len(header.Columns))) - } - if sc := header.Columns[0].Type.GetScalar(); sc != typesv1.ScalarType_ts { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("expected 1st column to be a timestamp, got %v", header.Columns[0].Type)) - } - if sc := header.Columns[1].Type.GetScalar(); sc != typesv1.ScalarType_i64 { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("expected 2nd column to be an i64, got %v", header.Columns[1].Type)) - } - - out := &qrv1.SummarizeEventsResponse{} - for _, row := range table.Rows { - ts := row.Items[0].GetTs() - count := row.Items[1].GetI64() - out.Buckets = append(out.Buckets, &qrv1.SummarizeEventsResponse_Bucket{ - Ts: ts, - EventCount: uint64(count), - }) - } - ll.DebugContext(ctx, "non-zero buckets filled", slog.Int("buckets_len", len(out.Buckets))) - return connect.NewResponse(out), nil -} - -func (svc *Service) Parse(ctx context.Context, req *connect.Request[qrv1.ParseRequest]) (*connect.Response[qrv1.ParseResponse], error) { - query := req.Msg.GetQuery() - - q, err := svc.storage.Parse(ctx, query) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("parsing query: %v", err)) - } - dst, err := svc.storage.ResolveQueryType(ctx, q) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("resolving query's data type: %v", err)) - } - out := &qrv1.ParseResponse{Query: q, DataType: dst} - return connect.NewResponse(out), nil -} - -func (svc *Service) Format(ctx context.Context, req *connect.Request[qrv1.FormatRequest]) (*connect.Response[qrv1.FormatResponse], error) { - query := req.Msg.GetQuery() - - var parsed *typesv1.Query - switch q := query.(type) { - case *qrv1.FormatRequest_Parsed: - parsed = q.Parsed - case *qrv1.FormatRequest_Raw: - v, err := svc.storage.Parse(ctx, q.Raw) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("parsing query: %v", err)) - } - parsed = v - - default: - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("unsupported query option %T", q)) - } - - formatted, err := svc.storage.Format(ctx, parsed) - if err != nil { - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("formatting query: %v", err)) - } - - out := &qrv1.FormatResponse{Formatted: formatted} - return connect.NewResponse(out), nil -} - -func (svc *Service) Query(ctx context.Context, req *connect.Request[qrv1.QueryRequest]) (*connect.Response[qrv1.QueryResponse], error) { - if req.Msg.Limit < 1 { - req.Msg.Limit = 1000 // default is 1000 - } - if req.Msg.Limit < 10 { - req.Msg.Limit = 10 // minimum is 10 - } - query := req.Msg.GetQuery() - if query == nil { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("required: `query`")) - } - - var opts []localstorage.QueryOption - if req.Msg.IncludeDetailedProfiling != nil { - opts = append(opts, localstorage.QueryWithProfiling(*req.Msg.IncludeDetailedProfiling)) - } - - data, cursor, metrics, err := svc.storage.Query(ctx, query, req.Msg.Cursor, int(req.Msg.Limit), opts...) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("querying local storage: %v", err)) - } - out := &qrv1.QueryResponse{ - Next: cursor, - Data: data, - Metrics: metrics, - } - return connect.NewResponse(out), nil -} - -func (svc *Service) Stream(ctx context.Context, req *connect.Request[qrv1.StreamRequest], srv *connect.ServerStream[qrv1.StreamResponse]) error { - query := req.Msg.GetQuery() - if query == nil { - return connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("required: `query`")) - } - - batchSize, err := validate.StreamResolveBatchSize(int(req.Msg.MaxBatchSize)) - if err != nil { - return connect.NewError(connect.CodeInvalidArgument, err) - } - ticker, doneTicker, err := validate.StreamResolveBatchTicker(req.Msg.MaxBatchingFor) - if err != nil { - return connect.NewError(connect.CodeInvalidArgument, err) - } - defer doneTicker() - - opts := &localstorage.StreamOption{ - BatchSize: batchSize, - BatchTrigger: ticker, - } - - err = svc.storage.Stream(ctx, query, func(ctx context.Context, d *typesv1.Data) (bool, error) { - return true, srv.Send(&qrv1.StreamResponse{Data: d}) - }, opts) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - return cerr - } - return connect.NewError(connect.CodeInternal, fmt.Errorf("streaming from local storage: %v", err)) - } - return nil -} - -func (svc *Service) GetTrace(ctx context.Context, req *connect.Request[qrv1.GetTraceRequest]) (*connect.Response[qrv1.GetTraceResponse], error) { - ctx, span := svc.tracer.Start(ctx, "localsvc.GetTrace") - defer span.End() - var ( - trace *typesv1.Trace - err error - ) - switch by := req.Msg.By.(type) { - case *qrv1.GetTraceRequest_TraceId: - span.SetAttributes(attribute.String("by.trace_id", by.TraceId)) - traceID, perr := typesv1.TraceIDFromHex(nil, by.TraceId) - if perr != nil { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("invalid trace ID: %v", err)) - } - trace, err = svc.storage.GetTraceByID(ctx, traceID) - case *qrv1.GetTraceRequest_SpanId: - span.SetAttributes(attribute.String("by.span_id", by.SpanId)) - spanID, perr := typesv1.SpanIDFromHex(nil, by.SpanId) - if perr != nil { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("invalid span ID: %v", err)) - } - trace, err = svc.storage.GetTraceBySpanID(ctx, spanID) - } - if err != nil { - span.SetStatus(codes.Error, err.Error()) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("getting trace from localstorage: %v", err)) - } - if trace == nil { - return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("no such trace ")) - } - span.SetStatus(codes.Ok, "trace found") - out := &qrv1.GetTraceResponse{Trace: trace} - return connect.NewResponse(out), nil -} - -func (svc *Service) GetSpan(ctx context.Context, req *connect.Request[qrv1.GetSpanRequest]) (*connect.Response[qrv1.GetSpanResponse], error) { - ctx, span := svc.tracer.Start(ctx, "localsvc.GetSpan", trace.WithAttributes( - attribute.String("span_id", req.Msg.SpanId), - )) - defer span.End() - - spanID, err := typesv1.SpanIDFromHex(nil, req.Msg.SpanId) - if err != nil { - return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("invalid span ID: %v", err)) - } - - sp, err := svc.storage.GetSpanByID(ctx, spanID) - if err != nil { - span.SetStatus(codes.Error, err.Error()) - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("getting span from localstorage: %v", err)) - } - if sp == nil { - return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("no span with ID %x", req.Msg.SpanId)) - } - span.SetStatus(codes.Ok, "span found") - out := &qrv1.GetSpanResponse{Span: sp} - return connect.NewResponse(out), nil -} - -func (svc *Service) ListSymbols(ctx context.Context, req *connect.Request[qrv1.ListSymbolsRequest]) (*connect.Response[qrv1.ListSymbolsResponse], error) { - if req.Msg.Limit < 1 { - req.Msg.Limit = 1000 // default is 1000 - } - if req.Msg.Limit < 10 { - req.Msg.Limit = 10 // minimum is 10 - } - symbols, next, err := svc.storage.ListSymbols(ctx, nil, req.Msg.Cursor, int(req.Msg.Limit)) - if err != nil { - if cerr, ok := err.(*connect.Error); ok { - return nil, cerr - } - return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("querying local storage: %v", err)) - } - out := &qrv1.ListSymbolsResponse{ - Next: next, - Items: make([]*qrv1.ListSymbolsResponse_ListItem, 0, len(symbols)), - } - for _, sym := range symbols { - out.Items = append(out.Items, &qrv1.ListSymbolsResponse_ListItem{ - Symbol: sym, - }) - } - return connect.NewResponse(out), nil -} - -func (svc *Service) CreateProject(ctx context.Context, req *connect.Request[projectv1.CreateProjectRequest]) (*connect.Response[projectv1.CreateProjectResponse], error) { - msg := req.Msg - out, err := svc.db.CreateProject(ctx, msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) ValidateProject(ctx context.Context, req *connect.Request[projectv1.ValidateProjectRequest]) (*connect.Response[projectv1.ValidateProjectResponse], error) { - msg := req.Msg - out, err := svc.db.ValidateProject(ctx, msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) GetProject(ctx context.Context, req *connect.Request[projectv1.GetProjectRequest]) (*connect.Response[projectv1.GetProjectResponse], error) { - msg := req.Msg - out, err := svc.db.GetProject(ctx, msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) SyncProject(ctx context.Context, req *connect.Request[projectv1.SyncProjectRequest]) (*connect.Response[projectv1.SyncProjectResponse], error) { - msg := req.Msg - out, err := svc.db.SyncProject(ctx, msg) - if err != nil { - return nil, err - } - - // Trigger alert scheduler reconciliation if configured - if svc.doSyncProject != nil { - if err := svc.doSyncProject(ctx); err != nil { - svc.ll.WarnContext(ctx, "failed to trigger alert reconciliation after SyncProject", slog.Any("err", err)) - } - } - - return connect.NewResponse(out), nil -} - -func (svc *Service) UpdateProject(ctx context.Context, req *connect.Request[projectv1.UpdateProjectRequest]) (*connect.Response[projectv1.UpdateProjectResponse], error) { - msg := req.Msg - out, err := svc.db.UpdateProject(ctx, msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) DeleteProject(ctx context.Context, req *connect.Request[projectv1.DeleteProjectRequest]) (*connect.Response[projectv1.DeleteProjectResponse], error) { - msg := req.Msg - out, err := svc.db.DeleteProject(ctx, msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) ListProject(ctx context.Context, req *connect.Request[projectv1.ListProjectRequest]) (*connect.Response[projectv1.ListProjectResponse], error) { - msg := req.Msg - out, err := svc.db.ListProject(ctx, msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) CreateDashboard(ctx context.Context, req *connect.Request[dashboardv1.CreateDashboardRequest]) (*connect.Response[dashboardv1.CreateDashboardResponse], error) { - msg := req.Msg - out, err := svc.db.CreateDashboard(ctx, msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) GetDashboard(ctx context.Context, req *connect.Request[dashboardv1.GetDashboardRequest]) (*connect.Response[dashboardv1.GetDashboardResponse], error) { - out, err := svc.db.GetDashboard(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) UpdateDashboard(ctx context.Context, req *connect.Request[dashboardv1.UpdateDashboardRequest]) (*connect.Response[dashboardv1.UpdateDashboardResponse], error) { - out, err := svc.db.UpdateDashboard(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) DeleteDashboard(ctx context.Context, req *connect.Request[dashboardv1.DeleteDashboardRequest]) (*connect.Response[dashboardv1.DeleteDashboardResponse], error) { - out, err := svc.db.DeleteDashboard(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) ListDashboard(ctx context.Context, req *connect.Request[dashboardv1.ListDashboardRequest]) (*connect.Response[dashboardv1.ListDashboardResponse], error) { - out, err := svc.db.ListDashboard(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) CreateAlertGroup(ctx context.Context, req *connect.Request[alertv1.CreateAlertGroupRequest]) (*connect.Response[alertv1.CreateAlertGroupResponse], error) { - out, err := svc.db.CreateAlertGroup(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), err -} - -func (svc *Service) GetAlertGroup(ctx context.Context, req *connect.Request[alertv1.GetAlertGroupRequest]) (*connect.Response[alertv1.GetAlertGroupResponse], error) { - out, err := svc.db.GetAlertGroup(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), err -} -func (svc *Service) UpdateAlertGroup(ctx context.Context, req *connect.Request[alertv1.UpdateAlertGroupRequest]) (*connect.Response[alertv1.UpdateAlertGroupResponse], error) { - out, err := svc.db.UpdateAlertGroup(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), err -} -func (svc *Service) DeleteAlertGroup(ctx context.Context, req *connect.Request[alertv1.DeleteAlertGroupRequest]) (*connect.Response[alertv1.DeleteAlertGroupResponse], error) { - out, err := svc.db.DeleteAlertGroup(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), err -} -func (svc *Service) ListAlertGroup(ctx context.Context, req *connect.Request[alertv1.ListAlertGroupRequest]) (*connect.Response[alertv1.ListAlertGroupResponse], error) { - out, err := svc.db.ListAlertGroup(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), err -} - -func (svc *Service) CreateAlertRule(ctx context.Context, req *connect.Request[alertv1.CreateAlertRuleRequest]) (*connect.Response[alertv1.CreateAlertRuleResponse], error) { - out, err := svc.db.CreateAlertRule(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) GetAlertRule(ctx context.Context, req *connect.Request[alertv1.GetAlertRuleRequest]) (*connect.Response[alertv1.GetAlertRuleResponse], error) { - out, err := svc.db.GetAlertRule(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) UpdateAlertRule(ctx context.Context, req *connect.Request[alertv1.UpdateAlertRuleRequest]) (*connect.Response[alertv1.UpdateAlertRuleResponse], error) { - out, err := svc.db.UpdateAlertRule(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) DeleteAlertRule(ctx context.Context, req *connect.Request[alertv1.DeleteAlertRuleRequest]) (*connect.Response[alertv1.DeleteAlertRuleResponse], error) { - out, err := svc.db.DeleteAlertRule(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} - -func (svc *Service) ListAlertRule(ctx context.Context, req *connect.Request[alertv1.ListAlertRuleRequest]) (*connect.Response[alertv1.ListAlertRuleResponse], error) { - out, err := svc.db.ListAlertRule(ctx, req.Msg) - if err != nil { - return nil, err - } - return connect.NewResponse(out), nil -} diff --git a/internal/pkg/absfs/fs.go b/internal/pkg/absfs/fs.go deleted file mode 100644 index 908a4fb9..00000000 --- a/internal/pkg/absfs/fs.go +++ /dev/null @@ -1,21 +0,0 @@ -package absfs - -import ( - "io/fs" - "os" - "strings" -) - -type AbsFS struct { - root string - fs.FS -} - -func New(root string) *AbsFS { - return &AbsFS{root: root, FS: os.DirFS(root)} -} - -func (a *AbsFS) Open(name string) (fs.File, error) { - name = strings.TrimPrefix(name, a.root) - return a.FS.Open(name) -} diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index c3da0fd5..2ad0e4f3 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -6,16 +6,13 @@ import ( "fmt" "os" "path/filepath" - "slices" "strings" "time" typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/state" "github.com/humanlogio/humanlog/pkg/sink/stdiosink" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" - structpb "google.golang.org/protobuf/types/known/structpb" ) func init() { @@ -23,32 +20,9 @@ func init() { if err != nil { panic(err) } - _, err = GetDefaultLocalhostConfig() - if err != nil { - panic(err) - } } -const ( - runLocalhostByDefault = false - sendLogsToCloudByDefault = false -) - func GetDefaultConfig(releaseChannel string) (*Config, error) { - var ( - serveLocalhostCfg *typesv1.ServeLocalhostConfig - sendLogsToCloud *bool - err error - ) - if runLocalhostByDefault { - serveLocalhostCfg, err = GetDefaultLocalhostConfig() - if err != nil { - return nil, err - } - } - if sendLogsToCloudByDefault { - sendLogsToCloud = ptr(true) - } return &Config{ Version: currentConfigVersion, CurrentConfig: &typesv1.LocalhostConfig{ @@ -84,43 +58,13 @@ func GetDefaultConfig(releaseChannel string) (*Config, error) { SkipCheckForUpdates: ptr(false), Features: &typesv1.RuntimeConfig_Features{}, ExperimentalFeatures: &typesv1.RuntimeConfig_ExperimentalFeatures{ - ReleaseChannel: &releaseChannel, - SendLogsToCloud: sendLogsToCloud, - ServeLocalhost: serveLocalhostCfg, - Projects: &typesv1.ProjectsConfig{}, + ReleaseChannel: &releaseChannel, }, }, }, }, nil } -func GetDefaultLocalhostConfig() (*typesv1.ServeLocalhostConfig, error) { - stateDir, err := state.GetDefaultStateDirpath() - if err != nil { - return nil, err - } - dbpath := filepath.Join(stateDir, "data", "db.humanlog") - logDir := filepath.Join(stateDir, "logs") - - engineConfig, err := structpb.NewStruct(map[string]any{ - "path": dbpath, - }) - if err != nil { - return nil, err - } - return &typesv1.ServeLocalhostConfig{ - Port: 32764, - Engine: "advanced", - EngineConfig: engineConfig, - ShowInSystray: ptr(true), - LogDir: ptr(logDir), - Otlp: &typesv1.ServeLocalhostConfig_OTLP{ - GrpcPort: 4317, - HttpPort: 4318, - }, - }, nil -} - func GetDefaultConfigFilepath() (string, error) { home, err := os.UserHomeDir() if err != nil { @@ -523,10 +467,10 @@ func mergeRuntimeExperimentalFeatures(prev, next *typesv1.RuntimeConfig_Experime out.SendLogsToCloud = next.SendLogsToCloud } if next.ServeLocalhost != nil { - out.ServeLocalhost = mergeRuntimeServeLocalhostConfig(prev.GetServeLocalhost(), next.ServeLocalhost) + out.ServeLocalhost = proto.Clone(next.ServeLocalhost).(*typesv1.ServeLocalhostConfig) } if next.Projects != nil { - out.Projects = mergeRuntimeProjectsConfig(prev.GetProjects(), next.Projects) + out.Projects = proto.Clone(next.Projects).(*typesv1.ProjectsConfig) } return out } @@ -545,56 +489,6 @@ func mergeRuntimeClientConfig(prev, next *typesv1.RuntimeConfig_ClientConfig) *t return out } -func mergeRuntimeServeLocalhostConfig(prev, next *typesv1.ServeLocalhostConfig) *typesv1.ServeLocalhostConfig { - out := proto.Clone(prev).(*typesv1.ServeLocalhostConfig) - if out == nil { - out = new(typesv1.ServeLocalhostConfig) - } - // next overrides everything, but not - // - ShowInSystray - // - LogDir - out.Port = next.Port - out.Engine = next.Engine - out.EngineConfig = next.EngineConfig - if next.ShowInSystray != nil { - out.ShowInSystray = next.ShowInSystray - } - if next.LogDir != nil { - out.LogDir = next.LogDir - } - if next.Otlp != nil { - out.Otlp = mergeRuntimeServeLocalhostConfigOltp(prev.GetOtlp(), next.Otlp) - } - return out -} - -func mergeRuntimeServeLocalhostConfigOltp(prev, next *typesv1.ServeLocalhostConfig_OTLP) *typesv1.ServeLocalhostConfig_OTLP { - out := proto.Clone(prev).(*typesv1.ServeLocalhostConfig_OTLP) - if out == nil { - out = new(typesv1.ServeLocalhostConfig_OTLP) - } - out.GrpcPort = next.GrpcPort - out.HttpPort = next.HttpPort - return out -} - -func mergeRuntimeProjectsConfig(prev, next *typesv1.ProjectsConfig) *typesv1.ProjectsConfig { - out := proto.Clone(prev).(*typesv1.ProjectsConfig) - if out == nil { - out = new(typesv1.ProjectsConfig) - } - out.Projects = mergeRuntimeProjectsConfig_Pointer(prev.Projects, next.Projects) - return out -} - -func mergeRuntimeProjectsConfig_Pointer(prev, next []*typesv1.ProjectsConfig_Project) []*typesv1.ProjectsConfig_Project { - out := slices.Concat(prev, next) - slices.SortFunc(out, func(a, b *typesv1.ProjectsConfig_Project) int { - return strings.Compare(a.Name, b.Name) - }) - return out -} - func ParseColorMode(colorMode string) (typesv1.FormatConfig_ColorMode, error) { switch strings.ToLower(colorMode) { case "on", "always", "force", "true", "yes", "1": diff --git a/internal/pkg/iterapi/iter.go b/internal/pkg/iterapi/iter.go deleted file mode 100644 index 8fe84593..00000000 --- a/internal/pkg/iterapi/iter.go +++ /dev/null @@ -1,71 +0,0 @@ -package iterapi - -import ( - "context" - - typesv1 "github.com/minitape/api/go/types/v1" -) - -type Lister[Elem any] func(ctx context.Context, cursor *typesv1.Cursor, limit int32) ([]Elem, *typesv1.Cursor, error) - -type Iter[Elem any] struct { - ctx context.Context - lister Lister[Elem] - limit int32 - - i int - items []Elem - cursor *typesv1.Cursor - err error -} - -func New[Elem any](ctx context.Context, limit int32, lister Lister[Elem]) *Iter[Elem] { - return &Iter[Elem]{ - ctx: ctx, - lister: lister, - limit: limit, - } -} - -func (iter *Iter[Elem]) Next() bool { - - if iter.i == -1 || // first call - iter.i+1 >= len(iter.items) { // or reached last item - - if len(iter.items) > 0 && len(iter.items) < int(iter.limit) { - // last list call returned less than limit - return false - } - iter.items, iter.cursor, iter.err = iter.lister(iter.ctx, iter.cursor, iter.limit) - if iter.err != nil { - return false - } - if len(iter.items) == 0 { - return false - } - iter.i = 0 - } else { - iter.i++ - } - - return true -} - -func (iter *Iter[Elem]) Current() Elem { - return iter.items[iter.i] -} - -func (iter *Iter[Elem]) Err() error { - return iter.err -} - -func Find[Elem any](iter *Iter[Elem], lookup func(Elem) bool) (Elem, bool, error) { - for iter.Next() { - cur := iter.Current() - if lookup(cur) { - return cur, true, nil - } - } - var e Elem - return e, false, iter.Err() -} diff --git a/pkg/localstorage/queryable.go b/pkg/localstorage/queryable.go deleted file mode 100644 index dc12fdce..00000000 --- a/pkg/localstorage/queryable.go +++ /dev/null @@ -1,152 +0,0 @@ -package localstorage - -import ( - "context" - "fmt" - "log/slog" - "time" - - "github.com/minitape/api/go/svc/feature/v1/featurev1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/internal/pkg/config" - "github.com/humanlogio/humanlog/internal/pkg/state" - "github.com/humanlogio/humanlog/pkg/sink" - otlplogssvcpb "go.opentelemetry.io/proto/otlp/collector/logs/v1" - otlpmetricssvcpb "go.opentelemetry.io/proto/otlp/collector/metrics/v1" - otlptracesvcpb "go.opentelemetry.io/proto/otlp/collector/trace/v1" -) - -type AppCtx struct { - Version string - EnsureLoggedIn func(ctx context.Context) error - Features featurev1connect.FeatureServiceClient - Config *config.Config - State *state.State -} - -type StorageBuilder func( - ctx context.Context, - ll *slog.Logger, - cfg map[string]interface{}, - app *AppCtx, -) (Storage, error) - -var registry = make(map[string]StorageBuilder) - -func RegisterStorage(name string, builder StorageBuilder) { - _, ok := registry[name] - if ok { - panic(fmt.Sprintf("already used: %q", name)) - } - registry[name] = builder -} - -func Open(ctx context.Context, name string, ll *slog.Logger, cfg map[string]interface{}, app *AppCtx) (Storage, error) { - builder, ok := registry[name] - if !ok { - return nil, fmt.Errorf("no storage engine with name %q", name) - } - return builder(ctx, ll, cfg, app) -} - -type InternalMetrics struct { -} - -type MetricsReporterFunc func( - ctx context.Context, - public *typesv1.DatabaseStats, - internal *InternalMetrics, - details any, -) error - -type Storage interface { - Queryable - SinkFor(ctx context.Context, res *typesv1.Resource, scope *typesv1.Scope) (_ sink.Sink, _ error) - ReportMetrics(ctx context.Context, report MetricsReporterFunc) error - // TODO: uncomment the line below when storage implementation ready for this method - // Trim(ctx context.Context, opts TrimOptions) (logsTrimmed uint64, spansTrimmed uint64, metricsTrimmed uint64, _ error) - Close() error - - OTLPLogger - OTLPTracer - OTLPMeter - - Alertable -} - -type Alertable interface { - AlertGetOrCreate(ctx context.Context, stackName, groupName, alertName string, create func() *typesv1.AlertRuleStatus) (*typesv1.AlertRuleStatus, error) - AlertUpdateState(ctx context.Context, stackName, groupName, alertName string, state *typesv1.AlertRuleStatus) error - AlertDeleteStateNotInList(ctx context.Context, stackName, groupName string, keeplist []string) error -} - -type OTLPLogger interface { - ExportLogs(ctx context.Context, req *otlplogssvcpb.ExportLogsServiceRequest) (*otlplogssvcpb.ExportLogsServiceResponse, error) -} - -type OTLPTracer interface { - ExportTraces(ctx context.Context, req *otlptracesvcpb.ExportTraceServiceRequest) (*otlptracesvcpb.ExportTraceServiceResponse, error) -} - -type OTLPMeter interface { - ExportMetrics(ctx context.Context, req *otlpmetricssvcpb.ExportMetricsServiceRequest) (*otlpmetricssvcpb.ExportMetricsServiceResponse, error) -} - -type StreamOption struct { - BatchSize int - BatchTrigger <-chan time.Time - NotifyStreamListening func(ctx context.Context) -} - -type QueryConfig struct { - ProfilingEnabled bool - GeneratedIRCallback func(string) -} -type QueryOption func(*QueryConfig) - -func QueryWithProfiling(enabled bool) func(*QueryConfig) { - return func(qc *QueryConfig) { qc.ProfilingEnabled = enabled } -} - -func QueryWithGeneratedIRCallback(cb func(string)) func(*QueryConfig) { - return func(qc *QueryConfig) { qc.GeneratedIRCallback = cb } -} - -type Queryable interface { - Parse(ctx context.Context, q string) (*typesv1.Query, error) - Format(ctx context.Context, q *typesv1.Query) (string, error) - - Query(ctx context.Context, q *typesv1.Query, c *typesv1.Cursor, limit int, opts ...QueryOption) (*typesv1.Data, *typesv1.Cursor, *typesv1.QueryMetrics, error) - ResolveQueryType(ctx context.Context, query *typesv1.Query) (*typesv1.DataStreamType, error) - ListSymbols(ctx context.Context, query *typesv1.Query, c *typesv1.Cursor, limit int) ([]*typesv1.Symbol, *typesv1.Cursor, error) - - Stream(ctx context.Context, q *typesv1.Query, cb func(context.Context, *typesv1.Data) (bool, error), opts *StreamOption) error - - GetTraceByID(ctx context.Context, traceID *typesv1.TraceID) (*typesv1.Trace, error) - GetTraceBySpanID(ctx context.Context, spanID *typesv1.SpanID) (*typesv1.Trace, error) - GetSpanByID(ctx context.Context, spanID *typesv1.SpanID) (*typesv1.Span, error) -} - -type Symbol struct { - Name string - Type *typesv1.VarType -} - -type Cursor interface { - IDs() (machineID, sessionID int64) - Next(context.Context) bool - Event(*typesv1.LogEvent) error - Err() error - Close() error -} - -type TrimOptions struct { - ForLogs TrimOption - ForSpans TrimOption - ForMetrics TrimOption -} - -type TrimOption struct { - ByTime *time.Time - BySize *uint64 -} diff --git a/pkg/localstorage/test_suite.go b/pkg/localstorage/test_suite.go deleted file mode 100644 index b2627647..00000000 --- a/pkg/localstorage/test_suite.go +++ /dev/null @@ -1,335 +0,0 @@ -package localstorage - -import ( - "context" - "testing" - "time" - - "github.com/google/go-cmp/cmp" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog" - "github.com/humanlogio/humanlog/pkg/sink" - "github.com/stretchr/testify/require" - semconv "go.opentelemetry.io/otel/semconv/v1.34.0" - "google.golang.org/protobuf/testing/protocmp" - "google.golang.org/protobuf/types/known/timestamppb" -) - -var ( - ServiceName = "antoine's service" - TestRes = typesv1.NewResource("res_schema_url", []*typesv1.KV{ - typesv1.KeyVal(string(semconv.ServiceNameKey), typesv1.ValStr(ServiceName)), - }) - TestScope = typesv1.NewScope("scope_schema_url", "test-scope", "v0.0.0-test", []*typesv1.KV{ - typesv1.KeyVal("component", typesv1.ValStr("database")), - }) -) - -func RunTest(t *testing.T, constructor func(t *testing.T, timeNow func() time.Time, newUlid func() *typesv1.ULID) Storage) { - tests := []struct { - name string - q string - limit int - input []*typesv1.Log - want []*typesv1.Data - }{ - { - name: "nothing", - q: `{from==2006-01-02T15:04:06.00500000Z}`, - limit: 4, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs(nil), - }, - }, - { - name: "all", - q: `{to==2006-01-02T15:04:06.00500000Z}`, - limit: 5, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }), - }, - }, - - { - name: "all", - q: `{to==2006-01-02T15:04:06.00500000Z}`, - limit: 5, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }), - }, - }, - { - name: "all with pagination", - q: `{to==2006-01-02T15:04:06.00500000Z}`, - limit: 3, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - }), - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }), - }, - }, - { - name: "all with pagination overflow", - q: `{to==2006-01-02T15:04:06.00500000Z}`, - limit: 2, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - }), - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }), - dataLogs(nil), - }, - }, - { - name: "skip last", - q: `{to==2006-01-02T15:04:06.004000000Z}`, - limit: 4, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - }), - }, - }, - { - name: "skip first", - q: `{from==2006-01-02T15:04:06.002000000Z to==2006-01-02T15:04:06.005000000Z}`, - limit: 4, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }), - }, - }, - { - name: "from only", - q: `{from==2006-01-02T15:04:06.002000000Z}`, - limit: 4, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }), - }, - }, - { - name: "slice", - q: `{from==2006-01-02T15:04:06.002000000Z to==2006-01-02T15:04:06.004000000Z}`, - limit: 4, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl": "info", "msg":"hello world 1"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.004"), `{"ts":"2006-01-02T15:04:06.004", "lvl": "info", "msg":"hello world 4"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.002"), `{"ts":"2006-01-02T15:04:06.002", "lvl": "info", "msg":"hello world 2"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl": "info", "msg":"hello world 3"}`), - }), - }, - }, - { - name: "simple query on `severity_text`", - q: `{from==2006-01-02T15:04:06.002000000Z to==2006-01-02T15:04:06.004000000Z} filter severity_text=="error"`, - limit: 4, - input: []*typesv1.Log{ - reallog(TestRes, TestScope, 1, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl":"error", "msg":"some sort of problem"}`), - reallog(TestRes, TestScope, 2, ServiceName, musttime("2006-01-02T15:04:06.001"), `{"ts":"2006-01-02T15:04:06.001", "lvl":"info", "msg":"no problem, all is fine"}`), - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl":"error", "msg":"some sort of problem a bit later"}`), - reallog(TestRes, TestScope, 4, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl":"info", "msg":"no problem, all is fine a bit later"}`), - reallog(TestRes, TestScope, 5, ServiceName, musttime("2006-01-02T15:04:06.006"), `{"ts":"2006-01-02T15:04:06.006", "lvl":"error", "msg":"some sort of problem too late"}`), - reallog(TestRes, TestScope, 6, ServiceName, musttime("2006-01-02T15:04:06.006"), `{"ts":"2006-01-02T15:04:06.006", "lvl":"info", "msg":"no problem, all is fine too late"}`), - }, - want: []*typesv1.Data{ - dataLogs([]*typesv1.Log{ - reallog(TestRes, TestScope, 3, ServiceName, musttime("2006-01-02T15:04:06.003"), `{"ts":"2006-01-02T15:04:06.003", "lvl":"error", "msg":"some sort of problem a bit later"}`), - }), - }, - }, - } - type sinkid struct { - resID uint64 - scopeID uint64 - } - ctx := context.Background() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - - now := time.Date(2025, 3, 10, 20, 55, 20, 0, time.UTC) - timeNow := func() time.Time { - return now - } - i := 0 - newUlid := func() *typesv1.ULID { - i++ - return &typesv1.ULID{Low: uint64(i)} - } - - db := constructor(t, timeNow, newUlid) - defer db.Close() - - snks := map[sinkid]sink.Sink{} - defer func() { - for _, snk := range snks { - err := snk.Close(ctx) - require.NoError(t, err) - } - }() - for _, ev := range tt.input { - res := ev.Resource - scope := ev.Scope - snkid := sinkid{resID: res.ResourceHash_64, scopeID: scope.ScopeHash_64} - snk, ok := snks[snkid] - if !ok { - var err error - snk, err = db.SinkFor(ctx, res, scope) - require.NoError(t, err) - snks[snkid] = snk - } - err := snk.Receive(ctx, ev) - require.NoError(t, err) - } - - q, err := db.Parse(ctx, tt.q) - require.NoError(t, err) - - var ( - got []*typesv1.Data - c *typesv1.Cursor - ) - for { - out, next, metrics, err := db.Query(ctx, q, c, int(tt.limit)) - require.NoError(t, err) - require.NotNil(t, metrics) - got = append(got, out) - c = next - if next == nil { - break - } - require.LessOrEqual(t, len(got), len(tt.want)) - } - - require.Len(t, got, len(tt.want)) - for i := range tt.want { - diff := cmp.Diff(tt.want[i], got[i], protocmp.Transform()) - require.Empty(t, diff) - } - }) - } -} - -func musttime(str string) time.Time { - t, err := time.Parse("2006-01-02T15:04:05.000", str) - if err != nil { - panic(err) - } - return t -} - -func dataLogs(logs []*typesv1.Log) *typesv1.Data { - return &typesv1.Data{ - Shape: &typesv1.Data_Logs{ - Logs: &typesv1.Logs{Logs: logs}, - }, - } -} - -func reallog(res *typesv1.Resource, scp *typesv1.Scope, ulid uint64, svcname string, parsedAt time.Time, raw string) *typesv1.Log { - ev := &typesv1.Log{Ulid: &typesv1.ULID{Low: ulid}, ObservedTimestamp: timestamppb.New(parsedAt), Resource: res, Scope: scp, Raw: []byte(raw)} - - opts := humanlog.DefaultOptions() - opts.DetectTimestamp = true - jsonHandler := humanlog.JSONHandler{Opts: opts} - logfmtHandler := humanlog.LogfmtHandler{Opts: opts} - - handlers := []func([]byte, *typesv1.Log) bool{ - jsonHandler.TryHandle, - logfmtHandler.TryHandle, - } - - isHandled := false - for _, hdlr := range handlers { - if hdlr([]byte(raw), ev) { - isHandled = true - break - } - } - if !isHandled { - panic("raw doesn't parse with humanlog") - } - ev.ServiceName = svcname - - return ev -} diff --git a/pkg/retry/retry.go b/pkg/retry/retry.go deleted file mode 100644 index 3eafcf0e..00000000 --- a/pkg/retry/retry.go +++ /dev/null @@ -1,114 +0,0 @@ -package retry - -import ( - "context" - "math" - "math/rand" - "time" -) - -// Defaults for the retries. -const ( - DefaultBaseSleep = 100 * time.Millisecond - DefaultCapSleep = 30 * time.Second - DefaultFactor = 2.0 -) - -type OnRetry func(attempt float64, err error) - -type retrier struct { - log OnRetry - ctx context.Context - r *rand.Rand - sleep time.Duration - cap time.Duration - factor float64 - sleepFn func(time.Duration) <-chan time.Time -} - -func newRetrier(ctx context.Context) *retrier { - return &retrier{ - log: func(_ float64, _ error) {}, - ctx: ctx, - r: rand.New(rand.NewSource(time.Now().UnixNano())), - sleep: DefaultBaseSleep, - cap: DefaultCapSleep, - factor: DefaultFactor, - sleepFn: time.After, - } -} - -// An Option changes the default behavior of a retrier. -type Option func(*retrier) - -// UseBaseSleep makes the retrier sleep at least `base`. -func UseBaseSleep(base time.Duration) Option { - return func(r *retrier) { r.sleep = base } -} - -// UseCapSleep makes the retrier sleep at most `cap`. -func UseCapSleep(cap time.Duration) Option { - return func(r *retrier) { r.cap = cap } -} - -// UseFactor makes the retrier grow its exponential backoff using factor -// as the base of the exponent. -func UseFactor(factor float64) Option { - return func(r *retrier) { r.factor = factor } -} - -// UseLog makes the retrier log retries to the given func. -func UseLog(log OnRetry) Option { - return func(r *retrier) { r.log = log } -} - -// UseRand makes the retrier use the *rand.Rand for randomization of retries. -func UseRand(rd *rand.Rand) Option { - return func(r *retrier) { r.r = rd } -} - -// useSleepFn makes the retrier use the sleep func for sleeps. -func useSleepFn(fn func(time.Duration) <-chan time.Time) Option { - return func(r *retrier) { r.sleepFn = fn } -} - -// Do an action with exponential randomized backoff. -func Do(ctx context.Context, fn func(context.Context) (bool, error), opts ...Option) error { - - retrier := newRetrier(ctx) - for _, opt := range opts { - opt(retrier) - } - - var ( - baseSeconds = retrier.sleep.Seconds() - capSecond = retrier.cap.Seconds() - factor = retrier.factor - r = retrier.r - sleepFn = retrier.sleepFn - attempt = 0.0 - ) - retryFunc := func() bool { - sleepSeconds := r.Float64() * math.Min(capSecond, baseSeconds*math.Pow(factor, attempt)) - sleep := time.Duration(sleepSeconds * float64(time.Second)) - select { - case <-sleepFn(sleep): - case <-ctx.Done(): - return false - } - attempt += 1.0 - return true - } - - for { - retry, err := fn(ctx) - if !retry { - return err - } - - retrier.log(attempt, err) - if !retryFunc() { - return err - } - } -} diff --git a/pkg/retry/retry_test.go b/pkg/retry/retry_test.go deleted file mode 100644 index d992004d..00000000 --- a/pkg/retry/retry_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package retry - -import ( - "context" - "math/rand" - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func TestRetrySuccess(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - now := time.Date(2024, time.October, 25, 13, 40, 37, 0, time.UTC) - start := now - r := rand.New(rand.NewSource(now.UnixNano())) - tch := make(chan time.Time, 10) - tch <- now - - called := 0 - err := Do(ctx, - func(ctx context.Context) (bool, error) { - called++ - return false, nil - }, - UseRand(r), - useSleepFn(func(d time.Duration) <-chan time.Time { - t.Logf("sleeping for %v", d) - now = now.Add(d) - go func() { - select { - case tch <- now: - case <-ctx.Done(): - panic("so sloooow") - } - }() - return tch - }), - ) - require.NoError(t, err) - require.Equal(t, 1, called) - require.Equal(t, start, now) -} diff --git a/pkg/sink/logsvcsink/stream_sink.go b/pkg/sink/logsvcsink/stream_sink.go deleted file mode 100644 index 32b78dcc..00000000 --- a/pkg/sink/logsvcsink/stream_sink.go +++ /dev/null @@ -1,242 +0,0 @@ -package logsvcsink - -import ( - "context" - "errors" - "fmt" - "io" - "log/slog" - "time" - - "connectrpc.com/connect" - v1 "github.com/minitape/api/go/svc/ingest/v1" - "github.com/minitape/api/go/svc/ingest/v1/ingestv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/pkg/retry" - "github.com/humanlogio/humanlog/pkg/sink" - "google.golang.org/protobuf/proto" -) - -var ( - _ sink.Sink = (*ConnectStreamSink)(nil) -) - -type ConnectStreamSink struct { - ll *slog.Logger - name string - eventsc chan *typesv1.Log - dropIfFull bool - doneFlushing chan struct{} -} - -func StartStreamSink( - ctx context.Context, - ll *slog.Logger, - client ingestv1connect.IngestServiceClient, - name string, - resource *typesv1.Resource, - scope *typesv1.Scope, - bufferSize int, - drainBufferFor time.Duration, - dropIfFull bool, - notifyUnableToIngest func(err error), -) *ConnectStreamSink { - - snk := &ConnectStreamSink{ - ll: ll.With(slog.String("sink", name)), - name: name, - eventsc: make(chan *typesv1.Log, bufferSize/10), - dropIfFull: dropIfFull, - doneFlushing: make(chan struct{}), - } - - go func() { - var ( - buffered []*typesv1.Log - err error - ) - for { - startedAt := time.Now() - buffered, err = snk.connectAndHandleBuffer(ctx, client, resource, scope, bufferSize, drainBufferFor, buffered) - if err == io.EOF { - close(snk.doneFlushing) - return - } - var cerr *connect.Error - if errors.As(err, &cerr) && cerr.Code() == connect.CodeResourceExhausted { - close(snk.doneFlushing) - notifyUnableToIngest(err) - return - } - if err != nil { - ll.DebugContext(ctx, "failed to send logs", slog.Any("err", err)) - } - if time.Since(startedAt) < time.Second { - select { - case <-ctx.Done(): - return - case <-time.After(time.Second): - } - } else { - select { - case <-ctx.Done(): - return - default: - } - } - - } - }() - - return snk -} - -func (snk *ConnectStreamSink) connectAndHandleBuffer( - ctx context.Context, - client ingestv1connect.IngestServiceClient, - resource *typesv1.Resource, - scope *typesv1.Scope, - bufferSize int, - drainBufferFor time.Duration, - buffered []*typesv1.Log, -) (lastBuffer []*typesv1.Log, sendErr error) { - ll := snk.ll - ll.DebugContext(ctx, "contacting log ingestor") - var stream *connect.ClientStreamForClient[v1.IngestStreamRequest, v1.IngestStreamResponse] - err := retry.Do(ctx, func(ctx context.Context) (bool, error) { - - stream = client.IngestStream(ctx) - firstReq := &v1.IngestStreamRequest{Logs: buffered, Resource: resource, Scope: scope} - if err := stream.Send(firstReq); err != nil { - return true, fmt.Errorf("creating ingestion stream: %w", err) - } - return false, nil - }, retry.UseCapSleep(time.Second), retry.UseLog(func(attempt float64, err error) { - ll.DebugContext(ctx, "can't reach ingestion service", slog.Int("attempt", int(attempt)), slog.Any("err", err)) - })) - if err != nil { - return buffered, fmt.Errorf("retry aborted: %w", err) - } - - defer func() { - res, err := stream.CloseAndReceive() - if err != nil { - var cerr *connect.Error - if errors.Is(sendErr, io.EOF) && errors.As(err, &cerr) && cerr.Code() == connect.CodeResourceExhausted { - sendErr = cerr - ll.ErrorContext(ctx, "no active plan, can't ingest logs", slog.Any("err", err)) - return - } - if !errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { - ll.ErrorContext(ctx, "closing and receiving response for log ingestor session", slog.Any("err", err)) - } - return - } - if res.Msg == nil { - return - } - }() - - ll.DebugContext(ctx, "ready to send logs") - ticker := time.NewTicker(drainBufferFor) - ticker.Stop() - req := new(v1.IngestStreamRequest) - flushing := false - for !flushing { - // wait for any event to come - select { - case ev, more := <-snk.eventsc: - if !more { - ll.DebugContext(ctx, "no more events coming, flushing buffer (while waiting)") - flushing = true - } - if ev != nil { - req.Logs = append(req.Logs, ev) - } - // send whatever is there - case <-ctx.Done(): - return req.Logs, nil - } - ticker.Reset(drainBufferFor) - - // try to drain the channel for 100ms - ll.DebugContext(ctx, "draining for a bit before sending", slog.Duration("drain_for", drainBufferFor)) - drain_buffered_events_loop: - for len(req.Logs) < bufferSize { - select { - case ev, more := <-snk.eventsc: - if ev != nil { - req.Logs = append(req.Logs, ev) - } - if !more { - ll.DebugContext(ctx, "no more events coming, flushing buffer (while draining)") - flushing = true - break drain_buffered_events_loop - } - case <-ticker.C: - ticker.Stop() - ll.DebugContext(ctx, "done draining") - break drain_buffered_events_loop - } - } - // until it's empty, then send what we have - start := time.Now() - sendErr = stream.Send(req) - dur := time.Since(start) - ll.DebugContext(ctx, "sent logs", - slog.String("sink", snk.name), - slog.Int64("send_ms", dur.Milliseconds()), - slog.Any("err", sendErr), - slog.Int("ev_count", len(req.Logs)), - slog.Int("buffer_size", bufferSize), - slog.Int64("drain_for_ms", drainBufferFor.Milliseconds()), - ) - if sendErr != nil { - return req.Logs, sendErr - } - req.Logs = req.Logs[:0:len(req.Logs)] - } - return nil, io.EOF -} - -func (snk *ConnectStreamSink) Receive(ctx context.Context, ev *typesv1.Log) error { - send := proto.Clone(ev).(*typesv1.Log) - if snk.dropIfFull { - select { - case snk.eventsc <- send: - case <-ctx.Done(): - return nil - default: - snk.ll.WarnContext(ctx, "dropping log event, buffer full!") - } - } else { - select { - case snk.eventsc <- send: - case <-ctx.Done(): - return nil - default: - // would have blocked~ - snk.ll.WarnContext(ctx, "blocking on log event, buffer full!") - select { - case snk.eventsc <- send: - case <-ctx.Done(): - return nil - } - } - } - return nil -} - -// Close can only be called once, calling it twice will panic. -func (snk *ConnectStreamSink) Close(ctx context.Context) error { - close(snk.eventsc) - snk.ll.DebugContext(ctx, "starting to flush") - select { - case <-snk.doneFlushing: - snk.ll.DebugContext(ctx, "done flushing") - case <-ctx.Done(): - snk.ll.DebugContext(ctx, "unable to finish flushing") - return ctx.Err() - } - return nil -} diff --git a/pkg/sink/logsvcsink/unary_sink.go b/pkg/sink/logsvcsink/unary_sink.go deleted file mode 100644 index 1b5799b5..00000000 --- a/pkg/sink/logsvcsink/unary_sink.go +++ /dev/null @@ -1,209 +0,0 @@ -package logsvcsink - -import ( - "context" - "errors" - "io" - "log/slog" - "time" - - "connectrpc.com/connect" - v1 "github.com/minitape/api/go/svc/ingest/v1" - "github.com/minitape/api/go/svc/ingest/v1/ingestv1connect" - typesv1 "github.com/minitape/api/go/types/v1" - "github.com/humanlogio/humanlog/pkg/sink" - "google.golang.org/protobuf/proto" -) - -var ( - _ sink.Sink = (*ConnectUnarySink)(nil) -) - -type ConnectUnarySink struct { - ll *slog.Logger - name string - eventsc chan *typesv1.Log - dropIfFull bool - doneFlushing chan struct{} -} - -func StartUnarySink( - ctx context.Context, - ll *slog.Logger, - client ingestv1connect.IngestServiceClient, - name string, - resource *typesv1.Resource, - scope *typesv1.Scope, - bufferSize int, - drainBufferFor time.Duration, - dropIfFull bool, - notifyUnableToIngest func(err error), -) *ConnectUnarySink { - snk := &ConnectUnarySink{ - ll: ll.With(slog.String("sink", name)), - name: name, - eventsc: make(chan *typesv1.Log, bufferSize), - dropIfFull: dropIfFull, - doneFlushing: make(chan struct{}), - } - - go func() { - var ( - buffered []*typesv1.Log - err error - ) - for { - startedAt := time.Now() - buffered, err = snk.connectAndHandleBuffer(ctx, client, resource, scope, bufferSize, drainBufferFor, buffered) - if err == io.EOF { - close(snk.doneFlushing) - return - } - var cerr *connect.Error - if errors.As(err, &cerr) && cerr.Code() == connect.CodeResourceExhausted { - close(snk.doneFlushing) - notifyUnableToIngest(err) - return - } - if err != nil { - ll.DebugContext(ctx, "failed to send logs", slog.Any("err", err)) - } - if time.Since(startedAt) < time.Second { - select { - case <-ctx.Done(): - return - case <-time.After(time.Second): - } - } else { - select { - case <-ctx.Done(): - return - default: - } - } - - } - }() - - return snk -} - -func (snk *ConnectUnarySink) connectAndHandleBuffer( - ctx context.Context, - client ingestv1connect.IngestServiceClient, - resource *typesv1.Resource, - scope *typesv1.Scope, - bufferSize int, - drainBufferFor time.Duration, - buffered []*typesv1.Log, -) (lastBuffer []*typesv1.Log, _ error) { - ll := snk.ll - ll.DebugContext(ctx, "contacting log ingestor") - - ll.DebugContext(ctx, "ready to send logs") - req := connect.NewRequest(&v1.IngestRequest{ - Resource: resource, - Scope: scope, - Logs: buffered, - }) - ticker := time.NewTicker(drainBufferFor) - ticker.Stop() - flushing := false - for !flushing { - // wait for any event to come - select { - case ev, more := <-snk.eventsc: - if !more { - ll.DebugContext(ctx, "no more events coming, flushing buffer (while waiting)") - flushing = true - } - if ev != nil { - req.Msg.Logs = append(req.Msg.Logs, ev) - } - case <-ctx.Done(): - return req.Msg.Logs, nil - } - ticker.Reset(drainBufferFor) - - // try to drain the channel for 100ms - ll.DebugContext(ctx, "draining for a bit before sending", slog.Duration("drain_for", drainBufferFor)) - drain_buffered_events_loop: - for len(req.Msg.Logs) < bufferSize { - select { - case ev, more := <-snk.eventsc: - if ev != nil { - req.Msg.Logs = append(req.Msg.Logs, ev) - } - if !more { - ll.DebugContext(ctx, "no more events coming, flushing buffer (while draining)") - flushing = true - break drain_buffered_events_loop - } - case <-ticker.C: - ticker.Stop() - ll.DebugContext(ctx, "done draining") - break drain_buffered_events_loop - } - } - // until it's empty, then send what we have - start := time.Now() - _, err := client.Ingest(ctx, req) - dur := time.Since(start) - ll.DebugContext(ctx, "sent logs", - slog.String("sink", snk.name), - slog.Int64("send_ms", dur.Milliseconds()), - slog.Any("err", err), - slog.Int("ev_count", len(req.Msg.Logs)), - slog.Int("buffer_size", bufferSize), - slog.Int64("drain_for_ms", drainBufferFor.Milliseconds()), - ) - if err != nil { - return req.Msg.Logs, err - } - - req.Msg.Logs = req.Msg.Logs[:0:len(req.Msg.Logs)] - } - return nil, io.EOF -} - -func (snk *ConnectUnarySink) Receive(ctx context.Context, ev *typesv1.Log) error { - send := proto.Clone(ev).(*typesv1.Log) - if snk.dropIfFull { - select { - case snk.eventsc <- send: - case <-ctx.Done(): - return nil - default: - snk.ll.WarnContext(ctx, "dropping log event, buffer full!") - } - } else { - select { - case snk.eventsc <- send: - case <-ctx.Done(): - return nil - default: - // would have blocked~ - snk.ll.WarnContext(ctx, "blocking on log event, buffer full!") - select { - case snk.eventsc <- send: - case <-ctx.Done(): - return nil - } - } - } - return nil -} - -// Close can only be called once, calling it twice will panic. -func (snk *ConnectUnarySink) Close(ctx context.Context) error { - close(snk.eventsc) - snk.ll.DebugContext(ctx, "starting to flush") - select { - case <-snk.doneFlushing: - snk.ll.DebugContext(ctx, "done flushing") - case <-ctx.Done(): - snk.ll.DebugContext(ctx, "unable to finish flushing") - return ctx.Err() - } - return nil -} diff --git a/pkg/sink/otlpsink/otlp_sink.go b/pkg/sink/otlpsink/otlp_sink.go index 69f6f139..d5b01853 100644 --- a/pkg/sink/otlpsink/otlp_sink.go +++ b/pkg/sink/otlpsink/otlp_sink.go @@ -2,12 +2,10 @@ package otlpink import ( "context" - "errors" "io" "log/slog" "time" - "connectrpc.com/connect" typesv1 "github.com/minitape/api/go/types/v1" "github.com/humanlogio/humanlog/pkg/sink" "github.com/oklog/ulid/v2" @@ -74,14 +72,9 @@ func StartOTLPSink( close(snk.doneFlushing) return } - var cerr *connect.Error - if errors.As(err, &cerr) && cerr.Code() == connect.CodeResourceExhausted { - close(snk.doneFlushing) - notifyUnableToIngest(err) - return - } if err != nil { ll.DebugContext(ctx, "failed to send logs", slog.Any("err", err)) + notifyUnableToIngest(err) } if time.Since(startedAt) < time.Second { select { diff --git a/pkg/validate/validate.go b/pkg/validate/validate.go deleted file mode 100644 index d52155aa..00000000 --- a/pkg/validate/validate.go +++ /dev/null @@ -1,37 +0,0 @@ -package validate - -import ( - "fmt" - "time" - - "google.golang.org/protobuf/types/known/durationpb" -) - -func StreamResolveBatchSize(req int) (int, error) { - const ( - maxBatchSize = 1000 - defaultBatchSize = 100 - ) - if req == 0 { - return defaultBatchSize, nil - } - if req > maxBatchSize { - return 0, fmt.Errorf("invalid `max_batch_size`: must be less than %d but was %d", maxBatchSize, req) - } - return req, nil -} - -func StreamResolveBatchTicker(d *durationpb.Duration) (<-chan time.Time, func(), error) { - const ( - minMaxBatchFor = 16 * time.Millisecond - ) - if d == nil || d.AsDuration() == 0 { - return nil, func() {}, nil - } - req := d.AsDuration() - if req < minMaxBatchFor { - return nil, nil, fmt.Errorf("invalid `max_batching_for`: must be greater than %v but was %v", minMaxBatchFor, req) - } - ticker := time.NewTicker(req) - return ticker.C, ticker.Stop, nil -} diff --git a/script/build.sh b/script/build.sh index 0e27a0bb..0d11ed49 100755 --- a/script/build.sh +++ b/script/build.sh @@ -4,7 +4,6 @@ set -euox pipefail root=$(git rev-parse --show-toplevel) -gotags="${HUMANLOG_GOTAGS:-}" goos="${GOOS:-$(go env GOOS)}" goarch="${GOARCH:-$(go env GOARCH)}" is_prod_build="${HUMANLOG_IS_PROD_BUILD:-}" @@ -86,9 +85,6 @@ function main() { local tarname="humanlog_${version}_${goos}_${goarch}.tar.gz" local flags="-o ${output_path} -trimpath" - if [[ ! -z "${gotags}" ]]; then - flags+=" -tags ${gotags}" - fi ldflags="-s -w" @@ -102,14 +98,13 @@ function main() { ldflags+=" -X main.versionBuild=${build}" if [[ "${is_prod_build}" != "true" ]]; then ldflags+=" -X main.versionPrerelease=${pre}" - ldflags+=" -X main.defaultApiAddr=https://api.humanlog.dev" - ldflags+=" -X main.defaultBaseSiteAddr=https://humanlog.dev" + ldflags+=" -X main.defaultApiURL=https://api.humanlog.dev" + ldflags+=" -X main.defaultBaseSiteURL=https://humanlog.dev" ldflags+=" -X main.defaultReleaseChannel=dev" else ldflags+=" -X main.versionPrerelease=" - ldflags+=" -X main.hideUnreleasedFeatures=true" - ldflags+=" -X main.defaultApiAddr=https://api.humanlog.io" - ldflags+=" -X main.defaultBaseSiteAddr=https://humanlog.io" + ldflags+=" -X main.defaultApiURL=https://api.humanlog.io" + ldflags+=" -X main.defaultBaseSiteURL=https://humanlog.io" ldflags+=" -X main.defaultReleaseChannel=main" fi diff --git a/vendor/connectrpc.com/cors/.gitignore b/vendor/connectrpc.com/cors/.gitignore deleted file mode 100644 index 987d6a1c..00000000 --- a/vendor/connectrpc.com/cors/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/.tmp/ -*.pprof -*.svg -cover.out diff --git a/vendor/connectrpc.com/cors/.golangci.yml b/vendor/connectrpc.com/cors/.golangci.yml deleted file mode 100644 index 3f573aab..00000000 --- a/vendor/connectrpc.com/cors/.golangci.yml +++ /dev/null @@ -1,54 +0,0 @@ -run: - skip-dirs-use-default: false -linters-settings: - errcheck: - check-type-assertions: true - forbidigo: - forbid: - - '^fmt\.Print' - - '^log\.' - - '^print$' - - '^println$' - - '^panic$' - godox: - # TODO, OPT, etc. comments are fine to commit. Use FIXME comments for - # temporary hacks, and use godox to prevent committing them. - keywords: [FIXME] - varnamelen: - ignore-decls: - - T any - - i int - - wg sync.WaitGroup -linters: - enable-all: true - disable: - - cyclop # covered by gocyclo - - depguard # unnecessary for small libraries - - deadcode # abandoned - - exhaustivestruct # replaced by exhaustruct - - funlen # rely on code review to limit function length - - gocognit # dubious "cognitive overhead" quantification - - gofumpt # prefer standard gofmt - - goimports # rely on gci instead - - golint # deprecated by Go team - - gomnd # some unnamed constants are okay - - ifshort # deprecated by author - - interfacer # deprecated by author - - ireturn # "accept interfaces, return structs" isn't ironclad - - lll # don't want hard limits for line length - - maintidx # covered by gocyclo - - maligned # readability trumps efficient struct packing - - nlreturn # generous whitespace violates house style - - nonamedreturns # named returns are fine; it's *bare* returns that are bad - - nosnakecase # deprecated in https://github.com/golangci/golangci-lint/pull/3065 - - scopelint # deprecated by author - - structcheck # abandoned - - testpackage # internal tests are fine - - varcheck # abandoned - - wrapcheck # don't _always_ need to wrap errors - - wsl # generous whitespace violates house style -issues: - exclude: - # Don't ban use of fmt.Errorf to create new errors, but the remaining - # checks from err113 are useful. - - "err113: do not define dynamic errors.*" diff --git a/vendor/connectrpc.com/cors/LICENSE b/vendor/connectrpc.com/cors/LICENSE deleted file mode 100644 index 9348264f..00000000 --- a/vendor/connectrpc.com/cors/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2023 The Connect 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. diff --git a/vendor/connectrpc.com/cors/MAINTAINERS.md b/vendor/connectrpc.com/cors/MAINTAINERS.md deleted file mode 100644 index d95df072..00000000 --- a/vendor/connectrpc.com/cors/MAINTAINERS.md +++ /dev/null @@ -1,7 +0,0 @@ -Maintainers -=========== - -## Current -* [Akshay Shah](https://github.com/akshayjshah), [Buf](https://buf.build) -* [Edward McFarlane](https://github.com/emcfarlane), [Buf](https://buf.build) -* [Timo Stamm](https://github.com/timostamm), [Buf](https://buf.build) diff --git a/vendor/connectrpc.com/cors/Makefile b/vendor/connectrpc.com/cors/Makefile deleted file mode 100644 index 41471a63..00000000 --- a/vendor/connectrpc.com/cors/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -# See https://tech.davis-hansson.com/p/make/ -SHELL := bash -.DELETE_ON_ERROR: -.SHELLFLAGS := -eu -o pipefail -c -.DEFAULT_GOAL := all -MAKEFLAGS += --warn-undefined-variables -MAKEFLAGS += --no-builtin-rules -MAKEFLAGS += --no-print-directory -BIN := .tmp/bin -export PATH := $(BIN):$(PATH) -export GOBIN := $(abspath $(BIN)) -COPYRIGHT_YEARS := 2023 -LICENSE_IGNORE := --ignore testdata/ - -.PHONY: help -help: ## Describe useful make targets - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}' - -.PHONY: all -all: ## Build, test, and lint (default) - $(MAKE) test - $(MAKE) lint - -.PHONY: clean -clean: ## Delete intermediate build artifacts - @# -X only removes untracked files, -d recurses into directories, -f actually removes files/dirs - git clean -Xdf - -.PHONY: test -test: build ## Run unit tests - go test -vet=off -race -cover ./... - -.PHONY: build -build: generate ## Build all packages - go build ./... - -.PHONY: generate -generate: $(BIN)/license-header ## Regenerate code and licenses - license-header \ - --license-type apache \ - --copyright-holder "The Connect Authors" \ - --year-range "$(COPYRIGHT_YEARS)" $(LICENSE_IGNORE) - -.PHONY: lint -lint: $(BIN)/golangci-lint ## Lint - go vet ./... - golangci-lint run --modules-download-mode=readonly --timeout=3m0s - -.PHONY: lintfix -lintfix: $(BIN)/golangci-lint ## Automatically fix some lint errors - golangci-lint run --fix --modules-download-mode=readonly --timeout=3m0s - -.PHONY: install -install: ## Install all binaries - go install ./... - -.PHONY: upgrade -upgrade: ## Upgrade dependencies - go get -u -t ./... - go mod tidy -v - -.PHONY: checkgenerate -checkgenerate: - @# Used in CI to verify that `make generate` doesn't produce a diff. - test -z "$$(git status --porcelain | tee /dev/stderr)" - -$(BIN)/license-header: Makefile - @mkdir -p $(@D) - go install github.com/bufbuild/buf/private/pkg/licenseheader/cmd/license-header@v1.26.1 - -$(BIN)/golangci-lint: Makefile - @mkdir -p $(@D) - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.1 diff --git a/vendor/connectrpc.com/cors/README.md b/vendor/connectrpc.com/cors/README.md deleted file mode 100644 index 997a3ab8..00000000 --- a/vendor/connectrpc.com/cors/README.md +++ /dev/null @@ -1,85 +0,0 @@ -cors -==== -[![Build](https://github.com/connectrpc/cors-go/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/connectrpc/cors-go/actions/workflows/ci.yaml) -[![Report Card](https://goreportcard.com/badge/connectrpc.com/cors)](https://goreportcard.com/report/connectrpc.com/cors) -[![GoDoc](https://pkg.go.dev/badge/connectrpc.com/cors.svg)](https://pkg.go.dev/connectrpc.com/cors) -[![Slack](https://img.shields.io/badge/slack-buf-%23e01563)][slack] - -`connectrpc.com/cors` simplifies Cross-Origin Resource Sharing (CORS) for -[Connect](https://github.com/connectrpc/connect-go) servers. CORS is usually -required for the Connect and gRPC-Web protocols to work correctly in -web browsers. - -For background, more details, and best practices, see [Connect's CORS -documentation](https://connectrpc.com/docs/cors). For more on Connect, see the -[announcement blog post][blog], the documentation on [connectrpc.com][docs] -(especially the [Getting Started] guide for Go), the [demo -service][examples-go], or the [protocol specification][protocol]. - -## Example - -This package should work with any CORS implementation. As an example, we'll use -it with [github.com/rs/cors](https://github.com/rs/cors). - -```go -import ( - connectcors "connectrpc.com/cors" - "github.com/rs/cors" -) - -// withCORS adds CORS support to a Connect HTTP handler. -func withCORS(connectHandler http.Handler) http.Handler { - c := cors.New(cors.Options{ - AllowedOrigins: []string{"https://acme.com"}, // replace with your domain - AllowedMethods: connectcors.AllowedMethods(), - AllowedHeaders: connectcors.AllowedHeaders(), - ExposedHeaders: connectcors.ExposedHeaders(), - MaxAge: 7200, // 2 hours in seconds - }) - return c.Handler(connectHandler) -} -``` - -## Ecosystem - -* [connect-go]: the Go implementation of Connect's RPC runtime -* [examples-go]: service powering [demo.connectrpc.com][demo], including bidi streaming -* [grpchealth]: gRPC-compatible health checks -* [grpcreflect]: gRPC-compatible server reflection -* [authn]: pluggable authentication for Connect servers -* [connect-es]: Type-safe APIs with Protobuf and TypeScript -* [conformance]: Connect, gRPC, and gRPC-Web interoperability tests - -## Status: Unstable - -This module isn't stable yet, but it's fairly small — we expect to reach -a stable release quickly. - -It supports the three most recent major releases of Go. -Keep in mind that [only the last two releases receive security -patches][go-support-policy]. - -Within those parameters, `cors` follows semantic versioning. We will _not_ -make breaking changes in the 1.x series of releases. - -## Legal - -Offered under the [Apache 2 license][license]. - -[Getting Started]: https://connectrpc.com/docs/go/getting-started -[authn]: https://github.com/connectrpc/authn-go -[blog]: https://buf.build/blog/connect-a-better-grpc -[conformance]: https://github.com/connectrpc/conformance -[connect-es]: https://github.com/connectrpc/connect-es -[connect-go]: https://github.com/connectrpc/connect-go -[cors]: https://github.com/connectrpc/cors-go -[demo]: https://demo.connectrpc.com -[docs]: https://connectrpc.com -[examples-go]: https://github.com/connectrpc/examples-go -[go-support-policy]: https://golang.org/doc/devel/release#policy -[godoc]: https://pkg.go.dev/connectrpc.com/authn -[grpchealth]: https://github.com/connectrpc/grpchealth-go -[grpcreflect]: https://github.com/connectrpc/grpcreflect-go -[license]: https://github.com/connectrpc/cors-go/blob/main/LICENSE -[protocol]: https://connectrpc.com/docs/protocol -[slack]: https://buf.build/links/slack diff --git a/vendor/connectrpc.com/cors/SECURITY.md b/vendor/connectrpc.com/cors/SECURITY.md deleted file mode 100644 index 04dcde52..00000000 --- a/vendor/connectrpc.com/cors/SECURITY.md +++ /dev/null @@ -1,5 +0,0 @@ -Security Policy -=============== - -This project follows the [Connect security policy and reporting -process](https://connectrpc.com/docs/governance/security). diff --git a/vendor/connectrpc.com/cors/cors.go b/vendor/connectrpc.com/cors/cors.go deleted file mode 100644 index 52b52088..00000000 --- a/vendor/connectrpc.com/cors/cors.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2023 The Connect 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 cors provides helpers to configure cross-origin resource sharing -// (CORS) for Connect servers. -package cors - -// AllowedMethods returns the allowed HTTP methods that scripts running in the -// browser are permitted to use. -// -// To support cross-domain requests with the protocols supported by Connect, -// these headers fields must be included in the preflight response header -// Access-Control-Allow-Methods. -func AllowedMethods() []string { - return []string{ - "GET", // for Connect - "POST", // for all protocols - } -} - -// AllowedHeaders returns the headers that scripts running in the browser send -// when making RPC requests. To support cross-domain requests with the -// protocols supported by Connect, these field names must be included in the -// Access-Control-Allow-Headers header of the preflight response. -// -// When configuring CORS, make sure to also include any application-specific -// headers your server expects to receive from the browser. -func AllowedHeaders() []string { - return []string{ - "Content-Type", // for all protocols - "Connect-Protocol-Version", // for Connect - "Connect-Timeout-Ms", // for Connect - "Grpc-Timeout", // for gRPC-web - "X-Grpc-Web", // for gRPC-web - "X-User-Agent", // for all protocols - } -} - -// ExposedHeaders returns the headers that scripts running in the -// browser expect to access when receiving RPC responses. To support -// cross-domain requests with the protocols supported by Connect, these field -// names must be included in the Access-Control-Expose-Headers header of the -// actual response. -// -// When configuring CORS, make sure to also include any application-specific -// headers your server expects to send to the browser. If your application uses -// trailers, they will be sent as headers with a `Trailer-` prefix for -// unary Connect RPCs - make sure to expose them! -func ExposedHeaders() []string { - return []string{ - "Grpc-Status", // for gRPC-web - "Grpc-Message", // for gRPC-web - "Grpc-Status-Details-Bin", // for gRPC-web - } -} diff --git a/vendor/connectrpc.com/otelconnect/.gitignore b/vendor/connectrpc.com/otelconnect/.gitignore deleted file mode 100644 index 987d6a1c..00000000 --- a/vendor/connectrpc.com/otelconnect/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/.tmp/ -*.pprof -*.svg -cover.out diff --git a/vendor/connectrpc.com/otelconnect/.golangci.yml b/vendor/connectrpc.com/otelconnect/.golangci.yml deleted file mode 100644 index b3543e1e..00000000 --- a/vendor/connectrpc.com/otelconnect/.golangci.yml +++ /dev/null @@ -1,66 +0,0 @@ -linters-settings: - dupl: - threshold: 200 - errcheck: - check-type-assertions: true - exhaustruct: - include: - # No zero values for param structs. - - 'connectrpc\.com/otelconnect\..*[pP]arams' - forbidigo: - forbid: - - '^fmt\.Print' - - '^log\.' - - '^print$' - - '^println$' - - '^panic$' - importas: - no-unaliased: true - alias: - - pkg: connectrpc.com/otelconnect/internal/gen/observability/ping/v1 - alias: pingv1 - godox: - # TODO, OPT, etc. comments are fine to commit. Use FIXME comments for - # temporary hacks, and use godox to prevent committing them. - keywords: [FIXME] - varnamelen: - ignore-decls: - - T any - - i int - - wg sync.WaitGroup -linters: - enable-all: true - disable: - - cyclop # covered by gocyclo - - depguard # unnecessary for small libraries - - funlen # rely on code review to limit function length - - gocognit # dubious "cognitive overhead" quantification - - gofumpt # prefer standard gofmt - - goimports # rely on gci instead - - inamedparam # convention is not followed - - ireturn # "accept interfaces, return structs" isn't ironclad - - lll # don't want hard limits for line length - - maintidx # covered by gocyclo - - mnd # status codes are clearer than constants - - nlreturn # generous whitespace violates house style - - nonamedreturns # named returns are fine; it's *bare* returns that are bad - - protogetter # too many false positives - - tenv # replaced by usetesting - - testpackage # internal tests are fine - - wrapcheck # don't _always_ need to wrap errors - - wsl # generous whitespace violates house style -issues: - exclude-dirs-use-default: false - exclude: - # Don't ban use of fmt.Errorf to create new errors, but the remaining - # checks from err113 are useful. - - "do not define dynamic errors, use wrapped static errors instead: .*" - - exclude-rules: - # If-else is clearer than switch here. - - linters: [gocritic] - path: trace.go - # interceptor_test tests a lot of data structure equality so naturally there are - # a lot of duplications - - path: interceptor_test.go - linters: [dupl] diff --git a/vendor/connectrpc.com/otelconnect/LICENSE b/vendor/connectrpc.com/otelconnect/LICENSE deleted file mode 100644 index bf1edf38..00000000 --- a/vendor/connectrpc.com/otelconnect/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2022-2025 The Connect 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. diff --git a/vendor/connectrpc.com/otelconnect/MAINTAINERS.md b/vendor/connectrpc.com/otelconnect/MAINTAINERS.md deleted file mode 100644 index 90c5bdfb..00000000 --- a/vendor/connectrpc.com/otelconnect/MAINTAINERS.md +++ /dev/null @@ -1,10 +0,0 @@ -Maintainers -=========== - -## Current -* [Akshay Shah](https://github.com/akshayjshah), [Buf](https://buf.build) -* [Josh Humphries](https://github.com/jhump), [Buf](https://buf.build) -* [Edward McFarlane](https://github.com/emcfarlane), [Buf](https://buf.build) - -## Former -* [Josh Carpeggiani](https://github.com/joshcarp) diff --git a/vendor/connectrpc.com/otelconnect/Makefile b/vendor/connectrpc.com/otelconnect/Makefile deleted file mode 100644 index 5d14023d..00000000 --- a/vendor/connectrpc.com/otelconnect/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -# See https://tech.davis-hansson.com/p/make/ -SHELL := bash -.DELETE_ON_ERROR: -.SHELLFLAGS := -eu -o pipefail -c -.DEFAULT_GOAL := all -MAKEFLAGS += --warn-undefined-variables -MAKEFLAGS += --no-builtin-rules -MAKEFLAGS += --no-print-directory -BIN := $(abspath .tmp/bin) -COPYRIGHT_YEARS := 2022-2025 -LICENSE_IGNORE := -e /gen/ -# Set to use a different compiler. For example, `GO=go1.18rc1 make test`. -GO ?= go - -.PHONY: help -help: ## Describe useful make targets - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}' - -.PHONY: all -all: ## Build, test, and lint (default) - $(MAKE) test - $(MAKE) lint - -.PHONY: clean -clean: ## Delete intermediate build artifacts - @# -X only removes untracked files, -d recurses into directories, -f actually removes files/dirs - git clean -Xdf - -.PHONY: test -test: build ## Run unit tests - $(GO) test -vet=off -race -cover ./... - -.PHONY: build -build: generate ## Build all packages - $(GO) build ./... - -.PHONY: lint -lint: $(BIN)/golangci-lint $(BIN)/buf ## Lint Go and protobuf - test -z "$$($(BIN)/buf format -d . | tee /dev/stderr)" - $(GO) vet ./... - $(BIN)/golangci-lint run - $(BIN)/buf lint - -.PHONY: lintfix -lintfix: $(BIN)/golangci-lint $(BIN)/buf ## Automatically fix some lint errors - $(BIN)/golangci-lint run --fix - $(BIN)/buf format -w . - -.PHONY: generate -generate: $(BIN)/buf $(BIN)/protoc-gen-go $(BIN)/protoc-gen-connect-go $(BIN)/license-header ## Regenerate code and licenses - rm -rf internal/gen - PATH=$(BIN) $(BIN)/buf generate - @# We want to operate on a list of modified and new files, excluding - @# deleted and ignored files. git-ls-files can't do this alone. comm -23 takes - @# two files and prints the union, dropping lines common to both (-3) and - @# those only in the second file (-2). We make one git-ls-files call for - @# the modified, cached, and new (--others) files, and a second for the - @# deleted files. - comm -23 \ - <(git ls-files --cached --modified --others --no-empty-directory --exclude-standard | sort -u | grep -v $(LICENSE_IGNORE) ) \ - <(git ls-files --deleted | sort -u) | \ - xargs $(BIN)/license-header \ - --license-type apache \ - --copyright-holder "The Connect Authors" \ - --year-range "$(COPYRIGHT_YEARS)" - -.PHONY: upgrade -upgrade: ## Upgrade dependencies - go get -u -t ./... && go mod tidy -v - -.PHONY: checkgenerate -checkgenerate: - @# Used in CI to verify that `make generate` doesn't produce a diff. - test -z "$$(git status --porcelain | tee /dev/stderr)" - -$(BIN)/protoc-gen-connect-go: go.mod - @mkdir -p $(@D) - @# The version of protoc-gen-connect-go is determined by the version in go.mod - GOBIN=$(abspath $(@D)) $(GO) install connectrpc.com/connect/cmd/protoc-gen-connect-go - -$(BIN)/buf: Makefile - @mkdir -p $(@D) - GOBIN=$(abspath $(@D)) $(GO) install github.com/bufbuild/buf/cmd/buf@v1.50.0 - -$(BIN)/license-header: Makefile - @mkdir -p $(@D) - GOBIN=$(abspath $(@D)) $(GO) install \ - github.com/bufbuild/buf/private/pkg/licenseheader/cmd/license-header@v1.50.0 - -$(BIN)/golangci-lint: Makefile - @mkdir -p $(@D) - GOBIN=$(abspath $(@D)) $(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5 - -$(BIN)/protoc-gen-go: Makefile - @mkdir -p $(@D) - @# The version of protoc-gen-go is determined by the version in go.mod - GOBIN=$(abspath $(@D)) $(GO) install google.golang.org/protobuf/cmd/protoc-gen-go - diff --git a/vendor/connectrpc.com/otelconnect/README.md b/vendor/connectrpc.com/otelconnect/README.md deleted file mode 100644 index 32ce7157..00000000 --- a/vendor/connectrpc.com/otelconnect/README.md +++ /dev/null @@ -1,144 +0,0 @@ -otelconnect -=========== - -[![Build](https://github.com/connectrpc/otelconnect-go/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/connectrpc/otelconnect-go/actions/workflows/ci.yaml) -[![Report Card](https://goreportcard.com/badge/connectrpc.com/otelconnect)](https://goreportcard.com/report/connectrpc.com/otelconnect) -[![GoDoc](https://pkg.go.dev/badge/connectrpc.com/otelconnect.svg)][godoc] - -`connectrpc.com/otelconnect` adds support for [OpenTelemetry][opentelemetry.io] -tracing and metrics collection to [Connect][connect] servers and clients. - -For more on Connect, OpenTelemetry, and `otelconnect`, see the [Connect -announcement blog post][blog] and the observability documentation on -[connectrpc.com](https://connectrpc.com/docs/go/observability/). - -## An example - -```go -package main - -import ( - "context" - "fmt" - "log" - "net/http" - - "connectrpc.com/connect" - "connectrpc.com/otelconnect" - // Generated from your protobuf schema by protoc-gen-go and - // protoc-gen-connect-go. - pingv1 "connectrpc.com/otelconnect/internal/gen/observability/ping/v1" - "connectrpc.com/otelconnect/internal/gen/observability/ping/v1/pingv1connect" -) - -func main() { - mux := http.NewServeMux() - otelInterceptor, err := otelconnect.NewInterceptor() - if err != nil { - log.Fatal(err) - } - - // otelconnect.NewInterceptor provides an interceptor that adds tracing and - // metrics to both clients and handlers. By default, it uses OpenTelemetry's - // global TracerProvider and MeterProvider, which you can configure by - // following the OpenTelemetry documentation. If you'd prefer to avoid - // globals, use otelconnect.WithTracerProvider and - // otelconnect.WithMeterProvider. - mux.Handle(pingv1connect.NewPingServiceHandler( - &pingv1connect.UnimplementedPingServiceHandler{}, - connect.WithInterceptors(otelInterceptor), - )) - - http.ListenAndServe("localhost:8080", mux) -} - -func makeRequest() { - otelInterceptor, err := otelconnect.NewInterceptor() - if err != nil { - log.Fatal(err) - } - - client := pingv1connect.NewPingServiceClient( - http.DefaultClient, - "http://localhost:8080", - connect.WithInterceptors(otelInterceptor), - ) - resp, err := client.Ping( - context.Background(), - connect.NewRequest(&pingv1.PingRequest{}), - ) - if err != nil { - log.Fatal(err) - } - fmt.Println(resp) -} - -``` - -## Configuration for internal services - -By default, instrumented servers are conservative and behave as though they're -internet-facing. They don't trust any tracing information sent by the client, -and will create new trace spans for each request. The new spans are linked to -the remote span for reference (using OpenTelemetry's -[`trace.Link`](https://pkg.go.dev/go.opentelemetry.io/otel/trace#Link)), but -tracing UIs will display the request as a new top-level transaction. - -If your server is deployed as an internal service, configure `otelconnect` to -trust the client's tracing information using -[`otelconnect.WithTrustRemote`][WithTrustRemote]. With this option, servers -will create child spans for each request. - -## Reducing metrics and tracing cardinality - -By default, the [OpenTelemetry RPC conventions][otel-rpc-conventions] produce -high-cardinality server-side metric and tracing output. In particular, servers -tag all metrics and trace data with the server's IP address and the remote port -number. To drop these attributes, use -[`otelconnect.WithoutServerPeerAttributes`][WithoutServerPeerAttributes]. For -more customizable attribute filtering, use -[otelconnect.WithFilter][WithFilter]. - -## Status - -| | Unary | Streaming Client | Streaming Handler | -|---------|:-----:|:----------------:|:-----------------:| -| Metrics | ✅ | ✅ | ✅ | -| Tracing | ✅ | ✅ | ✅ | - -## Ecosystem - -* [connect-go][connect]: Service handlers and clients for Go -* [connect-swift]: Swift clients for idiomatic gRPC & Connect RPC -* [connect-kotlin]: Kotlin clients for idiomatic gRPC & Connect RPC -* [connect-es]: Type-safe APIs with Protobuf and TypeScript. -* [Buf Studio]: web UI for ad-hoc RPCs -* [conformance]: Connect, gRPC, and gRPC-Web interoperability tests - -## Support and Versioning - -`otelconnect` supports: - -* The [two most recent major releases][go-support-policy] of Go. -* v1 of the `go.opentelemetry.io/otel` tracing and metrics SDK. - -## Legal - -Offered under the [Apache 2 license][license]. - -[Buf Studio]: https://buf.build/studio -[WithFilter]: https://pkg.go.dev/connectrpc.com/otelconnect#WithFilter -[WithTrustRemote]: https://pkg.go.dev/connectrpc.com/otelconnect#WithTrustRemote -[WithoutServerPeerAttributes]: https://pkg.go.dev/connectrpc.com/otelconnect#WithoutServerPeerAttributes -[blog]: https://buf.build/blog/connect-a-better-grpc -[conformance]: https://github.com/connectrpc/conformance -[connect]: https://github.com/connectrpc/connect-go -[connect-kotlin]: https://github.com/connectrpc/connect-kotlin -[connect-swift]: https://github.com/connectrpc/connect-swift -[connect-es]: https://github.com/connectrpc/connect-es -[docs]: https://connectrpc.com -[go-support-policy]: https://go.dev/doc/devel/release#policy -[godoc]: https://pkg.go.dev/connectrpc.com/otelconnect -[license]: https://github.com/connectrpc/otelconnect-go/blob/main/LICENSE -[opentelemetry.io]: https://opentelemetry.io/ -[otel-rpc-conventions]: https://opentelemetry.io/docs/specs/semconv/rpc/ diff --git a/vendor/connectrpc.com/otelconnect/SECURITY.md b/vendor/connectrpc.com/otelconnect/SECURITY.md deleted file mode 100644 index 04dcde52..00000000 --- a/vendor/connectrpc.com/otelconnect/SECURITY.md +++ /dev/null @@ -1,5 +0,0 @@ -Security Policy -=============== - -This project follows the [Connect security policy and reporting -process](https://connectrpc.com/docs/governance/security). diff --git a/vendor/connectrpc.com/otelconnect/attributes.go b/vendor/connectrpc.com/otelconnect/attributes.go deleted file mode 100644 index af2e7b39..00000000 --- a/vendor/connectrpc.com/otelconnect/attributes.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect - -import ( - "fmt" - "net" - "net/http" - "strconv" - "strings" - - "connectrpc.com/connect" - "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" -) - -// AttributeFilter is used to filter attributes out based on the [connect.Spec] -// and [attribute.KeyValue]. If the filter returns true the attribute will be -// kept else it will be removed. AttributeFilter must be safe to call concurrently. -type AttributeFilter func(connect.Spec, attribute.KeyValue) bool - -func (filter AttributeFilter) filter(spec connect.Spec, values ...attribute.KeyValue) []attribute.KeyValue { - if filter == nil { - return values - } - // Assign a new slice of zero length with the same underlying - // array as the values slice. This avoids unnecessary memory allocations. - filteredValues := values[:0] - for _, attr := range values { - if filter(spec, attr) { - filteredValues = append(filteredValues, attr) - } - } - clear(values[len(filteredValues):]) - return filteredValues -} - -func addProcedureAttributes(attrs []attribute.KeyValue, procedure string) []attribute.KeyValue { - svc, method, ok := strings.Cut(procedure, "/") - if !ok { - // fall back to treating the whole string as the method - return append(attrs, semconv.RPCMethodKey.String(procedure)) - } - if svc != "" { - attrs = append(attrs, semconv.RPCServiceKey.String(svc)) - } - if method != "" { - attrs = append(attrs, semconv.RPCMethodKey.String(method)) - } - return attrs -} - -func addRequestAttributes(attrs []attribute.KeyValue, spec connect.Spec, peer connect.Peer) []attribute.KeyValue { - if addr := peer.Addr; addr != "" { - attrs = addAddressAttributes(attrs, addr) - } - name := strings.TrimLeft(spec.Procedure, "/") - protocol := protocolToSemConv(peer.Protocol) - attrs = append(attrs, semconv.RPCSystemKey.String(protocol)) - attrs = addProcedureAttributes(attrs, name) - return attrs -} - -func addAddressAttributes(attrs []attribute.KeyValue, address string) []attribute.KeyValue { - if host, port, err := net.SplitHostPort(address); err == nil { - portInt, err := strconv.Atoi(port) - if err == nil { - return append(attrs, - semconv.NetPeerNameKey.String(host), - semconv.NetPeerPortKey.Int(portInt), - ) - } - } - return append(attrs, semconv.NetPeerNameKey.String(address)) -} - -func statusCodeAttribute(protocol string, serverErr error) (attribute.KeyValue, bool) { - // Following the respective specifications, use integers and "status_code" for - // gRPC codes in contrast to strings and "error_code" for Connect codes. - switch protocol { - case grpcProtocol, grpcwebProtocol: - codeKey := attribute.Key("rpc." + protocol + ".status_code") - if serverErr != nil { - return codeKey.Int64(int64(connect.CodeOf(serverErr))), true - } - return codeKey.Int64(0), true // gRPC uses 0 for success - case connectProtocol: - if connect.IsNotModifiedError(serverErr) { - // A "not modified" error is special: it's code is technically "unknown" but - // it would be misleading to label it as an unknown error since it's not really - // an error, but rather a sentinel to trigger a "304 Not Modified" HTTP status. - return semconv.HTTPStatusCodeKey.Int(http.StatusNotModified), true - } - if serverErr != nil { - codeKey := attribute.Key("rpc." + protocol + ".error_code") - return codeKey.String(connect.CodeOf(serverErr).String()), true - } - } - return attribute.KeyValue{}, false -} - -func headerAttributes(protocol, eventType string, metadata http.Header, allowedKeys []string) []attribute.KeyValue { - attributes := make([]attribute.KeyValue, 0, len(allowedKeys)) - return addHeaderAttributes(attributes, protocol, eventType, metadata, allowedKeys) -} - -func addHeaderAttributes(attributes []attribute.KeyValue, protocol, eventType string, metadata http.Header, allowedKeys []string) []attribute.KeyValue { - for _, allowedKey := range allowedKeys { - if val, ok := metadata[allowedKey]; ok { - keyValue := attribute.StringSlice( - formatHeaderAttributeKey(protocol, eventType, allowedKey), - val, - ) - attributes = append(attributes, keyValue) - } - } - return attributes -} - -// formatHeaderAttributeKey formats header attributes as suggested by the OpenTelemetry specification: -// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md#grpc-request-and-response-metadata -func formatHeaderAttributeKey(protocol, eventType, key string) string { - key = strings.ReplaceAll(strings.ToLower(key), "-", "_") - return fmt.Sprintf("rpc.%s.%s.metadata.%s", protocol, eventType, key) -} diff --git a/vendor/connectrpc.com/otelconnect/buf.gen.yaml b/vendor/connectrpc.com/otelconnect/buf.gen.yaml deleted file mode 100644 index d2baac13..00000000 --- a/vendor/connectrpc.com/otelconnect/buf.gen.yaml +++ /dev/null @@ -1,13 +0,0 @@ -version: v2 -managed: - enabled: true - override: - - file_option: go_package_prefix - value: connectrpc.com/otelconnect/internal/gen -plugins: - - local: protoc-gen-go - out: internal/gen - opt: paths=source_relative - - local: protoc-gen-connect-go - out: internal/gen - opt: paths=source_relative diff --git a/vendor/connectrpc.com/otelconnect/buf.yaml b/vendor/connectrpc.com/otelconnect/buf.yaml deleted file mode 100644 index c656dcb6..00000000 --- a/vendor/connectrpc.com/otelconnect/buf.yaml +++ /dev/null @@ -1,15 +0,0 @@ -version: v2 -modules: - - path: internal/proto -lint: - use: - - STANDARD - except: - - FIELD_NOT_REQUIRED - - PACKAGE_NO_IMPORT_CYCLE - disallow_comment_ignores: true -breaking: - use: - - WIRE_JSON - except: - - FIELD_SAME_DEFAULT diff --git a/vendor/connectrpc.com/otelconnect/doc.go b/vendor/connectrpc.com/otelconnect/doc.go deleted file mode 100644 index fa1a2317..00000000 --- a/vendor/connectrpc.com/otelconnect/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect provides OpenTelemetry tracing and metrics for -// [connectrpc.com/connect] servers and clients. -// The specification followed was the [OpenTelemetry specification] -// with both the [rpc metrics specification] -// and [rpc spans specification] implemented. -// -// [OpenTelemetry specification]: https://github.com/open-telemetry/opentelemetry-specification -// [rpc metrics specification]: https://opentelemetry.io/docs/specs/semconv/rpc/rpc-metrics/ -// [rpc spans specification]: https://opentelemetry.io/docs/specs/semconv/rpc/rpc-spans/ -package otelconnect diff --git a/vendor/connectrpc.com/otelconnect/instruments.go b/vendor/connectrpc.com/otelconnect/instruments.go deleted file mode 100644 index 04a660af..00000000 --- a/vendor/connectrpc.com/otelconnect/instruments.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect - -import ( - "fmt" - - "go.opentelemetry.io/otel/metric" -) - -const ( - metricKeyFormat = "rpc.%s.%s" - durationKey = "duration" - durationDesc = "Measures the duration of inbound RPC." - requestSizeKey = "request.size" - requestSizeDesc = "Measures size of RPC request messages (uncompressed)." - responseSizeKey = "response.size" - responseSizeDesc = "Measures size of RPC response messages (uncompressed)." - requestsPerRPCKey = "requests_per_rpc" - requestsPerRPCDesc = "Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs." - responsesPerRPCKey = "responses_per_rpc" - responsesPerRPCDesc = "Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs." - messageKey = "message" - serverKey = "server" - clientKey = "client" - requestKey = "request" - responseKey = "response" - unitDimensionless = "1" - unitBytes = "By" - unitMilliseconds = "ms" -) - -type instruments struct { - duration metric.Int64Histogram - requestSize metric.Int64Histogram - responseSize metric.Int64Histogram - requestsPerRPC metric.Int64Histogram - responsesPerRPC metric.Int64Histogram -} - -// createInstruments creates the metrics for the interceptor. -func createInstruments(meter metric.Meter, interceptorType string) (instruments, error) { - duration, err := meter.Int64Histogram( - formatkeys(interceptorType, durationKey), - metric.WithUnit(unitMilliseconds), - metric.WithDescription(durationDesc), - ) - if err != nil { - return instruments{}, err - } - requestSize, err := meter.Int64Histogram( - formatkeys(interceptorType, requestSizeKey), - metric.WithUnit(unitBytes), - metric.WithDescription(requestSizeDesc), - ) - if err != nil { - return instruments{}, err - } - responseSize, err := meter.Int64Histogram( - formatkeys(interceptorType, responseSizeKey), - metric.WithUnit(unitBytes), - metric.WithDescription(responseSizeDesc), - ) - if err != nil { - return instruments{}, err - } - requestsPerRPC, err := meter.Int64Histogram( - formatkeys(interceptorType, requestsPerRPCKey), - metric.WithUnit(unitDimensionless), - metric.WithDescription(requestsPerRPCDesc), - ) - if err != nil { - return instruments{}, err - } - responsesPerRPC, err := meter.Int64Histogram( - formatkeys(interceptorType, responsesPerRPCKey), - metric.WithUnit(unitDimensionless), - metric.WithDescription(responsesPerRPCDesc), - ) - if err != nil { - return instruments{}, err - } - return instruments{ - duration: duration, - requestSize: requestSize, - responseSize: responseSize, - requestsPerRPC: requestsPerRPC, - responsesPerRPC: responsesPerRPC, - }, nil -} - -func formatkeys(interceptorType string, metricName string) string { - return fmt.Sprintf(metricKeyFormat, interceptorType, metricName) -} diff --git a/vendor/connectrpc.com/otelconnect/interceptor.go b/vendor/connectrpc.com/otelconnect/interceptor.go deleted file mode 100644 index 79eb5ad3..00000000 --- a/vendor/connectrpc.com/otelconnect/interceptor.go +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect - -import ( - "context" - "errors" - "fmt" - "strings" - "sync" - "time" - - "connectrpc.com/connect" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/propagation" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" - "go.opentelemetry.io/otel/trace" - "google.golang.org/protobuf/proto" -) - -// Interceptor implements [connect.Interceptor] that adds -// OpenTelemetry metrics and tracing to connect handlers and clients. -type Interceptor struct { - config config - clientInstruments instruments - serverInstruments instruments -} - -var _ connect.Interceptor = &Interceptor{} - -// NewInterceptor returns an interceptor that implements [connect.Interceptor]. -// It adds OpenTelemetry metrics and tracing to connect handlers and clients. -// Use options to configure the interceptor. Any invalid options will cause an -// error to be returned. The interceptor will use the default tracer and meter -// providers. To use a custom tracer or meter provider pass in the -// [WithTracerProvider] or [WithMeterProvider] options. To disable metrics or -// tracing pass in the [WithoutMetrics] or [WithoutTracing] options. -func NewInterceptor(options ...Option) (*Interceptor, error) { - cfg := config{ - now: time.Now, - tracer: otel.GetTracerProvider().Tracer( - instrumentationName, - trace.WithInstrumentationVersion(semanticVersion), - ), - propagator: otel.GetTextMapPropagator(), - meter: otel.GetMeterProvider().Meter( - instrumentationName, - metric.WithInstrumentationVersion(semanticVersion)), - } - for _, opt := range options { - opt.apply(&cfg) - } - clientInstruments, err := createInstruments(cfg.meter, clientKey) - if err != nil { - return nil, fmt.Errorf("failed to create client instruments: %w", err) - } - serverInstruments, err := createInstruments(cfg.meter, serverKey) - if err != nil { - return nil, fmt.Errorf("failed to create server instruments: %w", err) - } - return &Interceptor{ - config: cfg, - clientInstruments: clientInstruments, - serverInstruments: serverInstruments, - }, nil -} - -// getInstruments returns the correct instrumentation for the interceptor. -func (i *Interceptor) getInstruments(isClient bool) *instruments { - if isClient { - return &i.clientInstruments - } - return &i.serverInstruments -} - -// WrapUnary implements otel tracing and metrics for unary handlers. -func (i *Interceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc { - return func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) { - requestStartTime := i.config.now() - if i.config.filter != nil { - if !i.config.filter(ctx, request.Spec()) { - return next(ctx, request) - } - } - attributeFilter := i.config.filterAttribute.filter - isClient := request.Spec().IsClient - name := strings.TrimLeft(request.Spec().Procedure, "/") - protocol := protocolToSemConv(request.Peer().Protocol) - attributes := make([]attribute.KeyValue, 0, 6+len(i.config.requestHeaderKeys)) // 5 max request attrs + status code attr + headers - attributes = attributeFilter(request.Spec(), addRequestAttributes(attributes, request.Spec(), request.Peer())...) - instrumentation := i.getInstruments(isClient) - carrier := propagation.HeaderCarrier(request.Header()) - spanKind := trace.SpanKindClient - requestSpan, responseSpan := semconv.MessageTypeSent, semconv.MessageTypeReceived - attributes = addHeaderAttributes(attributes, protocol, requestKey, request.Header(), i.config.requestHeaderKeys) - traceOpts := make([]trace.SpanStartOption, 0, 4) - traceOpts = append(traceOpts, trace.WithAttributes(attributes...)) - if !isClient { - spanKind = trace.SpanKindServer - requestSpan, responseSpan = semconv.MessageTypeReceived, semconv.MessageTypeSent - // if a span already exists in ctx then there must have already been another interceptor - // that set it, so don't extract from carrier. - if !trace.SpanContextFromContext(ctx).IsValid() { - ctx = i.config.propagator.Extract(ctx, carrier) - if !i.config.trustRemote { - traceOpts = append(traceOpts, - trace.WithNewRoot(), - trace.WithLinks(trace.LinkFromContext(ctx)), - ) - } - } - } - traceOpts = append(traceOpts, trace.WithSpanKind(spanKind)) - ctx, span := i.config.tracer.Start( - ctx, - name, - traceOpts..., - ) - defer span.End() - if isClient { - i.config.propagator.Inject(ctx, carrier) - } - var requestSize int - if request != nil { - if msg, ok := request.Any().(proto.Message); ok { - requestSize = proto.Size(msg) - } - } - if !i.config.omitTraceEvents { - span.AddEvent(messageKey, - trace.WithAttributes( - requestSpan, - semconv.MessageIDKey.Int(1), - semconv.MessageUncompressedSizeKey.Int(requestSize), - ), - ) - } - response, err := next(ctx, request) - if statusCode, ok := statusCodeAttribute(protocol, err); ok { - attributes = append(attributes, statusCode) - } - var responseSize int - if err == nil { - if msg, ok := response.Any().(proto.Message); ok { - responseSize = proto.Size(msg) - } - span.SetAttributes(headerAttributes(protocol, responseKey, response.Header(), i.config.responseHeaderKeys)...) - } - if !i.config.omitTraceEvents { - span.AddEvent(messageKey, - trace.WithAttributes( - responseSpan, - semconv.MessageIDKey.Int(1), - semconv.MessageUncompressedSizeKey.Int(responseSize), - ), - ) - } - attributes = attributeFilter(request.Spec(), attributes...) - if isClient { - span.SetStatus(clientSpanStatus(protocol, err)) - } else { - span.SetStatus(serverSpanStatus(protocol, err)) - } - span.SetAttributes(attributes...) - attributesSet := attribute.NewSet(attributes...) - instrumentation.duration.Record(ctx, i.config.now().Sub(requestStartTime).Milliseconds(), metric.WithAttributeSet(attributesSet)) - instrumentation.requestSize.Record(ctx, int64(requestSize), metric.WithAttributeSet(attributesSet)) - instrumentation.requestsPerRPC.Record(ctx, 1, metric.WithAttributeSet(attributesSet)) - instrumentation.responseSize.Record(ctx, int64(responseSize), metric.WithAttributeSet(attributesSet)) - instrumentation.responsesPerRPC.Record(ctx, 1, metric.WithAttributeSet(attributesSet)) - return response, err - } -} - -// WrapStreamingClient implements otel tracing and metrics for streaming connect clients. -func (i *Interceptor) WrapStreamingClient(next connect.StreamingClientFunc) connect.StreamingClientFunc { - return func(ctx context.Context, spec connect.Spec) connect.StreamingClientConn { - if i.config.filter != nil { - if !i.config.filter(ctx, spec) { - return next(ctx, spec) - } - } - requestStartTime := i.config.now() - name := strings.TrimLeft(spec.Procedure, "/") - // Span is closed on context cancelation or when the stream is closed. - ctx, span := i.config.tracer.Start( //nolint:spancheck - ctx, - name, - trace.WithSpanKind(trace.SpanKindClient), - ) - conn := next(ctx, spec) - instrumentation := i.getInstruments(spec.IsClient) - // inject the newly created span into the carrier - carrier := propagation.HeaderCarrier(conn.RequestHeader()) - i.config.propagator.Inject(ctx, carrier) - state := newStreamingState( - spec, - conn.Peer(), - i.config.filterAttribute, - i.config.omitTraceEvents, - instrumentation.responseSize, - instrumentation.requestSize, - ) - protocol := protocolToSemConv(conn.Peer().Protocol) - var requestOnce sync.Once - setRequestAttributes := func() { - span.SetAttributes( - headerAttributes( - protocol, - requestKey, - conn.RequestHeader(), - i.config.requestHeaderKeys, - )..., - ) - } - closeSpan := func() { - requestOnce.Do(setRequestAttributes) - state.mu.Lock() - defer state.mu.Unlock() - // state.attributes is updated with the final error that was recorded. - // If error is nil a "success" is recorded on the span and on the final duration - // metric. The "rpc..status_code" is not defined for any other metrics for - // streams because the error only exists when finishing the stream. - if statusCode, ok := statusCodeAttribute(protocol, state.error); ok { - state.addAttributes(statusCode) - } - span.SetAttributes(state.attributes...) - span.SetAttributes(headerAttributes(protocol, responseKey, conn.ResponseHeader(), i.config.responseHeaderKeys)...) - span.SetStatus(clientSpanStatus(protocol, state.error)) - span.End() - attributeSet := attribute.NewSet(state.attributes...) - instrumentation.requestsPerRPC.Record(ctx, state.sentCounter, metric.WithAttributeSet(attributeSet)) - instrumentation.responsesPerRPC.Record(ctx, state.receivedCounter, metric.WithAttributeSet(attributeSet)) - duration := i.config.now().Sub(requestStartTime).Milliseconds() - instrumentation.duration.Record(ctx, duration, metric.WithAttributeSet(attributeSet)) - } - stopCtxClose := context.AfterFunc(ctx, closeSpan) - return &streamingClientInterceptor{ //nolint:spancheck - StreamingClientConn: conn, - onClose: func() { - if stopCtxClose() { - closeSpan() - } - }, - receive: func(msg any, conn connect.StreamingClientConn) error { - return state.receive(ctx, msg, conn) - }, - send: func(msg any, conn connect.StreamingClientConn) error { - requestOnce.Do(setRequestAttributes) - return state.send(ctx, msg, conn) - }, - } - } -} - -// WrapStreamingHandler implements otel tracing and metrics for streaming connect handlers. -func (i *Interceptor) WrapStreamingHandler(next connect.StreamingHandlerFunc) connect.StreamingHandlerFunc { - return func(ctx context.Context, conn connect.StreamingHandlerConn) error { - requestStartTime := i.config.now() - isClient := conn.Spec().IsClient - instrumentation := i.getInstruments(isClient) - if i.config.filter != nil { - if !i.config.filter(ctx, conn.Spec()) { - return next(ctx, conn) - } - } - name := strings.TrimLeft(conn.Spec().Procedure, "/") - protocol := protocolToSemConv(conn.Peer().Protocol) - state := newStreamingState( - conn.Spec(), - conn.Peer(), - i.config.filterAttribute, - i.config.omitTraceEvents, - instrumentation.requestSize, - instrumentation.responseSize, - ) - // extract any request headers into the context - carrier := propagation.HeaderCarrier(conn.RequestHeader()) - traceOpts := make([]trace.SpanStartOption, 0, 5) - traceOpts = append(traceOpts, - trace.WithSpanKind(trace.SpanKindServer), - trace.WithAttributes(state.attributes...), - trace.WithAttributes(headerAttributes(protocol, requestKey, conn.RequestHeader(), i.config.requestHeaderKeys)...), - ) - if !trace.SpanContextFromContext(ctx).IsValid() { - ctx = i.config.propagator.Extract(ctx, carrier) - if !i.config.trustRemote { - traceOpts = append(traceOpts, - trace.WithNewRoot(), - trace.WithLinks(trace.LinkFromContext(ctx)), - ) - } - } - // start a new span with any trace that is in the context - ctx, span := i.config.tracer.Start( - ctx, - name, - traceOpts..., - ) - defer span.End() - streamingHandler := &streamingHandlerInterceptor{ - StreamingHandlerConn: conn, - receive: func(msg any, conn connect.StreamingHandlerConn) error { - return state.receive(ctx, msg, conn) - }, - send: func(msg any, conn connect.StreamingHandlerConn) error { - return state.send(ctx, msg, conn) - }, - } - err := next(ctx, streamingHandler) - if statusCode, ok := statusCodeAttribute(protocol, err); ok { - state.addAttributes(statusCode) - } - span.SetAttributes(state.attributes...) - span.SetAttributes(headerAttributes(protocol, responseKey, conn.ResponseHeader(), i.config.responseHeaderKeys)...) - span.SetStatus(serverSpanStatus(protocol, err)) - attributeSet := attribute.NewSet(state.attributes...) - instrumentation.requestsPerRPC.Record(ctx, state.receivedCounter, metric.WithAttributeSet(attributeSet)) - instrumentation.responsesPerRPC.Record(ctx, state.sentCounter, metric.WithAttributeSet(attributeSet)) - duration := i.config.now().Sub(requestStartTime).Milliseconds() - instrumentation.duration.Record(ctx, duration, metric.WithAttributeSet(attributeSet)) - return err - } -} - -// protocolToSemConv converts the protocol string to the OpenTelemetry format. -func protocolToSemConv(protocol string) string { - switch protocol { - case grpcwebString: - return grpcwebProtocol - case grpcProtocol: - return grpcProtocol - case connectString: - return connectProtocol - default: - return protocol - } -} - -func clientSpanStatus(protocol string, err error) (codes.Code, string) { - if err == nil { - return codes.Unset, "" - } - if protocol == connectProtocol && connect.IsNotModifiedError(err) { - return codes.Unset, "" - } - if connectErr := new(connect.Error); errors.As(err, &connectErr) { - return codes.Error, connectErr.Message() - } - return codes.Error, err.Error() -} - -func serverSpanStatus(protocol string, err error) (codes.Code, string) { - if err == nil { - return codes.Unset, "" - } - if protocol == connectProtocol && connect.IsNotModifiedError(err) { - return codes.Unset, "" - } - - if connectErr := new(connect.Error); errors.As(err, &connectErr) { - switch connectErr.Code() { - case connect.CodeUnknown, - connect.CodeDeadlineExceeded, - connect.CodeUnimplemented, - connect.CodeInternal, - connect.CodeUnavailable, - connect.CodeDataLoss: - return codes.Error, connectErr.Message() - case connect.CodeCanceled, - connect.CodeInvalidArgument, - connect.CodeNotFound, - connect.CodeAlreadyExists, - connect.CodePermissionDenied, - connect.CodeResourceExhausted, - connect.CodeFailedPrecondition, - connect.CodeAborted, - connect.CodeOutOfRange, - connect.CodeUnauthenticated: - return codes.Unset, "" - default: - return codes.Unset, "" - } - } - - return codes.Error, err.Error() -} diff --git a/vendor/connectrpc.com/otelconnect/option.go b/vendor/connectrpc.com/otelconnect/option.go deleted file mode 100644 index 1729bb47..00000000 --- a/vendor/connectrpc.com/otelconnect/option.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect - -import ( - "context" - "net/http" - - "connectrpc.com/connect" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" - metricnoop "go.opentelemetry.io/otel/metric/noop" - "go.opentelemetry.io/otel/propagation" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" - "go.opentelemetry.io/otel/trace" - tracenoop "go.opentelemetry.io/otel/trace/noop" -) - -// An Option configures the OpenTelemetry instrumentation. -type Option interface { - apply(*config) -} - -// WithPropagator configures the instrumentation to use the supplied propagator -// when extracting and injecting trace context. By default, the instrumentation -// uses otel.GetTextMapPropagator(). -func WithPropagator(propagator propagation.TextMapPropagator) Option { - return &propagatorOption{propagator} -} - -// WithMeterProvider configures the instrumentation to use the supplied [metric.MeterProvider] -// when extracting and injecting trace context. By default, the instrumentation -// uses global.MeterProvider(). -func WithMeterProvider(provider metric.MeterProvider) Option { - return &meterProviderOption{provider: provider} -} - -// WithTracerProvider configures the instrumentation to use the supplied -// provider when creating a tracer. By default, the instrumentation -// uses otel.GetTracerProvider(). -func WithTracerProvider(provider trace.TracerProvider) Option { - return &tracerProviderOption{provider} -} - -// WithFilter configures the instrumentation to emit traces and metrics only -// when the filter function returns true. Filter functions must be safe to call concurrently. -func WithFilter(filter func(context.Context, connect.Spec) bool) Option { - return &filterOption{filter} -} - -// WithoutTracing disables tracing. -func WithoutTracing() Option { - return WithTracerProvider(tracenoop.NewTracerProvider()) -} - -// WithoutMetrics disables metrics. -func WithoutMetrics() Option { - return WithMeterProvider(metricnoop.NewMeterProvider()) -} - -// WithAttributeFilter sets the attribute filter for all metrics and trace attributes. -func WithAttributeFilter(filter AttributeFilter) Option { - return &attributeFilterOption{filterAttribute: filter} -} - -// WithoutServerPeerAttributes removes net.peer.port and net.peer.name -// attributes from server trace and span attributes. The default behavior -// follows the OpenTelemetry semantic conventions for RPC, but produces very -// high-cardinality data; this option significantly reduces cardinality in most -// environments. -func WithoutServerPeerAttributes() Option { - return WithAttributeFilter(func(spec connect.Spec, value attribute.KeyValue) bool { - if spec.IsClient { - return true - } - if value.Key == semconv.NetPeerPortKey { - return false - } - if value.Key == semconv.NetPeerNameKey { - return false - } - return true - }) -} - -// WithTrustRemote sets the Interceptor to trust remote spans. -// By default, all incoming server spans are untrusted and will be linked -// with a [trace.Link] and will not be a child span. -// By default, all client spans are trusted and no change occurs when WithTrustRemote is used. -func WithTrustRemote() Option { - return &trustRemoteOption{} -} - -// WithTraceRequestHeader enables header attributes for the request header keys provided. -// Attributes will be added as Trace attributes only. -func WithTraceRequestHeader(keys ...string) Option { - return &traceRequestHeaderOption{ - keys: keys, - } -} - -// WithTraceResponseHeader enables header attributes for the response header keys provided. -// Attributes will be added as Trace attributes only. -func WithTraceResponseHeader(keys ...string) Option { - return &traceResponseHeaderOption{ - keys: keys, - } -} - -// WithoutTraceEvents disables trace events for both unary and streaming -// interceptors. This reduces the quantity of data sent to your tracing system -// by omitting per-message information like message size. -func WithoutTraceEvents() Option { - return &omitTraceEventsOption{} -} - -type attributeFilterOption struct { - filterAttribute AttributeFilter -} - -func (o *attributeFilterOption) apply(c *config) { - if o.filterAttribute != nil { - c.filterAttribute = o.filterAttribute - } -} - -type propagatorOption struct { - propagator propagation.TextMapPropagator -} - -func (o *propagatorOption) apply(c *config) { - if o.propagator != nil { - c.propagator = o.propagator - } -} - -type tracerProviderOption struct { - provider trace.TracerProvider -} - -func (o *tracerProviderOption) apply(c *config) { - if o.provider != nil { - c.tracer = o.provider.Tracer( - instrumentationName, - trace.WithInstrumentationVersion(semanticVersion), - ) - } -} - -type filterOption struct { - filter func(context.Context, connect.Spec) bool -} - -func (o *filterOption) apply(c *config) { - if o.filter != nil { - c.filter = o.filter - } -} - -type meterProviderOption struct { - provider metric.MeterProvider -} - -func (m meterProviderOption) apply(c *config) { - c.meter = m.provider.Meter( - instrumentationName, - metric.WithInstrumentationVersion(semanticVersion), - ) -} - -type trustRemoteOption struct{} - -func (o *trustRemoteOption) apply(c *config) { - c.trustRemote = true -} - -type traceRequestHeaderOption struct { - keys []string -} - -func (o *traceRequestHeaderOption) apply(c *config) { - for _, key := range o.keys { - c.requestHeaderKeys = append(c.requestHeaderKeys, http.CanonicalHeaderKey(key)) - } -} - -type traceResponseHeaderOption struct { - keys []string -} - -func (o *traceResponseHeaderOption) apply(c *config) { - for _, key := range o.keys { - c.responseHeaderKeys = append(c.responseHeaderKeys, http.CanonicalHeaderKey(key)) - } -} - -type omitTraceEventsOption struct{} - -func (o *omitTraceEventsOption) apply(c *config) { - c.omitTraceEvents = true -} diff --git a/vendor/connectrpc.com/otelconnect/otelconnect.go b/vendor/connectrpc.com/otelconnect/otelconnect.go deleted file mode 100644 index fc10f22b..00000000 --- a/vendor/connectrpc.com/otelconnect/otelconnect.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect - -import ( - "context" - "time" - - "connectrpc.com/connect" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/trace" -) - -const ( - version = "0.6.0-dev" - semanticVersion = "semver:" + version - instrumentationName = "connectrpc.com/otelconnect" - grpcProtocol = "grpc" - grpcwebString = "grpcweb" - grpcwebProtocol = "grpc_web" - connectString = "connect" - connectProtocol = "connect_rpc" -) - -type config struct { - filter func(context.Context, connect.Spec) bool - filterAttribute AttributeFilter - meter metric.Meter - tracer trace.Tracer - propagator propagation.TextMapPropagator - now func() time.Time - trustRemote bool - requestHeaderKeys []string - responseHeaderKeys []string - omitTraceEvents bool -} diff --git a/vendor/connectrpc.com/otelconnect/payloadinterceptor.go b/vendor/connectrpc.com/otelconnect/payloadinterceptor.go deleted file mode 100644 index 84a11b1f..00000000 --- a/vendor/connectrpc.com/otelconnect/payloadinterceptor.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect - -import ( - "connectrpc.com/connect" -) - -type streamingClientInterceptor struct { - connect.StreamingClientConn - - receive func(any, connect.StreamingClientConn) error - send func(any, connect.StreamingClientConn) error - onClose func() -} - -func (s *streamingClientInterceptor) Receive(msg any) error { - return s.receive(msg, s.StreamingClientConn) -} - -func (s *streamingClientInterceptor) Send(msg any) error { - return s.send(msg, s.StreamingClientConn) -} - -func (s *streamingClientInterceptor) CloseResponse() error { - err := s.StreamingClientConn.CloseResponse() - s.onClose() - return err -} - -type streamingHandlerInterceptor struct { - connect.StreamingHandlerConn - - receive func(any, connect.StreamingHandlerConn) error - send func(any, connect.StreamingHandlerConn) error -} - -func (p *streamingHandlerInterceptor) Receive(msg any) error { - return p.receive(msg, p.StreamingHandlerConn) -} - -func (p *streamingHandlerInterceptor) Send(msg any) error { - return p.send(msg, p.StreamingHandlerConn) -} diff --git a/vendor/connectrpc.com/otelconnect/streaming.go b/vendor/connectrpc.com/otelconnect/streaming.go deleted file mode 100644 index a71e0057..00000000 --- a/vendor/connectrpc.com/otelconnect/streaming.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2022-2025 The Connect 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 otelconnect - -import ( - "context" - "errors" - "io" - "sync" - - "connectrpc.com/connect" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" - "go.opentelemetry.io/otel/trace" - "google.golang.org/protobuf/proto" -) - -type streamingState struct { - mu sync.Mutex - spec connect.Spec - protocol string - attributeFilter AttributeFilter - omitTraceEvents bool - attributes []attribute.KeyValue - error error - sentCounter int64 - receivedCounter int64 - receiveSize metric.Int64Histogram - sendSize metric.Int64Histogram -} - -func newStreamingState( - spec connect.Spec, - peer connect.Peer, - attributeFilter AttributeFilter, - omitTraceEvents bool, - receiveSize, sendSize metric.Int64Histogram, -) *streamingState { - protocol := protocolToSemConv(peer.Protocol) - attributes := make([]attribute.KeyValue, 0, 6) // 5 max request attrs + status code attr - attributes = attributeFilter.filter(spec, - addRequestAttributes(attributes, spec, peer)..., - ) - return &streamingState{ - spec: spec, - protocol: protocol, - attributeFilter: attributeFilter, - omitTraceEvents: omitTraceEvents, - attributes: attributes, - receiveSize: receiveSize, - sendSize: sendSize, - } -} - -type sendReceiver interface { - Receive(any) error - Send(any) error -} - -func (s *streamingState) addAttributes(attributes ...attribute.KeyValue) { - s.attributes = append(s.attributes, s.attributeFilter.filter(s.spec, attributes...)...) -} - -func (s *streamingState) receive(ctx context.Context, msg any, conn sendReceiver) error { - err := conn.Receive(msg) - s.mu.Lock() - defer s.mu.Unlock() - if errors.Is(err, io.EOF) { - return err - } - s.receivedCounter++ - if err != nil { - s.error = err - // If error add it to the attributes because the stream is about to terminate. - // If no error don't add anything because status only exists at end of stream. - if statusCode, ok := statusCodeAttribute(s.protocol, err); ok { - s.addAttributes(statusCode) - } - } - protomsg, ok := msg.(proto.Message) - size := proto.Size(protomsg) - if !s.omitTraceEvents { - s.emitEvent(ctx, semconv.MessageTypeReceived, s.receivedCounter, size, ok) - } - s.receiveSize.Record(ctx, int64(size), metric.WithAttributes(s.attributes...)) - return err -} - -func (s *streamingState) send(ctx context.Context, msg any, conn sendReceiver) error { - err := conn.Send(msg) - s.mu.Lock() - defer s.mu.Unlock() - if errors.Is(err, io.EOF) { - return err - } - s.sentCounter++ - if err != nil { - s.error = err - // If error add it to the attributes because the stream is about to terminate. - // If no error don't add anything because status only exists at end of stream. - if statusCode, ok := statusCodeAttribute(s.protocol, err); ok { - s.addAttributes(statusCode) - } - } - protomsg, ok := msg.(proto.Message) - size := proto.Size(protomsg) - if !s.omitTraceEvents { - s.emitEvent(ctx, semconv.MessageTypeSent, s.sentCounter, size, ok) - } - s.sendSize.Record(ctx, int64(size), metric.WithAttributes(s.attributes...)) - return err -} - -func (s *streamingState) emitEvent(ctx context.Context, msgType attribute.KeyValue, msgID int64, msgSize int, hasSize bool) { - span := trace.SpanFromContext(ctx) - if !span.IsRecording() { - return - } - attrs := make([]attribute.KeyValue, 0, 3) - attrs = append(attrs, - msgType, - semconv.MessageIDKey.Int64(msgID), - ) - if hasSize { - attrs = append(attrs, semconv.MessageUncompressedSizeKey.Int(msgSize)) - } - span.AddEvent(messageKey, trace.WithAttributes( - s.attributeFilter.filter(s.spec, attrs...)..., - )) -} diff --git a/vendor/github.com/Microsoft/go-winio/.gitattributes b/vendor/github.com/Microsoft/go-winio/.gitattributes deleted file mode 100644 index 94f480de..00000000 --- a/vendor/github.com/Microsoft/go-winio/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto eol=lf \ No newline at end of file diff --git a/vendor/github.com/Microsoft/go-winio/.gitignore b/vendor/github.com/Microsoft/go-winio/.gitignore deleted file mode 100644 index 815e2066..00000000 --- a/vendor/github.com/Microsoft/go-winio/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -.vscode/ - -*.exe - -# testing -testdata - -# go workspaces -go.work -go.work.sum diff --git a/vendor/github.com/Microsoft/go-winio/.golangci.yml b/vendor/github.com/Microsoft/go-winio/.golangci.yml deleted file mode 100644 index faedfe93..00000000 --- a/vendor/github.com/Microsoft/go-winio/.golangci.yml +++ /dev/null @@ -1,147 +0,0 @@ -linters: - enable: - # style - - containedctx # struct contains a context - - dupl # duplicate code - - errname # erorrs are named correctly - - nolintlint # "//nolint" directives are properly explained - - revive # golint replacement - - unconvert # unnecessary conversions - - wastedassign - - # bugs, performance, unused, etc ... - - contextcheck # function uses a non-inherited context - - errorlint # errors not wrapped for 1.13 - - exhaustive # check exhaustiveness of enum switch statements - - gofmt # files are gofmt'ed - - gosec # security - - nilerr # returns nil even with non-nil error - - thelper # test helpers without t.Helper() - - unparam # unused function params - -issues: - exclude-dirs: - - pkg/etw/sample - - exclude-rules: - # err is very often shadowed in nested scopes - - linters: - - govet - text: '^shadow: declaration of "err" shadows declaration' - - # ignore long lines for skip autogen directives - - linters: - - revive - text: "^line-length-limit: " - source: "^//(go:generate|sys) " - - #TODO: remove after upgrading to go1.18 - # ignore comment spacing for nolint and sys directives - - linters: - - revive - text: "^comment-spacings: no space between comment delimiter and comment text" - source: "//(cspell:|nolint:|sys |todo)" - - # not on go 1.18 yet, so no any - - linters: - - revive - text: "^use-any: since GO 1.18 'interface{}' can be replaced by 'any'" - - # allow unjustified ignores of error checks in defer statements - - linters: - - nolintlint - text: "^directive `//nolint:errcheck` should provide explanation" - source: '^\s*defer ' - - # allow unjustified ignores of error lints for io.EOF - - linters: - - nolintlint - text: "^directive `//nolint:errorlint` should provide explanation" - source: '[=|!]= io.EOF' - - -linters-settings: - exhaustive: - default-signifies-exhaustive: true - govet: - enable-all: true - disable: - # struct order is often for Win32 compat - # also, ignore pointer bytes/GC issues for now until performance becomes an issue - - fieldalignment - nolintlint: - require-explanation: true - require-specific: true - revive: - # revive is more configurable than static check, so likely the preferred alternative to static-check - # (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997) - enable-all-rules: - true - # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md - rules: - # rules with required arguments - - name: argument-limit - disabled: true - - name: banned-characters - disabled: true - - name: cognitive-complexity - disabled: true - - name: cyclomatic - disabled: true - - name: file-header - disabled: true - - name: function-length - disabled: true - - name: function-result-limit - disabled: true - - name: max-public-structs - disabled: true - # geneally annoying rules - - name: add-constant # complains about any and all strings and integers - disabled: true - - name: confusing-naming # we frequently use "Foo()" and "foo()" together - disabled: true - - name: flag-parameter # excessive, and a common idiom we use - disabled: true - - name: unhandled-error # warns over common fmt.Print* and io.Close; rely on errcheck instead - disabled: true - # general config - - name: line-length-limit - arguments: - - 140 - - name: var-naming - arguments: - - [] - - - CID - - CRI - - CTRD - - DACL - - DLL - - DOS - - ETW - - FSCTL - - GCS - - GMSA - - HCS - - HV - - IO - - LCOW - - LDAP - - LPAC - - LTSC - - MMIO - - NT - - OCI - - PMEM - - PWSH - - RX - - SACl - - SID - - SMB - - TX - - VHD - - VHDX - - VMID - - VPCI - - WCOW - - WIM diff --git a/vendor/github.com/Microsoft/go-winio/CODEOWNERS b/vendor/github.com/Microsoft/go-winio/CODEOWNERS deleted file mode 100644 index ae1b4942..00000000 --- a/vendor/github.com/Microsoft/go-winio/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ - * @microsoft/containerplat diff --git a/vendor/github.com/Microsoft/go-winio/LICENSE b/vendor/github.com/Microsoft/go-winio/LICENSE deleted file mode 100644 index b8b569d7..00000000 --- a/vendor/github.com/Microsoft/go-winio/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Microsoft - -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/Microsoft/go-winio/README.md b/vendor/github.com/Microsoft/go-winio/README.md deleted file mode 100644 index 7474b4f0..00000000 --- a/vendor/github.com/Microsoft/go-winio/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# go-winio [![Build Status](https://github.com/microsoft/go-winio/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/go-winio/actions/workflows/ci.yml) - -This repository contains utilities for efficiently performing Win32 IO operations in -Go. Currently, this is focused on accessing named pipes and other file handles, and -for using named pipes as a net transport. - -This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go -to reuse the thread to schedule another goroutine. This limits support to Windows Vista and -newer operating systems. This is similar to the implementation of network sockets in Go's net -package. - -Please see the LICENSE file for licensing information. - -## Contributing - -This project welcomes contributions and suggestions. -Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that -you have the right to, and actually do, grant us the rights to use your contribution. -For details, visit [Microsoft CLA](https://cla.microsoft.com). - -When you submit a pull request, a CLA-bot will automatically determine whether you need to -provide a CLA and decorate the PR appropriately (e.g., label, comment). -Simply follow the instructions provided by the bot. -You will only need to do this once across all repos using our CLA. - -Additionally, the pull request pipeline requires the following steps to be performed before -mergining. - -### Code Sign-Off - -We require that contributors sign their commits using [`git commit --signoff`][git-commit-s] -to certify they either authored the work themselves or otherwise have permission to use it in this project. - -A range of commits can be signed off using [`git rebase --signoff`][git-rebase-s]. - -Please see [the developer certificate](https://developercertificate.org) for more info, -as well as to make sure that you can attest to the rules listed. -Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off. - -### Linting - -Code must pass a linting stage, which uses [`golangci-lint`][lint]. -The linting settings are stored in [`.golangci.yaml`](./.golangci.yaml), and can be run -automatically with VSCode by adding the following to your workspace or folder settings: - -```json - "go.lintTool": "golangci-lint", - "go.lintOnSave": "package", -``` - -Additional editor [integrations options are also available][lint-ide]. - -Alternatively, `golangci-lint` can be [installed locally][lint-install] and run from the repo root: - -```shell -# use . or specify a path to only lint a package -# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0" -> golangci-lint run ./... -``` - -### Go Generate - -The pipeline checks that auto-generated code, via `go generate`, are up to date. - -This can be done for the entire repo: - -```shell -> go generate ./... -``` - -## Code of Conduct - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - -## Special Thanks - -Thanks to [natefinch][natefinch] for the inspiration for this library. -See [npipe](https://github.com/natefinch/npipe) for another named pipe implementation. - -[lint]: https://golangci-lint.run/ -[lint-ide]: https://golangci-lint.run/usage/integrations/#editor-integration -[lint-install]: https://golangci-lint.run/usage/install/#local-installation - -[git-commit-s]: https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s -[git-rebase-s]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---signoff - -[natefinch]: https://github.com/natefinch diff --git a/vendor/github.com/Microsoft/go-winio/SECURITY.md b/vendor/github.com/Microsoft/go-winio/SECURITY.md deleted file mode 100644 index 869fdfe2..00000000 --- a/vendor/github.com/Microsoft/go-winio/SECURITY.md +++ /dev/null @@ -1,41 +0,0 @@ - - -## Security - -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). - -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. - -## Reporting Security Issues - -**Please do not report security vulnerabilities through public GitHub issues.** - -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). - -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). - -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). - -Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue - -This information will help us triage your report more quickly. - -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. - -## Preferred Languages - -We prefer all communications to be in English. - -## Policy - -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). - - diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go deleted file mode 100644 index b54341da..00000000 --- a/vendor/github.com/Microsoft/go-winio/backup.go +++ /dev/null @@ -1,287 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "encoding/binary" - "errors" - "fmt" - "io" - "os" - "runtime" - "unicode/utf16" - - "github.com/Microsoft/go-winio/internal/fs" - "golang.org/x/sys/windows" -) - -//sys backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead -//sys backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite - -const ( - BackupData = uint32(iota + 1) - BackupEaData - BackupSecurity - BackupAlternateData - BackupLink - BackupPropertyData - BackupObjectId //revive:disable-line:var-naming ID, not Id - BackupReparseData - BackupSparseBlock - BackupTxfsData -) - -const ( - StreamSparseAttributes = uint32(8) -) - -//nolint:revive // var-naming: ALL_CAPS -const ( - WRITE_DAC = windows.WRITE_DAC - WRITE_OWNER = windows.WRITE_OWNER - ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY -) - -// BackupHeader represents a backup stream of a file. -type BackupHeader struct { - //revive:disable-next-line:var-naming ID, not Id - Id uint32 // The backup stream ID - Attributes uint32 // Stream attributes - Size int64 // The size of the stream in bytes - Name string // The name of the stream (for BackupAlternateData only). - Offset int64 // The offset of the stream in the file (for BackupSparseBlock only). -} - -type win32StreamID struct { - StreamID uint32 - Attributes uint32 - Size uint64 - NameSize uint32 -} - -// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series -// of BackupHeader values. -type BackupStreamReader struct { - r io.Reader - bytesLeft int64 -} - -// NewBackupStreamReader produces a BackupStreamReader from any io.Reader. -func NewBackupStreamReader(r io.Reader) *BackupStreamReader { - return &BackupStreamReader{r, 0} -} - -// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if -// it was not completely read. -func (r *BackupStreamReader) Next() (*BackupHeader, error) { - if r.bytesLeft > 0 { //nolint:nestif // todo: flatten this - if s, ok := r.r.(io.Seeker); ok { - // Make sure Seek on io.SeekCurrent sometimes succeeds - // before trying the actual seek. - if _, err := s.Seek(0, io.SeekCurrent); err == nil { - if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil { - return nil, err - } - r.bytesLeft = 0 - } - } - if _, err := io.Copy(io.Discard, r); err != nil { - return nil, err - } - } - var wsi win32StreamID - if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil { - return nil, err - } - hdr := &BackupHeader{ - Id: wsi.StreamID, - Attributes: wsi.Attributes, - Size: int64(wsi.Size), - } - if wsi.NameSize != 0 { - name := make([]uint16, int(wsi.NameSize/2)) - if err := binary.Read(r.r, binary.LittleEndian, name); err != nil { - return nil, err - } - hdr.Name = windows.UTF16ToString(name) - } - if wsi.StreamID == BackupSparseBlock { - if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil { - return nil, err - } - hdr.Size -= 8 - } - r.bytesLeft = hdr.Size - return hdr, nil -} - -// Read reads from the current backup stream. -func (r *BackupStreamReader) Read(b []byte) (int, error) { - if r.bytesLeft == 0 { - return 0, io.EOF - } - if int64(len(b)) > r.bytesLeft { - b = b[:r.bytesLeft] - } - n, err := r.r.Read(b) - r.bytesLeft -= int64(n) - if err == io.EOF { - err = io.ErrUnexpectedEOF - } else if r.bytesLeft == 0 && err == nil { - err = io.EOF - } - return n, err -} - -// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API. -type BackupStreamWriter struct { - w io.Writer - bytesLeft int64 -} - -// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer. -func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter { - return &BackupStreamWriter{w, 0} -} - -// WriteHeader writes the next backup stream header and prepares for calls to Write(). -func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error { - if w.bytesLeft != 0 { - return fmt.Errorf("missing %d bytes", w.bytesLeft) - } - name := utf16.Encode([]rune(hdr.Name)) - wsi := win32StreamID{ - StreamID: hdr.Id, - Attributes: hdr.Attributes, - Size: uint64(hdr.Size), - NameSize: uint32(len(name) * 2), - } - if hdr.Id == BackupSparseBlock { - // Include space for the int64 block offset - wsi.Size += 8 - } - if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil { - return err - } - if len(name) != 0 { - if err := binary.Write(w.w, binary.LittleEndian, name); err != nil { - return err - } - } - if hdr.Id == BackupSparseBlock { - if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil { - return err - } - } - w.bytesLeft = hdr.Size - return nil -} - -// Write writes to the current backup stream. -func (w *BackupStreamWriter) Write(b []byte) (int, error) { - if w.bytesLeft < int64(len(b)) { - return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft) - } - n, err := w.w.Write(b) - w.bytesLeft -= int64(n) - return n, err -} - -// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API. -type BackupFileReader struct { - f *os.File - includeSecurity bool - ctx uintptr -} - -// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true, -// Read will attempt to read the security descriptor of the file. -func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader { - r := &BackupFileReader{f, includeSecurity, 0} - return r -} - -// Read reads a backup stream from the file by calling the Win32 API BackupRead(). -func (r *BackupFileReader) Read(b []byte) (int, error) { - var bytesRead uint32 - err := backupRead(windows.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) - if err != nil { - return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err} - } - runtime.KeepAlive(r.f) - if bytesRead == 0 { - return 0, io.EOF - } - return int(bytesRead), nil -} - -// Close frees Win32 resources associated with the BackupFileReader. It does not close -// the underlying file. -func (r *BackupFileReader) Close() error { - if r.ctx != 0 { - _ = backupRead(windows.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) - runtime.KeepAlive(r.f) - r.ctx = 0 - } - return nil -} - -// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API. -type BackupFileWriter struct { - f *os.File - includeSecurity bool - ctx uintptr -} - -// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true, -// Write() will attempt to restore the security descriptor from the stream. -func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter { - w := &BackupFileWriter{f, includeSecurity, 0} - return w -} - -// Write restores a portion of the file using the provided backup stream. -func (w *BackupFileWriter) Write(b []byte) (int, error) { - var bytesWritten uint32 - err := backupWrite(windows.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) - if err != nil { - return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err} - } - runtime.KeepAlive(w.f) - if int(bytesWritten) != len(b) { - return int(bytesWritten), errors.New("not all bytes could be written") - } - return len(b), nil -} - -// Close frees Win32 resources associated with the BackupFileWriter. It does not -// close the underlying file. -func (w *BackupFileWriter) Close() error { - if w.ctx != 0 { - _ = backupWrite(windows.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) - runtime.KeepAlive(w.f) - w.ctx = 0 - } - return nil -} - -// OpenForBackup opens a file or directory, potentially skipping access checks if the backup -// or restore privileges have been acquired. -// -// If the file opened was a directory, it cannot be used with Readdir(). -func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) { - h, err := fs.CreateFile(path, - fs.AccessMask(access), - fs.FileShareMode(share), - nil, - fs.FileCreationDisposition(createmode), - fs.FILE_FLAG_BACKUP_SEMANTICS|fs.FILE_FLAG_OPEN_REPARSE_POINT, - 0, - ) - if err != nil { - err = &os.PathError{Op: "open", Path: path, Err: err} - return nil, err - } - return os.NewFile(uintptr(h), path), nil -} diff --git a/vendor/github.com/Microsoft/go-winio/doc.go b/vendor/github.com/Microsoft/go-winio/doc.go deleted file mode 100644 index 1f5bfe2d..00000000 --- a/vendor/github.com/Microsoft/go-winio/doc.go +++ /dev/null @@ -1,22 +0,0 @@ -// This package provides utilities for efficiently performing Win32 IO operations in Go. -// Currently, this package is provides support for genreal IO and management of -// - named pipes -// - files -// - [Hyper-V sockets] -// -// This code is similar to Go's [net] package, and uses IO completion ports to avoid -// blocking IO on system threads, allowing Go to reuse the thread to schedule other goroutines. -// -// This limits support to Windows Vista and newer operating systems. -// -// Additionally, this package provides support for: -// - creating and managing GUIDs -// - writing to [ETW] -// - opening and manageing VHDs -// - parsing [Windows Image files] -// - auto-generating Win32 API code -// -// [Hyper-V sockets]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service -// [ETW]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw- -// [Windows Image files]: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/work-with-windows-images -package winio diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go deleted file mode 100644 index e104dbdf..00000000 --- a/vendor/github.com/Microsoft/go-winio/ea.go +++ /dev/null @@ -1,137 +0,0 @@ -package winio - -import ( - "bytes" - "encoding/binary" - "errors" -) - -type fileFullEaInformation struct { - NextEntryOffset uint32 - Flags uint8 - NameLength uint8 - ValueLength uint16 -} - -var ( - fileFullEaInformationSize = binary.Size(&fileFullEaInformation{}) - - errInvalidEaBuffer = errors.New("invalid extended attribute buffer") - errEaNameTooLarge = errors.New("extended attribute name too large") - errEaValueTooLarge = errors.New("extended attribute value too large") -) - -// ExtendedAttribute represents a single Windows EA. -type ExtendedAttribute struct { - Name string - Value []byte - Flags uint8 -} - -func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { - var info fileFullEaInformation - err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info) - if err != nil { - err = errInvalidEaBuffer - return ea, nb, err - } - - nameOffset := fileFullEaInformationSize - nameLen := int(info.NameLength) - valueOffset := nameOffset + int(info.NameLength) + 1 - valueLen := int(info.ValueLength) - nextOffset := int(info.NextEntryOffset) - if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) { - err = errInvalidEaBuffer - return ea, nb, err - } - - ea.Name = string(b[nameOffset : nameOffset+nameLen]) - ea.Value = b[valueOffset : valueOffset+valueLen] - ea.Flags = info.Flags - if info.NextEntryOffset != 0 { - nb = b[info.NextEntryOffset:] - } - return ea, nb, err -} - -// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION -// buffer retrieved from BackupRead, ZwQueryEaFile, etc. -func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { - for len(b) != 0 { - ea, nb, err := parseEa(b) - if err != nil { - return nil, err - } - - eas = append(eas, ea) - b = nb - } - return eas, err -} - -func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { - if int(uint8(len(ea.Name))) != len(ea.Name) { - return errEaNameTooLarge - } - if int(uint16(len(ea.Value))) != len(ea.Value) { - return errEaValueTooLarge - } - entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value)) - withPadding := (entrySize + 3) &^ 3 - nextOffset := uint32(0) - if !last { - nextOffset = withPadding - } - info := fileFullEaInformation{ - NextEntryOffset: nextOffset, - Flags: ea.Flags, - NameLength: uint8(len(ea.Name)), - ValueLength: uint16(len(ea.Value)), - } - - err := binary.Write(buf, binary.LittleEndian, &info) - if err != nil { - return err - } - - _, err = buf.Write([]byte(ea.Name)) - if err != nil { - return err - } - - err = buf.WriteByte(0) - if err != nil { - return err - } - - _, err = buf.Write(ea.Value) - if err != nil { - return err - } - - _, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize]) - if err != nil { - return err - } - - return nil -} - -// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION -// buffer for use with BackupWrite, ZwSetEaFile, etc. -func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) { - var buf bytes.Buffer - for i := range eas { - last := false - if i == len(eas)-1 { - last = true - } - - err := writeEa(&buf, &eas[i], last) - if err != nil { - return nil, err - } - } - return buf.Bytes(), nil -} diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go deleted file mode 100644 index fe82a180..00000000 --- a/vendor/github.com/Microsoft/go-winio/file.go +++ /dev/null @@ -1,320 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "errors" - "io" - "runtime" - "sync" - "sync/atomic" - "syscall" - "time" - - "golang.org/x/sys/windows" -) - -//sys cancelIoEx(file windows.Handle, o *windows.Overlapped) (err error) = CancelIoEx -//sys createIoCompletionPort(file windows.Handle, port windows.Handle, key uintptr, threadCount uint32) (newport windows.Handle, err error) = CreateIoCompletionPort -//sys getQueuedCompletionStatus(port windows.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus -//sys setFileCompletionNotificationModes(h windows.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes -//sys wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult - -var ( - ErrFileClosed = errors.New("file has already been closed") - ErrTimeout = &timeoutError{} -) - -type timeoutError struct{} - -func (*timeoutError) Error() string { return "i/o timeout" } -func (*timeoutError) Timeout() bool { return true } -func (*timeoutError) Temporary() bool { return true } - -type timeoutChan chan struct{} - -var ioInitOnce sync.Once -var ioCompletionPort windows.Handle - -// ioResult contains the result of an asynchronous IO operation. -type ioResult struct { - bytes uint32 - err error -} - -// ioOperation represents an outstanding asynchronous Win32 IO. -type ioOperation struct { - o windows.Overlapped - ch chan ioResult -} - -func initIO() { - h, err := createIoCompletionPort(windows.InvalidHandle, 0, 0, 0xffffffff) - if err != nil { - panic(err) - } - ioCompletionPort = h - go ioCompletionProcessor(h) -} - -// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall. -// It takes ownership of this handle and will close it if it is garbage collected. -type win32File struct { - handle windows.Handle - wg sync.WaitGroup - wgLock sync.RWMutex - closing atomic.Bool - socket bool - readDeadline deadlineHandler - writeDeadline deadlineHandler -} - -type deadlineHandler struct { - setLock sync.Mutex - channel timeoutChan - channelLock sync.RWMutex - timer *time.Timer - timedout atomic.Bool -} - -// makeWin32File makes a new win32File from an existing file handle. -func makeWin32File(h windows.Handle) (*win32File, error) { - f := &win32File{handle: h} - ioInitOnce.Do(initIO) - _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) - if err != nil { - return nil, err - } - err = setFileCompletionNotificationModes(h, windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS|windows.FILE_SKIP_SET_EVENT_ON_HANDLE) - if err != nil { - return nil, err - } - f.readDeadline.channel = make(timeoutChan) - f.writeDeadline.channel = make(timeoutChan) - return f, nil -} - -// Deprecated: use NewOpenFile instead. -func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { - return NewOpenFile(windows.Handle(h)) -} - -func NewOpenFile(h windows.Handle) (io.ReadWriteCloser, error) { - // If we return the result of makeWin32File directly, it can result in an - // interface-wrapped nil, rather than a nil interface value. - f, err := makeWin32File(h) - if err != nil { - return nil, err - } - return f, nil -} - -// closeHandle closes the resources associated with a Win32 handle. -func (f *win32File) closeHandle() { - f.wgLock.Lock() - // Atomically set that we are closing, releasing the resources only once. - if !f.closing.Swap(true) { - f.wgLock.Unlock() - // cancel all IO and wait for it to complete - _ = cancelIoEx(f.handle, nil) - f.wg.Wait() - // at this point, no new IO can start - windows.Close(f.handle) - f.handle = 0 - } else { - f.wgLock.Unlock() - } -} - -// Close closes a win32File. -func (f *win32File) Close() error { - f.closeHandle() - return nil -} - -// IsClosed checks if the file has been closed. -func (f *win32File) IsClosed() bool { - return f.closing.Load() -} - -// prepareIO prepares for a new IO operation. -// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. -func (f *win32File) prepareIO() (*ioOperation, error) { - f.wgLock.RLock() - if f.closing.Load() { - f.wgLock.RUnlock() - return nil, ErrFileClosed - } - f.wg.Add(1) - f.wgLock.RUnlock() - c := &ioOperation{} - c.ch = make(chan ioResult) - return c, nil -} - -// ioCompletionProcessor processes completed async IOs forever. -func ioCompletionProcessor(h windows.Handle) { - for { - var bytes uint32 - var key uintptr - var op *ioOperation - err := getQueuedCompletionStatus(h, &bytes, &key, &op, windows.INFINITE) - if op == nil { - panic(err) - } - op.ch <- ioResult{bytes, err} - } -} - -// todo: helsaawy - create an asyncIO version that takes a context - -// asyncIO processes the return value from ReadFile or WriteFile, blocking until -// the operation has actually completed. -func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { - if err != windows.ERROR_IO_PENDING { //nolint:errorlint // err is Errno - return int(bytes), err - } - - if f.closing.Load() { - _ = cancelIoEx(f.handle, &c.o) - } - - var timeout timeoutChan - if d != nil { - d.channelLock.Lock() - timeout = d.channel - d.channelLock.Unlock() - } - - var r ioResult - select { - case r = <-c.ch: - err = r.err - if err == windows.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno - if f.closing.Load() { - err = ErrFileClosed - } - } else if err != nil && f.socket { - // err is from Win32. Query the overlapped structure to get the winsock error. - var bytes, flags uint32 - err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags) - } - case <-timeout: - _ = cancelIoEx(f.handle, &c.o) - r = <-c.ch - err = r.err - if err == windows.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno - err = ErrTimeout - } - } - - // runtime.KeepAlive is needed, as c is passed via native - // code to ioCompletionProcessor, c must remain alive - // until the channel read is complete. - // todo: (de)allocate *ioOperation via win32 heap functions, instead of needing to KeepAlive? - runtime.KeepAlive(c) - return int(r.bytes), err -} - -// Read reads from a file handle. -func (f *win32File) Read(b []byte) (int, error) { - c, err := f.prepareIO() - if err != nil { - return 0, err - } - defer f.wg.Done() - - if f.readDeadline.timedout.Load() { - return 0, ErrTimeout - } - - var bytes uint32 - err = windows.ReadFile(f.handle, b, &bytes, &c.o) - n, err := f.asyncIO(c, &f.readDeadline, bytes, err) - runtime.KeepAlive(b) - - // Handle EOF conditions. - if err == nil && n == 0 && len(b) != 0 { - return 0, io.EOF - } else if err == windows.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno - return 0, io.EOF - } - return n, err -} - -// Write writes to a file handle. -func (f *win32File) Write(b []byte) (int, error) { - c, err := f.prepareIO() - if err != nil { - return 0, err - } - defer f.wg.Done() - - if f.writeDeadline.timedout.Load() { - return 0, ErrTimeout - } - - var bytes uint32 - err = windows.WriteFile(f.handle, b, &bytes, &c.o) - n, err := f.asyncIO(c, &f.writeDeadline, bytes, err) - runtime.KeepAlive(b) - return n, err -} - -func (f *win32File) SetReadDeadline(deadline time.Time) error { - return f.readDeadline.set(deadline) -} - -func (f *win32File) SetWriteDeadline(deadline time.Time) error { - return f.writeDeadline.set(deadline) -} - -func (f *win32File) Flush() error { - return windows.FlushFileBuffers(f.handle) -} - -func (f *win32File) Fd() uintptr { - return uintptr(f.handle) -} - -func (d *deadlineHandler) set(deadline time.Time) error { - d.setLock.Lock() - defer d.setLock.Unlock() - - if d.timer != nil { - if !d.timer.Stop() { - <-d.channel - } - d.timer = nil - } - d.timedout.Store(false) - - select { - case <-d.channel: - d.channelLock.Lock() - d.channel = make(chan struct{}) - d.channelLock.Unlock() - default: - } - - if deadline.IsZero() { - return nil - } - - timeoutIO := func() { - d.timedout.Store(true) - close(d.channel) - } - - now := time.Now() - duration := deadline.Sub(now) - if deadline.After(now) { - // Deadline is in the future, set a timer to wait - d.timer = time.AfterFunc(duration, timeoutIO) - } else { - // Deadline is in the past. Cancel all pending IO now. - timeoutIO() - } - return nil -} diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go deleted file mode 100644 index c860eb99..00000000 --- a/vendor/github.com/Microsoft/go-winio/fileinfo.go +++ /dev/null @@ -1,106 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "os" - "runtime" - "unsafe" - - "golang.org/x/sys/windows" -) - -// FileBasicInfo contains file access time and file attributes information. -type FileBasicInfo struct { - CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime - FileAttributes uint32 - _ uint32 // padding -} - -// alignedFileBasicInfo is a FileBasicInfo, but aligned to uint64 by containing -// uint64 rather than windows.Filetime. Filetime contains two uint32s. uint64 -// alignment is necessary to pass this as FILE_BASIC_INFO. -type alignedFileBasicInfo struct { - CreationTime, LastAccessTime, LastWriteTime, ChangeTime uint64 - FileAttributes uint32 - _ uint32 // padding -} - -// GetFileBasicInfo retrieves times and attributes for a file. -func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { - bi := &alignedFileBasicInfo{} - if err := windows.GetFileInformationByHandleEx( - windows.Handle(f.Fd()), - windows.FileBasicInfo, - (*byte)(unsafe.Pointer(bi)), - uint32(unsafe.Sizeof(*bi)), - ); err != nil { - return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} - } - runtime.KeepAlive(f) - // Reinterpret the alignedFileBasicInfo as a FileBasicInfo so it matches the - // public API of this module. The data may be unnecessarily aligned. - return (*FileBasicInfo)(unsafe.Pointer(bi)), nil -} - -// SetFileBasicInfo sets times and attributes for a file. -func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { - // Create an alignedFileBasicInfo based on a FileBasicInfo. The copy is - // suitable to pass to GetFileInformationByHandleEx. - biAligned := *(*alignedFileBasicInfo)(unsafe.Pointer(bi)) - if err := windows.SetFileInformationByHandle( - windows.Handle(f.Fd()), - windows.FileBasicInfo, - (*byte)(unsafe.Pointer(&biAligned)), - uint32(unsafe.Sizeof(biAligned)), - ); err != nil { - return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} - } - runtime.KeepAlive(f) - return nil -} - -// FileStandardInfo contains extended information for the file. -// FILE_STANDARD_INFO in WinBase.h -// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info -type FileStandardInfo struct { - AllocationSize, EndOfFile int64 - NumberOfLinks uint32 - DeletePending, Directory bool -} - -// GetFileStandardInfo retrieves ended information for the file. -func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { - si := &FileStandardInfo{} - if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), - windows.FileStandardInfo, - (*byte)(unsafe.Pointer(si)), - uint32(unsafe.Sizeof(*si))); err != nil { - return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} - } - runtime.KeepAlive(f) - return si, nil -} - -// FileIDInfo contains the volume serial number and file ID for a file. This pair should be -// unique on a system. -type FileIDInfo struct { - VolumeSerialNumber uint64 - FileID [16]byte -} - -// GetFileID retrieves the unique (volume, file ID) pair for a file. -func GetFileID(f *os.File) (*FileIDInfo, error) { - fileID := &FileIDInfo{} - if err := windows.GetFileInformationByHandleEx( - windows.Handle(f.Fd()), - windows.FileIdInfo, - (*byte)(unsafe.Pointer(fileID)), - uint32(unsafe.Sizeof(*fileID)), - ); err != nil { - return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} - } - runtime.KeepAlive(f) - return fileID, nil -} diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go deleted file mode 100644 index c4fdd9d4..00000000 --- a/vendor/github.com/Microsoft/go-winio/hvsock.go +++ /dev/null @@ -1,582 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "context" - "errors" - "fmt" - "io" - "net" - "os" - "time" - "unsafe" - - "golang.org/x/sys/windows" - - "github.com/Microsoft/go-winio/internal/socket" - "github.com/Microsoft/go-winio/pkg/guid" -) - -const afHVSock = 34 // AF_HYPERV - -// Well known Service and VM IDs -// https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards - -// HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions. -func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000 - return guid.GUID{} -} - -// HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions. -func HvsockGUIDBroadcast() guid.GUID { // ffffffff-ffff-ffff-ffff-ffffffffffff - return guid.GUID{ - Data1: 0xffffffff, - Data2: 0xffff, - Data3: 0xffff, - Data4: [8]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - } -} - -// HvsockGUIDLoopback is the Loopback VmId for accepting connections to the same partition as the connector. -func HvsockGUIDLoopback() guid.GUID { // e0e16197-dd56-4a10-9195-5ee7a155a838 - return guid.GUID{ - Data1: 0xe0e16197, - Data2: 0xdd56, - Data3: 0x4a10, - Data4: [8]uint8{0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38}, - } -} - -// HvsockGUIDSiloHost is the address of a silo's host partition: -// - The silo host of a hosted silo is the utility VM. -// - The silo host of a silo on a physical host is the physical host. -func HvsockGUIDSiloHost() guid.GUID { // 36bd0c5c-7276-4223-88ba-7d03b654c568 - return guid.GUID{ - Data1: 0x36bd0c5c, - Data2: 0x7276, - Data3: 0x4223, - Data4: [8]byte{0x88, 0xba, 0x7d, 0x03, 0xb6, 0x54, 0xc5, 0x68}, - } -} - -// HvsockGUIDChildren is the wildcard VmId for accepting connections from the connector's child partitions. -func HvsockGUIDChildren() guid.GUID { // 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd - return guid.GUID{ - Data1: 0x90db8b89, - Data2: 0xd35, - Data3: 0x4f79, - Data4: [8]uint8{0x8c, 0xe9, 0x49, 0xea, 0xa, 0xc8, 0xb7, 0xcd}, - } -} - -// HvsockGUIDParent is the wildcard VmId for accepting connections from the connector's parent partition. -// Listening on this VmId accepts connection from: -// - Inside silos: silo host partition. -// - Inside hosted silo: host of the VM. -// - Inside VM: VM host. -// - Physical host: Not supported. -func HvsockGUIDParent() guid.GUID { // a42e7cda-d03f-480c-9cc2-a4de20abb878 - return guid.GUID{ - Data1: 0xa42e7cda, - Data2: 0xd03f, - Data3: 0x480c, - Data4: [8]uint8{0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78}, - } -} - -// hvsockVsockServiceTemplate is the Service GUID used for the VSOCK protocol. -func hvsockVsockServiceTemplate() guid.GUID { // 00000000-facb-11e6-bd58-64006a7986d3 - return guid.GUID{ - Data2: 0xfacb, - Data3: 0x11e6, - Data4: [8]uint8{0xbd, 0x58, 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3}, - } -} - -// An HvsockAddr is an address for a AF_HYPERV socket. -type HvsockAddr struct { - VMID guid.GUID - ServiceID guid.GUID -} - -type rawHvsockAddr struct { - Family uint16 - _ uint16 - VMID guid.GUID - ServiceID guid.GUID -} - -var _ socket.RawSockaddr = &rawHvsockAddr{} - -// Network returns the address's network name, "hvsock". -func (*HvsockAddr) Network() string { - return "hvsock" -} - -func (addr *HvsockAddr) String() string { - return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID) -} - -// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port. -func VsockServiceID(port uint32) guid.GUID { - g := hvsockVsockServiceTemplate() // make a copy - g.Data1 = port - return g -} - -func (addr *HvsockAddr) raw() rawHvsockAddr { - return rawHvsockAddr{ - Family: afHVSock, - VMID: addr.VMID, - ServiceID: addr.ServiceID, - } -} - -func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) { - addr.VMID = raw.VMID - addr.ServiceID = raw.ServiceID -} - -// Sockaddr returns a pointer to and the size of this struct. -// -// Implements the [socket.RawSockaddr] interface, and allows use in -// [socket.Bind] and [socket.ConnectEx]. -func (r *rawHvsockAddr) Sockaddr() (unsafe.Pointer, int32, error) { - return unsafe.Pointer(r), int32(unsafe.Sizeof(rawHvsockAddr{})), nil -} - -// Sockaddr interface allows use with `sockets.Bind()` and `.ConnectEx()`. -func (r *rawHvsockAddr) FromBytes(b []byte) error { - n := int(unsafe.Sizeof(rawHvsockAddr{})) - - if len(b) < n { - return fmt.Errorf("got %d, want %d: %w", len(b), n, socket.ErrBufferSize) - } - - copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), b[:n]) - if r.Family != afHVSock { - return fmt.Errorf("got %d, want %d: %w", r.Family, afHVSock, socket.ErrAddrFamily) - } - - return nil -} - -// HvsockListener is a socket listener for the AF_HYPERV address family. -type HvsockListener struct { - sock *win32File - addr HvsockAddr -} - -var _ net.Listener = &HvsockListener{} - -// HvsockConn is a connected socket of the AF_HYPERV address family. -type HvsockConn struct { - sock *win32File - local, remote HvsockAddr -} - -var _ net.Conn = &HvsockConn{} - -func newHVSocket() (*win32File, error) { - fd, err := windows.Socket(afHVSock, windows.SOCK_STREAM, 1) - if err != nil { - return nil, os.NewSyscallError("socket", err) - } - f, err := makeWin32File(fd) - if err != nil { - windows.Close(fd) - return nil, err - } - f.socket = true - return f, nil -} - -// ListenHvsock listens for connections on the specified hvsock address. -func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { - l := &HvsockListener{addr: *addr} - - var sock *win32File - sock, err = newHVSocket() - if err != nil { - return nil, l.opErr("listen", err) - } - defer func() { - if err != nil { - _ = sock.Close() - } - }() - - sa := addr.raw() - err = socket.Bind(sock.handle, &sa) - if err != nil { - return nil, l.opErr("listen", os.NewSyscallError("socket", err)) - } - err = windows.Listen(sock.handle, 16) - if err != nil { - return nil, l.opErr("listen", os.NewSyscallError("listen", err)) - } - return &HvsockListener{sock: sock, addr: *addr}, nil -} - -func (l *HvsockListener) opErr(op string, err error) error { - return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err} -} - -// Addr returns the listener's network address. -func (l *HvsockListener) Addr() net.Addr { - return &l.addr -} - -// Accept waits for the next connection and returns it. -func (l *HvsockListener) Accept() (_ net.Conn, err error) { - sock, err := newHVSocket() - if err != nil { - return nil, l.opErr("accept", err) - } - defer func() { - if sock != nil { - sock.Close() - } - }() - c, err := l.sock.prepareIO() - if err != nil { - return nil, l.opErr("accept", err) - } - defer l.sock.wg.Done() - - // AcceptEx, per documentation, requires an extra 16 bytes per address. - // - // https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex - const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{})) - var addrbuf [addrlen * 2]byte - - var bytes uint32 - err = windows.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o) - if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil { - return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) - } - - conn := &HvsockConn{ - sock: sock, - } - // The local address returned in the AcceptEx buffer is the same as the Listener socket's - // address. However, the service GUID reported by GetSockName is different from the Listeners - // socket, and is sometimes the same as the local address of the socket that dialed the - // address, with the service GUID.Data1 incremented, but othertimes is different. - // todo: does the local address matter? is the listener's address or the actual address appropriate? - conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0]))) - conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen]))) - - // initialize the accepted socket and update its properties with those of the listening socket - if err = windows.Setsockopt(sock.handle, - windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT, - (*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil { - return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err)) - } - - sock = nil - return conn, nil -} - -// Close closes the listener, causing any pending Accept calls to fail. -func (l *HvsockListener) Close() error { - return l.sock.Close() -} - -// HvsockDialer configures and dials a Hyper-V Socket (ie, [HvsockConn]). -type HvsockDialer struct { - // Deadline is the time the Dial operation must connect before erroring. - Deadline time.Time - - // Retries is the number of additional connects to try if the connection times out, is refused, - // or the host is unreachable - Retries uint - - // RetryWait is the time to wait after a connection error to retry - RetryWait time.Duration - - rt *time.Timer // redial wait timer -} - -// Dial the Hyper-V socket at addr. -// -// See [HvsockDialer.Dial] for more information. -func Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) { - return (&HvsockDialer{}).Dial(ctx, addr) -} - -// Dial attempts to connect to the Hyper-V socket at addr, and returns a connection if successful. -// Will attempt (HvsockDialer).Retries if dialing fails, waiting (HvsockDialer).RetryWait between -// retries. -// -// Dialing can be cancelled either by providing (HvsockDialer).Deadline, or cancelling ctx. -func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) { - op := "dial" - // create the conn early to use opErr() - conn = &HvsockConn{ - remote: *addr, - } - - if !d.Deadline.IsZero() { - var cancel context.CancelFunc - ctx, cancel = context.WithDeadline(ctx, d.Deadline) - defer cancel() - } - - // preemptive timeout/cancellation check - if err = ctx.Err(); err != nil { - return nil, conn.opErr(op, err) - } - - sock, err := newHVSocket() - if err != nil { - return nil, conn.opErr(op, err) - } - defer func() { - if sock != nil { - sock.Close() - } - }() - - sa := addr.raw() - err = socket.Bind(sock.handle, &sa) - if err != nil { - return nil, conn.opErr(op, os.NewSyscallError("bind", err)) - } - - c, err := sock.prepareIO() - if err != nil { - return nil, conn.opErr(op, err) - } - defer sock.wg.Done() - var bytes uint32 - for i := uint(0); i <= d.Retries; i++ { - err = socket.ConnectEx( - sock.handle, - &sa, - nil, // sendBuf - 0, // sendDataLen - &bytes, - (*windows.Overlapped)(unsafe.Pointer(&c.o))) - _, err = sock.asyncIO(c, nil, bytes, err) - if i < d.Retries && canRedial(err) { - if err = d.redialWait(ctx); err == nil { - continue - } - } - break - } - if err != nil { - return nil, conn.opErr(op, os.NewSyscallError("connectex", err)) - } - - // update the connection properties, so shutdown can be used - if err = windows.Setsockopt( - sock.handle, - windows.SOL_SOCKET, - windows.SO_UPDATE_CONNECT_CONTEXT, - nil, // optvalue - 0, // optlen - ); err != nil { - return nil, conn.opErr(op, os.NewSyscallError("setsockopt", err)) - } - - // get the local name - var sal rawHvsockAddr - err = socket.GetSockName(sock.handle, &sal) - if err != nil { - return nil, conn.opErr(op, os.NewSyscallError("getsockname", err)) - } - conn.local.fromRaw(&sal) - - // one last check for timeout, since asyncIO doesn't check the context - if err = ctx.Err(); err != nil { - return nil, conn.opErr(op, err) - } - - conn.sock = sock - sock = nil - - return conn, nil -} - -// redialWait waits before attempting to redial, resetting the timer as appropriate. -func (d *HvsockDialer) redialWait(ctx context.Context) (err error) { - if d.RetryWait == 0 { - return nil - } - - if d.rt == nil { - d.rt = time.NewTimer(d.RetryWait) - } else { - // should already be stopped and drained - d.rt.Reset(d.RetryWait) - } - - select { - case <-ctx.Done(): - case <-d.rt.C: - return nil - } - - // stop and drain the timer - if !d.rt.Stop() { - <-d.rt.C - } - return ctx.Err() -} - -// assumes error is a plain, unwrapped windows.Errno provided by direct syscall. -func canRedial(err error) bool { - //nolint:errorlint // guaranteed to be an Errno - switch err { - case windows.WSAECONNREFUSED, windows.WSAENETUNREACH, windows.WSAETIMEDOUT, - windows.ERROR_CONNECTION_REFUSED, windows.ERROR_CONNECTION_UNAVAIL: - return true - default: - return false - } -} - -func (conn *HvsockConn) opErr(op string, err error) error { - // translate from "file closed" to "socket closed" - if errors.Is(err, ErrFileClosed) { - err = socket.ErrSocketClosed - } - return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err} -} - -func (conn *HvsockConn) Read(b []byte) (int, error) { - c, err := conn.sock.prepareIO() - if err != nil { - return 0, conn.opErr("read", err) - } - defer conn.sock.wg.Done() - buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))} - var flags, bytes uint32 - err = windows.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) - n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err) - if err != nil { - var eno windows.Errno - if errors.As(err, &eno) { - err = os.NewSyscallError("wsarecv", eno) - } - return 0, conn.opErr("read", err) - } else if n == 0 { - err = io.EOF - } - return n, err -} - -func (conn *HvsockConn) Write(b []byte) (int, error) { - t := 0 - for len(b) != 0 { - n, err := conn.write(b) - if err != nil { - return t + n, err - } - t += n - b = b[n:] - } - return t, nil -} - -func (conn *HvsockConn) write(b []byte) (int, error) { - c, err := conn.sock.prepareIO() - if err != nil { - return 0, conn.opErr("write", err) - } - defer conn.sock.wg.Done() - buf := windows.WSABuf{Buf: &b[0], Len: uint32(len(b))} - var bytes uint32 - err = windows.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) - n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err) - if err != nil { - var eno windows.Errno - if errors.As(err, &eno) { - err = os.NewSyscallError("wsasend", eno) - } - return 0, conn.opErr("write", err) - } - return n, err -} - -// Close closes the socket connection, failing any pending read or write calls. -func (conn *HvsockConn) Close() error { - return conn.sock.Close() -} - -func (conn *HvsockConn) IsClosed() bool { - return conn.sock.IsClosed() -} - -// shutdown disables sending or receiving on a socket. -func (conn *HvsockConn) shutdown(how int) error { - if conn.IsClosed() { - return socket.ErrSocketClosed - } - - err := windows.Shutdown(conn.sock.handle, how) - if err != nil { - // If the connection was closed, shutdowns fail with "not connected" - if errors.Is(err, windows.WSAENOTCONN) || - errors.Is(err, windows.WSAESHUTDOWN) { - err = socket.ErrSocketClosed - } - return os.NewSyscallError("shutdown", err) - } - return nil -} - -// CloseRead shuts down the read end of the socket, preventing future read operations. -func (conn *HvsockConn) CloseRead() error { - err := conn.shutdown(windows.SHUT_RD) - if err != nil { - return conn.opErr("closeread", err) - } - return nil -} - -// CloseWrite shuts down the write end of the socket, preventing future write operations and -// notifying the other endpoint that no more data will be written. -func (conn *HvsockConn) CloseWrite() error { - err := conn.shutdown(windows.SHUT_WR) - if err != nil { - return conn.opErr("closewrite", err) - } - return nil -} - -// LocalAddr returns the local address of the connection. -func (conn *HvsockConn) LocalAddr() net.Addr { - return &conn.local -} - -// RemoteAddr returns the remote address of the connection. -func (conn *HvsockConn) RemoteAddr() net.Addr { - return &conn.remote -} - -// SetDeadline implements the net.Conn SetDeadline method. -func (conn *HvsockConn) SetDeadline(t time.Time) error { - // todo: implement `SetDeadline` for `win32File` - if err := conn.SetReadDeadline(t); err != nil { - return fmt.Errorf("set read deadline: %w", err) - } - if err := conn.SetWriteDeadline(t); err != nil { - return fmt.Errorf("set write deadline: %w", err) - } - return nil -} - -// SetReadDeadline implements the net.Conn SetReadDeadline method. -func (conn *HvsockConn) SetReadDeadline(t time.Time) error { - return conn.sock.SetReadDeadline(t) -} - -// SetWriteDeadline implements the net.Conn SetWriteDeadline method. -func (conn *HvsockConn) SetWriteDeadline(t time.Time) error { - return conn.sock.SetWriteDeadline(t) -} diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/doc.go b/vendor/github.com/Microsoft/go-winio/internal/fs/doc.go deleted file mode 100644 index 1f653881..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// This package contains Win32 filesystem functionality. -package fs diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go b/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go deleted file mode 100644 index 0cd9621d..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go +++ /dev/null @@ -1,262 +0,0 @@ -//go:build windows - -package fs - -import ( - "golang.org/x/sys/windows" - - "github.com/Microsoft/go-winio/internal/stringbuffer" -) - -//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go - -// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew -//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW - -const NullHandle windows.Handle = 0 - -// AccessMask defines standard, specific, and generic rights. -// -// Used with CreateFile and NtCreateFile (and co.). -// -// Bitmask: -// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 -// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -// +---------------+---------------+-------------------------------+ -// |G|G|G|G|Resvd|A| StandardRights| SpecificRights | -// |R|W|E|A| |S| | | -// +-+-------------+---------------+-------------------------------+ -// -// GR Generic Read -// GW Generic Write -// GE Generic Exectue -// GA Generic All -// Resvd Reserved -// AS Access Security System -// -// https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask -// -// https://learn.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights -// -// https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants -type AccessMask = windows.ACCESS_MASK - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - // Not actually any. - // - // For CreateFile: "query certain metadata such as file, directory, or device attributes without accessing that file or device" - // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters - FILE_ANY_ACCESS AccessMask = 0 - - GENERIC_READ AccessMask = 0x8000_0000 - GENERIC_WRITE AccessMask = 0x4000_0000 - GENERIC_EXECUTE AccessMask = 0x2000_0000 - GENERIC_ALL AccessMask = 0x1000_0000 - ACCESS_SYSTEM_SECURITY AccessMask = 0x0100_0000 - - // Specific Object Access - // from ntioapi.h - - FILE_READ_DATA AccessMask = (0x0001) // file & pipe - FILE_LIST_DIRECTORY AccessMask = (0x0001) // directory - - FILE_WRITE_DATA AccessMask = (0x0002) // file & pipe - FILE_ADD_FILE AccessMask = (0x0002) // directory - - FILE_APPEND_DATA AccessMask = (0x0004) // file - FILE_ADD_SUBDIRECTORY AccessMask = (0x0004) // directory - FILE_CREATE_PIPE_INSTANCE AccessMask = (0x0004) // named pipe - - FILE_READ_EA AccessMask = (0x0008) // file & directory - FILE_READ_PROPERTIES AccessMask = FILE_READ_EA - - FILE_WRITE_EA AccessMask = (0x0010) // file & directory - FILE_WRITE_PROPERTIES AccessMask = FILE_WRITE_EA - - FILE_EXECUTE AccessMask = (0x0020) // file - FILE_TRAVERSE AccessMask = (0x0020) // directory - - FILE_DELETE_CHILD AccessMask = (0x0040) // directory - - FILE_READ_ATTRIBUTES AccessMask = (0x0080) // all - - FILE_WRITE_ATTRIBUTES AccessMask = (0x0100) // all - - FILE_ALL_ACCESS AccessMask = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF) - FILE_GENERIC_READ AccessMask = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE) - FILE_GENERIC_WRITE AccessMask = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE) - FILE_GENERIC_EXECUTE AccessMask = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE) - - SPECIFIC_RIGHTS_ALL AccessMask = 0x0000FFFF - - // Standard Access - // from ntseapi.h - - DELETE AccessMask = 0x0001_0000 - READ_CONTROL AccessMask = 0x0002_0000 - WRITE_DAC AccessMask = 0x0004_0000 - WRITE_OWNER AccessMask = 0x0008_0000 - SYNCHRONIZE AccessMask = 0x0010_0000 - - STANDARD_RIGHTS_REQUIRED AccessMask = 0x000F_0000 - - STANDARD_RIGHTS_READ AccessMask = READ_CONTROL - STANDARD_RIGHTS_WRITE AccessMask = READ_CONTROL - STANDARD_RIGHTS_EXECUTE AccessMask = READ_CONTROL - - STANDARD_RIGHTS_ALL AccessMask = 0x001F_0000 -) - -type FileShareMode uint32 - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - FILE_SHARE_NONE FileShareMode = 0x00 - FILE_SHARE_READ FileShareMode = 0x01 - FILE_SHARE_WRITE FileShareMode = 0x02 - FILE_SHARE_DELETE FileShareMode = 0x04 - FILE_SHARE_VALID_FLAGS FileShareMode = 0x07 -) - -type FileCreationDisposition uint32 - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - // from winbase.h - - CREATE_NEW FileCreationDisposition = 0x01 - CREATE_ALWAYS FileCreationDisposition = 0x02 - OPEN_EXISTING FileCreationDisposition = 0x03 - OPEN_ALWAYS FileCreationDisposition = 0x04 - TRUNCATE_EXISTING FileCreationDisposition = 0x05 -) - -// Create disposition values for NtCreate* -type NTFileCreationDisposition uint32 - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - // From ntioapi.h - - FILE_SUPERSEDE NTFileCreationDisposition = 0x00 - FILE_OPEN NTFileCreationDisposition = 0x01 - FILE_CREATE NTFileCreationDisposition = 0x02 - FILE_OPEN_IF NTFileCreationDisposition = 0x03 - FILE_OVERWRITE NTFileCreationDisposition = 0x04 - FILE_OVERWRITE_IF NTFileCreationDisposition = 0x05 - FILE_MAXIMUM_DISPOSITION NTFileCreationDisposition = 0x05 -) - -// CreateFile and co. take flags or attributes together as one parameter. -// Define alias until we can use generics to allow both -// -// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants -type FileFlagOrAttribute uint32 - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - // from winnt.h - - FILE_FLAG_WRITE_THROUGH FileFlagOrAttribute = 0x8000_0000 - FILE_FLAG_OVERLAPPED FileFlagOrAttribute = 0x4000_0000 - FILE_FLAG_NO_BUFFERING FileFlagOrAttribute = 0x2000_0000 - FILE_FLAG_RANDOM_ACCESS FileFlagOrAttribute = 0x1000_0000 - FILE_FLAG_SEQUENTIAL_SCAN FileFlagOrAttribute = 0x0800_0000 - FILE_FLAG_DELETE_ON_CLOSE FileFlagOrAttribute = 0x0400_0000 - FILE_FLAG_BACKUP_SEMANTICS FileFlagOrAttribute = 0x0200_0000 - FILE_FLAG_POSIX_SEMANTICS FileFlagOrAttribute = 0x0100_0000 - FILE_FLAG_OPEN_REPARSE_POINT FileFlagOrAttribute = 0x0020_0000 - FILE_FLAG_OPEN_NO_RECALL FileFlagOrAttribute = 0x0010_0000 - FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000 -) - -// NtCreate* functions take a dedicated CreateOptions parameter. -// -// https://learn.microsoft.com/en-us/windows/win32/api/Winternl/nf-winternl-ntcreatefile -// -// https://learn.microsoft.com/en-us/windows/win32/devnotes/nt-create-named-pipe-file -type NTCreateOptions uint32 - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - // From ntioapi.h - - FILE_DIRECTORY_FILE NTCreateOptions = 0x0000_0001 - FILE_WRITE_THROUGH NTCreateOptions = 0x0000_0002 - FILE_SEQUENTIAL_ONLY NTCreateOptions = 0x0000_0004 - FILE_NO_INTERMEDIATE_BUFFERING NTCreateOptions = 0x0000_0008 - - FILE_SYNCHRONOUS_IO_ALERT NTCreateOptions = 0x0000_0010 - FILE_SYNCHRONOUS_IO_NONALERT NTCreateOptions = 0x0000_0020 - FILE_NON_DIRECTORY_FILE NTCreateOptions = 0x0000_0040 - FILE_CREATE_TREE_CONNECTION NTCreateOptions = 0x0000_0080 - - FILE_COMPLETE_IF_OPLOCKED NTCreateOptions = 0x0000_0100 - FILE_NO_EA_KNOWLEDGE NTCreateOptions = 0x0000_0200 - FILE_DISABLE_TUNNELING NTCreateOptions = 0x0000_0400 - FILE_RANDOM_ACCESS NTCreateOptions = 0x0000_0800 - - FILE_DELETE_ON_CLOSE NTCreateOptions = 0x0000_1000 - FILE_OPEN_BY_FILE_ID NTCreateOptions = 0x0000_2000 - FILE_OPEN_FOR_BACKUP_INTENT NTCreateOptions = 0x0000_4000 - FILE_NO_COMPRESSION NTCreateOptions = 0x0000_8000 -) - -type FileSQSFlag = FileFlagOrAttribute - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - // from winbase.h - - SECURITY_ANONYMOUS FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16) - SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16) - SECURITY_IMPERSONATION FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16) - SECURITY_DELEGATION FileSQSFlag = FileSQSFlag(SecurityDelegation << 16) - - SECURITY_SQOS_PRESENT FileSQSFlag = 0x0010_0000 - SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F_0000 -) - -// GetFinalPathNameByHandle flags -// -// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew#parameters -type GetFinalPathFlag uint32 - -//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. -const ( - GetFinalPathDefaultFlag GetFinalPathFlag = 0x0 - - FILE_NAME_NORMALIZED GetFinalPathFlag = 0x0 - FILE_NAME_OPENED GetFinalPathFlag = 0x8 - - VOLUME_NAME_DOS GetFinalPathFlag = 0x0 - VOLUME_NAME_GUID GetFinalPathFlag = 0x1 - VOLUME_NAME_NT GetFinalPathFlag = 0x2 - VOLUME_NAME_NONE GetFinalPathFlag = 0x4 -) - -// getFinalPathNameByHandle facilitates calling the Windows API GetFinalPathNameByHandle -// with the given handle and flags. It transparently takes care of creating a buffer of the -// correct size for the call. -// -// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew -func GetFinalPathNameByHandle(h windows.Handle, flags GetFinalPathFlag) (string, error) { - b := stringbuffer.NewWString() - //TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n? - for { - n, err := windows.GetFinalPathNameByHandle(h, b.Pointer(), b.Cap(), uint32(flags)) - if err != nil { - return "", err - } - // If the buffer wasn't large enough, n will be the total size needed (including null terminator). - // Resize and try again. - if n > b.Cap() { - b.ResizeTo(n) - continue - } - // If the buffer is large enough, n will be the size not including the null terminator. - // Convert to a Go string and return. - return b.String(), nil - } -} diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/security.go b/vendor/github.com/Microsoft/go-winio/internal/fs/security.go deleted file mode 100644 index 81760ac6..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/security.go +++ /dev/null @@ -1,12 +0,0 @@ -package fs - -// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level -type SecurityImpersonationLevel int32 // C default enums underlying type is `int`, which is Go `int32` - -// Impersonation levels -const ( - SecurityAnonymous SecurityImpersonationLevel = 0 - SecurityIdentification SecurityImpersonationLevel = 1 - SecurityImpersonation SecurityImpersonationLevel = 2 - SecurityDelegation SecurityImpersonationLevel = 3 -) diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go deleted file mode 100644 index a94e234c..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go +++ /dev/null @@ -1,61 +0,0 @@ -//go:build windows - -// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. - -package fs - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) - errERROR_EINVAL error = syscall.EINVAL -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return errERROR_EINVAL - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - return e -} - -var ( - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - - procCreateFileW = modkernel32.NewProc("CreateFileW") -) - -func CreateFile(name string, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(name) - if err != nil { - return - } - return _CreateFile(_p0, access, mode, sa, createmode, attrs, templatefile) -} - -func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *windows.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { - r0, _, e1 := syscall.SyscallN(procCreateFileW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile)) - handle = windows.Handle(r0) - if handle == windows.InvalidHandle { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go b/vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go deleted file mode 100644 index 7e82f9af..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go +++ /dev/null @@ -1,20 +0,0 @@ -package socket - -import ( - "unsafe" -) - -// RawSockaddr allows structs to be used with [Bind] and [ConnectEx]. The -// struct must meet the Win32 sockaddr requirements specified here: -// https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2 -// -// Specifically, the struct size must be least larger than an int16 (unsigned short) -// for the address family. -type RawSockaddr interface { - // Sockaddr returns a pointer to the RawSockaddr and its struct size, allowing - // for the RawSockaddr's data to be overwritten by syscalls (if necessary). - // - // It is the callers responsibility to validate that the values are valid; invalid - // pointers or size can cause a panic. - Sockaddr() (unsafe.Pointer, int32, error) -} diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go b/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go deleted file mode 100644 index 88580d97..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go +++ /dev/null @@ -1,177 +0,0 @@ -//go:build windows - -package socket - -import ( - "errors" - "fmt" - "net" - "sync" - "syscall" - "unsafe" - - "github.com/Microsoft/go-winio/pkg/guid" - "golang.org/x/sys/windows" -) - -//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go socket.go - -//sys getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getsockname -//sys getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getpeername -//sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind - -const socketError = uintptr(^uint32(0)) - -var ( - // todo(helsaawy): create custom error types to store the desired vs actual size and addr family? - - ErrBufferSize = errors.New("buffer size") - ErrAddrFamily = errors.New("address family") - ErrInvalidPointer = errors.New("invalid pointer") - ErrSocketClosed = fmt.Errorf("socket closed: %w", net.ErrClosed) -) - -// todo(helsaawy): replace these with generics, ie: GetSockName[S RawSockaddr](s windows.Handle) (S, error) - -// GetSockName writes the local address of socket s to the [RawSockaddr] rsa. -// If rsa is not large enough, the [windows.WSAEFAULT] is returned. -func GetSockName(s windows.Handle, rsa RawSockaddr) error { - ptr, l, err := rsa.Sockaddr() - if err != nil { - return fmt.Errorf("could not retrieve socket pointer and size: %w", err) - } - - // although getsockname returns WSAEFAULT if the buffer is too small, it does not set - // &l to the correct size, so--apart from doubling the buffer repeatedly--there is no remedy - return getsockname(s, ptr, &l) -} - -// GetPeerName returns the remote address the socket is connected to. -// -// See [GetSockName] for more information. -func GetPeerName(s windows.Handle, rsa RawSockaddr) error { - ptr, l, err := rsa.Sockaddr() - if err != nil { - return fmt.Errorf("could not retrieve socket pointer and size: %w", err) - } - - return getpeername(s, ptr, &l) -} - -func Bind(s windows.Handle, rsa RawSockaddr) (err error) { - ptr, l, err := rsa.Sockaddr() - if err != nil { - return fmt.Errorf("could not retrieve socket pointer and size: %w", err) - } - - return bind(s, ptr, l) -} - -// "golang.org/x/sys/windows".ConnectEx and .Bind only accept internal implementations of the -// their sockaddr interface, so they cannot be used with HvsockAddr -// Replicate functionality here from -// https://cs.opensource.google/go/x/sys/+/master:windows/syscall_windows.go - -// The function pointers to `AcceptEx`, `ConnectEx` and `GetAcceptExSockaddrs` must be loaded at -// runtime via a WSAIoctl call: -// https://docs.microsoft.com/en-us/windows/win32/api/Mswsock/nc-mswsock-lpfn_connectex#remarks - -type runtimeFunc struct { - id guid.GUID - once sync.Once - addr uintptr - err error -} - -func (f *runtimeFunc) Load() error { - f.once.Do(func() { - var s windows.Handle - s, f.err = windows.Socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP) - if f.err != nil { - return - } - defer windows.CloseHandle(s) //nolint:errcheck - - var n uint32 - f.err = windows.WSAIoctl(s, - windows.SIO_GET_EXTENSION_FUNCTION_POINTER, - (*byte)(unsafe.Pointer(&f.id)), - uint32(unsafe.Sizeof(f.id)), - (*byte)(unsafe.Pointer(&f.addr)), - uint32(unsafe.Sizeof(f.addr)), - &n, - nil, // overlapped - 0, // completionRoutine - ) - }) - return f.err -} - -var ( - // todo: add `AcceptEx` and `GetAcceptExSockaddrs` - WSAID_CONNECTEX = guid.GUID{ //revive:disable-line:var-naming ALL_CAPS - Data1: 0x25a207b9, - Data2: 0xddf3, - Data3: 0x4660, - Data4: [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, - } - - connectExFunc = runtimeFunc{id: WSAID_CONNECTEX} -) - -func ConnectEx( - fd windows.Handle, - rsa RawSockaddr, - sendBuf *byte, - sendDataLen uint32, - bytesSent *uint32, - overlapped *windows.Overlapped, -) error { - if err := connectExFunc.Load(); err != nil { - return fmt.Errorf("failed to load ConnectEx function pointer: %w", err) - } - ptr, n, err := rsa.Sockaddr() - if err != nil { - return err - } - return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) -} - -// BOOL LpfnConnectex( -// [in] SOCKET s, -// [in] const sockaddr *name, -// [in] int namelen, -// [in, optional] PVOID lpSendBuffer, -// [in] DWORD dwSendDataLength, -// [out] LPDWORD lpdwBytesSent, -// [in] LPOVERLAPPED lpOverlapped -// ) - -func connectEx( - s windows.Handle, - name unsafe.Pointer, - namelen int32, - sendBuf *byte, - sendDataLen uint32, - bytesSent *uint32, - overlapped *windows.Overlapped, -) (err error) { - r1, _, e1 := syscall.SyscallN(connectExFunc.addr, - uintptr(s), - uintptr(name), - uintptr(namelen), - uintptr(unsafe.Pointer(sendBuf)), - uintptr(sendDataLen), - uintptr(unsafe.Pointer(bytesSent)), - uintptr(unsafe.Pointer(overlapped)), - ) - - if r1 == 0 { - if e1 != 0 { - err = error(e1) - } else { - err = syscall.EINVAL - } - } - return err -} diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go deleted file mode 100644 index e1504126..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build windows - -// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. - -package socket - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) - errERROR_EINVAL error = syscall.EINVAL -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return errERROR_EINVAL - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - return e -} - -var ( - modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") - - procbind = modws2_32.NewProc("bind") - procgetpeername = modws2_32.NewProc("getpeername") - procgetsockname = modws2_32.NewProc("getsockname") -) - -func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.SyscallN(procbind.Addr(), uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socketError { - err = errnoErr(e1) - } - return -} - -func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { - r1, _, e1 := syscall.SyscallN(procgetpeername.Addr(), uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) - if r1 == socketError { - err = errnoErr(e1) - } - return -} - -func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { - r1, _, e1 := syscall.SyscallN(procgetsockname.Addr(), uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) - if r1 == socketError { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go b/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go deleted file mode 100644 index 42ebc019..00000000 --- a/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go +++ /dev/null @@ -1,132 +0,0 @@ -package stringbuffer - -import ( - "sync" - "unicode/utf16" -) - -// TODO: worth exporting and using in mkwinsyscall? - -// Uint16BufferSize is the buffer size in the pool, chosen somewhat arbitrarily to accommodate -// large path strings: -// MAX_PATH (260) + size of volume GUID prefix (49) + null terminator = 310. -const MinWStringCap = 310 - -// use *[]uint16 since []uint16 creates an extra allocation where the slice header -// is copied to heap and then referenced via pointer in the interface header that sync.Pool -// stores. -var pathPool = sync.Pool{ // if go1.18+ adds Pool[T], use that to store []uint16 directly - New: func() interface{} { - b := make([]uint16, MinWStringCap) - return &b - }, -} - -func newBuffer() []uint16 { return *(pathPool.Get().(*[]uint16)) } - -// freeBuffer copies the slice header data, and puts a pointer to that in the pool. -// This avoids taking a pointer to the slice header in WString, which can be set to nil. -func freeBuffer(b []uint16) { pathPool.Put(&b) } - -// WString is a wide string buffer ([]uint16) meant for storing UTF-16 encoded strings -// for interacting with Win32 APIs. -// Sizes are specified as uint32 and not int. -// -// It is not thread safe. -type WString struct { - // type-def allows casting to []uint16 directly, use struct to prevent that and allow adding fields in the future. - - // raw buffer - b []uint16 -} - -// NewWString returns a [WString] allocated from a shared pool with an -// initial capacity of at least [MinWStringCap]. -// Since the buffer may have been previously used, its contents are not guaranteed to be empty. -// -// The buffer should be freed via [WString.Free] -func NewWString() *WString { - return &WString{ - b: newBuffer(), - } -} - -func (b *WString) Free() { - if b.empty() { - return - } - freeBuffer(b.b) - b.b = nil -} - -// ResizeTo grows the buffer to at least c and returns the new capacity, freeing the -// previous buffer back into pool. -func (b *WString) ResizeTo(c uint32) uint32 { - // already sufficient (or n is 0) - if c <= b.Cap() { - return b.Cap() - } - - if c <= MinWStringCap { - c = MinWStringCap - } - // allocate at-least double buffer size, as is done in [bytes.Buffer] and other places - if c <= 2*b.Cap() { - c = 2 * b.Cap() - } - - b2 := make([]uint16, c) - if !b.empty() { - copy(b2, b.b) - freeBuffer(b.b) - } - b.b = b2 - return c -} - -// Buffer returns the underlying []uint16 buffer. -func (b *WString) Buffer() []uint16 { - if b.empty() { - return nil - } - return b.b -} - -// Pointer returns a pointer to the first uint16 in the buffer. -// If the [WString.Free] has already been called, the pointer will be nil. -func (b *WString) Pointer() *uint16 { - if b.empty() { - return nil - } - return &b.b[0] -} - -// String returns the returns the UTF-8 encoding of the UTF-16 string in the buffer. -// -// It assumes that the data is null-terminated. -func (b *WString) String() string { - // Using [windows.UTF16ToString] would require importing "golang.org/x/sys/windows" - // and would make this code Windows-only, which makes no sense. - // So copy UTF16ToString code into here. - // If other windows-specific code is added, switch to [windows.UTF16ToString] - - s := b.b - for i, v := range s { - if v == 0 { - s = s[:i] - break - } - } - return string(utf16.Decode(s)) -} - -// Cap returns the underlying buffer capacity. -func (b *WString) Cap() uint32 { - if b.empty() { - return 0 - } - return b.cap() -} - -func (b *WString) cap() uint32 { return uint32(cap(b.b)) } -func (b *WString) empty() bool { return b == nil || b.cap() == 0 } diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go deleted file mode 100644 index a2da6639..00000000 --- a/vendor/github.com/Microsoft/go-winio/pipe.go +++ /dev/null @@ -1,586 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "context" - "errors" - "fmt" - "io" - "net" - "os" - "runtime" - "time" - "unsafe" - - "golang.org/x/sys/windows" - - "github.com/Microsoft/go-winio/internal/fs" -) - -//sys connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) = ConnectNamedPipe -//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateNamedPipeW -//sys disconnectNamedPipe(pipe windows.Handle) (err error) = DisconnectNamedPipe -//sys getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo -//sys getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW -//sys ntCreateNamedPipeFile(pipe *windows.Handle, access ntAccessMask, oa *objectAttributes, iosb *ioStatusBlock, share ntFileShareMode, disposition ntFileCreationDisposition, options ntFileOptions, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile -//sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb -//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U -//sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl - -type PipeConn interface { - net.Conn - Disconnect() error - Flush() error -} - -// type aliases for mkwinsyscall code -type ( - ntAccessMask = fs.AccessMask - ntFileShareMode = fs.FileShareMode - ntFileCreationDisposition = fs.NTFileCreationDisposition - ntFileOptions = fs.NTCreateOptions -) - -type ioStatusBlock struct { - Status, Information uintptr -} - -// typedef struct _OBJECT_ATTRIBUTES { -// ULONG Length; -// HANDLE RootDirectory; -// PUNICODE_STRING ObjectName; -// ULONG Attributes; -// PVOID SecurityDescriptor; -// PVOID SecurityQualityOfService; -// } OBJECT_ATTRIBUTES; -// -// https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes -type objectAttributes struct { - Length uintptr - RootDirectory uintptr - ObjectName *unicodeString - Attributes uintptr - SecurityDescriptor *securityDescriptor - SecurityQoS uintptr -} - -type unicodeString struct { - Length uint16 - MaximumLength uint16 - Buffer uintptr -} - -// typedef struct _SECURITY_DESCRIPTOR { -// BYTE Revision; -// BYTE Sbz1; -// SECURITY_DESCRIPTOR_CONTROL Control; -// PSID Owner; -// PSID Group; -// PACL Sacl; -// PACL Dacl; -// } SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR; -// -// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-security_descriptor -type securityDescriptor struct { - Revision byte - Sbz1 byte - Control uint16 - Owner uintptr - Group uintptr - Sacl uintptr //revive:disable-line:var-naming SACL, not Sacl - Dacl uintptr //revive:disable-line:var-naming DACL, not Dacl -} - -type ntStatus int32 - -func (status ntStatus) Err() error { - if status >= 0 { - return nil - } - return rtlNtStatusToDosError(status) -} - -var ( - // ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed. - ErrPipeListenerClosed = net.ErrClosed - - errPipeWriteClosed = errors.New("pipe has been closed for write") -) - -type win32Pipe struct { - *win32File - path string -} - -var _ PipeConn = (*win32Pipe)(nil) - -type win32MessageBytePipe struct { - win32Pipe - writeClosed bool - readEOF bool -} - -type pipeAddress string - -func (f *win32Pipe) LocalAddr() net.Addr { - return pipeAddress(f.path) -} - -func (f *win32Pipe) RemoteAddr() net.Addr { - return pipeAddress(f.path) -} - -func (f *win32Pipe) SetDeadline(t time.Time) error { - if err := f.SetReadDeadline(t); err != nil { - return err - } - return f.SetWriteDeadline(t) -} - -func (f *win32Pipe) Disconnect() error { - return disconnectNamedPipe(f.win32File.handle) -} - -// CloseWrite closes the write side of a message pipe in byte mode. -func (f *win32MessageBytePipe) CloseWrite() error { - if f.writeClosed { - return errPipeWriteClosed - } - err := f.win32File.Flush() - if err != nil { - return err - } - _, err = f.win32File.Write(nil) - if err != nil { - return err - } - f.writeClosed = true - return nil -} - -// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since -// they are used to implement CloseWrite(). -func (f *win32MessageBytePipe) Write(b []byte) (int, error) { - if f.writeClosed { - return 0, errPipeWriteClosed - } - if len(b) == 0 { - return 0, nil - } - return f.win32File.Write(b) -} - -// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message -// mode pipe will return io.EOF, as will all subsequent reads. -func (f *win32MessageBytePipe) Read(b []byte) (int, error) { - if f.readEOF { - return 0, io.EOF - } - n, err := f.win32File.Read(b) - if err == io.EOF { //nolint:errorlint - // If this was the result of a zero-byte read, then - // it is possible that the read was due to a zero-size - // message. Since we are simulating CloseWrite with a - // zero-byte message, ensure that all future Read() calls - // also return EOF. - f.readEOF = true - } else if err == windows.ERROR_MORE_DATA { //nolint:errorlint // err is Errno - // ERROR_MORE_DATA indicates that the pipe's read mode is message mode - // and the message still has more bytes. Treat this as a success, since - // this package presents all named pipes as byte streams. - err = nil - } - return n, err -} - -func (pipeAddress) Network() string { - return "pipe" -} - -func (s pipeAddress) String() string { - return string(s) -} - -// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout. -func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask, impLevel PipeImpLevel) (windows.Handle, error) { - for { - select { - case <-ctx.Done(): - return windows.Handle(0), ctx.Err() - default: - h, err := fs.CreateFile(*path, - access, - 0, // mode - nil, // security attributes - fs.OPEN_EXISTING, - fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.FileSQSFlag(impLevel), - 0, // template file handle - ) - if err == nil { - return h, nil - } - if err != windows.ERROR_PIPE_BUSY { //nolint:errorlint // err is Errno - return h, &os.PathError{Err: err, Op: "open", Path: *path} - } - // Wait 10 msec and try again. This is a rather simplistic - // view, as we always try each 10 milliseconds. - time.Sleep(10 * time.Millisecond) - } - } -} - -// DialPipe connects to a named pipe by path, timing out if the connection -// takes longer than the specified duration. If timeout is nil, then we use -// a default timeout of 2 seconds. (We do not use WaitNamedPipe.) -func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { - var absTimeout time.Time - if timeout != nil { - absTimeout = time.Now().Add(*timeout) - } else { - absTimeout = time.Now().Add(2 * time.Second) - } - ctx, cancel := context.WithDeadline(context.Background(), absTimeout) - defer cancel() - conn, err := DialPipeContext(ctx, path) - if errors.Is(err, context.DeadlineExceeded) { - return nil, ErrTimeout - } - return conn, err -} - -// DialPipeContext attempts to connect to a named pipe by `path` until `ctx` -// cancellation or timeout. -func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { - return DialPipeAccess(ctx, path, uint32(fs.GENERIC_READ|fs.GENERIC_WRITE)) -} - -// PipeImpLevel is an enumeration of impersonation levels that may be set -// when calling DialPipeAccessImpersonation. -type PipeImpLevel uint32 - -const ( - PipeImpLevelAnonymous = PipeImpLevel(fs.SECURITY_ANONYMOUS) - PipeImpLevelIdentification = PipeImpLevel(fs.SECURITY_IDENTIFICATION) - PipeImpLevelImpersonation = PipeImpLevel(fs.SECURITY_IMPERSONATION) - PipeImpLevelDelegation = PipeImpLevel(fs.SECURITY_DELEGATION) -) - -// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx` -// cancellation or timeout. -func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) { - return DialPipeAccessImpLevel(ctx, path, access, PipeImpLevelAnonymous) -} - -// DialPipeAccessImpLevel attempts to connect to a named pipe by `path` with -// `access` at `impLevel` until `ctx` cancellation or timeout. The other -// DialPipe* implementations use PipeImpLevelAnonymous. -func DialPipeAccessImpLevel(ctx context.Context, path string, access uint32, impLevel PipeImpLevel) (net.Conn, error) { - var err error - var h windows.Handle - h, err = tryDialPipe(ctx, &path, fs.AccessMask(access), impLevel) - if err != nil { - return nil, err - } - - var flags uint32 - err = getNamedPipeInfo(h, &flags, nil, nil, nil) - if err != nil { - return nil, err - } - - f, err := makeWin32File(h) - if err != nil { - windows.Close(h) - return nil, err - } - - // If the pipe is in message mode, return a message byte pipe, which - // supports CloseWrite(). - if flags&windows.PIPE_TYPE_MESSAGE != 0 { - return &win32MessageBytePipe{ - win32Pipe: win32Pipe{win32File: f, path: path}, - }, nil - } - return &win32Pipe{win32File: f, path: path}, nil -} - -type acceptResponse struct { - f *win32File - err error -} - -type win32PipeListener struct { - firstHandle windows.Handle - path string - config PipeConfig - acceptCh chan (chan acceptResponse) - closeCh chan int - doneCh chan int -} - -func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (windows.Handle, error) { - path16, err := windows.UTF16FromString(path) - if err != nil { - return 0, &os.PathError{Op: "open", Path: path, Err: err} - } - - var oa objectAttributes - oa.Length = unsafe.Sizeof(oa) - - var ntPath unicodeString - if err := rtlDosPathNameToNtPathName(&path16[0], - &ntPath, - 0, - 0, - ).Err(); err != nil { - return 0, &os.PathError{Op: "open", Path: path, Err: err} - } - defer windows.LocalFree(windows.Handle(ntPath.Buffer)) //nolint:errcheck - oa.ObjectName = &ntPath - oa.Attributes = windows.OBJ_CASE_INSENSITIVE - - // The security descriptor is only needed for the first pipe. - if first { - if sd != nil { - //todo: does `sdb` need to be allocated on the heap, or can go allocate it? - l := uint32(len(sd)) - sdb, err := windows.LocalAlloc(0, l) - if err != nil { - return 0, fmt.Errorf("LocalAlloc for security descriptor with of length %d: %w", l, err) - } - defer windows.LocalFree(windows.Handle(sdb)) //nolint:errcheck - copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) - oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) - } else { - // Construct the default named pipe security descriptor. - var dacl uintptr - if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { - return 0, fmt.Errorf("getting default named pipe ACL: %w", err) - } - defer windows.LocalFree(windows.Handle(dacl)) //nolint:errcheck - - sdb := &securityDescriptor{ - Revision: 1, - Control: windows.SE_DACL_PRESENT, - Dacl: dacl, - } - oa.SecurityDescriptor = sdb - } - } - - typ := uint32(windows.FILE_PIPE_REJECT_REMOTE_CLIENTS) - if c.MessageMode { - typ |= windows.FILE_PIPE_MESSAGE_TYPE - } - - disposition := fs.FILE_OPEN - access := fs.GENERIC_READ | fs.GENERIC_WRITE | fs.SYNCHRONIZE - if first { - disposition = fs.FILE_CREATE - // By not asking for read or write access, the named pipe file system - // will put this pipe into an initially disconnected state, blocking - // client connections until the next call with first == false. - access = fs.SYNCHRONIZE - } - - timeout := int64(-50 * 10000) // 50ms - - var ( - h windows.Handle - iosb ioStatusBlock - ) - err = ntCreateNamedPipeFile(&h, - access, - &oa, - &iosb, - fs.FILE_SHARE_READ|fs.FILE_SHARE_WRITE, - disposition, - 0, - typ, - 0, - 0, - 0xffffffff, - uint32(c.InputBufferSize), - uint32(c.OutputBufferSize), - &timeout).Err() - if err != nil { - return 0, &os.PathError{Op: "open", Path: path, Err: err} - } - - runtime.KeepAlive(ntPath) - return h, nil -} - -func (l *win32PipeListener) makeServerPipe() (*win32File, error) { - h, err := makeServerPipeHandle(l.path, nil, &l.config, false) - if err != nil { - return nil, err - } - f, err := makeWin32File(h) - if err != nil { - windows.Close(h) - return nil, err - } - return f, nil -} - -func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) { - p, err := l.makeServerPipe() - if err != nil { - return nil, err - } - - // Wait for the client to connect. - ch := make(chan error) - go func(p *win32File) { - ch <- connectPipe(p) - }(p) - - select { - case err = <-ch: - if err != nil { - p.Close() - p = nil - } - case <-l.closeCh: - // Abort the connect request by closing the handle. - p.Close() - p = nil - err = <-ch - if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno - err = ErrPipeListenerClosed - } - } - return p, err -} - -func (l *win32PipeListener) listenerRoutine() { - closed := false - for !closed { - select { - case <-l.closeCh: - closed = true - case responseCh := <-l.acceptCh: - var ( - p *win32File - err error - ) - for { - p, err = l.makeConnectedServerPipe() - // If the connection was immediately closed by the client, try - // again. - if err != windows.ERROR_NO_DATA { //nolint:errorlint // err is Errno - break - } - } - responseCh <- acceptResponse{p, err} - closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno - } - } - windows.Close(l.firstHandle) - l.firstHandle = 0 - // Notify Close() and Accept() callers that the handle has been closed. - close(l.doneCh) -} - -// PipeConfig contain configuration for the pipe listener. -type PipeConfig struct { - // SecurityDescriptor contains a Windows security descriptor in SDDL format. - SecurityDescriptor string - - // MessageMode determines whether the pipe is in byte or message mode. In either - // case the pipe is read in byte mode by default. The only practical difference in - // this implementation is that CloseWrite() is only supported for message mode pipes; - // CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only - // transferred to the reader (and returned as io.EOF in this implementation) - // when the pipe is in message mode. - MessageMode bool - - // InputBufferSize specifies the size of the input buffer, in bytes. - InputBufferSize int32 - - // OutputBufferSize specifies the size of the output buffer, in bytes. - OutputBufferSize int32 -} - -// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe. -// The pipe must not already exist. -func ListenPipe(path string, c *PipeConfig) (net.Listener, error) { - var ( - sd []byte - err error - ) - if c == nil { - c = &PipeConfig{} - } - if c.SecurityDescriptor != "" { - sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor) - if err != nil { - return nil, err - } - } - h, err := makeServerPipeHandle(path, sd, c, true) - if err != nil { - return nil, err - } - l := &win32PipeListener{ - firstHandle: h, - path: path, - config: *c, - acceptCh: make(chan (chan acceptResponse)), - closeCh: make(chan int), - doneCh: make(chan int), - } - go l.listenerRoutine() - return l, nil -} - -func connectPipe(p *win32File) error { - c, err := p.prepareIO() - if err != nil { - return err - } - defer p.wg.Done() - - err = connectNamedPipe(p.handle, &c.o) - _, err = p.asyncIO(c, nil, 0, err) - if err != nil && err != windows.ERROR_PIPE_CONNECTED { //nolint:errorlint // err is Errno - return err - } - return nil -} - -func (l *win32PipeListener) Accept() (net.Conn, error) { - ch := make(chan acceptResponse) - select { - case l.acceptCh <- ch: - response := <-ch - err := response.err - if err != nil { - return nil, err - } - if l.config.MessageMode { - return &win32MessageBytePipe{ - win32Pipe: win32Pipe{win32File: response.f, path: l.path}, - }, nil - } - return &win32Pipe{win32File: response.f, path: l.path}, nil - case <-l.doneCh: - return nil, ErrPipeListenerClosed - } -} - -func (l *win32PipeListener) Close() error { - select { - case l.closeCh <- 1: - <-l.doneCh - case <-l.doneCh: - } - return nil -} - -func (l *win32PipeListener) Addr() net.Addr { - return pipeAddress(l.path) -} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go deleted file mode 100644 index 48ce4e92..00000000 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go +++ /dev/null @@ -1,232 +0,0 @@ -// Package guid provides a GUID type. The backing structure for a GUID is -// identical to that used by the golang.org/x/sys/windows GUID type. -// There are two main binary encodings used for a GUID, the big-endian encoding, -// and the Windows (mixed-endian) encoding. See here for details: -// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding -package guid - -import ( - "crypto/rand" - "crypto/sha1" //nolint:gosec // not used for secure application - "encoding" - "encoding/binary" - "fmt" - "strconv" -) - -//go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment - -// Variant specifies which GUID variant (or "type") of the GUID. It determines -// how the entirety of the rest of the GUID is interpreted. -type Variant uint8 - -// The variants specified by RFC 4122 section 4.1.1. -const ( - // VariantUnknown specifies a GUID variant which does not conform to one of - // the variant encodings specified in RFC 4122. - VariantUnknown Variant = iota - VariantNCS - VariantRFC4122 // RFC 4122 - VariantMicrosoft - VariantFuture -) - -// Version specifies how the bits in the GUID were generated. For instance, a -// version 4 GUID is randomly generated, and a version 5 is generated from the -// hash of an input string. -type Version uint8 - -func (v Version) String() string { - return strconv.FormatUint(uint64(v), 10) -} - -var _ = (encoding.TextMarshaler)(GUID{}) -var _ = (encoding.TextUnmarshaler)(&GUID{}) - -// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122. -func NewV4() (GUID, error) { - var b [16]byte - if _, err := rand.Read(b[:]); err != nil { - return GUID{}, err - } - - g := FromArray(b) - g.setVersion(4) // Version 4 means randomly generated. - g.setVariant(VariantRFC4122) - - return g, nil -} - -// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing) -// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name, -// and the sample code treats it as a series of bytes, so we do the same here. -// -// Some implementations, such as those found on Windows, treat the name as a -// big-endian UTF16 stream of bytes. If that is desired, the string can be -// encoded as such before being passed to this function. -func NewV5(namespace GUID, name []byte) (GUID, error) { - b := sha1.New() //nolint:gosec // not used for secure application - namespaceBytes := namespace.ToArray() - b.Write(namespaceBytes[:]) - b.Write(name) - - a := [16]byte{} - copy(a[:], b.Sum(nil)) - - g := FromArray(a) - g.setVersion(5) // Version 5 means generated from a string. - g.setVariant(VariantRFC4122) - - return g, nil -} - -func fromArray(b [16]byte, order binary.ByteOrder) GUID { - var g GUID - g.Data1 = order.Uint32(b[0:4]) - g.Data2 = order.Uint16(b[4:6]) - g.Data3 = order.Uint16(b[6:8]) - copy(g.Data4[:], b[8:16]) - return g -} - -func (g GUID) toArray(order binary.ByteOrder) [16]byte { - b := [16]byte{} - order.PutUint32(b[0:4], g.Data1) - order.PutUint16(b[4:6], g.Data2) - order.PutUint16(b[6:8], g.Data3) - copy(b[8:16], g.Data4[:]) - return b -} - -// FromArray constructs a GUID from a big-endian encoding array of 16 bytes. -func FromArray(b [16]byte) GUID { - return fromArray(b, binary.BigEndian) -} - -// ToArray returns an array of 16 bytes representing the GUID in big-endian -// encoding. -func (g GUID) ToArray() [16]byte { - return g.toArray(binary.BigEndian) -} - -// FromWindowsArray constructs a GUID from a Windows encoding array of bytes. -func FromWindowsArray(b [16]byte) GUID { - return fromArray(b, binary.LittleEndian) -} - -// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows -// encoding. -func (g GUID) ToWindowsArray() [16]byte { - return g.toArray(binary.LittleEndian) -} - -func (g GUID) String() string { - return fmt.Sprintf( - "%08x-%04x-%04x-%04x-%012x", - g.Data1, - g.Data2, - g.Data3, - g.Data4[:2], - g.Data4[2:]) -} - -// FromString parses a string containing a GUID and returns the GUID. The only -// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` -// format. -func FromString(s string) (GUID, error) { - if len(s) != 36 { - return GUID{}, fmt.Errorf("invalid GUID %q", s) - } - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return GUID{}, fmt.Errorf("invalid GUID %q", s) - } - - var g GUID - - data1, err := strconv.ParseUint(s[0:8], 16, 32) - if err != nil { - return GUID{}, fmt.Errorf("invalid GUID %q", s) - } - g.Data1 = uint32(data1) - - data2, err := strconv.ParseUint(s[9:13], 16, 16) - if err != nil { - return GUID{}, fmt.Errorf("invalid GUID %q", s) - } - g.Data2 = uint16(data2) - - data3, err := strconv.ParseUint(s[14:18], 16, 16) - if err != nil { - return GUID{}, fmt.Errorf("invalid GUID %q", s) - } - g.Data3 = uint16(data3) - - for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} { - v, err := strconv.ParseUint(s[x:x+2], 16, 8) - if err != nil { - return GUID{}, fmt.Errorf("invalid GUID %q", s) - } - g.Data4[i] = uint8(v) - } - - return g, nil -} - -func (g *GUID) setVariant(v Variant) { - d := g.Data4[0] - switch v { - case VariantNCS: - d = (d & 0x7f) - case VariantRFC4122: - d = (d & 0x3f) | 0x80 - case VariantMicrosoft: - d = (d & 0x1f) | 0xc0 - case VariantFuture: - d = (d & 0x0f) | 0xe0 - case VariantUnknown: - fallthrough - default: - panic(fmt.Sprintf("invalid variant: %d", v)) - } - g.Data4[0] = d -} - -// Variant returns the GUID variant, as defined in RFC 4122. -func (g GUID) Variant() Variant { - b := g.Data4[0] - if b&0x80 == 0 { - return VariantNCS - } else if b&0xc0 == 0x80 { - return VariantRFC4122 - } else if b&0xe0 == 0xc0 { - return VariantMicrosoft - } else if b&0xe0 == 0xe0 { - return VariantFuture - } - return VariantUnknown -} - -func (g *GUID) setVersion(v Version) { - g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12) -} - -// Version returns the GUID version, as defined in RFC 4122. -func (g GUID) Version() Version { - return Version((g.Data3 & 0xF000) >> 12) -} - -// MarshalText returns the textual representation of the GUID. -func (g GUID) MarshalText() ([]byte, error) { - return []byte(g.String()), nil -} - -// UnmarshalText takes the textual representation of a GUID, and unmarhals it -// into this GUID. -func (g *GUID) UnmarshalText(text []byte) error { - g2, err := FromString(string(text)) - if err != nil { - return err - } - *g = g2 - return nil -} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go deleted file mode 100644 index 805bd354..00000000 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !windows -// +build !windows - -package guid - -// GUID represents a GUID/UUID. It has the same structure as -// golang.org/x/sys/windows.GUID so that it can be used with functions expecting -// that type. It is defined as its own type as that is only available to builds -// targeted at `windows`. The representation matches that used by native Windows -// code. -type GUID struct { - Data1 uint32 - Data2 uint16 - Data3 uint16 - Data4 [8]byte -} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go deleted file mode 100644 index 27e45ee5..00000000 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build windows -// +build windows - -package guid - -import "golang.org/x/sys/windows" - -// GUID represents a GUID/UUID. It has the same structure as -// golang.org/x/sys/windows.GUID so that it can be used with functions expecting -// that type. It is defined as its own type so that stringification and -// marshaling can be supported. The representation matches that used by native -// Windows code. -type GUID windows.GUID diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go deleted file mode 100644 index 4076d313..00000000 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by "stringer -type=Variant -trimprefix=Variant -linecomment"; DO NOT EDIT. - -package guid - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[VariantUnknown-0] - _ = x[VariantNCS-1] - _ = x[VariantRFC4122-2] - _ = x[VariantMicrosoft-3] - _ = x[VariantFuture-4] -} - -const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture" - -var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33} - -func (i Variant) String() string { - if i >= Variant(len(_Variant_index)-1) { - return "Variant(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _Variant_name[_Variant_index[i]:_Variant_index[i+1]] -} diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go deleted file mode 100644 index d9b90b6e..00000000 --- a/vendor/github.com/Microsoft/go-winio/privilege.go +++ /dev/null @@ -1,196 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "bytes" - "encoding/binary" - "fmt" - "runtime" - "sync" - "unicode/utf16" - - "golang.org/x/sys/windows" -) - -//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges -//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf -//sys revertToSelf() (err error) = advapi32.RevertToSelf -//sys openThreadToken(thread windows.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken -//sys getCurrentThread() (h windows.Handle) = GetCurrentThread -//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW -//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW -//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW - -const ( - //revive:disable-next-line:var-naming ALL_CAPS - SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED - - //revive:disable-next-line:var-naming ALL_CAPS - ERROR_NOT_ALL_ASSIGNED windows.Errno = windows.ERROR_NOT_ALL_ASSIGNED - - SeBackupPrivilege = "SeBackupPrivilege" - SeRestorePrivilege = "SeRestorePrivilege" - SeSecurityPrivilege = "SeSecurityPrivilege" -) - -var ( - privNames = make(map[string]uint64) - privNameMutex sync.Mutex -) - -// PrivilegeError represents an error enabling privileges. -type PrivilegeError struct { - privileges []uint64 -} - -func (e *PrivilegeError) Error() string { - s := "Could not enable privilege " - if len(e.privileges) > 1 { - s = "Could not enable privileges " - } - for i, p := range e.privileges { - if i != 0 { - s += ", " - } - s += `"` - s += getPrivilegeName(p) - s += `"` - } - return s -} - -// RunWithPrivilege enables a single privilege for a function call. -func RunWithPrivilege(name string, fn func() error) error { - return RunWithPrivileges([]string{name}, fn) -} - -// RunWithPrivileges enables privileges for a function call. -func RunWithPrivileges(names []string, fn func() error) error { - privileges, err := mapPrivileges(names) - if err != nil { - return err - } - runtime.LockOSThread() - defer runtime.UnlockOSThread() - token, err := newThreadToken() - if err != nil { - return err - } - defer releaseThreadToken(token) - err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED) - if err != nil { - return err - } - return fn() -} - -func mapPrivileges(names []string) ([]uint64, error) { - privileges := make([]uint64, 0, len(names)) - privNameMutex.Lock() - defer privNameMutex.Unlock() - for _, name := range names { - p, ok := privNames[name] - if !ok { - err := lookupPrivilegeValue("", name, &p) - if err != nil { - return nil, err - } - privNames[name] = p - } - privileges = append(privileges, p) - } - return privileges, nil -} - -// EnableProcessPrivileges enables privileges globally for the process. -func EnableProcessPrivileges(names []string) error { - return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED) -} - -// DisableProcessPrivileges disables privileges globally for the process. -func DisableProcessPrivileges(names []string) error { - return enableDisableProcessPrivilege(names, 0) -} - -func enableDisableProcessPrivilege(names []string, action uint32) error { - privileges, err := mapPrivileges(names) - if err != nil { - return err - } - - p := windows.CurrentProcess() - var token windows.Token - err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token) - if err != nil { - return err - } - - defer token.Close() - return adjustPrivileges(token, privileges, action) -} - -func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error { - var b bytes.Buffer - _ = binary.Write(&b, binary.LittleEndian, uint32(len(privileges))) - for _, p := range privileges { - _ = binary.Write(&b, binary.LittleEndian, p) - _ = binary.Write(&b, binary.LittleEndian, action) - } - prevState := make([]byte, b.Len()) - reqSize := uint32(0) - success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize) - if !success { - return err - } - if err == ERROR_NOT_ALL_ASSIGNED { //nolint:errorlint // err is Errno - return &PrivilegeError{privileges} - } - return nil -} - -func getPrivilegeName(luid uint64) string { - var nameBuffer [256]uint16 - bufSize := uint32(len(nameBuffer)) - err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize) - if err != nil { - return fmt.Sprintf("", luid) - } - - var displayNameBuffer [256]uint16 - displayBufSize := uint32(len(displayNameBuffer)) - var langID uint32 - err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langID) - if err != nil { - return fmt.Sprintf("", string(utf16.Decode(nameBuffer[:bufSize]))) - } - - return string(utf16.Decode(displayNameBuffer[:displayBufSize])) -} - -func newThreadToken() (windows.Token, error) { - err := impersonateSelf(windows.SecurityImpersonation) - if err != nil { - return 0, err - } - - var token windows.Token - err = openThreadToken(getCurrentThread(), windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, false, &token) - if err != nil { - rerr := revertToSelf() - if rerr != nil { - panic(rerr) - } - return 0, err - } - return token, nil -} - -func releaseThreadToken(h windows.Token) { - err := revertToSelf() - if err != nil { - panic(err) - } - h.Close() -} diff --git a/vendor/github.com/Microsoft/go-winio/reparse.go b/vendor/github.com/Microsoft/go-winio/reparse.go deleted file mode 100644 index 67d1a104..00000000 --- a/vendor/github.com/Microsoft/go-winio/reparse.go +++ /dev/null @@ -1,131 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "bytes" - "encoding/binary" - "fmt" - "strings" - "unicode/utf16" - "unsafe" -) - -const ( - reparseTagMountPoint = 0xA0000003 - reparseTagSymlink = 0xA000000C -) - -type reparseDataBuffer struct { - ReparseTag uint32 - ReparseDataLength uint16 - Reserved uint16 - SubstituteNameOffset uint16 - SubstituteNameLength uint16 - PrintNameOffset uint16 - PrintNameLength uint16 -} - -// ReparsePoint describes a Win32 symlink or mount point. -type ReparsePoint struct { - Target string - IsMountPoint bool -} - -// UnsupportedReparsePointError is returned when trying to decode a non-symlink or -// mount point reparse point. -type UnsupportedReparsePointError struct { - Tag uint32 -} - -func (e *UnsupportedReparsePointError) Error() string { - return fmt.Sprintf("unsupported reparse point %x", e.Tag) -} - -// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink -// or a mount point. -func DecodeReparsePoint(b []byte) (*ReparsePoint, error) { - tag := binary.LittleEndian.Uint32(b[0:4]) - return DecodeReparsePointData(tag, b[8:]) -} - -func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) { - isMountPoint := false - switch tag { - case reparseTagMountPoint: - isMountPoint = true - case reparseTagSymlink: - default: - return nil, &UnsupportedReparsePointError{tag} - } - nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6]) - if !isMountPoint { - nameOffset += 4 - } - nameLength := binary.LittleEndian.Uint16(b[6:8]) - name := make([]uint16, nameLength/2) - err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name) - if err != nil { - return nil, err - } - return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil -} - -func isDriveLetter(c byte) bool { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') -} - -// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or -// mount point. -func EncodeReparsePoint(rp *ReparsePoint) []byte { - // Generate an NT path and determine if this is a relative path. - var ntTarget string - relative := false - if strings.HasPrefix(rp.Target, `\\?\`) { - ntTarget = `\??\` + rp.Target[4:] - } else if strings.HasPrefix(rp.Target, `\\`) { - ntTarget = `\??\UNC\` + rp.Target[2:] - } else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' { - ntTarget = `\??\` + rp.Target - } else { - ntTarget = rp.Target - relative = true - } - - // The paths must be NUL-terminated even though they are counted strings. - target16 := utf16.Encode([]rune(rp.Target + "\x00")) - ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00")) - - size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8 - size += len(ntTarget16)*2 + len(target16)*2 - - tag := uint32(reparseTagMountPoint) - if !rp.IsMountPoint { - tag = reparseTagSymlink - size += 4 // Add room for symlink flags - } - - data := reparseDataBuffer{ - ReparseTag: tag, - ReparseDataLength: uint16(size), - SubstituteNameOffset: 0, - SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2), - PrintNameOffset: uint16(len(ntTarget16) * 2), - PrintNameLength: uint16((len(target16) - 1) * 2), - } - - var b bytes.Buffer - _ = binary.Write(&b, binary.LittleEndian, &data) - if !rp.IsMountPoint { - flags := uint32(0) - if relative { - flags |= 1 - } - _ = binary.Write(&b, binary.LittleEndian, flags) - } - - _ = binary.Write(&b, binary.LittleEndian, ntTarget16) - _ = binary.Write(&b, binary.LittleEndian, target16) - return b.Bytes() -} diff --git a/vendor/github.com/Microsoft/go-winio/sd.go b/vendor/github.com/Microsoft/go-winio/sd.go deleted file mode 100644 index c3685e98..00000000 --- a/vendor/github.com/Microsoft/go-winio/sd.go +++ /dev/null @@ -1,133 +0,0 @@ -//go:build windows -// +build windows - -package winio - -import ( - "errors" - "fmt" - "unsafe" - - "golang.org/x/sys/windows" -) - -//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW -//sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW -//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW -//sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW - -type AccountLookupError struct { - Name string - Err error -} - -func (e *AccountLookupError) Error() string { - if e.Name == "" { - return "lookup account: empty account name specified" - } - var s string - switch { - case errors.Is(e.Err, windows.ERROR_INVALID_SID): - s = "the security ID structure is invalid" - case errors.Is(e.Err, windows.ERROR_NONE_MAPPED): - s = "not found" - default: - s = e.Err.Error() - } - return "lookup account " + e.Name + ": " + s -} - -func (e *AccountLookupError) Unwrap() error { return e.Err } - -type SddlConversionError struct { - Sddl string - Err error -} - -func (e *SddlConversionError) Error() string { - return "convert " + e.Sddl + ": " + e.Err.Error() -} - -func (e *SddlConversionError) Unwrap() error { return e.Err } - -// LookupSidByName looks up the SID of an account by name -// -//revive:disable-next-line:var-naming SID, not Sid -func LookupSidByName(name string) (sid string, err error) { - if name == "" { - return "", &AccountLookupError{name, windows.ERROR_NONE_MAPPED} - } - - var sidSize, sidNameUse, refDomainSize uint32 - err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) - if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno - return "", &AccountLookupError{name, err} - } - sidBuffer := make([]byte, sidSize) - refDomainBuffer := make([]uint16, refDomainSize) - err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) - if err != nil { - return "", &AccountLookupError{name, err} - } - var strBuffer *uint16 - err = convertSidToStringSid(&sidBuffer[0], &strBuffer) - if err != nil { - return "", &AccountLookupError{name, err} - } - sid = windows.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:]) - _, _ = windows.LocalFree(windows.Handle(unsafe.Pointer(strBuffer))) - return sid, nil -} - -// LookupNameBySid looks up the name of an account by SID -// -//revive:disable-next-line:var-naming SID, not Sid -func LookupNameBySid(sid string) (name string, err error) { - if sid == "" { - return "", &AccountLookupError{sid, windows.ERROR_NONE_MAPPED} - } - - sidBuffer, err := windows.UTF16PtrFromString(sid) - if err != nil { - return "", &AccountLookupError{sid, err} - } - - var sidPtr *byte - if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil { - return "", &AccountLookupError{sid, err} - } - defer windows.LocalFree(windows.Handle(unsafe.Pointer(sidPtr))) //nolint:errcheck - - var nameSize, refDomainSize, sidNameUse uint32 - err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse) - if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno - return "", &AccountLookupError{sid, err} - } - - nameBuffer := make([]uint16, nameSize) - refDomainBuffer := make([]uint16, refDomainSize) - err = lookupAccountSid(nil, sidPtr, &nameBuffer[0], &nameSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) - if err != nil { - return "", &AccountLookupError{sid, err} - } - - name = windows.UTF16ToString(nameBuffer) - return name, nil -} - -func SddlToSecurityDescriptor(sddl string) ([]byte, error) { - sd, err := windows.SecurityDescriptorFromString(sddl) - if err != nil { - return nil, &SddlConversionError{Sddl: sddl, Err: err} - } - b := unsafe.Slice((*byte)(unsafe.Pointer(sd)), sd.Length()) - return b, nil -} - -func SecurityDescriptorToSddl(sd []byte) (string, error) { - if l := int(unsafe.Sizeof(windows.SECURITY_DESCRIPTOR{})); len(sd) < l { - return "", fmt.Errorf("SecurityDescriptor (%d) smaller than expected (%d): %w", len(sd), l, windows.ERROR_INCORRECT_SIZE) - } - s := (*windows.SECURITY_DESCRIPTOR)(unsafe.Pointer(&sd[0])) - return s.String(), nil -} diff --git a/vendor/github.com/Microsoft/go-winio/syscall.go b/vendor/github.com/Microsoft/go-winio/syscall.go deleted file mode 100644 index a6ca111b..00000000 --- a/vendor/github.com/Microsoft/go-winio/syscall.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build windows - -package winio - -//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go deleted file mode 100644 index 89b66eda..00000000 --- a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go +++ /dev/null @@ -1,378 +0,0 @@ -//go:build windows - -// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. - -package winio - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) - errERROR_EINVAL error = syscall.EINVAL -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return errERROR_EINVAL - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - return e -} - -var ( - modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - modntdll = windows.NewLazySystemDLL("ntdll.dll") - modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") - - procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") - procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") - procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") - procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") - procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") - procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") - procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") - procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") - procBackupRead = modkernel32.NewProc("BackupRead") - procBackupWrite = modkernel32.NewProc("BackupWrite") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") - procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") - procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe") - procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") - procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") - procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") - procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") - procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") - procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") - procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") -) - -func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { - var _p0 uint32 - if releaseAll { - _p0 = 1 - } - r0, _, e1 := syscall.SyscallN(procAdjustTokenPrivileges.Addr(), uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) - success = r0 != 0 - if true { - err = errnoErr(e1) - } - return -} - -func convertSidToStringSid(sid *byte, str **uint16) (err error) { - r1, _, e1 := syscall.SyscallN(procConvertSidToStringSidW.Addr(), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func convertStringSidToSid(str *uint16, sid **byte) (err error) { - r1, _, e1 := syscall.SyscallN(procConvertStringSidToSidW.Addr(), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func impersonateSelf(level uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procImpersonateSelf.Addr(), uintptr(level)) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(accountName) - if err != nil { - return - } - return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) -} - -func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procLookupAccountNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procLookupAccountSidW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(systemName) - if err != nil { - return - } - return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId) -} - -func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procLookupPrivilegeDisplayNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(systemName) - if err != nil { - return - } - return _lookupPrivilegeName(_p0, luid, buffer, size) -} - -func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procLookupPrivilegeNameW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(systemName) - if err != nil { - return - } - var _p1 *uint16 - _p1, err = syscall.UTF16PtrFromString(name) - if err != nil { - return - } - return _lookupPrivilegeValue(_p0, _p1, luid) -} - -func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) { - r1, _, e1 := syscall.SyscallN(procLookupPrivilegeValueW.Addr(), uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func openThreadToken(thread windows.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { - var _p0 uint32 - if openAsSelf { - _p0 = 1 - } - r1, _, e1 := syscall.SyscallN(procOpenThreadToken.Addr(), uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func revertToSelf() (err error) { - r1, _, e1 := syscall.SyscallN(procRevertToSelf.Addr()) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func backupRead(h windows.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { - var _p0 *byte - if len(b) > 0 { - _p0 = &b[0] - } - var _p1 uint32 - if abort { - _p1 = 1 - } - var _p2 uint32 - if processSecurity { - _p2 = 1 - } - r1, _, e1 := syscall.SyscallN(procBackupRead.Addr(), uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func backupWrite(h windows.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { - var _p0 *byte - if len(b) > 0 { - _p0 = &b[0] - } - var _p1 uint32 - if abort { - _p1 = 1 - } - var _p2 uint32 - if processSecurity { - _p2 = 1 - } - r1, _, e1 := syscall.SyscallN(procBackupWrite.Addr(), uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func cancelIoEx(file windows.Handle, o *windows.Overlapped) (err error) { - r1, _, e1 := syscall.SyscallN(procCancelIoEx.Addr(), uintptr(file), uintptr(unsafe.Pointer(o))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func connectNamedPipe(pipe windows.Handle, o *windows.Overlapped) (err error) { - r1, _, e1 := syscall.SyscallN(procConnectNamedPipe.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(o))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func createIoCompletionPort(file windows.Handle, port windows.Handle, key uintptr, threadCount uint32) (newport windows.Handle, err error) { - r0, _, e1 := syscall.SyscallN(procCreateIoCompletionPort.Addr(), uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount)) - newport = windows.Handle(r0) - if newport == 0 { - err = errnoErr(e1) - } - return -} - -func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(name) - if err != nil { - return - } - return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) -} - -func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *windows.SecurityAttributes) (handle windows.Handle, err error) { - r0, _, e1 := syscall.SyscallN(procCreateNamedPipeW.Addr(), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa))) - handle = windows.Handle(r0) - if handle == windows.InvalidHandle { - err = errnoErr(e1) - } - return -} - -func disconnectNamedPipe(pipe windows.Handle) (err error) { - r1, _, e1 := syscall.SyscallN(procDisconnectNamedPipe.Addr(), uintptr(pipe)) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func getCurrentThread() (h windows.Handle) { - r0, _, _ := syscall.SyscallN(procGetCurrentThread.Addr()) - h = windows.Handle(r0) - return -} - -func getNamedPipeHandleState(pipe windows.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procGetNamedPipeHandleStateW.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize)) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func getNamedPipeInfo(pipe windows.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procGetNamedPipeInfo.Addr(), uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func getQueuedCompletionStatus(port windows.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { - r1, _, e1 := syscall.SyscallN(procGetQueuedCompletionStatus.Addr(), uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout)) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func setFileCompletionNotificationModes(h windows.Handle, flags uint8) (err error) { - r1, _, e1 := syscall.SyscallN(procSetFileCompletionNotificationModes.Addr(), uintptr(h), uintptr(flags)) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func ntCreateNamedPipeFile(pipe *windows.Handle, access ntAccessMask, oa *objectAttributes, iosb *ioStatusBlock, share ntFileShareMode, disposition ntFileCreationDisposition, options ntFileOptions, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) { - r0, _, _ := syscall.SyscallN(procNtCreateNamedPipeFile.Addr(), uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout))) - status = ntStatus(r0) - return -} - -func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) { - r0, _, _ := syscall.SyscallN(procRtlDefaultNpAcl.Addr(), uintptr(unsafe.Pointer(dacl))) - status = ntStatus(r0) - return -} - -func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) { - r0, _, _ := syscall.SyscallN(procRtlDosPathNameToNtPathName_U.Addr(), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved)) - status = ntStatus(r0) - return -} - -func rtlNtStatusToDosError(status ntStatus) (winerr error) { - r0, _, _ := syscall.SyscallN(procRtlNtStatusToDosErrorNoTeb.Addr(), uintptr(status)) - if r0 != 0 { - winerr = syscall.Errno(r0) - } - return -} - -func wsaGetOverlappedResult(h windows.Handle, o *windows.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { - var _p0 uint32 - if wait { - _p0 = 1 - } - r1, _, e1 := syscall.SyscallN(procWSAGetOverlappedResult.Addr(), uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags))) - if r1 == 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/LICENSE.txt b/vendor/github.com/NimbleMarkets/ntcharts/LICENSE.txt deleted file mode 100644 index 189104ae..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Neomantra Corp - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/NimbleMarkets/ntcharts/canvas/buffer/buffer.go b/vendor/github.com/NimbleMarkets/ntcharts/canvas/buffer/buffer.go deleted file mode 100644 index 58322efb..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/canvas/buffer/buffer.go +++ /dev/null @@ -1,342 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -// Package buffer contain buffers used with charts. -package buffer - -import ( - "github.com/NimbleMarkets/ntcharts/canvas" -) - -// Float64ScaleBuffer is a variable size buffer -// that stores float64 data values and a scaled version of the data. -// Scaling is done by multiplying incoming values -// by a constant scale factor. -type Float64ScaleBuffer struct { - buf []float64 // original data - sbuf []float64 // scaled data - offset float64 // offset to subtract - scale float64 // scaling factor -} - -// NewFloat64ScaleBuffer returns *Float64ScaleBuffer initialized to default settings. -func NewFloat64ScaleBuffer(o, sc float64) *Float64ScaleBuffer { - return &Float64ScaleBuffer{ - buf: []float64{}, - sbuf: []float64{}, - offset: o, - scale: sc, - } -} - -// Clear resets buffer contents. -func (b *Float64ScaleBuffer) Clear() { - b.buf = []float64{} - b.sbuf = []float64{} -} - -// Length returns number of data in buffer. -func (b *Float64ScaleBuffer) Length() int { - return len(b.buf) -} - -// Scale returns scaling factor. -func (b *Float64ScaleBuffer) Scale() float64 { - return b.scale -} - -// SetScale updates scaling factor and recomputes all scaled data. -func (b *Float64ScaleBuffer) SetScale(sc float64) { - b.scale = sc - b.sbuf = make([]float64, 0, len(b.buf)) - for _, v := range b.buf { - b.sbuf = append(b.sbuf, (v-b.offset)*b.scale) - } -} - -// Offset returns data value offset. -func (b *Float64ScaleBuffer) Offset() float64 { - return b.offset -} - -// SetOffset updates offset and recomputes all scaled data. -func (b *Float64ScaleBuffer) SetOffset(o float64) { - b.offset = o - b.sbuf = make([]float64, 0, len(b.buf)) - for _, v := range b.buf { - b.sbuf = append(b.sbuf, (v-b.offset)*b.scale) - } -} - -// Push adds Float64Point data to the back of the buffer. -func (b *Float64ScaleBuffer) Push(p float64) { - b.buf = append(b.buf, p) - b.sbuf = append(b.sbuf, (p-b.offset)*b.scale) -} - -// Pop erases the oldest Float64Point from the buffer. -func (b *Float64ScaleBuffer) Pop() { - b.buf = b.buf[1:] - b.sbuf = b.sbuf[1:] -} - -// SetData sets contents of internal buffer -// to given []float64 and scales the data. -func (b *Float64ScaleBuffer) SetData(d []float64) { - b.buf = make([]float64, 0, len(d)) - b.sbuf = make([]float64, 0, len(d)) - for _, p := range d { - b.buf = append(b.buf, p) - b.sbuf = append(b.sbuf, (p-b.offset)*b.scale) - } -} - -// ReadAll returns entire scaled data buffer. -func (b *Float64ScaleBuffer) ReadAll() []float64 { - return b.sbuf -} - -// ReadAllRaw returns entire original data buffer. -func (b *Float64ScaleBuffer) ReadAllRaw() []float64 { - return b.buf -} - -// At returns Float64Point of scaled data at index i of buffer. -func (b *Float64ScaleBuffer) At(i int) float64 { - return b.sbuf[i] -} - -// AtRaw returns Float64Point of original data at index i of buffer. -func (b *Float64ScaleBuffer) AtRaw(i int) float64 { - return b.buf[i] -} - -// Float64ScaleRingBuffer is a fix-sized ring buffer -// that stores float64 data values and a scaled version of the data. -// Scaling is done by first subtracting by the offset and then multiplying -// incoming values by a constant scale factor. -// Unlike traditional ring buffers, pushing data to the buffer -// while at full capacity will erase the oldest datum -// from the buffer to create room for writing. -type Float64ScaleRingBuffer struct { - buf []float64 // original data - sbuf []float64 // scaled data - offset float64 // offset to subtract - scale float64 // scaling factor - - length int // number of elements - sz int // capacitiy - - wIdx int // write index - rIdx int // read index -} - -// NewFloat64ScaleRingBuffer returns *Float64ScaleRingBuffer initialized to default settings. -func NewFloat64ScaleRingBuffer(s int, o, sc float64) *Float64ScaleRingBuffer { - return &Float64ScaleRingBuffer{ - buf: make([]float64, s, s), - sbuf: make([]float64, s, s), - offset: o, - scale: sc, - sz: s, - wIdx: 0, - rIdx: 0} -} - -// Clear resets buffer contents. -func (b *Float64ScaleRingBuffer) Clear() { - b.length = 0 - b.wIdx = 0 - b.rIdx = 0 -} - -// Length returns number of data in buffer. -func (b *Float64ScaleRingBuffer) Length() int { - return b.length -} - -// Size returns buffer capacity. -func (b *Float64ScaleRingBuffer) Size() int { - return b.sz -} - -// Scale returns scaling factor. -func (b *Float64ScaleRingBuffer) Scale() float64 { - return b.scale -} - -// SetScale updates scaling factor and recomputes all scaled data. -func (b *Float64ScaleRingBuffer) SetScale(sc float64) { - b.scale = sc - for i, v := range b.buf { - b.sbuf[i] = (v - b.offset) * b.scale - } -} - -// Offset returns data value offset. -func (b *Float64ScaleRingBuffer) Offset() float64 { - return b.offset -} - -// SetOffset updates offset and recomputes all scaled data. -func (b *Float64ScaleRingBuffer) SetOffset(o float64) { - b.offset = o - for i, v := range b.buf { - b.sbuf[i] = (v - b.offset) * b.scale - } -} - -// Push adds float64 data to the back of the buffer. -func (b *Float64ScaleRingBuffer) Push(f float64) { - b.buf[b.wIdx] = f - b.sbuf[b.wIdx] = (f - b.offset) * b.scale - b.wIdx++ - if b.wIdx >= b.sz { - b.wIdx = 0 - } - if b.length == b.sz { // on full buffer, just increment read index - b.rIdx++ - if b.rIdx >= b.sz { - b.rIdx = 0 - } - } else { - b.length++ - } -} - -// Pop erases the oldest float64 from the buffer. -func (b *Float64ScaleRingBuffer) Pop() { - b.rIdx++ - if b.rIdx >= b.sz { - b.rIdx = 0 - } - b.length-- -} - -// ReadAll returns entire scaled data buffer. -func (b *Float64ScaleRingBuffer) ReadAll() []float64 { - return b.getBuffer(b.sbuf) -} - -// ReadAllRaw returns entire original data buffer. -func (b *Float64ScaleRingBuffer) ReadAllRaw() []float64 { - return b.getBuffer(b.buf) -} - -func (b *Float64ScaleRingBuffer) getBuffer(buf []float64) (f []float64) { - sz := b.sz - ln := b.length - idx := b.rIdx - - f = make([]float64, 0, sz) - for i := 0; i < ln; i++ { - f = append(f, buf[idx]) - idx++ - if idx >= sz { - idx = 0 - } - } - return -} - -// Float64PointScaleBuffer is a variable size buffer -// that stores Float64Points and a scaled version of the Float64Points. -// Scaling is done by multiplying incoming values (X,Y) coordinates -// by a constant scale factor. -type Float64PointScaleBuffer struct { - buf []canvas.Float64Point // original data - sbuf []canvas.Float64Point // scaled data - offsetP canvas.Float64Point // offset to subtract X,Y values from - scale canvas.Float64Point // scaling factor for X,Y values -} - -// NewFloat64PointScaleBuffer returns *Float64PointScaleBuffer initialized to default settings. -func NewFloat64PointScaleBuffer(o, sc canvas.Float64Point) *Float64PointScaleBuffer { - return &Float64PointScaleBuffer{ - buf: []canvas.Float64Point{}, - sbuf: []canvas.Float64Point{}, - offsetP: o, - scale: sc, - } -} - -// Clear resets buffer contents. -func (b *Float64PointScaleBuffer) Clear() { - b.buf = []canvas.Float64Point{} - b.sbuf = []canvas.Float64Point{} -} - -// Length returns number of data in buffer. -func (b *Float64PointScaleBuffer) Length() int { - return len(b.buf) -} - -// Scale returns Float64Point used to multiple data points by. -func (b *Float64PointScaleBuffer) Scale() canvas.Float64Point { - return b.scale -} - -// SetScale updates scaling factor and recomputes all scaled data. -func (b *Float64PointScaleBuffer) SetScale(sc canvas.Float64Point) { - b.scale = sc - b.sbuf = make([]canvas.Float64Point, 0, len(b.buf)) - for _, v := range b.buf { - b.sbuf = append(b.sbuf, v.Sub(b.offsetP).Mul(b.scale)) - } -} - -// Offset returns Float64Point used to subtract data points from. -func (b *Float64PointScaleBuffer) Offset() canvas.Float64Point { - return b.scale -} - -// SetOffset updates offsets and recomputes all scaled data. -func (b *Float64PointScaleBuffer) SetOffset(o canvas.Float64Point) { - b.offsetP = o - b.sbuf = make([]canvas.Float64Point, 0, len(b.buf)) - for _, v := range b.buf { - b.sbuf = append(b.sbuf, v.Sub(b.offsetP).Mul(b.scale)) - } -} - -// Push adds Float64Point data to the back of the buffer. -func (b *Float64PointScaleBuffer) Push(p canvas.Float64Point) { - b.buf = append(b.buf, p) - b.sbuf = append(b.sbuf, p.Sub(b.offsetP).Mul(b.scale)) -} - -// Pop erases the oldest Float64Point from the buffer. -func (b *Float64PointScaleBuffer) Pop() { - b.buf = b.buf[1:] - b.sbuf = b.sbuf[1:] -} - -// SetData sets contents of internal buffer -// to given []float64 and scales the data. -func (b *Float64PointScaleBuffer) SetData(d []canvas.Float64Point) { - b.buf = make([]canvas.Float64Point, 0, len(d)) - b.sbuf = make([]canvas.Float64Point, 0, len(d)) - for _, p := range d { - b.buf = append(b.buf, p) - b.sbuf = append(b.sbuf, p.Sub(b.offsetP).Mul(b.scale)) - } -} - -// ReadAll returns entire scaled data buffer. -func (b *Float64PointScaleBuffer) ReadAll() []canvas.Float64Point { - return b.sbuf -} - -// ReadAllRaw returns entire original data buffer. -func (b *Float64PointScaleBuffer) ReadAllRaw() []canvas.Float64Point { - return b.buf -} - -// At returns Float64Point of scaled data at index i of buffer. -func (b *Float64PointScaleBuffer) At(i int) canvas.Float64Point { - return b.sbuf[i] -} - -// AtRaw returns Float64Point of original data at index i of buffer. -func (b *Float64PointScaleBuffer) AtRaw(i int) canvas.Float64Point { - return b.buf[i] -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/canvas/canvas.go b/vendor/github.com/NimbleMarkets/ntcharts/canvas/canvas.go deleted file mode 100644 index e096b40e..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/canvas/canvas.go +++ /dev/null @@ -1,514 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -// Package canvas implements an abstract 2D area used to plot -// arbitary runes that can be displayed using the bubbletea framework. -package canvas - -// File contains a Model using the bubbletea framework -// representing the state of the canvas, -// types and functions of the coordinates system used by the canvas -// and types and functions of the contents of the canvas. - -import ( - "image" - "math" - "strings" - - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - zone "github.com/lrstanley/bubblezone" -) - -// Point is alias for image.Point -type Point = image.Point - -// Float64Point represents a point in a coordinate system -// with floating point precision. -type Float64Point struct { - X float64 - Y float64 -} - -// NewFloat64PointFromPoint returns a new Float64Point from a given Point. -func NewFloat64PointFromPoint(p Point) Float64Point { - return Float64Point{X: float64(p.X), Y: float64(p.Y)} -} - -// Mul returns a Float64Point with both X and Y values -// multiplied by the X and Y values of the given Float64Point. -func (p Float64Point) Mul(f Float64Point) Float64Point { - return Float64Point{p.X * f.X, p.Y * f.Y} -} - -// Add returns a Float64Point with both X and Y values -// added to the X and Y values of the given Float64Point. -func (p Float64Point) Add(f Float64Point) Float64Point { - return Float64Point{p.X + f.X, p.Y + f.Y} -} - -// Sub returns a Float64Point with both X and Y values -// subtracted by the X and Y values of the given Float64Point. -func (p Float64Point) Sub(f Float64Point) Float64Point { - return Float64Point{p.X - f.X, p.Y - f.Y} -} - -// NewPointFromFloat64Point returns a new Point from a given Float64Point. -func NewPointFromFloat64Point(f Float64Point) Point { - return Point{int(math.Round(f.X)), int(math.Round(f.Y))} -} - -// CanvasYCoordinates returns a sequence of Y coordinates in the -// canvas coordinates system (X,Y is top left) from a given sequence of Y coordinates -// in the Cartesian coordinates system (X,Y is bottom left) -// by passing the graph X axis in the canvas coordinates system. -func CanvasYCoordinates(xAxis int, seq []int) (r []int) { - r = make([]int, 0, len(seq)) - for _, v := range seq { - r = append(r, CanvasYCoordinate(xAxis, v)) - } - return -} - -// CanvasYCoordinate returns a Y coordinates in the -// canvas coordinates system (X,Y is top left) from a Y coordinate -// in the Cartesian coordinates system (X,Y is bottom left) -// by passing the graph X axis in the canvas coordinates system. -func CanvasYCoordinate(xAxis int, y int) (r int) { - return xAxis - y -} - -// CanvasPoints returns a sequence of Points in the -// canvas coordinates system (X,Y is top left) from a given sequence of Points -// in the Cartesian coordinates system (X,Y is bottom left) -// by passing the graph origin in the canvas coordinates system. -func CanvasPoints(origin Point, seq []Point) (r []Point) { - r = make([]Point, 0, len(seq)) - for _, v := range seq { - r = append(r, CanvasPoint(origin, v)) - } - return -} - -// CanvasPoint returns a Point in the -// canvas coordinates system (X,Y is top left) from a given Point -// in the Cartesian coordinates system (X,Y is bottom left) -// by passing the graph origin in the canvas coordinates system. -func CanvasPoint(origin Point, p Point) (r Point) { - return Point{origin.X + p.X, origin.Y - p.Y} -} - -// CanvasPointFromFloat64Point returns a Point -// in the canvas coordinates systems (X,Y is top left) -// from a canvas Float64Point in the -// Cartesian coordinates system (X,Y is bottom left) -// by passing the graph origin in the canvas coordinates system. -func CanvasPointFromFloat64Point(origin Point, f Float64Point) Point { - // round coordinates to nearest integer and - // convert Cartesian coordinates to canvas coordinates - return CanvasPoint(origin, NewPointFromFloat64Point(f)) -} - -// CanvasFloat64Point returns a Float64Point in the -// canvas coordinates system (X,Y is top left) from a given Float64Point -// in the Cartesian coordinates system (X,Y is bottom left) -// by passing the graph origin in the canvas coordinates system. -func CanvasFloat64Point(origin Point, p Float64Point) (r Float64Point) { - return Float64Point{float64(origin.X) + p.X, float64(origin.Y) - p.Y} -} - -var defaultStyle = lipgloss.NewStyle() - -// Cell contains a rune and lipgloss Style for rendering -type Cell struct { - Rune rune - Style lipgloss.Style -} - -// NewCell returns Cell with given rune and default lipgloss Style. -func NewCell(r rune) Cell { - return Cell{Rune: r, Style: defaultStyle} -} - -// NewCellWithStyle returns Cell with given rune and lipgloss Style. -func NewCellWithStyle(r rune, s lipgloss.Style) Cell { - return Cell{Rune: r, Style: s} -} - -// CellLine is a slice of Cells -type CellLine []Cell - -// Model contains state of a canvas -type Model struct { - Style lipgloss.Style // default style applied to all cells - KeyMap KeyMap // KeyMap used for keyboard msgs during Update() - UpdateHandler UpdateHandler // callback invoked during Update() - - // overall canvas size - area image.Rectangle // 0,0 is top left of canvas - content []CellLine - focus bool - - // simulates a viewport width and height - // to display contents of the canvas - ViewWidth int - ViewHeight int - - // internal coordinates tracking viewport cursor - // the contents will be displayed from top to bottom - // and left to right of the cursor - // 0,0 is top left of canvas - cursor Point - - // bubblezone Manager used to handler mouse events during Update() - zoneManager *zone.Manager - zoneID string -} - -// New returns a canvas Model initialized with given width, height -// and various options. -func New(w, h int, opts ...Option) Model { - m := Model{ - Style: defaultStyle, - KeyMap: DefaultKeyMap(), - UpdateHandler: DefaultUpdateHandler(), - area: image.Rect(0, 0, w, h), - content: make([]CellLine, h), - ViewWidth: w, - ViewHeight: h, - } - for i := range m.content { - m.content[i] = make(CellLine, w) - } - for _, opt := range opts { - opt(&m) - } - return m -} - -// Width returns canvas width. -func (m *Model) Width() int { - return m.area.Dx() -} - -// Height returns canvas height. -func (m *Model) Height() int { - return m.area.Dy() -} - -// Cursor returns Point containg (X,Y) coordinates pointing to top left of viewport. -func (m *Model) Cursor() Point { - return m.cursor -} - -// SetCursor sets (X,Y) coordinates of cursor pointing to top left of viewport. -// Coordinates will be bounded by canvas if x, y coordinates are out of bound. -func (m *Model) SetCursor(p Point) { - m.cursor.X = p.X - m.cursor.Y = p.Y - if m.cursor.X < 0 { - m.cursor.X = 0 - } else if m.cursor.X >= m.area.Dx() { - m.cursor.X = m.area.Dx() - 1 - } - if m.cursor.Y < 0 { - m.cursor.Y = 0 - } else if m.cursor.Y >= m.area.Dy() { - m.cursor.Y = m.area.Dy() - 1 - } -} - -// Resize will resize canvas to new height and width, and resets cursor. -// Will truncate existing content if canvas size shrinks. -// Does not change viewport for displaying contents. -func (m *Model) Resize(w, h int) { - // create new lines and copy over previous contents - newLines := make([]CellLine, h) - for i := range newLines { - newLines[i] = make(CellLine, w) - // copy over previous line - if i < m.area.Dy() { - for j, r := range m.content[i] { - if j >= w { - break - } - newLines[i][j] = r - } - } - } - m.area = image.Rect(0, 0, w, h) - m.cursor.X = 0 - m.cursor.Y = 0 - m.content = newLines -} - -// Clear will reset canvas contents. -func (m *Model) Clear() { - for i := range m.content { - m.content[i] = make(CellLine, m.area.Dx()) - } -} - -// SetLines copies []string into canvas as contents. -// Each string element represents a line in the canvas starting from top to bottom. -// Truncates contents if contents are greater than canvas height and width. -func (m *Model) SetLines(lines []string) bool { - return m.SetLinesWithStyle(lines, m.Style) -} - -// SetLinesWithStyle copies []string into canvas as contents with style applied to all Cells. -// Each string element represents a line in the canvas starting from top to bottom. -// Truncates contents if contents are greater than canvas height and width. -func (m *Model) SetLinesWithStyle(lines []string, s lipgloss.Style) bool { - for y, l := range lines { - if y >= m.area.Dy() { - break - } - if !m.SetStringWithStyle(Point{0, y}, l, s) { - return false // should not happen - } - } - return true -} - -// SetString copies string as rune values into canvas CellLine starting at coordinates (X, Y). -// Truncates values execeeding the canvas width. -func (m *Model) SetString(p Point, l string) bool { - return m.SetStringWithStyle(p, l, m.Style) -} - -// SetStringWithStyle copies string as rune values into canvas CellLine starting at coordinates (X, Y). -// Style will be applied to all Cells. -// Truncates values execeeding the canvas width. -func (m *Model) SetStringWithStyle(p Point, l string, s lipgloss.Style) bool { - return m.SetRunesWithStyle(p, []rune(l), s) -} - -// SetRunes copies rune values into canvas CellLine starting at coordinates (X, Y). -// Style will be applied to all Cells. -// Truncates values execeeding the canvas width. -func (m *Model) SetRunes(p Point, l []rune) bool { - return m.SetRunesWithStyle(p, l, m.Style) -} - -// SetRunesWithStyle copies rune values into canvas CellLine starting at coordinates (X, Y). -// Style will be applied to all Cells. -// Truncates values execeeding the canvas width. -func (m *Model) SetRunesWithStyle(p Point, l []rune, s lipgloss.Style) bool { - if !m.insideYBounds(p.Y) { - return false - } - xIdx := p.X - for _, r := range l { - if m.insideXBounds(xIdx) { - m.content[p.Y][xIdx] = NewCellWithStyle(r, s) - } - xIdx += 1 - } - return true -} - -// SetCell sets a Cell using (X,Y) coordinates of canvas. -func (m *Model) SetCell(p Point, c Cell) bool { - if !p.In(m.area) { - return false - } - m.content[p.Y][p.X] = c - return true -} - -// SetCellStyle sets Cell.Style using (X,Y) coordinates of canvas. -func (m *Model) SetCellStyle(p Point, s lipgloss.Style) bool { - if !p.In(m.area) { - return false - } - m.content[p.Y][p.X].Style = s - return true -} - -// SetRune sets Cell.Rune using (X,Y) coordinates of canvas. -func (m *Model) SetRune(p Point, r rune) bool { - if !p.In(m.area) { - return false - } - m.content[p.Y][p.X] = NewCell(r) - return true -} - -// Cell returns Cell located at (X,Y) coordinates of canvas. -// Returns default Cell if coorindates are out of bounds. -func (m *Model) Cell(p Point) (c Cell) { - if !p.In(m.area) { - return - } - c = m.content[p.Y][p.X] - return -} - -// Fill sets all content in canvas to Cell. -func (m *Model) Fill(c Cell) { - for i := range m.content { - for j := range m.content[i] { - m.content[i][j] = c - } - } -} - -// FillLine sets all Cells in a CellLine y away -// from origin to given Cell. -func (m *Model) FillLine(y int, c Cell) { - if !m.insideYBounds(y) { - return - } - for j := range m.content[y] { - m.content[y][j] = c - } -} - -// SetStyle applies a lipgloss.Style to all Cells to change -// visual elements of each rune in the canvas. -func (m *Model) SetStyle(s lipgloss.Style) { - for i := range m.content { - for j := range m.content[i] { - m.content[i][j].Style = s - } - } -} - -// SetZoneManager enables mouse functionality -// by setting a bubblezone.Manager to the canvas. -// The bubblezone.Manager can check bubbletea mouse event Msgs -// passed to the UpdateHandler handler during an Update(). -// The root bubbletea model must wrap the View() string with -// bubblezone.Manager.Scan() to enable mouse functionality. -// To disable mouse functionality after enabling, call SetZoneManager on nil. -func (m *Model) SetZoneManager(zm *zone.Manager) { - m.zoneManager = zm - if (zm != nil) && (m.zoneID == "") { - m.zoneID = zm.NewPrefix() - } -} - -// ZoneManager will return canvas zone Manager. -func (m *Model) ZoneManager() *zone.Manager { - return m.zoneManager -} - -// ZoneID will return canvas zone ID used by zone Manager. -func (m *Model) ZoneID() string { - return m.zoneID -} - -// ShiftUp moves all Cells up once. -// Last CellLine will be set to a new CellLine. -func (m *Model) ShiftUp() { - c := m.content - copy(c, c[1:]) - c[len(c)-1] = make(CellLine, m.area.Dx()) -} - -// ShiftDown moves all Cells down once. -// First CellLine will be set to a new CellLine. -func (m *Model) ShiftDown() { - c := m.content - copy(c[1:], c) - c[0] = make(CellLine, m.area.Dx()) -} - -// ShiftLeft moves all Cells left once. -// Last cell in each CellLine will be a new default Cell. -func (m *Model) ShiftLeft() { - for i := range m.content { - cl := m.content[i] - copy(cl, cl[1:]) - cl[len(cl)-1] = Cell{} - } -} - -// ShiftRight moves all Cells right once. -// First cell in each CellLine will be a new default Cell. -func (m *Model) ShiftRight() { - for i := range m.content { - cl := m.content[i] - copy(cl[1:], cl) - cl[0] = Cell{} - } -} - -// Focused returns whether canvas is being focused. -func (m *Model) Focused() bool { - return m.focus -} - -// Focus enables Update events processing. -func (m *Model) Focus() { - m.focus = true -} - -// Blur disables Update events processing. -func (m *Model) Blur() { - m.focus = false -} - -// Init initializes the canvas. -func (m Model) Init() tea.Cmd { - return nil -} - -// Update processes bubbletea Msg to by invoking -// UpdateHandler callback if canvas is focused. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - if !m.focus { - return m, nil - } - m.UpdateHandler(&m, msg) - return m, nil -} - -// View returns a string used by the bubbletea framework to display the canvas. -func (m Model) View() (r string) { - var sb strings.Builder - sb.Grow(m.area.Dx() * m.area.Dy()) - - endY := m.cursor.Y + m.ViewHeight - 1 - endX := m.cursor.X + m.ViewWidth - 1 - for i := m.cursor.Y; i <= endY; i++ { - if i >= m.area.Dy() { - break - } - for j := m.cursor.X; j <= endX; j++ { - if j >= m.area.Dx() { - break - } - cell := m.content[i][j] - if cell.Rune == 0 { - sb.WriteString(cell.Style.Render(" ")) - } else { - sb.WriteString(cell.Style.Render(string(cell.Rune))) - } - } - if i != endY { - sb.WriteRune('\n') - } - } - r = sb.String() - if m.zoneManager != nil { - r = m.zoneManager.Mark(m.zoneID, r) - } - return -} - -// insideXBounds returns whether X coordinate is within canvas bounds. -func (m *Model) insideXBounds(x int) bool { - if (x < 0) || (x >= m.area.Dx()) { - return false - } - return true -} - -// insideYBounds returns whether Y coordinate is within canvas bounds. -func (m *Model) insideYBounds(y int) bool { - if (y < 0) || (y >= m.area.Dy()) { - return false - } - return true -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/canvas/graph/graph.go b/vendor/github.com/NimbleMarkets/ntcharts/canvas/graph/graph.go deleted file mode 100644 index 857efdd8..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/canvas/graph/graph.go +++ /dev/null @@ -1,737 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -// Package graph contains data structures and functions to help draw runes on to a canvas. -package graph - -// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm -// https://en.wikipedia.org/wiki/Midpoint_circle_algorithm - -import ( - "math" - "sort" - - "github.com/NimbleMarkets/ntcharts/canvas" - "github.com/NimbleMarkets/ntcharts/canvas/runes" - - "github.com/charmbracelet/lipgloss" -) - -// BrailleGrid wraps a runes.PatternDotsGrid -// to implements a 2D grid with (X, Y) floating point coordinates -// used to display Braille Pattern runes. -// Since Braille Pattern runes are 4 high and 2 wide, -// the BrailleGrid will internally scale the width and height -// sizes to match those patterns. -// BrailleGrid uses canvas coordinates system with (0,0) being top left. -type BrailleGrid struct { - cWidth int // canvas width - cHeight int // canvas height - - minX float64 - maxX float64 - minY float64 - maxY float64 - - gWidth int // grid width - gHeight int // grid height - grid *runes.PatternDotsGrid -} - -// NewBrailleGrid returns new initialized *BrailleGrid -// with given canvas width, canvas height and -// minimums and maximums X and Y values of the data points. -func NewBrailleGrid(w, h int, minX, maxX, minY, maxY float64) *BrailleGrid { - gridW := w * 2 - gridH := h * 4 - g := BrailleGrid{ - cWidth: w, - cHeight: h, - minX: minX, - maxX: maxX, - minY: minY, - maxY: maxY, - gWidth: gridW, - gHeight: gridH, - grid: runes.NewPatternDotsGrid(gridW, gridH), - } - g.Clear() - return &g -} - -// Clear will reset the internal grid -func (g *BrailleGrid) Clear() { - g.grid.Reset() -} - -// GridPoint returns a canvas Point representing a point in the braille grid -// in the canvas coordinates system from a Float64Point data point -// in the Cartesian coordinates system. -func (g *BrailleGrid) GridPoint(f canvas.Float64Point) canvas.Point { - var sf canvas.Float64Point - dx := g.maxX - g.minX - dy := g.maxY - g.minY - if dx > 0 { - xs := float64(g.gWidth-1) / dx - sf.X = (f.X - g.minX) * xs - } - if dy > 0 { - ys := float64(g.gHeight-1) / dy - sf.Y = (f.Y - g.minY) * ys - } - return canvas.CanvasPointFromFloat64Point(canvas.Point{X: 0, Y: g.gHeight - 1}, sf) -} - -// Set will set point on grid from given canvas Point. -func (g *BrailleGrid) Set(p canvas.Point) { - g.grid.Set(p.X, p.Y) -} - -// BraillePatterns returns [][]rune containing -// braille pattern runes to draw on to the canvas. -func (g *BrailleGrid) BraillePatterns() [][]rune { - return g.grid.BraillePatterns() -} - -// DrawVerticalLineUp draws a vertical line going up starting from (X,Y) coordinates. -// Applies given style to all runes. -// Coordinates (0,0) is top left of canvas. -func DrawVerticalLineUp(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - x := p.X - r := canvas.NewCellWithStyle(runes.LineVertical, s) - for i := p.Y; i >= 0; i-- { - m.SetCell(canvas.Point{x, i}, r) - } -} - -// DrawVerticalLineDown draws a vertical line going down starting from (X,Y) coordinates. -// Applies given style to all runes. -// Coordinates (0,0) is top left of canvas. -func DrawVerticalLineDown(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - x := p.X - r := canvas.NewCellWithStyle(runes.LineVertical, s) - for i := p.Y; i < m.Height(); i++ { - m.SetCell(canvas.Point{x, i}, r) - } -} - -// DrawHorizonalLineLeft draws a horizontal line going to the left starting from (X,Y) coordinates. -// Applies given style to all runes. -// Coordinates (0,0) is top left of canvas. -func DrawHorizonalLineLeft(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - y := p.Y - r := canvas.NewCellWithStyle(runes.LineHorizontal, s) - for i := p.X; i >= 0; i-- { - m.SetCell(canvas.Point{i, y}, r) - } -} - -// DrawHorizonalLineRight draws a horizontal line going to the right starting from (X,Y) coordinates. -// Applies given style to all runes. -// Coordinates (0,0) is top left of canvas. -func DrawHorizonalLineRight(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - y := p.Y - r := canvas.NewCellWithStyle(runes.LineHorizontal, s) - for i := p.X; i < m.Width(); i++ { - m.SetCell(canvas.Point{i, y}, r) - } -} - -// DrawXYAxis draws X and Y axes with origin at (X,Y cordinates) with given style. -// Y axis extends up, and X axis extends right. -// Coordinates (0,0) is top left of canvas. -func DrawXYAxis(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - m.SetCell(p, canvas.NewCellWithStyle(runes.LineUpRight, s)) - DrawVerticalLineUp(m, canvas.Point{p.X, p.Y - 1}, s) - DrawHorizonalLineRight(m, canvas.Point{p.X + 1, p.Y}, s) -} - -// DrawXYAxisDown draws X and Y axes with origin at (X,Y cordinates) with given style. -// Y axis extends up and down, and X axis extends right. -// Coordinates (0,0) is top left of canvas. -func DrawXYAxisDown(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - m.SetCell(p, canvas.NewCellWithStyle(runes.LineVerticalRight, s)) - DrawVerticalLineUp(m, canvas.Point{p.X, p.Y - 1}, s) - DrawVerticalLineDown(m, canvas.Point{p.X, p.Y + 1}, s) - DrawHorizonalLineRight(m, canvas.Point{p.X + 1, p.Y}, s) -} - -// DrawXYAxisLeft draws X and Y axes with origin at (X,Y cordinates) with given style. -// Y axis extends up, and X axis extends left and right. -// Coordinates (0,0) is top left of canvas. -func DrawXYAxisLeft(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - m.SetCell(p, canvas.NewCellWithStyle(runes.LineHorizontalUp, s)) - DrawVerticalLineUp(m, canvas.Point{p.X, p.Y - 1}, s) - DrawHorizonalLineRight(m, canvas.Point{p.X + 1, p.Y}, s) - DrawHorizonalLineLeft(m, canvas.Point{p.X - 1, p.Y}, s) -} - -// DrawXYAxisAll draws X and Y axes with origin at (X,Y cordinates) with given style. -// Y axis extends up and down, and X axis extends left and right. -// Coordinates (0,0) is top left of canvas. -func DrawXYAxisAll(m *canvas.Model, p canvas.Point, s lipgloss.Style) { - m.SetCell(p, canvas.NewCellWithStyle(runes.LineHorizontalVertical, s)) - DrawVerticalLineUp(m, canvas.Point{p.X, p.Y - 1}, s) - DrawVerticalLineDown(m, canvas.Point{p.X, p.Y + 1}, s) - DrawHorizonalLineRight(m, canvas.Point{p.X + 1, p.Y}, s) - DrawHorizonalLineLeft(m, canvas.Point{p.X - 1, p.Y}, s) -} - -// DrawColumnRune draws a braille rune on to the canvas at given (X,Y) coordinates with given style. -// The function checks for existing braille runes already on the canvas and -// will draw a new braille pattern with the dot patterns of both the existing and given runes. -// Does nothing if given rune is Null or is not a braille rune. -func DrawBrailleRune(m *canvas.Model, p canvas.Point, r rune, s lipgloss.Style) { - if (r == runes.Null) || !runes.IsBraillePattern(r) { - return - } - cr := m.Cell(p).Rune - if cr == 0 { // set rune if nothing exists on canvas - m.SetCell(p, canvas.NewCellWithStyle(r, s)) - return - } - m.SetCell(p, canvas.NewCellWithStyle(runes.CombineBraillePatterns(m.Cell(p).Rune, r), s)) -} - -// DrawBraillePatterns draws braille runes from a [][]rune representing a 2D grid of -// Braille Pattern runes. The runes will be drawn onto the canvas from starting from top -// left of the grid to the bottom right of the grid starting at the given canvas Point. -// Given style will be applied to all runes drawn. -// This function can be used with the output [][]rune from PatternDotsGrid.BraillePatterns(). -func DrawBraillePatterns(m *canvas.Model, p canvas.Point, b [][]rune, s lipgloss.Style) { - for y, row := range b { - for x, r := range row { - if r != runes.BrailleBlockOffset { - DrawBrailleRune(m, p.Add(canvas.Point{X: x, Y: y}), r, s) - } - } - } -} - -// DrawLineSequence draws line runes on to the canvas starting -// from a given X coordinate and a sequence of Y coordinates. -// `startYAxis` should be true if `startX` is the Y axis. -// Sequential Y coordinates will increment X coordinates. -// Applies style to all line runes. -// Handles overlapping lines. -// Handles X and Y axes drawn using DrawXYAxis functions. -// Coordinates (0,0) is top left of canvas. -func DrawLineSequence(m *canvas.Model, startYAxis bool, startX int, seqY []int, ls runes.LineStyle, s lipgloss.Style) { - var prevY int - for i, y := range seqY { - if i == 0 { // draw first point - p := canvas.Point{startX, y} - r := runes.LineHorizontal - if startYAxis { - switch m.Cell(p).Rune { - case runes.LineUpRight: // first point is origin - m.SetCell(p, canvas.NewCellWithStyle(runes.LineUpRight, s)) - case runes.LineVertical: // first point on Y axis - m.SetCell(p, canvas.NewCellWithStyle(runes.LineVerticalRight, s)) - case runes.LineVerticalRight: // first point on Y axis overlapping another line - m.SetCell(p, canvas.NewCellWithStyle(runes.LineVerticalRight, s)) - default: - DrawLineRune(m, p, r, ls, s) - } - } else { - DrawLineRune(m, p, r, ls, s) - } - } else { - DrawLineSequenceLeftToRight(m, canvas.Point{i + startX - 1, prevY}, canvas.Point{i + startX, y}, ls, s) - } - prevY = y - } -} - -// DrawLineSequenceLeftToRight draws line runes from point A to point B where B.X = A.X+1. -// Assumes point A has already been drawn and does not draw point A. -// Applies style to all line runes. -// Handles overlapping lines. -// Handles X and Y axes drawn using DrawXYAxis functions. -// Coordinates (0,0) is top left of canvas. -func DrawLineSequenceLeftToRight(m *canvas.Model, a canvas.Point, b canvas.Point, ls runes.LineStyle, s lipgloss.Style) { - if a.X >= b.X { - return - } - - prevY := a.Y - y := b.Y - x := b.X - r := runes.LineHorizontal // default: point A has same Y coordinate as point B - - // if not the same Y coordinates, - // draw vertical lines from point A to point B - if prevY > y { // drawing line up - r = runes.ArcDownRight - DrawLineRune(m, canvas.Point{x, prevY}, runes.ArcUpLeft, ls, s) - for j := prevY - 1; j > y; j-- { // draw vertical lines - DrawLineRune(m, canvas.Point{x, j}, runes.LineVertical, ls, s) - } - } else if prevY < y { // drawing line down - r = runes.ArcUpRight - DrawLineRune(m, canvas.Point{x, prevY}, runes.ArcDownLeft, ls, s) - for j := prevY + 1; j < y; j++ { // draw vertical lines - DrawLineRune(m, canvas.Point{x, j}, runes.LineVertical, ls, s) - } - } - - DrawLineRune(m, b, r, ls, s) -} - -// DrawLinePoints draws line runes on to the canvas from a []canvas.Point. -// Each canvas Point is expected to be either adjacent or diagonal from each other. -// At least two Points are required to draw any runes on to the canvas. -// This function can be used with the []canvas.Point output from GetLinePoints(). -func DrawLinePoints(m *canvas.Model, points []canvas.Point, ls runes.LineStyle, s lipgloss.Style) { - if len(points) < 2 { - return - } - extraPoints := []canvas.Point{} - extraRunes := []rune{} // additional corner runes to draw - dir := make([]runes.LineSegments, len(points), len(points)) - for i := 1; i < len(points); i++ { - p := points[i] - prev := points[i-1] - - if p.X > prev.X { - if p.Y > prev.Y { // p down right of prev - dir[i-1].Right = true - dir[i].Up = true - extraPoints = append(extraPoints, canvas.Point{X: p.X, Y: p.Y - 1}) - extraRunes = append(extraRunes, runes.ArcDownLeft) - } else if p.Y < prev.Y { // p up right of prev - dir[i-1].Right = true - dir[i].Down = true - extraPoints = append(extraPoints, canvas.Point{X: p.X, Y: p.Y + 1}) - extraRunes = append(extraRunes, runes.ArcUpLeft) - } else { // p right of prev - dir[i-1].Right = true - dir[i].Left = true - } - } else if p.X < prev.X { - if p.Y > prev.Y { // p down left of prev - dir[i-1].Left = true - dir[i].Up = true - extraPoints = append(extraPoints, canvas.Point{X: p.X, Y: p.Y - 1}) - extraRunes = append(extraRunes, runes.ArcDownRight) - } else if p.Y < prev.Y { // p up left of prev - dir[i-1].Left = true - dir[i].Down = true - extraPoints = append(extraPoints, canvas.Point{X: p.X, Y: p.Y + 1}) - extraRunes = append(extraRunes, runes.ArcUpRight) - } else { // p left of prev - dir[i-1].Left = true - dir[i].Right = true - } - } else { - if p.Y > prev.Y { // p below prev - dir[i-1].Down = true - dir[i].Up = true - } else if p.Y < prev.Y { // p above prev - dir[i-1].Up = true - dir[i].Down = true - } else { - // same point - do nothing - } - } - } - for i, l := range dir { - DrawLineRune(m, points[i], runes.ArcLineFromLineSegments(l), ls, s) - } - for i, r := range extraRunes { - DrawLineRune(m, extraPoints[i], r, ls, s) - } -} - -// DrawLineRune draws a line rune on to the canvas at given (X,Y) coordinates with given style. -// The given rune is used to check line directions, and the final output line rune -// depends on the given runes.LineStyle. -// The function checks for existing X,Y axis or line runes already on the canvas and draws runes -// such that the lines appear overlapping. -// Does nothing if given rune is empty or is not a line rune. -func DrawLineRune(m *canvas.Model, p canvas.Point, r rune, ls runes.LineStyle, s lipgloss.Style) { - if (r == runes.Null) || !runes.IsLine(r) { - return - } - m.SetCell(p, canvas.NewCellWithStyle(runes.CombineLines(m.Cell(p).Rune, r, ls), s)) -} - -// DrawColumns draws columns going upwards on to canvas -// starting from a given (X,Y) coordinate and a sequence of column lengths. -// Columns will be drawn from left to right and -// sequential column lengths will increment X coordinates for drawing. -// Handles overlapping columns of diferent rune heights. -// If there exists an existing column at given Point with same height as new column, -// then the existing column will be replaced. -// Applies style to all block runes. -// Coordinates (0,0) is top left of canvas. -func DrawColumns(m *canvas.Model, p canvas.Point, seqLen []float64, s lipgloss.Style) { - y := p.Y - x := p.X - for i, f := range seqLen { - DrawColumnBottomToTop(m, canvas.Point{x + i, y}, f, s) - } -} - -// DrawColumnBottomToTop draws block element runes going up from given point. -// The value of float64 is the number of characters to draw going up. -// A fractional value is used since there are 1/8th lower block elements and -// fractional values will map to the nearest 1/8th block for the last rune drawn. -// Handles overlapping columns of diferent rune heights. -// If there exists an existing column at given Point with same height as new column, -// then the existing column will be replaced. -// Applies style to all block runes. -// Coordinates (0,0) is top left of canvas. -func DrawColumnBottomToTop(m *canvas.Model, p canvas.Point, v float64, s lipgloss.Style) { - if v <= 0 { - return - } - x := p.X - y := p.Y - - h := getColumnHeight(m, p) // height of existing column on canvas - n := math.Floor(v) // number of full blocks to show - nh := int(n) // height of new column to draw on canvas - - r := runes.LowerBlockElementFromFloat64(v - n) - if r != runes.Null { - nh++ - } - - fb := canvas.NewCellWithStyle(runes.FullBlock, s) - if (h == 0) || (nh == h) { // replace entire column if same height or no existing column - // set full block columns - end := int(n) - for i := 0; i < end; i++ { - m.SetCell(canvas.Point{x, y - i}, fb) - } - // set column top rune - DrawColumnRune(m, canvas.Point{x, y - end}, r, s) - } else if nh < h { // new column shorter than old column - // replace existing full blocks with new full blocks - end := int(n) - for i := 0; i < end; i++ { - m.SetCell(canvas.Point{x, y - i}, fb) - } - // overlap new column top rune on top of old full block - DrawColumnRune(m, canvas.Point{x, y - end}, r, s) - } else if nh > h { // new column taller than old column - oc := (h - 1) // index of existing column top - if oc <= 0 { - oc = 0 - } - // overlap existing column top rune on top of new full block - DrawColumnRune(m, canvas.Point{x, y - oc}, runes.FullBlock, s) - // draw new full blocks above existing columns - end := int(n) - for i := h; i < end; i++ { - m.SetCell(canvas.Point{x, y - i}, fb) - } - // set new column top rune - m.SetCell(canvas.Point{x, y - end}, canvas.NewCellWithStyle(r, s)) - } -} - -// DrawColumnRune draws a column rune on to the canvas at given (X,Y) coordinates with given style. -// The function checks for existing column runes already on the canvas and attempts to -// draws runes such that the runes appear overlapping. -// Overlapping runes can only occur if either one of the runes is a full block element rune, -// and the other rune is not a full block element rune. -// If the runes cannot overlap, then it will the existing rune will be replaced. -// Does nothing if given rune is Null or is not a column rune. -func DrawColumnRune(m *canvas.Model, p canvas.Point, r rune, s lipgloss.Style) { - if (r == runes.Null) || !runes.IsLowerBlockElement(r) { - return - } - rs := s.Copy() - c := m.Cell(p) - if runes.IsLowerBlockElement(c.Rune) { - if (r == runes.FullBlock) && (c.Rune != runes.FullBlock) { // existing rune on top of new full block - r = c.Rune - rs.Background(s.GetForeground()).Foreground(c.Style.GetForeground()) - } else if (c.Rune == runes.FullBlock) && r != runes.FullBlock { // new rune on top of existing full block - rs.Background(c.Style.GetForeground()).Foreground(s.GetForeground()) - } - } - m.SetCell(p, canvas.NewCellWithStyle(r, rs)) -} - -// getColumnHeight obtains number of runes drawn -// by the DrawColumnBottomToTop function at given Point. -func getColumnHeight(m *canvas.Model, p canvas.Point) int { - x := p.X - y := p.Y - i := 0 - c := m.Cell(canvas.Point{x, y}) - for runes.IsLowerBlockElement(c.Rune) { - i++ - c = m.Cell(canvas.Point{x, y - i}) - } - return i -} - -// DrawRows draws rows going right on to canvas -// starting from a given (X,Y) coordinate and a sequence of row widths. -// Rows will be drawn from top to bottom and -// sequential row widths will increment Y coordinates for drawing. -// Handles overlapping rows of diferent rune widths. -// If there exists an existing row at given Point with same width as new row, -// then the existing row will be replaced. -// Applies style to all block runes. -// Coordinates (0,0) is top left of canvas. -func DrawRows(m *canvas.Model, p canvas.Point, seqLen []float64, s lipgloss.Style) { - y := p.Y - x := p.X - for i, f := range seqLen { - DrawRowLeftToRight(m, canvas.Point{x, y + i}, f, s) - } -} - -// DrawRowLeftToRight draws block element runes going right from given point. -// The value of float64 is the number of characters to draw going right. -// A fractional value is used since there are 1/8th left block elements and -// fractional values will map to the nearest 1/8th block for the last rune drawn. -// Handles overlapping rows of diferent rune widths. -// If there exists an existing row at given Point with same width as new row, -// then the existing row will be replaced. -// Applies style to all block runes. -// Coordinates (0,0) is top left of canvas. -func DrawRowLeftToRight(m *canvas.Model, p canvas.Point, v float64, s lipgloss.Style) { - if v <= 0 { - return - } - x := p.X - y := p.Y - - w := getRowWidth(m, p) // width of existing row on canvas - n := math.Floor(v) // number of full blocks to show - nw := int(n) // width of new row to draw on canvas - - r := runes.LeftBlockElementFromFloat64(v - n) - if r != runes.Null { - nw++ - } - - fb := canvas.NewCellWithStyle(runes.FullBlock, s) - if (w == 0) || (nw == w) { // replace entire row if same width or no existing row - // set full block rows - end := int(n) - for i := 0; i < end; i++ { - m.SetCell(canvas.Point{x + i, y}, fb) - } - // set row rightmost rune - DrawRowRune(m, canvas.Point{x + end, y}, r, s) - } else if nw < w { // new row thinner than old row - // replace existing full blocks with new full blocks - end := int(n) - for i := 0; i < end; i++ { - m.SetCell(canvas.Point{x + i, y}, fb) - } - // overlap new row rightmost rune on top of old full block - DrawRowRune(m, canvas.Point{x + end, y}, r, s) - } else if nw > w { // new row wider than old row - oc := (w - 1) // index of existing row rightmost rune - if oc <= 0 { - oc = 0 - } - // overlap existing row rightmost rune on top of new full block - DrawRowRune(m, canvas.Point{x + oc, y}, runes.FullBlock, s) - // draw new full blocks above existing rows - end := int(n) - for i := w; i < end; i++ { - m.SetCell(canvas.Point{x + i, y}, fb) - } - // set new row rightmost rune - m.SetCell(canvas.Point{x + end, y}, canvas.NewCellWithStyle(r, s)) - } -} - -// DrawRowRune draws a row rune on to the canvas at given (X,Y) coordinates with given style. -// The function checks for existing row runes already on the canvas and attempts to -// draws runes such that the runes appear overlapping. -// Overlapping runes can only occur if either one of the runes is a full block element rune, -// and the other rune is not a full block element rune. -// If the runes cannot overlap, then it will the existing rune will be replaced. -// Does nothing if given rune is Null or is not a row rune. -func DrawRowRune(m *canvas.Model, p canvas.Point, r rune, s lipgloss.Style) { - if (r == runes.Null) || !runes.IsLeftBlockElement(r) { - return - } - rs := s.Copy() - c := m.Cell(p) - if runes.IsLeftBlockElement(c.Rune) { - if (r == runes.FullBlock) && (c.Rune != runes.FullBlock) { // existing rune on top of new full block - r = c.Rune - rs.Background(s.GetForeground()).Foreground(c.Style.GetForeground()) - } else if (c.Rune == runes.FullBlock) && r != runes.FullBlock { // new rune on top of existing full block - rs.Background(c.Style.GetForeground()).Foreground(s.GetForeground()) - } - } - m.SetCell(p, canvas.NewCellWithStyle(r, rs)) -} - -// getRowWidth obtains number of runes drawn -// by the DrawRowRightToLeft function at given Point. -func getRowWidth(m *canvas.Model, p canvas.Point) int { - x := p.X - y := p.Y - i := 0 - c := m.Cell(canvas.Point{x, y}) - for runes.IsLeftBlockElement(c.Rune) { - i++ - c = m.Cell(canvas.Point{x + i, y}) - } - return i -} - -// abs returns absolute value of given integer. -func abs(i int) int { - if i < 0 { - return i * -1 - } - return i -} - -// GetFullCirclePoints returns a []canvas.Point containing points -// that approximates a filled circle of radius r for center Point c. -func GetFullCirclePoints(c canvas.Point, r int) (p []canvas.Point) { - if r <= 0 { - return - } - // sort points - cPoints := GetCirclePoints(c, r) - sort.Slice(cPoints, func(i, j int) bool { - a := cPoints[i] - b := cPoints[j] - if a.Y == b.Y { - return a.X < b.X - } - return a.Y < b.Y - }) - // set all cells between first and last point of a row - f := cPoints[0] - l := cPoints[0] - for _, v := range cPoints { - // if new row, draw line between previous row first and last points - if v.Y != l.Y { - for i := f.X; i < l.X; i++ { - p = append(p, canvas.Point{X: i, Y: l.Y}) - } - f = v - } - l = v - p = append(p, v) - } - return -} - -// GetCirclePoints returns a []canvas.Point containing points -// that approximates a circle of radius r for center Point c. -func GetCirclePoints(c canvas.Point, r int) (p []canvas.Point) { - if r <= 0 { - return - } - t1 := r / 16 - t2 := 0 - x := r - y := 0 - for x >= y { - p = append(p, c.Add(canvas.Point{X: x, Y: y})) - p = append(p, c.Add(canvas.Point{X: x, Y: -y})) - p = append(p, c.Add(canvas.Point{X: -x, Y: y})) - p = append(p, c.Add(canvas.Point{X: -x, Y: -y})) - p = append(p, c.Add(canvas.Point{X: y, Y: x})) - p = append(p, c.Add(canvas.Point{X: y, Y: -x})) - p = append(p, c.Add(canvas.Point{X: -y, Y: x})) - p = append(p, c.Add(canvas.Point{X: -y, Y: -x})) - y++ - t1 += y - t2 = t1 - x - if t2 >= 0 { - t1 = t2 - x-- - } - } - return -} - -// GetLinePoints returns a []canvas.Point containing points -// that approximates a line between points p1 and p2. -func GetLinePoints(p1 canvas.Point, p2 canvas.Point) []canvas.Point { - if abs(p2.Y-p1.Y) < abs(p2.X-p1.X) { - if p1.X > p2.X { - return getLinePointsLow(p2, p1) - } else { - return getLinePointsLow(p1, p2) - } - } else { - if p1.Y > p2.Y { - return getLinePointsHigh(p2, p1) - } else { - return getLinePointsHigh(p1, p2) - } - } -} - -// getLinePointsLow returns a []canvas.Point containing points -// that approximates a line between points p1 and p2 for -// slight line slopes between -1 and 1. -func getLinePointsLow(p1 canvas.Point, p2 canvas.Point) (r []canvas.Point) { - dx := (p2.X - p1.X) - dy := (p2.Y - p1.Y) - yi := 1 - if dy < 0 { - yi = -1 - dy = -dy - } - D := (2 * dy) - dx - y := p1.Y - - start := p1.X - end := p2.X - if start > end { - start = p2.X - end = p1.X - } - for x := start; x <= end; x++ { - r = append(r, canvas.Point{X: x, Y: y}) - if D > 0 { - y += yi - D += (2 * (dy - dx)) - } else { - D += 2 * dy - } - } - return -} - -// getLinePointsHigh returns a []canvas.Point containing points -// that approximates a line between points p1 and p2 for -// steep line slopes <= -1 or >= 1. -func getLinePointsHigh(p1 canvas.Point, p2 canvas.Point) (r []canvas.Point) { - dx := (p2.X - p1.X) - dy := (p2.Y - p1.Y) - xi := 1 - if dx < 0 { - xi = -1 - dx = -dx - } - D := (2 * dx) - dy - x := p1.X - - start := p1.Y - end := p2.Y - if start > end { - start = p2.Y - end = p1.Y - } - for y := start; y <= end; y++ { - r = append(r, canvas.Point{X: x, Y: y}) - if D > 0 { - x += xi - D += (2 * (dx - dy)) - } else { - D += 2 * dx - } - } - return -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/canvas/options.go b/vendor/github.com/NimbleMarkets/ntcharts/canvas/options.go deleted file mode 100644 index e4f8e297..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/canvas/options.go +++ /dev/null @@ -1,86 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -package canvas - -// File contains options used by the canvas during initialization with New(). - -import ( - "github.com/charmbracelet/lipgloss" - zone "github.com/lrstanley/bubblezone" -) - -// Option is used to set options when initializing a sparkline. Example: -// -// canvas := New(width, height, WithStyle(someStyle), WithKeyMap(someKeyMap)) -type Option func(*Model) - -// WithStyle sets the default Cell style. -func WithStyle(s lipgloss.Style) Option { - return func(m *Model) { - m.Style = s - } -} - -// WithKeyMap sets the KeyMap used -// when processing keyboard event messages in Update(). -func WithKeyMap(k KeyMap) Option { - return func(m *Model) { - m.KeyMap = k - } -} - -// WithUpdateHandler sets the UpdateHandler used -// when processing bubbletea Msg events in Update(). -func WithUpdateHandler(h UpdateHandler) Option { - return func(m *Model) { - m.UpdateHandler = h - } -} - -// WithZoneManager sets the bubblezone Manager used -// when processing bubbletea Msg mouse events in Update(). -func WithZoneManager(zm *zone.Manager) Option { - return func(m *Model) { - m.SetZoneManager(zm) - } -} - -// WithCursor sets the cursor starting position for the viewport. -func WithCursor(p Point) Option { - return func(m *Model) { - m.SetCursor(p) - } -} - -// WithFocus sets the canvas to be focused. -func WithFocus() Option { - return func(m *Model) { - m.Focus() - } -} - -// WithContent copies the given []string into -// the contents of the canvas with default style. -// Each string will be copied into a row starting -// from the top of the canvas to bottom. -// Use option WithStyle() to set canvas style -// before using WithContent() for styling. -func WithContent(l []string) Option { - return func(m *Model) { - m.SetLines(l) - } -} - -// WithViewWidth sets the viewport width of the canvas. -func WithViewWidth(w int) Option { - return func(m *Model) { - m.ViewWidth = w - } -} - -// WithViewHeight sets the viewport height of the canvas. -func WithViewHeight(h int) Option { - return func(m *Model) { - m.ViewHeight = h - } -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/canvas/runes/runes.go b/vendor/github.com/NimbleMarkets/ntcharts/canvas/runes/runes.go deleted file mode 100644 index 45b2a843..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/canvas/runes/runes.go +++ /dev/null @@ -1,457 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -// Package runes contains commonly used runes and functions to obtain runes. -package runes - -// https://en.wikipedia.org/wiki/Box-drawing_character -// https://en.wikipedia.org/wiki/Braille_Patterns - -const ( - Null = '\u0000' - - LineHorizontal = '\u2500' // ─ - LineVertical = '\u2502' // │ - LineDownRight = '\u250C' // ┌ - LineDownLeft = '\u2510' // ┐ - LineUpRight = '\u2514' // └ - LineUpLeft = '\u2518' // ┘ - LineVerticalRight = '\u251C' // ├ - LineVerticalLeft = '\u2524' // ┤ - LineHorizontalUp = '\u2534' // ┴ - LineHorizontalDown = '\u252C' // ┬ - LineHorizontalVertical = '\u253C' // ┼ - LineLeft = '\u2574' // ╴ - LineUp = '\u2575' // ╵ - LineRight = '\u2576' // ╶ - LineDown = '\u2577' // ╷ - - ArcDownRight = '\u256D' // ╭ - ArcDownLeft = '\u256E' // ╮ - ArcUpLeft = '\u256F' // ╯ - ArcUpRight = '\u2570' // ╰ - - LowerBlockOne = '\u2581' // ▁ - LowerBlockTwo = '\u2582' // ▂ - LowerBlockThree = '\u2583' // ▃ - LowerBlockFour = '\u2584' // ▄ - LowerBlockFive = '\u2585' // ▅ - LowerBlockSix = '\u2586' // ▆ - LowerBlockSeven = '\u2587' // ▇ - FullBlock = '\u2588' // █ - LeftBlockSeven = '\u2589' // ▉ - LeftBlockSix = '\u258A' // ▊ - LeftBlockFive = '\u258B' // ▋ - LeftBlockFour = '\u258C' // ▌ - LeftBlockThree = '\u258D' // ▍ - LeftBlockTwo = '\u258E' // ▎ - LeftBlockOne = '\u258F' // ▏ -) - -/* -Braille dot number offsets - -Unicode Braille Patterns can be computed by -adding hex values to the beginning block offset - -[0][3] = [0x0001][0x0008] -[1][4] [0x0002][0x0010] -[2][5] [0x0004][0x0020] -[6][7] [0x0040][0x0080] -*/ - -const BrailleBlockOffset = 0x2800 // beginning of Unicode Braille Patterns (empty Braille Pattern) - -var brailleDotNumberOffsets = [8]int32{0x0001, 0x0002, 0x0004, 0x0008, 0x00010, 0x0020, 0x0040, 0x0080} - -// PatternDots indicates whether a dot in a Braille Pattern is displayed. -type PatternDots [8]bool - -// PatternDotsGrid is a 2D array where each row and column indicates whether -// a dot in a sequence of Braille Patterns runes should be displayed. -// Example: -// -// width = 4, height = 4 will give 2 Braille Pattern runes -// [0][3][0][3] -// [1][4][1][4] -// [2][5][2][5] -// [6][7][6][7] -// -// setting (0,0) will set Dot 0 of first braille rune -// setting (0,3) will set Dot 6 of first braille rune -// setting (3,0) will set Dot 3 of second braille rune -// setting (3,3) will set Dot 7 of second braille rune -type PatternDotsGrid struct { - w int // grid width - h int // grid height - g [][]bool // each index indicates whether to display Braille Pattern dot -} - -// NewPatternDotsGrid returns new initialized *PatternDotsGrid -func NewPatternDotsGrid(w, h int) *PatternDotsGrid { - g := PatternDotsGrid{ - w: w, - h: h, - } - g.Reset() - return &g -} - -// Reset will reset the internal grid -func (g *PatternDotsGrid) Reset() { - g.g = make([][]bool, g.h, g.h) - for i := range g.g { - g.g[i] = make([]bool, g.w) - } -} - -// Set will set value in grid at given column and row -func (g *PatternDotsGrid) Set(x int, y int) { - if (x < 0) || (x >= g.w) || (y < 0) || (y >= g.h) { - return - } - g.g[y][x] = true -} - -// Unset will unset value in grid at given column and row -func (g *PatternDotsGrid) Unset(x int, y int) { - if (x < 0) || (x >= g.w) || (y < 0) || (y >= g.h) { - return - } - g.g[y][x] = false -} - -// BraillePatterns returns a [][]rune containing Braille Pattern -// runes based on internal grid values. -func (g *PatternDotsGrid) BraillePatterns() (p [][]rune) { - for y := 0; y < g.h; { - xb := []rune{} - for x := 0; x < g.w; { - xb = append(xb, g.getBraillePattern(x, y)) - x += 2 // each braille pattern rune has a width of 2 - } - p = append(p, xb) - y += 4 // each braille pattern rune has a height of 4 - } - return -} - -// getBraillePattern returns Braille Pattern rune -// starting at internal grid column and row. -func (g *PatternDotsGrid) getBraillePattern(x int, y int) (b rune) { - if (x < 0) || (x >= g.w) || (y < 0) || (y >= g.h) { - return - } - b = BrailleBlockOffset - // set left side of braille pattern - if g.g[y][x] { - b |= brailleDotNumberOffsets[0] - } - if (y+1 < g.h) && (g.g[y+1][x]) { - b |= brailleDotNumberOffsets[1] - } - if (y+2 < g.h) && (g.g[y+2][x]) { - b |= brailleDotNumberOffsets[2] - } - if (y+3 < g.h) && (g.g[y+3][x]) { - b |= brailleDotNumberOffsets[6] - } - // set right side of braille pattern - if (x+1 < g.w) && (g.g[y][x+1]) { - b |= brailleDotNumberOffsets[3] - } - if (y+1 < g.h) && (x+1 < g.w) && (g.g[y+1][x+1]) { - b |= brailleDotNumberOffsets[4] - } - if (y+2 < g.h) && (x+1 < g.w) && (g.g[y+2][x+1]) { - b |= brailleDotNumberOffsets[5] - } - if (y+3 < g.h) && (x+1 < g.w) && (g.g[y+3][x+1]) { - b |= brailleDotNumberOffsets[7] - } - return -} - -// IsBraillePattern returns whether a given rune is -// considered a Braile Pattern rune. -func IsBraillePattern(r rune) bool { - if r >= 0x2800 && r <= 0x28FF { - return true - } - return false -} - -// BraillePatternFromPatternDots returns a Braille Pattern rune using given PatternDots. -// Each index in PatternDots corresponds to Braille dot number -// and whether the dot should be displayed. -func BraillePatternFromPatternDots(p PatternDots) (r rune) { - r = BrailleBlockOffset - for i, b := range p { - if b { - r |= brailleDotNumberOffsets[i] - } - } - return -} - -// SetPatternDots sets given PatternDots dots based on given rune. -func SetPatternDots(r rune, p *PatternDots) { - if !IsBraillePattern(r) { - return - } - for i, b := range brailleDotNumberOffsets { - if (b & r) != Null { - p[i] = true - } - } - return -} - -// CombineBraillePatterns returns a rune -// that is a combination of two braille pattern runes. -// Any invalid braille pattern rune combinations will return r2. -func CombineBraillePatterns(r1 rune, r2 rune) rune { - if !IsBraillePattern(r1) || !IsBraillePattern(r2) { - return r2 - } - return (r1 | r2) -} - -var lowerBlockElements = [9]rune{ - Null, - LowerBlockOne, - LowerBlockTwo, - LowerBlockThree, - LowerBlockFour, - LowerBlockFive, - LowerBlockSix, - LowerBlockSeven, - FullBlock, -} - -// IsLowerBlockElement returns whether a given rune is -// considered a lower block or full block element. -func IsLowerBlockElement(r rune) bool { - if r >= 0x2581 && r <= 0x2588 { - return true - } - return false -} - -// LowerBlockElementFromFloat64 returns either an empty rune -// or a lower Block Element rune using given float64. -// A float64 < 1.0 will return the nearest one eights lower block element -// corresponding to the float value. An empty rune will be returned if -// float64 does not round to lowest 1/8 lower block. -func LowerBlockElementFromFloat64(f float64) rune { - if f >= 1 { - return lowerBlockElements[8] - } else if f <= 0 { - return lowerBlockElements[0] - } - e := int(f / .125) // number of 1/8s blocks to show - // round remaining fraction smaller than 1/8 to nearest 1/16 - if n := f - (float64(e) * .125); n >= 0.0625 { - e++ - } - return lowerBlockElements[e] -} - -var leftBlockElements = [9]rune{ - Null, - LeftBlockOne, - LeftBlockTwo, - LeftBlockThree, - LeftBlockFour, - LeftBlockFive, - LeftBlockSix, - LeftBlockSeven, - FullBlock, -} - -// IsLeftBlockElement returns whether a given rune is -// considered a left block or full block element. -func IsLeftBlockElement(r rune) bool { - if r >= 0x2588 && r <= 0x258F { - return true - } - return false -} - -// LeftBlockElementFromFloat64 returns either an empty rune -// or a left Block Element rune using given float64. -// A float64 < 1.0 will return the nearest one eights left block element -// corresponding to the float value. An empty rune will be returned if -// float64 does not round to lowest 1/8 left block. -func LeftBlockElementFromFloat64(f float64) rune { - if f >= 1 { - return leftBlockElements[8] - } else if f <= 0 { - return leftBlockElements[0] - } - e := int(f / .125) // number of 1/8s blocks to show - // round remaining fraction smaller than 1/8 to nearest 1/16 - if n := f - (float64(e) * .125); n >= 0.0625 { - e++ - } - return leftBlockElements[e] -} - -// LineStyle enumerates the different style of line runes to display. -type LineStyle int - -const ( - ThinLineStyle LineStyle = iota - ArcLineStyle -) - -// LineSegments indicates whether a line segment -// going up, down, left, or right is displayed. -type LineSegments struct { - Up bool - Down bool - Left bool - Right bool -} - -var arcLineSegmentsMap = map[LineSegments]rune{ - {false, false, false, false}: Null, - {false, false, false, true}: LineRight, - {false, false, true, false}: LineLeft, - {false, false, true, true}: LineHorizontal, - {false, true, false, false}: LineDown, - {false, true, false, true}: ArcDownRight, - {false, true, true, false}: ArcDownLeft, - {false, true, true, true}: LineHorizontalDown, - {true, false, false, false}: LineUp, - {true, false, false, true}: ArcUpRight, - {true, false, true, false}: ArcUpLeft, - {true, false, true, true}: LineHorizontalUp, - {true, true, false, false}: LineVertical, - {true, true, false, true}: LineVerticalRight, - {true, true, true, false}: LineVerticalLeft, - {true, true, true, true}: LineHorizontalVertical, -} - -var thinLineSegmentsMap = map[LineSegments]rune{ - {false, false, false, false}: Null, - {false, false, false, true}: LineRight, - {false, false, true, false}: LineLeft, - {false, false, true, true}: LineHorizontal, - {false, true, false, false}: LineDown, - {false, true, false, true}: LineDownRight, - {false, true, true, false}: LineDownLeft, - {false, true, true, true}: LineHorizontalDown, - {true, false, false, false}: LineUp, - {true, false, false, true}: LineUpRight, - {true, false, true, false}: LineUpLeft, - {true, false, true, true}: LineHorizontalUp, - {true, true, false, false}: LineVertical, - {true, true, false, true}: LineVerticalRight, - {true, true, true, false}: LineVerticalLeft, - {true, true, true, true}: LineHorizontalVertical, -} - -// SetLineSegments sets given LineSegments directions based on given rune. -func SetLineSegments(r rune, l *LineSegments) { - switch r { - case ArcDownRight, LineDownRight: - l.Down = true - l.Right = true - case ArcDownLeft, LineDownLeft: - l.Down = true - l.Left = true - case ArcUpLeft, LineUpLeft: - l.Up = true - l.Left = true - case ArcUpRight, LineUpRight: - l.Up = true - l.Right = true - case LineHorizontal: - l.Left = true - l.Right = true - case LineVertical: - l.Up = true - l.Down = true - case LineHorizontalUp: - l.Up = true - l.Left = true - l.Right = true - case LineHorizontalDown: - l.Down = true - l.Left = true - l.Right = true - case LineVerticalRight: - l.Up = true - l.Down = true - l.Right = true - case LineVerticalLeft: - l.Up = true - l.Down = true - l.Left = true - case LineHorizontalVertical: - l.Up = true - l.Down = true - l.Left = true - l.Right = true - case LineUp: - l.Up = true - case LineDown: - l.Down = true - case LineLeft: - l.Left = true - case LineRight: - l.Right = true - } - return -} - -// IsLine returns whether a given rune is considered a line rune. -func IsLine(r rune) bool { - if (r >= 0x2500 && r <= 0x253C) || (r >= 0x256D && r <= 0x2570) || (r >= 0x2574 && r <= 0x2577) { - return true - } - return false -} - -// ArcLineFromLineSegments returns either an empty rune -// or a line rune using given LineSegments. -// LineSegments contain whether or not the returned rune -// should display arc lines going up, down, left or right. -func ArcLineFromLineSegments(l LineSegments) rune { - return arcLineSegmentsMap[l] -} - -// ThinLineFromLineSegments returns either an empty rune -// or a line rune using given LineSegments. -// LineSegments contain whether or not the returned rune -// should display thin lines going up, down, left or right. -func ThinLineFromLineSegments(l LineSegments) rune { - return thinLineSegmentsMap[l] -} - -// CombineLines returns a rune that is a combination of two line runes. -// Any invalid line rune combinations or invalid LineStyle will return r2. -// The Linestyle determines the output line rune, even if -// the two input line runes are not of that style. -func CombineLines(r1 rune, r2 rune, ls LineStyle) (r rune) { - r = r2 - r1ok := IsLine(r1) - r2ok := IsLine(r2) - if !r1ok && !r2ok { - return - } - var l LineSegments - if r1ok { - SetLineSegments(r1, &l) - } - if r2ok { - SetLineSegments(r2, &l) - } - switch ls { - case ThinLineStyle: - r = ThinLineFromLineSegments(l) - case ArcLineStyle: - r = ArcLineFromLineSegments(l) - } - return -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/canvas/updatehandler.go b/vendor/github.com/NimbleMarkets/ntcharts/canvas/updatehandler.go deleted file mode 100644 index df57891f..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/canvas/updatehandler.go +++ /dev/null @@ -1,155 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -package canvas - -// File contains methods and objects used during canvas Model Update() -// to modify internal state. -// canvas is able to move the viewport displaying the contents -// either up, down, left and right - -import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" -) - -type KeyMap struct { - Up key.Binding - Down key.Binding - Left key.Binding - Right key.Binding - PgUp key.Binding - PgDown key.Binding -} - -// DefaultKeyMap returns a default KeyMap for canvas. -func DefaultKeyMap() KeyMap { - return KeyMap{ - Up: key.NewBinding( - key.WithKeys("up", "k"), - key.WithHelp("↑/k", "move up"), - ), - Down: key.NewBinding( - key.WithKeys("down", "j"), - key.WithHelp("↓/j", "move down"), - ), - Left: key.NewBinding( - key.WithKeys("left", "h"), - key.WithHelp("←/h", "move left"), - ), - Right: key.NewBinding( - key.WithKeys("right", "l"), - key.WithHelp("→/l", "move right"), - ), - PgUp: key.NewBinding( - key.WithKeys("pgup"), - key.WithHelp("PgUp", "zoom in"), - ), - PgDown: key.NewBinding( - key.WithKeys("pgdown"), - key.WithHelp("PgDown", "zoom out"), - ), - } -} - -// UpdateHandler callback invoked during an Update() -// and passes in the canvas *Model and bubbletea Msg. -type UpdateHandler func(*Model, tea.Msg) - -// DefaultUpdateHandler is used by canvas chart to enable -// moving viewing window using the mouse wheel, -// holding down mouse left button and moving, -// and with the arrow keys. -// Uses canvas Keymap for keyboard messages. -func DefaultUpdateHandler() UpdateHandler { - var lastPos Point // tracks zone position of last zone mouse position - return func(m *Model, tm tea.Msg) { - switch msg := tm.(type) { - case tea.KeyMsg: - switch { - case key.Matches(msg, m.KeyMap.Up): - m.MoveUp(1) - case key.Matches(msg, m.KeyMap.Down): - m.MoveDown(1) - case key.Matches(msg, m.KeyMap.Left): - m.MoveLeft(1) - case key.Matches(msg, m.KeyMap.Right): - m.MoveRight(1) - case key.Matches(msg, m.KeyMap.PgUp): - m.MoveUp(1) - case key.Matches(msg, m.KeyMap.PgDown): - m.MoveDown(1) - } - case tea.MouseMsg: - switch msg.Button { - case tea.MouseButtonWheelUp: - m.MoveUp(1) - case tea.MouseButtonWheelDown: - m.MoveDown(1) - case tea.MouseButtonWheelRight: - m.MoveRight(1) - case tea.MouseButtonWheelLeft: - m.MoveLeft(1) - } - - if m.zoneManager == nil { - return - } - switch msg.Action { - case tea.MouseActionPress: - zInfo := m.zoneManager.Get(m.zoneID) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - lastPos = Point{X: x, Y: y} // set position of last click - } - case tea.MouseActionMotion: // event occurs when mouse is pressed - zInfo := m.zoneManager.Get(m.zoneID) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - if x > lastPos.X { - m.MoveRight(1) - } else if x < lastPos.X { - m.MoveLeft(1) - } - if y > lastPos.Y { - m.MoveDown(1) - } else if y < lastPos.Y { - m.MoveUp(1) - } - lastPos = Point{X: x, Y: y} // update last mouse position - } - } - } - } -} - -// MoveUp moves cursor up if possible. -func (m *Model) MoveUp(i int) { - m.cursor.Y -= i - if m.cursor.Y < 0 { - m.cursor.Y = 0 - } -} - -// MoveDown moves cursor down if possible. -func (m *Model) MoveDown(i int) { - endY := m.cursor.Y + m.ViewHeight + i - if endY <= m.area.Dy() { - m.cursor.Y += i - } -} - -// MoveLeft moves cursor left if possible. -func (m *Model) MoveLeft(i int) { - m.cursor.X -= i - if m.cursor.X < 0 { - m.cursor.X = 0 - } -} - -// MoveRight moves cursor right if possible. -func (m *Model) MoveRight(i int) { - endX := m.cursor.X + m.ViewWidth + 1 - if endX <= m.area.Dx() { - m.cursor.X += i - } -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/linechart/linechart.go b/vendor/github.com/NimbleMarkets/ntcharts/linechart/linechart.go deleted file mode 100644 index 12ccba49..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/linechart/linechart.go +++ /dev/null @@ -1,733 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -// Package linechart implements a canvas that displays -// (X,Y) Cartesian coordinates as a line chart. -package linechart - -import ( - "fmt" - "math" - - "github.com/NimbleMarkets/ntcharts/canvas" - "github.com/NimbleMarkets/ntcharts/canvas/graph" - "github.com/NimbleMarkets/ntcharts/canvas/runes" - - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - zone "github.com/lrstanley/bubblezone" -) - -var defaultStyle = lipgloss.NewStyle() - -// LabelFormatter converts a float64 into text -// for displaying the X and Y axis labels -// given an index of label and numeric value -// Index increments from minimum value to maximum values. -type LabelFormatter func(int, float64) string - -// DefaultLabelFormatter returns a LabelFormatter -// that convert float64 to integers -func DefaultLabelFormatter() LabelFormatter { - return func(i int, v float64) string { - return fmt.Sprintf("%.0f", v) - } -} - -// Model contains state of a linechart with an embedded canvas.Model -type Model struct { - UpdateHandler UpdateHandler - Canvas canvas.Model - Style lipgloss.Style // style applied when drawing runes - AxisStyle lipgloss.Style // style applied when drawing X and Y axes - LabelStyle lipgloss.Style // style applied when drawing X and Y number value - XLabelFormatter LabelFormatter // convert to X number values display string - YLabelFormatter LabelFormatter // convert to Y number values display string - xStep int // number of steps when displaying X axis values - yStep int // number of steps when displaying Y axis values - focus bool - - // the expected min and max values - minX float64 - maxX float64 - minY float64 - maxY float64 - - // current min and max axes values to display - viewMinX float64 - viewMaxX float64 - viewMinY float64 - viewMaxY float64 - - // whether to automatically set expected values - // when a value appears beyond the existing bounds - AutoMinX bool - AutoMaxX bool - AutoMinY bool - AutoMaxY bool - - origin canvas.Point // start of X and Y axes lines on canvas for graphing area - graphWidth int // width of graphing area - excludes X axis and labels - graphHeight int // height of graphing area - excludes Y axis and labels - - zoneManager *zone.Manager // provides mouse functionality - zoneID string -} - -// New returns a linechart Model initialized with given width, height, -// expected data value ranges and various options. -// Width and height includes area used for chart labeling. -// If xStep is 0, then will not draw X axis or values below X axis. -// If yStep is 0, then will not draw Y axis or values left of Y axis. -func New(w, h int, minX, maxX, minY, maxY float64, opts ...Option) Model { - m := Model{ - UpdateHandler: XYAxesUpdateHandler(1, 1), - Canvas: canvas.New(w, h), - Style: defaultStyle, - AxisStyle: defaultStyle, - LabelStyle: defaultStyle, - XLabelFormatter: DefaultLabelFormatter(), - YLabelFormatter: DefaultLabelFormatter(), - yStep: 2, - xStep: 2, - minX: minX, - maxX: maxX, - minY: minY, - maxY: maxY, - viewMinX: minX, - viewMaxX: maxX, - viewMinY: minY, - viewMaxY: maxY, - } - for _, opt := range opts { - opt(&m) - } - m.UpdateGraphSizes() - return m -} - -// getGraphSizeAndOrigin calculates and returns the linechart origin and graph width and height -func getGraphSizeAndOrigin(w, h int, minY, maxY float64, xStep, yStep int, yFmter LabelFormatter) (canvas.Point, int, int) { - // graph width and height exclude area used by axes - // origin point is canvas coordinates of where axes are drawn - origin := canvas.Point{X: 0, Y: h - 1} - gWidth := w - gHeight := h - if xStep > 0 { - // use last 2 rows of canvas to plot X axis and tick values - origin.Y -= 1 - gHeight -= 2 - } - if yStep > 0 { - // find out how many spaces left of the Y axis - // to reserve for axis tick value by checking the string length - // of all values to be displayed - var lastVal string - valueLen := 0 - rangeSz := maxY - minY // range of possible expected values - increment := rangeSz / float64(gHeight) - for i := 0; i <= gHeight; { - v := minY + (increment * float64(i)) // value to set left of Y axis - s := yFmter(i, v) - if lastVal != s { - if len(s) > valueLen { - valueLen = len(s) - } - lastVal = s - } - i += yStep - } - origin.X += valueLen - gWidth -= (valueLen + 1) // ignore Y axis and tick values - } - return origin, gWidth, gHeight -} - -// UpdateGraphSizes updates the Model origin, graph width and graph height. -// This method is should be called whenever the X and Y axes values have changed, -// for example when X and Y ranges have been adjusted by AutoAdjustRange(). -func (m *Model) UpdateGraphSizes() { - origin, gWidth, gHeight := getGraphSizeAndOrigin( - m.Canvas.Width(), - m.Canvas.Height(), - m.viewMinY, - m.viewMaxY, - m.xStep, - m.yStep, - m.YLabelFormatter, - ) - m.origin = origin - m.graphWidth = gWidth - m.graphHeight = gHeight -} - -// Width returns linechart width. -func (m *Model) Width() int { - return m.Canvas.Width() -} - -// Height returns linechart height. -func (m *Model) Height() int { - return m.Canvas.Height() -} - -// GraphWidth returns linechart graphing area width. -func (m *Model) GraphWidth() int { - return m.graphWidth -} - -// GraphHeight returns linechart graphing area height. -func (m *Model) GraphHeight() int { - return m.graphHeight -} - -// MinX returns linechart expected minimum X value. -func (m *Model) MinX() float64 { - return m.minX -} - -// MaxX returns linechart expected maximum X value. -func (m *Model) MaxX() float64 { - return m.maxX -} - -// MinY returns linechart expected minimum Y value. -func (m *Model) MinY() float64 { - return m.minY -} - -// MaxY returns linechart expected maximum Y value. -func (m *Model) MaxY() float64 { - return m.maxY -} - -// ViewMinX returns linechart displayed minimum X value. -func (m *Model) ViewMinX() float64 { - return m.viewMinX -} - -// ViewMaxX returns linechart displayed maximum X value. -func (m *Model) ViewMaxX() float64 { - return m.viewMaxX -} - -// ViewMinY returns linechart displayed minimum Y value. -func (m *Model) ViewMinY() float64 { - return m.viewMinY -} - -// ViewMaxY returns linechart displayed maximum Y value. -func (m *Model) ViewMaxY() float64 { - return m.viewMaxY -} - -// XStep returns number of steps when displaying Y axis values. -func (m *Model) XStep() int { - return m.xStep -} - -// XStep returns number of steps when displaying Y axis values. -func (m *Model) YStep() int { - return m.yStep -} - -// Origin returns a canvas Point with the coordinates -// of the linechart graph (X,Y) origin. -func (m *Model) Origin() canvas.Point { - return m.origin -} - -// Clear will reset linechart canvas including axes and labels. -func (m *Model) Clear() { - m.Canvas.Clear() -} - -// SetXStep updates the number of steps when displaying X axis values. -func (m *Model) SetXStep(xStep int) { - m.xStep = xStep - m.UpdateGraphSizes() -} - -// SetYStep updates the number of steps when displaying Y axis values. -func (m *Model) SetYStep(yStep int) { - m.yStep = yStep - m.UpdateGraphSizes() -} - -// SetXRange updates the minimum and maximum expected X values. -func (m *Model) SetXRange(min, max float64) { - m.minX = min - m.maxX = max -} - -// SetYRange updates the minimum and maximum expected Y values. -func (m *Model) SetYRange(min, max float64) { - m.minY = min - m.maxY = max -} - -// SetXYRange updates the minimum and maximum expected X and Y values. -func (m *Model) SetXYRange(minX, maxX, minY, maxY float64) { - m.SetXRange(minX, maxX) - m.SetYRange(minY, maxY) -} - -// SetXRange updates the displayed minimum and maximum X values. -// Minimum and maximum values will be bounded by the expected X values. -// Returns whether not displayed X values have updated. -func (m *Model) SetViewXRange(min, max float64) bool { - vMin := math.Max(m.minX, min) - vMax := math.Min(m.maxX, max) - if vMin < vMax { - m.viewMinX = vMin - m.viewMaxX = vMax - m.UpdateGraphSizes() - return true - } - return false -} - -// SetYRange updates the displayed minimum and maximum Y values. -// Minimum and maximum values will be bounded by the expected Y values. -// Returns whether not displayed Y values have updated. -func (m *Model) SetViewYRange(min, max float64) bool { - vMin := math.Max(m.minY, min) - vMax := math.Min(m.maxY, max) - if vMin < vMax { - m.viewMinY = vMin - m.viewMaxY = vMax - m.UpdateGraphSizes() - return true - } - return false -} - -// SetViewXYRange updates the displayed minimum and maximum X and Y values. -// Minimum and maximum values will be bounded by the expected values. -func (m *Model) SetViewXYRange(minX, maxX, minY, maxY float64) { - m.SetViewXRange(minX, maxX) - m.SetViewYRange(minY, maxY) -} - -// Resize will change linechart display width and height. -// Existing runes on the linechart will not be redrawn. -func (m *Model) Resize(w, h int) { - m.Canvas.Resize(w, h) - m.Canvas.ViewWidth = w - m.Canvas.ViewHeight = h - m.UpdateGraphSizes() -} - -// AutoAdjustRange automatically adjusts both the expected X and Y values -// and the displayed X and Y values if enabled and the given Float64Point -// is outside of expected ranges. -// It returns whether or not the display X and Y ranges have been adjusted. -func (m *Model) AutoAdjustRange(f canvas.Float64Point) (b bool) { - // adjusts both expected range and - // the display range (if not zoomed in) - if m.AutoMinX && (f.X < m.minX) { - if m.minX == m.viewMinX { - m.viewMinX = f.X - b = true - } - m.minX = f.X - } - if m.AutoMaxX && (f.X > m.maxX) { - if m.maxX == m.viewMaxX { - m.viewMaxX = f.X - b = true - } - m.maxX = f.X - } - if m.AutoMinY && (f.Y < m.minY) { - if m.minY == m.viewMinY { - m.viewMinY = f.Y - b = true - } - m.minY = f.Y - } - if m.AutoMaxY && (f.Y > m.maxY) { - if m.maxY == m.viewMaxY { - m.viewMaxY = f.Y - b = true - } - m.maxY = f.Y - } - return -} - -// SetZoneManager enables mouse functionality -// by setting a bubblezone.Manager to the linechart. -// The bubblezone.Manager can check bubbletea mouse event Msgs -// passed to the UpdateHandler handler during an Update(). -// The root bubbletea model must wrap the View() string with -// bubblezone.Manager.Scan() to enable mouse functionality. -// To disable mouse functionality after enabling, call SetZoneManager on nil. -func (m *Model) SetZoneManager(zm *zone.Manager) { - m.zoneManager = zm - if (zm != nil) && (m.zoneID == "") { - m.zoneID = zm.NewPrefix() - } -} - -// ZoneManager will return linechart zone Manager. -func (m *Model) ZoneManager() *zone.Manager { - return m.zoneManager -} - -// ZoneID will return linechart zone ID used by zone Manager. -func (m *Model) ZoneID() string { - return m.zoneID -} - -// drawYLabel draws Y axis values left of the Y axis every n step. -// Repeating values will be hidden. -// Does nothing if n <= 0. -func (m *Model) drawYLabel(n int) { - // from origin going up, draw data value left of the Y axis every n steps - // origin X coordinates already set such that there is space available - if n <= 0 { - return - } - var lastVal string - rangeSz := m.viewMaxY - m.viewMinY // range of possible expected values - increment := rangeSz / float64(m.graphHeight) - for i := 0; i <= m.graphHeight; { - v := m.viewMinY + (increment * float64(i)) // value to set left of Y axis - s := m.YLabelFormatter(i, v) - if lastVal != s { - m.Canvas.SetStringWithStyle(canvas.Point{m.origin.X - len(s), m.origin.Y - i}, s, m.LabelStyle) - lastVal = s - } - i += n - } -} - -// drawXLabel draws X axis values below the X axis every n step. -// Repeating values will be hidden. -// Does nothing if n <= 0. -func (m *Model) drawXLabel(n int) { - // from origin going right, draw data value left of the Y axis every n steps - if n <= 0 { - return - } - var lastVal string - rangeSz := m.viewMaxX - m.viewMinX // range of possible expected values - increment := rangeSz / float64(m.graphWidth) - for i := 0; i < m.graphWidth; { - // can only set if rune to the left of target coordinates is empty - if c := m.Canvas.Cell(canvas.Point{m.origin.X + i - 1, m.origin.Y + 1}); c.Rune == runes.Null { - v := m.viewMinX + (increment * float64(i)) // value to set under X axis - s := m.XLabelFormatter(i, v) - // dont display if number will be cut off or value repeats - sLen := len(s) + m.origin.X + i - if (s != lastVal) && (sLen <= m.Canvas.Width()) { - m.Canvas.SetStringWithStyle(canvas.Point{m.origin.X + i, m.origin.Y + 1}, s, m.LabelStyle) - lastVal = s - } - } - i += n - } -} - -// DrawXYAxisAndLabel draws the X, Y axes. -func (m *Model) DrawXYAxisAndLabel() { - drawY := m.yStep > 0 - drawX := m.xStep > 0 - if drawY && drawX { - graph.DrawXYAxis(&m.Canvas, m.origin, m.AxisStyle) - } else { - if drawY { // draw Y axis - graph.DrawVerticalLineUp(&m.Canvas, m.origin, m.AxisStyle) - } - if drawX { // draw X axis - graph.DrawHorizonalLineRight(&m.Canvas, m.origin, m.AxisStyle) - } - } - m.drawYLabel(m.yStep) - m.drawXLabel(m.xStep) -} - -// scalePoint returns a Float64Point scaled to the graph size -// of the linechart from a Float64Point data point, width and height. -func (m *Model) scalePoint(f canvas.Float64Point, w, h int) (r canvas.Float64Point) { - dx := m.viewMaxX - m.viewMinX - dy := m.viewMaxY - m.viewMinY - if dx > 0 { - xs := float64(w) / dx - r.X = (f.X - m.viewMinX) * xs - } - if dy > 0 { - ys := float64(h) / dy - r.Y = (f.Y - m.viewMinY) * ys - } - return -} - -// ScaleFloat64Point returns a Float64Point scaled to the graph size -// of the linechart from a Float64Point data point. -func (m *Model) ScaleFloat64Point(f canvas.Float64Point) (r canvas.Float64Point) { - // Need to use one less width and height, otherwise values rounded to the nearest - // integer would be would be between 0 to graph width/height, - // and indexing the full graph width/height would be outside of the canvas - return m.scalePoint(f, m.graphWidth-1, m.graphHeight-1) -} - -// ScaleFloat64PointForLine returns a Float64Point scaled to the graph size -// of the linechart from a Float64Point data point. Used when drawing line runes -// with line styles that can combine with the axes. -func (m *Model) ScaleFloat64PointForLine(f canvas.Float64Point) (r canvas.Float64Point) { - // Full graph height and can be used since LineStyle runes - // can be combined with axes instead of overriding them - return m.scalePoint(f, m.graphWidth, m.graphHeight) -} - -// DrawRune draws the rune on to the linechart -// from a given Float64Point data point. -func (m *Model) DrawRune(f canvas.Float64Point, r rune) { - m.DrawRuneWithStyle(f, r, m.Style) -} - -// DrawRuneWithStyle draws the rune with style on to the linechart -// from a given Float64Point data point. -func (m *Model) DrawRuneWithStyle(f canvas.Float64Point, r rune, s lipgloss.Style) { - if m.AutoAdjustRange(f) { // auto adjust x and y ranges if enabled - m.UpdateGraphSizes() - } - sf := m.ScaleFloat64Point(f) // scale Cartesian coordinates data point to graphing area - p := canvas.CanvasPointFromFloat64Point(m.origin, sf) - // draw rune avoiding the axes - if m.yStep > 0 { - p.X++ - } - if m.xStep > 0 { - p.Y-- - } - m.Canvas.SetCell(p, canvas.NewCellWithStyle(r, s)) -} - -// DrawRuneLine draws the rune on to the linechart -// such that there is an approximate straight line between the two given -// Float64Point data points. -func (m *Model) DrawRuneLine(f1 canvas.Float64Point, f2 canvas.Float64Point, r rune) { - m.DrawRuneLineWithStyle(f1, f2, r, m.Style) -} - -// DrawRuneLineWithStyle draws the rune with style on to the linechart -// such that there is an approximate straight line between the two given -// Float64Point data points. -func (m *Model) DrawRuneLineWithStyle(f1 canvas.Float64Point, f2 canvas.Float64Point, r rune, s lipgloss.Style) { - // auto adjust x and y ranges if enabled - r1 := m.AutoAdjustRange(f1) - r2 := m.AutoAdjustRange(f2) - if r1 || r2 { - m.UpdateGraphSizes() - } - - // scale Cartesian coordinates data point to graphing area - sf1 := m.ScaleFloat64Point(f1) - sf2 := m.ScaleFloat64Point(f2) - - // convert scaled points to canvas points - p1 := canvas.CanvasPointFromFloat64Point(m.origin, sf1) - p2 := canvas.CanvasPointFromFloat64Point(m.origin, sf2) - - // draw rune on all canvas coordinates between - // the two canvas points that approximates a line - points := graph.GetLinePoints(p1, p2) - for _, p := range points { - if m.yStep > 0 { - p.X++ - } - if m.xStep > 0 { - p.Y-- - } - m.Canvas.SetCell(p, canvas.NewCellWithStyle(r, s)) - } -} - -// DrawRuneCircle draws the rune on to the linechart -// such that there is an approximate circle of float64 radious around -// the center of a circle at Float64Point data point. -func (m *Model) DrawRuneCircle(c canvas.Float64Point, f float64, r rune) { - m.DrawRuneCircleWithStyle(c, f, r, m.Style) -} - -// DrawRuneCircleWithStyle draws the rune with style on to the linechart -// such that there is an approximate circle of float64 radious around -// the center of a circle at Float64Point data point. -func (m *Model) DrawRuneCircleWithStyle(c canvas.Float64Point, f float64, r rune, s lipgloss.Style) { - center := canvas.NewPointFromFloat64Point(c) // round center to nearest integers - radius := int(math.Round(f)) // round radius to nearest integer - - points := graph.GetCirclePoints(center, radius) - for _, v := range points { - np := canvas.NewFloat64PointFromPoint(v) - // auto adjust x and y ranges if enabled - if m.AutoAdjustRange(np) { - m.UpdateGraphSizes() - } - // scale Cartesian coordinates data point to graphing area - sf := m.ScaleFloat64Point(np) - // convert scaled points to canvas points - p := canvas.CanvasPointFromFloat64Point(m.origin, sf) - // draw rune while avoiding drawing outside of graphing area - // or on the X and Y axes - ok := (p.X >= m.origin.X) && (p.Y <= m.origin.Y) - if (m.yStep > 0) && (p.X == m.origin.X) { - ok = false - } - if (m.xStep > 0) && (p.Y == m.origin.Y) { - ok = false - } - if ok { - m.Canvas.SetCell(p, canvas.NewCellWithStyle(r, s)) - } - } -} - -// DrawLine draws line runes of a given LineStyle on to the linechart -// such that there is an approximate straight line between the two given Float64Point data points. -func (m *Model) DrawLine(f1 canvas.Float64Point, f2 canvas.Float64Point, ls runes.LineStyle) { - m.DrawLineWithStyle(f1, f2, ls, m.Style) -} - -// DrawLineWithStyle draws line runes of a given LineStyle and style on to the linechart -// such that there is an approximate straight line between the two given Float64Point data points. -func (m *Model) DrawLineWithStyle(f1 canvas.Float64Point, f2 canvas.Float64Point, ls runes.LineStyle, s lipgloss.Style) { - // auto adjust x and y ranges if enabled - r1 := m.AutoAdjustRange(f1) - r2 := m.AutoAdjustRange(f2) - if r1 || r2 { - m.UpdateGraphSizes() - } - - // scale Cartesian coordinates data points to graphing area - sf1 := m.ScaleFloat64PointForLine(f1) - sf2 := m.ScaleFloat64PointForLine(f2) - - // convert scaled points to canvas points - p1 := canvas.CanvasPointFromFloat64Point(m.origin, sf1) - p2 := canvas.CanvasPointFromFloat64Point(m.origin, sf2) - - // draw line runes on all canvas coordinates between - // the two canvas points that approximates a line - points := graph.GetLinePoints(p1, p2) - if len(points) <= 0 { - return - } - graph.DrawLinePoints(&m.Canvas, points, ls, s) -} - -// DrawBrailleLine draws braille line runes of a given LineStyle on to the linechart -// such that there is an approximate straight line between the two given Float64Point data points. -// Braille runes will not overlap the axes. -func (m *Model) DrawBrailleLine(f1 canvas.Float64Point, f2 canvas.Float64Point) { - m.DrawBrailleLineWithStyle(f1, f2, m.Style) -} - -// DrawBrailleLineWithStyle draws braille line runes of a given LineStyle and style on to the linechart -// such that there is an approximate straight line between the two given Float64Point data points. -// Braille runes will not overlap the axes. -func (m *Model) DrawBrailleLineWithStyle(f1 canvas.Float64Point, f2 canvas.Float64Point, s lipgloss.Style) { - // auto adjust x and y ranges if enabled - r1 := m.AutoAdjustRange(f1) - r2 := m.AutoAdjustRange(f2) - if r1 || r2 { - m.UpdateGraphSizes() - } - - bGrid := graph.NewBrailleGrid(m.graphWidth, m.graphHeight, m.minX, m.maxX, m.minY, m.maxY) - - // get braille grid points from two Float64Point data points - p1 := bGrid.GridPoint(f1) - p2 := bGrid.GridPoint(f2) - - // set all points in the braille grid between two points that approximates a line - points := graph.GetLinePoints(p1, p2) - for _, p := range points { - bGrid.Set(p) - } - - // get all rune patterns for braille grid and draw them on to the canvas - startX := 0 - if m.yStep > 0 { - startX = m.origin.X + 1 - } - patterns := bGrid.BraillePatterns() - graph.DrawBraillePatterns(&m.Canvas, canvas.Point{X: startX, Y: 0}, patterns, s) -} - -// DrawBrailleCircle draws braille line runes of a given LineStyle on to the linechart -// such that there is an approximate circle of given float64 radius -// around the center of a circle at Float64Point data point. -// Braille runes will not overlap the axes. -func (m *Model) DrawBrailleCircle(p canvas.Float64Point, f float64) { - m.DrawBrailleCircleWithStyle(p, f, m.Style) -} - -// DrawBrailleCircleWithStyle draws braille line runes of a given LineStyle and style on to the linechart -// such that there is an approximate circle of given float64 radius -// around the center of a circle at Float64Point data point. -// Braille runes will not overlap the axes. -func (m *Model) DrawBrailleCircleWithStyle(c canvas.Float64Point, f float64, s lipgloss.Style) { - center := canvas.NewPointFromFloat64Point(c) // round center to nearest integer - radius := int(math.Round(f)) // round radius to nearest integer - - // set braille grid points from computed circle points around center - bGrid := graph.NewBrailleGrid(m.graphWidth, m.graphHeight, m.minX, m.maxX, m.minY, m.maxY) - points := graph.GetCirclePoints(center, radius) - for _, p := range points { - np := canvas.NewFloat64PointFromPoint(p) - if m.AutoAdjustRange(np) { - m.UpdateGraphSizes() - } - bGrid.Set(bGrid.GridPoint(np)) - } - - // get all rune patterns for braille grid and draw them on to the canvas - startX := 0 - if m.yStep > 0 { - startX = m.origin.X + 1 - } - patterns := bGrid.BraillePatterns() - graph.DrawBraillePatterns(&m.Canvas, canvas.Point{X: startX, Y: 0}, patterns, s) -} - -// Focused returns whether canvas is being focused. -func (m *Model) Focused() bool { - return m.focus -} - -// Focus enables Update events processing. -func (m *Model) Focus() { - m.focus = true -} - -// Blur disables Update events processing. -func (m *Model) Blur() { - m.focus = false -} - -// Init initializes the linechart. -func (m Model) Init() tea.Cmd { - return m.Canvas.Init() -} - -// Update processes bubbletea Msg to by invoking -// UpdateHandlerFunc callback if linechart is focused. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - if !m.focus { - return m, nil - } - m.UpdateHandler(&m, msg) - return m, nil -} - -// View returns a string used by the bubbletea framework to display the linechart. -func (m Model) View() (r string) { - r = m.Canvas.View() - if m.zoneManager != nil { - r = m.zoneManager.Mark(m.zoneID, r) - } - return -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/linechart/options.go b/vendor/github.com/NimbleMarkets/ntcharts/linechart/options.go deleted file mode 100644 index 648481d2..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/linechart/options.go +++ /dev/null @@ -1,103 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -package linechart - -// File contains options used by the linechart during initialization with New(). - -import ( - "github.com/NimbleMarkets/ntcharts/canvas" - - "github.com/charmbracelet/lipgloss" - zone "github.com/lrstanley/bubblezone" -) - -// Option is used to set options when initializing a linechart. Example: -// -// lc := New(width, height, minX, maxX, minY, maxY, WithZoneManager(someZoneManager)) -type Option func(*Model) - -// WithStyles sets the default style of the axes, the value shown for the axes -// and runes drawn on linechart. -func WithStyles(as lipgloss.Style, ls lipgloss.Style, s lipgloss.Style) Option { - return func(m *Model) { - m.AxisStyle = as - m.LabelStyle = ls - m.Style = s - } -} - -// WithXLabelFormatter sets the default X label formatter for displaying X values as strings. -func WithXLabelFormatter(fmter LabelFormatter) Option { - return func(m *Model) { - m.XLabelFormatter = fmter - } -} - -// WithYLabelFormatter sets the default Y label formatter for displaying Y values as strings. -func WithYLabelFormatter(fmter LabelFormatter) Option { - return func(m *Model) { - m.YLabelFormatter = fmter - } -} - -// / WithKeyMap sets the KeyMap used -// when processing keyboard event messages in Update(). -func WithKeyMap(k canvas.KeyMap) Option { - return func(m *Model) { - m.Canvas.KeyMap = k - } -} - -// WithUpdateHandler sets the UpdateHandler used -// when processing bubbletea Msg events in Update(). -func WithUpdateHandler(h UpdateHandler) Option { - return func(m *Model) { - m.UpdateHandler = h - } -} - -// WithZoneManager sets the bubblezone Manager used -// when processing bubbletea Msg mouse events in Update(). -func WithZoneManager(zm *zone.Manager) Option { - return func(m *Model) { - m.SetZoneManager(zm) - } -} - -// WithXYSteps sets the number of steps when drawing -// X and Y axes values. -func WithXYSteps(x, y int) Option { - return func(m *Model) { - m.xStep = x - m.yStep = y - } -} - -// WithAutoXYRange enables automatically setting the minimum and maximum -// expected X and Y values if new data values are beyond the current ranges. -func WithAutoXYRange() Option { - return func(m *Model) { - m.AutoMinX = true - m.AutoMaxX = true - m.AutoMinY = true - m.AutoMaxY = true - } -} - -// WithAutoXRange enables automatically setting the minimum and maximum -// expected X values if new data values are beyond the current range. -func WithAutoXRange() Option { - return func(m *Model) { - m.AutoMinX = true - m.AutoMaxX = true - } -} - -// WithAutoYRange enables automatically setting the minimum and maximum -// expected Y values if new data values are beyond the current range. -func WithAutoYRange() Option { - return func(m *Model) { - m.AutoMinY = true - m.AutoMaxY = true - } -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/options.go b/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/options.go deleted file mode 100644 index c68b1cc6..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/options.go +++ /dev/null @@ -1,139 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -package timeserieslinechart - -// File contains options used by the timeserieslinechart during initialization with New(). - -import ( - "time" - - "github.com/NimbleMarkets/ntcharts/canvas/runes" - "github.com/NimbleMarkets/ntcharts/linechart" - - "github.com/charmbracelet/lipgloss" - zone "github.com/lrstanley/bubblezone" -) - -// Option is used to set options when initializing a timeserieslinechart. Example: -// -// tslc := New(width, height, minX, maxX, minY, maxY, WithStyles(someLineStyle, someLipglossStyle)) -type Option func(*Model) - -// WithLineChart sets internal linechart to given linechart. -func WithLineChart(lc *linechart.Model) Option { - return func(m *Model) { - m.Model = *lc - } -} - -// WithUpdateHandler sets the UpdateHandler used -// when processing bubbletea Msg events in Update(). -func WithUpdateHandler(h linechart.UpdateHandler) Option { - return func(m *Model) { - m.UpdateHandler = h - } -} - -// WithZoneManager sets the bubblezone Manager used -// when processing bubbletea Msg mouse events in Update(). -func WithZoneManager(zm *zone.Manager) Option { - return func(m *Model) { - m.SetZoneManager(zm) - } -} - -// WithXLabelFormatter sets the default X label formatter for displaying X values as strings. -func WithXLabelFormatter(fmter linechart.LabelFormatter) Option { - return func(m *Model) { - m.XLabelFormatter = fmter - } -} - -// WithYLabelFormatter sets the default Y label formatter for displaying Y values as strings. -func WithYLabelFormatter(fmter linechart.LabelFormatter) Option { - return func(m *Model) { - m.YLabelFormatter = fmter - } -} - -// WithAxesStyles sets the axes line and line label styles. -func WithAxesStyles(as lipgloss.Style, ls lipgloss.Style) Option { - return func(m *Model) { - m.AxisStyle = as - m.LabelStyle = ls - } -} - -// WithXYSteps sets the number of steps when drawing X and Y axes values. -// If X steps 0, then X axis will be hidden. -// If Y steps 0, then Y axis will be hidden. -func WithXYSteps(x, y int) Option { - return func(m *Model) { - m.SetXStep(x) - m.SetYStep(y) - } -} - -// WithYRange sets expected and displayed -// minimum and maximum Y value range. -func WithYRange(min, max float64) Option { - return func(m *Model) { - m.SetYRange(min, max) - m.SetViewYRange(min, max) - } -} - -// WithTimeRange sets expected and displayed minimun and maximum -// time values range on the X axis. -func WithTimeRange(min, max time.Time) Option { - return func(m *Model) { - m.SetTimeRange(min, max) - m.SetViewTimeRange(min, max) - } -} - -// WithLineStyle sets the default line style of data sets. -func WithLineStyle(ls runes.LineStyle) Option { - return func(m *Model) { - m.SetLineStyle(ls) - } -} - -// WithDataSetLineStyle sets the line style of the data set given by name. -func WithDataSetLineStyle(n string, ls runes.LineStyle) Option { - return func(m *Model) { - m.SetDataSetLineStyle(n, ls) - } -} - -// WithStyle sets the default lipgloss style of data sets. -func WithStyle(s lipgloss.Style) Option { - return func(m *Model) { - m.SetStyle(s) - } -} - -// WithDataSetStyle sets the lipgloss style of the data set given by name. -func WithDataSetStyle(n string, s lipgloss.Style) Option { - return func(m *Model) { - m.SetDataSetStyle(n, s) - } -} - -// WithTimeSeries adds []TimePoint values to the default data set. -func WithTimeSeries(p []TimePoint) Option { - return func(m *Model) { - for _, v := range p { - m.Push(v) - } - } -} - -// WithDataSetTimeSeries adds []TimePoint data points to the data set given by name. -func WithDataSetTimeSeries(n string, p []TimePoint) Option { - return func(m *Model) { - for _, v := range p { - m.PushDataSet(n, v) - } - } -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/timeserieslinechart.go b/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/timeserieslinechart.go deleted file mode 100644 index f81b4911..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/timeserieslinechart.go +++ /dev/null @@ -1,450 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -// Package timeserieslinechart implements a linechart that draws lines -// for time series data points -package timeserieslinechart - -// https://en.wikipedia.org/wiki/Moving_average - -import ( - "fmt" - "math" - "sort" - "time" - - "github.com/NimbleMarkets/ntcharts/canvas" - "github.com/NimbleMarkets/ntcharts/canvas/buffer" - "github.com/NimbleMarkets/ntcharts/canvas/graph" - "github.com/NimbleMarkets/ntcharts/canvas/runes" - "github.com/NimbleMarkets/ntcharts/linechart" - - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const DefaultDataSetName = "default" - -func DateTimeLabelFormatter() linechart.LabelFormatter { - var yearLabel string - return func(i int, v float64) string { - if i == 0 { // reset year labeling if redisplaying values - yearLabel = "" - } - t := time.Unix(int64(v), 0).UTC() - monthDay := t.Format("01/02") - year := t.Format("'06") - if yearLabel != year { // apply year label if first time seeing year - yearLabel = year - return fmt.Sprintf("%s %s", yearLabel, monthDay) - } else { - return monthDay - } - } -} - -func HourTimeLabelFormatter() linechart.LabelFormatter { - return func(i int, v float64) string { - t := time.Unix(int64(v), 0).UTC() - return t.Format("15:04:05") - } -} - -type TimePoint struct { - Time time.Time - Value float64 -} - -// cAverage tracks cumulative average -type cAverage struct { - Avg float64 - Count float64 -} - -// Add adds a float64 to current cumulative average -func (a *cAverage) Add(f float64) float64 { - a.Count += 1 - a.Avg += (f - a.Avg) / a.Count - return a.Avg -} - -type dataSet struct { - LineStyle runes.LineStyle // type of line runes to draw - Style lipgloss.Style - - lastTime time.Time // last seen time value - - // stores TimePoints as FloatPoint64{X:time.Time, Y: value} - // time.Time will be converted to seconds since epoch. - // both time and value will be scaled to fit the graphing area - tBuf *buffer.Float64PointScaleBuffer -} - -// Model contains state of a timeserieslinechart with an embedded linechart.Model -// The X axis contains time.Time values and the Y axis contains float64 values. -// A data set consists of a sequence TimePoints in chronological order. -// If multiple TimePoints map to the same column, then average value the time points -// will be used as the Y value of the column. -// The X axis contains a time range and the Y axis contains a numeric value range. -// Uses linechart Model UpdateHandler() for processing keyboard and mouse messages. -type Model struct { - linechart.Model - dLineStyle runes.LineStyle // default data set LineStyletype - dStyle lipgloss.Style // default data set Style - dSets map[string]*dataSet // maps names to data sets -} - -// New returns a timeserieslinechart Model initialized from -// width, height, Y value range and various options. -// By default, the chart will set time.Now() as the minimum time, -// enable auto set X and Y value ranges, -// and only allow moving viewport on X axis. -func New(w, h int, opts ...Option) Model { - min := time.Now() - max := min.Add(time.Second) - m := Model{ - Model: linechart.New(w, h, float64(min.Unix()), float64(max.Unix()), 0, 1, - linechart.WithXYSteps(4, 2), - linechart.WithXLabelFormatter(DateTimeLabelFormatter()), - linechart.WithAutoXYRange(), // automatically adjust value ranges - linechart.WithUpdateHandler(DateUpdateHandler(1))), // only scroll on X axis, increments by 1 day - dLineStyle: runes.ArcLineStyle, - dStyle: lipgloss.NewStyle(), - dSets: make(map[string]*dataSet), - } - for _, opt := range opts { - opt(&m) - } - m.UpdateGraphSizes() - m.rescaleData() - if _, ok := m.dSets[DefaultDataSetName]; !ok { - m.dSets[DefaultDataSetName] = m.newDataSet() - } - return m -} - -// newDataSet returns a new initialize *dataSet. -func (m *Model) newDataSet() *dataSet { - xs := float64(m.GraphWidth()) / (m.ViewMaxX() - m.ViewMinX()) // x scale factor - ys := float64(m.Origin().Y) / (m.ViewMaxY() - m.ViewMinY()) // y scale factor - offset := canvas.Float64Point{X: m.ViewMinX(), Y: m.ViewMinY()} - scale := canvas.Float64Point{X: xs, Y: ys} - return &dataSet{ - LineStyle: m.dLineStyle, - Style: m.dStyle, - tBuf: buffer.NewFloat64PointScaleBuffer(offset, scale), - } -} - -// rescaleData will reinitialize time chunks and -// map time points into graph columns for display -func (m *Model) rescaleData() { - // rescale time points buffer - xs := float64(m.GraphWidth()) / (m.ViewMaxX() - m.ViewMinX()) // x scale factor - ys := float64(m.Origin().Y) / (m.ViewMaxY() - m.ViewMinY()) // y scale factor - offset := canvas.Float64Point{X: m.ViewMinX(), Y: m.ViewMinY()} - scale := canvas.Float64Point{X: xs, Y: ys} - for _, ds := range m.dSets { - if ds.tBuf.Offset() != offset { - ds.tBuf.SetOffset(offset) - } - if ds.tBuf.Scale() != scale { - ds.tBuf.SetScale(scale) - } - } -} - -// ClearAllData will reset stored data values in all data sets. -func (m *Model) ClearAllData() { - for _, ds := range m.dSets { - ds.tBuf.Clear() - } - m.dSets[DefaultDataSetName] = m.newDataSet() -} - -// ClearDataSet will erase stored data set given by name string. -func (m *Model) ClearDataSet(n string) { - if ds, ok := m.dSets[n]; ok { - ds.tBuf.Clear() - } -} - -// SetTimeRange updates the minimum and maximum expected time values. -// Existing data will be rescaled. -func (m *Model) SetTimeRange(min, max time.Time) { - m.Model.SetXRange(float64(min.Unix()), float64(max.Unix())) - m.rescaleData() -} - -// SetYRange updates the minimum and maximum expected Y values. -// Existing data will be rescaled. -func (m *Model) SetYRange(min, max float64) { - m.Model.SetYRange(min, max) - m.rescaleData() -} - -// SetViewTimeRange updates the displayed minimum and maximum time values. -// Existing data will be rescaled. -func (m *Model) SetViewTimeRange(min, max time.Time) { - m.Model.SetViewXRange(float64(min.Unix()), float64(max.Unix())) - m.rescaleData() -} - -// SetViewYRange updates the displayed minimum and maximum Y values. -// Existing data will be rescaled. -func (m *Model) SetViewYRange(min, max float64) { - m.Model.SetViewYRange(min, max) - m.rescaleData() -} - -// SetViewTimeAndYRange updates the displayed minimum and maximum time and Y values. -// Existing data will be rescaled. -func (m *Model) SetViewTimeAndYRange(minX, maxX time.Time, minY, maxY float64) { - m.Model.SetViewXRange(float64(minX.Unix()), float64(maxX.Unix())) - m.Model.SetViewYRange(minY, maxY) - m.rescaleData() -} - -// Resize will change timeserieslinechart display width and height. -// Existing data will be rescaled. -func (m *Model) Resize(w, h int) { - m.Model.Resize(w, h) - m.rescaleData() -} - -// SetLineStyle will set the default line styles of data sets. -func (m *Model) SetLineStyle(ls runes.LineStyle) { - m.dLineStyle = ls - m.SetDataSetLineStyle(DefaultDataSetName, ls) -} - -// SetStyle will set the default lipgloss styles of data sets. -func (m *Model) SetStyle(s lipgloss.Style) { - m.dStyle = s - m.SetDataSetStyle(DefaultDataSetName, s) -} - -// SetDataSetLineStyle will set the line style of the given data set by name string. -func (m *Model) SetDataSetLineStyle(n string, ls runes.LineStyle) { - if _, ok := m.dSets[n]; !ok { - m.dSets[n] = m.newDataSet() - } - ds := m.dSets[n] - ds.LineStyle = ls -} - -// SetDataSetStyle will set the lipgloss style of the given data set by name string. -func (m *Model) SetDataSetStyle(n string, s lipgloss.Style) { - if _, ok := m.dSets[n]; !ok { - m.dSets[n] = m.newDataSet() - } - ds := m.dSets[n] - ds.Style = s -} - -// Push will push a TimePoint data value to the default data set -// to be displayed with Draw. -func (m *Model) Push(t TimePoint) { - m.PushDataSet(DefaultDataSetName, t) -} - -// Push will push a TimePoint data value to a data set -// to be displayed with Draw. Using given data set by name string. -func (m *Model) PushDataSet(n string, t TimePoint) { - f := canvas.Float64Point{X: float64(t.Time.Unix()), Y: t.Value} - // auto adjust x and y ranges if enabled - if m.AutoAdjustRange(f) { - m.UpdateGraphSizes() - m.rescaleData() - } - if _, ok := m.dSets[n]; !ok { - m.dSets[n] = m.newDataSet() - } - ds := m.dSets[n] - ds.tBuf.Push(f) -} - -// Draw will draw lines runes displayed from right to left -// of the graphing area of the canvas. Uses default data set. -func (m *Model) Draw() { - m.DrawDataSets([]string{DefaultDataSetName}) -} - -// DrawAll will draw lines runes for all data sets -// from right to left of the graphing area of the canvas. -func (m *Model) DrawAll() { - names := make([]string, 0, len(m.dSets)) - for n, ds := range m.dSets { - if ds.tBuf.Length() > 0 { - names = append(names, n) - } - } - sort.Strings(names) - m.DrawDataSets(names) -} - -// DrawDataSets will draw lines runes from right to left -// of the graphing area of the canvas for each data set given -// by name strings. -func (m *Model) DrawDataSets(names []string) { - if len(names) == 0 { - return - } - m.Clear() - m.DrawXYAxisAndLabel() - for _, n := range names { - if ds, ok := m.dSets[n]; ok { - dataPoints := ds.tBuf.ReadAll() - dataLen := len(dataPoints) - if dataLen == 0 { - return - } - // get sequence of line values for graphing - seqY := m.getLineSequence(dataPoints) - // convert to canvas coordinates and avoid drawing below X axis - yCoords := canvas.CanvasYCoordinates(m.Origin().Y, seqY) - if m.XStep() > 0 { - for i, v := range yCoords { - if v > m.Origin().Y { - yCoords[i] = m.Origin().Y - } - } - } - startX := m.Canvas.Width() - len(yCoords) - graph.DrawLineSequence(&m.Canvas, - (startX == m.Origin().X), - startX, - yCoords, - ds.LineStyle, - ds.Style) - } - } -} - -// DrawBraille will draw braille runes displayed from right to left -// of the graphing area of the canvas. Uses default data set. -func (m *Model) DrawBraille() { - m.DrawBrailleDataSets([]string{DefaultDataSetName}) -} - -// DrawBrailleAll will draw braille runes for all data sets -// from right to left of the graphing area of the canvas. -func (m *Model) DrawBrailleAll() { - names := make([]string, 0, len(m.dSets)) - for n, ds := range m.dSets { - if ds.tBuf.Length() > 0 { - names = append(names, n) - } - } - sort.Strings(names) - m.DrawBrailleDataSets(names) -} - -// DrawBrailleDataSets will draw braille runes from right to left -// of the graphing area of the canvas for each data set given -// by name strings. -func (m *Model) DrawBrailleDataSets(names []string) { - if len(names) == 0 { - return - } - m.Clear() - m.DrawXYAxisAndLabel() - for _, n := range names { - if ds, ok := m.dSets[n]; ok { - dataPoints := ds.tBuf.ReadAll() - dataLen := len(dataPoints) - if dataLen == 0 { - return - } - // draw lines from each point to the next point - bGrid := graph.NewBrailleGrid(m.GraphWidth(), m.GraphHeight(), - 0, float64(m.GraphWidth()), // X values already scaled to graph - 0, float64(m.GraphHeight())) // Y values already scaled to graph - for i := 0; i < dataLen; i++ { - j := i + 1 - if j >= dataLen { - j = i - } - p1 := dataPoints[i] - p2 := dataPoints[j] - // ignore points that will not be displayed - bothBeforeMin := (p1.X < 0 && p2.X < 0) - bothAfterMax := (p1.X > float64(m.GraphWidth()) && p2.X > float64(m.GraphWidth())) - if bothBeforeMin || bothAfterMax { - continue - } - // get braille grid points from two Float64Point data points - gp1 := bGrid.GridPoint(p1) - gp2 := bGrid.GridPoint(p2) - // set all points in the braille grid - // between two points that approximates a line - points := graph.GetLinePoints(gp1, gp2) - for _, p := range points { - bGrid.Set(p) - } - } - - // get all rune patterns for braille grid - // and draw them on to the canvas - startX := 0 - if m.YStep() > 0 { - startX = m.Origin().X + 1 - } - patterns := bGrid.BraillePatterns() - graph.DrawBraillePatterns(&m.Canvas, - canvas.Point{X: startX, Y: 0}, patterns, ds.Style) - } - } -} - -// getLineSequence returns a sequence of Y values -// to draw line runes from a given set of scaled []FloatPoint64. -func (m *Model) getLineSequence(points []canvas.Float64Point) []int { - width := m.Width() - m.Origin().X // line runes can draw on axes - if width <= 0 { - return []int{} - } - dataLen := len(points) - // each index of the bucket corresponds to a graph column. - // each index value is the average of data point values - // that is mapped to that graph column. - buckets := make([]cAverage, width, width) - for i := 0; i < dataLen; i++ { - j := i + 1 - if j >= dataLen { - j = i - } - p1 := canvas.NewPointFromFloat64Point(points[i]) - p2 := canvas.NewPointFromFloat64Point(points[j]) - // ignore points that will not be displayed on the graph - bothBeforeMin := (p1.X < 0 && p2.X < 0) - bothAfterMax := (p1.X > m.GraphWidth() && p2.X > m.GraphWidth()) - if bothBeforeMin || bothAfterMax { - continue - } - // place all points between two points - // that approximates a line into buckets - points := graph.GetLinePoints(p1, p2) - for _, p := range points { - if (p.X >= 0) && (p.X) < width { - buckets[p.X].Add(float64(p.Y)) - } - } - } - // populate sequence of Y values to for drawing - r := make([]int, width, width) - for i, v := range buckets { - r[i] = int(math.Round(v.Avg)) - } - return r -} - -// Update processes bubbletea Msg to by invoking -// UpdateHandlerFunc callback if linechart is focused. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - if !m.Focused() { - return m, nil - } - m.UpdateHandler(&m.Model, msg) - m.rescaleData() - return m, nil -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/updatehandler.go b/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/updatehandler.go deleted file mode 100644 index 0192293f..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart/updatehandler.go +++ /dev/null @@ -1,77 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -package timeserieslinechart - -// File contains methods and objects used during -// timeserieslinechart Model Update() to modify internal state. -// timeserieslinechart is able to zoom in and out of the graph, -// and increase and decrease the X values to simulating moving -// the viewport of the linechart - -import ( - "github.com/NimbleMarkets/ntcharts/linechart" -) - -// DateUpdateHandler is used by timeserieslinechart to enable -// zooming in and out with the mouse wheel or page up and page down, -// moving the viewing window by holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the X axis by day increments. -// Uses linechart Canvas Keymap for keyboard messages. -func DateUpdateHandler(i int) linechart.UpdateHandler { - daySeconds := 86400 * i // number of seconds in a day - return linechart.XAxisUpdateHandler(float64(daySeconds)) -} - -// DateNoZoomUpdateHandler is used by timeserieslinechart to enable -// moving the viewing window by using the mouse scroll wheel, -// holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the X axis by day increments. -// Uses linechart Canvas Keymap for keyboard messages. -func DateNoZoomUpdateHandler(i int) linechart.UpdateHandler { - daySeconds := 86400 * i // number of seconds in a day - return linechart.XAxisNoZoomUpdateHandler(float64(daySeconds)) -} - -// HourUpdateHandler is used by timeserieslinechart to enable -// zooming in and out with the mouse wheel or page up and page down, -// moving the viewing window by holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the X axis by hour increments. -// Uses linechart Canvas Keymap for keyboard messages. -func HourUpdateHandler(i int) linechart.UpdateHandler { - hourSeconds := 3600 * i // number of seconds in a hour - return linechart.XAxisUpdateHandler(float64(hourSeconds)) -} - -// HourNoZoomUpdateHandler is used by timeserieslinechart to enable -// moving the viewing window by using the mouse scroll wheel, -// holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the X axis by hour increments. -// Uses linechart Canvas Keymap for keyboard messages. -func HourNoZoomUpdateHandler(i int) linechart.UpdateHandler { - hourSeconds := 3600 * i // number of seconds in a hour - return linechart.XAxisNoZoomUpdateHandler(float64(hourSeconds)) -} - -// SecondUpdateHandler is used by timeserieslinechart to enable -// zooming in and out with the mouse wheel or page up and page down, -// moving the viewing window by holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the X axis by second increments. -// Uses linechart Canvas Keymap for keyboard messages. -func SecondUpdateHandler(i int) linechart.UpdateHandler { - return linechart.XAxisUpdateHandler(float64(i)) -} - -// SecondNoZoomUpdateHandler is used by timeserieslinechart to enable -// moving the viewing window by using the mouse scroll wheel, -// holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the X axis by second increments. -// Uses linechart Canvas Keymap for keyboard messages. -func SecondNoZoomUpdateHandler(i int) linechart.UpdateHandler { - return linechart.XAxisNoZoomUpdateHandler(float64(i)) -} diff --git a/vendor/github.com/NimbleMarkets/ntcharts/linechart/updatehandler.go b/vendor/github.com/NimbleMarkets/ntcharts/linechart/updatehandler.go deleted file mode 100644 index 974af8e4..00000000 --- a/vendor/github.com/NimbleMarkets/ntcharts/linechart/updatehandler.go +++ /dev/null @@ -1,361 +0,0 @@ -// ntcharts - Copyright (c) 2024 Neomantra Corp. - -package linechart - -// File contains methods and objects used during linechart Model Update() -// to modify internal state. -// linechart is able to zoom in and out of the graph, -// and increase and decrease the X and Y values to simulating moving -// the viewport of the linechart - -import ( - "github.com/NimbleMarkets/ntcharts/canvas" - - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" -) - -// UpdateHandler callback invoked during an Update() -// and passes in the linechart Model and bubbletea Msg. -type UpdateHandler func(*Model, tea.Msg) - -// XYAxesUpdateHandler is used by linechart to enable -// zooming in and out with the mouse wheel or page up and page down, -// moving the viewing window by holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// Uses linechart Canvas Keymap for keyboard messages. -func XYAxesUpdateHandler(xIncrement, yIncrement float64) UpdateHandler { - var lastPos canvas.Point - return func(m *Model, tm tea.Msg) { - switch msg := tm.(type) { - case tea.KeyMsg: - keyXYHandler(m, msg, xIncrement, yIncrement) - keyXYZoomHandler(m, msg, xIncrement, yIncrement) - case tea.MouseMsg: - switch msg.Button { - case tea.MouseButtonWheelUp: - // zoom in limited values cannot cross - m.ZoomIn(xIncrement, yIncrement) - case tea.MouseButtonWheelDown: - // zoom out limited by max values - m.ZoomOut(xIncrement, yIncrement) - } - mouseActionXYHandler(m, msg, &lastPos, xIncrement, yIncrement) - } - } -} - -// XAxisUpdateHandler is used by linechart to enable -// zooming in and out with the mouse wheel or page up and page down, -// moving the viewing window by holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the X axis with the given increment. -// Uses linechart Canvas Keymap for keyboard messages. -func XAxisUpdateHandler(increment float64) UpdateHandler { - var lastPos canvas.Point - return func(m *Model, tm tea.Msg) { - switch msg := tm.(type) { - case tea.KeyMsg: - keyXHandler(m, msg, increment) - keyXZoomHandler(m, msg, increment) - case tea.MouseMsg: - switch msg.Button { - case tea.MouseButtonWheelUp: - // zoom in limited values cannot cross - m.ZoomIn(increment, 0) - case tea.MouseButtonWheelDown: - // zoom out limited by max values - m.ZoomOut(increment, 0) - } - mouseActionXHandler(m, msg, &lastPos, increment) - } - } -} - -// XAxisNoZoomUpdateHandler is used by linechart to enable -// moving the viewing window along the X axis with mouse wheel, -// holding down the mouse button and moving, and with arrow keys. -// There is only movement along the X axis with the given increment. -// Uses linechart Canvas Keymap for keyboard messages. -func XAxisNoZoomUpdateHandler(increment float64) UpdateHandler { - var lastPos canvas.Point - return func(m *Model, tm tea.Msg) { - switch msg := tm.(type) { - case tea.KeyMsg: - keyXHandler(m, msg, increment) - case tea.MouseMsg: - switch msg.Button { - case tea.MouseButtonWheelUp, tea.MouseButtonWheelLeft: - m.MoveLeft(increment) - case tea.MouseButtonWheelDown, tea.MouseButtonWheelRight: - m.MoveRight(increment) - } - mouseActionXHandler(m, msg, &lastPos, increment) - } - } -} - -// YAxisUpdateHandler is used by steamlinechart to enable -// zooming in and out with the mouse wheel or page up and page down, -// moving the viewing window by holding down mouse button and moving, -// and moving the viewing window with the arrow keys. -// There is only movement along the Y axis with the given increment. -// Uses linechart Canvas Keymap for keyboard messages. -func YAxisUpdateHandler(increment float64) UpdateHandler { - var lastPos canvas.Point - return func(m *Model, tm tea.Msg) { - switch msg := tm.(type) { - case tea.KeyMsg: - keyYHandler(m, msg, increment) - keyYZoomHandler(m, msg, increment) - case tea.MouseMsg: - switch msg.Button { - case tea.MouseButtonWheelUp: - // zoom in limited values cannot cross - m.ZoomIn(0, increment) - case tea.MouseButtonWheelDown: - // zoom out limited by max values - m.ZoomOut(0, increment) - } - mouseActionYHandler(m, msg, &lastPos, increment) - } - } -} - -// YAxisNoZoomUpdateHandler is used by steamlinechart to enable -// moving the viewing window along the Y axis with mouse wheel, -// holding down the mouse button and moving, and with arrow keys. -// There is only movement along the Y axis with the given increment. -// Uses linechart Canvas Keymap for keyboard messages. -func YAxisNoZoomUpdateHandler(increment float64) UpdateHandler { - var lastPos canvas.Point - return func(m *Model, tm tea.Msg) { - switch msg := tm.(type) { - case tea.KeyMsg: - keyYHandler(m, msg, increment) - case tea.MouseMsg: - switch msg.Button { - case tea.MouseButtonWheelUp: - m.MoveUp(increment) - case tea.MouseButtonWheelDown: - m.MoveDown(increment) - } - mouseActionYHandler(m, msg, &lastPos, increment) - } - } -} - -// ZoomIn will update display X and Y values to simulate -// zooming into the linechart by given increments. -func (m *Model) ZoomIn(x, y float64) { - m.SetViewXYRange( - m.viewMinX+x, - m.viewMaxX-x, - m.viewMinY+y, - m.viewMaxY-y, - ) -} - -// ZoomOut will update display X and Y values to simulate -// zooming into the linechart by given increments. -func (m *Model) ZoomOut(x, y float64) { - m.SetViewXYRange( - m.viewMinX-x, - m.viewMaxX+x, - m.viewMinY-y, - m.viewMaxY+y, - ) -} - -// MoveLeft will update display Y values to simulate -// moving left on the linechart by given increment -func (m *Model) MoveLeft(i float64) { - if (m.viewMinX - i) >= m.MinX() { - m.SetViewXRange(m.viewMinX-i, m.viewMaxX-i) - } else { - i = m.viewMinX - m.MinX() - m.SetViewXRange(m.viewMinX-i, m.viewMaxX-i) - } -} - -// MoveRight will update display Y values to simulate -// moving right on the linechart by given increment. -func (m *Model) MoveRight(i float64) { - if (m.viewMaxX + i) <= m.MaxX() { - m.SetViewXRange(m.viewMinX+i, m.viewMaxX+i) - } else { - i = m.MaxX() - m.viewMaxX - m.SetViewXRange(m.viewMinX+i, m.viewMaxX+i) - } -} - -// MoveUp will update display X values to simulate -// moving up on the linechart chart by given increment. -func (m *Model) MoveUp(i float64) { - if (m.viewMaxY + i) <= m.MaxY() { - m.SetViewYRange(m.viewMinY+i, m.viewMaxY+i) - } else { - i = m.MaxY() - m.viewMaxY - m.SetViewYRange(m.viewMinY+i, m.viewMaxY+i) - } -} - -// MoveDown will update display Y values to simulate -// moving down on the linechart chart by given increment. -func (m *Model) MoveDown(i float64) { - if (m.viewMinY - i) >= m.MinY() { - m.SetViewYRange(m.viewMinY-i, m.viewMaxY-i) - } else { - i = m.viewMinY - m.MinY() - m.SetViewYRange(m.viewMinY-i, m.viewMaxY-i) - } - -} - -// keyXYHandler handles keyboard messages for X and Y axis moving -func keyXYHandler(m *Model, msg tea.KeyMsg, xIncrement, yIncrement float64) { - switch { - case key.Matches(msg, m.Canvas.KeyMap.Up): - m.MoveUp(yIncrement) - case key.Matches(msg, m.Canvas.KeyMap.Down): - m.MoveDown(yIncrement) - case key.Matches(msg, m.Canvas.KeyMap.Left): - m.MoveLeft(xIncrement) - case key.Matches(msg, m.Canvas.KeyMap.Right): - m.MoveRight(xIncrement) - } -} - -// keyXHandler handles keyboard messages for X axis moving -func keyXHandler(m *Model, msg tea.KeyMsg, xIncrement float64) { - switch { - case key.Matches(msg, m.Canvas.KeyMap.Left): - m.MoveLeft(xIncrement) - case key.Matches(msg, m.Canvas.KeyMap.Right): - m.MoveRight(xIncrement) - } -} - -// keyYHandler handles keyboard messages for Y axis moving -func keyYHandler(m *Model, msg tea.KeyMsg, yIncrement float64) { - switch { - case key.Matches(msg, m.Canvas.KeyMap.Up): - m.MoveUp(yIncrement) - case key.Matches(msg, m.Canvas.KeyMap.Down): - m.MoveDown(yIncrement) - } -} - -// keyXYZoomHandler handles keyboard messages for X and Y axis zooming -func keyXYZoomHandler(m *Model, msg tea.KeyMsg, xIncrement, yIncrement float64) { - switch { - case key.Matches(msg, m.Canvas.KeyMap.PgUp): - m.ZoomIn(xIncrement, yIncrement) - case key.Matches(msg, m.Canvas.KeyMap.PgDown): - m.ZoomOut(xIncrement, yIncrement) - } -} - -// keyXZoomHandler handles keyboard messages for X axis zooming -func keyXZoomHandler(m *Model, msg tea.KeyMsg, xIncrement float64) { - switch { - case key.Matches(msg, m.Canvas.KeyMap.PgUp): - m.ZoomIn(xIncrement, 0) - case key.Matches(msg, m.Canvas.KeyMap.PgDown): - m.ZoomOut(xIncrement, 0) - } -} - -// keyYZoomHandler handles keyboard messages for Y axis zooming -func keyYZoomHandler(m *Model, msg tea.KeyMsg, yIncrement float64) { - switch { - case key.Matches(msg, m.Canvas.KeyMap.PgUp): - m.ZoomIn(0, yIncrement) - case key.Matches(msg, m.Canvas.KeyMap.PgDown): - m.ZoomOut(0, yIncrement) - } -} - -// mouseActionXYHandler handles mouse click messages for X and Y axes -func mouseActionXYHandler(m *Model, msg tea.MouseMsg, lastPos *canvas.Point, xIncrement, yIncrement float64) { - if m.ZoneManager() == nil { - return - } - switch msg.Action { - case tea.MouseActionPress: - zInfo := m.ZoneManager().Get(m.ZoneID()) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - *lastPos = canvas.Point{X: x, Y: y} - } - case tea.MouseActionMotion: - zInfo := m.ZoneManager().Get(m.ZoneID()) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - if x > lastPos.X { - m.MoveRight(xIncrement) - } else if x < lastPos.X { - m.MoveLeft(xIncrement) - } - if y > lastPos.Y { - m.MoveDown(yIncrement) - } else if y < lastPos.Y { - m.MoveUp(yIncrement) - } - *lastPos = canvas.Point{X: x, Y: y} - } - } -} - -// mouseActionXHandler handles mouse click messages for X axis -func mouseActionXHandler(m *Model, msg tea.MouseMsg, lastPos *canvas.Point, increment float64) { - if m.ZoneManager() == nil { - return - } - switch msg.Action { - case tea.MouseActionPress: - zInfo := m.ZoneManager().Get(m.ZoneID()) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - *lastPos = canvas.Point{X: x, Y: y} - } - case tea.MouseActionMotion: - zInfo := m.ZoneManager().Get(m.ZoneID()) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - if x > lastPos.X { - m.MoveRight(increment) - } else if x < lastPos.X { - m.MoveLeft(increment) - } - *lastPos = canvas.Point{X: x, Y: y} - } - } - -} - -// mouseActionYHandler handles mouse click messages for Y axis -func mouseActionYHandler(m *Model, msg tea.MouseMsg, lastPos *canvas.Point, increment float64) { - if m.ZoneManager() == nil { - return - } - switch msg.Action { - case tea.MouseActionPress: - zInfo := m.ZoneManager().Get(m.ZoneID()) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - *lastPos = canvas.Point{X: x, Y: y} // set position of last click - } - case tea.MouseActionMotion: // event occurs when mouse is pressed - zInfo := m.ZoneManager().Get(m.ZoneID()) - if zInfo.InBounds(msg) { - x, y := zInfo.Pos(msg) - if y > lastPos.Y { - m.MoveDown(increment) - } else if y < lastPos.Y { - m.MoveUp(increment) - } - *lastPos = canvas.Point{X: x, Y: y} // update last mouse position - } - } -} diff --git a/vendor/github.com/ProtonMail/go-crypto/AUTHORS b/vendor/github.com/ProtonMail/go-crypto/AUTHORS deleted file mode 100644 index 2b00ddba..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS b/vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS deleted file mode 100644 index 1fbd3e97..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/ProtonMail/go-crypto/LICENSE b/vendor/github.com/ProtonMail/go-crypto/LICENSE deleted file mode 100644 index 6a66aea5..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ProtonMail/go-crypto/PATENTS b/vendor/github.com/ProtonMail/go-crypto/PATENTS deleted file mode 100644 index 73309904..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go b/vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go deleted file mode 100644 index c85e6bef..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go +++ /dev/null @@ -1,381 +0,0 @@ -package bitcurves - -// Copyright 2010 The Go Authors. All rights reserved. -// Copyright 2011 ThePiachu. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package bitelliptic implements several Koblitz elliptic curves over prime -// fields. - -// This package operates, internally, on Jacobian coordinates. For a given -// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1) -// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole -// calculation can be performed within the transform (as in ScalarMult and -// ScalarBaseMult). But even for Add and Double, it's faster to apply and -// reverse the transform than to operate in affine coordinates. - -import ( - "crypto/elliptic" - "io" - "math/big" - "sync" -) - -// A BitCurve represents a Koblitz Curve with a=0. -// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html -type BitCurve struct { - Name string - P *big.Int // the order of the underlying field - N *big.Int // the order of the base point - B *big.Int // the constant of the BitCurve equation - Gx, Gy *big.Int // (x,y) of the base point - BitSize int // the size of the underlying field -} - -// Params returns the parameters of the given BitCurve (see BitCurve struct) -func (bitCurve *BitCurve) Params() (cp *elliptic.CurveParams) { - cp = new(elliptic.CurveParams) - cp.Name = bitCurve.Name - cp.P = bitCurve.P - cp.N = bitCurve.N - cp.Gx = bitCurve.Gx - cp.Gy = bitCurve.Gy - cp.BitSize = bitCurve.BitSize - return cp -} - -// IsOnCurve returns true if the given (x,y) lies on the BitCurve. -func (bitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool { - // y² = x³ + b - y2 := new(big.Int).Mul(y, y) //y² - y2.Mod(y2, bitCurve.P) //y²%P - - x3 := new(big.Int).Mul(x, x) //x² - x3.Mul(x3, x) //x³ - - x3.Add(x3, bitCurve.B) //x³+B - x3.Mod(x3, bitCurve.P) //(x³+B)%P - - return x3.Cmp(y2) == 0 -} - -// affineFromJacobian reverses the Jacobian transform. See the comment at the -// top of the file. -func (bitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { - if z.Cmp(big.NewInt(0)) == 0 { - panic("bitcurve: Can't convert to affine with Jacobian Z = 0") - } - // x = YZ^2 mod P - zinv := new(big.Int).ModInverse(z, bitCurve.P) - zinvsq := new(big.Int).Mul(zinv, zinv) - - xOut = new(big.Int).Mul(x, zinvsq) - xOut.Mod(xOut, bitCurve.P) - // y = YZ^3 mod P - zinvsq.Mul(zinvsq, zinv) - yOut = new(big.Int).Mul(y, zinvsq) - yOut.Mod(yOut, bitCurve.P) - return xOut, yOut -} - -// Add returns the sum of (x1,y1) and (x2,y2) -func (bitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { - z := new(big.Int).SetInt64(1) - x, y, z := bitCurve.addJacobian(x1, y1, z, x2, y2, z) - return bitCurve.affineFromJacobian(x, y, z) -} - -// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and -// (x2, y2, z2) and returns their sum, also in Jacobian form. -func (bitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl - z1z1 := new(big.Int).Mul(z1, z1) - z1z1.Mod(z1z1, bitCurve.P) - z2z2 := new(big.Int).Mul(z2, z2) - z2z2.Mod(z2z2, bitCurve.P) - - u1 := new(big.Int).Mul(x1, z2z2) - u1.Mod(u1, bitCurve.P) - u2 := new(big.Int).Mul(x2, z1z1) - u2.Mod(u2, bitCurve.P) - h := new(big.Int).Sub(u2, u1) - if h.Sign() == -1 { - h.Add(h, bitCurve.P) - } - i := new(big.Int).Lsh(h, 1) - i.Mul(i, i) - j := new(big.Int).Mul(h, i) - - s1 := new(big.Int).Mul(y1, z2) - s1.Mul(s1, z2z2) - s1.Mod(s1, bitCurve.P) - s2 := new(big.Int).Mul(y2, z1) - s2.Mul(s2, z1z1) - s2.Mod(s2, bitCurve.P) - r := new(big.Int).Sub(s2, s1) - if r.Sign() == -1 { - r.Add(r, bitCurve.P) - } - r.Lsh(r, 1) - v := new(big.Int).Mul(u1, i) - - x3 := new(big.Int).Set(r) - x3.Mul(x3, x3) - x3.Sub(x3, j) - x3.Sub(x3, v) - x3.Sub(x3, v) - x3.Mod(x3, bitCurve.P) - - y3 := new(big.Int).Set(r) - v.Sub(v, x3) - y3.Mul(y3, v) - s1.Mul(s1, j) - s1.Lsh(s1, 1) - y3.Sub(y3, s1) - y3.Mod(y3, bitCurve.P) - - z3 := new(big.Int).Add(z1, z2) - z3.Mul(z3, z3) - z3.Sub(z3, z1z1) - if z3.Sign() == -1 { - z3.Add(z3, bitCurve.P) - } - z3.Sub(z3, z2z2) - if z3.Sign() == -1 { - z3.Add(z3, bitCurve.P) - } - z3.Mul(z3, h) - z3.Mod(z3, bitCurve.P) - - return x3, y3, z3 -} - -// Double returns 2*(x,y) -func (bitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { - z1 := new(big.Int).SetInt64(1) - return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z1)) -} - -// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and -// returns its double, also in Jacobian form. -func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - - a := new(big.Int).Mul(x, x) //X1² - b := new(big.Int).Mul(y, y) //Y1² - c := new(big.Int).Mul(b, b) //B² - - d := new(big.Int).Add(x, b) //X1+B - d.Mul(d, d) //(X1+B)² - d.Sub(d, a) //(X1+B)²-A - d.Sub(d, c) //(X1+B)²-A-C - d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C) - - e := new(big.Int).Mul(big.NewInt(3), a) //3*A - f := new(big.Int).Mul(e, e) //E² - - x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D - x3.Sub(f, x3) //F-2*D - x3.Mod(x3, bitCurve.P) - - y3 := new(big.Int).Sub(d, x3) //D-X3 - y3.Mul(e, y3) //E*(D-X3) - y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C - y3.Mod(y3, bitCurve.P) - - z3 := new(big.Int).Mul(y, z) //Y1*Z1 - z3.Mul(big.NewInt(2), z3) //3*Y1*Z1 - z3.Mod(z3, bitCurve.P) - - return x3, y3, z3 -} - -// TODO: double check if it is okay -// ScalarMult returns k*(Bx,By) where k is a number in big-endian form. -func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { - // We have a slight problem in that the identity of the group (the - // point at infinity) cannot be represented in (x, y) form on a finite - // machine. Thus the standard add/double algorithm has to be tweaked - // slightly: our initial state is not the identity, but x, and we - // ignore the first true bit in |k|. If we don't find any true bits in - // |k|, then we return nil, nil, because we cannot return the identity - // element. - - Bz := new(big.Int).SetInt64(1) - x := Bx - y := By - z := Bz - - seenFirstTrue := false - for _, byte := range k { - for bitNum := 0; bitNum < 8; bitNum++ { - if seenFirstTrue { - x, y, z = bitCurve.doubleJacobian(x, y, z) - } - if byte&0x80 == 0x80 { - if !seenFirstTrue { - seenFirstTrue = true - } else { - x, y, z = bitCurve.addJacobian(Bx, By, Bz, x, y, z) - } - } - byte <<= 1 - } - } - - if !seenFirstTrue { - return nil, nil - } - - return bitCurve.affineFromJacobian(x, y, z) -} - -// ScalarBaseMult returns k*G, where G is the base point of the group and k is -// an integer in big-endian form. -func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { - return bitCurve.ScalarMult(bitCurve.Gx, bitCurve.Gy, k) -} - -var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} - -// TODO: double check if it is okay -// GenerateKey returns a public/private key pair. The private key is generated -// using the given reader, which must return random data. -func (bitCurve *BitCurve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err error) { - byteLen := (bitCurve.BitSize + 7) >> 3 - priv = make([]byte, byteLen) - - for x == nil { - _, err = io.ReadFull(rand, priv) - if err != nil { - return - } - // We have to mask off any excess bits in the case that the size of the - // underlying field is not a whole number of bytes. - priv[0] &= mask[bitCurve.BitSize%8] - // This is because, in tests, rand will return all zeros and we don't - // want to get the point at infinity and loop forever. - priv[1] ^= 0x42 - x, y = bitCurve.ScalarBaseMult(priv) - } - return -} - -// Marshal converts a point into the form specified in section 4.3.6 of ANSI -// X9.62. -func (bitCurve *BitCurve) Marshal(x, y *big.Int) []byte { - byteLen := (bitCurve.BitSize + 7) >> 3 - - ret := make([]byte, 1+2*byteLen) - ret[0] = 4 // uncompressed point - - xBytes := x.Bytes() - copy(ret[1+byteLen-len(xBytes):], xBytes) - yBytes := y.Bytes() - copy(ret[1+2*byteLen-len(yBytes):], yBytes) - return ret -} - -// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On -// error, x = nil. -func (bitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) { - byteLen := (bitCurve.BitSize + 7) >> 3 - if len(data) != 1+2*byteLen { - return - } - if data[0] != 4 { // uncompressed form - return - } - x = new(big.Int).SetBytes(data[1 : 1+byteLen]) - y = new(big.Int).SetBytes(data[1+byteLen:]) - return -} - -//curve parameters taken from: -//http://www.secg.org/collateral/sec2_final.pdf - -var initonce sync.Once -var secp160k1 *BitCurve -var secp192k1 *BitCurve -var secp224k1 *BitCurve -var secp256k1 *BitCurve - -func initAll() { - initS160() - initS192() - initS224() - initS256() -} - -func initS160() { - // See SEC 2 section 2.4.1 - secp160k1 = new(BitCurve) - secp160k1.Name = "secp160k1" - secp160k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", 16) - secp160k1.N, _ = new(big.Int).SetString("0100000000000000000001B8FA16DFAB9ACA16B6B3", 16) - secp160k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000007", 16) - secp160k1.Gx, _ = new(big.Int).SetString("3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", 16) - secp160k1.Gy, _ = new(big.Int).SetString("938CF935318FDCED6BC28286531733C3F03C4FEE", 16) - secp160k1.BitSize = 160 -} - -func initS192() { - // See SEC 2 section 2.5.1 - secp192k1 = new(BitCurve) - secp192k1.Name = "secp192k1" - secp192k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", 16) - secp192k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 16) - secp192k1.B, _ = new(big.Int).SetString("000000000000000000000000000000000000000000000003", 16) - secp192k1.Gx, _ = new(big.Int).SetString("DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", 16) - secp192k1.Gy, _ = new(big.Int).SetString("9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", 16) - secp192k1.BitSize = 192 -} - -func initS224() { - // See SEC 2 section 2.6.1 - secp224k1 = new(BitCurve) - secp224k1.Name = "secp224k1" - secp224k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", 16) - secp224k1.N, _ = new(big.Int).SetString("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 16) - secp224k1.B, _ = new(big.Int).SetString("00000000000000000000000000000000000000000000000000000005", 16) - secp224k1.Gx, _ = new(big.Int).SetString("A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", 16) - secp224k1.Gy, _ = new(big.Int).SetString("7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", 16) - secp224k1.BitSize = 224 -} - -func initS256() { - // See SEC 2 section 2.7.1 - secp256k1 = new(BitCurve) - secp256k1.Name = "secp256k1" - secp256k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16) - secp256k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) - secp256k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16) - secp256k1.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16) - secp256k1.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16) - secp256k1.BitSize = 256 -} - -// S160 returns a BitCurve which implements secp160k1 (see SEC 2 section 2.4.1) -func S160() *BitCurve { - initonce.Do(initAll) - return secp160k1 -} - -// S192 returns a BitCurve which implements secp192k1 (see SEC 2 section 2.5.1) -func S192() *BitCurve { - initonce.Do(initAll) - return secp192k1 -} - -// S224 returns a BitCurve which implements secp224k1 (see SEC 2 section 2.6.1) -func S224() *BitCurve { - initonce.Do(initAll) - return secp224k1 -} - -// S256 returns a BitCurve which implements bitcurves (see SEC 2 section 2.7.1) -func S256() *BitCurve { - initonce.Do(initAll) - return secp256k1 -} diff --git a/vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go b/vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go deleted file mode 100644 index cb6676de..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go +++ /dev/null @@ -1,134 +0,0 @@ -// Package brainpool implements Brainpool elliptic curves. -// Implementation of rcurves is from github.com/ebfe/brainpool -// Note that these curves are implemented with naive, non-constant time operations -// and are likely not suitable for environments where timing attacks are a concern. -package brainpool - -import ( - "crypto/elliptic" - "math/big" - "sync" -) - -var ( - once sync.Once - p256t1, p384t1, p512t1 *elliptic.CurveParams - p256r1, p384r1, p512r1 *rcurve -) - -func initAll() { - initP256t1() - initP384t1() - initP512t1() - initP256r1() - initP384r1() - initP512r1() -} - -func initP256t1() { - p256t1 = &elliptic.CurveParams{Name: "brainpoolP256t1"} - p256t1.P, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16) - p256t1.N, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16) - p256t1.B, _ = new(big.Int).SetString("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16) - p256t1.Gx, _ = new(big.Int).SetString("A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", 16) - p256t1.Gy, _ = new(big.Int).SetString("2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", 16) - p256t1.BitSize = 256 -} - -func initP256r1() { - twisted := p256t1 - params := &elliptic.CurveParams{ - Name: "brainpoolP256r1", - P: twisted.P, - N: twisted.N, - BitSize: twisted.BitSize, - } - params.Gx, _ = new(big.Int).SetString("8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", 16) - params.Gy, _ = new(big.Int).SetString("547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", 16) - z, _ := new(big.Int).SetString("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0", 16) - p256r1 = newrcurve(twisted, params, z) -} - -func initP384t1() { - p384t1 = &elliptic.CurveParams{Name: "brainpoolP384t1"} - p384t1.P, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16) - p384t1.N, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16) - p384t1.B, _ = new(big.Int).SetString("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16) - p384t1.Gx, _ = new(big.Int).SetString("18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", 16) - p384t1.Gy, _ = new(big.Int).SetString("25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", 16) - p384t1.BitSize = 384 -} - -func initP384r1() { - twisted := p384t1 - params := &elliptic.CurveParams{ - Name: "brainpoolP384r1", - P: twisted.P, - N: twisted.N, - BitSize: twisted.BitSize, - } - params.Gx, _ = new(big.Int).SetString("1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", 16) - params.Gy, _ = new(big.Int).SetString("8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", 16) - z, _ := new(big.Int).SetString("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C", 16) - p384r1 = newrcurve(twisted, params, z) -} - -func initP512t1() { - p512t1 = &elliptic.CurveParams{Name: "brainpoolP512t1"} - p512t1.P, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16) - p512t1.N, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16) - p512t1.B, _ = new(big.Int).SetString("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16) - p512t1.Gx, _ = new(big.Int).SetString("640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", 16) - p512t1.Gy, _ = new(big.Int).SetString("5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", 16) - p512t1.BitSize = 512 -} - -func initP512r1() { - twisted := p512t1 - params := &elliptic.CurveParams{ - Name: "brainpoolP512r1", - P: twisted.P, - N: twisted.N, - BitSize: twisted.BitSize, - } - params.Gx, _ = new(big.Int).SetString("81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", 16) - params.Gy, _ = new(big.Int).SetString("7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", 16) - z, _ := new(big.Int).SetString("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB", 16) - p512r1 = newrcurve(twisted, params, z) -} - -// P256t1 returns a Curve which implements Brainpool P256t1 (see RFC 5639, section 3.4) -func P256t1() elliptic.Curve { - once.Do(initAll) - return p256t1 -} - -// P256r1 returns a Curve which implements Brainpool P256r1 (see RFC 5639, section 3.4) -func P256r1() elliptic.Curve { - once.Do(initAll) - return p256r1 -} - -// P384t1 returns a Curve which implements Brainpool P384t1 (see RFC 5639, section 3.6) -func P384t1() elliptic.Curve { - once.Do(initAll) - return p384t1 -} - -// P384r1 returns a Curve which implements Brainpool P384r1 (see RFC 5639, section 3.6) -func P384r1() elliptic.Curve { - once.Do(initAll) - return p384r1 -} - -// P512t1 returns a Curve which implements Brainpool P512t1 (see RFC 5639, section 3.7) -func P512t1() elliptic.Curve { - once.Do(initAll) - return p512t1 -} - -// P512r1 returns a Curve which implements Brainpool P512r1 (see RFC 5639, section 3.7) -func P512r1() elliptic.Curve { - once.Do(initAll) - return p512r1 -} diff --git a/vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go b/vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go deleted file mode 100644 index 7e291d6a..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go +++ /dev/null @@ -1,83 +0,0 @@ -package brainpool - -import ( - "crypto/elliptic" - "math/big" -) - -var _ elliptic.Curve = (*rcurve)(nil) - -type rcurve struct { - twisted elliptic.Curve - params *elliptic.CurveParams - z *big.Int - zinv *big.Int - z2 *big.Int - z3 *big.Int - zinv2 *big.Int - zinv3 *big.Int -} - -var ( - two = big.NewInt(2) - three = big.NewInt(3) -) - -func newrcurve(twisted elliptic.Curve, params *elliptic.CurveParams, z *big.Int) *rcurve { - zinv := new(big.Int).ModInverse(z, params.P) - return &rcurve{ - twisted: twisted, - params: params, - z: z, - zinv: zinv, - z2: new(big.Int).Exp(z, two, params.P), - z3: new(big.Int).Exp(z, three, params.P), - zinv2: new(big.Int).Exp(zinv, two, params.P), - zinv3: new(big.Int).Exp(zinv, three, params.P), - } -} - -func (curve *rcurve) toTwisted(x, y *big.Int) (*big.Int, *big.Int) { - var tx, ty big.Int - tx.Mul(x, curve.z2) - tx.Mod(&tx, curve.params.P) - ty.Mul(y, curve.z3) - ty.Mod(&ty, curve.params.P) - return &tx, &ty -} - -func (curve *rcurve) fromTwisted(tx, ty *big.Int) (*big.Int, *big.Int) { - var x, y big.Int - x.Mul(tx, curve.zinv2) - x.Mod(&x, curve.params.P) - y.Mul(ty, curve.zinv3) - y.Mod(&y, curve.params.P) - return &x, &y -} - -func (curve *rcurve) Params() *elliptic.CurveParams { - return curve.params -} - -func (curve *rcurve) IsOnCurve(x, y *big.Int) bool { - return curve.twisted.IsOnCurve(curve.toTwisted(x, y)) -} - -func (curve *rcurve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) { - tx1, ty1 := curve.toTwisted(x1, y1) - tx2, ty2 := curve.toTwisted(x2, y2) - return curve.fromTwisted(curve.twisted.Add(tx1, ty1, tx2, ty2)) -} - -func (curve *rcurve) Double(x1, y1 *big.Int) (x, y *big.Int) { - return curve.fromTwisted(curve.twisted.Double(curve.toTwisted(x1, y1))) -} - -func (curve *rcurve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) { - tx1, ty1 := curve.toTwisted(x1, y1) - return curve.fromTwisted(curve.twisted.ScalarMult(tx1, ty1, scalar)) -} - -func (curve *rcurve) ScalarBaseMult(scalar []byte) (x, y *big.Int) { - return curve.fromTwisted(curve.twisted.ScalarBaseMult(scalar)) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/eax/eax.go b/vendor/github.com/ProtonMail/go-crypto/eax/eax.go deleted file mode 100644 index 3ae91d59..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/eax/eax.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (C) 2019 ProtonTech AG - -// Package eax provides an implementation of the EAX -// (encrypt-authenticate-translate) mode of operation, as described in -// Bellare, Rogaway, and Wagner "THE EAX MODE OF OPERATION: A TWO-PASS -// AUTHENTICATED-ENCRYPTION SCHEME OPTIMIZED FOR SIMPLICITY AND EFFICIENCY." -// In FSE'04, volume 3017 of LNCS, 2004 -package eax - -import ( - "crypto/cipher" - "crypto/subtle" - "errors" - "github.com/ProtonMail/go-crypto/internal/byteutil" -) - -const ( - defaultTagSize = 16 - defaultNonceSize = 16 -) - -type eax struct { - block cipher.Block // Only AES-{128, 192, 256} supported - tagSize int // At least 12 bytes recommended - nonceSize int -} - -func (e *eax) NonceSize() int { - return e.nonceSize -} - -func (e *eax) Overhead() int { - return e.tagSize -} - -// NewEAX returns an EAX instance with AES-{KEYLENGTH} and default nonce and -// tag lengths. Supports {128, 192, 256}- bit key length. -func NewEAX(block cipher.Block) (cipher.AEAD, error) { - return NewEAXWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize) -} - -// NewEAXWithNonceAndTagSize returns an EAX instance with AES-{keyLength} and -// given nonce and tag lengths in bytes. Panics on zero nonceSize and -// exceedingly long tags. -// -// It is recommended to use at least 12 bytes as tag length (see, for instance, -// NIST SP 800-38D). -// -// Only to be used for compatibility with existing cryptosystems with -// non-standard parameters. For all other cases, prefer NewEAX. -func NewEAXWithNonceAndTagSize( - block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) { - if nonceSize < 1 { - return nil, eaxError("Cannot initialize EAX with nonceSize = 0") - } - if tagSize > block.BlockSize() { - return nil, eaxError("Custom tag length exceeds blocksize") - } - return &eax{ - block: block, - tagSize: tagSize, - nonceSize: nonceSize, - }, nil -} - -func (e *eax) Seal(dst, nonce, plaintext, adata []byte) []byte { - if len(nonce) > e.nonceSize { - panic("crypto/eax: Nonce too long for this instance") - } - ret, out := byteutil.SliceForAppend(dst, len(plaintext)+e.tagSize) - omacNonce := e.omacT(0, nonce) - omacAdata := e.omacT(1, adata) - - // Encrypt message using CTR mode and omacNonce as IV - ctr := cipher.NewCTR(e.block, omacNonce) - ciphertextData := out[:len(plaintext)] - ctr.XORKeyStream(ciphertextData, plaintext) - - omacCiphertext := e.omacT(2, ciphertextData) - - tag := out[len(plaintext):] - for i := 0; i < e.tagSize; i++ { - tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i] - } - return ret -} - -func (e *eax) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { - if len(nonce) > e.nonceSize { - panic("crypto/eax: Nonce too long for this instance") - } - if len(ciphertext) < e.tagSize { - return nil, eaxError("Ciphertext shorter than tag length") - } - sep := len(ciphertext) - e.tagSize - - // Compute tag - omacNonce := e.omacT(0, nonce) - omacAdata := e.omacT(1, adata) - omacCiphertext := e.omacT(2, ciphertext[:sep]) - - tag := make([]byte, e.tagSize) - for i := 0; i < e.tagSize; i++ { - tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i] - } - - // Compare tags - if subtle.ConstantTimeCompare(ciphertext[sep:], tag) != 1 { - return nil, eaxError("Tag authentication failed") - } - - // Decrypt ciphertext - ret, out := byteutil.SliceForAppend(dst, len(ciphertext)) - ctr := cipher.NewCTR(e.block, omacNonce) - ctr.XORKeyStream(out, ciphertext[:sep]) - - return ret[:sep], nil -} - -// Tweakable OMAC - Calls OMAC_K([t]_n || plaintext) -func (e *eax) omacT(t byte, plaintext []byte) []byte { - blockSize := e.block.BlockSize() - byteT := make([]byte, blockSize) - byteT[blockSize-1] = t - concat := append(byteT, plaintext...) - return e.omac(concat) -} - -func (e *eax) omac(plaintext []byte) []byte { - blockSize := e.block.BlockSize() - // L ← E_K(0^n); B ← 2L; P ← 4L - L := make([]byte, blockSize) - e.block.Encrypt(L, L) - B := byteutil.GfnDouble(L) - P := byteutil.GfnDouble(B) - - // CBC with IV = 0 - cbc := cipher.NewCBCEncrypter(e.block, make([]byte, blockSize)) - padded := e.pad(plaintext, B, P) - cbcCiphertext := make([]byte, len(padded)) - cbc.CryptBlocks(cbcCiphertext, padded) - - return cbcCiphertext[len(cbcCiphertext)-blockSize:] -} - -func (e *eax) pad(plaintext, B, P []byte) []byte { - // if |M| in {n, 2n, 3n, ...} - blockSize := e.block.BlockSize() - if len(plaintext) != 0 && len(plaintext)%blockSize == 0 { - return byteutil.RightXor(plaintext, B) - } - - // else return (M || 1 || 0^(n−1−(|M| % n))) xor→ P - ending := make([]byte, blockSize-len(plaintext)%blockSize) - ending[0] = 0x80 - padded := append(plaintext, ending...) - return byteutil.RightXor(padded, P) -} - -func eaxError(err string) error { - return errors.New("crypto/eax: " + err) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go b/vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go deleted file mode 100644 index ddb53d07..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go +++ /dev/null @@ -1,58 +0,0 @@ -package eax - -// Test vectors from -// https://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf -var testVectors = []struct { - msg, key, nonce, header, ciphertext string -}{ - {"", - "233952DEE4D5ED5F9B9C6D6FF80FF478", - "62EC67F9C3A4A407FCB2A8C49031A8B3", - "6BFB914FD07EAE6B", - "E037830E8389F27B025A2D6527E79D01"}, - {"F7FB", - "91945D3F4DCBEE0BF45EF52255F095A4", - "BECAF043B0A23D843194BA972C66DEBD", - "FA3BFD4806EB53FA", - "19DD5C4C9331049D0BDAB0277408F67967E5"}, - {"1A47CB4933", - "01F74AD64077F2E704C0F60ADA3DD523", - "70C3DB4F0D26368400A10ED05D2BFF5E", - "234A3463C1264AC6", - "D851D5BAE03A59F238A23E39199DC9266626C40F80"}, - {"481C9E39B1", - "D07CF6CBB7F313BDDE66B727AFD3C5E8", - "8408DFFF3C1A2B1292DC199E46B7D617", - "33CCE2EABFF5A79D", - "632A9D131AD4C168A4225D8E1FF755939974A7BEDE"}, - {"40D0C07DA5E4", - "35B6D0580005BBC12B0587124557D2C2", - "FDB6B06676EEDC5C61D74276E1F8E816", - "AEB96EAEBE2970E9", - "071DFE16C675CB0677E536F73AFE6A14B74EE49844DD"}, - {"4DE3B35C3FC039245BD1FB7D", - "BD8E6E11475E60B268784C38C62FEB22", - "6EAC5C93072D8E8513F750935E46DA1B", - "D4482D1CA78DCE0F", - "835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F"}, - {"8B0A79306C9CE7ED99DAE4F87F8DD61636", - "7C77D6E813BED5AC98BAA417477A2E7D", - "1A8C98DCD73D38393B2BF1569DEEFC19", - "65D2017990D62528", - "02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2"}, - {"1BDA122BCE8A8DBAF1877D962B8592DD2D56", - "5FFF20CAFAB119CA2FC73549E20F5B0D", - "DDE59B97D722156D4D9AFF2BC7559826", - "54B9F04E6A09189A", - "2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A"}, - {"6CF36720872B8513F6EAB1A8A44438D5EF11", - "A4A4782BCFFD3EC5E7EF6D8C34A56123", - "B781FCF2F75FA5A8DE97A9CA48E522EC", - "899A175897561D7E", - "0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700"}, - {"CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7", - "8395FCF1E95BEBD697BD010BC766AAC3", - "22E7ADD93CFC6393C57EC0B3C17D6B44", - "126735FCC320D25A", - "CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E"}, -} diff --git a/vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go b/vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go deleted file mode 100644 index 4eb19f28..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go +++ /dev/null @@ -1,131 +0,0 @@ -// These vectors include key length in {128, 192, 256}, tag size 128, and -// random nonce, header, and plaintext lengths. - -// This file was automatically generated. - -package eax - -var randomVectors = []struct { - key, nonce, header, plaintext, ciphertext string -}{ - {"DFDE093F36B0356E5A81F609786982E3", - "1D8AC604419001816905BA72B14CED7E", - "152A1517A998D7A24163FCDD146DE81AC347C8B97088F502093C1ABB8F6E33D9A219C34D7603A18B1F5ABE02E56661B7D7F67E81EC08C1302EF38D80A859486D450E94A4F26AD9E68EEBBC0C857A0FC5CF9E641D63D565A7E361BC8908F5A8DC8FD6", - "1C8EAAB71077FE18B39730A3156ADE29C5EE824C7EE86ED2A253B775603FB237116E654F6FEC588DD27F523A0E01246FE73FE348491F2A8E9ABC6CA58D663F71CDBCF4AD798BE46C42AE6EE8B599DB44A1A48D7BBBBA0F7D2750181E1C5E66967F7D57CBD30AFBDA5727", - "79E7E150934BBEBF7013F61C60462A14D8B15AF7A248AFB8A344EF021C1500E16666891D6E973D8BB56B71A371F12CA34660C4410C016982B20F547E3762A58B7BF4F20236CADCF559E2BE7D783B13723B2741FC7CDC8997D839E39A3DDD2BADB96743DD7049F1BDB0516A262869915B3F70498AFB7B191BF960"}, - {"F10619EF02E5D94D7550EB84ED364A21", - "8DC0D4F2F745BBAE835CC5574B942D20", - "FE561358F2E8DF7E1024FF1AE9A8D36EBD01352214505CB99D644777A8A1F6027FA2BDBFC529A9B91136D5F2416CFC5F0F4EC3A1AFD32BDDA23CA504C5A5CB451785FABF4DFE4CD50D817491991A60615B30286361C100A95D1712F2A45F8E374461F4CA2B", - "D7B5A971FC219631D30EFC3664AE3127D9CF3097DAD9C24AC7905D15E8D9B25B026B31D68CAE00975CDB81EB1FD96FD5E1A12E2BB83FA25F1B1D91363457657FC03875C27F2946C5", - "2F336ED42D3CC38FC61660C4CD60BA4BD438B05F5965D8B7B399D2E7167F5D34F792D318F94DB15D67463AC449E13D568CC09BFCE32A35EE3EE96A041927680AE329811811E27F2D1E8E657707AF99BA96D13A478D695D59"}, - {"429F514EFC64D98A698A9247274CFF45", - "976AA5EB072F912D126ACEBC954FEC38", - "A71D89DC5B6CEDBB7451A27C3C2CAE09126DB4C421", - "5632FE62AB1DC549D54D3BC3FC868ACCEDEFD9ECF5E9F8", - "848AE4306CA8C7F416F8707625B7F55881C0AB430353A5C967CDA2DA787F581A70E34DBEBB2385"}, - {"398138F309085F47F8457CDF53895A63", - "F8A8A7F2D28E5FFF7BBC2F24353F7A36", - "5D633C21BA7764B8855CAB586F3746E236AD486039C83C6B56EFA9C651D38A41D6B20DAEE3418BFEA44B8BD6", - "A3BBAA91920AF5E10659818B1B3B300AC79BFC129C8329E75251F73A66D3AE0128EB91D5031E0A65C329DB7D1E9C0493E268", - "D078097267606E5FB07CFB7E2B4B718172A82C6A4CEE65D549A4DFB9838003BD2FBF64A7A66988AC1A632FD88F9E9FBB57C5A78AD2E086EACBA3DB68511D81C2970A"}, - {"7A4151EBD3901B42CBA45DAFB2E931BA", - "0FC88ACEE74DD538040321C330974EB8", - "250464FB04733BAB934C59E6AD2D6AE8D662CBCFEFBE61E5A308D4211E58C4C25935B72C69107722E946BFCBF416796600542D76AEB73F2B25BF53BAF97BDEB36ED3A7A51C31E7F170EB897457E7C17571D1BA0A908954E9", - "88C41F3EBEC23FAB8A362D969CAC810FAD4F7CA6A7F7D0D44F060F92E37E1183768DD4A8C733F71C96058D362A39876D183B86C103DE", - "74A25B2182C51096D48A870D80F18E1CE15867778E34FCBA6BD7BFB3739FDCD42AD0F2D9F4EBA29085285C6048C15BCE5E5166F1F962D3337AA88E6062F05523029D0A7F0BF9"}, - {"BFB147E1CD5459424F8C0271FC0E0DC5", - "EABCC126442BF373969EA3015988CC45", - "4C0880E1D71AA2C7", - "BE1B5EC78FBF73E7A6682B21BA7E0E5D2D1C7ABE", - "5660D7C1380E2F306895B1402CB2D6C37876504276B414D120F4CF92FDDDBB293A238EA0"}, - {"595DD6F52D18BC2CA8EB4EDAA18D9FA3", - "0F84B5D36CF4BC3B863313AF3B4D2E97", - "30AE6CC5F99580F12A779D98BD379A60948020C0B6FBD5746B30BA3A15C6CD33DAF376C70A9F15B6C0EB410A93161F7958AE23", - "8EF3687A1642B070970B0B91462229D1D76ABC154D18211F7152AA9FF368", - "317C1DDB11417E5A9CC4DDE7FDFF6659A5AC4B31DE025212580A05CDAC6024D3E4AE7C2966E52B9129E9ECDBED86"}, - {"44E6F2DC8FDC778AD007137D11410F50", - "270A237AD977F7187AA6C158A0BAB24F", - "509B0F0EB12E2AA5C5BA2DE553C07FAF4CE0C9E926531AA709A3D6224FCB783ACCF1559E10B1123EBB7D52E8AB54E6B5352A9ED0D04124BF0E9D9BACFD7E32B817B2E625F5EE94A64EDE9E470DE7FE6886C19B294F9F828209FE257A78", - "8B3D7815DF25618A5D0C55A601711881483878F113A12EC36CF64900549A3199555528559DC118F789788A55FAFD944E6E99A9CA3F72F238CD3F4D88223F7A745992B3FAED1848", - "1CC00D79F7AD82FDA71B58D286E5F34D0CC4CEF30704E771CC1E50746BDF83E182B078DB27149A42BAE619DF0F85B0B1090AD55D3B4471B0D6F6ECCD09C8F876B30081F0E7537A9624F8AAF29DA85E324122EFB4D68A56"}, - {"BB7BC352A03044B4428D8DBB4B0701FDEC4649FD17B81452", - "8B4BBE26CCD9859DCD84884159D6B0A4", - "2212BEB0E78E0F044A86944CF33C8D5C80D9DBE1034BF3BCF73611835C7D3A52F5BD2D81B68FD681B68540A496EE5DA16FD8AC8824E60E1EC2042BE28FB0BFAD4E4B03596446BDD8C37D936D9B3D5295BE19F19CF5ACE1D33A46C952CE4DE5C12F92C1DD051E04AEED", - "9037234CC44FFF828FABED3A7084AF40FA7ABFF8E0C0EFB57A1CC361E18FC4FAC1AB54F3ABFE9FF77263ACE16C3A", - "A9391B805CCD956081E0B63D282BEA46E7025126F1C1631239C33E92AA6F92CD56E5A4C56F00FF9658E93D48AF4EF0EF81628E34AD4DB0CDAEDCD2A17EE7"}, - {"99C0AD703196D2F60A74E6B378B838B31F82EA861F06FC4E", - "92745C018AA708ECFEB1667E9F3F1B01", - "828C69F376C0C0EC651C67749C69577D589EE39E51404D80EBF70C8660A8F5FD375473F4A7C611D59CB546A605D67446CE2AA844135FCD78BB5FBC90222A00D42920BB1D7EEDFB0C4672554F583EF23184F89063CDECBE482367B5F9AF3ACBC3AF61392BD94CBCD9B64677", - "A879214658FD0A5B0E09836639BF82E05EC7A5EF71D4701934BDA228435C68AC3D5CEB54997878B06A655EEACEFB1345C15867E7FE6C6423660C8B88DF128EBD6BCD85118DBAE16E9252FFB204324E5C8F38CA97759BDBF3CB0083", - "51FE87996F194A2585E438B023B345439EA60D1AEBED4650CDAF48A4D4EEC4FC77DC71CC4B09D3BEEF8B7B7AF716CE2B4EFFB3AC9E6323C18AC35E0AA6E2BBBC8889490EB6226C896B0D105EAB42BFE7053CCF00ED66BA94C1BA09A792AA873F0C3B26C5C5F9A936E57B25"}, - {"7086816D00D648FB8304AA8C9E552E1B69A9955FB59B25D1", - "0F45CF7F0BF31CCEB85D9DA10F4D749F", - "93F27C60A417D9F0669E86ACC784FC8917B502DAF30A6338F11B30B94D74FEFE2F8BE1BBE2EAD10FAB7EED3C6F72B7C3ECEE1937C32ED4970A6404E139209C05", - "877F046601F3CBE4FB1491943FA29487E738F94B99AF206262A1D6FF856C9AA0B8D4D08A54370C98F8E88FA3DCC2B14C1F76D71B2A4C7963AEE8AF960464C5BEC8357AD00DC8", - "FE96906B895CE6A8E72BC72344E2C8BB3C63113D70EAFA26C299BAFE77A8A6568172EB447FB3E86648A0AF3512DEB1AAC0819F3EC553903BF28A9FB0F43411237A774BF9EE03E445D280FBB9CD12B9BAAB6EF5E52691"}, - {"062F65A896D5BF1401BADFF70E91B458E1F9BD4888CB2E4D", - "5B11EA1D6008EBB41CF892FCA5B943D1", - "BAF4FF5C8242", - "A8870E091238355984EB2F7D61A865B9170F440BFF999A5993DD41A10F4440D21FF948DDA2BF663B2E03AC3324492DC5E40262ECC6A65C07672353BE23E7FB3A9D79FF6AA38D97960905A38DECC312CB6A59E5467ECF06C311CD43ADC0B543EDF34FE8BE611F176460D5627CA51F8F8D9FED71F55C", - "B10E127A632172CF8AA7539B140D2C9C2590E6F28C3CB892FC498FCE56A34F732FBFF32E79C7B9747D9094E8635A0C084D6F0247F9768FB5FF83493799A9BEC6C39572120C40E9292C8C947AE8573462A9108C36D9D7112E6995AE5867E6C8BB387D1C5D4BEF524F391B9FD9F0A3B4BFA079E915BCD920185CFD38D114C558928BD7D47877"}, - {"38A8E45D6D705A11AF58AED5A1344896998EACF359F2E26A", - "FD82B5B31804FF47D44199B533D0CF84", - "DE454D4E62FE879F2050EE3E25853623D3E9AC52EEC1A1779A48CFAF5ECA0BFDE44749391866D1", - "B804", - "164BB965C05EBE0931A1A63293EDF9C38C27"}, - {"34C33C97C6D7A0850DA94D78A58DC61EC717CD7574833068", - "343BE00DA9483F05C14F2E9EB8EA6AE8", - "78312A43EFDE3CAE34A65796FF059A3FE15304EEA5CF1D9306949FE5BF3349D4977D4EBE76C040FE894C5949E4E4D6681153DA87FB9AC5062063CA2EA183566343362370944CE0362D25FC195E124FD60E8682E665D13F2229DDA3E4B2CB1DCA", - "CC11BB284B1153578E4A5ED9D937B869DAF00F5B1960C23455CA9CC43F486A3BE0B66254F1041F04FDF459C8640465B6E1D2CF899A381451E8E7FCB50CF87823BE77E24B132BBEEDC72E53369B275E1D8F49ECE59F4F215230AC4FE133FC80E4F634EE80BA4682B62C86", - "E7F703DC31A95E3A4919FF957836CB76C063D81702AEA4703E1C2BF30831E58C4609D626EC6810E12EAA5B930F049FF9EFC22C3E3F1EBD4A1FB285CB02A1AC5AD46B425199FC0A85670A5C4E3DAA9636C8F64C199F42F18AAC8EA7457FD377F322DD7752D7D01B946C8F0A97E6113F0D50106F319AFD291AAACE"}, - {"C6ECF7F053573E403E61B83052A343D93CBCC179D1E835BE", - "E280E13D7367042E3AA09A80111B6184", - "21486C9D7A9647", - "5F2639AFA6F17931853791CD8C92382BBB677FD72D0AB1A080D0E49BFAA21810E963E4FACD422E92F65CBFAD5884A60CD94740DF31AF02F95AA57DA0C4401B0ED906", - "5C51DB20755302070C45F52E50128A67C8B2E4ED0EACB7E29998CCE2E8C289DD5655913EC1A51CC3AABE5CDC2402B2BE7D6D4BF6945F266FBD70BA9F37109067157AE7530678B45F64475D4EBFCB5FFF46A5"}, - {"5EC6CF7401BC57B18EF154E8C38ACCA8959E57D2F3975FF5", - "656B41CB3F9CF8C08BAD7EBFC80BD225", - "6B817C2906E2AF425861A7EF59BA5801F143EE2A139EE72697CDE168B4", - "2C0E1DDC9B1E5389BA63845B18B1F8A1DB062037151BCC56EF7C21C0BB4DAE366636BBA975685D7CC5A94AFBE89C769016388C56FB7B57CE750A12B718A8BDCF70E80E8659A8330EFC8F86640F21735E8C80E23FE43ABF23507CE3F964AE4EC99D", - "ED780CF911E6D1AA8C979B889B0B9DC1ABE261832980BDBFB576901D9EF5AB8048998E31A15BE54B3E5845A4D136AD24D0BDA1C3006168DF2F8AC06729CB0818867398150020131D8F04EDF1923758C9EABB5F735DE5EA1758D4BC0ACFCA98AFD202E9839B8720253693B874C65586C6F0"}, - {"C92F678EB2208662F5BCF3403EC05F5961E957908A3E79421E1D25FC19054153", - "DA0F3A40983D92F2D4C01FED33C7A192", - "2B6E9D26DB406A0FAB47608657AA10EFC2B4AA5F459B29FF85AC9A40BFFE7AEB04F77E9A11FAAA116D7F6D4DA417671A9AB02C588E0EF59CB1BFB4B1CC931B63A3B3A159FCEC97A04D1E6F0C7E6A9CEF6B0ABB04758A69F1FE754DF4C2610E8C46B6CF413BDB31351D55BEDCB7B4A13A1C98E10984475E0F2F957853", - "F37326A80E08", - "83519E53E321D334F7C10B568183775C0E9AAE55F806"}, - {"6847E0491BE57E72995D186D50094B0B3593957A5146798FCE68B287B2FB37B5", - "3EE1182AEBB19A02B128F28E1D5F7F99", - "D9F35ABB16D776CE", - "DB7566ED8EA95BDF837F23DB277BAFBC5E70D1105ADFD0D9EF15475051B1EF94709C67DCA9F8D5", - "2CDCED0C9EBD6E2A508822A685F7DCD1CDD99E7A5FCA786C234E7F7F1D27EC49751AD5DCFA30C5EDA87C43CAE3B919B6BBCFE34C8EDA59"}, - {"82B019673642C08388D3E42075A4D5D587558C229E4AB8F660E37650C4C41A0A", - "336F5D681E0410FAE7B607246092C6DC", - "D430CBD8FE435B64214E9E9CDC5DE99D31CFCFB8C10AA0587A49DF276611", - "998404153AD77003E1737EDE93ED79859EE6DCCA93CB40C4363AA817ABF2DBBD46E42A14A7183B6CC01E12A577888141363D0AE011EB6E8D28C0B235", - "9BEF69EEB60BD3D6065707B7557F25292A8872857CFBD24F2F3C088E4450995333088DA50FD9121221C504DF1D0CD5EFE6A12666C5D5BB12282CF4C19906E9CFAB97E9BDF7F49DC17CFC384B"}, - {"747B2E269B1859F0622C15C8BAD6A725028B1F94B8DB7326948D1E6ED663A8BC", - "AB91F7245DDCE3F1C747872D47BE0A8A", - "3B03F786EF1DDD76E1D42646DA4CD2A5165DC5383CE86D1A0B5F13F910DC278A4E451EE0192CBA178E13B3BA27FDC7840DF73D2E104B", - "6B803F4701114F3E5FE21718845F8416F70F626303F545BE197189E0A2BA396F37CE06D389EB2658BC7D56D67868708F6D0D32", - "1570DDB0BCE75AA25D1957A287A2C36B1A5F2270186DA81BA6112B7F43B0F3D1D0ED072591DCF1F1C99BBB25621FC39B896FF9BD9413A2845363A9DCD310C32CF98E57"}, - {"02E59853FB29AEDA0FE1C5F19180AD99A12FF2F144670BB2B8BADF09AD812E0A", - "C691294EF67CD04D1B9242AF83DD1421", - "879334DAE3", - "1E17F46A98FEF5CBB40759D95354", - "FED8C3FF27DDF6313AED444A2985B36CBA268AAD6AAC563C0BA28F6DB5DB"}, - {"F6C1FB9B4188F2288FF03BD716023198C3582CF2A037FC2F29760916C2B7FCDB", - "4228DA0678CA3534588859E77DFF014C", - "D8153CAF35539A61DD8D05B3C9B44F01E564FB9348BCD09A1C23B84195171308861058F0A3CD2A55B912A3AAEE06FF4D356C77275828F2157C2FC7C115DA39E443210CCC56BEDB0CC99BBFB227ABD5CC454F4E7F547C7378A659EEB6A7E809101A84F866503CB18D4484E1FA09B3EC7FC75EB2E35270800AA7", - "23B660A779AD285704B12EC1C580387A47BEC7B00D452C6570", - "5AA642BBABA8E49849002A2FAF31DB8FC7773EFDD656E469CEC19B3206D4174C9A263D0A05484261F6"}, - {"8FF6086F1FADB9A3FBE245EAC52640C43B39D43F89526BB5A6EBA47710931446", - "943188480C99437495958B0AE4831AA9", - "AD5CD0BDA426F6EBA23C8EB23DC73FF9FEC173355EDBD6C9344C4C4383F211888F7CE6B29899A6801DF6B38651A7C77150941A", - "80CD5EA8D7F81DDF5070B934937912E8F541A5301877528EB41AB60C020968D459960ED8FB73083329841A", - "ABAE8EB7F36FCA2362551E72DAC890BA1BB6794797E0FC3B67426EC9372726ED4725D379EA0AC9147E48DCD0005C502863C2C5358A38817C8264B5"}, - {"A083B54E6B1FE01B65D42FCD248F97BB477A41462BBFE6FD591006C022C8FD84", - "B0490F5BD68A52459556B3749ACDF40E", - "8892E047DA5CFBBDF7F3CFCBD1BD21C6D4C80774B1826999234394BD3E513CC7C222BB40E1E3140A152F19B3802F0D036C24A590512AD0E8", - "D7B15752789DC94ED0F36778A5C7BBB207BEC32BAC66E702B39966F06E381E090C6757653C3D26A81EC6AD6C364D66867A334C91BB0B8A8A4B6EACDF0783D09010AEBA2DD2062308FE99CC1F", - "C071280A732ADC93DF272BF1E613B2BB7D46FC6665EF2DC1671F3E211D6BDE1D6ADDD28DF3AA2E47053FC8BB8AE9271EC8BC8B2CFFA320D225B451685B6D23ACEFDD241FE284F8ADC8DB07F456985B14330BBB66E0FB212213E05B3E"}, -} diff --git a/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go b/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go deleted file mode 100644 index d558b9bd..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 2019 ProtonTech AG -// This file contains necessary tools for the aex and ocb packages. -// -// These functions SHOULD NOT be used elsewhere, since they are optimized for -// specific input nature in the EAX and OCB modes of operation. - -package byteutil - -// GfnDouble computes 2 * input in the field of 2^n elements. -// The irreducible polynomial in the finite field for n=128 is -// x^128 + x^7 + x^2 + x + 1 (equals 0x87) -// Constant-time execution in order to avoid side-channel attacks -func GfnDouble(input []byte) []byte { - if len(input) != 16 { - panic("Doubling in GFn only implemented for n = 128") - } - // If the first bit is zero, return 2L = L << 1 - // Else return (L << 1) xor 0^120 10000111 - shifted := ShiftBytesLeft(input) - shifted[15] ^= ((input[0] >> 7) * 0x87) - return shifted -} - -// ShiftBytesLeft outputs the byte array corresponding to x << 1 in binary. -func ShiftBytesLeft(x []byte) []byte { - l := len(x) - dst := make([]byte, l) - for i := 0; i < l-1; i++ { - dst[i] = (x[i] << 1) | (x[i+1] >> 7) - } - dst[l-1] = x[l-1] << 1 - return dst -} - -// ShiftNBytesLeft puts in dst the byte array corresponding to x << n in binary. -func ShiftNBytesLeft(dst, x []byte, n int) { - // Erase first n / 8 bytes - copy(dst, x[n/8:]) - - // Shift the remaining n % 8 bits - bits := uint(n % 8) - l := len(dst) - for i := 0; i < l-1; i++ { - dst[i] = (dst[i] << bits) | (dst[i+1] >> uint(8-bits)) - } - dst[l-1] = dst[l-1] << bits - - // Append trailing zeroes - dst = append(dst, make([]byte, n/8)...) -} - -// XorBytesMut replaces X with X XOR Y. len(X) must be >= len(Y). -func XorBytesMut(X, Y []byte) { - for i := 0; i < len(Y); i++ { - X[i] ^= Y[i] - } -} - -// XorBytes puts X XOR Y into Z. len(Z) and len(X) must be >= len(Y). -func XorBytes(Z, X, Y []byte) { - for i := 0; i < len(Y); i++ { - Z[i] = X[i] ^ Y[i] - } -} - -// RightXor XORs smaller input (assumed Y) at the right of the larger input (assumed X) -func RightXor(X, Y []byte) []byte { - offset := len(X) - len(Y) - xored := make([]byte, len(X)) - copy(xored, X) - for i := 0; i < len(Y); i++ { - xored[offset+i] ^= Y[i] - } - return xored -} - -// SliceForAppend takes a slice and a requested number of bytes. It returns a -// slice with the contents of the given slice followed by that many bytes and a -// second slice that aliases into it and contains only the extra bytes. If the -// original slice has sufficient capacity then no allocation is performed. -func SliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go b/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go deleted file mode 100644 index 24f89301..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (C) 2019 ProtonTech AG - -// Package ocb provides an implementation of the OCB (offset codebook) mode of -// operation, as described in RFC-7253 of the IRTF and in Rogaway, Bellare, -// Black and Krovetz - OCB: A BLOCK-CIPHER MODE OF OPERATION FOR EFFICIENT -// AUTHENTICATED ENCRYPTION (2003). -// Security considerations (from RFC-7253): A private key MUST NOT be used to -// encrypt more than 2^48 blocks. Tag length should be at least 12 bytes (a -// brute-force forging adversary succeeds after 2^{tag length} attempts). A -// single key SHOULD NOT be used to decrypt ciphertext with different tag -// lengths. Nonces need not be secret, but MUST NOT be reused. -// This package only supports underlying block ciphers with 128-bit blocks, -// such as AES-{128, 192, 256}, but may be extended to other sizes. -package ocb - -import ( - "bytes" - "crypto/cipher" - "crypto/subtle" - "errors" - "math/bits" - - "github.com/ProtonMail/go-crypto/internal/byteutil" -) - -type ocb struct { - block cipher.Block - tagSize int - nonceSize int - mask mask - // Optimized en/decrypt: For each nonce N used to en/decrypt, the 'Ktop' - // internal variable can be reused for en/decrypting with nonces sharing - // all but the last 6 bits with N. The prefix of the first nonce used to - // compute the new Ktop, and the Ktop value itself, are stored in - // reusableKtop. If using incremental nonces, this saves one block cipher - // call every 63 out of 64 OCB encryptions, and stores one nonce and one - // output of the block cipher in memory only. - reusableKtop reusableKtop -} - -type mask struct { - // L_*, L_$, (L_i)_{i ∈ N} - lAst []byte - lDol []byte - L [][]byte -} - -type reusableKtop struct { - noncePrefix []byte - Ktop []byte -} - -const ( - defaultTagSize = 16 - defaultNonceSize = 15 -) - -const ( - enc = iota - dec -) - -func (o *ocb) NonceSize() int { - return o.nonceSize -} - -func (o *ocb) Overhead() int { - return o.tagSize -} - -// NewOCB returns an OCB instance with the given block cipher and default -// tag and nonce sizes. -func NewOCB(block cipher.Block) (cipher.AEAD, error) { - return NewOCBWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize) -} - -// NewOCBWithNonceAndTagSize returns an OCB instance with the given block -// cipher, nonce length, and tag length. Panics on zero nonceSize and -// exceedingly long tag size. -// -// It is recommended to use at least 12 bytes as tag length. -func NewOCBWithNonceAndTagSize( - block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) { - if block.BlockSize() != 16 { - return nil, ocbError("Block cipher must have 128-bit blocks") - } - if nonceSize < 1 { - return nil, ocbError("Incorrect nonce length") - } - if nonceSize >= block.BlockSize() { - return nil, ocbError("Nonce length exceeds blocksize - 1") - } - if tagSize > block.BlockSize() { - return nil, ocbError("Custom tag length exceeds blocksize") - } - return &ocb{ - block: block, - tagSize: tagSize, - nonceSize: nonceSize, - mask: initializeMaskTable(block), - reusableKtop: reusableKtop{ - noncePrefix: nil, - Ktop: nil, - }, - }, nil -} - -func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte { - if len(nonce) > o.nonceSize { - panic("crypto/ocb: Incorrect nonce length given to OCB") - } - sep := len(plaintext) - ret, out := byteutil.SliceForAppend(dst, sep+o.tagSize) - tag := o.crypt(enc, out[:sep], nonce, adata, plaintext) - copy(out[sep:], tag) - return ret -} - -func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { - if len(nonce) > o.nonceSize { - panic("Nonce too long for this instance") - } - if len(ciphertext) < o.tagSize { - return nil, ocbError("Ciphertext shorter than tag length") - } - sep := len(ciphertext) - o.tagSize - ret, out := byteutil.SliceForAppend(dst, sep) - ciphertextData := ciphertext[:sep] - tag := o.crypt(dec, out, nonce, adata, ciphertextData) - if subtle.ConstantTimeCompare(tag, ciphertext[sep:]) == 1 { - return ret, nil - } - for i := range out { - out[i] = 0 - } - return nil, ocbError("Tag authentication failed") -} - -// On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt) -// function. It writes the resulting plain/ciphertext into Y and returns -// the tag. -func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte { - // - // Consider X as a sequence of 128-bit blocks - // - // Note: For encryption (resp. decryption), X is the plaintext (resp., the - // ciphertext without the tag). - blockSize := o.block.BlockSize() - - // - // Nonce-dependent and per-encryption variables - // - // Zero out the last 6 bits of the nonce into truncatedNonce to see if Ktop - // is already computed. - truncatedNonce := make([]byte, len(nonce)) - copy(truncatedNonce, nonce) - truncatedNonce[len(truncatedNonce)-1] &= 192 - var Ktop []byte - if bytes.Equal(truncatedNonce, o.reusableKtop.noncePrefix) { - Ktop = o.reusableKtop.Ktop - } else { - // Nonce = num2str(TAGLEN mod 128, 7) || zeros(120 - bitlen(N)) || 1 || N - paddedNonce := append(make([]byte, blockSize-1-len(nonce)), 1) - paddedNonce = append(paddedNonce, truncatedNonce...) - paddedNonce[0] |= byte(((8 * o.tagSize) % (8 * blockSize)) << 1) - // Last 6 bits of paddedNonce are already zero. Encrypt into Ktop - paddedNonce[blockSize-1] &= 192 - Ktop = paddedNonce - o.block.Encrypt(Ktop, Ktop) - o.reusableKtop.noncePrefix = truncatedNonce - o.reusableKtop.Ktop = Ktop - } - - // Stretch = Ktop || ((lower half of Ktop) XOR (lower half of Ktop << 8)) - xorHalves := make([]byte, blockSize/2) - byteutil.XorBytes(xorHalves, Ktop[:blockSize/2], Ktop[1:1+blockSize/2]) - stretch := append(Ktop, xorHalves...) - bottom := int(nonce[len(nonce)-1] & 63) - offset := make([]byte, len(stretch)) - byteutil.ShiftNBytesLeft(offset, stretch, bottom) - offset = offset[:blockSize] - - // - // Process any whole blocks - // - // Note: For encryption Y is ciphertext || tag, for decryption Y is - // plaintext || tag. - checksum := make([]byte, blockSize) - m := len(X) / blockSize - for i := 0; i < m; i++ { - index := bits.TrailingZeros(uint(i + 1)) - if len(o.mask.L)-1 < index { - o.mask.extendTable(index) - } - byteutil.XorBytesMut(offset, o.mask.L[bits.TrailingZeros(uint(i+1))]) - blockX := X[i*blockSize : (i+1)*blockSize] - blockY := Y[i*blockSize : (i+1)*blockSize] - switch instruction { - case enc: - byteutil.XorBytesMut(checksum, blockX) - byteutil.XorBytes(blockY, blockX, offset) - o.block.Encrypt(blockY, blockY) - byteutil.XorBytesMut(blockY, offset) - case dec: - byteutil.XorBytes(blockY, blockX, offset) - o.block.Decrypt(blockY, blockY) - byteutil.XorBytesMut(blockY, offset) - byteutil.XorBytesMut(checksum, blockY) - } - } - // - // Process any final partial block and compute raw tag - // - tag := make([]byte, blockSize) - if len(X)%blockSize != 0 { - byteutil.XorBytesMut(offset, o.mask.lAst) - pad := make([]byte, blockSize) - o.block.Encrypt(pad, offset) - chunkX := X[blockSize*m:] - chunkY := Y[blockSize*m : len(X)] - switch instruction { - case enc: - byteutil.XorBytesMut(checksum, chunkX) - checksum[len(chunkX)] ^= 128 - byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)]) - // P_* || bit(1) || zeroes(127) - len(P_*) - case dec: - byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)]) - // P_* || bit(1) || zeroes(127) - len(P_*) - byteutil.XorBytesMut(checksum, chunkY) - checksum[len(chunkY)] ^= 128 - } - } - byteutil.XorBytes(tag, checksum, offset) - byteutil.XorBytesMut(tag, o.mask.lDol) - o.block.Encrypt(tag, tag) - byteutil.XorBytesMut(tag, o.hash(adata)) - return tag[:o.tagSize] -} - -// This hash function is used to compute the tag. Per design, on empty input it -// returns a slice of zeros, of the same length as the underlying block cipher -// block size. -func (o *ocb) hash(adata []byte) []byte { - // - // Consider A as a sequence of 128-bit blocks - // - A := make([]byte, len(adata)) - copy(A, adata) - blockSize := o.block.BlockSize() - - // - // Process any whole blocks - // - sum := make([]byte, blockSize) - offset := make([]byte, blockSize) - m := len(A) / blockSize - for i := 0; i < m; i++ { - chunk := A[blockSize*i : blockSize*(i+1)] - index := bits.TrailingZeros(uint(i + 1)) - // If the mask table is too short - if len(o.mask.L)-1 < index { - o.mask.extendTable(index) - } - byteutil.XorBytesMut(offset, o.mask.L[index]) - byteutil.XorBytesMut(chunk, offset) - o.block.Encrypt(chunk, chunk) - byteutil.XorBytesMut(sum, chunk) - } - - // - // Process any final partial block; compute final hash value - // - if len(A)%blockSize != 0 { - byteutil.XorBytesMut(offset, o.mask.lAst) - // Pad block with 1 || 0 ^ 127 - bitlength(a) - ending := make([]byte, blockSize-len(A)%blockSize) - ending[0] = 0x80 - encrypted := append(A[blockSize*m:], ending...) - byteutil.XorBytesMut(encrypted, offset) - o.block.Encrypt(encrypted, encrypted) - byteutil.XorBytesMut(sum, encrypted) - } - return sum -} - -func initializeMaskTable(block cipher.Block) mask { - // - // Key-dependent variables - // - lAst := make([]byte, block.BlockSize()) - block.Encrypt(lAst, lAst) - lDol := byteutil.GfnDouble(lAst) - L := make([][]byte, 1) - L[0] = byteutil.GfnDouble(lDol) - - return mask{ - lAst: lAst, - lDol: lDol, - L: L, - } -} - -// Extends the L array of mask m up to L[limit], with L[i] = GfnDouble(L[i-1]) -func (m *mask) extendTable(limit int) { - for i := len(m.L); i <= limit; i++ { - m.L = append(m.L, byteutil.GfnDouble(m.L[i-1])) - } -} - -func ocbError(err string) error { - return errors.New("crypto/ocb: " + err) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go b/vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go deleted file mode 100644 index 0efaf344..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go +++ /dev/null @@ -1,136 +0,0 @@ -// In the test vectors provided by RFC 7253, the "bottom" -// internal variable, which defines "offset" for the first time, does not -// exceed 15. However, it can attain values up to 63. - -// These vectors include key length in {128, 192, 256}, tag size 128, and -// random nonce, header, and plaintext lengths. - -// This file was automatically generated. - -package ocb - -var randomVectors = []struct { - key, nonce, header, plaintext, ciphertext string -}{ - - {"9438C5D599308EAF13F800D2D31EA7F0", - "C38EE4801BEBFFA1CD8635BE", - "0E507B7DADD8A98CDFE272D3CB6B3E8332B56AE583FB049C0874D4200BED16BD1A044182434E9DA0E841F182DFD5B3016B34641CED0784F1745F63AB3D0DA22D3351C9EF9A658B8081E24498EBF61FCE40DA6D8E184536", - "962D227786FB8913A8BAD5DC3250", - "EEDEF5FFA5986D1E3BF86DDD33EF9ADC79DCA06E215FA772CCBA814F63AD"}, - {"BA7DE631C7D6712167C6724F5B9A2B1D", - "35263EBDA05765DC0E71F1F5", - "0103257B4224507C0242FEFE821EA7FA42E0A82863E5F8B68F7D881B4B44FA428A2B6B21D2F591260802D8AB6D83", - "9D6D1FC93AE8A64E7889B7B2E3521EFA9B920A8DDB692E6F833DDC4A38AFA535E5E2A3ED82CB7E26404AB86C54D01C4668F28398C2DF33D5D561CBA1C8DCFA7A912F5048E545B59483C0E3221F54B14DAA2E4EB657B3BEF9554F34CAD69B2724AE962D3D8A", - "E93852D1985C5E775655E937FA79CE5BF28A585F2AF53A5018853B9634BE3C84499AC0081918FDCE0624494D60E25F76ACD6853AC7576E3C350F332249BFCABD4E73CEABC36BE4EDDA40914E598AE74174A0D7442149B26990899491BDDFE8FC54D6C18E83AE9E9A6FFBF5D376565633862EEAD88D"}, - {"2E74B25289F6FD3E578C24866E9C72A5", - "FD912F15025AF8414642BA1D1D", - "FB5FB8C26F365EEDAB5FE260C6E3CCD27806729C8335F146063A7F9EA93290E56CF84576EB446350D22AD730547C267B1F0BBB97EB34E1E2C41A", - "6C092EBF78F76EE8C1C6E592277D9545BA16EDB67BC7D8480B9827702DC2F8A129E2B08A2CE710CA7E1DA45CE162BB6CD4B512E632116E2211D3C90871EFB06B8D4B902681C7FB", - "6AC0A77F26531BF4F354A1737F99E49BE32ECD909A7A71AD69352906F54B08A9CE9B8CA5D724CBFFC5673437F23F630697F3B84117A1431D6FA8CC13A974FB4AD360300522E09511B99E71065D5AC4BBCB1D791E864EF4"}, - {"E7EC507C802528F790AFF5303A017B17", - "4B97A7A568940A9E3CE7A99E93031E", - "28349BDC5A09390C480F9B8AA3EDEA3DDB8B9D64BCA322C570B8225DF0E31190DAB25A4014BA39519E02ABFB12B89AA28BBFD29E486E7FB28734258C817B63CED9912DBAFEBB93E2798AB2890DE3B0ACFCFF906AB15563EF7823CE83D27CDB251195E22BD1337BCBDE65E7C2C427321C463C2777BFE5AEAA", - "9455B3EA706B74", - "7F33BA3EA848D48A96B9530E26888F43EBD4463C9399B6"}, - {"6C928AA3224736F28EE7378DE0090191", - "8936138E2E4C6A13280017A1622D", - "6202717F2631565BDCDC57C6584543E72A7C8BD444D0D108ED35069819633C", - "DA0691439E5F035F3E455269D14FE5C201C8C9B0A3FE2D3F86BCC59387C868FE65733D388360B31E3CE28B4BF6A8BE636706B536D5720DB66B47CF1C7A5AFD6F61E0EF90F1726D6B0E169F9A768B2B7AE4EE00A17F630AC905FCAAA1B707FFF25B3A1AAE83B504837C64A5639B2A34002B300EC035C9B43654DA55", - "B8804D182AB0F0EEB464FA7BD1329AD6154F982013F3765FEDFE09E26DAC078C9C1439BFC1159D6C02A25E3FF83EF852570117B315852AD5EE20E0FA3AA0A626B0E43BC0CEA38B44579DD36803455FB46989B90E6D229F513FD727AF8372517E9488384C515D6067704119C931299A0982EDDFB9C2E86A90C450C077EB222511EC9CCABC9FCFDB19F70088"}, - {"ECEA315CA4B3F425B0C9957A17805EA4", - "664CDAE18403F4F9BA13015A44FC", - "642AFB090D6C6DB46783F08B01A3EF2A8FEB5736B531EAC226E7888FCC8505F396818F83105065FACB3267485B9E5E4A0261F621041C08FCCB2A809A49AB5252A91D0971BCC620B9D614BD77E57A0EED2FA5", - "6852C31F8083E20E364CEA21BB7854D67CEE812FE1C9ED2425C0932A90D3780728D1BB", - "2ECEF962A9695A463ADABB275BDA9FF8B2BA57AEC2F52EFFB700CD9271A74D2A011C24AEA946051BD6291776429B7E681BA33E"}, - {"4EE616C4A58AAA380878F71A373461F6", - "91B8C9C176D9C385E9C47E52", - "CDA440B7F9762C572A718AC754EDEECC119E5EE0CCB9FEA4FFB22EEE75087C032EBF3DA9CDD8A28CC010B99ED45143B41A4BA50EA2A005473F89639237838867A57F23B0F0ED3BF22490E4501DAC9C658A9B9F", - "D6E645FA9AE410D15B8123FD757FA356A8DBE9258DDB5BE88832E615910993F497EC", - "B70ED7BF959FB2AAED4F36174A2A99BFB16992C8CDF369C782C4DB9C73DE78C5DB8E0615F647243B97ACDB24503BC9CADC48"}, - {"DCD475773136C830D5E3D0C5FE05B7FF", - "BB8E1FBB483BE7616A922C4A", - "36FEF2E1CB29E76A6EA663FC3AF66ECD7404F466382F7B040AABED62293302B56E8783EF7EBC21B4A16C3E78A7483A0A403F253A2CDC5BBF79DC3DAE6C73F39A961D8FBBE8D41B", - "441E886EA38322B2437ECA7DEB5282518865A66780A454E510878E61BFEC3106A3CD93D2A02052E6F9E1832F9791053E3B76BF4C07EFDD6D4106E3027FABB752E60C1AA425416A87D53938163817A1051EBA1D1DEEB4B9B25C7E97368B52E5911A31810B0EC5AF547559B6142D9F4C4A6EF24A4CF75271BF9D48F62B", - "1BE4DD2F4E25A6512C2CC71D24BBB07368589A94C2714962CD0ACE5605688F06342587521E75F0ACAFFD86212FB5C34327D238DB36CF2B787794B9A4412E7CD1410EA5DDD2450C265F29CF96013CD213FD2880657694D718558964BC189B4A84AFCF47EB012935483052399DBA5B088B0A0477F20DFE0E85DCB735E21F22A439FB837DD365A93116D063E607"}, - {"3FBA2B3D30177FFE15C1C59ED2148BB2C091F5615FBA7C07", - "FACF804A4BEBF998505FF9DE", - "8213B9263B2971A5BDA18DBD02208EE1", - "15B323926993B326EA19F892D704439FC478828322AF72118748284A1FD8A6D814E641F70512FD706980337379F31DC63355974738D7FEA87AD2858C0C2EBBFBE74371C21450072373C7B651B334D7C4D43260B9D7CCD3AF9EDB", - "6D35DC1469B26E6AAB26272A41B46916397C24C485B61162E640A062D9275BC33DDCFD3D9E1A53B6C8F51AC89B66A41D59B3574197A40D9B6DCF8A4E2A001409C8112F16B9C389E0096179DB914E05D6D11ED0005AD17E1CE105A2F0BAB8F6B1540DEB968B7A5428FF44"}, - {"53B52B8D4D748BCDF1DDE68857832FA46227FA6E2F32EFA1", - "0B0EF53D4606B28D1398355F", - "F23882436349094AF98BCACA8218E81581A043B19009E28EFBF2DE37883E04864148CC01D240552CA8844EC1456F42034653067DA67E80F87105FD06E14FF771246C9612867BE4D215F6D761", - "F15030679BD4088D42CAC9BF2E9606EAD4798782FA3ED8C57EBE7F84A53236F51B25967C6489D0CD20C9EEA752F9BC", - "67B96E2D67C3729C96DAEAEDF821D61C17E648643A2134C5621FEC621186915AD80864BFD1EB5B238BF526A679385E012A457F583AFA78134242E9D9C1B4E4"}, - {"0272DD80F23399F49BFC320381A5CD8225867245A49A7D41", - "5C83F4896D0738E1366B1836", - "69B0337289B19F73A12BAEEA857CCAF396C11113715D9500CCCF48BA08CFF12BC8B4BADB3084E63B85719DB5058FA7C2C11DEB096D7943CFA7CAF5", - "C01AD10FC8B562CD17C7BC2FAB3E26CBDFF8D7F4DEA816794BBCC12336991712972F52816AABAB244EB43B0137E2BAC1DD413CE79531E78BEF782E6B439612BB3AEF154DE3502784F287958EBC159419F9EBA27916A28D6307324129F506B1DE80C1755A929F87", - "FEFE52DD7159C8DD6E8EC2D3D3C0F37AB6CB471A75A071D17EC4ACDD8F3AA4D7D4F7BB559F3C09099E3D9003E5E8AA1F556B79CECDE66F85B08FA5955E6976BF2695EA076388A62D2AD5BAB7CBF1A7F3F4C8D5CDF37CDE99BD3E30B685D9E5EEE48C7C89118EF4878EB89747F28271FA2CC45F8E9E7601"}, - {"3EEAED04A455D6E5E5AB53CFD5AFD2F2BC625C7BF4BE49A5", - "36B88F63ADBB5668588181D774", - "D367E3CB3703E762D23C6533188EF7028EFF9D935A3977150361997EC9DEAF1E4794BDE26AA8B53C124980B1362EC86FCDDFC7A90073171C1BAEE351A53234B86C66E8AB92FAE99EC6967A6D3428892D80", - "573454C719A9A55E04437BF7CBAAF27563CCCD92ADD5E515CD63305DFF0687E5EEF790C5DCA5C0033E9AB129505E2775438D92B38F08F3B0356BA142C6F694", - "E9F79A5B432D9E682C9AAA5661CFC2E49A0FCB81A431E54B42EB73DD3BED3F377FEC556ABA81624BA64A5D739AD41467460088F8D4F442180A9382CA635745473794C382FCDDC49BA4EB6D8A44AE3C"}, - {"B695C691538F8CBD60F039D0E28894E3693CC7C36D92D79D", - "BC099AEB637361BAC536B57618", - "BFFF1A65AE38D1DC142C71637319F5F6508E2CB33C9DCB94202B359ED5A5ED8042E7F4F09231D32A7242976677E6F4C549BF65FADC99E5AF43F7A46FD95E16C2", - "081DF3FD85B415D803F0BE5AC58CFF0023FDDED99788296C3731D8", - "E50C64E3614D94FE69C47092E46ACC9957C6FEA2CCBF96BC62FBABE7424753C75F9C147C42AE26FE171531"}, - {"C9ACBD2718F0689A1BE9802A551B6B8D9CF5614DAF5E65ED", - "B1B0AAF373B8B026EB80422051D8", - "6648C0E61AC733C76119D23FB24548D637751387AA2EAE9D80E912B7BD486CAAD9EAF4D7A5FE2B54AAD481E8EC94BB4D558000896E2010462B70C9FED1E7273080D1", - "189F591F6CB6D59AFEDD14C341741A8F1037DC0DF00FC57CE65C30F49E860255CEA5DC6019380CC0FE8880BC1A9E685F41C239C38F36E3F2A1388865C5C311059C0A", - "922A5E949B61D03BE34AB5F4E58607D4504EA14017BB363DAE3C873059EA7A1C77A746FB78981671D26C2CF6D9F24952D510044CE02A10177E9DB42D0145211DFE6E84369C5E3BC2669EAB4147B2822895F9"}, - {"7A832BD2CF5BF4919F353CE2A8C86A5E406DA2D52BE16A72", - "2F2F17CECF7E5A756D10785A3CB9DB", - "61DA05E3788CC2D8405DBA70C7A28E5AF699863C9F72E6C6770126929F5D6FA267F005EBCF49495CB46400958A3AE80D1289D1C671", - "44E91121195A41AF14E8CFDBD39A4B517BE0DF1A72977ED8A3EEF8EEDA1166B2EB6DB2C4AE2E74FA0F0C74537F659BFBD141E5DDEC67E64EDA85AABD3F52C85A785B9FB3CECD70E7DF", - "BEDF596EA21288D2B84901E188F6EE1468B14D5161D3802DBFE00D60203A24E2AB62714BF272A45551489838C3A7FEAADC177B591836E73684867CCF4E12901DCF2064058726BBA554E84ADC5136F507E961188D4AF06943D3"}, - {"1508E8AE9079AA15F1CEC4F776B4D11BCCB061B58AA56C18", - "BCA625674F41D1E3AB47672DC0C3", - "8B12CF84F16360F0EAD2A41BC021530FFCEC7F3579CAE658E10E2D3D81870F65AFCED0C77C6C4C6E6BA424FF23088C796BA6195ABA35094BF1829E089662E7A95FC90750AE16D0C8AFA55DAC789D7735B970B58D4BE7CEC7341DA82A0179A01929C27A59C5063215B859EA43", - "E525422519ECE070E82C", - "B47BC07C3ED1C0A43BA52C43CBACBCDBB29CAF1001E09FDF7107"}, - {"7550C2761644E911FE9ADD119BAC07376BEA442845FEAD876D7E7AC1B713E464", - "36D2EC25ADD33CDEDF495205BBC923", - "7FCFE81A3790DE97FFC3DE160C470847EA7E841177C2F759571CBD837EA004A6CA8C6F4AEBFF2E9FD552D73EB8A30705D58D70C0B67AEEA280CBBF0A477358ACEF1E7508F2735CD9A0E4F9AC92B8C008F575D3B6278F1C18BD01227E3502E5255F3AB1893632AD00C717C588EF652A51A43209E7EE90", - "2B1A62F8FDFAA3C16470A21AD307C9A7D03ADE8EF72C69B06F8D738CDE578D7AEFD0D40BD9C022FB9F580DF5394C998ACCCEFC5471A3996FB8F1045A81FDC6F32D13502EA65A211390C8D882B8E0BEFD8DD8CBEF51D1597B124E9F7F", - "C873E02A22DB89EB0787DB6A60B99F7E4A0A085D5C4232A81ADCE2D60AA36F92DDC33F93DD8640AC0E08416B187FB382B3EC3EE85A64B0E6EE41C1366A5AD2A282F66605E87031CCBA2FA7B2DA201D975994AADE3DD1EE122AE09604AD489B84BF0C1AB7129EE16C6934850E"}, - {"A51300285E554FDBDE7F771A9A9A80955639DD87129FAEF74987C91FB9687C71", - "81691D5D20EC818FCFF24B33DECC", - "C948093218AA9EB2A8E44A87EEA73FC8B6B75A196819A14BD83709EA323E8DF8B491045220E1D88729A38DBCFFB60D3056DAD4564498FD6574F74512945DEB34B69329ACED9FFC05D5D59DFCD5B973E2ACAFE6AD1EF8BBBC49351A2DD12508ED89ED", - "EB861165DAF7625F827C6B574ED703F03215", - "C6CD1CE76D2B3679C1B5AA1CFD67CCB55444B6BFD3E22C81CBC9BB738796B83E54E3"}, - {"8CE0156D26FAEB7E0B9B800BBB2E9D4075B5EAC5C62358B0E7F6FCE610223282", - "D2A7B94DD12CDACA909D3AD7", - "E021A78F374FC271389AB9A3E97077D755", - "7C26000B58929F5095E1CEE154F76C2A299248E299F9B5ADE6C403AA1FD4A67FD4E0232F214CE7B919EE7A1027D2B76C57475715CD078461", - "C556FB38DF069B56F337B5FF5775CE6EAA16824DFA754F20B78819028EA635C3BB7AA731DE8776B2DCB67DCA2D33EEDF3C7E52EA450013722A41755A0752433ED17BDD5991AAE77A"}, - {"1E8000A2CE00A561C9920A30BF0D7B983FEF8A1014C8F04C35CA6970E6BA02BD", - "65ED3D63F79F90BBFD19775E", - "336A8C0B7243582A46B221AA677647FCAE91", - "134A8B34824A290E7B", - "914FBEF80D0E6E17F8BDBB6097EBF5FBB0554952DC2B9E5151"}, - {"53D5607BBE690B6E8D8F6D97F3DF2BA853B682597A214B8AA0EA6E598650AF15", - "C391A856B9FE234E14BA1AC7BB40FF", - "479682BC21349C4BE1641D5E78FE2C79EC1B9CF5470936DCAD9967A4DCD7C4EFADA593BC9EDE71E6A08829B8580901B61E274227E9D918502DE3", - "EAD154DC09C5E26C5D26FF33ED148B27120C7F2C23225CC0D0631B03E1F6C6D96FEB88C1A4052ACB4CE746B884B6502931F407021126C6AAB8C514C077A5A38438AE88EE", - "938821286EBB671D999B87C032E1D6055392EB564E57970D55E545FC5E8BAB90E6E3E3C0913F6320995FC636D72CD9919657CC38BD51552F4A502D8D1FE56DB33EBAC5092630E69EBB986F0E15CEE9FC8C052501"}, - {"294362FCC984F440CEA3E9F7D2C06AF20C53AAC1B3738CA2186C914A6E193ABB", - "B15B61C8BB39261A8F55AB178EC3", - "D0729B6B75BB", - "2BD089ADCE9F334BAE3B065996C7D616DD0C27DF4218DCEEA0FBCA0F968837CE26B0876083327E25681FDDD620A32EC0DA12F73FAE826CC94BFF2B90A54D2651", - "AC94B25E4E21DE2437B806966CCD5D9385EF0CD4A51AB9FA6DE675C7B8952D67802E9FEC1FDE9F5D1EAB06057498BC0EEA454804FC9D2068982A3E24182D9AC2E7AB9994DDC899A604264583F63D066B"}, - {"959DBFEB039B1A5B8CE6A44649B602AAA5F98A906DB96143D202CD2024F749D9", - "01D7BDB1133E9C347486C1EFA6", - "F3843955BD741F379DD750585EDC55E2CDA05CCBA8C1F4622AC2FE35214BC3A019B8BD12C4CC42D9213D1E1556941E8D8450830287FFB3B763A13722DD4140ED9846FB5FFF745D7B0B967D810A068222E10B259AF1D392035B0D83DC1498A6830B11B2418A840212599171E0258A1C203B05362978", - "A21811232C950FA8B12237C2EBD6A7CD2C3A155905E9E0C7C120", - "63C1CE397B22F1A03F1FA549B43178BC405B152D3C95E977426D519B3DFCA28498823240592B6EEE7A14"}, - {"096AE499F5294173F34FF2B375F0E5D5AB79D0D03B33B1A74D7D576826345DF4", - "0C52B3D11D636E5910A4DD76D32C", - "229E9ECA3053789E937447BC719467075B6138A142DA528DA8F0CF8DDF022FD9AF8E74779BA3AC306609", - "8B7A00038783E8BAF6EDEAE0C4EAB48FC8FD501A588C7E4A4DB71E3604F2155A97687D3D2FFF8569261375A513CF4398CE0F87CA1658A1050F6EF6C4EA3E25", - "C20B6CF8D3C8241825FD90B2EDAC7593600646E579A8D8DAAE9E2E40C3835FE801B2BE4379131452BC5182C90307B176DFBE2049544222FE7783147B690774F6D9D7CEF52A91E61E298E9AA15464AC"}, -} diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go b/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go deleted file mode 100644 index 330309ff..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go +++ /dev/null @@ -1,78 +0,0 @@ -package ocb - -import ( - "encoding/hex" -) - -// Test vectors from https://tools.ietf.org/html/rfc7253. Note that key is -// shared across tests. -var testKey, _ = hex.DecodeString("000102030405060708090A0B0C0D0E0F") - -var rfc7253testVectors = []struct { - nonce, header, plaintext, ciphertext string -}{ - {"BBAA99887766554433221100", - "", - "", - "785407BFFFC8AD9EDCC5520AC9111EE6"}, - {"BBAA99887766554433221101", - "0001020304050607", - "0001020304050607", - "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009"}, - {"BBAA99887766554433221102", - "0001020304050607", - "", - "81017F8203F081277152FADE694A0A00"}, - {"BBAA99887766554433221103", - "", - "0001020304050607", - "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9"}, - {"BBAA99887766554433221104", - "000102030405060708090A0B0C0D0E0F", - "000102030405060708090A0B0C0D0E0F", - "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358"}, - {"BBAA99887766554433221105", - "000102030405060708090A0B0C0D0E0F", - "", - "8CF761B6902EF764462AD86498CA6B97"}, - {"BBAA99887766554433221106", - "", - "000102030405060708090A0B0C0D0E0F", - "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D"}, - {"BBAA99887766554433221107", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F"}, - {"BBAA99887766554433221108", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "", - "6DC225A071FC1B9F7C69F93B0F1E10DE"}, - {"BBAA99887766554433221109", - "", - "000102030405060708090A0B0C0D0E0F1011121314151617", - "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF"}, - {"BBAA9988776655443322110A", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240"}, - {"BBAA9988776655443322110B", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "", - "FE80690BEE8A485D11F32965BC9D2A32"}, - {"BBAA9988776655443322110C", - "", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF"}, - {"BBAA9988776655443322110D", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", - "D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60"}, - {"BBAA9988776655443322110E", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", - "", - "C5CD9D1850C141E358649994EE701B68"}, - {"BBAA9988776655443322110F", - "", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", - "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479"}, -} diff --git a/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go b/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go deleted file mode 100644 index 14a3c336..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go +++ /dev/null @@ -1,25 +0,0 @@ -package ocb - -// Second set of test vectors from https://tools.ietf.org/html/rfc7253 -var rfc7253TestVectorTaglen96 = struct { - key, nonce, header, plaintext, ciphertext string -}{"0F0E0D0C0B0A09080706050403020100", - "BBAA9988776655443322110D", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627", - "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA"} - -var rfc7253AlgorithmTest = []struct { - KEYLEN, TAGLEN int - OUTPUT string -}{ - {128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"}, - {192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"}, - {256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"}, - {128, 96, "77A3D8E73589158D25D01209"}, - {192, 96, "05D56EAD2752C86BE6932C5E"}, - {256, 96, "5458359AC23B0CBA9E6330DD"}, - {128, 64, "192C9B7BD90BA06A"}, - {192, 64, "0066BC6E0EF34E24"}, - {256, 64, "7D4EA5D445501CBE"}, -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go deleted file mode 100644 index 3c6251d1..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2014 Matthew Endsley -// All rights reserved -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted providing that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// Package keywrap is an implementation of the RFC 3394 AES key wrapping -// algorithm. This is used in OpenPGP with elliptic curve keys. -package keywrap - -import ( - "crypto/aes" - "encoding/binary" - "errors" -) - -var ( - // ErrWrapPlaintext is returned if the plaintext is not a multiple - // of 64 bits. - ErrWrapPlaintext = errors.New("keywrap: plainText must be a multiple of 64 bits") - - // ErrUnwrapCiphertext is returned if the ciphertext is not a - // multiple of 64 bits. - ErrUnwrapCiphertext = errors.New("keywrap: cipherText must by a multiple of 64 bits") - - // ErrUnwrapFailed is returned if unwrapping a key fails. - ErrUnwrapFailed = errors.New("keywrap: failed to unwrap key") - - // NB: the AES NewCipher call only fails if the key is an invalid length. - - // ErrInvalidKey is returned when the AES key is invalid. - ErrInvalidKey = errors.New("keywrap: invalid AES key") -) - -// Wrap a key using the RFC 3394 AES Key Wrap Algorithm. -func Wrap(key, plainText []byte) ([]byte, error) { - if len(plainText)%8 != 0 { - return nil, ErrWrapPlaintext - } - - c, err := aes.NewCipher(key) - if err != nil { - return nil, ErrInvalidKey - } - - nblocks := len(plainText) / 8 - - // 1) Initialize variables. - var block [aes.BlockSize]byte - // - Set A = IV, an initial value (see 2.2.3) - for ii := 0; ii < 8; ii++ { - block[ii] = 0xA6 - } - - // - For i = 1 to n - // - Set R[i] = P[i] - intermediate := make([]byte, len(plainText)) - copy(intermediate, plainText) - - // 2) Calculate intermediate values. - for ii := 0; ii < 6; ii++ { - for jj := 0; jj < nblocks; jj++ { - // - B = AES(K, A | R[i]) - copy(block[8:], intermediate[jj*8:jj*8+8]) - c.Encrypt(block[:], block[:]) - - // - A = MSB(64, B) ^ t where t = (n*j)+1 - t := uint64(ii*nblocks + jj + 1) - val := binary.BigEndian.Uint64(block[:8]) ^ t - binary.BigEndian.PutUint64(block[:8], val) - - // - R[i] = LSB(64, B) - copy(intermediate[jj*8:jj*8+8], block[8:]) - } - } - - // 3) Output results. - // - Set C[0] = A - // - For i = 1 to n - // - C[i] = R[i] - return append(block[:8], intermediate...), nil -} - -// Unwrap a key using the RFC 3394 AES Key Wrap Algorithm. -func Unwrap(key, cipherText []byte) ([]byte, error) { - if len(cipherText)%8 != 0 { - return nil, ErrUnwrapCiphertext - } - - c, err := aes.NewCipher(key) - if err != nil { - return nil, ErrInvalidKey - } - - nblocks := len(cipherText)/8 - 1 - - // 1) Initialize variables. - var block [aes.BlockSize]byte - // - Set A = C[0] - copy(block[:8], cipherText[:8]) - - // - For i = 1 to n - // - Set R[i] = C[i] - intermediate := make([]byte, len(cipherText)-8) - copy(intermediate, cipherText[8:]) - - // 2) Compute intermediate values. - for jj := 5; jj >= 0; jj-- { - for ii := nblocks - 1; ii >= 0; ii-- { - // - B = AES-1(K, (A ^ t) | R[i]) where t = n*j+1 - // - A = MSB(64, B) - t := uint64(jj*nblocks + ii + 1) - val := binary.BigEndian.Uint64(block[:8]) ^ t - binary.BigEndian.PutUint64(block[:8], val) - - copy(block[8:], intermediate[ii*8:ii*8+8]) - c.Decrypt(block[:], block[:]) - - // - R[i] = LSB(B, 64) - copy(intermediate[ii*8:ii*8+8], block[8:]) - } - } - - // 3) Output results. - // - If A is an appropriate initial value (see 2.2.3), - for ii := 0; ii < 8; ii++ { - if block[ii] != 0xA6 { - return nil, ErrUnwrapFailed - } - } - - // - For i = 1 to n - // - P[i] = R[i] - return intermediate, nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go deleted file mode 100644 index e0a677f2..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2010 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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is -// very similar to PEM except that it has an additional CRC checksum. -package armor // import "github.com/ProtonMail/go-crypto/openpgp/armor" - -import ( - "bufio" - "bytes" - "encoding/base64" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -// A Block represents an OpenPGP armored structure. -// -// The encoded form is: -// -// -----BEGIN Type----- -// Headers -// -// base64-encoded Bytes -// '=' base64 encoded checksum (optional) not checked anymore -// -----END Type----- -// -// where Headers is a possibly empty sequence of Key: Value lines. -// -// Since the armored data can be very large, this package presents a streaming -// interface. -type Block struct { - Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). - Header map[string]string // Optional headers. - Body io.Reader // A Reader from which the contents can be read - lReader lineReader - oReader openpgpReader -} - -var ArmorCorrupt error = errors.StructuralError("armor invalid") - -var armorStart = []byte("-----BEGIN ") -var armorEnd = []byte("-----END ") -var armorEndOfLine = []byte("-----") - -// lineReader wraps a line based reader. It watches for the end of an armor block -type lineReader struct { - in *bufio.Reader - buf []byte - eof bool -} - -func (l *lineReader) Read(p []byte) (n int, err error) { - if l.eof { - return 0, io.EOF - } - - if len(l.buf) > 0 { - n = copy(p, l.buf) - l.buf = l.buf[n:] - return - } - - line, isPrefix, err := l.in.ReadLine() - if err != nil { - return - } - if isPrefix { - return 0, ArmorCorrupt - } - - if bytes.HasPrefix(line, armorEnd) { - l.eof = true - return 0, io.EOF - } - - if len(line) == 5 && line[0] == '=' { - // This is the checksum line - // Don't check the checksum - - l.eof = true - return 0, io.EOF - } - - if len(line) > 96 { - return 0, ArmorCorrupt - } - - n = copy(p, line) - bytesToSave := len(line) - n - if bytesToSave > 0 { - if cap(l.buf) < bytesToSave { - l.buf = make([]byte, 0, bytesToSave) - } - l.buf = l.buf[0:bytesToSave] - copy(l.buf, line[n:]) - } - - return -} - -// openpgpReader passes Read calls to the underlying base64 decoder. -type openpgpReader struct { - lReader *lineReader - b64Reader io.Reader -} - -func (r *openpgpReader) Read(p []byte) (n int, err error) { - n, err = r.b64Reader.Read(p) - return -} - -// Decode reads a PGP armored block from the given Reader. It will ignore -// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The -// given Reader is not usable after calling this function: an arbitrary amount -// of data may have been read past the end of the block. -func Decode(in io.Reader) (p *Block, err error) { - r := bufio.NewReaderSize(in, 100) - var line []byte - ignoreNext := false - -TryNextBlock: - p = nil - - // Skip leading garbage - for { - ignoreThis := ignoreNext - line, ignoreNext, err = r.ReadLine() - if err != nil { - return - } - if ignoreNext || ignoreThis { - continue - } - line = bytes.TrimSpace(line) - if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { - break - } - } - - p = new(Block) - p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) - p.Header = make(map[string]string) - nextIsContinuation := false - var lastKey string - - // Read headers - for { - isContinuation := nextIsContinuation - line, nextIsContinuation, err = r.ReadLine() - if err != nil { - p = nil - return - } - if isContinuation { - p.Header[lastKey] += string(line) - continue - } - line = bytes.TrimSpace(line) - if len(line) == 0 { - break - } - - i := bytes.Index(line, []byte(":")) - if i == -1 { - goto TryNextBlock - } - lastKey = string(line[:i]) - var value string - if len(line) > i+2 { - value = string(line[i+2:]) - } - p.Header[lastKey] = value - } - - p.lReader.in = r - p.oReader.lReader = &p.lReader - p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) - p.Body = &p.oReader - - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go deleted file mode 100644 index 550efddf..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2010 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 armor - -import ( - "encoding/base64" - "io" - "sort" -) - -var armorHeaderSep = []byte(": ") -var blockEnd = []byte("\n=") -var newline = []byte("\n") -var armorEndOfLineOut = []byte("-----\n") - -const crc24Init = 0xb704ce -const crc24Poly = 0x1864cfb - -// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 -func crc24(crc uint32, d []byte) uint32 { - for _, b := range d { - crc ^= uint32(b) << 16 - for i := 0; i < 8; i++ { - crc <<= 1 - if crc&0x1000000 != 0 { - crc ^= crc24Poly - } - } - } - return crc -} - -// writeSlices writes its arguments to the given Writer. -func writeSlices(out io.Writer, slices ...[]byte) (err error) { - for _, s := range slices { - _, err = out.Write(s) - if err != nil { - return err - } - } - return -} - -// lineBreaker breaks data across several lines, all of the same byte length -// (except possibly the last). Lines are broken with a single '\n'. -type lineBreaker struct { - lineLength int - line []byte - used int - out io.Writer - haveWritten bool -} - -func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { - return &lineBreaker{ - lineLength: lineLength, - line: make([]byte, lineLength), - used: 0, - out: out, - } -} - -func (l *lineBreaker) Write(b []byte) (n int, err error) { - n = len(b) - - if n == 0 { - return - } - - if l.used == 0 && l.haveWritten { - _, err = l.out.Write([]byte{'\n'}) - if err != nil { - return - } - } - - if l.used+len(b) < l.lineLength { - l.used += copy(l.line[l.used:], b) - return - } - - l.haveWritten = true - _, err = l.out.Write(l.line[0:l.used]) - if err != nil { - return - } - excess := l.lineLength - l.used - l.used = 0 - - _, err = l.out.Write(b[0:excess]) - if err != nil { - return - } - - _, err = l.Write(b[excess:]) - return -} - -func (l *lineBreaker) Close() (err error) { - if l.used > 0 { - _, err = l.out.Write(l.line[0:l.used]) - if err != nil { - return - } - } - - return -} - -// encoding keeps track of a running CRC24 over the data which has been written -// to it and outputs a OpenPGP checksum when closed, followed by an armor -// trailer. -// -// It's built into a stack of io.Writers: -// -// encoding -> base64 encoder -> lineBreaker -> out -type encoding struct { - out io.Writer - breaker *lineBreaker - b64 io.WriteCloser - crc uint32 - crcEnabled bool - blockType []byte -} - -func (e *encoding) Write(data []byte) (n int, err error) { - if e.crcEnabled { - e.crc = crc24(e.crc, data) - } - return e.b64.Write(data) -} - -func (e *encoding) Close() (err error) { - err = e.b64.Close() - if err != nil { - return - } - e.breaker.Close() - - if e.crcEnabled { - var checksumBytes [3]byte - checksumBytes[0] = byte(e.crc >> 16) - checksumBytes[1] = byte(e.crc >> 8) - checksumBytes[2] = byte(e.crc) - - var b64ChecksumBytes [4]byte - base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) - - return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) - } - return writeSlices(e.out, newline, armorEnd, e.blockType, armorEndOfLine) -} - -func encode(out io.Writer, blockType string, headers map[string]string, checksum bool) (w io.WriteCloser, err error) { - bType := []byte(blockType) - err = writeSlices(out, armorStart, bType, armorEndOfLineOut) - if err != nil { - return - } - - keys := make([]string, len(headers)) - i := 0 - for k := range headers { - keys[i] = k - i++ - } - sort.Strings(keys) - for _, k := range keys { - err = writeSlices(out, []byte(k), armorHeaderSep, []byte(headers[k]), newline) - if err != nil { - return - } - } - - _, err = out.Write(newline) - if err != nil { - return - } - - e := &encoding{ - out: out, - breaker: newLineBreaker(out, 64), - blockType: bType, - crc: crc24Init, - crcEnabled: checksum, - } - e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) - return e, nil -} - -// Encode returns a WriteCloser which will encode the data written to it in -// OpenPGP armor. -func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { - return encode(out, blockType, headers, true) -} - -// EncodeWithChecksumOption returns a WriteCloser which will encode the data written to it in -// OpenPGP armor and provides the option to include a checksum. -// When forming ASCII Armor, the CRC24 footer SHOULD NOT be generated, -// unless interoperability with implementations that require the CRC24 footer -// to be present is a concern. -func EncodeWithChecksumOption(out io.Writer, blockType string, headers map[string]string, doChecksum bool) (w io.WriteCloser, err error) { - return encode(out, blockType, headers, doChecksum) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go deleted file mode 100644 index 5b40e137..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2011 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 openpgp - -import ( - "hash" - "io" -) - -// NewCanonicalTextHash reformats text written to it into the canonical -// form and then applies the hash h. See RFC 4880, section 5.2.1. -func NewCanonicalTextHash(h hash.Hash) hash.Hash { - return &canonicalTextHash{h, 0} -} - -type canonicalTextHash struct { - h hash.Hash - s int -} - -var newline = []byte{'\r', '\n'} - -func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) { - start := 0 - for i, c := range buf { - switch *s { - case 0: - if c == '\r' { - *s = 1 - } else if c == '\n' { - if _, err := cw.Write(buf[start:i]); err != nil { - return 0, err - } - if _, err := cw.Write(newline); err != nil { - return 0, err - } - start = i + 1 - } - case 1: - *s = 0 - } - } - - if _, err := cw.Write(buf[start:]); err != nil { - return 0, err - } - return len(buf), nil -} - -func (cth *canonicalTextHash) Write(buf []byte) (int, error) { - return writeCanonical(cth.h, buf, &cth.s) -} - -func (cth *canonicalTextHash) Sum(in []byte) []byte { - return cth.h.Sum(in) -} - -func (cth *canonicalTextHash) Reset() { - cth.h.Reset() - cth.s = 0 -} - -func (cth *canonicalTextHash) Size() int { - return cth.h.Size() -} - -func (cth *canonicalTextHash) BlockSize() int { - return cth.h.BlockSize() -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go deleted file mode 100644 index db8fb163..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2017 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 ecdh implements ECDH encryption, suitable for OpenPGP, -// as specified in RFC 6637, section 8. -package ecdh - -import ( - "bytes" - "errors" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" - "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" -) - -type KDF struct { - Hash algorithm.Hash - Cipher algorithm.Cipher -} - -type PublicKey struct { - curve ecc.ECDHCurve - Point []byte - KDF -} - -type PrivateKey struct { - PublicKey - D []byte -} - -func NewPublicKey(curve ecc.ECDHCurve, kdfHash algorithm.Hash, kdfCipher algorithm.Cipher) *PublicKey { - return &PublicKey{ - curve: curve, - KDF: KDF{ - Hash: kdfHash, - Cipher: kdfCipher, - }, - } -} - -func NewPrivateKey(key PublicKey) *PrivateKey { - return &PrivateKey{ - PublicKey: key, - } -} - -func (pk *PublicKey) GetCurve() ecc.ECDHCurve { - return pk.curve -} - -func (pk *PublicKey) MarshalPoint() []byte { - return pk.curve.MarshalBytePoint(pk.Point) -} - -func (pk *PublicKey) UnmarshalPoint(p []byte) error { - pk.Point = pk.curve.UnmarshalBytePoint(p) - if pk.Point == nil { - return errors.New("ecdh: failed to parse EC point") - } - return nil -} - -func (sk *PrivateKey) MarshalByteSecret() []byte { - return sk.curve.MarshalByteSecret(sk.D) -} - -func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error { - sk.D = sk.curve.UnmarshalByteSecret(d) - - if sk.D == nil { - return errors.New("ecdh: failed to parse scalar") - } - return nil -} - -func GenerateKey(rand io.Reader, c ecc.ECDHCurve, kdf KDF) (priv *PrivateKey, err error) { - priv = new(PrivateKey) - priv.PublicKey.curve = c - priv.PublicKey.KDF = kdf - priv.PublicKey.Point, priv.D, err = c.GenerateECDH(rand) - return -} - -func Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) { - if len(msg) > 40 { - return nil, nil, errors.New("ecdh: message too long") - } - // the sender MAY use 21, 13, and 5 bytes of padding for AES-128, - // AES-192, and AES-256, respectively, to provide the same number of - // octets, 40 total, as an input to the key wrapping method. - padding := make([]byte, 40-len(msg)) - for i := range padding { - padding[i] = byte(40 - len(msg)) - } - m := append(msg, padding...) - - ephemeral, zb, err := pub.curve.Encaps(random, pub.Point) - if err != nil { - return nil, nil, err - } - - vsG = pub.curve.MarshalBytePoint(ephemeral) - - z, err := buildKey(pub, zb, curveOID, fingerprint, false, false) - if err != nil { - return nil, nil, err - } - - if c, err = keywrap.Wrap(z, m); err != nil { - return nil, nil, err - } - - return vsG, c, nil - -} - -func Decrypt(priv *PrivateKey, vsG, c, curveOID, fingerprint []byte) (msg []byte, err error) { - var m []byte - zb, err := priv.PublicKey.curve.Decaps(priv.curve.UnmarshalBytePoint(vsG), priv.D) - - // Try buildKey three times to workaround an old bug, see comments in buildKey. - for i := 0; i < 3; i++ { - var z []byte - // RFC6637 §8: "Compute Z = KDF( S, Z_len, Param );" - z, err = buildKey(&priv.PublicKey, zb, curveOID, fingerprint, i == 1, i == 2) - if err != nil { - return nil, err - } - - // RFC6637 §8: "Compute C = AESKeyWrap( Z, c ) as per [RFC3394]" - m, err = keywrap.Unwrap(z, c) - if err == nil { - break - } - } - - // Only return an error after we've tried all (required) variants of buildKey. - if err != nil { - return nil, err - } - - // RFC6637 §8: "m = symm_alg_ID || session key || checksum || pkcs5_padding" - // The last byte should be the length of the padding, as per PKCS5; strip it off. - return m[:len(m)-int(m[len(m)-1])], nil -} - -func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLeading, stripTrailing bool) ([]byte, error) { - // Param = curve_OID_len || curve_OID || public_key_alg_ID || 03 - // || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap - // || "Anonymous Sender " || recipient_fingerprint; - param := new(bytes.Buffer) - if _, err := param.Write(curveOID); err != nil { - return nil, err - } - algKDF := []byte{18, 3, 1, pub.KDF.Hash.Id(), pub.KDF.Cipher.Id()} - if _, err := param.Write(algKDF); err != nil { - return nil, err - } - if _, err := param.Write([]byte("Anonymous Sender ")); err != nil { - return nil, err - } - if _, err := param.Write(fingerprint[:]); err != nil { - return nil, err - } - - // MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param ); - h := pub.KDF.Hash.New() - if _, err := h.Write([]byte{0x0, 0x0, 0x0, 0x1}); err != nil { - return nil, err - } - zbLen := len(zb) - i := 0 - j := zbLen - 1 - if stripLeading { - // Work around old go crypto bug where the leading zeros are missing. - for i < zbLen && zb[i] == 0 { - i++ - } - } - if stripTrailing { - // Work around old OpenPGP.js bug where insignificant trailing zeros in - // this little-endian number are missing. - // (See https://github.com/openpgpjs/openpgpjs/pull/853.) - for j >= 0 && zb[j] == 0 { - j-- - } - } - if _, err := h.Write(zb[i : j+1]); err != nil { - return nil, err - } - if _, err := h.Write(param.Bytes()); err != nil { - return nil, err - } - mb := h.Sum(nil) - - return mb[:pub.KDF.Cipher.KeySize()], nil // return oBits leftmost bits of MB. - -} - -func Validate(priv *PrivateKey) error { - return priv.curve.ValidateECDH(priv.Point, priv.D) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdsa/ecdsa.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdsa/ecdsa.go deleted file mode 100644 index f94ae1b2..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/ecdsa/ecdsa.go +++ /dev/null @@ -1,80 +0,0 @@ -// Package ecdsa implements ECDSA signature, suitable for OpenPGP, -// as specified in RFC 6637, section 5. -package ecdsa - -import ( - "errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" - "io" - "math/big" -) - -type PublicKey struct { - X, Y *big.Int - curve ecc.ECDSACurve -} - -type PrivateKey struct { - PublicKey - D *big.Int -} - -func NewPublicKey(curve ecc.ECDSACurve) *PublicKey { - return &PublicKey{ - curve: curve, - } -} - -func NewPrivateKey(key PublicKey) *PrivateKey { - return &PrivateKey{ - PublicKey: key, - } -} - -func (pk *PublicKey) GetCurve() ecc.ECDSACurve { - return pk.curve -} - -func (pk *PublicKey) MarshalPoint() []byte { - return pk.curve.MarshalIntegerPoint(pk.X, pk.Y) -} - -func (pk *PublicKey) UnmarshalPoint(p []byte) error { - pk.X, pk.Y = pk.curve.UnmarshalIntegerPoint(p) - if pk.X == nil { - return errors.New("ecdsa: failed to parse EC point") - } - return nil -} - -func (sk *PrivateKey) MarshalIntegerSecret() []byte { - return sk.curve.MarshalIntegerSecret(sk.D) -} - -func (sk *PrivateKey) UnmarshalIntegerSecret(d []byte) error { - sk.D = sk.curve.UnmarshalIntegerSecret(d) - - if sk.D == nil { - return errors.New("ecdsa: failed to parse scalar") - } - return nil -} - -func GenerateKey(rand io.Reader, c ecc.ECDSACurve) (priv *PrivateKey, err error) { - priv = new(PrivateKey) - priv.PublicKey.curve = c - priv.PublicKey.X, priv.PublicKey.Y, priv.D, err = c.GenerateECDSA(rand) - return -} - -func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { - return priv.PublicKey.curve.Sign(rand, priv.X, priv.Y, priv.D, hash) -} - -func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { - return pub.curve.Verify(pub.X, pub.Y, hash, r, s) -} - -func Validate(priv *PrivateKey) error { - return priv.curve.ValidateECDSA(priv.X, priv.Y, priv.D.Bytes()) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go deleted file mode 100644 index 6abdf7c4..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go +++ /dev/null @@ -1,115 +0,0 @@ -// Package ed25519 implements the ed25519 signature algorithm for OpenPGP -// as defined in the Open PGP crypto refresh. -package ed25519 - -import ( - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - ed25519lib "github.com/cloudflare/circl/sign/ed25519" -) - -const ( - // PublicKeySize is the size, in bytes, of public keys in this package. - PublicKeySize = ed25519lib.PublicKeySize - // SeedSize is the size, in bytes, of private key seeds. - // The private key representation used by RFC 8032. - SeedSize = ed25519lib.SeedSize - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - SignatureSize = ed25519lib.SignatureSize -) - -type PublicKey struct { - // Point represents the elliptic curve point of the public key. - Point []byte -} - -type PrivateKey struct { - PublicKey - // Key the private key representation by RFC 8032, - // encoded as seed | pub key point. - Key []byte -} - -// NewPublicKey creates a new empty ed25519 public key. -func NewPublicKey() *PublicKey { - return &PublicKey{} -} - -// NewPrivateKey creates a new empty private key referencing the public key. -func NewPrivateKey(key PublicKey) *PrivateKey { - return &PrivateKey{ - PublicKey: key, - } -} - -// Seed returns the ed25519 private key secret seed. -// The private key representation by RFC 8032. -func (pk *PrivateKey) Seed() []byte { - return pk.Key[:SeedSize] -} - -// MarshalByteSecret returns the underlying 32 byte seed of the private key. -func (pk *PrivateKey) MarshalByteSecret() []byte { - return pk.Seed() -} - -// UnmarshalByteSecret computes the private key from the secret seed -// and stores it in the private key object. -func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error { - sk.Key = ed25519lib.NewKeyFromSeed(seed) - return nil -} - -// GenerateKey generates a fresh private key with the provided randomness source. -func GenerateKey(rand io.Reader) (*PrivateKey, error) { - publicKey, privateKey, err := ed25519lib.GenerateKey(rand) - if err != nil { - return nil, err - } - privateKeyOut := new(PrivateKey) - privateKeyOut.PublicKey.Point = publicKey[:] - privateKeyOut.Key = privateKey[:] - return privateKeyOut, nil -} - -// Sign signs a message with the ed25519 algorithm. -// priv MUST be a valid key! Check this with Validate() before use. -func Sign(priv *PrivateKey, message []byte) ([]byte, error) { - return ed25519lib.Sign(priv.Key, message), nil -} - -// Verify verifies an ed25519 signature. -func Verify(pub *PublicKey, message []byte, signature []byte) bool { - return ed25519lib.Verify(pub.Point, message, signature) -} - -// Validate checks if the ed25519 private key is valid. -func Validate(priv *PrivateKey) error { - expectedPrivateKey := ed25519lib.NewKeyFromSeed(priv.Seed()) - if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 { - return errors.KeyInvalidError("ed25519: invalid ed25519 secret") - } - if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 { - return errors.KeyInvalidError("ed25519: invalid ed25519 public key") - } - return nil -} - -// ENCODING/DECODING signature: - -// WriteSignature encodes and writes an ed25519 signature to writer. -func WriteSignature(writer io.Writer, signature []byte) error { - _, err := writer.Write(signature) - return err -} - -// ReadSignature decodes an ed25519 signature from a reader. -func ReadSignature(reader io.Reader) ([]byte, error) { - signature := make([]byte, SignatureSize) - if _, err := io.ReadFull(reader, signature); err != nil { - return nil, err - } - return signature, nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go deleted file mode 100644 index b11fb4fb..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go +++ /dev/null @@ -1,119 +0,0 @@ -// Package ed448 implements the ed448 signature algorithm for OpenPGP -// as defined in the Open PGP crypto refresh. -package ed448 - -import ( - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - ed448lib "github.com/cloudflare/circl/sign/ed448" -) - -const ( - // PublicKeySize is the size, in bytes, of public keys in this package. - PublicKeySize = ed448lib.PublicKeySize - // SeedSize is the size, in bytes, of private key seeds. - // The private key representation used by RFC 8032. - SeedSize = ed448lib.SeedSize - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - SignatureSize = ed448lib.SignatureSize -) - -type PublicKey struct { - // Point represents the elliptic curve point of the public key. - Point []byte -} - -type PrivateKey struct { - PublicKey - // Key the private key representation by RFC 8032, - // encoded as seed | public key point. - Key []byte -} - -// NewPublicKey creates a new empty ed448 public key. -func NewPublicKey() *PublicKey { - return &PublicKey{} -} - -// NewPrivateKey creates a new empty private key referencing the public key. -func NewPrivateKey(key PublicKey) *PrivateKey { - return &PrivateKey{ - PublicKey: key, - } -} - -// Seed returns the ed448 private key secret seed. -// The private key representation by RFC 8032. -func (pk *PrivateKey) Seed() []byte { - return pk.Key[:SeedSize] -} - -// MarshalByteSecret returns the underlying seed of the private key. -func (pk *PrivateKey) MarshalByteSecret() []byte { - return pk.Seed() -} - -// UnmarshalByteSecret computes the private key from the secret seed -// and stores it in the private key object. -func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error { - sk.Key = ed448lib.NewKeyFromSeed(seed) - return nil -} - -// GenerateKey generates a fresh private key with the provided randomness source. -func GenerateKey(rand io.Reader) (*PrivateKey, error) { - publicKey, privateKey, err := ed448lib.GenerateKey(rand) - if err != nil { - return nil, err - } - privateKeyOut := new(PrivateKey) - privateKeyOut.PublicKey.Point = publicKey[:] - privateKeyOut.Key = privateKey[:] - return privateKeyOut, nil -} - -// Sign signs a message with the ed448 algorithm. -// priv MUST be a valid key! Check this with Validate() before use. -func Sign(priv *PrivateKey, message []byte) ([]byte, error) { - // Ed448 is used with the empty string as a context string. - // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7 - return ed448lib.Sign(priv.Key, message, ""), nil -} - -// Verify verifies a ed448 signature -func Verify(pub *PublicKey, message []byte, signature []byte) bool { - // Ed448 is used with the empty string as a context string. - // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7 - return ed448lib.Verify(pub.Point, message, signature, "") -} - -// Validate checks if the ed448 private key is valid -func Validate(priv *PrivateKey) error { - expectedPrivateKey := ed448lib.NewKeyFromSeed(priv.Seed()) - if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 { - return errors.KeyInvalidError("ed448: invalid ed448 secret") - } - if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 { - return errors.KeyInvalidError("ed448: invalid ed448 public key") - } - return nil -} - -// ENCODING/DECODING signature: - -// WriteSignature encodes and writes an ed448 signature to writer. -func WriteSignature(writer io.Writer, signature []byte) error { - _, err := writer.Write(signature) - return err -} - -// ReadSignature decodes an ed448 signature from a reader. -func ReadSignature(reader io.Reader) ([]byte, error) { - signature := make([]byte, SignatureSize) - if _, err := io.ReadFull(reader, signature); err != nil { - return nil, err - } - return signature, nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/eddsa/eddsa.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/eddsa/eddsa.go deleted file mode 100644 index 99ecfc7f..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/eddsa/eddsa.go +++ /dev/null @@ -1,91 +0,0 @@ -// Package eddsa implements EdDSA signature, suitable for OpenPGP, as specified in -// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7 -package eddsa - -import ( - "errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" - "io" -) - -type PublicKey struct { - X []byte - curve ecc.EdDSACurve -} - -type PrivateKey struct { - PublicKey - D []byte -} - -func NewPublicKey(curve ecc.EdDSACurve) *PublicKey { - return &PublicKey{ - curve: curve, - } -} - -func NewPrivateKey(key PublicKey) *PrivateKey { - return &PrivateKey{ - PublicKey: key, - } -} - -func (pk *PublicKey) GetCurve() ecc.EdDSACurve { - return pk.curve -} - -func (pk *PublicKey) MarshalPoint() []byte { - return pk.curve.MarshalBytePoint(pk.X) -} - -func (pk *PublicKey) UnmarshalPoint(x []byte) error { - pk.X = pk.curve.UnmarshalBytePoint(x) - - if pk.X == nil { - return errors.New("eddsa: failed to parse EC point") - } - return nil -} - -func (sk *PrivateKey) MarshalByteSecret() []byte { - return sk.curve.MarshalByteSecret(sk.D) -} - -func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error { - sk.D = sk.curve.UnmarshalByteSecret(d) - - if sk.D == nil { - return errors.New("eddsa: failed to parse scalar") - } - return nil -} - -func GenerateKey(rand io.Reader, c ecc.EdDSACurve) (priv *PrivateKey, err error) { - priv = new(PrivateKey) - priv.PublicKey.curve = c - priv.PublicKey.X, priv.D, err = c.GenerateEdDSA(rand) - return -} - -func Sign(priv *PrivateKey, message []byte) (r, s []byte, err error) { - sig, err := priv.PublicKey.curve.Sign(priv.PublicKey.X, priv.D, message) - if err != nil { - return nil, nil, err - } - - r, s = priv.PublicKey.curve.MarshalSignature(sig) - return -} - -func Verify(pub *PublicKey, message, r, s []byte) bool { - sig := pub.curve.UnmarshalSignature(r, s) - if sig == nil { - return false - } - - return pub.curve.Verify(pub.X, message, sig) -} - -func Validate(priv *PrivateKey) error { - return priv.curve.ValidateEdDSA(priv.PublicKey.X, priv.D) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go deleted file mode 100644 index bad27743..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2011 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 elgamal implements ElGamal encryption, suitable for OpenPGP, -// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on -// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, -// n. 4, 1985, pp. 469-472. -// -// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it -// unsuitable for other protocols. RSA should be used in preference in any -// case. -package elgamal // import "github.com/ProtonMail/go-crypto/openpgp/elgamal" - -import ( - "crypto/rand" - "crypto/subtle" - "errors" - "io" - "math/big" -) - -// PublicKey represents an ElGamal public key. -type PublicKey struct { - G, P, Y *big.Int -} - -// PrivateKey represents an ElGamal private key. -type PrivateKey struct { - PublicKey - X *big.Int -} - -// Encrypt encrypts the given message to the given public key. The result is a -// pair of integers. Errors can result from reading random, or because msg is -// too large to be encrypted to the public key. -func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { - pLen := (pub.P.BitLen() + 7) / 8 - if len(msg) > pLen-11 { - err = errors.New("elgamal: message too long") - return - } - - // EM = 0x02 || PS || 0x00 || M - em := make([]byte, pLen-1) - em[0] = 2 - ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] - err = nonZeroRandomBytes(ps, random) - if err != nil { - return - } - em[len(em)-len(msg)-1] = 0 - copy(mm, msg) - - m := new(big.Int).SetBytes(em) - - k, err := rand.Int(random, pub.P) - if err != nil { - return - } - - c1 = new(big.Int).Exp(pub.G, k, pub.P) - s := new(big.Int).Exp(pub.Y, k, pub.P) - c2 = s.Mul(s, m) - c2.Mod(c2, pub.P) - - return -} - -// Decrypt takes two integers, resulting from an ElGamal encryption, and -// returns the plaintext of the message. An error can result only if the -// ciphertext is invalid. Users should keep in mind that this is a padding -// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can -// be used to break the cryptosystem. See “Chosen Ciphertext Attacks -// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel -// Bleichenbacher, Advances in Cryptology (Crypto '98), -func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { - s := new(big.Int).Exp(c1, priv.X, priv.P) - if s.ModInverse(s, priv.P) == nil { - return nil, errors.New("elgamal: invalid private key") - } - s.Mul(s, c2) - s.Mod(s, priv.P) - em := s.Bytes() - - firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) - - // The remainder of the plaintext must be a string of non-zero random - // octets, followed by a 0, followed by the message. - // lookingForIndex: 1 iff we are still looking for the zero. - // index: the offset of the first zero byte. - var lookingForIndex, index int - lookingForIndex = 1 - - for i := 1; i < len(em); i++ { - equals0 := subtle.ConstantTimeByteEq(em[i], 0) - index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) - lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) - } - - if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { - return nil, errors.New("elgamal: decryption error") - } - return em[index+1:], nil -} - -// nonZeroRandomBytes fills the given slice with non-zero random octets. -func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { - _, err = io.ReadFull(rand, s) - if err != nil { - return - } - - for i := 0; i < len(s); i++ { - for s[i] == 0 { - _, err = io.ReadFull(rand, s[i:i+1]) - if err != nil { - return - } - } - } - - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go deleted file mode 100644 index 2e341507..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2010 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 errors contains common error types for the OpenPGP packages. -package errors // import "github.com/ProtonMail/go-crypto/openpgp/errors" - -import ( - "fmt" - "strconv" -) - -var ( - // ErrDecryptSessionKeyParsing is a generic error message for parsing errors in decrypted data - // to reduce the risk of oracle attacks. - ErrDecryptSessionKeyParsing = DecryptWithSessionKeyError("parsing error") - // ErrAEADTagVerification is returned if one of the tag verifications in SEIPDv2 fails - ErrAEADTagVerification error = DecryptWithSessionKeyError("AEAD tag verification failed") - // ErrMDCHashMismatch - ErrMDCHashMismatch error = SignatureError("MDC hash mismatch") - // ErrMDCMissing - ErrMDCMissing error = SignatureError("MDC packet not found") -) - -// A StructuralError is returned when OpenPGP data is found to be syntactically -// invalid. -type StructuralError string - -func (s StructuralError) Error() string { - return "openpgp: invalid data: " + string(s) -} - -// A DecryptWithSessionKeyError is returned when a failure occurs when reading from symmetrically decrypted data or -// an authentication tag verification fails. -// Such an error indicates that the supplied session key is likely wrong or the data got corrupted. -type DecryptWithSessionKeyError string - -func (s DecryptWithSessionKeyError) Error() string { - return "openpgp: decryption with session key failed: " + string(s) -} - -// HandleSensitiveParsingError handles parsing errors when reading data from potentially decrypted data. -// The function makes parsing errors generic to reduce the risk of oracle attacks in SEIPDv1. -func HandleSensitiveParsingError(err error, decrypted bool) error { - if !decrypted { - // Data was not encrypted so we return the inner error. - return err - } - // The data is read from a stream that decrypts using a session key; - // therefore, we need to handle parsing errors appropriately. - // This is essential to mitigate the risk of oracle attacks. - if decError, ok := err.(*DecryptWithSessionKeyError); ok { - return decError - } - if decError, ok := err.(DecryptWithSessionKeyError); ok { - return decError - } - return ErrDecryptSessionKeyParsing -} - -// UnsupportedError indicates that, although the OpenPGP data is valid, it -// makes use of currently unimplemented features. -type UnsupportedError string - -func (s UnsupportedError) Error() string { - return "openpgp: unsupported feature: " + string(s) -} - -// InvalidArgumentError indicates that the caller is in error and passed an -// incorrect value. -type InvalidArgumentError string - -func (i InvalidArgumentError) Error() string { - return "openpgp: invalid argument: " + string(i) -} - -// SignatureError indicates that a syntactically valid signature failed to -// validate. -type SignatureError string - -func (b SignatureError) Error() string { - return "openpgp: invalid signature: " + string(b) -} - -type signatureExpiredError int - -func (se signatureExpiredError) Error() string { - return "openpgp: signature expired" -} - -var ErrSignatureExpired error = signatureExpiredError(0) - -type keyExpiredError int - -func (ke keyExpiredError) Error() string { - return "openpgp: key expired" -} - -var ErrSignatureOlderThanKey error = signatureOlderThanKeyError(0) - -type signatureOlderThanKeyError int - -func (ske signatureOlderThanKeyError) Error() string { - return "openpgp: signature is older than the key" -} - -var ErrKeyExpired error = keyExpiredError(0) - -type keyIncorrectError int - -func (ki keyIncorrectError) Error() string { - return "openpgp: incorrect key" -} - -var ErrKeyIncorrect error = keyIncorrectError(0) - -// KeyInvalidError indicates that the public key parameters are invalid -// as they do not match the private ones -type KeyInvalidError string - -func (e KeyInvalidError) Error() string { - return "openpgp: invalid key: " + string(e) -} - -type unknownIssuerError int - -func (unknownIssuerError) Error() string { - return "openpgp: signature made by unknown entity" -} - -var ErrUnknownIssuer error = unknownIssuerError(0) - -type keyRevokedError int - -func (keyRevokedError) Error() string { - return "openpgp: signature made by revoked key" -} - -var ErrKeyRevoked error = keyRevokedError(0) - -type WeakAlgorithmError string - -func (e WeakAlgorithmError) Error() string { - return "openpgp: weak algorithms are rejected: " + string(e) -} - -type UnknownPacketTypeError uint8 - -func (upte UnknownPacketTypeError) Error() string { - return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) -} - -type CriticalUnknownPacketTypeError uint8 - -func (upte CriticalUnknownPacketTypeError) Error() string { - return "openpgp: unknown critical packet type: " + strconv.Itoa(int(upte)) -} - -// AEADError indicates that there is a problem when initializing or using a -// AEAD instance, configuration struct, nonces or index values. -type AEADError string - -func (ae AEADError) Error() string { - return "openpgp: aead error: " + string(ae) -} - -// ErrDummyPrivateKey results when operations are attempted on a private key -// that is just a dummy key. See -// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109 -type ErrDummyPrivateKey string - -func (dke ErrDummyPrivateKey) Error() string { - return "openpgp: s2k GNU dummy key: " + string(dke) -} - -// ErrMalformedMessage results when the packet sequence is incorrect -type ErrMalformedMessage string - -func (dke ErrMalformedMessage) Error() string { - return "openpgp: malformed message " + string(dke) -} - -type messageTooLargeError int - -func (e messageTooLargeError) Error() string { - return "openpgp: decompressed message size exceeds provided limit" -} - -// ErrMessageTooLarge is returned if the read data from -// a compressed packet exceeds the provided limit. -var ErrMessageTooLarge error = messageTooLargeError(0) - -// ErrEncryptionKeySelection is returned if encryption key selection fails (v2 API). -type ErrEncryptionKeySelection struct { - PrimaryKeyId string - PrimaryKeyErr error - EncSelectionKeyId *string - EncSelectionErr error -} - -func (eks ErrEncryptionKeySelection) Error() string { - prefix := fmt.Sprintf("openpgp: key selection for primary key %s:", eks.PrimaryKeyId) - if eks.PrimaryKeyErr != nil { - return fmt.Sprintf("%s invalid primary key: %s", prefix, eks.PrimaryKeyErr) - } - if eks.EncSelectionKeyId != nil { - return fmt.Sprintf("%s invalid encryption key %s: %s", prefix, *eks.EncSelectionKeyId, eks.EncSelectionErr) - } - return fmt.Sprintf("%s no encryption key: %s", prefix, eks.EncSelectionErr) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go deleted file mode 100644 index 526bd777..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go +++ /dev/null @@ -1,24 +0,0 @@ -package openpgp - -import ( - "crypto" - - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" -) - -// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP -// hash id. -func HashIdToHash(id byte) (h crypto.Hash, ok bool) { - return algorithm.HashIdToHash(id) -} - -// HashIdToString returns the name of the hash function corresponding to the -// given OpenPGP hash id. -func HashIdToString(id byte) (name string, ok bool) { - return algorithm.HashIdToString(id) -} - -// HashToHashId returns an OpenPGP hash id which corresponds the given Hash. -func HashToHashId(h crypto.Hash) (id byte, ok bool) { - return algorithm.HashToHashId(h) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go deleted file mode 100644 index d0670651..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2019 ProtonTech AG - -package algorithm - -import ( - "crypto/cipher" - "github.com/ProtonMail/go-crypto/eax" - "github.com/ProtonMail/go-crypto/ocb" -) - -// AEADMode defines the Authenticated Encryption with Associated Data mode of -// operation. -type AEADMode uint8 - -// Supported modes of operation (see RFC4880bis [EAX] and RFC7253) -const ( - AEADModeEAX = AEADMode(1) - AEADModeOCB = AEADMode(2) - AEADModeGCM = AEADMode(3) -) - -// TagLength returns the length in bytes of authentication tags. -func (mode AEADMode) TagLength() int { - switch mode { - case AEADModeEAX: - return 16 - case AEADModeOCB: - return 16 - case AEADModeGCM: - return 16 - default: - return 0 - } -} - -// NonceLength returns the length in bytes of nonces. -func (mode AEADMode) NonceLength() int { - switch mode { - case AEADModeEAX: - return 16 - case AEADModeOCB: - return 15 - case AEADModeGCM: - return 12 - default: - return 0 - } -} - -// New returns a fresh instance of the given mode -func (mode AEADMode) New(block cipher.Block) (alg cipher.AEAD) { - var err error - switch mode { - case AEADModeEAX: - alg, err = eax.NewEAX(block) - case AEADModeOCB: - alg, err = ocb.NewOCB(block) - case AEADModeGCM: - alg, err = cipher.NewGCM(block) - } - if err != nil { - panic(err.Error()) - } - return alg -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go deleted file mode 100644 index c76a75bc..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2017 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 algorithm - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/des" - - "golang.org/x/crypto/cast5" -) - -// Cipher is an official symmetric key cipher algorithm. See RFC 4880, -// section 9.2. -type Cipher interface { - // Id returns the algorithm ID, as a byte, of the cipher. - Id() uint8 - // KeySize returns the key size, in bytes, of the cipher. - KeySize() int - // BlockSize returns the block size, in bytes, of the cipher. - BlockSize() int - // New returns a fresh instance of the given cipher. - New(key []byte) cipher.Block -} - -// The following constants mirror the OpenPGP standard (RFC 4880). -const ( - TripleDES = CipherFunction(2) - CAST5 = CipherFunction(3) - AES128 = CipherFunction(7) - AES192 = CipherFunction(8) - AES256 = CipherFunction(9) -) - -// CipherById represents the different block ciphers specified for OpenPGP. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 -var CipherById = map[uint8]Cipher{ - TripleDES.Id(): TripleDES, - CAST5.Id(): CAST5, - AES128.Id(): AES128, - AES192.Id(): AES192, - AES256.Id(): AES256, -} - -type CipherFunction uint8 - -// ID returns the algorithm Id, as a byte, of cipher. -func (sk CipherFunction) Id() uint8 { - return uint8(sk) -} - -// KeySize returns the key size, in bytes, of cipher. -func (cipher CipherFunction) KeySize() int { - switch cipher { - case CAST5: - return cast5.KeySize - case AES128: - return 16 - case AES192, TripleDES: - return 24 - case AES256: - return 32 - } - return 0 -} - -// BlockSize returns the block size, in bytes, of cipher. -func (cipher CipherFunction) BlockSize() int { - switch cipher { - case TripleDES: - return des.BlockSize - case CAST5: - return 8 - case AES128, AES192, AES256: - return 16 - } - return 0 -} - -// New returns a fresh instance of the given cipher. -func (cipher CipherFunction) New(key []byte) (block cipher.Block) { - var err error - switch cipher { - case TripleDES: - block, err = des.NewTripleDESCipher(key) - case CAST5: - block, err = cast5.NewCipher(key) - case AES128, AES192, AES256: - block, err = aes.NewCipher(key) - } - if err != nil { - panic(err.Error()) - } - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go deleted file mode 100644 index d1a00fc7..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2017 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 algorithm - -import ( - "crypto" - "fmt" - "hash" -) - -// Hash is an official hash function algorithm. See RFC 4880, section 9.4. -type Hash interface { - // Id returns the algorithm ID, as a byte, of Hash. - Id() uint8 - // Available reports whether the given hash function is linked into the binary. - Available() bool - // HashFunc simply returns the value of h so that Hash implements SignerOpts. - HashFunc() crypto.Hash - // New returns a new hash.Hash calculating the given hash function. New - // panics if the hash function is not linked into the binary. - New() hash.Hash - // Size returns the length, in bytes, of a digest resulting from the given - // hash function. It doesn't require that the hash function in question be - // linked into the program. - Size() int - // String is the name of the hash function corresponding to the given - // OpenPGP hash id. - String() string -} - -// The following vars mirror the crypto/Hash supported hash functions. -var ( - SHA1 Hash = cryptoHash{2, crypto.SHA1} - SHA256 Hash = cryptoHash{8, crypto.SHA256} - SHA384 Hash = cryptoHash{9, crypto.SHA384} - SHA512 Hash = cryptoHash{10, crypto.SHA512} - SHA224 Hash = cryptoHash{11, crypto.SHA224} - SHA3_256 Hash = cryptoHash{12, crypto.SHA3_256} - SHA3_512 Hash = cryptoHash{14, crypto.SHA3_512} -) - -// HashById represents the different hash functions specified for OpenPGP. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14 -var ( - HashById = map[uint8]Hash{ - SHA256.Id(): SHA256, - SHA384.Id(): SHA384, - SHA512.Id(): SHA512, - SHA224.Id(): SHA224, - SHA3_256.Id(): SHA3_256, - SHA3_512.Id(): SHA3_512, - } -) - -// cryptoHash contains pairs relating OpenPGP's hash identifier with -// Go's crypto.Hash type. See RFC 4880, section 9.4. -type cryptoHash struct { - id uint8 - crypto.Hash -} - -// Id returns the algorithm ID, as a byte, of cryptoHash. -func (h cryptoHash) Id() uint8 { - return h.id -} - -var hashNames = map[uint8]string{ - SHA256.Id(): "SHA256", - SHA384.Id(): "SHA384", - SHA512.Id(): "SHA512", - SHA224.Id(): "SHA224", - SHA3_256.Id(): "SHA3-256", - SHA3_512.Id(): "SHA3-512", -} - -func (h cryptoHash) String() string { - s, ok := hashNames[h.id] - if !ok { - panic(fmt.Sprintf("Unsupported hash function %d", h.id)) - } - return s -} - -// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP -// hash id. -func HashIdToHash(id byte) (h crypto.Hash, ok bool) { - if hash, ok := HashById[id]; ok { - return hash.HashFunc(), true - } - return 0, false -} - -// HashIdToHashWithSha1 returns a crypto.Hash which corresponds to the given OpenPGP -// hash id, allowing sha1. -func HashIdToHashWithSha1(id byte) (h crypto.Hash, ok bool) { - if hash, ok := HashById[id]; ok { - return hash.HashFunc(), true - } - - if id == SHA1.Id() { - return SHA1.HashFunc(), true - } - - return 0, false -} - -// HashIdToString returns the name of the hash function corresponding to the -// given OpenPGP hash id. -func HashIdToString(id byte) (name string, ok bool) { - if hash, ok := HashById[id]; ok { - return hash.String(), true - } - return "", false -} - -// HashToHashId returns an OpenPGP hash id which corresponds the given Hash. -func HashToHashId(h crypto.Hash) (id byte, ok bool) { - for id, hash := range HashById { - if hash.HashFunc() == h { - return id, true - } - } - - return 0, false -} - -// HashToHashIdWithSha1 returns an OpenPGP hash id which corresponds the given Hash, -// allowing instances of SHA1 -func HashToHashIdWithSha1(h crypto.Hash) (id byte, ok bool) { - for id, hash := range HashById { - if hash.HashFunc() == h { - return id, true - } - } - - if h == SHA1.HashFunc() { - return SHA1.Id(), true - } - - return 0, false -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go deleted file mode 100644 index 888767c4..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go +++ /dev/null @@ -1,171 +0,0 @@ -// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA. -package ecc - -import ( - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - x25519lib "github.com/cloudflare/circl/dh/x25519" -) - -type curve25519 struct{} - -func NewCurve25519() *curve25519 { - return &curve25519{} -} - -func (c *curve25519) GetCurveName() string { - return "curve25519" -} - -// MarshalBytePoint encodes the public point from native format, adding the prefix. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6 -func (c *curve25519) MarshalBytePoint(point []byte) []byte { - return append([]byte{0x40}, point...) -} - -// UnmarshalBytePoint decodes the public point to native format, removing the prefix. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6 -func (c *curve25519) UnmarshalBytePoint(point []byte) []byte { - if len(point) != x25519lib.Size+1 { - return nil - } - - // Remove prefix - return point[1:] -} - -// MarshalByteSecret encodes the secret scalar from native format. -// Note that the EC secret scalar differs from the definition of public keys in -// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is -// more uniform with how big integers are represented in OpenPGP, and (2) the -// leading zeros are truncated. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1 -// Note that leading zero bytes are stripped later when encoding as an MPI. -func (c *curve25519) MarshalByteSecret(secret []byte) []byte { - d := make([]byte, x25519lib.Size) - copyReversed(d, secret) - - // The following ensures that the private key is a number of the form - // 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of - // the curve. - // - // This masking is done internally in the underlying lib and so is unnecessary - // for security, but OpenPGP implementations require that private keys be - // pre-masked. - d[0] &= 127 - d[0] |= 64 - d[31] &= 248 - - return d -} - -// UnmarshalByteSecret decodes the secret scalar from native format. -// Note that the EC secret scalar differs from the definition of public keys in -// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is -// more uniform with how big integers are represented in OpenPGP, and (2) the -// leading zeros are truncated. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1 -func (c *curve25519) UnmarshalByteSecret(d []byte) []byte { - if len(d) > x25519lib.Size { - return nil - } - - // Ensure truncated leading bytes are re-added - secret := make([]byte, x25519lib.Size) - copyReversed(secret, d) - - return secret -} - -// generateKeyPairBytes Generates a private-public key-pair. -// 'priv' is a private key; a little-endian scalar belonging to the set -// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the -// curve. 'pub' is simply 'priv' * G where G is the base point. -// See https://cr.yp.to/ecdh.html and RFC7748, sec 5. -func (c *curve25519) generateKeyPairBytes(rand io.Reader) (priv, pub x25519lib.Key, err error) { - _, err = io.ReadFull(rand, priv[:]) - if err != nil { - return - } - - x25519lib.KeyGen(&pub, &priv) - return -} - -func (c *curve25519) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) { - priv, pub, err := c.generateKeyPairBytes(rand) - if err != nil { - return - } - - return pub[:], priv[:], nil -} - -func (c *genericCurve) MaskSecret(secret []byte) []byte { - return secret -} - -func (c *curve25519) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) { - // RFC6637 §8: "Generate an ephemeral key pair {v, V=vG}" - // ephemeralPrivate corresponds to `v`. - // ephemeralPublic corresponds to `V`. - ephemeralPrivate, ephemeralPublic, err := c.generateKeyPairBytes(rand) - if err != nil { - return nil, nil, err - } - - // RFC6637 §8: "Obtain the authenticated recipient public key R" - // pubKey corresponds to `R`. - var pubKey x25519lib.Key - copy(pubKey[:], point) - - // RFC6637 §8: "Compute the shared point S = vR" - // "VB = convert point V to the octet string" - // sharedPoint corresponds to `VB`. - var sharedPoint x25519lib.Key - x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey) - - return ephemeralPublic[:], sharedPoint[:], nil -} - -func (c *curve25519) Decaps(vsG, secret []byte) (sharedSecret []byte, err error) { - var ephemeralPublic, decodedPrivate, sharedPoint x25519lib.Key - // RFC6637 §8: "The decryption is the inverse of the method given." - // All quoted descriptions in comments below describe encryption, and - // the reverse is performed. - // vsG corresponds to `VB` in RFC6637 §8 . - - // RFC6637 §8: "VB = convert point V to the octet string" - copy(ephemeralPublic[:], vsG) - - // decodedPrivate corresponds to `r` in RFC6637 §8 . - copy(decodedPrivate[:], secret) - - // RFC6637 §8: "Note that the recipient obtains the shared secret by calculating - // S = rV = rvG, where (r,R) is the recipient's key pair." - // sharedPoint corresponds to `S`. - x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic) - - return sharedPoint[:], nil -} - -func (c *curve25519) ValidateECDH(point []byte, secret []byte) (err error) { - var pk, sk x25519lib.Key - copy(sk[:], secret) - x25519lib.KeyGen(&pk, &sk) - - if subtle.ConstantTimeCompare(point, pk[:]) == 0 { - return errors.KeyInvalidError("ecc: invalid curve25519 public point") - } - - return nil -} - -func copyReversed(out []byte, in []byte) { - l := len(in) - for i := 0; i < l; i++ { - out[i] = in[l-i-1] - } -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go deleted file mode 100644 index 0da2d0d8..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go +++ /dev/null @@ -1,143 +0,0 @@ -// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA. -package ecc - -import ( - "bytes" - "crypto/elliptic" - - "github.com/ProtonMail/go-crypto/bitcurves" - "github.com/ProtonMail/go-crypto/brainpool" - "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" -) - -const Curve25519GenName = "Curve25519" - -type CurveInfo struct { - GenName string - Oid *encoding.OID - Curve Curve -} - -var Curves = []CurveInfo{ - { - // NIST P-256 - GenName: "P256", - Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}), - Curve: NewGenericCurve(elliptic.P256()), - }, - { - // NIST P-384 - GenName: "P384", - Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}), - Curve: NewGenericCurve(elliptic.P384()), - }, - { - // NIST P-521 - GenName: "P521", - Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}), - Curve: NewGenericCurve(elliptic.P521()), - }, - { - // SecP256k1 - GenName: "SecP256k1", - Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}), - Curve: NewGenericCurve(bitcurves.S256()), - }, - { - // Curve25519 - GenName: Curve25519GenName, - Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}), - Curve: NewCurve25519(), - }, - { - // x448 - GenName: "Curve448", - Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x6F}), - Curve: NewX448(), - }, - { - // Ed25519 - GenName: Curve25519GenName, - Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}), - Curve: NewEd25519(), - }, - { - // Ed448 - GenName: "Curve448", - Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x71}), - Curve: NewEd448(), - }, - { - // BrainpoolP256r1 - GenName: "BrainpoolP256", - Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}), - Curve: NewGenericCurve(brainpool.P256r1()), - }, - { - // BrainpoolP384r1 - GenName: "BrainpoolP384", - Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}), - Curve: NewGenericCurve(brainpool.P384r1()), - }, - { - // BrainpoolP512r1 - GenName: "BrainpoolP512", - Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}), - Curve: NewGenericCurve(brainpool.P512r1()), - }, -} - -func FindByCurve(curve Curve) *CurveInfo { - for _, curveInfo := range Curves { - if curveInfo.Curve.GetCurveName() == curve.GetCurveName() { - return &curveInfo - } - } - return nil -} - -func FindByOid(oid encoding.Field) *CurveInfo { - var rawBytes = oid.Bytes() - for _, curveInfo := range Curves { - if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) { - return &curveInfo - } - } - return nil -} - -func FindEdDSAByGenName(curveGenName string) EdDSACurve { - for _, curveInfo := range Curves { - if curveInfo.GenName == curveGenName { - curve, ok := curveInfo.Curve.(EdDSACurve) - if ok { - return curve - } - } - } - return nil -} - -func FindECDSAByGenName(curveGenName string) ECDSACurve { - for _, curveInfo := range Curves { - if curveInfo.GenName == curveGenName { - curve, ok := curveInfo.Curve.(ECDSACurve) - if ok { - return curve - } - } - } - return nil -} - -func FindECDHByGenName(curveGenName string) ECDHCurve { - for _, curveInfo := range Curves { - if curveInfo.GenName == curveGenName { - curve, ok := curveInfo.Curve.(ECDHCurve) - if ok { - return curve - } - } - } - return nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curves.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curves.go deleted file mode 100644 index 5ed9c93b..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curves.go +++ /dev/null @@ -1,48 +0,0 @@ -// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA. -package ecc - -import ( - "io" - "math/big" -) - -type Curve interface { - GetCurveName() string -} - -type ECDSACurve interface { - Curve - MarshalIntegerPoint(x, y *big.Int) []byte - UnmarshalIntegerPoint([]byte) (x, y *big.Int) - MarshalIntegerSecret(d *big.Int) []byte - UnmarshalIntegerSecret(d []byte) *big.Int - GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error) - Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error) - Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool - ValidateECDSA(x, y *big.Int, secret []byte) error -} - -type EdDSACurve interface { - Curve - MarshalBytePoint(x []byte) []byte - UnmarshalBytePoint([]byte) (x []byte) - MarshalByteSecret(d []byte) []byte - UnmarshalByteSecret(d []byte) []byte - MarshalSignature(sig []byte) (r, s []byte) - UnmarshalSignature(r, s []byte) (sig []byte) - GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) - Sign(publicKey, privateKey, message []byte) (sig []byte, err error) - Verify(publicKey, message, sig []byte) bool - ValidateEdDSA(publicKey, privateKey []byte) (err error) -} -type ECDHCurve interface { - Curve - MarshalBytePoint([]byte) (encoded []byte) - UnmarshalBytePoint(encoded []byte) []byte - MarshalByteSecret(d []byte) []byte - UnmarshalByteSecret(d []byte) []byte - GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) - Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) - Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) - ValidateECDH(public []byte, secret []byte) error -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go deleted file mode 100644 index 5a4c3a85..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go +++ /dev/null @@ -1,120 +0,0 @@ -// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA. -package ecc - -import ( - "bytes" - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - ed25519lib "github.com/cloudflare/circl/sign/ed25519" -) - -const ed25519Size = 32 - -type ed25519 struct{} - -func NewEd25519() *ed25519 { - return &ed25519{} -} - -func (c *ed25519) GetCurveName() string { - return "ed25519" -} - -// MarshalBytePoint encodes the public point from native format, adding the prefix. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed25519) MarshalBytePoint(x []byte) []byte { - return append([]byte{0x40}, x...) -} - -// UnmarshalBytePoint decodes a point from prefixed format to native. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed25519) UnmarshalBytePoint(point []byte) (x []byte) { - if len(point) != ed25519lib.PublicKeySize+1 { - return nil - } - - // Return unprefixed - return point[1:] -} - -// MarshalByteSecret encodes a scalar in native format. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed25519) MarshalByteSecret(d []byte) []byte { - return d -} - -// UnmarshalByteSecret decodes a scalar in native format and re-adds the stripped leading zeroes -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed25519) UnmarshalByteSecret(s []byte) (d []byte) { - if len(s) > ed25519lib.SeedSize { - return nil - } - - // Handle stripped leading zeroes - d = make([]byte, ed25519lib.SeedSize) - copy(d[ed25519lib.SeedSize-len(s):], s) - return -} - -// MarshalSignature splits a signature in R and S. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1 -func (c *ed25519) MarshalSignature(sig []byte) (r, s []byte) { - return sig[:ed25519Size], sig[ed25519Size:] -} - -// UnmarshalSignature decodes R and S in the native format, re-adding the stripped leading zeroes -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1 -func (c *ed25519) UnmarshalSignature(r, s []byte) (sig []byte) { - // Check size - if len(r) > 32 || len(s) > 32 { - return nil - } - - sig = make([]byte, ed25519lib.SignatureSize) - - // Handle stripped leading zeroes - copy(sig[ed25519Size-len(r):ed25519Size], r) - copy(sig[ed25519lib.SignatureSize-len(s):], s) - return sig -} - -func (c *ed25519) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) { - pk, sk, err := ed25519lib.GenerateKey(rand) - - if err != nil { - return nil, nil, err - } - - return pk, sk[:ed25519lib.SeedSize], nil -} - -func getEd25519Sk(publicKey, privateKey []byte) ed25519lib.PrivateKey { - privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey) - - if privateKeyCap >= privateKeyLen+publicKeyLen && - bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) { - return privateKey[:privateKeyLen+publicKeyLen] - } - - return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...) -} - -func (c *ed25519) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) { - sig = ed25519lib.Sign(getEd25519Sk(publicKey, privateKey), message) - return sig, nil -} - -func (c *ed25519) Verify(publicKey, message, sig []byte) bool { - return ed25519lib.Verify(publicKey, message, sig) -} - -func (c *ed25519) ValidateEdDSA(publicKey, privateKey []byte) (err error) { - priv := getEd25519Sk(publicKey, privateKey) - expectedPriv := ed25519lib.NewKeyFromSeed(priv.Seed()) - if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 { - return errors.KeyInvalidError("ecc: invalid ed25519 secret") - } - return nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go deleted file mode 100644 index b6edda74..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go +++ /dev/null @@ -1,119 +0,0 @@ -// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA. -package ecc - -import ( - "bytes" - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - ed448lib "github.com/cloudflare/circl/sign/ed448" -) - -type ed448 struct{} - -func NewEd448() *ed448 { - return &ed448{} -} - -func (c *ed448) GetCurveName() string { - return "ed448" -} - -// MarshalBytePoint encodes the public point from native format, adding the prefix. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed448) MarshalBytePoint(x []byte) []byte { - // Return prefixed - return append([]byte{0x40}, x...) -} - -// UnmarshalBytePoint decodes a point from prefixed format to native. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed448) UnmarshalBytePoint(point []byte) (x []byte) { - if len(point) != ed448lib.PublicKeySize+1 { - return nil - } - - // Strip prefix - return point[1:] -} - -// MarshalByteSecret encoded a scalar from native format to prefixed. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed448) MarshalByteSecret(d []byte) []byte { - // Return prefixed - return append([]byte{0x40}, d...) -} - -// UnmarshalByteSecret decodes a scalar from prefixed format to native. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5 -func (c *ed448) UnmarshalByteSecret(s []byte) (d []byte) { - // Check prefixed size - if len(s) != ed448lib.SeedSize+1 { - return nil - } - - // Strip prefix - return s[1:] -} - -// MarshalSignature splits a signature in R and S, where R is in prefixed native format and -// S is an MPI with value zero. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2 -func (c *ed448) MarshalSignature(sig []byte) (r, s []byte) { - return append([]byte{0x40}, sig...), []byte{} -} - -// UnmarshalSignature decodes R and S in the native format. Only R is used, in prefixed native format. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2 -func (c *ed448) UnmarshalSignature(r, s []byte) (sig []byte) { - if len(r) != ed448lib.SignatureSize+1 { - return nil - } - - return r[1:] -} - -func (c *ed448) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) { - pk, sk, err := ed448lib.GenerateKey(rand) - - if err != nil { - return nil, nil, err - } - - return pk, sk[:ed448lib.SeedSize], nil -} - -func getEd448Sk(publicKey, privateKey []byte) ed448lib.PrivateKey { - privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey) - - if privateKeyCap >= privateKeyLen+publicKeyLen && - bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) { - return privateKey[:privateKeyLen+publicKeyLen] - } - - return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...) -} - -func (c *ed448) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) { - // Ed448 is used with the empty string as a context string. - // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7 - sig = ed448lib.Sign(getEd448Sk(publicKey, privateKey), message, "") - - return sig, nil -} - -func (c *ed448) Verify(publicKey, message, sig []byte) bool { - // Ed448 is used with the empty string as a context string. - // See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7 - return ed448lib.Verify(publicKey, message, sig, "") -} - -func (c *ed448) ValidateEdDSA(publicKey, privateKey []byte) (err error) { - priv := getEd448Sk(publicKey, privateKey) - expectedPriv := ed448lib.NewKeyFromSeed(priv.Seed()) - if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 { - return errors.KeyInvalidError("ecc: invalid ed448 secret") - } - return nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go deleted file mode 100644 index e28d7c71..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go +++ /dev/null @@ -1,149 +0,0 @@ -// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA. -package ecc - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "fmt" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "io" - "math/big" -) - -type genericCurve struct { - Curve elliptic.Curve -} - -func NewGenericCurve(c elliptic.Curve) *genericCurve { - return &genericCurve{ - Curve: c, - } -} - -func (c *genericCurve) GetCurveName() string { - return c.Curve.Params().Name -} - -func (c *genericCurve) MarshalBytePoint(point []byte) []byte { - return point -} - -func (c *genericCurve) UnmarshalBytePoint(point []byte) []byte { - return point -} - -func (c *genericCurve) MarshalIntegerPoint(x, y *big.Int) []byte { - return elliptic.Marshal(c.Curve, x, y) -} - -func (c *genericCurve) UnmarshalIntegerPoint(point []byte) (x, y *big.Int) { - return elliptic.Unmarshal(c.Curve, point) -} - -func (c *genericCurve) MarshalByteSecret(d []byte) []byte { - return d -} - -func (c *genericCurve) UnmarshalByteSecret(d []byte) []byte { - return d -} - -func (c *genericCurve) MarshalIntegerSecret(d *big.Int) []byte { - return d.Bytes() -} - -func (c *genericCurve) UnmarshalIntegerSecret(d []byte) *big.Int { - return new(big.Int).SetBytes(d) -} - -func (c *genericCurve) GenerateECDH(rand io.Reader) (point, secret []byte, err error) { - secret, x, y, err := elliptic.GenerateKey(c.Curve, rand) - if err != nil { - return nil, nil, err - } - - point = elliptic.Marshal(c.Curve, x, y) - return point, secret, nil -} - -func (c *genericCurve) GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error) { - priv, err := ecdsa.GenerateKey(c.Curve, rand) - if err != nil { - return - } - - return priv.X, priv.Y, priv.D, nil -} - -func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) { - xP, yP := elliptic.Unmarshal(c.Curve, point) - if xP == nil { - panic("invalid point") - } - - d, x, y, err := elliptic.GenerateKey(c.Curve, rand) - if err != nil { - return nil, nil, err - } - - vsG := elliptic.Marshal(c.Curve, x, y) - zbBig, _ := c.Curve.ScalarMult(xP, yP, d) - - byteLen := (c.Curve.Params().BitSize + 7) >> 3 - zb := make([]byte, byteLen) - zbBytes := zbBig.Bytes() - copy(zb[byteLen-len(zbBytes):], zbBytes) - - return vsG, zb, nil -} - -func (c *genericCurve) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) { - x, y := elliptic.Unmarshal(c.Curve, ephemeral) - zbBig, _ := c.Curve.ScalarMult(x, y, secret) - byteLen := (c.Curve.Params().BitSize + 7) >> 3 - zb := make([]byte, byteLen) - zbBytes := zbBig.Bytes() - copy(zb[byteLen-len(zbBytes):], zbBytes) - - return zb, nil -} - -func (c *genericCurve) Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error) { - priv := &ecdsa.PrivateKey{D: d, PublicKey: ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}} - return ecdsa.Sign(rand, priv, hash) -} - -func (c *genericCurve) Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool { - pub := &ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve} - return ecdsa.Verify(pub, hash, r, s) -} - -func (c *genericCurve) validate(xP, yP *big.Int, secret []byte) error { - // the public point should not be at infinity (0,0) - zero := new(big.Int) - if xP.Cmp(zero) == 0 && yP.Cmp(zero) == 0 { - return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", c.Curve.Params().Name)) - } - - // re-derive the public point Q' = (X,Y) = dG - // to compare to declared Q in public key - expectedX, expectedY := c.Curve.ScalarBaseMult(secret) - if xP.Cmp(expectedX) != 0 || yP.Cmp(expectedY) != 0 { - return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name)) - } - - return nil -} - -func (c *genericCurve) ValidateECDSA(xP, yP *big.Int, secret []byte) error { - return c.validate(xP, yP, secret) -} - -func (c *genericCurve) ValidateECDH(point []byte, secret []byte) error { - xP, yP := elliptic.Unmarshal(c.Curve, point) - if xP == nil { - return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name)) - } - - return c.validate(xP, yP, secret) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.go deleted file mode 100644 index df04262e..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.go +++ /dev/null @@ -1,107 +0,0 @@ -// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA. -package ecc - -import ( - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - x448lib "github.com/cloudflare/circl/dh/x448" -) - -type x448 struct{} - -func NewX448() *x448 { - return &x448{} -} - -func (c *x448) GetCurveName() string { - return "x448" -} - -// MarshalBytePoint encodes the public point from native format, adding the prefix. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6 -func (c *x448) MarshalBytePoint(point []byte) []byte { - return append([]byte{0x40}, point...) -} - -// UnmarshalBytePoint decodes a point from prefixed format to native. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6 -func (c *x448) UnmarshalBytePoint(point []byte) []byte { - if len(point) != x448lib.Size+1 { - return nil - } - - return point[1:] -} - -// MarshalByteSecret encoded a scalar from native format to prefixed. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2 -func (c *x448) MarshalByteSecret(d []byte) []byte { - return append([]byte{0x40}, d...) -} - -// UnmarshalByteSecret decodes a scalar from prefixed format to native. -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2 -func (c *x448) UnmarshalByteSecret(d []byte) []byte { - if len(d) != x448lib.Size+1 { - return nil - } - - // Store without prefix - return d[1:] -} - -func (c *x448) generateKeyPairBytes(rand io.Reader) (sk, pk x448lib.Key, err error) { - if _, err = rand.Read(sk[:]); err != nil { - return - } - - x448lib.KeyGen(&pk, &sk) - return -} - -func (c *x448) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) { - priv, pub, err := c.generateKeyPairBytes(rand) - if err != nil { - return - } - - return pub[:], priv[:], nil -} - -func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) { - var pk, ss x448lib.Key - seed, e, err := c.generateKeyPairBytes(rand) - if err != nil { - return nil, nil, err - } - copy(pk[:], point) - x448lib.Shared(&ss, &seed, &pk) - - return e[:], ss[:], nil -} - -func (c *x448) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) { - var ss, sk, e x448lib.Key - - copy(sk[:], secret) - copy(e[:], ephemeral) - x448lib.Shared(&ss, &sk, &e) - - return ss[:], nil -} - -func (c *x448) ValidateECDH(point []byte, secret []byte) error { - var sk, pk, expectedPk x448lib.Key - - copy(pk[:], point) - copy(sk[:], secret) - x448lib.KeyGen(&expectedPk, &sk) - - if subtle.ConstantTimeCompare(expectedPk[:], pk[:]) == 0 { - return errors.KeyInvalidError("ecc: invalid curve25519 public point") - } - - return nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go deleted file mode 100644 index 6c921481..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017 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 encoding implements openpgp packet field encodings as specified in -// RFC 4880 and 6637. -package encoding - -import "io" - -// Field is an encoded field of an openpgp packet. -type Field interface { - // Bytes returns the decoded data. - Bytes() []byte - - // BitLength is the size in bits of the decoded data. - BitLength() uint16 - - // EncodedBytes returns the encoded data. - EncodedBytes() []byte - - // EncodedLength is the size in bytes of the encoded data. - EncodedLength() uint16 - - // ReadFrom reads the next Field from r. - ReadFrom(r io.Reader) (int64, error) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go deleted file mode 100644 index 02e5e695..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2017 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 encoding - -import ( - "io" - "math/big" - "math/bits" -) - -// An MPI is used to store the contents of a big integer, along with the bit -// length that was specified in the original input. This allows the MPI to be -// reserialized exactly. -type MPI struct { - bytes []byte - bitLength uint16 -} - -// NewMPI returns a MPI initialized with bytes. -func NewMPI(bytes []byte) *MPI { - for len(bytes) != 0 && bytes[0] == 0 { - bytes = bytes[1:] - } - if len(bytes) == 0 { - bitLength := uint16(0) - return &MPI{bytes, bitLength} - } - bitLength := 8*uint16(len(bytes)-1) + uint16(bits.Len8(bytes[0])) - return &MPI{bytes, bitLength} -} - -// Bytes returns the decoded data. -func (m *MPI) Bytes() []byte { - return m.bytes -} - -// BitLength is the size in bits of the decoded data. -func (m *MPI) BitLength() uint16 { - return m.bitLength -} - -// EncodedBytes returns the encoded data. -func (m *MPI) EncodedBytes() []byte { - return append([]byte{byte(m.bitLength >> 8), byte(m.bitLength)}, m.bytes...) -} - -// EncodedLength is the size in bytes of the encoded data. -func (m *MPI) EncodedLength() uint16 { - return uint16(2 + len(m.bytes)) -} - -// ReadFrom reads into m the next MPI from r. -func (m *MPI) ReadFrom(r io.Reader) (int64, error) { - var buf [2]byte - n, err := io.ReadFull(r, buf[0:]) - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return int64(n), err - } - - m.bitLength = uint16(buf[0])<<8 | uint16(buf[1]) - m.bytes = make([]byte, (int(m.bitLength)+7)/8) - - nn, err := io.ReadFull(r, m.bytes) - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - - // remove leading zero bytes from malformed GnuPG encoded MPIs: - // https://bugs.gnupg.org/gnupg/issue1853 - // for _, b := range m.bytes { - // if b != 0 { - // break - // } - // m.bytes = m.bytes[1:] - // m.bitLength -= 8 - // } - - return int64(n) + int64(nn), err -} - -// SetBig initializes m with the bits from n. -func (m *MPI) SetBig(n *big.Int) *MPI { - m.bytes = n.Bytes() - m.bitLength = uint16(n.BitLen()) - return m -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go deleted file mode 100644 index c9df9fe2..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2017 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 encoding - -import ( - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -// OID is used to store a variable-length field with a one-octet size -// prefix. See https://tools.ietf.org/html/rfc6637#section-9. -type OID struct { - bytes []byte -} - -const ( - // maxOID is the maximum number of bytes in a OID. - maxOID = 254 - // reservedOIDLength1 and reservedOIDLength2 are OID lengths that the RFC - // specifies are reserved. - reservedOIDLength1 = 0 - reservedOIDLength2 = 0xff -) - -// NewOID returns a OID initialized with bytes. -func NewOID(bytes []byte) *OID { - switch len(bytes) { - case reservedOIDLength1, reservedOIDLength2: - panic("encoding: NewOID argument length is reserved") - default: - if len(bytes) > maxOID { - panic("encoding: NewOID argument too large") - } - } - - return &OID{ - bytes: bytes, - } -} - -// Bytes returns the decoded data. -func (o *OID) Bytes() []byte { - return o.bytes -} - -// BitLength is the size in bits of the decoded data. -func (o *OID) BitLength() uint16 { - return uint16(len(o.bytes) * 8) -} - -// EncodedBytes returns the encoded data. -func (o *OID) EncodedBytes() []byte { - return append([]byte{byte(len(o.bytes))}, o.bytes...) -} - -// EncodedLength is the size in bytes of the encoded data. -func (o *OID) EncodedLength() uint16 { - return uint16(1 + len(o.bytes)) -} - -// ReadFrom reads into b the next OID from r. -func (o *OID) ReadFrom(r io.Reader) (int64, error) { - var buf [1]byte - n, err := io.ReadFull(r, buf[:]) - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return int64(n), err - } - - switch buf[0] { - case reservedOIDLength1, reservedOIDLength2: - return int64(n), errors.UnsupportedError("reserved for future extensions") - } - - o.bytes = make([]byte, buf[0]) - - nn, err := io.ReadFull(r, o.bytes) - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - - return int64(n) + int64(nn), err -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go deleted file mode 100644 index 77213f66..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2011 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 openpgp - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" - goerrors "errors" - "io" - "math/big" - "time" - - "github.com/ProtonMail/go-crypto/openpgp/ecdh" - "github.com/ProtonMail/go-crypto/openpgp/ecdsa" - "github.com/ProtonMail/go-crypto/openpgp/ed25519" - "github.com/ProtonMail/go-crypto/openpgp/ed448" - "github.com/ProtonMail/go-crypto/openpgp/eddsa" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" - "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" - "github.com/ProtonMail/go-crypto/openpgp/packet" - "github.com/ProtonMail/go-crypto/openpgp/x25519" - "github.com/ProtonMail/go-crypto/openpgp/x448" -) - -// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a -// single identity composed of the given full name, comment and email, any of -// which may be empty but must not contain any of "()<>\x00". -// If config is nil, sensible defaults will be used. -func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { - creationTime := config.Now() - keyLifetimeSecs := config.KeyLifetime() - - // Generate a primary signing key - primaryPrivRaw, err := newSigner(config) - if err != nil { - return nil, err - } - primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw) - if config.V6() { - if err := primary.UpgradeToV6(); err != nil { - return nil, err - } - } - - e := &Entity{ - PrimaryKey: &primary.PublicKey, - PrivateKey: primary, - Identities: make(map[string]*Identity), - Subkeys: []Subkey{}, - Signatures: []*packet.Signature{}, - } - - if config.V6() { - // In v6 keys algorithm preferences should be stored in direct key signatures - selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypeDirectSignature, config) - err = writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config) - if err != nil { - return nil, err - } - err = selfSignature.SignDirectKeyBinding(&primary.PublicKey, primary, config) - if err != nil { - return nil, err - } - e.Signatures = append(e.Signatures, selfSignature) - e.SelfSignature = selfSignature - } - - err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6()) - if err != nil { - return nil, err - } - - // NOTE: No key expiry here, but we will not return this subkey in EncryptionKey() - // if the primary/master key has expired. - err = e.addEncryptionSubkey(config, creationTime, 0) - if err != nil { - return nil, err - } - - return e, nil -} - -func (t *Entity) AddUserId(name, comment, email string, config *packet.Config) error { - creationTime := config.Now() - keyLifetimeSecs := config.KeyLifetime() - return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6()) -} - -func writeKeyProperties(selfSignature *packet.Signature, creationTime time.Time, keyLifetimeSecs uint32, config *packet.Config) error { - advertiseAead := config.AEAD() != nil - - selfSignature.CreationTime = creationTime - selfSignature.KeyLifetimeSecs = &keyLifetimeSecs - selfSignature.FlagsValid = true - selfSignature.FlagSign = true - selfSignature.FlagCertify = true - selfSignature.SEIPDv1 = true // true by default, see 5.8 vs. 5.14 - selfSignature.SEIPDv2 = advertiseAead - - // Set the PreferredHash for the SelfSignature from the packet.Config. - // If it is not the must-implement algorithm from rfc4880bis, append that. - hash, ok := algorithm.HashToHashId(config.Hash()) - if !ok { - return errors.UnsupportedError("unsupported preferred hash function") - } - - selfSignature.PreferredHash = []uint8{hash} - if config.Hash() != crypto.SHA256 { - selfSignature.PreferredHash = append(selfSignature.PreferredHash, hashToHashId(crypto.SHA256)) - } - - // Likewise for DefaultCipher. - selfSignature.PreferredSymmetric = []uint8{uint8(config.Cipher())} - if config.Cipher() != packet.CipherAES128 { - selfSignature.PreferredSymmetric = append(selfSignature.PreferredSymmetric, uint8(packet.CipherAES128)) - } - - // We set CompressionNone as the preferred compression algorithm because - // of compression side channel attacks, then append the configured - // DefaultCompressionAlgo if any is set (to signal support for cases - // where the application knows that using compression is safe). - selfSignature.PreferredCompression = []uint8{uint8(packet.CompressionNone)} - if config.Compression() != packet.CompressionNone { - selfSignature.PreferredCompression = append(selfSignature.PreferredCompression, uint8(config.Compression())) - } - - if advertiseAead { - // Get the preferred AEAD mode from the packet.Config. - // If it is not the must-implement algorithm from rfc9580, append that. - modes := []uint8{uint8(config.AEAD().Mode())} - if config.AEAD().Mode() != packet.AEADModeOCB { - modes = append(modes, uint8(packet.AEADModeOCB)) - } - - // For preferred (AES256, GCM), we'll generate (AES256, GCM), (AES256, OCB), (AES128, GCM), (AES128, OCB) - for _, cipher := range selfSignature.PreferredSymmetric { - for _, mode := range modes { - selfSignature.PreferredCipherSuites = append(selfSignature.PreferredCipherSuites, [2]uint8{cipher, mode}) - } - } - } - return nil -} - -func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32, writeProperties bool) error { - uid := packet.NewUserId(name, comment, email) - if uid == nil { - return errors.InvalidArgumentError("user id field contained invalid characters") - } - - if _, ok := t.Identities[uid.Id]; ok { - return errors.InvalidArgumentError("user id exist") - } - - primary := t.PrivateKey - isPrimaryId := len(t.Identities) == 0 - selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypePositiveCert, config) - if writeProperties { - err := writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config) - if err != nil { - return err - } - } - selfSignature.IsPrimaryId = &isPrimaryId - - // User ID binding signature - err := selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config) - if err != nil { - return err - } - t.Identities[uid.Id] = &Identity{ - Name: uid.Id, - UserId: uid, - SelfSignature: selfSignature, - Signatures: []*packet.Signature{selfSignature}, - } - return nil -} - -// AddSigningSubkey adds a signing keypair as a subkey to the Entity. -// If config is nil, sensible defaults will be used. -func (e *Entity) AddSigningSubkey(config *packet.Config) error { - creationTime := config.Now() - keyLifetimeSecs := config.KeyLifetime() - - subPrivRaw, err := newSigner(config) - if err != nil { - return err - } - sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw) - sub.IsSubkey = true - if config.V6() { - if err := sub.UpgradeToV6(); err != nil { - return err - } - } - - subkey := Subkey{ - PublicKey: &sub.PublicKey, - PrivateKey: sub, - } - subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config) - subkey.Sig.CreationTime = creationTime - subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs - subkey.Sig.FlagsValid = true - subkey.Sig.FlagSign = true - subkey.Sig.EmbeddedSignature = createSignaturePacket(subkey.PublicKey, packet.SigTypePrimaryKeyBinding, config) - subkey.Sig.EmbeddedSignature.CreationTime = creationTime - - err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, subkey.PrivateKey, config) - if err != nil { - return err - } - - err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) - if err != nil { - return err - } - - e.Subkeys = append(e.Subkeys, subkey) - return nil -} - -// AddEncryptionSubkey adds an encryption keypair as a subkey to the Entity. -// If config is nil, sensible defaults will be used. -func (e *Entity) AddEncryptionSubkey(config *packet.Config) error { - creationTime := config.Now() - keyLifetimeSecs := config.KeyLifetime() - return e.addEncryptionSubkey(config, creationTime, keyLifetimeSecs) -} - -func (e *Entity) addEncryptionSubkey(config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error { - subPrivRaw, err := newDecrypter(config) - if err != nil { - return err - } - sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw) - sub.IsSubkey = true - if config.V6() { - if err := sub.UpgradeToV6(); err != nil { - return err - } - } - - subkey := Subkey{ - PublicKey: &sub.PublicKey, - PrivateKey: sub, - } - subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config) - subkey.Sig.CreationTime = creationTime - subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs - subkey.Sig.FlagsValid = true - subkey.Sig.FlagEncryptStorage = true - subkey.Sig.FlagEncryptCommunications = true - - err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) - if err != nil { - return err - } - - e.Subkeys = append(e.Subkeys, subkey) - return nil -} - -// Generates a signing key -func newSigner(config *packet.Config) (signer interface{}, err error) { - switch config.PublicKeyAlgorithm() { - case packet.PubKeyAlgoRSA: - bits := config.RSAModulusBits() - if bits < 1024 { - return nil, errors.InvalidArgumentError("bits must be >= 1024") - } - if config != nil && len(config.RSAPrimes) >= 2 { - primes := config.RSAPrimes[0:2] - config.RSAPrimes = config.RSAPrimes[2:] - return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes) - } - return rsa.GenerateKey(config.Random(), bits) - case packet.PubKeyAlgoEdDSA: - if config.V6() { - // Implementations MUST NOT accept or generate v6 key material - // using the deprecated OIDs. - return nil, errors.InvalidArgumentError("EdDSALegacy cannot be used for v6 keys") - } - curve := ecc.FindEdDSAByGenName(string(config.CurveName())) - if curve == nil { - return nil, errors.InvalidArgumentError("unsupported curve") - } - - priv, err := eddsa.GenerateKey(config.Random(), curve) - if err != nil { - return nil, err - } - return priv, nil - case packet.PubKeyAlgoECDSA: - curve := ecc.FindECDSAByGenName(string(config.CurveName())) - if curve == nil { - return nil, errors.InvalidArgumentError("unsupported curve") - } - - priv, err := ecdsa.GenerateKey(config.Random(), curve) - if err != nil { - return nil, err - } - return priv, nil - case packet.PubKeyAlgoEd25519: - priv, err := ed25519.GenerateKey(config.Random()) - if err != nil { - return nil, err - } - return priv, nil - case packet.PubKeyAlgoEd448: - priv, err := ed448.GenerateKey(config.Random()) - if err != nil { - return nil, err - } - return priv, nil - default: - return nil, errors.InvalidArgumentError("unsupported public key algorithm") - } -} - -// Generates an encryption/decryption key -func newDecrypter(config *packet.Config) (decrypter interface{}, err error) { - switch config.PublicKeyAlgorithm() { - case packet.PubKeyAlgoRSA: - bits := config.RSAModulusBits() - if bits < 1024 { - return nil, errors.InvalidArgumentError("bits must be >= 1024") - } - if config != nil && len(config.RSAPrimes) >= 2 { - primes := config.RSAPrimes[0:2] - config.RSAPrimes = config.RSAPrimes[2:] - return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes) - } - return rsa.GenerateKey(config.Random(), bits) - case packet.PubKeyAlgoEdDSA, packet.PubKeyAlgoECDSA: - fallthrough // When passing EdDSA or ECDSA, we generate an ECDH subkey - case packet.PubKeyAlgoECDH: - if config.V6() && - (config.CurveName() == packet.Curve25519 || - config.CurveName() == packet.Curve448) { - // Implementations MUST NOT accept or generate v6 key material - // using the deprecated OIDs. - return nil, errors.InvalidArgumentError("ECDH with Curve25519/448 legacy cannot be used for v6 keys") - } - var kdf = ecdh.KDF{ - Hash: algorithm.SHA512, - Cipher: algorithm.AES256, - } - curve := ecc.FindECDHByGenName(string(config.CurveName())) - if curve == nil { - return nil, errors.InvalidArgumentError("unsupported curve") - } - return ecdh.GenerateKey(config.Random(), curve, kdf) - case packet.PubKeyAlgoEd25519, packet.PubKeyAlgoX25519: // When passing Ed25519, we generate an x25519 subkey - return x25519.GenerateKey(config.Random()) - case packet.PubKeyAlgoEd448, packet.PubKeyAlgoX448: // When passing Ed448, we generate an x448 subkey - return x448.GenerateKey(config.Random()) - default: - return nil, errors.InvalidArgumentError("unsupported public key algorithm") - } -} - -var bigOne = big.NewInt(1) - -// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the -// given bit size, using the given random source and pre-populated primes. -func generateRSAKeyWithPrimes(random io.Reader, nprimes int, bits int, prepopulatedPrimes []*big.Int) (*rsa.PrivateKey, error) { - priv := new(rsa.PrivateKey) - priv.E = 65537 - - if nprimes < 2 { - return nil, goerrors.New("generateRSAKeyWithPrimes: nprimes must be >= 2") - } - - if bits < 1024 { - return nil, goerrors.New("generateRSAKeyWithPrimes: bits must be >= 1024") - } - - primes := make([]*big.Int, nprimes) - -NextSetOfPrimes: - for { - todo := bits - // crypto/rand should set the top two bits in each prime. - // Thus each prime has the form - // p_i = 2^bitlen(p_i) × 0.11... (in base 2). - // And the product is: - // P = 2^todo × α - // where α is the product of nprimes numbers of the form 0.11... - // - // If α < 1/2 (which can happen for nprimes > 2), we need to - // shift todo to compensate for lost bits: the mean value of 0.11... - // is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2 - // will give good results. - if nprimes >= 7 { - todo += (nprimes - 2) / 5 - } - for i := 0; i < nprimes; i++ { - var err error - if len(prepopulatedPrimes) == 0 { - primes[i], err = rand.Prime(random, todo/(nprimes-i)) - if err != nil { - return nil, err - } - } else { - primes[i] = prepopulatedPrimes[0] - prepopulatedPrimes = prepopulatedPrimes[1:] - } - - todo -= primes[i].BitLen() - } - - // Make sure that primes is pairwise unequal. - for i, prime := range primes { - for j := 0; j < i; j++ { - if prime.Cmp(primes[j]) == 0 { - continue NextSetOfPrimes - } - } - } - - n := new(big.Int).Set(bigOne) - totient := new(big.Int).Set(bigOne) - pminus1 := new(big.Int) - for _, prime := range primes { - n.Mul(n, prime) - pminus1.Sub(prime, bigOne) - totient.Mul(totient, pminus1) - } - if n.BitLen() != bits { - // This should never happen for nprimes == 2 because - // crypto/rand should set the top two bits in each prime. - // For nprimes > 2 we hope it does not happen often. - continue NextSetOfPrimes - } - - priv.D = new(big.Int) - e := big.NewInt(int64(priv.E)) - ok := priv.D.ModInverse(e, totient) - - if ok != nil { - priv.Primes = primes - priv.N = n - break - } - } - - priv.Precompute() - return priv, nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go deleted file mode 100644 index a071353e..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go +++ /dev/null @@ -1,901 +0,0 @@ -// Copyright 2011 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 openpgp - -import ( - goerrors "errors" - "fmt" - "io" - "time" - - "github.com/ProtonMail/go-crypto/openpgp/armor" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/packet" -) - -// PublicKeyType is the armor type for a PGP public key. -var PublicKeyType = "PGP PUBLIC KEY BLOCK" - -// PrivateKeyType is the armor type for a PGP private key. -var PrivateKeyType = "PGP PRIVATE KEY BLOCK" - -// An Entity represents the components of an OpenPGP key: a primary public key -// (which must be a signing key), one or more identities claimed by that key, -// and zero or more subkeys, which may be encryption keys. -type Entity struct { - PrimaryKey *packet.PublicKey - PrivateKey *packet.PrivateKey - Identities map[string]*Identity // indexed by Identity.Name - Revocations []*packet.Signature - Subkeys []Subkey - SelfSignature *packet.Signature // Direct-key self signature of the PrimaryKey (contains primary key properties in v6) - Signatures []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures -} - -// An Identity represents an identity claimed by an Entity and zero or more -// assertions by other entities about that claim. -type Identity struct { - Name string // by convention, has the form "Full Name (comment) " - UserId *packet.UserId - SelfSignature *packet.Signature - Revocations []*packet.Signature - Signatures []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures -} - -// A Subkey is an additional public key in an Entity. Subkeys can be used for -// encryption. -type Subkey struct { - PublicKey *packet.PublicKey - PrivateKey *packet.PrivateKey - Sig *packet.Signature - Revocations []*packet.Signature -} - -// A Key identifies a specific public key in an Entity. This is either the -// Entity's primary key or a subkey. -type Key struct { - Entity *Entity - PublicKey *packet.PublicKey - PrivateKey *packet.PrivateKey - SelfSignature *packet.Signature - Revocations []*packet.Signature -} - -// A KeyRing provides access to public and private keys. -type KeyRing interface { - // KeysById returns the set of keys that have the given key id. - KeysById(id uint64) []Key - // KeysByIdAndUsage returns the set of keys with the given id - // that also meet the key usage given by requiredUsage. - // The requiredUsage is expressed as the bitwise-OR of - // packet.KeyFlag* values. - KeysByIdUsage(id uint64, requiredUsage byte) []Key - // DecryptionKeys returns all private keys that are valid for - // decryption. - DecryptionKeys() []Key -} - -// PrimaryIdentity returns an Identity, preferring non-revoked identities, -// identities marked as primary, or the latest-created identity, in that order. -func (e *Entity) PrimaryIdentity() *Identity { - var primaryIdentity *Identity - for _, ident := range e.Identities { - if shouldPreferIdentity(primaryIdentity, ident) { - primaryIdentity = ident - } - } - return primaryIdentity -} - -func shouldPreferIdentity(existingId, potentialNewId *Identity) bool { - if existingId == nil { - return true - } - - if len(existingId.Revocations) > len(potentialNewId.Revocations) { - return true - } - - if len(existingId.Revocations) < len(potentialNewId.Revocations) { - return false - } - - if existingId.SelfSignature == nil { - return true - } - - if existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId && - !(potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId) { - return false - } - - if !(existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId) && - potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId { - return true - } - - return potentialNewId.SelfSignature.CreationTime.After(existingId.SelfSignature.CreationTime) -} - -// EncryptionKey returns the best candidate Key for encrypting a message to the -// given Entity. -func (e *Entity) EncryptionKey(now time.Time) (Key, bool) { - // Fail to find any encryption key if the... - primarySelfSignature, primaryIdentity := e.PrimarySelfSignature() - if primarySelfSignature == nil || // no self-signature found - e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired - e.Revoked(now) || // primary key has been revoked - primarySelfSignature.SigExpired(now) || // user ID or or direct self-signature has expired - (primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys) - return Key{}, false - } - - // Iterate the keys to find the newest, unexpired one - candidateSubkey := -1 - var maxTime time.Time - for i, subkey := range e.Subkeys { - if subkey.Sig.FlagsValid && - subkey.Sig.FlagEncryptCommunications && - subkey.PublicKey.PubKeyAlgo.CanEncrypt() && - !subkey.PublicKey.KeyExpired(subkey.Sig, now) && - !subkey.Sig.SigExpired(now) && - !subkey.Revoked(now) && - (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { - candidateSubkey = i - maxTime = subkey.Sig.CreationTime - } - } - - if candidateSubkey != -1 { - subkey := e.Subkeys[candidateSubkey] - return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true - } - - // If we don't have any subkeys for encryption and the primary key - // is marked as OK to encrypt with, then we can use it. - if primarySelfSignature.FlagsValid && primarySelfSignature.FlagEncryptCommunications && - e.PrimaryKey.PubKeyAlgo.CanEncrypt() { - return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true - } - - return Key{}, false -} - -// CertificationKey return the best candidate Key for certifying a key with this -// Entity. -func (e *Entity) CertificationKey(now time.Time) (Key, bool) { - return e.CertificationKeyById(now, 0) -} - -// CertificationKeyById return the Key for key certification with this -// Entity and keyID. -func (e *Entity) CertificationKeyById(now time.Time, id uint64) (Key, bool) { - return e.signingKeyByIdUsage(now, id, packet.KeyFlagCertify) -} - -// SigningKey return the best candidate Key for signing a message with this -// Entity. -func (e *Entity) SigningKey(now time.Time) (Key, bool) { - return e.SigningKeyById(now, 0) -} - -// SigningKeyById return the Key for signing a message with this -// Entity and keyID. -func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) { - return e.signingKeyByIdUsage(now, id, packet.KeyFlagSign) -} - -func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key, bool) { - // Fail to find any signing key if the... - primarySelfSignature, primaryIdentity := e.PrimarySelfSignature() - if primarySelfSignature == nil || // no self-signature found - e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired - e.Revoked(now) || // primary key has been revoked - primarySelfSignature.SigExpired(now) || // user ID or direct self-signature has expired - (primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys) - return Key{}, false - } - - // Iterate the keys to find the newest, unexpired one - candidateSubkey := -1 - var maxTime time.Time - for idx, subkey := range e.Subkeys { - if subkey.Sig.FlagsValid && - (flags&packet.KeyFlagCertify == 0 || subkey.Sig.FlagCertify) && - (flags&packet.KeyFlagSign == 0 || subkey.Sig.FlagSign) && - subkey.PublicKey.PubKeyAlgo.CanSign() && - !subkey.PublicKey.KeyExpired(subkey.Sig, now) && - !subkey.Sig.SigExpired(now) && - !subkey.Revoked(now) && - (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) && - (id == 0 || subkey.PublicKey.KeyId == id) { - candidateSubkey = idx - maxTime = subkey.Sig.CreationTime - } - } - - if candidateSubkey != -1 { - subkey := e.Subkeys[candidateSubkey] - return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true - } - - // If we don't have any subkeys for signing and the primary key - // is marked as OK to sign with, then we can use it. - if primarySelfSignature.FlagsValid && - (flags&packet.KeyFlagCertify == 0 || primarySelfSignature.FlagCertify) && - (flags&packet.KeyFlagSign == 0 || primarySelfSignature.FlagSign) && - e.PrimaryKey.PubKeyAlgo.CanSign() && - (id == 0 || e.PrimaryKey.KeyId == id) { - return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true - } - - // No keys with a valid Signing Flag or no keys matched the id passed in - return Key{}, false -} - -func revoked(revocations []*packet.Signature, now time.Time) bool { - for _, revocation := range revocations { - if revocation.RevocationReason != nil && *revocation.RevocationReason == packet.KeyCompromised { - // If the key is compromised, the key is considered revoked even before the revocation date. - return true - } - if !revocation.SigExpired(now) { - return true - } - } - return false -} - -// Revoked returns whether the entity has any direct key revocation signatures. -// Note that third-party revocation signatures are not supported. -// Note also that Identity and Subkey revocation should be checked separately. -func (e *Entity) Revoked(now time.Time) bool { - return revoked(e.Revocations, now) -} - -// EncryptPrivateKeys encrypts all non-encrypted keys in the entity with the same key -// derived from the provided passphrase. Public keys and dummy keys are ignored, -// and don't cause an error to be returned. -func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) error { - var keysToEncrypt []*packet.PrivateKey - // Add entity private key to encrypt. - if e.PrivateKey != nil && !e.PrivateKey.Dummy() && !e.PrivateKey.Encrypted { - keysToEncrypt = append(keysToEncrypt, e.PrivateKey) - } - - // Add subkeys to encrypt. - for _, sub := range e.Subkeys { - if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && !sub.PrivateKey.Encrypted { - keysToEncrypt = append(keysToEncrypt, sub.PrivateKey) - } - } - return packet.EncryptPrivateKeys(keysToEncrypt, passphrase, config) -} - -// DecryptPrivateKeys decrypts all encrypted keys in the entity with the given passphrase. -// Avoids recomputation of similar s2k key derivations. Public keys and dummy keys are ignored, -// and don't cause an error to be returned. -func (e *Entity) DecryptPrivateKeys(passphrase []byte) error { - var keysToDecrypt []*packet.PrivateKey - // Add entity private key to decrypt. - if e.PrivateKey != nil && !e.PrivateKey.Dummy() && e.PrivateKey.Encrypted { - keysToDecrypt = append(keysToDecrypt, e.PrivateKey) - } - - // Add subkeys to decrypt. - for _, sub := range e.Subkeys { - if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && sub.PrivateKey.Encrypted { - keysToDecrypt = append(keysToDecrypt, sub.PrivateKey) - } - } - return packet.DecryptPrivateKeys(keysToDecrypt, passphrase) -} - -// Revoked returns whether the identity has been revoked by a self-signature. -// Note that third-party revocation signatures are not supported. -func (i *Identity) Revoked(now time.Time) bool { - return revoked(i.Revocations, now) -} - -// Revoked returns whether the subkey has been revoked by a self-signature. -// Note that third-party revocation signatures are not supported. -func (s *Subkey) Revoked(now time.Time) bool { - return revoked(s.Revocations, now) -} - -// Revoked returns whether the key or subkey has been revoked by a self-signature. -// Note that third-party revocation signatures are not supported. -// Note also that Identity revocation should be checked separately. -// Normally, it's not necessary to call this function, except on keys returned by -// KeysById or KeysByIdUsage. -func (key *Key) Revoked(now time.Time) bool { - return revoked(key.Revocations, now) -} - -// An EntityList contains one or more Entities. -type EntityList []*Entity - -// KeysById returns the set of keys that have the given key id. -func (el EntityList) KeysById(id uint64) (keys []Key) { - for _, e := range el { - if e.PrimaryKey.KeyId == id { - selfSig, _ := e.PrimarySelfSignature() - keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, e.Revocations}) - } - - for _, subKey := range e.Subkeys { - if subKey.PublicKey.KeyId == id { - keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations}) - } - } - } - return -} - -// KeysByIdAndUsage returns the set of keys with the given id that also meet -// the key usage given by requiredUsage. The requiredUsage is expressed as -// the bitwise-OR of packet.KeyFlag* values. -func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { - for _, key := range el.KeysById(id) { - if requiredUsage != 0 { - if key.SelfSignature == nil || !key.SelfSignature.FlagsValid { - continue - } - - var usage byte - if key.SelfSignature.FlagCertify { - usage |= packet.KeyFlagCertify - } - if key.SelfSignature.FlagSign { - usage |= packet.KeyFlagSign - } - if key.SelfSignature.FlagEncryptCommunications { - usage |= packet.KeyFlagEncryptCommunications - } - if key.SelfSignature.FlagEncryptStorage { - usage |= packet.KeyFlagEncryptStorage - } - if usage&requiredUsage != requiredUsage { - continue - } - } - - keys = append(keys, key) - } - return -} - -// DecryptionKeys returns all private keys that are valid for decryption. -func (el EntityList) DecryptionKeys() (keys []Key) { - for _, e := range el { - for _, subKey := range e.Subkeys { - if subKey.PrivateKey != nil && subKey.Sig.FlagsValid && (subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { - keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations}) - } - } - } - return -} - -// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. -func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { - block, err := armor.Decode(r) - if err == io.EOF { - return nil, errors.InvalidArgumentError("no armored data found") - } - if err != nil { - return nil, err - } - if block.Type != PublicKeyType && block.Type != PrivateKeyType { - return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) - } - - return ReadKeyRing(block.Body) -} - -// ReadKeyRing reads one or more public/private keys. Unsupported keys are -// ignored as long as at least a single valid key is found. -func ReadKeyRing(r io.Reader) (el EntityList, err error) { - packets := packet.NewReader(r) - var lastUnsupportedError error - - for { - var e *Entity - e, err = ReadEntity(packets) - if err != nil { - // TODO: warn about skipped unsupported/unreadable keys - if _, ok := err.(errors.UnsupportedError); ok { - lastUnsupportedError = err - err = readToNextPublicKey(packets) - } else if _, ok := err.(errors.StructuralError); ok { - // Skip unreadable, badly-formatted keys - lastUnsupportedError = err - err = readToNextPublicKey(packets) - } - if err == io.EOF { - err = nil - break - } - if err != nil { - el = nil - break - } - } else { - el = append(el, e) - } - } - - if len(el) == 0 && err == nil { - err = lastUnsupportedError - } - return -} - -// readToNextPublicKey reads packets until the start of the entity and leaves -// the first packet of the new entity in the Reader. -func readToNextPublicKey(packets *packet.Reader) (err error) { - var p packet.Packet - for { - p, err = packets.Next() - if err == io.EOF { - return - } else if err != nil { - if _, ok := err.(errors.UnsupportedError); ok { - continue - } - return - } - - if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { - packets.Unread(p) - return - } - } -} - -// ReadEntity reads an entity (public key, identities, subkeys etc) from the -// given Reader. -func ReadEntity(packets *packet.Reader) (*Entity, error) { - e := new(Entity) - e.Identities = make(map[string]*Identity) - - p, err := packets.Next() - if err != nil { - return nil, err - } - - var ok bool - if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { - if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { - packets.Unread(p) - return nil, errors.StructuralError("first packet was not a public/private key") - } - e.PrimaryKey = &e.PrivateKey.PublicKey - } - - if !e.PrimaryKey.PubKeyAlgo.CanSign() { - return nil, errors.StructuralError("primary key cannot be used for signatures") - } - - var revocations []*packet.Signature - var directSignatures []*packet.Signature -EachPacket: - for { - p, err := packets.Next() - if err == io.EOF { - break - } else if err != nil { - return nil, err - } - - switch pkt := p.(type) { - case *packet.UserId: - if err := addUserID(e, packets, pkt); err != nil { - return nil, err - } - case *packet.Signature: - if pkt.SigType == packet.SigTypeKeyRevocation { - revocations = append(revocations, pkt) - } else if pkt.SigType == packet.SigTypeDirectSignature { - directSignatures = append(directSignatures, pkt) - } - // Else, ignoring the signature as it does not follow anything - // we would know to attach it to. - case *packet.PrivateKey: - if !pkt.IsSubkey { - packets.Unread(p) - break EachPacket - } - err = addSubkey(e, packets, &pkt.PublicKey, pkt) - if err != nil { - return nil, err - } - case *packet.PublicKey: - if !pkt.IsSubkey { - packets.Unread(p) - break EachPacket - } - err = addSubkey(e, packets, pkt, nil) - if err != nil { - return nil, err - } - default: - // we ignore unknown packets. - } - } - - if len(e.Identities) == 0 && e.PrimaryKey.Version < 6 { - return nil, errors.StructuralError(fmt.Sprintf("v%d entity without any identities", e.PrimaryKey.Version)) - } - - // An implementation MUST ensure that a valid direct-key signature is present before using a v6 key. - if e.PrimaryKey.Version == 6 { - if len(directSignatures) == 0 { - return nil, errors.StructuralError("v6 entity without a valid direct-key signature") - } - // Select main direct key signature. - var mainDirectKeySelfSignature *packet.Signature - for _, directSignature := range directSignatures { - if directSignature.SigType == packet.SigTypeDirectSignature && - directSignature.CheckKeyIdOrFingerprint(e.PrimaryKey) && - (mainDirectKeySelfSignature == nil || - directSignature.CreationTime.After(mainDirectKeySelfSignature.CreationTime)) { - mainDirectKeySelfSignature = directSignature - } - } - if mainDirectKeySelfSignature == nil { - return nil, errors.StructuralError("no valid direct-key self-signature for v6 primary key found") - } - // Check that the main self-signature is valid. - err = e.PrimaryKey.VerifyDirectKeySignature(mainDirectKeySelfSignature) - if err != nil { - return nil, errors.StructuralError("invalid direct-key self-signature for v6 primary key") - } - e.SelfSignature = mainDirectKeySelfSignature - e.Signatures = directSignatures - } - - for _, revocation := range revocations { - err = e.PrimaryKey.VerifyRevocationSignature(revocation) - if err == nil { - e.Revocations = append(e.Revocations, revocation) - } else { - // TODO: RFC 4880 5.2.3.15 defines revocation keys. - return nil, errors.StructuralError("revocation signature signed by alternate key") - } - } - - return e, nil -} - -func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error { - // Make a new Identity object, that we might wind up throwing away. - // We'll only add it if we get a valid self-signature over this - // userID. - identity := new(Identity) - identity.Name = pkt.Id - identity.UserId = pkt - - for { - p, err := packets.Next() - if err == io.EOF { - break - } else if err != nil { - return err - } - - sig, ok := p.(*packet.Signature) - if !ok { - packets.Unread(p) - break - } - - if sig.SigType != packet.SigTypeGenericCert && - sig.SigType != packet.SigTypePersonaCert && - sig.SigType != packet.SigTypeCasualCert && - sig.SigType != packet.SigTypePositiveCert && - sig.SigType != packet.SigTypeCertificationRevocation { - return errors.StructuralError("user ID signature with wrong type") - } - - if sig.CheckKeyIdOrFingerprint(e.PrimaryKey) { - if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { - return errors.StructuralError("user ID self-signature invalid: " + err.Error()) - } - if sig.SigType == packet.SigTypeCertificationRevocation { - identity.Revocations = append(identity.Revocations, sig) - } else if identity.SelfSignature == nil || sig.CreationTime.After(identity.SelfSignature.CreationTime) { - identity.SelfSignature = sig - } - identity.Signatures = append(identity.Signatures, sig) - e.Identities[pkt.Id] = identity - } else { - identity.Signatures = append(identity.Signatures, sig) - } - } - - return nil -} - -func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { - var subKey Subkey - subKey.PublicKey = pub - subKey.PrivateKey = priv - - for { - p, err := packets.Next() - if err == io.EOF { - break - } else if err != nil { - return errors.StructuralError("subkey signature invalid: " + err.Error()) - } - - sig, ok := p.(*packet.Signature) - if !ok { - packets.Unread(p) - break - } - - if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation { - return errors.StructuralError("subkey signature with wrong type") - } - - if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil { - return errors.StructuralError("subkey signature invalid: " + err.Error()) - } - - switch sig.SigType { - case packet.SigTypeSubkeyRevocation: - subKey.Revocations = append(subKey.Revocations, sig) - case packet.SigTypeSubkeyBinding: - if subKey.Sig == nil || sig.CreationTime.After(subKey.Sig.CreationTime) { - subKey.Sig = sig - } - } - } - - if subKey.Sig == nil { - return errors.StructuralError("subkey packet not followed by signature") - } - - e.Subkeys = append(e.Subkeys, subKey) - - return nil -} - -// SerializePrivate serializes an Entity, including private key material, but -// excluding signatures from other entities, to the given Writer. -// Identities and subkeys are re-signed in case they changed since NewEntry. -// If config is nil, sensible defaults will be used. -func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { - if e.PrivateKey.Dummy() { - return errors.ErrDummyPrivateKey("dummy private key cannot re-sign identities") - } - return e.serializePrivate(w, config, true) -} - -// SerializePrivateWithoutSigning serializes an Entity, including private key -// material, but excluding signatures from other entities, to the given Writer. -// Self-signatures of identities and subkeys are not re-signed. This is useful -// when serializing GNU dummy keys, among other things. -// If config is nil, sensible defaults will be used. -func (e *Entity) SerializePrivateWithoutSigning(w io.Writer, config *packet.Config) (err error) { - return e.serializePrivate(w, config, false) -} - -func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign bool) (err error) { - if e.PrivateKey == nil { - return goerrors.New("openpgp: private key is missing") - } - err = e.PrivateKey.Serialize(w) - if err != nil { - return - } - for _, revocation := range e.Revocations { - err := revocation.Serialize(w) - if err != nil { - return err - } - } - for _, directSignature := range e.Signatures { - err := directSignature.Serialize(w) - if err != nil { - return err - } - } - for _, ident := range e.Identities { - err = ident.UserId.Serialize(w) - if err != nil { - return - } - if reSign { - if ident.SelfSignature == nil { - return goerrors.New("openpgp: can't re-sign identity without valid self-signature") - } - err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) - if err != nil { - return - } - } - for _, sig := range ident.Signatures { - err = sig.Serialize(w) - if err != nil { - return err - } - } - } - for _, subkey := range e.Subkeys { - err = subkey.PrivateKey.Serialize(w) - if err != nil { - return - } - if reSign { - err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) - if err != nil { - return - } - if subkey.Sig.EmbeddedSignature != nil { - err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, - subkey.PrivateKey, config) - if err != nil { - return - } - } - } - for _, revocation := range subkey.Revocations { - err := revocation.Serialize(w) - if err != nil { - return err - } - } - err = subkey.Sig.Serialize(w) - if err != nil { - return - } - } - return nil -} - -// Serialize writes the public part of the given Entity to w, including -// signatures from other entities. No private key material will be output. -func (e *Entity) Serialize(w io.Writer) error { - err := e.PrimaryKey.Serialize(w) - if err != nil { - return err - } - for _, revocation := range e.Revocations { - err := revocation.Serialize(w) - if err != nil { - return err - } - } - for _, directSignature := range e.Signatures { - err := directSignature.Serialize(w) - if err != nil { - return err - } - } - for _, ident := range e.Identities { - err = ident.UserId.Serialize(w) - if err != nil { - return err - } - for _, sig := range ident.Signatures { - err = sig.Serialize(w) - if err != nil { - return err - } - } - } - for _, subkey := range e.Subkeys { - err = subkey.PublicKey.Serialize(w) - if err != nil { - return err - } - for _, revocation := range subkey.Revocations { - err := revocation.Serialize(w) - if err != nil { - return err - } - } - err = subkey.Sig.Serialize(w) - if err != nil { - return err - } - } - return nil -} - -// SignIdentity adds a signature to e, from signer, attesting that identity is -// associated with e. The provided identity must already be an element of -// e.Identities and the private key of signer must have been decrypted if -// necessary. -// If config is nil, sensible defaults will be used. -func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { - certificationKey, ok := signer.CertificationKey(config.Now()) - if !ok { - return errors.InvalidArgumentError("no valid certification key found") - } - - if certificationKey.PrivateKey.Encrypted { - return errors.InvalidArgumentError("signing Entity's private key must be decrypted") - } - - ident, ok := e.Identities[identity] - if !ok { - return errors.InvalidArgumentError("given identity string not found in Entity") - } - - sig := createSignaturePacket(certificationKey.PublicKey, packet.SigTypeGenericCert, config) - - signingUserID := config.SigningUserId() - if signingUserID != "" { - if _, ok := signer.Identities[signingUserID]; !ok { - return errors.InvalidArgumentError("signer identity string not found in signer Entity") - } - sig.SignerUserId = &signingUserID - } - - if err := sig.SignUserId(identity, e.PrimaryKey, certificationKey.PrivateKey, config); err != nil { - return err - } - ident.Signatures = append(ident.Signatures, sig) - return nil -} - -// RevokeKey generates a key revocation signature (packet.SigTypeKeyRevocation) with the -// specified reason code and text (RFC4880 section-5.2.3.23). -// If config is nil, sensible defaults will be used. -func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error { - revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeKeyRevocation, config) - revSig.RevocationReason = &reason - revSig.RevocationReasonText = reasonText - - if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil { - return err - } - e.Revocations = append(e.Revocations, revSig) - return nil -} - -// RevokeSubkey generates a subkey revocation signature (packet.SigTypeSubkeyRevocation) for -// a subkey with the specified reason code and text (RFC4880 section-5.2.3.23). -// If config is nil, sensible defaults will be used. -func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error { - if err := e.PrimaryKey.VerifyKeySignature(sk.PublicKey, sk.Sig); err != nil { - return errors.InvalidArgumentError("given subkey is not associated with this key") - } - - revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyRevocation, config) - revSig.RevocationReason = &reason - revSig.RevocationReasonText = reasonText - - if err := revSig.RevokeSubkey(sk.PublicKey, e.PrivateKey, config); err != nil { - return err - } - - sk.Revocations = append(sk.Revocations, revSig) - return nil -} - -func (e *Entity) primaryDirectSignature() *packet.Signature { - return e.SelfSignature -} - -// PrimarySelfSignature searches the entity for the self-signature that stores key preferences. -// For V4 keys, returns the self-signature of the primary identity, and the identity. -// For V6 keys, returns the latest valid direct-key self-signature, and no identity (nil). -// This self-signature is to be used to check the key expiration, -// algorithm preferences, and so on. -func (e *Entity) PrimarySelfSignature() (*packet.Signature, *Identity) { - if e.PrimaryKey.Version == 6 { - return e.primaryDirectSignature(), nil - } - primaryIdentity := e.PrimaryIdentity() - if primaryIdentity == nil { - return nil, nil - } - return primaryIdentity.SelfSignature, primaryIdentity -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go deleted file mode 100644 index 108fd096..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go +++ /dev/null @@ -1,538 +0,0 @@ -package openpgp - -const expiringKeyHex = "c6c04d0451d0c680010800abbb021fd03ffc4e96618901180c3fdcb060ee69eeead97b91256d11420d80b5f1b51930248044130bd300605cf8a05b7a40d3d8cfb0a910be2e3db50dcd50a9c54064c2a5550801daa834ff4480b33d3d3ca495ff8a4e84a886977d17d998f881241a874083d8b995beab555b6d22b8a4817ab17ac3e7304f7d4d2c05c495fb2218348d3bc13651db1d92732e368a9dd7dcefa6eddff30b94706a9aaee47e9d39321460b740c59c6fc3c2fd8ab6c0fb868cb87c0051f0321301fe0f0e1820b15e7fb7063395769b525005c7e30a7ce85984f5cac00504e7b4fdc45d74958de8388436fd5c7ba9ea121f1c851b5911dd1b47a14d81a09e92ef37721e2325b6790011010001cd00c2c07b041001080025050251d0c680050900278d00060b09070803020415080a0203160201021901021b03021e01000a0910e7b484133a890a35ae4b0800a1beb82e7f28eaf5273d6af9d3391314f6280b2b624eaca2851f89a9ebcaf80ac589ebd509f168bc4322106ca2e2ce77a76e071a3c7444787d65216b5f05e82c77928860b92aace3b7d0327db59492f422eb9dfab7249266d37429870b091a98aba8724c2259ebf8f85093f21255eafa75aa841e31d94f2ac891b9755fed455e539044ee69fc47950b80e003fc9f298d695660f28329eaa38037c367efde1727458e514faf990d439a21461b719edaddf9296d3d0647b43ca56cb8dbf63b4fcf8b9968e7928c463470fab3b98e44d0d95645062f94b2d04fe56bd52822b71934db8ce845622c40b92fcbe765a142e7f38b61a6aa9606c8e8858dcd3b6eb1894acec04d0451d1f06b01080088bea67444e1789390e7c0335c86775502d58ec783d99c8ef4e06de235ed3dd4b0467f6f358d818c7d8989d43ec6d69fcbc8c32632d5a1b605e3fa8e41d695fcdcaa535936cd0157f9040dce362519803b908eafe838bb13216c885c6f93e9e8d5745607f0d062322085d6bdc760969149a8ff8dd9f5c18d9bfe2e6f63a06e17694cf1f67587c6fb70e9aebf90ffc528ca3b615ac7c9d4a21ea4f7c06f2e98fbbd90a859b8608bf9ea638e3a54289ce44c283110d0c45fa458de6251cd6e7baf71f80f12c8978340490fd90c92b81736ae902ed958e478dceae2835953d189c45d182aff02ea2be61b81d8e94430f041d638647b43e2fcb45fd512fbf5068b810011010001c2c06504180108000f050251d1f06b050900081095021b0c000a0910e7b484133a890a35e63407fe2ec88d6d1e6c9ce7553ece0cb2524747217bad29f251d33df84599ffcc900141a355abd62126800744068a5e05dc167056aa9205273dc7765a2ed49db15c2a83b8d6e6429c902136f1e12229086c1c10c0053242c2a4ae1930db58163387a48cad64607ff2153c320e42843dec28e3fce90e7399d63ac0affa2fee1f0adc0953c89eb3f46ef1d6c04328ed13b491669d5120a3782e3ffb7c69575fb77eebd108794f4dda9d34be2bae57e8e59ec8ebfda2f6f06104b2321be408ea146e2db482b00c5055c8618de36ac9716f80da2617e225556d0fce61b01c8cea2d1e0ea982c31711060ca370f2739366e1e708f38405d784b49d16a26cf62d152eae734327cec04d0451d1f07b010800d5af91c5e7c2fd8951c8d254eab0c97cdcb66822f868b79b78c366255059a68fd74ebca9adb9b970cd9e586690e6e0756705432306878c897b10a4b4ca0005966f99ac8fa4e6f9caf54bf8e53844544beee9872a7ac64c119cf1393d96e674254b661f61ee975633d0e8a8672531edb6bb8e211204e7754a9efa802342118eee850beea742bac95a3f706cc2024cf6037a308bb68162b2f53b9a6346a96e6d31871a2456186e24a1c7a82b82ac04afdfd57cd7fb9ba77a9c760d40b76a170f7be525e5fb6a9848cc726e806187710d9b190387df28700f321f988a392899f93815cc937f309129eb94d5299c5547cb2c085898e6639496e70d746c9d3fb9881d0011010001c2c06504180108000f050251d1f07b050900266305021b0c000a0910e7b484133a890a35bff207fd10dfe8c4a6ea1dd30568012b6fd6891a763c87ad0f7a1d112aad9e8e3239378a3b85588c235865bac2e614348cb4f216d7217f53b3ef48c192e0a4d31d64d7bfa5faccf21155965fa156e887056db644a05ad08a85cc6152d1377d9e37b46f4ff462bbe68ace2dc586ef90070314576c985d8037c2ba63f0a7dc17a62e15bd77e88bc61d9d00858979709f12304264a4cf4225c5cf86f12c8e19486cb9cdcc69f18f027e5f16f4ca8b50e28b3115eaff3a345acd21f624aef81f6ede515c1b55b26b84c1e32264754eab672d5489b287e7277ea855e0a5ff2aa9e8b8c76d579a964ec225255f4d57bf66639ccb34b64798846943e162a41096a7002ca21c7f56" -const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" -const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" -const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011" - -const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Charset: UTF-8 - -mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY -ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG -zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 -QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ -QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo -9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu -Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ -dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R -JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL -ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew -RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW -/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu -yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv -2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR -bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL -C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP -WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y -MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA -EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ -MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N -1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm -+ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N -lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW -CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF -4artDmrG -=7FfJ ------END PGP PUBLIC KEY BLOCK-----` - -const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY -ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG -zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 -QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ -QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo -9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu -Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ -dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R -JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL -ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew -RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW -/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu -yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAIINDqlj7X6jYKc6DjwrOkjQ -UIRWbQQar0LwmNilehmt70g5DCL1SYm9q4LcgJJ2Nhxj0/5qqsYib50OSWMcKeEe -iRXpXzv1ObpcQtI5ithp0gR53YPXBib80t3bUzomQ5UyZqAAHzMp3BKC54/vUrSK -FeRaxDzNLrCeyI00+LHNUtwghAqHvdNcsIf8VRumK8oTm3RmDh0TyjASWYbrt9c8 -R1Um3zuoACOVy+mEIgIzsfHq0u7dwYwJB5+KeM7ZLx+HGIYdUYzHuUE1sLwVoELh -+SHIGHI1HDicOjzqgajShuIjj5hZTyQySVprrsLKiXS6NEwHAP20+XjayJ/R3tEA -EQEAAYkCPgQYAQIBKAUCU5ygeQIbAsBdIAQZAQIABgUCU5ygeQAKCRCpVlnFZmhO -52RJB/9uD1MSa0wjY6tHOIgquZcP3bHBvHmrHNMw9HR2wRCMO91ZkhrpdS3ZHtgb -u3/55etj0FdvDo1tb8P8FGSVtO5Vcwf5APM8sbbqoi8L951Q3i7qt847lfhu6sMl -w0LWFvPTOLHrliZHItPRjOltS1WAWfr2jUYhsU9ytaDAJmvf9DujxEOsN5G1YJep -54JCKVCkM/y585Zcnn+yxk/XwqoNQ0/iJUT9qRrZWvoeasxhl1PQcwihCwss44A+ -YXaAt3hbk+6LEQuZoYS73yR3WHj+42tfm7YxRGeubXfgCEz/brETEWXMh4pe0vCL -bfWrmfSPq2rDegYcAybxRQz0lF8PAAoJEO3UDQUIHpI/exkH/0vQfdHA8g/N4T6E -i6b1CUVBAkvtdJpCATZjWPhXmShOw62gkDw306vHPilL4SCvEEi4KzG72zkp6VsB -DSRcpxCwT4mHue+duiy53/aRMtSJ+vDfiV1Vhq+3sWAck/yUtfDU9/u4eFaiNok1 -8/Gd7reyuZt5CiJnpdPpjCwelK21l2w7sHAnJF55ITXdOxI8oG3BRKufz0z5lyDY -s2tXYmhhQIggdgelN8LbcMhWs/PBbtUr6uZlNJG2lW1yscD4aI529VjwJlCeo745 -U7pO4eF05VViUJ2mmfoivL3tkhoTUWhx8xs8xCUcCg8DoEoSIhxtOmoTPR22Z9BL -6LCg2mg= -=Dhm4 ------END PGP PUBLIC KEY BLOCK-----` - -const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo -7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom -lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0 -E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC -CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw -6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH -7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv -X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7 -GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl -y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw -R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW -CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+ -LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO -aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx -yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl -BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr -Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK -CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp -C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ -SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/ -MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70= -=vtbN ------END PGP PUBLIC KEY BLOCK-----` - -const revokedUserIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -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 -7qTZOahrETw= -=IKnw ------END PGP PUBLIC KEY BLOCK-----` - -const keyWithFirstUserIDRevoked = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Version: OpenPGP.js v4.10.10 -Comment: https://openpgpjs.org - -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 -=+2T8 ------END PGP PUBLIC KEY BLOCK----- -` - -const keyWithOnlyUserIDRevoked = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -mDMEYYwB7RYJKwYBBAHaRw8BAQdARimqhPPzyGAXmfQJjcqM1QVPzLtURJSzNVll -JV4tEaW0KVJldm9rZWQgUHJpbWFyeSBVc2VyIElEIDxyZXZva2VkQGtleS5jb20+ -iHgEMBYIACAWIQSpyJZAXYqVEFkjyKutFcS0yeB0LQUCYYwCtgIdAAAKCRCtFcS0 -yeB0LbSsAQD8OYMaaBjrdzzpwIkP1stgmPd4/kzN/ZG28Ywl6a5F5QEA5Xg7aq4e -/t6Fsb4F5iqB956kSPe6YJrikobD/tBbMwSIkAQTFggAOBYhBKnIlkBdipUQWSPI -q60VxLTJ4HQtBQJhjAHtAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEK0V -xLTJ4HQtBaoBAPZL7luTCji+Tqhn7XNfFE/0QIahCt8k9wfO1cGlB3inAQDf8Tzw -ZGR5fNluUcNoVxQT7bUSFStbaGo3k0BaOYPbCLg4BGGMAe0SCisGAQQBl1UBBQEB -B0DLwSpveSrbIO/IVZD13yrs1XuB3FURZUnafGrRq7+jUAMBCAeIeAQYFggAIBYh -BKnIlkBdipUQWSPIq60VxLTJ4HQtBQJhjAHtAhsMAAoJEK0VxLTJ4HQtZ1oA/j9u -8+p3xTNzsmabTL6BkNbMeB/RUKCrlm6woM6AV+vxAQCcXTn3JC2sNoNrLoXuVzaA -mcG3/TwG5GSQUUPkrDsGDA== -=mFWy ------END PGP PUBLIC KEY BLOCK----- -` - -const keyWithSubKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -mI0EWyKwKQEEALwXhKBnyaaNFeK3ljfc/qn9X/QFw+28EUfgZPHjRmHubuXLE2uR -s3ZoSXY2z7Dkv+NyHYMt8p+X8q5fR7JvUjK2XbPyKoiJVnHINll83yl67DaWfKNL -EjNoO0kIfbXfCkZ7EG6DL+iKtuxniGTcnGT47e+HJSqb/STpLMnWwXjBABEBAAG0 -I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQQ/ -lRafP/p9PytHbwxMvYJsOQdOOAUCWyKwKQIbAwULCQgHAwUVCgkICwUWAgMBAAIe -AQIXgAAKCRBMvYJsOQdOOOsFBAC62mXww8XuqvYLcVOvHkWLT6mhxrQOJXnlfpn7 -2uBV9CMhoG/Ycd43NONsJrB95Apr9TDIqWnVszNbqPCuBhZQSGLdbiDKjxnCWBk0 -69qv4RNtkpOhYB7jK4s8F5oQZqId6JasT/PmJTH92mhBYhhTQr0GYFuPX2UJdkw9 -Sn9C67iNBFsisDUBBAC3A+Yo9lgCnxi/pfskyLrweYif6kIXWLAtLTsM6g/6jt7b -wTrknuCPyTv0QKGXsAEe/cK/Xq3HvX9WfXPGIHc/X56ZIsHQ+RLowbZV/Lhok1IW -FAuQm8axr/by80cRwFnzhfPc/ukkAq2Qyj4hLsGblu6mxeAhzcp8aqmWOO2H9QAR -AQABiLYEKAEKACAWIQQ/lRafP/p9PytHbwxMvYJsOQdOOAUCWyK16gIdAAAKCRBM -vYJsOQdOOB1vA/4u4uLONsE+2GVOyBsHyy7uTdkuxaR9b54A/cz6jT/tzUbeIzgx -22neWhgvIEghnUZd0vEyK9k1wy5vbDlEo6nKzHso32N1QExGr5upRERAxweDxGOj -7luDwNypI7QcifE64lS/JmlnunwRCdRWMKc0Fp+7jtRc5mpwyHN/Suf5RokBagQY -AQoAIBYhBD+VFp8/+n0/K0dvDEy9gmw5B044BQJbIrA1AhsCAL8JEEy9gmw5B044 -tCAEGQEKAB0WIQSNdnkaWY6t62iX336UXbGvYdhXJwUCWyKwNQAKCRCUXbGvYdhX -JxJSA/9fCPHP6sUtGF1o3G1a3yvOUDGr1JWcct9U+QpbCt1mZoNopCNDDQAJvDWl -mvDgHfuogmgNJRjOMznvahbF+wpTXmB7LS0SK412gJzl1fFIpK4bgnhu0TwxNsO1 -8UkCZWqxRMgcNUn9z6XWONK8dgt5JNvHSHrwF4CxxwjL23AAtK+FA/UUoi3U4kbC -0XnSr1Sl+mrzQi1+H7xyMe7zjqe+gGANtskqexHzwWPUJCPZ5qpIa2l8ghiUim6b -4ymJ+N8/T8Yva1FaPEqfMzzqJr8McYFm0URioXJPvOAlRxdHPteZ0qUopt/Jawxl -Xt6B9h1YpeLoJwjwsvbi98UTRs0jXwoY -=3fWu ------END PGP PUBLIC KEY BLOCK-----` - -const keyWithSubKeyAndBadSelfSigOrder = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -mI0EWyLLDQEEAOqIOpJ/ha1OYAGduu9tS3rBz5vyjbNgJO4sFveEM0mgsHQ0X9/L -plonW+d0gRoO1dhJ8QICjDAc6+cna1DE3tEb5m6JtQ30teLZuqrR398Cf6w7NNVz -r3lrlmnH9JaKRuXl7tZciwyovneBfZVCdtsRZjaLI1uMQCz/BToiYe3DABEBAAG0 -I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQRZ -sixZOfQcZdW0wUqmgmdsv1O9xgUCWyLLDQIbAwULCQgHAwUVCgkICwUWAgMBAAIe -AQIXgAAKCRCmgmdsv1O9xql2A/4pix98NxjhdsXtazA9agpAKeADf9tG4Za27Gj+ -3DCww/E4iP2X35jZimSm/30QRB6j08uGCqd9vXkkJxtOt63y/IpVOtWX6vMWSTUm -k8xKkaYMP0/IzKNJ1qC/qYEUYpwERBKg9Z+k99E2Ql4kRHdxXUHq6OzY79H18Y+s -GdeM/riNBFsiyxsBBAC54Pxg/8ZWaZX1phGdwfe5mek27SOYpC0AxIDCSOdMeQ6G -HPk38pywl1d+S+KmF/F4Tdi+kWro62O4eG2uc/T8JQuRDUhSjX0Qa51gPzJrUOVT -CFyUkiZ/3ZDhtXkgfuso8ua2ChBgR9Ngr4v43tSqa9y6AK7v0qjxD1x+xMrjXQAR -AQABiQFxBBgBCgAmAhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsizTIFCQAN -MRcAv7QgBBkBCgAdFiEEJcoVUVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62j -UpRPICQq5gQApoWIigZxXFoM0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBS -YnjyA4+n1D+zB2VqliD2QrsX12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZs -nRJmXV+bsvD4sidLZLjdwOVa3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/ -U73GGi0D/i20VW8AWYAPACm2zMlzExKTOAV01YTQH/3vW0WLrOse53WcIVZga6es -HuO4So0SOEAvxKMe5HpRIu2dJxTvd99Bo9xk9xJU0AoFrO0vNCRnL+5y68xMlODK -lEw5/kl0jeaTBp6xX0HDQOEVOpPGUwWV4Ij2EnvfNDXaE1vK1kffiQFrBBgBCgAg -AhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsi0AYAv7QgBBkBCgAdFiEEJcoV -UVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62jUpRPICQq5gQApoWIigZxXFoM -0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBSYnjyA4+n1D+zB2VqliD2QrsX -12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZsnRJmXV+bsvD4sidLZLjdwOVa -3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/U73GRl0EAJokkXmy4zKDHWWi -wvK9gi2gQgRkVnu2AiONxJb5vjeLhM/07BRmH6K1o+w3fOeEQp4FjXj1eQ5fPSM6 -Hhwx2CTl9SDnPSBMiKXsEFRkmwQ2AAsQZLmQZvKBkLZYeBiwf+IY621eYDhZfo+G -1dh1WoUCyREZsJQg2YoIpWIcvw+a -=bNRo ------END PGP PUBLIC KEY BLOCK----- -` - -const onlySubkeyNoPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v1 - -lQCVBFggvocBBAC7vBsHn7MKmS6IiiZNTXdciplVgS9cqVd+RTdIAoyNTcsiV1H0 -GQ3QtodOPeDlQDNoqinqaobd7R9g3m3hS53Nor7yBZkCWQ5x9v9JxRtoAq0sklh1 -I1X2zEqZk2l6YrfBF/64zWrhjnW3j23szkrAIVu0faQXbQ4z56tmZrw11wARAQAB -/gdlAkdOVQG0CUdOVSBEdW1teYi4BBMBAgAiBQJYIL6HAhsDBgsJCAcDAgYVCAIJ -CgsEFgIDAQIeAQIXgAAKCRCd1xxWp1CYAnjGA/9synn6ZXJUKAXQzySgmCZvCIbl -rqBfEpxwLG4Q/lONhm5vthAE0z49I8hj5Gc5e2tLYUtq0o0OCRdCrYHa/efOYWpJ -6RsK99bePOisVzmOABLIgZkcr022kHoMCmkPgv9CUGKP1yqbGl+zzAwQfUjRUmvD -ZIcWLHi2ge4GzPMPi50B2ARYIL6cAQQAxWHnicKejAFcFcF1/3gUSgSH7eiwuBPX -M7vDdgGzlve1o1jbV4tzrjN9jsCl6r0nJPDMfBSzgLr1auNTRG6HpJ4abcOx86ED -Ad+avDcQPZb7z3dPhH/gb2lQejZsHh7bbeOS8WMSzHV3RqCLd8J/xwWPNR5zKn1f -yp4IGfopidMAEQEAAQAD+wQOelnR82+dxyM2IFmZdOB9wSXQeCVOvxSaNMh6Y3lk -UOOkO8Nlic4x0ungQRvjoRs4wBmCuwFK/MII6jKui0B7dn/NDf51i7rGdNGuJXDH -e676By1sEY/NGkc74jr74T+5GWNU64W0vkpfgVmjSAzsUtpmhJMXsc7beBhJdnVl -AgDKCb8hZqj1alcdmLoNvb7ibA3K/V8J462CPD7bMySPBa/uayoFhNxibpoXml2r -oOtHa5izF3b0/9JY97F6rqkdAgD6GdTJ+xmlCoz1Sewoif1I6krq6xoa7gOYpIXo -UL1Afr+LiJeyAnF/M34j/kjIVmPanZJjry0kkjHE5ILjH3uvAf4/6n9np+Th8ujS -YDCIzKwR7639+H+qccOaddCep8Y6KGUMVdD/vTKEx1rMtK+hK/CDkkkxnFslifMJ -kqoqv3WUqCWJAT0EGAECAAkFAlggvpwCGwIAqAkQndccVqdQmAKdIAQZAQIABgUC -WCC+nAAKCRDmGUholQPwvQk+A/9latnSsR5s5/1A9TFki11GzSEnfLbx46FYOdkW -n3YBxZoPQGxNA1vIn8GmouxZInw9CF4jdOJxEdzLlYQJ9YLTLtN5tQEMl/19/bR8 -/qLacAZ9IOezYRWxxZsyn6//jfl7A0Y+FV59d4YajKkEfItcIIlgVBSW6T+TNQT3 -R+EH5HJ/A/4/AN0CmBhhE2vGzTnVU0VPrE4V64pjn1rufFdclgpixNZCuuqpKpoE -VVHn6mnBf4njKjZrAGPs5kfQ+H4NsM7v3Zz4yV6deu9FZc4O6E+V1WJ38rO8eBix -7G2jko106CC6vtxsCPVIzY7aaG3H5pjRtomw+pX7SzrQ7FUg2PGumg== -=F/T0 ------END PGP PRIVATE KEY BLOCK-----` - -const ecdsaPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -xaUEX1KsSRMIKoZIzj0DAQcCAwTpYqJsnJiFhKKh+8TulWD+lVmerBFNS+Ii -B+nlG3T0xQQ4Sy5eIjJ0CExIQQzi3EElF/Z2l4F3WC5taFA11NgA/gkDCHSS -PThf1M2K4LN8F1MRcvR+sb7i0nH55ojkwuVB1DE6jqIT9m9i+mX1tzjSAS+6 -lPQiweCJvG7xTC7Hs3AzRapf/r1At4TB+v+5G2/CKynNFEJpbGwgPGJpbGxA -aG9tZS5jb20+wncEEBMIAB8FAl9SrEkGCwkHCAMCBBUICgIDFgIBAhkBAhsD -Ah4BAAoJEMpwT3+q3+xqw5UBAMebZN9isEZ1ML+R/jWAAWMwa/knMugrEZ1v -Bl9+ZwM0AQCZdf80/wYY4Nve01qSRFv8OmKswLli3TvDv6FKc4cLz8epBF9S -rEkSCCqGSM49AwEHAgMEAjKnT9b5wY2bf9TpAV3d7OUfPOxKj9c4VzeVzSrH -AtQgo/MuI1cdYVURicV4i76DNjFhQHQFTk7BrC+C2u1yqQMBCAf+CQMIHImA -iYfzQtjgQWSFZYUkCFpbbwhNF0ch+3HNaZkaHCnZRIsWsRnc6FCb6lRQyK9+ -Dq59kHlduE5QgY40894jfmP2JdJHU6nBdYrivbEdbMJhBBgTCAAJBQJfUqxJ -AhsMAAoJEMpwT3+q3+xqUI0BAMykhV08kQ4Ip9Qlbss6Jdufv7YrU0Vd5hou -b5TmiPd0APoDBh3qIic+aLLUcAuG3+Gt1P1AbUlmqV61ozn1WfHxfw== -=KLN8 ------END PGP PRIVATE KEY BLOCK-----` - -const dsaPrivateKeyWithElGamalSubkey = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -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 -4g== -=XZm8 ------END PGP PRIVATE KEY BLOCK-----` - -// https://tests.sequoia-pgp.org/#Certificate_expiration -// P _ U p -const expiringPrimaryUIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -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 -=AmgT ------END PGP PUBLIC KEY BLOCK-----` - -const rsa2048PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- -Comment: gpg (GnuPG) 2.2.27 with libgcrypt 1.9.4 - -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 -=u442 ------END PGP PRIVATE KEY BLOCK-----` - -const curve25519PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- -Comment: gpg (GnuPG) 2.2.27 with libgcrypt 1.9.4 - -lFgEYvTtQBYJKwYBBAHaRw8BAQdAxsNXLbrk5xOjpO24VhOMvQ0/F+JcyIkckMDH -X3FIGxcAAQDFOlunZWYuPsCx5JLp78vKqUTfgef9TGG4oD6I/Sa0zBMstCJHb2xh -bmcgR29waGVyIDxnb2xhbmdAZXhhbXBsZS5vcmc+iJAEExYIADgWIQSFQHEOazmo -h1ldII4MvfnLQ4JBNwUCYvTtQAIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAK -CRAMvfnLQ4JBN5yeAQCKdry8B5ScCPrev2+UByMCss7Sdu5RhomCFsHdNPLcKAEA -8ugei+1owHsV+3cGwWWzKk6sLa8ZN87i3SKuOGp9DQycXQRi9O1AEgorBgEEAZdV -AQUBAQdA5CubPp8l7lrVQ25h7Hx5XN2C8xanRnnpcjzEooCaEA0DAQgHAAD/Rpc+ -sOZUXrFk9HOWB1XU41LoWbDBoG8sP8RWAVYwD5AQRYh4BBgWCAAgFiEEhUBxDms5 -qIdZXSCODL35y0OCQTcFAmL07UACGwwACgkQDL35y0OCQTcvdwEA7lb5g/YisrEf -iq660uwMGoepLUfvtqKzuQ6heYe83y0BAN65Ffg5HYOJzUEi0kZQRf7OhdtuL2kJ -SRXn8DmCTfEB -=cELM ------END PGP PRIVATE KEY BLOCK-----` - -const curve448PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- -Comment: C1DB 65D5 80D7 B922 7254 4B1E A699 9895 FABA CE52 - -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 -QgqsfguR1PqPuJxpXV4bSr6CGAAAAA== -=MSvh ------END PGP PRIVATE KEY BLOCK-----` - -const keyWithNotation = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -xVgEY9gIshYJKwYBBAHaRw8BAQdAF25fSM8OpFlXZhop4Qpqo5ywGZ4jgWlR -ppjhIKDthREAAQC+LFpzFcMJYcjxGKzBGHN0Px2jU4d04YSRnFAik+lVVQ6u -zRdUZXN0IDx0ZXN0QGV4YW1wbGUuY29tPsLACgQQFgoAfAUCY9gIsgQLCQcI -CRD/utJOCym8pR0UgAAAAAAQAAR0ZXh0QGV4YW1wbGUuY29tdGVzdB8UAAAA -AAASAARiaW5hcnlAZXhhbXBsZS5jb20AAQIDAxUICgQWAAIBAhkBAhsDAh4B -FiEEEMCQTUVGKgCX5rDQ/7rSTgspvKUAAPl5AP9Npz90LxzrB97Qr2DrGwfG -wuYn4FSYwtuPfZHHeoIabwD/QEbvpQJ/NBb9EAZuow4Rirlt1yv19mmnF+j5 -8yUzhQjHXQRj2AiyEgorBgEEAZdVAQUBAQdARXAo30DmKcyUg6co7OUm0RNT -z9iqFbDBzA8A47JEt1MDAQgHAAD/XKK3lBm0SqMR558HLWdBrNG6NqKuqb5X -joCML987ZNgRD8J4BBgWCAAqBQJj2AiyCRD/utJOCym8pQIbDBYhBBDAkE1F -RioAl+aw0P+60k4LKbylAADRxgEAg7UfBDiDPp5LHcW9D+SgFHk6+GyEU4ev -VppQxdtxPvAA/34snHBX7Twnip1nMt7P4e2hDiw/hwQ7oqioOvc6jMkP -=Z8YJ ------END PGP PRIVATE KEY BLOCK----- -` diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go deleted file mode 100644 index ef100d37..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2019 ProtonTech AG - -package packet - -import "math/bits" - -// CipherSuite contains a combination of Cipher and Mode -type CipherSuite struct { - // The cipher function - Cipher CipherFunction - // The AEAD mode of operation. - Mode AEADMode -} - -// AEADConfig collects a number of AEAD parameters along with sensible defaults. -// A nil AEADConfig is valid and results in all default values. -type AEADConfig struct { - // The AEAD mode of operation. - DefaultMode AEADMode - // Amount of octets in each chunk of data - ChunkSize uint64 -} - -// Mode returns the AEAD mode of operation. -func (conf *AEADConfig) Mode() AEADMode { - // If no preference is specified, OCB is used (which is mandatory to implement). - if conf == nil || conf.DefaultMode == 0 { - return AEADModeOCB - } - - mode := conf.DefaultMode - if mode != AEADModeEAX && mode != AEADModeOCB && mode != AEADModeGCM { - panic("AEAD mode unsupported") - } - return mode -} - -// ChunkSizeByte returns the byte indicating the chunk size. The effective -// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6) -// limit chunkSizeByte to 16 which equals to 2^22 = 4 MiB -// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2 -func (conf *AEADConfig) ChunkSizeByte() byte { - if conf == nil || conf.ChunkSize == 0 { - return 12 // 1 << (12 + 6) == 262144 bytes - } - - chunkSize := conf.ChunkSize - exponent := bits.Len64(chunkSize) - 1 - switch { - case exponent < 6: - exponent = 6 - case exponent > 22: - exponent = 22 - } - - return byte(exponent - 6) -} - -// decodeAEADChunkSize returns the effective chunk size. In 32-bit systems, the -// maximum returned value is 1 << 30. -func decodeAEADChunkSize(c byte) int { - size := uint64(1 << (c + 6)) - if size != uint64(int(size)) { - return 1 << 30 - } - return int(size) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go deleted file mode 100644 index 5e460465..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright (C) 2019 ProtonTech AG - -package packet - -import ( - "crypto/cipher" - "encoding/binary" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -// aeadCrypter is an AEAD opener/sealer, its configuration, and data for en/decryption. -type aeadCrypter struct { - aead cipher.AEAD - chunkSize int - nonce []byte - associatedData []byte // Chunk-independent associated data - chunkIndex []byte // Chunk counter - packetTag packetType // SEIP packet (v2) or AEAD Encrypted Data packet - bytesProcessed int // Amount of plaintext bytes encrypted/decrypted -} - -// computeNonce takes the incremental index and computes an eXclusive OR with -// the least significant 8 bytes of the receivers' initial nonce (see sec. -// 5.16.1 and 5.16.2). It returns the resulting nonce. -func (wo *aeadCrypter) computeNextNonce() (nonce []byte) { - if wo.packetTag == packetTypeSymmetricallyEncryptedIntegrityProtected { - return wo.nonce - } - - nonce = make([]byte, len(wo.nonce)) - copy(nonce, wo.nonce) - offset := len(wo.nonce) - 8 - for i := 0; i < 8; i++ { - nonce[i+offset] ^= wo.chunkIndex[i] - } - return -} - -// incrementIndex performs an integer increment by 1 of the integer represented by the -// slice, modifying it accordingly. -func (wo *aeadCrypter) incrementIndex() error { - index := wo.chunkIndex - if len(index) == 0 { - return errors.AEADError("Index has length 0") - } - for i := len(index) - 1; i >= 0; i-- { - if index[i] < 255 { - index[i]++ - return nil - } - index[i] = 0 - } - return errors.AEADError("cannot further increment index") -} - -// aeadDecrypter reads and decrypts bytes. It buffers extra decrypted bytes when -// necessary, similar to aeadEncrypter. -type aeadDecrypter struct { - aeadCrypter // Embedded ciphertext opener - reader io.Reader // 'reader' is a partialLengthReader - chunkBytes []byte - peekedBytes []byte // Used to detect last chunk - buffer []byte // Buffered decrypted bytes -} - -// Read decrypts bytes and reads them into dst. It decrypts when necessary and -// buffers extra decrypted bytes. It returns the number of bytes copied into dst -// and an error. -func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) { - // Return buffered plaintext bytes from previous calls - if len(ar.buffer) > 0 { - n = copy(dst, ar.buffer) - ar.buffer = ar.buffer[n:] - return - } - - // Read a chunk - tagLen := ar.aead.Overhead() - copy(ar.chunkBytes, ar.peekedBytes) // Copy bytes peeked in previous chunk or in initialization - bytesRead, errRead := io.ReadFull(ar.reader, ar.chunkBytes[tagLen:]) - if errRead != nil && errRead != io.EOF && errRead != io.ErrUnexpectedEOF { - return 0, errRead - } - - if bytesRead > 0 { - ar.peekedBytes = ar.chunkBytes[bytesRead:bytesRead+tagLen] - - decrypted, errChunk := ar.openChunk(ar.chunkBytes[:bytesRead]) - if errChunk != nil { - return 0, errChunk - } - - // Return decrypted bytes, buffering if necessary - n = copy(dst, decrypted) - ar.buffer = decrypted[n:] - return - } - - return 0, io.EOF -} - -// Close checks the final authentication tag of the stream. -// In the future, this function could also be used to wipe the reader -// and peeked & decrypted bytes, if necessary. -func (ar *aeadDecrypter) Close() (err error) { - errChunk := ar.validateFinalTag(ar.peekedBytes) - if errChunk != nil { - return errChunk - } - return nil -} - -// openChunk decrypts and checks integrity of an encrypted chunk, returning -// the underlying plaintext and an error. It accesses peeked bytes from next -// chunk, to identify the last chunk and decrypt/validate accordingly. -func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) { - adata := ar.associatedData - if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted { - adata = append(ar.associatedData, ar.chunkIndex...) - } - - nonce := ar.computeNextNonce() - plainChunk, err := ar.aead.Open(data[:0:len(data)], nonce, data, adata) - if err != nil { - return nil, errors.ErrAEADTagVerification - } - ar.bytesProcessed += len(plainChunk) - if err = ar.aeadCrypter.incrementIndex(); err != nil { - return nil, err - } - return plainChunk, nil -} - -// Checks the summary tag. It takes into account the total decrypted bytes into -// the associated data. It returns an error, or nil if the tag is valid. -func (ar *aeadDecrypter) validateFinalTag(tag []byte) error { - // Associated: tag, version, cipher, aead, chunk size, ... - amountBytes := make([]byte, 8) - binary.BigEndian.PutUint64(amountBytes, uint64(ar.bytesProcessed)) - - adata := ar.associatedData - if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted { - // ... index ... - adata = append(ar.associatedData, ar.chunkIndex...) - } - - // ... and total number of encrypted octets - adata = append(adata, amountBytes...) - nonce := ar.computeNextNonce() - if _, err := ar.aead.Open(nil, nonce, tag, adata); err != nil { - return errors.ErrAEADTagVerification - } - return nil -} - -// aeadEncrypter encrypts and writes bytes. It encrypts when necessary according -// to the AEAD block size, and buffers the extra encrypted bytes for next write. -type aeadEncrypter struct { - aeadCrypter // Embedded plaintext sealer - writer io.WriteCloser // 'writer' is a partialLengthWriter - chunkBytes []byte - offset int -} - -// Write encrypts and writes bytes. It encrypts when necessary and buffers extra -// plaintext bytes for next call. When the stream is finished, Close() MUST be -// called to append the final tag. -func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) { - for n != len(plaintextBytes) { - copied := copy(aw.chunkBytes[aw.offset:aw.chunkSize], plaintextBytes[n:]) - n += copied - aw.offset += copied - - if aw.offset == aw.chunkSize { - encryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset]) - if err != nil { - return n, err - } - _, err = aw.writer.Write(encryptedChunk) - if err != nil { - return n, err - } - aw.offset = 0 - } - } - return -} - -// Close encrypts and writes the remaining buffered plaintext if any, appends -// the final authentication tag, and closes the embedded writer. This function -// MUST be called at the end of a stream. -func (aw *aeadEncrypter) Close() (err error) { - // Encrypt and write a chunk if there's buffered data left, or if we haven't - // written any chunks yet. - if aw.offset > 0 || aw.bytesProcessed == 0 { - lastEncryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset]) - if err != nil { - return err - } - _, err = aw.writer.Write(lastEncryptedChunk) - if err != nil { - return err - } - } - // Compute final tag (associated data: packet tag, version, cipher, aead, - // chunk size... - adata := aw.associatedData - - if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted { - // ... index ... - adata = append(aw.associatedData, aw.chunkIndex...) - } - - // ... and total number of encrypted octets - amountBytes := make([]byte, 8) - binary.BigEndian.PutUint64(amountBytes, uint64(aw.bytesProcessed)) - adata = append(adata, amountBytes...) - - nonce := aw.computeNextNonce() - finalTag := aw.aead.Seal(nil, nonce, nil, adata) - _, err = aw.writer.Write(finalTag) - if err != nil { - return err - } - return aw.writer.Close() -} - -// sealChunk Encrypts and authenticates the given chunk. -func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) { - if len(data) > aw.chunkSize { - return nil, errors.AEADError("chunk exceeds maximum length") - } - if aw.associatedData == nil { - return nil, errors.AEADError("can't seal without headers") - } - adata := aw.associatedData - if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted { - adata = append(aw.associatedData, aw.chunkIndex...) - } - - nonce := aw.computeNextNonce() - encrypted := aw.aead.Seal(data[:0], nonce, data, adata) - aw.bytesProcessed += len(data) - if err := aw.aeadCrypter.incrementIndex(); err != nil { - return nil, err - } - return encrypted, nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go deleted file mode 100644 index 583765d8..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2019 ProtonTech AG - -package packet - -import ( - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" -) - -// AEADEncrypted represents an AEAD Encrypted Packet. -// See https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t -type AEADEncrypted struct { - cipher CipherFunction - mode AEADMode - chunkSizeByte byte - Contents io.Reader // Encrypted chunks and tags - initialNonce []byte // Referred to as IV in RFC4880-bis -} - -// Only currently defined version -const aeadEncryptedVersion = 1 - -func (ae *AEADEncrypted) parse(buf io.Reader) error { - headerData := make([]byte, 4) - if n, err := io.ReadFull(buf, headerData); n < 4 { - return errors.AEADError("could not read aead header:" + err.Error()) - } - // Read initial nonce - mode := AEADMode(headerData[2]) - nonceLen := mode.IvLength() - - // This packet supports only EAX and OCB - // https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t - if nonceLen == 0 || mode > AEADModeOCB { - return errors.AEADError("unknown mode") - } - - initialNonce := make([]byte, nonceLen) - if n, err := io.ReadFull(buf, initialNonce); n < nonceLen { - return errors.AEADError("could not read aead nonce:" + err.Error()) - } - ae.Contents = buf - ae.initialNonce = initialNonce - c := headerData[1] - if _, ok := algorithm.CipherById[c]; !ok { - return errors.UnsupportedError("unknown cipher: " + string(c)) - } - ae.cipher = CipherFunction(c) - ae.mode = mode - ae.chunkSizeByte = headerData[3] - return nil -} - -// Decrypt returns a io.ReadCloser from which decrypted bytes can be read, or -// an error. -func (ae *AEADEncrypted) Decrypt(ciph CipherFunction, key []byte) (io.ReadCloser, error) { - return ae.decrypt(key) -} - -// decrypt prepares an aeadCrypter and returns a ReadCloser from which -// decrypted bytes can be read (see aeadDecrypter.Read()). -func (ae *AEADEncrypted) decrypt(key []byte) (io.ReadCloser, error) { - blockCipher := ae.cipher.new(key) - aead := ae.mode.new(blockCipher) - // Carry the first tagLen bytes - chunkSize := decodeAEADChunkSize(ae.chunkSizeByte) - tagLen := ae.mode.TagLength() - chunkBytes := make([]byte, chunkSize+tagLen*2) - peekedBytes := chunkBytes[chunkSize+tagLen:] - n, err := io.ReadFull(ae.Contents, peekedBytes) - if n < tagLen || (err != nil && err != io.EOF) { - return nil, errors.AEADError("Not enough data to decrypt:" + err.Error()) - } - - return &aeadDecrypter{ - aeadCrypter: aeadCrypter{ - aead: aead, - chunkSize: chunkSize, - nonce: ae.initialNonce, - associatedData: ae.associatedData(), - chunkIndex: make([]byte, 8), - packetTag: packetTypeAEADEncrypted, - }, - reader: ae.Contents, - chunkBytes: chunkBytes, - peekedBytes: peekedBytes, - }, nil -} - -// associatedData for chunks: tag, version, cipher, mode, chunk size byte -func (ae *AEADEncrypted) associatedData() []byte { - return []byte{ - 0xD4, - aeadEncryptedVersion, - byte(ae.cipher), - byte(ae.mode), - ae.chunkSizeByte} -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go deleted file mode 100644 index 931f55a4..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "compress/bzip2" - "compress/flate" - "compress/zlib" - "io" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -// Compressed represents a compressed OpenPGP packet. The decompressed contents -// will contain more OpenPGP packets. See RFC 4880, section 5.6. -type Compressed struct { - Body io.Reader -} - -const ( - NoCompression = flate.NoCompression - BestSpeed = flate.BestSpeed - BestCompression = flate.BestCompression - DefaultCompression = flate.DefaultCompression -) - -// CompressionConfig contains compressor configuration settings. -type CompressionConfig struct { - // Level is the compression level to use. It must be set to - // between -1 and 9, with -1 causing the compressor to use the - // default compression level, 0 causing the compressor to use - // no compression and 1 to 9 representing increasing (better, - // slower) compression levels. If Level is less than -1 or - // more then 9, a non-nil error will be returned during - // encryption. See the constants above for convenient common - // settings for Level. - Level int -} - -// decompressionReader ensures that the whole compression packet is read. -type decompressionReader struct { - compressed io.Reader - decompressed io.ReadCloser - readAll bool -} - -func newDecompressionReader(r io.Reader, decompressor io.ReadCloser) *decompressionReader { - return &decompressionReader{ - compressed: r, - decompressed: decompressor, - } -} - -func (dr *decompressionReader) Read(data []byte) (n int, err error) { - if dr.readAll { - return 0, io.EOF - } - n, err = dr.decompressed.Read(data) - if err == io.EOF { - dr.readAll = true - // Close the decompressor. - if errDec := dr.decompressed.Close(); errDec != nil { - return n, errDec - } - // Consume all remaining data from the compressed packet. - consumeAll(dr.compressed) - } - return n, err -} - -func (c *Compressed) parse(r io.Reader) error { - var buf [1]byte - _, err := readFull(r, buf[:]) - if err != nil { - return err - } - - switch buf[0] { - case 0: - c.Body = r - case 1: - c.Body = newDecompressionReader(r, flate.NewReader(r)) - case 2: - decompressor, err := zlib.NewReader(r) - if err != nil { - return err - } - c.Body = newDecompressionReader(r, decompressor) - case 3: - c.Body = newDecompressionReader(r, io.NopCloser(bzip2.NewReader(r))) - default: - err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) - } - - return err -} - -// LimitedBodyReader wraps the provided body reader with a limiter that restricts -// the number of bytes read to the specified limit. -// If limit is nil, the reader is unbounded. -func (c *Compressed) LimitedBodyReader(limit *int64) io.Reader { - if limit == nil { - return c.Body - } - return &LimitReader{R: c.Body, N: *limit} -} - -// compressedWriterCloser represents the serialized compression stream -// header and the compressor. Its Close() method ensures that both the -// compressor and serialized stream header are closed. Its Write() -// method writes to the compressor. -type compressedWriteCloser struct { - sh io.Closer // Stream Header - c io.WriteCloser // Compressor -} - -func (cwc compressedWriteCloser) Write(p []byte) (int, error) { - return cwc.c.Write(p) -} - -func (cwc compressedWriteCloser) Close() (err error) { - err = cwc.c.Close() - if err != nil { - return err - } - - return cwc.sh.Close() -} - -// SerializeCompressed serializes a compressed data packet to w and -// returns a WriteCloser to which the literal data packets themselves -// can be written and which MUST be closed on completion. If cc is -// nil, sensible defaults will be used to configure the compression -// algorithm. -func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { - compressed, err := serializeStreamHeader(w, packetTypeCompressed) - if err != nil { - return - } - - _, err = compressed.Write([]byte{uint8(algo)}) - if err != nil { - return - } - - level := DefaultCompression - if cc != nil { - level = cc.Level - } - - var compressor io.WriteCloser - switch algo { - case CompressionZIP: - compressor, err = flate.NewWriter(compressed, level) - case CompressionZLIB: - compressor, err = zlib.NewWriterLevel(compressed, level) - default: - s := strconv.Itoa(int(algo)) - err = errors.UnsupportedError("Unsupported compression algorithm: " + s) - } - if err != nil { - return - } - - literaldata = compressedWriteCloser{compressed, compressor} - - return -} - -// LimitReader is an io.Reader that fails with MessageToLarge if read bytes exceed N. -type LimitReader struct { - R io.Reader // underlying reader - N int64 // max bytes allowed -} - -func (l *LimitReader) Read(p []byte) (int, error) { - if l.N <= 0 { - return 0, errors.ErrMessageTooLarge - } - - n, err := l.R.Read(p) - l.N -= int64(n) - - if err == nil && l.N <= 0 { - err = errors.ErrMessageTooLarge - } - - return n, err -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go deleted file mode 100644 index 30167ed9..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go +++ /dev/null @@ -1,434 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto" - "crypto/rand" - "io" - "math/big" - "time" - - "github.com/ProtonMail/go-crypto/openpgp/s2k" -) - -var ( - defaultRejectPublicKeyAlgorithms = map[PublicKeyAlgorithm]bool{ - PubKeyAlgoElGamal: true, - PubKeyAlgoDSA: true, - } - defaultRejectHashAlgorithms = map[crypto.Hash]bool{ - crypto.MD5: true, - crypto.RIPEMD160: true, - } - defaultRejectMessageHashAlgorithms = map[crypto.Hash]bool{ - crypto.SHA1: true, - crypto.MD5: true, - crypto.RIPEMD160: true, - } - defaultRejectCurves = map[Curve]bool{ - CurveSecP256k1: true, - } -) - -// A global feature flag to indicate v5 support. -// Can be set via a build tag, e.g.: `go build -tags v5 ./...` -// If the build tag is missing config_v5.go will set it to true. -// -// Disables parsing of v5 keys and v5 signatures. -// These are non-standard entities, which in the crypto-refresh have been superseded -// by v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively. -var V5Disabled = false - -// Config collects a number of parameters along with sensible defaults. -// A nil *Config is valid and results in all default values. -type Config struct { - // Rand provides the source of entropy. - // If nil, the crypto/rand Reader is used. - Rand io.Reader - // DefaultHash is the default hash function to be used. - // If zero, SHA-256 is used. - DefaultHash crypto.Hash - // DefaultCipher is the cipher to be used. - // If zero, AES-128 is used. - DefaultCipher CipherFunction - // Time returns the current time as the number of seconds since the - // epoch. If Time is nil, time.Now is used. - Time func() time.Time - // DefaultCompressionAlgo is the compression algorithm to be - // applied to the plaintext before encryption. If zero, no - // compression is done. - DefaultCompressionAlgo CompressionAlgo - // CompressionConfig configures the compression settings. - CompressionConfig *CompressionConfig - // S2K (String to Key) config, used for key derivation in the context of secret key encryption - // and password-encrypted data. - // If nil, the default configuration is used - S2KConfig *s2k.Config - // Iteration count for Iterated S2K (String to Key). - // Only used if sk2.Mode is nil. - // This value is duplicated here from s2k.Config for backwards compatibility. - // It determines the strength of the passphrase stretching when - // the said passphrase is hashed to produce a key. S2KCount - // should be between 65536 and 65011712, inclusive. If Config - // is nil or S2KCount is 0, the value 16777216 used. Not all - // values in the above range can be represented. S2KCount will - // be rounded up to the next representable value if it cannot - // be encoded exactly. When set, it is strongly encrouraged to - // use a value that is at least 65536. See RFC 4880 Section - // 3.7.1.3. - // - // Deprecated: SK2Count should be configured in S2KConfig instead. - S2KCount int - // RSABits is the number of bits in new RSA keys made with NewEntity. - // If zero, then 2048 bit keys are created. - RSABits int - // The public key algorithm to use - will always create a signing primary - // key and encryption subkey. - Algorithm PublicKeyAlgorithm - // Some known primes that are optionally prepopulated by the caller - RSAPrimes []*big.Int - // Curve configures the desired packet.Curve if the Algorithm is PubKeyAlgoECDSA, - // PubKeyAlgoEdDSA, or PubKeyAlgoECDH. If empty Curve25519 is used. - Curve Curve - // AEADConfig configures the use of the new AEAD Encrypted Data Packet, - // defined in the draft of the next version of the OpenPGP specification. - // If a non-nil AEADConfig is passed, usage of this packet is enabled. By - // default, it is disabled. See the documentation of AEADConfig for more - // configuration options related to AEAD. - // **Note: using this option may break compatibility with other OpenPGP - // implementations, as well as future versions of this library.** - AEADConfig *AEADConfig - // V6Keys configures version 6 key generation. If false, this package still - // supports version 6 keys, but produces version 4 keys. - V6Keys bool - // Minimum RSA key size allowed for key generation and message signing, verification and encryption. - MinRSABits uint16 - // Reject insecure algorithms, only works with v2 api - RejectPublicKeyAlgorithms map[PublicKeyAlgorithm]bool - RejectHashAlgorithms map[crypto.Hash]bool - RejectMessageHashAlgorithms map[crypto.Hash]bool - RejectCurves map[Curve]bool - // "The validity period of the key. This is the number of seconds after - // the key creation time that the key expires. If this is not present - // or has a value of zero, the key never expires. This is found only on - // a self-signature."" - // https://tools.ietf.org/html/rfc4880#section-5.2.3.6 - KeyLifetimeSecs uint32 - // "The validity period of the signature. This is the number of seconds - // after the signature creation time that the signature expires. If - // this is not present or has a value of zero, it never expires." - // https://tools.ietf.org/html/rfc4880#section-5.2.3.10 - SigLifetimeSecs uint32 - // SigningKeyId is used to specify the signing key to use (by Key ID). - // By default, the signing key is selected automatically, preferring - // signing subkeys if available. - SigningKeyId uint64 - // SigningIdentity is used to specify a user ID (packet Signer's User ID, type 28) - // when producing a generic certification signature onto an existing user ID. - // The identity must be present in the signer Entity. - SigningIdentity string - // InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read - // encrypted messages without Modification Detection Code (MDC). - // MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented - // in most OpenPGP implementations. Messages without MDC are considered unnecessarily - // insecure and should be prevented whenever possible. - // In case one needs to deal with messages from very old OpenPGP implementations, there - // might be no other way than to tolerate the missing MDC. Setting this flag, allows this - // mode of operation. It should be considered a measure of last resort. - InsecureAllowUnauthenticatedMessages bool - // InsecureAllowDecryptionWithSigningKeys allows decryption with keys marked as signing keys in the v2 API. - // This setting is potentially insecure, but it is needed as some libraries - // ignored key flags when selecting a key for encryption. - // Not relevant for the v1 API, as all keys were allowed in decryption. - InsecureAllowDecryptionWithSigningKeys bool - // KnownNotations is a map of Notation Data names to bools, which controls - // the notation names that are allowed to be present in critical Notation Data - // signature subpackets. - KnownNotations map[string]bool - // SignatureNotations is a list of Notations to be added to any signatures. - SignatureNotations []*Notation - // CheckIntendedRecipients controls, whether the OpenPGP Intended Recipient Fingerprint feature - // should be enabled for encryption and decryption. - // (See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr). - // When the flag is set, encryption produces Intended Recipient Fingerprint signature sub-packets and decryption - // checks whether the key it was encrypted to is one of the included fingerprints in the signature. - // If the flag is disabled, no Intended Recipient Fingerprint sub-packets are created or checked. - // The default behavior, when the config or flag is nil, is to enable the feature. - CheckIntendedRecipients *bool - // CacheSessionKey controls if decryption should return the session key used for decryption. - // If the flag is set, the session key is cached in the message details struct. - CacheSessionKey bool - // CheckPacketSequence is a flag that controls if the pgp message reader should strictly check - // that the packet sequence conforms with the grammar mandated by rfc4880. - // The default behavior, when the config or flag is nil, is to check the packet sequence. - CheckPacketSequence *bool - // NonDeterministicSignaturesViaNotation is a flag to enable randomization of signatures. - // If true, a salt notation is used to randomize signatures generated by v4 and v5 keys - // (v6 signatures are always non-deterministic, by design). - // This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur - // during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of - // weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks. - // The default behavior, when the config or flag is nil, is to enable the feature. - NonDeterministicSignaturesViaNotation *bool - - // InsecureAllowAllKeyFlagsWhenMissing determines how a key without valid key flags is handled. - // When set to true, a key without flags is treated as if all flags are enabled. - // This behavior is consistent with GPG. - InsecureAllowAllKeyFlagsWhenMissing bool - - // MaxDecompressedMessageSize specifies the maximum number of bytes that can be - // read from a compressed packet. This serves as an upper limit to prevent - // excessively large decompressed messages. - MaxDecompressedMessageSize *int64 -} - -func (c *Config) Random() io.Reader { - if c == nil || c.Rand == nil { - return rand.Reader - } - return c.Rand -} - -func (c *Config) Hash() crypto.Hash { - if c == nil || uint(c.DefaultHash) == 0 { - return crypto.SHA256 - } - return c.DefaultHash -} - -func (c *Config) Cipher() CipherFunction { - if c == nil || uint8(c.DefaultCipher) == 0 { - return CipherAES128 - } - return c.DefaultCipher -} - -func (c *Config) Now() time.Time { - if c == nil || c.Time == nil { - return time.Now().Truncate(time.Second) - } - return c.Time().Truncate(time.Second) -} - -// KeyLifetime returns the validity period of the key. -func (c *Config) KeyLifetime() uint32 { - if c == nil { - return 0 - } - return c.KeyLifetimeSecs -} - -// SigLifetime returns the validity period of the signature. -func (c *Config) SigLifetime() uint32 { - if c == nil { - return 0 - } - return c.SigLifetimeSecs -} - -func (c *Config) Compression() CompressionAlgo { - if c == nil { - return CompressionNone - } - return c.DefaultCompressionAlgo -} - -func (c *Config) RSAModulusBits() int { - if c == nil || c.RSABits == 0 { - return 2048 - } - return c.RSABits -} - -func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm { - if c == nil || c.Algorithm == 0 { - return PubKeyAlgoRSA - } - return c.Algorithm -} - -func (c *Config) CurveName() Curve { - if c == nil || c.Curve == "" { - return Curve25519 - } - return c.Curve -} - -// Deprecated: The hash iterations should now be queried via the S2K() method. -func (c *Config) PasswordHashIterations() int { - if c == nil || c.S2KCount == 0 { - return 0 - } - return c.S2KCount -} - -func (c *Config) S2K() *s2k.Config { - if c == nil { - return nil - } - // for backwards compatibility - if c.S2KCount > 0 && c.S2KConfig == nil { - return &s2k.Config{ - S2KCount: c.S2KCount, - } - } - return c.S2KConfig -} - -func (c *Config) AEAD() *AEADConfig { - if c == nil { - return nil - } - return c.AEADConfig -} - -func (c *Config) SigningKey() uint64 { - if c == nil { - return 0 - } - return c.SigningKeyId -} - -func (c *Config) SigningUserId() string { - if c == nil { - return "" - } - return c.SigningIdentity -} - -func (c *Config) AllowUnauthenticatedMessages() bool { - if c == nil { - return false - } - return c.InsecureAllowUnauthenticatedMessages -} - -func (c *Config) AllowDecryptionWithSigningKeys() bool { - if c == nil { - return false - } - return c.InsecureAllowDecryptionWithSigningKeys -} - -func (c *Config) KnownNotation(notationName string) bool { - if c == nil { - return false - } - return c.KnownNotations[notationName] -} - -func (c *Config) Notations() []*Notation { - if c == nil { - return nil - } - return c.SignatureNotations -} - -func (c *Config) V6() bool { - if c == nil { - return false - } - return c.V6Keys -} - -func (c *Config) IntendedRecipients() bool { - if c == nil || c.CheckIntendedRecipients == nil { - return true - } - return *c.CheckIntendedRecipients -} - -func (c *Config) RetrieveSessionKey() bool { - if c == nil { - return false - } - return c.CacheSessionKey -} - -func (c *Config) MinimumRSABits() uint16 { - if c == nil || c.MinRSABits == 0 { - return 2047 - } - return c.MinRSABits -} - -func (c *Config) RejectPublicKeyAlgorithm(alg PublicKeyAlgorithm) bool { - var rejectedAlgorithms map[PublicKeyAlgorithm]bool - if c == nil || c.RejectPublicKeyAlgorithms == nil { - // Default - rejectedAlgorithms = defaultRejectPublicKeyAlgorithms - } else { - rejectedAlgorithms = c.RejectPublicKeyAlgorithms - } - return rejectedAlgorithms[alg] -} - -func (c *Config) RejectHashAlgorithm(hash crypto.Hash) bool { - var rejectedAlgorithms map[crypto.Hash]bool - if c == nil || c.RejectHashAlgorithms == nil { - // Default - rejectedAlgorithms = defaultRejectHashAlgorithms - } else { - rejectedAlgorithms = c.RejectHashAlgorithms - } - return rejectedAlgorithms[hash] -} - -func (c *Config) RejectMessageHashAlgorithm(hash crypto.Hash) bool { - var rejectedAlgorithms map[crypto.Hash]bool - if c == nil || c.RejectMessageHashAlgorithms == nil { - // Default - rejectedAlgorithms = defaultRejectMessageHashAlgorithms - } else { - rejectedAlgorithms = c.RejectMessageHashAlgorithms - } - return rejectedAlgorithms[hash] -} - -func (c *Config) RejectCurve(curve Curve) bool { - var rejectedCurve map[Curve]bool - if c == nil || c.RejectCurves == nil { - // Default - rejectedCurve = defaultRejectCurves - } else { - rejectedCurve = c.RejectCurves - } - return rejectedCurve[curve] -} - -func (c *Config) StrictPacketSequence() bool { - if c == nil || c.CheckPacketSequence == nil { - return true - } - return *c.CheckPacketSequence -} - -func (c *Config) RandomizeSignaturesViaNotation() bool { - if c == nil || c.NonDeterministicSignaturesViaNotation == nil { - return true - } - return *c.NonDeterministicSignaturesViaNotation -} - -func (c *Config) AllowAllKeyFlagsWhenMissing() bool { - if c == nil { - return false - } - return c.InsecureAllowAllKeyFlagsWhenMissing -} - -func (c *Config) DecompressedMessageSizeLimit() *int64 { - if c == nil { - return nil - } - return c.MaxDecompressedMessageSize -} - -// BoolPointer is a helper function to set a boolean pointer in the Config. -// e.g., config.CheckPacketSequence = BoolPointer(true) -func BoolPointer(value bool) *bool { - return &value -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go deleted file mode 100644 index f2415906..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !v5 - -package packet - -func init() { - V5Disabled = true -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go deleted file mode 100644 index b90bb289..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go +++ /dev/null @@ -1,584 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "bytes" - "crypto" - "crypto/rsa" - "encoding/binary" - "encoding/hex" - "io" - "math/big" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/ecdh" - "github.com/ProtonMail/go-crypto/openpgp/elgamal" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" - "github.com/ProtonMail/go-crypto/openpgp/x25519" - "github.com/ProtonMail/go-crypto/openpgp/x448" -) - -// EncryptedKey represents a public-key encrypted session key. See RFC 4880, -// section 5.1. -type EncryptedKey struct { - Version int - KeyId uint64 - KeyVersion int // v6 - KeyFingerprint []byte // v6 - Algo PublicKeyAlgorithm - CipherFunc CipherFunction // only valid after a successful Decrypt for a v3 packet - Key []byte // only valid after a successful Decrypt - - encryptedMPI1, encryptedMPI2 encoding.Field - ephemeralPublicX25519 *x25519.PublicKey // used for x25519 - ephemeralPublicX448 *x448.PublicKey // used for x448 - encryptedSession []byte // used for x25519 and x448 -} - -func (e *EncryptedKey) parse(r io.Reader) (err error) { - var buf [8]byte - _, err = readFull(r, buf[:versionSize]) - if err != nil { - return - } - e.Version = int(buf[0]) - if e.Version != 3 && e.Version != 6 { - return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) - } - if e.Version == 6 { - //Read a one-octet size of the following two fields. - if _, err = readFull(r, buf[:1]); err != nil { - return - } - // The size may also be zero, and the key version and - // fingerprint omitted for an "anonymous recipient" - if buf[0] != 0 { - // non-anonymous case - _, err = readFull(r, buf[:versionSize]) - if err != nil { - return - } - e.KeyVersion = int(buf[0]) - if e.KeyVersion != 4 && e.KeyVersion != 6 { - return errors.UnsupportedError("unknown public key version " + strconv.Itoa(e.KeyVersion)) - } - var fingerprint []byte - if e.KeyVersion == 6 { - fingerprint = make([]byte, fingerprintSizeV6) - } else if e.KeyVersion == 4 { - fingerprint = make([]byte, fingerprintSize) - } - _, err = readFull(r, fingerprint) - if err != nil { - return - } - e.KeyFingerprint = fingerprint - if e.KeyVersion == 6 { - e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[:keyIdSize]) - } else if e.KeyVersion == 4 { - e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[fingerprintSize-keyIdSize : fingerprintSize]) - } - } - } else { - _, err = readFull(r, buf[:8]) - if err != nil { - return - } - e.KeyId = binary.BigEndian.Uint64(buf[:keyIdSize]) - } - - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - e.Algo = PublicKeyAlgorithm(buf[0]) - var cipherFunction byte - switch e.Algo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - e.encryptedMPI1 = new(encoding.MPI) - if _, err = e.encryptedMPI1.ReadFrom(r); err != nil { - return - } - case PubKeyAlgoElGamal: - e.encryptedMPI1 = new(encoding.MPI) - if _, err = e.encryptedMPI1.ReadFrom(r); err != nil { - return - } - - e.encryptedMPI2 = new(encoding.MPI) - if _, err = e.encryptedMPI2.ReadFrom(r); err != nil { - return - } - case PubKeyAlgoECDH: - e.encryptedMPI1 = new(encoding.MPI) - if _, err = e.encryptedMPI1.ReadFrom(r); err != nil { - return - } - - e.encryptedMPI2 = new(encoding.OID) - if _, err = e.encryptedMPI2.ReadFrom(r); err != nil { - return - } - case PubKeyAlgoX25519: - e.ephemeralPublicX25519, e.encryptedSession, cipherFunction, err = x25519.DecodeFields(r, e.Version == 6) - if err != nil { - return - } - case PubKeyAlgoX448: - e.ephemeralPublicX448, e.encryptedSession, cipherFunction, err = x448.DecodeFields(r, e.Version == 6) - if err != nil { - return - } - } - if e.Version < 6 { - switch e.Algo { - case PubKeyAlgoX25519, PubKeyAlgoX448: - e.CipherFunc = CipherFunction(cipherFunction) - // Check for validiy is in the Decrypt method - } - } - - _, err = consumeAll(r) - return -} - -// Decrypt decrypts an encrypted session key with the given private key. The -// private key must have been decrypted first. -// If config is nil, sensible defaults will be used. -func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { - if e.Version < 6 && e.KeyId != 0 && e.KeyId != priv.KeyId { - return errors.InvalidArgumentError("cannot decrypt encrypted session key for key id " + strconv.FormatUint(e.KeyId, 16) + " with private key id " + strconv.FormatUint(priv.KeyId, 16)) - } - if e.Version == 6 && e.KeyVersion != 0 && !bytes.Equal(e.KeyFingerprint, priv.Fingerprint) { - return errors.InvalidArgumentError("cannot decrypt encrypted session key for key fingerprint " + hex.EncodeToString(e.KeyFingerprint) + " with private key fingerprint " + hex.EncodeToString(priv.Fingerprint)) - } - if e.Algo != priv.PubKeyAlgo { - return errors.InvalidArgumentError("cannot decrypt encrypted session key of type " + strconv.Itoa(int(e.Algo)) + " with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) - } - if priv.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - - var err error - var b []byte - - // TODO(agl): use session key decryption routines here to avoid - // padding oracle attacks. - switch priv.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - // Supports both *rsa.PrivateKey and crypto.Decrypter - k := priv.PrivateKey.(crypto.Decrypter) - b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.Bytes()), nil) - case PubKeyAlgoElGamal: - c1 := new(big.Int).SetBytes(e.encryptedMPI1.Bytes()) - c2 := new(big.Int).SetBytes(e.encryptedMPI2.Bytes()) - b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) - case PubKeyAlgoECDH: - vsG := e.encryptedMPI1.Bytes() - m := e.encryptedMPI2.Bytes() - oid := priv.PublicKey.oid.EncodedBytes() - fp := priv.PublicKey.Fingerprint[:] - if priv.PublicKey.Version == 5 { - // For v5 the, the fingerprint must be restricted to 20 bytes - fp = fp[:20] - } - b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, fp) - case PubKeyAlgoX25519: - b, err = x25519.Decrypt(priv.PrivateKey.(*x25519.PrivateKey), e.ephemeralPublicX25519, e.encryptedSession) - case PubKeyAlgoX448: - b, err = x448.Decrypt(priv.PrivateKey.(*x448.PrivateKey), e.ephemeralPublicX448, e.encryptedSession) - default: - err = errors.InvalidArgumentError("cannot decrypt encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) - } - if err != nil { - return err - } - - var key []byte - switch priv.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH: - keyOffset := 0 - if e.Version < 6 { - e.CipherFunc = CipherFunction(b[0]) - keyOffset = 1 - if !e.CipherFunc.IsSupported() { - return errors.UnsupportedError("unsupported encryption function") - } - } - key, err = decodeChecksumKey(b[keyOffset:]) - if err != nil { - return err - } - case PubKeyAlgoX25519, PubKeyAlgoX448: - if e.Version < 6 { - switch e.CipherFunc { - case CipherAES128, CipherAES192, CipherAES256: - break - default: - return errors.StructuralError("v3 PKESK mandates AES as cipher function for x25519 and x448") - } - } - key = b[:] - default: - return errors.UnsupportedError("unsupported algorithm for decryption") - } - e.Key = key - return nil -} - -// Serialize writes the encrypted key packet, e, to w. -func (e *EncryptedKey) Serialize(w io.Writer) error { - var encodedLength int - switch e.Algo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - encodedLength = int(e.encryptedMPI1.EncodedLength()) - case PubKeyAlgoElGamal: - encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength()) - case PubKeyAlgoECDH: - encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength()) - case PubKeyAlgoX25519: - encodedLength = x25519.EncodedFieldsLength(e.encryptedSession, e.Version == 6) - case PubKeyAlgoX448: - encodedLength = x448.EncodedFieldsLength(e.encryptedSession, e.Version == 6) - default: - return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) - } - - packetLen := versionSize /* version */ + keyIdSize /* key id */ + algorithmSize /* algo */ + encodedLength - if e.Version == 6 { - packetLen = versionSize /* version */ + algorithmSize /* algo */ + encodedLength + keyVersionSize /* key version */ - if e.KeyVersion == 6 { - packetLen += fingerprintSizeV6 - } else if e.KeyVersion == 4 { - packetLen += fingerprintSize - } - } - - err := serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - - _, err = w.Write([]byte{byte(e.Version)}) - if err != nil { - return err - } - if e.Version == 6 { - _, err = w.Write([]byte{byte(e.KeyVersion)}) - if err != nil { - return err - } - // The key version number may also be zero, - // and the fingerprint omitted - if e.KeyVersion != 0 { - _, err = w.Write(e.KeyFingerprint) - if err != nil { - return err - } - } - } else { - // Write KeyID - err = binary.Write(w, binary.BigEndian, e.KeyId) - if err != nil { - return err - } - } - _, err = w.Write([]byte{byte(e.Algo)}) - if err != nil { - return err - } - - switch e.Algo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - _, err := w.Write(e.encryptedMPI1.EncodedBytes()) - return err - case PubKeyAlgoElGamal: - if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil { - return err - } - _, err := w.Write(e.encryptedMPI2.EncodedBytes()) - return err - case PubKeyAlgoECDH: - if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil { - return err - } - _, err := w.Write(e.encryptedMPI2.EncodedBytes()) - return err - case PubKeyAlgoX25519: - err := x25519.EncodeFields(w, e.ephemeralPublicX25519, e.encryptedSession, byte(e.CipherFunc), e.Version == 6) - return err - case PubKeyAlgoX448: - err := x448.EncodeFields(w, e.ephemeralPublicX448, e.encryptedSession, byte(e.CipherFunc), e.Version == 6) - return err - default: - panic("internal error") - } -} - -// SerializeEncryptedKeyAEAD serializes an encrypted key packet to w that contains -// key, encrypted to pub. -// If aeadSupported is set, PKESK v6 is used, otherwise v3. -// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted. -// If config is nil, sensible defaults will be used. -func SerializeEncryptedKeyAEAD(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, config *Config) error { - return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, aeadSupported, key, false, config) -} - -// SerializeEncryptedKeyAEADwithHiddenOption serializes an encrypted key packet to w that contains -// key, encrypted to pub. -// Offers the hidden flag option to indicated if the PKESK packet should include a wildcard KeyID. -// If aeadSupported is set, PKESK v6 is used, otherwise v3. -// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted. -// If config is nil, sensible defaults will be used. -func SerializeEncryptedKeyAEADwithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, hidden bool, config *Config) error { - var buf [36]byte // max possible header size is v6 - lenHeaderWritten := versionSize - version := 3 - - if aeadSupported { - version = 6 - } - // An implementation MUST NOT generate ElGamal v6 PKESKs. - if version == 6 && pub.PubKeyAlgo == PubKeyAlgoElGamal { - return errors.InvalidArgumentError("ElGamal v6 PKESK are not allowed") - } - // In v3 PKESKs, for x25519 and x448, mandate using AES - if version == 3 && (pub.PubKeyAlgo == PubKeyAlgoX25519 || pub.PubKeyAlgo == PubKeyAlgoX448) { - switch cipherFunc { - case CipherAES128, CipherAES192, CipherAES256: - break - default: - return errors.InvalidArgumentError("v3 PKESK mandates AES for x25519 and x448") - } - } - - buf[0] = byte(version) - - // If hidden is set, the key should be hidden - // An implementation MAY accept or use a Key ID of all zeros, - // or a key version of zero and no key fingerprint, to hide the intended decryption key. - // See Section 5.1.8. in the open pgp crypto refresh - if version == 6 { - if !hidden { - // A one-octet size of the following two fields. - buf[1] = byte(keyVersionSize + len(pub.Fingerprint)) - // A one octet key version number. - buf[2] = byte(pub.Version) - lenHeaderWritten += keyVersionSize + 1 - // The fingerprint of the public key - copy(buf[lenHeaderWritten:lenHeaderWritten+len(pub.Fingerprint)], pub.Fingerprint) - lenHeaderWritten += len(pub.Fingerprint) - } else { - // The size may also be zero, and the key version - // and fingerprint omitted for an "anonymous recipient" - buf[1] = 0 - lenHeaderWritten += 1 - } - } else { - if !hidden { - binary.BigEndian.PutUint64(buf[versionSize:(versionSize+keyIdSize)], pub.KeyId) - } - lenHeaderWritten += keyIdSize - } - buf[lenHeaderWritten] = byte(pub.PubKeyAlgo) - lenHeaderWritten += algorithmSize - - var keyBlock []byte - switch pub.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH: - lenKeyBlock := len(key) + 2 - if version < 6 { - lenKeyBlock += 1 // cipher type included - } - keyBlock = make([]byte, lenKeyBlock) - keyOffset := 0 - if version < 6 { - keyBlock[0] = byte(cipherFunc) - keyOffset = 1 - } - encodeChecksumKey(keyBlock[keyOffset:], key) - case PubKeyAlgoX25519, PubKeyAlgoX448: - // algorithm is added in plaintext below - keyBlock = key - } - - switch pub.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: - return serializeEncryptedKeyRSA(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*rsa.PublicKey), keyBlock) - case PubKeyAlgoElGamal: - return serializeEncryptedKeyElGamal(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*elgamal.PublicKey), keyBlock) - case PubKeyAlgoECDH: - return serializeEncryptedKeyECDH(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint) - case PubKeyAlgoX25519: - return serializeEncryptedKeyX25519(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x25519.PublicKey), keyBlock, byte(cipherFunc), version) - case PubKeyAlgoX448: - return serializeEncryptedKeyX448(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x448.PublicKey), keyBlock, byte(cipherFunc), version) - case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: - return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) - } - - return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) -} - -// SerializeEncryptedKey serializes an encrypted key packet to w that contains -// key, encrypted to pub. -// PKESKv6 is used if config.AEAD() is not nil. -// If config is nil, sensible defaults will be used. -// Deprecated: Use SerializeEncryptedKeyAEAD instead. -func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { - return SerializeEncryptedKeyAEAD(w, pub, cipherFunc, config.AEAD() != nil, key, config) -} - -// SerializeEncryptedKeyWithHiddenOption serializes an encrypted key packet to w that contains -// key, encrypted to pub. PKESKv6 is used if config.AEAD() is not nil. -// The hidden option controls if the packet should be anonymous, i.e., omit key metadata. -// If config is nil, sensible defaults will be used. -// Deprecated: Use SerializeEncryptedKeyAEADwithHiddenOption instead. -func SerializeEncryptedKeyWithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, hidden bool, config *Config) error { - return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, config.AEAD() != nil, key, hidden, config) -} - -func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header []byte, pub *rsa.PublicKey, keyBlock []byte) error { - cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) - if err != nil { - return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) - } - - cipherMPI := encoding.NewMPI(cipherText) - packetLen := len(header) /* header length */ + int(cipherMPI.EncodedLength()) - - err = serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - _, err = w.Write(header[:]) - if err != nil { - return err - } - _, err = w.Write(cipherMPI.EncodedBytes()) - return err -} - -func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header []byte, pub *elgamal.PublicKey, keyBlock []byte) error { - c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) - if err != nil { - return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) - } - - packetLen := len(header) /* header length */ - packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 - packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 - - err = serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - _, err = w.Write(header[:]) - if err != nil { - return err - } - if _, err = w.Write(new(encoding.MPI).SetBig(c1).EncodedBytes()); err != nil { - return err - } - _, err = w.Write(new(encoding.MPI).SetBig(c2).EncodedBytes()) - return err -} - -func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header []byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error { - vsG, c, err := ecdh.Encrypt(rand, pub, keyBlock, oid.EncodedBytes(), fingerprint) - if err != nil { - return errors.InvalidArgumentError("ECDH encryption failed: " + err.Error()) - } - - g := encoding.NewMPI(vsG) - m := encoding.NewOID(c) - - packetLen := len(header) /* header length */ - packetLen += int(g.EncodedLength()) + int(m.EncodedLength()) - - err = serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - - _, err = w.Write(header[:]) - if err != nil { - return err - } - if _, err = w.Write(g.EncodedBytes()); err != nil { - return err - } - _, err = w.Write(m.EncodedBytes()) - return err -} - -func serializeEncryptedKeyX25519(w io.Writer, rand io.Reader, header []byte, pub *x25519.PublicKey, keyBlock []byte, cipherFunc byte, version int) error { - ephemeralPublicX25519, ciphertext, err := x25519.Encrypt(rand, pub, keyBlock) - if err != nil { - return errors.InvalidArgumentError("x25519 encryption failed: " + err.Error()) - } - - packetLen := len(header) /* header length */ - packetLen += x25519.EncodedFieldsLength(ciphertext, version == 6) - - err = serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - - _, err = w.Write(header[:]) - if err != nil { - return err - } - return x25519.EncodeFields(w, ephemeralPublicX25519, ciphertext, cipherFunc, version == 6) -} - -func serializeEncryptedKeyX448(w io.Writer, rand io.Reader, header []byte, pub *x448.PublicKey, keyBlock []byte, cipherFunc byte, version int) error { - ephemeralPublicX448, ciphertext, err := x448.Encrypt(rand, pub, keyBlock) - if err != nil { - return errors.InvalidArgumentError("x448 encryption failed: " + err.Error()) - } - - packetLen := len(header) /* header length */ - packetLen += x448.EncodedFieldsLength(ciphertext, version == 6) - - err = serializeHeader(w, packetTypeEncryptedKey, packetLen) - if err != nil { - return err - } - - _, err = w.Write(header[:]) - if err != nil { - return err - } - return x448.EncodeFields(w, ephemeralPublicX448, ciphertext, cipherFunc, version == 6) -} - -func checksumKeyMaterial(key []byte) uint16 { - var checksum uint16 - for _, v := range key { - checksum += uint16(v) - } - return checksum -} - -func decodeChecksumKey(msg []byte) (key []byte, err error) { - key = msg[:len(msg)-2] - expectedChecksum := uint16(msg[len(msg)-2])<<8 | uint16(msg[len(msg)-1]) - checksum := checksumKeyMaterial(key) - if checksum != expectedChecksum { - err = errors.StructuralError("session key checksum is incorrect") - } - return -} - -func encodeChecksumKey(buffer []byte, key []byte) { - copy(buffer, key) - checksum := checksumKeyMaterial(key) - buffer[len(key)] = byte(checksum >> 8) - buffer[len(key)+1] = byte(checksum) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go deleted file mode 100644 index 8a028c8a..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "encoding/binary" - "io" -) - -// LiteralData represents an encrypted file. See RFC 4880, section 5.9. -type LiteralData struct { - Format uint8 - IsBinary bool - FileName string - Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. - Body io.Reader -} - -// ForEyesOnly returns whether the contents of the LiteralData have been marked -// as especially sensitive. -func (l *LiteralData) ForEyesOnly() bool { - return l.FileName == "_CONSOLE" -} - -func (l *LiteralData) parse(r io.Reader) (err error) { - var buf [256]byte - - _, err = readFull(r, buf[:2]) - if err != nil { - return - } - - l.Format = buf[0] - l.IsBinary = l.Format == 'b' - fileNameLen := int(buf[1]) - - _, err = readFull(r, buf[:fileNameLen]) - if err != nil { - return - } - - l.FileName = string(buf[:fileNameLen]) - - _, err = readFull(r, buf[:4]) - if err != nil { - return - } - - l.Time = binary.BigEndian.Uint32(buf[:4]) - l.Body = r - return -} - -// SerializeLiteral serializes a literal data packet to w and returns a -// WriteCloser to which the data itself can be written and which MUST be closed -// on completion. The fileName is truncated to 255 bytes. -func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { - var buf [4]byte - buf[0] = 'b' - if !isBinary { - buf[0] = 'u' - } - if len(fileName) > 255 { - fileName = fileName[:255] - } - buf[1] = byte(len(fileName)) - - inner, err := serializeStreamHeader(w, packetTypeLiteralData) - if err != nil { - return - } - - _, err = inner.Write(buf[:2]) - if err != nil { - return - } - _, err = inner.Write([]byte(fileName)) - if err != nil { - return - } - binary.BigEndian.PutUint32(buf[:], time) - _, err = inner.Write(buf[:]) - if err != nil { - return - } - - plaintext = inner - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go deleted file mode 100644 index 1ee378ba..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go +++ /dev/null @@ -1,33 +0,0 @@ -package packet - -import ( - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -type Marker struct{} - -const markerString = "PGP" - -// parse just checks if the packet contains "PGP". -func (m *Marker) parse(reader io.Reader) error { - var buffer [3]byte - if _, err := io.ReadFull(reader, buffer[:]); err != nil { - return err - } - if string(buffer[:]) != markerString { - return errors.StructuralError("invalid marker packet") - } - return nil -} - -// SerializeMarker writes a marker packet to writer. -func SerializeMarker(writer io.Writer) error { - err := serializeHeader(writer, packetTypeMarker, len(markerString)) - if err != nil { - return err - } - _, err = writer.Write([]byte(markerString)) - return err -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/notation.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/notation.go deleted file mode 100644 index 2c3e3f50..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/notation.go +++ /dev/null @@ -1,29 +0,0 @@ -package packet - -// Notation type represents a Notation Data subpacket -// see https://tools.ietf.org/html/rfc4880#section-5.2.3.16 -type Notation struct { - Name string - Value []byte - IsCritical bool - IsHumanReadable bool -} - -func (notation *Notation) getData() []byte { - nameData := []byte(notation.Name) - nameLen := len(nameData) - valueLen := len(notation.Value) - - data := make([]byte, 8+nameLen+valueLen) - if notation.IsHumanReadable { - data[0] = 0x80 - } - - data[4] = byte(nameLen >> 8) - data[5] = byte(nameLen) - data[6] = byte(valueLen >> 8) - data[7] = byte(valueLen) - copy(data[8:8+nameLen], nameData) - copy(data[8+nameLen:], notation.Value) - return data -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go deleted file mode 100644 index 4f26d0a0..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2010 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. - -// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 - -package packet - -import ( - "crypto/cipher" -) - -type ocfbEncrypter struct { - b cipher.Block - fre []byte - outUsed int -} - -// An OCFBResyncOption determines if the "resynchronization step" of OCFB is -// performed. -type OCFBResyncOption bool - -const ( - OCFBResync OCFBResyncOption = true - OCFBNoResync OCFBResyncOption = false -) - -// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's -// cipher feedback mode using the given cipher.Block, and an initial amount of -// ciphertext. randData must be random bytes and be the same length as the -// cipher.Block's block size. Resync determines if the "resynchronization step" -// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on -// this point. -func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { - blockSize := block.BlockSize() - if len(randData) != blockSize { - return nil, nil - } - - x := &ocfbEncrypter{ - b: block, - fre: make([]byte, blockSize), - outUsed: 0, - } - prefix := make([]byte, blockSize+2) - - block.Encrypt(x.fre, x.fre) - for i := 0; i < blockSize; i++ { - prefix[i] = randData[i] ^ x.fre[i] - } - - block.Encrypt(x.fre, prefix[:blockSize]) - prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] - prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] - - if resync { - block.Encrypt(x.fre, prefix[2:]) - } else { - x.fre[0] = prefix[blockSize] - x.fre[1] = prefix[blockSize+1] - x.outUsed = 2 - } - return x, prefix -} - -func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { - for i := 0; i < len(src); i++ { - if x.outUsed == len(x.fre) { - x.b.Encrypt(x.fre, x.fre) - x.outUsed = 0 - } - - x.fre[x.outUsed] ^= src[i] - dst[i] = x.fre[x.outUsed] - x.outUsed++ - } -} - -type ocfbDecrypter struct { - b cipher.Block - fre []byte - outUsed int -} - -// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's -// cipher feedback mode using the given cipher.Block. Prefix must be the first -// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's -// block size. On successful exit, blockSize+2 bytes of decrypted data are written into -// prefix. Resync determines if the "resynchronization step" from RFC 4880, -// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. -func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { - blockSize := block.BlockSize() - if len(prefix) != blockSize+2 { - return nil - } - - x := &ocfbDecrypter{ - b: block, - fre: make([]byte, blockSize), - outUsed: 0, - } - prefixCopy := make([]byte, len(prefix)) - copy(prefixCopy, prefix) - - block.Encrypt(x.fre, x.fre) - for i := 0; i < blockSize; i++ { - prefixCopy[i] ^= x.fre[i] - } - - block.Encrypt(x.fre, prefix[:blockSize]) - prefixCopy[blockSize] ^= x.fre[0] - prefixCopy[blockSize+1] ^= x.fre[1] - - if resync { - block.Encrypt(x.fre, prefix[2:]) - } else { - x.fre[0] = prefix[blockSize] - x.fre[1] = prefix[blockSize+1] - x.outUsed = 2 - } - copy(prefix, prefixCopy) - return x -} - -func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { - for i := 0; i < len(src); i++ { - if x.outUsed == len(x.fre) { - x.b.Encrypt(x.fre, x.fre) - x.outUsed = 0 - } - - c := src[i] - dst[i] = x.fre[x.outUsed] ^ src[i] - x.fre[x.outUsed] = c - x.outUsed++ - } -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go deleted file mode 100644 index f393c406..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "crypto" - "encoding/binary" - "io" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" -) - -// OnePassSignature represents a one-pass signature packet. See RFC 4880, -// section 5.4. -type OnePassSignature struct { - Version int - SigType SignatureType - Hash crypto.Hash - PubKeyAlgo PublicKeyAlgorithm - KeyId uint64 - IsLast bool - Salt []byte // v6 only - KeyFingerprint []byte // v6 only -} - -func (ops *OnePassSignature) parse(r io.Reader) (err error) { - var buf [8]byte - // Read: version | signature type | hash algorithm | public-key algorithm - _, err = readFull(r, buf[:4]) - if err != nil { - return - } - if buf[0] != 3 && buf[0] != 6 { - return errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) - } - ops.Version = int(buf[0]) - - var ok bool - ops.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2]) - if !ok { - return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) - } - - ops.SigType = SignatureType(buf[1]) - ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) - - if ops.Version == 6 { - // Only for v6, a variable-length field containing the salt - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - saltLength := int(buf[0]) - var expectedSaltLength int - expectedSaltLength, err = SaltLengthForHash(ops.Hash) - if err != nil { - return - } - if saltLength != expectedSaltLength { - err = errors.StructuralError("unexpected salt size for the given hash algorithm") - return - } - salt := make([]byte, expectedSaltLength) - _, err = readFull(r, salt) - if err != nil { - return - } - ops.Salt = salt - - // Only for v6 packets, 32 octets of the fingerprint of the signing key. - fingerprint := make([]byte, 32) - _, err = readFull(r, fingerprint) - if err != nil { - return - } - ops.KeyFingerprint = fingerprint - ops.KeyId = binary.BigEndian.Uint64(ops.KeyFingerprint[:8]) - } else { - _, err = readFull(r, buf[:8]) - if err != nil { - return - } - ops.KeyId = binary.BigEndian.Uint64(buf[:8]) - } - - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - ops.IsLast = buf[0] != 0 - return -} - -// Serialize marshals the given OnePassSignature to w. -func (ops *OnePassSignature) Serialize(w io.Writer) error { - //v3 length 1+1+1+1+8+1 = - packetLength := 13 - if ops.Version == 6 { - // v6 length 1+1+1+1+1+len(salt)+32+1 = - packetLength = 38 + len(ops.Salt) - } - - if err := serializeHeader(w, packetTypeOnePassSignature, packetLength); err != nil { - return err - } - - var buf [8]byte - buf[0] = byte(ops.Version) - buf[1] = uint8(ops.SigType) - var ok bool - buf[2], ok = algorithm.HashToHashIdWithSha1(ops.Hash) - if !ok { - return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) - } - buf[3] = uint8(ops.PubKeyAlgo) - - _, err := w.Write(buf[:4]) - if err != nil { - return err - } - - if ops.Version == 6 { - // write salt for v6 signatures - _, err := w.Write([]byte{uint8(len(ops.Salt))}) - if err != nil { - return err - } - _, err = w.Write(ops.Salt) - if err != nil { - return err - } - - // write fingerprint v6 signatures - _, err = w.Write(ops.KeyFingerprint) - if err != nil { - return err - } - } else { - binary.BigEndian.PutUint64(buf[:8], ops.KeyId) - _, err := w.Write(buf[:8]) - if err != nil { - return err - } - } - - isLast := []byte{byte(0)} - if ops.IsLast { - isLast[0] = 1 - } - - _, err = w.Write(isLast) - return err -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go deleted file mode 100644 index cef7c661..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is -// useful for splitting and storing the original packet contents separately, -// handling unsupported packet types or accessing parts of the packet not yet -// implemented by this package. -type OpaquePacket struct { - // Packet type - Tag uint8 - // Reason why the packet was parsed opaquely - Reason error - // Binary contents of the packet data - Contents []byte -} - -func (op *OpaquePacket) parse(r io.Reader) (err error) { - op.Contents, err = io.ReadAll(r) - return -} - -// Serialize marshals the packet to a writer in its original form, including -// the packet header. -func (op *OpaquePacket) Serialize(w io.Writer) (err error) { - err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) - if err == nil { - _, err = w.Write(op.Contents) - } - return -} - -// Parse attempts to parse the opaque contents into a structure supported by -// this package. If the packet is not known then the result will be another -// OpaquePacket. -func (op *OpaquePacket) Parse() (p Packet, err error) { - hdr := bytes.NewBuffer(nil) - err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) - if err != nil { - op.Reason = err - return op, err - } - p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) - if err != nil { - op.Reason = err - p = op - } - return -} - -// OpaqueReader reads OpaquePackets from an io.Reader. -type OpaqueReader struct { - r io.Reader -} - -func NewOpaqueReader(r io.Reader) *OpaqueReader { - return &OpaqueReader{r: r} -} - -// Read the next OpaquePacket. -func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { - tag, _, contents, err := readHeader(or.r) - if err != nil { - return - } - op = &OpaquePacket{Tag: uint8(tag), Reason: err} - err = op.parse(contents) - if err != nil { - consumeAll(contents) - } - return -} - -// OpaqueSubpacket represents an unparsed OpenPGP subpacket, -// as found in signature and user attribute packets. -type OpaqueSubpacket struct { - SubType uint8 - EncodedLength []byte // Store the original encoded length for signature verifications. - Contents []byte -} - -// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from -// their byte representation. -func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { - var ( - subHeaderLen int - subPacket *OpaqueSubpacket - ) - for len(contents) > 0 { - subHeaderLen, subPacket, err = nextSubpacket(contents) - if err != nil { - break - } - result = append(result, subPacket) - contents = contents[subHeaderLen+len(subPacket.Contents):] - } - return -} - -func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { - // RFC 4880, section 5.2.3.1 - var subLen uint32 - var encodedLength []byte - if len(contents) < 1 { - goto Truncated - } - subPacket = &OpaqueSubpacket{} - switch { - case contents[0] < 192: - subHeaderLen = 2 // 1 length byte, 1 subtype byte - if len(contents) < subHeaderLen { - goto Truncated - } - encodedLength = contents[0:1] - subLen = uint32(contents[0]) - contents = contents[1:] - case contents[0] < 255: - subHeaderLen = 3 // 2 length bytes, 1 subtype - if len(contents) < subHeaderLen { - goto Truncated - } - encodedLength = contents[0:2] - subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 - contents = contents[2:] - default: - subHeaderLen = 6 // 5 length bytes, 1 subtype - if len(contents) < subHeaderLen { - goto Truncated - } - encodedLength = contents[0:5] - subLen = uint32(contents[1])<<24 | - uint32(contents[2])<<16 | - uint32(contents[3])<<8 | - uint32(contents[4]) - contents = contents[5:] - - } - if subLen > uint32(len(contents)) || subLen == 0 { - goto Truncated - } - subPacket.SubType = contents[0] - subPacket.EncodedLength = encodedLength - subPacket.Contents = contents[1:subLen] - return -Truncated: - err = errors.StructuralError("subpacket truncated") - return -} - -func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { - buf := make([]byte, 6) - copy(buf, osp.EncodedLength) - n := len(osp.EncodedLength) - - buf[n] = osp.SubType - if _, err = w.Write(buf[:n+1]); err != nil { - return - } - _, err = w.Write(osp.Contents) - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go deleted file mode 100644 index 1e92e22c..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright 2011 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 packet implements parsing and serialization of OpenPGP packets, as -// specified in RFC 4880. -package packet // import "github.com/ProtonMail/go-crypto/openpgp/packet" - -import ( - "bytes" - "crypto/cipher" - "crypto/rsa" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" -) - -// readFull is the same as io.ReadFull except that reading zero bytes returns -// ErrUnexpectedEOF rather than EOF. -func readFull(r io.Reader, buf []byte) (n int, err error) { - n, err = io.ReadFull(r, buf) - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return -} - -// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. -func readLength(r io.Reader) (length int64, isPartial bool, err error) { - var buf [4]byte - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - switch { - case buf[0] < 192: - length = int64(buf[0]) - case buf[0] < 224: - length = int64(buf[0]-192) << 8 - _, err = readFull(r, buf[0:1]) - if err != nil { - return - } - length += int64(buf[0]) + 192 - case buf[0] < 255: - length = int64(1) << (buf[0] & 0x1f) - isPartial = true - default: - _, err = readFull(r, buf[0:4]) - if err != nil { - return - } - length = int64(buf[0])<<24 | - int64(buf[1])<<16 | - int64(buf[2])<<8 | - int64(buf[3]) - } - return -} - -// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. -// The continuation lengths are parsed and removed from the stream and EOF is -// returned at the end of the packet. See RFC 4880, section 4.2.2.4. -type partialLengthReader struct { - r io.Reader - remaining int64 - isPartial bool -} - -func (r *partialLengthReader) Read(p []byte) (n int, err error) { - for r.remaining == 0 { - if !r.isPartial { - return 0, io.EOF - } - r.remaining, r.isPartial, err = readLength(r.r) - if err != nil { - return 0, err - } - } - - toRead := int64(len(p)) - if toRead > r.remaining { - toRead = r.remaining - } - - n, err = r.r.Read(p[:int(toRead)]) - r.remaining -= int64(n) - if n < int(toRead) && err == io.EOF { - err = io.ErrUnexpectedEOF - } - return -} - -// partialLengthWriter writes a stream of data using OpenPGP partial lengths. -// See RFC 4880, section 4.2.2.4. -type partialLengthWriter struct { - w io.WriteCloser - buf bytes.Buffer - lengthByte [1]byte -} - -func (w *partialLengthWriter) Write(p []byte) (n int, err error) { - bufLen := w.buf.Len() - if bufLen > 512 { - for power := uint(30); ; power-- { - l := 1 << power - if bufLen >= l { - w.lengthByte[0] = 224 + uint8(power) - _, err = w.w.Write(w.lengthByte[:]) - if err != nil { - return - } - var m int - m, err = w.w.Write(w.buf.Next(l)) - if err != nil { - return - } - if m != l { - return 0, io.ErrShortWrite - } - break - } - } - } - return w.buf.Write(p) -} - -func (w *partialLengthWriter) Close() (err error) { - len := w.buf.Len() - err = serializeLength(w.w, len) - if err != nil { - return err - } - _, err = w.buf.WriteTo(w.w) - if err != nil { - return err - } - return w.w.Close() -} - -// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the -// underlying Reader returns EOF before the limit has been reached. -type spanReader struct { - r io.Reader - n int64 -} - -func (l *spanReader) Read(p []byte) (n int, err error) { - if l.n <= 0 { - return 0, io.EOF - } - if int64(len(p)) > l.n { - p = p[0:l.n] - } - n, err = l.r.Read(p) - l.n -= int64(n) - if l.n > 0 && err == io.EOF { - err = io.ErrUnexpectedEOF - } - return -} - -// readHeader parses a packet header and returns an io.Reader which will return -// the contents of the packet. See RFC 4880, section 4.2. -func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { - var buf [4]byte - _, err = io.ReadFull(r, buf[:1]) - if err != nil { - return - } - if buf[0]&0x80 == 0 { - err = errors.StructuralError("tag byte does not have MSB set") - return - } - if buf[0]&0x40 == 0 { - // Old format packet - tag = packetType((buf[0] & 0x3f) >> 2) - lengthType := buf[0] & 3 - if lengthType == 3 { - length = -1 - contents = r - return - } - lengthBytes := 1 << lengthType - _, err = readFull(r, buf[0:lengthBytes]) - if err != nil { - return - } - for i := 0; i < lengthBytes; i++ { - length <<= 8 - length |= int64(buf[i]) - } - contents = &spanReader{r, length} - return - } - - // New format packet - tag = packetType(buf[0] & 0x3f) - length, isPartial, err := readLength(r) - if err != nil { - return - } - if isPartial { - contents = &partialLengthReader{ - remaining: length, - isPartial: true, - r: r, - } - length = -1 - } else { - contents = &spanReader{r, length} - } - return -} - -// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section -// 4.2. -func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { - err = serializeType(w, ptype) - if err != nil { - return - } - return serializeLength(w, length) -} - -// serializeType writes an OpenPGP packet type to w. See RFC 4880, section -// 4.2. -func serializeType(w io.Writer, ptype packetType) (err error) { - var buf [1]byte - buf[0] = 0x80 | 0x40 | byte(ptype) - _, err = w.Write(buf[:]) - return -} - -// serializeLength writes an OpenPGP packet length to w. See RFC 4880, section -// 4.2.2. -func serializeLength(w io.Writer, length int) (err error) { - var buf [5]byte - var n int - - if length < 192 { - buf[0] = byte(length) - n = 1 - } else if length < 8384 { - length -= 192 - buf[0] = 192 + byte(length>>8) - buf[1] = byte(length) - n = 2 - } else { - buf[0] = 255 - buf[1] = byte(length >> 24) - buf[2] = byte(length >> 16) - buf[3] = byte(length >> 8) - buf[4] = byte(length) - n = 5 - } - - _, err = w.Write(buf[:n]) - return -} - -// serializeStreamHeader writes an OpenPGP packet header to w where the -// length of the packet is unknown. It returns a io.WriteCloser which can be -// used to write the contents of the packet. See RFC 4880, section 4.2. -func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { - err = serializeType(w, ptype) - if err != nil { - return - } - out = &partialLengthWriter{w: w} - return -} - -// Packet represents an OpenPGP packet. Users are expected to try casting -// instances of this interface to specific packet types. -type Packet interface { - parse(io.Reader) error -} - -// consumeAll reads from the given Reader until error, returning the number of -// bytes read. -func consumeAll(r io.Reader) (n int64, err error) { - var m int - var buf [1024]byte - - for { - m, err = r.Read(buf[:]) - n += int64(m) - if err == io.EOF { - err = nil - return - } - if err != nil { - return - } - } -} - -// packetType represents the numeric ids of the different OpenPGP packet types. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 -type packetType uint8 - -const ( - packetTypeEncryptedKey packetType = 1 - packetTypeSignature packetType = 2 - packetTypeSymmetricKeyEncrypted packetType = 3 - packetTypeOnePassSignature packetType = 4 - packetTypePrivateKey packetType = 5 - packetTypePublicKey packetType = 6 - packetTypePrivateSubkey packetType = 7 - packetTypeCompressed packetType = 8 - packetTypeSymmetricallyEncrypted packetType = 9 - packetTypeMarker packetType = 10 - packetTypeLiteralData packetType = 11 - packetTypeTrust packetType = 12 - packetTypeUserId packetType = 13 - packetTypePublicSubkey packetType = 14 - packetTypeUserAttribute packetType = 17 - packetTypeSymmetricallyEncryptedIntegrityProtected packetType = 18 - packetTypeAEADEncrypted packetType = 20 - packetPadding packetType = 21 -) - -// EncryptedDataPacket holds encrypted data. It is currently implemented by -// SymmetricallyEncrypted and AEADEncrypted. -type EncryptedDataPacket interface { - Decrypt(CipherFunction, []byte) (io.ReadCloser, error) -} - -// Read reads a single OpenPGP packet from the given io.Reader. If there is an -// error parsing a packet, the whole packet is consumed from the input. -func Read(r io.Reader) (p Packet, err error) { - tag, len, contents, err := readHeader(r) - if err != nil { - return - } - - switch tag { - case packetTypeEncryptedKey: - p = new(EncryptedKey) - case packetTypeSignature: - p = new(Signature) - case packetTypeSymmetricKeyEncrypted: - p = new(SymmetricKeyEncrypted) - case packetTypeOnePassSignature: - p = new(OnePassSignature) - case packetTypePrivateKey, packetTypePrivateSubkey: - pk := new(PrivateKey) - if tag == packetTypePrivateSubkey { - pk.IsSubkey = true - } - p = pk - case packetTypePublicKey, packetTypePublicSubkey: - isSubkey := tag == packetTypePublicSubkey - p = &PublicKey{IsSubkey: isSubkey} - case packetTypeCompressed: - p = new(Compressed) - case packetTypeSymmetricallyEncrypted: - p = new(SymmetricallyEncrypted) - case packetTypeLiteralData: - p = new(LiteralData) - case packetTypeUserId: - p = new(UserId) - case packetTypeUserAttribute: - p = new(UserAttribute) - case packetTypeSymmetricallyEncryptedIntegrityProtected: - se := new(SymmetricallyEncrypted) - se.IntegrityProtected = true - p = se - case packetTypeAEADEncrypted: - p = new(AEADEncrypted) - case packetPadding: - p = Padding(len) - case packetTypeMarker: - p = new(Marker) - case packetTypeTrust: - // Not implemented, just consume - err = errors.UnknownPacketTypeError(tag) - default: - // Packet Tags from 0 to 39 are critical. - // Packet Tags from 40 to 63 are non-critical. - if tag < 40 { - err = errors.CriticalUnknownPacketTypeError(tag) - } else { - err = errors.UnknownPacketTypeError(tag) - } - } - if p != nil { - err = p.parse(contents) - } - if err != nil { - consumeAll(contents) - } - return -} - -// ReadWithCheck reads a single OpenPGP message packet from the given io.Reader. If there is an -// error parsing a packet, the whole packet is consumed from the input. -// ReadWithCheck additionally checks if the OpenPGP message packet sequence adheres -// to the packet composition rules in rfc4880, if not throws an error. -func ReadWithCheck(r io.Reader, sequence *SequenceVerifier) (p Packet, msgErr error, err error) { - tag, len, contents, err := readHeader(r) - if err != nil { - return - } - switch tag { - case packetTypeEncryptedKey: - msgErr = sequence.Next(ESKSymbol) - p = new(EncryptedKey) - case packetTypeSignature: - msgErr = sequence.Next(SigSymbol) - p = new(Signature) - case packetTypeSymmetricKeyEncrypted: - msgErr = sequence.Next(ESKSymbol) - p = new(SymmetricKeyEncrypted) - case packetTypeOnePassSignature: - msgErr = sequence.Next(OPSSymbol) - p = new(OnePassSignature) - case packetTypeCompressed: - msgErr = sequence.Next(CompSymbol) - p = new(Compressed) - case packetTypeSymmetricallyEncrypted: - msgErr = sequence.Next(EncSymbol) - p = new(SymmetricallyEncrypted) - case packetTypeLiteralData: - msgErr = sequence.Next(LDSymbol) - p = new(LiteralData) - case packetTypeSymmetricallyEncryptedIntegrityProtected: - msgErr = sequence.Next(EncSymbol) - se := new(SymmetricallyEncrypted) - se.IntegrityProtected = true - p = se - case packetTypeAEADEncrypted: - msgErr = sequence.Next(EncSymbol) - p = new(AEADEncrypted) - case packetPadding: - p = Padding(len) - case packetTypeMarker: - p = new(Marker) - case packetTypeTrust: - // Not implemented, just consume - err = errors.UnknownPacketTypeError(tag) - case packetTypePrivateKey, - packetTypePrivateSubkey, - packetTypePublicKey, - packetTypePublicSubkey, - packetTypeUserId, - packetTypeUserAttribute: - msgErr = sequence.Next(UnknownSymbol) - consumeAll(contents) - default: - // Packet Tags from 0 to 39 are critical. - // Packet Tags from 40 to 63 are non-critical. - if tag < 40 { - err = errors.CriticalUnknownPacketTypeError(tag) - } else { - err = errors.UnknownPacketTypeError(tag) - } - } - if p != nil { - err = p.parse(contents) - } - if err != nil { - consumeAll(contents) - } - return -} - -// SignatureType represents the different semantic meanings of an OpenPGP -// signature. See RFC 4880, section 5.2.1. -type SignatureType uint8 - -const ( - SigTypeBinary SignatureType = 0x00 - SigTypeText SignatureType = 0x01 - SigTypeGenericCert SignatureType = 0x10 - SigTypePersonaCert SignatureType = 0x11 - SigTypeCasualCert SignatureType = 0x12 - SigTypePositiveCert SignatureType = 0x13 - SigTypeSubkeyBinding SignatureType = 0x18 - SigTypePrimaryKeyBinding SignatureType = 0x19 - SigTypeDirectSignature SignatureType = 0x1F - SigTypeKeyRevocation SignatureType = 0x20 - SigTypeSubkeyRevocation SignatureType = 0x28 - SigTypeCertificationRevocation SignatureType = 0x30 -) - -// PublicKeyAlgorithm represents the different public key system specified for -// OpenPGP. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 -type PublicKeyAlgorithm uint8 - -const ( - PubKeyAlgoRSA PublicKeyAlgorithm = 1 - PubKeyAlgoElGamal PublicKeyAlgorithm = 16 - PubKeyAlgoDSA PublicKeyAlgorithm = 17 - // RFC 6637, Section 5. - PubKeyAlgoECDH PublicKeyAlgorithm = 18 - PubKeyAlgoECDSA PublicKeyAlgorithm = 19 - // https://www.ietf.org/archive/id/draft-koch-eddsa-for-openpgp-04.txt - PubKeyAlgoEdDSA PublicKeyAlgorithm = 22 - // https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh - PubKeyAlgoX25519 PublicKeyAlgorithm = 25 - PubKeyAlgoX448 PublicKeyAlgorithm = 26 - PubKeyAlgoEd25519 PublicKeyAlgorithm = 27 - PubKeyAlgoEd448 PublicKeyAlgorithm = 28 - - // Deprecated in RFC 4880, Section 13.5. Use key flags instead. - PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 - PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 -) - -// CanEncrypt returns true if it's possible to encrypt a message to a public -// key of the given type. -func (pka PublicKeyAlgorithm) CanEncrypt() bool { - switch pka { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH, PubKeyAlgoX25519, PubKeyAlgoX448: - return true - } - return false -} - -// CanSign returns true if it's possible for a public key of the given type to -// sign a message. -func (pka PublicKeyAlgorithm) CanSign() bool { - switch pka { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA, PubKeyAlgoEd25519, PubKeyAlgoEd448: - return true - } - return false -} - -// CipherFunction represents the different block ciphers specified for OpenPGP. See -// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 -type CipherFunction algorithm.CipherFunction - -const ( - Cipher3DES CipherFunction = 2 - CipherCAST5 CipherFunction = 3 - CipherAES128 CipherFunction = 7 - CipherAES192 CipherFunction = 8 - CipherAES256 CipherFunction = 9 -) - -// KeySize returns the key size, in bytes, of cipher. -func (cipher CipherFunction) KeySize() int { - return algorithm.CipherFunction(cipher).KeySize() -} - -// IsSupported returns true if the cipher is supported from the library -func (cipher CipherFunction) IsSupported() bool { - return algorithm.CipherFunction(cipher).KeySize() > 0 -} - -// blockSize returns the block size, in bytes, of cipher. -func (cipher CipherFunction) blockSize() int { - return algorithm.CipherFunction(cipher).BlockSize() -} - -// new returns a fresh instance of the given cipher. -func (cipher CipherFunction) new(key []byte) (block cipher.Block) { - return algorithm.CipherFunction(cipher).New(key) -} - -// padToKeySize left-pads a MPI with zeroes to match the length of the -// specified RSA public. -func padToKeySize(pub *rsa.PublicKey, b []byte) []byte { - k := (pub.N.BitLen() + 7) / 8 - if len(b) >= k { - return b - } - bb := make([]byte, k) - copy(bb[len(bb)-len(b):], b) - return bb -} - -// CompressionAlgo Represents the different compression algorithms -// supported by OpenPGP (except for BZIP2, which is not currently -// supported). See Section 9.3 of RFC 4880. -type CompressionAlgo uint8 - -const ( - CompressionNone CompressionAlgo = 0 - CompressionZIP CompressionAlgo = 1 - CompressionZLIB CompressionAlgo = 2 -) - -// AEADMode represents the different Authenticated Encryption with Associated -// Data specified for OpenPGP. -// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.6 -type AEADMode algorithm.AEADMode - -const ( - AEADModeEAX AEADMode = 1 - AEADModeOCB AEADMode = 2 - AEADModeGCM AEADMode = 3 -) - -func (mode AEADMode) IvLength() int { - return algorithm.AEADMode(mode).NonceLength() -} - -func (mode AEADMode) TagLength() int { - return algorithm.AEADMode(mode).TagLength() -} - -// IsSupported returns true if the aead mode is supported from the library -func (mode AEADMode) IsSupported() bool { - return algorithm.AEADMode(mode).TagLength() > 0 -} - -// new returns a fresh instance of the given mode. -func (mode AEADMode) new(block cipher.Block) cipher.AEAD { - return algorithm.AEADMode(mode).New(block) -} - -// ReasonForRevocation represents a revocation reason code as per RFC4880 -// section 5.2.3.23. -type ReasonForRevocation uint8 - -const ( - NoReason ReasonForRevocation = 0 - KeySuperseded ReasonForRevocation = 1 - KeyCompromised ReasonForRevocation = 2 - KeyRetired ReasonForRevocation = 3 - UserIDNotValid ReasonForRevocation = 32 - Unknown ReasonForRevocation = 200 -) - -func NewReasonForRevocation(value byte) ReasonForRevocation { - if value < 4 || value == 32 { - return ReasonForRevocation(value) - } - return Unknown -} - -// Curve is a mapping to supported ECC curves for key generation. -// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-06.html#name-curve-specific-wire-formats -type Curve string - -const ( - Curve25519 Curve = "Curve25519" - Curve448 Curve = "Curve448" - CurveNistP256 Curve = "P256" - CurveNistP384 Curve = "P384" - CurveNistP521 Curve = "P521" - CurveSecP256k1 Curve = "SecP256k1" - CurveBrainpoolP256 Curve = "BrainpoolP256" - CurveBrainpoolP384 Curve = "BrainpoolP384" - CurveBrainpoolP512 Curve = "BrainpoolP512" -) - -// TrustLevel represents a trust level per RFC4880 5.2.3.13 -type TrustLevel uint8 - -// TrustAmount represents a trust amount per RFC4880 5.2.3.13 -type TrustAmount uint8 - -const ( - // versionSize is the length in bytes of the version value. - versionSize = 1 - // algorithmSize is the length in bytes of the key algorithm value. - algorithmSize = 1 - // keyVersionSize is the length in bytes of the key version value - keyVersionSize = 1 - // keyIdSize is the length in bytes of the key identifier value. - keyIdSize = 8 - // timestampSize is the length in bytes of encoded timestamps. - timestampSize = 4 - // fingerprintSizeV6 is the length in bytes of the key fingerprint in v6. - fingerprintSizeV6 = 32 - // fingerprintSize is the length in bytes of the key fingerprint. - fingerprintSize = 20 -) diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go deleted file mode 100644 index 55a8a56c..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go +++ /dev/null @@ -1,222 +0,0 @@ -package packet - -// This file implements the pushdown automata (PDA) from PGPainless (Paul Schaub) -// to verify pgp packet sequences. See Paul's blogpost for more details: -// https://blog.jabberhead.tk/2022/10/26/implementing-packet-sequence-validation-using-pushdown-automata/ -import ( - "fmt" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -func NewErrMalformedMessage(from State, input InputSymbol, stackSymbol StackSymbol) errors.ErrMalformedMessage { - return errors.ErrMalformedMessage(fmt.Sprintf("state %d, input symbol %d, stack symbol %d ", from, input, stackSymbol)) -} - -// InputSymbol defines the input alphabet of the PDA -type InputSymbol uint8 - -const ( - LDSymbol InputSymbol = iota - SigSymbol - OPSSymbol - CompSymbol - ESKSymbol - EncSymbol - EOSSymbol - UnknownSymbol -) - -// StackSymbol defines the stack alphabet of the PDA -type StackSymbol int8 - -const ( - MsgStackSymbol StackSymbol = iota - OpsStackSymbol - KeyStackSymbol - EndStackSymbol - EmptyStackSymbol -) - -// State defines the states of the PDA -type State int8 - -const ( - OpenPGPMessage State = iota - ESKMessage - LiteralMessage - CompressedMessage - EncryptedMessage - ValidMessage -) - -// transition represents a state transition in the PDA -type transition func(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) - -// SequenceVerifier is a pushdown automata to verify -// PGP messages packet sequences according to rfc4880. -type SequenceVerifier struct { - stack []StackSymbol - state State -} - -// Next performs a state transition with the given input symbol. -// If the transition fails a ErrMalformedMessage is returned. -func (sv *SequenceVerifier) Next(input InputSymbol) error { - for { - stackSymbol := sv.popStack() - transitionFunc := getTransition(sv.state) - nextState, newStackSymbols, redo, err := transitionFunc(input, stackSymbol) - if err != nil { - return err - } - if redo { - sv.pushStack(stackSymbol) - } - for _, newStackSymbol := range newStackSymbols { - sv.pushStack(newStackSymbol) - } - sv.state = nextState - if !redo { - break - } - } - return nil -} - -// Valid returns true if RDA is in a valid state. -func (sv *SequenceVerifier) Valid() bool { - return sv.state == ValidMessage && len(sv.stack) == 0 -} - -func (sv *SequenceVerifier) AssertValid() error { - if !sv.Valid() { - return errors.ErrMalformedMessage("invalid message") - } - return nil -} - -func NewSequenceVerifier() *SequenceVerifier { - return &SequenceVerifier{ - stack: []StackSymbol{EndStackSymbol, MsgStackSymbol}, - state: OpenPGPMessage, - } -} - -func (sv *SequenceVerifier) popStack() StackSymbol { - if len(sv.stack) == 0 { - return EmptyStackSymbol - } - elemIndex := len(sv.stack) - 1 - stackSymbol := sv.stack[elemIndex] - sv.stack = sv.stack[:elemIndex] - return stackSymbol -} - -func (sv *SequenceVerifier) pushStack(stackSymbol StackSymbol) { - sv.stack = append(sv.stack, stackSymbol) -} - -func getTransition(from State) transition { - switch from { - case OpenPGPMessage: - return fromOpenPGPMessage - case LiteralMessage: - return fromLiteralMessage - case CompressedMessage: - return fromCompressedMessage - case EncryptedMessage: - return fromEncryptedMessage - case ESKMessage: - return fromESKMessage - case ValidMessage: - return fromValidMessage - } - return nil -} - -// fromOpenPGPMessage is the transition for the state OpenPGPMessage. -func fromOpenPGPMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) { - if stackSymbol != MsgStackSymbol { - return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol) - } - switch input { - case LDSymbol: - return LiteralMessage, nil, false, nil - case SigSymbol: - return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, false, nil - case OPSSymbol: - return OpenPGPMessage, []StackSymbol{OpsStackSymbol, MsgStackSymbol}, false, nil - case CompSymbol: - return CompressedMessage, nil, false, nil - case ESKSymbol: - return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil - case EncSymbol: - return EncryptedMessage, nil, false, nil - } - return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol) -} - -// fromESKMessage is the transition for the state ESKMessage. -func fromESKMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) { - if stackSymbol != KeyStackSymbol { - return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol) - } - switch input { - case ESKSymbol: - return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil - case EncSymbol: - return EncryptedMessage, nil, false, nil - } - return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol) -} - -// fromLiteralMessage is the transition for the state LiteralMessage. -func fromLiteralMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) { - switch input { - case SigSymbol: - if stackSymbol == OpsStackSymbol { - return LiteralMessage, nil, false, nil - } - case EOSSymbol: - if stackSymbol == EndStackSymbol { - return ValidMessage, nil, false, nil - } - } - return 0, nil, false, NewErrMalformedMessage(LiteralMessage, input, stackSymbol) -} - -// fromLiteralMessage is the transition for the state CompressedMessage. -func fromCompressedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) { - switch input { - case SigSymbol: - if stackSymbol == OpsStackSymbol { - return CompressedMessage, nil, false, nil - } - case EOSSymbol: - if stackSymbol == EndStackSymbol { - return ValidMessage, nil, false, nil - } - } - return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil -} - -// fromEncryptedMessage is the transition for the state EncryptedMessage. -func fromEncryptedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) { - switch input { - case SigSymbol: - if stackSymbol == OpsStackSymbol { - return EncryptedMessage, nil, false, nil - } - case EOSSymbol: - if stackSymbol == EndStackSymbol { - return ValidMessage, nil, false, nil - } - } - return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil -} - -// fromValidMessage is the transition for the state ValidMessage. -func fromValidMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) { - return 0, nil, false, NewErrMalformedMessage(ValidMessage, input, stackSymbol) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go deleted file mode 100644 index 2d714723..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go +++ /dev/null @@ -1,24 +0,0 @@ -package packet - -import ( - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -// UnsupportedPackage represents a OpenPGP packet with a known packet type -// but with unsupported content. -type UnsupportedPacket struct { - IncompletePacket Packet - Error errors.UnsupportedError -} - -// Implements the Packet interface -func (up *UnsupportedPacket) parse(read io.Reader) error { - err := up.IncompletePacket.parse(read) - if castedErr, ok := err.(errors.UnsupportedError); ok { - up.Error = castedErr - return nil - } - return err -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go deleted file mode 100644 index 3b6a7045..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go +++ /dev/null @@ -1,26 +0,0 @@ -package packet - -import ( - "io" -) - -// Padding type represents a Padding Packet (Tag 21). -// The padding type is represented by the length of its padding. -// see https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-padding-packet-tag-21 -type Padding int - -// parse just ignores the padding content. -func (pad Padding) parse(reader io.Reader) error { - _, err := io.CopyN(io.Discard, reader, int64(pad)) - return err -} - -// SerializePadding writes the padding to writer. -func (pad Padding) SerializePadding(writer io.Writer, rand io.Reader) error { - err := serializeHeader(writer, packetPadding, int(pad)) - if err != nil { - return err - } - _, err = io.CopyN(writer, rand, int64(pad)) - return err -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go deleted file mode 100644 index f04e6c6b..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go +++ /dev/null @@ -1,1191 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "bytes" - "crypto" - "crypto/cipher" - "crypto/dsa" - "crypto/rsa" - "crypto/sha1" - "crypto/sha256" - "crypto/subtle" - "fmt" - "io" - "math/big" - "strconv" - "time" - - "github.com/ProtonMail/go-crypto/openpgp/ecdh" - "github.com/ProtonMail/go-crypto/openpgp/ecdsa" - "github.com/ProtonMail/go-crypto/openpgp/ed25519" - "github.com/ProtonMail/go-crypto/openpgp/ed448" - "github.com/ProtonMail/go-crypto/openpgp/eddsa" - "github.com/ProtonMail/go-crypto/openpgp/elgamal" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" - "github.com/ProtonMail/go-crypto/openpgp/s2k" - "github.com/ProtonMail/go-crypto/openpgp/x25519" - "github.com/ProtonMail/go-crypto/openpgp/x448" - "golang.org/x/crypto/hkdf" -) - -// PrivateKey represents a possibly encrypted private key. See RFC 4880, -// section 5.5.3. -type PrivateKey struct { - PublicKey - Encrypted bool // if true then the private key is unavailable until Decrypt has been called. - encryptedData []byte - cipher CipherFunction - s2k func(out, in []byte) - aead AEADMode // only relevant if S2KAEAD is enabled - // An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519|ed448}.PrivateKey or - // crypto.Signer/crypto.Decrypter (Decryptor RSA only). - PrivateKey interface{} - iv []byte - - // Type of encryption of the S2K packet - // Allowed values are 0 (Not encrypted), 253 (AEAD), 254 (SHA1), or - // 255 (2-byte checksum) - s2kType S2KType - // Full parameters of the S2K packet - s2kParams *s2k.Params -} - -// S2KType s2k packet type -type S2KType uint8 - -const ( - // S2KNON unencrypt - S2KNON S2KType = 0 - // S2KAEAD use authenticated encryption - S2KAEAD S2KType = 253 - // S2KSHA1 sha1 sum check - S2KSHA1 S2KType = 254 - // S2KCHECKSUM sum check - S2KCHECKSUM S2KType = 255 -) - -func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewEdDSAPrivateKey(creationTime time.Time, priv *eddsa.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewEdDSAPublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewECDHPrivateKey(creationTime time.Time, priv *ecdh.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewX25519PrivateKey(creationTime time.Time, priv *x25519.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewX448PrivateKey(creationTime time.Time, priv *x448.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewEd25519PrivateKey(creationTime time.Time, priv *ed25519.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewEd25519PublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -func NewEd448PrivateKey(creationTime time.Time, priv *ed448.PrivateKey) *PrivateKey { - pk := new(PrivateKey) - pk.PublicKey = *NewEd448PublicKey(creationTime, &priv.PublicKey) - pk.PrivateKey = priv - return pk -} - -// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that -// implements RSA, ECDSA or EdDSA. -func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey { - pk := new(PrivateKey) - // In general, the public Keys should be used as pointers. We still - // type-switch on the values, for backwards-compatibility. - switch pubkey := signer.(type) { - case *rsa.PrivateKey: - pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey.PublicKey) - case rsa.PrivateKey: - pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey.PublicKey) - case *ecdsa.PrivateKey: - pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey.PublicKey) - case ecdsa.PrivateKey: - pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey.PublicKey) - case *eddsa.PrivateKey: - pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey) - case eddsa.PrivateKey: - pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey) - case *ed25519.PrivateKey: - pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey) - case ed25519.PrivateKey: - pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey) - case *ed448.PrivateKey: - pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey) - case ed448.PrivateKey: - pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey) - default: - panic("openpgp: unknown signer type in NewSignerPrivateKey") - } - pk.PrivateKey = signer - return pk -} - -// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh|x25519|x448}.PrivateKey. -func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *PrivateKey { - pk := new(PrivateKey) - switch priv := decrypter.(type) { - case *rsa.PrivateKey: - pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) - case *elgamal.PrivateKey: - pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) - case *ecdh.PrivateKey: - pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey) - case *x25519.PrivateKey: - pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey) - case *x448.PrivateKey: - pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey) - default: - panic("openpgp: unknown decrypter type in NewDecrypterPrivateKey") - } - pk.PrivateKey = decrypter - return pk -} - -func (pk *PrivateKey) parse(r io.Reader) (err error) { - err = (&pk.PublicKey).parse(r) - if err != nil { - return - } - v5 := pk.PublicKey.Version == 5 - v6 := pk.PublicKey.Version == 6 - - if V5Disabled && v5 { - return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed") - } - - var buf [1]byte - _, err = readFull(r, buf[:]) - if err != nil { - return - } - pk.s2kType = S2KType(buf[0]) - var optCount [1]byte - if v5 || (v6 && pk.s2kType != S2KNON) { - if _, err = readFull(r, optCount[:]); err != nil { - return - } - } - - switch pk.s2kType { - case S2KNON: - pk.s2k = nil - pk.Encrypted = false - case S2KSHA1, S2KCHECKSUM, S2KAEAD: - if (v5 || v6) && pk.s2kType == S2KCHECKSUM { - return errors.StructuralError(fmt.Sprintf("wrong s2k identifier for version %d", pk.Version)) - } - _, err = readFull(r, buf[:]) - if err != nil { - return - } - pk.cipher = CipherFunction(buf[0]) - if pk.cipher != 0 && !pk.cipher.IsSupported() { - return errors.UnsupportedError("unsupported cipher function in private key") - } - // [Optional] If string-to-key usage octet was 253, - // a one-octet AEAD algorithm. - if pk.s2kType == S2KAEAD { - _, err = readFull(r, buf[:]) - if err != nil { - return - } - pk.aead = AEADMode(buf[0]) - if !pk.aead.IsSupported() { - return errors.UnsupportedError("unsupported aead mode in private key") - } - } - - // [Optional] Only for a version 6 packet, - // and if string-to-key usage octet was 255, 254, or 253, - // an one-octet count of the following field. - if v6 { - _, err = readFull(r, buf[:]) - if err != nil { - return - } - } - - pk.s2kParams, err = s2k.ParseIntoParams(r) - if err != nil { - return - } - if pk.s2kParams.Dummy() { - return - } - if pk.s2kParams.Mode() == s2k.Argon2S2K && pk.s2kType != S2KAEAD { - return errors.StructuralError("using Argon2 S2K without AEAD is not allowed") - } - if pk.s2kParams.Mode() == s2k.SimpleS2K && pk.Version == 6 { - return errors.StructuralError("using Simple S2K with version 6 keys is not allowed") - } - pk.s2k, err = pk.s2kParams.Function() - if err != nil { - return - } - pk.Encrypted = true - default: - return errors.UnsupportedError("deprecated s2k function in private key") - } - - if pk.Encrypted { - var ivSize int - // If the S2K usage octet was 253, the IV is of the size expected by the AEAD mode, - // unless it's a version 5 key, in which case it's the size of the symmetric cipher's block size. - // For all other S2K modes, it's always the block size. - if !v5 && pk.s2kType == S2KAEAD { - ivSize = pk.aead.IvLength() - } else { - ivSize = pk.cipher.blockSize() - } - - if ivSize == 0 { - return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) - } - pk.iv = make([]byte, ivSize) - _, err = readFull(r, pk.iv) - if err != nil { - return - } - if v5 && pk.s2kType == S2KAEAD { - pk.iv = pk.iv[:pk.aead.IvLength()] - } - } - - var privateKeyData []byte - if v5 { - var n [4]byte /* secret material four octet count */ - _, err = readFull(r, n[:]) - if err != nil { - return - } - count := uint32(uint32(n[0])<<24 | uint32(n[1])<<16 | uint32(n[2])<<8 | uint32(n[3])) - if !pk.Encrypted { - count = count + 2 /* two octet checksum */ - } - privateKeyData = make([]byte, count) - _, err = readFull(r, privateKeyData) - if err != nil { - return - } - } else { - privateKeyData, err = io.ReadAll(r) - if err != nil { - return - } - } - if !pk.Encrypted { - if len(privateKeyData) < 2 { - return errors.StructuralError("truncated private key data") - } - if pk.Version != 6 { - // checksum - var sum uint16 - for i := 0; i < len(privateKeyData)-2; i++ { - sum += uint16(privateKeyData[i]) - } - if privateKeyData[len(privateKeyData)-2] != uint8(sum>>8) || - privateKeyData[len(privateKeyData)-1] != uint8(sum) { - return errors.StructuralError("private key checksum failure") - } - privateKeyData = privateKeyData[:len(privateKeyData)-2] - return pk.parsePrivateKey(privateKeyData) - } else { - // No checksum - return pk.parsePrivateKey(privateKeyData) - } - } - - pk.encryptedData = privateKeyData - return -} - -// Dummy returns true if the private key is a dummy key. This is a GNU extension. -func (pk *PrivateKey) Dummy() bool { - return pk.s2kParams.Dummy() -} - -func mod64kHash(d []byte) uint16 { - var h uint16 - for _, b := range d { - h += uint16(b) - } - return h -} - -func (pk *PrivateKey) Serialize(w io.Writer) (err error) { - contents := bytes.NewBuffer(nil) - err = pk.PublicKey.serializeWithoutHeaders(contents) - if err != nil { - return - } - if _, err = contents.Write([]byte{uint8(pk.s2kType)}); err != nil { - return - } - - optional := bytes.NewBuffer(nil) - if pk.Encrypted || pk.Dummy() { - // [Optional] If string-to-key usage octet was 255, 254, or 253, - // a one-octet symmetric encryption algorithm. - if _, err = optional.Write([]byte{uint8(pk.cipher)}); err != nil { - return - } - // [Optional] If string-to-key usage octet was 253, - // a one-octet AEAD algorithm. - if pk.s2kType == S2KAEAD { - if _, err = optional.Write([]byte{uint8(pk.aead)}); err != nil { - return - } - } - - s2kBuffer := bytes.NewBuffer(nil) - if err := pk.s2kParams.Serialize(s2kBuffer); err != nil { - return err - } - // [Optional] Only for a version 6 packet, and if string-to-key - // usage octet was 255, 254, or 253, an one-octet - // count of the following field. - if pk.Version == 6 { - if _, err = optional.Write([]byte{uint8(s2kBuffer.Len())}); err != nil { - return - } - } - // [Optional] If string-to-key usage octet was 255, 254, or 253, - // a string-to-key (S2K) specifier. The length of the string-to-key specifier - // depends on its type - if _, err = io.Copy(optional, s2kBuffer); err != nil { - return - } - - // IV - if pk.Encrypted { - if _, err = optional.Write(pk.iv); err != nil { - return - } - if pk.Version == 5 && pk.s2kType == S2KAEAD { - // Add padding for version 5 - padding := make([]byte, pk.cipher.blockSize()-len(pk.iv)) - if _, err = optional.Write(padding); err != nil { - return - } - } - } - } - if pk.Version == 5 || (pk.Version == 6 && pk.s2kType != S2KNON) { - contents.Write([]byte{uint8(optional.Len())}) - } - - if _, err := io.Copy(contents, optional); err != nil { - return err - } - - if !pk.Dummy() { - l := 0 - var priv []byte - if !pk.Encrypted { - buf := bytes.NewBuffer(nil) - err = pk.serializePrivateKey(buf) - if err != nil { - return err - } - l = buf.Len() - if pk.Version != 6 { - checksum := mod64kHash(buf.Bytes()) - buf.Write([]byte{byte(checksum >> 8), byte(checksum)}) - } - priv = buf.Bytes() - } else { - priv, l = pk.encryptedData, len(pk.encryptedData) - } - - if pk.Version == 5 { - contents.Write([]byte{byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l)}) - } - contents.Write(priv) - } - - ptype := packetTypePrivateKey - if pk.IsSubkey { - ptype = packetTypePrivateSubkey - } - err = serializeHeader(w, ptype, contents.Len()) - if err != nil { - return - } - _, err = io.Copy(w, contents) - if err != nil { - return - } - return -} - -func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { - if _, err := w.Write(new(encoding.MPI).SetBig(priv.D).EncodedBytes()); err != nil { - return err - } - if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[1]).EncodedBytes()); err != nil { - return err - } - if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[0]).EncodedBytes()); err != nil { - return err - } - _, err := w.Write(new(encoding.MPI).SetBig(priv.Precomputed.Qinv).EncodedBytes()) - return err -} - -func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { - _, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes()) - return err -} - -func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { - _, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes()) - return err -} - -func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { - _, err := w.Write(encoding.NewMPI(priv.MarshalIntegerSecret()).EncodedBytes()) - return err -} - -func serializeEdDSAPrivateKey(w io.Writer, priv *eddsa.PrivateKey) error { - _, err := w.Write(encoding.NewMPI(priv.MarshalByteSecret()).EncodedBytes()) - return err -} - -func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error { - _, err := w.Write(encoding.NewMPI(priv.MarshalByteSecret()).EncodedBytes()) - return err -} - -func serializeX25519PrivateKey(w io.Writer, priv *x25519.PrivateKey) error { - _, err := w.Write(priv.Secret) - return err -} - -func serializeX448PrivateKey(w io.Writer, priv *x448.PrivateKey) error { - _, err := w.Write(priv.Secret) - return err -} - -func serializeEd25519PrivateKey(w io.Writer, priv *ed25519.PrivateKey) error { - _, err := w.Write(priv.MarshalByteSecret()) - return err -} - -func serializeEd448PrivateKey(w io.Writer, priv *ed448.PrivateKey) error { - _, err := w.Write(priv.MarshalByteSecret()) - return err -} - -// decrypt decrypts an encrypted private key using a decryption key. -func (pk *PrivateKey) decrypt(decryptionKey []byte) error { - if pk.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - if !pk.Encrypted { - return nil - } - block := pk.cipher.new(decryptionKey) - var data []byte - switch pk.s2kType { - case S2KAEAD: - aead := pk.aead.new(block) - additionalData, err := pk.additionalData() - if err != nil { - return err - } - // Decrypt the encrypted key material with aead - data, err = aead.Open(nil, pk.iv, pk.encryptedData, additionalData) - if err != nil { - return err - } - case S2KSHA1, S2KCHECKSUM: - cfb := cipher.NewCFBDecrypter(block, pk.iv) - data = make([]byte, len(pk.encryptedData)) - cfb.XORKeyStream(data, pk.encryptedData) - if pk.s2kType == S2KSHA1 { - if len(data) < sha1.Size { - return errors.StructuralError("truncated private key data") - } - h := sha1.New() - h.Write(data[:len(data)-sha1.Size]) - sum := h.Sum(nil) - if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { - return errors.StructuralError("private key checksum failure") - } - data = data[:len(data)-sha1.Size] - } else { - if len(data) < 2 { - return errors.StructuralError("truncated private key data") - } - var sum uint16 - for i := 0; i < len(data)-2; i++ { - sum += uint16(data[i]) - } - if data[len(data)-2] != uint8(sum>>8) || - data[len(data)-1] != uint8(sum) { - return errors.StructuralError("private key checksum failure") - } - data = data[:len(data)-2] - } - default: - return errors.InvalidArgumentError("invalid s2k type") - } - - err := pk.parsePrivateKey(data) - if _, ok := err.(errors.KeyInvalidError); ok { - return errors.KeyInvalidError("invalid key parameters") - } - if err != nil { - return err - } - - // Mark key as unencrypted - pk.s2kType = S2KNON - pk.s2k = nil - pk.Encrypted = false - pk.encryptedData = nil - return nil -} - -func (pk *PrivateKey) decryptWithCache(passphrase []byte, keyCache *s2k.Cache) error { - if pk.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - if !pk.Encrypted { - return nil - } - - key, err := keyCache.GetOrComputeDerivedKey(passphrase, pk.s2kParams, pk.cipher.KeySize()) - if err != nil { - return err - } - if pk.s2kType == S2KAEAD { - key = pk.applyHKDF(key) - } - return pk.decrypt(key) -} - -// Decrypt decrypts an encrypted private key using a passphrase. -func (pk *PrivateKey) Decrypt(passphrase []byte) error { - if pk.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - if !pk.Encrypted { - return nil - } - - key := make([]byte, pk.cipher.KeySize()) - pk.s2k(key, passphrase) - if pk.s2kType == S2KAEAD { - key = pk.applyHKDF(key) - } - return pk.decrypt(key) -} - -// DecryptPrivateKeys decrypts all encrypted keys with the given config and passphrase. -// Avoids recomputation of similar s2k key derivations. -func DecryptPrivateKeys(keys []*PrivateKey, passphrase []byte) error { - // Create a cache to avoid recomputation of key derviations for the same passphrase. - s2kCache := &s2k.Cache{} - for _, key := range keys { - if key != nil && !key.Dummy() && key.Encrypted { - err := key.decryptWithCache(passphrase, s2kCache) - if err != nil { - return err - } - } - } - return nil -} - -// encrypt encrypts an unencrypted private key. -func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, s2kType S2KType, cipherFunction CipherFunction, rand io.Reader) error { - if pk.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - if pk.Encrypted { - return nil - } - // check if encryptionKey has the correct size - if len(key) != cipherFunction.KeySize() { - return errors.InvalidArgumentError("supplied encryption key has the wrong size") - } - - if params.Mode() == s2k.Argon2S2K && s2kType != S2KAEAD { - return errors.InvalidArgumentError("using Argon2 S2K without AEAD is not allowed") - } - if params.Mode() != s2k.Argon2S2K && params.Mode() != s2k.IteratedSaltedS2K && - params.Mode() != s2k.SaltedS2K { // only allowed for high-entropy passphrases - return errors.InvalidArgumentError("insecure S2K mode") - } - - priv := bytes.NewBuffer(nil) - err := pk.serializePrivateKey(priv) - if err != nil { - return err - } - - pk.cipher = cipherFunction - pk.s2kParams = params - pk.s2k, err = pk.s2kParams.Function() - if err != nil { - return err - } - - privateKeyBytes := priv.Bytes() - pk.s2kType = s2kType - block := pk.cipher.new(key) - switch s2kType { - case S2KAEAD: - if pk.aead == 0 { - return errors.StructuralError("aead mode is not set on key") - } - aead := pk.aead.new(block) - additionalData, err := pk.additionalData() - if err != nil { - return err - } - pk.iv = make([]byte, aead.NonceSize()) - _, err = io.ReadFull(rand, pk.iv) - if err != nil { - return err - } - // Decrypt the encrypted key material with aead - pk.encryptedData = aead.Seal(nil, pk.iv, privateKeyBytes, additionalData) - case S2KSHA1, S2KCHECKSUM: - pk.iv = make([]byte, pk.cipher.blockSize()) - _, err = io.ReadFull(rand, pk.iv) - if err != nil { - return err - } - cfb := cipher.NewCFBEncrypter(block, pk.iv) - if s2kType == S2KSHA1 { - h := sha1.New() - h.Write(privateKeyBytes) - sum := h.Sum(nil) - privateKeyBytes = append(privateKeyBytes, sum...) - } else { - var sum uint16 - for _, b := range privateKeyBytes { - sum += uint16(b) - } - privateKeyBytes = append(privateKeyBytes, []byte{uint8(sum >> 8), uint8(sum)}...) - } - pk.encryptedData = make([]byte, len(privateKeyBytes)) - cfb.XORKeyStream(pk.encryptedData, privateKeyBytes) - default: - return errors.InvalidArgumentError("invalid s2k type for encryption") - } - - pk.Encrypted = true - pk.PrivateKey = nil - return err -} - -// EncryptWithConfig encrypts an unencrypted private key using the passphrase and the config. -func (pk *PrivateKey) EncryptWithConfig(passphrase []byte, config *Config) error { - params, err := s2k.Generate(config.Random(), config.S2K()) - if err != nil { - return err - } - // Derive an encryption key with the configured s2k function. - key := make([]byte, config.Cipher().KeySize()) - s2k, err := params.Function() - if err != nil { - return err - } - s2k(key, passphrase) - s2kType := S2KSHA1 - if config.AEAD() != nil { - s2kType = S2KAEAD - pk.aead = config.AEAD().Mode() - pk.cipher = config.Cipher() - key = pk.applyHKDF(key) - } - // Encrypt the private key with the derived encryption key. - return pk.encrypt(key, params, s2kType, config.Cipher(), config.Random()) -} - -// EncryptPrivateKeys encrypts all unencrypted keys with the given config and passphrase. -// Only derives one key from the passphrase, which is then used to encrypt each key. -func EncryptPrivateKeys(keys []*PrivateKey, passphrase []byte, config *Config) error { - params, err := s2k.Generate(config.Random(), config.S2K()) - if err != nil { - return err - } - // Derive an encryption key with the configured s2k function. - encryptionKey := make([]byte, config.Cipher().KeySize()) - s2k, err := params.Function() - if err != nil { - return err - } - s2k(encryptionKey, passphrase) - for _, key := range keys { - if key != nil && !key.Dummy() && !key.Encrypted { - s2kType := S2KSHA1 - if config.AEAD() != nil { - s2kType = S2KAEAD - key.aead = config.AEAD().Mode() - key.cipher = config.Cipher() - derivedKey := key.applyHKDF(encryptionKey) - err = key.encrypt(derivedKey, params, s2kType, config.Cipher(), config.Random()) - } else { - err = key.encrypt(encryptionKey, params, s2kType, config.Cipher(), config.Random()) - } - if err != nil { - return err - } - } - } - return nil -} - -// Encrypt encrypts an unencrypted private key using a passphrase. -func (pk *PrivateKey) Encrypt(passphrase []byte) error { - // Default config of private key encryption - config := &Config{ - S2KConfig: &s2k.Config{ - S2KMode: s2k.IteratedSaltedS2K, - S2KCount: 65536, - Hash: crypto.SHA256, - }, - DefaultCipher: CipherAES256, - } - return pk.EncryptWithConfig(passphrase, config) -} - -func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) { - switch priv := pk.PrivateKey.(type) { - case *rsa.PrivateKey: - err = serializeRSAPrivateKey(w, priv) - case *dsa.PrivateKey: - err = serializeDSAPrivateKey(w, priv) - case *elgamal.PrivateKey: - err = serializeElGamalPrivateKey(w, priv) - case *ecdsa.PrivateKey: - err = serializeECDSAPrivateKey(w, priv) - case *eddsa.PrivateKey: - err = serializeEdDSAPrivateKey(w, priv) - case *ecdh.PrivateKey: - err = serializeECDHPrivateKey(w, priv) - case *x25519.PrivateKey: - err = serializeX25519PrivateKey(w, priv) - case *x448.PrivateKey: - err = serializeX448PrivateKey(w, priv) - case *ed25519.PrivateKey: - err = serializeEd25519PrivateKey(w, priv) - case *ed448.PrivateKey: - err = serializeEd448PrivateKey(w, priv) - default: - err = errors.InvalidArgumentError("unknown private key type") - } - return -} - -func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { - switch pk.PublicKey.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: - return pk.parseRSAPrivateKey(data) - case PubKeyAlgoDSA: - return pk.parseDSAPrivateKey(data) - case PubKeyAlgoElGamal: - return pk.parseElGamalPrivateKey(data) - case PubKeyAlgoECDSA: - return pk.parseECDSAPrivateKey(data) - case PubKeyAlgoECDH: - return pk.parseECDHPrivateKey(data) - case PubKeyAlgoEdDSA: - return pk.parseEdDSAPrivateKey(data) - case PubKeyAlgoX25519: - return pk.parseX25519PrivateKey(data) - case PubKeyAlgoX448: - return pk.parseX448PrivateKey(data) - case PubKeyAlgoEd25519: - return pk.parseEd25519PrivateKey(data) - case PubKeyAlgoEd448: - return pk.parseEd448PrivateKey(data) - default: - err = errors.StructuralError("unknown private key type") - return - } -} - -func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { - rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) - rsaPriv := new(rsa.PrivateKey) - rsaPriv.PublicKey = *rsaPub - - buf := bytes.NewBuffer(data) - d := new(encoding.MPI) - if _, err := d.ReadFrom(buf); err != nil { - return err - } - - p := new(encoding.MPI) - if _, err := p.ReadFrom(buf); err != nil { - return err - } - - q := new(encoding.MPI) - if _, err := q.ReadFrom(buf); err != nil { - return err - } - - rsaPriv.D = new(big.Int).SetBytes(d.Bytes()) - rsaPriv.Primes = make([]*big.Int, 2) - rsaPriv.Primes[0] = new(big.Int).SetBytes(p.Bytes()) - rsaPriv.Primes[1] = new(big.Int).SetBytes(q.Bytes()) - if err := rsaPriv.Validate(); err != nil { - return errors.KeyInvalidError(err.Error()) - } - rsaPriv.Precompute() - pk.PrivateKey = rsaPriv - - return nil -} - -func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { - dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) - dsaPriv := new(dsa.PrivateKey) - dsaPriv.PublicKey = *dsaPub - - buf := bytes.NewBuffer(data) - x := new(encoding.MPI) - if _, err := x.ReadFrom(buf); err != nil { - return err - } - - dsaPriv.X = new(big.Int).SetBytes(x.Bytes()) - if err := validateDSAParameters(dsaPriv); err != nil { - return err - } - pk.PrivateKey = dsaPriv - - return nil -} - -func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { - pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) - priv := new(elgamal.PrivateKey) - priv.PublicKey = *pub - - buf := bytes.NewBuffer(data) - x := new(encoding.MPI) - if _, err := x.ReadFrom(buf); err != nil { - return err - } - - priv.X = new(big.Int).SetBytes(x.Bytes()) - if err := validateElGamalParameters(priv); err != nil { - return err - } - pk.PrivateKey = priv - - return nil -} - -func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { - ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) - ecdsaPriv := ecdsa.NewPrivateKey(*ecdsaPub) - - buf := bytes.NewBuffer(data) - d := new(encoding.MPI) - if _, err := d.ReadFrom(buf); err != nil { - return err - } - - if err := ecdsaPriv.UnmarshalIntegerSecret(d.Bytes()); err != nil { - return err - } - if err := ecdsa.Validate(ecdsaPriv); err != nil { - return err - } - pk.PrivateKey = ecdsaPriv - - return nil -} - -func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) { - ecdhPub := pk.PublicKey.PublicKey.(*ecdh.PublicKey) - ecdhPriv := ecdh.NewPrivateKey(*ecdhPub) - - buf := bytes.NewBuffer(data) - d := new(encoding.MPI) - if _, err := d.ReadFrom(buf); err != nil { - return err - } - - if err := ecdhPriv.UnmarshalByteSecret(d.Bytes()); err != nil { - return err - } - - if err := ecdh.Validate(ecdhPriv); err != nil { - return err - } - - pk.PrivateKey = ecdhPriv - - return nil -} - -func (pk *PrivateKey) parseX25519PrivateKey(data []byte) (err error) { - publicKey := pk.PublicKey.PublicKey.(*x25519.PublicKey) - privateKey := x25519.NewPrivateKey(*publicKey) - privateKey.PublicKey = *publicKey - - privateKey.Secret = make([]byte, x25519.KeySize) - - if len(data) != x25519.KeySize { - err = errors.StructuralError("wrong x25519 key size") - return err - } - subtle.ConstantTimeCopy(1, privateKey.Secret, data) - if err = x25519.Validate(privateKey); err != nil { - return err - } - pk.PrivateKey = privateKey - return nil -} - -func (pk *PrivateKey) parseX448PrivateKey(data []byte) (err error) { - publicKey := pk.PublicKey.PublicKey.(*x448.PublicKey) - privateKey := x448.NewPrivateKey(*publicKey) - privateKey.PublicKey = *publicKey - - privateKey.Secret = make([]byte, x448.KeySize) - - if len(data) != x448.KeySize { - err = errors.StructuralError("wrong x448 key size") - return err - } - subtle.ConstantTimeCopy(1, privateKey.Secret, data) - if err = x448.Validate(privateKey); err != nil { - return err - } - pk.PrivateKey = privateKey - return nil -} - -func (pk *PrivateKey) parseEd25519PrivateKey(data []byte) (err error) { - publicKey := pk.PublicKey.PublicKey.(*ed25519.PublicKey) - privateKey := ed25519.NewPrivateKey(*publicKey) - privateKey.PublicKey = *publicKey - - if len(data) != ed25519.SeedSize { - err = errors.StructuralError("wrong ed25519 key size") - return err - } - err = privateKey.UnmarshalByteSecret(data) - if err != nil { - return err - } - err = ed25519.Validate(privateKey) - if err != nil { - return err - } - pk.PrivateKey = privateKey - return nil -} - -func (pk *PrivateKey) parseEd448PrivateKey(data []byte) (err error) { - publicKey := pk.PublicKey.PublicKey.(*ed448.PublicKey) - privateKey := ed448.NewPrivateKey(*publicKey) - privateKey.PublicKey = *publicKey - - if len(data) != ed448.SeedSize { - err = errors.StructuralError("wrong ed448 key size") - return err - } - err = privateKey.UnmarshalByteSecret(data) - if err != nil { - return err - } - err = ed448.Validate(privateKey) - if err != nil { - return err - } - pk.PrivateKey = privateKey - return nil -} - -func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) { - eddsaPub := pk.PublicKey.PublicKey.(*eddsa.PublicKey) - eddsaPriv := eddsa.NewPrivateKey(*eddsaPub) - eddsaPriv.PublicKey = *eddsaPub - - buf := bytes.NewBuffer(data) - d := new(encoding.MPI) - if _, err := d.ReadFrom(buf); err != nil { - return err - } - - if err = eddsaPriv.UnmarshalByteSecret(d.Bytes()); err != nil { - return err - } - - if err := eddsa.Validate(eddsaPriv); err != nil { - return err - } - - pk.PrivateKey = eddsaPriv - - return nil -} - -func (pk *PrivateKey) additionalData() ([]byte, error) { - additionalData := bytes.NewBuffer(nil) - // Write additional data prefix based on packet type - var packetByte byte - if pk.PublicKey.IsSubkey { - packetByte = 0xc7 - } else { - packetByte = 0xc5 - } - // Write public key to additional data - _, err := additionalData.Write([]byte{packetByte}) - if err != nil { - return nil, err - } - err = pk.PublicKey.serializeWithoutHeaders(additionalData) - if err != nil { - return nil, err - } - return additionalData.Bytes(), nil -} - -func (pk *PrivateKey) applyHKDF(inputKey []byte) []byte { - var packetByte byte - if pk.PublicKey.IsSubkey { - packetByte = 0xc7 - } else { - packetByte = 0xc5 - } - associatedData := []byte{packetByte, byte(pk.Version), byte(pk.cipher), byte(pk.aead)} - hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData) - encryptionKey := make([]byte, pk.cipher.KeySize()) - _, _ = readFull(hkdfReader, encryptionKey) - return encryptionKey -} - -func validateDSAParameters(priv *dsa.PrivateKey) error { - p := priv.P // group prime - q := priv.Q // subgroup order - g := priv.G // g has order q mod p - x := priv.X // secret - y := priv.Y // y == g**x mod p - one := big.NewInt(1) - // expect g, y >= 2 and g < p - if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 { - return errors.KeyInvalidError("dsa: invalid group") - } - // expect p > q - if p.Cmp(q) <= 0 { - return errors.KeyInvalidError("dsa: invalid group prime") - } - // q should be large enough and divide p-1 - pSub1 := new(big.Int).Sub(p, one) - if q.BitLen() < 150 || new(big.Int).Mod(pSub1, q).Cmp(big.NewInt(0)) != 0 { - return errors.KeyInvalidError("dsa: invalid order") - } - // confirm that g has order q mod p - if !q.ProbablyPrime(32) || new(big.Int).Exp(g, q, p).Cmp(one) != 0 { - return errors.KeyInvalidError("dsa: invalid order") - } - // check y - if new(big.Int).Exp(g, x, p).Cmp(y) != 0 { - return errors.KeyInvalidError("dsa: mismatching values") - } - - return nil -} - -func validateElGamalParameters(priv *elgamal.PrivateKey) error { - p := priv.P // group prime - g := priv.G // g has order p-1 mod p - x := priv.X // secret - y := priv.Y // y == g**x mod p - one := big.NewInt(1) - // Expect g, y >= 2 and g < p - if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 { - return errors.KeyInvalidError("elgamal: invalid group") - } - if p.BitLen() < 1024 { - return errors.KeyInvalidError("elgamal: group order too small") - } - pSub1 := new(big.Int).Sub(p, one) - if new(big.Int).Exp(g, pSub1, p).Cmp(one) != 0 { - return errors.KeyInvalidError("elgamal: invalid group") - } - // Since p-1 is not prime, g might have a smaller order that divides p-1. - // We cannot confirm the exact order of g, but we make sure it is not too small. - gExpI := new(big.Int).Set(g) - i := 1 - threshold := 2 << 17 // we want order > threshold - for i < threshold { - i++ // we check every order to make sure key validation is not easily bypassed by guessing y' - gExpI.Mod(new(big.Int).Mul(gExpI, g), p) - if gExpI.Cmp(one) == 0 { - return errors.KeyInvalidError("elgamal: order too small") - } - } - // Check y - if new(big.Int).Exp(g, x, p).Cmp(y) != 0 { - return errors.KeyInvalidError("elgamal: mismatching values") - } - - return nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go deleted file mode 100644 index 029b8f1a..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go +++ /dev/null @@ -1,12 +0,0 @@ -package packet - -// Generated with `gpg --export-secret-keys "Test Key 2"` -const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec" - -// Generated by `gpg --export-secret-keys` followed by a manual extraction of -// the ElGamal subkey from the packets. -const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc" - -// pkcs1PrivKeyHex is a PKCS#1, RSA private key. -// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p` -const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7" diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go deleted file mode 100644 index e2813396..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go +++ /dev/null @@ -1,1125 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "crypto/dsa" - "crypto/rsa" - "crypto/sha1" - "crypto/sha256" - _ "crypto/sha512" - "encoding/binary" - "fmt" - "hash" - "io" - "math/big" - "strconv" - "time" - - "github.com/ProtonMail/go-crypto/openpgp/ecdh" - "github.com/ProtonMail/go-crypto/openpgp/ecdsa" - "github.com/ProtonMail/go-crypto/openpgp/ed25519" - "github.com/ProtonMail/go-crypto/openpgp/ed448" - "github.com/ProtonMail/go-crypto/openpgp/eddsa" - "github.com/ProtonMail/go-crypto/openpgp/elgamal" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" - "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" - "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" - "github.com/ProtonMail/go-crypto/openpgp/x25519" - "github.com/ProtonMail/go-crypto/openpgp/x448" -) - -// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. -type PublicKey struct { - Version int - CreationTime time.Time - PubKeyAlgo PublicKeyAlgorithm - PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey, *x25519.PublicKey, *x448.PublicKey, *ed25519.PublicKey, *ed448.PublicKey - Fingerprint []byte - KeyId uint64 - IsSubkey bool - - // RFC 4880 fields - n, e, p, q, g, y encoding.Field - - // RFC 6637 fields - // oid contains the OID byte sequence identifying the elliptic curve used - oid encoding.Field - - // kdf stores key derivation function parameters - // used for ECDH encryption. See RFC 6637, Section 9. - kdf encoding.Field -} - -// UpgradeToV5 updates the version of the key to v5, and updates all necessary -// fields. -func (pk *PublicKey) UpgradeToV5() { - pk.Version = 5 - pk.setFingerprintAndKeyId() -} - -// UpgradeToV6 updates the version of the key to v6, and updates all necessary -// fields. -func (pk *PublicKey) UpgradeToV6() error { - pk.Version = 6 - pk.setFingerprintAndKeyId() - return pk.checkV6Compatibility() -} - -// signingKey provides a convenient abstraction over signature verification -// for v3 and v4 public keys. -type signingKey interface { - SerializeForHash(io.Writer) error - SerializeSignaturePrefix(io.Writer) error - serializeWithoutHeaders(io.Writer) error -} - -// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. -func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoRSA, - PublicKey: pub, - n: new(encoding.MPI).SetBig(pub.N), - e: new(encoding.MPI).SetBig(big.NewInt(int64(pub.E))), - } - - pk.setFingerprintAndKeyId() - return pk -} - -// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. -func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoDSA, - PublicKey: pub, - p: new(encoding.MPI).SetBig(pub.P), - q: new(encoding.MPI).SetBig(pub.Q), - g: new(encoding.MPI).SetBig(pub.G), - y: new(encoding.MPI).SetBig(pub.Y), - } - - pk.setFingerprintAndKeyId() - return pk -} - -// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. -func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoElGamal, - PublicKey: pub, - p: new(encoding.MPI).SetBig(pub.P), - g: new(encoding.MPI).SetBig(pub.G), - y: new(encoding.MPI).SetBig(pub.Y), - } - - pk.setFingerprintAndKeyId() - return pk -} - -func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoECDSA, - PublicKey: pub, - p: encoding.NewMPI(pub.MarshalPoint()), - } - - curveInfo := ecc.FindByCurve(pub.GetCurve()) - if curveInfo == nil { - panic("unknown elliptic curve") - } - pk.oid = curveInfo.Oid - pk.setFingerprintAndKeyId() - return pk -} - -func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey { - var pk *PublicKey - var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()}) - pk = &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoECDH, - PublicKey: pub, - p: encoding.NewMPI(pub.MarshalPoint()), - kdf: kdf, - } - - curveInfo := ecc.FindByCurve(pub.GetCurve()) - - if curveInfo == nil { - panic("unknown elliptic curve") - } - - pk.oid = curveInfo.Oid - pk.setFingerprintAndKeyId() - return pk -} - -func NewEdDSAPublicKey(creationTime time.Time, pub *eddsa.PublicKey) *PublicKey { - curveInfo := ecc.FindByCurve(pub.GetCurve()) - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoEdDSA, - PublicKey: pub, - oid: curveInfo.Oid, - // Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B - p: encoding.NewMPI(pub.MarshalPoint()), - } - - pk.setFingerprintAndKeyId() - return pk -} - -func NewX25519PublicKey(creationTime time.Time, pub *x25519.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoX25519, - PublicKey: pub, - } - - pk.setFingerprintAndKeyId() - return pk -} - -func NewX448PublicKey(creationTime time.Time, pub *x448.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoX448, - PublicKey: pub, - } - - pk.setFingerprintAndKeyId() - return pk -} - -func NewEd25519PublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoEd25519, - PublicKey: pub, - } - - pk.setFingerprintAndKeyId() - return pk -} - -func NewEd448PublicKey(creationTime time.Time, pub *ed448.PublicKey) *PublicKey { - pk := &PublicKey{ - Version: 4, - CreationTime: creationTime, - PubKeyAlgo: PubKeyAlgoEd448, - PublicKey: pub, - } - - pk.setFingerprintAndKeyId() - return pk -} - -func (pk *PublicKey) parse(r io.Reader) (err error) { - // RFC 4880, section 5.5.2 - var buf [6]byte - _, err = readFull(r, buf[:]) - if err != nil { - return - } - - pk.Version = int(buf[0]) - if pk.Version != 4 && pk.Version != 5 && pk.Version != 6 { - return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0]))) - } - - if V5Disabled && pk.Version == 5 { - return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed") - } - - if pk.Version >= 5 { - // Read the four-octet scalar octet count - // The count is not used in this implementation - var n [4]byte - _, err = readFull(r, n[:]) - if err != nil { - return - } - } - pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) - pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) - // Ignore four-ocet length - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - err = pk.parseRSA(r) - case PubKeyAlgoDSA: - err = pk.parseDSA(r) - case PubKeyAlgoElGamal: - err = pk.parseElGamal(r) - case PubKeyAlgoECDSA: - err = pk.parseECDSA(r) - case PubKeyAlgoECDH: - err = pk.parseECDH(r) - case PubKeyAlgoEdDSA: - err = pk.parseEdDSA(r) - case PubKeyAlgoX25519: - err = pk.parseX25519(r) - case PubKeyAlgoX448: - err = pk.parseX448(r) - case PubKeyAlgoEd25519: - err = pk.parseEd25519(r) - case PubKeyAlgoEd448: - err = pk.parseEd448(r) - default: - err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) - } - if err != nil { - return - } - - pk.setFingerprintAndKeyId() - return -} - -func (pk *PublicKey) setFingerprintAndKeyId() { - // RFC 4880, section 12.2 - if pk.Version >= 5 { - fingerprint := sha256.New() - if err := pk.SerializeForHash(fingerprint); err != nil { - // Should not happen for a hash. - panic(err) - } - pk.Fingerprint = make([]byte, 32) - copy(pk.Fingerprint, fingerprint.Sum(nil)) - pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8]) - } else { - fingerprint := sha1.New() - if err := pk.SerializeForHash(fingerprint); err != nil { - // Should not happen for a hash. - panic(err) - } - pk.Fingerprint = make([]byte, 20) - copy(pk.Fingerprint, fingerprint.Sum(nil)) - pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) - } -} - -func (pk *PublicKey) checkV6Compatibility() error { - // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs. - switch pk.PubKeyAlgo { - case PubKeyAlgoECDH: - curveInfo := ecc.FindByOid(pk.oid) - if curveInfo == nil { - return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid)) - } - if curveInfo.GenName == ecc.Curve25519GenName { - return errors.StructuralError("cannot generate v6 key with deprecated OID: Curve25519Legacy") - } - case PubKeyAlgoEdDSA: - return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy") - } - return nil -} - -// parseRSA parses RSA public key material from the given Reader. See RFC 4880, -// section 5.5.2. -func (pk *PublicKey) parseRSA(r io.Reader) (err error) { - pk.n = new(encoding.MPI) - if _, err = pk.n.ReadFrom(r); err != nil { - return - } - pk.e = new(encoding.MPI) - if _, err = pk.e.ReadFrom(r); err != nil { - return - } - - if len(pk.e.Bytes()) > 3 { - err = errors.UnsupportedError("large public exponent") - return - } - rsa := &rsa.PublicKey{ - N: new(big.Int).SetBytes(pk.n.Bytes()), - E: 0, - } - for i := 0; i < len(pk.e.Bytes()); i++ { - rsa.E <<= 8 - rsa.E |= int(pk.e.Bytes()[i]) - } - pk.PublicKey = rsa - return -} - -// parseDSA parses DSA public key material from the given Reader. See RFC 4880, -// section 5.5.2. -func (pk *PublicKey) parseDSA(r io.Reader) (err error) { - pk.p = new(encoding.MPI) - if _, err = pk.p.ReadFrom(r); err != nil { - return - } - pk.q = new(encoding.MPI) - if _, err = pk.q.ReadFrom(r); err != nil { - return - } - pk.g = new(encoding.MPI) - if _, err = pk.g.ReadFrom(r); err != nil { - return - } - pk.y = new(encoding.MPI) - if _, err = pk.y.ReadFrom(r); err != nil { - return - } - - dsa := new(dsa.PublicKey) - dsa.P = new(big.Int).SetBytes(pk.p.Bytes()) - dsa.Q = new(big.Int).SetBytes(pk.q.Bytes()) - dsa.G = new(big.Int).SetBytes(pk.g.Bytes()) - dsa.Y = new(big.Int).SetBytes(pk.y.Bytes()) - pk.PublicKey = dsa - return -} - -// parseElGamal parses ElGamal public key material from the given Reader. See -// RFC 4880, section 5.5.2. -func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { - pk.p = new(encoding.MPI) - if _, err = pk.p.ReadFrom(r); err != nil { - return - } - pk.g = new(encoding.MPI) - if _, err = pk.g.ReadFrom(r); err != nil { - return - } - pk.y = new(encoding.MPI) - if _, err = pk.y.ReadFrom(r); err != nil { - return - } - - elgamal := new(elgamal.PublicKey) - elgamal.P = new(big.Int).SetBytes(pk.p.Bytes()) - elgamal.G = new(big.Int).SetBytes(pk.g.Bytes()) - elgamal.Y = new(big.Int).SetBytes(pk.y.Bytes()) - pk.PublicKey = elgamal - return -} - -// parseECDSA parses ECDSA public key material from the given Reader. See -// RFC 6637, Section 9. -func (pk *PublicKey) parseECDSA(r io.Reader) (err error) { - pk.oid = new(encoding.OID) - if _, err = pk.oid.ReadFrom(r); err != nil { - return - } - - curveInfo := ecc.FindByOid(pk.oid) - if curveInfo == nil { - return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid)) - } - - pk.p = new(encoding.MPI) - if _, err = pk.p.ReadFrom(r); err != nil { - return - } - - c, ok := curveInfo.Curve.(ecc.ECDSACurve) - if !ok { - return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) - } - - ecdsaKey := ecdsa.NewPublicKey(c) - err = ecdsaKey.UnmarshalPoint(pk.p.Bytes()) - pk.PublicKey = ecdsaKey - - return -} - -// parseECDH parses ECDH public key material from the given Reader. See -// RFC 6637, Section 9. -func (pk *PublicKey) parseECDH(r io.Reader) (err error) { - pk.oid = new(encoding.OID) - if _, err = pk.oid.ReadFrom(r); err != nil { - return - } - - curveInfo := ecc.FindByOid(pk.oid) - if curveInfo == nil { - return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid)) - } - - if pk.Version == 6 && curveInfo.GenName == ecc.Curve25519GenName { - // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs. - return errors.StructuralError("cannot read v6 key with deprecated OID: Curve25519Legacy") - } - - pk.p = new(encoding.MPI) - if _, err = pk.p.ReadFrom(r); err != nil { - return - } - pk.kdf = new(encoding.OID) - if _, err = pk.kdf.ReadFrom(r); err != nil { - return - } - - c, ok := curveInfo.Curve.(ecc.ECDHCurve) - if !ok { - return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) - } - - if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 { - return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) - } - if reserved := pk.kdf.Bytes()[0]; reserved != 0x01 { - return errors.UnsupportedError("unsupported KDF reserved field: " + strconv.Itoa(int(reserved))) - } - kdfHash, ok := algorithm.HashById[pk.kdf.Bytes()[1]] - if !ok { - return errors.UnsupportedError("unsupported ECDH KDF hash: " + strconv.Itoa(int(pk.kdf.Bytes()[1]))) - } - kdfCipher, ok := algorithm.CipherById[pk.kdf.Bytes()[2]] - if !ok { - return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2]))) - } - - ecdhKey := ecdh.NewPublicKey(c, kdfHash, kdfCipher) - err = ecdhKey.UnmarshalPoint(pk.p.Bytes()) - pk.PublicKey = ecdhKey - - return -} - -func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) { - if pk.Version == 6 { - // Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs. - return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy") - } - - pk.oid = new(encoding.OID) - if _, err = pk.oid.ReadFrom(r); err != nil { - return - } - - curveInfo := ecc.FindByOid(pk.oid) - if curveInfo == nil { - return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid)) - } - - c, ok := curveInfo.Curve.(ecc.EdDSACurve) - if !ok { - return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) - } - - pk.p = new(encoding.MPI) - if _, err = pk.p.ReadFrom(r); err != nil { - return - } - - if len(pk.p.Bytes()) == 0 { - return errors.StructuralError("empty EdDSA public key") - } - - pub := eddsa.NewPublicKey(c) - - switch flag := pk.p.Bytes()[0]; flag { - case 0x04: - // TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt - return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag))) - case 0x40: - err = pub.UnmarshalPoint(pk.p.Bytes()) - default: - return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag))) - } - - pk.PublicKey = pub - return -} - -func (pk *PublicKey) parseX25519(r io.Reader) (err error) { - point := make([]byte, x25519.KeySize) - _, err = io.ReadFull(r, point) - if err != nil { - return - } - pub := &x25519.PublicKey{ - Point: point, - } - pk.PublicKey = pub - return -} - -func (pk *PublicKey) parseX448(r io.Reader) (err error) { - point := make([]byte, x448.KeySize) - _, err = io.ReadFull(r, point) - if err != nil { - return - } - pub := &x448.PublicKey{ - Point: point, - } - pk.PublicKey = pub - return -} - -func (pk *PublicKey) parseEd25519(r io.Reader) (err error) { - point := make([]byte, ed25519.PublicKeySize) - _, err = io.ReadFull(r, point) - if err != nil { - return - } - pub := &ed25519.PublicKey{ - Point: point, - } - pk.PublicKey = pub - return -} - -func (pk *PublicKey) parseEd448(r io.Reader) (err error) { - point := make([]byte, ed448.PublicKeySize) - _, err = io.ReadFull(r, point) - if err != nil { - return - } - pub := &ed448.PublicKey{ - Point: point, - } - pk.PublicKey = pub - return -} - -// SerializeForHash serializes the PublicKey to w with the special packet -// header format needed for hashing. -func (pk *PublicKey) SerializeForHash(w io.Writer) error { - if err := pk.SerializeSignaturePrefix(w); err != nil { - return err - } - return pk.serializeWithoutHeaders(w) -} - -// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. -// The prefix is used when calculating a signature over this public key. See -// RFC 4880, section 5.2.4. -func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) error { - var pLength = pk.algorithmSpecificByteCount() - // version, timestamp, algorithm - pLength += versionSize + timestampSize + algorithmSize - if pk.Version >= 5 { - // key octet count (4). - pLength += 4 - _, err := w.Write([]byte{ - // When a v4 signature is made over a key, the hash data starts with the octet 0x99, followed by a two-octet length - // of the key, and then the body of the key packet. When a v6 signature is made over a key, the hash data starts - // with the salt, then octet 0x9B, followed by a four-octet length of the key, and then the body of the key packet. - 0x95 + byte(pk.Version), - byte(pLength >> 24), - byte(pLength >> 16), - byte(pLength >> 8), - byte(pLength), - }) - return err - } - if _, err := w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}); err != nil { - return err - } - return nil -} - -func (pk *PublicKey) Serialize(w io.Writer) (err error) { - length := uint32(versionSize + timestampSize + algorithmSize) // 6 byte header - length += pk.algorithmSpecificByteCount() - if pk.Version >= 5 { - length += 4 // octet key count - } - packetType := packetTypePublicKey - if pk.IsSubkey { - packetType = packetTypePublicSubkey - } - err = serializeHeader(w, packetType, int(length)) - if err != nil { - return - } - return pk.serializeWithoutHeaders(w) -} - -func (pk *PublicKey) algorithmSpecificByteCount() uint32 { - length := uint32(0) - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - length += uint32(pk.n.EncodedLength()) - length += uint32(pk.e.EncodedLength()) - case PubKeyAlgoDSA: - length += uint32(pk.p.EncodedLength()) - length += uint32(pk.q.EncodedLength()) - length += uint32(pk.g.EncodedLength()) - length += uint32(pk.y.EncodedLength()) - case PubKeyAlgoElGamal: - length += uint32(pk.p.EncodedLength()) - length += uint32(pk.g.EncodedLength()) - length += uint32(pk.y.EncodedLength()) - case PubKeyAlgoECDSA: - length += uint32(pk.oid.EncodedLength()) - length += uint32(pk.p.EncodedLength()) - case PubKeyAlgoECDH: - length += uint32(pk.oid.EncodedLength()) - length += uint32(pk.p.EncodedLength()) - length += uint32(pk.kdf.EncodedLength()) - case PubKeyAlgoEdDSA: - length += uint32(pk.oid.EncodedLength()) - length += uint32(pk.p.EncodedLength()) - case PubKeyAlgoX25519: - length += x25519.KeySize - case PubKeyAlgoX448: - length += x448.KeySize - case PubKeyAlgoEd25519: - length += ed25519.PublicKeySize - case PubKeyAlgoEd448: - length += ed448.PublicKeySize - default: - panic("unknown public key algorithm") - } - return length -} - -// serializeWithoutHeaders marshals the PublicKey to w in the form of an -// OpenPGP public key packet, not including the packet header. -func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { - t := uint32(pk.CreationTime.Unix()) - if _, err = w.Write([]byte{ - byte(pk.Version), - byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t), - byte(pk.PubKeyAlgo), - }); err != nil { - return - } - - if pk.Version >= 5 { - n := pk.algorithmSpecificByteCount() - if _, err = w.Write([]byte{ - byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n), - }); err != nil { - return - } - } - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - if _, err = w.Write(pk.n.EncodedBytes()); err != nil { - return - } - _, err = w.Write(pk.e.EncodedBytes()) - return - case PubKeyAlgoDSA: - if _, err = w.Write(pk.p.EncodedBytes()); err != nil { - return - } - if _, err = w.Write(pk.q.EncodedBytes()); err != nil { - return - } - if _, err = w.Write(pk.g.EncodedBytes()); err != nil { - return - } - _, err = w.Write(pk.y.EncodedBytes()) - return - case PubKeyAlgoElGamal: - if _, err = w.Write(pk.p.EncodedBytes()); err != nil { - return - } - if _, err = w.Write(pk.g.EncodedBytes()); err != nil { - return - } - _, err = w.Write(pk.y.EncodedBytes()) - return - case PubKeyAlgoECDSA: - if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { - return - } - _, err = w.Write(pk.p.EncodedBytes()) - return - case PubKeyAlgoECDH: - if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { - return - } - if _, err = w.Write(pk.p.EncodedBytes()); err != nil { - return - } - _, err = w.Write(pk.kdf.EncodedBytes()) - return - case PubKeyAlgoEdDSA: - if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { - return - } - _, err = w.Write(pk.p.EncodedBytes()) - return - case PubKeyAlgoX25519: - publicKey := pk.PublicKey.(*x25519.PublicKey) - _, err = w.Write(publicKey.Point) - return - case PubKeyAlgoX448: - publicKey := pk.PublicKey.(*x448.PublicKey) - _, err = w.Write(publicKey.Point) - return - case PubKeyAlgoEd25519: - publicKey := pk.PublicKey.(*ed25519.PublicKey) - _, err = w.Write(publicKey.Point) - return - case PubKeyAlgoEd448: - publicKey := pk.PublicKey.(*ed448.PublicKey) - _, err = w.Write(publicKey.Point) - return - } - return errors.InvalidArgumentError("bad public-key algorithm") -} - -// CanSign returns true iff this public key can generate signatures -func (pk *PublicKey) CanSign() bool { - return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH -} - -// VerifyHashTag returns nil iff sig appears to be a plausible signature of the data -// hashed into signed, based solely on its HashTag. signed is mutated by this call. -func VerifyHashTag(signed hash.Hash, sig *Signature) (err error) { - if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { - sig.AddMetadataToHashSuffix() - } - signed.Write(sig.HashSuffix) - hashBytes := signed.Sum(nil) - if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { - return errors.SignatureError("hash tag doesn't match") - } - return nil -} - -// VerifySignature returns nil iff sig is a valid signature, made by this -// public key, of the data hashed into signed. signed is mutated by this call. -func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { - if !pk.CanSign() { - return errors.InvalidArgumentError("public key cannot generate signatures") - } - if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { - sig.AddMetadataToHashSuffix() - } - signed.Write(sig.HashSuffix) - hashBytes := signed.Sum(nil) - // see discussion https://github.com/ProtonMail/go-crypto/issues/107 - if sig.Version >= 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) { - return errors.SignatureError("hash tag doesn't match") - } - - if pk.PubKeyAlgo != sig.PubKeyAlgo { - return errors.InvalidArgumentError("public key and signature use different algorithms") - } - - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) - err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.Bytes())) - if err != nil { - return errors.SignatureError("RSA verification failure") - } - return nil - case PubKeyAlgoDSA: - dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) - // Need to truncate hashBytes to match FIPS 186-3 section 4.6. - subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 - if len(hashBytes) > subgroupSize { - hashBytes = hashBytes[:subgroupSize] - } - if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.Bytes()), new(big.Int).SetBytes(sig.DSASigS.Bytes())) { - return errors.SignatureError("DSA verification failure") - } - return nil - case PubKeyAlgoECDSA: - ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) - if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.Bytes()), new(big.Int).SetBytes(sig.ECDSASigS.Bytes())) { - return errors.SignatureError("ECDSA verification failure") - } - return nil - case PubKeyAlgoEdDSA: - eddsaPublicKey := pk.PublicKey.(*eddsa.PublicKey) - if !eddsa.Verify(eddsaPublicKey, hashBytes, sig.EdDSASigR.Bytes(), sig.EdDSASigS.Bytes()) { - return errors.SignatureError("EdDSA verification failure") - } - return nil - case PubKeyAlgoEd25519: - ed25519PublicKey := pk.PublicKey.(*ed25519.PublicKey) - if !ed25519.Verify(ed25519PublicKey, hashBytes, sig.EdSig) { - return errors.SignatureError("Ed25519 verification failure") - } - return nil - case PubKeyAlgoEd448: - ed448PublicKey := pk.PublicKey.(*ed448.PublicKey) - if !ed448.Verify(ed448PublicKey, hashBytes, sig.EdSig) { - return errors.SignatureError("ed448 verification failure") - } - return nil - default: - return errors.SignatureError("Unsupported public key algorithm used in signature") - } -} - -// keySignatureHash returns a Hash of the message that needs to be signed for -// pk to assert a subkey relationship to signed. -func keySignatureHash(pk, signed signingKey, hashFunc hash.Hash) (h hash.Hash, err error) { - h = hashFunc - - // RFC 4880, section 5.2.4 - err = pk.SerializeForHash(h) - if err != nil { - return nil, err - } - - err = signed.SerializeForHash(h) - return -} - -// VerifyKeyHashTag returns nil iff sig appears to be a plausible signature over this -// primary key and subkey, based solely on its HashTag. -func (pk *PublicKey) VerifyKeyHashTag(signed *PublicKey, sig *Signature) error { - preparedHash, err := sig.PrepareVerify() - if err != nil { - return err - } - h, err := keySignatureHash(pk, signed, preparedHash) - if err != nil { - return err - } - return VerifyHashTag(h, sig) -} - -// VerifyKeySignature returns nil iff sig is a valid signature, made by this -// public key, of signed. -func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { - preparedHash, err := sig.PrepareVerify() - if err != nil { - return err - } - h, err := keySignatureHash(pk, signed, preparedHash) - if err != nil { - return err - } - if err = pk.VerifySignature(h, sig); err != nil { - return err - } - - if sig.FlagSign { - // Signing subkeys must be cross-signed. See - // https://www.gnupg.org/faq/subkey-cross-certify.html. - if sig.EmbeddedSignature == nil { - return errors.StructuralError("signing subkey is missing cross-signature") - } - preparedHashEmbedded, err := sig.EmbeddedSignature.PrepareVerify() - if err != nil { - return err - } - // Verify the cross-signature. This is calculated over the same - // data as the main signature, so we cannot just recursively - // call signed.VerifyKeySignature(...) - if h, err = keySignatureHash(pk, signed, preparedHashEmbedded); err != nil { - return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) - } - if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { - return errors.StructuralError("error while verifying cross-signature: " + err.Error()) - } - } - - return nil -} - -func keyRevocationHash(pk signingKey, hashFunc hash.Hash) (err error) { - return pk.SerializeForHash(hashFunc) -} - -// VerifyRevocationHashTag returns nil iff sig appears to be a plausible signature -// over this public key, based solely on its HashTag. -func (pk *PublicKey) VerifyRevocationHashTag(sig *Signature) (err error) { - preparedHash, err := sig.PrepareVerify() - if err != nil { - return err - } - if err = keyRevocationHash(pk, preparedHash); err != nil { - return err - } - return VerifyHashTag(preparedHash, sig) -} - -// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this -// public key. -func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { - preparedHash, err := sig.PrepareVerify() - if err != nil { - return err - } - if err = keyRevocationHash(pk, preparedHash); err != nil { - return err - } - return pk.VerifySignature(preparedHash, sig) -} - -// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature, -// made by this public key, of signed. -func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *PublicKey) (err error) { - preparedHash, err := sig.PrepareVerify() - if err != nil { - return err - } - h, err := keySignatureHash(pk, signed, preparedHash) - if err != nil { - return err - } - return pk.VerifySignature(h, sig) -} - -// userIdSignatureHash returns a Hash of the message that needs to be signed -// to assert that pk is a valid key for id. -func userIdSignatureHash(id string, pk *PublicKey, h hash.Hash) (err error) { - - // RFC 4880, section 5.2.4 - if err := pk.SerializeSignaturePrefix(h); err != nil { - return err - } - if err := pk.serializeWithoutHeaders(h); err != nil { - return err - } - - var buf [5]byte - buf[0] = 0xb4 - buf[1] = byte(len(id) >> 24) - buf[2] = byte(len(id) >> 16) - buf[3] = byte(len(id) >> 8) - buf[4] = byte(len(id)) - h.Write(buf[:]) - h.Write([]byte(id)) - - return nil -} - -// directKeySignatureHash returns a Hash of the message that needs to be signed. -func directKeySignatureHash(pk *PublicKey, h hash.Hash) (err error) { - return pk.SerializeForHash(h) -} - -// VerifyUserIdHashTag returns nil iff sig appears to be a plausible signature over this -// public key and UserId, based solely on its HashTag -func (pk *PublicKey) VerifyUserIdHashTag(id string, sig *Signature) (err error) { - preparedHash, err := sig.PrepareVerify() - if err != nil { - return err - } - err = userIdSignatureHash(id, pk, preparedHash) - if err != nil { - return err - } - return VerifyHashTag(preparedHash, sig) -} - -// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this -// public key, that id is the identity of pub. -func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { - h, err := sig.PrepareVerify() - if err != nil { - return err - } - if err := userIdSignatureHash(id, pub, h); err != nil { - return err - } - return pk.VerifySignature(h, sig) -} - -// VerifyDirectKeySignature returns nil iff sig is a valid signature, made by this -// public key. -func (pk *PublicKey) VerifyDirectKeySignature(sig *Signature) (err error) { - h, err := sig.PrepareVerify() - if err != nil { - return err - } - if err := directKeySignatureHash(pk, h); err != nil { - return err - } - return pk.VerifySignature(h, sig) -} - -// KeyIdString returns the public key's fingerprint in capital hex -// (e.g. "6C7EE1B8621CC013"). -func (pk *PublicKey) KeyIdString() string { - return fmt.Sprintf("%016X", pk.KeyId) -} - -// KeyIdShortString returns the short form of public key's fingerprint -// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). -// This function will return the full key id for v5 and v6 keys -// since the short key id is undefined for them. -func (pk *PublicKey) KeyIdShortString() string { - if pk.Version >= 5 { - return pk.KeyIdString() - } - return fmt.Sprintf("%X", pk.Fingerprint[16:20]) -} - -// BitLength returns the bit length for the given public key. -func (pk *PublicKey) BitLength() (bitLength uint16, err error) { - switch pk.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: - bitLength = pk.n.BitLength() - case PubKeyAlgoDSA: - bitLength = pk.p.BitLength() - case PubKeyAlgoElGamal: - bitLength = pk.p.BitLength() - case PubKeyAlgoECDSA: - bitLength = pk.p.BitLength() - case PubKeyAlgoECDH: - bitLength = pk.p.BitLength() - case PubKeyAlgoEdDSA: - bitLength = pk.p.BitLength() - case PubKeyAlgoX25519: - bitLength = x25519.KeySize * 8 - case PubKeyAlgoX448: - bitLength = x448.KeySize * 8 - case PubKeyAlgoEd25519: - bitLength = ed25519.PublicKeySize * 8 - case PubKeyAlgoEd448: - bitLength = ed448.PublicKeySize * 8 - default: - err = errors.InvalidArgumentError("bad public-key algorithm") - } - return -} - -// Curve returns the used elliptic curve of this public key. -// Returns an error if no elliptic curve is used. -func (pk *PublicKey) Curve() (curve Curve, err error) { - switch pk.PubKeyAlgo { - case PubKeyAlgoECDSA, PubKeyAlgoECDH, PubKeyAlgoEdDSA: - curveInfo := ecc.FindByOid(pk.oid) - if curveInfo == nil { - return "", errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid)) - } - curve = Curve(curveInfo.GenName) - case PubKeyAlgoEd25519, PubKeyAlgoX25519: - curve = Curve25519 - case PubKeyAlgoEd448, PubKeyAlgoX448: - curve = Curve448 - default: - err = errors.InvalidArgumentError("public key does not operate with an elliptic curve") - } - return -} - -// KeyExpired returns whether sig is a self-signature of a key that has -// expired or is created in the future. -func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool { - if pk.CreationTime.Unix() > currentTime.Unix() { - return true - } - if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 { - return false - } - expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) - return currentTime.Unix() > expiry.Unix() -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go deleted file mode 100644 index b255f1f6..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go +++ /dev/null @@ -1,24 +0,0 @@ -package packet - -const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" - -const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" - -const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed" - -const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0" - -const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b" - -const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4" - -const ecdhFingerprintHex = "722354df2475a42164d1d49faa8b938f9a201946" - -const ecdhPkDataHex = "b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec91803010909" - -const eddsaFingerprintHex = "b2d5e5ec0e6deca6bc8eeeb00907e75e1dd99ad8" - -const eddsaPkDataHex = "98330456e2132b16092b06010401da470f01010740bbda39266affa511a8c2d02edf690fb784b0499c4406185811a163539ef11dc1b41d74657374696e67203c74657374696e674074657374696e672e636f6d3e8879041316080021050256e2132b021b03050b09080702061508090a0b020416020301021e01021780000a09100907e75e1dd99ad86d0c00fe39d2008359352782bc9b61ac382584cd8eff3f57a18c2287e3afeeb05d1f04ba00fe2d0bc1ddf3ff8adb9afa3e7d9287244b4ec567f3db4d60b74a9b5465ed528203" - -// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key -const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267` diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go deleted file mode 100644 index dd840923..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -type PacketReader interface { - Next() (p Packet, err error) - Push(reader io.Reader) (err error) - Unread(p Packet) -} - -// Reader reads packets from an io.Reader and allows packets to be 'unread' so -// that they result from the next call to Next. -type Reader struct { - q []Packet - readers []io.Reader -} - -// New io.Readers are pushed when a compressed or encrypted packet is processed -// and recursively treated as a new source of packets. However, a carefully -// crafted packet can trigger an infinite recursive sequence of packets. See -// http://mumble.net/~campbell/misc/pgp-quine -// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 -// This constant limits the number of recursive packets that may be pushed. -const maxReaders = 32 - -// Next returns the most recently unread Packet, or reads another packet from -// the top-most io.Reader. Unknown/unsupported/Marker packet types are skipped. -func (r *Reader) Next() (p Packet, err error) { - for { - p, err := r.read() - if err == io.EOF { - break - } else if err != nil { - if _, ok := err.(errors.UnknownPacketTypeError); ok { - continue - } - if _, ok := err.(errors.UnsupportedError); ok { - switch p.(type) { - case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData: - return nil, err - } - continue - } - return nil, err - } else { - //A marker packet MUST be ignored when received - switch p.(type) { - case *Marker: - continue - } - return p, nil - } - } - return nil, io.EOF -} - -// Next returns the most recently unread Packet, or reads another packet from -// the top-most io.Reader. Unknown/Marker packet types are skipped while unsupported -// packets are returned as UnsupportedPacket type. -func (r *Reader) NextWithUnsupported() (p Packet, err error) { - for { - p, err = r.read() - if err == io.EOF { - break - } else if err != nil { - if _, ok := err.(errors.UnknownPacketTypeError); ok { - continue - } - if casteErr, ok := err.(errors.UnsupportedError); ok { - return &UnsupportedPacket{ - IncompletePacket: p, - Error: casteErr, - }, nil - } - return - } else { - //A marker packet MUST be ignored when received - switch p.(type) { - case *Marker: - continue - } - return - } - } - return nil, io.EOF -} - -func (r *Reader) read() (p Packet, err error) { - if len(r.q) > 0 { - p = r.q[len(r.q)-1] - r.q = r.q[:len(r.q)-1] - return - } - for len(r.readers) > 0 { - p, err = Read(r.readers[len(r.readers)-1]) - if err == io.EOF { - r.readers = r.readers[:len(r.readers)-1] - continue - } - return p, err - } - return nil, io.EOF -} - -// Push causes the Reader to start reading from a new io.Reader. When an EOF -// error is seen from the new io.Reader, it is popped and the Reader continues -// to read from the next most recent io.Reader. Push returns a StructuralError -// if pushing the reader would exceed the maximum recursion level, otherwise it -// returns nil. -func (r *Reader) Push(reader io.Reader) (err error) { - if len(r.readers) >= maxReaders { - return errors.StructuralError("too many layers of packets") - } - r.readers = append(r.readers, reader) - return nil -} - -// Unread causes the given Packet to be returned from the next call to Next. -func (r *Reader) Unread(p Packet) { - r.q = append(r.q, p) -} - -func NewReader(r io.Reader) *Reader { - return &Reader{ - q: nil, - readers: []io.Reader{r}, - } -} - -// CheckReader is similar to Reader but additionally -// uses the pushdown automata to verify the read packet sequence. -type CheckReader struct { - Reader - verifier *SequenceVerifier - fullyRead bool -} - -// Next returns the most recently unread Packet, or reads another packet from -// the top-most io.Reader. Unknown packet types are skipped. -// If the read packet sequence does not conform to the packet composition -// rules in rfc4880, it returns an error. -func (r *CheckReader) Next() (p Packet, err error) { - if r.fullyRead { - return nil, io.EOF - } - if len(r.q) > 0 { - p = r.q[len(r.q)-1] - r.q = r.q[:len(r.q)-1] - return - } - var errMsg error - for len(r.readers) > 0 { - p, errMsg, err = ReadWithCheck(r.readers[len(r.readers)-1], r.verifier) - if errMsg != nil { - err = errMsg - return - } - if err == nil { - return - } - if err == io.EOF { - r.readers = r.readers[:len(r.readers)-1] - continue - } - //A marker packet MUST be ignored when received - switch p.(type) { - case *Marker: - continue - } - if _, ok := err.(errors.UnknownPacketTypeError); ok { - continue - } - if _, ok := err.(errors.UnsupportedError); ok { - switch p.(type) { - case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData: - return nil, err - } - continue - } - return nil, err - } - if errMsg = r.verifier.Next(EOSSymbol); errMsg != nil { - return nil, errMsg - } - if errMsg = r.verifier.AssertValid(); errMsg != nil { - return nil, errMsg - } - r.fullyRead = true - return nil, io.EOF -} - -func NewCheckReader(r io.Reader) *CheckReader { - return &CheckReader{ - Reader: Reader{ - q: nil, - readers: []io.Reader{r}, - }, - verifier: NewSequenceVerifier(), - fullyRead: false, - } -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go deleted file mode 100644 index fb2e362e..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go +++ /dev/null @@ -1,15 +0,0 @@ -package packet - -// Recipient type represents a Intended Recipient Fingerprint subpacket -// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-intended-recipient-fingerpr -type Recipient struct { - KeyVersion int - Fingerprint []byte -} - -func (r *Recipient) Serialize() []byte { - packet := make([]byte, len(r.Fingerprint)+1) - packet[0] = byte(r.KeyVersion) - copy(packet[1:], r.Fingerprint) - return packet -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go deleted file mode 100644 index 84dd3b86..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go +++ /dev/null @@ -1,1511 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "bytes" - "crypto" - "crypto/dsa" - "encoding/asn1" - "encoding/binary" - "hash" - "io" - "math/big" - "strconv" - "time" - - "github.com/ProtonMail/go-crypto/openpgp/ecdsa" - "github.com/ProtonMail/go-crypto/openpgp/ed25519" - "github.com/ProtonMail/go-crypto/openpgp/ed448" - "github.com/ProtonMail/go-crypto/openpgp/eddsa" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" - "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" -) - -const ( - // First octet of key flags. - // See RFC 9580, section 5.2.3.29 for details. - KeyFlagCertify = 1 << iota - KeyFlagSign - KeyFlagEncryptCommunications - KeyFlagEncryptStorage - KeyFlagSplitKey - KeyFlagAuthenticate - _ - KeyFlagGroupKey -) - -const ( - // First octet of keyserver preference flags. - // See RFC 9580, section 5.2.3.25 for details. - _ = 1 << iota - _ - _ - _ - _ - _ - _ - KeyserverPrefNoModify -) - -const SaltNotationName = "salt@notations.openpgpjs.org" - -// Signature represents a signature. See RFC 9580, section 5.2. -type Signature struct { - Version int - SigType SignatureType - PubKeyAlgo PublicKeyAlgorithm - Hash crypto.Hash - // salt contains a random salt value for v6 signatures - // See RFC 9580 Section 5.2.4. - salt []byte - - // HashSuffix is extra data that is hashed in after the signed data. - HashSuffix []byte - // HashTag contains the first two bytes of the hash for fast rejection - // of bad signed data. - HashTag [2]byte - - // Metadata includes format, filename and time, and is protected by v5 - // signatures of type 0x00 or 0x01. This metadata is included into the hash - // computation; if nil, six 0x00 bytes are used instead. See section 5.2.4. - Metadata *LiteralData - - CreationTime time.Time - - RSASignature encoding.Field - DSASigR, DSASigS encoding.Field - ECDSASigR, ECDSASigS encoding.Field - EdDSASigR, EdDSASigS encoding.Field - EdSig []byte - - // rawSubpackets contains the unparsed subpackets, in order. - rawSubpackets []outputSubpacket - - // The following are optional so are nil when not included in the - // signature. - - SigLifetimeSecs, KeyLifetimeSecs *uint32 - PreferredSymmetric, PreferredHash, PreferredCompression []uint8 - PreferredCipherSuites [][2]uint8 - IssuerKeyId *uint64 - IssuerFingerprint []byte - SignerUserId *string - IsPrimaryId *bool - Notations []*Notation - IntendedRecipients []*Recipient - - // TrustLevel and TrustAmount can be set by the signer to assert that - // the key is not only valid but also trustworthy at the specified - // level. - // See RFC 9580, section 5.2.3.21 for details. - TrustLevel TrustLevel - TrustAmount TrustAmount - - // TrustRegularExpression can be used in conjunction with trust Signature - // packets to limit the scope of the trust that is extended. - // See RFC 9580, section 5.2.3.22 for details. - TrustRegularExpression *string - - // KeyserverPrefsValid is set if any keyserver preferences were given. See RFC 9580, section - // 5.2.3.25 for details. - KeyserverPrefsValid bool - KeyserverPrefNoModify bool - - // PreferredKeyserver can be set to a URI where the latest version of the - // key that this signature is made over can be found. See RFC 9580, section - // 5.2.3.26 for details. - PreferredKeyserver string - - // PolicyURI can be set to the URI of a document that describes the - // policy under which the signature was issued. See RFC 9580, section - // 5.2.3.28 for details. - PolicyURI string - - // FlagsValid is set if any flags were given. See RFC 9580, section - // 5.2.3.29 for details. - FlagsValid bool - FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage, FlagSplitKey, FlagAuthenticate, FlagGroupKey bool - - // RevocationReason is set if this signature has been revoked. - // See RFC 9580, section 5.2.3.31 for details. - RevocationReason *ReasonForRevocation - RevocationReasonText string - - // In a self-signature, these flags are set there is a features subpacket - // indicating that the issuer implementation supports these features - // see https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#features-subpacket - SEIPDv1, SEIPDv2 bool - - // EmbeddedSignature, if non-nil, is a signature of the parent key, by - // this key. This prevents an attacker from claiming another's signing - // subkey as their own. - EmbeddedSignature *Signature - - outSubpackets []outputSubpacket -} - -// VerifiableSignature internally keeps state if the -// the signature has been verified before. -type VerifiableSignature struct { - Valid *bool // nil if it has not been verified yet - Packet *Signature -} - -// NewVerifiableSig returns a struct of type VerifiableSignature referencing the input signature. -func NewVerifiableSig(signature *Signature) *VerifiableSignature { - return &VerifiableSignature{ - Packet: signature, - } -} - -// Salt returns the signature salt for v6 signatures. -func (sig *Signature) Salt() []byte { - if sig == nil { - return nil - } - return sig.salt -} - -func (sig *Signature) parse(r io.Reader) (err error) { - // RFC 9580, section 5.2.3 - var buf [7]byte - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - sig.Version = int(buf[0]) - if sig.Version != 4 && sig.Version != 5 && sig.Version != 6 { - err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) - return - } - - if V5Disabled && sig.Version == 5 { - return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed") - } - - if sig.Version == 6 { - _, err = readFull(r, buf[:7]) - } else { - _, err = readFull(r, buf[:5]) - } - if err != nil { - return - } - sig.SigType = SignatureType(buf[0]) - sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA, PubKeyAlgoEd25519, PubKeyAlgoEd448: - default: - err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) - return - } - - var ok bool - - if sig.Version < 5 { - sig.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2]) - } else { - sig.Hash, ok = algorithm.HashIdToHash(buf[2]) - } - - if !ok { - return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) - } - - var hashedSubpacketsLength int - if sig.Version == 6 { - // For a v6 signature, a four-octet length is used. - hashedSubpacketsLength = - int(buf[3])<<24 | - int(buf[4])<<16 | - int(buf[5])<<8 | - int(buf[6]) - } else { - hashedSubpacketsLength = int(buf[3])<<8 | int(buf[4]) - } - hashedSubpackets := make([]byte, hashedSubpacketsLength) - _, err = readFull(r, hashedSubpackets) - if err != nil { - return - } - err = sig.buildHashSuffix(hashedSubpackets) - if err != nil { - return - } - - err = parseSignatureSubpackets(sig, hashedSubpackets, true) - if err != nil { - return - } - - if sig.Version == 6 { - _, err = readFull(r, buf[:4]) - } else { - _, err = readFull(r, buf[:2]) - } - - if err != nil { - return - } - var unhashedSubpacketsLength uint32 - if sig.Version == 6 { - unhashedSubpacketsLength = uint32(buf[0])<<24 | uint32(buf[1])<<16 | uint32(buf[2])<<8 | uint32(buf[3]) - } else { - unhashedSubpacketsLength = uint32(buf[0])<<8 | uint32(buf[1]) - } - unhashedSubpackets := make([]byte, unhashedSubpacketsLength) - _, err = readFull(r, unhashedSubpackets) - if err != nil { - return - } - err = parseSignatureSubpackets(sig, unhashedSubpackets, false) - if err != nil { - return - } - - _, err = readFull(r, sig.HashTag[:2]) - if err != nil { - return - } - - if sig.Version == 6 { - // Only for v6 signatures, a variable-length field containing the salt - _, err = readFull(r, buf[:1]) - if err != nil { - return - } - saltLength := int(buf[0]) - var expectedSaltLength int - expectedSaltLength, err = SaltLengthForHash(sig.Hash) - if err != nil { - return - } - if saltLength != expectedSaltLength { - err = errors.StructuralError("unexpected salt size for the given hash algorithm") - return - } - salt := make([]byte, expectedSaltLength) - _, err = readFull(r, salt) - if err != nil { - return - } - sig.salt = salt - } - - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sig.RSASignature = new(encoding.MPI) - _, err = sig.RSASignature.ReadFrom(r) - case PubKeyAlgoDSA: - sig.DSASigR = new(encoding.MPI) - if _, err = sig.DSASigR.ReadFrom(r); err != nil { - return - } - - sig.DSASigS = new(encoding.MPI) - _, err = sig.DSASigS.ReadFrom(r) - case PubKeyAlgoECDSA: - sig.ECDSASigR = new(encoding.MPI) - if _, err = sig.ECDSASigR.ReadFrom(r); err != nil { - return - } - - sig.ECDSASigS = new(encoding.MPI) - _, err = sig.ECDSASigS.ReadFrom(r) - case PubKeyAlgoEdDSA: - sig.EdDSASigR = new(encoding.MPI) - if _, err = sig.EdDSASigR.ReadFrom(r); err != nil { - return - } - - sig.EdDSASigS = new(encoding.MPI) - if _, err = sig.EdDSASigS.ReadFrom(r); err != nil { - return - } - case PubKeyAlgoEd25519: - sig.EdSig, err = ed25519.ReadSignature(r) - if err != nil { - return - } - case PubKeyAlgoEd448: - sig.EdSig, err = ed448.ReadSignature(r) - if err != nil { - return - } - default: - panic("unreachable") - } - return -} - -// parseSignatureSubpackets parses subpackets of the main signature packet. See -// RFC 9580, section 5.2.3.1. -func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { - for len(subpackets) > 0 { - subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) - if err != nil { - return - } - } - - if sig.CreationTime.IsZero() { - err = errors.StructuralError("no creation time in signature") - } - - return -} - -type signatureSubpacketType uint8 - -const ( - creationTimeSubpacket signatureSubpacketType = 2 - signatureExpirationSubpacket signatureSubpacketType = 3 - exportableCertSubpacket signatureSubpacketType = 4 - trustSubpacket signatureSubpacketType = 5 - regularExpressionSubpacket signatureSubpacketType = 6 - keyExpirationSubpacket signatureSubpacketType = 9 - prefSymmetricAlgosSubpacket signatureSubpacketType = 11 - issuerSubpacket signatureSubpacketType = 16 - notationDataSubpacket signatureSubpacketType = 20 - prefHashAlgosSubpacket signatureSubpacketType = 21 - prefCompressionSubpacket signatureSubpacketType = 22 - keyserverPrefsSubpacket signatureSubpacketType = 23 - prefKeyserverSubpacket signatureSubpacketType = 24 - primaryUserIdSubpacket signatureSubpacketType = 25 - policyUriSubpacket signatureSubpacketType = 26 - keyFlagsSubpacket signatureSubpacketType = 27 - signerUserIdSubpacket signatureSubpacketType = 28 - reasonForRevocationSubpacket signatureSubpacketType = 29 - featuresSubpacket signatureSubpacketType = 30 - embeddedSignatureSubpacket signatureSubpacketType = 32 - issuerFingerprintSubpacket signatureSubpacketType = 33 - intendedRecipientSubpacket signatureSubpacketType = 35 - prefCipherSuitesSubpacket signatureSubpacketType = 39 -) - -// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. -func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { - // RFC 9580, section 5.2.3.7 - var ( - length uint32 - packetType signatureSubpacketType - isCritical bool - ) - if len(subpacket) == 0 { - err = errors.StructuralError("zero length signature subpacket") - return - } - switch { - case subpacket[0] < 192: - length = uint32(subpacket[0]) - subpacket = subpacket[1:] - case subpacket[0] < 255: - if len(subpacket) < 2 { - goto Truncated - } - length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 - subpacket = subpacket[2:] - default: - if len(subpacket) < 5 { - goto Truncated - } - length = uint32(subpacket[1])<<24 | - uint32(subpacket[2])<<16 | - uint32(subpacket[3])<<8 | - uint32(subpacket[4]) - subpacket = subpacket[5:] - } - if length > uint32(len(subpacket)) { - goto Truncated - } - rest = subpacket[length:] - subpacket = subpacket[:length] - if len(subpacket) == 0 { - err = errors.StructuralError("zero length signature subpacket") - return - } - packetType = signatureSubpacketType(subpacket[0] & 0x7f) - isCritical = subpacket[0]&0x80 == 0x80 - subpacket = subpacket[1:] - sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) - if !isHashed && - packetType != issuerSubpacket && - packetType != issuerFingerprintSubpacket && - packetType != embeddedSignatureSubpacket { - return - } - switch packetType { - case creationTimeSubpacket: - if len(subpacket) != 4 { - err = errors.StructuralError("signature creation time not four bytes") - return - } - t := binary.BigEndian.Uint32(subpacket) - sig.CreationTime = time.Unix(int64(t), 0) - case signatureExpirationSubpacket: - // Signature expiration time, section 5.2.3.18 - if len(subpacket) != 4 { - err = errors.StructuralError("expiration subpacket with bad length") - return - } - sig.SigLifetimeSecs = new(uint32) - *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) - case exportableCertSubpacket: - if subpacket[0] == 0 { - err = errors.UnsupportedError("signature with non-exportable certification") - return - } - case trustSubpacket: - if len(subpacket) != 2 { - err = errors.StructuralError("trust subpacket with bad length") - return - } - // Trust level and amount, section 5.2.3.21 - sig.TrustLevel = TrustLevel(subpacket[0]) - sig.TrustAmount = TrustAmount(subpacket[1]) - case regularExpressionSubpacket: - if len(subpacket) == 0 { - err = errors.StructuralError("regexp subpacket with bad length") - return - } - // Trust regular expression, section 5.2.3.22 - // RFC specifies the string should be null-terminated; remove a null byte from the end - if subpacket[len(subpacket)-1] != 0x00 { - err = errors.StructuralError("expected regular expression to be null-terminated") - return - } - trustRegularExpression := string(subpacket[:len(subpacket)-1]) - sig.TrustRegularExpression = &trustRegularExpression - case keyExpirationSubpacket: - // Key expiration time, section 5.2.3.13 - if len(subpacket) != 4 { - err = errors.StructuralError("key expiration subpacket with bad length") - return - } - sig.KeyLifetimeSecs = new(uint32) - *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) - case prefSymmetricAlgosSubpacket: - // Preferred symmetric algorithms, section 5.2.3.14 - sig.PreferredSymmetric = make([]byte, len(subpacket)) - copy(sig.PreferredSymmetric, subpacket) - case issuerSubpacket: - // Issuer, section 5.2.3.12 - if sig.Version > 4 && isHashed { - err = errors.StructuralError("issuer subpacket found in v6 key") - return - } - if len(subpacket) != 8 { - err = errors.StructuralError("issuer subpacket with bad length") - return - } - if sig.Version <= 4 { - sig.IssuerKeyId = new(uint64) - *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) - } - case notationDataSubpacket: - // Notation data, section 5.2.3.24 - if len(subpacket) < 8 { - err = errors.StructuralError("notation data subpacket with bad length") - return - } - - nameLength := uint32(subpacket[4])<<8 | uint32(subpacket[5]) - valueLength := uint32(subpacket[6])<<8 | uint32(subpacket[7]) - if len(subpacket) != int(nameLength)+int(valueLength)+8 { - err = errors.StructuralError("notation data subpacket with bad length") - return - } - - notation := Notation{ - IsHumanReadable: (subpacket[0] & 0x80) == 0x80, - Name: string(subpacket[8:(nameLength + 8)]), - Value: subpacket[(nameLength + 8):(valueLength + nameLength + 8)], - IsCritical: isCritical, - } - - sig.Notations = append(sig.Notations, ¬ation) - case prefHashAlgosSubpacket: - // Preferred hash algorithms, section 5.2.3.16 - sig.PreferredHash = make([]byte, len(subpacket)) - copy(sig.PreferredHash, subpacket) - case prefCompressionSubpacket: - // Preferred compression algorithms, section 5.2.3.17 - sig.PreferredCompression = make([]byte, len(subpacket)) - copy(sig.PreferredCompression, subpacket) - case keyserverPrefsSubpacket: - // Keyserver preferences, section 5.2.3.25 - sig.KeyserverPrefsValid = true - if len(subpacket) == 0 { - return - } - if subpacket[0]&KeyserverPrefNoModify != 0 { - sig.KeyserverPrefNoModify = true - } - case prefKeyserverSubpacket: - // Preferred keyserver, section 5.2.3.26 - sig.PreferredKeyserver = string(subpacket) - case primaryUserIdSubpacket: - // Primary User ID, section 5.2.3.27 - if len(subpacket) != 1 { - err = errors.StructuralError("primary user id subpacket with bad length") - return - } - sig.IsPrimaryId = new(bool) - if subpacket[0] > 0 { - *sig.IsPrimaryId = true - } - case keyFlagsSubpacket: - // Key flags, section 5.2.3.29 - sig.FlagsValid = true - if len(subpacket) == 0 { - return - } - if subpacket[0]&KeyFlagCertify != 0 { - sig.FlagCertify = true - } - if subpacket[0]&KeyFlagSign != 0 { - sig.FlagSign = true - } - if subpacket[0]&KeyFlagEncryptCommunications != 0 { - sig.FlagEncryptCommunications = true - } - if subpacket[0]&KeyFlagEncryptStorage != 0 { - sig.FlagEncryptStorage = true - } - if subpacket[0]&KeyFlagSplitKey != 0 { - sig.FlagSplitKey = true - } - if subpacket[0]&KeyFlagAuthenticate != 0 { - sig.FlagAuthenticate = true - } - if subpacket[0]&KeyFlagGroupKey != 0 { - sig.FlagGroupKey = true - } - case signerUserIdSubpacket: - userId := string(subpacket) - sig.SignerUserId = &userId - case reasonForRevocationSubpacket: - // Reason For Revocation, section 5.2.3.31 - if len(subpacket) == 0 { - err = errors.StructuralError("empty revocation reason subpacket") - return - } - sig.RevocationReason = new(ReasonForRevocation) - *sig.RevocationReason = NewReasonForRevocation(subpacket[0]) - sig.RevocationReasonText = string(subpacket[1:]) - case featuresSubpacket: - // Features subpacket, section 5.2.3.32 specifies a very general - // mechanism for OpenPGP implementations to signal support for new - // features. - if len(subpacket) > 0 { - if subpacket[0]&0x01 != 0 { - sig.SEIPDv1 = true - } - // 0x02 and 0x04 are reserved - if subpacket[0]&0x08 != 0 { - sig.SEIPDv2 = true - } - } - case embeddedSignatureSubpacket: - // Only usage is in signatures that cross-certify - // signing subkeys. section 5.2.3.34 describes the - // format, with its usage described in section 11.1 - if sig.EmbeddedSignature != nil { - err = errors.StructuralError("Cannot have multiple embedded signatures") - return - } - sig.EmbeddedSignature = new(Signature) - if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { - return nil, err - } - if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { - return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) - } - case policyUriSubpacket: - // Policy URI, section 5.2.3.28 - sig.PolicyURI = string(subpacket) - case issuerFingerprintSubpacket: - if len(subpacket) == 0 { - err = errors.StructuralError("empty issuer fingerprint subpacket") - return - } - v, l := subpacket[0], len(subpacket[1:]) - if v >= 5 && l != 32 || v < 5 && l != 20 { - return nil, errors.StructuralError("bad fingerprint length") - } - sig.IssuerFingerprint = make([]byte, l) - copy(sig.IssuerFingerprint, subpacket[1:]) - sig.IssuerKeyId = new(uint64) - if v >= 5 { - *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[1:9]) - } else { - *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[13:21]) - } - case intendedRecipientSubpacket: - // Intended Recipient Fingerprint, section 5.2.3.36 - if len(subpacket) < 1 { - return nil, errors.StructuralError("invalid intended recipient fingerpring length") - } - version, length := subpacket[0], len(subpacket[1:]) - if version >= 5 && length != 32 || version < 5 && length != 20 { - return nil, errors.StructuralError("invalid fingerprint length") - } - fingerprint := make([]byte, length) - copy(fingerprint, subpacket[1:]) - sig.IntendedRecipients = append(sig.IntendedRecipients, &Recipient{int(version), fingerprint}) - case prefCipherSuitesSubpacket: - // Preferred AEAD cipher suites, section 5.2.3.15 - if len(subpacket)%2 != 0 { - err = errors.StructuralError("invalid aead cipher suite length") - return - } - - sig.PreferredCipherSuites = make([][2]byte, len(subpacket)/2) - - for i := 0; i < len(subpacket)/2; i++ { - sig.PreferredCipherSuites[i] = [2]uint8{subpacket[2*i], subpacket[2*i+1]} - } - default: - if isCritical { - err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) - return - } - } - return - -Truncated: - err = errors.StructuralError("signature subpacket truncated") - return -} - -// subpacketLengthLength returns the length, in bytes, of an encoded length value. -func subpacketLengthLength(length int) int { - if length < 192 { - return 1 - } - if length < 16320 { - return 2 - } - return 5 -} - -func (sig *Signature) CheckKeyIdOrFingerprint(pk *PublicKey) bool { - if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) >= 20 { - return bytes.Equal(sig.IssuerFingerprint, pk.Fingerprint) - } - return sig.IssuerKeyId != nil && *sig.IssuerKeyId == pk.KeyId -} - -func (sig *Signature) CheckKeyIdOrFingerprintExplicit(fingerprint []byte, keyId uint64) bool { - if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) >= 20 && fingerprint != nil { - return bytes.Equal(sig.IssuerFingerprint, fingerprint) - } - return sig.IssuerKeyId != nil && *sig.IssuerKeyId == keyId -} - -// serializeSubpacketLength marshals the given length into to. -func serializeSubpacketLength(to []byte, length int) int { - // RFC 9580, Section 4.2.1. - if length < 192 { - to[0] = byte(length) - return 1 - } - if length < 16320 { - length -= 192 - to[0] = byte((length >> 8) + 192) - to[1] = byte(length) - return 2 - } - to[0] = 255 - to[1] = byte(length >> 24) - to[2] = byte(length >> 16) - to[3] = byte(length >> 8) - to[4] = byte(length) - return 5 -} - -// subpacketsLength returns the serialized length, in bytes, of the given -// subpackets. -func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { - for _, subpacket := range subpackets { - if subpacket.hashed == hashed { - length += subpacketLengthLength(len(subpacket.contents) + 1) - length += 1 // type byte - length += len(subpacket.contents) - } - } - return -} - -// serializeSubpackets marshals the given subpackets into to. -func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { - for _, subpacket := range subpackets { - if subpacket.hashed == hashed { - n := serializeSubpacketLength(to, len(subpacket.contents)+1) - to[n] = byte(subpacket.subpacketType) - if subpacket.isCritical { - to[n] |= 0x80 - } - to = to[1+n:] - n = copy(to, subpacket.contents) - to = to[n:] - } - } -} - -// SigExpired returns whether sig is a signature that has expired or is created -// in the future. -func (sig *Signature) SigExpired(currentTime time.Time) bool { - if sig.CreationTime.Unix() > currentTime.Unix() { - return true - } - if sig.SigLifetimeSecs == nil || *sig.SigLifetimeSecs == 0 { - return false - } - expiry := sig.CreationTime.Add(time.Duration(*sig.SigLifetimeSecs) * time.Second) - return currentTime.Unix() > expiry.Unix() -} - -// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. -func (sig *Signature) buildHashSuffix(hashedSubpackets []byte) (err error) { - var hashId byte - var ok bool - - if sig.Version < 5 { - hashId, ok = algorithm.HashToHashIdWithSha1(sig.Hash) - } else { - hashId, ok = algorithm.HashToHashId(sig.Hash) - } - - if !ok { - sig.HashSuffix = nil - return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) - } - - hashedFields := bytes.NewBuffer([]byte{ - uint8(sig.Version), - uint8(sig.SigType), - uint8(sig.PubKeyAlgo), - uint8(hashId), - }) - hashedSubpacketsLength := len(hashedSubpackets) - if sig.Version == 6 { - // v6 signatures store the length in 4 octets - hashedFields.Write([]byte{ - uint8(hashedSubpacketsLength >> 24), - uint8(hashedSubpacketsLength >> 16), - uint8(hashedSubpacketsLength >> 8), - uint8(hashedSubpacketsLength), - }) - } else { - hashedFields.Write([]byte{ - uint8(hashedSubpacketsLength >> 8), - uint8(hashedSubpacketsLength), - }) - } - lenPrefix := hashedFields.Len() - hashedFields.Write(hashedSubpackets) - - var l uint64 = uint64(lenPrefix + len(hashedSubpackets)) - if sig.Version == 5 { - // v5 case - hashedFields.Write([]byte{0x05, 0xff}) - hashedFields.Write([]byte{ - uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32), - uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l), - }) - } else { - // v4 and v6 case - hashedFields.Write([]byte{byte(sig.Version), 0xff}) - hashedFields.Write([]byte{ - uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l), - }) - } - sig.HashSuffix = make([]byte, hashedFields.Len()) - copy(sig.HashSuffix, hashedFields.Bytes()) - return -} - -func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { - hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) - hashedSubpackets := make([]byte, hashedSubpacketsLen) - serializeSubpackets(hashedSubpackets, sig.outSubpackets, true) - err = sig.buildHashSuffix(hashedSubpackets) - if err != nil { - return - } - if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { - sig.AddMetadataToHashSuffix() - } - - h.Write(sig.HashSuffix) - digest = h.Sum(nil) - copy(sig.HashTag[:], digest) - return -} - -// PrepareSign must be called to create a hash object before Sign for v6 signatures. -// The created hash object initially hashes a randomly generated salt -// as required by v6 signatures. The generated salt is stored in sig. If the signature is not v6, -// the method returns an empty hash object. -// See RFC 9580 Section 5.2.4. -func (sig *Signature) PrepareSign(config *Config) (hash.Hash, error) { - if !sig.Hash.Available() { - return nil, errors.UnsupportedError("hash function") - } - hasher := sig.Hash.New() - if sig.Version == 6 { - if sig.salt == nil { - var err error - sig.salt, err = SignatureSaltForHash(sig.Hash, config.Random()) - if err != nil { - return nil, err - } - } - hasher.Write(sig.salt) - } - return hasher, nil -} - -// SetSalt sets the signature salt for v6 signatures. -// Assumes salt is generated correctly and checks if length matches. -// If the signature is not v6, the method ignores the salt. -// Use PrepareSign whenever possible instead of generating and -// hashing the salt externally. -// See RFC 9580 Section 5.2.4. -func (sig *Signature) SetSalt(salt []byte) error { - if sig.Version == 6 { - expectedSaltLength, err := SaltLengthForHash(sig.Hash) - if err != nil { - return err - } - if salt == nil || len(salt) != expectedSaltLength { - return errors.InvalidArgumentError("unexpected salt size for the given hash algorithm") - } - sig.salt = salt - } - return nil -} - -// PrepareVerify must be called to create a hash object before verifying v6 signatures. -// The created hash object initially hashes the internally stored salt. -// If the signature is not v6, the method returns an empty hash object. -// See RFC 9580 Section 5.2.4. -func (sig *Signature) PrepareVerify() (hash.Hash, error) { - if !sig.Hash.Available() { - return nil, errors.UnsupportedError("hash function") - } - hasher := sig.Hash.New() - if sig.Version == 6 { - if sig.salt == nil { - return nil, errors.StructuralError("v6 requires a salt for the hash to be signed") - } - hasher.Write(sig.salt) - } - return hasher, nil -} - -// Sign signs a message with a private key. The hash, h, must contain -// the hash of the message to be signed and will be mutated by this function. -// On success, the signature is stored in sig. Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { - if priv.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - sig.Version = priv.PublicKey.Version - sig.IssuerFingerprint = priv.PublicKey.Fingerprint - if sig.Version < 6 && config.RandomizeSignaturesViaNotation() { - sig.removeNotationsWithName(SaltNotationName) - salt, err := SignatureSaltForHash(sig.Hash, config.Random()) - if err != nil { - return err - } - notation := Notation{ - Name: SaltNotationName, - Value: salt, - IsCritical: false, - IsHumanReadable: false, - } - sig.Notations = append(sig.Notations, ¬ation) - } - sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey) - if err != nil { - return err - } - digest, err := sig.signPrepareHash(h) - if err != nil { - return - } - switch priv.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - // supports both *rsa.PrivateKey and crypto.Signer - sigdata, err := priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) - if err == nil { - sig.RSASignature = encoding.NewMPI(sigdata) - } - case PubKeyAlgoDSA: - dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) - - // Need to truncate hashBytes to match FIPS 186-3 section 4.6. - subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 - if len(digest) > subgroupSize { - digest = digest[:subgroupSize] - } - r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) - if err == nil { - sig.DSASigR = new(encoding.MPI).SetBig(r) - sig.DSASigS = new(encoding.MPI).SetBig(s) - } - case PubKeyAlgoECDSA: - var r, s *big.Int - if sk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { - r, s, err = ecdsa.Sign(config.Random(), sk, digest) - } else { - var b []byte - b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) - if err == nil { - r, s, err = unwrapECDSASig(b) - } - } - - if err == nil { - sig.ECDSASigR = new(encoding.MPI).SetBig(r) - sig.ECDSASigS = new(encoding.MPI).SetBig(s) - } - case PubKeyAlgoEdDSA: - sk := priv.PrivateKey.(*eddsa.PrivateKey) - r, s, err := eddsa.Sign(sk, digest) - if err == nil { - sig.EdDSASigR = encoding.NewMPI(r) - sig.EdDSASigS = encoding.NewMPI(s) - } - case PubKeyAlgoEd25519: - sk := priv.PrivateKey.(*ed25519.PrivateKey) - signature, err := ed25519.Sign(sk, digest) - if err == nil { - sig.EdSig = signature - } - case PubKeyAlgoEd448: - sk := priv.PrivateKey.(*ed448.PrivateKey) - signature, err := ed448.Sign(sk, digest) - if err == nil { - sig.EdSig = signature - } - default: - err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) - } - - return -} - -// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA signature. -func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { - var ecsdaSig struct { - R, S *big.Int - } - _, err = asn1.Unmarshal(b, &ecsdaSig) - if err != nil { - return - } - return ecsdaSig.R, ecsdaSig.S, nil -} - -// SignUserId computes a signature from priv, asserting that pub is a valid -// key for the identity id. On success, the signature is stored in sig. Call -// Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { - if priv.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - prepareHash, err := sig.PrepareSign(config) - if err != nil { - return err - } - if err := userIdSignatureHash(id, pub, prepareHash); err != nil { - return err - } - return sig.Sign(prepareHash, priv, config) -} - -// SignDirectKeyBinding computes a signature from priv -// On success, the signature is stored in sig. -// Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) SignDirectKeyBinding(pub *PublicKey, priv *PrivateKey, config *Config) error { - if priv.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - prepareHash, err := sig.PrepareSign(config) - if err != nil { - return err - } - if err := directKeySignatureHash(pub, prepareHash); err != nil { - return err - } - return sig.Sign(prepareHash, priv, config) -} - -// CrossSignKey computes a signature from signingKey on pub hashed using hashKey. On success, -// the signature is stored in sig. Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) CrossSignKey(pub *PublicKey, hashKey *PublicKey, signingKey *PrivateKey, - config *Config) error { - prepareHash, err := sig.PrepareSign(config) - if err != nil { - return err - } - h, err := keySignatureHash(hashKey, pub, prepareHash) - if err != nil { - return err - } - return sig.Sign(h, signingKey, config) -} - -// SignKey computes a signature from priv, asserting that pub is a subkey. On -// success, the signature is stored in sig. Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { - if priv.Dummy() { - return errors.ErrDummyPrivateKey("dummy key found") - } - prepareHash, err := sig.PrepareSign(config) - if err != nil { - return err - } - h, err := keySignatureHash(&priv.PublicKey, pub, prepareHash) - if err != nil { - return err - } - return sig.Sign(h, priv, config) -} - -// RevokeKey computes a revocation signature of pub using priv. On success, the signature is -// stored in sig. Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) RevokeKey(pub *PublicKey, priv *PrivateKey, config *Config) error { - prepareHash, err := sig.PrepareSign(config) - if err != nil { - return err - } - if err := keyRevocationHash(pub, prepareHash); err != nil { - return err - } - return sig.Sign(prepareHash, priv, config) -} - -// RevokeSubkey computes a subkey revocation signature of pub using priv. -// On success, the signature is stored in sig. Call Serialize to write it out. -// If config is nil, sensible defaults will be used. -func (sig *Signature) RevokeSubkey(pub *PublicKey, priv *PrivateKey, config *Config) error { - // Identical to a subkey binding signature - return sig.SignKey(pub, priv, config) -} - -// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been -// called first. -func (sig *Signature) Serialize(w io.Writer) (err error) { - if len(sig.outSubpackets) == 0 { - sig.outSubpackets = sig.rawSubpackets - } - if sig.RSASignature == nil && sig.DSASigR == nil && sig.ECDSASigR == nil && sig.EdDSASigR == nil && sig.EdSig == nil { - return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") - } - - sigLength := 0 - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sigLength = int(sig.RSASignature.EncodedLength()) - case PubKeyAlgoDSA: - sigLength = int(sig.DSASigR.EncodedLength()) - sigLength += int(sig.DSASigS.EncodedLength()) - case PubKeyAlgoECDSA: - sigLength = int(sig.ECDSASigR.EncodedLength()) - sigLength += int(sig.ECDSASigS.EncodedLength()) - case PubKeyAlgoEdDSA: - sigLength = int(sig.EdDSASigR.EncodedLength()) - sigLength += int(sig.EdDSASigS.EncodedLength()) - case PubKeyAlgoEd25519: - sigLength = ed25519.SignatureSize - case PubKeyAlgoEd448: - sigLength = ed448.SignatureSize - default: - panic("impossible") - } - - hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) - unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) - length := 4 + /* length of version|signature type|public-key algorithm|hash algorithm */ - 2 /* length of hashed subpackets */ + hashedSubpacketsLen + - 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + - 2 /* hash tag */ + sigLength - if sig.Version == 6 { - length += 4 + /* the two length fields are four-octet instead of two */ - 1 + /* salt length */ - len(sig.salt) /* length salt */ - } - err = serializeHeader(w, packetTypeSignature, length) - if err != nil { - return - } - err = sig.serializeBody(w) - if err != nil { - return err - } - return -} - -func (sig *Signature) serializeBody(w io.Writer) (err error) { - var fields []byte - if sig.Version == 6 { - // v6 signatures use 4 octets for length - hashedSubpacketsLen := - uint32(uint32(sig.HashSuffix[4])<<24) | - uint32(uint32(sig.HashSuffix[5])<<16) | - uint32(uint32(sig.HashSuffix[6])<<8) | - uint32(sig.HashSuffix[7]) - fields = sig.HashSuffix[:8+hashedSubpacketsLen] - } else { - hashedSubpacketsLen := uint16(uint16(sig.HashSuffix[4])<<8) | - uint16(sig.HashSuffix[5]) - fields = sig.HashSuffix[:6+hashedSubpacketsLen] - - } - _, err = w.Write(fields) - if err != nil { - return - } - - unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) - var unhashedSubpackets []byte - if sig.Version == 6 { - unhashedSubpackets = make([]byte, 4+unhashedSubpacketsLen) - unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 24) - unhashedSubpackets[1] = byte(unhashedSubpacketsLen >> 16) - unhashedSubpackets[2] = byte(unhashedSubpacketsLen >> 8) - unhashedSubpackets[3] = byte(unhashedSubpacketsLen) - serializeSubpackets(unhashedSubpackets[4:], sig.outSubpackets, false) - } else { - unhashedSubpackets = make([]byte, 2+unhashedSubpacketsLen) - unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) - unhashedSubpackets[1] = byte(unhashedSubpacketsLen) - serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) - } - - _, err = w.Write(unhashedSubpackets) - if err != nil { - return - } - _, err = w.Write(sig.HashTag[:]) - if err != nil { - return - } - - if sig.Version == 6 { - // write salt for v6 signatures - _, err = w.Write([]byte{uint8(len(sig.salt))}) - if err != nil { - return - } - _, err = w.Write(sig.salt) - if err != nil { - return - } - } - - switch sig.PubKeyAlgo { - case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - _, err = w.Write(sig.RSASignature.EncodedBytes()) - case PubKeyAlgoDSA: - if _, err = w.Write(sig.DSASigR.EncodedBytes()); err != nil { - return - } - _, err = w.Write(sig.DSASigS.EncodedBytes()) - case PubKeyAlgoECDSA: - if _, err = w.Write(sig.ECDSASigR.EncodedBytes()); err != nil { - return - } - _, err = w.Write(sig.ECDSASigS.EncodedBytes()) - case PubKeyAlgoEdDSA: - if _, err = w.Write(sig.EdDSASigR.EncodedBytes()); err != nil { - return - } - _, err = w.Write(sig.EdDSASigS.EncodedBytes()) - case PubKeyAlgoEd25519: - err = ed25519.WriteSignature(w, sig.EdSig) - case PubKeyAlgoEd448: - err = ed448.WriteSignature(w, sig.EdSig) - default: - panic("impossible") - } - return -} - -// outputSubpacket represents a subpacket to be marshaled. -type outputSubpacket struct { - hashed bool // true if this subpacket is in the hashed area. - subpacketType signatureSubpacketType - isCritical bool - contents []byte -} - -func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubpacket, err error) { - creationTime := make([]byte, 4) - binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) - // Signature Creation Time - subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, true, creationTime}) - // Signature Expiration Time - if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { - sigLifetime := make([]byte, 4) - binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) - subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) - } - // Trust Signature - if sig.TrustLevel != 0 { - subpackets = append(subpackets, outputSubpacket{true, trustSubpacket, true, []byte{byte(sig.TrustLevel), byte(sig.TrustAmount)}}) - } - // Regular Expression - if sig.TrustRegularExpression != nil { - // RFC specifies the string should be null-terminated; add a null byte to the end - subpackets = append(subpackets, outputSubpacket{true, regularExpressionSubpacket, true, []byte(*sig.TrustRegularExpression + "\000")}) - } - // Key Expiration Time - if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { - keyLifetime := make([]byte, 4) - binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) - subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) - } - // Preferred Symmetric Ciphers for v1 SEIPD - if len(sig.PreferredSymmetric) > 0 { - subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) - } - // Issuer Key ID - if sig.IssuerKeyId != nil && sig.Version == 4 { - keyId := make([]byte, 8) - binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) - // Note: making this critical breaks RPM <=4.16. - // See: https://github.com/ProtonMail/go-crypto/issues/263 - subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) - } - // Notation Data - for _, notation := range sig.Notations { - subpackets = append( - subpackets, - outputSubpacket{ - true, - notationDataSubpacket, - notation.IsCritical, - notation.getData(), - }) - } - // Preferred Hash Algorithms - if len(sig.PreferredHash) > 0 { - subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) - } - // Preferred Compression Algorithms - if len(sig.PreferredCompression) > 0 { - subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) - } - // Keyserver Preferences - // Keyserver preferences may only appear in self-signatures or certification signatures. - if sig.KeyserverPrefsValid { - var prefs byte - if sig.KeyserverPrefNoModify { - prefs |= KeyserverPrefNoModify - } - subpackets = append(subpackets, outputSubpacket{true, keyserverPrefsSubpacket, false, []byte{prefs}}) - } - // Preferred Keyserver - if len(sig.PreferredKeyserver) > 0 { - subpackets = append(subpackets, outputSubpacket{true, prefKeyserverSubpacket, false, []uint8(sig.PreferredKeyserver)}) - } - // Primary User ID - if sig.IsPrimaryId != nil && *sig.IsPrimaryId { - subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) - } - // Policy URI - if len(sig.PolicyURI) > 0 { - subpackets = append(subpackets, outputSubpacket{true, policyUriSubpacket, false, []uint8(sig.PolicyURI)}) - } - // Key Flags - // Key flags may only appear in self-signatures or certification signatures. - if sig.FlagsValid { - var flags byte - if sig.FlagCertify { - flags |= KeyFlagCertify - } - if sig.FlagSign { - flags |= KeyFlagSign - } - if sig.FlagEncryptCommunications { - flags |= KeyFlagEncryptCommunications - } - if sig.FlagEncryptStorage { - flags |= KeyFlagEncryptStorage - } - if sig.FlagSplitKey { - flags |= KeyFlagSplitKey - } - if sig.FlagAuthenticate { - flags |= KeyFlagAuthenticate - } - if sig.FlagGroupKey { - flags |= KeyFlagGroupKey - } - subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, true, []byte{flags}}) - } - // Signer's User ID - if sig.SignerUserId != nil { - subpackets = append(subpackets, outputSubpacket{true, signerUserIdSubpacket, false, []byte(*sig.SignerUserId)}) - } - // Reason for Revocation - // Revocation reason appears only in revocation signatures and is serialized as per section 5.2.3.31. - if sig.RevocationReason != nil { - subpackets = append(subpackets, outputSubpacket{true, reasonForRevocationSubpacket, true, - append([]uint8{uint8(*sig.RevocationReason)}, []uint8(sig.RevocationReasonText)...)}) - } - // Features - var features = byte(0x00) - if sig.SEIPDv1 { - features |= 0x01 - } - if sig.SEIPDv2 { - features |= 0x08 - } - if features != 0x00 { - subpackets = append(subpackets, outputSubpacket{true, featuresSubpacket, false, []byte{features}}) - } - // Embedded Signature - // EmbeddedSignature appears only in subkeys capable of signing and is serialized as per section 5.2.3.34. - if sig.EmbeddedSignature != nil { - var buf bytes.Buffer - err = sig.EmbeddedSignature.serializeBody(&buf) - if err != nil { - return - } - subpackets = append(subpackets, outputSubpacket{true, embeddedSignatureSubpacket, true, buf.Bytes()}) - } - // Issuer Fingerprint - if sig.IssuerFingerprint != nil { - contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...) - subpackets = append(subpackets, outputSubpacket{true, issuerFingerprintSubpacket, sig.Version >= 5, contents}) - } - // Intended Recipient Fingerprint - for _, recipient := range sig.IntendedRecipients { - subpackets = append( - subpackets, - outputSubpacket{ - true, - intendedRecipientSubpacket, - false, - recipient.Serialize(), - }) - } - // Preferred AEAD Ciphersuites - if len(sig.PreferredCipherSuites) > 0 { - serialized := make([]byte, len(sig.PreferredCipherSuites)*2) - for i, cipherSuite := range sig.PreferredCipherSuites { - serialized[2*i] = cipherSuite[0] - serialized[2*i+1] = cipherSuite[1] - } - subpackets = append(subpackets, outputSubpacket{true, prefCipherSuitesSubpacket, false, serialized}) - } - return -} - -// AddMetadataToHashSuffix modifies the current hash suffix to include metadata -// (format, filename, and time). Version 5 keys protect this data including it -// in the hash computation. See section 5.2.4. -func (sig *Signature) AddMetadataToHashSuffix() { - if sig == nil || sig.Version != 5 { - return - } - if sig.SigType != 0x00 && sig.SigType != 0x01 { - return - } - lit := sig.Metadata - if lit == nil { - // This will translate into six 0x00 bytes. - lit = &LiteralData{} - } - - // Extract the current byte count - n := sig.HashSuffix[len(sig.HashSuffix)-8:] - l := uint64( - uint64(n[0])<<56 | uint64(n[1])<<48 | uint64(n[2])<<40 | uint64(n[3])<<32 | - uint64(n[4])<<24 | uint64(n[5])<<16 | uint64(n[6])<<8 | uint64(n[7])) - - suffix := bytes.NewBuffer(nil) - suffix.Write(sig.HashSuffix[:l]) - - // Add the metadata - var buf [4]byte - buf[0] = lit.Format - fileName := lit.FileName - if len(lit.FileName) > 255 { - fileName = fileName[:255] - } - buf[1] = byte(len(fileName)) - suffix.Write(buf[:2]) - suffix.Write([]byte(lit.FileName)) - binary.BigEndian.PutUint32(buf[:], lit.Time) - suffix.Write(buf[:]) - - suffix.Write([]byte{0x05, 0xff}) - suffix.Write([]byte{ - uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32), - uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l), - }) - sig.HashSuffix = suffix.Bytes() -} - -// SaltLengthForHash selects the required salt length for the given hash algorithm, -// as per Table 23 (Hash algorithm registry) of the crypto refresh. -// See RFC 9580 Section 9.5. -func SaltLengthForHash(hash crypto.Hash) (int, error) { - switch hash { - case crypto.SHA256, crypto.SHA224, crypto.SHA3_256: - return 16, nil - case crypto.SHA384: - return 24, nil - case crypto.SHA512, crypto.SHA3_512: - return 32, nil - default: - return 0, errors.UnsupportedError("hash function not supported for V6 signatures") - } -} - -// SignatureSaltForHash generates a random signature salt -// with the length for the given hash algorithm. -// See RFC 9580 Section 9.5. -func SignatureSaltForHash(hash crypto.Hash, randReader io.Reader) ([]byte, error) { - saltLength, err := SaltLengthForHash(hash) - if err != nil { - return nil, err - } - salt := make([]byte, saltLength) - _, err = io.ReadFull(randReader, salt) - if err != nil { - return nil, err - } - return salt, nil -} - -// removeNotationsWithName removes all notations in this signature with the given name. -func (sig *Signature) removeNotationsWithName(name string) { - if sig == nil || sig.Notations == nil { - return - } - updatedNotations := make([]*Notation, 0, len(sig.Notations)) - for _, notation := range sig.Notations { - if notation.Name != name { - updatedNotations = append(updatedNotations, notation) - } - } - sig.Notations = updatedNotations -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go deleted file mode 100644 index 2812a1db..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "bytes" - "crypto/cipher" - "crypto/sha256" - "io" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/s2k" - "golang.org/x/crypto/hkdf" -) - -// This is the largest session key that we'll support. Since at most 256-bit cipher -// is supported in OpenPGP, this is large enough to contain also the auth tag. -const maxSessionKeySizeInBytes = 64 - -// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC -// 4880, section 5.3. -type SymmetricKeyEncrypted struct { - Version int - CipherFunc CipherFunction - Mode AEADMode - s2k func(out, in []byte) - iv []byte - encryptedKey []byte // Contains also the authentication tag for AEAD -} - -// parse parses an SymmetricKeyEncrypted packet as specified in -// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#name-symmetric-key-encrypted-ses -func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { - var buf [1]byte - - // Version - if _, err := readFull(r, buf[:]); err != nil { - return err - } - ske.Version = int(buf[0]) - if ske.Version != 4 && ske.Version != 5 && ske.Version != 6 { - return errors.UnsupportedError("unknown SymmetricKeyEncrypted version") - } - - if V5Disabled && ske.Version == 5 { - return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed") - } - - if ske.Version > 5 { - // Scalar octet count - if _, err := readFull(r, buf[:]); err != nil { - return err - } - } - - // Cipher function - if _, err := readFull(r, buf[:]); err != nil { - return err - } - ske.CipherFunc = CipherFunction(buf[0]) - if !ske.CipherFunc.IsSupported() { - return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[0]))) - } - - if ske.Version >= 5 { - // AEAD mode - if _, err := readFull(r, buf[:]); err != nil { - return errors.StructuralError("cannot read AEAD octet from packet") - } - ske.Mode = AEADMode(buf[0]) - } - - if ske.Version > 5 { - // Scalar octet count - if _, err := readFull(r, buf[:]); err != nil { - return err - } - } - - var err error - if ske.s2k, err = s2k.Parse(r); err != nil { - if _, ok := err.(errors.ErrDummyPrivateKey); ok { - return errors.UnsupportedError("missing key GNU extension in session key") - } - return err - } - - if ske.Version >= 5 { - // AEAD IV - iv := make([]byte, ske.Mode.IvLength()) - _, err := readFull(r, iv) - if err != nil { - return errors.StructuralError("cannot read AEAD IV") - } - - ske.iv = iv - } - - encryptedKey := make([]byte, maxSessionKeySizeInBytes) - // The session key may follow. We just have to try and read to find - // out. If it exists then we limit it to maxSessionKeySizeInBytes. - n, err := readFull(r, encryptedKey) - if err != nil && err != io.ErrUnexpectedEOF { - return err - } - - if n != 0 { - if n == maxSessionKeySizeInBytes { - return errors.UnsupportedError("oversized encrypted session key") - } - ske.encryptedKey = encryptedKey[:n] - } - return nil -} - -// Decrypt attempts to decrypt an encrypted session key and returns the key and -// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data -// packet. -func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { - key := make([]byte, ske.CipherFunc.KeySize()) - ske.s2k(key, passphrase) - if len(ske.encryptedKey) == 0 { - return key, ske.CipherFunc, nil - } - switch ske.Version { - case 4: - plaintextKey, cipherFunc, err := ske.decryptV4(key) - return plaintextKey, cipherFunc, err - case 5, 6: - plaintextKey, err := ske.aeadDecrypt(ske.Version, key) - return plaintextKey, CipherFunction(0), err - } - err := errors.UnsupportedError("unknown SymmetricKeyEncrypted version") - return nil, CipherFunction(0), err -} - -func (ske *SymmetricKeyEncrypted) decryptV4(key []byte) ([]byte, CipherFunction, error) { - // the IV is all zeros - iv := make([]byte, ske.CipherFunc.blockSize()) - c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) - plaintextKey := make([]byte, len(ske.encryptedKey)) - c.XORKeyStream(plaintextKey, ske.encryptedKey) - cipherFunc := CipherFunction(plaintextKey[0]) - if cipherFunc.blockSize() == 0 { - return nil, ske.CipherFunc, errors.UnsupportedError( - "unknown cipher: " + strconv.Itoa(int(cipherFunc))) - } - plaintextKey = plaintextKey[1:] - if len(plaintextKey) != cipherFunc.KeySize() { - return nil, cipherFunc, errors.StructuralError( - "length of decrypted key not equal to cipher keysize") - } - return plaintextKey, cipherFunc, nil -} - -func (ske *SymmetricKeyEncrypted) aeadDecrypt(version int, key []byte) ([]byte, error) { - adata := []byte{0xc3, byte(version), byte(ske.CipherFunc), byte(ske.Mode)} - aead := getEncryptedKeyAeadInstance(ske.CipherFunc, ske.Mode, key, adata, version) - - plaintextKey, err := aead.Open(nil, ske.iv, ske.encryptedKey, adata) - if err != nil { - return nil, err - } - return plaintextKey, nil -} - -// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. -// The packet contains a random session key, encrypted by a key derived from -// the given passphrase. The session key is returned and must be passed to -// SerializeSymmetricallyEncrypted. -// If config is nil, sensible defaults will be used. -func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { - cipherFunc := config.Cipher() - - sessionKey := make([]byte, cipherFunc.KeySize()) - _, err = io.ReadFull(config.Random(), sessionKey) - if err != nil { - return - } - - err = SerializeSymmetricKeyEncryptedReuseKey(w, sessionKey, passphrase, config) - if err != nil { - return - } - - key = sessionKey - return -} - -// SerializeSymmetricKeyEncryptedReuseKey serializes a symmetric key packet to w. -// The packet contains the given session key, encrypted by a key derived from -// the given passphrase. The returned session key must be passed to -// SerializeSymmetricallyEncrypted. -// If config is nil, sensible defaults will be used. -// Deprecated: Use SerializeSymmetricKeyEncryptedAEADReuseKey instead. -func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, config *Config) (err error) { - return SerializeSymmetricKeyEncryptedAEADReuseKey(w, sessionKey, passphrase, config.AEAD() != nil, config) -} - -// SerializeSymmetricKeyEncryptedAEADReuseKey serializes a symmetric key packet to w. -// The packet contains the given session key, encrypted by a key derived from -// the given passphrase. The returned session key must be passed to -// SerializeSymmetricallyEncrypted. -// If aeadSupported is set, SKESK v6 is used, otherwise v4. -// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted. -// If config is nil, sensible defaults will be used. -func SerializeSymmetricKeyEncryptedAEADReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, aeadSupported bool, config *Config) (err error) { - var version int - if aeadSupported { - version = 6 - } else { - version = 4 - } - cipherFunc := config.Cipher() - // cipherFunc must be AES - if !cipherFunc.IsSupported() || cipherFunc < CipherAES128 || cipherFunc > CipherAES256 { - return errors.UnsupportedError("unsupported cipher: " + strconv.Itoa(int(cipherFunc))) - } - - keySize := cipherFunc.KeySize() - s2kBuf := new(bytes.Buffer) - keyEncryptingKey := make([]byte, keySize) - // s2k.Serialize salts and stretches the passphrase, and writes the - // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. - err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, config.S2K()) - if err != nil { - return - } - s2kBytes := s2kBuf.Bytes() - - var packetLength int - switch version { - case 4: - packetLength = 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize - case 5, 6: - ivLen := config.AEAD().Mode().IvLength() - tagLen := config.AEAD().Mode().TagLength() - packetLength = 3 + len(s2kBytes) + ivLen + keySize + tagLen - } - if version > 5 { - packetLength += 2 // additional octet count fields - } - - err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) - if err != nil { - return - } - - // Symmetric Key Encrypted Version - buf := []byte{byte(version)} - - if version > 5 { - // Scalar octet count - buf = append(buf, byte(3+len(s2kBytes)+config.AEAD().Mode().IvLength())) - } - - // Cipher function - buf = append(buf, byte(cipherFunc)) - - if version >= 5 { - // AEAD mode - buf = append(buf, byte(config.AEAD().Mode())) - } - if version > 5 { - // Scalar octet count - buf = append(buf, byte(len(s2kBytes))) - } - _, err = w.Write(buf) - if err != nil { - return - } - _, err = w.Write(s2kBytes) - if err != nil { - return - } - - switch version { - case 4: - iv := make([]byte, cipherFunc.blockSize()) - c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) - encryptedCipherAndKey := make([]byte, keySize+1) - c.XORKeyStream(encryptedCipherAndKey, buf[1:]) - c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) - _, err = w.Write(encryptedCipherAndKey) - if err != nil { - return - } - case 5, 6: - mode := config.AEAD().Mode() - adata := []byte{0xc3, byte(version), byte(cipherFunc), byte(mode)} - aead := getEncryptedKeyAeadInstance(cipherFunc, mode, keyEncryptingKey, adata, version) - - // Sample iv using random reader - iv := make([]byte, config.AEAD().Mode().IvLength()) - _, err = io.ReadFull(config.Random(), iv) - if err != nil { - return - } - // Seal and write (encryptedData includes auth. tag) - - encryptedData := aead.Seal(nil, iv, sessionKey, adata) - _, err = w.Write(iv) - if err != nil { - return - } - _, err = w.Write(encryptedData) - if err != nil { - return - } - } - - return -} - -func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte, version int) (aead cipher.AEAD) { - var blockCipher cipher.Block - if version > 5 { - hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData) - - encryptionKey := make([]byte, c.KeySize()) - _, _ = readFull(hkdfReader, encryptionKey) - - blockCipher = c.new(encryptionKey) - } else { - blockCipher = c.new(inputKey) - } - return mode.new(blockCipher) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go deleted file mode 100644 index 0e898742..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "io" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -const aeadSaltSize = 32 - -// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The -// encrypted Contents will consist of more OpenPGP packets. See RFC 4880, -// sections 5.7 and 5.13. -type SymmetricallyEncrypted struct { - Version int - Contents io.Reader // contains tag for version 2 - IntegrityProtected bool // If true it is type 18 (with MDC or AEAD). False is packet type 9 - - // Specific to version 1 - prefix []byte - - // Specific to version 2 - Cipher CipherFunction - Mode AEADMode - ChunkSizeByte byte - Salt [aeadSaltSize]byte -} - -const ( - symmetricallyEncryptedVersionMdc = 1 - symmetricallyEncryptedVersionAead = 2 -) - -func (se *SymmetricallyEncrypted) parse(r io.Reader) error { - if se.IntegrityProtected { - // See RFC 4880, section 5.13. - var buf [1]byte - _, err := readFull(r, buf[:]) - if err != nil { - return err - } - - switch buf[0] { - case symmetricallyEncryptedVersionMdc: - se.Version = symmetricallyEncryptedVersionMdc - case symmetricallyEncryptedVersionAead: - se.Version = symmetricallyEncryptedVersionAead - if err := se.parseAead(r); err != nil { - return err - } - default: - return errors.UnsupportedError("unknown SymmetricallyEncrypted version") - } - } - se.Contents = r - return nil -} - -// Decrypt returns a ReadCloser, from which the decrypted Contents of the -// packet can be read. An incorrect key will only be detected after trying -// to decrypt the entire data. -func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { - if se.Version == symmetricallyEncryptedVersionAead { - return se.decryptAead(key) - } - - return se.decryptMdc(c, key) -} - -// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet -// to w and returns a WriteCloser to which the to-be-encrypted packets can be -// written. -// If aeadSupported is set to true, SEIPDv2 is used with the indicated CipherSuite. -// Otherwise, SEIPDv1 is used with the indicated CipherFunction. -// Note: aeadSupported MUST match the value passed to SerializeEncryptedKeyAEAD -// and/or SerializeSymmetricKeyEncryptedAEADReuseKey. -// If config is nil, sensible defaults will be used. -func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, aeadSupported bool, cipherSuite CipherSuite, key []byte, config *Config) (Contents io.WriteCloser, err error) { - writeCloser := noOpCloser{w} - ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedIntegrityProtected) - if err != nil { - return - } - - if aeadSupported { - return serializeSymmetricallyEncryptedAead(ciphertext, cipherSuite, config.AEADConfig.ChunkSizeByte(), config.Random(), key) - } - - return serializeSymmetricallyEncryptedMdc(ciphertext, c, key, config) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go deleted file mode 100644 index 3ddc4fe4..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2023 Proton AG. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "crypto/cipher" - "crypto/sha256" - "fmt" - "io" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - "golang.org/x/crypto/hkdf" -) - -// parseAead parses a V2 SEIPD packet (AEAD) as specified in -// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2 -func (se *SymmetricallyEncrypted) parseAead(r io.Reader) error { - headerData := make([]byte, 3) - if n, err := io.ReadFull(r, headerData); n < 3 { - return errors.StructuralError("could not read aead header: " + err.Error()) - } - - // Cipher - se.Cipher = CipherFunction(headerData[0]) - // cipherFunc must have block size 16 to use AEAD - if se.Cipher.blockSize() != 16 { - return errors.UnsupportedError("invalid aead cipher: " + strconv.Itoa(int(se.Cipher))) - } - - // Mode - se.Mode = AEADMode(headerData[1]) - if se.Mode.TagLength() == 0 { - return errors.UnsupportedError("unknown aead mode: " + strconv.Itoa(int(se.Mode))) - } - - // Chunk size - se.ChunkSizeByte = headerData[2] - if se.ChunkSizeByte > 16 { - return errors.UnsupportedError("invalid aead chunk size byte: " + strconv.Itoa(int(se.ChunkSizeByte))) - } - - // Salt - if n, err := io.ReadFull(r, se.Salt[:]); n < aeadSaltSize { - return errors.StructuralError("could not read aead salt: " + err.Error()) - } - - return nil -} - -// associatedData for chunks: tag, version, cipher, mode, chunk size byte -func (se *SymmetricallyEncrypted) associatedData() []byte { - return []byte{ - 0xD2, - symmetricallyEncryptedVersionAead, - byte(se.Cipher), - byte(se.Mode), - se.ChunkSizeByte, - } -} - -// decryptAead decrypts a V2 SEIPD packet (AEAD) as specified in -// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2 -func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, error) { - if se.Cipher.KeySize() != len(inputKey) { - return nil, errors.StructuralError(fmt.Sprintf("invalid session key length for cipher: got %d bytes, but expected %d bytes", len(inputKey), se.Cipher.KeySize())) - } - - aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData()) - // Carry the first tagLen bytes - chunkSize := decodeAEADChunkSize(se.ChunkSizeByte) - tagLen := se.Mode.TagLength() - chunkBytes := make([]byte, chunkSize+tagLen*2) - peekedBytes := chunkBytes[chunkSize+tagLen:] - n, err := io.ReadFull(se.Contents, peekedBytes) - if n < tagLen || (err != nil && err != io.EOF) { - return nil, errors.StructuralError("not enough data to decrypt:" + err.Error()) - } - - return &aeadDecrypter{ - aeadCrypter: aeadCrypter{ - aead: aead, - chunkSize: decodeAEADChunkSize(se.ChunkSizeByte), - nonce: nonce, - associatedData: se.associatedData(), - chunkIndex: nonce[len(nonce)-8:], - packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected, - }, - reader: se.Contents, - chunkBytes: chunkBytes, - peekedBytes: peekedBytes, - }, nil -} - -// serializeSymmetricallyEncryptedAead encrypts to a writer a V2 SEIPD packet (AEAD) as specified in -// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2 -func serializeSymmetricallyEncryptedAead(ciphertext io.WriteCloser, cipherSuite CipherSuite, chunkSizeByte byte, rand io.Reader, inputKey []byte) (Contents io.WriteCloser, err error) { - // cipherFunc must have block size 16 to use AEAD - if cipherSuite.Cipher.blockSize() != 16 { - return nil, errors.InvalidArgumentError("invalid aead cipher function") - } - - if cipherSuite.Cipher.KeySize() != len(inputKey) { - return nil, errors.InvalidArgumentError("error in aead serialization: bad key length") - } - - // Data for en/decryption: tag, version, cipher, aead mode, chunk size - prefix := []byte{ - 0xD2, - symmetricallyEncryptedVersionAead, - byte(cipherSuite.Cipher), - byte(cipherSuite.Mode), - chunkSizeByte, - } - - // Write header (that correspond to prefix except first byte) - n, err := ciphertext.Write(prefix[1:]) - if err != nil || n < 4 { - return nil, err - } - - // Random salt - salt := make([]byte, aeadSaltSize) - if _, err := io.ReadFull(rand, salt); err != nil { - return nil, err - } - - if _, err := ciphertext.Write(salt); err != nil { - return nil, err - } - - aead, nonce := getSymmetricallyEncryptedAeadInstance(cipherSuite.Cipher, cipherSuite.Mode, inputKey, salt, prefix) - - chunkSize := decodeAEADChunkSize(chunkSizeByte) - tagLen := aead.Overhead() - chunkBytes := make([]byte, chunkSize+tagLen) - return &aeadEncrypter{ - aeadCrypter: aeadCrypter{ - aead: aead, - chunkSize: chunkSize, - associatedData: prefix, - nonce: nonce, - chunkIndex: nonce[len(nonce)-8:], - packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected, - }, - writer: ciphertext, - chunkBytes: chunkBytes, - }, nil -} - -func getSymmetricallyEncryptedAeadInstance(c CipherFunction, mode AEADMode, inputKey, salt, associatedData []byte) (aead cipher.AEAD, nonce []byte) { - hkdfReader := hkdf.New(sha256.New, inputKey, salt, associatedData) - - encryptionKey := make([]byte, c.KeySize()) - _, _ = readFull(hkdfReader, encryptionKey) - - nonce = make([]byte, mode.IvLength()) - - // Last 64 bits of nonce are the counter - _, _ = readFull(hkdfReader, nonce[:len(nonce)-8]) - - blockCipher := c.new(encryptionKey) - aead = mode.new(blockCipher) - - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go deleted file mode 100644 index 8b186236..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "crypto/cipher" - "crypto/sha1" - "crypto/subtle" - "hash" - "io" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/errors" -) - -// seMdcReader wraps an io.Reader with a no-op Close method. -type seMdcReader struct { - in io.Reader -} - -func (ser seMdcReader) Read(buf []byte) (int, error) { - return ser.in.Read(buf) -} - -func (ser seMdcReader) Close() error { - return nil -} - -func (se *SymmetricallyEncrypted) decryptMdc(c CipherFunction, key []byte) (io.ReadCloser, error) { - if !c.IsSupported() { - return nil, errors.UnsupportedError("unsupported cipher: " + strconv.Itoa(int(c))) - } - - if len(key) != c.KeySize() { - return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") - } - - if se.prefix == nil { - se.prefix = make([]byte, c.blockSize()+2) - _, err := readFull(se.Contents, se.prefix) - if err != nil { - return nil, err - } - } else if len(se.prefix) != c.blockSize()+2 { - return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") - } - - ocfbResync := OCFBResync - if se.IntegrityProtected { - // MDC packets use a different form of OCFB mode. - ocfbResync = OCFBNoResync - } - - s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) - - plaintext := cipher.StreamReader{S: s, R: se.Contents} - - if se.IntegrityProtected { - // IntegrityProtected packets have an embedded hash that we need to check. - h := sha1.New() - h.Write(se.prefix) - return &seMDCReader{in: plaintext, h: h}, nil - } - - // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. - return seMdcReader{plaintext}, nil -} - -const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size - -// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold -// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an -// MDC packet containing a hash of the previous Contents which is checked -// against the running hash. See RFC 4880, section 5.13. -type seMDCReader struct { - in io.Reader - h hash.Hash - trailer [mdcTrailerSize]byte - scratch [mdcTrailerSize]byte - trailerUsed int - error bool - eof bool -} - -func (ser *seMDCReader) Read(buf []byte) (n int, err error) { - if ser.error { - err = io.ErrUnexpectedEOF - return - } - if ser.eof { - err = io.EOF - return - } - - // If we haven't yet filled the trailer buffer then we must do that - // first. - for ser.trailerUsed < mdcTrailerSize { - n, err = ser.in.Read(ser.trailer[ser.trailerUsed:]) - ser.trailerUsed += n - if err == io.EOF { - if ser.trailerUsed != mdcTrailerSize { - n = 0 - err = io.ErrUnexpectedEOF - ser.error = true - return - } - ser.eof = true - n = 0 - return - } - - if err != nil { - n = 0 - return - } - } - - // If it's a short read then we read into a temporary buffer and shift - // the data into the caller's buffer. - if len(buf) <= mdcTrailerSize { - n, err = readFull(ser.in, ser.scratch[:len(buf)]) - copy(buf, ser.trailer[:n]) - ser.h.Write(buf[:n]) - copy(ser.trailer[:], ser.trailer[n:]) - copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:]) - if n < len(buf) { - ser.eof = true - err = io.EOF - } - return - } - - n, err = ser.in.Read(buf[mdcTrailerSize:]) - copy(buf, ser.trailer[:]) - ser.h.Write(buf[:n]) - copy(ser.trailer[:], buf[n:]) - - if err == io.EOF { - ser.eof = true - } - return -} - -// This is a new-format packet tag byte for a type 19 (Integrity Protected) packet. -const mdcPacketTagByte = byte(0x80) | 0x40 | 19 - -func (ser *seMDCReader) Close() error { - if ser.error { - return errors.ErrMDCHashMismatch - } - - for !ser.eof { - // We haven't seen EOF so we need to read to the end - var buf [1024]byte - _, err := ser.Read(buf[:]) - if err == io.EOF { - break - } - if err != nil { - return errors.ErrMDCHashMismatch - } - } - - ser.h.Write(ser.trailer[:2]) - - final := ser.h.Sum(nil) - if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { - return errors.ErrMDCHashMismatch - } - // The hash already includes the MDC header, but we still check its value - // to confirm encryption correctness - if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { - return errors.ErrMDCHashMismatch - } - return nil -} - -// An seMDCWriter writes through to an io.WriteCloser while maintains a running -// hash of the data written. On close, it emits an MDC packet containing the -// running hash. -type seMDCWriter struct { - w io.WriteCloser - h hash.Hash -} - -func (w *seMDCWriter) Write(buf []byte) (n int, err error) { - w.h.Write(buf) - return w.w.Write(buf) -} - -func (w *seMDCWriter) Close() (err error) { - var buf [mdcTrailerSize]byte - - buf[0] = mdcPacketTagByte - buf[1] = sha1.Size - w.h.Write(buf[:2]) - digest := w.h.Sum(nil) - copy(buf[2:], digest) - - _, err = w.w.Write(buf[:]) - if err != nil { - return - } - return w.w.Close() -} - -// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. -type noOpCloser struct { - w io.Writer -} - -func (c noOpCloser) Write(data []byte) (n int, err error) { - return c.w.Write(data) -} - -func (c noOpCloser) Close() error { - return nil -} - -func serializeSymmetricallyEncryptedMdc(ciphertext io.WriteCloser, c CipherFunction, key []byte, config *Config) (Contents io.WriteCloser, err error) { - // Disallow old cipher suites - if !c.IsSupported() || c < CipherAES128 { - return nil, errors.InvalidArgumentError("invalid mdc cipher function") - } - - if c.KeySize() != len(key) { - return nil, errors.InvalidArgumentError("error in mdc serialization: bad key length") - } - - _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersionMdc}) - if err != nil { - return - } - - block := c.new(key) - blockSize := block.BlockSize() - iv := make([]byte, blockSize) - _, err = io.ReadFull(config.Random(), iv) - if err != nil { - return nil, err - } - s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) - _, err = ciphertext.Write(prefix) - if err != nil { - return - } - plaintext := cipher.StreamWriter{S: s, W: ciphertext} - - h := sha1.New() - h.Write(iv) - h.Write(iv[blockSize-2:]) - Contents = &seMDCWriter{w: plaintext, h: h} - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go deleted file mode 100644 index 63814ed1..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packet - -import ( - "bytes" - "image" - "image/jpeg" - "io" -) - -const UserAttrImageSubpacket = 1 - -// UserAttribute is capable of storing other types of data about a user -// beyond name, email and a text comment. In practice, user attributes are typically used -// to store a signed thumbnail photo JPEG image of the user. -// See RFC 4880, section 5.12. -type UserAttribute struct { - Contents []*OpaqueSubpacket -} - -// NewUserAttributePhoto creates a user attribute packet -// containing the given images. -func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { - uat = new(UserAttribute) - for _, photo := range photos { - var buf bytes.Buffer - // RFC 4880, Section 5.12.1. - data := []byte{ - 0x10, 0x00, // Little-endian image header length (16 bytes) - 0x01, // Image header version 1 - 0x01, // JPEG - 0, 0, 0, 0, // 12 reserved octets, must be all zero. - 0, 0, 0, 0, - 0, 0, 0, 0} - if _, err = buf.Write(data); err != nil { - return - } - if err = jpeg.Encode(&buf, photo, nil); err != nil { - return - } - - lengthBuf := make([]byte, 5) - n := serializeSubpacketLength(lengthBuf, len(buf.Bytes())+1) - lengthBuf = lengthBuf[:n] - - uat.Contents = append(uat.Contents, &OpaqueSubpacket{ - SubType: UserAttrImageSubpacket, - EncodedLength: lengthBuf, - Contents: buf.Bytes(), - }) - } - return -} - -// NewUserAttribute creates a new user attribute packet containing the given subpackets. -func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { - return &UserAttribute{Contents: contents} -} - -func (uat *UserAttribute) parse(r io.Reader) (err error) { - // RFC 4880, section 5.13 - b, err := io.ReadAll(r) - if err != nil { - return - } - uat.Contents, err = OpaqueSubpackets(b) - return -} - -// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including -// header. -func (uat *UserAttribute) Serialize(w io.Writer) (err error) { - var buf bytes.Buffer - for _, sp := range uat.Contents { - err = sp.Serialize(&buf) - if err != nil { - return err - } - } - if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { - return err - } - _, err = w.Write(buf.Bytes()) - return -} - -// ImageData returns zero or more byte slices, each containing -// JPEG File Interchange Format (JFIF), for each photo in the -// user attribute packet. -func (uat *UserAttribute) ImageData() (imageData [][]byte) { - for _, sp := range uat.Contents { - if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { - imageData = append(imageData, sp.Contents[16:]) - } - } - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go deleted file mode 100644 index 3c7451a3..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2011 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 packet - -import ( - "io" - "strings" -) - -// UserId contains text that is intended to represent the name and email -// address of the key holder. See RFC 4880, section 5.11. By convention, this -// takes the form "Full Name (Comment) " -type UserId struct { - Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. - - Name, Comment, Email string -} - -func hasInvalidCharacters(s string) bool { - for _, c := range s { - switch c { - case '(', ')', '<', '>', 0: - return true - } - } - return false -} - -// NewUserId returns a UserId or nil if any of the arguments contain invalid -// characters. The invalid characters are '\x00', '(', ')', '<' and '>' -func NewUserId(name, comment, email string) *UserId { - // RFC 4880 doesn't deal with the structure of userid strings; the - // name, comment and email form is just a convention. However, there's - // no convention about escaping the metacharacters and GPG just refuses - // to create user ids where, say, the name contains a '('. We mirror - // this behaviour. - - if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { - return nil - } - - uid := new(UserId) - uid.Name, uid.Comment, uid.Email = name, comment, email - uid.Id = name - if len(comment) > 0 { - if len(uid.Id) > 0 { - uid.Id += " " - } - uid.Id += "(" - uid.Id += comment - uid.Id += ")" - } - if len(email) > 0 { - if len(uid.Id) > 0 { - uid.Id += " " - } - uid.Id += "<" - uid.Id += email - uid.Id += ">" - } - return uid -} - -func (uid *UserId) parse(r io.Reader) (err error) { - // RFC 4880, section 5.11 - b, err := io.ReadAll(r) - if err != nil { - return - } - uid.Id = string(b) - uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) - return -} - -// Serialize marshals uid to w in the form of an OpenPGP packet, including -// header. -func (uid *UserId) Serialize(w io.Writer) error { - err := serializeHeader(w, packetTypeUserId, len(uid.Id)) - if err != nil { - return err - } - _, err = w.Write([]byte(uid.Id)) - return err -} - -// parseUserId extracts the name, comment and email from a user id string that -// is formatted as "Full Name (Comment) ". -func parseUserId(id string) (name, comment, email string) { - var n, c, e struct { - start, end int - } - var state int - - for offset, rune := range id { - switch state { - case 0: - // Entering name - n.start = offset - state = 1 - fallthrough - case 1: - // In name - if rune == '(' { - state = 2 - n.end = offset - } else if rune == '<' { - state = 5 - n.end = offset - } - case 2: - // Entering comment - c.start = offset - state = 3 - fallthrough - case 3: - // In comment - if rune == ')' { - state = 4 - c.end = offset - } - case 4: - // Between comment and email - if rune == '<' { - state = 5 - } - case 5: - // Entering email - e.start = offset - state = 6 - fallthrough - case 6: - // In email - if rune == '>' { - state = 7 - e.end = offset - } - default: - // After email - } - } - switch state { - case 1: - // ended in the name - n.end = len(id) - case 3: - // ended in comment - c.end = len(id) - case 6: - // ended in email - e.end = len(id) - } - - name = strings.TrimSpace(id[n.start:n.end]) - comment = strings.TrimSpace(id[c.start:c.end]) - email = strings.TrimSpace(id[e.start:e.end]) - - // RFC 2822 3.4: alternate simple form of a mailbox - if email == "" && strings.ContainsRune(name, '@') { - email = name - name = "" - } - - return -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go deleted file mode 100644 index 5578797e..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/read.go +++ /dev/null @@ -1,619 +0,0 @@ -// Copyright 2011 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 openpgp implements high level operations on OpenPGP messages. -package openpgp // import "github.com/ProtonMail/go-crypto/openpgp" - -import ( - "crypto" - _ "crypto/sha256" - _ "crypto/sha512" - "hash" - "io" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/armor" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" - "github.com/ProtonMail/go-crypto/openpgp/packet" - _ "golang.org/x/crypto/sha3" -) - -// SignatureType is the armor type for a PGP signature. -var SignatureType = "PGP SIGNATURE" - -// readArmored reads an armored block with the given type. -func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { - block, err := armor.Decode(r) - if err != nil { - return - } - - if block.Type != expectedType { - return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) - } - - return block.Body, nil -} - -// MessageDetails contains the result of parsing an OpenPGP encrypted and/or -// signed message. -type MessageDetails struct { - IsEncrypted bool // true if the message was encrypted. - EncryptedToKeyIds []uint64 // the list of recipient key ids. - IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. - DecryptedWith Key // the private key used to decrypt the message, if any. - IsSigned bool // true if the message is signed. - SignedByKeyId uint64 // the key id of the signer, if any. - SignedByFingerprint []byte // the key fingerprint of the signer, if any. - SignedBy *Key // the key of the signer, if available. - LiteralData *packet.LiteralData // the metadata of the contents - UnverifiedBody io.Reader // the contents of the message. - - // If IsSigned is true and SignedBy is non-zero then the signature will - // be verified as UnverifiedBody is read. The signature cannot be - // checked until the whole of UnverifiedBody is read so UnverifiedBody - // must be consumed until EOF before the data can be trusted. Even if a - // message isn't signed (or the signer is unknown) the data may contain - // an authentication code that is only checked once UnverifiedBody has - // been consumed. Once EOF has been seen, the following fields are - // valid. (An authentication code failure is reported as a - // SignatureError error when reading from UnverifiedBody.) - Signature *packet.Signature // the signature packet itself. - SignatureError error // nil if the signature is good. - UnverifiedSignatures []*packet.Signature // all other unverified signature packets. - - decrypted io.ReadCloser -} - -// A PromptFunction is used as a callback by functions that may need to decrypt -// a private key, or prompt for a passphrase. It is called with a list of -// acceptable, encrypted private keys and a boolean that indicates whether a -// passphrase is usable. It should either decrypt a private key or return a -// passphrase to try. If the decrypted private key or given passphrase isn't -// correct, the function will be called again, forever. Any error returned will -// be passed up. -type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) - -// A keyEnvelopePair is used to store a private key with the envelope that -// contains a symmetric key, encrypted with that key. -type keyEnvelopePair struct { - key Key - encryptedKey *packet.EncryptedKey -} - -// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. -// The given KeyRing should contain both public keys (for signature -// verification) and, possibly encrypted, private keys for decrypting. -// If config is nil, sensible defaults will be used. -func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { - var p packet.Packet - - var symKeys []*packet.SymmetricKeyEncrypted - var pubKeys []keyEnvelopePair - // Integrity protected encrypted packet: SymmetricallyEncrypted or AEADEncrypted - var edp packet.EncryptedDataPacket - - packets := packet.NewReader(r) - md = new(MessageDetails) - md.IsEncrypted = true - - // The message, if encrypted, starts with a number of packets - // containing an encrypted decryption key. The decryption key is either - // encrypted to a public key, or with a passphrase. This loop - // collects these packets. -ParsePackets: - for { - p, err = packets.Next() - if err != nil { - return nil, err - } - switch p := p.(type) { - case *packet.SymmetricKeyEncrypted: - // This packet contains the decryption key encrypted with a passphrase. - md.IsSymmetricallyEncrypted = true - symKeys = append(symKeys, p) - case *packet.EncryptedKey: - // This packet contains the decryption key encrypted to a public key. - md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) - switch p.Algo { - case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH, packet.PubKeyAlgoX25519, packet.PubKeyAlgoX448: - break - default: - continue - } - if keyring != nil { - var keys []Key - if p.KeyId == 0 { - keys = keyring.DecryptionKeys() - } else { - keys = keyring.KeysById(p.KeyId) - } - for _, k := range keys { - pubKeys = append(pubKeys, keyEnvelopePair{k, p}) - } - } - case *packet.SymmetricallyEncrypted: - if !p.IntegrityProtected && !config.AllowUnauthenticatedMessages() { - return nil, errors.UnsupportedError("message is not integrity protected") - } - edp = p - break ParsePackets - case *packet.AEADEncrypted: - edp = p - break ParsePackets - case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: - // This message isn't encrypted. - if len(symKeys) != 0 || len(pubKeys) != 0 { - return nil, errors.StructuralError("key material not followed by encrypted message") - } - packets.Unread(p) - return readSignedMessage(packets, nil, keyring, config) - } - } - - var candidates []Key - var decrypted io.ReadCloser - - // Now that we have the list of encrypted keys we need to decrypt at - // least one of them or, if we cannot, we need to call the prompt - // function so that it can decrypt a key or give us a passphrase. -FindKey: - for { - // See if any of the keys already have a private key available - candidates = candidates[:0] - candidateFingerprints := make(map[string]bool) - - for _, pk := range pubKeys { - if pk.key.PrivateKey == nil { - continue - } - if !pk.key.PrivateKey.Encrypted { - if len(pk.encryptedKey.Key) == 0 { - errDec := pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) - if errDec != nil { - continue - } - } - // Try to decrypt symmetrically encrypted - decrypted, err = edp.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) - if err != nil && err != errors.ErrKeyIncorrect { - return nil, err - } - if decrypted != nil { - md.DecryptedWith = pk.key - break FindKey - } - } else { - fpr := string(pk.key.PublicKey.Fingerprint[:]) - if v := candidateFingerprints[fpr]; v { - continue - } - candidates = append(candidates, pk.key) - candidateFingerprints[fpr] = true - } - } - - if len(candidates) == 0 && len(symKeys) == 0 { - return nil, errors.ErrKeyIncorrect - } - - if prompt == nil { - return nil, errors.ErrKeyIncorrect - } - - passphrase, err := prompt(candidates, len(symKeys) != 0) - if err != nil { - return nil, err - } - - // Try the symmetric passphrase first - if len(symKeys) != 0 && passphrase != nil { - for _, s := range symKeys { - key, cipherFunc, err := s.Decrypt(passphrase) - // In v4, on wrong passphrase, session key decryption is very likely to result in an invalid cipherFunc: - // only for < 5% of cases we will proceed to decrypt the data - if err == nil { - decrypted, err = edp.Decrypt(cipherFunc, key) - if err != nil { - return nil, err - } - if decrypted != nil { - break FindKey - } - } - } - } - } - - md.decrypted = decrypted - if err := packets.Push(decrypted); err != nil { - return nil, err - } - mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config) - if sensitiveParsingErr != nil { - return nil, errors.HandleSensitiveParsingError(sensitiveParsingErr, md.decrypted != nil) - } - return mdFinal, nil -} - -// readSignedMessage reads a possibly signed message if mdin is non-zero then -// that structure is updated and returned. Otherwise a fresh MessageDetails is -// used. -func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing, config *packet.Config) (md *MessageDetails, err error) { - if mdin == nil { - mdin = new(MessageDetails) - } - md = mdin - - var p packet.Packet - var h hash.Hash - var wrappedHash hash.Hash - var prevLast bool -FindLiteralData: - for { - p, err = packets.Next() - if err != nil { - return nil, err - } - switch p := p.(type) { - case *packet.Compressed: - if err := packets.Push(p.LimitedBodyReader(config.DecompressedMessageSizeLimit())); err != nil { - return nil, err - } - case *packet.OnePassSignature: - if prevLast { - return nil, errors.UnsupportedError("nested signature packets") - } - - if p.IsLast { - prevLast = true - } - - h, wrappedHash, err = hashForSignature(p.Hash, p.SigType, p.Salt) - if err != nil { - md.SignatureError = err - } - - md.IsSigned = true - if p.Version == 6 { - md.SignedByFingerprint = p.KeyFingerprint - } - md.SignedByKeyId = p.KeyId - - if keyring != nil { - keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) - if len(keys) > 0 { - md.SignedBy = &keys[0] - } - } - case *packet.LiteralData: - md.LiteralData = p - break FindLiteralData - } - } - - if md.IsSigned && md.SignatureError == nil { - md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config} - } else if md.decrypted != nil { - md.UnverifiedBody = &checkReader{md, false} - } else { - md.UnverifiedBody = md.LiteralData.Body - } - - return md, nil -} - -func wrapHashForSignature(hashFunc hash.Hash, sigType packet.SignatureType) (hash.Hash, error) { - switch sigType { - case packet.SigTypeBinary: - return hashFunc, nil - case packet.SigTypeText: - return NewCanonicalTextHash(hashFunc), nil - } - return nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) -} - -// hashForSignature returns a pair of hashes that can be used to verify a -// signature. The signature may specify that the contents of the signed message -// should be preprocessed (i.e. to normalize line endings). Thus this function -// returns two hashes. The second should be used to hash the message itself and -// performs any needed preprocessing. -func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType, sigSalt []byte) (hash.Hash, hash.Hash, error) { - if _, ok := algorithm.HashToHashIdWithSha1(hashFunc); !ok { - return nil, nil, errors.UnsupportedError("unsupported hash function") - } - if !hashFunc.Available() { - return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashFunc))) - } - h := hashFunc.New() - if sigSalt != nil { - h.Write(sigSalt) - } - wrappedHash, err := wrapHashForSignature(h, sigType) - if err != nil { - return nil, nil, err - } - switch sigType { - case packet.SigTypeBinary: - return h, wrappedHash, nil - case packet.SigTypeText: - return h, wrappedHash, nil - } - return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) -} - -// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF -// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger -// MDC checks. -type checkReader struct { - md *MessageDetails - checked bool -} - -func (cr *checkReader) Read(buf []byte) (int, error) { - n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf) - if sensitiveParsingError == io.EOF { - if cr.checked { - // Only check once - return n, io.EOF - } - mdcErr := cr.md.decrypted.Close() - if mdcErr != nil { - return n, mdcErr - } - cr.checked = true - return n, io.EOF - } - - if sensitiveParsingError != nil { - return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true) - } - - return n, nil -} - -// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes -// the data as it is read. When it sees an EOF from the underlying io.Reader -// it parses and checks a trailing Signature packet and triggers any MDC checks. -type signatureCheckReader struct { - packets *packet.Reader - h, wrappedHash hash.Hash - md *MessageDetails - config *packet.Config -} - -func (scr *signatureCheckReader) Read(buf []byte) (int, error) { - n, sensitiveParsingError := scr.md.LiteralData.Body.Read(buf) - - // Hash only if required - if scr.md.SignedBy != nil { - scr.wrappedHash.Write(buf[:n]) - } - - readsDecryptedData := scr.md.decrypted != nil - if sensitiveParsingError == io.EOF { - var p packet.Packet - var readError error - var sig *packet.Signature - - p, readError = scr.packets.Next() - for readError == nil { - var ok bool - if sig, ok = p.(*packet.Signature); ok { - if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { - sig.Metadata = scr.md.LiteralData - } - - // If signature KeyID matches - if scr.md.SignedBy != nil && *sig.IssuerKeyId == scr.md.SignedByKeyId { - key := scr.md.SignedBy - signatureError := key.PublicKey.VerifySignature(scr.h, sig) - if signatureError == nil { - signatureError = checkMessageSignatureDetails(key, sig, scr.config) - } - scr.md.Signature = sig - scr.md.SignatureError = signatureError - } else { - scr.md.UnverifiedSignatures = append(scr.md.UnverifiedSignatures, sig) - } - } - - p, readError = scr.packets.Next() - } - - if scr.md.SignedBy != nil && scr.md.Signature == nil { - if scr.md.UnverifiedSignatures == nil { - scr.md.SignatureError = errors.StructuralError("LiteralData not followed by signature") - } else { - scr.md.SignatureError = errors.StructuralError("No matching signature found") - } - } - - // The SymmetricallyEncrypted packet, if any, might have an - // unsigned hash of its own. In order to check this we need to - // close that Reader. - if scr.md.decrypted != nil { - if sensitiveParsingError := scr.md.decrypted.Close(); sensitiveParsingError != nil { - return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true) - } - } - return n, io.EOF - } - - if sensitiveParsingError != nil { - return n, errors.HandleSensitiveParsingError(sensitiveParsingError, readsDecryptedData) - } - - return n, nil -} - -// VerifyDetachedSignature takes a signed file and a detached signature and -// returns the signature packet and the entity the signature was signed by, -// if any, and a possible signature verification error. -// If the signer isn't known, ErrUnknownIssuer is returned. -func VerifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) { - return verifyDetachedSignature(keyring, signed, signature, nil, false, config) -} - -// VerifyDetachedSignatureAndHash performs the same actions as -// VerifyDetachedSignature and checks that the expected hash functions were used. -func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) { - return verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config) -} - -// CheckDetachedSignature takes a signed file and a detached signature and -// returns the entity the signature was signed by, if any, and a possible -// signature verification error. If the signer isn't known, -// ErrUnknownIssuer is returned. -func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) { - _, signer, err = verifyDetachedSignature(keyring, signed, signature, nil, false, config) - return -} - -// CheckDetachedSignatureAndHash performs the same actions as -// CheckDetachedSignature and checks that the expected hash functions were used. -func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) { - _, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config) - return -} - -func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, checkHashes bool, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) { - var issuerKeyId uint64 - var hashFunc crypto.Hash - var sigType packet.SignatureType - var keys []Key - var p packet.Packet - - packets := packet.NewReader(signature) - for { - p, err = packets.Next() - if err == io.EOF { - return nil, nil, errors.ErrUnknownIssuer - } - if err != nil { - return nil, nil, err - } - - var ok bool - sig, ok = p.(*packet.Signature) - if !ok { - return nil, nil, errors.StructuralError("non signature packet found") - } - if sig.IssuerKeyId == nil { - return nil, nil, errors.StructuralError("signature doesn't have an issuer") - } - issuerKeyId = *sig.IssuerKeyId - hashFunc = sig.Hash - sigType = sig.SigType - if checkHashes { - matchFound := false - // check for hashes - for _, expectedHash := range expectedHashes { - if hashFunc == expectedHash { - matchFound = true - break - } - } - if !matchFound { - return nil, nil, errors.StructuralError("hash algorithm or salt mismatch with cleartext message headers") - } - } - keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) - if len(keys) > 0 { - break - } - } - - if len(keys) == 0 { - panic("unreachable") - } - - h, err := sig.PrepareVerify() - if err != nil { - return nil, nil, err - } - wrappedHash, err := wrapHashForSignature(h, sigType) - if err != nil { - return nil, nil, err - } - - if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { - return nil, nil, err - } - - for _, key := range keys { - err = key.PublicKey.VerifySignature(h, sig) - if err == nil { - return sig, key.Entity, checkMessageSignatureDetails(&key, sig, config) - } - } - - return nil, nil, err -} - -// CheckArmoredDetachedSignature performs the same actions as -// CheckDetachedSignature but expects the signature to be armored. -func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) { - body, err := readArmored(signature, SignatureType) - if err != nil { - return - } - - return CheckDetachedSignature(keyring, signed, body, config) -} - -// checkMessageSignatureDetails returns an error if: -// - The signature (or one of the binding signatures mentioned below) -// has a unknown critical notation data subpacket -// - The primary key of the signing entity is revoked -// - The primary identity is revoked -// - The signature is expired -// - The primary key of the signing entity is expired according to the -// primary identity binding signature -// -// ... or, if the signature was signed by a subkey and: -// - The signing subkey is revoked -// - The signing subkey is expired according to the subkey binding signature -// - The signing subkey binding signature is expired -// - The signing subkey cross-signature is expired -// -// NOTE: The order of these checks is important, as the caller may choose to -// ignore ErrSignatureExpired or ErrKeyExpired errors, but should never -// ignore any other errors. -func checkMessageSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error { - now := config.Now() - primarySelfSignature, primaryIdentity := key.Entity.PrimarySelfSignature() - signedBySubKey := key.PublicKey != key.Entity.PrimaryKey - sigsToCheck := []*packet.Signature{signature, primarySelfSignature} - if signedBySubKey { - sigsToCheck = append(sigsToCheck, key.SelfSignature, key.SelfSignature.EmbeddedSignature) - } - for _, sig := range sigsToCheck { - for _, notation := range sig.Notations { - if notation.IsCritical && !config.KnownNotation(notation.Name) { - return errors.SignatureError("unknown critical notation: " + notation.Name) - } - } - } - if key.Entity.Revoked(now) || // primary key is revoked - (signedBySubKey && key.Revoked(now)) || // subkey is revoked - (primaryIdentity != nil && primaryIdentity.Revoked(now)) { // primary identity is revoked for v4 - return errors.ErrKeyRevoked - } - if key.Entity.PrimaryKey.KeyExpired(primarySelfSignature, now) { // primary key is expired - return errors.ErrKeyExpired - } - if signedBySubKey { - if key.PublicKey.KeyExpired(key.SelfSignature, now) { // subkey is expired - return errors.ErrKeyExpired - } - } - for _, sig := range sigsToCheck { - if sig.SigExpired(now) { // any of the relevant signatures are expired - return errors.ErrSignatureExpired - } - } - return nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go deleted file mode 100644 index 670d6022..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go +++ /dev/null @@ -1,457 +0,0 @@ -package openpgp - -const testKey1KeyId uint64 = 0xA34D7E18C20C31BB -const testKey3KeyId uint64 = 0x338934250CCC0360 -const testKeyP256KeyId uint64 = 0xd44a2c495918513e - -const signedInput = "Signed message\nline 2\nline 3\n" -const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n" - -const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b" - -const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77" - -const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39" - -const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83" - -const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817" - -// The plaintext is https://www.gutenberg.org/cache/epub/1080/pg1080.txt -const modestProposalSha512 = "lbbrB1+WP3T9AaC9OQqBdOcCjgeEQadlulXsNPgVx0tyqPzDHwUugZ2gE7V0ESKAw6kAVfgkcuvfgxAAGaeHtw==" - -const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003" - -const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000" - -const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000" - -const ed25519wX25519Key = "c54b0663877fe31b00000020f94da7bb48d60a61e567706a6587d0331999bb9d891a08242ead84543df895a3001972817b12be707e8d5f586ce61361201d344eb266a2c82fde6835762b65b0b7c2b1061f1b0a00000042058263877fe3030b090705150a0e080c021600029b03021e09222106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc905270902070200000000ad2820103e2d7d227ec0e6d7ce4471db36bfc97083253690271498a7ef0576c07faae14585b3b903b0127ec4fda2f023045a2ec76bcb4f9571a9651e14aee1137a1d668442c88f951e33c4ffd33fb9a17d511eed758fc6d9cc50cb5fd793b2039d5804c74b0663877fe319000000208693248367f9e5015db922f8f48095dda784987f2d5985b12fbad16caf5e4435004d600a4f794d44775c57a26e0feefed558e9afffd6ad0d582d57fb2ba2dcedb8c29b06181b0a0000002c050263877fe322a106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9021b0c00000000defa20a6e9186d9d5935fc8fe56314cdb527486a5a5120f9b762a235a729f039010a56b89c658568341fbef3b894e9834ad9bc72afae2f4c9c47a43855e65f1cb0a3f77bbc5f61085c1f8249fe4e7ca59af5f0bcee9398e0fa8d76e522e1d8ab42bb0d" - -const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300" - -const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200" - -const signedEncryptedMessageHex = "c18c032a67d68660df41c70103ff5a84c9a72f80e74ef0384c2d6a9ebfe2b09e06a8f298394f6d2abf174e40934ab0ec01fb2d0ddf21211c6fe13eb238563663b017a6b44edca552eb4736c4b7dc6ed907dd9e12a21b51b64b46f902f76fb7aaf805c1db8070574d8d0431a23e324a750f77fb72340a17a42300ee4ca8207301e95a731da229a63ab9c6b44541fbd2c11d016d810b3b3b2b38f15b5b40f0a4910332829c2062f1f7cc61f5b03677d73c54cafa1004ced41f315d46444946faae571d6f426e6dbd45d9780eb466df042005298adabf7ce0ef766dfeb94cd449c7ed0046c880339599c4711af073ce649b1e237c40b50a5536283e03bdbb7afad78bd08707715c67fb43295f905b4c479178809d429a8e167a9a8c6dfd8ab20b4edebdc38d6dec879a3202e1b752690d9bb5b0c07c5a227c79cc200e713a99251a4219d62ad5556900cf69bd384b6c8e726c7be267471d0d23af956da165af4af757246c2ebcc302b39e8ef2fccb4971b234fcda22d759ddb20e27269ee7f7fe67898a9de721bfa02ab0becaa046d00ea16cb1afc4e2eab40d0ac17121c565686e5cbd0cbdfbd9d6db5c70278b9c9db5a83176d04f61fbfbc4471d721340ede2746e5c312ded4f26787985af92b64fae3f253dbdde97f6a5e1996fd4d865599e32ff76325d3e9abe93184c02988ee89a4504356a4ef3b9b7a57cbb9637ca90af34a7676b9ef559325c3cca4e29d69fec1887f5440bb101361d744ad292a8547f22b4f22b419a42aa836169b89190f46d9560824cb2ac6e8771de8223216a5e647e132ab9eebcba89569ab339cb1c3d70fe806b31f4f4c600b4103b8d7583ebff16e43dcda551e6530f975122eb8b29" - -const verifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61" - -const unverifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61" - -const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3" - -const signatureEncryptedMessage2Hex = "c24604001102000605024dfd0166000a091033af447ccd759b09bae600a096ec5e63ecf0a403085e10f75cc3bab327663282009f51fad9df457ed8d2b70d8a73c76e0443eac0f377" - -const symmetricallyEncryptedCompressedHex = "c32e040903085a357c1a7b5614ed00cc0d1d92f428162058b3f558a0fb0980d221ebac6c97d5eda4e0fe32f6e706e94dd263012d6ca1ef8c4bbd324098225e603a10c85ebf09cbf7b5aeeb5ce46381a52edc51038b76a8454483be74e6dcd1e50d5689a8ae7eceaeefed98a0023d49b22eb1f65c2aa1ef1783bb5e1995713b0457102ec3c3075fe871267ffa4b686ad5d52000d857" - -const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" - -const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" - -const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" - -const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" - -const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v1.4.10 (GNU/Linux) - -lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp -idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn -vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB -AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X -0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL -IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk -VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn -gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 -TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx -q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz -dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA -CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 -ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ -eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid -AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV -bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK -/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA -A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX -TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc -lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 -rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN -oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 -QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU -nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC -AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp -BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad -AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL -VrM0m72/jnpKo04= -=zNCn ------END PGP PRIVATE KEY BLOCK-----` - -const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Charset: UTF-8 - -xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4 -sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk -Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/ -AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD -24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX -+WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8 -B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX -fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA -FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9 -ex7En5r7rHR5xwX82Msc+Rq9dSyO -=7MrZ ------END PGP PUBLIC KEY BLOCK-----` - -const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003` - -const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` - -const rsaSignatureBadMPIlength = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` - -const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` - -const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` - -const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Comment: GPGTools - https://gpgtools.org - -mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY -BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z -tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0 -JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV -/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+ -K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H -JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx -YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1 -b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi -UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M -pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM -AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz -786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd -EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB -=RZia ------END PGP PUBLIC KEY BLOCK----- -` - -const signedMessageV3 = `-----BEGIN PGP MESSAGE----- -Comment: GPGTools - https://gpgtools.org - -owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP -q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka -uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka -DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d -iT57d/OhWwA= -=hG7R ------END PGP MESSAGE----- -` - -// https://mailarchive.ietf.org/arch/msg/openpgp/9SheW_LENE0Kxf7haNllovPyAdY/ -const v5PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd -fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA -Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC -X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI -CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9 -M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA -MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD -AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF -GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb -DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7 -TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw== -=IiS2 ------END PGP PRIVATE KEY BLOCK-----` - -// See OpenPGP crypto refresh Section A.3. -const v6PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -xUsGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laMAGXKB -exK+cH6NX1hs5hNhIB00TrJmosgv3mg1ditlsLfCsQYfGwoAAABCBYJjh3/jAwsJ -BwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6 -2azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lwgyU2kCcUmKfvBXbAf6rh -RYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaEQsiPlR4zxP/TP7mhfVEe -7XWPxtnMUMtf15OyA51YBMdLBmOHf+MZAAAAIIaTJINn+eUBXbki+PSAld2nhJh/ -LVmFsS+60WyvXkQ1AE1gCk95TUR3XFeibg/u/tVY6a//1q0NWC1X+yui3O24wpsG -GBsKAAAALAWCY4d/4wKbDCIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6 -2azJAAAAAAQBIKbpGG2dWTX8j+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDE -M0g12vYxoWM8Y81W+bHBw805I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUr -k0mXubZvyl4GBg== ------END PGP PRIVATE KEY BLOCK-----` - -// See OpenPGP crypto refresh merge request: -// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/304 -const v6PrivKeyMsg = `-----BEGIN PGP MESSAGE----- - -wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO -WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS -aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l -yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo -bhF30A+IitsxxA== ------END PGP MESSAGE-----` - -// See OpenPGP crypto refresh merge request: -// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/305 -const v6PrivKeyInlineSignMsg = `-----BEGIN PGP MESSAGE----- - -wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO -WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS -aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l -yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo -bhF30A+IitsxxA== ------END PGP MESSAGE-----` - -// See https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/274 -// decryption password: "correct horse battery staple" -const v6ArgonSealedPrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -xYIGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laP9JgkC -FARdb9ccngltHraRe25uHuyuAQQVtKipJ0+r5jL4dacGWSAheCWPpITYiyfyIOPS -3gIDyg8f7strd1OB4+LZsUhcIjOMpVHgmiY/IutJkulneoBYwrEGHxsKAAAAQgWC -Y4d/4wMLCQcFFQoOCAwCFgACmwMCHgkiIQbLGGxPBgmml+TVLfpscisMHx4nwYpW -cI9lJewnutmsyQUnCQIHAgAAAACtKCAQPi19In7A5tfORHHbNr/JcIMlNpAnFJin -7wV2wH+q4UWFs7kDsBJ+xP2i8CMEWi7Ha8tPlXGpZR4UruETeh1mhELIj5UeM8T/ -0z+5oX1RHu11j8bZzFDLX9eTsgOdWATHggZjh3/jGQAAACCGkySDZ/nlAV25Ivj0 -gJXdp4SYfy1ZhbEvutFsr15ENf0mCQIUBA5hhGgp2oaavg6mFUXcFMwBBBUuE8qf -9Ock+xwusd+GAglBr5LVyr/lup3xxQvHXFSjjA2haXfoN6xUGRdDEHI6+uevKjVR -v5oAxgu7eJpaXNjCmwYYGwoAAAAsBYJjh3/jApsMIiEGyxhsTwYJppfk1S36bHIr -DB8eJ8GKVnCPZSXsJ7rZrMkAAAAABAEgpukYbZ1ZNfyP5WMUzbUnSGpaUSD5t2Ki -Nacp8DkBClZRa2c3AMQzSDXa9jGhYzxjzVb5scHDzTkjyRZWRdTq8U6L4da+/+Kt -ruh8m7Xo2ehSSFyWRSuTSZe5tm/KXgYG ------END PGP PRIVATE KEY BLOCK-----` - -const v4Key25519 = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -xUkEZB3qzRto01j2k2pwN5ux9w70stPinAdXULLr20CRW7U7h2GSeACch0M+ -qzQg8yjFQ8VBvu3uwgKH9senoHmj72lLSCLTmhFKzQR0ZXN0wogEEBsIAD4F -gmQd6s0ECwkHCAmQIf45+TuC+xMDFQgKBBYAAgECGQECmwMCHgEWIQSWEzMi -jJUHvyIbVKIh/jn5O4L7EwAAUhaHNlgudvxARdPPETUzVgjuWi+YIz8w1xIb -lHQMvIrbe2sGCQIethpWofd0x7DHuv/ciHg+EoxJ/Td6h4pWtIoKx0kEZB3q -zRm4CyA7quliq7yx08AoOqHTuuCgvpkSdEhpp3pEyejQOgBo0p6ywIiLPllY -0t+jpNspHpAGfXID6oqjpYuJw3AfVRBlwnQEGBsIACoFgmQd6s0JkCH+Ofk7 -gvsTApsMFiEElhMzIoyVB78iG1SiIf45+TuC+xMAAGgQuN9G73446ykvJ/mL -sCZ7zGFId2gBd1EnG0FTC4npfOKpck0X8dngByrCxU8LDSfvjsEp/xDAiKsQ -aU71tdtNBQ== -=e7jT ------END PGP PRIVATE KEY BLOCK-----` - -const keyWithExpiredCrossSig = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -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 -hW1Hj9AO8lzggBQ= -=Nt+N ------END PGP PUBLIC KEY BLOCK----- -` - -const sigFromKeyWithExpiredCrossSig = `-----BEGIN PGP SIGNATURE----- - -wsDzBAABCgAGBYJfLAFsACEJEHwvqk35PDeyFiEEHdzhXwkhfO4vOzdgfC+qTfk8 -N7KiqwwAts4QGB7v9bABCC2qkTxJhmStC0wQMcHRcjL/qAiVnmasQWmvE9KVsdm3 -AaXd8mIx4a37/RRvr9dYrY2eE4uw72cMqPxNja2tvVXkHQvk1oEUqfkvbXs4ypKI -NyeTWjXNOTZEbg0hbm3nMy+Wv7zgB1CEvAsEboLDJlhGqPcD+X8a6CJGrBGUBUrv -KVmZr3U6vEzClz3DBLpoddCQseJRhT4YM1nKmBlZ5quh2LFgTSpajv5OsZheqt9y -EZAPbqmLhDmWRQwGzkWHKceKS7nZ/ox2WK6OS7Ob8ZGZkM64iPo6/EGj5Yc19vQN -AGiIaPEGszBBWlOpHTPhNm0LB0nMWqqaT87oNYwP8CQuuxDb6rKJ2lffCmZH27Lb -UbQZcH8J+0UhpeaiadPZxH5ATJAcenmVtVVMLVOFnm+eIlxzov9ntpgGYt8hLdXB -ITEG9mMgp3TGS9ZzSifMZ8UGtHdp9QdBg8NEVPFzDOMGxpc/Bftav7RRRuPiAER+ -7A5CBid5 -=aQkm ------END PGP SIGNATURE----- -` - -const signedMessageWithCriticalNotation = `-----BEGIN PGP MESSAGE----- - -owGbwMvMwMH4oOW7S46CznTG09xJDDE3Wl1KUotLuDousDAwcjBYiSmyXL+48d6x -U1PSGUxcj8IUszKBVMpMaWAAAgEGZpAeh9SKxNyCnFS95PzcytRiBi5OAZjyXXzM -f8WYLqv7TXP61Sa4rqT12CI3xaN73YS2pt089f96odCKaEPnWJ3iSGmzJaW/ug10 -2Zo8Wj2k4s7t8wt4H3HtTu+y5UZfV3VOO+l//sdE/o+Lsub8FZH7/eOq7OnbNp4n -vwjE8mqJXetNMfj8r2SCyvkEnlVRYR+/mnge+ib56FdJ8uKtqSxyvgA= -=fRXs ------END PGP MESSAGE-----` - -const criticalNotationSigner = `-----BEGIN PGP PUBLIC KEY BLOCK----- - -mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+ -fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5 -GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0 -JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS -YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6 -AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki -Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf -9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa -JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag -Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr -woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb -LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA -SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP -GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2 -bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X -W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD -AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY -hz3tYjKhoFTKEIq3y3Pp -=h/aX ------END PGP PUBLIC KEY BLOCK-----` - -const keyv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK----- -Comment: Bob's OpenPGP Transferable Secret Key - -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 -=miES ------END PGP PRIVATE KEY BLOCK----- -` - -const certv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK----- - -lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd -fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA -Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC -X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI -CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9 -M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA -MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD -AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF -GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb -DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7 -TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw== -=IiS2 ------END PGP PRIVATE KEY BLOCK----- -` - -const msgv5Test = `-----BEGIN PGP MESSAGE----- - -wcDMA3wvqk35PDeyAQv+PcQiLsoYTH30nJYQh3j3cJaO2+jErtVCrIQRIU0+ -rmgMddERYST4A9mA0DQIiTI4FQ0Lp440D3BWCgpq3LlNWewGzduaWwym5rN6 -cwHz5ccDqOcqbd9X0GXXGy/ZH/ljSgzuVMIytMAXKdF/vrRrVgH/+I7cxvm9 -HwnhjMN5dF0j4aEt996H2T7cbtzSr2GN9SWGW8Gyu7I8Zx73hgrGUI7gDiJB -Afaff+P6hfkkHSGOItr94dde8J/7AUF4VEwwxdVVPvsNEFyvv6gRIbYtOCa2 -6RE6h1V/QTxW2O7zZgzWALrE2ui0oaYr9QuqQSssd9CdgExLfdPbI+3/ZAnE -v31Idzpk3/6ILiakYHtXkElPXvf46mCNpobty8ysT34irF+fy3C1p3oGwAsx -5VDV9OSFU6z5U+UPbSPYAy9rkc5ZssuIKxCER2oTvZ2L8Q5cfUvEUiJtRGGn -CJlHrVDdp3FssKv2tlKgLkvxJLyoOjuEkj44H1qRk+D02FzmmUT/0sAHAYYx -lTir6mjHeLpcGjn4waUuWIAJyph8SxUexP60bic0L0NBa6Qp5SxxijKsPIDb -FPHxWwfJSDZRrgUyYT7089YFB/ZM4FHyH9TZcnxn0f0xIB7NS6YNDsxzN2zT -EVEYf+De4qT/dQTsdww78Chtcv9JY9r2kDm77dk2MUGHL2j7n8jasbLtgA7h -pn2DMIWLrGamMLWRmlwslolKr1sMV5x8w+5Ias6C33iBMl9phkg42an0gYmc -byVJHvLO/XErtC+GNIJeMg== -=liRq ------END PGP MESSAGE----- -` diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go deleted file mode 100644 index 6871b84f..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2011 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 s2k implements the various OpenPGP string-to-key transforms as -// specified in RFC 4800 section 3.7.1, and Argon2 specified in -// draft-ietf-openpgp-crypto-refresh-08 section 3.7.1.4. -package s2k // import "github.com/ProtonMail/go-crypto/openpgp/s2k" - -import ( - "crypto" - "hash" - "io" - "strconv" - - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" - "golang.org/x/crypto/argon2" -) - -type Mode uint8 - -// Defines the default S2KMode constants -// -// 0 (simple), 1(salted), 3(iterated), 4(argon2) -const ( - SimpleS2K Mode = 0 - SaltedS2K Mode = 1 - IteratedSaltedS2K Mode = 3 - Argon2S2K Mode = 4 - GnuS2K Mode = 101 -) - -const Argon2SaltSize int = 16 - -// Params contains all the parameters of the s2k packet -type Params struct { - // mode is the mode of s2k function. - // It can be 0 (simple), 1(salted), 3(iterated) - // 2(reserved) 100-110(private/experimental). - mode Mode - // hashId is the ID of the hash function used in any of the modes - hashId byte - // salt is a byte array to use as a salt in hashing process or argon2 - saltBytes [Argon2SaltSize]byte - // countByte is used to determine how many rounds of hashing are to - // be performed in s2k mode 3. See RFC 4880 Section 3.7.1.3. - countByte byte - // passes is a parameter in Argon2 to determine the number of iterations - // See RFC the crypto refresh Section 3.7.1.4. - passes byte - // parallelism is a parameter in Argon2 to determine the degree of paralellism - // See RFC the crypto refresh Section 3.7.1.4. - parallelism byte - // memoryExp is a parameter in Argon2 to determine the memory usage - // i.e., 2 ** memoryExp kibibytes - // See RFC the crypto refresh Section 3.7.1.4. - memoryExp byte -} - -// encodeCount converts an iterative "count" in the range 1024 to -// 65011712, inclusive, to an encoded count. The return value is the -// octet that is actually stored in the GPG file. encodeCount panics -// if i is not in the above range (encodedCount above takes care to -// pass i in the correct range). See RFC 4880 Section 3.7.7.1. -func encodeCount(i int) uint8 { - if i < 65536 || i > 65011712 { - panic("count arg i outside the required range") - } - - for encoded := 96; encoded < 256; encoded++ { - count := decodeCount(uint8(encoded)) - if count >= i { - return uint8(encoded) - } - } - - return 255 -} - -// decodeCount returns the s2k mode 3 iterative "count" corresponding to -// the encoded octet c. -func decodeCount(c uint8) int { - return (16 + int(c&15)) << (uint32(c>>4) + 6) -} - -// encodeMemory converts the Argon2 "memory" in the range parallelism*8 to -// 2**31, inclusive, to an encoded memory. The return value is the -// octet that is actually stored in the GPG file. encodeMemory panics -// if is not in the above range -// See OpenPGP crypto refresh Section 3.7.1.4. -func encodeMemory(memory uint32, parallelism uint8) uint8 { - if memory < (8*uint32(parallelism)) || memory > uint32(2147483648) { - panic("Memory argument memory is outside the required range") - } - - for exp := 3; exp < 31; exp++ { - compare := decodeMemory(uint8(exp)) - if compare >= memory { - return uint8(exp) - } - } - - return 31 -} - -// decodeMemory computes the decoded memory in kibibytes as 2**memoryExponent -func decodeMemory(memoryExponent uint8) uint32 { - return uint32(1) << memoryExponent -} - -// Simple writes to out the result of computing the Simple S2K function (RFC -// 4880, section 3.7.1.1) using the given hash and input passphrase. -func Simple(out []byte, h hash.Hash, in []byte) { - Salted(out, h, in, nil) -} - -var zero [1]byte - -// Salted writes to out the result of computing the Salted S2K function (RFC -// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. -func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { - done := 0 - var digest []byte - - for i := 0; done < len(out); i++ { - h.Reset() - for j := 0; j < i; j++ { - h.Write(zero[:]) - } - h.Write(salt) - h.Write(in) - digest = h.Sum(digest[:0]) - n := copy(out[done:], digest) - done += n - } -} - -// Iterated writes to out the result of computing the Iterated and Salted S2K -// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, -// salt and iteration count. -func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { - combined := make([]byte, len(in)+len(salt)) - copy(combined, salt) - copy(combined[len(salt):], in) - - if count < len(combined) { - count = len(combined) - } - - done := 0 - var digest []byte - for i := 0; done < len(out); i++ { - h.Reset() - for j := 0; j < i; j++ { - h.Write(zero[:]) - } - written := 0 - for written < count { - if written+len(combined) > count { - todo := count - written - h.Write(combined[:todo]) - written = count - } else { - h.Write(combined) - written += len(combined) - } - } - digest = h.Sum(digest[:0]) - n := copy(out[done:], digest) - done += n - } -} - -// Argon2 writes to out the key derived from the password (in) with the Argon2 -// function (the crypto refresh, section 3.7.1.4) -func Argon2(out []byte, in []byte, salt []byte, passes uint8, paralellism uint8, memoryExp uint8) { - key := argon2.IDKey(in, salt, uint32(passes), decodeMemory(memoryExp), paralellism, uint32(len(out))) - copy(out[:], key) -} - -// Generate generates valid parameters from given configuration. -// It will enforce the Iterated and Salted or Argon2 S2K method. -func Generate(rand io.Reader, c *Config) (*Params, error) { - var params *Params - if c != nil && c.Mode() == Argon2S2K { - // handle Argon2 case - argonConfig := c.Argon2() - params = &Params{ - mode: Argon2S2K, - passes: argonConfig.Passes(), - parallelism: argonConfig.Parallelism(), - memoryExp: argonConfig.EncodedMemory(), - } - } else if c != nil && c.PassphraseIsHighEntropy && c.Mode() == SaltedS2K { // Allow SaltedS2K if PassphraseIsHighEntropy - hashId, ok := algorithm.HashToHashId(c.hash()) - if !ok { - return nil, errors.UnsupportedError("no such hash") - } - - params = &Params{ - mode: SaltedS2K, - hashId: hashId, - } - } else { // Enforce IteratedSaltedS2K method otherwise - hashId, ok := algorithm.HashToHashId(c.hash()) - if !ok { - return nil, errors.UnsupportedError("no such hash") - } - if c != nil { - c.S2KMode = IteratedSaltedS2K - } - params = &Params{ - mode: IteratedSaltedS2K, - hashId: hashId, - countByte: c.EncodedCount(), - } - } - if _, err := io.ReadFull(rand, params.salt()); err != nil { - return nil, err - } - return params, nil -} - -// Parse reads a binary specification for a string-to-key transformation from r -// and returns a function which performs that transform. If the S2K is a special -// GNU extension that indicates that the private key is missing, then the error -// returned is errors.ErrDummyPrivateKey. -func Parse(r io.Reader) (f func(out, in []byte), err error) { - params, err := ParseIntoParams(r) - if err != nil { - return nil, err - } - - return params.Function() -} - -// ParseIntoParams reads a binary specification for a string-to-key -// transformation from r and returns a struct describing the s2k parameters. -func ParseIntoParams(r io.Reader) (params *Params, err error) { - var buf [Argon2SaltSize + 3]byte - - _, err = io.ReadFull(r, buf[:1]) - if err != nil { - return - } - - params = &Params{ - mode: Mode(buf[0]), - } - - switch params.mode { - case SimpleS2K: - _, err = io.ReadFull(r, buf[:1]) - if err != nil { - return nil, err - } - params.hashId = buf[0] - return params, nil - case SaltedS2K: - _, err = io.ReadFull(r, buf[:9]) - if err != nil { - return nil, err - } - params.hashId = buf[0] - copy(params.salt(), buf[1:9]) - return params, nil - case IteratedSaltedS2K: - _, err = io.ReadFull(r, buf[:10]) - if err != nil { - return nil, err - } - params.hashId = buf[0] - copy(params.salt(), buf[1:9]) - params.countByte = buf[9] - return params, nil - case Argon2S2K: - _, err = io.ReadFull(r, buf[:Argon2SaltSize+3]) - if err != nil { - return nil, err - } - copy(params.salt(), buf[:Argon2SaltSize]) - params.passes = buf[Argon2SaltSize] - params.parallelism = buf[Argon2SaltSize+1] - params.memoryExp = buf[Argon2SaltSize+2] - if err := validateArgon2Params(params); err != nil { - return nil, err - } - return params, nil - case GnuS2K: - // This is a GNU extension. See - // https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109 - if _, err = io.ReadFull(r, buf[:5]); err != nil { - return nil, err - } - params.hashId = buf[0] - if buf[1] == 'G' && buf[2] == 'N' && buf[3] == 'U' && buf[4] == 1 { - return params, nil - } - return nil, errors.UnsupportedError("GNU S2K extension") - } - - return nil, errors.UnsupportedError("S2K function") -} - -func (params *Params) Mode() Mode { - return params.mode -} - -func (params *Params) Dummy() bool { - return params != nil && params.mode == GnuS2K -} - -func (params *Params) salt() []byte { - switch params.mode { - case SaltedS2K, IteratedSaltedS2K: - return params.saltBytes[:8] - case Argon2S2K: - return params.saltBytes[:Argon2SaltSize] - default: - return nil - } -} - -func (params *Params) Function() (f func(out, in []byte), err error) { - if params.Dummy() { - return nil, errors.ErrDummyPrivateKey("dummy key found") - } - var hashObj crypto.Hash - if params.mode != Argon2S2K { - var ok bool - hashObj, ok = algorithm.HashIdToHashWithSha1(params.hashId) - if !ok { - return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(params.hashId))) - } - if !hashObj.Available() { - return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashObj))) - } - } - - switch params.mode { - case SimpleS2K: - f := func(out, in []byte) { - Simple(out, hashObj.New(), in) - } - - return f, nil - case SaltedS2K: - f := func(out, in []byte) { - Salted(out, hashObj.New(), in, params.salt()) - } - - return f, nil - case IteratedSaltedS2K: - f := func(out, in []byte) { - Iterated(out, hashObj.New(), in, params.salt(), decodeCount(params.countByte)) - } - - return f, nil - case Argon2S2K: - f := func(out, in []byte) { - Argon2(out, in, params.salt(), params.passes, params.parallelism, params.memoryExp) - } - return f, nil - } - - return nil, errors.UnsupportedError("S2K function") -} - -func (params *Params) Serialize(w io.Writer) (err error) { - if _, err = w.Write([]byte{uint8(params.mode)}); err != nil { - return - } - if params.mode != Argon2S2K { - if _, err = w.Write([]byte{params.hashId}); err != nil { - return - } - } - if params.Dummy() { - _, err = w.Write(append([]byte("GNU"), 1)) - return - } - if params.mode > 0 { - if _, err = w.Write(params.salt()); err != nil { - return - } - if params.mode == IteratedSaltedS2K { - _, err = w.Write([]byte{params.countByte}) - } - if params.mode == Argon2S2K { - _, err = w.Write([]byte{params.passes, params.parallelism, params.memoryExp}) - } - } - return -} - -// Serialize salts and stretches the given passphrase and writes the -// resulting key into key. It also serializes an S2K descriptor to -// w. The key stretching can be configured with c, which may be -// nil. In that case, sensible defaults will be used. -func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { - params, err := Generate(rand, c) - if err != nil { - return err - } - err = params.Serialize(w) - if err != nil { - return err - } - - f, err := params.Function() - if err != nil { - return err - } - f(key, passphrase) - return nil -} - -// validateArgon2Params checks that the argon2 parameters are valid according to RFC9580. -func validateArgon2Params(params *Params) error { - // The number of passes t and the degree of parallelism p MUST be non-zero. - if params.parallelism == 0 { - return errors.StructuralError("invalid argon2 params: parallelism is 0") - } - if params.passes == 0 { - return errors.StructuralError("invalid argon2 params: iterations is 0") - } - - // The encoded memory size MUST be a value from 3+ceil(log2(p)) to 31, - // such that the decoded memory size m is a value from 8*p to 2^31. - if params.memoryExp > 31 || decodeMemory(params.memoryExp) < 8*uint32(params.parallelism) { - return errors.StructuralError("invalid argon2 params: memory is out of bounds") - } - - return nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go deleted file mode 100644 index 616e0d12..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go +++ /dev/null @@ -1,26 +0,0 @@ -package s2k - -// Cache stores keys derived with s2k functions from one passphrase -// to avoid recomputation if multiple items are encrypted with -// the same parameters. -type Cache map[Params][]byte - -// GetOrComputeDerivedKey tries to retrieve the key -// for the given s2k parameters from the cache. -// If there is no hit, it derives the key with the s2k function from the passphrase, -// updates the cache, and returns the key. -func (c *Cache) GetOrComputeDerivedKey(passphrase []byte, params *Params, expectedKeySize int) ([]byte, error) { - key, found := (*c)[*params] - if !found || len(key) != expectedKeySize { - var err error - derivedKey := make([]byte, expectedKeySize) - s2k, err := params.Function() - if err != nil { - return nil, err - } - s2k(derivedKey, passphrase) - (*c)[*params] = key - return derivedKey, nil - } - return key, nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go deleted file mode 100644 index b93db1ab..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go +++ /dev/null @@ -1,129 +0,0 @@ -package s2k - -import "crypto" - -// Config collects configuration parameters for s2k key-stretching -// transformations. A nil *Config is valid and results in all default -// values. -type Config struct { - // S2K (String to Key) mode, used for key derivation in the context of secret key encryption - // and passphrase-encrypted data. Either s2k.Argon2S2K or s2k.IteratedSaltedS2K may be used. - // If the passphrase is a high-entropy key, indicated by setting PassphraseIsHighEntropy to true, - // s2k.SaltedS2K can also be used. - // Note: Argon2 is the strongest option but not all OpenPGP implementations are compatible with it - //(pending standardisation). - // 0 (simple), 1(salted), 3(iterated), 4(argon2) - // 2(reserved) 100-110(private/experimental). - S2KMode Mode - // Only relevant if S2KMode is not set to s2k.Argon2S2K. - // Hash is the default hash function to be used. If - // nil, SHA256 is used. - Hash crypto.Hash - // Argon2 parameters for S2K (String to Key). - // Only relevant if S2KMode is set to s2k.Argon2S2K. - // If nil, default parameters are used. - // For more details on the choice of parameters, see https://tools.ietf.org/html/rfc9106#section-4. - Argon2Config *Argon2Config - // Only relevant if S2KMode is set to s2k.IteratedSaltedS2K. - // Iteration count for Iterated S2K (String to Key). It - // determines the strength of the passphrase stretching when - // the said passphrase is hashed to produce a key. S2KCount - // should be between 65536 and 65011712, inclusive. If Config - // is nil or S2KCount is 0, the value 16777216 used. Not all - // values in the above range can be represented. S2KCount will - // be rounded up to the next representable value if it cannot - // be encoded exactly. When set, it is strongly encrouraged to - // use a value that is at least 65536. See RFC 4880 Section - // 3.7.1.3. - S2KCount int - // Indicates whether the passphrase passed by the application is a - // high-entropy key (e.g. it's randomly generated or derived from - // another passphrase using a strong key derivation function). - // When true, allows the S2KMode to be s2k.SaltedS2K. - // When the passphrase is not a high-entropy key, using SaltedS2K is - // insecure, and not allowed by draft-ietf-openpgp-crypto-refresh-08. - PassphraseIsHighEntropy bool -} - -// Argon2Config stores the Argon2 parameters -// A nil *Argon2Config is valid and results in all default -type Argon2Config struct { - NumberOfPasses uint8 - DegreeOfParallelism uint8 - // Memory specifies the desired Argon2 memory usage in kibibytes. - // For example memory=64*1024 sets the memory cost to ~64 MB. - Memory uint32 -} - -func (c *Config) Mode() Mode { - if c == nil { - return IteratedSaltedS2K - } - return c.S2KMode -} - -func (c *Config) hash() crypto.Hash { - if c == nil || uint(c.Hash) == 0 { - return crypto.SHA256 - } - - return c.Hash -} - -func (c *Config) Argon2() *Argon2Config { - if c == nil || c.Argon2Config == nil { - return nil - } - return c.Argon2Config -} - -// EncodedCount get encoded count -func (c *Config) EncodedCount() uint8 { - if c == nil || c.S2KCount == 0 { - return 224 // The common case. Corresponding to 16777216 - } - - i := c.S2KCount - - switch { - case i < 65536: - i = 65536 - case i > 65011712: - i = 65011712 - } - - return encodeCount(i) -} - -func (c *Argon2Config) Passes() uint8 { - if c == nil || c.NumberOfPasses == 0 { - return 3 - } - return c.NumberOfPasses -} - -func (c *Argon2Config) Parallelism() uint8 { - if c == nil || c.DegreeOfParallelism == 0 { - return 4 - } - return c.DegreeOfParallelism -} - -func (c *Argon2Config) EncodedMemory() uint8 { - if c == nil || c.Memory == 0 { - return 16 // 64 MiB of RAM - } - - memory := c.Memory - lowerBound := uint32(c.Parallelism()) * 8 - upperBound := uint32(2147483648) - - switch { - case memory < lowerBound: - memory = lowerBound - case memory > upperBound: - memory = upperBound - } - - return encodeMemory(memory, c.Parallelism()) -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go deleted file mode 100644 index 84bc27d8..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/write.go +++ /dev/null @@ -1,690 +0,0 @@ -// Copyright 2011 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 openpgp - -import ( - "crypto" - "hash" - "io" - "strconv" - "time" - - "github.com/ProtonMail/go-crypto/openpgp/armor" - "github.com/ProtonMail/go-crypto/openpgp/errors" - "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" - "github.com/ProtonMail/go-crypto/openpgp/packet" -) - -// DetachSign signs message with the private key from signer (which must -// already have been decrypted) and writes the signature to w. -// If config is nil, sensible defaults will be used. -func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { - return detachSign(w, signer, message, packet.SigTypeBinary, config) -} - -// ArmoredDetachSign signs message with the private key from signer (which -// must already have been decrypted) and writes an armored signature to w. -// If config is nil, sensible defaults will be used. -func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { - return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) -} - -// DetachSignText signs message (after canonicalising the line endings) with -// the private key from signer (which must already have been decrypted) and -// writes the signature to w. -// If config is nil, sensible defaults will be used. -func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { - return detachSign(w, signer, message, packet.SigTypeText, config) -} - -// ArmoredDetachSignText signs message (after canonicalising the line endings) -// with the private key from signer (which must already have been decrypted) -// and writes an armored signature to w. -// If config is nil, sensible defaults will be used. -func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { - return armoredDetachSign(w, signer, message, packet.SigTypeText, config) -} - -func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { - out, err := armor.Encode(w, SignatureType, nil) - if err != nil { - return - } - err = detachSign(out, signer, message, sigType, config) - if err != nil { - return - } - return out.Close() -} - -func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { - signingKey, ok := signer.SigningKeyById(config.Now(), config.SigningKey()) - if !ok { - return errors.InvalidArgumentError("no valid signing keys") - } - if signingKey.PrivateKey == nil { - return errors.InvalidArgumentError("signing key doesn't have a private key") - } - if signingKey.PrivateKey.Encrypted { - return errors.InvalidArgumentError("signing key is encrypted") - } - if _, ok := algorithm.HashToHashId(config.Hash()); !ok { - return errors.InvalidArgumentError("invalid hash function") - } - - sig := createSignaturePacket(signingKey.PublicKey, sigType, config) - - h, err := sig.PrepareSign(config) - if err != nil { - return - } - wrappedHash, err := wrapHashForSignature(h, sig.SigType) - if err != nil { - return - } - if _, err = io.Copy(wrappedHash, message); err != nil { - return err - } - - err = sig.Sign(h, signingKey.PrivateKey, config) - if err != nil { - return - } - - return sig.Serialize(w) -} - -// FileHints contains metadata about encrypted files. This metadata is, itself, -// encrypted. -type FileHints struct { - // IsBinary can be set to hint that the contents are binary data. - IsBinary bool - // FileName hints at the name of the file that should be written. It's - // truncated to 255 bytes if longer. It may be empty to suggest that the - // file should not be written to disk. It may be equal to "_CONSOLE" to - // suggest the data should not be written to disk. - FileName string - // ModTime contains the modification time of the file, or the zero time if not applicable. - ModTime time.Time -} - -// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. -// The resulting WriteCloser must be closed after the contents of the file have -// been written. -// If config is nil, sensible defaults will be used. -func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { - if hints == nil { - hints = &FileHints{} - } - - key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) - if err != nil { - return - } - - var w io.WriteCloser - cipherSuite := packet.CipherSuite{ - Cipher: config.Cipher(), - Mode: config.AEAD().Mode(), - } - w, err = packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), config.AEAD() != nil, cipherSuite, key, config) - if err != nil { - return - } - - literalData := w - if algo := config.Compression(); algo != packet.CompressionNone { - var compConfig *packet.CompressionConfig - if config != nil { - compConfig = config.CompressionConfig - } - literalData, err = packet.SerializeCompressed(w, algo, compConfig) - if err != nil { - return - } - } - - var epochSeconds uint32 - if !hints.ModTime.IsZero() { - epochSeconds = uint32(hints.ModTime.Unix()) - } - return packet.SerializeLiteral(literalData, hints.IsBinary, hints.FileName, epochSeconds) -} - -// intersectPreferences mutates and returns a prefix of a that contains only -// the values in the intersection of a and b. The order of a is preserved. -func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { - var j int - for _, v := range a { - for _, v2 := range b { - if v == v2 { - a[j] = v - j++ - break - } - } - } - - return a[:j] -} - -// intersectPreferences mutates and returns a prefix of a that contains only -// the values in the intersection of a and b. The order of a is preserved. -func intersectCipherSuites(a [][2]uint8, b [][2]uint8) (intersection [][2]uint8) { - var j int - for _, v := range a { - for _, v2 := range b { - if v[0] == v2[0] && v[1] == v2[1] { - a[j] = v - j++ - break - } - } - } - - return a[:j] -} - -func hashToHashId(h crypto.Hash) uint8 { - v, ok := algorithm.HashToHashId(h) - if !ok { - panic("tried to convert unknown hash") - } - return v -} - -// EncryptText encrypts a message to a number of recipients and, optionally, -// signs it. Optional information is contained in 'hints', also encrypted, that -// aids the recipients in processing the message. The resulting WriteCloser -// must be closed after the contents of the file have been written. If config -// is nil, sensible defaults will be used. The signing is done in text mode. -func EncryptText(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { - return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeText, config) -} - -// Encrypt encrypts a message to a number of recipients and, optionally, signs -// it. hints contains optional information, that is also encrypted, that aids -// the recipients in processing the message. The resulting WriteCloser must -// be closed after the contents of the file have been written. -// If config is nil, sensible defaults will be used. -func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { - return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeBinary, config) -} - -// EncryptSplit encrypts a message to a number of recipients and, optionally, signs -// it. hints contains optional information, that is also encrypted, that aids -// the recipients in processing the message. The resulting WriteCloser must -// be closed after the contents of the file have been written. -// If config is nil, sensible defaults will be used. -func EncryptSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { - return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeBinary, config) -} - -// EncryptTextSplit encrypts a message to a number of recipients and, optionally, signs -// it. hints contains optional information, that is also encrypted, that aids -// the recipients in processing the message. The resulting WriteCloser must -// be closed after the contents of the file have been written. -// If config is nil, sensible defaults will be used. -func EncryptTextSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { - return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeText, config) -} - -// writeAndSign writes the data as a payload package and, optionally, signs -// it. hints contains optional information, that is also encrypted, -// that aids the recipients in processing the message. The resulting -// WriteCloser must be closed after the contents of the file have been -// written. If config is nil, sensible defaults will be used. -func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) { - var signer *packet.PrivateKey - if signed != nil { - signKey, ok := signed.SigningKeyById(config.Now(), config.SigningKey()) - if !ok { - return nil, errors.InvalidArgumentError("no valid signing keys") - } - signer = signKey.PrivateKey - if signer == nil { - return nil, errors.InvalidArgumentError("no private key in signing key") - } - if signer.Encrypted { - return nil, errors.InvalidArgumentError("signing key must be decrypted") - } - } - - var hash crypto.Hash - var salt []byte - if signer != nil { - if hash, err = selectHash(candidateHashes, config.Hash(), signer); err != nil { - return nil, err - } - - var opsVersion = 3 - if signer.Version == 6 { - opsVersion = signer.Version - } - ops := &packet.OnePassSignature{ - Version: opsVersion, - SigType: sigType, - Hash: hash, - PubKeyAlgo: signer.PubKeyAlgo, - KeyId: signer.KeyId, - IsLast: true, - } - if opsVersion == 6 { - ops.KeyFingerprint = signer.Fingerprint - salt, err = packet.SignatureSaltForHash(hash, config.Random()) - if err != nil { - return nil, err - } - ops.Salt = salt - } - if err := ops.Serialize(payload); err != nil { - return nil, err - } - } - - if hints == nil { - hints = &FileHints{} - } - - w := payload - if signer != nil { - // If we need to write a signature packet after the literal - // data then we need to stop literalData from closing - // encryptedData. - w = noOpCloser{w} - - } - var epochSeconds uint32 - if !hints.ModTime.IsZero() { - epochSeconds = uint32(hints.ModTime.Unix()) - } - literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) - if err != nil { - return nil, err - } - - if signer != nil { - h, wrappedHash, err := hashForSignature(hash, sigType, salt) - if err != nil { - return nil, err - } - metadata := &packet.LiteralData{ - Format: 'u', - FileName: hints.FileName, - Time: epochSeconds, - } - if hints.IsBinary { - metadata.Format = 'b' - } - return signatureWriter{payload, literalData, hash, wrappedHash, h, salt, signer, sigType, config, metadata}, nil - } - return literalData, nil -} - -// encrypt encrypts a message to a number of recipients and, optionally, signs -// it. hints contains optional information, that is also encrypted, that aids -// the recipients in processing the message. The resulting WriteCloser must -// be closed after the contents of the file have been written. -// If config is nil, sensible defaults will be used. -func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) { - if len(to) == 0 { - return nil, errors.InvalidArgumentError("no encryption recipient provided") - } - - // These are the possible ciphers that we'll use for the message. - candidateCiphers := []uint8{ - uint8(packet.CipherAES256), - uint8(packet.CipherAES128), - } - - // These are the possible hash functions that we'll use for the signature. - candidateHashes := []uint8{ - hashToHashId(crypto.SHA256), - hashToHashId(crypto.SHA384), - hashToHashId(crypto.SHA512), - hashToHashId(crypto.SHA3_256), - hashToHashId(crypto.SHA3_512), - } - - // Prefer GCM if everyone supports it - candidateCipherSuites := [][2]uint8{ - {uint8(packet.CipherAES256), uint8(packet.AEADModeGCM)}, - {uint8(packet.CipherAES256), uint8(packet.AEADModeEAX)}, - {uint8(packet.CipherAES256), uint8(packet.AEADModeOCB)}, - {uint8(packet.CipherAES128), uint8(packet.AEADModeGCM)}, - {uint8(packet.CipherAES128), uint8(packet.AEADModeEAX)}, - {uint8(packet.CipherAES128), uint8(packet.AEADModeOCB)}, - } - - candidateCompression := []uint8{ - uint8(packet.CompressionNone), - uint8(packet.CompressionZIP), - uint8(packet.CompressionZLIB), - } - - encryptKeys := make([]Key, len(to)) - - // AEAD is used only if config enables it and every key supports it - aeadSupported := config.AEAD() != nil - - for i := range to { - var ok bool - encryptKeys[i], ok = to[i].EncryptionKey(config.Now()) - if !ok { - return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no valid encryption keys") - } - - primarySelfSignature, _ := to[i].PrimarySelfSignature() - if primarySelfSignature == nil { - return nil, errors.InvalidArgumentError("entity without a self-signature") - } - - if !primarySelfSignature.SEIPDv2 { - aeadSupported = false - } - - candidateCiphers = intersectPreferences(candidateCiphers, primarySelfSignature.PreferredSymmetric) - candidateHashes = intersectPreferences(candidateHashes, primarySelfSignature.PreferredHash) - candidateCipherSuites = intersectCipherSuites(candidateCipherSuites, primarySelfSignature.PreferredCipherSuites) - candidateCompression = intersectPreferences(candidateCompression, primarySelfSignature.PreferredCompression) - } - - // In the event that the intersection of supported algorithms is empty we use the ones - // labelled as MUST that every implementation supports. - if len(candidateCiphers) == 0 { - // https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.3 - candidateCiphers = []uint8{uint8(packet.CipherAES128)} - } - if len(candidateHashes) == 0 { - // https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#hash-algos - candidateHashes = []uint8{hashToHashId(crypto.SHA256)} - } - if len(candidateCipherSuites) == 0 { - // https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.6 - candidateCipherSuites = [][2]uint8{{uint8(packet.CipherAES128), uint8(packet.AEADModeOCB)}} - } - - cipher := packet.CipherFunction(candidateCiphers[0]) - aeadCipherSuite := packet.CipherSuite{ - Cipher: packet.CipherFunction(candidateCipherSuites[0][0]), - Mode: packet.AEADMode(candidateCipherSuites[0][1]), - } - - // If the cipher specified by config is a candidate, we'll use that. - configuredCipher := config.Cipher() - for _, c := range candidateCiphers { - cipherFunc := packet.CipherFunction(c) - if cipherFunc == configuredCipher { - cipher = cipherFunc - break - } - } - - var symKey []byte - if aeadSupported { - symKey = make([]byte, aeadCipherSuite.Cipher.KeySize()) - } else { - symKey = make([]byte, cipher.KeySize()) - } - - if _, err := io.ReadFull(config.Random(), symKey); err != nil { - return nil, err - } - - for _, key := range encryptKeys { - if err := packet.SerializeEncryptedKeyAEAD(keyWriter, key.PublicKey, cipher, aeadSupported, symKey, config); err != nil { - return nil, err - } - } - - var payload io.WriteCloser - payload, err = packet.SerializeSymmetricallyEncrypted(dataWriter, cipher, aeadSupported, aeadCipherSuite, symKey, config) - if err != nil { - return - } - - payload, err = handleCompression(payload, candidateCompression, config) - if err != nil { - return nil, err - } - - return writeAndSign(payload, candidateHashes, signed, hints, sigType, config) -} - -// Sign signs a message. The resulting WriteCloser must be closed after the -// contents of the file have been written. hints contains optional information -// that aids the recipients in processing the message. -// If config is nil, sensible defaults will be used. -func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) { - if signed == nil { - return nil, errors.InvalidArgumentError("no signer provided") - } - - // These are the possible hash functions that we'll use for the signature. - candidateHashes := []uint8{ - hashToHashId(crypto.SHA256), - hashToHashId(crypto.SHA384), - hashToHashId(crypto.SHA512), - hashToHashId(crypto.SHA3_256), - hashToHashId(crypto.SHA3_512), - } - defaultHashes := candidateHashes[0:1] - primarySelfSignature, _ := signed.PrimarySelfSignature() - if primarySelfSignature == nil { - return nil, errors.StructuralError("signed entity has no self-signature") - } - preferredHashes := primarySelfSignature.PreferredHash - if len(preferredHashes) == 0 { - preferredHashes = defaultHashes - } - candidateHashes = intersectPreferences(candidateHashes, preferredHashes) - if len(candidateHashes) == 0 { - return nil, errors.StructuralError("cannot sign because signing key shares no common algorithms with candidate hashes") - } - - return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, packet.SigTypeBinary, config) -} - -// signatureWriter hashes the contents of a message while passing it along to -// literalData. When closed, it closes literalData, writes a signature packet -// to encryptedData and then also closes encryptedData. -type signatureWriter struct { - encryptedData io.WriteCloser - literalData io.WriteCloser - hashType crypto.Hash - wrappedHash hash.Hash - h hash.Hash - salt []byte // v6 only - signer *packet.PrivateKey - sigType packet.SignatureType - config *packet.Config - metadata *packet.LiteralData // V5 signatures protect document metadata -} - -func (s signatureWriter) Write(data []byte) (int, error) { - s.wrappedHash.Write(data) - switch s.sigType { - case packet.SigTypeBinary: - return s.literalData.Write(data) - case packet.SigTypeText: - flag := 0 - return writeCanonical(s.literalData, data, &flag) - } - return 0, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(s.sigType))) -} - -func (s signatureWriter) Close() error { - sig := createSignaturePacket(&s.signer.PublicKey, s.sigType, s.config) - sig.Hash = s.hashType - sig.Metadata = s.metadata - - if err := sig.SetSalt(s.salt); err != nil { - return err - } - - if err := sig.Sign(s.h, s.signer, s.config); err != nil { - return err - } - if err := s.literalData.Close(); err != nil { - return err - } - if err := sig.Serialize(s.encryptedData); err != nil { - return err - } - return s.encryptedData.Close() -} - -func selectHashForSigningKey(config *packet.Config, signer *packet.PublicKey) crypto.Hash { - acceptableHashes := acceptableHashesToWrite(signer) - hash, ok := algorithm.HashToHashId(config.Hash()) - if !ok { - return config.Hash() - } - for _, acceptableHashes := range acceptableHashes { - if acceptableHashes == hash { - return config.Hash() - } - } - if len(acceptableHashes) > 0 { - defaultAcceptedHash, ok := algorithm.HashIdToHash(acceptableHashes[0]) - if ok { - return defaultAcceptedHash - } - } - return config.Hash() -} - -func createSignaturePacket(signer *packet.PublicKey, sigType packet.SignatureType, config *packet.Config) *packet.Signature { - sigLifetimeSecs := config.SigLifetime() - hash := selectHashForSigningKey(config, signer) - return &packet.Signature{ - Version: signer.Version, - SigType: sigType, - PubKeyAlgo: signer.PubKeyAlgo, - Hash: hash, - CreationTime: config.Now(), - IssuerKeyId: &signer.KeyId, - IssuerFingerprint: signer.Fingerprint, - Notations: config.Notations(), - SigLifetimeSecs: &sigLifetimeSecs, - } -} - -// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. -// TODO: we have two of these in OpenPGP packages alone. This probably needs -// to be promoted somewhere more common. -type noOpCloser struct { - w io.Writer -} - -func (c noOpCloser) Write(data []byte) (n int, err error) { - return c.w.Write(data) -} - -func (c noOpCloser) Close() error { - return nil -} - -func handleCompression(compressed io.WriteCloser, candidateCompression []uint8, config *packet.Config) (data io.WriteCloser, err error) { - data = compressed - confAlgo := config.Compression() - if confAlgo == packet.CompressionNone { - return - } - - // Set algorithm labelled as MUST as fallback - // https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.4 - finalAlgo := packet.CompressionNone - // if compression specified by config available we will use it - for _, c := range candidateCompression { - if uint8(confAlgo) == c { - finalAlgo = confAlgo - break - } - } - - if finalAlgo != packet.CompressionNone { - var compConfig *packet.CompressionConfig - if config != nil { - compConfig = config.CompressionConfig - } - data, err = packet.SerializeCompressed(compressed, finalAlgo, compConfig) - if err != nil { - return - } - } - return data, nil -} - -// selectHash selects the preferred hash given the candidateHashes and the configuredHash -func selectHash(candidateHashes []byte, configuredHash crypto.Hash, signer *packet.PrivateKey) (hash crypto.Hash, err error) { - acceptableHashes := acceptableHashesToWrite(&signer.PublicKey) - candidateHashes = intersectPreferences(acceptableHashes, candidateHashes) - - for _, hashId := range candidateHashes { - if h, ok := algorithm.HashIdToHash(hashId); ok && h.Available() { - hash = h - break - } - } - - // If the hash specified by config is a candidate, we'll use that. - if configuredHash.Available() { - for _, hashId := range candidateHashes { - if h, ok := algorithm.HashIdToHash(hashId); ok && h == configuredHash { - hash = h - break - } - } - } - - if hash == 0 { - if len(acceptableHashes) > 0 { - if h, ok := algorithm.HashIdToHash(acceptableHashes[0]); ok { - hash = h - } else { - return 0, errors.UnsupportedError("no candidate hash functions are compiled in.") - } - } else { - return 0, errors.UnsupportedError("no candidate hash functions are compiled in.") - } - } - return -} - -func acceptableHashesToWrite(singingKey *packet.PublicKey) []uint8 { - switch singingKey.PubKeyAlgo { - case packet.PubKeyAlgoEd448: - return []uint8{ - hashToHashId(crypto.SHA512), - hashToHashId(crypto.SHA3_512), - } - case packet.PubKeyAlgoECDSA, packet.PubKeyAlgoEdDSA: - if curve, err := singingKey.Curve(); err == nil { - if curve == packet.Curve448 || - curve == packet.CurveNistP521 || - curve == packet.CurveBrainpoolP512 { - return []uint8{ - hashToHashId(crypto.SHA512), - hashToHashId(crypto.SHA3_512), - } - } else if curve == packet.CurveBrainpoolP384 || - curve == packet.CurveNistP384 { - return []uint8{ - hashToHashId(crypto.SHA384), - hashToHashId(crypto.SHA512), - hashToHashId(crypto.SHA3_512), - } - } - } - } - return []uint8{ - hashToHashId(crypto.SHA256), - hashToHashId(crypto.SHA384), - hashToHashId(crypto.SHA512), - hashToHashId(crypto.SHA3_256), - hashToHashId(crypto.SHA3_512), - } -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go deleted file mode 100644 index 38afcc74..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go +++ /dev/null @@ -1,221 +0,0 @@ -package x25519 - -import ( - "crypto/sha256" - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap" - "github.com/ProtonMail/go-crypto/openpgp/errors" - x25519lib "github.com/cloudflare/circl/dh/x25519" - "golang.org/x/crypto/hkdf" -) - -const ( - hkdfInfo = "OpenPGP X25519" - aes128KeySize = 16 - // The size of a public or private key in bytes. - KeySize = x25519lib.Size -) - -type PublicKey struct { - // Point represents the encoded elliptic curve point of the public key. - Point []byte -} - -type PrivateKey struct { - PublicKey - // Secret represents the secret of the private key. - Secret []byte -} - -// NewPrivateKey creates a new empty private key including the public key. -func NewPrivateKey(key PublicKey) *PrivateKey { - return &PrivateKey{ - PublicKey: key, - } -} - -// Validate validates that the provided public key matches the private key. -func Validate(pk *PrivateKey) (err error) { - var expectedPublicKey, privateKey x25519lib.Key - subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret) - x25519lib.KeyGen(&expectedPublicKey, &privateKey) - if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 { - return errors.KeyInvalidError("x25519: invalid key") - } - return nil -} - -// GenerateKey generates a new x25519 key pair. -func GenerateKey(rand io.Reader) (*PrivateKey, error) { - var privateKey, publicKey x25519lib.Key - privateKeyOut := new(PrivateKey) - err := generateKey(rand, &privateKey, &publicKey) - if err != nil { - return nil, err - } - privateKeyOut.PublicKey.Point = publicKey[:] - privateKeyOut.Secret = privateKey[:] - return privateKeyOut, nil -} - -func generateKey(rand io.Reader, privateKey *x25519lib.Key, publicKey *x25519lib.Key) error { - maxRounds := 10 - isZero := true - for round := 0; isZero; round++ { - if round == maxRounds { - return errors.InvalidArgumentError("x25519: zero keys only, randomness source might be corrupt") - } - _, err := io.ReadFull(rand, privateKey[:]) - if err != nil { - return err - } - isZero = constantTimeIsZero(privateKey[:]) - } - x25519lib.KeyGen(publicKey, privateKey) - return nil -} - -// Encrypt encrypts a sessionKey with x25519 according to -// the OpenPGP crypto refresh specification section 5.1.6. The function assumes that the -// sessionKey has the correct format and padding according to the specification. -func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) { - var ephemeralPrivate, ephemeralPublic, staticPublic, shared x25519lib.Key - // Check that the input static public key has 32 bytes - if len(publicKey.Point) != KeySize { - err = errors.KeyInvalidError("x25519: the public key has the wrong size") - return - } - copy(staticPublic[:], publicKey.Point) - // Generate ephemeral keyPair - err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic) - if err != nil { - return - } - // Compute shared key - ok := x25519lib.Shared(&shared, &ephemeralPrivate, &staticPublic) - if !ok { - err = errors.KeyInvalidError("x25519: the public key is a low order point") - return - } - // Derive the encryption key from the shared secret - encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:]) - ephemeralPublicKey = &PublicKey{ - Point: ephemeralPublic[:], - } - // Encrypt the sessionKey with aes key wrapping - encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey) - return -} - -// Decrypt decrypts a session key stored in ciphertext with the provided x25519 -// private key and ephemeral public key. -func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) { - var ephemeralPublic, staticPrivate, shared x25519lib.Key - // Check that the input ephemeral public key has 32 bytes - if len(ephemeralPublicKey.Point) != KeySize { - err = errors.KeyInvalidError("x25519: the public key has the wrong size") - return - } - copy(ephemeralPublic[:], ephemeralPublicKey.Point) - subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret) - // Compute shared key - ok := x25519lib.Shared(&shared, &staticPrivate, &ephemeralPublic) - if !ok { - err = errors.KeyInvalidError("x25519: the ephemeral public key is a low order point") - return - } - // Derive the encryption key from the shared secret - encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:]) - // Decrypt the session key with aes key wrapping - encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext) - return -} - -func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte { - inputKey := make([]byte, 3*KeySize) - // ephemeral public key | recipient public key | shared secret - subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey) - subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey) - subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret) - hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, []byte(hkdfInfo)) - encryptionKey := make([]byte, aes128KeySize) - _, _ = io.ReadFull(hkdfReader, encryptionKey) - return encryptionKey -} - -func constantTimeIsZero(bytes []byte) bool { - isZero := byte(0) - for _, b := range bytes { - isZero |= b - } - return isZero == 0 -} - -// ENCODING/DECODING ciphertexts: - -// EncodeFieldsLength returns the length of the ciphertext encoding -// given the encrypted session key. -func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int { - lenCipherFunction := 0 - if !v6 { - lenCipherFunction = 1 - } - return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction -} - -// EncodeField encodes x25519 session key encryption fields as -// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey -// and writes it to writer. -func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) { - lenAlgorithm := 0 - if !v6 { - lenAlgorithm = 1 - } - if _, err = writer.Write(ephemeralPublicKey.Point); err != nil { - return err - } - if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil { - return err - } - if !v6 { - if _, err = writer.Write([]byte{cipherFunction}); err != nil { - return err - } - } - _, err = writer.Write(encryptedSessionKey) - return err -} - -// DecodeField decodes a x25519 session key encryption as -// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey. -func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) { - var buf [1]byte - ephemeralPublicKey = &PublicKey{ - Point: make([]byte, KeySize), - } - // 32 octets representing an ephemeral x25519 public key. - if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil { - return nil, nil, 0, err - } - // A one-octet size of the following fields. - if _, err = io.ReadFull(reader, buf[:]); err != nil { - return nil, nil, 0, err - } - followingLen := buf[0] - // The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet). - if !v6 { - if _, err = io.ReadFull(reader, buf[:]); err != nil { - return nil, nil, 0, err - } - cipherFunction = buf[0] - followingLen -= 1 - } - // The encrypted session key. - encryptedSessionKey = make([]byte, followingLen) - if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil { - return nil, nil, 0, err - } - return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil -} diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go deleted file mode 100644 index 65a082da..00000000 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go +++ /dev/null @@ -1,229 +0,0 @@ -package x448 - -import ( - "crypto/sha512" - "crypto/subtle" - "io" - - "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap" - "github.com/ProtonMail/go-crypto/openpgp/errors" - x448lib "github.com/cloudflare/circl/dh/x448" - "golang.org/x/crypto/hkdf" -) - -const ( - hkdfInfo = "OpenPGP X448" - aes256KeySize = 32 - // The size of a public or private key in bytes. - KeySize = x448lib.Size -) - -type PublicKey struct { - // Point represents the encoded elliptic curve point of the public key. - Point []byte -} - -type PrivateKey struct { - PublicKey - // Secret represents the secret of the private key. - Secret []byte -} - -// NewPrivateKey creates a new empty private key including the public key. -func NewPrivateKey(key PublicKey) *PrivateKey { - return &PrivateKey{ - PublicKey: key, - } -} - -// Validate validates that the provided public key matches -// the private key. -func Validate(pk *PrivateKey) (err error) { - var expectedPublicKey, privateKey x448lib.Key - subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret) - x448lib.KeyGen(&expectedPublicKey, &privateKey) - if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 { - return errors.KeyInvalidError("x448: invalid key") - } - return nil -} - -// GenerateKey generates a new x448 key pair. -func GenerateKey(rand io.Reader) (*PrivateKey, error) { - var privateKey, publicKey x448lib.Key - privateKeyOut := new(PrivateKey) - err := generateKey(rand, &privateKey, &publicKey) - if err != nil { - return nil, err - } - privateKeyOut.PublicKey.Point = publicKey[:] - privateKeyOut.Secret = privateKey[:] - return privateKeyOut, nil -} - -func generateKey(rand io.Reader, privateKey *x448lib.Key, publicKey *x448lib.Key) error { - maxRounds := 10 - isZero := true - for round := 0; isZero; round++ { - if round == maxRounds { - return errors.InvalidArgumentError("x448: zero keys only, randomness source might be corrupt") - } - _, err := io.ReadFull(rand, privateKey[:]) - if err != nil { - return err - } - isZero = constantTimeIsZero(privateKey[:]) - } - x448lib.KeyGen(publicKey, privateKey) - return nil -} - -// Encrypt encrypts a sessionKey with x448 according to -// the OpenPGP crypto refresh specification section 5.1.7. The function assumes that the -// sessionKey has the correct format and padding according to the specification. -func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) { - var ephemeralPrivate, ephemeralPublic, staticPublic, shared x448lib.Key - // Check that the input static public key has 56 bytes. - if len(publicKey.Point) != KeySize { - err = errors.KeyInvalidError("x448: the public key has the wrong size") - return nil, nil, err - } - copy(staticPublic[:], publicKey.Point) - // Generate ephemeral keyPair. - if err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic); err != nil { - return nil, nil, err - } - // Compute shared key. - ok := x448lib.Shared(&shared, &ephemeralPrivate, &staticPublic) - if !ok { - err = errors.KeyInvalidError("x448: the public key is a low order point") - return nil, nil, err - } - // Derive the encryption key from the shared secret. - encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:]) - ephemeralPublicKey = &PublicKey{ - Point: ephemeralPublic[:], - } - // Encrypt the sessionKey with aes key wrapping. - encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey) - if err != nil { - return nil, nil, err - } - return ephemeralPublicKey, encryptedSessionKey, nil -} - -// Decrypt decrypts a session key stored in ciphertext with the provided x448 -// private key and ephemeral public key. -func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) { - var ephemeralPublic, staticPrivate, shared x448lib.Key - // Check that the input ephemeral public key has 56 bytes. - if len(ephemeralPublicKey.Point) != KeySize { - err = errors.KeyInvalidError("x448: the public key has the wrong size") - return nil, err - } - copy(ephemeralPublic[:], ephemeralPublicKey.Point) - subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret) - // Compute shared key. - ok := x448lib.Shared(&shared, &staticPrivate, &ephemeralPublic) - if !ok { - err = errors.KeyInvalidError("x448: the ephemeral public key is a low order point") - return nil, err - } - // Derive the encryption key from the shared secret. - encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:]) - // Decrypt the session key with aes key wrapping. - encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext) - if err != nil { - return nil, err - } - return encodedSessionKey, nil -} - -func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte { - inputKey := make([]byte, 3*KeySize) - // ephemeral public key | recipient public key | shared secret. - subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey) - subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey) - subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret) - hkdfReader := hkdf.New(sha512.New, inputKey, []byte{}, []byte(hkdfInfo)) - encryptionKey := make([]byte, aes256KeySize) - _, _ = io.ReadFull(hkdfReader, encryptionKey) - return encryptionKey -} - -func constantTimeIsZero(bytes []byte) bool { - isZero := byte(0) - for _, b := range bytes { - isZero |= b - } - return isZero == 0 -} - -// ENCODING/DECODING ciphertexts: - -// EncodeFieldsLength returns the length of the ciphertext encoding -// given the encrypted session key. -func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int { - lenCipherFunction := 0 - if !v6 { - lenCipherFunction = 1 - } - return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction -} - -// EncodeField encodes x448 session key encryption fields as -// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey -// and writes it to writer. -func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) { - lenAlgorithm := 0 - if !v6 { - lenAlgorithm = 1 - } - if _, err = writer.Write(ephemeralPublicKey.Point); err != nil { - return err - } - if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil { - return err - } - if !v6 { - if _, err = writer.Write([]byte{cipherFunction}); err != nil { - return err - } - } - if _, err = writer.Write(encryptedSessionKey); err != nil { - return err - } - return nil -} - -// DecodeField decodes a x448 session key encryption as -// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey. -func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) { - var buf [1]byte - ephemeralPublicKey = &PublicKey{ - Point: make([]byte, KeySize), - } - // 56 octets representing an ephemeral x448 public key. - if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil { - return nil, nil, 0, err - } - // A one-octet size of the following fields. - if _, err = io.ReadFull(reader, buf[:]); err != nil { - return nil, nil, 0, err - } - followingLen := buf[0] - // The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet). - if !v6 { - if _, err = io.ReadFull(reader, buf[:]); err != nil { - return nil, nil, 0, err - } - cipherFunction = buf[0] - followingLen -= 1 - } - // The encrypted session key. - encryptedSessionKey = make([]byte, followingLen) - if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil { - return nil, nil, 0, err - } - return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil -} diff --git a/vendor/github.com/alecthomas/chroma/v2/.editorconfig b/vendor/github.com/alecthomas/chroma/v2/.editorconfig deleted file mode 100644 index cfb2c669..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -root = true - -[*] -indent_style = tab -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.xml] -indent_style = space -indent_size = 2 -insert_final_newline = false - -[*.yml] -indent_style = space -indent_size = 2 diff --git a/vendor/github.com/alecthomas/chroma/v2/.gitignore b/vendor/github.com/alecthomas/chroma/v2/.gitignore deleted file mode 100644 index 8cbdd75e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Binaries for programs and plugins -.git -.idea -.vscode -.hermit -*.exe -*.dll -*.so -*.dylib -/cmd/chroma/chroma - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 -.glide/ - -_models/ - -_examples/ -*.min.* -build/ diff --git a/vendor/github.com/alecthomas/chroma/v2/.golangci.yml b/vendor/github.com/alecthomas/chroma/v2/.golangci.yml deleted file mode 100644 index 668be374..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/.golangci.yml +++ /dev/null @@ -1,92 +0,0 @@ -run: - tests: true - skip-dirs: - - _examples - -output: - print-issued-lines: false - -linters: - enable-all: true - disable: - - maligned - - megacheck - - lll - - gocyclo - - dupl - - gochecknoglobals - - funlen - - godox - - wsl - - gomnd - - gocognit - - goerr113 - - nolintlint - - testpackage - - godot - - nestif - - paralleltest - - nlreturn - - cyclop - - exhaustivestruct - - gci - - gofumpt - - errorlint - - exhaustive - - ifshort - - wrapcheck - - stylecheck - - thelper - - nonamedreturns - - revive - - dupword - - exhaustruct - - varnamelen - - forcetypeassert - - ireturn - - maintidx - - govet - - nosnakecase - - testableexamples - - musttag - - depguard - - goconst - -linters-settings: - govet: - check-shadowing: true - gocyclo: - min-complexity: 10 - dupl: - threshold: 100 - goconst: - min-len: 8 - min-occurrences: 3 - forbidigo: - #forbid: - # - (Must)?NewLexer$ - exclude_godoc_examples: false - - -issues: - max-per-linter: 0 - max-same: 0 - exclude-use-default: false - exclude: - # Captured by errcheck. - - '^(G104|G204):' - # Very commonly not checked. - - 'Error return value of .(.*\.Help|.*\.MarkFlagRequired|(os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked' - - 'exported method (.*\.MarshalJSON|.*\.UnmarshalJSON|.*\.EntityURN|.*\.GoString|.*\.Pos) should have comment or be unexported' - - 'composite literal uses unkeyed fields' - - 'declaration of "err" shadows declaration' - - 'should not use dot imports' - - 'Potential file inclusion via variable' - - 'should have comment or be unexported' - - 'comment on exported var .* should be of the form' - - 'at least one file in a package should have a package comment' - - 'string literal contains the Unicode' - - 'methods on the same type should have the same receiver name' - - '_TokenType_name should be _TokenTypeName' - - '`_TokenType_map` should be `_TokenTypeMap`' - - 'rewrite if-else to switch statement' diff --git a/vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml b/vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml deleted file mode 100644 index 8cd7592d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/.goreleaser.yml +++ /dev/null @@ -1,37 +0,0 @@ -project_name: chroma -release: - github: - owner: alecthomas - name: chroma -brews: - - - install: bin.install "chroma" -env: - - CGO_ENABLED=0 -builds: -- goos: - - linux - - darwin - - windows - goarch: - - arm64 - - amd64 - - "386" - goarm: - - "6" - dir: ./cmd/chroma - main: . - ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} - binary: chroma -archives: - - - format: tar.gz - name_template: '{{ .Binary }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ - .Arm }}{{ end }}' - files: - - COPYING - - README* -snapshot: - name_template: SNAPSHOT-{{ .Commit }} -checksum: - name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt' diff --git a/vendor/github.com/alecthomas/chroma/v2/Bitfile b/vendor/github.com/alecthomas/chroma/v2/Bitfile deleted file mode 100644 index bf158633..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/Bitfile +++ /dev/null @@ -1,24 +0,0 @@ -VERSION = %(git describe --tags --dirty --always)% -export CGOENABLED = 0 - -tokentype_enumer.go: types.go - build: go generate - -# Regenerate the list of lexers in the README -README.md: lexers/*.go lexers/*/*.xml table.py - build: ./table.py - -clean - -implicit %{1}%{2}.min.%{3}: **/*.{css,js} - build: esbuild --bundle %{IN} --minify --outfile=%{OUT} - -implicit build/%{1}: cmd/* - cd cmd/%{1} - inputs: cmd/%{1}/**/* **/*.go - build: go build -ldflags="-X 'main.version=%{VERSION}'" -o ../../build/%{1} . - -#upload: chromad -# build: -# scp chromad root@swapoff.org: -# ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart' -# touch upload diff --git a/vendor/github.com/alecthomas/chroma/v2/COPYING b/vendor/github.com/alecthomas/chroma/v2/COPYING deleted file mode 100644 index 92dc39f7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2017 Alec Thomas - -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/alecthomas/chroma/v2/Makefile b/vendor/github.com/alecthomas/chroma/v2/Makefile deleted file mode 100644 index e2ff762e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -.PHONY: chromad upload all - -VERSION ?= $(shell git describe --tags --dirty --always) -export GOOS ?= linux -export GOARCH ?= amd64 - -all: README.md tokentype_string.go - -README.md: lexers/*/*.go - ./table.py - -tokentype_string.go: types.go - go generate - -chromad: - rm -rf build - esbuild --bundle cmd/chromad/static/index.js --minify --outfile=cmd/chromad/static/index.min.js - esbuild --bundle cmd/chromad/static/index.css --minify --outfile=cmd/chromad/static/index.min.css - (export CGOENABLED=0 ; cd ./cmd/chromad && go build -ldflags="-X 'main.version=$(VERSION)'" -o ../../build/chromad .) - -upload: build/chromad - scp build/chromad root@swapoff.org: && \ - ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart' diff --git a/vendor/github.com/alecthomas/chroma/v2/README.md b/vendor/github.com/alecthomas/chroma/v2/README.md deleted file mode 100644 index 775d3af2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/README.md +++ /dev/null @@ -1,297 +0,0 @@ -# Chroma — A general purpose syntax highlighter in pure Go - -[![Golang Documentation](https://godoc.org/github.com/alecthomas/chroma?status.svg)](https://godoc.org/github.com/alecthomas/chroma) [![CI](https://github.com/alecthomas/chroma/actions/workflows/ci.yml/badge.svg)](https://github.com/alecthomas/chroma/actions/workflows/ci.yml) [![Slack chat](https://img.shields.io/static/v1?logo=slack&style=flat&label=slack&color=green&message=gophers)](https://invite.slack.golangbridge.org/) - -Chroma takes source code and other structured text and converts it into syntax -highlighted HTML, ANSI-coloured text, etc. - -Chroma is based heavily on [Pygments](http://pygments.org/), and includes -translators for Pygments lexers and styles. - -## Table of Contents - - - -1. [Supported languages](#supported-languages) -2. [Try it](#try-it) -3. [Using the library](#using-the-library) - 1. [Quick start](#quick-start) - 2. [Identifying the language](#identifying-the-language) - 3. [Formatting the output](#formatting-the-output) - 4. [The HTML formatter](#the-html-formatter) -4. [More detail](#more-detail) - 1. [Lexers](#lexers) - 2. [Formatters](#formatters) - 3. [Styles](#styles) -5. [Command-line interface](#command-line-interface) -6. [Testing lexers](#testing-lexers) -7. [What's missing compared to Pygments?](#whats-missing-compared-to-pygments) - - - -## Supported languages - -| Prefix | Language | -| :----: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Agda, AL, Alloy, Angular2, ANTLR, ApacheConf, APL, AppleScript, ArangoDB AQL, Arduino, ArmAsm, AutoHotkey, AutoIt, Awk | -| B | Ballerina, Bash, Bash Session, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, BQN, Brainfuck | -| C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython | -| D | D, Dart, Dax, Desktop Entry, Diff, Django/Jinja, dns, Docker, DTD, Dylan | -| E | EBNF, Elixir, Elm, EmacsLisp, Erlang | -| F | Factor, Fennel, Fish, Forth, Fortran, FortranFixed, FSharp | -| G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, Gherkin, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groff, Groovy | -| H | Handlebars, Hare, Haskell, Haxe, HCL, Hexdump, HLB, HLSL, HolyC, HTML, HTTP, Hy | -| I | Idris, Igor, INI, Io, ISCdhcpd | -| J | J, Java, JavaScript, JSON, Julia, Jungle | -| K | Kotlin | -| L | Lighttpd configuration file, LLVM, Lua | -| M | Makefile, Mako, markdown, Mason, Materialize SQL dialect, Mathematica, Matlab, mcfunction, Meson, Metal, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL | -| N | NASM, Natural, Newspeak, Nginx configuration file, Nim, Nix | -| O | Objective-C, OCaml, Octave, Odin, OnesEnterprise, OpenEdge ABL, OpenSCAD, Org Mode | -| P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Plutus Core, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerQuery, PowerShell, Prolog, PromQL, Promela, properties, Protocol Buffer, PRQL, PSL, Puppet, Python, Python 2 | -| Q | QBasic, QML | -| R | R, Racket, Ragel, Raku, react, ReasonML, reg, Rego, reStructuredText, Rexx, RPMSpec, Ruby, Rust | -| S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Sed, Sieve, Smali, Smalltalk, Smarty, Snobol, Solidity, SourcePawn, SPARQL, SQL, SquidConf, Standard ML, stas, Stylus, Svelte, Swift, SYSTEMD, systemverilog | -| T | TableGen, Tal, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData | -| V | V, V shell, Vala, VB.net, verilog, VHDL, VHS, VimL, vue | -| W | WDTE, WebGPU Shading Language, Whiley | -| X | XML, Xorg | -| Y | YAML, YANG | -| Z | Z80 Assembly, Zed, Zig | - -_I will attempt to keep this section up to date, but an authoritative list can be -displayed with `chroma --list`._ - -## Try it - -Try out various languages and styles on the [Chroma Playground](https://swapoff.org/chroma/playground/). - -## Using the library - -This is version 2 of Chroma, use the import path: - -```go -import "github.com/alecthomas/chroma/v2" -``` - -Chroma, like Pygments, has the concepts of -[lexers](https://github.com/alecthomas/chroma/tree/master/lexers), -[formatters](https://github.com/alecthomas/chroma/tree/master/formatters) and -[styles](https://github.com/alecthomas/chroma/tree/master/styles). - -Lexers convert source text into a stream of tokens, styles specify how token -types are mapped to colours, and formatters convert tokens and styles into -formatted output. - -A package exists for each of these, containing a global `Registry` variable -with all of the registered implementations. There are also helper functions -for using the registry in each package, such as looking up lexers by name or -matching filenames, etc. - -In all cases, if a lexer, formatter or style can not be determined, `nil` will -be returned. In this situation you may want to default to the `Fallback` -value in each respective package, which provides sane defaults. - -### Quick start - -A convenience function exists that can be used to simply format some source -text, without any effort: - -```go -err := quick.Highlight(os.Stdout, someSourceCode, "go", "html", "monokai") -``` - -### Identifying the language - -To highlight code, you'll first have to identify what language the code is -written in. There are three primary ways to do that: - -1. Detect the language from its filename. - - ```go - lexer := lexers.Match("foo.go") - ``` - -2. Explicitly specify the language by its Chroma syntax ID (a full list is available from `lexers.Names()`). - - ```go - lexer := lexers.Get("go") - ``` - -3. Detect the language from its content. - - ```go - lexer := lexers.Analyse("package main\n\nfunc main()\n{\n}\n") - ``` - -In all cases, `nil` will be returned if the language can not be identified. - -```go -if lexer == nil { - lexer = lexers.Fallback -} -``` - -At this point, it should be noted that some lexers can be extremely chatty. To -mitigate this, you can use the coalescing lexer to coalesce runs of identical -token types into a single token: - -```go -lexer = chroma.Coalesce(lexer) -``` - -### Formatting the output - -Once a language is identified you will need to pick a formatter and a style (theme). - -```go -style := styles.Get("swapoff") -if style == nil { - style = styles.Fallback -} -formatter := formatters.Get("html") -if formatter == nil { - formatter = formatters.Fallback -} -``` - -Then obtain an iterator over the tokens: - -```go -contents, err := ioutil.ReadAll(r) -iterator, err := lexer.Tokenise(nil, string(contents)) -``` - -And finally, format the tokens from the iterator: - -```go -err := formatter.Format(w, style, iterator) -``` - -### The HTML formatter - -By default the `html` registered formatter generates standalone HTML with -embedded CSS. More flexibility is available through the `formatters/html` package. - -Firstly, the output generated by the formatter can be customised with the -following constructor options: - -- `Standalone()` - generate standalone HTML with embedded CSS. -- `WithClasses()` - use classes rather than inlined style attributes. -- `ClassPrefix(prefix)` - prefix each generated CSS class. -- `TabWidth(width)` - Set the rendered tab width, in characters. -- `WithLineNumbers()` - Render line numbers (style with `LineNumbers`). -- `WithLinkableLineNumbers()` - Make the line numbers linkable and be a link to themselves. -- `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`). -- `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans. - -If `WithClasses()` is used, the corresponding CSS can be obtained from the formatter with: - -```go -formatter := html.New(html.WithClasses(true)) -err := formatter.WriteCSS(w, style) -``` - -## More detail - -### Lexers - -See the [Pygments documentation](http://pygments.org/docs/lexerdevelopment/) -for details on implementing lexers. Most concepts apply directly to Chroma, -but see existing lexer implementations for real examples. - -In many cases lexers can be automatically converted directly from Pygments by -using the included Python 3 script `pygments2chroma_xml.py`. I use something like -the following: - -```sh -python3 _tools/pygments2chroma_xml.py \ - pygments.lexers.jvm.KotlinLexer \ - > lexers/embedded/kotlin.xml -``` - -See notes in [pygments-lexers.txt](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt) -for a list of lexers, and notes on some of the issues importing them. - -### Formatters - -Chroma supports HTML output, as well as terminal output in 8 colour, 256 colour, and true-colour. - -A `noop` formatter is included that outputs the token text only, and a `tokens` -formatter outputs raw tokens. The latter is useful for debugging lexers. - -### Styles - -Chroma styles are defined in XML. The style entries use the -[same syntax](http://pygments.org/docs/styles/) as Pygments. - -All Pygments styles have been converted to Chroma using the `_tools/style.py` -script. - -When you work with one of [Chroma's styles](https://github.com/alecthomas/chroma/tree/master/styles), -know that the `Background` token type provides the default style for tokens. It does so -by defining a foreground color and background color. - -For example, this gives each token name not defined in the style a default color -of `#f8f8f8` and uses `#000000` for the highlighted code block's background: - -```xml - -``` - -Also, token types in a style file are hierarchical. For instance, when `CommentSpecial` is not defined, Chroma uses the token style from `Comment`. So when several comment tokens use the same color, you'll only need to define `Comment` and override the one that has a different color. - -For a quick overview of the available styles and how they look, check out the [Chroma Style Gallery](https://xyproto.github.io/splash/docs/). - -## Command-line interface - -A command-line interface to Chroma is included. - -Binaries are available to install from [the releases page](https://github.com/alecthomas/chroma/releases). - -The CLI can be used as a preprocessor to colorise output of `less(1)`, -see documentation for the `LESSOPEN` environment variable. - -The `--fail` flag can be used to suppress output and return with exit status -1 to facilitate falling back to some other preprocessor in case chroma -does not resolve a specific lexer to use for the given file. For example: - -```shell -export LESSOPEN='| p() { chroma --fail "$1" || cat "$1"; }; p "%s"' -``` - -Replace `cat` with your favourite fallback preprocessor. - -When invoked as `.lessfilter`, the `--fail` flag is automatically turned -on under the hood for easy integration with [lesspipe shipping with -Debian and derivatives](https://manpages.debian.org/lesspipe#USER_DEFINED_FILTERS); -for that setup the `chroma` executable can be just symlinked to `~/.lessfilter`. - -## Testing lexers - -If you edit some lexers and want to try it, open a shell in `cmd/chromad` and run: - -```shell -go run . -``` - -A Link will be printed. Open it in your Browser. Now you can test on the Playground with your local changes. - -If you want to run the tests and the lexers, open a shell in the root directory and run: - -```shell -go test ./lexers -``` - -When updating or adding a lexer, please add tests. See [lexers/README.md](lexers/README.md) for more. - -## What's missing compared to Pygments? - -- Quite a few lexers, for various reasons (pull-requests welcome): - - Pygments lexers for complex languages often include custom code to - handle certain aspects, such as Raku's ability to nest code inside - regular expressions. These require time and effort to convert. - - I mostly only converted languages I had heard of, to reduce the porting cost. -- Some more esoteric features of Pygments are omitted for simplicity. -- Though the Chroma API supports content detection, very few languages support them. - I have plans to implement a statistical analyser at some point, but not enough time. diff --git a/vendor/github.com/alecthomas/chroma/v2/coalesce.go b/vendor/github.com/alecthomas/chroma/v2/coalesce.go deleted file mode 100644 index f5048951..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/coalesce.go +++ /dev/null @@ -1,35 +0,0 @@ -package chroma - -// Coalesce is a Lexer interceptor that collapses runs of common types into a single token. -func Coalesce(lexer Lexer) Lexer { return &coalescer{lexer} } - -type coalescer struct{ Lexer } - -func (d *coalescer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { - var prev Token - it, err := d.Lexer.Tokenise(options, text) - if err != nil { - return nil, err - } - return func() Token { - for token := it(); token != (EOF); token = it() { - if len(token.Value) == 0 { - continue - } - if prev == EOF { - prev = token - } else { - if prev.Type == token.Type && len(prev.Value) < 8192 { - prev.Value += token.Value - } else { - out := prev - prev = token - return out - } - } - } - out := prev - prev = EOF - return out - }, nil -} diff --git a/vendor/github.com/alecthomas/chroma/v2/colour.go b/vendor/github.com/alecthomas/chroma/v2/colour.go deleted file mode 100644 index b7fd6e0e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/colour.go +++ /dev/null @@ -1,192 +0,0 @@ -package chroma - -import ( - "fmt" - "math" - "strconv" - "strings" -) - -// ANSI2RGB maps ANSI colour names, as supported by Chroma, to hex RGB values. -var ANSI2RGB = map[string]string{ - "#ansiblack": "000000", - "#ansidarkred": "7f0000", - "#ansidarkgreen": "007f00", - "#ansibrown": "7f7fe0", - "#ansidarkblue": "00007f", - "#ansipurple": "7f007f", - "#ansiteal": "007f7f", - "#ansilightgray": "e5e5e5", - // Normal - "#ansidarkgray": "555555", - "#ansired": "ff0000", - "#ansigreen": "00ff00", - "#ansiyellow": "ffff00", - "#ansiblue": "0000ff", - "#ansifuchsia": "ff00ff", - "#ansiturquoise": "00ffff", - "#ansiwhite": "ffffff", - - // Aliases without the "ansi" prefix, because...why? - "#black": "000000", - "#darkred": "7f0000", - "#darkgreen": "007f00", - "#brown": "7f7fe0", - "#darkblue": "00007f", - "#purple": "7f007f", - "#teal": "007f7f", - "#lightgray": "e5e5e5", - // Normal - "#darkgray": "555555", - "#red": "ff0000", - "#green": "00ff00", - "#yellow": "ffff00", - "#blue": "0000ff", - "#fuchsia": "ff00ff", - "#turquoise": "00ffff", - "#white": "ffffff", -} - -// Colour represents an RGB colour. -type Colour int32 - -// NewColour creates a Colour directly from RGB values. -func NewColour(r, g, b uint8) Colour { - return ParseColour(fmt.Sprintf("%02x%02x%02x", r, g, b)) -} - -// Distance between this colour and another. -// -// This uses the approach described here (https://www.compuphase.com/cmetric.htm). -// This is not as accurate as LAB, et. al. but is *vastly* simpler and sufficient for our needs. -func (c Colour) Distance(e2 Colour) float64 { - ar, ag, ab := int64(c.Red()), int64(c.Green()), int64(c.Blue()) - br, bg, bb := int64(e2.Red()), int64(e2.Green()), int64(e2.Blue()) - rmean := (ar + br) / 2 - r := ar - br - g := ag - bg - b := ab - bb - return math.Sqrt(float64((((512 + rmean) * r * r) >> 8) + 4*g*g + (((767 - rmean) * b * b) >> 8))) -} - -// Brighten returns a copy of this colour with its brightness adjusted. -// -// If factor is negative, the colour is darkened. -// -// Uses approach described here (http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html). -func (c Colour) Brighten(factor float64) Colour { - r := float64(c.Red()) - g := float64(c.Green()) - b := float64(c.Blue()) - - if factor < 0 { - factor++ - r *= factor - g *= factor - b *= factor - } else { - r = (255-r)*factor + r - g = (255-g)*factor + g - b = (255-b)*factor + b - } - return NewColour(uint8(r), uint8(g), uint8(b)) -} - -// BrightenOrDarken brightens a colour if it is < 0.5 brightness or darkens if > 0.5 brightness. -func (c Colour) BrightenOrDarken(factor float64) Colour { - if c.Brightness() < 0.5 { - return c.Brighten(factor) - } - return c.Brighten(-factor) -} - -// ClampBrightness returns a copy of this colour with its brightness adjusted such that -// it falls within the range [min, max] (or very close to it due to rounding errors). -// The supplied values use the same [0.0, 1.0] range as Brightness. -func (c Colour) ClampBrightness(min, max float64) Colour { - if !c.IsSet() { - return c - } - - min = math.Max(min, 0) - max = math.Min(max, 1) - current := c.Brightness() - target := math.Min(math.Max(current, min), max) - if current == target { - return c - } - - r := float64(c.Red()) - g := float64(c.Green()) - b := float64(c.Blue()) - rgb := r + g + b - if target > current { - // Solve for x: target == ((255-r)*x + r + (255-g)*x + g + (255-b)*x + b) / 255 / 3 - return c.Brighten((target*255*3 - rgb) / (255*3 - rgb)) - } - // Solve for x: target == (r*(x+1) + g*(x+1) + b*(x+1)) / 255 / 3 - return c.Brighten((target*255*3)/rgb - 1) -} - -// Brightness of the colour (roughly) in the range 0.0 to 1.0. -func (c Colour) Brightness() float64 { - return (float64(c.Red()) + float64(c.Green()) + float64(c.Blue())) / 255.0 / 3.0 -} - -// ParseColour in the forms #rgb, #rrggbb, #ansi, or #. -// Will return an "unset" colour if invalid. -func ParseColour(colour string) Colour { - colour = normaliseColour(colour) - n, err := strconv.ParseUint(colour, 16, 32) - if err != nil { - return 0 - } - return Colour(n + 1) -} - -// MustParseColour is like ParseColour except it panics if the colour is invalid. -// -// Will panic if colour is in an invalid format. -func MustParseColour(colour string) Colour { - parsed := ParseColour(colour) - if !parsed.IsSet() { - panic(fmt.Errorf("invalid colour %q", colour)) - } - return parsed -} - -// IsSet returns true if the colour is set. -func (c Colour) IsSet() bool { return c != 0 } - -func (c Colour) String() string { return fmt.Sprintf("#%06x", int(c-1)) } -func (c Colour) GoString() string { return fmt.Sprintf("Colour(0x%06x)", int(c-1)) } - -// Red component of colour. -func (c Colour) Red() uint8 { return uint8(((c - 1) >> 16) & 0xff) } - -// Green component of colour. -func (c Colour) Green() uint8 { return uint8(((c - 1) >> 8) & 0xff) } - -// Blue component of colour. -func (c Colour) Blue() uint8 { return uint8((c - 1) & 0xff) } - -// Colours is an orderable set of colours. -type Colours []Colour - -func (c Colours) Len() int { return len(c) } -func (c Colours) Swap(i, j int) { c[i], c[j] = c[j], c[i] } -func (c Colours) Less(i, j int) bool { return c[i] < c[j] } - -// Convert colours to #rrggbb. -func normaliseColour(colour string) string { - if ansi, ok := ANSI2RGB[colour]; ok { - return ansi - } - if strings.HasPrefix(colour, "#") { - colour = colour[1:] - if len(colour) == 3 { - return colour[0:1] + colour[0:1] + colour[1:2] + colour[1:2] + colour[2:3] + colour[2:3] - } - } - return colour -} diff --git a/vendor/github.com/alecthomas/chroma/v2/delegate.go b/vendor/github.com/alecthomas/chroma/v2/delegate.go deleted file mode 100644 index f848194f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/delegate.go +++ /dev/null @@ -1,152 +0,0 @@ -package chroma - -import ( - "bytes" -) - -type delegatingLexer struct { - root Lexer - language Lexer -} - -// DelegatingLexer combines two lexers to handle the common case of a language embedded inside another, such as PHP -// inside HTML or PHP inside plain text. -// -// It takes two lexer as arguments: a root lexer and a language lexer. First everything is scanned using the language -// lexer, which must return "Other" for unrecognised tokens. Then all "Other" tokens are lexed using the root lexer. -// Finally, these two sets of tokens are merged. -// -// The lexers from the template lexer package use this base lexer. -func DelegatingLexer(root Lexer, language Lexer) Lexer { - return &delegatingLexer{ - root: root, - language: language, - } -} - -func (d *delegatingLexer) AnalyseText(text string) float32 { - return d.root.AnalyseText(text) -} - -func (d *delegatingLexer) SetAnalyser(analyser func(text string) float32) Lexer { - d.root.SetAnalyser(analyser) - return d -} - -func (d *delegatingLexer) SetRegistry(r *LexerRegistry) Lexer { - d.root.SetRegistry(r) - d.language.SetRegistry(r) - return d -} - -func (d *delegatingLexer) Config() *Config { - return d.language.Config() -} - -// An insertion is the character range where language tokens should be inserted. -type insertion struct { - start, end int - tokens []Token -} - -func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit - tokens, err := Tokenise(Coalesce(d.language), options, text) - if err != nil { - return nil, err - } - // Compute insertions and gather "Other" tokens. - others := &bytes.Buffer{} - insertions := []*insertion{} - var insert *insertion - offset := 0 - var last Token - for _, t := range tokens { - if t.Type == Other { - if last != EOF && insert != nil && last.Type != Other { - insert.end = offset - } - others.WriteString(t.Value) - } else { - if last == EOF || last.Type == Other { - insert = &insertion{start: offset} - insertions = append(insertions, insert) - } - insert.tokens = append(insert.tokens, t) - } - last = t - offset += len(t.Value) - } - - if len(insertions) == 0 { - return d.root.Tokenise(options, text) - } - - // Lex the other tokens. - rootTokens, err := Tokenise(Coalesce(d.root), options, others.String()) - if err != nil { - return nil, err - } - - // Interleave the two sets of tokens. - var out []Token - offset = 0 // Offset into text. - tokenIndex := 0 - nextToken := func() Token { - if tokenIndex >= len(rootTokens) { - return EOF - } - t := rootTokens[tokenIndex] - tokenIndex++ - return t - } - insertionIndex := 0 - nextInsertion := func() *insertion { - if insertionIndex >= len(insertions) { - return nil - } - i := insertions[insertionIndex] - insertionIndex++ - return i - } - t := nextToken() - i := nextInsertion() - for t != EOF || i != nil { - // fmt.Printf("%d->%d:%q %d->%d:%q\n", offset, offset+len(t.Value), t.Value, i.start, i.end, Stringify(i.tokens...)) - if t == EOF || (i != nil && i.start < offset+len(t.Value)) { - var l Token - l, t = splitToken(t, i.start-offset) - if l != EOF { - out = append(out, l) - offset += len(l.Value) - } - out = append(out, i.tokens...) - offset += i.end - i.start - if t == EOF { - t = nextToken() - } - i = nextInsertion() - } else { - out = append(out, t) - offset += len(t.Value) - t = nextToken() - } - } - return Literator(out...), nil -} - -func splitToken(t Token, offset int) (l Token, r Token) { - if t == EOF { - return EOF, EOF - } - if offset == 0 { - return EOF, t - } - if offset == len(t.Value) { - return t, EOF - } - l = t.Clone() - r = t.Clone() - l.Value = l.Value[:offset] - r.Value = r.Value[offset:] - return -} diff --git a/vendor/github.com/alecthomas/chroma/v2/doc.go b/vendor/github.com/alecthomas/chroma/v2/doc.go deleted file mode 100644 index 4dde77c8..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Package chroma takes source code and other structured text and converts it into syntax highlighted HTML, ANSI- -// coloured text, etc. -// -// Chroma is based heavily on Pygments, and includes translators for Pygments lexers and styles. -// -// For more information, go here: https://github.com/alecthomas/chroma -package chroma diff --git a/vendor/github.com/alecthomas/chroma/v2/emitters.go b/vendor/github.com/alecthomas/chroma/v2/emitters.go deleted file mode 100644 index 0788b5b2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/emitters.go +++ /dev/null @@ -1,218 +0,0 @@ -package chroma - -import ( - "fmt" -) - -// An Emitter takes group matches and returns tokens. -type Emitter interface { - // Emit tokens for the given regex groups. - Emit(groups []string, state *LexerState) Iterator -} - -// SerialisableEmitter is an Emitter that can be serialised and deserialised to/from JSON. -type SerialisableEmitter interface { - Emitter - EmitterKind() string -} - -// EmitterFunc is a function that is an Emitter. -type EmitterFunc func(groups []string, state *LexerState) Iterator - -// Emit tokens for groups. -func (e EmitterFunc) Emit(groups []string, state *LexerState) Iterator { - return e(groups, state) -} - -type Emitters []Emitter - -type byGroupsEmitter struct { - Emitters -} - -// ByGroups emits a token for each matching group in the rule's regex. -func ByGroups(emitters ...Emitter) Emitter { - return &byGroupsEmitter{Emitters: emitters} -} - -func (b *byGroupsEmitter) EmitterKind() string { return "bygroups" } - -func (b *byGroupsEmitter) Emit(groups []string, state *LexerState) Iterator { - iterators := make([]Iterator, 0, len(groups)-1) - if len(b.Emitters) != len(groups)-1 { - iterators = append(iterators, Error.Emit(groups, state)) - // panic(errors.Errorf("number of groups %q does not match number of emitters %v", groups, emitters)) - } else { - for i, group := range groups[1:] { - if b.Emitters[i] != nil { - iterators = append(iterators, b.Emitters[i].Emit([]string{group}, state)) - } - } - } - return Concaterator(iterators...) -} - -// ByGroupNames emits a token for each named matching group in the rule's regex. -func ByGroupNames(emitters map[string]Emitter) Emitter { - return EmitterFunc(func(groups []string, state *LexerState) Iterator { - iterators := make([]Iterator, 0, len(state.NamedGroups)-1) - if len(state.NamedGroups)-1 == 0 { - if emitter, ok := emitters[`0`]; ok { - iterators = append(iterators, emitter.Emit(groups, state)) - } else { - iterators = append(iterators, Error.Emit(groups, state)) - } - } else { - ruleRegex := state.Rules[state.State][state.Rule].Regexp - for i := 1; i < len(state.NamedGroups); i++ { - groupName := ruleRegex.GroupNameFromNumber(i) - group := state.NamedGroups[groupName] - if emitter, ok := emitters[groupName]; ok { - if emitter != nil { - iterators = append(iterators, emitter.Emit([]string{group}, state)) - } - } else { - iterators = append(iterators, Error.Emit([]string{group}, state)) - } - } - } - return Concaterator(iterators...) - }) -} - -// UsingByGroup emits tokens for the matched groups in the regex using a -// sublexer. Used when lexing code blocks where the name of a sublexer is -// contained within the block, for example on a Markdown text block or SQL -// language block. -// -// An attempt to load the sublexer will be made using the captured value from -// the text of the matched sublexerNameGroup. If a sublexer matching the -// sublexerNameGroup is available, then tokens for the matched codeGroup will -// be emitted using the sublexer. Otherwise, if no sublexer is available, then -// tokens will be emitted from the passed emitter. -// -// Example: -// -// var Markdown = internal.Register(MustNewLexer( -// &Config{ -// Name: "markdown", -// Aliases: []string{"md", "mkd"}, -// Filenames: []string{"*.md", "*.mkd", "*.markdown"}, -// MimeTypes: []string{"text/x-markdown"}, -// }, -// Rules{ -// "root": { -// {"^(```)(\\w+)(\\n)([\\w\\W]*?)(^```$)", -// UsingByGroup( -// 2, 4, -// String, String, String, Text, String, -// ), -// nil, -// }, -// }, -// }, -// )) -// -// See the lexers/markdown.go for the complete example. -// -// Note: panic's if the number of emitters does not equal the number of matched -// groups in the regex. -func UsingByGroup(sublexerNameGroup, codeGroup int, emitters ...Emitter) Emitter { - return &usingByGroup{ - SublexerNameGroup: sublexerNameGroup, - CodeGroup: codeGroup, - Emitters: emitters, - } -} - -type usingByGroup struct { - SublexerNameGroup int `xml:"sublexer_name_group"` - CodeGroup int `xml:"code_group"` - Emitters Emitters `xml:"emitters"` -} - -func (u *usingByGroup) EmitterKind() string { return "usingbygroup" } -func (u *usingByGroup) Emit(groups []string, state *LexerState) Iterator { - // bounds check - if len(u.Emitters) != len(groups)-1 { - panic("UsingByGroup expects number of emitters to be the same as len(groups)-1") - } - - // grab sublexer - sublexer := state.Registry.Get(groups[u.SublexerNameGroup]) - - // build iterators - iterators := make([]Iterator, len(groups)-1) - for i, group := range groups[1:] { - if i == u.CodeGroup-1 && sublexer != nil { - var err error - iterators[i], err = sublexer.Tokenise(nil, groups[u.CodeGroup]) - if err != nil { - panic(err) - } - } else if u.Emitters[i] != nil { - iterators[i] = u.Emitters[i].Emit([]string{group}, state) - } - } - return Concaterator(iterators...) -} - -// UsingLexer returns an Emitter that uses a given Lexer for parsing and emitting. -// -// This Emitter is not serialisable. -func UsingLexer(lexer Lexer) Emitter { - return EmitterFunc(func(groups []string, _ *LexerState) Iterator { - it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0]) - if err != nil { - panic(err) - } - return it - }) -} - -type usingEmitter struct { - Lexer string `xml:"lexer,attr"` -} - -func (u *usingEmitter) EmitterKind() string { return "using" } - -func (u *usingEmitter) Emit(groups []string, state *LexerState) Iterator { - if state.Registry == nil { - panic(fmt.Sprintf("no LexerRegistry available for Using(%q)", u.Lexer)) - } - lexer := state.Registry.Get(u.Lexer) - if lexer == nil { - panic(fmt.Sprintf("no such lexer %q", u.Lexer)) - } - it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0]) - if err != nil { - panic(err) - } - return it -} - -// Using returns an Emitter that uses a given Lexer reference for parsing and emitting. -// -// The referenced lexer must be stored in the same LexerRegistry. -func Using(lexer string) Emitter { - return &usingEmitter{Lexer: lexer} -} - -type usingSelfEmitter struct { - State string `xml:"state,attr"` -} - -func (u *usingSelfEmitter) EmitterKind() string { return "usingself" } - -func (u *usingSelfEmitter) Emit(groups []string, state *LexerState) Iterator { - it, err := state.Lexer.Tokenise(&TokeniseOptions{State: u.State, Nested: true}, groups[0]) - if err != nil { - panic(err) - } - return it -} - -// UsingSelf is like Using, but uses the current Lexer. -func UsingSelf(stateName string) Emitter { - return &usingSelfEmitter{stateName} -} diff --git a/vendor/github.com/alecthomas/chroma/v2/formatter.go b/vendor/github.com/alecthomas/chroma/v2/formatter.go deleted file mode 100644 index 00dd5d8d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatter.go +++ /dev/null @@ -1,43 +0,0 @@ -package chroma - -import ( - "io" -) - -// A Formatter for Chroma lexers. -type Formatter interface { - // Format returns a formatting function for tokens. - // - // If the iterator panics, the Formatter should recover. - Format(w io.Writer, style *Style, iterator Iterator) error -} - -// A FormatterFunc is a Formatter implemented as a function. -// -// Guards against iterator panics. -type FormatterFunc func(w io.Writer, style *Style, iterator Iterator) error - -func (f FormatterFunc) Format(w io.Writer, s *Style, it Iterator) (err error) { // nolint - defer func() { - if perr := recover(); perr != nil { - err = perr.(error) - } - }() - return f(w, s, it) -} - -type recoveringFormatter struct { - Formatter -} - -func (r recoveringFormatter) Format(w io.Writer, s *Style, it Iterator) (err error) { - defer func() { - if perr := recover(); perr != nil { - err = perr.(error) - } - }() - return r.Formatter.Format(w, s, it) -} - -// RecoveringFormatter wraps a formatter with panic recovery. -func RecoveringFormatter(formatter Formatter) Formatter { return recoveringFormatter{formatter} } diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/api.go b/vendor/github.com/alecthomas/chroma/v2/formatters/api.go deleted file mode 100644 index 9ca0d01d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/api.go +++ /dev/null @@ -1,57 +0,0 @@ -package formatters - -import ( - "io" - "sort" - - "github.com/alecthomas/chroma/v2" - "github.com/alecthomas/chroma/v2/formatters/html" - "github.com/alecthomas/chroma/v2/formatters/svg" -) - -var ( - // NoOp formatter. - NoOp = Register("noop", chroma.FormatterFunc(func(w io.Writer, s *chroma.Style, iterator chroma.Iterator) error { - for t := iterator(); t != chroma.EOF; t = iterator() { - if _, err := io.WriteString(w, t.Value); err != nil { - return err - } - } - return nil - })) - // Default HTML formatter outputs self-contained HTML. - htmlFull = Register("html", html.New(html.Standalone(true), html.WithClasses(true))) // nolint - SVG = Register("svg", svg.New(svg.EmbedFont("Liberation Mono", svg.FontLiberationMono, svg.WOFF))) -) - -// Fallback formatter. -var Fallback = NoOp - -// Registry of Formatters. -var Registry = map[string]chroma.Formatter{} - -// Names of registered formatters. -func Names() []string { - out := []string{} - for name := range Registry { - out = append(out, name) - } - sort.Strings(out) - return out -} - -// Get formatter by name. -// -// If the given formatter is not found, the Fallback formatter will be returned. -func Get(name string) chroma.Formatter { - if f, ok := Registry[name]; ok { - return f - } - return Fallback -} - -// Register a named formatter. -func Register(name string, formatter chroma.Formatter) chroma.Formatter { - Registry[name] = formatter - return formatter -} diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go b/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go deleted file mode 100644 index 92d784c2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/html/html.go +++ /dev/null @@ -1,623 +0,0 @@ -package html - -import ( - "fmt" - "html" - "io" - "sort" - "strconv" - "strings" - "sync" - - "github.com/alecthomas/chroma/v2" -) - -// Option sets an option of the HTML formatter. -type Option func(f *Formatter) - -// Standalone configures the HTML formatter for generating a standalone HTML document. -func Standalone(b bool) Option { return func(f *Formatter) { f.standalone = b } } - -// ClassPrefix sets the CSS class prefix. -func ClassPrefix(prefix string) Option { return func(f *Formatter) { f.prefix = prefix } } - -// WithClasses emits HTML using CSS classes, rather than inline styles. -func WithClasses(b bool) Option { return func(f *Formatter) { f.Classes = b } } - -// WithAllClasses disables an optimisation that omits redundant CSS classes. -func WithAllClasses(b bool) Option { return func(f *Formatter) { f.allClasses = b } } - -// WithCustomCSS sets user's custom CSS styles. -func WithCustomCSS(css map[chroma.TokenType]string) Option { - return func(f *Formatter) { - f.customCSS = css - } -} - -// TabWidth sets the number of characters for a tab. Defaults to 8. -func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width } } - -// PreventSurroundingPre prevents the surrounding pre tags around the generated code. -func PreventSurroundingPre(b bool) Option { - return func(f *Formatter) { - f.preventSurroundingPre = b - - if b { - f.preWrapper = nopPreWrapper - } else { - f.preWrapper = defaultPreWrapper - } - } -} - -// InlineCode creates inline code wrapped in a code tag. -func InlineCode(b bool) Option { - return func(f *Formatter) { - f.inlineCode = b - f.preWrapper = preWrapper{ - start: func(code bool, styleAttr string) string { - if code { - return fmt.Sprintf(``, styleAttr) - } - - return `` - }, - end: func(code bool) string { - if code { - return `` - } - - return `` - }, - } - } -} - -// WithPreWrapper allows control of the surrounding pre tags. -func WithPreWrapper(wrapper PreWrapper) Option { - return func(f *Formatter) { - f.preWrapper = wrapper - } -} - -// WrapLongLines wraps long lines. -func WrapLongLines(b bool) Option { - return func(f *Formatter) { - f.wrapLongLines = b - } -} - -// WithLineNumbers formats output with line numbers. -func WithLineNumbers(b bool) Option { - return func(f *Formatter) { - f.lineNumbers = b - } -} - -// LineNumbersInTable will, when combined with WithLineNumbers, separate the line numbers -// and code in table td's, which make them copy-and-paste friendly. -func LineNumbersInTable(b bool) Option { - return func(f *Formatter) { - f.lineNumbersInTable = b - } -} - -// WithLinkableLineNumbers decorates the line numbers HTML elements with an "id" -// attribute so they can be linked. -func WithLinkableLineNumbers(b bool, prefix string) Option { - return func(f *Formatter) { - f.linkableLineNumbers = b - f.lineNumbersIDPrefix = prefix - } -} - -// HighlightLines higlights the given line ranges with the Highlight style. -// -// A range is the beginning and ending of a range as 1-based line numbers, inclusive. -func HighlightLines(ranges [][2]int) Option { - return func(f *Formatter) { - f.highlightRanges = ranges - sort.Sort(f.highlightRanges) - } -} - -// BaseLineNumber sets the initial number to start line numbering at. Defaults to 1. -func BaseLineNumber(n int) Option { - return func(f *Formatter) { - f.baseLineNumber = n - } -} - -// New HTML formatter. -func New(options ...Option) *Formatter { - f := &Formatter{ - baseLineNumber: 1, - preWrapper: defaultPreWrapper, - } - f.styleCache = newStyleCache(f) - for _, option := range options { - option(f) - } - return f -} - -// PreWrapper defines the operations supported in WithPreWrapper. -type PreWrapper interface { - // Start is called to write a start

 element.
-	// The code flag tells whether this block surrounds
-	// highlighted code. This will be false when surrounding
-	// line numbers.
-	Start(code bool, styleAttr string) string
-
-	// End is called to write the end 
element. - End(code bool) string -} - -type preWrapper struct { - start func(code bool, styleAttr string) string - end func(code bool) string -} - -func (p preWrapper) Start(code bool, styleAttr string) string { - return p.start(code, styleAttr) -} - -func (p preWrapper) End(code bool) string { - return p.end(code) -} - -var ( - nopPreWrapper = preWrapper{ - start: func(code bool, styleAttr string) string { return "" }, - end: func(code bool) string { return "" }, - } - defaultPreWrapper = preWrapper{ - start: func(code bool, styleAttr string) string { - if code { - return fmt.Sprintf(``, styleAttr) - } - - return fmt.Sprintf(``, styleAttr) - }, - end: func(code bool) string { - if code { - return `` - } - - return `` - }, - } -) - -// Formatter that generates HTML. -type Formatter struct { - styleCache *styleCache - standalone bool - prefix string - Classes bool // Exported field to detect when classes are being used - allClasses bool - customCSS map[chroma.TokenType]string - preWrapper PreWrapper - inlineCode bool - preventSurroundingPre bool - tabWidth int - wrapLongLines bool - lineNumbers bool - lineNumbersInTable bool - linkableLineNumbers bool - lineNumbersIDPrefix string - highlightRanges highlightRanges - baseLineNumber int -} - -type highlightRanges [][2]int - -func (h highlightRanges) Len() int { return len(h) } -func (h highlightRanges) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h highlightRanges) Less(i, j int) bool { return h[i][0] < h[j][0] } - -func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) { - return f.writeHTML(w, style, iterator.Tokens()) -} - -// We deliberately don't use html/template here because it is two orders of magnitude slower (benchmarked). -// -// OTOH we need to be super careful about correct escaping... -func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.Token) (err error) { // nolint: gocyclo - css := f.styleCache.get(style, true) - if f.standalone { - fmt.Fprint(w, "\n") - if f.Classes { - fmt.Fprint(w, "") - } - fmt.Fprintf(w, "\n", f.styleAttr(css, chroma.Background)) - } - - wrapInTable := f.lineNumbers && f.lineNumbersInTable - - lines := chroma.SplitTokensIntoLines(tokens) - lineDigits := len(strconv.Itoa(f.baseLineNumber + len(lines) - 1)) - highlightIndex := 0 - - if wrapInTable { - // List line numbers in its own - fmt.Fprintf(w, "\n", f.styleAttr(css, chroma.PreWrapper)) - fmt.Fprintf(w, "", f.styleAttr(css, chroma.LineTable)) - fmt.Fprintf(w, "\n", f.styleAttr(css, chroma.LineTableTD)) - fmt.Fprintf(w, "%s", f.preWrapper.Start(false, f.styleAttr(css, chroma.PreWrapper))) - for index := range lines { - line := f.baseLineNumber + index - highlight, next := f.shouldHighlight(highlightIndex, line) - if next { - highlightIndex++ - } - if highlight { - fmt.Fprintf(w, "", f.styleAttr(css, chroma.LineHighlight)) - } - - fmt.Fprintf(w, "%s\n", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(css, lineDigits, line)) - - if highlight { - fmt.Fprintf(w, "") - } - } - fmt.Fprint(w, f.preWrapper.End(false)) - fmt.Fprint(w, "\n") - fmt.Fprintf(w, "\n", f.styleAttr(css, chroma.LineTableTD, "width:100%")) - } - - fmt.Fprintf(w, "%s", f.preWrapper.Start(true, f.styleAttr(css, chroma.PreWrapper))) - - highlightIndex = 0 - for index, tokens := range lines { - // 1-based line number. - line := f.baseLineNumber + index - highlight, next := f.shouldHighlight(highlightIndex, line) - if next { - highlightIndex++ - } - - if !(f.preventSurroundingPre || f.inlineCode) { - // Start of Line - fmt.Fprint(w, ``) - } else { - fmt.Fprintf(w, "%s>", f.styleAttr(css, chroma.Line)) - } - - // Line number - if f.lineNumbers && !wrapInTable { - fmt.Fprintf(w, "%s", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), f.lineTitleWithLinkIfNeeded(css, lineDigits, line)) - } - - fmt.Fprintf(w, ``, f.styleAttr(css, chroma.CodeLine)) - } - - for _, token := range tokens { - html := html.EscapeString(token.String()) - attr := f.styleAttr(css, token.Type) - if attr != "" { - html = fmt.Sprintf("%s", attr, html) - } - fmt.Fprint(w, html) - } - - if !(f.preventSurroundingPre || f.inlineCode) { - fmt.Fprint(w, ``) // End of CodeLine - - fmt.Fprint(w, ``) // End of Line - } - } - fmt.Fprintf(w, "%s", f.preWrapper.End(true)) - - if wrapInTable { - fmt.Fprint(w, "\n") - fmt.Fprint(w, "\n") - } - - if f.standalone { - fmt.Fprint(w, "\n\n") - fmt.Fprint(w, "\n") - } - - return nil -} - -func (f *Formatter) lineIDAttribute(line int) string { - if !f.linkableLineNumbers { - return "" - } - return fmt.Sprintf(" id=\"%s\"", f.lineID(line)) -} - -func (f *Formatter) lineTitleWithLinkIfNeeded(css map[chroma.TokenType]string, lineDigits, line int) string { - title := fmt.Sprintf("%*d", lineDigits, line) - if !f.linkableLineNumbers { - return title - } - return fmt.Sprintf("%s", f.styleAttr(css, chroma.LineLink), f.lineID(line), title) -} - -func (f *Formatter) lineID(line int) string { - return fmt.Sprintf("%s%d", f.lineNumbersIDPrefix, line) -} - -func (f *Formatter) shouldHighlight(highlightIndex, line int) (bool, bool) { - next := false - for highlightIndex < len(f.highlightRanges) && line > f.highlightRanges[highlightIndex][1] { - highlightIndex++ - next = true - } - if highlightIndex < len(f.highlightRanges) { - hrange := f.highlightRanges[highlightIndex] - if line >= hrange[0] && line <= hrange[1] { - return true, next - } - } - return false, next -} - -func (f *Formatter) class(t chroma.TokenType) string { - for t != 0 { - if cls, ok := chroma.StandardTypes[t]; ok { - if cls != "" { - return f.prefix + cls - } - return "" - } - t = t.Parent() - } - if cls := chroma.StandardTypes[t]; cls != "" { - return f.prefix + cls - } - return "" -} - -func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.TokenType, extraCSS ...string) string { - if f.Classes { - cls := f.class(tt) - if cls == "" { - return "" - } - return fmt.Sprintf(` class="%s"`, cls) - } - if _, ok := styles[tt]; !ok { - tt = tt.SubCategory() - if _, ok := styles[tt]; !ok { - tt = tt.Category() - if _, ok := styles[tt]; !ok { - return "" - } - } - } - css := []string{styles[tt]} - css = append(css, extraCSS...) - return fmt.Sprintf(` style="%s"`, strings.Join(css, ";")) -} - -func (f *Formatter) tabWidthStyle() string { - if f.tabWidth != 0 && f.tabWidth != 8 { - return fmt.Sprintf("-moz-tab-size: %[1]d; -o-tab-size: %[1]d; tab-size: %[1]d;", f.tabWidth) - } - return "" -} - -// WriteCSS writes CSS style definitions (without any surrounding HTML). -func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error { - css := f.styleCache.get(style, false) - // Special-case background as it is mapped to the outer ".chroma" class. - if _, err := fmt.Fprintf(w, "/* %s */ .%sbg { %s }\n", chroma.Background, f.prefix, css[chroma.Background]); err != nil { - return err - } - // Special-case PreWrapper as it is the ".chroma" class. - if _, err := fmt.Fprintf(w, "/* %s */ .%schroma { %s }\n", chroma.PreWrapper, f.prefix, css[chroma.PreWrapper]); err != nil { - return err - } - // Special-case code column of table to expand width. - if f.lineNumbers && f.lineNumbersInTable { - if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s:last-child { width: 100%%; }", - chroma.LineTableTD, f.prefix, f.class(chroma.LineTableTD)); err != nil { - return err - } - } - // Special-case line number highlighting when targeted. - if f.lineNumbers || f.lineNumbersInTable { - targetedLineCSS := StyleEntryToCSS(style.Get(chroma.LineHighlight)) - for _, tt := range []chroma.TokenType{chroma.LineNumbers, chroma.LineNumbersTable} { - fmt.Fprintf(w, "/* %s targeted by URL anchor */ .%schroma .%s:target { %s }\n", tt, f.prefix, f.class(tt), targetedLineCSS) - } - } - tts := []int{} - for tt := range css { - tts = append(tts, int(tt)) - } - sort.Ints(tts) - for _, ti := range tts { - tt := chroma.TokenType(ti) - switch tt { - case chroma.Background, chroma.PreWrapper: - continue - } - class := f.class(tt) - if class == "" { - continue - } - styles := css[tt] - if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s { %s }\n", tt, f.prefix, class, styles); err != nil { - return err - } - } - return nil -} - -func (f *Formatter) styleToCSS(style *chroma.Style) map[chroma.TokenType]string { - classes := map[chroma.TokenType]string{} - bg := style.Get(chroma.Background) - // Convert the style. - for t := range chroma.StandardTypes { - entry := style.Get(t) - if t != chroma.Background { - entry = entry.Sub(bg) - } - - // Inherit from custom CSS provided by user - tokenCategory := t.Category() - tokenSubCategory := t.SubCategory() - if t != tokenCategory { - if css, ok := f.customCSS[tokenCategory]; ok { - classes[t] = css - } - } - if tokenCategory != tokenSubCategory { - if css, ok := f.customCSS[tokenSubCategory]; ok { - classes[t] += css - } - } - // Add custom CSS provided by user - if css, ok := f.customCSS[t]; ok { - classes[t] += css - } - - if !f.allClasses && entry.IsZero() && classes[t] == `` { - continue - } - - styleEntryCSS := StyleEntryToCSS(entry) - if styleEntryCSS != `` && classes[t] != `` { - styleEntryCSS += `;` - } - classes[t] = styleEntryCSS + classes[t] - } - classes[chroma.Background] += `;` + f.tabWidthStyle() - classes[chroma.PreWrapper] += classes[chroma.Background] - // Make PreWrapper a grid to show highlight style with full width. - if len(f.highlightRanges) > 0 && f.customCSS[chroma.PreWrapper] == `` { - classes[chroma.PreWrapper] += `display: grid;` - } - // Make PreWrapper wrap long lines. - if f.wrapLongLines { - classes[chroma.PreWrapper] += `white-space: pre-wrap; word-break: break-word;` - } - lineNumbersStyle := `white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;` - // All rules begin with default rules followed by user provided rules - classes[chroma.Line] = `display: flex;` + classes[chroma.Line] - classes[chroma.LineNumbers] = lineNumbersStyle + classes[chroma.LineNumbers] - classes[chroma.LineNumbersTable] = lineNumbersStyle + classes[chroma.LineNumbersTable] - classes[chroma.LineTable] = "border-spacing: 0; padding: 0; margin: 0; border: 0;" + classes[chroma.LineTable] - classes[chroma.LineTableTD] = "vertical-align: top; padding: 0; margin: 0; border: 0;" + classes[chroma.LineTableTD] - classes[chroma.LineLink] = "outline: none; text-decoration: none; color: inherit" + classes[chroma.LineLink] - return classes -} - -// StyleEntryToCSS converts a chroma.StyleEntry to CSS attributes. -func StyleEntryToCSS(e chroma.StyleEntry) string { - styles := []string{} - if e.Colour.IsSet() { - styles = append(styles, "color: "+e.Colour.String()) - } - if e.Background.IsSet() { - styles = append(styles, "background-color: "+e.Background.String()) - } - if e.Bold == chroma.Yes { - styles = append(styles, "font-weight: bold") - } - if e.Italic == chroma.Yes { - styles = append(styles, "font-style: italic") - } - if e.Underline == chroma.Yes { - styles = append(styles, "text-decoration: underline") - } - return strings.Join(styles, "; ") -} - -// Compress CSS attributes - remove spaces, transform 6-digit colours to 3. -func compressStyle(s string) string { - parts := strings.Split(s, ";") - out := []string{} - for _, p := range parts { - p = strings.Join(strings.Fields(p), " ") - p = strings.Replace(p, ": ", ":", 1) - if strings.Contains(p, "#") { - c := p[len(p)-6:] - if c[0] == c[1] && c[2] == c[3] && c[4] == c[5] { - p = p[:len(p)-6] + c[0:1] + c[2:3] + c[4:5] - } - } - out = append(out, p) - } - return strings.Join(out, ";") -} - -const styleCacheLimit = 32 - -type styleCacheEntry struct { - style *chroma.Style - compressed bool - cache map[chroma.TokenType]string -} - -type styleCache struct { - mu sync.Mutex - // LRU cache of compiled (and possibly compressed) styles. This is a slice - // because the cache size is small, and a slice is sufficiently fast for - // small N. - cache []styleCacheEntry - f *Formatter -} - -func newStyleCache(f *Formatter) *styleCache { - return &styleCache{f: f} -} - -func (l *styleCache) get(style *chroma.Style, compress bool) map[chroma.TokenType]string { - l.mu.Lock() - defer l.mu.Unlock() - - // Look for an existing entry. - for i := len(l.cache) - 1; i >= 0; i-- { - entry := l.cache[i] - if entry.style == style && entry.compressed == compress { - // Top of the cache, no need to adjust the order. - if i == len(l.cache)-1 { - return entry.cache - } - // Move this entry to the end of the LRU - copy(l.cache[i:], l.cache[i+1:]) - l.cache[len(l.cache)-1] = entry - return entry.cache - } - } - - // No entry, create one. - cached := l.f.styleToCSS(style) - if !l.f.Classes { - for t, style := range cached { - cached[t] = compressStyle(style) - } - } - if compress { - for t, style := range cached { - cached[t] = compressStyle(style) - } - } - // Evict the oldest entry. - if len(l.cache) >= styleCacheLimit { - l.cache = l.cache[0:copy(l.cache, l.cache[1:])] - } - l.cache = append(l.cache, styleCacheEntry{style: style, cache: cached, compressed: compress}) - return cached -} diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/json.go b/vendor/github.com/alecthomas/chroma/v2/formatters/json.go deleted file mode 100644 index f167bc06..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/json.go +++ /dev/null @@ -1,31 +0,0 @@ -package formatters - -import ( - "encoding/json" - "fmt" - "io" - - "github.com/alecthomas/chroma/v2" -) - -// JSON formatter outputs the raw token structures as JSON. -var JSON = Register("json", chroma.FormatterFunc(func(w io.Writer, s *chroma.Style, it chroma.Iterator) error { - fmt.Fprintln(w, "[") - i := 0 - for t := it(); t != chroma.EOF; t = it() { - if i > 0 { - fmt.Fprintln(w, ",") - } - i++ - bytes, err := json.Marshal(t) - if err != nil { - return err - } - if _, err := fmt.Fprint(w, " "+string(bytes)); err != nil { - return err - } - } - fmt.Fprintln(w) - fmt.Fprintln(w, "]") - return nil -})) diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go b/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go deleted file mode 100644 index 70d692ec..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/svg/font_liberation_mono.go +++ /dev/null @@ -1,51 +0,0 @@ -// Digitized data copyright (c) 2010 Google Corporation -// with Reserved Font Arimo, Tinos and Cousine. -// Copyright (c) 2012 Red Hat, Inc. -// with Reserved Font Name Liberation. -// -// This Font Software is licensed under the SIL Open Font License, Version 1.1. -// This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL -// -// ----------------------------------------------------------- -// SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 -// ----------------------------------------------------------- -// -// PREAMBLE -// The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. -// -// The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. -// -// DEFINITIONS -// "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. -// -// "Reserved Font Name" refers to any names specified as such after the copyright statement(s). -// -// "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). -// -// "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. -// -// "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. -// -// PERMISSION & CONDITIONS -// Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: -// -// 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. -// -// 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. -// -// 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. -// -// 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. -// -// 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. -// -// TERMINATION -// This license becomes null and void if any of the above conditions are not met. -// -// DISCLAIMER -// THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. - -package svg - -// Liberation Mono as base64 encoded woff (SIL Open Font License)[https://en.wikipedia.org/wiki/Liberation_fonts] -var FontLiberationMono = `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` diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/svg/svg.go b/vendor/github.com/alecthomas/chroma/v2/formatters/svg/svg.go deleted file mode 100644 index 6d457f90..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/svg/svg.go +++ /dev/null @@ -1,222 +0,0 @@ -// Package svg contains an SVG formatter. -package svg - -import ( - "encoding/base64" - "errors" - "fmt" - "io" - "os" - "path" - "strings" - - "github.com/alecthomas/chroma/v2" -) - -// Option sets an option of the SVG formatter. -type Option func(f *Formatter) - -// FontFamily sets the font-family. -func FontFamily(fontFamily string) Option { return func(f *Formatter) { f.fontFamily = fontFamily } } - -// EmbedFontFile embeds given font file -func EmbedFontFile(fontFamily string, fileName string) (option Option, err error) { - var format FontFormat - switch path.Ext(fileName) { - case ".woff": - format = WOFF - case ".woff2": - format = WOFF2 - case ".ttf": - format = TRUETYPE - default: - return nil, errors.New("unexpected font file suffix") - } - - var content []byte - if content, err = os.ReadFile(fileName); err == nil { - option = EmbedFont(fontFamily, base64.StdEncoding.EncodeToString(content), format) - } - return -} - -// EmbedFont embeds given base64 encoded font -func EmbedFont(fontFamily string, font string, format FontFormat) Option { - return func(f *Formatter) { f.fontFamily = fontFamily; f.embeddedFont = font; f.fontFormat = format } -} - -// New SVG formatter. -func New(options ...Option) *Formatter { - f := &Formatter{fontFamily: "Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace"} - for _, option := range options { - option(f) - } - return f -} - -// Formatter that generates SVG. -type Formatter struct { - fontFamily string - embeddedFont string - fontFormat FontFormat -} - -func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) { - f.writeSVG(w, style, iterator.Tokens()) - return err -} - -var svgEscaper = strings.NewReplacer( - `&`, "&", - `<`, "<", - `>`, ">", - `"`, """, - ` `, " ", - ` `, "    ", -) - -// EscapeString escapes special characters. -func escapeString(s string) string { - return svgEscaper.Replace(s) -} - -func (f *Formatter) writeSVG(w io.Writer, style *chroma.Style, tokens []chroma.Token) { // nolint: gocyclo - svgStyles := f.styleToSVG(style) - lines := chroma.SplitTokensIntoLines(tokens) - - fmt.Fprint(w, "\n") - fmt.Fprint(w, "\n") - fmt.Fprintf(w, "\n", 8*maxLineWidth(lines), 10+int(16.8*float64(len(lines)+1))) - - if f.embeddedFont != "" { - f.writeFontStyle(w) - } - - fmt.Fprintf(w, "\n", style.Get(chroma.Background).Background.String()) - fmt.Fprintf(w, "\n", f.fontFamily, style.Get(chroma.Text).Colour.String()) - - f.writeTokenBackgrounds(w, lines, style) - - for index, tokens := range lines { - fmt.Fprintf(w, "", 1.2*float64(index+1)) - - for _, token := range tokens { - text := escapeString(token.String()) - attr := f.styleAttr(svgStyles, token.Type) - if attr != "" { - text = fmt.Sprintf("%s", attr, text) - } - fmt.Fprint(w, text) - } - fmt.Fprint(w, "") - } - - fmt.Fprint(w, "\n\n") - fmt.Fprint(w, "\n") -} - -func maxLineWidth(lines [][]chroma.Token) int { - maxWidth := 0 - for _, tokens := range lines { - length := 0 - for _, token := range tokens { - length += len(strings.ReplaceAll(token.String(), ` `, " ")) - } - if length > maxWidth { - maxWidth = length - } - } - return maxWidth -} - -// There is no background attribute for text in SVG so simply calculate the position and text -// of tokens with a background color that differs from the default and add a rectangle for each before -// adding the token. -func (f *Formatter) writeTokenBackgrounds(w io.Writer, lines [][]chroma.Token, style *chroma.Style) { - for index, tokens := range lines { - lineLength := 0 - for _, token := range tokens { - length := len(strings.ReplaceAll(token.String(), ` `, " ")) - tokenBackground := style.Get(token.Type).Background - if tokenBackground.IsSet() && tokenBackground != style.Get(chroma.Background).Background { - fmt.Fprintf(w, "\n", escapeString(token.String()), lineLength, 1.2*float64(index)+0.25, length, style.Get(token.Type).Background.String()) - } - lineLength += length - } - } -} - -type FontFormat int - -// https://transfonter.org/formats -const ( - WOFF FontFormat = iota - WOFF2 - TRUETYPE -) - -var fontFormats = [...]string{ - "woff", - "woff2", - "truetype", -} - -func (f *Formatter) writeFontStyle(w io.Writer) { - fmt.Fprintf(w, ``, f.fontFamily, fontFormats[f.fontFormat], f.embeddedFont, fontFormats[f.fontFormat]) -} - -func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.TokenType) string { - if _, ok := styles[tt]; !ok { - tt = tt.SubCategory() - if _, ok := styles[tt]; !ok { - tt = tt.Category() - if _, ok := styles[tt]; !ok { - return "" - } - } - } - return styles[tt] -} - -func (f *Formatter) styleToSVG(style *chroma.Style) map[chroma.TokenType]string { - converted := map[chroma.TokenType]string{} - bg := style.Get(chroma.Background) - // Convert the style. - for t := range chroma.StandardTypes { - entry := style.Get(t) - if t != chroma.Background { - entry = entry.Sub(bg) - } - if entry.IsZero() { - continue - } - converted[t] = StyleEntryToSVG(entry) - } - return converted -} - -// StyleEntryToSVG converts a chroma.StyleEntry to SVG attributes. -func StyleEntryToSVG(e chroma.StyleEntry) string { - var styles []string - - if e.Colour.IsSet() { - styles = append(styles, "fill=\""+e.Colour.String()+"\"") - } - if e.Bold == chroma.Yes { - styles = append(styles, "font-weight=\"bold\"") - } - if e.Italic == chroma.Yes { - styles = append(styles, "font-style=\"italic\"") - } - if e.Underline == chroma.Yes { - styles = append(styles, "text-decoration=\"underline\"") - } - return strings.Join(styles, " ") -} diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/tokens.go b/vendor/github.com/alecthomas/chroma/v2/formatters/tokens.go deleted file mode 100644 index 3bdd57cc..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/tokens.go +++ /dev/null @@ -1,18 +0,0 @@ -package formatters - -import ( - "fmt" - "io" - - "github.com/alecthomas/chroma/v2" -) - -// Tokens formatter outputs the raw token structures. -var Tokens = Register("tokens", chroma.FormatterFunc(func(w io.Writer, s *chroma.Style, it chroma.Iterator) error { - for t := it(); t != chroma.EOF; t = it() { - if _, err := fmt.Fprintln(w, t.GoString()); err != nil { - return err - } - } - return nil -})) diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go b/vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go deleted file mode 100644 index d383d985..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/tty_indexed.go +++ /dev/null @@ -1,291 +0,0 @@ -package formatters - -import ( - "fmt" - "io" - "math" - - "github.com/alecthomas/chroma/v2" -) - -type ttyTable struct { - foreground map[chroma.Colour]string - background map[chroma.Colour]string -} - -var c = chroma.MustParseColour - -var ttyTables = map[int]*ttyTable{ - 8: { - foreground: map[chroma.Colour]string{ - c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m", - c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m", - c("#555555"): "\033[1m\033[30m", c("#ff0000"): "\033[1m\033[31m", c("#00ff00"): "\033[1m\033[32m", c("#ffff00"): "\033[1m\033[33m", - c("#0000ff"): "\033[1m\033[34m", c("#ff00ff"): "\033[1m\033[35m", c("#00ffff"): "\033[1m\033[36m", c("#ffffff"): "\033[1m\033[37m", - }, - background: map[chroma.Colour]string{ - c("#000000"): "\033[40m", c("#7f0000"): "\033[41m", c("#007f00"): "\033[42m", c("#7f7fe0"): "\033[43m", - c("#00007f"): "\033[44m", c("#7f007f"): "\033[45m", c("#007f7f"): "\033[46m", c("#e5e5e5"): "\033[47m", - c("#555555"): "\033[1m\033[40m", c("#ff0000"): "\033[1m\033[41m", c("#00ff00"): "\033[1m\033[42m", c("#ffff00"): "\033[1m\033[43m", - c("#0000ff"): "\033[1m\033[44m", c("#ff00ff"): "\033[1m\033[45m", c("#00ffff"): "\033[1m\033[46m", c("#ffffff"): "\033[1m\033[47m", - }, - }, - 16: { - foreground: map[chroma.Colour]string{ - c("#000000"): "\033[30m", c("#7f0000"): "\033[31m", c("#007f00"): "\033[32m", c("#7f7fe0"): "\033[33m", - c("#00007f"): "\033[34m", c("#7f007f"): "\033[35m", c("#007f7f"): "\033[36m", c("#e5e5e5"): "\033[37m", - c("#555555"): "\033[90m", c("#ff0000"): "\033[91m", c("#00ff00"): "\033[92m", c("#ffff00"): "\033[93m", - c("#0000ff"): "\033[94m", c("#ff00ff"): "\033[95m", c("#00ffff"): "\033[96m", c("#ffffff"): "\033[97m", - }, - background: map[chroma.Colour]string{ - c("#000000"): "\033[40m", c("#7f0000"): "\033[41m", c("#007f00"): "\033[42m", c("#7f7fe0"): "\033[43m", - c("#00007f"): "\033[44m", c("#7f007f"): "\033[45m", c("#007f7f"): "\033[46m", c("#e5e5e5"): "\033[47m", - c("#555555"): "\033[100m", c("#ff0000"): "\033[101m", c("#00ff00"): "\033[102m", c("#ffff00"): "\033[103m", - c("#0000ff"): "\033[104m", c("#ff00ff"): "\033[105m", c("#00ffff"): "\033[106m", c("#ffffff"): "\033[107m", - }, - }, - 256: { - foreground: map[chroma.Colour]string{ - c("#000000"): "\033[38;5;0m", c("#800000"): "\033[38;5;1m", c("#008000"): "\033[38;5;2m", c("#808000"): "\033[38;5;3m", - c("#000080"): "\033[38;5;4m", c("#800080"): "\033[38;5;5m", c("#008080"): "\033[38;5;6m", c("#c0c0c0"): "\033[38;5;7m", - c("#808080"): "\033[38;5;8m", c("#ff0000"): "\033[38;5;9m", c("#00ff00"): "\033[38;5;10m", c("#ffff00"): "\033[38;5;11m", - c("#0000ff"): "\033[38;5;12m", c("#ff00ff"): "\033[38;5;13m", c("#00ffff"): "\033[38;5;14m", c("#ffffff"): "\033[38;5;15m", - c("#000000"): "\033[38;5;16m", c("#00005f"): "\033[38;5;17m", c("#000087"): "\033[38;5;18m", c("#0000af"): "\033[38;5;19m", - c("#0000d7"): "\033[38;5;20m", c("#0000ff"): "\033[38;5;21m", c("#005f00"): "\033[38;5;22m", c("#005f5f"): "\033[38;5;23m", - c("#005f87"): "\033[38;5;24m", c("#005faf"): "\033[38;5;25m", c("#005fd7"): "\033[38;5;26m", c("#005fff"): "\033[38;5;27m", - c("#008700"): "\033[38;5;28m", c("#00875f"): "\033[38;5;29m", c("#008787"): "\033[38;5;30m", c("#0087af"): "\033[38;5;31m", - c("#0087d7"): "\033[38;5;32m", c("#0087ff"): "\033[38;5;33m", c("#00af00"): "\033[38;5;34m", c("#00af5f"): "\033[38;5;35m", - c("#00af87"): "\033[38;5;36m", c("#00afaf"): "\033[38;5;37m", c("#00afd7"): "\033[38;5;38m", c("#00afff"): "\033[38;5;39m", - c("#00d700"): "\033[38;5;40m", c("#00d75f"): "\033[38;5;41m", c("#00d787"): "\033[38;5;42m", c("#00d7af"): "\033[38;5;43m", - c("#00d7d7"): "\033[38;5;44m", c("#00d7ff"): "\033[38;5;45m", c("#00ff00"): "\033[38;5;46m", c("#00ff5f"): "\033[38;5;47m", - c("#00ff87"): "\033[38;5;48m", c("#00ffaf"): "\033[38;5;49m", c("#00ffd7"): "\033[38;5;50m", c("#00ffff"): "\033[38;5;51m", - c("#5f0000"): "\033[38;5;52m", c("#5f005f"): "\033[38;5;53m", c("#5f0087"): "\033[38;5;54m", c("#5f00af"): "\033[38;5;55m", - c("#5f00d7"): "\033[38;5;56m", c("#5f00ff"): "\033[38;5;57m", c("#5f5f00"): "\033[38;5;58m", c("#5f5f5f"): "\033[38;5;59m", - c("#5f5f87"): "\033[38;5;60m", c("#5f5faf"): "\033[38;5;61m", c("#5f5fd7"): "\033[38;5;62m", c("#5f5fff"): "\033[38;5;63m", - c("#5f8700"): "\033[38;5;64m", c("#5f875f"): "\033[38;5;65m", c("#5f8787"): "\033[38;5;66m", c("#5f87af"): "\033[38;5;67m", - c("#5f87d7"): "\033[38;5;68m", c("#5f87ff"): "\033[38;5;69m", c("#5faf00"): "\033[38;5;70m", c("#5faf5f"): "\033[38;5;71m", - c("#5faf87"): "\033[38;5;72m", c("#5fafaf"): "\033[38;5;73m", c("#5fafd7"): "\033[38;5;74m", c("#5fafff"): "\033[38;5;75m", - c("#5fd700"): "\033[38;5;76m", c("#5fd75f"): "\033[38;5;77m", c("#5fd787"): "\033[38;5;78m", c("#5fd7af"): "\033[38;5;79m", - c("#5fd7d7"): "\033[38;5;80m", c("#5fd7ff"): "\033[38;5;81m", c("#5fff00"): "\033[38;5;82m", c("#5fff5f"): "\033[38;5;83m", - c("#5fff87"): "\033[38;5;84m", c("#5fffaf"): "\033[38;5;85m", c("#5fffd7"): "\033[38;5;86m", c("#5fffff"): "\033[38;5;87m", - c("#870000"): "\033[38;5;88m", c("#87005f"): "\033[38;5;89m", c("#870087"): "\033[38;5;90m", c("#8700af"): "\033[38;5;91m", - c("#8700d7"): "\033[38;5;92m", c("#8700ff"): "\033[38;5;93m", c("#875f00"): "\033[38;5;94m", c("#875f5f"): "\033[38;5;95m", - c("#875f87"): "\033[38;5;96m", c("#875faf"): "\033[38;5;97m", c("#875fd7"): "\033[38;5;98m", c("#875fff"): "\033[38;5;99m", - c("#878700"): "\033[38;5;100m", c("#87875f"): "\033[38;5;101m", c("#878787"): "\033[38;5;102m", c("#8787af"): "\033[38;5;103m", - c("#8787d7"): "\033[38;5;104m", c("#8787ff"): "\033[38;5;105m", c("#87af00"): "\033[38;5;106m", c("#87af5f"): "\033[38;5;107m", - c("#87af87"): "\033[38;5;108m", c("#87afaf"): "\033[38;5;109m", c("#87afd7"): "\033[38;5;110m", c("#87afff"): "\033[38;5;111m", - c("#87d700"): "\033[38;5;112m", c("#87d75f"): "\033[38;5;113m", c("#87d787"): "\033[38;5;114m", c("#87d7af"): "\033[38;5;115m", - c("#87d7d7"): "\033[38;5;116m", c("#87d7ff"): "\033[38;5;117m", c("#87ff00"): "\033[38;5;118m", c("#87ff5f"): "\033[38;5;119m", - c("#87ff87"): "\033[38;5;120m", c("#87ffaf"): "\033[38;5;121m", c("#87ffd7"): "\033[38;5;122m", c("#87ffff"): "\033[38;5;123m", - c("#af0000"): "\033[38;5;124m", c("#af005f"): "\033[38;5;125m", c("#af0087"): "\033[38;5;126m", c("#af00af"): "\033[38;5;127m", - c("#af00d7"): "\033[38;5;128m", c("#af00ff"): "\033[38;5;129m", c("#af5f00"): "\033[38;5;130m", c("#af5f5f"): "\033[38;5;131m", - c("#af5f87"): "\033[38;5;132m", c("#af5faf"): "\033[38;5;133m", c("#af5fd7"): "\033[38;5;134m", c("#af5fff"): "\033[38;5;135m", - c("#af8700"): "\033[38;5;136m", c("#af875f"): "\033[38;5;137m", c("#af8787"): "\033[38;5;138m", c("#af87af"): "\033[38;5;139m", - c("#af87d7"): "\033[38;5;140m", c("#af87ff"): "\033[38;5;141m", c("#afaf00"): "\033[38;5;142m", c("#afaf5f"): "\033[38;5;143m", - c("#afaf87"): "\033[38;5;144m", c("#afafaf"): "\033[38;5;145m", c("#afafd7"): "\033[38;5;146m", c("#afafff"): "\033[38;5;147m", - c("#afd700"): "\033[38;5;148m", c("#afd75f"): "\033[38;5;149m", c("#afd787"): "\033[38;5;150m", c("#afd7af"): "\033[38;5;151m", - c("#afd7d7"): "\033[38;5;152m", c("#afd7ff"): "\033[38;5;153m", c("#afff00"): "\033[38;5;154m", c("#afff5f"): "\033[38;5;155m", - c("#afff87"): "\033[38;5;156m", c("#afffaf"): "\033[38;5;157m", c("#afffd7"): "\033[38;5;158m", c("#afffff"): "\033[38;5;159m", - c("#d70000"): "\033[38;5;160m", c("#d7005f"): "\033[38;5;161m", c("#d70087"): "\033[38;5;162m", c("#d700af"): "\033[38;5;163m", - c("#d700d7"): "\033[38;5;164m", c("#d700ff"): "\033[38;5;165m", c("#d75f00"): "\033[38;5;166m", c("#d75f5f"): "\033[38;5;167m", - c("#d75f87"): "\033[38;5;168m", c("#d75faf"): "\033[38;5;169m", c("#d75fd7"): "\033[38;5;170m", c("#d75fff"): "\033[38;5;171m", - c("#d78700"): "\033[38;5;172m", c("#d7875f"): "\033[38;5;173m", c("#d78787"): "\033[38;5;174m", c("#d787af"): "\033[38;5;175m", - c("#d787d7"): "\033[38;5;176m", c("#d787ff"): "\033[38;5;177m", c("#d7af00"): "\033[38;5;178m", c("#d7af5f"): "\033[38;5;179m", - c("#d7af87"): "\033[38;5;180m", c("#d7afaf"): "\033[38;5;181m", c("#d7afd7"): "\033[38;5;182m", c("#d7afff"): "\033[38;5;183m", - c("#d7d700"): "\033[38;5;184m", c("#d7d75f"): "\033[38;5;185m", c("#d7d787"): "\033[38;5;186m", c("#d7d7af"): "\033[38;5;187m", - c("#d7d7d7"): "\033[38;5;188m", c("#d7d7ff"): "\033[38;5;189m", c("#d7ff00"): "\033[38;5;190m", c("#d7ff5f"): "\033[38;5;191m", - c("#d7ff87"): "\033[38;5;192m", c("#d7ffaf"): "\033[38;5;193m", c("#d7ffd7"): "\033[38;5;194m", c("#d7ffff"): "\033[38;5;195m", - c("#ff0000"): "\033[38;5;196m", c("#ff005f"): "\033[38;5;197m", c("#ff0087"): "\033[38;5;198m", c("#ff00af"): "\033[38;5;199m", - c("#ff00d7"): "\033[38;5;200m", c("#ff00ff"): "\033[38;5;201m", c("#ff5f00"): "\033[38;5;202m", c("#ff5f5f"): "\033[38;5;203m", - c("#ff5f87"): "\033[38;5;204m", c("#ff5faf"): "\033[38;5;205m", c("#ff5fd7"): "\033[38;5;206m", c("#ff5fff"): "\033[38;5;207m", - c("#ff8700"): "\033[38;5;208m", c("#ff875f"): "\033[38;5;209m", c("#ff8787"): "\033[38;5;210m", c("#ff87af"): "\033[38;5;211m", - c("#ff87d7"): "\033[38;5;212m", c("#ff87ff"): "\033[38;5;213m", c("#ffaf00"): "\033[38;5;214m", c("#ffaf5f"): "\033[38;5;215m", - c("#ffaf87"): "\033[38;5;216m", c("#ffafaf"): "\033[38;5;217m", c("#ffafd7"): "\033[38;5;218m", c("#ffafff"): "\033[38;5;219m", - c("#ffd700"): "\033[38;5;220m", c("#ffd75f"): "\033[38;5;221m", c("#ffd787"): "\033[38;5;222m", c("#ffd7af"): "\033[38;5;223m", - c("#ffd7d7"): "\033[38;5;224m", c("#ffd7ff"): "\033[38;5;225m", c("#ffff00"): "\033[38;5;226m", c("#ffff5f"): "\033[38;5;227m", - c("#ffff87"): "\033[38;5;228m", c("#ffffaf"): "\033[38;5;229m", c("#ffffd7"): "\033[38;5;230m", c("#ffffff"): "\033[38;5;231m", - c("#080808"): "\033[38;5;232m", c("#121212"): "\033[38;5;233m", c("#1c1c1c"): "\033[38;5;234m", c("#262626"): "\033[38;5;235m", - c("#303030"): "\033[38;5;236m", c("#3a3a3a"): "\033[38;5;237m", c("#444444"): "\033[38;5;238m", c("#4e4e4e"): "\033[38;5;239m", - c("#585858"): "\033[38;5;240m", c("#626262"): "\033[38;5;241m", c("#6c6c6c"): "\033[38;5;242m", c("#767676"): "\033[38;5;243m", - c("#808080"): "\033[38;5;244m", c("#8a8a8a"): "\033[38;5;245m", c("#949494"): "\033[38;5;246m", c("#9e9e9e"): "\033[38;5;247m", - c("#a8a8a8"): "\033[38;5;248m", c("#b2b2b2"): "\033[38;5;249m", c("#bcbcbc"): "\033[38;5;250m", c("#c6c6c6"): "\033[38;5;251m", - c("#d0d0d0"): "\033[38;5;252m", c("#dadada"): "\033[38;5;253m", c("#e4e4e4"): "\033[38;5;254m", c("#eeeeee"): "\033[38;5;255m", - }, - background: map[chroma.Colour]string{ - c("#000000"): "\033[48;5;0m", c("#800000"): "\033[48;5;1m", c("#008000"): "\033[48;5;2m", c("#808000"): "\033[48;5;3m", - c("#000080"): "\033[48;5;4m", c("#800080"): "\033[48;5;5m", c("#008080"): "\033[48;5;6m", c("#c0c0c0"): "\033[48;5;7m", - c("#808080"): "\033[48;5;8m", c("#ff0000"): "\033[48;5;9m", c("#00ff00"): "\033[48;5;10m", c("#ffff00"): "\033[48;5;11m", - c("#0000ff"): "\033[48;5;12m", c("#ff00ff"): "\033[48;5;13m", c("#00ffff"): "\033[48;5;14m", c("#ffffff"): "\033[48;5;15m", - c("#000000"): "\033[48;5;16m", c("#00005f"): "\033[48;5;17m", c("#000087"): "\033[48;5;18m", c("#0000af"): "\033[48;5;19m", - c("#0000d7"): "\033[48;5;20m", c("#0000ff"): "\033[48;5;21m", c("#005f00"): "\033[48;5;22m", c("#005f5f"): "\033[48;5;23m", - c("#005f87"): "\033[48;5;24m", c("#005faf"): "\033[48;5;25m", c("#005fd7"): "\033[48;5;26m", c("#005fff"): "\033[48;5;27m", - c("#008700"): "\033[48;5;28m", c("#00875f"): "\033[48;5;29m", c("#008787"): "\033[48;5;30m", c("#0087af"): "\033[48;5;31m", - c("#0087d7"): "\033[48;5;32m", c("#0087ff"): "\033[48;5;33m", c("#00af00"): "\033[48;5;34m", c("#00af5f"): "\033[48;5;35m", - c("#00af87"): "\033[48;5;36m", c("#00afaf"): "\033[48;5;37m", c("#00afd7"): "\033[48;5;38m", c("#00afff"): "\033[48;5;39m", - c("#00d700"): "\033[48;5;40m", c("#00d75f"): "\033[48;5;41m", c("#00d787"): "\033[48;5;42m", c("#00d7af"): "\033[48;5;43m", - c("#00d7d7"): "\033[48;5;44m", c("#00d7ff"): "\033[48;5;45m", c("#00ff00"): "\033[48;5;46m", c("#00ff5f"): "\033[48;5;47m", - c("#00ff87"): "\033[48;5;48m", c("#00ffaf"): "\033[48;5;49m", c("#00ffd7"): "\033[48;5;50m", c("#00ffff"): "\033[48;5;51m", - c("#5f0000"): "\033[48;5;52m", c("#5f005f"): "\033[48;5;53m", c("#5f0087"): "\033[48;5;54m", c("#5f00af"): "\033[48;5;55m", - c("#5f00d7"): "\033[48;5;56m", c("#5f00ff"): "\033[48;5;57m", c("#5f5f00"): "\033[48;5;58m", c("#5f5f5f"): "\033[48;5;59m", - c("#5f5f87"): "\033[48;5;60m", c("#5f5faf"): "\033[48;5;61m", c("#5f5fd7"): "\033[48;5;62m", c("#5f5fff"): "\033[48;5;63m", - c("#5f8700"): "\033[48;5;64m", c("#5f875f"): "\033[48;5;65m", c("#5f8787"): "\033[48;5;66m", c("#5f87af"): "\033[48;5;67m", - c("#5f87d7"): "\033[48;5;68m", c("#5f87ff"): "\033[48;5;69m", c("#5faf00"): "\033[48;5;70m", c("#5faf5f"): "\033[48;5;71m", - c("#5faf87"): "\033[48;5;72m", c("#5fafaf"): "\033[48;5;73m", c("#5fafd7"): "\033[48;5;74m", c("#5fafff"): "\033[48;5;75m", - c("#5fd700"): "\033[48;5;76m", c("#5fd75f"): "\033[48;5;77m", c("#5fd787"): "\033[48;5;78m", c("#5fd7af"): "\033[48;5;79m", - c("#5fd7d7"): "\033[48;5;80m", c("#5fd7ff"): "\033[48;5;81m", c("#5fff00"): "\033[48;5;82m", c("#5fff5f"): "\033[48;5;83m", - c("#5fff87"): "\033[48;5;84m", c("#5fffaf"): "\033[48;5;85m", c("#5fffd7"): "\033[48;5;86m", c("#5fffff"): "\033[48;5;87m", - c("#870000"): "\033[48;5;88m", c("#87005f"): "\033[48;5;89m", c("#870087"): "\033[48;5;90m", c("#8700af"): "\033[48;5;91m", - c("#8700d7"): "\033[48;5;92m", c("#8700ff"): "\033[48;5;93m", c("#875f00"): "\033[48;5;94m", c("#875f5f"): "\033[48;5;95m", - c("#875f87"): "\033[48;5;96m", c("#875faf"): "\033[48;5;97m", c("#875fd7"): "\033[48;5;98m", c("#875fff"): "\033[48;5;99m", - c("#878700"): "\033[48;5;100m", c("#87875f"): "\033[48;5;101m", c("#878787"): "\033[48;5;102m", c("#8787af"): "\033[48;5;103m", - c("#8787d7"): "\033[48;5;104m", c("#8787ff"): "\033[48;5;105m", c("#87af00"): "\033[48;5;106m", c("#87af5f"): "\033[48;5;107m", - c("#87af87"): "\033[48;5;108m", c("#87afaf"): "\033[48;5;109m", c("#87afd7"): "\033[48;5;110m", c("#87afff"): "\033[48;5;111m", - c("#87d700"): "\033[48;5;112m", c("#87d75f"): "\033[48;5;113m", c("#87d787"): "\033[48;5;114m", c("#87d7af"): "\033[48;5;115m", - c("#87d7d7"): "\033[48;5;116m", c("#87d7ff"): "\033[48;5;117m", c("#87ff00"): "\033[48;5;118m", c("#87ff5f"): "\033[48;5;119m", - c("#87ff87"): "\033[48;5;120m", c("#87ffaf"): "\033[48;5;121m", c("#87ffd7"): "\033[48;5;122m", c("#87ffff"): "\033[48;5;123m", - c("#af0000"): "\033[48;5;124m", c("#af005f"): "\033[48;5;125m", c("#af0087"): "\033[48;5;126m", c("#af00af"): "\033[48;5;127m", - c("#af00d7"): "\033[48;5;128m", c("#af00ff"): "\033[48;5;129m", c("#af5f00"): "\033[48;5;130m", c("#af5f5f"): "\033[48;5;131m", - c("#af5f87"): "\033[48;5;132m", c("#af5faf"): "\033[48;5;133m", c("#af5fd7"): "\033[48;5;134m", c("#af5fff"): "\033[48;5;135m", - c("#af8700"): "\033[48;5;136m", c("#af875f"): "\033[48;5;137m", c("#af8787"): "\033[48;5;138m", c("#af87af"): "\033[48;5;139m", - c("#af87d7"): "\033[48;5;140m", c("#af87ff"): "\033[48;5;141m", c("#afaf00"): "\033[48;5;142m", c("#afaf5f"): "\033[48;5;143m", - c("#afaf87"): "\033[48;5;144m", c("#afafaf"): "\033[48;5;145m", c("#afafd7"): "\033[48;5;146m", c("#afafff"): "\033[48;5;147m", - c("#afd700"): "\033[48;5;148m", c("#afd75f"): "\033[48;5;149m", c("#afd787"): "\033[48;5;150m", c("#afd7af"): "\033[48;5;151m", - c("#afd7d7"): "\033[48;5;152m", c("#afd7ff"): "\033[48;5;153m", c("#afff00"): "\033[48;5;154m", c("#afff5f"): "\033[48;5;155m", - c("#afff87"): "\033[48;5;156m", c("#afffaf"): "\033[48;5;157m", c("#afffd7"): "\033[48;5;158m", c("#afffff"): "\033[48;5;159m", - c("#d70000"): "\033[48;5;160m", c("#d7005f"): "\033[48;5;161m", c("#d70087"): "\033[48;5;162m", c("#d700af"): "\033[48;5;163m", - c("#d700d7"): "\033[48;5;164m", c("#d700ff"): "\033[48;5;165m", c("#d75f00"): "\033[48;5;166m", c("#d75f5f"): "\033[48;5;167m", - c("#d75f87"): "\033[48;5;168m", c("#d75faf"): "\033[48;5;169m", c("#d75fd7"): "\033[48;5;170m", c("#d75fff"): "\033[48;5;171m", - c("#d78700"): "\033[48;5;172m", c("#d7875f"): "\033[48;5;173m", c("#d78787"): "\033[48;5;174m", c("#d787af"): "\033[48;5;175m", - c("#d787d7"): "\033[48;5;176m", c("#d787ff"): "\033[48;5;177m", c("#d7af00"): "\033[48;5;178m", c("#d7af5f"): "\033[48;5;179m", - c("#d7af87"): "\033[48;5;180m", c("#d7afaf"): "\033[48;5;181m", c("#d7afd7"): "\033[48;5;182m", c("#d7afff"): "\033[48;5;183m", - c("#d7d700"): "\033[48;5;184m", c("#d7d75f"): "\033[48;5;185m", c("#d7d787"): "\033[48;5;186m", c("#d7d7af"): "\033[48;5;187m", - c("#d7d7d7"): "\033[48;5;188m", c("#d7d7ff"): "\033[48;5;189m", c("#d7ff00"): "\033[48;5;190m", c("#d7ff5f"): "\033[48;5;191m", - c("#d7ff87"): "\033[48;5;192m", c("#d7ffaf"): "\033[48;5;193m", c("#d7ffd7"): "\033[48;5;194m", c("#d7ffff"): "\033[48;5;195m", - c("#ff0000"): "\033[48;5;196m", c("#ff005f"): "\033[48;5;197m", c("#ff0087"): "\033[48;5;198m", c("#ff00af"): "\033[48;5;199m", - c("#ff00d7"): "\033[48;5;200m", c("#ff00ff"): "\033[48;5;201m", c("#ff5f00"): "\033[48;5;202m", c("#ff5f5f"): "\033[48;5;203m", - c("#ff5f87"): "\033[48;5;204m", c("#ff5faf"): "\033[48;5;205m", c("#ff5fd7"): "\033[48;5;206m", c("#ff5fff"): "\033[48;5;207m", - c("#ff8700"): "\033[48;5;208m", c("#ff875f"): "\033[48;5;209m", c("#ff8787"): "\033[48;5;210m", c("#ff87af"): "\033[48;5;211m", - c("#ff87d7"): "\033[48;5;212m", c("#ff87ff"): "\033[48;5;213m", c("#ffaf00"): "\033[48;5;214m", c("#ffaf5f"): "\033[48;5;215m", - c("#ffaf87"): "\033[48;5;216m", c("#ffafaf"): "\033[48;5;217m", c("#ffafd7"): "\033[48;5;218m", c("#ffafff"): "\033[48;5;219m", - c("#ffd700"): "\033[48;5;220m", c("#ffd75f"): "\033[48;5;221m", c("#ffd787"): "\033[48;5;222m", c("#ffd7af"): "\033[48;5;223m", - c("#ffd7d7"): "\033[48;5;224m", c("#ffd7ff"): "\033[48;5;225m", c("#ffff00"): "\033[48;5;226m", c("#ffff5f"): "\033[48;5;227m", - c("#ffff87"): "\033[48;5;228m", c("#ffffaf"): "\033[48;5;229m", c("#ffffd7"): "\033[48;5;230m", c("#ffffff"): "\033[48;5;231m", - c("#080808"): "\033[48;5;232m", c("#121212"): "\033[48;5;233m", c("#1c1c1c"): "\033[48;5;234m", c("#262626"): "\033[48;5;235m", - c("#303030"): "\033[48;5;236m", c("#3a3a3a"): "\033[48;5;237m", c("#444444"): "\033[48;5;238m", c("#4e4e4e"): "\033[48;5;239m", - c("#585858"): "\033[48;5;240m", c("#626262"): "\033[48;5;241m", c("#6c6c6c"): "\033[48;5;242m", c("#767676"): "\033[48;5;243m", - c("#808080"): "\033[48;5;244m", c("#8a8a8a"): "\033[48;5;245m", c("#949494"): "\033[48;5;246m", c("#9e9e9e"): "\033[48;5;247m", - c("#a8a8a8"): "\033[48;5;248m", c("#b2b2b2"): "\033[48;5;249m", c("#bcbcbc"): "\033[48;5;250m", c("#c6c6c6"): "\033[48;5;251m", - c("#d0d0d0"): "\033[48;5;252m", c("#dadada"): "\033[48;5;253m", c("#e4e4e4"): "\033[48;5;254m", c("#eeeeee"): "\033[48;5;255m", - }, - }, -} - -func entryToEscapeSequence(table *ttyTable, entry chroma.StyleEntry) string { - out := "" - if entry.Bold == chroma.Yes { - out += "\033[1m" - } - if entry.Underline == chroma.Yes { - out += "\033[4m" - } - if entry.Italic == chroma.Yes { - out += "\033[3m" - } - if entry.Colour.IsSet() { - out += table.foreground[findClosest(table, entry.Colour)] - } - if entry.Background.IsSet() { - out += table.background[findClosest(table, entry.Background)] - } - return out -} - -func findClosest(table *ttyTable, seeking chroma.Colour) chroma.Colour { - closestColour := chroma.Colour(0) - closest := float64(math.MaxFloat64) - for colour := range table.foreground { - distance := colour.Distance(seeking) - if distance < closest { - closest = distance - closestColour = colour - } - } - return closestColour -} - -func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.TokenType]string { - style = clearBackground(style) - out := map[chroma.TokenType]string{} - for _, ttype := range style.Types() { - entry := style.Get(ttype) - out[ttype] = entryToEscapeSequence(table, entry) - } - return out -} - -// Clear the background colour. -func clearBackground(style *chroma.Style) *chroma.Style { - builder := style.Builder() - bg := builder.Get(chroma.Background) - bg.Background = 0 - bg.NoInherit = true - builder.AddEntry(chroma.Background, bg) - style, _ = builder.Build() - return style -} - -type indexedTTYFormatter struct { - table *ttyTable -} - -func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) { - theme := styleToEscapeSequence(c.table, style) - for token := it(); token != chroma.EOF; token = it() { - clr, ok := theme[token.Type] - - // This search mimics how styles.Get() is used in tty_truecolour.go. - if !ok { - clr, ok = theme[token.Type.SubCategory()] - if !ok { - clr, ok = theme[token.Type.Category()] - if !ok { - clr, ok = theme[chroma.Text] - if !ok { - clr = theme[chroma.Background] - } - } - } - } - - if clr != "" { - fmt.Fprint(w, clr) - } - fmt.Fprint(w, token.Value) - if clr != "" { - fmt.Fprintf(w, "\033[0m") - } - } - return nil -} - -// TTY is an 8-colour terminal formatter. -// -// The Lab colour space is used to map RGB values to the most appropriate index colour. -var TTY = Register("terminal", &indexedTTYFormatter{ttyTables[8]}) - -// TTY8 is an 8-colour terminal formatter. -// -// The Lab colour space is used to map RGB values to the most appropriate index colour. -var TTY8 = Register("terminal8", &indexedTTYFormatter{ttyTables[8]}) - -// TTY16 is a 16-colour terminal formatter. -// -// It uses \033[3xm for normal colours and \033[90Xm for bright colours. -// -// The Lab colour space is used to map RGB values to the most appropriate index colour. -var TTY16 = Register("terminal16", &indexedTTYFormatter{ttyTables[16]}) - -// TTY256 is a 256-colour terminal formatter. -// -// The Lab colour space is used to map RGB values to the most appropriate index colour. -var TTY256 = Register("terminal256", &indexedTTYFormatter{ttyTables[256]}) diff --git a/vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go b/vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go deleted file mode 100644 index 7b43c6eb..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/formatters/tty_truecolour.go +++ /dev/null @@ -1,42 +0,0 @@ -package formatters - -import ( - "fmt" - "io" - - "github.com/alecthomas/chroma/v2" -) - -// TTY16m is a true-colour terminal formatter. -var TTY16m = Register("terminal16m", chroma.FormatterFunc(trueColourFormatter)) - -func trueColourFormatter(w io.Writer, style *chroma.Style, it chroma.Iterator) error { - style = clearBackground(style) - for token := it(); token != chroma.EOF; token = it() { - entry := style.Get(token.Type) - if !entry.IsZero() { - out := "" - if entry.Bold == chroma.Yes { - out += "\033[1m" - } - if entry.Underline == chroma.Yes { - out += "\033[4m" - } - if entry.Italic == chroma.Yes { - out += "\033[3m" - } - if entry.Colour.IsSet() { - out += fmt.Sprintf("\033[38;2;%d;%d;%dm", entry.Colour.Red(), entry.Colour.Green(), entry.Colour.Blue()) - } - if entry.Background.IsSet() { - out += fmt.Sprintf("\033[48;2;%d;%d;%dm", entry.Background.Red(), entry.Background.Green(), entry.Background.Blue()) - } - fmt.Fprint(w, out) - } - fmt.Fprint(w, token.Value) - if !entry.IsZero() { - fmt.Fprint(w, "\033[0m") - } - } - return nil -} diff --git a/vendor/github.com/alecthomas/chroma/v2/iterator.go b/vendor/github.com/alecthomas/chroma/v2/iterator.go deleted file mode 100644 index d5175de8..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/iterator.go +++ /dev/null @@ -1,76 +0,0 @@ -package chroma - -import "strings" - -// An Iterator across tokens. -// -// EOF will be returned at the end of the Token stream. -// -// If an error occurs within an Iterator, it may propagate this in a panic. Formatters should recover. -type Iterator func() Token - -// Tokens consumes all tokens from the iterator and returns them as a slice. -func (i Iterator) Tokens() []Token { - var out []Token - for t := i(); t != EOF; t = i() { - out = append(out, t) - } - return out -} - -// Concaterator concatenates tokens from a series of iterators. -func Concaterator(iterators ...Iterator) Iterator { - return func() Token { - for len(iterators) > 0 { - t := iterators[0]() - if t != EOF { - return t - } - iterators = iterators[1:] - } - return EOF - } -} - -// Literator converts a sequence of literal Tokens into an Iterator. -func Literator(tokens ...Token) Iterator { - return func() Token { - if len(tokens) == 0 { - return EOF - } - token := tokens[0] - tokens = tokens[1:] - return token - } -} - -// SplitTokensIntoLines splits tokens containing newlines in two. -func SplitTokensIntoLines(tokens []Token) (out [][]Token) { - var line []Token // nolint: prealloc - for _, token := range tokens { - for strings.Contains(token.Value, "\n") { - parts := strings.SplitAfterN(token.Value, "\n", 2) - // Token becomes the tail. - token.Value = parts[1] - - // Append the head to the line and flush the line. - clone := token.Clone() - clone.Value = parts[0] - line = append(line, clone) - out = append(out, line) - line = nil - } - line = append(line, token) - } - if len(line) > 0 { - out = append(out, line) - } - // Strip empty trailing token line. - if len(out) > 0 { - last := out[len(out)-1] - if len(last) == 1 && last[0].Value == "" { - out = out[:len(out)-1] - } - } - return -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexer.go b/vendor/github.com/alecthomas/chroma/v2/lexer.go deleted file mode 100644 index eb027bf6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexer.go +++ /dev/null @@ -1,162 +0,0 @@ -package chroma - -import ( - "fmt" - "strings" -) - -var ( - defaultOptions = &TokeniseOptions{ - State: "root", - EnsureLF: true, - } -) - -// Config for a lexer. -type Config struct { - // Name of the lexer. - Name string `xml:"name,omitempty"` - - // Shortcuts for the lexer - Aliases []string `xml:"alias,omitempty"` - - // File name globs - Filenames []string `xml:"filename,omitempty"` - - // Secondary file name globs - AliasFilenames []string `xml:"alias_filename,omitempty"` - - // MIME types - MimeTypes []string `xml:"mime_type,omitempty"` - - // Regex matching is case-insensitive. - CaseInsensitive bool `xml:"case_insensitive,omitempty"` - - // Regex matches all characters. - DotAll bool `xml:"dot_all,omitempty"` - - // Regex does not match across lines ($ matches EOL). - // - // Defaults to multiline. - NotMultiline bool `xml:"not_multiline,omitempty"` - - // Don't strip leading and trailing newlines from the input. - // DontStripNL bool - - // Strip all leading and trailing whitespace from the input - // StripAll bool - - // Make sure that the input ends with a newline. This - // is required for some lexers that consume input linewise. - EnsureNL bool `xml:"ensure_nl,omitempty"` - - // If given and greater than 0, expand tabs in the input. - // TabSize int - - // Priority of lexer. - // - // If this is 0 it will be treated as a default of 1. - Priority float32 `xml:"priority,omitempty"` - - // Analyse is a list of regexes to match against the input. - // - // If a match is found, the score is returned if single attribute is set to true, - // otherwise the sum of all the score of matching patterns will be - // used as the final score. - Analyse *AnalyseConfig `xml:"analyse,omitempty"` -} - -// AnalyseConfig defines the list of regexes analysers. -type AnalyseConfig struct { - Regexes []RegexConfig `xml:"regex,omitempty"` - // If true, the first matching score is returned. - First bool `xml:"first,attr"` -} - -// RegexConfig defines a single regex pattern and its score in case of match. -type RegexConfig struct { - Pattern string `xml:"pattern,attr"` - Score float32 `xml:"score,attr"` -} - -// Token output to formatter. -type Token struct { - Type TokenType `json:"type"` - Value string `json:"value"` -} - -func (t *Token) String() string { return t.Value } -func (t *Token) GoString() string { return fmt.Sprintf("&Token{%s, %q}", t.Type, t.Value) } - -// Clone returns a clone of the Token. -func (t *Token) Clone() Token { - return *t -} - -// EOF is returned by lexers at the end of input. -var EOF Token - -// TokeniseOptions contains options for tokenisers. -type TokeniseOptions struct { - // State to start tokenisation in. Defaults to "root". - State string - // Nested tokenisation. - Nested bool - - // If true, all EOLs are converted into LF - // by replacing CRLF and CR - EnsureLF bool -} - -// A Lexer for tokenising source code. -type Lexer interface { - // Config describing the features of the Lexer. - Config() *Config - // Tokenise returns an Iterator over tokens in text. - Tokenise(options *TokeniseOptions, text string) (Iterator, error) - // SetRegistry sets the registry this Lexer is associated with. - // - // The registry should be used by the Lexer if it needs to look up other - // lexers. - SetRegistry(registry *LexerRegistry) Lexer - // SetAnalyser sets a function the Lexer should use for scoring how - // likely a fragment of text is to match this lexer, between 0.0 and 1.0. - // A value of 1 indicates high confidence. - // - // Lexers may ignore this if they implement their own analysers. - SetAnalyser(analyser func(text string) float32) Lexer - // AnalyseText scores how likely a fragment of text is to match - // this lexer, between 0.0 and 1.0. A value of 1 indicates high confidence. - AnalyseText(text string) float32 -} - -// Lexers is a slice of lexers sortable by name. -type Lexers []Lexer - -func (l Lexers) Len() int { return len(l) } -func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l Lexers) Less(i, j int) bool { - return strings.ToLower(l[i].Config().Name) < strings.ToLower(l[j].Config().Name) -} - -// PrioritisedLexers is a slice of lexers sortable by priority. -type PrioritisedLexers []Lexer - -func (l PrioritisedLexers) Len() int { return len(l) } -func (l PrioritisedLexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l PrioritisedLexers) Less(i, j int) bool { - ip := l[i].Config().Priority - if ip == 0 { - ip = 1 - } - jp := l[j].Config().Priority - if jp == 0 { - jp = 1 - } - return ip > jp -} - -// Analyser determines how appropriate this lexer is for the given text. -type Analyser interface { - AnalyseText(text string) float32 -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/README.md b/vendor/github.com/alecthomas/chroma/v2/lexers/README.md deleted file mode 100644 index 60a0055a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Chroma lexers - -All lexers in Chroma should now be defined in XML unless they require custom code. - -## Lexer tests - -The tests in this directory feed a known input `testdata/.actual` into the parser for `` and check -that its output matches `.expected`. - -It is also possible to perform several tests on a same parser ``, by placing know inputs `*.actual` into a -directory `testdata//`. - -### Running the tests - -Run the tests as normal: -```go -go test ./lexers -``` - -### Update existing tests - -When you add a new test data file (`*.actual`), you need to regenerate all tests. That's how Chroma creates the `*.expected` test file based on the corresponding lexer. - -To regenerate all tests, type in your terminal: - -```go -RECORD=true go test ./lexers -``` - -This first sets the `RECORD` environment variable to `true`. Then it runs `go test` on the `./lexers` directory of the Chroma project. - -(That environment variable tells Chroma it needs to output test data. After running `go test ./lexers` you can remove or reset that variable.) - -#### Windows users - -Windows users will find that the `RECORD=true go test ./lexers` command fails in both the standard command prompt terminal and in PowerShell. - -Instead we have to perform both steps separately: - -- Set the `RECORD` environment variable to `true`. - + In the regular command prompt window, the `set` command sets an environment variable for the current session: `set RECORD=true`. See [this page](https://superuser.com/questions/212150/how-to-set-env-variable-in-windows-cmd-line) for more. - + In PowerShell, you can use the `$env:RECORD = 'true'` command for that. See [this article](https://mcpmag.com/articles/2019/03/28/environment-variables-in-powershell.aspx) for more. - + You can also make a persistent environment variable by hand in the Windows computer settings. See [this article](https://www.computerhope.com/issues/ch000549.htm) for how. -- When the environment variable is set, run `go test ./lexers`. - -Chroma will now regenerate the test files and print its results to the console window. diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go b/vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go deleted file mode 100644 index 82a7efa4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/caddyfile.go +++ /dev/null @@ -1,275 +0,0 @@ -package lexers - -import ( - . "github.com/alecthomas/chroma/v2" // nolint -) - -// Matcher token stub for docs, or -// Named matcher: @name, or -// Path matcher: /foo, or -// Wildcard path matcher: * -// nolint: gosec -var caddyfileMatcherTokenRegexp = `(\[\\]|@[^\s]+|/[^\s]+|\*)` - -// Comment at start of line, or -// Comment preceded by whitespace -var caddyfileCommentRegexp = `(^|\s+)#.*\n` - -// caddyfileCommon are the rules common to both of the lexer variants -func caddyfileCommonRules() Rules { - return Rules{ - "site_block_common": { - Include("site_body"), - // Any other directive - {`[^\s#]+`, Keyword, Push("directive")}, - Include("base"), - }, - "site_body": { - // Import keyword - {`\b(import|invoke)\b( [^\s#]+)`, ByGroups(Keyword, Text), Push("subdirective")}, - // Matcher definition - {`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")}, - // Matcher token stub for docs - {`\[\\]`, NameDecorator, Push("matcher")}, - // These cannot have matchers but may have things that look like - // matchers in their arguments, so we just parse as a subdirective. - {`\b(try_files|tls|log|bind)\b`, Keyword, Push("subdirective")}, - // These are special, they can nest more directives - {`\b(handle_errors|handle_path|handle_response|replace_status|handle|route)\b`, Keyword, Push("nested_directive")}, - // uri directive has special syntax - {`\b(uri)\b`, Keyword, Push("uri_directive")}, - }, - "matcher": { - {`\{`, Punctuation, Push("block")}, - // Not can be one-liner - {`not`, Keyword, Push("deep_not_matcher")}, - // Heredoc for CEL expression - Include("heredoc"), - // Backtick for CEL expression - {"`", StringBacktick, Push("backticks")}, - // Any other same-line matcher - {`[^\s#]+`, Keyword, Push("arguments")}, - // Terminators - {`\s*\n`, Text, Pop(1)}, - {`\}`, Punctuation, Pop(1)}, - Include("base"), - }, - "block": { - {`\}`, Punctuation, Pop(2)}, - // Using double quotes doesn't stop at spaces - {`"`, StringDouble, Push("double_quotes")}, - // Using backticks doesn't stop at spaces - {"`", StringBacktick, Push("backticks")}, - // Not can be one-liner - {`not`, Keyword, Push("not_matcher")}, - // Directives & matcher definitions - Include("site_body"), - // Any directive - {`[^\s#]+`, Keyword, Push("subdirective")}, - Include("base"), - }, - "nested_block": { - {`\}`, Punctuation, Pop(2)}, - // Using double quotes doesn't stop at spaces - {`"`, StringDouble, Push("double_quotes")}, - // Using backticks doesn't stop at spaces - {"`", StringBacktick, Push("backticks")}, - // Not can be one-liner - {`not`, Keyword, Push("not_matcher")}, - // Directives & matcher definitions - Include("site_body"), - // Any other subdirective - {`[^\s#]+`, Keyword, Push("directive")}, - Include("base"), - }, - "not_matcher": { - {`\}`, Punctuation, Pop(2)}, - {`\{(?=\s)`, Punctuation, Push("block")}, - {`[^\s#]+`, Keyword, Push("arguments")}, - {`\s+`, Text, nil}, - }, - "deep_not_matcher": { - {`\}`, Punctuation, Pop(2)}, - {`\{(?=\s)`, Punctuation, Push("block")}, - {`[^\s#]+`, Keyword, Push("deep_subdirective")}, - {`\s+`, Text, nil}, - }, - "directive": { - {`\{(?=\s)`, Punctuation, Push("block")}, - {caddyfileMatcherTokenRegexp, NameDecorator, Push("arguments")}, - {caddyfileCommentRegexp, CommentSingle, Pop(1)}, - {`\s*\n`, Text, Pop(1)}, - Include("base"), - }, - "nested_directive": { - {`\{(?=\s)`, Punctuation, Push("nested_block")}, - {caddyfileMatcherTokenRegexp, NameDecorator, Push("nested_arguments")}, - {caddyfileCommentRegexp, CommentSingle, Pop(1)}, - {`\s*\n`, Text, Pop(1)}, - Include("base"), - }, - "subdirective": { - {`\{(?=\s)`, Punctuation, Push("block")}, - {caddyfileCommentRegexp, CommentSingle, Pop(1)}, - {`\s*\n`, Text, Pop(1)}, - Include("base"), - }, - "arguments": { - {`\{(?=\s)`, Punctuation, Push("block")}, - {caddyfileCommentRegexp, CommentSingle, Pop(2)}, - {`\\\n`, Text, nil}, // Skip escaped newlines - {`\s*\n`, Text, Pop(2)}, - Include("base"), - }, - "nested_arguments": { - {`\{(?=\s)`, Punctuation, Push("nested_block")}, - {caddyfileCommentRegexp, CommentSingle, Pop(2)}, - {`\\\n`, Text, nil}, // Skip escaped newlines - {`\s*\n`, Text, Pop(2)}, - Include("base"), - }, - "deep_subdirective": { - {`\{(?=\s)`, Punctuation, Push("block")}, - {caddyfileCommentRegexp, CommentSingle, Pop(3)}, - {`\s*\n`, Text, Pop(3)}, - Include("base"), - }, - "uri_directive": { - {`\{(?=\s)`, Punctuation, Push("block")}, - {caddyfileMatcherTokenRegexp, NameDecorator, nil}, - {`(strip_prefix|strip_suffix|replace|path_regexp)`, NameConstant, Push("arguments")}, - {caddyfileCommentRegexp, CommentSingle, Pop(1)}, - {`\s*\n`, Text, Pop(1)}, - Include("base"), - }, - "double_quotes": { - Include("placeholder"), - {`\\"`, StringDouble, nil}, - {`[^"]`, StringDouble, nil}, - {`"`, StringDouble, Pop(1)}, - }, - "backticks": { - Include("placeholder"), - {"\\\\`", StringBacktick, nil}, - {"[^`]", StringBacktick, nil}, - {"`", StringBacktick, Pop(1)}, - }, - "optional": { - // Docs syntax for showing optional parts with [ ] - {`\[`, Punctuation, Push("optional")}, - Include("name_constants"), - {`\|`, Punctuation, nil}, - {`[^\[\]\|]+`, String, nil}, - {`\]`, Punctuation, Pop(1)}, - }, - "heredoc": { - {`(<<([a-zA-Z0-9_-]+))(\n(.*|\n)*)(\s*)(\2)`, ByGroups(StringHeredoc, nil, String, String, String, StringHeredoc), nil}, - }, - "name_constants": { - {`\b(most_recently_modified|largest_size|smallest_size|first_exist|internal|disable_redirects|ignore_loaded_certs|disable_certs|private_ranges|first|last|before|after|on|off)\b(\||(?=\]|\s|$))`, ByGroups(NameConstant, Punctuation), nil}, - }, - "placeholder": { - // Placeholder with dots, colon for default value, brackets for args[0:] - {`\{[\w+.\[\]\:\$-]+\}`, StringEscape, nil}, - // Handle opening brackets with no matching closing one - {`\{[^\}\s]*\b`, String, nil}, - }, - "base": { - {caddyfileCommentRegexp, CommentSingle, nil}, - {`\[\\]`, NameDecorator, nil}, - Include("name_constants"), - Include("heredoc"), - {`(https?://)?([a-z0-9.-]+)(:)([0-9]+)([^\s]*)`, ByGroups(Name, Name, Punctuation, NumberInteger, Name), nil}, - {`\[`, Punctuation, Push("optional")}, - {"`", StringBacktick, Push("backticks")}, - {`"`, StringDouble, Push("double_quotes")}, - Include("placeholder"), - {`[a-z-]+/[a-z-+]+`, String, nil}, - {`[0-9]+([smhdk]|ns|us|µs|ms)?\b`, NumberInteger, nil}, - {`[^\s\n#\{]+`, String, nil}, - {`/[^\s#]*`, Name, nil}, - {`\s+`, Text, nil}, - }, - } -} - -// Caddyfile lexer. -var Caddyfile = Register(MustNewLexer( - &Config{ - Name: "Caddyfile", - Aliases: []string{"caddyfile", "caddy"}, - Filenames: []string{"Caddyfile*"}, - MimeTypes: []string{}, - }, - caddyfileRules, -)) - -func caddyfileRules() Rules { - return Rules{ - "root": { - {caddyfileCommentRegexp, CommentSingle, nil}, - // Global options block - {`^\s*(\{)\s*$`, ByGroups(Punctuation), Push("globals")}, - // Top level import - {`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil}, - // Snippets - {`(&?\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")}, - // Site label - {`[^#{(\s,]+`, GenericHeading, Push("label")}, - // Site label with placeholder - {`\{[\w+.\[\]\:\$-]+\}`, StringEscape, Push("label")}, - {`\s+`, Text, nil}, - }, - "globals": { - {`\}`, Punctuation, Pop(1)}, - // Global options are parsed as subdirectives (no matcher) - {`[^\s#]+`, Keyword, Push("subdirective")}, - Include("base"), - }, - "snippet": { - {`\}`, Punctuation, Pop(1)}, - Include("site_body"), - // Any other directive - {`[^\s#]+`, Keyword, Push("directive")}, - Include("base"), - }, - "label": { - // Allow multiple labels, comma separated, newlines after - // a comma means another label is coming - {`,\s*\n?`, Text, nil}, - {` `, Text, nil}, - // Site label with placeholder - Include("placeholder"), - // Site label - {`[^#{(\s,]+`, GenericHeading, nil}, - // Comment after non-block label (hack because comments end in \n) - {`#.*\n`, CommentSingle, Push("site_block")}, - // Note: if \n, we'll never pop out of the site_block, it's valid - {`\{(?=\s)|\n`, Punctuation, Push("site_block")}, - }, - "site_block": { - {`\}`, Punctuation, Pop(2)}, - Include("site_block_common"), - }, - }.Merge(caddyfileCommonRules()) -} - -// Caddyfile directive-only lexer. -var CaddyfileDirectives = Register(MustNewLexer( - &Config{ - Name: "Caddyfile Directives", - Aliases: []string{"caddyfile-directives", "caddyfile-d", "caddy-d"}, - Filenames: []string{}, - MimeTypes: []string{}, - }, - caddyfileDirectivesRules, -)) - -func caddyfileDirectivesRules() Rules { - return Rules{ - // Same as "site_block" in Caddyfile - "root": { - Include("site_block_common"), - }, - }.Merge(caddyfileCommonRules()) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/cl.go b/vendor/github.com/alecthomas/chroma/v2/lexers/cl.go deleted file mode 100644 index 3eb0c230..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/cl.go +++ /dev/null @@ -1,243 +0,0 @@ -package lexers - -import ( - . "github.com/alecthomas/chroma/v2" // nolint -) - -var ( - clBuiltinFunctions = []string{ - "<", "<=", "=", ">", ">=", "-", "/", "/=", "*", "+", "1-", "1+", - "abort", "abs", "acons", "acos", "acosh", "add-method", "adjoin", - "adjustable-array-p", "adjust-array", "allocate-instance", - "alpha-char-p", "alphanumericp", "append", "apply", "apropos", - "apropos-list", "aref", "arithmetic-error-operands", - "arithmetic-error-operation", "array-dimension", "array-dimensions", - "array-displacement", "array-element-type", "array-has-fill-pointer-p", - "array-in-bounds-p", "arrayp", "array-rank", "array-row-major-index", - "array-total-size", "ash", "asin", "asinh", "assoc", "assoc-if", - "assoc-if-not", "atan", "atanh", "atom", "bit", "bit-and", "bit-andc1", - "bit-andc2", "bit-eqv", "bit-ior", "bit-nand", "bit-nor", "bit-not", - "bit-orc1", "bit-orc2", "bit-vector-p", "bit-xor", "boole", - "both-case-p", "boundp", "break", "broadcast-stream-streams", - "butlast", "byte", "byte-position", "byte-size", "caaaar", "caaadr", - "caaar", "caadar", "caaddr", "caadr", "caar", "cadaar", "cadadr", - "cadar", "caddar", "cadddr", "caddr", "cadr", "call-next-method", "car", - "cdaaar", "cdaadr", "cdaar", "cdadar", "cdaddr", "cdadr", "cdar", - "cddaar", "cddadr", "cddar", "cdddar", "cddddr", "cdddr", "cddr", "cdr", - "ceiling", "cell-error-name", "cerror", "change-class", "char", "char<", - "char<=", "char=", "char>", "char>=", "char/=", "character", - "characterp", "char-code", "char-downcase", "char-equal", - "char-greaterp", "char-int", "char-lessp", "char-name", - "char-not-equal", "char-not-greaterp", "char-not-lessp", "char-upcase", - "cis", "class-name", "class-of", "clear-input", "clear-output", - "close", "clrhash", "code-char", "coerce", "compile", - "compiled-function-p", "compile-file", "compile-file-pathname", - "compiler-macro-function", "complement", "complex", "complexp", - "compute-applicable-methods", "compute-restarts", "concatenate", - "concatenated-stream-streams", "conjugate", "cons", "consp", - "constantly", "constantp", "continue", "copy-alist", "copy-list", - "copy-pprint-dispatch", "copy-readtable", "copy-seq", "copy-structure", - "copy-symbol", "copy-tree", "cos", "cosh", "count", "count-if", - "count-if-not", "decode-float", "decode-universal-time", "delete", - "delete-duplicates", "delete-file", "delete-if", "delete-if-not", - "delete-package", "denominator", "deposit-field", "describe", - "describe-object", "digit-char", "digit-char-p", "directory", - "directory-namestring", "disassemble", "documentation", "dpb", - "dribble", "echo-stream-input-stream", "echo-stream-output-stream", - "ed", "eighth", "elt", "encode-universal-time", "endp", - "enough-namestring", "ensure-directories-exist", - "ensure-generic-function", "eq", "eql", "equal", "equalp", "error", - "eval", "evenp", "every", "exp", "export", "expt", "fboundp", - "fceiling", "fdefinition", "ffloor", "fifth", "file-author", - "file-error-pathname", "file-length", "file-namestring", - "file-position", "file-string-length", "file-write-date", - "fill", "fill-pointer", "find", "find-all-symbols", "find-class", - "find-if", "find-if-not", "find-method", "find-package", "find-restart", - "find-symbol", "finish-output", "first", "float", "float-digits", - "floatp", "float-precision", "float-radix", "float-sign", "floor", - "fmakunbound", "force-output", "format", "fourth", "fresh-line", - "fround", "ftruncate", "funcall", "function-keywords", - "function-lambda-expression", "functionp", "gcd", "gensym", "gentemp", - "get", "get-decoded-time", "get-dispatch-macro-character", "getf", - "gethash", "get-internal-real-time", "get-internal-run-time", - "get-macro-character", "get-output-stream-string", "get-properties", - "get-setf-expansion", "get-universal-time", "graphic-char-p", - "hash-table-count", "hash-table-p", "hash-table-rehash-size", - "hash-table-rehash-threshold", "hash-table-size", "hash-table-test", - "host-namestring", "identity", "imagpart", "import", - "initialize-instance", "input-stream-p", "inspect", - "integer-decode-float", "integer-length", "integerp", - "interactive-stream-p", "intern", "intersection", - "invalid-method-error", "invoke-debugger", "invoke-restart", - "invoke-restart-interactively", "isqrt", "keywordp", "last", "lcm", - "ldb", "ldb-test", "ldiff", "length", "lisp-implementation-type", - "lisp-implementation-version", "list", "list*", "list-all-packages", - "listen", "list-length", "listp", "load", - "load-logical-pathname-translations", "log", "logand", "logandc1", - "logandc2", "logbitp", "logcount", "logeqv", "logical-pathname", - "logical-pathname-translations", "logior", "lognand", "lognor", - "lognot", "logorc1", "logorc2", "logtest", "logxor", "long-site-name", - "lower-case-p", "machine-instance", "machine-type", "machine-version", - "macroexpand", "macroexpand-1", "macro-function", "make-array", - "make-broadcast-stream", "make-concatenated-stream", "make-condition", - "make-dispatch-macro-character", "make-echo-stream", "make-hash-table", - "make-instance", "make-instances-obsolete", "make-list", - "make-load-form", "make-load-form-saving-slots", "make-package", - "make-pathname", "make-random-state", "make-sequence", "make-string", - "make-string-input-stream", "make-string-output-stream", "make-symbol", - "make-synonym-stream", "make-two-way-stream", "makunbound", "map", - "mapc", "mapcan", "mapcar", "mapcon", "maphash", "map-into", "mapl", - "maplist", "mask-field", "max", "member", "member-if", "member-if-not", - "merge", "merge-pathnames", "method-combination-error", - "method-qualifiers", "min", "minusp", "mismatch", "mod", - "muffle-warning", "name-char", "namestring", "nbutlast", "nconc", - "next-method-p", "nintersection", "ninth", "no-applicable-method", - "no-next-method", "not", "notany", "notevery", "nreconc", "nreverse", - "nset-difference", "nset-exclusive-or", "nstring-capitalize", - "nstring-downcase", "nstring-upcase", "nsublis", "nsubst", "nsubst-if", - "nsubst-if-not", "nsubstitute", "nsubstitute-if", "nsubstitute-if-not", - "nth", "nthcdr", "null", "numberp", "numerator", "nunion", "oddp", - "open", "open-stream-p", "output-stream-p", "package-error-package", - "package-name", "package-nicknames", "packagep", - "package-shadowing-symbols", "package-used-by-list", "package-use-list", - "pairlis", "parse-integer", "parse-namestring", "pathname", - "pathname-device", "pathname-directory", "pathname-host", - "pathname-match-p", "pathname-name", "pathnamep", "pathname-type", - "pathname-version", "peek-char", "phase", "plusp", "position", - "position-if", "position-if-not", "pprint", "pprint-dispatch", - "pprint-fill", "pprint-indent", "pprint-linear", "pprint-newline", - "pprint-tab", "pprint-tabular", "prin1", "prin1-to-string", "princ", - "princ-to-string", "print", "print-object", "probe-file", "proclaim", - "provide", "random", "random-state-p", "rassoc", "rassoc-if", - "rassoc-if-not", "rational", "rationalize", "rationalp", "read", - "read-byte", "read-char", "read-char-no-hang", "read-delimited-list", - "read-from-string", "read-line", "read-preserving-whitespace", - "read-sequence", "readtable-case", "readtablep", "realp", "realpart", - "reduce", "reinitialize-instance", "rem", "remhash", "remove", - "remove-duplicates", "remove-if", "remove-if-not", "remove-method", - "remprop", "rename-file", "rename-package", "replace", "require", - "rest", "restart-name", "revappend", "reverse", "room", "round", - "row-major-aref", "rplaca", "rplacd", "sbit", "scale-float", "schar", - "search", "second", "set", "set-difference", - "set-dispatch-macro-character", "set-exclusive-or", - "set-macro-character", "set-pprint-dispatch", "set-syntax-from-char", - "seventh", "shadow", "shadowing-import", "shared-initialize", - "short-site-name", "signal", "signum", "simple-bit-vector-p", - "simple-condition-format-arguments", "simple-condition-format-control", - "simple-string-p", "simple-vector-p", "sin", "sinh", "sixth", "sleep", - "slot-boundp", "slot-exists-p", "slot-makunbound", "slot-missing", - "slot-unbound", "slot-value", "software-type", "software-version", - "some", "sort", "special-operator-p", "sqrt", "stable-sort", - "standard-char-p", "store-value", "stream-element-type", - "stream-error-stream", "stream-external-format", "streamp", "string", - "string<", "string<=", "string=", "string>", "string>=", "string/=", - "string-capitalize", "string-downcase", "string-equal", - "string-greaterp", "string-left-trim", "string-lessp", - "string-not-equal", "string-not-greaterp", "string-not-lessp", - "stringp", "string-right-trim", "string-trim", "string-upcase", - "sublis", "subseq", "subsetp", "subst", "subst-if", "subst-if-not", - "substitute", "substitute-if", "substitute-if-not", "subtypep", "svref", - "sxhash", "symbol-function", "symbol-name", "symbolp", "symbol-package", - "symbol-plist", "symbol-value", "synonym-stream-symbol", "syntax:", - "tailp", "tan", "tanh", "tenth", "terpri", "third", - "translate-logical-pathname", "translate-pathname", "tree-equal", - "truename", "truncate", "two-way-stream-input-stream", - "two-way-stream-output-stream", "type-error-datum", - "type-error-expected-type", "type-of", "typep", "unbound-slot-instance", - "unexport", "unintern", "union", "unread-char", "unuse-package", - "update-instance-for-different-class", - "update-instance-for-redefined-class", "upgraded-array-element-type", - "upgraded-complex-part-type", "upper-case-p", "use-package", - "user-homedir-pathname", "use-value", "values", "values-list", "vector", - "vectorp", "vector-pop", "vector-push", "vector-push-extend", "warn", - "wild-pathname-p", "write", "write-byte", "write-char", "write-line", - "write-sequence", "write-string", "write-to-string", "yes-or-no-p", - "y-or-n-p", "zerop", - } - - clSpecialForms = []string{ - "block", "catch", "declare", "eval-when", "flet", "function", "go", "if", - "labels", "lambda", "let", "let*", "load-time-value", "locally", "macrolet", - "multiple-value-call", "multiple-value-prog1", "progn", "progv", "quote", - "return-from", "setq", "symbol-macrolet", "tagbody", "the", "throw", - "unwind-protect", - } - - clMacros = []string{ - "and", "assert", "call-method", "case", "ccase", "check-type", "cond", - "ctypecase", "decf", "declaim", "defclass", "defconstant", "defgeneric", - "define-compiler-macro", "define-condition", "define-method-combination", - "define-modify-macro", "define-setf-expander", "define-symbol-macro", - "defmacro", "defmethod", "defpackage", "defparameter", "defsetf", - "defstruct", "deftype", "defun", "defvar", "destructuring-bind", "do", - "do*", "do-all-symbols", "do-external-symbols", "dolist", "do-symbols", - "dotimes", "ecase", "etypecase", "formatter", "handler-bind", - "handler-case", "ignore-errors", "incf", "in-package", "lambda", "loop", - "loop-finish", "make-method", "multiple-value-bind", "multiple-value-list", - "multiple-value-setq", "nth-value", "or", "pop", - "pprint-exit-if-list-exhausted", "pprint-logical-block", "pprint-pop", - "print-unreadable-object", "prog", "prog*", "prog1", "prog2", "psetf", - "psetq", "push", "pushnew", "remf", "restart-bind", "restart-case", - "return", "rotatef", "setf", "shiftf", "step", "time", "trace", "typecase", - "unless", "untrace", "when", "with-accessors", "with-compilation-unit", - "with-condition-restarts", "with-hash-table-iterator", - "with-input-from-string", "with-open-file", "with-open-stream", - "with-output-to-string", "with-package-iterator", "with-simple-restart", - "with-slots", "with-standard-io-syntax", - } - - clLambdaListKeywords = []string{ - "&allow-other-keys", "&aux", "&body", "&environment", "&key", "&optional", - "&rest", "&whole", - } - - clDeclarations = []string{ - "dynamic-extent", "ignore", "optimize", "ftype", "inline", "special", - "ignorable", "notinline", "type", - } - - clBuiltinTypes = []string{ - "atom", "boolean", "base-char", "base-string", "bignum", "bit", - "compiled-function", "extended-char", "fixnum", "keyword", "nil", - "signed-byte", "short-float", "single-float", "double-float", "long-float", - "simple-array", "simple-base-string", "simple-bit-vector", "simple-string", - "simple-vector", "standard-char", "unsigned-byte", - - // Condition Types - "arithmetic-error", "cell-error", "condition", "control-error", - "division-by-zero", "end-of-file", "error", "file-error", - "floating-point-inexact", "floating-point-overflow", - "floating-point-underflow", "floating-point-invalid-operation", - "parse-error", "package-error", "print-not-readable", "program-error", - "reader-error", "serious-condition", "simple-condition", "simple-error", - "simple-type-error", "simple-warning", "stream-error", "storage-condition", - "style-warning", "type-error", "unbound-variable", "unbound-slot", - "undefined-function", "warning", - } - - clBuiltinClasses = []string{ - "array", "broadcast-stream", "bit-vector", "built-in-class", "character", - "class", "complex", "concatenated-stream", "cons", "echo-stream", - "file-stream", "float", "function", "generic-function", "hash-table", - "integer", "list", "logical-pathname", "method-combination", "method", - "null", "number", "package", "pathname", "ratio", "rational", "readtable", - "real", "random-state", "restart", "sequence", "standard-class", - "standard-generic-function", "standard-method", "standard-object", - "string-stream", "stream", "string", "structure-class", "structure-object", - "symbol", "synonym-stream", "t", "two-way-stream", "vector", - } -) - -// Common Lisp lexer. -var CommonLisp = Register(TypeRemappingLexer(MustNewXMLLexer( - embedded, - "embedded/common_lisp.xml", -), TypeMapping{ - {NameVariable, NameFunction, clBuiltinFunctions}, - {NameVariable, Keyword, clSpecialForms}, - {NameVariable, NameBuiltin, clMacros}, - {NameVariable, Keyword, clLambdaListKeywords}, - {NameVariable, Keyword, clDeclarations}, - {NameVariable, KeywordType, clBuiltinTypes}, - {NameVariable, NameClass, clBuiltinClasses}, -})) diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/dns.go b/vendor/github.com/alecthomas/chroma/v2/lexers/dns.go deleted file mode 100644 index 7e699622..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/dns.go +++ /dev/null @@ -1,17 +0,0 @@ -package lexers - -import ( - "regexp" -) - -// TODO(moorereason): can this be factored away? -var zoneAnalyserRe = regexp.MustCompile(`(?m)^@\s+IN\s+SOA\s+`) - -func init() { // nolint: gochecknoinits - Get("dns").SetAnalyser(func(text string) float32 { - if zoneAnalyserRe.FindString(text) != "" { - return 1.0 - } - return 0.0 - }) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/emacs.go b/vendor/github.com/alecthomas/chroma/v2/lexers/emacs.go deleted file mode 100644 index 869b0f3f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/emacs.go +++ /dev/null @@ -1,533 +0,0 @@ -package lexers - -import ( - . "github.com/alecthomas/chroma/v2" // nolint -) - -var ( - emacsMacros = []string{ - "atomic-change-group", "case", "block", "cl-block", "cl-callf", "cl-callf2", - "cl-case", "cl-decf", "cl-declaim", "cl-declare", - "cl-define-compiler-macro", "cl-defmacro", "cl-defstruct", - "cl-defsubst", "cl-deftype", "cl-defun", "cl-destructuring-bind", - "cl-do", "cl-do*", "cl-do-all-symbols", "cl-do-symbols", "cl-dolist", - "cl-dotimes", "cl-ecase", "cl-etypecase", "eval-when", "cl-eval-when", "cl-flet", - "cl-flet*", "cl-function", "cl-incf", "cl-labels", "cl-letf", - "cl-letf*", "cl-load-time-value", "cl-locally", "cl-loop", - "cl-macrolet", "cl-multiple-value-bind", "cl-multiple-value-setq", - "cl-progv", "cl-psetf", "cl-psetq", "cl-pushnew", "cl-remf", - "cl-return", "cl-return-from", "cl-rotatef", "cl-shiftf", - "cl-symbol-macrolet", "cl-tagbody", "cl-the", "cl-typecase", - "combine-after-change-calls", "condition-case-unless-debug", "decf", - "declaim", "declare", "declare-function", "def-edebug-spec", - "defadvice", "defclass", "defcustom", "defface", "defgeneric", - "defgroup", "define-advice", "define-alternatives", - "define-compiler-macro", "define-derived-mode", "define-generic-mode", - "define-global-minor-mode", "define-globalized-minor-mode", - "define-minor-mode", "define-modify-macro", - "define-obsolete-face-alias", "define-obsolete-function-alias", - "define-obsolete-variable-alias", "define-setf-expander", - "define-skeleton", "defmacro", "defmethod", "defsetf", "defstruct", - "defsubst", "deftheme", "deftype", "defun", "defvar-local", - "delay-mode-hooks", "destructuring-bind", "do", "do*", - "do-all-symbols", "do-symbols", "dolist", "dont-compile", "dotimes", - "dotimes-with-progress-reporter", "ecase", "ert-deftest", "etypecase", - "eval-and-compile", "eval-when-compile", "flet", "ignore-errors", - "incf", "labels", "lambda", "letrec", "lexical-let", "lexical-let*", - "loop", "multiple-value-bind", "multiple-value-setq", "noreturn", - "oref", "oref-default", "oset", "oset-default", "pcase", - "pcase-defmacro", "pcase-dolist", "pcase-exhaustive", "pcase-let", - "pcase-let*", "pop", "psetf", "psetq", "push", "pushnew", "remf", - "return", "rotatef", "rx", "save-match-data", "save-selected-window", - "save-window-excursion", "setf", "setq-local", "shiftf", - "track-mouse", "typecase", "unless", "use-package", "when", - "while-no-input", "with-case-table", "with-category-table", - "with-coding-priority", "with-current-buffer", "with-demoted-errors", - "with-eval-after-load", "with-file-modes", "with-local-quit", - "with-output-to-string", "with-output-to-temp-buffer", - "with-parsed-tramp-file-name", "with-selected-frame", - "with-selected-window", "with-silent-modifications", "with-slots", - "with-syntax-table", "with-temp-buffer", "with-temp-file", - "with-temp-message", "with-timeout", "with-tramp-connection-property", - "with-tramp-file-property", "with-tramp-progress-reporter", - "with-wrapper-hook", "load-time-value", "locally", "macrolet", "progv", - "return-from", - } - - emacsSpecialForms = []string{ - "and", "catch", "cond", "condition-case", "defconst", "defvar", - "function", "if", "interactive", "let", "let*", "or", "prog1", - "prog2", "progn", "quote", "save-current-buffer", "save-excursion", - "save-restriction", "setq", "setq-default", "subr-arity", - "unwind-protect", "while", - } - - emacsBuiltinFunction = []string{ - "%", "*", "+", "-", "/", "/=", "1+", "1-", "<", "<=", "=", ">", ">=", - "Snarf-documentation", "abort-recursive-edit", "abs", - "accept-process-output", "access-file", "accessible-keymaps", "acos", - "active-minibuffer-window", "add-face-text-property", - "add-name-to-file", "add-text-properties", "all-completions", - "append", "apply", "apropos-internal", "aref", "arrayp", "aset", - "ash", "asin", "assoc", "assoc-string", "assq", "atan", "atom", - "autoload", "autoload-do-load", "backtrace", "backtrace--locals", - "backtrace-debug", "backtrace-eval", "backtrace-frame", - "backward-char", "backward-prefix-chars", "barf-if-buffer-read-only", - "base64-decode-region", "base64-decode-string", - "base64-encode-region", "base64-encode-string", "beginning-of-line", - "bidi-find-overridden-directionality", "bidi-resolved-levels", - "bitmap-spec-p", "bobp", "bolp", "bool-vector", - "bool-vector-count-consecutive", "bool-vector-count-population", - "bool-vector-exclusive-or", "bool-vector-intersection", - "bool-vector-not", "bool-vector-p", "bool-vector-set-difference", - "bool-vector-subsetp", "bool-vector-union", "boundp", - "buffer-base-buffer", "buffer-chars-modified-tick", - "buffer-enable-undo", "buffer-file-name", "buffer-has-markers-at", - "buffer-list", "buffer-live-p", "buffer-local-value", - "buffer-local-variables", "buffer-modified-p", "buffer-modified-tick", - "buffer-name", "buffer-size", "buffer-string", "buffer-substring", - "buffer-substring-no-properties", "buffer-swap-text", "bufferp", - "bury-buffer-internal", "byte-code", "byte-code-function-p", - "byte-to-position", "byte-to-string", "byteorder", - "call-interactively", "call-last-kbd-macro", "call-process", - "call-process-region", "cancel-kbd-macro-events", "capitalize", - "capitalize-region", "capitalize-word", "car", "car-less-than-car", - "car-safe", "case-table-p", "category-docstring", - "category-set-mnemonics", "category-table", "category-table-p", - "ccl-execute", "ccl-execute-on-string", "ccl-program-p", "cdr", - "cdr-safe", "ceiling", "char-after", "char-before", - "char-category-set", "char-charset", "char-equal", "char-or-string-p", - "char-resolve-modifiers", "char-syntax", "char-table-extra-slot", - "char-table-p", "char-table-parent", "char-table-range", - "char-table-subtype", "char-to-string", "char-width", "characterp", - "charset-after", "charset-id-internal", "charset-plist", - "charset-priority-list", "charsetp", "check-coding-system", - "check-coding-systems-region", "clear-buffer-auto-save-failure", - "clear-charset-maps", "clear-face-cache", "clear-font-cache", - "clear-image-cache", "clear-string", "clear-this-command-keys", - "close-font", "clrhash", "coding-system-aliases", - "coding-system-base", "coding-system-eol-type", "coding-system-p", - "coding-system-plist", "coding-system-priority-list", - "coding-system-put", "color-distance", "color-gray-p", - "color-supported-p", "combine-after-change-execute", - "command-error-default-function", "command-remapping", "commandp", - "compare-buffer-substrings", "compare-strings", - "compare-window-configurations", "completing-read", - "compose-region-internal", "compose-string-internal", - "composition-get-gstring", "compute-motion", "concat", "cons", - "consp", "constrain-to-field", "continue-process", - "controlling-tty-p", "coordinates-in-window-p", "copy-alist", - "copy-category-table", "copy-file", "copy-hash-table", "copy-keymap", - "copy-marker", "copy-sequence", "copy-syntax-table", "copysign", - "cos", "current-active-maps", "current-bidi-paragraph-direction", - "current-buffer", "current-case-table", "current-column", - "current-global-map", "current-idle-time", "current-indentation", - "current-input-mode", "current-local-map", "current-message", - "current-minor-mode-maps", "current-time", "current-time-string", - "current-time-zone", "current-window-configuration", - "cygwin-convert-file-name-from-windows", - "cygwin-convert-file-name-to-windows", "daemon-initialized", - "daemonp", "dbus--init-bus", "dbus-get-unique-name", - "dbus-message-internal", "debug-timer-check", "declare-equiv-charset", - "decode-big5-char", "decode-char", "decode-coding-region", - "decode-coding-string", "decode-sjis-char", "decode-time", - "default-boundp", "default-file-modes", "default-printer-name", - "default-toplevel-value", "default-value", "define-category", - "define-charset-alias", "define-charset-internal", - "define-coding-system-alias", "define-coding-system-internal", - "define-fringe-bitmap", "define-hash-table-test", "define-key", - "define-prefix-command", "delete", - "delete-all-overlays", "delete-and-extract-region", "delete-char", - "delete-directory-internal", "delete-field", "delete-file", - "delete-frame", "delete-other-windows-internal", "delete-overlay", - "delete-process", "delete-region", "delete-terminal", - "delete-window-internal", "delq", "describe-buffer-bindings", - "describe-vector", "destroy-fringe-bitmap", "detect-coding-region", - "detect-coding-string", "ding", "directory-file-name", - "directory-files", "directory-files-and-attributes", "discard-input", - "display-supports-face-attributes-p", "do-auto-save", "documentation", - "documentation-property", "downcase", "downcase-region", - "downcase-word", "draw-string", "dump-colors", "dump-emacs", - "dump-face", "dump-frame-glyph-matrix", "dump-glyph-matrix", - "dump-glyph-row", "dump-redisplay-history", "dump-tool-bar-row", - "elt", "emacs-pid", "encode-big5-char", "encode-char", - "encode-coding-region", "encode-coding-string", "encode-sjis-char", - "encode-time", "end-kbd-macro", "end-of-line", "eobp", "eolp", "eq", - "eql", "equal", "equal-including-properties", "erase-buffer", - "error-message-string", "eval", "eval-buffer", "eval-region", - "event-convert-list", "execute-kbd-macro", "exit-recursive-edit", - "exp", "expand-file-name", "expt", "external-debugging-output", - "face-attribute-relative-p", "face-attributes-as-vector", "face-font", - "fboundp", "fceiling", "fetch-bytecode", "ffloor", - "field-beginning", "field-end", "field-string", - "field-string-no-properties", "file-accessible-directory-p", - "file-acl", "file-attributes", "file-attributes-lessp", - "file-directory-p", "file-executable-p", "file-exists-p", - "file-locked-p", "file-modes", "file-name-absolute-p", - "file-name-all-completions", "file-name-as-directory", - "file-name-completion", "file-name-directory", - "file-name-nondirectory", "file-newer-than-file-p", "file-readable-p", - "file-regular-p", "file-selinux-context", "file-symlink-p", - "file-system-info", "file-system-info", "file-writable-p", - "fillarray", "find-charset-region", "find-charset-string", - "find-coding-systems-region-internal", "find-composition-internal", - "find-file-name-handler", "find-font", "find-operation-coding-system", - "float", "float-time", "floatp", "floor", "fmakunbound", - "following-char", "font-at", "font-drive-otf", "font-face-attributes", - "font-family-list", "font-get", "font-get-glyphs", - "font-get-system-font", "font-get-system-normal-font", "font-info", - "font-match-p", "font-otf-alternates", "font-put", - "font-shape-gstring", "font-spec", "font-variation-glyphs", - "font-xlfd-name", "fontp", "fontset-font", "fontset-info", - "fontset-list", "fontset-list-all", "force-mode-line-update", - "force-window-update", "format", "format-mode-line", - "format-network-address", "format-time-string", "forward-char", - "forward-comment", "forward-line", "forward-word", - "frame-border-width", "frame-bottom-divider-width", - "frame-can-run-window-configuration-change-hook", "frame-char-height", - "frame-char-width", "frame-face-alist", "frame-first-window", - "frame-focus", "frame-font-cache", "frame-fringe-width", "frame-list", - "frame-live-p", "frame-or-buffer-changed-p", "frame-parameter", - "frame-parameters", "frame-pixel-height", "frame-pixel-width", - "frame-pointer-visible-p", "frame-right-divider-width", - "frame-root-window", "frame-scroll-bar-height", - "frame-scroll-bar-width", "frame-selected-window", "frame-terminal", - "frame-text-cols", "frame-text-height", "frame-text-lines", - "frame-text-width", "frame-total-cols", "frame-total-lines", - "frame-visible-p", "framep", "frexp", "fringe-bitmaps-at-pos", - "fround", "fset", "ftruncate", "funcall", "funcall-interactively", - "function-equal", "functionp", "gap-position", "gap-size", - "garbage-collect", "gc-status", "generate-new-buffer-name", "get", - "get-buffer", "get-buffer-create", "get-buffer-process", - "get-buffer-window", "get-byte", "get-char-property", - "get-char-property-and-overlay", "get-file-buffer", "get-file-char", - "get-internal-run-time", "get-load-suffixes", "get-pos-property", - "get-process", "get-screen-color", "get-text-property", - "get-unicode-property-internal", "get-unused-category", - "get-unused-iso-final-char", "getenv-internal", "gethash", - "gfile-add-watch", "gfile-rm-watch", "global-key-binding", - "gnutls-available-p", "gnutls-boot", "gnutls-bye", "gnutls-deinit", - "gnutls-error-fatalp", "gnutls-error-string", "gnutls-errorp", - "gnutls-get-initstage", "gnutls-peer-status", - "gnutls-peer-status-warning-describe", "goto-char", "gpm-mouse-start", - "gpm-mouse-stop", "group-gid", "group-real-gid", - "handle-save-session", "handle-switch-frame", "hash-table-count", - "hash-table-p", "hash-table-rehash-size", - "hash-table-rehash-threshold", "hash-table-size", "hash-table-test", - "hash-table-weakness", "iconify-frame", "identity", "image-flush", - "image-mask-p", "image-metadata", "image-size", "imagemagick-types", - "imagep", "indent-to", "indirect-function", "indirect-variable", - "init-image-library", "inotify-add-watch", "inotify-rm-watch", - "input-pending-p", "insert", "insert-and-inherit", - "insert-before-markers", "insert-before-markers-and-inherit", - "insert-buffer-substring", "insert-byte", "insert-char", - "insert-file-contents", "insert-startup-screen", "int86", - "integer-or-marker-p", "integerp", "interactive-form", "intern", - "intern-soft", "internal--track-mouse", "internal-char-font", - "internal-complete-buffer", "internal-copy-lisp-face", - "internal-default-process-filter", - "internal-default-process-sentinel", "internal-describe-syntax-value", - "internal-event-symbol-parse-modifiers", - "internal-face-x-get-resource", "internal-get-lisp-face-attribute", - "internal-lisp-face-attribute-values", "internal-lisp-face-empty-p", - "internal-lisp-face-equal-p", "internal-lisp-face-p", - "internal-make-lisp-face", "internal-make-var-non-special", - "internal-merge-in-global-face", - "internal-set-alternative-font-family-alist", - "internal-set-alternative-font-registry-alist", - "internal-set-font-selection-order", - "internal-set-lisp-face-attribute", - "internal-set-lisp-face-attribute-from-resource", - "internal-show-cursor", "internal-show-cursor-p", "interrupt-process", - "invisible-p", "invocation-directory", "invocation-name", "isnan", - "iso-charset", "key-binding", "key-description", - "keyboard-coding-system", "keymap-parent", "keymap-prompt", "keymapp", - "keywordp", "kill-all-local-variables", "kill-buffer", "kill-emacs", - "kill-local-variable", "kill-process", "last-nonminibuffer-frame", - "lax-plist-get", "lax-plist-put", "ldexp", "length", - "libxml-parse-html-region", "libxml-parse-xml-region", - "line-beginning-position", "line-end-position", "line-pixel-height", - "list", "list-fonts", "list-system-processes", "listp", "load", - "load-average", "local-key-binding", "local-variable-if-set-p", - "local-variable-p", "locale-info", "locate-file-internal", - "lock-buffer", "log", "logand", "logb", "logior", "lognot", "logxor", - "looking-at", "lookup-image", "lookup-image-map", "lookup-key", - "lower-frame", "lsh", "macroexpand", "make-bool-vector", - "make-byte-code", "make-category-set", "make-category-table", - "make-char", "make-char-table", "make-directory-internal", - "make-frame-invisible", "make-frame-visible", "make-hash-table", - "make-indirect-buffer", "make-keymap", "make-list", - "make-local-variable", "make-marker", "make-network-process", - "make-overlay", "make-serial-process", "make-sparse-keymap", - "make-string", "make-symbol", "make-symbolic-link", "make-temp-name", - "make-terminal-frame", "make-variable-buffer-local", - "make-variable-frame-local", "make-vector", "makunbound", - "map-char-table", "map-charset-chars", "map-keymap", - "map-keymap-internal", "mapatoms", "mapc", "mapcar", "mapconcat", - "maphash", "mark-marker", "marker-buffer", "marker-insertion-type", - "marker-position", "markerp", "match-beginning", "match-data", - "match-end", "matching-paren", "max", "max-char", "md5", "member", - "memory-info", "memory-limit", "memory-use-counts", "memq", "memql", - "menu-bar-menu-at-x-y", "menu-or-popup-active-p", - "menu-or-popup-active-p", "merge-face-attribute", "message", - "message-box", "message-or-box", "min", - "minibuffer-completion-contents", "minibuffer-contents", - "minibuffer-contents-no-properties", "minibuffer-depth", - "minibuffer-prompt", "minibuffer-prompt-end", - "minibuffer-selected-window", "minibuffer-window", "minibufferp", - "minor-mode-key-binding", "mod", "modify-category-entry", - "modify-frame-parameters", "modify-syntax-entry", - "mouse-pixel-position", "mouse-position", "move-overlay", - "move-point-visually", "move-to-column", "move-to-window-line", - "msdos-downcase-filename", "msdos-long-file-names", "msdos-memget", - "msdos-memput", "msdos-mouse-disable", "msdos-mouse-enable", - "msdos-mouse-init", "msdos-mouse-p", "msdos-remember-default-colors", - "msdos-set-keyboard", "msdos-set-mouse-buttons", - "multibyte-char-to-unibyte", "multibyte-string-p", "narrow-to-region", - "natnump", "nconc", "network-interface-info", - "network-interface-list", "new-fontset", "newline-cache-check", - "next-char-property-change", "next-frame", "next-overlay-change", - "next-property-change", "next-read-file-uses-dialog-p", - "next-single-char-property-change", "next-single-property-change", - "next-window", "nlistp", "nreverse", "nth", "nthcdr", "null", - "number-or-marker-p", "number-to-string", "numberp", - "open-dribble-file", "open-font", "open-termscript", - "optimize-char-table", "other-buffer", "other-window-for-scrolling", - "overlay-buffer", "overlay-end", "overlay-get", "overlay-lists", - "overlay-properties", "overlay-put", "overlay-recenter", - "overlay-start", "overlayp", "overlays-at", "overlays-in", - "parse-partial-sexp", "play-sound-internal", "plist-get", - "plist-member", "plist-put", "point", "point-marker", "point-max", - "point-max-marker", "point-min", "point-min-marker", - "pos-visible-in-window-p", "position-bytes", "posix-looking-at", - "posix-search-backward", "posix-search-forward", "posix-string-match", - "posn-at-point", "posn-at-x-y", "preceding-char", - "prefix-numeric-value", "previous-char-property-change", - "previous-frame", "previous-overlay-change", - "previous-property-change", "previous-single-char-property-change", - "previous-single-property-change", "previous-window", "prin1", - "prin1-to-string", "princ", "print", "process-attributes", - "process-buffer", "process-coding-system", "process-command", - "process-connection", "process-contact", "process-datagram-address", - "process-exit-status", "process-filter", "process-filter-multibyte-p", - "process-id", "process-inherit-coding-system-flag", "process-list", - "process-mark", "process-name", "process-plist", - "process-query-on-exit-flag", "process-running-child-p", - "process-send-eof", "process-send-region", "process-send-string", - "process-sentinel", "process-status", "process-tty-name", - "process-type", "processp", "profiler-cpu-log", - "profiler-cpu-running-p", "profiler-cpu-start", "profiler-cpu-stop", - "profiler-memory-log", "profiler-memory-running-p", - "profiler-memory-start", "profiler-memory-stop", "propertize", - "purecopy", "put", "put-text-property", - "put-unicode-property-internal", "puthash", "query-font", - "query-fontset", "quit-process", "raise-frame", "random", "rassoc", - "rassq", "re-search-backward", "re-search-forward", "read", - "read-buffer", "read-char", "read-char-exclusive", - "read-coding-system", "read-command", "read-event", - "read-from-minibuffer", "read-from-string", "read-function", - "read-key-sequence", "read-key-sequence-vector", - "read-no-blanks-input", "read-non-nil-coding-system", "read-string", - "read-variable", "recent-auto-save-p", "recent-doskeys", - "recent-keys", "recenter", "recursion-depth", "recursive-edit", - "redirect-debugging-output", "redirect-frame-focus", "redisplay", - "redraw-display", "redraw-frame", "regexp-quote", "region-beginning", - "region-end", "register-ccl-program", "register-code-conversion-map", - "remhash", "remove-list-of-text-properties", "remove-text-properties", - "rename-buffer", "rename-file", "replace-match", - "reset-this-command-lengths", "resize-mini-window-internal", - "restore-buffer-modified-p", "resume-tty", "reverse", "round", - "run-hook-with-args", "run-hook-with-args-until-failure", - "run-hook-with-args-until-success", "run-hook-wrapped", "run-hooks", - "run-window-configuration-change-hook", "run-window-scroll-functions", - "safe-length", "scan-lists", "scan-sexps", "scroll-down", - "scroll-left", "scroll-other-window", "scroll-right", "scroll-up", - "search-backward", "search-forward", "secure-hash", "select-frame", - "select-window", "selected-frame", "selected-window", - "self-insert-command", "send-string-to-terminal", "sequencep", - "serial-process-configure", "set", "set-buffer", - "set-buffer-auto-saved", "set-buffer-major-mode", - "set-buffer-modified-p", "set-buffer-multibyte", "set-case-table", - "set-category-table", "set-char-table-extra-slot", - "set-char-table-parent", "set-char-table-range", "set-charset-plist", - "set-charset-priority", "set-coding-system-priority", - "set-cursor-size", "set-default", "set-default-file-modes", - "set-default-toplevel-value", "set-file-acl", "set-file-modes", - "set-file-selinux-context", "set-file-times", "set-fontset-font", - "set-frame-height", "set-frame-position", "set-frame-selected-window", - "set-frame-size", "set-frame-width", "set-fringe-bitmap-face", - "set-input-interrupt-mode", "set-input-meta-mode", "set-input-mode", - "set-keyboard-coding-system-internal", "set-keymap-parent", - "set-marker", "set-marker-insertion-type", "set-match-data", - "set-message-beep", "set-minibuffer-window", - "set-mouse-pixel-position", "set-mouse-position", - "set-network-process-option", "set-output-flow-control", - "set-process-buffer", "set-process-coding-system", - "set-process-datagram-address", "set-process-filter", - "set-process-filter-multibyte", - "set-process-inherit-coding-system-flag", "set-process-plist", - "set-process-query-on-exit-flag", "set-process-sentinel", - "set-process-window-size", "set-quit-char", - "set-safe-terminal-coding-system-internal", "set-screen-color", - "set-standard-case-table", "set-syntax-table", - "set-terminal-coding-system-internal", "set-terminal-local-value", - "set-terminal-parameter", "set-text-properties", "set-time-zone-rule", - "set-visited-file-modtime", "set-window-buffer", - "set-window-combination-limit", "set-window-configuration", - "set-window-dedicated-p", "set-window-display-table", - "set-window-fringes", "set-window-hscroll", "set-window-margins", - "set-window-new-normal", "set-window-new-pixel", - "set-window-new-total", "set-window-next-buffers", - "set-window-parameter", "set-window-point", "set-window-prev-buffers", - "set-window-redisplay-end-trigger", "set-window-scroll-bars", - "set-window-start", "set-window-vscroll", "setcar", "setcdr", - "setplist", "show-face-resources", "signal", "signal-process", "sin", - "single-key-description", "skip-chars-backward", "skip-chars-forward", - "skip-syntax-backward", "skip-syntax-forward", "sleep-for", "sort", - "sort-charsets", "special-variable-p", "split-char", - "split-window-internal", "sqrt", "standard-case-table", - "standard-category-table", "standard-syntax-table", "start-kbd-macro", - "start-process", "stop-process", "store-kbd-macro-event", "string", - "string-as-multibyte", "string-as-unibyte", "string-bytes", - "string-collate-equalp", "string-collate-lessp", "string-equal", - "string-lessp", "string-make-multibyte", "string-make-unibyte", - "string-match", "string-to-char", "string-to-multibyte", - "string-to-number", "string-to-syntax", "string-to-unibyte", - "string-width", "stringp", "subr-name", "subrp", - "subst-char-in-region", "substitute-command-keys", - "substitute-in-file-name", "substring", "substring-no-properties", - "suspend-emacs", "suspend-tty", "suspicious-object", "sxhash", - "symbol-function", "symbol-name", "symbol-plist", "symbol-value", - "symbolp", "syntax-table", "syntax-table-p", "system-groups", - "system-move-file-to-trash", "system-name", "system-users", "tan", - "terminal-coding-system", "terminal-list", "terminal-live-p", - "terminal-local-value", "terminal-name", "terminal-parameter", - "terminal-parameters", "terpri", "test-completion", - "text-char-description", "text-properties-at", "text-property-any", - "text-property-not-all", "this-command-keys", - "this-command-keys-vector", "this-single-command-keys", - "this-single-command-raw-keys", "time-add", "time-less-p", - "time-subtract", "tool-bar-get-system-style", "tool-bar-height", - "tool-bar-pixel-width", "top-level", "trace-redisplay", - "trace-to-stderr", "translate-region-internal", "transpose-regions", - "truncate", "try-completion", "tty-display-color-cells", - "tty-display-color-p", "tty-no-underline", - "tty-suppress-bold-inverse-default-colors", "tty-top-frame", - "tty-type", "type-of", "undo-boundary", "unencodable-char-position", - "unhandled-file-name-directory", "unibyte-char-to-multibyte", - "unibyte-string", "unicode-property-table-internal", "unify-charset", - "unintern", "unix-sync", "unlock-buffer", "upcase", "upcase-initials", - "upcase-initials-region", "upcase-region", "upcase-word", - "use-global-map", "use-local-map", "user-full-name", - "user-login-name", "user-real-login-name", "user-real-uid", - "user-uid", "variable-binding-locus", "vconcat", "vector", - "vector-or-char-table-p", "vectorp", "verify-visited-file-modtime", - "vertical-motion", "visible-frame-list", "visited-file-modtime", - "w16-get-clipboard-data", "w16-selection-exists-p", - "w16-set-clipboard-data", "w32-battery-status", - "w32-default-color-map", "w32-define-rgb-color", - "w32-display-monitor-attributes-list", "w32-frame-menu-bar-size", - "w32-frame-rect", "w32-get-clipboard-data", - "w32-get-codepage-charset", "w32-get-console-codepage", - "w32-get-console-output-codepage", "w32-get-current-locale-id", - "w32-get-default-locale-id", "w32-get-keyboard-layout", - "w32-get-locale-info", "w32-get-valid-codepages", - "w32-get-valid-keyboard-layouts", "w32-get-valid-locale-ids", - "w32-has-winsock", "w32-long-file-name", "w32-reconstruct-hot-key", - "w32-register-hot-key", "w32-registered-hot-keys", - "w32-selection-exists-p", "w32-send-sys-command", - "w32-set-clipboard-data", "w32-set-console-codepage", - "w32-set-console-output-codepage", "w32-set-current-locale", - "w32-set-keyboard-layout", "w32-set-process-priority", - "w32-shell-execute", "w32-short-file-name", "w32-toggle-lock-key", - "w32-unload-winsock", "w32-unregister-hot-key", "w32-window-exists-p", - "w32notify-add-watch", "w32notify-rm-watch", - "waiting-for-user-input-p", "where-is-internal", "widen", - "widget-apply", "widget-get", "widget-put", - "window-absolute-pixel-edges", "window-at", "window-body-height", - "window-body-width", "window-bottom-divider-width", "window-buffer", - "window-combination-limit", "window-configuration-frame", - "window-configuration-p", "window-dedicated-p", - "window-display-table", "window-edges", "window-end", "window-frame", - "window-fringes", "window-header-line-height", "window-hscroll", - "window-inside-absolute-pixel-edges", "window-inside-edges", - "window-inside-pixel-edges", "window-left-child", - "window-left-column", "window-line-height", "window-list", - "window-list-1", "window-live-p", "window-margins", - "window-minibuffer-p", "window-mode-line-height", "window-new-normal", - "window-new-pixel", "window-new-total", "window-next-buffers", - "window-next-sibling", "window-normal-size", "window-old-point", - "window-parameter", "window-parameters", "window-parent", - "window-pixel-edges", "window-pixel-height", "window-pixel-left", - "window-pixel-top", "window-pixel-width", "window-point", - "window-prev-buffers", "window-prev-sibling", - "window-redisplay-end-trigger", "window-resize-apply", - "window-resize-apply-total", "window-right-divider-width", - "window-scroll-bar-height", "window-scroll-bar-width", - "window-scroll-bars", "window-start", "window-system", - "window-text-height", "window-text-pixel-size", "window-text-width", - "window-top-child", "window-top-line", "window-total-height", - "window-total-width", "window-use-time", "window-valid-p", - "window-vscroll", "windowp", "write-char", "write-region", - "x-backspace-delete-keys-p", "x-change-window-property", - "x-change-window-property", "x-close-connection", - "x-close-connection", "x-create-frame", "x-create-frame", - "x-delete-window-property", "x-delete-window-property", - "x-disown-selection-internal", "x-display-backing-store", - "x-display-backing-store", "x-display-color-cells", - "x-display-color-cells", "x-display-grayscale-p", - "x-display-grayscale-p", "x-display-list", "x-display-list", - "x-display-mm-height", "x-display-mm-height", "x-display-mm-width", - "x-display-mm-width", "x-display-monitor-attributes-list", - "x-display-pixel-height", "x-display-pixel-height", - "x-display-pixel-width", "x-display-pixel-width", "x-display-planes", - "x-display-planes", "x-display-save-under", "x-display-save-under", - "x-display-screens", "x-display-screens", "x-display-visual-class", - "x-display-visual-class", "x-family-fonts", "x-file-dialog", - "x-file-dialog", "x-file-dialog", "x-focus-frame", "x-frame-geometry", - "x-frame-geometry", "x-get-atom-name", "x-get-resource", - "x-get-selection-internal", "x-hide-tip", "x-hide-tip", - "x-list-fonts", "x-load-color-file", "x-menu-bar-open-internal", - "x-menu-bar-open-internal", "x-open-connection", "x-open-connection", - "x-own-selection-internal", "x-parse-geometry", "x-popup-dialog", - "x-popup-menu", "x-register-dnd-atom", "x-select-font", - "x-select-font", "x-selection-exists-p", "x-selection-owner-p", - "x-send-client-message", "x-server-max-request-size", - "x-server-max-request-size", "x-server-vendor", "x-server-vendor", - "x-server-version", "x-server-version", "x-show-tip", "x-show-tip", - "x-synchronize", "x-synchronize", "x-uses-old-gtk-dialog", - "x-window-property", "x-window-property", "x-wm-set-size-hint", - "xw-color-defined-p", "xw-color-defined-p", "xw-color-values", - "xw-color-values", "xw-display-color-p", "xw-display-color-p", - "yes-or-no-p", "zlib-available-p", "zlib-decompress-region", - "forward-point", - } - - emacsBuiltinFunctionHighlighted = []string{ - "defvaralias", "provide", "require", - "with-no-warnings", "define-widget", "with-electric-help", - "throw", "defalias", "featurep", - } - - emacsLambdaListKeywords = []string{ - "&allow-other-keys", "&aux", "&body", "&environment", "&key", "&optional", - "&rest", "&whole", - } - - emacsErrorKeywords = []string{ - "cl-assert", "cl-check-type", "error", "signal", - "user-error", "warn", - } -) - -// EmacsLisp lexer. -var EmacsLisp = Register(TypeRemappingLexer(MustNewXMLLexer( - embedded, - "embedded/emacslisp.xml", -), TypeMapping{ - {NameVariable, NameFunction, emacsBuiltinFunction}, - {NameVariable, NameBuiltin, emacsSpecialForms}, - {NameVariable, NameException, emacsErrorKeywords}, - {NameVariable, NameBuiltin, append(emacsBuiltinFunctionHighlighted, emacsMacros...)}, - {NameVariable, KeywordPseudo, emacsLambdaListKeywords}, -})) diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abap.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abap.xml deleted file mode 100644 index e8140b73..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abap.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - ABAP - abap - *.abap - *.ABAP - text/x-abap - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abnf.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abnf.xml deleted file mode 100644 index 3ffd51c6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/abnf.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - ABNF - abnf - *.abnf - text/x-abnf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript.xml deleted file mode 100644 index d6727a10..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - ActionScript - as - actionscript - *.as - application/x-actionscript - text/x-actionscript - text/actionscript - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript_3.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript_3.xml deleted file mode 100644 index e5f65384..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/actionscript_3.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - ActionScript 3 - as3 - actionscript3 - *.as - application/x-actionscript3 - text/x-actionscript3 - text/actionscript3 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ada.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ada.xml deleted file mode 100644 index 5854a20e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ada.xml +++ /dev/null @@ -1,321 +0,0 @@ - - - Ada - ada - ada95 - ada2005 - *.adb - *.ads - *.ada - text/x-ada - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/agda.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/agda.xml deleted file mode 100644 index 6f2b2d50..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/agda.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - Agda - agda - *.agda - text/x-agda - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/al.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/al.xml deleted file mode 100644 index 30bad5ae..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/al.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - AL - al - *.al - *.dal - text/x-al - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/alloy.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/alloy.xml deleted file mode 100644 index 1de9ea6c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/alloy.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - Alloy - alloy - *.als - text/x-alloy - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml deleted file mode 100644 index 84fe20b3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/angular2.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - Angular2 - ng2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/antlr.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/antlr.xml deleted file mode 100644 index e57edd40..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/antlr.xml +++ /dev/null @@ -1,317 +0,0 @@ - - - ANTLR - antlr - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apacheconf.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apacheconf.xml deleted file mode 100644 index 7643541c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apacheconf.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - ApacheConf - apacheconf - aconf - apache - .htaccess - apache.conf - apache2.conf - text/x-apacheconf - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apl.xml deleted file mode 100644 index 959448ca..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/apl.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - APL - apl - *.apl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml deleted file mode 100644 index 1de6c67e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/applescript.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - AppleScript - applescript - *.applescript - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml deleted file mode 100644 index e7119737..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arangodb_aql.xml +++ /dev/null @@ -1,174 +0,0 @@ - - - ArangoDB AQL - aql - *.aql - text/x-aql - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml deleted file mode 100644 index 00399c2c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/arduino.xml +++ /dev/null @@ -1,309 +0,0 @@ - - - Arduino - arduino - *.ino - text/x-arduino - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml deleted file mode 100644 index e5966cf6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/armasm.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - ArmAsm - armasm - *.s - *.S - text/x-armasm - text/x-asm - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autohotkey.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autohotkey.xml deleted file mode 100644 index 6ec94ede..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autohotkey.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - AutoHotkey - autohotkey - ahk - *.ahk - *.ahkl - text/x-autohotkey - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autoit.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autoit.xml deleted file mode 100644 index 1f7e15df..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/autoit.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - AutoIt - autoit - *.au3 - text/x-autoit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/awk.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/awk.xml deleted file mode 100644 index 07476ff7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/awk.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - Awk - awk - gawk - mawk - nawk - *.awk - application/x-awk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ballerina.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ballerina.xml deleted file mode 100644 index d13c1231..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ballerina.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - Ballerina - ballerina - *.bal - text/x-ballerina - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash.xml deleted file mode 100644 index d704a8ff..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash.xml +++ /dev/null @@ -1,220 +0,0 @@ - - - Bash - bash - sh - ksh - zsh - shell - *.sh - *.ksh - *.bash - *.ebuild - *.eclass - .env - *.env - *.exheres-0 - *.exlib - *.zsh - *.zshrc - .bashrc - bashrc - .bash_* - bash_* - zshrc - .zshrc - PKGBUILD - application/x-sh - application/x-shellscript - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash_session.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash_session.xml deleted file mode 100644 index 82c5fd6d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bash_session.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - Bash Session - bash-session - console - shell-session - *.sh-session - text/x-sh - true - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/batchfile.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/batchfile.xml deleted file mode 100644 index d3e06272..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/batchfile.xml +++ /dev/null @@ -1,660 +0,0 @@ - - - Batchfile - bat - batch - dosbatch - winbatch - *.bat - *.cmd - application/x-dos-batch - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bibtex.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bibtex.xml deleted file mode 100644 index 8fde161b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bibtex.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - BibTeX - bib - bibtex - *.bib - text/x-bibtex - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bicep.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bicep.xml deleted file mode 100644 index db90f31b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bicep.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - Bicep - bicep - *.bicep - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/blitzbasic.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/blitzbasic.xml deleted file mode 100644 index 591b1ad0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/blitzbasic.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - BlitzBasic - blitzbasic - b3d - bplus - *.bb - *.decls - text/x-bb - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bnf.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bnf.xml deleted file mode 100644 index 5c984247..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bnf.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - BNF - bnf - *.bnf - text/x-bnf - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bqn.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bqn.xml deleted file mode 100644 index c1090ea5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/bqn.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - BQN - bqn - *.bqn - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/brainfuck.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/brainfuck.xml deleted file mode 100644 index 4c84c330..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/brainfuck.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - Brainfuck - brainfuck - bf - *.bf - *.b - application/x-brainfuck - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c#.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c#.xml deleted file mode 100644 index f1e21db0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c#.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - C# - csharp - c# - *.cs - text/x-csharp - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c++.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c++.xml deleted file mode 100644 index 680a19af..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c++.xml +++ /dev/null @@ -1,331 +0,0 @@ - - - C++ - cpp - c++ - *.cpp - *.hpp - *.c++ - *.h++ - *.cc - *.hh - *.cxx - *.hxx - *.C - *.H - *.cp - *.CPP - *.tpp - text/x-c++hdr - text/x-c++src - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c.xml deleted file mode 100644 index 35ee32dc..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/c.xml +++ /dev/null @@ -1,260 +0,0 @@ - - - C - c - *.c - *.h - *.idc - *.x[bp]m - text/x-chdr - text/x-csrc - image/x-xbitmap - image/x-xpixmap - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cap_n_proto.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cap_n_proto.xml deleted file mode 100644 index 3e7d1470..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cap_n_proto.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - Cap'n Proto - capnp - *.capnp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cassandra_cql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cassandra_cql.xml deleted file mode 100644 index 1a78f99a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cassandra_cql.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - Cassandra CQL - cassandra - cql - *.cql - text/x-cql - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ceylon.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ceylon.xml deleted file mode 100644 index 4c412183..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ceylon.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - Ceylon - ceylon - *.ceylon - text/x-ceylon - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml deleted file mode 100644 index 49503050..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfengine3.xml +++ /dev/null @@ -1,197 +0,0 @@ - - - CFEngine3 - cfengine3 - cf3 - *.cf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfstatement.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfstatement.xml deleted file mode 100644 index 46a84cf6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cfstatement.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - cfstatement - cfs - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chaiscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chaiscript.xml deleted file mode 100644 index 860439aa..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chaiscript.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - ChaiScript - chai - chaiscript - *.chai - text/x-chaiscript - application/x-chaiscript - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chapel.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chapel.xml deleted file mode 100644 index c89cafc6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/chapel.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - Chapel - chapel - chpl - *.chpl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cheetah.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cheetah.xml deleted file mode 100644 index 284457c6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cheetah.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - Cheetah - cheetah - spitfire - *.tmpl - *.spt - application/x-cheetah - application/x-spitfire - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/clojure.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/clojure.xml deleted file mode 100644 index 967ba399..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/clojure.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - Clojure - clojure - clj - edn - *.clj - *.edn - text/x-clojure - application/x-clojure - application/edn - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cmake.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cmake.xml deleted file mode 100644 index b041cfd0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cmake.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - CMake - cmake - *.cmake - CMakeLists.txt - text/x-cmake - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cobol.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cobol.xml deleted file mode 100644 index a8a80291..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cobol.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - COBOL - cobol - *.cob - *.COB - *.cpy - *.CPY - text/x-cobol - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coffeescript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coffeescript.xml deleted file mode 100644 index e29722fb..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coffeescript.xml +++ /dev/null @@ -1,210 +0,0 @@ - - - CoffeeScript - coffee-script - coffeescript - coffee - *.coffee - text/coffeescript - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/common_lisp.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/common_lisp.xml deleted file mode 100644 index 0fb9a7a4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/common_lisp.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - Common Lisp - common-lisp - cl - lisp - *.cl - *.lisp - text/x-common-lisp - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coq.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coq.xml deleted file mode 100644 index 62f64ff9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/coq.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - Coq - coq - *.v - text/x-coq - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/crystal.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/crystal.xml deleted file mode 100644 index 94853db3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/crystal.xml +++ /dev/null @@ -1,762 +0,0 @@ - - - Crystal - cr - crystal - *.cr - text/x-crystal - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml deleted file mode 100644 index 6e370c76..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/css.xml +++ /dev/null @@ -1,323 +0,0 @@ - - - CSS - css - *.css - text/css - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cue.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cue.xml deleted file mode 100644 index 2a12f395..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cue.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - CUE - cue - *.cue - text/x-cue - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cython.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cython.xml deleted file mode 100644 index 15dfe4d4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/cython.xml +++ /dev/null @@ -1,372 +0,0 @@ - - - Cython - cython - pyx - pyrex - *.pyx - *.pxd - *.pxi - text/x-cython - application/x-cython - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/d.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/d.xml deleted file mode 100644 index 3c030e22..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/d.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - D - d - *.d - *.di - text/x-d - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml deleted file mode 100644 index f1b454fa..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dart.xml +++ /dev/null @@ -1,213 +0,0 @@ - - - Dart - dart - *.dart - text/x-dart - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dax.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dax.xml deleted file mode 100644 index 2bb3a1aa..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dax.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - Dax - dax - *.dax - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/desktop_entry.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/desktop_entry.xml deleted file mode 100644 index ad71ad47..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/desktop_entry.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - Desktop file - desktop - desktop_entry - *.desktop - application/x-desktop - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/diff.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/diff.xml deleted file mode 100644 index dc0beb7f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/diff.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - Diff - diff - udiff - *.diff - *.patch - text/x-diff - text/x-patch - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/django_jinja.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/django_jinja.xml deleted file mode 100644 index 3c97c222..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/django_jinja.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - Django/Jinja - django - jinja - application/x-django-templating - application/x-jinja - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml deleted file mode 100644 index ef8f663f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dns.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - dns - zone - bind - *.zone - text/dns - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml deleted file mode 100644 index a73c52cd..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/docker.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - Docker - docker - dockerfile - Dockerfile - Dockerfile.* - *.Dockerfile - *.docker - text/x-dockerfile-config - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dtd.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dtd.xml deleted file mode 100644 index 0edbbdea..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dtd.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - DTD - dtd - *.dtd - application/xml-dtd - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dylan.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dylan.xml deleted file mode 100644 index 3660d144..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/dylan.xml +++ /dev/null @@ -1,176 +0,0 @@ - - - Dylan - dylan - *.dylan - *.dyl - *.intr - text/x-dylan - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ebnf.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ebnf.xml deleted file mode 100644 index df5d62ff..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ebnf.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - EBNF - ebnf - *.ebnf - text/x-ebnf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elixir.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elixir.xml deleted file mode 100644 index 286f53a2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elixir.xml +++ /dev/null @@ -1,744 +0,0 @@ - - - Elixir - elixir - ex - exs - *.ex - *.eex - *.exs - text/x-elixir - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elm.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elm.xml deleted file mode 100644 index ed65efc6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/elm.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - Elm - elm - *.elm - text/x-elm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/emacslisp.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/emacslisp.xml deleted file mode 100644 index 668bc621..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/emacslisp.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - EmacsLisp - emacs - elisp - emacs-lisp - *.el - text/x-elisp - application/x-elisp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erlang.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erlang.xml deleted file mode 100644 index b1865886..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/erlang.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - Erlang - erlang - *.erl - *.hrl - *.es - *.escript - text/x-erlang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/factor.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/factor.xml deleted file mode 100644 index 4743b9a2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/factor.xml +++ /dev/null @@ -1,412 +0,0 @@ - - - Factor - factor - *.factor - text/x-factor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fennel.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fennel.xml deleted file mode 100644 index b9b6d595..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fennel.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - Fennel - fennel - fnl - *.fennel - text/x-fennel - application/x-fennel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fish.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fish.xml deleted file mode 100644 index deb78145..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fish.xml +++ /dev/null @@ -1,159 +0,0 @@ - - - Fish - fish - fishshell - *.fish - *.load - application/x-fish - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/forth.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/forth.xml deleted file mode 100644 index 31096a22..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/forth.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - Forth - forth - *.frt - *.fth - *.fs - application/x-forth - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml deleted file mode 100644 index 6140e704..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortran.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - Fortran - fortran - f90 - *.f03 - *.f90 - *.f95 - *.F03 - *.F90 - *.F95 - text/x-fortran - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortranfixed.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortranfixed.xml deleted file mode 100644 index 11343c0e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fortranfixed.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - FortranFixed - fortranfixed - *.f - *.F - text/x-fortran - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fsharp.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fsharp.xml deleted file mode 100644 index e1c19ffb..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/fsharp.xml +++ /dev/null @@ -1,245 +0,0 @@ - - - FSharp - fsharp - *.fs - *.fsi - text/x-fsharp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml deleted file mode 100644 index 7557bce0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gas.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - GAS - gas - asm - *.s - *.S - text/x-gas - 0.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript.xml deleted file mode 100644 index 811f38d0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript.xml +++ /dev/null @@ -1,259 +0,0 @@ - - - GDScript - gdscript - gd - *.gd - text/x-gdscript - application/x-gdscript - 0.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript3.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript3.xml deleted file mode 100644 index b50c9dd7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gdscript3.xml +++ /dev/null @@ -1,270 +0,0 @@ - - - GDScript3 - gdscript3 - gd3 - *.gd - text/x-gdscript - application/x-gdscript - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gherkin.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gherkin.xml deleted file mode 100644 index c53a2cbb..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gherkin.xml +++ /dev/null @@ -1,263 +0,0 @@ - - - Gherkin - cucumber - Cucumber - gherkin - Gherkin - *.feature - *.FEATURE - text/x-gherkin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gleam.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gleam.xml deleted file mode 100644 index c706e962..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gleam.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - Gleam - gleam> - *.gleam - text/x-gleam - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/glsl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/glsl.xml deleted file mode 100644 index ca0b696d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/glsl.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - GLSL - glsl - *.vert - *.frag - *.geo - text/x-glslsrc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gnuplot.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gnuplot.xml deleted file mode 100644 index ee6a245f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/gnuplot.xml +++ /dev/null @@ -1,289 +0,0 @@ - - - Gnuplot - gnuplot - *.plot - *.plt - text/x-gnuplot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/go_template.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/go_template.xml deleted file mode 100644 index 36f737b9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/go_template.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - Go Template - go-template - *.gotmpl - *.go.tmpl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml deleted file mode 100644 index b0622735..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/graphql.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - GraphQL - graphql - graphqls - gql - *.graphql - *.graphqls - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groff.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groff.xml deleted file mode 100644 index 3af0a43e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groff.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - Groff - groff - nroff - man - *.[1-9] - *.1p - *.3pm - *.man - application/x-troff - text/troff - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groovy.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groovy.xml deleted file mode 100644 index 3cca2e9a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/groovy.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - Groovy - groovy - *.groovy - *.gradle - text/x-groovy - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/handlebars.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/handlebars.xml deleted file mode 100644 index 7cf2a648..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/handlebars.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - Handlebars - handlebars - hbs - *.handlebars - *.hbs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hare.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hare.xml deleted file mode 100644 index ea636422..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hare.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - Hare - hare - *.ha - text/x-hare - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/haskell.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/haskell.xml deleted file mode 100644 index 5f805d6d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/haskell.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - Haskell - haskell - hs - *.hs - text/x-haskell - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hcl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hcl.xml deleted file mode 100644 index d3ed208a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hcl.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - HCL - hcl - *.hcl - application/x-hcl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hexdump.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hexdump.xml deleted file mode 100644 index a6f28eab..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hexdump.xml +++ /dev/null @@ -1,189 +0,0 @@ - - - Hexdump - hexdump - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml deleted file mode 100644 index 64e667dd..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlb.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - HLB - hlb - *.hlb - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlsl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlsl.xml deleted file mode 100644 index 41ab3239..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hlsl.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - HLSL - hlsl - *.hlsl - *.hlsli - *.cginc - *.fx - *.fxh - text/x-hlsl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/holyc.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/holyc.xml deleted file mode 100644 index cd2d9d16..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/holyc.xml +++ /dev/null @@ -1,252 +0,0 @@ - - - HolyC - holyc - *.HC - *.hc - *.HH - *.hh - *.hc.z - *.HC.Z - text/x-chdr - text/x-csrc - image/x-xbitmap - image/x-xpixmap - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/html.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/html.xml deleted file mode 100644 index 2f1a8a97..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/html.xml +++ /dev/null @@ -1,159 +0,0 @@ - - - HTML - html - *.html - *.htm - *.xhtml - *.xslt - text/html - application/xhtml+xml - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hy.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hy.xml deleted file mode 100644 index a0dae46a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/hy.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - Hy - hylang - *.hy - text/x-hy - application/x-hy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/idris.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/idris.xml deleted file mode 100644 index 9592d882..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/idris.xml +++ /dev/null @@ -1,216 +0,0 @@ - - - Idris - idris - idr - *.idr - text/x-idris - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/igor.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/igor.xml deleted file mode 100644 index 1cc02057..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/igor.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - Igor - igor - igorpro - *.ipf - text/ipf - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ini.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ini.xml deleted file mode 100644 index 08f3870b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ini.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - INI - ini - cfg - dosini - *.ini - *.cfg - *.inf - *.service - *.socket - .gitconfig - .editorconfig - pylintrc - .pylintrc - text/x-ini - text/inf - 0.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/io.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/io.xml deleted file mode 100644 index 9ad94fa5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/io.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - Io - io - *.io - text/x-iosrc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/iscdhcpd.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/iscdhcpd.xml deleted file mode 100644 index 645cb05d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/iscdhcpd.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - ISCdhcpd - iscdhcpd - dhcpd.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/j.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/j.xml deleted file mode 100644 index 872d0812..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/j.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - J - j - *.ijs - text/x-j - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml deleted file mode 100644 index 3ce33ff6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/java.xml +++ /dev/null @@ -1,193 +0,0 @@ - - - Java - java - *.java - text/x-java - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml deleted file mode 100644 index efe80ed3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/javascript.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - JavaScript - js - javascript - *.js - *.jsm - *.mjs - *.cjs - application/javascript - application/x-javascript - text/x-javascript - text/javascript - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml deleted file mode 100644 index 3473cfd1..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/json.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - JSON - json - *.json - *.avsc - application/json - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/julia.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/julia.xml deleted file mode 100644 index 776dcdbc..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/julia.xml +++ /dev/null @@ -1,400 +0,0 @@ - - - Julia - julia - jl - *.jl - text/x-julia - application/x-julia - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jungle.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jungle.xml deleted file mode 100644 index 92c785d0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/jungle.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - Jungle - jungle - *.jungle - text/x-jungle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml deleted file mode 100644 index 09c638a9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/kotlin.xml +++ /dev/null @@ -1,223 +0,0 @@ - - - Kotlin - kotlin - *.kt - text/x-kotlin - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lighttpd_configuration_file.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lighttpd_configuration_file.xml deleted file mode 100644 index 1319e5c8..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lighttpd_configuration_file.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - Lighttpd configuration file - lighty - lighttpd - text/x-lighttpd-conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/llvm.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/llvm.xml deleted file mode 100644 index f24f1522..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/llvm.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - LLVM - llvm - *.ll - text/x-llvm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml deleted file mode 100644 index 903d4581..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/lua.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - Lua - lua - *.lua - *.wlua - text/x-lua - application/x-lua - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/makefile.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/makefile.xml deleted file mode 100644 index a82a7f8d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/makefile.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - Makefile - make - makefile - mf - bsdmake - *.mak - *.mk - Makefile - makefile - Makefile.* - GNUmakefile - BSDmakefile - Justfile - justfile - .justfile - text/x-makefile - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mako.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mako.xml deleted file mode 100644 index 78241408..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mako.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - Mako - mako - *.mao - application/x-mako - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mason.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mason.xml deleted file mode 100644 index 5873f2af..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mason.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - Mason - mason - *.m - *.mhtml - *.mc - *.mi - autohandler - dhandler - application/x-mason - 0.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml deleted file mode 100644 index 7b22a46c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/materialize_sql_dialect.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - Materialize SQL dialect - materialize - mzsql - text/x-materializesql - true - true - - - - - - - - - - - - - - - - - - - 6 - 12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mathematica.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mathematica.xml deleted file mode 100644 index 0b8dfb61..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mathematica.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - Mathematica - mathematica - mma - nb - *.cdf - *.m - *.ma - *.mt - *.mx - *.nb - *.nbp - *.wl - application/mathematica - application/vnd.wolfram.mathematica - application/vnd.wolfram.mathematica.package - application/vnd.wolfram.cdf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/matlab.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/matlab.xml deleted file mode 100644 index ebb4e2c3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/matlab.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - Matlab - matlab - *.m - text/matlab - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml deleted file mode 100644 index 33105203..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mcfunction.xml +++ /dev/null @@ -1,182 +0,0 @@ - - - mcfunction - mcfunction - *.mcfunction - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml deleted file mode 100644 index 130047df..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/meson.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - Meson - meson - meson.build - meson.build - meson_options.txt - text/x-meson - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/metal.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/metal.xml deleted file mode 100644 index 62d04ba8..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/metal.xml +++ /dev/null @@ -1,270 +0,0 @@ - - - Metal - metal - *.metal - text/x-metal - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/minizinc.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/minizinc.xml deleted file mode 100644 index 1ad6860f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/minizinc.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - MiniZinc - minizinc - MZN - mzn - *.mzn - *.dzn - *.fzn - text/minizinc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mlir.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mlir.xml deleted file mode 100644 index 025c3dc5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mlir.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - MLIR - mlir - *.mlir - text/x-mlir - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modula-2.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modula-2.xml deleted file mode 100644 index 0bf37bcc..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/modula-2.xml +++ /dev/null @@ -1,245 +0,0 @@ - - - Modula-2 - modula2 - m2 - *.def - *.mod - text/x-modula2 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/monkeyc.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/monkeyc.xml deleted file mode 100644 index 7445a639..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/monkeyc.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - MonkeyC - monkeyc - *.mc - text/x-monkeyc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/morrowindscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/morrowindscript.xml deleted file mode 100644 index 724a19fc..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/morrowindscript.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - MorrowindScript - morrowind - mwscript - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/myghty.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/myghty.xml deleted file mode 100644 index 6d03917e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/myghty.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - Myghty - myghty - *.myt - autodelegate - application/x-myghty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml deleted file mode 100644 index b6c2046d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/mysql.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - MySQL - mysql - mariadb - *.sql - text/x-mysql - text/x-mariadb - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nasm.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nasm.xml deleted file mode 100644 index defe65b3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nasm.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - NASM - nasm - *.asm - *.ASM - *.nasm - text/x-nasm - true - 1.0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/natural.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/natural.xml deleted file mode 100644 index 707252b4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/natural.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - Natural - natural - *.NSN - *.NSP - *.NSS - *.NSH - *.NSG - *.NSL - *.NSA - *.NSM - *.NSC - *.NS7 - text/x-natural - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ndisasm.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ndisasm.xml deleted file mode 100644 index 74d443b6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ndisasm.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - NDISASM - ndisasm - text/x-disasm - true - 0.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/newspeak.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/newspeak.xml deleted file mode 100644 index b9326570..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/newspeak.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - Newspeak - newspeak - *.ns2 - text/x-newspeak - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nginx_configuration_file.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nginx_configuration_file.xml deleted file mode 100644 index 46bdf573..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nginx_configuration_file.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - Nginx configuration file - nginx - nginx.conf - text/x-nginx-conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nim.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nim.xml deleted file mode 100644 index bfdd6156..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nim.xml +++ /dev/null @@ -1,211 +0,0 @@ - - - Nim - nim - nimrod - *.nim - *.nimrod - text/x-nim - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nix.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nix.xml deleted file mode 100644 index 0ed040ca..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/nix.xml +++ /dev/null @@ -1,258 +0,0 @@ - - - Nix - nixos - nix - *.nix - text/x-nix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objective-c.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objective-c.xml deleted file mode 100644 index 0dc93285..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objective-c.xml +++ /dev/null @@ -1,510 +0,0 @@ - - - Objective-C - objective-c - objectivec - obj-c - objc - *.m - *.h - text/x-objective-c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml deleted file mode 100644 index 12af64b9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/objectpascal.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - ObjectPascal - objectpascal - *.pas - *.pp - *.inc - *.dpr - *.dpk - *.lpr - *.lpk - text/x-pascal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ocaml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ocaml.xml deleted file mode 100644 index 77f67ac9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ocaml.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - OCaml - ocaml - *.ml - *.mli - *.mll - *.mly - text/x-ocaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/octave.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/octave.xml deleted file mode 100644 index 0515d289..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/octave.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - Octave - octave - *.m - text/octave - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/odin.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/odin.xml deleted file mode 100644 index b9842638..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/odin.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - Odin - odin - *.odin - text/odin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/onesenterprise.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/onesenterprise.xml deleted file mode 100644 index 530bad70..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/onesenterprise.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - OnesEnterprise - ones - onesenterprise - 1S - 1S:Enterprise - *.EPF - *.epf - *.ERF - *.erf - application/octet-stream - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openedge_abl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openedge_abl.xml deleted file mode 100644 index 04a80f3c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openedge_abl.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - OpenEdge ABL - openedge - abl - progress - openedgeabl - *.p - *.cls - *.w - *.i - text/x-openedge - application/x-openedge - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openscad.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openscad.xml deleted file mode 100644 index 84d0fe13..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/openscad.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - OpenSCAD - openscad - *.scad - text/x-scad - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/org_mode.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/org_mode.xml deleted file mode 100644 index 259e54ef..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/org_mode.xml +++ /dev/null @@ -1,329 +0,0 @@ - - - Org Mode - org - orgmode - *.org - text/org - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - 4 - - - - - - - - - - - - 2 - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pacmanconf.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pacmanconf.xml deleted file mode 100644 index caf72367..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pacmanconf.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - PacmanConf - pacmanconf - pacman.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/perl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/perl.xml deleted file mode 100644 index 8ac02ab4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/perl.xml +++ /dev/null @@ -1,400 +0,0 @@ - - - Perl - perl - pl - *.pl - *.pm - *.t - text/x-perl - application/x-perl - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml deleted file mode 100644 index c9e22ea5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/php.xml +++ /dev/null @@ -1,212 +0,0 @@ - - - PHP - php - php3 - php4 - php5 - *.php - *.php[345] - *.inc - text/x-php - true - true - true - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pig.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pig.xml deleted file mode 100644 index 5acd7739..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pig.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - Pig - pig - *.pig - text/x-pig - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pkgconfig.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pkgconfig.xml deleted file mode 100644 index 875dcba6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pkgconfig.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - PkgConfig - pkgconfig - *.pc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pl_pgsql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pl_pgsql.xml deleted file mode 100644 index e3e813ad..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pl_pgsql.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - PL/pgSQL - plpgsql - text/x-plpgsql - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plaintext.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plaintext.xml deleted file mode 100644 index d5e3243e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plaintext.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - plaintext - text - plain - no-highlight - *.txt - text/plain - -1 - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plutus_core.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plutus_core.xml deleted file mode 100644 index 4ff5a970..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/plutus_core.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - Plutus Core - plutus-core - plc - *.plc - text/x-plutus-core - application/x-plutus-core - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pony.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pony.xml deleted file mode 100644 index 4efa9db5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/pony.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - Pony - pony - *.pony - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postgresql_sql_dialect.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postgresql_sql_dialect.xml deleted file mode 100644 index e901c185..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postgresql_sql_dialect.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - PostgreSQL SQL dialect - postgresql - postgres - text/x-postgresql - true - true - - - - - - - - - - - - - - - - - - - 6 - 12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml deleted file mode 100644 index 15a3422d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/postscript.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - PostScript - postscript - postscr - *.ps - *.eps - application/postscript - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/povray.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/povray.xml deleted file mode 100644 index f37dab90..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/povray.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - POVRay - pov - *.pov - *.inc - text/x-povray - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powerquery.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powerquery.xml deleted file mode 100644 index 0ff1e355..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powerquery.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - PowerQuery - powerquery - pq - *.pq - text/x-powerquery - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powershell.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powershell.xml deleted file mode 100644 index b63a1508..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/powershell.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - PowerShell - powershell - posh - ps1 - psm1 - psd1 - pwsh - *.ps1 - *.psm1 - *.psd1 - text/x-powershell - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prolog.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prolog.xml deleted file mode 100644 index 391bae36..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prolog.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - Prolog - prolog - *.ecl - *.prolog - *.pro - *.pl - text/x-prolog - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promela.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promela.xml deleted file mode 100644 index 84558c3b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promela.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - Promela - promela - *.pml - *.prom - *.prm - *.promela - *.pr - *.pm - text/x-promela - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promql.xml deleted file mode 100644 index e95e333d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/promql.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - PromQL - promql - *.promql - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml deleted file mode 100644 index d5ae0a28..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/properties.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - properties - java-properties - *.properties - text/x-java-properties - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml deleted file mode 100644 index 157d321f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/protocol_buffer.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - Protocol Buffer - protobuf - proto - *.proto - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prql.xml deleted file mode 100644 index 21f21c65..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/prql.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - PRQL - prql - *.prql - application/prql - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/psl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/psl.xml deleted file mode 100644 index ab375dae..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/psl.xml +++ /dev/null @@ -1,213 +0,0 @@ - - - PSL - psl - *.psl - *.BATCH - *.TRIG - *.PROC - text/x-psl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/puppet.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/puppet.xml deleted file mode 100644 index fbb587cf..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/puppet.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - Puppet - puppet - *.pp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python.xml deleted file mode 100644 index a58686ff..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python.xml +++ /dev/null @@ -1,593 +0,0 @@ - - - Python - python - py - sage - python3 - py3 - *.py - *.pyi - *.pyw - *.jy - *.sage - *.sc - SConstruct - SConscript - *.bzl - BUCK - BUILD - BUILD.bazel - WORKSPACE - WORKSPACE.bzlmod - WORKSPACE.bazel - MODULE.bazel - REPO.bazel - *.tac - text/x-python - application/x-python - text/x-python3 - application/x-python3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python_2.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python_2.xml deleted file mode 100644 index 3297a226..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/python_2.xml +++ /dev/null @@ -1,356 +0,0 @@ - - - Python 2 - python2 - py2 - text/x-python2 - application/x-python2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qbasic.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qbasic.xml deleted file mode 100644 index 193fe180..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qbasic.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - QBasic - qbasic - basic - *.BAS - *.bas - text/basic - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qml.xml deleted file mode 100644 index 43eb3eb3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/qml.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - QML - qml - qbs - *.qml - *.qbs - application/x-qml - application/x-qt.qbs+qml - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/r.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/r.xml deleted file mode 100644 index c1fba4e5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/r.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - R - splus - s - r - *.S - *.R - *.r - .Rhistory - .Rprofile - .Renviron - text/S-plus - text/S - text/x-r-source - text/x-r - text/x-R - text/x-r-history - text/x-r-profile - 0.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/racket.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/racket.xml deleted file mode 100644 index 6cdd3031..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/racket.xml +++ /dev/null @@ -1,260 +0,0 @@ - - - Racket - racket - rkt - *.rkt - *.rktd - *.rktl - text/x-racket - application/x-racket - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ragel.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ragel.xml deleted file mode 100644 index 69638d2e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ragel.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - Ragel - ragel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/react.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/react.xml deleted file mode 100644 index a4109b09..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/react.xml +++ /dev/null @@ -1,236 +0,0 @@ - - - react - jsx - react - *.jsx - *.react - text/jsx - text/typescript-jsx - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reasonml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reasonml.xml deleted file mode 100644 index 8b7bcc50..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reasonml.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - ReasonML - reason - reasonml - *.re - *.rei - text/x-reasonml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reg.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reg.xml deleted file mode 100644 index 501d3803..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/reg.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - reg - registry - *.reg - text/x-windows-registry - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rego.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rego.xml deleted file mode 100644 index 517b7133..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rego.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - Rego - rego - *.rego - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rexx.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rexx.xml deleted file mode 100644 index e682500c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rexx.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - Rexx - rexx - arexx - *.rexx - *.rex - *.rx - *.arexx - text/x-rexx - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpm_spec.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpm_spec.xml deleted file mode 100644 index 8362772a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rpm_spec.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - RPMSpec - spec - *.spec - text/x-rpm-spec - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml deleted file mode 100644 index baa7e435..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ruby.xml +++ /dev/null @@ -1,724 +0,0 @@ - - - Ruby - rb - ruby - duby - *.rb - *.rbw - Rakefile - *.rake - *.gemspec - *.rbx - *.duby - Gemfile - Vagrantfile - text/x-ruby - application/x-ruby - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rust.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rust.xml deleted file mode 100644 index 083b96ff..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/rust.xml +++ /dev/null @@ -1,375 +0,0 @@ - - - Rust - rust - rs - *.rs - *.rs.in - text/rust - text/x-rust - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sas.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sas.xml deleted file mode 100644 index af1107bf..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sas.xml +++ /dev/null @@ -1,191 +0,0 @@ - - - SAS - sas - *.SAS - *.sas - text/x-sas - text/sas - application/x-sas - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sass.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sass.xml deleted file mode 100644 index f8015949..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sass.xml +++ /dev/null @@ -1,362 +0,0 @@ - - - Sass - sass - *.sass - text/x-sass - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scala.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scala.xml deleted file mode 100644 index 2f8ddd49..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scala.xml +++ /dev/null @@ -1,274 +0,0 @@ - - - Scala - scala - *.scala - text/x-scala - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scheme.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scheme.xml deleted file mode 100644 index 0198bd72..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scheme.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - Scheme - scheme - scm - *.scm - *.ss - text/x-scheme - application/x-scheme - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scilab.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scilab.xml deleted file mode 100644 index 9e109495..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scilab.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - Scilab - scilab - *.sci - *.sce - *.tst - text/scilab - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scss.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scss.xml deleted file mode 100644 index ee060fc2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/scss.xml +++ /dev/null @@ -1,373 +0,0 @@ - - - SCSS - scss - *.scss - text/x-scss - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml deleted file mode 100644 index 2209aa77..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sed.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - Sed - sed - gsed - ssed - *.sed - *.[gs]sed - text/x-sed - - - - - - - - - - - - - - None - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sieve.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sieve.xml deleted file mode 100644 index fc605638..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sieve.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - Sieve - sieve - *.siv - *.sieve - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smali.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smali.xml deleted file mode 100644 index e468766d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smali.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - Smali - smali - *.smali - text/smali - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smalltalk.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smalltalk.xml deleted file mode 100644 index 00271118..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smalltalk.xml +++ /dev/null @@ -1,294 +0,0 @@ - - - Smalltalk - smalltalk - squeak - st - *.st - text/x-smalltalk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smarty.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smarty.xml deleted file mode 100644 index dd7752c5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/smarty.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - Smarty - smarty - *.tpl - application/x-smarty - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snobol.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snobol.xml deleted file mode 100644 index f53dbcba..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/snobol.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - Snobol - snobol - *.snobol - text/x-snobol - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/solidity.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/solidity.xml deleted file mode 100644 index 04403c84..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/solidity.xml +++ /dev/null @@ -1,279 +0,0 @@ - - - Solidity - sol - solidity - *.sol - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sourcepawn.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sourcepawn.xml deleted file mode 100644 index caca401e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sourcepawn.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - SourcePawn - sp - *.sp - *.inc - text/x-sourcepawn - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sparql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sparql.xml deleted file mode 100644 index 7dc65af7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sparql.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - SPARQL - sparql - *.rq - *.sparql - application/sparql-query - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sql.xml deleted file mode 100644 index b542b65f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/sql.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - SQL - sql - *.sql - text/x-sql - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/squidconf.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/squidconf.xml deleted file mode 100644 index cbd8dbce..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/squidconf.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - SquidConf - squidconf - squid.conf - squid - squid.conf - text/x-squidconf - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/standard_ml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/standard_ml.xml deleted file mode 100644 index 39cf4f2a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/standard_ml.xml +++ /dev/null @@ -1,548 +0,0 @@ - - - Standard ML - sml - *.sml - *.sig - *.fun - text/x-standardml - application/x-standardml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stas.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stas.xml deleted file mode 100644 index 56b4f923..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stas.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - stas - *.stas - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stylus.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stylus.xml deleted file mode 100644 index c2d88073..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/stylus.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - Stylus - stylus - *.styl - text/x-styl - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/swift.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/swift.xml deleted file mode 100644 index 416bf90c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/swift.xml +++ /dev/null @@ -1,207 +0,0 @@ - - - Swift - swift - *.swift - text/x-swift - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemd.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemd.xml deleted file mode 100644 index e31bfc29..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemd.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - SYSTEMD - systemd - *.automount - *.device - *.dnssd - *.link - *.mount - *.netdev - *.network - *.path - *.scope - *.service - *.slice - *.socket - *.swap - *.target - *.timer - text/plain - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemverilog.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemverilog.xml deleted file mode 100644 index fac3da23..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/systemverilog.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - systemverilog - systemverilog - sv - *.sv - *.svh - text/x-systemverilog - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tablegen.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tablegen.xml deleted file mode 100644 index a020ce80..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tablegen.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - TableGen - tablegen - *.td - text/x-tablegen - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tal.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tal.xml deleted file mode 100644 index a071d4c1..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tal.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - Tal - tal - uxntal - *.tal - text/x-uxntal - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tasm.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tasm.xml deleted file mode 100644 index 1347f539..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tasm.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - TASM - tasm - *.asm - *.ASM - *.tasm - text/x-tasm - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcl.xml deleted file mode 100644 index 7ed69bc2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcl.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - Tcl - tcl - *.tcl - *.rvt - text/x-tcl - text/x-script.tcl - application/x-tcl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcsh.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcsh.xml deleted file mode 100644 index 9895643c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tcsh.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - Tcsh - tcsh - csh - *.tcsh - *.csh - application/x-csh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/termcap.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/termcap.xml deleted file mode 100644 index e863bbd0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/termcap.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - Termcap - termcap - termcap - termcap.src - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terminfo.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terminfo.xml deleted file mode 100644 index 9e8f56ec..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terminfo.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - Terminfo - terminfo - terminfo - terminfo.src - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml deleted file mode 100644 index 452f211d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/terraform.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - Terraform - terraform - tf - *.tf - application/x-tf - application/x-terraform - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tex.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tex.xml deleted file mode 100644 index 809bb9a2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tex.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - TeX - tex - latex - *.tex - *.aux - *.toc - text/x-tex - text/x-latex - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/thrift.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/thrift.xml deleted file mode 100644 index f14257d4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/thrift.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - Thrift - thrift - *.thrift - application/x-thrift - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml deleted file mode 100644 index 9c98ba53..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/toml.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - TOML - toml - *.toml - Pipfile - poetry.lock - text/x-toml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tradingview.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tradingview.xml deleted file mode 100644 index 3671f61e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/tradingview.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - TradingView - tradingview - tv - *.tv - text/x-tradingview - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml deleted file mode 100644 index b0490aa7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/transact-sql.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - Transact-SQL - tsql - t-sql - text/x-tsql - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turing.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turing.xml deleted file mode 100644 index 4eab69b7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turing.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - Turing - turing - *.turing - *.tu - text/x-turing - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turtle.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turtle.xml deleted file mode 100644 index 7c572f9c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/turtle.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - Turtle - turtle - *.ttl - text/turtle - application/x-turtle - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/twig.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/twig.xml deleted file mode 100644 index de95c5f9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/twig.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - Twig - twig - *.twig - application/x-twig - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml deleted file mode 100644 index 9828e92f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typescript.xml +++ /dev/null @@ -1,279 +0,0 @@ - - - TypeScript - ts - tsx - typescript - *.ts - *.tsx - *.mts - *.cts - text/x-typescript - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscript.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscript.xml deleted file mode 100644 index bc416d47..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscript.xml +++ /dev/null @@ -1,178 +0,0 @@ - - - TypoScript - typoscript - *.ts - text/x-typoscript - true - 0.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscriptcssdata.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscriptcssdata.xml deleted file mode 100644 index 62c42c15..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscriptcssdata.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - TypoScriptCssData - typoscriptcssdata - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscripthtmldata.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscripthtmldata.xml deleted file mode 100644 index 1b0af3a4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/typoscripthtmldata.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - TypoScriptHtmlData - typoscripthtmldata - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ucode.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ucode.xml deleted file mode 100644 index 054fa891..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/ucode.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - ucode - *.uc - application/x.ucode - text/x.ucode - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v.xml deleted file mode 100644 index e1af3d1c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v.xml +++ /dev/null @@ -1,355 +0,0 @@ - - - V - v - vlang - *.v - *.vv - v.mod - text/x-v - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v_shell.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v_shell.xml deleted file mode 100644 index 34ce6106..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/v_shell.xml +++ /dev/null @@ -1,365 +0,0 @@ - - - V shell - vsh - vshell - *.vsh - text/x-vsh - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vala.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vala.xml deleted file mode 100644 index 17c1acf4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vala.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - Vala - vala - vapi - *.vala - *.vapi - text/x-vala - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vb_net.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vb_net.xml deleted file mode 100644 index 9f85afd0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vb_net.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - VB.net - vb.net - vbnet - *.vb - *.bas - text/x-vbnet - text/x-vba - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/verilog.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/verilog.xml deleted file mode 100644 index cd4b9ff0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/verilog.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - verilog - verilog - v - *.v - text/x-verilog - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhdl.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhdl.xml deleted file mode 100644 index aa420448..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhdl.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - VHDL - vhdl - *.vhdl - *.vhd - text/x-vhdl - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhs.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhs.xml deleted file mode 100644 index ee84d129..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vhs.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - VHS - vhs - tape - cassette - *.tape - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/viml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/viml.xml deleted file mode 100644 index 43e6bfa7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/viml.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - VimL - vim - *.vim - .vimrc - .exrc - .gvimrc - _vimrc - _exrc - _gvimrc - vimrc - gvimrc - text/x-vim - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vue.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vue.xml deleted file mode 100644 index ec350835..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/vue.xml +++ /dev/null @@ -1,307 +0,0 @@ - - - vue - vue - vuejs - *.vue - text/x-vue - application/x-vue - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wdte.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wdte.xml deleted file mode 100644 index c663ee2f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/wdte.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - WDTE - *.wdte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webgpu_shading_language.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webgpu_shading_language.xml deleted file mode 100644 index ea2b6e1e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/webgpu_shading_language.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - WebGPU Shading Language - wgsl - *.wgsl - text/wgsl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/whiley.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/whiley.xml deleted file mode 100644 index 1762c966..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/whiley.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - Whiley - whiley - *.whiley - text/x-whiley - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml deleted file mode 100644 index 2c6a4d99..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xml.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - XML - xml - *.xml - *.xsl - *.rss - *.xslt - *.xsd - *.wsdl - *.wsf - *.svg - *.csproj - *.vcxproj - *.fsproj - text/xml - application/xml - image/svg+xml - application/rss+xml - application/atom+xml - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xorg.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xorg.xml deleted file mode 100644 index 53bf4328..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/xorg.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - Xorg - xorg.conf - xorg.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml deleted file mode 100644 index 97a0b6ed..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yaml.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - YAML - yaml - *.yaml - *.yml - text/x-yaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yang.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yang.xml deleted file mode 100644 index f3da7ceb..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/yang.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - YANG - yang - *.yang - application/yang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/z80_assembly.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/z80_assembly.xml deleted file mode 100644 index 5bb77a9a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/z80_assembly.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - Z80 Assembly - z80 - *.z80 - *.asm - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zed.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zed.xml deleted file mode 100644 index 929f4953..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zed.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - Zed - zed - *.zed - text/zed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml b/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml deleted file mode 100644 index fb51cc1a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/embedded/zig.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - Zig - zig - *.zig - text/zig - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/genshi.go b/vendor/github.com/alecthomas/chroma/v2/lexers/genshi.go deleted file mode 100644 index 7f396f4b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/genshi.go +++ /dev/null @@ -1,118 +0,0 @@ -package lexers - -import ( - . "github.com/alecthomas/chroma/v2" // nolint -) - -// Genshi Text lexer. -var GenshiText = Register(MustNewLexer( - &Config{ - Name: "Genshi Text", - Aliases: []string{"genshitext"}, - Filenames: []string{}, - MimeTypes: []string{"application/x-genshi-text", "text/x-genshi"}, - }, - genshiTextRules, -)) - -func genshiTextRules() Rules { - return Rules{ - "root": { - {`[^#$\s]+`, Other, nil}, - {`^(\s*)(##.*)$`, ByGroups(Text, Comment), nil}, - {`^(\s*)(#)`, ByGroups(Text, CommentPreproc), Push("directive")}, - Include("variable"), - {`[#$\s]`, Other, nil}, - }, - "directive": { - {`\n`, Text, Pop(1)}, - {`(?:def|for|if)\s+.*`, Using("Python"), Pop(1)}, - {`(choose|when|with)([^\S\n]+)(.*)`, ByGroups(Keyword, Text, Using("Python")), Pop(1)}, - {`(choose|otherwise)\b`, Keyword, Pop(1)}, - {`(end\w*)([^\S\n]*)(.*)`, ByGroups(Keyword, Text, Comment), Pop(1)}, - }, - "variable": { - {`(?)`, ByGroups(CommentPreproc, Using("Python"), CommentPreproc), nil}, - {`<\s*(script|style)\s*.*?>.*?<\s*/\1\s*>`, Other, nil}, - {`<\s*py:[a-zA-Z0-9]+`, NameTag, Push("pytag")}, - {`<\s*[a-zA-Z0-9:.]+`, NameTag, Push("tag")}, - Include("variable"), - {`[<$]`, Other, nil}, - }, - "pytag": { - {`\s+`, Text, nil}, - {`[\w:-]+\s*=`, NameAttribute, Push("pyattr")}, - {`/?\s*>`, NameTag, Pop(1)}, - }, - "pyattr": { - {`(")(.*?)(")`, ByGroups(LiteralString, Using("Python"), LiteralString), Pop(1)}, - {`(')(.*?)(')`, ByGroups(LiteralString, Using("Python"), LiteralString), Pop(1)}, - {`[^\s>]+`, LiteralString, Pop(1)}, - }, - "tag": { - {`\s+`, Text, nil}, - {`py:[\w-]+\s*=`, NameAttribute, Push("pyattr")}, - {`[\w:-]+\s*=`, NameAttribute, Push("attr")}, - {`/?\s*>`, NameTag, Pop(1)}, - }, - "attr": { - {`"`, LiteralString, Push("attr-dstring")}, - {`'`, LiteralString, Push("attr-sstring")}, - {`[^\s>]*`, LiteralString, Pop(1)}, - }, - "attr-dstring": { - {`"`, LiteralString, Pop(1)}, - Include("strings"), - {`'`, LiteralString, nil}, - }, - "attr-sstring": { - {`'`, LiteralString, Pop(1)}, - Include("strings"), - {`'`, LiteralString, nil}, - }, - "strings": { - {`[^"'$]+`, LiteralString, nil}, - Include("variable"), - }, - "variable": { - {`(?>=|<<|>>|<=|>=|&\^=|&\^|\+=|-=|\*=|/=|%=|&=|\|=|&&|\|\||<-|\+\+|--|==|!=|:=|\.\.\.|[+\-*/%&])`, Operator, nil}, - {`([a-zA-Z_]\w*)(\s*)(\()`, ByGroups(NameFunction, UsingSelf("root"), Punctuation), nil}, - {`[|^<>=!()\[\]{}.,;:~]`, Punctuation, nil}, - {`[^\W\d]\w*`, NameOther, nil}, - }, - } -} - -var GoHTMLTemplate = Register(DelegatingLexer(HTML, MustNewXMLLexer( - embedded, - "embedded/go_template.xml", -).SetConfig( - &Config{ - Name: "Go HTML Template", - Aliases: []string{"go-html-template"}, - }, -))) - -var GoTextTemplate = Register(MustNewXMLLexer( - embedded, - "embedded/go_template.xml", -).SetConfig( - &Config{ - Name: "Go Text Template", - Aliases: []string{"go-text-template"}, - }, -)) diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/haxe.go b/vendor/github.com/alecthomas/chroma/v2/lexers/haxe.go deleted file mode 100644 index 9a72de86..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/haxe.go +++ /dev/null @@ -1,647 +0,0 @@ -package lexers - -import ( - . "github.com/alecthomas/chroma/v2" // nolint -) - -// Haxe lexer. -var Haxe = Register(MustNewLexer( - &Config{ - Name: "Haxe", - Aliases: []string{"hx", "haxe", "hxsl"}, - Filenames: []string{"*.hx", "*.hxsl"}, - MimeTypes: []string{"text/haxe", "text/x-haxe", "text/x-hx"}, - DotAll: true, - }, - haxeRules, -)) - -func haxeRules() Rules { - return Rules{ - "root": { - Include("spaces"), - Include("meta"), - {`(?:package)\b`, KeywordNamespace, Push("semicolon", "package")}, - {`(?:import)\b`, KeywordNamespace, Push("semicolon", "import")}, - {`(?:using)\b`, KeywordNamespace, Push("semicolon", "using")}, - {`(?:extern|private)\b`, KeywordDeclaration, nil}, - {`(?:abstract)\b`, KeywordDeclaration, Push("abstract")}, - {`(?:class|interface)\b`, KeywordDeclaration, Push("class")}, - {`(?:enum)\b`, KeywordDeclaration, Push("enum")}, - {`(?:typedef)\b`, KeywordDeclaration, Push("typedef")}, - {`(?=.)`, Text, Push("expr-statement")}, - }, - "spaces": { - {`\s+`, Text, nil}, - {`//[^\n\r]*`, CommentSingle, nil}, - {`/\*.*?\*/`, CommentMultiline, nil}, - {`(#)(if|elseif|else|end|error)\b`, CommentPreproc, MutatorFunc(haxePreProcMutator)}, - }, - "string-single-interpol": { - {`\$\{`, LiteralStringInterpol, Push("string-interpol-close", "expr")}, - {`\$\$`, LiteralStringEscape, nil}, - {`\$(?=(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+))`, LiteralStringInterpol, Push("ident")}, - Include("string-single"), - }, - "string-single": { - {`'`, LiteralStringSingle, Pop(1)}, - {`\\.`, LiteralStringEscape, nil}, - {`.`, LiteralStringSingle, nil}, - }, - "string-double": { - {`"`, LiteralStringDouble, Pop(1)}, - {`\\.`, LiteralStringEscape, nil}, - {`.`, LiteralStringDouble, nil}, - }, - "string-interpol-close": { - {`\$(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, LiteralStringInterpol, nil}, - {`\}`, LiteralStringInterpol, Pop(1)}, - }, - "package": { - Include("spaces"), - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, nil}, - {`\.`, Punctuation, Push("import-ident")}, - Default(Pop(1)), - }, - "import": { - Include("spaces"), - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, nil}, - {`\*`, Keyword, nil}, - {`\.`, Punctuation, Push("import-ident")}, - {`in`, KeywordNamespace, Push("ident")}, - Default(Pop(1)), - }, - "import-ident": { - Include("spaces"), - {`\*`, Keyword, Pop(1)}, - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, Pop(1)}, - }, - "using": { - Include("spaces"), - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, nil}, - {`\.`, Punctuation, Push("import-ident")}, - Default(Pop(1)), - }, - "preproc-error": { - {`\s+`, CommentPreproc, nil}, - {`'`, LiteralStringSingle, Push("#pop", "string-single")}, - {`"`, LiteralStringDouble, Push("#pop", "string-double")}, - Default(Pop(1)), - }, - "preproc-expr": { - {`\s+`, CommentPreproc, nil}, - {`\!`, CommentPreproc, nil}, - {`\(`, CommentPreproc, Push("#pop", "preproc-parenthesis")}, - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, CommentPreproc, Pop(1)}, - {`\.[0-9]+`, LiteralNumberFloat, nil}, - {`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, nil}, - {`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, nil}, - {`[0-9]+\.[0-9]+`, LiteralNumberFloat, nil}, - {`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, nil}, - {`0x[0-9a-fA-F]+`, LiteralNumberHex, nil}, - {`[0-9]+`, LiteralNumberInteger, nil}, - {`'`, LiteralStringSingle, Push("#pop", "string-single")}, - {`"`, LiteralStringDouble, Push("#pop", "string-double")}, - }, - "preproc-parenthesis": { - {`\s+`, CommentPreproc, nil}, - {`\)`, CommentPreproc, Pop(1)}, - Default(Push("preproc-expr-in-parenthesis")), - }, - "preproc-expr-chain": { - {`\s+`, CommentPreproc, nil}, - {`(?:%=|&=|\|=|\^=|\+=|\-=|\*=|/=|<<=|>\s*>\s*=|>\s*>\s*>\s*=|==|!=|<=|>\s*=|&&|\|\||<<|>>>|>\s*>|\.\.\.|<|>|%|&|\||\^|\+|\*|/|\-|=>|=)`, CommentPreproc, Push("#pop", "preproc-expr-in-parenthesis")}, - Default(Pop(1)), - }, - "preproc-expr-in-parenthesis": { - {`\s+`, CommentPreproc, nil}, - {`\!`, CommentPreproc, nil}, - {`\(`, CommentPreproc, Push("#pop", "preproc-expr-chain", "preproc-parenthesis")}, - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, CommentPreproc, Push("#pop", "preproc-expr-chain")}, - {`\.[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")}, - {`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")}, - {`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")}, - {`[0-9]+\.[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")}, - {`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")}, - {`0x[0-9a-fA-F]+`, LiteralNumberHex, Push("#pop", "preproc-expr-chain")}, - {`[0-9]+`, LiteralNumberInteger, Push("#pop", "preproc-expr-chain")}, - {`'`, LiteralStringSingle, Push("#pop", "preproc-expr-chain", "string-single")}, - {`"`, LiteralStringDouble, Push("#pop", "preproc-expr-chain", "string-double")}, - }, - "abstract": { - Include("spaces"), - Default(Pop(1), Push("abstract-body"), Push("abstract-relation"), Push("abstract-opaque"), Push("type-param-constraint"), Push("type-name")), - }, - "abstract-body": { - Include("spaces"), - {`\{`, Punctuation, Push("#pop", "class-body")}, - }, - "abstract-opaque": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "parenthesis-close", "type")}, - Default(Pop(1)), - }, - "abstract-relation": { - Include("spaces"), - {`(?:to|from)`, KeywordDeclaration, Push("type")}, - {`,`, Punctuation, nil}, - Default(Pop(1)), - }, - "meta": { - Include("spaces"), - {`@`, NameDecorator, Push("meta-body", "meta-ident", "meta-colon")}, - }, - "meta-colon": { - Include("spaces"), - {`:`, NameDecorator, Pop(1)}, - Default(Pop(1)), - }, - "meta-ident": { - Include("spaces"), - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameDecorator, Pop(1)}, - }, - "meta-body": { - Include("spaces"), - {`\(`, NameDecorator, Push("#pop", "meta-call")}, - Default(Pop(1)), - }, - "meta-call": { - Include("spaces"), - {`\)`, NameDecorator, Pop(1)}, - Default(Pop(1), Push("meta-call-sep"), Push("expr")), - }, - "meta-call-sep": { - Include("spaces"), - {`\)`, NameDecorator, Pop(1)}, - {`,`, Punctuation, Push("#pop", "meta-call")}, - }, - "typedef": { - Include("spaces"), - Default(Pop(1), Push("typedef-body"), Push("type-param-constraint"), Push("type-name")), - }, - "typedef-body": { - Include("spaces"), - {`=`, Operator, Push("#pop", "optional-semicolon", "type")}, - }, - "enum": { - Include("spaces"), - Default(Pop(1), Push("enum-body"), Push("bracket-open"), Push("type-param-constraint"), Push("type-name")), - }, - "enum-body": { - Include("spaces"), - Include("meta"), - {`\}`, Punctuation, Pop(1)}, - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("enum-member", "type-param-constraint")}, - }, - "enum-member": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "semicolon", "flag", "function-param")}, - Default(Pop(1), Push("semicolon"), Push("flag")), - }, - "class": { - Include("spaces"), - Default(Pop(1), Push("class-body"), Push("bracket-open"), Push("extends"), Push("type-param-constraint"), Push("type-name")), - }, - "extends": { - Include("spaces"), - {`(?:extends|implements)\b`, KeywordDeclaration, Push("type")}, - {`,`, Punctuation, nil}, - Default(Pop(1)), - }, - "bracket-open": { - Include("spaces"), - {`\{`, Punctuation, Pop(1)}, - }, - "bracket-close": { - Include("spaces"), - {`\}`, Punctuation, Pop(1)}, - }, - "class-body": { - Include("spaces"), - Include("meta"), - {`\}`, Punctuation, Pop(1)}, - {`(?:static|public|private|override|dynamic|inline|macro)\b`, KeywordDeclaration, nil}, - Default(Push("class-member")), - }, - "class-member": { - Include("spaces"), - {`(var)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "var")}, - {`(function)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "class-method")}, - }, - "function-local": { - Include("spaces"), - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameFunction, Push("#pop", "optional-expr", "flag", "function-param", "parenthesis-open", "type-param-constraint")}, - Default(Pop(1), Push("optional-expr"), Push("flag"), Push("function-param"), Push("parenthesis-open"), Push("type-param-constraint")), - }, - "optional-expr": { - Include("spaces"), - Include("expr"), - Default(Pop(1)), - }, - "class-method": { - Include("spaces"), - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameFunction, Push("#pop", "optional-expr", "flag", "function-param", "parenthesis-open", "type-param-constraint")}, - }, - "function-param": { - Include("spaces"), - {`\)`, Punctuation, Pop(1)}, - {`\?`, Punctuation, nil}, - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "function-param-sep", "assign", "flag")}, - }, - "function-param-sep": { - Include("spaces"), - {`\)`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "function-param")}, - }, - "prop-get-set": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "parenthesis-close", "prop-get-set-opt", "comma", "prop-get-set-opt")}, - Default(Pop(1)), - }, - "prop-get-set-opt": { - Include("spaces"), - {`(?:default|null|never|dynamic|get|set)\b`, Keyword, Pop(1)}, - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Text, Pop(1)}, - }, - "expr-statement": { - Include("spaces"), - Default(Pop(1), Push("optional-semicolon"), Push("expr")), - }, - "expr": { - Include("spaces"), - {`@`, NameDecorator, Push("#pop", "optional-expr", "meta-body", "meta-ident", "meta-colon")}, - {`(?:\+\+|\-\-|~(?!/)|!|\-)`, Operator, nil}, - {`\(`, Punctuation, Push("#pop", "expr-chain", "parenthesis")}, - {`(?:static|public|private|override|dynamic|inline)\b`, KeywordDeclaration, nil}, - {`(?:function)\b`, KeywordDeclaration, Push("#pop", "expr-chain", "function-local")}, - {`\{`, Punctuation, Push("#pop", "expr-chain", "bracket")}, - {`(?:true|false|null)\b`, KeywordConstant, Push("#pop", "expr-chain")}, - {`(?:this)\b`, Keyword, Push("#pop", "expr-chain")}, - {`(?:cast)\b`, Keyword, Push("#pop", "expr-chain", "cast")}, - {`(?:try)\b`, Keyword, Push("#pop", "catch", "expr")}, - {`(?:var)\b`, KeywordDeclaration, Push("#pop", "var")}, - {`(?:new)\b`, Keyword, Push("#pop", "expr-chain", "new")}, - {`(?:switch)\b`, Keyword, Push("#pop", "switch")}, - {`(?:if)\b`, Keyword, Push("#pop", "if")}, - {`(?:do)\b`, Keyword, Push("#pop", "do")}, - {`(?:while)\b`, Keyword, Push("#pop", "while")}, - {`(?:for)\b`, Keyword, Push("#pop", "for")}, - {`(?:untyped|throw)\b`, Keyword, nil}, - {`(?:return)\b`, Keyword, Push("#pop", "optional-expr")}, - {`(?:macro)\b`, Keyword, Push("#pop", "macro")}, - {`(?:continue|break)\b`, Keyword, Pop(1)}, - {`(?:\$\s*[a-z]\b|\$(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)))`, Name, Push("#pop", "dollar")}, - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "expr-chain")}, - {`\.[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")}, - {`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")}, - {`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")}, - {`[0-9]+\.[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")}, - {`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, Push("#pop", "expr-chain")}, - {`0x[0-9a-fA-F]+`, LiteralNumberHex, Push("#pop", "expr-chain")}, - {`[0-9]+`, LiteralNumberInteger, Push("#pop", "expr-chain")}, - {`'`, LiteralStringSingle, Push("#pop", "expr-chain", "string-single-interpol")}, - {`"`, LiteralStringDouble, Push("#pop", "expr-chain", "string-double")}, - {`~/(\\\\|\\/|[^/\n])*/[gimsu]*`, LiteralStringRegex, Push("#pop", "expr-chain")}, - {`\[`, Punctuation, Push("#pop", "expr-chain", "array-decl")}, - }, - "expr-chain": { - Include("spaces"), - {`(?:\+\+|\-\-)`, Operator, nil}, - {`(?:%=|&=|\|=|\^=|\+=|\-=|\*=|/=|<<=|>\s*>\s*=|>\s*>\s*>\s*=|==|!=|<=|>\s*=|&&|\|\||<<|>>>|>\s*>|\.\.\.|<|>|%|&|\||\^|\+|\*|/|\-|=>|=)`, Operator, Push("#pop", "expr")}, - {`(?:in)\b`, Keyword, Push("#pop", "expr")}, - {`\?`, Operator, Push("#pop", "expr", "ternary", "expr")}, - {`(\.)((?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+))`, ByGroups(Punctuation, Name), nil}, - {`\[`, Punctuation, Push("array-access")}, - {`\(`, Punctuation, Push("call")}, - Default(Pop(1)), - }, - "macro": { - Include("spaces"), - Include("meta"), - {`:`, Punctuation, Push("#pop", "type")}, - {`(?:extern|private)\b`, KeywordDeclaration, nil}, - {`(?:abstract)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "abstract")}, - {`(?:class|interface)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "macro-class")}, - {`(?:enum)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "enum")}, - {`(?:typedef)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "typedef")}, - Default(Pop(1), Push("expr")), - }, - "macro-class": { - {`\{`, Punctuation, Push("#pop", "class-body")}, - Include("class"), - }, - "cast": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "parenthesis-close", "cast-type", "expr")}, - Default(Pop(1), Push("expr")), - }, - "cast-type": { - Include("spaces"), - {`,`, Punctuation, Push("#pop", "type")}, - Default(Pop(1)), - }, - "catch": { - Include("spaces"), - {`(?:catch)\b`, Keyword, Push("expr", "function-param", "parenthesis-open")}, - Default(Pop(1)), - }, - "do": { - Include("spaces"), - Default(Pop(1), Push("do-while"), Push("expr")), - }, - "do-while": { - Include("spaces"), - {`(?:while)\b`, Keyword, Push("#pop", "parenthesis", "parenthesis-open")}, - }, - "while": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "expr", "parenthesis")}, - }, - "for": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "expr", "parenthesis")}, - }, - "if": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "else", "optional-semicolon", "expr", "parenthesis")}, - }, - "else": { - Include("spaces"), - {`(?:else)\b`, Keyword, Push("#pop", "expr")}, - Default(Pop(1)), - }, - "switch": { - Include("spaces"), - Default(Pop(1), Push("switch-body"), Push("bracket-open"), Push("expr")), - }, - "switch-body": { - Include("spaces"), - {`(?:case|default)\b`, Keyword, Push("case-block", "case")}, - {`\}`, Punctuation, Pop(1)}, - }, - "case": { - Include("spaces"), - {`:`, Punctuation, Pop(1)}, - Default(Pop(1), Push("case-sep"), Push("case-guard"), Push("expr")), - }, - "case-sep": { - Include("spaces"), - {`:`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "case")}, - }, - "case-guard": { - Include("spaces"), - {`(?:if)\b`, Keyword, Push("#pop", "parenthesis", "parenthesis-open")}, - Default(Pop(1)), - }, - "case-block": { - Include("spaces"), - {`(?!(?:case|default)\b|\})`, Keyword, Push("expr-statement")}, - Default(Pop(1)), - }, - "new": { - Include("spaces"), - Default(Pop(1), Push("call"), Push("parenthesis-open"), Push("type")), - }, - "array-decl": { - Include("spaces"), - {`\]`, Punctuation, Pop(1)}, - Default(Pop(1), Push("array-decl-sep"), Push("expr")), - }, - "array-decl-sep": { - Include("spaces"), - {`\]`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "array-decl")}, - }, - "array-access": { - Include("spaces"), - Default(Pop(1), Push("array-access-close"), Push("expr")), - }, - "array-access-close": { - Include("spaces"), - {`\]`, Punctuation, Pop(1)}, - }, - "comma": { - Include("spaces"), - {`,`, Punctuation, Pop(1)}, - }, - "colon": { - Include("spaces"), - {`:`, Punctuation, Pop(1)}, - }, - "semicolon": { - Include("spaces"), - {`;`, Punctuation, Pop(1)}, - }, - "optional-semicolon": { - Include("spaces"), - {`;`, Punctuation, Pop(1)}, - Default(Pop(1)), - }, - "ident": { - Include("spaces"), - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Pop(1)}, - }, - "dollar": { - Include("spaces"), - {`\{`, Punctuation, Push("#pop", "expr-chain", "bracket-close", "expr")}, - Default(Pop(1), Push("expr-chain")), - }, - "type-name": { - Include("spaces"), - {`_*[A-Z]\w*`, Name, Pop(1)}, - }, - "type-full-name": { - Include("spaces"), - {`\.`, Punctuation, Push("ident")}, - Default(Pop(1)), - }, - "type": { - Include("spaces"), - {`\?`, Punctuation, nil}, - {`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "type-check", "type-full-name")}, - {`\{`, Punctuation, Push("#pop", "type-check", "type-struct")}, - {`\(`, Punctuation, Push("#pop", "type-check", "type-parenthesis")}, - }, - "type-parenthesis": { - Include("spaces"), - Default(Pop(1), Push("parenthesis-close"), Push("type")), - }, - "type-check": { - Include("spaces"), - {`->`, Punctuation, Push("#pop", "type")}, - {`<(?!=)`, Punctuation, Push("type-param")}, - Default(Pop(1)), - }, - "type-struct": { - Include("spaces"), - {`\}`, Punctuation, Pop(1)}, - {`\?`, Punctuation, nil}, - {`>`, Punctuation, Push("comma", "type")}, - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "type-struct-sep", "type", "colon")}, - Include("class-body"), - }, - "type-struct-sep": { - Include("spaces"), - {`\}`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "type-struct")}, - }, - "type-param-type": { - {`\.[0-9]+`, LiteralNumberFloat, Pop(1)}, - {`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, Pop(1)}, - {`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, Pop(1)}, - {`[0-9]+\.[0-9]+`, LiteralNumberFloat, Pop(1)}, - {`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, Pop(1)}, - {`0x[0-9a-fA-F]+`, LiteralNumberHex, Pop(1)}, - {`[0-9]+`, LiteralNumberInteger, Pop(1)}, - {`'`, LiteralStringSingle, Push("#pop", "string-single")}, - {`"`, LiteralStringDouble, Push("#pop", "string-double")}, - {`~/(\\\\|\\/|[^/\n])*/[gim]*`, LiteralStringRegex, Pop(1)}, - {`\[`, Operator, Push("#pop", "array-decl")}, - Include("type"), - }, - "type-param": { - Include("spaces"), - Default(Pop(1), Push("type-param-sep"), Push("type-param-type")), - }, - "type-param-sep": { - Include("spaces"), - {`>`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "type-param")}, - }, - "type-param-constraint": { - Include("spaces"), - {`<(?!=)`, Punctuation, Push("#pop", "type-param-constraint-sep", "type-param-constraint-flag", "type-name")}, - Default(Pop(1)), - }, - "type-param-constraint-sep": { - Include("spaces"), - {`>`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "type-param-constraint-sep", "type-param-constraint-flag", "type-name")}, - }, - "type-param-constraint-flag": { - Include("spaces"), - {`:`, Punctuation, Push("#pop", "type-param-constraint-flag-type")}, - Default(Pop(1)), - }, - "type-param-constraint-flag-type": { - Include("spaces"), - {`\(`, Punctuation, Push("#pop", "type-param-constraint-flag-type-sep", "type")}, - Default(Pop(1), Push("type")), - }, - "type-param-constraint-flag-type-sep": { - Include("spaces"), - {`\)`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("type")}, - }, - "parenthesis": { - Include("spaces"), - Default(Pop(1), Push("parenthesis-close"), Push("flag"), Push("expr")), - }, - "parenthesis-open": { - Include("spaces"), - {`\(`, Punctuation, Pop(1)}, - }, - "parenthesis-close": { - Include("spaces"), - {`\)`, Punctuation, Pop(1)}, - }, - "var": { - Include("spaces"), - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Text, Push("#pop", "var-sep", "assign", "flag", "prop-get-set")}, - }, - "var-sep": { - Include("spaces"), - {`,`, Punctuation, Push("#pop", "var")}, - Default(Pop(1)), - }, - "assign": { - Include("spaces"), - {`=`, Operator, Push("#pop", "expr")}, - Default(Pop(1)), - }, - "flag": { - Include("spaces"), - {`:`, Punctuation, Push("#pop", "type")}, - Default(Pop(1)), - }, - "ternary": { - Include("spaces"), - {`:`, Operator, Pop(1)}, - }, - "call": { - Include("spaces"), - {`\)`, Punctuation, Pop(1)}, - Default(Pop(1), Push("call-sep"), Push("expr")), - }, - "call-sep": { - Include("spaces"), - {`\)`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "call")}, - }, - "bracket": { - Include("spaces"), - {`(?!(?:\$\s*[a-z]\b|\$(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+))))(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "bracket-check")}, - {`'`, LiteralStringSingle, Push("#pop", "bracket-check", "string-single")}, - {`"`, LiteralStringDouble, Push("#pop", "bracket-check", "string-double")}, - Default(Pop(1), Push("block")), - }, - "bracket-check": { - Include("spaces"), - {`:`, Punctuation, Push("#pop", "object-sep", "expr")}, - Default(Pop(1), Push("block"), Push("optional-semicolon"), Push("expr-chain")), - }, - "block": { - Include("spaces"), - {`\}`, Punctuation, Pop(1)}, - Default(Push("expr-statement")), - }, - "object": { - Include("spaces"), - {`\}`, Punctuation, Pop(1)}, - Default(Pop(1), Push("object-sep"), Push("expr"), Push("colon"), Push("ident-or-string")), - }, - "ident-or-string": { - Include("spaces"), - {`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Pop(1)}, - {`'`, LiteralStringSingle, Push("#pop", "string-single")}, - {`"`, LiteralStringDouble, Push("#pop", "string-double")}, - }, - "object-sep": { - Include("spaces"), - {`\}`, Punctuation, Pop(1)}, - {`,`, Punctuation, Push("#pop", "object")}, - }, - } -} - -func haxePreProcMutator(state *LexerState) error { - stack, ok := state.Get("haxe-pre-proc").([][]string) - if !ok { - stack = [][]string{} - } - - proc := state.Groups[2] - switch proc { - case "if": - stack = append(stack, state.Stack) - case "else", "elseif": - if len(stack) > 0 { - state.Stack = stack[len(stack)-1] - } - case "end": - if len(stack) > 0 { - stack = stack[:len(stack)-1] - } - } - - if proc == "if" || proc == "elseif" { - state.Stack = append(state.Stack, "preproc-expr") - } - - if proc == "error" { - state.Stack = append(state.Stack, "preproc-error") - } - state.Set("haxe-pre-proc", stack) - return nil -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/html.go b/vendor/github.com/alecthomas/chroma/v2/lexers/html.go deleted file mode 100644 index c858042b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/html.go +++ /dev/null @@ -1,8 +0,0 @@ -package lexers - -import ( - "github.com/alecthomas/chroma/v2" -) - -// HTML lexer. -var HTML = chroma.MustNewXMLLexer(embedded, "embedded/html.xml") diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/http.go b/vendor/github.com/alecthomas/chroma/v2/lexers/http.go deleted file mode 100644 index b57cb1b8..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/http.go +++ /dev/null @@ -1,131 +0,0 @@ -package lexers - -import ( - "strings" - - . "github.com/alecthomas/chroma/v2" // nolint -) - -// HTTP lexer. -var HTTP = Register(httpBodyContentTypeLexer(MustNewLexer( - &Config{ - Name: "HTTP", - Aliases: []string{"http"}, - Filenames: []string{}, - MimeTypes: []string{}, - NotMultiline: true, - DotAll: true, - }, - httpRules, -))) - -func httpRules() Rules { - return Rules{ - "root": { - {`(GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|PATCH|CONNECT)( +)([^ ]+)( +)(HTTP)(/)([123](?:\.[01])?)(\r?\n|\Z)`, ByGroups(NameFunction, Text, NameNamespace, Text, KeywordReserved, Operator, LiteralNumber, Text), Push("headers")}, - {`(HTTP)(/)([123](?:\.[01])?)( +)(\d{3})( *)([^\r\n]*)(\r?\n|\Z)`, ByGroups(KeywordReserved, Operator, LiteralNumber, Text, LiteralNumber, Text, NameException, Text), Push("headers")}, - }, - "headers": { - {`([^\s:]+)( *)(:)( *)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpHeaderBlock), nil}, - {`([\t ]+)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpContinuousHeaderBlock), nil}, - {`\r?\n`, Text, Push("content")}, - }, - "content": { - {`.+`, EmitterFunc(httpContentBlock), nil}, - }, - } -} - -func httpContentBlock(groups []string, state *LexerState) Iterator { - tokens := []Token{ - {Generic, groups[0]}, - } - return Literator(tokens...) -} - -func httpHeaderBlock(groups []string, state *LexerState) Iterator { - tokens := []Token{ - {Name, groups[1]}, - {Text, groups[2]}, - {Operator, groups[3]}, - {Text, groups[4]}, - {Literal, groups[5]}, - {Text, groups[6]}, - } - return Literator(tokens...) -} - -func httpContinuousHeaderBlock(groups []string, state *LexerState) Iterator { - tokens := []Token{ - {Text, groups[1]}, - {Literal, groups[2]}, - {Text, groups[3]}, - } - return Literator(tokens...) -} - -func httpBodyContentTypeLexer(lexer Lexer) Lexer { return &httpBodyContentTyper{lexer} } - -type httpBodyContentTyper struct{ Lexer } - -func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit - var contentType string - var isContentType bool - var subIterator Iterator - - it, err := d.Lexer.Tokenise(options, text) - if err != nil { - return nil, err - } - - return func() Token { - token := it() - - if token == EOF { - if subIterator != nil { - return subIterator() - } - return EOF - } - - switch { - case token.Type == Name && strings.ToLower(token.Value) == "content-type": - { - isContentType = true - } - case token.Type == Literal && isContentType: - { - isContentType = false - contentType = strings.TrimSpace(token.Value) - pos := strings.Index(contentType, ";") - if pos > 0 { - contentType = strings.TrimSpace(contentType[:pos]) - } - } - case token.Type == Generic && contentType != "": - { - lexer := MatchMimeType(contentType) - - // application/calendar+xml can be treated as application/xml - // if there's not a better match. - if lexer == nil && strings.Contains(contentType, "+") { - slashPos := strings.Index(contentType, "/") - plusPos := strings.LastIndex(contentType, "+") - contentType = contentType[:slashPos+1] + contentType[plusPos+1:] - lexer = MatchMimeType(contentType) - } - - if lexer == nil { - token.Type = Text - } else { - subIterator, err = lexer.Tokenise(nil, token.Value) - if err != nil { - panic(err) - } - return EOF - } - } - } - return token - }, nil -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/lexers.go b/vendor/github.com/alecthomas/chroma/v2/lexers/lexers.go deleted file mode 100644 index 4fa35ad2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/lexers.go +++ /dev/null @@ -1,79 +0,0 @@ -package lexers - -import ( - "embed" - "io/fs" - - "github.com/alecthomas/chroma/v2" -) - -//go:embed embedded -var embedded embed.FS - -// GlobalLexerRegistry is the global LexerRegistry of Lexers. -var GlobalLexerRegistry = func() *chroma.LexerRegistry { - reg := chroma.NewLexerRegistry() - // index(reg) - paths, err := fs.Glob(embedded, "embedded/*.xml") - if err != nil { - panic(err) - } - for _, path := range paths { - reg.Register(chroma.MustNewXMLLexer(embedded, path)) - } - return reg -}() - -// Names of all lexers, optionally including aliases. -func Names(withAliases bool) []string { - return GlobalLexerRegistry.Names(withAliases) -} - -// Get a Lexer by name, alias or file extension. -// -// Note that this if there isn't an exact match on name or alias, this will -// call Match(), so it is not efficient. -func Get(name string) chroma.Lexer { - return GlobalLexerRegistry.Get(name) -} - -// MatchMimeType attempts to find a lexer for the given MIME type. -func MatchMimeType(mimeType string) chroma.Lexer { - return GlobalLexerRegistry.MatchMimeType(mimeType) -} - -// Match returns the first lexer matching filename. -// -// Note that this iterates over all file patterns in all lexers, so it's not -// particularly efficient. -func Match(filename string) chroma.Lexer { - return GlobalLexerRegistry.Match(filename) -} - -// Register a Lexer with the global registry. -func Register(lexer chroma.Lexer) chroma.Lexer { - return GlobalLexerRegistry.Register(lexer) -} - -// Analyse text content and return the "best" lexer.. -func Analyse(text string) chroma.Lexer { - return GlobalLexerRegistry.Analyse(text) -} - -// PlaintextRules is used for the fallback lexer as well as the explicit -// plaintext lexer. -func PlaintextRules() chroma.Rules { - return chroma.Rules{ - "root": []chroma.Rule{ - {`.+`, chroma.Text, nil}, - {`\n`, chroma.Text, nil}, - }, - } -} - -// Fallback lexer if no other is found. -var Fallback chroma.Lexer = chroma.MustNewLexer(&chroma.Config{ - Name: "fallback", - Filenames: []string{"*"}, - Priority: -1, -}, PlaintextRules) diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go b/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go deleted file mode 100644 index 1fb9f5bf..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/markdown.go +++ /dev/null @@ -1,47 +0,0 @@ -package lexers - -import ( - . "github.com/alecthomas/chroma/v2" // nolint -) - -// Markdown lexer. -var Markdown = Register(DelegatingLexer(HTML, MustNewLexer( - &Config{ - Name: "markdown", - Aliases: []string{"md", "mkd"}, - Filenames: []string{"*.md", "*.mkd", "*.markdown"}, - MimeTypes: []string{"text/x-markdown"}, - }, - markdownRules, -))) - -func markdownRules() Rules { - return Rules{ - "root": { - {`^(#[^#].+\n)`, ByGroups(GenericHeading), nil}, - {`^(#{2,6}.+\n)`, ByGroups(GenericSubheading), nil}, - {`^(\s*)([*-] )(\[[ xX]\])( .+\n)`, ByGroups(Text, Keyword, Keyword, UsingSelf("inline")), nil}, - {`^(\s*)([*-])(\s)(.+\n)`, ByGroups(Text, Keyword, Text, UsingSelf("inline")), nil}, - {`^(\s*)([0-9]+\.)( .+\n)`, ByGroups(Text, Keyword, UsingSelf("inline")), nil}, - {`^(\s*>\s)(.+\n)`, ByGroups(Keyword, GenericEmph), nil}, - {"^(```\\n)([\\w\\W]*?)(^```$)", ByGroups(String, Text, String), nil}, - { - "^(```)(\\w+)(\\n)([\\w\\W]*?)(^```$)", - UsingByGroup(2, 4, String, String, String, Text, String), - nil, - }, - Include("inline"), - }, - "inline": { - {`\\.`, Text, nil}, - {`(\s)(\*|_)((?:(?!\2).)*)(\2)((?=\W|\n))`, ByGroups(Text, GenericEmph, GenericEmph, GenericEmph, Text), nil}, - {`(\s)((\*\*|__).*?)\3((?=\W|\n))`, ByGroups(Text, GenericStrong, GenericStrong, Text), nil}, - {`(\s)(~~[^~]+~~)((?=\W|\n))`, ByGroups(Text, GenericDeleted, Text), nil}, - {"`[^`]+`", LiteralStringBacktick, nil}, - {`[@#][\w/:]+`, NameEntity, nil}, - {`(!?\[)([^]]+)(\])(\()([^)]+)(\))`, ByGroups(Text, NameTag, Text, Text, NameAttribute, Text), nil}, - {`[^\\\s]+`, Other, nil}, - {`.|\n`, Other, nil}, - }, - } -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/mysql.go b/vendor/github.com/alecthomas/chroma/v2/lexers/mysql.go deleted file mode 100644 index 32e94c2f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/mysql.go +++ /dev/null @@ -1,33 +0,0 @@ -package lexers - -import ( - "regexp" -) - -var ( - mysqlAnalyserNameBetweenBacktickRe = regexp.MustCompile("`[a-zA-Z_]\\w*`") - mysqlAnalyserNameBetweenBracketRe = regexp.MustCompile(`\[[a-zA-Z_]\w*\]`) -) - -func init() { // nolint: gochecknoinits - Get("mysql"). - SetAnalyser(func(text string) float32 { - nameBetweenBacktickCount := len(mysqlAnalyserNameBetweenBacktickRe.FindAllString(text, -1)) - nameBetweenBracketCount := len(mysqlAnalyserNameBetweenBracketRe.FindAllString(text, -1)) - - var result float32 - - // Same logic as above in the TSQL analysis. - dialectNameCount := nameBetweenBacktickCount + nameBetweenBracketCount - if dialectNameCount >= 1 && nameBetweenBacktickCount >= (2*nameBetweenBracketCount) { - // Found at least twice as many `name` as [name]. - result += 0.5 - } else if nameBetweenBacktickCount > nameBetweenBracketCount { - result += 0.2 - } else if nameBetweenBacktickCount > 0 { - result += 0.1 - } - - return result - }) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/php.go b/vendor/github.com/alecthomas/chroma/v2/lexers/php.go deleted file mode 100644 index ff82f6ea..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/php.go +++ /dev/null @@ -1,37 +0,0 @@ -package lexers - -import ( - "strings" - - . "github.com/alecthomas/chroma/v2" // nolint -) - -// phtml lexer is PHP in HTML. -var _ = Register(DelegatingLexer(HTML, MustNewLexer( - &Config{ - Name: "PHTML", - Aliases: []string{"phtml"}, - Filenames: []string{"*.phtml", "*.php", "*.php[345]", "*.inc"}, - MimeTypes: []string{"application/x-php", "application/x-httpd-php", "application/x-httpd-php3", "application/x-httpd-php4", "application/x-httpd-php5", "text/x-php"}, - DotAll: true, - CaseInsensitive: true, - EnsureNL: true, - Priority: 2, - }, - func() Rules { - return Get("PHP").(*RegexLexer).MustRules(). - Rename("root", "php"). - Merge(Rules{ - "root": { - {`<\?(php)?`, CommentPreproc, Push("php")}, - {`[^<]+`, Other, nil}, - {`<`, Other, nil}, - }, - }) - }, -).SetAnalyser(func(text string) float32 { - if strings.Contains(text, ">|>|»|\)|\]|\})` - colonPairPattern = `(?:)(?\w[\w'-]*)(?` + colonPairOpeningBrackets + `)` - colonPairLookahead = `(?=(:['\w-]+` + - colonPairOpeningBrackets + `.+?` + colonPairClosingBrackets + `)?` - namePattern = `(?:(?!` + colonPairPattern + `)(?:::|[\w':-]))+` - variablePattern = `[$@%&]+[.^:?=!~]?` + namePattern - globalVariablePattern = `[$@%&]+\*` + namePattern - ) - - keywords := []string{ - `BEGIN`, `CATCH`, `CHECK`, `CLOSE`, `CONTROL`, `DOC`, `END`, `ENTER`, `FIRST`, `INIT`, - `KEEP`, `LAST`, `LEAVE`, `NEXT`, `POST`, `PRE`, `QUIT`, `UNDO`, `anon`, `augment`, `but`, - `class`, `constant`, `default`, `does`, `else`, `elsif`, `enum`, `for`, `gather`, `given`, - `grammar`, `has`, `if`, `import`, `is`, `of`, `let`, `loop`, `made`, `make`, `method`, - `module`, `multi`, `my`, `need`, `orwith`, `our`, `proceed`, `proto`, `repeat`, `require`, - `where`, `return`, `return-rw`, `returns`, `->`, `-->`, `role`, `state`, `sub`, `no`, - `submethod`, `subset`, `succeed`, `supersede`, `try`, `unit`, `unless`, `until`, - `use`, `when`, `while`, `with`, `without`, `export`, `native`, `repr`, `required`, `rw`, - `symbol`, `default`, `cached`, `DEPRECATED`, `dynamic`, `hidden-from-backtrace`, `nodal`, - `pure`, `raw`, `start`, `react`, `supply`, `whenever`, `also`, `rule`, `token`, `regex`, - `dynamic-scope`, `built`, `temp`, - } - - keywordsPattern := Words(`(?)`, `(>=)`, `minmax`, `notandthen`, `S`, - } - - wordOperatorsPattern := Words(`(?<=^|\b|\s)`, `(?=$|\b|\s)`, wordOperators...) - - operators := []string{ - `++`, `--`, `-`, `**`, `!`, `+`, `~`, `?`, `+^`, `~^`, `?^`, `^`, `*`, `/`, `%`, `%%`, `+&`, - `+<`, `+>`, `~&`, `~<`, `~>`, `?&`, `+|`, `+^`, `~|`, `~^`, `?`, `?|`, `?^`, `&`, `^`, - `<=>`, `^…^`, `^…`, `…^`, `…`, `...`, `...^`, `^...`, `^...^`, `..`, `..^`, `^..`, `^..^`, - `::=`, `:=`, `!=`, `==`, `<=`, `<`, `>=`, `>`, `~~`, `===`, `&&`, `||`, `|`, `^^`, `//`, - `??`, `!!`, `^fff^`, `^ff^`, `<==`, `==>`, `<<==`, `==>>`, `=>`, `=`, `<<`, `«`, `>>`, `»`, - `,`, `>>.`, `».`, `.&`, `.=`, `.^`, `.?`, `.+`, `.*`, `.`, `∘`, `∩`, `⊍`, `∪`, `⊎`, `∖`, - `⊖`, `≠`, `≤`, `≥`, `=:=`, `=~=`, `≅`, `∈`, `∉`, `≡`, `≢`, `∋`, `∌`, `⊂`, `⊄`, `⊆`, `⊈`, - `⊃`, `⊅`, `⊇`, `⊉`, `:`, `!!!`, `???`, `¯`, `×`, `÷`, `−`, `⁺`, `⁻`, - } - - operatorsPattern := Words(``, ``, operators...) - - builtinTypes := []string{ - `False`, `True`, `Order`, `More`, `Less`, `Same`, `Any`, `Array`, `Associative`, `AST`, - `atomicint`, `Attribute`, `Backtrace`, `Backtrace::Frame`, `Bag`, `Baggy`, `BagHash`, - `Blob`, `Block`, `Bool`, `Buf`, `Callable`, `CallFrame`, `Cancellation`, `Capture`, - `CArray`, `Channel`, `Code`, `compiler`, `Complex`, `ComplexStr`, `CompUnit`, - `CompUnit::PrecompilationRepository`, `CompUnit::Repository`, `Empty`, - `CompUnit::Repository::FileSystem`, `CompUnit::Repository::Installation`, `Cool`, - `CurrentThreadScheduler`, `CX::Warn`, `CX::Take`, `CX::Succeed`, `CX::Return`, `CX::Redo`, - `CX::Proceed`, `CX::Next`, `CX::Last`, `CX::Emit`, `CX::Done`, `Cursor`, `Date`, `Dateish`, - `DateTime`, `Distribution`, `Distribution::Hash`, `Distribution::Locally`, - `Distribution::Path`, `Distribution::Resource`, `Distro`, `Duration`, `Encoding`, - `Encoding::GlobalLexerRegistry`, `Endian`, `Enumeration`, `Exception`, `Failure`, `FatRat`, `Grammar`, - `Hash`, `HyperWhatever`, `Instant`, `Int`, `int`, `int16`, `int32`, `int64`, `int8`, `str`, - `IntStr`, `IO`, `IO::ArgFiles`, `IO::CatHandle`, `IO::Handle`, `IO::Notification`, - `IO::Notification::Change`, `IO::Path`, `IO::Path::Cygwin`, `IO::Path::Parts`, - `IO::Path::QNX`, `IO::Path::Unix`, `IO::Path::Win32`, `IO::Pipe`, `IO::Socket`, - `IO::Socket::Async`, `IO::Socket::Async::ListenSocket`, `IO::Socket::INET`, `IO::Spec`, - `IO::Spec::Cygwin`, `IO::Spec::QNX`, `IO::Spec::Unix`, `IO::Spec::Win32`, `IO::Special`, - `Iterable`, `Iterator`, `Junction`, `Kernel`, `Label`, `List`, `Lock`, `Lock::Async`, - `Lock::ConditionVariable`, `long`, `longlong`, `Macro`, `Map`, `Match`, - `Metamodel::AttributeContainer`, `Metamodel::C3MRO`, `Metamodel::ClassHOW`, - `Metamodel::ConcreteRoleHOW`, `Metamodel::CurriedRoleHOW`, `Metamodel::DefiniteHOW`, - `Metamodel::Documenting`, `Metamodel::EnumHOW`, `Metamodel::Finalization`, - `Metamodel::MethodContainer`, `Metamodel::Mixins`, `Metamodel::MROBasedMethodDispatch`, - `Metamodel::MultipleInheritance`, `Metamodel::Naming`, `Metamodel::Primitives`, - `Metamodel::PrivateMethodContainer`, `Metamodel::RoleContainer`, `Metamodel::RolePunning`, - `Metamodel::Stashing`, `Metamodel::Trusting`, `Metamodel::Versioning`, `Method`, `Mix`, - `MixHash`, `Mixy`, `Mu`, `NFC`, `NFD`, `NFKC`, `NFKD`, `Nil`, `Num`, `num32`, `num64`, - `Numeric`, `NumStr`, `ObjAt`, `Order`, `Pair`, `Parameter`, `Perl`, `Pod::Block`, - `Pod::Block::Code`, `Pod::Block::Comment`, `Pod::Block::Declarator`, `Pod::Block::Named`, - `Pod::Block::Para`, `Pod::Block::Table`, `Pod::Heading`, `Pod::Item`, `Pointer`, - `Positional`, `PositionalBindFailover`, `Proc`, `Proc::Async`, `Promise`, `Proxy`, - `PseudoStash`, `QuantHash`, `RaceSeq`, `Raku`, `Range`, `Rat`, `Rational`, `RatStr`, - `Real`, `Regex`, `Routine`, `Routine::WrapHandle`, `Scalar`, `Scheduler`, `Semaphore`, - `Seq`, `Sequence`, `Set`, `SetHash`, `Setty`, `Signature`, `size_t`, `Slip`, `Stash`, - `Str`, `StrDistance`, `Stringy`, `Sub`, `Submethod`, `Supplier`, `Supplier::Preserving`, - `Supply`, `Systemic`, `Tap`, `Telemetry`, `Telemetry::Instrument::Thread`, - `Telemetry::Instrument::ThreadPool`, `Telemetry::Instrument::Usage`, `Telemetry::Period`, - `Telemetry::Sampler`, `Thread`, `Test`, `ThreadPoolScheduler`, `UInt`, `uint16`, `uint32`, - `uint64`, `uint8`, `Uni`, `utf8`, `ValueObjAt`, `Variable`, `Version`, `VM`, `Whatever`, - `WhateverCode`, `WrapHandle`, `NativeCall`, - // Pragmas - `precompilation`, `experimental`, `worries`, `MONKEY-TYPING`, `MONKEY-SEE-NO-EVAL`, - `MONKEY-GUTS`, `fatal`, `lib`, `isms`, `newline`, `nqp`, `soft`, - `strict`, `trace`, `variables`, - } - - builtinTypesPattern := Words(`(? 0 { - if tokenClass == rakuPod { - match, err := podRegex.FindRunesMatchStartingAt(text, searchPos+nChars) - if err == nil { - closingChars = match.Runes() - nextClosePos = match.Index - } else { - nextClosePos = -1 - } - } else { - nextClosePos = indexAt(text, closingChars, searchPos+nChars) - } - - nextOpenPos := indexAt(text, openingChars, searchPos+nChars) - - switch { - case nextClosePos == -1: - nextClosePos = len(text) - nestingLevel = 0 - case nextOpenPos != -1 && nextOpenPos < nextClosePos: - nestingLevel++ - nChars = len(openingChars) - searchPos = nextOpenPos - default: // next_close_pos < next_open_pos - nestingLevel-- - nChars = len(closingChars) - searchPos = nextClosePos - } - } - - endPos = nextClosePos - } - - if endPos < 0 { - // if we didn't find a closer, just highlight the - // rest of the text in this class - endPos = len(text) - } - - adverbre := regexp.MustCompile(`:to\b|:heredoc\b`) - var heredocTerminator []rune - var endHeredocPos int - if adverbre.MatchString(string(adverbs)) { - if endPos != len(text) { - heredocTerminator = text[state.Pos:endPos] - nChars = len(heredocTerminator) - } else { - endPos = state.Pos + 1 - heredocTerminator = []rune{} - nChars = 0 - } - - if nChars > 0 { - endHeredocPos = indexAt(text[endPos:], heredocTerminator, 0) - if endHeredocPos > -1 { - endPos += endHeredocPos - } else { - endPos = len(text) - } - } - } - - textBetweenBrackets := string(text[state.Pos:endPos]) - switch tokenClass { - case rakuPod, rakuPodDeclaration, rakuNameAttribute: - state.NamedGroups[`value`] = textBetweenBrackets - state.NamedGroups[`closing_delimiters`] = string(closingChars) - case rakuQuote: - if len(heredocTerminator) > 0 { - // Length of heredoc terminator + closing chars + `;` - heredocFristPunctuationLen := nChars + len(openingChars) + 1 - - state.NamedGroups[`opening_delimiters`] = string(openingChars) + - string(text[state.Pos:state.Pos+heredocFristPunctuationLen]) - - state.NamedGroups[`value`] = - string(text[state.Pos+heredocFristPunctuationLen : endPos]) - - if endHeredocPos > -1 { - state.NamedGroups[`closing_delimiters`] = string(heredocTerminator) - } - } else { - state.NamedGroups[`value`] = textBetweenBrackets - if nChars > 0 { - state.NamedGroups[`closing_delimiters`] = string(closingChars) - } - } - default: - state.Groups = []string{state.Groups[0] + string(text[state.Pos:endPos+nChars])} - } - - state.Pos = endPos + nChars - - return nil - } - } - - // Raku rules - // Empty capture groups are placeholders and will be replaced by mutators - // DO NOT REMOVE THEM! - return Rules{ - "root": { - // Placeholder, will be overwritten by mutators, DO NOT REMOVE! - {`\A\z`, nil, nil}, - Include("common"), - {`{`, Punctuation, Push(`root`)}, - {`\(`, Punctuation, Push(`root`)}, - {`[)}]`, Punctuation, Pop(1)}, - {`;`, Punctuation, nil}, - {`\[|\]`, Operator, nil}, - {`.+?`, Text, nil}, - }, - "common": { - {`^#![^\n]*$`, CommentHashbang, nil}, - Include("pod"), - // Multi-line, Embedded comment - { - "#`(?(?" + bracketsPattern + `)\k*)`, - CommentMultiline, - findBrackets(rakuMultilineComment), - }, - {`#[^\n]*$`, CommentSingle, nil}, - // /regex/ - { - `(?<=(?:^|\(|=|:|~~|\[|{|,|=>)\s*)(/)(?!\]|\))((?:\\\\|\\/|.)*?)((?>)(\S+?)(<<)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, - {`(»)(\S+?)(«)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, - // Hyperoperator | «*« - {`(<<)(\S+?)(<<)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, - {`(«)(\S+?)(«)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, - // Hyperoperator | »*» - {`(>>)(\S+?)(>>)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, - {`(»)(\S+?)(»)`, ByGroups(Operator, UsingSelf("root"), Operator), nil}, - // <> - {`(?>)[^\n])+?[},;] *\n)(?!(?:(?!>>).)+?>>\S+?>>)`, Punctuation, Push("<<")}, - // «quoted words» - {`(? operators | something < onething > something - { - `(?<=[$@%&]?\w[\w':-]* +)(<=?)( *[^ ]+? *)(>=?)(?= *[$@%&]?\w[\w':-]*)`, - ByGroups(Operator, UsingSelf("root"), Operator), - nil, - }, - // - { - `(?])+?)(>)(?!\s*(?:\d+|\.(?:Int|Numeric)|[$@%]\*?\w[\w':-]*[^(]|\s+\[))`, - ByGroups(Punctuation, String, Punctuation), - nil, - }, - {`C?X::['\w:-]+`, NameException, nil}, - Include("metaoperator"), - // Pair | key => value - { - `(\w[\w'-]*)(\s*)(=>)`, - ByGroups(String, Text, Operator), - nil, - }, - Include("colon-pair"), - // Token - { - `(?<=(?:^|\s)(?:regex|token|rule)(\s+))` + namePattern + colonPairLookahead + `\s*[({])`, - NameFunction, - Push("token", "name-adverb"), - }, - // Substitution - {`(?<=^|\b|\s)(?(?:qq|q|Q))(?(?::?(?:heredoc|to|qq|ww|q|w|s|a|h|f|c|b|to|v|x))*)(?\s*)(?(?[^0-9a-zA-Z:\s])\k*)`, - EmitterFunc(quote), - findBrackets(rakuQuote), - }, - // Function - { - `\b` + namePattern + colonPairLookahead + `\()`, - NameFunction, - Push("name-adverb"), - }, - // Method - { - `(?(?[^\w:\s])\k*)`, - ByGroupNames( - map[string]Emitter{ - `opening_delimiters`: Punctuation, - `delimiter`: nil, - }, - ), - findBrackets(rakuMatchRegex), - }, - }, - "substitution": { - Include("colon-pair-attribute"), - // Substitution | s{regex} = value - { - `(?(?` + bracketsPattern + `)\k*)`, - ByGroupNames(map[string]Emitter{ - `opening_delimiters`: Punctuation, - `delimiter`: nil, - }), - findBrackets(rakuMatchRegex), - }, - // Substitution | s/regex/string/ - { - `(?[^\w:\s])`, - Punctuation, - findBrackets(rakuSubstitutionRegex), - }, - }, - "number": { - {`0_?[0-7]+(_[0-7]+)*`, LiteralNumberOct, nil}, - {`0x[0-9A-Fa-f]+(_[0-9A-Fa-f]+)*`, LiteralNumberHex, nil}, - {`0b[01]+(_[01]+)*`, LiteralNumberBin, nil}, - { - `(?i)(\d*(_\d*)*\.\d+(_\d*)*|\d+(_\d*)*\.\d+(_\d*)*)(e[+-]?\d+)?`, - LiteralNumberFloat, - nil, - }, - {`(?i)\d+(_\d*)*e[+-]?\d+(_\d*)*`, LiteralNumberFloat, nil}, - {`(?<=\d+)i`, NameConstant, nil}, - {`\d+(_\d+)*`, LiteralNumberInteger, nil}, - }, - "name-adverb": { - Include("colon-pair-attribute-keyvalue"), - Default(Pop(1)), - }, - "colon-pair": { - // :key(value) - {colonPairPattern, colonPair(String), findBrackets(rakuNameAttribute)}, - // :123abc - { - `(:)(\d+)(\w[\w'-]*)`, - ByGroups(Punctuation, UsingSelf("number"), String), - nil, - }, - // :key - {`(:)(!?)(\w[\w'-]*)`, ByGroups(Punctuation, Operator, String), nil}, - {`\s+`, Text, nil}, - }, - "colon-pair-attribute": { - // :key(value) - {colonPairPattern, colonPair(NameAttribute), findBrackets(rakuNameAttribute)}, - // :123abc - { - `(:)(\d+)(\w[\w'-]*)`, - ByGroups(Punctuation, UsingSelf("number"), NameAttribute), - nil, - }, - // :key - {`(:)(!?)(\w[\w'-]*)`, ByGroups(Punctuation, Operator, NameAttribute), nil}, - {`\s+`, Text, nil}, - }, - "colon-pair-attribute-keyvalue": { - // :key(value) - {colonPairPattern, colonPair(NameAttribute), findBrackets(rakuNameAttribute)}, - }, - "escape-qq": { - { - `(? - { - `(?`), - tokenType: Punctuation, - stateName: `root`, - pushState: true, - }), - }, - // {code} - Include(`closure`), - // Properties - {`(:)(\w+)`, ByGroups(Punctuation, NameAttribute), nil}, - // Operator - {`\|\||\||&&|&|\.\.|\*\*|%%|%|:|!|<<|«|>>|»|\+|\*\*|\*|\?|=|~|<~~>`, Operator, nil}, - // Anchors - {`\^\^|\^|\$\$|\$`, NameEntity, nil}, - {`\.`, NameEntity, nil}, - {`#[^\n]*\n`, CommentSingle, nil}, - // Lookaround - { - `(?`), - tokenType: Punctuation, - stateName: `regex`, - pushState: true, - }), - }, - { - `(?)`, - ByGroups(Punctuation, Operator, OperatorWord, Punctuation), - nil, - }, - // <$variable> - { - `(?)`, - ByGroups(Punctuation, Operator, NameVariable, Punctuation), - nil, - }, - // Capture markers - {`(?`, Operator, nil}, - { - `(? - {`(?`, Punctuation, Pop(1)}, - // - { - `\(`, - Punctuation, - replaceRule(ruleReplacingConfig{ - delimiter: []rune(`)>`), - tokenType: Punctuation, - stateName: `root`, - popState: true, - pushState: true, - }), - }, - // - { - `\s+`, - StringRegex, - replaceRule(ruleReplacingConfig{ - delimiter: []rune(`>`), - tokenType: Punctuation, - stateName: `regex`, - popState: true, - pushState: true, - }), - }, - // - { - `:`, - Punctuation, - replaceRule(ruleReplacingConfig{ - delimiter: []rune(`>`), - tokenType: Punctuation, - stateName: `root`, - popState: true, - pushState: true, - }), - }, - }, - "regex-variable": { - Include(`regex-starting-operators`), - // - {`(&)?(\w[\w':-]*)(>)`, ByGroups(Operator, NameFunction, Punctuation), Pop(1)}, - // `, Punctuation, Pop(1)}, - Include("regex-class-builtin"), - Include("variable"), - Include(`regex-starting-operators`), - Include("colon-pair-attribute"), - {`(?] - { - `\b([RZX]+)\b(\[)([^\s\]]+?)(\])`, - ByGroups(OperatorWord, Punctuation, UsingSelf("root"), Punctuation), - nil, - }, - // Z=> - {`\b([RZX]+)\b([^\s\]]+)`, ByGroups(OperatorWord, UsingSelf("operator")), nil}, - }, - "operator": { - // Word Operator - {wordOperatorsPattern, OperatorWord, nil}, - // Operator - {operatorsPattern, Operator, nil}, - }, - "pod": { - // Single-line pod declaration - {`(#[|=])\s`, Keyword, Push("pod-single")}, - // Multi-line pod declaration - { - "(?#[|=])(?(?" + bracketsPattern + `)\k*)(?)(?)`, - ByGroupNames( - map[string]Emitter{ - `keyword`: Keyword, - `opening_delimiters`: Punctuation, - `delimiter`: nil, - `value`: UsingSelf("pod-declaration"), - `closing_delimiters`: Punctuation, - }), - findBrackets(rakuPodDeclaration), - }, - Include("pod-blocks"), - }, - "pod-blocks": { - // =begin code - { - `(?<=^ *)(? *)(?=begin)(? +)(?code)(?[^\n]*)(?.*?)(?^\k)(?=end)(? +)\k`, - EmitterFunc(podCode), - nil, - }, - // =begin - { - `(?<=^ *)(? *)(?=begin)(? +)(?!code)(?\w[\w'-]*)(?[^\n]*)(?)(?)`, - ByGroupNames( - map[string]Emitter{ - `ws`: Comment, - `keyword`: Keyword, - `ws2`: StringDoc, - `name`: Keyword, - `config`: EmitterFunc(podConfig), - `value`: UsingSelf("pod-begin"), - `closing_delimiters`: Keyword, - }), - findBrackets(rakuPod), - }, - // =for ... - { - `(?<=^ *)(? *)(?=(?:for|defn))(? +)(?\w[\w'-]*)(?[^\n]*\n)`, - ByGroups(Comment, Keyword, StringDoc, Keyword, EmitterFunc(podConfig)), - Push("pod-paragraph"), - }, - // =config - { - `(?<=^ *)(? *)(?=config)(? +)(?\w[\w'-]*)(?[^\n]*\n)`, - ByGroups(Comment, Keyword, StringDoc, Keyword, EmitterFunc(podConfig)), - nil, - }, - // =alias - { - `(?<=^ *)(? *)(?=alias)(? +)(?\w[\w'-]*)(?[^\n]*\n)`, - ByGroups(Comment, Keyword, StringDoc, Keyword, StringDoc), - nil, - }, - // =encoding - { - `(?<=^ *)(? *)(?=encoding)(? +)(?[^\n]+)`, - ByGroups(Comment, Keyword, StringDoc, Name), - nil, - }, - // =para ... - { - `(?<=^ *)(? *)(?=(?:para|table|pod))(?(? *)(?=head\d+)(? *)(?#?)`, - ByGroups(Comment, Keyword, GenericHeading, Keyword), - Push("pod-heading"), - }, - // =item ... - { - `(?<=^ *)(? *)(?=(?:item\d*|comment|data|[A-Z]+))(? *)(?#?)`, - ByGroups(Comment, Keyword, StringDoc, Keyword), - Push("pod-paragraph"), - }, - { - `(?<=^ *)(? *)(?=finish)(?[^\n]*)`, - ByGroups(Comment, Keyword, EmitterFunc(podConfig)), - Push("pod-finish"), - }, - // ={custom} ... - { - `(?<=^ *)(? *)(?=\w[\w'-]*)(? *)(?#?)`, - ByGroups(Comment, Name, StringDoc, Keyword), - Push("pod-paragraph"), - }, - // = podconfig - { - `(?<=^ *)(? *=)(? *)(?(?::\w[\w'-]*(?:` + colonPairOpeningBrackets + `.+?` + - colonPairClosingBrackets + `) *)*\n)`, - ByGroups(Keyword, StringDoc, EmitterFunc(podConfig)), - nil, - }, - }, - "pod-begin": { - Include("pod-blocks"), - Include("pre-pod-formatter"), - {`.+?`, StringDoc, nil}, - }, - "pod-declaration": { - Include("pre-pod-formatter"), - {`.+?`, StringDoc, nil}, - }, - "pod-paragraph": { - {`\n *\n|\n(?=^ *=)`, StringDoc, Pop(1)}, - Include("pre-pod-formatter"), - {`.+?`, StringDoc, nil}, - }, - "pod-single": { - {`\n`, StringDoc, Pop(1)}, - Include("pre-pod-formatter"), - {`.+?`, StringDoc, nil}, - }, - "pod-heading": { - {`\n *\n|\n(?=^ *=)`, GenericHeading, Pop(1)}, - Include("pre-pod-formatter"), - {`.+?`, GenericHeading, nil}, - }, - "pod-finish": { - {`\z`, nil, Pop(1)}, - Include("pre-pod-formatter"), - {`.+?`, StringDoc, nil}, - }, - "pre-pod-formatter": { - // C, B, ... - { - `(?[CBIUDTKRPAELZVMSXN])(?<+|«)`, - ByGroups(Keyword, Punctuation), - findBrackets(rakuPodFormatter), - }, - }, - "pod-formatter": { - // Placeholder rule, will be replaced by mutators. DO NOT REMOVE! - {`>`, Punctuation, Pop(1)}, - Include("pre-pod-formatter"), - // Placeholder rule, will be replaced by mutators. DO NOT REMOVE! - {`.+?`, StringOther, nil}, - }, - "variable": { - {variablePattern, NameVariable, Push("name-adverb")}, - {globalVariablePattern, NameVariableGlobal, Push("name-adverb")}, - {`[$@]<[^>]+>`, NameVariable, nil}, - {`\$[/!¢]`, NameVariable, nil}, - {`[$@%]`, NameVariable, nil}, - }, - "single-quote": { - {`(?>(?!\s*(?:\d+|\.(?:Int|Numeric)|[$@%]\*?[\w':-]+|\s+\[))`, Punctuation, Pop(1)}, - Include("ww"), - }, - "«": { - {`»(?!\s*(?:\d+|\.(?:Int|Numeric)|[$@%]\*?[\w':-]+|\s+\[))`, Punctuation, Pop(1)}, - Include("ww"), - }, - "ww": { - Include("single-quote"), - Include("qq"), - }, - "qq": { - Include("qq-variable"), - Include("closure"), - Include(`escape-char`), - Include("escape-hexadecimal"), - Include("escape-c-name"), - Include("escape-qq"), - {`.+?`, StringDouble, nil}, - }, - "qq-variable": { - { - `(?\.)(?` + namePattern + `)` + colonPairLookahead + `\()`, - ByGroupNames(map[string]Emitter{ - `operator`: Operator, - `method_name`: NameFunction, - }), - Push(`name-adverb`), - }, - // Function/Signature - { - `\(`, Punctuation, replaceRule( - ruleReplacingConfig{ - delimiter: []rune(`)`), - tokenType: Punctuation, - stateName: `root`, - pushState: true, - }), - }, - Default(Pop(1)), - }, - "Q": { - Include("escape-qq"), - {`.+?`, String, nil}, - }, - "Q-closure": { - Include("escape-qq"), - Include("closure"), - {`.+?`, String, nil}, - }, - "Q-variable": { - Include("escape-qq"), - Include("qq-variable"), - {`.+?`, String, nil}, - }, - "closure": { - {`(? -1 { - idx = utf8.RuneCountInString(text[:idx]) - - // Search again if the substr is escaped with backslash - if (idx > 1 && strFromPos[idx-1] == '\\' && strFromPos[idx-2] != '\\') || - (idx == 1 && strFromPos[idx-1] == '\\') { - idx = indexAt(str[pos:], substr, idx+1) - - idx = utf8.RuneCountInString(text[:idx]) - - if idx < 0 { - return idx - } - } - idx += pos - } - - return idx -} - -// Tells if an array of string contains a string -func contains(s []string, e string) bool { - for _, value := range s { - if value == e { - return true - } - } - return false -} - -type rulePosition int - -const ( - topRule rulePosition = 0 - bottomRule = -1 -) - -type ruleMakingConfig struct { - delimiter []rune - pattern string - tokenType Emitter - mutator Mutator - numberOfDelimiterChars int -} - -type ruleReplacingConfig struct { - delimiter []rune - pattern string - tokenType Emitter - numberOfDelimiterChars int - mutator Mutator - appendMutator Mutator - rulePosition rulePosition - stateName string - pop bool - popState bool - pushState bool -} - -// Pops rule from state-stack and replaces the rule with the previous rule -func popRule(rule ruleReplacingConfig) MutatorFunc { - return func(state *LexerState) error { - stackName := genStackName(rule.stateName, rule.rulePosition) - - stack, ok := state.Get(stackName).([]ruleReplacingConfig) - - if ok && len(stack) > 0 { - // Pop from stack - stack = stack[:len(stack)-1] - lastRule := stack[len(stack)-1] - lastRule.pushState = false - lastRule.popState = false - lastRule.pop = true - state.Set(stackName, stack) - - // Call replaceRule to use the last rule - err := replaceRule(lastRule)(state) - if err != nil { - panic(err) - } - } - - return nil - } -} - -// Replaces a state's rule based on the rule config and position -func replaceRule(rule ruleReplacingConfig) MutatorFunc { - return func(state *LexerState) error { - stateName := rule.stateName - stackName := genStackName(rule.stateName, rule.rulePosition) - - stack, ok := state.Get(stackName).([]ruleReplacingConfig) - if !ok { - stack = []ruleReplacingConfig{} - } - - // If state-stack is empty fill it with the placeholder rule - if len(stack) == 0 { - stack = []ruleReplacingConfig{ - { - // Placeholder, will be overwritten by mutators, DO NOT REMOVE! - pattern: `\A\z`, - tokenType: nil, - mutator: nil, - stateName: stateName, - rulePosition: rule.rulePosition, - }, - } - state.Set(stackName, stack) - } - - var mutator Mutator - mutators := []Mutator{} - - switch { - case rule.rulePosition == topRule && rule.mutator == nil: - // Default mutator for top rule - mutators = []Mutator{Pop(1), popRule(rule)} - case rule.rulePosition == topRule && rule.mutator != nil: - // Default mutator for top rule, when rule.mutator is set - mutators = []Mutator{rule.mutator, popRule(rule)} - case rule.mutator != nil: - mutators = []Mutator{rule.mutator} - } - - if rule.appendMutator != nil { - mutators = append(mutators, rule.appendMutator) - } - - if len(mutators) > 0 { - mutator = Mutators(mutators...) - } else { - mutator = nil - } - - ruleConfig := ruleMakingConfig{ - pattern: rule.pattern, - delimiter: rule.delimiter, - numberOfDelimiterChars: rule.numberOfDelimiterChars, - tokenType: rule.tokenType, - mutator: mutator, - } - - cRule := makeRule(ruleConfig) - - switch rule.rulePosition { - case topRule: - state.Rules[stateName][0] = cRule - case bottomRule: - state.Rules[stateName][len(state.Rules[stateName])-1] = cRule - } - - // Pop state name from stack if asked. State should be popped first before Pushing - if rule.popState { - err := Pop(1).Mutate(state) - if err != nil { - panic(err) - } - } - - // Push state name to stack if asked - if rule.pushState { - err := Push(stateName).Mutate(state) - if err != nil { - panic(err) - } - } - - if !rule.pop { - state.Set(stackName, append(stack, rule)) - } - - return nil - } -} - -// Generates rule replacing stack using state name and rule position -func genStackName(stateName string, rulePosition rulePosition) (stackName string) { - switch rulePosition { - case topRule: - stackName = stateName + `-top-stack` - case bottomRule: - stackName = stateName + `-bottom-stack` - } - return -} - -// Makes a compiled rule and returns it -func makeRule(config ruleMakingConfig) *CompiledRule { - var rePattern string - - if len(config.delimiter) > 0 { - delimiter := string(config.delimiter) - - if config.numberOfDelimiterChars > 1 { - delimiter = strings.Repeat(delimiter, config.numberOfDelimiterChars) - } - - rePattern = `(? 1 { - lang = langMatch[1] - } - - // Tokenise code based on lang property - sublexer := Get(lang) - if sublexer != nil { - iterator, err := sublexer.Tokenise(nil, state.NamedGroups[`value`]) - - if err != nil { - panic(err) - } else { - iterators = append(iterators, iterator) - } - } else { - iterators = append(iterators, Literator(tokens[4])) - } - - // Append the rest of the tokens - iterators = append(iterators, Literator(tokens[5:]...)) - - return Concaterator(iterators...) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/rst.go b/vendor/github.com/alecthomas/chroma/v2/lexers/rst.go deleted file mode 100644 index 66ec03cd..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/rst.go +++ /dev/null @@ -1,89 +0,0 @@ -package lexers - -import ( - "strings" - - . "github.com/alecthomas/chroma/v2" // nolint -) - -// Restructuredtext lexer. -var Restructuredtext = Register(MustNewLexer( - &Config{ - Name: "reStructuredText", - Aliases: []string{"rst", "rest", "restructuredtext"}, - Filenames: []string{"*.rst", "*.rest"}, - MimeTypes: []string{"text/x-rst", "text/prs.fallenstein.rst"}, - }, - restructuredtextRules, -)) - -func restructuredtextRules() Rules { - return Rules{ - "root": { - {"^(=+|-+|`+|:+|\\.+|\\'+|\"+|~+|\\^+|_+|\\*+|\\++|#+)([ \\t]*\\n)(.+)(\\n)(\\1)(\\n)", ByGroups(GenericHeading, Text, GenericHeading, Text, GenericHeading, Text), nil}, - {"^(\\S.*)(\\n)(={3,}|-{3,}|`{3,}|:{3,}|\\.{3,}|\\'{3,}|\"{3,}|~{3,}|\\^{3,}|_{3,}|\\*{3,}|\\+{3,}|#{3,})(\\n)", ByGroups(GenericHeading, Text, GenericHeading, Text), nil}, - {`^(\s*)([-*+])( .+\n(?:\1 .+\n)*)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil}, - {`^(\s*)([0-9#ivxlcmIVXLCM]+\.)( .+\n(?:\1 .+\n)*)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil}, - {`^(\s*)(\(?[0-9#ivxlcmIVXLCM]+\))( .+\n(?:\1 .+\n)*)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil}, - {`^(\s*)([A-Z]+\.)( .+\n(?:\1 .+\n)+)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil}, - {`^(\s*)(\(?[A-Za-z]+\))( .+\n(?:\1 .+\n)+)`, ByGroups(Text, LiteralNumber, UsingSelf("inline")), nil}, - {`^(\s*)(\|)( .+\n(?:\| .+\n)*)`, ByGroups(Text, Operator, UsingSelf("inline")), nil}, - {`^( *\.\.)(\s*)((?:source)?code(?:-block)?)(::)([ \t]*)([^\n]+)(\n[ \t]*\n)([ \t]+)(.*)(\n)((?:(?:\8.*|)\n)+)`, EmitterFunc(rstCodeBlock), nil}, - {`^( *\.\.)(\s*)([\w:-]+?)(::)(?:([ \t]*)(.*))`, ByGroups(Punctuation, Text, OperatorWord, Punctuation, Text, UsingSelf("inline")), nil}, - {`^( *\.\.)(\s*)(_(?:[^:\\]|\\.)+:)(.*?)$`, ByGroups(Punctuation, Text, NameTag, UsingSelf("inline")), nil}, - {`^( *\.\.)(\s*)(\[.+\])(.*?)$`, ByGroups(Punctuation, Text, NameTag, UsingSelf("inline")), nil}, - {`^( *\.\.)(\s*)(\|.+\|)(\s*)([\w:-]+?)(::)(?:([ \t]*)(.*))`, ByGroups(Punctuation, Text, NameTag, Text, OperatorWord, Punctuation, Text, UsingSelf("inline")), nil}, - {`^ *\.\..*(\n( +.*\n|\n)+)?`, CommentPreproc, nil}, - {`^( *)(:[a-zA-Z-]+:)(\s*)$`, ByGroups(Text, NameClass, Text), nil}, - {`^( *)(:.*?:)([ \t]+)(.*?)$`, ByGroups(Text, NameClass, Text, NameFunction), nil}, - {`^(\S.*(?)(`__?)", ByGroups(LiteralString, LiteralStringInterpol, LiteralString), nil}, - {"`.+?`__?", LiteralString, nil}, - {"(`.+?`)(:[a-zA-Z0-9:-]+?:)?", ByGroups(NameVariable, NameAttribute), nil}, - {"(:[a-zA-Z0-9:-]+?:)(`.+?`)", ByGroups(NameAttribute, NameVariable), nil}, - {`\*\*.+?\*\*`, GenericStrong, nil}, - {`\*.+?\*`, GenericEmph, nil}, - {`\[.*?\]_`, LiteralString, nil}, - {`<.+?>`, NameTag, nil}, - {"[^\\\\\\n\\[*`:]+", Text, nil}, - {`.`, Text, nil}, - }, - "literal": { - {"[^`]+", LiteralString, nil}, - {"``((?=$)|(?=[-/:.,; \\n\\x00\\\u2010\\\u2011\\\u2012\\\u2013\\\u2014\\\u00a0\\'\\\"\\)\\]\\}\\>\\\u2019\\\u201d\\\u00bb\\!\\?]))", LiteralString, Pop(1)}, - {"`", LiteralString, nil}, - }, - } -} - -func rstCodeBlock(groups []string, state *LexerState) Iterator { - iterators := []Iterator{} - tokens := []Token{ - {Punctuation, groups[1]}, - {Text, groups[2]}, - {OperatorWord, groups[3]}, - {Punctuation, groups[4]}, - {Text, groups[5]}, - {Keyword, groups[6]}, - {Text, groups[7]}, - } - code := strings.Join(groups[8:], "") - lexer := Get(groups[6]) - if lexer == nil { - tokens = append(tokens, Token{String, code}) - iterators = append(iterators, Literator(tokens...)) - } else { - sub, err := lexer.Tokenise(nil, code) - if err != nil { - panic(err) - } - iterators = append(iterators, Literator(tokens...), sub) - } - return Concaterator(iterators...) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/lexers/svelte.go b/vendor/github.com/alecthomas/chroma/v2/lexers/svelte.go deleted file mode 100644 index 39211c4f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/lexers/svelte.go +++ /dev/null @@ -1,70 +0,0 @@ -package lexers - -import ( - . "github.com/alecthomas/chroma/v2" // nolint -) - -// Svelte lexer. -var Svelte = Register(DelegatingLexer(HTML, MustNewLexer( - &Config{ - Name: "Svelte", - Aliases: []string{"svelte"}, - Filenames: []string{"*.svelte"}, - MimeTypes: []string{"application/x-svelte"}, - DotAll: true, - }, - svelteRules, -))) - -func svelteRules() Rules { - return Rules{ - "root": { - // Let HTML handle the comments, including comments containing script and style tags - {``, Other, Pop(1)}, - {`.+?`, Other, nil}, - }, - "templates": { - {`}`, Punctuation, Pop(1)}, - // Let TypeScript handle strings and the curly braces inside them - {`(?]*>`, Using("TypoScriptHTMLData"), nil}, - {`&[^;\n]*;`, LiteralString, nil}, - {`(_CSS_DEFAULT_STYLE)(\s*)(\()(?s)(.*(?=\n\)))`, ByGroups(NameClass, Text, LiteralStringSymbol, Using("TypoScriptCSSData")), nil}, - }, - "literal": { - {`0x[0-9A-Fa-f]+t?`, LiteralNumberHex, nil}, - {`[0-9]+`, LiteralNumberInteger, nil}, - {`(###\w+###)`, NameConstant, nil}, - }, - "label": { - {`(EXT|FILE|LLL):[^}\n"]*`, LiteralString, nil}, - {`(?![^\w\-])([\w\-]+(?:/[\w\-]+)+/?)(\S*\n)`, ByGroups(LiteralString, LiteralString), nil}, - }, - "punctuation": { - {`[,.]`, Punctuation, nil}, - }, - "operator": { - {`[<>,:=.*%+|]`, Operator, nil}, - }, - "structure": { - {`[{}()\[\]\\]`, LiteralStringSymbol, nil}, - }, - "constant": { - {`(\{)(\$)((?:[\w\-]+\.)*)([\w\-]+)(\})`, ByGroups(LiteralStringSymbol, Operator, NameConstant, NameConstant, LiteralStringSymbol), nil}, - {`(\{)([\w\-]+)(\s*:\s*)([\w\-]+)(\})`, ByGroups(LiteralStringSymbol, NameConstant, Operator, NameConstant, LiteralStringSymbol), nil}, - {`(#[a-fA-F0-9]{6}\b|#[a-fA-F0-9]{3}\b)`, LiteralStringChar, nil}, - }, - "comment": { - {`(? lexers.txt - -kotlin: - invalid unicode escape sequences - FIXED: Have to disable wide Unicode characters in unistring.py - -pygments.lexers.ambient.AmbientTalkLexer -pygments.lexers.ampl.AmplLexer -pygments.lexers.actionscript.ActionScriptLexer -pygments.lexers.actionscript.ActionScript3Lexer -pygments.lexers.actionscript.MxmlLexer -pygments.lexers.algebra.GAPLexer -pygments.lexers.algebra.MathematicaLexer -pygments.lexers.algebra.MuPADLexer -pygments.lexers.algebra.BCLexer -pygments.lexers.apl.APLLexer -pygments.lexers.bibtex.BibTeXLexer -pygments.lexers.bibtex.BSTLexer -pygments.lexers.basic.BlitzMaxLexer -pygments.lexers.basic.BlitzBasicLexer -pygments.lexers.basic.MonkeyLexer -pygments.lexers.basic.CbmBasicV2Lexer -pygments.lexers.basic.QBasicLexer -pygments.lexers.automation.AutohotkeyLexer -pygments.lexers.automation.AutoItLexer -pygments.lexers.archetype.AtomsLexer -pygments.lexers.c_like.ClayLexer -pygments.lexers.c_like.ValaLexer -pygments.lexers.asm.GasLexer -pygments.lexers.asm.ObjdumpLexer -pygments.lexers.asm.HsailLexer -pygments.lexers.asm.LlvmLexer -pygments.lexers.asm.NasmLexer -pygments.lexers.asm.TasmLexer -pygments.lexers.asm.Ca65Lexer -pygments.lexers.business.CobolLexer -pygments.lexers.business.ABAPLexer -pygments.lexers.business.OpenEdgeLexer -pygments.lexers.business.GoodDataCLLexer -pygments.lexers.business.MaqlLexer -pygments.lexers.capnproto.CapnProtoLexer -pygments.lexers.chapel.ChapelLexer -pygments.lexers.clean.CleanLexer -pygments.lexers.c_cpp.CFamilyLexer -pygments.lexers.console.VCTreeStatusLexer -pygments.lexers.console.PyPyLogLexer -pygments.lexers.csound.CsoundLexer -pygments.lexers.csound.CsoundDocumentLexer -pygments.lexers.csound.CsoundDocumentLexer -pygments.lexers.crystal.CrystalLexer -pygments.lexers.dalvik.SmaliLexer -pygments.lexers.css.CssLexer -pygments.lexers.css.SassLexer -pygments.lexers.css.ScssLexer -pygments.lexers.configs.IniLexer -pygments.lexers.configs.RegeditLexer -pygments.lexers.configs.PropertiesLexer -pygments.lexers.configs.KconfigLexer -pygments.lexers.configs.Cfengine3Lexer -pygments.lexers.configs.ApacheConfLexer -pygments.lexers.configs.SquidConfLexer -pygments.lexers.configs.NginxConfLexer -pygments.lexers.configs.LighttpdConfLexer -pygments.lexers.configs.DockerLexer -pygments.lexers.configs.TerraformLexer -pygments.lexers.configs.TermcapLexer -pygments.lexers.configs.TerminfoLexer -pygments.lexers.configs.PkgConfigLexer -pygments.lexers.configs.PacmanConfLexer -pygments.lexers.data.YamlLexer -pygments.lexers.data.JsonLexer -pygments.lexers.diff.DiffLexer -pygments.lexers.diff.DarcsPatchLexer -pygments.lexers.diff.WDiffLexer -pygments.lexers.dotnet.CSharpLexer -pygments.lexers.dotnet.NemerleLexer -pygments.lexers.dotnet.BooLexer -pygments.lexers.dotnet.VbNetLexer -pygments.lexers.dotnet.GenericAspxLexer -pygments.lexers.dotnet.FSharpLexer -pygments.lexers.dylan.DylanLexer -pygments.lexers.dylan.DylanLidLexer -pygments.lexers.ecl.ECLLexer -pygments.lexers.eiffel.EiffelLexer -pygments.lexers.dsls.ProtoBufLexer -pygments.lexers.dsls.ThriftLexer -pygments.lexers.dsls.BroLexer -pygments.lexers.dsls.PuppetLexer -pygments.lexers.dsls.RslLexer -pygments.lexers.dsls.MscgenLexer -pygments.lexers.dsls.VGLLexer -pygments.lexers.dsls.AlloyLexer -pygments.lexers.dsls.PanLexer -pygments.lexers.dsls.CrmshLexer -pygments.lexers.dsls.FlatlineLexer -pygments.lexers.dsls.SnowballLexer -pygments.lexers.elm.ElmLexer -pygments.lexers.erlang.ErlangLexer -pygments.lexers.erlang.ElixirLexer -pygments.lexers.ezhil.EzhilLexer -pygments.lexers.esoteric.BrainfuckLexer -pygments.lexers.esoteric.BefungeLexer -pygments.lexers.esoteric.CAmkESLexer -pygments.lexers.esoteric.CapDLLexer -pygments.lexers.esoteric.RedcodeLexer -pygments.lexers.esoteric.AheuiLexer -pygments.lexers.factor.FactorLexer -pygments.lexers.fantom.FantomLexer -pygments.lexers.felix.FelixLexer -pygments.lexers.forth.ForthLexer -pygments.lexers.fortran.FortranLexer -pygments.lexers.fortran.FortranFixedLexer -pygments.lexers.go.GoLexer -pygments.lexers.foxpro.FoxProLexer -pygments.lexers.graph.CypherLexer -pygments.lexers.grammar_notation.BnfLexer -pygments.lexers.grammar_notation.AbnfLexer -pygments.lexers.grammar_notation.JsgfLexer -pygments.lexers.graphics.GLShaderLexer -pygments.lexers.graphics.PostScriptLexer -pygments.lexers.graphics.AsymptoteLexer -pygments.lexers.graphics.GnuplotLexer -pygments.lexers.graphics.PovrayLexer -pygments.lexers.hexdump.HexdumpLexer -pygments.lexers.haskell.HaskellLexer -pygments.lexers.haskell.IdrisLexer -pygments.lexers.haskell.AgdaLexer -pygments.lexers.haskell.CryptolLexer -pygments.lexers.haskell.KokaLexer -pygments.lexers.haxe.HaxeLexer -pygments.lexers.haxe.HxmlLexer -pygments.lexers.hdl.VerilogLexer -pygments.lexers.hdl.SystemVerilogLexer -pygments.lexers.hdl.VhdlLexer -pygments.lexers.idl.IDLLexer -pygments.lexers.inferno.LimboLexer -pygments.lexers.igor.IgorLexer -pygments.lexers.html.HtmlLexer -pygments.lexers.html.DtdLexer -pygments.lexers.html.XmlLexer -pygments.lexers.html.HamlLexer -pygments.lexers.html.ScamlLexer -pygments.lexers.html.PugLexer -pygments.lexers.installers.NSISLexer -pygments.lexers.installers.RPMSpecLexer -pygments.lexers.installers.SourcesListLexer -pygments.lexers.installers.DebianControlLexer -pygments.lexers.iolang.IoLexer -pygments.lexers.julia.JuliaLexer -pygments.lexers.int_fiction.Inform6Lexer -pygments.lexers.int_fiction.Inform7Lexer -pygments.lexers.int_fiction.Tads3Lexer -pygments.lexers.make.BaseMakefileLexer -pygments.lexers.make.CMakeLexer -pygments.lexers.javascript.JavascriptLexer -pygments.lexers.javascript.KalLexer -pygments.lexers.javascript.LiveScriptLexer -pygments.lexers.javascript.DartLexer -pygments.lexers.javascript.TypeScriptLexer -pygments.lexers.javascript.LassoLexer -pygments.lexers.javascript.ObjectiveJLexer -pygments.lexers.javascript.CoffeeScriptLexer -pygments.lexers.javascript.MaskLexer -pygments.lexers.javascript.EarlGreyLexer -pygments.lexers.javascript.JuttleLexer -pygments.lexers.jvm.JavaLexer -pygments.lexers.jvm.ScalaLexer -pygments.lexers.jvm.GosuLexer -pygments.lexers.jvm.GroovyLexer -pygments.lexers.jvm.IokeLexer -pygments.lexers.jvm.ClojureLexer -pygments.lexers.jvm.TeaLangLexer -pygments.lexers.jvm.CeylonLexer -pygments.lexers.jvm.KotlinLexer -pygments.lexers.jvm.XtendLexer -pygments.lexers.jvm.PigLexer -pygments.lexers.jvm.GoloLexer -pygments.lexers.jvm.JasminLexer -pygments.lexers.markup.BBCodeLexer -pygments.lexers.markup.MoinWikiLexer -pygments.lexers.markup.RstLexer -pygments.lexers.markup.TexLexer -pygments.lexers.markup.GroffLexer -pygments.lexers.markup.MozPreprocHashLexer -pygments.lexers.markup.MarkdownLexer -pygments.lexers.ml.SMLLexer -pygments.lexers.ml.OcamlLexer -pygments.lexers.ml.OpaLexer -pygments.lexers.modeling.ModelicaLexer -pygments.lexers.modeling.BugsLexer -pygments.lexers.modeling.JagsLexer -pygments.lexers.modeling.StanLexer -pygments.lexers.matlab.MatlabLexer -pygments.lexers.matlab.OctaveLexer -pygments.lexers.matlab.ScilabLexer -pygments.lexers.monte.MonteLexer -pygments.lexers.lisp.SchemeLexer -pygments.lexers.lisp.CommonLispLexer -pygments.lexers.lisp.HyLexer -pygments.lexers.lisp.RacketLexer -pygments.lexers.lisp.NewLispLexer -pygments.lexers.lisp.EmacsLispLexer -pygments.lexers.lisp.ShenLexer -pygments.lexers.lisp.XtlangLexer -pygments.lexers.modula2.Modula2Lexer -pygments.lexers.ncl.NCLLexer -pygments.lexers.nim.NimLexer -pygments.lexers.nit.NitLexer -pygments.lexers.nix.NixLexer -pygments.lexers.oberon.ComponentPascalLexer -pygments.lexers.ooc.OocLexer -pygments.lexers.objective.SwiftLexer -pygments.lexers.parasail.ParaSailLexer -pygments.lexers.pawn.SourcePawnLexer -pygments.lexers.pawn.PawnLexer -pygments.lexers.pascal.AdaLexer -pygments.lexers.parsers.RagelLexer -pygments.lexers.parsers.RagelEmbeddedLexer -pygments.lexers.parsers.AntlrLexer -pygments.lexers.parsers.TreetopBaseLexer -pygments.lexers.parsers.EbnfLexer -pygments.lexers.php.ZephirLexer -pygments.lexers.php.PhpLexer -pygments.lexers.perl.PerlLexer -pygments.lexers.perl.Perl6Lexer -pygments.lexers.praat.PraatLexer -pygments.lexers.prolog.PrologLexer -pygments.lexers.prolog.LogtalkLexer -pygments.lexers.qvt.QVToLexer -pygments.lexers.rdf.SparqlLexer -pygments.lexers.rdf.TurtleLexer -pygments.lexers.python.PythonLexer -pygments.lexers.python.Python3Lexer -pygments.lexers.python.PythonTracebackLexer -pygments.lexers.python.Python3TracebackLexer -pygments.lexers.python.CythonLexer -pygments.lexers.python.DgLexer -pygments.lexers.rebol.RebolLexer -pygments.lexers.rebol.RedLexer -pygments.lexers.resource.ResourceLexer -pygments.lexers.rnc.RNCCompactLexer -pygments.lexers.roboconf.RoboconfGraphLexer -pygments.lexers.roboconf.RoboconfInstancesLexer -pygments.lexers.rust.RustLexer -pygments.lexers.ruby.RubyLexer -pygments.lexers.ruby.FancyLexer -pygments.lexers.sas.SASLexer -pygments.lexers.smalltalk.SmalltalkLexer -pygments.lexers.smalltalk.NewspeakLexer -pygments.lexers.smv.NuSMVLexer -pygments.lexers.shell.BashLexer -pygments.lexers.shell.BatchLexer -pygments.lexers.shell.TcshLexer -pygments.lexers.shell.PowerShellLexer -pygments.lexers.shell.FishShellLexer -pygments.lexers.snobol.SnobolLexer -pygments.lexers.scripting.LuaLexer -pygments.lexers.scripting.ChaiscriptLexer -pygments.lexers.scripting.LSLLexer -pygments.lexers.scripting.AppleScriptLexer -pygments.lexers.scripting.RexxLexer -pygments.lexers.scripting.MOOCodeLexer -pygments.lexers.scripting.HybrisLexer -pygments.lexers.scripting.EasytrieveLexer -pygments.lexers.scripting.JclLexer -pygments.lexers.supercollider.SuperColliderLexer -pygments.lexers.stata.StataLexer -pygments.lexers.tcl.TclLexer -pygments.lexers.sql.PostgresLexer -pygments.lexers.sql.PlPgsqlLexer -pygments.lexers.sql.PsqlRegexLexer -pygments.lexers.sql.SqlLexer -pygments.lexers.sql.TransactSqlLexer -pygments.lexers.sql.MySqlLexer -pygments.lexers.sql.RqlLexer -pygments.lexers.testing.GherkinLexer -pygments.lexers.testing.TAPLexer -pygments.lexers.textedit.AwkLexer -pygments.lexers.textedit.VimLexer -pygments.lexers.textfmts.IrcLogsLexer -pygments.lexers.textfmts.GettextLexer -pygments.lexers.textfmts.HttpLexer -pygments.lexers.textfmts.TodotxtLexer -pygments.lexers.trafficscript.RtsLexer -pygments.lexers.theorem.CoqLexer -pygments.lexers.theorem.IsabelleLexer -pygments.lexers.theorem.LeanLexer -pygments.lexers.templates.SmartyLexer -pygments.lexers.templates.VelocityLexer -pygments.lexers.templates.DjangoLexer -pygments.lexers.templates.MyghtyLexer -pygments.lexers.templates.MasonLexer -pygments.lexers.templates.MakoLexer -pygments.lexers.templates.CheetahLexer -pygments.lexers.templates.GenshiTextLexer -pygments.lexers.templates.GenshiMarkupLexer -pygments.lexers.templates.JspRootLexer -pygments.lexers.templates.EvoqueLexer -pygments.lexers.templates.ColdfusionLexer -pygments.lexers.templates.ColdfusionMarkupLexer -pygments.lexers.templates.TeaTemplateRootLexer -pygments.lexers.templates.HandlebarsLexer -pygments.lexers.templates.LiquidLexer -pygments.lexers.templates.TwigLexer -pygments.lexers.templates.Angular2Lexer -pygments.lexers.urbi.UrbiscriptLexer -pygments.lexers.typoscript.TypoScriptCssDataLexer -pygments.lexers.typoscript.TypoScriptHtmlDataLexer -pygments.lexers.typoscript.TypoScriptLexer -pygments.lexers.varnish.VCLLexer -pygments.lexers.verification.BoogieLexer -pygments.lexers.verification.SilverLexer -pygments.lexers.x10.X10Lexer -pygments.lexers.whiley.WhileyLexer -pygments.lexers.xorg.XorgLexer -pygments.lexers.webmisc.DuelLexer -pygments.lexers.webmisc.XQueryLexer -pygments.lexers.webmisc.QmlLexer -pygments.lexers.webmisc.CirruLexer -pygments.lexers.webmisc.SlimLexer diff --git a/vendor/github.com/alecthomas/chroma/v2/quick/quick.go b/vendor/github.com/alecthomas/chroma/v2/quick/quick.go deleted file mode 100644 index af701d9c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/quick/quick.go +++ /dev/null @@ -1,44 +0,0 @@ -// Package quick provides simple, no-configuration source code highlighting. -package quick - -import ( - "io" - - "github.com/alecthomas/chroma/v2" - "github.com/alecthomas/chroma/v2/formatters" - "github.com/alecthomas/chroma/v2/lexers" - "github.com/alecthomas/chroma/v2/styles" -) - -// Highlight some text. -// -// Lexer, formatter and style may be empty, in which case a best-effort is made. -func Highlight(w io.Writer, source, lexer, formatter, style string) error { - // Determine lexer. - l := lexers.Get(lexer) - if l == nil { - l = lexers.Analyse(source) - } - if l == nil { - l = lexers.Fallback - } - l = chroma.Coalesce(l) - - // Determine formatter. - f := formatters.Get(formatter) - if f == nil { - f = formatters.Fallback - } - - // Determine style. - s := styles.Get(style) - if s == nil { - s = styles.Fallback - } - - it, err := l.Tokenise(nil, source) - if err != nil { - return err - } - return f.Format(w, s, it) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/regexp.go b/vendor/github.com/alecthomas/chroma/v2/regexp.go deleted file mode 100644 index 0dcb077f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/regexp.go +++ /dev/null @@ -1,483 +0,0 @@ -package chroma - -import ( - "fmt" - "os" - "path/filepath" - "regexp" - "sort" - "strings" - "sync" - "time" - "unicode/utf8" - - "github.com/dlclark/regexp2" -) - -// A Rule is the fundamental matching unit of the Regex lexer state machine. -type Rule struct { - Pattern string - Type Emitter - Mutator Mutator -} - -// Words creates a regex that matches any of the given literal words. -func Words(prefix, suffix string, words ...string) string { - sort.Slice(words, func(i, j int) bool { - return len(words[j]) < len(words[i]) - }) - for i, word := range words { - words[i] = regexp.QuoteMeta(word) - } - return prefix + `(` + strings.Join(words, `|`) + `)` + suffix -} - -// Tokenise text using lexer, returning tokens as a slice. -func Tokenise(lexer Lexer, options *TokeniseOptions, text string) ([]Token, error) { - var out []Token - it, err := lexer.Tokenise(options, text) - if err != nil { - return nil, err - } - for t := it(); t != EOF; t = it() { - out = append(out, t) - } - return out, nil -} - -// Rules maps from state to a sequence of Rules. -type Rules map[string][]Rule - -// Rename clones rules then a rule. -func (r Rules) Rename(oldRule, newRule string) Rules { - r = r.Clone() - r[newRule] = r[oldRule] - delete(r, oldRule) - return r -} - -// Clone returns a clone of the Rules. -func (r Rules) Clone() Rules { - out := map[string][]Rule{} - for key, rules := range r { - out[key] = make([]Rule, len(rules)) - copy(out[key], rules) - } - return out -} - -// Merge creates a clone of "r" then merges "rules" into the clone. -func (r Rules) Merge(rules Rules) Rules { - out := r.Clone() - for k, v := range rules.Clone() { - out[k] = v - } - return out -} - -// MustNewLexer creates a new Lexer with deferred rules generation or panics. -func MustNewLexer(config *Config, rules func() Rules) *RegexLexer { - lexer, err := NewLexer(config, rules) - if err != nil { - panic(err) - } - return lexer -} - -// NewLexer creates a new regex-based Lexer. -// -// "rules" is a state machine transition map. Each key is a state. Values are sets of rules -// that match input, optionally modify lexer state, and output tokens. -func NewLexer(config *Config, rulesFunc func() Rules) (*RegexLexer, error) { - if config == nil { - config = &Config{} - } - for _, glob := range append(config.Filenames, config.AliasFilenames...) { - _, err := filepath.Match(glob, "") - if err != nil { - return nil, fmt.Errorf("%s: %q is not a valid glob: %w", config.Name, glob, err) - } - } - r := &RegexLexer{ - config: config, - fetchRulesFunc: func() (Rules, error) { return rulesFunc(), nil }, - } - // One-off code to generate XML lexers in the Chroma source tree. - // var nameCleanRe = regexp.MustCompile(`[^-+A-Za-z0-9_]`) - // name := strings.ToLower(nameCleanRe.ReplaceAllString(config.Name, "_")) - // data, err := Marshal(r) - // if err != nil { - // if errors.Is(err, ErrNotSerialisable) { - // fmt.Fprintf(os.Stderr, "warning: %q: %s\n", name, err) - // return r, nil - // } - // return nil, err - // } - // _, file, _, ok := runtime.Caller(2) - // if !ok { - // panic("??") - // } - // fmt.Println(file) - // if strings.Contains(file, "/lexers/") { - // dir := filepath.Join(filepath.Dir(file), "embedded") - // err = os.MkdirAll(dir, 0700) - // if err != nil { - // return nil, err - // } - // filename := filepath.Join(dir, name) + ".xml" - // fmt.Println(filename) - // err = ioutil.WriteFile(filename, data, 0600) - // if err != nil { - // return nil, err - // } - // } - return r, nil -} - -// Trace enables debug tracing. -func (r *RegexLexer) Trace(trace bool) *RegexLexer { - r.trace = trace - return r -} - -// A CompiledRule is a Rule with a pre-compiled regex. -// -// Note that regular expressions are lazily compiled on first use of the lexer. -type CompiledRule struct { - Rule - Regexp *regexp2.Regexp - flags string -} - -// CompiledRules is a map of rule name to sequence of compiled rules in that rule. -type CompiledRules map[string][]*CompiledRule - -// LexerState contains the state for a single lex. -type LexerState struct { - Lexer *RegexLexer - Registry *LexerRegistry - Text []rune - Pos int - Rules CompiledRules - Stack []string - State string - Rule int - // Group matches. - Groups []string - // Named Group matches. - NamedGroups map[string]string - // Custum context for mutators. - MutatorContext map[interface{}]interface{} - iteratorStack []Iterator - options *TokeniseOptions - newlineAdded bool -} - -// Set mutator context. -func (l *LexerState) Set(key interface{}, value interface{}) { - l.MutatorContext[key] = value -} - -// Get mutator context. -func (l *LexerState) Get(key interface{}) interface{} { - return l.MutatorContext[key] -} - -// Iterator returns the next Token from the lexer. -func (l *LexerState) Iterator() Token { // nolint: gocognit - end := len(l.Text) - if l.newlineAdded { - end-- - } - for l.Pos < end && len(l.Stack) > 0 { - // Exhaust the iterator stack, if any. - for len(l.iteratorStack) > 0 { - n := len(l.iteratorStack) - 1 - t := l.iteratorStack[n]() - if t == EOF { - l.iteratorStack = l.iteratorStack[:n] - continue - } - return t - } - - l.State = l.Stack[len(l.Stack)-1] - if l.Lexer.trace { - fmt.Fprintf(os.Stderr, "%s: pos=%d, text=%q\n", l.State, l.Pos, string(l.Text[l.Pos:])) - } - selectedRule, ok := l.Rules[l.State] - if !ok { - panic("unknown state " + l.State) - } - ruleIndex, rule, groups, namedGroups := matchRules(l.Text, l.Pos, selectedRule) - // No match. - if groups == nil { - // From Pygments :\ - // - // If the RegexLexer encounters a newline that is flagged as an error token, the stack is - // emptied and the lexer continues scanning in the 'root' state. This can help producing - // error-tolerant highlighting for erroneous input, e.g. when a single-line string is not - // closed. - if l.Text[l.Pos] == '\n' && l.State != l.options.State { - l.Stack = []string{l.options.State} - continue - } - l.Pos++ - return Token{Error, string(l.Text[l.Pos-1 : l.Pos])} - } - l.Rule = ruleIndex - l.Groups = groups - l.NamedGroups = namedGroups - l.Pos += utf8.RuneCountInString(groups[0]) - if rule.Mutator != nil { - if err := rule.Mutator.Mutate(l); err != nil { - panic(err) - } - } - if rule.Type != nil { - l.iteratorStack = append(l.iteratorStack, rule.Type.Emit(l.Groups, l)) - } - } - // Exhaust the IteratorStack, if any. - // Duplicate code, but eh. - for len(l.iteratorStack) > 0 { - n := len(l.iteratorStack) - 1 - t := l.iteratorStack[n]() - if t == EOF { - l.iteratorStack = l.iteratorStack[:n] - continue - } - return t - } - - // If we get to here and we still have text, return it as an error. - if l.Pos != len(l.Text) && len(l.Stack) == 0 { - value := string(l.Text[l.Pos:]) - l.Pos = len(l.Text) - return Token{Type: Error, Value: value} - } - return EOF -} - -// RegexLexer is the default lexer implementation used in Chroma. -type RegexLexer struct { - registry *LexerRegistry // The LexerRegistry this Lexer is associated with, if any. - config *Config - analyser func(text string) float32 - trace bool - - mu sync.Mutex - compiled bool - rawRules Rules - rules map[string][]*CompiledRule - fetchRulesFunc func() (Rules, error) - compileOnce sync.Once -} - -func (r *RegexLexer) String() string { - return r.config.Name -} - -// Rules in the Lexer. -func (r *RegexLexer) Rules() (Rules, error) { - if err := r.needRules(); err != nil { - return nil, err - } - return r.rawRules, nil -} - -// SetRegistry the lexer will use to lookup other lexers if necessary. -func (r *RegexLexer) SetRegistry(registry *LexerRegistry) Lexer { - r.registry = registry - return r -} - -// SetAnalyser sets the analyser function used to perform content inspection. -func (r *RegexLexer) SetAnalyser(analyser func(text string) float32) Lexer { - r.analyser = analyser - return r -} - -// AnalyseText scores how likely a fragment of text is to match this lexer, between 0.0 and 1.0. -func (r *RegexLexer) AnalyseText(text string) float32 { - if r.analyser != nil { - return r.analyser(text) - } - return 0 -} - -// SetConfig replaces the Config for this Lexer. -func (r *RegexLexer) SetConfig(config *Config) *RegexLexer { - r.config = config - return r -} - -// Config returns the Config for this Lexer. -func (r *RegexLexer) Config() *Config { - return r.config -} - -// Regex compilation is deferred until the lexer is used. This is to avoid significant init() time costs. -func (r *RegexLexer) maybeCompile() (err error) { - r.mu.Lock() - defer r.mu.Unlock() - if r.compiled { - return nil - } - for state, rules := range r.rules { - for i, rule := range rules { - if rule.Regexp == nil { - pattern := "(?:" + rule.Pattern + ")" - if rule.flags != "" { - pattern = "(?" + rule.flags + ")" + pattern - } - pattern = `\G` + pattern - rule.Regexp, err = regexp2.Compile(pattern, 0) - if err != nil { - return fmt.Errorf("failed to compile rule %s.%d: %s", state, i, err) - } - rule.Regexp.MatchTimeout = time.Millisecond * 250 - } - } - } -restart: - seen := map[LexerMutator]bool{} - for state := range r.rules { - for i := 0; i < len(r.rules[state]); i++ { - rule := r.rules[state][i] - if compile, ok := rule.Mutator.(LexerMutator); ok { - if seen[compile] { - return fmt.Errorf("saw mutator %T twice; this should not happen", compile) - } - seen[compile] = true - if err := compile.MutateLexer(r.rules, state, i); err != nil { - return err - } - // Process the rules again in case the mutator added/removed rules. - // - // This sounds bad, but shouldn't be significant in practice. - goto restart - } - } - } - r.compiled = true - return nil -} - -func (r *RegexLexer) fetchRules() error { - rules, err := r.fetchRulesFunc() - if err != nil { - return fmt.Errorf("%s: failed to compile rules: %w", r.config.Name, err) - } - if _, ok := rules["root"]; !ok { - return fmt.Errorf("no \"root\" state") - } - compiledRules := map[string][]*CompiledRule{} - for state, rules := range rules { - compiledRules[state] = nil - for _, rule := range rules { - flags := "" - if !r.config.NotMultiline { - flags += "m" - } - if r.config.CaseInsensitive { - flags += "i" - } - if r.config.DotAll { - flags += "s" - } - compiledRules[state] = append(compiledRules[state], &CompiledRule{Rule: rule, flags: flags}) - } - } - - r.rawRules = rules - r.rules = compiledRules - return nil -} - -func (r *RegexLexer) needRules() error { - var err error - if r.fetchRulesFunc != nil { - r.compileOnce.Do(func() { - err = r.fetchRules() - }) - } - if err := r.maybeCompile(); err != nil { - return err - } - return err -} - -// Tokenise text using lexer, returning an iterator. -func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { - err := r.needRules() - if err != nil { - return nil, err - } - if options == nil { - options = defaultOptions - } - if options.EnsureLF { - text = ensureLF(text) - } - newlineAdded := false - if !options.Nested && r.config.EnsureNL && !strings.HasSuffix(text, "\n") { - text += "\n" - newlineAdded = true - } - state := &LexerState{ - Registry: r.registry, - newlineAdded: newlineAdded, - options: options, - Lexer: r, - Text: []rune(text), - Stack: []string{options.State}, - Rules: r.rules, - MutatorContext: map[interface{}]interface{}{}, - } - return state.Iterator, nil -} - -// MustRules is like Rules() but will panic on error. -func (r *RegexLexer) MustRules() Rules { - rules, err := r.Rules() - if err != nil { - panic(err) - } - return rules -} - -func matchRules(text []rune, pos int, rules []*CompiledRule) (int, *CompiledRule, []string, map[string]string) { - for i, rule := range rules { - match, err := rule.Regexp.FindRunesMatchStartingAt(text, pos) - if match != nil && err == nil && match.Index == pos { - groups := []string{} - namedGroups := make(map[string]string) - for _, g := range match.Groups() { - namedGroups[g.Name] = g.String() - groups = append(groups, g.String()) - } - return i, rule, groups, namedGroups - } - } - return 0, &CompiledRule{}, nil, nil -} - -// replace \r and \r\n with \n -// same as strings.ReplaceAll but more efficient -func ensureLF(text string) string { - buf := make([]byte, len(text)) - var j int - for i := 0; i < len(text); i++ { - c := text[i] - if c == '\r' { - if i < len(text)-1 && text[i+1] == '\n' { - continue - } - c = '\n' - } - buf[j] = c - j++ - } - return string(buf[:j]) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/registry.go b/vendor/github.com/alecthomas/chroma/v2/registry.go deleted file mode 100644 index 4742e8c5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/registry.go +++ /dev/null @@ -1,210 +0,0 @@ -package chroma - -import ( - "path/filepath" - "sort" - "strings" -) - -var ( - ignoredSuffixes = [...]string{ - // Editor backups - "~", ".bak", ".old", ".orig", - // Debian and derivatives apt/dpkg/ucf backups - ".dpkg-dist", ".dpkg-old", ".ucf-dist", ".ucf-new", ".ucf-old", - // Red Hat and derivatives rpm backups - ".rpmnew", ".rpmorig", ".rpmsave", - // Build system input/template files - ".in", - } -) - -// LexerRegistry is a registry of Lexers. -type LexerRegistry struct { - Lexers Lexers - byName map[string]Lexer - byAlias map[string]Lexer -} - -// NewLexerRegistry creates a new LexerRegistry of Lexers. -func NewLexerRegistry() *LexerRegistry { - return &LexerRegistry{ - byName: map[string]Lexer{}, - byAlias: map[string]Lexer{}, - } -} - -// Names of all lexers, optionally including aliases. -func (l *LexerRegistry) Names(withAliases bool) []string { - out := []string{} - for _, lexer := range l.Lexers { - config := lexer.Config() - out = append(out, config.Name) - if withAliases { - out = append(out, config.Aliases...) - } - } - sort.Strings(out) - return out -} - -// Get a Lexer by name, alias or file extension. -func (l *LexerRegistry) Get(name string) Lexer { - if lexer := l.byName[name]; lexer != nil { - return lexer - } - if lexer := l.byAlias[name]; lexer != nil { - return lexer - } - if lexer := l.byName[strings.ToLower(name)]; lexer != nil { - return lexer - } - if lexer := l.byAlias[strings.ToLower(name)]; lexer != nil { - return lexer - } - - candidates := PrioritisedLexers{} - // Try file extension. - if lexer := l.Match("filename." + name); lexer != nil { - candidates = append(candidates, lexer) - } - // Try exact filename. - if lexer := l.Match(name); lexer != nil { - candidates = append(candidates, lexer) - } - if len(candidates) == 0 { - return nil - } - sort.Sort(candidates) - return candidates[0] -} - -// MatchMimeType attempts to find a lexer for the given MIME type. -func (l *LexerRegistry) MatchMimeType(mimeType string) Lexer { - matched := PrioritisedLexers{} - for _, l := range l.Lexers { - for _, lmt := range l.Config().MimeTypes { - if mimeType == lmt { - matched = append(matched, l) - } - } - } - if len(matched) != 0 { - sort.Sort(matched) - return matched[0] - } - return nil -} - -// Match returns the first lexer matching filename. -// -// Note that this iterates over all file patterns in all lexers, so is not fast. -func (l *LexerRegistry) Match(filename string) Lexer { - filename = filepath.Base(filename) - matched := PrioritisedLexers{} - // First, try primary filename matches. - for _, lexer := range l.Lexers { - config := lexer.Config() - for _, glob := range config.Filenames { - ok, err := filepath.Match(glob, filename) - if err != nil { // nolint - panic(err) - } else if ok { - matched = append(matched, lexer) - } else { - for _, suf := range &ignoredSuffixes { - ok, err := filepath.Match(glob+suf, filename) - if err != nil { - panic(err) - } else if ok { - matched = append(matched, lexer) - break - } - } - } - } - } - if len(matched) > 0 { - sort.Sort(matched) - return matched[0] - } - matched = nil - // Next, try filename aliases. - for _, lexer := range l.Lexers { - config := lexer.Config() - for _, glob := range config.AliasFilenames { - ok, err := filepath.Match(glob, filename) - if err != nil { // nolint - panic(err) - } else if ok { - matched = append(matched, lexer) - } else { - for _, suf := range &ignoredSuffixes { - ok, err := filepath.Match(glob+suf, filename) - if err != nil { - panic(err) - } else if ok { - matched = append(matched, lexer) - break - } - } - } - } - } - if len(matched) > 0 { - sort.Sort(matched) - return matched[0] - } - return nil -} - -// Analyse text content and return the "best" lexer.. -func (l *LexerRegistry) Analyse(text string) Lexer { - var picked Lexer - highest := float32(0.0) - for _, lexer := range l.Lexers { - if analyser, ok := lexer.(Analyser); ok { - weight := analyser.AnalyseText(text) - if weight > highest { - picked = lexer - highest = weight - } - } - } - return picked -} - -// Register a Lexer with the LexerRegistry. If the lexer is already registered -// it will be replaced. -func (l *LexerRegistry) Register(lexer Lexer) Lexer { - lexer.SetRegistry(l) - config := lexer.Config() - - l.byName[config.Name] = lexer - l.byName[strings.ToLower(config.Name)] = lexer - - for _, alias := range config.Aliases { - l.byAlias[alias] = lexer - l.byAlias[strings.ToLower(alias)] = lexer - } - - l.Lexers = add(l.Lexers, lexer) - - return lexer -} - -// add adds a lexer to a slice of lexers if it doesn't already exist, or if found will replace it. -func add(lexers Lexers, lexer Lexer) Lexers { - for i, val := range lexers { - if val == nil { - continue - } - - if val.Config().Name == lexer.Config().Name { - lexers[i] = lexer - return lexers - } - } - - return append(lexers, lexer) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/remap.go b/vendor/github.com/alecthomas/chroma/v2/remap.go deleted file mode 100644 index bcf5e66d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/remap.go +++ /dev/null @@ -1,94 +0,0 @@ -package chroma - -type remappingLexer struct { - lexer Lexer - mapper func(Token) []Token -} - -// RemappingLexer remaps a token to a set of, potentially empty, tokens. -func RemappingLexer(lexer Lexer, mapper func(Token) []Token) Lexer { - return &remappingLexer{lexer, mapper} -} - -func (r *remappingLexer) AnalyseText(text string) float32 { - return r.lexer.AnalyseText(text) -} - -func (r *remappingLexer) SetAnalyser(analyser func(text string) float32) Lexer { - r.lexer.SetAnalyser(analyser) - return r -} - -func (r *remappingLexer) SetRegistry(registry *LexerRegistry) Lexer { - r.lexer.SetRegistry(registry) - return r -} - -func (r *remappingLexer) Config() *Config { - return r.lexer.Config() -} - -func (r *remappingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { - it, err := r.lexer.Tokenise(options, text) - if err != nil { - return nil, err - } - var buffer []Token - return func() Token { - for { - if len(buffer) > 0 { - t := buffer[0] - buffer = buffer[1:] - return t - } - t := it() - if t == EOF { - return t - } - buffer = r.mapper(t) - } - }, nil -} - -// TypeMapping defines type maps for the TypeRemappingLexer. -type TypeMapping []struct { - From, To TokenType - Words []string -} - -// TypeRemappingLexer remaps types of tokens coming from a parent Lexer. -// -// eg. Map "defvaralias" tokens of type NameVariable to NameFunction: -// -// mapping := TypeMapping{ -// {NameVariable, NameFunction, []string{"defvaralias"}, -// } -// lexer = TypeRemappingLexer(lexer, mapping) -func TypeRemappingLexer(lexer Lexer, mapping TypeMapping) Lexer { - // Lookup table for fast remapping. - lut := map[TokenType]map[string]TokenType{} - for _, rt := range mapping { - km, ok := lut[rt.From] - if !ok { - km = map[string]TokenType{} - lut[rt.From] = km - } - if len(rt.Words) == 0 { - km[""] = rt.To - } else { - for _, k := range rt.Words { - km[k] = rt.To - } - } - } - return RemappingLexer(lexer, func(t Token) []Token { - if k, ok := lut[t.Type]; ok { - if tt, ok := k[t.Value]; ok { - t.Type = tt - } else if tt, ok := k[""]; ok { - t.Type = tt - } - } - return []Token{t} - }) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/renovate.json5 b/vendor/github.com/alecthomas/chroma/v2/renovate.json5 deleted file mode 100644 index 77c7b016..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/renovate.json5 +++ /dev/null @@ -1,18 +0,0 @@ -{ - $schema: "https://docs.renovatebot.com/renovate-schema.json", - extends: [ - "config:recommended", - ":semanticCommits", - ":semanticCommitTypeAll(chore)", - ":semanticCommitScope(deps)", - "group:allNonMajor", - "schedule:earlyMondays", // Run once a week. - ], - packageRules: [ - { - matchPackageNames: ["golangci-lint"], - matchManagers: ["hermit"], - enabled: false, - }, - ], -} diff --git a/vendor/github.com/alecthomas/chroma/v2/serialise.go b/vendor/github.com/alecthomas/chroma/v2/serialise.go deleted file mode 100644 index 645a5faa..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/serialise.go +++ /dev/null @@ -1,479 +0,0 @@ -package chroma - -import ( - "compress/gzip" - "encoding/xml" - "errors" - "fmt" - "io" - "io/fs" - "math" - "path/filepath" - "reflect" - "regexp" - "strings" - - "github.com/dlclark/regexp2" -) - -// Serialisation of Chroma rules to XML. The format is: -// -// -// -// -// [<$EMITTER ...>] -// [<$MUTATOR ...>] -// -// -// -// -// eg. Include("String") would become: -// -// -// -// -// -// [null, null, {"kind": "include", "state": "String"}] -// -// eg. Rule{`\d+`, Text, nil} would become: -// -// -// -// -// -// eg. Rule{`"`, String, Push("String")} -// -// -// -// -// -// -// eg. Rule{`(\w+)(\n)`, ByGroups(Keyword, Whitespace), nil}, -// -// -// -// -// -var ( - // ErrNotSerialisable is returned if a lexer contains Rules that cannot be serialised. - ErrNotSerialisable = fmt.Errorf("not serialisable") - emitterTemplates = func() map[string]SerialisableEmitter { - out := map[string]SerialisableEmitter{} - for _, emitter := range []SerialisableEmitter{ - &byGroupsEmitter{}, - &usingSelfEmitter{}, - TokenType(0), - &usingEmitter{}, - &usingByGroup{}, - } { - out[emitter.EmitterKind()] = emitter - } - return out - }() - mutatorTemplates = func() map[string]SerialisableMutator { - out := map[string]SerialisableMutator{} - for _, mutator := range []SerialisableMutator{ - &includeMutator{}, - &combinedMutator{}, - &multiMutator{}, - &pushMutator{}, - &popMutator{}, - } { - out[mutator.MutatorKind()] = mutator - } - return out - }() -) - -// fastUnmarshalConfig unmarshals only the Config from a serialised lexer. -func fastUnmarshalConfig(from fs.FS, path string) (*Config, error) { - r, err := from.Open(path) - if err != nil { - return nil, err - } - defer r.Close() - dec := xml.NewDecoder(r) - for { - token, err := dec.Token() - if err != nil { - if errors.Is(err, io.EOF) { - return nil, fmt.Errorf("could not find element") - } - return nil, err - } - switch se := token.(type) { - case xml.StartElement: - if se.Name.Local != "config" { - break - } - - var config Config - err = dec.DecodeElement(&config, &se) - if err != nil { - return nil, fmt.Errorf("%s: %w", path, err) - } - return &config, nil - } - } -} - -// MustNewXMLLexer constructs a new RegexLexer from an XML file or panics. -func MustNewXMLLexer(from fs.FS, path string) *RegexLexer { - lex, err := NewXMLLexer(from, path) - if err != nil { - panic(err) - } - return lex -} - -// NewXMLLexer creates a new RegexLexer from a serialised RegexLexer. -func NewXMLLexer(from fs.FS, path string) (*RegexLexer, error) { - config, err := fastUnmarshalConfig(from, path) - if err != nil { - return nil, err - } - - for _, glob := range append(config.Filenames, config.AliasFilenames...) { - _, err := filepath.Match(glob, "") - if err != nil { - return nil, fmt.Errorf("%s: %q is not a valid glob: %w", config.Name, glob, err) - } - } - - var analyserFn func(string) float32 - - if config.Analyse != nil { - type regexAnalyse struct { - re *regexp2.Regexp - score float32 - } - - regexAnalysers := make([]regexAnalyse, 0, len(config.Analyse.Regexes)) - - for _, ra := range config.Analyse.Regexes { - re, err := regexp2.Compile(ra.Pattern, regexp2.None) - if err != nil { - return nil, fmt.Errorf("%s: %q is not a valid analyser regex: %w", config.Name, ra.Pattern, err) - } - - regexAnalysers = append(regexAnalysers, regexAnalyse{re, ra.Score}) - } - - analyserFn = func(text string) float32 { - var score float32 - - for _, ra := range regexAnalysers { - ok, err := ra.re.MatchString(text) - if err != nil { - return 0 - } - - if ok && config.Analyse.First { - return float32(math.Min(float64(ra.score), 1.0)) - } - - if ok { - score += ra.score - } - } - - return float32(math.Min(float64(score), 1.0)) - } - } - - return &RegexLexer{ - config: config, - analyser: analyserFn, - fetchRulesFunc: func() (Rules, error) { - var lexer struct { - Config - Rules Rules `xml:"rules"` - } - // Try to open .xml fallback to .xml.gz - fr, err := from.Open(path) - if err != nil { - if errors.Is(err, fs.ErrNotExist) { - path += ".gz" - fr, err = from.Open(path) - if err != nil { - return nil, err - } - } else { - return nil, err - } - } - defer fr.Close() - var r io.Reader = fr - if strings.HasSuffix(path, ".gz") { - r, err = gzip.NewReader(r) - if err != nil { - return nil, fmt.Errorf("%s: %w", path, err) - } - } - err = xml.NewDecoder(r).Decode(&lexer) - if err != nil { - return nil, fmt.Errorf("%s: %w", path, err) - } - return lexer.Rules, nil - }, - }, nil -} - -// Marshal a RegexLexer to XML. -func Marshal(l *RegexLexer) ([]byte, error) { - type lexer struct { - Config Config `xml:"config"` - Rules Rules `xml:"rules"` - } - - rules, err := l.Rules() - if err != nil { - return nil, err - } - root := &lexer{ - Config: *l.Config(), - Rules: rules, - } - data, err := xml.MarshalIndent(root, "", " ") - if err != nil { - return nil, err - } - re := regexp.MustCompile(`>`) - data = re.ReplaceAll(data, []byte(`/>`)) - return data, nil -} - -// Unmarshal a RegexLexer from XML. -func Unmarshal(data []byte) (*RegexLexer, error) { - type lexer struct { - Config Config `xml:"config"` - Rules Rules `xml:"rules"` - } - root := &lexer{} - err := xml.Unmarshal(data, root) - if err != nil { - return nil, fmt.Errorf("invalid Lexer XML: %w", err) - } - lex, err := NewLexer(&root.Config, func() Rules { return root.Rules }) - if err != nil { - return nil, err - } - return lex, nil -} - -func marshalMutator(e *xml.Encoder, mutator Mutator) error { - if mutator == nil { - return nil - } - smutator, ok := mutator.(SerialisableMutator) - if !ok { - return fmt.Errorf("unsupported mutator: %w", ErrNotSerialisable) - } - return e.EncodeElement(mutator, xml.StartElement{Name: xml.Name{Local: smutator.MutatorKind()}}) -} - -func unmarshalMutator(d *xml.Decoder, start xml.StartElement) (Mutator, error) { - kind := start.Name.Local - mutator, ok := mutatorTemplates[kind] - if !ok { - return nil, fmt.Errorf("unknown mutator %q: %w", kind, ErrNotSerialisable) - } - value, target := newFromTemplate(mutator) - if err := d.DecodeElement(target, &start); err != nil { - return nil, err - } - return value().(SerialisableMutator), nil -} - -func marshalEmitter(e *xml.Encoder, emitter Emitter) error { - if emitter == nil { - return nil - } - semitter, ok := emitter.(SerialisableEmitter) - if !ok { - return fmt.Errorf("unsupported emitter %T: %w", emitter, ErrNotSerialisable) - } - return e.EncodeElement(emitter, xml.StartElement{ - Name: xml.Name{Local: semitter.EmitterKind()}, - }) -} - -func unmarshalEmitter(d *xml.Decoder, start xml.StartElement) (Emitter, error) { - kind := start.Name.Local - mutator, ok := emitterTemplates[kind] - if !ok { - return nil, fmt.Errorf("unknown emitter %q: %w", kind, ErrNotSerialisable) - } - value, target := newFromTemplate(mutator) - if err := d.DecodeElement(target, &start); err != nil { - return nil, err - } - return value().(SerialisableEmitter), nil -} - -func (r Rule) MarshalXML(e *xml.Encoder, _ xml.StartElement) error { - start := xml.StartElement{ - Name: xml.Name{Local: "rule"}, - } - if r.Pattern != "" { - start.Attr = append(start.Attr, xml.Attr{ - Name: xml.Name{Local: "pattern"}, - Value: r.Pattern, - }) - } - if err := e.EncodeToken(start); err != nil { - return err - } - if err := marshalEmitter(e, r.Type); err != nil { - return err - } - if err := marshalMutator(e, r.Mutator); err != nil { - return err - } - return e.EncodeToken(xml.EndElement{Name: start.Name}) -} - -func (r *Rule) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { - for _, attr := range start.Attr { - if attr.Name.Local == "pattern" { - r.Pattern = attr.Value - break - } - } - for { - token, err := d.Token() - if err != nil { - return err - } - switch token := token.(type) { - case xml.StartElement: - mutator, err := unmarshalMutator(d, token) - if err != nil && !errors.Is(err, ErrNotSerialisable) { - return err - } else if err == nil { - if r.Mutator != nil { - return fmt.Errorf("duplicate mutator") - } - r.Mutator = mutator - continue - } - emitter, err := unmarshalEmitter(d, token) - if err != nil && !errors.Is(err, ErrNotSerialisable) { // nolint: gocritic - return err - } else if err == nil { - if r.Type != nil { - return fmt.Errorf("duplicate emitter") - } - r.Type = emitter - continue - } else { - return err - } - - case xml.EndElement: - return nil - } - } -} - -type xmlRuleState struct { - Name string `xml:"name,attr"` - Rules []Rule `xml:"rule"` -} - -type xmlRules struct { - States []xmlRuleState `xml:"state"` -} - -func (r Rules) MarshalXML(e *xml.Encoder, _ xml.StartElement) error { - xr := xmlRules{} - for state, rules := range r { - xr.States = append(xr.States, xmlRuleState{ - Name: state, - Rules: rules, - }) - } - return e.EncodeElement(xr, xml.StartElement{Name: xml.Name{Local: "rules"}}) -} - -func (r *Rules) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { - xr := xmlRules{} - if err := d.DecodeElement(&xr, &start); err != nil { - return err - } - if *r == nil { - *r = Rules{} - } - for _, state := range xr.States { - (*r)[state.Name] = state.Rules - } - return nil -} - -type xmlTokenType struct { - Type string `xml:"type,attr"` -} - -func (t *TokenType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { - el := xmlTokenType{} - if err := d.DecodeElement(&el, &start); err != nil { - return err - } - tt, err := TokenTypeString(el.Type) - if err != nil { - return err - } - *t = tt - return nil -} - -func (t TokenType) MarshalXML(e *xml.Encoder, start xml.StartElement) error { - start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "type"}, Value: t.String()}) - if err := e.EncodeToken(start); err != nil { - return err - } - return e.EncodeToken(xml.EndElement{Name: start.Name}) -} - -// This hijinks is a bit unfortunate but without it we can't deserialise into TokenType. -func newFromTemplate(template interface{}) (value func() interface{}, target interface{}) { - t := reflect.TypeOf(template) - if t.Kind() == reflect.Ptr { - v := reflect.New(t.Elem()) - return v.Interface, v.Interface() - } - v := reflect.New(t) - return func() interface{} { return v.Elem().Interface() }, v.Interface() -} - -func (b *Emitters) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { - for { - token, err := d.Token() - if err != nil { - return err - } - switch token := token.(type) { - case xml.StartElement: - emitter, err := unmarshalEmitter(d, token) - if err != nil { - return err - } - *b = append(*b, emitter) - - case xml.EndElement: - return nil - } - } -} - -func (b Emitters) MarshalXML(e *xml.Encoder, start xml.StartElement) error { - if err := e.EncodeToken(start); err != nil { - return err - } - for _, m := range b { - if err := marshalEmitter(e, m); err != nil { - return err - } - } - return e.EncodeToken(xml.EndElement{Name: start.Name}) -} diff --git a/vendor/github.com/alecthomas/chroma/v2/style.go b/vendor/github.com/alecthomas/chroma/v2/style.go deleted file mode 100644 index cc8d9a60..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/style.go +++ /dev/null @@ -1,481 +0,0 @@ -package chroma - -import ( - "encoding/xml" - "fmt" - "io" - "sort" - "strings" -) - -// Trilean value for StyleEntry value inheritance. -type Trilean uint8 - -// Trilean states. -const ( - Pass Trilean = iota - Yes - No -) - -func (t Trilean) String() string { - switch t { - case Yes: - return "Yes" - case No: - return "No" - default: - return "Pass" - } -} - -// Prefix returns s with "no" as a prefix if Trilean is no. -func (t Trilean) Prefix(s string) string { - if t == Yes { - return s - } else if t == No { - return "no" + s - } - return "" -} - -// A StyleEntry in the Style map. -type StyleEntry struct { - // Hex colours. - Colour Colour - Background Colour - Border Colour - - Bold Trilean - Italic Trilean - Underline Trilean - NoInherit bool -} - -func (s StyleEntry) MarshalText() ([]byte, error) { - return []byte(s.String()), nil -} - -func (s StyleEntry) String() string { - out := []string{} - if s.Bold != Pass { - out = append(out, s.Bold.Prefix("bold")) - } - if s.Italic != Pass { - out = append(out, s.Italic.Prefix("italic")) - } - if s.Underline != Pass { - out = append(out, s.Underline.Prefix("underline")) - } - if s.NoInherit { - out = append(out, "noinherit") - } - if s.Colour.IsSet() { - out = append(out, s.Colour.String()) - } - if s.Background.IsSet() { - out = append(out, "bg:"+s.Background.String()) - } - if s.Border.IsSet() { - out = append(out, "border:"+s.Border.String()) - } - return strings.Join(out, " ") -} - -// Sub subtracts e from s where elements match. -func (s StyleEntry) Sub(e StyleEntry) StyleEntry { - out := StyleEntry{} - if e.Colour != s.Colour { - out.Colour = s.Colour - } - if e.Background != s.Background { - out.Background = s.Background - } - if e.Bold != s.Bold { - out.Bold = s.Bold - } - if e.Italic != s.Italic { - out.Italic = s.Italic - } - if e.Underline != s.Underline { - out.Underline = s.Underline - } - if e.Border != s.Border { - out.Border = s.Border - } - return out -} - -// Inherit styles from ancestors. -// -// Ancestors should be provided from oldest to newest. -func (s StyleEntry) Inherit(ancestors ...StyleEntry) StyleEntry { - out := s - for i := len(ancestors) - 1; i >= 0; i-- { - if out.NoInherit { - return out - } - ancestor := ancestors[i] - if !out.Colour.IsSet() { - out.Colour = ancestor.Colour - } - if !out.Background.IsSet() { - out.Background = ancestor.Background - } - if !out.Border.IsSet() { - out.Border = ancestor.Border - } - if out.Bold == Pass { - out.Bold = ancestor.Bold - } - if out.Italic == Pass { - out.Italic = ancestor.Italic - } - if out.Underline == Pass { - out.Underline = ancestor.Underline - } - } - return out -} - -func (s StyleEntry) IsZero() bool { - return s.Colour == 0 && s.Background == 0 && s.Border == 0 && s.Bold == Pass && s.Italic == Pass && - s.Underline == Pass && !s.NoInherit -} - -// A StyleBuilder is a mutable structure for building styles. -// -// Once built, a Style is immutable. -type StyleBuilder struct { - entries map[TokenType]string - name string - parent *Style -} - -func NewStyleBuilder(name string) *StyleBuilder { - return &StyleBuilder{name: name, entries: map[TokenType]string{}} -} - -func (s *StyleBuilder) AddAll(entries StyleEntries) *StyleBuilder { - for ttype, entry := range entries { - s.entries[ttype] = entry - } - return s -} - -func (s *StyleBuilder) Get(ttype TokenType) StyleEntry { - // This is less than ideal, but it's the price for not having to check errors on each Add(). - entry, _ := ParseStyleEntry(s.entries[ttype]) - if s.parent != nil { - entry = entry.Inherit(s.parent.Get(ttype)) - } - return entry -} - -// Add an entry to the Style map. -// -// See http://pygments.org/docs/styles/#style-rules for details. -func (s *StyleBuilder) Add(ttype TokenType, entry string) *StyleBuilder { // nolint: gocyclo - s.entries[ttype] = entry - return s -} - -func (s *StyleBuilder) AddEntry(ttype TokenType, entry StyleEntry) *StyleBuilder { - s.entries[ttype] = entry.String() - return s -} - -// Transform passes each style entry currently defined in the builder to the supplied -// function and saves the returned value. This can be used to adjust a style's colours; -// see Colour's ClampBrightness function, for example. -func (s *StyleBuilder) Transform(transform func(StyleEntry) StyleEntry) *StyleBuilder { - types := make(map[TokenType]struct{}) - for tt := range s.entries { - types[tt] = struct{}{} - } - if s.parent != nil { - for _, tt := range s.parent.Types() { - types[tt] = struct{}{} - } - } - for tt := range types { - s.AddEntry(tt, transform(s.Get(tt))) - } - return s -} - -func (s *StyleBuilder) Build() (*Style, error) { - style := &Style{ - Name: s.name, - entries: map[TokenType]StyleEntry{}, - parent: s.parent, - } - for ttype, descriptor := range s.entries { - entry, err := ParseStyleEntry(descriptor) - if err != nil { - return nil, fmt.Errorf("invalid entry for %s: %s", ttype, err) - } - style.entries[ttype] = entry - } - return style, nil -} - -// StyleEntries mapping TokenType to colour definition. -type StyleEntries map[TokenType]string - -// NewXMLStyle parses an XML style definition. -func NewXMLStyle(r io.Reader) (*Style, error) { - dec := xml.NewDecoder(r) - style := &Style{} - return style, dec.Decode(style) -} - -// MustNewXMLStyle is like NewXMLStyle but panics on error. -func MustNewXMLStyle(r io.Reader) *Style { - style, err := NewXMLStyle(r) - if err != nil { - panic(err) - } - return style -} - -// NewStyle creates a new style definition. -func NewStyle(name string, entries StyleEntries) (*Style, error) { - return NewStyleBuilder(name).AddAll(entries).Build() -} - -// MustNewStyle creates a new style or panics. -func MustNewStyle(name string, entries StyleEntries) *Style { - style, err := NewStyle(name, entries) - if err != nil { - panic(err) - } - return style -} - -// A Style definition. -// -// See http://pygments.org/docs/styles/ for details. Semantics are intended to be identical. -type Style struct { - Name string - entries map[TokenType]StyleEntry - parent *Style -} - -func (s *Style) MarshalXML(e *xml.Encoder, start xml.StartElement) error { - if s.parent != nil { - return fmt.Errorf("cannot marshal style with parent") - } - start.Name = xml.Name{Local: "style"} - start.Attr = []xml.Attr{{Name: xml.Name{Local: "name"}, Value: s.Name}} - if err := e.EncodeToken(start); err != nil { - return err - } - sorted := make([]TokenType, 0, len(s.entries)) - for ttype := range s.entries { - sorted = append(sorted, ttype) - } - sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] }) - for _, ttype := range sorted { - entry := s.entries[ttype] - el := xml.StartElement{Name: xml.Name{Local: "entry"}} - el.Attr = []xml.Attr{ - {Name: xml.Name{Local: "type"}, Value: ttype.String()}, - {Name: xml.Name{Local: "style"}, Value: entry.String()}, - } - if err := e.EncodeToken(el); err != nil { - return err - } - if err := e.EncodeToken(xml.EndElement{Name: el.Name}); err != nil { - return err - } - } - return e.EncodeToken(xml.EndElement{Name: start.Name}) -} - -func (s *Style) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { - for _, attr := range start.Attr { - if attr.Name.Local == "name" { - s.Name = attr.Value - } else { - return fmt.Errorf("unexpected attribute %s", attr.Name.Local) - } - } - if s.Name == "" { - return fmt.Errorf("missing style name attribute") - } - s.entries = map[TokenType]StyleEntry{} - for { - tok, err := d.Token() - if err != nil { - return err - } - switch el := tok.(type) { - case xml.StartElement: - if el.Name.Local != "entry" { - return fmt.Errorf("unexpected element %s", el.Name.Local) - } - var ttype TokenType - var entry StyleEntry - for _, attr := range el.Attr { - switch attr.Name.Local { - case "type": - ttype, err = TokenTypeString(attr.Value) - if err != nil { - return err - } - - case "style": - entry, err = ParseStyleEntry(attr.Value) - if err != nil { - return err - } - - default: - return fmt.Errorf("unexpected attribute %s", attr.Name.Local) - } - } - s.entries[ttype] = entry - - case xml.EndElement: - if el.Name.Local == start.Name.Local { - return nil - } - } - } -} - -// Types that are styled. -func (s *Style) Types() []TokenType { - dedupe := map[TokenType]bool{} - for tt := range s.entries { - dedupe[tt] = true - } - if s.parent != nil { - for _, tt := range s.parent.Types() { - dedupe[tt] = true - } - } - out := make([]TokenType, 0, len(dedupe)) - for tt := range dedupe { - out = append(out, tt) - } - return out -} - -// Builder creates a mutable builder from this Style. -// -// The builder can then be safely modified. This is a cheap operation. -func (s *Style) Builder() *StyleBuilder { - return &StyleBuilder{ - name: s.Name, - entries: map[TokenType]string{}, - parent: s, - } -} - -// Has checks if an exact style entry match exists for a token type. -// -// This is distinct from Get() which will merge parent tokens. -func (s *Style) Has(ttype TokenType) bool { - return !s.get(ttype).IsZero() || s.synthesisable(ttype) -} - -// Get a style entry. Will try sub-category or category if an exact match is not found, and -// finally return the Background. -func (s *Style) Get(ttype TokenType) StyleEntry { - return s.get(ttype).Inherit( - s.get(Background), - s.get(Text), - s.get(ttype.Category()), - s.get(ttype.SubCategory())) -} - -func (s *Style) get(ttype TokenType) StyleEntry { - out := s.entries[ttype] - if out.IsZero() && s.parent != nil { - return s.parent.get(ttype) - } - if out.IsZero() && s.synthesisable(ttype) { - out = s.synthesise(ttype) - } - return out -} - -func (s *Style) synthesise(ttype TokenType) StyleEntry { - bg := s.get(Background) - text := StyleEntry{Colour: bg.Colour} - text.Colour = text.Colour.BrightenOrDarken(0.5) - - switch ttype { - // If we don't have a line highlight colour, make one that is 10% brighter/darker than the background. - case LineHighlight: - return StyleEntry{Background: bg.Background.BrightenOrDarken(0.1)} - - // If we don't have line numbers, use the text colour but 20% brighter/darker - case LineNumbers, LineNumbersTable: - return text - - default: - return StyleEntry{} - } -} - -func (s *Style) synthesisable(ttype TokenType) bool { - return ttype == LineHighlight || ttype == LineNumbers || ttype == LineNumbersTable -} - -// MustParseStyleEntry parses a Pygments style entry or panics. -func MustParseStyleEntry(entry string) StyleEntry { - out, err := ParseStyleEntry(entry) - if err != nil { - panic(err) - } - return out -} - -// ParseStyleEntry parses a Pygments style entry. -func ParseStyleEntry(entry string) (StyleEntry, error) { // nolint: gocyclo - out := StyleEntry{} - parts := strings.Fields(entry) - for _, part := range parts { - switch { - case part == "italic": - out.Italic = Yes - case part == "noitalic": - out.Italic = No - case part == "bold": - out.Bold = Yes - case part == "nobold": - out.Bold = No - case part == "underline": - out.Underline = Yes - case part == "nounderline": - out.Underline = No - case part == "inherit": - out.NoInherit = false - case part == "noinherit": - out.NoInherit = true - case part == "bg:": - out.Background = 0 - case strings.HasPrefix(part, "bg:#"): - out.Background = ParseColour(part[3:]) - if !out.Background.IsSet() { - return StyleEntry{}, fmt.Errorf("invalid background colour %q", part) - } - case strings.HasPrefix(part, "border:#"): - out.Border = ParseColour(part[7:]) - if !out.Border.IsSet() { - return StyleEntry{}, fmt.Errorf("invalid border colour %q", part) - } - case strings.HasPrefix(part, "#"): - out.Colour = ParseColour(part) - if !out.Colour.IsSet() { - return StyleEntry{}, fmt.Errorf("invalid colour %q", part) - } - default: - return StyleEntry{}, fmt.Errorf("unknown style element %q", part) - } - } - return out, nil -} diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/abap.xml b/vendor/github.com/alecthomas/chroma/v2/styles/abap.xml deleted file mode 100644 index 36ea2f1d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/abap.xml +++ /dev/null @@ -1,11 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/algol.xml b/vendor/github.com/alecthomas/chroma/v2/styles/algol.xml deleted file mode 100644 index e8a6dc1b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/algol.xml +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/algol_nu.xml b/vendor/github.com/alecthomas/chroma/v2/styles/algol_nu.xml deleted file mode 100644 index 7fa340f3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/algol_nu.xml +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/api.go b/vendor/github.com/alecthomas/chroma/v2/styles/api.go deleted file mode 100644 index e26d6f0a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/api.go +++ /dev/null @@ -1,65 +0,0 @@ -package styles - -import ( - "embed" - "io/fs" - "sort" - - "github.com/alecthomas/chroma/v2" -) - -//go:embed *.xml -var embedded embed.FS - -// Registry of Styles. -var Registry = func() map[string]*chroma.Style { - registry := map[string]*chroma.Style{} - // Register all embedded styles. - files, err := fs.ReadDir(embedded, ".") - if err != nil { - panic(err) - } - for _, file := range files { - if file.IsDir() { - continue - } - r, err := embedded.Open(file.Name()) - if err != nil { - panic(err) - } - style, err := chroma.NewXMLStyle(r) - if err != nil { - panic(err) - } - registry[style.Name] = style - _ = r.Close() - } - return registry -}() - -// Fallback style. Reassign to change the default fallback style. -var Fallback = Registry["swapoff"] - -// Register a chroma.Style. -func Register(style *chroma.Style) *chroma.Style { - Registry[style.Name] = style - return style -} - -// Names of all available styles. -func Names() []string { - out := []string{} - for name := range Registry { - out = append(out, name) - } - sort.Strings(out) - return out -} - -// Get named style, or Fallback. -func Get(name string) *chroma.Style { - if style, ok := Registry[name]; ok { - return style - } - return Fallback -} diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/arduino.xml b/vendor/github.com/alecthomas/chroma/v2/styles/arduino.xml deleted file mode 100644 index d9891dc5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/arduino.xml +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/autumn.xml b/vendor/github.com/alecthomas/chroma/v2/styles/autumn.xml deleted file mode 100644 index 74d2eae9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/autumn.xml +++ /dev/null @@ -1,36 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/average.xml b/vendor/github.com/alecthomas/chroma/v2/styles/average.xml deleted file mode 100644 index 79bdb95f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/average.xml +++ /dev/null @@ -1,74 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/base16-snazzy.xml b/vendor/github.com/alecthomas/chroma/v2/styles/base16-snazzy.xml deleted file mode 100644 index a05ba24e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/base16-snazzy.xml +++ /dev/null @@ -1,74 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/borland.xml b/vendor/github.com/alecthomas/chroma/v2/styles/borland.xml deleted file mode 100644 index 0d8f574c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/borland.xml +++ /dev/null @@ -1,26 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/bw.xml b/vendor/github.com/alecthomas/chroma/v2/styles/bw.xml deleted file mode 100644 index fb0e868d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/bw.xml +++ /dev/null @@ -1,23 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml deleted file mode 100644 index 0adf1ba9..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-frappe.xml +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml deleted file mode 100644 index 3ea767fd..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-latte.xml +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml deleted file mode 100644 index 6b500284..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-macchiato.xml +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml b/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml deleted file mode 100644 index 9a401912..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/catppuccin-mocha.xml +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/colorful.xml b/vendor/github.com/alecthomas/chroma/v2/styles/colorful.xml deleted file mode 100644 index 32442d71..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/colorful.xml +++ /dev/null @@ -1,52 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/compat.go b/vendor/github.com/alecthomas/chroma/v2/styles/compat.go deleted file mode 100644 index 4a6aaa66..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/compat.go +++ /dev/null @@ -1,66 +0,0 @@ -package styles - -// Present for backwards compatibility. -// -// Deprecated: use styles.Get(name) instead. -var ( - Abap = Registry["abap"] - Algol = Registry["algol"] - AlgolNu = Registry["algol_nu"] - Arduino = Registry["arduino"] - Autumn = Registry["autumn"] - Average = Registry["average"] - Base16Snazzy = Registry["base16-snazzy"] - Borland = Registry["borland"] - BlackWhite = Registry["bw"] - CatppuccinFrappe = Registry["catppuccin-frappe"] - CatppuccinLatte = Registry["catppuccin-latte"] - CatppuccinMacchiato = Registry["catppuccin-macchiato"] - CatppuccinMocha = Registry["catppuccin-mocha"] - Colorful = Registry["colorful"] - DoomOne = Registry["doom-one"] - DoomOne2 = Registry["doom-one2"] - Dracula = Registry["dracula"] - Emacs = Registry["emacs"] - Friendly = Registry["friendly"] - Fruity = Registry["fruity"] - GitHubDark = Registry["github-dark"] - GitHub = Registry["github"] - GruvboxLight = Registry["gruvbox-light"] - Gruvbox = Registry["gruvbox"] - HrDark = Registry["hrdark"] - HrHighContrast = Registry["hr_high_contrast"] - Igor = Registry["igor"] - Lovelace = Registry["lovelace"] - Manni = Registry["manni"] - ModusOperandi = Registry["modus-operandi"] - ModusVivendi = Registry["modus-vivendi"] - Monokai = Registry["monokai"] - MonokaiLight = Registry["monokailight"] - Murphy = Registry["murphy"] - Native = Registry["native"] - Nord = Registry["nord"] - OnesEnterprise = Registry["onesenterprise"] - ParaisoDark = Registry["paraiso-dark"] - ParaisoLight = Registry["paraiso-light"] - Pastie = Registry["pastie"] - Perldoc = Registry["perldoc"] - Pygments = Registry["pygments"] - RainbowDash = Registry["rainbow_dash"] - RosePineDawn = Registry["rose-pine-dawn"] - RosePineMoon = Registry["rose-pine-moon"] - RosePine = Registry["rose-pine"] - Rrt = Registry["rrt"] - SolarizedDark = Registry["solarized-dark"] - SolarizedDark256 = Registry["solarized-dark256"] - SolarizedLight = Registry["solarized-light"] - SwapOff = Registry["swapoff"] - Tango = Registry["tango"] - Trac = Registry["trac"] - Vim = Registry["vim"] - VisualStudio = Registry["vs"] - Vulcan = Registry["vulcan"] - WitchHazel = Registry["witchhazel"] - XcodeDark = Registry["xcode-dark"] - Xcode = Registry["xcode"] -) diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/doom-one.xml b/vendor/github.com/alecthomas/chroma/v2/styles/doom-one.xml deleted file mode 100644 index 1f5127ef..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/doom-one.xml +++ /dev/null @@ -1,51 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/doom-one2.xml b/vendor/github.com/alecthomas/chroma/v2/styles/doom-one2.xml deleted file mode 100644 index f47debaf..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/doom-one2.xml +++ /dev/null @@ -1,64 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/dracula.xml b/vendor/github.com/alecthomas/chroma/v2/styles/dracula.xml deleted file mode 100644 index 9df7da11..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/dracula.xml +++ /dev/null @@ -1,74 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/emacs.xml b/vendor/github.com/alecthomas/chroma/v2/styles/emacs.xml deleted file mode 100644 index 981ce8e4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/emacs.xml +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/friendly.xml b/vendor/github.com/alecthomas/chroma/v2/styles/friendly.xml deleted file mode 100644 index f4980104..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/friendly.xml +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/fruity.xml b/vendor/github.com/alecthomas/chroma/v2/styles/fruity.xml deleted file mode 100644 index bcc06aa7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/fruity.xml +++ /dev/null @@ -1,19 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml b/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml deleted file mode 100644 index 711aeafc..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/github-dark.xml +++ /dev/null @@ -1,45 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/github.xml b/vendor/github.com/alecthomas/chroma/v2/styles/github.xml deleted file mode 100644 index e7caee7b..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/github.xml +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.xml b/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.xml deleted file mode 100644 index 8c4f0642..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox-light.xml +++ /dev/null @@ -1,33 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox.xml b/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox.xml deleted file mode 100644 index 2f6a0a2a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/gruvbox.xml +++ /dev/null @@ -1,33 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/hr_high_contrast.xml b/vendor/github.com/alecthomas/chroma/v2/styles/hr_high_contrast.xml deleted file mode 100644 index 61cde204..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/hr_high_contrast.xml +++ /dev/null @@ -1,12 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/hrdark.xml b/vendor/github.com/alecthomas/chroma/v2/styles/hrdark.xml deleted file mode 100644 index bc7a6f31..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/hrdark.xml +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/igor.xml b/vendor/github.com/alecthomas/chroma/v2/styles/igor.xml deleted file mode 100644 index 773c83b6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/igor.xml +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/lovelace.xml b/vendor/github.com/alecthomas/chroma/v2/styles/lovelace.xml deleted file mode 100644 index e336c930..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/lovelace.xml +++ /dev/null @@ -1,53 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/manni.xml b/vendor/github.com/alecthomas/chroma/v2/styles/manni.xml deleted file mode 100644 index 99324bd3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/manni.xml +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml b/vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml deleted file mode 100644 index 023137aa..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/modus-operandi.xml +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/modus-vivendi.xml b/vendor/github.com/alecthomas/chroma/v2/styles/modus-vivendi.xml deleted file mode 100644 index 8da663dc..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/modus-vivendi.xml +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/monokai.xml b/vendor/github.com/alecthomas/chroma/v2/styles/monokai.xml deleted file mode 100644 index 1a789dde..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/monokai.xml +++ /dev/null @@ -1,29 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/monokailight.xml b/vendor/github.com/alecthomas/chroma/v2/styles/monokailight.xml deleted file mode 100644 index 85cd23e0..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/monokailight.xml +++ /dev/null @@ -1,26 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/murphy.xml b/vendor/github.com/alecthomas/chroma/v2/styles/murphy.xml deleted file mode 100644 index 112d6205..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/murphy.xml +++ /dev/null @@ -1,52 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/native.xml b/vendor/github.com/alecthomas/chroma/v2/styles/native.xml deleted file mode 100644 index 43eea7fd..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/native.xml +++ /dev/null @@ -1,35 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/nord.xml b/vendor/github.com/alecthomas/chroma/v2/styles/nord.xml deleted file mode 100644 index 1c1d1ffb..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/nord.xml +++ /dev/null @@ -1,46 +0,0 @@ - diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/onedark.xml b/vendor/github.com/alecthomas/chroma/v2/styles/onedark.xml deleted file mode 100644 index 6921eb5e..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/onedark.xml +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/onesenterprise.xml b/vendor/github.com/alecthomas/chroma/v2/styles/onesenterprise.xml deleted file mode 100644 index ce86db3f..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/onesenterprise.xml +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/paraiso-dark.xml b/vendor/github.com/alecthomas/chroma/v2/styles/paraiso-dark.xml deleted file mode 100644 index 788db3f7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/paraiso-dark.xml +++ /dev/null @@ -1,37 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/paraiso-light.xml b/vendor/github.com/alecthomas/chroma/v2/styles/paraiso-light.xml deleted file mode 100644 index 06a63bae..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/paraiso-light.xml +++ /dev/null @@ -1,37 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/pastie.xml b/vendor/github.com/alecthomas/chroma/v2/styles/pastie.xml deleted file mode 100644 index a3b0abde..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/pastie.xml +++ /dev/null @@ -1,45 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/perldoc.xml b/vendor/github.com/alecthomas/chroma/v2/styles/perldoc.xml deleted file mode 100644 index 9e5564c3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/perldoc.xml +++ /dev/null @@ -1,37 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/pygments.xml b/vendor/github.com/alecthomas/chroma/v2/styles/pygments.xml deleted file mode 100644 index a3d0d8ba..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/pygments.xml +++ /dev/null @@ -1,42 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/rainbow_dash.xml b/vendor/github.com/alecthomas/chroma/v2/styles/rainbow_dash.xml deleted file mode 100644 index 5b0fe49d..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/rainbow_dash.xml +++ /dev/null @@ -1,40 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-dawn.xml b/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-dawn.xml deleted file mode 100644 index 788bd6f6..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-dawn.xml +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-moon.xml b/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-moon.xml deleted file mode 100644 index f67b8043..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine-moon.xml +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine.xml b/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine.xml deleted file mode 100644 index 3fb70a5a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/rose-pine.xml +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/rrt.xml b/vendor/github.com/alecthomas/chroma/v2/styles/rrt.xml deleted file mode 100644 index 5f1daaa2..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/rrt.xml +++ /dev/null @@ -1,13 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark.xml b/vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark.xml deleted file mode 100644 index a3cf46fd..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark.xml +++ /dev/null @@ -1,39 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark256.xml b/vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark256.xml deleted file mode 100644 index 977cfbe3..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/solarized-dark256.xml +++ /dev/null @@ -1,41 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml b/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml deleted file mode 100644 index 4fbc1d4a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/solarized-light.xml +++ /dev/null @@ -1,17 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/swapoff.xml b/vendor/github.com/alecthomas/chroma/v2/styles/swapoff.xml deleted file mode 100644 index 8a398df8..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/swapoff.xml +++ /dev/null @@ -1,18 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/tango.xml b/vendor/github.com/alecthomas/chroma/v2/styles/tango.xml deleted file mode 100644 index 5ca46bb7..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/tango.xml +++ /dev/null @@ -1,72 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-day.xml b/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-day.xml deleted file mode 100644 index c20d9a41..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-day.xml +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-moon.xml b/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-moon.xml deleted file mode 100644 index 3312f029..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-moon.xml +++ /dev/null @@ -1,83 +0,0 @@ - diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-night.xml b/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-night.xml deleted file mode 100644 index c798bad4..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-night.xml +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-storm.xml b/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-storm.xml deleted file mode 100644 index c0811524..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/tokyonight-storm.xml +++ /dev/null @@ -1,83 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/trac.xml b/vendor/github.com/alecthomas/chroma/v2/styles/trac.xml deleted file mode 100644 index 9f1d2667..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/trac.xml +++ /dev/null @@ -1,35 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/vim.xml b/vendor/github.com/alecthomas/chroma/v2/styles/vim.xml deleted file mode 100644 index fec69343..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/vim.xml +++ /dev/null @@ -1,29 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/vs.xml b/vendor/github.com/alecthomas/chroma/v2/styles/vs.xml deleted file mode 100644 index 56435015..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/vs.xml +++ /dev/null @@ -1,16 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/vulcan.xml b/vendor/github.com/alecthomas/chroma/v2/styles/vulcan.xml deleted file mode 100644 index 4e690945..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/vulcan.xml +++ /dev/null @@ -1,74 +0,0 @@ - diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/witchhazel.xml b/vendor/github.com/alecthomas/chroma/v2/styles/witchhazel.xml deleted file mode 100644 index 52f22991..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/witchhazel.xml +++ /dev/null @@ -1,31 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/xcode-dark.xml b/vendor/github.com/alecthomas/chroma/v2/styles/xcode-dark.xml deleted file mode 100644 index 93439791..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/xcode-dark.xml +++ /dev/null @@ -1,31 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/styles/xcode.xml b/vendor/github.com/alecthomas/chroma/v2/styles/xcode.xml deleted file mode 100644 index 523d746c..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/styles/xcode.xml +++ /dev/null @@ -1,22 +0,0 @@ - \ No newline at end of file diff --git a/vendor/github.com/alecthomas/chroma/v2/table.py b/vendor/github.com/alecthomas/chroma/v2/table.py deleted file mode 100644 index ea4b7556..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/table.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -import re -from collections import defaultdict -from subprocess import check_output - -README_FILE = "README.md" - -lines = check_output(["chroma", "--list"]).decode("utf-8").splitlines() -lines = [line.strip() for line in lines if line.startswith(" ") and not line.startswith(" ")] -lines = sorted(lines, key=lambda l: l.lower()) - -table = defaultdict(list) - -for line in lines: - table[line[0].upper()].append(line) - -rows = [] -for key, value in table.items(): - rows.append("{} | {}".format(key, ", ".join(value))) -tbody = "\n".join(rows) - -with open(README_FILE, "r") as f: - content = f.read() - -with open(README_FILE, "w") as f: - marker = re.compile(r"(?P:----: \\| --------\n).*?(?P\n\n)", re.DOTALL) - replacement = r"\g%s\g" % tbody - updated_content = marker.sub(replacement, content) - f.write(updated_content) - -print(tbody) diff --git a/vendor/github.com/alecthomas/chroma/v2/tokentype_enumer.go b/vendor/github.com/alecthomas/chroma/v2/tokentype_enumer.go deleted file mode 100644 index 696e9ce5..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/tokentype_enumer.go +++ /dev/null @@ -1,573 +0,0 @@ -// Code generated by "enumer -text -type TokenType"; DO NOT EDIT. - -package chroma - -import ( - "fmt" - "strings" -) - -const _TokenTypeName = "NoneOtherErrorCodeLineLineLinkLineTableTDLineTableLineHighlightLineNumbersTableLineNumbersLinePreWrapperBackgroundEOFTypeKeywordKeywordConstantKeywordDeclarationKeywordNamespaceKeywordPseudoKeywordReservedKeywordTypeNameNameAttributeNameBuiltinNameBuiltinPseudoNameClassNameConstantNameDecoratorNameEntityNameExceptionNameFunctionNameFunctionMagicNameKeywordNameLabelNameNamespaceNameOperatorNameOtherNamePseudoNamePropertyNameTagNameVariableNameVariableAnonymousNameVariableClassNameVariableGlobalNameVariableInstanceNameVariableMagicLiteralLiteralDateLiteralOtherLiteralStringLiteralStringAffixLiteralStringAtomLiteralStringBacktickLiteralStringBooleanLiteralStringCharLiteralStringDelimiterLiteralStringDocLiteralStringDoubleLiteralStringEscapeLiteralStringHeredocLiteralStringInterpolLiteralStringNameLiteralStringOtherLiteralStringRegexLiteralStringSingleLiteralStringSymbolLiteralNumberLiteralNumberBinLiteralNumberFloatLiteralNumberHexLiteralNumberIntegerLiteralNumberIntegerLongLiteralNumberOctOperatorOperatorWordPunctuationCommentCommentHashbangCommentMultilineCommentSingleCommentSpecialCommentPreprocCommentPreprocFileGenericGenericDeletedGenericEmphGenericErrorGenericHeadingGenericInsertedGenericOutputGenericPromptGenericStrongGenericSubheadingGenericTracebackGenericUnderlineTextTextWhitespaceTextSymbolTextPunctuation" -const _TokenTypeLowerName = "noneothererrorcodelinelinelinklinetabletdlinetablelinehighlightlinenumberstablelinenumberslineprewrapperbackgroundeoftypekeywordkeywordconstantkeyworddeclarationkeywordnamespacekeywordpseudokeywordreservedkeywordtypenamenameattributenamebuiltinnamebuiltinpseudonameclassnameconstantnamedecoratornameentitynameexceptionnamefunctionnamefunctionmagicnamekeywordnamelabelnamenamespacenameoperatornameothernamepseudonamepropertynametagnamevariablenamevariableanonymousnamevariableclassnamevariableglobalnamevariableinstancenamevariablemagicliteralliteraldateliteralotherliteralstringliteralstringaffixliteralstringatomliteralstringbacktickliteralstringbooleanliteralstringcharliteralstringdelimiterliteralstringdocliteralstringdoubleliteralstringescapeliteralstringheredocliteralstringinterpolliteralstringnameliteralstringotherliteralstringregexliteralstringsingleliteralstringsymbolliteralnumberliteralnumberbinliteralnumberfloatliteralnumberhexliteralnumberintegerliteralnumberintegerlongliteralnumberoctoperatoroperatorwordpunctuationcommentcommenthashbangcommentmultilinecommentsinglecommentspecialcommentpreproccommentpreprocfilegenericgenericdeletedgenericemphgenericerrorgenericheadinggenericinsertedgenericoutputgenericpromptgenericstronggenericsubheadinggenerictracebackgenericunderlinetexttextwhitespacetextsymboltextpunctuation" - -var _TokenTypeMap = map[TokenType]string{ - -13: _TokenTypeName[0:4], - -12: _TokenTypeName[4:9], - -11: _TokenTypeName[9:14], - -10: _TokenTypeName[14:22], - -9: _TokenTypeName[22:30], - -8: _TokenTypeName[30:41], - -7: _TokenTypeName[41:50], - -6: _TokenTypeName[50:63], - -5: _TokenTypeName[63:79], - -4: _TokenTypeName[79:90], - -3: _TokenTypeName[90:94], - -2: _TokenTypeName[94:104], - -1: _TokenTypeName[104:114], - 0: _TokenTypeName[114:121], - 1000: _TokenTypeName[121:128], - 1001: _TokenTypeName[128:143], - 1002: _TokenTypeName[143:161], - 1003: _TokenTypeName[161:177], - 1004: _TokenTypeName[177:190], - 1005: _TokenTypeName[190:205], - 1006: _TokenTypeName[205:216], - 2000: _TokenTypeName[216:220], - 2001: _TokenTypeName[220:233], - 2002: _TokenTypeName[233:244], - 2003: _TokenTypeName[244:261], - 2004: _TokenTypeName[261:270], - 2005: _TokenTypeName[270:282], - 2006: _TokenTypeName[282:295], - 2007: _TokenTypeName[295:305], - 2008: _TokenTypeName[305:318], - 2009: _TokenTypeName[318:330], - 2010: _TokenTypeName[330:347], - 2011: _TokenTypeName[347:358], - 2012: _TokenTypeName[358:367], - 2013: _TokenTypeName[367:380], - 2014: _TokenTypeName[380:392], - 2015: _TokenTypeName[392:401], - 2016: _TokenTypeName[401:411], - 2017: _TokenTypeName[411:423], - 2018: _TokenTypeName[423:430], - 2019: _TokenTypeName[430:442], - 2020: _TokenTypeName[442:463], - 2021: _TokenTypeName[463:480], - 2022: _TokenTypeName[480:498], - 2023: _TokenTypeName[498:518], - 2024: _TokenTypeName[518:535], - 3000: _TokenTypeName[535:542], - 3001: _TokenTypeName[542:553], - 3002: _TokenTypeName[553:565], - 3100: _TokenTypeName[565:578], - 3101: _TokenTypeName[578:596], - 3102: _TokenTypeName[596:613], - 3103: _TokenTypeName[613:634], - 3104: _TokenTypeName[634:654], - 3105: _TokenTypeName[654:671], - 3106: _TokenTypeName[671:693], - 3107: _TokenTypeName[693:709], - 3108: _TokenTypeName[709:728], - 3109: _TokenTypeName[728:747], - 3110: _TokenTypeName[747:767], - 3111: _TokenTypeName[767:788], - 3112: _TokenTypeName[788:805], - 3113: _TokenTypeName[805:823], - 3114: _TokenTypeName[823:841], - 3115: _TokenTypeName[841:860], - 3116: _TokenTypeName[860:879], - 3200: _TokenTypeName[879:892], - 3201: _TokenTypeName[892:908], - 3202: _TokenTypeName[908:926], - 3203: _TokenTypeName[926:942], - 3204: _TokenTypeName[942:962], - 3205: _TokenTypeName[962:986], - 3206: _TokenTypeName[986:1002], - 4000: _TokenTypeName[1002:1010], - 4001: _TokenTypeName[1010:1022], - 5000: _TokenTypeName[1022:1033], - 6000: _TokenTypeName[1033:1040], - 6001: _TokenTypeName[1040:1055], - 6002: _TokenTypeName[1055:1071], - 6003: _TokenTypeName[1071:1084], - 6004: _TokenTypeName[1084:1098], - 6100: _TokenTypeName[1098:1112], - 6101: _TokenTypeName[1112:1130], - 7000: _TokenTypeName[1130:1137], - 7001: _TokenTypeName[1137:1151], - 7002: _TokenTypeName[1151:1162], - 7003: _TokenTypeName[1162:1174], - 7004: _TokenTypeName[1174:1188], - 7005: _TokenTypeName[1188:1203], - 7006: _TokenTypeName[1203:1216], - 7007: _TokenTypeName[1216:1229], - 7008: _TokenTypeName[1229:1242], - 7009: _TokenTypeName[1242:1259], - 7010: _TokenTypeName[1259:1275], - 7011: _TokenTypeName[1275:1291], - 8000: _TokenTypeName[1291:1295], - 8001: _TokenTypeName[1295:1309], - 8002: _TokenTypeName[1309:1319], - 8003: _TokenTypeName[1319:1334], -} - -func (i TokenType) String() string { - if str, ok := _TokenTypeMap[i]; ok { - return str - } - return fmt.Sprintf("TokenType(%d)", i) -} - -// An "invalid array index" compiler error signifies that the constant values have changed. -// Re-run the stringer command to generate them again. -func _TokenTypeNoOp() { - var x [1]struct{} - _ = x[None-(-13)] - _ = x[Other-(-12)] - _ = x[Error-(-11)] - _ = x[CodeLine-(-10)] - _ = x[LineLink-(-9)] - _ = x[LineTableTD-(-8)] - _ = x[LineTable-(-7)] - _ = x[LineHighlight-(-6)] - _ = x[LineNumbersTable-(-5)] - _ = x[LineNumbers-(-4)] - _ = x[Line-(-3)] - _ = x[PreWrapper-(-2)] - _ = x[Background-(-1)] - _ = x[EOFType-(0)] - _ = x[Keyword-(1000)] - _ = x[KeywordConstant-(1001)] - _ = x[KeywordDeclaration-(1002)] - _ = x[KeywordNamespace-(1003)] - _ = x[KeywordPseudo-(1004)] - _ = x[KeywordReserved-(1005)] - _ = x[KeywordType-(1006)] - _ = x[Name-(2000)] - _ = x[NameAttribute-(2001)] - _ = x[NameBuiltin-(2002)] - _ = x[NameBuiltinPseudo-(2003)] - _ = x[NameClass-(2004)] - _ = x[NameConstant-(2005)] - _ = x[NameDecorator-(2006)] - _ = x[NameEntity-(2007)] - _ = x[NameException-(2008)] - _ = x[NameFunction-(2009)] - _ = x[NameFunctionMagic-(2010)] - _ = x[NameKeyword-(2011)] - _ = x[NameLabel-(2012)] - _ = x[NameNamespace-(2013)] - _ = x[NameOperator-(2014)] - _ = x[NameOther-(2015)] - _ = x[NamePseudo-(2016)] - _ = x[NameProperty-(2017)] - _ = x[NameTag-(2018)] - _ = x[NameVariable-(2019)] - _ = x[NameVariableAnonymous-(2020)] - _ = x[NameVariableClass-(2021)] - _ = x[NameVariableGlobal-(2022)] - _ = x[NameVariableInstance-(2023)] - _ = x[NameVariableMagic-(2024)] - _ = x[Literal-(3000)] - _ = x[LiteralDate-(3001)] - _ = x[LiteralOther-(3002)] - _ = x[LiteralString-(3100)] - _ = x[LiteralStringAffix-(3101)] - _ = x[LiteralStringAtom-(3102)] - _ = x[LiteralStringBacktick-(3103)] - _ = x[LiteralStringBoolean-(3104)] - _ = x[LiteralStringChar-(3105)] - _ = x[LiteralStringDelimiter-(3106)] - _ = x[LiteralStringDoc-(3107)] - _ = x[LiteralStringDouble-(3108)] - _ = x[LiteralStringEscape-(3109)] - _ = x[LiteralStringHeredoc-(3110)] - _ = x[LiteralStringInterpol-(3111)] - _ = x[LiteralStringName-(3112)] - _ = x[LiteralStringOther-(3113)] - _ = x[LiteralStringRegex-(3114)] - _ = x[LiteralStringSingle-(3115)] - _ = x[LiteralStringSymbol-(3116)] - _ = x[LiteralNumber-(3200)] - _ = x[LiteralNumberBin-(3201)] - _ = x[LiteralNumberFloat-(3202)] - _ = x[LiteralNumberHex-(3203)] - _ = x[LiteralNumberInteger-(3204)] - _ = x[LiteralNumberIntegerLong-(3205)] - _ = x[LiteralNumberOct-(3206)] - _ = x[Operator-(4000)] - _ = x[OperatorWord-(4001)] - _ = x[Punctuation-(5000)] - _ = x[Comment-(6000)] - _ = x[CommentHashbang-(6001)] - _ = x[CommentMultiline-(6002)] - _ = x[CommentSingle-(6003)] - _ = x[CommentSpecial-(6004)] - _ = x[CommentPreproc-(6100)] - _ = x[CommentPreprocFile-(6101)] - _ = x[Generic-(7000)] - _ = x[GenericDeleted-(7001)] - _ = x[GenericEmph-(7002)] - _ = x[GenericError-(7003)] - _ = x[GenericHeading-(7004)] - _ = x[GenericInserted-(7005)] - _ = x[GenericOutput-(7006)] - _ = x[GenericPrompt-(7007)] - _ = x[GenericStrong-(7008)] - _ = x[GenericSubheading-(7009)] - _ = x[GenericTraceback-(7010)] - _ = x[GenericUnderline-(7011)] - _ = x[Text-(8000)] - _ = x[TextWhitespace-(8001)] - _ = x[TextSymbol-(8002)] - _ = x[TextPunctuation-(8003)] -} - -var _TokenTypeValues = []TokenType{None, Other, Error, CodeLine, LineLink, LineTableTD, LineTable, LineHighlight, LineNumbersTable, LineNumbers, Line, PreWrapper, Background, EOFType, Keyword, KeywordConstant, KeywordDeclaration, KeywordNamespace, KeywordPseudo, KeywordReserved, KeywordType, Name, NameAttribute, NameBuiltin, NameBuiltinPseudo, NameClass, NameConstant, NameDecorator, NameEntity, NameException, NameFunction, NameFunctionMagic, NameKeyword, NameLabel, NameNamespace, NameOperator, NameOther, NamePseudo, NameProperty, NameTag, NameVariable, NameVariableAnonymous, NameVariableClass, NameVariableGlobal, NameVariableInstance, NameVariableMagic, Literal, LiteralDate, LiteralOther, LiteralString, LiteralStringAffix, LiteralStringAtom, LiteralStringBacktick, LiteralStringBoolean, LiteralStringChar, LiteralStringDelimiter, LiteralStringDoc, LiteralStringDouble, LiteralStringEscape, LiteralStringHeredoc, LiteralStringInterpol, LiteralStringName, LiteralStringOther, LiteralStringRegex, LiteralStringSingle, LiteralStringSymbol, LiteralNumber, LiteralNumberBin, LiteralNumberFloat, LiteralNumberHex, LiteralNumberInteger, LiteralNumberIntegerLong, LiteralNumberOct, Operator, OperatorWord, Punctuation, Comment, CommentHashbang, CommentMultiline, CommentSingle, CommentSpecial, CommentPreproc, CommentPreprocFile, Generic, GenericDeleted, GenericEmph, GenericError, GenericHeading, GenericInserted, GenericOutput, GenericPrompt, GenericStrong, GenericSubheading, GenericTraceback, GenericUnderline, Text, TextWhitespace, TextSymbol, TextPunctuation} - -var _TokenTypeNameToValueMap = map[string]TokenType{ - _TokenTypeName[0:4]: None, - _TokenTypeLowerName[0:4]: None, - _TokenTypeName[4:9]: Other, - _TokenTypeLowerName[4:9]: Other, - _TokenTypeName[9:14]: Error, - _TokenTypeLowerName[9:14]: Error, - _TokenTypeName[14:22]: CodeLine, - _TokenTypeLowerName[14:22]: CodeLine, - _TokenTypeName[22:30]: LineLink, - _TokenTypeLowerName[22:30]: LineLink, - _TokenTypeName[30:41]: LineTableTD, - _TokenTypeLowerName[30:41]: LineTableTD, - _TokenTypeName[41:50]: LineTable, - _TokenTypeLowerName[41:50]: LineTable, - _TokenTypeName[50:63]: LineHighlight, - _TokenTypeLowerName[50:63]: LineHighlight, - _TokenTypeName[63:79]: LineNumbersTable, - _TokenTypeLowerName[63:79]: LineNumbersTable, - _TokenTypeName[79:90]: LineNumbers, - _TokenTypeLowerName[79:90]: LineNumbers, - _TokenTypeName[90:94]: Line, - _TokenTypeLowerName[90:94]: Line, - _TokenTypeName[94:104]: PreWrapper, - _TokenTypeLowerName[94:104]: PreWrapper, - _TokenTypeName[104:114]: Background, - _TokenTypeLowerName[104:114]: Background, - _TokenTypeName[114:121]: EOFType, - _TokenTypeLowerName[114:121]: EOFType, - _TokenTypeName[121:128]: Keyword, - _TokenTypeLowerName[121:128]: Keyword, - _TokenTypeName[128:143]: KeywordConstant, - _TokenTypeLowerName[128:143]: KeywordConstant, - _TokenTypeName[143:161]: KeywordDeclaration, - _TokenTypeLowerName[143:161]: KeywordDeclaration, - _TokenTypeName[161:177]: KeywordNamespace, - _TokenTypeLowerName[161:177]: KeywordNamespace, - _TokenTypeName[177:190]: KeywordPseudo, - _TokenTypeLowerName[177:190]: KeywordPseudo, - _TokenTypeName[190:205]: KeywordReserved, - _TokenTypeLowerName[190:205]: KeywordReserved, - _TokenTypeName[205:216]: KeywordType, - _TokenTypeLowerName[205:216]: KeywordType, - _TokenTypeName[216:220]: Name, - _TokenTypeLowerName[216:220]: Name, - _TokenTypeName[220:233]: NameAttribute, - _TokenTypeLowerName[220:233]: NameAttribute, - _TokenTypeName[233:244]: NameBuiltin, - _TokenTypeLowerName[233:244]: NameBuiltin, - _TokenTypeName[244:261]: NameBuiltinPseudo, - _TokenTypeLowerName[244:261]: NameBuiltinPseudo, - _TokenTypeName[261:270]: NameClass, - _TokenTypeLowerName[261:270]: NameClass, - _TokenTypeName[270:282]: NameConstant, - _TokenTypeLowerName[270:282]: NameConstant, - _TokenTypeName[282:295]: NameDecorator, - _TokenTypeLowerName[282:295]: NameDecorator, - _TokenTypeName[295:305]: NameEntity, - _TokenTypeLowerName[295:305]: NameEntity, - _TokenTypeName[305:318]: NameException, - _TokenTypeLowerName[305:318]: NameException, - _TokenTypeName[318:330]: NameFunction, - _TokenTypeLowerName[318:330]: NameFunction, - _TokenTypeName[330:347]: NameFunctionMagic, - _TokenTypeLowerName[330:347]: NameFunctionMagic, - _TokenTypeName[347:358]: NameKeyword, - _TokenTypeLowerName[347:358]: NameKeyword, - _TokenTypeName[358:367]: NameLabel, - _TokenTypeLowerName[358:367]: NameLabel, - _TokenTypeName[367:380]: NameNamespace, - _TokenTypeLowerName[367:380]: NameNamespace, - _TokenTypeName[380:392]: NameOperator, - _TokenTypeLowerName[380:392]: NameOperator, - _TokenTypeName[392:401]: NameOther, - _TokenTypeLowerName[392:401]: NameOther, - _TokenTypeName[401:411]: NamePseudo, - _TokenTypeLowerName[401:411]: NamePseudo, - _TokenTypeName[411:423]: NameProperty, - _TokenTypeLowerName[411:423]: NameProperty, - _TokenTypeName[423:430]: NameTag, - _TokenTypeLowerName[423:430]: NameTag, - _TokenTypeName[430:442]: NameVariable, - _TokenTypeLowerName[430:442]: NameVariable, - _TokenTypeName[442:463]: NameVariableAnonymous, - _TokenTypeLowerName[442:463]: NameVariableAnonymous, - _TokenTypeName[463:480]: NameVariableClass, - _TokenTypeLowerName[463:480]: NameVariableClass, - _TokenTypeName[480:498]: NameVariableGlobal, - _TokenTypeLowerName[480:498]: NameVariableGlobal, - _TokenTypeName[498:518]: NameVariableInstance, - _TokenTypeLowerName[498:518]: NameVariableInstance, - _TokenTypeName[518:535]: NameVariableMagic, - _TokenTypeLowerName[518:535]: NameVariableMagic, - _TokenTypeName[535:542]: Literal, - _TokenTypeLowerName[535:542]: Literal, - _TokenTypeName[542:553]: LiteralDate, - _TokenTypeLowerName[542:553]: LiteralDate, - _TokenTypeName[553:565]: LiteralOther, - _TokenTypeLowerName[553:565]: LiteralOther, - _TokenTypeName[565:578]: LiteralString, - _TokenTypeLowerName[565:578]: LiteralString, - _TokenTypeName[578:596]: LiteralStringAffix, - _TokenTypeLowerName[578:596]: LiteralStringAffix, - _TokenTypeName[596:613]: LiteralStringAtom, - _TokenTypeLowerName[596:613]: LiteralStringAtom, - _TokenTypeName[613:634]: LiteralStringBacktick, - _TokenTypeLowerName[613:634]: LiteralStringBacktick, - _TokenTypeName[634:654]: LiteralStringBoolean, - _TokenTypeLowerName[634:654]: LiteralStringBoolean, - _TokenTypeName[654:671]: LiteralStringChar, - _TokenTypeLowerName[654:671]: LiteralStringChar, - _TokenTypeName[671:693]: LiteralStringDelimiter, - _TokenTypeLowerName[671:693]: LiteralStringDelimiter, - _TokenTypeName[693:709]: LiteralStringDoc, - _TokenTypeLowerName[693:709]: LiteralStringDoc, - _TokenTypeName[709:728]: LiteralStringDouble, - _TokenTypeLowerName[709:728]: LiteralStringDouble, - _TokenTypeName[728:747]: LiteralStringEscape, - _TokenTypeLowerName[728:747]: LiteralStringEscape, - _TokenTypeName[747:767]: LiteralStringHeredoc, - _TokenTypeLowerName[747:767]: LiteralStringHeredoc, - _TokenTypeName[767:788]: LiteralStringInterpol, - _TokenTypeLowerName[767:788]: LiteralStringInterpol, - _TokenTypeName[788:805]: LiteralStringName, - _TokenTypeLowerName[788:805]: LiteralStringName, - _TokenTypeName[805:823]: LiteralStringOther, - _TokenTypeLowerName[805:823]: LiteralStringOther, - _TokenTypeName[823:841]: LiteralStringRegex, - _TokenTypeLowerName[823:841]: LiteralStringRegex, - _TokenTypeName[841:860]: LiteralStringSingle, - _TokenTypeLowerName[841:860]: LiteralStringSingle, - _TokenTypeName[860:879]: LiteralStringSymbol, - _TokenTypeLowerName[860:879]: LiteralStringSymbol, - _TokenTypeName[879:892]: LiteralNumber, - _TokenTypeLowerName[879:892]: LiteralNumber, - _TokenTypeName[892:908]: LiteralNumberBin, - _TokenTypeLowerName[892:908]: LiteralNumberBin, - _TokenTypeName[908:926]: LiteralNumberFloat, - _TokenTypeLowerName[908:926]: LiteralNumberFloat, - _TokenTypeName[926:942]: LiteralNumberHex, - _TokenTypeLowerName[926:942]: LiteralNumberHex, - _TokenTypeName[942:962]: LiteralNumberInteger, - _TokenTypeLowerName[942:962]: LiteralNumberInteger, - _TokenTypeName[962:986]: LiteralNumberIntegerLong, - _TokenTypeLowerName[962:986]: LiteralNumberIntegerLong, - _TokenTypeName[986:1002]: LiteralNumberOct, - _TokenTypeLowerName[986:1002]: LiteralNumberOct, - _TokenTypeName[1002:1010]: Operator, - _TokenTypeLowerName[1002:1010]: Operator, - _TokenTypeName[1010:1022]: OperatorWord, - _TokenTypeLowerName[1010:1022]: OperatorWord, - _TokenTypeName[1022:1033]: Punctuation, - _TokenTypeLowerName[1022:1033]: Punctuation, - _TokenTypeName[1033:1040]: Comment, - _TokenTypeLowerName[1033:1040]: Comment, - _TokenTypeName[1040:1055]: CommentHashbang, - _TokenTypeLowerName[1040:1055]: CommentHashbang, - _TokenTypeName[1055:1071]: CommentMultiline, - _TokenTypeLowerName[1055:1071]: CommentMultiline, - _TokenTypeName[1071:1084]: CommentSingle, - _TokenTypeLowerName[1071:1084]: CommentSingle, - _TokenTypeName[1084:1098]: CommentSpecial, - _TokenTypeLowerName[1084:1098]: CommentSpecial, - _TokenTypeName[1098:1112]: CommentPreproc, - _TokenTypeLowerName[1098:1112]: CommentPreproc, - _TokenTypeName[1112:1130]: CommentPreprocFile, - _TokenTypeLowerName[1112:1130]: CommentPreprocFile, - _TokenTypeName[1130:1137]: Generic, - _TokenTypeLowerName[1130:1137]: Generic, - _TokenTypeName[1137:1151]: GenericDeleted, - _TokenTypeLowerName[1137:1151]: GenericDeleted, - _TokenTypeName[1151:1162]: GenericEmph, - _TokenTypeLowerName[1151:1162]: GenericEmph, - _TokenTypeName[1162:1174]: GenericError, - _TokenTypeLowerName[1162:1174]: GenericError, - _TokenTypeName[1174:1188]: GenericHeading, - _TokenTypeLowerName[1174:1188]: GenericHeading, - _TokenTypeName[1188:1203]: GenericInserted, - _TokenTypeLowerName[1188:1203]: GenericInserted, - _TokenTypeName[1203:1216]: GenericOutput, - _TokenTypeLowerName[1203:1216]: GenericOutput, - _TokenTypeName[1216:1229]: GenericPrompt, - _TokenTypeLowerName[1216:1229]: GenericPrompt, - _TokenTypeName[1229:1242]: GenericStrong, - _TokenTypeLowerName[1229:1242]: GenericStrong, - _TokenTypeName[1242:1259]: GenericSubheading, - _TokenTypeLowerName[1242:1259]: GenericSubheading, - _TokenTypeName[1259:1275]: GenericTraceback, - _TokenTypeLowerName[1259:1275]: GenericTraceback, - _TokenTypeName[1275:1291]: GenericUnderline, - _TokenTypeLowerName[1275:1291]: GenericUnderline, - _TokenTypeName[1291:1295]: Text, - _TokenTypeLowerName[1291:1295]: Text, - _TokenTypeName[1295:1309]: TextWhitespace, - _TokenTypeLowerName[1295:1309]: TextWhitespace, - _TokenTypeName[1309:1319]: TextSymbol, - _TokenTypeLowerName[1309:1319]: TextSymbol, - _TokenTypeName[1319:1334]: TextPunctuation, - _TokenTypeLowerName[1319:1334]: TextPunctuation, -} - -var _TokenTypeNames = []string{ - _TokenTypeName[0:4], - _TokenTypeName[4:9], - _TokenTypeName[9:14], - _TokenTypeName[14:22], - _TokenTypeName[22:30], - _TokenTypeName[30:41], - _TokenTypeName[41:50], - _TokenTypeName[50:63], - _TokenTypeName[63:79], - _TokenTypeName[79:90], - _TokenTypeName[90:94], - _TokenTypeName[94:104], - _TokenTypeName[104:114], - _TokenTypeName[114:121], - _TokenTypeName[121:128], - _TokenTypeName[128:143], - _TokenTypeName[143:161], - _TokenTypeName[161:177], - _TokenTypeName[177:190], - _TokenTypeName[190:205], - _TokenTypeName[205:216], - _TokenTypeName[216:220], - _TokenTypeName[220:233], - _TokenTypeName[233:244], - _TokenTypeName[244:261], - _TokenTypeName[261:270], - _TokenTypeName[270:282], - _TokenTypeName[282:295], - _TokenTypeName[295:305], - _TokenTypeName[305:318], - _TokenTypeName[318:330], - _TokenTypeName[330:347], - _TokenTypeName[347:358], - _TokenTypeName[358:367], - _TokenTypeName[367:380], - _TokenTypeName[380:392], - _TokenTypeName[392:401], - _TokenTypeName[401:411], - _TokenTypeName[411:423], - _TokenTypeName[423:430], - _TokenTypeName[430:442], - _TokenTypeName[442:463], - _TokenTypeName[463:480], - _TokenTypeName[480:498], - _TokenTypeName[498:518], - _TokenTypeName[518:535], - _TokenTypeName[535:542], - _TokenTypeName[542:553], - _TokenTypeName[553:565], - _TokenTypeName[565:578], - _TokenTypeName[578:596], - _TokenTypeName[596:613], - _TokenTypeName[613:634], - _TokenTypeName[634:654], - _TokenTypeName[654:671], - _TokenTypeName[671:693], - _TokenTypeName[693:709], - _TokenTypeName[709:728], - _TokenTypeName[728:747], - _TokenTypeName[747:767], - _TokenTypeName[767:788], - _TokenTypeName[788:805], - _TokenTypeName[805:823], - _TokenTypeName[823:841], - _TokenTypeName[841:860], - _TokenTypeName[860:879], - _TokenTypeName[879:892], - _TokenTypeName[892:908], - _TokenTypeName[908:926], - _TokenTypeName[926:942], - _TokenTypeName[942:962], - _TokenTypeName[962:986], - _TokenTypeName[986:1002], - _TokenTypeName[1002:1010], - _TokenTypeName[1010:1022], - _TokenTypeName[1022:1033], - _TokenTypeName[1033:1040], - _TokenTypeName[1040:1055], - _TokenTypeName[1055:1071], - _TokenTypeName[1071:1084], - _TokenTypeName[1084:1098], - _TokenTypeName[1098:1112], - _TokenTypeName[1112:1130], - _TokenTypeName[1130:1137], - _TokenTypeName[1137:1151], - _TokenTypeName[1151:1162], - _TokenTypeName[1162:1174], - _TokenTypeName[1174:1188], - _TokenTypeName[1188:1203], - _TokenTypeName[1203:1216], - _TokenTypeName[1216:1229], - _TokenTypeName[1229:1242], - _TokenTypeName[1242:1259], - _TokenTypeName[1259:1275], - _TokenTypeName[1275:1291], - _TokenTypeName[1291:1295], - _TokenTypeName[1295:1309], - _TokenTypeName[1309:1319], - _TokenTypeName[1319:1334], -} - -// TokenTypeString retrieves an enum value from the enum constants string name. -// Throws an error if the param is not part of the enum. -func TokenTypeString(s string) (TokenType, error) { - if val, ok := _TokenTypeNameToValueMap[s]; ok { - return val, nil - } - - if val, ok := _TokenTypeNameToValueMap[strings.ToLower(s)]; ok { - return val, nil - } - return 0, fmt.Errorf("%s does not belong to TokenType values", s) -} - -// TokenTypeValues returns all values of the enum -func TokenTypeValues() []TokenType { - return _TokenTypeValues -} - -// TokenTypeStrings returns a slice of all String values of the enum -func TokenTypeStrings() []string { - strs := make([]string, len(_TokenTypeNames)) - copy(strs, _TokenTypeNames) - return strs -} - -// IsATokenType returns "true" if the value is listed in the enum definition. "false" otherwise -func (i TokenType) IsATokenType() bool { - _, ok := _TokenTypeMap[i] - return ok -} - -// MarshalText implements the encoding.TextMarshaler interface for TokenType -func (i TokenType) MarshalText() ([]byte, error) { - return []byte(i.String()), nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface for TokenType -func (i *TokenType) UnmarshalText(text []byte) error { - var err error - *i, err = TokenTypeString(string(text)) - return err -} diff --git a/vendor/github.com/alecthomas/chroma/v2/types.go b/vendor/github.com/alecthomas/chroma/v2/types.go deleted file mode 100644 index 3d12310a..00000000 --- a/vendor/github.com/alecthomas/chroma/v2/types.go +++ /dev/null @@ -1,340 +0,0 @@ -package chroma - -//go:generate enumer -text -type TokenType - -// TokenType is the type of token to highlight. -// -// It is also an Emitter, emitting a single token of itself -type TokenType int - -// Set of TokenTypes. -// -// Categories of types are grouped in ranges of 1000, while sub-categories are in ranges of 100. For -// example, the literal category is in the range 3000-3999. The sub-category for literal strings is -// in the range 3100-3199. - -// Meta token types. -const ( - // Default background style. - Background TokenType = -1 - iota - // PreWrapper style. - PreWrapper - // Line style. - Line - // Line numbers in output. - LineNumbers - // Line numbers in output when in table. - LineNumbersTable - // Line higlight style. - LineHighlight - // Line numbers table wrapper style. - LineTable - // Line numbers table TD wrapper style. - LineTableTD - // Line number links. - LineLink - // Code line wrapper style. - CodeLine - // Input that could not be tokenised. - Error - // Other is used by the Delegate lexer to indicate which tokens should be handled by the delegate. - Other - // No highlighting. - None - // Used as an EOF marker / nil token - EOFType TokenType = 0 -) - -// Keywords. -const ( - Keyword TokenType = 1000 + iota - KeywordConstant - KeywordDeclaration - KeywordNamespace - KeywordPseudo - KeywordReserved - KeywordType -) - -// Names. -const ( - Name TokenType = 2000 + iota - NameAttribute - NameBuiltin - NameBuiltinPseudo - NameClass - NameConstant - NameDecorator - NameEntity - NameException - NameFunction - NameFunctionMagic - NameKeyword - NameLabel - NameNamespace - NameOperator - NameOther - NamePseudo - NameProperty - NameTag - NameVariable - NameVariableAnonymous - NameVariableClass - NameVariableGlobal - NameVariableInstance - NameVariableMagic -) - -// Literals. -const ( - Literal TokenType = 3000 + iota - LiteralDate - LiteralOther -) - -// Strings. -const ( - LiteralString TokenType = 3100 + iota - LiteralStringAffix - LiteralStringAtom - LiteralStringBacktick - LiteralStringBoolean - LiteralStringChar - LiteralStringDelimiter - LiteralStringDoc - LiteralStringDouble - LiteralStringEscape - LiteralStringHeredoc - LiteralStringInterpol - LiteralStringName - LiteralStringOther - LiteralStringRegex - LiteralStringSingle - LiteralStringSymbol -) - -// Literals. -const ( - LiteralNumber TokenType = 3200 + iota - LiteralNumberBin - LiteralNumberFloat - LiteralNumberHex - LiteralNumberInteger - LiteralNumberIntegerLong - LiteralNumberOct -) - -// Operators. -const ( - Operator TokenType = 4000 + iota - OperatorWord -) - -// Punctuation. -const ( - Punctuation TokenType = 5000 + iota -) - -// Comments. -const ( - Comment TokenType = 6000 + iota - CommentHashbang - CommentMultiline - CommentSingle - CommentSpecial -) - -// Preprocessor "comments". -const ( - CommentPreproc TokenType = 6100 + iota - CommentPreprocFile -) - -// Generic tokens. -const ( - Generic TokenType = 7000 + iota - GenericDeleted - GenericEmph - GenericError - GenericHeading - GenericInserted - GenericOutput - GenericPrompt - GenericStrong - GenericSubheading - GenericTraceback - GenericUnderline -) - -// Text. -const ( - Text TokenType = 8000 + iota - TextWhitespace - TextSymbol - TextPunctuation -) - -// Aliases. -const ( - Whitespace = TextWhitespace - - Date = LiteralDate - - String = LiteralString - StringAffix = LiteralStringAffix - StringBacktick = LiteralStringBacktick - StringChar = LiteralStringChar - StringDelimiter = LiteralStringDelimiter - StringDoc = LiteralStringDoc - StringDouble = LiteralStringDouble - StringEscape = LiteralStringEscape - StringHeredoc = LiteralStringHeredoc - StringInterpol = LiteralStringInterpol - StringOther = LiteralStringOther - StringRegex = LiteralStringRegex - StringSingle = LiteralStringSingle - StringSymbol = LiteralStringSymbol - - Number = LiteralNumber - NumberBin = LiteralNumberBin - NumberFloat = LiteralNumberFloat - NumberHex = LiteralNumberHex - NumberInteger = LiteralNumberInteger - NumberIntegerLong = LiteralNumberIntegerLong - NumberOct = LiteralNumberOct -) - -var ( - StandardTypes = map[TokenType]string{ - Background: "bg", - PreWrapper: "chroma", - Line: "line", - LineNumbers: "ln", - LineNumbersTable: "lnt", - LineHighlight: "hl", - LineTable: "lntable", - LineTableTD: "lntd", - LineLink: "lnlinks", - CodeLine: "cl", - Text: "", - Whitespace: "w", - Error: "err", - Other: "x", - // I have no idea what this is used for... - // Escape: "esc", - - Keyword: "k", - KeywordConstant: "kc", - KeywordDeclaration: "kd", - KeywordNamespace: "kn", - KeywordPseudo: "kp", - KeywordReserved: "kr", - KeywordType: "kt", - - Name: "n", - NameAttribute: "na", - NameBuiltin: "nb", - NameBuiltinPseudo: "bp", - NameClass: "nc", - NameConstant: "no", - NameDecorator: "nd", - NameEntity: "ni", - NameException: "ne", - NameFunction: "nf", - NameFunctionMagic: "fm", - NameProperty: "py", - NameLabel: "nl", - NameNamespace: "nn", - NameOther: "nx", - NameTag: "nt", - NameVariable: "nv", - NameVariableClass: "vc", - NameVariableGlobal: "vg", - NameVariableInstance: "vi", - NameVariableMagic: "vm", - - Literal: "l", - LiteralDate: "ld", - - String: "s", - StringAffix: "sa", - StringBacktick: "sb", - StringChar: "sc", - StringDelimiter: "dl", - StringDoc: "sd", - StringDouble: "s2", - StringEscape: "se", - StringHeredoc: "sh", - StringInterpol: "si", - StringOther: "sx", - StringRegex: "sr", - StringSingle: "s1", - StringSymbol: "ss", - - Number: "m", - NumberBin: "mb", - NumberFloat: "mf", - NumberHex: "mh", - NumberInteger: "mi", - NumberIntegerLong: "il", - NumberOct: "mo", - - Operator: "o", - OperatorWord: "ow", - - Punctuation: "p", - - Comment: "c", - CommentHashbang: "ch", - CommentMultiline: "cm", - CommentPreproc: "cp", - CommentPreprocFile: "cpf", - CommentSingle: "c1", - CommentSpecial: "cs", - - Generic: "g", - GenericDeleted: "gd", - GenericEmph: "ge", - GenericError: "gr", - GenericHeading: "gh", - GenericInserted: "gi", - GenericOutput: "go", - GenericPrompt: "gp", - GenericStrong: "gs", - GenericSubheading: "gu", - GenericTraceback: "gt", - GenericUnderline: "gl", - } -) - -func (t TokenType) Parent() TokenType { - if t%100 != 0 { - return t / 100 * 100 - } - if t%1000 != 0 { - return t / 1000 * 1000 - } - return 0 -} - -func (t TokenType) Category() TokenType { - return t / 1000 * 1000 -} - -func (t TokenType) SubCategory() TokenType { - return t / 100 * 100 -} - -func (t TokenType) InCategory(other TokenType) bool { - return t/1000 == other/1000 -} - -func (t TokenType) InSubCategory(other TokenType) bool { - return t/100 == other/100 -} - -func (t TokenType) Emit(groups []string, _ *LexerState) Iterator { - return Literator(Token{Type: t, Value: groups[0]}) -} - -func (t TokenType) EmitterKind() string { return "token" } diff --git a/vendor/github.com/atotto/clipboard/.travis.yml b/vendor/github.com/atotto/clipboard/.travis.yml deleted file mode 100644 index 23f21d83..00000000 --- a/vendor/github.com/atotto/clipboard/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: go - -os: - - linux - - osx - - windows - -go: - - go1.13.x - - go1.x - -services: - - xvfb - -before_install: - - export DISPLAY=:99.0 - -script: - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xsel; fi - - go test -v . - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xclip; fi - - go test -v . diff --git a/vendor/github.com/atotto/clipboard/LICENSE b/vendor/github.com/atotto/clipboard/LICENSE deleted file mode 100644 index dee3257b..00000000 --- a/vendor/github.com/atotto/clipboard/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2013 Ato Araki. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of @atotto. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/atotto/clipboard/README.md b/vendor/github.com/atotto/clipboard/README.md deleted file mode 100644 index 41fdd57b..00000000 --- a/vendor/github.com/atotto/clipboard/README.md +++ /dev/null @@ -1,48 +0,0 @@ -[![Build Status](https://travis-ci.org/atotto/clipboard.svg?branch=master)](https://travis-ci.org/atotto/clipboard) - -[![GoDoc](https://godoc.org/github.com/atotto/clipboard?status.svg)](http://godoc.org/github.com/atotto/clipboard) - -# Clipboard for Go - -Provide copying and pasting to the Clipboard for Go. - -Build: - - $ go get github.com/atotto/clipboard - -Platforms: - -* OSX -* Windows 7 (probably work on other Windows) -* Linux, Unix (requires 'xclip' or 'xsel' command to be installed) - - -Document: - -* http://godoc.org/github.com/atotto/clipboard - -Notes: - -* Text string only -* UTF-8 text encoding only (no conversion) - -TODO: - -* Clipboard watcher(?) - -## Commands: - -paste shell command: - - $ go get github.com/atotto/clipboard/cmd/gopaste - $ # example: - $ gopaste > document.txt - -copy shell command: - - $ go get github.com/atotto/clipboard/cmd/gocopy - $ # example: - $ cat document.txt | gocopy - - - diff --git a/vendor/github.com/atotto/clipboard/clipboard.go b/vendor/github.com/atotto/clipboard/clipboard.go deleted file mode 100644 index d7907d3a..00000000 --- a/vendor/github.com/atotto/clipboard/clipboard.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 @atotto. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package clipboard read/write on clipboard -package clipboard - -// ReadAll read string from clipboard -func ReadAll() (string, error) { - return readAll() -} - -// WriteAll write string to clipboard -func WriteAll(text string) error { - return writeAll(text) -} - -// Unsupported might be set true during clipboard init, to help callers decide -// whether or not to offer clipboard options. -var Unsupported bool diff --git a/vendor/github.com/atotto/clipboard/clipboard_darwin.go b/vendor/github.com/atotto/clipboard/clipboard_darwin.go deleted file mode 100644 index 6f33078d..00000000 --- a/vendor/github.com/atotto/clipboard/clipboard_darwin.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2013 @atotto. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin - -package clipboard - -import ( - "os/exec" -) - -var ( - pasteCmdArgs = "pbpaste" - copyCmdArgs = "pbcopy" -) - -func getPasteCommand() *exec.Cmd { - return exec.Command(pasteCmdArgs) -} - -func getCopyCommand() *exec.Cmd { - return exec.Command(copyCmdArgs) -} - -func readAll() (string, error) { - pasteCmd := getPasteCommand() - out, err := pasteCmd.Output() - if err != nil { - return "", err - } - return string(out), nil -} - -func writeAll(text string) error { - copyCmd := getCopyCommand() - in, err := copyCmd.StdinPipe() - if err != nil { - return err - } - - if err := copyCmd.Start(); err != nil { - return err - } - if _, err := in.Write([]byte(text)); err != nil { - return err - } - if err := in.Close(); err != nil { - return err - } - return copyCmd.Wait() -} diff --git a/vendor/github.com/atotto/clipboard/clipboard_plan9.go b/vendor/github.com/atotto/clipboard/clipboard_plan9.go deleted file mode 100644 index 9d2fef4e..00000000 --- a/vendor/github.com/atotto/clipboard/clipboard_plan9.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2013 @atotto. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build plan9 - -package clipboard - -import ( - "os" - "io/ioutil" -) - -func readAll() (string, error) { - f, err := os.Open("/dev/snarf") - if err != nil { - return "", err - } - defer f.Close() - - str, err := ioutil.ReadAll(f) - if err != nil { - return "", err - } - - return string(str), nil -} - -func writeAll(text string) error { - f, err := os.OpenFile("/dev/snarf", os.O_WRONLY, 0666) - if err != nil { - return err - } - defer f.Close() - - _, err = f.Write([]byte(text)) - if err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/atotto/clipboard/clipboard_unix.go b/vendor/github.com/atotto/clipboard/clipboard_unix.go deleted file mode 100644 index d9f6a561..00000000 --- a/vendor/github.com/atotto/clipboard/clipboard_unix.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2013 @atotto. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build freebsd linux netbsd openbsd solaris dragonfly - -package clipboard - -import ( - "errors" - "os" - "os/exec" -) - -const ( - xsel = "xsel" - xclip = "xclip" - powershellExe = "powershell.exe" - clipExe = "clip.exe" - wlcopy = "wl-copy" - wlpaste = "wl-paste" - termuxClipboardGet = "termux-clipboard-get" - termuxClipboardSet = "termux-clipboard-set" -) - -var ( - Primary bool - trimDos bool - - pasteCmdArgs []string - copyCmdArgs []string - - xselPasteArgs = []string{xsel, "--output", "--clipboard"} - xselCopyArgs = []string{xsel, "--input", "--clipboard"} - - xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"} - xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"} - - powershellExePasteArgs = []string{powershellExe, "Get-Clipboard"} - clipExeCopyArgs = []string{clipExe} - - wlpasteArgs = []string{wlpaste, "--no-newline"} - wlcopyArgs = []string{wlcopy} - - termuxPasteArgs = []string{termuxClipboardGet} - termuxCopyArgs = []string{termuxClipboardSet} - - missingCommands = errors.New("No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.") -) - -func init() { - if os.Getenv("WAYLAND_DISPLAY") != "" { - pasteCmdArgs = wlpasteArgs - copyCmdArgs = wlcopyArgs - - if _, err := exec.LookPath(wlcopy); err == nil { - if _, err := exec.LookPath(wlpaste); err == nil { - return - } - } - } - - pasteCmdArgs = xclipPasteArgs - copyCmdArgs = xclipCopyArgs - - if _, err := exec.LookPath(xclip); err == nil { - return - } - - pasteCmdArgs = xselPasteArgs - copyCmdArgs = xselCopyArgs - - if _, err := exec.LookPath(xsel); err == nil { - return - } - - pasteCmdArgs = termuxPasteArgs - copyCmdArgs = termuxCopyArgs - - if _, err := exec.LookPath(termuxClipboardSet); err == nil { - if _, err := exec.LookPath(termuxClipboardGet); err == nil { - return - } - } - - pasteCmdArgs = powershellExePasteArgs - copyCmdArgs = clipExeCopyArgs - trimDos = true - - if _, err := exec.LookPath(clipExe); err == nil { - if _, err := exec.LookPath(powershellExe); err == nil { - return - } - } - - Unsupported = true -} - -func getPasteCommand() *exec.Cmd { - if Primary { - pasteCmdArgs = pasteCmdArgs[:1] - } - return exec.Command(pasteCmdArgs[0], pasteCmdArgs[1:]...) -} - -func getCopyCommand() *exec.Cmd { - if Primary { - copyCmdArgs = copyCmdArgs[:1] - } - return exec.Command(copyCmdArgs[0], copyCmdArgs[1:]...) -} - -func readAll() (string, error) { - if Unsupported { - return "", missingCommands - } - pasteCmd := getPasteCommand() - out, err := pasteCmd.Output() - if err != nil { - return "", err - } - result := string(out) - if trimDos && len(result) > 1 { - result = result[:len(result)-2] - } - return result, nil -} - -func writeAll(text string) error { - if Unsupported { - return missingCommands - } - copyCmd := getCopyCommand() - in, err := copyCmd.StdinPipe() - if err != nil { - return err - } - - if err := copyCmd.Start(); err != nil { - return err - } - if _, err := in.Write([]byte(text)); err != nil { - return err - } - if err := in.Close(); err != nil { - return err - } - return copyCmd.Wait() -} diff --git a/vendor/github.com/atotto/clipboard/clipboard_windows.go b/vendor/github.com/atotto/clipboard/clipboard_windows.go deleted file mode 100644 index 253bb932..00000000 --- a/vendor/github.com/atotto/clipboard/clipboard_windows.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2013 @atotto. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -package clipboard - -import ( - "runtime" - "syscall" - "time" - "unsafe" -) - -const ( - cfUnicodetext = 13 - gmemMoveable = 0x0002 -) - -var ( - user32 = syscall.MustLoadDLL("user32") - isClipboardFormatAvailable = user32.MustFindProc("IsClipboardFormatAvailable") - openClipboard = user32.MustFindProc("OpenClipboard") - closeClipboard = user32.MustFindProc("CloseClipboard") - emptyClipboard = user32.MustFindProc("EmptyClipboard") - getClipboardData = user32.MustFindProc("GetClipboardData") - setClipboardData = user32.MustFindProc("SetClipboardData") - - kernel32 = syscall.NewLazyDLL("kernel32") - globalAlloc = kernel32.NewProc("GlobalAlloc") - globalFree = kernel32.NewProc("GlobalFree") - globalLock = kernel32.NewProc("GlobalLock") - globalUnlock = kernel32.NewProc("GlobalUnlock") - lstrcpy = kernel32.NewProc("lstrcpyW") -) - -// waitOpenClipboard opens the clipboard, waiting for up to a second to do so. -func waitOpenClipboard() error { - started := time.Now() - limit := started.Add(time.Second) - var r uintptr - var err error - for time.Now().Before(limit) { - r, _, err = openClipboard.Call(0) - if r != 0 { - return nil - } - time.Sleep(time.Millisecond) - } - return err -} - -func readAll() (string, error) { - // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). - // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. - runtime.LockOSThread() - defer runtime.UnlockOSThread() - if formatAvailable, _, err := isClipboardFormatAvailable.Call(cfUnicodetext); formatAvailable == 0 { - return "", err - } - err := waitOpenClipboard() - if err != nil { - return "", err - } - - h, _, err := getClipboardData.Call(cfUnicodetext) - if h == 0 { - _, _, _ = closeClipboard.Call() - return "", err - } - - l, _, err := globalLock.Call(h) - if l == 0 { - _, _, _ = closeClipboard.Call() - return "", err - } - - text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:]) - - r, _, err := globalUnlock.Call(h) - if r == 0 { - _, _, _ = closeClipboard.Call() - return "", err - } - - closed, _, err := closeClipboard.Call() - if closed == 0 { - return "", err - } - return text, nil -} - -func writeAll(text string) error { - // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). - // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - err := waitOpenClipboard() - if err != nil { - return err - } - - r, _, err := emptyClipboard.Call(0) - if r == 0 { - _, _, _ = closeClipboard.Call() - return err - } - - data := syscall.StringToUTF16(text) - - // "If the hMem parameter identifies a memory object, the object must have - // been allocated using the function with the GMEM_MOVEABLE flag." - h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0])))) - if h == 0 { - _, _, _ = closeClipboard.Call() - return err - } - defer func() { - if h != 0 { - globalFree.Call(h) - } - }() - - l, _, err := globalLock.Call(h) - if l == 0 { - _, _, _ = closeClipboard.Call() - return err - } - - r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) - if r == 0 { - _, _, _ = closeClipboard.Call() - return err - } - - r, _, err = globalUnlock.Call(h) - if r == 0 { - if err.(syscall.Errno) != 0 { - _, _, _ = closeClipboard.Call() - return err - } - } - - r, _, err = setClipboardData.Call(cfUnicodetext, h) - if r == 0 { - _, _, _ = closeClipboard.Call() - return err - } - h = 0 // suppress deferred cleanup - closed, _, err := closeClipboard.Call() - if closed == 0 { - return err - } - return nil -} diff --git a/vendor/github.com/aymerick/douceur/LICENSE b/vendor/github.com/aymerick/douceur/LICENSE deleted file mode 100644 index 6ce87cd3..00000000 --- a/vendor/github.com/aymerick/douceur/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Aymerick JEHANNE - -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/aymerick/douceur/css/declaration.go b/vendor/github.com/aymerick/douceur/css/declaration.go deleted file mode 100644 index 61d29d33..00000000 --- a/vendor/github.com/aymerick/douceur/css/declaration.go +++ /dev/null @@ -1,60 +0,0 @@ -package css - -import "fmt" - -// Declaration represents a parsed style property -type Declaration struct { - Property string - Value string - Important bool -} - -// NewDeclaration instanciates a new Declaration -func NewDeclaration() *Declaration { - return &Declaration{} -} - -// Returns string representation of the Declaration -func (decl *Declaration) String() string { - return decl.StringWithImportant(true) -} - -// StringWithImportant returns string representation with optional !important part -func (decl *Declaration) StringWithImportant(option bool) string { - result := fmt.Sprintf("%s: %s", decl.Property, decl.Value) - - if option && decl.Important { - result += " !important" - } - - result += ";" - - return result -} - -// Equal returns true if both Declarations are equals -func (decl *Declaration) Equal(other *Declaration) bool { - return (decl.Property == other.Property) && (decl.Value == other.Value) && (decl.Important == other.Important) -} - -// -// DeclarationsByProperty -// - -// DeclarationsByProperty represents sortable style declarations -type DeclarationsByProperty []*Declaration - -// Implements sort.Interface -func (declarations DeclarationsByProperty) Len() int { - return len(declarations) -} - -// Implements sort.Interface -func (declarations DeclarationsByProperty) Swap(i, j int) { - declarations[i], declarations[j] = declarations[j], declarations[i] -} - -// Implements sort.Interface -func (declarations DeclarationsByProperty) Less(i, j int) bool { - return declarations[i].Property < declarations[j].Property -} diff --git a/vendor/github.com/aymerick/douceur/css/rule.go b/vendor/github.com/aymerick/douceur/css/rule.go deleted file mode 100644 index b5a44b54..00000000 --- a/vendor/github.com/aymerick/douceur/css/rule.go +++ /dev/null @@ -1,230 +0,0 @@ -package css - -import ( - "fmt" - "strings" -) - -const ( - indentSpace = 2 -) - -// RuleKind represents a Rule kind -type RuleKind int - -// Rule kinds -const ( - QualifiedRule RuleKind = iota - AtRule -) - -// At Rules than have Rules inside their block instead of Declarations -var atRulesWithRulesBlock = []string{ - "@document", "@font-feature-values", "@keyframes", "@media", "@supports", -} - -// Rule represents a parsed CSS rule -type Rule struct { - Kind RuleKind - - // At Rule name (eg: "@media") - Name string - - // Raw prelude - Prelude string - - // Qualified Rule selectors parsed from prelude - Selectors []string - - // Style properties - Declarations []*Declaration - - // At Rule embedded rules - Rules []*Rule - - // Current rule embedding level - EmbedLevel int -} - -// NewRule instanciates a new Rule -func NewRule(kind RuleKind) *Rule { - return &Rule{ - Kind: kind, - } -} - -// Returns string representation of rule kind -func (kind RuleKind) String() string { - switch kind { - case QualifiedRule: - return "Qualified Rule" - case AtRule: - return "At Rule" - default: - return "WAT" - } -} - -// EmbedsRules returns true if this rule embeds another rules -func (rule *Rule) EmbedsRules() bool { - if rule.Kind == AtRule { - for _, atRuleName := range atRulesWithRulesBlock { - if rule.Name == atRuleName { - return true - } - } - } - - return false -} - -// Equal returns true if both rules are equals -func (rule *Rule) Equal(other *Rule) bool { - if (rule.Kind != other.Kind) || - (rule.Prelude != other.Prelude) || - (rule.Name != other.Name) { - return false - } - - if (len(rule.Selectors) != len(other.Selectors)) || - (len(rule.Declarations) != len(other.Declarations)) || - (len(rule.Rules) != len(other.Rules)) { - return false - } - - for i, sel := range rule.Selectors { - if sel != other.Selectors[i] { - return false - } - } - - for i, decl := range rule.Declarations { - if !decl.Equal(other.Declarations[i]) { - return false - } - } - - for i, rule := range rule.Rules { - if !rule.Equal(other.Rules[i]) { - return false - } - } - - return true -} - -// Diff returns a string representation of rules differences -func (rule *Rule) Diff(other *Rule) []string { - result := []string{} - - if rule.Kind != other.Kind { - result = append(result, fmt.Sprintf("Kind: %s | %s", rule.Kind.String(), other.Kind.String())) - } - - if rule.Prelude != other.Prelude { - result = append(result, fmt.Sprintf("Prelude: \"%s\" | \"%s\"", rule.Prelude, other.Prelude)) - } - - if rule.Name != other.Name { - result = append(result, fmt.Sprintf("Name: \"%s\" | \"%s\"", rule.Name, other.Name)) - } - - if len(rule.Selectors) != len(other.Selectors) { - result = append(result, fmt.Sprintf("Selectors: %v | %v", strings.Join(rule.Selectors, ", "), strings.Join(other.Selectors, ", "))) - } else { - for i, sel := range rule.Selectors { - if sel != other.Selectors[i] { - result = append(result, fmt.Sprintf("Selector: \"%s\" | \"%s\"", sel, other.Selectors[i])) - } - } - } - - if len(rule.Declarations) != len(other.Declarations) { - result = append(result, fmt.Sprintf("Declarations Nb: %d | %d", len(rule.Declarations), len(other.Declarations))) - } else { - for i, decl := range rule.Declarations { - if !decl.Equal(other.Declarations[i]) { - result = append(result, fmt.Sprintf("Declaration: \"%s\" | \"%s\"", decl.String(), other.Declarations[i].String())) - } - } - } - - if len(rule.Rules) != len(other.Rules) { - result = append(result, fmt.Sprintf("Rules Nb: %d | %d", len(rule.Rules), len(other.Rules))) - } else { - - for i, rule := range rule.Rules { - if !rule.Equal(other.Rules[i]) { - result = append(result, fmt.Sprintf("Rule: \"%s\" | \"%s\"", rule.String(), other.Rules[i].String())) - } - } - } - - return result -} - -// Returns the string representation of a rule -func (rule *Rule) String() string { - result := "" - - if rule.Kind == QualifiedRule { - for i, sel := range rule.Selectors { - if i != 0 { - result += ", " - } - result += sel - } - } else { - // AtRule - result += fmt.Sprintf("%s", rule.Name) - - if rule.Prelude != "" { - if result != "" { - result += " " - } - result += fmt.Sprintf("%s", rule.Prelude) - } - } - - if (len(rule.Declarations) == 0) && (len(rule.Rules) == 0) { - result += ";" - } else { - result += " {\n" - - if rule.EmbedsRules() { - for _, subRule := range rule.Rules { - result += fmt.Sprintf("%s%s\n", rule.indent(), subRule.String()) - } - } else { - for _, decl := range rule.Declarations { - result += fmt.Sprintf("%s%s\n", rule.indent(), decl.String()) - } - } - - result += fmt.Sprintf("%s}", rule.indentEndBlock()) - } - - return result -} - -// Returns identation spaces for declarations and rules -func (rule *Rule) indent() string { - result := "" - - for i := 0; i < ((rule.EmbedLevel + 1) * indentSpace); i++ { - result += " " - } - - return result -} - -// Returns identation spaces for end of block character -func (rule *Rule) indentEndBlock() string { - result := "" - - for i := 0; i < (rule.EmbedLevel * indentSpace); i++ { - result += " " - } - - return result -} diff --git a/vendor/github.com/aymerick/douceur/css/stylesheet.go b/vendor/github.com/aymerick/douceur/css/stylesheet.go deleted file mode 100644 index 6b32c2ec..00000000 --- a/vendor/github.com/aymerick/douceur/css/stylesheet.go +++ /dev/null @@ -1,25 +0,0 @@ -package css - -// Stylesheet represents a parsed stylesheet -type Stylesheet struct { - Rules []*Rule -} - -// NewStylesheet instanciate a new Stylesheet -func NewStylesheet() *Stylesheet { - return &Stylesheet{} -} - -// Returns string representation of the Stylesheet -func (sheet *Stylesheet) String() string { - result := "" - - for _, rule := range sheet.Rules { - if result != "" { - result += "\n" - } - result += rule.String() - } - - return result -} diff --git a/vendor/github.com/aymerick/douceur/parser/parser.go b/vendor/github.com/aymerick/douceur/parser/parser.go deleted file mode 100644 index 6c4917cc..00000000 --- a/vendor/github.com/aymerick/douceur/parser/parser.go +++ /dev/null @@ -1,409 +0,0 @@ -package parser - -import ( - "errors" - "fmt" - "regexp" - "strings" - - "github.com/gorilla/css/scanner" - - "github.com/aymerick/douceur/css" -) - -const ( - importantSuffixRegexp = `(?i)\s*!important\s*$` -) - -var ( - importantRegexp *regexp.Regexp -) - -// Parser represents a CSS parser -type Parser struct { - scan *scanner.Scanner // Tokenizer - - // Tokens parsed but not consumed yet - tokens []*scanner.Token - - // Rule embedding level - embedLevel int -} - -func init() { - importantRegexp = regexp.MustCompile(importantSuffixRegexp) -} - -// NewParser instanciates a new parser -func NewParser(txt string) *Parser { - return &Parser{ - scan: scanner.New(txt), - } -} - -// Parse parses a whole stylesheet -func Parse(text string) (*css.Stylesheet, error) { - result, err := NewParser(text).ParseStylesheet() - if err != nil { - return nil, err - } - - return result, nil -} - -// ParseDeclarations parses CSS declarations -func ParseDeclarations(text string) ([]*css.Declaration, error) { - result, err := NewParser(text).ParseDeclarations() - if err != nil { - return nil, err - } - - return result, nil -} - -// ParseStylesheet parses a stylesheet -func (parser *Parser) ParseStylesheet() (*css.Stylesheet, error) { - result := css.NewStylesheet() - - // Parse BOM - if _, err := parser.parseBOM(); err != nil { - return result, err - } - - // Parse list of rules - rules, err := parser.ParseRules() - if err != nil { - return result, err - } - - result.Rules = rules - - return result, nil -} - -// ParseRules parses a list of rules -func (parser *Parser) ParseRules() ([]*css.Rule, error) { - result := []*css.Rule{} - - inBlock := false - if parser.tokenChar("{") { - // parsing a block of rules - inBlock = true - parser.embedLevel++ - - parser.shiftToken() - } - - for parser.tokenParsable() { - if parser.tokenIgnorable() { - parser.shiftToken() - } else if parser.tokenChar("}") { - if !inBlock { - errMsg := fmt.Sprintf("Unexpected } character: %s", parser.nextToken().String()) - return result, errors.New(errMsg) - } - - parser.shiftToken() - parser.embedLevel-- - - // finished - break - } else { - rule, err := parser.ParseRule() - if err != nil { - return result, err - } - - rule.EmbedLevel = parser.embedLevel - result = append(result, rule) - } - } - - return result, parser.err() -} - -// ParseRule parses a rule -func (parser *Parser) ParseRule() (*css.Rule, error) { - if parser.tokenAtKeyword() { - return parser.parseAtRule() - } - - return parser.parseQualifiedRule() -} - -// ParseDeclarations parses a list of declarations -func (parser *Parser) ParseDeclarations() ([]*css.Declaration, error) { - result := []*css.Declaration{} - - if parser.tokenChar("{") { - parser.shiftToken() - } - - for parser.tokenParsable() { - if parser.tokenIgnorable() { - parser.shiftToken() - } else if parser.tokenChar("}") { - // end of block - parser.shiftToken() - break - } else { - declaration, err := parser.ParseDeclaration() - if err != nil { - return result, err - } - - result = append(result, declaration) - } - } - - return result, parser.err() -} - -// ParseDeclaration parses a declaration -func (parser *Parser) ParseDeclaration() (*css.Declaration, error) { - result := css.NewDeclaration() - curValue := "" - - for parser.tokenParsable() { - if parser.tokenChar(":") { - result.Property = strings.TrimSpace(curValue) - curValue = "" - - parser.shiftToken() - } else if parser.tokenChar(";") || parser.tokenChar("}") { - if result.Property == "" { - errMsg := fmt.Sprintf("Unexpected ; character: %s", parser.nextToken().String()) - return result, errors.New(errMsg) - } - - if importantRegexp.MatchString(curValue) { - result.Important = true - curValue = importantRegexp.ReplaceAllString(curValue, "") - } - - result.Value = strings.TrimSpace(curValue) - - if parser.tokenChar(";") { - parser.shiftToken() - } - - // finished - break - } else { - token := parser.shiftToken() - curValue += token.Value - } - } - - // log.Printf("[parsed] Declaration: %s", result.String()) - - return result, parser.err() -} - -// Parse an At Rule -func (parser *Parser) parseAtRule() (*css.Rule, error) { - // parse rule name (eg: "@import") - token := parser.shiftToken() - - result := css.NewRule(css.AtRule) - result.Name = token.Value - - for parser.tokenParsable() { - if parser.tokenChar(";") { - parser.shiftToken() - - // finished - break - } else if parser.tokenChar("{") { - if result.EmbedsRules() { - // parse rules block - rules, err := parser.ParseRules() - if err != nil { - return result, err - } - - result.Rules = rules - } else { - // parse declarations block - declarations, err := parser.ParseDeclarations() - if err != nil { - return result, err - } - - result.Declarations = declarations - } - - // finished - break - } else { - // parse prelude - prelude, err := parser.parsePrelude() - if err != nil { - return result, err - } - - result.Prelude = prelude - } - } - - // log.Printf("[parsed] Rule: %s", result.String()) - - return result, parser.err() -} - -// Parse a Qualified Rule -func (parser *Parser) parseQualifiedRule() (*css.Rule, error) { - result := css.NewRule(css.QualifiedRule) - - for parser.tokenParsable() { - if parser.tokenChar("{") { - if result.Prelude == "" { - errMsg := fmt.Sprintf("Unexpected { character: %s", parser.nextToken().String()) - return result, errors.New(errMsg) - } - - // parse declarations block - declarations, err := parser.ParseDeclarations() - if err != nil { - return result, err - } - - result.Declarations = declarations - - // finished - break - } else { - // parse prelude - prelude, err := parser.parsePrelude() - if err != nil { - return result, err - } - - result.Prelude = prelude - } - } - - result.Selectors = strings.Split(result.Prelude, ",") - for i, sel := range result.Selectors { - result.Selectors[i] = strings.TrimSpace(sel) - } - - // log.Printf("[parsed] Rule: %s", result.String()) - - return result, parser.err() -} - -// Parse Rule prelude -func (parser *Parser) parsePrelude() (string, error) { - result := "" - - for parser.tokenParsable() && !parser.tokenEndOfPrelude() { - token := parser.shiftToken() - result += token.Value - } - - result = strings.TrimSpace(result) - - // log.Printf("[parsed] prelude: %s", result) - - return result, parser.err() -} - -// Parse BOM -func (parser *Parser) parseBOM() (bool, error) { - if parser.nextToken().Type == scanner.TokenBOM { - parser.shiftToken() - return true, nil - } - - return false, parser.err() -} - -// Returns next token without removing it from tokens buffer -func (parser *Parser) nextToken() *scanner.Token { - if len(parser.tokens) == 0 { - // fetch next token - nextToken := parser.scan.Next() - - // log.Printf("[token] %s => %v", nextToken.Type.String(), nextToken.Value) - - // queue it - parser.tokens = append(parser.tokens, nextToken) - } - - return parser.tokens[0] -} - -// Returns next token and remove it from the tokens buffer -func (parser *Parser) shiftToken() *scanner.Token { - var result *scanner.Token - - result, parser.tokens = parser.tokens[0], parser.tokens[1:] - return result -} - -// Returns tokenizer error, or nil if no error -func (parser *Parser) err() error { - if parser.tokenError() { - token := parser.nextToken() - return fmt.Errorf("Tokenizer error: %s", token.String()) - } - - return nil -} - -// Returns true if next token is Error -func (parser *Parser) tokenError() bool { - return parser.nextToken().Type == scanner.TokenError -} - -// Returns true if next token is EOF -func (parser *Parser) tokenEOF() bool { - return parser.nextToken().Type == scanner.TokenEOF -} - -// Returns true if next token is a whitespace -func (parser *Parser) tokenWS() bool { - return parser.nextToken().Type == scanner.TokenS -} - -// Returns true if next token is a comment -func (parser *Parser) tokenComment() bool { - return parser.nextToken().Type == scanner.TokenComment -} - -// Returns true if next token is a CDO or a CDC -func (parser *Parser) tokenCDOorCDC() bool { - switch parser.nextToken().Type { - case scanner.TokenCDO, scanner.TokenCDC: - return true - default: - return false - } -} - -// Returns true if next token is ignorable -func (parser *Parser) tokenIgnorable() bool { - return parser.tokenWS() || parser.tokenComment() || parser.tokenCDOorCDC() -} - -// Returns true if next token is parsable -func (parser *Parser) tokenParsable() bool { - return !parser.tokenEOF() && !parser.tokenError() -} - -// Returns true if next token is an At Rule keyword -func (parser *Parser) tokenAtKeyword() bool { - return parser.nextToken().Type == scanner.TokenAtKeyword -} - -// Returns true if next token is given character -func (parser *Parser) tokenChar(value string) bool { - token := parser.nextToken() - return (token.Type == scanner.TokenChar) && (token.Value == value) -} - -// Returns true if next token marks the end of a prelude -func (parser *Parser) tokenEndOfPrelude() bool { - return parser.tokenChar(";") || parser.tokenChar("{") -} diff --git a/vendor/github.com/beorn7/perks/LICENSE b/vendor/github.com/beorn7/perks/LICENSE deleted file mode 100644 index 339177be..00000000 --- a/vendor/github.com/beorn7/perks/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2013 Blake Mizerany - -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/beorn7/perks/quantile/exampledata.txt b/vendor/github.com/beorn7/perks/quantile/exampledata.txt deleted file mode 100644 index 1602287d..00000000 --- a/vendor/github.com/beorn7/perks/quantile/exampledata.txt +++ /dev/null @@ -1,2388 +0,0 @@ -8 -5 -26 -12 -5 -235 -13 -6 -28 -30 -3 -3 -3 -3 -5 -2 -33 -7 -2 -4 -7 -12 -14 -5 -8 -3 -10 -4 -5 -3 -6 -6 -209 -20 -3 -10 -14 -3 -4 -6 -8 -5 -11 -7 -3 -2 -3 -3 -212 -5 -222 -4 -10 -10 -5 -6 -3 -8 -3 -10 -254 -220 -2 -3 -5 -24 -5 -4 -222 -7 -3 -3 -223 -8 -15 -12 -14 -14 -3 -2 -2 -3 -13 -3 -11 -4 -4 -6 -5 -7 -13 -5 -3 -5 -2 -5 -3 -5 -2 -7 -15 -17 -14 -3 -6 -6 -3 -17 -5 -4 -7 -6 -4 -4 -8 -6 -8 -3 -9 -3 -6 -3 -4 -5 -3 -3 -660 -4 -6 -10 -3 -6 -3 -2 -5 -13 -2 -4 -4 -10 -4 -8 -4 -3 -7 -9 -9 -3 -10 -37 -3 -13 -4 -12 -3 -6 -10 -8 -5 -21 -2 -3 -8 -3 -2 -3 -3 -4 -12 -2 -4 -8 -8 -4 -3 -2 -20 -1 -6 -32 -2 -11 -6 -18 -3 -8 -11 -3 -212 -3 -4 -2 -6 -7 -12 -11 -3 -2 -16 -10 -6 -4 -6 -3 -2 -7 -3 -2 -2 -2 -2 -5 -6 -4 -3 -10 -3 -4 -6 -5 -3 -4 -4 -5 -6 -4 -3 -4 -4 -5 -7 -5 -5 -3 -2 -7 -2 -4 -12 -4 -5 -6 -2 -4 -4 -8 -4 -15 -13 -7 -16 -5 -3 -23 -5 -5 -7 -3 -2 -9 -8 -7 -5 -8 -11 -4 -10 -76 -4 -47 -4 -3 -2 -7 -4 -2 -3 -37 -10 -4 -2 -20 -5 -4 -4 -10 -10 -4 -3 -7 -23 -240 -7 -13 -5 -5 -3 -3 -2 -5 -4 -2 -8 -7 -19 -2 -23 -8 -7 -2 -5 -3 -8 -3 -8 -13 -5 -5 -5 -2 -3 -23 -4 -9 -8 -4 -3 -3 -5 -220 -2 -3 -4 -6 -14 -3 -53 -6 -2 -5 -18 -6 -3 -219 -6 -5 -2 -5 -3 -6 -5 -15 -4 -3 -17 -3 -2 -4 -7 -2 -3 -3 -4 -4 -3 -2 -664 -6 -3 -23 -5 -5 -16 -5 -8 -2 -4 -2 -24 -12 -3 -2 -3 -5 -8 -3 -5 -4 -3 -14 -3 -5 -8 -2 -3 -7 -9 -4 -2 -3 -6 -8 -4 -3 -4 -6 -5 -3 -3 -6 -3 -19 -4 -4 -6 -3 -6 -3 -5 -22 -5 -4 -4 -3 -8 -11 -4 -9 -7 -6 -13 -4 -4 -4 -6 -17 -9 -3 -3 -3 -4 -3 -221 -5 -11 -3 -4 -2 -12 -6 -3 -5 -7 -5 -7 -4 -9 -7 -14 -37 -19 -217 -16 -3 -5 -2 -2 -7 -19 -7 -6 -7 -4 -24 -5 -11 -4 -7 -7 -9 -13 -3 -4 -3 -6 -28 -4 -4 -5 -5 -2 -5 -6 -4 -4 -6 -10 -5 -4 -3 -2 -3 -3 -6 -5 -5 -4 -3 -2 -3 -7 -4 -6 -18 -16 -8 -16 -4 -5 -8 -6 -9 -13 -1545 -6 -215 -6 -5 -6 -3 -45 -31 -5 -2 -2 -4 -3 -3 -2 -5 -4 -3 -5 -7 -7 -4 -5 -8 -5 -4 -749 -2 -31 -9 -11 -2 -11 -5 -4 -4 -7 -9 -11 -4 -5 -4 -7 -3 -4 -6 -2 -15 -3 -4 -3 -4 -3 -5 -2 -13 -5 -5 -3 -3 -23 -4 -4 -5 -7 -4 -13 -2 -4 -3 -4 -2 -6 -2 -7 -3 -5 -5 -3 -29 -5 -4 -4 -3 -10 -2 -3 -79 -16 -6 -6 -7 -7 -3 -5 -5 -7 -4 -3 -7 -9 -5 -6 -5 -9 -6 -3 -6 -4 -17 -2 -10 -9 -3 -6 -2 -3 -21 -22 -5 -11 -4 -2 -17 -2 -224 -2 -14 -3 -4 -4 -2 -4 -4 -4 -4 -5 -3 -4 -4 -10 -2 -6 -3 -3 -5 -7 -2 -7 -5 -6 -3 -218 -2 -2 -5 -2 -6 -3 -5 -222 -14 -6 -33 -3 -2 -5 -3 -3 -3 -9 -5 -3 -3 -2 -7 -4 -3 -4 -3 -5 -6 -5 -26 -4 -13 -9 -7 -3 -221 -3 -3 -4 -4 -4 -4 -2 -18 -5 -3 -7 -9 -6 -8 -3 -10 -3 -11 -9 -5 -4 -17 -5 -5 -6 -6 -3 -2 -4 -12 -17 -6 -7 -218 -4 -2 -4 -10 -3 -5 -15 -3 -9 -4 -3 -3 -6 -29 -3 -3 -4 -5 -5 -3 -8 -5 -6 -6 -7 -5 -3 -5 -3 -29 -2 -31 -5 -15 -24 -16 -5 -207 -4 -3 -3 -2 -15 -4 -4 -13 -5 -5 -4 -6 -10 -2 -7 -8 -4 -6 -20 -5 -3 -4 -3 -12 -12 -5 -17 -7 -3 -3 -3 -6 -10 -3 -5 -25 -80 -4 -9 -3 -2 -11 -3 -3 -2 -3 -8 -7 -5 -5 -19 -5 -3 -3 -12 -11 -2 -6 -5 -5 -5 -3 -3 -3 -4 -209 -14 -3 -2 -5 -19 -4 -4 -3 -4 -14 -5 -6 -4 -13 -9 -7 -4 -7 -10 -2 -9 -5 -7 -2 -8 -4 -6 -5 -5 -222 -8 -7 -12 -5 -216 -3 -4 -4 -6 -3 -14 -8 -7 -13 -4 -3 -3 -3 -3 -17 -5 -4 -3 -33 -6 -6 -33 -7 -5 -3 -8 -7 -5 -2 -9 -4 -2 -233 -24 -7 -4 -8 -10 -3 -4 -15 -2 -16 -3 -3 -13 -12 -7 -5 -4 -207 -4 -2 -4 -27 -15 -2 -5 -2 -25 -6 -5 -5 -6 -13 -6 -18 -6 -4 -12 -225 -10 -7 -5 -2 -2 -11 -4 -14 -21 -8 -10 -3 -5 -4 -232 -2 -5 -5 -3 -7 -17 -11 -6 -6 -23 -4 -6 -3 -5 -4 -2 -17 -3 -6 -5 -8 -3 -2 -2 -14 -9 -4 -4 -2 -5 -5 -3 -7 -6 -12 -6 -10 -3 -6 -2 -2 -19 -5 -4 -4 -9 -2 -4 -13 -3 -5 -6 -3 -6 -5 -4 -9 -6 -3 -5 -7 -3 -6 -6 -4 -3 -10 -6 -3 -221 -3 -5 -3 -6 -4 -8 -5 -3 -6 -4 -4 -2 -54 -5 -6 -11 -3 -3 -4 -4 -4 -3 -7 -3 -11 -11 -7 -10 -6 -13 -223 -213 -15 -231 -7 -3 -7 -228 -2 -3 -4 -4 -5 -6 -7 -4 -13 -3 -4 -5 -3 -6 -4 -6 -7 -2 -4 -3 -4 -3 -3 -6 -3 -7 -3 -5 -18 -5 -6 -8 -10 -3 -3 -3 -2 -4 -2 -4 -4 -5 -6 -6 -4 -10 -13 -3 -12 -5 -12 -16 -8 -4 -19 -11 -2 -4 -5 -6 -8 -5 -6 -4 -18 -10 -4 -2 -216 -6 -6 -6 -2 -4 -12 -8 -3 -11 -5 -6 -14 -5 -3 -13 -4 -5 -4 -5 -3 -28 -6 -3 -7 -219 -3 -9 -7 -3 -10 -6 -3 -4 -19 -5 -7 -11 -6 -15 -19 -4 -13 -11 -3 -7 -5 -10 -2 -8 -11 -2 -6 -4 -6 -24 -6 -3 -3 -3 -3 -6 -18 -4 -11 -4 -2 -5 -10 -8 -3 -9 -5 -3 -4 -5 -6 -2 -5 -7 -4 -4 -14 -6 -4 -4 -5 -5 -7 -2 -4 -3 -7 -3 -3 -6 -4 -5 -4 -4 -4 -3 -3 -3 -3 -8 -14 -2 -3 -5 -3 -2 -4 -5 -3 -7 -3 -3 -18 -3 -4 -4 -5 -7 -3 -3 -3 -13 -5 -4 -8 -211 -5 -5 -3 -5 -2 -5 -4 -2 -655 -6 -3 -5 -11 -2 -5 -3 -12 -9 -15 -11 -5 -12 -217 -2 -6 -17 -3 -3 -207 -5 -5 -4 -5 -9 -3 -2 -8 -5 -4 -3 -2 -5 -12 -4 -14 -5 -4 -2 -13 -5 -8 -4 -225 -4 -3 -4 -5 -4 -3 -3 -6 -23 -9 -2 -6 -7 -233 -4 -4 -6 -18 -3 -4 -6 -3 -4 -4 -2 -3 -7 -4 -13 -227 -4 -3 -5 -4 -2 -12 -9 -17 -3 -7 -14 -6 -4 -5 -21 -4 -8 -9 -2 -9 -25 -16 -3 -6 -4 -7 -8 -5 -2 -3 -5 -4 -3 -3 -5 -3 -3 -3 -2 -3 -19 -2 -4 -3 -4 -2 -3 -4 -4 -2 -4 -3 -3 -3 -2 -6 -3 -17 -5 -6 -4 -3 -13 -5 -3 -3 -3 -4 -9 -4 -2 -14 -12 -4 -5 -24 -4 -3 -37 -12 -11 -21 -3 -4 -3 -13 -4 -2 -3 -15 -4 -11 -4 -4 -3 -8 -3 -4 -4 -12 -8 -5 -3 -3 -4 -2 -220 -3 -5 -223 -3 -3 -3 -10 -3 -15 -4 -241 -9 -7 -3 -6 -6 -23 -4 -13 -7 -3 -4 -7 -4 -9 -3 -3 -4 -10 -5 -5 -1 -5 -24 -2 -4 -5 -5 -6 -14 -3 -8 -2 -3 -5 -13 -13 -3 -5 -2 -3 -15 -3 -4 -2 -10 -4 -4 -4 -5 -5 -3 -5 -3 -4 -7 -4 -27 -3 -6 -4 -15 -3 -5 -6 -6 -5 -4 -8 -3 -9 -2 -6 -3 -4 -3 -7 -4 -18 -3 -11 -3 -3 -8 -9 -7 -24 -3 -219 -7 -10 -4 -5 -9 -12 -2 -5 -4 -4 -4 -3 -3 -19 -5 -8 -16 -8 -6 -22 -3 -23 -3 -242 -9 -4 -3 -3 -5 -7 -3 -3 -5 -8 -3 -7 -5 -14 -8 -10 -3 -4 -3 -7 -4 -6 -7 -4 -10 -4 -3 -11 -3 -7 -10 -3 -13 -6 -8 -12 -10 -5 -7 -9 -3 -4 -7 -7 -10 -8 -30 -9 -19 -4 -3 -19 -15 -4 -13 -3 -215 -223 -4 -7 -4 -8 -17 -16 -3 -7 -6 -5 -5 -4 -12 -3 -7 -4 -4 -13 -4 -5 -2 -5 -6 -5 -6 -6 -7 -10 -18 -23 -9 -3 -3 -6 -5 -2 -4 -2 -7 -3 -3 -2 -5 -5 -14 -10 -224 -6 -3 -4 -3 -7 -5 -9 -3 -6 -4 -2 -5 -11 -4 -3 -3 -2 -8 -4 -7 -4 -10 -7 -3 -3 -18 -18 -17 -3 -3 -3 -4 -5 -3 -3 -4 -12 -7 -3 -11 -13 -5 -4 -7 -13 -5 -4 -11 -3 -12 -3 -6 -4 -4 -21 -4 -6 -9 -5 -3 -10 -8 -4 -6 -4 -4 -6 -5 -4 -8 -6 -4 -6 -4 -4 -5 -9 -6 -3 -4 -2 -9 -3 -18 -2 -4 -3 -13 -3 -6 -6 -8 -7 -9 -3 -2 -16 -3 -4 -6 -3 -2 -33 -22 -14 -4 -9 -12 -4 -5 -6 -3 -23 -9 -4 -3 -5 -5 -3 -4 -5 -3 -5 -3 -10 -4 -5 -5 -8 -4 -4 -6 -8 -5 -4 -3 -4 -6 -3 -3 -3 -5 -9 -12 -6 -5 -9 -3 -5 -3 -2 -2 -2 -18 -3 -2 -21 -2 -5 -4 -6 -4 -5 -10 -3 -9 -3 -2 -10 -7 -3 -6 -6 -4 -4 -8 -12 -7 -3 -7 -3 -3 -9 -3 -4 -5 -4 -4 -5 -5 -10 -15 -4 -4 -14 -6 -227 -3 -14 -5 -216 -22 -5 -4 -2 -2 -6 -3 -4 -2 -9 -9 -4 -3 -28 -13 -11 -4 -5 -3 -3 -2 -3 -3 -5 -3 -4 -3 -5 -23 -26 -3 -4 -5 -6 -4 -6 -3 -5 -5 -3 -4 -3 -2 -2 -2 -7 -14 -3 -6 -7 -17 -2 -2 -15 -14 -16 -4 -6 -7 -13 -6 -4 -5 -6 -16 -3 -3 -28 -3 -6 -15 -3 -9 -2 -4 -6 -3 -3 -22 -4 -12 -6 -7 -2 -5 -4 -10 -3 -16 -6 -9 -2 -5 -12 -7 -5 -5 -5 -5 -2 -11 -9 -17 -4 -3 -11 -7 -3 -5 -15 -4 -3 -4 -211 -8 -7 -5 -4 -7 -6 -7 -6 -3 -6 -5 -6 -5 -3 -4 -4 -26 -4 -6 -10 -4 -4 -3 -2 -3 -3 -4 -5 -9 -3 -9 -4 -4 -5 -5 -8 -2 -4 -2 -3 -8 -4 -11 -19 -5 -8 -6 -3 -5 -6 -12 -3 -2 -4 -16 -12 -3 -4 -4 -8 -6 -5 -6 -6 -219 -8 -222 -6 -16 -3 -13 -19 -5 -4 -3 -11 -6 -10 -4 -7 -7 -12 -5 -3 -3 -5 -6 -10 -3 -8 -2 -5 -4 -7 -2 -4 -4 -2 -12 -9 -6 -4 -2 -40 -2 -4 -10 -4 -223 -4 -2 -20 -6 -7 -24 -5 -4 -5 -2 -20 -16 -6 -5 -13 -2 -3 -3 -19 -3 -2 -4 -5 -6 -7 -11 -12 -5 -6 -7 -7 -3 -5 -3 -5 -3 -14 -3 -4 -4 -2 -11 -1 -7 -3 -9 -6 -11 -12 -5 -8 -6 -221 -4 -2 -12 -4 -3 -15 -4 -5 -226 -7 -218 -7 -5 -4 -5 -18 -4 -5 -9 -4 -4 -2 -9 -18 -18 -9 -5 -6 -6 -3 -3 -7 -3 -5 -4 -4 -4 -12 -3 -6 -31 -5 -4 -7 -3 -6 -5 -6 -5 -11 -2 -2 -11 -11 -6 -7 -5 -8 -7 -10 -5 -23 -7 -4 -3 -5 -34 -2 -5 -23 -7 -3 -6 -8 -4 -4 -4 -2 -5 -3 -8 -5 -4 -8 -25 -2 -3 -17 -8 -3 -4 -8 -7 -3 -15 -6 -5 -7 -21 -9 -5 -6 -6 -5 -3 -2 -3 -10 -3 -6 -3 -14 -7 -4 -4 -8 -7 -8 -2 -6 -12 -4 -213 -6 -5 -21 -8 -2 -5 -23 -3 -11 -2 -3 -6 -25 -2 -3 -6 -7 -6 -6 -4 -4 -6 -3 -17 -9 -7 -6 -4 -3 -10 -7 -2 -3 -3 -3 -11 -8 -3 -7 -6 -4 -14 -36 -3 -4 -3 -3 -22 -13 -21 -4 -2 -7 -4 -4 -17 -15 -3 -7 -11 -2 -4 -7 -6 -209 -6 -3 -2 -2 -24 -4 -9 -4 -3 -3 -3 -29 -2 -2 -4 -3 -3 -5 -4 -6 -3 -3 -2 -4 diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go deleted file mode 100644 index d7d14f8e..00000000 --- a/vendor/github.com/beorn7/perks/quantile/stream.go +++ /dev/null @@ -1,316 +0,0 @@ -// Package quantile computes approximate quantiles over an unbounded data -// stream within low memory and CPU bounds. -// -// A small amount of accuracy is traded to achieve the above properties. -// -// Multiple streams can be merged before calling Query to generate a single set -// of results. This is meaningful when the streams represent the same type of -// data. See Merge and Samples. -// -// For more detailed information about the algorithm used, see: -// -// Effective Computation of Biased Quantiles over Data Streams -// -// http://www.cs.rutgers.edu/~muthu/bquant.pdf -package quantile - -import ( - "math" - "sort" -) - -// Sample holds an observed value and meta information for compression. JSON -// tags have been added for convenience. -type Sample struct { - Value float64 `json:",string"` - Width float64 `json:",string"` - Delta float64 `json:",string"` -} - -// Samples represents a slice of samples. It implements sort.Interface. -type Samples []Sample - -func (a Samples) Len() int { return len(a) } -func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value } -func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -type invariant func(s *stream, r float64) float64 - -// NewLowBiased returns an initialized Stream for low-biased quantiles -// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but -// error guarantees can still be given even for the lower ranks of the data -// distribution. -// -// The provided epsilon is a relative error, i.e. the true quantile of a value -// returned by a query is guaranteed to be within (1±Epsilon)*Quantile. -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error -// properties. -func NewLowBiased(epsilon float64) *Stream { - ƒ := func(s *stream, r float64) float64 { - return 2 * epsilon * r - } - return newStream(ƒ) -} - -// NewHighBiased returns an initialized Stream for high-biased quantiles -// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but -// error guarantees can still be given even for the higher ranks of the data -// distribution. -// -// The provided epsilon is a relative error, i.e. the true quantile of a value -// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile). -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error -// properties. -func NewHighBiased(epsilon float64) *Stream { - ƒ := func(s *stream, r float64) float64 { - return 2 * epsilon * (s.n - r) - } - return newStream(ƒ) -} - -// NewTargeted returns an initialized Stream concerned with a particular set of -// quantile values that are supplied a priori. Knowing these a priori reduces -// space and computation time. The targets map maps the desired quantiles to -// their absolute errors, i.e. the true quantile of a value returned by a query -// is guaranteed to be within (Quantile±Epsilon). -// -// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties. -func NewTargeted(targetMap map[float64]float64) *Stream { - // Convert map to slice to avoid slow iterations on a map. - // ƒ is called on the hot path, so converting the map to a slice - // beforehand results in significant CPU savings. - targets := targetMapToSlice(targetMap) - - ƒ := func(s *stream, r float64) float64 { - var m = math.MaxFloat64 - var f float64 - for _, t := range targets { - if t.quantile*s.n <= r { - f = (2 * t.epsilon * r) / t.quantile - } else { - f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile) - } - if f < m { - m = f - } - } - return m - } - return newStream(ƒ) -} - -type target struct { - quantile float64 - epsilon float64 -} - -func targetMapToSlice(targetMap map[float64]float64) []target { - targets := make([]target, 0, len(targetMap)) - - for quantile, epsilon := range targetMap { - t := target{ - quantile: quantile, - epsilon: epsilon, - } - targets = append(targets, t) - } - - return targets -} - -// Stream computes quantiles for a stream of float64s. It is not thread-safe by -// design. Take care when using across multiple goroutines. -type Stream struct { - *stream - b Samples - sorted bool -} - -func newStream(ƒ invariant) *Stream { - x := &stream{ƒ: ƒ} - return &Stream{x, make(Samples, 0, 500), true} -} - -// Insert inserts v into the stream. -func (s *Stream) Insert(v float64) { - s.insert(Sample{Value: v, Width: 1}) -} - -func (s *Stream) insert(sample Sample) { - s.b = append(s.b, sample) - s.sorted = false - if len(s.b) == cap(s.b) { - s.flush() - } -} - -// Query returns the computed qth percentiles value. If s was created with -// NewTargeted, and q is not in the set of quantiles provided a priori, Query -// will return an unspecified result. -func (s *Stream) Query(q float64) float64 { - if !s.flushed() { - // Fast path when there hasn't been enough data for a flush; - // this also yields better accuracy for small sets of data. - l := len(s.b) - if l == 0 { - return 0 - } - i := int(math.Ceil(float64(l) * q)) - if i > 0 { - i -= 1 - } - s.maybeSort() - return s.b[i].Value - } - s.flush() - return s.stream.query(q) -} - -// Merge merges samples into the underlying streams samples. This is handy when -// merging multiple streams from separate threads, database shards, etc. -// -// ATTENTION: This method is broken and does not yield correct results. The -// underlying algorithm is not capable of merging streams correctly. -func (s *Stream) Merge(samples Samples) { - sort.Sort(samples) - s.stream.merge(samples) -} - -// Reset reinitializes and clears the list reusing the samples buffer memory. -func (s *Stream) Reset() { - s.stream.reset() - s.b = s.b[:0] -} - -// Samples returns stream samples held by s. -func (s *Stream) Samples() Samples { - if !s.flushed() { - return s.b - } - s.flush() - return s.stream.samples() -} - -// Count returns the total number of samples observed in the stream -// since initialization. -func (s *Stream) Count() int { - return len(s.b) + s.stream.count() -} - -func (s *Stream) flush() { - s.maybeSort() - s.stream.merge(s.b) - s.b = s.b[:0] -} - -func (s *Stream) maybeSort() { - if !s.sorted { - s.sorted = true - sort.Sort(s.b) - } -} - -func (s *Stream) flushed() bool { - return len(s.stream.l) > 0 -} - -type stream struct { - n float64 - l []Sample - ƒ invariant -} - -func (s *stream) reset() { - s.l = s.l[:0] - s.n = 0 -} - -func (s *stream) insert(v float64) { - s.merge(Samples{{v, 1, 0}}) -} - -func (s *stream) merge(samples Samples) { - // TODO(beorn7): This tries to merge not only individual samples, but - // whole summaries. The paper doesn't mention merging summaries at - // all. Unittests show that the merging is inaccurate. Find out how to - // do merges properly. - var r float64 - i := 0 - for _, sample := range samples { - for ; i < len(s.l); i++ { - c := s.l[i] - if c.Value > sample.Value { - // Insert at position i. - s.l = append(s.l, Sample{}) - copy(s.l[i+1:], s.l[i:]) - s.l[i] = Sample{ - sample.Value, - sample.Width, - math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1), - // TODO(beorn7): How to calculate delta correctly? - } - i++ - goto inserted - } - r += c.Width - } - s.l = append(s.l, Sample{sample.Value, sample.Width, 0}) - i++ - inserted: - s.n += sample.Width - r += sample.Width - } - s.compress() -} - -func (s *stream) count() int { - return int(s.n) -} - -func (s *stream) query(q float64) float64 { - t := math.Ceil(q * s.n) - t += math.Ceil(s.ƒ(s, t) / 2) - p := s.l[0] - var r float64 - for _, c := range s.l[1:] { - r += p.Width - if r+c.Width+c.Delta > t { - return p.Value - } - p = c - } - return p.Value -} - -func (s *stream) compress() { - if len(s.l) < 2 { - return - } - x := s.l[len(s.l)-1] - xi := len(s.l) - 1 - r := s.n - 1 - x.Width - - for i := len(s.l) - 2; i >= 0; i-- { - c := s.l[i] - if c.Width+x.Width+x.Delta <= s.ƒ(s, r) { - x.Width += c.Width - s.l[xi] = x - // Remove element at i. - copy(s.l[i:], s.l[i+1:]) - s.l = s.l[:len(s.l)-1] - xi -= 1 - } else { - x = c - xi = i - } - r -= c.Width - } -} - -func (s *stream) samples() Samples { - samples := make(Samples, len(s.l)) - copy(samples, s.l) - return samples -} diff --git a/vendor/github.com/catppuccin/go/.editorconfig b/vendor/github.com/catppuccin/go/.editorconfig deleted file mode 100644 index d86ac027..00000000 --- a/vendor/github.com/catppuccin/go/.editorconfig +++ /dev/null @@ -1,34 +0,0 @@ -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# EditorConfig is awesome: https://EditorConfig.org - -root = true - -[*] -charset = utf-8 -indent_size = 2 -indent_style = space -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -# go -[*.go] -indent_style = tab -indent_size = 4 - -# python -[*.{ini,py,py.tpl,rst}] -indent_size = 4 - -# rust -[*.rs] -indent_size = 4 - -# documentation, utils -[*.{md,mdx,diff}] -trim_trailing_whitespace = false - -# windows shell scripts -[*.{cmd,bat,ps1}] -end_of_line = crlf diff --git a/vendor/github.com/catppuccin/go/.gitignore b/vendor/github.com/catppuccin/go/.gitignore deleted file mode 100644 index de015a99..00000000 --- a/vendor/github.com/catppuccin/go/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -coverage.txt -dist/ -_examples/catppuccin -_examples/frames/ diff --git a/vendor/github.com/catppuccin/go/.goreleaser.yaml b/vendor/github.com/catppuccin/go/.goreleaser.yaml deleted file mode 100644 index 9d806952..00000000 --- a/vendor/github.com/catppuccin/go/.goreleaser.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# modelines, feel free to remove those if you don't want/use them: -# yaml-language-server: $schema=https://goreleaser.com/static/schema.json -# vim: set ts=2 sw=2 tw=0 fo=cnqoj - -version: 2 - -before: - hooks: - - go mod tidy -builds: - - skip: true diff --git a/vendor/github.com/catppuccin/go/LICENSE b/vendor/github.com/catppuccin/go/LICENSE deleted file mode 100644 index 006383b8..00000000 --- a/vendor/github.com/catppuccin/go/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 Catppuccin - -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/catppuccin/go/README.md b/vendor/github.com/catppuccin/go/README.md deleted file mode 100644 index b73a3fcd..00000000 --- a/vendor/github.com/catppuccin/go/README.md +++ /dev/null @@ -1,48 +0,0 @@ -

- Logo
- - Catppuccin for Go - -

- -

- - - -

- -![Catppuccin Variants](https://raw.githubusercontent.com/catppuccin/go/main/_examples/catppuccin.gif) - -## Usage - -1. Run `go get github.com/catppuccin/go`. -2. Add `import catppuccin "github.com/catppuccin/go"` to your file. -3. Refer to the [pkg.go.dev documentation](https://pkg.go.dev/github.com/catppuccin/go) and [`_examples/main.go`](https://github.com/catppuccin/go/blob/main/_examples/main.go) for usage. - -## Contributing - -This repository uses [Whiskers](https://github.com/catppuccin/whiskers) to generate the Go flavor files. - -Ensure `whiskers` and `go` are in your `$PATH`, and run: - -```sh -go generate ./... -``` - -## 💝 Thanks to - -- [Carlos Becker](https://github.com/caarlos0) - -  - -

- -

- -

- Copyright © 2021-present Catppuccin Org -

- -

- -

diff --git a/vendor/github.com/catppuccin/go/flake.lock b/vendor/github.com/catppuccin/go/flake.lock deleted file mode 100644 index 059e0c76..00000000 --- a/vendor/github.com/catppuccin/go/flake.lock +++ /dev/null @@ -1,95 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1718198959, - "narHash": "sha256-s04G4JzMhLmlxK56DRMimXZ0n/lCQYRNOusKIGdaYks=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "375801cfcba34b1b2d4360cf54817a114e1411f0", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1732014248, - "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "whiskers": "whiskers" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "whiskers": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1732368895, - "narHash": "sha256-AZf606SzxtrkspfkypNHwgY0RBgKvPgqoyxY4FLVleg=", - "owner": "catppuccin", - "repo": "whiskers", - "rev": "c36c9fe101448cd6755d91c83321ceb4346b9ae6", - "type": "github" - }, - "original": { - "owner": "catppuccin", - "repo": "whiskers", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/vendor/github.com/catppuccin/go/flake.nix b/vendor/github.com/catppuccin/go/flake.nix deleted file mode 100644 index 790e5d2b..00000000 --- a/vendor/github.com/catppuccin/go/flake.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ - inputs = { - nixpkgs.url = "github:nixos/nixpkgs"; - flake-utils.url = "github:numtide/flake-utils"; - whiskers.url = "github:catppuccin/whiskers"; - }; - - outputs = - { self - , flake-utils - , nixpkgs - , whiskers - , - } @ inputs: - flake-utils.lib.eachDefaultSystem ( - system: - let - pkgs = nixpkgs.legacyPackages.${system}; - whiskers = inputs.whiskers.packages.${system}.default; - in - { - devShells.default = pkgs.mkShell { - nativeBuildInputs = with pkgs; [ - go - gopls - whiskers - (writeScriptBin "update" '' - whiskers go.tera - go fmt - '') - ]; - }; - } - ); -} diff --git a/vendor/github.com/catppuccin/go/frappe.go b/vendor/github.com/catppuccin/go/frappe.go deleted file mode 100644 index a9185559..00000000 --- a/vendor/github.com/catppuccin/go/frappe.go +++ /dev/null @@ -1,244 +0,0 @@ -package catppuccingo - -// Frappé variant -type frappe struct{} - -// Frappé flavor variant -var Frappe Flavor = frappe{} - -// Frappé -func (frappe) Name() string { return "frappe" } - -// Rosewater -func (frappe) Rosewater() Color { - return Color{ - Hex: "#f2d5cf", - RGB: [3]uint8{242, 213, 207}, - HSL: [3]float32{10, 0.57, 0.88}, - } -} - -// Flamingo -func (frappe) Flamingo() Color { - return Color{ - Hex: "#eebebe", - RGB: [3]uint8{238, 190, 190}, - HSL: [3]float32{0, 0.59, 0.84}, - } -} - -// Pink -func (frappe) Pink() Color { - return Color{ - Hex: "#f4b8e4", - RGB: [3]uint8{244, 184, 228}, - HSL: [3]float32{316, 0.73, 0.84}, - } -} - -// Mauve -func (frappe) Mauve() Color { - return Color{ - Hex: "#ca9ee6", - RGB: [3]uint8{202, 158, 230}, - HSL: [3]float32{277, 0.59, 0.76}, - } -} - -// Red -func (frappe) Red() Color { - return Color{ - Hex: "#e78284", - RGB: [3]uint8{231, 130, 132}, - HSL: [3]float32{359, 0.68, 0.71}, - } -} - -// Maroon -func (frappe) Maroon() Color { - return Color{ - Hex: "#ea999c", - RGB: [3]uint8{234, 153, 156}, - HSL: [3]float32{358, 0.66, 0.76}, - } -} - -// Peach -func (frappe) Peach() Color { - return Color{ - Hex: "#ef9f76", - RGB: [3]uint8{239, 159, 118}, - HSL: [3]float32{20, 0.79, 0.7}, - } -} - -// Yellow -func (frappe) Yellow() Color { - return Color{ - Hex: "#e5c890", - RGB: [3]uint8{229, 200, 144}, - HSL: [3]float32{40, 0.62, 0.73}, - } -} - -// Green -func (frappe) Green() Color { - return Color{ - Hex: "#a6d189", - RGB: [3]uint8{166, 209, 137}, - HSL: [3]float32{96, 0.44, 0.68}, - } -} - -// Teal -func (frappe) Teal() Color { - return Color{ - Hex: "#81c8be", - RGB: [3]uint8{129, 200, 190}, - HSL: [3]float32{172, 0.39, 0.65}, - } -} - -// Sky -func (frappe) Sky() Color { - return Color{ - Hex: "#99d1db", - RGB: [3]uint8{153, 209, 219}, - HSL: [3]float32{189, 0.48, 0.73}, - } -} - -// Sapphire -func (frappe) Sapphire() Color { - return Color{ - Hex: "#85c1dc", - RGB: [3]uint8{133, 193, 220}, - HSL: [3]float32{199, 0.55, 0.69}, - } -} - -// Blue -func (frappe) Blue() Color { - return Color{ - Hex: "#8caaee", - RGB: [3]uint8{140, 170, 238}, - HSL: [3]float32{222, 0.74, 0.74}, - } -} - -// Lavender -func (frappe) Lavender() Color { - return Color{ - Hex: "#babbf1", - RGB: [3]uint8{186, 187, 241}, - HSL: [3]float32{239, 0.66, 0.84}, - } -} - -// Text -func (frappe) Text() Color { - return Color{ - Hex: "#c6d0f5", - RGB: [3]uint8{198, 208, 245}, - HSL: [3]float32{227, 0.7, 0.87}, - } -} - -// Subtext 1 -func (frappe) Subtext1() Color { - return Color{ - Hex: "#b5bfe2", - RGB: [3]uint8{181, 191, 226}, - HSL: [3]float32{227, 0.44, 0.8}, - } -} - -// Subtext 0 -func (frappe) Subtext0() Color { - return Color{ - Hex: "#a5adce", - RGB: [3]uint8{165, 173, 206}, - HSL: [3]float32{228, 0.29, 0.73}, - } -} - -// Overlay 2 -func (frappe) Overlay2() Color { - return Color{ - Hex: "#949cbb", - RGB: [3]uint8{148, 156, 187}, - HSL: [3]float32{228, 0.22, 0.66}, - } -} - -// Overlay 1 -func (frappe) Overlay1() Color { - return Color{ - Hex: "#838ba7", - RGB: [3]uint8{131, 139, 167}, - HSL: [3]float32{227, 0.17, 0.58}, - } -} - -// Overlay 0 -func (frappe) Overlay0() Color { - return Color{ - Hex: "#737994", - RGB: [3]uint8{115, 121, 148}, - HSL: [3]float32{229, 0.13, 0.52}, - } -} - -// Surface 2 -func (frappe) Surface2() Color { - return Color{ - Hex: "#626880", - RGB: [3]uint8{98, 104, 128}, - HSL: [3]float32{228, 0.13, 0.44}, - } -} - -// Surface 1 -func (frappe) Surface1() Color { - return Color{ - Hex: "#51576d", - RGB: [3]uint8{81, 87, 109}, - HSL: [3]float32{227, 0.15, 0.37}, - } -} - -// Surface 0 -func (frappe) Surface0() Color { - return Color{ - Hex: "#414559", - RGB: [3]uint8{65, 69, 89}, - HSL: [3]float32{230, 0.16, 0.3}, - } -} - -// Base -func (frappe) Base() Color { - return Color{ - Hex: "#303446", - RGB: [3]uint8{48, 52, 70}, - HSL: [3]float32{229, 0.19, 0.23}, - } -} - -// Mantle -func (frappe) Mantle() Color { - return Color{ - Hex: "#292c3c", - RGB: [3]uint8{41, 44, 60}, - HSL: [3]float32{231, 0.19, 0.2}, - } -} - -// Crust -func (frappe) Crust() Color { - return Color{ - Hex: "#232634", - RGB: [3]uint8{35, 38, 52}, - HSL: [3]float32{229, 0.2, 0.17}, - } -} diff --git a/vendor/github.com/catppuccin/go/go.tera b/vendor/github.com/catppuccin/go/go.tera deleted file mode 100644 index 5dbc1f80..00000000 --- a/vendor/github.com/catppuccin/go/go.tera +++ /dev/null @@ -1,28 +0,0 @@ ---- -whiskers: - version: 2.5.1 - matrix: - - flavor - filename: "{{flavor.identifier}}.go" ---- -package catppuccingo - -// {{flavor.name}} variant -type {{flavor.identifier}} struct{} - -// {{flavor.name}} flavor variant -var {{flavor.identifier | title}} Flavor = {{flavor.identifier}}{} - -// {{flavor.name}} -func ({{flavor.identifier}}) Name() string { return "{{flavor.identifier}}" } - -{% for _, color in flavor.colors %} -// {{color.name}} -func ({{flavor.identifier}}) {{color.identifier | title}}() Color { - return Color{ - Hex: "#{{color.hex}}", - RGB: [3]uint8{ {{color.rgb.r}}, {{color.rgb.g}}, {{color.rgb.b}}}, - HSL: [3]float32{ {{color.hsl.h | round(precision=2)}}, {{color.hsl.s | round(precision=2)}}, {{color.hsl.l | round(precision=2)}}}, - } -} -{% endfor %} diff --git a/vendor/github.com/catppuccin/go/latte.go b/vendor/github.com/catppuccin/go/latte.go deleted file mode 100644 index 34b6af58..00000000 --- a/vendor/github.com/catppuccin/go/latte.go +++ /dev/null @@ -1,244 +0,0 @@ -package catppuccingo - -// Latte variant -type latte struct{} - -// Latte flavor variant -var Latte Flavor = latte{} - -// Latte -func (latte) Name() string { return "latte" } - -// Rosewater -func (latte) Rosewater() Color { - return Color{ - Hex: "#dc8a78", - RGB: [3]uint8{220, 138, 120}, - HSL: [3]float32{11, 0.59, 0.67}, - } -} - -// Flamingo -func (latte) Flamingo() Color { - return Color{ - Hex: "#dd7878", - RGB: [3]uint8{221, 120, 120}, - HSL: [3]float32{0, 0.6, 0.67}, - } -} - -// Pink -func (latte) Pink() Color { - return Color{ - Hex: "#ea76cb", - RGB: [3]uint8{234, 118, 203}, - HSL: [3]float32{316, 0.73, 0.69}, - } -} - -// Mauve -func (latte) Mauve() Color { - return Color{ - Hex: "#8839ef", - RGB: [3]uint8{136, 57, 239}, - HSL: [3]float32{266, 0.85, 0.58}, - } -} - -// Red -func (latte) Red() Color { - return Color{ - Hex: "#d20f39", - RGB: [3]uint8{210, 15, 57}, - HSL: [3]float32{347, 0.87, 0.44}, - } -} - -// Maroon -func (latte) Maroon() Color { - return Color{ - Hex: "#e64553", - RGB: [3]uint8{230, 69, 83}, - HSL: [3]float32{355, 0.76, 0.59}, - } -} - -// Peach -func (latte) Peach() Color { - return Color{ - Hex: "#fe640b", - RGB: [3]uint8{254, 100, 11}, - HSL: [3]float32{22, 0.99, 0.52}, - } -} - -// Yellow -func (latte) Yellow() Color { - return Color{ - Hex: "#df8e1d", - RGB: [3]uint8{223, 142, 29}, - HSL: [3]float32{35, 0.77, 0.49}, - } -} - -// Green -func (latte) Green() Color { - return Color{ - Hex: "#40a02b", - RGB: [3]uint8{64, 160, 43}, - HSL: [3]float32{109, 0.58, 0.4}, - } -} - -// Teal -func (latte) Teal() Color { - return Color{ - Hex: "#179299", - RGB: [3]uint8{23, 146, 153}, - HSL: [3]float32{183, 0.74, 0.35}, - } -} - -// Sky -func (latte) Sky() Color { - return Color{ - Hex: "#04a5e5", - RGB: [3]uint8{4, 165, 229}, - HSL: [3]float32{197, 0.97, 0.46}, - } -} - -// Sapphire -func (latte) Sapphire() Color { - return Color{ - Hex: "#209fb5", - RGB: [3]uint8{32, 159, 181}, - HSL: [3]float32{189, 0.7, 0.42}, - } -} - -// Blue -func (latte) Blue() Color { - return Color{ - Hex: "#1e66f5", - RGB: [3]uint8{30, 102, 245}, - HSL: [3]float32{220, 0.91, 0.54}, - } -} - -// Lavender -func (latte) Lavender() Color { - return Color{ - Hex: "#7287fd", - RGB: [3]uint8{114, 135, 253}, - HSL: [3]float32{231, 0.97, 0.72}, - } -} - -// Text -func (latte) Text() Color { - return Color{ - Hex: "#4c4f69", - RGB: [3]uint8{76, 79, 105}, - HSL: [3]float32{234, 0.16, 0.35}, - } -} - -// Subtext 1 -func (latte) Subtext1() Color { - return Color{ - Hex: "#5c5f77", - RGB: [3]uint8{92, 95, 119}, - HSL: [3]float32{233, 0.13, 0.41}, - } -} - -// Subtext 0 -func (latte) Subtext0() Color { - return Color{ - Hex: "#6c6f85", - RGB: [3]uint8{108, 111, 133}, - HSL: [3]float32{233, 0.1, 0.47}, - } -} - -// Overlay 2 -func (latte) Overlay2() Color { - return Color{ - Hex: "#7c7f93", - RGB: [3]uint8{124, 127, 147}, - HSL: [3]float32{232, 0.1, 0.53}, - } -} - -// Overlay 1 -func (latte) Overlay1() Color { - return Color{ - Hex: "#8c8fa1", - RGB: [3]uint8{140, 143, 161}, - HSL: [3]float32{231, 0.1, 0.59}, - } -} - -// Overlay 0 -func (latte) Overlay0() Color { - return Color{ - Hex: "#9ca0b0", - RGB: [3]uint8{156, 160, 176}, - HSL: [3]float32{228, 0.11, 0.65}, - } -} - -// Surface 2 -func (latte) Surface2() Color { - return Color{ - Hex: "#acb0be", - RGB: [3]uint8{172, 176, 190}, - HSL: [3]float32{227, 0.12, 0.71}, - } -} - -// Surface 1 -func (latte) Surface1() Color { - return Color{ - Hex: "#bcc0cc", - RGB: [3]uint8{188, 192, 204}, - HSL: [3]float32{225, 0.14, 0.77}, - } -} - -// Surface 0 -func (latte) Surface0() Color { - return Color{ - Hex: "#ccd0da", - RGB: [3]uint8{204, 208, 218}, - HSL: [3]float32{223, 0.16, 0.83}, - } -} - -// Base -func (latte) Base() Color { - return Color{ - Hex: "#eff1f5", - RGB: [3]uint8{239, 241, 245}, - HSL: [3]float32{220, 0.23, 0.95}, - } -} - -// Mantle -func (latte) Mantle() Color { - return Color{ - Hex: "#e6e9ef", - RGB: [3]uint8{230, 233, 239}, - HSL: [3]float32{220, 0.22, 0.92}, - } -} - -// Crust -func (latte) Crust() Color { - return Color{ - Hex: "#dce0e8", - RGB: [3]uint8{220, 224, 232}, - HSL: [3]float32{220, 0.21, 0.89}, - } -} diff --git a/vendor/github.com/catppuccin/go/macchiato.go b/vendor/github.com/catppuccin/go/macchiato.go deleted file mode 100644 index 8709fd4c..00000000 --- a/vendor/github.com/catppuccin/go/macchiato.go +++ /dev/null @@ -1,244 +0,0 @@ -package catppuccingo - -// Macchiato variant -type macchiato struct{} - -// Macchiato flavor variant -var Macchiato Flavor = macchiato{} - -// Macchiato -func (macchiato) Name() string { return "macchiato" } - -// Rosewater -func (macchiato) Rosewater() Color { - return Color{ - Hex: "#f4dbd6", - RGB: [3]uint8{244, 219, 214}, - HSL: [3]float32{10, 0.58, 0.9}, - } -} - -// Flamingo -func (macchiato) Flamingo() Color { - return Color{ - Hex: "#f0c6c6", - RGB: [3]uint8{240, 198, 198}, - HSL: [3]float32{0, 0.58, 0.86}, - } -} - -// Pink -func (macchiato) Pink() Color { - return Color{ - Hex: "#f5bde6", - RGB: [3]uint8{245, 189, 230}, - HSL: [3]float32{316, 0.74, 0.85}, - } -} - -// Mauve -func (macchiato) Mauve() Color { - return Color{ - Hex: "#c6a0f6", - RGB: [3]uint8{198, 160, 246}, - HSL: [3]float32{267, 0.83, 0.8}, - } -} - -// Red -func (macchiato) Red() Color { - return Color{ - Hex: "#ed8796", - RGB: [3]uint8{237, 135, 150}, - HSL: [3]float32{351, 0.74, 0.73}, - } -} - -// Maroon -func (macchiato) Maroon() Color { - return Color{ - Hex: "#ee99a0", - RGB: [3]uint8{238, 153, 160}, - HSL: [3]float32{355, 0.71, 0.77}, - } -} - -// Peach -func (macchiato) Peach() Color { - return Color{ - Hex: "#f5a97f", - RGB: [3]uint8{245, 169, 127}, - HSL: [3]float32{21, 0.86, 0.73}, - } -} - -// Yellow -func (macchiato) Yellow() Color { - return Color{ - Hex: "#eed49f", - RGB: [3]uint8{238, 212, 159}, - HSL: [3]float32{40, 0.7, 0.78}, - } -} - -// Green -func (macchiato) Green() Color { - return Color{ - Hex: "#a6da95", - RGB: [3]uint8{166, 218, 149}, - HSL: [3]float32{105, 0.48, 0.72}, - } -} - -// Teal -func (macchiato) Teal() Color { - return Color{ - Hex: "#8bd5ca", - RGB: [3]uint8{139, 213, 202}, - HSL: [3]float32{171, 0.47, 0.69}, - } -} - -// Sky -func (macchiato) Sky() Color { - return Color{ - Hex: "#91d7e3", - RGB: [3]uint8{145, 215, 227}, - HSL: [3]float32{189, 0.59, 0.73}, - } -} - -// Sapphire -func (macchiato) Sapphire() Color { - return Color{ - Hex: "#7dc4e4", - RGB: [3]uint8{125, 196, 228}, - HSL: [3]float32{199, 0.66, 0.69}, - } -} - -// Blue -func (macchiato) Blue() Color { - return Color{ - Hex: "#8aadf4", - RGB: [3]uint8{138, 173, 244}, - HSL: [3]float32{220, 0.83, 0.75}, - } -} - -// Lavender -func (macchiato) Lavender() Color { - return Color{ - Hex: "#b7bdf8", - RGB: [3]uint8{183, 189, 248}, - HSL: [3]float32{234, 0.82, 0.85}, - } -} - -// Text -func (macchiato) Text() Color { - return Color{ - Hex: "#cad3f5", - RGB: [3]uint8{202, 211, 245}, - HSL: [3]float32{227, 0.68, 0.88}, - } -} - -// Subtext 1 -func (macchiato) Subtext1() Color { - return Color{ - Hex: "#b8c0e0", - RGB: [3]uint8{184, 192, 224}, - HSL: [3]float32{228, 0.39, 0.8}, - } -} - -// Subtext 0 -func (macchiato) Subtext0() Color { - return Color{ - Hex: "#a5adcb", - RGB: [3]uint8{165, 173, 203}, - HSL: [3]float32{227, 0.27, 0.72}, - } -} - -// Overlay 2 -func (macchiato) Overlay2() Color { - return Color{ - Hex: "#939ab7", - RGB: [3]uint8{147, 154, 183}, - HSL: [3]float32{228, 0.2, 0.65}, - } -} - -// Overlay 1 -func (macchiato) Overlay1() Color { - return Color{ - Hex: "#8087a2", - RGB: [3]uint8{128, 135, 162}, - HSL: [3]float32{228, 0.15, 0.57}, - } -} - -// Overlay 0 -func (macchiato) Overlay0() Color { - return Color{ - Hex: "#6e738d", - RGB: [3]uint8{110, 115, 141}, - HSL: [3]float32{230, 0.12, 0.49}, - } -} - -// Surface 2 -func (macchiato) Surface2() Color { - return Color{ - Hex: "#5b6078", - RGB: [3]uint8{91, 96, 120}, - HSL: [3]float32{230, 0.14, 0.41}, - } -} - -// Surface 1 -func (macchiato) Surface1() Color { - return Color{ - Hex: "#494d64", - RGB: [3]uint8{73, 77, 100}, - HSL: [3]float32{231, 0.16, 0.34}, - } -} - -// Surface 0 -func (macchiato) Surface0() Color { - return Color{ - Hex: "#363a4f", - RGB: [3]uint8{54, 58, 79}, - HSL: [3]float32{230, 0.19, 0.26}, - } -} - -// Base -func (macchiato) Base() Color { - return Color{ - Hex: "#24273a", - RGB: [3]uint8{36, 39, 58}, - HSL: [3]float32{232, 0.23, 0.18}, - } -} - -// Mantle -func (macchiato) Mantle() Color { - return Color{ - Hex: "#1e2030", - RGB: [3]uint8{30, 32, 48}, - HSL: [3]float32{233, 0.23, 0.15}, - } -} - -// Crust -func (macchiato) Crust() Color { - return Color{ - Hex: "#181926", - RGB: [3]uint8{24, 25, 38}, - HSL: [3]float32{236, 0.23, 0.12}, - } -} diff --git a/vendor/github.com/catppuccin/go/main.go b/vendor/github.com/catppuccin/go/main.go deleted file mode 100644 index 96760fa1..00000000 --- a/vendor/github.com/catppuccin/go/main.go +++ /dev/null @@ -1,81 +0,0 @@ -//go:generate whiskers go.tera -//go:generate go fmt ./... -package catppuccingo - -import ( - "image/color" - "strings" -) - -// Flavor is an interface implemented by all Catppuccin variations. -type Flavor interface { - Rosewater() Color - Flamingo() Color - Pink() Color - Mauve() Color - Red() Color - Maroon() Color - Peach() Color - Yellow() Color - Green() Color - Teal() Color - Sky() Color - Sapphire() Color - Blue() Color - Lavender() Color - Text() Color - Subtext1() Color - Subtext0() Color - Overlay2() Color - Overlay1() Color - Overlay0() Color - Surface2() Color - Surface1() Color - Surface0() Color - Crust() Color - Mantle() Color - Base() Color - Name() string -} - -// Theme and Flavour are type aliases of Flavor to keep compatibility with previous versions. -type ( - Theme = Flavour - Flavour = Flavor -) - -// Color is a color in Hex, RGB, and HSL. -type Color struct { - Hex string - RGB [3]uint8 - HSL [3]float32 -} - -// RGBA implements color.Color -func (c Color) RGBA() (r, g, b, a uint32) { - r = uint32(c.RGB[0]) - r |= r << 8 - g = uint32(c.RGB[1]) - g |= g << 8 - b = uint32(c.RGB[2]) - b |= b << 8 - a = 0xffff - return -} - -var _ color.Color = Color{} - -// Variant returns the Theme variant by name. -func Variant(flavor string) Theme { - for _, t := range []Theme{ - Mocha, - Frappe, - Macchiato, - Latte, - } { - if strings.EqualFold(t.Name(), flavor) { - return t - } - } - return nil -} diff --git a/vendor/github.com/catppuccin/go/mocha.go b/vendor/github.com/catppuccin/go/mocha.go deleted file mode 100644 index 0490abfd..00000000 --- a/vendor/github.com/catppuccin/go/mocha.go +++ /dev/null @@ -1,244 +0,0 @@ -package catppuccingo - -// Mocha variant -type mocha struct{} - -// Mocha flavor variant -var Mocha Flavor = mocha{} - -// Mocha -func (mocha) Name() string { return "mocha" } - -// Rosewater -func (mocha) Rosewater() Color { - return Color{ - Hex: "#f5e0dc", - RGB: [3]uint8{245, 224, 220}, - HSL: [3]float32{10, 0.56, 0.91}, - } -} - -// Flamingo -func (mocha) Flamingo() Color { - return Color{ - Hex: "#f2cdcd", - RGB: [3]uint8{242, 205, 205}, - HSL: [3]float32{0, 0.59, 0.88}, - } -} - -// Pink -func (mocha) Pink() Color { - return Color{ - Hex: "#f5c2e7", - RGB: [3]uint8{245, 194, 231}, - HSL: [3]float32{316, 0.72, 0.86}, - } -} - -// Mauve -func (mocha) Mauve() Color { - return Color{ - Hex: "#cba6f7", - RGB: [3]uint8{203, 166, 247}, - HSL: [3]float32{267, 0.84, 0.81}, - } -} - -// Red -func (mocha) Red() Color { - return Color{ - Hex: "#f38ba8", - RGB: [3]uint8{243, 139, 168}, - HSL: [3]float32{343, 0.81, 0.75}, - } -} - -// Maroon -func (mocha) Maroon() Color { - return Color{ - Hex: "#eba0ac", - RGB: [3]uint8{235, 160, 172}, - HSL: [3]float32{350, 0.65, 0.77}, - } -} - -// Peach -func (mocha) Peach() Color { - return Color{ - Hex: "#fab387", - RGB: [3]uint8{250, 179, 135}, - HSL: [3]float32{23, 0.92, 0.75}, - } -} - -// Yellow -func (mocha) Yellow() Color { - return Color{ - Hex: "#f9e2af", - RGB: [3]uint8{249, 226, 175}, - HSL: [3]float32{41, 0.86, 0.83}, - } -} - -// Green -func (mocha) Green() Color { - return Color{ - Hex: "#a6e3a1", - RGB: [3]uint8{166, 227, 161}, - HSL: [3]float32{115, 0.54, 0.76}, - } -} - -// Teal -func (mocha) Teal() Color { - return Color{ - Hex: "#94e2d5", - RGB: [3]uint8{148, 226, 213}, - HSL: [3]float32{170, 0.57, 0.73}, - } -} - -// Sky -func (mocha) Sky() Color { - return Color{ - Hex: "#89dceb", - RGB: [3]uint8{137, 220, 235}, - HSL: [3]float32{189, 0.71, 0.73}, - } -} - -// Sapphire -func (mocha) Sapphire() Color { - return Color{ - Hex: "#74c7ec", - RGB: [3]uint8{116, 199, 236}, - HSL: [3]float32{199, 0.76, 0.69}, - } -} - -// Blue -func (mocha) Blue() Color { - return Color{ - Hex: "#89b4fa", - RGB: [3]uint8{137, 180, 250}, - HSL: [3]float32{217, 0.92, 0.76}, - } -} - -// Lavender -func (mocha) Lavender() Color { - return Color{ - Hex: "#b4befe", - RGB: [3]uint8{180, 190, 254}, - HSL: [3]float32{232, 0.97, 0.85}, - } -} - -// Text -func (mocha) Text() Color { - return Color{ - Hex: "#cdd6f4", - RGB: [3]uint8{205, 214, 244}, - HSL: [3]float32{226, 0.64, 0.88}, - } -} - -// Subtext 1 -func (mocha) Subtext1() Color { - return Color{ - Hex: "#bac2de", - RGB: [3]uint8{186, 194, 222}, - HSL: [3]float32{227, 0.35, 0.8}, - } -} - -// Subtext 0 -func (mocha) Subtext0() Color { - return Color{ - Hex: "#a6adc8", - RGB: [3]uint8{166, 173, 200}, - HSL: [3]float32{228, 0.24, 0.72}, - } -} - -// Overlay 2 -func (mocha) Overlay2() Color { - return Color{ - Hex: "#9399b2", - RGB: [3]uint8{147, 153, 178}, - HSL: [3]float32{228, 0.17, 0.64}, - } -} - -// Overlay 1 -func (mocha) Overlay1() Color { - return Color{ - Hex: "#7f849c", - RGB: [3]uint8{127, 132, 156}, - HSL: [3]float32{230, 0.13, 0.55}, - } -} - -// Overlay 0 -func (mocha) Overlay0() Color { - return Color{ - Hex: "#6c7086", - RGB: [3]uint8{108, 112, 134}, - HSL: [3]float32{231, 0.11, 0.47}, - } -} - -// Surface 2 -func (mocha) Surface2() Color { - return Color{ - Hex: "#585b70", - RGB: [3]uint8{88, 91, 112}, - HSL: [3]float32{233, 0.12, 0.39}, - } -} - -// Surface 1 -func (mocha) Surface1() Color { - return Color{ - Hex: "#45475a", - RGB: [3]uint8{69, 71, 90}, - HSL: [3]float32{234, 0.13, 0.31}, - } -} - -// Surface 0 -func (mocha) Surface0() Color { - return Color{ - Hex: "#313244", - RGB: [3]uint8{49, 50, 68}, - HSL: [3]float32{237, 0.16, 0.23}, - } -} - -// Base -func (mocha) Base() Color { - return Color{ - Hex: "#1e1e2e", - RGB: [3]uint8{30, 30, 46}, - HSL: [3]float32{240, 0.21, 0.15}, - } -} - -// Mantle -func (mocha) Mantle() Color { - return Color{ - Hex: "#181825", - RGB: [3]uint8{24, 24, 37}, - HSL: [3]float32{240, 0.21, 0.12}, - } -} - -// Crust -func (mocha) Crust() Color { - return Color{ - Hex: "#11111b", - RGB: [3]uint8{17, 17, 27}, - HSL: [3]float32{240, 0.23, 0.09}, - } -} diff --git a/vendor/github.com/catppuccin/go/renovate.json b/vendor/github.com/catppuccin/go/renovate.json deleted file mode 100644 index a2220005..00000000 --- a/vendor/github.com/catppuccin/go/renovate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "local>catppuccin/renovate-config" - ] -} diff --git a/vendor/github.com/cenkalti/backoff/v4/.gitignore b/vendor/github.com/cenkalti/backoff/v4/.gitignore deleted file mode 100644 index 50d95c54..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -# IDEs -.idea/ diff --git a/vendor/github.com/cenkalti/backoff/v4/LICENSE b/vendor/github.com/cenkalti/backoff/v4/LICENSE deleted file mode 100644 index 89b81799..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Cenk Altı - -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/cenkalti/backoff/v4/README.md b/vendor/github.com/cenkalti/backoff/v4/README.md deleted file mode 100644 index 9433004a..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Coverage Status][coveralls image]][coveralls] - -This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. - -[Exponential backoff][exponential backoff wiki] -is an algorithm that uses feedback to multiplicatively decrease the rate of some process, -in order to gradually find an acceptable rate. -The retries exponentially increase and stop increasing when a certain threshold is met. - -## Usage - -Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end. - -Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation. - -## Contributing - -* I would like to keep this library as small as possible. -* Please don't send a PR without opening an issue and discussing it first. -* If proposed change is not a common use case, I will probably not accept it. - -[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4 -[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png -[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master -[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master - -[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java -[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff - -[advanced example]: https://pkg.go.dev/github.com/cenkalti/backoff/v4?tab=doc#pkg-examples diff --git a/vendor/github.com/cenkalti/backoff/v4/backoff.go b/vendor/github.com/cenkalti/backoff/v4/backoff.go deleted file mode 100644 index 3676ee40..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/backoff.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package backoff implements backoff algorithms for retrying operations. -// -// Use Retry function for retrying operations that may fail. -// If Retry does not meet your needs, -// copy/paste the function into your project and modify as you wish. -// -// There is also Ticker type similar to time.Ticker. -// You can use it if you need to work with channels. -// -// See Examples section below for usage examples. -package backoff - -import "time" - -// BackOff is a backoff policy for retrying an operation. -type BackOff interface { - // NextBackOff returns the duration to wait before retrying the operation, - // or backoff. Stop to indicate that no more retries should be made. - // - // Example usage: - // - // duration := backoff.NextBackOff(); - // if (duration == backoff.Stop) { - // // Do not retry operation. - // } else { - // // Sleep for duration and retry operation. - // } - // - NextBackOff() time.Duration - - // Reset to initial state. - Reset() -} - -// Stop indicates that no more retries should be made for use in NextBackOff(). -const Stop time.Duration = -1 - -// ZeroBackOff is a fixed backoff policy whose backoff time is always zero, -// meaning that the operation is retried immediately without waiting, indefinitely. -type ZeroBackOff struct{} - -func (b *ZeroBackOff) Reset() {} - -func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } - -// StopBackOff is a fixed backoff policy that always returns backoff.Stop for -// NextBackOff(), meaning that the operation should never be retried. -type StopBackOff struct{} - -func (b *StopBackOff) Reset() {} - -func (b *StopBackOff) NextBackOff() time.Duration { return Stop } - -// ConstantBackOff is a backoff policy that always returns the same backoff delay. -// This is in contrast to an exponential backoff policy, -// which returns a delay that grows longer as you call NextBackOff() over and over again. -type ConstantBackOff struct { - Interval time.Duration -} - -func (b *ConstantBackOff) Reset() {} -func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } - -func NewConstantBackOff(d time.Duration) *ConstantBackOff { - return &ConstantBackOff{Interval: d} -} diff --git a/vendor/github.com/cenkalti/backoff/v4/context.go b/vendor/github.com/cenkalti/backoff/v4/context.go deleted file mode 100644 index 48482330..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/context.go +++ /dev/null @@ -1,62 +0,0 @@ -package backoff - -import ( - "context" - "time" -) - -// BackOffContext is a backoff policy that stops retrying after the context -// is canceled. -type BackOffContext interface { // nolint: golint - BackOff - Context() context.Context -} - -type backOffContext struct { - BackOff - ctx context.Context -} - -// WithContext returns a BackOffContext with context ctx -// -// ctx must not be nil -func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint - if ctx == nil { - panic("nil context") - } - - if b, ok := b.(*backOffContext); ok { - return &backOffContext{ - BackOff: b.BackOff, - ctx: ctx, - } - } - - return &backOffContext{ - BackOff: b, - ctx: ctx, - } -} - -func getContext(b BackOff) context.Context { - if cb, ok := b.(BackOffContext); ok { - return cb.Context() - } - if tb, ok := b.(*backOffTries); ok { - return getContext(tb.delegate) - } - return context.Background() -} - -func (b *backOffContext) Context() context.Context { - return b.ctx -} - -func (b *backOffContext) NextBackOff() time.Duration { - select { - case <-b.ctx.Done(): - return Stop - default: - return b.BackOff.NextBackOff() - } -} diff --git a/vendor/github.com/cenkalti/backoff/v4/exponential.go b/vendor/github.com/cenkalti/backoff/v4/exponential.go deleted file mode 100644 index aac99f19..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/exponential.go +++ /dev/null @@ -1,216 +0,0 @@ -package backoff - -import ( - "math/rand" - "time" -) - -/* -ExponentialBackOff is a backoff implementation that increases the backoff -period for each retry attempt using a randomization function that grows exponentially. - -NextBackOff() is calculated using the following formula: - - randomized interval = - RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) - -In other words NextBackOff() will range between the randomization factor -percentage below and above the retry interval. - -For example, given the following parameters: - - RetryInterval = 2 - RandomizationFactor = 0.5 - Multiplier = 2 - -the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, -multiplied by the exponential, that is, between 2 and 6 seconds. - -Note: MaxInterval caps the RetryInterval and not the randomized interval. - -If the time elapsed since an ExponentialBackOff instance is created goes past the -MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop. - -The elapsed time can be reset by calling Reset(). - -Example: Given the following default arguments, for 10 tries the sequence will be, -and assuming we go over the MaxElapsedTime on the 10th try: - - Request # RetryInterval (seconds) Randomized Interval (seconds) - - 1 0.5 [0.25, 0.75] - 2 0.75 [0.375, 1.125] - 3 1.125 [0.562, 1.687] - 4 1.687 [0.8435, 2.53] - 5 2.53 [1.265, 3.795] - 6 3.795 [1.897, 5.692] - 7 5.692 [2.846, 8.538] - 8 8.538 [4.269, 12.807] - 9 12.807 [6.403, 19.210] - 10 19.210 backoff.Stop - -Note: Implementation is not thread-safe. -*/ -type ExponentialBackOff struct { - InitialInterval time.Duration - RandomizationFactor float64 - Multiplier float64 - MaxInterval time.Duration - // After MaxElapsedTime the ExponentialBackOff returns Stop. - // It never stops if MaxElapsedTime == 0. - MaxElapsedTime time.Duration - Stop time.Duration - Clock Clock - - currentInterval time.Duration - startTime time.Time -} - -// Clock is an interface that returns current time for BackOff. -type Clock interface { - Now() time.Time -} - -// ExponentialBackOffOpts is a function type used to configure ExponentialBackOff options. -type ExponentialBackOffOpts func(*ExponentialBackOff) - -// Default values for ExponentialBackOff. -const ( - DefaultInitialInterval = 500 * time.Millisecond - DefaultRandomizationFactor = 0.5 - DefaultMultiplier = 1.5 - DefaultMaxInterval = 60 * time.Second - DefaultMaxElapsedTime = 15 * time.Minute -) - -// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. -func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff { - b := &ExponentialBackOff{ - InitialInterval: DefaultInitialInterval, - RandomizationFactor: DefaultRandomizationFactor, - Multiplier: DefaultMultiplier, - MaxInterval: DefaultMaxInterval, - MaxElapsedTime: DefaultMaxElapsedTime, - Stop: Stop, - Clock: SystemClock, - } - for _, fn := range opts { - fn(b) - } - b.Reset() - return b -} - -// WithInitialInterval sets the initial interval between retries. -func WithInitialInterval(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.InitialInterval = duration - } -} - -// WithRandomizationFactor sets the randomization factor to add jitter to intervals. -func WithRandomizationFactor(randomizationFactor float64) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.RandomizationFactor = randomizationFactor - } -} - -// WithMultiplier sets the multiplier for increasing the interval after each retry. -func WithMultiplier(multiplier float64) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.Multiplier = multiplier - } -} - -// WithMaxInterval sets the maximum interval between retries. -func WithMaxInterval(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.MaxInterval = duration - } -} - -// WithMaxElapsedTime sets the maximum total time for retries. -func WithMaxElapsedTime(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.MaxElapsedTime = duration - } -} - -// WithRetryStopDuration sets the duration after which retries should stop. -func WithRetryStopDuration(duration time.Duration) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.Stop = duration - } -} - -// WithClockProvider sets the clock used to measure time. -func WithClockProvider(clock Clock) ExponentialBackOffOpts { - return func(ebo *ExponentialBackOff) { - ebo.Clock = clock - } -} - -type systemClock struct{} - -func (t systemClock) Now() time.Time { - return time.Now() -} - -// SystemClock implements Clock interface that uses time.Now(). -var SystemClock = systemClock{} - -// Reset the interval back to the initial retry interval and restarts the timer. -// Reset must be called before using b. -func (b *ExponentialBackOff) Reset() { - b.currentInterval = b.InitialInterval - b.startTime = b.Clock.Now() -} - -// NextBackOff calculates the next backoff interval using the formula: -// Randomized interval = RetryInterval * (1 ± RandomizationFactor) -func (b *ExponentialBackOff) NextBackOff() time.Duration { - // Make sure we have not gone over the maximum elapsed time. - elapsed := b.GetElapsedTime() - next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) - b.incrementCurrentInterval() - if b.MaxElapsedTime != 0 && elapsed+next > b.MaxElapsedTime { - return b.Stop - } - return next -} - -// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance -// is created and is reset when Reset() is called. -// -// The elapsed time is computed using time.Now().UnixNano(). It is -// safe to call even while the backoff policy is used by a running -// ticker. -func (b *ExponentialBackOff) GetElapsedTime() time.Duration { - return b.Clock.Now().Sub(b.startTime) -} - -// Increments the current interval by multiplying it with the multiplier. -func (b *ExponentialBackOff) incrementCurrentInterval() { - // Check for overflow, if overflow is detected set the current interval to the max interval. - if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { - b.currentInterval = b.MaxInterval - } else { - b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) - } -} - -// Returns a random value from the following interval: -// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval]. -func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { - if randomizationFactor == 0 { - return currentInterval // make sure no randomness is used when randomizationFactor is 0. - } - var delta = randomizationFactor * float64(currentInterval) - var minInterval = float64(currentInterval) - delta - var maxInterval = float64(currentInterval) + delta - - // Get a random value from the range [minInterval, maxInterval]. - // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then - // we want a 33% chance for selecting either 1, 2 or 3. - return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) -} diff --git a/vendor/github.com/cenkalti/backoff/v4/retry.go b/vendor/github.com/cenkalti/backoff/v4/retry.go deleted file mode 100644 index b9c0c51c..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/retry.go +++ /dev/null @@ -1,146 +0,0 @@ -package backoff - -import ( - "errors" - "time" -) - -// An OperationWithData is executing by RetryWithData() or RetryNotifyWithData(). -// The operation will be retried using a backoff policy if it returns an error. -type OperationWithData[T any] func() (T, error) - -// An Operation is executing by Retry() or RetryNotify(). -// The operation will be retried using a backoff policy if it returns an error. -type Operation func() error - -func (o Operation) withEmptyData() OperationWithData[struct{}] { - return func() (struct{}, error) { - return struct{}{}, o() - } -} - -// Notify is a notify-on-error function. It receives an operation error and -// backoff delay if the operation failed (with an error). -// -// NOTE that if the backoff policy stated to stop retrying, -// the notify function isn't called. -type Notify func(error, time.Duration) - -// Retry the operation o until it does not return error or BackOff stops. -// o is guaranteed to be run at least once. -// -// If o returns a *PermanentError, the operation is not retried, and the -// wrapped error is returned. -// -// Retry sleeps the goroutine for the duration returned by BackOff after a -// failed operation returns. -func Retry(o Operation, b BackOff) error { - return RetryNotify(o, b, nil) -} - -// RetryWithData is like Retry but returns data in the response too. -func RetryWithData[T any](o OperationWithData[T], b BackOff) (T, error) { - return RetryNotifyWithData(o, b, nil) -} - -// RetryNotify calls notify function with the error and wait duration -// for each failed attempt before sleep. -func RetryNotify(operation Operation, b BackOff, notify Notify) error { - return RetryNotifyWithTimer(operation, b, notify, nil) -} - -// RetryNotifyWithData is like RetryNotify but returns data in the response too. -func RetryNotifyWithData[T any](operation OperationWithData[T], b BackOff, notify Notify) (T, error) { - return doRetryNotify(operation, b, notify, nil) -} - -// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer -// for each failed attempt before sleep. -// A default timer that uses system timer is used when nil is passed. -func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error { - _, err := doRetryNotify(operation.withEmptyData(), b, notify, t) - return err -} - -// RetryNotifyWithTimerAndData is like RetryNotifyWithTimer but returns data in the response too. -func RetryNotifyWithTimerAndData[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) { - return doRetryNotify(operation, b, notify, t) -} - -func doRetryNotify[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) { - var ( - err error - next time.Duration - res T - ) - if t == nil { - t = &defaultTimer{} - } - - defer func() { - t.Stop() - }() - - ctx := getContext(b) - - b.Reset() - for { - res, err = operation() - if err == nil { - return res, nil - } - - var permanent *PermanentError - if errors.As(err, &permanent) { - return res, permanent.Err - } - - if next = b.NextBackOff(); next == Stop { - if cerr := ctx.Err(); cerr != nil { - return res, cerr - } - - return res, err - } - - if notify != nil { - notify(err, next) - } - - t.Start(next) - - select { - case <-ctx.Done(): - return res, ctx.Err() - case <-t.C(): - } - } -} - -// PermanentError signals that the operation should not be retried. -type PermanentError struct { - Err error -} - -func (e *PermanentError) Error() string { - return e.Err.Error() -} - -func (e *PermanentError) Unwrap() error { - return e.Err -} - -func (e *PermanentError) Is(target error) bool { - _, ok := target.(*PermanentError) - return ok -} - -// Permanent wraps the given err in a *PermanentError. -func Permanent(err error) error { - if err == nil { - return nil - } - return &PermanentError{ - Err: err, - } -} diff --git a/vendor/github.com/cenkalti/backoff/v4/ticker.go b/vendor/github.com/cenkalti/backoff/v4/ticker.go deleted file mode 100644 index df9d68bc..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/ticker.go +++ /dev/null @@ -1,97 +0,0 @@ -package backoff - -import ( - "context" - "sync" - "time" -) - -// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. -// -// Ticks will continue to arrive when the previous operation is still running, -// so operations that take a while to fail could run in quick succession. -type Ticker struct { - C <-chan time.Time - c chan time.Time - b BackOff - ctx context.Context - timer Timer - stop chan struct{} - stopOnce sync.Once -} - -// NewTicker returns a new Ticker containing a channel that will send -// the time at times specified by the BackOff argument. Ticker is -// guaranteed to tick at least once. The channel is closed when Stop -// method is called or BackOff stops. It is not safe to manipulate the -// provided backoff policy (notably calling NextBackOff or Reset) -// while the ticker is running. -func NewTicker(b BackOff) *Ticker { - return NewTickerWithTimer(b, &defaultTimer{}) -} - -// NewTickerWithTimer returns a new Ticker with a custom timer. -// A default timer that uses system timer is used when nil is passed. -func NewTickerWithTimer(b BackOff, timer Timer) *Ticker { - if timer == nil { - timer = &defaultTimer{} - } - c := make(chan time.Time) - t := &Ticker{ - C: c, - c: c, - b: b, - ctx: getContext(b), - timer: timer, - stop: make(chan struct{}), - } - t.b.Reset() - go t.run() - return t -} - -// Stop turns off a ticker. After Stop, no more ticks will be sent. -func (t *Ticker) Stop() { - t.stopOnce.Do(func() { close(t.stop) }) -} - -func (t *Ticker) run() { - c := t.c - defer close(c) - - // Ticker is guaranteed to tick at least once. - afterC := t.send(time.Now()) - - for { - if afterC == nil { - return - } - - select { - case tick := <-afterC: - afterC = t.send(tick) - case <-t.stop: - t.c = nil // Prevent future ticks from being sent to the channel. - return - case <-t.ctx.Done(): - return - } - } -} - -func (t *Ticker) send(tick time.Time) <-chan time.Time { - select { - case t.c <- tick: - case <-t.stop: - return nil - } - - next := t.b.NextBackOff() - if next == Stop { - t.Stop() - return nil - } - - t.timer.Start(next) - return t.timer.C() -} diff --git a/vendor/github.com/cenkalti/backoff/v4/timer.go b/vendor/github.com/cenkalti/backoff/v4/timer.go deleted file mode 100644 index 8120d021..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/timer.go +++ /dev/null @@ -1,35 +0,0 @@ -package backoff - -import "time" - -type Timer interface { - Start(duration time.Duration) - Stop() - C() <-chan time.Time -} - -// defaultTimer implements Timer interface using time.Timer -type defaultTimer struct { - timer *time.Timer -} - -// C returns the timers channel which receives the current time when the timer fires. -func (t *defaultTimer) C() <-chan time.Time { - return t.timer.C -} - -// Start starts the timer to fire after the given duration -func (t *defaultTimer) Start(duration time.Duration) { - if t.timer == nil { - t.timer = time.NewTimer(duration) - } else { - t.timer.Reset(duration) - } -} - -// Stop is called when the timer is not used anymore and resources may be freed. -func (t *defaultTimer) Stop() { - if t.timer != nil { - t.timer.Stop() - } -} diff --git a/vendor/github.com/cenkalti/backoff/v4/tries.go b/vendor/github.com/cenkalti/backoff/v4/tries.go deleted file mode 100644 index 28d58ca3..00000000 --- a/vendor/github.com/cenkalti/backoff/v4/tries.go +++ /dev/null @@ -1,38 +0,0 @@ -package backoff - -import "time" - -/* -WithMaxRetries creates a wrapper around another BackOff, which will -return Stop if NextBackOff() has been called too many times since -the last time Reset() was called - -Note: Implementation is not thread-safe. -*/ -func WithMaxRetries(b BackOff, max uint64) BackOff { - return &backOffTries{delegate: b, maxTries: max} -} - -type backOffTries struct { - delegate BackOff - maxTries uint64 - numTries uint64 -} - -func (b *backOffTries) NextBackOff() time.Duration { - if b.maxTries == 0 { - return Stop - } - if b.maxTries > 0 { - if b.maxTries <= b.numTries { - return Stop - } - b.numTries++ - } - return b.delegate.NextBackOff() -} - -func (b *backOffTries) Reset() { - b.numTries = 0 - b.delegate.Reset() -} diff --git a/vendor/github.com/cenkalti/backoff/v5/.gitignore b/vendor/github.com/cenkalti/backoff/v5/.gitignore deleted file mode 100644 index 50d95c54..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -# IDEs -.idea/ diff --git a/vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md b/vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md deleted file mode 100644 index 658c3743..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md +++ /dev/null @@ -1,29 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [5.0.0] - 2024-12-19 - -### Added - -- RetryAfterError can be returned from an operation to indicate how long to wait before the next retry. - -### Changed - -- Retry function now accepts additional options for specifying max number of tries and max elapsed time. -- Retry function now accepts a context.Context. -- Operation function signature changed to return result (any type) and error. - -### Removed - -- RetryNotify* and RetryWithData functions. Only single Retry function remains. -- Optional arguments from ExponentialBackoff constructor. -- Clock and Timer interfaces. - -### Fixed - -- The original error is returned from Retry if there's a PermanentError. (#144) -- The Retry function respects the wrapped PermanentError. (#140) diff --git a/vendor/github.com/cenkalti/backoff/v5/LICENSE b/vendor/github.com/cenkalti/backoff/v5/LICENSE deleted file mode 100644 index 89b81799..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Cenk Altı - -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/cenkalti/backoff/v5/README.md b/vendor/github.com/cenkalti/backoff/v5/README.md deleted file mode 100644 index 4611b1d1..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Exponential Backoff [![GoDoc][godoc image]][godoc] - -This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. - -[Exponential backoff][exponential backoff wiki] -is an algorithm that uses feedback to multiplicatively decrease the rate of some process, -in order to gradually find an acceptable rate. -The retries exponentially increase and stop increasing when a certain threshold is met. - -## Usage - -Import path is `github.com/cenkalti/backoff/v5`. Please note the version part at the end. - -For most cases, use `Retry` function. See [example_test.go][example] for an example. - -If you have specific needs, copy `Retry` function (from [retry.go][retry-src]) into your code and modify it as needed. - -## Contributing - -* I would like to keep this library as small as possible. -* Please don't send a PR without opening an issue and discussing it first. -* If proposed change is not a common use case, I will probably not accept it. - -[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v5 -[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png - -[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java -[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff - -[retry-src]: https://github.com/cenkalti/backoff/blob/v5/retry.go -[example]: https://github.com/cenkalti/backoff/blob/v5/example_test.go diff --git a/vendor/github.com/cenkalti/backoff/v5/backoff.go b/vendor/github.com/cenkalti/backoff/v5/backoff.go deleted file mode 100644 index dd2b24ca..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/backoff.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package backoff implements backoff algorithms for retrying operations. -// -// Use Retry function for retrying operations that may fail. -// If Retry does not meet your needs, -// copy/paste the function into your project and modify as you wish. -// -// There is also Ticker type similar to time.Ticker. -// You can use it if you need to work with channels. -// -// See Examples section below for usage examples. -package backoff - -import "time" - -// BackOff is a backoff policy for retrying an operation. -type BackOff interface { - // NextBackOff returns the duration to wait before retrying the operation, - // backoff.Stop to indicate that no more retries should be made. - // - // Example usage: - // - // duration := backoff.NextBackOff() - // if duration == backoff.Stop { - // // Do not retry operation. - // } else { - // // Sleep for duration and retry operation. - // } - // - NextBackOff() time.Duration - - // Reset to initial state. - Reset() -} - -// Stop indicates that no more retries should be made for use in NextBackOff(). -const Stop time.Duration = -1 - -// ZeroBackOff is a fixed backoff policy whose backoff time is always zero, -// meaning that the operation is retried immediately without waiting, indefinitely. -type ZeroBackOff struct{} - -func (b *ZeroBackOff) Reset() {} - -func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } - -// StopBackOff is a fixed backoff policy that always returns backoff.Stop for -// NextBackOff(), meaning that the operation should never be retried. -type StopBackOff struct{} - -func (b *StopBackOff) Reset() {} - -func (b *StopBackOff) NextBackOff() time.Duration { return Stop } - -// ConstantBackOff is a backoff policy that always returns the same backoff delay. -// This is in contrast to an exponential backoff policy, -// which returns a delay that grows longer as you call NextBackOff() over and over again. -type ConstantBackOff struct { - Interval time.Duration -} - -func (b *ConstantBackOff) Reset() {} -func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } - -func NewConstantBackOff(d time.Duration) *ConstantBackOff { - return &ConstantBackOff{Interval: d} -} diff --git a/vendor/github.com/cenkalti/backoff/v5/error.go b/vendor/github.com/cenkalti/backoff/v5/error.go deleted file mode 100644 index beb2b38a..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/error.go +++ /dev/null @@ -1,46 +0,0 @@ -package backoff - -import ( - "fmt" - "time" -) - -// PermanentError signals that the operation should not be retried. -type PermanentError struct { - Err error -} - -// Permanent wraps the given err in a *PermanentError. -func Permanent(err error) error { - if err == nil { - return nil - } - return &PermanentError{ - Err: err, - } -} - -// Error returns a string representation of the Permanent error. -func (e *PermanentError) Error() string { - return e.Err.Error() -} - -// Unwrap returns the wrapped error. -func (e *PermanentError) Unwrap() error { - return e.Err -} - -// RetryAfterError signals that the operation should be retried after the given duration. -type RetryAfterError struct { - Duration time.Duration -} - -// RetryAfter returns a RetryAfter error that specifies how long to wait before retrying. -func RetryAfter(seconds int) error { - return &RetryAfterError{Duration: time.Duration(seconds) * time.Second} -} - -// Error returns a string representation of the RetryAfter error. -func (e *RetryAfterError) Error() string { - return fmt.Sprintf("retry after %s", e.Duration) -} diff --git a/vendor/github.com/cenkalti/backoff/v5/exponential.go b/vendor/github.com/cenkalti/backoff/v5/exponential.go deleted file mode 100644 index 79d425e8..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/exponential.go +++ /dev/null @@ -1,118 +0,0 @@ -package backoff - -import ( - "math/rand/v2" - "time" -) - -/* -ExponentialBackOff is a backoff implementation that increases the backoff -period for each retry attempt using a randomization function that grows exponentially. - -NextBackOff() is calculated using the following formula: - - randomized interval = - RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) - -In other words NextBackOff() will range between the randomization factor -percentage below and above the retry interval. - -For example, given the following parameters: - - RetryInterval = 2 - RandomizationFactor = 0.5 - Multiplier = 2 - -the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, -multiplied by the exponential, that is, between 2 and 6 seconds. - -Note: MaxInterval caps the RetryInterval and not the randomized interval. - -Example: Given the following default arguments, for 9 tries the sequence will be: - - Request # RetryInterval (seconds) Randomized Interval (seconds) - - 1 0.5 [0.25, 0.75] - 2 0.75 [0.375, 1.125] - 3 1.125 [0.562, 1.687] - 4 1.687 [0.8435, 2.53] - 5 2.53 [1.265, 3.795] - 6 3.795 [1.897, 5.692] - 7 5.692 [2.846, 8.538] - 8 8.538 [4.269, 12.807] - 9 12.807 [6.403, 19.210] - -Note: Implementation is not thread-safe. -*/ -type ExponentialBackOff struct { - InitialInterval time.Duration - RandomizationFactor float64 - Multiplier float64 - MaxInterval time.Duration - - currentInterval time.Duration -} - -// Default values for ExponentialBackOff. -const ( - DefaultInitialInterval = 500 * time.Millisecond - DefaultRandomizationFactor = 0.5 - DefaultMultiplier = 1.5 - DefaultMaxInterval = 60 * time.Second -) - -// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. -func NewExponentialBackOff() *ExponentialBackOff { - return &ExponentialBackOff{ - InitialInterval: DefaultInitialInterval, - RandomizationFactor: DefaultRandomizationFactor, - Multiplier: DefaultMultiplier, - MaxInterval: DefaultMaxInterval, - } -} - -// Reset the interval back to the initial retry interval and restarts the timer. -// Reset must be called before using b. -func (b *ExponentialBackOff) Reset() { - b.currentInterval = b.InitialInterval -} - -// NextBackOff calculates the next backoff interval using the formula: -// -// Randomized interval = RetryInterval * (1 ± RandomizationFactor) -func (b *ExponentialBackOff) NextBackOff() time.Duration { - if b.currentInterval == 0 { - b.currentInterval = b.InitialInterval - } - - next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) - b.incrementCurrentInterval() - return next -} - -// Increments the current interval by multiplying it with the multiplier. -func (b *ExponentialBackOff) incrementCurrentInterval() { - // Check for overflow, if overflow is detected set the current interval to the max interval. - if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { - b.currentInterval = b.MaxInterval - } else { - b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) - } -} - -// Returns a random value from the following interval: -// -// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval]. -func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { - if randomizationFactor == 0 { - return currentInterval // make sure no randomness is used when randomizationFactor is 0. - } - var delta = randomizationFactor * float64(currentInterval) - var minInterval = float64(currentInterval) - delta - var maxInterval = float64(currentInterval) + delta - - // Get a random value from the range [minInterval, maxInterval]. - // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then - // we want a 33% chance for selecting either 1, 2 or 3. - return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) -} diff --git a/vendor/github.com/cenkalti/backoff/v5/retry.go b/vendor/github.com/cenkalti/backoff/v5/retry.go deleted file mode 100644 index 32a7f988..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/retry.go +++ /dev/null @@ -1,139 +0,0 @@ -package backoff - -import ( - "context" - "errors" - "time" -) - -// DefaultMaxElapsedTime sets a default limit for the total retry duration. -const DefaultMaxElapsedTime = 15 * time.Minute - -// Operation is a function that attempts an operation and may be retried. -type Operation[T any] func() (T, error) - -// Notify is a function called on operation error with the error and backoff duration. -type Notify func(error, time.Duration) - -// retryOptions holds configuration settings for the retry mechanism. -type retryOptions struct { - BackOff BackOff // Strategy for calculating backoff periods. - Timer timer // Timer to manage retry delays. - Notify Notify // Optional function to notify on each retry error. - MaxTries uint // Maximum number of retry attempts. - MaxElapsedTime time.Duration // Maximum total time for all retries. -} - -type RetryOption func(*retryOptions) - -// WithBackOff configures a custom backoff strategy. -func WithBackOff(b BackOff) RetryOption { - return func(args *retryOptions) { - args.BackOff = b - } -} - -// withTimer sets a custom timer for managing delays between retries. -func withTimer(t timer) RetryOption { - return func(args *retryOptions) { - args.Timer = t - } -} - -// WithNotify sets a notification function to handle retry errors. -func WithNotify(n Notify) RetryOption { - return func(args *retryOptions) { - args.Notify = n - } -} - -// WithMaxTries limits the number of all attempts. -func WithMaxTries(n uint) RetryOption { - return func(args *retryOptions) { - args.MaxTries = n - } -} - -// WithMaxElapsedTime limits the total duration for retry attempts. -func WithMaxElapsedTime(d time.Duration) RetryOption { - return func(args *retryOptions) { - args.MaxElapsedTime = d - } -} - -// Retry attempts the operation until success, a permanent error, or backoff completion. -// It ensures the operation is executed at least once. -// -// Returns the operation result or error if retries are exhausted or context is cancelled. -func Retry[T any](ctx context.Context, operation Operation[T], opts ...RetryOption) (T, error) { - // Initialize default retry options. - args := &retryOptions{ - BackOff: NewExponentialBackOff(), - Timer: &defaultTimer{}, - MaxElapsedTime: DefaultMaxElapsedTime, - } - - // Apply user-provided options to the default settings. - for _, opt := range opts { - opt(args) - } - - defer args.Timer.Stop() - - startedAt := time.Now() - args.BackOff.Reset() - for numTries := uint(1); ; numTries++ { - // Execute the operation. - res, err := operation() - if err == nil { - return res, nil - } - - // Stop retrying if maximum tries exceeded. - if args.MaxTries > 0 && numTries >= args.MaxTries { - return res, err - } - - // Handle permanent errors without retrying. - var permanent *PermanentError - if errors.As(err, &permanent) { - return res, permanent.Unwrap() - } - - // Stop retrying if context is cancelled. - if cerr := context.Cause(ctx); cerr != nil { - return res, cerr - } - - // Calculate next backoff duration. - next := args.BackOff.NextBackOff() - if next == Stop { - return res, err - } - - // Reset backoff if RetryAfterError is encountered. - var retryAfter *RetryAfterError - if errors.As(err, &retryAfter) { - next = retryAfter.Duration - args.BackOff.Reset() - } - - // Stop retrying if maximum elapsed time exceeded. - if args.MaxElapsedTime > 0 && time.Since(startedAt)+next > args.MaxElapsedTime { - return res, err - } - - // Notify on error if a notifier function is provided. - if args.Notify != nil { - args.Notify(err, next) - } - - // Wait for the next backoff period or context cancellation. - args.Timer.Start(next) - select { - case <-args.Timer.C(): - case <-ctx.Done(): - return res, context.Cause(ctx) - } - } -} diff --git a/vendor/github.com/cenkalti/backoff/v5/ticker.go b/vendor/github.com/cenkalti/backoff/v5/ticker.go deleted file mode 100644 index f0d4b2ae..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/ticker.go +++ /dev/null @@ -1,83 +0,0 @@ -package backoff - -import ( - "sync" - "time" -) - -// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. -// -// Ticks will continue to arrive when the previous operation is still running, -// so operations that take a while to fail could run in quick succession. -type Ticker struct { - C <-chan time.Time - c chan time.Time - b BackOff - timer timer - stop chan struct{} - stopOnce sync.Once -} - -// NewTicker returns a new Ticker containing a channel that will send -// the time at times specified by the BackOff argument. Ticker is -// guaranteed to tick at least once. The channel is closed when Stop -// method is called or BackOff stops. It is not safe to manipulate the -// provided backoff policy (notably calling NextBackOff or Reset) -// while the ticker is running. -func NewTicker(b BackOff) *Ticker { - c := make(chan time.Time) - t := &Ticker{ - C: c, - c: c, - b: b, - timer: &defaultTimer{}, - stop: make(chan struct{}), - } - t.b.Reset() - go t.run() - return t -} - -// Stop turns off a ticker. After Stop, no more ticks will be sent. -func (t *Ticker) Stop() { - t.stopOnce.Do(func() { close(t.stop) }) -} - -func (t *Ticker) run() { - c := t.c - defer close(c) - - // Ticker is guaranteed to tick at least once. - afterC := t.send(time.Now()) - - for { - if afterC == nil { - return - } - - select { - case tick := <-afterC: - afterC = t.send(tick) - case <-t.stop: - t.c = nil // Prevent future ticks from being sent to the channel. - return - } - } -} - -func (t *Ticker) send(tick time.Time) <-chan time.Time { - select { - case t.c <- tick: - case <-t.stop: - return nil - } - - next := t.b.NextBackOff() - if next == Stop { - t.Stop() - return nil - } - - t.timer.Start(next) - return t.timer.C() -} diff --git a/vendor/github.com/cenkalti/backoff/v5/timer.go b/vendor/github.com/cenkalti/backoff/v5/timer.go deleted file mode 100644 index a8953097..00000000 --- a/vendor/github.com/cenkalti/backoff/v5/timer.go +++ /dev/null @@ -1,35 +0,0 @@ -package backoff - -import "time" - -type timer interface { - Start(duration time.Duration) - Stop() - C() <-chan time.Time -} - -// defaultTimer implements Timer interface using time.Timer -type defaultTimer struct { - timer *time.Timer -} - -// C returns the timers channel which receives the current time when the timer fires. -func (t *defaultTimer) C() <-chan time.Time { - return t.timer.C -} - -// Start starts the timer to fire after the given duration -func (t *defaultTimer) Start(duration time.Duration) { - if t.timer == nil { - t.timer = time.NewTimer(duration) - } else { - t.timer.Reset(duration) - } -} - -// Stop is called when the timer is not used anymore and resources may be freed. -func (t *defaultTimer) Stop() { - if t.timer != nil { - t.timer.Stop() - } -} diff --git a/vendor/github.com/cespare/xxhash/v2/LICENSE.txt b/vendor/github.com/cespare/xxhash/v2/LICENSE.txt deleted file mode 100644 index 24b53065..00000000 --- a/vendor/github.com/cespare/xxhash/v2/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2016 Caleb Spare - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md deleted file mode 100644 index 33c88305..00000000 --- a/vendor/github.com/cespare/xxhash/v2/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# xxhash - -[![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2) -[![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml) - -xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a -high-quality hashing algorithm that is much faster than anything in the Go -standard library. - -This package provides a straightforward API: - -``` -func Sum64(b []byte) uint64 -func Sum64String(s string) uint64 -type Digest struct{ ... } - func New() *Digest -``` - -The `Digest` type implements hash.Hash64. Its key methods are: - -``` -func (*Digest) Write([]byte) (int, error) -func (*Digest) WriteString(string) (int, error) -func (*Digest) Sum64() uint64 -``` - -The package is written with optimized pure Go and also contains even faster -assembly implementations for amd64 and arm64. If desired, the `purego` build tag -opts into using the Go code even on those architectures. - -[xxHash]: http://cyan4973.github.io/xxHash/ - -## Compatibility - -This package is in a module and the latest code is in version 2 of the module. -You need a version of Go with at least "minimal module compatibility" to use -github.com/cespare/xxhash/v2: - -* 1.9.7+ for Go 1.9 -* 1.10.3+ for Go 1.10 -* Go 1.11 or later - -I recommend using the latest release of Go. - -## Benchmarks - -Here are some quick benchmarks comparing the pure-Go and assembly -implementations of Sum64. - -| input size | purego | asm | -| ---------- | --------- | --------- | -| 4 B | 1.3 GB/s | 1.2 GB/s | -| 16 B | 2.9 GB/s | 3.5 GB/s | -| 100 B | 6.9 GB/s | 8.1 GB/s | -| 4 KB | 11.7 GB/s | 16.7 GB/s | -| 10 MB | 12.0 GB/s | 17.3 GB/s | - -These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C -CPU using the following commands under Go 1.19.2: - -``` -benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$') -benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$') -``` - -## Projects using this package - -- [InfluxDB](https://github.com/influxdata/influxdb) -- [Prometheus](https://github.com/prometheus/prometheus) -- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics) -- [FreeCache](https://github.com/coocood/freecache) -- [FastCache](https://github.com/VictoriaMetrics/fastcache) -- [Ristretto](https://github.com/dgraph-io/ristretto) -- [Badger](https://github.com/dgraph-io/badger) diff --git a/vendor/github.com/cespare/xxhash/v2/testall.sh b/vendor/github.com/cespare/xxhash/v2/testall.sh deleted file mode 100644 index 94b9c443..00000000 --- a/vendor/github.com/cespare/xxhash/v2/testall.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -eu -o pipefail - -# Small convenience script for running the tests with various combinations of -# arch/tags. This assumes we're running on amd64 and have qemu available. - -go test ./... -go test -tags purego ./... -GOARCH=arm64 go test -GOARCH=arm64 go test -tags purego diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go deleted file mode 100644 index 78bddf1c..00000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash.go +++ /dev/null @@ -1,243 +0,0 @@ -// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described -// at http://cyan4973.github.io/xxHash/. -package xxhash - -import ( - "encoding/binary" - "errors" - "math/bits" -) - -const ( - prime1 uint64 = 11400714785074694791 - prime2 uint64 = 14029467366897019727 - prime3 uint64 = 1609587929392839161 - prime4 uint64 = 9650029242287828579 - prime5 uint64 = 2870177450012600261 -) - -// Store the primes in an array as well. -// -// The consts are used when possible in Go code to avoid MOVs but we need a -// contiguous array for the assembly code. -var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5} - -// Digest implements hash.Hash64. -// -// Note that a zero-valued Digest is not ready to receive writes. -// Call Reset or create a Digest using New before calling other methods. -type Digest struct { - v1 uint64 - v2 uint64 - v3 uint64 - v4 uint64 - total uint64 - mem [32]byte - n int // how much of mem is used -} - -// New creates a new Digest with a zero seed. -func New() *Digest { - return NewWithSeed(0) -} - -// NewWithSeed creates a new Digest with the given seed. -func NewWithSeed(seed uint64) *Digest { - var d Digest - d.ResetWithSeed(seed) - return &d -} - -// Reset clears the Digest's state so that it can be reused. -// It uses a seed value of zero. -func (d *Digest) Reset() { - d.ResetWithSeed(0) -} - -// ResetWithSeed clears the Digest's state so that it can be reused. -// It uses the given seed to initialize the state. -func (d *Digest) ResetWithSeed(seed uint64) { - d.v1 = seed + prime1 + prime2 - d.v2 = seed + prime2 - d.v3 = seed - d.v4 = seed - prime1 - d.total = 0 - d.n = 0 -} - -// Size always returns 8 bytes. -func (d *Digest) Size() int { return 8 } - -// BlockSize always returns 32 bytes. -func (d *Digest) BlockSize() int { return 32 } - -// Write adds more data to d. It always returns len(b), nil. -func (d *Digest) Write(b []byte) (n int, err error) { - n = len(b) - d.total += uint64(n) - - memleft := d.mem[d.n&(len(d.mem)-1):] - - if d.n+n < 32 { - // This new data doesn't even fill the current block. - copy(memleft, b) - d.n += n - return - } - - if d.n > 0 { - // Finish off the partial block. - c := copy(memleft, b) - d.v1 = round(d.v1, u64(d.mem[0:8])) - d.v2 = round(d.v2, u64(d.mem[8:16])) - d.v3 = round(d.v3, u64(d.mem[16:24])) - d.v4 = round(d.v4, u64(d.mem[24:32])) - b = b[c:] - d.n = 0 - } - - if len(b) >= 32 { - // One or more full blocks left. - nw := writeBlocks(d, b) - b = b[nw:] - } - - // Store any remaining partial block. - copy(d.mem[:], b) - d.n = len(b) - - return -} - -// Sum appends the current hash to b and returns the resulting slice. -func (d *Digest) Sum(b []byte) []byte { - s := d.Sum64() - return append( - b, - byte(s>>56), - byte(s>>48), - byte(s>>40), - byte(s>>32), - byte(s>>24), - byte(s>>16), - byte(s>>8), - byte(s), - ) -} - -// Sum64 returns the current hash. -func (d *Digest) Sum64() uint64 { - var h uint64 - - if d.total >= 32 { - v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4 - h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4) - h = mergeRound(h, v1) - h = mergeRound(h, v2) - h = mergeRound(h, v3) - h = mergeRound(h, v4) - } else { - h = d.v3 + prime5 - } - - h += d.total - - b := d.mem[:d.n&(len(d.mem)-1)] - for ; len(b) >= 8; b = b[8:] { - k1 := round(0, u64(b[:8])) - h ^= k1 - h = rol27(h)*prime1 + prime4 - } - if len(b) >= 4 { - h ^= uint64(u32(b[:4])) * prime1 - h = rol23(h)*prime2 + prime3 - b = b[4:] - } - for ; len(b) > 0; b = b[1:] { - h ^= uint64(b[0]) * prime5 - h = rol11(h) * prime1 - } - - h ^= h >> 33 - h *= prime2 - h ^= h >> 29 - h *= prime3 - h ^= h >> 32 - - return h -} - -const ( - magic = "xxh\x06" - marshaledSize = len(magic) + 8*5 + 32 -) - -// MarshalBinary implements the encoding.BinaryMarshaler interface. -func (d *Digest) MarshalBinary() ([]byte, error) { - b := make([]byte, 0, marshaledSize) - b = append(b, magic...) - b = appendUint64(b, d.v1) - b = appendUint64(b, d.v2) - b = appendUint64(b, d.v3) - b = appendUint64(b, d.v4) - b = appendUint64(b, d.total) - b = append(b, d.mem[:d.n]...) - b = b[:len(b)+len(d.mem)-d.n] - return b, nil -} - -// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -func (d *Digest) UnmarshalBinary(b []byte) error { - if len(b) < len(magic) || string(b[:len(magic)]) != magic { - return errors.New("xxhash: invalid hash state identifier") - } - if len(b) != marshaledSize { - return errors.New("xxhash: invalid hash state size") - } - b = b[len(magic):] - b, d.v1 = consumeUint64(b) - b, d.v2 = consumeUint64(b) - b, d.v3 = consumeUint64(b) - b, d.v4 = consumeUint64(b) - b, d.total = consumeUint64(b) - copy(d.mem[:], b) - d.n = int(d.total % uint64(len(d.mem))) - return nil -} - -func appendUint64(b []byte, x uint64) []byte { - var a [8]byte - binary.LittleEndian.PutUint64(a[:], x) - return append(b, a[:]...) -} - -func consumeUint64(b []byte) ([]byte, uint64) { - x := u64(b) - return b[8:], x -} - -func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) } -func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } - -func round(acc, input uint64) uint64 { - acc += input * prime2 - acc = rol31(acc) - acc *= prime1 - return acc -} - -func mergeRound(acc, val uint64) uint64 { - val = round(0, val) - acc ^= val - acc = acc*prime1 + prime4 - return acc -} - -func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) } -func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) } -func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) } -func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) } -func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) } -func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) } -func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) } -func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) } diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s deleted file mode 100644 index 3e8b1325..00000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s +++ /dev/null @@ -1,209 +0,0 @@ -//go:build !appengine && gc && !purego -// +build !appengine -// +build gc -// +build !purego - -#include "textflag.h" - -// Registers: -#define h AX -#define d AX -#define p SI // pointer to advance through b -#define n DX -#define end BX // loop end -#define v1 R8 -#define v2 R9 -#define v3 R10 -#define v4 R11 -#define x R12 -#define prime1 R13 -#define prime2 R14 -#define prime4 DI - -#define round(acc, x) \ - IMULQ prime2, x \ - ADDQ x, acc \ - ROLQ $31, acc \ - IMULQ prime1, acc - -// round0 performs the operation x = round(0, x). -#define round0(x) \ - IMULQ prime2, x \ - ROLQ $31, x \ - IMULQ prime1, x - -// mergeRound applies a merge round on the two registers acc and x. -// It assumes that prime1, prime2, and prime4 have been loaded. -#define mergeRound(acc, x) \ - round0(x) \ - XORQ x, acc \ - IMULQ prime1, acc \ - ADDQ prime4, acc - -// blockLoop processes as many 32-byte blocks as possible, -// updating v1, v2, v3, and v4. It assumes that there is at least one block -// to process. -#define blockLoop() \ -loop: \ - MOVQ +0(p), x \ - round(v1, x) \ - MOVQ +8(p), x \ - round(v2, x) \ - MOVQ +16(p), x \ - round(v3, x) \ - MOVQ +24(p), x \ - round(v4, x) \ - ADDQ $32, p \ - CMPQ p, end \ - JLE loop - -// func Sum64(b []byte) uint64 -TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 - // Load fixed primes. - MOVQ ·primes+0(SB), prime1 - MOVQ ·primes+8(SB), prime2 - MOVQ ·primes+24(SB), prime4 - - // Load slice. - MOVQ b_base+0(FP), p - MOVQ b_len+8(FP), n - LEAQ (p)(n*1), end - - // The first loop limit will be len(b)-32. - SUBQ $32, end - - // Check whether we have at least one block. - CMPQ n, $32 - JLT noBlocks - - // Set up initial state (v1, v2, v3, v4). - MOVQ prime1, v1 - ADDQ prime2, v1 - MOVQ prime2, v2 - XORQ v3, v3 - XORQ v4, v4 - SUBQ prime1, v4 - - blockLoop() - - MOVQ v1, h - ROLQ $1, h - MOVQ v2, x - ROLQ $7, x - ADDQ x, h - MOVQ v3, x - ROLQ $12, x - ADDQ x, h - MOVQ v4, x - ROLQ $18, x - ADDQ x, h - - mergeRound(h, v1) - mergeRound(h, v2) - mergeRound(h, v3) - mergeRound(h, v4) - - JMP afterBlocks - -noBlocks: - MOVQ ·primes+32(SB), h - -afterBlocks: - ADDQ n, h - - ADDQ $24, end - CMPQ p, end - JG try4 - -loop8: - MOVQ (p), x - ADDQ $8, p - round0(x) - XORQ x, h - ROLQ $27, h - IMULQ prime1, h - ADDQ prime4, h - - CMPQ p, end - JLE loop8 - -try4: - ADDQ $4, end - CMPQ p, end - JG try1 - - MOVL (p), x - ADDQ $4, p - IMULQ prime1, x - XORQ x, h - - ROLQ $23, h - IMULQ prime2, h - ADDQ ·primes+16(SB), h - -try1: - ADDQ $4, end - CMPQ p, end - JGE finalize - -loop1: - MOVBQZX (p), x - ADDQ $1, p - IMULQ ·primes+32(SB), x - XORQ x, h - ROLQ $11, h - IMULQ prime1, h - - CMPQ p, end - JL loop1 - -finalize: - MOVQ h, x - SHRQ $33, x - XORQ x, h - IMULQ prime2, h - MOVQ h, x - SHRQ $29, x - XORQ x, h - IMULQ ·primes+16(SB), h - MOVQ h, x - SHRQ $32, x - XORQ x, h - - MOVQ h, ret+24(FP) - RET - -// func writeBlocks(d *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 - // Load fixed primes needed for round. - MOVQ ·primes+0(SB), prime1 - MOVQ ·primes+8(SB), prime2 - - // Load slice. - MOVQ b_base+8(FP), p - MOVQ b_len+16(FP), n - LEAQ (p)(n*1), end - SUBQ $32, end - - // Load vN from d. - MOVQ s+0(FP), d - MOVQ 0(d), v1 - MOVQ 8(d), v2 - MOVQ 16(d), v3 - MOVQ 24(d), v4 - - // We don't need to check the loop condition here; this function is - // always called with at least one block of data to process. - blockLoop() - - // Copy vN back to d. - MOVQ v1, 0(d) - MOVQ v2, 8(d) - MOVQ v3, 16(d) - MOVQ v4, 24(d) - - // The number of bytes written is p minus the old base pointer. - SUBQ b_base+8(FP), p - MOVQ p, ret+32(FP) - - RET diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s deleted file mode 100644 index 7e3145a2..00000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s +++ /dev/null @@ -1,183 +0,0 @@ -//go:build !appengine && gc && !purego -// +build !appengine -// +build gc -// +build !purego - -#include "textflag.h" - -// Registers: -#define digest R1 -#define h R2 // return value -#define p R3 // input pointer -#define n R4 // input length -#define nblocks R5 // n / 32 -#define prime1 R7 -#define prime2 R8 -#define prime3 R9 -#define prime4 R10 -#define prime5 R11 -#define v1 R12 -#define v2 R13 -#define v3 R14 -#define v4 R15 -#define x1 R20 -#define x2 R21 -#define x3 R22 -#define x4 R23 - -#define round(acc, x) \ - MADD prime2, acc, x, acc \ - ROR $64-31, acc \ - MUL prime1, acc - -// round0 performs the operation x = round(0, x). -#define round0(x) \ - MUL prime2, x \ - ROR $64-31, x \ - MUL prime1, x - -#define mergeRound(acc, x) \ - round0(x) \ - EOR x, acc \ - MADD acc, prime4, prime1, acc - -// blockLoop processes as many 32-byte blocks as possible, -// updating v1, v2, v3, and v4. It assumes that n >= 32. -#define blockLoop() \ - LSR $5, n, nblocks \ - PCALIGN $16 \ - loop: \ - LDP.P 16(p), (x1, x2) \ - LDP.P 16(p), (x3, x4) \ - round(v1, x1) \ - round(v2, x2) \ - round(v3, x3) \ - round(v4, x4) \ - SUB $1, nblocks \ - CBNZ nblocks, loop - -// func Sum64(b []byte) uint64 -TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 - LDP b_base+0(FP), (p, n) - - LDP ·primes+0(SB), (prime1, prime2) - LDP ·primes+16(SB), (prime3, prime4) - MOVD ·primes+32(SB), prime5 - - CMP $32, n - CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 } - BLT afterLoop - - ADD prime1, prime2, v1 - MOVD prime2, v2 - MOVD $0, v3 - NEG prime1, v4 - - blockLoop() - - ROR $64-1, v1, x1 - ROR $64-7, v2, x2 - ADD x1, x2 - ROR $64-12, v3, x3 - ROR $64-18, v4, x4 - ADD x3, x4 - ADD x2, x4, h - - mergeRound(h, v1) - mergeRound(h, v2) - mergeRound(h, v3) - mergeRound(h, v4) - -afterLoop: - ADD n, h - - TBZ $4, n, try8 - LDP.P 16(p), (x1, x2) - - round0(x1) - - // NOTE: here and below, sequencing the EOR after the ROR (using a - // rotated register) is worth a small but measurable speedup for small - // inputs. - ROR $64-27, h - EOR x1 @> 64-27, h, h - MADD h, prime4, prime1, h - - round0(x2) - ROR $64-27, h - EOR x2 @> 64-27, h, h - MADD h, prime4, prime1, h - -try8: - TBZ $3, n, try4 - MOVD.P 8(p), x1 - - round0(x1) - ROR $64-27, h - EOR x1 @> 64-27, h, h - MADD h, prime4, prime1, h - -try4: - TBZ $2, n, try2 - MOVWU.P 4(p), x2 - - MUL prime1, x2 - ROR $64-23, h - EOR x2 @> 64-23, h, h - MADD h, prime3, prime2, h - -try2: - TBZ $1, n, try1 - MOVHU.P 2(p), x3 - AND $255, x3, x1 - LSR $8, x3, x2 - - MUL prime5, x1 - ROR $64-11, h - EOR x1 @> 64-11, h, h - MUL prime1, h - - MUL prime5, x2 - ROR $64-11, h - EOR x2 @> 64-11, h, h - MUL prime1, h - -try1: - TBZ $0, n, finalize - MOVBU (p), x4 - - MUL prime5, x4 - ROR $64-11, h - EOR x4 @> 64-11, h, h - MUL prime1, h - -finalize: - EOR h >> 33, h - MUL prime2, h - EOR h >> 29, h - MUL prime3, h - EOR h >> 32, h - - MOVD h, ret+24(FP) - RET - -// func writeBlocks(d *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 - LDP ·primes+0(SB), (prime1, prime2) - - // Load state. Assume v[1-4] are stored contiguously. - MOVD d+0(FP), digest - LDP 0(digest), (v1, v2) - LDP 16(digest), (v3, v4) - - LDP b_base+8(FP), (p, n) - - blockLoop() - - // Store updated state. - STP (v1, v2), 0(digest) - STP (v3, v4), 16(digest) - - BIC $31, n - MOVD n, ret+32(FP) - RET diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go deleted file mode 100644 index 78f95f25..00000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build (amd64 || arm64) && !appengine && gc && !purego -// +build amd64 arm64 -// +build !appengine -// +build gc -// +build !purego - -package xxhash - -// Sum64 computes the 64-bit xxHash digest of b with a zero seed. -// -//go:noescape -func Sum64(b []byte) uint64 - -//go:noescape -func writeBlocks(d *Digest, b []byte) int diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go deleted file mode 100644 index 118e49e8..00000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go +++ /dev/null @@ -1,76 +0,0 @@ -//go:build (!amd64 && !arm64) || appengine || !gc || purego -// +build !amd64,!arm64 appengine !gc purego - -package xxhash - -// Sum64 computes the 64-bit xxHash digest of b with a zero seed. -func Sum64(b []byte) uint64 { - // A simpler version would be - // d := New() - // d.Write(b) - // return d.Sum64() - // but this is faster, particularly for small inputs. - - n := len(b) - var h uint64 - - if n >= 32 { - v1 := primes[0] + prime2 - v2 := prime2 - v3 := uint64(0) - v4 := -primes[0] - for len(b) >= 32 { - v1 = round(v1, u64(b[0:8:len(b)])) - v2 = round(v2, u64(b[8:16:len(b)])) - v3 = round(v3, u64(b[16:24:len(b)])) - v4 = round(v4, u64(b[24:32:len(b)])) - b = b[32:len(b):len(b)] - } - h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4) - h = mergeRound(h, v1) - h = mergeRound(h, v2) - h = mergeRound(h, v3) - h = mergeRound(h, v4) - } else { - h = prime5 - } - - h += uint64(n) - - for ; len(b) >= 8; b = b[8:] { - k1 := round(0, u64(b[:8])) - h ^= k1 - h = rol27(h)*prime1 + prime4 - } - if len(b) >= 4 { - h ^= uint64(u32(b[:4])) * prime1 - h = rol23(h)*prime2 + prime3 - b = b[4:] - } - for ; len(b) > 0; b = b[1:] { - h ^= uint64(b[0]) * prime5 - h = rol11(h) * prime1 - } - - h ^= h >> 33 - h *= prime2 - h ^= h >> 29 - h *= prime3 - h ^= h >> 32 - - return h -} - -func writeBlocks(d *Digest, b []byte) int { - v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4 - n := len(b) - for len(b) >= 32 { - v1 = round(v1, u64(b[0:8:len(b)])) - v2 = round(v2, u64(b[8:16:len(b)])) - v3 = round(v3, u64(b[16:24:len(b)])) - v4 = round(v4, u64(b[24:32:len(b)])) - b = b[32:len(b):len(b)] - } - d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4 - return n - len(b) -} diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go deleted file mode 100644 index 05f5e7df..00000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build appengine -// +build appengine - -// This file contains the safe implementations of otherwise unsafe-using code. - -package xxhash - -// Sum64String computes the 64-bit xxHash digest of s with a zero seed. -func Sum64String(s string) uint64 { - return Sum64([]byte(s)) -} - -// WriteString adds more data to d. It always returns len(s), nil. -func (d *Digest) WriteString(s string) (n int, err error) { - return d.Write([]byte(s)) -} diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go deleted file mode 100644 index cf9d42ae..00000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go +++ /dev/null @@ -1,58 +0,0 @@ -//go:build !appengine -// +build !appengine - -// This file encapsulates usage of unsafe. -// xxhash_safe.go contains the safe implementations. - -package xxhash - -import ( - "unsafe" -) - -// In the future it's possible that compiler optimizations will make these -// XxxString functions unnecessary by realizing that calls such as -// Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205. -// If that happens, even if we keep these functions they can be replaced with -// the trivial safe code. - -// NOTE: The usual way of doing an unsafe string-to-[]byte conversion is: -// -// var b []byte -// bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) -// bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data -// bh.Len = len(s) -// bh.Cap = len(s) -// -// Unfortunately, as of Go 1.15.3 the inliner's cost model assigns a high enough -// weight to this sequence of expressions that any function that uses it will -// not be inlined. Instead, the functions below use a different unsafe -// conversion designed to minimize the inliner weight and allow both to be -// inlined. There is also a test (TestInlining) which verifies that these are -// inlined. -// -// See https://github.com/golang/go/issues/42739 for discussion. - -// Sum64String computes the 64-bit xxHash digest of s with a zero seed. -// It may be faster than Sum64([]byte(s)) by avoiding a copy. -func Sum64String(s string) uint64 { - b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})) - return Sum64(b) -} - -// WriteString adds more data to d. It always returns len(s), nil. -// It may be faster than Write([]byte(s)) by avoiding a copy. -func (d *Digest) WriteString(s string) (n int, err error) { - d.Write(*(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))) - // d.Write always returns len(s), nil. - // Ignoring the return output and returning these fixed values buys a - // savings of 6 in the inliner's cost model. - return len(s), nil -} - -// sliceHeader is similar to reflect.SliceHeader, but it assumes that the layout -// of the first two words is the same as the layout of a string. -type sliceHeader struct { - s string - cap int -} diff --git a/vendor/github.com/charmbracelet/bubbles/LICENSE b/vendor/github.com/charmbracelet/bubbles/LICENSE deleted file mode 100644 index 31d76c1c..00000000 --- a/vendor/github.com/charmbracelet/bubbles/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020-2023 Charmbracelet, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/charmbracelet/bubbles/cursor/cursor.go b/vendor/github.com/charmbracelet/bubbles/cursor/cursor.go deleted file mode 100644 index d101332b..00000000 --- a/vendor/github.com/charmbracelet/bubbles/cursor/cursor.go +++ /dev/null @@ -1,219 +0,0 @@ -// Package cursor provides cursor functionality for Bubble Tea applications. -package cursor - -import ( - "context" - "time" - - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const defaultBlinkSpeed = time.Millisecond * 530 - -// initialBlinkMsg initializes cursor blinking. -type initialBlinkMsg struct{} - -// BlinkMsg signals that the cursor should blink. It contains metadata that -// allows us to tell if the blink message is the one we're expecting. -type BlinkMsg struct { - id int - tag int -} - -// blinkCanceled is sent when a blink operation is canceled. -type blinkCanceled struct{} - -// blinkCtx manages cursor blinking. -type blinkCtx struct { - ctx context.Context - cancel context.CancelFunc -} - -// Mode describes the behavior of the cursor. -type Mode int - -// Available cursor modes. -const ( - CursorBlink Mode = iota - CursorStatic - CursorHide -) - -// String returns the cursor mode in a human-readable format. This method is -// provisional and for informational purposes only. -func (c Mode) String() string { - return [...]string{ - "blink", - "static", - "hidden", - }[c] -} - -// Model is the Bubble Tea model for this cursor element. -type Model struct { - BlinkSpeed time.Duration - // Style for styling the cursor block. - Style lipgloss.Style - // TextStyle is the style used for the cursor when it is hidden (when blinking). - // I.e. displaying normal text. - TextStyle lipgloss.Style - - // char is the character under the cursor - char string - // The ID of this Model as it relates to other cursors - id int - // focus indicates whether the containing input is focused - focus bool - // Cursor Blink state. - Blink bool - // Used to manage cursor blink - blinkCtx *blinkCtx - // The ID of the blink message we're expecting to receive. - blinkTag int - // mode determines the behavior of the cursor - mode Mode -} - -// New creates a new model with default settings. -func New() Model { - return Model{ - BlinkSpeed: defaultBlinkSpeed, - - Blink: true, - mode: CursorBlink, - - blinkCtx: &blinkCtx{ - ctx: context.Background(), - }, - } -} - -// Update updates the cursor. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - switch msg := msg.(type) { - case initialBlinkMsg: - // We accept all initialBlinkMsgs generated by the Blink command. - - if m.mode != CursorBlink || !m.focus { - return m, nil - } - - cmd := m.BlinkCmd() - return m, cmd - - case tea.FocusMsg: - return m, m.Focus() - - case tea.BlurMsg: - m.Blur() - return m, nil - - case BlinkMsg: - // We're choosy about whether to accept blinkMsgs so that our cursor - // only exactly when it should. - - // Is this model blink-able? - if m.mode != CursorBlink || !m.focus { - return m, nil - } - - // Were we expecting this blink message? - if msg.id != m.id || msg.tag != m.blinkTag { - return m, nil - } - - var cmd tea.Cmd - if m.mode == CursorBlink { - m.Blink = !m.Blink - cmd = m.BlinkCmd() - } - return m, cmd - - case blinkCanceled: // no-op - return m, nil - } - return m, nil -} - -// Mode returns the model's cursor mode. For available cursor modes, see -// type Mode. -func (m Model) Mode() Mode { - return m.mode -} - -// SetMode sets the model's cursor mode. This method returns a command. -// -// For available cursor modes, see type CursorMode. -func (m *Model) SetMode(mode Mode) tea.Cmd { - // Adjust the mode value if it's value is out of range - if mode < CursorBlink || mode > CursorHide { - return nil - } - m.mode = mode - m.Blink = m.mode == CursorHide || !m.focus - if mode == CursorBlink { - return Blink - } - return nil -} - -// BlinkCmd is a command used to manage cursor blinking. -func (m *Model) BlinkCmd() tea.Cmd { - if m.mode != CursorBlink { - return nil - } - - if m.blinkCtx != nil && m.blinkCtx.cancel != nil { - m.blinkCtx.cancel() - } - - ctx, cancel := context.WithTimeout(m.blinkCtx.ctx, m.BlinkSpeed) - m.blinkCtx.cancel = cancel - - m.blinkTag++ - - return func() tea.Msg { - defer cancel() - <-ctx.Done() - if ctx.Err() == context.DeadlineExceeded { - return BlinkMsg{id: m.id, tag: m.blinkTag} - } - return blinkCanceled{} - } -} - -// Blink is a command used to initialize cursor blinking. -func Blink() tea.Msg { - return initialBlinkMsg{} -} - -// Focus focuses the cursor to allow it to blink if desired. -func (m *Model) Focus() tea.Cmd { - m.focus = true - m.Blink = m.mode == CursorHide // show the cursor unless we've explicitly hidden it - - if m.mode == CursorBlink && m.focus { - return m.BlinkCmd() - } - return nil -} - -// Blur blurs the cursor. -func (m *Model) Blur() { - m.focus = false - m.Blink = true -} - -// SetChar sets the character under the cursor. -func (m *Model) SetChar(char string) { - m.char = char -} - -// View displays the cursor. -func (m Model) View() string { - if m.Blink { - return m.TextStyle.Inline(true).Render(m.char) - } - return m.Style.Inline(true).Reverse(true).Render(m.char) -} diff --git a/vendor/github.com/charmbracelet/bubbles/filepicker/filepicker.go b/vendor/github.com/charmbracelet/bubbles/filepicker/filepicker.go deleted file mode 100644 index 3898742c..00000000 --- a/vendor/github.com/charmbracelet/bubbles/filepicker/filepicker.go +++ /dev/null @@ -1,522 +0,0 @@ -// Package filepicker provides a file picker component for Bubble Tea -// applications. -package filepicker - -import ( - "fmt" - "os" - "path/filepath" - "sort" - "strconv" - "strings" - "sync/atomic" - - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/dustin/go-humanize" -) - -var lastID int64 - -func nextID() int { - return int(atomic.AddInt64(&lastID, 1)) -} - -// New returns a new filepicker model with default styling and key bindings. -func New() Model { - return Model{ - id: nextID(), - CurrentDirectory: ".", - Cursor: ">", - AllowedTypes: []string{}, - selected: 0, - ShowPermissions: true, - ShowSize: true, - ShowHidden: false, - DirAllowed: false, - FileAllowed: true, - AutoHeight: true, - Height: 0, - max: 0, - min: 0, - selectedStack: newStack(), - minStack: newStack(), - maxStack: newStack(), - KeyMap: DefaultKeyMap(), - Styles: DefaultStyles(), - } -} - -type errorMsg struct { - err error -} - -type readDirMsg struct { - id int - entries []os.DirEntry -} - -const ( - marginBottom = 5 - fileSizeWidth = 7 - paddingLeft = 2 -) - -// KeyMap defines key bindings for each user action. -type KeyMap struct { - GoToTop key.Binding - GoToLast key.Binding - Down key.Binding - Up key.Binding - PageUp key.Binding - PageDown key.Binding - Back key.Binding - Open key.Binding - Select key.Binding -} - -// DefaultKeyMap defines the default keybindings. -func DefaultKeyMap() KeyMap { - return KeyMap{ - GoToTop: key.NewBinding(key.WithKeys("g"), key.WithHelp("g", "first")), - GoToLast: key.NewBinding(key.WithKeys("G"), key.WithHelp("G", "last")), - Down: key.NewBinding(key.WithKeys("j", "down", "ctrl+n"), key.WithHelp("j", "down")), - Up: key.NewBinding(key.WithKeys("k", "up", "ctrl+p"), key.WithHelp("k", "up")), - PageUp: key.NewBinding(key.WithKeys("K", "pgup"), key.WithHelp("pgup", "page up")), - PageDown: key.NewBinding(key.WithKeys("J", "pgdown"), key.WithHelp("pgdown", "page down")), - Back: key.NewBinding(key.WithKeys("h", "backspace", "left", "esc"), key.WithHelp("h", "back")), - Open: key.NewBinding(key.WithKeys("l", "right", "enter"), key.WithHelp("l", "open")), - Select: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "select")), - } -} - -// Styles defines the possible customizations for styles in the file picker. -type Styles struct { - DisabledCursor lipgloss.Style - Cursor lipgloss.Style - Symlink lipgloss.Style - Directory lipgloss.Style - File lipgloss.Style - DisabledFile lipgloss.Style - Permission lipgloss.Style - Selected lipgloss.Style - DisabledSelected lipgloss.Style - FileSize lipgloss.Style - EmptyDirectory lipgloss.Style -} - -// DefaultStyles defines the default styling for the file picker. -func DefaultStyles() Styles { - return DefaultStylesWithRenderer(lipgloss.DefaultRenderer()) -} - -// DefaultStylesWithRenderer defines the default styling for the file picker, -// with a given Lip Gloss renderer. -func DefaultStylesWithRenderer(r *lipgloss.Renderer) Styles { - return Styles{ - DisabledCursor: r.NewStyle().Foreground(lipgloss.Color("247")), - Cursor: r.NewStyle().Foreground(lipgloss.Color("212")), - Symlink: r.NewStyle().Foreground(lipgloss.Color("36")), - Directory: r.NewStyle().Foreground(lipgloss.Color("99")), - File: r.NewStyle(), - DisabledFile: r.NewStyle().Foreground(lipgloss.Color("243")), - DisabledSelected: r.NewStyle().Foreground(lipgloss.Color("247")), - Permission: r.NewStyle().Foreground(lipgloss.Color("244")), - Selected: r.NewStyle().Foreground(lipgloss.Color("212")).Bold(true), - FileSize: r.NewStyle().Foreground(lipgloss.Color("240")).Width(fileSizeWidth).Align(lipgloss.Right), - EmptyDirectory: r.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(paddingLeft).SetString("Bummer. No Files Found."), - } -} - -// Model represents a file picker. -type Model struct { - id int - - // Path is the path which the user has selected with the file picker. - Path string - - // CurrentDirectory is the directory that the user is currently in. - CurrentDirectory string - - // AllowedTypes specifies which file types the user may select. - // If empty the user may select any file. - AllowedTypes []string - - KeyMap KeyMap - files []os.DirEntry - ShowPermissions bool - ShowSize bool - ShowHidden bool - DirAllowed bool - FileAllowed bool - - FileSelected string - selected int - selectedStack stack - - min int - max int - maxStack stack - minStack stack - - // Height of the picker. - // - // Deprecated: use [Model.SetHeight] instead. - Height int - AutoHeight bool - - Cursor string - Styles Styles -} - -type stack struct { - Push func(int) - Pop func() int - Length func() int -} - -func newStack() stack { - slice := make([]int, 0) - return stack{ - Push: func(i int) { - slice = append(slice, i) - }, - Pop: func() int { - res := slice[len(slice)-1] - slice = slice[:len(slice)-1] - return res - }, - Length: func() int { - return len(slice) - }, - } -} - -func (m *Model) pushView(selected, minimum, maximum int) { - m.selectedStack.Push(selected) - m.minStack.Push(minimum) - m.maxStack.Push(maximum) -} - -func (m *Model) popView() (int, int, int) { - return m.selectedStack.Pop(), m.minStack.Pop(), m.maxStack.Pop() -} - -func (m Model) readDir(path string, showHidden bool) tea.Cmd { - return func() tea.Msg { - dirEntries, err := os.ReadDir(path) - if err != nil { - return errorMsg{err} - } - - sort.Slice(dirEntries, func(i, j int) bool { - if dirEntries[i].IsDir() == dirEntries[j].IsDir() { - return dirEntries[i].Name() < dirEntries[j].Name() - } - return dirEntries[i].IsDir() - }) - - if showHidden { - return readDirMsg{id: m.id, entries: dirEntries} - } - - var sanitizedDirEntries []os.DirEntry - for _, dirEntry := range dirEntries { - isHidden, _ := IsHidden(dirEntry.Name()) - if isHidden { - continue - } - sanitizedDirEntries = append(sanitizedDirEntries, dirEntry) - } - return readDirMsg{id: m.id, entries: sanitizedDirEntries} - } -} - -// Init initializes the file picker model. -func (m Model) Init() tea.Cmd { - return m.readDir(m.CurrentDirectory, m.ShowHidden) -} - -// SetHeight sets the height of the filepicker. -func (m *Model) SetHeight(height int) { - m.Height = height - if m.max > m.Height-1 { - m.max = m.min + m.Height - 1 - } -} - -// Update handles user interactions within the file picker model. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - switch msg := msg.(type) { - case readDirMsg: - if msg.id != m.id { - break - } - m.files = msg.entries - m.max = max(m.max, m.Height-1) - case tea.WindowSizeMsg: - if m.AutoHeight { - m.Height = msg.Height - marginBottom - } - m.max = m.Height - 1 - case tea.KeyMsg: - switch { - case key.Matches(msg, m.KeyMap.GoToTop): - m.selected = 0 - m.min = 0 - m.max = m.Height - 1 - case key.Matches(msg, m.KeyMap.GoToLast): - m.selected = len(m.files) - 1 - m.min = len(m.files) - m.Height - m.max = len(m.files) - 1 - case key.Matches(msg, m.KeyMap.Down): - m.selected++ - if m.selected >= len(m.files) { - m.selected = len(m.files) - 1 - } - if m.selected > m.max { - m.min++ - m.max++ - } - case key.Matches(msg, m.KeyMap.Up): - m.selected-- - if m.selected < 0 { - m.selected = 0 - } - if m.selected < m.min { - m.min-- - m.max-- - } - case key.Matches(msg, m.KeyMap.PageDown): - m.selected += m.Height - if m.selected >= len(m.files) { - m.selected = len(m.files) - 1 - } - m.min += m.Height - m.max += m.Height - - if m.max >= len(m.files) { - m.max = len(m.files) - 1 - m.min = m.max - m.Height - } - case key.Matches(msg, m.KeyMap.PageUp): - m.selected -= m.Height - if m.selected < 0 { - m.selected = 0 - } - m.min -= m.Height - m.max -= m.Height - - if m.min < 0 { - m.min = 0 - m.max = m.min + m.Height - } - case key.Matches(msg, m.KeyMap.Back): - m.CurrentDirectory = filepath.Dir(m.CurrentDirectory) - if m.selectedStack.Length() > 0 { - m.selected, m.min, m.max = m.popView() - } else { - m.selected = 0 - m.min = 0 - m.max = m.Height - 1 - } - return m, m.readDir(m.CurrentDirectory, m.ShowHidden) - case key.Matches(msg, m.KeyMap.Open): - if len(m.files) == 0 { - break - } - - f := m.files[m.selected] - info, err := f.Info() - if err != nil { - break - } - isSymlink := info.Mode()&os.ModeSymlink != 0 - isDir := f.IsDir() - - if isSymlink { - symlinkPath, _ := filepath.EvalSymlinks(filepath.Join(m.CurrentDirectory, f.Name())) - info, err := os.Stat(symlinkPath) - if err != nil { - break - } - if info.IsDir() { - isDir = true - } - } - - if (!isDir && m.FileAllowed) || (isDir && m.DirAllowed) { - if key.Matches(msg, m.KeyMap.Select) { - // Select the current path as the selection - m.Path = filepath.Join(m.CurrentDirectory, f.Name()) - } - } - - if !isDir { - break - } - - m.CurrentDirectory = filepath.Join(m.CurrentDirectory, f.Name()) - m.pushView(m.selected, m.min, m.max) - m.selected = 0 - m.min = 0 - m.max = m.Height - 1 - return m, m.readDir(m.CurrentDirectory, m.ShowHidden) - } - } - return m, nil -} - -// View returns the view of the file picker. -func (m Model) View() string { - if len(m.files) == 0 { - return m.Styles.EmptyDirectory.Height(m.Height).MaxHeight(m.Height).String() - } - var s strings.Builder - - for i, f := range m.files { - if i < m.min || i > m.max { - continue - } - - var symlinkPath string - info, _ := f.Info() - isSymlink := info.Mode()&os.ModeSymlink != 0 - size := strings.Replace(humanize.Bytes(uint64(info.Size())), " ", "", 1) //nolint:gosec - name := f.Name() - - if isSymlink { - symlinkPath, _ = filepath.EvalSymlinks(filepath.Join(m.CurrentDirectory, name)) - } - - disabled := !m.canSelect(name) && !f.IsDir() - - if m.selected == i { //nolint:nestif - selected := "" - if m.ShowPermissions { - selected += " " + info.Mode().String() - } - if m.ShowSize { - selected += fmt.Sprintf("%"+strconv.Itoa(m.Styles.FileSize.GetWidth())+"s", size) - } - selected += " " + name - if isSymlink { - selected += " → " + symlinkPath - } - if disabled { - s.WriteString(m.Styles.DisabledSelected.Render(m.Cursor) + m.Styles.DisabledSelected.Render(selected)) - } else { - s.WriteString(m.Styles.Cursor.Render(m.Cursor) + m.Styles.Selected.Render(selected)) - } - s.WriteRune('\n') - continue - } - - style := m.Styles.File - if f.IsDir() { - style = m.Styles.Directory - } else if isSymlink { - style = m.Styles.Symlink - } else if disabled { - style = m.Styles.DisabledFile - } - - fileName := style.Render(name) - s.WriteString(m.Styles.Cursor.Render(" ")) - if isSymlink { - fileName += " → " + symlinkPath - } - if m.ShowPermissions { - s.WriteString(" " + m.Styles.Permission.Render(info.Mode().String())) - } - if m.ShowSize { - s.WriteString(m.Styles.FileSize.Render(size)) - } - s.WriteString(" " + fileName) - s.WriteRune('\n') - } - - for i := lipgloss.Height(s.String()); i <= m.Height; i++ { - s.WriteRune('\n') - } - - return s.String() -} - -// DidSelectFile returns whether a user has selected a file (on this msg). -func (m Model) DidSelectFile(msg tea.Msg) (bool, string) { - didSelect, path := m.didSelectFile(msg) - if didSelect && m.canSelect(path) { - return true, path - } - return false, "" -} - -// DidSelectDisabledFile returns whether a user tried to select a disabled file -// (on this msg). This is necessary only if you would like to warn the user that -// they tried to select a disabled file. -func (m Model) DidSelectDisabledFile(msg tea.Msg) (bool, string) { - didSelect, path := m.didSelectFile(msg) - if didSelect && !m.canSelect(path) { - return true, path - } - return false, "" -} - -func (m Model) didSelectFile(msg tea.Msg) (bool, string) { - if len(m.files) == 0 { - return false, "" - } - switch msg := msg.(type) { - case tea.KeyMsg: - // If the msg does not match the Select keymap then this could not have been a selection. - if !key.Matches(msg, m.KeyMap.Select) { - return false, "" - } - - // The key press was a selection, let's confirm whether the current file could - // be selected or used for navigating deeper into the stack. - f := m.files[m.selected] - info, err := f.Info() - if err != nil { - return false, "" - } - isSymlink := info.Mode()&os.ModeSymlink != 0 - isDir := f.IsDir() - - if isSymlink { - symlinkPath, _ := filepath.EvalSymlinks(filepath.Join(m.CurrentDirectory, f.Name())) - info, err := os.Stat(symlinkPath) - if err != nil { - break - } - if info.IsDir() { - isDir = true - } - } - - if (!isDir && m.FileAllowed) || (isDir && m.DirAllowed) && m.Path != "" { - return true, m.Path - } - - // If the msg was not a KeyMsg, then the file could not have been selected this iteration. - // Only a KeyMsg can select a file. - default: - return false, "" - } - return false, "" -} - -func (m Model) canSelect(file string) bool { - if len(m.AllowedTypes) <= 0 { - return true - } - - for _, ext := range m.AllowedTypes { - if strings.HasSuffix(file, ext) { - return true - } - } - return false -} diff --git a/vendor/github.com/charmbracelet/bubbles/filepicker/hidden_unix.go b/vendor/github.com/charmbracelet/bubbles/filepicker/hidden_unix.go deleted file mode 100644 index f611d0e1..00000000 --- a/vendor/github.com/charmbracelet/bubbles/filepicker/hidden_unix.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !windows -// +build !windows - -package filepicker - -import "strings" - -// IsHidden reports whether a file is hidden or not. -func IsHidden(file string) (bool, error) { - return strings.HasPrefix(file, "."), nil -} diff --git a/vendor/github.com/charmbracelet/bubbles/filepicker/hidden_windows.go b/vendor/github.com/charmbracelet/bubbles/filepicker/hidden_windows.go deleted file mode 100644 index b5f81265..00000000 --- a/vendor/github.com/charmbracelet/bubbles/filepicker/hidden_windows.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build windows -// +build windows - -package filepicker - -import ( - "syscall" -) - -// IsHidden reports whether a file is hidden or not. -func IsHidden(file string) (bool, error) { - pointer, err := syscall.UTF16PtrFromString(file) - if err != nil { - return false, err //nolint:wrapcheck - } - attributes, err := syscall.GetFileAttributes(pointer) - if err != nil { - return false, err //nolint:wrapcheck - } - return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil -} diff --git a/vendor/github.com/charmbracelet/bubbles/help/help.go b/vendor/github.com/charmbracelet/bubbles/help/help.go deleted file mode 100644 index bb402a6c..00000000 --- a/vendor/github.com/charmbracelet/bubbles/help/help.go +++ /dev/null @@ -1,240 +0,0 @@ -// Package help provides a simple help view for Bubble Tea applications. -package help - -import ( - "strings" - - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -// KeyMap is a map of keybindings used to generate help. Since it's an -// interface it can be any type, though struct or a map[string][]key.Binding -// are likely candidates. -// -// Note that if a key is disabled (via key.Binding.SetEnabled) it will not be -// rendered in the help view, so in theory generated help should self-manage. -type KeyMap interface { - // ShortHelp returns a slice of bindings to be displayed in the short - // version of the help. The help bubble will render help in the order in - // which the help items are returned here. - ShortHelp() []key.Binding - - // FullHelp returns an extended group of help items, grouped by columns. - // The help bubble will render the help in the order in which the help - // items are returned here. - FullHelp() [][]key.Binding -} - -// Styles is a set of available style definitions for the Help bubble. -type Styles struct { - Ellipsis lipgloss.Style - - // Styling for the short help - ShortKey lipgloss.Style - ShortDesc lipgloss.Style - ShortSeparator lipgloss.Style - - // Styling for the full help - FullKey lipgloss.Style - FullDesc lipgloss.Style - FullSeparator lipgloss.Style -} - -// Model contains the state of the help view. -type Model struct { - Width int - ShowAll bool // if true, render the "full" help menu - - ShortSeparator string - FullSeparator string - - // The symbol we use in the short help when help items have been truncated - // due to width. Periods of ellipsis by default. - Ellipsis string - - Styles Styles -} - -// New creates a new help view with some useful defaults. -func New() Model { - keyStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#909090", - Dark: "#626262", - }) - - descStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#B2B2B2", - Dark: "#4A4A4A", - }) - - sepStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#DDDADA", - Dark: "#3C3C3C", - }) - - return Model{ - ShortSeparator: " • ", - FullSeparator: " ", - Ellipsis: "…", - Styles: Styles{ - ShortKey: keyStyle, - ShortDesc: descStyle, - ShortSeparator: sepStyle, - Ellipsis: sepStyle, - FullKey: keyStyle, - FullDesc: descStyle, - FullSeparator: sepStyle, - }, - } -} - -// NewModel creates a new help view with some useful defaults. -// -// Deprecated: use [New] instead. -var NewModel = New - -// Update helps satisfy the Bubble Tea Model interface. It's a no-op. -func (m Model) Update(_ tea.Msg) (Model, tea.Cmd) { - return m, nil -} - -// View renders the help view's current state. -func (m Model) View(k KeyMap) string { - if m.ShowAll { - return m.FullHelpView(k.FullHelp()) - } - return m.ShortHelpView(k.ShortHelp()) -} - -// ShortHelpView renders a single line help view from a slice of keybindings. -// If the line is longer than the maximum width it will be gracefully -// truncated, showing only as many help items as possible. -func (m Model) ShortHelpView(bindings []key.Binding) string { - if len(bindings) == 0 { - return "" - } - - var b strings.Builder - var totalWidth int - separator := m.Styles.ShortSeparator.Inline(true).Render(m.ShortSeparator) - - for i, kb := range bindings { - if !kb.Enabled() { - continue - } - - // Sep - var sep string - if totalWidth > 0 && i < len(bindings) { - sep = separator - } - - // Item - str := sep + - m.Styles.ShortKey.Inline(true).Render(kb.Help().Key) + " " + - m.Styles.ShortDesc.Inline(true).Render(kb.Help().Desc) - w := lipgloss.Width(str) - - // Tail - if tail, ok := m.shouldAddItem(totalWidth, w); !ok { - if tail != "" { - b.WriteString(tail) - } - break - } - - totalWidth += w - b.WriteString(str) - } - - return b.String() -} - -// FullHelpView renders help columns from a slice of key binding slices. Each -// top level slice entry renders into a column. -func (m Model) FullHelpView(groups [][]key.Binding) string { - if len(groups) == 0 { - return "" - } - - // Linter note: at this time we don't think it's worth the additional - // code complexity involved in preallocating this slice. - //nolint:prealloc - var ( - out []string - - totalWidth int - separator = m.Styles.FullSeparator.Inline(true).Render(m.FullSeparator) - ) - - // Iterate over groups to build columns - for i, group := range groups { - if group == nil || !shouldRenderColumn(group) { - continue - } - var ( - sep string - keys []string - descriptions []string - ) - - // Sep - if totalWidth > 0 && i < len(groups) { - sep = separator - } - - // Separate keys and descriptions into different slices - for _, kb := range group { - if !kb.Enabled() { - continue - } - keys = append(keys, kb.Help().Key) - descriptions = append(descriptions, kb.Help().Desc) - } - - // Column - col := lipgloss.JoinHorizontal(lipgloss.Top, - sep, - m.Styles.FullKey.Render(strings.Join(keys, "\n")), - " ", - m.Styles.FullDesc.Render(strings.Join(descriptions, "\n")), - ) - w := lipgloss.Width(col) - - // Tail - if tail, ok := m.shouldAddItem(totalWidth, w); !ok { - if tail != "" { - out = append(out, tail) - } - break - } - - totalWidth += w - out = append(out, col) - } - - return lipgloss.JoinHorizontal(lipgloss.Top, out...) -} - -func (m Model) shouldAddItem(totalWidth, width int) (tail string, ok bool) { - // If there's room for an ellipsis, print that. - if m.Width > 0 && totalWidth+width > m.Width { - tail = " " + m.Styles.Ellipsis.Inline(true).Render(m.Ellipsis) - - if totalWidth+lipgloss.Width(tail) < m.Width { - return tail, false - } - } - return "", true -} - -func shouldRenderColumn(b []key.Binding) (ok bool) { - for _, v := range b { - if v.Enabled() { - return true - } - } - return false -} diff --git a/vendor/github.com/charmbracelet/bubbles/key/key.go b/vendor/github.com/charmbracelet/bubbles/key/key.go deleted file mode 100644 index 0682665d..00000000 --- a/vendor/github.com/charmbracelet/bubbles/key/key.go +++ /dev/null @@ -1,140 +0,0 @@ -// Package key provides some types and functions for generating user-definable -// keymappings useful in Bubble Tea components. There are a few different ways -// you can define a keymapping with this package. Here's one example: -// -// type KeyMap struct { -// Up key.Binding -// Down key.Binding -// } -// -// var DefaultKeyMap = KeyMap{ -// Up: key.NewBinding( -// key.WithKeys("k", "up"), // actual keybindings -// key.WithHelp("↑/k", "move up"), // corresponding help text -// ), -// Down: key.NewBinding( -// key.WithKeys("j", "down"), -// key.WithHelp("↓/j", "move down"), -// ), -// } -// -// func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { -// switch msg := msg.(type) { -// case tea.KeyMsg: -// switch { -// case key.Matches(msg, DefaultKeyMap.Up): -// // The user pressed up -// case key.Matches(msg, DefaultKeyMap.Down): -// // The user pressed down -// } -// } -// -// // ... -// } -// -// The help information, which is not used in the example above, can be used -// to render help text for keystrokes in your views. -package key - -import "fmt" - -// Binding describes a set of keybindings and, optionally, their associated -// help text. -type Binding struct { - keys []string - help Help - disabled bool -} - -// BindingOpt is an initialization option for a keybinding. It's used as an -// argument to NewBinding. -type BindingOpt func(*Binding) - -// NewBinding returns a new keybinding from a set of BindingOpt options. -func NewBinding(opts ...BindingOpt) Binding { - b := &Binding{} - for _, opt := range opts { - opt(b) - } - return *b -} - -// WithKeys initializes a keybinding with the given keystrokes. -func WithKeys(keys ...string) BindingOpt { - return func(b *Binding) { - b.keys = keys - } -} - -// WithHelp initializes a keybinding with the given help text. -func WithHelp(key, desc string) BindingOpt { - return func(b *Binding) { - b.help = Help{Key: key, Desc: desc} - } -} - -// WithDisabled initializes a disabled keybinding. -func WithDisabled() BindingOpt { - return func(b *Binding) { - b.disabled = true - } -} - -// SetKeys sets the keys for the keybinding. -func (b *Binding) SetKeys(keys ...string) { - b.keys = keys -} - -// Keys returns the keys for the keybinding. -func (b Binding) Keys() []string { - return b.keys -} - -// SetHelp sets the help text for the keybinding. -func (b *Binding) SetHelp(key, desc string) { - b.help = Help{Key: key, Desc: desc} -} - -// Help returns the Help information for the keybinding. -func (b Binding) Help() Help { - return b.help -} - -// Enabled returns whether or not the keybinding is enabled. Disabled -// keybindings won't be activated and won't show up in help. Keybindings are -// enabled by default. -func (b Binding) Enabled() bool { - return !b.disabled && b.keys != nil -} - -// SetEnabled enables or disables the keybinding. -func (b *Binding) SetEnabled(v bool) { - b.disabled = !v -} - -// Unbind removes the keys and help from this binding, effectively nullifying -// it. This is a step beyond disabling it, since applications can enable -// or disable key bindings based on application state. -func (b *Binding) Unbind() { - b.keys = nil - b.help = Help{} -} - -// Help is help information for a given keybinding. -type Help struct { - Key string - Desc string -} - -// Matches checks if the given key matches the given bindings. -func Matches[Key fmt.Stringer](k Key, b ...Binding) bool { - keys := k.String() - for _, binding := range b { - for _, v := range binding.keys { - if keys == v && binding.Enabled() { - return true - } - } - } - return false -} diff --git a/vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go b/vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go deleted file mode 100644 index 82ea90a2..00000000 --- a/vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go +++ /dev/null @@ -1,102 +0,0 @@ -// Package runeutil provides a utility function for use in Bubbles -// that can process Key messages containing runes. -package runeutil - -import ( - "unicode" - "unicode/utf8" -) - -// Sanitizer is a helper for bubble widgets that want to process -// Runes from input key messages. -type Sanitizer interface { - // Sanitize removes control characters from runes in a KeyRunes - // message, and optionally replaces newline/carriage return/tabs by a - // specified character. - // - // The rune array is modified in-place if possible. In that case, the - // returned slice is the original slice shortened after the control - // characters have been removed/translated. - Sanitize(runes []rune) []rune -} - -// NewSanitizer constructs a rune sanitizer. -func NewSanitizer(opts ...Option) Sanitizer { - s := sanitizer{ - replaceNewLine: []rune("\n"), - replaceTab: []rune(" "), - } - for _, o := range opts { - s = o(s) - } - return &s -} - -// Option is the type of option that can be passed to Sanitize(). -type Option func(sanitizer) sanitizer - -// ReplaceTabs replaces tabs by the specified string. -func ReplaceTabs(tabRepl string) Option { - return func(s sanitizer) sanitizer { - s.replaceTab = []rune(tabRepl) - return s - } -} - -// ReplaceNewlines replaces newline characters by the specified string. -func ReplaceNewlines(nlRepl string) Option { - return func(s sanitizer) sanitizer { - s.replaceNewLine = []rune(nlRepl) - return s - } -} - -func (s *sanitizer) Sanitize(runes []rune) []rune { - // dstrunes are where we are storing the result. - dstrunes := runes[:0:len(runes)] - // copied indicates whether dstrunes is an alias of runes - // or a copy. We need a copy when dst moves past src. - // We use this as an optimization to avoid allocating - // a new rune slice in the common case where the output - // is smaller or equal to the input. - copied := false - - for src := 0; src < len(runes); src++ { - r := runes[src] - switch { - case r == utf8.RuneError: - // skip - - case r == '\r' || r == '\n': - if len(dstrunes)+len(s.replaceNewLine) > src && !copied { - dst := len(dstrunes) - dstrunes = make([]rune, dst, len(runes)+len(s.replaceNewLine)) - copy(dstrunes, runes[:dst]) - copied = true - } - dstrunes = append(dstrunes, s.replaceNewLine...) - - case r == '\t': - if len(dstrunes)+len(s.replaceTab) > src && !copied { - dst := len(dstrunes) - dstrunes = make([]rune, dst, len(runes)+len(s.replaceTab)) - copy(dstrunes, runes[:dst]) - copied = true - } - dstrunes = append(dstrunes, s.replaceTab...) - - case unicode.IsControl(r): - // Other control characters: skip. - - default: - // Keep the character. - dstrunes = append(dstrunes, runes[src]) - } - } - return dstrunes -} - -type sanitizer struct { - replaceNewLine []rune - replaceTab []rune -} diff --git a/vendor/github.com/charmbracelet/bubbles/spinner/spinner.go b/vendor/github.com/charmbracelet/bubbles/spinner/spinner.go deleted file mode 100644 index b2d24b09..00000000 --- a/vendor/github.com/charmbracelet/bubbles/spinner/spinner.go +++ /dev/null @@ -1,224 +0,0 @@ -// Package spinner provides a spinner component for Bubble Tea applications. -package spinner - -import ( - "sync/atomic" - "time" - - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -// Internal ID management. Used during animating to ensure that frame messages -// are received only by spinner components that sent them. -var lastID int64 - -func nextID() int { - return int(atomic.AddInt64(&lastID, 1)) -} - -// Spinner is a set of frames used in animating the spinner. -type Spinner struct { - Frames []string - FPS time.Duration -} - -// Some spinners to choose from. You could also make your own. -var ( - Line = Spinner{ - Frames: []string{"|", "/", "-", "\\"}, - FPS: time.Second / 10, //nolint:mnd - } - Dot = Spinner{ - Frames: []string{"⣾ ", "⣽ ", "⣻ ", "⢿ ", "⡿ ", "⣟ ", "⣯ ", "⣷ "}, - FPS: time.Second / 10, //nolint:mnd - } - MiniDot = Spinner{ - Frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}, - FPS: time.Second / 12, //nolint:mnd - } - Jump = Spinner{ - Frames: []string{"⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠"}, - FPS: time.Second / 10, //nolint:mnd - } - Pulse = Spinner{ - Frames: []string{"█", "▓", "▒", "░"}, - FPS: time.Second / 8, //nolint:mnd - } - Points = Spinner{ - Frames: []string{"∙∙∙", "●∙∙", "∙●∙", "∙∙●"}, - FPS: time.Second / 7, //nolint:mnd - } - Globe = Spinner{ - Frames: []string{"🌍", "🌎", "🌏"}, - FPS: time.Second / 4, //nolint:mnd - } - Moon = Spinner{ - Frames: []string{"🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"}, - FPS: time.Second / 8, //nolint:mnd - } - Monkey = Spinner{ - Frames: []string{"🙈", "🙉", "🙊"}, - FPS: time.Second / 3, //nolint:mnd - } - Meter = Spinner{ - Frames: []string{ - "▱▱▱", - "▰▱▱", - "▰▰▱", - "▰▰▰", - "▰▰▱", - "▰▱▱", - "▱▱▱", - }, - FPS: time.Second / 7, //nolint:mnd - } - Hamburger = Spinner{ - Frames: []string{"☱", "☲", "☴", "☲"}, - FPS: time.Second / 3, //nolint:mnd - } - Ellipsis = Spinner{ - Frames: []string{"", ".", "..", "..."}, - FPS: time.Second / 3, //nolint:mnd - } -) - -// Model contains the state for the spinner. Use New to create new models -// rather than using Model as a struct literal. -type Model struct { - // Spinner settings to use. See type Spinner. - Spinner Spinner - - // Style sets the styling for the spinner. Most of the time you'll just - // want foreground and background coloring, and potentially some padding. - // - // For an introduction to styling with Lip Gloss see: - // https://github.com/charmbracelet/lipgloss - Style lipgloss.Style - - frame int - id int - tag int -} - -// ID returns the spinner's unique ID. -func (m Model) ID() int { - return m.id -} - -// New returns a model with default values. -func New(opts ...Option) Model { - m := Model{ - Spinner: Line, - id: nextID(), - } - - for _, opt := range opts { - opt(&m) - } - - return m -} - -// NewModel returns a model with default values. -// -// Deprecated: use [New] instead. -var NewModel = New - -// TickMsg indicates that the timer has ticked and we should render a frame. -type TickMsg struct { - Time time.Time - tag int - ID int -} - -// Update is the Tea update function. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - switch msg := msg.(type) { - case TickMsg: - // If an ID is set, and the ID doesn't belong to this spinner, reject - // the message. - if msg.ID > 0 && msg.ID != m.id { - return m, nil - } - - // If a tag is set, and it's not the one we expect, reject the message. - // This prevents the spinner from receiving too many messages and - // thus spinning too fast. - if msg.tag > 0 && msg.tag != m.tag { - return m, nil - } - - m.frame++ - if m.frame >= len(m.Spinner.Frames) { - m.frame = 0 - } - - m.tag++ - return m, m.tick(m.id, m.tag) - default: - return m, nil - } -} - -// View renders the model's view. -func (m Model) View() string { - if m.frame >= len(m.Spinner.Frames) { - return "(error)" - } - - return m.Style.Render(m.Spinner.Frames[m.frame]) -} - -// Tick is the command used to advance the spinner one frame. Use this command -// to effectively start the spinner. -func (m Model) Tick() tea.Msg { - return TickMsg{ - // The time at which the tick occurred. - Time: time.Now(), - - // The ID of the spinner that this message belongs to. This can be - // helpful when routing messages, however bear in mind that spinners - // will ignore messages that don't contain ID by default. - ID: m.id, - - tag: m.tag, - } -} - -func (m Model) tick(id, tag int) tea.Cmd { - return tea.Tick(m.Spinner.FPS, func(t time.Time) tea.Msg { - return TickMsg{ - Time: t, - ID: id, - tag: tag, - } - }) -} - -// Tick is the command used to advance the spinner one frame. Use this command -// to effectively start the spinner. -// -// Deprecated: Use [Model.Tick] instead. -func Tick() tea.Msg { - return TickMsg{Time: time.Now()} -} - -// Option is used to set options in New. For example: -// -// spinner := New(WithSpinner(Dot)) -type Option func(*Model) - -// WithSpinner is an option to set the spinner. -func WithSpinner(spinner Spinner) Option { - return func(m *Model) { - m.Spinner = spinner - } -} - -// WithStyle is an option to set the spinner style. -func WithStyle(style lipgloss.Style) Option { - return func(m *Model) { - m.Style = style - } -} diff --git a/vendor/github.com/charmbracelet/bubbles/textarea/memoization/memoization.go b/vendor/github.com/charmbracelet/bubbles/textarea/memoization/memoization.go deleted file mode 100644 index 07f3796b..00000000 --- a/vendor/github.com/charmbracelet/bubbles/textarea/memoization/memoization.go +++ /dev/null @@ -1,125 +0,0 @@ -// Package memoization is an internal package that provides a simple memoization -// for text area. -package memoization - -import ( - "container/list" - "crypto/sha256" - "fmt" - "sync" -) - -// Hasher is an interface that requires a Hash method. The Hash method is -// expected to return a string representation of the hash of the object. -type Hasher interface { - Hash() string -} - -// entry is a struct that holds a key-value pair. It is used as an element -// in the evictionList of the MemoCache. -type entry[T any] struct { - key string - value T -} - -// MemoCache is a struct that represents a cache with a set capacity. It -// uses an LRU (Least Recently Used) eviction policy. It is safe for -// concurrent use. -type MemoCache[H Hasher, T any] struct { - capacity int - mutex sync.Mutex - cache map[string]*list.Element // The cache holding the results - evictionList *list.List // A list to keep track of the order for LRU - hashableItems map[string]T // This map keeps track of the original hashable items (optional) -} - -// NewMemoCache is a function that creates a new MemoCache with a given -// capacity. It returns a pointer to the created MemoCache. -func NewMemoCache[H Hasher, T any](capacity int) *MemoCache[H, T] { - return &MemoCache[H, T]{ - capacity: capacity, - cache: make(map[string]*list.Element), - evictionList: list.New(), - hashableItems: make(map[string]T), - } -} - -// Capacity is a method that returns the capacity of the MemoCache. -func (m *MemoCache[H, T]) Capacity() int { - return m.capacity -} - -// Size is a method that returns the current size of the MemoCache. It is -// the number of items currently stored in the cache. -func (m *MemoCache[H, T]) Size() int { - m.mutex.Lock() - defer m.mutex.Unlock() - return m.evictionList.Len() -} - -// Get is a method that returns the value associated with the given -// hashable item in the MemoCache. If there is no corresponding value, the -// method returns nil. -func (m *MemoCache[H, T]) Get(h H) (T, bool) { - m.mutex.Lock() - defer m.mutex.Unlock() - - hashedKey := h.Hash() - if element, found := m.cache[hashedKey]; found { - m.evictionList.MoveToFront(element) - return element.Value.(*entry[T]).value, true - } - var result T - return result, false -} - -// Set is a method that sets the value for the given hashable item in the -// MemoCache. If the cache is at capacity, it evicts the least recently -// used item before adding the new item. -func (m *MemoCache[H, T]) Set(h H, value T) { - m.mutex.Lock() - defer m.mutex.Unlock() - - hashedKey := h.Hash() - if element, found := m.cache[hashedKey]; found { - m.evictionList.MoveToFront(element) - element.Value.(*entry[T]).value = value - return - } - - // Check if the cache is at capacity - if m.evictionList.Len() >= m.capacity { - // Evict the least recently used item from the cache - toEvict := m.evictionList.Back() - if toEvict != nil { - evictedEntry := m.evictionList.Remove(toEvict).(*entry[T]) - delete(m.cache, evictedEntry.key) - delete(m.hashableItems, evictedEntry.key) // if you're keeping track of original items - } - } - - // Add the value to the cache and the evictionList - newEntry := &entry[T]{ - key: hashedKey, - value: value, - } - element := m.evictionList.PushFront(newEntry) - m.cache[hashedKey] = element - m.hashableItems[hashedKey] = value // if you're keeping track of original items -} - -// HString is a type that implements the Hasher interface for strings. -type HString string - -// Hash is a method that returns the hash of the string. -func (h HString) Hash() string { - return fmt.Sprintf("%x", sha256.Sum256([]byte(h))) -} - -// HInt is a type that implements the Hasher interface for integers. -type HInt int - -// Hash is a method that returns the hash of the integer. -func (h HInt) Hash() string { - return fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%d", h)))) -} diff --git a/vendor/github.com/charmbracelet/bubbles/textarea/textarea.go b/vendor/github.com/charmbracelet/bubbles/textarea/textarea.go deleted file mode 100644 index d82ae971..00000000 --- a/vendor/github.com/charmbracelet/bubbles/textarea/textarea.go +++ /dev/null @@ -1,1472 +0,0 @@ -// Package textarea provides a multi-line text input component for Bubble Tea -// applications. -package textarea - -import ( - "crypto/sha256" - "fmt" - "strconv" - "strings" - "unicode" - - "github.com/atotto/clipboard" - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/runeutil" - "github.com/charmbracelet/bubbles/textarea/memoization" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/x/ansi" - rw "github.com/mattn/go-runewidth" - "github.com/rivo/uniseg" -) - -const ( - minHeight = 1 - defaultHeight = 6 - defaultWidth = 40 - defaultCharLimit = 0 // no limit - defaultMaxHeight = 99 - defaultMaxWidth = 500 - - // XXX: in v2, make max lines dynamic and default max lines configurable. - maxLines = 10000 -) - -// Internal messages for clipboard operations. -type ( - pasteMsg string - pasteErrMsg struct{ error } -) - -// KeyMap is the key bindings for different actions within the textarea. -type KeyMap struct { - CharacterBackward key.Binding - CharacterForward key.Binding - DeleteAfterCursor key.Binding - DeleteBeforeCursor key.Binding - DeleteCharacterBackward key.Binding - DeleteCharacterForward key.Binding - DeleteWordBackward key.Binding - DeleteWordForward key.Binding - InsertNewline key.Binding - LineEnd key.Binding - LineNext key.Binding - LinePrevious key.Binding - LineStart key.Binding - Paste key.Binding - WordBackward key.Binding - WordForward key.Binding - InputBegin key.Binding - InputEnd key.Binding - - UppercaseWordForward key.Binding - LowercaseWordForward key.Binding - CapitalizeWordForward key.Binding - - TransposeCharacterBackward key.Binding -} - -// DefaultKeyMap is the default set of key bindings for navigating and acting -// upon the textarea. -var DefaultKeyMap = KeyMap{ - CharacterForward: key.NewBinding(key.WithKeys("right", "ctrl+f"), key.WithHelp("right", "character forward")), - CharacterBackward: key.NewBinding(key.WithKeys("left", "ctrl+b"), key.WithHelp("left", "character backward")), - WordForward: key.NewBinding(key.WithKeys("alt+right", "alt+f"), key.WithHelp("alt+right", "word forward")), - WordBackward: key.NewBinding(key.WithKeys("alt+left", "alt+b"), key.WithHelp("alt+left", "word backward")), - LineNext: key.NewBinding(key.WithKeys("down", "ctrl+n"), key.WithHelp("down", "next line")), - LinePrevious: key.NewBinding(key.WithKeys("up", "ctrl+p"), key.WithHelp("up", "previous line")), - DeleteWordBackward: key.NewBinding(key.WithKeys("alt+backspace", "ctrl+w"), key.WithHelp("alt+backspace", "delete word backward")), - DeleteWordForward: key.NewBinding(key.WithKeys("alt+delete", "alt+d"), key.WithHelp("alt+delete", "delete word forward")), - DeleteAfterCursor: key.NewBinding(key.WithKeys("ctrl+k"), key.WithHelp("ctrl+k", "delete after cursor")), - DeleteBeforeCursor: key.NewBinding(key.WithKeys("ctrl+u"), key.WithHelp("ctrl+u", "delete before cursor")), - InsertNewline: key.NewBinding(key.WithKeys("enter", "ctrl+m"), key.WithHelp("enter", "insert newline")), - DeleteCharacterBackward: key.NewBinding(key.WithKeys("backspace", "ctrl+h"), key.WithHelp("backspace", "delete character backward")), - DeleteCharacterForward: key.NewBinding(key.WithKeys("delete", "ctrl+d"), key.WithHelp("delete", "delete character forward")), - LineStart: key.NewBinding(key.WithKeys("home", "ctrl+a"), key.WithHelp("home", "line start")), - LineEnd: key.NewBinding(key.WithKeys("end", "ctrl+e"), key.WithHelp("end", "line end")), - Paste: key.NewBinding(key.WithKeys("ctrl+v"), key.WithHelp("ctrl+v", "paste")), - InputBegin: key.NewBinding(key.WithKeys("alt+<", "ctrl+home"), key.WithHelp("alt+<", "input begin")), - InputEnd: key.NewBinding(key.WithKeys("alt+>", "ctrl+end"), key.WithHelp("alt+>", "input end")), - - CapitalizeWordForward: key.NewBinding(key.WithKeys("alt+c"), key.WithHelp("alt+c", "capitalize word forward")), - LowercaseWordForward: key.NewBinding(key.WithKeys("alt+l"), key.WithHelp("alt+l", "lowercase word forward")), - UppercaseWordForward: key.NewBinding(key.WithKeys("alt+u"), key.WithHelp("alt+u", "uppercase word forward")), - - TransposeCharacterBackward: key.NewBinding(key.WithKeys("ctrl+t"), key.WithHelp("ctrl+t", "transpose character backward")), -} - -// LineInfo is a helper for keeping track of line information regarding -// soft-wrapped lines. -type LineInfo struct { - // Width is the number of columns in the line. - Width int - // CharWidth is the number of characters in the line to account for - // double-width runes. - CharWidth int - // Height is the number of rows in the line. - Height int - // StartColumn is the index of the first column of the line. - StartColumn int - // ColumnOffset is the number of columns that the cursor is offset from the - // start of the line. - ColumnOffset int - // RowOffset is the number of rows that the cursor is offset from the start - // of the line. - RowOffset int - // CharOffset is the number of characters that the cursor is offset - // from the start of the line. This will generally be equivalent to - // ColumnOffset, but will be different there are double-width runes before - // the cursor. - CharOffset int -} - -// Style that will be applied to the text area. -// -// Style can be applied to focused and unfocused states to change the styles -// depending on the focus state. -// -// For an introduction to styling with Lip Gloss see: -// https://github.com/charmbracelet/lipgloss -type Style struct { - Base lipgloss.Style - CursorLine lipgloss.Style - CursorLineNumber lipgloss.Style - EndOfBuffer lipgloss.Style - LineNumber lipgloss.Style - Placeholder lipgloss.Style - Prompt lipgloss.Style - Text lipgloss.Style -} - -func (s Style) computedCursorLine() lipgloss.Style { - return s.CursorLine.Inherit(s.Base).Inline(true) -} - -func (s Style) computedCursorLineNumber() lipgloss.Style { - return s.CursorLineNumber. - Inherit(s.CursorLine). - Inherit(s.Base). - Inline(true) -} - -func (s Style) computedEndOfBuffer() lipgloss.Style { - return s.EndOfBuffer.Inherit(s.Base).Inline(true) -} - -func (s Style) computedLineNumber() lipgloss.Style { - return s.LineNumber.Inherit(s.Base).Inline(true) -} - -func (s Style) computedPlaceholder() lipgloss.Style { - return s.Placeholder.Inherit(s.Base).Inline(true) -} - -func (s Style) computedPrompt() lipgloss.Style { - return s.Prompt.Inherit(s.Base).Inline(true) -} - -func (s Style) computedText() lipgloss.Style { - return s.Text.Inherit(s.Base).Inline(true) -} - -// line is the input to the text wrapping function. This is stored in a struct -// so that it can be hashed and memoized. -type line struct { - runes []rune - width int -} - -// Hash returns a hash of the line. -func (w line) Hash() string { - v := fmt.Sprintf("%s:%d", string(w.runes), w.width) - return fmt.Sprintf("%x", sha256.Sum256([]byte(v))) -} - -// Model is the Bubble Tea model for this text area element. -type Model struct { - Err error - - // General settings. - cache *memoization.MemoCache[line, [][]rune] - - // Prompt is printed at the beginning of each line. - // - // When changing the value of Prompt after the model has been - // initialized, ensure that SetWidth() gets called afterwards. - // - // See also SetPromptFunc(). - Prompt string - - // Placeholder is the text displayed when the user - // hasn't entered anything yet. - Placeholder string - - // ShowLineNumbers, if enabled, causes line numbers to be printed - // after the prompt. - ShowLineNumbers bool - - // EndOfBufferCharacter is displayed at the end of the input. - EndOfBufferCharacter rune - - // KeyMap encodes the keybindings recognized by the widget. - KeyMap KeyMap - - // Styling. FocusedStyle and BlurredStyle are used to style the textarea in - // focused and blurred states. - FocusedStyle Style - BlurredStyle Style - // style is the current styling to use. - // It is used to abstract the differences in focus state when styling the - // model, since we can simply assign the set of styles to this variable - // when switching focus states. - style *Style - - // Cursor is the text area cursor. - Cursor cursor.Model - - // CharLimit is the maximum number of characters this input element will - // accept. If 0 or less, there's no limit. - CharLimit int - - // MaxHeight is the maximum height of the text area in rows. If 0 or less, - // there's no limit. - MaxHeight int - - // MaxWidth is the maximum width of the text area in columns. If 0 or less, - // there's no limit. - MaxWidth int - - // If promptFunc is set, it replaces Prompt as a generator for - // prompt strings at the beginning of each line. - promptFunc func(line int) string - - // promptWidth is the width of the prompt. - promptWidth int - - // width is the maximum number of characters that can be displayed at once. - // If 0 or less this setting is ignored. - width int - - // height is the maximum number of lines that can be displayed at once. It - // essentially treats the text field like a vertically scrolling viewport - // if there are more lines than the permitted height. - height int - - // Underlying text value. - value [][]rune - - // focus indicates whether user input focus should be on this input - // component. When false, ignore keyboard input and hide the cursor. - focus bool - - // Cursor column. - col int - - // Cursor row. - row int - - // Last character offset, used to maintain state when the cursor is moved - // vertically such that we can maintain the same navigating position. - lastCharOffset int - - // viewport is the vertically-scrollable viewport of the multi-line text - // input. - viewport *viewport.Model - - // rune sanitizer for input. - rsan runeutil.Sanitizer -} - -// New creates a new model with default settings. -func New() Model { - vp := viewport.New(0, 0) - vp.KeyMap = viewport.KeyMap{} - cur := cursor.New() - - focusedStyle, blurredStyle := DefaultStyles() - - m := Model{ - CharLimit: defaultCharLimit, - MaxHeight: defaultMaxHeight, - MaxWidth: defaultMaxWidth, - Prompt: lipgloss.ThickBorder().Left + " ", - style: &blurredStyle, - FocusedStyle: focusedStyle, - BlurredStyle: blurredStyle, - cache: memoization.NewMemoCache[line, [][]rune](maxLines), - EndOfBufferCharacter: ' ', - ShowLineNumbers: true, - Cursor: cur, - KeyMap: DefaultKeyMap, - - value: make([][]rune, minHeight, maxLines), - focus: false, - col: 0, - row: 0, - - viewport: &vp, - } - - m.SetHeight(defaultHeight) - m.SetWidth(defaultWidth) - - return m -} - -// DefaultStyles returns the default styles for focused and blurred states for -// the textarea. -func DefaultStyles() (Style, Style) { - focused := Style{ - Base: lipgloss.NewStyle(), - CursorLine: lipgloss.NewStyle().Background(lipgloss.AdaptiveColor{Light: "255", Dark: "0"}), - CursorLineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "240"}), - EndOfBuffer: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "254", Dark: "0"}), - LineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "249", Dark: "7"}), - Placeholder: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), - Prompt: lipgloss.NewStyle().Foreground(lipgloss.Color("7")), - Text: lipgloss.NewStyle(), - } - blurred := Style{ - Base: lipgloss.NewStyle(), - CursorLine: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "245", Dark: "7"}), - CursorLineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "249", Dark: "7"}), - EndOfBuffer: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "254", Dark: "0"}), - LineNumber: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "249", Dark: "7"}), - Placeholder: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), - Prompt: lipgloss.NewStyle().Foreground(lipgloss.Color("7")), - Text: lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "245", Dark: "7"}), - } - - return focused, blurred -} - -// SetValue sets the value of the text input. -func (m *Model) SetValue(s string) { - m.Reset() - m.InsertString(s) -} - -// InsertString inserts a string at the cursor position. -func (m *Model) InsertString(s string) { - m.insertRunesFromUserInput([]rune(s)) -} - -// InsertRune inserts a rune at the cursor position. -func (m *Model) InsertRune(r rune) { - m.insertRunesFromUserInput([]rune{r}) -} - -// insertRunesFromUserInput inserts runes at the current cursor position. -func (m *Model) insertRunesFromUserInput(runes []rune) { - // Clean up any special characters in the input provided by the - // clipboard. This avoids bugs due to e.g. tab characters and - // whatnot. - runes = m.san().Sanitize(runes) - - if m.CharLimit > 0 { - availSpace := m.CharLimit - m.Length() - // If the char limit's been reached, cancel. - if availSpace <= 0 { - return - } - // If there's not enough space to paste the whole thing cut the pasted - // runes down so they'll fit. - if availSpace < len(runes) { - runes = runes[:availSpace] - } - } - - // Split the input into lines. - var lines [][]rune - lstart := 0 - for i := 0; i < len(runes); i++ { - if runes[i] == '\n' { - // Queue a line to become a new row in the text area below. - // Beware to clamp the max capacity of the slice, to ensure no - // data from different rows get overwritten when later edits - // will modify this line. - lines = append(lines, runes[lstart:i:i]) - lstart = i + 1 - } - } - if lstart <= len(runes) { - // The last line did not end with a newline character. - // Take it now. - lines = append(lines, runes[lstart:]) - } - - // Obey the maximum line limit. - if maxLines > 0 && len(m.value)+len(lines)-1 > maxLines { - allowedHeight := max(0, maxLines-len(m.value)+1) - lines = lines[:allowedHeight] - } - - if len(lines) == 0 { - // Nothing left to insert. - return - } - - // Save the remainder of the original line at the current - // cursor position. - tail := make([]rune, len(m.value[m.row][m.col:])) - copy(tail, m.value[m.row][m.col:]) - - // Paste the first line at the current cursor position. - m.value[m.row] = append(m.value[m.row][:m.col], lines[0]...) - m.col += len(lines[0]) - - if numExtraLines := len(lines) - 1; numExtraLines > 0 { - // Add the new lines. - // We try to reuse the slice if there's already space. - var newGrid [][]rune - if cap(m.value) >= len(m.value)+numExtraLines { - // Can reuse the extra space. - newGrid = m.value[:len(m.value)+numExtraLines] - } else { - // No space left; need a new slice. - newGrid = make([][]rune, len(m.value)+numExtraLines) - copy(newGrid, m.value[:m.row+1]) - } - // Add all the rows that were after the cursor in the original - // grid at the end of the new grid. - copy(newGrid[m.row+1+numExtraLines:], m.value[m.row+1:]) - m.value = newGrid - // Insert all the new lines in the middle. - for _, l := range lines[1:] { - m.row++ - m.value[m.row] = l - m.col = len(l) - } - } - - // Finally add the tail at the end of the last line inserted. - m.value[m.row] = append(m.value[m.row], tail...) - - m.SetCursor(m.col) -} - -// Value returns the value of the text input. -func (m Model) Value() string { - if m.value == nil { - return "" - } - - var v strings.Builder - for _, l := range m.value { - v.WriteString(string(l)) - v.WriteByte('\n') - } - - return strings.TrimSuffix(v.String(), "\n") -} - -// Length returns the number of characters currently in the text input. -func (m *Model) Length() int { - var l int - for _, row := range m.value { - l += uniseg.StringWidth(string(row)) - } - // We add len(m.value) to include the newline characters. - return l + len(m.value) - 1 -} - -// LineCount returns the number of lines that are currently in the text input. -func (m *Model) LineCount() int { - return len(m.value) -} - -// Line returns the line position. -func (m Model) Line() int { - return m.row -} - -// CursorDown moves the cursor down by one line. -// Returns whether or not the cursor blink should be reset. -func (m *Model) CursorDown() { - li := m.LineInfo() - charOffset := max(m.lastCharOffset, li.CharOffset) - m.lastCharOffset = charOffset - - if li.RowOffset+1 >= li.Height && m.row < len(m.value)-1 { - m.row++ - m.col = 0 - } else { - // Move the cursor to the start of the next line so that we can get - // the line information. We need to add 2 columns to account for the - // trailing space wrapping. - const trailingSpace = 2 - m.col = min(li.StartColumn+li.Width+trailingSpace, len(m.value[m.row])-1) - } - - nli := m.LineInfo() - m.col = nli.StartColumn - - if nli.Width <= 0 { - return - } - - offset := 0 - for offset < charOffset { - if m.row >= len(m.value) || m.col >= len(m.value[m.row]) || offset >= nli.CharWidth-1 { - break - } - offset += rw.RuneWidth(m.value[m.row][m.col]) - m.col++ - } -} - -// CursorUp moves the cursor up by one line. -func (m *Model) CursorUp() { - li := m.LineInfo() - charOffset := max(m.lastCharOffset, li.CharOffset) - m.lastCharOffset = charOffset - - if li.RowOffset <= 0 && m.row > 0 { - m.row-- - m.col = len(m.value[m.row]) - } else { - // Move the cursor to the end of the previous line. - // This can be done by moving the cursor to the start of the line and - // then subtracting 2 to account for the trailing space we keep on - // soft-wrapped lines. - const trailingSpace = 2 - m.col = li.StartColumn - trailingSpace - } - - nli := m.LineInfo() - m.col = nli.StartColumn - - if nli.Width <= 0 { - return - } - - offset := 0 - for offset < charOffset { - if m.col >= len(m.value[m.row]) || offset >= nli.CharWidth-1 { - break - } - offset += rw.RuneWidth(m.value[m.row][m.col]) - m.col++ - } -} - -// SetCursor moves the cursor to the given position. If the position is -// out of bounds the cursor will be moved to the start or end accordingly. -func (m *Model) SetCursor(col int) { - m.col = clamp(col, 0, len(m.value[m.row])) - // Any time that we move the cursor horizontally we need to reset the last - // offset so that the horizontal position when navigating is adjusted. - m.lastCharOffset = 0 -} - -// CursorStart moves the cursor to the start of the input field. -func (m *Model) CursorStart() { - m.SetCursor(0) -} - -// CursorEnd moves the cursor to the end of the input field. -func (m *Model) CursorEnd() { - m.SetCursor(len(m.value[m.row])) -} - -// Focused returns the focus state on the model. -func (m Model) Focused() bool { - return m.focus -} - -// Focus sets the focus state on the model. When the model is in focus it can -// receive keyboard input and the cursor will be hidden. -func (m *Model) Focus() tea.Cmd { - m.focus = true - m.style = &m.FocusedStyle - return m.Cursor.Focus() -} - -// Blur removes the focus state on the model. When the model is blurred it can -// not receive keyboard input and the cursor will be hidden. -func (m *Model) Blur() { - m.focus = false - m.style = &m.BlurredStyle - m.Cursor.Blur() -} - -// Reset sets the input to its default state with no input. -func (m *Model) Reset() { - m.value = make([][]rune, minHeight, maxLines) - m.col = 0 - m.row = 0 - m.viewport.GotoTop() - m.SetCursor(0) -} - -// san initializes or retrieves the rune sanitizer. -func (m *Model) san() runeutil.Sanitizer { - if m.rsan == nil { - // Textinput has all its input on a single line so collapse - // newlines/tabs to single spaces. - m.rsan = runeutil.NewSanitizer() - } - return m.rsan -} - -// deleteBeforeCursor deletes all text before the cursor. Returns whether or -// not the cursor blink should be reset. -func (m *Model) deleteBeforeCursor() { - m.value[m.row] = m.value[m.row][m.col:] - m.SetCursor(0) -} - -// deleteAfterCursor deletes all text after the cursor. Returns whether or not -// the cursor blink should be reset. If input is masked delete everything after -// the cursor so as not to reveal word breaks in the masked input. -func (m *Model) deleteAfterCursor() { - m.value[m.row] = m.value[m.row][:m.col] - m.SetCursor(len(m.value[m.row])) -} - -// transposeLeft exchanges the runes at the cursor and immediately -// before. No-op if the cursor is at the beginning of the line. If -// the cursor is not at the end of the line yet, moves the cursor to -// the right. -func (m *Model) transposeLeft() { - if m.col == 0 || len(m.value[m.row]) < 2 { - return - } - if m.col >= len(m.value[m.row]) { - m.SetCursor(m.col - 1) - } - m.value[m.row][m.col-1], m.value[m.row][m.col] = m.value[m.row][m.col], m.value[m.row][m.col-1] - if m.col < len(m.value[m.row]) { - m.SetCursor(m.col + 1) - } -} - -// deleteWordLeft deletes the word left to the cursor. Returns whether or not -// the cursor blink should be reset. -func (m *Model) deleteWordLeft() { - if m.col == 0 || len(m.value[m.row]) == 0 { - return - } - - // Linter note: it's critical that we acquire the initial cursor position - // here prior to altering it via SetCursor() below. As such, moving this - // call into the corresponding if clause does not apply here. - oldCol := m.col //nolint:ifshort - - m.SetCursor(m.col - 1) - for unicode.IsSpace(m.value[m.row][m.col]) { - if m.col <= 0 { - break - } - // ignore series of whitespace before cursor - m.SetCursor(m.col - 1) - } - - for m.col > 0 { - if !unicode.IsSpace(m.value[m.row][m.col]) { - m.SetCursor(m.col - 1) - } else { - if m.col > 0 { - // keep the previous space - m.SetCursor(m.col + 1) - } - break - } - } - - if oldCol > len(m.value[m.row]) { - m.value[m.row] = m.value[m.row][:m.col] - } else { - m.value[m.row] = append(m.value[m.row][:m.col], m.value[m.row][oldCol:]...) - } -} - -// deleteWordRight deletes the word right to the cursor. -func (m *Model) deleteWordRight() { - if m.col >= len(m.value[m.row]) || len(m.value[m.row]) == 0 { - return - } - - oldCol := m.col - - for m.col < len(m.value[m.row]) && unicode.IsSpace(m.value[m.row][m.col]) { - // ignore series of whitespace after cursor - m.SetCursor(m.col + 1) - } - - for m.col < len(m.value[m.row]) { - if !unicode.IsSpace(m.value[m.row][m.col]) { - m.SetCursor(m.col + 1) - } else { - break - } - } - - if m.col > len(m.value[m.row]) { - m.value[m.row] = m.value[m.row][:oldCol] - } else { - m.value[m.row] = append(m.value[m.row][:oldCol], m.value[m.row][m.col:]...) - } - - m.SetCursor(oldCol) -} - -// characterRight moves the cursor one character to the right. -func (m *Model) characterRight() { - if m.col < len(m.value[m.row]) { - m.SetCursor(m.col + 1) - } else { - if m.row < len(m.value)-1 { - m.row++ - m.CursorStart() - } - } -} - -// characterLeft moves the cursor one character to the left. -// If insideLine is set, the cursor is moved to the last -// character in the previous line, instead of one past that. -func (m *Model) characterLeft(insideLine bool) { - if m.col == 0 && m.row != 0 { - m.row-- - m.CursorEnd() - if !insideLine { - return - } - } - if m.col > 0 { - m.SetCursor(m.col - 1) - } -} - -// wordLeft moves the cursor one word to the left. Returns whether or not the -// cursor blink should be reset. If input is masked, move input to the start -// so as not to reveal word breaks in the masked input. -func (m *Model) wordLeft() { - for { - m.characterLeft(true /* insideLine */) - if m.col < len(m.value[m.row]) && !unicode.IsSpace(m.value[m.row][m.col]) { - break - } - } - - for m.col > 0 { - if unicode.IsSpace(m.value[m.row][m.col-1]) { - break - } - m.SetCursor(m.col - 1) - } -} - -// wordRight moves the cursor one word to the right. Returns whether or not the -// cursor blink should be reset. If the input is masked, move input to the end -// so as not to reveal word breaks in the masked input. -func (m *Model) wordRight() { - m.doWordRight(func(int, int) { /* nothing */ }) -} - -func (m *Model) doWordRight(fn func(charIdx int, pos int)) { - // Skip spaces forward. - for m.col >= len(m.value[m.row]) || unicode.IsSpace(m.value[m.row][m.col]) { - if m.row == len(m.value)-1 && m.col == len(m.value[m.row]) { - // End of text. - break - } - m.characterRight() - } - - charIdx := 0 - for m.col < len(m.value[m.row]) { - if unicode.IsSpace(m.value[m.row][m.col]) { - break - } - fn(charIdx, m.col) - m.SetCursor(m.col + 1) - charIdx++ - } -} - -// uppercaseRight changes the word to the right to uppercase. -func (m *Model) uppercaseRight() { - m.doWordRight(func(_ int, i int) { - m.value[m.row][i] = unicode.ToUpper(m.value[m.row][i]) - }) -} - -// lowercaseRight changes the word to the right to lowercase. -func (m *Model) lowercaseRight() { - m.doWordRight(func(_ int, i int) { - m.value[m.row][i] = unicode.ToLower(m.value[m.row][i]) - }) -} - -// capitalizeRight changes the word to the right to title case. -func (m *Model) capitalizeRight() { - m.doWordRight(func(charIdx int, i int) { - if charIdx == 0 { - m.value[m.row][i] = unicode.ToTitle(m.value[m.row][i]) - } - }) -} - -// LineInfo returns the number of characters from the start of the -// (soft-wrapped) line and the (soft-wrapped) line width. -func (m Model) LineInfo() LineInfo { - grid := m.memoizedWrap(m.value[m.row], m.width) - - // Find out which line we are currently on. This can be determined by the - // m.col and counting the number of runes that we need to skip. - var counter int - for i, line := range grid { - // We've found the line that we are on - if counter+len(line) == m.col && i+1 < len(grid) { - // We wrap around to the next line if we are at the end of the - // previous line so that we can be at the very beginning of the row - return LineInfo{ - CharOffset: 0, - ColumnOffset: 0, - Height: len(grid), - RowOffset: i + 1, - StartColumn: m.col, - Width: len(grid[i+1]), - CharWidth: uniseg.StringWidth(string(line)), - } - } - - if counter+len(line) >= m.col { - return LineInfo{ - CharOffset: uniseg.StringWidth(string(line[:max(0, m.col-counter)])), - ColumnOffset: m.col - counter, - Height: len(grid), - RowOffset: i, - StartColumn: counter, - Width: len(line), - CharWidth: uniseg.StringWidth(string(line)), - } - } - - counter += len(line) - } - return LineInfo{} -} - -// repositionView repositions the view of the viewport based on the defined -// scrolling behavior. -func (m *Model) repositionView() { - minimum := m.viewport.YOffset - maximum := minimum + m.viewport.Height - 1 - - if row := m.cursorLineNumber(); row < minimum { - m.viewport.ScrollUp(minimum - row) - } else if row > maximum { - m.viewport.ScrollDown(row - maximum) - } -} - -// Width returns the width of the textarea. -func (m Model) Width() int { - return m.width -} - -// moveToBegin moves the cursor to the beginning of the input. -func (m *Model) moveToBegin() { - m.row = 0 - m.SetCursor(0) -} - -// moveToEnd moves the cursor to the end of the input. -func (m *Model) moveToEnd() { - m.row = len(m.value) - 1 - m.SetCursor(len(m.value[m.row])) -} - -// SetWidth sets the width of the textarea to fit exactly within the given width. -// This means that the textarea will account for the width of the prompt and -// whether or not line numbers are being shown. -// -// Ensure that SetWidth is called after setting the Prompt and ShowLineNumbers, -// It is important that the width of the textarea be exactly the given width -// and no more. -func (m *Model) SetWidth(w int) { - // Update prompt width only if there is no prompt function as SetPromptFunc - // updates the prompt width when it is called. - if m.promptFunc == nil { - m.promptWidth = uniseg.StringWidth(m.Prompt) - } - - // Add base style borders and padding to reserved outer width. - reservedOuter := m.style.Base.GetHorizontalFrameSize() - - // Add prompt width to reserved inner width. - reservedInner := m.promptWidth - - // Add line number width to reserved inner width. - if m.ShowLineNumbers { - const lnWidth = 4 // Up to 3 digits for line number plus 1 margin. - reservedInner += lnWidth - } - - // Input width must be at least one more than the reserved inner and outer - // width. This gives us a minimum input width of 1. - minWidth := reservedInner + reservedOuter + 1 - inputWidth := max(w, minWidth) - - // Input width must be no more than maximum width. - if m.MaxWidth > 0 { - inputWidth = min(inputWidth, m.MaxWidth) - } - - // Since the width of the viewport and input area is dependent on the width of - // borders, prompt and line numbers, we need to calculate it by subtracting - // the reserved width from them. - - m.viewport.Width = inputWidth - reservedOuter - m.width = inputWidth - reservedOuter - reservedInner -} - -// SetPromptFunc supersedes the Prompt field and sets a dynamic prompt -// instead. -// If the function returns a prompt that is shorter than the -// specified promptWidth, it will be padded to the left. -// If it returns a prompt that is longer, display artifacts -// may occur; the caller is responsible for computing an adequate -// promptWidth. -func (m *Model) SetPromptFunc(promptWidth int, fn func(lineIdx int) string) { - m.promptFunc = fn - m.promptWidth = promptWidth -} - -// Height returns the current height of the textarea. -func (m Model) Height() int { - return m.height -} - -// SetHeight sets the height of the textarea. -func (m *Model) SetHeight(h int) { - if m.MaxHeight > 0 { - m.height = clamp(h, minHeight, m.MaxHeight) - m.viewport.Height = clamp(h, minHeight, m.MaxHeight) - } else { - m.height = max(h, minHeight) - m.viewport.Height = max(h, minHeight) - } -} - -// Update is the Bubble Tea update loop. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - if !m.focus { - m.Cursor.Blur() - return m, nil - } - - // Used to determine if the cursor should blink. - oldRow, oldCol := m.cursorLineNumber(), m.col - - var cmds []tea.Cmd - - if m.value[m.row] == nil { - m.value[m.row] = make([]rune, 0) - } - - if m.MaxHeight > 0 && m.MaxHeight != m.cache.Capacity() { - m.cache = memoization.NewMemoCache[line, [][]rune](m.MaxHeight) - } - - switch msg := msg.(type) { - case tea.KeyMsg: - switch { - case key.Matches(msg, m.KeyMap.DeleteAfterCursor): - m.col = clamp(m.col, 0, len(m.value[m.row])) - if m.col >= len(m.value[m.row]) { - m.mergeLineBelow(m.row) - break - } - m.deleteAfterCursor() - case key.Matches(msg, m.KeyMap.DeleteBeforeCursor): - m.col = clamp(m.col, 0, len(m.value[m.row])) - if m.col <= 0 { - m.mergeLineAbove(m.row) - break - } - m.deleteBeforeCursor() - case key.Matches(msg, m.KeyMap.DeleteCharacterBackward): - m.col = clamp(m.col, 0, len(m.value[m.row])) - if m.col <= 0 { - m.mergeLineAbove(m.row) - break - } - if len(m.value[m.row]) > 0 { - m.value[m.row] = append(m.value[m.row][:max(0, m.col-1)], m.value[m.row][m.col:]...) - if m.col > 0 { - m.SetCursor(m.col - 1) - } - } - case key.Matches(msg, m.KeyMap.DeleteCharacterForward): - if len(m.value[m.row]) > 0 && m.col < len(m.value[m.row]) { - m.value[m.row] = append(m.value[m.row][:m.col], m.value[m.row][m.col+1:]...) - } - if m.col >= len(m.value[m.row]) { - m.mergeLineBelow(m.row) - break - } - case key.Matches(msg, m.KeyMap.DeleteWordBackward): - if m.col <= 0 { - m.mergeLineAbove(m.row) - break - } - m.deleteWordLeft() - case key.Matches(msg, m.KeyMap.DeleteWordForward): - m.col = clamp(m.col, 0, len(m.value[m.row])) - if m.col >= len(m.value[m.row]) { - m.mergeLineBelow(m.row) - break - } - m.deleteWordRight() - case key.Matches(msg, m.KeyMap.InsertNewline): - if m.MaxHeight > 0 && len(m.value) >= m.MaxHeight { - return m, nil - } - m.col = clamp(m.col, 0, len(m.value[m.row])) - m.splitLine(m.row, m.col) - case key.Matches(msg, m.KeyMap.LineEnd): - m.CursorEnd() - case key.Matches(msg, m.KeyMap.LineStart): - m.CursorStart() - case key.Matches(msg, m.KeyMap.CharacterForward): - m.characterRight() - case key.Matches(msg, m.KeyMap.LineNext): - m.CursorDown() - case key.Matches(msg, m.KeyMap.WordForward): - m.wordRight() - case key.Matches(msg, m.KeyMap.Paste): - return m, Paste - case key.Matches(msg, m.KeyMap.CharacterBackward): - m.characterLeft(false /* insideLine */) - case key.Matches(msg, m.KeyMap.LinePrevious): - m.CursorUp() - case key.Matches(msg, m.KeyMap.WordBackward): - m.wordLeft() - case key.Matches(msg, m.KeyMap.InputBegin): - m.moveToBegin() - case key.Matches(msg, m.KeyMap.InputEnd): - m.moveToEnd() - case key.Matches(msg, m.KeyMap.LowercaseWordForward): - m.lowercaseRight() - case key.Matches(msg, m.KeyMap.UppercaseWordForward): - m.uppercaseRight() - case key.Matches(msg, m.KeyMap.CapitalizeWordForward): - m.capitalizeRight() - case key.Matches(msg, m.KeyMap.TransposeCharacterBackward): - m.transposeLeft() - - default: - m.insertRunesFromUserInput(msg.Runes) - } - - case pasteMsg: - m.insertRunesFromUserInput([]rune(msg)) - - case pasteErrMsg: - m.Err = msg - } - - vp, cmd := m.viewport.Update(msg) - m.viewport = &vp - cmds = append(cmds, cmd) - - newRow, newCol := m.cursorLineNumber(), m.col - m.Cursor, cmd = m.Cursor.Update(msg) - if (newRow != oldRow || newCol != oldCol) && m.Cursor.Mode() == cursor.CursorBlink { - m.Cursor.Blink = false - cmd = m.Cursor.BlinkCmd() - } - cmds = append(cmds, cmd) - - m.repositionView() - - return m, tea.Batch(cmds...) -} - -// View renders the text area in its current state. -func (m Model) View() string { - if m.Value() == "" && m.row == 0 && m.col == 0 && m.Placeholder != "" { - return m.placeholderView() - } - m.Cursor.TextStyle = m.style.computedCursorLine() - - var ( - s strings.Builder - style lipgloss.Style - newLines int - widestLineNumber int - lineInfo = m.LineInfo() - ) - - displayLine := 0 - for l, line := range m.value { - wrappedLines := m.memoizedWrap(line, m.width) - - if m.row == l { - style = m.style.computedCursorLine() - } else { - style = m.style.computedText() - } - - for wl, wrappedLine := range wrappedLines { - prompt := m.getPromptString(displayLine) - prompt = m.style.computedPrompt().Render(prompt) - s.WriteString(style.Render(prompt)) - displayLine++ - - var ln string - if m.ShowLineNumbers { //nolint:nestif - if wl == 0 { - if m.row == l { - ln = style.Render(m.style.computedCursorLineNumber().Render(m.formatLineNumber(l + 1))) - s.WriteString(ln) - } else { - ln = style.Render(m.style.computedLineNumber().Render(m.formatLineNumber(l + 1))) - s.WriteString(ln) - } - } else { - if m.row == l { - ln = style.Render(m.style.computedCursorLineNumber().Render(m.formatLineNumber(" "))) - s.WriteString(ln) - } else { - ln = style.Render(m.style.computedLineNumber().Render(m.formatLineNumber(" "))) - s.WriteString(ln) - } - } - } - - // Note the widest line number for padding purposes later. - lnw := lipgloss.Width(ln) - if lnw > widestLineNumber { - widestLineNumber = lnw - } - - strwidth := uniseg.StringWidth(string(wrappedLine)) - padding := m.width - strwidth - // If the trailing space causes the line to be wider than the - // width, we should not draw it to the screen since it will result - // in an extra space at the end of the line which can look off when - // the cursor line is showing. - if strwidth > m.width { - // The character causing the line to be wider than the width is - // guaranteed to be a space since any other character would - // have been wrapped. - wrappedLine = []rune(strings.TrimSuffix(string(wrappedLine), " ")) - padding -= m.width - strwidth - } - if m.row == l && lineInfo.RowOffset == wl { - s.WriteString(style.Render(string(wrappedLine[:lineInfo.ColumnOffset]))) - if m.col >= len(line) && lineInfo.CharOffset >= m.width { - m.Cursor.SetChar(" ") - s.WriteString(m.Cursor.View()) - } else { - m.Cursor.SetChar(string(wrappedLine[lineInfo.ColumnOffset])) - s.WriteString(style.Render(m.Cursor.View())) - s.WriteString(style.Render(string(wrappedLine[lineInfo.ColumnOffset+1:]))) - } - } else { - s.WriteString(style.Render(string(wrappedLine))) - } - s.WriteString(style.Render(strings.Repeat(" ", max(0, padding)))) - s.WriteRune('\n') - newLines++ - } - } - - // Always show at least `m.Height` lines at all times. - // To do this we can simply pad out a few extra new lines in the view. - for i := 0; i < m.height; i++ { - prompt := m.getPromptString(displayLine) - prompt = m.style.computedPrompt().Render(prompt) - s.WriteString(prompt) - displayLine++ - - // Write end of buffer content - leftGutter := string(m.EndOfBufferCharacter) - rightGapWidth := m.Width() - lipgloss.Width(leftGutter) + widestLineNumber - rightGap := strings.Repeat(" ", max(0, rightGapWidth)) - s.WriteString(m.style.computedEndOfBuffer().Render(leftGutter + rightGap)) - s.WriteRune('\n') - } - - m.viewport.SetContent(s.String()) - return m.style.Base.Render(m.viewport.View()) -} - -// formatLineNumber formats the line number for display dynamically based on -// the maximum number of lines. -func (m Model) formatLineNumber(x any) string { - // XXX: ultimately we should use a max buffer height, which has yet to be - // implemented. - digits := len(strconv.Itoa(m.MaxHeight)) - return fmt.Sprintf(" %*v ", digits, x) -} - -func (m Model) getPromptString(displayLine int) (prompt string) { - prompt = m.Prompt - if m.promptFunc == nil { - return prompt - } - prompt = m.promptFunc(displayLine) - pl := uniseg.StringWidth(prompt) - if pl < m.promptWidth { - prompt = fmt.Sprintf("%*s%s", m.promptWidth-pl, "", prompt) - } - return prompt -} - -// placeholderView returns the prompt and placeholder view, if any. -func (m Model) placeholderView() string { - var ( - s strings.Builder - p = m.Placeholder - style = m.style.computedPlaceholder() - ) - - // word wrap lines - pwordwrap := ansi.Wordwrap(p, m.width, "") - // wrap lines (handles lines that could not be word wrapped) - pwrap := ansi.Hardwrap(pwordwrap, m.width, true) - // split string by new lines - plines := strings.Split(strings.TrimSpace(pwrap), "\n") - - for i := 0; i < m.height; i++ { - lineStyle := m.style.computedPlaceholder() - lineNumberStyle := m.style.computedLineNumber() - if len(plines) > i { - lineStyle = m.style.computedCursorLine() - lineNumberStyle = m.style.computedCursorLineNumber() - } - - // render prompt - prompt := m.getPromptString(i) - prompt = m.style.computedPrompt().Render(prompt) - s.WriteString(lineStyle.Render(prompt)) - - // when show line numbers enabled: - // - render line number for only the cursor line - // - indent other placeholder lines - // this is consistent with vim with line numbers enabled - if m.ShowLineNumbers { - var ln string - - switch { - case i == 0: - ln = strconv.Itoa(i + 1) - fallthrough - case len(plines) > i: - s.WriteString(lineStyle.Render(lineNumberStyle.Render(m.formatLineNumber(ln)))) - default: - } - } - - switch { - // first line - case i == 0: - // first character of first line as cursor with character - m.Cursor.TextStyle = m.style.computedPlaceholder() - - ch, rest, _, _ := uniseg.FirstGraphemeClusterInString(plines[0], 0) - m.Cursor.SetChar(ch) - s.WriteString(lineStyle.Render(m.Cursor.View())) - - // the rest of the first line - s.WriteString(lineStyle.Render(style.Render(rest))) - // remaining lines - case len(plines) > i: - // current line placeholder text - if len(plines) > i { - s.WriteString(lineStyle.Render(style.Render(plines[i] + strings.Repeat(" ", max(0, m.width-uniseg.StringWidth(plines[i])))))) - } - default: - // end of line buffer character - eob := m.style.computedEndOfBuffer().Render(string(m.EndOfBufferCharacter)) - s.WriteString(eob) - } - - // terminate with new line - s.WriteRune('\n') - } - - m.viewport.SetContent(s.String()) - return m.style.Base.Render(m.viewport.View()) -} - -// Blink returns the blink command for the cursor. -func Blink() tea.Msg { - return cursor.Blink() -} - -func (m Model) memoizedWrap(runes []rune, width int) [][]rune { - input := line{runes: runes, width: width} - if v, ok := m.cache.Get(input); ok { - return v - } - v := wrap(runes, width) - m.cache.Set(input, v) - return v -} - -// cursorLineNumber returns the line number that the cursor is on. -// This accounts for soft wrapped lines. -func (m Model) cursorLineNumber() int { - line := 0 - for i := 0; i < m.row; i++ { - // Calculate the number of lines that the current line will be split - // into. - line += len(m.memoizedWrap(m.value[i], m.width)) - } - line += m.LineInfo().RowOffset - return line -} - -// mergeLineBelow merges the current line the cursor is on with the line below. -func (m *Model) mergeLineBelow(row int) { - if row >= len(m.value)-1 { - return - } - - // To perform a merge, we will need to combine the two lines and then - m.value[row] = append(m.value[row], m.value[row+1]...) - - // Shift all lines up by one - for i := row + 1; i < len(m.value)-1; i++ { - m.value[i] = m.value[i+1] - } - - // And, remove the last line - if len(m.value) > 0 { - m.value = m.value[:len(m.value)-1] - } -} - -// mergeLineAbove merges the current line the cursor is on with the line above. -func (m *Model) mergeLineAbove(row int) { - if row <= 0 { - return - } - - m.col = len(m.value[row-1]) - m.row = m.row - 1 - - // To perform a merge, we will need to combine the two lines and then - m.value[row-1] = append(m.value[row-1], m.value[row]...) - - // Shift all lines up by one - for i := row; i < len(m.value)-1; i++ { - m.value[i] = m.value[i+1] - } - - // And, remove the last line - if len(m.value) > 0 { - m.value = m.value[:len(m.value)-1] - } -} - -func (m *Model) splitLine(row, col int) { - // To perform a split, take the current line and keep the content before - // the cursor, take the content after the cursor and make it the content of - // the line underneath, and shift the remaining lines down by one - head, tailSrc := m.value[row][:col], m.value[row][col:] - tail := make([]rune, len(tailSrc)) - copy(tail, tailSrc) - - m.value = append(m.value[:row+1], m.value[row:]...) - - m.value[row] = head - m.value[row+1] = tail - - m.col = 0 - m.row++ -} - -// Paste is a command for pasting from the clipboard into the text input. -func Paste() tea.Msg { - str, err := clipboard.ReadAll() - if err != nil { - return pasteErrMsg{err} - } - return pasteMsg(str) -} - -func wrap(runes []rune, width int) [][]rune { - var ( - lines = [][]rune{{}} - word = []rune{} - row int - spaces int - ) - - // Word wrap the runes - for _, r := range runes { - if unicode.IsSpace(r) { - spaces++ - } else { - word = append(word, r) - } - - if spaces > 0 { //nolint:nestif - if uniseg.StringWidth(string(lines[row]))+uniseg.StringWidth(string(word))+spaces > width { - row++ - lines = append(lines, []rune{}) - lines[row] = append(lines[row], word...) - lines[row] = append(lines[row], repeatSpaces(spaces)...) - spaces = 0 - word = nil - } else { - lines[row] = append(lines[row], word...) - lines[row] = append(lines[row], repeatSpaces(spaces)...) - spaces = 0 - word = nil - } - } else { - // If the last character is a double-width rune, then we may not be able to add it to this line - // as it might cause us to go past the width. - lastCharLen := rw.RuneWidth(word[len(word)-1]) - if uniseg.StringWidth(string(word))+lastCharLen > width { - // If the current line has any content, let's move to the next - // line because the current word fills up the entire line. - if len(lines[row]) > 0 { - row++ - lines = append(lines, []rune{}) - } - lines[row] = append(lines[row], word...) - word = nil - } - } - } - - if uniseg.StringWidth(string(lines[row]))+uniseg.StringWidth(string(word))+spaces >= width { - lines = append(lines, []rune{}) - lines[row+1] = append(lines[row+1], word...) - // We add an extra space at the end of the line to account for the - // trailing space at the end of the previous soft-wrapped lines so that - // behaviour when navigating is consistent and so that we don't need to - // continually add edges to handle the last line of the wrapped input. - spaces++ - lines[row+1] = append(lines[row+1], repeatSpaces(spaces)...) - } else { - lines[row] = append(lines[row], word...) - spaces++ - lines[row] = append(lines[row], repeatSpaces(spaces)...) - } - - return lines -} - -func repeatSpaces(n int) []rune { - return []rune(strings.Repeat(string(' '), n)) -} - -func clamp(v, low, high int) int { - if high < low { - low, high = high, low - } - return min(high, max(low, v)) -} diff --git a/vendor/github.com/charmbracelet/bubbles/textinput/textinput.go b/vendor/github.com/charmbracelet/bubbles/textinput/textinput.go deleted file mode 100644 index 84cbbc93..00000000 --- a/vendor/github.com/charmbracelet/bubbles/textinput/textinput.go +++ /dev/null @@ -1,898 +0,0 @@ -// Package textinput provides a text input component for Bubble Tea -// applications. -package textinput - -import ( - "reflect" - "strings" - "time" - "unicode" - - "github.com/atotto/clipboard" - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/runeutil" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - rw "github.com/mattn/go-runewidth" - "github.com/rivo/uniseg" -) - -// Internal messages for clipboard operations. -type ( - pasteMsg string - pasteErrMsg struct{ error } -) - -// EchoMode sets the input behavior of the text input field. -type EchoMode int - -const ( - // EchoNormal displays text as is. This is the default behavior. - EchoNormal EchoMode = iota - - // EchoPassword displays the EchoCharacter mask instead of actual - // characters. This is commonly used for password fields. - EchoPassword - - // EchoNone displays nothing as characters are entered. This is commonly - // seen for password fields on the command line. - EchoNone -) - -// ValidateFunc is a function that returns an error if the input is invalid. -type ValidateFunc func(string) error - -// KeyMap is the key bindings for different actions within the textinput. -type KeyMap struct { - CharacterForward key.Binding - CharacterBackward key.Binding - WordForward key.Binding - WordBackward key.Binding - DeleteWordBackward key.Binding - DeleteWordForward key.Binding - DeleteAfterCursor key.Binding - DeleteBeforeCursor key.Binding - DeleteCharacterBackward key.Binding - DeleteCharacterForward key.Binding - LineStart key.Binding - LineEnd key.Binding - Paste key.Binding - AcceptSuggestion key.Binding - NextSuggestion key.Binding - PrevSuggestion key.Binding -} - -// DefaultKeyMap is the default set of key bindings for navigating and acting -// upon the textinput. -var DefaultKeyMap = KeyMap{ - CharacterForward: key.NewBinding(key.WithKeys("right", "ctrl+f")), - CharacterBackward: key.NewBinding(key.WithKeys("left", "ctrl+b")), - WordForward: key.NewBinding(key.WithKeys("alt+right", "ctrl+right", "alt+f")), - WordBackward: key.NewBinding(key.WithKeys("alt+left", "ctrl+left", "alt+b")), - DeleteWordBackward: key.NewBinding(key.WithKeys("alt+backspace", "ctrl+w")), - DeleteWordForward: key.NewBinding(key.WithKeys("alt+delete", "alt+d")), - DeleteAfterCursor: key.NewBinding(key.WithKeys("ctrl+k")), - DeleteBeforeCursor: key.NewBinding(key.WithKeys("ctrl+u")), - DeleteCharacterBackward: key.NewBinding(key.WithKeys("backspace", "ctrl+h")), - DeleteCharacterForward: key.NewBinding(key.WithKeys("delete", "ctrl+d")), - LineStart: key.NewBinding(key.WithKeys("home", "ctrl+a")), - LineEnd: key.NewBinding(key.WithKeys("end", "ctrl+e")), - Paste: key.NewBinding(key.WithKeys("ctrl+v")), - AcceptSuggestion: key.NewBinding(key.WithKeys("tab")), - NextSuggestion: key.NewBinding(key.WithKeys("down", "ctrl+n")), - PrevSuggestion: key.NewBinding(key.WithKeys("up", "ctrl+p")), -} - -// Model is the Bubble Tea model for this text input element. -type Model struct { - Err error - - // General settings. - Prompt string - Placeholder string - EchoMode EchoMode - EchoCharacter rune - Cursor cursor.Model - - // Deprecated: use [cursor.BlinkSpeed] instead. - BlinkSpeed time.Duration - - // Styles. These will be applied as inline styles. - // - // For an introduction to styling with Lip Gloss see: - // https://github.com/charmbracelet/lipgloss - PromptStyle lipgloss.Style - TextStyle lipgloss.Style - PlaceholderStyle lipgloss.Style - CompletionStyle lipgloss.Style - - // Deprecated: use Cursor.Style instead. - CursorStyle lipgloss.Style - - // CharLimit is the maximum amount of characters this input element will - // accept. If 0 or less, there's no limit. - CharLimit int - - // Width is the maximum number of characters that can be displayed at once. - // It essentially treats the text field like a horizontally scrolling - // viewport. If 0 or less this setting is ignored. - Width int - - // KeyMap encodes the keybindings recognized by the widget. - KeyMap KeyMap - - // Underlying text value. - value []rune - - // focus indicates whether user input focus should be on this input - // component. When false, ignore keyboard input and hide the cursor. - focus bool - - // Cursor position. - pos int - - // Used to emulate a viewport when width is set and the content is - // overflowing. - offset int - offsetRight int - - // Validate is a function that checks whether or not the text within the - // input is valid. If it is not valid, the `Err` field will be set to the - // error returned by the function. If the function is not defined, all - // input is considered valid. - Validate ValidateFunc - - // rune sanitizer for input. - rsan runeutil.Sanitizer - - // Should the input suggest to complete - ShowSuggestions bool - - // suggestions is a list of suggestions that may be used to complete the - // input. - suggestions [][]rune - matchedSuggestions [][]rune - currentSuggestionIndex int -} - -// New creates a new model with default settings. -func New() Model { - return Model{ - Prompt: "> ", - EchoCharacter: '*', - CharLimit: 0, - PlaceholderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), - ShowSuggestions: false, - CompletionStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), - Cursor: cursor.New(), - KeyMap: DefaultKeyMap, - - suggestions: [][]rune{}, - value: nil, - focus: false, - pos: 0, - } -} - -// NewModel creates a new model with default settings. -// -// Deprecated: Use [New] instead. -var NewModel = New - -// SetValue sets the value of the text input. -func (m *Model) SetValue(s string) { - // Clean up any special characters in the input provided by the - // caller. This avoids bugs due to e.g. tab characters and whatnot. - runes := m.san().Sanitize([]rune(s)) - err := m.validate(runes) - m.setValueInternal(runes, err) -} - -func (m *Model) setValueInternal(runes []rune, err error) { - m.Err = err - - empty := len(m.value) == 0 - - if m.CharLimit > 0 && len(runes) > m.CharLimit { - m.value = runes[:m.CharLimit] - } else { - m.value = runes - } - if (m.pos == 0 && empty) || m.pos > len(m.value) { - m.SetCursor(len(m.value)) - } - m.handleOverflow() -} - -// Value returns the value of the text input. -func (m Model) Value() string { - return string(m.value) -} - -// Position returns the cursor position. -func (m Model) Position() int { - return m.pos -} - -// SetCursor moves the cursor to the given position. If the position is -// out of bounds the cursor will be moved to the start or end accordingly. -func (m *Model) SetCursor(pos int) { - m.pos = clamp(pos, 0, len(m.value)) - m.handleOverflow() -} - -// CursorStart moves the cursor to the start of the input field. -func (m *Model) CursorStart() { - m.SetCursor(0) -} - -// CursorEnd moves the cursor to the end of the input field. -func (m *Model) CursorEnd() { - m.SetCursor(len(m.value)) -} - -// Focused returns the focus state on the model. -func (m Model) Focused() bool { - return m.focus -} - -// Focus sets the focus state on the model. When the model is in focus it can -// receive keyboard input and the cursor will be shown. -func (m *Model) Focus() tea.Cmd { - m.focus = true - return m.Cursor.Focus() -} - -// Blur removes the focus state on the model. When the model is blurred it can -// not receive keyboard input and the cursor will be hidden. -func (m *Model) Blur() { - m.focus = false - m.Cursor.Blur() -} - -// Reset sets the input to its default state with no input. -func (m *Model) Reset() { - m.value = nil - m.SetCursor(0) -} - -// SetSuggestions sets the suggestions for the input. -func (m *Model) SetSuggestions(suggestions []string) { - m.suggestions = make([][]rune, len(suggestions)) - for i, s := range suggestions { - m.suggestions[i] = []rune(s) - } - - m.updateSuggestions() -} - -// rsan initializes or retrieves the rune sanitizer. -func (m *Model) san() runeutil.Sanitizer { - if m.rsan == nil { - // Textinput has all its input on a single line so collapse - // newlines/tabs to single spaces. - m.rsan = runeutil.NewSanitizer( - runeutil.ReplaceTabs(" "), runeutil.ReplaceNewlines(" ")) - } - return m.rsan -} - -func (m *Model) insertRunesFromUserInput(v []rune) { - // Clean up any special characters in the input provided by the - // clipboard. This avoids bugs due to e.g. tab characters and - // whatnot. - paste := m.san().Sanitize(v) - - var availSpace int - if m.CharLimit > 0 { - availSpace = m.CharLimit - len(m.value) - - // If the char limit's been reached, cancel. - if availSpace <= 0 { - return - } - - // If there's not enough space to paste the whole thing cut the pasted - // runes down so they'll fit. - if availSpace < len(paste) { - paste = paste[:availSpace] - } - } - - // Stuff before and after the cursor - head := m.value[:m.pos] - tailSrc := m.value[m.pos:] - tail := make([]rune, len(tailSrc)) - copy(tail, tailSrc) - - // Insert pasted runes - for _, r := range paste { - head = append(head, r) - m.pos++ - if m.CharLimit > 0 { - availSpace-- - if availSpace <= 0 { - break - } - } - } - - // Put it all back together - value := append(head, tail...) - inputErr := m.validate(value) - m.setValueInternal(value, inputErr) -} - -// If a max width is defined, perform some logic to treat the visible area -// as a horizontally scrolling viewport. -func (m *Model) handleOverflow() { - if m.Width <= 0 || uniseg.StringWidth(string(m.value)) <= m.Width { - m.offset = 0 - m.offsetRight = len(m.value) - return - } - - // Correct right offset if we've deleted characters - m.offsetRight = min(m.offsetRight, len(m.value)) - - if m.pos < m.offset { - m.offset = m.pos - - w := 0 - i := 0 - runes := m.value[m.offset:] - - for i < len(runes) && w <= m.Width { - w += rw.RuneWidth(runes[i]) - if w <= m.Width+1 { - i++ - } - } - - m.offsetRight = m.offset + i - } else if m.pos >= m.offsetRight { - m.offsetRight = m.pos - - w := 0 - runes := m.value[:m.offsetRight] - i := len(runes) - 1 - - for i > 0 && w < m.Width { - w += rw.RuneWidth(runes[i]) - if w <= m.Width { - i-- - } - } - - m.offset = m.offsetRight - (len(runes) - 1 - i) - } -} - -// deleteBeforeCursor deletes all text before the cursor. -func (m *Model) deleteBeforeCursor() { - m.value = m.value[m.pos:] - m.Err = m.validate(m.value) - m.offset = 0 - m.SetCursor(0) -} - -// deleteAfterCursor deletes all text after the cursor. If input is masked -// delete everything after the cursor so as not to reveal word breaks in the -// masked input. -func (m *Model) deleteAfterCursor() { - m.value = m.value[:m.pos] - m.Err = m.validate(m.value) - m.SetCursor(len(m.value)) -} - -// deleteWordBackward deletes the word left to the cursor. -func (m *Model) deleteWordBackward() { - if m.pos == 0 || len(m.value) == 0 { - return - } - - if m.EchoMode != EchoNormal { - m.deleteBeforeCursor() - return - } - - // Linter note: it's critical that we acquire the initial cursor position - // here prior to altering it via SetCursor() below. As such, moving this - // call into the corresponding if clause does not apply here. - oldPos := m.pos //nolint:ifshort - - m.SetCursor(m.pos - 1) - for unicode.IsSpace(m.value[m.pos]) { - if m.pos <= 0 { - break - } - // ignore series of whitespace before cursor - m.SetCursor(m.pos - 1) - } - - for m.pos > 0 { - if !unicode.IsSpace(m.value[m.pos]) { - m.SetCursor(m.pos - 1) - } else { - if m.pos > 0 { - // keep the previous space - m.SetCursor(m.pos + 1) - } - break - } - } - - if oldPos > len(m.value) { - m.value = m.value[:m.pos] - } else { - m.value = append(m.value[:m.pos], m.value[oldPos:]...) - } - m.Err = m.validate(m.value) -} - -// deleteWordForward deletes the word right to the cursor. If input is masked -// delete everything after the cursor so as not to reveal word breaks in the -// masked input. -func (m *Model) deleteWordForward() { - if m.pos >= len(m.value) || len(m.value) == 0 { - return - } - - if m.EchoMode != EchoNormal { - m.deleteAfterCursor() - return - } - - oldPos := m.pos - m.SetCursor(m.pos + 1) - for unicode.IsSpace(m.value[m.pos]) { - // ignore series of whitespace after cursor - m.SetCursor(m.pos + 1) - - if m.pos >= len(m.value) { - break - } - } - - for m.pos < len(m.value) { - if !unicode.IsSpace(m.value[m.pos]) { - m.SetCursor(m.pos + 1) - } else { - break - } - } - - if m.pos > len(m.value) { - m.value = m.value[:oldPos] - } else { - m.value = append(m.value[:oldPos], m.value[m.pos:]...) - } - m.Err = m.validate(m.value) - - m.SetCursor(oldPos) -} - -// wordBackward moves the cursor one word to the left. If input is masked, move -// input to the start so as not to reveal word breaks in the masked input. -func (m *Model) wordBackward() { - if m.pos == 0 || len(m.value) == 0 { - return - } - - if m.EchoMode != EchoNormal { - m.CursorStart() - return - } - - i := m.pos - 1 - for i >= 0 { - if unicode.IsSpace(m.value[i]) { - m.SetCursor(m.pos - 1) - i-- - } else { - break - } - } - - for i >= 0 { - if !unicode.IsSpace(m.value[i]) { - m.SetCursor(m.pos - 1) - i-- - } else { - break - } - } -} - -// wordForward moves the cursor one word to the right. If the input is masked, -// move input to the end so as not to reveal word breaks in the masked input. -func (m *Model) wordForward() { - if m.pos >= len(m.value) || len(m.value) == 0 { - return - } - - if m.EchoMode != EchoNormal { - m.CursorEnd() - return - } - - i := m.pos - for i < len(m.value) { - if unicode.IsSpace(m.value[i]) { - m.SetCursor(m.pos + 1) - i++ - } else { - break - } - } - - for i < len(m.value) { - if !unicode.IsSpace(m.value[i]) { - m.SetCursor(m.pos + 1) - i++ - } else { - break - } - } -} - -func (m Model) echoTransform(v string) string { - switch m.EchoMode { - case EchoPassword: - return strings.Repeat(string(m.EchoCharacter), uniseg.StringWidth(v)) - case EchoNone: - return "" - case EchoNormal: - return v - default: - return v - } -} - -// Update is the Bubble Tea update loop. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - if !m.focus { - return m, nil - } - - // Need to check for completion before, because key is configurable and might be double assigned - keyMsg, ok := msg.(tea.KeyMsg) - if ok && key.Matches(keyMsg, m.KeyMap.AcceptSuggestion) { - if m.canAcceptSuggestion() { - m.value = append(m.value, m.matchedSuggestions[m.currentSuggestionIndex][len(m.value):]...) - m.CursorEnd() - } - } - - // Let's remember where the position of the cursor currently is so that if - // the cursor position changes, we can reset the blink. - oldPos := m.pos - - switch msg := msg.(type) { - case tea.KeyMsg: - switch { - case key.Matches(msg, m.KeyMap.DeleteWordBackward): - m.deleteWordBackward() - case key.Matches(msg, m.KeyMap.DeleteCharacterBackward): - m.Err = nil - if len(m.value) > 0 { - m.value = append(m.value[:max(0, m.pos-1)], m.value[m.pos:]...) - m.Err = m.validate(m.value) - if m.pos > 0 { - m.SetCursor(m.pos - 1) - } - } - case key.Matches(msg, m.KeyMap.WordBackward): - m.wordBackward() - case key.Matches(msg, m.KeyMap.CharacterBackward): - if m.pos > 0 { - m.SetCursor(m.pos - 1) - } - case key.Matches(msg, m.KeyMap.WordForward): - m.wordForward() - case key.Matches(msg, m.KeyMap.CharacterForward): - if m.pos < len(m.value) { - m.SetCursor(m.pos + 1) - } - case key.Matches(msg, m.KeyMap.LineStart): - m.CursorStart() - case key.Matches(msg, m.KeyMap.DeleteCharacterForward): - if len(m.value) > 0 && m.pos < len(m.value) { - m.value = append(m.value[:m.pos], m.value[m.pos+1:]...) - m.Err = m.validate(m.value) - } - case key.Matches(msg, m.KeyMap.LineEnd): - m.CursorEnd() - case key.Matches(msg, m.KeyMap.DeleteAfterCursor): - m.deleteAfterCursor() - case key.Matches(msg, m.KeyMap.DeleteBeforeCursor): - m.deleteBeforeCursor() - case key.Matches(msg, m.KeyMap.Paste): - return m, Paste - case key.Matches(msg, m.KeyMap.DeleteWordForward): - m.deleteWordForward() - case key.Matches(msg, m.KeyMap.NextSuggestion): - m.nextSuggestion() - case key.Matches(msg, m.KeyMap.PrevSuggestion): - m.previousSuggestion() - default: - // Input one or more regular characters. - m.insertRunesFromUserInput(msg.Runes) - } - - // Check again if can be completed - // because value might be something that does not match the completion prefix - m.updateSuggestions() - - case pasteMsg: - m.insertRunesFromUserInput([]rune(msg)) - - case pasteErrMsg: - m.Err = msg - } - - var cmds []tea.Cmd - var cmd tea.Cmd - - m.Cursor, cmd = m.Cursor.Update(msg) - cmds = append(cmds, cmd) - - if oldPos != m.pos && m.Cursor.Mode() == cursor.CursorBlink { - m.Cursor.Blink = false - cmds = append(cmds, m.Cursor.BlinkCmd()) - } - - m.handleOverflow() - return m, tea.Batch(cmds...) -} - -// View renders the textinput in its current state. -func (m Model) View() string { - // Placeholder text - if len(m.value) == 0 && m.Placeholder != "" { - return m.placeholderView() - } - - styleText := m.TextStyle.Inline(true).Render - - value := m.value[m.offset:m.offsetRight] - pos := max(0, m.pos-m.offset) - v := styleText(m.echoTransform(string(value[:pos]))) - - if pos < len(value) { //nolint:nestif - char := m.echoTransform(string(value[pos])) - m.Cursor.SetChar(char) - v += m.Cursor.View() // cursor and text under it - v += styleText(m.echoTransform(string(value[pos+1:]))) // text after cursor - v += m.completionView(0) // suggested completion - } else { - if m.focus && m.canAcceptSuggestion() { - suggestion := m.matchedSuggestions[m.currentSuggestionIndex] - if len(value) < len(suggestion) { - m.Cursor.TextStyle = m.CompletionStyle - m.Cursor.SetChar(m.echoTransform(string(suggestion[pos]))) - v += m.Cursor.View() - v += m.completionView(1) - } else { - m.Cursor.SetChar(" ") - v += m.Cursor.View() - } - } else { - m.Cursor.SetChar(" ") - v += m.Cursor.View() - } - } - - // If a max width and background color were set fill the empty spaces with - // the background color. - valWidth := uniseg.StringWidth(string(value)) - if m.Width > 0 && valWidth <= m.Width { - padding := max(0, m.Width-valWidth) - if valWidth+padding <= m.Width && pos < len(value) { - padding++ - } - v += styleText(strings.Repeat(" ", padding)) - } - - return m.PromptStyle.Render(m.Prompt) + v -} - -// placeholderView returns the prompt and placeholder view, if any. -func (m Model) placeholderView() string { - var ( - v string - style = m.PlaceholderStyle.Inline(true).Render - ) - - p := make([]rune, m.Width+1) - copy(p, []rune(m.Placeholder)) - - m.Cursor.TextStyle = m.PlaceholderStyle - m.Cursor.SetChar(string(p[:1])) - v += m.Cursor.View() - - // If the entire placeholder is already set and no padding is needed, finish - if m.Width < 1 && len(p) <= 1 { - return m.PromptStyle.Render(m.Prompt) + v - } - - // If Width is set then size placeholder accordingly - if m.Width > 0 { - // available width is width - len + cursor offset of 1 - minWidth := lipgloss.Width(m.Placeholder) - availWidth := m.Width - minWidth + 1 - - // if width < len, 'subtract'(add) number to len and dont add padding - if availWidth < 0 { - minWidth += availWidth - availWidth = 0 - } - // append placeholder[len] - cursor, append padding - v += style(string(p[1:minWidth])) - v += style(strings.Repeat(" ", availWidth)) - } else { - // if there is no width, the placeholder can be any length - v += style(string(p[1:])) - } - - return m.PromptStyle.Render(m.Prompt) + v -} - -// Blink is a command used to initialize cursor blinking. -func Blink() tea.Msg { - return cursor.Blink() -} - -// Paste is a command for pasting from the clipboard into the text input. -func Paste() tea.Msg { - str, err := clipboard.ReadAll() - if err != nil { - return pasteErrMsg{err} - } - return pasteMsg(str) -} - -func clamp(v, low, high int) int { - if high < low { - low, high = high, low - } - return min(high, max(low, v)) -} - -// Deprecated. - -// Deprecated: use [cursor.Mode]. -// -//nolint:revive -type CursorMode int - -//nolint:revive -const ( - // Deprecated: use [cursor.CursorBlink]. - CursorBlink = CursorMode(cursor.CursorBlink) - // Deprecated: use [cursor.CursorStatic]. - CursorStatic = CursorMode(cursor.CursorStatic) - // Deprecated: use [cursor.CursorHide]. - CursorHide = CursorMode(cursor.CursorHide) -) - -func (c CursorMode) String() string { - return cursor.Mode(c).String() -} - -// Deprecated: use [cursor.Mode]. -// -//nolint:revive -func (m Model) CursorMode() CursorMode { - return CursorMode(m.Cursor.Mode()) -} - -// Deprecated: use cursor.SetMode(). -// -//nolint:revive -func (m *Model) SetCursorMode(mode CursorMode) tea.Cmd { - return m.Cursor.SetMode(cursor.Mode(mode)) -} - -func (m Model) completionView(offset int) string { - var ( - value = m.value - style = m.PlaceholderStyle.Inline(true).Render - ) - - if m.canAcceptSuggestion() { - suggestion := m.matchedSuggestions[m.currentSuggestionIndex] - if len(value) < len(suggestion) { - return style(string(suggestion[len(value)+offset:])) - } - } - return "" -} - -func (m *Model) getSuggestions(sugs [][]rune) []string { - suggestions := make([]string, len(sugs)) - for i, s := range sugs { - suggestions[i] = string(s) - } - return suggestions -} - -// AvailableSuggestions returns the list of available suggestions. -func (m *Model) AvailableSuggestions() []string { - return m.getSuggestions(m.suggestions) -} - -// MatchedSuggestions returns the list of matched suggestions. -func (m *Model) MatchedSuggestions() []string { - return m.getSuggestions(m.matchedSuggestions) -} - -// CurrentSuggestionIndex returns the currently selected suggestion index. -func (m *Model) CurrentSuggestionIndex() int { - return m.currentSuggestionIndex -} - -// CurrentSuggestion returns the currently selected suggestion. -func (m *Model) CurrentSuggestion() string { - if m.currentSuggestionIndex >= len(m.matchedSuggestions) { - return "" - } - - return string(m.matchedSuggestions[m.currentSuggestionIndex]) -} - -// canAcceptSuggestion returns whether there is an acceptable suggestion to -// autocomplete the current value. -func (m *Model) canAcceptSuggestion() bool { - return len(m.matchedSuggestions) > 0 -} - -// updateSuggestions refreshes the list of matching suggestions. -func (m *Model) updateSuggestions() { - if !m.ShowSuggestions { - return - } - - if len(m.value) <= 0 || len(m.suggestions) <= 0 { - m.matchedSuggestions = [][]rune{} - return - } - - matches := [][]rune{} - for _, s := range m.suggestions { - suggestion := string(s) - - if strings.HasPrefix(strings.ToLower(suggestion), strings.ToLower(string(m.value))) { - matches = append(matches, []rune(suggestion)) - } - } - if !reflect.DeepEqual(matches, m.matchedSuggestions) { - m.currentSuggestionIndex = 0 - } - - m.matchedSuggestions = matches -} - -// nextSuggestion selects the next suggestion. -func (m *Model) nextSuggestion() { - m.currentSuggestionIndex = (m.currentSuggestionIndex + 1) - if m.currentSuggestionIndex >= len(m.matchedSuggestions) { - m.currentSuggestionIndex = 0 - } -} - -// previousSuggestion selects the previous suggestion. -func (m *Model) previousSuggestion() { - m.currentSuggestionIndex = (m.currentSuggestionIndex - 1) - if m.currentSuggestionIndex < 0 { - m.currentSuggestionIndex = len(m.matchedSuggestions) - 1 - } -} - -func (m Model) validate(v []rune) error { - if m.Validate != nil { - return m.Validate(string(v)) - } - return nil -} diff --git a/vendor/github.com/charmbracelet/bubbles/viewport/keymap.go b/vendor/github.com/charmbracelet/bubbles/viewport/keymap.go deleted file mode 100644 index 86eff98a..00000000 --- a/vendor/github.com/charmbracelet/bubbles/viewport/keymap.go +++ /dev/null @@ -1,60 +0,0 @@ -// Package viewport provides a component for rendering a viewport in a Bubble -// Tea. -package viewport - -import "github.com/charmbracelet/bubbles/key" - -const spacebar = " " - -// KeyMap defines the keybindings for the viewport. Note that you don't -// necessary need to use keybindings at all; the viewport can be controlled -// programmatically with methods like Model.LineDown(1). See the GoDocs for -// details. -type KeyMap struct { - PageDown key.Binding - PageUp key.Binding - HalfPageUp key.Binding - HalfPageDown key.Binding - Down key.Binding - Up key.Binding - Left key.Binding - Right key.Binding -} - -// DefaultKeyMap returns a set of pager-like default keybindings. -func DefaultKeyMap() KeyMap { - return KeyMap{ - PageDown: key.NewBinding( - key.WithKeys("pgdown", spacebar, "f"), - key.WithHelp("f/pgdn", "page down"), - ), - PageUp: key.NewBinding( - key.WithKeys("pgup", "b"), - key.WithHelp("b/pgup", "page up"), - ), - HalfPageUp: key.NewBinding( - key.WithKeys("u", "ctrl+u"), - key.WithHelp("u", "½ page up"), - ), - HalfPageDown: key.NewBinding( - key.WithKeys("d", "ctrl+d"), - key.WithHelp("d", "½ page down"), - ), - Up: key.NewBinding( - key.WithKeys("up", "k"), - key.WithHelp("↑/k", "up"), - ), - Down: key.NewBinding( - key.WithKeys("down", "j"), - key.WithHelp("↓/j", "down"), - ), - Left: key.NewBinding( - key.WithKeys("left", "h"), - key.WithHelp("←/h", "move left"), - ), - Right: key.NewBinding( - key.WithKeys("right", "l"), - key.WithHelp("→/l", "move right"), - ), - } -} diff --git a/vendor/github.com/charmbracelet/bubbles/viewport/viewport.go b/vendor/github.com/charmbracelet/bubbles/viewport/viewport.go deleted file mode 100644 index 5862ac05..00000000 --- a/vendor/github.com/charmbracelet/bubbles/viewport/viewport.go +++ /dev/null @@ -1,544 +0,0 @@ -package viewport - -import ( - "math" - "strings" - - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/x/ansi" -) - -// New returns a new model with the given width and height as well as default -// key mappings. -func New(width, height int) (m Model) { - m.Width = width - m.Height = height - m.setInitialValues() - return m -} - -// Model is the Bubble Tea model for this viewport element. -type Model struct { - Width int - Height int - KeyMap KeyMap - - // Whether or not to respond to the mouse. The mouse must be enabled in - // Bubble Tea for this to work. For details, see the Bubble Tea docs. - MouseWheelEnabled bool - - // The number of lines the mouse wheel will scroll. By default, this is 3. - MouseWheelDelta int - - // YOffset is the vertical scroll position. - YOffset int - - // xOffset is the horizontal scroll position. - xOffset int - - // horizontalStep is the number of columns we move left or right during a - // default horizontal scroll. - horizontalStep int - - // YPosition is the position of the viewport in relation to the terminal - // window. It's used in high performance rendering only. - YPosition int - - // Style applies a lipgloss style to the viewport. Realistically, it's most - // useful for setting borders, margins and padding. - Style lipgloss.Style - - // HighPerformanceRendering bypasses the normal Bubble Tea renderer to - // provide higher performance rendering. Most of the time the normal Bubble - // Tea rendering methods will suffice, but if you're passing content with - // a lot of ANSI escape codes you may see improved rendering in certain - // terminals with this enabled. - // - // This should only be used in program occupying the entire terminal, - // which is usually via the alternate screen buffer. - // - // Deprecated: high performance rendering is now deprecated in Bubble Tea. - HighPerformanceRendering bool - - initialized bool - lines []string - longestLineWidth int -} - -func (m *Model) setInitialValues() { - m.KeyMap = DefaultKeyMap() - m.MouseWheelEnabled = true - m.MouseWheelDelta = 3 - m.initialized = true -} - -// Init exists to satisfy the tea.Model interface for composability purposes. -func (m Model) Init() tea.Cmd { - return nil -} - -// AtTop returns whether or not the viewport is at the very top position. -func (m Model) AtTop() bool { - return m.YOffset <= 0 -} - -// AtBottom returns whether or not the viewport is at or past the very bottom -// position. -func (m Model) AtBottom() bool { - return m.YOffset >= m.maxYOffset() -} - -// PastBottom returns whether or not the viewport is scrolled beyond the last -// line. This can happen when adjusting the viewport height. -func (m Model) PastBottom() bool { - return m.YOffset > m.maxYOffset() -} - -// ScrollPercent returns the amount scrolled as a float between 0 and 1. -func (m Model) ScrollPercent() float64 { - if m.Height >= len(m.lines) { - return 1.0 - } - y := float64(m.YOffset) - h := float64(m.Height) - t := float64(len(m.lines)) - v := y / (t - h) - return math.Max(0.0, math.Min(1.0, v)) -} - -// HorizontalScrollPercent returns the amount horizontally scrolled as a float -// between 0 and 1. -func (m Model) HorizontalScrollPercent() float64 { - if m.xOffset >= m.longestLineWidth-m.Width { - return 1.0 - } - y := float64(m.xOffset) - h := float64(m.Width) - t := float64(m.longestLineWidth) - v := y / (t - h) - return math.Max(0.0, math.Min(1.0, v)) -} - -// SetContent set the pager's text content. -func (m *Model) SetContent(s string) { - s = strings.ReplaceAll(s, "\r\n", "\n") // normalize line endings - m.lines = strings.Split(s, "\n") - m.longestLineWidth = findLongestLineWidth(m.lines) - - if m.YOffset > len(m.lines)-1 { - m.GotoBottom() - } -} - -// maxYOffset returns the maximum possible value of the y-offset based on the -// viewport's content and set height. -func (m Model) maxYOffset() int { - return max(0, len(m.lines)-m.Height+m.Style.GetVerticalFrameSize()) -} - -// visibleLines returns the lines that should currently be visible in the -// viewport. -func (m Model) visibleLines() (lines []string) { - h := m.Height - m.Style.GetVerticalFrameSize() - w := m.Width - m.Style.GetHorizontalFrameSize() - - if len(m.lines) > 0 { - top := max(0, m.YOffset) - bottom := clamp(m.YOffset+h, top, len(m.lines)) - lines = m.lines[top:bottom] - } - - if (m.xOffset == 0 && m.longestLineWidth <= w) || w == 0 { - return lines - } - - cutLines := make([]string, len(lines)) - for i := range lines { - cutLines[i] = ansi.Cut(lines[i], m.xOffset, m.xOffset+w) - } - return cutLines -} - -// scrollArea returns the scrollable boundaries for high performance rendering. -// -// Deprecated: high performance rendering is deprecated in Bubble Tea. -func (m Model) scrollArea() (top, bottom int) { - top = max(0, m.YPosition) - bottom = max(top, top+m.Height) - if top > 0 && bottom > top { - bottom-- - } - return top, bottom -} - -// SetYOffset sets the Y offset. -func (m *Model) SetYOffset(n int) { - m.YOffset = clamp(n, 0, m.maxYOffset()) -} - -// ViewDown moves the view down by the number of lines in the viewport. -// Basically, "page down". -// -// Deprecated: use [Model.PageDown] instead. -func (m *Model) ViewDown() []string { - return m.PageDown() -} - -// PageDown moves the view down by the number of lines in the viewport. -func (m *Model) PageDown() []string { - if m.AtBottom() { - return nil - } - - return m.ScrollDown(m.Height) -} - -// ViewUp moves the view up by one height of the viewport. -// Basically, "page up". -// -// Deprecated: use [Model.PageUp] instead. -func (m *Model) ViewUp() []string { - return m.PageUp() -} - -// PageUp moves the view up by one height of the viewport. -func (m *Model) PageUp() []string { - if m.AtTop() { - return nil - } - - return m.ScrollUp(m.Height) -} - -// HalfViewDown moves the view down by half the height of the viewport. -// -// Deprecated: use [Model.HalfPageDown] instead. -func (m *Model) HalfViewDown() (lines []string) { - return m.HalfPageDown() -} - -// HalfPageDown moves the view down by half the height of the viewport. -func (m *Model) HalfPageDown() (lines []string) { - if m.AtBottom() { - return nil - } - - return m.ScrollDown(m.Height / 2) //nolint:mnd -} - -// HalfViewUp moves the view up by half the height of the viewport. -// -// Deprecated: use [Model.HalfPageUp] instead. -func (m *Model) HalfViewUp() (lines []string) { - return m.HalfPageUp() -} - -// HalfPageUp moves the view up by half the height of the viewport. -func (m *Model) HalfPageUp() (lines []string) { - if m.AtTop() { - return nil - } - - return m.ScrollUp(m.Height / 2) //nolint:mnd -} - -// LineDown moves the view down by the given number of lines. -// -// Deprecated: use [Model.ScrollDown] instead. -func (m *Model) LineDown(n int) (lines []string) { - return m.ScrollDown(n) -} - -// ScrollDown moves the view down by the given number of lines. -func (m *Model) ScrollDown(n int) (lines []string) { - if m.AtBottom() || n == 0 || len(m.lines) == 0 { - return nil - } - - // Make sure the number of lines by which we're going to scroll isn't - // greater than the number of lines we actually have left before we reach - // the bottom. - m.SetYOffset(m.YOffset + n) - - // Gather lines to send off for performance scrolling. - // - // XXX: high performance rendering is deprecated in Bubble Tea. - bottom := clamp(m.YOffset+m.Height, 0, len(m.lines)) - top := clamp(m.YOffset+m.Height-n, 0, bottom) - return m.lines[top:bottom] -} - -// LineUp moves the view down by the given number of lines. Returns the new -// lines to show. -// -// Deprecated: use [Model.ScrollUp] instead. -func (m *Model) LineUp(n int) (lines []string) { - return m.ScrollUp(n) -} - -// ScrollUp moves the view down by the given number of lines. Returns the new -// lines to show. -func (m *Model) ScrollUp(n int) (lines []string) { - if m.AtTop() || n == 0 || len(m.lines) == 0 { - return nil - } - - // Make sure the number of lines by which we're going to scroll isn't - // greater than the number of lines we are from the top. - m.SetYOffset(m.YOffset - n) - - // Gather lines to send off for performance scrolling. - // - // XXX: high performance rendering is deprecated in Bubble Tea. - top := max(0, m.YOffset) - bottom := clamp(m.YOffset+n, 0, m.maxYOffset()) - return m.lines[top:bottom] -} - -// SetHorizontalStep sets the default amount of columns to scroll left or right -// with the default viewport key map. -// -// If set to 0 or less, horizontal scrolling is disabled. -// -// On v1, horizontal scrolling is disabled by default. -func (m *Model) SetHorizontalStep(n int) { - m.horizontalStep = max(n, 0) -} - -// SetXOffset sets the X offset. -func (m *Model) SetXOffset(n int) { - m.xOffset = clamp(n, 0, m.longestLineWidth-m.Width) -} - -// ScrollLeft moves the viewport to the left by the given number of columns. -func (m *Model) ScrollLeft(n int) { - m.SetXOffset(m.xOffset - n) -} - -// ScrollRight moves viewport to the right by the given number of columns. -func (m *Model) ScrollRight(n int) { - m.SetXOffset(m.xOffset + n) -} - -// TotalLineCount returns the total number of lines (both hidden and visible) within the viewport. -func (m Model) TotalLineCount() int { - return len(m.lines) -} - -// VisibleLineCount returns the number of the visible lines within the viewport. -func (m Model) VisibleLineCount() int { - return len(m.visibleLines()) -} - -// GotoTop sets the viewport to the top position. -func (m *Model) GotoTop() (lines []string) { - if m.AtTop() { - return nil - } - - m.SetYOffset(0) - return m.visibleLines() -} - -// GotoBottom sets the viewport to the bottom position. -func (m *Model) GotoBottom() (lines []string) { - m.SetYOffset(m.maxYOffset()) - return m.visibleLines() -} - -// Sync tells the renderer where the viewport will be located and requests -// a render of the current state of the viewport. It should be called for the -// first render and after a window resize. -// -// For high performance rendering only. -// -// Deprecated: high performance rendering is deprecated in Bubble Tea. -func Sync(m Model) tea.Cmd { - if len(m.lines) == 0 { - return nil - } - top, bottom := m.scrollArea() - return tea.SyncScrollArea(m.visibleLines(), top, bottom) -} - -// ViewDown is a high performance command that moves the viewport up by a given -// number of lines. Use Model.ViewDown to get the lines that should be rendered. -// For example: -// -// lines := model.ViewDown(1) -// cmd := ViewDown(m, lines) -// -// Deprecated: high performance rendering is deprecated in Bubble Tea. -func ViewDown(m Model, lines []string) tea.Cmd { - if len(lines) == 0 { - return nil - } - top, bottom := m.scrollArea() - - // XXX: high performance rendering is deprecated in Bubble Tea. In a v2 we - // won't need to return a command here. - return tea.ScrollDown(lines, top, bottom) -} - -// ViewUp is a high performance command the moves the viewport down by a given -// number of lines height. Use Model.ViewUp to get the lines that should be -// rendered. -// -// Deprecated: high performance rendering is deprecated in Bubble Tea. -func ViewUp(m Model, lines []string) tea.Cmd { - if len(lines) == 0 { - return nil - } - top, bottom := m.scrollArea() - - // XXX: high performance rendering is deprecated in Bubble Tea. In a v2 we - // won't need to return a command here. - return tea.ScrollUp(lines, top, bottom) -} - -// Update handles standard message-based viewport updates. -func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { - var cmd tea.Cmd - m, cmd = m.updateAsModel(msg) - return m, cmd -} - -// Author's note: this method has been broken out to make it easier to -// potentially transition Update to satisfy tea.Model. -func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) { - if !m.initialized { - m.setInitialValues() - } - - var cmd tea.Cmd - - switch msg := msg.(type) { - case tea.KeyMsg: - switch { - case key.Matches(msg, m.KeyMap.PageDown): - lines := m.PageDown() - if m.HighPerformanceRendering { - cmd = ViewDown(m, lines) - } - - case key.Matches(msg, m.KeyMap.PageUp): - lines := m.PageUp() - if m.HighPerformanceRendering { - cmd = ViewUp(m, lines) - } - - case key.Matches(msg, m.KeyMap.HalfPageDown): - lines := m.HalfPageDown() - if m.HighPerformanceRendering { - cmd = ViewDown(m, lines) - } - - case key.Matches(msg, m.KeyMap.HalfPageUp): - lines := m.HalfPageUp() - if m.HighPerformanceRendering { - cmd = ViewUp(m, lines) - } - - case key.Matches(msg, m.KeyMap.Down): - lines := m.ScrollDown(1) - if m.HighPerformanceRendering { - cmd = ViewDown(m, lines) - } - - case key.Matches(msg, m.KeyMap.Up): - lines := m.ScrollUp(1) - if m.HighPerformanceRendering { - cmd = ViewUp(m, lines) - } - - case key.Matches(msg, m.KeyMap.Left): - m.ScrollLeft(m.horizontalStep) - - case key.Matches(msg, m.KeyMap.Right): - m.ScrollRight(m.horizontalStep) - } - - case tea.MouseMsg: - if !m.MouseWheelEnabled || msg.Action != tea.MouseActionPress { - break - } - switch msg.Button { //nolint:exhaustive - case tea.MouseButtonWheelUp: - if msg.Shift { - // Note that not every terminal emulator sends the shift event for mouse actions by default (looking at you Konsole) - m.ScrollLeft(m.horizontalStep) - } else { - lines := m.ScrollUp(m.MouseWheelDelta) - if m.HighPerformanceRendering { - cmd = ViewUp(m, lines) - } - } - - case tea.MouseButtonWheelDown: - if msg.Shift { - m.ScrollRight(m.horizontalStep) - } else { - lines := m.ScrollDown(m.MouseWheelDelta) - if m.HighPerformanceRendering { - cmd = ViewDown(m, lines) - } - } - // Note that not every terminal emulator sends the horizontal wheel events by default (looking at you Konsole) - case tea.MouseButtonWheelLeft: - m.ScrollLeft(m.horizontalStep) - case tea.MouseButtonWheelRight: - m.ScrollRight(m.horizontalStep) - } - } - - return m, cmd -} - -// View renders the viewport into a string. -func (m Model) View() string { - if m.HighPerformanceRendering { - // Just send newlines since we're going to be rendering the actual - // content separately. We still need to send something that equals the - // height of this view so that the Bubble Tea standard renderer can - // position anything below this view properly. - return strings.Repeat("\n", max(0, m.Height-1)) - } - - w, h := m.Width, m.Height - if sw := m.Style.GetWidth(); sw != 0 { - w = min(w, sw) - } - if sh := m.Style.GetHeight(); sh != 0 { - h = min(h, sh) - } - contentWidth := w - m.Style.GetHorizontalFrameSize() - contentHeight := h - m.Style.GetVerticalFrameSize() - contents := lipgloss.NewStyle(). - Width(contentWidth). // pad to width. - Height(contentHeight). // pad to height. - MaxHeight(contentHeight). // truncate height if taller. - MaxWidth(contentWidth). // truncate width if wider. - Render(strings.Join(m.visibleLines(), "\n")) - return m.Style. - UnsetWidth().UnsetHeight(). // Style size already applied in contents. - Render(contents) -} - -func clamp(v, low, high int) int { - if high < low { - low, high = high, low - } - return min(high, max(low, v)) -} - -func findLongestLineWidth(lines []string) int { - w := 0 - for _, l := range lines { - if ww := ansi.StringWidth(l); ww > w { - w = ww - } - } - return w -} diff --git a/vendor/github.com/charmbracelet/bubbletea/.gitattributes b/vendor/github.com/charmbracelet/bubbletea/.gitattributes deleted file mode 100644 index 6c929d48..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.golden -text diff --git a/vendor/github.com/charmbracelet/bubbletea/.gitignore b/vendor/github.com/charmbracelet/bubbletea/.gitignore deleted file mode 100644 index abd7c061..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -.DS_Store -.envrc - -examples/fullscreen/fullscreen -examples/help/help -examples/http/http -examples/list-default/list-default -examples/list-fancy/list-fancy -examples/list-simple/list-simple -examples/mouse/mouse -examples/pager/pager -examples/progress-download/color_vortex.blend -examples/progress-download/progress-download -examples/simple/simple -examples/spinner/spinner -examples/textinput/textinput -examples/textinputs/textinputs -examples/views/views -tutorials/basics/basics -tutorials/commands/commands -.idea -coverage.txt -dist/ diff --git a/vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml b/vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml deleted file mode 100644 index d325d4fc..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml +++ /dev/null @@ -1,40 +0,0 @@ -run: - tests: false - issues-exit-code: 0 - -issues: - include: - - EXC0001 - - EXC0005 - - EXC0011 - - EXC0012 - - EXC0013 - - max-issues-per-linter: 0 - max-same-issues: 0 - -linters: - enable: - - exhaustive - - goconst - - godot - - godox - - mnd - - gomoddirectives - - goprintffuncname - - misspell - - nakedret - - nestif - - noctx - - nolintlint - - prealloc - - wrapcheck - - # disable default linters, they are already enabled in .golangci.yml - disable: - - errcheck - - gosimple - - govet - - ineffassign - - staticcheck - - unused diff --git a/vendor/github.com/charmbracelet/bubbletea/.golangci.yml b/vendor/github.com/charmbracelet/bubbletea/.golangci.yml deleted file mode 100644 index d6789e01..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/.golangci.yml +++ /dev/null @@ -1,28 +0,0 @@ -run: - tests: false - -issues: - include: - - EXC0001 - - EXC0005 - - EXC0011 - - EXC0012 - - EXC0013 - - max-issues-per-linter: 0 - max-same-issues: 0 - -linters: - enable: - - bodyclose - - gofumpt - - goimports - - gosec - - nilerr - - revive - - rowserrcheck - - sqlclosecheck - - tparallel - - unconvert - - unparam - - whitespace diff --git a/vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml b/vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml deleted file mode 100644 index 3353d020..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml +++ /dev/null @@ -1,5 +0,0 @@ -# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json -version: 2 -includes: - - from_url: - url: charmbracelet/meta/main/goreleaser-lib.yaml diff --git a/vendor/github.com/charmbracelet/bubbletea/LICENSE b/vendor/github.com/charmbracelet/bubbletea/LICENSE deleted file mode 100644 index 31d76c1c..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020-2023 Charmbracelet, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/charmbracelet/bubbletea/README.md b/vendor/github.com/charmbracelet/bubbletea/README.md deleted file mode 100644 index 58dd1828..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/README.md +++ /dev/null @@ -1,396 +0,0 @@ -# Bubble Tea - -

- Bubble Tea Title Treatment
- Latest Release - GoDoc - Build Status - phorm.ai -

- -The fun, functional and stateful way to build terminal apps. A Go framework -based on [The Elm Architecture][elm]. Bubble Tea is well-suited for simple and -complex terminal applications, either inline, full-window, or a mix of both. - -

- Bubble Tea Example -

- -Bubble Tea is in use in production and includes a number of features and -performance optimizations we’ve added along the way. Among those is -a framerate-based renderer, mouse support, focus reporting and more. - -To get started, see the tutorial below, the [examples][examples], the -[docs][docs], the [video tutorials][youtube] and some common [resources](#libraries-we-use-with-bubble-tea). - -[youtube]: https://charm.sh/yt - -## By the way - -Be sure to check out [Bubbles][bubbles], a library of common UI components for Bubble Tea. - -

- Bubbles Badge   - Text Input Example from Bubbles -

- ---- - -## Tutorial - -Bubble Tea is based on the functional design paradigms of [The Elm -Architecture][elm], which happens to work nicely with Go. It's a delightful way -to build applications. - -This tutorial assumes you have a working knowledge of Go. - -By the way, the non-annotated source code for this program is available -[on GitHub][tut-source]. - -[elm]: https://guide.elm-lang.org/architecture/ -[tut-source]: https://github.com/charmbracelet/bubbletea/tree/main/tutorials/basics - -### Enough! Let's get to it. - -For this tutorial, we're making a shopping list. - -To start we'll define our package and import some libraries. Our only external -import will be the Bubble Tea library, which we'll call `tea` for short. - -```go -package main - -// These imports will be used later on the tutorial. If you save the file -// now, Go might complain they are unused, but that's fine. -// You may also need to run `go mod tidy` to download bubbletea and its -// dependencies. -import ( - "fmt" - "os" - - tea "github.com/charmbracelet/bubbletea" -) -``` - -Bubble Tea programs are comprised of a **model** that describes the application -state and three simple methods on that model: - -- **Init**, a function that returns an initial command for the application to run. -- **Update**, a function that handles incoming events and updates the model accordingly. -- **View**, a function that renders the UI based on the data in the model. - -### The Model - -So let's start by defining our model which will store our application's state. -It can be any type, but a `struct` usually makes the most sense. - -```go -type model struct { - choices []string // items on the to-do list - cursor int // which to-do list item our cursor is pointing at - selected map[int]struct{} // which to-do items are selected -} -``` - -### Initialization - -Next, we’ll define our application’s initial state. In this case, we’re defining -a function to return our initial model, however, we could just as easily define -the initial model as a variable elsewhere, too. - -```go -func initialModel() model { - return model{ - // Our to-do list is a grocery list - choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"}, - - // A map which indicates which choices are selected. We're using - // the map like a mathematical set. The keys refer to the indexes - // of the `choices` slice, above. - selected: make(map[int]struct{}), - } -} -``` - -Next, we define the `Init` method. `Init` can return a `Cmd` that could perform -some initial I/O. For now, we don't need to do any I/O, so for the command, -we'll just return `nil`, which translates to "no command." - -```go -func (m model) Init() tea.Cmd { - // Just return `nil`, which means "no I/O right now, please." - return nil -} -``` - -### The Update Method - -Next up is the update method. The update function is called when ”things -happen.” Its job is to look at what has happened and return an updated model in -response. It can also return a `Cmd` to make more things happen, but for now -don't worry about that part. - -In our case, when a user presses the down arrow, `Update`’s job is to notice -that the down arrow was pressed and move the cursor accordingly (or not). - -The “something happened” comes in the form of a `Msg`, which can be any type. -Messages are the result of some I/O that took place, such as a keypress, timer -tick, or a response from a server. - -We usually figure out which type of `Msg` we received with a type switch, but -you could also use a type assertion. - -For now, we'll just deal with `tea.KeyMsg` messages, which are automatically -sent to the update function when keys are pressed. - -```go -func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - - // Is it a key press? - case tea.KeyMsg: - - // Cool, what was the actual key pressed? - switch msg.String() { - - // These keys should exit the program. - case "ctrl+c", "q": - return m, tea.Quit - - // The "up" and "k" keys move the cursor up - case "up", "k": - if m.cursor > 0 { - m.cursor-- - } - - // The "down" and "j" keys move the cursor down - case "down", "j": - if m.cursor < len(m.choices)-1 { - m.cursor++ - } - - // The "enter" key and the spacebar (a literal space) toggle - // the selected state for the item that the cursor is pointing at. - case "enter", " ": - _, ok := m.selected[m.cursor] - if ok { - delete(m.selected, m.cursor) - } else { - m.selected[m.cursor] = struct{}{} - } - } - } - - // Return the updated model to the Bubble Tea runtime for processing. - // Note that we're not returning a command. - return m, nil -} -``` - -You may have noticed that ctrl+c and q above return -a `tea.Quit` command with the model. That’s a special command which instructs -the Bubble Tea runtime to quit, exiting the program. - -### The View Method - -At last, it’s time to render our UI. Of all the methods, the view is the -simplest. We look at the model in its current state and use it to return -a `string`. That string is our UI! - -Because the view describes the entire UI of your application, you don’t have to -worry about redrawing logic and stuff like that. Bubble Tea takes care of it -for you. - -```go -func (m model) View() string { - // The header - s := "What should we buy at the market?\n\n" - - // Iterate over our choices - for i, choice := range m.choices { - - // Is the cursor pointing at this choice? - cursor := " " // no cursor - if m.cursor == i { - cursor = ">" // cursor! - } - - // Is this choice selected? - checked := " " // not selected - if _, ok := m.selected[i]; ok { - checked = "x" // selected! - } - - // Render the row - s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice) - } - - // The footer - s += "\nPress q to quit.\n" - - // Send the UI for rendering - return s -} -``` - -### All Together Now - -The last step is to simply run our program. We pass our initial model to -`tea.NewProgram` and let it rip: - -```go -func main() { - p := tea.NewProgram(initialModel()) - if _, err := p.Run(); err != nil { - fmt.Printf("Alas, there's been an error: %v", err) - os.Exit(1) - } -} -``` - -## What’s Next? - -This tutorial covers the basics of building an interactive terminal UI, but -in the real world you'll also need to perform I/O. To learn about that have a -look at the [Command Tutorial][cmd]. It's pretty simple. - -There are also several [Bubble Tea examples][examples] available and, of course, -there are [Go Docs][docs]. - -[cmd]: https://github.com/charmbracelet/bubbletea/tree/main/tutorials/commands/ -[examples]: https://github.com/charmbracelet/bubbletea/tree/main/examples -[docs]: https://pkg.go.dev/github.com/charmbracelet/bubbletea?tab=doc - -## Debugging - -### Debugging with Delve - -Since Bubble Tea apps assume control of stdin and stdout, you’ll need to run -delve in headless mode and then connect to it: - -```bash -# Start the debugger -$ dlv debug --headless --api-version=2 --listen=127.0.0.1:43000 . -API server listening at: 127.0.0.1:43000 - -# Connect to it from another terminal -$ dlv connect 127.0.0.1:43000 -``` - -If you do not explicitly supply the `--listen` flag, the port used will vary -per run, so passing this in makes the debugger easier to use from a script -or your IDE of choice. - -Additionally, we pass in `--api-version=2` because delve defaults to version 1 -for backwards compatibility reasons. However, delve recommends using version 2 -for all new development and some clients may no longer work with version 1. -For more information, see the [Delve documentation](https://github.com/go-delve/delve/tree/master/Documentation/api). - -### Logging Stuff - -You can’t really log to stdout with Bubble Tea because your TUI is busy -occupying that! You can, however, log to a file by including something like -the following prior to starting your Bubble Tea program: - -```go -if len(os.Getenv("DEBUG")) > 0 { - f, err := tea.LogToFile("debug.log", "debug") - if err != nil { - fmt.Println("fatal:", err) - os.Exit(1) - } - defer f.Close() -} -``` - -To see what’s being logged in real time, run `tail -f debug.log` while you run -your program in another window. - -## Libraries we use with Bubble Tea - -- [Bubbles][bubbles]: Common Bubble Tea components such as text inputs, viewports, spinners and so on -- [Lip Gloss][lipgloss]: Style, format and layout tools for terminal applications -- [Harmonica][harmonica]: A spring animation library for smooth, natural motion -- [BubbleZone][bubblezone]: Easy mouse event tracking for Bubble Tea components -- [ntcharts][ntcharts]: A terminal charting library built for Bubble Tea and [Lip Gloss][lipgloss] - -[bubbles]: https://github.com/charmbracelet/bubbles -[lipgloss]: https://github.com/charmbracelet/lipgloss -[harmonica]: https://github.com/charmbracelet/harmonica -[bubblezone]: https://github.com/lrstanley/bubblezone -[ntcharts]: https://github.com/NimbleMarkets/ntcharts - -## Bubble Tea in the Wild - -There are over [10,000 applications](https://github.com/charmbracelet/bubbletea/network/dependents) built with Bubble Tea! Here are a handful of ’em. - -### Staff favourites - -- [chezmoi](https://github.com/twpayne/chezmoi): securely manage your dotfiles across multiple machines -- [circumflex](https://github.com/bensadeh/circumflex): read Hacker News in the terminal -- [gh-dash](https://www.github.com/dlvhdr/gh-dash): a GitHub CLI extension for PRs and issues -- [Tetrigo](https://github.com/Broderick-Westrope/tetrigo): Tetris in the terminal -- [Signls](https://github.com/emprcl/signls): a generative midi sequencer designed for composition and live performance -- [Superfile](https://github.com/yorukot/superfile): a super file manager - -### In Industry - -- Microsoft Azure – [Aztify](https://github.com/Azure/aztfy): bring Microsoft Azure resources under Terraform -- Daytona – [Daytona](https://github.com/daytonaio/daytona): open source dev environment manager -- Cockroach Labs – [CockroachDB](https://github.com/cockroachdb/cockroach): a cloud-native, high-availability distributed SQL database -- Truffle Security Co. – [Trufflehog](https://github.com/trufflesecurity/trufflehog): find leaked credentials -- NVIDIA – [container-canary](https://github.com/NVIDIA/container-canary): a container validator -- AWS – [eks-node-viewer](https://github.com/awslabs/eks-node-viewer): a tool for visualizing dynamic node usage within an EKS cluster -- MinIO – [mc](https://github.com/minio/mc): the official [MinIO](https://min.io) client -- Ubuntu – [Authd](https://github.com/ubuntu/authd): an authentication daemon for cloud-based identity providers - -### Charm stuff - -- [Glow](https://github.com/charmbracelet/glow): a markdown reader, browser, and online markdown stash -- [Huh?](https://github.com/charmbracelet/huh): an interactive prompt and form toolkit -- [Mods](https://github.com/charmbracelet/mods): AI on the CLI, built for pipelines -- [Wishlist](https://github.com/charmbracelet/wishlist): an SSH directory (and bastion!) - -### There’s so much more where that came from - -For more applications built with Bubble Tea see [Charm & Friends][community]. -Is there something cool you made with Bubble Tea you want to share? [PRs][community] are -welcome! - -## Contributing - -See [contributing][contribute]. - -[contribute]: https://github.com/charmbracelet/bubbletea/contribute - -## Feedback - -We’d love to hear your thoughts on this project. Feel free to drop us a note! - -- [Twitter](https://twitter.com/charmcli) -- [The Fediverse](https://mastodon.social/@charmcli) -- [Discord](https://charm.sh/chat) - -## Acknowledgments - -Bubble Tea is based on the paradigms of [The Elm Architecture][elm] by Evan -Czaplicki et alia and the excellent [go-tea][gotea] by TJ Holowaychuk. It’s -inspired by the many great [_Zeichenorientierte Benutzerschnittstellen_][zb] -of days past. - -[elm]: https://guide.elm-lang.org/architecture/ -[gotea]: https://github.com/tj/go-tea -[zb]: https://de.wikipedia.org/wiki/Zeichenorientierte_Benutzerschnittstelle -[community]: https://github.com/charm-and-friends/charm-in-the-wild - -## License - -[MIT](https://github.com/charmbracelet/bubbletea/raw/main/LICENSE) - ---- - -Part of [Charm](https://charm.sh). - -The Charm logo - -Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة diff --git a/vendor/github.com/charmbracelet/bubbletea/commands.go b/vendor/github.com/charmbracelet/bubbletea/commands.go deleted file mode 100644 index bfa3b704..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/commands.go +++ /dev/null @@ -1,216 +0,0 @@ -package tea - -import ( - "time" -) - -// Batch performs a bunch of commands concurrently with no ordering guarantees -// about the results. Use a Batch to return several commands. -// -// Example: -// -// func (m model) Init() Cmd { -// return tea.Batch(someCommand, someOtherCommand) -// } -func Batch(cmds ...Cmd) Cmd { - var validCmds []Cmd //nolint:prealloc - for _, c := range cmds { - if c == nil { - continue - } - validCmds = append(validCmds, c) - } - switch len(validCmds) { - case 0: - return nil - case 1: - return validCmds[0] - default: - return func() Msg { - return BatchMsg(validCmds) - } - } -} - -// BatchMsg is a message used to perform a bunch of commands concurrently with -// no ordering guarantees. You can send a BatchMsg with Batch. -type BatchMsg []Cmd - -// Sequence runs the given commands one at a time, in order. Contrast this with -// Batch, which runs commands concurrently. -func Sequence(cmds ...Cmd) Cmd { - return func() Msg { - return sequenceMsg(cmds) - } -} - -// sequenceMsg is used internally to run the given commands in order. -type sequenceMsg []Cmd - -// Every is a command that ticks in sync with the system clock. So, if you -// wanted to tick with the system clock every second, minute or hour you -// could use this. It's also handy for having different things tick in sync. -// -// Because we're ticking with the system clock the tick will likely not run for -// the entire specified duration. For example, if we're ticking for one minute -// and the clock is at 12:34:20 then the next tick will happen at 12:35:00, 40 -// seconds later. -// -// To produce the command, pass a duration and a function which returns -// a message containing the time at which the tick occurred. -// -// type TickMsg time.Time -// -// cmd := Every(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// -// Beginners' note: Every sends a single message and won't automatically -// dispatch messages at an interval. To do that, you'll want to return another -// Every command after receiving your tick message. For example: -// -// type TickMsg time.Time -// -// // Send a message every second. -// func tickEvery() Cmd { -// return Every(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// } -// -// func (m model) Init() Cmd { -// // Start ticking. -// return tickEvery() -// } -// -// func (m model) Update(msg Msg) (Model, Cmd) { -// switch msg.(type) { -// case TickMsg: -// // Return your Every command again to loop. -// return m, tickEvery() -// } -// return m, nil -// } -// -// Every is analogous to Tick in the Elm Architecture. -func Every(duration time.Duration, fn func(time.Time) Msg) Cmd { - n := time.Now() - d := n.Truncate(duration).Add(duration).Sub(n) - t := time.NewTimer(d) - return func() Msg { - ts := <-t.C - t.Stop() - for len(t.C) > 0 { - <-t.C - } - return fn(ts) - } -} - -// Tick produces a command at an interval independent of the system clock at -// the given duration. That is, the timer begins precisely when invoked, -// and runs for its entire duration. -// -// To produce the command, pass a duration and a function which returns -// a message containing the time at which the tick occurred. -// -// type TickMsg time.Time -// -// cmd := Tick(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// -// Beginners' note: Tick sends a single message and won't automatically -// dispatch messages at an interval. To do that, you'll want to return another -// Tick command after receiving your tick message. For example: -// -// type TickMsg time.Time -// -// func doTick() Cmd { -// return Tick(time.Second, func(t time.Time) Msg { -// return TickMsg(t) -// }) -// } -// -// func (m model) Init() Cmd { -// // Start ticking. -// return doTick() -// } -// -// func (m model) Update(msg Msg) (Model, Cmd) { -// switch msg.(type) { -// case TickMsg: -// // Return your Tick command again to loop. -// return m, doTick() -// } -// return m, nil -// } -func Tick(d time.Duration, fn func(time.Time) Msg) Cmd { - t := time.NewTimer(d) - return func() Msg { - ts := <-t.C - t.Stop() - for len(t.C) > 0 { - <-t.C - } - return fn(ts) - } -} - -// Sequentially produces a command that sequentially executes the given -// commands. -// The Msg returned is the first non-nil message returned by a Cmd. -// -// func saveStateCmd() Msg { -// if err := save(); err != nil { -// return errMsg{err} -// } -// return nil -// } -// -// cmd := Sequentially(saveStateCmd, Quit) -// -// Deprecated: use Sequence instead. -func Sequentially(cmds ...Cmd) Cmd { - return func() Msg { - for _, cmd := range cmds { - if cmd == nil { - continue - } - if msg := cmd(); msg != nil { - return msg - } - } - return nil - } -} - -// setWindowTitleMsg is an internal message used to set the window title. -type setWindowTitleMsg string - -// SetWindowTitle produces a command that sets the terminal title. -// -// For example: -// -// func (m model) Init() Cmd { -// // Set title. -// return tea.SetWindowTitle("My App") -// } -func SetWindowTitle(title string) Cmd { - return func() Msg { - return setWindowTitleMsg(title) - } -} - -type windowSizeMsg struct{} - -// WindowSize is a command that queries the terminal for its current size. It -// delivers the results to Update via a [WindowSizeMsg]. Keep in mind that -// WindowSizeMsgs will automatically be delivered to Update when the [Program] -// starts and when the window dimensions change so in many cases you will not -// need to explicitly invoke this command. -func WindowSize() Cmd { - return func() Msg { - return windowSizeMsg{} - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/exec.go b/vendor/github.com/charmbracelet/bubbletea/exec.go deleted file mode 100644 index 7a14d2a7..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/exec.go +++ /dev/null @@ -1,129 +0,0 @@ -package tea - -import ( - "io" - "os" - "os/exec" -) - -// execMsg is used internally to run an ExecCommand sent with Exec. -type execMsg struct { - cmd ExecCommand - fn ExecCallback -} - -// Exec is used to perform arbitrary I/O in a blocking fashion, effectively -// pausing the Program while execution is running and resuming it when -// execution has completed. -// -// Most of the time you'll want to use ExecProcess, which runs an exec.Cmd. -// -// For non-interactive i/o you should use a Cmd (that is, a tea.Cmd). -func Exec(c ExecCommand, fn ExecCallback) Cmd { - return func() Msg { - return execMsg{cmd: c, fn: fn} - } -} - -// ExecProcess runs the given *exec.Cmd in a blocking fashion, effectively -// pausing the Program while the command is running. After the *exec.Cmd exists -// the Program resumes. It's useful for spawning other interactive applications -// such as editors and shells from within a Program. -// -// To produce the command, pass an *exec.Cmd and a function which returns -// a message containing the error which may have occurred when running the -// ExecCommand. -// -// type VimFinishedMsg struct { err error } -// -// c := exec.Command("vim", "file.txt") -// -// cmd := ExecProcess(c, func(err error) Msg { -// return VimFinishedMsg{err: err} -// }) -// -// Or, if you don't care about errors, you could simply: -// -// cmd := ExecProcess(exec.Command("vim", "file.txt"), nil) -// -// For non-interactive i/o you should use a Cmd (that is, a tea.Cmd). -func ExecProcess(c *exec.Cmd, fn ExecCallback) Cmd { - return Exec(wrapExecCommand(c), fn) -} - -// ExecCallback is used when executing an *exec.Command to return a message -// with an error, which may or may not be nil. -type ExecCallback func(error) Msg - -// ExecCommand can be implemented to execute things in a blocking fashion in -// the current terminal. -type ExecCommand interface { - Run() error - SetStdin(io.Reader) - SetStdout(io.Writer) - SetStderr(io.Writer) -} - -// wrapExecCommand wraps an exec.Cmd so that it satisfies the ExecCommand -// interface so it can be used with Exec. -func wrapExecCommand(c *exec.Cmd) ExecCommand { - return &osExecCommand{Cmd: c} -} - -// osExecCommand is a layer over an exec.Cmd that satisfies the ExecCommand -// interface. -type osExecCommand struct{ *exec.Cmd } - -// SetStdin sets stdin on underlying exec.Cmd to the given io.Reader. -func (c *osExecCommand) SetStdin(r io.Reader) { - // If unset, have the command use the same input as the terminal. - if c.Stdin == nil { - c.Stdin = r - } -} - -// SetStdout sets stdout on underlying exec.Cmd to the given io.Writer. -func (c *osExecCommand) SetStdout(w io.Writer) { - // If unset, have the command use the same output as the terminal. - if c.Stdout == nil { - c.Stdout = w - } -} - -// SetStderr sets stderr on the underlying exec.Cmd to the given io.Writer. -func (c *osExecCommand) SetStderr(w io.Writer) { - // If unset, use stderr for the command's stderr - if c.Stderr == nil { - c.Stderr = w - } -} - -// exec runs an ExecCommand and delivers the results to the program as a Msg. -func (p *Program) exec(c ExecCommand, fn ExecCallback) { - if err := p.ReleaseTerminal(); err != nil { - // If we can't release input, abort. - if fn != nil { - go p.Send(fn(err)) - } - return - } - - c.SetStdin(p.input) - c.SetStdout(p.output) - c.SetStderr(os.Stderr) - - // Execute system command. - if err := c.Run(); err != nil { - _ = p.RestoreTerminal() // also try to restore the terminal. - if fn != nil { - go p.Send(fn(err)) - } - return - } - - // Have the program re-capture input. - err := p.RestoreTerminal() - if fn != nil { - go p.Send(fn(err)) - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/focus.go b/vendor/github.com/charmbracelet/bubbletea/focus.go deleted file mode 100644 index 4d34bea6..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/focus.go +++ /dev/null @@ -1,9 +0,0 @@ -package tea - -// FocusMsg represents a terminal focus message. -// This occurs when the terminal gains focus. -type FocusMsg struct{} - -// BlurMsg represents a terminal blur message. -// This occurs when the terminal loses focus. -type BlurMsg struct{} diff --git a/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go b/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go deleted file mode 100644 index 3426a177..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build !windows -// +build !windows - -package tea - -import ( - "io" - - "github.com/muesli/cancelreader" -) - -func newInputReader(r io.Reader, _ bool) (cancelreader.CancelReader, error) { - return cancelreader.NewReader(r) -} diff --git a/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go b/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go deleted file mode 100644 index 9af89428..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build windows -// +build windows - -package tea - -import ( - "fmt" - "io" - "os" - "sync" - - "github.com/charmbracelet/x/term" - "github.com/erikgeiser/coninput" - "github.com/muesli/cancelreader" - "golang.org/x/sys/windows" -) - -type conInputReader struct { - cancelMixin - - conin windows.Handle - - originalMode uint32 -} - -var _ cancelreader.CancelReader = &conInputReader{} - -func newInputReader(r io.Reader, enableMouse bool) (cancelreader.CancelReader, error) { - fallback := func(io.Reader) (cancelreader.CancelReader, error) { - return cancelreader.NewReader(r) - } - if f, ok := r.(term.File); !ok || f.Fd() != os.Stdin.Fd() { - return fallback(r) - } - - conin, err := coninput.NewStdinHandle() - if err != nil { - return fallback(r) - } - - modes := []uint32{ - windows.ENABLE_WINDOW_INPUT, - windows.ENABLE_EXTENDED_FLAGS, - } - - // Since we have options to enable mouse events, [WithMouseCellMotion], - // [WithMouseAllMotion], and [EnableMouseCellMotion], - // [EnableMouseAllMotion], and [DisableMouse], we need to check if the user - // has enabled mouse events and add the appropriate mode accordingly. - // Otherwise, mouse events will be enabled all the time. - if enableMouse { - modes = append(modes, windows.ENABLE_MOUSE_INPUT) - } - - originalMode, err := prepareConsole(conin, modes...) - if err != nil { - return nil, fmt.Errorf("failed to prepare console input: %w", err) - } - - return &conInputReader{ - conin: conin, - originalMode: originalMode, - }, nil -} - -// Cancel implements cancelreader.CancelReader. -func (r *conInputReader) Cancel() bool { - r.setCanceled() - - return windows.CancelIoEx(r.conin, nil) == nil || windows.CancelIo(r.conin) == nil -} - -// Close implements cancelreader.CancelReader. -func (r *conInputReader) Close() error { - if r.originalMode != 0 { - err := windows.SetConsoleMode(r.conin, r.originalMode) - if err != nil { - return fmt.Errorf("reset console mode: %w", err) - } - } - - return nil -} - -// Read implements cancelreader.CancelReader. -func (r *conInputReader) Read(_ []byte) (n int, err error) { - if r.isCanceled() { - err = cancelreader.ErrCanceled - } - return -} - -func prepareConsole(input windows.Handle, modes ...uint32) (originalMode uint32, err error) { - err = windows.GetConsoleMode(input, &originalMode) - if err != nil { - return 0, fmt.Errorf("get console mode: %w", err) - } - - newMode := coninput.AddInputModes(0, modes...) - - err = windows.SetConsoleMode(input, newMode) - if err != nil { - return 0, fmt.Errorf("set console mode: %w", err) - } - - return originalMode, nil -} - -// cancelMixin represents a goroutine-safe cancelation status. -type cancelMixin struct { - unsafeCanceled bool - lock sync.Mutex -} - -func (c *cancelMixin) setCanceled() { - c.lock.Lock() - defer c.lock.Unlock() - - c.unsafeCanceled = true -} - -func (c *cancelMixin) isCanceled() bool { - c.lock.Lock() - defer c.lock.Unlock() - - return c.unsafeCanceled -} diff --git a/vendor/github.com/charmbracelet/bubbletea/key.go b/vendor/github.com/charmbracelet/bubbletea/key.go deleted file mode 100644 index ab4792ac..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/key.go +++ /dev/null @@ -1,715 +0,0 @@ -package tea - -import ( - "context" - "fmt" - "io" - "regexp" - "strings" - "unicode/utf8" -) - -// KeyMsg contains information about a keypress. KeyMsgs are always sent to -// the program's update function. There are a couple general patterns you could -// use to check for keypresses: -// -// // Switch on the string representation of the key (shorter) -// switch msg := msg.(type) { -// case KeyMsg: -// switch msg.String() { -// case "enter": -// fmt.Println("you pressed enter!") -// case "a": -// fmt.Println("you pressed a!") -// } -// } -// -// // Switch on the key type (more foolproof) -// switch msg := msg.(type) { -// case KeyMsg: -// switch msg.Type { -// case KeyEnter: -// fmt.Println("you pressed enter!") -// case KeyRunes: -// switch string(msg.Runes) { -// case "a": -// fmt.Println("you pressed a!") -// } -// } -// } -// -// Note that Key.Runes will always contain at least one character, so you can -// always safely call Key.Runes[0]. In most cases Key.Runes will only contain -// one character, though certain input method editors (most notably Chinese -// IMEs) can input multiple runes at once. -type KeyMsg Key - -// String returns a string representation for a key message. It's safe (and -// encouraged) for use in key comparison. -func (k KeyMsg) String() (str string) { - return Key(k).String() -} - -// Key contains information about a keypress. -type Key struct { - Type KeyType - Runes []rune - Alt bool - Paste bool -} - -// String returns a friendly string representation for a key. It's safe (and -// encouraged) for use in key comparison. -// -// k := Key{Type: KeyEnter} -// fmt.Println(k) -// // Output: enter -func (k Key) String() (str string) { - var buf strings.Builder - if k.Alt { - buf.WriteString("alt+") - } - if k.Type == KeyRunes { - if k.Paste { - // Note: bubbles/keys bindings currently do string compares to - // recognize shortcuts. Since pasted text should never activate - // shortcuts, we need to ensure that the binding code doesn't - // match Key events that result from pastes. We achieve this - // here by enclosing pastes in '[...]' so that the string - // comparison in Matches() fails in that case. - buf.WriteByte('[') - } - buf.WriteString(string(k.Runes)) - if k.Paste { - buf.WriteByte(']') - } - return buf.String() - } else if s, ok := keyNames[k.Type]; ok { - buf.WriteString(s) - return buf.String() - } - return "" -} - -// KeyType indicates the key pressed, such as KeyEnter or KeyBreak or KeyCtrlC. -// All other keys will be type KeyRunes. To get the rune value, check the Rune -// method on a Key struct, or use the Key.String() method: -// -// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} -// if k.Type == KeyRunes { -// -// fmt.Println(k.Runes) -// // Output: a -// -// fmt.Println(k.String()) -// // Output: alt+a -// -// } -type KeyType int - -func (k KeyType) String() (str string) { - if s, ok := keyNames[k]; ok { - return s - } - return "" -} - -// Control keys. We could do this with an iota, but the values are very -// specific, so we set the values explicitly to avoid any confusion. -// -// See also: -// https://en.wikipedia.org/wiki/C0_and_C1_control_codes -const ( - keyNUL KeyType = 0 // null, \0 - keySOH KeyType = 1 // start of heading - keySTX KeyType = 2 // start of text - keyETX KeyType = 3 // break, ctrl+c - keyEOT KeyType = 4 // end of transmission - keyENQ KeyType = 5 // enquiry - keyACK KeyType = 6 // acknowledge - keyBEL KeyType = 7 // bell, \a - keyBS KeyType = 8 // backspace - keyHT KeyType = 9 // horizontal tabulation, \t - keyLF KeyType = 10 // line feed, \n - keyVT KeyType = 11 // vertical tabulation \v - keyFF KeyType = 12 // form feed \f - keyCR KeyType = 13 // carriage return, \r - keySO KeyType = 14 // shift out - keySI KeyType = 15 // shift in - keyDLE KeyType = 16 // data link escape - keyDC1 KeyType = 17 // device control one - keyDC2 KeyType = 18 // device control two - keyDC3 KeyType = 19 // device control three - keyDC4 KeyType = 20 // device control four - keyNAK KeyType = 21 // negative acknowledge - keySYN KeyType = 22 // synchronous idle - keyETB KeyType = 23 // end of transmission block - keyCAN KeyType = 24 // cancel - keyEM KeyType = 25 // end of medium - keySUB KeyType = 26 // substitution - keyESC KeyType = 27 // escape, \e - keyFS KeyType = 28 // file separator - keyGS KeyType = 29 // group separator - keyRS KeyType = 30 // record separator - keyUS KeyType = 31 // unit separator - keyDEL KeyType = 127 // delete. on most systems this is mapped to backspace, I hear -) - -// Control key aliases. -const ( - KeyNull KeyType = keyNUL - KeyBreak KeyType = keyETX - KeyEnter KeyType = keyCR - KeyBackspace KeyType = keyDEL - KeyTab KeyType = keyHT - KeyEsc KeyType = keyESC - KeyEscape KeyType = keyESC - - KeyCtrlAt KeyType = keyNUL // ctrl+@ - KeyCtrlA KeyType = keySOH - KeyCtrlB KeyType = keySTX - KeyCtrlC KeyType = keyETX - KeyCtrlD KeyType = keyEOT - KeyCtrlE KeyType = keyENQ - KeyCtrlF KeyType = keyACK - KeyCtrlG KeyType = keyBEL - KeyCtrlH KeyType = keyBS - KeyCtrlI KeyType = keyHT - KeyCtrlJ KeyType = keyLF - KeyCtrlK KeyType = keyVT - KeyCtrlL KeyType = keyFF - KeyCtrlM KeyType = keyCR - KeyCtrlN KeyType = keySO - KeyCtrlO KeyType = keySI - KeyCtrlP KeyType = keyDLE - KeyCtrlQ KeyType = keyDC1 - KeyCtrlR KeyType = keyDC2 - KeyCtrlS KeyType = keyDC3 - KeyCtrlT KeyType = keyDC4 - KeyCtrlU KeyType = keyNAK - KeyCtrlV KeyType = keySYN - KeyCtrlW KeyType = keyETB - KeyCtrlX KeyType = keyCAN - KeyCtrlY KeyType = keyEM - KeyCtrlZ KeyType = keySUB - KeyCtrlOpenBracket KeyType = keyESC // ctrl+[ - KeyCtrlBackslash KeyType = keyFS // ctrl+\ - KeyCtrlCloseBracket KeyType = keyGS // ctrl+] - KeyCtrlCaret KeyType = keyRS // ctrl+^ - KeyCtrlUnderscore KeyType = keyUS // ctrl+_ - KeyCtrlQuestionMark KeyType = keyDEL // ctrl+? -) - -// Other keys. -const ( - KeyRunes KeyType = -(iota + 1) - KeyUp - KeyDown - KeyRight - KeyLeft - KeyShiftTab - KeyHome - KeyEnd - KeyPgUp - KeyPgDown - KeyCtrlPgUp - KeyCtrlPgDown - KeyDelete - KeyInsert - KeySpace - KeyCtrlUp - KeyCtrlDown - KeyCtrlRight - KeyCtrlLeft - KeyCtrlHome - KeyCtrlEnd - KeyShiftUp - KeyShiftDown - KeyShiftRight - KeyShiftLeft - KeyShiftHome - KeyShiftEnd - KeyCtrlShiftUp - KeyCtrlShiftDown - KeyCtrlShiftLeft - KeyCtrlShiftRight - KeyCtrlShiftHome - KeyCtrlShiftEnd - KeyF1 - KeyF2 - KeyF3 - KeyF4 - KeyF5 - KeyF6 - KeyF7 - KeyF8 - KeyF9 - KeyF10 - KeyF11 - KeyF12 - KeyF13 - KeyF14 - KeyF15 - KeyF16 - KeyF17 - KeyF18 - KeyF19 - KeyF20 -) - -// Mappings for control keys and other special keys to friendly consts. -var keyNames = map[KeyType]string{ - // Control keys. - keyNUL: "ctrl+@", // also ctrl+` (that's ctrl+backtick) - keySOH: "ctrl+a", - keySTX: "ctrl+b", - keyETX: "ctrl+c", - keyEOT: "ctrl+d", - keyENQ: "ctrl+e", - keyACK: "ctrl+f", - keyBEL: "ctrl+g", - keyBS: "ctrl+h", - keyHT: "tab", // also ctrl+i - keyLF: "ctrl+j", - keyVT: "ctrl+k", - keyFF: "ctrl+l", - keyCR: "enter", - keySO: "ctrl+n", - keySI: "ctrl+o", - keyDLE: "ctrl+p", - keyDC1: "ctrl+q", - keyDC2: "ctrl+r", - keyDC3: "ctrl+s", - keyDC4: "ctrl+t", - keyNAK: "ctrl+u", - keySYN: "ctrl+v", - keyETB: "ctrl+w", - keyCAN: "ctrl+x", - keyEM: "ctrl+y", - keySUB: "ctrl+z", - keyESC: "esc", - keyFS: "ctrl+\\", - keyGS: "ctrl+]", - keyRS: "ctrl+^", - keyUS: "ctrl+_", - keyDEL: "backspace", - - // Other keys. - KeyRunes: "runes", - KeyUp: "up", - KeyDown: "down", - KeyRight: "right", - KeySpace: " ", // for backwards compatibility - KeyLeft: "left", - KeyShiftTab: "shift+tab", - KeyHome: "home", - KeyEnd: "end", - KeyCtrlHome: "ctrl+home", - KeyCtrlEnd: "ctrl+end", - KeyShiftHome: "shift+home", - KeyShiftEnd: "shift+end", - KeyCtrlShiftHome: "ctrl+shift+home", - KeyCtrlShiftEnd: "ctrl+shift+end", - KeyPgUp: "pgup", - KeyPgDown: "pgdown", - KeyCtrlPgUp: "ctrl+pgup", - KeyCtrlPgDown: "ctrl+pgdown", - KeyDelete: "delete", - KeyInsert: "insert", - KeyCtrlUp: "ctrl+up", - KeyCtrlDown: "ctrl+down", - KeyCtrlRight: "ctrl+right", - KeyCtrlLeft: "ctrl+left", - KeyShiftUp: "shift+up", - KeyShiftDown: "shift+down", - KeyShiftRight: "shift+right", - KeyShiftLeft: "shift+left", - KeyCtrlShiftUp: "ctrl+shift+up", - KeyCtrlShiftDown: "ctrl+shift+down", - KeyCtrlShiftLeft: "ctrl+shift+left", - KeyCtrlShiftRight: "ctrl+shift+right", - KeyF1: "f1", - KeyF2: "f2", - KeyF3: "f3", - KeyF4: "f4", - KeyF5: "f5", - KeyF6: "f6", - KeyF7: "f7", - KeyF8: "f8", - KeyF9: "f9", - KeyF10: "f10", - KeyF11: "f11", - KeyF12: "f12", - KeyF13: "f13", - KeyF14: "f14", - KeyF15: "f15", - KeyF16: "f16", - KeyF17: "f17", - KeyF18: "f18", - KeyF19: "f19", - KeyF20: "f20", -} - -// Sequence mappings. -var sequences = map[string]Key{ - // Arrow keys - "\x1b[A": {Type: KeyUp}, - "\x1b[B": {Type: KeyDown}, - "\x1b[C": {Type: KeyRight}, - "\x1b[D": {Type: KeyLeft}, - "\x1b[1;2A": {Type: KeyShiftUp}, - "\x1b[1;2B": {Type: KeyShiftDown}, - "\x1b[1;2C": {Type: KeyShiftRight}, - "\x1b[1;2D": {Type: KeyShiftLeft}, - "\x1b[OA": {Type: KeyShiftUp}, // DECCKM - "\x1b[OB": {Type: KeyShiftDown}, // DECCKM - "\x1b[OC": {Type: KeyShiftRight}, // DECCKM - "\x1b[OD": {Type: KeyShiftLeft}, // DECCKM - "\x1b[a": {Type: KeyShiftUp}, // urxvt - "\x1b[b": {Type: KeyShiftDown}, // urxvt - "\x1b[c": {Type: KeyShiftRight}, // urxvt - "\x1b[d": {Type: KeyShiftLeft}, // urxvt - "\x1b[1;3A": {Type: KeyUp, Alt: true}, - "\x1b[1;3B": {Type: KeyDown, Alt: true}, - "\x1b[1;3C": {Type: KeyRight, Alt: true}, - "\x1b[1;3D": {Type: KeyLeft, Alt: true}, - - "\x1b[1;4A": {Type: KeyShiftUp, Alt: true}, - "\x1b[1;4B": {Type: KeyShiftDown, Alt: true}, - "\x1b[1;4C": {Type: KeyShiftRight, Alt: true}, - "\x1b[1;4D": {Type: KeyShiftLeft, Alt: true}, - - "\x1b[1;5A": {Type: KeyCtrlUp}, - "\x1b[1;5B": {Type: KeyCtrlDown}, - "\x1b[1;5C": {Type: KeyCtrlRight}, - "\x1b[1;5D": {Type: KeyCtrlLeft}, - "\x1b[Oa": {Type: KeyCtrlUp, Alt: true}, // urxvt - "\x1b[Ob": {Type: KeyCtrlDown, Alt: true}, // urxvt - "\x1b[Oc": {Type: KeyCtrlRight, Alt: true}, // urxvt - "\x1b[Od": {Type: KeyCtrlLeft, Alt: true}, // urxvt - "\x1b[1;6A": {Type: KeyCtrlShiftUp}, - "\x1b[1;6B": {Type: KeyCtrlShiftDown}, - "\x1b[1;6C": {Type: KeyCtrlShiftRight}, - "\x1b[1;6D": {Type: KeyCtrlShiftLeft}, - "\x1b[1;7A": {Type: KeyCtrlUp, Alt: true}, - "\x1b[1;7B": {Type: KeyCtrlDown, Alt: true}, - "\x1b[1;7C": {Type: KeyCtrlRight, Alt: true}, - "\x1b[1;7D": {Type: KeyCtrlLeft, Alt: true}, - "\x1b[1;8A": {Type: KeyCtrlShiftUp, Alt: true}, - "\x1b[1;8B": {Type: KeyCtrlShiftDown, Alt: true}, - "\x1b[1;8C": {Type: KeyCtrlShiftRight, Alt: true}, - "\x1b[1;8D": {Type: KeyCtrlShiftLeft, Alt: true}, - - // Miscellaneous keys - "\x1b[Z": {Type: KeyShiftTab}, - - "\x1b[2~": {Type: KeyInsert}, - "\x1b[3;2~": {Type: KeyInsert, Alt: true}, - - "\x1b[3~": {Type: KeyDelete}, - "\x1b[3;3~": {Type: KeyDelete, Alt: true}, - - "\x1b[5~": {Type: KeyPgUp}, - "\x1b[5;3~": {Type: KeyPgUp, Alt: true}, - "\x1b[5;5~": {Type: KeyCtrlPgUp}, - "\x1b[5^": {Type: KeyCtrlPgUp}, // urxvt - "\x1b[5;7~": {Type: KeyCtrlPgUp, Alt: true}, - - "\x1b[6~": {Type: KeyPgDown}, - "\x1b[6;3~": {Type: KeyPgDown, Alt: true}, - "\x1b[6;5~": {Type: KeyCtrlPgDown}, - "\x1b[6^": {Type: KeyCtrlPgDown}, // urxvt - "\x1b[6;7~": {Type: KeyCtrlPgDown, Alt: true}, - - "\x1b[1~": {Type: KeyHome}, - "\x1b[H": {Type: KeyHome}, // xterm, lxterm - "\x1b[1;3H": {Type: KeyHome, Alt: true}, // xterm, lxterm - "\x1b[1;5H": {Type: KeyCtrlHome}, // xterm, lxterm - "\x1b[1;7H": {Type: KeyCtrlHome, Alt: true}, // xterm, lxterm - "\x1b[1;2H": {Type: KeyShiftHome}, // xterm, lxterm - "\x1b[1;4H": {Type: KeyShiftHome, Alt: true}, // xterm, lxterm - "\x1b[1;6H": {Type: KeyCtrlShiftHome}, // xterm, lxterm - "\x1b[1;8H": {Type: KeyCtrlShiftHome, Alt: true}, // xterm, lxterm - - "\x1b[4~": {Type: KeyEnd}, - "\x1b[F": {Type: KeyEnd}, // xterm, lxterm - "\x1b[1;3F": {Type: KeyEnd, Alt: true}, // xterm, lxterm - "\x1b[1;5F": {Type: KeyCtrlEnd}, // xterm, lxterm - "\x1b[1;7F": {Type: KeyCtrlEnd, Alt: true}, // xterm, lxterm - "\x1b[1;2F": {Type: KeyShiftEnd}, // xterm, lxterm - "\x1b[1;4F": {Type: KeyShiftEnd, Alt: true}, // xterm, lxterm - "\x1b[1;6F": {Type: KeyCtrlShiftEnd}, // xterm, lxterm - "\x1b[1;8F": {Type: KeyCtrlShiftEnd, Alt: true}, // xterm, lxterm - - "\x1b[7~": {Type: KeyHome}, // urxvt - "\x1b[7^": {Type: KeyCtrlHome}, // urxvt - "\x1b[7$": {Type: KeyShiftHome}, // urxvt - "\x1b[7@": {Type: KeyCtrlShiftHome}, // urxvt - - "\x1b[8~": {Type: KeyEnd}, // urxvt - "\x1b[8^": {Type: KeyCtrlEnd}, // urxvt - "\x1b[8$": {Type: KeyShiftEnd}, // urxvt - "\x1b[8@": {Type: KeyCtrlShiftEnd}, // urxvt - - // Function keys, Linux console - "\x1b[[A": {Type: KeyF1}, // linux console - "\x1b[[B": {Type: KeyF2}, // linux console - "\x1b[[C": {Type: KeyF3}, // linux console - "\x1b[[D": {Type: KeyF4}, // linux console - "\x1b[[E": {Type: KeyF5}, // linux console - - // Function keys, X11 - "\x1bOP": {Type: KeyF1}, // vt100, xterm - "\x1bOQ": {Type: KeyF2}, // vt100, xterm - "\x1bOR": {Type: KeyF3}, // vt100, xterm - "\x1bOS": {Type: KeyF4}, // vt100, xterm - - "\x1b[1;3P": {Type: KeyF1, Alt: true}, // vt100, xterm - "\x1b[1;3Q": {Type: KeyF2, Alt: true}, // vt100, xterm - "\x1b[1;3R": {Type: KeyF3, Alt: true}, // vt100, xterm - "\x1b[1;3S": {Type: KeyF4, Alt: true}, // vt100, xterm - - "\x1b[11~": {Type: KeyF1}, // urxvt - "\x1b[12~": {Type: KeyF2}, // urxvt - "\x1b[13~": {Type: KeyF3}, // urxvt - "\x1b[14~": {Type: KeyF4}, // urxvt - - "\x1b[15~": {Type: KeyF5}, // vt100, xterm, also urxvt - - "\x1b[15;3~": {Type: KeyF5, Alt: true}, // vt100, xterm, also urxvt - - "\x1b[17~": {Type: KeyF6}, // vt100, xterm, also urxvt - "\x1b[18~": {Type: KeyF7}, // vt100, xterm, also urxvt - "\x1b[19~": {Type: KeyF8}, // vt100, xterm, also urxvt - "\x1b[20~": {Type: KeyF9}, // vt100, xterm, also urxvt - "\x1b[21~": {Type: KeyF10}, // vt100, xterm, also urxvt - - "\x1b[17;3~": {Type: KeyF6, Alt: true}, // vt100, xterm - "\x1b[18;3~": {Type: KeyF7, Alt: true}, // vt100, xterm - "\x1b[19;3~": {Type: KeyF8, Alt: true}, // vt100, xterm - "\x1b[20;3~": {Type: KeyF9, Alt: true}, // vt100, xterm - "\x1b[21;3~": {Type: KeyF10, Alt: true}, // vt100, xterm - - "\x1b[23~": {Type: KeyF11}, // vt100, xterm, also urxvt - "\x1b[24~": {Type: KeyF12}, // vt100, xterm, also urxvt - - "\x1b[23;3~": {Type: KeyF11, Alt: true}, // vt100, xterm - "\x1b[24;3~": {Type: KeyF12, Alt: true}, // vt100, xterm - - "\x1b[1;2P": {Type: KeyF13}, - "\x1b[1;2Q": {Type: KeyF14}, - - "\x1b[25~": {Type: KeyF13}, // vt100, xterm, also urxvt - "\x1b[26~": {Type: KeyF14}, // vt100, xterm, also urxvt - - "\x1b[25;3~": {Type: KeyF13, Alt: true}, // vt100, xterm - "\x1b[26;3~": {Type: KeyF14, Alt: true}, // vt100, xterm - - "\x1b[1;2R": {Type: KeyF15}, - "\x1b[1;2S": {Type: KeyF16}, - - "\x1b[28~": {Type: KeyF15}, // vt100, xterm, also urxvt - "\x1b[29~": {Type: KeyF16}, // vt100, xterm, also urxvt - - "\x1b[28;3~": {Type: KeyF15, Alt: true}, // vt100, xterm - "\x1b[29;3~": {Type: KeyF16, Alt: true}, // vt100, xterm - - "\x1b[15;2~": {Type: KeyF17}, - "\x1b[17;2~": {Type: KeyF18}, - "\x1b[18;2~": {Type: KeyF19}, - "\x1b[19;2~": {Type: KeyF20}, - - "\x1b[31~": {Type: KeyF17}, - "\x1b[32~": {Type: KeyF18}, - "\x1b[33~": {Type: KeyF19}, - "\x1b[34~": {Type: KeyF20}, - - // Powershell sequences. - "\x1bOA": {Type: KeyUp, Alt: false}, - "\x1bOB": {Type: KeyDown, Alt: false}, - "\x1bOC": {Type: KeyRight, Alt: false}, - "\x1bOD": {Type: KeyLeft, Alt: false}, -} - -// unknownInputByteMsg is reported by the input reader when an invalid -// utf-8 byte is detected on the input. Currently, it is not handled -// further by bubbletea. However, having this event makes it possible -// to troubleshoot invalid inputs. -type unknownInputByteMsg byte - -func (u unknownInputByteMsg) String() string { - return fmt.Sprintf("?%#02x?", int(u)) -} - -// unknownCSISequenceMsg is reported by the input reader when an -// unrecognized CSI sequence is detected on the input. Currently, it -// is not handled further by bubbletea. However, having this event -// makes it possible to troubleshoot invalid inputs. -type unknownCSISequenceMsg []byte - -func (u unknownCSISequenceMsg) String() string { - return fmt.Sprintf("?CSI%+v?", []byte(u)[2:]) -} - -var spaceRunes = []rune{' '} - -// readAnsiInputs reads keypress and mouse inputs from a TTY and produces messages -// containing information about the key or mouse events accordingly. -func readAnsiInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { - var buf [256]byte - - var leftOverFromPrevIteration []byte -loop: - for { - // Read and block. - numBytes, err := input.Read(buf[:]) - if err != nil { - return fmt.Errorf("error reading input: %w", err) - } - b := buf[:numBytes] - if leftOverFromPrevIteration != nil { - b = append(leftOverFromPrevIteration, b...) - } - - // If we had a short read (numBytes < len(buf)), we're sure that - // the end of this read is an event boundary, so there is no doubt - // if we are encountering the end of the buffer while parsing a message. - // However, if we've succeeded in filling up the buffer, there may - // be more data in the OS buffer ready to be read in, to complete - // the last message in the input. In that case, we will retry with - // the left over data in the next iteration. - canHaveMoreData := numBytes == len(buf) - - var i, w int - for i, w = 0, 0; i < len(b); i += w { - var msg Msg - w, msg = detectOneMsg(b[i:], canHaveMoreData) - if w == 0 { - // Expecting more bytes beyond the current buffer. Try waiting - // for more input. - leftOverFromPrevIteration = make([]byte, 0, len(b[i:])+len(buf)) - leftOverFromPrevIteration = append(leftOverFromPrevIteration, b[i:]...) - continue loop - } - - select { - case msgs <- msg: - case <-ctx.Done(): - err := ctx.Err() - if err != nil { - err = fmt.Errorf("found context error while reading input: %w", err) - } - return err - } - } - leftOverFromPrevIteration = nil - } -} - -var ( - unknownCSIRe = regexp.MustCompile(`^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]`) - mouseSGRRegex = regexp.MustCompile(`(\d+);(\d+);(\d+)([Mm])`) -) - -func detectOneMsg(b []byte, canHaveMoreData bool) (w int, msg Msg) { - // Detect mouse events. - // X10 mouse events have a length of 6 bytes - const mouseEventX10Len = 6 - if len(b) >= mouseEventX10Len && b[0] == '\x1b' && b[1] == '[' { - switch b[2] { - case 'M': - return mouseEventX10Len, MouseMsg(parseX10MouseEvent(b)) - case '<': - if matchIndices := mouseSGRRegex.FindSubmatchIndex(b[3:]); matchIndices != nil { - // SGR mouse events length is the length of the match plus the length of the escape sequence - mouseEventSGRLen := matchIndices[1] + 3 //nolint:gomnd - return mouseEventSGRLen, MouseMsg(parseSGRMouseEvent(b)) - } - } - } - - // Detect focus events. - var foundRF bool - foundRF, w, msg = detectReportFocus(b) - if foundRF { - return w, msg - } - - // Detect bracketed paste. - var foundbp bool - foundbp, w, msg = detectBracketedPaste(b) - if foundbp { - return w, msg - } - - // Detect escape sequence and control characters other than NUL, - // possibly with an escape character in front to mark the Alt - // modifier. - var foundSeq bool - foundSeq, w, msg = detectSequence(b) - if foundSeq { - return w, msg - } - - // No non-NUL control character or escape sequence. - // If we are seeing at least an escape character, remember it for later below. - alt := false - i := 0 - if b[0] == '\x1b' { - alt = true - i++ - } - - // Are we seeing a standalone NUL? This is not handled by detectSequence(). - if i < len(b) && b[i] == 0 { - return i + 1, KeyMsg{Type: keyNUL, Alt: alt} - } - - // Find the longest sequence of runes that are not control - // characters from this point. - var runes []rune - for rw := 0; i < len(b); i += rw { - var r rune - r, rw = utf8.DecodeRune(b[i:]) - if r == utf8.RuneError || r <= rune(keyUS) || r == rune(keyDEL) || r == ' ' { - // Rune errors are handled below; control characters and spaces will - // be handled by detectSequence in the next call to detectOneMsg. - break - } - runes = append(runes, r) - if alt { - // We only support a single rune after an escape alt modifier. - i += rw - break - } - } - if i >= len(b) && canHaveMoreData { - // We have encountered the end of the input buffer. Alas, we can't - // be sure whether the data in the remainder of the buffer is - // complete (maybe there was a short read). Instead of sending anything - // dumb to the message channel, do a short read. The outer loop will - // handle this case by extending the buffer as necessary. - return 0, nil - } - - // If we found at least one rune, we report the bunch of them as - // a single KeyRunes or KeySpace event. - if len(runes) > 0 { - k := Key{Type: KeyRunes, Runes: runes, Alt: alt} - if len(runes) == 1 && runes[0] == ' ' { - k.Type = KeySpace - } - return i, KeyMsg(k) - } - - // We didn't find an escape sequence, nor a valid rune. Was this a - // lone escape character at the end of the input? - if alt && len(b) == 1 { - return 1, KeyMsg(Key{Type: KeyEscape}) - } - - // The character at the current position is neither an escape - // sequence, a valid rune start or a sole escape character. Report - // it as an invalid byte. - return 1, unknownInputByteMsg(b[0]) -} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_other.go b/vendor/github.com/charmbracelet/bubbletea/key_other.go deleted file mode 100644 index b8c46082..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/key_other.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !windows -// +build !windows - -package tea - -import ( - "context" - "io" -) - -func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { - return readAnsiInputs(ctx, msgs, input) -} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_sequences.go b/vendor/github.com/charmbracelet/bubbletea/key_sequences.go deleted file mode 100644 index 15483ef5..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/key_sequences.go +++ /dev/null @@ -1,131 +0,0 @@ -package tea - -import ( - "bytes" - "sort" - "unicode/utf8" -) - -// extSequences is used by the map-based algorithm below. It contains -// the sequences plus their alternatives with an escape character -// prefixed, plus the control chars, plus the space. -// It does not contain the NUL character, which is handled specially -// by detectOneMsg. -var extSequences = func() map[string]Key { - s := map[string]Key{} - for seq, key := range sequences { - key := key - s[seq] = key - if !key.Alt { - key.Alt = true - s["\x1b"+seq] = key - } - } - for i := keyNUL + 1; i <= keyDEL; i++ { - if i == keyESC { - continue - } - s[string([]byte{byte(i)})] = Key{Type: i} - s[string([]byte{'\x1b', byte(i)})] = Key{Type: i, Alt: true} - if i == keyUS { - i = keyDEL - 1 - } - } - s[" "] = Key{Type: KeySpace, Runes: spaceRunes} - s["\x1b "] = Key{Type: KeySpace, Alt: true, Runes: spaceRunes} - s["\x1b\x1b"] = Key{Type: KeyEscape, Alt: true} - return s -}() - -// seqLengths is the sizes of valid sequences, starting with the -// largest size. -var seqLengths = func() []int { - sizes := map[int]struct{}{} - for seq := range extSequences { - sizes[len(seq)] = struct{}{} - } - lsizes := make([]int, 0, len(sizes)) - for sz := range sizes { - lsizes = append(lsizes, sz) - } - sort.Slice(lsizes, func(i, j int) bool { return lsizes[i] > lsizes[j] }) - return lsizes -}() - -// detectSequence uses a longest prefix match over the input -// sequence and a hash map. -func detectSequence(input []byte) (hasSeq bool, width int, msg Msg) { - seqs := extSequences - for _, sz := range seqLengths { - if sz > len(input) { - continue - } - prefix := input[:sz] - key, ok := seqs[string(prefix)] - if ok { - return true, sz, KeyMsg(key) - } - } - // Is this an unknown CSI sequence? - if loc := unknownCSIRe.FindIndex(input); loc != nil { - return true, loc[1], unknownCSISequenceMsg(input[:loc[1]]) - } - - return false, 0, nil -} - -// detectBracketedPaste detects an input pasted while bracketed -// paste mode was enabled. -// -// Note: this function is a no-op if bracketed paste was not enabled -// on the terminal, since in that case we'd never see this -// particular escape sequence. -func detectBracketedPaste(input []byte) (hasBp bool, width int, msg Msg) { - // Detect the start sequence. - const bpStart = "\x1b[200~" - if len(input) < len(bpStart) || string(input[:len(bpStart)]) != bpStart { - return false, 0, nil - } - - // Skip over the start sequence. - input = input[len(bpStart):] - - // If we saw the start sequence, then we must have an end sequence - // as well. Find it. - const bpEnd = "\x1b[201~" - idx := bytes.Index(input, []byte(bpEnd)) - inputLen := len(bpStart) + idx + len(bpEnd) - if idx == -1 { - // We have encountered the end of the input buffer without seeing - // the marker for the end of the bracketed paste. - // Tell the outer loop we have done a short read and we want more. - return true, 0, nil - } - - // The paste is everything in-between. - paste := input[:idx] - - // All there is in-between is runes, not to be interpreted further. - k := Key{Type: KeyRunes, Paste: true} - for len(paste) > 0 { - r, w := utf8.DecodeRune(paste) - if r != utf8.RuneError { - k.Runes = append(k.Runes, r) - } - paste = paste[w:] - } - - return true, inputLen, KeyMsg(k) -} - -// detectReportFocus detects a focus report sequence. -// nolint: gomnd -func detectReportFocus(input []byte) (hasRF bool, width int, msg Msg) { - switch { - case bytes.Equal(input, []byte("\x1b[I")): - return true, 3, FocusMsg{} - case bytes.Equal(input, []byte("\x1b[O")): - return true, 3, BlurMsg{} - } - return false, 0, nil -} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_windows.go b/vendor/github.com/charmbracelet/bubbletea/key_windows.go deleted file mode 100644 index d59ff1c4..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/key_windows.go +++ /dev/null @@ -1,360 +0,0 @@ -//go:build windows -// +build windows - -package tea - -import ( - "context" - "fmt" - "io" - - "github.com/erikgeiser/coninput" - localereader "github.com/mattn/go-localereader" - "github.com/muesli/cancelreader" -) - -func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { - if coninReader, ok := input.(*conInputReader); ok { - return readConInputs(ctx, msgs, coninReader) - } - - return readAnsiInputs(ctx, msgs, localereader.NewReader(input)) -} - -func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInputReader) error { - var ps coninput.ButtonState // keep track of previous mouse state - var ws coninput.WindowBufferSizeEventRecord // keep track of the last window size event - for { - events, err := coninput.ReadNConsoleInputs(con.conin, 16) - if err != nil { - if con.isCanceled() { - return cancelreader.ErrCanceled - } - return fmt.Errorf("read coninput events: %w", err) - } - - for _, event := range events { - var msgs []Msg - switch e := event.Unwrap().(type) { - case coninput.KeyEventRecord: - if !e.KeyDown || e.VirtualKeyCode == coninput.VK_SHIFT { - continue - } - - for i := 0; i < int(e.RepeatCount); i++ { - eventKeyType := keyType(e) - var runes []rune - - // Add the character only if the key type is an actual character and not a control sequence. - // This mimics the behavior in readAnsiInputs where the character is also removed. - // We don't need to handle KeySpace here. See the comment in keyType(). - if eventKeyType == KeyRunes { - runes = []rune{e.Char} - } - - msgs = append(msgs, KeyMsg{ - Type: eventKeyType, - Runes: runes, - Alt: e.ControlKeyState.Contains(coninput.LEFT_ALT_PRESSED | coninput.RIGHT_ALT_PRESSED), - }) - } - case coninput.WindowBufferSizeEventRecord: - if e != ws { - ws = e - msgs = append(msgs, WindowSizeMsg{ - Width: int(e.Size.X), - Height: int(e.Size.Y), - }) - } - case coninput.MouseEventRecord: - event := mouseEvent(ps, e) - if event.Type != MouseUnknown { - msgs = append(msgs, event) - } - ps = e.ButtonState - case coninput.FocusEventRecord, coninput.MenuEventRecord: - // ignore - default: // unknown event - continue - } - - // Send all messages to the channel - for _, msg := range msgs { - select { - case msgsch <- msg: - case <-ctx.Done(): - err := ctx.Err() - if err != nil { - return fmt.Errorf("coninput context error: %w", err) - } - return err - } - } - } - } -} - -func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action MouseAction) { - btn := p ^ s - action = MouseActionPress - if btn&s == 0 { - action = MouseActionRelease - } - - if btn == 0 { - switch { - case s&coninput.FROM_LEFT_1ST_BUTTON_PRESSED > 0: - button = MouseButtonLeft - case s&coninput.FROM_LEFT_2ND_BUTTON_PRESSED > 0: - button = MouseButtonMiddle - case s&coninput.RIGHTMOST_BUTTON_PRESSED > 0: - button = MouseButtonRight - case s&coninput.FROM_LEFT_3RD_BUTTON_PRESSED > 0: - button = MouseButtonBackward - case s&coninput.FROM_LEFT_4TH_BUTTON_PRESSED > 0: - button = MouseButtonForward - } - return - } - - switch { - case btn == coninput.FROM_LEFT_1ST_BUTTON_PRESSED: // left button - button = MouseButtonLeft - case btn == coninput.RIGHTMOST_BUTTON_PRESSED: // right button - button = MouseButtonRight - case btn == coninput.FROM_LEFT_2ND_BUTTON_PRESSED: // middle button - button = MouseButtonMiddle - case btn == coninput.FROM_LEFT_3RD_BUTTON_PRESSED: // unknown (possibly mouse backward) - button = MouseButtonBackward - case btn == coninput.FROM_LEFT_4TH_BUTTON_PRESSED: // unknown (possibly mouse forward) - button = MouseButtonForward - } - - return button, action -} - -func mouseEvent(p coninput.ButtonState, e coninput.MouseEventRecord) MouseMsg { - ev := MouseMsg{ - X: int(e.MousePositon.X), - Y: int(e.MousePositon.Y), - Alt: e.ControlKeyState.Contains(coninput.LEFT_ALT_PRESSED | coninput.RIGHT_ALT_PRESSED), - Ctrl: e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED), - Shift: e.ControlKeyState.Contains(coninput.SHIFT_PRESSED), - } - switch e.EventFlags { - case coninput.CLICK, coninput.DOUBLE_CLICK: - ev.Button, ev.Action = mouseEventButton(p, e.ButtonState) - if ev.Action == MouseActionRelease { - ev.Type = MouseRelease - } - switch ev.Button { - case MouseButtonLeft: - ev.Type = MouseLeft - case MouseButtonMiddle: - ev.Type = MouseMiddle - case MouseButtonRight: - ev.Type = MouseRight - case MouseButtonBackward: - ev.Type = MouseBackward - case MouseButtonForward: - ev.Type = MouseForward - } - case coninput.MOUSE_WHEELED: - if e.WheelDirection > 0 { - ev.Button = MouseButtonWheelUp - ev.Type = MouseWheelUp - } else { - ev.Button = MouseButtonWheelDown - ev.Type = MouseWheelDown - } - case coninput.MOUSE_HWHEELED: - if e.WheelDirection > 0 { - ev.Button = MouseButtonWheelRight - ev.Type = MouseWheelRight - } else { - ev.Button = MouseButtonWheelLeft - ev.Type = MouseWheelLeft - } - case coninput.MOUSE_MOVED: - ev.Button, _ = mouseEventButton(p, e.ButtonState) - ev.Action = MouseActionMotion - ev.Type = MouseMotion - } - - return ev -} - -func keyType(e coninput.KeyEventRecord) KeyType { - code := e.VirtualKeyCode - - shiftPressed := e.ControlKeyState.Contains(coninput.SHIFT_PRESSED) - ctrlPressed := e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED) - - switch code { - case coninput.VK_RETURN: - return KeyEnter - case coninput.VK_BACK: - return KeyBackspace - case coninput.VK_TAB: - if shiftPressed { - return KeyShiftTab - } - return KeyTab - case coninput.VK_SPACE: - return KeyRunes // this could be KeySpace but on unix space also produces KeyRunes - case coninput.VK_ESCAPE: - return KeyEscape - case coninput.VK_UP: - switch { - case shiftPressed && ctrlPressed: - return KeyCtrlShiftUp - case shiftPressed: - return KeyShiftUp - case ctrlPressed: - return KeyCtrlUp - default: - return KeyUp - } - case coninput.VK_DOWN: - switch { - case shiftPressed && ctrlPressed: - return KeyCtrlShiftDown - case shiftPressed: - return KeyShiftDown - case ctrlPressed: - return KeyCtrlDown - default: - return KeyDown - } - case coninput.VK_RIGHT: - switch { - case shiftPressed && ctrlPressed: - return KeyCtrlShiftRight - case shiftPressed: - return KeyShiftRight - case ctrlPressed: - return KeyCtrlRight - default: - return KeyRight - } - case coninput.VK_LEFT: - switch { - case shiftPressed && ctrlPressed: - return KeyCtrlShiftLeft - case shiftPressed: - return KeyShiftLeft - case ctrlPressed: - return KeyCtrlLeft - default: - return KeyLeft - } - case coninput.VK_HOME: - switch { - case shiftPressed && ctrlPressed: - return KeyCtrlShiftHome - case shiftPressed: - return KeyShiftHome - case ctrlPressed: - return KeyCtrlHome - default: - return KeyHome - } - case coninput.VK_END: - switch { - case shiftPressed && ctrlPressed: - return KeyCtrlShiftEnd - case shiftPressed: - return KeyShiftEnd - case ctrlPressed: - return KeyCtrlEnd - default: - return KeyEnd - } - case coninput.VK_PRIOR: - return KeyPgUp - case coninput.VK_NEXT: - return KeyPgDown - case coninput.VK_DELETE: - return KeyDelete - default: - switch { - case e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED) && e.ControlKeyState.Contains(coninput.RIGHT_ALT_PRESSED): - // AltGr is pressed, then it's a rune. - fallthrough - case !e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED) && !e.ControlKeyState.Contains(coninput.RIGHT_CTRL_PRESSED): - return KeyRunes - } - - switch e.Char { - case '@': - return KeyCtrlAt - case '\x01': - return KeyCtrlA - case '\x02': - return KeyCtrlB - case '\x03': - return KeyCtrlC - case '\x04': - return KeyCtrlD - case '\x05': - return KeyCtrlE - case '\x06': - return KeyCtrlF - case '\a': - return KeyCtrlG - case '\b': - return KeyCtrlH - case '\t': - return KeyCtrlI - case '\n': - return KeyCtrlJ - case '\v': - return KeyCtrlK - case '\f': - return KeyCtrlL - case '\r': - return KeyCtrlM - case '\x0e': - return KeyCtrlN - case '\x0f': - return KeyCtrlO - case '\x10': - return KeyCtrlP - case '\x11': - return KeyCtrlQ - case '\x12': - return KeyCtrlR - case '\x13': - return KeyCtrlS - case '\x14': - return KeyCtrlT - case '\x15': - return KeyCtrlU - case '\x16': - return KeyCtrlV - case '\x17': - return KeyCtrlW - case '\x18': - return KeyCtrlX - case '\x19': - return KeyCtrlY - case '\x1a': - return KeyCtrlZ - case '\x1b': - return KeyCtrlOpenBracket // KeyEscape - case '\x1c': - return KeyCtrlBackslash - case '\x1f': - return KeyCtrlUnderscore - } - - switch code { - case coninput.VK_OEM_4: - return KeyCtrlOpenBracket - case coninput.VK_OEM_6: - return KeyCtrlCloseBracket - } - - return KeyRunes - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/logging.go b/vendor/github.com/charmbracelet/bubbletea/logging.go deleted file mode 100644 index a5311819..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/logging.go +++ /dev/null @@ -1,53 +0,0 @@ -package tea - -import ( - "fmt" - "io" - "log" - "os" - "unicode" -) - -// LogToFile sets up default logging to log to a file. This is helpful as we -// can't print to the terminal since our TUI is occupying it. If the file -// doesn't exist it will be created. -// -// Don't forget to close the file when you're done with it. -// -// f, err := LogToFile("debug.log", "debug") -// if err != nil { -// fmt.Println("fatal:", err) -// os.Exit(1) -// } -// defer f.Close() -func LogToFile(path string, prefix string) (*os.File, error) { - return LogToFileWith(path, prefix, log.Default()) -} - -// LogOptionsSetter is an interface implemented by stdlib's log and charm's log -// libraries. -type LogOptionsSetter interface { - SetOutput(io.Writer) - SetPrefix(string) -} - -// LogToFileWith does allows to call LogToFile with a custom LogOptionsSetter. -func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*os.File, error) { - f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:gomnd - if err != nil { - return nil, fmt.Errorf("error opening file for logging: %w", err) - } - log.SetOutput(f) - - // Add a space after the prefix if a prefix is being specified and it - // doesn't already have a trailing space. - if len(prefix) > 0 { - finalChar := prefix[len(prefix)-1] - if !unicode.IsSpace(rune(finalChar)) { - prefix += " " - } - } - log.SetPrefix(prefix) - - return f, nil -} diff --git a/vendor/github.com/charmbracelet/bubbletea/mouse.go b/vendor/github.com/charmbracelet/bubbletea/mouse.go deleted file mode 100644 index 6ec51cc0..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/mouse.go +++ /dev/null @@ -1,308 +0,0 @@ -package tea - -import "strconv" - -// MouseMsg contains information about a mouse event and are sent to a programs -// update function when mouse activity occurs. Note that the mouse must first -// be enabled in order for the mouse events to be received. -type MouseMsg MouseEvent - -// String returns a string representation of a mouse event. -func (m MouseMsg) String() string { - return MouseEvent(m).String() -} - -// MouseEvent represents a mouse event, which could be a click, a scroll wheel -// movement, a cursor movement, or a combination. -type MouseEvent struct { - X int - Y int - Shift bool - Alt bool - Ctrl bool - Action MouseAction - Button MouseButton - - // Deprecated: Use MouseAction & MouseButton instead. - Type MouseEventType -} - -// IsWheel returns true if the mouse event is a wheel event. -func (m MouseEvent) IsWheel() bool { - return m.Button == MouseButtonWheelUp || m.Button == MouseButtonWheelDown || - m.Button == MouseButtonWheelLeft || m.Button == MouseButtonWheelRight -} - -// String returns a string representation of a mouse event. -func (m MouseEvent) String() (s string) { - if m.Ctrl { - s += "ctrl+" - } - if m.Alt { - s += "alt+" - } - if m.Shift { - s += "shift+" - } - - if m.Button == MouseButtonNone { //nolint:nestif - if m.Action == MouseActionMotion || m.Action == MouseActionRelease { - s += mouseActions[m.Action] - } else { - s += "unknown" - } - } else if m.IsWheel() { - s += mouseButtons[m.Button] - } else { - btn := mouseButtons[m.Button] - if btn != "" { - s += btn - } - act := mouseActions[m.Action] - if act != "" { - s += " " + act - } - } - - return s -} - -// MouseAction represents the action that occurred during a mouse event. -type MouseAction int - -// Mouse event actions. -const ( - MouseActionPress MouseAction = iota - MouseActionRelease - MouseActionMotion -) - -var mouseActions = map[MouseAction]string{ - MouseActionPress: "press", - MouseActionRelease: "release", - MouseActionMotion: "motion", -} - -// MouseButton represents the button that was pressed during a mouse event. -type MouseButton int - -// Mouse event buttons -// -// This is based on X11 mouse button codes. -// -// 1 = left button -// 2 = middle button (pressing the scroll wheel) -// 3 = right button -// 4 = turn scroll wheel up -// 5 = turn scroll wheel down -// 6 = push scroll wheel left -// 7 = push scroll wheel right -// 8 = 4th button (aka browser backward button) -// 9 = 5th button (aka browser forward button) -// 10 -// 11 -// -// Other buttons are not supported. -const ( - MouseButtonNone MouseButton = iota - MouseButtonLeft - MouseButtonMiddle - MouseButtonRight - MouseButtonWheelUp - MouseButtonWheelDown - MouseButtonWheelLeft - MouseButtonWheelRight - MouseButtonBackward - MouseButtonForward - MouseButton10 - MouseButton11 -) - -var mouseButtons = map[MouseButton]string{ - MouseButtonNone: "none", - MouseButtonLeft: "left", - MouseButtonMiddle: "middle", - MouseButtonRight: "right", - MouseButtonWheelUp: "wheel up", - MouseButtonWheelDown: "wheel down", - MouseButtonWheelLeft: "wheel left", - MouseButtonWheelRight: "wheel right", - MouseButtonBackward: "backward", - MouseButtonForward: "forward", - MouseButton10: "button 10", - MouseButton11: "button 11", -} - -// MouseEventType indicates the type of mouse event occurring. -// -// Deprecated: Use MouseAction & MouseButton instead. -type MouseEventType int - -// Mouse event types. -// -// Deprecated: Use MouseAction & MouseButton instead. -const ( - MouseUnknown MouseEventType = iota - MouseLeft - MouseRight - MouseMiddle - MouseRelease // mouse button release (X10 only) - MouseWheelUp - MouseWheelDown - MouseWheelLeft - MouseWheelRight - MouseBackward - MouseForward - MouseMotion -) - -// Parse SGR-encoded mouse events; SGR extended mouse events. SGR mouse events -// look like: -// -// ESC [ < Cb ; Cx ; Cy (M or m) -// -// where: -// -// Cb is the encoded button code -// Cx is the x-coordinate of the mouse -// Cy is the y-coordinate of the mouse -// M is for button press, m is for button release -// -// https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Extended-coordinates -func parseSGRMouseEvent(buf []byte) MouseEvent { - str := string(buf[3:]) - matches := mouseSGRRegex.FindStringSubmatch(str) - if len(matches) != 5 { //nolint:gomnd - // Unreachable, we already checked the regex in `detectOneMsg`. - panic("invalid mouse event") - } - - b, _ := strconv.Atoi(matches[1]) - px := matches[2] - py := matches[3] - release := matches[4] == "m" - m := parseMouseButton(b, true) - - // Wheel buttons don't have release events - // Motion can be reported as a release event in some terminals (Windows Terminal) - if m.Action != MouseActionMotion && !m.IsWheel() && release { - m.Action = MouseActionRelease - m.Type = MouseRelease - } - - x, _ := strconv.Atoi(px) - y, _ := strconv.Atoi(py) - - // (1,1) is the upper left. We subtract 1 to normalize it to (0,0). - m.X = x - 1 - m.Y = y - 1 - - return m -} - -const x10MouseByteOffset = 32 - -// Parse X10-encoded mouse events; the simplest kind. The last release of X10 -// was December 1986, by the way. The original X10 mouse protocol limits the Cx -// and Cy coordinates to 223 (=255-032). -// -// X10 mouse events look like: -// -// ESC [M Cb Cx Cy -// -// See: http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking -func parseX10MouseEvent(buf []byte) MouseEvent { - v := buf[3:6] - m := parseMouseButton(int(v[0]), false) - - // (1,1) is the upper left. We subtract 1 to normalize it to (0,0). - m.X = int(v[1]) - x10MouseByteOffset - 1 - m.Y = int(v[2]) - x10MouseByteOffset - 1 - - return m -} - -// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Extended-coordinates -func parseMouseButton(b int, isSGR bool) MouseEvent { - var m MouseEvent - e := b - if !isSGR { - e -= x10MouseByteOffset - } - - const ( - bitShift = 0b0000_0100 - bitAlt = 0b0000_1000 - bitCtrl = 0b0001_0000 - bitMotion = 0b0010_0000 - bitWheel = 0b0100_0000 - bitAdd = 0b1000_0000 // additional buttons 8-11 - - bitsMask = 0b0000_0011 - ) - - if e&bitAdd != 0 { - m.Button = MouseButtonBackward + MouseButton(e&bitsMask) - } else if e&bitWheel != 0 { - m.Button = MouseButtonWheelUp + MouseButton(e&bitsMask) - } else { - m.Button = MouseButtonLeft + MouseButton(e&bitsMask) - // X10 reports a button release as 0b0000_0011 (3) - if e&bitsMask == bitsMask { - m.Action = MouseActionRelease - m.Button = MouseButtonNone - } - } - - // Motion bit doesn't get reported for wheel events. - if e&bitMotion != 0 && !m.IsWheel() { - m.Action = MouseActionMotion - } - - // Modifiers - m.Alt = e&bitAlt != 0 - m.Ctrl = e&bitCtrl != 0 - m.Shift = e&bitShift != 0 - - // backward compatibility - switch { - case m.Button == MouseButtonLeft && m.Action == MouseActionPress: - m.Type = MouseLeft - case m.Button == MouseButtonMiddle && m.Action == MouseActionPress: - m.Type = MouseMiddle - case m.Button == MouseButtonRight && m.Action == MouseActionPress: - m.Type = MouseRight - case m.Button == MouseButtonNone && m.Action == MouseActionRelease: - m.Type = MouseRelease - case m.Button == MouseButtonWheelUp && m.Action == MouseActionPress: - m.Type = MouseWheelUp - case m.Button == MouseButtonWheelDown && m.Action == MouseActionPress: - m.Type = MouseWheelDown - case m.Button == MouseButtonWheelLeft && m.Action == MouseActionPress: - m.Type = MouseWheelLeft - case m.Button == MouseButtonWheelRight && m.Action == MouseActionPress: - m.Type = MouseWheelRight - case m.Button == MouseButtonBackward && m.Action == MouseActionPress: - m.Type = MouseBackward - case m.Button == MouseButtonForward && m.Action == MouseActionPress: - m.Type = MouseForward - case m.Action == MouseActionMotion: - m.Type = MouseMotion - switch m.Button { //nolint:exhaustive - case MouseButtonLeft: - m.Type = MouseLeft - case MouseButtonMiddle: - m.Type = MouseMiddle - case MouseButtonRight: - m.Type = MouseRight - case MouseButtonBackward: - m.Type = MouseBackward - case MouseButtonForward: - m.Type = MouseForward - } - default: - m.Type = MouseUnknown - } - - return m -} diff --git a/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go b/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go deleted file mode 100644 index 0bc4a172..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go +++ /dev/null @@ -1,28 +0,0 @@ -package tea - -type nilRenderer struct{} - -func (n nilRenderer) start() {} -func (n nilRenderer) stop() {} -func (n nilRenderer) kill() {} -func (n nilRenderer) write(_ string) {} -func (n nilRenderer) repaint() {} -func (n nilRenderer) clearScreen() {} -func (n nilRenderer) altScreen() bool { return false } -func (n nilRenderer) enterAltScreen() {} -func (n nilRenderer) exitAltScreen() {} -func (n nilRenderer) showCursor() {} -func (n nilRenderer) hideCursor() {} -func (n nilRenderer) enableMouseCellMotion() {} -func (n nilRenderer) disableMouseCellMotion() {} -func (n nilRenderer) enableMouseAllMotion() {} -func (n nilRenderer) disableMouseAllMotion() {} -func (n nilRenderer) enableBracketedPaste() {} -func (n nilRenderer) disableBracketedPaste() {} -func (n nilRenderer) enableMouseSGRMode() {} -func (n nilRenderer) disableMouseSGRMode() {} -func (n nilRenderer) bracketedPasteActive() bool { return false } -func (n nilRenderer) setWindowTitle(_ string) {} -func (n nilRenderer) reportFocus() bool { return false } -func (n nilRenderer) enableReportFocus() {} -func (n nilRenderer) disableReportFocus() {} diff --git a/vendor/github.com/charmbracelet/bubbletea/options.go b/vendor/github.com/charmbracelet/bubbletea/options.go deleted file mode 100644 index c509353b..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/options.go +++ /dev/null @@ -1,252 +0,0 @@ -package tea - -import ( - "context" - "io" - "sync/atomic" -) - -// ProgramOption is used to set options when initializing a Program. Program can -// accept a variable number of options. -// -// Example usage: -// -// p := NewProgram(model, WithInput(someInput), WithOutput(someOutput)) -type ProgramOption func(*Program) - -// WithContext lets you specify a context in which to run the Program. This is -// useful if you want to cancel the execution from outside. When a Program gets -// cancelled it will exit with an error ErrProgramKilled. -func WithContext(ctx context.Context) ProgramOption { - return func(p *Program) { - p.ctx = ctx - } -} - -// WithOutput sets the output which, by default, is stdout. In most cases you -// won't need to use this. -func WithOutput(output io.Writer) ProgramOption { - return func(p *Program) { - p.output = output - } -} - -// WithInput sets the input which, by default, is stdin. In most cases you -// won't need to use this. To disable input entirely pass nil. -// -// p := NewProgram(model, WithInput(nil)) -func WithInput(input io.Reader) ProgramOption { - return func(p *Program) { - p.input = input - p.inputType = customInput - } -} - -// WithInputTTY opens a new TTY for input (or console input device on Windows). -func WithInputTTY() ProgramOption { - return func(p *Program) { - p.inputType = ttyInput - } -} - -// WithEnvironment sets the environment variables that the program will use. -// This useful when the program is running in a remote session (e.g. SSH) and -// you want to pass the environment variables from the remote session to the -// program. -// -// Example: -// -// var sess ssh.Session // ssh.Session is a type from the github.com/charmbracelet/ssh package -// pty, _, _ := sess.Pty() -// environ := append(sess.Environ(), "TERM="+pty.Term) -// p := tea.NewProgram(model, tea.WithEnvironment(environ) -func WithEnvironment(env []string) ProgramOption { - return func(p *Program) { - p.environ = env - } -} - -// WithoutSignalHandler disables the signal handler that Bubble Tea sets up for -// Programs. This is useful if you want to handle signals yourself. -func WithoutSignalHandler() ProgramOption { - return func(p *Program) { - p.startupOptions |= withoutSignalHandler - } -} - -// WithoutCatchPanics disables the panic catching that Bubble Tea does by -// default. If panic catching is disabled the terminal will be in a fairly -// unusable state after a panic because Bubble Tea will not perform its usual -// cleanup on exit. -func WithoutCatchPanics() ProgramOption { - return func(p *Program) { - p.startupOptions |= withoutCatchPanics - } -} - -// WithoutSignals will ignore OS signals. -// This is mainly useful for testing. -func WithoutSignals() ProgramOption { - return func(p *Program) { - atomic.StoreUint32(&p.ignoreSignals, 1) - } -} - -// WithAltScreen starts the program with the alternate screen buffer enabled -// (i.e. the program starts in full window mode). Note that the altscreen will -// be automatically exited when the program quits. -// -// Example: -// -// p := tea.NewProgram(Model{}, tea.WithAltScreen()) -// if _, err := p.Run(); err != nil { -// fmt.Println("Error running program:", err) -// os.Exit(1) -// } -// -// To enter the altscreen once the program has already started running use the -// EnterAltScreen command. -func WithAltScreen() ProgramOption { - return func(p *Program) { - p.startupOptions |= withAltScreen - } -} - -// WithoutBracketedPaste starts the program with bracketed paste disabled. -func WithoutBracketedPaste() ProgramOption { - return func(p *Program) { - p.startupOptions |= withoutBracketedPaste - } -} - -// WithMouseCellMotion starts the program with the mouse enabled in "cell -// motion" mode. -// -// Cell motion mode enables mouse click, release, and wheel events. Mouse -// movement events are also captured if a mouse button is pressed (i.e., drag -// events). Cell motion mode is better supported than all motion mode. -// -// This will try to enable the mouse in extended mode (SGR), if that is not -// supported by the terminal it will fall back to normal mode (X10). -// -// To enable mouse cell motion once the program has already started running use -// the EnableMouseCellMotion command. To disable the mouse when the program is -// running use the DisableMouse command. -// -// The mouse will be automatically disabled when the program exits. -func WithMouseCellMotion() ProgramOption { - return func(p *Program) { - p.startupOptions |= withMouseCellMotion // set - p.startupOptions &^= withMouseAllMotion // clear - } -} - -// WithMouseAllMotion starts the program with the mouse enabled in "all motion" -// mode. -// -// EnableMouseAllMotion is a special command that enables mouse click, release, -// wheel, and motion events, which are delivered regardless of whether a mouse -// button is pressed, effectively enabling support for hover interactions. -// -// This will try to enable the mouse in extended mode (SGR), if that is not -// supported by the terminal it will fall back to normal mode (X10). -// -// Many modern terminals support this, but not all. If in doubt, use -// EnableMouseCellMotion instead. -// -// To enable the mouse once the program has already started running use the -// EnableMouseAllMotion command. To disable the mouse when the program is -// running use the DisableMouse command. -// -// The mouse will be automatically disabled when the program exits. -func WithMouseAllMotion() ProgramOption { - return func(p *Program) { - p.startupOptions |= withMouseAllMotion // set - p.startupOptions &^= withMouseCellMotion // clear - } -} - -// WithoutRenderer disables the renderer. When this is set output and log -// statements will be plainly sent to stdout (or another output if one is set) -// without any rendering and redrawing logic. In other words, printing and -// logging will behave the same way it would in a non-TUI commandline tool. -// This can be useful if you want to use the Bubble Tea framework for a non-TUI -// application, or to provide an additional non-TUI mode to your Bubble Tea -// programs. For example, your program could behave like a daemon if output is -// not a TTY. -func WithoutRenderer() ProgramOption { - return func(p *Program) { - p.renderer = &nilRenderer{} - } -} - -// WithANSICompressor removes redundant ANSI sequences to produce potentially -// smaller output, at the cost of some processing overhead. -// -// This feature is provisional, and may be changed or removed in a future version -// of this package. -// -// Deprecated: this incurs a noticeable performance hit. A future release will -// optimize ANSI automatically without the performance penalty. -func WithANSICompressor() ProgramOption { - return func(p *Program) { - p.startupOptions |= withANSICompressor - } -} - -// WithFilter supplies an event filter that will be invoked before Bubble Tea -// processes a tea.Msg. The event filter can return any tea.Msg which will then -// get handled by Bubble Tea instead of the original event. If the event filter -// returns nil, the event will be ignored and Bubble Tea will not process it. -// -// As an example, this could be used to prevent a program from shutting down if -// there are unsaved changes. -// -// Example: -// -// func filter(m tea.Model, msg tea.Msg) tea.Msg { -// if _, ok := msg.(tea.QuitMsg); !ok { -// return msg -// } -// -// model := m.(myModel) -// if model.hasChanges { -// return nil -// } -// -// return msg -// } -// -// p := tea.NewProgram(Model{}, tea.WithFilter(filter)); -// -// if _,err := p.Run(); err != nil { -// fmt.Println("Error running program:", err) -// os.Exit(1) -// } -func WithFilter(filter func(Model, Msg) Msg) ProgramOption { - return func(p *Program) { - p.filter = filter - } -} - -// WithFPS sets a custom maximum FPS at which the renderer should run. If -// less than 1, the default value of 60 will be used. If over 120, the FPS -// will be capped at 120. -func WithFPS(fps int) ProgramOption { - return func(p *Program) { - p.fps = fps - } -} - -// WithReportFocus enables reporting when the terminal gains and loses -// focus. When this is enabled [FocusMsg] and [BlurMsg] messages will be sent -// to your Update method. -// -// Note that while most terminals and multiplexers support focus reporting, -// some do not. Also note that tmux needs to be configured to report focus -// events. -func WithReportFocus() ProgramOption { - return func(p *Program) { - p.startupOptions |= withReportFocus - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/renderer.go b/vendor/github.com/charmbracelet/bubbletea/renderer.go deleted file mode 100644 index 9eb7943b..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/renderer.go +++ /dev/null @@ -1,85 +0,0 @@ -package tea - -// renderer is the interface for Bubble Tea renderers. -type renderer interface { - // Start the renderer. - start() - - // Stop the renderer, but render the final frame in the buffer, if any. - stop() - - // Stop the renderer without doing any final rendering. - kill() - - // Write a frame to the renderer. The renderer can write this data to - // output at its discretion. - write(string) - - // Request a full re-render. Note that this will not trigger a render - // immediately. Rather, this method causes the next render to be a full - // repaint. Because of this, it's safe to call this method multiple times - // in succession. - repaint() - - // Clears the terminal. - clearScreen() - - // Whether or not the alternate screen buffer is enabled. - altScreen() bool - // Enable the alternate screen buffer. - enterAltScreen() - // Disable the alternate screen buffer. - exitAltScreen() - - // Show the cursor. - showCursor() - // Hide the cursor. - hideCursor() - - // enableMouseCellMotion enables mouse click, release, wheel and motion - // events if a mouse button is pressed (i.e., drag events). - enableMouseCellMotion() - - // disableMouseCellMotion disables Mouse Cell Motion tracking. - disableMouseCellMotion() - - // enableMouseAllMotion enables mouse click, release, wheel and motion - // events, regardless of whether a mouse button is pressed. Many modern - // terminals support this, but not all. - enableMouseAllMotion() - - // disableMouseAllMotion disables All Motion mouse tracking. - disableMouseAllMotion() - - // enableMouseSGRMode enables mouse extended mode (SGR). - enableMouseSGRMode() - - // disableMouseSGRMode disables mouse extended mode (SGR). - disableMouseSGRMode() - - // enableBracketedPaste enables bracketed paste, where characters - // inside the input are not interpreted when pasted as a whole. - enableBracketedPaste() - - // disableBracketedPaste disables bracketed paste. - disableBracketedPaste() - - // bracketedPasteActive reports whether bracketed paste mode is - // currently enabled. - bracketedPasteActive() bool - - // setWindowTitle sets the terminal window title. - setWindowTitle(string) - - // reportFocus returns whether reporting focus events is enabled. - reportFocus() bool - - // enableReportFocus reports focus events to the program. - enableReportFocus() - - // disableReportFocus stops reporting focus events to the program. - disableReportFocus() -} - -// repaintMsg forces a full repaint. -type repaintMsg struct{} diff --git a/vendor/github.com/charmbracelet/bubbletea/screen.go b/vendor/github.com/charmbracelet/bubbletea/screen.go deleted file mode 100644 index dfec48f0..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/screen.go +++ /dev/null @@ -1,248 +0,0 @@ -package tea - -// WindowSizeMsg is used to report the terminal size. It's sent to Update once -// initially and then on every terminal resize. Note that Windows does not -// have support for reporting when resizes occur as it does not support the -// SIGWINCH signal. -type WindowSizeMsg struct { - Width int - Height int -} - -// ClearScreen is a special command that tells the program to clear the screen -// before the next update. This can be used to move the cursor to the top left -// of the screen and clear visual clutter when the alt screen is not in use. -// -// Note that it should never be necessary to call ClearScreen() for regular -// redraws. -func ClearScreen() Msg { - return clearScreenMsg{} -} - -// clearScreenMsg is an internal message that signals to clear the screen. -// You can send a clearScreenMsg with ClearScreen. -type clearScreenMsg struct{} - -// EnterAltScreen is a special command that tells the Bubble Tea program to -// enter the alternate screen buffer. -// -// Because commands run asynchronously, this command should not be used in your -// model's Init function. To initialize your program with the altscreen enabled -// use the WithAltScreen ProgramOption instead. -func EnterAltScreen() Msg { - return enterAltScreenMsg{} -} - -// enterAltScreenMsg in an internal message signals that the program should -// enter alternate screen buffer. You can send a enterAltScreenMsg with -// EnterAltScreen. -type enterAltScreenMsg struct{} - -// ExitAltScreen is a special command that tells the Bubble Tea program to exit -// the alternate screen buffer. This command should be used to exit the -// alternate screen buffer while the program is running. -// -// Note that the alternate screen buffer will be automatically exited when the -// program quits. -func ExitAltScreen() Msg { - return exitAltScreenMsg{} -} - -// exitAltScreenMsg in an internal message signals that the program should exit -// alternate screen buffer. You can send a exitAltScreenMsg with ExitAltScreen. -type exitAltScreenMsg struct{} - -// EnableMouseCellMotion is a special command that enables mouse click, -// release, and wheel events. Mouse movement events are also captured if -// a mouse button is pressed (i.e., drag events). -// -// Because commands run asynchronously, this command should not be used in your -// model's Init function. Use the WithMouseCellMotion ProgramOption instead. -func EnableMouseCellMotion() Msg { - return enableMouseCellMotionMsg{} -} - -// enableMouseCellMotionMsg is a special command that signals to start -// listening for "cell motion" type mouse events (ESC[?1002l). To send an -// enableMouseCellMotionMsg, use the EnableMouseCellMotion command. -type enableMouseCellMotionMsg struct{} - -// EnableMouseAllMotion is a special command that enables mouse click, release, -// wheel, and motion events, which are delivered regardless of whether a mouse -// button is pressed, effectively enabling support for hover interactions. -// -// Many modern terminals support this, but not all. If in doubt, use -// EnableMouseCellMotion instead. -// -// Because commands run asynchronously, this command should not be used in your -// model's Init function. Use the WithMouseAllMotion ProgramOption instead. -func EnableMouseAllMotion() Msg { - return enableMouseAllMotionMsg{} -} - -// enableMouseAllMotionMsg is a special command that signals to start listening -// for "all motion" type mouse events (ESC[?1003l). To send an -// enableMouseAllMotionMsg, use the EnableMouseAllMotion command. -type enableMouseAllMotionMsg struct{} - -// DisableMouse is a special command that stops listening for mouse events. -func DisableMouse() Msg { - return disableMouseMsg{} -} - -// disableMouseMsg is an internal message that signals to stop listening -// for mouse events. To send a disableMouseMsg, use the DisableMouse command. -type disableMouseMsg struct{} - -// HideCursor is a special command for manually instructing Bubble Tea to hide -// the cursor. In some rare cases, certain operations will cause the terminal -// to show the cursor, which is normally hidden for the duration of a Bubble -// Tea program's lifetime. You will most likely not need to use this command. -func HideCursor() Msg { - return hideCursorMsg{} -} - -// hideCursorMsg is an internal command used to hide the cursor. You can send -// this message with HideCursor. -type hideCursorMsg struct{} - -// ShowCursor is a special command for manually instructing Bubble Tea to show -// the cursor. -func ShowCursor() Msg { - return showCursorMsg{} -} - -// showCursorMsg is an internal command used to show the cursor. You can send -// this message with ShowCursor. -type showCursorMsg struct{} - -// EnableBracketedPaste is a special command that tells the Bubble Tea program -// to accept bracketed paste input. -// -// Note that bracketed paste will be automatically disabled when the -// program quits. -func EnableBracketedPaste() Msg { - return enableBracketedPasteMsg{} -} - -// enableBracketedPasteMsg in an internal message signals that -// bracketed paste should be enabled. You can send an -// enableBracketedPasteMsg with EnableBracketedPaste. -type enableBracketedPasteMsg struct{} - -// DisableBracketedPaste is a special command that tells the Bubble Tea program -// to accept bracketed paste input. -// -// Note that bracketed paste will be automatically disabled when the -// program quits. -func DisableBracketedPaste() Msg { - return disableBracketedPasteMsg{} -} - -// disableBracketedPasteMsg in an internal message signals that -// bracketed paste should be disabled. You can send an -// disableBracketedPasteMsg with DisableBracketedPaste. -type disableBracketedPasteMsg struct{} - -// enableReportFocusMsg is an internal message that signals to enable focus -// reporting. You can send an enableReportFocusMsg with EnableReportFocus. -type enableReportFocusMsg struct{} - -// EnableReportFocus is a special command that tells the Bubble Tea program to -// report focus events to the program. -func EnableReportFocus() Msg { - return enableReportFocusMsg{} -} - -// disableReportFocusMsg is an internal message that signals to disable focus -// reporting. You can send an disableReportFocusMsg with DisableReportFocus. -type disableReportFocusMsg struct{} - -// DisableReportFocus is a special command that tells the Bubble Tea program to -// stop reporting focus events to the program. -func DisableReportFocus() Msg { - return disableReportFocusMsg{} -} - -// EnterAltScreen enters the alternate screen buffer, which consumes the entire -// terminal window. ExitAltScreen will return the terminal to its former state. -// -// Deprecated: Use the WithAltScreen ProgramOption instead. -func (p *Program) EnterAltScreen() { - if p.renderer != nil { - p.renderer.enterAltScreen() - } else { - p.startupOptions |= withAltScreen - } -} - -// ExitAltScreen exits the alternate screen buffer. -// -// Deprecated: The altscreen will exited automatically when the program exits. -func (p *Program) ExitAltScreen() { - if p.renderer != nil { - p.renderer.exitAltScreen() - } else { - p.startupOptions &^= withAltScreen - } -} - -// EnableMouseCellMotion enables mouse click, release, wheel and motion events -// if a mouse button is pressed (i.e., drag events). -// -// Deprecated: Use the WithMouseCellMotion ProgramOption instead. -func (p *Program) EnableMouseCellMotion() { - if p.renderer != nil { - p.renderer.enableMouseCellMotion() - } else { - p.startupOptions |= withMouseCellMotion - } -} - -// DisableMouseCellMotion disables Mouse Cell Motion tracking. This will be -// called automatically when exiting a Bubble Tea program. -// -// Deprecated: The mouse will automatically be disabled when the program exits. -func (p *Program) DisableMouseCellMotion() { - if p.renderer != nil { - p.renderer.disableMouseCellMotion() - } else { - p.startupOptions &^= withMouseCellMotion - } -} - -// EnableMouseAllMotion enables mouse click, release, wheel and motion events, -// regardless of whether a mouse button is pressed. Many modern terminals -// support this, but not all. -// -// Deprecated: Use the WithMouseAllMotion ProgramOption instead. -func (p *Program) EnableMouseAllMotion() { - if p.renderer != nil { - p.renderer.enableMouseAllMotion() - } else { - p.startupOptions |= withMouseAllMotion - } -} - -// DisableMouseAllMotion disables All Motion mouse tracking. This will be -// called automatically when exiting a Bubble Tea program. -// -// Deprecated: The mouse will automatically be disabled when the program exits. -func (p *Program) DisableMouseAllMotion() { - if p.renderer != nil { - p.renderer.disableMouseAllMotion() - } else { - p.startupOptions &^= withMouseAllMotion - } -} - -// SetWindowTitle sets the terminal window title. -// -// Deprecated: Use the SetWindowTitle command instead. -func (p *Program) SetWindowTitle(title string) { - if p.renderer != nil { - p.renderer.setWindowTitle(title) - } else { - p.startupTitle = title - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/signals_unix.go b/vendor/github.com/charmbracelet/bubbletea/signals_unix.go deleted file mode 100644 index 40954038..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/signals_unix.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix || zos -// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix zos - -package tea - -import ( - "os" - "os/signal" - "syscall" -) - -// listenForResize sends messages (or errors) when the terminal resizes. -// Argument output should be the file descriptor for the terminal; usually -// os.Stdout. -func (p *Program) listenForResize(done chan struct{}) { - sig := make(chan os.Signal, 1) - signal.Notify(sig, syscall.SIGWINCH) - - defer func() { - signal.Stop(sig) - close(done) - }() - - for { - select { - case <-p.ctx.Done(): - return - case <-sig: - } - - p.checkResize() - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/signals_windows.go b/vendor/github.com/charmbracelet/bubbletea/signals_windows.go deleted file mode 100644 index 2fc6f8ae..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/signals_windows.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build windows -// +build windows - -package tea - -// listenForResize is not available on windows because windows does not -// implement syscall.SIGWINCH. -func (p *Program) listenForResize(done chan struct{}) { - close(done) -} diff --git a/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go b/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go deleted file mode 100644 index 45e8c82d..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go +++ /dev/null @@ -1,786 +0,0 @@ -package tea - -import ( - "bytes" - "fmt" - "io" - "strings" - "sync" - "time" - - "github.com/charmbracelet/x/ansi" - "github.com/muesli/ansi/compressor" -) - -const ( - // defaultFramerate specifies the maximum interval at which we should - // update the view. - defaultFPS = 60 - maxFPS = 120 -) - -// standardRenderer is a framerate-based terminal renderer, updating the view -// at a given framerate to avoid overloading the terminal emulator. -// -// In cases where very high performance is needed the renderer can be told -// to exclude ranges of lines, allowing them to be written to directly. -type standardRenderer struct { - mtx *sync.Mutex - out io.Writer - - buf bytes.Buffer - queuedMessageLines []string - framerate time.Duration - ticker *time.Ticker - done chan struct{} - lastRender string - lastRenderedLines []string - linesRendered int - altLinesRendered int - useANSICompressor bool - once sync.Once - - // cursor visibility state - cursorHidden bool - - // essentially whether or not we're using the full size of the terminal - altScreenActive bool - - // whether or not we're currently using bracketed paste - bpActive bool - - // reportingFocus whether reporting focus events is enabled - reportingFocus bool - - // renderer dimensions; usually the size of the window - width int - height int - - // lines explicitly set not to render - ignoreLines map[int]struct{} -} - -// newRenderer creates a new renderer. Normally you'll want to initialize it -// with os.Stdout as the first argument. -func newRenderer(out io.Writer, useANSICompressor bool, fps int) renderer { - if fps < 1 { - fps = defaultFPS - } else if fps > maxFPS { - fps = maxFPS - } - r := &standardRenderer{ - out: out, - mtx: &sync.Mutex{}, - done: make(chan struct{}), - framerate: time.Second / time.Duration(fps), - useANSICompressor: useANSICompressor, - queuedMessageLines: []string{}, - } - if r.useANSICompressor { - r.out = &compressor.Writer{Forward: out} - } - return r -} - -// start starts the renderer. -func (r *standardRenderer) start() { - if r.ticker == nil { - r.ticker = time.NewTicker(r.framerate) - } else { - // If the ticker already exists, it has been stopped and we need to - // reset it. - r.ticker.Reset(r.framerate) - } - - // Since the renderer can be restarted after a stop, we need to reset - // the done channel and its corresponding sync.Once. - r.once = sync.Once{} - - go r.listen() -} - -// stop permanently halts the renderer, rendering the final frame. -func (r *standardRenderer) stop() { - // Stop the renderer before acquiring the mutex to avoid a deadlock. - r.once.Do(func() { - r.done <- struct{}{} - }) - - // flush locks the mutex - r.flush() - - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.EraseEntireLine) - // Move the cursor back to the beginning of the line - r.execute("\r") - - if r.useANSICompressor { - if w, ok := r.out.(io.WriteCloser); ok { - _ = w.Close() - } - } -} - -// execute writes a sequence to the terminal. -func (r *standardRenderer) execute(seq string) { - _, _ = io.WriteString(r.out, seq) -} - -// kill halts the renderer. The final frame will not be rendered. -func (r *standardRenderer) kill() { - // Stop the renderer before acquiring the mutex to avoid a deadlock. - r.once.Do(func() { - r.done <- struct{}{} - }) - - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.EraseEntireLine) - // Move the cursor back to the beginning of the line - r.execute("\r") -} - -// listen waits for ticks on the ticker, or a signal to stop the renderer. -func (r *standardRenderer) listen() { - for { - select { - case <-r.done: - r.ticker.Stop() - return - - case <-r.ticker.C: - r.flush() - } - } -} - -// flush renders the buffer. -func (r *standardRenderer) flush() { - r.mtx.Lock() - defer r.mtx.Unlock() - - if r.buf.Len() == 0 || r.buf.String() == r.lastRender { - // Nothing to do. - return - } - - // Output buffer. - buf := &bytes.Buffer{} - - // Moving to the beginning of the section, that we rendered. - if r.altScreenActive { - buf.WriteString(ansi.CursorHomePosition) - } else if r.linesRendered > 1 { - buf.WriteString(ansi.CursorUp(r.linesRendered - 1)) - } - - newLines := strings.Split(r.buf.String(), "\n") - - // If we know the output's height, we can use it to determine how many - // lines we can render. We drop lines from the top of the render buffer if - // necessary, as we can't navigate the cursor into the terminal's scrollback - // buffer. - if r.height > 0 && len(newLines) > r.height { - newLines = newLines[len(newLines)-r.height:] - } - - flushQueuedMessages := len(r.queuedMessageLines) > 0 && !r.altScreenActive - - if flushQueuedMessages { - // Dump the lines we've queued up for printing. - for _, line := range r.queuedMessageLines { - if ansi.StringWidth(line) < r.width { - // We only erase the rest of the line when the line is shorter than - // the width of the terminal. When the cursor reaches the end of - // the line, any escape sequences that follow will only affect the - // last cell of the line. - - // Removing previously rendered content at the end of line. - line = line + ansi.EraseLineRight - } - - _, _ = buf.WriteString(line) - _, _ = buf.WriteString("\r\n") - } - // Clear the queued message lines. - r.queuedMessageLines = []string{} - } - - // Paint new lines. - for i := 0; i < len(newLines); i++ { - canSkip := !flushQueuedMessages && // Queuing messages triggers repaint -> we don't have access to previous frame content. - len(r.lastRenderedLines) > i && r.lastRenderedLines[i] == newLines[i] // Previously rendered line is the same. - - if _, ignore := r.ignoreLines[i]; ignore || canSkip { - // Unless this is the last line, move the cursor down. - if i < len(newLines)-1 { - buf.WriteByte('\n') - } - continue - } - - if i == 0 && r.lastRender == "" { - // On first render, reset the cursor to the start of the line - // before writing anything. - buf.WriteByte('\r') - } - - line := newLines[i] - - // Truncate lines wider than the width of the window to avoid - // wrapping, which will mess up rendering. If we don't have the - // width of the window this will be ignored. - // - // Note that on Windows we only get the width of the window on - // program initialization, so after a resize this won't perform - // correctly (signal SIGWINCH is not supported on Windows). - if r.width > 0 { - line = ansi.Truncate(line, r.width, "") - } - - if ansi.StringWidth(line) < r.width { - // We only erase the rest of the line when the line is shorter than - // the width of the terminal. When the cursor reaches the end of - // the line, any escape sequences that follow will only affect the - // last cell of the line. - - // Removing previously rendered content at the end of line. - line = line + ansi.EraseLineRight - } - - _, _ = buf.WriteString(line) - - if i < len(newLines)-1 { - _, _ = buf.WriteString("\r\n") - } - } - - // Clearing left over content from last render. - if r.lastLinesRendered() > len(newLines) { - buf.WriteString(ansi.EraseScreenBelow) - } - - if r.altScreenActive { - r.altLinesRendered = len(newLines) - } else { - r.linesRendered = len(newLines) - } - - // Make sure the cursor is at the start of the last line to keep rendering - // behavior consistent. - if r.altScreenActive { - // This case fixes a bug in macOS terminal. In other terminals the - // other case seems to do the job regardless of whether or not we're - // using the full terminal window. - buf.WriteString(ansi.CursorPosition(0, len(newLines))) - } else { - buf.WriteString(ansi.CursorBackward(r.width)) - } - - _, _ = r.out.Write(buf.Bytes()) - r.lastRender = r.buf.String() - - // Save previously rendered lines for comparison in the next render. If we - // don't do this, we can't skip rendering lines that haven't changed. - // See https://github.com/charmbracelet/bubbletea/pull/1233 - r.lastRenderedLines = newLines - r.buf.Reset() -} - -// lastLinesRendered returns the number of lines rendered lastly. -func (r *standardRenderer) lastLinesRendered() int { - if r.altScreenActive { - return r.altLinesRendered - } - return r.linesRendered -} - -// write writes to the internal buffer. The buffer will be outputted via the -// ticker which calls flush(). -func (r *standardRenderer) write(s string) { - r.mtx.Lock() - defer r.mtx.Unlock() - r.buf.Reset() - - // If an empty string was passed we should clear existing output and - // rendering nothing. Rather than introduce additional state to manage - // this, we render a single space as a simple (albeit less correct) - // solution. - if s == "" { - s = " " - } - - _, _ = r.buf.WriteString(s) -} - -func (r *standardRenderer) repaint() { - r.lastRender = "" - r.lastRenderedLines = nil -} - -func (r *standardRenderer) clearScreen() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.EraseEntireScreen) - r.execute(ansi.CursorHomePosition) - - r.repaint() -} - -func (r *standardRenderer) altScreen() bool { - r.mtx.Lock() - defer r.mtx.Unlock() - - return r.altScreenActive -} - -func (r *standardRenderer) enterAltScreen() { - r.mtx.Lock() - defer r.mtx.Unlock() - - if r.altScreenActive { - return - } - - r.altScreenActive = true - r.execute(ansi.SetAltScreenSaveCursorMode) - - // Ensure that the terminal is cleared, even when it doesn't support - // alt screen (or alt screen support is disabled, like GNU screen by - // default). - // - // Note: we can't use r.clearScreen() here because the mutex is already - // locked. - r.execute(ansi.EraseEntireScreen) - r.execute(ansi.CursorHomePosition) - - // cmd.exe and other terminals keep separate cursor states for the AltScreen - // and the main buffer. We have to explicitly reset the cursor visibility - // whenever we enter AltScreen. - if r.cursorHidden { - r.execute(ansi.HideCursor) - } else { - r.execute(ansi.ShowCursor) - } - - // Entering the alt screen resets the lines rendered count. - r.altLinesRendered = 0 - - r.repaint() -} - -func (r *standardRenderer) exitAltScreen() { - r.mtx.Lock() - defer r.mtx.Unlock() - - if !r.altScreenActive { - return - } - - r.altScreenActive = false - r.execute(ansi.ResetAltScreenSaveCursorMode) - - // cmd.exe and other terminals keep separate cursor states for the AltScreen - // and the main buffer. We have to explicitly reset the cursor visibility - // whenever we exit AltScreen. - if r.cursorHidden { - r.execute(ansi.HideCursor) - } else { - r.execute(ansi.ShowCursor) - } - - r.repaint() -} - -func (r *standardRenderer) showCursor() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.cursorHidden = false - r.execute(ansi.ShowCursor) -} - -func (r *standardRenderer) hideCursor() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.cursorHidden = true - r.execute(ansi.HideCursor) -} - -func (r *standardRenderer) enableMouseCellMotion() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.SetButtonEventMouseMode) -} - -func (r *standardRenderer) disableMouseCellMotion() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.ResetButtonEventMouseMode) -} - -func (r *standardRenderer) enableMouseAllMotion() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.SetAnyEventMouseMode) -} - -func (r *standardRenderer) disableMouseAllMotion() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.ResetAnyEventMouseMode) -} - -func (r *standardRenderer) enableMouseSGRMode() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.SetSgrExtMouseMode) -} - -func (r *standardRenderer) disableMouseSGRMode() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.ResetSgrExtMouseMode) -} - -func (r *standardRenderer) enableBracketedPaste() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.SetBracketedPasteMode) - r.bpActive = true -} - -func (r *standardRenderer) disableBracketedPaste() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.ResetBracketedPasteMode) - r.bpActive = false -} - -func (r *standardRenderer) bracketedPasteActive() bool { - r.mtx.Lock() - defer r.mtx.Unlock() - - return r.bpActive -} - -func (r *standardRenderer) enableReportFocus() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.SetFocusEventMode) - r.reportingFocus = true -} - -func (r *standardRenderer) disableReportFocus() { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.execute(ansi.ResetFocusEventMode) - r.reportingFocus = false -} - -func (r *standardRenderer) reportFocus() bool { - r.mtx.Lock() - defer r.mtx.Unlock() - - return r.reportingFocus -} - -// setWindowTitle sets the terminal window title. -func (r *standardRenderer) setWindowTitle(title string) { - r.execute(ansi.SetWindowTitle(title)) -} - -// setIgnoredLines specifies lines not to be touched by the standard Bubble Tea -// renderer. -func (r *standardRenderer) setIgnoredLines(from int, to int) { - // Lock if we're going to be clearing some lines since we don't want - // anything jacking our cursor. - if r.lastLinesRendered() > 0 { - r.mtx.Lock() - defer r.mtx.Unlock() - } - - if r.ignoreLines == nil { - r.ignoreLines = make(map[int]struct{}) - } - for i := from; i < to; i++ { - r.ignoreLines[i] = struct{}{} - } - - // Erase ignored lines - lastLinesRendered := r.lastLinesRendered() - if lastLinesRendered > 0 { - buf := &bytes.Buffer{} - - for i := lastLinesRendered - 1; i >= 0; i-- { - if _, exists := r.ignoreLines[i]; exists { - buf.WriteString(ansi.EraseEntireLine) - } - buf.WriteString(ansi.CUU1) - } - buf.WriteString(ansi.CursorPosition(0, lastLinesRendered)) // put cursor back - _, _ = r.out.Write(buf.Bytes()) - } -} - -// clearIgnoredLines returns control of any ignored lines to the standard -// Bubble Tea renderer. That is, any lines previously set to be ignored can be -// rendered to again. -func (r *standardRenderer) clearIgnoredLines() { - r.ignoreLines = nil -} - -// insertTop effectively scrolls up. It inserts lines at the top of a given -// area designated to be a scrollable region, pushing everything else down. -// This is roughly how ncurses does it. -// -// To call this function use command ScrollUp(). -// -// For this to work renderer.ignoreLines must be set to ignore the scrollable -// region since we are bypassing the normal Bubble Tea renderer here. -// -// Because this method relies on the terminal dimensions, it's only valid for -// full-window applications (generally those that use the alternate screen -// buffer). -// -// This method bypasses the normal rendering buffer and is philosophically -// different than the normal way we approach rendering in Bubble Tea. It's for -// use in high-performance rendering, such as a pager that could potentially -// be rendering very complicated ansi. In cases where the content is simpler -// standard Bubble Tea rendering should suffice. -// -// Deprecated: This option is deprecated and will be removed in a future -// version of this package. -func (r *standardRenderer) insertTop(lines []string, topBoundary, bottomBoundary int) { - r.mtx.Lock() - defer r.mtx.Unlock() - - buf := &bytes.Buffer{} - - buf.WriteString(ansi.SetTopBottomMargins(topBoundary, bottomBoundary)) - buf.WriteString(ansi.CursorPosition(0, topBoundary)) - buf.WriteString(ansi.InsertLine(len(lines))) - _, _ = buf.WriteString(strings.Join(lines, "\r\n")) - buf.WriteString(ansi.SetTopBottomMargins(0, r.height)) - - // Move cursor back to where the main rendering routine expects it to be - buf.WriteString(ansi.CursorPosition(0, r.lastLinesRendered())) - - _, _ = r.out.Write(buf.Bytes()) -} - -// insertBottom effectively scrolls down. It inserts lines at the bottom of -// a given area designated to be a scrollable region, pushing everything else -// up. This is roughly how ncurses does it. -// -// To call this function use the command ScrollDown(). -// -// See note in insertTop() for caveats, how this function only makes sense for -// full-window applications, and how it differs from the normal way we do -// rendering in Bubble Tea. -// -// Deprecated: This option is deprecated and will be removed in a future -// version of this package. -func (r *standardRenderer) insertBottom(lines []string, topBoundary, bottomBoundary int) { - r.mtx.Lock() - defer r.mtx.Unlock() - - buf := &bytes.Buffer{} - - buf.WriteString(ansi.SetTopBottomMargins(topBoundary, bottomBoundary)) - buf.WriteString(ansi.CursorPosition(0, bottomBoundary)) - _, _ = buf.WriteString("\r\n" + strings.Join(lines, "\r\n")) - buf.WriteString(ansi.SetTopBottomMargins(0, r.height)) - - // Move cursor back to where the main rendering routine expects it to be - buf.WriteString(ansi.CursorPosition(0, r.lastLinesRendered())) - - _, _ = r.out.Write(buf.Bytes()) -} - -// handleMessages handles internal messages for the renderer. -func (r *standardRenderer) handleMessages(msg Msg) { - switch msg := msg.(type) { - case repaintMsg: - // Force a repaint by clearing the render cache as we slide into a - // render. - r.mtx.Lock() - r.repaint() - r.mtx.Unlock() - - case WindowSizeMsg: - r.mtx.Lock() - r.width = msg.Width - r.height = msg.Height - r.repaint() - r.mtx.Unlock() - - case clearScrollAreaMsg: - r.clearIgnoredLines() - - // Force a repaint on the area where the scrollable stuff was in this - // update cycle - r.mtx.Lock() - r.repaint() - r.mtx.Unlock() - - case syncScrollAreaMsg: - // Re-render scrolling area - r.clearIgnoredLines() - r.setIgnoredLines(msg.topBoundary, msg.bottomBoundary) - r.insertTop(msg.lines, msg.topBoundary, msg.bottomBoundary) - - // Force non-scrolling stuff to repaint in this update cycle - r.mtx.Lock() - r.repaint() - r.mtx.Unlock() - - case scrollUpMsg: - r.insertTop(msg.lines, msg.topBoundary, msg.bottomBoundary) - - case scrollDownMsg: - r.insertBottom(msg.lines, msg.topBoundary, msg.bottomBoundary) - - case printLineMessage: - if !r.altScreenActive { - lines := strings.Split(msg.messageBody, "\n") - r.mtx.Lock() - r.queuedMessageLines = append(r.queuedMessageLines, lines...) - r.repaint() - r.mtx.Unlock() - } - } -} - -// HIGH-PERFORMANCE RENDERING STUFF - -type syncScrollAreaMsg struct { - lines []string - topBoundary int - bottomBoundary int -} - -// SyncScrollArea performs a paint of the entire region designated to be the -// scrollable area. This is required to initialize the scrollable region and -// should also be called on resize (WindowSizeMsg). -// -// For high-performance, scroll-based rendering only. -// -// Deprecated: This option will be removed in a future version of this package. -func SyncScrollArea(lines []string, topBoundary int, bottomBoundary int) Cmd { - return func() Msg { - return syncScrollAreaMsg{ - lines: lines, - topBoundary: topBoundary, - bottomBoundary: bottomBoundary, - } - } -} - -type clearScrollAreaMsg struct{} - -// ClearScrollArea deallocates the scrollable region and returns the control of -// those lines to the main rendering routine. -// -// For high-performance, scroll-based rendering only. -// -// Deprecated: This option will be removed in a future version of this package. -func ClearScrollArea() Msg { - return clearScrollAreaMsg{} -} - -type scrollUpMsg struct { - lines []string - topBoundary int - bottomBoundary int -} - -// ScrollUp adds lines to the top of the scrollable region, pushing existing -// lines below down. Lines that are pushed out the scrollable region disappear -// from view. -// -// For high-performance, scroll-based rendering only. -// -// Deprecated: This option will be removed in a future version of this package. -func ScrollUp(newLines []string, topBoundary, bottomBoundary int) Cmd { - return func() Msg { - return scrollUpMsg{ - lines: newLines, - topBoundary: topBoundary, - bottomBoundary: bottomBoundary, - } - } -} - -type scrollDownMsg struct { - lines []string - topBoundary int - bottomBoundary int -} - -// ScrollDown adds lines to the bottom of the scrollable region, pushing -// existing lines above up. Lines that are pushed out of the scrollable region -// disappear from view. -// -// For high-performance, scroll-based rendering only. -// -// Deprecated: This option will be removed in a future version of this package. -func ScrollDown(newLines []string, topBoundary, bottomBoundary int) Cmd { - return func() Msg { - return scrollDownMsg{ - lines: newLines, - topBoundary: topBoundary, - bottomBoundary: bottomBoundary, - } - } -} - -type printLineMessage struct { - messageBody string -} - -// Println prints above the Program. This output is unmanaged by the program and -// will persist across renders by the Program. -// -// Unlike fmt.Println (but similar to log.Println) the message will be print on -// its own line. -// -// If the altscreen is active no output will be printed. -func Println(args ...interface{}) Cmd { - return func() Msg { - return printLineMessage{ - messageBody: fmt.Sprint(args...), - } - } -} - -// Printf prints above the Program. It takes a format template followed by -// values similar to fmt.Printf. This output is unmanaged by the program and -// will persist across renders by the Program. -// -// Unlike fmt.Printf (but similar to log.Printf) the message will be print on -// its own line. -// -// If the altscreen is active no output will be printed. -func Printf(template string, args ...interface{}) Cmd { - return func() Msg { - return printLineMessage{ - messageBody: fmt.Sprintf(template, args...), - } - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/tea.go b/vendor/github.com/charmbracelet/bubbletea/tea.go deleted file mode 100644 index 0bc915e5..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/tea.go +++ /dev/null @@ -1,841 +0,0 @@ -// Package tea provides a framework for building rich terminal user interfaces -// based on the paradigms of The Elm Architecture. It's well-suited for simple -// and complex terminal applications, either inline, full-window, or a mix of -// both. It's been battle-tested in several large projects and is -// production-ready. -// -// A tutorial is available at https://github.com/charmbracelet/bubbletea/tree/master/tutorials -// -// Example programs can be found at https://github.com/charmbracelet/bubbletea/tree/master/examples -package tea - -import ( - "context" - "errors" - "fmt" - "io" - "os" - "os/signal" - "runtime" - "runtime/debug" - "sync" - "sync/atomic" - "syscall" - - "github.com/charmbracelet/x/term" - "github.com/muesli/cancelreader" - "golang.org/x/sync/errgroup" -) - -// ErrProgramKilled is returned by [Program.Run] when the program gets killed. -var ErrProgramKilled = errors.New("program was killed") - -// ErrInterrupted is returned by [Program.Run] when the program get a SIGINT -// signal, or when it receives a [InterruptMsg]. -var ErrInterrupted = errors.New("program was interrupted") - -// Msg contain data from the result of a IO operation. Msgs trigger the update -// function and, henceforth, the UI. -type Msg interface{} - -// Model contains the program's state as well as its core functions. -type Model interface { - // Init is the first function that will be called. It returns an optional - // initial command. To not perform an initial command return nil. - Init() Cmd - - // Update is called when a message is received. Use it to inspect messages - // and, in response, update the model and/or send a command. - Update(Msg) (Model, Cmd) - - // View renders the program's UI, which is just a string. The view is - // rendered after every Update. - View() string -} - -// Cmd is an IO operation that returns a message when it's complete. If it's -// nil it's considered a no-op. Use it for things like HTTP requests, timers, -// saving and loading from disk, and so on. -// -// Note that there's almost never a reason to use a command to send a message -// to another part of your program. That can almost always be done in the -// update function. -type Cmd func() Msg - -type inputType int - -const ( - defaultInput inputType = iota - ttyInput - customInput -) - -// String implements the stringer interface for [inputType]. It is inteded to -// be used in testing. -func (i inputType) String() string { - return [...]string{ - "default input", - "tty input", - "custom input", - }[i] -} - -// Options to customize the program during its initialization. These are -// generally set with ProgramOptions. -// -// The options here are treated as bits. -type startupOptions int16 - -func (s startupOptions) has(option startupOptions) bool { - return s&option != 0 -} - -const ( - withAltScreen startupOptions = 1 << iota - withMouseCellMotion - withMouseAllMotion - withANSICompressor - withoutSignalHandler - // Catching panics is incredibly useful for restoring the terminal to a - // usable state after a panic occurs. When this is set, Bubble Tea will - // recover from panics, print the stack trace, and disable raw mode. This - // feature is on by default. - withoutCatchPanics - withoutBracketedPaste - withReportFocus -) - -// channelHandlers manages the series of channels returned by various processes. -// It allows us to wait for those processes to terminate before exiting the -// program. -type channelHandlers []chan struct{} - -// Adds a channel to the list of handlers. We wait for all handlers to terminate -// gracefully on shutdown. -func (h *channelHandlers) add(ch chan struct{}) { - *h = append(*h, ch) -} - -// shutdown waits for all handlers to terminate. -func (h channelHandlers) shutdown() { - var wg sync.WaitGroup - for _, ch := range h { - wg.Add(1) - go func(ch chan struct{}) { - <-ch - wg.Done() - }(ch) - } - wg.Wait() -} - -// Program is a terminal user interface. -type Program struct { - initialModel Model - - // handlers is a list of channels that need to be waited on before the - // program can exit. - handlers channelHandlers - - // Configuration options that will set as the program is initializing, - // treated as bits. These options can be set via various ProgramOptions. - startupOptions startupOptions - - // startupTitle is the title that will be set on the terminal when the - // program starts. - startupTitle string - - inputType inputType - - ctx context.Context - cancel context.CancelFunc - - msgs chan Msg - errs chan error - finished chan struct{} - - // where to send output, this will usually be os.Stdout. - output io.Writer - // ttyOutput is null if output is not a TTY. - ttyOutput term.File - previousOutputState *term.State - renderer renderer - - // the environment variables for the program, defaults to os.Environ(). - environ []string - - // where to read inputs from, this will usually be os.Stdin. - input io.Reader - // ttyInput is null if input is not a TTY. - ttyInput term.File - previousTtyInputState *term.State - cancelReader cancelreader.CancelReader - readLoopDone chan struct{} - - // was the altscreen active before releasing the terminal? - altScreenWasActive bool - ignoreSignals uint32 - - bpWasActive bool // was the bracketed paste mode active before releasing the terminal? - reportFocus bool // was focus reporting active before releasing the terminal? - - filter func(Model, Msg) Msg - - // fps is the frames per second we should set on the renderer, if - // applicable, - fps int - - // mouseMode is true if the program should enable mouse mode on Windows. - mouseMode bool -} - -// Quit is a special command that tells the Bubble Tea program to exit. -func Quit() Msg { - return QuitMsg{} -} - -// QuitMsg signals that the program should quit. You can send a [QuitMsg] with -// [Quit]. -type QuitMsg struct{} - -// Suspend is a special command that tells the Bubble Tea program to suspend. -func Suspend() Msg { - return SuspendMsg{} -} - -// SuspendMsg signals the program should suspend. -// This usually happens when ctrl+z is pressed on common programs, but since -// bubbletea puts the terminal in raw mode, we need to handle it in a -// per-program basis. -// -// You can send this message with [Suspend()]. -type SuspendMsg struct{} - -// ResumeMsg can be listen to to do something once a program is resumed back -// from a suspend state. -type ResumeMsg struct{} - -// InterruptMsg signals the program should suspend. -// This usually happens when ctrl+c is pressed on common programs, but since -// bubbletea puts the terminal in raw mode, we need to handle it in a -// per-program basis. -// -// You can send this message with [Interrupt()]. -type InterruptMsg struct{} - -// Interrupt is a special command that tells the Bubble Tea program to -// interrupt. -func Interrupt() Msg { - return InterruptMsg{} -} - -// NewProgram creates a new Program. -func NewProgram(model Model, opts ...ProgramOption) *Program { - p := &Program{ - initialModel: model, - msgs: make(chan Msg), - } - - // Apply all options to the program. - for _, opt := range opts { - opt(p) - } - - // A context can be provided with a ProgramOption, but if none was provided - // we'll use the default background context. - if p.ctx == nil { - p.ctx = context.Background() - } - // Initialize context and teardown channel. - p.ctx, p.cancel = context.WithCancel(p.ctx) - - // if no output was set, set it to stdout - if p.output == nil { - p.output = os.Stdout - } - - // if no environment was set, set it to os.Environ() - if p.environ == nil { - p.environ = os.Environ() - } - - return p -} - -func (p *Program) handleSignals() chan struct{} { - ch := make(chan struct{}) - - // Listen for SIGINT and SIGTERM. - // - // In most cases ^C will not send an interrupt because the terminal will be - // in raw mode and ^C will be captured as a keystroke and sent along to - // Program.Update as a KeyMsg. When input is not a TTY, however, ^C will be - // caught here. - // - // SIGTERM is sent by unix utilities (like kill) to terminate a process. - go func() { - sig := make(chan os.Signal, 1) - signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) - defer func() { - signal.Stop(sig) - close(ch) - }() - - for { - select { - case <-p.ctx.Done(): - return - - case s := <-sig: - if atomic.LoadUint32(&p.ignoreSignals) == 0 { - switch s { - case syscall.SIGINT: - p.msgs <- InterruptMsg{} - default: - p.msgs <- QuitMsg{} - } - return - } - } - } - }() - - return ch -} - -// handleResize handles terminal resize events. -func (p *Program) handleResize() chan struct{} { - ch := make(chan struct{}) - - if p.ttyOutput != nil { - // Get the initial terminal size and send it to the program. - go p.checkResize() - - // Listen for window resizes. - go p.listenForResize(ch) - } else { - close(ch) - } - - return ch -} - -// handleCommands runs commands in a goroutine and sends the result to the -// program's message channel. -func (p *Program) handleCommands(cmds chan Cmd) chan struct{} { - ch := make(chan struct{}) - - go func() { - defer close(ch) - - for { - select { - case <-p.ctx.Done(): - return - - case cmd := <-cmds: - if cmd == nil { - continue - } - - // Don't wait on these goroutines, otherwise the shutdown - // latency would get too large as a Cmd can run for some time - // (e.g. tick commands that sleep for half a second). It's not - // possible to cancel them so we'll have to leak the goroutine - // until Cmd returns. - go func() { - // Recover from panics. - if !p.startupOptions.has(withoutCatchPanics) { - defer p.recoverFromPanic() - } - - msg := cmd() // this can be long. - p.Send(msg) - }() - } - } - }() - - return ch -} - -func (p *Program) disableMouse() { - p.renderer.disableMouseCellMotion() - p.renderer.disableMouseAllMotion() - p.renderer.disableMouseSGRMode() -} - -// eventLoop is the central message loop. It receives and handles the default -// Bubble Tea messages, update the model and triggers redraws. -func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { - for { - select { - case <-p.ctx.Done(): - return model, nil - - case err := <-p.errs: - return model, err - - case msg := <-p.msgs: - // Filter messages. - if p.filter != nil { - msg = p.filter(model, msg) - } - if msg == nil { - continue - } - - // Handle special internal messages. - switch msg := msg.(type) { - case QuitMsg: - return model, nil - - case InterruptMsg: - return model, ErrInterrupted - - case SuspendMsg: - if suspendSupported { - p.suspend() - } - - case clearScreenMsg: - p.renderer.clearScreen() - - case enterAltScreenMsg: - p.renderer.enterAltScreen() - - case exitAltScreenMsg: - p.renderer.exitAltScreen() - - case enableMouseCellMotionMsg, enableMouseAllMotionMsg: - switch msg.(type) { - case enableMouseCellMotionMsg: - p.renderer.enableMouseCellMotion() - case enableMouseAllMotionMsg: - p.renderer.enableMouseAllMotion() - } - // mouse mode (1006) is a no-op if the terminal doesn't support it. - p.renderer.enableMouseSGRMode() - - // XXX: This is used to enable mouse mode on Windows. We need - // to reinitialize the cancel reader to get the mouse events to - // work. - if runtime.GOOS == "windows" && !p.mouseMode { - p.mouseMode = true - p.initCancelReader(true) //nolint:errcheck - } - - case disableMouseMsg: - p.disableMouse() - - // XXX: On Windows, mouse mode is enabled on the input reader - // level. We need to instruct the input reader to stop reading - // mouse events. - if runtime.GOOS == "windows" && p.mouseMode { - p.mouseMode = false - p.initCancelReader(true) //nolint:errcheck - } - - case showCursorMsg: - p.renderer.showCursor() - - case hideCursorMsg: - p.renderer.hideCursor() - - case enableBracketedPasteMsg: - p.renderer.enableBracketedPaste() - - case disableBracketedPasteMsg: - p.renderer.disableBracketedPaste() - - case enableReportFocusMsg: - p.renderer.enableReportFocus() - - case disableReportFocusMsg: - p.renderer.disableReportFocus() - - case execMsg: - // NB: this blocks. - p.exec(msg.cmd, msg.fn) - - case BatchMsg: - for _, cmd := range msg { - cmds <- cmd - } - continue - - case sequenceMsg: - go func() { - // Execute commands one at a time, in order. - for _, cmd := range msg { - if cmd == nil { - continue - } - - msg := cmd() - if batchMsg, ok := msg.(BatchMsg); ok { - g, _ := errgroup.WithContext(p.ctx) - for _, cmd := range batchMsg { - cmd := cmd - g.Go(func() error { - p.Send(cmd()) - return nil - }) - } - - //nolint:errcheck - g.Wait() // wait for all commands from batch msg to finish - continue - } - - p.Send(msg) - } - }() - - case setWindowTitleMsg: - p.SetWindowTitle(string(msg)) - - case windowSizeMsg: - go p.checkResize() - } - - // Process internal messages for the renderer. - if r, ok := p.renderer.(*standardRenderer); ok { - r.handleMessages(msg) - } - - var cmd Cmd - model, cmd = model.Update(msg) // run update - cmds <- cmd // process command (if any) - p.renderer.write(model.View()) // send view to renderer - } - } -} - -// Run initializes the program and runs its event loops, blocking until it gets -// terminated by either [Program.Quit], [Program.Kill], or its signal handler. -// Returns the final model. -func (p *Program) Run() (Model, error) { - p.handlers = channelHandlers{} - cmds := make(chan Cmd) - p.errs = make(chan error) - p.finished = make(chan struct{}, 1) - - defer p.cancel() - - switch p.inputType { - case defaultInput: - p.input = os.Stdin - - // The user has not set a custom input, so we need to check whether or - // not standard input is a terminal. If it's not, we open a new TTY for - // input. This will allow things to "just work" in cases where data was - // piped in or redirected to the application. - // - // To disable input entirely pass nil to the [WithInput] program option. - f, isFile := p.input.(term.File) - if !isFile { - break - } - if term.IsTerminal(f.Fd()) { - break - } - - f, err := openInputTTY() - if err != nil { - return p.initialModel, err - } - defer f.Close() //nolint:errcheck - p.input = f - - case ttyInput: - // Open a new TTY, by request - f, err := openInputTTY() - if err != nil { - return p.initialModel, err - } - defer f.Close() //nolint:errcheck - p.input = f - - case customInput: - // (There is nothing extra to do.) - } - - // Handle signals. - if !p.startupOptions.has(withoutSignalHandler) { - p.handlers.add(p.handleSignals()) - } - - // Recover from panics. - if !p.startupOptions.has(withoutCatchPanics) { - defer p.recoverFromPanic() - } - - // If no renderer is set use the standard one. - if p.renderer == nil { - p.renderer = newRenderer(p.output, p.startupOptions.has(withANSICompressor), p.fps) - } - - // Check if output is a TTY before entering raw mode, hiding the cursor and - // so on. - if err := p.initTerminal(); err != nil { - return p.initialModel, err - } - - // Honor program startup options. - if p.startupTitle != "" { - p.renderer.setWindowTitle(p.startupTitle) - } - if p.startupOptions&withAltScreen != 0 { - p.renderer.enterAltScreen() - } - if p.startupOptions&withoutBracketedPaste == 0 { - p.renderer.enableBracketedPaste() - } - if p.startupOptions&withMouseCellMotion != 0 { - p.renderer.enableMouseCellMotion() - p.renderer.enableMouseSGRMode() - } else if p.startupOptions&withMouseAllMotion != 0 { - p.renderer.enableMouseAllMotion() - p.renderer.enableMouseSGRMode() - } - - // XXX: Should we enable mouse mode on Windows? - // This needs to happen before initializing the cancel and input reader. - p.mouseMode = p.startupOptions&withMouseCellMotion != 0 || p.startupOptions&withMouseAllMotion != 0 - - if p.startupOptions&withReportFocus != 0 { - p.renderer.enableReportFocus() - } - - // Start the renderer. - p.renderer.start() - - // Initialize the program. - model := p.initialModel - if initCmd := model.Init(); initCmd != nil { - ch := make(chan struct{}) - p.handlers.add(ch) - - go func() { - defer close(ch) - - select { - case cmds <- initCmd: - case <-p.ctx.Done(): - } - }() - } - - // Render the initial view. - p.renderer.write(model.View()) - - // Subscribe to user input. - if p.input != nil { - if err := p.initCancelReader(false); err != nil { - return model, err - } - } - - // Handle resize events. - p.handlers.add(p.handleResize()) - - // Process commands. - p.handlers.add(p.handleCommands(cmds)) - - // Run event loop, handle updates and draw. - model, err := p.eventLoop(model, cmds) - killed := p.ctx.Err() != nil || err != nil - if killed && err == nil { - err = fmt.Errorf("%w: %s", ErrProgramKilled, p.ctx.Err()) - } - if err == nil { - // Ensure we rendered the final state of the model. - p.renderer.write(model.View()) - } - - // Restore terminal state. - p.shutdown(killed) - - return model, err -} - -// StartReturningModel initializes the program and runs its event loops, -// blocking until it gets terminated by either [Program.Quit], [Program.Kill], -// or its signal handler. Returns the final model. -// -// Deprecated: please use [Program.Run] instead. -func (p *Program) StartReturningModel() (Model, error) { - return p.Run() -} - -// Start initializes the program and runs its event loops, blocking until it -// gets terminated by either [Program.Quit], [Program.Kill], or its signal -// handler. -// -// Deprecated: please use [Program.Run] instead. -func (p *Program) Start() error { - _, err := p.Run() - return err -} - -// Send sends a message to the main update function, effectively allowing -// messages to be injected from outside the program for interoperability -// purposes. -// -// If the program hasn't started yet this will be a blocking operation. -// If the program has already been terminated this will be a no-op, so it's safe -// to send messages after the program has exited. -func (p *Program) Send(msg Msg) { - select { - case <-p.ctx.Done(): - case p.msgs <- msg: - } -} - -// Quit is a convenience function for quitting Bubble Tea programs. Use it -// when you need to shut down a Bubble Tea program from the outside. -// -// If you wish to quit from within a Bubble Tea program use the Quit command. -// -// If the program is not running this will be a no-op, so it's safe to call -// if the program is unstarted or has already exited. -func (p *Program) Quit() { - p.Send(Quit()) -} - -// Kill stops the program immediately and restores the former terminal state. -// The final render that you would normally see when quitting will be skipped. -// [program.Run] returns a [ErrProgramKilled] error. -func (p *Program) Kill() { - p.shutdown(true) -} - -// Wait waits/blocks until the underlying Program finished shutting down. -func (p *Program) Wait() { - <-p.finished -} - -// shutdown performs operations to free up resources and restore the terminal -// to its original state. -func (p *Program) shutdown(kill bool) { - p.cancel() - - // Wait for all handlers to finish. - p.handlers.shutdown() - - // Check if the cancel reader has been setup before waiting and closing. - if p.cancelReader != nil { - // Wait for input loop to finish. - if p.cancelReader.Cancel() { - if !kill { - p.waitForReadLoop() - } - } - _ = p.cancelReader.Close() - } - - if p.renderer != nil { - if kill { - p.renderer.kill() - } else { - p.renderer.stop() - } - } - - _ = p.restoreTerminalState() - if !kill { - p.finished <- struct{}{} - } -} - -// recoverFromPanic recovers from a panic, prints the stack trace, and restores -// the terminal to a usable state. -func (p *Program) recoverFromPanic() { - if r := recover(); r != nil { - p.shutdown(true) - fmt.Printf("Caught panic:\n\n%s\n\nRestoring terminal...\n\n", r) - debug.PrintStack() - } -} - -// ReleaseTerminal restores the original terminal state and cancels the input -// reader. You can return control to the Program with RestoreTerminal. -func (p *Program) ReleaseTerminal() error { - atomic.StoreUint32(&p.ignoreSignals, 1) - if p.cancelReader != nil { - p.cancelReader.Cancel() - } - - p.waitForReadLoop() - - if p.renderer != nil { - p.renderer.stop() - p.altScreenWasActive = p.renderer.altScreen() - p.bpWasActive = p.renderer.bracketedPasteActive() - p.reportFocus = p.renderer.reportFocus() - } - - return p.restoreTerminalState() -} - -// RestoreTerminal reinitializes the Program's input reader, restores the -// terminal to the former state when the program was running, and repaints. -// Use it to reinitialize a Program after running ReleaseTerminal. -func (p *Program) RestoreTerminal() error { - atomic.StoreUint32(&p.ignoreSignals, 0) - - if err := p.initTerminal(); err != nil { - return err - } - if err := p.initCancelReader(false); err != nil { - return err - } - if p.altScreenWasActive { - p.renderer.enterAltScreen() - } else { - // entering alt screen already causes a repaint. - go p.Send(repaintMsg{}) - } - if p.renderer != nil { - p.renderer.start() - } - if p.bpWasActive { - p.renderer.enableBracketedPaste() - } - if p.reportFocus { - p.renderer.enableReportFocus() - } - - // If the output is a terminal, it may have been resized while another - // process was at the foreground, in which case we may not have received - // SIGWINCH. Detect any size change now and propagate the new size as - // needed. - go p.checkResize() - - return nil -} - -// Println prints above the Program. This output is unmanaged by the program -// and will persist across renders by the Program. -// -// If the altscreen is active no output will be printed. -func (p *Program) Println(args ...interface{}) { - p.msgs <- printLineMessage{ - messageBody: fmt.Sprint(args...), - } -} - -// Printf prints above the Program. It takes a format template followed by -// values similar to fmt.Printf. This output is unmanaged by the program and -// will persist across renders by the Program. -// -// Unlike fmt.Printf (but similar to log.Printf) the message will be print on -// its own line. -// -// If the altscreen is active no output will be printed. -func (p *Program) Printf(template string, args ...interface{}) { - p.msgs <- printLineMessage{ - messageBody: fmt.Sprintf(template, args...), - } -} diff --git a/vendor/github.com/charmbracelet/bubbletea/tea_init.go b/vendor/github.com/charmbracelet/bubbletea/tea_init.go deleted file mode 100644 index 19b6cc39..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/tea_init.go +++ /dev/null @@ -1,22 +0,0 @@ -package tea - -import ( - "github.com/charmbracelet/lipgloss" -) - -func init() { - // XXX: This is a workaround to make assure that Lip Gloss and Termenv - // query the terminal before any Bubble Tea Program runs and acquires the - // terminal. Without this, Programs that use Lip Gloss/Termenv might hang - // while waiting for a a [termenv.OSCTimeout] while querying the terminal - // for its background/foreground colors. - // - // This happens because Bubble Tea acquires the terminal before termenv - // reads any responses. - // - // Note that this will only affect programs running on the default IO i.e. - // [os.Stdout] and [os.Stdin]. - // - // This workaround will be removed in v2. - _ = lipgloss.HasDarkBackground() -} diff --git a/vendor/github.com/charmbracelet/bubbletea/tty.go b/vendor/github.com/charmbracelet/bubbletea/tty.go deleted file mode 100644 index 9490faca..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/tty.go +++ /dev/null @@ -1,141 +0,0 @@ -package tea - -import ( - "errors" - "fmt" - "io" - "time" - - "github.com/charmbracelet/x/term" - "github.com/muesli/cancelreader" -) - -func (p *Program) suspend() { - if err := p.ReleaseTerminal(); err != nil { - // If we can't release input, abort. - return - } - - suspendProcess() - - _ = p.RestoreTerminal() - go p.Send(ResumeMsg{}) -} - -func (p *Program) initTerminal() error { - if _, ok := p.renderer.(*nilRenderer); ok { - // No need to initialize the terminal if we're not rendering - return nil - } - - if err := p.initInput(); err != nil { - return err - } - - p.renderer.hideCursor() - return nil -} - -// restoreTerminalState restores the terminal to the state prior to running the -// Bubble Tea program. -func (p *Program) restoreTerminalState() error { - if p.renderer != nil { - p.renderer.disableBracketedPaste() - p.renderer.showCursor() - p.disableMouse() - - if p.renderer.reportFocus() { - p.renderer.disableReportFocus() - } - - if p.renderer.altScreen() { - p.renderer.exitAltScreen() - - // give the terminal a moment to catch up - time.Sleep(time.Millisecond * 10) //nolint:gomnd - } - } - - return p.restoreInput() -} - -// restoreInput restores the tty input to its original state. -func (p *Program) restoreInput() error { - if p.ttyInput != nil && p.previousTtyInputState != nil { - if err := term.Restore(p.ttyInput.Fd(), p.previousTtyInputState); err != nil { - return fmt.Errorf("error restoring console: %w", err) - } - } - if p.ttyOutput != nil && p.previousOutputState != nil { - if err := term.Restore(p.ttyOutput.Fd(), p.previousOutputState); err != nil { - return fmt.Errorf("error restoring console: %w", err) - } - } - return nil -} - -// initCancelReader (re)commences reading inputs. -func (p *Program) initCancelReader(cancel bool) error { - if cancel && p.cancelReader != nil { - p.cancelReader.Cancel() - p.waitForReadLoop() - } - - var err error - p.cancelReader, err = newInputReader(p.input, p.mouseMode) - if err != nil { - return fmt.Errorf("error creating cancelreader: %w", err) - } - - p.readLoopDone = make(chan struct{}) - go p.readLoop() - - return nil -} - -func (p *Program) readLoop() { - defer close(p.readLoopDone) - - err := readInputs(p.ctx, p.msgs, p.cancelReader) - if !errors.Is(err, io.EOF) && !errors.Is(err, cancelreader.ErrCanceled) { - select { - case <-p.ctx.Done(): - case p.errs <- err: - } - } -} - -// waitForReadLoop waits for the cancelReader to finish its read loop. -func (p *Program) waitForReadLoop() { - select { - case <-p.readLoopDone: - case <-time.After(500 * time.Millisecond): //nolint:gomnd - // The read loop hangs, which means the input - // cancelReader's cancel function has returned true even - // though it was not able to cancel the read. - } -} - -// checkResize detects the current size of the output and informs the program -// via a WindowSizeMsg. -func (p *Program) checkResize() { - if p.ttyOutput == nil { - // can't query window size - return - } - - w, h, err := term.GetSize(p.ttyOutput.Fd()) - if err != nil { - select { - case <-p.ctx.Done(): - case p.errs <- err: - } - - return - } - - p.Send(WindowSizeMsg{ - Width: w, - Height: h, - }) -} diff --git a/vendor/github.com/charmbracelet/bubbletea/tty_unix.go b/vendor/github.com/charmbracelet/bubbletea/tty_unix.go deleted file mode 100644 index 5cbb4fe1..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/tty_unix.go +++ /dev/null @@ -1,49 +0,0 @@ -//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix || zos -// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix zos - -package tea - -import ( - "fmt" - "os" - "os/signal" - "syscall" - - "github.com/charmbracelet/x/term" -) - -func (p *Program) initInput() (err error) { - // Check if input is a terminal - if f, ok := p.input.(term.File); ok && term.IsTerminal(f.Fd()) { - p.ttyInput = f - p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd()) - if err != nil { - return fmt.Errorf("error entering raw mode: %w", err) - } - } - - if f, ok := p.output.(term.File); ok && term.IsTerminal(f.Fd()) { - p.ttyOutput = f - } - - return nil -} - -func openInputTTY() (*os.File, error) { - f, err := os.Open("/dev/tty") - if err != nil { - return nil, fmt.Errorf("could not open a new TTY: %w", err) - } - return f, nil -} - -const suspendSupported = true - -// Send SIGTSTP to the entire process group. -func suspendProcess() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGCONT) - _ = syscall.Kill(0, syscall.SIGTSTP) - // blocks until a CONT happens... - <-c -} diff --git a/vendor/github.com/charmbracelet/bubbletea/tty_windows.go b/vendor/github.com/charmbracelet/bubbletea/tty_windows.go deleted file mode 100644 index a3a2525b..00000000 --- a/vendor/github.com/charmbracelet/bubbletea/tty_windows.go +++ /dev/null @@ -1,68 +0,0 @@ -//go:build windows -// +build windows - -package tea - -import ( - "fmt" - "os" - - "github.com/charmbracelet/x/term" - "golang.org/x/sys/windows" -) - -func (p *Program) initInput() (err error) { - // Save stdin state and enable VT input - // We also need to enable VT - // input here. - if f, ok := p.input.(term.File); ok && term.IsTerminal(f.Fd()) { - p.ttyInput = f - p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd()) - if err != nil { - return err - } - - // Enable VT input - var mode uint32 - if err := windows.GetConsoleMode(windows.Handle(p.ttyInput.Fd()), &mode); err != nil { - return fmt.Errorf("error getting console mode: %w", err) - } - - if err := windows.SetConsoleMode(windows.Handle(p.ttyInput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil { - return fmt.Errorf("error setting console mode: %w", err) - } - } - - // Save output screen buffer state and enable VT processing. - if f, ok := p.output.(term.File); ok && term.IsTerminal(f.Fd()) { - p.ttyOutput = f - p.previousOutputState, err = term.GetState(f.Fd()) - if err != nil { - return err - } - - var mode uint32 - if err := windows.GetConsoleMode(windows.Handle(p.ttyOutput.Fd()), &mode); err != nil { - return fmt.Errorf("error getting console mode: %w", err) - } - - if err := windows.SetConsoleMode(windows.Handle(p.ttyOutput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil { - return fmt.Errorf("error setting console mode: %w", err) - } - } - - return -} - -// Open the Windows equivalent of a TTY. -func openInputTTY() (*os.File, error) { - f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644) - if err != nil { - return nil, err - } - return f, nil -} - -const suspendSupported = false - -func suspendProcess() {} diff --git a/vendor/github.com/charmbracelet/glamour/.editorconfig b/vendor/github.com/charmbracelet/glamour/.editorconfig deleted file mode 100644 index 5de2df8c..00000000 --- a/vendor/github.com/charmbracelet/glamour/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# https://editorconfig.org/ - -root = true - -[*] -charset = utf-8 -insert_final_newline = true -trim_trailing_whitespace = true -indent_style = space -indent_size = 2 - -[*.go] -indent_style = tab -indent_size = 8 - -[*.golden] -insert_final_newline = false -trim_trailing_whitespace = false diff --git a/vendor/github.com/charmbracelet/glamour/.gitattributes b/vendor/github.com/charmbracelet/glamour/.gitattributes deleted file mode 100644 index 68e84c9b..00000000 --- a/vendor/github.com/charmbracelet/glamour/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -*.golden linguist-generated=true -text -*.png filter=lfs diff=lfs merge=lfs -text diff --git a/vendor/github.com/charmbracelet/glamour/.gitignore b/vendor/github.com/charmbracelet/glamour/.gitignore deleted file mode 100644 index eafbdee6..00000000 --- a/vendor/github.com/charmbracelet/glamour/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -cmd/ -!*.test diff --git a/vendor/github.com/charmbracelet/glamour/.golangci.yml b/vendor/github.com/charmbracelet/glamour/.golangci.yml deleted file mode 100644 index 7c0a115e..00000000 --- a/vendor/github.com/charmbracelet/glamour/.golangci.yml +++ /dev/null @@ -1,49 +0,0 @@ -version: "2" -run: - tests: false -linters: - enable: - - bodyclose - - exhaustive - - goconst - - godot - - godox - - gomoddirectives - - goprintffuncname - - gosec - - misspell - - nakedret - - nestif - - nilerr - - noctx - - nolintlint - - prealloc - - revive - - rowserrcheck - - sqlclosecheck - - tparallel - - unconvert - - unparam - - whitespace - - wrapcheck - exclusions: - generated: lax - presets: - - common-false-positives - paths: - - third_party$ - - builtin$ - - examples$ -issues: - max-issues-per-linter: 0 - max-same-issues: 0 -formatters: - enable: - - gofumpt - - goimports - exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ diff --git a/vendor/github.com/charmbracelet/glamour/.goreleaser.yml b/vendor/github.com/charmbracelet/glamour/.goreleaser.yml deleted file mode 100644 index 40d9f298..00000000 --- a/vendor/github.com/charmbracelet/glamour/.goreleaser.yml +++ /dev/null @@ -1,6 +0,0 @@ -includes: - - from_url: - url: charmbracelet/meta/main/goreleaser-lib.yaml - -# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json - diff --git a/vendor/github.com/charmbracelet/glamour/CONTRIBUTING.md b/vendor/github.com/charmbracelet/glamour/CONTRIBUTING.md deleted file mode 100644 index 88e71e06..00000000 --- a/vendor/github.com/charmbracelet/glamour/CONTRIBUTING.md +++ /dev/null @@ -1,23 +0,0 @@ -# Contributing - -Contributions are welcome! - -Please submit a pull request for minor changes and submit issues for major changes for discussions. - -## Testing - -When providing a new feature or bug fix, please provide tests that demonstrate the issue along with your fix. - -### Golden Files - -If golden files need to be updated, you can do so with `-update`. - -Usage: `go test ./pkg/... -update`. - -## Themes - -New styles need to be implemented in `styles/.go`, and then `go generate -./...` will create the JSON files from it. - -You can look up all references of another theme (e.g. Dracula), and add your -theme accordingly. diff --git a/vendor/github.com/charmbracelet/glamour/LICENSE b/vendor/github.com/charmbracelet/glamour/LICENSE deleted file mode 100644 index e5a29162..00000000 --- a/vendor/github.com/charmbracelet/glamour/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019-2023 Charmbracelet, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/charmbracelet/glamour/README.md b/vendor/github.com/charmbracelet/glamour/README.md deleted file mode 100644 index db440e94..00000000 --- a/vendor/github.com/charmbracelet/glamour/README.md +++ /dev/null @@ -1,96 +0,0 @@ -# Glamour - -

- Glamour Title Treatment
- Latest Release - GoDoc - Build Status - Coverage Status - Go ReportCard -

- -Stylesheet-based markdown rendering for your CLI apps. - -Glamour example - -`glamour` lets you render [markdown](https://en.wikipedia.org/wiki/Markdown) -documents & templates on [ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code) -compatible terminals. You can create your own stylesheet or simply use one of -the stylish defaults. - -## Usage - -```go -import "github.com/charmbracelet/glamour" - -in := `# Hello World - -This is a simple example of Markdown rendering with Glamour! -Check out the [other examples](https://github.com/charmbracelet/glamour/tree/master/examples) too. - -Bye! -` - -out, err := glamour.Render(in, "dark") -fmt.Print(out) -``` - -Hello World example - -### Custom Renderer - -```go -import "github.com/charmbracelet/glamour" - -r, _ := glamour.NewTermRenderer( - // detect background color and pick either the default dark or light theme - glamour.WithAutoStyle(), - // wrap output at specific width (default is 80) - glamour.WithWordWrap(40), -) - -out, err := r.Render(in) -fmt.Print(out) -``` - -## Styles - -You can find all available default styles in our [gallery](https://github.com/charmbracelet/glamour/tree/master/styles/gallery). -Want to create your own style? [Learn how!](https://github.com/charmbracelet/glamour/tree/master/styles) - -There are a few options for using a custom style: - -1. Call `glamour.Render(inputText, "desiredStyle")` -1. Set the `GLAMOUR_STYLE` environment variable to your desired default style or a file location for a style and call `glamour.RenderWithEnvironmentConfig(inputText)` -1. Set the `GLAMOUR_STYLE` environment variable and pass `glamour.WithEnvironmentConfig()` to your custom renderer - -## Glamourous Projects - -Check out these projects, which use `glamour`: - -- [Glow](https://github.com/charmbracelet/glow), a markdown renderer for - the command-line. -- [GitHub CLI](https://github.com/cli/cli), GitHub’s official command line tool. -- [GitLab CLI](https://gitlab.com/gitlab-org/cli), GitLab's official command line tool. -- [Gitea CLI](https://gitea.com/gitea/tea), Gitea's official command line tool. -- [Meteor](https://github.com/odpf/meteor), an easy-to-use, plugin-driven metadata collection framework. - -## Feedback - -We’d love to hear your thoughts on this project. Feel free to drop us a note! - -- [Twitter](https://twitter.com/charmcli) -- [The Fediverse](https://mastodon.social/@charmcli) -- [Discord](https://charm.sh/chat) - -## License - -[MIT](https://github.com/charmbracelet/glamour/raw/master/LICENSE) - ---- - -Part of [Charm](https://charm.sh). - -The Charm logo - -Charm热爱开源 • Charm loves open source diff --git a/vendor/github.com/charmbracelet/glamour/Taskfile.yml b/vendor/github.com/charmbracelet/glamour/Taskfile.yml deleted file mode 100644 index 9019f78f..00000000 --- a/vendor/github.com/charmbracelet/glamour/Taskfile.yml +++ /dev/null @@ -1,25 +0,0 @@ -# https://taskfile.dev - -version: '3' - -tasks: - lint:all: - desc: Run all linters - cmds: - - task: lint - - task: lint:soft - - lint: - desc: Run base linters - cmds: - - golangci-lint run - - lint:soft: - desc: Run soft linters - cmds: - - golangci-lint run --config=.golangci-soft.yml - - test: - desc: Run tests - cmds: - - go test ./... {{.CLI_ARGS}} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/ansi.go b/vendor/github.com/charmbracelet/glamour/ansi/ansi.go deleted file mode 100644 index fba93c14..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/ansi.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package ansi handle conversion of markdown to pretty ANSI output on the -// terminal. -package ansi diff --git a/vendor/github.com/charmbracelet/glamour/ansi/baseelement.go b/vendor/github.com/charmbracelet/glamour/ansi/baseelement.go deleted file mode 100644 index 93c27b30..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/baseelement.go +++ /dev/null @@ -1,151 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "io" - "strings" - "text/template" - - "github.com/muesli/termenv" - "golang.org/x/text/cases" - "golang.org/x/text/language" -) - -// BaseElement renders a styled primitive element. -type BaseElement struct { - Token string - Prefix string - Suffix string - Style StylePrimitive -} - -func formatToken(format string, token string) (string, error) { - var b bytes.Buffer - - v := make(map[string]interface{}) - v["text"] = token - - tmpl, err := template.New(format).Funcs(TemplateFuncMap).Parse(format) - if err != nil { - return "", fmt.Errorf("glamour: error parsing template: %w", err) - } - - err = tmpl.Execute(&b, v) - return b.String(), err -} - -func renderText(w io.Writer, p termenv.Profile, rules StylePrimitive, s string) { - if len(s) == 0 { - return - } - - out := termenv.String(s) - if rules.Upper != nil && *rules.Upper { - out = termenv.String(cases.Upper(language.English).String(s)) - } - if rules.Lower != nil && *rules.Lower { - out = termenv.String(cases.Lower(language.English).String(s)) - } - if rules.Title != nil && *rules.Title { - out = termenv.String(cases.Title(language.English).String(s)) - } - if rules.Color != nil { - out = out.Foreground(p.Color(*rules.Color)) - } - if rules.BackgroundColor != nil { - out = out.Background(p.Color(*rules.BackgroundColor)) - } - if rules.Underline != nil && *rules.Underline { - out = out.Underline() - } - if rules.Bold != nil && *rules.Bold { - out = out.Bold() - } - if rules.Italic != nil && *rules.Italic { - out = out.Italic() - } - if rules.CrossedOut != nil && *rules.CrossedOut { - out = out.CrossOut() - } - if rules.Overlined != nil && *rules.Overlined { - out = out.Overline() - } - if rules.Inverse != nil && *rules.Inverse { - out = out.Reverse() - } - if rules.Blink != nil && *rules.Blink { - out = out.Blink() - } - - _, _ = io.WriteString(w, out.String()) -} - -// StyleOverrideRender renders a BaseElement with an overridden style. -func (e *BaseElement) StyleOverrideRender(w io.Writer, ctx RenderContext, style StylePrimitive) error { - bs := ctx.blockStack - st1 := cascadeStylePrimitives(bs.Current().Style.StylePrimitive, style) - st2 := cascadeStylePrimitives(bs.With(e.Style), style) - - return e.doRender(w, ctx.options.ColorProfile, st1, st2) -} - -// Render renders a BaseElement. -func (e *BaseElement) Render(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - st1 := bs.Current().Style.StylePrimitive - st2 := bs.With(e.Style) - return e.doRender(w, ctx.options.ColorProfile, st1, st2) -} - -func (e *BaseElement) doRender(w io.Writer, p termenv.Profile, st1, st2 StylePrimitive) error { - renderText(w, p, st1, e.Prefix) - defer func() { - renderText(w, p, st1, e.Suffix) - }() - - // render unstyled prefix/suffix - renderText(w, p, st1, st2.BlockPrefix) - defer func() { - renderText(w, p, st1, st2.BlockSuffix) - }() - - // render styled prefix/suffix - renderText(w, p, st2, st2.Prefix) - defer func() { - renderText(w, p, st2, st2.Suffix) - }() - - s := e.Token - if len(st2.Format) > 0 { - var err error - s, err = formatToken(st2.Format, s) - if err != nil { - return err - } - } - renderText(w, p, st2, escapeReplacer.Replace(s)) - return nil -} - -// https://www.markdownguide.org/basic-syntax/#characters-you-can-escape -var escapeReplacer = strings.NewReplacer( - "\\\\", "\\", - "\\`", "`", - "\\*", "*", - "\\_", "_", - "\\{", "{", - "\\}", "}", - "\\[", "[", - "\\]", "]", - "\\<", "<", - "\\>", ">", - "\\(", "(", - "\\)", ")", - "\\#", "#", - "\\+", "+", - "\\-", "-", - "\\.", ".", - "\\!", "!", - "\\|", "|", -) diff --git a/vendor/github.com/charmbracelet/glamour/ansi/blockelement.go b/vendor/github.com/charmbracelet/glamour/ansi/blockelement.go deleted file mode 100644 index 7fcf3990..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/blockelement.go +++ /dev/null @@ -1,65 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "io" - - "github.com/charmbracelet/x/ansi" -) - -// BlockElement provides a render buffer for children of a block element. -// After all children have been rendered into it, it applies indentation and -// margins around them and writes everything to the parent rendering buffer. -type BlockElement struct { - Block *bytes.Buffer - Style StyleBlock - Margin bool - Newline bool -} - -// Render renders a BlockElement. -func (e *BlockElement) Render(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - bs.Push(*e) - - renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, e.Style.BlockPrefix) - renderText(bs.Current().Block, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Style.Prefix) - return nil -} - -// Finish finishes rendering a BlockElement. -func (e *BlockElement) Finish(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - - if e.Margin { //nolint: nestif - s := ansi.Wordwrap( - bs.Current().Block.String(), - int(bs.Width(ctx)), //nolint: gosec - " ,.;-+|", - ) - - mw := NewMarginWriter(ctx, w, bs.Current().Style) - if _, err := io.WriteString(mw, s); err != nil { - return fmt.Errorf("glamour: error writing to writer: %w", err) - } - - if e.Newline { - if _, err := io.WriteString(mw, "\n"); err != nil { - return fmt.Errorf("glamour: error writing to writer: %w", err) - } - } - } else { - _, err := bs.Parent().Block.Write(bs.Current().Block.Bytes()) - if err != nil { - return fmt.Errorf("glamour: error writing to writer: %w", err) - } - } - - renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, e.Style.Suffix) - renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, e.Style.BlockSuffix) - - bs.Current().Block.Reset() - bs.Pop() - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/blockstack.go b/vendor/github.com/charmbracelet/glamour/ansi/blockstack.go deleted file mode 100644 index 8a5d77c7..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/blockstack.go +++ /dev/null @@ -1,95 +0,0 @@ -package ansi - -import ( - "bytes" -) - -// BlockStack is a stack of block elements, used to calculate the current -// indentation & margin level during the rendering process. -type BlockStack []BlockElement - -// Len returns the length of the stack. -func (s *BlockStack) Len() int { - return len(*s) -} - -// Push appends an item to the stack. -func (s *BlockStack) Push(e BlockElement) { - *s = append(*s, e) -} - -// Pop removes the last item on the stack. -func (s *BlockStack) Pop() { - stack := *s - if len(stack) == 0 { - return - } - - stack = stack[0 : len(stack)-1] - *s = stack -} - -// Indent returns the current indentation level of all elements in the stack. -func (s BlockStack) Indent() uint { - var i uint - - for _, v := range s { - if v.Style.Indent == nil { - continue - } - i += *v.Style.Indent - } - - return i -} - -// Margin returns the current margin level of all elements in the stack. -func (s BlockStack) Margin() uint { - var i uint - - for _, v := range s { - if v.Style.Margin == nil { - continue - } - i += *v.Style.Margin - } - - return i -} - -// Width returns the available rendering width. -func (s BlockStack) Width(ctx RenderContext) uint { - if s.Indent()+s.Margin()*2 > uint(ctx.options.WordWrap) { //nolint: gosec - return 0 - } - return uint(ctx.options.WordWrap) - s.Indent() - s.Margin()*2 //nolint: gosec -} - -// Parent returns the current BlockElement's parent. -func (s BlockStack) Parent() BlockElement { - if len(s) == 1 { - return BlockElement{ - Block: &bytes.Buffer{}, - } - } - - return s[len(s)-2] -} - -// Current returns the current BlockElement. -func (s BlockStack) Current() BlockElement { - if len(s) == 0 { - return BlockElement{ - Block: &bytes.Buffer{}, - } - } - - return s[len(s)-1] -} - -// With returns a StylePrimitive that inherits the current BlockElement's style. -func (s BlockStack) With(child StylePrimitive) StylePrimitive { - sb := StyleBlock{} - sb.StylePrimitive = child - return cascadeStyle(s.Current().Style, sb, false).StylePrimitive -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/codeblock.go b/vendor/github.com/charmbracelet/glamour/ansi/codeblock.go deleted file mode 100644 index 90976e56..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/codeblock.go +++ /dev/null @@ -1,152 +0,0 @@ -package ansi - -import ( - "fmt" - "io" - "sync" - - "github.com/alecthomas/chroma/v2" - "github.com/alecthomas/chroma/v2/quick" - "github.com/alecthomas/chroma/v2/styles" - "github.com/muesli/reflow/indent" - "github.com/muesli/termenv" -) - -const ( - // The chroma style theme name used for rendering. - chromaStyleTheme = "charm" - - // The chroma formatter name used for rendering. - chromaFormatter = "terminal256" -) - -// mutex for synchronizing access to the chroma style registry. -// Related https://github.com/alecthomas/chroma/pull/650 -var mutex = sync.Mutex{} - -// A CodeBlockElement is used to render code blocks. -type CodeBlockElement struct { - Code string - Language string -} - -func chromaStyle(style StylePrimitive) string { - var s string - - if style.Color != nil { - s = *style.Color - } - if style.BackgroundColor != nil { - if s != "" { - s += " " - } - s += "bg:" + *style.BackgroundColor - } - if style.Italic != nil && *style.Italic { - if s != "" { - s += " " - } - s += "italic" - } - if style.Bold != nil && *style.Bold { - if s != "" { - s += " " - } - s += "bold" - } - if style.Underline != nil && *style.Underline { - if s != "" { - s += " " - } - s += "underline" - } - - return s -} - -// Render renders a CodeBlockElement. -func (e *CodeBlockElement) Render(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - - var indentation uint - var margin uint - formatter := chromaFormatter - rules := ctx.options.Styles.CodeBlock - if rules.Indent != nil { - indentation = *rules.Indent - } - if rules.Margin != nil { - margin = *rules.Margin - } - if len(ctx.options.ChromaFormatter) > 0 { - formatter = ctx.options.ChromaFormatter - } - theme := rules.Theme - - if rules.Chroma != nil && ctx.options.ColorProfile != termenv.Ascii { - theme = chromaStyleTheme - mutex.Lock() - // Don't register the style if it's already registered. - _, ok := styles.Registry[theme] - if !ok { - styles.Register(chroma.MustNewStyle(theme, - chroma.StyleEntries{ - chroma.Text: chromaStyle(rules.Chroma.Text), - chroma.Error: chromaStyle(rules.Chroma.Error), - chroma.Comment: chromaStyle(rules.Chroma.Comment), - chroma.CommentPreproc: chromaStyle(rules.Chroma.CommentPreproc), - chroma.Keyword: chromaStyle(rules.Chroma.Keyword), - chroma.KeywordReserved: chromaStyle(rules.Chroma.KeywordReserved), - chroma.KeywordNamespace: chromaStyle(rules.Chroma.KeywordNamespace), - chroma.KeywordType: chromaStyle(rules.Chroma.KeywordType), - chroma.Operator: chromaStyle(rules.Chroma.Operator), - chroma.Punctuation: chromaStyle(rules.Chroma.Punctuation), - chroma.Name: chromaStyle(rules.Chroma.Name), - chroma.NameBuiltin: chromaStyle(rules.Chroma.NameBuiltin), - chroma.NameTag: chromaStyle(rules.Chroma.NameTag), - chroma.NameAttribute: chromaStyle(rules.Chroma.NameAttribute), - chroma.NameClass: chromaStyle(rules.Chroma.NameClass), - chroma.NameConstant: chromaStyle(rules.Chroma.NameConstant), - chroma.NameDecorator: chromaStyle(rules.Chroma.NameDecorator), - chroma.NameException: chromaStyle(rules.Chroma.NameException), - chroma.NameFunction: chromaStyle(rules.Chroma.NameFunction), - chroma.NameOther: chromaStyle(rules.Chroma.NameOther), - chroma.Literal: chromaStyle(rules.Chroma.Literal), - chroma.LiteralNumber: chromaStyle(rules.Chroma.LiteralNumber), - chroma.LiteralDate: chromaStyle(rules.Chroma.LiteralDate), - chroma.LiteralString: chromaStyle(rules.Chroma.LiteralString), - chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape), - chroma.GenericDeleted: chromaStyle(rules.Chroma.GenericDeleted), - chroma.GenericEmph: chromaStyle(rules.Chroma.GenericEmph), - chroma.GenericInserted: chromaStyle(rules.Chroma.GenericInserted), - chroma.GenericStrong: chromaStyle(rules.Chroma.GenericStrong), - chroma.GenericSubheading: chromaStyle(rules.Chroma.GenericSubheading), - chroma.Background: chromaStyle(rules.Chroma.Background), - })) - } - mutex.Unlock() - } - - iw := indent.NewWriterPipe(w, indentation+margin, func(_ io.Writer) { - renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, " ") - }) - - if len(theme) > 0 { - renderText(iw, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) - - err := quick.Highlight(iw, e.Code, e.Language, formatter, theme) - if err != nil { - return fmt.Errorf("glamour: error highlighting code: %w", err) - } - renderText(iw, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockSuffix) - return nil - } - - // fallback rendering - el := &BaseElement{ - Token: e.Code, - Style: rules.StylePrimitive, - } - - return el.Render(iw, ctx) -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/codespan.go b/vendor/github.com/charmbracelet/glamour/ansi/codespan.go deleted file mode 100644 index 66a4d493..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/codespan.go +++ /dev/null @@ -1,15 +0,0 @@ -package ansi - -import "io" - -// A CodeSpanElement is used to render codespan. -type CodeSpanElement struct { - Text string - Style StylePrimitive -} - -// Render renders a CodeSpanElement. -func (e *CodeSpanElement) Render(w io.Writer, ctx RenderContext) error { - renderText(w, ctx.options.ColorProfile, e.Style, e.Style.Prefix+e.Text+e.Style.Suffix) - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/context.go b/vendor/github.com/charmbracelet/glamour/ansi/context.go deleted file mode 100644 index ee3c2eb0..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/context.go +++ /dev/null @@ -1,38 +0,0 @@ -package ansi - -import ( - "html" - "strings" - - "github.com/microcosm-cc/bluemonday" -) - -// RenderContext holds the current rendering options and state. -type RenderContext struct { - options Options - - blockStack *BlockStack - table *TableElement - - stripper *bluemonday.Policy -} - -// NewRenderContext returns a new RenderContext. -func NewRenderContext(options Options) RenderContext { - return RenderContext{ - options: options, - blockStack: &BlockStack{}, - table: &TableElement{}, - stripper: bluemonday.StrictPolicy(), - } -} - -// SanitizeHTML sanitizes HTML content. -func (ctx RenderContext) SanitizeHTML(s string, trimSpaces bool) string { - s = ctx.stripper.Sanitize(s) - if trimSpaces { - s = strings.TrimSpace(s) - } - - return html.UnescapeString(s) -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/elements.go b/vendor/github.com/charmbracelet/glamour/ansi/elements.go deleted file mode 100644 index f8d0fef3..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/elements.go +++ /dev/null @@ -1,479 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "html" - "io" - "strings" - - "github.com/charmbracelet/glamour/internal/autolink" - east "github.com/yuin/goldmark-emoji/ast" - "github.com/yuin/goldmark/ast" - astext "github.com/yuin/goldmark/extension/ast" -) - -// ElementRenderer is called when entering a markdown node. -type ElementRenderer interface { - Render(w io.Writer, ctx RenderContext) error -} - -// StyleOverriderElementRenderer is called when entering a markdown node with a specific style. -type StyleOverriderElementRenderer interface { - StyleOverrideRender(w io.Writer, ctx RenderContext, style StylePrimitive) error -} - -// ElementFinisher is called when leaving a markdown node. -type ElementFinisher interface { - Finish(w io.Writer, ctx RenderContext) error -} - -// An Element is used to instruct the renderer how to handle individual markdown -// nodes. -type Element struct { - Entering string - Exiting string - Renderer ElementRenderer - Finisher ElementFinisher -} - -// NewElement returns the appropriate render Element for a given node. -func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element { - ctx := tr.context - - switch node.Kind() { - // Document - case ast.KindDocument: - e := &BlockElement{ - Block: &bytes.Buffer{}, - Style: ctx.options.Styles.Document, - Margin: true, - } - return Element{ - Renderer: e, - Finisher: e, - } - - // Heading - case ast.KindHeading: - n := node.(*ast.Heading) - he := &HeadingElement{ - Level: n.Level, - First: node.PreviousSibling() == nil, - } - return Element{ - Exiting: "", - Renderer: he, - Finisher: he, - } - - // Paragraph - case ast.KindParagraph: - if node.Parent() != nil { - kind := node.Parent().Kind() - if kind == ast.KindListItem { - return Element{} - } - } - return Element{ - Renderer: &ParagraphElement{ - First: node.PreviousSibling() == nil, - }, - Finisher: &ParagraphElement{}, - } - - // Blockquote - case ast.KindBlockquote: - e := &BlockElement{ - Block: &bytes.Buffer{}, - Style: cascadeStyle(ctx.blockStack.Current().Style, ctx.options.Styles.BlockQuote, false), - Margin: true, - } - return Element{ - Entering: "\n", - Renderer: e, - Finisher: e, - } - - // Lists - case ast.KindList: - s := ctx.options.Styles.List.StyleBlock - if s.Indent == nil { - var i uint - s.Indent = &i - } - n := node.Parent() - for n != nil { - if n.Kind() == ast.KindList { - i := ctx.options.Styles.List.LevelIndent - s.Indent = &i - break - } - n = n.Parent() - } - - e := &BlockElement{ - Block: &bytes.Buffer{}, - Style: cascadeStyle(ctx.blockStack.Current().Style, s, false), - Margin: true, - Newline: true, - } - return Element{ - Entering: "\n", - Renderer: e, - Finisher: e, - } - - case ast.KindListItem: - var l uint - var e uint - l = 1 - n := node - for n.PreviousSibling() != nil && (n.PreviousSibling().Kind() == ast.KindListItem) { - l++ - n = n.PreviousSibling() - } - if node.Parent().(*ast.List).IsOrdered() { - e = l - if node.Parent().(*ast.List).Start != 1 { - e += uint(node.Parent().(*ast.List).Start) - 1 //nolint: gosec - } - } - - post := "\n" - if (node.LastChild() != nil && node.LastChild().Kind() == ast.KindList) || - node.NextSibling() == nil { - post = "" - } - - if node.FirstChild() != nil && - node.FirstChild().FirstChild() != nil && - node.FirstChild().FirstChild().Kind() == astext.KindTaskCheckBox { - nc := node.FirstChild().FirstChild().(*astext.TaskCheckBox) - - return Element{ - Exiting: post, - Renderer: &TaskElement{ - Checked: nc.IsChecked, - }, - } - } - - return Element{ - Exiting: post, - Renderer: &ItemElement{ - IsOrdered: node.Parent().(*ast.List).IsOrdered(), - Enumeration: e, - }, - } - - // Text Elements - case ast.KindText: - n := node.(*ast.Text) - s := string(n.Segment.Value(source)) - - if n.HardLineBreak() || (n.SoftLineBreak()) { - s += "\n" - } - return Element{ - Renderer: &BaseElement{ - Token: html.UnescapeString(s), - Style: ctx.options.Styles.Text, - }, - } - - case ast.KindEmphasis: - n := node.(*ast.Emphasis) - var children []ElementRenderer - nn := n.FirstChild() - for nn != nil { - children = append(children, tr.NewElement(nn, source).Renderer) - nn = nn.NextSibling() - } - return Element{ - Renderer: &EmphasisElement{ - Level: n.Level, - Children: children, - }, - } - - case astext.KindStrikethrough: - n := node.(*astext.Strikethrough) - s := string(n.Text(source)) //nolint: staticcheck - style := ctx.options.Styles.Strikethrough - - return Element{ - Renderer: &BaseElement{ - Token: html.UnescapeString(s), - Style: style, - }, - } - - case ast.KindThematicBreak: - return Element{ - Entering: "", - Exiting: "", - Renderer: &BaseElement{ - Style: ctx.options.Styles.HorizontalRule, - }, - } - - // Links - case ast.KindLink: - n := node.(*ast.Link) - isFooterLinks := !ctx.options.InlineTableLinks && isInsideTable(node) - - var children []ElementRenderer - content, err := nodeContent(node, source) - - if isFooterLinks && err == nil { - text := string(content) - tl := tableLink{ - content: text, - href: string(n.Destination), - title: string(n.Title), - linkType: linkTypeRegular, - } - text = linkWithSuffix(tl, ctx.table.tableLinks) - children = []ElementRenderer{&BaseElement{Token: text}} - } else { - nn := n.FirstChild() - for nn != nil { - children = append(children, tr.NewElement(nn, source).Renderer) - nn = nn.NextSibling() - } - } - - return Element{ - Renderer: &LinkElement{ - BaseURL: ctx.options.BaseURL, - URL: string(n.Destination), - Children: children, - SkipHref: isFooterLinks, - }, - } - case ast.KindAutoLink: - n := node.(*ast.AutoLink) - u := string(n.URL(source)) - isFooterLinks := !ctx.options.InlineTableLinks && isInsideTable(node) - - var children []ElementRenderer - nn := n.FirstChild() - for nn != nil { - children = append(children, tr.NewElement(nn, source).Renderer) - nn = nn.NextSibling() - } - - if len(children) == 0 { - children = append(children, &BaseElement{Token: u}) - } - - if n.AutoLinkType == ast.AutoLinkEmail && !strings.HasPrefix(strings.ToLower(u), "mailto:") { - u = "mailto:" + u - } - - var renderer ElementRenderer - if isFooterLinks { - domain := linkDomain(u) - tl := tableLink{ - content: domain, - href: u, - linkType: linkTypeAuto, - } - if shortned, ok := autolink.Detect(u); ok { - tl.content = shortned - } - text := linkWithSuffix(tl, ctx.table.tableLinks) - - renderer = &LinkElement{ - Children: []ElementRenderer{&BaseElement{Token: text}}, - URL: u, - SkipHref: true, - } - } else { - renderer = &LinkElement{ - Children: children, - URL: u, - SkipText: n.AutoLinkType != ast.AutoLinkEmail, - } - } - return Element{Renderer: renderer} - - // Images - case ast.KindImage: - n := node.(*ast.Image) - text := string(n.Text(source)) //nolint: staticcheck - isFooterLinks := !ctx.options.InlineTableLinks && isInsideTable(node) - - if isFooterLinks { - if text == "" { - text = linkDomain(string(n.Destination)) - } - tl := tableLink{ - title: string(n.Title), - content: text, - href: string(n.Destination), - linkType: linkTypeImage, - } - text = linkWithSuffix(tl, ctx.table.tableImages) - } - - return Element{ - Renderer: &ImageElement{ - Text: text, - BaseURL: ctx.options.BaseURL, - URL: string(n.Destination), - TextOnly: isFooterLinks, - }, - } - - // Code - case ast.KindFencedCodeBlock: - n := node.(*ast.FencedCodeBlock) - l := n.Lines().Len() - s := "" - for i := 0; i < l; i++ { - line := n.Lines().At(i) - s += string(line.Value(source)) - } - return Element{ - Entering: "\n", - Renderer: &CodeBlockElement{ - Code: s, - Language: string(n.Language(source)), - }, - } - - case ast.KindCodeBlock: - n := node.(*ast.CodeBlock) - l := n.Lines().Len() - s := "" - for i := 0; i < l; i++ { - line := n.Lines().At(i) - s += string(line.Value(source)) - } - return Element{ - Entering: "\n", - Renderer: &CodeBlockElement{ - Code: s, - }, - } - - case ast.KindCodeSpan: - n := node.(*ast.CodeSpan) - s := string(n.Text(source)) //nolint: staticcheck - return Element{ - Renderer: &CodeSpanElement{ - Text: html.UnescapeString(s), - Style: cascadeStyle(ctx.blockStack.Current().Style, ctx.options.Styles.Code, false).StylePrimitive, - }, - } - - // Tables - case astext.KindTable: - table := node.(*astext.Table) - te := &TableElement{ - table: table, - source: source, - } - return Element{ - Entering: "\n", - Exiting: "\n", - Renderer: te, - Finisher: te, - } - - case astext.KindTableCell: - n := node.(*astext.TableCell) - var children []ElementRenderer - nn := n.FirstChild() - for nn != nil { - children = append(children, tr.NewElement(nn, source).Renderer) - nn = nn.NextSibling() - } - - r := &TableCellElement{ - Children: children, - Head: node.Parent().Kind() == astext.KindTableHeader, - } - return Element{ - Renderer: r, - } - - case astext.KindTableHeader: - return Element{ - Finisher: &TableHeadElement{}, - } - case astext.KindTableRow: - return Element{ - Finisher: &TableRowElement{}, - } - - // HTML Elements - case ast.KindHTMLBlock: - n := node.(*ast.HTMLBlock) - return Element{ - Renderer: &BaseElement{ - Token: ctx.SanitizeHTML(string(n.Text(source)), true), //nolint: staticcheck - Style: ctx.options.Styles.HTMLBlock.StylePrimitive, - }, - } - case ast.KindRawHTML: - n := node.(*ast.RawHTML) - return Element{ - Renderer: &BaseElement{ - Token: ctx.SanitizeHTML(string(n.Text(source)), true), //nolint: staticcheck - Style: ctx.options.Styles.HTMLSpan.StylePrimitive, - }, - } - - // Definition Lists - case astext.KindDefinitionList: - e := &BlockElement{ - Block: &bytes.Buffer{}, - Style: cascadeStyle(ctx.blockStack.Current().Style, ctx.options.Styles.DefinitionList, false), - Margin: true, - Newline: true, - } - return Element{ - Renderer: e, - Finisher: e, - } - - case astext.KindDefinitionTerm: - return Element{ - Entering: "\n", - Renderer: &BaseElement{ - Style: ctx.options.Styles.DefinitionTerm, - }, - } - - case astext.KindDefinitionDescription: - return Element{ - Exiting: "\n", - Renderer: &BaseElement{ - Style: ctx.options.Styles.DefinitionDescription, - }, - } - - // Handled by parents - case astext.KindTaskCheckBox: - // handled by KindListItem - return Element{} - case ast.KindTextBlock: - return Element{} - - case east.KindEmoji: - n := node.(*east.Emoji) - return Element{ - Renderer: &BaseElement{ - Token: string(n.Value.Unicode), - }, - } - - // Unknown case - default: - fmt.Println("Warning: unhandled element", node.Kind().String()) - return Element{} - } -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/emphasis.go b/vendor/github.com/charmbracelet/glamour/ansi/emphasis.go deleted file mode 100644 index 04ee4d0a..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/emphasis.go +++ /dev/null @@ -1,47 +0,0 @@ -package ansi - -import ( - "fmt" - "io" -) - -// A EmphasisElement is used to render emphasis. -type EmphasisElement struct { - Children []ElementRenderer - Level int -} - -// Render renders a EmphasisElement. -func (e *EmphasisElement) Render(w io.Writer, ctx RenderContext) error { - style := ctx.options.Styles.Emph - if e.Level > 1 { - style = ctx.options.Styles.Strong - } - - return e.doRender(w, ctx, style) -} - -// StyleOverrideRender renders a EmphasisElement with a given style. -func (e *EmphasisElement) StyleOverrideRender(w io.Writer, ctx RenderContext, style StylePrimitive) error { - base := ctx.options.Styles.Emph - if e.Level > 1 { - base = ctx.options.Styles.Strong - } - return e.doRender(w, ctx, cascadeStylePrimitives(base, style)) -} - -func (e *EmphasisElement) doRender(w io.Writer, ctx RenderContext, style StylePrimitive) error { - for _, child := range e.Children { - if r, ok := child.(StyleOverriderElementRenderer); ok { - if err := r.StyleOverrideRender(w, ctx, style); err != nil { - return fmt.Errorf("glamour: error rendering with style: %w", err) - } - } else { - if err := child.Render(w, ctx); err != nil { - return fmt.Errorf("glamour: error rendering: %w", err) - } - } - } - - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/heading.go b/vendor/github.com/charmbracelet/glamour/ansi/heading.go deleted file mode 100644 index b261ad7f..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/heading.go +++ /dev/null @@ -1,87 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "io" - - "github.com/muesli/reflow/wordwrap" -) - -// A HeadingElement is used to render headings. -type HeadingElement struct { - Level int - First bool -} - -const ( - h1 = iota + 1 - h2 - h3 - h4 - h5 - h6 -) - -// Render renders a HeadingElement. -func (e *HeadingElement) Render(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - rules := ctx.options.Styles.Heading - - switch e.Level { - case h1: - rules = cascadeStyles(rules, ctx.options.Styles.H1) - case h2: - rules = cascadeStyles(rules, ctx.options.Styles.H2) - case h3: - rules = cascadeStyles(rules, ctx.options.Styles.H3) - case h4: - rules = cascadeStyles(rules, ctx.options.Styles.H4) - case h5: - rules = cascadeStyles(rules, ctx.options.Styles.H5) - case h6: - rules = cascadeStyles(rules, ctx.options.Styles.H6) - } - - if !e.First { - renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, "\n") - } - - be := BlockElement{ - Block: &bytes.Buffer{}, - Style: cascadeStyle(bs.Current().Style, rules, false), - } - bs.Push(be) - - renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockPrefix) - renderText(bs.Current().Block, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Prefix) - return nil -} - -// Finish finishes rendering a HeadingElement. -func (e *HeadingElement) Finish(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - rules := bs.Current().Style - mw := NewMarginWriter(ctx, w, rules) - - flow := wordwrap.NewWriter(int(bs.Width(ctx))) //nolint: gosec - _, err := flow.Write(bs.Current().Block.Bytes()) - if err != nil { - return fmt.Errorf("glamour: error writing bytes: %w", err) - } - if err := flow.Close(); err != nil { - return fmt.Errorf("glamour: error closing flow: %w", err) - } - - _, err = mw.Write(flow.Bytes()) - if err != nil { - return err - } - - renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Suffix) - renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockSuffix) - - bs.Current().Block.Reset() - bs.Pop() - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/image.go b/vendor/github.com/charmbracelet/glamour/ansi/image.go deleted file mode 100644 index 16df5d8a..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/image.go +++ /dev/null @@ -1,52 +0,0 @@ -package ansi - -import ( - "io" - "strings" -) - -// An ImageElement is used to render images elements. -type ImageElement struct { - Text string - BaseURL string - URL string - Child ElementRenderer - TextOnly bool -} - -// Render renders an ImageElement. -func (e *ImageElement) Render(w io.Writer, ctx RenderContext) error { - style := ctx.options.Styles.ImageText - if e.TextOnly { - style.Format = strings.TrimSuffix(style.Format, " →") - } - - if len(e.Text) > 0 { - el := &BaseElement{ - Token: e.Text, - Style: style, - } - err := el.Render(w, ctx) - if err != nil { - return err - } - } - - if e.TextOnly { - return nil - } - - if len(e.URL) > 0 { - el := &BaseElement{ - Token: resolveRelativeURL(e.BaseURL, e.URL), - Prefix: " ", - Style: ctx.options.Styles.Image, - } - err := el.Render(w, ctx) - if err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/link.go b/vendor/github.com/charmbracelet/glamour/ansi/link.go deleted file mode 100644 index efc383d5..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/link.go +++ /dev/null @@ -1,76 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "io" - "net/url" -) - -// A LinkElement is used to render hyperlinks. -type LinkElement struct { - BaseURL string - URL string - Children []ElementRenderer - SkipText bool - SkipHref bool -} - -// Render renders a LinkElement. -func (e *LinkElement) Render(w io.Writer, ctx RenderContext) error { - if !e.SkipText { - if err := e.renderTextPart(w, ctx); err != nil { - return err - } - } - if !e.SkipHref { - if err := e.renderHrefPart(w, ctx); err != nil { - return err - } - } - return nil -} - -func (e *LinkElement) renderTextPart(w io.Writer, ctx RenderContext) error { - for _, child := range e.Children { - if r, ok := child.(StyleOverriderElementRenderer); ok { - st := ctx.options.Styles.LinkText - if err := r.StyleOverrideRender(w, ctx, st); err != nil { - return fmt.Errorf("glamour: error rendering with style: %w", err) - } - } else { - var b bytes.Buffer - if err := child.Render(&b, ctx); err != nil { - return fmt.Errorf("glamour: error rendering: %w", err) - } - el := &BaseElement{ - Token: b.String(), - Style: ctx.options.Styles.LinkText, - } - if err := el.Render(w, ctx); err != nil { - return fmt.Errorf("glamour: error rendering: %w", err) - } - } - } - return nil -} - -func (e *LinkElement) renderHrefPart(w io.Writer, ctx RenderContext) error { - prefix := "" - if !e.SkipText { - prefix = " " - } - - u, err := url.Parse(e.URL) - if err == nil && "#"+u.Fragment != e.URL { // if the URL only consists of an anchor, ignore it - el := &BaseElement{ - Token: resolveRelativeURL(e.BaseURL, e.URL), - Prefix: prefix, - Style: ctx.options.Styles.Link, - } - if err := el.Render(w, ctx); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/listitem.go b/vendor/github.com/charmbracelet/glamour/ansi/listitem.go deleted file mode 100644 index 66738d4f..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/listitem.go +++ /dev/null @@ -1,29 +0,0 @@ -package ansi - -import ( - "io" - "strconv" -) - -// An ItemElement is used to render items inside a list. -type ItemElement struct { - IsOrdered bool - Enumeration uint -} - -// Render renders an ItemElement. -func (e *ItemElement) Render(w io.Writer, ctx RenderContext) error { - var el *BaseElement - if e.IsOrdered { - el = &BaseElement{ - Style: ctx.options.Styles.Enumeration, - Prefix: strconv.FormatInt(int64(e.Enumeration), 10), //nolint: gosec - } - } else { - el = &BaseElement{ - Style: ctx.options.Styles.Item, - } - } - - return el.Render(w, ctx) -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/margin.go b/vendor/github.com/charmbracelet/glamour/ansi/margin.go deleted file mode 100644 index 9de2ad06..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/margin.go +++ /dev/null @@ -1,57 +0,0 @@ -package ansi - -import ( - "fmt" - "io" - - "github.com/muesli/reflow/indent" - "github.com/muesli/reflow/padding" -) - -// MarginWriter is a Writer that applies indentation and padding around -// whatever you write to it. -type MarginWriter struct { - w io.Writer - pw *padding.Writer - iw *indent.Writer -} - -// NewMarginWriter returns a new MarginWriter. -func NewMarginWriter(ctx RenderContext, w io.Writer, rules StyleBlock) *MarginWriter { - bs := ctx.blockStack - - var indentation uint - var margin uint - if rules.Indent != nil { - indentation = *rules.Indent - } - if rules.Margin != nil { - margin = *rules.Margin - } - - pw := padding.NewWriterPipe(w, bs.Width(ctx), func(_ io.Writer) { - renderText(w, ctx.options.ColorProfile, rules.StylePrimitive, " ") - }) - - ic := " " - if rules.IndentToken != nil { - ic = *rules.IndentToken - } - iw := indent.NewWriterPipe(pw, indentation+margin, func(_ io.Writer) { - renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, ic) - }) - - return &MarginWriter{ - w: w, - pw: pw, - iw: iw, - } -} - -func (w *MarginWriter) Write(b []byte) (int, error) { - n, err := w.iw.Write(b) - if err != nil { - return 0, fmt.Errorf("glamour: error writing bytes: %w", err) - } - return n, nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/paragraph.go b/vendor/github.com/charmbracelet/glamour/ansi/paragraph.go deleted file mode 100644 index b76b8fed..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/paragraph.go +++ /dev/null @@ -1,63 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "io" - "strings" - - "github.com/muesli/reflow/wordwrap" -) - -// A ParagraphElement is used to render individual paragraphs. -type ParagraphElement struct { - First bool -} - -// Render renders a ParagraphElement. -func (e *ParagraphElement) Render(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - rules := ctx.options.Styles.Paragraph - - if !e.First { - _, _ = io.WriteString(w, "\n") - } - be := BlockElement{ - Block: &bytes.Buffer{}, - Style: cascadeStyle(bs.Current().Style, rules, false), - } - bs.Push(be) - - renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockPrefix) - renderText(bs.Current().Block, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Prefix) - return nil -} - -// Finish finishes rendering a ParagraphElement. -func (e *ParagraphElement) Finish(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - rules := bs.Current().Style - - mw := NewMarginWriter(ctx, w, rules) - if len(strings.TrimSpace(bs.Current().Block.String())) > 0 { - flow := wordwrap.NewWriter(int(bs.Width(ctx))) //nolint: gosec - flow.KeepNewlines = ctx.options.PreserveNewLines - _, _ = flow.Write(bs.Current().Block.Bytes()) - if err := flow.Close(); err != nil { - return fmt.Errorf("glamour: error closing flow: %w", err) - } - - _, err := mw.Write(flow.Bytes()) - if err != nil { - return err - } - _, _ = io.WriteString(mw, "\n") - } - - renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Suffix) - renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockSuffix) - - bs.Current().Block.Reset() - bs.Pop() - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/renderer.go b/vendor/github.com/charmbracelet/glamour/ansi/renderer.go deleted file mode 100644 index 56ebfa50..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/renderer.go +++ /dev/null @@ -1,168 +0,0 @@ -package ansi - -import ( - "fmt" - "io" - "net/url" - "strings" - - "github.com/muesli/termenv" - east "github.com/yuin/goldmark-emoji/ast" - "github.com/yuin/goldmark/ast" - astext "github.com/yuin/goldmark/extension/ast" - "github.com/yuin/goldmark/renderer" - "github.com/yuin/goldmark/util" -) - -// Options is used to configure an ANSIRenderer. -type Options struct { - BaseURL string - WordWrap int - TableWrap *bool - InlineTableLinks bool - PreserveNewLines bool - ColorProfile termenv.Profile - Styles StyleConfig - ChromaFormatter string -} - -// ANSIRenderer renders markdown content as ANSI escaped sequences. -type ANSIRenderer struct { //nolint: revive - context RenderContext -} - -// NewRenderer returns a new ANSIRenderer with style and options set. -func NewRenderer(options Options) *ANSIRenderer { - return &ANSIRenderer{ - context: NewRenderContext(options), - } -} - -// RegisterFuncs implements NodeRenderer.RegisterFuncs. -func (r *ANSIRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) { - // blocks - reg.Register(ast.KindDocument, r.renderNode) - reg.Register(ast.KindHeading, r.renderNode) - reg.Register(ast.KindBlockquote, r.renderNode) - reg.Register(ast.KindCodeBlock, r.renderNode) - reg.Register(ast.KindFencedCodeBlock, r.renderNode) - reg.Register(ast.KindHTMLBlock, r.renderNode) - reg.Register(ast.KindList, r.renderNode) - reg.Register(ast.KindListItem, r.renderNode) - reg.Register(ast.KindParagraph, r.renderNode) - reg.Register(ast.KindTextBlock, r.renderNode) - reg.Register(ast.KindThematicBreak, r.renderNode) - - // inlines - reg.Register(ast.KindAutoLink, r.renderNode) - reg.Register(ast.KindCodeSpan, r.renderNode) - reg.Register(ast.KindEmphasis, r.renderNode) - reg.Register(ast.KindImage, r.renderNode) - reg.Register(ast.KindLink, r.renderNode) - reg.Register(ast.KindRawHTML, r.renderNode) - reg.Register(ast.KindText, r.renderNode) - reg.Register(ast.KindString, r.renderNode) - - // tables - reg.Register(astext.KindTable, r.renderNode) - reg.Register(astext.KindTableHeader, r.renderNode) - reg.Register(astext.KindTableRow, r.renderNode) - reg.Register(astext.KindTableCell, r.renderNode) - - // definitions - reg.Register(astext.KindDefinitionList, r.renderNode) - reg.Register(astext.KindDefinitionTerm, r.renderNode) - reg.Register(astext.KindDefinitionDescription, r.renderNode) - - // footnotes - reg.Register(astext.KindFootnote, r.renderNode) - reg.Register(astext.KindFootnoteList, r.renderNode) - reg.Register(astext.KindFootnoteLink, r.renderNode) - reg.Register(astext.KindFootnoteBacklink, r.renderNode) - - // checkboxes - reg.Register(astext.KindTaskCheckBox, r.renderNode) - - // strikethrough - reg.Register(astext.KindStrikethrough, r.renderNode) - - // emoji - reg.Register(east.KindEmoji, r.renderNode) -} - -func (r *ANSIRenderer) renderNode(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { - writeTo := io.Writer(w) - bs := r.context.blockStack - - // children get rendered by their parent - if isChild(node) { - return ast.WalkContinue, nil - } - - e := r.NewElement(node, source) - if entering { //nolint: nestif - // everything below the Document element gets rendered into a block buffer - if bs.Len() > 0 { - writeTo = io.Writer(bs.Current().Block) - } - - _, _ = io.WriteString(writeTo, e.Entering) - if e.Renderer != nil { - err := e.Renderer.Render(writeTo, r.context) - if err != nil { - return ast.WalkStop, fmt.Errorf("glamour: error rendering: %w", err) - } - } - } else { - // everything below the Document element gets rendered into a block buffer - if bs.Len() > 0 { - writeTo = io.Writer(bs.Parent().Block) - } - - // if we're finished rendering the entire document, - // flush to the real writer - if node.Type() == ast.TypeDocument { - writeTo = w - } - - if e.Finisher != nil { - err := e.Finisher.Finish(writeTo, r.context) - if err != nil { - return ast.WalkStop, fmt.Errorf("glamour: error finishing render: %w", err) - } - } - - _, _ = io.WriteString(bs.Current().Block, e.Exiting) - } - - return ast.WalkContinue, nil -} - -func isChild(node ast.Node) bool { - for n := node.Parent(); n != nil; n = n.Parent() { - // These types are already rendered by their parent - switch n.Kind() { - case ast.KindCodeSpan, ast.KindAutoLink, ast.KindLink, ast.KindImage, ast.KindEmphasis, astext.KindStrikethrough, astext.KindTableCell: - return true - } - } - - return false -} - -func resolveRelativeURL(baseURL string, rel string) string { - u, err := url.Parse(rel) - if err != nil { - return rel - } - if u.IsAbs() { - return rel - } - u.Path = strings.TrimPrefix(u.Path, "/") - - base, err := url.Parse(baseURL) - if err != nil { - return rel - } - return base.ResolveReference(u).String() -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/style.go b/vendor/github.com/charmbracelet/glamour/ansi/style.go deleted file mode 100644 index a660a455..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/style.go +++ /dev/null @@ -1,257 +0,0 @@ -package ansi - -// Chroma holds all the chroma settings. -type Chroma struct { - Text StylePrimitive `json:"text,omitempty"` - Error StylePrimitive `json:"error,omitempty"` - Comment StylePrimitive `json:"comment,omitempty"` - CommentPreproc StylePrimitive `json:"comment_preproc,omitempty"` - Keyword StylePrimitive `json:"keyword,omitempty"` - KeywordReserved StylePrimitive `json:"keyword_reserved,omitempty"` - KeywordNamespace StylePrimitive `json:"keyword_namespace,omitempty"` - KeywordType StylePrimitive `json:"keyword_type,omitempty"` - Operator StylePrimitive `json:"operator,omitempty"` - Punctuation StylePrimitive `json:"punctuation,omitempty"` - Name StylePrimitive `json:"name,omitempty"` - NameBuiltin StylePrimitive `json:"name_builtin,omitempty"` - NameTag StylePrimitive `json:"name_tag,omitempty"` - NameAttribute StylePrimitive `json:"name_attribute,omitempty"` - NameClass StylePrimitive `json:"name_class,omitempty"` - NameConstant StylePrimitive `json:"name_constant,omitempty"` - NameDecorator StylePrimitive `json:"name_decorator,omitempty"` - NameException StylePrimitive `json:"name_exception,omitempty"` - NameFunction StylePrimitive `json:"name_function,omitempty"` - NameOther StylePrimitive `json:"name_other,omitempty"` - Literal StylePrimitive `json:"literal,omitempty"` - LiteralNumber StylePrimitive `json:"literal_number,omitempty"` - LiteralDate StylePrimitive `json:"literal_date,omitempty"` - LiteralString StylePrimitive `json:"literal_string,omitempty"` - LiteralStringEscape StylePrimitive `json:"literal_string_escape,omitempty"` - GenericDeleted StylePrimitive `json:"generic_deleted,omitempty"` - GenericEmph StylePrimitive `json:"generic_emph,omitempty"` - GenericInserted StylePrimitive `json:"generic_inserted,omitempty"` - GenericStrong StylePrimitive `json:"generic_strong,omitempty"` - GenericSubheading StylePrimitive `json:"generic_subheading,omitempty"` - Background StylePrimitive `json:"background,omitempty"` -} - -// StylePrimitive holds all the basic style settings. -type StylePrimitive struct { - BlockPrefix string `json:"block_prefix,omitempty"` - BlockSuffix string `json:"block_suffix,omitempty"` - Prefix string `json:"prefix,omitempty"` - Suffix string `json:"suffix,omitempty"` - Color *string `json:"color,omitempty"` - BackgroundColor *string `json:"background_color,omitempty"` - Underline *bool `json:"underline,omitempty"` - Bold *bool `json:"bold,omitempty"` - Upper *bool `json:"upper,omitempty"` - Lower *bool `json:"lower,omitempty"` - Title *bool `json:"title,omitempty"` - Italic *bool `json:"italic,omitempty"` - CrossedOut *bool `json:"crossed_out,omitempty"` - Faint *bool `json:"faint,omitempty"` - Conceal *bool `json:"conceal,omitempty"` - Overlined *bool `json:"overlined,omitempty"` - Inverse *bool `json:"inverse,omitempty"` - Blink *bool `json:"blink,omitempty"` - Format string `json:"format,omitempty"` -} - -// StyleTask holds the style settings for a task item. -type StyleTask struct { - StylePrimitive - Ticked string `json:"ticked,omitempty"` - Unticked string `json:"unticked,omitempty"` -} - -// StyleBlock holds the basic style settings for block elements. -type StyleBlock struct { - StylePrimitive - Indent *uint `json:"indent,omitempty"` - IndentToken *string `json:"indent_token,omitempty"` - Margin *uint `json:"margin,omitempty"` -} - -// StyleCodeBlock holds the style settings for a code block. -type StyleCodeBlock struct { - StyleBlock - Theme string `json:"theme,omitempty"` - Chroma *Chroma `json:"chroma,omitempty"` -} - -// StyleList holds the style settings for a list. -type StyleList struct { - StyleBlock - LevelIndent uint `json:"level_indent,omitempty"` -} - -// StyleTable holds the style settings for a table. -type StyleTable struct { - StyleBlock - CenterSeparator *string `json:"center_separator,omitempty"` - ColumnSeparator *string `json:"column_separator,omitempty"` - RowSeparator *string `json:"row_separator,omitempty"` -} - -// StyleConfig is used to configure the styling behavior of an ANSIRenderer. -type StyleConfig struct { - Document StyleBlock `json:"document,omitempty"` - BlockQuote StyleBlock `json:"block_quote,omitempty"` - Paragraph StyleBlock `json:"paragraph,omitempty"` - List StyleList `json:"list,omitempty"` - - Heading StyleBlock `json:"heading,omitempty"` - H1 StyleBlock `json:"h1,omitempty"` - H2 StyleBlock `json:"h2,omitempty"` - H3 StyleBlock `json:"h3,omitempty"` - H4 StyleBlock `json:"h4,omitempty"` - H5 StyleBlock `json:"h5,omitempty"` - H6 StyleBlock `json:"h6,omitempty"` - - Text StylePrimitive `json:"text,omitempty"` - Strikethrough StylePrimitive `json:"strikethrough,omitempty"` - Emph StylePrimitive `json:"emph,omitempty"` - Strong StylePrimitive `json:"strong,omitempty"` - HorizontalRule StylePrimitive `json:"hr,omitempty"` - - Item StylePrimitive `json:"item,omitempty"` - Enumeration StylePrimitive `json:"enumeration,omitempty"` - Task StyleTask `json:"task,omitempty"` - - Link StylePrimitive `json:"link,omitempty"` - LinkText StylePrimitive `json:"link_text,omitempty"` - - Image StylePrimitive `json:"image,omitempty"` - ImageText StylePrimitive `json:"image_text,omitempty"` - - Code StyleBlock `json:"code,omitempty"` - CodeBlock StyleCodeBlock `json:"code_block,omitempty"` - - Table StyleTable `json:"table,omitempty"` - - DefinitionList StyleBlock `json:"definition_list,omitempty"` - DefinitionTerm StylePrimitive `json:"definition_term,omitempty"` - DefinitionDescription StylePrimitive `json:"definition_description,omitempty"` - - HTMLBlock StyleBlock `json:"html_block,omitempty"` - HTMLSpan StyleBlock `json:"html_span,omitempty"` -} - -func cascadeStyles(s ...StyleBlock) StyleBlock { - var r StyleBlock - for _, v := range s { - r = cascadeStyle(r, v, true) - } - return r -} - -func cascadeStylePrimitives(s ...StylePrimitive) StylePrimitive { - var r StylePrimitive - for _, v := range s { - r = cascadeStylePrimitive(r, v, true) - } - return r -} - -func cascadeStylePrimitive(parent, child StylePrimitive, toBlock bool) StylePrimitive { - s := child - - s.Color = parent.Color - s.BackgroundColor = parent.BackgroundColor - s.Underline = parent.Underline - s.Bold = parent.Bold - s.Upper = parent.Upper - s.Title = parent.Title - s.Lower = parent.Lower - s.Italic = parent.Italic - s.CrossedOut = parent.CrossedOut - s.Faint = parent.Faint - s.Conceal = parent.Conceal - s.Overlined = parent.Overlined - s.Inverse = parent.Inverse - s.Blink = parent.Blink - - if toBlock { - s.BlockPrefix = parent.BlockPrefix - s.BlockSuffix = parent.BlockSuffix - s.Prefix = parent.Prefix - s.Suffix = parent.Suffix - } - - if child.Color != nil { - s.Color = child.Color - } - if child.BackgroundColor != nil { - s.BackgroundColor = child.BackgroundColor - } - if child.Underline != nil { - s.Underline = child.Underline - } - if child.Bold != nil { - s.Bold = child.Bold - } - if child.Upper != nil { - s.Upper = child.Upper - } - if child.Lower != nil { - s.Lower = child.Lower - } - if child.Title != nil { - s.Title = child.Title - } - if child.Italic != nil { - s.Italic = child.Italic - } - if child.CrossedOut != nil { - s.CrossedOut = child.CrossedOut - } - if child.Faint != nil { - s.Faint = child.Faint - } - if child.Conceal != nil { - s.Conceal = child.Conceal - } - if child.Overlined != nil { - s.Overlined = child.Overlined - } - if child.Inverse != nil { - s.Inverse = child.Inverse - } - if child.Blink != nil { - s.Blink = child.Blink - } - if child.BlockPrefix != "" { - s.BlockPrefix = child.BlockPrefix - } - if child.BlockSuffix != "" { - s.BlockSuffix = child.BlockSuffix - } - if child.Prefix != "" { - s.Prefix = child.Prefix - } - if child.Suffix != "" { - s.Suffix = child.Suffix - } - if child.Format != "" { - s.Format = child.Format - } - - return s -} - -func cascadeStyle(parent StyleBlock, child StyleBlock, toBlock bool) StyleBlock { - s := child - s.StylePrimitive = cascadeStylePrimitive(parent.StylePrimitive, child.StylePrimitive, toBlock) - - if toBlock { - s.Indent = parent.Indent - s.Margin = parent.Margin - } - - if child.Indent != nil { - s.Indent = child.Indent - } - - return s -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/table.go b/vendor/github.com/charmbracelet/glamour/ansi/table.go deleted file mode 100644 index 98c420ea..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/table.go +++ /dev/null @@ -1,199 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "io" - - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/lipgloss/table" - "github.com/muesli/reflow/indent" - astext "github.com/yuin/goldmark/extension/ast" -) - -// A TableElement is used to render tables. -type TableElement struct { - lipgloss *table.Table - table *astext.Table - header []string - row []string - source []byte - - tableImages []tableLink - tableLinks []tableLink -} - -// A TableRowElement is used to render a single row in a table. -type TableRowElement struct{} - -// A TableHeadElement is used to render a table's head element. -type TableHeadElement struct{} - -// A TableCellElement is used to render a single cell in a row. -type TableCellElement struct { - Children []ElementRenderer - Head bool -} - -// Render renders a TableElement. -func (e *TableElement) Render(w io.Writer, ctx RenderContext) error { - bs := ctx.blockStack - - var indentation uint - var margin uint - rules := ctx.options.Styles.Table - if rules.Indent != nil { - indentation = *rules.Indent - } - if rules.Margin != nil { - margin = *rules.Margin - } - - iw := indent.NewWriterPipe(w, indentation+margin, func(_ io.Writer) { - renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, " ") - }) - - style := bs.With(rules.StylePrimitive) - - renderText(iw, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.BlockPrefix) - renderText(iw, ctx.options.ColorProfile, style, rules.Prefix) - width := int(ctx.blockStack.Width(ctx)) //nolint: gosec - - wrap := true - if ctx.options.TableWrap != nil { - wrap = *ctx.options.TableWrap - } - ctx.table.lipgloss = table.New().Width(width).Wrap(wrap) - - if err := e.collectLinksAndImages(ctx); err != nil { - return err - } - - return nil -} - -func (e *TableElement) setStyles(ctx RenderContext) { - ctx.table.lipgloss = ctx.table.lipgloss.StyleFunc(func(_, col int) lipgloss.Style { - st := lipgloss.NewStyle().Inline(false) - // Default Styles - st = st.Margin(0, 1) - - // Override with custom styles - if m := ctx.options.Styles.Table.Margin; m != nil { - st = st.Padding(0, int(*m)) //nolint: gosec - } - switch e.table.Alignments[col] { - case astext.AlignLeft: - st = st.Align(lipgloss.Left).PaddingRight(0) - case astext.AlignCenter: - st = st.Align(lipgloss.Center) - case astext.AlignRight: - st = st.Align(lipgloss.Right).PaddingLeft(0) - case astext.AlignNone: - // do nothing - } - - return st - }) -} - -func (e *TableElement) setBorders(ctx RenderContext) { - rules := ctx.options.Styles.Table - border := lipgloss.NormalBorder() - - if rules.RowSeparator != nil && rules.ColumnSeparator != nil { - border = lipgloss.Border{ - Top: *rules.RowSeparator, - Bottom: *rules.RowSeparator, - Left: *rules.ColumnSeparator, - Right: *rules.ColumnSeparator, - Middle: *rules.CenterSeparator, - } - } - ctx.table.lipgloss.Border(border) - ctx.table.lipgloss.BorderTop(false) - ctx.table.lipgloss.BorderLeft(false) - ctx.table.lipgloss.BorderRight(false) - ctx.table.lipgloss.BorderBottom(false) -} - -// Finish finishes rendering a TableElement. -func (e *TableElement) Finish(_ io.Writer, ctx RenderContext) error { - defer func() { - ctx.table.lipgloss = nil - ctx.table.tableImages = nil - ctx.table.tableLinks = nil - }() - - rules := ctx.options.Styles.Table - - e.setStyles(ctx) - e.setBorders(ctx) - - ow := ctx.blockStack.Current().Block - if _, err := ow.WriteString(ctx.table.lipgloss.String()); err != nil { - return fmt.Errorf("glamour: error writing to buffer: %w", err) - } - - renderText(ow, ctx.options.ColorProfile, ctx.blockStack.With(rules.StylePrimitive), rules.Suffix) - renderText(ow, ctx.options.ColorProfile, ctx.blockStack.Current().Style.StylePrimitive, rules.BlockSuffix) - - e.printTableLinks(ctx) - - return nil -} - -// Finish finishes rendering a TableRowElement. -func (e *TableRowElement) Finish(_ io.Writer, ctx RenderContext) error { - if ctx.table.lipgloss == nil { - return nil - } - - ctx.table.lipgloss.Row(ctx.table.row...) - ctx.table.row = []string{} - return nil -} - -// Finish finishes rendering a TableHeadElement. -func (e *TableHeadElement) Finish(_ io.Writer, ctx RenderContext) error { - if ctx.table.lipgloss == nil { - return nil - } - - ctx.table.lipgloss.Headers(ctx.table.header...) - ctx.table.header = []string{} - return nil -} - -// Render renders a TableCellElement. -func (e *TableCellElement) Render(_ io.Writer, ctx RenderContext) error { - var b bytes.Buffer - style := ctx.options.Styles.Table.StylePrimitive - for _, child := range e.Children { - if r, ok := child.(StyleOverriderElementRenderer); ok { - if err := r.StyleOverrideRender(&b, ctx, style); err != nil { - return fmt.Errorf("glamour: error rendering with style: %w", err) - } - } else { - var bb bytes.Buffer - if err := child.Render(&bb, ctx); err != nil { - return fmt.Errorf("glamour: error rendering: %w", err) - } - el := &BaseElement{ - Token: bb.String(), - Style: style, - } - if err := el.Render(&b, ctx); err != nil { - return err - } - } - } - - if e.Head { - ctx.table.header = append(ctx.table.header, b.String()) - } else { - ctx.table.row = append(ctx.table.row, b.String()) - } - - return nil -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/table_links.go b/vendor/github.com/charmbracelet/glamour/ansi/table_links.go deleted file mode 100644 index ab7a4293..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/table_links.go +++ /dev/null @@ -1,235 +0,0 @@ -package ansi - -import ( - "bytes" - "fmt" - "io" - "net/url" - "slices" - "strconv" - "strings" - - "github.com/charmbracelet/glamour/internal/autolink" - xansi "github.com/charmbracelet/x/ansi" - "github.com/charmbracelet/x/exp/slice" - "github.com/yuin/goldmark/ast" - astext "github.com/yuin/goldmark/extension/ast" -) - -type tableLink struct { - href string - title string - content string - linkType linkType -} - -type linkType int - -const ( - _ linkType = iota - linkTypeAuto - linkTypeImage - linkTypeRegular -) - -func (e *TableElement) printTableLinks(ctx RenderContext) { - if !e.shouldPrintTableLinks(ctx) { - return - } - - w := ctx.blockStack.Current().Block - termWidth := int(ctx.blockStack.Width(ctx)) //nolint: gosec - - renderLinkText := func(link tableLink, position, padding int) string { - token := strings.Repeat(" ", padding) - style := ctx.options.Styles.LinkText - - switch link.linkType { - case linkTypeAuto, linkTypeRegular: - token += fmt.Sprintf("[%d]: %s", position, link.content) - case linkTypeImage: - token += link.content - style = ctx.options.Styles.ImageText - style.Prefix = fmt.Sprintf("[%d]: %s", position, style.Prefix) - } - - var b bytes.Buffer - el := &BaseElement{Token: token, Style: style} - _ = el.Render(io.MultiWriter(w, &b), ctx) - return b.String() - } - - renderLinkHref := func(link tableLink, linkText string) { - style := ctx.options.Styles.Link - if link.linkType == linkTypeImage { - style = ctx.options.Styles.Image - } - - // XXX(@andreynering): Once #411 is merged, use the hyperlink - // protocol to make the link work for the full URL even if we - // show it truncated. - linkMaxWidth := max(termWidth-xansi.StringWidth(linkText)-1, 0) - token := xansi.Truncate(link.href, linkMaxWidth, "…") - - el := &BaseElement{Token: token, Style: style} - _ = el.Render(w, ctx) - } - - renderString := func(str string) { - renderText(w, ctx.options.ColorProfile, ctx.blockStack.Current().Style.StylePrimitive, str) - } - - paddingFor := func(total, position int) int { - totalSize := len(strconv.Itoa(total)) - positionSize := len(strconv.Itoa(position)) - - return max(totalSize-positionSize, 0) - } - - renderList := func(list []tableLink) { - for i, item := range list { - position := i + 1 - padding := paddingFor(len(list), position) - - renderString("\n") - linkText := renderLinkText(item, position, padding) - renderString(" ") - renderLinkHref(item, linkText) - } - } - - if len(ctx.table.tableLinks) > 0 { - renderString("\n") - } - renderList(ctx.table.tableLinks) - - if len(ctx.table.tableImages) > 0 { - renderString("\n") - } - renderList(ctx.table.tableImages) -} - -func (e *TableElement) shouldPrintTableLinks(ctx RenderContext) bool { - if ctx.options.InlineTableLinks { - return false - } - if len(ctx.table.tableLinks) == 0 && len(ctx.table.tableImages) == 0 { - return false - } - return true -} - -func (e *TableElement) collectLinksAndImages(ctx RenderContext) error { - images := make([]tableLink, 0) - links := make([]tableLink, 0) - - err := ast.Walk(e.table, func(node ast.Node, entering bool) (ast.WalkStatus, error) { - if !entering { - return ast.WalkContinue, nil - } - - switch n := node.(type) { - case *ast.AutoLink: - uri := string(n.URL(e.source)) - autoLink := tableLink{ - href: uri, - content: linkDomain(uri), - linkType: linkTypeAuto, - } - if shortned, ok := autolink.Detect(uri); ok { - autoLink.content = shortned - } - links = append(links, autoLink) - case *ast.Image: - content, err := nodeContent(node, e.source) - if err != nil { - return ast.WalkStop, err - } - image := tableLink{ - href: string(n.Destination), - title: string(n.Title), - content: string(content), - linkType: linkTypeImage, - } - if image.content == "" { - image.content = linkDomain(image.href) - } - images = append(images, image) - case *ast.Link: - content, err := nodeContent(node, e.source) - if err != nil { - return ast.WalkStop, err - } - link := tableLink{ - href: string(n.Destination), - title: string(n.Title), - content: string(content), - linkType: linkTypeRegular, - } - links = append(links, link) - } - - return ast.WalkContinue, nil - }) - if err != nil { - return fmt.Errorf("glamour: error collecting links: %w", err) - } - - ctx.table.tableImages = slice.Uniq(images) - ctx.table.tableLinks = slice.Uniq(links) - return nil -} - -func isInsideTable(node ast.Node) bool { - parent := node.Parent() - for parent != nil { - switch parent.Kind() { - case astext.KindTable, astext.KindTableHeader, astext.KindTableRow, astext.KindTableCell: - return true - default: - parent = parent.Parent() - } - } - return false -} - -func nodeContent(node ast.Node, source []byte) ([]byte, error) { - var builder bytes.Buffer - - var traverse func(node ast.Node) error - traverse = func(node ast.Node) error { - for n := node.FirstChild(); n != nil; n = n.NextSibling() { - switch nn := n.(type) { - case *ast.Text: - if _, err := builder.Write(nn.Segment.Value(source)); err != nil { - return fmt.Errorf("glamour: error writing text node: %w", err) - } - default: - if err := traverse(nn); err != nil { - return err - } - } - } - return nil - } - if err := traverse(node); err != nil { - return nil, err - } - - return builder.Bytes(), nil -} - -func linkDomain(href string) string { - if uri, err := url.Parse(href); err == nil { - return uri.Hostname() - } - return "link" -} - -func linkWithSuffix(tl tableLink, list []tableLink) string { - index := slices.Index(list, tl) - if index == -1 { - return tl.content - } - return fmt.Sprintf("%s[%d]", tl.content, index+1) -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/task.go b/vendor/github.com/charmbracelet/glamour/ansi/task.go deleted file mode 100644 index 61d2c838..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/task.go +++ /dev/null @@ -1,27 +0,0 @@ -package ansi - -import ( - "io" -) - -// A TaskElement is used to render tasks inside a todo-list. -type TaskElement struct { - Checked bool -} - -// Render renders a TaskElement. -func (e *TaskElement) Render(w io.Writer, ctx RenderContext) error { - var el *BaseElement - - pre := ctx.options.Styles.Task.Unticked - if e.Checked { - pre = ctx.options.Styles.Task.Ticked - } - - el = &BaseElement{ - Prefix: pre, - Style: ctx.options.Styles.Task.StylePrimitive, - } - - return el.Render(w, ctx) -} diff --git a/vendor/github.com/charmbracelet/glamour/ansi/templatehelper.go b/vendor/github.com/charmbracelet/glamour/ansi/templatehelper.go deleted file mode 100644 index bd31d376..00000000 --- a/vendor/github.com/charmbracelet/glamour/ansi/templatehelper.go +++ /dev/null @@ -1,86 +0,0 @@ -package ansi - -import ( - "regexp" - "strings" - "text/template" - - "golang.org/x/text/cases" - "golang.org/x/text/language" -) - -// TemplateFuncMap contains a few useful template helpers. -var ( - TemplateFuncMap = template.FuncMap{ - "Left": func(values ...interface{}) string { - s := values[0].(string) - n := values[1].(int) - if n > len(s) { - n = len(s) - } - - return s[:n] - }, - "Matches": func(values ...interface{}) bool { - ok, _ := regexp.MatchString(values[1].(string), values[0].(string)) - return ok - }, - "Mid": func(values ...interface{}) string { - s := values[0].(string) - l := values[1].(int) - if l > len(s) { - l = len(s) - } - - if len(values) > 2 { //nolint:mnd - r := values[2].(int) - if r > len(s) { - r = len(s) - } - return s[l:r] - } - return s[l:] - }, - "Right": func(values ...interface{}) string { - s := values[0].(string) - n := len(s) - values[1].(int) - if n < 0 { - n = 0 - } - - return s[n:] - }, - "Last": func(values ...interface{}) string { - return values[0].([]string)[len(values[0].([]string))-1] - }, - // strings functions - "Compare": strings.Compare, // 1.5+ only - "Contains": strings.Contains, - "ContainsAny": strings.ContainsAny, - "Count": strings.Count, - "EqualFold": strings.EqualFold, - "HasPrefix": strings.HasPrefix, - "HasSuffix": strings.HasSuffix, - "Index": strings.Index, - "IndexAny": strings.IndexAny, - "Join": strings.Join, - "LastIndex": strings.LastIndex, - "LastIndexAny": strings.LastIndexAny, - "Repeat": strings.Repeat, - "Replace": strings.Replace, - "Split": strings.Split, - "SplitAfter": strings.SplitAfter, - "SplitAfterN": strings.SplitAfterN, - "SplitN": strings.SplitN, - "Title": cases.Title(language.English).String, - "ToLower": cases.Lower(language.English).String, - "ToTitle": cases.Upper(language.English).String, - "ToUpper": strings.ToUpper, - "Trim": strings.Trim, - "TrimLeft": strings.TrimLeft, - "TrimPrefix": strings.TrimPrefix, - "TrimRight": strings.TrimRight, - "TrimSpace": strings.TrimSpace, - "TrimSuffix": strings.TrimSuffix, - } -) diff --git a/vendor/github.com/charmbracelet/glamour/examples.sh b/vendor/github.com/charmbracelet/glamour/examples.sh deleted file mode 100644 index 48aecf69..00000000 --- a/vendor/github.com/charmbracelet/glamour/examples.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -set -e - -for element in ./styles/examples/*.md; do - echo "Generating screenshot for element ${element}" - basename="`basename -s .md ${element}`" - stylename="${basename}.style" - filename="${basename}.png" - - # take screenshot - ./termshot -o ./styles/examples/ -f "$filename" glow -s ./styles/examples/${stylename} ${element} - - # add border - convert -bordercolor black -border 16x16 "./styles/examples/$filename" "./styles/examples/$filename" - - # optimize filesize - pngcrush -ow "./styles/examples/$filename" -done diff --git a/vendor/github.com/charmbracelet/glamour/gallery.sh b/vendor/github.com/charmbracelet/glamour/gallery.sh deleted file mode 100644 index 36d95008..00000000 --- a/vendor/github.com/charmbracelet/glamour/gallery.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -if ! command -v freeze &> /dev/null; then - echo "freeze not found. Please install freeze to capture images." - echo "https://github.com/charmbracelet/freeze/" - exit 1 -fi - -defaultStyles=("ascii" "auto" "dark" "dracula" "light" "notty" "pink") - -for style in "${defaultStyles[@]}"; do - echo "Generating screenshot for ${style}" - # take screenshot - if [[ $style == *"light"* ]]; then - # Provide a light background to images - freeze -x "go run ./examples/artichokes ${style}" -b "#FAFAFA" -o "./styles/gallery/${style}.png" - else - freeze -x "go run ./examples/artichokes ${style}" -o "./styles/gallery/${style}.png" - fi - - # optimize filesize - pngcrush -ow "./styles/gallery/$style.png" -done diff --git a/vendor/github.com/charmbracelet/glamour/glamour.go b/vendor/github.com/charmbracelet/glamour/glamour.go deleted file mode 100644 index bc1870cc..00000000 --- a/vendor/github.com/charmbracelet/glamour/glamour.go +++ /dev/null @@ -1,322 +0,0 @@ -// Package glamour lets you render markdown documents & templates on ANSI -// compatible terminals. You can create your own stylesheet or simply use one of -// the stylish defaults -package glamour - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "os" - - "github.com/muesli/termenv" - "github.com/yuin/goldmark" - emoji "github.com/yuin/goldmark-emoji" - "github.com/yuin/goldmark/extension" - "github.com/yuin/goldmark/parser" - "github.com/yuin/goldmark/renderer" - "github.com/yuin/goldmark/util" - "golang.org/x/term" - - "github.com/charmbracelet/glamour/ansi" - styles "github.com/charmbracelet/glamour/styles" -) - -const ( - defaultWidth = 80 - highPriority = 1000 -) - -// A TermRendererOption sets an option on a TermRenderer. -type TermRendererOption func(*TermRenderer) error - -// TermRenderer can be used to render markdown content, posing a depth of -// customization and styles to fit your needs. -type TermRenderer struct { - md goldmark.Markdown - ansiOptions ansi.Options - buf bytes.Buffer - renderBuf bytes.Buffer -} - -// Render initializes a new TermRenderer and renders a markdown with a specific -// style. -func Render(in string, stylePath string) (string, error) { - b, err := RenderBytes([]byte(in), stylePath) - return string(b), err -} - -// RenderWithEnvironmentConfig initializes a new TermRenderer and renders a -// markdown with a specific style defined by the GLAMOUR_STYLE environment variable. -func RenderWithEnvironmentConfig(in string) (string, error) { - b, err := RenderBytes([]byte(in), getEnvironmentStyle()) - return string(b), err -} - -// RenderBytes initializes a new TermRenderer and renders a markdown with a -// specific style. -func RenderBytes(in []byte, stylePath string) ([]byte, error) { - r, err := NewTermRenderer( - WithStylePath(stylePath), - ) - if err != nil { - return nil, err - } - return r.RenderBytes(in) -} - -// NewTermRenderer returns a new TermRenderer the given options. -func NewTermRenderer(options ...TermRendererOption) (*TermRenderer, error) { - tr := &TermRenderer{ - md: goldmark.New( - goldmark.WithExtensions( - extension.GFM, - extension.DefinitionList, - ), - goldmark.WithParserOptions( - parser.WithAutoHeadingID(), - ), - ), - ansiOptions: ansi.Options{ - WordWrap: defaultWidth, - ColorProfile: termenv.TrueColor, - }, - } - for _, o := range options { - if err := o(tr); err != nil { - return nil, err - } - } - ar := ansi.NewRenderer(tr.ansiOptions) - tr.md.SetRenderer( - renderer.NewRenderer( - renderer.WithNodeRenderers( - util.Prioritized(ar, highPriority), - ), - ), - ) - return tr, nil -} - -// WithBaseURL sets a TermRenderer's base URL. -func WithBaseURL(baseURL string) TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.BaseURL = baseURL - return nil - } -} - -// WithColorProfile sets the TermRenderer's color profile -// (TrueColor / ANSI256 / ANSI). -func WithColorProfile(profile termenv.Profile) TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.ColorProfile = profile - return nil - } -} - -// WithStandardStyle sets a TermRenderer's styles with a standard (builtin) -// style. -func WithStandardStyle(style string) TermRendererOption { - return func(tr *TermRenderer) error { - styles, err := getDefaultStyle(style) - if err != nil { - return err - } - tr.ansiOptions.Styles = *styles - return nil - } -} - -// WithAutoStyle sets a TermRenderer's styles with either the standard dark -// or light style, depending on the terminal's background color at run-time. -func WithAutoStyle() TermRendererOption { - return WithStandardStyle(styles.AutoStyle) -} - -// WithEnvironmentConfig sets a TermRenderer's styles based on the -// GLAMOUR_STYLE environment variable. -func WithEnvironmentConfig() TermRendererOption { - return WithStylePath(getEnvironmentStyle()) -} - -// WithStylePath sets a TermRenderer's style from stylePath. stylePath is first -// interpreted as a filename. If no such file exists, it is re-interpreted as a -// standard style. -func WithStylePath(stylePath string) TermRendererOption { - return func(tr *TermRenderer) error { - styles, err := getDefaultStyle(stylePath) - if err != nil { - jsonBytes, err := os.ReadFile(stylePath) - if err != nil { - return fmt.Errorf("glamour: error reading file: %w", err) - } - - return json.Unmarshal(jsonBytes, &tr.ansiOptions.Styles) - } - tr.ansiOptions.Styles = *styles - return nil - } -} - -// WithStyles sets a TermRenderer's styles. -func WithStyles(styles ansi.StyleConfig) TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.Styles = styles - return nil - } -} - -// WithStylesFromJSONBytes sets a TermRenderer's styles by parsing styles from -// jsonBytes. -func WithStylesFromJSONBytes(jsonBytes []byte) TermRendererOption { - return func(tr *TermRenderer) error { - return json.Unmarshal(jsonBytes, &tr.ansiOptions.Styles) - } -} - -// WithStylesFromJSONFile sets a TermRenderer's styles from a JSON file. -func WithStylesFromJSONFile(filename string) TermRendererOption { - return func(tr *TermRenderer) error { - jsonBytes, err := os.ReadFile(filename) - if err != nil { - return fmt.Errorf("glamour: error reading file: %w", err) - } - return json.Unmarshal(jsonBytes, &tr.ansiOptions.Styles) - } -} - -// WithWordWrap sets a TermRenderer's word wrap. -func WithWordWrap(wordWrap int) TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.WordWrap = wordWrap - return nil - } -} - -// WithTableWrap controls whether table content will wrap if too long. -// This is true by default. If false, table content will be truncated with an -// ellipsis if too long to fit. -func WithTableWrap(tableWrap bool) TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.TableWrap = &tableWrap - return nil - } -} - -// WithInlineTableLinks forces tables to render links inline. By default,links -// are rendered as a list of links at the bottom of the table. -func WithInlineTableLinks(inlineTableLinks bool) TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.InlineTableLinks = inlineTableLinks - return nil - } -} - -// WithPreservedNewLines preserves newlines from being replaced. -func WithPreservedNewLines() TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.PreserveNewLines = true - return nil - } -} - -// WithEmoji sets a TermRenderer's emoji rendering. -func WithEmoji() TermRendererOption { - return func(tr *TermRenderer) error { - emoji.New().Extend(tr.md) - return nil - } -} - -// WithChromaFormatter sets a TermRenderer's chroma formatter used for code blocks. -func WithChromaFormatter(formatter string) TermRendererOption { - return func(tr *TermRenderer) error { - tr.ansiOptions.ChromaFormatter = formatter - return nil - } -} - -// WithOptions sets multiple TermRenderer options within a single TermRendererOption. -func WithOptions(options ...TermRendererOption) TermRendererOption { - return func(tr *TermRenderer) error { - for _, o := range options { - if err := o(tr); err != nil { - return err - } - } - return nil - } -} - -func (tr *TermRenderer) Read(b []byte) (int, error) { - n, err := tr.renderBuf.Read(b) - if err == io.EOF { - return n, io.EOF - } - if err != nil { - return 0, fmt.Errorf("glamour: error reading from buffer: %w", err) - } - return n, nil -} - -func (tr *TermRenderer) Write(b []byte) (int, error) { - n, err := tr.buf.Write(b) - if err != nil { - return 0, fmt.Errorf("glamour: error writing bytes: %w", err) - } - return n, nil -} - -// Close must be called after writing to TermRenderer. You can then retrieve -// the rendered markdown by calling Read. -func (tr *TermRenderer) Close() error { - err := tr.md.Convert(tr.buf.Bytes(), &tr.renderBuf) - if err != nil { - return fmt.Errorf("glamour: error converting markdown: %w", err) - } - - tr.buf.Reset() - return nil -} - -// Render returns the markdown rendered into a string. -func (tr *TermRenderer) Render(in string) (string, error) { - b, err := tr.RenderBytes([]byte(in)) - return string(b), err -} - -// RenderBytes returns the markdown rendered into a byte slice. -func (tr *TermRenderer) RenderBytes(in []byte) ([]byte, error) { - var buf bytes.Buffer - err := tr.md.Convert(in, &buf) - return buf.Bytes(), err -} - -func getEnvironmentStyle() string { - glamourStyle := os.Getenv("GLAMOUR_STYLE") - if len(glamourStyle) == 0 { - glamourStyle = styles.AutoStyle - } - - return glamourStyle -} - -func getDefaultStyle(style string) (*ansi.StyleConfig, error) { - if style == styles.AutoStyle { - if !term.IsTerminal(int(os.Stdout.Fd())) { - return &styles.NoTTYStyleConfig, nil - } - if termenv.HasDarkBackground() { - return &styles.DarkStyleConfig, nil - } - return &styles.LightStyleConfig, nil - } - - styles, ok := styles.DefaultStyles[style] - if !ok { - return nil, fmt.Errorf("%s: style not found", style) - } - return styles, nil -} diff --git a/vendor/github.com/charmbracelet/glamour/internal/autolink/autolink.go b/vendor/github.com/charmbracelet/glamour/internal/autolink/autolink.go deleted file mode 100644 index 99d0501b..00000000 --- a/vendor/github.com/charmbracelet/glamour/internal/autolink/autolink.go +++ /dev/null @@ -1,55 +0,0 @@ -// Package autolink provides a function to detect and format GitHub links into -// a more readable manner. -package autolink - -import ( - "fmt" - "regexp" -) - -type pattern struct { - pattern *regexp.Regexp - yield func(m []string) string -} - -var patterns = []pattern{ - { - regexp.MustCompile(`^https?://github\.com/([A-z0-9_-]+)/([A-z0-9_-]+)/(issues?|pulls?|discussions?)/([0-9]+)$`), - func(m []string) string { return fmt.Sprintf("%s/%s#%s", m[1], m[2], m[4]) }, - }, - { - regexp.MustCompile(`^https?://github\.com/([A-z0-9_-]+)/([A-z0-9_-]+)/(issues?|pulls?|discussions?)/([0-9]+)#issuecomment-[0-9]+$`), - func(m []string) string { return fmt.Sprintf("%s/%s#%s (comment)", m[1], m[2], m[4]) }, - }, - { - regexp.MustCompile(`^https?://github\.com/([A-z0-9_-]+)/([A-z0-9_-]+)/pulls?/([0-9]+)#discussion_r[0-9]+$`), - func(m []string) string { return fmt.Sprintf("%s/%s#%s (comment)", m[1], m[2], m[3]) }, - }, - { - regexp.MustCompile(`^https?://github\.com/([A-z0-9_-]+)/([A-z0-9_-]+)/pulls?/([0-9]+)#pullrequestreview-[0-9]+$`), - func(m []string) string { return fmt.Sprintf("%s/%s#%s (review)", m[1], m[2], m[3]) }, - }, - { - regexp.MustCompile(`^https?://github\.com/([A-z0-9_-]+)/([A-z0-9_-]+)/discussions/([0-9]+)#discussioncomment-[0-9]+$`), - func(m []string) string { return fmt.Sprintf("%s/%s#%s (comment)", m[1], m[2], m[3]) }, - }, - { - regexp.MustCompile(`^https?://github\.com/([A-z0-9_-]+)/([A-z0-9_-]+)/commit/([A-z0-9]{7,})(#.*)?$`), - func(m []string) string { return fmt.Sprintf("%s/%s@%s", m[1], m[2], m[3][:7]) }, - }, - { - regexp.MustCompile(`^https?://github\.com/([A-z0-9_-]+)/([A-z0-9_-]+)/pulls?/[0-9]+/commits/([A-z0-9]{7,})(#.*)?$`), - func(m []string) string { return fmt.Sprintf("%s/%s@%s", m[1], m[2], m[3][:7]) }, - }, -} - -// Detect checks if the given URL matches any of the known patterns and -// returns a human-readable formatted string if a match is found. -func Detect(u string) (string, bool) { - for _, p := range patterns { - if m := p.pattern.FindStringSubmatch(u); len(m) > 0 { - return p.yield(m), true - } - } - return "", false -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/README.md b/vendor/github.com/charmbracelet/glamour/styles/README.md deleted file mode 100644 index 350d4305..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/README.md +++ /dev/null @@ -1,565 +0,0 @@ -# Glamour Style Guide - -The JSON files in this directory are generated from the default styles. To -re-generate them, run: - - go generate .. - -## Block Elements - -Block elements contain other elements and are rendered around them. All block -elements support the following style settings: - -| Attribute | Value | Description | -| ---------------- | ------ | ------------------------------------------------------------ | -| block_prefix | string | Printed before the block's first element (in parent's style) | -| block_suffix | string | Printed after the block's last element (in parent's style) | -| prefix | string | Printed before the block's first element | -| suffix | string | Printed after the block's last element | -| indent | number | Specifies the indentation of the block | -| indent_token | string | Specifies the indentation format | -| margin | number | Specifies the margin around the block | -| color | color | Defines the default text color for the block | -| background_color | color | Defines the default background color for the block | - -Elements inside a block inherit the block's following style settings: - -| Attribute | Value | Description | -| ---------------- | ----- | -------------------------------------------------- | -| color | color | Defines the default text color for the block | -| background_color | color | Defines the default background color for the block | -| bold | bool | Increases text intensity | -| faint | bool | Decreases text intensity | -| italic | bool | Prints the text in italic | -| crossed_out | bool | Enables strikethrough as text decoration | -| underline | bool | Enables underline as text decoration | -| overlined | bool | Enables overline as text decoration | -| blink | bool | Enables blinking text | -| conceal | bool | Conceals / hides the text | -| inverse | bool | Swaps fore- & background colors | - -### document - -The `document` element represents the markdown's body. - -#### Example - -Style: - -```json -"document": { - "indent": 2, - "background_color": "234", - "block_prefix": "\n", - "block_suffix": "\n" -} -``` - ---- - -### paragraph - -The `paragraph` element represents a paragraph in the document. - -#### Example - -Style: - -```json -"paragraph": { - "margin": 4, - "color": "15", - "background_color": "235" -} -``` - ---- - -### heading - -The `heading` element represents a heading. - -### h1 - h6 - -The `h1` to `h6` elements represent headings. `h1` defines the most important -heading, `h6` the least important heading. Undefined attributes are inherited -from the `heading` element. - -#### Example - -Markdown: - -```markdown -# h1 - -## h2 - -### h3 -``` - -Style: - -```json -"heading": { - "color": "15", - "background_color": "57" -}, -"h1": { - "prefix": "=> ", - "suffix": " <=", - "margin": 2, - "bold": true, - "background_color": "69" -}, -"h2": { - "prefix": "## ", - "margin": 4 -}, -"h3": { - "prefix": "### ", - "margin": 6 -} -``` - -Output: - -![Heading Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/heading.png) - ---- - -### block_quote - -The `block_quote` element represents a quote. - -#### Example - -Style: - -```json -"block_quote": { - "color": "200", - "indent": 1, - "indent_token": "=> " -} -``` - -Output: - -![Block Quote Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/block_quote.png) - ---- - -### list - -The `list` element represents a list in the document. - -| Attribute | Value | Description | -| ------------ | ------ | ------------------------------------------ | -| level_indent | number | Specifies the indentation for nested lists | - -#### Example - -Style: - -```json -"list": { - "color": "15", - "background_color": "52", - "level_indent": 4 -} -``` - ---- - -### code_block - -The `code_block` element represents a block of code. - -| Attribute | Value | Description | -| --------- | ------ | --------------------------------------------------------------- | -| theme | string | Defines the [Chroma][chroma] theme used for syntax highlighting | - -[chroma]: https://github.com/alecthomas/chroma - -#### Example - -Style: - -```json -"code_block": { - "color": "200", - "theme": "solarized-dark" -} -``` - -Output: - -![Code Block Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/code_block.png) - ---- - -### table - -The `table` element represents a table of data. - -#### Example - -Markdown: - -```markdown -| Label | Value | -| ------ | ----- | -| First | foo | -| Second | bar | -``` - -Style: - -```json -"table": { - "margin": 4 -} -``` - -Output: - -![Table Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/table.png) - -## Inline Elements - -All inline elements support the following style settings: - -| Attribute | Value | Description | -| ---------------- | ------ | ----------------------------------------------------- | -| block_prefix | string | Printed before the element (in parent's style) | -| block_suffix | string | Printed after the element (in parent's style) | -| prefix | string | Printed before the element | -| suffix | string | Printed after the element | -| color | color | Defines the default text color for the document | -| background_color | color | Defines the default background color for the document | -| bold | bool | Increases text intensity | -| faint | bool | Decreases text intensity | -| italic | bool | Prints the text in italic | -| crossed_out | bool | Enables strikethrough as text decoration | -| underline | bool | Enables underline as text decoration | -| overlined | bool | Enables overline as text decoration | -| blink | bool | Enables blinking text | -| conceal | bool | Conceals / hides the text | -| inverse | bool | Swaps fore- & background colors | - -### text - -The `text` element represents a block of text. - -#### Example - -Style: - -```json -"text": { - "bold": true, - "color": "15", - "background_color": "57" -} -``` - ---- - -### item - -The `item` element represents an item in a list. - -#### Example - -Markdown: - -```markdown -- First Item - - Nested List Item -- Second Item -``` - -Style: - -```json -"item": { - "block_prefix": "• " -} -``` - -Output: - -![List Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/list.png) - ---- - -### enumeration - -The `enumeration` element represents an item in an ordered list. - -#### Example - -Markdown: - -```markdown -1. First Item -2. Second Item -``` - -Style: - -```json -"enumeration": { - "block_prefix": ". " -} -``` - -Output: - -![Enumeration Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/enumeration.png) - ---- - -### task - -The `task` element represents a task item. - -| Attribute | Value | Description | -| --------- | ------ | --------------------------- | -| ticked | string | Prefix for finished tasks | -| unticked | string | Prefix for unfinished tasks | - -#### Example - -Markdown: - -```markdown -- [x] Finished Task -- [ ] Outstanding Task -``` - -Style: - -```json -"task": { - "ticked": "✓ ", - "unticked": "✗ " -} -``` - -Output: - -![Task Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/task.png) - ---- - -### link - -The `link` element represents a link. - -#### Example - -Markdown: - -```markdown -This is a [link](https://charm.sh). -``` - -Style: - -```json -"link": { - "color": "123", - "underline": true, - "block_prefix": "(", - "block_suffix": ")" -} -``` - -Output: - -![Link Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/link.png) - ---- - -### link_text - -The `link_text` element represents the text associated with a link. - -#### Example - -Style: - -```json -"link_text": { - "color": "123", - "bold": true -} -``` - ---- - -### image - -The `image` element represents an image. - -#### Example - -Markdown: - -```markdown -![Image](https://charm.sh/logo.png). -``` - -Style: - -```json -"image": { - "color": "123", - "block_prefix": "[Image: ", - "block_suffix": "]" -} -``` - -Output: - -![Image Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/image.png) - ---- - -### image_text - -The `image_text` element represents the text associated with an image. - -#### Example - -Style: - -```json -"image_text": { - "color": "8" -} -``` - ---- - -### code - -The `code` element represents an inline code segment. - -#### Example - -Style: - -```json -"code": { - "color": "200" -} -``` - -Output: - -![Code Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/code.png) - ---- - -### emph - -The `emph` element represents an emphasized text. - -#### Example - -Markdown: - -```markdown -This text is *emphasized*. -``` - -Style: - -```json -"emph": { - "italic": true -} -``` - -Output: - -![Emph Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/emph.png) - ---- - -### strong - -The `strong` element represents important text. - -#### Example - -Markdown: - -```markdown -This text is **strong**. -``` - -Style: - -```json -"strong": { - "bold": true -} -``` - -Output: - -![Strong Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/strong.png) - ---- - -### strikethrough - -The `strikethrough` element represents strikethrough text. - -#### Example - -Markdown: - -```markdown -~~Scratch this~~. -``` - -Style: - -```json -"strikethrough": { - "crossed_out": true -} -``` - -Output: - -![Strikethrough Example](https://github.com/charmbracelet/glamour/raw/master/styles/examples/strikethrough.png) - ---- - -### hr - -The `hr` element represents a horizontal rule. - -#### Example - -Markdown: - -```markdown ---- -``` - -Style: - -```json -"hr": { - "block_prefix": "---" -} -``` - -## html_block -## html_span diff --git a/vendor/github.com/charmbracelet/glamour/styles/ascii.json b/vendor/github.com/charmbracelet/glamour/styles/ascii.json deleted file mode 100644 index be13b917..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/ascii.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "document": { - "block_prefix": "\n", - "block_suffix": "\n", - "margin": 2 - }, - "block_quote": { - "indent": 1, - "indent_token": "| " - }, - "paragraph": {}, - "list": { - "level_indent": 4 - }, - "heading": { - "block_suffix": "\n" - }, - "h1": { - "prefix": "# " - }, - "h2": { - "prefix": "## " - }, - "h3": { - "prefix": "### " - }, - "h4": { - "prefix": "#### " - }, - "h5": { - "prefix": "##### " - }, - "h6": { - "prefix": "###### " - }, - "text": {}, - "strikethrough": { - "block_prefix": "~~", - "block_suffix": "~~" - }, - "emph": { - "block_prefix": "*", - "block_suffix": "*" - }, - "strong": { - "block_prefix": "**", - "block_suffix": "**" - }, - "hr": { - "format": "\n--------\n" - }, - "item": { - "block_prefix": "• " - }, - "enumeration": { - "block_prefix": ". " - }, - "task": { - "ticked": "[x] ", - "unticked": "[ ] " - }, - "link": {}, - "link_text": {}, - "image": {}, - "image_text": { - "format": "Image: {{.text}} →" - }, - "code": { - "block_prefix": "`", - "block_suffix": "`" - }, - "code_block": { - "margin": 2 - }, - "table": {}, - "definition_list": {}, - "definition_term": {}, - "definition_description": { - "block_prefix": "\n* " - }, - "html_block": {}, - "html_span": {} -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/dark.json b/vendor/github.com/charmbracelet/glamour/styles/dark.json deleted file mode 100644 index 47bf0afc..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/dark.json +++ /dev/null @@ -1,191 +0,0 @@ -{ - "document": { - "block_prefix": "\n", - "block_suffix": "\n", - "color": "252", - "margin": 2 - }, - "block_quote": { - "indent": 1, - "indent_token": "│ " - }, - "paragraph": {}, - "list": { - "level_indent": 2 - }, - "heading": { - "block_suffix": "\n", - "color": "39", - "bold": true - }, - "h1": { - "prefix": " ", - "suffix": " ", - "color": "228", - "background_color": "63", - "bold": true - }, - "h2": { - "prefix": "## " - }, - "h3": { - "prefix": "### " - }, - "h4": { - "prefix": "#### " - }, - "h5": { - "prefix": "##### " - }, - "h6": { - "prefix": "###### ", - "color": "35", - "bold": false - }, - "text": {}, - "strikethrough": { - "crossed_out": true - }, - "emph": { - "italic": true - }, - "strong": { - "bold": true - }, - "hr": { - "color": "240", - "format": "\n--------\n" - }, - "item": { - "block_prefix": "• " - }, - "enumeration": { - "block_prefix": ". " - }, - "task": { - "ticked": "[✓] ", - "unticked": "[ ] " - }, - "link": { - "color": "30", - "underline": true - }, - "link_text": { - "color": "35", - "bold": true - }, - "image": { - "color": "212", - "underline": true - }, - "image_text": { - "color": "243", - "format": "Image: {{.text}} →" - }, - "code": { - "prefix": " ", - "suffix": " ", - "color": "203", - "background_color": "236" - }, - "code_block": { - "color": "244", - "margin": 2, - "chroma": { - "text": { - "color": "#C4C4C4" - }, - "error": { - "color": "#F1F1F1", - "background_color": "#F05B5B" - }, - "comment": { - "color": "#676767" - }, - "comment_preproc": { - "color": "#FF875F" - }, - "keyword": { - "color": "#00AAFF" - }, - "keyword_reserved": { - "color": "#FF5FD2" - }, - "keyword_namespace": { - "color": "#FF5F87" - }, - "keyword_type": { - "color": "#6E6ED8" - }, - "operator": { - "color": "#EF8080" - }, - "punctuation": { - "color": "#E8E8A8" - }, - "name": { - "color": "#C4C4C4" - }, - "name_builtin": { - "color": "#FF8EC7" - }, - "name_tag": { - "color": "#B083EA" - }, - "name_attribute": { - "color": "#7A7AE6" - }, - "name_class": { - "color": "#F1F1F1", - "underline": true, - "bold": true - }, - "name_constant": {}, - "name_decorator": { - "color": "#FFFF87" - }, - "name_exception": {}, - "name_function": { - "color": "#00D787" - }, - "name_other": {}, - "literal": {}, - "literal_number": { - "color": "#6EEFC0" - }, - "literal_date": {}, - "literal_string": { - "color": "#C69669" - }, - "literal_string_escape": { - "color": "#AFFFD7" - }, - "generic_deleted": { - "color": "#FD5B5B" - }, - "generic_emph": { - "italic": true - }, - "generic_inserted": { - "color": "#00D787" - }, - "generic_strong": { - "bold": true - }, - "generic_subheading": { - "color": "#777777" - }, - "background": { - "background_color": "#373737" - } - } - }, - "table": {}, - "definition_list": {}, - "definition_term": {}, - "definition_description": { - "block_prefix": "\n🠶 " - }, - "html_block": {}, - "html_span": {} -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/dracula.go b/vendor/github.com/charmbracelet/glamour/styles/dracula.go deleted file mode 100644 index 12eaf9d4..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/dracula.go +++ /dev/null @@ -1,216 +0,0 @@ -package styles - -import "github.com/charmbracelet/glamour/ansi" - -// DraculaStyleConfig is the dracula style. -var DraculaStyleConfig = ansi.StyleConfig{ - Document: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "\n", - BlockSuffix: "\n", - Color: stringPtr("#f8f8f2"), - }, - Margin: uintPtr(defaultMargin), - }, - BlockQuote: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("#f1fa8c"), - Italic: boolPtr(true), - }, - Indent: uintPtr(defaultMargin), - }, - List: ansi.StyleList{ - LevelIndent: defaultMargin, - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("#f8f8f2"), - }, - }, - }, - Heading: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - Color: stringPtr("#bd93f9"), - Bold: boolPtr(true), - }, - }, - H1: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "# ", - }, - }, - H2: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "## ", - }, - }, - H3: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "### ", - }, - }, - H4: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "#### ", - }, - }, - H5: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "##### ", - }, - }, - H6: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "###### ", - }, - }, - Strikethrough: ansi.StylePrimitive{ - CrossedOut: boolPtr(true), - }, - Emph: ansi.StylePrimitive{ - Color: stringPtr("#f1fa8c"), - Italic: boolPtr(true), - }, - Strong: ansi.StylePrimitive{ - Bold: boolPtr(true), - Color: stringPtr("#ffb86c"), - }, - HorizontalRule: ansi.StylePrimitive{ - Color: stringPtr("#6272A4"), - Format: "\n--------\n", - }, - Item: ansi.StylePrimitive{ - BlockPrefix: "• ", - }, - Enumeration: ansi.StylePrimitive{ - BlockPrefix: ". ", - Color: stringPtr("#8be9fd"), - }, - Task: ansi.StyleTask{ - StylePrimitive: ansi.StylePrimitive{}, - Ticked: "[✓] ", - Unticked: "[ ] ", - }, - Link: ansi.StylePrimitive{ - Color: stringPtr("#8be9fd"), - Underline: boolPtr(true), - }, - LinkText: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - Image: ansi.StylePrimitive{ - Color: stringPtr("#8be9fd"), - Underline: boolPtr(true), - }, - ImageText: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - Format: "Image: {{.text}} →", - }, - Code: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("#50fa7b"), - }, - }, - CodeBlock: ansi.StyleCodeBlock{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("#ffb86c"), - }, - Margin: uintPtr(defaultMargin), - }, - Chroma: &ansi.Chroma{ - Text: ansi.StylePrimitive{ - Color: stringPtr("#f8f8f2"), - }, - Error: ansi.StylePrimitive{ - Color: stringPtr("#f8f8f2"), - BackgroundColor: stringPtr("#ff5555"), - }, - Comment: ansi.StylePrimitive{ - Color: stringPtr("#6272A4"), - }, - CommentPreproc: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - Keyword: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - KeywordReserved: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - KeywordNamespace: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - KeywordType: ansi.StylePrimitive{ - Color: stringPtr("#8be9fd"), - }, - Operator: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - Punctuation: ansi.StylePrimitive{ - Color: stringPtr("#f8f8f2"), - }, - Name: ansi.StylePrimitive{ - Color: stringPtr("#8be9fd"), - }, - NameBuiltin: ansi.StylePrimitive{ - Color: stringPtr("#8be9fd"), - }, - NameTag: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - NameAttribute: ansi.StylePrimitive{ - Color: stringPtr("#50fa7b"), - }, - NameClass: ansi.StylePrimitive{ - Color: stringPtr("#8be9fd"), - }, - NameConstant: ansi.StylePrimitive{ - Color: stringPtr("#bd93f9"), - }, - NameDecorator: ansi.StylePrimitive{ - Color: stringPtr("#50fa7b"), - }, - NameFunction: ansi.StylePrimitive{ - Color: stringPtr("#50fa7b"), - }, - LiteralNumber: ansi.StylePrimitive{ - Color: stringPtr("#6EEFC0"), - }, - LiteralString: ansi.StylePrimitive{ - Color: stringPtr("#f1fa8c"), - }, - LiteralStringEscape: ansi.StylePrimitive{ - Color: stringPtr("#ff79c6"), - }, - GenericDeleted: ansi.StylePrimitive{ - Color: stringPtr("#ff5555"), - }, - GenericEmph: ansi.StylePrimitive{ - Color: stringPtr("#f1fa8c"), - Italic: boolPtr(true), - }, - GenericInserted: ansi.StylePrimitive{ - Color: stringPtr("#50fa7b"), - }, - GenericStrong: ansi.StylePrimitive{ - Color: stringPtr("#ffb86c"), - Bold: boolPtr(true), - }, - GenericSubheading: ansi.StylePrimitive{ - Color: stringPtr("#bd93f9"), - }, - Background: ansi.StylePrimitive{ - BackgroundColor: stringPtr("#282a36"), - }, - }, - }, - Table: ansi.StyleTable{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - }, - }, - DefinitionDescription: ansi.StylePrimitive{ - BlockPrefix: "\n🠶 ", - }, -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/dracula.json b/vendor/github.com/charmbracelet/glamour/styles/dracula.json deleted file mode 100644 index 4bbcd497..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/dracula.json +++ /dev/null @@ -1,188 +0,0 @@ -{ - "document": { - "block_prefix": "\n", - "block_suffix": "\n", - "color": "#f8f8f2", - "margin": 2 - }, - "block_quote": { - "color": "#f1fa8c", - "italic": true, - "indent": 2 - }, - "paragraph": {}, - "list": { - "color": "#f8f8f2", - "level_indent": 2 - }, - "heading": { - "block_suffix": "\n", - "color": "#bd93f9", - "bold": true - }, - "h1": { - "prefix": "# " - }, - "h2": { - "prefix": "## " - }, - "h3": { - "prefix": "### " - }, - "h4": { - "prefix": "#### " - }, - "h5": { - "prefix": "##### " - }, - "h6": { - "prefix": "###### " - }, - "text": {}, - "strikethrough": { - "crossed_out": true - }, - "emph": { - "color": "#f1fa8c", - "italic": true - }, - "strong": { - "color": "#ffb86c", - "bold": true - }, - "hr": { - "color": "#6272A4", - "format": "\n--------\n" - }, - "item": { - "block_prefix": "• " - }, - "enumeration": { - "block_prefix": ". ", - "color": "#8be9fd" - }, - "task": { - "ticked": "[✓] ", - "unticked": "[ ] " - }, - "link": { - "color": "#8be9fd", - "underline": true - }, - "link_text": { - "color": "#ff79c6" - }, - "image": { - "color": "#8be9fd", - "underline": true - }, - "image_text": { - "color": "#ff79c6", - "format": "Image: {{.text}} →" - }, - "code": { - "color": "#50fa7b" - }, - "code_block": { - "color": "#ffb86c", - "margin": 2, - "chroma": { - "text": { - "color": "#f8f8f2" - }, - "error": { - "color": "#f8f8f2", - "background_color": "#ff5555" - }, - "comment": { - "color": "#6272A4" - }, - "comment_preproc": { - "color": "#ff79c6" - }, - "keyword": { - "color": "#ff79c6" - }, - "keyword_reserved": { - "color": "#ff79c6" - }, - "keyword_namespace": { - "color": "#ff79c6" - }, - "keyword_type": { - "color": "#8be9fd" - }, - "operator": { - "color": "#ff79c6" - }, - "punctuation": { - "color": "#f8f8f2" - }, - "name": { - "color": "#8be9fd" - }, - "name_builtin": { - "color": "#8be9fd" - }, - "name_tag": { - "color": "#ff79c6" - }, - "name_attribute": { - "color": "#50fa7b" - }, - "name_class": { - "color": "#8be9fd" - }, - "name_constant": { - "color": "#bd93f9" - }, - "name_decorator": { - "color": "#50fa7b" - }, - "name_exception": {}, - "name_function": { - "color": "#50fa7b" - }, - "name_other": {}, - "literal": {}, - "literal_number": { - "color": "#6EEFC0" - }, - "literal_date": {}, - "literal_string": { - "color": "#f1fa8c" - }, - "literal_string_escape": { - "color": "#ff79c6" - }, - "generic_deleted": { - "color": "#ff5555" - }, - "generic_emph": { - "color": "#f1fa8c", - "italic": true - }, - "generic_inserted": { - "color": "#50fa7b" - }, - "generic_strong": { - "color": "#ffb86c", - "bold": true - }, - "generic_subheading": { - "color": "#bd93f9" - }, - "background": { - "background_color": "#282a36" - } - } - }, - "table": {}, - "definition_list": {}, - "definition_term": {}, - "definition_description": { - "block_prefix": "\n🠶 " - }, - "html_block": {}, - "html_span": {} -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/light.json b/vendor/github.com/charmbracelet/glamour/styles/light.json deleted file mode 100644 index 08533592..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/light.json +++ /dev/null @@ -1,190 +0,0 @@ -{ - "document": { - "block_prefix": "\n", - "block_suffix": "\n", - "color": "234", - "margin": 2 - }, - "block_quote": { - "indent": 1, - "indent_token": "│ " - }, - "paragraph": {}, - "list": { - "level_indent": 2 - }, - "heading": { - "block_suffix": "\n", - "color": "27", - "bold": true - }, - "h1": { - "prefix": " ", - "suffix": " ", - "color": "228", - "background_color": "63", - "bold": true - }, - "h2": { - "prefix": "## " - }, - "h3": { - "prefix": "### " - }, - "h4": { - "prefix": "#### " - }, - "h5": { - "prefix": "##### " - }, - "h6": { - "prefix": "###### ", - "bold": false - }, - "text": {}, - "strikethrough": { - "crossed_out": true - }, - "emph": { - "italic": true - }, - "strong": { - "bold": true - }, - "hr": { - "color": "249", - "format": "\n--------\n" - }, - "item": { - "block_prefix": "• " - }, - "enumeration": { - "block_prefix": ". " - }, - "task": { - "ticked": "[✓] ", - "unticked": "[ ] " - }, - "link": { - "color": "36", - "underline": true - }, - "link_text": { - "color": "29", - "bold": true - }, - "image": { - "color": "205", - "underline": true - }, - "image_text": { - "color": "243", - "format": "Image: {{.text}} →" - }, - "code": { - "prefix": " ", - "suffix": " ", - "color": "203", - "background_color": "254" - }, - "code_block": { - "color": "242", - "margin": 2, - "chroma": { - "text": { - "color": "#2A2A2A" - }, - "error": { - "color": "#F1F1F1", - "background_color": "#FF5555" - }, - "comment": { - "color": "#8D8D8D" - }, - "comment_preproc": { - "color": "#FF875F" - }, - "keyword": { - "color": "#279EFC" - }, - "keyword_reserved": { - "color": "#FF5FD2" - }, - "keyword_namespace": { - "color": "#FB406F" - }, - "keyword_type": { - "color": "#7049C2" - }, - "operator": { - "color": "#FF2626" - }, - "punctuation": { - "color": "#FA7878" - }, - "name": {}, - "name_builtin": { - "color": "#0A1BB1" - }, - "name_tag": { - "color": "#581290" - }, - "name_attribute": { - "color": "#8362CB" - }, - "name_class": { - "color": "#212121", - "underline": true, - "bold": true - }, - "name_constant": { - "color": "#581290" - }, - "name_decorator": { - "color": "#A3A322" - }, - "name_exception": {}, - "name_function": { - "color": "#019F57" - }, - "name_other": {}, - "literal": {}, - "literal_number": { - "color": "#22CCAE" - }, - "literal_date": {}, - "literal_string": { - "color": "#7E5B38" - }, - "literal_string_escape": { - "color": "#00AEAE" - }, - "generic_deleted": { - "color": "#FD5B5B" - }, - "generic_emph": { - "italic": true - }, - "generic_inserted": { - "color": "#00D787" - }, - "generic_strong": { - "bold": true - }, - "generic_subheading": { - "color": "#777777" - }, - "background": { - "background_color": "#373737" - } - } - }, - "table": {}, - "definition_list": {}, - "definition_term": {}, - "definition_description": { - "block_prefix": "\n🠶 " - }, - "html_block": {}, - "html_span": {} -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/notty.json b/vendor/github.com/charmbracelet/glamour/styles/notty.json deleted file mode 100644 index be13b917..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/notty.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "document": { - "block_prefix": "\n", - "block_suffix": "\n", - "margin": 2 - }, - "block_quote": { - "indent": 1, - "indent_token": "| " - }, - "paragraph": {}, - "list": { - "level_indent": 4 - }, - "heading": { - "block_suffix": "\n" - }, - "h1": { - "prefix": "# " - }, - "h2": { - "prefix": "## " - }, - "h3": { - "prefix": "### " - }, - "h4": { - "prefix": "#### " - }, - "h5": { - "prefix": "##### " - }, - "h6": { - "prefix": "###### " - }, - "text": {}, - "strikethrough": { - "block_prefix": "~~", - "block_suffix": "~~" - }, - "emph": { - "block_prefix": "*", - "block_suffix": "*" - }, - "strong": { - "block_prefix": "**", - "block_suffix": "**" - }, - "hr": { - "format": "\n--------\n" - }, - "item": { - "block_prefix": "• " - }, - "enumeration": { - "block_prefix": ". " - }, - "task": { - "ticked": "[x] ", - "unticked": "[ ] " - }, - "link": {}, - "link_text": {}, - "image": {}, - "image_text": { - "format": "Image: {{.text}} →" - }, - "code": { - "block_prefix": "`", - "block_suffix": "`" - }, - "code_block": { - "margin": 2 - }, - "table": {}, - "definition_list": {}, - "definition_term": {}, - "definition_description": { - "block_prefix": "\n* " - }, - "html_block": {}, - "html_span": {} -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/pink.json b/vendor/github.com/charmbracelet/glamour/styles/pink.json deleted file mode 100644 index 39a7f9ec..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/pink.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "document": { - "margin": 2 - }, - "block_quote": { - "indent": 1, - "indent_token": "│ " - }, - "paragraph": {}, - "list": { - "level_indent": 2 - }, - "heading": { - "block_suffix": "\n", - "color": "212", - "bold": true - }, - "h1": { - "block_prefix": "\n", - "block_suffix": "\n" - }, - "h2": { - "prefix": "▌ " - }, - "h3": { - "prefix": "┃ " - }, - "h4": { - "prefix": "│ " - }, - "h5": { - "prefix": "┆ " - }, - "h6": { - "prefix": "┊ ", - "bold": false - }, - "text": {}, - "strikethrough": { - "crossed_out": true - }, - "emph": { - "italic": true - }, - "strong": { - "bold": true - }, - "hr": { - "color": "212", - "format": "\n──────\n" - }, - "item": { - "block_prefix": "• " - }, - "enumeration": { - "block_prefix": ". " - }, - "task": { - "ticked": "[✓] ", - "unticked": "[ ] " - }, - "link": { - "color": "99", - "underline": true - }, - "link_text": { - "bold": true - }, - "image": { - "underline": true - }, - "image_text": { - "format": "Image: {{.text}}" - }, - "code": { - "prefix": " ", - "suffix": " ", - "color": "212", - "background_color": "236" - }, - "code_block": {}, - "table": {}, - "definition_list": {}, - "definition_term": {}, - "definition_description": { - "block_prefix": "\n🠶 " - }, - "html_block": {}, - "html_span": {} -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/styles.go b/vendor/github.com/charmbracelet/glamour/styles/styles.go deleted file mode 100644 index 72ee1a55..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/styles.go +++ /dev/null @@ -1,681 +0,0 @@ -// Package styles provides default styles for the glamour package. -package styles - -//go:generate go run ../internal/generate-style-json - -import ( - "github.com/charmbracelet/glamour/ansi" -) - -const ( - defaultListIndent = 2 - defaultListLevelIndent = 4 - defaultMargin = 2 -) - -// Default styles. -const ( - AsciiStyle = "ascii" //nolint: revive - AutoStyle = "auto" - DarkStyle = "dark" - DraculaStyle = "dracula" - TokyoNightStyle = "tokyo-night" - LightStyle = "light" - NoTTYStyle = "notty" - PinkStyle = "pink" -) - -var ( - // ASCIIStyleConfig uses only ASCII characters. - ASCIIStyleConfig = ansi.StyleConfig{ - Document: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "\n", - BlockSuffix: "\n", - }, - Margin: uintPtr(defaultMargin), - }, - BlockQuote: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - Indent: uintPtr(1), - IndentToken: stringPtr("| "), - }, - Paragraph: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - }, - List: ansi.StyleList{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - }, - LevelIndent: defaultListLevelIndent, - }, - Heading: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - }, - }, - H1: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "# ", - }, - }, - H2: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "## ", - }, - }, - H3: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "### ", - }, - }, - H4: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "#### ", - }, - }, - H5: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "##### ", - }, - }, - H6: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "###### ", - }, - }, - Strikethrough: ansi.StylePrimitive{ - BlockPrefix: "~~", - BlockSuffix: "~~", - }, - Emph: ansi.StylePrimitive{ - BlockPrefix: "*", - BlockSuffix: "*", - }, - Strong: ansi.StylePrimitive{ - BlockPrefix: "**", - BlockSuffix: "**", - }, - HorizontalRule: ansi.StylePrimitive{ - Format: "\n--------\n", - }, - Item: ansi.StylePrimitive{ - BlockPrefix: "• ", - }, - Enumeration: ansi.StylePrimitive{ - BlockPrefix: ". ", - }, - Task: ansi.StyleTask{ - Ticked: "[x] ", - Unticked: "[ ] ", - }, - ImageText: ansi.StylePrimitive{ - Format: "Image: {{.text}} →", - }, - Code: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "`", - BlockSuffix: "`", - }, - }, - CodeBlock: ansi.StyleCodeBlock{ - StyleBlock: ansi.StyleBlock{ - Margin: uintPtr(defaultMargin), - }, - }, - Table: ansi.StyleTable{ - CenterSeparator: stringPtr("|"), - ColumnSeparator: stringPtr("|"), - RowSeparator: stringPtr("-"), - }, - DefinitionDescription: ansi.StylePrimitive{ - BlockPrefix: "\n* ", - }, - } - - // DarkStyleConfig is the default dark style. - DarkStyleConfig = ansi.StyleConfig{ - Document: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "\n", - BlockSuffix: "\n", - Color: stringPtr("252"), - }, - Margin: uintPtr(defaultMargin), - }, - BlockQuote: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - Indent: uintPtr(1), - IndentToken: stringPtr("│ "), - }, - List: ansi.StyleList{ - LevelIndent: defaultListIndent, - }, - Heading: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - Color: stringPtr("39"), - Bold: boolPtr(true), - }, - }, - H1: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: " ", - Suffix: " ", - Color: stringPtr("228"), - BackgroundColor: stringPtr("63"), - Bold: boolPtr(true), - }, - }, - H2: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "## ", - }, - }, - H3: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "### ", - }, - }, - H4: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "#### ", - }, - }, - H5: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "##### ", - }, - }, - H6: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "###### ", - Color: stringPtr("35"), - Bold: boolPtr(false), - }, - }, - Strikethrough: ansi.StylePrimitive{ - CrossedOut: boolPtr(true), - }, - Emph: ansi.StylePrimitive{ - Italic: boolPtr(true), - }, - Strong: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - HorizontalRule: ansi.StylePrimitive{ - Color: stringPtr("240"), - Format: "\n--------\n", - }, - Item: ansi.StylePrimitive{ - BlockPrefix: "• ", - }, - Enumeration: ansi.StylePrimitive{ - BlockPrefix: ". ", - }, - Task: ansi.StyleTask{ - StylePrimitive: ansi.StylePrimitive{}, - Ticked: "[✓] ", - Unticked: "[ ] ", - }, - Link: ansi.StylePrimitive{ - Color: stringPtr("30"), - Underline: boolPtr(true), - }, - LinkText: ansi.StylePrimitive{ - Color: stringPtr("35"), - Bold: boolPtr(true), - }, - Image: ansi.StylePrimitive{ - Color: stringPtr("212"), - Underline: boolPtr(true), - }, - ImageText: ansi.StylePrimitive{ - Color: stringPtr("243"), - Format: "Image: {{.text}} →", - }, - Code: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: " ", - Suffix: " ", - Color: stringPtr("203"), - BackgroundColor: stringPtr("236"), - }, - }, - CodeBlock: ansi.StyleCodeBlock{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("244"), - }, - Margin: uintPtr(defaultMargin), - }, - Chroma: &ansi.Chroma{ - Text: ansi.StylePrimitive{ - Color: stringPtr("#C4C4C4"), - }, - Error: ansi.StylePrimitive{ - Color: stringPtr("#F1F1F1"), - BackgroundColor: stringPtr("#F05B5B"), - }, - Comment: ansi.StylePrimitive{ - Color: stringPtr("#676767"), - }, - CommentPreproc: ansi.StylePrimitive{ - Color: stringPtr("#FF875F"), - }, - Keyword: ansi.StylePrimitive{ - Color: stringPtr("#00AAFF"), - }, - KeywordReserved: ansi.StylePrimitive{ - Color: stringPtr("#FF5FD2"), - }, - KeywordNamespace: ansi.StylePrimitive{ - Color: stringPtr("#FF5F87"), - }, - KeywordType: ansi.StylePrimitive{ - Color: stringPtr("#6E6ED8"), - }, - Operator: ansi.StylePrimitive{ - Color: stringPtr("#EF8080"), - }, - Punctuation: ansi.StylePrimitive{ - Color: stringPtr("#E8E8A8"), - }, - Name: ansi.StylePrimitive{ - Color: stringPtr("#C4C4C4"), - }, - NameBuiltin: ansi.StylePrimitive{ - Color: stringPtr("#FF8EC7"), - }, - NameTag: ansi.StylePrimitive{ - Color: stringPtr("#B083EA"), - }, - NameAttribute: ansi.StylePrimitive{ - Color: stringPtr("#7A7AE6"), - }, - NameClass: ansi.StylePrimitive{ - Color: stringPtr("#F1F1F1"), - Underline: boolPtr(true), - Bold: boolPtr(true), - }, - NameDecorator: ansi.StylePrimitive{ - Color: stringPtr("#FFFF87"), - }, - NameFunction: ansi.StylePrimitive{ - Color: stringPtr("#00D787"), - }, - LiteralNumber: ansi.StylePrimitive{ - Color: stringPtr("#6EEFC0"), - }, - LiteralString: ansi.StylePrimitive{ - Color: stringPtr("#C69669"), - }, - LiteralStringEscape: ansi.StylePrimitive{ - Color: stringPtr("#AFFFD7"), - }, - GenericDeleted: ansi.StylePrimitive{ - Color: stringPtr("#FD5B5B"), - }, - GenericEmph: ansi.StylePrimitive{ - Italic: boolPtr(true), - }, - GenericInserted: ansi.StylePrimitive{ - Color: stringPtr("#00D787"), - }, - GenericStrong: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - GenericSubheading: ansi.StylePrimitive{ - Color: stringPtr("#777777"), - }, - Background: ansi.StylePrimitive{ - BackgroundColor: stringPtr("#373737"), - }, - }, - }, - Table: ansi.StyleTable{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - }, - }, - DefinitionDescription: ansi.StylePrimitive{ - BlockPrefix: "\n🠶 ", - }, - } - - // LightStyleConfig is the default light style. - LightStyleConfig = ansi.StyleConfig{ - Document: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "\n", - BlockSuffix: "\n", - Color: stringPtr("234"), - }, - Margin: uintPtr(defaultMargin), - }, - BlockQuote: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - Indent: uintPtr(1), - IndentToken: stringPtr("│ "), - }, - List: ansi.StyleList{ - LevelIndent: defaultListIndent, - }, - Heading: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - Color: stringPtr("27"), - Bold: boolPtr(true), - }, - }, - H1: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: " ", - Suffix: " ", - Color: stringPtr("228"), - BackgroundColor: stringPtr("63"), - Bold: boolPtr(true), - }, - }, - H2: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "## ", - }, - }, - H3: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "### ", - }, - }, - H4: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "#### ", - }, - }, - H5: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "##### ", - }, - }, - H6: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "###### ", - Bold: boolPtr(false), - }, - }, - Strikethrough: ansi.StylePrimitive{ - CrossedOut: boolPtr(true), - }, - Emph: ansi.StylePrimitive{ - Italic: boolPtr(true), - }, - Strong: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - HorizontalRule: ansi.StylePrimitive{ - Color: stringPtr("249"), - Format: "\n--------\n", - }, - Item: ansi.StylePrimitive{ - BlockPrefix: "• ", - }, - Enumeration: ansi.StylePrimitive{ - BlockPrefix: ". ", - }, - Task: ansi.StyleTask{ - StylePrimitive: ansi.StylePrimitive{}, - Ticked: "[✓] ", - Unticked: "[ ] ", - }, - Link: ansi.StylePrimitive{ - Color: stringPtr("36"), - Underline: boolPtr(true), - }, - LinkText: ansi.StylePrimitive{ - Color: stringPtr("29"), - Bold: boolPtr(true), - }, - Image: ansi.StylePrimitive{ - Color: stringPtr("205"), - Underline: boolPtr(true), - }, - ImageText: ansi.StylePrimitive{ - Color: stringPtr("243"), - Format: "Image: {{.text}} →", - }, - Code: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: " ", - Suffix: " ", - Color: stringPtr("203"), - BackgroundColor: stringPtr("254"), - }, - }, - CodeBlock: ansi.StyleCodeBlock{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("242"), - }, - Margin: uintPtr(defaultMargin), - }, - Chroma: &ansi.Chroma{ - Text: ansi.StylePrimitive{ - Color: stringPtr("#2A2A2A"), - }, - Error: ansi.StylePrimitive{ - Color: stringPtr("#F1F1F1"), - BackgroundColor: stringPtr("#FF5555"), - }, - Comment: ansi.StylePrimitive{ - Color: stringPtr("#8D8D8D"), - }, - CommentPreproc: ansi.StylePrimitive{ - Color: stringPtr("#FF875F"), - }, - Keyword: ansi.StylePrimitive{ - Color: stringPtr("#279EFC"), - }, - KeywordReserved: ansi.StylePrimitive{ - Color: stringPtr("#FF5FD2"), - }, - KeywordNamespace: ansi.StylePrimitive{ - Color: stringPtr("#FB406F"), - }, - KeywordType: ansi.StylePrimitive{ - Color: stringPtr("#7049C2"), - }, - Operator: ansi.StylePrimitive{ - Color: stringPtr("#FF2626"), - }, - Punctuation: ansi.StylePrimitive{ - Color: stringPtr("#FA7878"), - }, - NameBuiltin: ansi.StylePrimitive{ - Color: stringPtr("#0A1BB1"), - }, - NameTag: ansi.StylePrimitive{ - Color: stringPtr("#581290"), - }, - NameAttribute: ansi.StylePrimitive{ - Color: stringPtr("#8362CB"), - }, - NameClass: ansi.StylePrimitive{ - Color: stringPtr("#212121"), - Underline: boolPtr(true), - Bold: boolPtr(true), - }, - NameConstant: ansi.StylePrimitive{ - Color: stringPtr("#581290"), - }, - NameDecorator: ansi.StylePrimitive{ - Color: stringPtr("#A3A322"), - }, - NameFunction: ansi.StylePrimitive{ - Color: stringPtr("#019F57"), - }, - LiteralNumber: ansi.StylePrimitive{ - Color: stringPtr("#22CCAE"), - }, - LiteralString: ansi.StylePrimitive{ - Color: stringPtr("#7E5B38"), - }, - LiteralStringEscape: ansi.StylePrimitive{ - Color: stringPtr("#00AEAE"), - }, - GenericDeleted: ansi.StylePrimitive{ - Color: stringPtr("#FD5B5B"), - }, - GenericEmph: ansi.StylePrimitive{ - Italic: boolPtr(true), - }, - GenericInserted: ansi.StylePrimitive{ - Color: stringPtr("#00D787"), - }, - GenericStrong: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - GenericSubheading: ansi.StylePrimitive{ - Color: stringPtr("#777777"), - }, - Background: ansi.StylePrimitive{ - BackgroundColor: stringPtr("#373737"), - }, - }, - }, - Table: ansi.StyleTable{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - }, - }, - DefinitionDescription: ansi.StylePrimitive{ - BlockPrefix: "\n🠶 ", - }, - } - - // PinkStyleConfig is the default pink style. - PinkStyleConfig = ansi.StyleConfig{ - Document: ansi.StyleBlock{ - Margin: uintPtr(defaultMargin), - }, - BlockQuote: ansi.StyleBlock{ - Indent: uintPtr(1), - IndentToken: stringPtr("│ "), - }, - List: ansi.StyleList{ - LevelIndent: defaultListIndent, - }, - Heading: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - Color: stringPtr("212"), - Bold: boolPtr(true), - }, - }, - H1: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - BlockPrefix: "\n", - Prefix: "", - }, - }, - H2: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "▌ ", - }, - }, - H3: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "┃ ", - }, - }, - H4: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "│ ", - }, - }, - H5: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "┆ ", - }, - }, - H6: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "┊ ", - Bold: boolPtr(false), - }, - }, - Text: ansi.StylePrimitive{}, - Strikethrough: ansi.StylePrimitive{ - CrossedOut: boolPtr(true), - }, - Emph: ansi.StylePrimitive{ - Italic: boolPtr(true), - }, - Strong: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - HorizontalRule: ansi.StylePrimitive{ - Color: stringPtr("212"), - Format: "\n──────\n", - }, - Item: ansi.StylePrimitive{ - BlockPrefix: "• ", - }, - Enumeration: ansi.StylePrimitive{ - BlockPrefix: ". ", - }, - Task: ansi.StyleTask{ - Ticked: "[✓] ", - Unticked: "[ ] ", - }, - Link: ansi.StylePrimitive{ - Color: stringPtr("99"), - Underline: boolPtr(true), - }, - LinkText: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - Image: ansi.StylePrimitive{ - Underline: boolPtr(true), - }, - ImageText: ansi.StylePrimitive{ - Format: "Image: {{.text}}", - }, - Code: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("212"), - BackgroundColor: stringPtr("236"), - Prefix: " ", - Suffix: " ", - }, - }, - Table: ansi.StyleTable{}, - DefinitionList: ansi.StyleBlock{}, - DefinitionTerm: ansi.StylePrimitive{}, - DefinitionDescription: ansi.StylePrimitive{ - BlockPrefix: "\n🠶 ", - }, - HTMLBlock: ansi.StyleBlock{}, - HTMLSpan: ansi.StyleBlock{}, - } - - // NoTTYStyleConfig is the default notty style. - NoTTYStyleConfig = ASCIIStyleConfig - - // DefaultStyles are the default styles. - DefaultStyles = map[string]*ansi.StyleConfig{ - AsciiStyle: &ASCIIStyleConfig, - DarkStyle: &DarkStyleConfig, - LightStyle: &LightStyleConfig, - NoTTYStyle: &NoTTYStyleConfig, - PinkStyle: &PinkStyleConfig, - - // Popular themes - DraculaStyle: &DraculaStyleConfig, - TokyoNightStyle: &TokyoNightStyleConfig, - } -) - -func boolPtr(b bool) *bool { return &b } -func stringPtr(s string) *string { return &s } -func uintPtr(u uint) *uint { return &u } diff --git a/vendor/github.com/charmbracelet/glamour/styles/tokyo-night.go b/vendor/github.com/charmbracelet/glamour/styles/tokyo-night.go deleted file mode 100644 index a7c1d793..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/tokyo-night.go +++ /dev/null @@ -1,209 +0,0 @@ -package styles - -import "github.com/charmbracelet/glamour/ansi" - -// TokyoNightStyleConfig is the tokyo night style. -var TokyoNightStyleConfig = ansi.StyleConfig{ - Document: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockPrefix: "\n", - BlockSuffix: "\n", - Color: stringPtr("#a9b1d6"), - }, - Margin: uintPtr(defaultMargin), - }, - BlockQuote: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - Indent: uintPtr(1), - IndentToken: stringPtr("│ "), - }, - List: ansi.StyleList{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("#a9b1d6"), - }, - }, - LevelIndent: defaultListIndent, - }, - Heading: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - BlockSuffix: "\n", - Color: stringPtr("#bb9af7"), - Bold: boolPtr(true), - }, - }, - H1: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "# ", - Bold: boolPtr(true), - }, - }, - H2: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "## ", - }, - }, - H3: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "### ", - }, - }, - H4: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "#### ", - }, - }, - H5: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "##### ", - }, - }, - H6: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Prefix: "###### ", - }, - }, - Strikethrough: ansi.StylePrimitive{ - CrossedOut: boolPtr(true), - }, - Emph: ansi.StylePrimitive{ - Italic: boolPtr(true), - }, - Strong: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - HorizontalRule: ansi.StylePrimitive{ - Color: stringPtr("#565f89"), - Format: "\n--------\n", - }, - Item: ansi.StylePrimitive{ - BlockPrefix: "• ", - }, - Enumeration: ansi.StylePrimitive{ - BlockPrefix: ". ", - Color: stringPtr("#7aa2f7"), - }, - Task: ansi.StyleTask{ - StylePrimitive: ansi.StylePrimitive{}, - Ticked: "[✓] ", - Unticked: "[ ] ", - }, - Link: ansi.StylePrimitive{ - Color: stringPtr("#7aa2f7"), - Underline: boolPtr(true), - }, - LinkText: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - Image: ansi.StylePrimitive{ - Color: stringPtr("#7aa2f7"), - Underline: boolPtr(true), - }, - ImageText: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - Format: "Image: {{.text}} →", - }, - Code: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("#9ece6a"), - }, - }, - CodeBlock: ansi.StyleCodeBlock{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr("#ff9e64"), - }, - Margin: uintPtr(defaultMargin), - }, - Chroma: &ansi.Chroma{ - Text: ansi.StylePrimitive{ - Color: stringPtr("#a9b1d6"), - }, - Error: ansi.StylePrimitive{ - Color: stringPtr("#a9b1d6"), - BackgroundColor: stringPtr("#f7768e"), - }, - Comment: ansi.StylePrimitive{ - Color: stringPtr("#565f89"), - }, - CommentPreproc: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - Keyword: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - KeywordReserved: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - KeywordNamespace: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - KeywordType: ansi.StylePrimitive{ - Color: stringPtr("#7aa2f7"), - }, - Operator: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - Punctuation: ansi.StylePrimitive{ - Color: stringPtr("#a9b1d6"), - }, - Name: ansi.StylePrimitive{ - Color: stringPtr("#7aa2f7"), - }, - NameConstant: ansi.StylePrimitive{ - Color: stringPtr("#bb9af7"), - }, - NameBuiltin: ansi.StylePrimitive{ - Color: stringPtr("#7aa2f7"), - }, - NameTag: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - NameAttribute: ansi.StylePrimitive{ - Color: stringPtr("#9ece6a"), - }, - NameClass: ansi.StylePrimitive{ - Color: stringPtr("#7aa2f7"), - }, - NameDecorator: ansi.StylePrimitive{ - Color: stringPtr("#9ece6a"), - }, - NameFunction: ansi.StylePrimitive{ - Color: stringPtr("#9ece6a"), - }, - LiteralNumber: ansi.StylePrimitive{}, - LiteralString: ansi.StylePrimitive{ - Color: stringPtr("#e0af68"), - }, - LiteralStringEscape: ansi.StylePrimitive{ - Color: stringPtr("#2ac3de"), - }, - GenericDeleted: ansi.StylePrimitive{ - Color: stringPtr("#f7768e"), - }, - GenericEmph: ansi.StylePrimitive{ - Italic: boolPtr(true), - }, - GenericInserted: ansi.StylePrimitive{ - Color: stringPtr("#9ece6a"), - }, - GenericStrong: ansi.StylePrimitive{ - Bold: boolPtr(true), - }, - GenericSubheading: ansi.StylePrimitive{ - Color: stringPtr("#bb9af7"), - }, - Background: ansi.StylePrimitive{ - BackgroundColor: stringPtr("#1a1b26"), - }, - }, - }, - Table: ansi.StyleTable{ - StyleBlock: ansi.StyleBlock{ - StylePrimitive: ansi.StylePrimitive{}, - }, - }, - DefinitionDescription: ansi.StylePrimitive{ - BlockPrefix: "\n🠶 ", - }, -} diff --git a/vendor/github.com/charmbracelet/glamour/styles/tokyo_night.json b/vendor/github.com/charmbracelet/glamour/styles/tokyo_night.json deleted file mode 100644 index 8016b096..00000000 --- a/vendor/github.com/charmbracelet/glamour/styles/tokyo_night.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "document": { - "block_prefix": "\n", - "block_suffix": "\n", - "color": "#a9b1d6", - "margin": 2 - }, - "block_quote": { - "indent": 1, - "indent_token": "│ " - }, - "paragraph": {}, - "list": { - "color": "#a9b1d6", - "level_indent": 2 - }, - "heading": { - "block_suffix": "\n", - "color": "#bb9af7", - "bold": true - }, - "h1": { - "prefix": "# ", - "bold": true - }, - "h2": { - "prefix": "## " - }, - "h3": { - "prefix": "### " - }, - "h4": { - "prefix": "#### " - }, - "h5": { - "prefix": "##### " - }, - "h6": { - "prefix": "###### " - }, - "text": {}, - "strikethrough": { - "crossed_out": true - }, - "emph": { - "italic": true - }, - "strong": { - "bold": true - }, - "hr": { - "color": "#565f89", - "format": "\n--------\n" - }, - "item": { - "block_prefix": "• " - }, - "enumeration": { - "block_prefix": ". ", - "color": "#7aa2f7" - }, - "task": { - "ticked": "[✓] ", - "unticked": "[ ] " - }, - "link": { - "color": "#7aa2f7", - "underline": true - }, - "link_text": { - "color": "#2ac3de" - }, - "image": { - "color": "#7aa2f7", - "underline": true - }, - "image_text": { - "color": "#2ac3de", - "format": "Image: {{.text}} →" - }, - "code": { - "color": "#9ece6a" - }, - "code_block": { - "color": "#ff9e64", - "margin": 2, - "chroma": { - "text": { - "color": "#a9b1d6" - }, - "error": { - "color": "#a9b1d6", - "background_color": "#f7768e" - }, - "comment": { - "color": "#565f89" - }, - "comment_preproc": { - "color": "#2ac3de" - }, - "keyword": { - "color": "#2ac3de" - }, - "keyword_reserved": { - "color": "#2ac3de" - }, - "keyword_namespace": { - "color": "#2ac3de" - }, - "keyword_type": { - "color": "#7aa2f7" - }, - "operator": { - "color": "#2ac3de" - }, - "punctuation": { - "color": "#a9b1d6" - }, - "name": { - "color": "#7aa2f7" - }, - "name_builtin": { - "color": "#7aa2f7" - }, - "name_tag": { - "color": "#2ac3de" - }, - "name_attribute": { - "color": "#9ece6a" - }, - "name_class": { - "color": "#7aa2f7" - }, - "name_constant": { - "color": "#bb9af7" - }, - "name_decorator": { - "color": "#9ece6a" - }, - "name_exception": {}, - "name_function": { - "color": "#9ece6a" - }, - "name_other": {}, - "literal": {}, - "literal_number": {}, - "literal_date": {}, - "literal_string": { - "color": "#e0af68" - }, - "literal_string_escape": { - "color": "#2ac3de" - }, - "generic_deleted": { - "color": "#f7768e" - }, - "generic_emph": { - "italic": true - }, - "generic_inserted": { - "color": "#9ece6a" - }, - "generic_strong": { - "bold": true - }, - "generic_subheading": { - "color": "#bb9af7" - }, - "background": { - "background_color": "#1a1b26" - } - } - }, - "table": {}, - "definition_list": {}, - "definition_term": {}, - "definition_description": { - "block_prefix": "\n🠶 " - }, - "html_block": {}, - "html_span": {} -} diff --git a/vendor/github.com/charmbracelet/huh/.gitattributes b/vendor/github.com/charmbracelet/huh/.gitattributes deleted file mode 100644 index 5f9b1ec3..00000000 --- a/vendor/github.com/charmbracelet/huh/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -*.gif filter=lfs diff=lfs merge=lfs -text -*.png filter=lfs diff=lfs merge=lfs -text diff --git a/vendor/github.com/charmbracelet/huh/.gitignore b/vendor/github.com/charmbracelet/huh/.gitignore deleted file mode 100644 index ba65d3b0..00000000 --- a/vendor/github.com/charmbracelet/huh/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work - -# Debugging -debug.log diff --git a/vendor/github.com/charmbracelet/huh/.golangci.yml b/vendor/github.com/charmbracelet/huh/.golangci.yml deleted file mode 100644 index 7c0a115e..00000000 --- a/vendor/github.com/charmbracelet/huh/.golangci.yml +++ /dev/null @@ -1,49 +0,0 @@ -version: "2" -run: - tests: false -linters: - enable: - - bodyclose - - exhaustive - - goconst - - godot - - godox - - gomoddirectives - - goprintffuncname - - gosec - - misspell - - nakedret - - nestif - - nilerr - - noctx - - nolintlint - - prealloc - - revive - - rowserrcheck - - sqlclosecheck - - tparallel - - unconvert - - unparam - - whitespace - - wrapcheck - exclusions: - generated: lax - presets: - - common-false-positives - paths: - - third_party$ - - builtin$ - - examples$ -issues: - max-issues-per-linter: 0 - max-same-issues: 0 -formatters: - enable: - - gofumpt - - goimports - exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ diff --git a/vendor/github.com/charmbracelet/huh/LICENSE b/vendor/github.com/charmbracelet/huh/LICENSE deleted file mode 100644 index 2a08f15d..00000000 --- a/vendor/github.com/charmbracelet/huh/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Charm - -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/charmbracelet/huh/Makefile b/vendor/github.com/charmbracelet/huh/Makefile deleted file mode 100644 index d3f18ae9..00000000 --- a/vendor/github.com/charmbracelet/huh/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -.PHONY: spinner - -$(V).SILENT: -test: - go test ./... - -spinner: - cd spinner/examples/loading && go run . - -burger: - cd examples/burger && go run . - -theme: - cd examples/theme && go run . - -gh: - cd examples/gh && go run . diff --git a/vendor/github.com/charmbracelet/huh/README.md b/vendor/github.com/charmbracelet/huh/README.md deleted file mode 100644 index 5694c791..00000000 --- a/vendor/github.com/charmbracelet/huh/README.md +++ /dev/null @@ -1,512 +0,0 @@ -# Huh? - -

- Hey there! I’m Glenn! -

- Latest Release - Go Docs - Build Status -

- -A simple, powerful library for building interactive forms and prompts in the terminal. - -Running a burger form - -`huh?` is easy to use in a standalone fashion, can be -[integrated into a Bubble Tea application](#what-about-bubble-tea), and contains -a first-class [accessible mode](#accessibility) for screen readers. - -The above example is running from a single Go program ([source](./examples/burger/main.go)). - -## Tutorial - -Let’s build a form for ordering burgers. To start, we’ll import the library and -define a few variables where we'll store answers. - -```go -package main - -import "github.com/charmbracelet/huh" - -var ( - burger string - toppings []string - sauceLevel int - name string - instructions string - discount bool -) -``` - -`huh?` separates forms into groups (you can think of groups as pages). Groups -are made of fields (e.g. `Select`, `Input`, `Text`). We will set up three -groups for the customer to fill out. - -```go -form := huh.NewForm( - huh.NewGroup( - // Ask the user for a base burger and toppings. - huh.NewSelect[string](). - Title("Choose your burger"). - Options( - huh.NewOption("Charmburger Classic", "classic"), - huh.NewOption("Chickwich", "chickwich"), - huh.NewOption("Fishburger", "fishburger"), - huh.NewOption("Charmpossible™ Burger", "charmpossible"), - ). - Value(&burger), // store the chosen option in the "burger" variable - - // Let the user select multiple toppings. - huh.NewMultiSelect[string](). - Title("Toppings"). - Options( - huh.NewOption("Lettuce", "lettuce").Selected(true), - huh.NewOption("Tomatoes", "tomatoes").Selected(true), - huh.NewOption("Jalapeños", "jalapeños"), - huh.NewOption("Cheese", "cheese"), - huh.NewOption("Vegan Cheese", "vegan cheese"), - huh.NewOption("Nutella", "nutella"), - ). - Limit(4). // there’s a 4 topping limit! - Value(&toppings), - - // Option values in selects and multi selects can be any type you - // want. We’ve been recording strings above, but here we’ll store - // answers as integers. Note the generic "[int]" directive below. - huh.NewSelect[int](). - Title("How much Charm Sauce do you want?"). - Options( - huh.NewOption("None", 0), - huh.NewOption("A little", 1), - huh.NewOption("A lot", 2), - ). - Value(&sauceLevel), - ), - - // Gather some final details about the order. - huh.NewGroup( - huh.NewInput(). - Title("What’s your name?"). - Value(&name). - // Validating fields is easy. The form will mark erroneous fields - // and display error messages accordingly. - Validate(func(str string) error { - if str == "Frank" { - return errors.New("Sorry, we don’t serve customers named Frank.") - } - return nil - }), - - huh.NewText(). - Title("Special Instructions"). - CharLimit(400). - Value(&instructions), - - huh.NewConfirm(). - Title("Would you like 15% off?"). - Value(&discount), - ), -) -``` - -Finally, run the form: - -```go -err := form.Run() -if err != nil { - log.Fatal(err) -} - -if !discount { - fmt.Println("What? You didn’t take the discount?!") -} -``` - -And that’s it! For more info see [the full source][burgersource] for this -example as well as [the docs][docs]. - -If you need more dynamic forms that change based on input from previous fields, -check out the [dynamic forms](#dynamic-forms) example. - -[burgersource]: ./examples/burger/main.go -[docs]: https://pkg.go.dev/github.com/charmbracelet/huh?tab=doc - -## Field Reference - -- [`Input`](#input): single line text input -- [`Text`](#text): multi-line text input -- [`Select`](#select): select an option from a list -- [`MultiSelect`](#multiple-select): select multiple options from a list -- [`Confirm`](#confirm): confirm an action (yes or no) - -> [!TIP] -> Just want to prompt the user with a single field? Each field has a `Run` -> method that can be used as a shorthand for gathering quick and easy input. - -```go -var name string - -huh.NewInput(). - Title("What’s your name?"). - Value(&name). - Run() // this is blocking... - -fmt.Printf("Hey, %s!\n", name) -``` - -### Input - -Prompt the user for a single line of text. - -Input field - -```go -huh.NewInput(). - Title("What’s for lunch?"). - Prompt("?"). - Validate(isFood). - Value(&lunch) -``` - -### Text - -Prompt the user for multiple lines of text. - -Text field - -```go -huh.NewText(). - Title("Tell me a story."). - Validate(checkForPlagiarism). - Value(&story) -``` - -### Select - -Prompt the user to select a single option from a list. - -Select field - -```go -huh.NewSelect[string](). - Title("Pick a country."). - Options( - huh.NewOption("United States", "US"), - huh.NewOption("Germany", "DE"), - huh.NewOption("Brazil", "BR"), - huh.NewOption("Canada", "CA"), - ). - Value(&country) -``` - -### Multiple Select - -Prompt the user to select multiple (zero or more) options from a list. - -Multiselect field - -```go -huh.NewMultiSelect[string](). - Options( - huh.NewOption("Lettuce", "Lettuce").Selected(true), - huh.NewOption("Tomatoes", "Tomatoes").Selected(true), - huh.NewOption("Charm Sauce", "Charm Sauce"), - huh.NewOption("Jalapeños", "Jalapeños"), - huh.NewOption("Cheese", "Cheese"), - huh.NewOption("Vegan Cheese", "Vegan Cheese"), - huh.NewOption("Nutella", "Nutella"), - ). - Title("Toppings"). - Limit(4). - Value(&toppings) -``` - -### Confirm - -Prompt the user to confirm (Yes or No). - -Confirm field - -```go -huh.NewConfirm(). - Title("Are you sure?"). - Affirmative("Yes!"). - Negative("No."). - Value(&confirm) -``` - -## Accessibility - -`huh?` has a special rendering option designed specifically for screen readers. -You can enable it with `form.WithAccessible(true)`. - -> [!TIP] -> We recommend setting this through an environment variable or configuration -> option to allow the user to control accessibility. - -```go -accessibleMode := os.Getenv("ACCESSIBLE") != "" -form.WithAccessible(accessibleMode) -``` - -Accessible forms will drop TUIs in favor of standard prompts, providing better -dictation and feedback of the information on screen for the visually impaired. - -Accessible cuisine form - -## Themes - -`huh?` contains a powerful theme abstraction. Supply your own custom theme or -choose from one of the five predefined themes: - -- `Charm` -- `Dracula` -- `Catppuccin` -- `Base 16` -- `Default` - -
-

- Charm-themed form - Dracula-themed form - Catppuccin-themed form - Base 16-themed form - Default-themed form -

- -Themes can take advantage of the full range of -[Lip Gloss][lipgloss] style options. For a high level theme reference see -[the docs](https://pkg.go.dev/github.com/charmbracelet/huh#Theme). - -[lipgloss]: https://github.com/charmbracelet/lipgloss - -## Dynamic Forms - -`huh?` forms can be as dynamic as your heart desires. Simply replace properties -with their equivalent `Func` to recompute the properties value every time a -different part of your form changes. - -Here’s how you would build a simple country + state / province picker. - -First, define some variables that we’ll use to store the user selection. - -```go -var country string -var state string -``` - -Define your country select as you normally would: - -```go -huh.NewSelect[string](). - Options(huh.NewOptions("United States", "Canada", "Mexico")...). - Value(&country). - Title("Country"). -``` - -Define your state select with `TitleFunc` and `OptionsFunc` instead of `Title` -and `Options`. This will allow you to change the title and options based on the -selection of the previous field, i.e. `country`. - -To do this, we provide a `func() string` and a `binding any` to `TitleFunc`. The -function defines what to show for the title and the binding specifies what value -needs to change for the function to recompute. So if `country` changes (e.g. the -user changes the selection) we will recompute the function. - -For `OptionsFunc`, we provide a `func() []Option[string]` and a `binding any`. -We’ll fetch the country’s states, provinces, or territories from an API. `huh` -will automatically handle caching for you. - -> [!IMPORTANT] -> We have to pass `&country` as the binding to recompute the function only when -> `country` changes, otherwise we will hit the API too often. - -```go -huh.NewSelect[string](). - Value(&state). - Height(8). - TitleFunc(func() string { - switch country { - case "United States": - return "State" - case "Canada": - return "Province" - default: - return "Territory" - } - }, &country). - OptionsFunc(func() []huh.Option[string] { - opts := fetchStatesForCountry(country) - return huh.NewOptions(opts...) - }, &country), -``` - -Lastly, run the `form` with these inputs. - -```go -err := form.Run() -if err != nil { - log.Fatal(err) -} -``` - -Country / State form with dynamic inputs running. - -## Bonus: Spinner - -`huh?` ships with a standalone spinner package. It’s useful for indicating -background activity after a form is submitted. - -Spinner while making a burger - -Create a new spinner, set a title, set the action (or provide a `Context`), and run the spinner: - - - - - - - - - -
Action Style Context Style
- -```go -err := spinner.New(). - Title("Making your burger..."). - Action(makeBurger). - Run() - -fmt.Println("Order up!") -``` - - - -```go -go makeBurger() - -err := spinner.New(). - Type(spinner.Line). - Title("Making your burger..."). - Context(ctx). - Run() - -fmt.Println("Order up!") -``` - -
- -For more on Spinners see the [spinner examples](./spinner/examples) and -[the spinner docs](https://pkg.go.dev/github.com/charmbracelet/huh/spinner). - -## What about Bubble Tea? - -Bubbletea + Huh? - -In addition to its standalone mode, `huh?` has first-class support for -[Bubble Tea][tea] and can be easily integrated into Bubble Tea applications. -It’s incredibly useful in portions of your Bubble Tea application that need -form-like input. - -Bubble Tea embedded form example - -A `huh.Form` is merely a `tea.Model`, so you can use it just as -you would any other [Bubble](https://github.com/charmbracelet/bubbles). - -```go -type Model struct { - form *huh.Form // huh.Form is just a tea.Model -} - -func NewModel() Model { - return Model{ - form: huh.NewForm( - huh.NewGroup( - huh.NewSelect[string](). - Key("class"). - Options(huh.NewOptions("Warrior", "Mage", "Rogue")...). - Title("Choose your class"), - - huh.NewSelect[int](). - Key("level"). - Options(huh.NewOptions(1, 20, 9999)...). - Title("Choose your level"), - ), - ) - } -} - -func (m Model) Init() tea.Cmd { - return m.form.Init() -} - -func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - // ... - - form, cmd := m.form.Update(msg) - if f, ok := form.(*huh.Form); ok { - m.form = f - } - - return m, cmd -} - -func (m Model) View() string { - if m.form.State == huh.StateCompleted { - class := m.form.GetString("class") - level := m.form.GetInt("level") - return fmt.Sprintf("You selected: %s, Lvl. %d", class, level) - } - return m.form.View() -} - -``` - -For more info in using `huh?` in Bubble Tea applications see [the full Bubble -Tea example][example]. - -[tea]: https://github.com/charmbracelet/bubbletea -[bubbles]: https://github.com/charmbracelet/bubbles -[example]: https://github.com/charmbracelet/huh/blob/main/examples/bubbletea/main.go - -## `Huh?` in the Wild - -For some `Huh?` programs in production, see: - -* [glyphs](https://github.com/maaslalani/glyphs): a unicode symbol picker -* [meteor](https://github.com/stefanlogue/meteor): a highly customisable conventional commit message tool -* [freeze](https://github.com/charmbracelet/freeze): a tool for generating images of code and terminal output -* [gum](https://github.com/charmbracelet/gum): a tool for glamorous shell scripts -* [savvy](https://github.com/getsavvyinc/savvy-cli): the easiest way to create, share, and run runbooks in the terminal - -## Contributing - -See [contributing][contribute]. - -[contribute]: https://github.com/charmbracelet/huh/contribute - -## Feedback - -We’d love to hear your thoughts on this project. Feel free to drop us a note! - -- [Twitter](https://twitter.com/charmcli) -- [The Fediverse](https://mastodon.social/@charmcli) -- [Discord](https://charm.sh/chat) - -## Acknowledgments - -`huh?` is inspired by the wonderful [Survey][survey] library by Alec Aivazis. - -[survey]: https://github.com/AlecAivazis/survey - -## License - -[MIT](https://github.com/charmbracelet/bubbletea/raw/master/LICENSE) - ---- - -Part of [Charm](https://charm.sh). - -The Charm logo - -Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة diff --git a/vendor/github.com/charmbracelet/huh/accessor.go b/vendor/github.com/charmbracelet/huh/accessor.go deleted file mode 100644 index 95b4ba9e..00000000 --- a/vendor/github.com/charmbracelet/huh/accessor.go +++ /dev/null @@ -1,44 +0,0 @@ -package huh - -// Accessor give read/write access to field values. -type Accessor[T any] interface { - Get() T - Set(value T) -} - -// EmbeddedAccessor is a basic accessor, acting as the default one for fields. -type EmbeddedAccessor[T any] struct { - value T -} - -// Get gets the value. -func (a *EmbeddedAccessor[T]) Get() T { - return a.value -} - -// Set sets the value. -func (a *EmbeddedAccessor[T]) Set(value T) { - a.value = value -} - -// PointerAccessor allows field value to be exposed as a pointed variable. -type PointerAccessor[T any] struct { - value *T -} - -// NewPointerAccessor returns a new pointer accessor. -func NewPointerAccessor[T any](value *T) *PointerAccessor[T] { - return &PointerAccessor[T]{ - value: value, - } -} - -// Get gets the value. -func (a *PointerAccessor[T]) Get() T { - return *a.value -} - -// Set sets the value. -func (a *PointerAccessor[T]) Set(value T) { - *a.value = value -} diff --git a/vendor/github.com/charmbracelet/huh/clamp.go b/vendor/github.com/charmbracelet/huh/clamp.go deleted file mode 100644 index 185e56e5..00000000 --- a/vendor/github.com/charmbracelet/huh/clamp.go +++ /dev/null @@ -1,8 +0,0 @@ -package huh - -func clamp(n, low, high int) int { - if low > high { - low, high = high, low - } - return min(high, max(low, n)) -} diff --git a/vendor/github.com/charmbracelet/huh/eval.go b/vendor/github.com/charmbracelet/huh/eval.go deleted file mode 100644 index b9e808dd..00000000 --- a/vendor/github.com/charmbracelet/huh/eval.go +++ /dev/null @@ -1,84 +0,0 @@ -package huh - -import ( - "time" - - "github.com/mitchellh/hashstructure/v2" -) - -// Eval is an evaluatable value, it stores a cached value and a function to -// recompute it. It's bindings are what we check to see if we need to recompute -// the value. -// -// By default it is also cached. -type Eval[T any] struct { - val T - fn func() T - - bindings any - bindingsHash uint64 - cache map[uint64]T - - loading bool - loadingStart time.Time -} - -const spinnerShowThreshold = 25 * time.Millisecond - -func hash(val any) uint64 { - hash, _ := hashstructure.Hash(val, hashstructure.FormatV2, nil) - return hash -} - -func (e *Eval[T]) shouldUpdate() (bool, uint64) { - if e.fn == nil { - return false, 0 - } - newHash := hash(e.bindings) - return e.bindingsHash != newHash, newHash -} - -func (e *Eval[T]) loadFromCache() bool { - val, ok := e.cache[e.bindingsHash] - if ok { - e.loading = false - e.val = val - } - return ok -} - -func (e *Eval[T]) update(val T) { - e.val = val - e.cache[e.bindingsHash] = val - e.loading = false -} - -type updateTitleMsg struct { - id int - hash uint64 - title string -} - -type updateDescriptionMsg struct { - id int - hash uint64 - description string -} - -type updatePlaceholderMsg struct { - id int - hash uint64 - placeholder string -} - -type updateSuggestionsMsg struct { - id int - hash uint64 - suggestions []string -} - -type updateOptionsMsg[T comparable] struct { - id int - hash uint64 - options []Option[T] -} diff --git a/vendor/github.com/charmbracelet/huh/field_confirm.go b/vendor/github.com/charmbracelet/huh/field_confirm.go deleted file mode 100644 index 1c4b572d..00000000 --- a/vendor/github.com/charmbracelet/huh/field_confirm.go +++ /dev/null @@ -1,385 +0,0 @@ -package huh - -import ( - "cmp" - "io" - "os" - "strings" - - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/accessibility" - "github.com/charmbracelet/lipgloss" -) - -// Confirm is a form confirm field. -type Confirm struct { - accessor Accessor[bool] - key string - id int - - // customization - title Eval[string] - description Eval[string] - affirmative string - negative string - - // error handling - validate func(bool) error - err error - - // state - focused bool - - // options - width int - height int - inline bool - accessible bool - theme *Theme - keymap ConfirmKeyMap - buttonAlignment lipgloss.Position -} - -// NewConfirm returns a new confirm field. -func NewConfirm() *Confirm { - return &Confirm{ - accessor: &EmbeddedAccessor[bool]{}, - id: nextID(), - title: Eval[string]{cache: make(map[uint64]string)}, - description: Eval[string]{cache: make(map[uint64]string)}, - affirmative: "Yes", - negative: "No", - validate: func(bool) error { return nil }, - buttonAlignment: lipgloss.Center, - } -} - -// Validate sets the validation function of the confirm field. -func (c *Confirm) Validate(validate func(bool) error) *Confirm { - c.validate = validate - return c -} - -// Error returns the error of the confirm field. -func (c *Confirm) Error() error { - return c.err -} - -// Skip returns whether the confirm should be skipped or should be blocking. -func (*Confirm) Skip() bool { - return false -} - -// Zoom returns whether the input should be zoomed. -func (*Confirm) Zoom() bool { - return false -} - -// Affirmative sets the affirmative value of the confirm field. -func (c *Confirm) Affirmative(affirmative string) *Confirm { - c.affirmative = affirmative - return c -} - -// Negative sets the negative value of the confirm field. -func (c *Confirm) Negative(negative string) *Confirm { - c.negative = negative - return c -} - -// Value sets the value of the confirm field. -func (c *Confirm) Value(value *bool) *Confirm { - return c.Accessor(NewPointerAccessor(value)) -} - -// Accessor sets the accessor of the confirm field. -func (c *Confirm) Accessor(accessor Accessor[bool]) *Confirm { - c.accessor = accessor - return c -} - -// Key sets the key of the confirm field. -func (c *Confirm) Key(key string) *Confirm { - c.key = key - return c -} - -// Title sets the title of the confirm field. -func (c *Confirm) Title(title string) *Confirm { - c.title.val = title - c.title.fn = nil - return c -} - -// TitleFunc sets the title func of the confirm field. -func (c *Confirm) TitleFunc(f func() string, bindings any) *Confirm { - c.title.fn = f - c.title.bindings = bindings - return c -} - -// Description sets the description of the confirm field. -func (c *Confirm) Description(description string) *Confirm { - c.description.val = description - c.description.fn = nil - return c -} - -// DescriptionFunc sets the description function of the confirm field. -func (c *Confirm) DescriptionFunc(f func() string, bindings any) *Confirm { - c.description.fn = f - c.description.bindings = bindings - return c -} - -// Inline sets whether the field should be inline. -func (c *Confirm) Inline(inline bool) *Confirm { - c.inline = inline - return c -} - -// Focus focuses the confirm field. -func (c *Confirm) Focus() tea.Cmd { - c.focused = true - return nil -} - -// Blur blurs the confirm field. -func (c *Confirm) Blur() tea.Cmd { - c.focused = false - c.err = c.validate(c.accessor.Get()) - return nil -} - -// KeyBinds returns the help message for the confirm field. -func (c *Confirm) KeyBinds() []key.Binding { - return []key.Binding{c.keymap.Toggle, c.keymap.Prev, c.keymap.Submit, c.keymap.Next, c.keymap.Accept, c.keymap.Reject} -} - -// Init initializes the confirm field. -func (c *Confirm) Init() tea.Cmd { - return nil -} - -// Update updates the confirm field. -func (c *Confirm) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmds []tea.Cmd - - switch msg := msg.(type) { - case updateFieldMsg: - if ok, hash := c.title.shouldUpdate(); ok { - c.title.bindingsHash = hash - if !c.title.loadFromCache() { - c.title.loading = true - cmds = append(cmds, func() tea.Msg { - return updateTitleMsg{id: c.id, title: c.title.fn(), hash: hash} - }) - } - } - if ok, hash := c.description.shouldUpdate(); ok { - c.description.bindingsHash = hash - if !c.description.loadFromCache() { - c.description.loading = true - cmds = append(cmds, func() tea.Msg { - return updateDescriptionMsg{id: c.id, description: c.description.fn(), hash: hash} - }) - } - } - - case updateTitleMsg: - if msg.id == c.id && msg.hash == c.title.bindingsHash { - c.title.val = msg.title - c.title.loading = false - } - case updateDescriptionMsg: - if msg.id == c.id && msg.hash == c.description.bindingsHash { - c.description.val = msg.description - c.description.loading = false - } - case tea.KeyMsg: - c.err = nil - switch { - case key.Matches(msg, c.keymap.Toggle): - if c.negative == "" { - break - } - c.accessor.Set(!c.accessor.Get()) - case key.Matches(msg, c.keymap.Prev): - cmds = append(cmds, PrevField) - case key.Matches(msg, c.keymap.Next, c.keymap.Submit): - cmds = append(cmds, NextField) - case key.Matches(msg, c.keymap.Accept): - c.accessor.Set(true) - cmds = append(cmds, NextField) - case key.Matches(msg, c.keymap.Reject): - c.accessor.Set(false) - cmds = append(cmds, NextField) - } - } - - return c, tea.Batch(cmds...) -} - -func (c *Confirm) activeStyles() *FieldStyles { - theme := c.theme - if theme == nil { - theme = ThemeCharm() - } - if c.focused { - return &theme.Focused - } - return &theme.Blurred -} - -// View renders the confirm field. -func (c *Confirm) View() string { - styles := c.activeStyles() - maxWidth := c.width - styles.Base.GetHorizontalFrameSize() - - var wroteHeader bool - var sb strings.Builder - if c.title.val != "" { - sb.WriteString(styles.Title.Render(wrap(c.title.val, maxWidth))) - wroteHeader = true - } - if c.err != nil { - sb.WriteString(styles.ErrorIndicator.String()) - wroteHeader = true - } - - if c.description.val != "" { - description := styles.Description.Render(wrap(c.description.val, maxWidth)) - if !c.inline && (c.description.val != "" || c.description.fn != nil) { - sb.WriteString("\n") - } - sb.WriteString(description) - wroteHeader = true - } - - if !c.inline && wroteHeader { - sb.WriteString("\n") - sb.WriteString("\n") - } - - var negative string - var affirmative string - if c.negative != "" { - if c.accessor.Get() { - affirmative = styles.FocusedButton.Render(c.affirmative) - negative = styles.BlurredButton.Render(c.negative) - } else { - affirmative = styles.BlurredButton.Render(c.affirmative) - negative = styles.FocusedButton.Render(c.negative) - } - c.keymap.Reject.SetHelp("n", c.negative) - } else { - affirmative = styles.FocusedButton.Render(c.affirmative) - c.keymap.Reject.SetEnabled(false) - } - - c.keymap.Accept.SetHelp("y", c.affirmative) - - buttonsRow := lipgloss.JoinHorizontal(c.buttonAlignment, affirmative, negative) - - promptWidth := lipgloss.Width(sb.String()) - buttonsWidth := lipgloss.Width(buttonsRow) - - renderWidth := promptWidth - if buttonsWidth > renderWidth { - renderWidth = buttonsWidth - } - - style := lipgloss.NewStyle().Width(renderWidth).Align(c.buttonAlignment) - - sb.WriteString(style.Render(buttonsRow)) - return styles.Base.Width(c.width).Height(c.height). - Render(sb.String()) -} - -// Run runs the confirm field in accessible mode. -func (c *Confirm) Run() error { - if c.accessible { - return c.runAccessible(os.Stdout, os.Stdin) - } - return Run(c) -} - -// runAccessible runs the confirm field in accessible mode. -func (c *Confirm) runAccessible(w io.Writer, r io.Reader) error { - styles := c.activeStyles() - defaultValue := c.GetValue().(bool) - opts := "[y/N]" - if defaultValue { - opts = "[Y/n]" - } - prompt := styles.Title. - PaddingRight(1). - Render(cmp.Or(c.title.val, "Choose"), opts) - c.accessor.Set(accessibility.PromptBool(w, r, prompt, defaultValue)) - return nil -} - -func (c *Confirm) String() string { - if c.accessor.Get() { - return c.affirmative - } - return c.negative -} - -// WithTheme sets the theme of the confirm field. -func (c *Confirm) WithTheme(theme *Theme) Field { - if c.theme != nil { - return c - } - c.theme = theme - return c -} - -// WithKeyMap sets the keymap of the confirm field. -func (c *Confirm) WithKeyMap(k *KeyMap) Field { - c.keymap = k.Confirm - return c -} - -// WithAccessible sets the accessible mode of the confirm field. -func (c *Confirm) WithAccessible(accessible bool) Field { - c.accessible = accessible - return c -} - -// WithWidth sets the width of the confirm field. -func (c *Confirm) WithWidth(width int) Field { - c.width = width - return c -} - -// WithHeight sets the height of the confirm field. -func (c *Confirm) WithHeight(height int) Field { - c.height = height - return c -} - -// WithPosition sets the position of the confirm field. -func (c *Confirm) WithPosition(p FieldPosition) Field { - c.keymap.Prev.SetEnabled(!p.IsFirst()) - c.keymap.Next.SetEnabled(!p.IsLast()) - c.keymap.Submit.SetEnabled(p.IsLast()) - return c -} - -// WithButtonAlignment sets the button position of the confirm field. -func (c *Confirm) WithButtonAlignment(p lipgloss.Position) *Confirm { - c.buttonAlignment = p - return c -} - -// GetKey returns the key of the field. -func (c *Confirm) GetKey() string { - return c.key -} - -// GetValue returns the value of the field. -func (c *Confirm) GetValue() any { - return c.accessor.Get() -} diff --git a/vendor/github.com/charmbracelet/huh/field_filepicker.go b/vendor/github.com/charmbracelet/huh/field_filepicker.go deleted file mode 100644 index 06ab056f..00000000 --- a/vendor/github.com/charmbracelet/huh/field_filepicker.go +++ /dev/null @@ -1,450 +0,0 @@ -package huh - -import ( - "cmp" - "errors" - "io" - "os" - "strings" - - "github.com/charmbracelet/bubbles/filepicker" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/accessibility" - "github.com/charmbracelet/lipgloss" - xstrings "github.com/charmbracelet/x/exp/strings" -) - -// FilePicker is a form file file field. -type FilePicker struct { - accessor Accessor[string] - key string - picker filepicker.Model - - // state - focused bool - picking bool - - // customization - title string - description string - - // error handling - validate func(string) error - err error - - // options - width int - height int - accessible bool - theme *Theme - keymap FilePickerKeyMap -} - -// NewFilePicker returns a new file field. -func NewFilePicker() *FilePicker { - fp := filepicker.New() - fp.ShowSize = false - - if cmd := fp.Init(); cmd != nil { - fp, _ = fp.Update(cmd()) - } - - return &FilePicker{ - accessor: &EmbeddedAccessor[string]{}, - validate: func(string) error { return nil }, - picker: fp, - } -} - -// CurrentDirectory sets the directory of the file field. -func (f *FilePicker) CurrentDirectory(directory string) *FilePicker { - f.picker.CurrentDirectory = directory - if cmd := f.picker.Init(); cmd != nil { - f.picker, _ = f.picker.Update(cmd()) - } - return f -} - -// Cursor sets the cursor of the file field. -func (f *FilePicker) Cursor(cursor string) *FilePicker { - f.picker.Cursor = cursor - return f -} - -// Picking sets whether the file picker should be in the picking files state. -func (f *FilePicker) Picking(v bool) *FilePicker { - f.setPicking(v) - return f -} - -// ShowHidden sets whether to show hidden files. -func (f *FilePicker) ShowHidden(v bool) *FilePicker { - f.picker.ShowHidden = v - return f -} - -// ShowSize sets whether to show file sizes. -func (f *FilePicker) ShowSize(v bool) *FilePicker { - f.picker.ShowSize = v - return f -} - -// ShowPermissions sets whether to show file permissions. -func (f *FilePicker) ShowPermissions(v bool) *FilePicker { - f.picker.ShowPermissions = v - return f -} - -// FileAllowed sets whether to allow files to be selected. -func (f *FilePicker) FileAllowed(v bool) *FilePicker { - f.picker.FileAllowed = v - return f -} - -// DirAllowed sets whether to allow files to be selected. -func (f *FilePicker) DirAllowed(v bool) *FilePicker { - f.picker.DirAllowed = v - return f -} - -// Value sets the value of the file field. -func (f *FilePicker) Value(value *string) *FilePicker { - return f.Accessor(NewPointerAccessor(value)) -} - -// Accessor sets the accessor of the file field. -func (f *FilePicker) Accessor(accessor Accessor[string]) *FilePicker { - f.accessor = accessor - return f -} - -// Key sets the key of the file field which can be used to retrieve the value -// after submission. -func (f *FilePicker) Key(key string) *FilePicker { - f.key = key - return f -} - -// Title sets the title of the file field. -func (f *FilePicker) Title(title string) *FilePicker { - f.title = title - return f -} - -// Description sets the description of the file field. -func (f *FilePicker) Description(description string) *FilePicker { - f.description = description - return f -} - -// AllowedTypes sets the allowed types of the file field. These will be the only -// valid file types accepted, other files will show as disabled. -func (f *FilePicker) AllowedTypes(types []string) *FilePicker { - f.picker.AllowedTypes = types - return f -} - -// Height sets the height of the file field. If the number of options -// exceeds the height, the file field will become scrollable. -func (f *FilePicker) Height(height int) *FilePicker { - f.WithHeight(height) - return f -} - -// Validate sets the validation function of the file field. -func (f *FilePicker) Validate(validate func(string) error) *FilePicker { - f.validate = validate - return f -} - -// Error returns the error of the file field. -func (f *FilePicker) Error() error { - return f.err -} - -// Skip returns whether the file should be skipped or should be blocking. -func (*FilePicker) Skip() bool { - return false -} - -// Zoom returns whether the input should be zoomed. -func (f *FilePicker) Zoom() bool { - return f.picking -} - -// Focus focuses the file field. -func (f *FilePicker) Focus() tea.Cmd { - f.focused = true - return f.picker.Init() -} - -// Blur blurs the file field. -func (f *FilePicker) Blur() tea.Cmd { - f.focused = false - f.setPicking(false) - f.err = f.validate(f.accessor.Get()) - return nil -} - -// KeyBinds returns the help keybindings for the file field. -func (f *FilePicker) KeyBinds() []key.Binding { - return []key.Binding{f.keymap.Up, f.keymap.Down, f.keymap.Close, f.keymap.Open, f.keymap.Prev, f.keymap.Next, f.keymap.Submit} -} - -// Init initializes the file field. -func (f *FilePicker) Init() tea.Cmd { - return f.picker.Init() -} - -// Update updates the file field. -func (f *FilePicker) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - f.err = nil - - switch msg := msg.(type) { - case tea.KeyMsg: - switch { - case key.Matches(msg, f.keymap.Open): - if f.picking { - break - } - f.setPicking(true) - return f, f.picker.Init() - case key.Matches(msg, f.keymap.Close): - f.setPicking(false) - return f, NextField - case key.Matches(msg, f.keymap.Next): - f.setPicking(false) - return f, NextField - case key.Matches(msg, f.keymap.Prev): - f.setPicking(false) - return f, PrevField - } - } - - var cmd tea.Cmd - f.picker, cmd = f.picker.Update(msg) - didSelect, file := f.picker.DidSelectFile(msg) - if didSelect { - f.accessor.Set(file) - f.setPicking(false) - return f, NextField - } - didSelect, _ = f.picker.DidSelectDisabledFile(msg) - if didSelect { - f.err = errors.New(xstrings.EnglishJoin(f.picker.AllowedTypes, true) + " files only") - return f, nil - } - - return f, cmd -} - -func (f *FilePicker) activeStyles() *FieldStyles { - theme := f.theme - if theme == nil { - theme = ThemeCharm() - } - if f.focused { - return &theme.Focused - } - return &theme.Blurred -} - -func (f *FilePicker) renderTitle() string { - styles := f.activeStyles() - maxWidth := f.width - styles.Base.GetHorizontalFrameSize() - return styles.Title.Render(wrap(f.title, maxWidth)) -} - -func (f FilePicker) renderDescription() string { - styles := f.activeStyles() - maxWidth := f.width - styles.Base.GetHorizontalFrameSize() - return styles.Description.Render(wrap(f.description, maxWidth)) -} - -// View renders the file field. -func (f *FilePicker) View() string { - styles := f.activeStyles() - var parts []string - if f.title != "" { - parts = append(parts, f.renderTitle()) - } - if f.description != "" { - parts = append(parts, f.renderDescription()) - } - parts = append(parts, f.pickerView()) - return styles.Base.Width(f.width).Height(f.height). - Render(lipgloss.JoinVertical(lipgloss.Top, parts...)) -} - -func (f *FilePicker) pickerView() string { - if f.picking { - return f.picker.View() - } - styles := f.activeStyles() - if f.accessor.Get() != "" { - return styles.SelectedOption.Render(f.accessor.Get()) - } - return styles.TextInput.Placeholder.Render("No file selected.") -} - -func (f *FilePicker) setPicking(v bool) { - f.picking = v - - f.keymap.Close.SetEnabled(v) - f.keymap.Up.SetEnabled(v) - f.keymap.Down.SetEnabled(v) - f.keymap.Select.SetEnabled(v) - f.keymap.Back.SetEnabled(v) - - f.picker.KeyMap.Up.SetEnabled(v) - f.picker.KeyMap.Down.SetEnabled(v) - f.picker.KeyMap.GoToTop.SetEnabled(v) - f.picker.KeyMap.GoToLast.SetEnabled(v) - f.picker.KeyMap.Select.SetEnabled(v) - f.picker.KeyMap.Open.SetEnabled(v) - f.picker.KeyMap.Back.SetEnabled(v) -} - -// Run runs the file field. -func (f *FilePicker) Run() error { - if f.accessible { - return f.runAccessible(os.Stdout, os.Stdin) - } - return Run(f) -} - -// runAccessible runs an accessible file field. -func (f *FilePicker) runAccessible(w io.Writer, r io.Reader) error { - styles := f.activeStyles() - prompt := styles.Title. - PaddingRight(1). - Render(cmp.Or(f.title, "Choose a file:")) - - validateFile := func(s string) error { - // is the string a file? - if _, err := os.Open(s); err != nil { - return errors.New("not a file") - } - - // is it one of the allowed types? - valid := len(f.picker.AllowedTypes) == 0 - for _, ext := range f.picker.AllowedTypes { - if strings.HasSuffix(s, ext) { - valid = true - break - } - } - if !valid { - return errors.New("cannot select: " + s) - } - - // does it pass user validation? - return f.validate(s) - } - - f.accessor.Set(accessibility.PromptString( - w, - r, - prompt, - f.GetValue().(string), - validateFile, - )) - return nil -} - -// copied from bubbles' filepicker. -const ( - fileSizeWidth = 7 - paddingLeft = 2 -) - -// WithTheme sets the theme of the file field. -func (f *FilePicker) WithTheme(theme *Theme) Field { - if f.theme != nil || theme == nil { - return f - } - f.theme = theme - - // XXX: add specific themes - f.picker.Styles = filepicker.Styles{ - DisabledCursor: lipgloss.Style{}, - Cursor: theme.Focused.TextInput.Prompt, - Symlink: lipgloss.NewStyle(), - Directory: theme.Focused.Directory, - File: theme.Focused.File, - DisabledFile: theme.Focused.TextInput.Placeholder, - Permission: theme.Focused.TextInput.Placeholder, - Selected: theme.Focused.SelectedOption, - DisabledSelected: theme.Focused.TextInput.Placeholder, - FileSize: theme.Focused.TextInput.Placeholder.Width(fileSizeWidth).Align(lipgloss.Right), - EmptyDirectory: theme.Focused.TextInput.Placeholder.PaddingLeft(paddingLeft).SetString("No files found."), - } - - return f -} - -// WithKeyMap sets the keymap on a file field. -func (f *FilePicker) WithKeyMap(k *KeyMap) Field { - f.keymap = k.FilePicker - f.picker.KeyMap = filepicker.KeyMap{ - GoToTop: k.FilePicker.GotoTop, - GoToLast: k.FilePicker.GotoBottom, - Down: k.FilePicker.Down, - Up: k.FilePicker.Up, - PageUp: k.FilePicker.PageUp, - PageDown: k.FilePicker.PageDown, - Back: k.FilePicker.Back, - Open: k.FilePicker.Open, - Select: k.FilePicker.Select, - } - f.setPicking(f.picking) - return f -} - -// WithAccessible sets the accessible mode of the file field. -func (f *FilePicker) WithAccessible(accessible bool) Field { - f.accessible = accessible - return f -} - -// WithWidth sets the width of the file field. -func (f *FilePicker) WithWidth(width int) Field { - f.width = width - return f -} - -// WithHeight sets the height of the file field. -func (f *FilePicker) WithHeight(height int) Field { - if height == 0 { - return f - } - adjust := 0 - if f.title != "" { - adjust += lipgloss.Height(f.renderTitle()) - } - if f.description != "" { - adjust += lipgloss.Height(f.renderDescription()) - } - adjust++ // picker's own help height - f.picker.SetHeight(height - adjust) - return f -} - -// WithPosition sets the position of the file field. -func (f *FilePicker) WithPosition(p FieldPosition) Field { - f.keymap.Prev.SetEnabled(!p.IsFirst()) - f.keymap.Next.SetEnabled(!p.IsLast()) - f.keymap.Submit.SetEnabled(p.IsLast()) - return f -} - -// GetKey returns the key of the field. -func (f *FilePicker) GetKey() string { - return f.key -} - -// GetValue returns the value of the field. -func (f *FilePicker) GetValue() any { - return f.accessor.Get() -} diff --git a/vendor/github.com/charmbracelet/huh/field_input.go b/vendor/github.com/charmbracelet/huh/field_input.go deleted file mode 100644 index 7a66dcda..00000000 --- a/vendor/github.com/charmbracelet/huh/field_input.go +++ /dev/null @@ -1,524 +0,0 @@ -package huh - -import ( - "cmp" - "errors" - "fmt" - "io" - "os" - "strings" - - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/accessibility" - "github.com/charmbracelet/lipgloss" -) - -// Input is a input field. -// -// The input field is a field that allows the user to enter text. Use it to user -// input. It can be used for collecting text, passwords, or other short input. -// -// The input field supports Suggestions, Placeholder, and Validation. -type Input struct { - accessor Accessor[string] - key string - id int - - title Eval[string] - description Eval[string] - placeholder Eval[string] - suggestions Eval[[]string] - - textinput textinput.Model - - inline bool - validate func(string) error - err error - focused bool - - accessible bool - width int - height int // not really used anywhere - - theme *Theme - keymap InputKeyMap -} - -// NewInput creates a new input field. -// -// The input field is a field that allows the user to enter text. Use it to user -// input. It can be used for collecting text, passwords, or other short input. -// -// The input field supports Suggestions, Placeholder, and Validation. -func NewInput() *Input { - input := textinput.New() - - i := &Input{ - accessor: &EmbeddedAccessor[string]{}, - textinput: input, - validate: func(string) error { return nil }, - id: nextID(), - title: Eval[string]{cache: make(map[uint64]string)}, - description: Eval[string]{cache: make(map[uint64]string)}, - placeholder: Eval[string]{cache: make(map[uint64]string)}, - suggestions: Eval[[]string]{cache: make(map[uint64][]string)}, - } - - return i -} - -// Value sets the value of the input field. -func (i *Input) Value(value *string) *Input { - return i.Accessor(NewPointerAccessor(value)) -} - -// Accessor sets the accessor of the input field. -func (i *Input) Accessor(accessor Accessor[string]) *Input { - i.accessor = accessor - i.textinput.SetValue(i.accessor.Get()) - return i -} - -// Key sets the key of the input field. -func (i *Input) Key(key string) *Input { - i.key = key - return i -} - -// Title sets the title of the input field. -// -// The Title is static for dynamic Title use `TitleFunc`. -func (i *Input) Title(title string) *Input { - i.title.val = title - i.title.fn = nil - return i -} - -// Description sets the description of the input field. -// -// The Description is static for dynamic Description use `DescriptionFunc`. -func (i *Input) Description(description string) *Input { - i.description.val = description - i.description.fn = nil - return i -} - -// TitleFunc sets the title func of the input field. -// -// The TitleFunc will be re-evaluated when the binding of the TitleFunc changes. -// This is useful when you want to display dynamic content and update the title -// when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (i *Input) TitleFunc(f func() string, bindings any) *Input { - i.title.fn = f - i.title.bindings = bindings - return i -} - -// DescriptionFunc sets the description func of the input field. -// -// The DescriptionFunc will be re-evaluated when the binding of the -// DescriptionFunc changes. This is useful when you want to display dynamic -// content and update the description when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (i *Input) DescriptionFunc(f func() string, bindings any) *Input { - i.description.fn = f - i.description.bindings = bindings - return i -} - -// Prompt sets the prompt of the input field. -func (i *Input) Prompt(prompt string) *Input { - i.textinput.Prompt = prompt - return i -} - -// CharLimit sets the character limit of the input field. -func (i *Input) CharLimit(charlimit int) *Input { - i.textinput.CharLimit = charlimit - return i -} - -// Suggestions sets the suggestions to display for autocomplete in the input -// field. -// -// The suggestions are static for dynamic suggestions use `SuggestionsFunc`. -func (i *Input) Suggestions(suggestions []string) *Input { - i.suggestions.fn = nil - - i.textinput.ShowSuggestions = len(suggestions) > 0 - i.textinput.KeyMap.AcceptSuggestion.SetEnabled(len(suggestions) > 0) - i.textinput.SetSuggestions(suggestions) - return i -} - -// SuggestionsFunc sets the suggestions func to display for autocomplete in the -// input field. -// -// The SuggestionsFunc will be re-evaluated when the binding of the -// SuggestionsFunc changes. This is useful when you want to display dynamic -// suggestions when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (i *Input) SuggestionsFunc(f func() []string, bindings any) *Input { - i.suggestions.fn = f - i.suggestions.bindings = bindings - i.suggestions.loading = true - - i.textinput.KeyMap.AcceptSuggestion.SetEnabled(f != nil) - i.textinput.ShowSuggestions = f != nil - return i -} - -// EchoMode sets the input behavior of the text Input field. -type EchoMode textinput.EchoMode - -const ( - // EchoModeNormal displays text as is. - // This is the default behavior. - EchoModeNormal EchoMode = EchoMode(textinput.EchoNormal) - - // EchoModePassword displays the EchoCharacter mask instead of actual characters. - // This is commonly used for password fields. - EchoModePassword EchoMode = EchoMode(textinput.EchoPassword) - - // EchoModeNone displays nothing as characters are entered. - // This is commonly seen for password fields on the command line. - EchoModeNone EchoMode = EchoMode(textinput.EchoNone) -) - -// EchoMode sets the echo mode of the input. -func (i *Input) EchoMode(mode EchoMode) *Input { - i.textinput.EchoMode = textinput.EchoMode(mode) - return i -} - -// Password sets whether or not to hide the input while the user is typing. -// -// Deprecated: use EchoMode(EchoPassword) instead. -func (i *Input) Password(password bool) *Input { - if password { - i.textinput.EchoMode = textinput.EchoPassword - } else { - i.textinput.EchoMode = textinput.EchoNormal - } - return i -} - -// Placeholder sets the placeholder of the text input. -func (i *Input) Placeholder(str string) *Input { - i.textinput.Placeholder = str - return i -} - -// PlaceholderFunc sets the placeholder func of the text input. -func (i *Input) PlaceholderFunc(f func() string, bindings any) *Input { - i.placeholder.fn = f - i.placeholder.bindings = bindings - return i -} - -// Inline sets whether the title and input should be on the same line. -func (i *Input) Inline(inline bool) *Input { - i.inline = inline - return i -} - -// Validate sets the validation function of the input field. -func (i *Input) Validate(validate func(string) error) *Input { - i.validate = validate - return i -} - -// Error returns the error of the input field. -func (i *Input) Error() error { return i.err } - -// Skip returns whether the input should be skipped or should be blocking. -func (*Input) Skip() bool { return false } - -// Zoom returns whether the input should be zoomed. -func (*Input) Zoom() bool { return false } - -// Focus focuses the input field. -func (i *Input) Focus() tea.Cmd { - i.focused = true - return i.textinput.Focus() -} - -// Blur blurs the input field. -func (i *Input) Blur() tea.Cmd { - i.focused = false - i.accessor.Set(i.textinput.Value()) - i.textinput.Blur() - i.err = i.validate(i.accessor.Get()) - return nil -} - -// KeyBinds returns the help message for the input field. -func (i *Input) KeyBinds() []key.Binding { - if i.textinput.ShowSuggestions { - return []key.Binding{i.keymap.AcceptSuggestion, i.keymap.Prev, i.keymap.Submit, i.keymap.Next} - } - return []key.Binding{i.keymap.Prev, i.keymap.Submit, i.keymap.Next} -} - -// Init initializes the input field. -func (i *Input) Init() tea.Cmd { - i.textinput.Blur() - return nil -} - -// Update updates the input field. -func (i *Input) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmds []tea.Cmd - var cmd tea.Cmd - - switch msg := msg.(type) { - case updateFieldMsg: - var cmds []tea.Cmd - if ok, hash := i.title.shouldUpdate(); ok { - i.title.bindingsHash = hash - if !i.title.loadFromCache() { - i.title.loading = true - cmds = append(cmds, func() tea.Msg { - return updateTitleMsg{id: i.id, title: i.title.fn(), hash: hash} - }) - } - } - if ok, hash := i.description.shouldUpdate(); ok { - i.description.bindingsHash = hash - if !i.description.loadFromCache() { - i.description.loading = true - cmds = append(cmds, func() tea.Msg { - return updateDescriptionMsg{id: i.id, description: i.description.fn(), hash: hash} - }) - } - } - if ok, hash := i.placeholder.shouldUpdate(); ok { - i.placeholder.bindingsHash = hash - if i.placeholder.loadFromCache() { - i.textinput.Placeholder = i.placeholder.val - } else { - i.placeholder.loading = true - cmds = append(cmds, func() tea.Msg { - return updatePlaceholderMsg{id: i.id, placeholder: i.placeholder.fn(), hash: hash} - }) - } - } - if ok, hash := i.suggestions.shouldUpdate(); ok { - i.suggestions.bindingsHash = hash - if i.suggestions.loadFromCache() { - i.textinput.ShowSuggestions = len(i.suggestions.val) > 0 - i.textinput.SetSuggestions(i.suggestions.val) - } else { - i.suggestions.loading = true - cmds = append(cmds, func() tea.Msg { - return updateSuggestionsMsg{id: i.id, suggestions: i.suggestions.fn(), hash: hash} - }) - } - } - return i, tea.Batch(cmds...) - case updateTitleMsg: - if i.id == msg.id && i.title.bindingsHash == msg.hash { - i.title.update(msg.title) - } - case updateDescriptionMsg: - if i.id == msg.id && i.description.bindingsHash == msg.hash { - i.description.update(msg.description) - } - case updatePlaceholderMsg: - if i.id == msg.id && i.placeholder.bindingsHash == msg.hash { - i.placeholder.update(msg.placeholder) - i.textinput.Placeholder = msg.placeholder - } - case updateSuggestionsMsg: - if i.id == msg.id && i.suggestions.bindingsHash == msg.hash { - i.suggestions.update(msg.suggestions) - i.textinput.ShowSuggestions = len(msg.suggestions) > 0 - i.textinput.SetSuggestions(msg.suggestions) - } - case tea.KeyMsg: - i.err = nil - - switch { - case key.Matches(msg, i.keymap.Prev): - cmds = append(cmds, PrevField) - case key.Matches(msg, i.keymap.Next, i.keymap.Submit): - value := i.textinput.Value() - i.err = i.validate(value) - if i.err != nil { - return i, nil - } - cmds = append(cmds, NextField) - } - } - - i.textinput, cmd = i.textinput.Update(msg) - cmds = append(cmds, cmd) - i.accessor.Set(i.textinput.Value()) - - return i, tea.Batch(cmds...) -} - -func (i *Input) activeStyles() *FieldStyles { - theme := i.theme - if theme == nil { - theme = ThemeCharm() - } - if i.focused { - return &theme.Focused - } - return &theme.Blurred -} - -// View renders the input field. -func (i *Input) View() string { - styles := i.activeStyles() - maxWidth := i.width - styles.Base.GetHorizontalFrameSize() - - // NB: since the method is on a pointer receiver these are being mutated. - // Because this runs on every render this shouldn't matter in practice, - // however. - i.textinput.PlaceholderStyle = styles.TextInput.Placeholder - i.textinput.PromptStyle = styles.TextInput.Prompt - i.textinput.Cursor.Style = styles.TextInput.Cursor - i.textinput.Cursor.TextStyle = styles.TextInput.CursorText - i.textinput.TextStyle = styles.TextInput.Text - - // Adjust text input size to its char limit if it fit in its width - if i.textinput.CharLimit > 0 { - i.textinput.Width = max(min(i.textinput.CharLimit, i.textinput.Width, maxWidth), 0) - } - - var sb strings.Builder - if i.title.val != "" || i.title.fn != nil { - sb.WriteString(styles.Title.Render(wrap(i.title.val, maxWidth))) - if !i.inline { - sb.WriteString("\n") - } - } - if i.description.val != "" || i.description.fn != nil { - sb.WriteString(styles.Description.Render(wrap(i.description.val, maxWidth))) - if !i.inline { - sb.WriteString("\n") - } - } - sb.WriteString(i.textinput.View()) - - return styles.Base. - Width(i.width). - Height(i.height). - Render(sb.String()) -} - -// Run runs the input field in accessible mode. -func (i *Input) Run() error { - if i.accessible { - return i.runAccessible(os.Stdout, os.Stdin) - } - return i.run() -} - -// run runs the input field. -func (i *Input) run() error { - return Run(i) -} - -// runAccessible runs the input field in accessible mode. -func (i *Input) runAccessible(w io.Writer, r io.Reader) error { - styles := i.activeStyles() - validator := func(input string) error { - if i.textinput.CharLimit > 0 && len(input) > i.textinput.CharLimit { - return fmt.Errorf("Input cannot exceed %d characters", i.textinput.CharLimit) - } - return i.validate(input) - } - - //nolint:exhaustive - switch i.textinput.EchoMode { - case textinput.EchoNormal: - prompt := styles.Title. - PaddingRight(1). - Render(cmp.Or(i.title.val, "Input:")) - value := accessibility.PromptString(w, r, prompt, i.GetValue().(string), validator) - i.accessor.Set(value) - return nil - default: - prompt := styles.Title. - PaddingRight(1). - Render(cmp.Or(i.title.val, "Password:")) - if fd, ok := r.(interface{ Fd() uintptr }); ok { - value, err := accessibility.PromptPassword(w, fd.Fd(), prompt, validator) - if err != nil { - return err //nolint:wrapcheck - } - i.accessor.Set(value) - return nil - } - return errors.New("password asking needs a tty") - } -} - -// WithKeyMap sets the keymap on an input field. -func (i *Input) WithKeyMap(k *KeyMap) Field { - i.keymap = k.Input - i.textinput.KeyMap.AcceptSuggestion = i.keymap.AcceptSuggestion - return i -} - -// WithAccessible sets the accessible mode of the input field. -func (i *Input) WithAccessible(accessible bool) Field { - i.accessible = accessible - return i -} - -// WithTheme sets the theme of the input field. -func (i *Input) WithTheme(theme *Theme) Field { - if i.theme != nil { - return i - } - i.theme = theme - return i -} - -// WithWidth sets the width of the input field. -func (i *Input) WithWidth(width int) Field { - styles := i.activeStyles() - i.width = width - frameSize := styles.Base.GetHorizontalFrameSize() - promptWidth := lipgloss.Width(i.textinput.PromptStyle.Render(i.textinput.Prompt)) - titleWidth := lipgloss.Width(styles.Title.Render(i.title.val)) - descriptionWidth := lipgloss.Width(styles.Description.Render(i.description.val)) - i.textinput.Width = width - frameSize - promptWidth - 1 - if i.inline { - i.textinput.Width -= titleWidth - i.textinput.Width -= descriptionWidth - } - return i -} - -// WithHeight sets the height of the input field. -func (i *Input) WithHeight(height int) Field { - i.height = height - return i -} - -// WithPosition sets the position of the input field. -func (i *Input) WithPosition(p FieldPosition) Field { - i.keymap.Prev.SetEnabled(!p.IsFirst()) - i.keymap.Next.SetEnabled(!p.IsLast()) - i.keymap.Submit.SetEnabled(p.IsLast()) - return i -} - -// GetKey returns the key of the field. -func (i *Input) GetKey() string { return i.key } - -// GetValue returns the value of the field. -func (i *Input) GetValue() any { - return i.accessor.Get() -} diff --git a/vendor/github.com/charmbracelet/huh/field_multiselect.go b/vendor/github.com/charmbracelet/huh/field_multiselect.go deleted file mode 100644 index f3328a53..00000000 --- a/vendor/github.com/charmbracelet/huh/field_multiselect.go +++ /dev/null @@ -1,819 +0,0 @@ -package huh - -import ( - "cmp" - "fmt" - "io" - "os" - "slices" - "strings" - "time" - - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/spinner" - "github.com/charmbracelet/bubbles/textinput" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/accessibility" - "github.com/charmbracelet/lipgloss" -) - -// MultiSelect is a form multi-select field. -type MultiSelect[T comparable] struct { - accessor Accessor[[]T] - key string - id int - - // customization - title Eval[string] - description Eval[string] - options Eval[[]Option[T]] - filterable bool - filteredOptions []Option[T] - limit int - height int - - // error handling - validate func([]T) error - err error - - // state - cursor int - focused bool - filtering bool - filter textinput.Model - viewport viewport.Model - spinner spinner.Model - - // options - width int - accessible bool - theme *Theme - keymap MultiSelectKeyMap -} - -// NewMultiSelect returns a new multi-select field. -func NewMultiSelect[T comparable]() *MultiSelect[T] { - filter := textinput.New() - filter.Prompt = "/" - - s := spinner.New(spinner.WithSpinner(spinner.Line)) - - return &MultiSelect[T]{ - accessor: &EmbeddedAccessor[[]T]{}, - validate: func([]T) error { return nil }, - filtering: false, - filter: filter, - id: nextID(), - options: Eval[[]Option[T]]{cache: make(map[uint64][]Option[T])}, - title: Eval[string]{cache: make(map[uint64]string)}, - description: Eval[string]{cache: make(map[uint64]string)}, - spinner: s, - filterable: true, - } -} - -// Value sets the value of the multi-select field. -func (m *MultiSelect[T]) Value(value *[]T) *MultiSelect[T] { - return m.Accessor(NewPointerAccessor(value)) -} - -// Accessor sets the accessor of the input field. -func (m *MultiSelect[T]) Accessor(accessor Accessor[[]T]) *MultiSelect[T] { - m.accessor = accessor - for i, o := range m.options.val { - if slices.Contains(m.accessor.Get(), o.Value) { - m.options.val[i].selected = true - } - } - return m -} - -// Key sets the key of the select field which can be used to retrieve the value -// after submission. -func (m *MultiSelect[T]) Key(key string) *MultiSelect[T] { - m.key = key - return m -} - -// Title sets the title of the multi-select field. -func (m *MultiSelect[T]) Title(title string) *MultiSelect[T] { - m.title.val = title - m.title.fn = nil - return m -} - -// TitleFunc sets the title func of the multi-select field. -func (m *MultiSelect[T]) TitleFunc(f func() string, bindings any) *MultiSelect[T] { - m.title.fn = f - m.title.bindings = bindings - return m -} - -// Description sets the description of the multi-select field. -func (m *MultiSelect[T]) Description(description string) *MultiSelect[T] { - m.description.val = description - return m -} - -// DescriptionFunc sets the description func of the multi-select field. -func (m *MultiSelect[T]) DescriptionFunc(f func() string, bindings any) *MultiSelect[T] { - m.description.fn = f - m.description.bindings = bindings - return m -} - -// Options sets the options of the multi-select field. -func (m *MultiSelect[T]) Options(options ...Option[T]) *MultiSelect[T] { - if len(options) <= 0 { - return m - } - - m.options.val = options - m.filteredOptions = options - m.selectOptions() - m.updateViewportHeight() - return m -} - -func (m *MultiSelect[T]) selectOptions() { - // Set the cursor to the existing value or the last selected option. - for i, o := range m.options.val { - for _, v := range m.accessor.Get() { - if o.Value == v { - m.options.val[i].selected = true - } - } - } - - for i, o := range m.options.val { - if !o.selected { - continue - } - m.cursor = i - m.viewport.YOffset = i - break - } -} - -// OptionsFunc sets the options func of the multi-select field. -func (m *MultiSelect[T]) OptionsFunc(f func() []Option[T], bindings any) *MultiSelect[T] { - m.options.fn = f - m.options.bindings = bindings - m.filteredOptions = make([]Option[T], 0) - // If there is no height set, we should attach a static height since these - // options are possibly dynamic. - if m.height <= 0 { - m.height = defaultHeight - m.updateViewportHeight() - } - return m -} - -// Filterable sets the multi-select field as filterable. -func (m *MultiSelect[T]) Filterable(filterable bool) *MultiSelect[T] { - m.filterable = filterable - return m -} - -// Filtering sets the filtering state of the multi-select field. -func (m *MultiSelect[T]) Filtering(filtering bool) *MultiSelect[T] { - m.filtering = filtering - m.filter.Focus() - return m -} - -// Limit sets the limit of the multi-select field. -func (m *MultiSelect[T]) Limit(limit int) *MultiSelect[T] { - m.limit = limit - m.setSelectAllHelp() - return m -} - -// Height sets the height of the multi-select field. -func (m *MultiSelect[T]) Height(height int) *MultiSelect[T] { - // What we really want to do is set the height of the viewport, but we - // need a theme applied before we can calcualate its height. - m.height = height - m.updateViewportHeight() - return m -} - -// Validate sets the validation function of the multi-select field. -func (m *MultiSelect[T]) Validate(validate func([]T) error) *MultiSelect[T] { - m.validate = validate - return m -} - -// Error returns the error of the multi-select field. -func (m *MultiSelect[T]) Error() error { - return m.err -} - -// Skip returns whether the multiselect should be skipped or should be blocking. -func (*MultiSelect[T]) Skip() bool { - return false -} - -// Zoom returns whether the multiselect should be zoomed. -func (*MultiSelect[T]) Zoom() bool { - return false -} - -// Focus focuses the multi-select field. -func (m *MultiSelect[T]) Focus() tea.Cmd { - m.updateValue() - m.focused = true - return nil -} - -// Blur blurs the multi-select field. -func (m *MultiSelect[T]) Blur() tea.Cmd { - m.updateValue() - m.focused = false - return nil -} - -// Hovered returns the value of the option under the cursor, and a bool -// indicating whether one was found. If there are no visible options, returns -// a zero-valued T and false. -func (m *MultiSelect[T]) Hovered() (T, bool) { - if len(m.filteredOptions) == 0 || m.cursor >= len(m.filteredOptions) { - var zero T - return zero, false - } - return m.filteredOptions[m.cursor].Value, true -} - -// KeyBinds returns the help message for the multi-select field. -func (m *MultiSelect[T]) KeyBinds() []key.Binding { - m.setSelectAllHelp() - binds := []key.Binding{ - m.keymap.Toggle, - m.keymap.Up, - m.keymap.Down, - } - if m.filterable { - binds = append( - binds, - m.keymap.Filter, - m.keymap.SetFilter, - m.keymap.ClearFilter, - ) - } - binds = append( - binds, - m.keymap.Prev, - m.keymap.Submit, - m.keymap.Next, - m.keymap.SelectAll, - m.keymap.SelectNone, - ) - return binds -} - -// Init initializes the multi-select field. -func (m *MultiSelect[T]) Init() tea.Cmd { - return nil -} - -// Update updates the multi-select field. -func (m *MultiSelect[T]) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmds []tea.Cmd - - // Enforce height on the viewport during update as we need themes to - // be applied before we can calculate the height. - m.updateViewportHeight() - - var cmd tea.Cmd - if m.filtering { - m.filter, cmd = m.filter.Update(msg) - m.setSelectAllHelp() - cmds = append(cmds, cmd) - } - - switch msg := msg.(type) { - case updateFieldMsg: - var fieldCmds []tea.Cmd - if ok, hash := m.title.shouldUpdate(); ok { - m.title.bindingsHash = hash - if !m.title.loadFromCache() { - m.title.loading = true - fieldCmds = append(fieldCmds, func() tea.Msg { - return updateTitleMsg{id: m.id, title: m.title.fn(), hash: hash} - }) - } - } - if ok, hash := m.description.shouldUpdate(); ok { - m.description.bindingsHash = hash - if !m.description.loadFromCache() { - m.description.loading = true - fieldCmds = append(fieldCmds, func() tea.Msg { - return updateDescriptionMsg{id: m.id, description: m.description.fn(), hash: hash} - }) - } - } - if ok, hash := m.options.shouldUpdate(); ok { - m.options.bindingsHash = hash - if m.options.loadFromCache() { - m.filteredOptions = m.options.val - m.updateValue() - m.cursor = clamp(m.cursor, 0, len(m.filteredOptions)-1) - } else { - m.options.loading = true - m.options.loadingStart = time.Now() - fieldCmds = append(fieldCmds, func() tea.Msg { - return updateOptionsMsg[T]{id: m.id, options: m.options.fn(), hash: hash} - }, m.spinner.Tick) - } - } - - return m, tea.Batch(fieldCmds...) - - case spinner.TickMsg: - if !m.options.loading { - break - } - m.spinner, cmd = m.spinner.Update(msg) - return m, cmd - - case updateTitleMsg: - if msg.id == m.id && msg.hash == m.title.bindingsHash { - m.title.update(msg.title) - } - case updateDescriptionMsg: - if msg.id == m.id && msg.hash == m.description.bindingsHash { - m.description.update(msg.description) - } - case updateOptionsMsg[T]: - if msg.id == m.id && msg.hash == m.options.bindingsHash { - m.options.update(msg.options) - m.selectOptions() - // since we're updating the options, we need to reset the cursor. - m.filteredOptions = m.options.val - m.updateValue() - m.cursor = clamp(m.cursor, 0, len(m.filteredOptions)-1) - } - case tea.KeyMsg: - m.err = nil - switch { - case key.Matches(msg, m.keymap.Filter): - m.setFilter(true) - return m, m.filter.Focus() - case key.Matches(msg, m.keymap.SetFilter): - if len(m.filteredOptions) <= 0 { - m.filter.SetValue("") - m.filteredOptions = m.options.val - } - m.setFilter(false) - case key.Matches(msg, m.keymap.ClearFilter): - m.filter.SetValue("") - m.filteredOptions = m.options.val - m.setFilter(false) - case key.Matches(msg, m.keymap.Up): - //nolint:godox - // FIXME: should use keys in keymap - if m.filtering && msg.String() == "k" { - break - } - - m.cursor = max(m.cursor-1, 0) - if m.cursor < m.viewport.YOffset { - m.viewport.SetYOffset(m.cursor) - } - case key.Matches(msg, m.keymap.Down): - //nolint:godox - // FIXME: should use keys in keymap - if m.filtering && msg.String() == "j" { - break - } - - m.cursor = min(m.cursor+1, len(m.filteredOptions)-1) - if m.cursor >= m.viewport.YOffset+m.viewport.Height { - m.viewport.ScrollDown(1) - } - case key.Matches(msg, m.keymap.GotoTop): - if m.filtering { - break - } - m.cursor = 0 - m.viewport.GotoTop() - case key.Matches(msg, m.keymap.GotoBottom): - if m.filtering { - break - } - m.cursor = len(m.filteredOptions) - 1 - m.viewport.GotoBottom() - case key.Matches(msg, m.keymap.HalfPageUp): - m.cursor = max(m.cursor-m.viewport.Height/2, 0) - m.viewport.HalfPageUp() - case key.Matches(msg, m.keymap.HalfPageDown): - m.cursor = min(m.cursor+m.viewport.Height/2, len(m.filteredOptions)-1) - m.viewport.HalfPageDown() - case key.Matches(msg, m.keymap.Toggle) && !m.filtering: - for i, option := range m.options.val { - if option.Key == m.filteredOptions[m.cursor].Key { - if !m.options.val[m.cursor].selected && m.limit > 0 && m.numSelected() >= m.limit { - break - } - selected := m.options.val[i].selected - m.options.val[i].selected = !selected - m.filteredOptions[m.cursor].selected = !selected - } - } - m.setSelectAllHelp() - m.updateValue() - case key.Matches(msg, m.keymap.SelectAll, m.keymap.SelectNone) && m.limit <= 0: - selected := false - - for _, option := range m.filteredOptions { - if !option.selected { - selected = true - break - } - } - - for i, option := range m.options.val { - for j := range m.filteredOptions { - if option.Key == m.filteredOptions[j].Key { - m.options.val[i].selected = selected - m.filteredOptions[j].selected = selected - break - } - } - } - m.setSelectAllHelp() - m.updateValue() - case key.Matches(msg, m.keymap.Prev): - m.updateValue() - m.err = m.validate(m.accessor.Get()) - if m.err != nil { - return m, nil - } - return m, PrevField - case key.Matches(msg, m.keymap.Next, m.keymap.Submit): - m.updateValue() - m.err = m.validate(m.accessor.Get()) - if m.err != nil { - return m, nil - } - return m, NextField - } - - if m.filtering { - m.filteredOptions = m.options.val - if m.filter.Value() != "" { - m.filteredOptions = nil - for _, option := range m.options.val { - if m.filterFunc(option.Key) { - m.filteredOptions = append(m.filteredOptions, option) - } - } - } - if len(m.filteredOptions) > 0 { - m.cursor = min(m.cursor, len(m.filteredOptions)-1) - } - } - _, offset, height := m.optionsView() - if offset > -1 && height > 0 && (offset < m.viewport.YOffset || height+offset >= m.viewport.YOffset+m.viewport.Height) { - m.viewport.SetYOffset(offset) - } - } - - return m, tea.Batch(cmds...) -} - -// updateViewportHeight updates the viewport size according to the Height setting -// on this multi-select field. -func (m *MultiSelect[T]) updateViewportHeight() { - // If no height is set size the viewport to the height of the options. - if m.height <= 0 { - v, _, _ := m.optionsView() - m.viewport.Height = lipgloss.Height(v) - return - } - - offset := 0 - if ss := m.titleView(); ss != "" { - offset += lipgloss.Height(ss) - } - if ss := m.descriptionView(); ss != "" { - offset += lipgloss.Height(ss) - } - - m.viewport.Height = max(minHeight, m.height-offset) -} - -// numSelected returns the total number of selected options. -func (m *MultiSelect[T]) numSelected() int { - var count int - for _, o := range m.options.val { - if o.selected { - count++ - } - } - return count -} - -// numFilteredOptionsSelected returns the number of selected options with the -// current filter applied. -func (m *MultiSelect[T]) numFilteredSelected() int { - var count int - for _, o := range m.filteredOptions { - if o.selected { - count++ - } - } - return count -} - -func (m *MultiSelect[T]) updateValue() { - value := make([]T, 0) - for _, option := range m.options.val { - if option.selected { - value = append(value, option.Value) - } - } - m.accessor.Set(value) - m.err = m.validate(m.accessor.Get()) -} - -func (m *MultiSelect[T]) activeStyles() *FieldStyles { - theme := m.theme - if theme == nil { - theme = ThemeCharm() - } - if m.focused { - return &theme.Focused - } - return &theme.Blurred -} - -func (m *MultiSelect[T]) titleView() string { - if m.title.val == "" { - return "" - } - var ( - styles = m.activeStyles() - sb = strings.Builder{} - maxWidth = m.width - styles.Base.GetHorizontalFrameSize() - ) - if m.filtering { - sb.WriteString(m.filter.View()) - } else if m.filter.Value() != "" { - sb.WriteString(styles.Title.Render(wrap(m.title.val, maxWidth))) - sb.WriteString(styles.Description.Render("/" + m.filter.Value())) - } else { - sb.WriteString(styles.Title.Render(wrap(m.title.val, maxWidth))) - } - if m.err != nil { - sb.WriteString(styles.ErrorIndicator.String()) - } - return sb.String() -} - -func (m *MultiSelect[T]) descriptionView() string { - if m.description.val == "" { - return "" - } - maxWidth := m.width - m.activeStyles().Base.GetHorizontalFrameSize() - return m.activeStyles().Description.Render(wrap(m.description.val, maxWidth)) -} - -func (m *MultiSelect[T]) renderOption(option Option[T], cursor, selected bool) string { - styles := m.activeStyles() - var parts []string - if cursor { - parts = append(parts, styles.MultiSelectSelector.String()) - } else { - parts = append(parts, strings.Repeat(" ", lipgloss.Width(styles.MultiSelectSelector.String()))) - } - if selected { - parts = append(parts, styles.SelectedPrefix.String()) - parts = append(parts, styles.SelectedOption.Render(option.Key)) - } else { - parts = append(parts, styles.UnselectedPrefix.String()) - parts = append(parts, styles.UnselectedOption.Render(option.Key)) - } - return lipgloss.JoinHorizontal(lipgloss.Left, parts...) -} - -func (m *MultiSelect[T]) optionsView() (string, int, int) { - var sb strings.Builder - - if m.options.loading && time.Since(m.options.loadingStart) > spinnerShowThreshold { - m.spinner.Style = m.activeStyles().MultiSelectSelector.UnsetString() - sb.WriteString(m.spinner.View() + " Loading...") - return sb.String(), -1, 1 - } - - var cursorOffset int - var cursorHeight int - for i, option := range m.filteredOptions { - cursor := m.cursor == i - line := m.renderOption(option, cursor, m.filteredOptions[i].selected) - if i < m.cursor { - cursorOffset += lipgloss.Height(line) - } - if cursor { - cursorHeight = lipgloss.Height(line) - } - sb.WriteString(line) - if i < len(m.options.val)-1 { - sb.WriteString("\n") - } - } - - for i := len(m.filteredOptions); i < len(m.options.val)-1; i++ { - sb.WriteString("\n") - } - - return sb.String(), cursorOffset, cursorHeight -} - -// View renders the multi-select field. -func (m *MultiSelect[T]) View() string { - styles := m.activeStyles() - - vpc, _, _ := m.optionsView() - m.viewport.SetContent(vpc) - - var sb strings.Builder - if m.title.val != "" || m.title.fn != nil { - sb.WriteString(m.titleView()) - sb.WriteString("\n") - } - if m.description.val != "" || m.description.fn != nil { - sb.WriteString(m.descriptionView() + "\n") - } - sb.WriteString(m.viewport.View()) - return styles.Base.Width(m.width).Height(m.height). - Render(sb.String()) -} - -func (m *MultiSelect[T]) printOptions(w io.Writer) { - styles := m.activeStyles() - var sb strings.Builder - for i, option := range m.options.val { - if option.selected { - sb.WriteString(styles.SelectedOption.Render(fmt.Sprintf("%d. %s %s", i+1, "✓", option.Key))) - } else { - sb.WriteString(fmt.Sprintf("%d. %s", i+1, option.Key)) - } - sb.WriteString("\n") - } - sb.WriteString("0. Confirm selection\n") - _, _ = fmt.Fprint(w, sb.String()) -} - -// setFilter sets the filter of the select field. -func (m *MultiSelect[T]) setFilter(filter bool) { - m.filtering = filter - m.keymap.SetFilter.SetEnabled(filter) - m.keymap.Filter.SetEnabled(!filter) - m.keymap.Next.SetEnabled(!filter) - m.keymap.Submit.SetEnabled(!filter) - m.keymap.Prev.SetEnabled(!filter) - m.keymap.ClearFilter.SetEnabled(!filter && m.filter.Value() != "") -} - -// filterFunc returns true if the option matches the filter. -func (m *MultiSelect[T]) filterFunc(option string) bool { - // XXX: remove diacritics or allow customization of filter function. - return strings.Contains(strings.ToLower(option), strings.ToLower(m.filter.Value())) -} - -// setSelectAllHelp enables the appropriate select all or select none keybinding. -func (m *MultiSelect[T]) setSelectAllHelp() { - if m.limit > 0 { - m.keymap.SelectAll.SetEnabled(false) - m.keymap.SelectNone.SetEnabled(false) - return - } - - noneSelected := m.numFilteredSelected() <= 0 - allSelected := m.numFilteredSelected() > 0 && m.numFilteredSelected() < len(m.filteredOptions) - selectAll := noneSelected || allSelected - m.keymap.SelectAll.SetEnabled(selectAll) - m.keymap.SelectNone.SetEnabled(!selectAll) -} - -// Run runs the multi-select field. -func (m *MultiSelect[T]) Run() error { - if m.accessible { - return m.runAccessible(os.Stdout, os.Stdin) - } - return Run(m) -} - -// runAccessible() runs the multi-select field in accessible mode. -func (m *MultiSelect[T]) runAccessible(w io.Writer, r io.Reader) error { - styles := m.activeStyles() - title := styles.Title. - PaddingRight(1). - Render(cmp.Or(m.title.val, "Select:")) - _, _ = fmt.Fprintln(w, title) - limit := m.limit - if limit == 0 { - limit = len(m.options.val) - } - _, _ = fmt.Fprintf(w, "Select up to %d options.\n", limit) - - var choice int - for { - m.printOptions(w) - - prompt := fmt.Sprintf("Input a number between %d and %d: ", 0, len(m.options.val)) - choice = accessibility.PromptInt(w, r, prompt, 0, len(m.options.val), nil) - if choice == 0 { - m.updateValue() - err := m.validate(m.accessor.Get()) - if err != nil { - _, _ = fmt.Fprintln(w, err) - continue - } - break - } - - if !m.options.val[choice-1].selected && m.limit > 0 && m.numSelected() >= m.limit { - _, _ = fmt.Fprintf(w, "You can't select more than %d options.\n", m.limit) - _, _ = fmt.Fprintln(w) - continue - } - m.options.val[choice-1].selected = !m.options.val[choice-1].selected - _, _ = fmt.Fprintln(w) - } - - return nil -} - -// WithTheme sets the theme of the multi-select field. -func (m *MultiSelect[T]) WithTheme(theme *Theme) Field { - if m.theme != nil { - return m - } - m.theme = theme - m.filter.Cursor.Style = theme.Focused.TextInput.Cursor - m.filter.Cursor.TextStyle = theme.Focused.TextInput.CursorText - m.filter.PromptStyle = theme.Focused.TextInput.Prompt - m.filter.TextStyle = theme.Focused.TextInput.Text - m.filter.PlaceholderStyle = theme.Focused.TextInput.Placeholder - m.updateViewportHeight() - return m -} - -// WithKeyMap sets the keymap of the multi-select field. -func (m *MultiSelect[T]) WithKeyMap(k *KeyMap) Field { - m.keymap = k.MultiSelect - if !m.filterable { - m.keymap.Filter.SetEnabled(false) - m.keymap.ClearFilter.SetEnabled(false) - m.keymap.SetFilter.SetEnabled(false) - } - return m -} - -// WithAccessible sets the accessible mode of the multi-select field. -func (m *MultiSelect[T]) WithAccessible(accessible bool) Field { - m.accessible = accessible - return m -} - -// WithWidth sets the width of the multi-select field. -func (m *MultiSelect[T]) WithWidth(width int) Field { - m.width = width - return m -} - -// WithHeight sets the total height of the multi-select field. Including padding -// and help menu heights. -func (m *MultiSelect[T]) WithHeight(height int) Field { - m.Height(height) - return m -} - -// WithPosition sets the position of the multi-select field. -func (m *MultiSelect[T]) WithPosition(p FieldPosition) Field { - if m.filtering { - return m - } - m.keymap.Prev.SetEnabled(!p.IsFirst()) - m.keymap.Next.SetEnabled(!p.IsLast()) - m.keymap.Submit.SetEnabled(p.IsLast()) - return m -} - -// GetKey returns the multi-select's key. -func (m *MultiSelect[T]) GetKey() string { - return m.key -} - -// GetValue returns the multi-select's value. -func (m *MultiSelect[T]) GetValue() any { - return m.accessor.Get() -} - -// GetFiltering returns whether the multi-select is filtering. -func (m *MultiSelect[T]) GetFiltering() bool { - return m.filtering -} diff --git a/vendor/github.com/charmbracelet/huh/field_note.go b/vendor/github.com/charmbracelet/huh/field_note.go deleted file mode 100644 index cb4285c4..00000000 --- a/vendor/github.com/charmbracelet/huh/field_note.go +++ /dev/null @@ -1,371 +0,0 @@ -package huh - -import ( - "fmt" - "io" - "os" - "strings" - - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" -) - -// Note is a note field. -// -// A note is responsible for displaying information to the user. Use it to -// provide context around a different field. Generally, the notes are not -// interacted with unless the note has a next button `Next(true)`. -type Note struct { - id int - - title Eval[string] - description Eval[string] - nextLabel string - - focused bool - showNextButton bool - skip bool - - accessible bool - height int - width int - - theme *Theme - keymap NoteKeyMap -} - -// NewNote creates a new note field. -// -// A note is responsible for displaying information to the user. Use it to -// provide context around a different field. Generally, the notes are not -// interacted with unless the note has a next button `Next(true)`. -func NewNote() *Note { - return &Note{ - id: nextID(), - showNextButton: false, - skip: true, - nextLabel: "Next", - title: Eval[string]{cache: make(map[uint64]string)}, - description: Eval[string]{cache: make(map[uint64]string)}, - } -} - -// Title sets the note field's title. -// -// This title will be static, for dynamic titles use `TitleFunc`. -func (n *Note) Title(title string) *Note { - n.title.val = title - n.title.fn = nil - return n -} - -// TitleFunc sets the title func of the note field. -// -// The TitleFunc will be re-evaluated when the binding of the TitleFunc changes. -// This is useful when you want to display dynamic content and update the title -// of a note when another part of your form changes. -// -// See README.md#Dynamic for more usage information. -func (n *Note) TitleFunc(f func() string, bindings any) *Note { - n.title.fn = f - n.title.bindings = bindings - return n -} - -// Description sets the note field's description. -// -// This description will be static, for dynamic descriptions use `DescriptionFunc`. -func (n *Note) Description(description string) *Note { - n.description.val = description - n.description.fn = nil - return n -} - -// DescriptionFunc sets the description func of the note field. -// -// The DescriptionFunc will be re-evaluated when the binding of the -// DescriptionFunc changes. This is useful when you want to display dynamic -// content and update the description of a note when another part of your form -// changes. -// -// For example, you can make a dynamic markdown preview with the following Form & Group. -// -// huh.NewText().Title("Markdown").Value(&md), -// huh.NewNote().Height(20).Title("Preview"). -// DescriptionFunc(func() string { -// return md -// }, &md), -// -// Notice the `binding` of the Note is the same as the `Value` of the Text field. -// This binds the two values together, so that when the `Value` of the Text -// field changes so does the Note description. -func (n *Note) DescriptionFunc(f func() string, bindings any) *Note { - n.description.fn = f - n.description.bindings = bindings - return n -} - -// Height sets the note field's height. -func (n *Note) Height(height int) *Note { - n.height = height - return n -} - -// Next sets whether or not to show the next button. -// -// Title -// Description -// -// [ Next ] -func (n *Note) Next(show bool) *Note { - n.showNextButton = show - return n -} - -// NextLabel sets the next button label. -func (n *Note) NextLabel(label string) *Note { - n.nextLabel = label - return n -} - -// Focus focuses the note field. -func (n *Note) Focus() tea.Cmd { - n.focused = true - return nil -} - -// Blur blurs the note field. -func (n *Note) Blur() tea.Cmd { - n.focused = false - return nil -} - -// Error returns the error of the note field. -func (n *Note) Error() error { return nil } - -// Skip returns whether the note should be skipped or should be blocking. -func (n *Note) Skip() bool { return n.skip } - -// Zoom returns whether the note should be zoomed. -func (n *Note) Zoom() bool { return false } - -// KeyBinds returns the help message for the note field. -func (n *Note) KeyBinds() []key.Binding { - return []key.Binding{ - n.keymap.Prev, - n.keymap.Submit, - n.keymap.Next, - } -} - -// Init initializes the note field. -func (n *Note) Init() tea.Cmd { return nil } - -// Update updates the note field. -func (n *Note) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case updateFieldMsg: - var cmds []tea.Cmd - if ok, hash := n.title.shouldUpdate(); ok { - n.title.bindingsHash = hash - if !n.title.loadFromCache() { - n.title.loading = true - cmds = append(cmds, func() tea.Msg { - return updateTitleMsg{id: n.id, title: n.title.fn(), hash: hash} - }) - } - } - if ok, hash := n.description.shouldUpdate(); ok { - n.description.bindingsHash = hash - if !n.description.loadFromCache() { - n.description.loading = true - cmds = append(cmds, func() tea.Msg { - return updateDescriptionMsg{id: n.id, description: n.description.fn(), hash: hash} - }) - } - } - return n, tea.Batch(cmds...) - case updateTitleMsg: - if msg.id == n.id && msg.hash == n.title.bindingsHash { - n.title.update(msg.title) - } - case updateDescriptionMsg: - if msg.id == n.id && msg.hash == n.description.bindingsHash { - n.description.update(msg.description) - } - case tea.KeyMsg: - switch { - case key.Matches(msg, n.keymap.Prev): - return n, PrevField - case key.Matches(msg, n.keymap.Next, n.keymap.Submit): - return n, NextField - } - return n, NextField - } - return n, nil -} - -func (n *Note) activeStyles() *FieldStyles { - theme := n.theme - if theme == nil { - theme = ThemeCharm() - } - if n.focused { - return &theme.Focused - } - return &theme.Blurred -} - -// View renders the note field. -func (n *Note) View() string { - styles := n.activeStyles() - maxWidth := n.width - styles.Card.GetHorizontalFrameSize() - sb := strings.Builder{} - - if n.title.val != "" || n.title.fn != nil { - sb.WriteString(styles.NoteTitle.Render(wrap(n.title.val, maxWidth))) - } - if n.description.val != "" || n.description.fn != nil { - sb.WriteRune('\n') - sb.WriteString(wrap(render(n.description.val), maxWidth)) - sb.WriteRune('\n') - } - if n.showNextButton { - sb.WriteRune('\n') - sb.WriteString(styles.Next.Render(n.nextLabel)) - } - return styles.Card. - Height(n.height). - Width(n.width). - Render(sb.String()) -} - -// Run runs the note field. -func (n *Note) Run() error { - if n.accessible { - return n.runAccessible(os.Stdout, os.Stdin) - } - return Run(n) -} - -// runAccessible runs an accessible note field. -func (n *Note) runAccessible(w io.Writer, _ io.Reader) error { - styles := n.activeStyles() - if n.title.val != "" { - _, _ = fmt.Fprintln(w, styles.Title.Render(n.title.val)) - } - if n.description.val != "" { - _, _ = fmt.Fprintln(w, n.description.val) - } - return nil -} - -// WithTheme sets the theme on a note field. -func (n *Note) WithTheme(theme *Theme) Field { - if n.theme != nil { - return n - } - n.theme = theme - return n -} - -// WithKeyMap sets the keymap on a note field. -func (n *Note) WithKeyMap(k *KeyMap) Field { - n.keymap = k.Note - return n -} - -// WithAccessible sets the accessible mode of the note field. -func (n *Note) WithAccessible(accessible bool) Field { - n.accessible = accessible - return n -} - -// WithWidth sets the width of the note field. -func (n *Note) WithWidth(width int) Field { - n.width = width - return n -} - -// WithHeight sets the height of the note field. -func (n *Note) WithHeight(height int) Field { - n.Height(height) - return n -} - -// WithPosition sets the position information of the note field. -func (n *Note) WithPosition(p FieldPosition) Field { - // if the note is the only field on the screen, - // we shouldn't skip the entire group. - if p.Field == p.FirstField && p.Field == p.LastField { - n.skip = false - } - n.keymap.Prev.SetEnabled(!p.IsFirst()) - n.keymap.Next.SetEnabled(!p.IsLast()) - n.keymap.Submit.SetEnabled(p.IsLast()) - return n -} - -// GetValue satisfies the Field interface, notes do not have values. -func (n *Note) GetValue() any { return nil } - -// GetKey satisfies the Field interface, notes do not have keys. -func (n *Note) GetKey() string { return "" } - -func render(input string) string { - var result strings.Builder - var italic, bold, codeblock bool - var escape bool - - for _, char := range input { - if escape || codeblock { - result.WriteRune(char) - escape = false - continue - } - switch char { - case '\\': - escape = true - case '_': - if !italic { - result.WriteString("\033[3m") - italic = true - } else { - result.WriteString("\033[23m") - italic = false - } - case '*': - if !bold { - result.WriteString("\033[1m") - bold = true - } else { - result.WriteString("\033[22m") - bold = false - } - case '`': - if !codeblock { - result.WriteString("\033[0;37;40m") - result.WriteString(" ") - codeblock = true - } else { - result.WriteString(" ") - result.WriteString("\033[0m") - codeblock = false - - if bold { - result.WriteString("\033[1m") - } - if italic { - result.WriteString("\033[3m") - } - } - default: - result.WriteRune(char) - } - } - - // Reset any open formatting - result.WriteString("\033[0m") - - return result.String() -} diff --git a/vendor/github.com/charmbracelet/huh/field_select.go b/vendor/github.com/charmbracelet/huh/field_select.go deleted file mode 100644 index 5fe66fe4..00000000 --- a/vendor/github.com/charmbracelet/huh/field_select.go +++ /dev/null @@ -1,800 +0,0 @@ -package huh - -import ( - "cmp" - "fmt" - "io" - "os" - "strings" - "time" - - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/spinner" - "github.com/charmbracelet/bubbles/textinput" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/accessibility" - "github.com/charmbracelet/lipgloss" -) - -const ( - minHeight = 1 - defaultHeight = 10 -) - -// Select is a select field. -// -// A select field is a field that allows the user to select from a list of -// options. The options can be provided statically or dynamically using Options -// or OptionsFunc. The options can be filtered using "/" and navigation is done -// using j/k, up/down, or ctrl+n/ctrl+p keys. -type Select[T comparable] struct { - id int - accessor Accessor[T] - key string - - viewport viewport.Model - - title Eval[string] - description Eval[string] - options Eval[[]Option[T]] - filteredOptions []Option[T] - - validate func(T) error - err error - - selected int - focused bool - filtering bool - filter textinput.Model - spinner spinner.Model - - inline bool - width int - height int - accessible bool - theme *Theme - keymap SelectKeyMap -} - -// NewSelect creates a new select field. -// -// A select field is a field that allows the user to select from a list of -// options. The options can be provided statically or dynamically using Options -// or OptionsFunc. The options can be filtered using "/" and navigation is done -// using j/k, up/down, or ctrl+n/ctrl+p keys. -func NewSelect[T comparable]() *Select[T] { - filter := textinput.New() - filter.Prompt = "/" - - s := spinner.New(spinner.WithSpinner(spinner.Line)) - - return &Select[T]{ - accessor: &EmbeddedAccessor[T]{}, - validate: func(T) error { return nil }, - filtering: false, - filter: filter, - options: Eval[[]Option[T]]{cache: make(map[uint64][]Option[T])}, - title: Eval[string]{cache: make(map[uint64]string)}, - description: Eval[string]{cache: make(map[uint64]string)}, - spinner: s, - } -} - -// Value sets the value of the select field. -func (s *Select[T]) Value(value *T) *Select[T] { - return s.Accessor(NewPointerAccessor(value)) -} - -// Accessor sets the accessor of the select field. -func (s *Select[T]) Accessor(accessor Accessor[T]) *Select[T] { - s.accessor = accessor - s.selectValue(s.accessor.Get()) - s.updateValue() - return s -} - -func (s *Select[T]) selectValue(value T) { - for i, o := range s.options.val { - if o.Value == value { - s.selected = i - break - } - } -} - -// Key sets the key of the select field which can be used to retrieve the value -// after submission. -func (s *Select[T]) Key(key string) *Select[T] { - s.key = key - return s -} - -// Title sets the title of the select field. -// -// This title will be static, for dynamic titles use `TitleFunc`. -func (s *Select[T]) Title(title string) *Select[T] { - s.title.val = title - s.title.fn = nil - return s -} - -// TitleFunc sets the title func of the select field. -// -// This TitleFunc will be re-evaluated when the binding of the TitleFunc -// changes. This when you want to display dynamic content and update the title -// when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (s *Select[T]) TitleFunc(f func() string, bindings any) *Select[T] { - s.title.fn = f - s.title.bindings = bindings - return s -} - -// Filtering sets the filtering state of the select field. -func (s *Select[T]) Filtering(filtering bool) *Select[T] { - s.filtering = filtering - s.filter.Focus() - return s -} - -// Description sets the description of the select field. -// -// This description will be static, for dynamic descriptions use `DescriptionFunc`. -func (s *Select[T]) Description(description string) *Select[T] { - s.description.val = description - return s -} - -// DescriptionFunc sets the description func of the select field. -// -// This DescriptionFunc will be re-evaluated when the binding of the -// DescriptionFunc changes. This is useful when you want to display dynamic -// content and update the description when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (s *Select[T]) DescriptionFunc(f func() string, bindings any) *Select[T] { - s.description.fn = f - s.description.bindings = bindings - return s -} - -// Options sets the options of the select field. -// -// This is what your user will select from. -// -// Title -// Description -// -// -> Option 1 -// Option 2 -// Option 3 -// -// These options will be static, for dynamic options use `OptionsFunc`. -func (s *Select[T]) Options(options ...Option[T]) *Select[T] { - if len(options) <= 0 { - return s - } - s.options.val = options - s.filteredOptions = options - - s.selectOption() - - s.updateViewportHeight() - s.updateValue() - - return s -} - -func (s *Select[T]) selectOption() { - // Set the cursor to the existing value or the last selected option. - for i, option := range s.options.val { - if option.Value == s.accessor.Get() { - s.selected = i - break - } - if option.selected { - s.selected = i - break - } - } - s.viewport.YOffset = s.selected -} - -// OptionsFunc sets the options func of the select field. -// -// This OptionsFunc will be re-evaluated when the binding of the OptionsFunc -// changes. This is useful when you want to display dynamic content and update -// the options when another part of your form changes. -// -// For example, changing the state / provinces, based on the selected country. -// -// huh.NewSelect[string](). -// Options(huh.NewOptions("United States", "Canada", "Mexico")...). -// Value(&country). -// Title("Country"). -// Height(5), -// -// huh.NewSelect[string](). -// Title("State / Province"). // This can also be made dynamic with `TitleFunc`. -// OptionsFunc(func() []huh.Option[string] { -// s := states[country] -// time.Sleep(1000 * time.Millisecond) -// return huh.NewOptions(s...) -// }, &country), -// -// See examples/dynamic/dynamic-country/main.go for the full example. -func (s *Select[T]) OptionsFunc(f func() []Option[T], bindings any) *Select[T] { - s.options.fn = f - s.options.bindings = bindings - // If there is no height set, we should attach a static height since these - // options are possibly dynamic. - if s.height <= 0 { - s.height = defaultHeight - s.updateViewportHeight() - } - return s -} - -// Inline sets whether the select input should be inline. -func (s *Select[T]) Inline(v bool) *Select[T] { - s.inline = v - if v { - s.Height(1) - } - s.keymap.Left.SetEnabled(v) - s.keymap.Right.SetEnabled(v) - s.keymap.Up.SetEnabled(!v) - s.keymap.Down.SetEnabled(!v) - return s -} - -// Height sets the height of the select field. If the number of options exceeds -// the height, the select field will become scrollable. -func (s *Select[T]) Height(height int) *Select[T] { - s.height = height - s.updateViewportHeight() - return s -} - -// Validate sets the validation function of the select field. -func (s *Select[T]) Validate(validate func(T) error) *Select[T] { - s.validate = validate - return s -} - -// Error returns the error of the select field. -func (s *Select[T]) Error() error { return s.err } - -// Skip returns whether the select should be skipped or should be blocking. -func (*Select[T]) Skip() bool { return false } - -// Zoom returns whether the input should be zoomed. -func (*Select[T]) Zoom() bool { return false } - -// Focus focuses the select field. -func (s *Select[T]) Focus() tea.Cmd { - s.focused = true - return nil -} - -// Blur blurs the select field. -func (s *Select[T]) Blur() tea.Cmd { - value := s.accessor.Get() - if s.inline { - s.clearFilter() - s.selectValue(value) - } - s.focused = false - s.err = s.validate(value) - return nil -} - -// Hovered returns the value of the option under the cursor, and a bool -// indicating whether one was found. If there are no visible options, returns -// a zero-valued T and false. -func (s *Select[T]) Hovered() (T, bool) { - if len(s.filteredOptions) == 0 || s.selected >= len(s.filteredOptions) { - var zero T - return zero, false - } - return s.filteredOptions[s.selected].Value, true -} - -// KeyBinds returns the help keybindings for the select field. -func (s *Select[T]) KeyBinds() []key.Binding { - return []key.Binding{ - s.keymap.Up, - s.keymap.Down, - s.keymap.Left, - s.keymap.Right, - s.keymap.Filter, - s.keymap.SetFilter, - s.keymap.ClearFilter, - s.keymap.Prev, - s.keymap.Next, - s.keymap.Submit, - } -} - -// Init initializes the select field. -func (s *Select[T]) Init() tea.Cmd { - return nil -} - -// Update updates the select field. -func (s *Select[T]) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - s.updateViewportHeight() - - var cmd tea.Cmd - if s.filtering { - s.filter, cmd = s.filter.Update(msg) - } - - switch msg := msg.(type) { - case updateFieldMsg: - var cmds []tea.Cmd - if ok, hash := s.title.shouldUpdate(); ok { - s.title.bindingsHash = hash - if !s.title.loadFromCache() { - s.title.loading = true - cmds = append(cmds, func() tea.Msg { - return updateTitleMsg{id: s.id, title: s.title.fn(), hash: hash} - }) - } - } - if ok, hash := s.description.shouldUpdate(); ok { - s.description.bindingsHash = hash - if !s.description.loadFromCache() { - s.description.loading = true - cmds = append(cmds, func() tea.Msg { - return updateDescriptionMsg{id: s.id, description: s.description.fn(), hash: hash} - }) - } - } - if ok, hash := s.options.shouldUpdate(); ok { - s.clearFilter() - s.options.bindingsHash = hash - if s.options.loadFromCache() { - s.filteredOptions = s.options.val - s.selected = clamp(s.selected, 0, len(s.options.val)-1) - } else { - s.options.loading = true - s.options.loadingStart = time.Now() - cmds = append(cmds, func() tea.Msg { - return updateOptionsMsg[T]{id: s.id, hash: hash, options: s.options.fn()} - }, s.spinner.Tick) - } - } - return s, tea.Batch(cmds...) - - case spinner.TickMsg: - if !s.options.loading { - break - } - s.spinner, cmd = s.spinner.Update(msg) - return s, cmd - - case updateTitleMsg: - if msg.id == s.id && msg.hash == s.title.bindingsHash { - s.title.update(msg.title) - } - case updateDescriptionMsg: - if msg.id == s.id && msg.hash == s.description.bindingsHash { - s.description.update(msg.description) - } - case updateOptionsMsg[T]: - if msg.id == s.id && msg.hash == s.options.bindingsHash { - s.options.update(msg.options) - s.selectOption() - - // since we're updating the options, we need to update the selected - // cursor position and filteredOptions. - s.selected = clamp(s.selected, 0, len(msg.options)-1) - s.filteredOptions = msg.options - s.updateValue() - } - case tea.KeyMsg: - s.err = nil - switch { - case key.Matches(msg, s.keymap.Filter): - s.setFiltering(true) - return s, s.filter.Focus() - case key.Matches(msg, s.keymap.SetFilter): - if len(s.filteredOptions) <= 0 { - s.filter.SetValue("") - s.filteredOptions = s.options.val - } - s.setFiltering(false) - case key.Matches(msg, s.keymap.ClearFilter): - s.clearFilter() - case key.Matches(msg, s.keymap.Up, s.keymap.Left): - // When filtering we should ignore j/k keybindings - // - // XXX: Currently, the below check doesn't account for keymap - // changes. When making this fix it's worth considering ignoring - // whether to ignore all up/down keybindings as ignoring a-zA-Z0-9 - // may not be enough when international keyboards are considered. - if s.filtering && (msg.String() == "k" || msg.String() == "h") { - break - } - s.selected = s.selected - 1 - if s.selected < 0 { - s.selected = len(s.filteredOptions) - 1 - s.viewport.GotoBottom() - } - if s.selected < s.viewport.YOffset { - s.viewport.SetYOffset(s.selected) - } - s.updateValue() - case key.Matches(msg, s.keymap.GotoTop): - if s.filtering { - break - } - s.selected = 0 - s.viewport.GotoTop() - s.updateValue() - case key.Matches(msg, s.keymap.GotoBottom): - if s.filtering { - break - } - s.selected = len(s.filteredOptions) - 1 - s.viewport.GotoBottom() - case key.Matches(msg, s.keymap.HalfPageUp): - s.selected = max(s.selected-s.viewport.Height/2, 0) - s.viewport.HalfPageUp() - s.updateValue() - case key.Matches(msg, s.keymap.HalfPageDown): - s.selected = min(s.selected+s.viewport.Height/2, len(s.filteredOptions)-1) - s.viewport.HalfPageDown() - s.updateValue() - case key.Matches(msg, s.keymap.Down, s.keymap.Right): - // When filtering we should ignore j/k keybindings - // - // XXX: See note in the previous case match. - if s.filtering && (msg.String() == "j" || msg.String() == "l") { - break - } - s.selected = s.selected + 1 - if s.selected > len(s.filteredOptions)-1 { - s.selected = 0 - s.viewport.GotoTop() - } - if s.selected >= s.viewport.YOffset+s.viewport.Height { - s.viewport.ScrollDown(1) - } - s.updateValue() - case key.Matches(msg, s.keymap.Prev): - if s.selected >= len(s.filteredOptions) { - break - } - s.updateValue() - s.err = s.validate(s.accessor.Get()) - if s.err != nil { - return s, nil - } - s.updateValue() - return s, PrevField - case key.Matches(msg, s.keymap.Next, s.keymap.Submit): - if s.selected >= len(s.filteredOptions) { - break - } - s.setFiltering(false) - s.updateValue() - s.err = s.validate(s.accessor.Get()) - if s.err != nil { - return s, nil - } - s.updateValue() - return s, NextField - } - - if s.filtering { - s.filteredOptions = s.options.val - if s.filter.Value() != "" { - s.filteredOptions = nil - for _, option := range s.options.val { - if s.filterFunc(option.Key) { - s.filteredOptions = append(s.filteredOptions, option) - } - } - } - if len(s.filteredOptions) > 0 { - s.selected = min(s.selected, len(s.filteredOptions)-1) - } - } - - _, offset, height := s.optionsView() - if offset > -1 && height > 0 && (offset < s.viewport.YOffset || height+offset >= s.viewport.YOffset+s.viewport.Height) { - s.viewport.SetYOffset(offset) - } - } - - return s, cmd -} - -func (s *Select[T]) updateValue() { - if s.selected < len(s.filteredOptions) && s.selected >= 0 { - s.accessor.Set(s.filteredOptions[s.selected].Value) - } -} - -// updateViewportHeight updates the viewport size according to the Height setting -// on this select field. -func (s *Select[T]) updateViewportHeight() { - // If no height is set size the viewport to the number of options. - if s.height <= 0 { - v, _, _ := s.optionsView() - s.viewport.Height = lipgloss.Height(v) - return - } - - offset := 0 - if ss := s.titleView(); ss != "" { - offset += lipgloss.Height(ss) - } - if ss := s.descriptionView(); ss != "" { - offset += lipgloss.Height(ss) - } - - s.viewport.Height = max(minHeight, s.height-offset) -} - -func (s *Select[T]) activeStyles() *FieldStyles { - theme := s.theme - if theme == nil { - theme = ThemeCharm() - } - if s.focused { - return &theme.Focused - } - return &theme.Blurred -} - -func (s *Select[T]) titleView() string { - var ( - styles = s.activeStyles() - sb = strings.Builder{} - maxWidth = s.width - styles.Base.GetHorizontalFrameSize() - ) - if s.filtering { - sb.WriteString(s.filter.View()) - } else if s.filter.Value() != "" && !s.inline { - sb.WriteString(styles.Title.Render(wrap(s.title.val, maxWidth))) - sb.WriteString(styles.Description.Render("/" + s.filter.Value())) - } else { - sb.WriteString(styles.Title.Render(wrap(s.title.val, maxWidth))) - } - if s.err != nil { - sb.WriteString(styles.ErrorIndicator.String()) - } - return sb.String() -} - -func (s *Select[T]) descriptionView() string { - if s.description.val == "" { - return "" - } - maxWidth := s.width - s.activeStyles().Base.GetHorizontalFrameSize() - return s.activeStyles().Description.Render(wrap(s.description.val, maxWidth)) -} - -func (s *Select[T]) optionsView() (string, int, int) { - var ( - styles = s.activeStyles() - sb strings.Builder - ) - - if s.options.loading && time.Since(s.options.loadingStart) > spinnerShowThreshold { - s.spinner.Style = s.activeStyles().MultiSelectSelector.UnsetString() - sb.WriteString(s.spinner.View() + " Loading...") - return sb.String(), -1, 1 - } - - if s.inline { - option := styles.TextInput.Placeholder.Render("No matches") - if len(s.filteredOptions) > 0 { - option = styles.SelectedOption.Render(s.filteredOptions[s.selected].Key) - } - return lipgloss.NewStyle(). - Width(s.width). - Render(lipgloss.JoinHorizontal( - lipgloss.Left, - styles.PrevIndicator.Faint(s.selected <= 0).String(), - option, - styles.NextIndicator.Faint(s.selected == len(s.filteredOptions)-1).String(), - )), - -1, 1 - } - - var cursorOffset int - var cursorHeight int - for i, option := range s.filteredOptions { - selected := s.selected == i - line := s.renderOption(option, selected) - if i < s.selected { - cursorOffset += lipgloss.Height(line) - } - if selected { - cursorHeight = lipgloss.Height(line) - } - - sb.WriteString(line) - if i < len(s.options.val)-1 { - sb.WriteString("\n") - } - } - - for i := len(s.filteredOptions); i < len(s.options.val)-1; i++ { - sb.WriteString("\n") - } - - return sb.String(), cursorOffset, cursorHeight -} - -func (s *Select[T]) renderOption(option Option[T], selected bool) string { - var ( - styles = s.activeStyles() - cursor = styles.SelectSelector.String() - cursorW = lipgloss.Width(cursor) - maxWidth = s.width - s.activeStyles().Base.GetHorizontalFrameSize() - cursorW - ) - - key := wrap(option.Key, maxWidth) - - if selected { - return lipgloss.JoinHorizontal( - lipgloss.Left, - cursor, - styles.SelectedOption.Render(key), - ) - } - return lipgloss.JoinHorizontal( - lipgloss.Left, - strings.Repeat(" ", cursorW), - styles.UnselectedOption.Render(key), - ) -} - -// View renders the select field. -func (s *Select[T]) View() string { - styles := s.activeStyles() - vpc, _, _ := s.optionsView() - s.viewport.SetContent(vpc) - - var parts []string - if s.title.val != "" || s.title.fn != nil { - parts = append(parts, s.titleView()) - } - if s.description.val != "" || s.description.fn != nil { - parts = append(parts, s.descriptionView()) - } - parts = append(parts, s.viewport.View()) - return styles.Base.Width(s.width).Height(s.height). - Render(lipgloss.JoinVertical(lipgloss.Top, parts...)) -} - -// clearFilter clears the value of the filter. -func (s *Select[T]) clearFilter() { - s.filter.SetValue("") - s.filteredOptions = s.options.val - s.setFiltering(false) -} - -// setFiltering sets the filter of the select field. -func (s *Select[T]) setFiltering(filtering bool) { - if s.inline && filtering { - s.filter.Width = lipgloss.Width(s.titleView()) - 1 - 1 - } - s.filtering = filtering - s.keymap.SetFilter.SetEnabled(filtering) - s.keymap.Filter.SetEnabled(!filtering) - s.keymap.ClearFilter.SetEnabled(!filtering && s.filter.Value() != "") -} - -// filterFunc returns true if the option matches the filter. -func (s *Select[T]) filterFunc(option string) bool { - // XXX: remove diacritics or allow customization of filter function. - return strings.Contains(strings.ToLower(option), strings.ToLower(s.filter.Value())) -} - -// Run runs the select field. -func (s *Select[T]) Run() error { - if s.accessible { - return s.runAccessible(os.Stdout, os.Stdin) - } - return Run(s) -} - -// runAccessible runs an accessible select field. -func (s *Select[T]) runAccessible(w io.Writer, r io.Reader) error { - styles := s.activeStyles() - _, _ = fmt.Fprintln(w, styles.Title. - PaddingRight(1). - Render(cmp.Or(s.title.val, "Select:"))) - - for i, option := range s.options.val { - _, _ = fmt.Fprintf(w, "%d. %s\n", i+1, option.Key) - } - - prompt := fmt.Sprintf("Input a number between %d and %d: ", 1, len(s.options.val)) - for { - selected := s.selected + 1 - choice := accessibility.PromptInt(w, r, prompt, 1, len(s.options.val), &selected) - option := s.options.val[choice-1] - if err := s.validate(option.Value); err != nil { - _, _ = fmt.Fprintln(w, err.Error()) - _, _ = fmt.Fprintln(w) - continue - } - s.accessor.Set(option.Value) - return nil - } -} - -// WithTheme sets the theme of the select field. -func (s *Select[T]) WithTheme(theme *Theme) Field { - if s.theme != nil { - return s - } - s.theme = theme - s.filter.Cursor.Style = theme.Focused.TextInput.Cursor - s.filter.Cursor.TextStyle = theme.Focused.TextInput.CursorText - s.filter.PromptStyle = theme.Focused.TextInput.Prompt - s.filter.TextStyle = theme.Focused.TextInput.Text - s.filter.PlaceholderStyle = theme.Focused.TextInput.Placeholder - s.updateViewportHeight() - return s -} - -// WithKeyMap sets the keymap on a select field. -func (s *Select[T]) WithKeyMap(k *KeyMap) Field { - s.keymap = k.Select - s.keymap.Left.SetEnabled(s.inline) - s.keymap.Right.SetEnabled(s.inline) - s.keymap.Up.SetEnabled(!s.inline) - s.keymap.Down.SetEnabled(!s.inline) - return s -} - -// WithAccessible sets the accessible mode of the select field. -func (s *Select[T]) WithAccessible(accessible bool) Field { - s.accessible = accessible - return s -} - -// WithWidth sets the width of the select field. -func (s *Select[T]) WithWidth(width int) Field { - s.width = width - return s -} - -// WithHeight sets the height of the select field. -func (s *Select[T]) WithHeight(height int) Field { - return s.Height(height) -} - -// WithPosition sets the position of the select field. -func (s *Select[T]) WithPosition(p FieldPosition) Field { - if s.filtering { - return s - } - s.keymap.Prev.SetEnabled(!p.IsFirst()) - s.keymap.Next.SetEnabled(!p.IsLast()) - s.keymap.Submit.SetEnabled(p.IsLast()) - return s -} - -// GetKey returns the key of the field. -func (s *Select[T]) GetKey() string { return s.key } - -// GetValue returns the value of the field. -func (s *Select[T]) GetValue() any { - return s.accessor.Get() -} - -// GetFiltering returns the filtering state of the field. -func (s *Select[T]) GetFiltering() bool { - return s.filtering -} diff --git a/vendor/github.com/charmbracelet/huh/field_text.go b/vendor/github.com/charmbracelet/huh/field_text.go deleted file mode 100644 index 827ad65a..00000000 --- a/vendor/github.com/charmbracelet/huh/field_text.go +++ /dev/null @@ -1,498 +0,0 @@ -package huh - -import ( - "cmp" - "fmt" - "io" - "os" - "os/exec" - "strings" - - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/textarea" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/accessibility" - "github.com/charmbracelet/lipgloss" -) - -// Text is a text field. -// -// A text box is responsible for getting multi-line input from the user. Use -// it to gather longer-form user input. The Text field can be filled with an -// EDITOR. -type Text struct { - accessor Accessor[string] - key string - id int - - title Eval[string] - description Eval[string] - placeholder Eval[string] - - externalEditor bool - editorCmd string - editorArgs []string - editorExtension string - - textarea textarea.Model - - focused bool - validate func(string) error - err error - - accessible bool - width int - - theme *Theme - keymap TextKeyMap -} - -// NewText creates a new text field. -// -// A text box is responsible for getting multi-line input from the user. Use -// it to gather longer-form user input. The Text field can be filled with an -// EDITOR. -func NewText() *Text { - text := textarea.New() - text.ShowLineNumbers = false - text.Prompt = "" - text.FocusedStyle.CursorLine = lipgloss.NewStyle() - - editorCmd, editorArgs := getEditor() - - t := &Text{ - accessor: &EmbeddedAccessor[string]{}, - id: nextID(), - textarea: text, - validate: func(string) error { return nil }, - externalEditor: true, - editorCmd: editorCmd, - editorArgs: editorArgs, - editorExtension: "md", - title: Eval[string]{cache: make(map[uint64]string)}, - description: Eval[string]{cache: make(map[uint64]string)}, - placeholder: Eval[string]{cache: make(map[uint64]string)}, - } - - return t -} - -// Value sets the value of the text field. -func (t *Text) Value(value *string) *Text { - return t.Accessor(NewPointerAccessor(value)) -} - -// Accessor sets the accessor of the text field. -func (t *Text) Accessor(accessor Accessor[string]) *Text { - t.accessor = accessor - t.textarea.SetValue(t.accessor.Get()) - return t -} - -// Key sets the key of the text field. -func (t *Text) Key(key string) *Text { - t.key = key - return t -} - -// Title sets the text field's title. -// -// This title will be static, for dynamic titles use `TitleFunc`. -func (t *Text) Title(title string) *Text { - t.title.val = title - t.title.fn = nil - return t -} - -// TitleFunc sets the text field's title func. -// -// The TitleFunc will be re-evaluated when the binding of the TitleFunc changes. -// This is useful when you want to display dynamic content and update the title -// when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (t *Text) TitleFunc(f func() string, bindings any) *Text { - t.title.fn = f - t.title.bindings = bindings - return t -} - -// Description sets the description of the text field. -// -// This description will be static, for dynamic description use `DescriptionFunc`. -func (t *Text) Description(description string) *Text { - t.description.val = description - t.description.fn = nil - return t -} - -// DescriptionFunc sets the description func of the text field. -// -// The DescriptionFunc will be re-evaluated when the binding of the -// DescriptionFunc changes. This is useful when you want to display dynamic -// content and update the description when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (t *Text) DescriptionFunc(f func() string, bindings any) *Text { - t.description.fn = f - t.description.bindings = bindings - return t -} - -// Lines sets the number of lines to show of the text field. -func (t *Text) Lines(lines int) *Text { - t.textarea.SetHeight(lines) - return t -} - -// CharLimit sets the character limit of the text field. -func (t *Text) CharLimit(charlimit int) *Text { - t.textarea.CharLimit = charlimit - return t -} - -// ShowLineNumbers sets whether or not to show line numbers. -func (t *Text) ShowLineNumbers(show bool) *Text { - t.textarea.ShowLineNumbers = show - return t -} - -// Placeholder sets the placeholder of the text field. -// -// This placeholder will be static, for dynamic placeholders use `PlaceholderFunc`. -func (t *Text) Placeholder(str string) *Text { - t.textarea.Placeholder = str - return t -} - -// PlaceholderFunc sets the placeholder func of the text field. -// -// The PlaceholderFunc will be re-evaluated when the binding of the -// PlaceholderFunc changes. This is useful when you want to display dynamic -// content and update the placeholder when another part of your form changes. -// -// See README#Dynamic for more usage information. -func (t *Text) PlaceholderFunc(f func() string, bindings any) *Text { - t.placeholder.fn = f - t.placeholder.bindings = bindings - return t -} - -// Validate sets the validation function of the text field. -func (t *Text) Validate(validate func(string) error) *Text { - t.validate = validate - return t -} - -// ExternalEditor sets whether option to launch an editor is available. -func (t *Text) ExternalEditor(enabled bool) *Text { - t.externalEditor = enabled - return t -} - -const defaultEditor = "nano" - -// getEditor returns the editor command and arguments. -func getEditor() (string, []string) { - editor := strings.Fields(os.Getenv("EDITOR")) - if len(editor) > 0 { - return editor[0], editor[1:] - } - return defaultEditor, nil -} - -// Editor specifies which editor to use. -// -// The first argument provided is used as the editor command (vim, nvim, nano, etc...) -// The following (optional) arguments provided are passed as arguments to the editor command. -func (t *Text) Editor(editor ...string) *Text { - if len(editor) > 0 { - t.editorCmd = editor[0] - } - if len(editor) > 1 { - t.editorArgs = editor[1:] - } - return t -} - -// EditorExtension specifies arguments to pass into the editor. -func (t *Text) EditorExtension(extension string) *Text { - t.editorExtension = extension - return t -} - -// Error returns the error of the text field. -func (t *Text) Error() error { return t.err } - -// Skip returns whether the textarea should be skipped or should be blocking. -func (*Text) Skip() bool { return false } - -// Zoom returns whether the note should be zoomed. -func (*Text) Zoom() bool { return false } - -// Focus focuses the text field. -func (t *Text) Focus() tea.Cmd { - t.focused = true - return t.textarea.Focus() -} - -// Blur blurs the text field. -func (t *Text) Blur() tea.Cmd { - t.focused = false - t.accessor.Set(t.textarea.Value()) - t.textarea.Blur() - t.err = t.validate(t.accessor.Get()) - return nil -} - -// KeyBinds returns the help message for the text field. -func (t *Text) KeyBinds() []key.Binding { - t.keymap.Editor.SetEnabled(t.externalEditor) - return []key.Binding{t.keymap.NewLine, t.keymap.Editor, t.keymap.Prev, t.keymap.Submit, t.keymap.Next} -} - -type updateValueMsg []byte - -// Init initializes the text field. -func (t *Text) Init() tea.Cmd { - t.textarea.Blur() - return nil -} - -// Update updates the text field. -func (t *Text) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmds []tea.Cmd - var cmd tea.Cmd - - switch msg := msg.(type) { - case updateValueMsg: - t.textarea.SetValue(string(msg)) - t.textarea, cmd = t.textarea.Update(msg) - cmds = append(cmds, cmd) - t.accessor.Set(t.textarea.Value()) - case updateFieldMsg: - var cmds []tea.Cmd - if ok, hash := t.placeholder.shouldUpdate(); ok { - t.placeholder.bindingsHash = hash - if t.placeholder.loadFromCache() { - t.textarea.Placeholder = t.placeholder.val - } else { - t.placeholder.loading = true - cmds = append(cmds, func() tea.Msg { - return updatePlaceholderMsg{id: t.id, placeholder: t.placeholder.fn(), hash: hash} - }) - } - } - if ok, hash := t.title.shouldUpdate(); ok { - t.title.bindingsHash = hash - if !t.title.loadFromCache() { - cmds = append(cmds, func() tea.Msg { - return updateTitleMsg{id: t.id, title: t.title.fn(), hash: hash} - }) - } - } - if ok, hash := t.description.shouldUpdate(); ok { - t.description.bindingsHash = hash - if !t.description.loadFromCache() { - t.description.loading = true - cmds = append(cmds, func() tea.Msg { - return updateDescriptionMsg{id: t.id, description: t.description.fn(), hash: hash} - }) - } - } - return t, tea.Batch(cmds...) - case updatePlaceholderMsg: - if t.id == msg.id && t.placeholder.bindingsHash == msg.hash { - t.placeholder.update(msg.placeholder) - t.textarea.Placeholder = msg.placeholder - } - case updateTitleMsg: - if t.id == msg.id && t.title.bindingsHash == msg.hash { - t.title.update(msg.title) - } - case updateDescriptionMsg: - if t.id == msg.id && t.description.bindingsHash == msg.hash { - t.description.update(msg.description) - } - case tea.KeyMsg: - t.err = nil - - switch { - case key.Matches(msg, t.keymap.Editor): - ext := strings.TrimPrefix(t.editorExtension, ".") - tmpFile, _ := os.CreateTemp(os.TempDir(), "*."+ext) - cmd := exec.Command(t.editorCmd, append(t.editorArgs, tmpFile.Name())...) //nolint:gosec - _ = os.WriteFile(tmpFile.Name(), []byte(t.textarea.Value()), 0o644) //nolint:mnd,gosec - cmds = append(cmds, tea.ExecProcess(cmd, func(error) tea.Msg { - content, _ := os.ReadFile(tmpFile.Name()) - _ = os.Remove(tmpFile.Name()) - return updateValueMsg(content) - })) - case key.Matches(msg, t.keymap.Next, t.keymap.Submit): - value := t.textarea.Value() - t.err = t.validate(value) - if t.err != nil { - return t, nil - } - cmds = append(cmds, NextField) - case key.Matches(msg, t.keymap.Prev): - value := t.textarea.Value() - t.err = t.validate(value) - if t.err != nil { - return t, nil - } - cmds = append(cmds, PrevField) - } - } - - t.textarea, cmd = t.textarea.Update(msg) - cmds = append(cmds, cmd) - t.accessor.Set(t.textarea.Value()) - - return t, tea.Batch(cmds...) -} - -func (t *Text) activeStyles() *FieldStyles { - theme := t.theme - if theme == nil { - theme = ThemeCharm() - } - if t.focused { - return &theme.Focused - } - return &theme.Blurred -} - -func (t *Text) activeTextAreaStyles() *textarea.Style { - if t.theme == nil { - return &t.textarea.BlurredStyle - } - if t.focused { - return &t.textarea.FocusedStyle - } - return &t.textarea.BlurredStyle -} - -// View renders the text field. -func (t *Text) View() string { - styles := t.activeStyles() - textareaStyles := t.activeTextAreaStyles() - - // NB: since the method is on a pointer receiver these are being mutated. - // Because this runs on every render this shouldn't matter in practice, - // however. - textareaStyles.Placeholder = styles.TextInput.Placeholder - textareaStyles.Text = styles.TextInput.Text - textareaStyles.Prompt = styles.TextInput.Prompt - textareaStyles.CursorLine = styles.TextInput.Text - t.textarea.Cursor.Style = styles.TextInput.Cursor - t.textarea.Cursor.TextStyle = styles.TextInput.CursorText - - maxWidth := t.width - styles.Base.GetHorizontalFrameSize() - var parts []string - if t.title.val != "" || t.title.fn != nil { - header := styles.Title.Render(wrap(t.title.val, maxWidth)) - if t.err != nil { - header += styles.ErrorIndicator.String() - } - parts = append(parts, header) - } - if t.description.val != "" || t.description.fn != nil { - parts = append(parts, styles.Description.Render(wrap(t.description.val, maxWidth))) - } - parts = append(parts, t.textarea.View()) - - return styles.Base.Render(lipgloss.JoinVertical(lipgloss.Top, parts...)) -} - -// Run runs the text field. -func (t *Text) Run() error { - if t.accessible { - return t.runAccessible(os.Stdout, os.Stdin) - } - return Run(t) -} - -// runAccessible runs an accessible text field. -func (t *Text) runAccessible(w io.Writer, r io.Reader) error { - styles := t.activeStyles() - prompt := styles.Title. - PaddingRight(1). - Render(cmp.Or(t.title.val, "Input:")) - t.accessor.Set(accessibility.PromptString( - w, - r, - prompt, - t.GetValue().(string), - func(input string) error { - if err := t.validate(input); err != nil { - // Handle the error from t.validate, return it - return err - } - - if t.textarea.CharLimit > 0 && len(input) > t.textarea.CharLimit { - return fmt.Errorf("Input cannot exceed %d characters", t.textarea.CharLimit) - } - return nil - }, - )) - return nil -} - -// WithTheme sets the theme on a text field. -func (t *Text) WithTheme(theme *Theme) Field { - if t.theme != nil { - return t - } - t.theme = theme - return t -} - -// WithKeyMap sets the keymap on a text field. -func (t *Text) WithKeyMap(k *KeyMap) Field { - t.keymap = k.Text - t.textarea.KeyMap.InsertNewline.SetKeys(t.keymap.NewLine.Keys()...) - return t -} - -// WithAccessible sets the accessible mode of the text field. -func (t *Text) WithAccessible(accessible bool) Field { - t.accessible = accessible - return t -} - -// WithWidth sets the width of the text field. -func (t *Text) WithWidth(width int) Field { - t.width = width - t.textarea.SetWidth(width - t.activeStyles().Base.GetHorizontalFrameSize()) - return t -} - -// WithHeight sets the height of the text field. -func (t *Text) WithHeight(height int) Field { - adjust := 0 - if t.title.val != "" { - adjust++ - } - if t.description.val != "" { - adjust++ - } - t.textarea.SetHeight(height - t.activeStyles().Base.GetVerticalFrameSize() - adjust) - return t -} - -// WithPosition sets the position information of the text field. -func (t *Text) WithPosition(p FieldPosition) Field { - t.keymap.Prev.SetEnabled(!p.IsFirst()) - t.keymap.Next.SetEnabled(!p.IsLast()) - t.keymap.Submit.SetEnabled(p.IsLast()) - return t -} - -// GetKey returns the key of the field. -func (t *Text) GetKey() string { return t.key } - -// GetValue returns the value of the field. -func (t *Text) GetValue() any { - return t.accessor.Get() -} diff --git a/vendor/github.com/charmbracelet/huh/form.go b/vendor/github.com/charmbracelet/huh/form.go deleted file mode 100644 index f04bd72e..00000000 --- a/vendor/github.com/charmbracelet/huh/form.go +++ /dev/null @@ -1,720 +0,0 @@ -package huh - -import ( - "cmp" - "context" - "errors" - "fmt" - "io" - "os" - "sync" - "time" - - "github.com/charmbracelet/bubbles/help" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/selector" -) - -const defaultWidth = 80 - -// Internal ID management. Used during animating to ensure that frame messages -// are received only by spinner components that sent them. -var ( - lastID int - idMtx sync.Mutex -) - -// Return the next ID we should use on the Model. -func nextID() int { - idMtx.Lock() - defer idMtx.Unlock() - lastID++ - return lastID -} - -// FormState represents the current state of the form. -type FormState int - -const ( - // StateNormal is when the user is completing the form. - StateNormal FormState = iota - - // StateCompleted is when the user has completed the form. - StateCompleted - - // StateAborted is when the user has aborted the form. - StateAborted -) - -// ErrUserAborted is the error returned when a user exits the form before submitting. -var ErrUserAborted = errors.New("user aborted") - -// ErrTimeout is the error returned when the timeout is reached. -var ErrTimeout = errors.New("timeout") - -// ErrTimeoutUnsupported is the error returned when timeout is used while in accessible mode. -var ErrTimeoutUnsupported = errors.New("timeout is not supported in accessible mode") - -// Form is a collection of groups that are displayed one at a time on a "page". -// -// The form can navigate between groups and is complete once all the groups are -// complete. -type Form struct { - // collection of groups - selector *selector.Selector[*Group] - - results map[string]any - - // callbacks - SubmitCmd tea.Cmd - CancelCmd tea.Cmd - - State FormState - - // whether or not to use bubble tea rendering for accessibility - // purposes, if true, the form will render with basic prompting primitives - // to be more accessible to screen readers. - accessible bool - - quitting bool - aborted bool - - // options - width int - height int - theme *Theme - keymap *KeyMap - timeout time.Duration - teaOptions []tea.ProgramOption - - layout Layout - - // accessible mode IO - output io.Writer - input io.Reader -} - -// NewForm returns a form with the given groups and default themes and -// keybindings. -// -// Use With* methods to customize the form with options, such as setting -// different themes and keybindings. -func NewForm(groups ...*Group) *Form { - selector := selector.NewSelector(groups) - - f := &Form{ - selector: selector, - keymap: NewDefaultKeyMap(), - results: make(map[string]any), - layout: LayoutDefault, - teaOptions: []tea.ProgramOption{ - tea.WithOutput(os.Stderr), - tea.WithReportFocus(), - }, - } - - // NB: If dynamic forms come into play this will need to be applied when - // groups and fields are added. - f.WithKeyMap(f.keymap) - f.WithWidth(f.width) - f.WithHeight(f.height) - f.UpdateFieldPositions() - - if os.Getenv("TERM") == "dumb" { - f.WithWidth(defaultWidth) - f.WithAccessible(true) - } - - return f -} - -// Field is a primitive of a form. -// -// A field represents a single input control on a form such as a text input, -// confirm button, select option, etc... -// -// Each field implements the Bubble Tea Model interface. -type Field interface { - // Bubble Tea Model - Init() tea.Cmd - Update(tea.Msg) (tea.Model, tea.Cmd) - View() string - - // Bubble Tea Events - Blur() tea.Cmd - Focus() tea.Cmd - - // Errors and Validation - Error() error - - // Run runs the field individually. - Run() error - - runAccessible(w io.Writer, r io.Reader) error - - // Skip returns whether this input should be skipped or not. - Skip() bool - - // Zoom returns whether this input should be zoomed or not. - // Zoom allows the field to take focus of the group / form height. - Zoom() bool - - // KeyBinds returns help keybindings. - KeyBinds() []key.Binding - - // WithTheme sets the theme on a field. - WithTheme(*Theme) Field - - // WithAccessible sets whether the field should run in accessible mode. - WithAccessible(bool) Field - - // WithKeyMap sets the keymap on a field. - WithKeyMap(*KeyMap) Field - - // WithWidth sets the width of a field. - WithWidth(int) Field - - // WithHeight sets the height of a field. - WithHeight(int) Field - - // WithPosition tells the field the index of the group and position it is in. - WithPosition(FieldPosition) Field - - // GetKey returns the field's key. - GetKey() string - - // GetValue returns the field's value. - GetValue() any -} - -// FieldPosition is positional information about the given field and form. -type FieldPosition struct { - Group int - Field int - FirstField int - LastField int - GroupCount int - FirstGroup int - LastGroup int -} - -// IsFirst returns whether a field is the form's first field. -func (p FieldPosition) IsFirst() bool { - return p.Field == p.FirstField && p.Group == p.FirstGroup -} - -// IsLast returns whether a field is the form's last field. -func (p FieldPosition) IsLast() bool { - return p.Field == p.LastField && p.Group == p.LastGroup -} - -// nextGroupMsg is a message to move to the next group. -type nextGroupMsg struct{} - -// prevGroupMsg is a message to move to the previous group. -type prevGroupMsg struct{} - -// nextGroup is the command to move to the next group. -func nextGroup() tea.Msg { - return nextGroupMsg{} -} - -// prevGroup is the command to move to the previous group. -func prevGroup() tea.Msg { - return prevGroupMsg{} -} - -// WithAccessible sets the form to run in accessible mode to avoid redrawing the -// views which makes it easier for screen readers to read and describe the form. -// -// This avoids using the Bubble Tea renderer and instead simply uses basic -// terminal prompting to gather input which degrades the user experience but -// provides accessibility. -func (f *Form) WithAccessible(accessible bool) *Form { - f.accessible = accessible - return f -} - -// WithShowHelp sets whether or not the form should show help. -// -// This allows the form groups and field to show what keybindings are available -// to the user. -func (f *Form) WithShowHelp(v bool) *Form { - f.selector.Range(func(_ int, group *Group) bool { - group.WithShowHelp(v) - return true - }) - return f -} - -// WithShowErrors sets whether or not the form should show errors. -// -// This allows the form groups and fields to show errors when the Validate -// function returns an error. -func (f *Form) WithShowErrors(v bool) *Form { - f.selector.Range(func(_ int, group *Group) bool { - group.WithShowErrors(v) - return true - }) - return f -} - -// WithTheme sets the theme on a form. -// -// This allows all groups and fields to be themed consistently, however themes -// can be applied to each group and field individually for more granular -// control. -func (f *Form) WithTheme(theme *Theme) *Form { - if theme == nil { - return f - } - f.theme = theme - f.selector.Range(func(_ int, group *Group) bool { - group.WithTheme(theme) - return true - }) - return f -} - -// WithKeyMap sets the keymap on a form. -// -// This allows customization of the form key bindings. -func (f *Form) WithKeyMap(keymap *KeyMap) *Form { - if keymap == nil { - return f - } - f.keymap = keymap - f.selector.Range(func(_ int, group *Group) bool { - group.WithKeyMap(keymap) - return true - }) - f.UpdateFieldPositions() - return f -} - -// WithWidth sets the width of a form. -// -// This allows all groups and fields to be sized consistently, however width -// can be applied to each group and field individually for more granular -// control. -func (f *Form) WithWidth(width int) *Form { - if width <= 0 { - return f - } - f.width = width - f.selector.Range(func(_ int, group *Group) bool { - width := f.layout.GroupWidth(f, group, width) - group.WithWidth(width) - return true - }) - return f -} - -// WithHeight sets the height of a form. -func (f *Form) WithHeight(height int) *Form { - if height <= 0 { - return f - } - f.height = height - f.selector.Range(func(_ int, group *Group) bool { - group.WithHeight(height) - return true - }) - return f -} - -// WithOutput sets the io.Writer to output the form. -// Default is STDOUT when [Form] is accessible (set with [Form.WithAccessible], STDERR otherwise. -func (f *Form) WithOutput(w io.Writer) *Form { - f.output = w - f.teaOptions = append(f.teaOptions, tea.WithOutput(w)) - return f -} - -// WithInput sets the io.Reader to the input form. -// Default is STDIN. -func (f *Form) WithInput(r io.Reader) *Form { - f.input = r - f.teaOptions = append(f.teaOptions, tea.WithInput(r)) - return f -} - -// WithTimeout sets the duration for the form to be killed. -func (f *Form) WithTimeout(t time.Duration) *Form { - f.timeout = t - return f -} - -// WithProgramOptions sets the tea options of the form. -func (f *Form) WithProgramOptions(opts ...tea.ProgramOption) *Form { - f.teaOptions = opts - return f -} - -// WithLayout sets the layout on a form. -// -// This allows customization of the form group layout. -func (f *Form) WithLayout(layout Layout) *Form { - f.layout = layout - return f -} - -// UpdateFieldPositions sets the position on all the fields. -func (f *Form) UpdateFieldPositions() *Form { - firstGroup := 0 - lastGroup := f.selector.Total() - 1 - - // determine the first non-hidden group. - f.selector.Range(func(_ int, g *Group) bool { - if !f.isGroupHidden(g) { - return false - } - firstGroup++ - return true - }) - - // determine the last non-hidden group. - f.selector.ReverseRange(func(_ int, g *Group) bool { - if !f.isGroupHidden(g) { - return false - } - lastGroup-- - return true - }) - - f.selector.Range(func(g int, group *Group) bool { - // determine the first non-skippable field. - var firstField int - group.selector.Range(func(_ int, field Field) bool { - if !field.Skip() || group.selector.Total() == 1 { - return false - } - firstField++ - return true - }) - - // determine the last non-skippable field. - var lastField int - group.selector.ReverseRange(func(i int, field Field) bool { - lastField = i - if !field.Skip() || group.selector.Total() == 1 { - return false - } - return true - }) - - group.selector.Range(func(i int, field Field) bool { - field.WithPosition(FieldPosition{ - Group: g, - Field: i, - FirstField: firstField, - LastField: lastField, - FirstGroup: firstGroup, - LastGroup: lastGroup, - }) - return true - }) - - return true - }) - return f -} - -// Errors returns the current groups' errors. -func (f *Form) Errors() []error { - return f.selector.Selected().Errors() -} - -// Help returns the current groups' help. -func (f *Form) Help() help.Model { - return f.selector.Selected().help -} - -// KeyBinds returns the current fields' keybinds. -func (f *Form) KeyBinds() []key.Binding { - group := f.selector.Selected() - return group.selector.Selected().KeyBinds() -} - -// Get returns a result from the form. -func (f *Form) Get(key string) any { - return f.results[key] -} - -// GetString returns a result as a string from the form. -func (f *Form) GetString(key string) string { - v, ok := f.results[key].(string) - if !ok { - return "" - } - return v -} - -// GetInt returns a result as a int from the form. -func (f *Form) GetInt(key string) int { - v, ok := f.results[key].(int) - if !ok { - return 0 - } - return v -} - -// GetBool returns a result as a string from the form. -func (f *Form) GetBool(key string) bool { - v, ok := f.results[key].(bool) - if !ok { - return false - } - return v -} - -// NextGroup moves the form to the next group. -func (f *Form) NextGroup() tea.Cmd { - _, cmd := f.Update(nextGroup()) - return cmd -} - -// PrevGroup moves the form to the next group. -func (f *Form) PrevGroup() tea.Cmd { - _, cmd := f.Update(prevGroup()) - return cmd -} - -// NextField moves the form to the next field. -func (f *Form) NextField() tea.Cmd { - _, cmd := f.Update(NextField()) - return cmd -} - -// PrevField moves the form to the next field. -func (f *Form) PrevField() tea.Cmd { - _, cmd := f.Update(PrevField()) - return cmd -} - -// GetFocusedField returns the focused form field. -func (f *Form) GetFocusedField() Field { - return f.selector.Selected().selector.Selected() -} - -// Init initializes the form. -func (f *Form) Init() tea.Cmd { - var cmds []tea.Cmd - f.selector.Range(func(i int, group *Group) bool { - if i == 0 { - group.active = true - } - cmds = append(cmds, group.Init()) - return true - }) - - if f.isGroupHidden(f.selector.Selected()) { - cmds = append(cmds, nextGroup) - } - - cmds = append(cmds, tea.WindowSize()) - return tea.Sequence(cmds...) -} - -// Update updates the form. -func (f *Form) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - // If the form is aborted or completed there's no need to update it. - if f.State != StateNormal { - return f, nil - } - - group := f.selector.Selected() - - switch msg := msg.(type) { - case tea.WindowSizeMsg: - if f.width == 0 { - f.selector.Range(func(_ int, group *Group) bool { - width := f.layout.GroupWidth(f, group, msg.Width) - group.WithWidth(width) - return true - }) - } - if f.height == 0 { - // calculate the needed height, which is the height of the - // heightest group, accounting for the width, wraps, etc. - neededHeight := 0 - f.selector.Range(func(_ int, group *Group) bool { - if h := group.rawHeight(); h > neededHeight { - neededHeight = h - } - return true - }) - - f.selector.Range(func(_ int, group *Group) bool { - group.WithHeight(min(neededHeight, msg.Height)) - return true - }) - } - - case tea.KeyMsg: - switch { - case key.Matches(msg, f.keymap.Quit): - f.aborted = true - f.quitting = true - f.State = StateAborted - return f, f.CancelCmd - } - - case nextFieldMsg: - // Form is progressing to the next field, let's save the value of the current field. - field := group.selector.Selected() - f.results[field.GetKey()] = field.GetValue() - - case nextGroupMsg: - if len(group.Errors()) > 0 { - return f, nil - } - - submit := func() (tea.Model, tea.Cmd) { - f.quitting = true - f.State = StateCompleted - return f, f.SubmitCmd - } - - if f.selector.OnLast() { - return submit() - } - - for i := f.selector.Index() + 1; i < f.selector.Total(); i++ { - if !f.isGroupHidden(f.selector.Get(i)) { - f.selector.SetIndex(i) - break - } - // all subsequent groups are hidden, so we must act as - // if we were in the last one. - if i == f.selector.Total()-1 { - return submit() - } - } - f.selector.Selected().active = true - return f, f.selector.Selected().Init() - - case prevGroupMsg: - if len(group.Errors()) > 0 { - return f, nil - } - - for i := f.selector.Index() - 1; i >= 0; i-- { - if !f.isGroupHidden(f.selector.Get(i)) { - f.selector.SetIndex(i) - break - } - } - - f.selector.Selected().active = true - return f, f.selector.Selected().Init() - } - - m, cmd := group.Update(msg) - f.selector.Set(f.selector.Index(), m.(*Group)) - - // A user input a key, this could hide or show other groups, - // let's update all of their positions. - switch msg.(type) { - case tea.KeyMsg: - f.UpdateFieldPositions() - } - - return f, cmd -} - -func (f *Form) isGroupHidden(group *Group) bool { - hide := group.hide - if hide == nil { - return false - } - return hide() -} - -func (f *Form) getTheme() *Theme { - if f.theme != nil { - return f.theme - } - return ThemeCharm() -} - -func (f *Form) styles() FormStyles { - return f.getTheme().Form -} - -// View renders the form. -func (f *Form) View() string { - if f.quitting { - return "" - } - - return f.styles().Base.Render(f.layout.View(f)) -} - -// Run runs the form. -func (f *Form) Run() error { - return f.RunWithContext(context.Background()) -} - -// RunWithContext runs the form with the given context. -func (f *Form) RunWithContext(ctx context.Context) error { - f.SubmitCmd = tea.Quit - f.CancelCmd = tea.Interrupt - - if f.selector.Total() == 0 { - return nil - } - - if f.accessible { - return f.runAccessible( - cmp.Or[io.Writer](f.output, os.Stdout), - cmp.Or[io.Reader](f.input, os.Stdin), - ) - } - - return f.run(ctx) -} - -// run runs the form in normal mode. -func (f *Form) run(ctx context.Context) error { - var cancel context.CancelFunc - if f.timeout > 0 { - ctx, cancel = context.WithTimeout(ctx, f.timeout) - defer cancel() - } - - f.teaOptions = append(f.teaOptions, tea.WithContext(ctx)) - m, err := tea.NewProgram(f, f.teaOptions...).Run() - if m.(*Form).aborted || errors.Is(err, tea.ErrInterrupted) { - return ErrUserAborted - } - if errors.Is(err, tea.ErrProgramKilled) { - return ErrTimeout - } - if err != nil { - return fmt.Errorf("huh: %w", err) - } - return nil -} - -// runAccessible runs the form in accessible mode. -func (f *Form) runAccessible(w io.Writer, r io.Reader) error { - // Timeouts are not supported in this mode. - if f.timeout > 0 { - return ErrTimeoutUnsupported - } - - f.selector.Range(func(_ int, group *Group) bool { - group.selector.Range(func(_ int, field Field) bool { - field.Init() - field.Focus() - _ = field.WithAccessible(true).runAccessible(w, r) - _, _ = fmt.Fprintln(w) - return true - }) - return true - }) - - return nil -} diff --git a/vendor/github.com/charmbracelet/huh/group.go b/vendor/github.com/charmbracelet/huh/group.go deleted file mode 100644 index 4f9bdb32..00000000 --- a/vendor/github.com/charmbracelet/huh/group.go +++ /dev/null @@ -1,399 +0,0 @@ -package huh - -import ( - "strings" - - "github.com/charmbracelet/bubbles/help" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/huh/internal/selector" - "github.com/charmbracelet/lipgloss" -) - -// Group is a collection of fields that are displayed together with a page of -// the form. While a group is displayed the form completer can switch between -// fields in the group. -// -// If any of the fields in a group have errors, the form will not be able to -// progress to the next group. -type Group struct { - // collection of fields - selector *selector.Selector[Field] - - // information - title string - description string - - // navigation - viewport viewport.Model - - // help - showHelp bool - help help.Model - - // errors - showErrors bool - - // group options - width int - height int - theme *Theme - keymap *KeyMap - hide func() bool - active bool -} - -// NewGroup returns a new group with the given fields. -func NewGroup(fields ...Field) *Group { - selector := selector.NewSelector(fields) - group := &Group{ - selector: selector, - help: help.New(), - showHelp: true, - showErrors: true, - active: false, - } - - group.width = 80 - height := group.rawHeight() - v := viewport.New(group.width, height) //nolint:mnd - group.viewport = v - group.height = height - - return group -} - -// Title sets the group's title. -func (g *Group) Title(title string) *Group { - g.title = title - return g -} - -// Description sets the group's description. -func (g *Group) Description(description string) *Group { - g.description = description - return g -} - -// WithShowHelp sets whether or not the group's help should be shown. -func (g *Group) WithShowHelp(show bool) *Group { - g.showHelp = show - return g -} - -// WithShowErrors sets whether or not the group's errors should be shown. -func (g *Group) WithShowErrors(show bool) *Group { - g.showErrors = show - return g -} - -// WithTheme sets the theme on a group. -func (g *Group) WithTheme(t *Theme) *Group { - g.theme = t - g.help.Styles = t.Help - g.selector.Range(func(_ int, field Field) bool { - field.WithTheme(t) - return true - }) - if g.height <= 0 { - g.WithHeight(g.rawHeight()) - } - return g -} - -// WithKeyMap sets the keymap on a group. -func (g *Group) WithKeyMap(k *KeyMap) *Group { - g.keymap = k - g.selector.Range(func(_ int, field Field) bool { - field.WithKeyMap(k) - return true - }) - return g -} - -// WithWidth sets the width on a group. -func (g *Group) WithWidth(width int) *Group { - g.width = width - g.viewport.Width = width - g.help.Width = width - g.selector.Range(func(_ int, field Field) bool { - field.WithWidth(width) - return true - }) - return g -} - -// WithHeight sets the height on a group. -func (g *Group) WithHeight(height int) *Group { - g.height = height - h := height - g.nonContentHeight() - g.viewport.Height = h - g.selector.Range(func(_ int, field Field) bool { - // A field height must not exceed the form height. - if h < lipgloss.Height(field.View()) { - field.WithHeight(h) - } - return true - }) - return g -} - -// WithHide sets whether this group should be skipped. -func (g *Group) WithHide(hide bool) *Group { - g.WithHideFunc(func() bool { return hide }) - return g -} - -// WithHideFunc sets the function that checks if this group should be skipped. -func (g *Group) WithHideFunc(hideFunc func() bool) *Group { - g.hide = hideFunc - return g -} - -// Errors returns the groups' fields' errors. -func (g *Group) Errors() []error { - var errs []error - g.selector.Range(func(_ int, field Field) bool { - if err := field.Error(); err != nil { - errs = append(errs, err) - } - return true - }) - return errs -} - -// updateFieldMsg is a message to update the fields of a group that is currently -// displayed. -// -// This is used to update all TitleFunc, DescriptionFunc, and ...Func update -// methods to make all fields dynamically update based on user input. -type updateFieldMsg struct{} - -// nextFieldMsg is a message to move to the next field, -// -// each field controls when to send this message such that it is able to use -// different key bindings or events to trigger group progression. -type nextFieldMsg struct{} - -// prevFieldMsg is a message to move to the previous field. -// -// each field controls when to send this message such that it is able to use -// different key bindings or events to trigger group progression. -type prevFieldMsg struct{} - -// NextField is the command to move to the next field. -func NextField() tea.Msg { - return nextFieldMsg{} -} - -// PrevField is the command to move to the previous field. -func PrevField() tea.Msg { - return prevFieldMsg{} -} - -// Init initializes the group. -func (g *Group) Init() tea.Cmd { - var cmds []tea.Cmd - - cmds = append(cmds, func() tea.Msg { return updateFieldMsg{} }) - - if g.selector.Selected().Skip() { - if g.selector.OnLast() { - cmds = append(cmds, g.prevField()...) - } else if g.selector.OnFirst() { - cmds = append(cmds, g.nextField()...) - } - return tea.Batch(cmds...) - } - - if g.active { - cmd := g.selector.Selected().Focus() - cmds = append(cmds, cmd) - } - g.buildView() - return tea.Batch(cmds...) -} - -// nextField moves to the next field. -func (g *Group) nextField() []tea.Cmd { - blurCmd := g.selector.Selected().Blur() - if g.selector.OnLast() { - return []tea.Cmd{blurCmd, nextGroup} - } - g.selector.Next() - for g.selector.Selected().Skip() { - if g.selector.OnLast() { - return []tea.Cmd{blurCmd, nextGroup} - } - g.selector.Next() - } - focusCmd := g.selector.Selected().Focus() - return []tea.Cmd{blurCmd, focusCmd} -} - -// prevField moves to the previous field. -func (g *Group) prevField() []tea.Cmd { - blurCmd := g.selector.Selected().Blur() - if g.selector.OnFirst() { - return []tea.Cmd{blurCmd, prevGroup} - } - g.selector.Prev() - for g.selector.Selected().Skip() { - if g.selector.OnFirst() { - return []tea.Cmd{blurCmd, prevGroup} - } - g.selector.Prev() - } - focusCmd := g.selector.Selected().Focus() - return []tea.Cmd{blurCmd, focusCmd} -} - -// Update updates the group. -func (g *Group) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmds []tea.Cmd - - // Update all the fields in the group. - g.selector.Range(func(i int, field Field) bool { - switch msg := msg.(type) { - case tea.KeyMsg: - break - default: - m, cmd := field.Update(msg) - g.selector.Set(i, m.(Field)) - cmds = append(cmds, cmd) - } - if g.selector.Index() == i { - m, cmd := field.Update(msg) - g.selector.Set(i, m.(Field)) - cmds = append(cmds, cmd) - } - m, cmd := field.Update(updateFieldMsg{}) - g.selector.Set(i, m.(Field)) - cmds = append(cmds, cmd) - return true - }) - - switch msg.(type) { - case nextFieldMsg: - cmds = append(cmds, g.nextField()...) - case prevFieldMsg: - cmds = append(cmds, g.prevField()...) - } - - g.buildView() - - return g, tea.Batch(cmds...) -} - -func (g *Group) getTheme() *Theme { - if theme := g.theme; theme != nil { - return theme - } - return ThemeCharm() -} - -func (g *Group) styles() GroupStyles { return g.getTheme().Group } - -func (g *Group) getContent() (int, string) { - var fields strings.Builder - offset := 0 - - gap := g.getTheme().FieldSeparator.Render() - - // if the focused field is requesting it be zoomed, only show that field. - if g.selector.Selected().Zoom() { - g.selector.Selected().WithHeight(g.height) - fields.WriteString(g.selector.Selected().View()) - } else { - g.selector.Range(func(i int, field Field) bool { - fields.WriteString(field.View()) - if i == g.selector.Index() { - offset = lipgloss.Height(fields.String()) - lipgloss.Height(field.View()) - } - if i < g.selector.Total()-1 { - fields.WriteString(gap) - } - return true - }) - } - - return offset, fields.String() -} - -func (g *Group) buildView() { - offset, content := g.getContent() - - g.viewport.SetContent(content) - g.viewport.SetYOffset(offset) -} - -// Header renders the group's header only (no content). -func (g *Group) Header() string { - styles := g.styles() - var parts []string - if g.title != "" { - parts = append(parts, styles.Title.Render(wrap(g.title, g.width))) - } - if g.description != "" { - parts = append(parts, styles.Description.Render(wrap(g.description, g.width))) - } - return lipgloss.JoinVertical(lipgloss.Top, parts...) -} - -// nonContentHeight returns the height of the footer + header. -func (g *Group) nonContentHeight() int { - var parts []string - if s := g.Header(); s != "" { - parts = append(parts, s) - } - if s := g.Footer(); s != "" { - parts = append(parts, s) - } - return lipgloss.Height(lipgloss.JoinVertical(lipgloss.Top, parts...)) -} - -// rawHeight returns the full height of the group, without using a viewport. -func (g *Group) rawHeight() int { - return lipgloss.Height(g.Content()) + g.nonContentHeight() -} - -// View renders the group. -func (g *Group) View() string { - var parts []string - if s := g.Header(); s != "" { - parts = append(parts, s) - } - parts = append(parts, g.viewport.View()) - if s := g.Footer(); s != "" { - // append an empty line, and the footer (usually the help). - parts = append(parts, "", s) - } - return lipgloss.JoinVertical(lipgloss.Top, parts...) -} - -// Content renders the group's content only (no footer). -func (g *Group) Content() string { - _, content := g.getContent() - return content -} - -// Footer renders the group's footer only (no content). -func (g *Group) Footer() string { - var parts []string - errors := g.Errors() - if g.showHelp && len(errors) <= 0 { - parts = append(parts, g.help.ShortHelpView(g.selector.Selected().KeyBinds())) - } - if g.showErrors { - for _, err := range errors { - parts = append(parts, wrap( - g.getTheme().Focused.ErrorMessage.Render(err.Error()), - g.width, - )) - } - } - return g.styles().Base.Render(lipgloss.JoinVertical( - lipgloss.Top, - parts..., - )) -} diff --git a/vendor/github.com/charmbracelet/huh/huh.go b/vendor/github.com/charmbracelet/huh/huh.go deleted file mode 100644 index 00f50fae..00000000 --- a/vendor/github.com/charmbracelet/huh/huh.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package huh provides components to build terminal-based forms and prompts. -package huh diff --git a/vendor/github.com/charmbracelet/huh/internal/accessibility/accessibility.go b/vendor/github.com/charmbracelet/huh/internal/accessibility/accessibility.go deleted file mode 100644 index 9e139f44..00000000 --- a/vendor/github.com/charmbracelet/huh/internal/accessibility/accessibility.go +++ /dev/null @@ -1,169 +0,0 @@ -// Package accessibility provides accessible functions to capture user input. -package accessibility - -import ( - "bufio" - "cmp" - "errors" - "fmt" - "io" - "slices" - "strconv" - "strings" - - "github.com/charmbracelet/x/term" -) - -// PromptInt prompts a user for an integer between a certain range. -// -// Given invalid input (non-integers, integers outside of the range), the user -// will continue to be reprompted until a valid input is given, ensuring that -// the return value is always valid. -func PromptInt( - out io.Writer, - in io.Reader, - prompt string, - low, high int, - defaultValue *int, -) int { - var choice int - - validInt := func(s string) error { - if strings.TrimSpace(s) == "" && defaultValue != nil { - return nil - } - i, err := strconv.Atoi(s) - if err != nil || i < low || i > high { - return fmt.Errorf("Invalid: must be between %d and %d", low, high) //nolint:staticcheck - } - return nil - } - - input := PromptString( - out, - in, - prompt, - ptrToStr(defaultValue, strconv.Itoa), - validInt, - ) - choice, _ = strconv.Atoi(input) - return choice -} - -func parseBool(s string) (bool, error) { - s = strings.ToLower(s) - - if slices.Contains([]string{"y", "yes"}, s) { - return true, nil - } - - // As a special case, we default to "" to no since the usage of this - // function suggests N is the default. - if slices.Contains([]string{"n", "no"}, s) { - return false, nil - } - - return false, errors.New("invalid input. please try again") -} - -// PromptBool prompts a user for a boolean value. -// -// Given invalid input (non-boolean), the user will continue to be reprompted -// until a valid input is given, ensuring that the return value is always valid. -func PromptBool( - out io.Writer, - in io.Reader, - prompt string, - defaultValue bool, -) bool { - validBool := func(s string) error { - if strings.TrimSpace(s) == "" { - return nil - } - _, err := parseBool(s) - return err - } - - input := PromptString( - out, in, prompt, - boolToStr(defaultValue), - validBool, - ) - b, _ := parseBool(input) - return b -} - -// PromptPassword allows to prompt for a password. -// In must be the fd of a tty. -func PromptPassword( - out io.Writer, - in uintptr, - prompt string, - validator func(input string) error, -) (string, error) { - for { - _, _ = fmt.Fprint(out, prompt) - pwd, err := term.ReadPassword(in) - if err != nil { - return "", err //nolint:wrapcheck - } - _, _ = fmt.Fprintln(out) - if err := validator(string(pwd)); err != nil { - _, _ = fmt.Fprintln(out, err) - continue - } - return string(pwd), nil - } -} - -// PromptString prompts a user for a string value and validates it against a -// validator function. It re-prompts the user until a valid input is given. -func PromptString( - out io.Writer, - in io.Reader, - prompt string, - defaultValue string, - validator func(input string) error, -) string { - scanner := bufio.NewScanner(in) - - var ( - valid bool - input string - ) - - for !valid { - _, _ = fmt.Fprint(out, prompt) - if !scanner.Scan() { - // no way to bubble up errors or signal cancellation - // but the program is probably not continuing if - // stdin sent EOF - _, _ = fmt.Fprintln(out) - break - } - input = scanner.Text() - - if err := validator(input); err != nil { - _, _ = fmt.Fprintln(out, err) - continue - } - - break - } - - return cmp.Or(strings.TrimSpace(input), defaultValue) -} - -func ptrToStr[T any](t *T, fn func(t T) string) string { - if t == nil { - return "" - } - return fn(*t) -} - -func boolToStr(b bool) string { - if b { - return "y" - } - return "N" -} diff --git a/vendor/github.com/charmbracelet/huh/internal/selector/selector.go b/vendor/github.com/charmbracelet/huh/internal/selector/selector.go deleted file mode 100644 index ecbaed4b..00000000 --- a/vendor/github.com/charmbracelet/huh/internal/selector/selector.go +++ /dev/null @@ -1,97 +0,0 @@ -// Package selector provides a helper type for selecting items. -package selector - -// Selector is a helper type for selecting items. -type Selector[T any] struct { - items []T - index int -} - -// NewSelector creates a new item selector. -func NewSelector[T any](items []T) *Selector[T] { - return &Selector[T]{ - items: items, - } -} - -// Append adds an item to the selector. -func (s *Selector[T]) Append(item T) { - s.items = append(s.items, item) -} - -// Next moves the selector to the next item. -func (s *Selector[T]) Next() { - if s.index < len(s.items)-1 { - s.index++ - } -} - -// Prev moves the selector to the previous item. -func (s *Selector[T]) Prev() { - if s.index > 0 { - s.index-- - } -} - -// OnFirst returns true if the selector is on the first item. -func (s *Selector[T]) OnFirst() bool { - return s.index == 0 -} - -// OnLast returns true if the selector is on the last item. -func (s *Selector[T]) OnLast() bool { - return s.index == len(s.items)-1 -} - -// Selected returns the index of the current selected item. -func (s *Selector[T]) Selected() T { - return s.items[s.index] -} - -// Index returns the index of the current selected item. -func (s *Selector[T]) Index() int { - return s.index -} - -// Total returns the total number of items. -func (s *Selector[T]) Total() int { - return len(s.items) -} - -// SetIndex sets the selected item. -func (s *Selector[T]) SetIndex(i int) { - if i < 0 || i >= len(s.items) { - return - } - s.index = i -} - -// Get returns the item at the given index. -func (s *Selector[T]) Get(i int) T { - return s.items[i] -} - -// Set sets the item at the given index. -func (s *Selector[T]) Set(i int, item T) { - s.items[i] = item -} - -// Range iterates over the items. -// The callback function should return true to continue the iteration. -func (s *Selector[T]) Range(f func(i int, item T) bool) { - for i, item := range s.items { - if !f(i, item) { - break - } - } -} - -// ReverseRange iterates over the items in reverse. -// The callback function should return true to continue the iteration. -func (s *Selector[T]) ReverseRange(f func(i int, item T) bool) { - for i := len(s.items) - 1; i >= 0; i-- { - if !f(i, s.items[i]) { - break - } - } -} diff --git a/vendor/github.com/charmbracelet/huh/keymap.go b/vendor/github.com/charmbracelet/huh/keymap.go deleted file mode 100644 index 45f9d0d3..00000000 --- a/vendor/github.com/charmbracelet/huh/keymap.go +++ /dev/null @@ -1,186 +0,0 @@ -package huh - -import "github.com/charmbracelet/bubbles/key" - -// KeyMap is the keybindings to navigate the form. -type KeyMap struct { - Quit key.Binding - - Confirm ConfirmKeyMap - FilePicker FilePickerKeyMap - Input InputKeyMap - MultiSelect MultiSelectKeyMap - Note NoteKeyMap - Select SelectKeyMap - Text TextKeyMap -} - -// InputKeyMap is the keybindings for input fields. -type InputKeyMap struct { - AcceptSuggestion key.Binding - Next key.Binding - Prev key.Binding - Submit key.Binding -} - -// TextKeyMap is the keybindings for text fields. -type TextKeyMap struct { - Next key.Binding - Prev key.Binding - NewLine key.Binding - Editor key.Binding - Submit key.Binding -} - -// SelectKeyMap is the keybindings for select fields. -type SelectKeyMap struct { - Next key.Binding - Prev key.Binding - Up key.Binding - Down key.Binding - HalfPageUp key.Binding - HalfPageDown key.Binding - GotoTop key.Binding - GotoBottom key.Binding - Left key.Binding - Right key.Binding - Filter key.Binding - SetFilter key.Binding - ClearFilter key.Binding - Submit key.Binding -} - -// MultiSelectKeyMap is the keybindings for multi-select fields. -type MultiSelectKeyMap struct { - Next key.Binding - Prev key.Binding - Up key.Binding - Down key.Binding - HalfPageUp key.Binding - HalfPageDown key.Binding - GotoTop key.Binding - GotoBottom key.Binding - Toggle key.Binding - Filter key.Binding - SetFilter key.Binding - ClearFilter key.Binding - Submit key.Binding - SelectAll key.Binding - SelectNone key.Binding -} - -// FilePickerKeyMap is the keybindings for filepicker fields. -type FilePickerKeyMap struct { - Open key.Binding - Close key.Binding - GotoTop key.Binding - GotoBottom key.Binding - PageUp key.Binding - PageDown key.Binding - Back key.Binding - Select key.Binding - Up key.Binding - Down key.Binding - Prev key.Binding - Next key.Binding - Submit key.Binding -} - -// NoteKeyMap is the keybindings for note fields. -type NoteKeyMap struct { - Next key.Binding - Prev key.Binding - Submit key.Binding -} - -// ConfirmKeyMap is the keybindings for confirm fields. -type ConfirmKeyMap struct { - Next key.Binding - Prev key.Binding - Toggle key.Binding - Submit key.Binding - Accept key.Binding - Reject key.Binding -} - -// NewDefaultKeyMap returns a new default keymap. -func NewDefaultKeyMap() *KeyMap { - return &KeyMap{ - Quit: key.NewBinding(key.WithKeys("ctrl+c")), - Input: InputKeyMap{ - AcceptSuggestion: key.NewBinding(key.WithKeys("ctrl+e"), key.WithHelp("ctrl+e", "complete")), - Prev: key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "back")), - Next: key.NewBinding(key.WithKeys("enter", "tab"), key.WithHelp("enter", "next")), - Submit: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "submit")), - }, - FilePicker: FilePickerKeyMap{ - GotoTop: key.NewBinding(key.WithKeys("g"), key.WithHelp("g", "first"), key.WithDisabled()), - GotoBottom: key.NewBinding(key.WithKeys("G"), key.WithHelp("G", "last"), key.WithDisabled()), - PageUp: key.NewBinding(key.WithKeys("K", "pgup"), key.WithHelp("pgup", "page up"), key.WithDisabled()), - PageDown: key.NewBinding(key.WithKeys("J", "pgdown"), key.WithHelp("pgdown", "page down"), key.WithDisabled()), - Back: key.NewBinding(key.WithKeys("h", "backspace", "left", "esc"), key.WithHelp("h", "back"), key.WithDisabled()), - Select: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "select"), key.WithDisabled()), - Up: key.NewBinding(key.WithKeys("up", "k", "ctrl+k", "ctrl+p"), key.WithHelp("↑", "up"), key.WithDisabled()), - Down: key.NewBinding(key.WithKeys("down", "j", "ctrl+j", "ctrl+n"), key.WithHelp("↓", "down"), key.WithDisabled()), - - Open: key.NewBinding(key.WithKeys("l", "right", "enter"), key.WithHelp("enter", "open")), - Close: key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "close"), key.WithDisabled()), - Prev: key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "back")), - Next: key.NewBinding(key.WithKeys("tab"), key.WithHelp("tab", "next")), - Submit: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "submit")), - }, - Text: TextKeyMap{ - Prev: key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "back")), - Next: key.NewBinding(key.WithKeys("tab", "enter"), key.WithHelp("enter", "next")), - Submit: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "submit")), - NewLine: key.NewBinding(key.WithKeys("alt+enter", "ctrl+j"), key.WithHelp("alt+enter / ctrl+j", "new line")), - Editor: key.NewBinding(key.WithKeys("ctrl+e"), key.WithHelp("ctrl+e", "open editor")), - }, - Select: SelectKeyMap{ - Prev: key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "back")), - Next: key.NewBinding(key.WithKeys("enter", "tab"), key.WithHelp("enter", "select")), - Submit: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "submit")), - Up: key.NewBinding(key.WithKeys("up", "k", "ctrl+k", "ctrl+p"), key.WithHelp("↑", "up")), - Down: key.NewBinding(key.WithKeys("down", "j", "ctrl+j", "ctrl+n"), key.WithHelp("↓", "down")), - Left: key.NewBinding(key.WithKeys("h", "left"), key.WithHelp("←", "left"), key.WithDisabled()), - Right: key.NewBinding(key.WithKeys("l", "right"), key.WithHelp("→", "right"), key.WithDisabled()), - Filter: key.NewBinding(key.WithKeys("/"), key.WithHelp("/", "filter")), - SetFilter: key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "set filter"), key.WithDisabled()), - ClearFilter: key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "clear filter"), key.WithDisabled()), - HalfPageUp: key.NewBinding(key.WithKeys("ctrl+u"), key.WithHelp("ctrl+u", "½ page up")), - HalfPageDown: key.NewBinding(key.WithKeys("ctrl+d"), key.WithHelp("ctrl+d", "½ page down")), - GotoTop: key.NewBinding(key.WithKeys("home", "g"), key.WithHelp("g/home", "go to start")), - GotoBottom: key.NewBinding(key.WithKeys("end", "G"), key.WithHelp("G/end", "go to end")), - }, - MultiSelect: MultiSelectKeyMap{ - Prev: key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "back")), - Next: key.NewBinding(key.WithKeys("enter", "tab"), key.WithHelp("enter", "confirm")), - Submit: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "submit")), - Toggle: key.NewBinding(key.WithKeys(" ", "x"), key.WithHelp("x", "toggle")), - Up: key.NewBinding(key.WithKeys("up", "k", "ctrl+p"), key.WithHelp("↑", "up")), - Down: key.NewBinding(key.WithKeys("down", "j", "ctrl+n"), key.WithHelp("↓", "down")), - Filter: key.NewBinding(key.WithKeys("/"), key.WithHelp("/", "filter")), - SetFilter: key.NewBinding(key.WithKeys("enter", "esc"), key.WithHelp("esc", "set filter"), key.WithDisabled()), - ClearFilter: key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "clear filter"), key.WithDisabled()), - HalfPageUp: key.NewBinding(key.WithKeys("ctrl+u"), key.WithHelp("ctrl+u", "½ page up")), - HalfPageDown: key.NewBinding(key.WithKeys("ctrl+d"), key.WithHelp("ctrl+d", "½ page down")), - GotoTop: key.NewBinding(key.WithKeys("home", "g"), key.WithHelp("g/home", "go to start")), - GotoBottom: key.NewBinding(key.WithKeys("end", "G"), key.WithHelp("G/end", "go to end")), - SelectAll: key.NewBinding(key.WithKeys("ctrl+a"), key.WithHelp("ctrl+a", "select all")), - SelectNone: key.NewBinding(key.WithKeys("ctrl+a"), key.WithHelp("ctrl+a", "select none"), key.WithDisabled()), - }, - Note: NoteKeyMap{ - Prev: key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "back")), - Next: key.NewBinding(key.WithKeys("enter", "tab"), key.WithHelp("enter", "next")), - Submit: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "submit")), - }, - Confirm: ConfirmKeyMap{ - Prev: key.NewBinding(key.WithKeys("shift+tab"), key.WithHelp("shift+tab", "back")), - Next: key.NewBinding(key.WithKeys("enter", "tab"), key.WithHelp("enter", "next")), - Submit: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "submit")), - Toggle: key.NewBinding(key.WithKeys("h", "l", "right", "left"), key.WithHelp("←/→", "toggle")), - Accept: key.NewBinding(key.WithKeys("y", "Y"), key.WithHelp("y", "Yes")), - Reject: key.NewBinding(key.WithKeys("n", "N"), key.WithHelp("n", "No")), - }, - } -} diff --git a/vendor/github.com/charmbracelet/huh/layout.go b/vendor/github.com/charmbracelet/huh/layout.go deleted file mode 100644 index 4bb7f462..00000000 --- a/vendor/github.com/charmbracelet/huh/layout.go +++ /dev/null @@ -1,170 +0,0 @@ -package huh - -import ( - "github.com/charmbracelet/lipgloss" -) - -// A Layout is responsible for laying out groups in a form. -type Layout interface { - View(f *Form) string - GroupWidth(f *Form, g *Group, w int) int -} - -// LayoutDefault is the default layout shows a single group at a time. -var LayoutDefault Layout = &layoutDefault{} - -// LayoutStack is a layout stacks all groups on top of each other. -var LayoutStack Layout = &layoutStack{} - -// LayoutColumns layout distributes groups in even columns. -func LayoutColumns(columns int) Layout { - return &layoutColumns{columns: columns} -} - -// LayoutGrid layout distributes groups in a grid. -func LayoutGrid(rows int, columns int) Layout { - return &layoutGrid{rows: rows, columns: columns} -} - -type layoutDefault struct{} - -func (l *layoutDefault) View(f *Form) string { - return f.selector.Selected().View() -} - -func (l *layoutDefault) GroupWidth(_ *Form, _ *Group, w int) int { - return w -} - -type layoutColumns struct { - columns int -} - -func (l *layoutColumns) visibleGroups(f *Form) []*Group { - segmentIndex := f.selector.Index() / l.columns - start := segmentIndex * l.columns - end := start + l.columns - - total := f.selector.Total() - if end > total { - end = total - } - - var groups []*Group - f.selector.Range(func(i int, group *Group) bool { - if i >= start && i < end { - groups = append(groups, group) - return true - } - return true - }) - - return groups -} - -func (l *layoutColumns) View(f *Form) string { - groups := l.visibleGroups(f) - if len(groups) == 0 { - return "" - } - - columns := make([]string, 0, len(groups)) - for _, group := range groups { - columns = append(columns, group.Content()) - } - - header := f.selector.Selected().Header() - footer := f.selector.Selected().Footer() - - return lipgloss.JoinVertical(lipgloss.Left, - header, - lipgloss.JoinHorizontal(lipgloss.Left, columns...), - footer, - ) -} - -func (l *layoutColumns) GroupWidth(_ *Form, _ *Group, w int) int { - return w / l.columns -} - -type layoutStack struct{} - -func (l *layoutStack) View(f *Form) string { - var columns []string - f.selector.Range(func(_ int, group *Group) bool { - columns = append(columns, group.Content(), "") - return true - }) - - if footer := f.selector.Selected().Footer(); footer != "" { - columns = append(columns, footer) - } - return lipgloss.JoinVertical(lipgloss.Top, columns...) -} - -func (l *layoutStack) GroupWidth(_ *Form, _ *Group, w int) int { - return w -} - -type layoutGrid struct { - rows, columns int -} - -func (l *layoutGrid) visibleGroups(f *Form) [][]*Group { - total := l.rows * l.columns - segmentIndex := f.selector.Index() / total - start := segmentIndex * total - end := start + total - - if glen := f.selector.Total(); end > glen { - end = glen - } - - var visible []*Group - f.selector.Range(func(i int, group *Group) bool { - if i >= start && i < end { - visible = append(visible, group) - return true - } - return true - }) - grid := make([][]*Group, l.rows) - for i := 0; i < l.rows; i++ { - startRow := i * l.columns - endRow := startRow + l.columns - if startRow >= len(visible) { - break - } - if endRow > len(visible) { - endRow = len(visible) - } - grid[i] = visible[startRow:endRow] - } - return grid -} - -func (l *layoutGrid) View(f *Form) string { - grid := l.visibleGroups(f) - if len(grid) == 0 { - return "" - } - - rows := make([]string, 0, len(grid)) - for _, row := range grid { - var columns []string - for _, group := range row { - columns = append(columns, group.Content()) - } - rows = append(rows, lipgloss.JoinHorizontal(lipgloss.Left, columns...), "") - } - footer := f.selector.Selected().Footer() - - return lipgloss.JoinVertical( - lipgloss.Top, - append(rows, footer)..., - ) -} - -func (l *layoutGrid) GroupWidth(_ *Form, _ *Group, w int) int { - return w / l.columns -} diff --git a/vendor/github.com/charmbracelet/huh/option.go b/vendor/github.com/charmbracelet/huh/option.go deleted file mode 100644 index 2dcea0be..00000000 --- a/vendor/github.com/charmbracelet/huh/option.go +++ /dev/null @@ -1,38 +0,0 @@ -package huh - -import "fmt" - -// Option is an option for select fields. -type Option[T comparable] struct { - Key string - Value T - selected bool -} - -// NewOptions returns new options from a list of values. -func NewOptions[T comparable](values ...T) []Option[T] { - options := make([]Option[T], len(values)) - for i, o := range values { - options[i] = Option[T]{ - Key: fmt.Sprint(o), - Value: o, - } - } - return options -} - -// NewOption returns a new select option. -func NewOption[T comparable](key string, value T) Option[T] { - return Option[T]{Key: key, Value: value} -} - -// Selected sets whether the option is currently selected. -func (o Option[T]) Selected(selected bool) Option[T] { - o.selected = selected - return o -} - -// String returns the key of the option. -func (o Option[T]) String() string { - return o.Key -} diff --git a/vendor/github.com/charmbracelet/huh/run.go b/vendor/github.com/charmbracelet/huh/run.go deleted file mode 100644 index 81e164d0..00000000 --- a/vendor/github.com/charmbracelet/huh/run.go +++ /dev/null @@ -1,8 +0,0 @@ -package huh - -// Run runs a single field by wrapping it within a group and a form. -func Run(field Field) error { - group := NewGroup(field) - form := NewForm(group).WithShowHelp(false) - return form.Run() -} diff --git a/vendor/github.com/charmbracelet/huh/theme.go b/vendor/github.com/charmbracelet/huh/theme.go deleted file mode 100644 index 6de20c37..00000000 --- a/vendor/github.com/charmbracelet/huh/theme.go +++ /dev/null @@ -1,329 +0,0 @@ -package huh - -import ( - catppuccin "github.com/catppuccin/go" - "github.com/charmbracelet/bubbles/help" - "github.com/charmbracelet/lipgloss" -) - -// Theme is a collection of styles for components of the form. -// Themes can be applied to a form using the WithTheme option. -type Theme struct { - Form FormStyles - Group GroupStyles - FieldSeparator lipgloss.Style - Blurred FieldStyles - Focused FieldStyles - Help help.Styles -} - -// FormStyles are the styles for a form. -type FormStyles struct { - Base lipgloss.Style -} - -// GroupStyles are the styles for a group. -type GroupStyles struct { - Base lipgloss.Style - Title lipgloss.Style - Description lipgloss.Style -} - -// FieldStyles are the styles for input fields. -type FieldStyles struct { - Base lipgloss.Style - Title lipgloss.Style - Description lipgloss.Style - ErrorIndicator lipgloss.Style - ErrorMessage lipgloss.Style - - // Select styles. - SelectSelector lipgloss.Style // Selection indicator - Option lipgloss.Style // Select options - NextIndicator lipgloss.Style - PrevIndicator lipgloss.Style - - // FilePicker styles. - Directory lipgloss.Style - File lipgloss.Style - - // Multi-select styles. - MultiSelectSelector lipgloss.Style - SelectedOption lipgloss.Style - SelectedPrefix lipgloss.Style - UnselectedOption lipgloss.Style - UnselectedPrefix lipgloss.Style - - // Textinput and teatarea styles. - TextInput TextInputStyles - - // Confirm styles. - FocusedButton lipgloss.Style - BlurredButton lipgloss.Style - - // Card styles. - Card lipgloss.Style - NoteTitle lipgloss.Style - Next lipgloss.Style -} - -// TextInputStyles are the styles for text inputs. -type TextInputStyles struct { - Cursor lipgloss.Style - CursorText lipgloss.Style - Placeholder lipgloss.Style - Prompt lipgloss.Style - Text lipgloss.Style -} - -const ( - buttonPaddingHorizontal = 2 - buttonPaddingVertical = 0 -) - -// ThemeBase returns a new base theme with general styles to be inherited by -// other themes. -func ThemeBase() *Theme { - var t Theme - - t.Form.Base = lipgloss.NewStyle() - t.Group.Base = lipgloss.NewStyle() - t.FieldSeparator = lipgloss.NewStyle().SetString("\n\n") - - button := lipgloss.NewStyle(). - Padding(buttonPaddingVertical, buttonPaddingHorizontal). - MarginRight(1) - - // Focused styles. - t.Focused.Base = lipgloss.NewStyle().PaddingLeft(1).BorderStyle(lipgloss.ThickBorder()).BorderLeft(true) - t.Focused.Card = t.Focused.Base - t.Focused.ErrorIndicator = lipgloss.NewStyle().SetString(" *") - t.Focused.ErrorMessage = lipgloss.NewStyle().SetString(" *") - t.Focused.SelectSelector = lipgloss.NewStyle().SetString("> ") - t.Focused.NextIndicator = lipgloss.NewStyle().MarginLeft(1).SetString("→") - t.Focused.PrevIndicator = lipgloss.NewStyle().MarginRight(1).SetString("←") - t.Focused.MultiSelectSelector = lipgloss.NewStyle().SetString("> ") - t.Focused.SelectedPrefix = lipgloss.NewStyle().SetString("[•] ") - t.Focused.UnselectedPrefix = lipgloss.NewStyle().SetString("[ ] ") - t.Focused.FocusedButton = button.Foreground(lipgloss.Color("0")).Background(lipgloss.Color("7")) - t.Focused.BlurredButton = button.Foreground(lipgloss.Color("7")).Background(lipgloss.Color("0")) - t.Focused.TextInput.Placeholder = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) - - t.Help = help.New().Styles - - // Blurred styles. - t.Blurred = t.Focused - t.Blurred.Base = t.Blurred.Base.BorderStyle(lipgloss.HiddenBorder()) - t.Blurred.Card = t.Blurred.Base - t.Blurred.MultiSelectSelector = lipgloss.NewStyle().SetString(" ") - t.Blurred.NextIndicator = lipgloss.NewStyle() - t.Blurred.PrevIndicator = lipgloss.NewStyle() - - return &t -} - -// ThemeCharm returns a new theme based on the Charm color scheme. -func ThemeCharm() *Theme { - t := ThemeBase() - - var ( - normalFg = lipgloss.AdaptiveColor{Light: "235", Dark: "252"} - indigo = lipgloss.AdaptiveColor{Light: "#5A56E0", Dark: "#7571F9"} - cream = lipgloss.AdaptiveColor{Light: "#FFFDF5", Dark: "#FFFDF5"} - fuchsia = lipgloss.Color("#F780E2") - green = lipgloss.AdaptiveColor{Light: "#02BA84", Dark: "#02BF87"} - red = lipgloss.AdaptiveColor{Light: "#FF4672", Dark: "#ED567A"} - ) - - t.Focused.Base = t.Focused.Base.BorderForeground(lipgloss.Color("238")) - t.Focused.Card = t.Focused.Base - t.Focused.Title = t.Focused.Title.Foreground(indigo).Bold(true) - t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(indigo).Bold(true).MarginBottom(1) - t.Focused.Directory = t.Focused.Directory.Foreground(indigo) - t.Focused.Description = t.Focused.Description.Foreground(lipgloss.AdaptiveColor{Light: "", Dark: "243"}) - t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(red) - t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(red) - t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(fuchsia) - t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(fuchsia) - t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(fuchsia) - t.Focused.Option = t.Focused.Option.Foreground(normalFg) - t.Focused.MultiSelectSelector = t.Focused.MultiSelectSelector.Foreground(fuchsia) - t.Focused.SelectedOption = t.Focused.SelectedOption.Foreground(green) - t.Focused.SelectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#02CF92", Dark: "#02A877"}).SetString("✓ ") - t.Focused.UnselectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "", Dark: "243"}).SetString("• ") - t.Focused.UnselectedOption = t.Focused.UnselectedOption.Foreground(normalFg) - t.Focused.FocusedButton = t.Focused.FocusedButton.Foreground(cream).Background(fuchsia) - t.Focused.Next = t.Focused.FocusedButton - t.Focused.BlurredButton = t.Focused.BlurredButton.Foreground(normalFg).Background(lipgloss.AdaptiveColor{Light: "252", Dark: "237"}) - - t.Focused.TextInput.Cursor = t.Focused.TextInput.Cursor.Foreground(green) - t.Focused.TextInput.Placeholder = t.Focused.TextInput.Placeholder.Foreground(lipgloss.AdaptiveColor{Light: "248", Dark: "238"}) - t.Focused.TextInput.Prompt = t.Focused.TextInput.Prompt.Foreground(fuchsia) - - t.Blurred = t.Focused - t.Blurred.Base = t.Focused.Base.BorderStyle(lipgloss.HiddenBorder()) - t.Blurred.Card = t.Blurred.Base - t.Blurred.NextIndicator = lipgloss.NewStyle() - t.Blurred.PrevIndicator = lipgloss.NewStyle() - - t.Group.Title = t.Focused.Title - t.Group.Description = t.Focused.Description - return t -} - -// ThemeDracula returns a new theme based on the Dracula color scheme. -func ThemeDracula() *Theme { - t := ThemeBase() - - var ( - background = lipgloss.AdaptiveColor{Dark: "#282a36"} - selection = lipgloss.AdaptiveColor{Dark: "#44475a"} - foreground = lipgloss.AdaptiveColor{Dark: "#f8f8f2"} - comment = lipgloss.AdaptiveColor{Dark: "#6272a4"} - green = lipgloss.AdaptiveColor{Dark: "#50fa7b"} - purple = lipgloss.AdaptiveColor{Dark: "#bd93f9"} - red = lipgloss.AdaptiveColor{Dark: "#ff5555"} - yellow = lipgloss.AdaptiveColor{Dark: "#f1fa8c"} - ) - - t.Focused.Base = t.Focused.Base.BorderForeground(selection) - t.Focused.Card = t.Focused.Base - t.Focused.Title = t.Focused.Title.Foreground(purple) - t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(purple) - t.Focused.Description = t.Focused.Description.Foreground(comment) - t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(red) - t.Focused.Directory = t.Focused.Directory.Foreground(purple) - t.Focused.File = t.Focused.File.Foreground(foreground) - t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(red) - t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(yellow) - t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(yellow) - t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(yellow) - t.Focused.Option = t.Focused.Option.Foreground(foreground) - t.Focused.MultiSelectSelector = t.Focused.MultiSelectSelector.Foreground(yellow) - t.Focused.SelectedOption = t.Focused.SelectedOption.Foreground(green) - t.Focused.SelectedPrefix = t.Focused.SelectedPrefix.Foreground(green) - t.Focused.UnselectedOption = t.Focused.UnselectedOption.Foreground(foreground) - t.Focused.UnselectedPrefix = t.Focused.UnselectedPrefix.Foreground(comment) - t.Focused.FocusedButton = t.Focused.FocusedButton.Foreground(yellow).Background(purple).Bold(true) - t.Focused.BlurredButton = t.Focused.BlurredButton.Foreground(foreground).Background(background) - - t.Focused.TextInput.Cursor = t.Focused.TextInput.Cursor.Foreground(yellow) - t.Focused.TextInput.Placeholder = t.Focused.TextInput.Placeholder.Foreground(comment) - t.Focused.TextInput.Prompt = t.Focused.TextInput.Prompt.Foreground(yellow) - - t.Blurred = t.Focused - t.Blurred.Base = t.Blurred.Base.BorderStyle(lipgloss.HiddenBorder()) - t.Blurred.Card = t.Blurred.Base - t.Blurred.NextIndicator = lipgloss.NewStyle() - t.Blurred.PrevIndicator = lipgloss.NewStyle() - - t.Group.Title = t.Focused.Title - t.Group.Description = t.Focused.Description - return t -} - -// ThemeBase16 returns a new theme based on the base16 color scheme. -func ThemeBase16() *Theme { - t := ThemeBase() - - t.Focused.Base = t.Focused.Base.BorderForeground(lipgloss.Color("8")) - t.Focused.Card = t.Focused.Base - t.Focused.Title = t.Focused.Title.Foreground(lipgloss.Color("6")) - t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(lipgloss.Color("6")) - t.Focused.Directory = t.Focused.Directory.Foreground(lipgloss.Color("6")) - t.Focused.Description = t.Focused.Description.Foreground(lipgloss.Color("8")) - t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(lipgloss.Color("9")) - t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(lipgloss.Color("9")) - t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(lipgloss.Color("3")) - t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(lipgloss.Color("3")) - t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(lipgloss.Color("3")) - t.Focused.Option = t.Focused.Option.Foreground(lipgloss.Color("7")) - t.Focused.MultiSelectSelector = t.Focused.MultiSelectSelector.Foreground(lipgloss.Color("3")) - t.Focused.SelectedOption = t.Focused.SelectedOption.Foreground(lipgloss.Color("2")) - t.Focused.SelectedPrefix = t.Focused.SelectedPrefix.Foreground(lipgloss.Color("2")) - t.Focused.UnselectedOption = t.Focused.UnselectedOption.Foreground(lipgloss.Color("7")) - t.Focused.FocusedButton = t.Focused.FocusedButton.Foreground(lipgloss.Color("7")).Background(lipgloss.Color("5")) - t.Focused.BlurredButton = t.Focused.BlurredButton.Foreground(lipgloss.Color("7")).Background(lipgloss.Color("0")) - - t.Focused.TextInput.Cursor.Foreground(lipgloss.Color("5")) - t.Focused.TextInput.Placeholder.Foreground(lipgloss.Color("8")) - t.Focused.TextInput.Prompt.Foreground(lipgloss.Color("3")) - - t.Blurred = t.Focused - t.Blurred.Base = t.Blurred.Base.BorderStyle(lipgloss.HiddenBorder()) - t.Blurred.Card = t.Blurred.Base - t.Blurred.NoteTitle = t.Blurred.NoteTitle.Foreground(lipgloss.Color("8")) - t.Blurred.Title = t.Blurred.NoteTitle.Foreground(lipgloss.Color("8")) - - t.Blurred.TextInput.Prompt = t.Blurred.TextInput.Prompt.Foreground(lipgloss.Color("8")) - t.Blurred.TextInput.Text = t.Blurred.TextInput.Text.Foreground(lipgloss.Color("7")) - - t.Blurred.NextIndicator = lipgloss.NewStyle() - t.Blurred.PrevIndicator = lipgloss.NewStyle() - - t.Group.Title = t.Focused.Title - t.Group.Description = t.Focused.Description - - return t -} - -// ThemeCatppuccin returns a new theme based on the Catppuccin color scheme. -func ThemeCatppuccin() *Theme { - t := ThemeBase() - - light := catppuccin.Latte - dark := catppuccin.Mocha - var ( - base = lipgloss.AdaptiveColor{Light: light.Base().Hex, Dark: dark.Base().Hex} - text = lipgloss.AdaptiveColor{Light: light.Text().Hex, Dark: dark.Text().Hex} - subtext1 = lipgloss.AdaptiveColor{Light: light.Subtext1().Hex, Dark: dark.Subtext1().Hex} - subtext0 = lipgloss.AdaptiveColor{Light: light.Subtext0().Hex, Dark: dark.Subtext0().Hex} - overlay1 = lipgloss.AdaptiveColor{Light: light.Overlay1().Hex, Dark: dark.Overlay1().Hex} - overlay0 = lipgloss.AdaptiveColor{Light: light.Overlay0().Hex, Dark: dark.Overlay0().Hex} - green = lipgloss.AdaptiveColor{Light: light.Green().Hex, Dark: dark.Green().Hex} - red = lipgloss.AdaptiveColor{Light: light.Red().Hex, Dark: dark.Red().Hex} - pink = lipgloss.AdaptiveColor{Light: light.Pink().Hex, Dark: dark.Pink().Hex} - mauve = lipgloss.AdaptiveColor{Light: light.Mauve().Hex, Dark: dark.Mauve().Hex} - cursor = lipgloss.AdaptiveColor{Light: light.Rosewater().Hex, Dark: dark.Rosewater().Hex} - ) - - t.Focused.Base = t.Focused.Base.BorderForeground(subtext1) - t.Focused.Card = t.Focused.Base - t.Focused.Title = t.Focused.Title.Foreground(mauve) - t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(mauve) - t.Focused.Directory = t.Focused.Directory.Foreground(mauve) - t.Focused.Description = t.Focused.Description.Foreground(subtext0) - t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(red) - t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(red) - t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(pink) - t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(pink) - t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(pink) - t.Focused.Option = t.Focused.Option.Foreground(text) - t.Focused.MultiSelectSelector = t.Focused.MultiSelectSelector.Foreground(pink) - t.Focused.SelectedOption = t.Focused.SelectedOption.Foreground(green) - t.Focused.SelectedPrefix = t.Focused.SelectedPrefix.Foreground(green) - t.Focused.UnselectedPrefix = t.Focused.UnselectedPrefix.Foreground(text) - t.Focused.UnselectedOption = t.Focused.UnselectedOption.Foreground(text) - t.Focused.FocusedButton = t.Focused.FocusedButton.Foreground(base).Background(pink) - t.Focused.BlurredButton = t.Focused.BlurredButton.Foreground(text).Background(base) - - t.Focused.TextInput.Cursor = t.Focused.TextInput.Cursor.Foreground(cursor) - t.Focused.TextInput.Placeholder = t.Focused.TextInput.Placeholder.Foreground(overlay0) - t.Focused.TextInput.Prompt = t.Focused.TextInput.Prompt.Foreground(pink) - - t.Blurred = t.Focused - t.Blurred.Base = t.Blurred.Base.BorderStyle(lipgloss.HiddenBorder()) - t.Blurred.Card = t.Blurred.Base - - t.Help.Ellipsis = t.Help.Ellipsis.Foreground(subtext0) - t.Help.ShortKey = t.Help.ShortKey.Foreground(subtext0) - t.Help.ShortDesc = t.Help.ShortDesc.Foreground(overlay1) - t.Help.ShortSeparator = t.Help.ShortSeparator.Foreground(subtext0) - t.Help.FullKey = t.Help.FullKey.Foreground(subtext0) - t.Help.FullDesc = t.Help.FullDesc.Foreground(overlay1) - t.Help.FullSeparator = t.Help.FullSeparator.Foreground(subtext0) - - t.Group.Title = t.Focused.Title - t.Group.Description = t.Focused.Description - return t -} diff --git a/vendor/github.com/charmbracelet/huh/validate.go b/vendor/github.com/charmbracelet/huh/validate.go deleted file mode 100644 index 7110e422..00000000 --- a/vendor/github.com/charmbracelet/huh/validate.go +++ /dev/null @@ -1,61 +0,0 @@ -package huh - -import ( - "fmt" - "unicode/utf8" -) - -// ValidateNotEmpty checks if the input is not empty. -func ValidateNotEmpty() func(s string) error { - return func(s string) error { - if err := ValidateMinLength(1)(s); err != nil { - return fmt.Errorf("input cannot be empty") - } - return nil - } -} - -// ValidateMinLength checks if the length of the input is at least min. -func ValidateMinLength(v int) func(s string) error { - return func(s string) error { - if utf8.RuneCountInString(s) < v { - return fmt.Errorf("input must be at least %d characters long", v) - } - return nil - } -} - -// ValidateMaxLength checks if the length of the input is at most max. -func ValidateMaxLength(v int) func(s string) error { - return func(s string) error { - if utf8.RuneCountInString(s) > v { - return fmt.Errorf("input must be at most %d characters long", v) - } - return nil - } -} - -// ValidateLength checks if the length of the input is within the specified range. -func ValidateLength(minl, maxl int) func(s string) error { - return func(s string) error { - if err := ValidateMinLength(minl)(s); err != nil { - return err - } - return ValidateMaxLength(maxl)(s) - } -} - -// ValidateOneOf checks if a string is one of the specified options. -func ValidateOneOf(options ...string) func(string) error { - validOptions := make(map[string]struct{}) - for _, option := range options { - validOptions[option] = struct{}{} - } - - return func(value string) error { - if _, ok := validOptions[value]; !ok { - return fmt.Errorf("invalid option: %s", value) - } - return nil - } -} diff --git a/vendor/github.com/charmbracelet/huh/wrap.go b/vendor/github.com/charmbracelet/huh/wrap.go deleted file mode 100644 index ed0119c8..00000000 --- a/vendor/github.com/charmbracelet/huh/wrap.go +++ /dev/null @@ -1,7 +0,0 @@ -package huh - -import "github.com/charmbracelet/x/cellbuf" - -func wrap(s string, limit int) string { - return cellbuf.Wrap(s, limit, ",.-; ") -} diff --git a/vendor/github.com/charmbracelet/lipgloss/table/resizing.go b/vendor/github.com/charmbracelet/lipgloss/table/resizing.go deleted file mode 100644 index 30b0a010..00000000 --- a/vendor/github.com/charmbracelet/lipgloss/table/resizing.go +++ /dev/null @@ -1,429 +0,0 @@ -package table - -import ( - "math" - "strings" - - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/x/ansi" -) - -// resize resizes the table to fit the specified width. -// -// Given a user defined table width, we must ensure the table is exactly that -// width. This must account for all borders, column, separators, and column -// data. -// -// In the case where the table is narrower than the specified table width, -// we simply expand the columns evenly to fit the width. -// For example, a table with 3 columns takes up 50 characters total, and the -// width specified is 80, we expand each column by 10 characters, adding 30 -// to the total width. -// -// In the case where the table is wider than the specified table width, we -// _could_ simply shrink the columns evenly but this would result in data -// being truncated (perhaps unnecessarily). The naive approach could result -// in very poor cropping of the table data. So, instead of shrinking columns -// evenly, we calculate the median non-whitespace length of each column, and -// shrink the columns based on the largest median. -// -// For example, -// -// ┌──────┬───────────────┬──────────┐ -// │ Name │ Age of Person │ Location │ -// ├──────┼───────────────┼──────────┤ -// │ Kini │ 40 │ New York │ -// │ Eli │ 30 │ London │ -// │ Iris │ 20 │ Paris │ -// └──────┴───────────────┴──────────┘ -// -// Median non-whitespace length vs column width of each column: -// -// Name: 4 / 5 -// Age of Person: 2 / 15 -// Location: 6 / 10 -// -// The biggest difference is 15 - 2, so we can shrink the 2nd column by 13. -func (t *Table) resize() { - hasHeaders := len(t.headers) > 0 - rows := dataToMatrix(t.data) - r := newResizer(t.width, t.height, t.headers, rows) - r.wrap = t.wrap - r.borderColumn = t.borderColumn - r.yPaddings = make([][]int, len(r.allRows)) - - var allRows [][]string - if hasHeaders { - allRows = append([][]string{t.headers}, rows...) - } else { - allRows = rows - } - - styleFunc := t.styleFunc - if t.styleFunc == nil { - styleFunc = DefaultStyles - } - - r.rowHeights = r.defaultRowHeights() - - for i, row := range allRows { - r.yPaddings[i] = make([]int, len(row)) - - for j := range row { - column := &r.columns[j] - - // Making sure we're passing the right index to `styleFunc`. The header row should be `-1` and - // the others should start from `0`. - rowIndex := i - if hasHeaders { - rowIndex-- - } - style := styleFunc(rowIndex, j) - - topMargin, rightMargin, bottomMargin, leftMargin := style.GetMargin() - topPadding, rightPadding, bottomPadding, leftPadding := style.GetPadding() - - totalHorizontalPadding := leftMargin + rightMargin + leftPadding + rightPadding - column.xPadding = max(column.xPadding, totalHorizontalPadding) - column.fixedWidth = max(column.fixedWidth, style.GetWidth()) - - r.rowHeights[i] = max(r.rowHeights[i], style.GetHeight()) - - totalVerticalPadding := topMargin + bottomMargin + topPadding + bottomPadding - r.yPaddings[i][j] = totalVerticalPadding - } - } - - // A table width wasn't specified. In this case, detect according to - // content width. - if r.tableWidth <= 0 { - r.tableWidth = r.detectTableWidth() - } - - t.widths, t.heights = r.optimizedWidths() -} - -// resizerColumn is a column in the resizer. -type resizerColumn struct { - index int - min int - max int - median int - rows [][]string - xPadding int // horizontal padding - fixedWidth int -} - -// resizer is a table resizer. -type resizer struct { - tableWidth int - tableHeight int - headers []string - allRows [][]string - rowHeights []int - columns []resizerColumn - - wrap bool - borderColumn bool - yPaddings [][]int // vertical paddings -} - -// newResizer creates a new resizer. -func newResizer(tableWidth, tableHeight int, headers []string, rows [][]string) *resizer { - r := &resizer{ - tableWidth: tableWidth, - tableHeight: tableHeight, - headers: headers, - } - - if len(headers) > 0 { - r.allRows = append([][]string{headers}, rows...) - } else { - r.allRows = rows - } - - for _, row := range r.allRows { - for i, cell := range row { - cellLen := lipgloss.Width(cell) - - // Header or first row. Just add as is. - if len(r.columns) <= i { - r.columns = append(r.columns, resizerColumn{ - index: i, - min: cellLen, - max: cellLen, - median: cellLen, - }) - continue - } - - r.columns[i].rows = append(r.columns[i].rows, row) - r.columns[i].min = min(r.columns[i].min, cellLen) - r.columns[i].max = max(r.columns[i].max, cellLen) - } - } - for j := range r.columns { - widths := make([]int, len(r.columns[j].rows)) - for i, row := range r.columns[j].rows { - widths[i] = lipgloss.Width(row[j]) - } - r.columns[j].median = median(widths) - } - - return r -} - -// optimizedWidths returns the optimized column widths and row heights. -func (r *resizer) optimizedWidths() (colWidths, rowHeights []int) { - if r.maxTotal() <= r.tableWidth { - return r.expandTableWidth() - } - return r.shrinkTableWidth() -} - -// detectTableWidth detects the table width. -func (r *resizer) detectTableWidth() int { - return r.maxCharCount() + r.totalHorizontalPadding() + r.totalHorizontalBorder() -} - -// expandTableWidth expands the table width. -func (r *resizer) expandTableWidth() (colWidths, rowHeights []int) { - colWidths = r.maxColumnWidths() - - for { - totalWidth := sum(colWidths) + r.totalHorizontalBorder() - if totalWidth >= r.tableWidth { - break - } - - shorterColumnIndex := 0 - shorterColumnWidth := math.MaxInt32 - - for j, width := range colWidths { - if width == r.columns[j].fixedWidth { - continue - } - if width < shorterColumnWidth { - shorterColumnWidth = width - shorterColumnIndex = j - } - } - - colWidths[shorterColumnIndex]++ - } - - rowHeights = r.expandRowHeights(colWidths) - return -} - -// shrinkTableWidth shrinks the table width. -func (r *resizer) shrinkTableWidth() (colWidths, rowHeights []int) { - colWidths = r.maxColumnWidths() - - // Cut width of columns that are way too big. - shrinkBiggestColumns := func(veryBigOnly bool) { - for { - totalWidth := sum(colWidths) + r.totalHorizontalBorder() - if totalWidth <= r.tableWidth { - break - } - - bigColumnIndex := -math.MaxInt32 - bigColumnWidth := -math.MaxInt32 - - for j, width := range colWidths { - if width == r.columns[j].fixedWidth { - continue - } - if veryBigOnly { - if width >= (r.tableWidth/2) && width > bigColumnWidth { //nolint:mnd - bigColumnWidth = width - bigColumnIndex = j - } - } else { - if width > bigColumnWidth { - bigColumnWidth = width - bigColumnIndex = j - } - } - } - - if bigColumnIndex < 0 || colWidths[bigColumnIndex] == 0 { - break - } - colWidths[bigColumnIndex]-- - } - } - - // Cut width of columns that differ the most from the median. - shrinkToMedian := func() { - for { - totalWidth := sum(colWidths) + r.totalHorizontalBorder() - if totalWidth <= r.tableWidth { - break - } - - biggestDiffToMedian := -math.MaxInt32 - biggestDiffToMedianIndex := -math.MaxInt32 - - for j, width := range colWidths { - if width == r.columns[j].fixedWidth { - continue - } - diffToMedian := width - r.columns[j].median - if diffToMedian > 0 && diffToMedian > biggestDiffToMedian { - biggestDiffToMedian = diffToMedian - biggestDiffToMedianIndex = j - } - } - - if biggestDiffToMedianIndex <= 0 || colWidths[biggestDiffToMedianIndex] == 0 { - break - } - colWidths[biggestDiffToMedianIndex]-- - } - } - - shrinkBiggestColumns(true) - shrinkToMedian() - shrinkBiggestColumns(false) - - return colWidths, r.expandRowHeights(colWidths) -} - -// expandRowHeights expands the row heights. -func (r *resizer) expandRowHeights(colWidths []int) (rowHeights []int) { - rowHeights = r.defaultRowHeights() - if !r.wrap { - return rowHeights - } - hasHeaders := len(r.headers) > 0 - - for i, row := range r.allRows { - for j, cell := range row { - // NOTE(@andreynering): Headers always have a height of 1, even when wrap is enabled. - if hasHeaders && i == 0 { - continue - } - height := r.detectContentHeight(cell, colWidths[j]-r.xPaddingForCol(j)) + r.xPaddingForCell(i, j) - if height > rowHeights[i] { - rowHeights[i] = height - } - } - } - return -} - -// defaultRowHeights returns the default row heights. -func (r *resizer) defaultRowHeights() (rowHeights []int) { - rowHeights = make([]int, len(r.allRows)) - for i := range rowHeights { - if i < len(r.rowHeights) { - rowHeights[i] = r.rowHeights[i] - } - if rowHeights[i] < 1 { - rowHeights[i] = 1 - } - } - return -} - -// maxColumnWidths returns the maximum column widths. -func (r *resizer) maxColumnWidths() []int { - maxColumnWidths := make([]int, len(r.columns)) - for i, col := range r.columns { - if col.fixedWidth > 0 { - maxColumnWidths[i] = col.fixedWidth - } else { - maxColumnWidths[i] = col.max + r.xPaddingForCol(col.index) - } - } - return maxColumnWidths -} - -// columnCount returns the column count. -func (r *resizer) columnCount() int { - return len(r.columns) -} - -// maxCharCount returns the maximum character count. -func (r *resizer) maxCharCount() int { - var count int - for _, col := range r.columns { - if col.fixedWidth > 0 { - count += col.fixedWidth - r.xPaddingForCol(col.index) - } else { - count += col.max - } - } - return count -} - -// maxTotal returns the maximum total width. -func (r *resizer) maxTotal() (maxTotal int) { - for j, column := range r.columns { - if column.fixedWidth > 0 { - maxTotal += column.fixedWidth - } else { - maxTotal += column.max + r.xPaddingForCol(j) - } - } - return -} - -// totalHorizontalPadding returns the total padding. -func (r *resizer) totalHorizontalPadding() (totalHorizontalPadding int) { - for _, col := range r.columns { - totalHorizontalPadding += col.xPadding - } - return -} - -// xPaddingForCol returns the horizontal padding for a column. -func (r *resizer) xPaddingForCol(j int) int { - if j >= len(r.columns) { - return 0 - } - return r.columns[j].xPadding -} - -// xPaddingForCell returns the horizontal padding for a cell. -func (r *resizer) xPaddingForCell(i, j int) int { - if i >= len(r.yPaddings) || j >= len(r.yPaddings[i]) { - return 0 - } - return r.yPaddings[i][j] -} - -// totalHorizontalBorder returns the total border. -func (r *resizer) totalHorizontalBorder() int { - return (r.columnCount() * r.borderPerCell()) + r.extraBorder() -} - -// borderPerCell returns number of border chars per cell. -func (r *resizer) borderPerCell() int { - if r.borderColumn { - return 1 - } - return 0 -} - -// extraBorder returns the number of the extra border char at the end of the table. -func (r *resizer) extraBorder() int { - if r.borderColumn { - return 1 - } - return 0 -} - -// detectContentHeight detects the content height. -func (r *resizer) detectContentHeight(content string, width int) (height int) { - if width == 0 { - return 1 - } - content = strings.ReplaceAll(content, "\r\n", "\n") - for _, line := range strings.Split(content, "\n") { - height += strings.Count(ansi.Wrap(line, width, ""), "\n") + 1 - } - return -} diff --git a/vendor/github.com/charmbracelet/lipgloss/table/rows.go b/vendor/github.com/charmbracelet/lipgloss/table/rows.go deleted file mode 100644 index a48bc794..00000000 --- a/vendor/github.com/charmbracelet/lipgloss/table/rows.go +++ /dev/null @@ -1,129 +0,0 @@ -package table - -// Data is the interface that wraps the basic methods of a table model. -type Data interface { - // At returns the contents of the cell at the given index. - At(row, cell int) string - - // Rows returns the number of rows in the table. - Rows() int - - // Columns returns the number of columns in the table. - Columns() int -} - -// StringData is a string-based implementation of the Data interface. -type StringData struct { - rows [][]string - columns int -} - -// NewStringData creates a new StringData with the given number of columns. -func NewStringData(rows ...[]string) *StringData { - m := StringData{columns: 0} - - for _, row := range rows { - m.columns = max(m.columns, len(row)) - m.rows = append(m.rows, row) - } - - return &m -} - -// Append appends the given row to the table. -func (m *StringData) Append(row []string) { - m.columns = max(m.columns, len(row)) - m.rows = append(m.rows, row) -} - -// At returns the contents of the cell at the given index. -func (m *StringData) At(row, cell int) string { - if row >= len(m.rows) || cell >= len(m.rows[row]) { - return "" - } - - return m.rows[row][cell] -} - -// Columns returns the number of columns in the table. -func (m *StringData) Columns() int { - return m.columns -} - -// Item appends the given row to the table. -func (m *StringData) Item(rows ...string) *StringData { - m.columns = max(m.columns, len(rows)) - m.rows = append(m.rows, rows) - return m -} - -// Rows returns the number of rows in the table. -func (m *StringData) Rows() int { - return len(m.rows) -} - -// Filter applies a filter on some data. -type Filter struct { - data Data - filter func(row int) bool -} - -// NewFilter initializes a new Filter. -func NewFilter(data Data) *Filter { - return &Filter{data: data} -} - -// Filter applies the given filter function to the data. -func (m *Filter) Filter(f func(row int) bool) *Filter { - m.filter = f - return m -} - -// At returns the row at the given index. -func (m *Filter) At(row, cell int) string { - j := 0 - for i := 0; i < m.data.Rows(); i++ { - if m.filter(i) { - if j == row { - return m.data.At(i, cell) - } - - j++ - } - } - - return "" -} - -// Columns returns the number of columns in the table. -func (m *Filter) Columns() int { - return m.data.Columns() -} - -// Rows returns the number of rows in the table. -func (m *Filter) Rows() int { - j := 0 - for i := 0; i < m.data.Rows(); i++ { - if m.filter(i) { - j++ - } - } - - return j -} - -// dataToMatrix converts an object that implements the Data interface to a table. -func dataToMatrix(data Data) (rows [][]string) { - numRows := data.Rows() - numCols := data.Columns() - rows = make([][]string, numRows) - - for i := 0; i < numRows; i++ { - rows[i] = make([]string, numCols) - - for j := 0; j < numCols; j++ { - rows[i][j] = data.At(i, j) - } - } - return -} diff --git a/vendor/github.com/charmbracelet/lipgloss/table/table.go b/vendor/github.com/charmbracelet/lipgloss/table/table.go deleted file mode 100644 index ad17fcfb..00000000 --- a/vendor/github.com/charmbracelet/lipgloss/table/table.go +++ /dev/null @@ -1,503 +0,0 @@ -// Package table provides a styled table renderer for terminals. -package table - -import ( - "strings" - - "github.com/charmbracelet/lipgloss" - "github.com/charmbracelet/x/ansi" -) - -// HeaderRow denotes the header's row index used when rendering headers. Use -// this value when looking to customize header styles in StyleFunc. -const HeaderRow int = -1 - -// StyleFunc is the style function that determines the style of a Cell. -// -// It takes the row and column of the cell as an input and determines the -// lipgloss Style to use for that cell position. -// -// Example: -// -// t := table.New(). -// Headers("Name", "Age"). -// Row("Kini", 4). -// Row("Eli", 1). -// Row("Iris", 102). -// StyleFunc(func(row, col int) lipgloss.Style { -// switch { -// case row == 0: -// return HeaderStyle -// case row%2 == 0: -// return EvenRowStyle -// default: -// return OddRowStyle -// } -// }) -type StyleFunc func(row, col int) lipgloss.Style - -// DefaultStyles is a TableStyleFunc that returns a new Style with no attributes. -func DefaultStyles(_, _ int) lipgloss.Style { - return lipgloss.NewStyle() -} - -// Table is a type for rendering tables. -type Table struct { - styleFunc StyleFunc - border lipgloss.Border - - borderTop bool - borderBottom bool - borderLeft bool - borderRight bool - borderHeader bool - borderColumn bool - borderRow bool - - borderStyle lipgloss.Style - headers []string - data Data - - width int - height int - useManualHeight bool - offset int - wrap bool - - // widths tracks the width of each column. - widths []int - - // heights tracks the height of each row. - heights []int -} - -// New returns a new Table that can be modified through different -// attributes. -// -// By default, a table has no border, no styling, and no rows. -func New() *Table { - return &Table{ - styleFunc: DefaultStyles, - border: lipgloss.RoundedBorder(), - borderBottom: true, - borderColumn: true, - borderHeader: true, - borderLeft: true, - borderRight: true, - borderTop: true, - wrap: true, - data: NewStringData(), - } -} - -// ClearRows clears the table rows. -func (t *Table) ClearRows() *Table { - t.data = NewStringData() - return t -} - -// StyleFunc sets the style for a cell based on it's position (row, column). -func (t *Table) StyleFunc(style StyleFunc) *Table { - t.styleFunc = style - return t -} - -// style returns the style for a cell based on it's position (row, column). -func (t *Table) style(row, col int) lipgloss.Style { - if t.styleFunc == nil { - return lipgloss.NewStyle() - } - return t.styleFunc(row, col) -} - -// Data sets the table data. -func (t *Table) Data(data Data) *Table { - t.data = data - return t -} - -// Rows appends rows to the table data. -func (t *Table) Rows(rows ...[]string) *Table { - for _, row := range rows { - switch t.data.(type) { - case *StringData: - t.data.(*StringData).Append(row) - } - } - return t -} - -// Row appends a row to the table data. -func (t *Table) Row(row ...string) *Table { - switch t.data.(type) { - case *StringData: - t.data.(*StringData).Append(row) - } - return t -} - -// Headers sets the table headers. -func (t *Table) Headers(headers ...string) *Table { - t.headers = headers - return t -} - -// Border sets the table border. -func (t *Table) Border(border lipgloss.Border) *Table { - t.border = border - return t -} - -// BorderTop sets the top border. -func (t *Table) BorderTop(v bool) *Table { - t.borderTop = v - return t -} - -// BorderBottom sets the bottom border. -func (t *Table) BorderBottom(v bool) *Table { - t.borderBottom = v - return t -} - -// BorderLeft sets the left border. -func (t *Table) BorderLeft(v bool) *Table { - t.borderLeft = v - return t -} - -// BorderRight sets the right border. -func (t *Table) BorderRight(v bool) *Table { - t.borderRight = v - return t -} - -// BorderHeader sets the header separator border. -func (t *Table) BorderHeader(v bool) *Table { - t.borderHeader = v - return t -} - -// BorderColumn sets the column border separator. -func (t *Table) BorderColumn(v bool) *Table { - t.borderColumn = v - return t -} - -// BorderRow sets the row border separator. -func (t *Table) BorderRow(v bool) *Table { - t.borderRow = v - return t -} - -// BorderStyle sets the style for the table border. -func (t *Table) BorderStyle(style lipgloss.Style) *Table { - t.borderStyle = style - return t -} - -// Width sets the table width, this auto-sizes the columns to fit the width by -// either expanding or contracting the widths of each column as a best effort -// approach. -func (t *Table) Width(w int) *Table { - t.width = w - return t -} - -// Height sets the table height. -func (t *Table) Height(h int) *Table { - t.height = h - t.useManualHeight = true - return t -} - -// Offset sets the table rendering offset. -// -// Warning: you may declare Offset only after setting Rows. Otherwise it will be -// ignored. -func (t *Table) Offset(o int) *Table { - t.offset = o - return t -} - -// Wrap dictates whether or not the table content should wrap. -func (t *Table) Wrap(w bool) *Table { - t.wrap = w - return t -} - -// String returns the table as a string. -func (t *Table) String() string { - hasHeaders := len(t.headers) > 0 - hasRows := t.data != nil && t.data.Rows() > 0 - - if !hasHeaders && !hasRows { - return "" - } - - // Add empty cells to the headers, until it's the same length as the longest - // row (only if there are at headers in the first place). - if hasHeaders { - for i := len(t.headers); i < t.data.Columns(); i++ { - t.headers = append(t.headers, "") - } - } - - // Do all the sizing calculations for width and height. - t.resize() - - var sb strings.Builder - - if t.borderTop { - sb.WriteString(t.constructTopBorder()) - sb.WriteString("\n") - } - - if hasHeaders { - sb.WriteString(t.constructHeaders()) - sb.WriteString("\n") - } - - var bottom string - if t.borderBottom { - bottom = t.constructBottomBorder() - } - - // If there are no data rows render nothing. - if t.data.Rows() > 0 { - switch { - case t.useManualHeight: - // The height of the top border. Subtract 1 for the newline. - topHeight := lipgloss.Height(sb.String()) - 1 - availableLines := t.height - (topHeight + lipgloss.Height(bottom)) - - // if the height is larger than the number of rows, use the number - // of rows. - if availableLines > t.data.Rows() { - availableLines = t.data.Rows() - } - sb.WriteString(t.constructRows(availableLines)) - - default: - for r := t.offset; r < t.data.Rows(); r++ { - sb.WriteString(t.constructRow(r, false)) - } - } - } - - sb.WriteString(bottom) - - return lipgloss.NewStyle(). - MaxHeight(t.computeHeight()). - MaxWidth(t.width). - Render(sb.String()) -} - -// computeHeight computes the height of the table in it's current configuration. -func (t *Table) computeHeight() int { - hasHeaders := len(t.headers) > 0 - return sum(t.heights) - 1 + btoi(hasHeaders) + - btoi(t.borderTop) + btoi(t.borderBottom) + - btoi(t.borderHeader) + t.data.Rows()*btoi(t.borderRow) -} - -// Render returns the table as a string. -func (t *Table) Render() string { - return t.String() -} - -// constructTopBorder constructs the top border for the table given it's current -// border configuration and data. -func (t *Table) constructTopBorder() string { - var s strings.Builder - if t.borderLeft { - s.WriteString(t.borderStyle.Render(t.border.TopLeft)) - } - for i := 0; i < len(t.widths); i++ { - s.WriteString(t.borderStyle.Render(strings.Repeat(t.border.Top, t.widths[i]))) - if i < len(t.widths)-1 && t.borderColumn { - s.WriteString(t.borderStyle.Render(t.border.MiddleTop)) - } - } - if t.borderRight { - s.WriteString(t.borderStyle.Render(t.border.TopRight)) - } - return s.String() -} - -// constructBottomBorder constructs the bottom border for the table given it's current -// border configuration and data. -func (t *Table) constructBottomBorder() string { - var s strings.Builder - if t.borderLeft { - s.WriteString(t.borderStyle.Render(t.border.BottomLeft)) - } - for i := 0; i < len(t.widths); i++ { - s.WriteString(t.borderStyle.Render(strings.Repeat(t.border.Bottom, t.widths[i]))) - if i < len(t.widths)-1 && t.borderColumn { - s.WriteString(t.borderStyle.Render(t.border.MiddleBottom)) - } - } - if t.borderRight { - s.WriteString(t.borderStyle.Render(t.border.BottomRight)) - } - return s.String() -} - -// constructHeaders constructs the headers for the table given it's current -// header configuration and data. -func (t *Table) constructHeaders() string { - height := t.heights[HeaderRow+1] - - var s strings.Builder - if t.borderLeft { - s.WriteString(t.borderStyle.Render(t.border.Left)) - } - for i, header := range t.headers { - cellStyle := t.style(HeaderRow, i) - - if !t.wrap { - header = t.truncateCell(header, HeaderRow, i) - } - - s.WriteString(cellStyle. - Height(height - cellStyle.GetVerticalMargins()). - MaxHeight(height). - Width(t.widths[i] - cellStyle.GetHorizontalMargins()). - MaxWidth(t.widths[i]). - Render(t.truncateCell(header, HeaderRow, i))) - if i < len(t.headers)-1 && t.borderColumn { - s.WriteString(t.borderStyle.Render(t.border.Left)) - } - } - if t.borderHeader { - if t.borderRight { - s.WriteString(t.borderStyle.Render(t.border.Right)) - } - s.WriteString("\n") - if t.borderLeft { - s.WriteString(t.borderStyle.Render(t.border.MiddleLeft)) - } - for i := 0; i < len(t.headers); i++ { - s.WriteString(t.borderStyle.Render(strings.Repeat(t.border.Top, t.widths[i]))) - if i < len(t.headers)-1 && t.borderColumn { - s.WriteString(t.borderStyle.Render(t.border.Middle)) - } - } - if t.borderRight { - s.WriteString(t.borderStyle.Render(t.border.MiddleRight)) - } - } - if t.borderRight && !t.borderHeader { - s.WriteString(t.borderStyle.Render(t.border.Right)) - } - return s.String() -} - -func (t *Table) constructRows(availableLines int) string { - var sb strings.Builder - - // The number of rows to render after removing the offset. - offsetRowCount := t.data.Rows() - t.offset - - // The number of rows to render. We always render at least one row. - rowsToRender := availableLines - rowsToRender = max(rowsToRender, 1) - - // Check if we need to render an overflow row. - needsOverflow := rowsToRender < offsetRowCount - - // only use the offset as the starting value if there is overflow. - rowIdx := t.offset - if !needsOverflow { - // if there is no overflow, just render to the height of the table - // check there's enough content to fill the table - rowIdx = t.data.Rows() - rowsToRender - } - for rowsToRender > 0 && rowIdx < t.data.Rows() { - // Whenever the height is too small to render all rows, the bottom row will be an overflow row (ellipsis). - isOverflow := needsOverflow && rowsToRender == 1 - - sb.WriteString(t.constructRow(rowIdx, isOverflow)) - - rowIdx++ - rowsToRender-- - } - return sb.String() -} - -// constructRow constructs the row for the table given an index and row data -// based on the current configuration. If isOverflow is true, the row is -// rendered as an overflow row (using ellipsis). -func (t *Table) constructRow(index int, isOverflow bool) string { - var s strings.Builder - - hasHeaders := len(t.headers) > 0 - height := t.heights[index+btoi(hasHeaders)] - if isOverflow { - height = 1 - } - - var cells []string - left := strings.Repeat(t.borderStyle.Render(t.border.Left)+"\n", height) - if t.borderLeft { - cells = append(cells, left) - } - - for c := 0; c < t.data.Columns(); c++ { - cell := "…" - if !isOverflow { - cell = t.data.At(index, c) - } - - cellStyle := t.style(index, c) - if !t.wrap { - cell = t.truncateCell(cell, index, c) - } - cells = append(cells, cellStyle. - // Account for the margins in the cell sizing. - Height(height-cellStyle.GetVerticalMargins()). - MaxHeight(height). - Width(t.widths[c]-cellStyle.GetHorizontalMargins()). - MaxWidth(t.widths[c]). - Render(cell)) - - if c < t.data.Columns()-1 && t.borderColumn { - cells = append(cells, left) - } - } - - if t.borderRight { - right := strings.Repeat(t.borderStyle.Render(t.border.Right)+"\n", height) - cells = append(cells, right) - } - - for i, cell := range cells { - cells[i] = strings.TrimRight(cell, "\n") - } - - s.WriteString(lipgloss.JoinHorizontal(lipgloss.Top, cells...) + "\n") - - if t.borderRow && index < t.data.Rows()-1 && !isOverflow { - s.WriteString(t.borderStyle.Render(t.border.MiddleLeft)) - for i := 0; i < len(t.widths); i++ { - s.WriteString(t.borderStyle.Render(strings.Repeat(t.border.Bottom, t.widths[i]))) - if i < len(t.widths)-1 && t.borderColumn { - s.WriteString(t.borderStyle.Render(t.border.Middle)) - } - } - s.WriteString(t.borderStyle.Render(t.border.MiddleRight) + "\n") - } - - return s.String() -} - -func (t *Table) truncateCell(cell string, rowIndex, colIndex int) string { - hasHeaders := len(t.headers) > 0 - height := t.heights[rowIndex+btoi(hasHeaders)] - cellWidth := t.widths[colIndex] - cellStyle := t.style(rowIndex, colIndex) - - length := (cellWidth * height) - cellStyle.GetHorizontalPadding() - cellStyle.GetHorizontalMargins() - return ansi.Truncate(cell, length, "…") -} diff --git a/vendor/github.com/charmbracelet/lipgloss/table/util.go b/vendor/github.com/charmbracelet/lipgloss/table/util.go deleted file mode 100644 index 74bcdffe..00000000 --- a/vendor/github.com/charmbracelet/lipgloss/table/util.go +++ /dev/null @@ -1,52 +0,0 @@ -package table - -import ( - "sort" -) - -// btoi converts a boolean to an integer, 1 if true, 0 if false. -func btoi(b bool) int { - if b { - return 1 - } - return 0 -} - -// max returns the greater of two integers. -func max(a, b int) int { //nolint:predeclared - if a > b { - return a - } - return b -} - -// min returns the smaller of two integers. -func min(a, b int) int { //nolint:predeclared - if a < b { - return a - } - return b -} - -// sum returns the sum of all integers in a slice. -func sum(n []int) int { - var sum int - for _, i := range n { - sum += i - } - return sum -} - -// median returns the median of a slice of integers. -func median(n []int) int { - sort.Ints(n) - - if len(n) <= 0 { - return 0 - } - if len(n)%2 == 0 { - h := len(n) / 2 //nolint:mnd - return (n[h-1] + n[h]) / 2 //nolint:mnd - } - return n[len(n)/2] -} diff --git a/vendor/github.com/charmbracelet/x/exp/slice/LICENSE b/vendor/github.com/charmbracelet/x/exp/slice/LICENSE deleted file mode 100644 index 65a5654e..00000000 --- a/vendor/github.com/charmbracelet/x/exp/slice/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Charmbracelet, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/charmbracelet/x/exp/slice/slice.go b/vendor/github.com/charmbracelet/x/exp/slice/slice.go deleted file mode 100644 index b909f090..00000000 --- a/vendor/github.com/charmbracelet/x/exp/slice/slice.go +++ /dev/null @@ -1,37 +0,0 @@ -package slice - -// GroupBy groups a slice of items by a key function. -func GroupBy[T any, K comparable](list []T, key func(T) K) map[K][]T { - groups := make(map[K][]T) - - for _, item := range list { - k := key(item) - groups[k] = append(groups[k], item) - } - - return groups -} - -// Take returns the first n elements of the given slice. If there are not -// enough elements in the slice, the whole slice is returned. -func Take[A any](slice []A, n int) []A { - if n > len(slice) { - return slice - } - return slice[:n] -} - -// Uniq returns a new slice with all duplicates removed. -func Uniq[T comparable](list []T) []T { - seen := make(map[T]struct{}, len(list)) - uniqList := make([]T, 0, len(list)) - - for _, item := range list { - if _, ok := seen[item]; !ok { - seen[item] = struct{}{} - uniqList = append(uniqList, item) - } - } - - return uniqList -} diff --git a/vendor/github.com/charmbracelet/x/exp/strings/LICENSE b/vendor/github.com/charmbracelet/x/exp/strings/LICENSE deleted file mode 100644 index 65a5654e..00000000 --- a/vendor/github.com/charmbracelet/x/exp/strings/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Charmbracelet, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/charmbracelet/x/exp/strings/join.go b/vendor/github.com/charmbracelet/x/exp/strings/join.go deleted file mode 100644 index d9d51b52..00000000 --- a/vendor/github.com/charmbracelet/x/exp/strings/join.go +++ /dev/null @@ -1,133 +0,0 @@ -package strings - -// The so-called spoken language join here works well for some Western -// languages. PRs for other languages are welcome, but do note that -// implementation for some languages will be less straightforward than the ones -// in use here. - -import ( - "strings" -) - -// Language is a spoken Language. -type Language int - -// Available spoken lanaguges. -const ( - DE Language = iota - DK - EN - ES - FR - IT - NO - PT - SE -) - -// String returns the English name of the [Language] code. -func (l Language) String() string { - return map[Language]string{ - DE: "German", - DK: "Danish", - EN: "English", - ES: "Spanish", - FR: "French", - IT: "Italian", - NO: "Norwegian", - PT: "Portuguese", - SE: "Swedish", - }[l] -} - -func (l Language) conjuction() string { - switch l { - case DE: - return "und" - case DK: - return "og" - case EN: - return "and" - case ES: - return "y" - case FR: - return "et" - case NO: - return "og" - case IT: - return "e" - case PT: - return "e" - case SE: - return "och" - default: - return "" - } -} - -func (l Language) separator() string { - switch l { - case DE, DK, EN, ES, FR, NO, IT, PT, SE: - return ", " - default: - return " " - } -} - -// EnglishJoin joins a slice of strings with commas and the "and" conjugation -// before the final item. The Oxford comma can optionally be applied. -// -// Example: -// -// str := EnglishJoin([]string{"meow", "purr", "raow"}, true) -// fmt.Println(str) // meow, purr, and raow -func EnglishJoin(words []string, oxfordComma bool) string { - return spokenLangJoin(words, EN, oxfordComma) -} - -// SpokenLangaugeJoin joins a slice of strings with commas and a conjuction -// before the final item. You may specify the language with [Language]. -// -// If you are using English and need the Oxford Comma, use [EnglishJoin]. -// -// Example: -// -// str := SpokenLanguageJoin([]string{"eins", "zwei", "drei"}, DE) -// fmt.Println(str) // eins, zwei und drei -func SpokenLanguageJoin(words []string, language Language) string { - return spokenLangJoin(words, language, false) -} - -func spokenLangJoin(words []string, language Language, oxfordComma bool) string { - conjuction := language.conjuction() + " " - separator := language.separator() - - b := strings.Builder{} - for i, word := range words { - if word == "" { - continue - } - - if i == 0 { - b.WriteString(word) - continue - } - - // Is this the final word? - if len(words) > 1 && i == len(words)-1 { - // Apply the Oxford comma if requested as long as the language is - // English. - if language == EN && oxfordComma && i > 1 { - b.WriteString(separator) - } else { - b.WriteRune(' ') - } - - b.WriteString(conjuction + word) - continue - } - - b.WriteString(separator + word) - } - return b.String() -} diff --git a/vendor/github.com/cloudflare/circl/LICENSE b/vendor/github.com/cloudflare/circl/LICENSE deleted file mode 100644 index 67edaa90..00000000 --- a/vendor/github.com/cloudflare/circl/LICENSE +++ /dev/null @@ -1,57 +0,0 @@ -Copyright (c) 2019 Cloudflare. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Cloudflare nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -======================================================================== - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/curve.go b/vendor/github.com/cloudflare/circl/dh/x25519/curve.go deleted file mode 100644 index f9057c2b..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/curve.go +++ /dev/null @@ -1,96 +0,0 @@ -package x25519 - -import ( - fp "github.com/cloudflare/circl/math/fp25519" -) - -// ladderJoye calculates a fixed-point multiplication with the generator point. -// The algorithm is the right-to-left Joye's ladder as described -// in "How to precompute a ladder" in SAC'2017. -func ladderJoye(k *Key) { - w := [5]fp.Elt{} // [mu,x1,z1,x2,z2] order must be preserved. - fp.SetOne(&w[1]) // x1 = 1 - fp.SetOne(&w[2]) // z1 = 1 - w[3] = fp.Elt{ // x2 = G-S - 0xbd, 0xaa, 0x2f, 0xc8, 0xfe, 0xe1, 0x94, 0x7e, - 0xf8, 0xed, 0xb2, 0x14, 0xae, 0x95, 0xf0, 0xbb, - 0xe2, 0x48, 0x5d, 0x23, 0xb9, 0xa0, 0xc7, 0xad, - 0x34, 0xab, 0x7c, 0xe2, 0xee, 0xcd, 0xae, 0x1e, - } - fp.SetOne(&w[4]) // z2 = 1 - - const n = 255 - const h = 3 - swap := uint(1) - for s := 0; s < n-h; s++ { - i := (s + h) / 8 - j := (s + h) % 8 - bit := uint((k[i] >> uint(j)) & 1) - copy(w[0][:], tableGenerator[s*Size:(s+1)*Size]) - diffAdd(&w, swap^bit) - swap = bit - } - for s := 0; s < h; s++ { - double(&w[1], &w[2]) - } - toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) -} - -// ladderMontgomery calculates a generic scalar point multiplication -// The algorithm implemented is the left-to-right Montgomery's ladder. -func ladderMontgomery(k, xP *Key) { - w := [5]fp.Elt{} // [x1, x2, z2, x3, z3] order must be preserved. - w[0] = *(*fp.Elt)(xP) // x1 = xP - fp.SetOne(&w[1]) // x2 = 1 - w[3] = *(*fp.Elt)(xP) // x3 = xP - fp.SetOne(&w[4]) // z3 = 1 - - move := uint(0) - for s := 255 - 1; s >= 0; s-- { - i := s / 8 - j := s % 8 - bit := uint((k[i] >> uint(j)) & 1) - ladderStep(&w, move^bit) - move = bit - } - toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) -} - -func toAffine(k *[fp.Size]byte, x, z *fp.Elt) { - fp.Inv(z, z) - fp.Mul(x, x, z) - _ = fp.ToBytes(k[:], x) -} - -var lowOrderPoints = [5]fp.Elt{ - { /* (0,_,1) point of order 2 on Curve25519 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - { /* (1,_,1) point of order 4 on Curve25519 */ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - { /* (x,_,1) first point of order 8 on Curve25519 */ - 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, - 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, - 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, - 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00, - }, - { /* (x,_,1) second point of order 8 on Curve25519 */ - 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, - 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, - 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, - 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57, - }, - { /* (-1,_,1) a point of order 4 on the twist of Curve25519 */ - 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - }, -} diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go b/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go deleted file mode 100644 index 8a3d54c5..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -package x25519 - -import ( - fp "github.com/cloudflare/circl/math/fp25519" - "golang.org/x/sys/cpu" -) - -var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX - -var _ = hasBmi2Adx - -func double(x, z *fp.Elt) { doubleAmd64(x, z) } -func diffAdd(w *[5]fp.Elt, b uint) { diffAddAmd64(w, b) } -func ladderStep(w *[5]fp.Elt, b uint) { ladderStepAmd64(w, b) } -func mulA24(z, x *fp.Elt) { mulA24Amd64(z, x) } - -//go:noescape -func ladderStepAmd64(w *[5]fp.Elt, b uint) - -//go:noescape -func diffAddAmd64(w *[5]fp.Elt, b uint) - -//go:noescape -func doubleAmd64(x, z *fp.Elt) - -//go:noescape -func mulA24Amd64(z, x *fp.Elt) diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h b/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h deleted file mode 100644 index 8c1ae4d0..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h +++ /dev/null @@ -1,111 +0,0 @@ -#define ladderStepLeg \ - addSub(x2,z2) \ - addSub(x3,z3) \ - integerMulLeg(b0,x2,z3) \ - integerMulLeg(b1,x3,z2) \ - reduceFromDoubleLeg(t0,b0) \ - reduceFromDoubleLeg(t1,b1) \ - addSub(t0,t1) \ - cselect(x2,x3,regMove) \ - cselect(z2,z3,regMove) \ - integerSqrLeg(b0,t0) \ - integerSqrLeg(b1,t1) \ - reduceFromDoubleLeg(x3,b0) \ - reduceFromDoubleLeg(z3,b1) \ - integerMulLeg(b0,x1,z3) \ - reduceFromDoubleLeg(z3,b0) \ - integerSqrLeg(b0,x2) \ - integerSqrLeg(b1,z2) \ - reduceFromDoubleLeg(x2,b0) \ - reduceFromDoubleLeg(z2,b1) \ - subtraction(t0,x2,z2) \ - multiplyA24Leg(t1,t0) \ - additionLeg(t1,t1,z2) \ - integerMulLeg(b0,x2,z2) \ - integerMulLeg(b1,t0,t1) \ - reduceFromDoubleLeg(x2,b0) \ - reduceFromDoubleLeg(z2,b1) - -#define ladderStepBmi2Adx \ - addSub(x2,z2) \ - addSub(x3,z3) \ - integerMulAdx(b0,x2,z3) \ - integerMulAdx(b1,x3,z2) \ - reduceFromDoubleAdx(t0,b0) \ - reduceFromDoubleAdx(t1,b1) \ - addSub(t0,t1) \ - cselect(x2,x3,regMove) \ - cselect(z2,z3,regMove) \ - integerSqrAdx(b0,t0) \ - integerSqrAdx(b1,t1) \ - reduceFromDoubleAdx(x3,b0) \ - reduceFromDoubleAdx(z3,b1) \ - integerMulAdx(b0,x1,z3) \ - reduceFromDoubleAdx(z3,b0) \ - integerSqrAdx(b0,x2) \ - integerSqrAdx(b1,z2) \ - reduceFromDoubleAdx(x2,b0) \ - reduceFromDoubleAdx(z2,b1) \ - subtraction(t0,x2,z2) \ - multiplyA24Adx(t1,t0) \ - additionAdx(t1,t1,z2) \ - integerMulAdx(b0,x2,z2) \ - integerMulAdx(b1,t0,t1) \ - reduceFromDoubleAdx(x2,b0) \ - reduceFromDoubleAdx(z2,b1) - -#define difAddLeg \ - addSub(x1,z1) \ - integerMulLeg(b0,z1,ui) \ - reduceFromDoubleLeg(z1,b0) \ - addSub(x1,z1) \ - integerSqrLeg(b0,x1) \ - integerSqrLeg(b1,z1) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) \ - integerMulLeg(b0,x1,z2) \ - integerMulLeg(b1,z1,x2) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) - -#define difAddBmi2Adx \ - addSub(x1,z1) \ - integerMulAdx(b0,z1,ui) \ - reduceFromDoubleAdx(z1,b0) \ - addSub(x1,z1) \ - integerSqrAdx(b0,x1) \ - integerSqrAdx(b1,z1) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) \ - integerMulAdx(b0,x1,z2) \ - integerMulAdx(b1,z1,x2) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) - -#define doubleLeg \ - addSub(x1,z1) \ - integerSqrLeg(b0,x1) \ - integerSqrLeg(b1,z1) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) \ - subtraction(t0,x1,z1) \ - multiplyA24Leg(t1,t0) \ - additionLeg(t1,t1,z1) \ - integerMulLeg(b0,x1,z1) \ - integerMulLeg(b1,t0,t1) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) - -#define doubleBmi2Adx \ - addSub(x1,z1) \ - integerSqrAdx(b0,x1) \ - integerSqrAdx(b1,z1) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) \ - subtraction(t0,x1,z1) \ - multiplyA24Adx(t1,t0) \ - additionAdx(t1,t1,z1) \ - integerMulAdx(b0,x1,z1) \ - integerMulAdx(b1,t0,t1) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s b/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s deleted file mode 100644 index ce9f0628..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s +++ /dev/null @@ -1,157 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -#include "textflag.h" - -// Depends on circl/math/fp25519 package -#include "../../math/fp25519/fp_amd64.h" -#include "curve_amd64.h" - -// CTE_A24 is (A+2)/4 from Curve25519 -#define CTE_A24 121666 - -#define Size 32 - -// multiplyA24Leg multiplies x times CTE_A24 and stores in z -// Uses: AX, DX, R8-R13, FLAGS -// Instr: x86_64, cmov -#define multiplyA24Leg(z,x) \ - MOVL $CTE_A24, AX; MULQ 0+x; MOVQ AX, R8; MOVQ DX, R9; \ - MOVL $CTE_A24, AX; MULQ 8+x; MOVQ AX, R12; MOVQ DX, R10; \ - MOVL $CTE_A24, AX; MULQ 16+x; MOVQ AX, R13; MOVQ DX, R11; \ - MOVL $CTE_A24, AX; MULQ 24+x; \ - ADDQ R12, R9; \ - ADCQ R13, R10; \ - ADCQ AX, R11; \ - ADCQ $0, DX; \ - MOVL $38, AX; /* 2*C = 38 = 2^256 MOD 2^255-19*/ \ - IMULQ AX, DX; \ - ADDQ DX, R8; \ - ADCQ $0, R9; MOVQ R9, 8+z; \ - ADCQ $0, R10; MOVQ R10, 16+z; \ - ADCQ $0, R11; MOVQ R11, 24+z; \ - MOVQ $0, DX; \ - CMOVQCS AX, DX; \ - ADDQ DX, R8; MOVQ R8, 0+z; - -// multiplyA24Adx multiplies x times CTE_A24 and stores in z -// Uses: AX, DX, R8-R12, FLAGS -// Instr: x86_64, cmov, bmi2 -#define multiplyA24Adx(z,x) \ - MOVQ $CTE_A24, DX; \ - MULXQ 0+x, R8, R10; \ - MULXQ 8+x, R9, R11; ADDQ R10, R9; \ - MULXQ 16+x, R10, AX; ADCQ R11, R10; \ - MULXQ 24+x, R11, R12; ADCQ AX, R11; \ - ;;;;;;;;;;;;;;;;;;;;; ADCQ $0, R12; \ - MOVL $38, DX; /* 2*C = 38 = 2^256 MOD 2^255-19*/ \ - IMULQ DX, R12; \ - ADDQ R12, R8; \ - ADCQ $0, R9; MOVQ R9, 8+z; \ - ADCQ $0, R10; MOVQ R10, 16+z; \ - ADCQ $0, R11; MOVQ R11, 24+z; \ - MOVQ $0, R12; \ - CMOVQCS DX, R12; \ - ADDQ R12, R8; MOVQ R8, 0+z; - -#define mulA24Legacy \ - multiplyA24Leg(0(DI),0(SI)) -#define mulA24Bmi2Adx \ - multiplyA24Adx(0(DI),0(SI)) - -// func mulA24Amd64(z, x *fp255.Elt) -TEXT ·mulA24Amd64(SB),NOSPLIT,$0-16 - MOVQ z+0(FP), DI - MOVQ x+8(FP), SI - CHECK_BMI2ADX(LMA24, mulA24Legacy, mulA24Bmi2Adx) - - -// func ladderStepAmd64(w *[5]fp255.Elt, b uint) -// ladderStepAmd64 calculates a point addition and doubling as follows: -// (x2,z2) = 2*(x2,z2) and (x3,z3) = (x2,z2)+(x3,z3) using as a difference (x1,-). -// work = (x1,x2,z2,x3,z3) are five fp255.Elt of 32 bytes. -// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and -// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. -TEXT ·ladderStepAmd64(SB),NOSPLIT,$192-16 - // Parameters - #define regWork DI - #define regMove SI - #define x1 0*Size(regWork) - #define x2 1*Size(regWork) - #define z2 2*Size(regWork) - #define x3 3*Size(regWork) - #define z3 4*Size(regWork) - // Local variables - #define t0 0*Size(SP) - #define t1 1*Size(SP) - #define b0 2*Size(SP) - #define b1 4*Size(SP) - MOVQ w+0(FP), regWork - MOVQ b+8(FP), regMove - CHECK_BMI2ADX(LLADSTEP, ladderStepLeg, ladderStepBmi2Adx) - #undef regWork - #undef regMove - #undef x1 - #undef x2 - #undef z2 - #undef x3 - #undef z3 - #undef t0 - #undef t1 - #undef b0 - #undef b1 - -// func diffAddAmd64(w *[5]fp255.Elt, b uint) -// diffAddAmd64 calculates a differential point addition using a precomputed point. -// (x1,z1) = (x1,z1)+(mu) using a difference point (x2,z2) -// w = (mu,x1,z1,x2,z2) are five fp.Elt, and -// stack = (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. -TEXT ·diffAddAmd64(SB),NOSPLIT,$128-16 - // Parameters - #define regWork DI - #define regSwap SI - #define ui 0*Size(regWork) - #define x1 1*Size(regWork) - #define z1 2*Size(regWork) - #define x2 3*Size(regWork) - #define z2 4*Size(regWork) - // Local variables - #define b0 0*Size(SP) - #define b1 2*Size(SP) - MOVQ w+0(FP), regWork - MOVQ b+8(FP), regSwap - cswap(x1,x2,regSwap) - cswap(z1,z2,regSwap) - CHECK_BMI2ADX(LDIFADD, difAddLeg, difAddBmi2Adx) - #undef regWork - #undef regSwap - #undef ui - #undef x1 - #undef z1 - #undef x2 - #undef z2 - #undef b0 - #undef b1 - -// func doubleAmd64(x, z *fp255.Elt) -// doubleAmd64 calculates a point doubling (x1,z1) = 2*(x1,z1). -// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and -// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. -TEXT ·doubleAmd64(SB),NOSPLIT,$192-16 - // Parameters - #define x1 0(DI) - #define z1 0(SI) - // Local variables - #define t0 0*Size(SP) - #define t1 1*Size(SP) - #define b0 2*Size(SP) - #define b1 4*Size(SP) - MOVQ x+0(FP), DI - MOVQ z+8(FP), SI - CHECK_BMI2ADX(LDOUB,doubleLeg,doubleBmi2Adx) - #undef x1 - #undef z1 - #undef t0 - #undef t1 - #undef b0 - #undef b1 diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go b/vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go deleted file mode 100644 index dae67ea3..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go +++ /dev/null @@ -1,85 +0,0 @@ -package x25519 - -import ( - "encoding/binary" - "math/bits" - - fp "github.com/cloudflare/circl/math/fp25519" -) - -func doubleGeneric(x, z *fp.Elt) { - t0, t1 := &fp.Elt{}, &fp.Elt{} - fp.AddSub(x, z) - fp.Sqr(x, x) - fp.Sqr(z, z) - fp.Sub(t0, x, z) - mulA24Generic(t1, t0) - fp.Add(t1, t1, z) - fp.Mul(x, x, z) - fp.Mul(z, t0, t1) -} - -func diffAddGeneric(w *[5]fp.Elt, b uint) { - mu, x1, z1, x2, z2 := &w[0], &w[1], &w[2], &w[3], &w[4] - fp.Cswap(x1, x2, b) - fp.Cswap(z1, z2, b) - fp.AddSub(x1, z1) - fp.Mul(z1, z1, mu) - fp.AddSub(x1, z1) - fp.Sqr(x1, x1) - fp.Sqr(z1, z1) - fp.Mul(x1, x1, z2) - fp.Mul(z1, z1, x2) -} - -func ladderStepGeneric(w *[5]fp.Elt, b uint) { - x1, x2, z2, x3, z3 := &w[0], &w[1], &w[2], &w[3], &w[4] - t0 := &fp.Elt{} - t1 := &fp.Elt{} - fp.AddSub(x2, z2) - fp.AddSub(x3, z3) - fp.Mul(t0, x2, z3) - fp.Mul(t1, x3, z2) - fp.AddSub(t0, t1) - fp.Cmov(x2, x3, b) - fp.Cmov(z2, z3, b) - fp.Sqr(x3, t0) - fp.Sqr(z3, t1) - fp.Mul(z3, x1, z3) - fp.Sqr(x2, x2) - fp.Sqr(z2, z2) - fp.Sub(t0, x2, z2) - mulA24Generic(t1, t0) - fp.Add(t1, t1, z2) - fp.Mul(x2, x2, z2) - fp.Mul(z2, t0, t1) -} - -func mulA24Generic(z, x *fp.Elt) { - const A24 = 121666 - const n = 8 - var xx [4]uint64 - for i := range xx { - xx[i] = binary.LittleEndian.Uint64(x[i*n : (i+1)*n]) - } - - h0, l0 := bits.Mul64(xx[0], A24) - h1, l1 := bits.Mul64(xx[1], A24) - h2, l2 := bits.Mul64(xx[2], A24) - h3, l3 := bits.Mul64(xx[3], A24) - - var c3 uint64 - l1, c0 := bits.Add64(h0, l1, 0) - l2, c1 := bits.Add64(h1, l2, c0) - l3, c2 := bits.Add64(h2, l3, c1) - l4, _ := bits.Add64(h3, 0, c2) - _, l4 = bits.Mul64(l4, 38) - l0, c0 = bits.Add64(l0, l4, 0) - xx[1], c1 = bits.Add64(l1, 0, c0) - xx[2], c2 = bits.Add64(l2, 0, c1) - xx[3], c3 = bits.Add64(l3, 0, c2) - xx[0], _ = bits.Add64(l0, (-c3)&38, 0) - for i := range xx { - binary.LittleEndian.PutUint64(z[i*n:(i+1)*n], xx[i]) - } -} diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go b/vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go deleted file mode 100644 index 07fab97d..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !amd64 || purego -// +build !amd64 purego - -package x25519 - -import fp "github.com/cloudflare/circl/math/fp25519" - -func double(x, z *fp.Elt) { doubleGeneric(x, z) } -func diffAdd(w *[5]fp.Elt, b uint) { diffAddGeneric(w, b) } -func ladderStep(w *[5]fp.Elt, b uint) { ladderStepGeneric(w, b) } -func mulA24(z, x *fp.Elt) { mulA24Generic(z, x) } diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/doc.go b/vendor/github.com/cloudflare/circl/dh/x25519/doc.go deleted file mode 100644 index 3ce102d1..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Package x25519 provides Diffie-Hellman functions as specified in RFC-7748. - -Validation of public keys. - -The Diffie-Hellman function, as described in RFC-7748 [1], works for any -public key. However, if a different protocol requires contributory -behaviour [2,3], then the public keys must be validated against low-order -points [3,4]. To do that, the Shared function performs this validation -internally and returns false when the public key is invalid (i.e., it -is a low-order point). - -References: - - [1] RFC7748 by Langley, Hamburg, Turner (https://rfc-editor.org/rfc/rfc7748.txt) - - [2] Curve25519 by Bernstein (https://cr.yp.to/ecdh.html) - - [3] Bernstein (https://cr.yp.to/ecdh.html#validate) - - [4] Cremers&Jackson (https://eprint.iacr.org/2019/526) -*/ -package x25519 diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/key.go b/vendor/github.com/cloudflare/circl/dh/x25519/key.go deleted file mode 100644 index c76f72ac..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/key.go +++ /dev/null @@ -1,47 +0,0 @@ -package x25519 - -import ( - "crypto/subtle" - - fp "github.com/cloudflare/circl/math/fp25519" -) - -// Size is the length in bytes of a X25519 key. -const Size = 32 - -// Key represents a X25519 key. -type Key [Size]byte - -func (k *Key) clamp(in *Key) *Key { - *k = *in - k[0] &= 248 - k[31] = (k[31] & 127) | 64 - return k -} - -// isValidPubKey verifies if the public key is not a low-order point. -func (k *Key) isValidPubKey() bool { - fp.Modp((*fp.Elt)(k)) - var isLowOrder int - for _, P := range lowOrderPoints { - isLowOrder |= subtle.ConstantTimeCompare(P[:], k[:]) - } - return isLowOrder == 0 -} - -// KeyGen obtains a public key given a secret key. -func KeyGen(public, secret *Key) { - ladderJoye(public.clamp(secret)) -} - -// Shared calculates Alice's shared key from Alice's secret key and Bob's -// public key returning true on success. A failure case happens when the public -// key is a low-order point, thus the shared key is all-zeros and the function -// returns false. -func Shared(shared, secret, public *Key) bool { - validPk := *public - validPk[31] &= (1 << (255 % 8)) - 1 - ok := validPk.isValidPubKey() - ladderMontgomery(shared.clamp(secret), &validPk) - return ok -} diff --git a/vendor/github.com/cloudflare/circl/dh/x25519/table.go b/vendor/github.com/cloudflare/circl/dh/x25519/table.go deleted file mode 100644 index 28c8c4ac..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x25519/table.go +++ /dev/null @@ -1,268 +0,0 @@ -package x25519 - -import "github.com/cloudflare/circl/math/fp25519" - -// tableGenerator contains the set of points: -// -// t[i] = (xi+1)/(xi-1), -// -// where (xi,yi) = 2^iG and G is the generator point -// Size = (256)*(256/8) = 8192 bytes. -var tableGenerator = [256 * fp25519.Size]byte{ - /* (2^ 0)P */ 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, - /* (2^ 1)P */ 0x96, 0xfe, 0xaa, 0x16, 0xf4, 0x20, 0x82, 0x6b, 0x34, 0x6a, 0x56, 0x4f, 0x2b, 0xeb, 0xeb, 0x82, 0x0f, 0x95, 0xa5, 0x75, 0xb0, 0xa5, 0xa9, 0xd5, 0xf4, 0x88, 0x24, 0x4b, 0xcf, 0xb2, 0x42, 0x51, - /* (2^ 2)P */ 0x0c, 0x68, 0x69, 0x00, 0x75, 0xbc, 0xae, 0x6a, 0x41, 0x9c, 0xf9, 0xa0, 0x20, 0x78, 0xcf, 0x89, 0xf4, 0xd0, 0x56, 0x3b, 0x18, 0xd9, 0x58, 0x2a, 0xa4, 0x11, 0x60, 0xe3, 0x80, 0xca, 0x5a, 0x4b, - /* (2^ 3)P */ 0x5d, 0x74, 0x29, 0x8c, 0x34, 0x32, 0x91, 0x32, 0xd7, 0x2f, 0x64, 0xe1, 0x16, 0xe6, 0xa2, 0xf4, 0x34, 0xbc, 0x67, 0xff, 0x03, 0xbb, 0x45, 0x1e, 0x4a, 0x9b, 0x2a, 0xf4, 0xd0, 0x12, 0x69, 0x30, - /* (2^ 4)P */ 0x54, 0x71, 0xaf, 0xe6, 0x07, 0x65, 0x88, 0xff, 0x2f, 0xc8, 0xee, 0xdf, 0x13, 0x0e, 0xf5, 0x04, 0xce, 0xb5, 0xba, 0x2a, 0xe8, 0x2f, 0x51, 0xaa, 0x22, 0xf2, 0xd5, 0x68, 0x1a, 0x25, 0x4e, 0x17, - /* (2^ 5)P */ 0x98, 0x88, 0x02, 0x82, 0x0d, 0x70, 0x96, 0xcf, 0xc5, 0x02, 0x2c, 0x0a, 0x37, 0xe3, 0x43, 0x17, 0xaa, 0x6e, 0xe8, 0xb4, 0x98, 0xec, 0x9e, 0x37, 0x2e, 0x48, 0xe0, 0x51, 0x8a, 0x88, 0x59, 0x0c, - /* (2^ 6)P */ 0x89, 0xd1, 0xb5, 0x99, 0xd6, 0xf1, 0xcb, 0xfb, 0x84, 0xdc, 0x9f, 0x8e, 0xd5, 0xf0, 0xae, 0xac, 0x14, 0x76, 0x1f, 0x23, 0x06, 0x0d, 0xc2, 0xc1, 0x72, 0xf9, 0x74, 0xa2, 0x8d, 0x21, 0x38, 0x29, - /* (2^ 7)P */ 0x18, 0x7f, 0x1d, 0xff, 0xbe, 0x49, 0xaf, 0xf6, 0xc2, 0xc9, 0x7a, 0x38, 0x22, 0x1c, 0x54, 0xcc, 0x6b, 0xc5, 0x15, 0x40, 0xef, 0xc9, 0xfc, 0x96, 0xa9, 0x13, 0x09, 0x69, 0x7c, 0x62, 0xc1, 0x69, - /* (2^ 8)P */ 0x0e, 0xdb, 0x33, 0x47, 0x2f, 0xfd, 0x86, 0x7a, 0xe9, 0x7d, 0x08, 0x9e, 0xf2, 0xc4, 0xb8, 0xfd, 0x29, 0xa2, 0xa2, 0x8e, 0x1a, 0x4b, 0x5e, 0x09, 0x79, 0x7a, 0xb3, 0x29, 0xc8, 0xa7, 0xd7, 0x1a, - /* (2^ 9)P */ 0xc0, 0xa0, 0x7e, 0xd1, 0xca, 0x89, 0x2d, 0x34, 0x51, 0x20, 0xed, 0xcc, 0xa6, 0xdd, 0xbe, 0x67, 0x74, 0x2f, 0xb4, 0x2b, 0xbf, 0x31, 0xca, 0x19, 0xbb, 0xac, 0x80, 0x49, 0xc8, 0xb4, 0xf7, 0x3d, - /* (2^ 10)P */ 0x83, 0xd8, 0x0a, 0xc8, 0x4d, 0x44, 0xc6, 0xa8, 0x85, 0xab, 0xe3, 0x66, 0x03, 0x44, 0x1e, 0xb9, 0xd8, 0xf6, 0x64, 0x01, 0xa0, 0xcd, 0x15, 0xc2, 0x68, 0xe6, 0x47, 0xf2, 0x6e, 0x7c, 0x86, 0x3d, - /* (2^ 11)P */ 0x8c, 0x65, 0x3e, 0xcc, 0x2b, 0x58, 0xdd, 0xc7, 0x28, 0x55, 0x0e, 0xee, 0x48, 0x47, 0x2c, 0xfd, 0x71, 0x4f, 0x9f, 0xcc, 0x95, 0x9b, 0xfd, 0xa0, 0xdf, 0x5d, 0x67, 0xb0, 0x71, 0xd8, 0x29, 0x75, - /* (2^ 12)P */ 0x78, 0xbd, 0x3c, 0x2d, 0xb4, 0x68, 0xf5, 0xb8, 0x82, 0xda, 0xf3, 0x91, 0x1b, 0x01, 0x33, 0x12, 0x62, 0x3b, 0x7c, 0x4a, 0xcd, 0x6c, 0xce, 0x2d, 0x03, 0x86, 0x49, 0x9e, 0x8e, 0xfc, 0xe7, 0x75, - /* (2^ 13)P */ 0xec, 0xb6, 0xd0, 0xfc, 0xf1, 0x13, 0x4f, 0x2f, 0x45, 0x7a, 0xff, 0x29, 0x1f, 0xca, 0xa8, 0xf1, 0x9b, 0xe2, 0x81, 0x29, 0xa7, 0xc1, 0x49, 0xc2, 0x6a, 0xb5, 0x83, 0x8c, 0xbb, 0x0d, 0xbe, 0x6e, - /* (2^ 14)P */ 0x22, 0xb2, 0x0b, 0x17, 0x8d, 0xfa, 0x14, 0x71, 0x5f, 0x93, 0x93, 0xbf, 0xd5, 0xdc, 0xa2, 0x65, 0x9a, 0x97, 0x9c, 0xb5, 0x68, 0x1f, 0xc4, 0xbd, 0x89, 0x92, 0xce, 0xa2, 0x79, 0xef, 0x0e, 0x2f, - /* (2^ 15)P */ 0xce, 0x37, 0x3c, 0x08, 0x0c, 0xbf, 0xec, 0x42, 0x22, 0x63, 0x49, 0xec, 0x09, 0xbc, 0x30, 0x29, 0x0d, 0xac, 0xfe, 0x9c, 0xc1, 0xb0, 0x94, 0xf2, 0x80, 0xbb, 0xfa, 0xed, 0x4b, 0xaa, 0x80, 0x37, - /* (2^ 16)P */ 0x29, 0xd9, 0xea, 0x7c, 0x3e, 0x7d, 0xc1, 0x56, 0xc5, 0x22, 0x57, 0x2e, 0xeb, 0x4b, 0xcb, 0xe7, 0x5a, 0xe1, 0xbf, 0x2d, 0x73, 0x31, 0xe9, 0x0c, 0xf8, 0x52, 0x10, 0x62, 0xc7, 0x83, 0xb8, 0x41, - /* (2^ 17)P */ 0x50, 0x53, 0xd2, 0xc3, 0xa0, 0x5c, 0xf7, 0xdb, 0x51, 0xe3, 0xb1, 0x6e, 0x08, 0xbe, 0x36, 0x29, 0x12, 0xb2, 0xa9, 0xb4, 0x3c, 0xe0, 0x36, 0xc9, 0xaa, 0x25, 0x22, 0x32, 0x82, 0xbf, 0x45, 0x1d, - /* (2^ 18)P */ 0xc5, 0x4c, 0x02, 0x6a, 0x03, 0xb1, 0x1a, 0xe8, 0x72, 0x9a, 0x4c, 0x30, 0x1c, 0x20, 0x12, 0xe2, 0xfc, 0xb1, 0x32, 0x68, 0xba, 0x3f, 0xd7, 0xc5, 0x81, 0x95, 0x83, 0x4d, 0x5a, 0xdb, 0xff, 0x20, - /* (2^ 19)P */ 0xad, 0x0f, 0x5d, 0xbe, 0x67, 0xd3, 0x83, 0xa2, 0x75, 0x44, 0x16, 0x8b, 0xca, 0x25, 0x2b, 0x6c, 0x2e, 0xf2, 0xaa, 0x7c, 0x46, 0x35, 0x49, 0x9d, 0x49, 0xff, 0x85, 0xee, 0x8e, 0x40, 0x66, 0x51, - /* (2^ 20)P */ 0x61, 0xe3, 0xb4, 0xfa, 0xa2, 0xba, 0x67, 0x3c, 0xef, 0x5c, 0xf3, 0x7e, 0xc6, 0x33, 0xe4, 0xb3, 0x1c, 0x9b, 0x15, 0x41, 0x92, 0x72, 0x59, 0x52, 0x33, 0xab, 0xb0, 0xd5, 0x92, 0x18, 0x62, 0x6a, - /* (2^ 21)P */ 0xcb, 0xcd, 0x55, 0x75, 0x38, 0x4a, 0xb7, 0x20, 0x3f, 0x92, 0x08, 0x12, 0x0e, 0xa1, 0x2a, 0x53, 0xd1, 0x1d, 0x28, 0x62, 0x77, 0x7b, 0xa1, 0xea, 0xbf, 0x44, 0x5c, 0xf0, 0x43, 0x34, 0xab, 0x61, - /* (2^ 22)P */ 0xf8, 0xde, 0x24, 0x23, 0x42, 0x6c, 0x7a, 0x25, 0x7f, 0xcf, 0xe3, 0x17, 0x10, 0x6c, 0x1c, 0x13, 0x57, 0xa2, 0x30, 0xf6, 0x39, 0x87, 0x75, 0x23, 0x80, 0x85, 0xa7, 0x01, 0x7a, 0x40, 0x5a, 0x29, - /* (2^ 23)P */ 0xd9, 0xa8, 0x5d, 0x6d, 0x24, 0x43, 0xc4, 0xf8, 0x5d, 0xfa, 0x52, 0x0c, 0x45, 0x75, 0xd7, 0x19, 0x3d, 0xf8, 0x1b, 0x73, 0x92, 0xfc, 0xfc, 0x2a, 0x00, 0x47, 0x2b, 0x1b, 0xe8, 0xc8, 0x10, 0x7d, - /* (2^ 24)P */ 0x0b, 0xa2, 0xba, 0x70, 0x1f, 0x27, 0xe0, 0xc8, 0x57, 0x39, 0xa6, 0x7c, 0x86, 0x48, 0x37, 0x99, 0xbb, 0xd4, 0x7e, 0xcb, 0xb3, 0xef, 0x12, 0x54, 0x75, 0x29, 0xe6, 0x73, 0x61, 0xd3, 0x96, 0x31, - /* (2^ 25)P */ 0xfc, 0xdf, 0xc7, 0x41, 0xd1, 0xca, 0x5b, 0xde, 0x48, 0xc8, 0x95, 0xb3, 0xd2, 0x8c, 0xcc, 0x47, 0xcb, 0xf3, 0x1a, 0xe1, 0x42, 0xd9, 0x4c, 0xa3, 0xc2, 0xce, 0x4e, 0xd0, 0xf2, 0xdb, 0x56, 0x02, - /* (2^ 26)P */ 0x7f, 0x66, 0x0e, 0x4b, 0xe9, 0xb7, 0x5a, 0x87, 0x10, 0x0d, 0x85, 0xc0, 0x83, 0xdd, 0xd4, 0xca, 0x9f, 0xc7, 0x72, 0x4e, 0x8f, 0x2e, 0xf1, 0x47, 0x9b, 0xb1, 0x85, 0x8c, 0xbb, 0x87, 0x1a, 0x5f, - /* (2^ 27)P */ 0xb8, 0x51, 0x7f, 0x43, 0xb6, 0xd0, 0xe9, 0x7a, 0x65, 0x90, 0x87, 0x18, 0x55, 0xce, 0xc7, 0x12, 0xee, 0x7a, 0xf7, 0x5c, 0xfe, 0x09, 0xde, 0x2a, 0x27, 0x56, 0x2c, 0x7d, 0x2f, 0x5a, 0xa0, 0x23, - /* (2^ 28)P */ 0x9a, 0x16, 0x7c, 0xf1, 0x28, 0xe1, 0x08, 0x59, 0x2d, 0x85, 0xd0, 0x8a, 0xdd, 0x98, 0x74, 0xf7, 0x64, 0x2f, 0x10, 0xab, 0xce, 0xc4, 0xb4, 0x74, 0x45, 0x98, 0x13, 0x10, 0xdd, 0xba, 0x3a, 0x18, - /* (2^ 29)P */ 0xac, 0xaa, 0x92, 0xaa, 0x8d, 0xba, 0x65, 0xb1, 0x05, 0x67, 0x38, 0x99, 0x95, 0xef, 0xc5, 0xd5, 0xd1, 0x40, 0xfc, 0xf8, 0x0c, 0x8f, 0x2f, 0xbe, 0x14, 0x45, 0x20, 0xee, 0x35, 0xe6, 0x01, 0x27, - /* (2^ 30)P */ 0x14, 0x65, 0x15, 0x20, 0x00, 0xa8, 0x9f, 0x62, 0xce, 0xc1, 0xa8, 0x64, 0x87, 0x86, 0x23, 0xf2, 0x0e, 0x06, 0x3f, 0x0b, 0xff, 0x4f, 0x89, 0x5b, 0xfa, 0xa3, 0x08, 0xf7, 0x4c, 0x94, 0xd9, 0x60, - /* (2^ 31)P */ 0x1f, 0x20, 0x7a, 0x1c, 0x1a, 0x00, 0xea, 0xae, 0x63, 0xce, 0xe2, 0x3e, 0x63, 0x6a, 0xf1, 0xeb, 0xe1, 0x07, 0x7a, 0x4c, 0x59, 0x09, 0x77, 0x6f, 0xcb, 0x08, 0x02, 0x0d, 0x15, 0x58, 0xb9, 0x79, - /* (2^ 32)P */ 0xe7, 0x10, 0xd4, 0x01, 0x53, 0x5e, 0xb5, 0x24, 0x4d, 0xc8, 0xfd, 0xf3, 0xdf, 0x4e, 0xa3, 0xe3, 0xd8, 0x32, 0x40, 0x90, 0xe4, 0x68, 0x87, 0xd8, 0xec, 0xae, 0x3a, 0x7b, 0x42, 0x84, 0x13, 0x13, - /* (2^ 33)P */ 0x14, 0x4f, 0x23, 0x86, 0x12, 0xe5, 0x05, 0x84, 0x29, 0xc5, 0xb4, 0xad, 0x39, 0x47, 0xdc, 0x14, 0xfd, 0x4f, 0x63, 0x50, 0xb2, 0xb5, 0xa2, 0xb8, 0x93, 0xff, 0xa7, 0xd8, 0x4a, 0xa9, 0xe2, 0x2f, - /* (2^ 34)P */ 0xdd, 0xfa, 0x43, 0xe8, 0xef, 0x57, 0x5c, 0xec, 0x18, 0x99, 0xbb, 0xf0, 0x40, 0xce, 0x43, 0x28, 0x05, 0x63, 0x3d, 0xcf, 0xd6, 0x61, 0xb5, 0xa4, 0x7e, 0x77, 0xfb, 0xe8, 0xbd, 0x29, 0x36, 0x74, - /* (2^ 35)P */ 0x8f, 0x73, 0xaf, 0xbb, 0x46, 0xdd, 0x3e, 0x34, 0x51, 0xa6, 0x01, 0xb1, 0x28, 0x18, 0x98, 0xed, 0x7a, 0x79, 0x2c, 0x88, 0x0b, 0x76, 0x01, 0xa4, 0x30, 0x87, 0xc8, 0x8d, 0xe2, 0x23, 0xc2, 0x1f, - /* (2^ 36)P */ 0x0e, 0xba, 0x0f, 0xfc, 0x91, 0x4e, 0x60, 0x48, 0xa4, 0x6f, 0x2c, 0x05, 0x8f, 0xf7, 0x37, 0xb6, 0x9c, 0x23, 0xe9, 0x09, 0x3d, 0xac, 0xcc, 0x91, 0x7c, 0x68, 0x7a, 0x43, 0xd4, 0xee, 0xf7, 0x23, - /* (2^ 37)P */ 0x00, 0xd8, 0x9b, 0x8d, 0x11, 0xb1, 0x73, 0x51, 0xa7, 0xd4, 0x89, 0x31, 0xb6, 0x41, 0xd6, 0x29, 0x86, 0xc5, 0xbb, 0x88, 0x79, 0x17, 0xbf, 0xfd, 0xf5, 0x1d, 0xd8, 0xca, 0x4f, 0x89, 0x59, 0x29, - /* (2^ 38)P */ 0x99, 0xc8, 0xbb, 0xb4, 0xf3, 0x8e, 0xbc, 0xae, 0xb9, 0x92, 0x69, 0xb2, 0x5a, 0x99, 0x48, 0x41, 0xfb, 0x2c, 0xf9, 0x34, 0x01, 0x0b, 0xe2, 0x24, 0xe8, 0xde, 0x05, 0x4a, 0x89, 0x58, 0xd1, 0x40, - /* (2^ 39)P */ 0xf6, 0x76, 0xaf, 0x85, 0x11, 0x0b, 0xb0, 0x46, 0x79, 0x7a, 0x18, 0x73, 0x78, 0xc7, 0xba, 0x26, 0x5f, 0xff, 0x8f, 0xab, 0x95, 0xbf, 0xc0, 0x3d, 0xd7, 0x24, 0x55, 0x94, 0xd8, 0x8b, 0x60, 0x2a, - /* (2^ 40)P */ 0x02, 0x63, 0x44, 0xbd, 0x88, 0x95, 0x44, 0x26, 0x9c, 0x43, 0x88, 0x03, 0x1c, 0xc2, 0x4b, 0x7c, 0xb2, 0x11, 0xbd, 0x83, 0xf3, 0xa4, 0x98, 0x8e, 0xb9, 0x76, 0xd8, 0xc9, 0x7b, 0x8d, 0x21, 0x26, - /* (2^ 41)P */ 0x8a, 0x17, 0x7c, 0x99, 0x42, 0x15, 0x08, 0xe3, 0x6f, 0x60, 0xb6, 0x6f, 0xa8, 0x29, 0x2d, 0x3c, 0x74, 0x93, 0x27, 0xfa, 0x36, 0x77, 0x21, 0x5c, 0xfa, 0xb1, 0xfe, 0x4a, 0x73, 0x05, 0xde, 0x7d, - /* (2^ 42)P */ 0xab, 0x2b, 0xd4, 0x06, 0x39, 0x0e, 0xf1, 0x3b, 0x9c, 0x64, 0x80, 0x19, 0x3e, 0x80, 0xf7, 0xe4, 0x7a, 0xbf, 0x95, 0x95, 0xf8, 0x3b, 0x05, 0xe6, 0x30, 0x55, 0x24, 0xda, 0x38, 0xaf, 0x4f, 0x39, - /* (2^ 43)P */ 0xf4, 0x28, 0x69, 0x89, 0x58, 0xfb, 0x8e, 0x7a, 0x3c, 0x11, 0x6a, 0xcc, 0xe9, 0x78, 0xc7, 0xfb, 0x6f, 0x59, 0xaf, 0x30, 0xe3, 0x0c, 0x67, 0x72, 0xf7, 0x6c, 0x3d, 0x1d, 0xa8, 0x22, 0xf2, 0x48, - /* (2^ 44)P */ 0xa7, 0xca, 0x72, 0x0d, 0x41, 0xce, 0x1f, 0xf0, 0x95, 0x55, 0x3b, 0x21, 0xc7, 0xec, 0x20, 0x5a, 0x83, 0x14, 0xfa, 0xc1, 0x65, 0x11, 0xc2, 0x7b, 0x41, 0xa7, 0xa8, 0x1d, 0xe3, 0x9a, 0xf8, 0x07, - /* (2^ 45)P */ 0xf9, 0x0f, 0x83, 0xc6, 0xb4, 0xc2, 0xd2, 0x05, 0x93, 0x62, 0x31, 0xc6, 0x0f, 0x33, 0x3e, 0xd4, 0x04, 0xa9, 0xd3, 0x96, 0x0a, 0x59, 0xa5, 0xa5, 0xb6, 0x33, 0x53, 0xa6, 0x91, 0xdb, 0x5e, 0x70, - /* (2^ 46)P */ 0xf7, 0xa5, 0xb9, 0x0b, 0x5e, 0xe1, 0x8e, 0x04, 0x5d, 0xaf, 0x0a, 0x9e, 0xca, 0xcf, 0x40, 0x32, 0x0b, 0xa4, 0xc4, 0xed, 0xce, 0x71, 0x4b, 0x8f, 0x6d, 0x4a, 0x54, 0xde, 0xa3, 0x0d, 0x1c, 0x62, - /* (2^ 47)P */ 0x91, 0x40, 0x8c, 0xa0, 0x36, 0x28, 0x87, 0x92, 0x45, 0x14, 0xc9, 0x10, 0xb0, 0x75, 0x83, 0xce, 0x94, 0x63, 0x27, 0x4f, 0x52, 0xeb, 0x72, 0x8a, 0x35, 0x36, 0xc8, 0x7e, 0xfa, 0xfc, 0x67, 0x26, - /* (2^ 48)P */ 0x2a, 0x75, 0xe8, 0x45, 0x33, 0x17, 0x4c, 0x7f, 0xa5, 0x79, 0x70, 0xee, 0xfe, 0x47, 0x1b, 0x06, 0x34, 0xff, 0x86, 0x9f, 0xfa, 0x9a, 0xdd, 0x25, 0x9c, 0xc8, 0x5d, 0x42, 0xf5, 0xce, 0x80, 0x37, - /* (2^ 49)P */ 0xe9, 0xb4, 0x3b, 0x51, 0x5a, 0x03, 0x46, 0x1a, 0xda, 0x5a, 0x57, 0xac, 0x79, 0xf3, 0x1e, 0x3e, 0x50, 0x4b, 0xa2, 0x5f, 0x1c, 0x5f, 0x8c, 0xc7, 0x22, 0x9f, 0xfd, 0x34, 0x76, 0x96, 0x1a, 0x32, - /* (2^ 50)P */ 0xfa, 0x27, 0x6e, 0x82, 0xb8, 0x07, 0x67, 0x94, 0xd0, 0x6f, 0x50, 0x4c, 0xd6, 0x84, 0xca, 0x3d, 0x36, 0x14, 0xe9, 0x75, 0x80, 0x21, 0x89, 0xc1, 0x84, 0x84, 0x3b, 0x9b, 0x16, 0x84, 0x92, 0x6d, - /* (2^ 51)P */ 0xdf, 0x2d, 0x3f, 0x38, 0x40, 0xe8, 0x67, 0x3a, 0x75, 0x9b, 0x4f, 0x0c, 0xa3, 0xc9, 0xee, 0x33, 0x47, 0xef, 0x83, 0xa7, 0x6f, 0xc8, 0xc7, 0x3e, 0xc4, 0xfb, 0xc9, 0xba, 0x9f, 0x44, 0xec, 0x26, - /* (2^ 52)P */ 0x7d, 0x9e, 0x9b, 0xa0, 0xcb, 0x38, 0x0f, 0x5c, 0x8c, 0x47, 0xa3, 0x62, 0xc7, 0x8c, 0x16, 0x81, 0x1c, 0x12, 0xfc, 0x06, 0xd3, 0xb0, 0x23, 0x3e, 0xdd, 0xdc, 0xef, 0xa5, 0xa0, 0x8a, 0x23, 0x5a, - /* (2^ 53)P */ 0xff, 0x43, 0xea, 0xc4, 0x21, 0x61, 0xa2, 0x1b, 0xb5, 0x32, 0x88, 0x7c, 0x7f, 0xc7, 0xf8, 0x36, 0x9a, 0xf9, 0xdc, 0x0a, 0x0b, 0xea, 0xfb, 0x88, 0xf9, 0xeb, 0x5b, 0xc2, 0x8e, 0x93, 0xa9, 0x5c, - /* (2^ 54)P */ 0xa0, 0xcd, 0xfc, 0x51, 0x5e, 0x6a, 0x43, 0xd5, 0x3b, 0x89, 0xcd, 0xc2, 0x97, 0x47, 0xbc, 0x1d, 0x08, 0x4a, 0x22, 0xd3, 0x65, 0x6a, 0x34, 0x19, 0x66, 0xf4, 0x9a, 0x9b, 0xe4, 0x34, 0x50, 0x0f, - /* (2^ 55)P */ 0x6e, 0xb9, 0xe0, 0xa1, 0x67, 0x39, 0x3c, 0xf2, 0x88, 0x4d, 0x7a, 0x86, 0xfa, 0x08, 0x8b, 0xe5, 0x79, 0x16, 0x34, 0xa7, 0xc6, 0xab, 0x2f, 0xfb, 0x46, 0x69, 0x02, 0xb6, 0x1e, 0x38, 0x75, 0x2a, - /* (2^ 56)P */ 0xac, 0x20, 0x94, 0xc1, 0xe4, 0x3b, 0x0a, 0xc8, 0xdc, 0xb6, 0xf2, 0x81, 0xc6, 0xf6, 0xb1, 0x66, 0x88, 0x33, 0xe9, 0x61, 0x67, 0x03, 0xf7, 0x7c, 0xc4, 0xa4, 0x60, 0xa6, 0xd8, 0xbb, 0xab, 0x25, - /* (2^ 57)P */ 0x98, 0x51, 0xfd, 0x14, 0xba, 0x12, 0xea, 0x91, 0xa9, 0xff, 0x3c, 0x4a, 0xfc, 0x50, 0x49, 0x68, 0x28, 0xad, 0xf5, 0x30, 0x21, 0x84, 0x26, 0xf8, 0x41, 0xa4, 0x01, 0x53, 0xf7, 0x88, 0xa9, 0x3e, - /* (2^ 58)P */ 0x6f, 0x8c, 0x5f, 0x69, 0x9a, 0x10, 0x78, 0xc9, 0xf3, 0xc3, 0x30, 0x05, 0x4a, 0xeb, 0x46, 0x17, 0x95, 0x99, 0x45, 0xb4, 0x77, 0x6d, 0x4d, 0x44, 0xc7, 0x5c, 0x4e, 0x05, 0x8c, 0x2b, 0x95, 0x75, - /* (2^ 59)P */ 0xaa, 0xd6, 0xf4, 0x15, 0x79, 0x3f, 0x70, 0xa3, 0xd8, 0x47, 0x26, 0x2f, 0x20, 0x46, 0xc3, 0x66, 0x4b, 0x64, 0x1d, 0x81, 0xdf, 0x69, 0x14, 0xd0, 0x1f, 0xd7, 0xa5, 0x81, 0x7d, 0xa4, 0xfe, 0x77, - /* (2^ 60)P */ 0x81, 0xa3, 0x7c, 0xf5, 0x9e, 0x52, 0xe9, 0xc5, 0x1a, 0x88, 0x2f, 0xce, 0xb9, 0xb4, 0xee, 0x6e, 0xd6, 0x9b, 0x00, 0xe8, 0x28, 0x1a, 0xe9, 0xb6, 0xec, 0x3f, 0xfc, 0x9a, 0x3e, 0xbe, 0x80, 0x4b, - /* (2^ 61)P */ 0xc5, 0xd2, 0xae, 0x26, 0xc5, 0x73, 0x37, 0x7e, 0x9d, 0xa4, 0xc9, 0x53, 0xb4, 0xfc, 0x4a, 0x1b, 0x4d, 0xb2, 0xff, 0xba, 0xd7, 0xbd, 0x20, 0xa9, 0x0e, 0x40, 0x2d, 0x12, 0x9f, 0x69, 0x54, 0x7c, - /* (2^ 62)P */ 0xc8, 0x4b, 0xa9, 0x4f, 0xe1, 0xc8, 0x46, 0xef, 0x5e, 0xed, 0x52, 0x29, 0xce, 0x74, 0xb0, 0xe0, 0xd5, 0x85, 0xd8, 0xdb, 0xe1, 0x50, 0xa4, 0xbe, 0x2c, 0x71, 0x0f, 0x32, 0x49, 0x86, 0xb6, 0x61, - /* (2^ 63)P */ 0xd1, 0xbd, 0xcc, 0x09, 0x73, 0x5f, 0x48, 0x8a, 0x2d, 0x1a, 0x4d, 0x7d, 0x0d, 0x32, 0x06, 0xbd, 0xf4, 0xbe, 0x2d, 0x32, 0x73, 0x29, 0x23, 0x25, 0x70, 0xf7, 0x17, 0x8c, 0x75, 0xc4, 0x5d, 0x44, - /* (2^ 64)P */ 0x3c, 0x93, 0xc8, 0x7c, 0x17, 0x34, 0x04, 0xdb, 0x9f, 0x05, 0xea, 0x75, 0x21, 0xe8, 0x6f, 0xed, 0x34, 0xdb, 0x53, 0xc0, 0xfd, 0xbe, 0xfe, 0x1e, 0x99, 0xaf, 0x5d, 0xc6, 0x67, 0xe8, 0xdb, 0x4a, - /* (2^ 65)P */ 0xdf, 0x09, 0x06, 0xa9, 0xa2, 0x71, 0xcd, 0x3a, 0x50, 0x40, 0xd0, 0x6d, 0x85, 0x91, 0xe9, 0xe5, 0x3c, 0xc2, 0x57, 0x81, 0x68, 0x9b, 0xc6, 0x1e, 0x4d, 0xfe, 0x5c, 0x88, 0xf6, 0x27, 0x74, 0x69, - /* (2^ 66)P */ 0x51, 0xa8, 0xe1, 0x65, 0x9b, 0x7b, 0xbe, 0xd7, 0xdd, 0x36, 0xc5, 0x22, 0xd5, 0x28, 0x3d, 0xa0, 0x45, 0xb6, 0xd2, 0x8f, 0x65, 0x9d, 0x39, 0x28, 0xe1, 0x41, 0x26, 0x7c, 0xe1, 0xb7, 0xe5, 0x49, - /* (2^ 67)P */ 0xa4, 0x57, 0x04, 0x70, 0x98, 0x3a, 0x8c, 0x6f, 0x78, 0x67, 0xbb, 0x5e, 0xa2, 0xf0, 0x78, 0x50, 0x0f, 0x96, 0x82, 0xc3, 0xcb, 0x3c, 0x3c, 0xd1, 0xb1, 0x84, 0xdf, 0xa7, 0x58, 0x32, 0x00, 0x2e, - /* (2^ 68)P */ 0x1c, 0x6a, 0x29, 0xe6, 0x9b, 0xf3, 0xd1, 0x8a, 0xb2, 0xbf, 0x5f, 0x2a, 0x65, 0xaa, 0xee, 0xc1, 0xcb, 0xf3, 0x26, 0xfd, 0x73, 0x06, 0xee, 0x33, 0xcc, 0x2c, 0x9d, 0xa6, 0x73, 0x61, 0x25, 0x59, - /* (2^ 69)P */ 0x41, 0xfc, 0x18, 0x4e, 0xaa, 0x07, 0xea, 0x41, 0x1e, 0xa5, 0x87, 0x7c, 0x52, 0x19, 0xfc, 0xd9, 0x6f, 0xca, 0x31, 0x58, 0x80, 0xcb, 0xaa, 0xbd, 0x4f, 0x69, 0x16, 0xc9, 0x2d, 0x65, 0x5b, 0x44, - /* (2^ 70)P */ 0x15, 0x23, 0x17, 0xf2, 0xa7, 0xa3, 0x92, 0xce, 0x64, 0x99, 0x1b, 0xe1, 0x2d, 0x28, 0xdc, 0x1e, 0x4a, 0x31, 0x4c, 0xe0, 0xaf, 0x3a, 0x82, 0xa1, 0x86, 0xf5, 0x7c, 0x43, 0x94, 0x2d, 0x0a, 0x79, - /* (2^ 71)P */ 0x09, 0xe0, 0xf6, 0x93, 0xfb, 0x47, 0xc4, 0x71, 0x76, 0x52, 0x84, 0x22, 0x67, 0xa5, 0x22, 0x89, 0x69, 0x51, 0x4f, 0x20, 0x3b, 0x90, 0x70, 0xbf, 0xfe, 0x19, 0xa3, 0x1b, 0x89, 0x89, 0x7a, 0x2f, - /* (2^ 72)P */ 0x0c, 0x14, 0xe2, 0x77, 0xb5, 0x8e, 0xa0, 0x02, 0xf4, 0xdc, 0x7b, 0x42, 0xd4, 0x4e, 0x9a, 0xed, 0xd1, 0x3c, 0x32, 0xe4, 0x44, 0xec, 0x53, 0x52, 0x5b, 0x35, 0xe9, 0x14, 0x3c, 0x36, 0x88, 0x3e, - /* (2^ 73)P */ 0x8c, 0x0b, 0x11, 0x77, 0x42, 0xc1, 0x66, 0xaa, 0x90, 0x33, 0xa2, 0x10, 0x16, 0x39, 0xe0, 0x1a, 0xa2, 0xc2, 0x3f, 0xc9, 0x12, 0xbd, 0x30, 0x20, 0xab, 0xc7, 0x55, 0x95, 0x57, 0x41, 0xe1, 0x3e, - /* (2^ 74)P */ 0x41, 0x7d, 0x6e, 0x6d, 0x3a, 0xde, 0x14, 0x92, 0xfe, 0x7e, 0xf1, 0x07, 0x86, 0xd8, 0xcd, 0x3c, 0x17, 0x12, 0xe1, 0xf8, 0x88, 0x12, 0x4f, 0x67, 0xd0, 0x93, 0x9f, 0x32, 0x0f, 0x25, 0x82, 0x56, - /* (2^ 75)P */ 0x6e, 0x39, 0x2e, 0x6d, 0x13, 0x0b, 0xf0, 0x6c, 0xbf, 0xde, 0x14, 0x10, 0x6f, 0xf8, 0x4c, 0x6e, 0x83, 0x4e, 0xcc, 0xbf, 0xb5, 0xb1, 0x30, 0x59, 0xb6, 0x16, 0xba, 0x8a, 0xb4, 0x69, 0x70, 0x04, - /* (2^ 76)P */ 0x93, 0x07, 0xb2, 0x69, 0xab, 0xe4, 0x4c, 0x0d, 0x9e, 0xfb, 0xd0, 0x97, 0x1a, 0xb9, 0x4d, 0xb2, 0x1d, 0xd0, 0x00, 0x4e, 0xf5, 0x50, 0xfa, 0xcd, 0xb5, 0xdd, 0x8b, 0x36, 0x85, 0x10, 0x1b, 0x22, - /* (2^ 77)P */ 0xd2, 0xd8, 0xe3, 0xb1, 0x68, 0x94, 0xe5, 0xe7, 0x93, 0x2f, 0x12, 0xbd, 0x63, 0x65, 0xc5, 0x53, 0x09, 0x3f, 0x66, 0xe0, 0x03, 0xa9, 0xe8, 0xee, 0x42, 0x3d, 0xbe, 0xcb, 0x62, 0xa6, 0xef, 0x61, - /* (2^ 78)P */ 0x2a, 0xab, 0x6e, 0xde, 0xdd, 0xdd, 0xf8, 0x2c, 0x31, 0xf2, 0x35, 0x14, 0xd5, 0x0a, 0xf8, 0x9b, 0x73, 0x49, 0xf0, 0xc9, 0xce, 0xda, 0xea, 0x5d, 0x27, 0x9b, 0xd2, 0x41, 0x5d, 0x5b, 0x27, 0x29, - /* (2^ 79)P */ 0x4f, 0xf1, 0xeb, 0x95, 0x08, 0x0f, 0xde, 0xcf, 0xa7, 0x05, 0x49, 0x05, 0x6b, 0xb9, 0xaa, 0xb9, 0xfd, 0x20, 0xc4, 0xa1, 0xd9, 0x0d, 0xe8, 0xca, 0xc7, 0xbb, 0x73, 0x16, 0x2f, 0xbf, 0x63, 0x0a, - /* (2^ 80)P */ 0x8c, 0xbc, 0x8f, 0x95, 0x11, 0x6e, 0x2f, 0x09, 0xad, 0x2f, 0x82, 0x04, 0xe8, 0x81, 0x2a, 0x67, 0x17, 0x25, 0xd5, 0x60, 0x15, 0x35, 0xc8, 0xca, 0xf8, 0x92, 0xf1, 0xc8, 0x22, 0x77, 0x3f, 0x6f, - /* (2^ 81)P */ 0xb7, 0x94, 0xe8, 0xc2, 0xcc, 0x90, 0xba, 0xf8, 0x0d, 0x9f, 0xff, 0x38, 0xa4, 0x57, 0x75, 0x2c, 0x59, 0x23, 0xe5, 0x5a, 0x85, 0x1d, 0x4d, 0x89, 0x69, 0x3d, 0x74, 0x7b, 0x15, 0x22, 0xe1, 0x68, - /* (2^ 82)P */ 0xf3, 0x19, 0xb9, 0xcf, 0x70, 0x55, 0x7e, 0xd8, 0xb9, 0x8d, 0x79, 0x95, 0xcd, 0xde, 0x2c, 0x3f, 0xce, 0xa2, 0xc0, 0x10, 0x47, 0x15, 0x21, 0x21, 0xb2, 0xc5, 0x6d, 0x24, 0x15, 0xa1, 0x66, 0x3c, - /* (2^ 83)P */ 0x72, 0xcb, 0x4e, 0x29, 0x62, 0xc5, 0xed, 0xcb, 0x16, 0x0b, 0x28, 0x6a, 0xc3, 0x43, 0x71, 0xba, 0x67, 0x8b, 0x07, 0xd4, 0xef, 0xc2, 0x10, 0x96, 0x1e, 0x4b, 0x6a, 0x94, 0x5d, 0x73, 0x44, 0x61, - /* (2^ 84)P */ 0x50, 0x33, 0x5b, 0xd7, 0x1e, 0x11, 0x6f, 0x53, 0x1b, 0xd8, 0x41, 0x20, 0x8c, 0xdb, 0x11, 0x02, 0x3c, 0x41, 0x10, 0x0e, 0x00, 0xb1, 0x3c, 0xf9, 0x76, 0x88, 0x9e, 0x03, 0x3c, 0xfd, 0x9d, 0x14, - /* (2^ 85)P */ 0x5b, 0x15, 0x63, 0x6b, 0xe4, 0xdd, 0x79, 0xd4, 0x76, 0x79, 0x83, 0x3c, 0xe9, 0x15, 0x6e, 0xb6, 0x38, 0xe0, 0x13, 0x1f, 0x3b, 0xe4, 0xfd, 0xda, 0x35, 0x0b, 0x4b, 0x2e, 0x1a, 0xda, 0xaf, 0x5f, - /* (2^ 86)P */ 0x81, 0x75, 0x19, 0x17, 0xdf, 0xbb, 0x00, 0x36, 0xc2, 0xd2, 0x3c, 0xbe, 0x0b, 0x05, 0x72, 0x39, 0x86, 0xbe, 0xd5, 0xbd, 0x6d, 0x90, 0x38, 0x59, 0x0f, 0x86, 0x9b, 0x3f, 0xe4, 0xe5, 0xfc, 0x34, - /* (2^ 87)P */ 0x02, 0x4d, 0xd1, 0x42, 0xcd, 0xa4, 0xa8, 0x75, 0x65, 0xdf, 0x41, 0x34, 0xc5, 0xab, 0x8d, 0x82, 0xd3, 0x31, 0xe1, 0xd2, 0xed, 0xab, 0xdc, 0x33, 0x5f, 0xd2, 0x14, 0xb8, 0x6f, 0xd7, 0xba, 0x3e, - /* (2^ 88)P */ 0x0f, 0xe1, 0x70, 0x6f, 0x56, 0x6f, 0x90, 0xd4, 0x5a, 0x0f, 0x69, 0x51, 0xaa, 0xf7, 0x12, 0x5d, 0xf2, 0xfc, 0xce, 0x76, 0x6e, 0xb1, 0xad, 0x45, 0x99, 0x29, 0x23, 0xad, 0xae, 0x68, 0xf7, 0x01, - /* (2^ 89)P */ 0xbd, 0xfe, 0x48, 0x62, 0x7b, 0xc7, 0x6c, 0x2b, 0xfd, 0xaf, 0x3a, 0xec, 0x28, 0x06, 0xd3, 0x3c, 0x6a, 0x48, 0xef, 0xd4, 0x80, 0x0b, 0x1c, 0xce, 0x23, 0x6c, 0xf6, 0xa6, 0x2e, 0xff, 0x3b, 0x4c, - /* (2^ 90)P */ 0x5f, 0xeb, 0xea, 0x4a, 0x09, 0xc4, 0x2e, 0x3f, 0xa7, 0x2c, 0x37, 0x6e, 0x28, 0x9b, 0xb1, 0x61, 0x1d, 0x70, 0x2a, 0xde, 0x66, 0xa9, 0xef, 0x5e, 0xef, 0xe3, 0x55, 0xde, 0x65, 0x05, 0xb2, 0x23, - /* (2^ 91)P */ 0x57, 0x85, 0xd5, 0x79, 0x52, 0xca, 0x01, 0xe3, 0x4f, 0x87, 0xc2, 0x27, 0xce, 0xd4, 0xb2, 0x07, 0x67, 0x1d, 0xcf, 0x9d, 0x8a, 0xcd, 0x32, 0xa5, 0x56, 0xff, 0x2b, 0x3f, 0xe2, 0xfe, 0x52, 0x2a, - /* (2^ 92)P */ 0x3d, 0x66, 0xd8, 0x7c, 0xb3, 0xef, 0x24, 0x86, 0x94, 0x75, 0xbd, 0xff, 0x20, 0xac, 0xc7, 0xbb, 0x45, 0x74, 0xd3, 0x82, 0x9c, 0x5e, 0xb8, 0x57, 0x66, 0xec, 0xa6, 0x86, 0xcb, 0x52, 0x30, 0x7b, - /* (2^ 93)P */ 0x1e, 0xe9, 0x25, 0x25, 0xad, 0xf0, 0x82, 0x34, 0xa0, 0xdc, 0x8e, 0xd2, 0x43, 0x80, 0xb6, 0x2c, 0x3a, 0x00, 0x1b, 0x2e, 0x05, 0x6d, 0x4f, 0xaf, 0x0a, 0x1b, 0x78, 0x29, 0x25, 0x8c, 0x5f, 0x18, - /* (2^ 94)P */ 0xd6, 0xe0, 0x0c, 0xd8, 0x5b, 0xde, 0x41, 0xaa, 0xd6, 0xe9, 0x53, 0x68, 0x41, 0xb2, 0x07, 0x94, 0x3a, 0x4c, 0x7f, 0x35, 0x6e, 0xc3, 0x3e, 0x56, 0xce, 0x7b, 0x29, 0x0e, 0xdd, 0xb8, 0xc4, 0x4c, - /* (2^ 95)P */ 0x0e, 0x73, 0xb8, 0xff, 0x52, 0x1a, 0xfc, 0xa2, 0x37, 0x8e, 0x05, 0x67, 0x6e, 0xf1, 0x11, 0x18, 0xe1, 0x4e, 0xdf, 0xcd, 0x66, 0xa3, 0xf9, 0x10, 0x99, 0xf0, 0xb9, 0xa0, 0xc4, 0xa0, 0xf4, 0x72, - /* (2^ 96)P */ 0xa7, 0x4e, 0x3f, 0x66, 0x6f, 0xc0, 0x16, 0x8c, 0xba, 0x0f, 0x97, 0x4e, 0xf7, 0x3a, 0x3b, 0x69, 0x45, 0xc3, 0x9e, 0xd6, 0xf1, 0xe7, 0x02, 0x21, 0x89, 0x80, 0x8a, 0x96, 0xbc, 0x3c, 0xa5, 0x0b, - /* (2^ 97)P */ 0x37, 0x55, 0xa1, 0xfe, 0xc7, 0x9d, 0x3d, 0xca, 0x93, 0x64, 0x53, 0x51, 0xbb, 0x24, 0x68, 0x4c, 0xb1, 0x06, 0x40, 0x84, 0x14, 0x63, 0x88, 0xb9, 0x60, 0xcc, 0x54, 0xb4, 0x2a, 0xa7, 0xd2, 0x40, - /* (2^ 98)P */ 0x75, 0x09, 0x57, 0x12, 0xb7, 0xa1, 0x36, 0x59, 0x57, 0xa6, 0xbd, 0xde, 0x48, 0xd6, 0xb9, 0x91, 0xea, 0x30, 0x43, 0xb6, 0x4b, 0x09, 0x44, 0x33, 0xd0, 0x51, 0xee, 0x12, 0x0d, 0xa1, 0x6b, 0x00, - /* (2^ 99)P */ 0x58, 0x5d, 0xde, 0xf5, 0x68, 0x84, 0x22, 0x19, 0xb0, 0x05, 0xcc, 0x38, 0x4c, 0x2f, 0xb1, 0x0e, 0x90, 0x19, 0x60, 0xd5, 0x9d, 0x9f, 0x03, 0xa1, 0x0b, 0x0e, 0xff, 0x4f, 0xce, 0xd4, 0x02, 0x45, - /* (2^100)P */ 0x89, 0xc1, 0x37, 0x68, 0x10, 0x54, 0x20, 0xeb, 0x3c, 0xb9, 0xd3, 0x6d, 0x4c, 0x54, 0xf6, 0xd0, 0x4f, 0xd7, 0x16, 0xc4, 0x64, 0x70, 0x72, 0x40, 0xf0, 0x2e, 0x50, 0x4b, 0x11, 0xc6, 0x15, 0x6e, - /* (2^101)P */ 0x6b, 0xa7, 0xb1, 0xcf, 0x98, 0xa3, 0xf2, 0x4d, 0xb1, 0xf6, 0xf2, 0x19, 0x74, 0x6c, 0x25, 0x11, 0x43, 0x60, 0x6e, 0x06, 0x62, 0x79, 0x49, 0x4a, 0x44, 0x5b, 0x35, 0x41, 0xab, 0x3a, 0x5b, 0x70, - /* (2^102)P */ 0xd8, 0xb1, 0x97, 0xd7, 0x36, 0xf5, 0x5e, 0x36, 0xdb, 0xf0, 0xdd, 0x22, 0xd6, 0x6b, 0x07, 0x00, 0x88, 0x5a, 0x57, 0xe0, 0xb0, 0x33, 0xbf, 0x3b, 0x4d, 0xca, 0xe4, 0xc8, 0x05, 0xaa, 0x77, 0x37, - /* (2^103)P */ 0x5f, 0xdb, 0x78, 0x55, 0xc8, 0x45, 0x27, 0x39, 0xe2, 0x5a, 0xae, 0xdb, 0x49, 0x41, 0xda, 0x6f, 0x67, 0x98, 0xdc, 0x8a, 0x0b, 0xb0, 0xf0, 0xb1, 0xa3, 0x1d, 0x6f, 0xd3, 0x37, 0x34, 0x96, 0x09, - /* (2^104)P */ 0x53, 0x38, 0xdc, 0xa5, 0x90, 0x4e, 0x82, 0x7e, 0xbd, 0x5c, 0x13, 0x1f, 0x64, 0xf6, 0xb5, 0xcc, 0xcc, 0x8f, 0xce, 0x87, 0x6c, 0xd8, 0x36, 0x67, 0x9f, 0x24, 0x04, 0x66, 0xe2, 0x3c, 0x5f, 0x62, - /* (2^105)P */ 0x3f, 0xf6, 0x02, 0x95, 0x05, 0xc8, 0x8a, 0xaf, 0x69, 0x14, 0x35, 0x2e, 0x0a, 0xe7, 0x05, 0x0c, 0x05, 0x63, 0x4b, 0x76, 0x9c, 0x2e, 0x29, 0x35, 0xc3, 0x3a, 0xe2, 0xc7, 0x60, 0x43, 0x39, 0x1a, - /* (2^106)P */ 0x64, 0x32, 0x18, 0x51, 0x32, 0xd5, 0xc6, 0xd5, 0x4f, 0xb7, 0xc2, 0x43, 0xbd, 0x5a, 0x06, 0x62, 0x9b, 0x3f, 0x97, 0x3b, 0xd0, 0xf5, 0xfb, 0xb5, 0x5e, 0x6e, 0x20, 0x61, 0x36, 0xda, 0xa3, 0x13, - /* (2^107)P */ 0xe5, 0x94, 0x5d, 0x72, 0x37, 0x58, 0xbd, 0xc6, 0xc5, 0x16, 0x50, 0x20, 0x12, 0x09, 0xe3, 0x18, 0x68, 0x3c, 0x03, 0x70, 0x15, 0xce, 0x88, 0x20, 0x87, 0x79, 0x83, 0x5c, 0x49, 0x1f, 0xba, 0x7f, - /* (2^108)P */ 0x9d, 0x07, 0xf9, 0xf2, 0x23, 0x74, 0x8c, 0x5a, 0xc5, 0x3f, 0x02, 0x34, 0x7b, 0x15, 0x35, 0x17, 0x51, 0xb3, 0xfa, 0xd2, 0x9a, 0xb4, 0xf9, 0xe4, 0x3c, 0xe3, 0x78, 0xc8, 0x72, 0xff, 0x91, 0x66, - /* (2^109)P */ 0x3e, 0xff, 0x5e, 0xdc, 0xde, 0x2a, 0x2c, 0x12, 0xf4, 0x6c, 0x95, 0xd8, 0xf1, 0x4b, 0xdd, 0xf8, 0xda, 0x5b, 0x9e, 0x9e, 0x5d, 0x20, 0x86, 0xeb, 0x43, 0xc7, 0x75, 0xd9, 0xb9, 0x92, 0x9b, 0x04, - /* (2^110)P */ 0x5a, 0xc0, 0xf6, 0xb0, 0x30, 0x97, 0x37, 0xa5, 0x53, 0xa5, 0xf3, 0xc6, 0xac, 0xff, 0xa0, 0x72, 0x6d, 0xcd, 0x0d, 0xb2, 0x34, 0x2c, 0x03, 0xb0, 0x4a, 0x16, 0xd5, 0x88, 0xbc, 0x9d, 0x0e, 0x47, - /* (2^111)P */ 0x47, 0xc0, 0x37, 0xa2, 0x0c, 0xf1, 0x9c, 0xb1, 0xa2, 0x81, 0x6c, 0x1f, 0x71, 0x66, 0x54, 0xb6, 0x43, 0x0b, 0xd8, 0x6d, 0xd1, 0x1b, 0x32, 0xb3, 0x8e, 0xbe, 0x5f, 0x0c, 0x60, 0x4f, 0xc1, 0x48, - /* (2^112)P */ 0x03, 0xc8, 0xa6, 0x4a, 0x26, 0x1c, 0x45, 0x66, 0xa6, 0x7d, 0xfa, 0xa4, 0x04, 0x39, 0x6e, 0xb6, 0x95, 0x83, 0x12, 0xb3, 0xb0, 0x19, 0x5f, 0xd4, 0x10, 0xbc, 0xc9, 0xc3, 0x27, 0x26, 0x60, 0x31, - /* (2^113)P */ 0x0d, 0xe1, 0xe4, 0x32, 0x48, 0xdc, 0x20, 0x31, 0xf7, 0x17, 0xc7, 0x56, 0x67, 0xc4, 0x20, 0xeb, 0x94, 0x02, 0x28, 0x67, 0x3f, 0x2e, 0xf5, 0x00, 0x09, 0xc5, 0x30, 0x47, 0xc1, 0x4f, 0x6d, 0x56, - /* (2^114)P */ 0x06, 0x72, 0x83, 0xfd, 0x40, 0x5d, 0x3a, 0x7e, 0x7a, 0x54, 0x59, 0x71, 0xdc, 0x26, 0xe9, 0xc1, 0x95, 0x60, 0x8d, 0xa6, 0xfb, 0x30, 0x67, 0x21, 0xa7, 0xce, 0x69, 0x3f, 0x84, 0xc3, 0xe8, 0x22, - /* (2^115)P */ 0x2b, 0x4b, 0x0e, 0x93, 0xe8, 0x74, 0xd0, 0x33, 0x16, 0x58, 0xd1, 0x84, 0x0e, 0x35, 0xe4, 0xb6, 0x65, 0x23, 0xba, 0xd6, 0x6a, 0xc2, 0x34, 0x55, 0xf3, 0xf3, 0xf1, 0x89, 0x2f, 0xc1, 0x73, 0x77, - /* (2^116)P */ 0xaa, 0x62, 0x79, 0xa5, 0x4d, 0x40, 0xba, 0x8c, 0x56, 0xce, 0x99, 0x19, 0xa8, 0x97, 0x98, 0x5b, 0xfc, 0x92, 0x16, 0x12, 0x2f, 0x86, 0x8e, 0x50, 0x91, 0xc2, 0x93, 0xa0, 0x7f, 0x90, 0x81, 0x3a, - /* (2^117)P */ 0x10, 0xa5, 0x25, 0x47, 0xff, 0xd0, 0xde, 0x0d, 0x03, 0xc5, 0x3f, 0x67, 0x10, 0xcc, 0xd8, 0x10, 0x89, 0x4e, 0x1f, 0x9f, 0x1c, 0x15, 0x9d, 0x5b, 0x4c, 0xa4, 0x09, 0xcb, 0xd5, 0xc1, 0xa5, 0x32, - /* (2^118)P */ 0xfb, 0x41, 0x05, 0xb9, 0x42, 0xa4, 0x0a, 0x1e, 0xdb, 0x85, 0xb4, 0xc1, 0x7c, 0xeb, 0x85, 0x5f, 0xe5, 0xf2, 0x9d, 0x8a, 0xce, 0x95, 0xe5, 0xbe, 0x36, 0x22, 0x42, 0x22, 0xc7, 0x96, 0xe4, 0x25, - /* (2^119)P */ 0xb9, 0xe5, 0x0f, 0xcd, 0x46, 0x3c, 0xdf, 0x5e, 0x88, 0x33, 0xa4, 0xd2, 0x7e, 0x5a, 0xe7, 0x34, 0x52, 0xe3, 0x61, 0xd7, 0x11, 0xde, 0x88, 0xe4, 0x5c, 0x54, 0x85, 0xa0, 0x01, 0x8a, 0x87, 0x0e, - /* (2^120)P */ 0x04, 0xbb, 0x21, 0xe0, 0x77, 0x3c, 0x49, 0xba, 0x9a, 0x89, 0xdf, 0xc7, 0x43, 0x18, 0x4d, 0x2b, 0x67, 0x0d, 0xe8, 0x7a, 0x48, 0x7a, 0xa3, 0x9e, 0x94, 0x17, 0xe4, 0x11, 0x80, 0x95, 0xa9, 0x67, - /* (2^121)P */ 0x65, 0xb0, 0x97, 0x66, 0x1a, 0x05, 0x58, 0x4b, 0xd4, 0xa6, 0x6b, 0x8d, 0x7d, 0x3f, 0xe3, 0x47, 0xc1, 0x46, 0xca, 0x83, 0xd4, 0xa8, 0x4d, 0xbb, 0x0d, 0xdb, 0xc2, 0x81, 0xa1, 0xca, 0xbe, 0x68, - /* (2^122)P */ 0xa5, 0x9a, 0x98, 0x0b, 0xe9, 0x80, 0x89, 0x8d, 0x9b, 0xc9, 0x93, 0x2c, 0x4a, 0xb1, 0x5e, 0xf9, 0xa2, 0x73, 0x6e, 0x79, 0xc4, 0xc7, 0xc6, 0x51, 0x69, 0xb5, 0xef, 0xb5, 0x63, 0x83, 0x22, 0x6e, - /* (2^123)P */ 0xc8, 0x24, 0xd6, 0x2d, 0xb0, 0xc0, 0xbb, 0xc6, 0xee, 0x70, 0x81, 0xec, 0x7d, 0xb4, 0x7e, 0x77, 0xa9, 0xaf, 0xcf, 0x04, 0xa0, 0x15, 0xde, 0x3c, 0x9b, 0xbf, 0x60, 0x71, 0x08, 0xbc, 0xc6, 0x1d, - /* (2^124)P */ 0x02, 0x40, 0xc3, 0xee, 0x43, 0xe0, 0x07, 0x2e, 0x7f, 0xdc, 0x68, 0x7a, 0x67, 0xfc, 0xe9, 0x18, 0x9a, 0x5b, 0xd1, 0x8b, 0x18, 0x03, 0xda, 0xd8, 0x53, 0x82, 0x56, 0x00, 0xbb, 0xc3, 0xfb, 0x48, - /* (2^125)P */ 0xe1, 0x4c, 0x65, 0xfb, 0x4c, 0x7d, 0x54, 0x57, 0xad, 0xe2, 0x58, 0xa0, 0x82, 0x5b, 0x56, 0xd3, 0x78, 0x44, 0x15, 0xbf, 0x0b, 0xaf, 0x3e, 0xf6, 0x18, 0xbb, 0xdf, 0x14, 0xf1, 0x1e, 0x53, 0x47, - /* (2^126)P */ 0x87, 0xc5, 0x78, 0x42, 0x0a, 0x63, 0xec, 0xe1, 0xf3, 0x83, 0x8e, 0xca, 0x46, 0xd5, 0x07, 0x55, 0x2b, 0x0c, 0xdc, 0x3a, 0xc6, 0x35, 0xe1, 0x85, 0x4e, 0x84, 0x82, 0x56, 0xa8, 0xef, 0xa7, 0x0a, - /* (2^127)P */ 0x15, 0xf6, 0xe1, 0xb3, 0xa8, 0x1b, 0x69, 0x72, 0xfa, 0x3f, 0xbe, 0x1f, 0x70, 0xe9, 0xb4, 0x32, 0x68, 0x78, 0xbb, 0x39, 0x2e, 0xd9, 0xb6, 0x97, 0xe8, 0x39, 0x2e, 0xa0, 0xde, 0x53, 0xfe, 0x2c, - /* (2^128)P */ 0xb0, 0x52, 0xcd, 0x85, 0xcd, 0x92, 0x73, 0x68, 0x31, 0x98, 0xe2, 0x10, 0xc9, 0x66, 0xff, 0x27, 0x06, 0x2d, 0x83, 0xa9, 0x56, 0x45, 0x13, 0x97, 0xa0, 0xf8, 0x84, 0x0a, 0x36, 0xb0, 0x9b, 0x26, - /* (2^129)P */ 0x5c, 0xf8, 0x43, 0x76, 0x45, 0x55, 0x6e, 0x70, 0x1b, 0x7d, 0x59, 0x9b, 0x8c, 0xa4, 0x34, 0x37, 0x72, 0xa4, 0xef, 0xc6, 0xe8, 0x91, 0xee, 0x7a, 0xe0, 0xd9, 0xa9, 0x98, 0xc1, 0xab, 0xd6, 0x5c, - /* (2^130)P */ 0x1a, 0xe4, 0x3c, 0xcb, 0x06, 0xde, 0x04, 0x0e, 0x38, 0xe1, 0x02, 0x34, 0x89, 0xeb, 0xc6, 0xd8, 0x72, 0x37, 0x6e, 0x68, 0xbb, 0x59, 0x46, 0x90, 0xc8, 0xa8, 0x6b, 0x74, 0x71, 0xc3, 0x15, 0x72, - /* (2^131)P */ 0xd9, 0xa2, 0xe4, 0xea, 0x7e, 0xa9, 0x12, 0xfd, 0xc5, 0xf2, 0x94, 0x63, 0x51, 0xb7, 0x14, 0x95, 0x94, 0xf2, 0x08, 0x92, 0x80, 0xd5, 0x6f, 0x26, 0xb9, 0x26, 0x9a, 0x61, 0x85, 0x70, 0x84, 0x5c, - /* (2^132)P */ 0xea, 0x94, 0xd6, 0xfe, 0x10, 0x54, 0x98, 0x52, 0x54, 0xd2, 0x2e, 0x4a, 0x93, 0x5b, 0x90, 0x3c, 0x67, 0xe4, 0x3b, 0x2d, 0x69, 0x47, 0xbb, 0x10, 0xe1, 0xe9, 0xe5, 0x69, 0x2d, 0x3d, 0x3b, 0x06, - /* (2^133)P */ 0xeb, 0x7d, 0xa5, 0xdd, 0xee, 0x26, 0x27, 0x47, 0x91, 0x18, 0xf4, 0x10, 0xae, 0xc4, 0xb6, 0xef, 0x14, 0x76, 0x30, 0x7b, 0x91, 0x41, 0x16, 0x2b, 0x7c, 0x5b, 0xf4, 0xc4, 0x4f, 0x55, 0x7c, 0x11, - /* (2^134)P */ 0x12, 0x88, 0x9d, 0x8f, 0x11, 0xf3, 0x7c, 0xc0, 0x39, 0x79, 0x01, 0x50, 0x20, 0xd8, 0xdb, 0x01, 0x27, 0x28, 0x1b, 0x17, 0xf4, 0x03, 0xe8, 0xd7, 0xea, 0x25, 0xd2, 0x87, 0x74, 0xe8, 0x15, 0x10, - /* (2^135)P */ 0x4d, 0xcc, 0x3a, 0xd2, 0xfe, 0xe3, 0x8d, 0xc5, 0x2d, 0xbe, 0xa7, 0x94, 0xc2, 0x91, 0xdb, 0x50, 0x57, 0xf4, 0x9c, 0x1c, 0x3d, 0xd4, 0x94, 0x0b, 0x4a, 0x52, 0x37, 0x6e, 0xfa, 0x40, 0x16, 0x6b, - /* (2^136)P */ 0x09, 0x0d, 0xda, 0x5f, 0x6c, 0x34, 0x2f, 0x69, 0x51, 0x31, 0x4d, 0xfa, 0x59, 0x1c, 0x0b, 0x20, 0x96, 0xa2, 0x77, 0x07, 0x76, 0x6f, 0xc4, 0xb8, 0xcf, 0xfb, 0xfd, 0x3f, 0x5f, 0x39, 0x38, 0x4b, - /* (2^137)P */ 0x71, 0xd6, 0x54, 0xbe, 0x00, 0x5e, 0xd2, 0x18, 0xa6, 0xab, 0xc8, 0xbe, 0x82, 0x05, 0xd5, 0x60, 0x82, 0xb9, 0x78, 0x3b, 0x26, 0x8f, 0xad, 0x87, 0x32, 0x04, 0xda, 0x9c, 0x4e, 0xf6, 0xfd, 0x50, - /* (2^138)P */ 0xf0, 0xdc, 0x78, 0xc5, 0xaa, 0x67, 0xf5, 0x90, 0x3b, 0x13, 0xa3, 0xf2, 0x0e, 0x9b, 0x1e, 0xef, 0x71, 0xde, 0xd9, 0x42, 0x92, 0xba, 0xeb, 0x0e, 0xc7, 0x01, 0x31, 0xf0, 0x9b, 0x3c, 0x47, 0x15, - /* (2^139)P */ 0x95, 0x80, 0xb7, 0x56, 0xae, 0xe8, 0x77, 0x7c, 0x8e, 0x07, 0x6f, 0x6e, 0x66, 0xe7, 0x78, 0xb6, 0x1f, 0xba, 0x48, 0x53, 0x61, 0xb9, 0xa0, 0x2d, 0x0b, 0x3f, 0x73, 0xff, 0xc1, 0x31, 0xf9, 0x7c, - /* (2^140)P */ 0x6c, 0x36, 0x0a, 0x0a, 0xf5, 0x57, 0xb3, 0x26, 0x32, 0xd7, 0x87, 0x2b, 0xf4, 0x8c, 0x70, 0xe9, 0xc0, 0xb2, 0x1c, 0xf9, 0xa5, 0xee, 0x3a, 0xc1, 0x4c, 0xbb, 0x43, 0x11, 0x99, 0x0c, 0xd9, 0x35, - /* (2^141)P */ 0xdc, 0xd9, 0xa0, 0xa9, 0x04, 0xc4, 0xc1, 0x47, 0x51, 0xd2, 0x72, 0x19, 0x45, 0x58, 0x9e, 0x65, 0x31, 0x8c, 0xb3, 0x73, 0xc4, 0xa8, 0x75, 0x38, 0x24, 0x1f, 0x56, 0x79, 0xd3, 0x9e, 0xbd, 0x1f, - /* (2^142)P */ 0x8d, 0xc2, 0x1e, 0xd4, 0x6f, 0xbc, 0xfa, 0x11, 0xca, 0x2d, 0x2a, 0xcd, 0xe3, 0xdf, 0xf8, 0x7e, 0x95, 0x45, 0x40, 0x8c, 0x5d, 0x3b, 0xe7, 0x72, 0x27, 0x2f, 0xb7, 0x54, 0x49, 0xfa, 0x35, 0x61, - /* (2^143)P */ 0x9c, 0xb6, 0x24, 0xde, 0xa2, 0x32, 0xfc, 0xcc, 0x88, 0x5d, 0x09, 0x1f, 0x8c, 0x69, 0x55, 0x3f, 0x29, 0xf9, 0xc3, 0x5a, 0xed, 0x50, 0x33, 0xbe, 0xeb, 0x7e, 0x47, 0xca, 0x06, 0xf8, 0x9b, 0x5e, - /* (2^144)P */ 0x68, 0x9f, 0x30, 0x3c, 0xb6, 0x8f, 0xce, 0xe9, 0xf4, 0xf9, 0xe1, 0x65, 0x35, 0xf6, 0x76, 0x53, 0xf1, 0x93, 0x63, 0x5a, 0xb3, 0xcf, 0xaf, 0xd1, 0x06, 0x35, 0x62, 0xe5, 0xed, 0xa1, 0x32, 0x66, - /* (2^145)P */ 0x4c, 0xed, 0x2d, 0x0c, 0x39, 0x6c, 0x7d, 0x0b, 0x1f, 0xcb, 0x04, 0xdf, 0x81, 0x32, 0xcb, 0x56, 0xc7, 0xc3, 0xec, 0x49, 0x12, 0x5a, 0x30, 0x66, 0x2a, 0xa7, 0x8c, 0xa3, 0x60, 0x8b, 0x58, 0x5d, - /* (2^146)P */ 0x2d, 0xf4, 0xe5, 0xe8, 0x78, 0xbf, 0xec, 0xa6, 0xec, 0x3e, 0x8a, 0x3c, 0x4b, 0xb4, 0xee, 0x86, 0x04, 0x16, 0xd2, 0xfb, 0x48, 0x9c, 0x21, 0xec, 0x31, 0x67, 0xc3, 0x17, 0xf5, 0x1a, 0xaf, 0x1a, - /* (2^147)P */ 0xe7, 0xbd, 0x69, 0x67, 0x83, 0xa2, 0x06, 0xc3, 0xdb, 0x2a, 0x1e, 0x2b, 0x62, 0x80, 0x82, 0x20, 0xa6, 0x94, 0xff, 0xfb, 0x1f, 0xf5, 0x27, 0x80, 0x6b, 0xf2, 0x24, 0x11, 0xce, 0xa1, 0xcf, 0x76, - /* (2^148)P */ 0xb6, 0xab, 0x22, 0x24, 0x56, 0x00, 0xeb, 0x18, 0xc3, 0x29, 0x8c, 0x8f, 0xd5, 0xc4, 0x77, 0xf3, 0x1a, 0x56, 0x31, 0xf5, 0x07, 0xc2, 0xbb, 0x4d, 0x27, 0x8a, 0x12, 0x82, 0xf0, 0xb7, 0x53, 0x02, - /* (2^149)P */ 0xe0, 0x17, 0x2c, 0xb6, 0x1c, 0x09, 0x1f, 0x3d, 0xa9, 0x28, 0x46, 0xd6, 0xab, 0xe1, 0x60, 0x48, 0x53, 0x42, 0x9d, 0x30, 0x36, 0x74, 0xd1, 0x52, 0x76, 0xe5, 0xfa, 0x3e, 0xe1, 0x97, 0x6f, 0x35, - /* (2^150)P */ 0x5b, 0x53, 0x50, 0xa1, 0x1a, 0xe1, 0x51, 0xd3, 0xcc, 0x78, 0xd8, 0x1d, 0xbb, 0x45, 0x6b, 0x3e, 0x98, 0x2c, 0xd9, 0xbe, 0x28, 0x61, 0x77, 0x0c, 0xb8, 0x85, 0x28, 0x03, 0x93, 0xae, 0x34, 0x1d, - /* (2^151)P */ 0xc3, 0xa4, 0x5b, 0xa8, 0x8c, 0x48, 0xa0, 0x4b, 0xce, 0xe6, 0x9c, 0x3c, 0xc3, 0x48, 0x53, 0x98, 0x70, 0xa7, 0xbd, 0x97, 0x6f, 0x4c, 0x12, 0x66, 0x4a, 0x12, 0x54, 0x06, 0x29, 0xa0, 0x81, 0x0f, - /* (2^152)P */ 0xfd, 0x86, 0x9b, 0x56, 0xa6, 0x9c, 0xd0, 0x9e, 0x2d, 0x9a, 0xaf, 0x18, 0xfd, 0x09, 0x10, 0x81, 0x0a, 0xc2, 0xd8, 0x93, 0x3f, 0xd0, 0x08, 0xff, 0x6b, 0xf2, 0xae, 0x9f, 0x19, 0x48, 0xa1, 0x52, - /* (2^153)P */ 0x73, 0x1b, 0x8d, 0x2d, 0xdc, 0xf9, 0x03, 0x3e, 0x70, 0x1a, 0x96, 0x73, 0x18, 0x80, 0x05, 0x42, 0x70, 0x59, 0xa3, 0x41, 0xf0, 0x87, 0xd9, 0xc0, 0x49, 0xd5, 0xc0, 0xa1, 0x15, 0x1f, 0xaa, 0x07, - /* (2^154)P */ 0x24, 0x72, 0xd2, 0x8c, 0xe0, 0x6c, 0xd4, 0xdf, 0x39, 0x42, 0x4e, 0x93, 0x4f, 0x02, 0x0a, 0x6d, 0x59, 0x7b, 0x89, 0x99, 0x63, 0x7a, 0x8a, 0x80, 0xa2, 0x95, 0x3d, 0xe1, 0xe9, 0x56, 0x45, 0x0a, - /* (2^155)P */ 0x45, 0x30, 0xc1, 0xe9, 0x1f, 0x99, 0x1a, 0xd2, 0xb8, 0x51, 0x77, 0xfe, 0x48, 0x85, 0x0e, 0x9b, 0x35, 0x00, 0xf3, 0x4b, 0xcb, 0x43, 0xa6, 0x5d, 0x21, 0xf7, 0x40, 0x39, 0xd6, 0x28, 0xdb, 0x77, - /* (2^156)P */ 0x11, 0x90, 0xdc, 0x4a, 0x61, 0xeb, 0x5e, 0xfc, 0xeb, 0x11, 0xc4, 0xe8, 0x9a, 0x41, 0x29, 0x52, 0x74, 0xcf, 0x1d, 0x7d, 0x78, 0xe7, 0xc3, 0x9e, 0xb5, 0x4c, 0x6e, 0x21, 0x3e, 0x05, 0x0d, 0x34, - /* (2^157)P */ 0xb4, 0xf2, 0x8d, 0xb4, 0x39, 0xaf, 0xc7, 0xca, 0x94, 0x0a, 0xa1, 0x71, 0x28, 0xec, 0xfa, 0xc0, 0xed, 0x75, 0xa5, 0x5c, 0x24, 0x69, 0x0a, 0x14, 0x4c, 0x3a, 0x27, 0x34, 0x71, 0xc3, 0xf1, 0x0c, - /* (2^158)P */ 0xa5, 0xb8, 0x24, 0xc2, 0x6a, 0x30, 0xee, 0xc8, 0xb0, 0x30, 0x49, 0xcb, 0x7c, 0xee, 0xea, 0x57, 0x4f, 0xe7, 0xcb, 0xaa, 0xbd, 0x06, 0xe8, 0xa1, 0x7d, 0x65, 0xeb, 0x2e, 0x74, 0x62, 0x9a, 0x7d, - /* (2^159)P */ 0x30, 0x48, 0x6c, 0x54, 0xef, 0xb6, 0xb6, 0x9e, 0x2e, 0x6e, 0xb3, 0xdd, 0x1f, 0xca, 0x5c, 0x88, 0x05, 0x71, 0x0d, 0xef, 0x83, 0xf3, 0xb9, 0xe6, 0x12, 0x04, 0x2e, 0x9d, 0xef, 0x4f, 0x65, 0x58, - /* (2^160)P */ 0x26, 0x8e, 0x0e, 0xbe, 0xff, 0xc4, 0x05, 0xa9, 0x6e, 0x81, 0x31, 0x9b, 0xdf, 0xe5, 0x2d, 0x94, 0xe1, 0x88, 0x2e, 0x80, 0x3f, 0x72, 0x7d, 0x49, 0x8d, 0x40, 0x2f, 0x60, 0xea, 0x4d, 0x68, 0x30, - /* (2^161)P */ 0x34, 0xcb, 0xe6, 0xa3, 0x78, 0xa2, 0xe5, 0x21, 0xc4, 0x1d, 0x15, 0x5b, 0x6f, 0x6e, 0xfb, 0xae, 0x15, 0xca, 0x77, 0x9d, 0x04, 0x8e, 0x0b, 0xb3, 0x81, 0x89, 0xb9, 0x53, 0xcf, 0xc9, 0xc3, 0x28, - /* (2^162)P */ 0x2a, 0xdd, 0x6c, 0x55, 0x21, 0xb7, 0x7f, 0x28, 0x74, 0x22, 0x02, 0x97, 0xa8, 0x7c, 0x31, 0x0d, 0x58, 0x32, 0x54, 0x3a, 0x42, 0xc7, 0x68, 0x74, 0x2f, 0x64, 0xb5, 0x4e, 0x46, 0x11, 0x7f, 0x4a, - /* (2^163)P */ 0xa6, 0x3a, 0x19, 0x4d, 0x77, 0xa4, 0x37, 0xa2, 0xa1, 0x29, 0x21, 0xa9, 0x6e, 0x98, 0x65, 0xd8, 0x88, 0x1a, 0x7c, 0xf8, 0xec, 0x15, 0xc5, 0x24, 0xeb, 0xf5, 0x39, 0x5f, 0x57, 0x03, 0x40, 0x60, - /* (2^164)P */ 0x27, 0x9b, 0x0a, 0x57, 0x89, 0xf1, 0xb9, 0x47, 0x78, 0x4b, 0x5e, 0x46, 0xde, 0xce, 0x98, 0x2b, 0x20, 0x5c, 0xb8, 0xdb, 0x51, 0xf5, 0x6d, 0x02, 0x01, 0x19, 0xe2, 0x47, 0x10, 0xd9, 0xfc, 0x74, - /* (2^165)P */ 0xa3, 0xbf, 0xc1, 0x23, 0x0a, 0xa9, 0xe2, 0x13, 0xf6, 0x19, 0x85, 0x47, 0x4e, 0x07, 0xb0, 0x0c, 0x44, 0xcf, 0xf6, 0x3a, 0xbe, 0xcb, 0xf1, 0x5f, 0xbe, 0x2d, 0x81, 0xbe, 0x38, 0x54, 0xfe, 0x67, - /* (2^166)P */ 0xb0, 0x05, 0x0f, 0xa4, 0x4f, 0xf6, 0x3c, 0xd1, 0x87, 0x37, 0x28, 0x32, 0x2f, 0xfb, 0x4d, 0x05, 0xea, 0x2a, 0x0d, 0x7f, 0x5b, 0x91, 0x73, 0x41, 0x4e, 0x0d, 0x61, 0x1f, 0x4f, 0x14, 0x2f, 0x48, - /* (2^167)P */ 0x34, 0x82, 0x7f, 0xb4, 0x01, 0x02, 0x21, 0xf6, 0x90, 0xb9, 0x70, 0x9e, 0x92, 0xe1, 0x0a, 0x5d, 0x7c, 0x56, 0x49, 0xb0, 0x55, 0xf4, 0xd7, 0xdc, 0x01, 0x6f, 0x91, 0xf0, 0xf1, 0xd0, 0x93, 0x7e, - /* (2^168)P */ 0xfa, 0xb4, 0x7d, 0x8a, 0xf1, 0xcb, 0x79, 0xdd, 0x2f, 0xc6, 0x74, 0x6f, 0xbf, 0x91, 0x83, 0xbe, 0xbd, 0x91, 0x82, 0x4b, 0xd1, 0x45, 0x71, 0x02, 0x05, 0x17, 0xbf, 0x2c, 0xea, 0x73, 0x5a, 0x58, - /* (2^169)P */ 0xb2, 0x0d, 0x8a, 0x92, 0x3e, 0xa0, 0x5c, 0x48, 0xe7, 0x57, 0x28, 0x74, 0xa5, 0x01, 0xfc, 0x10, 0xa7, 0x51, 0xd5, 0xd6, 0xdb, 0x2e, 0x48, 0x2f, 0x8a, 0xdb, 0x8f, 0x04, 0xb5, 0x33, 0x04, 0x0f, - /* (2^170)P */ 0x47, 0x62, 0xdc, 0xd7, 0x8d, 0x2e, 0xda, 0x60, 0x9a, 0x81, 0xd4, 0x8c, 0xd3, 0xc9, 0xb4, 0x88, 0x97, 0x66, 0xf6, 0x01, 0xc0, 0x3a, 0x03, 0x13, 0x75, 0x7d, 0x36, 0x3b, 0xfe, 0x24, 0x3b, 0x27, - /* (2^171)P */ 0xd4, 0xb9, 0xb3, 0x31, 0x6a, 0xf6, 0xe8, 0xc6, 0xd5, 0x49, 0xdf, 0x94, 0xa4, 0x14, 0x15, 0x28, 0xa7, 0x3d, 0xb2, 0xc8, 0xdf, 0x6f, 0x72, 0xd1, 0x48, 0xe5, 0xde, 0x03, 0xd1, 0xe7, 0x3a, 0x4b, - /* (2^172)P */ 0x7e, 0x9d, 0x4b, 0xce, 0x19, 0x6e, 0x25, 0xc6, 0x1c, 0xc6, 0xe3, 0x86, 0xf1, 0x5c, 0x5c, 0xff, 0x45, 0xc1, 0x8e, 0x4b, 0xa3, 0x3c, 0xc6, 0xac, 0x74, 0x65, 0xe6, 0xfe, 0x88, 0x18, 0x62, 0x74, - /* (2^173)P */ 0x1e, 0x0a, 0x29, 0x45, 0x96, 0x40, 0x6f, 0x95, 0x2e, 0x96, 0x3a, 0x26, 0xe3, 0xf8, 0x0b, 0xef, 0x7b, 0x64, 0xc2, 0x5e, 0xeb, 0x50, 0x6a, 0xed, 0x02, 0x75, 0xca, 0x9d, 0x3a, 0x28, 0x94, 0x06, - /* (2^174)P */ 0xd1, 0xdc, 0xa2, 0x43, 0x36, 0x96, 0x9b, 0x76, 0x53, 0x53, 0xfc, 0x09, 0xea, 0xc8, 0xb7, 0x42, 0xab, 0x7e, 0x39, 0x13, 0xee, 0x2a, 0x00, 0x4f, 0x3a, 0xd6, 0xb7, 0x19, 0x2c, 0x5e, 0x00, 0x63, - /* (2^175)P */ 0xea, 0x3b, 0x02, 0x63, 0xda, 0x36, 0x67, 0xca, 0xb7, 0x99, 0x2a, 0xb1, 0x6d, 0x7f, 0x6c, 0x96, 0xe1, 0xc5, 0x37, 0xc5, 0x90, 0x93, 0xe0, 0xac, 0xee, 0x89, 0xaa, 0xa1, 0x63, 0x60, 0x69, 0x0b, - /* (2^176)P */ 0xe5, 0x56, 0x8c, 0x28, 0x97, 0x3e, 0xb0, 0xeb, 0xe8, 0x8b, 0x8c, 0x93, 0x9f, 0x9f, 0x2a, 0x43, 0x71, 0x7f, 0x71, 0x5b, 0x3d, 0xa9, 0xa5, 0xa6, 0x97, 0x9d, 0x8f, 0xe1, 0xc3, 0xb4, 0x5f, 0x1a, - /* (2^177)P */ 0xce, 0xcd, 0x60, 0x1c, 0xad, 0xe7, 0x94, 0x1c, 0xa0, 0xc4, 0x02, 0xfc, 0x43, 0x2a, 0x20, 0xee, 0x20, 0x6a, 0xc4, 0x67, 0xd8, 0xe4, 0xaf, 0x8d, 0x58, 0x7b, 0xc2, 0x8a, 0x3c, 0x26, 0x10, 0x0a, - /* (2^178)P */ 0x4a, 0x2a, 0x43, 0xe4, 0xdf, 0xa9, 0xde, 0xd0, 0xc5, 0x77, 0x92, 0xbe, 0x7b, 0xf8, 0x6a, 0x85, 0x1a, 0xc7, 0x12, 0xc2, 0xac, 0x72, 0x84, 0xce, 0x91, 0x1e, 0xbb, 0x9b, 0x6d, 0x1b, 0x15, 0x6f, - /* (2^179)P */ 0x6a, 0xd5, 0xee, 0x7c, 0x52, 0x6c, 0x77, 0x26, 0xec, 0xfa, 0xf8, 0xfb, 0xb7, 0x1c, 0x21, 0x7d, 0xcc, 0x09, 0x46, 0xfd, 0xa6, 0x66, 0xae, 0x37, 0x42, 0x0c, 0x77, 0xd2, 0x02, 0xb7, 0x81, 0x1f, - /* (2^180)P */ 0x92, 0x83, 0xc5, 0xea, 0x57, 0xb0, 0xb0, 0x2f, 0x9d, 0x4e, 0x74, 0x29, 0xfe, 0x89, 0xdd, 0xe1, 0xf8, 0xb4, 0xbe, 0x17, 0xeb, 0xf8, 0x64, 0xc9, 0x1e, 0xd4, 0xa2, 0xc9, 0x73, 0x10, 0x57, 0x29, - /* (2^181)P */ 0x54, 0xe2, 0xc0, 0x81, 0x89, 0xa1, 0x48, 0xa9, 0x30, 0x28, 0xb2, 0x65, 0x9b, 0x36, 0xf6, 0x2d, 0xc6, 0xd3, 0xcf, 0x5f, 0xd7, 0xb2, 0x3e, 0xa3, 0x1f, 0xa0, 0x99, 0x41, 0xec, 0xd6, 0x8c, 0x07, - /* (2^182)P */ 0x2f, 0x0d, 0x90, 0xad, 0x41, 0x4a, 0x58, 0x4a, 0x52, 0x4c, 0xc7, 0xe2, 0x78, 0x2b, 0x14, 0x32, 0x78, 0xc9, 0x31, 0x84, 0x33, 0xe8, 0xc4, 0x68, 0xc2, 0x9f, 0x68, 0x08, 0x90, 0xea, 0x69, 0x7f, - /* (2^183)P */ 0x65, 0x82, 0xa3, 0x46, 0x1e, 0xc8, 0xf2, 0x52, 0xfd, 0x32, 0xa8, 0x04, 0x2d, 0x07, 0x78, 0xfd, 0x94, 0x9e, 0x35, 0x25, 0xfa, 0xd5, 0xd7, 0x8c, 0xd2, 0x29, 0xcc, 0x54, 0x74, 0x1b, 0xe7, 0x4d, - /* (2^184)P */ 0xc9, 0x6a, 0xda, 0x1e, 0xad, 0x60, 0xeb, 0x42, 0x3a, 0x9c, 0xc0, 0xdb, 0xdf, 0x37, 0xad, 0x0a, 0x91, 0xc1, 0x3c, 0xe3, 0x71, 0x4b, 0x00, 0x81, 0x3c, 0x80, 0x22, 0x51, 0x34, 0xbe, 0xe6, 0x44, - /* (2^185)P */ 0xdb, 0x20, 0x19, 0xba, 0x88, 0x83, 0xfe, 0x03, 0x08, 0xb0, 0x0d, 0x15, 0x32, 0x7c, 0xd5, 0xf5, 0x29, 0x0c, 0xf6, 0x1a, 0x28, 0xc4, 0xc8, 0x49, 0xee, 0x1a, 0x70, 0xde, 0x18, 0xb5, 0xed, 0x21, - /* (2^186)P */ 0x99, 0xdc, 0x06, 0x8f, 0x41, 0x3e, 0xb6, 0x7f, 0xb8, 0xd7, 0x66, 0xc1, 0x99, 0x0d, 0x46, 0xa4, 0x83, 0x0a, 0x52, 0xce, 0x48, 0x52, 0xdd, 0x24, 0x58, 0x83, 0x92, 0x2b, 0x71, 0xad, 0xc3, 0x5e, - /* (2^187)P */ 0x0f, 0x93, 0x17, 0xbd, 0x5f, 0x2a, 0x02, 0x15, 0xe3, 0x70, 0x25, 0xd8, 0x77, 0x4a, 0xf6, 0xa4, 0x12, 0x37, 0x78, 0x15, 0x69, 0x8d, 0xbc, 0x12, 0xbb, 0x0a, 0x62, 0xfc, 0xc0, 0x94, 0x81, 0x49, - /* (2^188)P */ 0x82, 0x6c, 0x68, 0x55, 0xd2, 0xd9, 0xa2, 0x38, 0xf0, 0x21, 0x3e, 0x19, 0xd9, 0x6b, 0x5c, 0x78, 0x84, 0x54, 0x4a, 0xb2, 0x1a, 0xc8, 0xd5, 0xe4, 0x89, 0x09, 0xe2, 0xb2, 0x60, 0x78, 0x30, 0x56, - /* (2^189)P */ 0xc4, 0x74, 0x4d, 0x8b, 0xf7, 0x55, 0x9d, 0x42, 0x31, 0x01, 0x35, 0x43, 0x46, 0x83, 0xf1, 0x22, 0xff, 0x1f, 0xc7, 0x98, 0x45, 0xc2, 0x60, 0x1e, 0xef, 0x83, 0x99, 0x97, 0x14, 0xf0, 0xf2, 0x59, - /* (2^190)P */ 0x44, 0x4a, 0x49, 0xeb, 0x56, 0x7d, 0xa4, 0x46, 0x8e, 0xa1, 0x36, 0xd6, 0x54, 0xa8, 0x22, 0x3e, 0x3b, 0x1c, 0x49, 0x74, 0x52, 0xe1, 0x46, 0xb3, 0xe7, 0xcd, 0x90, 0x53, 0x4e, 0xfd, 0xea, 0x2c, - /* (2^191)P */ 0x75, 0x66, 0x0d, 0xbe, 0x38, 0x85, 0x8a, 0xba, 0x23, 0x8e, 0x81, 0x50, 0xbb, 0x74, 0x90, 0x4b, 0xc3, 0x04, 0xd3, 0x85, 0x90, 0xb8, 0xda, 0xcb, 0xc4, 0x92, 0x61, 0xe5, 0xe0, 0x4f, 0xa2, 0x61, - /* (2^192)P */ 0xcb, 0x5b, 0x52, 0xdb, 0xe6, 0x15, 0x76, 0xcb, 0xca, 0xe4, 0x67, 0xa5, 0x35, 0x8c, 0x7d, 0xdd, 0x69, 0xdd, 0xfc, 0xca, 0x3a, 0x15, 0xb4, 0xe6, 0x66, 0x97, 0x3c, 0x7f, 0x09, 0x8e, 0x66, 0x2d, - /* (2^193)P */ 0xf0, 0x5e, 0xe5, 0x5c, 0x26, 0x7e, 0x7e, 0xa5, 0x67, 0xb9, 0xd4, 0x7c, 0x52, 0x4e, 0x9f, 0x5d, 0xe5, 0xd1, 0x2f, 0x49, 0x06, 0x36, 0xc8, 0xfb, 0xae, 0xf7, 0xc3, 0xb7, 0xbe, 0x52, 0x0d, 0x09, - /* (2^194)P */ 0x7c, 0x4d, 0x7b, 0x1e, 0x5a, 0x51, 0xb9, 0x09, 0xc0, 0x44, 0xda, 0x99, 0x25, 0x6a, 0x26, 0x1f, 0x04, 0x55, 0xc5, 0xe2, 0x48, 0x95, 0xc4, 0xa1, 0xcc, 0x15, 0x6f, 0x12, 0x87, 0x42, 0xf0, 0x7e, - /* (2^195)P */ 0x15, 0xef, 0x30, 0xbd, 0x9d, 0x65, 0xd1, 0xfe, 0x7b, 0x27, 0xe0, 0xc4, 0xee, 0xb9, 0x4a, 0x8b, 0x91, 0x32, 0xdf, 0xa5, 0x36, 0x62, 0x4d, 0x88, 0x88, 0xf7, 0x5c, 0xbf, 0xa6, 0x6e, 0xd9, 0x1f, - /* (2^196)P */ 0x9a, 0x0d, 0x19, 0x1f, 0x98, 0x61, 0xa1, 0x42, 0xc1, 0x52, 0x60, 0x7e, 0x50, 0x49, 0xd8, 0x61, 0xd5, 0x2c, 0x5a, 0x28, 0xbf, 0x13, 0xe1, 0x9f, 0xd8, 0x85, 0xad, 0xdb, 0x76, 0xd6, 0x22, 0x7c, - /* (2^197)P */ 0x7d, 0xd2, 0xfb, 0x2b, 0xed, 0x70, 0xe7, 0x82, 0xa5, 0xf5, 0x96, 0xe9, 0xec, 0xb2, 0x05, 0x4c, 0x50, 0x01, 0x90, 0xb0, 0xc2, 0xa9, 0x40, 0xcd, 0x64, 0xbf, 0xd9, 0x13, 0x92, 0x31, 0x95, 0x58, - /* (2^198)P */ 0x08, 0x2e, 0xea, 0x3f, 0x70, 0x5d, 0xcc, 0xe7, 0x8c, 0x18, 0xe2, 0x58, 0x12, 0x49, 0x0c, 0xb5, 0xf0, 0x5b, 0x20, 0x48, 0xaa, 0x0b, 0xe3, 0xcc, 0x62, 0x2d, 0xa3, 0xcf, 0x9c, 0x65, 0x7c, 0x53, - /* (2^199)P */ 0x88, 0xc0, 0xcf, 0x98, 0x3a, 0x62, 0xb6, 0x37, 0xa4, 0xac, 0xd6, 0xa4, 0x1f, 0xed, 0x9b, 0xfe, 0xb0, 0xd1, 0xa8, 0x56, 0x8e, 0x9b, 0xd2, 0x04, 0x75, 0x95, 0x51, 0x0b, 0xc4, 0x71, 0x5f, 0x72, - /* (2^200)P */ 0xe6, 0x9c, 0x33, 0xd0, 0x9c, 0xf8, 0xc7, 0x28, 0x8b, 0xc1, 0xdd, 0x69, 0x44, 0xb1, 0x67, 0x83, 0x2c, 0x65, 0xa1, 0xa6, 0x83, 0xda, 0x3a, 0x88, 0x17, 0x6c, 0x4d, 0x03, 0x74, 0x19, 0x5f, 0x58, - /* (2^201)P */ 0x88, 0x91, 0xb1, 0xf1, 0x66, 0xb2, 0xcf, 0x89, 0x17, 0x52, 0xc3, 0xe7, 0x63, 0x48, 0x3b, 0xe6, 0x6a, 0x52, 0xc0, 0xb4, 0xa6, 0x9d, 0x8c, 0xd8, 0x35, 0x46, 0x95, 0xf0, 0x9d, 0x5c, 0x03, 0x3e, - /* (2^202)P */ 0x9d, 0xde, 0x45, 0xfb, 0x12, 0x54, 0x9d, 0xdd, 0x0d, 0xf4, 0xcf, 0xe4, 0x32, 0x45, 0x68, 0xdd, 0x1c, 0x67, 0x1d, 0x15, 0x9b, 0x99, 0x5c, 0x4b, 0x90, 0xf6, 0xe7, 0x11, 0xc8, 0x2c, 0x8c, 0x2d, - /* (2^203)P */ 0x40, 0x5d, 0x05, 0x90, 0x1d, 0xbe, 0x54, 0x7f, 0x40, 0xaf, 0x4a, 0x46, 0xdf, 0xc5, 0x64, 0xa4, 0xbe, 0x17, 0xe9, 0xf0, 0x24, 0x96, 0x97, 0x33, 0x30, 0x6b, 0x35, 0x27, 0xc5, 0x8d, 0x01, 0x2c, - /* (2^204)P */ 0xd4, 0xb3, 0x30, 0xe3, 0x24, 0x50, 0x41, 0xa5, 0xd3, 0x52, 0x16, 0x69, 0x96, 0x3d, 0xff, 0x73, 0xf1, 0x59, 0x9b, 0xef, 0xc4, 0x42, 0xec, 0x94, 0x5a, 0x8e, 0xd0, 0x18, 0x16, 0x20, 0x47, 0x07, - /* (2^205)P */ 0x53, 0x1c, 0x41, 0xca, 0x8a, 0xa4, 0x6c, 0x4d, 0x19, 0x61, 0xa6, 0xcf, 0x2f, 0x5f, 0x41, 0x66, 0xff, 0x27, 0xe2, 0x51, 0x00, 0xd4, 0x4d, 0x9c, 0xeb, 0xf7, 0x02, 0x9a, 0xc0, 0x0b, 0x81, 0x59, - /* (2^206)P */ 0x1d, 0x10, 0xdc, 0xb3, 0x71, 0xb1, 0x7e, 0x2a, 0x8e, 0xf6, 0xfe, 0x9f, 0xb9, 0x5a, 0x1c, 0x44, 0xea, 0x59, 0xb3, 0x93, 0x9b, 0x5c, 0x02, 0x32, 0x2f, 0x11, 0x9d, 0x1e, 0xa7, 0xe0, 0x8c, 0x5e, - /* (2^207)P */ 0xfd, 0x03, 0x95, 0x42, 0x92, 0xcb, 0xcc, 0xbf, 0x55, 0x5d, 0x09, 0x2f, 0x75, 0xba, 0x71, 0xd2, 0x1e, 0x09, 0x2d, 0x97, 0x5e, 0xad, 0x5e, 0x34, 0xba, 0x03, 0x31, 0xa8, 0x11, 0xdf, 0xc8, 0x18, - /* (2^208)P */ 0x4c, 0x0f, 0xed, 0x9a, 0x9a, 0x94, 0xcd, 0x90, 0x7e, 0xe3, 0x60, 0x66, 0xcb, 0xf4, 0xd1, 0xc5, 0x0b, 0x2e, 0xc5, 0x56, 0x2d, 0xc5, 0xca, 0xb8, 0x0d, 0x8e, 0x80, 0xc5, 0x00, 0xe4, 0x42, 0x6e, - /* (2^209)P */ 0x23, 0xfd, 0xae, 0xee, 0x66, 0x69, 0xb4, 0xa3, 0xca, 0xcd, 0x9e, 0xe3, 0x0b, 0x1f, 0x4f, 0x0c, 0x1d, 0xa5, 0x83, 0xd6, 0xc9, 0xc8, 0x9d, 0x18, 0x1b, 0x35, 0x09, 0x4c, 0x05, 0x7f, 0xf2, 0x51, - /* (2^210)P */ 0x82, 0x06, 0x32, 0x2a, 0xcd, 0x7c, 0x48, 0x4c, 0x96, 0x1c, 0xdf, 0xb3, 0x5b, 0xa9, 0x7e, 0x58, 0xe8, 0xb8, 0x5c, 0x55, 0x9e, 0xf7, 0xcc, 0xc8, 0x3d, 0xd7, 0x06, 0xa2, 0x29, 0xc8, 0x7d, 0x54, - /* (2^211)P */ 0x06, 0x9b, 0xc3, 0x80, 0xcd, 0xa6, 0x22, 0xb8, 0xc6, 0xd4, 0x00, 0x20, 0x73, 0x54, 0x6d, 0xe9, 0x4d, 0x3b, 0x46, 0x91, 0x6f, 0x5b, 0x53, 0x28, 0x1d, 0x6e, 0x48, 0xe2, 0x60, 0x46, 0x8f, 0x22, - /* (2^212)P */ 0xbf, 0x3a, 0x8d, 0xde, 0x38, 0x95, 0x79, 0x98, 0x6e, 0xca, 0xeb, 0x45, 0x00, 0x33, 0xd8, 0x8c, 0x38, 0xe7, 0x21, 0x82, 0x00, 0x2a, 0x95, 0x79, 0xbb, 0xd2, 0x5c, 0x53, 0xa7, 0xe1, 0x22, 0x43, - /* (2^213)P */ 0x1c, 0x80, 0xd1, 0x19, 0x18, 0xc1, 0x14, 0xb1, 0xc7, 0x5e, 0x3f, 0x4f, 0xd8, 0xe4, 0x16, 0x20, 0x4c, 0x0f, 0x26, 0x09, 0xf4, 0x2d, 0x0e, 0xdd, 0x66, 0x72, 0x5f, 0xae, 0xc0, 0x62, 0xc3, 0x5e, - /* (2^214)P */ 0xee, 0xb4, 0xb2, 0xb8, 0x18, 0x2b, 0x46, 0xc0, 0xfb, 0x1a, 0x4d, 0x27, 0x50, 0xd9, 0xc8, 0x7c, 0xd2, 0x02, 0x6b, 0x43, 0x05, 0x71, 0x5f, 0xf2, 0xd3, 0xcc, 0xf9, 0xbf, 0xdc, 0xf8, 0xbb, 0x43, - /* (2^215)P */ 0xdf, 0xe9, 0x39, 0xa0, 0x67, 0x17, 0xad, 0xb6, 0x83, 0x35, 0x9d, 0xf6, 0xa8, 0x4d, 0x71, 0xb0, 0xf5, 0x31, 0x29, 0xb4, 0x18, 0xfa, 0x55, 0x5e, 0x61, 0x09, 0xc6, 0x33, 0x8f, 0x55, 0xd5, 0x4e, - /* (2^216)P */ 0xdd, 0xa5, 0x47, 0xc6, 0x01, 0x79, 0xe3, 0x1f, 0x57, 0xd3, 0x81, 0x80, 0x1f, 0xdf, 0x3d, 0x59, 0xa6, 0xd7, 0x3f, 0x81, 0xfd, 0xa4, 0x49, 0x02, 0x61, 0xaf, 0x9c, 0x4e, 0x27, 0xca, 0xac, 0x69, - /* (2^217)P */ 0xc9, 0x21, 0x07, 0x33, 0xea, 0xa3, 0x7b, 0x04, 0xa0, 0x1e, 0x7e, 0x0e, 0xc2, 0x3f, 0x42, 0x83, 0x60, 0x4a, 0x31, 0x01, 0xaf, 0xc0, 0xf4, 0x1d, 0x27, 0x95, 0x28, 0x89, 0xab, 0x2d, 0xa6, 0x09, - /* (2^218)P */ 0x00, 0xcb, 0xc6, 0x9c, 0xa4, 0x25, 0xb3, 0xa5, 0xb6, 0x6c, 0xb5, 0x54, 0xc6, 0x5d, 0x4b, 0xe9, 0xa0, 0x94, 0xc9, 0xad, 0x79, 0x87, 0xe2, 0x3b, 0xad, 0x4a, 0x3a, 0xba, 0xf8, 0xe8, 0x96, 0x42, - /* (2^219)P */ 0xab, 0x1e, 0x45, 0x1e, 0x76, 0x89, 0x86, 0x32, 0x4a, 0x59, 0x59, 0xff, 0x8b, 0x59, 0x4d, 0x2e, 0x4a, 0x08, 0xa7, 0xd7, 0x53, 0x68, 0xb9, 0x49, 0xa8, 0x20, 0x14, 0x60, 0x19, 0xa3, 0x80, 0x49, - /* (2^220)P */ 0x42, 0x2c, 0x55, 0x2f, 0xe1, 0xb9, 0x65, 0x95, 0x96, 0xfe, 0x00, 0x71, 0xdb, 0x18, 0x53, 0x8a, 0xd7, 0xd0, 0xad, 0x43, 0x4d, 0x0b, 0xc9, 0x05, 0xda, 0x4e, 0x5d, 0x6a, 0xd6, 0x4c, 0x8b, 0x53, - /* (2^221)P */ 0x9f, 0x03, 0x9f, 0xe8, 0xc3, 0x4f, 0xe9, 0xf4, 0x45, 0x80, 0x61, 0x6f, 0xf2, 0x9a, 0x2c, 0x59, 0x50, 0x95, 0x4b, 0xfd, 0xb5, 0x6e, 0xa3, 0x08, 0x19, 0x14, 0xed, 0xc2, 0xf6, 0xfa, 0xff, 0x25, - /* (2^222)P */ 0x54, 0xd3, 0x79, 0xcc, 0x59, 0x44, 0x43, 0x34, 0x6b, 0x47, 0xd5, 0xb1, 0xb4, 0xbf, 0xec, 0xee, 0x99, 0x5d, 0x61, 0x61, 0xa0, 0x34, 0xeb, 0xdd, 0x73, 0xb7, 0x64, 0xeb, 0xcc, 0xce, 0x29, 0x51, - /* (2^223)P */ 0x20, 0x35, 0x99, 0x94, 0x58, 0x21, 0x43, 0xee, 0x3b, 0x0b, 0x4c, 0xf1, 0x7c, 0x9c, 0x2f, 0x77, 0xd5, 0xda, 0xbe, 0x06, 0xe3, 0xfc, 0xe2, 0xd2, 0x97, 0x6a, 0xf0, 0x46, 0xb5, 0x42, 0x5f, 0x71, - /* (2^224)P */ 0x1a, 0x5f, 0x5b, 0xda, 0xce, 0xcd, 0x4e, 0x43, 0xa9, 0x41, 0x97, 0xa4, 0x15, 0x71, 0xa1, 0x0d, 0x2e, 0xad, 0xed, 0x73, 0x7c, 0xd7, 0x0b, 0x68, 0x41, 0x90, 0xdd, 0x4e, 0x35, 0x02, 0x7c, 0x48, - /* (2^225)P */ 0xc4, 0xd9, 0x0e, 0xa7, 0xf3, 0xef, 0xef, 0xb8, 0x02, 0xe3, 0x57, 0xe8, 0xa3, 0x2a, 0xa3, 0x56, 0xa0, 0xa5, 0xa2, 0x48, 0xbd, 0x68, 0x3a, 0xdf, 0x44, 0xc4, 0x76, 0x31, 0xb7, 0x50, 0xf6, 0x07, - /* (2^226)P */ 0xb1, 0xcc, 0xe0, 0x26, 0x16, 0x9b, 0x8b, 0xe3, 0x36, 0xfb, 0x09, 0x8b, 0xc1, 0x53, 0xe0, 0x79, 0x64, 0x49, 0xf9, 0xc9, 0x19, 0x03, 0xd9, 0x56, 0xc4, 0xf5, 0x9f, 0xac, 0xe7, 0x41, 0xa9, 0x1c, - /* (2^227)P */ 0xbb, 0xa0, 0x2f, 0x16, 0x29, 0xdf, 0xc4, 0x49, 0x05, 0x33, 0xb3, 0x82, 0x32, 0xcf, 0x88, 0x84, 0x7d, 0x43, 0xbb, 0xca, 0x14, 0xda, 0xdf, 0x95, 0x86, 0xad, 0xd5, 0x64, 0x82, 0xf7, 0x91, 0x33, - /* (2^228)P */ 0x5d, 0x09, 0xb5, 0xe2, 0x6a, 0xe0, 0x9a, 0x72, 0x46, 0xa9, 0x59, 0x32, 0xd7, 0x58, 0x8a, 0xd5, 0xed, 0x21, 0x39, 0xd1, 0x62, 0x42, 0x83, 0xe9, 0x92, 0xb5, 0x4b, 0xa5, 0xfa, 0xda, 0xfe, 0x27, - /* (2^229)P */ 0xbb, 0x48, 0xad, 0x29, 0xb8, 0xc5, 0x9d, 0xa9, 0x60, 0xe2, 0x9e, 0x49, 0x42, 0x57, 0x02, 0x5f, 0xfd, 0x13, 0x75, 0x5d, 0xcd, 0x8e, 0x2c, 0x80, 0x38, 0xd9, 0x6d, 0x3f, 0xef, 0xb3, 0xce, 0x78, - /* (2^230)P */ 0x94, 0x5d, 0x13, 0x8a, 0x4f, 0xf4, 0x42, 0xc3, 0xa3, 0xdd, 0x8c, 0x82, 0x44, 0xdb, 0x9e, 0x7b, 0xe7, 0xcf, 0x37, 0x05, 0x1a, 0xd1, 0x36, 0x94, 0xc8, 0xb4, 0x1a, 0xec, 0x64, 0xb1, 0x64, 0x50, - /* (2^231)P */ 0xfc, 0xb2, 0x7e, 0xd3, 0xcf, 0xec, 0x20, 0x70, 0xfc, 0x25, 0x0d, 0xd9, 0x3e, 0xea, 0x31, 0x1f, 0x34, 0xbb, 0xa1, 0xdf, 0x7b, 0x0d, 0x93, 0x1b, 0x44, 0x30, 0x11, 0x48, 0x7a, 0x46, 0x44, 0x53, - /* (2^232)P */ 0xfb, 0x6d, 0x5e, 0xf2, 0x70, 0x31, 0x07, 0x70, 0xc8, 0x4c, 0x11, 0x50, 0x1a, 0xdc, 0x85, 0xe3, 0x00, 0x4f, 0xfc, 0xc8, 0x8a, 0x69, 0x48, 0x23, 0xd8, 0x40, 0xdd, 0x84, 0x52, 0xa5, 0x77, 0x2a, - /* (2^233)P */ 0xe4, 0x6c, 0x8c, 0xc9, 0xe0, 0xaf, 0x06, 0xfe, 0xe4, 0xd6, 0xdf, 0xdd, 0x96, 0xdf, 0x35, 0xc2, 0xd3, 0x1e, 0xbf, 0x33, 0x1e, 0xd0, 0x28, 0x14, 0xaf, 0xbd, 0x00, 0x93, 0xec, 0x68, 0x57, 0x78, - /* (2^234)P */ 0x3b, 0xb6, 0xde, 0x91, 0x7a, 0xe5, 0x02, 0x97, 0x80, 0x8b, 0xce, 0xe5, 0xbf, 0xb8, 0xbd, 0x61, 0xac, 0x58, 0x1d, 0x3d, 0x6f, 0x42, 0x5b, 0x64, 0xbc, 0x57, 0xa5, 0x27, 0x22, 0xa8, 0x04, 0x48, - /* (2^235)P */ 0x01, 0x26, 0x4d, 0xb4, 0x8a, 0x04, 0x57, 0x8e, 0x35, 0x69, 0x3a, 0x4b, 0x1a, 0x50, 0xd6, 0x68, 0x93, 0xc2, 0xe1, 0xf9, 0xc3, 0x9e, 0x9c, 0xc3, 0xe2, 0x63, 0xde, 0xd4, 0x57, 0xf2, 0x72, 0x41, - /* (2^236)P */ 0x01, 0x64, 0x0c, 0x33, 0x50, 0xb4, 0x68, 0xd3, 0x91, 0x23, 0x8f, 0x41, 0x17, 0x30, 0x0d, 0x04, 0x0d, 0xd9, 0xb7, 0x90, 0x60, 0xbb, 0x34, 0x2c, 0x1f, 0xd5, 0xdf, 0x8f, 0x22, 0x49, 0xf6, 0x16, - /* (2^237)P */ 0xf5, 0x8e, 0x92, 0x2b, 0x8e, 0x81, 0xa6, 0xbe, 0x72, 0x1e, 0xc1, 0xcd, 0x91, 0xcf, 0x8c, 0xe2, 0xcd, 0x36, 0x7a, 0xe7, 0x68, 0xaa, 0x4a, 0x59, 0x0f, 0xfd, 0x7f, 0x6c, 0x80, 0x34, 0x30, 0x31, - /* (2^238)P */ 0x65, 0xbd, 0x49, 0x22, 0xac, 0x27, 0x9d, 0x8a, 0x12, 0x95, 0x8e, 0x01, 0x64, 0xb4, 0xa3, 0x19, 0xc7, 0x7e, 0xb3, 0x52, 0xf3, 0xcf, 0x6c, 0xc2, 0x21, 0x7b, 0x79, 0x1d, 0x34, 0x68, 0x6f, 0x05, - /* (2^239)P */ 0x27, 0x23, 0xfd, 0x7e, 0x75, 0xd6, 0x79, 0x5e, 0x15, 0xfe, 0x3a, 0x55, 0xb6, 0xbc, 0xbd, 0xfa, 0x60, 0x5a, 0xaf, 0x6e, 0x2c, 0x22, 0xe7, 0xd3, 0x3b, 0x74, 0xae, 0x4d, 0x6d, 0xc7, 0x46, 0x70, - /* (2^240)P */ 0x55, 0x4a, 0x8d, 0xb1, 0x72, 0xe8, 0x0b, 0x66, 0x96, 0x14, 0x4e, 0x57, 0x18, 0x25, 0x99, 0x19, 0xbb, 0xdc, 0x2b, 0x30, 0x3a, 0x05, 0x03, 0xc1, 0x8e, 0x8e, 0x21, 0x0b, 0x80, 0xe9, 0xd8, 0x3e, - /* (2^241)P */ 0x3e, 0xe0, 0x75, 0xfa, 0x39, 0x92, 0x0b, 0x7b, 0x83, 0xc0, 0x33, 0x46, 0x68, 0xfb, 0xe9, 0xef, 0x93, 0x77, 0x1a, 0x39, 0xbe, 0x5f, 0xa3, 0x98, 0x34, 0xfe, 0xd0, 0xe2, 0x0f, 0x51, 0x65, 0x60, - /* (2^242)P */ 0x0c, 0xad, 0xab, 0x48, 0x85, 0x66, 0xcb, 0x55, 0x27, 0xe5, 0x87, 0xda, 0x48, 0x45, 0x58, 0xb4, 0xdd, 0xc1, 0x07, 0x01, 0xea, 0xec, 0x43, 0x2c, 0x35, 0xde, 0x72, 0x93, 0x80, 0x28, 0x60, 0x52, - /* (2^243)P */ 0x1f, 0x3b, 0x21, 0xf9, 0x6a, 0xc5, 0x15, 0x34, 0xdb, 0x98, 0x7e, 0x01, 0x4d, 0x1a, 0xee, 0x5b, 0x9b, 0x70, 0xcf, 0xb5, 0x05, 0xb1, 0xf6, 0x13, 0xb6, 0x9a, 0xb2, 0x82, 0x34, 0x0e, 0xf2, 0x5f, - /* (2^244)P */ 0x90, 0x6c, 0x2e, 0xcc, 0x75, 0x9c, 0xa2, 0x0a, 0x06, 0xe2, 0x70, 0x3a, 0xca, 0x73, 0x7d, 0xfc, 0x15, 0xc5, 0xb5, 0xc4, 0x8f, 0xc3, 0x9f, 0x89, 0x07, 0xc2, 0xff, 0x24, 0xb1, 0x86, 0x03, 0x25, - /* (2^245)P */ 0x56, 0x2b, 0x3d, 0xae, 0xd5, 0x28, 0xea, 0x54, 0xce, 0x60, 0xde, 0xd6, 0x9d, 0x14, 0x13, 0x99, 0xc1, 0xd6, 0x06, 0x8f, 0xc5, 0x4f, 0x69, 0x16, 0xc7, 0x8f, 0x01, 0xeb, 0x75, 0x39, 0xb2, 0x46, - /* (2^246)P */ 0xe2, 0xb4, 0xb7, 0xb4, 0x0f, 0x6a, 0x0a, 0x47, 0xde, 0x53, 0x72, 0x8f, 0x5a, 0x47, 0x92, 0x5d, 0xdb, 0x3a, 0xbd, 0x2f, 0xb5, 0xe5, 0xee, 0xab, 0x68, 0x69, 0x80, 0xa0, 0x01, 0x08, 0xa2, 0x7f, - /* (2^247)P */ 0xd2, 0x14, 0x77, 0x9f, 0xf1, 0xfa, 0xf3, 0x76, 0xc3, 0x60, 0x46, 0x2f, 0xc1, 0x40, 0xe8, 0xb3, 0x4e, 0x74, 0x12, 0xf2, 0x8d, 0xcd, 0xb4, 0x0f, 0xd2, 0x2d, 0x3a, 0x1d, 0x25, 0x5a, 0x06, 0x4b, - /* (2^248)P */ 0x4a, 0xcd, 0x77, 0x3d, 0x38, 0xde, 0xeb, 0x5c, 0xb1, 0x9c, 0x2c, 0x88, 0xdf, 0x39, 0xdf, 0x6a, 0x59, 0xf7, 0x9a, 0xb0, 0x2e, 0x24, 0xdd, 0xa2, 0x22, 0x64, 0x5f, 0x0e, 0xe5, 0xc0, 0x47, 0x31, - /* (2^249)P */ 0xdb, 0x50, 0x13, 0x1d, 0x10, 0xa5, 0x4c, 0x16, 0x62, 0xc9, 0x3f, 0xc3, 0x79, 0x34, 0xd1, 0xf8, 0x08, 0xda, 0xe5, 0x13, 0x4d, 0xce, 0x40, 0xe6, 0xba, 0xf8, 0x61, 0x50, 0xc4, 0xe0, 0xde, 0x4b, - /* (2^250)P */ 0xc9, 0xb1, 0xed, 0xa4, 0xc1, 0x6d, 0xc4, 0xd7, 0x8a, 0xd9, 0x7f, 0x43, 0xb6, 0xd7, 0x14, 0x55, 0x0b, 0xc0, 0xa1, 0xb2, 0x6b, 0x2f, 0x94, 0x58, 0x0e, 0x71, 0x70, 0x1d, 0xab, 0xb2, 0xff, 0x2d, - /* (2^251)P */ 0x68, 0x6d, 0x8b, 0xc1, 0x2f, 0xcf, 0xdf, 0xcc, 0x67, 0x61, 0x80, 0xb7, 0xa8, 0xcb, 0xeb, 0xa8, 0xe3, 0x37, 0x29, 0x5e, 0xf9, 0x97, 0x06, 0x98, 0x8c, 0x6e, 0x12, 0xd0, 0x1c, 0xba, 0xfb, 0x02, - /* (2^252)P */ 0x65, 0x45, 0xff, 0xad, 0x60, 0xc3, 0x98, 0xcb, 0x19, 0x15, 0xdb, 0x4b, 0xd2, 0x01, 0x71, 0x44, 0xd5, 0x15, 0xfb, 0x75, 0x74, 0xc8, 0xc4, 0x98, 0x7d, 0xa2, 0x22, 0x6e, 0x6d, 0xc7, 0xf8, 0x05, - /* (2^253)P */ 0x94, 0xf4, 0xb9, 0xfe, 0xdf, 0xe5, 0x69, 0xab, 0x75, 0x6b, 0x40, 0x18, 0x9d, 0xc7, 0x09, 0xae, 0x1d, 0x2d, 0xa4, 0x94, 0xfb, 0x45, 0x9b, 0x19, 0x84, 0xfa, 0x2a, 0xae, 0xeb, 0x0a, 0x71, 0x79, - /* (2^254)P */ 0xdf, 0xd2, 0x34, 0xf3, 0xa7, 0xed, 0xad, 0xa6, 0xb4, 0x57, 0x2a, 0xaf, 0x51, 0x9c, 0xde, 0x7b, 0xa8, 0xea, 0xdc, 0x86, 0x4f, 0xc6, 0x8f, 0xa9, 0x7b, 0xd0, 0x0e, 0xc2, 0x35, 0x03, 0xbe, 0x6b, - /* (2^255)P */ 0x44, 0x43, 0x98, 0x53, 0xbe, 0xdc, 0x7f, 0x66, 0xa8, 0x49, 0x59, 0x00, 0x1c, 0xbc, 0x72, 0x07, 0x8e, 0xd6, 0xbe, 0x4e, 0x9f, 0xa4, 0x07, 0xba, 0xbf, 0x30, 0xdf, 0xba, 0x85, 0xb0, 0xa7, 0x1f, -} diff --git a/vendor/github.com/cloudflare/circl/dh/x448/curve.go b/vendor/github.com/cloudflare/circl/dh/x448/curve.go deleted file mode 100644 index d59564e4..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/curve.go +++ /dev/null @@ -1,104 +0,0 @@ -package x448 - -import ( - fp "github.com/cloudflare/circl/math/fp448" -) - -// ladderJoye calculates a fixed-point multiplication with the generator point. -// The algorithm is the right-to-left Joye's ladder as described -// in "How to precompute a ladder" in SAC'2017. -func ladderJoye(k *Key) { - w := [5]fp.Elt{} // [mu,x1,z1,x2,z2] order must be preserved. - w[1] = fp.Elt{ // x1 = S - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - } - fp.SetOne(&w[2]) // z1 = 1 - w[3] = fp.Elt{ // x2 = G-S - 0x20, 0x27, 0x9d, 0xc9, 0x7d, 0x19, 0xb1, 0xac, - 0xf8, 0xba, 0x69, 0x1c, 0xff, 0x33, 0xac, 0x23, - 0x51, 0x1b, 0xce, 0x3a, 0x64, 0x65, 0xbd, 0xf1, - 0x23, 0xf8, 0xc1, 0x84, 0x9d, 0x45, 0x54, 0x29, - 0x67, 0xb9, 0x81, 0x1c, 0x03, 0xd1, 0xcd, 0xda, - 0x7b, 0xeb, 0xff, 0x1a, 0x88, 0x03, 0xcf, 0x3a, - 0x42, 0x44, 0x32, 0x01, 0x25, 0xb7, 0xfa, 0xf0, - } - fp.SetOne(&w[4]) // z2 = 1 - - const n = 448 - const h = 2 - swap := uint(1) - for s := 0; s < n-h; s++ { - i := (s + h) / 8 - j := (s + h) % 8 - bit := uint((k[i] >> uint(j)) & 1) - copy(w[0][:], tableGenerator[s*Size:(s+1)*Size]) - diffAdd(&w, swap^bit) - swap = bit - } - for s := 0; s < h; s++ { - double(&w[1], &w[2]) - } - toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) -} - -// ladderMontgomery calculates a generic scalar point multiplication -// The algorithm implemented is the left-to-right Montgomery's ladder. -func ladderMontgomery(k, xP *Key) { - w := [5]fp.Elt{} // [x1, x2, z2, x3, z3] order must be preserved. - w[0] = *(*fp.Elt)(xP) // x1 = xP - fp.SetOne(&w[1]) // x2 = 1 - w[3] = *(*fp.Elt)(xP) // x3 = xP - fp.SetOne(&w[4]) // z3 = 1 - - move := uint(0) - for s := 448 - 1; s >= 0; s-- { - i := s / 8 - j := s % 8 - bit := uint((k[i] >> uint(j)) & 1) - ladderStep(&w, move^bit) - move = bit - } - toAffine((*[fp.Size]byte)(k), &w[1], &w[2]) -} - -func toAffine(k *[fp.Size]byte, x, z *fp.Elt) { - fp.Inv(z, z) - fp.Mul(x, x, z) - _ = fp.ToBytes(k[:], x) -} - -var lowOrderPoints = [3]fp.Elt{ - { /* (0,_,1) point of order 2 on Curve448 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - { /* (1,_,1) a point of order 4 on the twist of Curve448 */ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - { /* (-1,_,1) point of order 4 on Curve448 */ - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, -} diff --git a/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go b/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go deleted file mode 100644 index a0622666..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -package x448 - -import ( - fp "github.com/cloudflare/circl/math/fp448" - "golang.org/x/sys/cpu" -) - -var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX - -var _ = hasBmi2Adx - -func double(x, z *fp.Elt) { doubleAmd64(x, z) } -func diffAdd(w *[5]fp.Elt, b uint) { diffAddAmd64(w, b) } -func ladderStep(w *[5]fp.Elt, b uint) { ladderStepAmd64(w, b) } -func mulA24(z, x *fp.Elt) { mulA24Amd64(z, x) } - -//go:noescape -func doubleAmd64(x, z *fp.Elt) - -//go:noescape -func diffAddAmd64(w *[5]fp.Elt, b uint) - -//go:noescape -func ladderStepAmd64(w *[5]fp.Elt, b uint) - -//go:noescape -func mulA24Amd64(z, x *fp.Elt) diff --git a/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h b/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h deleted file mode 100644 index 8c1ae4d0..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h +++ /dev/null @@ -1,111 +0,0 @@ -#define ladderStepLeg \ - addSub(x2,z2) \ - addSub(x3,z3) \ - integerMulLeg(b0,x2,z3) \ - integerMulLeg(b1,x3,z2) \ - reduceFromDoubleLeg(t0,b0) \ - reduceFromDoubleLeg(t1,b1) \ - addSub(t0,t1) \ - cselect(x2,x3,regMove) \ - cselect(z2,z3,regMove) \ - integerSqrLeg(b0,t0) \ - integerSqrLeg(b1,t1) \ - reduceFromDoubleLeg(x3,b0) \ - reduceFromDoubleLeg(z3,b1) \ - integerMulLeg(b0,x1,z3) \ - reduceFromDoubleLeg(z3,b0) \ - integerSqrLeg(b0,x2) \ - integerSqrLeg(b1,z2) \ - reduceFromDoubleLeg(x2,b0) \ - reduceFromDoubleLeg(z2,b1) \ - subtraction(t0,x2,z2) \ - multiplyA24Leg(t1,t0) \ - additionLeg(t1,t1,z2) \ - integerMulLeg(b0,x2,z2) \ - integerMulLeg(b1,t0,t1) \ - reduceFromDoubleLeg(x2,b0) \ - reduceFromDoubleLeg(z2,b1) - -#define ladderStepBmi2Adx \ - addSub(x2,z2) \ - addSub(x3,z3) \ - integerMulAdx(b0,x2,z3) \ - integerMulAdx(b1,x3,z2) \ - reduceFromDoubleAdx(t0,b0) \ - reduceFromDoubleAdx(t1,b1) \ - addSub(t0,t1) \ - cselect(x2,x3,regMove) \ - cselect(z2,z3,regMove) \ - integerSqrAdx(b0,t0) \ - integerSqrAdx(b1,t1) \ - reduceFromDoubleAdx(x3,b0) \ - reduceFromDoubleAdx(z3,b1) \ - integerMulAdx(b0,x1,z3) \ - reduceFromDoubleAdx(z3,b0) \ - integerSqrAdx(b0,x2) \ - integerSqrAdx(b1,z2) \ - reduceFromDoubleAdx(x2,b0) \ - reduceFromDoubleAdx(z2,b1) \ - subtraction(t0,x2,z2) \ - multiplyA24Adx(t1,t0) \ - additionAdx(t1,t1,z2) \ - integerMulAdx(b0,x2,z2) \ - integerMulAdx(b1,t0,t1) \ - reduceFromDoubleAdx(x2,b0) \ - reduceFromDoubleAdx(z2,b1) - -#define difAddLeg \ - addSub(x1,z1) \ - integerMulLeg(b0,z1,ui) \ - reduceFromDoubleLeg(z1,b0) \ - addSub(x1,z1) \ - integerSqrLeg(b0,x1) \ - integerSqrLeg(b1,z1) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) \ - integerMulLeg(b0,x1,z2) \ - integerMulLeg(b1,z1,x2) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) - -#define difAddBmi2Adx \ - addSub(x1,z1) \ - integerMulAdx(b0,z1,ui) \ - reduceFromDoubleAdx(z1,b0) \ - addSub(x1,z1) \ - integerSqrAdx(b0,x1) \ - integerSqrAdx(b1,z1) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) \ - integerMulAdx(b0,x1,z2) \ - integerMulAdx(b1,z1,x2) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) - -#define doubleLeg \ - addSub(x1,z1) \ - integerSqrLeg(b0,x1) \ - integerSqrLeg(b1,z1) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) \ - subtraction(t0,x1,z1) \ - multiplyA24Leg(t1,t0) \ - additionLeg(t1,t1,z1) \ - integerMulLeg(b0,x1,z1) \ - integerMulLeg(b1,t0,t1) \ - reduceFromDoubleLeg(x1,b0) \ - reduceFromDoubleLeg(z1,b1) - -#define doubleBmi2Adx \ - addSub(x1,z1) \ - integerSqrAdx(b0,x1) \ - integerSqrAdx(b1,z1) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) \ - subtraction(t0,x1,z1) \ - multiplyA24Adx(t1,t0) \ - additionAdx(t1,t1,z1) \ - integerMulAdx(b0,x1,z1) \ - integerMulAdx(b1,t0,t1) \ - reduceFromDoubleAdx(x1,b0) \ - reduceFromDoubleAdx(z1,b1) diff --git a/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s b/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s deleted file mode 100644 index ed33ba3d..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s +++ /dev/null @@ -1,194 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -#include "textflag.h" - -// Depends on circl/math/fp448 package -#include "../../math/fp448/fp_amd64.h" -#include "curve_amd64.h" - -// CTE_A24 is (A+2)/4 from Curve448 -#define CTE_A24 39082 - -#define Size 56 - -// multiplyA24Leg multiplies x times CTE_A24 and stores in z -// Uses: AX, DX, R8-R15, FLAGS -// Instr: x86_64, cmov, adx -#define multiplyA24Leg(z,x) \ - MOVQ $CTE_A24, R15; \ - MOVQ 0+x, AX; MULQ R15; MOVQ AX, R8; ;;;;;;;;;;;; MOVQ DX, R9; \ - MOVQ 8+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \ - MOVQ 16+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \ - MOVQ 24+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \ - MOVQ 32+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \ - MOVQ 40+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \ - MOVQ 48+x, AX; MULQ R15; ADDQ AX, R14; ADCQ $0, DX; \ - MOVQ DX, AX; \ - SHLQ $32, AX; \ - ADDQ DX, R8; MOVQ $0, DX; \ - ADCQ $0, R9; \ - ADCQ $0, R10; \ - ADCQ AX, R11; \ - ADCQ $0, R12; \ - ADCQ $0, R13; \ - ADCQ $0, R14; \ - ADCQ $0, DX; \ - MOVQ DX, AX; \ - SHLQ $32, AX; \ - ADDQ DX, R8; \ - ADCQ $0, R9; \ - ADCQ $0, R10; \ - ADCQ AX, R11; \ - ADCQ $0, R12; \ - ADCQ $0, R13; \ - ADCQ $0, R14; \ - MOVQ R8, 0+z; \ - MOVQ R9, 8+z; \ - MOVQ R10, 16+z; \ - MOVQ R11, 24+z; \ - MOVQ R12, 32+z; \ - MOVQ R13, 40+z; \ - MOVQ R14, 48+z; - -// multiplyA24Adx multiplies x times CTE_A24 and stores in z -// Uses: AX, DX, R8-R14, FLAGS -// Instr: x86_64, bmi2 -#define multiplyA24Adx(z,x) \ - MOVQ $CTE_A24, DX; \ - MULXQ 0+x, R8, R9; \ - MULXQ 8+x, AX, R10; ADDQ AX, R9; \ - MULXQ 16+x, AX, R11; ADCQ AX, R10; \ - MULXQ 24+x, AX, R12; ADCQ AX, R11; \ - MULXQ 32+x, AX, R13; ADCQ AX, R12; \ - MULXQ 40+x, AX, R14; ADCQ AX, R13; \ - MULXQ 48+x, AX, DX; ADCQ AX, R14; \ - ;;;;;;;;;;;;;;;;;;;; ADCQ $0, DX; \ - MOVQ DX, AX; \ - SHLQ $32, AX; \ - ADDQ DX, R8; MOVQ $0, DX; \ - ADCQ $0, R9; \ - ADCQ $0, R10; \ - ADCQ AX, R11; \ - ADCQ $0, R12; \ - ADCQ $0, R13; \ - ADCQ $0, R14; \ - ADCQ $0, DX; \ - MOVQ DX, AX; \ - SHLQ $32, AX; \ - ADDQ DX, R8; \ - ADCQ $0, R9; \ - ADCQ $0, R10; \ - ADCQ AX, R11; \ - ADCQ $0, R12; \ - ADCQ $0, R13; \ - ADCQ $0, R14; \ - MOVQ R8, 0+z; \ - MOVQ R9, 8+z; \ - MOVQ R10, 16+z; \ - MOVQ R11, 24+z; \ - MOVQ R12, 32+z; \ - MOVQ R13, 40+z; \ - MOVQ R14, 48+z; - -#define mulA24Legacy \ - multiplyA24Leg(0(DI),0(SI)) -#define mulA24Bmi2Adx \ - multiplyA24Adx(0(DI),0(SI)) - -// func mulA24Amd64(z, x *fp448.Elt) -TEXT ·mulA24Amd64(SB),NOSPLIT,$0-16 - MOVQ z+0(FP), DI - MOVQ x+8(FP), SI - CHECK_BMI2ADX(LMA24, mulA24Legacy, mulA24Bmi2Adx) - -// func ladderStepAmd64(w *[5]fp448.Elt, b uint) -// ladderStepAmd64 calculates a point addition and doubling as follows: -// (x2,z2) = 2*(x2,z2) and (x3,z3) = (x2,z2)+(x3,z3) using as a difference (x1,-). -// w = {x1,x2,z2,x3,z4} are five fp255.Elt of 56 bytes. -// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and -// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. -TEXT ·ladderStepAmd64(SB),NOSPLIT,$336-16 - // Parameters - #define regWork DI - #define regMove SI - #define x1 0*Size(regWork) - #define x2 1*Size(regWork) - #define z2 2*Size(regWork) - #define x3 3*Size(regWork) - #define z3 4*Size(regWork) - // Local variables - #define t0 0*Size(SP) - #define t1 1*Size(SP) - #define b0 2*Size(SP) - #define b1 4*Size(SP) - MOVQ w+0(FP), regWork - MOVQ b+8(FP), regMove - CHECK_BMI2ADX(LLADSTEP, ladderStepLeg, ladderStepBmi2Adx) - #undef regWork - #undef regMove - #undef x1 - #undef x2 - #undef z2 - #undef x3 - #undef z3 - #undef t0 - #undef t1 - #undef b0 - #undef b1 - -// func diffAddAmd64(work *[5]fp.Elt, swap uint) -// diffAddAmd64 calculates a differential point addition using a precomputed point. -// (x1,z1) = (x1,z1)+(mu) using a difference point (x2,z2) -// work = {mu,x1,z1,x2,z2} are five fp448.Elt of 56 bytes, and -// stack = (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. -// This is Equation 7 at https://eprint.iacr.org/2017/264. -TEXT ·diffAddAmd64(SB),NOSPLIT,$224-16 - // Parameters - #define regWork DI - #define regSwap SI - #define ui 0*Size(regWork) - #define x1 1*Size(regWork) - #define z1 2*Size(regWork) - #define x2 3*Size(regWork) - #define z2 4*Size(regWork) - // Local variables - #define b0 0*Size(SP) - #define b1 2*Size(SP) - MOVQ w+0(FP), regWork - MOVQ b+8(FP), regSwap - cswap(x1,x2,regSwap) - cswap(z1,z2,regSwap) - CHECK_BMI2ADX(LDIFADD, difAddLeg, difAddBmi2Adx) - #undef regWork - #undef regSwap - #undef ui - #undef x1 - #undef z1 - #undef x2 - #undef z2 - #undef b0 - #undef b1 - -// func doubleAmd64(x, z *fp448.Elt) -// doubleAmd64 calculates a point doubling (x1,z1) = 2*(x1,z1). -// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and -// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes. -TEXT ·doubleAmd64(SB),NOSPLIT,$336-16 - // Parameters - #define x1 0(DI) - #define z1 0(SI) - // Local variables - #define t0 0*Size(SP) - #define t1 1*Size(SP) - #define b0 2*Size(SP) - #define b1 4*Size(SP) - MOVQ x+0(FP), DI - MOVQ z+8(FP), SI - CHECK_BMI2ADX(LDOUB,doubleLeg,doubleBmi2Adx) - #undef x1 - #undef z1 - #undef t0 - #undef t1 - #undef b0 - #undef b1 diff --git a/vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go b/vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go deleted file mode 100644 index b0b65ccf..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go +++ /dev/null @@ -1,100 +0,0 @@ -package x448 - -import ( - "encoding/binary" - "math/bits" - - "github.com/cloudflare/circl/math/fp448" -) - -func doubleGeneric(x, z *fp448.Elt) { - t0, t1 := &fp448.Elt{}, &fp448.Elt{} - fp448.AddSub(x, z) - fp448.Sqr(x, x) - fp448.Sqr(z, z) - fp448.Sub(t0, x, z) - mulA24Generic(t1, t0) - fp448.Add(t1, t1, z) - fp448.Mul(x, x, z) - fp448.Mul(z, t0, t1) -} - -func diffAddGeneric(w *[5]fp448.Elt, b uint) { - mu, x1, z1, x2, z2 := &w[0], &w[1], &w[2], &w[3], &w[4] - fp448.Cswap(x1, x2, b) - fp448.Cswap(z1, z2, b) - fp448.AddSub(x1, z1) - fp448.Mul(z1, z1, mu) - fp448.AddSub(x1, z1) - fp448.Sqr(x1, x1) - fp448.Sqr(z1, z1) - fp448.Mul(x1, x1, z2) - fp448.Mul(z1, z1, x2) -} - -func ladderStepGeneric(w *[5]fp448.Elt, b uint) { - x1, x2, z2, x3, z3 := &w[0], &w[1], &w[2], &w[3], &w[4] - t0 := &fp448.Elt{} - t1 := &fp448.Elt{} - fp448.AddSub(x2, z2) - fp448.AddSub(x3, z3) - fp448.Mul(t0, x2, z3) - fp448.Mul(t1, x3, z2) - fp448.AddSub(t0, t1) - fp448.Cmov(x2, x3, b) - fp448.Cmov(z2, z3, b) - fp448.Sqr(x3, t0) - fp448.Sqr(z3, t1) - fp448.Mul(z3, x1, z3) - fp448.Sqr(x2, x2) - fp448.Sqr(z2, z2) - fp448.Sub(t0, x2, z2) - mulA24Generic(t1, t0) - fp448.Add(t1, t1, z2) - fp448.Mul(x2, x2, z2) - fp448.Mul(z2, t0, t1) -} - -func mulA24Generic(z, x *fp448.Elt) { - const A24 = 39082 - const n = 8 - var xx [7]uint64 - for i := range xx { - xx[i] = binary.LittleEndian.Uint64(x[i*n : (i+1)*n]) - } - h0, l0 := bits.Mul64(xx[0], A24) - h1, l1 := bits.Mul64(xx[1], A24) - h2, l2 := bits.Mul64(xx[2], A24) - h3, l3 := bits.Mul64(xx[3], A24) - h4, l4 := bits.Mul64(xx[4], A24) - h5, l5 := bits.Mul64(xx[5], A24) - h6, l6 := bits.Mul64(xx[6], A24) - - l1, c0 := bits.Add64(h0, l1, 0) - l2, c1 := bits.Add64(h1, l2, c0) - l3, c2 := bits.Add64(h2, l3, c1) - l4, c3 := bits.Add64(h3, l4, c2) - l5, c4 := bits.Add64(h4, l5, c3) - l6, c5 := bits.Add64(h5, l6, c4) - l7, _ := bits.Add64(h6, 0, c5) - - l0, c0 = bits.Add64(l0, l7, 0) - l1, c1 = bits.Add64(l1, 0, c0) - l2, c2 = bits.Add64(l2, 0, c1) - l3, c3 = bits.Add64(l3, l7<<32, c2) - l4, c4 = bits.Add64(l4, 0, c3) - l5, c5 = bits.Add64(l5, 0, c4) - l6, l7 = bits.Add64(l6, 0, c5) - - xx[0], c0 = bits.Add64(l0, l7, 0) - xx[1], c1 = bits.Add64(l1, 0, c0) - xx[2], c2 = bits.Add64(l2, 0, c1) - xx[3], c3 = bits.Add64(l3, l7<<32, c2) - xx[4], c4 = bits.Add64(l4, 0, c3) - xx[5], c5 = bits.Add64(l5, 0, c4) - xx[6], _ = bits.Add64(l6, 0, c5) - - for i := range xx { - binary.LittleEndian.PutUint64(z[i*n:(i+1)*n], xx[i]) - } -} diff --git a/vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go b/vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go deleted file mode 100644 index 3755b7c8..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !amd64 || purego -// +build !amd64 purego - -package x448 - -import fp "github.com/cloudflare/circl/math/fp448" - -func double(x, z *fp.Elt) { doubleGeneric(x, z) } -func diffAdd(w *[5]fp.Elt, b uint) { diffAddGeneric(w, b) } -func ladderStep(w *[5]fp.Elt, b uint) { ladderStepGeneric(w, b) } -func mulA24(z, x *fp.Elt) { mulA24Generic(z, x) } diff --git a/vendor/github.com/cloudflare/circl/dh/x448/doc.go b/vendor/github.com/cloudflare/circl/dh/x448/doc.go deleted file mode 100644 index c02904fe..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Package x448 provides Diffie-Hellman functions as specified in RFC-7748. - -Validation of public keys. - -The Diffie-Hellman function, as described in RFC-7748 [1], works for any -public key. However, if a different protocol requires contributory -behaviour [2,3], then the public keys must be validated against low-order -points [3,4]. To do that, the Shared function performs this validation -internally and returns false when the public key is invalid (i.e., it -is a low-order point). - -References: - - [1] RFC7748 by Langley, Hamburg, Turner (https://rfc-editor.org/rfc/rfc7748.txt) - - [2] Curve25519 by Bernstein (https://cr.yp.to/ecdh.html) - - [3] Bernstein (https://cr.yp.to/ecdh.html#validate) - - [4] Cremers&Jackson (https://eprint.iacr.org/2019/526) -*/ -package x448 diff --git a/vendor/github.com/cloudflare/circl/dh/x448/key.go b/vendor/github.com/cloudflare/circl/dh/x448/key.go deleted file mode 100644 index 2fdde511..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/key.go +++ /dev/null @@ -1,46 +0,0 @@ -package x448 - -import ( - "crypto/subtle" - - fp "github.com/cloudflare/circl/math/fp448" -) - -// Size is the length in bytes of a X448 key. -const Size = 56 - -// Key represents a X448 key. -type Key [Size]byte - -func (k *Key) clamp(in *Key) *Key { - *k = *in - k[0] &= 252 - k[55] |= 128 - return k -} - -// isValidPubKey verifies if the public key is not a low-order point. -func (k *Key) isValidPubKey() bool { - fp.Modp((*fp.Elt)(k)) - var isLowOrder int - for _, P := range lowOrderPoints { - isLowOrder |= subtle.ConstantTimeCompare(P[:], k[:]) - } - return isLowOrder == 0 -} - -// KeyGen obtains a public key given a secret key. -func KeyGen(public, secret *Key) { - ladderJoye(public.clamp(secret)) -} - -// Shared calculates Alice's shared key from Alice's secret key and Bob's -// public key returning true on success. A failure case happens when the public -// key is a low-order point, thus the shared key is all-zeros and the function -// returns false. -func Shared(shared, secret, public *Key) bool { - validPk := *public - ok := validPk.isValidPubKey() - ladderMontgomery(shared.clamp(secret), &validPk) - return ok -} diff --git a/vendor/github.com/cloudflare/circl/dh/x448/table.go b/vendor/github.com/cloudflare/circl/dh/x448/table.go deleted file mode 100644 index eef53c30..00000000 --- a/vendor/github.com/cloudflare/circl/dh/x448/table.go +++ /dev/null @@ -1,460 +0,0 @@ -package x448 - -import fp "github.com/cloudflare/circl/math/fp448" - -// tableGenerator contains the set of points: -// -// t[i] = (xi+1)/(xi-1), -// -// where (xi,yi) = 2^iG and G is the generator point -// Size = (448)*(448/8) = 25088 bytes. -var tableGenerator = [448 * fp.Size]byte{ - /* (2^ 0)P */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - /* (2^ 1)P */ 0x37, 0xfa, 0xaa, 0x0d, 0x86, 0xa6, 0x24, 0xe9, 0x6c, 0x95, 0x08, 0x34, 0xba, 0x1a, 0x81, 0x3a, 0xae, 0x01, 0xa5, 0xa7, 0x05, 0x85, 0x96, 0x00, 0x06, 0x5a, 0xd7, 0xff, 0xee, 0x8e, 0x8f, 0x94, 0xd2, 0xdc, 0xd7, 0xfc, 0xe7, 0xe5, 0x99, 0x1d, 0x05, 0x46, 0x43, 0xe8, 0xbc, 0x12, 0xb7, 0xeb, 0x30, 0x5e, 0x7a, 0x85, 0x68, 0xed, 0x9d, 0x28, - /* (2^ 2)P */ 0xf1, 0x7d, 0x08, 0x2b, 0x32, 0x4a, 0x62, 0x80, 0x36, 0xe7, 0xa4, 0x76, 0x5a, 0x2a, 0x1e, 0xf7, 0x9e, 0x3c, 0x40, 0x46, 0x9a, 0x1b, 0x61, 0xc1, 0xbf, 0x1a, 0x1b, 0xae, 0x91, 0x80, 0xa3, 0x76, 0x6c, 0xd4, 0x8f, 0xa4, 0xee, 0x26, 0x39, 0x23, 0xa4, 0x80, 0xf4, 0x66, 0x92, 0xe4, 0xe1, 0x18, 0x76, 0xc5, 0xe2, 0x19, 0x87, 0xd5, 0xc3, 0xe8, - /* (2^ 3)P */ 0xfb, 0xc9, 0xf0, 0x07, 0xf2, 0x93, 0xd8, 0x50, 0x36, 0xed, 0xfb, 0xbd, 0xb2, 0xd3, 0xfc, 0xdf, 0xd5, 0x2a, 0x6e, 0x26, 0x09, 0xce, 0xd4, 0x07, 0x64, 0x9f, 0x40, 0x74, 0xad, 0x98, 0x2f, 0x1c, 0xb6, 0xdc, 0x2d, 0x42, 0xff, 0xbf, 0x97, 0xd8, 0xdb, 0xef, 0x99, 0xca, 0x73, 0x99, 0x1a, 0x04, 0x3b, 0x56, 0x2c, 0x1f, 0x87, 0x9d, 0x9f, 0x03, - /* (2^ 4)P */ 0x4c, 0x35, 0x97, 0xf7, 0x81, 0x2c, 0x84, 0xa6, 0xe0, 0xcb, 0xce, 0x37, 0x4c, 0x21, 0x1c, 0x67, 0xfa, 0xab, 0x18, 0x4d, 0xef, 0xd0, 0xf0, 0x44, 0xa9, 0xfb, 0xc0, 0x8e, 0xda, 0x57, 0xa1, 0xd8, 0xeb, 0x87, 0xf4, 0x17, 0xea, 0x66, 0x0f, 0x16, 0xea, 0xcd, 0x5f, 0x3e, 0x88, 0xea, 0x09, 0x68, 0x40, 0xdf, 0x43, 0xcc, 0x54, 0x61, 0x58, 0xaa, - /* (2^ 5)P */ 0x8d, 0xe7, 0x59, 0xd7, 0x5e, 0x63, 0x37, 0xa7, 0x3f, 0xd1, 0x49, 0x85, 0x01, 0xdd, 0x5e, 0xb3, 0xe6, 0x29, 0xcb, 0x25, 0x93, 0xdd, 0x08, 0x96, 0x83, 0x52, 0x76, 0x85, 0xf5, 0x5d, 0x02, 0xbf, 0xe9, 0x6d, 0x15, 0x27, 0xc1, 0x09, 0xd1, 0x14, 0x4d, 0x6e, 0xe8, 0xaf, 0x59, 0x58, 0x34, 0x9d, 0x2a, 0x99, 0x85, 0x26, 0xbe, 0x4b, 0x1e, 0xb9, - /* (2^ 6)P */ 0x8d, 0xce, 0x94, 0xe2, 0x18, 0x56, 0x0d, 0x82, 0x8e, 0xdf, 0x85, 0x01, 0x8f, 0x93, 0x3c, 0xc6, 0xbd, 0x61, 0xfb, 0xf4, 0x22, 0xc5, 0x16, 0x87, 0xd1, 0xb1, 0x9e, 0x09, 0xc5, 0x83, 0x2e, 0x4a, 0x07, 0x88, 0xee, 0xe0, 0x29, 0x8d, 0x2e, 0x1f, 0x88, 0xad, 0xfd, 0x18, 0x93, 0xb7, 0xed, 0x42, 0x86, 0x78, 0xf0, 0xb8, 0x70, 0xbe, 0x01, 0x67, - /* (2^ 7)P */ 0xdf, 0x62, 0x2d, 0x94, 0xc7, 0x35, 0x23, 0xda, 0x27, 0xbb, 0x2b, 0xdb, 0x30, 0x80, 0x68, 0x16, 0xa3, 0xae, 0xd7, 0xd2, 0xa7, 0x7c, 0xbf, 0x6a, 0x1d, 0x83, 0xde, 0x96, 0x0a, 0x43, 0xb6, 0x30, 0x37, 0xd6, 0xee, 0x63, 0x59, 0x9a, 0xbf, 0xa3, 0x30, 0x6c, 0xaf, 0x0c, 0xee, 0x3d, 0xcb, 0x35, 0x4b, 0x55, 0x5f, 0x84, 0x85, 0xcb, 0x4f, 0x1e, - /* (2^ 8)P */ 0x9d, 0x04, 0x68, 0x89, 0xa4, 0xa9, 0x0d, 0x87, 0xc1, 0x70, 0xf1, 0xeb, 0xfb, 0x47, 0x0a, 0xf0, 0xde, 0x67, 0xb7, 0x94, 0xcd, 0x36, 0x43, 0xa5, 0x49, 0x43, 0x67, 0xc3, 0xee, 0x3c, 0x6b, 0xec, 0xd0, 0x1a, 0xf4, 0xad, 0xef, 0x06, 0x4a, 0xe8, 0x46, 0x24, 0xd7, 0x93, 0xbf, 0xf0, 0xe3, 0x81, 0x61, 0xec, 0xea, 0x64, 0xfe, 0x67, 0xeb, 0xc7, - /* (2^ 9)P */ 0x95, 0x45, 0x79, 0xcf, 0x2c, 0xfd, 0x9b, 0xfe, 0x84, 0x46, 0x4b, 0x8f, 0xa1, 0xcf, 0xc3, 0x04, 0x94, 0x78, 0xdb, 0xc9, 0xa6, 0x01, 0x75, 0xa4, 0xb4, 0x93, 0x72, 0x43, 0xa7, 0x7d, 0xda, 0x31, 0x38, 0x54, 0xab, 0x4e, 0x3f, 0x89, 0xa6, 0xab, 0x57, 0xc0, 0x16, 0x65, 0xdb, 0x92, 0x96, 0xe4, 0xc8, 0xae, 0xe7, 0x4c, 0x7a, 0xeb, 0xbb, 0x5a, - /* (2^ 10)P */ 0xbe, 0xfe, 0x86, 0xc3, 0x97, 0xe0, 0x6a, 0x18, 0x20, 0x21, 0xca, 0x22, 0x55, 0xa1, 0xeb, 0xf5, 0x74, 0xe5, 0xc9, 0x59, 0xa7, 0x92, 0x65, 0x15, 0x08, 0x71, 0xd1, 0x09, 0x7e, 0x83, 0xfc, 0xbc, 0x5a, 0x93, 0x38, 0x0d, 0x43, 0x42, 0xfd, 0x76, 0x30, 0xe8, 0x63, 0x60, 0x09, 0x8d, 0x6c, 0xd3, 0xf8, 0x56, 0x3d, 0x68, 0x47, 0xab, 0xa0, 0x1d, - /* (2^ 11)P */ 0x38, 0x50, 0x1c, 0xb1, 0xac, 0x88, 0x8f, 0x38, 0xe3, 0x69, 0xe6, 0xfc, 0x4f, 0x8f, 0xe1, 0x9b, 0xb1, 0x1a, 0x09, 0x39, 0x19, 0xdf, 0xcd, 0x98, 0x7b, 0x64, 0x42, 0xf6, 0x11, 0xea, 0xc7, 0xe8, 0x92, 0x65, 0x00, 0x2c, 0x75, 0xb5, 0x94, 0x1e, 0x5b, 0xa6, 0x66, 0x81, 0x77, 0xf3, 0x39, 0x94, 0xac, 0xbd, 0xe4, 0x2a, 0x66, 0x84, 0x9c, 0x60, - /* (2^ 12)P */ 0xb5, 0xb6, 0xd9, 0x03, 0x67, 0xa4, 0xa8, 0x0a, 0x4a, 0x2b, 0x9d, 0xfa, 0x13, 0xe1, 0x99, 0x25, 0x4a, 0x5c, 0x67, 0xb9, 0xb2, 0xb7, 0xdd, 0x1e, 0xaf, 0xeb, 0x63, 0x41, 0xb6, 0xb9, 0xa0, 0x87, 0x0a, 0xe0, 0x06, 0x07, 0xaa, 0x97, 0xf8, 0xf9, 0x38, 0x4f, 0xdf, 0x0c, 0x40, 0x7c, 0xc3, 0x98, 0xa9, 0x74, 0xf1, 0x5d, 0xda, 0xd1, 0xc0, 0x0a, - /* (2^ 13)P */ 0xf2, 0x0a, 0xab, 0xab, 0x94, 0x50, 0xf0, 0xa3, 0x6f, 0xc6, 0x66, 0xba, 0xa6, 0xdc, 0x44, 0xdd, 0xd6, 0x08, 0xf4, 0xd3, 0xed, 0xb1, 0x40, 0x93, 0xee, 0xf6, 0xb8, 0x8e, 0xb4, 0x7c, 0xb9, 0x82, 0xc9, 0x9d, 0x45, 0x3b, 0x8e, 0x10, 0xcb, 0x70, 0x1e, 0xba, 0x3c, 0x62, 0x50, 0xda, 0xa9, 0x93, 0xb5, 0xd7, 0xd0, 0x6f, 0x29, 0x52, 0x95, 0xae, - /* (2^ 14)P */ 0x14, 0x68, 0x69, 0x23, 0xa8, 0x44, 0x87, 0x9e, 0x22, 0x91, 0xe8, 0x92, 0xdf, 0xf7, 0xae, 0xba, 0x1c, 0x96, 0xe1, 0xc3, 0x94, 0xed, 0x6c, 0x95, 0xae, 0x96, 0xa7, 0x15, 0x9f, 0xf1, 0x17, 0x11, 0x92, 0x42, 0xd5, 0xcd, 0x18, 0xe7, 0xa9, 0xb5, 0x2f, 0xcd, 0xde, 0x6c, 0xc9, 0x7d, 0xfc, 0x7e, 0xbd, 0x7f, 0x10, 0x3d, 0x01, 0x00, 0x8d, 0x95, - /* (2^ 15)P */ 0x3b, 0x76, 0x72, 0xae, 0xaf, 0x84, 0xf2, 0xf7, 0xd1, 0x6d, 0x13, 0x9c, 0x47, 0xe1, 0xb7, 0xa3, 0x19, 0x16, 0xee, 0x75, 0x45, 0xf6, 0x1a, 0x7b, 0x78, 0x49, 0x79, 0x05, 0x86, 0xf0, 0x7f, 0x9f, 0xfc, 0xc4, 0xbd, 0x86, 0xf3, 0x41, 0xa7, 0xfe, 0x01, 0xd5, 0x67, 0x16, 0x10, 0x5b, 0xa5, 0x16, 0xf3, 0x7f, 0x60, 0xce, 0xd2, 0x0c, 0x8e, 0x4b, - /* (2^ 16)P */ 0x4a, 0x07, 0x99, 0x4a, 0x0f, 0x74, 0x91, 0x14, 0x68, 0xb9, 0x48, 0xb7, 0x44, 0x77, 0x9b, 0x4a, 0xe0, 0x68, 0x0e, 0x43, 0x4d, 0x98, 0x98, 0xbf, 0xa8, 0x3a, 0xb7, 0x6d, 0x2a, 0x9a, 0x77, 0x5f, 0x62, 0xf5, 0x6b, 0x4a, 0xb7, 0x7d, 0xe5, 0x09, 0x6b, 0xc0, 0x8b, 0x9c, 0x88, 0x37, 0x33, 0xf2, 0x41, 0xac, 0x22, 0x1f, 0xcf, 0x3b, 0x82, 0x34, - /* (2^ 17)P */ 0x00, 0xc3, 0x78, 0x42, 0x32, 0x2e, 0xdc, 0xda, 0xb1, 0x96, 0x21, 0xa4, 0xe4, 0xbb, 0xe9, 0x9d, 0xbb, 0x0f, 0x93, 0xed, 0x26, 0x3d, 0xb5, 0xdb, 0x94, 0x31, 0x37, 0x07, 0xa2, 0xb2, 0xd5, 0x99, 0x0d, 0x93, 0xe1, 0xce, 0x3f, 0x0b, 0x96, 0x82, 0x47, 0xfe, 0x60, 0x6f, 0x8f, 0x61, 0x88, 0xd7, 0x05, 0x95, 0x0b, 0x46, 0x06, 0xb7, 0x32, 0x06, - /* (2^ 18)P */ 0x44, 0xf5, 0x34, 0xdf, 0x2f, 0x9c, 0x5d, 0x9f, 0x53, 0x5c, 0x42, 0x8f, 0xc9, 0xdc, 0xd8, 0x40, 0xa2, 0xe7, 0x6a, 0x4a, 0x05, 0xf7, 0x86, 0x77, 0x2b, 0xae, 0x37, 0xed, 0x48, 0xfb, 0xf7, 0x62, 0x7c, 0x17, 0x59, 0x92, 0x41, 0x61, 0x93, 0x38, 0x30, 0xd1, 0xef, 0x54, 0x54, 0x03, 0x17, 0x57, 0x91, 0x15, 0x11, 0x33, 0xb5, 0xfa, 0xfb, 0x17, - /* (2^ 19)P */ 0x29, 0xbb, 0xd4, 0xb4, 0x9c, 0xf1, 0x72, 0x94, 0xce, 0x6a, 0x29, 0xa8, 0x89, 0x18, 0x19, 0xf7, 0xb7, 0xcc, 0xee, 0x9a, 0x02, 0xe3, 0xc0, 0xb1, 0xe0, 0xee, 0x83, 0x78, 0xb4, 0x9e, 0x07, 0x87, 0xdf, 0xb0, 0x82, 0x26, 0x4e, 0xa4, 0x0c, 0x33, 0xaf, 0x40, 0x59, 0xb6, 0xdd, 0x52, 0x45, 0xf0, 0xb4, 0xf6, 0xe8, 0x4e, 0x4e, 0x79, 0x1a, 0x5d, - /* (2^ 20)P */ 0x27, 0x33, 0x4d, 0x4c, 0x6b, 0x4f, 0x75, 0xb1, 0xbc, 0x1f, 0xab, 0x5b, 0x2b, 0xf0, 0x1c, 0x57, 0x86, 0xdd, 0xfd, 0x60, 0xb0, 0x8c, 0xe7, 0x9a, 0xe5, 0x5c, 0xeb, 0x11, 0x3a, 0xda, 0x22, 0x25, 0x99, 0x06, 0x8d, 0xf4, 0xaf, 0x29, 0x7a, 0xc9, 0xe5, 0xd2, 0x16, 0x9e, 0xd4, 0x63, 0x1d, 0x64, 0xa6, 0x47, 0x96, 0x37, 0x6f, 0x93, 0x2c, 0xcc, - /* (2^ 21)P */ 0xc1, 0x94, 0x74, 0x86, 0x75, 0xf2, 0x91, 0x58, 0x23, 0x85, 0x63, 0x76, 0x54, 0xc7, 0xb4, 0x8c, 0xbc, 0x4e, 0xc4, 0xa7, 0xba, 0xa0, 0x55, 0x26, 0x71, 0xd5, 0x33, 0x72, 0xc9, 0xad, 0x1e, 0xf9, 0x5d, 0x78, 0x70, 0x93, 0x4e, 0x85, 0xfc, 0x39, 0x06, 0x73, 0x76, 0xff, 0xe8, 0x64, 0x69, 0x42, 0x45, 0xb2, 0x69, 0xb5, 0x32, 0xe7, 0x2c, 0xde, - /* (2^ 22)P */ 0xde, 0x16, 0xd8, 0x33, 0x49, 0x32, 0xe9, 0x0e, 0x3a, 0x60, 0xee, 0x2e, 0x24, 0x75, 0xe3, 0x9c, 0x92, 0x07, 0xdb, 0xad, 0x92, 0xf5, 0x11, 0xdf, 0xdb, 0xb0, 0x17, 0x5c, 0xd6, 0x1a, 0x70, 0x00, 0xb7, 0xe2, 0x18, 0xec, 0xdc, 0xc2, 0x02, 0x93, 0xb3, 0xc8, 0x3f, 0x4f, 0x1b, 0x96, 0xe6, 0x33, 0x8c, 0xfb, 0xcc, 0xa5, 0x4e, 0xe8, 0xe7, 0x11, - /* (2^ 23)P */ 0x05, 0x7a, 0x74, 0x52, 0xf8, 0xdf, 0x0d, 0x7c, 0x6a, 0x1a, 0x4e, 0x9a, 0x02, 0x1d, 0xae, 0x77, 0xf8, 0x8e, 0xf9, 0xa2, 0x38, 0x54, 0x50, 0xb2, 0x2c, 0x08, 0x9d, 0x9b, 0x9f, 0xfb, 0x2b, 0x06, 0xde, 0x9d, 0xc2, 0x03, 0x0b, 0x22, 0x2b, 0x10, 0x5b, 0x3a, 0x73, 0x29, 0x8e, 0x3e, 0x37, 0x08, 0x2c, 0x3b, 0xf8, 0x80, 0xc1, 0x66, 0x1e, 0x98, - /* (2^ 24)P */ 0xd8, 0xd6, 0x3e, 0xcd, 0x63, 0x8c, 0x2b, 0x41, 0x81, 0xc0, 0x0c, 0x06, 0x87, 0xd6, 0xe7, 0x92, 0xfe, 0xf1, 0x0c, 0x4a, 0x84, 0x5b, 0xaf, 0x40, 0x53, 0x6f, 0x60, 0xd6, 0x6b, 0x76, 0x4b, 0xc2, 0xad, 0xc9, 0xb6, 0xb6, 0x6a, 0xa2, 0xb3, 0xf5, 0xf5, 0xc2, 0x55, 0x83, 0xb2, 0xd3, 0xe9, 0x41, 0x6c, 0x63, 0x51, 0xb8, 0x81, 0x74, 0xc8, 0x2c, - /* (2^ 25)P */ 0xb2, 0xaf, 0x1c, 0xee, 0x07, 0xb0, 0x58, 0xa8, 0x2c, 0x6a, 0xc9, 0x2d, 0x62, 0x28, 0x75, 0x0c, 0x40, 0xb6, 0x11, 0x33, 0x96, 0x80, 0x28, 0x6d, 0xd5, 0x9e, 0x87, 0x90, 0x01, 0x66, 0x1d, 0x1c, 0xf8, 0xb4, 0x92, 0xac, 0x38, 0x18, 0x05, 0xc2, 0x4c, 0x4b, 0x54, 0x7d, 0x80, 0x46, 0x87, 0x2d, 0x99, 0x8e, 0x70, 0x80, 0x69, 0x71, 0x8b, 0xed, - /* (2^ 26)P */ 0x37, 0xa7, 0x6b, 0x71, 0x36, 0x75, 0x8e, 0xff, 0x0f, 0x42, 0xda, 0x5a, 0x46, 0xa6, 0x97, 0x79, 0x7e, 0x30, 0xb3, 0x8f, 0xc7, 0x3a, 0xa0, 0xcb, 0x1d, 0x9c, 0x78, 0x77, 0x36, 0xc2, 0xe7, 0xf4, 0x2f, 0x29, 0x07, 0xb1, 0x07, 0xfd, 0xed, 0x1b, 0x39, 0x77, 0x06, 0x38, 0x77, 0x0f, 0x50, 0x31, 0x12, 0xbf, 0x92, 0xbf, 0x72, 0x79, 0x54, 0xa9, - /* (2^ 27)P */ 0xbd, 0x4d, 0x46, 0x6b, 0x1a, 0x80, 0x46, 0x2d, 0xed, 0xfd, 0x64, 0x6d, 0x94, 0xbc, 0x4a, 0x6e, 0x0c, 0x12, 0xf6, 0x12, 0xab, 0x54, 0x88, 0xd3, 0x85, 0xac, 0x51, 0xae, 0x6f, 0xca, 0xc4, 0xb7, 0xec, 0x22, 0x54, 0x6d, 0x80, 0xb2, 0x1c, 0x63, 0x33, 0x76, 0x6b, 0x8e, 0x6d, 0x59, 0xcd, 0x73, 0x92, 0x5f, 0xff, 0xad, 0x10, 0x35, 0x70, 0x5f, - /* (2^ 28)P */ 0xb3, 0x84, 0xde, 0xc8, 0x04, 0x43, 0x63, 0xfa, 0x29, 0xd9, 0xf0, 0x69, 0x65, 0x5a, 0x0c, 0xe8, 0x2e, 0x0b, 0xfe, 0xb0, 0x7a, 0x42, 0xb3, 0xc3, 0xfc, 0xe6, 0xb8, 0x92, 0x29, 0xae, 0xed, 0xec, 0xd5, 0xe8, 0x4a, 0xa1, 0xbd, 0x3b, 0xd3, 0xc0, 0x07, 0xab, 0x65, 0x65, 0x35, 0x9a, 0xa6, 0x5e, 0x78, 0x18, 0x76, 0x1c, 0x15, 0x49, 0xe6, 0x75, - /* (2^ 29)P */ 0x45, 0xb3, 0x92, 0xa9, 0xc3, 0xb8, 0x11, 0x68, 0x64, 0x3a, 0x83, 0x5d, 0xa8, 0x94, 0x6a, 0x9d, 0xaa, 0x27, 0x9f, 0x98, 0x5d, 0xc0, 0x29, 0xf0, 0xc0, 0x4b, 0x14, 0x3c, 0x05, 0xe7, 0xf8, 0xbd, 0x38, 0x22, 0x96, 0x75, 0x65, 0x5e, 0x0d, 0x3f, 0xbb, 0x6f, 0xe8, 0x3f, 0x96, 0x76, 0x9f, 0xba, 0xd9, 0x44, 0x92, 0x96, 0x22, 0xe7, 0x52, 0xe7, - /* (2^ 30)P */ 0xf4, 0xa3, 0x95, 0x90, 0x47, 0xdf, 0x7d, 0xdc, 0xf4, 0x13, 0x87, 0x67, 0x7d, 0x4f, 0x9d, 0xa0, 0x00, 0x46, 0x72, 0x08, 0xc3, 0xa2, 0x7a, 0x3e, 0xe7, 0x6d, 0x52, 0x7c, 0x11, 0x36, 0x50, 0x83, 0x89, 0x64, 0xcb, 0x1f, 0x08, 0x83, 0x46, 0xcb, 0xac, 0xa6, 0xd8, 0x9c, 0x1b, 0xe8, 0x05, 0x47, 0xc7, 0x26, 0x06, 0x83, 0x39, 0xe9, 0xb1, 0x1c, - /* (2^ 31)P */ 0x11, 0xe8, 0xc8, 0x42, 0xbf, 0x30, 0x9c, 0xa3, 0xf1, 0x85, 0x96, 0x95, 0x4f, 0x4f, 0x52, 0xa2, 0xf5, 0x8b, 0x68, 0x24, 0x16, 0xac, 0x9b, 0xa9, 0x27, 0x28, 0x0e, 0x84, 0x03, 0x46, 0x22, 0x5f, 0xf7, 0x0d, 0xa6, 0x85, 0x88, 0xc1, 0x45, 0x4b, 0x85, 0x1a, 0x10, 0x7f, 0xc9, 0x94, 0x20, 0xb0, 0x04, 0x28, 0x12, 0x30, 0xb9, 0xe6, 0x40, 0x6b, - /* (2^ 32)P */ 0xac, 0x1b, 0x57, 0xb6, 0x42, 0xdb, 0x81, 0x8d, 0x76, 0xfd, 0x9b, 0x1c, 0x29, 0x30, 0xd5, 0x3a, 0xcc, 0x53, 0xd9, 0x26, 0x7a, 0x0f, 0x9c, 0x2e, 0x79, 0xf5, 0x62, 0xeb, 0x61, 0x9d, 0x9b, 0x80, 0x39, 0xcd, 0x60, 0x2e, 0x1f, 0x08, 0x22, 0xbc, 0x19, 0xb3, 0x2a, 0x43, 0x44, 0xf2, 0x4e, 0x66, 0xf4, 0x36, 0xa6, 0xa7, 0xbc, 0xa4, 0x15, 0x7e, - /* (2^ 33)P */ 0xc1, 0x90, 0x8a, 0xde, 0xff, 0x78, 0xc3, 0x73, 0x16, 0xee, 0x76, 0xa0, 0x84, 0x60, 0x8d, 0xe6, 0x82, 0x0f, 0xde, 0x4e, 0xc5, 0x99, 0x34, 0x06, 0x90, 0x44, 0x55, 0xf8, 0x91, 0xd8, 0xe1, 0xe4, 0x2c, 0x8a, 0xde, 0x94, 0x1e, 0x78, 0x25, 0x3d, 0xfd, 0xd8, 0x59, 0x7d, 0xaf, 0x6e, 0xbe, 0x96, 0xbe, 0x3c, 0x16, 0x23, 0x0f, 0x4c, 0xa4, 0x28, - /* (2^ 34)P */ 0xba, 0x11, 0x35, 0x57, 0x03, 0xb6, 0xf4, 0x24, 0x89, 0xb8, 0x5a, 0x0d, 0x50, 0x9c, 0xaa, 0x51, 0x7f, 0xa4, 0x0e, 0xfc, 0x71, 0xb3, 0x3b, 0xf1, 0x96, 0x50, 0x23, 0x15, 0xf5, 0xf5, 0xd4, 0x23, 0xdc, 0x8b, 0x26, 0x9e, 0xae, 0xb7, 0x50, 0xcd, 0xc4, 0x25, 0xf6, 0x75, 0x40, 0x9c, 0x37, 0x79, 0x33, 0x60, 0xd4, 0x4b, 0x13, 0x32, 0xee, 0xe2, - /* (2^ 35)P */ 0x43, 0xb8, 0x56, 0x59, 0xf0, 0x68, 0x23, 0xb3, 0xea, 0x70, 0x58, 0x4c, 0x1e, 0x5a, 0x16, 0x54, 0x03, 0xb2, 0xf4, 0x73, 0xb6, 0xd9, 0x5c, 0x9c, 0x6f, 0xcf, 0x82, 0x2e, 0x54, 0x15, 0x46, 0x2c, 0xa3, 0xda, 0x4e, 0x87, 0xf5, 0x2b, 0xba, 0x91, 0xa3, 0xa0, 0x89, 0xba, 0x48, 0x2b, 0xfa, 0x64, 0x02, 0x7f, 0x78, 0x03, 0xd1, 0xe8, 0x3b, 0xe9, - /* (2^ 36)P */ 0x15, 0xa4, 0x71, 0xd4, 0x0c, 0x24, 0xe9, 0x07, 0xa1, 0x43, 0xf4, 0x7f, 0xbb, 0xa2, 0xa6, 0x6b, 0xfa, 0xb7, 0xea, 0x58, 0xd1, 0x96, 0xb0, 0x24, 0x5c, 0xc7, 0x37, 0x4e, 0x60, 0x0f, 0x40, 0xf2, 0x2f, 0x44, 0x70, 0xea, 0x80, 0x63, 0xfe, 0xfc, 0x46, 0x59, 0x12, 0x27, 0xb5, 0x27, 0xfd, 0xb7, 0x73, 0x0b, 0xca, 0x8b, 0xc2, 0xd3, 0x71, 0x08, - /* (2^ 37)P */ 0x26, 0x0e, 0xd7, 0x52, 0x6f, 0xf1, 0xf2, 0x9d, 0xb8, 0x3d, 0xbd, 0xd4, 0x75, 0x97, 0xd8, 0xbf, 0xa8, 0x86, 0x96, 0xa5, 0x80, 0xa0, 0x45, 0x75, 0xf6, 0x77, 0x71, 0xdb, 0x77, 0x96, 0x55, 0x99, 0x31, 0xd0, 0x4f, 0x34, 0xf4, 0x35, 0x39, 0x41, 0xd3, 0x7d, 0xf7, 0xe2, 0x74, 0xde, 0xbe, 0x5b, 0x1f, 0x39, 0x10, 0x21, 0xa3, 0x4d, 0x3b, 0xc8, - /* (2^ 38)P */ 0x04, 0x00, 0x2a, 0x45, 0xb2, 0xaf, 0x9b, 0x18, 0x6a, 0xeb, 0x96, 0x28, 0xa4, 0x77, 0xd0, 0x13, 0xcf, 0x17, 0x65, 0xe8, 0xc5, 0x81, 0x28, 0xad, 0x39, 0x7a, 0x0b, 0xaa, 0x55, 0x2b, 0xf3, 0xfc, 0x86, 0x40, 0xad, 0x0d, 0x1e, 0x28, 0xa2, 0x2d, 0xc5, 0xd6, 0x04, 0x15, 0xa2, 0x30, 0x3d, 0x12, 0x8e, 0xd6, 0xb5, 0xf7, 0x69, 0xbb, 0x84, 0x20, - /* (2^ 39)P */ 0xd7, 0x7a, 0x77, 0x2c, 0xfb, 0x81, 0x80, 0xe9, 0x1e, 0xc6, 0x36, 0x31, 0x79, 0xc3, 0x7c, 0xa9, 0x57, 0x6b, 0xb5, 0x70, 0xfb, 0xe4, 0xa1, 0xff, 0xfd, 0x21, 0xa5, 0x7c, 0xfa, 0x44, 0xba, 0x0d, 0x96, 0x3d, 0xc4, 0x5c, 0x39, 0x52, 0x87, 0xd7, 0x22, 0x0f, 0x52, 0x88, 0x91, 0x87, 0x96, 0xac, 0xfa, 0x3b, 0xdf, 0xdc, 0x83, 0x8c, 0x99, 0x29, - /* (2^ 40)P */ 0x98, 0x6b, 0x3a, 0x8d, 0x83, 0x17, 0xe1, 0x62, 0xd8, 0x80, 0x4c, 0x97, 0xce, 0x6b, 0xaa, 0x10, 0xa7, 0xc4, 0xe9, 0xeb, 0xa5, 0xfb, 0xc9, 0xdd, 0x2d, 0xeb, 0xfc, 0x9a, 0x71, 0xcd, 0x68, 0x6e, 0xc0, 0x35, 0x64, 0x62, 0x1b, 0x95, 0x12, 0xe8, 0x53, 0xec, 0xf0, 0xf4, 0x86, 0x86, 0x78, 0x18, 0xc4, 0xc6, 0xbc, 0x5a, 0x59, 0x8f, 0x7c, 0x7e, - /* (2^ 41)P */ 0x7f, 0xd7, 0x1e, 0xc5, 0x83, 0xdc, 0x1f, 0xbe, 0x0b, 0xcf, 0x2e, 0x01, 0x01, 0xed, 0xac, 0x17, 0x3b, 0xed, 0xa4, 0x30, 0x96, 0x0e, 0x14, 0x7e, 0x19, 0x2b, 0xa5, 0x67, 0x1e, 0xb3, 0x34, 0x03, 0xa8, 0xbb, 0x0a, 0x7d, 0x08, 0x2d, 0xd5, 0x53, 0x19, 0x6f, 0x13, 0xd5, 0xc0, 0x90, 0x8a, 0xcc, 0xc9, 0x5c, 0xab, 0x24, 0xd7, 0x03, 0xf6, 0x57, - /* (2^ 42)P */ 0x49, 0xcb, 0xb4, 0x96, 0x5f, 0xa6, 0xf8, 0x71, 0x6f, 0x59, 0xad, 0x05, 0x24, 0x2d, 0xaf, 0x67, 0xa8, 0xbe, 0x95, 0xdf, 0x0d, 0x28, 0x5a, 0x7f, 0x6e, 0x87, 0x8c, 0x6e, 0x67, 0x0c, 0xf4, 0xe0, 0x1c, 0x30, 0xc2, 0x66, 0xae, 0x20, 0xa1, 0x34, 0xec, 0x9c, 0xbc, 0xae, 0x3d, 0xa1, 0x28, 0x28, 0x95, 0x1d, 0xc9, 0x3a, 0xa8, 0xfd, 0xfc, 0xa1, - /* (2^ 43)P */ 0xe2, 0x2b, 0x9d, 0xed, 0x02, 0x99, 0x67, 0xbb, 0x2e, 0x16, 0x62, 0x05, 0x70, 0xc7, 0x27, 0xb9, 0x1c, 0x3f, 0xf2, 0x11, 0x01, 0xd8, 0x51, 0xa4, 0x18, 0x92, 0xa9, 0x5d, 0xfb, 0xa9, 0xe4, 0x42, 0xba, 0x38, 0x34, 0x1a, 0x4a, 0xc5, 0x6a, 0x37, 0xde, 0xa7, 0x0c, 0xb4, 0x7e, 0x7f, 0xde, 0xa6, 0xee, 0xcd, 0x55, 0x57, 0x05, 0x06, 0xfd, 0x5d, - /* (2^ 44)P */ 0x2f, 0x32, 0xcf, 0x2e, 0x2c, 0x7b, 0xbe, 0x9a, 0x0c, 0x57, 0x35, 0xf8, 0x87, 0xda, 0x9c, 0xec, 0x48, 0xf2, 0xbb, 0xe2, 0xda, 0x10, 0x58, 0x20, 0xc6, 0xd3, 0x87, 0xe9, 0xc7, 0x26, 0xd1, 0x9a, 0x46, 0x87, 0x90, 0xda, 0xdc, 0xde, 0xc3, 0xb3, 0xf2, 0xe8, 0x6f, 0x4a, 0xe6, 0xe8, 0x9d, 0x98, 0x36, 0x20, 0x03, 0x47, 0x15, 0x3f, 0x64, 0x59, - /* (2^ 45)P */ 0xd4, 0x71, 0x49, 0x0a, 0x67, 0x97, 0xaa, 0x3f, 0xf4, 0x1b, 0x3a, 0x6e, 0x5e, 0x17, 0xcc, 0x0a, 0x8f, 0x81, 0x6a, 0x41, 0x38, 0x77, 0x40, 0x8a, 0x11, 0x42, 0x62, 0xd2, 0x50, 0x32, 0x79, 0x78, 0x28, 0xc2, 0x2e, 0x10, 0x01, 0x94, 0x30, 0x4f, 0x7f, 0x18, 0x17, 0x56, 0x85, 0x4e, 0xad, 0xf7, 0xcb, 0x87, 0x3c, 0x3f, 0x50, 0x2c, 0xc0, 0xba, - /* (2^ 46)P */ 0xbc, 0x30, 0x8e, 0x65, 0x8e, 0x57, 0x5b, 0x38, 0x7a, 0xd4, 0x95, 0x52, 0x7a, 0x32, 0x59, 0x69, 0xcd, 0x9d, 0x47, 0x34, 0x5b, 0x55, 0xa5, 0x24, 0x60, 0xdd, 0xc0, 0xc1, 0x62, 0x73, 0x44, 0xae, 0x4c, 0x9c, 0x65, 0x55, 0x1b, 0x9d, 0x8a, 0x29, 0xb0, 0x1a, 0x52, 0xa8, 0xf1, 0xe6, 0x9a, 0xb3, 0xf6, 0xa3, 0xc9, 0x0a, 0x70, 0x7d, 0x0f, 0xee, - /* (2^ 47)P */ 0x77, 0xd3, 0xe5, 0x8e, 0xfa, 0x00, 0xeb, 0x1b, 0x7f, 0xdc, 0x68, 0x3f, 0x92, 0xbd, 0xb7, 0x0b, 0xb7, 0xb5, 0x24, 0xdf, 0xc5, 0x67, 0x53, 0xd4, 0x36, 0x79, 0xc4, 0x7b, 0x57, 0xbc, 0x99, 0x97, 0x60, 0xef, 0xe4, 0x01, 0xa1, 0xa7, 0xaa, 0x12, 0x36, 0x29, 0xb1, 0x03, 0xc2, 0x83, 0x1c, 0x2b, 0x83, 0xef, 0x2e, 0x2c, 0x23, 0x92, 0xfd, 0xd1, - /* (2^ 48)P */ 0x94, 0xef, 0x03, 0x59, 0xfa, 0x8a, 0x18, 0x76, 0xee, 0x58, 0x08, 0x4d, 0x44, 0xce, 0xf1, 0x52, 0x33, 0x49, 0xf6, 0x69, 0x71, 0xe3, 0xa9, 0xbc, 0x86, 0xe3, 0x43, 0xde, 0x33, 0x7b, 0x90, 0x8b, 0x3e, 0x7d, 0xd5, 0x4a, 0xf0, 0x23, 0x99, 0xa6, 0xea, 0x5f, 0x08, 0xe5, 0xb9, 0x49, 0x8b, 0x0d, 0x6a, 0x21, 0xab, 0x07, 0x62, 0xcd, 0xc4, 0xbe, - /* (2^ 49)P */ 0x61, 0xbf, 0x70, 0x14, 0xfa, 0x4e, 0x9e, 0x7c, 0x0c, 0xf8, 0xb2, 0x48, 0x71, 0x62, 0x83, 0xd6, 0xd1, 0xdc, 0x9c, 0x29, 0x66, 0xb1, 0x34, 0x9c, 0x8d, 0xe6, 0x88, 0xaf, 0xbe, 0xdc, 0x4d, 0xeb, 0xb0, 0xe7, 0x28, 0xae, 0xb2, 0x05, 0x56, 0xc6, 0x0e, 0x10, 0x26, 0xab, 0x2c, 0x59, 0x72, 0x03, 0x66, 0xfe, 0x8f, 0x2c, 0x51, 0x2d, 0xdc, 0xae, - /* (2^ 50)P */ 0xdc, 0x63, 0xf1, 0x8b, 0x5c, 0x65, 0x0b, 0xf1, 0xa6, 0x22, 0xe2, 0xd9, 0xdb, 0x49, 0xb1, 0x3c, 0x47, 0xc2, 0xfe, 0xac, 0x86, 0x07, 0x52, 0xec, 0xb0, 0x08, 0x69, 0xfb, 0xd1, 0x06, 0xdc, 0x48, 0x5c, 0x3d, 0xb2, 0x4d, 0xb8, 0x1a, 0x4e, 0xda, 0xb9, 0xc1, 0x2b, 0xab, 0x4b, 0x62, 0x81, 0x21, 0x9a, 0xfc, 0x3d, 0x39, 0x83, 0x11, 0x36, 0xeb, - /* (2^ 51)P */ 0x94, 0xf3, 0x17, 0xef, 0xf9, 0x60, 0x54, 0xc3, 0xd7, 0x27, 0x35, 0xc5, 0x98, 0x5e, 0xf6, 0x63, 0x6c, 0xa0, 0x4a, 0xd3, 0xa3, 0x98, 0xd9, 0x42, 0xe3, 0xf1, 0xf8, 0x81, 0x96, 0xa9, 0xea, 0x6d, 0x4b, 0x8e, 0x33, 0xca, 0x94, 0x0d, 0xa0, 0xf7, 0xbb, 0x64, 0xa3, 0x36, 0x6f, 0xdc, 0x5a, 0x94, 0x42, 0xca, 0x06, 0xb2, 0x2b, 0x9a, 0x9f, 0x71, - /* (2^ 52)P */ 0xec, 0xdb, 0xa6, 0x1f, 0xdf, 0x15, 0x36, 0xa3, 0xda, 0x8a, 0x7a, 0xb6, 0xa7, 0xe3, 0xaf, 0x52, 0xe0, 0x8d, 0xe8, 0xf2, 0x44, 0x20, 0xeb, 0xa1, 0x20, 0xc4, 0x65, 0x3c, 0x7c, 0x6c, 0x49, 0xed, 0x2f, 0x66, 0x23, 0x68, 0x61, 0x91, 0x40, 0x9f, 0x50, 0x19, 0xd1, 0x84, 0xa7, 0xe2, 0xed, 0x34, 0x37, 0xe3, 0xe4, 0x11, 0x7f, 0x87, 0x55, 0x0f, - /* (2^ 53)P */ 0xb3, 0xa1, 0x0f, 0xb0, 0x48, 0xc0, 0x4d, 0x96, 0xa7, 0xcf, 0x5a, 0x81, 0xb8, 0x4a, 0x46, 0xef, 0x0a, 0xd3, 0x40, 0x7e, 0x02, 0xe3, 0x63, 0xaa, 0x50, 0xd1, 0x2a, 0x37, 0x22, 0x4a, 0x7f, 0x4f, 0xb6, 0xf9, 0x01, 0x82, 0x78, 0x3d, 0x93, 0x14, 0x11, 0x8a, 0x90, 0x60, 0xcd, 0x45, 0x4e, 0x7b, 0x42, 0xb9, 0x3e, 0x6e, 0x68, 0x1f, 0x36, 0x41, - /* (2^ 54)P */ 0x13, 0x73, 0x0e, 0x4f, 0x79, 0x93, 0x9e, 0x29, 0x70, 0x7b, 0x4a, 0x59, 0x1a, 0x9a, 0xf4, 0x55, 0x08, 0xf0, 0xdb, 0x17, 0x58, 0xec, 0x64, 0xad, 0x7f, 0x29, 0xeb, 0x3f, 0x85, 0x4e, 0x60, 0x28, 0x98, 0x1f, 0x73, 0x4e, 0xe6, 0xa8, 0xab, 0xd5, 0xd6, 0xfc, 0xa1, 0x36, 0x6d, 0x15, 0xc6, 0x13, 0x83, 0xa0, 0xc2, 0x6e, 0xd9, 0xdb, 0xc9, 0xcc, - /* (2^ 55)P */ 0xff, 0xd8, 0x52, 0xa3, 0xdc, 0x99, 0xcf, 0x3e, 0x19, 0xb3, 0x68, 0xd0, 0xb5, 0x0d, 0xb8, 0xee, 0x3f, 0xef, 0x6e, 0xc0, 0x38, 0x28, 0x44, 0x92, 0x78, 0x91, 0x1a, 0x08, 0x78, 0x6c, 0x65, 0x24, 0xf3, 0xa2, 0x3d, 0xf2, 0xe5, 0x79, 0x62, 0x69, 0x29, 0xf4, 0x22, 0xc5, 0xdb, 0x6a, 0xae, 0xf4, 0x44, 0xa3, 0x6f, 0xc7, 0x86, 0xab, 0xef, 0xef, - /* (2^ 56)P */ 0xbf, 0x54, 0x9a, 0x09, 0x5d, 0x17, 0xd0, 0xde, 0xfb, 0xf5, 0xca, 0xff, 0x13, 0x20, 0x88, 0x82, 0x3a, 0xe2, 0xd0, 0x3b, 0xfb, 0x05, 0x76, 0xd1, 0xc0, 0x02, 0x71, 0x3b, 0x94, 0xe8, 0xc9, 0x84, 0xcf, 0xa4, 0xe9, 0x28, 0x7b, 0xf5, 0x09, 0xc3, 0x2b, 0x22, 0x40, 0xf1, 0x68, 0x24, 0x24, 0x7d, 0x9f, 0x6e, 0xcd, 0xfe, 0xb0, 0x19, 0x61, 0xf5, - /* (2^ 57)P */ 0xe8, 0x63, 0x51, 0xb3, 0x95, 0x6b, 0x7b, 0x74, 0x92, 0x52, 0x45, 0xa4, 0xed, 0xea, 0x0e, 0x0d, 0x2b, 0x01, 0x1e, 0x2c, 0xbc, 0x91, 0x06, 0x69, 0xdb, 0x1f, 0xb5, 0x77, 0x1d, 0x56, 0xf5, 0xb4, 0x02, 0x80, 0x49, 0x56, 0x12, 0xce, 0x86, 0x05, 0xc9, 0xd9, 0xae, 0xf3, 0x6d, 0xe6, 0x3f, 0x40, 0x52, 0xe9, 0x49, 0x2b, 0x31, 0x06, 0x86, 0x14, - /* (2^ 58)P */ 0xf5, 0x09, 0x3b, 0xd2, 0xff, 0xdf, 0x11, 0xa5, 0x1c, 0x99, 0xe8, 0x1b, 0xa4, 0x2c, 0x7d, 0x8e, 0xc8, 0xf7, 0x03, 0x46, 0xfa, 0xb6, 0xde, 0x73, 0x91, 0x7e, 0x5a, 0x7a, 0xd7, 0x9a, 0x5b, 0x80, 0x24, 0x62, 0x5e, 0x92, 0xf1, 0xa3, 0x45, 0xa3, 0x43, 0x92, 0x8a, 0x2a, 0x5b, 0x0c, 0xb4, 0xc8, 0xad, 0x1c, 0xb6, 0x6c, 0x5e, 0x81, 0x18, 0x91, - /* (2^ 59)P */ 0x96, 0xb3, 0xca, 0x2b, 0xe3, 0x7a, 0x59, 0x72, 0x17, 0x74, 0x29, 0x21, 0xe7, 0x78, 0x07, 0xad, 0xda, 0xb6, 0xcd, 0xf9, 0x27, 0x4d, 0xc8, 0xf2, 0x98, 0x22, 0xca, 0xf2, 0x33, 0x74, 0x7a, 0xdd, 0x1e, 0x71, 0xec, 0xe3, 0x3f, 0xe2, 0xa2, 0xd2, 0x38, 0x75, 0xb0, 0xd0, 0x0a, 0xcf, 0x7d, 0x36, 0xdc, 0x49, 0x38, 0x25, 0x34, 0x4f, 0x20, 0x9a, - /* (2^ 60)P */ 0x2b, 0x6e, 0x04, 0x0d, 0x4f, 0x3d, 0x3b, 0x24, 0xf6, 0x4e, 0x5e, 0x0a, 0xbd, 0x48, 0x96, 0xba, 0x81, 0x8f, 0x39, 0x82, 0x13, 0xe6, 0x72, 0xf3, 0x0f, 0xb6, 0x94, 0xf4, 0xc5, 0x90, 0x74, 0x91, 0xa8, 0xf2, 0xc9, 0xca, 0x9a, 0x4d, 0x98, 0xf2, 0xdf, 0x52, 0x4e, 0x97, 0x2f, 0xeb, 0x84, 0xd3, 0xaf, 0xc2, 0xcc, 0xfb, 0x4c, 0x26, 0x4b, 0xe4, - /* (2^ 61)P */ 0x12, 0x9e, 0xfb, 0x9d, 0x78, 0x79, 0x99, 0xdd, 0xb3, 0x0b, 0x2e, 0x56, 0x41, 0x8e, 0x3f, 0x39, 0xb8, 0x97, 0x89, 0x53, 0x9b, 0x8a, 0x3c, 0x40, 0x9d, 0xa4, 0x6c, 0x2e, 0x31, 0x71, 0xc6, 0x0a, 0x41, 0xd4, 0x95, 0x06, 0x5e, 0xc1, 0xab, 0xc2, 0x14, 0xc4, 0xc7, 0x15, 0x08, 0x3a, 0xad, 0x7a, 0xb4, 0x62, 0xa3, 0x0c, 0x90, 0xf4, 0x47, 0x08, - /* (2^ 62)P */ 0x7f, 0xec, 0x09, 0x82, 0xf5, 0x94, 0x09, 0x93, 0x32, 0xd3, 0xdc, 0x56, 0x80, 0x7b, 0x5b, 0x22, 0x80, 0x6a, 0x96, 0x72, 0xb1, 0xc2, 0xd9, 0xa1, 0x8b, 0x66, 0x42, 0x16, 0xe2, 0x07, 0xb3, 0x2d, 0xf1, 0x75, 0x35, 0x72, 0xc7, 0x98, 0xbe, 0x63, 0x3b, 0x20, 0x75, 0x05, 0xc1, 0x3e, 0x31, 0x5a, 0xf7, 0xaa, 0xae, 0x4b, 0xdb, 0x1d, 0xd0, 0x74, - /* (2^ 63)P */ 0x36, 0x5c, 0x74, 0xe6, 0x5d, 0x59, 0x3f, 0x15, 0x4b, 0x4d, 0x4e, 0x67, 0x41, 0xfe, 0x98, 0x1f, 0x49, 0x76, 0x91, 0x0f, 0x9b, 0xf4, 0xaf, 0x86, 0xaf, 0x66, 0x19, 0xed, 0x46, 0xf1, 0x05, 0x9a, 0xcc, 0xd1, 0x14, 0x1f, 0x82, 0x12, 0x8e, 0xe6, 0xf4, 0xc3, 0x42, 0x5c, 0x4e, 0x33, 0x93, 0xbe, 0x30, 0xe7, 0x64, 0xa9, 0x35, 0x00, 0x4d, 0xf9, - /* (2^ 64)P */ 0x1f, 0xc1, 0x1e, 0xb7, 0xe3, 0x7c, 0xfa, 0xa3, 0x6b, 0x76, 0xaf, 0x9c, 0x05, 0x85, 0x4a, 0xa9, 0xfb, 0xe3, 0x7e, 0xf2, 0x49, 0x56, 0xdc, 0x2f, 0x57, 0x10, 0xba, 0x37, 0xb2, 0x62, 0xf5, 0x6b, 0xe5, 0x8f, 0x0a, 0x87, 0xd1, 0x6a, 0xcb, 0x9d, 0x07, 0xd0, 0xf6, 0x38, 0x99, 0x2c, 0x61, 0x4a, 0x4e, 0xd8, 0xd2, 0x88, 0x29, 0x99, 0x11, 0x95, - /* (2^ 65)P */ 0x6f, 0xdc, 0xd5, 0xd6, 0xd6, 0xa7, 0x4c, 0x46, 0x93, 0x65, 0x62, 0x23, 0x95, 0x32, 0x9c, 0xde, 0x40, 0x41, 0x68, 0x2c, 0x18, 0x4e, 0x5a, 0x8c, 0xc0, 0xc5, 0xc5, 0xea, 0x5c, 0x45, 0x0f, 0x60, 0x78, 0x39, 0xb6, 0x36, 0x23, 0x12, 0xbc, 0x21, 0x9a, 0xf8, 0x91, 0xac, 0xc4, 0x70, 0xdf, 0x85, 0x8e, 0x3c, 0xec, 0x22, 0x04, 0x98, 0xa8, 0xaa, - /* (2^ 66)P */ 0xcc, 0x52, 0x10, 0x5b, 0x4b, 0x6c, 0xc5, 0xfa, 0x3e, 0xd4, 0xf8, 0x1c, 0x04, 0x14, 0x48, 0x33, 0xd9, 0xfc, 0x5f, 0xb0, 0xa5, 0x48, 0x8c, 0x45, 0x8a, 0xee, 0x3e, 0xa7, 0xc1, 0x2e, 0x34, 0xca, 0xf6, 0xc9, 0xeb, 0x10, 0xbb, 0xe1, 0x59, 0x84, 0x25, 0xe8, 0x81, 0x70, 0xc0, 0x09, 0x42, 0xa7, 0x3b, 0x0d, 0x33, 0x00, 0xb5, 0x77, 0xbe, 0x25, - /* (2^ 67)P */ 0xcd, 0x1f, 0xbc, 0x7d, 0xef, 0xe5, 0xca, 0x91, 0xaf, 0xa9, 0x59, 0x6a, 0x09, 0xca, 0xd6, 0x1b, 0x3d, 0x55, 0xde, 0xa2, 0x6a, 0x80, 0xd6, 0x95, 0x47, 0xe4, 0x5f, 0x68, 0x54, 0x08, 0xdf, 0x29, 0xba, 0x2a, 0x02, 0x84, 0xe8, 0xe9, 0x00, 0x77, 0x99, 0x36, 0x03, 0xf6, 0x4a, 0x3e, 0x21, 0x81, 0x7d, 0xb8, 0xa4, 0x8a, 0xa2, 0x05, 0xef, 0xbc, - /* (2^ 68)P */ 0x7c, 0x59, 0x5f, 0x66, 0xd9, 0xb7, 0x83, 0x43, 0x8a, 0xa1, 0x8d, 0x51, 0x70, 0xba, 0xf2, 0x9b, 0x95, 0xc0, 0x4b, 0x4c, 0xa0, 0x14, 0xd3, 0xa4, 0x5d, 0x4a, 0x37, 0x36, 0x97, 0x31, 0x1e, 0x12, 0xe7, 0xbb, 0x08, 0x67, 0xa5, 0x23, 0xd7, 0xfb, 0x97, 0xd8, 0x6a, 0x03, 0xb1, 0xf8, 0x7f, 0xda, 0x58, 0xd9, 0x3f, 0x73, 0x4a, 0x53, 0xe1, 0x7b, - /* (2^ 69)P */ 0x55, 0x83, 0x98, 0x78, 0x6c, 0x56, 0x5e, 0xed, 0xf7, 0x23, 0x3e, 0x4c, 0x7d, 0x09, 0x2d, 0x09, 0x9c, 0x58, 0x8b, 0x32, 0xca, 0xfe, 0xbf, 0x47, 0x03, 0xeb, 0x4d, 0xe7, 0xeb, 0x9c, 0x83, 0x05, 0x68, 0xaa, 0x80, 0x89, 0x44, 0xf9, 0xd4, 0xdc, 0xdb, 0xb1, 0xdb, 0x77, 0xac, 0xf9, 0x2a, 0xae, 0x35, 0xac, 0x74, 0xb5, 0x95, 0x62, 0x18, 0x85, - /* (2^ 70)P */ 0xab, 0x82, 0x7e, 0x10, 0xd7, 0xe6, 0x57, 0xd1, 0x66, 0x12, 0x31, 0x9c, 0x9c, 0xa6, 0x27, 0x59, 0x71, 0x2e, 0xeb, 0xa0, 0x68, 0xc5, 0x87, 0x51, 0xf4, 0xca, 0x3f, 0x98, 0x56, 0xb0, 0x89, 0xb1, 0xc7, 0x7b, 0x46, 0xb3, 0xae, 0x36, 0xf2, 0xee, 0x15, 0x1a, 0x60, 0xf4, 0x50, 0x76, 0x4f, 0xc4, 0x53, 0x0d, 0x36, 0x4d, 0x31, 0xb1, 0x20, 0x51, - /* (2^ 71)P */ 0xf7, 0x1d, 0x8c, 0x1b, 0x5e, 0xe5, 0x02, 0x6f, 0xc5, 0xa5, 0xe0, 0x5f, 0xc6, 0xb6, 0x63, 0x43, 0xaf, 0x3c, 0x19, 0x6c, 0xf4, 0xaf, 0xa4, 0x33, 0xb1, 0x0a, 0x37, 0x3d, 0xd9, 0x4d, 0xe2, 0x29, 0x24, 0x26, 0x94, 0x7c, 0x02, 0xe4, 0xe2, 0xf2, 0xbe, 0xbd, 0xac, 0x1b, 0x48, 0xb8, 0xdd, 0xe9, 0x0d, 0x9a, 0x50, 0x1a, 0x98, 0x71, 0x6e, 0xdc, - /* (2^ 72)P */ 0x9f, 0x40, 0xb1, 0xb3, 0x66, 0x28, 0x6c, 0xfe, 0xa6, 0x7d, 0xf8, 0x3e, 0xb8, 0xf3, 0xde, 0x52, 0x76, 0x52, 0xa3, 0x92, 0x98, 0x23, 0xab, 0x4f, 0x88, 0x97, 0xfc, 0x22, 0xe1, 0x6b, 0x67, 0xcd, 0x13, 0x95, 0xda, 0x65, 0xdd, 0x3b, 0x67, 0x3f, 0x5f, 0x4c, 0xf2, 0x8a, 0xad, 0x98, 0xa7, 0x94, 0x24, 0x45, 0x87, 0x11, 0x7c, 0x75, 0x79, 0x85, - /* (2^ 73)P */ 0x70, 0xbf, 0xf9, 0x3b, 0xa9, 0x44, 0x57, 0x72, 0x96, 0xc9, 0xa4, 0x98, 0x65, 0xbf, 0x87, 0xb3, 0x3a, 0x39, 0x12, 0xde, 0xe5, 0x39, 0x01, 0x4f, 0xf7, 0xc0, 0x71, 0x52, 0x36, 0x85, 0xb3, 0x18, 0xf8, 0x14, 0xc0, 0x6d, 0xae, 0x9e, 0x4f, 0xb0, 0x72, 0x87, 0xac, 0x5c, 0xd1, 0x6c, 0x41, 0x6c, 0x90, 0x9d, 0x22, 0x81, 0xe4, 0x2b, 0xea, 0xe5, - /* (2^ 74)P */ 0xfc, 0xea, 0x1a, 0x65, 0xd9, 0x49, 0x6a, 0x39, 0xb5, 0x96, 0x72, 0x7b, 0x32, 0xf1, 0xd0, 0xe9, 0x45, 0xd9, 0x31, 0x55, 0xc7, 0x34, 0xe9, 0x5a, 0xec, 0x73, 0x0b, 0x03, 0xc4, 0xb3, 0xe6, 0xc9, 0x5e, 0x0a, 0x17, 0xfe, 0x53, 0x66, 0x7f, 0x21, 0x18, 0x74, 0x54, 0x1b, 0xc9, 0x49, 0x16, 0xd2, 0x48, 0xaf, 0x5b, 0x47, 0x7b, 0xeb, 0xaa, 0xc9, - /* (2^ 75)P */ 0x47, 0x04, 0xf5, 0x5a, 0x87, 0x77, 0x9e, 0x21, 0x34, 0x4e, 0x83, 0x88, 0xaf, 0x02, 0x1d, 0xb0, 0x5a, 0x1d, 0x1d, 0x7d, 0x8d, 0x2c, 0xd3, 0x8d, 0x63, 0xa9, 0x45, 0xfb, 0x15, 0x6d, 0x86, 0x45, 0xcd, 0x38, 0x0e, 0xf7, 0x37, 0x79, 0xed, 0x6d, 0x5a, 0xbc, 0x32, 0xcc, 0x66, 0xf1, 0x3a, 0xb2, 0x87, 0x6f, 0x70, 0x71, 0xd9, 0xf2, 0xfa, 0x7b, - /* (2^ 76)P */ 0x68, 0x07, 0xdc, 0x61, 0x40, 0xe4, 0xec, 0x32, 0xc8, 0xbe, 0x66, 0x30, 0x54, 0x80, 0xfd, 0x13, 0x7a, 0xef, 0xae, 0xed, 0x2e, 0x00, 0x6d, 0x3f, 0xbd, 0xfc, 0x91, 0x24, 0x53, 0x7f, 0x63, 0x9d, 0x2e, 0xe3, 0x76, 0xe0, 0xf3, 0xe1, 0x8f, 0x7a, 0xc4, 0x77, 0x0c, 0x91, 0xc0, 0xc2, 0x18, 0x6b, 0x04, 0xad, 0xb6, 0x70, 0x9a, 0x64, 0xc5, 0x82, - /* (2^ 77)P */ 0x7f, 0xea, 0x13, 0xd8, 0x9e, 0xfc, 0x5b, 0x06, 0xb5, 0x4f, 0xda, 0x38, 0xe0, 0x9c, 0xd2, 0x3a, 0xc1, 0x1c, 0x62, 0x70, 0x7f, 0xc6, 0x24, 0x0a, 0x47, 0x04, 0x01, 0xc4, 0x55, 0x09, 0xd1, 0x7a, 0x07, 0xba, 0xa3, 0x80, 0x4f, 0xc1, 0x65, 0x36, 0x6d, 0xc0, 0x10, 0xcf, 0x94, 0xa9, 0xa2, 0x01, 0x44, 0xd1, 0xf9, 0x1c, 0x4c, 0xfb, 0xf8, 0x99, - /* (2^ 78)P */ 0x6c, 0xb9, 0x6b, 0xee, 0x43, 0x5b, 0xb9, 0xbb, 0xee, 0x2e, 0x52, 0xc1, 0xc6, 0xb9, 0x61, 0xd2, 0x93, 0xa5, 0xaf, 0x52, 0xf4, 0xa4, 0x1a, 0x51, 0x61, 0xa7, 0xcb, 0x9e, 0xbb, 0x56, 0x65, 0xe2, 0xbf, 0x75, 0xb9, 0x9c, 0x50, 0x96, 0x60, 0x81, 0x74, 0x47, 0xc0, 0x04, 0x88, 0x71, 0x76, 0x39, 0x9a, 0xa7, 0xb1, 0x4e, 0x43, 0x15, 0xe0, 0xbb, - /* (2^ 79)P */ 0xbb, 0xce, 0xe2, 0xbb, 0xf9, 0x17, 0x0f, 0x82, 0x40, 0xad, 0x73, 0xe3, 0xeb, 0x3b, 0x06, 0x1a, 0xcf, 0x8e, 0x6e, 0x28, 0xb8, 0x26, 0xd9, 0x5b, 0xb7, 0xb3, 0xcf, 0xb4, 0x6a, 0x1c, 0xbf, 0x7f, 0xb8, 0xb5, 0x79, 0xcf, 0x45, 0x68, 0x7d, 0xc5, 0xeb, 0xf3, 0xbe, 0x39, 0x40, 0xfc, 0x07, 0x90, 0x7a, 0x62, 0xad, 0x86, 0x08, 0x71, 0x25, 0xe1, - /* (2^ 80)P */ 0x9b, 0x46, 0xac, 0xef, 0xc1, 0x4e, 0xa1, 0x97, 0x95, 0x76, 0xf9, 0x1b, 0xc2, 0xb2, 0x6a, 0x41, 0xea, 0x80, 0x3d, 0xe9, 0x08, 0x52, 0x5a, 0xe3, 0xf2, 0x08, 0xc5, 0xea, 0x39, 0x3f, 0x44, 0x71, 0x4d, 0xea, 0x0d, 0x05, 0x23, 0xe4, 0x2e, 0x3c, 0x89, 0xfe, 0x12, 0x8a, 0x95, 0x42, 0x0a, 0x68, 0xea, 0x5a, 0x28, 0x06, 0x9e, 0xe3, 0x5f, 0xe0, - /* (2^ 81)P */ 0x00, 0x61, 0x6c, 0x98, 0x9b, 0xe7, 0xb9, 0x06, 0x1c, 0xc5, 0x1b, 0xed, 0xbe, 0xc8, 0xb3, 0xea, 0x87, 0xf0, 0xc4, 0x24, 0x7d, 0xbb, 0x5d, 0xa4, 0x1d, 0x7a, 0x16, 0x00, 0x55, 0x94, 0x67, 0x78, 0xbd, 0x58, 0x02, 0x82, 0x90, 0x53, 0x76, 0xd4, 0x72, 0x99, 0x51, 0x6f, 0x7b, 0xcf, 0x80, 0x30, 0x31, 0x3b, 0x01, 0xc7, 0xc1, 0xef, 0xe6, 0x42, - /* (2^ 82)P */ 0xe2, 0x35, 0xaf, 0x4b, 0x79, 0xc6, 0x12, 0x24, 0x99, 0xc0, 0x68, 0xb0, 0x43, 0x3e, 0xe5, 0xef, 0xe2, 0x29, 0xea, 0xb8, 0xb3, 0xbc, 0x6a, 0x53, 0x2c, 0x69, 0x18, 0x5a, 0xf9, 0x15, 0xae, 0x66, 0x58, 0x18, 0xd3, 0x2d, 0x4b, 0x00, 0xfd, 0x84, 0xab, 0x4f, 0xae, 0x70, 0x6b, 0x9e, 0x9a, 0xdf, 0x83, 0xfd, 0x2e, 0x3c, 0xcf, 0xf8, 0x88, 0x5b, - /* (2^ 83)P */ 0xa4, 0x90, 0x31, 0x85, 0x13, 0xcd, 0xdf, 0x64, 0xc9, 0xa1, 0x0b, 0xe7, 0xb6, 0x73, 0x8a, 0x1b, 0x22, 0x78, 0x4c, 0xd4, 0xae, 0x48, 0x18, 0x00, 0x00, 0xa8, 0x9f, 0x06, 0xf9, 0xfb, 0x2d, 0xc3, 0xb1, 0x2a, 0xbc, 0x13, 0x99, 0x57, 0xaf, 0xf0, 0x8d, 0x61, 0x54, 0x29, 0xd5, 0xf2, 0x72, 0x00, 0x96, 0xd1, 0x85, 0x12, 0x8a, 0xf0, 0x23, 0xfb, - /* (2^ 84)P */ 0x69, 0xc7, 0xdb, 0xd9, 0x92, 0x75, 0x08, 0x9b, 0xeb, 0xa5, 0x93, 0xd1, 0x1a, 0xf4, 0xf5, 0xaf, 0xe6, 0xc4, 0x4a, 0x0d, 0x35, 0x26, 0x39, 0x9d, 0xd3, 0x17, 0x3e, 0xae, 0x2d, 0xbf, 0x73, 0x9f, 0xb7, 0x74, 0x91, 0xd1, 0xd8, 0x5c, 0x14, 0xf9, 0x75, 0xdf, 0xeb, 0xc2, 0x22, 0xd8, 0x14, 0x8d, 0x86, 0x23, 0x4d, 0xd1, 0x2d, 0xdb, 0x6b, 0x42, - /* (2^ 85)P */ 0x8c, 0xda, 0xc6, 0xf8, 0x71, 0xba, 0x2b, 0x06, 0x78, 0xae, 0xcc, 0x3a, 0xe3, 0xe3, 0xa1, 0x8b, 0xe2, 0x34, 0x6d, 0x28, 0x9e, 0x46, 0x13, 0x4d, 0x9e, 0xa6, 0x73, 0x49, 0x65, 0x79, 0x88, 0xb9, 0x3a, 0xd1, 0x6d, 0x2f, 0x48, 0x2b, 0x0a, 0x7f, 0x58, 0x20, 0x37, 0xf4, 0x0e, 0xbb, 0x4a, 0x95, 0x58, 0x0c, 0x88, 0x30, 0xc4, 0x74, 0xdd, 0xfd, - /* (2^ 86)P */ 0x6d, 0x13, 0x4e, 0x89, 0x2d, 0xa9, 0xa3, 0xed, 0x09, 0xe3, 0x0e, 0x71, 0x3e, 0x4a, 0xab, 0x90, 0xde, 0x03, 0xeb, 0x56, 0x46, 0x60, 0x06, 0xf5, 0x71, 0xe5, 0xee, 0x9b, 0xef, 0xff, 0xc4, 0x2c, 0x9f, 0x37, 0x48, 0x45, 0x94, 0x12, 0x41, 0x81, 0x15, 0x70, 0x91, 0x99, 0x5e, 0x56, 0x6b, 0xf4, 0xa6, 0xc9, 0xf5, 0x69, 0x9d, 0x78, 0x37, 0x57, - /* (2^ 87)P */ 0xf3, 0x51, 0x57, 0x7e, 0x43, 0x6f, 0xc6, 0x67, 0x59, 0x0c, 0xcf, 0x94, 0xe6, 0x3d, 0xb5, 0x07, 0xc9, 0x77, 0x48, 0xc9, 0x68, 0x0d, 0x98, 0x36, 0x62, 0x35, 0x38, 0x1c, 0xf5, 0xc5, 0xec, 0x66, 0x78, 0xfe, 0x47, 0xab, 0x26, 0xd6, 0x44, 0xb6, 0x06, 0x0f, 0x89, 0xe3, 0x19, 0x40, 0x1a, 0xe7, 0xd8, 0x65, 0x55, 0xf7, 0x1a, 0xfc, 0xa3, 0x0e, - /* (2^ 88)P */ 0x0e, 0x30, 0xa6, 0xb7, 0x58, 0x60, 0x62, 0x2a, 0x6c, 0x13, 0xa8, 0x14, 0x9b, 0xb8, 0xf2, 0x70, 0xd8, 0xb1, 0x71, 0x88, 0x8c, 0x18, 0x31, 0x25, 0x93, 0x90, 0xb4, 0xc7, 0x49, 0xd8, 0xd4, 0xdb, 0x1e, 0x1e, 0x7f, 0xaa, 0xba, 0xc9, 0xf2, 0x5d, 0xa9, 0x3a, 0x43, 0xb4, 0x5c, 0xee, 0x7b, 0xc7, 0x97, 0xb7, 0x66, 0xd7, 0x23, 0xd9, 0x22, 0x59, - /* (2^ 89)P */ 0x28, 0x19, 0xa6, 0xf9, 0x89, 0x20, 0x78, 0xd4, 0x6d, 0xcb, 0x79, 0x8f, 0x61, 0x6f, 0xb2, 0x5c, 0x4f, 0xa6, 0x54, 0x84, 0x95, 0x24, 0x36, 0x64, 0xcb, 0x39, 0xe7, 0x8f, 0x97, 0x9c, 0x5c, 0x3c, 0xfb, 0x51, 0x11, 0x01, 0x17, 0xdb, 0xc9, 0x9b, 0x51, 0x03, 0x9a, 0xe9, 0xe5, 0x24, 0x1e, 0xf5, 0xda, 0xe0, 0x48, 0x02, 0x23, 0xd0, 0x2c, 0x81, - /* (2^ 90)P */ 0x42, 0x1b, 0xe4, 0x91, 0x85, 0x2a, 0x0c, 0xd2, 0x28, 0x66, 0x57, 0x9e, 0x33, 0x8d, 0x25, 0x71, 0x10, 0x65, 0x76, 0xa2, 0x8c, 0x21, 0x86, 0x81, 0x15, 0xc2, 0x27, 0xeb, 0x54, 0x2d, 0x4f, 0x6c, 0xe6, 0xd6, 0x24, 0x9c, 0x1a, 0x12, 0xb8, 0x81, 0xe2, 0x0a, 0xf3, 0xd3, 0xf0, 0xd3, 0xe1, 0x74, 0x1f, 0x9b, 0x11, 0x47, 0xd0, 0xcf, 0xb6, 0x54, - /* (2^ 91)P */ 0x26, 0x45, 0xa2, 0x10, 0xd4, 0x2d, 0xae, 0xc0, 0xb0, 0xe8, 0x86, 0xb3, 0xc7, 0xea, 0x70, 0x87, 0x61, 0xb5, 0xa5, 0x55, 0xbe, 0x88, 0x1d, 0x7a, 0xd9, 0x6f, 0xeb, 0x83, 0xe2, 0x44, 0x7f, 0x98, 0x04, 0xd6, 0x50, 0x9d, 0xa7, 0x86, 0x66, 0x09, 0x63, 0xe1, 0xed, 0x72, 0xb1, 0xe4, 0x1d, 0x3a, 0xfd, 0x47, 0xce, 0x1c, 0xaa, 0x3b, 0x8f, 0x1b, - /* (2^ 92)P */ 0xf4, 0x3c, 0x4a, 0xb6, 0xc2, 0x9c, 0xe0, 0x2e, 0xb7, 0x38, 0xea, 0x61, 0x35, 0x97, 0x10, 0x90, 0xae, 0x22, 0x48, 0xb3, 0xa9, 0xc6, 0x7a, 0xbb, 0x23, 0xf2, 0xf8, 0x1b, 0xa7, 0xa1, 0x79, 0xcc, 0xc4, 0xf8, 0x08, 0x76, 0x8a, 0x5a, 0x1c, 0x1b, 0xc5, 0x33, 0x91, 0xa9, 0xb8, 0xb9, 0xd3, 0xf8, 0x49, 0xcd, 0xe5, 0x82, 0x43, 0xf7, 0xca, 0x68, - /* (2^ 93)P */ 0x38, 0xba, 0xae, 0x44, 0xfe, 0x57, 0x64, 0x56, 0x7c, 0x0e, 0x9c, 0xca, 0xff, 0xa9, 0x82, 0xbb, 0x38, 0x4a, 0xa7, 0xf7, 0x47, 0xab, 0xbe, 0x6d, 0x23, 0x0b, 0x8a, 0xed, 0xc2, 0xb9, 0x8f, 0xf1, 0xec, 0x91, 0x44, 0x73, 0x64, 0xba, 0xd5, 0x8f, 0x37, 0x38, 0x0d, 0xd5, 0xf8, 0x73, 0x57, 0xb6, 0xc2, 0x45, 0xdc, 0x25, 0xb2, 0xb6, 0xea, 0xd9, - /* (2^ 94)P */ 0xbf, 0xe9, 0x1a, 0x40, 0x4d, 0xcc, 0xe6, 0x1d, 0x70, 0x1a, 0x65, 0xcc, 0x34, 0x2c, 0x37, 0x2c, 0x2d, 0x6b, 0x6d, 0xe5, 0x2f, 0x19, 0x9e, 0xe4, 0xe1, 0xaa, 0xd4, 0xab, 0x54, 0xf4, 0xa8, 0xe4, 0x69, 0x2d, 0x8e, 0x4d, 0xd7, 0xac, 0xb0, 0x5b, 0xfe, 0xe3, 0x26, 0x07, 0xc3, 0xf8, 0x1b, 0x43, 0xa8, 0x1d, 0x64, 0xa5, 0x25, 0x88, 0xbb, 0x77, - /* (2^ 95)P */ 0x92, 0xcd, 0x6e, 0xa0, 0x79, 0x04, 0x18, 0xf4, 0x11, 0x58, 0x48, 0xb5, 0x3c, 0x7b, 0xd1, 0xcc, 0xd3, 0x14, 0x2c, 0xa0, 0xdd, 0x04, 0x44, 0x11, 0xb3, 0x6d, 0x2f, 0x0d, 0xf5, 0x2a, 0x75, 0x5d, 0x1d, 0xda, 0x86, 0x8d, 0x7d, 0x6b, 0x32, 0x68, 0xb6, 0x6c, 0x64, 0x9e, 0xde, 0x80, 0x88, 0xce, 0x08, 0xbf, 0x0b, 0xe5, 0x8e, 0x4f, 0x1d, 0xfb, - /* (2^ 96)P */ 0xaf, 0xe8, 0x85, 0xbf, 0x7f, 0x37, 0x8d, 0x66, 0x7c, 0xd5, 0xd3, 0x96, 0xa5, 0x81, 0x67, 0x95, 0xff, 0x48, 0xde, 0xde, 0xd7, 0x7a, 0x46, 0x34, 0xb1, 0x13, 0x70, 0x29, 0xed, 0x87, 0x90, 0xb0, 0x40, 0x2c, 0xa6, 0x43, 0x6e, 0xb6, 0xbc, 0x48, 0x8a, 0xc1, 0xae, 0xb8, 0xd4, 0xe2, 0xc0, 0x32, 0xb2, 0xa6, 0x2a, 0x8f, 0xb5, 0x16, 0x9e, 0xc3, - /* (2^ 97)P */ 0xff, 0x4d, 0xd2, 0xd6, 0x74, 0xef, 0x2c, 0x96, 0xc1, 0x11, 0xa8, 0xb8, 0xfe, 0x94, 0x87, 0x3e, 0xa0, 0xfb, 0x57, 0xa3, 0xfc, 0x7a, 0x7e, 0x6a, 0x59, 0x6c, 0x54, 0xbb, 0xbb, 0xa2, 0x25, 0x38, 0x1b, 0xdf, 0x5d, 0x7b, 0x94, 0x14, 0xde, 0x07, 0x6e, 0xd3, 0xab, 0x02, 0x26, 0x74, 0x16, 0x12, 0xdf, 0x2e, 0x2a, 0xa7, 0xb0, 0xe8, 0x29, 0xc0, - /* (2^ 98)P */ 0x6a, 0x38, 0x0b, 0xd3, 0xba, 0x45, 0x23, 0xe0, 0x04, 0x3b, 0x83, 0x39, 0xc5, 0x11, 0xe6, 0xcf, 0x39, 0x0a, 0xb3, 0xb0, 0x3b, 0x27, 0x29, 0x63, 0x1c, 0xf3, 0x00, 0xe6, 0xd2, 0x55, 0x21, 0x1f, 0x84, 0x97, 0x9f, 0x01, 0x49, 0x43, 0x30, 0x5f, 0xe0, 0x1d, 0x24, 0xc4, 0x4e, 0xa0, 0x2b, 0x0b, 0x12, 0x55, 0xc3, 0x27, 0xae, 0x08, 0x83, 0x7c, - /* (2^ 99)P */ 0x5d, 0x1a, 0xb7, 0xa9, 0xf5, 0xfd, 0xec, 0xad, 0xb7, 0x87, 0x02, 0x5f, 0x0d, 0x30, 0x4d, 0xe2, 0x65, 0x87, 0xa4, 0x41, 0x45, 0x1d, 0x67, 0xe0, 0x30, 0x5c, 0x13, 0x87, 0xf6, 0x2e, 0x08, 0xc1, 0xc7, 0x12, 0x45, 0xc8, 0x9b, 0xad, 0xb8, 0xd5, 0x57, 0xbb, 0x5c, 0x48, 0x3a, 0xe1, 0x91, 0x5e, 0xf6, 0x4d, 0x8a, 0x63, 0x75, 0x69, 0x0c, 0x01, - /* (2^100)P */ 0x8f, 0x53, 0x2d, 0xa0, 0x71, 0x3d, 0xfc, 0x45, 0x10, 0x96, 0xcf, 0x56, 0xf9, 0xbb, 0x40, 0x3c, 0x86, 0x52, 0x76, 0xbe, 0x84, 0xf9, 0xa6, 0x9d, 0x3d, 0x27, 0xbe, 0xb4, 0x00, 0x49, 0x94, 0xf5, 0x5d, 0xe1, 0x62, 0x85, 0x66, 0xe5, 0xb8, 0x20, 0x2c, 0x09, 0x7d, 0x9d, 0x3d, 0x6e, 0x74, 0x39, 0xab, 0xad, 0xa0, 0x90, 0x97, 0x5f, 0xbb, 0xa7, - /* (2^101)P */ 0xdb, 0x2d, 0x99, 0x08, 0x16, 0x46, 0x83, 0x7a, 0xa8, 0xea, 0x3d, 0x28, 0x5b, 0x49, 0xfc, 0xb9, 0x6d, 0x00, 0x9e, 0x54, 0x4f, 0x47, 0x64, 0x9b, 0x58, 0x4d, 0x07, 0x0c, 0x6f, 0x29, 0x56, 0x0b, 0x00, 0x14, 0x85, 0x96, 0x41, 0x04, 0xb9, 0x5c, 0xa4, 0xf6, 0x16, 0x73, 0x6a, 0xc7, 0x62, 0x0c, 0x65, 0x2f, 0x93, 0xbf, 0xf7, 0xb9, 0xb7, 0xf1, - /* (2^102)P */ 0xeb, 0x6d, 0xb3, 0x46, 0x32, 0xd2, 0xcb, 0x08, 0x94, 0x14, 0xbf, 0x3f, 0xc5, 0xcb, 0x5f, 0x9f, 0x8a, 0x89, 0x0c, 0x1b, 0x45, 0xad, 0x4c, 0x50, 0xb4, 0xe1, 0xa0, 0x6b, 0x11, 0x92, 0xaf, 0x1f, 0x00, 0xcc, 0xe5, 0x13, 0x7e, 0xe4, 0x2e, 0xa0, 0x57, 0xf3, 0xa7, 0x84, 0x79, 0x7a, 0xc2, 0xb7, 0xb7, 0xfc, 0x5d, 0xa5, 0xa9, 0x64, 0xcc, 0xd8, - /* (2^103)P */ 0xa9, 0xc4, 0x12, 0x8b, 0x34, 0x78, 0x3e, 0x38, 0xfd, 0x3f, 0x87, 0xfa, 0x88, 0x94, 0xd5, 0xd9, 0x7f, 0xeb, 0x58, 0xff, 0xb9, 0x45, 0xdb, 0xa1, 0xed, 0x22, 0x28, 0x1d, 0x00, 0x6d, 0x79, 0x85, 0x7a, 0x75, 0x5d, 0xf0, 0xb1, 0x9e, 0x47, 0x28, 0x8c, 0x62, 0xdf, 0xfb, 0x4c, 0x7b, 0xc5, 0x1a, 0x42, 0x95, 0xef, 0x9a, 0xb7, 0x27, 0x7e, 0xda, - /* (2^104)P */ 0xca, 0xd5, 0xc0, 0x17, 0xa1, 0x66, 0x79, 0x9c, 0x2a, 0xb7, 0x0a, 0xfe, 0x62, 0xe4, 0x26, 0x78, 0x90, 0xa7, 0xcb, 0xb0, 0x4f, 0x6d, 0xf9, 0x8f, 0xf7, 0x7d, 0xac, 0xb8, 0x78, 0x1f, 0x41, 0xea, 0x97, 0x1e, 0x62, 0x97, 0x43, 0x80, 0x58, 0x80, 0xb6, 0x69, 0x7d, 0xee, 0x16, 0xd2, 0xa1, 0x81, 0xd7, 0xb1, 0x27, 0x03, 0x48, 0xda, 0xab, 0xec, - /* (2^105)P */ 0x5b, 0xed, 0x40, 0x8e, 0x8c, 0xc1, 0x66, 0x90, 0x7f, 0x0c, 0xb2, 0xfc, 0xbd, 0x16, 0xac, 0x7d, 0x4c, 0x6a, 0xf9, 0xae, 0xe7, 0x4e, 0x11, 0x12, 0xe9, 0xbe, 0x17, 0x09, 0xc6, 0xc1, 0x5e, 0xb5, 0x7b, 0x50, 0x5c, 0x27, 0xfb, 0x80, 0xab, 0x01, 0xfa, 0x5b, 0x9b, 0x75, 0x16, 0x6e, 0xb2, 0x5c, 0x8c, 0x2f, 0xa5, 0x6a, 0x1a, 0x68, 0xa6, 0x90, - /* (2^106)P */ 0x75, 0xfe, 0xb6, 0x96, 0x96, 0x87, 0x4c, 0x12, 0xa9, 0xd1, 0xd8, 0x03, 0xa3, 0xc1, 0x15, 0x96, 0xe8, 0xa0, 0x75, 0x82, 0xa0, 0x6d, 0xea, 0x54, 0xdc, 0x5f, 0x0d, 0x7e, 0xf6, 0x70, 0xb5, 0xdc, 0x7a, 0xf6, 0xc4, 0xd4, 0x21, 0x49, 0xf5, 0xd4, 0x14, 0x6d, 0x48, 0x1d, 0x7c, 0x99, 0x42, 0xdf, 0x78, 0x6b, 0x9d, 0xb9, 0x30, 0x3c, 0xd0, 0x29, - /* (2^107)P */ 0x85, 0xd6, 0xd8, 0xf3, 0x91, 0x74, 0xdd, 0xbd, 0x72, 0x96, 0x10, 0xe4, 0x76, 0x02, 0x5a, 0x72, 0x67, 0xd3, 0x17, 0x72, 0x14, 0x9a, 0x20, 0x5b, 0x0f, 0x8d, 0xed, 0x6d, 0x4e, 0xe3, 0xd9, 0x82, 0xc2, 0x99, 0xee, 0x39, 0x61, 0x69, 0x8a, 0x24, 0x01, 0x92, 0x15, 0xe7, 0xfc, 0xf9, 0x4d, 0xac, 0xf1, 0x30, 0x49, 0x01, 0x0b, 0x6e, 0x0f, 0x20, - /* (2^108)P */ 0xd8, 0x25, 0x94, 0x5e, 0x43, 0x29, 0xf5, 0xcc, 0xe8, 0xe3, 0x55, 0x41, 0x3c, 0x9f, 0x58, 0x5b, 0x00, 0xeb, 0xc5, 0xdf, 0xcf, 0xfb, 0xfd, 0x6e, 0x92, 0xec, 0x99, 0x30, 0xd6, 0x05, 0xdd, 0x80, 0x7a, 0x5d, 0x6d, 0x16, 0x85, 0xd8, 0x9d, 0x43, 0x65, 0xd8, 0x2c, 0x33, 0x2f, 0x5c, 0x41, 0xea, 0xb7, 0x95, 0x77, 0xf2, 0x9e, 0x59, 0x09, 0xe8, - /* (2^109)P */ 0x00, 0xa0, 0x03, 0x80, 0xcd, 0x60, 0xe5, 0x17, 0xd4, 0x15, 0x99, 0xdd, 0x4f, 0xbf, 0x66, 0xb8, 0xc0, 0xf5, 0xf9, 0xfc, 0x6d, 0x42, 0x18, 0x34, 0x1c, 0x7d, 0x5b, 0xb5, 0x09, 0xd0, 0x99, 0x57, 0x81, 0x0b, 0x62, 0xb3, 0xa2, 0xf9, 0x0b, 0xae, 0x95, 0xb8, 0xc2, 0x3b, 0x0d, 0x5b, 0x00, 0xf1, 0xed, 0xbc, 0x05, 0x9d, 0x61, 0xbc, 0x73, 0x9d, - /* (2^110)P */ 0xd4, 0xdb, 0x29, 0xe5, 0x85, 0xe9, 0xc6, 0x89, 0x2a, 0xa8, 0x54, 0xab, 0xb3, 0x7f, 0x88, 0xc0, 0x4d, 0xe0, 0xd1, 0x74, 0x6e, 0xa3, 0xa7, 0x39, 0xd5, 0xcc, 0xa1, 0x8a, 0xcb, 0x5b, 0x34, 0xad, 0x92, 0xb4, 0xd8, 0xd5, 0x17, 0xf6, 0x77, 0x18, 0x9e, 0xaf, 0x45, 0x3b, 0x03, 0xe2, 0xf8, 0x52, 0x60, 0xdc, 0x15, 0x20, 0x9e, 0xdf, 0xd8, 0x5d, - /* (2^111)P */ 0x02, 0xc1, 0xac, 0x1a, 0x15, 0x8e, 0x6c, 0xf5, 0x1e, 0x1e, 0xba, 0x7e, 0xc2, 0xda, 0x7d, 0x02, 0xda, 0x43, 0xae, 0x04, 0x70, 0x28, 0x54, 0x78, 0x94, 0xf5, 0x4f, 0x07, 0x84, 0x8f, 0xed, 0xaa, 0xc0, 0xb8, 0xcd, 0x7f, 0x7e, 0x33, 0xa3, 0xbe, 0x21, 0x29, 0xc8, 0x56, 0x34, 0xc0, 0x76, 0x87, 0x8f, 0xc7, 0x73, 0x58, 0x90, 0x16, 0xfc, 0xd6, - /* (2^112)P */ 0xb8, 0x3f, 0xe1, 0xdf, 0x3a, 0x91, 0x25, 0x0c, 0xf6, 0x47, 0xa8, 0x89, 0xc4, 0xc6, 0x61, 0xec, 0x86, 0x2c, 0xfd, 0xbe, 0xa4, 0x6f, 0xc2, 0xd4, 0x46, 0x19, 0x70, 0x5d, 0x09, 0x02, 0x86, 0xd3, 0x4b, 0xe9, 0x16, 0x7b, 0xf0, 0x0d, 0x6c, 0xff, 0x91, 0x05, 0xbf, 0x55, 0xb4, 0x00, 0x8d, 0xe5, 0x6d, 0x68, 0x20, 0x90, 0x12, 0xb5, 0x5c, 0x32, - /* (2^113)P */ 0x80, 0x45, 0xc8, 0x51, 0x87, 0xba, 0x1c, 0x5c, 0xcf, 0x5f, 0x4b, 0x3c, 0x9e, 0x3b, 0x36, 0xd2, 0x26, 0xa2, 0x7f, 0xab, 0xb7, 0xbf, 0xda, 0x68, 0x23, 0x8f, 0xc3, 0xa0, 0xfd, 0xad, 0xf1, 0x56, 0x3b, 0xd0, 0x75, 0x2b, 0x44, 0x61, 0xd8, 0xf4, 0xf1, 0x05, 0x49, 0x53, 0x07, 0xee, 0x47, 0xef, 0xc0, 0x7c, 0x9d, 0xe4, 0x15, 0x88, 0xc5, 0x47, - /* (2^114)P */ 0x2d, 0xb5, 0x09, 0x80, 0xb9, 0xd3, 0xd8, 0xfe, 0x4c, 0xd2, 0xa6, 0x6e, 0xd3, 0x75, 0xcf, 0xb0, 0x99, 0xcb, 0x50, 0x8d, 0xe9, 0x67, 0x9b, 0x20, 0xe8, 0x57, 0xd8, 0x14, 0x85, 0x73, 0x6a, 0x74, 0xe0, 0x99, 0xf0, 0x6b, 0x6e, 0x59, 0x30, 0x31, 0x33, 0x96, 0x5f, 0xa1, 0x0c, 0x1b, 0xf4, 0xca, 0x09, 0xe1, 0x9b, 0xb5, 0xcf, 0x6d, 0x0b, 0xeb, - /* (2^115)P */ 0x1a, 0xde, 0x50, 0xa9, 0xac, 0x3e, 0x10, 0x43, 0x4f, 0x82, 0x4f, 0xc0, 0xfe, 0x3f, 0x33, 0xd2, 0x64, 0x86, 0x50, 0xa9, 0x51, 0x76, 0x5e, 0x50, 0x97, 0x6c, 0x73, 0x8d, 0x77, 0xa3, 0x75, 0x03, 0xbc, 0xc9, 0xfb, 0x50, 0xd9, 0x6d, 0x16, 0xad, 0x5d, 0x32, 0x3d, 0xac, 0x44, 0xdf, 0x51, 0xf7, 0x19, 0xd4, 0x0b, 0x57, 0x78, 0x0b, 0x81, 0x4e, - /* (2^116)P */ 0x32, 0x24, 0xf1, 0x6c, 0x55, 0x62, 0x1d, 0xb3, 0x1f, 0xda, 0xfa, 0x6a, 0x8f, 0x98, 0x01, 0x16, 0xde, 0x44, 0x50, 0x0d, 0x2e, 0x6c, 0x0b, 0xa2, 0xd3, 0x74, 0x0e, 0xa9, 0xbf, 0x8d, 0xa9, 0xc8, 0xc8, 0x2f, 0x62, 0xc1, 0x35, 0x5e, 0xfd, 0x3a, 0xb3, 0x83, 0x2d, 0xee, 0x4e, 0xfd, 0x5c, 0x5e, 0xad, 0x85, 0xa5, 0x10, 0xb5, 0x4f, 0x34, 0xa7, - /* (2^117)P */ 0xd1, 0x58, 0x6f, 0xe6, 0x54, 0x2c, 0xc2, 0xcd, 0xcf, 0x83, 0xdc, 0x88, 0x0c, 0xb9, 0xb4, 0x62, 0x18, 0x89, 0x65, 0x28, 0xe9, 0x72, 0x4b, 0x65, 0xcf, 0xd6, 0x90, 0x88, 0xd7, 0x76, 0x17, 0x4f, 0x74, 0x64, 0x1e, 0xcb, 0xd3, 0xf5, 0x4b, 0xaa, 0x2e, 0x4d, 0x2d, 0x7c, 0x13, 0x1f, 0xfd, 0xd9, 0x60, 0x83, 0x7e, 0xda, 0x64, 0x1c, 0xdc, 0x9f, - /* (2^118)P */ 0xad, 0xef, 0xac, 0x1b, 0xc1, 0x30, 0x5a, 0x15, 0xc9, 0x1f, 0xac, 0xf1, 0xca, 0x44, 0x95, 0x95, 0xea, 0xf2, 0x22, 0xe7, 0x8d, 0x25, 0xf0, 0xff, 0xd8, 0x71, 0xf7, 0xf8, 0x8f, 0x8f, 0xcd, 0xf4, 0x1e, 0xfe, 0x6c, 0x68, 0x04, 0xb8, 0x78, 0xa1, 0x5f, 0xa6, 0x5d, 0x5e, 0xf9, 0x8d, 0xea, 0x80, 0xcb, 0xf3, 0x17, 0xa6, 0x03, 0xc9, 0x38, 0xd5, - /* (2^119)P */ 0x79, 0x14, 0x31, 0xc3, 0x38, 0xe5, 0xaa, 0xbf, 0x17, 0xa3, 0x04, 0x4e, 0x80, 0x59, 0x9c, 0x9f, 0x19, 0x39, 0xe4, 0x2d, 0x23, 0x54, 0x4a, 0x7f, 0x3e, 0xf3, 0xd9, 0xc7, 0xba, 0x6c, 0x8f, 0x6b, 0xfa, 0x34, 0xb5, 0x23, 0x17, 0x1d, 0xff, 0x1d, 0xea, 0x1f, 0xd7, 0xba, 0x61, 0xb2, 0xe0, 0x38, 0x6a, 0xe9, 0xcf, 0x48, 0x5d, 0x6a, 0x10, 0x9c, - /* (2^120)P */ 0xc8, 0xbb, 0x13, 0x1c, 0x3f, 0x3c, 0x34, 0xfd, 0xac, 0x37, 0x52, 0x44, 0x25, 0xa8, 0xde, 0x1d, 0x63, 0xf4, 0x81, 0x9a, 0xbe, 0x0b, 0x74, 0x2e, 0xc8, 0x51, 0x16, 0xd3, 0xac, 0x4a, 0xaf, 0xe2, 0x5f, 0x3a, 0x89, 0x32, 0xd1, 0x9b, 0x7c, 0x90, 0x0d, 0xac, 0xdc, 0x8b, 0x73, 0x45, 0x45, 0x97, 0xb1, 0x90, 0x2c, 0x1b, 0x31, 0xca, 0xb1, 0x94, - /* (2^121)P */ 0x07, 0x28, 0xdd, 0x10, 0x14, 0xa5, 0x95, 0x7e, 0xf3, 0xe4, 0xd4, 0x14, 0xb4, 0x7e, 0x76, 0xdb, 0x42, 0xd6, 0x94, 0x3e, 0xeb, 0x44, 0x64, 0x88, 0x0d, 0xec, 0xc1, 0x21, 0xf0, 0x79, 0xe0, 0x83, 0x67, 0x55, 0x53, 0xc2, 0xf6, 0xc5, 0xc5, 0x89, 0x39, 0xe8, 0x42, 0xd0, 0x17, 0xbd, 0xff, 0x35, 0x59, 0x0e, 0xc3, 0x06, 0x86, 0xd4, 0x64, 0xcf, - /* (2^122)P */ 0x91, 0xa8, 0xdb, 0x57, 0x9b, 0xe2, 0x96, 0x31, 0x10, 0x6e, 0xd7, 0x9a, 0x97, 0xb3, 0xab, 0xb5, 0x15, 0x66, 0xbe, 0xcc, 0x6d, 0x9a, 0xac, 0x06, 0xb3, 0x0d, 0xaa, 0x4b, 0x9c, 0x96, 0x79, 0x6c, 0x34, 0xee, 0x9e, 0x53, 0x4d, 0x6e, 0xbd, 0x88, 0x02, 0xbf, 0x50, 0x54, 0x12, 0x5d, 0x01, 0x02, 0x46, 0xc6, 0x74, 0x02, 0x8c, 0x24, 0xae, 0xb1, - /* (2^123)P */ 0xf5, 0x22, 0xea, 0xac, 0x7d, 0x9c, 0x33, 0x8a, 0xa5, 0x36, 0x79, 0x6a, 0x4f, 0xa4, 0xdc, 0xa5, 0x73, 0x64, 0xc4, 0x6f, 0x43, 0x02, 0x3b, 0x94, 0x66, 0xd2, 0x4b, 0x4f, 0xf6, 0x45, 0x33, 0x5d, 0x10, 0x33, 0x18, 0x1e, 0xa3, 0xfc, 0xf7, 0xd2, 0xb8, 0xc8, 0xa7, 0xe0, 0x76, 0x8a, 0xcd, 0xff, 0x4f, 0x99, 0x34, 0x47, 0x84, 0x91, 0x96, 0x9f, - /* (2^124)P */ 0x8a, 0x48, 0x3b, 0x48, 0x4a, 0xbc, 0xac, 0xe2, 0x80, 0xd6, 0xd2, 0x35, 0xde, 0xd0, 0x56, 0x42, 0x33, 0xb3, 0x56, 0x5a, 0xcd, 0xb8, 0x3d, 0xb5, 0x25, 0xc1, 0xed, 0xff, 0x87, 0x0b, 0x79, 0xff, 0xf2, 0x62, 0xe1, 0x76, 0xc6, 0xa2, 0x0f, 0xa8, 0x9b, 0x0d, 0xcc, 0x3f, 0x3d, 0x35, 0x27, 0x8d, 0x0b, 0x74, 0xb0, 0xc3, 0x78, 0x8c, 0xcc, 0xc8, - /* (2^125)P */ 0xfc, 0x9a, 0x0c, 0xa8, 0x49, 0x42, 0xb8, 0xdf, 0xcf, 0xb3, 0x19, 0xa6, 0x64, 0x57, 0xfe, 0xe8, 0xf8, 0xa6, 0x4b, 0x86, 0xa1, 0xd5, 0x83, 0x7f, 0x14, 0x99, 0x18, 0x0c, 0x7d, 0x5b, 0xf7, 0x3d, 0xf9, 0x4b, 0x79, 0xb1, 0x86, 0x30, 0xb4, 0x5e, 0x6a, 0xe8, 0x9d, 0xfa, 0x8a, 0x41, 0xc4, 0x30, 0xfc, 0x56, 0x74, 0x14, 0x42, 0xc8, 0x96, 0x0e, - /* (2^126)P */ 0xdf, 0x66, 0xec, 0xbc, 0x44, 0xdb, 0x19, 0xce, 0xd4, 0xb5, 0x49, 0x40, 0x07, 0x49, 0xe0, 0x3a, 0x61, 0x10, 0xfb, 0x7d, 0xba, 0xb1, 0xe0, 0x28, 0x5b, 0x99, 0x59, 0x96, 0xa2, 0xee, 0xe0, 0x23, 0x37, 0x39, 0x1f, 0xe6, 0x57, 0x9f, 0xf8, 0xf8, 0xdc, 0x74, 0xf6, 0x8f, 0x4f, 0x5e, 0x51, 0xa4, 0x12, 0xac, 0xbe, 0xe4, 0xf3, 0xd1, 0xf0, 0x24, - /* (2^127)P */ 0x1e, 0x3e, 0x9a, 0x5f, 0xdf, 0x9f, 0xd6, 0x4e, 0x8a, 0x28, 0xc3, 0xcd, 0x96, 0x9d, 0x57, 0xc7, 0x61, 0x81, 0x90, 0xff, 0xae, 0xb1, 0x4f, 0xc2, 0x96, 0x8b, 0x1a, 0x18, 0xf4, 0x50, 0xcb, 0x31, 0xe1, 0x57, 0xf4, 0x90, 0xa8, 0xea, 0xac, 0xe7, 0x61, 0x98, 0xb6, 0x15, 0xc1, 0x7b, 0x29, 0xa4, 0xc3, 0x18, 0xef, 0xb9, 0xd8, 0xdf, 0xf6, 0xac, - /* (2^128)P */ 0xca, 0xa8, 0x6c, 0xf1, 0xb4, 0xca, 0xfe, 0x31, 0xee, 0x48, 0x38, 0x8b, 0x0e, 0xbb, 0x7a, 0x30, 0xaa, 0xf9, 0xee, 0x27, 0x53, 0x24, 0xdc, 0x2e, 0x15, 0xa6, 0x48, 0x8f, 0xa0, 0x7e, 0xf1, 0xdc, 0x93, 0x87, 0x39, 0xeb, 0x7f, 0x38, 0x92, 0x92, 0x4c, 0x29, 0xe9, 0x57, 0xd8, 0x59, 0xfc, 0xe9, 0x9c, 0x44, 0xc0, 0x65, 0xcf, 0xac, 0x4b, 0xdc, - /* (2^129)P */ 0xa3, 0xd0, 0x37, 0x8f, 0x86, 0x2f, 0xc6, 0x47, 0x55, 0x46, 0x65, 0x26, 0x4b, 0x91, 0xe2, 0x18, 0x5c, 0x4f, 0x23, 0xc1, 0x37, 0x29, 0xb9, 0xc1, 0x27, 0xc5, 0x3c, 0xbf, 0x7e, 0x23, 0xdb, 0x73, 0x99, 0xbd, 0x1b, 0xb2, 0x31, 0x68, 0x3a, 0xad, 0xb7, 0xb0, 0x10, 0xc5, 0xe5, 0x11, 0x51, 0xba, 0xa7, 0x60, 0x66, 0x54, 0xf0, 0x08, 0xd7, 0x69, - /* (2^130)P */ 0x89, 0x41, 0x79, 0xcc, 0xeb, 0x0a, 0xf5, 0x4b, 0xa3, 0x4c, 0xce, 0x52, 0xb0, 0xa7, 0xe4, 0x41, 0x75, 0x7d, 0x04, 0xbb, 0x09, 0x4c, 0x50, 0x9f, 0xdf, 0xea, 0x74, 0x61, 0x02, 0xad, 0xb4, 0x9d, 0xb7, 0x05, 0xb9, 0xea, 0xeb, 0x91, 0x35, 0xe7, 0x49, 0xea, 0xd3, 0x4f, 0x3c, 0x60, 0x21, 0x7a, 0xde, 0xc7, 0xe2, 0x5a, 0xee, 0x8e, 0x93, 0xc7, - /* (2^131)P */ 0x00, 0xe8, 0xed, 0xd0, 0xb3, 0x0d, 0xaf, 0xb2, 0xde, 0x2c, 0xf6, 0x00, 0xe2, 0xea, 0x6d, 0xf8, 0x0e, 0xd9, 0x67, 0x59, 0xa9, 0x50, 0xbb, 0x17, 0x8f, 0xff, 0xb1, 0x9f, 0x17, 0xb6, 0xf2, 0xb5, 0xba, 0x80, 0xf7, 0x0f, 0xba, 0xd5, 0x09, 0x43, 0xaa, 0x4e, 0x3a, 0x67, 0x6a, 0x89, 0x9b, 0x18, 0x65, 0x35, 0xf8, 0x3a, 0x49, 0x91, 0x30, 0x51, - /* (2^132)P */ 0x8d, 0x25, 0xe9, 0x0e, 0x7d, 0x50, 0x76, 0xe4, 0x58, 0x7e, 0xb9, 0x33, 0xe6, 0x65, 0x90, 0xc2, 0x50, 0x9d, 0x50, 0x2e, 0x11, 0xad, 0xd5, 0x43, 0x52, 0x32, 0x41, 0x4f, 0x7b, 0xb6, 0xa0, 0xec, 0x81, 0x75, 0x36, 0x7c, 0x77, 0x85, 0x59, 0x70, 0xe4, 0xf9, 0xef, 0x66, 0x8d, 0x35, 0xc8, 0x2a, 0x6e, 0x5b, 0xc6, 0x0d, 0x0b, 0x29, 0x60, 0x68, - /* (2^133)P */ 0xf8, 0xce, 0xb0, 0x3a, 0x56, 0x7d, 0x51, 0x9a, 0x25, 0x73, 0xea, 0xdd, 0xe4, 0xe0, 0x0e, 0xf0, 0x07, 0xc0, 0x31, 0x00, 0x73, 0x35, 0xd0, 0x39, 0xc4, 0x9b, 0xb7, 0x95, 0xe0, 0x62, 0x70, 0x36, 0x0b, 0xcb, 0xa0, 0x42, 0xde, 0x51, 0xcf, 0x41, 0xe0, 0xb8, 0xb4, 0xc0, 0xe5, 0x46, 0x99, 0x9f, 0x02, 0x7f, 0x14, 0x8c, 0xc1, 0x4e, 0xef, 0xe8, - /* (2^134)P */ 0x10, 0x01, 0x57, 0x0a, 0xbe, 0x8b, 0x18, 0xc8, 0xca, 0x00, 0x28, 0x77, 0x4a, 0x9a, 0xc7, 0x55, 0x2a, 0xcc, 0x0c, 0x7b, 0xb9, 0xe9, 0xc8, 0x97, 0x7c, 0x02, 0xe3, 0x09, 0x2f, 0x62, 0x30, 0xb8, 0x40, 0x09, 0x65, 0xe9, 0x55, 0x63, 0xb5, 0x07, 0xca, 0x9f, 0x00, 0xdf, 0x9d, 0x5c, 0xc7, 0xee, 0x57, 0xa5, 0x90, 0x15, 0x1e, 0x22, 0xa0, 0x12, - /* (2^135)P */ 0x71, 0x2d, 0xc9, 0xef, 0x27, 0xb9, 0xd8, 0x12, 0x43, 0x6b, 0xa8, 0xce, 0x3b, 0x6d, 0x6e, 0x91, 0x43, 0x23, 0xbc, 0x32, 0xb3, 0xbf, 0xe1, 0xc7, 0x39, 0xcf, 0x7c, 0x42, 0x4c, 0xb1, 0x30, 0xe2, 0xdd, 0x69, 0x06, 0xe5, 0xea, 0xf0, 0x2a, 0x16, 0x50, 0x71, 0xca, 0x92, 0xdf, 0xc1, 0xcc, 0xec, 0xe6, 0x54, 0x07, 0xf3, 0x18, 0x8d, 0xd8, 0x29, - /* (2^136)P */ 0x98, 0x51, 0x48, 0x8f, 0xfa, 0x2e, 0x5e, 0x67, 0xb0, 0xc6, 0x17, 0x12, 0xb6, 0x7d, 0xc9, 0xad, 0x81, 0x11, 0xad, 0x0c, 0x1c, 0x2d, 0x45, 0xdf, 0xac, 0x66, 0xbd, 0x08, 0x6f, 0x7c, 0xc7, 0x06, 0x6e, 0x19, 0x08, 0x39, 0x64, 0xd7, 0xe4, 0xd1, 0x11, 0x5f, 0x1c, 0xf4, 0x67, 0xc3, 0x88, 0x6a, 0xe6, 0x07, 0xa3, 0x83, 0xd7, 0xfd, 0x2a, 0xf9, - /* (2^137)P */ 0x87, 0xed, 0xeb, 0xd9, 0xdf, 0xff, 0x43, 0x8b, 0xaa, 0x20, 0x58, 0xb0, 0xb4, 0x6b, 0x14, 0xb8, 0x02, 0xc5, 0x40, 0x20, 0x22, 0xbb, 0xf7, 0xb4, 0xf3, 0x05, 0x1e, 0x4d, 0x94, 0xff, 0xe3, 0xc5, 0x22, 0x82, 0xfe, 0xaf, 0x90, 0x42, 0x98, 0x6b, 0x76, 0x8b, 0x3e, 0x89, 0x3f, 0x42, 0x2a, 0xa7, 0x26, 0x00, 0xda, 0x5c, 0xa2, 0x2b, 0xec, 0xdd, - /* (2^138)P */ 0x5c, 0x21, 0x16, 0x0d, 0x46, 0xb8, 0xd0, 0xa7, 0x88, 0xe7, 0x25, 0xcb, 0x3e, 0x50, 0x73, 0x61, 0xe7, 0xaf, 0x5a, 0x3f, 0x47, 0x8b, 0x3d, 0x97, 0x79, 0x2c, 0xe6, 0x6d, 0x95, 0x74, 0x65, 0x70, 0x36, 0xfd, 0xd1, 0x9e, 0x13, 0x18, 0x63, 0xb1, 0x2d, 0x0b, 0xb5, 0x36, 0x3e, 0xe7, 0x35, 0x42, 0x3b, 0xe6, 0x1f, 0x4d, 0x9d, 0x59, 0xa2, 0x43, - /* (2^139)P */ 0x8c, 0x0c, 0x7c, 0x24, 0x9e, 0xe0, 0xf8, 0x05, 0x1c, 0x9e, 0x1f, 0x31, 0xc0, 0x70, 0xb3, 0xfb, 0x4e, 0xf8, 0x0a, 0x57, 0xb7, 0x49, 0xb5, 0x73, 0xa1, 0x5f, 0x9b, 0x6a, 0x07, 0x6c, 0x87, 0x71, 0x87, 0xd4, 0xbe, 0x98, 0x1e, 0x98, 0xee, 0x52, 0xc1, 0x7b, 0x95, 0x0f, 0x28, 0x32, 0x36, 0x28, 0xd0, 0x3a, 0x0f, 0x7d, 0x2a, 0xa9, 0x62, 0xb9, - /* (2^140)P */ 0x97, 0xe6, 0x18, 0x77, 0xf9, 0x34, 0xac, 0xbc, 0xe0, 0x62, 0x9f, 0x42, 0xde, 0xbd, 0x2f, 0xf7, 0x1f, 0xb7, 0x14, 0x52, 0x8a, 0x79, 0xb2, 0x3f, 0xd2, 0x95, 0x71, 0x01, 0xe8, 0xaf, 0x8c, 0xa4, 0xa4, 0xa7, 0x27, 0xf3, 0x5c, 0xdf, 0x3e, 0x57, 0x7a, 0xf1, 0x76, 0x49, 0xe6, 0x42, 0x3f, 0x8f, 0x1e, 0x63, 0x4a, 0x65, 0xb5, 0x41, 0xf5, 0x02, - /* (2^141)P */ 0x72, 0x85, 0xc5, 0x0b, 0xe1, 0x47, 0x64, 0x02, 0xc5, 0x4d, 0x81, 0x69, 0xb2, 0xcf, 0x0f, 0x6c, 0xd4, 0x6d, 0xd0, 0xc7, 0xb4, 0x1c, 0xd0, 0x32, 0x59, 0x89, 0xe2, 0xe0, 0x96, 0x8b, 0x12, 0x98, 0xbf, 0x63, 0x7a, 0x4c, 0x76, 0x7e, 0x58, 0x17, 0x8f, 0x5b, 0x0a, 0x59, 0x65, 0x75, 0xbc, 0x61, 0x1f, 0xbe, 0xc5, 0x6e, 0x0a, 0x57, 0x52, 0x70, - /* (2^142)P */ 0x92, 0x1c, 0x77, 0xbb, 0x62, 0x02, 0x6c, 0x25, 0x9c, 0x66, 0x07, 0x83, 0xab, 0xcc, 0x80, 0x5d, 0xd2, 0x76, 0x0c, 0xa4, 0xc5, 0xb4, 0x8a, 0x68, 0x23, 0x31, 0x32, 0x29, 0x8a, 0x47, 0x92, 0x12, 0x80, 0xb3, 0xfa, 0x18, 0xe4, 0x8d, 0xc0, 0x4d, 0xfe, 0x97, 0x5f, 0x72, 0x41, 0xb5, 0x5c, 0x7a, 0xbd, 0xf0, 0xcf, 0x5e, 0x97, 0xaa, 0x64, 0x32, - /* (2^143)P */ 0x35, 0x3f, 0x75, 0xc1, 0x7a, 0x75, 0x7e, 0xa9, 0xc6, 0x0b, 0x4e, 0x32, 0x62, 0xec, 0xe3, 0x5c, 0xfb, 0x01, 0x43, 0xb6, 0xd4, 0x5b, 0x75, 0xd2, 0xee, 0x7f, 0x5d, 0x23, 0x2b, 0xb3, 0x54, 0x34, 0x4c, 0xd3, 0xb4, 0x32, 0x84, 0x81, 0xb5, 0x09, 0x76, 0x19, 0xda, 0x58, 0xda, 0x7c, 0xdb, 0x2e, 0xdd, 0x4c, 0x8e, 0xdd, 0x5d, 0x89, 0x10, 0x10, - /* (2^144)P */ 0x57, 0x25, 0x6a, 0x08, 0x37, 0x92, 0xa8, 0xdf, 0x24, 0xef, 0x8f, 0x33, 0x34, 0x52, 0xa4, 0x4c, 0xf0, 0x77, 0x9f, 0x69, 0x77, 0xd5, 0x8f, 0xd2, 0x9a, 0xb3, 0xb6, 0x1d, 0x2d, 0xa6, 0xf7, 0x1f, 0xda, 0xd7, 0xcb, 0x75, 0x11, 0xc3, 0x6b, 0xc0, 0x38, 0xb1, 0xd5, 0x2d, 0x96, 0x84, 0x16, 0xfa, 0x26, 0xb9, 0xcc, 0x3f, 0x16, 0x47, 0x23, 0x74, - /* (2^145)P */ 0x9b, 0x61, 0x2a, 0x1c, 0xdd, 0x39, 0xa5, 0xfa, 0x1c, 0x7d, 0x63, 0x50, 0xca, 0xe6, 0x9d, 0xfa, 0xb7, 0xc4, 0x4c, 0x6a, 0x97, 0x5f, 0x36, 0x4e, 0x47, 0xdd, 0x17, 0xf7, 0xf9, 0x19, 0xce, 0x75, 0x17, 0xad, 0xce, 0x2a, 0xf3, 0xfe, 0x27, 0x8f, 0x3e, 0x48, 0xc0, 0x60, 0x87, 0x24, 0x19, 0xae, 0x59, 0xe4, 0x5a, 0x00, 0x2a, 0xba, 0xa2, 0x1f, - /* (2^146)P */ 0x26, 0x88, 0x42, 0x60, 0x9f, 0x6e, 0x2c, 0x7c, 0x39, 0x0f, 0x47, 0x6a, 0x0e, 0x02, 0xbb, 0x4b, 0x34, 0x29, 0x55, 0x18, 0x36, 0xcf, 0x3b, 0x47, 0xf1, 0x2e, 0xfc, 0x6e, 0x94, 0xff, 0xe8, 0x6b, 0x06, 0xd2, 0xba, 0x77, 0x5e, 0x60, 0xd7, 0x19, 0xef, 0x02, 0x9d, 0x3a, 0xc2, 0xb7, 0xa9, 0xd8, 0x57, 0xee, 0x7e, 0x2b, 0xf2, 0x6d, 0x28, 0xda, - /* (2^147)P */ 0xdf, 0xd9, 0x92, 0x11, 0x98, 0x23, 0xe2, 0x45, 0x2f, 0x74, 0x70, 0xee, 0x0e, 0x55, 0x65, 0x79, 0x86, 0x38, 0x17, 0x92, 0x85, 0x87, 0x99, 0x50, 0xd9, 0x7c, 0xdb, 0xa1, 0x10, 0xec, 0x30, 0xb7, 0x40, 0xa3, 0x23, 0x9b, 0x0e, 0x27, 0x49, 0x29, 0x03, 0x94, 0xff, 0x53, 0xdc, 0xd7, 0xed, 0x49, 0xa9, 0x5a, 0x3b, 0xee, 0xd7, 0xc7, 0x65, 0xaf, - /* (2^148)P */ 0xa0, 0xbd, 0xbe, 0x03, 0xee, 0x0c, 0xbe, 0x32, 0x00, 0x7b, 0x52, 0xcb, 0x92, 0x29, 0xbf, 0xa0, 0xc6, 0xd9, 0xd2, 0xd6, 0x15, 0xe8, 0x3a, 0x75, 0x61, 0x65, 0x56, 0xae, 0xad, 0x3c, 0x2a, 0x64, 0x14, 0x3f, 0x8e, 0xc1, 0x2d, 0x0c, 0x8d, 0x20, 0xdb, 0x58, 0x4b, 0xe5, 0x40, 0x15, 0x4b, 0xdc, 0xa8, 0xbd, 0xef, 0x08, 0xa7, 0xd1, 0xf4, 0xb0, - /* (2^149)P */ 0xa9, 0x0f, 0x05, 0x94, 0x66, 0xac, 0x1f, 0x65, 0x3f, 0xe1, 0xb8, 0xe1, 0x34, 0x5e, 0x1d, 0x8f, 0xe3, 0x93, 0x03, 0x15, 0xff, 0xb6, 0x65, 0xb6, 0x6e, 0xc0, 0x2f, 0xd4, 0x2e, 0xb9, 0x2c, 0x13, 0x3c, 0x99, 0x1c, 0xb5, 0x87, 0xba, 0x79, 0xcb, 0xf0, 0x18, 0x06, 0x86, 0x04, 0x14, 0x25, 0x09, 0xcd, 0x1c, 0x14, 0xda, 0x35, 0xd0, 0x38, 0x3b, - /* (2^150)P */ 0x1b, 0x04, 0xa3, 0x27, 0xb4, 0xd3, 0x37, 0x48, 0x1e, 0x8f, 0x69, 0xd3, 0x5a, 0x2f, 0x20, 0x02, 0x36, 0xbe, 0x06, 0x7b, 0x6b, 0x6c, 0x12, 0x5b, 0x80, 0x74, 0x44, 0xe6, 0xf8, 0xf5, 0x95, 0x59, 0x29, 0xab, 0x51, 0x47, 0x83, 0x28, 0xe0, 0xad, 0xde, 0xaa, 0xd3, 0xb1, 0x1a, 0xcb, 0xa3, 0xcd, 0x8b, 0x6a, 0xb1, 0xa7, 0x0a, 0xd1, 0xf9, 0xbe, - /* (2^151)P */ 0xce, 0x2f, 0x85, 0xca, 0x74, 0x6d, 0x49, 0xb8, 0xce, 0x80, 0x44, 0xe0, 0xda, 0x5b, 0xcf, 0x2f, 0x79, 0x74, 0xfe, 0xb4, 0x2c, 0x99, 0x20, 0x6e, 0x09, 0x04, 0xfb, 0x6d, 0x57, 0x5b, 0x95, 0x0c, 0x45, 0xda, 0x4f, 0x7f, 0x63, 0xcc, 0x85, 0x5a, 0x67, 0x50, 0x68, 0x71, 0xb4, 0x67, 0xb1, 0x2e, 0xc1, 0x1c, 0xdc, 0xff, 0x2a, 0x7c, 0x10, 0x5e, - /* (2^152)P */ 0xa6, 0xde, 0xf3, 0xd4, 0x22, 0x30, 0x24, 0x9e, 0x0b, 0x30, 0x54, 0x59, 0x7e, 0xa2, 0xeb, 0x89, 0x54, 0x65, 0x3e, 0x40, 0xd1, 0xde, 0xe6, 0xee, 0x4d, 0xbf, 0x5e, 0x40, 0x1d, 0xee, 0x4f, 0x68, 0xd9, 0xa7, 0x2f, 0xb3, 0x64, 0xb3, 0xf5, 0xc8, 0xd3, 0xaa, 0x70, 0x70, 0x3d, 0xef, 0xd3, 0x95, 0x54, 0xdb, 0x3e, 0x94, 0x95, 0x92, 0x1f, 0x45, - /* (2^153)P */ 0x22, 0x80, 0x1d, 0x9d, 0x96, 0xa5, 0x78, 0x6f, 0xe0, 0x1e, 0x1b, 0x66, 0x42, 0xc8, 0xae, 0x9e, 0x46, 0x45, 0x08, 0x41, 0xdf, 0x80, 0xae, 0x6f, 0xdb, 0x15, 0x5a, 0x21, 0x31, 0x7a, 0xd0, 0xf2, 0x54, 0x15, 0x88, 0xd3, 0x0f, 0x7f, 0x14, 0x5a, 0x14, 0x97, 0xab, 0xf4, 0x58, 0x6a, 0x9f, 0xea, 0x74, 0xe5, 0x6b, 0x90, 0x59, 0x2b, 0x48, 0xd9, - /* (2^154)P */ 0x12, 0x24, 0x04, 0xf5, 0x50, 0xc2, 0x8c, 0xb0, 0x7c, 0x46, 0x98, 0xd5, 0x24, 0xad, 0xf6, 0x72, 0xdc, 0x82, 0x1a, 0x60, 0xc1, 0xeb, 0x48, 0xef, 0x7f, 0x6e, 0xe6, 0xcc, 0xdb, 0x7b, 0xae, 0xbe, 0x5e, 0x1e, 0x5c, 0xe6, 0x0a, 0x70, 0xdf, 0xa4, 0xa3, 0x85, 0x1b, 0x1b, 0x7f, 0x72, 0xb9, 0x96, 0x6f, 0xdc, 0x03, 0x76, 0x66, 0xfb, 0xa0, 0x33, - /* (2^155)P */ 0x37, 0x40, 0xbb, 0xbc, 0x68, 0x58, 0x86, 0xca, 0xbb, 0xa5, 0x24, 0x76, 0x3d, 0x48, 0xd1, 0xad, 0xb4, 0xa8, 0xcf, 0xc3, 0xb6, 0xa8, 0xba, 0x1a, 0x3a, 0xbe, 0x33, 0x75, 0x04, 0x5c, 0x13, 0x8c, 0x0d, 0x70, 0x8d, 0xa6, 0x4e, 0x2a, 0xeb, 0x17, 0x3c, 0x22, 0xdd, 0x3e, 0x96, 0x40, 0x11, 0x9e, 0x4e, 0xae, 0x3d, 0xf8, 0x91, 0xd7, 0x50, 0xc8, - /* (2^156)P */ 0xd8, 0xca, 0xde, 0x19, 0xcf, 0x00, 0xe4, 0x73, 0x18, 0x7f, 0x9b, 0x9f, 0xf4, 0x5b, 0x49, 0x49, 0x99, 0xdc, 0xa4, 0x46, 0x21, 0xb5, 0xd7, 0x3e, 0xb7, 0x47, 0x1b, 0xa9, 0x9f, 0x4c, 0x69, 0x7d, 0xec, 0x33, 0xd6, 0x1c, 0x51, 0x7f, 0x47, 0x74, 0x7a, 0x6c, 0xf3, 0xd2, 0x2e, 0xbf, 0xdf, 0x6c, 0x9e, 0x77, 0x3b, 0x34, 0xf6, 0x73, 0x80, 0xed, - /* (2^157)P */ 0x16, 0xfb, 0x16, 0xc3, 0xc2, 0x83, 0xe4, 0xf4, 0x03, 0x7f, 0x52, 0xb0, 0x67, 0x51, 0x7b, 0x24, 0x5a, 0x51, 0xd3, 0xb6, 0x4e, 0x59, 0x76, 0xcd, 0x08, 0x7b, 0x1d, 0x7a, 0x9c, 0x65, 0xae, 0xce, 0xaa, 0xd2, 0x1c, 0x85, 0x66, 0x68, 0x06, 0x15, 0xa8, 0x06, 0xe6, 0x16, 0x37, 0xf4, 0x49, 0x9e, 0x0f, 0x50, 0x37, 0xb1, 0xb2, 0x93, 0x70, 0x43, - /* (2^158)P */ 0x18, 0x3a, 0x16, 0xe5, 0x8d, 0xc8, 0x35, 0xd6, 0x7b, 0x09, 0xec, 0x61, 0x5f, 0x5c, 0x2a, 0x19, 0x96, 0x2e, 0xc3, 0xfd, 0xab, 0xe6, 0x23, 0xae, 0xab, 0xc5, 0xcb, 0xb9, 0x7b, 0x2d, 0x34, 0x51, 0xb9, 0x41, 0x9e, 0x7d, 0xca, 0xda, 0x25, 0x45, 0x14, 0xb0, 0xc7, 0x4d, 0x26, 0x2b, 0xfe, 0x43, 0xb0, 0x21, 0x5e, 0xfa, 0xdc, 0x7c, 0xf9, 0x5a, - /* (2^159)P */ 0x94, 0xad, 0x42, 0x17, 0xf5, 0xcd, 0x1c, 0x0d, 0xf6, 0x41, 0xd2, 0x55, 0xbb, 0x50, 0xf1, 0xc6, 0xbc, 0xa6, 0xc5, 0x3a, 0xfd, 0x9b, 0x75, 0x3e, 0xf6, 0x1a, 0xa7, 0xb2, 0x6e, 0x64, 0x12, 0xdc, 0x3c, 0xe5, 0xf6, 0xfc, 0x3b, 0xfa, 0x43, 0x81, 0xd4, 0xa5, 0xee, 0xf5, 0x9c, 0x47, 0x2f, 0xd0, 0x9c, 0xde, 0xa1, 0x48, 0x91, 0x9a, 0x34, 0xc1, - /* (2^160)P */ 0x37, 0x1b, 0xb3, 0x88, 0xc9, 0x98, 0x4e, 0xfb, 0x84, 0x4f, 0x2b, 0x0a, 0xb6, 0x8f, 0x35, 0x15, 0xcd, 0x61, 0x7a, 0x5f, 0x5c, 0xa0, 0xca, 0x23, 0xa0, 0x93, 0x1f, 0xcc, 0x3c, 0x39, 0x3a, 0x24, 0xa7, 0x49, 0xad, 0x8d, 0x59, 0xcc, 0x94, 0x5a, 0x16, 0xf5, 0x70, 0xe8, 0x52, 0x1e, 0xee, 0x20, 0x30, 0x17, 0x7e, 0xf0, 0x4c, 0x93, 0x06, 0x5a, - /* (2^161)P */ 0x81, 0xba, 0x3b, 0xd7, 0x3e, 0xb4, 0x32, 0x3a, 0x22, 0x39, 0x2a, 0xfc, 0x19, 0xd9, 0xd2, 0xf6, 0xc5, 0x79, 0x6c, 0x0e, 0xde, 0xda, 0x01, 0xff, 0x52, 0xfb, 0xb6, 0x95, 0x4e, 0x7a, 0x10, 0xb8, 0x06, 0x86, 0x3c, 0xcd, 0x56, 0xd6, 0x15, 0xbf, 0x6e, 0x3e, 0x4f, 0x35, 0x5e, 0xca, 0xbc, 0xa5, 0x95, 0xa2, 0xdf, 0x2d, 0x1d, 0xaf, 0x59, 0xf9, - /* (2^162)P */ 0x69, 0xe5, 0xe2, 0xfa, 0xc9, 0x7f, 0xdd, 0x09, 0xf5, 0x6b, 0x4e, 0x2e, 0xbe, 0xb4, 0xbf, 0x3e, 0xb2, 0xf2, 0x81, 0x30, 0xe1, 0x07, 0xa8, 0x0d, 0x2b, 0xd2, 0x5a, 0x55, 0xbe, 0x4b, 0x86, 0x5d, 0xb0, 0x5e, 0x7c, 0x8f, 0xc1, 0x3c, 0x81, 0x4c, 0xf7, 0x6d, 0x7d, 0xe6, 0x4f, 0x8a, 0x85, 0xc2, 0x2f, 0x28, 0xef, 0x8c, 0x69, 0xc2, 0xc2, 0x1a, - /* (2^163)P */ 0xd9, 0xe4, 0x0e, 0x1e, 0xc2, 0xf7, 0x2f, 0x9f, 0xa1, 0x40, 0xfe, 0x46, 0x16, 0xaf, 0x2e, 0xd1, 0xec, 0x15, 0x9b, 0x61, 0x92, 0xce, 0xfc, 0x10, 0x43, 0x1d, 0x00, 0xf6, 0xbe, 0x20, 0x80, 0x80, 0x6f, 0x3c, 0x16, 0x94, 0x59, 0xba, 0x03, 0x53, 0x6e, 0xb6, 0xdd, 0x25, 0x7b, 0x86, 0xbf, 0x96, 0xf4, 0x2f, 0xa1, 0x96, 0x8d, 0xf9, 0xb3, 0x29, - /* (2^164)P */ 0x3b, 0x04, 0x60, 0x6e, 0xce, 0xab, 0xd2, 0x63, 0x18, 0x53, 0x88, 0x16, 0x4a, 0x6a, 0xab, 0x72, 0x03, 0x68, 0xa5, 0xd4, 0x0d, 0xb2, 0x82, 0x81, 0x1f, 0x2b, 0x5c, 0x75, 0xe8, 0xd2, 0x1d, 0x7f, 0xe7, 0x1b, 0x35, 0x02, 0xde, 0xec, 0xbd, 0xcb, 0xc7, 0x01, 0xd3, 0x95, 0x61, 0xfe, 0xb2, 0x7a, 0x66, 0x09, 0x4c, 0x6d, 0xfd, 0x39, 0xf7, 0x52, - /* (2^165)P */ 0x42, 0xc1, 0x5f, 0xf8, 0x35, 0x52, 0xc1, 0xfe, 0xc5, 0x11, 0x80, 0x1c, 0x11, 0x46, 0x31, 0x11, 0xbe, 0xd0, 0xc4, 0xb6, 0x07, 0x13, 0x38, 0xa0, 0x8d, 0x65, 0xf0, 0x56, 0x9e, 0x16, 0xbf, 0x9d, 0xcd, 0x51, 0x34, 0xf9, 0x08, 0x48, 0x7b, 0x76, 0x0c, 0x7b, 0x30, 0x07, 0xa8, 0x76, 0xaf, 0xa3, 0x29, 0x38, 0xb0, 0x58, 0xde, 0x72, 0x4b, 0x45, - /* (2^166)P */ 0xd4, 0x16, 0xa7, 0xc0, 0xb4, 0x9f, 0xdf, 0x1a, 0x37, 0xc8, 0x35, 0xed, 0xc5, 0x85, 0x74, 0x64, 0x09, 0x22, 0xef, 0xe9, 0x0c, 0xaf, 0x12, 0x4c, 0x9e, 0xf8, 0x47, 0x56, 0xe0, 0x7f, 0x4e, 0x24, 0x6b, 0x0c, 0xe7, 0xad, 0xc6, 0x47, 0x1d, 0xa4, 0x0d, 0x86, 0x89, 0x65, 0xe8, 0x5f, 0x71, 0xc7, 0xe9, 0xcd, 0xec, 0x6c, 0x62, 0xc7, 0xe3, 0xb3, - /* (2^167)P */ 0xb5, 0xea, 0x86, 0xe3, 0x15, 0x18, 0x3f, 0x6d, 0x7b, 0x05, 0x95, 0x15, 0x53, 0x26, 0x1c, 0xeb, 0xbe, 0x7e, 0x16, 0x42, 0x4b, 0xa2, 0x3d, 0xdd, 0x0e, 0xff, 0xba, 0x67, 0xb5, 0xae, 0x7a, 0x17, 0xde, 0x23, 0xad, 0x14, 0xcc, 0xd7, 0xaf, 0x57, 0x01, 0xe0, 0xdd, 0x48, 0xdd, 0xd7, 0xe3, 0xdf, 0xe9, 0x2d, 0xda, 0x67, 0xa4, 0x9f, 0x29, 0x04, - /* (2^168)P */ 0x16, 0x53, 0xe6, 0x9c, 0x4e, 0xe5, 0x1e, 0x70, 0x81, 0x25, 0x02, 0x9b, 0x47, 0x6d, 0xd2, 0x08, 0x73, 0xbe, 0x0a, 0xf1, 0x7b, 0xeb, 0x24, 0xeb, 0x38, 0x23, 0x5c, 0xb6, 0x3e, 0xce, 0x1e, 0xe3, 0xbc, 0x82, 0x35, 0x1f, 0xaf, 0x3a, 0x3a, 0xe5, 0x4e, 0xc1, 0xca, 0xbf, 0x47, 0xb4, 0xbb, 0xbc, 0x5f, 0xea, 0xc6, 0xca, 0xf3, 0xa0, 0xa2, 0x73, - /* (2^169)P */ 0xef, 0xa4, 0x7a, 0x4e, 0xe4, 0xc7, 0xb6, 0x43, 0x2e, 0xa5, 0xe4, 0xa5, 0xba, 0x1e, 0xa5, 0xfe, 0x9e, 0xce, 0xa9, 0x80, 0x04, 0xcb, 0x4f, 0xd8, 0x74, 0x05, 0x48, 0xfa, 0x99, 0x11, 0x5d, 0x97, 0x3b, 0x07, 0x0d, 0xdd, 0xe6, 0xb1, 0x74, 0x87, 0x1a, 0xd3, 0x26, 0xb7, 0x8f, 0xe1, 0x63, 0x3d, 0xec, 0x53, 0x93, 0xb0, 0x81, 0x78, 0x34, 0xa4, - /* (2^170)P */ 0xe1, 0xe7, 0xd4, 0x58, 0x9d, 0x0e, 0x8b, 0x65, 0x66, 0x37, 0x16, 0x48, 0x6f, 0xaa, 0x42, 0x37, 0x77, 0xad, 0xb1, 0x56, 0x48, 0xdf, 0x65, 0x36, 0x30, 0xb8, 0x00, 0x12, 0xd8, 0x32, 0x28, 0x7f, 0xc1, 0x71, 0xeb, 0x93, 0x0f, 0x48, 0x04, 0xe1, 0x5a, 0x6a, 0x96, 0xc1, 0xca, 0x89, 0x6d, 0x1b, 0x82, 0x4c, 0x18, 0x6d, 0x55, 0x4b, 0xea, 0xfd, - /* (2^171)P */ 0x62, 0x1a, 0x53, 0xb4, 0xb1, 0xbe, 0x6f, 0x15, 0x18, 0x88, 0xd4, 0x66, 0x61, 0xc7, 0x12, 0x69, 0x02, 0xbd, 0x03, 0x23, 0x2b, 0xef, 0xf9, 0x54, 0xa4, 0x85, 0xa8, 0xe3, 0xb7, 0xbd, 0xa9, 0xa3, 0xf3, 0x2a, 0xdd, 0xf1, 0xd4, 0x03, 0x0f, 0xa9, 0xa1, 0xd8, 0xa3, 0xcd, 0xb2, 0x71, 0x90, 0x4b, 0x35, 0x62, 0xf2, 0x2f, 0xce, 0x67, 0x1f, 0xaa, - /* (2^172)P */ 0x9e, 0x1e, 0xcd, 0x43, 0x7e, 0x87, 0x37, 0x94, 0x3a, 0x97, 0x4c, 0x7e, 0xee, 0xc9, 0x37, 0x85, 0xf1, 0xd9, 0x4f, 0xbf, 0xf9, 0x6f, 0x39, 0x9a, 0x39, 0x87, 0x2e, 0x25, 0x84, 0x42, 0xc3, 0x80, 0xcb, 0x07, 0x22, 0xae, 0x30, 0xd5, 0x50, 0xa1, 0x23, 0xcc, 0x31, 0x81, 0x9d, 0xf1, 0x30, 0xd9, 0x2b, 0x73, 0x41, 0x16, 0x50, 0xab, 0x2d, 0xa2, - /* (2^173)P */ 0xa4, 0x69, 0x4f, 0xa1, 0x4e, 0xb9, 0xbf, 0x14, 0xe8, 0x2b, 0x04, 0x93, 0xb7, 0x6e, 0x9f, 0x7d, 0x73, 0x0a, 0xc5, 0x14, 0xb8, 0xde, 0x8c, 0xc1, 0xfe, 0xc0, 0xa7, 0xa4, 0xcc, 0x42, 0x42, 0x81, 0x15, 0x65, 0x8a, 0x80, 0xb9, 0xde, 0x1f, 0x60, 0x33, 0x0e, 0xcb, 0xfc, 0xe0, 0xdb, 0x83, 0xa1, 0xe5, 0xd0, 0x16, 0x86, 0x2c, 0xe2, 0x87, 0xed, - /* (2^174)P */ 0x7a, 0xc0, 0xeb, 0x6b, 0xf6, 0x0d, 0x4c, 0x6d, 0x1e, 0xdb, 0xab, 0xe7, 0x19, 0x45, 0xc6, 0xe3, 0xb2, 0x06, 0xbb, 0xbc, 0x70, 0x99, 0x83, 0x33, 0xeb, 0x28, 0xc8, 0x77, 0xf6, 0x4d, 0x01, 0xb7, 0x59, 0xa0, 0xd2, 0xb3, 0x2a, 0x72, 0x30, 0xe7, 0x11, 0x39, 0xb6, 0x41, 0x29, 0x65, 0x5a, 0x14, 0xb9, 0x86, 0x08, 0xe0, 0x7d, 0x32, 0x8c, 0xf0, - /* (2^175)P */ 0x5c, 0x11, 0x30, 0x9e, 0x05, 0x27, 0xf5, 0x45, 0x0f, 0xb3, 0xc9, 0x75, 0xc3, 0xd7, 0xe1, 0x82, 0x3b, 0x8e, 0x87, 0x23, 0x00, 0x15, 0x19, 0x07, 0xd9, 0x21, 0x53, 0xc7, 0xf1, 0xa3, 0xbf, 0x70, 0x64, 0x15, 0x18, 0xca, 0x23, 0x9e, 0xd3, 0x08, 0xc3, 0x2a, 0x8b, 0xe5, 0x83, 0x04, 0x89, 0x14, 0xfd, 0x28, 0x25, 0x1c, 0xe3, 0x26, 0xa7, 0x22, - /* (2^176)P */ 0xdc, 0xd4, 0x75, 0x60, 0x99, 0x94, 0xea, 0x09, 0x8e, 0x8a, 0x3c, 0x1b, 0xf9, 0xbd, 0x33, 0x0d, 0x51, 0x3d, 0x12, 0x6f, 0x4e, 0x72, 0xe0, 0x17, 0x20, 0xe9, 0x75, 0xe6, 0x3a, 0xb2, 0x13, 0x83, 0x4e, 0x7a, 0x08, 0x9e, 0xd1, 0x04, 0x5f, 0x6b, 0x42, 0x0b, 0x76, 0x2a, 0x2d, 0x77, 0x53, 0x6c, 0x65, 0x6d, 0x8e, 0x25, 0x3c, 0xb6, 0x8b, 0x69, - /* (2^177)P */ 0xb9, 0x49, 0x28, 0xd0, 0xdc, 0x6c, 0x8f, 0x4c, 0xc9, 0x14, 0x8a, 0x38, 0xa3, 0xcb, 0xc4, 0x9d, 0x53, 0xcf, 0xe9, 0xe3, 0xcf, 0xe0, 0xb1, 0xf2, 0x1b, 0x4c, 0x7f, 0x83, 0x2a, 0x7a, 0xe9, 0x8b, 0x3b, 0x86, 0x61, 0x30, 0xe9, 0x99, 0xbd, 0xba, 0x19, 0x6e, 0x65, 0x2a, 0x12, 0x3e, 0x9c, 0xa8, 0xaf, 0xc3, 0xcf, 0xf8, 0x1f, 0x77, 0x86, 0xea, - /* (2^178)P */ 0x30, 0xde, 0xe7, 0xff, 0x54, 0xf7, 0xa2, 0x59, 0xf6, 0x0b, 0xfb, 0x7a, 0xf2, 0x39, 0xf0, 0xdb, 0x39, 0xbc, 0xf0, 0xfa, 0x60, 0xeb, 0x6b, 0x4f, 0x47, 0x17, 0xc8, 0x00, 0x65, 0x6d, 0x25, 0x1c, 0xd0, 0x48, 0x56, 0x53, 0x45, 0x11, 0x30, 0x02, 0x49, 0x20, 0x27, 0xac, 0xf2, 0x4c, 0xac, 0x64, 0x3d, 0x52, 0xb8, 0x89, 0xe0, 0x93, 0x16, 0x0f, - /* (2^179)P */ 0x84, 0x09, 0xba, 0x40, 0xb2, 0x2f, 0xa3, 0xa8, 0xc2, 0xba, 0x46, 0x33, 0x05, 0x9d, 0x62, 0xad, 0xa1, 0x3c, 0x33, 0xef, 0x0d, 0xeb, 0xf0, 0x77, 0x11, 0x5a, 0xb0, 0x21, 0x9c, 0xdf, 0x55, 0x24, 0x25, 0x35, 0x51, 0x61, 0x92, 0xf0, 0xb1, 0xce, 0xf5, 0xd4, 0x7b, 0x6c, 0x21, 0x9d, 0x56, 0x52, 0xf8, 0xa1, 0x4c, 0xe9, 0x27, 0x55, 0xac, 0x91, - /* (2^180)P */ 0x03, 0x3e, 0x30, 0xd2, 0x0a, 0xfa, 0x7d, 0x82, 0x3d, 0x1f, 0x8b, 0xcb, 0xb6, 0x04, 0x5c, 0xcc, 0x8b, 0xda, 0xe2, 0x68, 0x74, 0x08, 0x8c, 0x44, 0x83, 0x57, 0x6d, 0x6f, 0x80, 0xb0, 0x7e, 0xa9, 0x82, 0x91, 0x7b, 0x4c, 0x37, 0x97, 0xd1, 0x63, 0xd1, 0xbd, 0x45, 0xe6, 0x8a, 0x86, 0xd6, 0x89, 0x54, 0xfd, 0xd2, 0xb1, 0xd7, 0x54, 0xad, 0xaf, - /* (2^181)P */ 0x8b, 0x33, 0x62, 0x49, 0x9f, 0x63, 0xf9, 0x87, 0x42, 0x58, 0xbf, 0xb3, 0xe6, 0x68, 0x02, 0x60, 0x5c, 0x76, 0x62, 0xf7, 0x61, 0xd7, 0x36, 0x31, 0xf7, 0x9c, 0xb5, 0xe5, 0x13, 0x6c, 0xea, 0x78, 0xae, 0xcf, 0xde, 0xbf, 0xb6, 0xeb, 0x4f, 0xc8, 0x2a, 0xb4, 0x9a, 0x9f, 0xf3, 0xd1, 0x6a, 0xec, 0x0c, 0xbd, 0x85, 0x98, 0x40, 0x06, 0x1c, 0x2a, - /* (2^182)P */ 0x74, 0x3b, 0xe7, 0x81, 0xd5, 0xae, 0x54, 0x56, 0x03, 0xe8, 0x97, 0x16, 0x76, 0xcf, 0x24, 0x96, 0x96, 0x5b, 0xcc, 0x09, 0xab, 0x23, 0x6f, 0x54, 0xae, 0x8f, 0xe4, 0x12, 0xcb, 0xfd, 0xbc, 0xac, 0x93, 0x45, 0x3d, 0x68, 0x08, 0x22, 0x59, 0xc6, 0xf0, 0x47, 0x19, 0x8c, 0x79, 0x93, 0x1e, 0x0e, 0x30, 0xb0, 0x94, 0xfb, 0x17, 0x1d, 0x5a, 0x12, - /* (2^183)P */ 0x85, 0xff, 0x40, 0x18, 0x85, 0xff, 0x44, 0x37, 0x69, 0x23, 0x4d, 0x34, 0xe1, 0xeb, 0xa3, 0x1b, 0x55, 0x40, 0xc1, 0x64, 0xf4, 0xd4, 0x13, 0x0a, 0x9f, 0xb9, 0x19, 0xfc, 0x88, 0x7d, 0xc0, 0x72, 0xcf, 0x69, 0x2f, 0xd2, 0x0c, 0x82, 0x0f, 0xda, 0x08, 0xba, 0x0f, 0xaa, 0x3b, 0xe9, 0xe5, 0x83, 0x7a, 0x06, 0xe8, 0x1b, 0x38, 0x43, 0xc3, 0x54, - /* (2^184)P */ 0x14, 0xaa, 0xb3, 0x6e, 0xe6, 0x28, 0xee, 0xc5, 0x22, 0x6c, 0x7c, 0xf9, 0xa8, 0x71, 0xcc, 0xfe, 0x68, 0x7e, 0xd3, 0xb8, 0x37, 0x96, 0xca, 0x0b, 0xd9, 0xb6, 0x06, 0xa9, 0xf6, 0x71, 0xe8, 0x31, 0xf7, 0xd8, 0xf1, 0x5d, 0xab, 0xb9, 0xf0, 0x5c, 0x98, 0xcf, 0x22, 0xa2, 0x2a, 0xf6, 0xd0, 0x59, 0xf0, 0x9d, 0xd9, 0x6a, 0x4f, 0x59, 0x57, 0xad, - /* (2^185)P */ 0xd7, 0x2b, 0x3d, 0x38, 0x4c, 0x2e, 0x23, 0x4d, 0x49, 0xa2, 0x62, 0x62, 0xf9, 0x0f, 0xde, 0x08, 0xf3, 0x86, 0x71, 0xb6, 0xc7, 0xf9, 0x85, 0x9c, 0x33, 0xa1, 0xcf, 0x16, 0xaa, 0x60, 0xb9, 0xb7, 0xea, 0xed, 0x01, 0x1c, 0x59, 0xdb, 0x3f, 0x3f, 0x97, 0x2e, 0xf0, 0x09, 0x9f, 0x10, 0x85, 0x5f, 0x53, 0x39, 0xf3, 0x13, 0x40, 0x56, 0x95, 0xf9, - /* (2^186)P */ 0xb4, 0xe3, 0xda, 0xc6, 0x1f, 0x78, 0x8e, 0xac, 0xd4, 0x20, 0x1d, 0xa0, 0xbf, 0x4c, 0x09, 0x16, 0xa7, 0x30, 0xb5, 0x8d, 0x9e, 0xa1, 0x5f, 0x6d, 0x52, 0xf4, 0x71, 0xb6, 0x32, 0x2d, 0x21, 0x51, 0xc6, 0xfc, 0x2f, 0x08, 0xf4, 0x13, 0x6c, 0x55, 0xba, 0x72, 0x81, 0x24, 0x49, 0x0e, 0x4f, 0x06, 0x36, 0x39, 0x6a, 0xc5, 0x81, 0xfc, 0xeb, 0xb2, - /* (2^187)P */ 0x7d, 0x8d, 0xc8, 0x6c, 0xea, 0xb4, 0xb9, 0xe8, 0x40, 0xc9, 0x69, 0xc9, 0x30, 0x05, 0xfd, 0x34, 0x46, 0xfd, 0x94, 0x05, 0x16, 0xf5, 0x4b, 0x13, 0x3d, 0x24, 0x1a, 0xd6, 0x64, 0x2b, 0x9c, 0xe2, 0xa5, 0xd9, 0x98, 0xe0, 0xe8, 0xf4, 0xbc, 0x2c, 0xbd, 0xa2, 0x56, 0xe3, 0x9e, 0x14, 0xdb, 0xbf, 0x05, 0xbf, 0x9a, 0x13, 0x5d, 0xf7, 0x91, 0xa3, - /* (2^188)P */ 0x8b, 0xcb, 0x27, 0xf3, 0x15, 0x26, 0x05, 0x40, 0x0f, 0xa6, 0x15, 0x13, 0x71, 0x95, 0xa2, 0xc6, 0x38, 0x04, 0x67, 0xf8, 0x9a, 0x83, 0x06, 0xaa, 0x25, 0x36, 0x72, 0x01, 0x6f, 0x74, 0x5f, 0xe5, 0x6e, 0x44, 0x99, 0xce, 0x13, 0xbc, 0x82, 0xc2, 0x0d, 0xa4, 0x98, 0x50, 0x38, 0xf3, 0xa2, 0xc5, 0xe5, 0x24, 0x1f, 0x6f, 0x56, 0x3e, 0x07, 0xb2, - /* (2^189)P */ 0xbd, 0x0f, 0x32, 0x60, 0x07, 0xb1, 0xd7, 0x0b, 0x11, 0x07, 0x57, 0x02, 0x89, 0xe8, 0x8b, 0xe8, 0x5a, 0x1f, 0xee, 0x54, 0x6b, 0xff, 0xb3, 0x04, 0x07, 0x57, 0x13, 0x0b, 0x94, 0xa8, 0x4d, 0x81, 0xe2, 0x17, 0x16, 0x45, 0xd4, 0x4b, 0xf7, 0x7e, 0x64, 0x66, 0x20, 0xe8, 0x0b, 0x26, 0xfd, 0xa9, 0x8a, 0x47, 0x52, 0x89, 0x14, 0xd0, 0xd1, 0xa1, - /* (2^190)P */ 0xdc, 0x03, 0xe6, 0x20, 0x44, 0x47, 0x8f, 0x04, 0x16, 0x24, 0x22, 0xc1, 0x55, 0x5c, 0xbe, 0x43, 0xc3, 0x92, 0xc5, 0x54, 0x3d, 0x5d, 0xd1, 0x05, 0x9c, 0xc6, 0x7c, 0xbf, 0x23, 0x84, 0x1a, 0xba, 0x4f, 0x1f, 0xfc, 0xa1, 0xae, 0x1a, 0x64, 0x02, 0x51, 0xf1, 0xcb, 0x7a, 0x20, 0xce, 0xb2, 0x34, 0x3c, 0xca, 0xe0, 0xe4, 0xba, 0x22, 0xd4, 0x7b, - /* (2^191)P */ 0xca, 0xfd, 0xca, 0xd7, 0xde, 0x61, 0xae, 0xf0, 0x79, 0x0c, 0x20, 0xab, 0xbc, 0x6f, 0x4d, 0x61, 0xf0, 0xc7, 0x9c, 0x8d, 0x4b, 0x52, 0xf3, 0xb9, 0x48, 0x63, 0x0b, 0xb6, 0xd2, 0x25, 0x9a, 0x96, 0x72, 0xc1, 0x6b, 0x0c, 0xb5, 0xfb, 0x71, 0xaa, 0xad, 0x47, 0x5b, 0xe7, 0xc0, 0x0a, 0x55, 0xb2, 0xd4, 0x16, 0x2f, 0xb1, 0x01, 0xfd, 0xce, 0x27, - /* (2^192)P */ 0x64, 0x11, 0x4b, 0xab, 0x57, 0x09, 0xc6, 0x49, 0x4a, 0x37, 0xc3, 0x36, 0xc4, 0x7b, 0x81, 0x1f, 0x42, 0xed, 0xbb, 0xe0, 0xa0, 0x8d, 0x51, 0xe6, 0xca, 0x8b, 0xb9, 0xcd, 0x99, 0x2d, 0x91, 0x53, 0xa9, 0x47, 0xcb, 0x32, 0xc7, 0xa4, 0x92, 0xec, 0x46, 0x74, 0x44, 0x6d, 0x71, 0x9f, 0x6d, 0x0c, 0x69, 0xa4, 0xf8, 0xbe, 0x9f, 0x7f, 0xa0, 0xd7, - /* (2^193)P */ 0x5f, 0x33, 0xb6, 0x91, 0xc8, 0xa5, 0x3f, 0x5d, 0x7f, 0x38, 0x6e, 0x74, 0x20, 0x4a, 0xd6, 0x2b, 0x98, 0x2a, 0x41, 0x4b, 0x83, 0x64, 0x0b, 0x92, 0x7a, 0x06, 0x1e, 0xc6, 0x2c, 0xf6, 0xe4, 0x91, 0xe5, 0xb1, 0x2e, 0x6e, 0x4e, 0xa8, 0xc8, 0x14, 0x32, 0x57, 0x44, 0x1c, 0xe4, 0xb9, 0x7f, 0x54, 0x51, 0x08, 0x81, 0xaa, 0x4e, 0xce, 0xa1, 0x5d, - /* (2^194)P */ 0x5c, 0xd5, 0x9b, 0x5e, 0x7c, 0xb5, 0xb1, 0x52, 0x73, 0x00, 0x41, 0x56, 0x79, 0x08, 0x7e, 0x07, 0x28, 0x06, 0xa6, 0xfb, 0x7f, 0x69, 0xbd, 0x7a, 0x3c, 0xae, 0x9f, 0x39, 0xbb, 0x54, 0xa2, 0x79, 0xb9, 0x0e, 0x7f, 0xbb, 0xe0, 0xe6, 0xb7, 0x27, 0x64, 0x38, 0x45, 0xdb, 0x84, 0xe4, 0x61, 0x72, 0x3f, 0xe2, 0x24, 0xfe, 0x7a, 0x31, 0x9a, 0xc9, - /* (2^195)P */ 0xa1, 0xd2, 0xa4, 0xee, 0x24, 0x96, 0xe5, 0x5b, 0x79, 0x78, 0x3c, 0x7b, 0x82, 0x3b, 0x8b, 0x58, 0x0b, 0xa3, 0x63, 0x2d, 0xbc, 0x75, 0x46, 0xe8, 0x83, 0x1a, 0xc0, 0x2a, 0x92, 0x61, 0xa8, 0x75, 0x37, 0x3c, 0xbf, 0x0f, 0xef, 0x8f, 0x6c, 0x97, 0x75, 0x10, 0x05, 0x7a, 0xde, 0x23, 0xe8, 0x2a, 0x35, 0xeb, 0x41, 0x64, 0x7d, 0xcf, 0xe0, 0x52, - /* (2^196)P */ 0x4a, 0xd0, 0x49, 0x93, 0xae, 0xf3, 0x24, 0x8c, 0xe1, 0x09, 0x98, 0x45, 0xd8, 0xb9, 0xfe, 0x8e, 0x8c, 0xa8, 0x2c, 0xc9, 0x9f, 0xce, 0x01, 0xdc, 0x38, 0x11, 0xab, 0x85, 0xb9, 0xe8, 0x00, 0x51, 0xfd, 0x82, 0xe1, 0x9b, 0x4e, 0xfc, 0xb5, 0x2a, 0x0f, 0x8b, 0xda, 0x4e, 0x02, 0xca, 0xcc, 0xe3, 0x91, 0xc4, 0xe0, 0xcf, 0x7b, 0xd6, 0xe6, 0x6a, - /* (2^197)P */ 0xfe, 0x11, 0xd7, 0xaa, 0xe3, 0x0c, 0x52, 0x2e, 0x04, 0xe0, 0xe0, 0x61, 0xc8, 0x05, 0xd7, 0x31, 0x4c, 0xc3, 0x9b, 0x2d, 0xce, 0x59, 0xbe, 0x12, 0xb7, 0x30, 0x21, 0xfc, 0x81, 0xb8, 0x5e, 0x57, 0x73, 0xd0, 0xad, 0x8e, 0x9e, 0xe4, 0xeb, 0xcd, 0xcf, 0xd2, 0x0f, 0x01, 0x35, 0x16, 0xed, 0x7a, 0x43, 0x8e, 0x42, 0xdc, 0xea, 0x4c, 0xa8, 0x7c, - /* (2^198)P */ 0x37, 0x26, 0xcc, 0x76, 0x0b, 0xe5, 0x76, 0xdd, 0x3e, 0x19, 0x3c, 0xc4, 0x6c, 0x7f, 0xd0, 0x03, 0xc1, 0xb8, 0x59, 0x82, 0xca, 0x36, 0xc1, 0xe4, 0xc8, 0xb2, 0x83, 0x69, 0x9c, 0xc5, 0x9d, 0x12, 0x82, 0x1c, 0xea, 0xb2, 0x84, 0x9f, 0xf3, 0x52, 0x6b, 0xbb, 0xd8, 0x81, 0x56, 0x83, 0x04, 0x66, 0x05, 0x22, 0x49, 0x37, 0x93, 0xb1, 0xfd, 0xd5, - /* (2^199)P */ 0xaf, 0x96, 0xbf, 0x03, 0xbe, 0xe6, 0x5d, 0x78, 0x19, 0xba, 0x37, 0x46, 0x0a, 0x2b, 0x52, 0x7c, 0xd8, 0x51, 0x9e, 0x3d, 0x29, 0x42, 0xdb, 0x0e, 0x31, 0x20, 0x94, 0xf8, 0x43, 0x9a, 0x2d, 0x22, 0xd3, 0xe3, 0xa1, 0x79, 0x68, 0xfb, 0x2d, 0x7e, 0xd6, 0x79, 0xda, 0x0b, 0xc6, 0x5b, 0x76, 0x68, 0xf0, 0xfe, 0x72, 0x59, 0xbb, 0xa1, 0x9c, 0x74, - /* (2^200)P */ 0x0a, 0xd9, 0xec, 0xc5, 0xbd, 0xf0, 0xda, 0xcf, 0x82, 0xab, 0x46, 0xc5, 0x32, 0x13, 0xdc, 0x5b, 0xac, 0xc3, 0x53, 0x9a, 0x7f, 0xef, 0xa5, 0x40, 0x5a, 0x1f, 0xc1, 0x12, 0x91, 0x54, 0x83, 0x6a, 0xb0, 0x9a, 0x85, 0x4d, 0xbf, 0x36, 0x8e, 0xd3, 0xa2, 0x2b, 0xe5, 0xd6, 0xc6, 0xe1, 0x58, 0x5b, 0x82, 0x9b, 0xc8, 0xf2, 0x03, 0xba, 0xf5, 0x92, - /* (2^201)P */ 0xfb, 0x21, 0x7e, 0xde, 0xe7, 0xb4, 0xc0, 0x56, 0x86, 0x3a, 0x5b, 0x78, 0xf8, 0xf0, 0xf4, 0xe7, 0x5c, 0x00, 0xd2, 0xd7, 0xd6, 0xf8, 0x75, 0x5e, 0x0f, 0x3e, 0xd1, 0x4b, 0x77, 0xd8, 0xad, 0xb0, 0xc9, 0x8b, 0x59, 0x7d, 0x30, 0x76, 0x64, 0x7a, 0x76, 0xd9, 0x51, 0x69, 0xfc, 0xbd, 0x8e, 0xb5, 0x55, 0xe0, 0xd2, 0x07, 0x15, 0xa9, 0xf7, 0xa4, - /* (2^202)P */ 0xaa, 0x2d, 0x2f, 0x2b, 0x3c, 0x15, 0xdd, 0xcd, 0xe9, 0x28, 0x82, 0x4f, 0xa2, 0xaa, 0x31, 0x48, 0xcc, 0xfa, 0x07, 0x73, 0x8a, 0x34, 0x74, 0x0d, 0xab, 0x1a, 0xca, 0xd2, 0xbf, 0x3a, 0xdb, 0x1a, 0x5f, 0x50, 0x62, 0xf4, 0x6b, 0x83, 0x38, 0x43, 0x96, 0xee, 0x6b, 0x39, 0x1e, 0xf0, 0x17, 0x80, 0x1e, 0x9b, 0xed, 0x2b, 0x2f, 0xcc, 0x65, 0xf7, - /* (2^203)P */ 0x03, 0xb3, 0x23, 0x9c, 0x0d, 0xd1, 0xeb, 0x7e, 0x34, 0x17, 0x8a, 0x4c, 0xde, 0x54, 0x39, 0xc4, 0x11, 0x82, 0xd3, 0xa4, 0x00, 0x32, 0x95, 0x9c, 0xa6, 0x64, 0x76, 0x6e, 0xd6, 0x53, 0x27, 0xb4, 0x6a, 0x14, 0x8c, 0x54, 0xf6, 0x58, 0x9e, 0x22, 0x4a, 0x55, 0x18, 0x77, 0xd0, 0x08, 0x6b, 0x19, 0x8a, 0xb5, 0xe7, 0x19, 0xb8, 0x60, 0x92, 0xb1, - /* (2^204)P */ 0x66, 0xec, 0xf3, 0x12, 0xde, 0x67, 0x7f, 0xd4, 0x5b, 0xf6, 0x70, 0x64, 0x0a, 0xb5, 0xc2, 0xf9, 0xb3, 0x64, 0xab, 0x56, 0x46, 0xc7, 0x93, 0xc2, 0x8b, 0x2d, 0xd0, 0xd6, 0x39, 0x3b, 0x1f, 0xcd, 0xb3, 0xac, 0xcc, 0x2c, 0x27, 0x6a, 0xbc, 0xb3, 0x4b, 0xa8, 0x3c, 0x69, 0x20, 0xe2, 0x18, 0x35, 0x17, 0xe1, 0x8a, 0xd3, 0x11, 0x74, 0xaa, 0x4d, - /* (2^205)P */ 0x96, 0xc4, 0x16, 0x7e, 0xfd, 0xf5, 0xd0, 0x7d, 0x1f, 0x32, 0x1b, 0xdb, 0xa6, 0xfd, 0x51, 0x75, 0x4d, 0xd7, 0x00, 0xe5, 0x7f, 0x58, 0x5b, 0xeb, 0x4b, 0x6a, 0x78, 0xfe, 0xe5, 0xd6, 0x8f, 0x99, 0x17, 0xca, 0x96, 0x45, 0xf7, 0x52, 0xdf, 0x84, 0x06, 0x77, 0xb9, 0x05, 0x63, 0x5d, 0xe9, 0x91, 0xb1, 0x4b, 0x82, 0x5a, 0xdb, 0xd7, 0xca, 0x69, - /* (2^206)P */ 0x02, 0xd3, 0x38, 0x38, 0x87, 0xea, 0xbd, 0x9f, 0x11, 0xca, 0xf3, 0x21, 0xf1, 0x9b, 0x35, 0x97, 0x98, 0xff, 0x8e, 0x6d, 0x3d, 0xd6, 0xb2, 0xfa, 0x68, 0xcb, 0x7e, 0x62, 0x85, 0xbb, 0xc7, 0x5d, 0xee, 0x32, 0x30, 0x2e, 0x71, 0x96, 0x63, 0x43, 0x98, 0xc4, 0xa7, 0xde, 0x60, 0xb2, 0xd9, 0x43, 0x4a, 0xfa, 0x97, 0x2d, 0x5f, 0x21, 0xd4, 0xfe, - /* (2^207)P */ 0x3b, 0x20, 0x29, 0x07, 0x07, 0xb5, 0x78, 0xc3, 0xc7, 0xab, 0x56, 0xba, 0x40, 0xde, 0x1d, 0xcf, 0xc3, 0x00, 0x56, 0x21, 0x0c, 0xc8, 0x42, 0xd9, 0x0e, 0xcd, 0x02, 0x7c, 0x07, 0xb9, 0x11, 0xd7, 0x96, 0xaf, 0xff, 0xad, 0xc5, 0xba, 0x30, 0x6d, 0x82, 0x3a, 0xbf, 0xef, 0x7b, 0xf7, 0x0a, 0x74, 0xbd, 0x31, 0x0c, 0xe4, 0xec, 0x1a, 0xe5, 0xc5, - /* (2^208)P */ 0xcc, 0xf2, 0x28, 0x16, 0x12, 0xbf, 0xef, 0x85, 0xbc, 0xf7, 0xcb, 0x9f, 0xdb, 0xa8, 0xb2, 0x49, 0x53, 0x48, 0xa8, 0x24, 0xa8, 0x68, 0x8d, 0xbb, 0x21, 0x0a, 0x5a, 0xbd, 0xb2, 0x91, 0x61, 0x47, 0xc4, 0x43, 0x08, 0xa6, 0x19, 0xef, 0x8e, 0x88, 0x39, 0xc6, 0x33, 0x30, 0xf3, 0x0e, 0xc5, 0x92, 0x66, 0xd6, 0xfe, 0xc5, 0x12, 0xd9, 0x4c, 0x2d, - /* (2^209)P */ 0x30, 0x34, 0x07, 0xbf, 0x9c, 0x5a, 0x4e, 0x65, 0xf1, 0x39, 0x35, 0x38, 0xae, 0x7b, 0x55, 0xac, 0x6a, 0x92, 0x24, 0x7e, 0x50, 0xd3, 0xba, 0x78, 0x51, 0xfe, 0x4d, 0x32, 0x05, 0x11, 0xf5, 0x52, 0xf1, 0x31, 0x45, 0x39, 0x98, 0x7b, 0x28, 0x56, 0xc3, 0x5d, 0x4f, 0x07, 0x6f, 0x84, 0xb8, 0x1a, 0x58, 0x0b, 0xc4, 0x7c, 0xc4, 0x8d, 0x32, 0x8e, - /* (2^210)P */ 0x7e, 0xaf, 0x98, 0xce, 0xc5, 0x2b, 0x9d, 0xf6, 0xfa, 0x2c, 0xb6, 0x2a, 0x5a, 0x1d, 0xc0, 0x24, 0x8d, 0xa4, 0xce, 0xb1, 0x12, 0x01, 0xf9, 0x79, 0xc6, 0x79, 0x38, 0x0c, 0xd4, 0x07, 0xc9, 0xf7, 0x37, 0xa1, 0x0b, 0xfe, 0x72, 0xec, 0x5d, 0xd6, 0xb0, 0x1c, 0x70, 0xbe, 0x70, 0x01, 0x13, 0xe0, 0x86, 0x95, 0xc7, 0x2e, 0x12, 0x3b, 0xe6, 0xa6, - /* (2^211)P */ 0x24, 0x82, 0x67, 0xe0, 0x14, 0x7b, 0x56, 0x08, 0x38, 0x44, 0xdb, 0xa0, 0x3a, 0x05, 0x47, 0xb2, 0xc0, 0xac, 0xd1, 0xcc, 0x3f, 0x82, 0xb8, 0x8a, 0x88, 0xbc, 0xf5, 0x33, 0xa1, 0x35, 0x0f, 0xf6, 0xe2, 0xef, 0x6c, 0xf7, 0x37, 0x9e, 0xe8, 0x10, 0xca, 0xb0, 0x8e, 0x80, 0x86, 0x00, 0x23, 0xd0, 0x4a, 0x76, 0x9f, 0xf7, 0x2c, 0x52, 0x15, 0x0e, - /* (2^212)P */ 0x5e, 0x49, 0xe1, 0x2c, 0x9a, 0x01, 0x76, 0xa6, 0xb3, 0x07, 0x5b, 0xa4, 0x07, 0xef, 0x1d, 0xc3, 0x6a, 0xbb, 0x64, 0xbe, 0x71, 0x15, 0x6e, 0x32, 0x31, 0x46, 0x9a, 0x9e, 0x8f, 0x45, 0x73, 0xce, 0x0b, 0x94, 0x1a, 0x52, 0x07, 0xf4, 0x50, 0x30, 0x49, 0x53, 0x50, 0xfb, 0x71, 0x1f, 0x5a, 0x03, 0xa9, 0x76, 0xf2, 0x8f, 0x42, 0xff, 0xed, 0xed, - /* (2^213)P */ 0xed, 0x08, 0xdb, 0x91, 0x1c, 0xee, 0xa2, 0xb4, 0x47, 0xa2, 0xfa, 0xcb, 0x03, 0xd1, 0xff, 0x8c, 0xad, 0x64, 0x50, 0x61, 0xcd, 0xfc, 0x88, 0xa0, 0x31, 0x95, 0x30, 0xb9, 0x58, 0xdd, 0xd7, 0x43, 0xe4, 0x46, 0xc2, 0x16, 0xd9, 0x72, 0x4a, 0x56, 0x51, 0x70, 0x85, 0xf1, 0xa1, 0x80, 0x40, 0xd5, 0xba, 0x67, 0x81, 0xda, 0xcd, 0x03, 0xea, 0x51, - /* (2^214)P */ 0x42, 0x50, 0xf0, 0xef, 0x37, 0x61, 0x72, 0x85, 0xe1, 0xf1, 0xff, 0x6f, 0x3d, 0xe8, 0x7b, 0x21, 0x5c, 0xe5, 0x50, 0x03, 0xde, 0x00, 0xc1, 0xf7, 0x3a, 0x55, 0x12, 0x1c, 0x9e, 0x1e, 0xce, 0xd1, 0x2f, 0xaf, 0x05, 0x70, 0x5b, 0x47, 0xf2, 0x04, 0x7a, 0x89, 0xbc, 0x78, 0xa6, 0x65, 0x6c, 0xaa, 0x3c, 0xa2, 0x3c, 0x8b, 0x5c, 0xa9, 0x22, 0x48, - /* (2^215)P */ 0x7e, 0x8c, 0x8f, 0x2f, 0x60, 0xe3, 0x5a, 0x94, 0xd4, 0xce, 0xdd, 0x9d, 0x83, 0x3b, 0x77, 0x78, 0x43, 0x1d, 0xfd, 0x8f, 0xc8, 0xe8, 0x02, 0x90, 0xab, 0xf6, 0xc9, 0xfc, 0xf1, 0x63, 0xaa, 0x5f, 0x42, 0xf1, 0x78, 0x34, 0x64, 0x16, 0x75, 0x9c, 0x7d, 0xd0, 0xe4, 0x74, 0x5a, 0xa8, 0xfb, 0xcb, 0xac, 0x20, 0xa3, 0xc2, 0xa6, 0x20, 0xf8, 0x1b, - /* (2^216)P */ 0x00, 0x4f, 0x1e, 0x56, 0xb5, 0x34, 0xb2, 0x87, 0x31, 0xe5, 0xee, 0x8d, 0xf1, 0x41, 0x67, 0xb7, 0x67, 0x3a, 0x54, 0x86, 0x5c, 0xf0, 0x0b, 0x37, 0x2f, 0x1b, 0x92, 0x5d, 0x58, 0x93, 0xdc, 0xd8, 0x58, 0xcc, 0x9e, 0x67, 0xd0, 0x97, 0x3a, 0xaf, 0x49, 0x39, 0x2d, 0x3b, 0xd8, 0x98, 0xfb, 0x76, 0x6b, 0xe7, 0xaf, 0xc3, 0x45, 0x44, 0x53, 0x94, - /* (2^217)P */ 0x30, 0xbd, 0x90, 0x75, 0xd3, 0xbd, 0x3b, 0x58, 0x27, 0x14, 0x9f, 0x6b, 0xd4, 0x31, 0x99, 0xcd, 0xde, 0x3a, 0x21, 0x1e, 0xb4, 0x02, 0xe4, 0x33, 0x04, 0x02, 0xb0, 0x50, 0x66, 0x68, 0x90, 0xdd, 0x7b, 0x69, 0x31, 0xd9, 0xcf, 0x68, 0x73, 0xf1, 0x60, 0xdd, 0xc8, 0x1d, 0x5d, 0xe3, 0xd6, 0x5b, 0x2a, 0xa4, 0xea, 0xc4, 0x3f, 0x08, 0xcd, 0x9c, - /* (2^218)P */ 0x6b, 0x1a, 0xbf, 0x55, 0xc1, 0x1b, 0x0c, 0x05, 0x09, 0xdf, 0xf5, 0x5e, 0xa3, 0x77, 0x95, 0xe9, 0xdf, 0x19, 0xdd, 0xc7, 0x94, 0xcb, 0x06, 0x73, 0xd0, 0x88, 0x02, 0x33, 0x94, 0xca, 0x7a, 0x2f, 0x8e, 0x3d, 0x72, 0x61, 0x2d, 0x4d, 0xa6, 0x61, 0x1f, 0x32, 0x5e, 0x87, 0x53, 0x36, 0x11, 0x15, 0x20, 0xb3, 0x5a, 0x57, 0x51, 0x93, 0x20, 0xd8, - /* (2^219)P */ 0xb7, 0x56, 0xf4, 0xab, 0x7d, 0x0c, 0xfb, 0x99, 0x1a, 0x30, 0x29, 0xb0, 0x75, 0x2a, 0xf8, 0x53, 0x71, 0x23, 0xbd, 0xa7, 0xd8, 0x0a, 0xe2, 0x27, 0x65, 0xe9, 0x74, 0x26, 0x98, 0x4a, 0x69, 0x19, 0xb2, 0x4d, 0x0a, 0x17, 0x98, 0xb2, 0xa9, 0x57, 0x4e, 0xf6, 0x86, 0xc8, 0x01, 0xa4, 0xc6, 0x98, 0xad, 0x5a, 0x90, 0x2c, 0x05, 0x46, 0x64, 0xb7, - /* (2^220)P */ 0x7b, 0x91, 0xdf, 0xfc, 0xf8, 0x1c, 0x8c, 0x15, 0x9e, 0xf7, 0xd5, 0xa8, 0xe8, 0xe7, 0xe3, 0xa3, 0xb0, 0x04, 0x74, 0xfa, 0x78, 0xfb, 0x26, 0xbf, 0x67, 0x42, 0xf9, 0x8c, 0x9b, 0xb4, 0x69, 0x5b, 0x02, 0x13, 0x6d, 0x09, 0x6c, 0xd6, 0x99, 0x61, 0x7b, 0x89, 0x4a, 0x67, 0x75, 0xa3, 0x98, 0x13, 0x23, 0x1d, 0x18, 0x24, 0x0e, 0xef, 0x41, 0x79, - /* (2^221)P */ 0x86, 0x33, 0xab, 0x08, 0xcb, 0xbf, 0x1e, 0x76, 0x3c, 0x0b, 0xbd, 0x30, 0xdb, 0xe9, 0xa3, 0x35, 0x87, 0x1b, 0xe9, 0x07, 0x00, 0x66, 0x7f, 0x3b, 0x35, 0x0c, 0x8a, 0x3f, 0x61, 0xbc, 0xe0, 0xae, 0xf6, 0xcc, 0x54, 0xe1, 0x72, 0x36, 0x2d, 0xee, 0x93, 0x24, 0xf8, 0xd7, 0xc5, 0xf9, 0xcb, 0xb0, 0xe5, 0x88, 0x0d, 0x23, 0x4b, 0x76, 0x15, 0xa2, - /* (2^222)P */ 0x37, 0xdb, 0x83, 0xd5, 0x6d, 0x06, 0x24, 0x37, 0x1b, 0x15, 0x85, 0x15, 0xe2, 0xc0, 0x4e, 0x02, 0xa9, 0x6d, 0x0a, 0x3a, 0x94, 0x4a, 0x6f, 0x49, 0x00, 0x01, 0x72, 0xbb, 0x60, 0x14, 0x35, 0xae, 0xb4, 0xc6, 0x01, 0x0a, 0x00, 0x9e, 0xc3, 0x58, 0xc5, 0xd1, 0x5e, 0x30, 0x73, 0x96, 0x24, 0x85, 0x9d, 0xf0, 0xf9, 0xec, 0x09, 0xd3, 0xe7, 0x70, - /* (2^223)P */ 0xf3, 0xbd, 0x96, 0x87, 0xe9, 0x71, 0xbd, 0xd6, 0xa2, 0x45, 0xeb, 0x0a, 0xcd, 0x2c, 0xf1, 0x72, 0xa6, 0x31, 0xa9, 0x6f, 0x09, 0xa1, 0x5e, 0xdd, 0xc8, 0x8d, 0x0d, 0xbc, 0x5a, 0x8d, 0xb1, 0x2c, 0x9a, 0xcc, 0x37, 0x74, 0xc2, 0xa9, 0x4e, 0xd6, 0xc0, 0x3c, 0xa0, 0x23, 0xb0, 0xa0, 0x77, 0x14, 0x80, 0x45, 0x71, 0x6a, 0x2d, 0x41, 0xc3, 0x82, - /* (2^224)P */ 0x37, 0x44, 0xec, 0x8a, 0x3e, 0xc1, 0x0c, 0xa9, 0x12, 0x9c, 0x08, 0x88, 0xcb, 0xd9, 0xf8, 0xba, 0x00, 0xd6, 0xc3, 0xdf, 0xef, 0x7a, 0x44, 0x7e, 0x25, 0x69, 0xc9, 0xc1, 0x46, 0xe5, 0x20, 0x9e, 0xcc, 0x0b, 0x05, 0x3e, 0xf4, 0x78, 0x43, 0x0c, 0xa6, 0x2f, 0xc1, 0xfa, 0x70, 0xb2, 0x3c, 0x31, 0x7a, 0x63, 0x58, 0xab, 0x17, 0xcf, 0x4c, 0x4f, - /* (2^225)P */ 0x2b, 0x08, 0x31, 0x59, 0x75, 0x8b, 0xec, 0x0a, 0xa9, 0x79, 0x70, 0xdd, 0xf1, 0x11, 0xc3, 0x11, 0x1f, 0xab, 0x37, 0xaa, 0x26, 0xea, 0x53, 0xc4, 0x79, 0xa7, 0x91, 0x00, 0xaa, 0x08, 0x42, 0xeb, 0x8b, 0x8b, 0xe8, 0xc3, 0x2f, 0xb8, 0x78, 0x90, 0x38, 0x0e, 0x8a, 0x42, 0x0c, 0x0f, 0xbf, 0x3e, 0xf8, 0xd8, 0x07, 0xcf, 0x6a, 0x34, 0xc9, 0xfa, - /* (2^226)P */ 0x11, 0xe0, 0x76, 0x4d, 0x23, 0xc5, 0xa6, 0xcc, 0x9f, 0x9a, 0x2a, 0xde, 0x3a, 0xb5, 0x92, 0x39, 0x19, 0x8a, 0xf1, 0x8d, 0xf9, 0x4d, 0xc9, 0xb4, 0x39, 0x9f, 0x57, 0xd8, 0x72, 0xab, 0x1d, 0x61, 0x6a, 0xb2, 0xff, 0x52, 0xba, 0x54, 0x0e, 0xfb, 0x83, 0x30, 0x8a, 0xf7, 0x3b, 0xf4, 0xd8, 0xae, 0x1a, 0x94, 0x3a, 0xec, 0x63, 0xfe, 0x6e, 0x7c, - /* (2^227)P */ 0xdc, 0x70, 0x8e, 0x55, 0x44, 0xbf, 0xd2, 0x6a, 0xa0, 0x14, 0x61, 0x89, 0xd5, 0x55, 0x45, 0x3c, 0xf6, 0x40, 0x0d, 0x83, 0x85, 0x44, 0xb4, 0x62, 0x56, 0xfe, 0x60, 0xd7, 0x07, 0x1d, 0x47, 0x30, 0x3b, 0x73, 0xa4, 0xb5, 0xb7, 0xea, 0xac, 0xda, 0xf1, 0x17, 0xaa, 0x60, 0xdf, 0xe9, 0x84, 0xda, 0x31, 0x32, 0x61, 0xbf, 0xd0, 0x7e, 0x8a, 0x02, - /* (2^228)P */ 0xb9, 0x51, 0xb3, 0x89, 0x21, 0x5d, 0xa2, 0xfe, 0x79, 0x2a, 0xb3, 0x2a, 0x3b, 0xe6, 0x6f, 0x2b, 0x22, 0x03, 0xea, 0x7b, 0x1f, 0xaf, 0x85, 0xc3, 0x38, 0x55, 0x5b, 0x8e, 0xb4, 0xaa, 0x77, 0xfe, 0x03, 0x6e, 0xda, 0x91, 0x24, 0x0c, 0x48, 0x39, 0x27, 0x43, 0x16, 0xd2, 0x0a, 0x0d, 0x43, 0xa3, 0x0e, 0xca, 0x45, 0xd1, 0x7f, 0xf5, 0xd3, 0x16, - /* (2^229)P */ 0x3d, 0x32, 0x9b, 0x38, 0xf8, 0x06, 0x93, 0x78, 0x5b, 0x50, 0x2b, 0x06, 0xd8, 0x66, 0xfe, 0xab, 0x9b, 0x58, 0xc7, 0xd1, 0x4d, 0xd5, 0xf8, 0x3b, 0x10, 0x7e, 0x85, 0xde, 0x58, 0x4e, 0xdf, 0x53, 0xd9, 0x58, 0xe0, 0x15, 0x81, 0x9f, 0x1a, 0x78, 0xfc, 0x9f, 0x10, 0xc2, 0x23, 0xd6, 0x78, 0xd1, 0x9d, 0xd2, 0xd5, 0x1c, 0x53, 0xe2, 0xc9, 0x76, - /* (2^230)P */ 0x98, 0x1e, 0x38, 0x7b, 0x71, 0x18, 0x4b, 0x15, 0xaf, 0xa1, 0xa6, 0x98, 0xcb, 0x26, 0xa3, 0xc8, 0x07, 0x46, 0xda, 0x3b, 0x70, 0x65, 0xec, 0x7a, 0x2b, 0x34, 0x94, 0xa8, 0xb6, 0x14, 0xf8, 0x1a, 0xce, 0xf7, 0xc8, 0x60, 0xf3, 0x88, 0xf4, 0x33, 0x60, 0x7b, 0xd1, 0x02, 0xe7, 0xda, 0x00, 0x4a, 0xea, 0xd2, 0xfd, 0x88, 0xd2, 0x99, 0x28, 0xf3, - /* (2^231)P */ 0x28, 0x24, 0x1d, 0x26, 0xc2, 0xeb, 0x8b, 0x3b, 0xb4, 0x6b, 0xbe, 0x6b, 0x77, 0xff, 0xf3, 0x21, 0x3b, 0x26, 0x6a, 0x8c, 0x8e, 0x2a, 0x44, 0xa8, 0x01, 0x2b, 0x71, 0xea, 0x64, 0x30, 0xfd, 0xfd, 0x95, 0xcb, 0x39, 0x38, 0x48, 0xfa, 0x96, 0x97, 0x8c, 0x2f, 0x33, 0xca, 0x03, 0xe6, 0xd7, 0x94, 0x55, 0x6c, 0xc3, 0xb3, 0xa8, 0xf7, 0xae, 0x8c, - /* (2^232)P */ 0xea, 0x62, 0x8a, 0xb4, 0xeb, 0x74, 0xf7, 0xb8, 0xae, 0xc5, 0x20, 0x71, 0x06, 0xd6, 0x7c, 0x62, 0x9b, 0x69, 0x74, 0xef, 0xa7, 0x6d, 0xd6, 0x8c, 0x37, 0xb9, 0xbf, 0xcf, 0xeb, 0xe4, 0x2f, 0x04, 0x02, 0x21, 0x7d, 0x75, 0x6b, 0x92, 0x48, 0xf8, 0x70, 0xad, 0x69, 0xe2, 0xea, 0x0e, 0x88, 0x67, 0x72, 0xcc, 0x2d, 0x10, 0xce, 0x2d, 0xcf, 0x65, - /* (2^233)P */ 0x49, 0xf3, 0x57, 0x64, 0xe5, 0x5c, 0xc5, 0x65, 0x49, 0x97, 0xc4, 0x8a, 0xcc, 0xa9, 0xca, 0x94, 0x7b, 0x86, 0x88, 0xb6, 0x51, 0x27, 0x69, 0xa5, 0x0f, 0x8b, 0x06, 0x59, 0xa0, 0x94, 0xef, 0x63, 0x1a, 0x01, 0x9e, 0x4f, 0xd2, 0x5a, 0x93, 0xc0, 0x7c, 0xe6, 0x61, 0x77, 0xb6, 0xf5, 0x40, 0xd9, 0x98, 0x43, 0x5b, 0x56, 0x68, 0xe9, 0x37, 0x8f, - /* (2^234)P */ 0xee, 0x87, 0xd2, 0x05, 0x1b, 0x39, 0x89, 0x10, 0x07, 0x6d, 0xe8, 0xfd, 0x8b, 0x4d, 0xb2, 0xa7, 0x7b, 0x1e, 0xa0, 0x6c, 0x0d, 0x3d, 0x3d, 0x49, 0xba, 0x61, 0x36, 0x1f, 0xc2, 0x84, 0x4a, 0xcc, 0x87, 0xa9, 0x1b, 0x23, 0x04, 0xe2, 0x3e, 0x97, 0xe1, 0xdb, 0xd5, 0x5a, 0xe8, 0x41, 0x6b, 0xe5, 0x5a, 0xa1, 0x99, 0xe5, 0x7b, 0xa7, 0xe0, 0x3b, - /* (2^235)P */ 0xea, 0xa3, 0x6a, 0xdd, 0x77, 0x7f, 0x77, 0x41, 0xc5, 0x6a, 0xe4, 0xaf, 0x11, 0x5f, 0x88, 0xa5, 0x10, 0xee, 0xd0, 0x8c, 0x0c, 0xb4, 0xa5, 0x2a, 0xd0, 0xd8, 0x1d, 0x47, 0x06, 0xc0, 0xd5, 0xce, 0x51, 0x54, 0x9b, 0x2b, 0xe6, 0x2f, 0xe7, 0xe7, 0x31, 0x5f, 0x5c, 0x23, 0x81, 0x3e, 0x03, 0x93, 0xaa, 0x2d, 0x71, 0x84, 0xa0, 0x89, 0x32, 0xa6, - /* (2^236)P */ 0x55, 0xa3, 0x13, 0x92, 0x4e, 0x93, 0x7d, 0xec, 0xca, 0x57, 0xfb, 0x37, 0xae, 0xd2, 0x18, 0x2e, 0x54, 0x05, 0x6c, 0xd1, 0x28, 0xca, 0x90, 0x40, 0x82, 0x2e, 0x79, 0xc6, 0x5a, 0xc7, 0xdd, 0x84, 0x93, 0xdf, 0x15, 0xb8, 0x1f, 0xb1, 0xf9, 0xaf, 0x2c, 0xe5, 0x32, 0xcd, 0xc2, 0x99, 0x6d, 0xac, 0x85, 0x5c, 0x63, 0xd3, 0xe2, 0xff, 0x24, 0xda, - /* (2^237)P */ 0x2d, 0x8d, 0xfd, 0x65, 0xcc, 0xe5, 0x02, 0xa0, 0xe5, 0xb9, 0xec, 0x59, 0x09, 0x50, 0x27, 0xb7, 0x3d, 0x2a, 0x79, 0xb2, 0x76, 0x5d, 0x64, 0x95, 0xf8, 0xc5, 0xaf, 0x8a, 0x62, 0x11, 0x5c, 0x56, 0x1c, 0x05, 0x64, 0x9e, 0x5e, 0xbd, 0x54, 0x04, 0xe6, 0x9e, 0xab, 0xe6, 0x22, 0x7e, 0x42, 0x54, 0xb5, 0xa5, 0xd0, 0x8d, 0x28, 0x6b, 0x0f, 0x0b, - /* (2^238)P */ 0x2d, 0xb2, 0x8c, 0x59, 0x10, 0x37, 0x84, 0x3b, 0x9b, 0x65, 0x1b, 0x0f, 0x10, 0xf9, 0xea, 0x60, 0x1b, 0x02, 0xf5, 0xee, 0x8b, 0xe6, 0x32, 0x7d, 0x10, 0x7f, 0x5f, 0x8c, 0x72, 0x09, 0x4e, 0x1f, 0x29, 0xff, 0x65, 0xcb, 0x3e, 0x3a, 0xd2, 0x96, 0x50, 0x1e, 0xea, 0x64, 0x99, 0xb5, 0x4c, 0x7a, 0x69, 0xb8, 0x95, 0xae, 0x48, 0xc0, 0x7c, 0xb1, - /* (2^239)P */ 0xcd, 0x7c, 0x4f, 0x3e, 0xea, 0xf3, 0x90, 0xcb, 0x12, 0x76, 0xd1, 0x17, 0xdc, 0x0d, 0x13, 0x0f, 0xfd, 0x4d, 0xb5, 0x1f, 0xe4, 0xdd, 0xf2, 0x4d, 0x58, 0xea, 0xa5, 0x66, 0x92, 0xcf, 0xe5, 0x54, 0xea, 0x9b, 0x35, 0x83, 0x1a, 0x44, 0x8e, 0x62, 0x73, 0x45, 0x98, 0xa3, 0x89, 0x95, 0x52, 0x93, 0x1a, 0x8d, 0x63, 0x0f, 0xc2, 0x57, 0x3c, 0xb1, - /* (2^240)P */ 0x72, 0xb4, 0xdf, 0x51, 0xb7, 0xf6, 0x52, 0xa2, 0x14, 0x56, 0xe5, 0x0a, 0x2e, 0x75, 0x81, 0x02, 0xee, 0x93, 0x48, 0x0a, 0x92, 0x4e, 0x0c, 0x0f, 0xdf, 0x09, 0x89, 0x99, 0xf6, 0xf9, 0x22, 0xa2, 0x32, 0xf8, 0xb0, 0x76, 0x0c, 0xb2, 0x4d, 0x6e, 0xbe, 0x83, 0x35, 0x61, 0x44, 0xd2, 0x58, 0xc7, 0xdd, 0x14, 0xcf, 0xc3, 0x4b, 0x7c, 0x07, 0xee, - /* (2^241)P */ 0x8b, 0x03, 0xee, 0xcb, 0xa7, 0x2e, 0x28, 0xbd, 0x97, 0xd1, 0x4c, 0x2b, 0xd1, 0x92, 0x67, 0x5b, 0x5a, 0x12, 0xbf, 0x29, 0x17, 0xfc, 0x50, 0x09, 0x74, 0x76, 0xa2, 0xd4, 0x82, 0xfd, 0x2c, 0x0c, 0x90, 0xf7, 0xe7, 0xe5, 0x9a, 0x2c, 0x16, 0x40, 0xb9, 0x6c, 0xd9, 0xe0, 0x22, 0x9e, 0xf8, 0xdd, 0x73, 0xe4, 0x7b, 0x9e, 0xbe, 0x4f, 0x66, 0x22, - /* (2^242)P */ 0xa4, 0x10, 0xbe, 0xb8, 0x83, 0x3a, 0x77, 0x8e, 0xea, 0x0a, 0xc4, 0x97, 0x3e, 0xb6, 0x6c, 0x81, 0xd7, 0x65, 0xd9, 0xf7, 0xae, 0xe6, 0xbe, 0xab, 0x59, 0x81, 0x29, 0x4b, 0xff, 0xe1, 0x0f, 0xc3, 0x2b, 0xad, 0x4b, 0xef, 0xc4, 0x50, 0x9f, 0x88, 0x31, 0xf2, 0xde, 0x80, 0xd6, 0xf4, 0x20, 0x9c, 0x77, 0x9b, 0xbe, 0xbe, 0x08, 0xf5, 0xf0, 0x95, - /* (2^243)P */ 0x0e, 0x7c, 0x7b, 0x7c, 0xb3, 0xd8, 0x83, 0xfc, 0x8c, 0x75, 0x51, 0x74, 0x1b, 0xe1, 0x6d, 0x11, 0x05, 0x46, 0x24, 0x0d, 0xa4, 0x2b, 0x32, 0xfd, 0x2c, 0x4e, 0x21, 0xdf, 0x39, 0x6b, 0x96, 0xfc, 0xff, 0x92, 0xfc, 0x35, 0x0d, 0x9a, 0x4b, 0xc0, 0x70, 0x46, 0x32, 0x7d, 0xc0, 0xc4, 0x04, 0xe0, 0x2d, 0x83, 0xa7, 0x00, 0xc7, 0xcb, 0xb4, 0x8f, - /* (2^244)P */ 0xa9, 0x5a, 0x7f, 0x0e, 0xdd, 0x2c, 0x85, 0xaa, 0x4d, 0xac, 0xde, 0xb3, 0xb6, 0xaf, 0xe6, 0xd1, 0x06, 0x7b, 0x2c, 0xa4, 0x01, 0x19, 0x22, 0x7d, 0x78, 0xf0, 0x3a, 0xea, 0x89, 0xfe, 0x21, 0x61, 0x6d, 0xb8, 0xfe, 0xa5, 0x2a, 0xab, 0x0d, 0x7b, 0x51, 0x39, 0xb6, 0xde, 0xbc, 0xf0, 0xc5, 0x48, 0xd7, 0x09, 0x82, 0x6e, 0x66, 0x75, 0xc5, 0xcd, - /* (2^245)P */ 0xee, 0xdf, 0x2b, 0x6c, 0xa8, 0xde, 0x61, 0xe1, 0x27, 0xfa, 0x2a, 0x0f, 0x68, 0xe7, 0x7a, 0x9b, 0x13, 0xe9, 0x56, 0xd2, 0x1c, 0x3d, 0x2f, 0x3c, 0x7a, 0xf6, 0x6f, 0x45, 0xee, 0xe8, 0xf4, 0xa0, 0xa6, 0xe8, 0xa5, 0x27, 0xee, 0xf2, 0x85, 0xa9, 0xd5, 0x0e, 0xa9, 0x26, 0x60, 0xfe, 0xee, 0xc7, 0x59, 0x99, 0x5e, 0xa3, 0xdf, 0x23, 0x36, 0xd5, - /* (2^246)P */ 0x15, 0x66, 0x6f, 0xd5, 0x78, 0xa4, 0x0a, 0xf7, 0xb1, 0xe8, 0x75, 0x6b, 0x48, 0x7d, 0xa6, 0x4d, 0x3d, 0x36, 0x9b, 0xc7, 0xcc, 0x68, 0x9a, 0xfe, 0x2f, 0x39, 0x2a, 0x51, 0x31, 0x39, 0x7d, 0x73, 0x6f, 0xc8, 0x74, 0x72, 0x6f, 0x6e, 0xda, 0x5f, 0xad, 0x48, 0xc8, 0x40, 0xe1, 0x06, 0x01, 0x36, 0xa1, 0x88, 0xc8, 0x99, 0x9c, 0xd1, 0x11, 0x8f, - /* (2^247)P */ 0xab, 0xc5, 0xcb, 0xcf, 0xbd, 0x73, 0x21, 0xd0, 0x82, 0xb1, 0x2e, 0x2d, 0xd4, 0x36, 0x1b, 0xed, 0xa9, 0x8a, 0x26, 0x79, 0xc4, 0x17, 0xae, 0xe5, 0x09, 0x0a, 0x0c, 0xa4, 0x21, 0xa0, 0x6e, 0xdd, 0x62, 0x8e, 0x44, 0x62, 0xcc, 0x50, 0xff, 0x93, 0xb3, 0x9a, 0x72, 0x8c, 0x3f, 0xa1, 0xa6, 0x4d, 0x87, 0xd5, 0x1c, 0x5a, 0xc0, 0x0b, 0x1a, 0xd6, - /* (2^248)P */ 0x67, 0x36, 0x6a, 0x1f, 0x96, 0xe5, 0x80, 0x20, 0xa9, 0xe8, 0x0b, 0x0e, 0x21, 0x29, 0x3f, 0xc8, 0x0a, 0x6d, 0x27, 0x47, 0xca, 0xd9, 0x05, 0x55, 0xbf, 0x11, 0xcf, 0x31, 0x7a, 0x37, 0xc7, 0x90, 0xa9, 0xf4, 0x07, 0x5e, 0xd5, 0xc3, 0x92, 0xaa, 0x95, 0xc8, 0x23, 0x2a, 0x53, 0x45, 0xe3, 0x3a, 0x24, 0xe9, 0x67, 0x97, 0x3a, 0x82, 0xf9, 0xa6, - /* (2^249)P */ 0x92, 0x9e, 0x6d, 0x82, 0x67, 0xe9, 0xf9, 0x17, 0x96, 0x2c, 0xa7, 0xd3, 0x89, 0xf9, 0xdb, 0xd8, 0x20, 0xc6, 0x2e, 0xec, 0x4a, 0x76, 0x64, 0xbf, 0x27, 0x40, 0xe2, 0xb4, 0xdf, 0x1f, 0xa0, 0xef, 0x07, 0x80, 0xfb, 0x8e, 0x12, 0xf8, 0xb8, 0xe1, 0xc6, 0xdf, 0x7c, 0x69, 0x35, 0x5a, 0xe1, 0x8e, 0x5d, 0x69, 0x84, 0x56, 0xb6, 0x31, 0x1c, 0x0b, - /* (2^250)P */ 0xd6, 0x94, 0x5c, 0xef, 0xbb, 0x46, 0x45, 0x44, 0x5b, 0xa1, 0xae, 0x03, 0x65, 0xdd, 0xb5, 0x66, 0x88, 0x35, 0x29, 0x95, 0x16, 0x54, 0xa6, 0xf5, 0xc9, 0x78, 0x34, 0xe6, 0x0f, 0xc4, 0x2b, 0x5b, 0x79, 0x51, 0x68, 0x48, 0x3a, 0x26, 0x87, 0x05, 0x70, 0xaf, 0x8b, 0xa6, 0xc7, 0x2e, 0xb3, 0xa9, 0x10, 0x01, 0xb0, 0xb9, 0x31, 0xfd, 0xdc, 0x80, - /* (2^251)P */ 0x25, 0xf2, 0xad, 0xd6, 0x75, 0xa3, 0x04, 0x05, 0x64, 0x8a, 0x97, 0x60, 0x27, 0x2a, 0xe5, 0x6d, 0xb0, 0x73, 0xf4, 0x07, 0x2a, 0x9d, 0xe9, 0x46, 0xb4, 0x1c, 0x51, 0xf8, 0x63, 0x98, 0x7e, 0xe5, 0x13, 0x51, 0xed, 0x98, 0x65, 0x98, 0x4f, 0x8f, 0xe7, 0x7e, 0x72, 0xd7, 0x64, 0x11, 0x2f, 0xcd, 0x12, 0xf8, 0xc4, 0x63, 0x52, 0x0f, 0x7f, 0xc4, - /* (2^252)P */ 0x5c, 0xd9, 0x85, 0x63, 0xc7, 0x8a, 0x65, 0x9a, 0x25, 0x83, 0x31, 0x73, 0x49, 0xf0, 0x93, 0x96, 0x70, 0x67, 0x6d, 0xb1, 0xff, 0x95, 0x54, 0xe4, 0xf8, 0x15, 0x6c, 0x5f, 0xbd, 0xf6, 0x0f, 0x38, 0x7b, 0x68, 0x7d, 0xd9, 0x3d, 0xf0, 0xa9, 0xa0, 0xe4, 0xd1, 0xb6, 0x34, 0x6d, 0x14, 0x16, 0xc2, 0x4c, 0x30, 0x0e, 0x67, 0xd3, 0xbe, 0x2e, 0xc0, - /* (2^253)P */ 0x06, 0x6b, 0x52, 0xc8, 0x14, 0xcd, 0xae, 0x03, 0x93, 0xea, 0xc1, 0xf2, 0xf6, 0x8b, 0xc5, 0xb6, 0xdc, 0x82, 0x42, 0x29, 0x94, 0xe0, 0x25, 0x6c, 0x3f, 0x9f, 0x5d, 0xe4, 0x96, 0xf6, 0x8e, 0x3f, 0xf9, 0x72, 0xc4, 0x77, 0x60, 0x8b, 0xa4, 0xf9, 0xa8, 0xc3, 0x0a, 0x81, 0xb1, 0x97, 0x70, 0x18, 0xab, 0xea, 0x37, 0x8a, 0x08, 0xc7, 0xe2, 0x95, - /* (2^254)P */ 0x94, 0x49, 0xd9, 0x5f, 0x76, 0x72, 0x82, 0xad, 0x2d, 0x50, 0x1a, 0x7a, 0x5b, 0xe6, 0x95, 0x1e, 0x95, 0x65, 0x87, 0x1c, 0x52, 0xd7, 0x44, 0xe6, 0x9b, 0x56, 0xcd, 0x6f, 0x05, 0xff, 0x67, 0xc5, 0xdb, 0xa2, 0xac, 0xe4, 0xa2, 0x28, 0x63, 0x5f, 0xfb, 0x0c, 0x3b, 0xf1, 0x87, 0xc3, 0x36, 0x78, 0x3f, 0x77, 0xfa, 0x50, 0x85, 0xf9, 0xd7, 0x82, - /* (2^255)P */ 0x64, 0xc0, 0xe0, 0xd8, 0x2d, 0xed, 0xcb, 0x6a, 0xfd, 0xcd, 0xbc, 0x7e, 0x9f, 0xc8, 0x85, 0xe9, 0xc1, 0x7c, 0x0f, 0xe5, 0x18, 0xea, 0xd4, 0x51, 0xad, 0x59, 0x13, 0x75, 0xd9, 0x3d, 0xd4, 0x8a, 0xb2, 0xbe, 0x78, 0x52, 0x2b, 0x52, 0x94, 0x37, 0x41, 0xd6, 0xb4, 0xb6, 0x45, 0x20, 0x76, 0xe0, 0x1f, 0x31, 0xdb, 0xb1, 0xa1, 0x43, 0xf0, 0x18, - /* (2^256)P */ 0x74, 0xa9, 0xa4, 0xa9, 0xdd, 0x6e, 0x3e, 0x68, 0xe5, 0xc3, 0x2e, 0x92, 0x17, 0xa4, 0xcb, 0x80, 0xb1, 0xf0, 0x06, 0x93, 0xef, 0xe6, 0x00, 0xe6, 0x3b, 0xb1, 0x32, 0x65, 0x7b, 0x83, 0xb6, 0x8a, 0x49, 0x1b, 0x14, 0x89, 0xee, 0xba, 0xf5, 0x6a, 0x8d, 0x36, 0xef, 0xb0, 0xd8, 0xb2, 0x16, 0x99, 0x17, 0x35, 0x02, 0x16, 0x55, 0x58, 0xdd, 0x82, - /* (2^257)P */ 0x36, 0x95, 0xe8, 0xf4, 0x36, 0x42, 0xbb, 0xc5, 0x3e, 0xfa, 0x30, 0x84, 0x9e, 0x59, 0xfd, 0xd2, 0x95, 0x42, 0xf8, 0x64, 0xd9, 0xb9, 0x0e, 0x9f, 0xfa, 0xd0, 0x7b, 0x20, 0x31, 0x77, 0x48, 0x29, 0x4d, 0xd0, 0x32, 0x57, 0x56, 0x30, 0xa6, 0x17, 0x53, 0x04, 0xbf, 0x08, 0x28, 0xec, 0xb8, 0x46, 0xc1, 0x03, 0x89, 0xdc, 0xed, 0xa0, 0x35, 0x53, - /* (2^258)P */ 0xc5, 0x7f, 0x9e, 0xd8, 0xc5, 0xba, 0x5f, 0x68, 0xc8, 0x23, 0x75, 0xea, 0x0d, 0xd9, 0x5a, 0xfd, 0x61, 0x1a, 0xa3, 0x2e, 0x45, 0x63, 0x14, 0x55, 0x86, 0x21, 0x29, 0xbe, 0xef, 0x5e, 0x50, 0xe5, 0x18, 0x59, 0xe7, 0xe3, 0xce, 0x4d, 0x8c, 0x15, 0x8f, 0x89, 0x66, 0x44, 0x52, 0x3d, 0xfa, 0xc7, 0x9a, 0x59, 0x90, 0x8e, 0xc0, 0x06, 0x3f, 0xc9, - /* (2^259)P */ 0x8e, 0x04, 0xd9, 0x16, 0x50, 0x1d, 0x8c, 0x9f, 0xd5, 0xe3, 0xce, 0xfd, 0x47, 0x04, 0x27, 0x4d, 0xc2, 0xfa, 0x71, 0xd9, 0x0b, 0xb8, 0x65, 0xf4, 0x11, 0xf3, 0x08, 0xee, 0x81, 0xc8, 0x67, 0x99, 0x0b, 0x8d, 0x77, 0xa3, 0x4f, 0xb5, 0x9b, 0xdb, 0x26, 0xf1, 0x97, 0xeb, 0x04, 0x54, 0xeb, 0x80, 0x08, 0x1d, 0x1d, 0xf6, 0x3d, 0x1f, 0x5a, 0xb8, - /* (2^260)P */ 0xb7, 0x9c, 0x9d, 0xee, 0xb9, 0x5c, 0xad, 0x0d, 0x9e, 0xfd, 0x60, 0x3c, 0x27, 0x4e, 0xa2, 0x95, 0xfb, 0x64, 0x7e, 0x79, 0x64, 0x87, 0x10, 0xb4, 0x73, 0xe0, 0x9d, 0x46, 0x4d, 0x3d, 0xee, 0x83, 0xe4, 0x16, 0x88, 0x97, 0xe6, 0x4d, 0xba, 0x70, 0xb6, 0x96, 0x7b, 0xff, 0x4b, 0xc8, 0xcf, 0x72, 0x83, 0x3e, 0x5b, 0x24, 0x2e, 0x57, 0xf1, 0x82, - /* (2^261)P */ 0x30, 0x71, 0x40, 0x51, 0x4f, 0x44, 0xbb, 0xc7, 0xf0, 0x54, 0x6e, 0x9d, 0xeb, 0x15, 0xad, 0xf8, 0x61, 0x43, 0x5a, 0xef, 0xc0, 0xb1, 0x57, 0xae, 0x03, 0x40, 0xe8, 0x68, 0x6f, 0x03, 0x20, 0x4f, 0x8a, 0x51, 0x2a, 0x9e, 0xd2, 0x45, 0xaf, 0xb4, 0xf5, 0xd4, 0x95, 0x7f, 0x3d, 0x3d, 0xb7, 0xb6, 0x28, 0xc5, 0x08, 0x8b, 0x44, 0xd6, 0x3f, 0xe7, - /* (2^262)P */ 0xa9, 0x52, 0x04, 0x67, 0xcb, 0x20, 0x63, 0xf8, 0x18, 0x01, 0x44, 0x21, 0x6a, 0x8a, 0x83, 0x48, 0xd4, 0xaf, 0x23, 0x0f, 0x35, 0x8d, 0xe5, 0x5a, 0xc4, 0x7c, 0x55, 0x46, 0x19, 0x5f, 0x35, 0xe0, 0x5d, 0x97, 0x4c, 0x2d, 0x04, 0xed, 0x59, 0xd4, 0xb0, 0xb2, 0xc6, 0xe3, 0x51, 0xe1, 0x38, 0xc6, 0x30, 0x49, 0x8f, 0xae, 0x61, 0x64, 0xce, 0xa8, - /* (2^263)P */ 0x9b, 0x64, 0x83, 0x3c, 0xd3, 0xdf, 0xb9, 0x27, 0xe7, 0x5b, 0x7f, 0xeb, 0xf3, 0x26, 0xcf, 0xb1, 0x8f, 0xaf, 0x26, 0xc8, 0x48, 0xce, 0xa1, 0xac, 0x7d, 0x10, 0x34, 0x28, 0xe1, 0x1f, 0x69, 0x03, 0x64, 0x77, 0x61, 0xdd, 0x4a, 0x9b, 0x18, 0x47, 0xf8, 0xca, 0x63, 0xc9, 0x03, 0x2d, 0x20, 0x2a, 0x69, 0x6e, 0x42, 0xd0, 0xe7, 0xaa, 0xb5, 0xf3, - /* (2^264)P */ 0xea, 0x31, 0x0c, 0x57, 0x0f, 0x3e, 0xe3, 0x35, 0xd8, 0x30, 0xa5, 0x6f, 0xdd, 0x95, 0x43, 0xc6, 0x66, 0x07, 0x4f, 0x34, 0xc3, 0x7e, 0x04, 0x10, 0x2d, 0xc4, 0x1c, 0x94, 0x52, 0x2e, 0x5b, 0x9a, 0x65, 0x2f, 0x91, 0xaa, 0x4f, 0x3c, 0xdc, 0x23, 0x18, 0xe1, 0x4f, 0x85, 0xcd, 0xf4, 0x8c, 0x51, 0xf7, 0xab, 0x4f, 0xdc, 0x15, 0x5c, 0x9e, 0xc5, - /* (2^265)P */ 0x54, 0x57, 0x23, 0x17, 0xe7, 0x82, 0x2f, 0x04, 0x7d, 0xfe, 0xe7, 0x1f, 0xa2, 0x57, 0x79, 0xe9, 0x58, 0x9b, 0xbe, 0xc6, 0x16, 0x4a, 0x17, 0x50, 0x90, 0x4a, 0x34, 0x70, 0x87, 0x37, 0x01, 0x26, 0xd8, 0xa3, 0x5f, 0x07, 0x7c, 0xd0, 0x7d, 0x05, 0x8a, 0x93, 0x51, 0x2f, 0x99, 0xea, 0xcf, 0x00, 0xd8, 0xc7, 0xe6, 0x9b, 0x8c, 0x62, 0x45, 0x87, - /* (2^266)P */ 0xc3, 0xfd, 0x29, 0x66, 0xe7, 0x30, 0x29, 0x77, 0xe0, 0x0d, 0x63, 0x5b, 0xe6, 0x90, 0x1a, 0x1e, 0x99, 0xc2, 0xa7, 0xab, 0xff, 0xa7, 0xbd, 0x79, 0x01, 0x97, 0xfd, 0x27, 0x1b, 0x43, 0x2b, 0xe6, 0xfe, 0x5e, 0xf1, 0xb9, 0x35, 0x38, 0x08, 0x25, 0x55, 0x90, 0x68, 0x2e, 0xc3, 0x67, 0x39, 0x9f, 0x2b, 0x2c, 0x70, 0x48, 0x8c, 0x47, 0xee, 0x56, - /* (2^267)P */ 0xf7, 0x32, 0x70, 0xb5, 0xe6, 0x42, 0xfd, 0x0a, 0x39, 0x9b, 0x07, 0xfe, 0x0e, 0xf4, 0x47, 0xba, 0x6a, 0x3f, 0xf5, 0x2c, 0x15, 0xf3, 0x60, 0x3f, 0xb1, 0x83, 0x7b, 0x2e, 0x34, 0x58, 0x1a, 0x6e, 0x4a, 0x49, 0x05, 0x45, 0xca, 0xdb, 0x00, 0x01, 0x0c, 0x42, 0x5e, 0x60, 0x40, 0x5f, 0xd9, 0xc7, 0x3a, 0x9e, 0x1c, 0x8d, 0xab, 0x11, 0x55, 0x65, - /* (2^268)P */ 0x87, 0x40, 0xb7, 0x0d, 0xaa, 0x34, 0x89, 0x90, 0x75, 0x6d, 0xa2, 0xfe, 0x3b, 0x6d, 0x5c, 0x39, 0x98, 0x10, 0x9e, 0x15, 0xc5, 0x35, 0xa2, 0x27, 0x23, 0x0a, 0x2d, 0x60, 0xe2, 0xa8, 0x7f, 0x3e, 0x77, 0x8f, 0xcc, 0x44, 0xcc, 0x30, 0x28, 0xe2, 0xf0, 0x04, 0x8c, 0xee, 0xe4, 0x5f, 0x68, 0x8c, 0xdf, 0x70, 0xbf, 0x31, 0xee, 0x2a, 0xfc, 0xce, - /* (2^269)P */ 0x92, 0xf2, 0xa0, 0xd9, 0x58, 0x3b, 0x7c, 0x1a, 0x99, 0x46, 0x59, 0x54, 0x60, 0x06, 0x8d, 0x5e, 0xf0, 0x22, 0xa1, 0xed, 0x92, 0x8a, 0x4d, 0x76, 0x95, 0x05, 0x0b, 0xff, 0xfc, 0x9a, 0xd1, 0xcc, 0x05, 0xb9, 0x5e, 0x99, 0xe8, 0x2a, 0x76, 0x7b, 0xfd, 0xa6, 0xe2, 0xd1, 0x1a, 0xd6, 0x76, 0x9f, 0x2f, 0x0e, 0xd1, 0xa8, 0x77, 0x5a, 0x40, 0x5a, - /* (2^270)P */ 0xff, 0xf9, 0x3f, 0xa9, 0xa6, 0x6c, 0x6d, 0x03, 0x8b, 0xa7, 0x10, 0x5d, 0x3f, 0xec, 0x3e, 0x1c, 0x0b, 0x6b, 0xa2, 0x6a, 0x22, 0xa9, 0x28, 0xd0, 0x66, 0xc9, 0xc2, 0x3d, 0x47, 0x20, 0x7d, 0xa6, 0x1d, 0xd8, 0x25, 0xb5, 0xf2, 0xf9, 0x70, 0x19, 0x6b, 0xf8, 0x43, 0x36, 0xc5, 0x1f, 0xe4, 0x5a, 0x4c, 0x13, 0xe4, 0x6d, 0x08, 0x0b, 0x1d, 0xb1, - /* (2^271)P */ 0x3f, 0x20, 0x9b, 0xfb, 0xec, 0x7d, 0x31, 0xc5, 0xfc, 0x88, 0x0b, 0x30, 0xed, 0x36, 0xc0, 0x63, 0xb1, 0x7d, 0x10, 0xda, 0xb6, 0x2e, 0xad, 0xf3, 0xec, 0x94, 0xe7, 0xec, 0xb5, 0x9c, 0xfe, 0xf5, 0x35, 0xf0, 0xa2, 0x2d, 0x7f, 0xca, 0x6b, 0x67, 0x1a, 0xf6, 0xb3, 0xda, 0x09, 0x2a, 0xaa, 0xdf, 0xb1, 0xca, 0x9b, 0xfb, 0xeb, 0xb3, 0xcd, 0xc0, - /* (2^272)P */ 0xcd, 0x4d, 0x89, 0x00, 0xa4, 0x3b, 0x48, 0xf0, 0x76, 0x91, 0x35, 0xa5, 0xf8, 0xc9, 0xb6, 0x46, 0xbc, 0xf6, 0x9a, 0x45, 0x47, 0x17, 0x96, 0x80, 0x5b, 0x3a, 0x28, 0x33, 0xf9, 0x5a, 0xef, 0x43, 0x07, 0xfe, 0x3b, 0xf4, 0x8e, 0x19, 0xce, 0xd2, 0x94, 0x4b, 0x6d, 0x8e, 0x67, 0x20, 0xc7, 0x4f, 0x2f, 0x59, 0x8e, 0xe1, 0xa1, 0xa9, 0xf9, 0x0e, - /* (2^273)P */ 0xdc, 0x7b, 0xb5, 0x50, 0x2e, 0xe9, 0x7e, 0x8b, 0x78, 0xa1, 0x38, 0x96, 0x22, 0xc3, 0x61, 0x67, 0x6d, 0xc8, 0x58, 0xed, 0x41, 0x1d, 0x5d, 0x86, 0x98, 0x7f, 0x2f, 0x1b, 0x8d, 0x3e, 0xaa, 0xc1, 0xd2, 0x0a, 0xf3, 0xbf, 0x95, 0x04, 0xf3, 0x10, 0x3c, 0x2b, 0x7f, 0x90, 0x46, 0x04, 0xaa, 0x6a, 0xa9, 0x35, 0x76, 0xac, 0x49, 0xb5, 0x00, 0x45, - /* (2^274)P */ 0xb1, 0x93, 0x79, 0x84, 0x4a, 0x2a, 0x30, 0x78, 0x16, 0xaa, 0xc5, 0x74, 0x06, 0xce, 0xa5, 0xa7, 0x32, 0x86, 0xe0, 0xf9, 0x10, 0xd2, 0x58, 0x76, 0xfb, 0x66, 0x49, 0x76, 0x3a, 0x90, 0xba, 0xb5, 0xcc, 0x99, 0xcd, 0x09, 0xc1, 0x9a, 0x74, 0x23, 0xdf, 0x0c, 0xfe, 0x99, 0x52, 0x80, 0xa3, 0x7c, 0x1c, 0x71, 0x5f, 0x2c, 0x49, 0x57, 0xf4, 0xf9, - /* (2^275)P */ 0x6d, 0xbf, 0x52, 0xe6, 0x25, 0x98, 0xed, 0xcf, 0xe3, 0xbc, 0x08, 0xa2, 0x1a, 0x90, 0xae, 0xa0, 0xbf, 0x07, 0x15, 0xad, 0x0a, 0x9f, 0x3e, 0x47, 0x44, 0xc2, 0x10, 0x46, 0xa6, 0x7a, 0x9e, 0x2f, 0x57, 0xbc, 0xe2, 0xf0, 0x1d, 0xd6, 0x9a, 0x06, 0xed, 0xfc, 0x54, 0x95, 0x92, 0x15, 0xa2, 0xf7, 0x8d, 0x6b, 0xef, 0xb2, 0x05, 0xed, 0x5c, 0x63, - /* (2^276)P */ 0xbc, 0x0b, 0x27, 0x3a, 0x3a, 0xf8, 0xe1, 0x48, 0x02, 0x7e, 0x27, 0xe6, 0x81, 0x62, 0x07, 0x73, 0x74, 0xe5, 0x52, 0xd7, 0xf8, 0x26, 0xca, 0x93, 0x4d, 0x3e, 0x9b, 0x55, 0x09, 0x8e, 0xe3, 0xd7, 0xa6, 0xe3, 0xb6, 0x2a, 0xa9, 0xb3, 0xb0, 0xa0, 0x8c, 0x01, 0xbb, 0x07, 0x90, 0x78, 0x6d, 0x6d, 0xe9, 0xf0, 0x7a, 0x90, 0xbd, 0xdc, 0x0c, 0x36, - /* (2^277)P */ 0x7f, 0x20, 0x12, 0x0f, 0x40, 0x00, 0x53, 0xd8, 0x0c, 0x27, 0x47, 0x47, 0x22, 0x80, 0xfb, 0x62, 0xe4, 0xa7, 0xf7, 0xbd, 0x42, 0xa5, 0xc3, 0x2b, 0xb2, 0x7f, 0x50, 0xcc, 0xe2, 0xfb, 0xd5, 0xc0, 0x63, 0xdd, 0x24, 0x5f, 0x7c, 0x08, 0x91, 0xbf, 0x6e, 0x47, 0x44, 0xd4, 0x6a, 0xc0, 0xc3, 0x09, 0x39, 0x27, 0xdd, 0xc7, 0xca, 0x06, 0x29, 0x55, - /* (2^278)P */ 0x76, 0x28, 0x58, 0xb0, 0xd2, 0xf3, 0x0f, 0x04, 0xe9, 0xc9, 0xab, 0x66, 0x5b, 0x75, 0x51, 0xdc, 0xe5, 0x8f, 0xe8, 0x1f, 0xdb, 0x03, 0x0f, 0xb0, 0x7d, 0xf9, 0x20, 0x64, 0x89, 0xe9, 0xdc, 0xe6, 0x24, 0xc3, 0xd5, 0xd2, 0x41, 0xa6, 0xe4, 0xe3, 0xc4, 0x79, 0x7c, 0x0f, 0xa1, 0x61, 0x2f, 0xda, 0xa4, 0xc9, 0xfd, 0xad, 0x5c, 0x65, 0x6a, 0xf3, - /* (2^279)P */ 0xd5, 0xab, 0x72, 0x7a, 0x3b, 0x59, 0xea, 0xcf, 0xd5, 0x17, 0xd2, 0xb2, 0x5f, 0x2d, 0xab, 0xad, 0x9e, 0x88, 0x64, 0x55, 0x96, 0x6e, 0xf3, 0x44, 0xa9, 0x11, 0xf5, 0xf8, 0x3a, 0xf1, 0xcd, 0x79, 0x4c, 0x99, 0x6d, 0x23, 0x6a, 0xa0, 0xc2, 0x1a, 0x19, 0x45, 0xb5, 0xd8, 0x95, 0x2f, 0x49, 0xe9, 0x46, 0x39, 0x26, 0x60, 0x04, 0x15, 0x8b, 0xcc, - /* (2^280)P */ 0x66, 0x0c, 0xf0, 0x54, 0x41, 0x02, 0x91, 0xab, 0xe5, 0x85, 0x8a, 0x44, 0xa6, 0x34, 0x96, 0x32, 0xc0, 0xdf, 0x6c, 0x41, 0x39, 0xd4, 0xc6, 0xe1, 0xe3, 0x81, 0xb0, 0x4c, 0x34, 0x4f, 0xe5, 0xf4, 0x35, 0x46, 0x1f, 0xeb, 0x75, 0xfd, 0x43, 0x37, 0x50, 0x99, 0xab, 0xad, 0xb7, 0x8c, 0xa1, 0x57, 0xcb, 0xe6, 0xce, 0x16, 0x2e, 0x85, 0xcc, 0xf9, - /* (2^281)P */ 0x63, 0xd1, 0x3f, 0x9e, 0xa2, 0x17, 0x2e, 0x1d, 0x3e, 0xce, 0x48, 0x2d, 0xbb, 0x8f, 0x69, 0xc9, 0xa6, 0x3d, 0x4e, 0xfe, 0x09, 0x56, 0xb3, 0x02, 0x5f, 0x99, 0x97, 0x0c, 0x54, 0xda, 0x32, 0x97, 0x9b, 0xf4, 0x95, 0xf1, 0xad, 0xe3, 0x2b, 0x04, 0xa7, 0x9b, 0x3f, 0xbb, 0xe7, 0x87, 0x2e, 0x1f, 0x8b, 0x4b, 0x7a, 0xa4, 0x43, 0x0c, 0x0f, 0x35, - /* (2^282)P */ 0x05, 0xdc, 0xe0, 0x2c, 0xa1, 0xc1, 0xd0, 0xf1, 0x1f, 0x4e, 0xc0, 0x6c, 0x35, 0x7b, 0xca, 0x8f, 0x8b, 0x02, 0xb1, 0xf7, 0xd6, 0x2e, 0xe7, 0x93, 0x80, 0x85, 0x18, 0x88, 0x19, 0xb9, 0xb4, 0x4a, 0xbc, 0xeb, 0x5a, 0x78, 0x38, 0xed, 0xc6, 0x27, 0x2a, 0x74, 0x76, 0xf0, 0x1b, 0x79, 0x92, 0x2f, 0xd2, 0x81, 0x98, 0xdf, 0xa9, 0x50, 0x19, 0xeb, - /* (2^283)P */ 0xb5, 0xe7, 0xb4, 0x11, 0x3a, 0x81, 0xb6, 0xb4, 0xf8, 0xa2, 0xb3, 0x6c, 0xfc, 0x9d, 0xe0, 0xc0, 0xe0, 0x59, 0x7f, 0x05, 0x37, 0xef, 0x2c, 0xa9, 0x3a, 0x24, 0xac, 0x7b, 0x25, 0xa0, 0x55, 0xd2, 0x44, 0x82, 0x82, 0x6e, 0x64, 0xa3, 0x58, 0xc8, 0x67, 0xae, 0x26, 0xa7, 0x0f, 0x42, 0x63, 0xe1, 0x93, 0x01, 0x52, 0x19, 0xaf, 0x49, 0x3e, 0x33, - /* (2^284)P */ 0x05, 0x85, 0xe6, 0x66, 0xaf, 0x5f, 0xdf, 0xbf, 0x9d, 0x24, 0x62, 0x60, 0x90, 0xe2, 0x4c, 0x7d, 0x4e, 0xc3, 0x74, 0x5d, 0x4f, 0x53, 0xf3, 0x63, 0x13, 0xf4, 0x74, 0x28, 0x6b, 0x7d, 0x57, 0x0c, 0x9d, 0x84, 0xa7, 0x1a, 0xff, 0xa0, 0x79, 0xdf, 0xfc, 0x65, 0x98, 0x8e, 0x22, 0x0d, 0x62, 0x7e, 0xf2, 0x34, 0x60, 0x83, 0x05, 0x14, 0xb1, 0xc1, - /* (2^285)P */ 0x64, 0x22, 0xcc, 0xdf, 0x5c, 0xbc, 0x88, 0x68, 0x4c, 0xd9, 0xbc, 0x0e, 0xc9, 0x8b, 0xb4, 0x23, 0x52, 0xad, 0xb0, 0xb3, 0xf1, 0x17, 0xd8, 0x15, 0x04, 0x6b, 0x99, 0xf0, 0xc4, 0x7d, 0x48, 0x22, 0x4a, 0xf8, 0x6f, 0xaa, 0x88, 0x0d, 0xc5, 0x5e, 0xa9, 0x1c, 0x61, 0x3d, 0x95, 0xa9, 0x7b, 0x6a, 0x79, 0x33, 0x0a, 0x2b, 0x99, 0xe3, 0x4e, 0x48, - /* (2^286)P */ 0x6b, 0x9b, 0x6a, 0x2a, 0xf1, 0x60, 0x31, 0xb4, 0x73, 0xd1, 0x87, 0x45, 0x9c, 0x15, 0x58, 0x4b, 0x91, 0x6d, 0x94, 0x1c, 0x41, 0x11, 0x4a, 0x83, 0xec, 0xaf, 0x65, 0xbc, 0x34, 0xaa, 0x26, 0xe2, 0xaf, 0xed, 0x46, 0x05, 0x4e, 0xdb, 0xc6, 0x4e, 0x10, 0x28, 0x4e, 0x72, 0xe5, 0x31, 0xa3, 0x20, 0xd7, 0xb1, 0x96, 0x64, 0xf6, 0xce, 0x08, 0x08, - /* (2^287)P */ 0x16, 0xa9, 0x5c, 0x9f, 0x9a, 0xb4, 0xb8, 0xc8, 0x32, 0x78, 0xc0, 0x3a, 0xd9, 0x5f, 0x94, 0xac, 0x3a, 0x42, 0x1f, 0x43, 0xd6, 0x80, 0x47, 0x2c, 0xdc, 0x76, 0x27, 0xfa, 0x50, 0xe5, 0xa1, 0xe4, 0xc3, 0xcb, 0x61, 0x31, 0xe1, 0x2e, 0xde, 0x81, 0x3b, 0x77, 0x1c, 0x39, 0x3c, 0xdb, 0xda, 0x87, 0x4b, 0x84, 0x12, 0xeb, 0xdd, 0x54, 0xbf, 0xe7, - /* (2^288)P */ 0xbf, 0xcb, 0x73, 0x21, 0x3d, 0x7e, 0x13, 0x8c, 0xa6, 0x34, 0x21, 0x2b, 0xa5, 0xe4, 0x9f, 0x8e, 0x9c, 0x01, 0x9c, 0x43, 0xd9, 0xc7, 0xb9, 0xf1, 0xbe, 0x7f, 0x45, 0x51, 0x97, 0xa1, 0x8e, 0x01, 0xf8, 0xbd, 0xd2, 0xbf, 0x81, 0x3a, 0x8b, 0xab, 0xe4, 0x89, 0xb7, 0xbd, 0xf2, 0xcd, 0xa9, 0x8a, 0x8a, 0xde, 0xfb, 0x8a, 0x55, 0x12, 0x7b, 0x17, - /* (2^289)P */ 0x1b, 0x95, 0x58, 0x4d, 0xe6, 0x51, 0x31, 0x52, 0x1c, 0xd8, 0x15, 0x84, 0xb1, 0x0d, 0x36, 0x25, 0x88, 0x91, 0x46, 0x71, 0x42, 0x56, 0xe2, 0x90, 0x08, 0x9e, 0x77, 0x1b, 0xee, 0x22, 0x3f, 0xec, 0xee, 0x8c, 0x7b, 0x2e, 0x79, 0xc4, 0x6c, 0x07, 0xa1, 0x7e, 0x52, 0xf5, 0x26, 0x5c, 0x84, 0x2a, 0x50, 0x6e, 0x82, 0xb3, 0x76, 0xda, 0x35, 0x16, - /* (2^290)P */ 0x0a, 0x6f, 0x99, 0x87, 0xc0, 0x7d, 0x8a, 0xb2, 0xca, 0xae, 0xe8, 0x65, 0x98, 0x0f, 0xb3, 0x44, 0xe1, 0xdc, 0x52, 0x79, 0x75, 0xec, 0x8f, 0x95, 0x87, 0x45, 0xd1, 0x32, 0x18, 0x55, 0x15, 0xce, 0x64, 0x9b, 0x08, 0x4f, 0x2c, 0xea, 0xba, 0x1c, 0x57, 0x06, 0x63, 0xc8, 0xb1, 0xfd, 0xc5, 0x67, 0xe7, 0x1f, 0x87, 0x9e, 0xde, 0x72, 0x7d, 0xec, - /* (2^291)P */ 0x36, 0x8b, 0x4d, 0x2c, 0xc2, 0x46, 0xe8, 0x96, 0xac, 0x0b, 0x8c, 0xc5, 0x09, 0x10, 0xfc, 0xf2, 0xda, 0xea, 0x22, 0xb2, 0xd3, 0x89, 0xeb, 0xb2, 0x85, 0x0f, 0xff, 0x59, 0x50, 0x2c, 0x99, 0x5a, 0x1f, 0xec, 0x2a, 0x6f, 0xec, 0xcf, 0xe9, 0xce, 0x12, 0x6b, 0x19, 0xd8, 0xde, 0x9b, 0xce, 0x0e, 0x6a, 0xaa, 0xe1, 0x32, 0xea, 0x4c, 0xfe, 0x92, - /* (2^292)P */ 0x5f, 0x17, 0x70, 0x53, 0x26, 0x03, 0x0b, 0xab, 0xd1, 0xc1, 0x42, 0x0b, 0xab, 0x2b, 0x3d, 0x31, 0xa4, 0xd5, 0x2b, 0x5e, 0x00, 0xd5, 0x9a, 0x22, 0x34, 0xe0, 0x53, 0x3f, 0x59, 0x7f, 0x2c, 0x6d, 0x72, 0x9a, 0xa4, 0xbe, 0x3d, 0x42, 0x05, 0x1b, 0xf2, 0x7f, 0x88, 0x56, 0xd1, 0x7c, 0x7d, 0x6b, 0x9f, 0x43, 0xfe, 0x65, 0x19, 0xae, 0x9c, 0x4c, - /* (2^293)P */ 0xf3, 0x7c, 0x20, 0xa9, 0xfc, 0xf2, 0xf2, 0x3b, 0x3c, 0x57, 0x41, 0x94, 0xe5, 0xcc, 0x6a, 0x37, 0x5d, 0x09, 0xf2, 0xab, 0xc2, 0xca, 0x60, 0x38, 0x6b, 0x7a, 0xe1, 0x78, 0x2b, 0xc1, 0x1d, 0xe8, 0xfd, 0xbc, 0x3d, 0x5c, 0xa2, 0xdb, 0x49, 0x20, 0x79, 0xe6, 0x1b, 0x9b, 0x65, 0xd9, 0x6d, 0xec, 0x57, 0x1d, 0xd2, 0xe9, 0x90, 0xeb, 0x43, 0x7b, - /* (2^294)P */ 0x2a, 0x8b, 0x2e, 0x19, 0x18, 0x10, 0xb8, 0x83, 0xe7, 0x7d, 0x2d, 0x9a, 0x3a, 0xe5, 0xd1, 0xe4, 0x7c, 0x38, 0xe5, 0x59, 0x2a, 0x6e, 0xd9, 0x01, 0x29, 0x3d, 0x23, 0xf7, 0x52, 0xba, 0x61, 0x04, 0x9a, 0xde, 0xc4, 0x31, 0x50, 0xeb, 0x1b, 0xaa, 0xde, 0x39, 0x58, 0xd8, 0x1b, 0x1e, 0xfc, 0x57, 0x9a, 0x28, 0x43, 0x9e, 0x97, 0x5e, 0xaa, 0xa3, - /* (2^295)P */ 0x97, 0x0a, 0x74, 0xc4, 0x39, 0x99, 0x6b, 0x40, 0xc7, 0x3e, 0x8c, 0xa7, 0xb1, 0x4e, 0x9a, 0x59, 0x6e, 0x1c, 0xfe, 0xfc, 0x2a, 0x5e, 0x73, 0x2b, 0x8c, 0xa9, 0x71, 0xf5, 0xda, 0x6b, 0x15, 0xab, 0xf7, 0xbe, 0x2a, 0x44, 0x5f, 0xba, 0xae, 0x67, 0x93, 0xc5, 0x86, 0xc1, 0xb8, 0xdf, 0xdc, 0xcb, 0xd7, 0xff, 0xb1, 0x71, 0x7c, 0x6f, 0x88, 0xf8, - /* (2^296)P */ 0x3f, 0x89, 0xb1, 0xbf, 0x24, 0x16, 0xac, 0x56, 0xfe, 0xdf, 0x94, 0x71, 0xbf, 0xd6, 0x57, 0x0c, 0xb4, 0x77, 0x37, 0xaa, 0x2a, 0x70, 0x76, 0x49, 0xaf, 0x0c, 0x97, 0x8e, 0x78, 0x2a, 0x67, 0xc9, 0x3b, 0x3d, 0x5b, 0x01, 0x2f, 0xda, 0xd5, 0xa8, 0xde, 0x02, 0xa9, 0xac, 0x76, 0x00, 0x0b, 0x46, 0xc6, 0x2d, 0xdc, 0x08, 0xf4, 0x10, 0x2c, 0xbe, - /* (2^297)P */ 0xcb, 0x07, 0xf9, 0x91, 0xc6, 0xd5, 0x3e, 0x54, 0x63, 0xae, 0xfc, 0x10, 0xbe, 0x3a, 0x20, 0x73, 0x4e, 0x65, 0x0e, 0x2d, 0x86, 0x77, 0x83, 0x9d, 0xe2, 0x0a, 0xe9, 0xac, 0x22, 0x52, 0x76, 0xd4, 0x6e, 0xfa, 0xe0, 0x09, 0xef, 0x78, 0x82, 0x9f, 0x26, 0xf9, 0x06, 0xb5, 0xe7, 0x05, 0x0e, 0xf2, 0x46, 0x72, 0x93, 0xd3, 0x24, 0xbd, 0x87, 0x60, - /* (2^298)P */ 0x14, 0x55, 0x84, 0x7b, 0x6c, 0x60, 0x80, 0x73, 0x8c, 0xbe, 0x2d, 0xd6, 0x69, 0xd6, 0x17, 0x26, 0x44, 0x9f, 0x88, 0xa2, 0x39, 0x7c, 0x89, 0xbc, 0x6d, 0x9e, 0x46, 0xb6, 0x68, 0x66, 0xea, 0xdc, 0x31, 0xd6, 0x21, 0x51, 0x9f, 0x28, 0x28, 0xaf, 0x9e, 0x47, 0x2c, 0x4c, 0x8f, 0xf3, 0xaf, 0x1f, 0xe4, 0xab, 0xac, 0xe9, 0x0c, 0x91, 0x3a, 0x61, - /* (2^299)P */ 0xb0, 0x37, 0x55, 0x4b, 0xe9, 0xc3, 0xb1, 0xce, 0x42, 0xe6, 0xc5, 0x11, 0x7f, 0x2c, 0x11, 0xfc, 0x4e, 0x71, 0x17, 0x00, 0x74, 0x7f, 0xbf, 0x07, 0x4d, 0xfd, 0x40, 0xb2, 0x87, 0xb0, 0xef, 0x1f, 0x35, 0x2c, 0x2d, 0xd7, 0xe1, 0xe4, 0xad, 0x0e, 0x7f, 0x63, 0x66, 0x62, 0x23, 0x41, 0xf6, 0xc1, 0x14, 0xa6, 0xd7, 0xa9, 0x11, 0x56, 0x9d, 0x1b, - /* (2^300)P */ 0x02, 0x82, 0x42, 0x18, 0x4f, 0x1b, 0xc9, 0x5d, 0x78, 0x5f, 0xee, 0xed, 0x01, 0x49, 0x8f, 0xf2, 0xa0, 0xe2, 0x6e, 0xbb, 0x6b, 0x04, 0x8d, 0xb2, 0x41, 0xae, 0xc8, 0x1b, 0x59, 0x34, 0xb8, 0x2a, 0xdb, 0x1f, 0xd2, 0x52, 0xdf, 0x3f, 0x35, 0x00, 0x8b, 0x61, 0xbc, 0x97, 0xa0, 0xc4, 0x77, 0xd1, 0xe4, 0x2c, 0x59, 0x68, 0xff, 0x30, 0xf2, 0xe2, - /* (2^301)P */ 0x79, 0x08, 0xb1, 0xdb, 0x55, 0xae, 0xd0, 0xed, 0xda, 0xa0, 0xec, 0x6c, 0xae, 0x68, 0xf2, 0x0b, 0x61, 0xb3, 0xf5, 0x21, 0x69, 0x87, 0x0b, 0x03, 0xea, 0x8a, 0x15, 0xd9, 0x7e, 0xca, 0xf7, 0xcd, 0xf3, 0x33, 0xb3, 0x4c, 0x5b, 0x23, 0x4e, 0x6f, 0x90, 0xad, 0x91, 0x4b, 0x4f, 0x46, 0x37, 0xe5, 0xe8, 0xb7, 0xeb, 0xd5, 0xca, 0x34, 0x4e, 0x23, - /* (2^302)P */ 0x09, 0x02, 0xdd, 0xfd, 0x70, 0xac, 0x56, 0x80, 0x36, 0x5e, 0x49, 0xd0, 0x3f, 0xc2, 0xe0, 0xba, 0x46, 0x7f, 0x5c, 0xf7, 0xc5, 0xbd, 0xd5, 0x55, 0x7d, 0x3f, 0xd5, 0x7d, 0x06, 0xdf, 0x27, 0x20, 0x4f, 0xe9, 0x30, 0xec, 0x1b, 0xa0, 0x0c, 0xd4, 0x2c, 0xe1, 0x2b, 0x65, 0x73, 0xea, 0x75, 0x35, 0xe8, 0xe6, 0x56, 0xd6, 0x07, 0x15, 0x99, 0xdf, - /* (2^303)P */ 0x4e, 0x10, 0xb7, 0xd0, 0x63, 0x8c, 0xcf, 0x16, 0x00, 0x7c, 0x58, 0xdf, 0x86, 0xdc, 0x4e, 0xca, 0x9c, 0x40, 0x5a, 0x42, 0xfd, 0xec, 0x98, 0xa4, 0x42, 0x53, 0xae, 0x16, 0x9d, 0xfd, 0x75, 0x5a, 0x12, 0x56, 0x1e, 0xc6, 0x57, 0xcc, 0x79, 0x27, 0x96, 0x00, 0xcf, 0x80, 0x4f, 0x8a, 0x36, 0x5c, 0xbb, 0xe9, 0x12, 0xdb, 0xb6, 0x2b, 0xad, 0x96, - /* (2^304)P */ 0x92, 0x32, 0x1f, 0xfd, 0xc6, 0x02, 0x94, 0x08, 0x1b, 0x60, 0x6a, 0x9f, 0x8b, 0xd6, 0xc8, 0xad, 0xd5, 0x1b, 0x27, 0x4e, 0xa4, 0x4d, 0x4a, 0x00, 0x10, 0x5f, 0x86, 0x11, 0xf5, 0xe3, 0x14, 0x32, 0x43, 0xee, 0xb9, 0xc7, 0xab, 0xf4, 0x6f, 0xe5, 0x66, 0x0c, 0x06, 0x0d, 0x96, 0x79, 0x28, 0xaf, 0x45, 0x2b, 0x56, 0xbe, 0xe4, 0x4a, 0x52, 0xd6, - /* (2^305)P */ 0x15, 0x16, 0x69, 0xef, 0x60, 0xca, 0x82, 0x25, 0x0f, 0xc6, 0x30, 0xa0, 0x0a, 0xd1, 0x83, 0x29, 0xcd, 0xb6, 0x89, 0x6c, 0xf5, 0xb2, 0x08, 0x38, 0xe6, 0xca, 0x6b, 0x19, 0x93, 0xc6, 0x5f, 0x75, 0x8e, 0x60, 0x34, 0x23, 0xc4, 0x13, 0x17, 0x69, 0x55, 0xcc, 0x72, 0x9c, 0x2b, 0x6c, 0x80, 0xf4, 0x4b, 0x8b, 0xb6, 0x97, 0x65, 0x07, 0xb6, 0xfb, - /* (2^306)P */ 0x01, 0x99, 0x74, 0x28, 0xa6, 0x67, 0xa3, 0xe5, 0x25, 0xfb, 0xdf, 0x82, 0x93, 0xe7, 0x35, 0x74, 0xce, 0xe3, 0x15, 0x1c, 0x1d, 0x79, 0x52, 0x84, 0x08, 0x04, 0x2f, 0x5c, 0xb8, 0xcd, 0x7f, 0x89, 0xb0, 0x39, 0x93, 0x63, 0xc9, 0x5d, 0x06, 0x01, 0x59, 0xf7, 0x7e, 0xf1, 0x4c, 0x3d, 0x12, 0x8d, 0x69, 0x1d, 0xb7, 0x21, 0x5e, 0x88, 0x82, 0xa2, - /* (2^307)P */ 0x8e, 0x69, 0xaf, 0x9a, 0x41, 0x0d, 0x9d, 0xcf, 0x8e, 0x8d, 0x5c, 0x51, 0x6e, 0xde, 0x0e, 0x48, 0x23, 0x89, 0xe5, 0x37, 0x80, 0xd6, 0x9d, 0x72, 0x32, 0x26, 0x38, 0x2d, 0x63, 0xa0, 0xfa, 0xd3, 0x40, 0xc0, 0x8c, 0x68, 0x6f, 0x2b, 0x1e, 0x9a, 0x39, 0x51, 0x78, 0x74, 0x9a, 0x7b, 0x4a, 0x8f, 0x0c, 0xa0, 0x88, 0x60, 0xa5, 0x21, 0xcd, 0xc7, - /* (2^308)P */ 0x3a, 0x7f, 0x73, 0x14, 0xbf, 0x89, 0x6a, 0x4c, 0x09, 0x5d, 0xf2, 0x93, 0x20, 0x2d, 0xc4, 0x29, 0x86, 0x06, 0x95, 0xab, 0x22, 0x76, 0x4c, 0x54, 0xe1, 0x7e, 0x80, 0x6d, 0xab, 0x29, 0x61, 0x87, 0x77, 0xf6, 0xc0, 0x3e, 0xda, 0xab, 0x65, 0x7e, 0x39, 0x12, 0xa1, 0x6b, 0x42, 0xf7, 0xc5, 0x97, 0x77, 0xec, 0x6f, 0x22, 0xbe, 0x44, 0xc7, 0x03, - /* (2^309)P */ 0xa5, 0x23, 0x90, 0x41, 0xa3, 0xc5, 0x3e, 0xe0, 0xa5, 0x32, 0x49, 0x1f, 0x39, 0x78, 0xb1, 0xd8, 0x24, 0xea, 0xd4, 0x87, 0x53, 0x42, 0x51, 0xf4, 0xd9, 0x46, 0x25, 0x2f, 0x62, 0xa9, 0x90, 0x9a, 0x4a, 0x25, 0x8a, 0xd2, 0x10, 0xe7, 0x3c, 0xbc, 0x58, 0x8d, 0x16, 0x14, 0x96, 0xa4, 0x6f, 0xf8, 0x12, 0x69, 0x91, 0x73, 0xe2, 0xfa, 0xf4, 0x57, - /* (2^310)P */ 0x51, 0x45, 0x3f, 0x96, 0xdc, 0x97, 0x38, 0xa6, 0x01, 0x63, 0x09, 0xea, 0xc2, 0x13, 0x30, 0xb0, 0x00, 0xb8, 0x0a, 0xce, 0xd1, 0x8f, 0x3e, 0x69, 0x62, 0x46, 0x33, 0x9c, 0xbf, 0x4b, 0xcb, 0x0c, 0x90, 0x1c, 0x45, 0xcf, 0x37, 0x5b, 0xf7, 0x4b, 0x5e, 0x95, 0xc3, 0x28, 0x9f, 0x08, 0x83, 0x53, 0x74, 0xab, 0x0c, 0xb4, 0xc0, 0xa1, 0xbc, 0x89, - /* (2^311)P */ 0x06, 0xb1, 0x51, 0x15, 0x65, 0x60, 0x21, 0x17, 0x7a, 0x20, 0x65, 0xee, 0x12, 0x35, 0x4d, 0x46, 0xf4, 0xf8, 0xd0, 0xb1, 0xca, 0x09, 0x30, 0x08, 0x89, 0x23, 0x3b, 0xe7, 0xab, 0x8b, 0x77, 0xa6, 0xad, 0x25, 0xdd, 0xea, 0x3c, 0x7d, 0xa5, 0x24, 0xb3, 0xe8, 0xfa, 0xfb, 0xc9, 0xf2, 0x71, 0xe9, 0xfa, 0xf2, 0xdc, 0x54, 0xdd, 0x55, 0x2e, 0x2f, - /* (2^312)P */ 0x7f, 0x96, 0x96, 0xfb, 0x52, 0x86, 0xcf, 0xea, 0x62, 0x18, 0xf1, 0x53, 0x1f, 0x61, 0x2a, 0x9f, 0x8c, 0x51, 0xca, 0x2c, 0xde, 0x6d, 0xce, 0xab, 0x58, 0x32, 0x0b, 0x33, 0x9b, 0x99, 0xb4, 0x5c, 0x88, 0x2a, 0x76, 0xcc, 0x3e, 0x54, 0x1e, 0x9d, 0xa2, 0x89, 0xe4, 0x19, 0xba, 0x80, 0xc8, 0x39, 0x32, 0x7f, 0x0f, 0xc7, 0x84, 0xbb, 0x43, 0x56, - /* (2^313)P */ 0x9b, 0x07, 0xb4, 0x42, 0xa9, 0xa0, 0x78, 0x4f, 0x28, 0x70, 0x2b, 0x7e, 0x61, 0xe0, 0xdd, 0x02, 0x98, 0xfc, 0xed, 0x31, 0x80, 0xf1, 0x15, 0x52, 0x89, 0x23, 0xcd, 0x5d, 0x2b, 0xc5, 0x19, 0x32, 0xfb, 0x70, 0x50, 0x7a, 0x97, 0x6b, 0x42, 0xdb, 0xca, 0xdb, 0xc4, 0x59, 0x99, 0xe0, 0x12, 0x1f, 0x17, 0xba, 0x8b, 0xf0, 0xc4, 0x38, 0x5d, 0x27, - /* (2^314)P */ 0x29, 0x1d, 0xdc, 0x2b, 0xf6, 0x5b, 0x04, 0x61, 0x36, 0x76, 0xa0, 0x56, 0x36, 0x6e, 0xd7, 0x24, 0x4d, 0xe7, 0xef, 0x44, 0xd2, 0xd5, 0x07, 0xcd, 0xc4, 0x9d, 0x80, 0x48, 0xc3, 0x38, 0xcf, 0xd8, 0xa3, 0xdd, 0xb2, 0x5e, 0xb5, 0x70, 0x15, 0xbb, 0x36, 0x85, 0x8a, 0xd7, 0xfb, 0x56, 0x94, 0x73, 0x9c, 0x81, 0xbe, 0xb1, 0x44, 0x28, 0xf1, 0x37, - /* (2^315)P */ 0xbf, 0xcf, 0x5c, 0xd2, 0xe2, 0xea, 0xc2, 0xcd, 0x70, 0x7a, 0x9d, 0xcb, 0x81, 0xc1, 0xe9, 0xf1, 0x56, 0x71, 0x52, 0xf7, 0x1b, 0x87, 0xc6, 0xd8, 0xcc, 0xb2, 0x69, 0xf3, 0xb0, 0xbd, 0xba, 0x83, 0x12, 0x26, 0xc4, 0xce, 0x72, 0xde, 0x3b, 0x21, 0x28, 0x9e, 0x5a, 0x94, 0xf5, 0x04, 0xa3, 0xc8, 0x0f, 0x5e, 0xbc, 0x71, 0xf9, 0x0d, 0xce, 0xf5, - /* (2^316)P */ 0x93, 0x97, 0x00, 0x85, 0xf4, 0xb4, 0x40, 0xec, 0xd9, 0x2b, 0x6c, 0xd6, 0x63, 0x9e, 0x93, 0x0a, 0x5a, 0xf4, 0xa7, 0x9a, 0xe3, 0x3c, 0xf0, 0x55, 0xd1, 0x96, 0x6c, 0xf5, 0x2a, 0xce, 0xd7, 0x95, 0x72, 0xbf, 0xc5, 0x0c, 0xce, 0x79, 0xa2, 0x0a, 0x78, 0xe0, 0x72, 0xd0, 0x66, 0x28, 0x05, 0x75, 0xd3, 0x23, 0x09, 0x91, 0xed, 0x7e, 0xc4, 0xbc, - /* (2^317)P */ 0x77, 0xc2, 0x9a, 0xf7, 0xa6, 0xe6, 0x18, 0xb4, 0xe7, 0xf6, 0xda, 0xec, 0x44, 0x6d, 0xfb, 0x08, 0xee, 0x65, 0xa8, 0x92, 0x85, 0x1f, 0xba, 0x38, 0x93, 0x20, 0x5c, 0x4d, 0xd2, 0x18, 0x0f, 0x24, 0xbe, 0x1a, 0x96, 0x44, 0x7d, 0xeb, 0xb3, 0xda, 0x95, 0xf4, 0xaf, 0x6c, 0x06, 0x0f, 0x47, 0x37, 0xc8, 0x77, 0x63, 0xe1, 0x29, 0xef, 0xff, 0xa5, - /* (2^318)P */ 0x16, 0x12, 0xd9, 0x47, 0x90, 0x22, 0x9b, 0x05, 0xf2, 0xa5, 0x9a, 0xae, 0x83, 0x98, 0xb5, 0xac, 0xab, 0x29, 0xaa, 0xdc, 0x5f, 0xde, 0xcd, 0xf7, 0x42, 0xad, 0x3b, 0x96, 0xd6, 0x3e, 0x6e, 0x52, 0x47, 0xb1, 0xab, 0x51, 0xde, 0x49, 0x7c, 0x87, 0x8d, 0x86, 0xe2, 0x70, 0x13, 0x21, 0x51, 0x1c, 0x0c, 0x25, 0xc1, 0xb0, 0xe6, 0x19, 0xcf, 0x12, - /* (2^319)P */ 0xf0, 0xbc, 0x97, 0x8f, 0x4b, 0x2f, 0xd1, 0x1f, 0x8c, 0x57, 0xed, 0x3c, 0xf4, 0x26, 0x19, 0xbb, 0x60, 0xca, 0x24, 0xc5, 0xd9, 0x97, 0xe2, 0x5f, 0x76, 0x49, 0x39, 0x7e, 0x2d, 0x12, 0x21, 0x98, 0xda, 0xe6, 0xdb, 0xd2, 0xd8, 0x9f, 0x18, 0xd8, 0x83, 0x6c, 0xba, 0x89, 0x8d, 0x29, 0xfa, 0x46, 0x33, 0x8c, 0x28, 0xdf, 0x6a, 0xb3, 0x69, 0x28, - /* (2^320)P */ 0x86, 0x17, 0xbc, 0xd6, 0x7c, 0xba, 0x1e, 0x83, 0xbb, 0x84, 0xb5, 0x8c, 0xad, 0xdf, 0xa1, 0x24, 0x81, 0x70, 0x40, 0x0f, 0xad, 0xad, 0x3b, 0x23, 0xd0, 0x93, 0xa0, 0x49, 0x5c, 0x4b, 0x51, 0xbe, 0x20, 0x49, 0x4e, 0xda, 0x2d, 0xd3, 0xad, 0x1b, 0x74, 0x08, 0x41, 0xf0, 0xef, 0x19, 0xe9, 0x45, 0x5d, 0x02, 0xae, 0x26, 0x25, 0xd9, 0xd1, 0xc2, - /* (2^321)P */ 0x48, 0x81, 0x3e, 0xb2, 0x83, 0xf8, 0x4d, 0xb3, 0xd0, 0x4c, 0x75, 0xb3, 0xa0, 0x52, 0x26, 0xf2, 0xaf, 0x5d, 0x36, 0x70, 0x72, 0xd6, 0xb7, 0x88, 0x08, 0x69, 0xbd, 0x15, 0x25, 0xb1, 0x45, 0x1b, 0xb7, 0x0b, 0x5f, 0x71, 0x5d, 0x83, 0x49, 0xb9, 0x84, 0x3b, 0x7c, 0xc1, 0x50, 0x93, 0x05, 0x53, 0xe0, 0x61, 0xea, 0xc1, 0xef, 0xdb, 0x82, 0x97, - /* (2^322)P */ 0x00, 0xd5, 0xc3, 0x3a, 0x4d, 0x8a, 0x23, 0x7a, 0xef, 0xff, 0x37, 0xef, 0xf3, 0xbc, 0xa9, 0xb6, 0xae, 0xd7, 0x3a, 0x7b, 0xfd, 0x3e, 0x8e, 0x9b, 0xab, 0x44, 0x54, 0x60, 0x28, 0x6c, 0xbf, 0x15, 0x24, 0x4a, 0x56, 0x60, 0x7f, 0xa9, 0x7a, 0x28, 0x59, 0x2c, 0x8a, 0xd1, 0x7d, 0x6b, 0x00, 0xfd, 0xa5, 0xad, 0xbc, 0x19, 0x3f, 0xcb, 0x73, 0xe0, - /* (2^323)P */ 0xcf, 0x9e, 0x66, 0x06, 0x4d, 0x2b, 0xf5, 0x9c, 0xc2, 0x9d, 0x9e, 0xed, 0x5a, 0x5c, 0x2d, 0x00, 0xbf, 0x29, 0x90, 0x88, 0xe4, 0x5d, 0xfd, 0xe2, 0xf0, 0x38, 0xec, 0x4d, 0x26, 0xea, 0x54, 0xf0, 0x3c, 0x84, 0x10, 0x6a, 0xf9, 0x66, 0x9c, 0xe7, 0x21, 0xfd, 0x0f, 0xc7, 0x13, 0x50, 0x81, 0xb6, 0x50, 0xf9, 0x04, 0x7f, 0xa4, 0x37, 0x85, 0x14, - /* (2^324)P */ 0xdb, 0x87, 0x49, 0xc7, 0xa8, 0x39, 0x0c, 0x32, 0x98, 0x0c, 0xb9, 0x1a, 0x1b, 0x4d, 0xe0, 0x8a, 0x9a, 0x8e, 0x8f, 0xab, 0x5a, 0x17, 0x3d, 0x04, 0x21, 0xce, 0x3e, 0x2c, 0xf9, 0xa3, 0x97, 0xe4, 0x77, 0x95, 0x0e, 0xb6, 0xa5, 0x15, 0xad, 0x3a, 0x1e, 0x46, 0x53, 0x17, 0x09, 0x83, 0x71, 0x4e, 0x86, 0x38, 0xd5, 0x23, 0x44, 0x16, 0x8d, 0xc8, - /* (2^325)P */ 0x05, 0x5e, 0x99, 0x08, 0xbb, 0xc3, 0xc0, 0xb7, 0x6c, 0x12, 0xf2, 0xf3, 0xf4, 0x7c, 0x6a, 0x4d, 0x9e, 0xeb, 0x3d, 0xb9, 0x63, 0x94, 0xce, 0x81, 0xd8, 0x11, 0xcb, 0x55, 0x69, 0x4a, 0x20, 0x0b, 0x4c, 0x2e, 0x14, 0xb8, 0xd4, 0x6a, 0x7c, 0xf0, 0xed, 0xfc, 0x8f, 0xef, 0xa0, 0xeb, 0x6c, 0x01, 0xe2, 0xdc, 0x10, 0x22, 0xa2, 0x01, 0x85, 0x64, - /* (2^326)P */ 0x58, 0xe1, 0x9c, 0x27, 0x55, 0xc6, 0x25, 0xa6, 0x7d, 0x67, 0x88, 0x65, 0x99, 0x6c, 0xcb, 0xdb, 0x27, 0x4f, 0x44, 0x29, 0xf5, 0x4a, 0x23, 0x10, 0xbc, 0x03, 0x3f, 0x36, 0x1e, 0xef, 0xb0, 0xba, 0x75, 0xe8, 0x74, 0x5f, 0x69, 0x3e, 0x26, 0x40, 0xb4, 0x2f, 0xdc, 0x43, 0xbf, 0xa1, 0x8b, 0xbd, 0xca, 0x6e, 0xc1, 0x6e, 0x21, 0x79, 0xa0, 0xd0, - /* (2^327)P */ 0x78, 0x93, 0x4a, 0x2d, 0x22, 0x6e, 0x6e, 0x7d, 0x74, 0xd2, 0x66, 0x58, 0xce, 0x7b, 0x1d, 0x97, 0xb1, 0xf2, 0xda, 0x1c, 0x79, 0xfb, 0xba, 0xd1, 0xc0, 0xc5, 0x6e, 0xc9, 0x11, 0x89, 0xd2, 0x41, 0x8d, 0x70, 0xb9, 0xcc, 0xea, 0x6a, 0xb3, 0x45, 0xb6, 0x05, 0x2e, 0xf2, 0x17, 0xf1, 0x27, 0xb8, 0xed, 0x06, 0x1f, 0xdb, 0x9d, 0x1f, 0x69, 0x28, - /* (2^328)P */ 0x93, 0x12, 0xa8, 0x11, 0xe1, 0x92, 0x30, 0x8d, 0xac, 0xe1, 0x1c, 0x60, 0x7c, 0xed, 0x2d, 0x2e, 0xd3, 0x03, 0x5c, 0x9c, 0xc5, 0xbd, 0x64, 0x4a, 0x8c, 0xba, 0x76, 0xfe, 0xc6, 0xc1, 0xea, 0xc2, 0x4f, 0xbe, 0x70, 0x3d, 0x64, 0xcf, 0x8e, 0x18, 0xcb, 0xcd, 0x57, 0xa7, 0xf7, 0x36, 0xa9, 0x6b, 0x3e, 0xb8, 0x69, 0xee, 0x47, 0xa2, 0x7e, 0xb2, - /* (2^329)P */ 0x96, 0xaf, 0x3a, 0xf5, 0xed, 0xcd, 0xaf, 0xf7, 0x82, 0xaf, 0x59, 0x62, 0x0b, 0x36, 0x85, 0xf9, 0xaf, 0xd6, 0x38, 0xff, 0x87, 0x2e, 0x1d, 0x6c, 0x8b, 0xaf, 0x3b, 0xdf, 0x28, 0xa2, 0xd6, 0x4d, 0x80, 0x92, 0xc3, 0x0f, 0x34, 0xa8, 0xae, 0x69, 0x5d, 0x7b, 0x9d, 0xbc, 0xf5, 0xfd, 0x1d, 0xb1, 0x96, 0x55, 0x86, 0xe1, 0x5c, 0xb6, 0xac, 0xb9, - /* (2^330)P */ 0x50, 0x9e, 0x37, 0x28, 0x7d, 0xa8, 0x33, 0x63, 0xda, 0x3f, 0x20, 0x98, 0x0e, 0x09, 0xa8, 0x77, 0x3b, 0x7a, 0xfc, 0x16, 0x85, 0x44, 0x64, 0x77, 0x65, 0x68, 0x92, 0x41, 0xc6, 0x1f, 0xdf, 0x27, 0xf9, 0xec, 0xa0, 0x61, 0x22, 0xea, 0x19, 0xe7, 0x75, 0x8b, 0x4e, 0xe5, 0x0f, 0xb7, 0xf7, 0xd2, 0x53, 0xf4, 0xdd, 0x4a, 0xaa, 0x78, 0x40, 0xb7, - /* (2^331)P */ 0xd4, 0x89, 0xe3, 0x79, 0xba, 0xb6, 0xc3, 0xda, 0xe6, 0x78, 0x65, 0x7d, 0x6e, 0x22, 0x62, 0xb1, 0x3d, 0xea, 0x90, 0x84, 0x30, 0x5e, 0xd4, 0x39, 0x84, 0x78, 0xd9, 0x75, 0xd6, 0xce, 0x2a, 0x11, 0x29, 0x69, 0xa4, 0x5e, 0xaa, 0x2a, 0x98, 0x5a, 0xe5, 0x91, 0x8f, 0xb2, 0xfb, 0xda, 0x97, 0xe8, 0x83, 0x6f, 0x04, 0xb9, 0x5d, 0xaf, 0xe1, 0x9b, - /* (2^332)P */ 0x8b, 0xe4, 0xe1, 0x48, 0x9c, 0xc4, 0x83, 0x89, 0xdf, 0x65, 0xd3, 0x35, 0x55, 0x13, 0xf4, 0x1f, 0x36, 0x92, 0x33, 0x38, 0xcb, 0xed, 0x15, 0xe6, 0x60, 0x2d, 0x25, 0xf5, 0x36, 0x60, 0x3a, 0x37, 0x9b, 0x71, 0x9d, 0x42, 0xb0, 0x14, 0xc8, 0xba, 0x62, 0xa3, 0x49, 0xb0, 0x88, 0xc1, 0x72, 0x73, 0xdd, 0x62, 0x40, 0xa9, 0x62, 0x88, 0x99, 0xca, - /* (2^333)P */ 0x47, 0x7b, 0xea, 0xda, 0x46, 0x2f, 0x45, 0xc6, 0xe3, 0xb4, 0x4d, 0x8d, 0xac, 0x0b, 0x54, 0x22, 0x06, 0x31, 0x16, 0x66, 0x3e, 0xe4, 0x38, 0x12, 0xcd, 0xf3, 0xe7, 0x99, 0x37, 0xd9, 0x62, 0x24, 0x4b, 0x05, 0xf2, 0x58, 0xe6, 0x29, 0x4b, 0x0d, 0xf6, 0xc1, 0xba, 0xa0, 0x1e, 0x0f, 0xcb, 0x1f, 0xc6, 0x2b, 0x19, 0xfc, 0x82, 0x01, 0xd0, 0x86, - /* (2^334)P */ 0xa2, 0xae, 0x77, 0x20, 0xfb, 0xa8, 0x18, 0xb4, 0x61, 0xef, 0xe8, 0x52, 0x79, 0xbb, 0x86, 0x90, 0x5d, 0x2e, 0x76, 0xed, 0x66, 0x60, 0x5d, 0x00, 0xb5, 0xa4, 0x00, 0x40, 0x89, 0xec, 0xd1, 0xd2, 0x0d, 0x26, 0xb9, 0x30, 0xb2, 0xd2, 0xb8, 0xe8, 0x0e, 0x56, 0xf9, 0x67, 0x94, 0x2e, 0x62, 0xe1, 0x79, 0x48, 0x2b, 0xa9, 0xfa, 0xea, 0xdb, 0x28, - /* (2^335)P */ 0x35, 0xf1, 0xb0, 0x43, 0xbd, 0x27, 0xef, 0x18, 0x44, 0xa2, 0x04, 0xb4, 0x69, 0xa1, 0x97, 0x1f, 0x8c, 0x04, 0x82, 0x9b, 0x00, 0x6d, 0xf8, 0xbf, 0x7d, 0xc1, 0x5b, 0xab, 0xe8, 0xb2, 0x34, 0xbd, 0xaf, 0x7f, 0xb2, 0x0d, 0xf3, 0xed, 0xfc, 0x5b, 0x50, 0xee, 0xe7, 0x4a, 0x20, 0xd9, 0xf5, 0xc6, 0x9a, 0x97, 0x6d, 0x07, 0x2f, 0xb9, 0x31, 0x02, - /* (2^336)P */ 0xf9, 0x54, 0x4a, 0xc5, 0x61, 0x7e, 0x1d, 0xa6, 0x0e, 0x1a, 0xa8, 0xd3, 0x8c, 0x36, 0x7d, 0xf1, 0x06, 0xb1, 0xac, 0x93, 0xcd, 0xe9, 0x8f, 0x61, 0x6c, 0x5d, 0x03, 0x23, 0xdf, 0x85, 0x53, 0x39, 0x63, 0x5e, 0xeb, 0xf3, 0xd3, 0xd3, 0x75, 0x97, 0x9b, 0x62, 0x9b, 0x01, 0xb3, 0x19, 0xd8, 0x2b, 0x36, 0xf2, 0x2c, 0x2c, 0x6f, 0x36, 0xc6, 0x3c, - /* (2^337)P */ 0x05, 0x74, 0x43, 0x10, 0xb6, 0xb0, 0xf8, 0xbf, 0x02, 0x46, 0x9a, 0xee, 0xc1, 0xaf, 0xc1, 0xe5, 0x5a, 0x2e, 0xbb, 0xe1, 0xdc, 0xc6, 0xce, 0x51, 0x29, 0x50, 0xbf, 0x1b, 0xde, 0xff, 0xba, 0x4d, 0x8d, 0x8b, 0x7e, 0xe7, 0xbd, 0x5b, 0x8f, 0xbe, 0xe3, 0x75, 0x71, 0xff, 0x37, 0x05, 0x5a, 0x10, 0xeb, 0x54, 0x7e, 0x44, 0x72, 0x2c, 0xd4, 0xfc, - /* (2^338)P */ 0x03, 0x12, 0x1c, 0xb2, 0x08, 0x90, 0xa1, 0x2d, 0x50, 0xa0, 0xad, 0x7f, 0x8d, 0xa6, 0x97, 0xc1, 0xbd, 0xdc, 0xc3, 0xa7, 0xad, 0x31, 0xdf, 0xb8, 0x03, 0x84, 0xc3, 0xb9, 0x29, 0x3d, 0x92, 0x2e, 0xc3, 0x90, 0x07, 0xe8, 0xa7, 0xc7, 0xbc, 0x61, 0xe9, 0x3e, 0xa0, 0x35, 0xda, 0x1d, 0xab, 0x48, 0xfe, 0x50, 0xc9, 0x25, 0x59, 0x23, 0x69, 0x3f, - /* (2^339)P */ 0x8e, 0x91, 0xab, 0x6b, 0x91, 0x4f, 0x89, 0x76, 0x67, 0xad, 0xb2, 0x65, 0x9d, 0xad, 0x02, 0x36, 0xdc, 0xac, 0x96, 0x93, 0x97, 0x21, 0x14, 0xd0, 0xe8, 0x11, 0x60, 0x1e, 0xeb, 0x96, 0x06, 0xf2, 0x53, 0xf2, 0x6d, 0xb7, 0x93, 0x6f, 0x26, 0x91, 0x23, 0xe3, 0x34, 0x04, 0x92, 0x91, 0x37, 0x08, 0x50, 0xd6, 0x28, 0x09, 0x27, 0xa1, 0x0c, 0x00, - /* (2^340)P */ 0x1f, 0xbb, 0x21, 0x26, 0x33, 0xcb, 0xa4, 0xd1, 0xee, 0x85, 0xf9, 0xd9, 0x3c, 0x90, 0xc3, 0xd1, 0x26, 0xa2, 0x25, 0x93, 0x43, 0x61, 0xed, 0x91, 0x6e, 0x54, 0x03, 0x2e, 0x42, 0x9d, 0xf7, 0xa6, 0x02, 0x0f, 0x2f, 0x9c, 0x7a, 0x8d, 0x12, 0xc2, 0x18, 0xfc, 0x41, 0xff, 0x85, 0x26, 0x1a, 0x44, 0x55, 0x0b, 0x89, 0xab, 0x6f, 0x62, 0x33, 0x8c, - /* (2^341)P */ 0xe0, 0x3c, 0x5d, 0x70, 0x64, 0x87, 0x81, 0x35, 0xf2, 0x37, 0xa6, 0x24, 0x3e, 0xe0, 0x62, 0xd5, 0x71, 0xe7, 0x93, 0xfb, 0xac, 0xc3, 0xe7, 0xc7, 0x04, 0xe2, 0x70, 0xd3, 0x29, 0x5b, 0x21, 0xbf, 0xf4, 0x26, 0x5d, 0xf3, 0x95, 0xb4, 0x2a, 0x6a, 0x07, 0x55, 0xa6, 0x4b, 0x3b, 0x15, 0xf2, 0x25, 0x8a, 0x95, 0x3f, 0x63, 0x2f, 0x7a, 0x23, 0x96, - /* (2^342)P */ 0x0d, 0x3d, 0xd9, 0x13, 0xa7, 0xb3, 0x5e, 0x67, 0xf7, 0x02, 0x23, 0xee, 0x84, 0xff, 0x99, 0xda, 0xb9, 0x53, 0xf8, 0xf0, 0x0e, 0x39, 0x2f, 0x3c, 0x64, 0x34, 0xe3, 0x09, 0xfd, 0x2b, 0x33, 0xc7, 0xfe, 0x62, 0x2b, 0x84, 0xdf, 0x2b, 0xd2, 0x7c, 0x26, 0x01, 0x70, 0x66, 0x5b, 0x85, 0xc2, 0xbe, 0x88, 0x37, 0xf1, 0x30, 0xac, 0xb8, 0x76, 0xa3, - /* (2^343)P */ 0x6e, 0x01, 0xf0, 0x55, 0x35, 0xe4, 0xbd, 0x43, 0x62, 0x9d, 0xd6, 0x11, 0xef, 0x6f, 0xb8, 0x8c, 0xaa, 0x98, 0x87, 0xc6, 0x6d, 0xc4, 0xcc, 0x74, 0x92, 0x53, 0x4a, 0xdf, 0xe4, 0x08, 0x89, 0x17, 0xd0, 0x0f, 0xf4, 0x00, 0x60, 0x78, 0x08, 0x44, 0xb5, 0xda, 0x18, 0xed, 0x98, 0xc8, 0x61, 0x3d, 0x39, 0xdb, 0xcf, 0x1d, 0x49, 0x40, 0x65, 0x75, - /* (2^344)P */ 0x8e, 0x10, 0xae, 0x5f, 0x06, 0xd2, 0x95, 0xfd, 0x20, 0x16, 0x49, 0x5b, 0x57, 0xbe, 0x22, 0x8b, 0x43, 0xfb, 0xe6, 0xcc, 0x26, 0xa5, 0x5d, 0xd3, 0x68, 0xc5, 0xf9, 0x5a, 0x86, 0x24, 0x87, 0x27, 0x05, 0xfd, 0xe2, 0xff, 0xb3, 0xa3, 0x7b, 0x37, 0x59, 0xc5, 0x4e, 0x14, 0x94, 0xf9, 0x3b, 0xcb, 0x7c, 0xed, 0xca, 0x1d, 0xb2, 0xac, 0x05, 0x4a, - /* (2^345)P */ 0xf4, 0xd1, 0x81, 0xeb, 0x89, 0xbf, 0xfe, 0x1e, 0x41, 0x92, 0x29, 0xee, 0xe1, 0x43, 0xf5, 0x86, 0x1d, 0x2f, 0xbb, 0x1e, 0x84, 0x5d, 0x7b, 0x8d, 0xd5, 0xda, 0xee, 0x1e, 0x8a, 0xd0, 0x27, 0xf2, 0x60, 0x51, 0x59, 0x82, 0xf4, 0x84, 0x2b, 0x5b, 0x14, 0x2d, 0x81, 0x82, 0x3e, 0x2b, 0xb4, 0x6d, 0x51, 0x4f, 0xc5, 0xcb, 0xbf, 0x74, 0xe3, 0xb4, - /* (2^346)P */ 0x19, 0x2f, 0x22, 0xb3, 0x04, 0x5f, 0x81, 0xca, 0x05, 0x60, 0xb9, 0xaa, 0xee, 0x0e, 0x2f, 0x48, 0x38, 0xf9, 0x91, 0xb4, 0x66, 0xe4, 0x57, 0x28, 0x54, 0x10, 0xe9, 0x61, 0x9d, 0xd4, 0x90, 0x75, 0xb1, 0x39, 0x23, 0xb6, 0xfc, 0x82, 0xe0, 0xfa, 0xbb, 0x5c, 0x6e, 0xc3, 0x44, 0x13, 0x00, 0x83, 0x55, 0x9e, 0x8e, 0x10, 0x61, 0x81, 0x91, 0x04, - /* (2^347)P */ 0x5f, 0x2a, 0xd7, 0x81, 0xd9, 0x9c, 0xbb, 0x79, 0xbc, 0x62, 0x56, 0x98, 0x03, 0x5a, 0x18, 0x85, 0x2a, 0x9c, 0xd0, 0xfb, 0xd2, 0xb1, 0xaf, 0xef, 0x0d, 0x24, 0xc5, 0xfa, 0x39, 0xbb, 0x6b, 0xed, 0xa4, 0xdf, 0xe4, 0x87, 0xcd, 0x41, 0xd3, 0x72, 0x32, 0xc6, 0x28, 0x21, 0xb1, 0xba, 0x8b, 0xa3, 0x91, 0x79, 0x76, 0x22, 0x25, 0x10, 0x61, 0xd1, - /* (2^348)P */ 0x73, 0xb5, 0x32, 0x97, 0xdd, 0xeb, 0xdd, 0x22, 0x22, 0xf1, 0x33, 0x3c, 0x77, 0x56, 0x7d, 0x6b, 0x48, 0x2b, 0x05, 0x81, 0x03, 0x03, 0x91, 0x9a, 0xe3, 0x5e, 0xd4, 0xee, 0x3f, 0xf8, 0xbb, 0x50, 0x21, 0x32, 0x4c, 0x4a, 0x58, 0x49, 0xde, 0x0c, 0xde, 0x30, 0x82, 0x3d, 0x92, 0xf0, 0x6c, 0xcc, 0x32, 0x3e, 0xd2, 0x78, 0x8a, 0x6e, 0x2c, 0xd0, - /* (2^349)P */ 0xf0, 0xf7, 0xa1, 0x0b, 0xc1, 0x74, 0x85, 0xa8, 0xe9, 0xdd, 0x48, 0xa1, 0xc0, 0x16, 0xd8, 0x2b, 0x61, 0x08, 0xc2, 0x2b, 0x30, 0x26, 0x79, 0xce, 0x9e, 0xfd, 0x39, 0xd7, 0x81, 0xa4, 0x63, 0x8c, 0xd5, 0x74, 0xa0, 0x88, 0xfa, 0x03, 0x30, 0xe9, 0x7f, 0x2b, 0xc6, 0x02, 0xc9, 0x5e, 0xe4, 0xd5, 0x4d, 0x92, 0xd0, 0xf6, 0xf2, 0x5b, 0x79, 0x08, - /* (2^350)P */ 0x34, 0x89, 0x81, 0x43, 0xd1, 0x94, 0x2c, 0x10, 0x54, 0x9b, 0xa0, 0xe5, 0x44, 0xe8, 0xc2, 0x2f, 0x3e, 0x0e, 0x74, 0xae, 0xba, 0xe2, 0xac, 0x85, 0x6b, 0xd3, 0x5c, 0x97, 0xf7, 0x90, 0xf1, 0x12, 0xc0, 0x03, 0xc8, 0x1f, 0x37, 0x72, 0x8c, 0x9b, 0x9c, 0x17, 0x96, 0x9d, 0xc7, 0xbf, 0xa3, 0x3f, 0x44, 0x3d, 0x87, 0x81, 0xbd, 0x81, 0xa6, 0x5f, - /* (2^351)P */ 0xe4, 0xff, 0x78, 0x62, 0x82, 0x5b, 0x76, 0x58, 0xf5, 0x5b, 0xa6, 0xc4, 0x53, 0x11, 0x3b, 0x7b, 0xaa, 0x67, 0xf8, 0xea, 0x3b, 0x5d, 0x9a, 0x2e, 0x04, 0xeb, 0x4a, 0x24, 0xfb, 0x56, 0xf0, 0xa8, 0xd4, 0x14, 0xed, 0x0f, 0xfd, 0xc5, 0x26, 0x17, 0x2a, 0xf0, 0xb9, 0x13, 0x8c, 0xbd, 0x65, 0x14, 0x24, 0x95, 0x27, 0x12, 0x63, 0x2a, 0x09, 0x18, - /* (2^352)P */ 0xe1, 0x5c, 0xe7, 0xe0, 0x00, 0x6a, 0x96, 0xf2, 0x49, 0x6a, 0x39, 0xa5, 0xe0, 0x17, 0x79, 0x4a, 0x63, 0x07, 0x62, 0x09, 0x61, 0x1b, 0x6e, 0xa9, 0xb5, 0x62, 0xb7, 0xde, 0xdf, 0x80, 0x4c, 0x5a, 0x99, 0x73, 0x59, 0x9d, 0xfb, 0xb1, 0x5e, 0xbe, 0xb8, 0xb7, 0x63, 0x93, 0xe8, 0xad, 0x5e, 0x1f, 0xae, 0x59, 0x1c, 0xcd, 0xb4, 0xc2, 0xb3, 0x8a, - /* (2^353)P */ 0x78, 0x53, 0xa1, 0x4c, 0x70, 0x9c, 0x63, 0x7e, 0xb3, 0x12, 0x40, 0x5f, 0xbb, 0x23, 0xa7, 0xf7, 0x77, 0x96, 0x5b, 0x4d, 0x91, 0x10, 0x52, 0x85, 0x9e, 0xa5, 0x38, 0x0b, 0xfd, 0x25, 0x01, 0x4b, 0xfa, 0x4d, 0xd3, 0x3f, 0x78, 0x74, 0x42, 0xff, 0x62, 0x2d, 0x27, 0xdc, 0x9d, 0xd1, 0x29, 0x76, 0x2e, 0x78, 0xb3, 0x35, 0xfa, 0x15, 0xd5, 0x38, - /* (2^354)P */ 0x8b, 0xc7, 0x43, 0xce, 0xf0, 0x5e, 0xf1, 0x0d, 0x02, 0x38, 0xe8, 0x82, 0xc9, 0x25, 0xad, 0x2d, 0x27, 0xa4, 0x54, 0x18, 0xb2, 0x30, 0x73, 0xa4, 0x41, 0x08, 0xe4, 0x86, 0xe6, 0x8c, 0xe9, 0x2a, 0x34, 0xb3, 0xd6, 0x61, 0x8f, 0x66, 0x26, 0x08, 0xb6, 0x06, 0x33, 0xaa, 0x12, 0xac, 0x72, 0xec, 0x2e, 0x52, 0xa3, 0x25, 0x3e, 0xd7, 0x62, 0xe8, - /* (2^355)P */ 0xc4, 0xbb, 0x89, 0xc8, 0x40, 0xcc, 0x84, 0xec, 0x4a, 0xd9, 0xc4, 0x55, 0x78, 0x00, 0xcf, 0xd8, 0xe9, 0x24, 0x59, 0xdc, 0x5e, 0xf0, 0x66, 0xa1, 0x83, 0xae, 0x97, 0x18, 0xc5, 0x54, 0x27, 0xa2, 0x21, 0x52, 0x03, 0x31, 0x5b, 0x11, 0x67, 0xf6, 0x12, 0x00, 0x87, 0x2f, 0xff, 0x59, 0x70, 0x8f, 0x6d, 0x71, 0xab, 0xab, 0x24, 0xb8, 0xba, 0x35, - /* (2^356)P */ 0x69, 0x43, 0xa7, 0x14, 0x06, 0x96, 0xe9, 0xc2, 0xe3, 0x2b, 0x45, 0x22, 0xc0, 0xd0, 0x2f, 0x34, 0xd1, 0x01, 0x99, 0xfc, 0x99, 0x38, 0xa1, 0x25, 0x2e, 0x59, 0x6c, 0x27, 0xc9, 0xeb, 0x7b, 0xdc, 0x4e, 0x26, 0x68, 0xba, 0xfa, 0xec, 0x02, 0x05, 0x64, 0x80, 0x30, 0x20, 0x5c, 0x26, 0x7f, 0xaf, 0x95, 0x17, 0x3d, 0x5c, 0x9e, 0x96, 0x96, 0xaf, - /* (2^357)P */ 0xa6, 0xba, 0x21, 0x29, 0x32, 0xe2, 0x98, 0xde, 0x9b, 0x6d, 0x0b, 0x44, 0x91, 0xa8, 0x3e, 0xd4, 0xb8, 0x04, 0x6c, 0xf6, 0x04, 0x39, 0xbd, 0x52, 0x05, 0x15, 0x27, 0x78, 0x8e, 0x55, 0xac, 0x79, 0xc5, 0xe6, 0x00, 0x7f, 0x90, 0xa2, 0xdd, 0x07, 0x13, 0xe0, 0x24, 0x70, 0x5c, 0x0f, 0x4d, 0xa9, 0xf9, 0xae, 0xcb, 0x34, 0x10, 0x9d, 0x89, 0x9d, - /* (2^358)P */ 0x12, 0xe0, 0xb3, 0x9f, 0xc4, 0x96, 0x1d, 0xcf, 0xed, 0x99, 0x64, 0x28, 0x8d, 0xc7, 0x31, 0x82, 0xee, 0x5e, 0x75, 0x48, 0xff, 0x3a, 0xf2, 0x09, 0x34, 0x03, 0x93, 0x52, 0x19, 0xb2, 0xc5, 0x81, 0x93, 0x45, 0x5e, 0x59, 0x21, 0x2b, 0xec, 0x89, 0xba, 0x36, 0x6e, 0xf9, 0x82, 0x75, 0x7e, 0x82, 0x3f, 0xaa, 0xe2, 0xe3, 0x3b, 0x94, 0xfd, 0x98, - /* (2^359)P */ 0x7c, 0xdb, 0x75, 0x31, 0x61, 0xfb, 0x15, 0x28, 0x94, 0xd7, 0xc3, 0x5a, 0xa9, 0xa1, 0x0a, 0x66, 0x0f, 0x2b, 0x13, 0x3e, 0x42, 0xb5, 0x28, 0x3a, 0xca, 0x83, 0xf3, 0x61, 0x22, 0xf4, 0x40, 0xc5, 0xdf, 0xe7, 0x31, 0x9f, 0x7e, 0x51, 0x75, 0x06, 0x9d, 0x51, 0xc8, 0xe7, 0x9f, 0xc3, 0x71, 0x4f, 0x3d, 0x5b, 0xfb, 0xe9, 0x8e, 0x08, 0x40, 0x8e, - /* (2^360)P */ 0xf7, 0x31, 0xad, 0x50, 0x5d, 0x25, 0x93, 0x73, 0x68, 0xf6, 0x7c, 0x89, 0x5a, 0x3d, 0x9f, 0x9b, 0x05, 0x82, 0xe7, 0x70, 0x4b, 0x19, 0xaa, 0xcf, 0xff, 0xde, 0x50, 0x8f, 0x2f, 0x69, 0xd3, 0xf0, 0x99, 0x51, 0x6b, 0x9d, 0xb6, 0x56, 0x6f, 0xf8, 0x4c, 0x74, 0x8b, 0x4c, 0x91, 0xf9, 0xa9, 0xb1, 0x3e, 0x07, 0xdf, 0x0b, 0x27, 0x8a, 0xb1, 0xed, - /* (2^361)P */ 0xfb, 0x67, 0xd9, 0x48, 0xd2, 0xe4, 0x44, 0x9b, 0x43, 0x15, 0x8a, 0xeb, 0x00, 0x53, 0xad, 0x25, 0xc7, 0x7e, 0x19, 0x30, 0x87, 0xb7, 0xd5, 0x5f, 0x04, 0xf8, 0xaa, 0xdd, 0x57, 0xae, 0x34, 0x75, 0xe2, 0x84, 0x4b, 0x54, 0x60, 0x37, 0x95, 0xe4, 0xd3, 0xec, 0xac, 0xef, 0x47, 0x31, 0xa3, 0xc8, 0x31, 0x22, 0xdb, 0x26, 0xe7, 0x6a, 0xb5, 0xad, - /* (2^362)P */ 0x44, 0x09, 0x5c, 0x95, 0xe4, 0x72, 0x3c, 0x1a, 0xd1, 0xac, 0x42, 0x51, 0x99, 0x6f, 0xfa, 0x1f, 0xf2, 0x22, 0xbe, 0xff, 0x7b, 0x66, 0xf5, 0x6c, 0xb3, 0x66, 0xc7, 0x4d, 0x78, 0x31, 0x83, 0x80, 0xf5, 0x41, 0xe9, 0x7f, 0xbe, 0xf7, 0x23, 0x49, 0x6b, 0x84, 0x4e, 0x7e, 0x47, 0x07, 0x6e, 0x74, 0xdf, 0xe5, 0x9d, 0x9e, 0x56, 0x2a, 0xc0, 0xbc, - /* (2^363)P */ 0xac, 0x10, 0x80, 0x8c, 0x7c, 0xfa, 0x83, 0xdf, 0xb3, 0xd0, 0xc4, 0xbe, 0xfb, 0x9f, 0xac, 0xc9, 0xc3, 0x40, 0x95, 0x0b, 0x09, 0x23, 0xda, 0x63, 0x67, 0xcf, 0xe7, 0x9f, 0x7d, 0x7b, 0x6b, 0xe2, 0xe6, 0x6d, 0xdb, 0x87, 0x9e, 0xa6, 0xff, 0x6d, 0xab, 0xbd, 0xfb, 0x54, 0x84, 0x68, 0xcf, 0x89, 0xf1, 0xd0, 0xe2, 0x85, 0x61, 0xdc, 0x22, 0xd1, - /* (2^364)P */ 0xa8, 0x48, 0xfb, 0x8c, 0x6a, 0x63, 0x01, 0x72, 0x43, 0x43, 0xeb, 0x21, 0xa3, 0x00, 0x8a, 0xc0, 0x87, 0x51, 0x9e, 0x86, 0x75, 0x16, 0x79, 0xf9, 0x6b, 0x11, 0x80, 0x62, 0xc2, 0x9d, 0xb8, 0x8c, 0x30, 0x8e, 0x8d, 0x03, 0x52, 0x7e, 0x31, 0x59, 0x38, 0xf9, 0x25, 0xc7, 0x0f, 0xc7, 0xa8, 0x2b, 0x5c, 0x80, 0xfa, 0x90, 0xa2, 0x63, 0xca, 0xe7, - /* (2^365)P */ 0xf1, 0x5d, 0xb5, 0xd9, 0x20, 0x10, 0x7d, 0x0f, 0xc5, 0x50, 0x46, 0x07, 0xff, 0x02, 0x75, 0x2b, 0x4a, 0xf3, 0x39, 0x91, 0x72, 0xb7, 0xd5, 0xcc, 0x38, 0xb8, 0xe7, 0x36, 0x26, 0x5e, 0x11, 0x97, 0x25, 0xfb, 0x49, 0x68, 0xdc, 0xb4, 0x46, 0x87, 0x5c, 0xc2, 0x7f, 0xaa, 0x7d, 0x36, 0x23, 0xa6, 0xc6, 0x53, 0xec, 0xbc, 0x57, 0x47, 0xc1, 0x2b, - /* (2^366)P */ 0x25, 0x5d, 0x7d, 0x95, 0xda, 0x0b, 0x8f, 0x78, 0x1e, 0x19, 0x09, 0xfa, 0x67, 0xe0, 0xa0, 0x17, 0x24, 0x76, 0x6c, 0x30, 0x1f, 0x62, 0x3d, 0xbe, 0x45, 0x70, 0xcc, 0xb6, 0x1e, 0x68, 0x06, 0x25, 0x68, 0x16, 0x1a, 0x33, 0x3f, 0x90, 0xc7, 0x78, 0x2d, 0x98, 0x3c, 0x2f, 0xb9, 0x2d, 0x94, 0x0b, 0xfb, 0x49, 0x56, 0x30, 0xd7, 0xc1, 0xe6, 0x48, - /* (2^367)P */ 0x7a, 0xd1, 0xe0, 0x8e, 0x67, 0xfc, 0x0b, 0x50, 0x1f, 0x84, 0x98, 0xfa, 0xaf, 0xae, 0x2e, 0x31, 0x27, 0xcf, 0x3f, 0xf2, 0x6e, 0x8d, 0x81, 0x8f, 0xd2, 0x5f, 0xde, 0xd3, 0x5e, 0xe9, 0xe7, 0x13, 0x48, 0x83, 0x5a, 0x4e, 0x84, 0xd1, 0x58, 0xcf, 0x6b, 0x84, 0xdf, 0x13, 0x1d, 0x91, 0x85, 0xe8, 0xcb, 0x29, 0x79, 0xd2, 0xca, 0xac, 0x6a, 0x93, - /* (2^368)P */ 0x53, 0x82, 0xce, 0x61, 0x96, 0x88, 0x6f, 0xe1, 0x4a, 0x4c, 0x1e, 0x30, 0x73, 0xe8, 0x74, 0xde, 0x40, 0x2b, 0xe0, 0xc4, 0xb5, 0xd8, 0x7c, 0x15, 0xe7, 0xe1, 0xb1, 0xe0, 0xd6, 0x88, 0xb1, 0x6a, 0x57, 0x19, 0x6a, 0x22, 0x66, 0x57, 0xf6, 0x8d, 0xfd, 0xc0, 0xf2, 0xa3, 0x03, 0x56, 0xfb, 0x2e, 0x75, 0x5e, 0xc7, 0x8e, 0x22, 0x96, 0x5c, 0x06, - /* (2^369)P */ 0x98, 0x7e, 0xbf, 0x3e, 0xbf, 0x24, 0x9d, 0x15, 0xd3, 0xf6, 0xd3, 0xd2, 0xf0, 0x11, 0xf2, 0xdb, 0x36, 0x23, 0x38, 0xf7, 0x1d, 0x71, 0x20, 0xd2, 0x54, 0x7f, 0x1e, 0x24, 0x8f, 0xe2, 0xaa, 0xf7, 0x3f, 0x6b, 0x41, 0x4e, 0xdc, 0x0e, 0xec, 0xe8, 0x35, 0x0a, 0x08, 0x6d, 0x89, 0x5b, 0x32, 0x91, 0x01, 0xb6, 0xe0, 0x2c, 0xc6, 0xa1, 0xbe, 0xb4, - /* (2^370)P */ 0x29, 0xf2, 0x1e, 0x1c, 0xdc, 0x68, 0x8a, 0x43, 0x87, 0x2c, 0x48, 0xb3, 0x9e, 0xed, 0xd2, 0x82, 0x46, 0xac, 0x2f, 0xef, 0x93, 0x34, 0x37, 0xca, 0x64, 0x8d, 0xc9, 0x06, 0x90, 0xbb, 0x78, 0x0a, 0x3c, 0x4c, 0xcf, 0x35, 0x7a, 0x0f, 0xf7, 0xa7, 0xf4, 0x2f, 0x45, 0x69, 0x3f, 0xa9, 0x5d, 0xce, 0x7b, 0x8a, 0x84, 0xc3, 0xae, 0xf4, 0xda, 0xd5, - /* (2^371)P */ 0xca, 0xba, 0x95, 0x43, 0x05, 0x7b, 0x06, 0xd9, 0x5c, 0x0a, 0x18, 0x5f, 0x6a, 0x6a, 0xce, 0xc0, 0x3d, 0x95, 0x51, 0x0e, 0x1a, 0xbe, 0x85, 0x7a, 0xf2, 0x69, 0xec, 0xc0, 0x8c, 0xca, 0xa3, 0x32, 0x0a, 0x76, 0x50, 0xc6, 0x76, 0x61, 0x00, 0x89, 0xbf, 0x6e, 0x0f, 0x48, 0x90, 0x31, 0x93, 0xec, 0x34, 0x70, 0xf0, 0xc3, 0x8d, 0xf0, 0x0f, 0xb5, - /* (2^372)P */ 0xbe, 0x23, 0xe2, 0x18, 0x99, 0xf1, 0xed, 0x8a, 0xf6, 0xc9, 0xac, 0xb8, 0x1e, 0x9a, 0x3c, 0x15, 0xae, 0xd7, 0x6d, 0xb3, 0x04, 0xee, 0x5b, 0x0d, 0x1e, 0x79, 0xb7, 0xf9, 0xf9, 0x8d, 0xad, 0xf9, 0x8f, 0x5a, 0x6a, 0x7b, 0xd7, 0x9b, 0xca, 0x62, 0xfe, 0x9c, 0xc0, 0x6f, 0x6d, 0x9d, 0x76, 0xa3, 0x69, 0xb9, 0x4c, 0xa1, 0xc4, 0x0c, 0x76, 0xaa, - /* (2^373)P */ 0x1c, 0x06, 0xfe, 0x3f, 0x45, 0x70, 0xcd, 0x97, 0xa9, 0xa2, 0xb1, 0xd3, 0xf2, 0xa5, 0x0c, 0x49, 0x2c, 0x75, 0x73, 0x1f, 0xcf, 0x00, 0xaf, 0xd5, 0x2e, 0xde, 0x0d, 0x8f, 0x8f, 0x7c, 0xc4, 0x58, 0xce, 0xd4, 0xf6, 0x24, 0x19, 0x2e, 0xd8, 0xc5, 0x1d, 0x1a, 0x3f, 0xb8, 0x4f, 0xbc, 0x7d, 0xbd, 0x68, 0xe3, 0x81, 0x98, 0x1b, 0xa8, 0xc9, 0xd9, - /* (2^374)P */ 0x39, 0x95, 0x78, 0x24, 0x6c, 0x38, 0xe4, 0xe7, 0xd0, 0x8d, 0xb9, 0x38, 0x71, 0x5e, 0xc1, 0x62, 0x80, 0xcc, 0xcb, 0x8c, 0x97, 0xca, 0xf8, 0xb9, 0xd9, 0x9c, 0xce, 0x72, 0x7b, 0x70, 0xee, 0x5f, 0xea, 0xa2, 0xdf, 0xa9, 0x14, 0x10, 0xf9, 0x6e, 0x59, 0x9f, 0x9c, 0xe0, 0x0c, 0xb2, 0x07, 0x97, 0xcd, 0xd2, 0x89, 0x16, 0xfd, 0x9c, 0xa8, 0xa5, - /* (2^375)P */ 0x5a, 0x61, 0xf1, 0x59, 0x7c, 0x38, 0xda, 0xe2, 0x85, 0x99, 0x68, 0xe9, 0xc9, 0xf7, 0x32, 0x7e, 0xc4, 0xca, 0xb7, 0x11, 0x08, 0x69, 0x2b, 0x66, 0x02, 0xf7, 0x2e, 0x18, 0xc3, 0x8e, 0xe1, 0xf9, 0xc5, 0x19, 0x9a, 0x0a, 0x9c, 0x07, 0xba, 0xc7, 0x9c, 0x03, 0x34, 0x89, 0x99, 0x67, 0x0b, 0x16, 0x4b, 0x07, 0x36, 0x16, 0x36, 0x2c, 0xe2, 0xa1, - /* (2^376)P */ 0x70, 0x10, 0x91, 0x27, 0xa8, 0x24, 0x8e, 0x29, 0x04, 0x6f, 0x79, 0x1f, 0xd3, 0xa5, 0x68, 0xd3, 0x0b, 0x7d, 0x56, 0x4d, 0x14, 0x57, 0x7b, 0x2e, 0x00, 0x9f, 0x9a, 0xfd, 0x6c, 0x63, 0x18, 0x81, 0xdb, 0x9d, 0xb7, 0xd7, 0xa4, 0x1e, 0xe8, 0x40, 0xf1, 0x4c, 0xa3, 0x01, 0xd5, 0x4b, 0x75, 0xea, 0xdd, 0x97, 0xfd, 0x5b, 0xb2, 0x66, 0x6a, 0x24, - /* (2^377)P */ 0x72, 0x11, 0xfe, 0x73, 0x1b, 0xd3, 0xea, 0x7f, 0x93, 0x15, 0x15, 0x05, 0xfe, 0x40, 0xe8, 0x28, 0xd8, 0x50, 0x47, 0x66, 0xfa, 0xb7, 0xb5, 0x04, 0xba, 0x35, 0x1e, 0x32, 0x9f, 0x5f, 0x32, 0xba, 0x3d, 0xd1, 0xed, 0x9a, 0x76, 0xca, 0xa3, 0x3e, 0x77, 0xd8, 0xd8, 0x7c, 0x5f, 0x68, 0x42, 0xb5, 0x86, 0x7f, 0x3b, 0xc9, 0xc1, 0x89, 0x64, 0xda, - /* (2^378)P */ 0xd5, 0xd4, 0x17, 0x31, 0xfc, 0x6a, 0xfd, 0xb8, 0xe8, 0xe5, 0x3e, 0x39, 0x06, 0xe4, 0xd1, 0x90, 0x2a, 0xca, 0xf6, 0x54, 0x6c, 0x1b, 0x2f, 0x49, 0x97, 0xb1, 0x2a, 0x82, 0x43, 0x3d, 0x1f, 0x8b, 0xe2, 0x47, 0xc5, 0x24, 0xa8, 0xd5, 0x53, 0x29, 0x7d, 0xc6, 0x87, 0xa6, 0x25, 0x3a, 0x64, 0xdd, 0x71, 0x08, 0x9e, 0xcd, 0xe9, 0x45, 0xc7, 0xba, - /* (2^379)P */ 0x37, 0x72, 0x6d, 0x13, 0x7a, 0x8d, 0x04, 0x31, 0xe6, 0xe3, 0x9e, 0x36, 0x71, 0x3e, 0xc0, 0x1e, 0xe3, 0x71, 0xd3, 0x49, 0x4e, 0x4a, 0x36, 0x42, 0x68, 0x68, 0x61, 0xc7, 0x3c, 0xdb, 0x81, 0x49, 0xf7, 0x91, 0x4d, 0xea, 0x4c, 0x4f, 0x98, 0xc6, 0x7e, 0x60, 0x84, 0x4b, 0x6a, 0x37, 0xbb, 0x52, 0xf7, 0xce, 0x02, 0xe4, 0xad, 0xd1, 0x3c, 0xa7, - /* (2^380)P */ 0x51, 0x06, 0x2d, 0xf8, 0x08, 0xe8, 0xf1, 0x0c, 0xe5, 0xa9, 0xac, 0x29, 0x73, 0x3b, 0xed, 0x98, 0x5f, 0x55, 0x08, 0x38, 0x51, 0x44, 0x36, 0x5d, 0xea, 0xc3, 0xb8, 0x0e, 0xa0, 0x4f, 0xd2, 0x79, 0xe9, 0x98, 0xc3, 0xf5, 0x00, 0xb9, 0x26, 0x27, 0x42, 0xa8, 0x07, 0xc1, 0x12, 0x31, 0xc1, 0xc3, 0x3c, 0x3b, 0x7a, 0x72, 0x97, 0xc2, 0x70, 0x3a, - /* (2^381)P */ 0xf4, 0xb2, 0xba, 0x32, 0xbc, 0xa9, 0x2f, 0x87, 0xc7, 0x3c, 0x45, 0xcd, 0xae, 0xe2, 0x13, 0x6d, 0x3a, 0xf2, 0xf5, 0x66, 0x97, 0x29, 0xaf, 0x53, 0x9f, 0xda, 0xea, 0x14, 0xdf, 0x04, 0x98, 0x19, 0x95, 0x9e, 0x2a, 0x00, 0x5c, 0x9d, 0x1d, 0xf0, 0x39, 0x23, 0xff, 0xfc, 0xca, 0x36, 0xb7, 0xde, 0xdf, 0x37, 0x78, 0x52, 0x21, 0xfa, 0x19, 0x10, - /* (2^382)P */ 0x50, 0x20, 0x73, 0x74, 0x62, 0x21, 0xf2, 0xf7, 0x9b, 0x66, 0x85, 0x34, 0x74, 0xd4, 0x9d, 0x60, 0xd7, 0xbc, 0xc8, 0x46, 0x3b, 0xb8, 0x80, 0x42, 0x15, 0x0a, 0x6c, 0x35, 0x1a, 0x69, 0xf0, 0x1d, 0x4b, 0x29, 0x54, 0x5a, 0x9a, 0x48, 0xec, 0x9f, 0x37, 0x74, 0x91, 0xd0, 0xd1, 0x9e, 0x00, 0xc2, 0x76, 0x56, 0xd6, 0xa0, 0x15, 0x14, 0x83, 0x59, - /* (2^383)P */ 0xc2, 0xf8, 0x22, 0x20, 0x23, 0x07, 0xbd, 0x1d, 0x6f, 0x1e, 0x8c, 0x56, 0x06, 0x6a, 0x4b, 0x9f, 0xe2, 0xa9, 0x92, 0x46, 0x4b, 0x46, 0x59, 0xd7, 0xe1, 0xda, 0x14, 0x98, 0x07, 0x65, 0x7e, 0x28, 0x20, 0xf2, 0x9d, 0x4f, 0x36, 0x5c, 0x92, 0xe0, 0x9d, 0xfe, 0x3e, 0xda, 0xe4, 0x47, 0x19, 0x3c, 0x00, 0x7f, 0x22, 0xf2, 0x9e, 0x51, 0xae, 0x4d, - /* (2^384)P */ 0xbe, 0x8c, 0x1b, 0x10, 0xb6, 0xad, 0xcc, 0xcc, 0xd8, 0x5e, 0x21, 0xa6, 0xfb, 0xf1, 0xf6, 0xbd, 0x0a, 0x24, 0x67, 0xb4, 0x57, 0x7a, 0xbc, 0xe8, 0xe9, 0xff, 0xee, 0x0a, 0x1f, 0xee, 0xbd, 0xc8, 0x44, 0xed, 0x2b, 0xbb, 0x55, 0x1f, 0xdd, 0x7c, 0xb3, 0xeb, 0x3f, 0x63, 0xa1, 0x28, 0x91, 0x21, 0xab, 0x71, 0xc6, 0x4c, 0xd0, 0xe9, 0xb0, 0x21, - /* (2^385)P */ 0xad, 0xc9, 0x77, 0x2b, 0xee, 0x89, 0xa4, 0x7b, 0xfd, 0xf9, 0xf6, 0x14, 0xe4, 0xed, 0x1a, 0x16, 0x9b, 0x78, 0x41, 0x43, 0xa8, 0x83, 0x72, 0x06, 0x2e, 0x7c, 0xdf, 0xeb, 0x7e, 0xdd, 0xd7, 0x8b, 0xea, 0x9a, 0x2b, 0x03, 0xba, 0x57, 0xf3, 0xf1, 0xd9, 0xe5, 0x09, 0xc5, 0x98, 0x61, 0x1c, 0x51, 0x6d, 0x5d, 0x6e, 0xfb, 0x5e, 0x95, 0x9f, 0xb5, - /* (2^386)P */ 0x23, 0xe2, 0x1e, 0x95, 0xa3, 0x5e, 0x42, 0x10, 0xc7, 0xc3, 0x70, 0xbf, 0x4b, 0x6b, 0x83, 0x36, 0x93, 0xb7, 0x68, 0x47, 0x88, 0x3a, 0x10, 0x88, 0x48, 0x7f, 0x8c, 0xae, 0x54, 0x10, 0x02, 0xa4, 0x52, 0x8f, 0x8d, 0xf7, 0x26, 0x4f, 0x50, 0xc3, 0x6a, 0xe2, 0x4e, 0x3b, 0x4c, 0xb9, 0x8a, 0x14, 0x15, 0x6d, 0x21, 0x29, 0xb3, 0x6e, 0x4e, 0xd0, - /* (2^387)P */ 0x4c, 0x8a, 0x18, 0x3f, 0xb7, 0x20, 0xfd, 0x3e, 0x54, 0xca, 0x68, 0x3c, 0xea, 0x6f, 0xf4, 0x6b, 0xa2, 0xbd, 0x01, 0xbd, 0xfe, 0x08, 0xa8, 0xd8, 0xc2, 0x20, 0x36, 0x05, 0xcd, 0xe9, 0xf3, 0x9e, 0xfa, 0x85, 0x66, 0x8f, 0x4b, 0x1d, 0x8c, 0x64, 0x4f, 0xb8, 0xc6, 0x0f, 0x5b, 0x57, 0xd8, 0x24, 0x19, 0x5a, 0x14, 0x4b, 0x92, 0xd3, 0x96, 0xbc, - /* (2^388)P */ 0xa9, 0x3f, 0xc9, 0x6c, 0xca, 0x64, 0x1e, 0x6f, 0xdf, 0x65, 0x7f, 0x9a, 0x47, 0x6b, 0x8a, 0x60, 0x31, 0xa6, 0x06, 0xac, 0x69, 0x30, 0xe6, 0xea, 0x63, 0x42, 0x26, 0x5f, 0xdb, 0xd0, 0xf2, 0x8e, 0x34, 0x0a, 0x3a, 0xeb, 0xf3, 0x79, 0xc8, 0xb7, 0x60, 0x56, 0x5c, 0x37, 0x95, 0x71, 0xf8, 0x7f, 0x49, 0x3e, 0x9e, 0x01, 0x26, 0x1e, 0x80, 0x9f, - /* (2^389)P */ 0xf8, 0x16, 0x9a, 0xaa, 0xb0, 0x28, 0xb5, 0x8e, 0xd0, 0x60, 0xe5, 0x26, 0xa9, 0x47, 0xc4, 0x5c, 0xa9, 0x39, 0xfe, 0x0a, 0xd8, 0x07, 0x2b, 0xb3, 0xce, 0xf1, 0xea, 0x1a, 0xf4, 0x7b, 0x98, 0x31, 0x3d, 0x13, 0x29, 0x80, 0xe8, 0x0d, 0xcf, 0x56, 0x39, 0x86, 0x50, 0x0c, 0xb3, 0x18, 0xf4, 0xc5, 0xca, 0xf2, 0x6f, 0xcd, 0x8d, 0xd5, 0x02, 0xb0, - /* (2^390)P */ 0xbf, 0x39, 0x3f, 0xac, 0x6d, 0x1a, 0x6a, 0xe4, 0x42, 0x24, 0xd6, 0x41, 0x9d, 0xb9, 0x5b, 0x46, 0x73, 0x93, 0x76, 0xaa, 0xb7, 0x37, 0x36, 0xa6, 0x09, 0xe5, 0x04, 0x3b, 0x66, 0xc4, 0x29, 0x3e, 0x41, 0xc2, 0xcb, 0xe5, 0x17, 0xd7, 0x34, 0x67, 0x1d, 0x2c, 0x12, 0xec, 0x24, 0x7a, 0x40, 0xa2, 0x45, 0x41, 0xf0, 0x75, 0xed, 0x43, 0x30, 0xc9, - /* (2^391)P */ 0x80, 0xf6, 0x47, 0x5b, 0xad, 0x54, 0x02, 0xbc, 0xdd, 0xa4, 0xb2, 0xd7, 0x42, 0x95, 0xf2, 0x0d, 0x1b, 0xef, 0x37, 0xa7, 0xb4, 0x34, 0x04, 0x08, 0x71, 0x1b, 0xd3, 0xdf, 0xa1, 0xf0, 0x2b, 0xfa, 0xc0, 0x1f, 0xf3, 0x44, 0xb5, 0xc6, 0x47, 0x3d, 0x65, 0x67, 0x45, 0x4d, 0x2f, 0xde, 0x52, 0x73, 0xfc, 0x30, 0x01, 0x6b, 0xc1, 0x03, 0xd8, 0xd7, - /* (2^392)P */ 0x1c, 0x67, 0x55, 0x3e, 0x01, 0x17, 0x0f, 0x3e, 0xe5, 0x34, 0x58, 0xfc, 0xcb, 0x71, 0x24, 0x74, 0x5d, 0x36, 0x1e, 0x89, 0x2a, 0x63, 0xf8, 0xf8, 0x9f, 0x50, 0x9f, 0x32, 0x92, 0x29, 0xd8, 0x1a, 0xec, 0x76, 0x57, 0x6c, 0x67, 0x12, 0x6a, 0x6e, 0xef, 0x97, 0x1f, 0xc3, 0x77, 0x60, 0x3c, 0x22, 0xcb, 0xc7, 0x04, 0x1a, 0x89, 0x2d, 0x10, 0xa6, - /* (2^393)P */ 0x12, 0xf5, 0xa9, 0x26, 0x16, 0xd9, 0x3c, 0x65, 0x5d, 0x83, 0xab, 0xd1, 0x70, 0x6b, 0x1c, 0xdb, 0xe7, 0x86, 0x0d, 0xfb, 0xe7, 0xf8, 0x2a, 0x58, 0x6e, 0x7a, 0x66, 0x13, 0x53, 0x3a, 0x6f, 0x8d, 0x43, 0x5f, 0x14, 0x23, 0x14, 0xff, 0x3d, 0x52, 0x7f, 0xee, 0xbd, 0x7a, 0x34, 0x8b, 0x35, 0x24, 0xc3, 0x7a, 0xdb, 0xcf, 0x22, 0x74, 0x9a, 0x8f, - /* (2^394)P */ 0xdb, 0x20, 0xfc, 0xe5, 0x39, 0x4e, 0x7d, 0x78, 0xee, 0x0b, 0xbf, 0x1d, 0x80, 0xd4, 0x05, 0x4f, 0xb9, 0xd7, 0x4e, 0x94, 0x88, 0x9a, 0x50, 0x78, 0x1a, 0x70, 0x8c, 0xcc, 0x25, 0xb6, 0x61, 0x09, 0xdc, 0x7b, 0xea, 0x3f, 0x7f, 0xea, 0x2a, 0x0d, 0x47, 0x1c, 0x8e, 0xa6, 0x5b, 0xd2, 0xa3, 0x61, 0x93, 0x3c, 0x68, 0x9f, 0x8b, 0xea, 0xb0, 0xcb, - /* (2^395)P */ 0xff, 0x54, 0x02, 0x19, 0xae, 0x8b, 0x4c, 0x2c, 0x3a, 0xe0, 0xe4, 0xac, 0x87, 0xf7, 0x51, 0x45, 0x41, 0x43, 0xdc, 0xaa, 0xcd, 0xcb, 0xdc, 0x40, 0xe3, 0x44, 0x3b, 0x1d, 0x9e, 0x3d, 0xb9, 0x82, 0xcc, 0x7a, 0xc5, 0x12, 0xf8, 0x1e, 0xdd, 0xdb, 0x8d, 0xb0, 0x2a, 0xe8, 0xe6, 0x6c, 0x94, 0x3b, 0xb7, 0x2d, 0xba, 0x79, 0x3b, 0xb5, 0x86, 0xfb, - /* (2^396)P */ 0x82, 0x88, 0x13, 0xdd, 0x6c, 0xcd, 0x85, 0x2b, 0x90, 0x86, 0xb7, 0xac, 0x16, 0xa6, 0x6e, 0x6a, 0x94, 0xd8, 0x1e, 0x4e, 0x41, 0x0f, 0xce, 0x81, 0x6a, 0xa8, 0x26, 0x56, 0x43, 0x52, 0x52, 0xe6, 0xff, 0x88, 0xcf, 0x47, 0x05, 0x1d, 0xff, 0xf3, 0xa0, 0x10, 0xb2, 0x97, 0x87, 0xeb, 0x47, 0xbb, 0xfa, 0x1f, 0xe8, 0x4c, 0xce, 0xc4, 0xcd, 0x93, - /* (2^397)P */ 0xf4, 0x11, 0xf5, 0x8d, 0x89, 0x29, 0x79, 0xb3, 0x59, 0x0b, 0x29, 0x7d, 0x9c, 0x12, 0x4a, 0x65, 0x72, 0x3a, 0xf9, 0xec, 0x37, 0x18, 0x86, 0xef, 0x44, 0x07, 0x25, 0x74, 0x76, 0x53, 0xed, 0x51, 0x01, 0xc6, 0x28, 0xc5, 0xc3, 0x4a, 0x0f, 0x99, 0xec, 0xc8, 0x40, 0x5a, 0x83, 0x30, 0x79, 0xa2, 0x3e, 0x63, 0x09, 0x2d, 0x6f, 0x23, 0x54, 0x1c, - /* (2^398)P */ 0x5c, 0x6f, 0x3b, 0x1c, 0x30, 0x77, 0x7e, 0x87, 0x66, 0x83, 0x2e, 0x7e, 0x85, 0x50, 0xfd, 0xa0, 0x7a, 0xc2, 0xf5, 0x0f, 0xc1, 0x64, 0xe7, 0x0b, 0xbd, 0x59, 0xa7, 0xe7, 0x65, 0x53, 0xc3, 0xf5, 0x55, 0x5b, 0xe1, 0x82, 0x30, 0x5a, 0x61, 0xcd, 0xa0, 0x89, 0x32, 0xdb, 0x87, 0xfc, 0x21, 0x8a, 0xab, 0x6d, 0x82, 0xa8, 0x42, 0x81, 0x4f, 0xf2, - /* (2^399)P */ 0xb3, 0xeb, 0x88, 0x18, 0xf6, 0x56, 0x96, 0xbf, 0xba, 0x5d, 0x71, 0xa1, 0x5a, 0xd1, 0x04, 0x7b, 0xd5, 0x46, 0x01, 0x74, 0xfe, 0x15, 0x25, 0xb7, 0xff, 0x0c, 0x24, 0x47, 0xac, 0xfd, 0xab, 0x47, 0x32, 0xe1, 0x6a, 0x4e, 0xca, 0xcf, 0x7f, 0xdd, 0xf8, 0xd2, 0x4b, 0x3b, 0xf5, 0x17, 0xba, 0xba, 0x8b, 0xa1, 0xec, 0x28, 0x3f, 0x97, 0xab, 0x2a, - /* (2^400)P */ 0x51, 0x38, 0xc9, 0x5e, 0xc6, 0xb3, 0x64, 0xf2, 0x24, 0x4d, 0x04, 0x7d, 0xc8, 0x39, 0x0c, 0x4a, 0xc9, 0x73, 0x74, 0x1b, 0x5c, 0xb2, 0xc5, 0x41, 0x62, 0xa0, 0x4c, 0x6d, 0x8d, 0x91, 0x9a, 0x7b, 0x88, 0xab, 0x9c, 0x7e, 0x23, 0xdb, 0x6f, 0xb5, 0x72, 0xd6, 0x47, 0x40, 0xef, 0x22, 0x58, 0x62, 0x19, 0x6c, 0x38, 0xba, 0x5b, 0x00, 0x30, 0x9f, - /* (2^401)P */ 0x65, 0xbb, 0x3b, 0x9b, 0xe9, 0xae, 0xbf, 0xbe, 0xe4, 0x13, 0x95, 0xf3, 0xe3, 0x77, 0xcb, 0xe4, 0x9a, 0x22, 0xb5, 0x4a, 0x08, 0x9d, 0xb3, 0x9e, 0x27, 0xe0, 0x15, 0x6c, 0x9f, 0x7e, 0x9a, 0x5e, 0x15, 0x45, 0x25, 0x8d, 0x01, 0x0a, 0xd2, 0x2b, 0xbd, 0x48, 0x06, 0x0d, 0x18, 0x97, 0x4b, 0xdc, 0xbc, 0xf0, 0xcd, 0xb2, 0x52, 0x3c, 0xac, 0xf5, - /* (2^402)P */ 0x3e, 0xed, 0x47, 0x6b, 0x5c, 0xf6, 0x76, 0xd0, 0xe9, 0x15, 0xa3, 0xcb, 0x36, 0x00, 0x21, 0xa3, 0x79, 0x20, 0xa5, 0x3e, 0x88, 0x03, 0xcb, 0x7e, 0x63, 0xbb, 0xed, 0xa9, 0x13, 0x35, 0x16, 0xaf, 0x2e, 0xb4, 0x70, 0x14, 0x93, 0xfb, 0xc4, 0x9b, 0xd8, 0xb1, 0xbe, 0x43, 0xd1, 0x85, 0xb8, 0x97, 0xef, 0xea, 0x88, 0xa1, 0x25, 0x52, 0x62, 0x75, - /* (2^403)P */ 0x8e, 0x4f, 0xaa, 0x23, 0x62, 0x7e, 0x2b, 0x37, 0x89, 0x00, 0x11, 0x30, 0xc5, 0x33, 0x4a, 0x89, 0x8a, 0xe2, 0xfc, 0x5c, 0x6a, 0x75, 0xe5, 0xf7, 0x02, 0x4a, 0x9b, 0xf7, 0xb5, 0x6a, 0x85, 0x31, 0xd3, 0x5a, 0xcf, 0xc3, 0xf8, 0xde, 0x2f, 0xcf, 0xb5, 0x24, 0xf4, 0xe3, 0xa1, 0xad, 0x42, 0xae, 0x09, 0xb9, 0x2e, 0x04, 0x2d, 0x01, 0x22, 0x3f, - /* (2^404)P */ 0x41, 0x16, 0xfb, 0x7d, 0x50, 0xfd, 0xb5, 0xba, 0x88, 0x24, 0xba, 0xfd, 0x3d, 0xb2, 0x90, 0x15, 0xb7, 0xfa, 0xa2, 0xe1, 0x4c, 0x7d, 0xb9, 0xc6, 0xff, 0x81, 0x57, 0xb6, 0xc2, 0x9e, 0xcb, 0xc4, 0x35, 0xbd, 0x01, 0xb7, 0xaa, 0xce, 0xd0, 0xe9, 0xb5, 0xd6, 0x72, 0xbf, 0xd2, 0xee, 0xc7, 0xac, 0x94, 0xff, 0x29, 0x57, 0x02, 0x49, 0x09, 0xad, - /* (2^405)P */ 0x27, 0xa5, 0x78, 0x1b, 0xbf, 0x6b, 0xaf, 0x0b, 0x8c, 0xd9, 0xa8, 0x37, 0xb0, 0x67, 0x18, 0xb6, 0xc7, 0x05, 0x8a, 0x67, 0x03, 0x30, 0x62, 0x6e, 0x56, 0x82, 0xa9, 0x54, 0x3e, 0x0c, 0x4e, 0x07, 0xe1, 0x5a, 0x38, 0xed, 0xfa, 0xc8, 0x55, 0x6b, 0x08, 0xa3, 0x6b, 0x64, 0x2a, 0x15, 0xd6, 0x39, 0x6f, 0x47, 0x99, 0x42, 0x3f, 0x33, 0x84, 0x8f, - /* (2^406)P */ 0xbc, 0x45, 0x29, 0x81, 0x0e, 0xa4, 0xc5, 0x72, 0x3a, 0x10, 0xe1, 0xc4, 0x1e, 0xda, 0xc3, 0xfe, 0xb0, 0xce, 0xd2, 0x13, 0x34, 0x67, 0x21, 0xc6, 0x7e, 0xf9, 0x8c, 0xff, 0x39, 0x50, 0xae, 0x92, 0x60, 0x35, 0x2f, 0x8b, 0x6e, 0xc9, 0xc1, 0x27, 0x3a, 0x94, 0x66, 0x3e, 0x26, 0x84, 0x93, 0xc8, 0x6c, 0xcf, 0xd2, 0x03, 0xa1, 0x10, 0xcf, 0xb7, - /* (2^407)P */ 0x64, 0xda, 0x19, 0xf6, 0xc5, 0x73, 0x17, 0x44, 0x88, 0x81, 0x07, 0x0d, 0x34, 0xb2, 0x75, 0xf9, 0xd9, 0xe2, 0xe0, 0x8b, 0x71, 0xcf, 0x72, 0x34, 0x83, 0xb4, 0xce, 0xfc, 0xd7, 0x29, 0x09, 0x5a, 0x98, 0xbf, 0x14, 0xac, 0x77, 0x55, 0x38, 0x47, 0x5b, 0x0f, 0x40, 0x24, 0xe5, 0xa5, 0xa6, 0xac, 0x2d, 0xa6, 0xff, 0x9c, 0x73, 0xfe, 0x5c, 0x7e, - /* (2^408)P */ 0x1e, 0x33, 0xcc, 0x68, 0xb2, 0xbc, 0x8c, 0x93, 0xaf, 0xcc, 0x38, 0xf8, 0xd9, 0x16, 0x72, 0x50, 0xac, 0xd9, 0xb5, 0x0b, 0x9a, 0xbe, 0x46, 0x7a, 0xf1, 0xee, 0xf1, 0xad, 0xec, 0x5b, 0x59, 0x27, 0x9c, 0x05, 0xa3, 0x87, 0xe0, 0x37, 0x2c, 0x83, 0xce, 0xb3, 0x65, 0x09, 0x8e, 0xc3, 0x9c, 0xbf, 0x6a, 0xa2, 0x00, 0xcc, 0x12, 0x36, 0xc5, 0x95, - /* (2^409)P */ 0x36, 0x11, 0x02, 0x14, 0x9c, 0x3c, 0xeb, 0x2f, 0x23, 0x5b, 0x6b, 0x2b, 0x08, 0x54, 0x53, 0xac, 0xb2, 0xa3, 0xe0, 0x26, 0x62, 0x3c, 0xe4, 0xe1, 0x81, 0xee, 0x13, 0x3e, 0xa4, 0x97, 0xef, 0xf9, 0x92, 0x27, 0x01, 0xce, 0x54, 0x8b, 0x3e, 0x31, 0xbe, 0xa7, 0x88, 0xcf, 0x47, 0x99, 0x3c, 0x10, 0x6f, 0x60, 0xb3, 0x06, 0x4e, 0xee, 0x1b, 0xf0, - /* (2^410)P */ 0x59, 0x49, 0x66, 0xcf, 0x22, 0xe6, 0xf6, 0x73, 0xfe, 0xa3, 0x1c, 0x09, 0xfa, 0x5f, 0x65, 0xa8, 0xf0, 0x82, 0xc2, 0xef, 0x16, 0x63, 0x6e, 0x79, 0x69, 0x51, 0x39, 0x07, 0x65, 0xc4, 0x81, 0xec, 0x73, 0x0f, 0x15, 0x93, 0xe1, 0x30, 0x33, 0xe9, 0x37, 0x86, 0x42, 0x4c, 0x1f, 0x9b, 0xad, 0xee, 0x3f, 0xf1, 0x2a, 0x8e, 0x6a, 0xa3, 0xc8, 0x35, - /* (2^411)P */ 0x1e, 0x49, 0xf1, 0xdd, 0xd2, 0x9c, 0x8e, 0x78, 0xb2, 0x06, 0xe4, 0x6a, 0xab, 0x3a, 0xdc, 0xcd, 0xf4, 0xeb, 0xe1, 0xe7, 0x2f, 0xaa, 0xeb, 0x40, 0x31, 0x9f, 0xb9, 0xab, 0x13, 0xa9, 0x78, 0xbf, 0x38, 0x89, 0x0e, 0x85, 0x14, 0x8b, 0x46, 0x76, 0x14, 0xda, 0xcf, 0x33, 0xc8, 0x79, 0xd3, 0xd5, 0xa3, 0x6a, 0x69, 0x45, 0x70, 0x34, 0xc3, 0xe9, - /* (2^412)P */ 0x5e, 0xe7, 0x78, 0xe9, 0x24, 0xcc, 0xe9, 0xf4, 0xc8, 0x6b, 0xe0, 0xfb, 0x3a, 0xbe, 0xcc, 0x42, 0x4a, 0x00, 0x22, 0xf8, 0xe6, 0x32, 0xbe, 0x6d, 0x18, 0x55, 0x60, 0xe9, 0x72, 0x69, 0x50, 0x56, 0xca, 0x04, 0x18, 0x38, 0xa1, 0xee, 0xd8, 0x38, 0x3c, 0xa7, 0x70, 0xe2, 0xb9, 0x4c, 0xa0, 0xc8, 0x89, 0x72, 0xcf, 0x49, 0x7f, 0xdf, 0xbc, 0x67, - /* (2^413)P */ 0x1d, 0x17, 0xcb, 0x0b, 0xbd, 0xb2, 0x36, 0xe3, 0xa8, 0x99, 0x31, 0xb6, 0x26, 0x9c, 0x0c, 0x74, 0xaf, 0x4d, 0x24, 0x61, 0xcf, 0x31, 0x7b, 0xed, 0xdd, 0xc3, 0xf6, 0x32, 0x70, 0xfe, 0x17, 0xf6, 0x51, 0x37, 0x65, 0xce, 0x5d, 0xaf, 0xa5, 0x2f, 0x2a, 0xfe, 0x00, 0x71, 0x7c, 0x50, 0xbe, 0x21, 0xc7, 0xed, 0xc6, 0xfc, 0x67, 0xcf, 0x9c, 0xdd, - /* (2^414)P */ 0x26, 0x3e, 0xf8, 0xbb, 0xd0, 0xb1, 0x01, 0xd8, 0xeb, 0x0b, 0x62, 0x87, 0x35, 0x4c, 0xde, 0xca, 0x99, 0x9c, 0x6d, 0xf7, 0xb6, 0xf0, 0x57, 0x0a, 0x52, 0x29, 0x6a, 0x3f, 0x26, 0x31, 0x04, 0x07, 0x2a, 0xc9, 0xfa, 0x9b, 0x0e, 0x62, 0x8e, 0x72, 0xf2, 0xad, 0xce, 0xb6, 0x35, 0x7a, 0xc1, 0xae, 0x35, 0xc7, 0xa3, 0x14, 0xcf, 0x0c, 0x28, 0xb7, - /* (2^415)P */ 0xa6, 0xf1, 0x32, 0x3a, 0x20, 0xd2, 0x24, 0x97, 0xcf, 0x5d, 0x37, 0x99, 0xaf, 0x33, 0x7a, 0x5b, 0x7a, 0xcc, 0x4e, 0x41, 0x38, 0xb1, 0x4e, 0xad, 0xc9, 0xd9, 0x71, 0x7e, 0xb2, 0xf5, 0xd5, 0x01, 0x6c, 0x4d, 0xfd, 0xa1, 0xda, 0x03, 0x38, 0x9b, 0x3d, 0x92, 0x92, 0xf2, 0xca, 0xbf, 0x1f, 0x24, 0xa4, 0xbb, 0x30, 0x6a, 0x74, 0x56, 0xc8, 0xce, - /* (2^416)P */ 0x27, 0xf4, 0xed, 0xc9, 0xc3, 0xb1, 0x79, 0x85, 0xbe, 0xf6, 0xeb, 0xf3, 0x55, 0xc7, 0xaa, 0xa6, 0xe9, 0x07, 0x5d, 0xf4, 0xeb, 0xa6, 0x81, 0xe3, 0x0e, 0xcf, 0xa3, 0xc1, 0xef, 0xe7, 0x34, 0xb2, 0x03, 0x73, 0x8a, 0x91, 0xf1, 0xad, 0x05, 0xc7, 0x0b, 0x43, 0x99, 0x12, 0x31, 0xc8, 0xc7, 0xc5, 0xa4, 0x3d, 0xcd, 0xe5, 0x4e, 0x6d, 0x24, 0xdd, - /* (2^417)P */ 0x61, 0x54, 0xd0, 0x95, 0x2c, 0x45, 0x75, 0xac, 0xb5, 0x1a, 0x9d, 0x11, 0xeb, 0xed, 0x6b, 0x57, 0xa3, 0xe6, 0xcd, 0x77, 0xd4, 0x83, 0x8e, 0x39, 0xf1, 0x0f, 0x98, 0xcb, 0x40, 0x02, 0x6e, 0x10, 0x82, 0x9e, 0xb4, 0x93, 0x76, 0xd7, 0x97, 0xa3, 0x53, 0x12, 0x86, 0xc6, 0x15, 0x78, 0x73, 0x93, 0xe7, 0x7f, 0xcf, 0x1f, 0xbf, 0xcd, 0xd2, 0x7a, - /* (2^418)P */ 0xc2, 0x21, 0xdc, 0xd5, 0x69, 0xff, 0xca, 0x49, 0x3a, 0xe1, 0xc3, 0x69, 0x41, 0x56, 0xc1, 0x76, 0x63, 0x24, 0xbd, 0x64, 0x1b, 0x3d, 0x92, 0xf9, 0x13, 0x04, 0x25, 0xeb, 0x27, 0xa6, 0xef, 0x39, 0x3a, 0x80, 0xe0, 0xf8, 0x27, 0xee, 0xc9, 0x49, 0x77, 0xef, 0x3f, 0x29, 0x3d, 0x5e, 0xe6, 0x66, 0x83, 0xd1, 0xf6, 0xfe, 0x9d, 0xbc, 0xf1, 0x96, - /* (2^419)P */ 0x6b, 0xc6, 0x99, 0x26, 0x3c, 0xf3, 0x63, 0xf9, 0xc7, 0x29, 0x8c, 0x52, 0x62, 0x2d, 0xdc, 0x8a, 0x66, 0xce, 0x2c, 0xa7, 0xe4, 0xf0, 0xd7, 0x37, 0x17, 0x1e, 0xe4, 0xa3, 0x53, 0x7b, 0x29, 0x8e, 0x60, 0x99, 0xf9, 0x0c, 0x7c, 0x6f, 0xa2, 0xcc, 0x9f, 0x80, 0xdd, 0x5e, 0x46, 0xaa, 0x0d, 0x6c, 0xc9, 0x6c, 0xf7, 0x78, 0x5b, 0x38, 0xe3, 0x24, - /* (2^420)P */ 0x4b, 0x75, 0x6a, 0x2f, 0x08, 0xe1, 0x72, 0x76, 0xab, 0x82, 0x96, 0xdf, 0x3b, 0x1f, 0x9b, 0xd8, 0xed, 0xdb, 0xcd, 0x15, 0x09, 0x5a, 0x1e, 0xb7, 0xc5, 0x26, 0x72, 0x07, 0x0c, 0x50, 0xcd, 0x3b, 0x4d, 0x3f, 0xa2, 0x67, 0xc2, 0x02, 0x61, 0x2e, 0x68, 0xe9, 0x6f, 0xf0, 0x21, 0x2a, 0xa7, 0x3b, 0x88, 0x04, 0x11, 0x64, 0x49, 0x0d, 0xb4, 0x46, - /* (2^421)P */ 0x63, 0x85, 0xf3, 0xc5, 0x2b, 0x5a, 0x9f, 0xf0, 0x17, 0xcb, 0x45, 0x0a, 0xf3, 0x6e, 0x7e, 0xb0, 0x7c, 0xbc, 0xf0, 0x4f, 0x3a, 0xb0, 0xbc, 0x36, 0x36, 0x52, 0x51, 0xcb, 0xfe, 0x9a, 0xcb, 0xe8, 0x7e, 0x4b, 0x06, 0x7f, 0xaa, 0x35, 0xc8, 0x0e, 0x7a, 0x30, 0xa3, 0xb1, 0x09, 0xbb, 0x86, 0x4c, 0xbe, 0xb8, 0xbd, 0xe0, 0x32, 0xa5, 0xd4, 0xf7, - /* (2^422)P */ 0x7d, 0x50, 0x37, 0x68, 0x4e, 0x22, 0xb2, 0x2c, 0xd5, 0x0f, 0x2b, 0x6d, 0xb1, 0x51, 0xf2, 0x82, 0xe9, 0x98, 0x7c, 0x50, 0xc7, 0x96, 0x7e, 0x0e, 0xdc, 0xb1, 0x0e, 0xb2, 0x63, 0x8c, 0x30, 0x37, 0x72, 0x21, 0x9c, 0x61, 0xc2, 0xa7, 0x33, 0xd9, 0xb2, 0x63, 0x93, 0xd1, 0x6b, 0x6a, 0x73, 0xa5, 0x58, 0x80, 0xff, 0x04, 0xc7, 0x83, 0x21, 0x29, - /* (2^423)P */ 0x29, 0x04, 0xbc, 0x99, 0x39, 0xc9, 0x58, 0xc9, 0x6b, 0x17, 0xe8, 0x90, 0xb3, 0xe6, 0xa9, 0xb6, 0x28, 0x9b, 0xcb, 0x3b, 0x28, 0x90, 0x68, 0x71, 0xff, 0xcf, 0x08, 0x78, 0xc9, 0x8d, 0xa8, 0x4e, 0x43, 0xd1, 0x1c, 0x9e, 0xa4, 0xe3, 0xdf, 0xbf, 0x92, 0xf4, 0xf9, 0x41, 0xba, 0x4d, 0x1c, 0xf9, 0xdd, 0x74, 0x76, 0x1c, 0x6e, 0x3e, 0x94, 0x87, - /* (2^424)P */ 0xe4, 0xda, 0xc5, 0xd7, 0xfb, 0x87, 0xc5, 0x4d, 0x6b, 0x19, 0xaa, 0xb9, 0xbc, 0x8c, 0xf2, 0x8a, 0xd8, 0x5d, 0xdb, 0x4d, 0xef, 0xa6, 0xf2, 0x65, 0xf1, 0x22, 0x9c, 0xf1, 0x46, 0x30, 0x71, 0x7c, 0xe4, 0x53, 0x8e, 0x55, 0x2e, 0x9c, 0x9a, 0x31, 0x2a, 0xc3, 0xab, 0x0f, 0xde, 0xe4, 0xbe, 0xd8, 0x96, 0x50, 0x6e, 0x0c, 0x54, 0x49, 0xe6, 0xec, - /* (2^425)P */ 0x3c, 0x1d, 0x5a, 0xa5, 0xda, 0xad, 0xdd, 0xc2, 0xae, 0xac, 0x6f, 0x86, 0x75, 0x31, 0x91, 0x64, 0x45, 0x9d, 0xa4, 0xf0, 0x81, 0xf1, 0x0e, 0xba, 0x74, 0xaf, 0x7b, 0xcd, 0x6f, 0xfe, 0xac, 0x4e, 0xdb, 0x4e, 0x45, 0x35, 0x36, 0xc5, 0xc0, 0x6c, 0x3d, 0x64, 0xf4, 0xd8, 0x07, 0x62, 0xd1, 0xec, 0xf3, 0xfc, 0x93, 0xc9, 0x28, 0x0c, 0x2c, 0xf3, - /* (2^426)P */ 0x0c, 0x69, 0x2b, 0x5c, 0xb6, 0x41, 0x69, 0xf1, 0xa4, 0xf1, 0x5b, 0x75, 0x4c, 0x42, 0x8b, 0x47, 0xeb, 0x69, 0xfb, 0xa8, 0xe6, 0xf9, 0x7b, 0x48, 0x50, 0xaf, 0xd3, 0xda, 0xb2, 0x35, 0x10, 0xb5, 0x5b, 0x40, 0x90, 0x39, 0xc9, 0x07, 0x06, 0x73, 0x26, 0x20, 0x95, 0x01, 0xa4, 0x2d, 0xf0, 0xe7, 0x2e, 0x00, 0x7d, 0x41, 0x09, 0x68, 0x13, 0xc4, - /* (2^427)P */ 0xbe, 0x38, 0x78, 0xcf, 0xc9, 0x4f, 0x36, 0xca, 0x09, 0x61, 0x31, 0x3c, 0x57, 0x2e, 0xec, 0x17, 0xa4, 0x7d, 0x19, 0x2b, 0x9b, 0x5b, 0xbe, 0x8f, 0xd6, 0xc5, 0x2f, 0x86, 0xf2, 0x64, 0x76, 0x17, 0x00, 0x6e, 0x1a, 0x8c, 0x67, 0x1b, 0x68, 0xeb, 0x15, 0xa2, 0xd6, 0x09, 0x91, 0xdd, 0x23, 0x0d, 0x98, 0xb2, 0x10, 0x19, 0x55, 0x9b, 0x63, 0xf2, - /* (2^428)P */ 0x51, 0x1f, 0x93, 0xea, 0x2a, 0x3a, 0xfa, 0x41, 0xc0, 0x57, 0xfb, 0x74, 0xa6, 0x65, 0x09, 0x56, 0x14, 0xb6, 0x12, 0xaa, 0xb3, 0x1a, 0x8d, 0x3b, 0x76, 0x91, 0x7a, 0x23, 0x56, 0x9c, 0x6a, 0xc0, 0xe0, 0x3c, 0x3f, 0xb5, 0x1a, 0xf4, 0x57, 0x71, 0x93, 0x2b, 0xb1, 0xa7, 0x70, 0x57, 0x22, 0x80, 0xf5, 0xb8, 0x07, 0x77, 0x87, 0x0c, 0xbe, 0x83, - /* (2^429)P */ 0x07, 0x9b, 0x0e, 0x52, 0x38, 0x63, 0x13, 0x86, 0x6a, 0xa6, 0xb4, 0xd2, 0x60, 0x68, 0x9a, 0x99, 0x82, 0x0a, 0x04, 0x5f, 0x89, 0x7a, 0x1a, 0x2a, 0xae, 0x2d, 0x35, 0x0c, 0x1e, 0xad, 0xef, 0x4f, 0x9a, 0xfc, 0xc8, 0xd9, 0xcf, 0x9d, 0x48, 0x71, 0xa5, 0x55, 0x79, 0x73, 0x39, 0x1b, 0xd8, 0x73, 0xec, 0x9b, 0x03, 0x16, 0xd8, 0x82, 0xf7, 0x67, - /* (2^430)P */ 0x52, 0x67, 0x42, 0x21, 0xc9, 0x40, 0x78, 0x82, 0x2b, 0x95, 0x2d, 0x20, 0x92, 0xd1, 0xe2, 0x61, 0x25, 0xb0, 0xc6, 0x9c, 0x20, 0x59, 0x8e, 0x28, 0x6f, 0xf3, 0xfd, 0xd3, 0xc1, 0x32, 0x43, 0xc9, 0xa6, 0x08, 0x7a, 0x77, 0x9c, 0x4c, 0x8c, 0x33, 0x71, 0x13, 0x69, 0xe3, 0x52, 0x30, 0xa7, 0xf5, 0x07, 0x67, 0xac, 0xad, 0x46, 0x8a, 0x26, 0x25, - /* (2^431)P */ 0xda, 0x86, 0xc4, 0xa2, 0x71, 0x56, 0xdd, 0xd2, 0x48, 0xd3, 0xde, 0x42, 0x63, 0x01, 0xa7, 0x2c, 0x92, 0x83, 0x6f, 0x2e, 0xd8, 0x1e, 0x3f, 0xc1, 0xc5, 0x42, 0x4e, 0x34, 0x19, 0x54, 0x6e, 0x35, 0x2c, 0x51, 0x2e, 0xfd, 0x0f, 0x9a, 0x45, 0x66, 0x5e, 0x4a, 0x83, 0xda, 0x0a, 0x53, 0x68, 0x63, 0xfa, 0xce, 0x47, 0x20, 0xd3, 0x34, 0xba, 0x0d, - /* (2^432)P */ 0xd0, 0xe9, 0x64, 0xa4, 0x61, 0x4b, 0x86, 0xe5, 0x93, 0x6f, 0xda, 0x0e, 0x31, 0x7e, 0x6e, 0xe3, 0xc6, 0x73, 0xd8, 0xa3, 0x08, 0x57, 0x52, 0xcd, 0x51, 0x63, 0x1d, 0x9f, 0x93, 0x00, 0x62, 0x91, 0x26, 0x21, 0xa7, 0xdd, 0x25, 0x0f, 0x09, 0x0d, 0x35, 0xad, 0xcf, 0x11, 0x8e, 0x6e, 0xe8, 0xae, 0x1d, 0x95, 0xcb, 0x88, 0xf8, 0x70, 0x7b, 0x91, - /* (2^433)P */ 0x0c, 0x19, 0x5c, 0xd9, 0x8d, 0xda, 0x9d, 0x2c, 0x90, 0x54, 0x65, 0xe8, 0xb6, 0x35, 0x50, 0xae, 0xea, 0xae, 0x43, 0xb7, 0x1e, 0x99, 0x8b, 0x4c, 0x36, 0x4e, 0xe4, 0x1e, 0xc4, 0x64, 0x43, 0xb6, 0xeb, 0xd4, 0xe9, 0x60, 0x22, 0xee, 0xcf, 0xb8, 0x52, 0x1b, 0xf0, 0x04, 0xce, 0xbc, 0x2b, 0xf0, 0xbe, 0xcd, 0x44, 0x74, 0x1e, 0x1f, 0x63, 0xf9, - /* (2^434)P */ 0xe1, 0x3f, 0x95, 0x94, 0xb2, 0xb6, 0x31, 0xa9, 0x1b, 0xdb, 0xfd, 0x0e, 0xdb, 0xdd, 0x1a, 0x22, 0x78, 0x60, 0x9f, 0x75, 0x5f, 0x93, 0x06, 0x0c, 0xd8, 0xbb, 0xa2, 0x85, 0x2b, 0x5e, 0xc0, 0x9b, 0xa8, 0x5d, 0xaf, 0x93, 0x91, 0x91, 0x47, 0x41, 0x1a, 0xfc, 0xb4, 0x51, 0x85, 0xad, 0x69, 0x4d, 0x73, 0x69, 0xd5, 0x4e, 0x82, 0xfb, 0x66, 0xcb, - /* (2^435)P */ 0x7c, 0xbe, 0xc7, 0x51, 0xc4, 0x74, 0x6e, 0xab, 0xfd, 0x41, 0x4f, 0x76, 0x4f, 0x24, 0x03, 0xd6, 0x2a, 0xb7, 0x42, 0xb4, 0xda, 0x41, 0x2c, 0x82, 0x48, 0x4c, 0x7f, 0x6f, 0x25, 0x5d, 0x36, 0xd4, 0x69, 0xf5, 0xef, 0x02, 0x81, 0xea, 0x6f, 0x19, 0x69, 0xe8, 0x6f, 0x5b, 0x2f, 0x14, 0x0e, 0x6f, 0x89, 0xb4, 0xb5, 0xd8, 0xae, 0xef, 0x7b, 0x87, - /* (2^436)P */ 0xe9, 0x91, 0xa0, 0x8b, 0xc9, 0xe0, 0x01, 0x90, 0x37, 0xc1, 0x6f, 0xdc, 0x5e, 0xf7, 0xbf, 0x43, 0x00, 0xaa, 0x10, 0x76, 0x76, 0x18, 0x6e, 0x19, 0x1e, 0x94, 0x50, 0x11, 0x0a, 0xd1, 0xe2, 0xdb, 0x08, 0x21, 0xa0, 0x1f, 0xdb, 0x54, 0xfe, 0xea, 0x6e, 0xa3, 0x68, 0x56, 0x87, 0x0b, 0x22, 0x4e, 0x66, 0xf3, 0x82, 0x82, 0x00, 0xcd, 0xd4, 0x12, - /* (2^437)P */ 0x25, 0x8e, 0x24, 0x77, 0x64, 0x4c, 0xe0, 0xf8, 0x18, 0xc0, 0xdc, 0xc7, 0x1b, 0x35, 0x65, 0xde, 0x67, 0x41, 0x5e, 0x6f, 0x90, 0x82, 0xa7, 0x2e, 0x6d, 0xf1, 0x47, 0xb4, 0x92, 0x9c, 0xfd, 0x6a, 0x9a, 0x41, 0x36, 0x20, 0x24, 0x58, 0xc3, 0x59, 0x07, 0x9a, 0xfa, 0x9f, 0x03, 0xcb, 0xc7, 0x69, 0x37, 0x60, 0xe1, 0xab, 0x13, 0x72, 0xee, 0xa2, - /* (2^438)P */ 0x74, 0x78, 0xfb, 0x13, 0xcb, 0x8e, 0x37, 0x1a, 0xf6, 0x1d, 0x17, 0x83, 0x06, 0xd4, 0x27, 0x06, 0x21, 0xe8, 0xda, 0xdf, 0x6b, 0xf3, 0x83, 0x6b, 0x34, 0x8a, 0x8c, 0xee, 0x01, 0x05, 0x5b, 0xed, 0xd3, 0x1b, 0xc9, 0x64, 0x83, 0xc9, 0x49, 0xc2, 0x57, 0x1b, 0xdd, 0xcf, 0xf1, 0x9d, 0x63, 0xee, 0x1c, 0x0d, 0xa0, 0x0a, 0x73, 0x1f, 0x5b, 0x32, - /* (2^439)P */ 0x29, 0xce, 0x1e, 0xc0, 0x6a, 0xf5, 0xeb, 0x99, 0x5a, 0x39, 0x23, 0xe9, 0xdd, 0xac, 0x44, 0x88, 0xbc, 0x80, 0x22, 0xde, 0x2c, 0xcb, 0xa8, 0x3b, 0xff, 0xf7, 0x6f, 0xc7, 0x71, 0x72, 0xa8, 0xa3, 0xf6, 0x4d, 0xc6, 0x75, 0xda, 0x80, 0xdc, 0xd9, 0x30, 0xd9, 0x07, 0x50, 0x5a, 0x54, 0x7d, 0xda, 0x39, 0x6f, 0x78, 0x94, 0xbf, 0x25, 0x98, 0xdc, - /* (2^440)P */ 0x01, 0x26, 0x62, 0x44, 0xfb, 0x0f, 0x11, 0x72, 0x73, 0x0a, 0x16, 0xc7, 0x16, 0x9c, 0x9b, 0x37, 0xd8, 0xff, 0x4f, 0xfe, 0x57, 0xdb, 0xae, 0xef, 0x7d, 0x94, 0x30, 0x04, 0x70, 0x83, 0xde, 0x3c, 0xd4, 0xb5, 0x70, 0xda, 0xa7, 0x55, 0xc8, 0x19, 0xe1, 0x36, 0x15, 0x61, 0xe7, 0x3b, 0x7d, 0x85, 0xbb, 0xf3, 0x42, 0x5a, 0x94, 0xf4, 0x53, 0x2a, - /* (2^441)P */ 0x14, 0x60, 0xa6, 0x0b, 0x83, 0xe1, 0x23, 0x77, 0xc0, 0xce, 0x50, 0xed, 0x35, 0x8d, 0x98, 0x99, 0x7d, 0xf5, 0x8d, 0xce, 0x94, 0x25, 0xc8, 0x0f, 0x6d, 0xfa, 0x4a, 0xa4, 0x3a, 0x1f, 0x66, 0xfb, 0x5a, 0x64, 0xaf, 0x8b, 0x54, 0x54, 0x44, 0x3f, 0x5b, 0x88, 0x61, 0xe4, 0x48, 0x45, 0x26, 0x20, 0xbe, 0x0d, 0x06, 0xbb, 0x65, 0x59, 0xe1, 0x36, - /* (2^442)P */ 0xb7, 0x98, 0xce, 0xa3, 0xe3, 0xee, 0x11, 0x1b, 0x9e, 0x24, 0x59, 0x75, 0x31, 0x37, 0x44, 0x6f, 0x6b, 0x9e, 0xec, 0xb7, 0x44, 0x01, 0x7e, 0xab, 0xbb, 0x69, 0x5d, 0x11, 0xb0, 0x30, 0x64, 0xea, 0x91, 0xb4, 0x7a, 0x8c, 0x02, 0x4c, 0xb9, 0x10, 0xa7, 0xc7, 0x79, 0xe6, 0xdc, 0x77, 0xe3, 0xc8, 0xef, 0x3e, 0xf9, 0x38, 0x81, 0xce, 0x9a, 0xb2, - /* (2^443)P */ 0x91, 0x12, 0x76, 0xd0, 0x10, 0xb4, 0xaf, 0xe1, 0x89, 0x3a, 0x93, 0x6b, 0x5c, 0x19, 0x5f, 0x24, 0xed, 0x04, 0x92, 0xc7, 0xf0, 0x00, 0x08, 0xc1, 0x92, 0xff, 0x90, 0xdb, 0xb2, 0xbf, 0xdf, 0x49, 0xcd, 0xbd, 0x5c, 0x6e, 0xbf, 0x16, 0xbb, 0x61, 0xf9, 0x20, 0x33, 0x35, 0x93, 0x11, 0xbc, 0x59, 0x69, 0xce, 0x18, 0x9f, 0xf8, 0x7b, 0xa1, 0x6e, - /* (2^444)P */ 0xa1, 0xf4, 0xaf, 0xad, 0xf8, 0xe6, 0x99, 0xd2, 0xa1, 0x4d, 0xde, 0x56, 0xc9, 0x7b, 0x0b, 0x11, 0x3e, 0xbf, 0x89, 0x1a, 0x9a, 0x90, 0xe5, 0xe2, 0xa6, 0x37, 0x88, 0xa1, 0x68, 0x59, 0xae, 0x8c, 0xec, 0x02, 0x14, 0x8d, 0xb7, 0x2e, 0x25, 0x75, 0x7f, 0x76, 0x1a, 0xd3, 0x4d, 0xad, 0x8a, 0x00, 0x6c, 0x96, 0x49, 0xa4, 0xc3, 0x2e, 0x5c, 0x7b, - /* (2^445)P */ 0x26, 0x53, 0xf7, 0xda, 0xa8, 0x01, 0x14, 0xb1, 0x63, 0xe3, 0xc3, 0x89, 0x88, 0xb0, 0x85, 0x40, 0x2b, 0x26, 0x9a, 0x10, 0x1a, 0x70, 0x33, 0xf4, 0x50, 0x9d, 0x4d, 0xd8, 0x64, 0xc6, 0x0f, 0xe1, 0x17, 0xc8, 0x10, 0x4b, 0xfc, 0xa0, 0xc9, 0xba, 0x2c, 0x98, 0x09, 0xf5, 0x84, 0xb6, 0x7c, 0x4e, 0xa3, 0xe3, 0x81, 0x1b, 0x32, 0x60, 0x02, 0xdd, - /* (2^446)P */ 0xa3, 0xe5, 0x86, 0xd4, 0x43, 0xa8, 0xd1, 0x98, 0x9d, 0x9d, 0xdb, 0x04, 0xcf, 0x6e, 0x35, 0x05, 0x30, 0x53, 0x3b, 0xbc, 0x90, 0x00, 0x4a, 0xc5, 0x40, 0x2a, 0x0f, 0xde, 0x1a, 0xd7, 0x36, 0x27, 0x44, 0x62, 0xa6, 0xac, 0x9d, 0xd2, 0x70, 0x69, 0x14, 0x39, 0x9b, 0xd1, 0xc3, 0x0a, 0x3a, 0x82, 0x0e, 0xf1, 0x94, 0xd7, 0x42, 0x94, 0xd5, 0x7d, - /* (2^447)P */ 0x04, 0xc0, 0x6e, 0x12, 0x90, 0x70, 0xf9, 0xdf, 0xf7, 0xc9, 0x86, 0xc0, 0xe6, 0x92, 0x8b, 0x0a, 0xa1, 0xc1, 0x3b, 0xcc, 0x33, 0xb7, 0xf0, 0xeb, 0x51, 0x50, 0x80, 0x20, 0x69, 0x1c, 0x4f, 0x89, 0x05, 0x1e, 0xe4, 0x7a, 0x0a, 0xc2, 0xf0, 0xf5, 0x78, 0x91, 0x76, 0x34, 0x45, 0xdc, 0x24, 0x53, 0x24, 0x98, 0xe2, 0x73, 0x6f, 0xe6, 0x46, 0x67, -} diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go deleted file mode 100644 index b6b236e5..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go +++ /dev/null @@ -1,71 +0,0 @@ -package goldilocks - -import fp "github.com/cloudflare/circl/math/fp448" - -var ( - // genX is the x-coordinate of the generator of Goldilocks curve. - genX = fp.Elt{ - 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, - 0x8e, 0x93, 0x00, 0x8b, 0xe1, 0x80, 0x3b, 0x43, - 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12, - 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, - 0x67, 0x17, 0x0f, 0x47, 0x70, 0x65, 0x14, 0x9e, - 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22, - 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, - } - // genY is the y-coordinate of the generator of Goldilocks curve. - genY = fp.Elt{ - 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, - 0xad, 0xc8, 0xd7, 0x4e, 0x2c, 0x13, 0xbd, 0xfd, - 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a, - 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, - 0x40, 0x98, 0xa3, 0x6c, 0x73, 0x73, 0xea, 0x4b, - 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88, - 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, - } - // paramD is -39081 in Fp. - paramD = fp.Elt{ - 0x56, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - } - // order is 2^446-0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d, - // which is the number of points in the prime subgroup. - order = Scalar{ - 0xf3, 0x44, 0x58, 0xab, 0x92, 0xc2, 0x78, 0x23, - 0x55, 0x8f, 0xc5, 0x8d, 0x72, 0xc2, 0x6c, 0x21, - 0x90, 0x36, 0xd6, 0xae, 0x49, 0xdb, 0x4e, 0xc4, - 0xe9, 0x23, 0xca, 0x7c, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - } - // residue448 is 2^448 mod order. - residue448 = [4]uint64{ - 0x721cf5b5529eec34, 0x7a4cf635c8e9c2ab, 0xeec492d944a725bf, 0x20cd77058, - } - // invFour is 1/4 mod order. - invFour = Scalar{ - 0x3d, 0x11, 0xd6, 0xaa, 0xa4, 0x30, 0xde, 0x48, - 0xd5, 0x63, 0x71, 0xa3, 0x9c, 0x30, 0x5b, 0x08, - 0xa4, 0x8d, 0xb5, 0x6b, 0xd2, 0xb6, 0x13, 0x71, - 0xfa, 0x88, 0x32, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, - } - // paramDTwist is -39082 in Fp. The D parameter of the twist curve. - paramDTwist = fp.Elt{ - 0x55, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - } -) diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go deleted file mode 100644 index 1f165141..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go +++ /dev/null @@ -1,84 +0,0 @@ -// Package goldilocks provides elliptic curve operations over the goldilocks curve. -package goldilocks - -import fp "github.com/cloudflare/circl/math/fp448" - -// Curve is the Goldilocks curve x^2+y^2=z^2-39081x^2y^2. -type Curve struct{} - -// Identity returns the identity point. -func (Curve) Identity() *Point { - return &Point{ - y: fp.One(), - z: fp.One(), - } -} - -// IsOnCurve returns true if the point lies on the curve. -func (Curve) IsOnCurve(P *Point) bool { - x2, y2, t, t2, z2 := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{} - rhs, lhs := &fp.Elt{}, &fp.Elt{} - // Check z != 0 - eq0 := !fp.IsZero(&P.z) - - fp.Mul(t, &P.ta, &P.tb) // t = ta*tb - fp.Sqr(x2, &P.x) // x^2 - fp.Sqr(y2, &P.y) // y^2 - fp.Sqr(z2, &P.z) // z^2 - fp.Sqr(t2, t) // t^2 - fp.Add(lhs, x2, y2) // x^2 + y^2 - fp.Mul(rhs, t2, ¶mD) // dt^2 - fp.Add(rhs, rhs, z2) // z^2 + dt^2 - fp.Sub(lhs, lhs, rhs) // x^2 + y^2 - (z^2 + dt^2) - eq1 := fp.IsZero(lhs) - - fp.Mul(lhs, &P.x, &P.y) // xy - fp.Mul(rhs, t, &P.z) // tz - fp.Sub(lhs, lhs, rhs) // xy - tz - eq2 := fp.IsZero(lhs) - - return eq0 && eq1 && eq2 -} - -// Generator returns the generator point. -func (Curve) Generator() *Point { - return &Point{ - x: genX, - y: genY, - z: fp.One(), - ta: genX, - tb: genY, - } -} - -// Order returns the number of points in the prime subgroup. -func (Curve) Order() Scalar { return order } - -// Double returns 2P. -func (Curve) Double(P *Point) *Point { R := *P; R.Double(); return &R } - -// Add returns P+Q. -func (Curve) Add(P, Q *Point) *Point { R := *P; R.Add(Q); return &R } - -// ScalarMult returns kP. This function runs in constant time. -func (e Curve) ScalarMult(k *Scalar, P *Point) *Point { - k4 := &Scalar{} - k4.divBy4(k) - return e.pull(twistCurve{}.ScalarMult(k4, e.push(P))) -} - -// ScalarBaseMult returns kG where G is the generator point. This function runs in constant time. -func (e Curve) ScalarBaseMult(k *Scalar) *Point { - k4 := &Scalar{} - k4.divBy4(k) - return e.pull(twistCurve{}.ScalarBaseMult(k4)) -} - -// CombinedMult returns mG+nP, where G is the generator point. This function is non-constant time. -func (e Curve) CombinedMult(m, n *Scalar, P *Point) *Point { - m4 := &Scalar{} - n4 := &Scalar{} - m4.divBy4(m) - n4.divBy4(n) - return e.pull(twistCurve{}.CombinedMult(m4, n4, twistCurve{}.pull(P))) -} diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go deleted file mode 100644 index b1daab85..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go +++ /dev/null @@ -1,52 +0,0 @@ -package goldilocks - -import fp "github.com/cloudflare/circl/math/fp448" - -func (Curve) pull(P *twistPoint) *Point { return twistCurve{}.push(P) } -func (twistCurve) pull(P *Point) *twistPoint { return Curve{}.push(P) } - -// push sends a point on the Goldilocks curve to a point on the twist curve. -func (Curve) push(P *Point) *twistPoint { - Q := &twistPoint{} - Px, Py, Pz := &P.x, &P.y, &P.z - a, b, c, d, e, f, g, h := &Q.x, &Q.y, &Q.z, &fp.Elt{}, &Q.ta, &Q.x, &Q.y, &Q.tb - fp.Add(e, Px, Py) // x+y - fp.Sqr(a, Px) // A = x^2 - fp.Sqr(b, Py) // B = y^2 - fp.Sqr(c, Pz) // z^2 - fp.Add(c, c, c) // C = 2*z^2 - *d = *a // D = A - fp.Sqr(e, e) // (x+y)^2 - fp.Sub(e, e, a) // (x+y)^2-A - fp.Sub(e, e, b) // E = (x+y)^2-A-B - fp.Add(h, b, d) // H = B+D - fp.Sub(g, b, d) // G = B-D - fp.Sub(f, c, h) // F = C-H - fp.Mul(&Q.z, f, g) // Z = F * G - fp.Mul(&Q.x, e, f) // X = E * F - fp.Mul(&Q.y, g, h) // Y = G * H, // T = E * H - return Q -} - -// push sends a point on the twist curve to a point on the Goldilocks curve. -func (twistCurve) push(P *twistPoint) *Point { - Q := &Point{} - Px, Py, Pz := &P.x, &P.y, &P.z - a, b, c, d, e, f, g, h := &Q.x, &Q.y, &Q.z, &fp.Elt{}, &Q.ta, &Q.x, &Q.y, &Q.tb - fp.Add(e, Px, Py) // x+y - fp.Sqr(a, Px) // A = x^2 - fp.Sqr(b, Py) // B = y^2 - fp.Sqr(c, Pz) // z^2 - fp.Add(c, c, c) // C = 2*z^2 - fp.Neg(d, a) // D = -A - fp.Sqr(e, e) // (x+y)^2 - fp.Sub(e, e, a) // (x+y)^2-A - fp.Sub(e, e, b) // E = (x+y)^2-A-B - fp.Add(h, b, d) // H = B+D - fp.Sub(g, b, d) // G = B-D - fp.Sub(f, c, h) // F = C-H - fp.Mul(&Q.z, f, g) // Z = F * G - fp.Mul(&Q.x, e, f) // X = E * F - fp.Mul(&Q.y, g, h) // Y = G * H, // T = E * H - return Q -} diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go deleted file mode 100644 index 11f73de0..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go +++ /dev/null @@ -1,171 +0,0 @@ -package goldilocks - -import ( - "errors" - "fmt" - - fp "github.com/cloudflare/circl/math/fp448" -) - -// Point is a point on the Goldilocks Curve. -type Point struct{ x, y, z, ta, tb fp.Elt } - -func (P Point) String() string { - return fmt.Sprintf("x: %v\ny: %v\nz: %v\nta: %v\ntb: %v", P.x, P.y, P.z, P.ta, P.tb) -} - -// FromAffine creates a point from affine coordinates. -func FromAffine(x, y *fp.Elt) (*Point, error) { - P := &Point{ - x: *x, - y: *y, - z: fp.One(), - ta: *x, - tb: *y, - } - if !(Curve{}).IsOnCurve(P) { - return P, errors.New("point not on curve") - } - return P, nil -} - -// isLessThan returns true if 0 <= x < y, and assumes that slices are of the -// same length and are interpreted in little-endian order. -func isLessThan(x, y []byte) bool { - i := len(x) - 1 - for i > 0 && x[i] == y[i] { - i-- - } - return x[i] < y[i] -} - -// FromBytes returns a point from the input buffer. -func FromBytes(in []byte) (*Point, error) { - if len(in) < fp.Size+1 { - return nil, errors.New("wrong input length") - } - err := errors.New("invalid decoding") - P := &Point{} - signX := in[fp.Size] >> 7 - copy(P.y[:], in[:fp.Size]) - p := fp.P() - if !isLessThan(P.y[:], p[:]) { - return nil, err - } - - u, v := &fp.Elt{}, &fp.Elt{} - one := fp.One() - fp.Sqr(u, &P.y) // u = y^2 - fp.Mul(v, u, ¶mD) // v = dy^2 - fp.Sub(u, u, &one) // u = y^2-1 - fp.Sub(v, v, &one) // v = dy^2-1 - isQR := fp.InvSqrt(&P.x, u, v) // x = sqrt(u/v) - if !isQR { - return nil, err - } - fp.Modp(&P.x) // x = x mod p - if fp.IsZero(&P.x) && signX == 1 { - return nil, err - } - if signX != (P.x[0] & 1) { - fp.Neg(&P.x, &P.x) - } - P.ta = P.x - P.tb = P.y - P.z = fp.One() - return P, nil -} - -// IsIdentity returns true is P is the identity Point. -func (P *Point) IsIdentity() bool { - return fp.IsZero(&P.x) && !fp.IsZero(&P.y) && !fp.IsZero(&P.z) && P.y == P.z -} - -// IsEqual returns true if P is equivalent to Q. -func (P *Point) IsEqual(Q *Point) bool { - l, r := &fp.Elt{}, &fp.Elt{} - fp.Mul(l, &P.x, &Q.z) - fp.Mul(r, &Q.x, &P.z) - fp.Sub(l, l, r) - b := fp.IsZero(l) - fp.Mul(l, &P.y, &Q.z) - fp.Mul(r, &Q.y, &P.z) - fp.Sub(l, l, r) - b = b && fp.IsZero(l) - fp.Mul(l, &P.ta, &P.tb) - fp.Mul(l, l, &Q.z) - fp.Mul(r, &Q.ta, &Q.tb) - fp.Mul(r, r, &P.z) - fp.Sub(l, l, r) - b = b && fp.IsZero(l) - return b -} - -// Neg obtains the inverse of the Point. -func (P *Point) Neg() { fp.Neg(&P.x, &P.x); fp.Neg(&P.ta, &P.ta) } - -// ToAffine returns the x,y affine coordinates of P. -func (P *Point) ToAffine() (x, y fp.Elt) { - fp.Inv(&P.z, &P.z) // 1/z - fp.Mul(&P.x, &P.x, &P.z) // x/z - fp.Mul(&P.y, &P.y, &P.z) // y/z - fp.Modp(&P.x) - fp.Modp(&P.y) - fp.SetOne(&P.z) - P.ta = P.x - P.tb = P.y - return P.x, P.y -} - -// ToBytes stores P into a slice of bytes. -func (P *Point) ToBytes(out []byte) error { - if len(out) < fp.Size+1 { - return errors.New("invalid decoding") - } - x, y := P.ToAffine() - out[fp.Size] = (x[0] & 1) << 7 - return fp.ToBytes(out[:fp.Size], &y) -} - -// MarshalBinary encodes the receiver into a binary form and returns the result. -func (P *Point) MarshalBinary() (data []byte, err error) { - data = make([]byte, fp.Size+1) - err = P.ToBytes(data[:fp.Size+1]) - return data, err -} - -// UnmarshalBinary must be able to decode the form generated by MarshalBinary. -func (P *Point) UnmarshalBinary(data []byte) error { Q, err := FromBytes(data); *P = *Q; return err } - -// Double sets P = 2Q. -func (P *Point) Double() { P.Add(P) } - -// Add sets P =P+Q.. -func (P *Point) Add(Q *Point) { - // This is formula (5) from "Twisted Edwards Curves Revisited" by - // Hisil H., Wong K.KH., Carter G., Dawson E. (2008) - // https://doi.org/10.1007/978-3-540-89255-7_20 - x1, y1, z1, ta1, tb1 := &P.x, &P.y, &P.z, &P.ta, &P.tb - x2, y2, z2, ta2, tb2 := &Q.x, &Q.y, &Q.z, &Q.ta, &Q.tb - x3, y3, z3, E, H := &P.x, &P.y, &P.z, &P.ta, &P.tb - A, B, C, D := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{} - t1, t2, F, G := C, D, &fp.Elt{}, &fp.Elt{} - fp.Mul(t1, ta1, tb1) // t1 = ta1*tb1 - fp.Mul(t2, ta2, tb2) // t2 = ta2*tb2 - fp.Mul(A, x1, x2) // A = x1*x2 - fp.Mul(B, y1, y2) // B = y1*y2 - fp.Mul(C, t1, t2) // t1*t2 - fp.Mul(C, C, ¶mD) // C = d*t1*t2 - fp.Mul(D, z1, z2) // D = z1*z2 - fp.Add(F, x1, y1) // x1+y1 - fp.Add(E, x2, y2) // x2+y2 - fp.Mul(E, E, F) // (x1+y1)*(x2+y2) - fp.Sub(E, E, A) // (x1+y1)*(x2+y2)-A - fp.Sub(E, E, B) // E = (x1+y1)*(x2+y2)-A-B - fp.Sub(F, D, C) // F = D-C - fp.Add(G, D, C) // G = D+C - fp.Sub(H, B, A) // H = B-A - fp.Mul(z3, F, G) // Z = F * G - fp.Mul(x3, E, F) // X = E * F - fp.Mul(y3, G, H) // Y = G * H, T = E * H -} diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go deleted file mode 100644 index f98117b2..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go +++ /dev/null @@ -1,203 +0,0 @@ -package goldilocks - -import ( - "encoding/binary" - "math/bits" -) - -// ScalarSize is the size (in bytes) of scalars. -const ScalarSize = 56 // 448 / 8 - -// _N is the number of 64-bit words to store scalars. -const _N = 7 // 448 / 64 - -// Scalar represents a positive integer stored in little-endian order. -type Scalar [ScalarSize]byte - -type scalar64 [_N]uint64 - -func (z *scalar64) fromScalar(x *Scalar) { - z[0] = binary.LittleEndian.Uint64(x[0*8 : 1*8]) - z[1] = binary.LittleEndian.Uint64(x[1*8 : 2*8]) - z[2] = binary.LittleEndian.Uint64(x[2*8 : 3*8]) - z[3] = binary.LittleEndian.Uint64(x[3*8 : 4*8]) - z[4] = binary.LittleEndian.Uint64(x[4*8 : 5*8]) - z[5] = binary.LittleEndian.Uint64(x[5*8 : 6*8]) - z[6] = binary.LittleEndian.Uint64(x[6*8 : 7*8]) -} - -func (z *scalar64) toScalar(x *Scalar) { - binary.LittleEndian.PutUint64(x[0*8:1*8], z[0]) - binary.LittleEndian.PutUint64(x[1*8:2*8], z[1]) - binary.LittleEndian.PutUint64(x[2*8:3*8], z[2]) - binary.LittleEndian.PutUint64(x[3*8:4*8], z[3]) - binary.LittleEndian.PutUint64(x[4*8:5*8], z[4]) - binary.LittleEndian.PutUint64(x[5*8:6*8], z[5]) - binary.LittleEndian.PutUint64(x[6*8:7*8], z[6]) -} - -// add calculates z = x + y. Assumes len(z) > max(len(x),len(y)). -func add(z, x, y []uint64) uint64 { - l, L, zz := len(x), len(y), y - if l > L { - l, L, zz = L, l, x - } - c := uint64(0) - for i := 0; i < l; i++ { - z[i], c = bits.Add64(x[i], y[i], c) - } - for i := l; i < L; i++ { - z[i], c = bits.Add64(zz[i], 0, c) - } - return c -} - -// sub calculates z = x - y. Assumes len(z) > max(len(x),len(y)). -func sub(z, x, y []uint64) uint64 { - l, L, zz := len(x), len(y), y - if l > L { - l, L, zz = L, l, x - } - c := uint64(0) - for i := 0; i < l; i++ { - z[i], c = bits.Sub64(x[i], y[i], c) - } - for i := l; i < L; i++ { - z[i], c = bits.Sub64(zz[i], 0, c) - } - return c -} - -// mulWord calculates z = x * y. Assumes len(z) >= len(x)+1. -func mulWord(z, x []uint64, y uint64) { - for i := range z { - z[i] = 0 - } - carry := uint64(0) - for i := range x { - hi, lo := bits.Mul64(x[i], y) - lo, cc := bits.Add64(lo, z[i], 0) - hi, _ = bits.Add64(hi, 0, cc) - z[i], cc = bits.Add64(lo, carry, 0) - carry, _ = bits.Add64(hi, 0, cc) - } - z[len(x)] = carry -} - -// Cmov moves x into z if b=1. -func (z *scalar64) Cmov(b uint64, x *scalar64) { - m := uint64(0) - b - for i := range z { - z[i] = (z[i] &^ m) | (x[i] & m) - } -} - -// leftShift shifts to the left the words of z returning the more significant word. -func (z *scalar64) leftShift(low uint64) uint64 { - high := z[_N-1] - for i := _N - 1; i > 0; i-- { - z[i] = z[i-1] - } - z[0] = low - return high -} - -// reduceOneWord calculates z = z + 2^448*x such that the result fits in a Scalar. -func (z *scalar64) reduceOneWord(x uint64) { - prod := (&scalar64{})[:] - mulWord(prod, residue448[:], x) - cc := add(z[:], z[:], prod) - mulWord(prod, residue448[:], cc) - add(z[:], z[:], prod) -} - -// modOrder reduces z mod order. -func (z *scalar64) modOrder() { - var o64, x scalar64 - o64.fromScalar(&order) - // Performs: while (z >= order) { z = z-order } - // At most 8 (eight) iterations reduce 3 bits by subtracting. - for i := 0; i < 8; i++ { - c := sub(x[:], z[:], o64[:]) // (c || x) = z-order - z.Cmov(1-c, &x) // if c != 0 { z = x } - } -} - -// FromBytes stores z = x mod order, where x is a number stored in little-endian order. -func (z *Scalar) FromBytes(x []byte) { - n := len(x) - nCeil := (n + 7) >> 3 - for i := range z { - z[i] = 0 - } - if nCeil < _N { - copy(z[:], x) - return - } - copy(z[:], x[8*(nCeil-_N):]) - var z64 scalar64 - z64.fromScalar(z) - for i := nCeil - _N - 1; i >= 0; i-- { - low := binary.LittleEndian.Uint64(x[8*i:]) - high := z64.leftShift(low) - z64.reduceOneWord(high) - } - z64.modOrder() - z64.toScalar(z) -} - -// divBy4 calculates z = x/4 mod order. -func (z *Scalar) divBy4(x *Scalar) { z.Mul(x, &invFour) } - -// Red reduces z mod order. -func (z *Scalar) Red() { var t scalar64; t.fromScalar(z); t.modOrder(); t.toScalar(z) } - -// Neg calculates z = -z mod order. -func (z *Scalar) Neg() { z.Sub(&order, z) } - -// Add calculates z = x+y mod order. -func (z *Scalar) Add(x, y *Scalar) { - var z64, x64, y64, t scalar64 - x64.fromScalar(x) - y64.fromScalar(y) - c := add(z64[:], x64[:], y64[:]) - add(t[:], z64[:], residue448[:]) - z64.Cmov(c, &t) - z64.modOrder() - z64.toScalar(z) -} - -// Sub calculates z = x-y mod order. -func (z *Scalar) Sub(x, y *Scalar) { - var z64, x64, y64, t scalar64 - x64.fromScalar(x) - y64.fromScalar(y) - c := sub(z64[:], x64[:], y64[:]) - sub(t[:], z64[:], residue448[:]) - z64.Cmov(c, &t) - z64.modOrder() - z64.toScalar(z) -} - -// Mul calculates z = x*y mod order. -func (z *Scalar) Mul(x, y *Scalar) { - var z64, x64, y64 scalar64 - prod := (&[_N + 1]uint64{})[:] - x64.fromScalar(x) - y64.fromScalar(y) - mulWord(prod, x64[:], y64[_N-1]) - copy(z64[:], prod[:_N]) - z64.reduceOneWord(prod[_N]) - for i := _N - 2; i >= 0; i-- { - h := z64.leftShift(0) - z64.reduceOneWord(h) - mulWord(prod, x64[:], y64[i]) - c := add(z64[:], z64[:], prod[:_N]) - z64.reduceOneWord(prod[_N] + c) - } - z64.modOrder() - z64.toScalar(z) -} - -// IsZero returns true if z=0. -func (z *Scalar) IsZero() bool { z.Red(); return *z == Scalar{} } diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go deleted file mode 100644 index 83d7cdad..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go +++ /dev/null @@ -1,138 +0,0 @@ -package goldilocks - -import ( - "crypto/subtle" - "math/bits" - - "github.com/cloudflare/circl/internal/conv" - "github.com/cloudflare/circl/math" - fp "github.com/cloudflare/circl/math/fp448" -) - -// twistCurve is -x^2+y^2=1-39082x^2y^2 and is 4-isogenous to Goldilocks. -type twistCurve struct{} - -// Identity returns the identity point. -func (twistCurve) Identity() *twistPoint { - return &twistPoint{ - y: fp.One(), - z: fp.One(), - } -} - -// subYDiv16 update x = (x - y) / 16. -func subYDiv16(x *scalar64, y int64) { - s := uint64(y >> 63) - x0, b0 := bits.Sub64((*x)[0], uint64(y), 0) - x1, b1 := bits.Sub64((*x)[1], s, b0) - x2, b2 := bits.Sub64((*x)[2], s, b1) - x3, b3 := bits.Sub64((*x)[3], s, b2) - x4, b4 := bits.Sub64((*x)[4], s, b3) - x5, b5 := bits.Sub64((*x)[5], s, b4) - x6, _ := bits.Sub64((*x)[6], s, b5) - x[0] = (x0 >> 4) | (x1 << 60) - x[1] = (x1 >> 4) | (x2 << 60) - x[2] = (x2 >> 4) | (x3 << 60) - x[3] = (x3 >> 4) | (x4 << 60) - x[4] = (x4 >> 4) | (x5 << 60) - x[5] = (x5 >> 4) | (x6 << 60) - x[6] = (x6 >> 4) -} - -func recodeScalar(d *[113]int8, k *Scalar) { - var k64 scalar64 - k64.fromScalar(k) - for i := 0; i < 112; i++ { - d[i] = int8((k64[0] & 0x1f) - 16) - subYDiv16(&k64, int64(d[i])) - } - d[112] = int8(k64[0]) -} - -// ScalarMult returns kP. -func (e twistCurve) ScalarMult(k *Scalar, P *twistPoint) *twistPoint { - var TabP [8]preTwistPointProy - var S preTwistPointProy - var d [113]int8 - - var isZero int - if k.IsZero() { - isZero = 1 - } - subtle.ConstantTimeCopy(isZero, k[:], order[:]) - - minusK := *k - isEven := 1 - int(k[0]&0x1) - minusK.Neg() - subtle.ConstantTimeCopy(isEven, k[:], minusK[:]) - recodeScalar(&d, k) - - P.oddMultiples(TabP[:]) - Q := e.Identity() - for i := 112; i >= 0; i-- { - Q.Double() - Q.Double() - Q.Double() - Q.Double() - mask := d[i] >> 7 - absDi := (d[i] + mask) ^ mask - inx := int32((absDi - 1) >> 1) - sig := int((d[i] >> 7) & 0x1) - for j := range TabP { - S.cmov(&TabP[j], uint(subtle.ConstantTimeEq(inx, int32(j)))) - } - S.cneg(sig) - Q.mixAdd(&S) - } - Q.cneg(uint(isEven)) - return Q -} - -const ( - omegaFix = 7 - omegaVar = 5 -) - -// CombinedMult returns mG+nP. -func (e twistCurve) CombinedMult(m, n *Scalar, P *twistPoint) *twistPoint { - nafFix := math.OmegaNAF(conv.BytesLe2BigInt(m[:]), omegaFix) - nafVar := math.OmegaNAF(conv.BytesLe2BigInt(n[:]), omegaVar) - - if len(nafFix) > len(nafVar) { - nafVar = append(nafVar, make([]int32, len(nafFix)-len(nafVar))...) - } else if len(nafFix) < len(nafVar) { - nafFix = append(nafFix, make([]int32, len(nafVar)-len(nafFix))...) - } - - var TabQ [1 << (omegaVar - 2)]preTwistPointProy - P.oddMultiples(TabQ[:]) - Q := e.Identity() - for i := len(nafFix) - 1; i >= 0; i-- { - Q.Double() - // Generator point - if nafFix[i] != 0 { - idxM := absolute(nafFix[i]) >> 1 - R := tabVerif[idxM] - if nafFix[i] < 0 { - R.neg() - } - Q.mixAddZ1(&R) - } - // Variable input point - if nafVar[i] != 0 { - idxN := absolute(nafVar[i]) >> 1 - S := TabQ[idxN] - if nafVar[i] < 0 { - S.neg() - } - Q.mixAdd(&S) - } - } - return Q -} - -// absolute returns always a positive value. -func absolute(x int32) int32 { - mask := x >> 31 - return (x + mask) ^ mask -} diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go deleted file mode 100644 index c55db77b..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go +++ /dev/null @@ -1,135 +0,0 @@ -package goldilocks - -import ( - "fmt" - - fp "github.com/cloudflare/circl/math/fp448" -) - -type twistPoint struct{ x, y, z, ta, tb fp.Elt } - -type preTwistPointAffine struct{ addYX, subYX, dt2 fp.Elt } - -type preTwistPointProy struct { - preTwistPointAffine - z2 fp.Elt -} - -func (P *twistPoint) String() string { - return fmt.Sprintf("x: %v\ny: %v\nz: %v\nta: %v\ntb: %v", P.x, P.y, P.z, P.ta, P.tb) -} - -// cneg conditionally negates the point if b=1. -func (P *twistPoint) cneg(b uint) { - t := &fp.Elt{} - fp.Neg(t, &P.x) - fp.Cmov(&P.x, t, b) - fp.Neg(t, &P.ta) - fp.Cmov(&P.ta, t, b) -} - -// Double updates P with 2P. -func (P *twistPoint) Double() { - // This is formula (7) from "Twisted Edwards Curves Revisited" by - // Hisil H., Wong K.KH., Carter G., Dawson E. (2008) - // https://doi.org/10.1007/978-3-540-89255-7_20 - Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb - a, b, c, e, f, g, h := Px, Py, Pz, Pta, Px, Py, Ptb - fp.Add(e, Px, Py) // x+y - fp.Sqr(a, Px) // A = x^2 - fp.Sqr(b, Py) // B = y^2 - fp.Sqr(c, Pz) // z^2 - fp.Add(c, c, c) // C = 2*z^2 - fp.Add(h, a, b) // H = A+B - fp.Sqr(e, e) // (x+y)^2 - fp.Sub(e, e, h) // E = (x+y)^2-A-B - fp.Sub(g, b, a) // G = B-A - fp.Sub(f, c, g) // F = C-G - fp.Mul(Pz, f, g) // Z = F * G - fp.Mul(Px, e, f) // X = E * F - fp.Mul(Py, g, h) // Y = G * H, T = E * H -} - -// mixAdd calculates P= P+Q, where Q is a precomputed point with Z_Q = 1. -func (P *twistPoint) mixAddZ1(Q *preTwistPointAffine) { - fp.Add(&P.z, &P.z, &P.z) // D = 2*z1 (z2=1) - P.coreAddition(Q) -} - -// coreAddition calculates P=P+Q for curves with A=-1. -func (P *twistPoint) coreAddition(Q *preTwistPointAffine) { - // This is the formula following (5) from "Twisted Edwards Curves Revisited" by - // Hisil H., Wong K.KH., Carter G., Dawson E. (2008) - // https://doi.org/10.1007/978-3-540-89255-7_20 - Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb - addYX2, subYX2, dt2 := &Q.addYX, &Q.subYX, &Q.dt2 - a, b, c, d, e, f, g, h := Px, Py, &fp.Elt{}, Pz, Pta, Px, Py, Ptb - fp.Mul(c, Pta, Ptb) // t1 = ta*tb - fp.Sub(h, Py, Px) // y1-x1 - fp.Add(b, Py, Px) // y1+x1 - fp.Mul(a, h, subYX2) // A = (y1-x1)*(y2-x2) - fp.Mul(b, b, addYX2) // B = (y1+x1)*(y2+x2) - fp.Mul(c, c, dt2) // C = 2*D*t1*t2 - fp.Sub(e, b, a) // E = B-A - fp.Add(h, b, a) // H = B+A - fp.Sub(f, d, c) // F = D-C - fp.Add(g, d, c) // G = D+C - fp.Mul(Pz, f, g) // Z = F * G - fp.Mul(Px, e, f) // X = E * F - fp.Mul(Py, g, h) // Y = G * H, T = E * H -} - -func (P *preTwistPointAffine) neg() { - P.addYX, P.subYX = P.subYX, P.addYX - fp.Neg(&P.dt2, &P.dt2) -} - -func (P *preTwistPointAffine) cneg(b int) { - t := &fp.Elt{} - fp.Cswap(&P.addYX, &P.subYX, uint(b)) - fp.Neg(t, &P.dt2) - fp.Cmov(&P.dt2, t, uint(b)) -} - -func (P *preTwistPointAffine) cmov(Q *preTwistPointAffine, b uint) { - fp.Cmov(&P.addYX, &Q.addYX, b) - fp.Cmov(&P.subYX, &Q.subYX, b) - fp.Cmov(&P.dt2, &Q.dt2, b) -} - -// mixAdd calculates P= P+Q, where Q is a precomputed point with Z_Q != 1. -func (P *twistPoint) mixAdd(Q *preTwistPointProy) { - fp.Mul(&P.z, &P.z, &Q.z2) // D = 2*z1*z2 - P.coreAddition(&Q.preTwistPointAffine) -} - -// oddMultiples calculates T[i] = (2*i-1)P for 0 < i < len(T). -func (P *twistPoint) oddMultiples(T []preTwistPointProy) { - if n := len(T); n > 0 { - T[0].FromTwistPoint(P) - _2P := *P - _2P.Double() - R := &preTwistPointProy{} - R.FromTwistPoint(&_2P) - for i := 1; i < n; i++ { - P.mixAdd(R) - T[i].FromTwistPoint(P) - } - } -} - -// cmov conditionally moves Q into P if b=1. -func (P *preTwistPointProy) cmov(Q *preTwistPointProy, b uint) { - P.preTwistPointAffine.cmov(&Q.preTwistPointAffine, b) - fp.Cmov(&P.z2, &Q.z2, b) -} - -// FromTwistPoint precomputes some coordinates of Q for missed addition. -func (P *preTwistPointProy) FromTwistPoint(Q *twistPoint) { - fp.Add(&P.addYX, &Q.y, &Q.x) // addYX = X + Y - fp.Sub(&P.subYX, &Q.y, &Q.x) // subYX = Y - X - fp.Mul(&P.dt2, &Q.ta, &Q.tb) // T = ta*tb - fp.Mul(&P.dt2, &P.dt2, ¶mDTwist) // D*T - fp.Add(&P.dt2, &P.dt2, &P.dt2) // dt2 = 2*D*T - fp.Add(&P.z2, &Q.z, &Q.z) // z2 = 2*Z -} diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go deleted file mode 100644 index ed432e02..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go +++ /dev/null @@ -1,216 +0,0 @@ -package goldilocks - -import fp "github.com/cloudflare/circl/math/fp448" - -var tabFixMult = [fxV][fx2w1]preTwistPointAffine{ - { - { - addYX: fp.Elt{0x65, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2b, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, - subYX: fp.Elt{0x64, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2d, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, - dt2: fp.Elt{0x1a, 0x33, 0xea, 0x64, 0x45, 0x1c, 0xdf, 0x17, 0x1d, 0x16, 0x34, 0x28, 0xd6, 0x61, 0x19, 0x67, 0x79, 0xb4, 0x13, 0xcf, 0x3e, 0x7c, 0x0e, 0x72, 0xda, 0xf1, 0x5f, 0xda, 0xe6, 0xcf, 0x42, 0xd3, 0xb6, 0x17, 0xc2, 0x68, 0x13, 0x2d, 0xd9, 0x60, 0x3e, 0xae, 0xf0, 0x5b, 0x96, 0xf0, 0xcd, 0xaf, 0xea, 0xb7, 0x0d, 0x59, 0x16, 0xa7, 0xff, 0x55}, - }, - { - addYX: fp.Elt{0xca, 0xd8, 0x7d, 0x86, 0x1a, 0xef, 0xad, 0x11, 0xe3, 0x27, 0x41, 0x7e, 0x7f, 0x3e, 0xa9, 0xd2, 0xb5, 0x4e, 0x50, 0xe0, 0x77, 0x91, 0xc2, 0x13, 0x52, 0x73, 0x41, 0x09, 0xa6, 0x57, 0x9a, 0xc8, 0xa8, 0x90, 0x9d, 0x26, 0x14, 0xbb, 0xa1, 0x2a, 0xf7, 0x45, 0x43, 0x4e, 0xea, 0x35, 0x62, 0xe1, 0x08, 0x85, 0x46, 0xb8, 0x24, 0x05, 0x2d, 0xab}, - subYX: fp.Elt{0x9b, 0xe6, 0xd3, 0xe5, 0xfe, 0x50, 0x36, 0x3c, 0x3c, 0x6d, 0x74, 0x1d, 0x74, 0xc0, 0xde, 0x5b, 0x45, 0x27, 0xe5, 0x12, 0xee, 0x63, 0x35, 0x6b, 0x13, 0xe2, 0x41, 0x6b, 0x3a, 0x05, 0x2b, 0xb1, 0x89, 0x26, 0xb6, 0xc6, 0xd1, 0x84, 0xff, 0x0e, 0x9b, 0xa3, 0xfb, 0x21, 0x36, 0x6b, 0x01, 0xf7, 0x9f, 0x7c, 0xeb, 0xf5, 0x18, 0x7a, 0x2a, 0x70}, - dt2: fp.Elt{0x09, 0xad, 0x99, 0x1a, 0x38, 0xd3, 0xdf, 0x22, 0x37, 0x32, 0x61, 0x8b, 0xf3, 0x19, 0x48, 0x08, 0xe8, 0x49, 0xb6, 0x4a, 0xa7, 0xed, 0xa4, 0xa2, 0xee, 0x86, 0xd7, 0x31, 0x5e, 0xce, 0x95, 0x76, 0x86, 0x42, 0x1c, 0x9d, 0x07, 0x14, 0x8c, 0x34, 0x18, 0x9c, 0x6d, 0x3a, 0xdf, 0xa9, 0xe8, 0x36, 0x7e, 0xe4, 0x95, 0xbe, 0xb5, 0x09, 0xf8, 0x9c}, - }, - { - addYX: fp.Elt{0x51, 0xdb, 0x49, 0xa8, 0x9f, 0xe3, 0xd7, 0xec, 0x0d, 0x0f, 0x49, 0xe8, 0xb6, 0xc5, 0x0f, 0x5a, 0x1c, 0xce, 0x54, 0x0d, 0xb1, 0x8d, 0x5b, 0xbf, 0xf4, 0xaa, 0x34, 0x77, 0xc4, 0x5d, 0x59, 0xb6, 0xc5, 0x0e, 0x5a, 0xd8, 0x5b, 0x30, 0xc2, 0x1d, 0xec, 0x85, 0x1c, 0x42, 0xbe, 0x24, 0x2e, 0x50, 0x55, 0x44, 0xb2, 0x3a, 0x01, 0xaa, 0x98, 0xfb}, - subYX: fp.Elt{0xe7, 0x29, 0xb7, 0xd0, 0xaa, 0x4f, 0x32, 0x53, 0x56, 0xde, 0xbc, 0xd1, 0x92, 0x5d, 0x19, 0xbe, 0xa3, 0xe3, 0x75, 0x48, 0xe0, 0x7a, 0x1b, 0x54, 0x7a, 0xb7, 0x41, 0x77, 0x84, 0x38, 0xdd, 0x14, 0x9f, 0xca, 0x3f, 0xa3, 0xc8, 0xa7, 0x04, 0x70, 0xf1, 0x4d, 0x3d, 0xb3, 0x84, 0x79, 0xcb, 0xdb, 0xe4, 0xc5, 0x42, 0x9b, 0x57, 0x19, 0xf1, 0x2d}, - dt2: fp.Elt{0x20, 0xb4, 0x94, 0x9e, 0xdf, 0x31, 0x44, 0x0b, 0xc9, 0x7b, 0x75, 0x40, 0x9d, 0xd1, 0x96, 0x39, 0x70, 0x71, 0x15, 0xc8, 0x93, 0xd5, 0xc5, 0xe5, 0xba, 0xfe, 0xee, 0x08, 0x6a, 0x98, 0x0a, 0x1b, 0xb2, 0xaa, 0x3a, 0xf4, 0xa4, 0x79, 0xf9, 0x8e, 0x4d, 0x65, 0x10, 0x9b, 0x3a, 0x6e, 0x7c, 0x87, 0x94, 0x92, 0x11, 0x65, 0xbf, 0x1a, 0x09, 0xde}, - }, - { - addYX: fp.Elt{0xf3, 0x84, 0x76, 0x77, 0xa5, 0x6b, 0x27, 0x3b, 0x83, 0x3d, 0xdf, 0xa0, 0xeb, 0x32, 0x6d, 0x58, 0x81, 0x57, 0x64, 0xc2, 0x21, 0x7c, 0x9b, 0xea, 0xe6, 0xb0, 0x93, 0xf9, 0xe7, 0xc3, 0xed, 0x5a, 0x8e, 0xe2, 0xb4, 0x72, 0x76, 0x66, 0x0f, 0x22, 0x29, 0x94, 0x3e, 0x63, 0x48, 0x5e, 0x80, 0xcb, 0xac, 0xfa, 0x95, 0xb6, 0x4b, 0xc4, 0x95, 0x33}, - subYX: fp.Elt{0x0c, 0x55, 0xd1, 0x5e, 0x5f, 0xbf, 0xbf, 0xe2, 0x4c, 0xfc, 0x37, 0x4a, 0xc4, 0xb1, 0xf4, 0x83, 0x61, 0x93, 0x60, 0x8e, 0x9f, 0x31, 0xf0, 0xa0, 0x41, 0xff, 0x1d, 0xe2, 0x7f, 0xca, 0x40, 0xd6, 0x88, 0xe8, 0x91, 0x61, 0xe2, 0x11, 0x18, 0x83, 0xf3, 0x25, 0x2f, 0x3f, 0x49, 0x40, 0xd4, 0x83, 0xe2, 0xd7, 0x74, 0x6a, 0x16, 0x86, 0x4e, 0xab}, - dt2: fp.Elt{0xdd, 0x58, 0x65, 0xd8, 0x9f, 0xdd, 0x70, 0x7f, 0x0f, 0xec, 0xbd, 0x5c, 0x5c, 0x9b, 0x7e, 0x1b, 0x9f, 0x79, 0x36, 0x1f, 0xfd, 0x79, 0x10, 0x1c, 0x52, 0xf3, 0x22, 0xa4, 0x1f, 0x71, 0x6e, 0x63, 0x14, 0xf4, 0xa7, 0x3e, 0xbe, 0xad, 0x43, 0x30, 0x38, 0x8c, 0x29, 0xc6, 0xcf, 0x50, 0x75, 0x21, 0xe5, 0x78, 0xfd, 0xb0, 0x9a, 0xc4, 0x6d, 0xd4}, - }, - }, - { - { - addYX: fp.Elt{0x7a, 0xa1, 0x38, 0xa6, 0xfd, 0x0e, 0x96, 0xd5, 0x26, 0x76, 0x86, 0x70, 0x80, 0x30, 0xa6, 0x67, 0xeb, 0xf4, 0x39, 0xdb, 0x22, 0xf5, 0x9f, 0x98, 0xe4, 0xb5, 0x3a, 0x0c, 0x59, 0xbf, 0x85, 0xc6, 0xf0, 0x0b, 0x1c, 0x41, 0x38, 0x09, 0x01, 0xdb, 0xd6, 0x3c, 0xb7, 0xf1, 0x08, 0x6b, 0x4b, 0x9e, 0x63, 0x53, 0x83, 0xd3, 0xab, 0xa3, 0x72, 0x0d}, - subYX: fp.Elt{0x84, 0x68, 0x25, 0xe8, 0xe9, 0x8f, 0x91, 0xbf, 0xf7, 0xa4, 0x30, 0xae, 0xea, 0x9f, 0xdd, 0x56, 0x64, 0x09, 0xc9, 0x54, 0x68, 0x4e, 0x33, 0xc5, 0x6f, 0x7b, 0x2d, 0x52, 0x2e, 0x42, 0xbe, 0xbe, 0xf5, 0x64, 0xbf, 0x77, 0x54, 0xdf, 0xb0, 0x10, 0xd2, 0x16, 0x5d, 0xce, 0xaf, 0x9f, 0xfb, 0xa3, 0x63, 0x50, 0xcb, 0xc0, 0xd0, 0x88, 0x44, 0xa3}, - dt2: fp.Elt{0xc3, 0x8b, 0xa5, 0xf1, 0x44, 0xe4, 0x41, 0xcd, 0x75, 0xe3, 0x17, 0x69, 0x5b, 0xb9, 0xbb, 0xee, 0x82, 0xbb, 0xce, 0x57, 0xdf, 0x2a, 0x9c, 0x12, 0xab, 0x66, 0x08, 0x68, 0x05, 0x1b, 0x87, 0xee, 0x5d, 0x1e, 0x18, 0x14, 0x22, 0x4b, 0x99, 0x61, 0x75, 0x28, 0xe7, 0x65, 0x1c, 0x36, 0xb6, 0x18, 0x09, 0xa8, 0xdf, 0xef, 0x30, 0x35, 0xbc, 0x58}, - }, - { - addYX: fp.Elt{0xc5, 0xd3, 0x0e, 0x6f, 0xaf, 0x06, 0x69, 0xc4, 0x07, 0x9e, 0x58, 0x6e, 0x3f, 0x49, 0xd9, 0x0a, 0x3c, 0x2c, 0x37, 0xcd, 0x27, 0x4d, 0x87, 0x91, 0x7a, 0xb0, 0x28, 0xad, 0x2f, 0x68, 0x92, 0x05, 0x97, 0xf1, 0x30, 0x5f, 0x4c, 0x10, 0x20, 0x30, 0xd3, 0x08, 0x3f, 0xc1, 0xc6, 0xb7, 0xb5, 0xd1, 0x71, 0x7b, 0xa8, 0x0a, 0xd8, 0xf5, 0x17, 0xcf}, - subYX: fp.Elt{0x64, 0xd4, 0x8f, 0x91, 0x40, 0xab, 0x6e, 0x1a, 0x62, 0x83, 0xdc, 0xd7, 0x30, 0x1a, 0x4a, 0x2a, 0x4c, 0x54, 0x86, 0x19, 0x81, 0x5d, 0x04, 0x52, 0xa3, 0xca, 0x82, 0x38, 0xdc, 0x1e, 0xf0, 0x7a, 0x78, 0x76, 0x49, 0x4f, 0x71, 0xc4, 0x74, 0x2f, 0xf0, 0x5b, 0x2e, 0x5e, 0xac, 0xef, 0x17, 0xe4, 0x8e, 0x6e, 0xed, 0x43, 0x23, 0x61, 0x99, 0x49}, - dt2: fp.Elt{0x64, 0x90, 0x72, 0x76, 0xf8, 0x2c, 0x7d, 0x57, 0xf9, 0x30, 0x5e, 0x7a, 0x10, 0x74, 0x19, 0x39, 0xd9, 0xaf, 0x0a, 0xf1, 0x43, 0xed, 0x88, 0x9c, 0x8b, 0xdc, 0x9b, 0x1c, 0x90, 0xe7, 0xf7, 0xa3, 0xa5, 0x0d, 0xc6, 0xbc, 0x30, 0xfb, 0x91, 0x1a, 0x51, 0xba, 0x2d, 0xbe, 0x89, 0xdf, 0x1d, 0xdc, 0x53, 0xa8, 0x82, 0x8a, 0xd3, 0x8d, 0x16, 0x68}, - }, - { - addYX: fp.Elt{0xef, 0x5c, 0xe3, 0x74, 0xbf, 0x13, 0x4a, 0xbf, 0x66, 0x73, 0x64, 0xb7, 0xd4, 0xce, 0x98, 0x82, 0x05, 0xfa, 0x98, 0x0c, 0x0a, 0xae, 0xe5, 0x6b, 0x9f, 0xac, 0xbb, 0x6e, 0x1f, 0xcf, 0xff, 0xa6, 0x71, 0x9a, 0xa8, 0x7a, 0x9e, 0x64, 0x1f, 0x20, 0x4a, 0x61, 0xa2, 0xd6, 0x50, 0xe3, 0xba, 0x81, 0x0c, 0x50, 0x59, 0x69, 0x59, 0x15, 0x55, 0xdb}, - subYX: fp.Elt{0xe8, 0x77, 0x4d, 0xe8, 0x66, 0x3d, 0xc1, 0x00, 0x3c, 0xf2, 0x25, 0x00, 0xdc, 0xb2, 0xe5, 0x9b, 0x12, 0x89, 0xf3, 0xd6, 0xea, 0x85, 0x60, 0xfe, 0x67, 0x91, 0xfd, 0x04, 0x7c, 0xe0, 0xf1, 0x86, 0x06, 0x11, 0x66, 0xee, 0xd4, 0xd5, 0xbe, 0x3b, 0x0f, 0xe3, 0x59, 0xb3, 0x4f, 0x00, 0xb6, 0xce, 0x80, 0xc1, 0x61, 0xf7, 0xaf, 0x04, 0x6a, 0x3c}, - dt2: fp.Elt{0x00, 0xd7, 0x32, 0x93, 0x67, 0x70, 0x6f, 0xd7, 0x69, 0xab, 0xb1, 0xd3, 0xdc, 0xd6, 0xa8, 0xdd, 0x35, 0x25, 0xca, 0xd3, 0x8a, 0x6d, 0xce, 0xfb, 0xfd, 0x2b, 0x83, 0xf0, 0xd4, 0xac, 0x66, 0xfb, 0x72, 0x87, 0x7e, 0x55, 0xb7, 0x91, 0x58, 0x10, 0xc3, 0x11, 0x7e, 0x15, 0xfe, 0x7c, 0x55, 0x90, 0xa3, 0x9e, 0xed, 0x9a, 0x7f, 0xa7, 0xb7, 0xeb}, - }, - { - addYX: fp.Elt{0x25, 0x0f, 0xc2, 0x09, 0x9c, 0x10, 0xc8, 0x7c, 0x93, 0xa7, 0xbe, 0xe9, 0x26, 0x25, 0x7c, 0x21, 0xfe, 0xe7, 0x5f, 0x3c, 0x02, 0x83, 0xa7, 0x9e, 0xdf, 0xc0, 0x94, 0x2b, 0x7d, 0x1a, 0xd0, 0x1d, 0xcc, 0x2e, 0x7d, 0xd4, 0x85, 0xe7, 0xc1, 0x15, 0x66, 0xd6, 0xd6, 0x32, 0xb8, 0xf7, 0x63, 0xaa, 0x3b, 0xa5, 0xea, 0x49, 0xad, 0x88, 0x9b, 0x66}, - subYX: fp.Elt{0x09, 0x97, 0x79, 0x36, 0x41, 0x56, 0x9b, 0xdf, 0x15, 0xd8, 0x43, 0x28, 0x17, 0x5b, 0x96, 0xc9, 0xcf, 0x39, 0x1f, 0x13, 0xf7, 0x4d, 0x1d, 0x1f, 0xda, 0x51, 0x56, 0xe7, 0x0a, 0x5a, 0x65, 0xb6, 0x2a, 0x87, 0x49, 0x86, 0xc2, 0x2b, 0xcd, 0xfe, 0x07, 0xf6, 0x4c, 0xe2, 0x1d, 0x9b, 0xd8, 0x82, 0x09, 0x5b, 0x11, 0x10, 0x62, 0x56, 0x89, 0xbd}, - dt2: fp.Elt{0xd9, 0x15, 0x73, 0xf2, 0x96, 0x35, 0x53, 0xb0, 0xe7, 0xa8, 0x0b, 0x93, 0x35, 0x0b, 0x3a, 0x00, 0xf5, 0x18, 0xb1, 0xc3, 0x12, 0x3f, 0x91, 0x17, 0xc1, 0x4c, 0x15, 0x5a, 0x86, 0x92, 0x11, 0xbd, 0x44, 0x40, 0x5a, 0x7b, 0x15, 0x89, 0xba, 0xc1, 0xc1, 0xbc, 0x43, 0x45, 0xe6, 0x52, 0x02, 0x73, 0x0a, 0xd0, 0x2a, 0x19, 0xda, 0x47, 0xa8, 0xff}, - }, - }, -} - -// tabVerif contains the odd multiples of P. The entry T[i] = (2i+1)P, where -// P = phi(G) and G is the generator of the Goldilocks curve, and phi is a -// 4-degree isogeny. -var tabVerif = [1 << (omegaFix - 2)]preTwistPointAffine{ - { /* 1P*/ - addYX: fp.Elt{0x65, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2b, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, - subYX: fp.Elt{0x64, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2d, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05}, - dt2: fp.Elt{0x1a, 0x33, 0xea, 0x64, 0x45, 0x1c, 0xdf, 0x17, 0x1d, 0x16, 0x34, 0x28, 0xd6, 0x61, 0x19, 0x67, 0x79, 0xb4, 0x13, 0xcf, 0x3e, 0x7c, 0x0e, 0x72, 0xda, 0xf1, 0x5f, 0xda, 0xe6, 0xcf, 0x42, 0xd3, 0xb6, 0x17, 0xc2, 0x68, 0x13, 0x2d, 0xd9, 0x60, 0x3e, 0xae, 0xf0, 0x5b, 0x96, 0xf0, 0xcd, 0xaf, 0xea, 0xb7, 0x0d, 0x59, 0x16, 0xa7, 0xff, 0x55}, - }, - { /* 3P*/ - addYX: fp.Elt{0xd1, 0xe9, 0xa8, 0x33, 0x20, 0x76, 0x18, 0x08, 0x45, 0x2a, 0xc9, 0x67, 0x2a, 0xc3, 0x15, 0x24, 0xf9, 0x74, 0x21, 0x30, 0x99, 0x59, 0x8b, 0xb2, 0xf0, 0xa4, 0x07, 0xe2, 0x6a, 0x36, 0x8d, 0xd9, 0xd2, 0x4a, 0x7f, 0x73, 0x50, 0x39, 0x3d, 0xaa, 0xa7, 0x51, 0x73, 0x0d, 0x2b, 0x8b, 0x96, 0x47, 0xac, 0x3c, 0x5d, 0xaa, 0x39, 0x9c, 0xcf, 0xd5}, - subYX: fp.Elt{0x6b, 0x11, 0x5d, 0x1a, 0xf9, 0x41, 0x9d, 0xc5, 0x30, 0x3e, 0xad, 0x25, 0x2c, 0x04, 0x45, 0xea, 0xcc, 0x67, 0x07, 0x85, 0xe9, 0xda, 0x0e, 0xb5, 0x40, 0xb7, 0x32, 0xb4, 0x49, 0xdd, 0xff, 0xaa, 0xfc, 0xbb, 0x19, 0xca, 0x8b, 0x79, 0x2b, 0x8f, 0x8d, 0x00, 0x33, 0xc2, 0xad, 0xe9, 0xd3, 0x12, 0xa8, 0xaa, 0x87, 0x62, 0xad, 0x2d, 0xff, 0xa4}, - dt2: fp.Elt{0xb0, 0xaf, 0x3b, 0xea, 0xf0, 0x42, 0x0b, 0x5e, 0x88, 0xd3, 0x98, 0x08, 0x87, 0x59, 0x72, 0x0a, 0xc2, 0xdf, 0xcb, 0x7f, 0x59, 0xb5, 0x4c, 0x63, 0x68, 0xe8, 0x41, 0x38, 0x67, 0x4f, 0xe9, 0xc6, 0xb2, 0x6b, 0x08, 0xa7, 0xf7, 0x0e, 0xcd, 0xea, 0xca, 0x3d, 0xaf, 0x8e, 0xda, 0x4b, 0x2e, 0xd2, 0x88, 0x64, 0x8d, 0xc5, 0x5f, 0x76, 0x0f, 0x3d}, - }, - { /* 5P*/ - addYX: fp.Elt{0xe5, 0x65, 0xc9, 0xe2, 0x75, 0xf0, 0x7d, 0x1a, 0xba, 0xa4, 0x40, 0x4b, 0x93, 0x12, 0xa2, 0x80, 0x95, 0x0d, 0x03, 0x93, 0xe8, 0xa5, 0x4d, 0xe2, 0x3d, 0x81, 0xf5, 0xce, 0xd4, 0x2d, 0x25, 0x59, 0x16, 0x5c, 0xe7, 0xda, 0xc7, 0x45, 0xd2, 0x7e, 0x2c, 0x38, 0xd4, 0x37, 0x64, 0xb2, 0xc2, 0x28, 0xc5, 0x72, 0x16, 0x32, 0x45, 0x36, 0x6f, 0x9f}, - subYX: fp.Elt{0x09, 0xf4, 0x7e, 0xbd, 0x89, 0xdb, 0x19, 0x58, 0xe1, 0x08, 0x00, 0x8a, 0xf4, 0x5f, 0x2a, 0x32, 0x40, 0xf0, 0x2c, 0x3f, 0x5d, 0xe4, 0xfc, 0x89, 0x11, 0x24, 0xb4, 0x2f, 0x97, 0xad, 0xac, 0x8f, 0x19, 0xab, 0xfa, 0x12, 0xe5, 0xf9, 0x50, 0x4e, 0x50, 0x6f, 0x32, 0x30, 0x88, 0xa6, 0xe5, 0x48, 0x28, 0xa2, 0x1b, 0x9f, 0xcd, 0xe2, 0x43, 0x38}, - dt2: fp.Elt{0xa9, 0xcc, 0x53, 0x39, 0x86, 0x02, 0x60, 0x75, 0x34, 0x99, 0x57, 0xbd, 0xfc, 0x5a, 0x8e, 0xce, 0x5e, 0x98, 0x22, 0xd0, 0xa5, 0x24, 0xff, 0x90, 0x28, 0x9f, 0x58, 0xf3, 0x39, 0xe9, 0xba, 0x36, 0x23, 0xfb, 0x7f, 0x41, 0xcc, 0x2b, 0x5a, 0x25, 0x3f, 0x4c, 0x2a, 0xf1, 0x52, 0x6f, 0x2f, 0x07, 0xe3, 0x88, 0x81, 0x77, 0xdd, 0x7c, 0x88, 0x82}, - }, - { /* 7P*/ - addYX: fp.Elt{0xf7, 0xee, 0x88, 0xfd, 0x3a, 0xbf, 0x7e, 0x28, 0x39, 0x23, 0x79, 0xe6, 0x5c, 0x56, 0xcb, 0xb5, 0x48, 0x6a, 0x80, 0x6d, 0x37, 0x60, 0x6c, 0x10, 0x35, 0x49, 0x4b, 0x46, 0x60, 0xd4, 0x79, 0xd4, 0x53, 0xd3, 0x67, 0x88, 0xd0, 0x41, 0xd5, 0x43, 0x85, 0xc8, 0x71, 0xe3, 0x1c, 0xb6, 0xda, 0x22, 0x64, 0x8f, 0x80, 0xac, 0xad, 0x7d, 0xd5, 0x82}, - subYX: fp.Elt{0x92, 0x40, 0xc1, 0x83, 0x21, 0x9b, 0xd5, 0x7d, 0x3f, 0x29, 0xb6, 0x26, 0xef, 0x12, 0xb9, 0x27, 0x39, 0x42, 0x37, 0x97, 0x09, 0x9a, 0x08, 0xe1, 0x68, 0xb6, 0x7a, 0x3f, 0x9f, 0x45, 0xf8, 0x37, 0x19, 0x83, 0x97, 0xe6, 0x73, 0x30, 0x32, 0x35, 0xcf, 0xae, 0x5c, 0x12, 0x68, 0xdf, 0x6e, 0x2b, 0xde, 0x83, 0xa0, 0x44, 0x74, 0x2e, 0x4a, 0xe9}, - dt2: fp.Elt{0xcb, 0x22, 0x0a, 0xda, 0x6b, 0xc1, 0x8a, 0x29, 0xa1, 0xac, 0x8b, 0x5b, 0x8b, 0x32, 0x20, 0xf2, 0x21, 0xae, 0x0c, 0x43, 0xc4, 0xd7, 0x19, 0x37, 0x3d, 0x79, 0x25, 0x98, 0x6c, 0x9c, 0x22, 0x31, 0x2a, 0x55, 0x9f, 0xda, 0x5e, 0xa8, 0x13, 0xdb, 0x8e, 0x2e, 0x16, 0x39, 0xf4, 0x91, 0x6f, 0xec, 0x71, 0x71, 0xc9, 0x10, 0xf2, 0xa4, 0x8f, 0x11}, - }, - { /* 9P*/ - addYX: fp.Elt{0x85, 0xdd, 0x37, 0x62, 0x74, 0x8e, 0x33, 0x5b, 0x25, 0x12, 0x1b, 0xe7, 0xdf, 0x47, 0xe5, 0x12, 0xfd, 0x3a, 0x3a, 0xf5, 0x5d, 0x4c, 0xa2, 0x29, 0x3c, 0x5c, 0x2f, 0xee, 0x18, 0x19, 0x0a, 0x2b, 0xef, 0x67, 0x50, 0x7a, 0x0d, 0x29, 0xae, 0x55, 0x82, 0xcd, 0xd6, 0x41, 0x90, 0xb4, 0x13, 0x31, 0x5d, 0x11, 0xb8, 0xaa, 0x12, 0x86, 0x08, 0xac}, - subYX: fp.Elt{0xcc, 0x37, 0x8d, 0x83, 0x5f, 0xfd, 0xde, 0xd5, 0xf7, 0xf1, 0xae, 0x0a, 0xa7, 0x0b, 0xeb, 0x6d, 0x19, 0x8a, 0xb6, 0x1a, 0x59, 0xd8, 0xff, 0x3c, 0xbc, 0xbc, 0xef, 0x9c, 0xda, 0x7b, 0x75, 0x12, 0xaf, 0x80, 0x8f, 0x2c, 0x3c, 0xaa, 0x0b, 0x17, 0x86, 0x36, 0x78, 0x18, 0xc8, 0x8a, 0xf6, 0xb8, 0x2c, 0x2f, 0x57, 0x2c, 0x62, 0x57, 0xf6, 0x90}, - dt2: fp.Elt{0x83, 0xbc, 0xa2, 0x07, 0xa5, 0x38, 0x96, 0xea, 0xfe, 0x11, 0x46, 0x1d, 0x3b, 0xcd, 0x42, 0xc5, 0xee, 0x67, 0x04, 0x72, 0x08, 0xd8, 0xd9, 0x96, 0x07, 0xf7, 0xac, 0xc3, 0x64, 0xf1, 0x98, 0x2c, 0x55, 0xd7, 0x7d, 0xc8, 0x6c, 0xbd, 0x2c, 0xff, 0x15, 0xd6, 0x6e, 0xb8, 0x17, 0x8e, 0xa8, 0x27, 0x66, 0xb1, 0x73, 0x79, 0x96, 0xff, 0x29, 0x10}, - }, - { /* 11P*/ - addYX: fp.Elt{0x76, 0xcb, 0x9b, 0x0c, 0x5b, 0xfe, 0xe1, 0x2a, 0xdd, 0x6f, 0x6c, 0xdd, 0x6f, 0xb4, 0xc0, 0xc2, 0x1b, 0x4b, 0x38, 0xe8, 0x66, 0x8c, 0x1e, 0x31, 0x63, 0xb9, 0x94, 0xcd, 0xc3, 0x8c, 0x44, 0x25, 0x7b, 0xd5, 0x39, 0x80, 0xfc, 0x01, 0xaa, 0xf7, 0x2a, 0x61, 0x8a, 0x25, 0xd2, 0x5f, 0xc5, 0x66, 0x38, 0xa4, 0x17, 0xcf, 0x3e, 0x11, 0x0f, 0xa3}, - subYX: fp.Elt{0xe0, 0xb6, 0xd1, 0x9c, 0x71, 0x49, 0x2e, 0x7b, 0xde, 0x00, 0xda, 0x6b, 0xf1, 0xec, 0xe6, 0x7a, 0x15, 0x38, 0x71, 0xe9, 0x7b, 0xdb, 0xf8, 0x98, 0xc0, 0x91, 0x2e, 0x53, 0xee, 0x92, 0x87, 0x25, 0xc9, 0xb0, 0xbb, 0x33, 0x15, 0x46, 0x7f, 0xfd, 0x4f, 0x8b, 0x77, 0x05, 0x96, 0xb6, 0xe2, 0x08, 0xdb, 0x0d, 0x09, 0xee, 0x5b, 0xd1, 0x2a, 0x63}, - dt2: fp.Elt{0x8f, 0x7b, 0x57, 0x8c, 0xbf, 0x06, 0x0d, 0x43, 0x21, 0x92, 0x94, 0x2d, 0x6a, 0x38, 0x07, 0x0f, 0xa0, 0xf1, 0xe3, 0xd8, 0x2a, 0xbf, 0x46, 0xc6, 0x9e, 0x1f, 0x8f, 0x2b, 0x46, 0x84, 0x0b, 0x74, 0xed, 0xff, 0xf8, 0xa5, 0x94, 0xae, 0xf1, 0x67, 0xb1, 0x9b, 0xdd, 0x4a, 0xd0, 0xdb, 0xc2, 0xb5, 0x58, 0x49, 0x0c, 0xa9, 0x1d, 0x7d, 0xa9, 0xd3}, - }, - { /* 13P*/ - addYX: fp.Elt{0x73, 0x84, 0x2e, 0x31, 0x1f, 0xdc, 0xed, 0x9f, 0x74, 0xfa, 0xe0, 0x35, 0xb1, 0x85, 0x6a, 0x8d, 0x86, 0xd0, 0xff, 0xd6, 0x08, 0x43, 0x73, 0x1a, 0xd5, 0xf8, 0x43, 0xd4, 0xb3, 0xe5, 0x3f, 0xa8, 0x84, 0x17, 0x59, 0x65, 0x4e, 0xe6, 0xee, 0x54, 0x9c, 0xda, 0x5e, 0x7e, 0x98, 0x29, 0x6d, 0x73, 0x34, 0x1f, 0x99, 0x80, 0x54, 0x54, 0x81, 0x0b}, - subYX: fp.Elt{0xb1, 0xe5, 0xbb, 0x80, 0x22, 0x9c, 0x81, 0x6d, 0xaf, 0x27, 0x65, 0x6f, 0x7e, 0x9c, 0xb6, 0x8d, 0x35, 0x5c, 0x2e, 0x20, 0x48, 0x7a, 0x28, 0xf0, 0x97, 0xfe, 0xb7, 0x71, 0xce, 0xd6, 0xad, 0x3a, 0x81, 0xf6, 0x74, 0x5e, 0xf3, 0xfd, 0x1b, 0xd4, 0x1e, 0x7c, 0xc2, 0xb7, 0xc8, 0xa6, 0xc9, 0x89, 0x03, 0x47, 0xec, 0x24, 0xd6, 0x0e, 0xec, 0x9c}, - dt2: fp.Elt{0x91, 0x0a, 0x43, 0x34, 0x20, 0xc2, 0x64, 0xf7, 0x4e, 0x48, 0xc8, 0xd2, 0x95, 0x83, 0xd1, 0xa4, 0xfb, 0x4e, 0x41, 0x3b, 0x0d, 0xd5, 0x07, 0xd9, 0xf1, 0x13, 0x16, 0x78, 0x54, 0x57, 0xd0, 0xf1, 0x4f, 0x20, 0xac, 0xcf, 0x9c, 0x3b, 0x33, 0x0b, 0x99, 0x54, 0xc3, 0x7f, 0x3e, 0x57, 0x26, 0x86, 0xd5, 0xa5, 0x2b, 0x8d, 0xe3, 0x19, 0x36, 0xf7}, - }, - { /* 15P*/ - addYX: fp.Elt{0x23, 0x69, 0x47, 0x14, 0xf9, 0x9a, 0x50, 0xff, 0x64, 0xd1, 0x50, 0x35, 0xc3, 0x11, 0xd3, 0x19, 0xcf, 0x87, 0xda, 0x30, 0x0b, 0x50, 0xda, 0xc0, 0xe0, 0x25, 0x00, 0xe5, 0x68, 0x93, 0x04, 0xc2, 0xaf, 0xbd, 0x2f, 0x36, 0x5f, 0x47, 0x96, 0x10, 0xa8, 0xbd, 0xe4, 0x88, 0xac, 0x80, 0x52, 0x61, 0x73, 0xe9, 0x63, 0xdd, 0x99, 0xad, 0x20, 0x5b}, - subYX: fp.Elt{0x1b, 0x5e, 0xa2, 0x2a, 0x25, 0x0f, 0x86, 0xc0, 0xb1, 0x2e, 0x0c, 0x13, 0x40, 0x8d, 0xf0, 0xe6, 0x00, 0x55, 0x08, 0xc5, 0x7d, 0xf4, 0xc9, 0x31, 0x25, 0x3a, 0x99, 0x69, 0xdd, 0x67, 0x63, 0x9a, 0xd6, 0x89, 0x2e, 0xa1, 0x19, 0xca, 0x2c, 0xd9, 0x59, 0x5f, 0x5d, 0xc3, 0x6e, 0x62, 0x36, 0x12, 0x59, 0x15, 0xe1, 0xdc, 0xa4, 0xad, 0xc9, 0xd0}, - dt2: fp.Elt{0xbc, 0xea, 0xfc, 0xaf, 0x66, 0x23, 0xb7, 0x39, 0x6b, 0x2a, 0x96, 0xa8, 0x54, 0x43, 0xe9, 0xaa, 0x32, 0x40, 0x63, 0x92, 0x5e, 0xdf, 0x35, 0xc2, 0x9f, 0x24, 0x0c, 0xed, 0xfc, 0xde, 0x73, 0x8f, 0xa7, 0xd5, 0xa3, 0x2b, 0x18, 0x1f, 0xb0, 0xf8, 0xeb, 0x55, 0xd9, 0xc3, 0xfd, 0x28, 0x7c, 0x4f, 0xce, 0x0d, 0xf7, 0xae, 0xc2, 0x83, 0xc3, 0x78}, - }, - { /* 17P*/ - addYX: fp.Elt{0x71, 0xe6, 0x60, 0x93, 0x37, 0xdb, 0x01, 0xa5, 0x4c, 0xba, 0xe8, 0x8e, 0xd5, 0xf9, 0xd3, 0x98, 0xe5, 0xeb, 0xab, 0x3a, 0x15, 0x8b, 0x35, 0x60, 0xbe, 0xe5, 0x9c, 0x2d, 0x10, 0x9b, 0x2e, 0xcf, 0x65, 0x64, 0xea, 0x8f, 0x72, 0xce, 0xf5, 0x18, 0xe5, 0xe2, 0xf0, 0x0e, 0xae, 0x04, 0xec, 0xa0, 0x20, 0x65, 0x63, 0x07, 0xb1, 0x9f, 0x03, 0x97}, - subYX: fp.Elt{0x9e, 0x41, 0x64, 0x30, 0x95, 0x7f, 0x3a, 0x89, 0x7b, 0x0a, 0x79, 0x59, 0x23, 0x9a, 0x3b, 0xfe, 0xa4, 0x13, 0x08, 0xb2, 0x2e, 0x04, 0x50, 0x10, 0x30, 0xcd, 0x2e, 0xa4, 0x91, 0x71, 0x50, 0x36, 0x4a, 0x02, 0xf4, 0x8d, 0xa3, 0x36, 0x1b, 0xf4, 0x52, 0xba, 0x15, 0x04, 0x8b, 0x80, 0x25, 0xd9, 0xae, 0x67, 0x20, 0xd9, 0x88, 0x8f, 0x97, 0xa6}, - dt2: fp.Elt{0xb5, 0xe7, 0x46, 0xbd, 0x55, 0x23, 0xa0, 0x68, 0xc0, 0x12, 0xd9, 0xf1, 0x0a, 0x75, 0xe2, 0xda, 0xf4, 0x6b, 0xca, 0x14, 0xe4, 0x9f, 0x0f, 0xb5, 0x3c, 0xa6, 0xa5, 0xa2, 0x63, 0x94, 0xd1, 0x1c, 0x39, 0x58, 0x57, 0x02, 0x27, 0x98, 0xb6, 0x47, 0xc6, 0x61, 0x4b, 0x5c, 0xab, 0x6f, 0x2d, 0xab, 0xe3, 0xc1, 0x69, 0xf9, 0x12, 0xb0, 0xc8, 0xd5}, - }, - { /* 19P*/ - addYX: fp.Elt{0x19, 0x7d, 0xd5, 0xac, 0x79, 0xa2, 0x82, 0x9b, 0x28, 0x31, 0x22, 0xc0, 0x73, 0x02, 0x76, 0x17, 0x10, 0x70, 0x79, 0x57, 0xc9, 0x84, 0x62, 0x8e, 0x04, 0x04, 0x61, 0x67, 0x08, 0x48, 0xb4, 0x4b, 0xde, 0x53, 0x8c, 0xff, 0x36, 0x1b, 0x62, 0x86, 0x5d, 0xe1, 0x9b, 0xb1, 0xe5, 0xe8, 0x44, 0x64, 0xa1, 0x68, 0x3f, 0xa8, 0x45, 0x52, 0x91, 0xed}, - subYX: fp.Elt{0x42, 0x1a, 0x36, 0x1f, 0x90, 0x15, 0x24, 0x8d, 0x24, 0x80, 0xe6, 0xfe, 0x1e, 0xf0, 0xad, 0xaf, 0x6a, 0x93, 0xf0, 0xa6, 0x0d, 0x5d, 0xea, 0xf6, 0x62, 0x96, 0x7a, 0x05, 0x76, 0x85, 0x74, 0x32, 0xc7, 0xc8, 0x64, 0x53, 0x62, 0xe7, 0x54, 0x84, 0xe0, 0x40, 0x66, 0x19, 0x70, 0x40, 0x95, 0x35, 0x68, 0x64, 0x43, 0xcd, 0xba, 0x29, 0x32, 0xa8}, - dt2: fp.Elt{0x3e, 0xf6, 0xd6, 0xe4, 0x99, 0xeb, 0x20, 0x66, 0x08, 0x2e, 0x26, 0x64, 0xd7, 0x76, 0xf3, 0xb4, 0xc5, 0xa4, 0x35, 0x92, 0xd2, 0x99, 0x70, 0x5a, 0x1a, 0xe9, 0xe9, 0x3d, 0x3b, 0xe1, 0xcd, 0x0e, 0xee, 0x24, 0x13, 0x03, 0x22, 0xd6, 0xd6, 0x72, 0x08, 0x2b, 0xde, 0xfd, 0x93, 0xed, 0x0c, 0x7f, 0x5e, 0x31, 0x22, 0x4d, 0x80, 0x78, 0xc0, 0x48}, - }, - { /* 21P*/ - addYX: fp.Elt{0x8f, 0x72, 0xd2, 0x9e, 0xc4, 0xcd, 0x2c, 0xbf, 0xa8, 0xd3, 0x24, 0x62, 0x28, 0xee, 0x39, 0x0a, 0x19, 0x3a, 0x58, 0xff, 0x21, 0x2e, 0x69, 0x6c, 0x6e, 0x18, 0xd0, 0xcd, 0x61, 0xc1, 0x18, 0x02, 0x5a, 0xe9, 0xe3, 0xef, 0x1f, 0x8e, 0x10, 0xe8, 0x90, 0x2b, 0x48, 0xcd, 0xee, 0x38, 0xbd, 0x3a, 0xca, 0xbc, 0x2d, 0xe2, 0x3a, 0x03, 0x71, 0x02}, - subYX: fp.Elt{0xf8, 0xa4, 0x32, 0x26, 0x66, 0xaf, 0x3b, 0x53, 0xe7, 0xb0, 0x91, 0x92, 0xf5, 0x3c, 0x74, 0xce, 0xf2, 0xdd, 0x68, 0xa9, 0xf4, 0xcd, 0x5f, 0x60, 0xab, 0x71, 0xdf, 0xcd, 0x5c, 0x5d, 0x51, 0x72, 0x3a, 0x96, 0xea, 0xd6, 0xde, 0x54, 0x8e, 0x55, 0x4c, 0x08, 0x4c, 0x60, 0xdd, 0x34, 0xa9, 0x6f, 0xf3, 0x04, 0x02, 0xa8, 0xa6, 0x4e, 0x4d, 0x62}, - dt2: fp.Elt{0x76, 0x4a, 0xae, 0x38, 0x62, 0x69, 0x72, 0xdc, 0xe8, 0x43, 0xbe, 0x1d, 0x61, 0xde, 0x31, 0xc3, 0x42, 0x8f, 0x33, 0x9d, 0xca, 0xc7, 0x9c, 0xec, 0x6a, 0xe2, 0xaa, 0x01, 0x49, 0x78, 0x8d, 0x72, 0x4f, 0x38, 0xea, 0x52, 0xc2, 0xd3, 0xc9, 0x39, 0x71, 0xba, 0xb9, 0x09, 0x9b, 0xa3, 0x7f, 0x45, 0x43, 0x65, 0x36, 0x29, 0xca, 0xe7, 0x5c, 0x5f}, - }, - { /* 23P*/ - addYX: fp.Elt{0x89, 0x42, 0x35, 0x48, 0x6d, 0x74, 0xe5, 0x1f, 0xc3, 0xdd, 0x28, 0x5b, 0x84, 0x41, 0x33, 0x9f, 0x42, 0xf3, 0x1d, 0x5d, 0x15, 0x6d, 0x76, 0x33, 0x36, 0xaf, 0xe9, 0xdd, 0xfa, 0x63, 0x4f, 0x7a, 0x9c, 0xeb, 0x1c, 0x4f, 0x34, 0x65, 0x07, 0x54, 0xbb, 0x4c, 0x8b, 0x62, 0x9d, 0xd0, 0x06, 0x99, 0xb3, 0xe9, 0xda, 0x85, 0x19, 0xb0, 0x3d, 0x3c}, - subYX: fp.Elt{0xbb, 0x99, 0xf6, 0xbf, 0xaf, 0x2c, 0x22, 0x0d, 0x7a, 0xaa, 0x98, 0x6f, 0x01, 0x82, 0x99, 0xcf, 0x88, 0xbd, 0x0e, 0x3a, 0x89, 0xe0, 0x9c, 0x8c, 0x17, 0x20, 0xc4, 0xe0, 0xcf, 0x43, 0x7a, 0xef, 0x0d, 0x9f, 0x87, 0xd4, 0xfb, 0xf2, 0x96, 0xb8, 0x03, 0xe8, 0xcb, 0x5c, 0xec, 0x65, 0x5f, 0x49, 0xa4, 0x7c, 0x85, 0xb4, 0xf6, 0xc7, 0xdb, 0xa3}, - dt2: fp.Elt{0x11, 0xf3, 0x32, 0xa3, 0xa7, 0xb2, 0x7d, 0x51, 0x82, 0x44, 0xeb, 0xa2, 0x7d, 0x72, 0xcb, 0xc6, 0xf6, 0xc7, 0xb2, 0x38, 0x0e, 0x0f, 0x4f, 0x29, 0x00, 0xe4, 0x5b, 0x94, 0x46, 0x86, 0x66, 0xa1, 0x83, 0xb3, 0xeb, 0x15, 0xb6, 0x31, 0x50, 0x28, 0xeb, 0xed, 0x0d, 0x32, 0x39, 0xe9, 0x23, 0x81, 0x99, 0x3e, 0xff, 0x17, 0x4c, 0x11, 0x43, 0xd1}, - }, - { /* 25P*/ - addYX: fp.Elt{0xce, 0xe7, 0xf8, 0x94, 0x8f, 0x96, 0xf8, 0x96, 0xe6, 0x72, 0x20, 0x44, 0x2c, 0xa7, 0xfc, 0xba, 0xc8, 0xe1, 0xbb, 0xc9, 0x16, 0x85, 0xcd, 0x0b, 0xe5, 0xb5, 0x5a, 0x7f, 0x51, 0x43, 0x63, 0x8b, 0x23, 0x8e, 0x1d, 0x31, 0xff, 0x46, 0x02, 0x66, 0xcc, 0x9e, 0x4d, 0xa2, 0xca, 0xe2, 0xc7, 0xfd, 0x22, 0xb1, 0xdb, 0xdf, 0x6f, 0xe6, 0xa5, 0x82}, - subYX: fp.Elt{0xd0, 0xf5, 0x65, 0x40, 0xec, 0x8e, 0x65, 0x42, 0x78, 0xc1, 0x65, 0xe4, 0x10, 0xc8, 0x0b, 0x1b, 0xdd, 0x96, 0x68, 0xce, 0xee, 0x45, 0x55, 0xd8, 0x6e, 0xd3, 0xe6, 0x77, 0x19, 0xae, 0xc2, 0x8d, 0x8d, 0x3e, 0x14, 0x3f, 0x6d, 0x00, 0x2f, 0x9b, 0xd1, 0x26, 0x60, 0x28, 0x0f, 0x3a, 0x47, 0xb3, 0xe6, 0x68, 0x28, 0x24, 0x25, 0xca, 0xc8, 0x06}, - dt2: fp.Elt{0x54, 0xbb, 0x60, 0x92, 0xdb, 0x8f, 0x0f, 0x38, 0xe0, 0xe6, 0xe4, 0xc9, 0xcc, 0x14, 0x62, 0x01, 0xc4, 0x2b, 0x0f, 0xcf, 0xed, 0x7d, 0x8e, 0xa4, 0xd9, 0x73, 0x0b, 0xba, 0x0c, 0xaf, 0x0c, 0xf9, 0xe2, 0xeb, 0x29, 0x2a, 0x53, 0xdf, 0x2c, 0x5a, 0xfa, 0x8f, 0xc1, 0x01, 0xd7, 0xb1, 0x45, 0x73, 0x92, 0x32, 0x83, 0x85, 0x12, 0x74, 0x89, 0x44}, - }, - { /* 27P*/ - addYX: fp.Elt{0x0b, 0x73, 0x3c, 0xc2, 0xb1, 0x2e, 0xe1, 0xa7, 0xf5, 0xc9, 0x7a, 0xfb, 0x3d, 0x2d, 0xac, 0x59, 0xdb, 0xfa, 0x36, 0x11, 0xd1, 0x13, 0x04, 0x51, 0x1d, 0xab, 0x9b, 0x6b, 0x93, 0xfe, 0xda, 0xb0, 0x8e, 0xb4, 0x79, 0x11, 0x21, 0x0f, 0x65, 0xb9, 0xbb, 0x79, 0x96, 0x2a, 0xfd, 0x30, 0xe0, 0xb4, 0x2d, 0x9a, 0x55, 0x25, 0x5d, 0xd4, 0xad, 0x2a}, - subYX: fp.Elt{0x9e, 0xc5, 0x04, 0xfe, 0xec, 0x3c, 0x64, 0x1c, 0xed, 0x95, 0xed, 0xae, 0xaf, 0x5c, 0x6e, 0x08, 0x9e, 0x02, 0x29, 0x59, 0x7e, 0x5f, 0xc4, 0x9a, 0xd5, 0x32, 0x72, 0x86, 0xe1, 0x4e, 0x3c, 0xce, 0x99, 0x69, 0x3b, 0xc4, 0xdd, 0x4d, 0xb7, 0xbb, 0xda, 0x3b, 0x1a, 0x99, 0xaa, 0x62, 0x15, 0xc1, 0xf0, 0xb6, 0x6c, 0xec, 0x56, 0xc1, 0xff, 0x0c}, - dt2: fp.Elt{0x2f, 0xf1, 0x3f, 0x7a, 0x2d, 0x56, 0x19, 0x7f, 0xea, 0xbe, 0x59, 0x2e, 0x13, 0x67, 0x81, 0xfb, 0xdb, 0xc8, 0xa3, 0x1d, 0xd5, 0xe9, 0x13, 0x8b, 0x29, 0xdf, 0xcf, 0x9f, 0xe7, 0xd9, 0x0b, 0x70, 0xd3, 0x15, 0x57, 0x4a, 0xe9, 0x50, 0x12, 0x1b, 0x81, 0x4b, 0x98, 0x98, 0xa8, 0x31, 0x1d, 0x27, 0x47, 0x38, 0xed, 0x57, 0x99, 0x26, 0xb2, 0xee}, - }, - { /* 29P*/ - addYX: fp.Elt{0x1c, 0xb2, 0xb2, 0x67, 0x3b, 0x8b, 0x3d, 0x5a, 0x30, 0x7e, 0x38, 0x7e, 0x3c, 0x3d, 0x28, 0x56, 0x59, 0xd8, 0x87, 0x53, 0x8b, 0xe6, 0x6c, 0x5d, 0xe5, 0x0a, 0x33, 0x10, 0xce, 0xa2, 0x17, 0x0d, 0xe8, 0x76, 0xee, 0x68, 0xa8, 0x72, 0x54, 0xbd, 0xa6, 0x24, 0x94, 0x6e, 0x77, 0xc7, 0x53, 0xb7, 0x89, 0x1c, 0x7a, 0xe9, 0x78, 0x9a, 0x74, 0x5f}, - subYX: fp.Elt{0x76, 0x96, 0x1c, 0xcf, 0x08, 0x55, 0xd8, 0x1e, 0x0d, 0xa3, 0x59, 0x95, 0x32, 0xf4, 0xc2, 0x8e, 0x84, 0x5e, 0x4b, 0x04, 0xda, 0x71, 0xc9, 0x78, 0x52, 0xde, 0x14, 0xb4, 0x31, 0xf4, 0xd4, 0xb8, 0x58, 0xc5, 0x20, 0xe8, 0xdd, 0x15, 0xb5, 0xee, 0xea, 0x61, 0xe0, 0xf5, 0xd6, 0xae, 0x55, 0x59, 0x05, 0x3e, 0xaf, 0x74, 0xac, 0x1f, 0x17, 0x82}, - dt2: fp.Elt{0x59, 0x24, 0xcd, 0xfc, 0x11, 0x7e, 0x85, 0x18, 0x3d, 0x69, 0xf7, 0x71, 0x31, 0x66, 0x98, 0x42, 0x95, 0x00, 0x8c, 0xb2, 0xae, 0x39, 0x7e, 0x85, 0xd6, 0xb0, 0x02, 0xec, 0xce, 0xfc, 0x25, 0xb2, 0xe3, 0x99, 0x8e, 0x5b, 0x61, 0x96, 0x2e, 0x6d, 0x96, 0x57, 0x71, 0xa5, 0x93, 0x41, 0x0e, 0x6f, 0xfd, 0x0a, 0xbf, 0xa9, 0xf7, 0x56, 0xa9, 0x3e}, - }, - { /* 31P*/ - addYX: fp.Elt{0xa2, 0x2e, 0x0c, 0x17, 0x4d, 0xcc, 0x85, 0x2c, 0x18, 0xa0, 0xd2, 0x08, 0xba, 0x11, 0xfa, 0x47, 0x71, 0x86, 0xaf, 0x36, 0x6a, 0xd7, 0xfe, 0xb9, 0xb0, 0x2f, 0x89, 0x98, 0x49, 0x69, 0xf8, 0x6a, 0xad, 0x27, 0x5e, 0x0a, 0x22, 0x60, 0x5e, 0x5d, 0xca, 0x06, 0x51, 0x27, 0x99, 0x29, 0x85, 0x68, 0x98, 0xe1, 0xc4, 0x21, 0x50, 0xa0, 0xe9, 0xc1}, - subYX: fp.Elt{0x4d, 0x70, 0xee, 0x91, 0x92, 0x3f, 0xb7, 0xd3, 0x1d, 0xdb, 0x8d, 0x6e, 0x16, 0xf5, 0x65, 0x7d, 0x5f, 0xb5, 0x6c, 0x59, 0x26, 0x70, 0x4b, 0xf2, 0xfc, 0xe7, 0xdf, 0x86, 0xfe, 0xa5, 0xa7, 0xa6, 0x5d, 0xfb, 0x06, 0xe9, 0xf9, 0xcc, 0xc0, 0x37, 0xcc, 0xd8, 0x09, 0x04, 0xd2, 0xa5, 0x1d, 0xd7, 0xb7, 0xce, 0x92, 0xac, 0x3c, 0xad, 0xfb, 0xae}, - dt2: fp.Elt{0x17, 0xa3, 0x9a, 0xc7, 0x86, 0x2a, 0x51, 0xf7, 0x96, 0x79, 0x49, 0x22, 0x2e, 0x5a, 0x01, 0x5c, 0xb5, 0x95, 0xd4, 0xe8, 0xcb, 0x00, 0xca, 0x2d, 0x55, 0xb6, 0x34, 0x36, 0x0b, 0x65, 0x46, 0xf0, 0x49, 0xfc, 0x87, 0x86, 0xe5, 0xc3, 0x15, 0xdb, 0x32, 0xcd, 0xf2, 0xd3, 0x82, 0x4c, 0xe6, 0x61, 0x8a, 0xaf, 0xd4, 0x9e, 0x0f, 0x5a, 0xf2, 0x81}, - }, - { /* 33P*/ - addYX: fp.Elt{0x88, 0x10, 0xc0, 0xcb, 0xf5, 0x77, 0xae, 0xa5, 0xbe, 0xf6, 0xcd, 0x2e, 0x8b, 0x7e, 0xbd, 0x79, 0x62, 0x4a, 0xeb, 0x69, 0xc3, 0x28, 0xaa, 0x72, 0x87, 0xa9, 0x25, 0x87, 0x46, 0xea, 0x0e, 0x62, 0xa3, 0x6a, 0x1a, 0xe2, 0xba, 0xdc, 0x81, 0x10, 0x33, 0x01, 0xf6, 0x16, 0x89, 0x80, 0xc6, 0xcd, 0xdb, 0xdc, 0xba, 0x0e, 0x09, 0x4a, 0x35, 0x4a}, - subYX: fp.Elt{0x86, 0xb2, 0x2b, 0xd0, 0xb8, 0x4a, 0x6d, 0x66, 0x7b, 0x32, 0xdf, 0x3b, 0x1a, 0x19, 0x1f, 0x63, 0xee, 0x1f, 0x3d, 0x1c, 0x5c, 0x14, 0x60, 0x5b, 0x72, 0x49, 0x07, 0xb1, 0x0d, 0x72, 0xc6, 0x35, 0xf0, 0xbc, 0x5e, 0xda, 0x80, 0x6b, 0x64, 0x5b, 0xe5, 0x34, 0x54, 0x39, 0xdd, 0xe6, 0x3c, 0xcb, 0xe5, 0x29, 0x32, 0x06, 0xc6, 0xb1, 0x96, 0x34}, - dt2: fp.Elt{0x85, 0x86, 0xf5, 0x84, 0x86, 0xe6, 0x77, 0x8a, 0x71, 0x85, 0x0c, 0x4f, 0x81, 0x5b, 0x29, 0x06, 0xb5, 0x2e, 0x26, 0x71, 0x07, 0x78, 0x07, 0xae, 0xbc, 0x95, 0x46, 0xc3, 0x65, 0xac, 0xe3, 0x76, 0x51, 0x7d, 0xd4, 0x85, 0x31, 0xe3, 0x43, 0xf3, 0x1b, 0x7c, 0xf7, 0x6b, 0x2c, 0xf8, 0x1c, 0xbb, 0x8d, 0xca, 0xab, 0x4b, 0xba, 0x7f, 0xa4, 0xe2}, - }, - { /* 35P*/ - addYX: fp.Elt{0x1a, 0xee, 0xe7, 0xa4, 0x8a, 0x9d, 0x53, 0x80, 0xc6, 0xb8, 0x4e, 0xdc, 0x89, 0xe0, 0xc4, 0x2b, 0x60, 0x52, 0x6f, 0xec, 0x81, 0xd2, 0x55, 0x6b, 0x1b, 0x6f, 0x17, 0x67, 0x8e, 0x42, 0x26, 0x4c, 0x65, 0x23, 0x29, 0xc6, 0x7b, 0xcd, 0x9f, 0xad, 0x4b, 0x42, 0xd3, 0x0c, 0x75, 0xc3, 0x8a, 0xf5, 0xbe, 0x9e, 0x55, 0xf7, 0x47, 0x5d, 0xbd, 0x3a}, - subYX: fp.Elt{0x0d, 0xa8, 0x3b, 0xf9, 0xc7, 0x7e, 0xc6, 0x86, 0x94, 0xc0, 0x01, 0xff, 0x27, 0xce, 0x43, 0xac, 0xe5, 0xe1, 0xd2, 0x8d, 0xc1, 0x22, 0x31, 0xbe, 0xe1, 0xaf, 0xf9, 0x4a, 0x78, 0xa1, 0x0c, 0xaa, 0xd4, 0x80, 0xe4, 0x09, 0x8d, 0xfb, 0x1d, 0x52, 0xc8, 0x60, 0x2d, 0xf2, 0xa2, 0x89, 0x02, 0x56, 0x3d, 0x56, 0x27, 0x85, 0xc7, 0xf0, 0x2b, 0x9a}, - dt2: fp.Elt{0x62, 0x7c, 0xc7, 0x6b, 0x2c, 0x9d, 0x0a, 0x7c, 0xe5, 0x50, 0x3c, 0xe6, 0x87, 0x1c, 0x82, 0x30, 0x67, 0x3c, 0x39, 0xb6, 0xa0, 0x31, 0xfb, 0x03, 0x7b, 0xa1, 0x58, 0xdf, 0x12, 0x76, 0x5d, 0x5d, 0x0a, 0x8f, 0x9b, 0x37, 0x32, 0xc3, 0x60, 0x33, 0xea, 0x9f, 0x0a, 0x99, 0xfa, 0x20, 0xd0, 0x33, 0x21, 0xc3, 0x94, 0xd4, 0x86, 0x49, 0x7c, 0x4e}, - }, - { /* 37P*/ - addYX: fp.Elt{0xc7, 0x0c, 0x71, 0xfe, 0x55, 0xd1, 0x95, 0x8f, 0x43, 0xbb, 0x6b, 0x74, 0x30, 0xbd, 0xe8, 0x6f, 0x1c, 0x1b, 0x06, 0x62, 0xf5, 0xfc, 0x65, 0xa0, 0xeb, 0x81, 0x12, 0xc9, 0x64, 0x66, 0x61, 0xde, 0xf3, 0x6d, 0xd4, 0xae, 0x8e, 0xb1, 0x72, 0xe0, 0xcd, 0x37, 0x01, 0x28, 0x52, 0xd7, 0x39, 0x46, 0x0c, 0x55, 0xcf, 0x47, 0x70, 0xef, 0xa1, 0x17}, - subYX: fp.Elt{0x8d, 0x58, 0xde, 0x83, 0x88, 0x16, 0x0e, 0x12, 0x42, 0x03, 0x50, 0x60, 0x4b, 0xdf, 0xbf, 0x95, 0xcc, 0x7d, 0x18, 0x17, 0x7e, 0x31, 0x5d, 0x8a, 0x66, 0xc1, 0xcf, 0x14, 0xea, 0xf4, 0xf4, 0xe5, 0x63, 0x2d, 0x32, 0x86, 0x9b, 0xed, 0x1f, 0x4f, 0x03, 0xaf, 0x33, 0x92, 0xcb, 0xaf, 0x9c, 0x05, 0x0d, 0x47, 0x1b, 0x42, 0xba, 0x13, 0x22, 0x98}, - dt2: fp.Elt{0xb5, 0x48, 0xeb, 0x7d, 0x3d, 0x10, 0x9f, 0x59, 0xde, 0xf8, 0x1c, 0x4f, 0x7d, 0x9d, 0x40, 0x4d, 0x9e, 0x13, 0x24, 0xb5, 0x21, 0x09, 0xb7, 0xee, 0x98, 0x5c, 0x56, 0xbc, 0x5e, 0x2b, 0x78, 0x38, 0x06, 0xac, 0xe3, 0xe0, 0xfa, 0x2e, 0xde, 0x4f, 0xd2, 0xb3, 0xfb, 0x2d, 0x71, 0x84, 0xd1, 0x9d, 0x12, 0x5b, 0x35, 0xc8, 0x03, 0x68, 0x67, 0xc7}, - }, - { /* 39P*/ - addYX: fp.Elt{0xb6, 0x65, 0xfb, 0xa7, 0x06, 0x35, 0xbb, 0xe0, 0x31, 0x8d, 0x91, 0x40, 0x98, 0xab, 0x30, 0xe4, 0xca, 0x12, 0x59, 0x89, 0xed, 0x65, 0x5d, 0x7f, 0xae, 0x69, 0xa0, 0xa4, 0xfa, 0x78, 0xb4, 0xf7, 0xed, 0xae, 0x86, 0x78, 0x79, 0x64, 0x24, 0xa6, 0xd4, 0xe1, 0xf6, 0xd3, 0xa0, 0x89, 0xba, 0x20, 0xf4, 0x54, 0x0d, 0x8f, 0xdb, 0x1a, 0x79, 0xdb}, - subYX: fp.Elt{0xe1, 0x82, 0x0c, 0x4d, 0xde, 0x9f, 0x40, 0xf0, 0xc1, 0xbd, 0x8b, 0xd3, 0x24, 0x03, 0xcd, 0xf2, 0x92, 0x7d, 0xe2, 0x68, 0x7f, 0xf1, 0xbe, 0x69, 0xde, 0x34, 0x67, 0x4c, 0x85, 0x3b, 0xec, 0x98, 0xcc, 0x4d, 0x3e, 0xc0, 0x96, 0x27, 0xe6, 0x75, 0xfc, 0xdf, 0x37, 0xc0, 0x1e, 0x27, 0xe0, 0xf6, 0xc2, 0xbd, 0xbc, 0x3d, 0x9b, 0x39, 0xdc, 0xe2}, - dt2: fp.Elt{0xd8, 0x29, 0xa7, 0x39, 0xe3, 0x9f, 0x2f, 0x0e, 0x4b, 0x24, 0x21, 0x70, 0xef, 0xfd, 0x91, 0xea, 0xbf, 0xe1, 0x72, 0x90, 0xcc, 0xc9, 0x84, 0x0e, 0xad, 0xd5, 0xe6, 0xbb, 0xc5, 0x99, 0x7f, 0xa4, 0xf0, 0x2e, 0xcc, 0x95, 0x64, 0x27, 0x19, 0xd8, 0x4c, 0x27, 0x0d, 0xff, 0xb6, 0x29, 0xe2, 0x6c, 0xfa, 0xbb, 0x4d, 0x9c, 0xbb, 0xaf, 0xa5, 0xec}, - }, - { /* 41P*/ - addYX: fp.Elt{0xd6, 0x33, 0x3f, 0x9f, 0xcf, 0xfd, 0x4c, 0xd1, 0xfe, 0xe5, 0xeb, 0x64, 0x27, 0xae, 0x7a, 0xa2, 0x82, 0x50, 0x6d, 0xaa, 0xe3, 0x5d, 0xe2, 0x48, 0x60, 0xb3, 0x76, 0x04, 0xd9, 0x19, 0xa7, 0xa1, 0x73, 0x8d, 0x38, 0xa9, 0xaf, 0x45, 0xb5, 0xb2, 0x62, 0x9b, 0xf1, 0x35, 0x7b, 0x84, 0x66, 0xeb, 0x06, 0xef, 0xf1, 0xb2, 0x2d, 0x6a, 0x61, 0x15}, - subYX: fp.Elt{0x86, 0x50, 0x42, 0xf7, 0xda, 0x59, 0xb2, 0xcf, 0x0d, 0x3d, 0xee, 0x8e, 0x53, 0x5d, 0xf7, 0x9e, 0x6a, 0x26, 0x2d, 0xc7, 0x8c, 0x8e, 0x18, 0x50, 0x6d, 0xb7, 0x51, 0x4c, 0xa7, 0x52, 0x6e, 0x0e, 0x0a, 0x16, 0x74, 0xb2, 0x81, 0x8b, 0x56, 0x27, 0x22, 0x84, 0xf4, 0x56, 0xc5, 0x06, 0xe1, 0x8b, 0xca, 0x2d, 0xdb, 0x9a, 0xf6, 0x10, 0x9c, 0x51}, - dt2: fp.Elt{0x1f, 0x16, 0xa2, 0x78, 0x96, 0x1b, 0x85, 0x9c, 0x76, 0x49, 0xd4, 0x0f, 0xac, 0xb0, 0xf4, 0xd0, 0x06, 0x2c, 0x7e, 0x6d, 0x6e, 0x8e, 0xc7, 0x9f, 0x18, 0xad, 0xfc, 0x88, 0x0c, 0x0c, 0x09, 0x05, 0x05, 0xa0, 0x79, 0x72, 0x32, 0x72, 0x87, 0x0f, 0x49, 0x87, 0x0c, 0xb4, 0x12, 0xc2, 0x09, 0xf8, 0x9f, 0x30, 0x72, 0xa9, 0x47, 0x13, 0x93, 0x49}, - }, - { /* 43P*/ - addYX: fp.Elt{0xcc, 0xb1, 0x4c, 0xd3, 0xc0, 0x9e, 0x9e, 0x4d, 0x6d, 0x28, 0x0b, 0xa5, 0x94, 0xa7, 0x2e, 0xc2, 0xc7, 0xaf, 0x29, 0x73, 0xc9, 0x68, 0xea, 0x0f, 0x34, 0x37, 0x8d, 0x96, 0x8f, 0x3a, 0x3d, 0x73, 0x1e, 0x6d, 0x9f, 0xcf, 0x8d, 0x83, 0xb5, 0x71, 0xb9, 0xe1, 0x4b, 0x67, 0x71, 0xea, 0xcf, 0x56, 0xe5, 0xeb, 0x72, 0x15, 0x2f, 0x9e, 0xa8, 0xaa}, - subYX: fp.Elt{0xf4, 0x3e, 0x85, 0x1c, 0x1a, 0xef, 0x50, 0xd1, 0xb4, 0x20, 0xb2, 0x60, 0x05, 0x98, 0xfe, 0x47, 0x3b, 0xc1, 0x76, 0xca, 0x2c, 0x4e, 0x5a, 0x42, 0xa3, 0xf7, 0x20, 0xaa, 0x57, 0x39, 0xee, 0x34, 0x1f, 0xe1, 0x68, 0xd3, 0x7e, 0x06, 0xc4, 0x6c, 0xc7, 0x76, 0x2b, 0xe4, 0x1c, 0x48, 0x44, 0xe6, 0xe5, 0x44, 0x24, 0x8d, 0xb3, 0xb6, 0x88, 0x32}, - dt2: fp.Elt{0x18, 0xa7, 0xba, 0xd0, 0x44, 0x6f, 0x33, 0x31, 0x00, 0xf8, 0xf6, 0x12, 0xe3, 0xc5, 0xc7, 0xb5, 0x91, 0x9c, 0x91, 0xb5, 0x75, 0x18, 0x18, 0x8a, 0xab, 0xed, 0x24, 0x11, 0x2e, 0xce, 0x5a, 0x0f, 0x94, 0x5f, 0x2e, 0xca, 0xd3, 0x80, 0xea, 0xe5, 0x34, 0x96, 0x67, 0x8b, 0x6a, 0x26, 0x5e, 0xc8, 0x9d, 0x2c, 0x5e, 0x6c, 0xa2, 0x0c, 0xbf, 0xf0}, - }, - { /* 45P*/ - addYX: fp.Elt{0xb3, 0xbf, 0xa3, 0x85, 0xee, 0xf6, 0x58, 0x02, 0x78, 0xc4, 0x30, 0xd6, 0x57, 0x59, 0x8c, 0x88, 0x08, 0x7c, 0xbc, 0xbe, 0x0a, 0x74, 0xa9, 0xde, 0x69, 0xe7, 0x41, 0xd8, 0xbf, 0x66, 0x8d, 0x3d, 0x28, 0x00, 0x8c, 0x47, 0x65, 0x34, 0xfe, 0x86, 0x9e, 0x6a, 0xf2, 0x41, 0x6a, 0x94, 0xc4, 0x88, 0x75, 0x23, 0x0d, 0x52, 0x69, 0xee, 0x07, 0x89}, - subYX: fp.Elt{0x22, 0x3c, 0xa1, 0x70, 0x58, 0x97, 0x93, 0xbe, 0x59, 0xa8, 0x0b, 0x8a, 0x46, 0x2a, 0x38, 0x1e, 0x08, 0x6b, 0x61, 0x9f, 0xf2, 0x4a, 0x8b, 0x80, 0x68, 0x6e, 0xc8, 0x92, 0x60, 0xf3, 0xc9, 0x89, 0xb2, 0x6d, 0x63, 0xb0, 0xeb, 0x83, 0x15, 0x63, 0x0e, 0x64, 0xbb, 0xb8, 0xfe, 0xb4, 0x81, 0x90, 0x01, 0x28, 0x10, 0xb9, 0x74, 0x6e, 0xde, 0xa4}, - dt2: fp.Elt{0x1a, 0x23, 0x45, 0xa8, 0x6f, 0x4e, 0xa7, 0x4a, 0x0c, 0xeb, 0xb0, 0x43, 0xf9, 0xef, 0x99, 0x60, 0x5b, 0xdb, 0x66, 0xc0, 0x86, 0x71, 0x43, 0xb1, 0x22, 0x7b, 0x1c, 0xe7, 0x8d, 0x09, 0x1d, 0x83, 0x76, 0x9c, 0xd3, 0x5a, 0xdd, 0x42, 0xd9, 0x2f, 0x2d, 0xba, 0x7a, 0xc2, 0xd9, 0x6b, 0xd4, 0x7a, 0xf1, 0xd5, 0x5f, 0x6b, 0x85, 0xbf, 0x0b, 0xf1}, - }, - { /* 47P*/ - addYX: fp.Elt{0xb2, 0x83, 0xfa, 0x1f, 0xd2, 0xce, 0xb6, 0xf2, 0x2d, 0xea, 0x1b, 0xe5, 0x29, 0xa5, 0x72, 0xf9, 0x25, 0x48, 0x4e, 0xf2, 0x50, 0x1b, 0x39, 0xda, 0x34, 0xc5, 0x16, 0x13, 0xb4, 0x0c, 0xa1, 0x00, 0x79, 0x7a, 0xf5, 0x8b, 0xf3, 0x70, 0x14, 0xb6, 0xfc, 0x9a, 0x47, 0x68, 0x1e, 0x42, 0x70, 0x64, 0x2a, 0x84, 0x3e, 0x3d, 0x20, 0x58, 0xf9, 0x6a}, - subYX: fp.Elt{0xd9, 0xee, 0xc0, 0xc4, 0xf5, 0xc2, 0x86, 0xaf, 0x45, 0xd2, 0xd2, 0x87, 0x1b, 0x64, 0xd5, 0xe0, 0x8c, 0x44, 0x00, 0x4f, 0x43, 0x89, 0x04, 0x48, 0x4a, 0x0b, 0xca, 0x94, 0x06, 0x2f, 0x23, 0x5b, 0x6c, 0x8d, 0x44, 0x66, 0x53, 0xf5, 0x5a, 0x20, 0x72, 0x28, 0x58, 0x84, 0xcc, 0x73, 0x22, 0x5e, 0xd1, 0x0b, 0x56, 0x5e, 0x6a, 0xa3, 0x11, 0x91}, - dt2: fp.Elt{0x6e, 0x9f, 0x88, 0xa8, 0x68, 0x2f, 0x12, 0x37, 0x88, 0xfc, 0x92, 0x8f, 0x24, 0xeb, 0x5b, 0x2a, 0x2a, 0xd0, 0x14, 0x40, 0x4c, 0xa9, 0xa4, 0x03, 0x0c, 0x45, 0x48, 0x13, 0xe8, 0xa6, 0x37, 0xab, 0xc0, 0x06, 0x38, 0x6c, 0x96, 0x73, 0x40, 0x6c, 0xc6, 0xea, 0x56, 0xc6, 0xe9, 0x1a, 0x69, 0xeb, 0x7a, 0xd1, 0x33, 0x69, 0x58, 0x2b, 0xea, 0x2f}, - }, - { /* 49P*/ - addYX: fp.Elt{0x58, 0xa8, 0x05, 0x41, 0x00, 0x9d, 0xaa, 0xd9, 0x98, 0xcf, 0xb9, 0x41, 0xb5, 0x4a, 0x8d, 0xe2, 0xe7, 0xc0, 0x72, 0xef, 0xc8, 0x28, 0x6b, 0x68, 0x9d, 0xc9, 0xdf, 0x05, 0x8b, 0xd0, 0x04, 0x74, 0x79, 0x45, 0x52, 0x05, 0xa3, 0x6e, 0x35, 0x3a, 0xe3, 0xef, 0xb2, 0xdc, 0x08, 0x6f, 0x4e, 0x76, 0x85, 0x67, 0xba, 0x23, 0x8f, 0xdd, 0xaf, 0x09}, - subYX: fp.Elt{0xb4, 0x38, 0xc8, 0xff, 0x4f, 0x65, 0x2a, 0x7e, 0xad, 0xb1, 0xc6, 0xb9, 0x3d, 0xd6, 0xf7, 0x14, 0xcf, 0xf6, 0x98, 0x75, 0xbb, 0x47, 0x83, 0x90, 0xe7, 0xe1, 0xf6, 0x14, 0x99, 0x7e, 0xfa, 0xe4, 0x77, 0x24, 0xe3, 0xe7, 0xf0, 0x1e, 0xdb, 0x27, 0x4e, 0x16, 0x04, 0xf2, 0x08, 0x52, 0xfc, 0xec, 0x55, 0xdb, 0x2e, 0x67, 0xe1, 0x94, 0x32, 0x89}, - dt2: fp.Elt{0x00, 0xad, 0x03, 0x35, 0x1a, 0xb1, 0x88, 0xf0, 0xc9, 0x11, 0xe4, 0x12, 0x52, 0x61, 0xfd, 0x8a, 0x1b, 0x6a, 0x0a, 0x4c, 0x42, 0x46, 0x22, 0x0e, 0xa5, 0xf9, 0xe2, 0x50, 0xf2, 0xb2, 0x1f, 0x20, 0x78, 0x10, 0xf6, 0xbf, 0x7f, 0x0c, 0x9c, 0xad, 0x40, 0x8b, 0x82, 0xd4, 0xba, 0x69, 0x09, 0xac, 0x4b, 0x6d, 0xc4, 0x49, 0x17, 0x81, 0x57, 0x3b}, - }, - { /* 51P*/ - addYX: fp.Elt{0x0d, 0xfe, 0xb4, 0x35, 0x11, 0xbd, 0x1d, 0x6b, 0xc2, 0xc5, 0x3b, 0xd2, 0x23, 0x2c, 0x72, 0xe3, 0x48, 0xb1, 0x48, 0x73, 0xfb, 0xa3, 0x21, 0x6e, 0xc0, 0x09, 0x69, 0xac, 0xe1, 0x60, 0xbc, 0x24, 0x03, 0x99, 0x63, 0x0a, 0x00, 0xf0, 0x75, 0xf6, 0x92, 0xc5, 0xd6, 0xdb, 0x51, 0xd4, 0x7d, 0xe6, 0xf4, 0x11, 0x79, 0xd7, 0xc3, 0xaf, 0x48, 0xd0}, - subYX: fp.Elt{0xf4, 0x4f, 0xaf, 0x31, 0xe3, 0x10, 0x89, 0x95, 0xf0, 0x8a, 0xf6, 0x31, 0x9f, 0x48, 0x02, 0xba, 0x42, 0x2b, 0x3c, 0x22, 0x8b, 0xcc, 0x12, 0x98, 0x6e, 0x7a, 0x64, 0x3a, 0xc4, 0xca, 0x32, 0x2a, 0x72, 0xf8, 0x2c, 0xcf, 0x78, 0x5e, 0x7a, 0x75, 0x6e, 0x72, 0x46, 0x48, 0x62, 0x28, 0xac, 0x58, 0x1a, 0xc6, 0x59, 0x88, 0x2a, 0x44, 0x9e, 0x83}, - dt2: fp.Elt{0xb3, 0xde, 0x36, 0xfd, 0xeb, 0x1b, 0xd4, 0x24, 0x1b, 0x08, 0x8c, 0xfe, 0xa9, 0x41, 0xa1, 0x64, 0xf2, 0x6d, 0xdb, 0xf9, 0x94, 0xae, 0x86, 0x71, 0xab, 0x10, 0xbf, 0xa3, 0xb2, 0xa0, 0xdf, 0x10, 0x8c, 0x74, 0xce, 0xb3, 0xfc, 0xdb, 0xba, 0x15, 0xf6, 0x91, 0x7a, 0x9c, 0x36, 0x1e, 0x45, 0x07, 0x3c, 0xec, 0x1a, 0x61, 0x26, 0x93, 0xe3, 0x50}, - }, - { /* 53P*/ - addYX: fp.Elt{0xc5, 0x50, 0xc5, 0x83, 0xb0, 0xbd, 0xd9, 0xf6, 0x6d, 0x15, 0x5e, 0xc1, 0x1a, 0x33, 0xa0, 0xce, 0x13, 0x70, 0x3b, 0xe1, 0x31, 0xc6, 0xc4, 0x02, 0xec, 0x8c, 0xd5, 0x9c, 0x97, 0xd3, 0x12, 0xc4, 0xa2, 0xf9, 0xd5, 0xfb, 0x22, 0x69, 0x94, 0x09, 0x2f, 0x59, 0xce, 0xdb, 0xf2, 0xf2, 0x00, 0xe0, 0xa9, 0x08, 0x44, 0x2e, 0x8b, 0x6b, 0xf5, 0xb3}, - subYX: fp.Elt{0x90, 0xdd, 0xec, 0xa2, 0x65, 0xb7, 0x61, 0xbc, 0xaa, 0x70, 0xa2, 0x15, 0xd8, 0xb0, 0xf8, 0x8e, 0x23, 0x3d, 0x9f, 0x46, 0xa3, 0x29, 0x20, 0xd1, 0xa1, 0x15, 0x81, 0xc6, 0xb6, 0xde, 0xbe, 0x60, 0x63, 0x24, 0xac, 0x15, 0xfb, 0xeb, 0xd3, 0xea, 0x57, 0x13, 0x86, 0x38, 0x1e, 0x22, 0xf4, 0x8c, 0x5d, 0xaf, 0x1b, 0x27, 0x21, 0x4f, 0xa3, 0x63}, - dt2: fp.Elt{0x07, 0x15, 0x87, 0xc4, 0xfd, 0xa1, 0x97, 0x7a, 0x07, 0x1f, 0x56, 0xcc, 0xe3, 0x6a, 0x01, 0x90, 0xce, 0xf9, 0xfa, 0x50, 0xb2, 0xe0, 0x87, 0x8b, 0x6c, 0x63, 0x6c, 0xf6, 0x2a, 0x09, 0xef, 0xef, 0xd2, 0x31, 0x40, 0x25, 0xf6, 0x84, 0xcb, 0xe0, 0xc4, 0x23, 0xc1, 0xcb, 0xe2, 0x02, 0x83, 0x2d, 0xed, 0x74, 0x74, 0x8b, 0xf8, 0x7c, 0x81, 0x18}, - }, - { /* 55P*/ - addYX: fp.Elt{0x9e, 0xe5, 0x59, 0x95, 0x63, 0x2e, 0xac, 0x8b, 0x03, 0x3c, 0xc1, 0x8e, 0xe1, 0x5b, 0x56, 0x3c, 0x16, 0x41, 0xe4, 0xc2, 0x60, 0x0c, 0x6d, 0x65, 0x9f, 0xfc, 0x27, 0x68, 0x43, 0x44, 0x05, 0x12, 0x6c, 0xda, 0x04, 0xef, 0xcf, 0xcf, 0xdc, 0x0a, 0x1a, 0x7f, 0x12, 0xd3, 0xeb, 0x02, 0xb6, 0x04, 0xca, 0xd6, 0xcb, 0xf0, 0x22, 0xba, 0x35, 0x6d}, - subYX: fp.Elt{0x09, 0x6d, 0xf9, 0x64, 0x4c, 0xe6, 0x41, 0xff, 0x01, 0x4d, 0xce, 0x1e, 0xfa, 0x38, 0xa2, 0x25, 0x62, 0xff, 0x03, 0x39, 0x18, 0x91, 0xbb, 0x9d, 0xce, 0x02, 0xf0, 0xf1, 0x3c, 0x55, 0x18, 0xa9, 0xab, 0x4d, 0xd2, 0x35, 0xfd, 0x8d, 0xa9, 0xb2, 0xad, 0xb7, 0x06, 0x6e, 0xc6, 0x69, 0x49, 0xd6, 0x98, 0x98, 0x0b, 0x22, 0x81, 0x6b, 0xbd, 0xa0}, - dt2: fp.Elt{0x22, 0xf4, 0x85, 0x5d, 0x2b, 0xf1, 0x55, 0xa5, 0xd6, 0x27, 0x86, 0x57, 0x12, 0x1f, 0x16, 0x0a, 0x5a, 0x9b, 0xf2, 0x38, 0xb6, 0x28, 0xd8, 0x99, 0x0c, 0x89, 0x1d, 0x7f, 0xca, 0x21, 0x17, 0x1a, 0x0b, 0x02, 0x5f, 0x77, 0x2f, 0x73, 0x30, 0x7c, 0xc8, 0xd7, 0x2b, 0xcc, 0xe7, 0xf3, 0x21, 0xac, 0x53, 0xa7, 0x11, 0x5d, 0xd8, 0x1d, 0x9b, 0xf5}, - }, - { /* 57P*/ - addYX: fp.Elt{0x94, 0x63, 0x5d, 0xef, 0xfd, 0x6d, 0x25, 0x4e, 0x6d, 0x29, 0x03, 0xed, 0x24, 0x28, 0x27, 0x57, 0x47, 0x3e, 0x6a, 0x1a, 0xfe, 0x37, 0xee, 0x5f, 0x83, 0x29, 0x14, 0xfd, 0x78, 0x25, 0x8a, 0xe1, 0x02, 0x38, 0xd8, 0xca, 0x65, 0x55, 0x40, 0x7d, 0x48, 0x2c, 0x7c, 0x7e, 0x60, 0xb6, 0x0c, 0x6d, 0xf7, 0xe8, 0xb3, 0x62, 0x53, 0xd6, 0x9c, 0x2b}, - subYX: fp.Elt{0x47, 0x25, 0x70, 0x62, 0xf5, 0x65, 0x93, 0x62, 0x08, 0xac, 0x59, 0x66, 0xdb, 0x08, 0xd9, 0x1a, 0x19, 0xaf, 0xf4, 0xef, 0x02, 0xa2, 0x78, 0xa9, 0x55, 0x1c, 0xfa, 0x08, 0x11, 0xcb, 0xa3, 0x71, 0x74, 0xb1, 0x62, 0xe7, 0xc7, 0xf3, 0x5a, 0xb5, 0x8b, 0xd4, 0xf6, 0x10, 0x57, 0x79, 0x72, 0x2f, 0x13, 0x86, 0x7b, 0x44, 0x5f, 0x48, 0xfd, 0x88}, - dt2: fp.Elt{0x10, 0x02, 0xcd, 0x05, 0x9a, 0xc3, 0x32, 0x6d, 0x10, 0x3a, 0x74, 0xba, 0x06, 0xc4, 0x3b, 0x34, 0xbc, 0x36, 0xed, 0xa3, 0xba, 0x9a, 0xdb, 0x6d, 0xd4, 0x69, 0x99, 0x97, 0xd0, 0xe4, 0xdd, 0xf5, 0xd4, 0x7c, 0xd3, 0x4e, 0xab, 0xd1, 0x3b, 0xbb, 0xe9, 0xc7, 0x6a, 0x94, 0x25, 0x61, 0xf0, 0x06, 0xc5, 0x12, 0xa8, 0x86, 0xe5, 0x35, 0x46, 0xeb}, - }, - { /* 59P*/ - addYX: fp.Elt{0x9e, 0x95, 0x11, 0xc6, 0xc7, 0xe8, 0xee, 0x5a, 0x26, 0xa0, 0x72, 0x72, 0x59, 0x91, 0x59, 0x16, 0x49, 0x99, 0x7e, 0xbb, 0xd7, 0x15, 0xb4, 0xf2, 0x40, 0xf9, 0x5a, 0x4d, 0xc8, 0xa0, 0xe2, 0x34, 0x7b, 0x34, 0xf3, 0x99, 0xbf, 0xa9, 0xf3, 0x79, 0xc1, 0x1a, 0x0c, 0xf4, 0x86, 0x74, 0x4e, 0xcb, 0xbc, 0x90, 0xad, 0xb6, 0x51, 0x6d, 0xaa, 0x33}, - subYX: fp.Elt{0x9f, 0xd1, 0xc5, 0xa2, 0x6c, 0x24, 0x88, 0x15, 0x71, 0x68, 0xf6, 0x07, 0x45, 0x02, 0xc4, 0x73, 0x7e, 0x75, 0x87, 0xca, 0x7c, 0xf0, 0x92, 0x00, 0x75, 0xd6, 0x5a, 0xdd, 0xe0, 0x64, 0x16, 0x9d, 0x62, 0x80, 0x33, 0x9f, 0xf4, 0x8e, 0x1a, 0x15, 0x1c, 0xd3, 0x0f, 0x4d, 0x4f, 0x62, 0x2d, 0xd7, 0xa5, 0x77, 0xe3, 0xea, 0xf0, 0xfb, 0x1a, 0xdb}, - dt2: fp.Elt{0x6a, 0xa2, 0xb1, 0xaa, 0xfb, 0x5a, 0x32, 0x4e, 0xff, 0x47, 0x06, 0xd5, 0x9a, 0x4f, 0xce, 0x83, 0x5b, 0x82, 0x34, 0x3e, 0x47, 0xb8, 0xf8, 0xe9, 0x7c, 0x67, 0x69, 0x8d, 0x9c, 0xb7, 0xde, 0x57, 0xf4, 0x88, 0x41, 0x56, 0x0c, 0x87, 0x1e, 0xc9, 0x2f, 0x54, 0xbf, 0x5c, 0x68, 0x2c, 0xd9, 0xc4, 0xef, 0x53, 0x73, 0x1e, 0xa6, 0x38, 0x02, 0x10}, - }, - { /* 61P*/ - addYX: fp.Elt{0x08, 0x80, 0x4a, 0xc9, 0xb7, 0xa8, 0x88, 0xd9, 0xfc, 0x6a, 0xc0, 0x3e, 0xc2, 0x33, 0x4d, 0x2b, 0x2a, 0xa3, 0x6d, 0x72, 0x3e, 0xdc, 0x34, 0x68, 0x08, 0xbf, 0x27, 0xef, 0xf4, 0xff, 0xe2, 0x0c, 0x31, 0x0c, 0xa2, 0x0a, 0x1f, 0x65, 0xc1, 0x4c, 0x61, 0xd3, 0x1b, 0xbc, 0x25, 0xb1, 0xd0, 0xd4, 0x89, 0xb2, 0x53, 0xfb, 0x43, 0xa5, 0xaf, 0x04}, - subYX: fp.Elt{0xe3, 0xe1, 0x37, 0xad, 0x58, 0xa9, 0x55, 0x81, 0xee, 0x64, 0x21, 0xb9, 0xf5, 0x4c, 0x35, 0xea, 0x4a, 0xd3, 0x26, 0xaa, 0x90, 0xd4, 0x60, 0x46, 0x09, 0x4b, 0x4a, 0x62, 0xf9, 0xcd, 0xe1, 0xee, 0xbb, 0xc2, 0x09, 0x0b, 0xb0, 0x96, 0x8e, 0x43, 0x77, 0xaf, 0x25, 0x20, 0x5e, 0x47, 0xe4, 0x1d, 0x50, 0x69, 0x74, 0x08, 0xd7, 0xb9, 0x90, 0x13}, - dt2: fp.Elt{0x51, 0x91, 0x95, 0x64, 0x03, 0x16, 0xfd, 0x6e, 0x26, 0x94, 0x6b, 0x61, 0xe7, 0xd9, 0xe0, 0x4a, 0x6d, 0x7c, 0xfa, 0xc0, 0xe2, 0x43, 0x23, 0x53, 0x70, 0xf5, 0x6f, 0x73, 0x8b, 0x81, 0xb0, 0x0c, 0xee, 0x2e, 0x46, 0xf2, 0x8d, 0xa6, 0xfb, 0xb5, 0x1c, 0x33, 0xbf, 0x90, 0x59, 0xc9, 0x7c, 0xb8, 0x6f, 0xad, 0x75, 0x02, 0x90, 0x8e, 0x59, 0x75}, - }, - { /* 63P*/ - addYX: fp.Elt{0x36, 0x4d, 0x77, 0x04, 0xb8, 0x7d, 0x4a, 0xd1, 0xc5, 0xbb, 0x7b, 0x50, 0x5f, 0x8d, 0x9d, 0x62, 0x0f, 0x66, 0x71, 0xec, 0x87, 0xc5, 0x80, 0x82, 0xc8, 0xf4, 0x6a, 0x94, 0x92, 0x5b, 0xb0, 0x16, 0x9b, 0xb2, 0xc9, 0x6f, 0x2b, 0x2d, 0xee, 0x95, 0x73, 0x2e, 0xc2, 0x1b, 0xc5, 0x55, 0x36, 0x86, 0x24, 0xf8, 0x20, 0x05, 0x0d, 0x93, 0xd7, 0x76}, - subYX: fp.Elt{0x7f, 0x01, 0xeb, 0x2e, 0x48, 0x4d, 0x1d, 0xf1, 0x06, 0x7e, 0x7c, 0x2a, 0x43, 0xbf, 0x28, 0xac, 0xe9, 0x58, 0x13, 0xc8, 0xbf, 0x8e, 0xc0, 0xef, 0xe8, 0x4f, 0x46, 0x8a, 0xe7, 0xc0, 0xf6, 0x0f, 0x0a, 0x03, 0x48, 0x91, 0x55, 0x39, 0x2a, 0xe3, 0xdc, 0xf6, 0x22, 0x9d, 0x4d, 0x71, 0x55, 0x68, 0x25, 0x6e, 0x95, 0x52, 0xee, 0x4c, 0xd9, 0x01}, - dt2: fp.Elt{0xac, 0x33, 0x3f, 0x7c, 0x27, 0x35, 0x15, 0x91, 0x33, 0x8d, 0xf9, 0xc4, 0xf4, 0xf3, 0x90, 0x09, 0x75, 0x69, 0x62, 0x9f, 0x61, 0x35, 0x83, 0x92, 0x04, 0xef, 0x96, 0x38, 0x80, 0x9e, 0x88, 0xb3, 0x67, 0x95, 0xbe, 0x79, 0x3c, 0x35, 0xd8, 0xdc, 0xb2, 0x3e, 0x2d, 0xe6, 0x46, 0xbe, 0x81, 0xf3, 0x32, 0x0e, 0x37, 0x23, 0x75, 0x2a, 0x3d, 0xa0}, - }, -} diff --git a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go b/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go deleted file mode 100644 index f6ac5edb..00000000 --- a/vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go +++ /dev/null @@ -1,62 +0,0 @@ -package goldilocks - -import ( - "crypto/subtle" - - mlsb "github.com/cloudflare/circl/math/mlsbset" -) - -const ( - // MLSBRecoding parameters - fxT = 448 - fxV = 2 - fxW = 3 - fx2w1 = 1 << (uint(fxW) - 1) -) - -// ScalarBaseMult returns kG where G is the generator point. -func (e twistCurve) ScalarBaseMult(k *Scalar) *twistPoint { - m, err := mlsb.New(fxT, fxV, fxW) - if err != nil { - panic(err) - } - if m.IsExtended() { - panic("not extended") - } - - var isZero int - if k.IsZero() { - isZero = 1 - } - subtle.ConstantTimeCopy(isZero, k[:], order[:]) - - minusK := *k - isEven := 1 - int(k[0]&0x1) - minusK.Neg() - subtle.ConstantTimeCopy(isEven, k[:], minusK[:]) - c, err := m.Encode(k[:]) - if err != nil { - panic(err) - } - - gP := c.Exp(groupMLSB{}) - P := gP.(*twistPoint) - P.cneg(uint(isEven)) - return P -} - -type groupMLSB struct{} - -func (e groupMLSB) ExtendedEltP() mlsb.EltP { return nil } -func (e groupMLSB) Sqr(x mlsb.EltG) { x.(*twistPoint).Double() } -func (e groupMLSB) Mul(x mlsb.EltG, y mlsb.EltP) { x.(*twistPoint).mixAddZ1(y.(*preTwistPointAffine)) } -func (e groupMLSB) Identity() mlsb.EltG { return twistCurve{}.Identity() } -func (e groupMLSB) NewEltP() mlsb.EltP { return &preTwistPointAffine{} } -func (e groupMLSB) Lookup(a mlsb.EltP, v uint, s, u int32) { - Tabj := &tabFixMult[v] - P := a.(*preTwistPointAffine) - for k := range Tabj { - P.cmov(&Tabj[k], uint(subtle.ConstantTimeEq(int32(k), u))) - } - P.cneg(int(s >> 31)) -} diff --git a/vendor/github.com/cloudflare/circl/internal/conv/conv.go b/vendor/github.com/cloudflare/circl/internal/conv/conv.go deleted file mode 100644 index 3fd0df49..00000000 --- a/vendor/github.com/cloudflare/circl/internal/conv/conv.go +++ /dev/null @@ -1,173 +0,0 @@ -package conv - -import ( - "encoding/binary" - "fmt" - "math/big" - "strings" - - "golang.org/x/crypto/cryptobyte" -) - -// BytesLe2Hex returns an hexadecimal string of a number stored in a -// little-endian order slice x. -func BytesLe2Hex(x []byte) string { - b := &strings.Builder{} - b.Grow(2*len(x) + 2) - fmt.Fprint(b, "0x") - if len(x) == 0 { - fmt.Fprint(b, "00") - } - for i := len(x) - 1; i >= 0; i-- { - fmt.Fprintf(b, "%02x", x[i]) - } - return b.String() -} - -// BytesLe2BigInt converts a little-endian slice x into a big-endian -// math/big.Int. -func BytesLe2BigInt(x []byte) *big.Int { - n := len(x) - b := new(big.Int) - if len(x) > 0 { - y := make([]byte, n) - for i := 0; i < n; i++ { - y[n-1-i] = x[i] - } - b.SetBytes(y) - } - return b -} - -// BytesBe2Uint64Le converts a big-endian slice x to a little-endian slice of uint64. -func BytesBe2Uint64Le(x []byte) []uint64 { - l := len(x) - z := make([]uint64, (l+7)/8) - blocks := l / 8 - for i := 0; i < blocks; i++ { - z[i] = binary.BigEndian.Uint64(x[l-8*(i+1):]) - } - remBytes := l % 8 - for i := 0; i < remBytes; i++ { - z[blocks] |= uint64(x[l-1-8*blocks-i]) << uint(8*i) - } - return z -} - -// BigInt2BytesLe stores a positive big.Int number x into a little-endian slice z. -// The slice is modified if the bitlength of x <= 8*len(z) (padding with zeros). -// If x does not fit in the slice or is negative, z is not modified. -func BigInt2BytesLe(z []byte, x *big.Int) { - xLen := (x.BitLen() + 7) >> 3 - zLen := len(z) - if zLen >= xLen && x.Sign() >= 0 { - y := x.Bytes() - for i := 0; i < xLen; i++ { - z[i] = y[xLen-1-i] - } - for i := xLen; i < zLen; i++ { - z[i] = 0 - } - } -} - -// Uint64Le2BigInt converts a little-endian slice x into a big number. -func Uint64Le2BigInt(x []uint64) *big.Int { - n := len(x) - b := new(big.Int) - var bi big.Int - for i := n - 1; i >= 0; i-- { - bi.SetUint64(x[i]) - b.Lsh(b, 64) - b.Add(b, &bi) - } - return b -} - -// Uint64Le2BytesLe converts a little-endian slice x to a little-endian slice of bytes. -func Uint64Le2BytesLe(x []uint64) []byte { - b := make([]byte, 8*len(x)) - n := len(x) - for i := 0; i < n; i++ { - binary.LittleEndian.PutUint64(b[i*8:], x[i]) - } - return b -} - -// Uint64Le2BytesBe converts a little-endian slice x to a big-endian slice of bytes. -func Uint64Le2BytesBe(x []uint64) []byte { - b := make([]byte, 8*len(x)) - n := len(x) - for i := 0; i < n; i++ { - binary.BigEndian.PutUint64(b[i*8:], x[n-1-i]) - } - return b -} - -// Uint64Le2Hex returns an hexadecimal string of a number stored in a -// little-endian order slice x. -func Uint64Le2Hex(x []uint64) string { - b := new(strings.Builder) - b.Grow(16*len(x) + 2) - fmt.Fprint(b, "0x") - if len(x) == 0 { - fmt.Fprint(b, "00") - } - for i := len(x) - 1; i >= 0; i-- { - fmt.Fprintf(b, "%016x", x[i]) - } - return b.String() -} - -// BigInt2Uint64Le stores a positive big.Int number x into a little-endian slice z. -// The slice is modified if the bitlength of x <= 8*len(z) (padding with zeros). -// If x does not fit in the slice or is negative, z is not modified. -func BigInt2Uint64Le(z []uint64, x *big.Int) { - xLen := (x.BitLen() + 63) >> 6 // number of 64-bit words - zLen := len(z) - if zLen >= xLen && x.Sign() > 0 { - var y, yi big.Int - y.Set(x) - two64 := big.NewInt(1) - two64.Lsh(two64, 64).Sub(two64, big.NewInt(1)) - for i := 0; i < xLen; i++ { - yi.And(&y, two64) - z[i] = yi.Uint64() - y.Rsh(&y, 64) - } - } - for i := xLen; i < zLen; i++ { - z[i] = 0 - } -} - -// MarshalBinary encodes a value into a byte array in a format readable by UnmarshalBinary. -func MarshalBinary(v cryptobyte.MarshalingValue) ([]byte, error) { - const DefaultSize = 32 - b := cryptobyte.NewBuilder(make([]byte, 0, DefaultSize)) - b.AddValue(v) - return b.Bytes() -} - -// MarshalBinaryLen encodes a value into an array of n bytes in a format readable by UnmarshalBinary. -func MarshalBinaryLen(v cryptobyte.MarshalingValue, length uint) ([]byte, error) { - b := cryptobyte.NewFixedBuilder(make([]byte, 0, length)) - b.AddValue(v) - return b.Bytes() -} - -// A UnmarshalingValue decodes itself from a cryptobyte.String and advances the pointer. -// It reports whether the read was successful. -type UnmarshalingValue interface { - Unmarshal(*cryptobyte.String) bool -} - -// UnmarshalBinary recovers a value from a byte array. -// It returns an error if the read was unsuccessful. -func UnmarshalBinary(v UnmarshalingValue, data []byte) (err error) { - s := cryptobyte.String(data) - if data == nil || !v.Unmarshal(&s) || !s.Empty() { - err = fmt.Errorf("cannot read %T from input string", v) - } - return -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/doc.go b/vendor/github.com/cloudflare/circl/internal/sha3/doc.go deleted file mode 100644 index 7e023090..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/doc.go +++ /dev/null @@ -1,62 +0,0 @@ -// 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 sha3 implements the SHA-3 fixed-output-length hash functions and -// the SHAKE variable-output-length hash functions defined by FIPS-202. -// -// Both types of hash function use the "sponge" construction and the Keccak -// permutation. For a detailed specification see http://keccak.noekeon.org/ -// -// # Guidance -// -// If you aren't sure what function you need, use SHAKE256 with at least 64 -// bytes of output. The SHAKE instances are faster than the SHA3 instances; -// the latter have to allocate memory to conform to the hash.Hash interface. -// -// If you need a secret-key MAC (message authentication code), prepend the -// secret key to the input, hash with SHAKE256 and read at least 32 bytes of -// output. -// -// # Security strengths -// -// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security -// strength against preimage attacks of x bits. Since they only produce "x" -// bits of output, their collision-resistance is only "x/2" bits. -// -// The SHAKE-256 and -128 functions have a generic security strength of 256 and -// 128 bits against all attacks, provided that at least 2x bits of their output -// is used. Requesting more than 64 or 32 bytes of output, respectively, does -// not increase the collision-resistance of the SHAKE functions. -// -// # The sponge construction -// -// A sponge builds a pseudo-random function from a public pseudo-random -// permutation, by applying the permutation to a state of "rate + capacity" -// bytes, but hiding "capacity" of the bytes. -// -// A sponge starts out with a zero state. To hash an input using a sponge, up -// to "rate" bytes of the input are XORed into the sponge's state. The sponge -// is then "full" and the permutation is applied to "empty" it. This process is -// repeated until all the input has been "absorbed". The input is then padded. -// The digest is "squeezed" from the sponge in the same way, except that output -// is copied out instead of input being XORed in. -// -// A sponge is parameterized by its generic security strength, which is equal -// to half its capacity; capacity + rate is equal to the permutation's width. -// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means -// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. -// -// # Recommendations -// -// The SHAKE functions are recommended for most new uses. They can produce -// output of arbitrary length. SHAKE256, with an output length of at least -// 64 bytes, provides 256-bit security against all attacks. The Keccak team -// recommends it for most applications upgrading from SHA2-512. (NIST chose a -// much stronger, but much slower, sponge instance for SHA3-512.) -// -// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. -// They produce output of the same length, with the same security strengths -// against all attacks. This means, in particular, that SHA3-256 only has -// 128-bit collision resistance, because its output length is 32 bytes. -package sha3 diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/hashes.go b/vendor/github.com/cloudflare/circl/internal/sha3/hashes.go deleted file mode 100644 index 7d2365a7..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/hashes.go +++ /dev/null @@ -1,69 +0,0 @@ -// 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 sha3 - -// This file provides functions for creating instances of the SHA-3 -// and SHAKE hash functions, as well as utility functions for hashing -// bytes. - -// New224 creates a new SHA3-224 hash. -// Its generic security strength is 224 bits against preimage attacks, -// and 112 bits against collision attacks. -func New224() State { - return State{rate: 144, outputLen: 28, dsbyte: 0x06} -} - -// New256 creates a new SHA3-256 hash. -// Its generic security strength is 256 bits against preimage attacks, -// and 128 bits against collision attacks. -func New256() State { - return State{rate: 136, outputLen: 32, dsbyte: 0x06} -} - -// New384 creates a new SHA3-384 hash. -// Its generic security strength is 384 bits against preimage attacks, -// and 192 bits against collision attacks. -func New384() State { - return State{rate: 104, outputLen: 48, dsbyte: 0x06} -} - -// New512 creates a new SHA3-512 hash. -// Its generic security strength is 512 bits against preimage attacks, -// and 256 bits against collision attacks. -func New512() State { - return State{rate: 72, outputLen: 64, dsbyte: 0x06} -} - -// Sum224 returns the SHA3-224 digest of the data. -func Sum224(data []byte) (digest [28]byte) { - h := New224() - _, _ = h.Write(data) - h.Sum(digest[:0]) - return -} - -// Sum256 returns the SHA3-256 digest of the data. -func Sum256(data []byte) (digest [32]byte) { - h := New256() - _, _ = h.Write(data) - h.Sum(digest[:0]) - return -} - -// Sum384 returns the SHA3-384 digest of the data. -func Sum384(data []byte) (digest [48]byte) { - h := New384() - _, _ = h.Write(data) - h.Sum(digest[:0]) - return -} - -// Sum512 returns the SHA3-512 digest of the data. -func Sum512(data []byte) (digest [64]byte) { - h := New512() - _, _ = h.Write(data) - h.Sum(digest[:0]) - return -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go b/vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go deleted file mode 100644 index 1755fd1e..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go +++ /dev/null @@ -1,391 +0,0 @@ -// 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 sha3 - -// KeccakF1600 applies the Keccak permutation to a 1600b-wide -// state represented as a slice of 25 uint64s. -// If turbo is true, applies the 12-round variant instead of the -// regular 24-round variant. -// nolint:funlen -func KeccakF1600(a *[25]uint64, turbo bool) { - // Implementation translated from Keccak-inplace.c - // in the keccak reference code. - var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 - - i := 0 - - if turbo { - i = 12 - } - - for ; i < 24; i += 4 { - // Combines the 5 steps in each round into 2 steps. - // Unrolls 4 rounds per loop and spreads some steps across rounds. - - // Round 1 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[6] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[12] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[18] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[24] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i] - a[6] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[16] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[22] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[3] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[10] = bc0 ^ (bc2 &^ bc1) - a[16] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[1] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[7] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[19] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[20] = bc0 ^ (bc2 &^ bc1) - a[1] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[11] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[23] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[4] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[5] = bc0 ^ (bc2 &^ bc1) - a[11] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[2] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[8] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[14] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[15] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - // Round 2 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[16] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[7] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[23] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[14] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+1] - a[16] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[11] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[2] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[18] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[20] = bc0 ^ (bc2 &^ bc1) - a[11] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[6] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[22] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[4] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[15] = bc0 ^ (bc2 &^ bc1) - a[6] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[1] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[8] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[24] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[10] = bc0 ^ (bc2 &^ bc1) - a[1] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[12] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[3] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[19] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[5] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - // Round 3 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[11] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[22] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[8] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[19] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+2] - a[11] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[1] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[12] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[23] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[15] = bc0 ^ (bc2 &^ bc1) - a[1] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[16] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[2] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[24] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[5] = bc0 ^ (bc2 &^ bc1) - a[16] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[6] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[3] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[14] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[20] = bc0 ^ (bc2 &^ bc1) - a[6] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[7] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[18] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[4] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[10] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - // Round 4 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[1] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[2] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[3] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[4] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+3] - a[1] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[6] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[7] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[8] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[5] = bc0 ^ (bc2 &^ bc1) - a[6] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[11] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[12] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[14] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[10] = bc0 ^ (bc2 &^ bc1) - a[11] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[16] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[18] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[19] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[15] = bc0 ^ (bc2 &^ bc1) - a[16] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[22] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[23] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[24] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[20] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - } -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/rc.go b/vendor/github.com/cloudflare/circl/internal/sha3/rc.go deleted file mode 100644 index 6a3df42f..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/rc.go +++ /dev/null @@ -1,29 +0,0 @@ -package sha3 - -// RC stores the round constants for use in the ι step. -var RC = [24]uint64{ - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/sha3.go b/vendor/github.com/cloudflare/circl/internal/sha3/sha3.go deleted file mode 100644 index a0df5aa6..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/sha3.go +++ /dev/null @@ -1,200 +0,0 @@ -// 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 sha3 - -// spongeDirection indicates the direction bytes are flowing through the sponge. -type spongeDirection int - -const ( - // spongeAbsorbing indicates that the sponge is absorbing input. - spongeAbsorbing spongeDirection = iota - // spongeSqueezing indicates that the sponge is being squeezed. - spongeSqueezing -) - -const ( - // maxRate is the maximum size of the internal buffer. SHAKE-256 - // currently needs the largest buffer. - maxRate = 168 -) - -func (d *State) buf() []byte { - return d.storage.asBytes()[d.bufo:d.bufe] -} - -type State struct { - // Generic sponge components. - a [25]uint64 // main state of the hash - rate int // the number of bytes of state to use - - bufo int // offset of buffer in storage - bufe int // end of buffer in storage - - // dsbyte contains the "domain separation" bits and the first bit of - // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the - // SHA-3 and SHAKE functions by appending bitstrings to the message. - // Using a little-endian bit-ordering convention, these are "01" for SHA-3 - // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the - // padding rule from section 5.1 is applied to pad the message to a multiple - // of the rate, which involves adding a "1" bit, zero or more "0" bits, and - // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, - // giving 00000110b (0x06) and 00011111b (0x1f). - // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf - // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and - // Extendable-Output Functions (May 2014)" - dsbyte byte - - storage storageBuf - - // Specific to SHA-3 and SHAKE. - outputLen int // the default output size in bytes - state spongeDirection // whether the sponge is absorbing or squeezing - turbo bool // Whether we're using 12 rounds instead of 24 -} - -// BlockSize returns the rate of sponge underlying this hash function. -func (d *State) BlockSize() int { return d.rate } - -// Size returns the output size of the hash function in bytes. -func (d *State) Size() int { return d.outputLen } - -// Reset clears the internal state by zeroing the sponge state and -// the byte buffer, and setting Sponge.state to absorbing. -func (d *State) Reset() { - // Zero the permutation's state. - for i := range d.a { - d.a[i] = 0 - } - d.state = spongeAbsorbing - d.bufo = 0 - d.bufe = 0 -} - -func (d *State) clone() *State { - ret := *d - return &ret -} - -// permute applies the KeccakF-1600 permutation. It handles -// any input-output buffering. -func (d *State) permute() { - switch d.state { - case spongeAbsorbing: - // If we're absorbing, we need to xor the input into the state - // before applying the permutation. - xorIn(d, d.buf()) - d.bufe = 0 - d.bufo = 0 - KeccakF1600(&d.a, d.turbo) - case spongeSqueezing: - // If we're squeezing, we need to apply the permutation before - // copying more output. - KeccakF1600(&d.a, d.turbo) - d.bufe = d.rate - d.bufo = 0 - copyOut(d, d.buf()) - } -} - -// pads appends the domain separation bits in dsbyte, applies -// the multi-bitrate 10..1 padding rule, and permutes the state. -func (d *State) padAndPermute(dsbyte byte) { - // Pad with this instance's domain-separator bits. We know that there's - // at least one byte of space in d.buf() because, if it were full, - // permute would have been called to empty it. dsbyte also contains the - // first one bit for the padding. See the comment in the state struct. - zerosStart := d.bufe + 1 - d.bufe = d.rate - buf := d.buf() - buf[zerosStart-1] = dsbyte - for i := zerosStart; i < d.rate; i++ { - buf[i] = 0 - } - // This adds the final one bit for the padding. Because of the way that - // bits are numbered from the LSB upwards, the final bit is the MSB of - // the last byte. - buf[d.rate-1] ^= 0x80 - // Apply the permutation - d.permute() - d.state = spongeSqueezing - d.bufe = d.rate - copyOut(d, buf) -} - -// Write absorbs more data into the hash's state. It produces an error -// if more data is written to the ShakeHash after writing -func (d *State) Write(p []byte) (written int, err error) { - if d.state != spongeAbsorbing { - panic("sha3: write to sponge after read") - } - written = len(p) - - for len(p) > 0 { - bufl := d.bufe - d.bufo - if bufl == 0 && len(p) >= d.rate { - // The fast path; absorb a full "rate" bytes of input and apply the permutation. - xorIn(d, p[:d.rate]) - p = p[d.rate:] - KeccakF1600(&d.a, d.turbo) - } else { - // The slow path; buffer the input until we can fill the sponge, and then xor it in. - todo := d.rate - bufl - if todo > len(p) { - todo = len(p) - } - d.bufe += todo - buf := d.buf() - copy(buf[bufl:], p[:todo]) - p = p[todo:] - - // If the sponge is full, apply the permutation. - if d.bufe == d.rate { - d.permute() - } - } - } - - return written, nil -} - -// Read squeezes an arbitrary number of bytes from the sponge. -func (d *State) Read(out []byte) (n int, err error) { - // If we're still absorbing, pad and apply the permutation. - if d.state == spongeAbsorbing { - d.padAndPermute(d.dsbyte) - } - - n = len(out) - - // Now, do the squeezing. - for len(out) > 0 { - buf := d.buf() - n := copy(out, buf) - d.bufo += n - out = out[n:] - - // Apply the permutation if we've squeezed the sponge dry. - if d.bufo == d.bufe { - d.permute() - } - } - - return -} - -// Sum applies padding to the hash state and then squeezes out the desired -// number of output bytes. -func (d *State) Sum(in []byte) []byte { - // Make a copy of the original hash so that caller can keep writing - // and summing. - dup := d.clone() - hash := make([]byte, dup.outputLen) - _, _ = dup.Read(hash) - return append(in, hash...) -} - -func (d *State) IsAbsorbing() bool { - return d.state == spongeAbsorbing -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s b/vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s deleted file mode 100644 index 8a4458f6..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 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. - -// +build !gccgo,!appengine - -#include "textflag.h" - -// func kimd(function code, chain *[200]byte, src []byte) -TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40 - MOVD function+0(FP), R0 - MOVD chain+8(FP), R1 - LMG src+16(FP), R2, R3 // R2=base, R3=len - -continue: - WORD $0xB93E0002 // KIMD --, R2 - BVS continue // continue if interrupted - MOVD $0, R0 // reset R0 for pre-go1.8 compilers - RET - -// func klmd(function code, chain *[200]byte, dst, src []byte) -TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64 - // TODO: SHAKE support - MOVD function+0(FP), R0 - MOVD chain+8(FP), R1 - LMG dst+16(FP), R2, R3 // R2=base, R3=len - LMG src+40(FP), R4, R5 // R4=base, R5=len - -continue: - WORD $0xB93F0024 // KLMD R2, R4 - BVS continue // continue if interrupted - MOVD $0, R0 // reset R0 for pre-go1.8 compilers - RET diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/shake.go b/vendor/github.com/cloudflare/circl/internal/sha3/shake.go deleted file mode 100644 index 77817f75..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/shake.go +++ /dev/null @@ -1,119 +0,0 @@ -// 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 sha3 - -// This file defines the ShakeHash interface, and provides -// functions for creating SHAKE and cSHAKE instances, as well as utility -// functions for hashing bytes to arbitrary-length output. -// -// -// SHAKE implementation is based on FIPS PUB 202 [1] -// cSHAKE implementations is based on NIST SP 800-185 [2] -// -// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf -// [2] https://doi.org/10.6028/NIST.SP.800-185 - -import ( - "io" -) - -// ShakeHash defines the interface to hash functions that -// support arbitrary-length output. -type ShakeHash interface { - // Write absorbs more data into the hash's state. It panics if input is - // written to it after output has been read from it. - io.Writer - - // Read reads more output from the hash; reading affects the hash's - // state. (ShakeHash.Read is thus very different from Hash.Sum) - // It never returns an error. - io.Reader - - // Clone returns a copy of the ShakeHash in its current state. - Clone() ShakeHash - - // Reset resets the ShakeHash to its initial state. - Reset() -} - -// Consts for configuring initial SHA-3 state -const ( - dsbyteShake = 0x1f - rate128 = 168 - rate256 = 136 -) - -// Clone returns copy of SHAKE context within its current state. -func (d *State) Clone() ShakeHash { - return d.clone() -} - -// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. -// Its generic security strength is 128 bits against all attacks if at -// least 32 bytes of its output are used. -func NewShake128() State { - return State{rate: rate128, dsbyte: dsbyteShake} -} - -// NewTurboShake128 creates a new TurboSHAKE128 variable-output-length ShakeHash. -// Its generic security strength is 128 bits against all attacks if at -// least 32 bytes of its output are used. -// D is the domain separation byte and must be between 0x01 and 0x7f inclusive. -func NewTurboShake128(D byte) State { - if D == 0 || D > 0x7f { - panic("turboshake: D out of range") - } - return State{rate: rate128, dsbyte: D, turbo: true} -} - -// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. -// Its generic security strength is 256 bits against all attacks if -// at least 64 bytes of its output are used. -func NewShake256() State { - return State{rate: rate256, dsbyte: dsbyteShake} -} - -// NewTurboShake256 creates a new TurboSHAKE256 variable-output-length ShakeHash. -// Its generic security strength is 256 bits against all attacks if -// at least 64 bytes of its output are used. -// D is the domain separation byte and must be between 0x01 and 0x7f inclusive. -func NewTurboShake256(D byte) State { - if D == 0 || D > 0x7f { - panic("turboshake: D out of range") - } - return State{rate: rate256, dsbyte: D, turbo: true} -} - -// ShakeSum128 writes an arbitrary-length digest of data into hash. -func ShakeSum128(hash, data []byte) { - h := NewShake128() - _, _ = h.Write(data) - _, _ = h.Read(hash) -} - -// ShakeSum256 writes an arbitrary-length digest of data into hash. -func ShakeSum256(hash, data []byte) { - h := NewShake256() - _, _ = h.Write(data) - _, _ = h.Read(hash) -} - -// TurboShakeSum128 writes an arbitrary-length digest of data into hash. -func TurboShakeSum128(hash, data []byte, D byte) { - h := NewTurboShake128(D) - _, _ = h.Write(data) - _, _ = h.Read(hash) -} - -// TurboShakeSum256 writes an arbitrary-length digest of data into hash. -func TurboShakeSum256(hash, data []byte, D byte) { - h := NewTurboShake256(D) - _, _ = h.Write(data) - _, _ = h.Read(hash) -} - -func (d *State) SwitchDS(D byte) { - d.dsbyte = D -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/xor.go b/vendor/github.com/cloudflare/circl/internal/sha3/xor.go deleted file mode 100644 index 1e213374..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/xor.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2015 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 (!amd64 && !386 && !ppc64le) || appengine -// +build !amd64,!386,!ppc64le appengine - -package sha3 - -// A storageBuf is an aligned array of maxRate bytes. -type storageBuf [maxRate]byte - -func (b *storageBuf) asBytes() *[maxRate]byte { - return (*[maxRate]byte)(b) -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go b/vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go deleted file mode 100644 index 2b0c6617..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2015 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 (!amd64 || appengine) && (!386 || appengine) && (!ppc64le || appengine) -// +build !amd64 appengine -// +build !386 appengine -// +build !ppc64le appengine - -package sha3 - -import "encoding/binary" - -// xorIn xors the bytes in buf into the state; it -// makes no non-portable assumptions about memory layout -// or alignment. -func xorIn(d *State, buf []byte) { - n := len(buf) / 8 - - for i := 0; i < n; i++ { - a := binary.LittleEndian.Uint64(buf) - d.a[i] ^= a - buf = buf[8:] - } -} - -// copyOut copies ulint64s to a byte buffer. -func copyOut(d *State, b []byte) { - for i := 0; len(b) >= 8; i++ { - binary.LittleEndian.PutUint64(b, d.a[i]) - b = b[8:] - } -} diff --git a/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go b/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go deleted file mode 100644 index 052fc8d3..00000000 --- a/vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2015 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 (amd64 || 386 || ppc64le) && !appengine -// +build amd64 386 ppc64le -// +build !appengine - -package sha3 - -import "unsafe" - -// A storageBuf is an aligned array of maxRate bytes. -type storageBuf [maxRate / 8]uint64 - -func (b *storageBuf) asBytes() *[maxRate]byte { - return (*[maxRate]byte)(unsafe.Pointer(b)) -} - -// xorInuses unaligned reads and writes to update d.a to contain d.a -// XOR buf. -func xorIn(d *State, buf []byte) { - n := len(buf) - bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8] - if n >= 72 { - d.a[0] ^= bw[0] - d.a[1] ^= bw[1] - d.a[2] ^= bw[2] - d.a[3] ^= bw[3] - d.a[4] ^= bw[4] - d.a[5] ^= bw[5] - d.a[6] ^= bw[6] - d.a[7] ^= bw[7] - d.a[8] ^= bw[8] - } - if n >= 104 { - d.a[9] ^= bw[9] - d.a[10] ^= bw[10] - d.a[11] ^= bw[11] - d.a[12] ^= bw[12] - } - if n >= 136 { - d.a[13] ^= bw[13] - d.a[14] ^= bw[14] - d.a[15] ^= bw[15] - d.a[16] ^= bw[16] - } - if n >= 144 { - d.a[17] ^= bw[17] - } - if n >= 168 { - d.a[18] ^= bw[18] - d.a[19] ^= bw[19] - d.a[20] ^= bw[20] - } -} - -func copyOut(d *State, buf []byte) { - ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) - copy(buf, ab[:]) -} diff --git a/vendor/github.com/cloudflare/circl/math/fp25519/fp.go b/vendor/github.com/cloudflare/circl/math/fp25519/fp.go deleted file mode 100644 index 57a50ff5..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp25519/fp.go +++ /dev/null @@ -1,205 +0,0 @@ -// Package fp25519 provides prime field arithmetic over GF(2^255-19). -package fp25519 - -import ( - "errors" - - "github.com/cloudflare/circl/internal/conv" -) - -// Size in bytes of an element. -const Size = 32 - -// Elt is a prime field element. -type Elt [Size]byte - -func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) } - -// p is the prime modulus 2^255-19. -var p = Elt{ - 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, -} - -// P returns the prime modulus 2^255-19. -func P() Elt { return p } - -// ToBytes stores in b the little-endian byte representation of x. -func ToBytes(b []byte, x *Elt) error { - if len(b) != Size { - return errors.New("wrong size") - } - Modp(x) - copy(b, x[:]) - return nil -} - -// IsZero returns true if x is equal to 0. -func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} } - -// SetOne assigns x=1. -func SetOne(x *Elt) { *x = Elt{}; x[0] = 1 } - -// Neg calculates z = -x. -func Neg(z, x *Elt) { Sub(z, &p, x) } - -// InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue, which is -// indicated by returning isQR = true. Otherwise, when x/y is a quadratic -// non-residue, z will have an undetermined value and isQR = false. -func InvSqrt(z, x, y *Elt) (isQR bool) { - sqrtMinusOne := &Elt{ - 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4, - 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f, - 0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b, - 0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b, - } - t0, t1, t2, t3 := &Elt{}, &Elt{}, &Elt{}, &Elt{} - - Mul(t0, x, y) // t0 = u*v - Sqr(t1, y) // t1 = v^2 - Mul(t2, t0, t1) // t2 = u*v^3 - Sqr(t0, t1) // t0 = v^4 - Mul(t1, t0, t2) // t1 = u*v^7 - - var Tab [4]*Elt - Tab[0] = &Elt{} - Tab[1] = &Elt{} - Tab[2] = t3 - Tab[3] = t1 - - *Tab[0] = *t1 - Sqr(Tab[0], Tab[0]) - Sqr(Tab[1], Tab[0]) - Sqr(Tab[1], Tab[1]) - Mul(Tab[1], Tab[1], Tab[3]) - Mul(Tab[0], Tab[0], Tab[1]) - Sqr(Tab[0], Tab[0]) - Mul(Tab[0], Tab[0], Tab[1]) - Sqr(Tab[1], Tab[0]) - for i := 0; i < 4; i++ { - Sqr(Tab[1], Tab[1]) - } - Mul(Tab[1], Tab[1], Tab[0]) - Sqr(Tab[2], Tab[1]) - for i := 0; i < 4; i++ { - Sqr(Tab[2], Tab[2]) - } - Mul(Tab[2], Tab[2], Tab[0]) - Sqr(Tab[1], Tab[2]) - for i := 0; i < 14; i++ { - Sqr(Tab[1], Tab[1]) - } - Mul(Tab[1], Tab[1], Tab[2]) - Sqr(Tab[2], Tab[1]) - for i := 0; i < 29; i++ { - Sqr(Tab[2], Tab[2]) - } - Mul(Tab[2], Tab[2], Tab[1]) - Sqr(Tab[1], Tab[2]) - for i := 0; i < 59; i++ { - Sqr(Tab[1], Tab[1]) - } - Mul(Tab[1], Tab[1], Tab[2]) - for i := 0; i < 5; i++ { - Sqr(Tab[1], Tab[1]) - } - Mul(Tab[1], Tab[1], Tab[0]) - Sqr(Tab[2], Tab[1]) - for i := 0; i < 124; i++ { - Sqr(Tab[2], Tab[2]) - } - Mul(Tab[2], Tab[2], Tab[1]) - Sqr(Tab[2], Tab[2]) - Sqr(Tab[2], Tab[2]) - Mul(Tab[2], Tab[2], Tab[3]) - - Mul(z, t3, t2) // z = xy^(p+3)/8 = xy^3*(xy^7)^(p-5)/8 - // Checking whether y z^2 == x - Sqr(t0, z) // t0 = z^2 - Mul(t0, t0, y) // t0 = yz^2 - Sub(t1, t0, x) // t1 = t0-u - Add(t2, t0, x) // t2 = t0+u - if IsZero(t1) { - return true - } else if IsZero(t2) { - Mul(z, z, sqrtMinusOne) // z = z*sqrt(-1) - return true - } else { - return false - } -} - -// Inv calculates z = 1/x mod p. -func Inv(z, x *Elt) { - x0, x1, x2 := &Elt{}, &Elt{}, &Elt{} - Sqr(x1, x) - Sqr(x0, x1) - Sqr(x0, x0) - Mul(x0, x0, x) - Mul(z, x0, x1) - Sqr(x1, z) - Mul(x0, x0, x1) - Sqr(x1, x0) - for i := 0; i < 4; i++ { - Sqr(x1, x1) - } - Mul(x0, x0, x1) - Sqr(x1, x0) - for i := 0; i < 9; i++ { - Sqr(x1, x1) - } - Mul(x1, x1, x0) - Sqr(x2, x1) - for i := 0; i < 19; i++ { - Sqr(x2, x2) - } - Mul(x2, x2, x1) - for i := 0; i < 10; i++ { - Sqr(x2, x2) - } - Mul(x2, x2, x0) - Sqr(x0, x2) - for i := 0; i < 49; i++ { - Sqr(x0, x0) - } - Mul(x0, x0, x2) - Sqr(x1, x0) - for i := 0; i < 99; i++ { - Sqr(x1, x1) - } - Mul(x1, x1, x0) - for i := 0; i < 50; i++ { - Sqr(x1, x1) - } - Mul(x1, x1, x2) - for i := 0; i < 5; i++ { - Sqr(x1, x1) - } - Mul(z, z, x1) -} - -// Cmov assigns y to x if n is 1. -func Cmov(x, y *Elt, n uint) { cmov(x, y, n) } - -// Cswap interchanges x and y if n is 1. -func Cswap(x, y *Elt, n uint) { cswap(x, y, n) } - -// Add calculates z = x+y mod p. -func Add(z, x, y *Elt) { add(z, x, y) } - -// Sub calculates z = x-y mod p. -func Sub(z, x, y *Elt) { sub(z, x, y) } - -// AddSub calculates (x,y) = (x+y mod p, x-y mod p). -func AddSub(x, y *Elt) { addsub(x, y) } - -// Mul calculates z = x*y mod p. -func Mul(z, x, y *Elt) { mul(z, x, y) } - -// Sqr calculates z = x^2 mod p. -func Sqr(z, x *Elt) { sqr(z, x) } - -// Modp ensures that z is between [0,p-1]. -func Modp(z *Elt) { modp(z) } diff --git a/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go b/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go deleted file mode 100644 index 057f0d28..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go +++ /dev/null @@ -1,45 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -package fp25519 - -import ( - "golang.org/x/sys/cpu" -) - -var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX - -var _ = hasBmi2Adx - -func cmov(x, y *Elt, n uint) { cmovAmd64(x, y, n) } -func cswap(x, y *Elt, n uint) { cswapAmd64(x, y, n) } -func add(z, x, y *Elt) { addAmd64(z, x, y) } -func sub(z, x, y *Elt) { subAmd64(z, x, y) } -func addsub(x, y *Elt) { addsubAmd64(x, y) } -func mul(z, x, y *Elt) { mulAmd64(z, x, y) } -func sqr(z, x *Elt) { sqrAmd64(z, x) } -func modp(z *Elt) { modpAmd64(z) } - -//go:noescape -func cmovAmd64(x, y *Elt, n uint) - -//go:noescape -func cswapAmd64(x, y *Elt, n uint) - -//go:noescape -func addAmd64(z, x, y *Elt) - -//go:noescape -func subAmd64(z, x, y *Elt) - -//go:noescape -func addsubAmd64(x, y *Elt) - -//go:noescape -func mulAmd64(z, x, y *Elt) - -//go:noescape -func sqrAmd64(z, x *Elt) - -//go:noescape -func modpAmd64(z *Elt) diff --git a/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h b/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h deleted file mode 100644 index b884b584..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h +++ /dev/null @@ -1,351 +0,0 @@ -// This code was imported from https://github.com/armfazh/rfc7748_precomputed - -// CHECK_BMI2ADX triggers bmi2adx if supported, -// otherwise it fallbacks to legacy code. -#define CHECK_BMI2ADX(label, legacy, bmi2adx) \ - CMPB ·hasBmi2Adx(SB), $0 \ - JE label \ - bmi2adx \ - RET \ - label: \ - legacy \ - RET - -// cselect is a conditional move -// if b=1: it copies y into x; -// if b=0: x remains with the same value; -// if b<> 0,1: undefined. -// Uses: AX, DX, FLAGS -// Instr: x86_64, cmov -#define cselect(x,y,b) \ - TESTQ b, b \ - MOVQ 0+x, AX; MOVQ 0+y, DX; CMOVQNE DX, AX; MOVQ AX, 0+x; \ - MOVQ 8+x, AX; MOVQ 8+y, DX; CMOVQNE DX, AX; MOVQ AX, 8+x; \ - MOVQ 16+x, AX; MOVQ 16+y, DX; CMOVQNE DX, AX; MOVQ AX, 16+x; \ - MOVQ 24+x, AX; MOVQ 24+y, DX; CMOVQNE DX, AX; MOVQ AX, 24+x; - -// cswap is a conditional swap -// if b=1: x,y <- y,x; -// if b=0: x,y remain with the same values; -// if b<> 0,1: undefined. -// Uses: AX, DX, R8, FLAGS -// Instr: x86_64, cmov -#define cswap(x,y,b) \ - TESTQ b, b \ - MOVQ 0+x, AX; MOVQ AX, R8; MOVQ 0+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 0+x; MOVQ DX, 0+y; \ - MOVQ 8+x, AX; MOVQ AX, R8; MOVQ 8+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 8+x; MOVQ DX, 8+y; \ - MOVQ 16+x, AX; MOVQ AX, R8; MOVQ 16+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 16+x; MOVQ DX, 16+y; \ - MOVQ 24+x, AX; MOVQ AX, R8; MOVQ 24+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 24+x; MOVQ DX, 24+y; - -// additionLeg adds x and y and stores in z -// Uses: AX, DX, R8-R11, FLAGS -// Instr: x86_64, cmov -#define additionLeg(z,x,y) \ - MOVL $38, AX; \ - MOVL $0, DX; \ - MOVQ 0+x, R8; ADDQ 0+y, R8; \ - MOVQ 8+x, R9; ADCQ 8+y, R9; \ - MOVQ 16+x, R10; ADCQ 16+y, R10; \ - MOVQ 24+x, R11; ADCQ 24+y, R11; \ - CMOVQCS AX, DX; \ - ADDQ DX, R8; \ - ADCQ $0, R9; MOVQ R9, 8+z; \ - ADCQ $0, R10; MOVQ R10, 16+z; \ - ADCQ $0, R11; MOVQ R11, 24+z; \ - MOVL $0, DX; \ - CMOVQCS AX, DX; \ - ADDQ DX, R8; MOVQ R8, 0+z; - -// additionAdx adds x and y and stores in z -// Uses: AX, DX, R8-R11, FLAGS -// Instr: x86_64, cmov, adx -#define additionAdx(z,x,y) \ - MOVL $38, AX; \ - XORL DX, DX; \ - MOVQ 0+x, R8; ADCXQ 0+y, R8; \ - MOVQ 8+x, R9; ADCXQ 8+y, R9; \ - MOVQ 16+x, R10; ADCXQ 16+y, R10; \ - MOVQ 24+x, R11; ADCXQ 24+y, R11; \ - CMOVQCS AX, DX ; \ - XORL AX, AX; \ - ADCXQ DX, R8; \ - ADCXQ AX, R9; MOVQ R9, 8+z; \ - ADCXQ AX, R10; MOVQ R10, 16+z; \ - ADCXQ AX, R11; MOVQ R11, 24+z; \ - MOVL $38, DX; \ - CMOVQCS DX, AX; \ - ADDQ AX, R8; MOVQ R8, 0+z; - -// subtraction subtracts y from x and stores in z -// Uses: AX, DX, R8-R11, FLAGS -// Instr: x86_64, cmov -#define subtraction(z,x,y) \ - MOVL $38, AX; \ - MOVQ 0+x, R8; SUBQ 0+y, R8; \ - MOVQ 8+x, R9; SBBQ 8+y, R9; \ - MOVQ 16+x, R10; SBBQ 16+y, R10; \ - MOVQ 24+x, R11; SBBQ 24+y, R11; \ - MOVL $0, DX; \ - CMOVQCS AX, DX; \ - SUBQ DX, R8; \ - SBBQ $0, R9; MOVQ R9, 8+z; \ - SBBQ $0, R10; MOVQ R10, 16+z; \ - SBBQ $0, R11; MOVQ R11, 24+z; \ - MOVL $0, DX; \ - CMOVQCS AX, DX; \ - SUBQ DX, R8; MOVQ R8, 0+z; - -// integerMulAdx multiplies x and y and stores in z -// Uses: AX, DX, R8-R15, FLAGS -// Instr: x86_64, bmi2, adx -#define integerMulAdx(z,x,y) \ - MOVL $0,R15; \ - MOVQ 0+y, DX; XORL AX, AX; \ - MULXQ 0+x, AX, R8; MOVQ AX, 0+z; \ - MULXQ 8+x, AX, R9; ADCXQ AX, R8; \ - MULXQ 16+x, AX, R10; ADCXQ AX, R9; \ - MULXQ 24+x, AX, R11; ADCXQ AX, R10; \ - MOVL $0, AX;;;;;;;;; ADCXQ AX, R11; \ - MOVQ 8+y, DX; XORL AX, AX; \ - MULXQ 0+x, AX, R12; ADCXQ R8, AX; MOVQ AX, 8+z; \ - MULXQ 8+x, AX, R13; ADCXQ R9, R12; ADOXQ AX, R12; \ - MULXQ 16+x, AX, R14; ADCXQ R10, R13; ADOXQ AX, R13; \ - MULXQ 24+x, AX, R15; ADCXQ R11, R14; ADOXQ AX, R14; \ - MOVL $0, AX;;;;;;;;; ADCXQ AX, R15; ADOXQ AX, R15; \ - MOVQ 16+y, DX; XORL AX, AX; \ - MULXQ 0+x, AX, R8; ADCXQ R12, AX; MOVQ AX, 16+z; \ - MULXQ 8+x, AX, R9; ADCXQ R13, R8; ADOXQ AX, R8; \ - MULXQ 16+x, AX, R10; ADCXQ R14, R9; ADOXQ AX, R9; \ - MULXQ 24+x, AX, R11; ADCXQ R15, R10; ADOXQ AX, R10; \ - MOVL $0, AX;;;;;;;;; ADCXQ AX, R11; ADOXQ AX, R11; \ - MOVQ 24+y, DX; XORL AX, AX; \ - MULXQ 0+x, AX, R12; ADCXQ R8, AX; MOVQ AX, 24+z; \ - MULXQ 8+x, AX, R13; ADCXQ R9, R12; ADOXQ AX, R12; MOVQ R12, 32+z; \ - MULXQ 16+x, AX, R14; ADCXQ R10, R13; ADOXQ AX, R13; MOVQ R13, 40+z; \ - MULXQ 24+x, AX, R15; ADCXQ R11, R14; ADOXQ AX, R14; MOVQ R14, 48+z; \ - MOVL $0, AX;;;;;;;;; ADCXQ AX, R15; ADOXQ AX, R15; MOVQ R15, 56+z; - -// integerMulLeg multiplies x and y and stores in z -// Uses: AX, DX, R8-R15, FLAGS -// Instr: x86_64 -#define integerMulLeg(z,x,y) \ - MOVQ 0+y, R8; \ - MOVQ 0+x, AX; MULQ R8; MOVQ AX, 0+z; MOVQ DX, R15; \ - MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ - MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ - MOVQ 24+x, AX; MULQ R8; \ - ADDQ R13, R15; \ - ADCQ R14, R10; MOVQ R10, 16+z; \ - ADCQ AX, R11; MOVQ R11, 24+z; \ - ADCQ $0, DX; MOVQ DX, 32+z; \ - MOVQ 8+y, R8; \ - MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \ - MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ - MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ - MOVQ 24+x, AX; MULQ R8; \ - ADDQ R12, R15; MOVQ R15, 8+z; \ - ADCQ R13, R9; \ - ADCQ R14, R10; \ - ADCQ AX, R11; \ - ADCQ $0, DX; \ - ADCQ 16+z, R9; MOVQ R9, R15; \ - ADCQ 24+z, R10; MOVQ R10, 24+z; \ - ADCQ 32+z, R11; MOVQ R11, 32+z; \ - ADCQ $0, DX; MOVQ DX, 40+z; \ - MOVQ 16+y, R8; \ - MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \ - MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ - MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ - MOVQ 24+x, AX; MULQ R8; \ - ADDQ R12, R15; MOVQ R15, 16+z; \ - ADCQ R13, R9; \ - ADCQ R14, R10; \ - ADCQ AX, R11; \ - ADCQ $0, DX; \ - ADCQ 24+z, R9; MOVQ R9, R15; \ - ADCQ 32+z, R10; MOVQ R10, 32+z; \ - ADCQ 40+z, R11; MOVQ R11, 40+z; \ - ADCQ $0, DX; MOVQ DX, 48+z; \ - MOVQ 24+y, R8; \ - MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \ - MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \ - MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \ - MOVQ 24+x, AX; MULQ R8; \ - ADDQ R12, R15; MOVQ R15, 24+z; \ - ADCQ R13, R9; \ - ADCQ R14, R10; \ - ADCQ AX, R11; \ - ADCQ $0, DX; \ - ADCQ 32+z, R9; MOVQ R9, 32+z; \ - ADCQ 40+z, R10; MOVQ R10, 40+z; \ - ADCQ 48+z, R11; MOVQ R11, 48+z; \ - ADCQ $0, DX; MOVQ DX, 56+z; - -// integerSqrLeg squares x and stores in z -// Uses: AX, CX, DX, R8-R15, FLAGS -// Instr: x86_64 -#define integerSqrLeg(z,x) \ - MOVQ 0+x, R8; \ - MOVQ 8+x, AX; MULQ R8; MOVQ AX, R9; MOVQ DX, R10; /* A[0]*A[1] */ \ - MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; /* A[0]*A[2] */ \ - MOVQ 24+x, AX; MULQ R8; MOVQ AX, R15; MOVQ DX, R12; /* A[0]*A[3] */ \ - MOVQ 24+x, R8; \ - MOVQ 8+x, AX; MULQ R8; MOVQ AX, CX; MOVQ DX, R13; /* A[3]*A[1] */ \ - MOVQ 16+x, AX; MULQ R8; /* A[3]*A[2] */ \ - \ - ADDQ R14, R10;\ - ADCQ R15, R11; MOVL $0, R15;\ - ADCQ CX, R12;\ - ADCQ AX, R13;\ - ADCQ $0, DX; MOVQ DX, R14;\ - MOVQ 8+x, AX; MULQ 16+x;\ - \ - ADDQ AX, R11;\ - ADCQ DX, R12;\ - ADCQ $0, R13;\ - ADCQ $0, R14;\ - ADCQ $0, R15;\ - \ - SHLQ $1, R14, R15; MOVQ R15, 56+z;\ - SHLQ $1, R13, R14; MOVQ R14, 48+z;\ - SHLQ $1, R12, R13; MOVQ R13, 40+z;\ - SHLQ $1, R11, R12; MOVQ R12, 32+z;\ - SHLQ $1, R10, R11; MOVQ R11, 24+z;\ - SHLQ $1, R9, R10; MOVQ R10, 16+z;\ - SHLQ $1, R9; MOVQ R9, 8+z;\ - \ - MOVQ 0+x,AX; MULQ AX; MOVQ AX, 0+z; MOVQ DX, R9;\ - MOVQ 8+x,AX; MULQ AX; MOVQ AX, R10; MOVQ DX, R11;\ - MOVQ 16+x,AX; MULQ AX; MOVQ AX, R12; MOVQ DX, R13;\ - MOVQ 24+x,AX; MULQ AX; MOVQ AX, R14; MOVQ DX, R15;\ - \ - ADDQ 8+z, R9; MOVQ R9, 8+z;\ - ADCQ 16+z, R10; MOVQ R10, 16+z;\ - ADCQ 24+z, R11; MOVQ R11, 24+z;\ - ADCQ 32+z, R12; MOVQ R12, 32+z;\ - ADCQ 40+z, R13; MOVQ R13, 40+z;\ - ADCQ 48+z, R14; MOVQ R14, 48+z;\ - ADCQ 56+z, R15; MOVQ R15, 56+z; - -// integerSqrAdx squares x and stores in z -// Uses: AX, CX, DX, R8-R15, FLAGS -// Instr: x86_64, bmi2, adx -#define integerSqrAdx(z,x) \ - MOVQ 0+x, DX; /* A[0] */ \ - MULXQ 8+x, R8, R14; /* A[1]*A[0] */ XORL R15, R15; \ - MULXQ 16+x, R9, R10; /* A[2]*A[0] */ ADCXQ R14, R9; \ - MULXQ 24+x, AX, CX; /* A[3]*A[0] */ ADCXQ AX, R10; \ - MOVQ 24+x, DX; /* A[3] */ \ - MULXQ 8+x, R11, R12; /* A[1]*A[3] */ ADCXQ CX, R11; \ - MULXQ 16+x, AX, R13; /* A[2]*A[3] */ ADCXQ AX, R12; \ - MOVQ 8+x, DX; /* A[1] */ ADCXQ R15, R13; \ - MULXQ 16+x, AX, CX; /* A[2]*A[1] */ MOVL $0, R14; \ - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADCXQ R15, R14; \ - XORL R15, R15; \ - ADOXQ AX, R10; ADCXQ R8, R8; \ - ADOXQ CX, R11; ADCXQ R9, R9; \ - ADOXQ R15, R12; ADCXQ R10, R10; \ - ADOXQ R15, R13; ADCXQ R11, R11; \ - ADOXQ R15, R14; ADCXQ R12, R12; \ - ;;;;;;;;;;;;;;; ADCXQ R13, R13; \ - ;;;;;;;;;;;;;;; ADCXQ R14, R14; \ - MOVQ 0+x, DX; MULXQ DX, AX, CX; /* A[0]^2 */ \ - ;;;;;;;;;;;;;;; MOVQ AX, 0+z; \ - ADDQ CX, R8; MOVQ R8, 8+z; \ - MOVQ 8+x, DX; MULXQ DX, AX, CX; /* A[1]^2 */ \ - ADCQ AX, R9; MOVQ R9, 16+z; \ - ADCQ CX, R10; MOVQ R10, 24+z; \ - MOVQ 16+x, DX; MULXQ DX, AX, CX; /* A[2]^2 */ \ - ADCQ AX, R11; MOVQ R11, 32+z; \ - ADCQ CX, R12; MOVQ R12, 40+z; \ - MOVQ 24+x, DX; MULXQ DX, AX, CX; /* A[3]^2 */ \ - ADCQ AX, R13; MOVQ R13, 48+z; \ - ADCQ CX, R14; MOVQ R14, 56+z; - -// reduceFromDouble finds z congruent to x modulo p such that 0> 63) - // PUT BIT 255 IN CARRY FLAG AND CLEAR - x3 &^= 1 << 63 - - x0, c0 := bits.Add64(x0, cx, 0) - x1, c1 := bits.Add64(x1, 0, c0) - x2, c2 := bits.Add64(x2, 0, c1) - x3, _ = bits.Add64(x3, 0, c2) - - // TEST FOR BIT 255 AGAIN; ONLY TRIGGERED ON OVERFLOW MODULO 2^255-19 - // cx = C[255] ? 0 : 19 - cx = uint64(19) &^ (-(x3 >> 63)) - // CLEAR BIT 255 - x3 &^= 1 << 63 - - x0, c0 = bits.Sub64(x0, cx, 0) - x1, c1 = bits.Sub64(x1, 0, c0) - x2, c2 = bits.Sub64(x2, 0, c1) - x3, _ = bits.Sub64(x3, 0, c2) - - binary.LittleEndian.PutUint64(x[0*8:1*8], x0) - binary.LittleEndian.PutUint64(x[1*8:2*8], x1) - binary.LittleEndian.PutUint64(x[2*8:3*8], x2) - binary.LittleEndian.PutUint64(x[3*8:4*8], x3) -} - -func red64(z *Elt, x0, x1, x2, x3, x4, x5, x6, x7 uint64) { - h0, l0 := bits.Mul64(x4, 38) - h1, l1 := bits.Mul64(x5, 38) - h2, l2 := bits.Mul64(x6, 38) - h3, l3 := bits.Mul64(x7, 38) - - l1, c0 := bits.Add64(h0, l1, 0) - l2, c1 := bits.Add64(h1, l2, c0) - l3, c2 := bits.Add64(h2, l3, c1) - l4, _ := bits.Add64(h3, 0, c2) - - l0, c0 = bits.Add64(l0, x0, 0) - l1, c1 = bits.Add64(l1, x1, c0) - l2, c2 = bits.Add64(l2, x2, c1) - l3, c3 := bits.Add64(l3, x3, c2) - l4, _ = bits.Add64(l4, 0, c3) - - _, l4 = bits.Mul64(l4, 38) - l0, c0 = bits.Add64(l0, l4, 0) - z1, c1 := bits.Add64(l1, 0, c0) - z2, c2 := bits.Add64(l2, 0, c1) - z3, c3 := bits.Add64(l3, 0, c2) - z0, _ := bits.Add64(l0, (-c3)&38, 0) - - binary.LittleEndian.PutUint64(z[0*8:1*8], z0) - binary.LittleEndian.PutUint64(z[1*8:2*8], z1) - binary.LittleEndian.PutUint64(z[2*8:3*8], z2) - binary.LittleEndian.PutUint64(z[3*8:4*8], z3) -} diff --git a/vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go b/vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go deleted file mode 100644 index 26ca4d01..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !amd64 || purego -// +build !amd64 purego - -package fp25519 - -func cmov(x, y *Elt, n uint) { cmovGeneric(x, y, n) } -func cswap(x, y *Elt, n uint) { cswapGeneric(x, y, n) } -func add(z, x, y *Elt) { addGeneric(z, x, y) } -func sub(z, x, y *Elt) { subGeneric(z, x, y) } -func addsub(x, y *Elt) { addsubGeneric(x, y) } -func mul(z, x, y *Elt) { mulGeneric(z, x, y) } -func sqr(z, x *Elt) { sqrGeneric(z, x) } -func modp(z *Elt) { modpGeneric(z) } diff --git a/vendor/github.com/cloudflare/circl/math/fp448/fp.go b/vendor/github.com/cloudflare/circl/math/fp448/fp.go deleted file mode 100644 index a5e36600..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp448/fp.go +++ /dev/null @@ -1,164 +0,0 @@ -// Package fp448 provides prime field arithmetic over GF(2^448-2^224-1). -package fp448 - -import ( - "errors" - - "github.com/cloudflare/circl/internal/conv" -) - -// Size in bytes of an element. -const Size = 56 - -// Elt is a prime field element. -type Elt [Size]byte - -func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) } - -// p is the prime modulus 2^448-2^224-1. -var p = Elt{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -} - -// P returns the prime modulus 2^448-2^224-1. -func P() Elt { return p } - -// ToBytes stores in b the little-endian byte representation of x. -func ToBytes(b []byte, x *Elt) error { - if len(b) != Size { - return errors.New("wrong size") - } - Modp(x) - copy(b, x[:]) - return nil -} - -// IsZero returns true if x is equal to 0. -func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} } - -// IsOne returns true if x is equal to 1. -func IsOne(x *Elt) bool { Modp(x); return *x == Elt{1} } - -// SetOne assigns x=1. -func SetOne(x *Elt) { *x = Elt{1} } - -// One returns the 1 element. -func One() (x Elt) { x = Elt{1}; return } - -// Neg calculates z = -x. -func Neg(z, x *Elt) { Sub(z, &p, x) } - -// Modp ensures that z is between [0,p-1]. -func Modp(z *Elt) { Sub(z, z, &p) } - -// InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue. If so, -// isQR = true; otherwise, isQR = false, since x/y is a quadratic non-residue, -// and z = sqrt(-x/y). -func InvSqrt(z, x, y *Elt) (isQR bool) { - // First note that x^(2(k+1)) = x^(p-1)/2 * x = legendre(x) * x - // so that's x if x is a quadratic residue and -x otherwise. - // Next, y^(6k+3) = y^(4k+2) * y^(2k+1) = y^(p-1) * y^((p-1)/2) = legendre(y). - // So the z we compute satisfies z^2 y = x^(2(k+1)) y^(6k+3) = legendre(x)*legendre(y). - // Thus if x and y are quadratic residues, then z is indeed sqrt(x/y). - t0, t1 := &Elt{}, &Elt{} - Mul(t0, x, y) // x*y - Sqr(t1, y) // y^2 - Mul(t1, t0, t1) // x*y^3 - powPminus3div4(z, t1) // (x*y^3)^k - Mul(z, z, t0) // z = x*y*(x*y^3)^k = x^(k+1) * y^(3k+1) - - // Check if x/y is a quadratic residue - Sqr(t0, z) // z^2 - Mul(t0, t0, y) // y*z^2 - Sub(t0, t0, x) // y*z^2-x - return IsZero(t0) -} - -// Inv calculates z = 1/x mod p. -func Inv(z, x *Elt) { - // Calculates z = x^(4k+1) = x^(p-3+1) = x^(p-2) = x^-1, where k = (p-3)/4. - t := &Elt{} - powPminus3div4(t, x) // t = x^k - Sqr(t, t) // t = x^2k - Sqr(t, t) // t = x^4k - Mul(z, t, x) // z = x^(4k+1) -} - -// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. -func powPminus3div4(z, x *Elt) { - x0, x1 := &Elt{}, &Elt{} - Sqr(z, x) - Mul(z, z, x) - Sqr(x0, z) - Mul(x0, x0, x) - Sqr(z, x0) - Sqr(z, z) - Sqr(z, z) - Mul(z, z, x0) - Sqr(x1, z) - for i := 0; i < 5; i++ { - Sqr(x1, x1) - } - Mul(x1, x1, z) - Sqr(z, x1) - for i := 0; i < 11; i++ { - Sqr(z, z) - } - Mul(z, z, x1) - Sqr(z, z) - Sqr(z, z) - Sqr(z, z) - Mul(z, z, x0) - Sqr(x1, z) - for i := 0; i < 26; i++ { - Sqr(x1, x1) - } - Mul(x1, x1, z) - Sqr(z, x1) - for i := 0; i < 53; i++ { - Sqr(z, z) - } - Mul(z, z, x1) - Sqr(z, z) - Sqr(z, z) - Sqr(z, z) - Mul(z, z, x0) - Sqr(x1, z) - for i := 0; i < 110; i++ { - Sqr(x1, x1) - } - Mul(x1, x1, z) - Sqr(z, x1) - Mul(z, z, x) - for i := 0; i < 223; i++ { - Sqr(z, z) - } - Mul(z, z, x1) -} - -// Cmov assigns y to x if n is 1. -func Cmov(x, y *Elt, n uint) { cmov(x, y, n) } - -// Cswap interchanges x and y if n is 1. -func Cswap(x, y *Elt, n uint) { cswap(x, y, n) } - -// Add calculates z = x+y mod p. -func Add(z, x, y *Elt) { add(z, x, y) } - -// Sub calculates z = x-y mod p. -func Sub(z, x, y *Elt) { sub(z, x, y) } - -// AddSub calculates (x,y) = (x+y mod p, x-y mod p). -func AddSub(x, y *Elt) { addsub(x, y) } - -// Mul calculates z = x*y mod p. -func Mul(z, x, y *Elt) { mul(z, x, y) } - -// Sqr calculates z = x^2 mod p. -func Sqr(z, x *Elt) { sqr(z, x) } diff --git a/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go b/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go deleted file mode 100644 index 6a12209a..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -package fp448 - -import ( - "golang.org/x/sys/cpu" -) - -var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX - -var _ = hasBmi2Adx - -func cmov(x, y *Elt, n uint) { cmovAmd64(x, y, n) } -func cswap(x, y *Elt, n uint) { cswapAmd64(x, y, n) } -func add(z, x, y *Elt) { addAmd64(z, x, y) } -func sub(z, x, y *Elt) { subAmd64(z, x, y) } -func addsub(x, y *Elt) { addsubAmd64(x, y) } -func mul(z, x, y *Elt) { mulAmd64(z, x, y) } -func sqr(z, x *Elt) { sqrAmd64(z, x) } - -/* Functions defined in fp_amd64.s */ - -//go:noescape -func cmovAmd64(x, y *Elt, n uint) - -//go:noescape -func cswapAmd64(x, y *Elt, n uint) - -//go:noescape -func addAmd64(z, x, y *Elt) - -//go:noescape -func subAmd64(z, x, y *Elt) - -//go:noescape -func addsubAmd64(x, y *Elt) - -//go:noescape -func mulAmd64(z, x, y *Elt) - -//go:noescape -func sqrAmd64(z, x *Elt) diff --git a/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h b/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h deleted file mode 100644 index 536fe5bd..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h +++ /dev/null @@ -1,591 +0,0 @@ -// This code was imported from https://github.com/armfazh/rfc7748_precomputed - -// CHECK_BMI2ADX triggers bmi2adx if supported, -// otherwise it fallbacks to legacy code. -#define CHECK_BMI2ADX(label, legacy, bmi2adx) \ - CMPB ·hasBmi2Adx(SB), $0 \ - JE label \ - bmi2adx \ - RET \ - label: \ - legacy \ - RET - -// cselect is a conditional move -// if b=1: it copies y into x; -// if b=0: x remains with the same value; -// if b<> 0,1: undefined. -// Uses: AX, DX, FLAGS -// Instr: x86_64, cmov -#define cselect(x,y,b) \ - TESTQ b, b \ - MOVQ 0+x, AX; MOVQ 0+y, DX; CMOVQNE DX, AX; MOVQ AX, 0+x; \ - MOVQ 8+x, AX; MOVQ 8+y, DX; CMOVQNE DX, AX; MOVQ AX, 8+x; \ - MOVQ 16+x, AX; MOVQ 16+y, DX; CMOVQNE DX, AX; MOVQ AX, 16+x; \ - MOVQ 24+x, AX; MOVQ 24+y, DX; CMOVQNE DX, AX; MOVQ AX, 24+x; \ - MOVQ 32+x, AX; MOVQ 32+y, DX; CMOVQNE DX, AX; MOVQ AX, 32+x; \ - MOVQ 40+x, AX; MOVQ 40+y, DX; CMOVQNE DX, AX; MOVQ AX, 40+x; \ - MOVQ 48+x, AX; MOVQ 48+y, DX; CMOVQNE DX, AX; MOVQ AX, 48+x; - -// cswap is a conditional swap -// if b=1: x,y <- y,x; -// if b=0: x,y remain with the same values; -// if b<> 0,1: undefined. -// Uses: AX, DX, R8, FLAGS -// Instr: x86_64, cmov -#define cswap(x,y,b) \ - TESTQ b, b \ - MOVQ 0+x, AX; MOVQ AX, R8; MOVQ 0+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 0+x; MOVQ DX, 0+y; \ - MOVQ 8+x, AX; MOVQ AX, R8; MOVQ 8+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 8+x; MOVQ DX, 8+y; \ - MOVQ 16+x, AX; MOVQ AX, R8; MOVQ 16+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 16+x; MOVQ DX, 16+y; \ - MOVQ 24+x, AX; MOVQ AX, R8; MOVQ 24+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 24+x; MOVQ DX, 24+y; \ - MOVQ 32+x, AX; MOVQ AX, R8; MOVQ 32+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 32+x; MOVQ DX, 32+y; \ - MOVQ 40+x, AX; MOVQ AX, R8; MOVQ 40+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 40+x; MOVQ DX, 40+y; \ - MOVQ 48+x, AX; MOVQ AX, R8; MOVQ 48+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 48+x; MOVQ DX, 48+y; - -// additionLeg adds x and y and stores in z -// Uses: AX, DX, R8-R14, FLAGS -// Instr: x86_64 -#define additionLeg(z,x,y) \ - MOVQ 0+x, R8; ADDQ 0+y, R8; \ - MOVQ 8+x, R9; ADCQ 8+y, R9; \ - MOVQ 16+x, R10; ADCQ 16+y, R10; \ - MOVQ 24+x, R11; ADCQ 24+y, R11; \ - MOVQ 32+x, R12; ADCQ 32+y, R12; \ - MOVQ 40+x, R13; ADCQ 40+y, R13; \ - MOVQ 48+x, R14; ADCQ 48+y, R14; \ - MOVQ $0, AX; ADCQ $0, AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - ADDQ AX, R8; MOVQ $0, AX; \ - ADCQ $0, R9; \ - ADCQ $0, R10; \ - ADCQ DX, R11; \ - ADCQ $0, R12; \ - ADCQ $0, R13; \ - ADCQ $0, R14; \ - ADCQ $0, AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - ADDQ AX, R8; MOVQ R8, 0+z; \ - ADCQ $0, R9; MOVQ R9, 8+z; \ - ADCQ $0, R10; MOVQ R10, 16+z; \ - ADCQ DX, R11; MOVQ R11, 24+z; \ - ADCQ $0, R12; MOVQ R12, 32+z; \ - ADCQ $0, R13; MOVQ R13, 40+z; \ - ADCQ $0, R14; MOVQ R14, 48+z; - - -// additionAdx adds x and y and stores in z -// Uses: AX, DX, R8-R15, FLAGS -// Instr: x86_64, adx -#define additionAdx(z,x,y) \ - MOVL $32, R15; \ - XORL DX, DX; \ - MOVQ 0+x, R8; ADCXQ 0+y, R8; \ - MOVQ 8+x, R9; ADCXQ 8+y, R9; \ - MOVQ 16+x, R10; ADCXQ 16+y, R10; \ - MOVQ 24+x, R11; ADCXQ 24+y, R11; \ - MOVQ 32+x, R12; ADCXQ 32+y, R12; \ - MOVQ 40+x, R13; ADCXQ 40+y, R13; \ - MOVQ 48+x, R14; ADCXQ 48+y, R14; \ - ;;;;;;;;;;;;;;; ADCXQ DX, DX; \ - XORL AX, AX; \ - ADCXQ DX, R8; SHLXQ R15, DX, DX; \ - ADCXQ AX, R9; \ - ADCXQ AX, R10; \ - ADCXQ DX, R11; \ - ADCXQ AX, R12; \ - ADCXQ AX, R13; \ - ADCXQ AX, R14; \ - ADCXQ AX, AX; \ - XORL DX, DX; \ - ADCXQ AX, R8; MOVQ R8, 0+z; SHLXQ R15, AX, AX; \ - ADCXQ DX, R9; MOVQ R9, 8+z; \ - ADCXQ DX, R10; MOVQ R10, 16+z; \ - ADCXQ AX, R11; MOVQ R11, 24+z; \ - ADCXQ DX, R12; MOVQ R12, 32+z; \ - ADCXQ DX, R13; MOVQ R13, 40+z; \ - ADCXQ DX, R14; MOVQ R14, 48+z; - -// subtraction subtracts y from x and stores in z -// Uses: AX, DX, R8-R14, FLAGS -// Instr: x86_64 -#define subtraction(z,x,y) \ - MOVQ 0+x, R8; SUBQ 0+y, R8; \ - MOVQ 8+x, R9; SBBQ 8+y, R9; \ - MOVQ 16+x, R10; SBBQ 16+y, R10; \ - MOVQ 24+x, R11; SBBQ 24+y, R11; \ - MOVQ 32+x, R12; SBBQ 32+y, R12; \ - MOVQ 40+x, R13; SBBQ 40+y, R13; \ - MOVQ 48+x, R14; SBBQ 48+y, R14; \ - MOVQ $0, AX; SETCS AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - SUBQ AX, R8; MOVQ $0, AX; \ - SBBQ $0, R9; \ - SBBQ $0, R10; \ - SBBQ DX, R11; \ - SBBQ $0, R12; \ - SBBQ $0, R13; \ - SBBQ $0, R14; \ - SETCS AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - SUBQ AX, R8; MOVQ R8, 0+z; \ - SBBQ $0, R9; MOVQ R9, 8+z; \ - SBBQ $0, R10; MOVQ R10, 16+z; \ - SBBQ DX, R11; MOVQ R11, 24+z; \ - SBBQ $0, R12; MOVQ R12, 32+z; \ - SBBQ $0, R13; MOVQ R13, 40+z; \ - SBBQ $0, R14; MOVQ R14, 48+z; - -// maddBmi2Adx multiplies x and y and accumulates in z -// Uses: AX, DX, R15, FLAGS -// Instr: x86_64, bmi2, adx -#define maddBmi2Adx(z,x,y,i,r0,r1,r2,r3,r4,r5,r6) \ - MOVQ i+y, DX; XORL AX, AX; \ - MULXQ 0+x, AX, R8; ADOXQ AX, r0; ADCXQ R8, r1; MOVQ r0,i+z; \ - MULXQ 8+x, AX, r0; ADOXQ AX, r1; ADCXQ r0, r2; MOVQ $0, R8; \ - MULXQ 16+x, AX, r0; ADOXQ AX, r2; ADCXQ r0, r3; \ - MULXQ 24+x, AX, r0; ADOXQ AX, r3; ADCXQ r0, r4; \ - MULXQ 32+x, AX, r0; ADOXQ AX, r4; ADCXQ r0, r5; \ - MULXQ 40+x, AX, r0; ADOXQ AX, r5; ADCXQ r0, r6; \ - MULXQ 48+x, AX, r0; ADOXQ AX, r6; ADCXQ R8, r0; \ - ;;;;;;;;;;;;;;;;;;; ADOXQ R8, r0; - -// integerMulAdx multiplies x and y and stores in z -// Uses: AX, DX, R8-R15, FLAGS -// Instr: x86_64, bmi2, adx -#define integerMulAdx(z,x,y) \ - MOVL $0,R15; \ - MOVQ 0+y, DX; XORL AX, AX; MOVQ $0, R8; \ - MULXQ 0+x, AX, R9; MOVQ AX, 0+z; \ - MULXQ 8+x, AX, R10; ADCXQ AX, R9; \ - MULXQ 16+x, AX, R11; ADCXQ AX, R10; \ - MULXQ 24+x, AX, R12; ADCXQ AX, R11; \ - MULXQ 32+x, AX, R13; ADCXQ AX, R12; \ - MULXQ 40+x, AX, R14; ADCXQ AX, R13; \ - MULXQ 48+x, AX, R15; ADCXQ AX, R14; \ - ;;;;;;;;;;;;;;;;;;;; ADCXQ R8, R15; \ - maddBmi2Adx(z,x,y, 8, R9,R10,R11,R12,R13,R14,R15) \ - maddBmi2Adx(z,x,y,16,R10,R11,R12,R13,R14,R15, R9) \ - maddBmi2Adx(z,x,y,24,R11,R12,R13,R14,R15, R9,R10) \ - maddBmi2Adx(z,x,y,32,R12,R13,R14,R15, R9,R10,R11) \ - maddBmi2Adx(z,x,y,40,R13,R14,R15, R9,R10,R11,R12) \ - maddBmi2Adx(z,x,y,48,R14,R15, R9,R10,R11,R12,R13) \ - MOVQ R15, 56+z; \ - MOVQ R9, 64+z; \ - MOVQ R10, 72+z; \ - MOVQ R11, 80+z; \ - MOVQ R12, 88+z; \ - MOVQ R13, 96+z; \ - MOVQ R14, 104+z; - -// maddLegacy multiplies x and y and accumulates in z -// Uses: AX, DX, R15, FLAGS -// Instr: x86_64 -#define maddLegacy(z,x,y,i) \ - MOVQ i+y, R15; \ - MOVQ 0+x, AX; MULQ R15; MOVQ AX, R8; ;;;;;;;;;;;; MOVQ DX, R9; \ - MOVQ 8+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \ - MOVQ 16+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \ - MOVQ 24+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \ - MOVQ 32+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \ - MOVQ 40+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \ - MOVQ 48+x, AX; MULQ R15; ADDQ AX, R14; ADCQ $0, DX; \ - ADDQ 0+i+z, R8; MOVQ R8, 0+i+z; \ - ADCQ 8+i+z, R9; MOVQ R9, 8+i+z; \ - ADCQ 16+i+z, R10; MOVQ R10, 16+i+z; \ - ADCQ 24+i+z, R11; MOVQ R11, 24+i+z; \ - ADCQ 32+i+z, R12; MOVQ R12, 32+i+z; \ - ADCQ 40+i+z, R13; MOVQ R13, 40+i+z; \ - ADCQ 48+i+z, R14; MOVQ R14, 48+i+z; \ - ADCQ $0, DX; MOVQ DX, 56+i+z; - -// integerMulLeg multiplies x and y and stores in z -// Uses: AX, DX, R8-R15, FLAGS -// Instr: x86_64 -#define integerMulLeg(z,x,y) \ - MOVQ 0+y, R15; \ - MOVQ 0+x, AX; MULQ R15; MOVQ AX, 0+z; ;;;;;;;;;;;; MOVQ DX, R8; \ - MOVQ 8+x, AX; MULQ R15; ADDQ AX, R8; ADCQ $0, DX; MOVQ DX, R9; MOVQ R8, 8+z; \ - MOVQ 16+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; MOVQ R9, 16+z; \ - MOVQ 24+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; MOVQ R10, 24+z; \ - MOVQ 32+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; MOVQ R11, 32+z; \ - MOVQ 40+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; MOVQ R12, 40+z; \ - MOVQ 48+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX,56+z; MOVQ R13, 48+z; \ - maddLegacy(z,x,y, 8) \ - maddLegacy(z,x,y,16) \ - maddLegacy(z,x,y,24) \ - maddLegacy(z,x,y,32) \ - maddLegacy(z,x,y,40) \ - maddLegacy(z,x,y,48) - -// integerSqrLeg squares x and stores in z -// Uses: AX, CX, DX, R8-R15, FLAGS -// Instr: x86_64 -#define integerSqrLeg(z,x) \ - XORL R15, R15; \ - MOVQ 0+x, CX; \ - MOVQ CX, AX; MULQ CX; MOVQ AX, 0+z; MOVQ DX, R8; \ - ADDQ CX, CX; ADCQ $0, R15; \ - MOVQ 8+x, AX; MULQ CX; ADDQ AX, R8; ADCQ $0, DX; MOVQ DX, R9; MOVQ R8, 8+z; \ - MOVQ 16+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \ - MOVQ 24+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \ - MOVQ 32+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \ - MOVQ 40+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \ - MOVQ 48+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \ - \ - MOVQ 8+x, CX; \ - MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ - ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ R9,16+z; \ - MOVQ R15, AX; NEGQ AX; ANDQ 8+x, AX; ADDQ AX, DX; ADCQ $0, R11; MOVQ DX, R8; \ - ADDQ 8+x, CX; ADCQ $0, R15; \ - MOVQ 16+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX, R8; MOVQ R10, 24+z; \ - MOVQ 24+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; ADDQ R8, R11; ADCQ $0, DX; MOVQ DX, R8; \ - MOVQ 32+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; \ - MOVQ 40+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; ADDQ R8, R13; ADCQ $0, DX; MOVQ DX, R8; \ - MOVQ 48+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R9; \ - \ - MOVQ 16+x, CX; \ - MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ - ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ R11, 32+z; \ - MOVQ R15, AX; NEGQ AX; ANDQ 16+x,AX; ADDQ AX, DX; ADCQ $0, R13; MOVQ DX, R8; \ - ADDQ 16+x, CX; ADCQ $0, R15; \ - MOVQ 24+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; MOVQ R12, 40+z; \ - MOVQ 32+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; ADDQ R8, R13; ADCQ $0, DX; MOVQ DX, R8; \ - MOVQ 40+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R8; \ - MOVQ 48+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; ADDQ R8, R9; ADCQ $0, DX; MOVQ DX,R10; \ - \ - MOVQ 24+x, CX; \ - MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ - ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ R13, 48+z; \ - MOVQ R15, AX; NEGQ AX; ANDQ 24+x,AX; ADDQ AX, DX; ADCQ $0, R9; MOVQ DX, R8; \ - ADDQ 24+x, CX; ADCQ $0, R15; \ - MOVQ 32+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R8; MOVQ R14, 56+z; \ - MOVQ 40+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; ADDQ R8, R9; ADCQ $0, DX; MOVQ DX, R8; \ - MOVQ 48+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX,R11; \ - \ - MOVQ 32+x, CX; \ - MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ - ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ R9, 64+z; \ - MOVQ R15, AX; NEGQ AX; ANDQ 32+x,AX; ADDQ AX, DX; ADCQ $0, R11; MOVQ DX, R8; \ - ADDQ 32+x, CX; ADCQ $0, R15; \ - MOVQ 40+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX, R8; MOVQ R10, 72+z; \ - MOVQ 48+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; ADDQ R8, R11; ADCQ $0, DX; MOVQ DX,R12; \ - \ - XORL R13, R13; \ - XORL R14, R14; \ - MOVQ 40+x, CX; \ - MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ - ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ R11, 80+z; \ - MOVQ R15, AX; NEGQ AX; ANDQ 40+x,AX; ADDQ AX, DX; ADCQ $0, R13; MOVQ DX, R8; \ - ADDQ 40+x, CX; ADCQ $0, R15; \ - MOVQ 48+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; MOVQ R12, 88+z; \ - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADDQ R8, R13; ADCQ $0,R14; \ - \ - XORL R9, R9; \ - MOVQ 48+x, CX; \ - MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \ - ;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ R13, 96+z; \ - MOVQ R15, AX; NEGQ AX; ANDQ 48+x,AX; ADDQ AX, DX; ADCQ $0, R9; MOVQ DX, R8; \ - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADDQ R8,R14; ADCQ $0, R9; MOVQ R14, 104+z; - - -// integerSqrAdx squares x and stores in z -// Uses: AX, CX, DX, R8-R15, FLAGS -// Instr: x86_64, bmi2, adx -#define integerSqrAdx(z,x) \ - XORL R15, R15; \ - MOVQ 0+x, DX; \ - ;;;;;;;;;;;;;; MULXQ DX, AX, R8; MOVQ AX, 0+z; \ - ADDQ DX, DX; ADCQ $0, R15; CLC; \ - MULXQ 8+x, AX, R9; ADCXQ AX, R8; MOVQ R8, 8+z; \ - MULXQ 16+x, AX, R10; ADCXQ AX, R9; MOVQ $0, R8;\ - MULXQ 24+x, AX, R11; ADCXQ AX, R10; \ - MULXQ 32+x, AX, R12; ADCXQ AX, R11; \ - MULXQ 40+x, AX, R13; ADCXQ AX, R12; \ - MULXQ 48+x, AX, R14; ADCXQ AX, R13; \ - ;;;;;;;;;;;;;;;;;;;; ADCXQ R8, R14; \ - \ - MOVQ 8+x, DX; \ - MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ - MULXQ AX, AX, CX; \ - MOVQ R15, R8; NEGQ R8; ANDQ 8+x, R8; \ - ADDQ AX, R9; MOVQ R9, 16+z; \ - ADCQ CX, R8; \ - ADCQ $0, R11; \ - ADDQ 8+x, DX; \ - ADCQ $0, R15; \ - XORL R9, R9; ;;;;;;;;;;;;;;;;;;;;; ADOXQ R8, R10; \ - MULXQ 16+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; MOVQ R10, 24+z; \ - MULXQ 24+x, AX, CX; ADCXQ AX, R11; ADOXQ CX, R12; MOVQ $0, R10; \ - MULXQ 32+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; \ - MULXQ 40+x, AX, CX; ADCXQ AX, R13; ADOXQ CX, R14; \ - MULXQ 48+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; \ - ;;;;;;;;;;;;;;;;;;; ADCXQ R10, R9; \ - \ - MOVQ 16+x, DX; \ - MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ - MULXQ AX, AX, CX; \ - MOVQ R15, R8; NEGQ R8; ANDQ 16+x, R8; \ - ADDQ AX, R11; MOVQ R11, 32+z; \ - ADCQ CX, R8; \ - ADCQ $0, R13; \ - ADDQ 16+x, DX; \ - ADCQ $0, R15; \ - XORL R11, R11; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R12; \ - MULXQ 24+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; MOVQ R12, 40+z; \ - MULXQ 32+x, AX, CX; ADCXQ AX, R13; ADOXQ CX, R14; MOVQ $0, R12; \ - MULXQ 40+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; \ - MULXQ 48+x, AX, CX; ADCXQ AX, R9; ADOXQ CX, R10; \ - ;;;;;;;;;;;;;;;;;;; ADCXQ R11,R10; \ - \ - MOVQ 24+x, DX; \ - MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ - MULXQ AX, AX, CX; \ - MOVQ R15, R8; NEGQ R8; ANDQ 24+x, R8; \ - ADDQ AX, R13; MOVQ R13, 48+z; \ - ADCQ CX, R8; \ - ADCQ $0, R9; \ - ADDQ 24+x, DX; \ - ADCQ $0, R15; \ - XORL R13, R13; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R14; \ - MULXQ 32+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; MOVQ R14, 56+z; \ - MULXQ 40+x, AX, CX; ADCXQ AX, R9; ADOXQ CX, R10; MOVQ $0, R14; \ - MULXQ 48+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; \ - ;;;;;;;;;;;;;;;;;;; ADCXQ R12,R11; \ - \ - MOVQ 32+x, DX; \ - MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ - MULXQ AX, AX, CX; \ - MOVQ R15, R8; NEGQ R8; ANDQ 32+x, R8; \ - ADDQ AX, R9; MOVQ R9, 64+z; \ - ADCQ CX, R8; \ - ADCQ $0, R11; \ - ADDQ 32+x, DX; \ - ADCQ $0, R15; \ - XORL R9, R9; ;;;;;;;;;;;;;;;;;;;;; ADOXQ R8, R10; \ - MULXQ 40+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; MOVQ R10, 72+z; \ - MULXQ 48+x, AX, CX; ADCXQ AX, R11; ADOXQ CX, R12; \ - ;;;;;;;;;;;;;;;;;;; ADCXQ R13,R12; \ - \ - MOVQ 40+x, DX; \ - MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ - MULXQ AX, AX, CX; \ - MOVQ R15, R8; NEGQ R8; ANDQ 40+x, R8; \ - ADDQ AX, R11; MOVQ R11, 80+z; \ - ADCQ CX, R8; \ - ADCQ $0, R13; \ - ADDQ 40+x, DX; \ - ADCQ $0, R15; \ - XORL R11, R11; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R12; \ - MULXQ 48+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; MOVQ R12, 88+z; \ - ;;;;;;;;;;;;;;;;;;; ADCXQ R14,R13; \ - \ - MOVQ 48+x, DX; \ - MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \ - MULXQ AX, AX, CX; \ - MOVQ R15, R8; NEGQ R8; ANDQ 48+x, R8; \ - XORL R10, R10; ;;;;;;;;;;;;;; ADOXQ CX, R14; \ - ;;;;;;;;;;;;;; ADCXQ AX, R13; ;;;;;;;;;;;;;; MOVQ R13, 96+z; \ - ;;;;;;;;;;;;;; ADCXQ R8, R14; MOVQ R14, 104+z; - -// reduceFromDoubleLeg finds a z=x modulo p such that z<2^448 and stores in z -// Uses: AX, R8-R15, FLAGS -// Instr: x86_64 -#define reduceFromDoubleLeg(z,x) \ - /* ( ,2C13,2C12,2C11,2C10|C10,C9,C8, C7) + (C6,...,C0) */ \ - /* (r14, r13, r12, r11, r10,r9,r8,r15) */ \ - MOVQ 80+x,AX; MOVQ AX,R10; \ - MOVQ $0xFFFFFFFF00000000, R8; \ - ANDQ R8,R10; \ - \ - MOVQ $0,R14; \ - MOVQ 104+x,R13; SHLQ $1,R13,R14; \ - MOVQ 96+x,R12; SHLQ $1,R12,R13; \ - MOVQ 88+x,R11; SHLQ $1,R11,R12; \ - MOVQ 72+x, R9; SHLQ $1,R10,R11; \ - MOVQ 64+x, R8; SHLQ $1,R10; \ - MOVQ $0xFFFFFFFF,R15; ANDQ R15,AX; ORQ AX,R10; \ - MOVQ 56+x,R15; \ - \ - ADDQ 0+x,R15; MOVQ R15, 0+z; MOVQ 56+x,R15; \ - ADCQ 8+x, R8; MOVQ R8, 8+z; MOVQ 64+x, R8; \ - ADCQ 16+x, R9; MOVQ R9,16+z; MOVQ 72+x, R9; \ - ADCQ 24+x,R10; MOVQ R10,24+z; MOVQ 80+x,R10; \ - ADCQ 32+x,R11; MOVQ R11,32+z; MOVQ 88+x,R11; \ - ADCQ 40+x,R12; MOVQ R12,40+z; MOVQ 96+x,R12; \ - ADCQ 48+x,R13; MOVQ R13,48+z; MOVQ 104+x,R13; \ - ADCQ $0,R14; \ - /* (c10c9,c9c8,c8c7,c7c13,c13c12,c12c11,c11c10) + (c6,...,c0) */ \ - /* ( r9, r8, r15, r13, r12, r11, r10) */ \ - MOVQ R10, AX; \ - SHRQ $32,R11,R10; \ - SHRQ $32,R12,R11; \ - SHRQ $32,R13,R12; \ - SHRQ $32,R15,R13; \ - SHRQ $32, R8,R15; \ - SHRQ $32, R9, R8; \ - SHRQ $32, AX, R9; \ - \ - ADDQ 0+z,R10; \ - ADCQ 8+z,R11; \ - ADCQ 16+z,R12; \ - ADCQ 24+z,R13; \ - ADCQ 32+z,R15; \ - ADCQ 40+z, R8; \ - ADCQ 48+z, R9; \ - ADCQ $0,R14; \ - /* ( c7) + (c6,...,c0) */ \ - /* (r14) */ \ - MOVQ R14, AX; SHLQ $32, AX; \ - ADDQ R14,R10; MOVQ $0,R14; \ - ADCQ $0,R11; \ - ADCQ $0,R12; \ - ADCQ AX,R13; \ - ADCQ $0,R15; \ - ADCQ $0, R8; \ - ADCQ $0, R9; \ - ADCQ $0,R14; \ - /* ( c7) + (c6,...,c0) */ \ - /* (r14) */ \ - MOVQ R14, AX; SHLQ $32,AX; \ - ADDQ R14,R10; MOVQ R10, 0+z; \ - ADCQ $0,R11; MOVQ R11, 8+z; \ - ADCQ $0,R12; MOVQ R12,16+z; \ - ADCQ AX,R13; MOVQ R13,24+z; \ - ADCQ $0,R15; MOVQ R15,32+z; \ - ADCQ $0, R8; MOVQ R8,40+z; \ - ADCQ $0, R9; MOVQ R9,48+z; - -// reduceFromDoubleAdx finds a z=x modulo p such that z<2^448 and stores in z -// Uses: AX, R8-R15, FLAGS -// Instr: x86_64, adx -#define reduceFromDoubleAdx(z,x) \ - /* ( ,2C13,2C12,2C11,2C10|C10,C9,C8, C7) + (C6,...,C0) */ \ - /* (r14, r13, r12, r11, r10,r9,r8,r15) */ \ - MOVQ 80+x,AX; MOVQ AX,R10; \ - MOVQ $0xFFFFFFFF00000000, R8; \ - ANDQ R8,R10; \ - \ - MOVQ $0,R14; \ - MOVQ 104+x,R13; SHLQ $1,R13,R14; \ - MOVQ 96+x,R12; SHLQ $1,R12,R13; \ - MOVQ 88+x,R11; SHLQ $1,R11,R12; \ - MOVQ 72+x, R9; SHLQ $1,R10,R11; \ - MOVQ 64+x, R8; SHLQ $1,R10; \ - MOVQ $0xFFFFFFFF,R15; ANDQ R15,AX; ORQ AX,R10; \ - MOVQ 56+x,R15; \ - \ - XORL AX,AX; \ - ADCXQ 0+x,R15; MOVQ R15, 0+z; MOVQ 56+x,R15; \ - ADCXQ 8+x, R8; MOVQ R8, 8+z; MOVQ 64+x, R8; \ - ADCXQ 16+x, R9; MOVQ R9,16+z; MOVQ 72+x, R9; \ - ADCXQ 24+x,R10; MOVQ R10,24+z; MOVQ 80+x,R10; \ - ADCXQ 32+x,R11; MOVQ R11,32+z; MOVQ 88+x,R11; \ - ADCXQ 40+x,R12; MOVQ R12,40+z; MOVQ 96+x,R12; \ - ADCXQ 48+x,R13; MOVQ R13,48+z; MOVQ 104+x,R13; \ - ADCXQ AX,R14; \ - /* (c10c9,c9c8,c8c7,c7c13,c13c12,c12c11,c11c10) + (c6,...,c0) */ \ - /* ( r9, r8, r15, r13, r12, r11, r10) */ \ - MOVQ R10, AX; \ - SHRQ $32,R11,R10; \ - SHRQ $32,R12,R11; \ - SHRQ $32,R13,R12; \ - SHRQ $32,R15,R13; \ - SHRQ $32, R8,R15; \ - SHRQ $32, R9, R8; \ - SHRQ $32, AX, R9; \ - \ - XORL AX,AX; \ - ADCXQ 0+z,R10; \ - ADCXQ 8+z,R11; \ - ADCXQ 16+z,R12; \ - ADCXQ 24+z,R13; \ - ADCXQ 32+z,R15; \ - ADCXQ 40+z, R8; \ - ADCXQ 48+z, R9; \ - ADCXQ AX,R14; \ - /* ( c7) + (c6,...,c0) */ \ - /* (r14) */ \ - MOVQ R14, AX; SHLQ $32, AX; \ - CLC; \ - ADCXQ R14,R10; MOVQ $0,R14; \ - ADCXQ R14,R11; \ - ADCXQ R14,R12; \ - ADCXQ AX,R13; \ - ADCXQ R14,R15; \ - ADCXQ R14, R8; \ - ADCXQ R14, R9; \ - ADCXQ R14,R14; \ - /* ( c7) + (c6,...,c0) */ \ - /* (r14) */ \ - MOVQ R14, AX; SHLQ $32, AX; \ - CLC; \ - ADCXQ R14,R10; MOVQ R10, 0+z; MOVQ $0,R14; \ - ADCXQ R14,R11; MOVQ R11, 8+z; \ - ADCXQ R14,R12; MOVQ R12,16+z; \ - ADCXQ AX,R13; MOVQ R13,24+z; \ - ADCXQ R14,R15; MOVQ R15,32+z; \ - ADCXQ R14, R8; MOVQ R8,40+z; \ - ADCXQ R14, R9; MOVQ R9,48+z; - -// addSub calculates two operations: x,y = x+y,x-y -// Uses: AX, DX, R8-R15, FLAGS -#define addSub(x,y) \ - MOVQ 0+x, R8; ADDQ 0+y, R8; \ - MOVQ 8+x, R9; ADCQ 8+y, R9; \ - MOVQ 16+x, R10; ADCQ 16+y, R10; \ - MOVQ 24+x, R11; ADCQ 24+y, R11; \ - MOVQ 32+x, R12; ADCQ 32+y, R12; \ - MOVQ 40+x, R13; ADCQ 40+y, R13; \ - MOVQ 48+x, R14; ADCQ 48+y, R14; \ - MOVQ $0, AX; ADCQ $0, AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - ADDQ AX, R8; MOVQ $0, AX; \ - ADCQ $0, R9; \ - ADCQ $0, R10; \ - ADCQ DX, R11; \ - ADCQ $0, R12; \ - ADCQ $0, R13; \ - ADCQ $0, R14; \ - ADCQ $0, AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - ADDQ AX, R8; MOVQ 0+x,AX; MOVQ R8, 0+x; MOVQ AX, R8; \ - ADCQ $0, R9; MOVQ 8+x,AX; MOVQ R9, 8+x; MOVQ AX, R9; \ - ADCQ $0, R10; MOVQ 16+x,AX; MOVQ R10, 16+x; MOVQ AX, R10; \ - ADCQ DX, R11; MOVQ 24+x,AX; MOVQ R11, 24+x; MOVQ AX, R11; \ - ADCQ $0, R12; MOVQ 32+x,AX; MOVQ R12, 32+x; MOVQ AX, R12; \ - ADCQ $0, R13; MOVQ 40+x,AX; MOVQ R13, 40+x; MOVQ AX, R13; \ - ADCQ $0, R14; MOVQ 48+x,AX; MOVQ R14, 48+x; MOVQ AX, R14; \ - SUBQ 0+y, R8; \ - SBBQ 8+y, R9; \ - SBBQ 16+y, R10; \ - SBBQ 24+y, R11; \ - SBBQ 32+y, R12; \ - SBBQ 40+y, R13; \ - SBBQ 48+y, R14; \ - MOVQ $0, AX; SETCS AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - SUBQ AX, R8; MOVQ $0, AX; \ - SBBQ $0, R9; \ - SBBQ $0, R10; \ - SBBQ DX, R11; \ - SBBQ $0, R12; \ - SBBQ $0, R13; \ - SBBQ $0, R14; \ - SETCS AX; \ - MOVQ AX, DX; \ - SHLQ $32, DX; \ - SUBQ AX, R8; MOVQ R8, 0+y; \ - SBBQ $0, R9; MOVQ R9, 8+y; \ - SBBQ $0, R10; MOVQ R10, 16+y; \ - SBBQ DX, R11; MOVQ R11, 24+y; \ - SBBQ $0, R12; MOVQ R12, 32+y; \ - SBBQ $0, R13; MOVQ R13, 40+y; \ - SBBQ $0, R14; MOVQ R14, 48+y; diff --git a/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s b/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s deleted file mode 100644 index 3f1f07c9..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s +++ /dev/null @@ -1,75 +0,0 @@ -//go:build amd64 && !purego -// +build amd64,!purego - -#include "textflag.h" -#include "fp_amd64.h" - -// func cmovAmd64(x, y *Elt, n uint) -TEXT ·cmovAmd64(SB),NOSPLIT,$0-24 - MOVQ x+0(FP), DI - MOVQ y+8(FP), SI - MOVQ n+16(FP), BX - cselect(0(DI),0(SI),BX) - RET - -// func cswapAmd64(x, y *Elt, n uint) -TEXT ·cswapAmd64(SB),NOSPLIT,$0-24 - MOVQ x+0(FP), DI - MOVQ y+8(FP), SI - MOVQ n+16(FP), BX - cswap(0(DI),0(SI),BX) - RET - -// func subAmd64(z, x, y *Elt) -TEXT ·subAmd64(SB),NOSPLIT,$0-24 - MOVQ z+0(FP), DI - MOVQ x+8(FP), SI - MOVQ y+16(FP), BX - subtraction(0(DI),0(SI),0(BX)) - RET - -// func addsubAmd64(x, y *Elt) -TEXT ·addsubAmd64(SB),NOSPLIT,$0-16 - MOVQ x+0(FP), DI - MOVQ y+8(FP), SI - addSub(0(DI),0(SI)) - RET - -#define addLegacy \ - additionLeg(0(DI),0(SI),0(BX)) -#define addBmi2Adx \ - additionAdx(0(DI),0(SI),0(BX)) - -#define mulLegacy \ - integerMulLeg(0(SP),0(SI),0(BX)) \ - reduceFromDoubleLeg(0(DI),0(SP)) -#define mulBmi2Adx \ - integerMulAdx(0(SP),0(SI),0(BX)) \ - reduceFromDoubleAdx(0(DI),0(SP)) - -#define sqrLegacy \ - integerSqrLeg(0(SP),0(SI)) \ - reduceFromDoubleLeg(0(DI),0(SP)) -#define sqrBmi2Adx \ - integerSqrAdx(0(SP),0(SI)) \ - reduceFromDoubleAdx(0(DI),0(SP)) - -// func addAmd64(z, x, y *Elt) -TEXT ·addAmd64(SB),NOSPLIT,$0-24 - MOVQ z+0(FP), DI - MOVQ x+8(FP), SI - MOVQ y+16(FP), BX - CHECK_BMI2ADX(LADD, addLegacy, addBmi2Adx) - -// func mulAmd64(z, x, y *Elt) -TEXT ·mulAmd64(SB),NOSPLIT,$112-24 - MOVQ z+0(FP), DI - MOVQ x+8(FP), SI - MOVQ y+16(FP), BX - CHECK_BMI2ADX(LMUL, mulLegacy, mulBmi2Adx) - -// func sqrAmd64(z, x *Elt) -TEXT ·sqrAmd64(SB),NOSPLIT,$112-16 - MOVQ z+0(FP), DI - MOVQ x+8(FP), SI - CHECK_BMI2ADX(LSQR, sqrLegacy, sqrBmi2Adx) diff --git a/vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go b/vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go deleted file mode 100644 index 47a0b632..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go +++ /dev/null @@ -1,339 +0,0 @@ -package fp448 - -import ( - "encoding/binary" - "math/bits" -) - -func cmovGeneric(x, y *Elt, n uint) { - m := -uint64(n & 0x1) - x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) - x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) - x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) - x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) - x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) - x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) - x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) - - y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) - y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) - y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) - y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) - y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) - y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) - y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) - - x0 = (x0 &^ m) | (y0 & m) - x1 = (x1 &^ m) | (y1 & m) - x2 = (x2 &^ m) | (y2 & m) - x3 = (x3 &^ m) | (y3 & m) - x4 = (x4 &^ m) | (y4 & m) - x5 = (x5 &^ m) | (y5 & m) - x6 = (x6 &^ m) | (y6 & m) - - binary.LittleEndian.PutUint64(x[0*8:1*8], x0) - binary.LittleEndian.PutUint64(x[1*8:2*8], x1) - binary.LittleEndian.PutUint64(x[2*8:3*8], x2) - binary.LittleEndian.PutUint64(x[3*8:4*8], x3) - binary.LittleEndian.PutUint64(x[4*8:5*8], x4) - binary.LittleEndian.PutUint64(x[5*8:6*8], x5) - binary.LittleEndian.PutUint64(x[6*8:7*8], x6) -} - -func cswapGeneric(x, y *Elt, n uint) { - m := -uint64(n & 0x1) - x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) - x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) - x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) - x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) - x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) - x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) - x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) - - y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) - y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) - y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) - y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) - y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) - y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) - y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) - - t0 := m & (x0 ^ y0) - t1 := m & (x1 ^ y1) - t2 := m & (x2 ^ y2) - t3 := m & (x3 ^ y3) - t4 := m & (x4 ^ y4) - t5 := m & (x5 ^ y5) - t6 := m & (x6 ^ y6) - x0 ^= t0 - x1 ^= t1 - x2 ^= t2 - x3 ^= t3 - x4 ^= t4 - x5 ^= t5 - x6 ^= t6 - y0 ^= t0 - y1 ^= t1 - y2 ^= t2 - y3 ^= t3 - y4 ^= t4 - y5 ^= t5 - y6 ^= t6 - - binary.LittleEndian.PutUint64(x[0*8:1*8], x0) - binary.LittleEndian.PutUint64(x[1*8:2*8], x1) - binary.LittleEndian.PutUint64(x[2*8:3*8], x2) - binary.LittleEndian.PutUint64(x[3*8:4*8], x3) - binary.LittleEndian.PutUint64(x[4*8:5*8], x4) - binary.LittleEndian.PutUint64(x[5*8:6*8], x5) - binary.LittleEndian.PutUint64(x[6*8:7*8], x6) - - binary.LittleEndian.PutUint64(y[0*8:1*8], y0) - binary.LittleEndian.PutUint64(y[1*8:2*8], y1) - binary.LittleEndian.PutUint64(y[2*8:3*8], y2) - binary.LittleEndian.PutUint64(y[3*8:4*8], y3) - binary.LittleEndian.PutUint64(y[4*8:5*8], y4) - binary.LittleEndian.PutUint64(y[5*8:6*8], y5) - binary.LittleEndian.PutUint64(y[6*8:7*8], y6) -} - -func addGeneric(z, x, y *Elt) { - x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) - x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) - x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) - x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) - x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) - x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) - x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) - - y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) - y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) - y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) - y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) - y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) - y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) - y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) - - z0, c0 := bits.Add64(x0, y0, 0) - z1, c1 := bits.Add64(x1, y1, c0) - z2, c2 := bits.Add64(x2, y2, c1) - z3, c3 := bits.Add64(x3, y3, c2) - z4, c4 := bits.Add64(x4, y4, c3) - z5, c5 := bits.Add64(x5, y5, c4) - z6, z7 := bits.Add64(x6, y6, c5) - - z0, c0 = bits.Add64(z0, z7, 0) - z1, c1 = bits.Add64(z1, 0, c0) - z2, c2 = bits.Add64(z2, 0, c1) - z3, c3 = bits.Add64(z3, z7<<32, c2) - z4, c4 = bits.Add64(z4, 0, c3) - z5, c5 = bits.Add64(z5, 0, c4) - z6, z7 = bits.Add64(z6, 0, c5) - - z0, c0 = bits.Add64(z0, z7, 0) - z1, c1 = bits.Add64(z1, 0, c0) - z2, c2 = bits.Add64(z2, 0, c1) - z3, c3 = bits.Add64(z3, z7<<32, c2) - z4, c4 = bits.Add64(z4, 0, c3) - z5, c5 = bits.Add64(z5, 0, c4) - z6, _ = bits.Add64(z6, 0, c5) - - binary.LittleEndian.PutUint64(z[0*8:1*8], z0) - binary.LittleEndian.PutUint64(z[1*8:2*8], z1) - binary.LittleEndian.PutUint64(z[2*8:3*8], z2) - binary.LittleEndian.PutUint64(z[3*8:4*8], z3) - binary.LittleEndian.PutUint64(z[4*8:5*8], z4) - binary.LittleEndian.PutUint64(z[5*8:6*8], z5) - binary.LittleEndian.PutUint64(z[6*8:7*8], z6) -} - -func subGeneric(z, x, y *Elt) { - x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) - x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) - x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) - x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) - x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) - x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) - x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) - - y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) - y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) - y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) - y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) - y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) - y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) - y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) - - z0, c0 := bits.Sub64(x0, y0, 0) - z1, c1 := bits.Sub64(x1, y1, c0) - z2, c2 := bits.Sub64(x2, y2, c1) - z3, c3 := bits.Sub64(x3, y3, c2) - z4, c4 := bits.Sub64(x4, y4, c3) - z5, c5 := bits.Sub64(x5, y5, c4) - z6, z7 := bits.Sub64(x6, y6, c5) - - z0, c0 = bits.Sub64(z0, z7, 0) - z1, c1 = bits.Sub64(z1, 0, c0) - z2, c2 = bits.Sub64(z2, 0, c1) - z3, c3 = bits.Sub64(z3, z7<<32, c2) - z4, c4 = bits.Sub64(z4, 0, c3) - z5, c5 = bits.Sub64(z5, 0, c4) - z6, z7 = bits.Sub64(z6, 0, c5) - - z0, c0 = bits.Sub64(z0, z7, 0) - z1, c1 = bits.Sub64(z1, 0, c0) - z2, c2 = bits.Sub64(z2, 0, c1) - z3, c3 = bits.Sub64(z3, z7<<32, c2) - z4, c4 = bits.Sub64(z4, 0, c3) - z5, c5 = bits.Sub64(z5, 0, c4) - z6, _ = bits.Sub64(z6, 0, c5) - - binary.LittleEndian.PutUint64(z[0*8:1*8], z0) - binary.LittleEndian.PutUint64(z[1*8:2*8], z1) - binary.LittleEndian.PutUint64(z[2*8:3*8], z2) - binary.LittleEndian.PutUint64(z[3*8:4*8], z3) - binary.LittleEndian.PutUint64(z[4*8:5*8], z4) - binary.LittleEndian.PutUint64(z[5*8:6*8], z5) - binary.LittleEndian.PutUint64(z[6*8:7*8], z6) -} - -func addsubGeneric(x, y *Elt) { - z := &Elt{} - addGeneric(z, x, y) - subGeneric(y, x, y) - *x = *z -} - -func mulGeneric(z, x, y *Elt) { - x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) - x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) - x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) - x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) - x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8]) - x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8]) - x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8]) - - y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) - y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) - y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) - y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) - y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8]) - y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8]) - y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8]) - - yy := [7]uint64{y0, y1, y2, y3, y4, y5, y6} - zz := [7]uint64{} - - yi := yy[0] - h0, l0 := bits.Mul64(x0, yi) - h1, l1 := bits.Mul64(x1, yi) - h2, l2 := bits.Mul64(x2, yi) - h3, l3 := bits.Mul64(x3, yi) - h4, l4 := bits.Mul64(x4, yi) - h5, l5 := bits.Mul64(x5, yi) - h6, l6 := bits.Mul64(x6, yi) - - zz[0] = l0 - a0, c0 := bits.Add64(h0, l1, 0) - a1, c1 := bits.Add64(h1, l2, c0) - a2, c2 := bits.Add64(h2, l3, c1) - a3, c3 := bits.Add64(h3, l4, c2) - a4, c4 := bits.Add64(h4, l5, c3) - a5, c5 := bits.Add64(h5, l6, c4) - a6, _ := bits.Add64(h6, 0, c5) - - for i := 1; i < 7; i++ { - yi = yy[i] - h0, l0 = bits.Mul64(x0, yi) - h1, l1 = bits.Mul64(x1, yi) - h2, l2 = bits.Mul64(x2, yi) - h3, l3 = bits.Mul64(x3, yi) - h4, l4 = bits.Mul64(x4, yi) - h5, l5 = bits.Mul64(x5, yi) - h6, l6 = bits.Mul64(x6, yi) - - zz[i], c0 = bits.Add64(a0, l0, 0) - a0, c1 = bits.Add64(a1, l1, c0) - a1, c2 = bits.Add64(a2, l2, c1) - a2, c3 = bits.Add64(a3, l3, c2) - a3, c4 = bits.Add64(a4, l4, c3) - a4, c5 = bits.Add64(a5, l5, c4) - a5, a6 = bits.Add64(a6, l6, c5) - - a0, c0 = bits.Add64(a0, h0, 0) - a1, c1 = bits.Add64(a1, h1, c0) - a2, c2 = bits.Add64(a2, h2, c1) - a3, c3 = bits.Add64(a3, h3, c2) - a4, c4 = bits.Add64(a4, h4, c3) - a5, c5 = bits.Add64(a5, h5, c4) - a6, _ = bits.Add64(a6, h6, c5) - } - red64(z, &zz, &[7]uint64{a0, a1, a2, a3, a4, a5, a6}) -} - -func sqrGeneric(z, x *Elt) { mulGeneric(z, x, x) } - -func red64(z *Elt, l, h *[7]uint64) { - /* (2C13, 2C12, 2C11, 2C10|C10, C9, C8, C7) + (C6,...,C0) */ - h0 := h[0] - h1 := h[1] - h2 := h[2] - h3 := ((h[3] & (0xFFFFFFFF << 32)) << 1) | (h[3] & 0xFFFFFFFF) - h4 := (h[3] >> 63) | (h[4] << 1) - h5 := (h[4] >> 63) | (h[5] << 1) - h6 := (h[5] >> 63) | (h[6] << 1) - h7 := (h[6] >> 63) - - l0, c0 := bits.Add64(h0, l[0], 0) - l1, c1 := bits.Add64(h1, l[1], c0) - l2, c2 := bits.Add64(h2, l[2], c1) - l3, c3 := bits.Add64(h3, l[3], c2) - l4, c4 := bits.Add64(h4, l[4], c3) - l5, c5 := bits.Add64(h5, l[5], c4) - l6, c6 := bits.Add64(h6, l[6], c5) - l7, _ := bits.Add64(h7, 0, c6) - - /* (C10C9, C9C8,C8C7,C7C13,C13C12,C12C11,C11C10) + (C6,...,C0) */ - h0 = (h[3] >> 32) | (h[4] << 32) - h1 = (h[4] >> 32) | (h[5] << 32) - h2 = (h[5] >> 32) | (h[6] << 32) - h3 = (h[6] >> 32) | (h[0] << 32) - h4 = (h[0] >> 32) | (h[1] << 32) - h5 = (h[1] >> 32) | (h[2] << 32) - h6 = (h[2] >> 32) | (h[3] << 32) - - l0, c0 = bits.Add64(l0, h0, 0) - l1, c1 = bits.Add64(l1, h1, c0) - l2, c2 = bits.Add64(l2, h2, c1) - l3, c3 = bits.Add64(l3, h3, c2) - l4, c4 = bits.Add64(l4, h4, c3) - l5, c5 = bits.Add64(l5, h5, c4) - l6, c6 = bits.Add64(l6, h6, c5) - l7, _ = bits.Add64(l7, 0, c6) - - /* (C7) + (C6,...,C0) */ - l0, c0 = bits.Add64(l0, l7, 0) - l1, c1 = bits.Add64(l1, 0, c0) - l2, c2 = bits.Add64(l2, 0, c1) - l3, c3 = bits.Add64(l3, l7<<32, c2) - l4, c4 = bits.Add64(l4, 0, c3) - l5, c5 = bits.Add64(l5, 0, c4) - l6, l7 = bits.Add64(l6, 0, c5) - - /* (C7) + (C6,...,C0) */ - l0, c0 = bits.Add64(l0, l7, 0) - l1, c1 = bits.Add64(l1, 0, c0) - l2, c2 = bits.Add64(l2, 0, c1) - l3, c3 = bits.Add64(l3, l7<<32, c2) - l4, c4 = bits.Add64(l4, 0, c3) - l5, c5 = bits.Add64(l5, 0, c4) - l6, _ = bits.Add64(l6, 0, c5) - - binary.LittleEndian.PutUint64(z[0*8:1*8], l0) - binary.LittleEndian.PutUint64(z[1*8:2*8], l1) - binary.LittleEndian.PutUint64(z[2*8:3*8], l2) - binary.LittleEndian.PutUint64(z[3*8:4*8], l3) - binary.LittleEndian.PutUint64(z[4*8:5*8], l4) - binary.LittleEndian.PutUint64(z[5*8:6*8], l5) - binary.LittleEndian.PutUint64(z[6*8:7*8], l6) -} diff --git a/vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go b/vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go deleted file mode 100644 index a62225d2..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !amd64 || purego -// +build !amd64 purego - -package fp448 - -func cmov(x, y *Elt, n uint) { cmovGeneric(x, y, n) } -func cswap(x, y *Elt, n uint) { cswapGeneric(x, y, n) } -func add(z, x, y *Elt) { addGeneric(z, x, y) } -func sub(z, x, y *Elt) { subGeneric(z, x, y) } -func addsub(x, y *Elt) { addsubGeneric(x, y) } -func mul(z, x, y *Elt) { mulGeneric(z, x, y) } -func sqr(z, x *Elt) { sqrGeneric(z, x) } diff --git a/vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go b/vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go deleted file mode 100644 index 2d7afc80..00000000 --- a/vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go +++ /dev/null @@ -1,75 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -// How to run the fuzzer: -// -// $ go get -u github.com/dvyukov/go-fuzz/go-fuzz -// $ go get -u github.com/dvyukov/go-fuzz/go-fuzz-build -// $ go-fuzz-build -libfuzzer -func FuzzReduction -o lib.a -// $ clang -fsanitize=fuzzer lib.a -o fu.exe -// $ ./fu.exe -package fp448 - -import ( - "encoding/binary" - "fmt" - "math/big" - - "github.com/cloudflare/circl/internal/conv" -) - -// FuzzReduction is a fuzzer target for red64 function, which reduces t -// (112 bits) to a number t' (56 bits) congruent modulo p448. -func FuzzReduction(data []byte) int { - if len(data) != 2*Size { - return -1 - } - var got, want Elt - var lo, hi [7]uint64 - a := data[:Size] - b := data[Size:] - lo[0] = binary.LittleEndian.Uint64(a[0*8 : 1*8]) - lo[1] = binary.LittleEndian.Uint64(a[1*8 : 2*8]) - lo[2] = binary.LittleEndian.Uint64(a[2*8 : 3*8]) - lo[3] = binary.LittleEndian.Uint64(a[3*8 : 4*8]) - lo[4] = binary.LittleEndian.Uint64(a[4*8 : 5*8]) - lo[5] = binary.LittleEndian.Uint64(a[5*8 : 6*8]) - lo[6] = binary.LittleEndian.Uint64(a[6*8 : 7*8]) - - hi[0] = binary.LittleEndian.Uint64(b[0*8 : 1*8]) - hi[1] = binary.LittleEndian.Uint64(b[1*8 : 2*8]) - hi[2] = binary.LittleEndian.Uint64(b[2*8 : 3*8]) - hi[3] = binary.LittleEndian.Uint64(b[3*8 : 4*8]) - hi[4] = binary.LittleEndian.Uint64(b[4*8 : 5*8]) - hi[5] = binary.LittleEndian.Uint64(b[5*8 : 6*8]) - hi[6] = binary.LittleEndian.Uint64(b[6*8 : 7*8]) - - red64(&got, &lo, &hi) - - t := conv.BytesLe2BigInt(data[:2*Size]) - - two448 := big.NewInt(1) - two448.Lsh(two448, 448) // 2^448 - mask448 := big.NewInt(1) - mask448.Sub(two448, mask448) // 2^448-1 - two224plus1 := big.NewInt(1) - two224plus1.Lsh(two224plus1, 224) - two224plus1.Add(two224plus1, big.NewInt(1)) // 2^224+1 - - var loBig, hiBig big.Int - for t.Cmp(two448) >= 0 { - loBig.And(t, mask448) - hiBig.Rsh(t, 448) - t.Mul(&hiBig, two224plus1) - t.Add(t, &loBig) - } - conv.BigInt2BytesLe(want[:], t) - - if got != want { - fmt.Printf("in: %v\n", conv.BytesLe2BigInt(data[:2*Size])) - fmt.Printf("got: %v\n", got) - fmt.Printf("want: %v\n", want) - panic("error found") - } - return 1 -} diff --git a/vendor/github.com/cloudflare/circl/math/integer.go b/vendor/github.com/cloudflare/circl/math/integer.go deleted file mode 100644 index 9c80c23b..00000000 --- a/vendor/github.com/cloudflare/circl/math/integer.go +++ /dev/null @@ -1,16 +0,0 @@ -package math - -import "math/bits" - -// NextPow2 finds the next power of two (N=2^k, k>=0) greater than n. -// If n is already a power of two, then this function returns n, and log2(n). -func NextPow2(n uint) (N uint, k uint) { - if bits.OnesCount(n) == 1 { - k = uint(bits.TrailingZeros(n)) - N = n - } else { - k = uint(bits.Len(n)) - N = uint(1) << k - } - return -} diff --git a/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go b/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go deleted file mode 100644 index a43851b8..00000000 --- a/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go +++ /dev/null @@ -1,122 +0,0 @@ -// Package mlsbset provides a constant-time exponentiation method with precomputation. -// -// References: "Efficient and secure algorithms for GLV-based scalar -// multiplication and their implementation on GLV–GLS curves" by (Faz-Hernandez et al.) -// - https://doi.org/10.1007/s13389-014-0085-7 -// - https://eprint.iacr.org/2013/158 -package mlsbset - -import ( - "errors" - "fmt" - "math/big" - - "github.com/cloudflare/circl/internal/conv" -) - -// EltG is a group element. -type EltG interface{} - -// EltP is a precomputed group element. -type EltP interface{} - -// Group defines the operations required by MLSBSet exponentiation method. -type Group interface { - Identity() EltG // Returns the identity of the group. - Sqr(x EltG) // Calculates x = x^2. - Mul(x EltG, y EltP) // Calculates x = x*y. - NewEltP() EltP // Returns an arbitrary precomputed element. - ExtendedEltP() EltP // Returns the precomputed element x^(2^(w*d)). - Lookup(a EltP, v uint, s, u int32) // Sets a = s*T[v][u]. -} - -// Params contains the parameters of the encoding. -type Params struct { - T uint // T is the maximum size (in bits) of exponents. - V uint // V is the number of tables. - W uint // W is the window size. - E uint // E is the number of digits per table. - D uint // D is the number of digits in total. - L uint // L is the length of the code. -} - -// Encoder allows to convert integers into valid powers. -type Encoder struct{ p Params } - -// New produces an encoder of the MLSBSet algorithm. -func New(t, v, w uint) (Encoder, error) { - if !(t > 1 && v >= 1 && w >= 2) { - return Encoder{}, errors.New("t>1, v>=1, w>=2") - } - e := (t + w*v - 1) / (w * v) - d := e * v - l := d * w - return Encoder{Params{t, v, w, e, d, l}}, nil -} - -// Encode converts an odd integer k into a valid power for exponentiation. -func (m Encoder) Encode(k []byte) (*Power, error) { - if len(k) == 0 { - return nil, errors.New("empty slice") - } - if !(len(k) <= int(m.p.L+7)>>3) { - return nil, errors.New("k too big") - } - if k[0]%2 == 0 { - return nil, errors.New("k must be odd") - } - ap := int((m.p.L+7)/8) - len(k) - k = append(k, make([]byte, ap)...) - s := m.signs(k) - b := make([]int32, m.p.L-m.p.D) - c := conv.BytesLe2BigInt(k) - c.Rsh(c, m.p.D) - var bi big.Int - for i := m.p.D; i < m.p.L; i++ { - c0 := int32(c.Bit(0)) - b[i-m.p.D] = s[i%m.p.D] * c0 - bi.SetInt64(int64(b[i-m.p.D] >> 1)) - c.Rsh(c, 1) - c.Sub(c, &bi) - } - carry := int(c.Int64()) - return &Power{m, s, b, carry}, nil -} - -// signs calculates the set of signs. -func (m Encoder) signs(k []byte) []int32 { - s := make([]int32, m.p.D) - s[m.p.D-1] = 1 - for i := uint(1); i < m.p.D; i++ { - ki := int32((k[i>>3] >> (i & 0x7)) & 0x1) - s[i-1] = 2*ki - 1 - } - return s -} - -// GetParams returns the complementary parameters of the encoding. -func (m Encoder) GetParams() Params { return m.p } - -// tableSize returns the size of each table. -func (m Encoder) tableSize() uint { return 1 << (m.p.W - 1) } - -// Elts returns the total number of elements that must be precomputed. -func (m Encoder) Elts() uint { return m.p.V * m.tableSize() } - -// IsExtended returns true if the element x^(2^(wd)) must be calculated. -func (m Encoder) IsExtended() bool { q := m.p.T / (m.p.V * m.p.W); return m.p.T == q*m.p.V*m.p.W } - -// Ops returns the number of squares and multiplications executed during an exponentiation. -func (m Encoder) Ops() (S uint, M uint) { - S = m.p.E - M = m.p.E * m.p.V - if m.IsExtended() { - M++ - } - return -} - -func (m Encoder) String() string { - return fmt.Sprintf("T: %v W: %v V: %v e: %v d: %v l: %v wv|t: %v", - m.p.T, m.p.W, m.p.V, m.p.E, m.p.D, m.p.L, m.IsExtended()) -} diff --git a/vendor/github.com/cloudflare/circl/math/mlsbset/power.go b/vendor/github.com/cloudflare/circl/math/mlsbset/power.go deleted file mode 100644 index 3f214c30..00000000 --- a/vendor/github.com/cloudflare/circl/math/mlsbset/power.go +++ /dev/null @@ -1,64 +0,0 @@ -package mlsbset - -import "fmt" - -// Power is a valid exponent produced by the MLSBSet encoding algorithm. -type Power struct { - set Encoder // parameters of code. - s []int32 // set of signs. - b []int32 // set of digits. - c int // carry is {0,1}. -} - -// Exp is calculates x^k, where x is a predetermined element of a group G. -func (p *Power) Exp(G Group) EltG { - a, b := G.Identity(), G.NewEltP() - for e := int(p.set.p.E - 1); e >= 0; e-- { - G.Sqr(a) - for v := uint(0); v < p.set.p.V; v++ { - sgnElt, idElt := p.Digit(v, uint(e)) - G.Lookup(b, v, sgnElt, idElt) - G.Mul(a, b) - } - } - if p.set.IsExtended() && p.c == 1 { - G.Mul(a, G.ExtendedEltP()) - } - return a -} - -// Digit returns the (v,e)-th digit and its sign. -func (p *Power) Digit(v, e uint) (sgn, dig int32) { - sgn = p.bit(0, v, e) - dig = 0 - for i := p.set.p.W - 1; i > 0; i-- { - dig = 2*dig + p.bit(i, v, e) - } - mask := dig >> 31 - dig = (dig + mask) ^ mask - return sgn, dig -} - -// bit returns the (w,v,e)-th bit of the code. -func (p *Power) bit(w, v, e uint) int32 { - if !(w < p.set.p.W && - v < p.set.p.V && - e < p.set.p.E) { - panic(fmt.Errorf("indexes outside (%v,%v,%v)", w, v, e)) - } - if w == 0 { - return p.s[p.set.p.E*v+e] - } - return p.b[p.set.p.D*(w-1)+p.set.p.E*v+e] -} - -func (p *Power) String() string { - dig := "" - for j := uint(0); j < p.set.p.V; j++ { - for i := uint(0); i < p.set.p.E; i++ { - s, d := p.Digit(j, i) - dig += fmt.Sprintf("(%2v,%2v) = %+2v %+2v\n", j, i, s, d) - } - } - return fmt.Sprintf("len: %v\ncarry: %v\ndigits:\n%v", len(p.b)+len(p.s), p.c, dig) -} diff --git a/vendor/github.com/cloudflare/circl/math/primes.go b/vendor/github.com/cloudflare/circl/math/primes.go deleted file mode 100644 index 158fd83a..00000000 --- a/vendor/github.com/cloudflare/circl/math/primes.go +++ /dev/null @@ -1,34 +0,0 @@ -package math - -import ( - "crypto/rand" - "io" - "math/big" -) - -// IsSafePrime reports whether p is (probably) a safe prime. -// The prime p=2*q+1 is safe prime if both p and q are primes. -// Note that ProbablyPrime is not suitable for judging primes -// that an adversary may have crafted to fool the test. -func IsSafePrime(p *big.Int) bool { - pdiv2 := new(big.Int).Rsh(p, 1) - return p.ProbablyPrime(20) && pdiv2.ProbablyPrime(20) -} - -// SafePrime returns a number of the given bit length that is a safe prime with high probability. -// The number returned p=2*q+1 is a safe prime if both p and q are primes. -// SafePrime will return error for any error returned by rand.Read or if bits < 2. -func SafePrime(random io.Reader, bits int) (*big.Int, error) { - one := big.NewInt(1) - p := new(big.Int) - for { - q, err := rand.Prime(random, bits-1) - if err != nil { - return nil, err - } - p.Lsh(q, 1).Add(p, one) - if p.ProbablyPrime(20) { - return p, nil - } - } -} diff --git a/vendor/github.com/cloudflare/circl/math/wnaf.go b/vendor/github.com/cloudflare/circl/math/wnaf.go deleted file mode 100644 index 94a1ec50..00000000 --- a/vendor/github.com/cloudflare/circl/math/wnaf.go +++ /dev/null @@ -1,84 +0,0 @@ -// Package math provides some utility functions for big integers. -package math - -import "math/big" - -// SignedDigit obtains the signed-digit recoding of n and returns a list L of -// digits such that n = sum( L[i]*2^(i*(w-1)) ), and each L[i] is an odd number -// in the set {±1, ±3, ..., ±2^(w-1)-1}. The third parameter ensures that the -// output has ceil(l/(w-1)) digits. -// -// Restrictions: -// - n is odd and n > 0. -// - 1 < w < 32. -// - l >= bit length of n. -// -// References: -// - Alg.6 in "Exponent Recoding and Regular Exponentiation Algorithms" -// by Joye-Tunstall. http://doi.org/10.1007/978-3-642-02384-2_21 -// - Alg.6 in "Selecting Elliptic Curves for Cryptography: An Efficiency and -// Security Analysis" by Bos et al. http://doi.org/10.1007/s13389-015-0097-y -func SignedDigit(n *big.Int, w, l uint) []int32 { - if n.Sign() <= 0 || n.Bit(0) == 0 { - panic("n must be non-zero, odd, and positive") - } - if w <= 1 || w >= 32 { - panic("Verify that 1 < w < 32") - } - if uint(n.BitLen()) > l { - panic("n is too big to fit in l digits") - } - lenN := (l + (w - 1) - 1) / (w - 1) // ceil(l/(w-1)) - L := make([]int32, lenN+1) - var k, v big.Int - k.Set(n) - - var i uint - for i = 0; i < lenN; i++ { - words := k.Bits() - value := int32(words[0] & ((1 << w) - 1)) - value -= int32(1) << (w - 1) - L[i] = value - v.SetInt64(int64(value)) - k.Sub(&k, &v) - k.Rsh(&k, w-1) - } - L[i] = int32(k.Int64()) - return L -} - -// OmegaNAF obtains the window-w Non-Adjacent Form of a positive number n and -// 1 < w < 32. The returned slice L holds n = sum( L[i]*2^i ). -// -// Reference: -// - Alg.9 "Efficient arithmetic on Koblitz curves" by Solinas. -// http://doi.org/10.1023/A:1008306223194 -func OmegaNAF(n *big.Int, w uint) (L []int32) { - if n.Sign() < 0 { - panic("n must be positive") - } - if w <= 1 || w >= 32 { - panic("Verify that 1 < w < 32") - } - - L = make([]int32, n.BitLen()+1) - var k, v big.Int - k.Set(n) - - i := 0 - for ; k.Sign() > 0; i++ { - value := int32(0) - if k.Bit(0) == 1 { - words := k.Bits() - value = int32(words[0] & ((1 << w) - 1)) - if value >= (int32(1) << (w - 1)) { - value -= int32(1) << w - } - v.SetInt64(int64(value)) - k.Sub(&k, &v) - } - L[i] = value - k.Rsh(&k, 1) - } - return L[:i] -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go b/vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go deleted file mode 100644 index 2c73c26f..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go +++ /dev/null @@ -1,453 +0,0 @@ -// Package ed25519 implements Ed25519 signature scheme as described in RFC-8032. -// -// This package provides optimized implementations of the three signature -// variants and maintaining closer compatibility with crypto/ed25519. -// -// | Scheme Name | Sign Function | Verification | Context | -// |-------------|-------------------|---------------|-------------------| -// | Ed25519 | Sign | Verify | None | -// | Ed25519Ph | SignPh | VerifyPh | Yes, can be empty | -// | Ed25519Ctx | SignWithCtx | VerifyWithCtx | Yes, non-empty | -// | All above | (PrivateKey).Sign | VerifyAny | As above | -// -// Specific functions for sign and verify are defined. A generic signing -// function for all schemes is available through the crypto.Signer interface, -// which is implemented by the PrivateKey type. A correspond all-in-one -// verification method is provided by the VerifyAny function. -// -// Signing with Ed25519Ph or Ed25519Ctx requires a context string for domain -// separation. This parameter is passed using a SignerOptions struct defined -// in this package. While Ed25519Ph accepts an empty context, Ed25519Ctx -// enforces non-empty context strings. -// -// # Compatibility with crypto.ed25519 -// -// These functions are compatible with the “Ed25519” function defined in -// RFC-8032. However, unlike RFC 8032's formulation, this package's private -// key representation includes a public key suffix to make multiple signing -// operations with the same key more efficient. This package refers to the -// RFC-8032 private key as the “seed”. -// -// References -// -// - RFC-8032: https://rfc-editor.org/rfc/rfc8032.txt -// - Ed25519: https://ed25519.cr.yp.to/ -// - EdDSA: High-speed high-security signatures. https://doi.org/10.1007/s13389-012-0027-1 -package ed25519 - -import ( - "bytes" - "crypto" - cryptoRand "crypto/rand" - "crypto/sha512" - "crypto/subtle" - "errors" - "fmt" - "io" - "strconv" - - "github.com/cloudflare/circl/sign" -) - -const ( - // ContextMaxSize is the maximum length (in bytes) allowed for context. - ContextMaxSize = 255 - // PublicKeySize is the size, in bytes, of public keys as used in this package. - PublicKeySize = 32 - // PrivateKeySize is the size, in bytes, of private keys as used in this package. - PrivateKeySize = 64 - // SignatureSize is the size, in bytes, of signatures generated and verified by this package. - SignatureSize = 64 - // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. - SeedSize = 32 -) - -const ( - paramB = 256 / 8 // Size of keys in bytes. -) - -// SignerOptions implements crypto.SignerOpts and augments with parameters -// that are specific to the Ed25519 signature schemes. -type SignerOptions struct { - // Hash must be crypto.Hash(0) for Ed25519/Ed25519ctx, or crypto.SHA512 - // for Ed25519ph. - crypto.Hash - - // Context is an optional domain separation string for Ed25519ph and a - // must for Ed25519ctx. Its length must be less or equal than 255 bytes. - Context string - - // Scheme is an identifier for choosing a signature scheme. The zero value - // is ED25519. - Scheme SchemeID -} - -// SchemeID is an identifier for each signature scheme. -type SchemeID uint - -const ( - ED25519 SchemeID = iota - ED25519Ph - ED25519Ctx -) - -// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. -type PrivateKey []byte - -// Equal reports whether priv and x have the same value. -func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { - xx, ok := x.(PrivateKey) - return ok && subtle.ConstantTimeCompare(priv, xx) == 1 -} - -// Public returns the PublicKey corresponding to priv. -func (priv PrivateKey) Public() crypto.PublicKey { - publicKey := make(PublicKey, PublicKeySize) - copy(publicKey, priv[SeedSize:]) - return publicKey -} - -// Seed returns the private key seed corresponding to priv. It is provided for -// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds -// in this package. -func (priv PrivateKey) Seed() []byte { - seed := make([]byte, SeedSize) - copy(seed, priv[:SeedSize]) - return seed -} - -func (priv PrivateKey) Scheme() sign.Scheme { return sch } - -func (pub PublicKey) Scheme() sign.Scheme { return sch } - -func (priv PrivateKey) MarshalBinary() (data []byte, err error) { - privateKey := make(PrivateKey, PrivateKeySize) - copy(privateKey, priv) - return privateKey, nil -} - -func (pub PublicKey) MarshalBinary() (data []byte, err error) { - publicKey := make(PublicKey, PublicKeySize) - copy(publicKey, pub) - return publicKey, nil -} - -// Equal reports whether pub and x have the same value. -func (pub PublicKey) Equal(x crypto.PublicKey) bool { - xx, ok := x.(PublicKey) - return ok && bytes.Equal(pub, xx) -} - -// Sign creates a signature of a message with priv key. -// This function is compatible with crypto.ed25519 and also supports the -// three signature variants defined in RFC-8032, namely Ed25519 (or pure -// EdDSA), Ed25519Ph, and Ed25519Ctx. -// The opts.HashFunc() must return zero to specify either Ed25519 or Ed25519Ctx -// variant. This can be achieved by passing crypto.Hash(0) as the value for -// opts. -// The opts.HashFunc() must return SHA512 to specify the Ed25519Ph variant. -// This can be achieved by passing crypto.SHA512 as the value for opts. -// Use a SignerOptions struct (defined in this package) to pass a context -// string for signing. -func (priv PrivateKey) Sign( - rand io.Reader, - message []byte, - opts crypto.SignerOpts, -) (signature []byte, err error) { - var ctx string - var scheme SchemeID - if o, ok := opts.(SignerOptions); ok { - ctx = o.Context - scheme = o.Scheme - } - - switch true { - case scheme == ED25519 && opts.HashFunc() == crypto.Hash(0): - return Sign(priv, message), nil - case scheme == ED25519Ph && opts.HashFunc() == crypto.SHA512: - return SignPh(priv, message, ctx), nil - case scheme == ED25519Ctx && opts.HashFunc() == crypto.Hash(0) && len(ctx) > 0: - return SignWithCtx(priv, message, ctx), nil - default: - return nil, errors.New("ed25519: bad hash algorithm") - } -} - -// GenerateKey generates a public/private key pair using entropy from rand. -// If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - if rand == nil { - rand = cryptoRand.Reader - } - - seed := make([]byte, SeedSize) - if _, err := io.ReadFull(rand, seed); err != nil { - return nil, nil, err - } - - privateKey := NewKeyFromSeed(seed) - publicKey := make(PublicKey, PublicKeySize) - copy(publicKey, privateKey[SeedSize:]) - - return publicKey, privateKey, nil -} - -// NewKeyFromSeed calculates a private key from a seed. It will panic if -// len(seed) is not SeedSize. This function is provided for interoperability -// with RFC 8032. RFC 8032's private keys correspond to seeds in this -// package. -func NewKeyFromSeed(seed []byte) PrivateKey { - privateKey := make(PrivateKey, PrivateKeySize) - newKeyFromSeed(privateKey, seed) - return privateKey -} - -func newKeyFromSeed(privateKey, seed []byte) { - if l := len(seed); l != SeedSize { - panic("ed25519: bad seed length: " + strconv.Itoa(l)) - } - var P pointR1 - k := sha512.Sum512(seed) - clamp(k[:]) - reduceModOrder(k[:paramB], false) - P.fixedMult(k[:paramB]) - copy(privateKey[:SeedSize], seed) - _ = P.ToBytes(privateKey[SeedSize:]) -} - -func signAll(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) { - if l := len(privateKey); l != PrivateKeySize { - panic("ed25519: bad private key length: " + strconv.Itoa(l)) - } - - H := sha512.New() - var PHM []byte - - if preHash { - _, _ = H.Write(message) - PHM = H.Sum(nil) - H.Reset() - } else { - PHM = message - } - - // 1. Hash the 32-byte private key using SHA-512. - _, _ = H.Write(privateKey[:SeedSize]) - h := H.Sum(nil) - clamp(h[:]) - prefix, s := h[paramB:], h[:paramB] - - // 2. Compute SHA-512(dom2(F, C) || prefix || PH(M)) - H.Reset() - - writeDom(H, ctx, preHash) - - _, _ = H.Write(prefix) - _, _ = H.Write(PHM) - r := H.Sum(nil) - reduceModOrder(r[:], true) - - // 3. Compute the point [r]B. - var P pointR1 - P.fixedMult(r[:paramB]) - R := (&[paramB]byte{})[:] - if err := P.ToBytes(R); err != nil { - panic(err) - } - - // 4. Compute SHA512(dom2(F, C) || R || A || PH(M)). - H.Reset() - - writeDom(H, ctx, preHash) - - _, _ = H.Write(R) - _, _ = H.Write(privateKey[SeedSize:]) - _, _ = H.Write(PHM) - hRAM := H.Sum(nil) - - reduceModOrder(hRAM[:], true) - - // 5. Compute S = (r + k * s) mod order. - S := (&[paramB]byte{})[:] - calculateS(S, r[:paramB], hRAM[:paramB], s) - - // 6. The signature is the concatenation of R and S. - copy(signature[:paramB], R[:]) - copy(signature[paramB:], S[:]) -} - -// Sign signs the message with privateKey and returns a signature. -// This function supports the signature variant defined in RFC-8032: Ed25519, -// also known as the pure version of EdDSA. -// It will panic if len(privateKey) is not PrivateKeySize. -func Sign(privateKey PrivateKey, message []byte) []byte { - signature := make([]byte, SignatureSize) - signAll(signature, privateKey, message, []byte(""), false) - return signature -} - -// SignPh creates a signature of a message with private key and context. -// This function supports the signature variant defined in RFC-8032: Ed25519ph, -// meaning it internally hashes the message using SHA-512, and optionally -// accepts a context string. -// It will panic if len(privateKey) is not PrivateKeySize. -// Context could be passed to this function, which length should be no more than -// ContextMaxSize=255. It can be empty. -func SignPh(privateKey PrivateKey, message []byte, ctx string) []byte { - if len(ctx) > ContextMaxSize { - panic(fmt.Errorf("ed25519: bad context length: %v", len(ctx))) - } - - signature := make([]byte, SignatureSize) - signAll(signature, privateKey, message, []byte(ctx), true) - return signature -} - -// SignWithCtx creates a signature of a message with private key and context. -// This function supports the signature variant defined in RFC-8032: Ed25519ctx, -// meaning it accepts a non-empty context string. -// It will panic if len(privateKey) is not PrivateKeySize. -// Context must be passed to this function, which length should be no more than -// ContextMaxSize=255 and cannot be empty. -func SignWithCtx(privateKey PrivateKey, message []byte, ctx string) []byte { - if len(ctx) == 0 || len(ctx) > ContextMaxSize { - panic(fmt.Errorf("ed25519: bad context length: %v > %v", len(ctx), ContextMaxSize)) - } - - signature := make([]byte, SignatureSize) - signAll(signature, privateKey, message, []byte(ctx), false) - return signature -} - -func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool { - if len(public) != PublicKeySize || - len(signature) != SignatureSize || - !isLessThanOrder(signature[paramB:]) { - return false - } - - var P pointR1 - if ok := P.FromBytes(public); !ok { - return false - } - - H := sha512.New() - var PHM []byte - - if preHash { - _, _ = H.Write(message) - PHM = H.Sum(nil) - H.Reset() - } else { - PHM = message - } - - R := signature[:paramB] - - writeDom(H, ctx, preHash) - - _, _ = H.Write(R) - _, _ = H.Write(public) - _, _ = H.Write(PHM) - hRAM := H.Sum(nil) - reduceModOrder(hRAM[:], true) - - var Q pointR1 - encR := (&[paramB]byte{})[:] - P.neg() - Q.doubleMult(&P, signature[paramB:], hRAM[:paramB]) - _ = Q.ToBytes(encR) - return bytes.Equal(R, encR) -} - -// VerifyAny returns true if the signature is valid. Failure cases are invalid -// signature, or when the public key cannot be decoded. -// This function supports all the three signature variants defined in RFC-8032, -// namely Ed25519 (or pure EdDSA), Ed25519Ph, and Ed25519Ctx. -// The opts.HashFunc() must return zero to specify either Ed25519 or Ed25519Ctx -// variant. This can be achieved by passing crypto.Hash(0) as the value for opts. -// The opts.HashFunc() must return SHA512 to specify the Ed25519Ph variant. -// This can be achieved by passing crypto.SHA512 as the value for opts. -// Use a SignerOptions struct to pass a context string for signing. -func VerifyAny(public PublicKey, message, signature []byte, opts crypto.SignerOpts) bool { - var ctx string - var scheme SchemeID - if o, ok := opts.(SignerOptions); ok { - ctx = o.Context - scheme = o.Scheme - } - - switch true { - case scheme == ED25519 && opts.HashFunc() == crypto.Hash(0): - return Verify(public, message, signature) - case scheme == ED25519Ph && opts.HashFunc() == crypto.SHA512: - return VerifyPh(public, message, signature, ctx) - case scheme == ED25519Ctx && opts.HashFunc() == crypto.Hash(0) && len(ctx) > 0: - return VerifyWithCtx(public, message, signature, ctx) - default: - return false - } -} - -// Verify returns true if the signature is valid. Failure cases are invalid -// signature, or when the public key cannot be decoded. -// This function supports the signature variant defined in RFC-8032: Ed25519, -// also known as the pure version of EdDSA. -func Verify(public PublicKey, message, signature []byte) bool { - return verify(public, message, signature, []byte(""), false) -} - -// VerifyPh returns true if the signature is valid. Failure cases are invalid -// signature, or when the public key cannot be decoded. -// This function supports the signature variant defined in RFC-8032: Ed25519ph, -// meaning it internally hashes the message using SHA-512. -// Context could be passed to this function, which length should be no more than -// 255. It can be empty. -func VerifyPh(public PublicKey, message, signature []byte, ctx string) bool { - return verify(public, message, signature, []byte(ctx), true) -} - -// VerifyWithCtx returns true if the signature is valid. Failure cases are invalid -// signature, or when the public key cannot be decoded, or when context is -// not provided. -// This function supports the signature variant defined in RFC-8032: Ed25519ctx, -// meaning it does not handle prehashed messages. Non-empty context string must be -// provided, and must not be more than 255 of length. -func VerifyWithCtx(public PublicKey, message, signature []byte, ctx string) bool { - if len(ctx) == 0 || len(ctx) > ContextMaxSize { - return false - } - - return verify(public, message, signature, []byte(ctx), false) -} - -func clamp(k []byte) { - k[0] &= 248 - k[paramB-1] = (k[paramB-1] & 127) | 64 -} - -// isLessThanOrder returns true if 0 <= x < order. -func isLessThanOrder(x []byte) bool { - i := len(order) - 1 - for i > 0 && x[i] == order[i] { - i-- - } - return x[i] < order[i] -} - -func writeDom(h io.Writer, ctx []byte, preHash bool) { - dom2 := "SigEd25519 no Ed25519 collisions" - - if len(ctx) > 0 { - _, _ = h.Write([]byte(dom2)) - if preHash { - _, _ = h.Write([]byte{byte(0x01), byte(len(ctx))}) - } else { - _, _ = h.Write([]byte{byte(0x00), byte(len(ctx))}) - } - _, _ = h.Write(ctx) - } else if preHash { - _, _ = h.Write([]byte(dom2)) - _, _ = h.Write([]byte{0x01, 0x00}) - } -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/modular.go b/vendor/github.com/cloudflare/circl/sign/ed25519/modular.go deleted file mode 100644 index 10efafdc..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/modular.go +++ /dev/null @@ -1,175 +0,0 @@ -package ed25519 - -import ( - "encoding/binary" - "math/bits" -) - -var order = [paramB]byte{ - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, - 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -} - -// isLessThan returns true if 0 <= x < y, and assumes that slices have the same length. -func isLessThan(x, y []byte) bool { - i := len(x) - 1 - for i > 0 && x[i] == y[i] { - i-- - } - return x[i] < y[i] -} - -// reduceModOrder calculates k = k mod order of the curve. -func reduceModOrder(k []byte, is512Bit bool) { - var X [((2 * paramB) * 8) / 64]uint64 - numWords := len(k) >> 3 - for i := 0; i < numWords; i++ { - X[i] = binary.LittleEndian.Uint64(k[i*8 : (i+1)*8]) - } - red512(&X, is512Bit) - for i := 0; i < numWords; i++ { - binary.LittleEndian.PutUint64(k[i*8:(i+1)*8], X[i]) - } -} - -// red512 calculates x = x mod Order of the curve. -func red512(x *[8]uint64, full bool) { - // Implementation of Algs.(14.47)+(14.52) of Handbook of Applied - // Cryptography, by A. Menezes, P. van Oorschot, and S. Vanstone. - const ( - ell0 = uint64(0x5812631a5cf5d3ed) - ell1 = uint64(0x14def9dea2f79cd6) - ell160 = uint64(0x812631a5cf5d3ed0) - ell161 = uint64(0x4def9dea2f79cd65) - ell162 = uint64(0x0000000000000001) - ) - - var c0, c1, c2, c3 uint64 - r0, r1, r2, r3, r4 := x[0], x[1], x[2], x[3], uint64(0) - - if full { - q0, q1, q2, q3 := x[4], x[5], x[6], x[7] - - for i := 0; i < 3; i++ { - h0, s0 := bits.Mul64(q0, ell160) - h1, s1 := bits.Mul64(q1, ell160) - h2, s2 := bits.Mul64(q2, ell160) - h3, s3 := bits.Mul64(q3, ell160) - - s1, c0 = bits.Add64(h0, s1, 0) - s2, c1 = bits.Add64(h1, s2, c0) - s3, c2 = bits.Add64(h2, s3, c1) - s4, _ := bits.Add64(h3, 0, c2) - - h0, l0 := bits.Mul64(q0, ell161) - h1, l1 := bits.Mul64(q1, ell161) - h2, l2 := bits.Mul64(q2, ell161) - h3, l3 := bits.Mul64(q3, ell161) - - l1, c0 = bits.Add64(h0, l1, 0) - l2, c1 = bits.Add64(h1, l2, c0) - l3, c2 = bits.Add64(h2, l3, c1) - l4, _ := bits.Add64(h3, 0, c2) - - s1, c0 = bits.Add64(s1, l0, 0) - s2, c1 = bits.Add64(s2, l1, c0) - s3, c2 = bits.Add64(s3, l2, c1) - s4, c3 = bits.Add64(s4, l3, c2) - s5, s6 := bits.Add64(l4, 0, c3) - - s2, c0 = bits.Add64(s2, q0, 0) - s3, c1 = bits.Add64(s3, q1, c0) - s4, c2 = bits.Add64(s4, q2, c1) - s5, c3 = bits.Add64(s5, q3, c2) - s6, s7 := bits.Add64(s6, 0, c3) - - q := q0 | q1 | q2 | q3 - m := -((q | -q) >> 63) // if q=0 then m=0...0 else m=1..1 - s0 &= m - s1 &= m - s2 &= m - s3 &= m - q0, q1, q2, q3 = s4, s5, s6, s7 - - if (i+1)%2 == 0 { - r0, c0 = bits.Add64(r0, s0, 0) - r1, c1 = bits.Add64(r1, s1, c0) - r2, c2 = bits.Add64(r2, s2, c1) - r3, c3 = bits.Add64(r3, s3, c2) - r4, _ = bits.Add64(r4, 0, c3) - } else { - r0, c0 = bits.Sub64(r0, s0, 0) - r1, c1 = bits.Sub64(r1, s1, c0) - r2, c2 = bits.Sub64(r2, s2, c1) - r3, c3 = bits.Sub64(r3, s3, c2) - r4, _ = bits.Sub64(r4, 0, c3) - } - } - - m := -(r4 >> 63) - r0, c0 = bits.Add64(r0, m&ell160, 0) - r1, c1 = bits.Add64(r1, m&ell161, c0) - r2, c2 = bits.Add64(r2, m&ell162, c1) - r3, c3 = bits.Add64(r3, 0, c2) - r4, _ = bits.Add64(r4, m&1, c3) - x[4], x[5], x[6], x[7] = 0, 0, 0, 0 - } - - q0 := (r4 << 4) | (r3 >> 60) - r3 &= (uint64(1) << 60) - 1 - - h0, s0 := bits.Mul64(ell0, q0) - h1, s1 := bits.Mul64(ell1, q0) - s1, c0 = bits.Add64(h0, s1, 0) - s2, _ := bits.Add64(h1, 0, c0) - - r0, c0 = bits.Sub64(r0, s0, 0) - r1, c1 = bits.Sub64(r1, s1, c0) - r2, c2 = bits.Sub64(r2, s2, c1) - r3, _ = bits.Sub64(r3, 0, c2) - - x[0], x[1], x[2], x[3] = r0, r1, r2, r3 -} - -// calculateS performs s = r+k*a mod Order of the curve. -func calculateS(s, r, k, a []byte) { - K := [4]uint64{ - binary.LittleEndian.Uint64(k[0*8 : 1*8]), - binary.LittleEndian.Uint64(k[1*8 : 2*8]), - binary.LittleEndian.Uint64(k[2*8 : 3*8]), - binary.LittleEndian.Uint64(k[3*8 : 4*8]), - } - S := [8]uint64{ - binary.LittleEndian.Uint64(r[0*8 : 1*8]), - binary.LittleEndian.Uint64(r[1*8 : 2*8]), - binary.LittleEndian.Uint64(r[2*8 : 3*8]), - binary.LittleEndian.Uint64(r[3*8 : 4*8]), - } - var c3 uint64 - for i := range K { - ai := binary.LittleEndian.Uint64(a[i*8 : (i+1)*8]) - - h0, l0 := bits.Mul64(K[0], ai) - h1, l1 := bits.Mul64(K[1], ai) - h2, l2 := bits.Mul64(K[2], ai) - h3, l3 := bits.Mul64(K[3], ai) - - l1, c0 := bits.Add64(h0, l1, 0) - l2, c1 := bits.Add64(h1, l2, c0) - l3, c2 := bits.Add64(h2, l3, c1) - l4, _ := bits.Add64(h3, 0, c2) - - S[i+0], c0 = bits.Add64(S[i+0], l0, 0) - S[i+1], c1 = bits.Add64(S[i+1], l1, c0) - S[i+2], c2 = bits.Add64(S[i+2], l2, c1) - S[i+3], c3 = bits.Add64(S[i+3], l3, c2) - S[i+4], _ = bits.Add64(S[i+4], l4, c3) - } - red512(&S, true) - binary.LittleEndian.PutUint64(s[0*8:1*8], S[0]) - binary.LittleEndian.PutUint64(s[1*8:2*8], S[1]) - binary.LittleEndian.PutUint64(s[2*8:3*8], S[2]) - binary.LittleEndian.PutUint64(s[3*8:4*8], S[3]) -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/mult.go b/vendor/github.com/cloudflare/circl/sign/ed25519/mult.go deleted file mode 100644 index 3216aae3..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/mult.go +++ /dev/null @@ -1,180 +0,0 @@ -package ed25519 - -import ( - "crypto/subtle" - "encoding/binary" - "math/bits" - - "github.com/cloudflare/circl/internal/conv" - "github.com/cloudflare/circl/math" - fp "github.com/cloudflare/circl/math/fp25519" -) - -var paramD = fp.Elt{ - 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, - 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, - 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, - 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52, -} - -// mLSBRecoding parameters. -const ( - fxT = 257 - fxV = 2 - fxW = 3 - fx2w1 = 1 << (uint(fxW) - 1) - numWords64 = (paramB * 8 / 64) -) - -// mLSBRecoding is the odd-only modified LSB-set. -// -// Reference: -// -// "Efficient and secure algorithms for GLV-based scalar multiplication and -// their implementation on GLV–GLS curves" by (Faz-Hernandez et al.) -// http://doi.org/10.1007/s13389-014-0085-7. -func mLSBRecoding(L []int8, k []byte) { - const ee = (fxT + fxW*fxV - 1) / (fxW * fxV) - const dd = ee * fxV - const ll = dd * fxW - if len(L) == (ll + 1) { - var m [numWords64 + 1]uint64 - for i := 0; i < numWords64; i++ { - m[i] = binary.LittleEndian.Uint64(k[8*i : 8*i+8]) - } - condAddOrderN(&m) - L[dd-1] = 1 - for i := 0; i < dd-1; i++ { - kip1 := (m[(i+1)/64] >> (uint(i+1) % 64)) & 0x1 - L[i] = int8(kip1<<1) - 1 - } - { // right-shift by d - right := uint(dd % 64) - left := uint(64) - right - lim := ((numWords64+1)*64 - dd) / 64 - j := dd / 64 - for i := 0; i < lim; i++ { - m[i] = (m[i+j] >> right) | (m[i+j+1] << left) - } - m[lim] = m[lim+j] >> right - } - for i := dd; i < ll; i++ { - L[i] = L[i%dd] * int8(m[0]&0x1) - div2subY(m[:], int64(L[i]>>1), numWords64) - } - L[ll] = int8(m[0]) - } -} - -// absolute returns always a positive value. -func absolute(x int32) int32 { - mask := x >> 31 - return (x + mask) ^ mask -} - -// condAddOrderN updates x = x+order if x is even, otherwise x remains unchanged. -func condAddOrderN(x *[numWords64 + 1]uint64) { - isOdd := (x[0] & 0x1) - 1 - c := uint64(0) - for i := 0; i < numWords64; i++ { - orderWord := binary.LittleEndian.Uint64(order[8*i : 8*i+8]) - o := isOdd & orderWord - x0, c0 := bits.Add64(x[i], o, c) - x[i] = x0 - c = c0 - } - x[numWords64], _ = bits.Add64(x[numWords64], 0, c) -} - -// div2subY update x = (x/2) - y. -func div2subY(x []uint64, y int64, l int) { - s := uint64(y >> 63) - for i := 0; i < l-1; i++ { - x[i] = (x[i] >> 1) | (x[i+1] << 63) - } - x[l-1] = (x[l-1] >> 1) - - b := uint64(0) - x0, b0 := bits.Sub64(x[0], uint64(y), b) - x[0] = x0 - b = b0 - for i := 1; i < l-1; i++ { - x0, b0 := bits.Sub64(x[i], s, b) - x[i] = x0 - b = b0 - } - x[l-1], _ = bits.Sub64(x[l-1], s, b) -} - -func (P *pointR1) fixedMult(scalar []byte) { - if len(scalar) != paramB { - panic("wrong scalar size") - } - const ee = (fxT + fxW*fxV - 1) / (fxW * fxV) - const dd = ee * fxV - const ll = dd * fxW - - L := make([]int8, ll+1) - mLSBRecoding(L[:], scalar) - S := &pointR3{} - P.SetIdentity() - for ii := ee - 1; ii >= 0; ii-- { - P.double() - for j := 0; j < fxV; j++ { - dig := L[fxW*dd-j*ee+ii-ee] - for i := (fxW-1)*dd - j*ee + ii - ee; i >= (2*dd - j*ee + ii - ee); i = i - dd { - dig = 2*dig + L[i] - } - idx := absolute(int32(dig)) - sig := L[dd-j*ee+ii-ee] - Tabj := &tabSign[fxV-j-1] - for k := 0; k < fx2w1; k++ { - S.cmov(&Tabj[k], subtle.ConstantTimeEq(int32(k), idx)) - } - S.cneg(subtle.ConstantTimeEq(int32(sig), -1)) - P.mixAdd(S) - } - } -} - -const ( - omegaFix = 7 - omegaVar = 5 -) - -// doubleMult returns P=mG+nQ. -func (P *pointR1) doubleMult(Q *pointR1, m, n []byte) { - nafFix := math.OmegaNAF(conv.BytesLe2BigInt(m), omegaFix) - nafVar := math.OmegaNAF(conv.BytesLe2BigInt(n), omegaVar) - - if len(nafFix) > len(nafVar) { - nafVar = append(nafVar, make([]int32, len(nafFix)-len(nafVar))...) - } else if len(nafFix) < len(nafVar) { - nafFix = append(nafFix, make([]int32, len(nafVar)-len(nafFix))...) - } - - var TabQ [1 << (omegaVar - 2)]pointR2 - Q.oddMultiples(TabQ[:]) - P.SetIdentity() - for i := len(nafFix) - 1; i >= 0; i-- { - P.double() - // Generator point - if nafFix[i] != 0 { - idxM := absolute(nafFix[i]) >> 1 - R := tabVerif[idxM] - if nafFix[i] < 0 { - R.neg() - } - P.mixAdd(&R) - } - // Variable input point - if nafVar[i] != 0 { - idxN := absolute(nafVar[i]) >> 1 - S := TabQ[idxN] - if nafVar[i] < 0 { - S.neg() - } - P.add(&S) - } - } -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/point.go b/vendor/github.com/cloudflare/circl/sign/ed25519/point.go deleted file mode 100644 index d1c3b146..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/point.go +++ /dev/null @@ -1,195 +0,0 @@ -package ed25519 - -import fp "github.com/cloudflare/circl/math/fp25519" - -type ( - pointR1 struct{ x, y, z, ta, tb fp.Elt } - pointR2 struct { - pointR3 - z2 fp.Elt - } -) -type pointR3 struct{ addYX, subYX, dt2 fp.Elt } - -func (P *pointR1) neg() { - fp.Neg(&P.x, &P.x) - fp.Neg(&P.ta, &P.ta) -} - -func (P *pointR1) SetIdentity() { - P.x = fp.Elt{} - fp.SetOne(&P.y) - fp.SetOne(&P.z) - P.ta = fp.Elt{} - P.tb = fp.Elt{} -} - -func (P *pointR1) toAffine() { - fp.Inv(&P.z, &P.z) - fp.Mul(&P.x, &P.x, &P.z) - fp.Mul(&P.y, &P.y, &P.z) - fp.Modp(&P.x) - fp.Modp(&P.y) - fp.SetOne(&P.z) - P.ta = P.x - P.tb = P.y -} - -func (P *pointR1) ToBytes(k []byte) error { - P.toAffine() - var x [fp.Size]byte - err := fp.ToBytes(k[:fp.Size], &P.y) - if err != nil { - return err - } - err = fp.ToBytes(x[:], &P.x) - if err != nil { - return err - } - b := x[0] & 1 - k[paramB-1] = k[paramB-1] | (b << 7) - return nil -} - -func (P *pointR1) FromBytes(k []byte) bool { - if len(k) != paramB { - panic("wrong size") - } - signX := k[paramB-1] >> 7 - copy(P.y[:], k[:fp.Size]) - P.y[fp.Size-1] &= 0x7F - p := fp.P() - if !isLessThan(P.y[:], p[:]) { - return false - } - - one, u, v := &fp.Elt{}, &fp.Elt{}, &fp.Elt{} - fp.SetOne(one) - fp.Sqr(u, &P.y) // u = y^2 - fp.Mul(v, u, ¶mD) // v = dy^2 - fp.Sub(u, u, one) // u = y^2-1 - fp.Add(v, v, one) // v = dy^2+1 - isQR := fp.InvSqrt(&P.x, u, v) // x = sqrt(u/v) - if !isQR { - return false - } - fp.Modp(&P.x) // x = x mod p - if fp.IsZero(&P.x) && signX == 1 { - return false - } - if signX != (P.x[0] & 1) { - fp.Neg(&P.x, &P.x) - } - P.ta = P.x - P.tb = P.y - fp.SetOne(&P.z) - return true -} - -// double calculates 2P for curves with A=-1. -func (P *pointR1) double() { - Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb - a, b, c, e, f, g, h := Px, Py, Pz, Pta, Px, Py, Ptb - fp.Add(e, Px, Py) // x+y - fp.Sqr(a, Px) // A = x^2 - fp.Sqr(b, Py) // B = y^2 - fp.Sqr(c, Pz) // z^2 - fp.Add(c, c, c) // C = 2*z^2 - fp.Add(h, a, b) // H = A+B - fp.Sqr(e, e) // (x+y)^2 - fp.Sub(e, e, h) // E = (x+y)^2-A-B - fp.Sub(g, b, a) // G = B-A - fp.Sub(f, c, g) // F = C-G - fp.Mul(Pz, f, g) // Z = F * G - fp.Mul(Px, e, f) // X = E * F - fp.Mul(Py, g, h) // Y = G * H, T = E * H -} - -func (P *pointR1) mixAdd(Q *pointR3) { - fp.Add(&P.z, &P.z, &P.z) // D = 2*z1 - P.coreAddition(Q) -} - -func (P *pointR1) add(Q *pointR2) { - fp.Mul(&P.z, &P.z, &Q.z2) // D = 2*z1*z2 - P.coreAddition(&Q.pointR3) -} - -// coreAddition calculates P=P+Q for curves with A=-1. -func (P *pointR1) coreAddition(Q *pointR3) { - Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb - addYX2, subYX2, dt2 := &Q.addYX, &Q.subYX, &Q.dt2 - a, b, c, d, e, f, g, h := Px, Py, &fp.Elt{}, Pz, Pta, Px, Py, Ptb - fp.Mul(c, Pta, Ptb) // t1 = ta*tb - fp.Sub(h, Py, Px) // y1-x1 - fp.Add(b, Py, Px) // y1+x1 - fp.Mul(a, h, subYX2) // A = (y1-x1)*(y2-x2) - fp.Mul(b, b, addYX2) // B = (y1+x1)*(y2+x2) - fp.Mul(c, c, dt2) // C = 2*D*t1*t2 - fp.Sub(e, b, a) // E = B-A - fp.Add(h, b, a) // H = B+A - fp.Sub(f, d, c) // F = D-C - fp.Add(g, d, c) // G = D+C - fp.Mul(Pz, f, g) // Z = F * G - fp.Mul(Px, e, f) // X = E * F - fp.Mul(Py, g, h) // Y = G * H, T = E * H -} - -func (P *pointR1) oddMultiples(T []pointR2) { - var R pointR2 - n := len(T) - T[0].fromR1(P) - _2P := *P - _2P.double() - R.fromR1(&_2P) - for i := 1; i < n; i++ { - P.add(&R) - T[i].fromR1(P) - } -} - -func (P *pointR1) isEqual(Q *pointR1) bool { - l, r := &fp.Elt{}, &fp.Elt{} - fp.Mul(l, &P.x, &Q.z) - fp.Mul(r, &Q.x, &P.z) - fp.Sub(l, l, r) - b := fp.IsZero(l) - fp.Mul(l, &P.y, &Q.z) - fp.Mul(r, &Q.y, &P.z) - fp.Sub(l, l, r) - b = b && fp.IsZero(l) - fp.Mul(l, &P.ta, &P.tb) - fp.Mul(l, l, &Q.z) - fp.Mul(r, &Q.ta, &Q.tb) - fp.Mul(r, r, &P.z) - fp.Sub(l, l, r) - b = b && fp.IsZero(l) - return b && !fp.IsZero(&P.z) && !fp.IsZero(&Q.z) -} - -func (P *pointR3) neg() { - P.addYX, P.subYX = P.subYX, P.addYX - fp.Neg(&P.dt2, &P.dt2) -} - -func (P *pointR2) fromR1(Q *pointR1) { - fp.Add(&P.addYX, &Q.y, &Q.x) - fp.Sub(&P.subYX, &Q.y, &Q.x) - fp.Mul(&P.dt2, &Q.ta, &Q.tb) - fp.Mul(&P.dt2, &P.dt2, ¶mD) - fp.Add(&P.dt2, &P.dt2, &P.dt2) - fp.Add(&P.z2, &Q.z, &Q.z) -} - -func (P *pointR3) cneg(b int) { - t := &fp.Elt{} - fp.Cswap(&P.addYX, &P.subYX, uint(b)) - fp.Neg(t, &P.dt2) - fp.Cmov(&P.dt2, t, uint(b)) -} - -func (P *pointR3) cmov(Q *pointR3, b int) { - fp.Cmov(&P.addYX, &Q.addYX, uint(b)) - fp.Cmov(&P.subYX, &Q.subYX, uint(b)) - fp.Cmov(&P.dt2, &Q.dt2, uint(b)) -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go b/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go deleted file mode 100644 index c3505b67..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build go1.13 -// +build go1.13 - -package ed25519 - -import cryptoEd25519 "crypto/ed25519" - -// PublicKey is the type of Ed25519 public keys. -type PublicKey cryptoEd25519.PublicKey diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go b/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go deleted file mode 100644 index d57d86ef..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !go1.13 -// +build !go1.13 - -package ed25519 - -// PublicKey is the type of Ed25519 public keys. -type PublicKey []byte diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go b/vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go deleted file mode 100644 index e4520f52..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go +++ /dev/null @@ -1,87 +0,0 @@ -package ed25519 - -import ( - "crypto/rand" - "encoding/asn1" - - "github.com/cloudflare/circl/sign" -) - -var sch sign.Scheme = &scheme{} - -// Scheme returns a signature interface. -func Scheme() sign.Scheme { return sch } - -type scheme struct{} - -func (*scheme) Name() string { return "Ed25519" } -func (*scheme) PublicKeySize() int { return PublicKeySize } -func (*scheme) PrivateKeySize() int { return PrivateKeySize } -func (*scheme) SignatureSize() int { return SignatureSize } -func (*scheme) SeedSize() int { return SeedSize } -func (*scheme) TLSIdentifier() uint { return 0x0807 } -func (*scheme) SupportsContext() bool { return false } -func (*scheme) Oid() asn1.ObjectIdentifier { - return asn1.ObjectIdentifier{1, 3, 101, 112} -} - -func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) { - return GenerateKey(rand.Reader) -} - -func (*scheme) Sign( - sk sign.PrivateKey, - message []byte, - opts *sign.SignatureOpts, -) []byte { - priv, ok := sk.(PrivateKey) - if !ok { - panic(sign.ErrTypeMismatch) - } - if opts != nil && opts.Context != "" { - panic(sign.ErrContextNotSupported) - } - return Sign(priv, message) -} - -func (*scheme) Verify( - pk sign.PublicKey, - message, signature []byte, - opts *sign.SignatureOpts, -) bool { - pub, ok := pk.(PublicKey) - if !ok { - panic(sign.ErrTypeMismatch) - } - if opts != nil { - if opts.Context != "" { - panic(sign.ErrContextNotSupported) - } - } - return Verify(pub, message, signature) -} - -func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { - privateKey := NewKeyFromSeed(seed) - publicKey := make(PublicKey, PublicKeySize) - copy(publicKey, privateKey[SeedSize:]) - return publicKey, privateKey -} - -func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { - if len(buf) < PublicKeySize { - return nil, sign.ErrPubKeySize - } - pub := make(PublicKey, PublicKeySize) - copy(pub, buf[:PublicKeySize]) - return pub, nil -} - -func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) { - if len(buf) < PrivateKeySize { - return nil, sign.ErrPrivKeySize - } - priv := make(PrivateKey, PrivateKeySize) - copy(priv, buf[:PrivateKeySize]) - return priv, nil -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed25519/tables.go b/vendor/github.com/cloudflare/circl/sign/ed25519/tables.go deleted file mode 100644 index 8763b426..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed25519/tables.go +++ /dev/null @@ -1,213 +0,0 @@ -package ed25519 - -import fp "github.com/cloudflare/circl/math/fp25519" - -var tabSign = [fxV][fx2w1]pointR3{ - { - pointR3{ - addYX: fp.Elt{0x85, 0x3b, 0x8c, 0xf5, 0xc6, 0x93, 0xbc, 0x2f, 0x19, 0x0e, 0x8c, 0xfb, 0xc6, 0x2d, 0x93, 0xcf, 0xc2, 0x42, 0x3d, 0x64, 0x98, 0x48, 0x0b, 0x27, 0x65, 0xba, 0xd4, 0x33, 0x3a, 0x9d, 0xcf, 0x07}, - subYX: fp.Elt{0x3e, 0x91, 0x40, 0xd7, 0x05, 0x39, 0x10, 0x9d, 0xb3, 0xbe, 0x40, 0xd1, 0x05, 0x9f, 0x39, 0xfd, 0x09, 0x8a, 0x8f, 0x68, 0x34, 0x84, 0xc1, 0xa5, 0x67, 0x12, 0xf8, 0x98, 0x92, 0x2f, 0xfd, 0x44}, - dt2: fp.Elt{0x68, 0xaa, 0x7a, 0x87, 0x05, 0x12, 0xc9, 0xab, 0x9e, 0xc4, 0xaa, 0xcc, 0x23, 0xe8, 0xd9, 0x26, 0x8c, 0x59, 0x43, 0xdd, 0xcb, 0x7d, 0x1b, 0x5a, 0xa8, 0x65, 0x0c, 0x9f, 0x68, 0x7b, 0x11, 0x6f}, - }, - { - addYX: fp.Elt{0x7c, 0xb0, 0x9e, 0xe6, 0xc5, 0xbf, 0xfa, 0x13, 0x8e, 0x0d, 0x22, 0xde, 0xc8, 0xd1, 0xce, 0x52, 0x02, 0xd5, 0x62, 0x31, 0x71, 0x0e, 0x8e, 0x9d, 0xb0, 0xd6, 0x00, 0xa5, 0x5a, 0x0e, 0xce, 0x72}, - subYX: fp.Elt{0x1a, 0x8e, 0x5c, 0xdc, 0xa4, 0xb3, 0x6c, 0x51, 0x18, 0xa0, 0x09, 0x80, 0x9a, 0x46, 0x33, 0xd5, 0xe0, 0x3c, 0x4d, 0x3b, 0xfc, 0x49, 0xa2, 0x43, 0x29, 0xe1, 0x29, 0xa9, 0x93, 0xea, 0x7c, 0x35}, - dt2: fp.Elt{0x08, 0x46, 0x6f, 0x68, 0x7f, 0x0b, 0x7c, 0x9e, 0xad, 0xba, 0x07, 0x61, 0x74, 0x83, 0x2f, 0xfc, 0x26, 0xd6, 0x09, 0xb9, 0x00, 0x34, 0x36, 0x4f, 0x01, 0xf3, 0x48, 0xdb, 0x43, 0xba, 0x04, 0x44}, - }, - { - addYX: fp.Elt{0x4c, 0xda, 0x0d, 0x13, 0x66, 0xfd, 0x82, 0x84, 0x9f, 0x75, 0x5b, 0xa2, 0x17, 0xfe, 0x34, 0xbf, 0x1f, 0xcb, 0xba, 0x90, 0x55, 0x80, 0x83, 0xfd, 0x63, 0xb9, 0x18, 0xf8, 0x5b, 0x5d, 0x94, 0x1e}, - subYX: fp.Elt{0xb9, 0xdb, 0x6c, 0x04, 0x88, 0x22, 0xd8, 0x79, 0x83, 0x2f, 0x8d, 0x65, 0x6b, 0xd2, 0xab, 0x1b, 0xdd, 0x65, 0xe5, 0x93, 0x63, 0xf8, 0xa2, 0xd8, 0x3c, 0xf1, 0x4b, 0xc5, 0x99, 0xd1, 0xf2, 0x12}, - dt2: fp.Elt{0x05, 0x4c, 0xb8, 0x3b, 0xfe, 0xf5, 0x9f, 0x2e, 0xd1, 0xb2, 0xb8, 0xff, 0xfe, 0x6d, 0xd9, 0x37, 0xe0, 0xae, 0xb4, 0x5a, 0x51, 0x80, 0x7e, 0x9b, 0x1d, 0xd1, 0x8d, 0x8c, 0x56, 0xb1, 0x84, 0x35}, - }, - { - addYX: fp.Elt{0x39, 0x71, 0x43, 0x34, 0xe3, 0x42, 0x45, 0xa1, 0xf2, 0x68, 0x71, 0xa7, 0xe8, 0x23, 0xfd, 0x9f, 0x86, 0x48, 0xff, 0xe5, 0x96, 0x74, 0xcf, 0x05, 0x49, 0xe2, 0xb3, 0x6c, 0x17, 0x77, 0x2f, 0x6d}, - subYX: fp.Elt{0x73, 0x3f, 0xc1, 0xc7, 0x6a, 0x66, 0xa1, 0x20, 0xdd, 0x11, 0xfb, 0x7a, 0x6e, 0xa8, 0x51, 0xb8, 0x3f, 0x9d, 0xa2, 0x97, 0x84, 0xb5, 0xc7, 0x90, 0x7c, 0xab, 0x48, 0xd6, 0x84, 0xa3, 0xd5, 0x1a}, - dt2: fp.Elt{0x63, 0x27, 0x3c, 0x49, 0x4b, 0xfc, 0x22, 0xf2, 0x0b, 0x50, 0xc2, 0x0f, 0xb4, 0x1f, 0x31, 0x0c, 0x2f, 0x53, 0xab, 0xaa, 0x75, 0x6f, 0xe0, 0x69, 0x39, 0x56, 0xe0, 0x3b, 0xb7, 0xa8, 0xbf, 0x45}, - }, - }, - { - { - addYX: fp.Elt{0x00, 0x45, 0xd9, 0x0d, 0x58, 0x03, 0xfc, 0x29, 0x93, 0xec, 0xbb, 0x6f, 0xa4, 0x7a, 0xd2, 0xec, 0xf8, 0xa7, 0xe2, 0xc2, 0x5f, 0x15, 0x0a, 0x13, 0xd5, 0xa1, 0x06, 0xb7, 0x1a, 0x15, 0x6b, 0x41}, - subYX: fp.Elt{0x85, 0x8c, 0xb2, 0x17, 0xd6, 0x3b, 0x0a, 0xd3, 0xea, 0x3b, 0x77, 0x39, 0xb7, 0x77, 0xd3, 0xc5, 0xbf, 0x5c, 0x6a, 0x1e, 0x8c, 0xe7, 0xc6, 0xc6, 0xc4, 0xb7, 0x2a, 0x8b, 0xf7, 0xb8, 0x61, 0x0d}, - dt2: fp.Elt{0xb0, 0x36, 0xc1, 0xe9, 0xef, 0xd7, 0xa8, 0x56, 0x20, 0x4b, 0xe4, 0x58, 0xcd, 0xe5, 0x07, 0xbd, 0xab, 0xe0, 0x57, 0x1b, 0xda, 0x2f, 0xe6, 0xaf, 0xd2, 0xe8, 0x77, 0x42, 0xf7, 0x2a, 0x1a, 0x19}, - }, - { - addYX: fp.Elt{0x6a, 0x6d, 0x6d, 0xd1, 0xfa, 0xf5, 0x03, 0x30, 0xbd, 0x6d, 0xc2, 0xc8, 0xf5, 0x38, 0x80, 0x4f, 0xb2, 0xbe, 0xa1, 0x76, 0x50, 0x1a, 0x73, 0xf2, 0x78, 0x2b, 0x8e, 0x3a, 0x1e, 0x34, 0x47, 0x7b}, - subYX: fp.Elt{0xc3, 0x2c, 0x36, 0xdc, 0xc5, 0x45, 0xbc, 0xef, 0x1b, 0x64, 0xd6, 0x65, 0x28, 0xe9, 0xda, 0x84, 0x13, 0xbe, 0x27, 0x8e, 0x3f, 0x98, 0x2a, 0x37, 0xee, 0x78, 0x97, 0xd6, 0xc0, 0x6f, 0xb4, 0x53}, - dt2: fp.Elt{0x58, 0x5d, 0xa7, 0xa3, 0x68, 0xbb, 0x20, 0x30, 0x2e, 0x03, 0xe9, 0xb1, 0xd4, 0x90, 0x72, 0xe3, 0x71, 0xb2, 0x36, 0x3e, 0x73, 0xa0, 0x2e, 0x3d, 0xd1, 0x85, 0x33, 0x62, 0x4e, 0xa7, 0x7b, 0x31}, - }, - { - addYX: fp.Elt{0xbf, 0xc4, 0x38, 0x53, 0xfb, 0x68, 0xa9, 0x77, 0xce, 0x55, 0xf9, 0x05, 0xcb, 0xeb, 0xfb, 0x8c, 0x46, 0xc2, 0x32, 0x7c, 0xf0, 0xdb, 0xd7, 0x2c, 0x62, 0x8e, 0xdd, 0x54, 0x75, 0xcf, 0x3f, 0x33}, - subYX: fp.Elt{0x49, 0x50, 0x1f, 0x4e, 0x6e, 0x55, 0x55, 0xde, 0x8c, 0x4e, 0x77, 0x96, 0x38, 0x3b, 0xfe, 0xb6, 0x43, 0x3c, 0x86, 0x69, 0xc2, 0x72, 0x66, 0x1f, 0x6b, 0xf9, 0x87, 0xbc, 0x4f, 0x37, 0x3e, 0x3c}, - dt2: fp.Elt{0xd2, 0x2f, 0x06, 0x6b, 0x08, 0x07, 0x69, 0x77, 0xc0, 0x94, 0xcc, 0xae, 0x43, 0x00, 0x59, 0x6e, 0xa3, 0x63, 0xa8, 0xdd, 0xfa, 0x24, 0x18, 0xd0, 0x35, 0xc7, 0x78, 0xf7, 0x0d, 0xd4, 0x5a, 0x1e}, - }, - { - addYX: fp.Elt{0x45, 0xc1, 0x17, 0x51, 0xf8, 0xed, 0x7e, 0xc7, 0xa9, 0x1a, 0x11, 0x6e, 0x2d, 0xef, 0x0b, 0xd5, 0x3f, 0x98, 0xb0, 0xa3, 0x9d, 0x65, 0xf1, 0xcd, 0x53, 0x4a, 0x8a, 0x18, 0x70, 0x0a, 0x7f, 0x23}, - subYX: fp.Elt{0xdd, 0xef, 0xbe, 0x3a, 0x31, 0xe0, 0xbc, 0xbe, 0x6d, 0x5d, 0x79, 0x87, 0xd6, 0xbe, 0x68, 0xe3, 0x59, 0x76, 0x8c, 0x86, 0x0e, 0x7a, 0x92, 0x13, 0x14, 0x8f, 0x67, 0xb3, 0xcb, 0x1a, 0x76, 0x76}, - dt2: fp.Elt{0x56, 0x7a, 0x1c, 0x9d, 0xca, 0x96, 0xf9, 0xf9, 0x03, 0x21, 0xd4, 0xe8, 0xb3, 0xd5, 0xe9, 0x52, 0xc8, 0x54, 0x1e, 0x1b, 0x13, 0xb6, 0xfd, 0x47, 0x7d, 0x02, 0x32, 0x33, 0x27, 0xe2, 0x1f, 0x19}, - }, - }, -} - -var tabVerif = [1 << (omegaFix - 2)]pointR3{ - { /* 1P */ - addYX: fp.Elt{0x85, 0x3b, 0x8c, 0xf5, 0xc6, 0x93, 0xbc, 0x2f, 0x19, 0x0e, 0x8c, 0xfb, 0xc6, 0x2d, 0x93, 0xcf, 0xc2, 0x42, 0x3d, 0x64, 0x98, 0x48, 0x0b, 0x27, 0x65, 0xba, 0xd4, 0x33, 0x3a, 0x9d, 0xcf, 0x07}, - subYX: fp.Elt{0x3e, 0x91, 0x40, 0xd7, 0x05, 0x39, 0x10, 0x9d, 0xb3, 0xbe, 0x40, 0xd1, 0x05, 0x9f, 0x39, 0xfd, 0x09, 0x8a, 0x8f, 0x68, 0x34, 0x84, 0xc1, 0xa5, 0x67, 0x12, 0xf8, 0x98, 0x92, 0x2f, 0xfd, 0x44}, - dt2: fp.Elt{0x68, 0xaa, 0x7a, 0x87, 0x05, 0x12, 0xc9, 0xab, 0x9e, 0xc4, 0xaa, 0xcc, 0x23, 0xe8, 0xd9, 0x26, 0x8c, 0x59, 0x43, 0xdd, 0xcb, 0x7d, 0x1b, 0x5a, 0xa8, 0x65, 0x0c, 0x9f, 0x68, 0x7b, 0x11, 0x6f}, - }, - { /* 3P */ - addYX: fp.Elt{0x30, 0x97, 0xee, 0x4c, 0xa8, 0xb0, 0x25, 0xaf, 0x8a, 0x4b, 0x86, 0xe8, 0x30, 0x84, 0x5a, 0x02, 0x32, 0x67, 0x01, 0x9f, 0x02, 0x50, 0x1b, 0xc1, 0xf4, 0xf8, 0x80, 0x9a, 0x1b, 0x4e, 0x16, 0x7a}, - subYX: fp.Elt{0x65, 0xd2, 0xfc, 0xa4, 0xe8, 0x1f, 0x61, 0x56, 0x7d, 0xba, 0xc1, 0xe5, 0xfd, 0x53, 0xd3, 0x3b, 0xbd, 0xd6, 0x4b, 0x21, 0x1a, 0xf3, 0x31, 0x81, 0x62, 0xda, 0x5b, 0x55, 0x87, 0x15, 0xb9, 0x2a}, - dt2: fp.Elt{0x89, 0xd8, 0xd0, 0x0d, 0x3f, 0x93, 0xae, 0x14, 0x62, 0xda, 0x35, 0x1c, 0x22, 0x23, 0x94, 0x58, 0x4c, 0xdb, 0xf2, 0x8c, 0x45, 0xe5, 0x70, 0xd1, 0xc6, 0xb4, 0xb9, 0x12, 0xaf, 0x26, 0x28, 0x5a}, - }, - { /* 5P */ - addYX: fp.Elt{0x33, 0xbb, 0xa5, 0x08, 0x44, 0xbc, 0x12, 0xa2, 0x02, 0xed, 0x5e, 0xc7, 0xc3, 0x48, 0x50, 0x8d, 0x44, 0xec, 0xbf, 0x5a, 0x0c, 0xeb, 0x1b, 0xdd, 0xeb, 0x06, 0xe2, 0x46, 0xf1, 0xcc, 0x45, 0x29}, - subYX: fp.Elt{0xba, 0xd6, 0x47, 0xa4, 0xc3, 0x82, 0x91, 0x7f, 0xb7, 0x29, 0x27, 0x4b, 0xd1, 0x14, 0x00, 0xd5, 0x87, 0xa0, 0x64, 0xb8, 0x1c, 0xf1, 0x3c, 0xe3, 0xf3, 0x55, 0x1b, 0xeb, 0x73, 0x7e, 0x4a, 0x15}, - dt2: fp.Elt{0x85, 0x82, 0x2a, 0x81, 0xf1, 0xdb, 0xbb, 0xbc, 0xfc, 0xd1, 0xbd, 0xd0, 0x07, 0x08, 0x0e, 0x27, 0x2d, 0xa7, 0xbd, 0x1b, 0x0b, 0x67, 0x1b, 0xb4, 0x9a, 0xb6, 0x3b, 0x6b, 0x69, 0xbe, 0xaa, 0x43}, - }, - { /* 7P */ - addYX: fp.Elt{0xbf, 0xa3, 0x4e, 0x94, 0xd0, 0x5c, 0x1a, 0x6b, 0xd2, 0xc0, 0x9d, 0xb3, 0x3a, 0x35, 0x70, 0x74, 0x49, 0x2e, 0x54, 0x28, 0x82, 0x52, 0xb2, 0x71, 0x7e, 0x92, 0x3c, 0x28, 0x69, 0xea, 0x1b, 0x46}, - subYX: fp.Elt{0xb1, 0x21, 0x32, 0xaa, 0x9a, 0x2c, 0x6f, 0xba, 0xa7, 0x23, 0xba, 0x3b, 0x53, 0x21, 0xa0, 0x6c, 0x3a, 0x2c, 0x19, 0x92, 0x4f, 0x76, 0xea, 0x9d, 0xe0, 0x17, 0x53, 0x2e, 0x5d, 0xdd, 0x6e, 0x1d}, - dt2: fp.Elt{0xa2, 0xb3, 0xb8, 0x01, 0xc8, 0x6d, 0x83, 0xf1, 0x9a, 0xa4, 0x3e, 0x05, 0x47, 0x5f, 0x03, 0xb3, 0xf3, 0xad, 0x77, 0x58, 0xba, 0x41, 0x9c, 0x52, 0xa7, 0x90, 0x0f, 0x6a, 0x1c, 0xbb, 0x9f, 0x7a}, - }, - { /* 9P */ - addYX: fp.Elt{0x2f, 0x63, 0xa8, 0xa6, 0x8a, 0x67, 0x2e, 0x9b, 0xc5, 0x46, 0xbc, 0x51, 0x6f, 0x9e, 0x50, 0xa6, 0xb5, 0xf5, 0x86, 0xc6, 0xc9, 0x33, 0xb2, 0xce, 0x59, 0x7f, 0xdd, 0x8a, 0x33, 0xed, 0xb9, 0x34}, - subYX: fp.Elt{0x64, 0x80, 0x9d, 0x03, 0x7e, 0x21, 0x6e, 0xf3, 0x9b, 0x41, 0x20, 0xf5, 0xb6, 0x81, 0xa0, 0x98, 0x44, 0xb0, 0x5e, 0xe7, 0x08, 0xc6, 0xcb, 0x96, 0x8f, 0x9c, 0xdc, 0xfa, 0x51, 0x5a, 0xc0, 0x49}, - dt2: fp.Elt{0x1b, 0xaf, 0x45, 0x90, 0xbf, 0xe8, 0xb4, 0x06, 0x2f, 0xd2, 0x19, 0xa7, 0xe8, 0x83, 0xff, 0xe2, 0x16, 0xcf, 0xd4, 0x93, 0x29, 0xfc, 0xf6, 0xaa, 0x06, 0x8b, 0x00, 0x1b, 0x02, 0x72, 0xc1, 0x73}, - }, - { /* 11P */ - addYX: fp.Elt{0xde, 0x2a, 0x80, 0x8a, 0x84, 0x00, 0xbf, 0x2f, 0x27, 0x2e, 0x30, 0x02, 0xcf, 0xfe, 0xd9, 0xe5, 0x06, 0x34, 0x70, 0x17, 0x71, 0x84, 0x3e, 0x11, 0xaf, 0x8f, 0x6d, 0x54, 0xe2, 0xaa, 0x75, 0x42}, - subYX: fp.Elt{0x48, 0x43, 0x86, 0x49, 0x02, 0x5b, 0x5f, 0x31, 0x81, 0x83, 0x08, 0x77, 0x69, 0xb3, 0xd6, 0x3e, 0x95, 0xeb, 0x8d, 0x6a, 0x55, 0x75, 0xa0, 0xa3, 0x7f, 0xc7, 0xd5, 0x29, 0x80, 0x59, 0xab, 0x18}, - dt2: fp.Elt{0xe9, 0x89, 0x60, 0xfd, 0xc5, 0x2c, 0x2b, 0xd8, 0xa4, 0xe4, 0x82, 0x32, 0xa1, 0xb4, 0x1e, 0x03, 0x22, 0x86, 0x1a, 0xb5, 0x99, 0x11, 0x31, 0x44, 0x48, 0xf9, 0x3d, 0xb5, 0x22, 0x55, 0xc6, 0x3d}, - }, - { /* 13P */ - addYX: fp.Elt{0x6d, 0x7f, 0x00, 0xa2, 0x22, 0xc2, 0x70, 0xbf, 0xdb, 0xde, 0xbc, 0xb5, 0x9a, 0xb3, 0x84, 0xbf, 0x07, 0xba, 0x07, 0xfb, 0x12, 0x0e, 0x7a, 0x53, 0x41, 0xf2, 0x46, 0xc3, 0xee, 0xd7, 0x4f, 0x23}, - subYX: fp.Elt{0x93, 0xbf, 0x7f, 0x32, 0x3b, 0x01, 0x6f, 0x50, 0x6b, 0x6f, 0x77, 0x9b, 0xc9, 0xeb, 0xfc, 0xae, 0x68, 0x59, 0xad, 0xaa, 0x32, 0xb2, 0x12, 0x9d, 0xa7, 0x24, 0x60, 0x17, 0x2d, 0x88, 0x67, 0x02}, - dt2: fp.Elt{0x78, 0xa3, 0x2e, 0x73, 0x19, 0xa1, 0x60, 0x53, 0x71, 0xd4, 0x8d, 0xdf, 0xb1, 0xe6, 0x37, 0x24, 0x33, 0xe5, 0xa7, 0x91, 0xf8, 0x37, 0xef, 0xa2, 0x63, 0x78, 0x09, 0xaa, 0xfd, 0xa6, 0x7b, 0x49}, - }, - { /* 15P */ - addYX: fp.Elt{0xa0, 0xea, 0xcf, 0x13, 0x03, 0xcc, 0xce, 0x24, 0x6d, 0x24, 0x9c, 0x18, 0x8d, 0xc2, 0x48, 0x86, 0xd0, 0xd4, 0xf2, 0xc1, 0xfa, 0xbd, 0xbd, 0x2d, 0x2b, 0xe7, 0x2d, 0xf1, 0x17, 0x29, 0xe2, 0x61}, - subYX: fp.Elt{0x0b, 0xcf, 0x8c, 0x46, 0x86, 0xcd, 0x0b, 0x04, 0xd6, 0x10, 0x99, 0x2a, 0xa4, 0x9b, 0x82, 0xd3, 0x92, 0x51, 0xb2, 0x07, 0x08, 0x30, 0x08, 0x75, 0xbf, 0x5e, 0xd0, 0x18, 0x42, 0xcd, 0xb5, 0x43}, - dt2: fp.Elt{0x16, 0xb5, 0xd0, 0x9b, 0x2f, 0x76, 0x9a, 0x5d, 0xee, 0xde, 0x3f, 0x37, 0x4e, 0xaf, 0x38, 0xeb, 0x70, 0x42, 0xd6, 0x93, 0x7d, 0x5a, 0x2e, 0x03, 0x42, 0xd8, 0xe4, 0x0a, 0x21, 0x61, 0x1d, 0x51}, - }, - { /* 17P */ - addYX: fp.Elt{0x81, 0x9d, 0x0e, 0x95, 0xef, 0x76, 0xc6, 0x92, 0x4f, 0x04, 0xd7, 0xc0, 0xcd, 0x20, 0x46, 0xa5, 0x48, 0x12, 0x8f, 0x6f, 0x64, 0x36, 0x9b, 0xaa, 0xe3, 0x55, 0xb8, 0xdd, 0x24, 0x59, 0x32, 0x6d}, - subYX: fp.Elt{0x87, 0xde, 0x20, 0x44, 0x48, 0x86, 0x13, 0x08, 0xb4, 0xed, 0x92, 0xb5, 0x16, 0xf0, 0x1c, 0x8a, 0x25, 0x2d, 0x94, 0x29, 0x27, 0x4e, 0xfa, 0x39, 0x10, 0x28, 0x48, 0xe2, 0x6f, 0xfe, 0xa7, 0x71}, - dt2: fp.Elt{0x54, 0xc8, 0xc8, 0xa5, 0xb8, 0x82, 0x71, 0x6c, 0x03, 0x2a, 0x5f, 0xfe, 0x79, 0x14, 0xfd, 0x33, 0x0c, 0x8d, 0x77, 0x83, 0x18, 0x59, 0xcf, 0x72, 0xa9, 0xea, 0x9e, 0x55, 0xb6, 0xc4, 0x46, 0x47}, - }, - { /* 19P */ - addYX: fp.Elt{0x2b, 0x9a, 0xc6, 0x6d, 0x3c, 0x7b, 0x77, 0xd3, 0x17, 0xf6, 0x89, 0x6f, 0x27, 0xb2, 0xfa, 0xde, 0xb5, 0x16, 0x3a, 0xb5, 0xf7, 0x1c, 0x65, 0x45, 0xb7, 0x9f, 0xfe, 0x34, 0xde, 0x51, 0x9a, 0x5c}, - subYX: fp.Elt{0x47, 0x11, 0x74, 0x64, 0xc8, 0x46, 0x85, 0x34, 0x49, 0xc8, 0xfc, 0x0e, 0xdd, 0xae, 0x35, 0x7d, 0x32, 0xa3, 0x72, 0x06, 0x76, 0x9a, 0x93, 0xff, 0xd6, 0xe6, 0xb5, 0x7d, 0x49, 0x63, 0x96, 0x21}, - dt2: fp.Elt{0x67, 0x0e, 0xf1, 0x79, 0xcf, 0xf1, 0x10, 0xf5, 0x5b, 0x51, 0x58, 0xe6, 0xa1, 0xda, 0xdd, 0xff, 0x77, 0x22, 0x14, 0x10, 0x17, 0xa7, 0xc3, 0x09, 0xbb, 0x23, 0x82, 0x60, 0x3c, 0x50, 0x04, 0x48}, - }, - { /* 21P */ - addYX: fp.Elt{0xc7, 0x7f, 0xa3, 0x2c, 0xd0, 0x9e, 0x24, 0xc4, 0xab, 0xac, 0x15, 0xa6, 0xe3, 0xa0, 0x59, 0xa0, 0x23, 0x0e, 0x6e, 0xc9, 0xd7, 0x6e, 0xa9, 0x88, 0x6d, 0x69, 0x50, 0x16, 0xa5, 0x98, 0x33, 0x55}, - subYX: fp.Elt{0x75, 0xd1, 0x36, 0x3a, 0xd2, 0x21, 0x68, 0x3b, 0x32, 0x9e, 0x9b, 0xe9, 0xa7, 0x0a, 0xb4, 0xbb, 0x47, 0x8a, 0x83, 0x20, 0xe4, 0x5c, 0x9e, 0x5d, 0x5e, 0x4c, 0xde, 0x58, 0x88, 0x09, 0x1e, 0x77}, - dt2: fp.Elt{0xdf, 0x1e, 0x45, 0x78, 0xd2, 0xf5, 0x12, 0x9a, 0xcb, 0x9c, 0x89, 0x85, 0x79, 0x5d, 0xda, 0x3a, 0x08, 0x95, 0xa5, 0x9f, 0x2d, 0x4a, 0x7f, 0x47, 0x11, 0xa6, 0xf5, 0x8f, 0xd6, 0xd1, 0x5e, 0x5a}, - }, - { /* 23P */ - addYX: fp.Elt{0x83, 0x0e, 0x15, 0xfe, 0x2a, 0x12, 0x95, 0x11, 0xd8, 0x35, 0x4b, 0x7e, 0x25, 0x9a, 0x20, 0xcf, 0x20, 0x1e, 0x71, 0x1e, 0x29, 0xf8, 0x87, 0x73, 0xf0, 0x92, 0xbf, 0xd8, 0x97, 0xb8, 0xac, 0x44}, - subYX: fp.Elt{0x59, 0x73, 0x52, 0x58, 0xc5, 0xe0, 0xe5, 0xba, 0x7e, 0x9d, 0xdb, 0xca, 0x19, 0x5c, 0x2e, 0x39, 0xe9, 0xab, 0x1c, 0xda, 0x1e, 0x3c, 0x65, 0x28, 0x44, 0xdc, 0xef, 0x5f, 0x13, 0x60, 0x9b, 0x01}, - dt2: fp.Elt{0x83, 0x4b, 0x13, 0x5e, 0x14, 0x68, 0x60, 0x1e, 0x16, 0x4c, 0x30, 0x24, 0x4f, 0xe6, 0xf5, 0xc4, 0xd7, 0x3e, 0x1a, 0xfc, 0xa8, 0x88, 0x6e, 0x50, 0x92, 0x2f, 0xad, 0xe6, 0xfd, 0x49, 0x0c, 0x15}, - }, - { /* 25P */ - addYX: fp.Elt{0x38, 0x11, 0x47, 0x09, 0x95, 0xf2, 0x7b, 0x8e, 0x51, 0xa6, 0x75, 0x4f, 0x39, 0xef, 0x6f, 0x5d, 0xad, 0x08, 0xa7, 0x25, 0xc4, 0x79, 0xaf, 0x10, 0x22, 0x99, 0xb9, 0x5b, 0x07, 0x5a, 0x2b, 0x6b}, - subYX: fp.Elt{0x68, 0xa8, 0xdc, 0x9c, 0x3c, 0x86, 0x49, 0xb8, 0xd0, 0x4a, 0x71, 0xb8, 0xdb, 0x44, 0x3f, 0xc8, 0x8d, 0x16, 0x36, 0x0c, 0x56, 0xe3, 0x3e, 0xfe, 0xc1, 0xfb, 0x05, 0x1e, 0x79, 0xd7, 0xa6, 0x78}, - dt2: fp.Elt{0x76, 0xb9, 0xa0, 0x47, 0x4b, 0x70, 0xbf, 0x58, 0xd5, 0x48, 0x17, 0x74, 0x55, 0xb3, 0x01, 0xa6, 0x90, 0xf5, 0x42, 0xd5, 0xb1, 0x1f, 0x2b, 0xaa, 0x00, 0x5d, 0xd5, 0x4a, 0xfc, 0x7f, 0x5c, 0x72}, - }, - { /* 27P */ - addYX: fp.Elt{0xb2, 0x99, 0xcf, 0xd1, 0x15, 0x67, 0x42, 0xe4, 0x34, 0x0d, 0xa2, 0x02, 0x11, 0xd5, 0x52, 0x73, 0x9f, 0x10, 0x12, 0x8b, 0x7b, 0x15, 0xd1, 0x23, 0xa3, 0xf3, 0xb1, 0x7c, 0x27, 0xc9, 0x4c, 0x79}, - subYX: fp.Elt{0xc0, 0x98, 0xd0, 0x1c, 0xf7, 0x2b, 0x80, 0x91, 0x66, 0x63, 0x5e, 0xed, 0xa4, 0x6c, 0x41, 0xfe, 0x4c, 0x99, 0x02, 0x49, 0x71, 0x5d, 0x58, 0xdf, 0xe7, 0xfa, 0x55, 0xf8, 0x25, 0x46, 0xd5, 0x4c}, - dt2: fp.Elt{0x53, 0x50, 0xac, 0xc2, 0x26, 0xc4, 0xf6, 0x4a, 0x58, 0x72, 0xf6, 0x32, 0xad, 0xed, 0x9a, 0xbc, 0x21, 0x10, 0x31, 0x0a, 0xf1, 0x32, 0xd0, 0x2a, 0x85, 0x8e, 0xcc, 0x6f, 0x7b, 0x35, 0x08, 0x70}, - }, - { /* 29P */ - addYX: fp.Elt{0x01, 0x3f, 0x77, 0x38, 0x27, 0x67, 0x88, 0x0b, 0xfb, 0xcc, 0xfb, 0x95, 0xfa, 0xc8, 0xcc, 0xb8, 0xb6, 0x29, 0xad, 0xb9, 0xa3, 0xd5, 0x2d, 0x8d, 0x6a, 0x0f, 0xad, 0x51, 0x98, 0x7e, 0xef, 0x06}, - subYX: fp.Elt{0x34, 0x4a, 0x58, 0x82, 0xbb, 0x9f, 0x1b, 0xd0, 0x2b, 0x79, 0xb4, 0xd2, 0x63, 0x64, 0xab, 0x47, 0x02, 0x62, 0x53, 0x48, 0x9c, 0x63, 0x31, 0xb6, 0x28, 0xd4, 0xd6, 0x69, 0x36, 0x2a, 0xa9, 0x13}, - dt2: fp.Elt{0xe5, 0x7d, 0x57, 0xc0, 0x1c, 0x77, 0x93, 0xca, 0x5c, 0xdc, 0x35, 0x50, 0x1e, 0xe4, 0x40, 0x75, 0x71, 0xe0, 0x02, 0xd8, 0x01, 0x0f, 0x68, 0x24, 0x6a, 0xf8, 0x2a, 0x8a, 0xdf, 0x6d, 0x29, 0x3c}, - }, - { /* 31P */ - addYX: fp.Elt{0x13, 0xa7, 0x14, 0xd9, 0xf9, 0x15, 0xad, 0xae, 0x12, 0xf9, 0x8f, 0x8c, 0xf9, 0x7b, 0x2f, 0xa9, 0x30, 0xd7, 0x53, 0x9f, 0x17, 0x23, 0xf8, 0xaf, 0xba, 0x77, 0x0c, 0x49, 0x93, 0xd3, 0x99, 0x7a}, - subYX: fp.Elt{0x41, 0x25, 0x1f, 0xbb, 0x2e, 0x4d, 0xeb, 0xfc, 0x1f, 0xb9, 0xad, 0x40, 0xc7, 0x10, 0x95, 0xb8, 0x05, 0xad, 0xa1, 0xd0, 0x7d, 0xa3, 0x71, 0xfc, 0x7b, 0x71, 0x47, 0x07, 0x70, 0x2c, 0x89, 0x0a}, - dt2: fp.Elt{0xe8, 0xa3, 0xbd, 0x36, 0x24, 0xed, 0x52, 0x8f, 0x94, 0x07, 0xe8, 0x57, 0x41, 0xc8, 0xa8, 0x77, 0xe0, 0x9c, 0x2f, 0x26, 0x63, 0x65, 0xa9, 0xa5, 0xd2, 0xf7, 0x02, 0x83, 0xd2, 0x62, 0x67, 0x28}, - }, - { /* 33P */ - addYX: fp.Elt{0x25, 0x5b, 0xe3, 0x3c, 0x09, 0x36, 0x78, 0x4e, 0x97, 0xaa, 0x6b, 0xb2, 0x1d, 0x18, 0xe1, 0x82, 0x3f, 0xb8, 0xc7, 0xcb, 0xd3, 0x92, 0xc1, 0x0c, 0x3a, 0x9d, 0x9d, 0x6a, 0x04, 0xda, 0xf1, 0x32}, - subYX: fp.Elt{0xbd, 0xf5, 0x2e, 0xce, 0x2b, 0x8e, 0x55, 0x7c, 0x63, 0xbc, 0x47, 0x67, 0xb4, 0x6c, 0x98, 0xe4, 0xb8, 0x89, 0xbb, 0x3b, 0x9f, 0x17, 0x4a, 0x15, 0x7a, 0x76, 0xf1, 0xd6, 0xa3, 0xf2, 0x86, 0x76}, - dt2: fp.Elt{0x6a, 0x7c, 0x59, 0x6d, 0xa6, 0x12, 0x8d, 0xaa, 0x2b, 0x85, 0xd3, 0x04, 0x03, 0x93, 0x11, 0x8f, 0x22, 0xb0, 0x09, 0xc2, 0x73, 0xdc, 0x91, 0x3f, 0xa6, 0x28, 0xad, 0xa9, 0xf8, 0x05, 0x13, 0x56}, - }, - { /* 35P */ - addYX: fp.Elt{0xd1, 0xae, 0x92, 0xec, 0x8d, 0x97, 0x0c, 0x10, 0xe5, 0x73, 0x6d, 0x4d, 0x43, 0xd5, 0x43, 0xca, 0x48, 0xba, 0x47, 0xd8, 0x22, 0x1b, 0x13, 0x83, 0x2c, 0x4d, 0x5d, 0xe3, 0x53, 0xec, 0xaa}, - subYX: fp.Elt{0xd5, 0xc0, 0xb0, 0xe7, 0x28, 0xcc, 0x22, 0x67, 0x53, 0x5c, 0x07, 0xdb, 0xbb, 0xe9, 0x9d, 0x70, 0x61, 0x0a, 0x01, 0xd7, 0xa7, 0x8d, 0xf6, 0xca, 0x6c, 0xcc, 0x57, 0x2c, 0xef, 0x1a, 0x0a, 0x03}, - dt2: fp.Elt{0xaa, 0xd2, 0x3a, 0x00, 0x73, 0xf7, 0xb1, 0x7b, 0x08, 0x66, 0x21, 0x2b, 0x80, 0x29, 0x3f, 0x0b, 0x3e, 0xd2, 0x0e, 0x52, 0x86, 0xdc, 0x21, 0x78, 0x80, 0x54, 0x06, 0x24, 0x1c, 0x9c, 0xbe, 0x20}, - }, - { /* 37P */ - addYX: fp.Elt{0xa6, 0x73, 0x96, 0x24, 0xd8, 0x87, 0x53, 0xe1, 0x93, 0xe4, 0x46, 0xf5, 0x2d, 0xbc, 0x43, 0x59, 0xb5, 0x63, 0x6f, 0xc3, 0x81, 0x9a, 0x7f, 0x1c, 0xde, 0xc1, 0x0a, 0x1f, 0x36, 0xb3, 0x0a, 0x75}, - subYX: fp.Elt{0x60, 0x5e, 0x02, 0xe2, 0x4a, 0xe4, 0xe0, 0x20, 0x38, 0xb9, 0xdc, 0xcb, 0x2f, 0x3b, 0x3b, 0xb0, 0x1c, 0x0d, 0x5a, 0xf9, 0x9c, 0x63, 0x5d, 0x10, 0x11, 0xe3, 0x67, 0x50, 0x54, 0x4c, 0x76, 0x69}, - dt2: fp.Elt{0x37, 0x10, 0xf8, 0xa2, 0x83, 0x32, 0x8a, 0x1e, 0xf1, 0xcb, 0x7f, 0xbd, 0x23, 0xda, 0x2e, 0x6f, 0x63, 0x25, 0x2e, 0xac, 0x5b, 0xd1, 0x2f, 0xb7, 0x40, 0x50, 0x07, 0xb7, 0x3f, 0x6b, 0xf9, 0x54}, - }, - { /* 39P */ - addYX: fp.Elt{0x79, 0x92, 0x66, 0x29, 0x04, 0xf2, 0xad, 0x0f, 0x4a, 0x72, 0x7d, 0x7d, 0x04, 0xa2, 0xdd, 0x3a, 0xf1, 0x60, 0x57, 0x8c, 0x82, 0x94, 0x3d, 0x6f, 0x9e, 0x53, 0xb7, 0x2b, 0xc5, 0xe9, 0x7f, 0x3d}, - subYX: fp.Elt{0xcd, 0x1e, 0xb1, 0x16, 0xc6, 0xaf, 0x7d, 0x17, 0x79, 0x64, 0x57, 0xfa, 0x9c, 0x4b, 0x76, 0x89, 0x85, 0xe7, 0xec, 0xe6, 0x10, 0xa1, 0xa8, 0xb7, 0xf0, 0xdb, 0x85, 0xbe, 0x9f, 0x83, 0xe6, 0x78}, - dt2: fp.Elt{0x6b, 0x85, 0xb8, 0x37, 0xf7, 0x2d, 0x33, 0x70, 0x8a, 0x17, 0x1a, 0x04, 0x43, 0x5d, 0xd0, 0x75, 0x22, 0x9e, 0xe5, 0xa0, 0x4a, 0xf7, 0x0f, 0x32, 0x42, 0x82, 0x08, 0x50, 0xf3, 0x68, 0xf2, 0x70}, - }, - { /* 41P */ - addYX: fp.Elt{0x47, 0x5f, 0x80, 0xb1, 0x83, 0x45, 0x86, 0x66, 0x19, 0x7c, 0xdd, 0x60, 0xd1, 0xc5, 0x35, 0xf5, 0x06, 0xb0, 0x4c, 0x1e, 0xb7, 0x4e, 0x87, 0xe9, 0xd9, 0x89, 0xd8, 0xfa, 0x5c, 0x34, 0x0d, 0x7c}, - subYX: fp.Elt{0x55, 0xf3, 0xdc, 0x70, 0x20, 0x11, 0x24, 0x23, 0x17, 0xe1, 0xfc, 0xe7, 0x7e, 0xc9, 0x0c, 0x38, 0x98, 0xb6, 0x52, 0x35, 0xed, 0xde, 0x1d, 0xb3, 0xb9, 0xc4, 0xb8, 0x39, 0xc0, 0x56, 0x4e, 0x40}, - dt2: fp.Elt{0x8a, 0x33, 0x78, 0x8c, 0x4b, 0x1f, 0x1f, 0x59, 0xe1, 0xb5, 0xe0, 0x67, 0xb1, 0x6a, 0x36, 0xa0, 0x44, 0x3d, 0x5f, 0xb4, 0x52, 0x41, 0xbc, 0x5c, 0x77, 0xc7, 0xae, 0x2a, 0x76, 0x54, 0xd7, 0x20}, - }, - { /* 43P */ - addYX: fp.Elt{0x58, 0xb7, 0x3b, 0xc7, 0x6f, 0xc3, 0x8f, 0x5e, 0x9a, 0xbb, 0x3c, 0x36, 0xa5, 0x43, 0xe5, 0xac, 0x22, 0xc9, 0x3b, 0x90, 0x7d, 0x4a, 0x93, 0xa9, 0x62, 0xec, 0xce, 0xf3, 0x46, 0x1e, 0x8f, 0x2b}, - subYX: fp.Elt{0x43, 0xf5, 0xb9, 0x35, 0xb1, 0xfe, 0x74, 0x9d, 0x6c, 0x95, 0x8c, 0xde, 0xf1, 0x7d, 0xb3, 0x84, 0xa9, 0x8b, 0x13, 0x57, 0x07, 0x2b, 0x32, 0xe9, 0xe1, 0x4c, 0x0b, 0x79, 0xa8, 0xad, 0xb8, 0x38}, - dt2: fp.Elt{0x5d, 0xf9, 0x51, 0xdf, 0x9c, 0x4a, 0xc0, 0xb5, 0xac, 0xde, 0x1f, 0xcb, 0xae, 0x52, 0x39, 0x2b, 0xda, 0x66, 0x8b, 0x32, 0x8b, 0x6d, 0x10, 0x1d, 0x53, 0x19, 0xba, 0xce, 0x32, 0xeb, 0x9a, 0x04}, - }, - { /* 45P */ - addYX: fp.Elt{0x31, 0x79, 0xfc, 0x75, 0x0b, 0x7d, 0x50, 0xaa, 0xd3, 0x25, 0x67, 0x7a, 0x4b, 0x92, 0xef, 0x0f, 0x30, 0x39, 0x6b, 0x39, 0x2b, 0x54, 0x82, 0x1d, 0xfc, 0x74, 0xf6, 0x30, 0x75, 0xe1, 0x5e, 0x79}, - subYX: fp.Elt{0x7e, 0xfe, 0xdc, 0x63, 0x3c, 0x7d, 0x76, 0xd7, 0x40, 0x6e, 0x85, 0x97, 0x48, 0x59, 0x9c, 0x20, 0x13, 0x7c, 0x4f, 0xe1, 0x61, 0x68, 0x67, 0xb6, 0xfc, 0x25, 0xd6, 0xc8, 0xe0, 0x65, 0xc6, 0x51}, - dt2: fp.Elt{0x81, 0xbd, 0xec, 0x52, 0x0a, 0x5b, 0x4a, 0x25, 0xe7, 0xaf, 0x34, 0xe0, 0x6e, 0x1f, 0x41, 0x5d, 0x31, 0x4a, 0xee, 0xca, 0x0d, 0x4d, 0xa2, 0xe6, 0x77, 0x44, 0xc5, 0x9d, 0xf4, 0x9b, 0xd1, 0x6c}, - }, - { /* 47P */ - addYX: fp.Elt{0x86, 0xc3, 0xaf, 0x65, 0x21, 0x61, 0xfe, 0x1f, 0x10, 0x1b, 0xd5, 0xb8, 0x88, 0x2a, 0x2a, 0x08, 0xaa, 0x0b, 0x99, 0x20, 0x7e, 0x62, 0xf6, 0x76, 0xe7, 0x43, 0x9e, 0x42, 0xa7, 0xb3, 0x01, 0x5e}, - subYX: fp.Elt{0xa3, 0x9c, 0x17, 0x52, 0x90, 0x61, 0x87, 0x7e, 0x85, 0x9f, 0x2c, 0x0b, 0x06, 0x0a, 0x1d, 0x57, 0x1e, 0x71, 0x99, 0x84, 0xa8, 0xba, 0xa2, 0x80, 0x38, 0xe6, 0xb2, 0x40, 0xdb, 0xf3, 0x20, 0x75}, - dt2: fp.Elt{0xa1, 0x57, 0x93, 0xd3, 0xe3, 0x0b, 0xb5, 0x3d, 0xa5, 0x94, 0x9e, 0x59, 0xdd, 0x6c, 0x7b, 0x96, 0x6e, 0x1e, 0x31, 0xdf, 0x64, 0x9a, 0x30, 0x1a, 0x86, 0xc9, 0xf3, 0xce, 0x9c, 0x2c, 0x09, 0x71}, - }, - { /* 49P */ - addYX: fp.Elt{0xcf, 0x1d, 0x05, 0x74, 0xac, 0xd8, 0x6b, 0x85, 0x1e, 0xaa, 0xb7, 0x55, 0x08, 0xa4, 0xf6, 0x03, 0xeb, 0x3c, 0x74, 0xc9, 0xcb, 0xe7, 0x4a, 0x3a, 0xde, 0xab, 0x37, 0x71, 0xbb, 0xa5, 0x73, 0x41}, - subYX: fp.Elt{0x8c, 0x91, 0x64, 0x03, 0x3f, 0x52, 0xd8, 0x53, 0x1c, 0x6b, 0xab, 0x3f, 0xf4, 0x04, 0xb4, 0xa2, 0xa4, 0xe5, 0x81, 0x66, 0x9e, 0x4a, 0x0b, 0x08, 0xa7, 0x7b, 0x25, 0xd0, 0x03, 0x5b, 0xa1, 0x0e}, - dt2: fp.Elt{0x8a, 0x21, 0xf9, 0xf0, 0x31, 0x6e, 0xc5, 0x17, 0x08, 0x47, 0xfc, 0x1a, 0x2b, 0x6e, 0x69, 0x5a, 0x76, 0xf1, 0xb2, 0xf4, 0x68, 0x16, 0x93, 0xf7, 0x67, 0x3a, 0x4e, 0x4a, 0x61, 0x65, 0xc5, 0x5f}, - }, - { /* 51P */ - addYX: fp.Elt{0x8e, 0x98, 0x90, 0x77, 0xe6, 0xe1, 0x92, 0x48, 0x22, 0xd7, 0x5c, 0x1c, 0x0f, 0x95, 0xd5, 0x01, 0xed, 0x3e, 0x92, 0xe5, 0x9a, 0x81, 0xb0, 0xe3, 0x1b, 0x65, 0x46, 0x9d, 0x40, 0xc7, 0x14, 0x32}, - subYX: fp.Elt{0xe5, 0x7a, 0x6d, 0xc4, 0x0d, 0x57, 0x6e, 0x13, 0x8f, 0xdc, 0xf8, 0x54, 0xcc, 0xaa, 0xd0, 0x0f, 0x86, 0xad, 0x0d, 0x31, 0x03, 0x9f, 0x54, 0x59, 0xa1, 0x4a, 0x45, 0x4c, 0x41, 0x1c, 0x71, 0x62}, - dt2: fp.Elt{0x70, 0x17, 0x65, 0x06, 0x74, 0x82, 0x29, 0x13, 0x36, 0x94, 0x27, 0x8a, 0x66, 0xa0, 0xa4, 0x3b, 0x3c, 0x22, 0x5d, 0x18, 0xec, 0xb8, 0xb6, 0xd9, 0x3c, 0x83, 0xcb, 0x3e, 0x07, 0x94, 0xea, 0x5b}, - }, - { /* 53P */ - addYX: fp.Elt{0xf8, 0xd2, 0x43, 0xf3, 0x63, 0xce, 0x70, 0xb4, 0xf1, 0xe8, 0x43, 0x05, 0x8f, 0xba, 0x67, 0x00, 0x6f, 0x7b, 0x11, 0xa2, 0xa1, 0x51, 0xda, 0x35, 0x2f, 0xbd, 0xf1, 0x44, 0x59, 0x78, 0xd0, 0x4a}, - subYX: fp.Elt{0xe4, 0x9b, 0xc8, 0x12, 0x09, 0xbf, 0x1d, 0x64, 0x9c, 0x57, 0x6e, 0x7d, 0x31, 0x8b, 0xf3, 0xac, 0x65, 0xb0, 0x97, 0xf6, 0x02, 0x9e, 0xfe, 0xab, 0xec, 0x1e, 0xf6, 0x48, 0xc1, 0xd5, 0xac, 0x3a}, - dt2: fp.Elt{0x01, 0x83, 0x31, 0xc3, 0x34, 0x3b, 0x8e, 0x85, 0x26, 0x68, 0x31, 0x07, 0x47, 0xc0, 0x99, 0xdc, 0x8c, 0xa8, 0x9d, 0xd3, 0x2e, 0x5b, 0x08, 0x34, 0x3d, 0x85, 0x02, 0xd9, 0xb1, 0x0c, 0xff, 0x3a}, - }, - { /* 55P */ - addYX: fp.Elt{0x05, 0x35, 0xc5, 0xf4, 0x0b, 0x43, 0x26, 0x92, 0x83, 0x22, 0x1f, 0x26, 0x13, 0x9c, 0xe4, 0x68, 0xc6, 0x27, 0xd3, 0x8f, 0x78, 0x33, 0xef, 0x09, 0x7f, 0x9e, 0xd9, 0x2b, 0x73, 0x9f, 0xcf, 0x2c}, - subYX: fp.Elt{0x5e, 0x40, 0x20, 0x3a, 0xeb, 0xc7, 0xc5, 0x87, 0xc9, 0x56, 0xad, 0xed, 0xef, 0x11, 0xe3, 0x8e, 0xf9, 0xd5, 0x29, 0xad, 0x48, 0x2e, 0x25, 0x29, 0x1d, 0x25, 0xcd, 0xf4, 0x86, 0x7e, 0x0e, 0x11}, - dt2: fp.Elt{0xe4, 0xf5, 0x03, 0xd6, 0x9e, 0xd8, 0xc0, 0x57, 0x0c, 0x20, 0xb0, 0xf0, 0x28, 0x86, 0x88, 0x12, 0xb7, 0x3b, 0x2e, 0xa0, 0x09, 0x27, 0x17, 0x53, 0x37, 0x3a, 0x69, 0xb9, 0xe0, 0x57, 0xc5, 0x05}, - }, - { /* 57P */ - addYX: fp.Elt{0xb0, 0x0e, 0xc2, 0x89, 0xb0, 0xbb, 0x76, 0xf7, 0x5c, 0xd8, 0x0f, 0xfa, 0xf6, 0x5b, 0xf8, 0x61, 0xfb, 0x21, 0x44, 0x63, 0x4e, 0x3f, 0xb9, 0xb6, 0x05, 0x12, 0x86, 0x41, 0x08, 0xef, 0x9f, 0x28}, - subYX: fp.Elt{0x6f, 0x7e, 0xc9, 0x1f, 0x31, 0xce, 0xf9, 0xd8, 0xae, 0xfd, 0xf9, 0x11, 0x30, 0x26, 0x3f, 0x7a, 0xdd, 0x25, 0xed, 0x8b, 0xa0, 0x7e, 0x5b, 0xe1, 0x5a, 0x87, 0xe9, 0x8f, 0x17, 0x4c, 0x15, 0x6e}, - dt2: fp.Elt{0xbf, 0x9a, 0xd6, 0xfe, 0x36, 0x63, 0x61, 0xcf, 0x4f, 0xc9, 0x35, 0x83, 0xe7, 0xe4, 0x16, 0x9b, 0xe7, 0x7f, 0x3a, 0x75, 0x65, 0x97, 0x78, 0x13, 0x19, 0xa3, 0x5c, 0xa9, 0x42, 0xf6, 0xfb, 0x6a}, - }, - { /* 59P */ - addYX: fp.Elt{0xcc, 0xa8, 0x13, 0xf9, 0x70, 0x50, 0xe5, 0x5d, 0x61, 0xf5, 0x0c, 0x2b, 0x7b, 0x16, 0x1d, 0x7d, 0x89, 0xd4, 0xea, 0x90, 0xb6, 0x56, 0x29, 0xda, 0xd9, 0x1e, 0x80, 0xdb, 0xce, 0x93, 0xc0, 0x12}, - subYX: fp.Elt{0xc1, 0xd2, 0xf5, 0x62, 0x0c, 0xde, 0xa8, 0x7d, 0x9a, 0x7b, 0x0e, 0xb0, 0xa4, 0x3d, 0xfc, 0x98, 0xe0, 0x70, 0xad, 0x0d, 0xda, 0x6a, 0xeb, 0x7d, 0xc4, 0x38, 0x50, 0xb9, 0x51, 0xb8, 0xb4, 0x0d}, - dt2: fp.Elt{0x0f, 0x19, 0xb8, 0x08, 0x93, 0x7f, 0x14, 0xfc, 0x10, 0xe3, 0x1a, 0xa1, 0xa0, 0x9d, 0x96, 0x06, 0xfd, 0xd7, 0xc7, 0xda, 0x72, 0x55, 0xe7, 0xce, 0xe6, 0x5c, 0x63, 0xc6, 0x99, 0x87, 0xaa, 0x33}, - }, - { /* 61P */ - addYX: fp.Elt{0xb1, 0x6c, 0x15, 0xfc, 0x88, 0xf5, 0x48, 0x83, 0x27, 0x6d, 0x0a, 0x1a, 0x9b, 0xba, 0xa2, 0x6d, 0xb6, 0x5a, 0xca, 0x87, 0x5c, 0x2d, 0x26, 0xe2, 0xa6, 0x89, 0xd5, 0xc8, 0xc1, 0xd0, 0x2c, 0x21}, - subYX: fp.Elt{0xf2, 0x5c, 0x08, 0xbd, 0x1e, 0xf5, 0x0f, 0xaf, 0x1f, 0x3f, 0xd3, 0x67, 0x89, 0x1a, 0xf5, 0x78, 0x3c, 0x03, 0x60, 0x50, 0xe1, 0xbf, 0xc2, 0x6e, 0x86, 0x1a, 0xe2, 0xe8, 0x29, 0x6f, 0x3c, 0x23}, - dt2: fp.Elt{0x81, 0xc7, 0x18, 0x7f, 0x10, 0xd5, 0xf4, 0xd2, 0x28, 0x9d, 0x7e, 0x52, 0xf2, 0xcd, 0x2e, 0x12, 0x41, 0x33, 0x3d, 0x3d, 0x2a, 0x86, 0x0a, 0xa7, 0xe3, 0x4c, 0x91, 0x11, 0x89, 0x77, 0xb7, 0x1d}, - }, - { /* 63P */ - addYX: fp.Elt{0xb6, 0x1a, 0x70, 0xdd, 0x69, 0x47, 0x39, 0xb3, 0xa5, 0x8d, 0xcf, 0x19, 0xd4, 0xde, 0xb8, 0xe2, 0x52, 0xc8, 0x2a, 0xfd, 0x61, 0x41, 0xdf, 0x15, 0xbe, 0x24, 0x7d, 0x01, 0x8a, 0xca, 0xe2, 0x7a}, - subYX: fp.Elt{0x6f, 0xc2, 0x6b, 0x7c, 0x39, 0x52, 0xf3, 0xdd, 0x13, 0x01, 0xd5, 0x53, 0xcc, 0xe2, 0x97, 0x7a, 0x30, 0xa3, 0x79, 0xbf, 0x3a, 0xf4, 0x74, 0x7c, 0xfc, 0xad, 0xe2, 0x26, 0xad, 0x97, 0xad, 0x31}, - dt2: fp.Elt{0x62, 0xb9, 0x20, 0x09, 0xed, 0x17, 0xe8, 0xb7, 0x9d, 0xda, 0x19, 0x3f, 0xcc, 0x18, 0x85, 0x1e, 0x64, 0x0a, 0x56, 0x25, 0x4f, 0xc1, 0x91, 0xe4, 0x83, 0x2c, 0x62, 0xa6, 0x53, 0xfc, 0xd1, 0x1e}, - }, -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed448/ed448.go b/vendor/github.com/cloudflare/circl/sign/ed448/ed448.go deleted file mode 100644 index c368b181..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed448/ed448.go +++ /dev/null @@ -1,411 +0,0 @@ -// Package ed448 implements Ed448 signature scheme as described in RFC-8032. -// -// This package implements two signature variants. -// -// | Scheme Name | Sign Function | Verification | Context | -// |-------------|-------------------|---------------|-------------------| -// | Ed448 | Sign | Verify | Yes, can be empty | -// | Ed448Ph | SignPh | VerifyPh | Yes, can be empty | -// | All above | (PrivateKey).Sign | VerifyAny | As above | -// -// Specific functions for sign and verify are defined. A generic signing -// function for all schemes is available through the crypto.Signer interface, -// which is implemented by the PrivateKey type. A correspond all-in-one -// verification method is provided by the VerifyAny function. -// -// Both schemes require a context string for domain separation. This parameter -// is passed using a SignerOptions struct defined in this package. -// -// References: -// -// - RFC8032: https://rfc-editor.org/rfc/rfc8032.txt -// - EdDSA for more curves: https://eprint.iacr.org/2015/677 -// - High-speed high-security signatures: https://doi.org/10.1007/s13389-012-0027-1 -package ed448 - -import ( - "bytes" - "crypto" - cryptoRand "crypto/rand" - "crypto/subtle" - "errors" - "fmt" - "io" - "strconv" - - "github.com/cloudflare/circl/ecc/goldilocks" - "github.com/cloudflare/circl/internal/sha3" - "github.com/cloudflare/circl/sign" -) - -const ( - // ContextMaxSize is the maximum length (in bytes) allowed for context. - ContextMaxSize = 255 - // PublicKeySize is the length in bytes of Ed448 public keys. - PublicKeySize = 57 - // PrivateKeySize is the length in bytes of Ed448 private keys. - PrivateKeySize = 114 - // SignatureSize is the length in bytes of signatures. - SignatureSize = 114 - // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. - SeedSize = 57 -) - -const ( - paramB = 456 / 8 // Size of keys in bytes. - hashSize = 2 * paramB // Size of the hash function's output. -) - -// SignerOptions implements crypto.SignerOpts and augments with parameters -// that are specific to the Ed448 signature schemes. -type SignerOptions struct { - // Hash must be crypto.Hash(0) for both Ed448 and Ed448Ph. - crypto.Hash - - // Context is an optional domain separation string for signing. - // Its length must be less or equal than 255 bytes. - Context string - - // Scheme is an identifier for choosing a signature scheme. - Scheme SchemeID -} - -// SchemeID is an identifier for each signature scheme. -type SchemeID uint - -const ( - ED448 SchemeID = iota - ED448Ph -) - -// PublicKey is the type of Ed448 public keys. -type PublicKey []byte - -// Equal reports whether pub and x have the same value. -func (pub PublicKey) Equal(x crypto.PublicKey) bool { - xx, ok := x.(PublicKey) - return ok && bytes.Equal(pub, xx) -} - -// PrivateKey is the type of Ed448 private keys. It implements crypto.Signer. -type PrivateKey []byte - -// Equal reports whether priv and x have the same value. -func (priv PrivateKey) Equal(x crypto.PrivateKey) bool { - xx, ok := x.(PrivateKey) - return ok && subtle.ConstantTimeCompare(priv, xx) == 1 -} - -// Public returns the PublicKey corresponding to priv. -func (priv PrivateKey) Public() crypto.PublicKey { - publicKey := make([]byte, PublicKeySize) - copy(publicKey, priv[SeedSize:]) - return PublicKey(publicKey) -} - -// Seed returns the private key seed corresponding to priv. It is provided for -// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds -// in this package. -func (priv PrivateKey) Seed() []byte { - seed := make([]byte, SeedSize) - copy(seed, priv[:SeedSize]) - return seed -} - -func (priv PrivateKey) Scheme() sign.Scheme { return sch } - -func (pub PublicKey) Scheme() sign.Scheme { return sch } - -func (priv PrivateKey) MarshalBinary() (data []byte, err error) { - privateKey := make(PrivateKey, PrivateKeySize) - copy(privateKey, priv) - return privateKey, nil -} - -func (pub PublicKey) MarshalBinary() (data []byte, err error) { - publicKey := make(PublicKey, PublicKeySize) - copy(publicKey, pub) - return publicKey, nil -} - -// Sign creates a signature of a message given a key pair. -// This function supports all the two signature variants defined in RFC-8032, -// namely Ed448 (or pure EdDSA) and Ed448Ph. -// The opts.HashFunc() must return zero to the specify Ed448 variant. This can -// be achieved by passing crypto.Hash(0) as the value for opts. -// Use an Options struct to pass a bool indicating that the ed448Ph variant -// should be used. -// The struct can also be optionally used to pass a context string for signing. -func (priv PrivateKey) Sign( - rand io.Reader, - message []byte, - opts crypto.SignerOpts, -) (signature []byte, err error) { - var ctx string - var scheme SchemeID - - if o, ok := opts.(SignerOptions); ok { - ctx = o.Context - scheme = o.Scheme - } - - switch true { - case scheme == ED448 && opts.HashFunc() == crypto.Hash(0): - return Sign(priv, message, ctx), nil - case scheme == ED448Ph && opts.HashFunc() == crypto.Hash(0): - return SignPh(priv, message, ctx), nil - default: - return nil, errors.New("ed448: bad hash algorithm") - } -} - -// GenerateKey generates a public/private key pair using entropy from rand. -// If rand is nil, crypto/rand.Reader will be used. -func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - if rand == nil { - rand = cryptoRand.Reader - } - - seed := make(PrivateKey, SeedSize) - if _, err := io.ReadFull(rand, seed); err != nil { - return nil, nil, err - } - - privateKey := NewKeyFromSeed(seed) - publicKey := make([]byte, PublicKeySize) - copy(publicKey, privateKey[SeedSize:]) - - return publicKey, privateKey, nil -} - -// NewKeyFromSeed calculates a private key from a seed. It will panic if -// len(seed) is not SeedSize. This function is provided for interoperability -// with RFC 8032. RFC 8032's private keys correspond to seeds in this -// package. -func NewKeyFromSeed(seed []byte) PrivateKey { - privateKey := make([]byte, PrivateKeySize) - newKeyFromSeed(privateKey, seed) - return privateKey -} - -func newKeyFromSeed(privateKey, seed []byte) { - if l := len(seed); l != SeedSize { - panic("ed448: bad seed length: " + strconv.Itoa(l)) - } - - var h [hashSize]byte - H := sha3.NewShake256() - _, _ = H.Write(seed) - _, _ = H.Read(h[:]) - s := &goldilocks.Scalar{} - deriveSecretScalar(s, h[:paramB]) - - copy(privateKey[:SeedSize], seed) - _ = goldilocks.Curve{}.ScalarBaseMult(s).ToBytes(privateKey[SeedSize:]) -} - -func signAll(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) { - if len(ctx) > ContextMaxSize { - panic(fmt.Errorf("ed448: bad context length: %v", len(ctx))) - } - - H := sha3.NewShake256() - var PHM []byte - - if preHash { - var h [64]byte - _, _ = H.Write(message) - _, _ = H.Read(h[:]) - PHM = h[:] - H.Reset() - } else { - PHM = message - } - - // 1. Hash the 57-byte private key using SHAKE256(x, 114). - var h [hashSize]byte - _, _ = H.Write(privateKey[:SeedSize]) - _, _ = H.Read(h[:]) - s := &goldilocks.Scalar{} - deriveSecretScalar(s, h[:paramB]) - prefix := h[paramB:] - - // 2. Compute SHAKE256(dom4(F, C) || prefix || PH(M), 114). - var rPM [hashSize]byte - H.Reset() - - writeDom(&H, ctx, preHash) - - _, _ = H.Write(prefix) - _, _ = H.Write(PHM) - _, _ = H.Read(rPM[:]) - - // 3. Compute the point [r]B. - r := &goldilocks.Scalar{} - r.FromBytes(rPM[:]) - R := (&[paramB]byte{})[:] - if err := (goldilocks.Curve{}.ScalarBaseMult(r).ToBytes(R)); err != nil { - panic(err) - } - // 4. Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114) - var hRAM [hashSize]byte - H.Reset() - - writeDom(&H, ctx, preHash) - - _, _ = H.Write(R) - _, _ = H.Write(privateKey[SeedSize:]) - _, _ = H.Write(PHM) - _, _ = H.Read(hRAM[:]) - - // 5. Compute S = (r + k * s) mod order. - k := &goldilocks.Scalar{} - k.FromBytes(hRAM[:]) - S := &goldilocks.Scalar{} - S.Mul(k, s) - S.Add(S, r) - - // 6. The signature is the concatenation of R and S. - copy(signature[:paramB], R[:]) - copy(signature[paramB:], S[:]) -} - -// Sign signs the message with privateKey and returns a signature. -// This function supports the signature variant defined in RFC-8032: Ed448, -// also known as the pure version of EdDSA. -// It will panic if len(privateKey) is not PrivateKeySize. -func Sign(priv PrivateKey, message []byte, ctx string) []byte { - signature := make([]byte, SignatureSize) - signAll(signature, priv, message, []byte(ctx), false) - return signature -} - -// SignPh creates a signature of a message given a keypair. -// This function supports the signature variant defined in RFC-8032: Ed448ph, -// meaning it internally hashes the message using SHAKE-256. -// Context could be passed to this function, which length should be no more than -// 255. It can be empty. -func SignPh(priv PrivateKey, message []byte, ctx string) []byte { - signature := make([]byte, SignatureSize) - signAll(signature, priv, message, []byte(ctx), true) - return signature -} - -func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool { - if len(public) != PublicKeySize || - len(signature) != SignatureSize || - len(ctx) > ContextMaxSize || - !isLessThanOrder(signature[paramB:]) { - return false - } - - P, err := goldilocks.FromBytes(public) - if err != nil { - return false - } - - H := sha3.NewShake256() - var PHM []byte - - if preHash { - var h [64]byte - _, _ = H.Write(message) - _, _ = H.Read(h[:]) - PHM = h[:] - H.Reset() - } else { - PHM = message - } - - var hRAM [hashSize]byte - R := signature[:paramB] - - writeDom(&H, ctx, preHash) - - _, _ = H.Write(R) - _, _ = H.Write(public) - _, _ = H.Write(PHM) - _, _ = H.Read(hRAM[:]) - - k := &goldilocks.Scalar{} - k.FromBytes(hRAM[:]) - S := &goldilocks.Scalar{} - S.FromBytes(signature[paramB:]) - - encR := (&[paramB]byte{})[:] - P.Neg() - _ = goldilocks.Curve{}.CombinedMult(S, k, P).ToBytes(encR) - return bytes.Equal(R, encR) -} - -// VerifyAny returns true if the signature is valid. Failure cases are invalid -// signature, or when the public key cannot be decoded. -// This function supports all the two signature variants defined in RFC-8032, -// namely Ed448 (or pure EdDSA) and Ed448Ph. -// The opts.HashFunc() must return zero, this can be achieved by passing -// crypto.Hash(0) as the value for opts. -// Use a SignerOptions struct to pass a context string for signing. -func VerifyAny(public PublicKey, message, signature []byte, opts crypto.SignerOpts) bool { - var ctx string - var scheme SchemeID - if o, ok := opts.(SignerOptions); ok { - ctx = o.Context - scheme = o.Scheme - } - - switch true { - case scheme == ED448 && opts.HashFunc() == crypto.Hash(0): - return Verify(public, message, signature, ctx) - case scheme == ED448Ph && opts.HashFunc() == crypto.Hash(0): - return VerifyPh(public, message, signature, ctx) - default: - return false - } -} - -// Verify returns true if the signature is valid. Failure cases are invalid -// signature, or when the public key cannot be decoded. -// This function supports the signature variant defined in RFC-8032: Ed448, -// also known as the pure version of EdDSA. -func Verify(public PublicKey, message, signature []byte, ctx string) bool { - return verify(public, message, signature, []byte(ctx), false) -} - -// VerifyPh returns true if the signature is valid. Failure cases are invalid -// signature, or when the public key cannot be decoded. -// This function supports the signature variant defined in RFC-8032: Ed448ph, -// meaning it internally hashes the message using SHAKE-256. -// Context could be passed to this function, which length should be no more than -// 255. It can be empty. -func VerifyPh(public PublicKey, message, signature []byte, ctx string) bool { - return verify(public, message, signature, []byte(ctx), true) -} - -func deriveSecretScalar(s *goldilocks.Scalar, h []byte) { - h[0] &= 0xFC // The two least significant bits of the first octet are cleared, - h[paramB-1] = 0x00 // all eight bits the last octet are cleared, and - h[paramB-2] |= 0x80 // the highest bit of the second to last octet is set. - s.FromBytes(h[:paramB]) -} - -// isLessThanOrder returns true if 0 <= x < order and if the last byte of x is zero. -func isLessThanOrder(x []byte) bool { - order := goldilocks.Curve{}.Order() - i := len(order) - 1 - for i > 0 && x[i] == order[i] { - i-- - } - return x[paramB-1] == 0 && x[i] < order[i] -} - -func writeDom(h io.Writer, ctx []byte, preHash bool) { - dom4 := "SigEd448" - _, _ = h.Write([]byte(dom4)) - - if preHash { - _, _ = h.Write([]byte{byte(0x01), byte(len(ctx))}) - } else { - _, _ = h.Write([]byte{byte(0x00), byte(len(ctx))}) - } - _, _ = h.Write(ctx) -} diff --git a/vendor/github.com/cloudflare/circl/sign/ed448/signapi.go b/vendor/github.com/cloudflare/circl/sign/ed448/signapi.go deleted file mode 100644 index 22da8bc0..00000000 --- a/vendor/github.com/cloudflare/circl/sign/ed448/signapi.go +++ /dev/null @@ -1,87 +0,0 @@ -package ed448 - -import ( - "crypto/rand" - "encoding/asn1" - - "github.com/cloudflare/circl/sign" -) - -var sch sign.Scheme = &scheme{} - -// Scheme returns a signature interface. -func Scheme() sign.Scheme { return sch } - -type scheme struct{} - -func (*scheme) Name() string { return "Ed448" } -func (*scheme) PublicKeySize() int { return PublicKeySize } -func (*scheme) PrivateKeySize() int { return PrivateKeySize } -func (*scheme) SignatureSize() int { return SignatureSize } -func (*scheme) SeedSize() int { return SeedSize } -func (*scheme) TLSIdentifier() uint { return 0x0808 } -func (*scheme) SupportsContext() bool { return true } -func (*scheme) Oid() asn1.ObjectIdentifier { - return asn1.ObjectIdentifier{1, 3, 101, 113} -} - -func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) { - return GenerateKey(rand.Reader) -} - -func (*scheme) Sign( - sk sign.PrivateKey, - message []byte, - opts *sign.SignatureOpts, -) []byte { - priv, ok := sk.(PrivateKey) - if !ok { - panic(sign.ErrTypeMismatch) - } - ctx := "" - if opts != nil { - ctx = opts.Context - } - return Sign(priv, message, ctx) -} - -func (*scheme) Verify( - pk sign.PublicKey, - message, signature []byte, - opts *sign.SignatureOpts, -) bool { - pub, ok := pk.(PublicKey) - if !ok { - panic(sign.ErrTypeMismatch) - } - ctx := "" - if opts != nil { - ctx = opts.Context - } - return Verify(pub, message, signature, ctx) -} - -func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) { - privateKey := NewKeyFromSeed(seed) - publicKey := make(PublicKey, PublicKeySize) - copy(publicKey, privateKey[SeedSize:]) - return publicKey, privateKey -} - -func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) { - if len(buf) < PublicKeySize { - return nil, sign.ErrPubKeySize - } - pub := make(PublicKey, PublicKeySize) - copy(pub, buf[:PublicKeySize]) - return pub, nil -} - -func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) { - if len(buf) < PrivateKeySize { - return nil, sign.ErrPrivKeySize - } - priv := make(PrivateKey, PrivateKeySize) - copy(priv, buf[:PrivateKeySize]) - return priv, nil -} diff --git a/vendor/github.com/cloudflare/circl/sign/sign.go b/vendor/github.com/cloudflare/circl/sign/sign.go deleted file mode 100644 index 557d6f09..00000000 --- a/vendor/github.com/cloudflare/circl/sign/sign.go +++ /dev/null @@ -1,113 +0,0 @@ -// Package sign provides unified interfaces for signature schemes. -// -// A register of schemes is available in the package -// -// github.com/cloudflare/circl/sign/schemes -package sign - -import ( - "crypto" - "encoding" - "errors" -) - -type SignatureOpts struct { - // If non-empty, includes the given context in the signature if supported - // and will cause an error during signing otherwise. - Context string -} - -// A public key is used to verify a signature set by the corresponding private -// key. -type PublicKey interface { - // Returns the signature scheme for this public key. - Scheme() Scheme - Equal(crypto.PublicKey) bool - encoding.BinaryMarshaler - crypto.PublicKey -} - -// A private key allows one to create signatures. -type PrivateKey interface { - // Returns the signature scheme for this private key. - Scheme() Scheme - Equal(crypto.PrivateKey) bool - // For compatibility with Go standard library - crypto.Signer - crypto.PrivateKey - encoding.BinaryMarshaler -} - -// A Scheme represents a specific instance of a signature scheme. -type Scheme interface { - // Name of the scheme. - Name() string - - // GenerateKey creates a new key-pair. - GenerateKey() (PublicKey, PrivateKey, error) - - // Creates a signature using the PrivateKey on the given message and - // returns the signature. opts are additional options which can be nil. - // - // Panics if key is nil or wrong type or opts context is not supported. - Sign(sk PrivateKey, message []byte, opts *SignatureOpts) []byte - - // Checks whether the given signature is a valid signature set by - // the private key corresponding to the given public key on the - // given message. opts are additional options which can be nil. - // - // Panics if key is nil or wrong type or opts context is not supported. - Verify(pk PublicKey, message []byte, signature []byte, opts *SignatureOpts) bool - - // Deterministically derives a keypair from a seed. If you're unsure, - // you're better off using GenerateKey(). - // - // Panics if seed is not of length SeedSize(). - DeriveKey(seed []byte) (PublicKey, PrivateKey) - - // Unmarshals a PublicKey from the provided buffer. - UnmarshalBinaryPublicKey([]byte) (PublicKey, error) - - // Unmarshals a PublicKey from the provided buffer. - UnmarshalBinaryPrivateKey([]byte) (PrivateKey, error) - - // Size of binary marshalled public keys. - PublicKeySize() int - - // Size of binary marshalled public keys. - PrivateKeySize() int - - // Size of signatures. - SignatureSize() int - - // Size of seeds. - SeedSize() int - - // Returns whether contexts are supported. - SupportsContext() bool -} - -var ( - // ErrTypeMismatch is the error used if types of, for instance, private - // and public keys don't match. - ErrTypeMismatch = errors.New("types mismatch") - - // ErrSeedSize is the error used if the provided seed is of the wrong - // size. - ErrSeedSize = errors.New("wrong seed size") - - // ErrPubKeySize is the error used if the provided public key is of - // the wrong size. - ErrPubKeySize = errors.New("wrong size for public key") - - // ErrPrivKeySize is the error used if the provided private key is of - // the wrong size. - ErrPrivKeySize = errors.New("wrong size for private key") - - // ErrContextNotSupported is the error used if a context is not - // supported. - ErrContextNotSupported = errors.New("context not supported") - - // ErrContextTooLong is the error used if the context string is too long. - ErrContextTooLong = errors.New("context string too long") -) diff --git a/vendor/github.com/crazy3lf/colorconv/LICENSE b/vendor/github.com/crazy3lf/colorconv/LICENSE deleted file mode 100644 index 98ba0bfc..00000000 --- a/vendor/github.com/crazy3lf/colorconv/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Shu Fu Xiang - -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/crazy3lf/colorconv/README.md b/vendor/github.com/crazy3lf/colorconv/README.md deleted file mode 100644 index fa184841..00000000 --- a/vendor/github.com/crazy3lf/colorconv/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# colorconv -[![Go Reference](https://pkg.go.dev/badge/github.com/crazy3lf/colorconv.svg)](https://pkg.go.dev/github.com/crazy3lf/colorconv) -[![Go Report Card](https://goreportcard.com/badge/github.com/Crazy3lf/colorconv)](https://goreportcard.com/report/github.com/Crazy3lf/colorconv) - -Library to support RGB conversion to HSL, HSV and Hex value for Golang. -This library make use of Go standard library with no external dependency. -### INSTALLATION / UPDATING - go get -u github.com/crazy3lf/colorconv diff --git a/vendor/github.com/crazy3lf/colorconv/colorconv.go b/vendor/github.com/crazy3lf/colorconv/colorconv.go deleted file mode 100644 index 48c60639..00000000 --- a/vendor/github.com/crazy3lf/colorconv/colorconv.go +++ /dev/null @@ -1,272 +0,0 @@ -// Package colorconv provide conversion of color to HSL, HSV and hex value. -// All the conversion methods is based on the website: https://www.rapidtables.com/convert/color/index.html -package colorconv - -import ( - "errors" - "fmt" - "image/color" - "math" - "strconv" - "strings" -) - -var ErrInvalidHexValue = errors.New("colorconv: invalid input") -var ErrOutOfRange = errors.New("colorconv: inputs out of range") - -//ColorToHSL convert color.Color into HSL triple, ignoring the alpha channel. -func ColorToHSL(c color.Color) (h, s, l float64) { - r, g, b, _ := c.RGBA() - return RGBToHSL(uint8(r>>8), uint8(g>>8), uint8(b>>8)) -} - -//ColorToHSV convert color.Color into HSV triple, ignoring the alpha channel. -func ColorToHSV(c color.Color) (h, s, v float64) { - r, g, b, _ := c.RGBA() - return RGBToHSV(uint8(r>>8), uint8(g>>8), uint8(b>>8)) -} - -//ColorToHex convert color.Color into Hex string, ignoring the alpha channel. -func ColorToHex(c color.Color) string { - r, g, b, _ := c.RGBA() - return RGBToHex(uint8(r>>8), uint8(g>>8), uint8(b>>8)) -} - -//HSLToColor convert HSL triple into color.Color. -func HSLToColor(h, s, l float64) (color.Color, error) { - r, g, b, err := HSLToRGB(h, s, l) - if err != nil { - return nil, err - } - return color.RGBA{R: r, G: g, B: b, A: 0}, nil -} - -//HSVToColor convert HSV triple into color.Color. -func HSVToColor(h, s, v float64) (color.Color, error) { - r, g, b, err := HSVToRGB(h, s, v) - if err != nil { - return nil, err - } - return color.RGBA{R: r, G: g, B: b, A: 0}, nil -} - -//HexToColor convert Hex string into color.Color. -func HexToColor(hex string) (color.Color, error) { - r, g, b, err := HexToRGB(hex) - if err != nil { - return nil, err - } - return color.RGBA{R: r, G: g, B: b, A: 0}, nil -} - -//RGBToHSL converts an RGB triple to an HSL triple. -func RGBToHSL(r, g, b uint8) (h, s, l float64) { - // convert uint32 pre-multiplied value to uint8 - // The r,g,b values are divided by 255 to change the range from 0..255 to 0..1: - Rnot := float64(r) / 255 - Gnot := float64(g) / 255 - Bnot := float64(b) / 255 - Cmax, Cmin := getMaxMin(Rnot, Gnot, Bnot) - Δ := Cmax - Cmin - // Lightness calculation: - l = (Cmax + Cmin) / 2 - // Hue and Saturation Calculation: - if Δ == 0 { - h = 0 - s = 0 - } else { - switch Cmax { - case Rnot: - h = 60 * (math.Mod((Gnot-Bnot)/Δ, 6)) - case Gnot: - h = 60 * (((Bnot - Rnot) / Δ) + 2) - case Bnot: - h = 60 * (((Rnot - Gnot) / Δ) + 4) - } - if h < 0 { - h += 360 - } - - s = Δ / (1 - math.Abs((2*l)-1)) - } - - return h, round(s), round(l) -} - -//HSLToRGB converts an HSL triple to an RGB triple. -func HSLToRGB(h, s, l float64) (r, g, b uint8, err error) { - if h < 0 || h >= 360 || - s < 0 || s > 1 || - l < 0 || l > 1 { - return 0, 0, 0, ErrOutOfRange - } - // When 0 ≤ h < 360, 0 ≤ s ≤ 1 and 0 ≤ l ≤ 1: - C := (1 - math.Abs((2*l)-1)) * s - X := C * (1 - math.Abs(math.Mod(h/60, 2)-1)) - m := l - (C / 2) - var Rnot, Gnot, Bnot float64 - - switch { - case 0 <= h && h < 60: - Rnot, Gnot, Bnot = C, X, 0 - case 60 <= h && h < 120: - Rnot, Gnot, Bnot = X, C, 0 - case 120 <= h && h < 180: - Rnot, Gnot, Bnot = 0, C, X - case 180 <= h && h < 240: - Rnot, Gnot, Bnot = 0, X, C - case 240 <= h && h < 300: - Rnot, Gnot, Bnot = X, 0, C - case 300 <= h && h < 360: - Rnot, Gnot, Bnot = C, 0, X - } - r = uint8(math.Round((Rnot + m) * 255)) - g = uint8(math.Round((Gnot + m) * 255)) - b = uint8(math.Round((Bnot + m) * 255)) - return r, g, b, nil -} - -//RGBToHSV converts an RGB triple to an HSV triple. -func RGBToHSV(r, g, b uint8) (h, s, v float64) { - // convert uint32 pre-multiplied value to uint8 - // The r,g,b values are divided by 255 to change the range from 0..255 to 0..1: - Rnot := float64(r) / 255 - Gnot := float64(g) / 255 - Bnot := float64(b) / 255 - Cmax, Cmin := getMaxMin(Rnot, Gnot, Bnot) - Δ := Cmax - Cmin - - // Hue calculation: - if Δ == 0 { - h = 0 - } else { - switch Cmax { - case Rnot: - h = 60 * (math.Mod((Gnot-Bnot)/Δ, 6)) - case Gnot: - h = 60 * (((Bnot - Rnot) / Δ) + 2) - case Bnot: - h = 60 * (((Rnot - Gnot) / Δ) + 4) - } - if h < 0 { - h += 360 - } - - } - // Saturation calculation: - if Cmax == 0 { - s = 0 - } else { - s = Δ / Cmax - } - // Value calculation: - v = Cmax - - return h, round(s), round(v) -} - -//HSVToRGB converts an HSV triple to an RGB triple. -func HSVToRGB(h, s, v float64) (r, g, b uint8, err error) { - if h < 0 || h >= 360 || - s < 0 || s > 1 || - v < 0 || v > 1 { - return 0, 0, 0, ErrOutOfRange - } - // When 0 ≤ h < 360, 0 ≤ s ≤ 1 and 0 ≤ v ≤ 1: - C := v * s - X := C * (1 - math.Abs(math.Mod(h/60, 2)-1)) - m := v - C - var Rnot, Gnot, Bnot float64 - switch { - case 0 <= h && h < 60: - Rnot, Gnot, Bnot = C, X, 0 - case 60 <= h && h < 120: - Rnot, Gnot, Bnot = X, C, 0 - case 120 <= h && h < 180: - Rnot, Gnot, Bnot = 0, C, X - case 180 <= h && h < 240: - Rnot, Gnot, Bnot = 0, X, C - case 240 <= h && h < 300: - Rnot, Gnot, Bnot = X, 0, C - case 300 <= h && h < 360: - Rnot, Gnot, Bnot = C, 0, X - } - r = uint8(math.Round((Rnot + m) * 255)) - g = uint8(math.Round((Gnot + m) * 255)) - b = uint8(math.Round((Bnot + m) * 255)) - return r, g, b, nil -} - -//RGBToHex converts an RGB triple to a Hex string in the format of 0xffff. -func RGBToHex(r, g, b uint8) string { - return fmt.Sprintf("0x%02x%02x%02x", r, g, b) -} - -//HexToRGB converts a Hex string to an RGB triple. -func HexToRGB(hex string) (r, g, b uint8, err error) { - // remove prefixes if found in the input string - hex = strings.Replace(hex, "0x", "", -1) - hex = strings.Replace(hex, "#", "", -1) - if len(hex) != 6 { - return 0, 0, 0, ErrInvalidHexValue - } - - r, err = hex2uint8(hex[0:2]) - if err != nil { - return 0, 0, 0, err - } - g, err = hex2uint8(hex[2:4]) - if err != nil { - return 0, 0, 0, err - } - b, err = hex2uint8(hex[4:6]) - if err != nil { - return 0, 0, 0, err - } - return r, g, b, nil -} - -//RGBToGrayAverage calculates the grayscale value of RGB with the average method, ignoring the alpha channel. -func RGBToGrayAverage(r, g, b uint8) color.Gray { - return RGBToGrayWithWeight(r, g, b, 1, 1, 1) -} - -// RGBToGrayWithWeight calculates the grayscale value of RGB wih provided weight, ignoring the alpha channel. -// In the standard library image/color, the conversion used the coefficient given by the JFIF specification. It is -// equivalent to using the weight 299, 587, 114 for rgb. -func RGBToGrayWithWeight(r, g, b uint8, rWeight, gWeight, bWeight uint) color.Gray { - rw := uint(r) * rWeight - gw := uint(g) * gWeight - bw := uint(b) * bWeight - - return color.Gray{Y: uint8(math.Round(float64(rw+gw+bw) / float64(rWeight+gWeight+bWeight)))} -} - -func hex2uint8(hexStr string) (uint8, error) { - // base 16 for hexadecimal - result, err := strconv.ParseUint(hexStr, 16, 8) - if err != nil { - return 0, err - } - return uint8(result), nil -} - -func getMaxMin(a, b, c float64) (max, min float64) { - if a > b { - max = a - min = b - } else { - max = b - min = a - } - if c > max { - max = c - } else if c < min { - min = c - } - return max, min -} - -func round(x float64) float64 { - return math.Round(x*1000) / 1000 -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md deleted file mode 100644 index ca0e3c62..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md +++ /dev/null @@ -1,256 +0,0 @@ -# Changelog # -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). - -## [Unreleased] ## - -## [0.4.1] - 2025-01-28 ## - -### Fixed ### -- The restrictions added for `root` paths passed to `SecureJoin` in 0.4.0 was - found to be too strict and caused some regressions when folks tried to - update, so this restriction has been relaxed to only return an error if the - path contains a `..` component. We still recommend users use `filepath.Clean` - (and even `filepath.EvalSymlinks`) on the `root` path they are using, but at - least you will no longer be punished for "trivial" unclean paths. - -## [0.4.0] - 2025-01-13 ## - -### Breaking #### -- `SecureJoin(VFS)` will now return an error if the provided `root` is not a - `filepath.Clean`'d path. - - While it is ultimately the responsibility of the caller to ensure the root is - a safe path to use, passing a path like `/symlink/..` as a root would result - in the `SecureJoin`'d path being placed in `/` even though `/symlink/..` - might be a different directory, and so we should more strongly discourage - such usage. - - All major users of `securejoin.SecureJoin` already ensure that the paths they - provide are safe (and this is ultimately a question of user error), but - removing this foot-gun is probably a good idea. Of course, this is - necessarily a breaking API change (though we expect no real users to be - affected by it). - - Thanks to [Erik Sjölund](https://github.com/eriksjolund), who initially - reported this issue as a possible security issue. - -- `MkdirAll` and `MkdirHandle` now take an `os.FileMode`-style mode argument - instead of a raw `unix.S_*`-style mode argument, which may cause compile-time - type errors depending on how you use `filepath-securejoin`. For most users, - there will be no change in behaviour aside from the type change (as the - bottom `0o777` bits are the same in both formats, and most users are probably - only using those bits). - - However, if you were using `unix.S_ISVTX` to set the sticky bit with - `MkdirAll(Handle)` you will need to switch to `os.ModeSticky` otherwise you - will get a runtime error with this update. In addition, the error message you - will get from passing `unix.S_ISUID` and `unix.S_ISGID` will be different as - they are treated as invalid bits now (note that previously passing said bits - was also an error). - -## [0.3.6] - 2024-12-17 ## - -### Compatibility ### -- The minimum Go version requirement for `filepath-securejoin` is now Go 1.18 - (we use generics internally). - - For reference, `filepath-securejoin@v0.3.0` somewhat-arbitrarily bumped the - Go version requirement to 1.21. - - While we did make some use of Go 1.21 stdlib features (and in principle Go - versions <= 1.21 are no longer even supported by upstream anymore), some - downstreams have complained that the version bump has meant that they have to - do workarounds when backporting fixes that use the new `filepath-securejoin` - API onto old branches. This is not an ideal situation, but since using this - library is probably better for most downstreams than a hand-rolled - workaround, we now have compatibility shims that allow us to build on older - Go versions. -- Lower minimum version requirement for `golang.org/x/sys` to `v0.18.0` (we - need the wrappers for `fsconfig(2)`), which should also make backporting - patches to older branches easier. - -## [0.3.5] - 2024-12-06 ## - -### Fixed ### -- `MkdirAll` will now no longer return an `EEXIST` error if two racing - processes are creating the same directory. We will still verify that the path - is a directory, but this will avoid spurious errors when multiple threads or - programs are trying to `MkdirAll` the same path. opencontainers/runc#4543 - -## [0.3.4] - 2024-10-09 ## - -### Fixed ### -- Previously, some testing mocks we had resulted in us doing `import "testing"` - in non-`_test.go` code, which made some downstreams like Kubernetes unhappy. - This has been fixed. (#32) - -## [0.3.3] - 2024-09-30 ## - -### Fixed ### -- The mode and owner verification logic in `MkdirAll` has been removed. This - was originally intended to protect against some theoretical attacks but upon - further consideration these protections don't actually buy us anything and - they were causing spurious errors with more complicated filesystem setups. -- The "is the created directory empty" logic in `MkdirAll` has also been - removed. This was not causing us issues yet, but some pseudofilesystems (such - as `cgroup`) create non-empty directories and so this logic would've been - wrong for such cases. - -## [0.3.2] - 2024-09-13 ## - -### Changed ### -- Passing the `S_ISUID` or `S_ISGID` modes to `MkdirAllInRoot` will now return - an explicit error saying that those bits are ignored by `mkdirat(2)`. In the - past a different error was returned, but since the silent ignoring behaviour - is codified in the man pages a more explicit error seems apt. While silently - ignoring these bits would be the most compatible option, it could lead to - users thinking their code sets these bits when it doesn't. Programs that need - to deal with compatibility can mask the bits themselves. (#23, #25) - -### Fixed ### -- If a directory has `S_ISGID` set, then all child directories will have - `S_ISGID` set when created and a different gid will be used for any inode - created under the directory. Previously, the "expected owner and mode" - validation in `securejoin.MkdirAll` did not correctly handle this. We now - correctly handle this case. (#24, #25) - -## [0.3.1] - 2024-07-23 ## - -### Changed ### -- By allowing `Open(at)InRoot` to opt-out of the extra work done by `MkdirAll` - to do the necessary "partial lookups", `Open(at)InRoot` now does less work - for both implementations (resulting in a many-fold decrease in the number of - operations for `openat2`, and a modest improvement for non-`openat2`) and is - far more guaranteed to match the correct `openat2(RESOLVE_IN_ROOT)` - behaviour. -- We now use `readlinkat(fd, "")` where possible. For `Open(at)InRoot` this - effectively just means that we no longer risk getting spurious errors during - rename races. However, for our hardened procfs handler, this in theory should - prevent mount attacks from tricking us when doing magic-link readlinks (even - when using the unsafe host `/proc` handle). Unfortunately `Reopen` is still - potentially vulnerable to those kinds of somewhat-esoteric attacks. - - Technically this [will only work on post-2.6.39 kernels][linux-readlinkat-emptypath] - but it seems incredibly unlikely anyone is using `filepath-securejoin` on a - pre-2011 kernel. - -### Fixed ### -- Several improvements were made to the errors returned by `Open(at)InRoot` and - `MkdirAll` when dealing with invalid paths under the emulated (ie. - non-`openat2`) implementation. Previously, some paths would return the wrong - error (`ENOENT` when the last component was a non-directory), and other paths - would be returned as though they were acceptable (trailing-slash components - after a non-directory would be ignored by `Open(at)InRoot`). - - These changes were done to match `openat2`'s behaviour and purely is a - consistency fix (most users are going to be using `openat2` anyway). - -[linux-readlinkat-emptypath]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65cfc6722361570bfe255698d9cd4dccaf47570d - -## [0.3.0] - 2024-07-11 ## - -### Added ### -- A new set of `*os.File`-based APIs have been added. These are adapted from - [libpathrs][] and we strongly suggest using them if possible (as they provide - far more protection against attacks than `SecureJoin`): - - - `Open(at)InRoot` resolves a path inside a rootfs and returns an `*os.File` - handle to the path. Note that the handle returned is an `O_PATH` handle, - which cannot be used for reading or writing (as well as some other - operations -- [see open(2) for more details][open.2]) - - - `Reopen` takes an `O_PATH` file handle and safely re-opens it to upgrade - it to a regular handle. This can also be used with non-`O_PATH` handles, - but `O_PATH` is the most obvious application. - - - `MkdirAll` is an implementation of `os.MkdirAll` that is safe to use to - create a directory tree within a rootfs. - - As these are new APIs, they may change in the future. However, they should be - safe to start migrating to as we have extensive tests ensuring they behave - correctly and are safe against various races and other attacks. - -[libpathrs]: https://github.com/openSUSE/libpathrs -[open.2]: https://www.man7.org/linux/man-pages/man2/open.2.html - -## [0.2.5] - 2024-05-03 ## - -### Changed ### -- Some minor changes were made to how lexical components (like `..` and `.`) - are handled during path generation in `SecureJoin`. There is no behaviour - change as a result of this fix (the resulting paths are the same). - -### Fixed ### -- The error returned when we hit a symlink loop now references the correct - path. (#10) - -## [0.2.4] - 2023-09-06 ## - -### Security ### -- This release fixes a potential security issue in filepath-securejoin when - used on Windows ([GHSA-6xv5-86q9-7xr8][], which could be used to generate - paths outside of the provided rootfs in certain cases), as well as improving - the overall behaviour of filepath-securejoin when dealing with Windows paths - that contain volume names. Thanks to Paulo Gomes for discovering and fixing - these issues. - -### Fixed ### -- Switch to GitHub Actions for CI so we can test on Windows as well as Linux - and MacOS. - -[GHSA-6xv5-86q9-7xr8]: https://github.com/advisories/GHSA-6xv5-86q9-7xr8 - -## [0.2.3] - 2021-06-04 ## - -### Changed ### -- Switch to Go 1.13-style `%w` error wrapping, letting us drop the dependency - on `github.com/pkg/errors`. - -## [0.2.2] - 2018-09-05 ## - -### Changed ### -- Use `syscall.ELOOP` as the base error for symlink loops, rather than our own - (internal) error. This allows callers to more easily use `errors.Is` to check - for this case. - -## [0.2.1] - 2018-09-05 ## - -### Fixed ### -- Use our own `IsNotExist` implementation, which lets us handle `ENOTDIR` - properly within `SecureJoin`. - -## [0.2.0] - 2017-07-19 ## - -We now have 100% test coverage! - -### Added ### -- Add a `SecureJoinVFS` API that can be used for mocking (as we do in our new - tests) or for implementing custom handling of lookup operations (such as for - rootless containers, where work is necessary to access directories with weird - modes because we don't have `CAP_DAC_READ_SEARCH` or `CAP_DAC_OVERRIDE`). - -## 0.1.0 - 2017-07-19 - -This is our first release of `github.com/cyphar/filepath-securejoin`, -containing a full implementation with a coverage of 93.5% (the only missing -cases are the error cases, which are hard to mocktest at the moment). - -[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.1...HEAD -[0.4.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.0...v0.4.1 -[0.4.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...v0.4.0 -[0.3.6]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.5...v0.3.6 -[0.3.5]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.4...v0.3.5 -[0.3.4]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.3...v0.3.4 -[0.3.3]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.2...v0.3.3 -[0.3.2]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.1...v0.3.2 -[0.3.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.0...v0.3.1 -[0.3.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.5...v0.3.0 -[0.2.5]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.4...v0.2.5 -[0.2.4]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.3...v0.2.4 -[0.2.3]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.2...v0.2.3 -[0.2.2]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.1...v0.2.2 -[0.2.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.0...v0.2.1 -[0.2.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.1.0...v0.2.0 diff --git a/vendor/github.com/cyphar/filepath-securejoin/LICENSE b/vendor/github.com/cyphar/filepath-securejoin/LICENSE deleted file mode 100644 index cb1ab88d..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. -Copyright (C) 2017-2024 SUSE LLC. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/cyphar/filepath-securejoin/README.md b/vendor/github.com/cyphar/filepath-securejoin/README.md deleted file mode 100644 index eaeb53fc..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/README.md +++ /dev/null @@ -1,169 +0,0 @@ -## `filepath-securejoin` ## - -[![Go Documentation](https://pkg.go.dev/badge/github.com/cyphar/filepath-securejoin.svg)](https://pkg.go.dev/github.com/cyphar/filepath-securejoin) -[![Build Status](https://github.com/cyphar/filepath-securejoin/actions/workflows/ci.yml/badge.svg)](https://github.com/cyphar/filepath-securejoin/actions/workflows/ci.yml) - -### Old API ### - -This library was originally just an implementation of `SecureJoin` which was -[intended to be included in the Go standard library][go#20126] as a safer -`filepath.Join` that would restrict the path lookup to be inside a root -directory. - -The implementation was based on code that existed in several container -runtimes. Unfortunately, this API is **fundamentally unsafe** against attackers -that can modify path components after `SecureJoin` returns and before the -caller uses the path, allowing for some fairly trivial TOCTOU attacks. - -`SecureJoin` (and `SecureJoinVFS`) are still provided by this library to -support legacy users, but new users are strongly suggested to avoid using -`SecureJoin` and instead use the [new api](#new-api) or switch to -[libpathrs][libpathrs]. - -With the above limitations in mind, this library guarantees the following: - -* If no error is set, the resulting string **must** be a child path of - `root` and will not contain any symlink path components (they will all be - expanded). - -* When expanding symlinks, all symlink path components **must** be resolved - relative to the provided root. In particular, this can be considered a - userspace implementation of how `chroot(2)` operates on file paths. Note that - these symlinks will **not** be expanded lexically (`filepath.Clean` is not - called on the input before processing). - -* Non-existent path components are unaffected by `SecureJoin` (similar to - `filepath.EvalSymlinks`'s semantics). - -* The returned path will always be `filepath.Clean`ed and thus not contain any - `..` components. - -A (trivial) implementation of this function on GNU/Linux systems could be done -with the following (note that this requires root privileges and is far more -opaque than the implementation in this library, and also requires that -`readlink` is inside the `root` path and is trustworthy): - -```go -package securejoin - -import ( - "os/exec" - "path/filepath" -) - -func SecureJoin(root, unsafePath string) (string, error) { - unsafePath = string(filepath.Separator) + unsafePath - cmd := exec.Command("chroot", root, - "readlink", "--canonicalize-missing", "--no-newline", unsafePath) - output, err := cmd.CombinedOutput() - if err != nil { - return "", err - } - expanded := string(output) - return filepath.Join(root, expanded), nil -} -``` - -[libpathrs]: https://github.com/openSUSE/libpathrs -[go#20126]: https://github.com/golang/go/issues/20126 - -### New API ### - -While we recommend users switch to [libpathrs][libpathrs] as soon as it has a -stable release, some methods implemented by libpathrs have been ported to this -library to ease the transition. These APIs are only supported on Linux. - -These APIs are implemented such that `filepath-securejoin` will -opportunistically use certain newer kernel APIs that make these operations far -more secure. In particular: - -* All of the lookup operations will use [`openat2`][openat2.2] on new enough - kernels (Linux 5.6 or later) to restrict lookups through magic-links and - bind-mounts (for certain operations) and to make use of `RESOLVE_IN_ROOT` to - efficiently resolve symlinks within a rootfs. - -* The APIs provide hardening against a malicious `/proc` mount to either detect - or avoid being tricked by a `/proc` that is not legitimate. This is done - using [`openat2`][openat2.2] for all users, and privileged users will also be - further protected by using [`fsopen`][fsopen.2] and [`open_tree`][open_tree.2] - (Linux 5.2 or later). - -[openat2.2]: https://www.man7.org/linux/man-pages/man2/openat2.2.html -[fsopen.2]: https://github.com/brauner/man-pages-md/blob/main/fsopen.md -[open_tree.2]: https://github.com/brauner/man-pages-md/blob/main/open_tree.md - -#### `OpenInRoot` #### - -```go -func OpenInRoot(root, unsafePath string) (*os.File, error) -func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) -func Reopen(handle *os.File, flags int) (*os.File, error) -``` - -`OpenInRoot` is a much safer version of - -```go -path, err := securejoin.SecureJoin(root, unsafePath) -file, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC) -``` - -that protects against various race attacks that could lead to serious security -issues, depending on the application. Note that the returned `*os.File` is an -`O_PATH` file descriptor, which is quite restricted. Callers will probably need -to use `Reopen` to get a more usable handle (this split is done to provide -useful features like PTY spawning and to avoid users accidentally opening bad -inodes that could cause a DoS). - -Callers need to be careful in how they use the returned `*os.File`. Usually it -is only safe to operate on the handle directly, and it is very easy to create a -security issue. [libpathrs][libpathrs] provides far more helpers to make using -these handles safer -- there is currently no plan to port them to -`filepath-securejoin`. - -`OpenatInRoot` is like `OpenInRoot` except that the root is provided using an -`*os.File`. This allows you to ensure that multiple `OpenatInRoot` (or -`MkdirAllHandle`) calls are operating on the same rootfs. - -> **NOTE**: Unlike `SecureJoin`, `OpenInRoot` will error out as soon as it hits -> a dangling symlink or non-existent path. This is in contrast to `SecureJoin` -> which treated non-existent components as though they were real directories, -> and would allow for partial resolution of dangling symlinks. These behaviours -> are at odds with how Linux treats non-existent paths and dangling symlinks, -> and so these are no longer allowed. - -#### `MkdirAll` #### - -```go -func MkdirAll(root, unsafePath string, mode int) error -func MkdirAllHandle(root *os.File, unsafePath string, mode int) (*os.File, error) -``` - -`MkdirAll` is a much safer version of - -```go -path, err := securejoin.SecureJoin(root, unsafePath) -err = os.MkdirAll(path, mode) -``` - -that protects against the same kinds of races that `OpenInRoot` protects -against. - -`MkdirAllHandle` is like `MkdirAll` except that the root is provided using an -`*os.File` (the reason for this is the same as with `OpenatInRoot`) and an -`*os.File` of the final created directory is returned (this directory is -guaranteed to be effectively identical to the directory created by -`MkdirAllHandle`, which is not possible to ensure by just using `OpenatInRoot` -after `MkdirAll`). - -> **NOTE**: Unlike `SecureJoin`, `MkdirAll` will error out as soon as it hits -> a dangling symlink or non-existent path. This is in contrast to `SecureJoin` -> which treated non-existent components as though they were real directories, -> and would allow for partial resolution of dangling symlinks. These behaviours -> are at odds with how Linux treats non-existent paths and dangling symlinks, -> and so these are no longer allowed. This means that `MkdirAll` will not -> create non-existent directories referenced by a dangling symlink. - -### License ### - -The license of this project is the same as Go, which is a BSD 3-clause license -available in the `LICENSE` file. diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION deleted file mode 100644 index 267577d4..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.4.1 diff --git a/vendor/github.com/cyphar/filepath-securejoin/doc.go b/vendor/github.com/cyphar/filepath-securejoin/doc.go deleted file mode 100644 index 1ec7d065..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/doc.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. -// Copyright (C) 2017-2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package securejoin implements a set of helpers to make it easier to write Go -// code that is safe against symlink-related escape attacks. The primary idea -// is to let you resolve a path within a rootfs directory as if the rootfs was -// a chroot. -// -// securejoin has two APIs, a "legacy" API and a "modern" API. -// -// The legacy API is [SecureJoin] and [SecureJoinVFS]. These methods are -// **not** safe against race conditions where an attacker changes the -// filesystem after (or during) the [SecureJoin] operation. -// -// The new API is made up of [OpenInRoot] and [MkdirAll] (and derived -// functions). These are safe against racing attackers and have several other -// protections that are not provided by the legacy API. There are many more -// operations that most programs expect to be able to do safely, but we do not -// provide explicit support for them because we want to encourage users to -// switch to [libpathrs](https://github.com/openSUSE/libpathrs) which is a -// cross-language next-generation library that is entirely designed around -// operating on paths safely. -// -// securejoin has been used by several container runtimes (Docker, runc, -// Kubernetes, etc) for quite a few years as a de-facto standard for operating -// on container filesystem paths "safely". However, most users still use the -// legacy API which is unsafe against various attacks (there is a fairly long -// history of CVEs in dependent as a result). Users should switch to the modern -// API as soon as possible (or even better, switch to libpathrs). -// -// This project was initially intended to be included in the Go standard -// library, but [it was rejected](https://go.dev/issue/20126). There is now a -// [new Go proposal](https://go.dev/issue/67002) for a safe path resolution API -// that shares some of the goals of filepath-securejoin. However, that design -// is intended to work like `openat2(RESOLVE_BENEATH)` which does not fit the -// usecase of container runtimes and most system tools. -package securejoin diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go deleted file mode 100644 index 42452bbf..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build linux && go1.20 - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "fmt" -) - -// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except -// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap) -// is only guaranteed to give you baseErr. -func wrapBaseError(baseErr, extraErr error) error { - return fmt.Errorf("%w: %w", extraErr, baseErr) -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go deleted file mode 100644 index e7adca3f..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build linux && !go1.20 - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "fmt" -) - -type wrappedError struct { - inner error - isError error -} - -func (err wrappedError) Is(target error) bool { - return err.isError == target -} - -func (err wrappedError) Unwrap() error { - return err.inner -} - -func (err wrappedError) Error() string { - return fmt.Sprintf("%v: %v", err.isError, err.inner) -} - -// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except -// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap) -// is only guaranteed to give you baseErr. -func wrapBaseError(baseErr, extraErr error) error { - return wrappedError{ - inner: baseErr, - isError: extraErr, - } -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go deleted file mode 100644 index ddd6fa9a..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build linux && go1.21 - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "slices" - "sync" -) - -func slices_DeleteFunc[S ~[]E, E any](slice S, delFn func(E) bool) S { - return slices.DeleteFunc(slice, delFn) -} - -func slices_Contains[S ~[]E, E comparable](slice S, val E) bool { - return slices.Contains(slice, val) -} - -func slices_Clone[S ~[]E, E any](slice S) S { - return slices.Clone(slice) -} - -func sync_OnceValue[T any](f func() T) func() T { - return sync.OnceValue(f) -} - -func sync_OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) { - return sync.OnceValues(f) -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go b/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go deleted file mode 100644 index f1e6fe7e..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go +++ /dev/null @@ -1,124 +0,0 @@ -//go:build linux && !go1.21 - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "sync" -) - -// These are very minimal implementations of functions that appear in Go 1.21's -// stdlib, included so that we can build on older Go versions. Most are -// borrowed directly from the stdlib, and a few are modified to be "obviously -// correct" without needing to copy too many other helpers. - -// clearSlice is equivalent to the builtin clear from Go 1.21. -// Copied from the Go 1.24 stdlib implementation. -func clearSlice[S ~[]E, E any](slice S) { - var zero E - for i := range slice { - slice[i] = zero - } -} - -// Copied from the Go 1.24 stdlib implementation. -func slices_IndexFunc[S ~[]E, E any](s S, f func(E) bool) int { - for i := range s { - if f(s[i]) { - return i - } - } - return -1 -} - -// Copied from the Go 1.24 stdlib implementation. -func slices_DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S { - i := slices_IndexFunc(s, del) - if i == -1 { - return s - } - // Don't start copying elements until we find one to delete. - for j := i + 1; j < len(s); j++ { - if v := s[j]; !del(v) { - s[i] = v - i++ - } - } - clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC - return s[:i] -} - -// Similar to the stdlib slices.Contains, except that we don't have -// slices.Index so we need to use slices.IndexFunc for this non-Func helper. -func slices_Contains[S ~[]E, E comparable](s S, v E) bool { - return slices_IndexFunc(s, func(e E) bool { return e == v }) >= 0 -} - -// Copied from the Go 1.24 stdlib implementation. -func slices_Clone[S ~[]E, E any](s S) S { - // Preserve nil in case it matters. - if s == nil { - return nil - } - return append(S([]E{}), s...) -} - -// Copied from the Go 1.24 stdlib implementation. -func sync_OnceValue[T any](f func() T) func() T { - var ( - once sync.Once - valid bool - p any - result T - ) - g := func() { - defer func() { - p = recover() - if !valid { - panic(p) - } - }() - result = f() - f = nil - valid = true - } - return func() T { - once.Do(g) - if !valid { - panic(p) - } - return result - } -} - -// Copied from the Go 1.24 stdlib implementation. -func sync_OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) { - var ( - once sync.Once - valid bool - p any - r1 T1 - r2 T2 - ) - g := func() { - defer func() { - p = recover() - if !valid { - panic(p) - } - }() - r1, r2 = f() - f = nil - valid = true - } - return func() (T1, T2) { - once.Do(g) - if !valid { - panic(p) - } - return r1, r2 - } -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/join.go b/vendor/github.com/cyphar/filepath-securejoin/join.go deleted file mode 100644 index e6634d47..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/join.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. -// Copyright (C) 2017-2025 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "errors" - "os" - "path/filepath" - "strings" - "syscall" -) - -const maxSymlinkLimit = 255 - -// IsNotExist tells you if err is an error that implies that either the path -// accessed does not exist (or path components don't exist). This is -// effectively a more broad version of [os.IsNotExist]. -func IsNotExist(err error) bool { - // Check that it's not actually an ENOTDIR, which in some cases is a more - // convoluted case of ENOENT (usually involving weird paths). - return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT) -} - -// errUnsafeRoot is returned if the user provides SecureJoinVFS with a path -// that contains ".." components. -var errUnsafeRoot = errors.New("root path provided to SecureJoin contains '..' components") - -// stripVolume just gets rid of the Windows volume included in a path. Based on -// some godbolt tests, the Go compiler is smart enough to make this a no-op on -// Linux. -func stripVolume(path string) string { - return path[len(filepath.VolumeName(path)):] -} - -// hasDotDot checks if the path contains ".." components in a platform-agnostic -// way. -func hasDotDot(path string) bool { - // If we are on Windows, strip any volume letters. It turns out that - // C:..\foo may (or may not) be a valid pathname and we need to handle that - // leading "..". - path = stripVolume(path) - // Look for "/../" in the path, but we need to handle leading and trailing - // ".."s by adding separators. Doing this with filepath.Separator is ugly - // so just convert to Unix-style "/" first. - path = filepath.ToSlash(path) - return strings.Contains("/"+path+"/", "/../") -} - -// SecureJoinVFS joins the two given path components (similar to [filepath.Join]) except -// that the returned path is guaranteed to be scoped inside the provided root -// path (when evaluated). Any symbolic links in the path are evaluated with the -// given root treated as the root of the filesystem, similar to a chroot. The -// filesystem state is evaluated through the given [VFS] interface (if nil, the -// standard [os].* family of functions are used). -// -// Note that the guarantees provided by this function only apply if the path -// components in the returned string are not modified (in other words are not -// replaced with symlinks on the filesystem) after this function has returned. -// Such a symlink race is necessarily out-of-scope of SecureJoinVFS. -// -// NOTE: Due to the above limitation, Linux users are strongly encouraged to -// use [OpenInRoot] instead, which does safely protect against these kinds of -// attacks. There is no way to solve this problem with SecureJoinVFS because -// the API is fundamentally wrong (you cannot return a "safe" path string and -// guarantee it won't be modified afterwards). -// -// Volume names in unsafePath are always discarded, regardless if they are -// provided via direct input or when evaluating symlinks. Therefore: -// -// "C:\Temp" + "D:\path\to\file.txt" results in "C:\Temp\path\to\file.txt" -// -// If the provided root is not [filepath.Clean] then an error will be returned, -// as such root paths are bordering on somewhat unsafe and using such paths is -// not best practice. We also strongly suggest that any root path is first -// fully resolved using [filepath.EvalSymlinks] or otherwise constructed to -// avoid containing symlink components. Of course, the root also *must not* be -// attacker-controlled. -func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) { - // The root path must not contain ".." components, otherwise when we join - // the subpath we will end up with a weird path. We could work around this - // in other ways but users shouldn't be giving us non-lexical root paths in - // the first place. - if hasDotDot(root) { - return "", errUnsafeRoot - } - - // Use the os.* VFS implementation if none was specified. - if vfs == nil { - vfs = osVFS{} - } - - unsafePath = filepath.FromSlash(unsafePath) - var ( - currentPath string - remainingPath = unsafePath - linksWalked int - ) - for remainingPath != "" { - // On Windows, if we managed to end up at a path referencing a volume, - // drop the volume to make sure we don't end up with broken paths or - // escaping the root volume. - remainingPath = stripVolume(remainingPath) - - // Get the next path component. - var part string - if i := strings.IndexRune(remainingPath, filepath.Separator); i == -1 { - part, remainingPath = remainingPath, "" - } else { - part, remainingPath = remainingPath[:i], remainingPath[i+1:] - } - - // Apply the component lexically to the path we are building. - // currentPath does not contain any symlinks, and we are lexically - // dealing with a single component, so it's okay to do a filepath.Clean - // here. - nextPath := filepath.Join(string(filepath.Separator), currentPath, part) - if nextPath == string(filepath.Separator) { - currentPath = "" - continue - } - fullPath := root + string(filepath.Separator) + nextPath - - // Figure out whether the path is a symlink. - fi, err := vfs.Lstat(fullPath) - if err != nil && !IsNotExist(err) { - return "", err - } - // Treat non-existent path components the same as non-symlinks (we - // can't do any better here). - if IsNotExist(err) || fi.Mode()&os.ModeSymlink == 0 { - currentPath = nextPath - continue - } - - // It's a symlink, so get its contents and expand it by prepending it - // to the yet-unparsed path. - linksWalked++ - if linksWalked > maxSymlinkLimit { - return "", &os.PathError{Op: "SecureJoin", Path: root + string(filepath.Separator) + unsafePath, Err: syscall.ELOOP} - } - - dest, err := vfs.Readlink(fullPath) - if err != nil { - return "", err - } - remainingPath = dest + string(filepath.Separator) + remainingPath - // Absolute symlinks reset any work we've already done. - if filepath.IsAbs(dest) { - currentPath = "" - } - } - - // There should be no lexical components like ".." left in the path here, - // but for safety clean up the path before joining it to the root. - finalPath := filepath.Join(string(filepath.Separator), currentPath) - return filepath.Join(root, finalPath), nil -} - -// SecureJoin is a wrapper around [SecureJoinVFS] that just uses the [os].* library -// of functions as the [VFS]. If in doubt, use this function over [SecureJoinVFS]. -func SecureJoin(root, unsafePath string) (string, error) { - return SecureJoinVFS(root, unsafePath, nil) -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go b/vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go deleted file mode 100644 index be81e498..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go +++ /dev/null @@ -1,388 +0,0 @@ -//go:build linux - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "errors" - "fmt" - "os" - "path" - "path/filepath" - "strings" - - "golang.org/x/sys/unix" -) - -type symlinkStackEntry struct { - // (dir, remainingPath) is what we would've returned if the link didn't - // exist. This matches what openat2(RESOLVE_IN_ROOT) would return in - // this case. - dir *os.File - remainingPath string - // linkUnwalked is the remaining path components from the original - // Readlink which we have yet to walk. When this slice is empty, we - // drop the link from the stack. - linkUnwalked []string -} - -func (se symlinkStackEntry) String() string { - return fmt.Sprintf("<%s>/%s [->%s]", se.dir.Name(), se.remainingPath, strings.Join(se.linkUnwalked, "/")) -} - -func (se symlinkStackEntry) Close() { - _ = se.dir.Close() -} - -type symlinkStack []*symlinkStackEntry - -func (s *symlinkStack) IsEmpty() bool { - return s == nil || len(*s) == 0 -} - -func (s *symlinkStack) Close() { - if s != nil { - for _, link := range *s { - link.Close() - } - // TODO: Switch to clear once we switch to Go 1.21. - *s = nil - } -} - -var ( - errEmptyStack = errors.New("[internal] stack is empty") - errBrokenSymlinkStack = errors.New("[internal error] broken symlink stack") -) - -func (s *symlinkStack) popPart(part string) error { - if s == nil || s.IsEmpty() { - // If there is nothing in the symlink stack, then the part was from the - // real path provided by the user, and this is a no-op. - return errEmptyStack - } - if part == "." { - // "." components are no-ops -- we drop them when doing SwapLink. - return nil - } - - tailEntry := (*s)[len(*s)-1] - - // Double-check that we are popping the component we expect. - if len(tailEntry.linkUnwalked) == 0 { - return fmt.Errorf("%w: trying to pop component %q of empty stack entry %s", errBrokenSymlinkStack, part, tailEntry) - } - headPart := tailEntry.linkUnwalked[0] - if headPart != part { - return fmt.Errorf("%w: trying to pop component %q but the last stack entry is %s (%q)", errBrokenSymlinkStack, part, tailEntry, headPart) - } - - // Drop the component, but keep the entry around in case we are dealing - // with a "tail-chained" symlink. - tailEntry.linkUnwalked = tailEntry.linkUnwalked[1:] - return nil -} - -func (s *symlinkStack) PopPart(part string) error { - if err := s.popPart(part); err != nil { - if errors.Is(err, errEmptyStack) { - // Skip empty stacks. - err = nil - } - return err - } - - // Clean up any of the trailing stack entries that are empty. - for lastGood := len(*s) - 1; lastGood >= 0; lastGood-- { - entry := (*s)[lastGood] - if len(entry.linkUnwalked) > 0 { - break - } - entry.Close() - (*s) = (*s)[:lastGood] - } - return nil -} - -func (s *symlinkStack) push(dir *os.File, remainingPath, linkTarget string) error { - if s == nil { - return nil - } - // Split the link target and clean up any "" parts. - linkTargetParts := slices_DeleteFunc( - strings.Split(linkTarget, "/"), - func(part string) bool { return part == "" || part == "." }) - - // Copy the directory so the caller doesn't close our copy. - dirCopy, err := dupFile(dir) - if err != nil { - return err - } - - // Add to the stack. - *s = append(*s, &symlinkStackEntry{ - dir: dirCopy, - remainingPath: remainingPath, - linkUnwalked: linkTargetParts, - }) - return nil -} - -func (s *symlinkStack) SwapLink(linkPart string, dir *os.File, remainingPath, linkTarget string) error { - // If we are currently inside a symlink resolution, remove the symlink - // component from the last symlink entry, but don't remove the entry even - // if it's empty. If we are a "tail-chained" symlink (a trailing symlink we - // hit during a symlink resolution) we need to keep the old symlink until - // we finish the resolution. - if err := s.popPart(linkPart); err != nil { - if !errors.Is(err, errEmptyStack) { - return err - } - // Push the component regardless of whether the stack was empty. - } - return s.push(dir, remainingPath, linkTarget) -} - -func (s *symlinkStack) PopTopSymlink() (*os.File, string, bool) { - if s == nil || s.IsEmpty() { - return nil, "", false - } - tailEntry := (*s)[0] - *s = (*s)[1:] - return tailEntry.dir, tailEntry.remainingPath, true -} - -// partialLookupInRoot tries to lookup as much of the request path as possible -// within the provided root (a-la RESOLVE_IN_ROOT) and opens the final existing -// component of the requested path, returning a file handle to the final -// existing component and a string containing the remaining path components. -func partialLookupInRoot(root *os.File, unsafePath string) (*os.File, string, error) { - return lookupInRoot(root, unsafePath, true) -} - -func completeLookupInRoot(root *os.File, unsafePath string) (*os.File, error) { - handle, remainingPath, err := lookupInRoot(root, unsafePath, false) - if remainingPath != "" && err == nil { - // should never happen - err = fmt.Errorf("[bug] non-empty remaining path when doing a non-partial lookup: %q", remainingPath) - } - // lookupInRoot(partial=false) will always close the handle if an error is - // returned, so no need to double-check here. - return handle, err -} - -func lookupInRoot(root *os.File, unsafePath string, partial bool) (Handle *os.File, _ string, _ error) { - unsafePath = filepath.ToSlash(unsafePath) // noop - - // This is very similar to SecureJoin, except that we operate on the - // components using file descriptors. We then return the last component we - // managed open, along with the remaining path components not opened. - - // Try to use openat2 if possible. - if hasOpenat2() { - return lookupOpenat2(root, unsafePath, partial) - } - - // Get the "actual" root path from /proc/self/fd. This is necessary if the - // root is some magic-link like /proc/$pid/root, in which case we want to - // make sure when we do checkProcSelfFdPath that we are using the correct - // root path. - logicalRootPath, err := procSelfFdReadlink(root) - if err != nil { - return nil, "", fmt.Errorf("get real root path: %w", err) - } - - currentDir, err := dupFile(root) - if err != nil { - return nil, "", fmt.Errorf("clone root fd: %w", err) - } - defer func() { - // If a handle is not returned, close the internal handle. - if Handle == nil { - _ = currentDir.Close() - } - }() - - // symlinkStack is used to emulate how openat2(RESOLVE_IN_ROOT) treats - // dangling symlinks. If we hit a non-existent path while resolving a - // symlink, we need to return the (dir, remainingPath) that we had when we - // hit the symlink (treating the symlink as though it were a regular file). - // The set of (dir, remainingPath) sets is stored within the symlinkStack - // and we add and remove parts when we hit symlink and non-symlink - // components respectively. We need a stack because of recursive symlinks - // (symlinks that contain symlink components in their target). - // - // Note that the stack is ONLY used for book-keeping. All of the actual - // path walking logic is still based on currentPath/remainingPath and - // currentDir (as in SecureJoin). - var symStack *symlinkStack - if partial { - symStack = new(symlinkStack) - defer symStack.Close() - } - - var ( - linksWalked int - currentPath string - remainingPath = unsafePath - ) - for remainingPath != "" { - // Save the current remaining path so if the part is not real we can - // return the path including the component. - oldRemainingPath := remainingPath - - // Get the next path component. - var part string - if i := strings.IndexByte(remainingPath, '/'); i == -1 { - part, remainingPath = remainingPath, "" - } else { - part, remainingPath = remainingPath[:i], remainingPath[i+1:] - } - // If we hit an empty component, we need to treat it as though it is - // "." so that trailing "/" and "//" components on a non-directory - // correctly return the right error code. - if part == "" { - part = "." - } - - // Apply the component lexically to the path we are building. - // currentPath does not contain any symlinks, and we are lexically - // dealing with a single component, so it's okay to do a filepath.Clean - // here. - nextPath := path.Join("/", currentPath, part) - // If we logically hit the root, just clone the root rather than - // opening the part and doing all of the other checks. - if nextPath == "/" { - if err := symStack.PopPart(part); err != nil { - return nil, "", fmt.Errorf("walking into root with part %q failed: %w", part, err) - } - // Jump to root. - rootClone, err := dupFile(root) - if err != nil { - return nil, "", fmt.Errorf("clone root fd: %w", err) - } - _ = currentDir.Close() - currentDir = rootClone - currentPath = nextPath - continue - } - - // Try to open the next component. - nextDir, err := openatFile(currentDir, part, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) - switch { - case err == nil: - st, err := nextDir.Stat() - if err != nil { - _ = nextDir.Close() - return nil, "", fmt.Errorf("stat component %q: %w", part, err) - } - - switch st.Mode() & os.ModeType { - case os.ModeSymlink: - // readlinkat implies AT_EMPTY_PATH since Linux 2.6.39. See - // Linux commit 65cfc6722361 ("readlinkat(), fchownat() and - // fstatat() with empty relative pathnames"). - linkDest, err := readlinkatFile(nextDir, "") - // We don't need the handle anymore. - _ = nextDir.Close() - if err != nil { - return nil, "", err - } - - linksWalked++ - if linksWalked > maxSymlinkLimit { - return nil, "", &os.PathError{Op: "securejoin.lookupInRoot", Path: logicalRootPath + "/" + unsafePath, Err: unix.ELOOP} - } - - // Swap out the symlink's component for the link entry itself. - if err := symStack.SwapLink(part, currentDir, oldRemainingPath, linkDest); err != nil { - return nil, "", fmt.Errorf("walking into symlink %q failed: push symlink: %w", part, err) - } - - // Update our logical remaining path. - remainingPath = linkDest + "/" + remainingPath - // Absolute symlinks reset any work we've already done. - if path.IsAbs(linkDest) { - // Jump to root. - rootClone, err := dupFile(root) - if err != nil { - return nil, "", fmt.Errorf("clone root fd: %w", err) - } - _ = currentDir.Close() - currentDir = rootClone - currentPath = "/" - } - - default: - // If we are dealing with a directory, simply walk into it. - _ = currentDir.Close() - currentDir = nextDir - currentPath = nextPath - - // The part was real, so drop it from the symlink stack. - if err := symStack.PopPart(part); err != nil { - return nil, "", fmt.Errorf("walking into directory %q failed: %w", part, err) - } - - // If we are operating on a .., make sure we haven't escaped. - // We only have to check for ".." here because walking down - // into a regular component component cannot cause you to - // escape. This mirrors the logic in RESOLVE_IN_ROOT, except we - // have to check every ".." rather than only checking after a - // rename or mount on the system. - if part == ".." { - // Make sure the root hasn't moved. - if err := checkProcSelfFdPath(logicalRootPath, root); err != nil { - return nil, "", fmt.Errorf("root path moved during lookup: %w", err) - } - // Make sure the path is what we expect. - fullPath := logicalRootPath + nextPath - if err := checkProcSelfFdPath(fullPath, currentDir); err != nil { - return nil, "", fmt.Errorf("walking into %q had unexpected result: %w", part, err) - } - } - } - - default: - if !partial { - return nil, "", err - } - // If there are any remaining components in the symlink stack, we - // are still within a symlink resolution and thus we hit a dangling - // symlink. So pretend that the first symlink in the stack we hit - // was an ENOENT (to match openat2). - if oldDir, remainingPath, ok := symStack.PopTopSymlink(); ok { - _ = currentDir.Close() - return oldDir, remainingPath, err - } - // We have hit a final component that doesn't exist, so we have our - // partial open result. Note that we have to use the OLD remaining - // path, since the lookup failed. - return currentDir, oldRemainingPath, err - } - } - - // If the unsafePath had a trailing slash, we need to make sure we try to - // do a relative "." open so that we will correctly return an error when - // the final component is a non-directory (to match openat2). In the - // context of openat2, a trailing slash and a trailing "/." are completely - // equivalent. - if strings.HasSuffix(unsafePath, "/") { - nextDir, err := openatFile(currentDir, ".", unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) - if err != nil { - if !partial { - _ = currentDir.Close() - currentDir = nil - } - return currentDir, "", err - } - _ = currentDir.Close() - currentDir = nextDir - } - - // All of the components existed! - return currentDir, "", nil -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go b/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go deleted file mode 100644 index a17ae3b0..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go +++ /dev/null @@ -1,236 +0,0 @@ -//go:build linux - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "strings" - - "golang.org/x/sys/unix" -) - -var ( - errInvalidMode = errors.New("invalid permission mode") - errPossibleAttack = errors.New("possible attack detected") -) - -// modePermExt is like os.ModePerm except that it also includes the set[ug]id -// and sticky bits. -const modePermExt = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky - -//nolint:cyclop // this function needs to handle a lot of cases -func toUnixMode(mode os.FileMode) (uint32, error) { - sysMode := uint32(mode.Perm()) - if mode&os.ModeSetuid != 0 { - sysMode |= unix.S_ISUID - } - if mode&os.ModeSetgid != 0 { - sysMode |= unix.S_ISGID - } - if mode&os.ModeSticky != 0 { - sysMode |= unix.S_ISVTX - } - // We don't allow file type bits. - if mode&os.ModeType != 0 { - return 0, fmt.Errorf("%w %+.3o (%s): type bits not permitted", errInvalidMode, mode, mode) - } - // We don't allow other unknown modes. - if mode&^modePermExt != 0 || sysMode&unix.S_IFMT != 0 { - return 0, fmt.Errorf("%w %+.3o (%s): unknown mode bits", errInvalidMode, mode, mode) - } - return sysMode, nil -} - -// MkdirAllHandle is equivalent to [MkdirAll], except that it is safer to use -// in two respects: -// -// - The caller provides the root directory as an *[os.File] (preferably O_PATH) -// handle. This means that the caller can be sure which root directory is -// being used. Note that this can be emulated by using /proc/self/fd/... as -// the root path with [os.MkdirAll]. -// -// - Once all of the directories have been created, an *[os.File] O_PATH handle -// to the directory at unsafePath is returned to the caller. This is done in -// an effectively-race-free way (an attacker would only be able to swap the -// final directory component), which is not possible to emulate with -// [MkdirAll]. -// -// In addition, the returned handle is obtained far more efficiently than doing -// a brand new lookup of unsafePath (such as with [SecureJoin] or openat2) after -// doing [MkdirAll]. If you intend to open the directory after creating it, you -// should use MkdirAllHandle. -func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (_ *os.File, Err error) { - unixMode, err := toUnixMode(mode) - if err != nil { - return nil, err - } - // On Linux, mkdirat(2) (and os.Mkdir) silently ignore the suid and sgid - // bits. We could also silently ignore them but since we have very few - // users it seems more prudent to return an error so users notice that - // these bits will not be set. - if unixMode&^0o1777 != 0 { - return nil, fmt.Errorf("%w for mkdir %+.3o: suid and sgid are ignored by mkdir", errInvalidMode, mode) - } - - // Try to open as much of the path as possible. - currentDir, remainingPath, err := partialLookupInRoot(root, unsafePath) - defer func() { - if Err != nil { - _ = currentDir.Close() - } - }() - if err != nil && !errors.Is(err, unix.ENOENT) { - return nil, fmt.Errorf("find existing subpath of %q: %w", unsafePath, err) - } - - // If there is an attacker deleting directories as we walk into them, - // detect this proactively. Note this is guaranteed to detect if the - // attacker deleted any part of the tree up to currentDir. - // - // Once we walk into a dead directory, partialLookupInRoot would not be - // able to walk further down the tree (directories must be empty before - // they are deleted), and if the attacker has removed the entire tree we - // can be sure that anything that was originally inside a dead directory - // must also be deleted and thus is a dead directory in its own right. - // - // This is mostly a quality-of-life check, because mkdir will simply fail - // later if the attacker deletes the tree after this check. - if err := isDeadInode(currentDir); err != nil { - return nil, fmt.Errorf("finding existing subpath of %q: %w", unsafePath, err) - } - - // Re-open the path to match the O_DIRECTORY reopen loop later (so that we - // always return a non-O_PATH handle). We also check that we actually got a - // directory. - if reopenDir, err := Reopen(currentDir, unix.O_DIRECTORY|unix.O_CLOEXEC); errors.Is(err, unix.ENOTDIR) { - return nil, fmt.Errorf("cannot create subdirectories in %q: %w", currentDir.Name(), unix.ENOTDIR) - } else if err != nil { - return nil, fmt.Errorf("re-opening handle to %q: %w", currentDir.Name(), err) - } else { - _ = currentDir.Close() - currentDir = reopenDir - } - - remainingParts := strings.Split(remainingPath, string(filepath.Separator)) - if slices_Contains(remainingParts, "..") { - // The path contained ".." components after the end of the "real" - // components. We could try to safely resolve ".." here but that would - // add a bunch of extra logic for something that it's not clear even - // needs to be supported. So just return an error. - // - // If we do filepath.Clean(remainingPath) then we end up with the - // problem that ".." can erase a trailing dangling symlink and produce - // a path that doesn't quite match what the user asked for. - return nil, fmt.Errorf("%w: yet-to-be-created path %q contains '..' components", unix.ENOENT, remainingPath) - } - - // Create the remaining components. - for _, part := range remainingParts { - switch part { - case "", ".": - // Skip over no-op paths. - continue - } - - // NOTE: mkdir(2) will not follow trailing symlinks, so we can safely - // create the final component without worrying about symlink-exchange - // attacks. - // - // If we get -EEXIST, it's possible that another program created the - // directory at the same time as us. In that case, just continue on as - // if we created it (if the created inode is not a directory, the - // following open call will fail). - if err := unix.Mkdirat(int(currentDir.Fd()), part, unixMode); err != nil && !errors.Is(err, unix.EEXIST) { - err = &os.PathError{Op: "mkdirat", Path: currentDir.Name() + "/" + part, Err: err} - // Make the error a bit nicer if the directory is dead. - if deadErr := isDeadInode(currentDir); deadErr != nil { - // TODO: Once we bump the minimum Go version to 1.20, we can use - // multiple %w verbs for this wrapping. For now we need to use a - // compatibility shim for older Go versions. - //err = fmt.Errorf("%w (%w)", err, deadErr) - err = wrapBaseError(err, deadErr) - } - return nil, err - } - - // Get a handle to the next component. O_DIRECTORY means we don't need - // to use O_PATH. - var nextDir *os.File - if hasOpenat2() { - nextDir, err = openat2File(currentDir, part, &unix.OpenHow{ - Flags: unix.O_NOFOLLOW | unix.O_DIRECTORY | unix.O_CLOEXEC, - Resolve: unix.RESOLVE_BENEATH | unix.RESOLVE_NO_SYMLINKS | unix.RESOLVE_NO_XDEV, - }) - } else { - nextDir, err = openatFile(currentDir, part, unix.O_NOFOLLOW|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) - } - if err != nil { - return nil, err - } - _ = currentDir.Close() - currentDir = nextDir - - // It's possible that the directory we just opened was swapped by an - // attacker. Unfortunately there isn't much we can do to protect - // against this, and MkdirAll's behaviour is that we will reuse - // existing directories anyway so the need to protect against this is - // incredibly limited (and arguably doesn't even deserve mention here). - // - // Ideally we might want to check that the owner and mode match what we - // would've created -- unfortunately, it is non-trivial to verify that - // the owner and mode of the created directory match. While plain Unix - // DAC rules seem simple enough to emulate, there are a bunch of other - // factors that can change the mode or owner of created directories - // (default POSIX ACLs, mount options like uid=1,gid=2,umask=0 on - // filesystems like vfat, etc etc). We used to try to verify this but - // it just lead to a series of spurious errors. - // - // We could also check that the directory is non-empty, but - // unfortunately some pseduofilesystems (like cgroupfs) create - // non-empty directories, which would result in different spurious - // errors. - } - return currentDir, nil -} - -// MkdirAll is a race-safe alternative to the [os.MkdirAll] function, -// where the new directory is guaranteed to be within the root directory (if an -// attacker can move directories from inside the root to outside the root, the -// created directory tree might be outside of the root but the key constraint -// is that at no point will we walk outside of the directory tree we are -// creating). -// -// Effectively, MkdirAll(root, unsafePath, mode) is equivalent to -// -// path, _ := securejoin.SecureJoin(root, unsafePath) -// err := os.MkdirAll(path, mode) -// -// But is much safer. The above implementation is unsafe because if an attacker -// can modify the filesystem tree between [SecureJoin] and [os.MkdirAll], it is -// possible for MkdirAll to resolve unsafe symlink components and create -// directories outside of the root. -// -// If you plan to open the directory after you have created it or want to use -// an open directory handle as the root, you should use [MkdirAllHandle] instead. -// This function is a wrapper around [MkdirAllHandle]. -func MkdirAll(root, unsafePath string, mode os.FileMode) error { - rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) - if err != nil { - return err - } - defer rootDir.Close() - - f, err := MkdirAllHandle(rootDir, unsafePath, mode) - if err != nil { - return err - } - _ = f.Close() - return nil -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/open_linux.go b/vendor/github.com/cyphar/filepath-securejoin/open_linux.go deleted file mode 100644 index 230be73f..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/open_linux.go +++ /dev/null @@ -1,103 +0,0 @@ -//go:build linux - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "fmt" - "os" - "strconv" - - "golang.org/x/sys/unix" -) - -// OpenatInRoot is equivalent to [OpenInRoot], except that the root is provided -// using an *[os.File] handle, to ensure that the correct root directory is used. -func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) { - handle, err := completeLookupInRoot(root, unsafePath) - if err != nil { - return nil, &os.PathError{Op: "securejoin.OpenInRoot", Path: unsafePath, Err: err} - } - return handle, nil -} - -// OpenInRoot safely opens the provided unsafePath within the root. -// Effectively, OpenInRoot(root, unsafePath) is equivalent to -// -// path, _ := securejoin.SecureJoin(root, unsafePath) -// handle, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC) -// -// But is much safer. The above implementation is unsafe because if an attacker -// can modify the filesystem tree between [SecureJoin] and [os.OpenFile], it is -// possible for the returned file to be outside of the root. -// -// Note that the returned handle is an O_PATH handle, meaning that only a very -// limited set of operations will work on the handle. This is done to avoid -// accidentally opening an untrusted file that could cause issues (such as a -// disconnected TTY that could cause a DoS, or some other issue). In order to -// use the returned handle, you can "upgrade" it to a proper handle using -// [Reopen]. -func OpenInRoot(root, unsafePath string) (*os.File, error) { - rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) - if err != nil { - return nil, err - } - defer rootDir.Close() - return OpenatInRoot(rootDir, unsafePath) -} - -// Reopen takes an *[os.File] handle and re-opens it through /proc/self/fd. -// Reopen(file, flags) is effectively equivalent to -// -// fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd()) -// os.OpenFile(fdPath, flags|unix.O_CLOEXEC) -// -// But with some extra hardenings to ensure that we are not tricked by a -// maliciously-configured /proc mount. While this attack scenario is not -// common, in container runtimes it is possible for higher-level runtimes to be -// tricked into configuring an unsafe /proc that can be used to attack file -// operations. See [CVE-2019-19921] for more details. -// -// [CVE-2019-19921]: https://github.com/advisories/GHSA-fh74-hm69-rqjw -func Reopen(handle *os.File, flags int) (*os.File, error) { - procRoot, err := getProcRoot() - if err != nil { - return nil, err - } - - // We can't operate on /proc/thread-self/fd/$n directly when doing a - // re-open, so we need to open /proc/thread-self/fd and then open a single - // final component. - procFdDir, closer, err := procThreadSelf(procRoot, "fd/") - if err != nil { - return nil, fmt.Errorf("get safe /proc/thread-self/fd handle: %w", err) - } - defer procFdDir.Close() - defer closer() - - // Try to detect if there is a mount on top of the magic-link we are about - // to open. If we are using unsafeHostProcRoot(), this could change after - // we check it (and there's nothing we can do about that) but for - // privateProcRoot() this should be guaranteed to be safe (at least since - // Linux 5.12[1], when anonymous mount namespaces were completely isolated - // from external mounts including mount propagation events). - // - // [1]: Linux commit ee2e3f50629f ("mount: fix mounting of detached mounts - // onto targets that reside on shared mounts"). - fdStr := strconv.Itoa(int(handle.Fd())) - if err := checkSymlinkOvermount(procRoot, procFdDir, fdStr); err != nil { - return nil, fmt.Errorf("check safety of /proc/thread-self/fd/%s magiclink: %w", fdStr, err) - } - - flags |= unix.O_CLOEXEC - // Rather than just wrapping openatFile, open-code it so we can copy - // handle.Name(). - reopenFd, err := unix.Openat(int(procFdDir.Fd()), fdStr, flags, 0) - if err != nil { - return nil, fmt.Errorf("reopen fd %d: %w", handle.Fd(), err) - } - return os.NewFile(uintptr(reopenFd), handle.Name()), nil -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go b/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go deleted file mode 100644 index f7a13e69..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build linux - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "strings" - - "golang.org/x/sys/unix" -) - -var hasOpenat2 = sync_OnceValue(func() bool { - fd, err := unix.Openat2(unix.AT_FDCWD, ".", &unix.OpenHow{ - Flags: unix.O_PATH | unix.O_CLOEXEC, - Resolve: unix.RESOLVE_NO_SYMLINKS | unix.RESOLVE_IN_ROOT, - }) - if err != nil { - return false - } - _ = unix.Close(fd) - return true -}) - -func scopedLookupShouldRetry(how *unix.OpenHow, err error) bool { - // RESOLVE_IN_ROOT (and RESOLVE_BENEATH) can return -EAGAIN if we resolve - // ".." while a mount or rename occurs anywhere on the system. This could - // happen spuriously, or as the result of an attacker trying to mess with - // us during lookup. - // - // In addition, scoped lookups have a "safety check" at the end of - // complete_walk which will return -EXDEV if the final path is not in the - // root. - return how.Resolve&(unix.RESOLVE_IN_ROOT|unix.RESOLVE_BENEATH) != 0 && - (errors.Is(err, unix.EAGAIN) || errors.Is(err, unix.EXDEV)) -} - -const scopedLookupMaxRetries = 10 - -func openat2File(dir *os.File, path string, how *unix.OpenHow) (*os.File, error) { - fullPath := dir.Name() + "/" + path - // Make sure we always set O_CLOEXEC. - how.Flags |= unix.O_CLOEXEC - var tries int - for tries < scopedLookupMaxRetries { - fd, err := unix.Openat2(int(dir.Fd()), path, how) - if err != nil { - if scopedLookupShouldRetry(how, err) { - // We retry a couple of times to avoid the spurious errors, and - // if we are being attacked then returning -EAGAIN is the best - // we can do. - tries++ - continue - } - return nil, &os.PathError{Op: "openat2", Path: fullPath, Err: err} - } - // If we are using RESOLVE_IN_ROOT, the name we generated may be wrong. - // NOTE: The procRoot code MUST NOT use RESOLVE_IN_ROOT, otherwise - // you'll get infinite recursion here. - if how.Resolve&unix.RESOLVE_IN_ROOT == unix.RESOLVE_IN_ROOT { - if actualPath, err := rawProcSelfFdReadlink(fd); err == nil { - fullPath = actualPath - } - } - return os.NewFile(uintptr(fd), fullPath), nil - } - return nil, &os.PathError{Op: "openat2", Path: fullPath, Err: errPossibleAttack} -} - -func lookupOpenat2(root *os.File, unsafePath string, partial bool) (*os.File, string, error) { - if !partial { - file, err := openat2File(root, unsafePath, &unix.OpenHow{ - Flags: unix.O_PATH | unix.O_CLOEXEC, - Resolve: unix.RESOLVE_IN_ROOT | unix.RESOLVE_NO_MAGICLINKS, - }) - return file, "", err - } - return partialLookupOpenat2(root, unsafePath) -} - -// partialLookupOpenat2 is an alternative implementation of -// partialLookupInRoot, using openat2(RESOLVE_IN_ROOT) to more safely get a -// handle to the deepest existing child of the requested path within the root. -func partialLookupOpenat2(root *os.File, unsafePath string) (*os.File, string, error) { - // TODO: Implement this as a git-bisect-like binary search. - - unsafePath = filepath.ToSlash(unsafePath) // noop - endIdx := len(unsafePath) - var lastError error - for endIdx > 0 { - subpath := unsafePath[:endIdx] - - handle, err := openat2File(root, subpath, &unix.OpenHow{ - Flags: unix.O_PATH | unix.O_CLOEXEC, - Resolve: unix.RESOLVE_IN_ROOT | unix.RESOLVE_NO_MAGICLINKS, - }) - if err == nil { - // Jump over the slash if we have a non-"" remainingPath. - if endIdx < len(unsafePath) { - endIdx += 1 - } - // We found a subpath! - return handle, unsafePath[endIdx:], lastError - } - if errors.Is(err, unix.ENOENT) || errors.Is(err, unix.ENOTDIR) { - // That path doesn't exist, let's try the next directory up. - endIdx = strings.LastIndexByte(subpath, '/') - lastError = err - continue - } - return nil, "", fmt.Errorf("open subpath: %w", err) - } - // If we couldn't open anything, the whole subpath is missing. Return a - // copy of the root fd so that the caller doesn't close this one by - // accident. - rootClone, err := dupFile(root) - if err != nil { - return nil, "", err - } - return rootClone, unsafePath, lastError -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/openat_linux.go b/vendor/github.com/cyphar/filepath-securejoin/openat_linux.go deleted file mode 100644 index 949fb5f2..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/openat_linux.go +++ /dev/null @@ -1,59 +0,0 @@ -//go:build linux - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "os" - "path/filepath" - - "golang.org/x/sys/unix" -) - -func dupFile(f *os.File) (*os.File, error) { - fd, err := unix.FcntlInt(f.Fd(), unix.F_DUPFD_CLOEXEC, 0) - if err != nil { - return nil, os.NewSyscallError("fcntl(F_DUPFD_CLOEXEC)", err) - } - return os.NewFile(uintptr(fd), f.Name()), nil -} - -func openatFile(dir *os.File, path string, flags int, mode int) (*os.File, error) { - // Make sure we always set O_CLOEXEC. - flags |= unix.O_CLOEXEC - fd, err := unix.Openat(int(dir.Fd()), path, flags, uint32(mode)) - if err != nil { - return nil, &os.PathError{Op: "openat", Path: dir.Name() + "/" + path, Err: err} - } - // All of the paths we use with openatFile(2) are guaranteed to be - // lexically safe, so we can use path.Join here. - fullPath := filepath.Join(dir.Name(), path) - return os.NewFile(uintptr(fd), fullPath), nil -} - -func fstatatFile(dir *os.File, path string, flags int) (unix.Stat_t, error) { - var stat unix.Stat_t - if err := unix.Fstatat(int(dir.Fd()), path, &stat, flags); err != nil { - return stat, &os.PathError{Op: "fstatat", Path: dir.Name() + "/" + path, Err: err} - } - return stat, nil -} - -func readlinkatFile(dir *os.File, path string) (string, error) { - size := 4096 - for { - linkBuf := make([]byte, size) - n, err := unix.Readlinkat(int(dir.Fd()), path, linkBuf) - if err != nil { - return "", &os.PathError{Op: "readlinkat", Path: dir.Name() + "/" + path, Err: err} - } - if n != size { - return string(linkBuf[:n]), nil - } - // Possible truncation, resize the buffer. - size *= 2 - } -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go b/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go deleted file mode 100644 index 809a579c..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go +++ /dev/null @@ -1,452 +0,0 @@ -//go:build linux - -// Copyright (C) 2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import ( - "errors" - "fmt" - "os" - "runtime" - "strconv" - - "golang.org/x/sys/unix" -) - -func fstat(f *os.File) (unix.Stat_t, error) { - var stat unix.Stat_t - if err := unix.Fstat(int(f.Fd()), &stat); err != nil { - return stat, &os.PathError{Op: "fstat", Path: f.Name(), Err: err} - } - return stat, nil -} - -func fstatfs(f *os.File) (unix.Statfs_t, error) { - var statfs unix.Statfs_t - if err := unix.Fstatfs(int(f.Fd()), &statfs); err != nil { - return statfs, &os.PathError{Op: "fstatfs", Path: f.Name(), Err: err} - } - return statfs, nil -} - -// The kernel guarantees that the root inode of a procfs mount has an -// f_type of PROC_SUPER_MAGIC and st_ino of PROC_ROOT_INO. -const ( - procSuperMagic = 0x9fa0 // PROC_SUPER_MAGIC - procRootIno = 1 // PROC_ROOT_INO -) - -func verifyProcRoot(procRoot *os.File) error { - if statfs, err := fstatfs(procRoot); err != nil { - return err - } else if statfs.Type != procSuperMagic { - return fmt.Errorf("%w: incorrect procfs root filesystem type 0x%x", errUnsafeProcfs, statfs.Type) - } - if stat, err := fstat(procRoot); err != nil { - return err - } else if stat.Ino != procRootIno { - return fmt.Errorf("%w: incorrect procfs root inode number %d", errUnsafeProcfs, stat.Ino) - } - return nil -} - -var hasNewMountApi = sync_OnceValue(func() bool { - // All of the pieces of the new mount API we use (fsopen, fsconfig, - // fsmount, open_tree) were added together in Linux 5.1[1,2], so we can - // just check for one of the syscalls and the others should also be - // available. - // - // Just try to use open_tree(2) to open a file without OPEN_TREE_CLONE. - // This is equivalent to openat(2), but tells us if open_tree is - // available (and thus all of the other basic new mount API syscalls). - // open_tree(2) is most light-weight syscall to test here. - // - // [1]: merge commit 400913252d09 - // [2]: - fd, err := unix.OpenTree(-int(unix.EBADF), "/", unix.OPEN_TREE_CLOEXEC) - if err != nil { - return false - } - _ = unix.Close(fd) - return true -}) - -func fsopen(fsName string, flags int) (*os.File, error) { - // Make sure we always set O_CLOEXEC. - flags |= unix.FSOPEN_CLOEXEC - fd, err := unix.Fsopen(fsName, flags) - if err != nil { - return nil, os.NewSyscallError("fsopen "+fsName, err) - } - return os.NewFile(uintptr(fd), "fscontext:"+fsName), nil -} - -func fsmount(ctx *os.File, flags, mountAttrs int) (*os.File, error) { - // Make sure we always set O_CLOEXEC. - flags |= unix.FSMOUNT_CLOEXEC - fd, err := unix.Fsmount(int(ctx.Fd()), flags, mountAttrs) - if err != nil { - return nil, os.NewSyscallError("fsmount "+ctx.Name(), err) - } - return os.NewFile(uintptr(fd), "fsmount:"+ctx.Name()), nil -} - -func newPrivateProcMount() (*os.File, error) { - procfsCtx, err := fsopen("proc", unix.FSOPEN_CLOEXEC) - if err != nil { - return nil, err - } - defer procfsCtx.Close() - - // Try to configure hidepid=ptraceable,subset=pid if possible, but ignore errors. - _ = unix.FsconfigSetString(int(procfsCtx.Fd()), "hidepid", "ptraceable") - _ = unix.FsconfigSetString(int(procfsCtx.Fd()), "subset", "pid") - - // Get an actual handle. - if err := unix.FsconfigCreate(int(procfsCtx.Fd())); err != nil { - return nil, os.NewSyscallError("fsconfig create procfs", err) - } - return fsmount(procfsCtx, unix.FSMOUNT_CLOEXEC, unix.MS_RDONLY|unix.MS_NODEV|unix.MS_NOEXEC|unix.MS_NOSUID) -} - -func openTree(dir *os.File, path string, flags uint) (*os.File, error) { - dirFd := -int(unix.EBADF) - dirName := "." - if dir != nil { - dirFd = int(dir.Fd()) - dirName = dir.Name() - } - // Make sure we always set O_CLOEXEC. - flags |= unix.OPEN_TREE_CLOEXEC - fd, err := unix.OpenTree(dirFd, path, flags) - if err != nil { - return nil, &os.PathError{Op: "open_tree", Path: path, Err: err} - } - return os.NewFile(uintptr(fd), dirName+"/"+path), nil -} - -func clonePrivateProcMount() (_ *os.File, Err error) { - // Try to make a clone without using AT_RECURSIVE if we can. If this works, - // we can be sure there are no over-mounts and so if the root is valid then - // we're golden. Otherwise, we have to deal with over-mounts. - procfsHandle, err := openTree(nil, "/proc", unix.OPEN_TREE_CLONE) - if err != nil || hookForcePrivateProcRootOpenTreeAtRecursive(procfsHandle) { - procfsHandle, err = openTree(nil, "/proc", unix.OPEN_TREE_CLONE|unix.AT_RECURSIVE) - } - if err != nil { - return nil, fmt.Errorf("creating a detached procfs clone: %w", err) - } - defer func() { - if Err != nil { - _ = procfsHandle.Close() - } - }() - if err := verifyProcRoot(procfsHandle); err != nil { - return nil, err - } - return procfsHandle, nil -} - -func privateProcRoot() (*os.File, error) { - if !hasNewMountApi() || hookForceGetProcRootUnsafe() { - return nil, fmt.Errorf("new mount api: %w", unix.ENOTSUP) - } - // Try to create a new procfs mount from scratch if we can. This ensures we - // can get a procfs mount even if /proc is fake (for whatever reason). - procRoot, err := newPrivateProcMount() - if err != nil || hookForcePrivateProcRootOpenTree(procRoot) { - // Try to clone /proc then... - procRoot, err = clonePrivateProcMount() - } - return procRoot, err -} - -func unsafeHostProcRoot() (_ *os.File, Err error) { - procRoot, err := os.OpenFile("/proc", unix.O_PATH|unix.O_NOFOLLOW|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) - if err != nil { - return nil, err - } - defer func() { - if Err != nil { - _ = procRoot.Close() - } - }() - if err := verifyProcRoot(procRoot); err != nil { - return nil, err - } - return procRoot, nil -} - -func doGetProcRoot() (*os.File, error) { - procRoot, err := privateProcRoot() - if err != nil { - // Fall back to using a /proc handle if making a private mount failed. - // If we have openat2, at least we can avoid some kinds of over-mount - // attacks, but without openat2 there's not much we can do. - procRoot, err = unsafeHostProcRoot() - } - return procRoot, err -} - -var getProcRoot = sync_OnceValues(func() (*os.File, error) { - return doGetProcRoot() -}) - -var hasProcThreadSelf = sync_OnceValue(func() bool { - return unix.Access("/proc/thread-self/", unix.F_OK) == nil -}) - -var errUnsafeProcfs = errors.New("unsafe procfs detected") - -type procThreadSelfCloser func() - -// procThreadSelf returns a handle to /proc/thread-self/ (or an -// equivalent handle on older kernels where /proc/thread-self doesn't exist). -// Once finished with the handle, you must call the returned closer function -// (runtime.UnlockOSThread). You must not pass the returned *os.File to other -// Go threads or use the handle after calling the closer. -// -// This is similar to ProcThreadSelf from runc, but with extra hardening -// applied and using *os.File. -func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThreadSelfCloser, Err error) { - // We need to lock our thread until the caller is done with the handle - // because between getting the handle and using it we could get interrupted - // by the Go runtime and hit the case where the underlying thread is - // swapped out and the original thread is killed, resulting in - // pull-your-hair-out-hard-to-debug issues in the caller. - runtime.LockOSThread() - defer func() { - if Err != nil { - runtime.UnlockOSThread() - } - }() - - // Figure out what prefix we want to use. - threadSelf := "thread-self/" - if !hasProcThreadSelf() || hookForceProcSelfTask() { - /// Pre-3.17 kernels don't have /proc/thread-self, so do it manually. - threadSelf = "self/task/" + strconv.Itoa(unix.Gettid()) + "/" - if _, err := fstatatFile(procRoot, threadSelf, unix.AT_SYMLINK_NOFOLLOW); err != nil || hookForceProcSelf() { - // In this case, we running in a pid namespace that doesn't match - // the /proc mount we have. This can happen inside runc. - // - // Unfortunately, there is no nice way to get the correct TID to - // use here because of the age of the kernel, so we have to just - // use /proc/self and hope that it works. - threadSelf = "self/" - } - } - - // Grab the handle. - var ( - handle *os.File - err error - ) - if hasOpenat2() { - // We prefer being able to use RESOLVE_NO_XDEV if we can, to be - // absolutely sure we are operating on a clean /proc handle that - // doesn't have any cheeky overmounts that could trick us (including - // symlink mounts on top of /proc/thread-self). RESOLVE_BENEATH isn't - // strictly needed, but just use it since we have it. - // - // NOTE: /proc/self is technically a magic-link (the contents of the - // symlink are generated dynamically), but it doesn't use - // nd_jump_link() so RESOLVE_NO_MAGICLINKS allows it. - // - // NOTE: We MUST NOT use RESOLVE_IN_ROOT here, as openat2File uses - // procSelfFdReadlink to clean up the returned f.Name() if we use - // RESOLVE_IN_ROOT (which would lead to an infinite recursion). - handle, err = openat2File(procRoot, threadSelf+subpath, &unix.OpenHow{ - Flags: unix.O_PATH | unix.O_NOFOLLOW | unix.O_CLOEXEC, - Resolve: unix.RESOLVE_BENEATH | unix.RESOLVE_NO_XDEV | unix.RESOLVE_NO_MAGICLINKS, - }) - if err != nil { - // TODO: Once we bump the minimum Go version to 1.20, we can use - // multiple %w verbs for this wrapping. For now we need to use a - // compatibility shim for older Go versions. - //err = fmt.Errorf("%w: %w", errUnsafeProcfs, err) - return nil, nil, wrapBaseError(err, errUnsafeProcfs) - } - } else { - handle, err = openatFile(procRoot, threadSelf+subpath, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0) - if err != nil { - // TODO: Once we bump the minimum Go version to 1.20, we can use - // multiple %w verbs for this wrapping. For now we need to use a - // compatibility shim for older Go versions. - //err = fmt.Errorf("%w: %w", errUnsafeProcfs, err) - return nil, nil, wrapBaseError(err, errUnsafeProcfs) - } - defer func() { - if Err != nil { - _ = handle.Close() - } - }() - // We can't detect bind-mounts of different parts of procfs on top of - // /proc (a-la RESOLVE_NO_XDEV), but we can at least be sure that we - // aren't on the wrong filesystem here. - if statfs, err := fstatfs(handle); err != nil { - return nil, nil, err - } else if statfs.Type != procSuperMagic { - return nil, nil, fmt.Errorf("%w: incorrect /proc/self/fd filesystem type 0x%x", errUnsafeProcfs, statfs.Type) - } - } - return handle, runtime.UnlockOSThread, nil -} - -// STATX_MNT_ID_UNIQUE is provided in golang.org/x/sys@v0.20.0, but in order to -// avoid bumping the requirement for a single constant we can just define it -// ourselves. -const STATX_MNT_ID_UNIQUE = 0x4000 - -var hasStatxMountId = sync_OnceValue(func() bool { - var ( - stx unix.Statx_t - // We don't care which mount ID we get. The kernel will give us the - // unique one if it is supported. - wantStxMask uint32 = STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID - ) - err := unix.Statx(-int(unix.EBADF), "/", 0, int(wantStxMask), &stx) - return err == nil && stx.Mask&wantStxMask != 0 -}) - -func getMountId(dir *os.File, path string) (uint64, error) { - // If we don't have statx(STATX_MNT_ID*) support, we can't do anything. - if !hasStatxMountId() { - return 0, nil - } - - var ( - stx unix.Statx_t - // We don't care which mount ID we get. The kernel will give us the - // unique one if it is supported. - wantStxMask uint32 = STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID - ) - - err := unix.Statx(int(dir.Fd()), path, unix.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW, int(wantStxMask), &stx) - if stx.Mask&wantStxMask == 0 { - // It's not a kernel limitation, for some reason we couldn't get a - // mount ID. Assume it's some kind of attack. - err = fmt.Errorf("%w: could not get mount id", errUnsafeProcfs) - } - if err != nil { - return 0, &os.PathError{Op: "statx(STATX_MNT_ID_...)", Path: dir.Name() + "/" + path, Err: err} - } - return stx.Mnt_id, nil -} - -func checkSymlinkOvermount(procRoot *os.File, dir *os.File, path string) error { - // Get the mntId of our procfs handle. - expectedMountId, err := getMountId(procRoot, "") - if err != nil { - return err - } - // Get the mntId of the target magic-link. - gotMountId, err := getMountId(dir, path) - if err != nil { - return err - } - // As long as the directory mount is alive, even with wrapping mount IDs, - // we would expect to see a different mount ID here. (Of course, if we're - // using unsafeHostProcRoot() then an attaker could change this after we - // did this check.) - if expectedMountId != gotMountId { - return fmt.Errorf("%w: symlink %s/%s has an overmount obscuring the real link (mount ids do not match %d != %d)", errUnsafeProcfs, dir.Name(), path, expectedMountId, gotMountId) - } - return nil -} - -func doRawProcSelfFdReadlink(procRoot *os.File, fd int) (string, error) { - fdPath := fmt.Sprintf("fd/%d", fd) - procFdLink, closer, err := procThreadSelf(procRoot, fdPath) - if err != nil { - return "", fmt.Errorf("get safe /proc/thread-self/%s handle: %w", fdPath, err) - } - defer procFdLink.Close() - defer closer() - - // Try to detect if there is a mount on top of the magic-link. Since we use the handle directly - // provide to the closure. If the closure uses the handle directly, this - // should be safe in general (a mount on top of the path afterwards would - // not affect the handle itself) and will definitely be safe if we are - // using privateProcRoot() (at least since Linux 5.12[1], when anonymous - // mount namespaces were completely isolated from external mounts including - // mount propagation events). - // - // [1]: Linux commit ee2e3f50629f ("mount: fix mounting of detached mounts - // onto targets that reside on shared mounts"). - if err := checkSymlinkOvermount(procRoot, procFdLink, ""); err != nil { - return "", fmt.Errorf("check safety of /proc/thread-self/fd/%d magiclink: %w", fd, err) - } - - // readlinkat implies AT_EMPTY_PATH since Linux 2.6.39. See Linux commit - // 65cfc6722361 ("readlinkat(), fchownat() and fstatat() with empty - // relative pathnames"). - return readlinkatFile(procFdLink, "") -} - -func rawProcSelfFdReadlink(fd int) (string, error) { - procRoot, err := getProcRoot() - if err != nil { - return "", err - } - return doRawProcSelfFdReadlink(procRoot, fd) -} - -func procSelfFdReadlink(f *os.File) (string, error) { - return rawProcSelfFdReadlink(int(f.Fd())) -} - -var ( - errPossibleBreakout = errors.New("possible breakout detected") - errInvalidDirectory = errors.New("wandered into deleted directory") - errDeletedInode = errors.New("cannot verify path of deleted inode") -) - -func isDeadInode(file *os.File) error { - // If the nlink of a file drops to 0, there is an attacker deleting - // directories during our walk, which could result in weird /proc values. - // It's better to error out in this case. - stat, err := fstat(file) - if err != nil { - return fmt.Errorf("check for dead inode: %w", err) - } - if stat.Nlink == 0 { - err := errDeletedInode - if stat.Mode&unix.S_IFMT == unix.S_IFDIR { - err = errInvalidDirectory - } - return fmt.Errorf("%w %q", err, file.Name()) - } - return nil -} - -func checkProcSelfFdPath(path string, file *os.File) error { - if err := isDeadInode(file); err != nil { - return err - } - actualPath, err := procSelfFdReadlink(file) - if err != nil { - return fmt.Errorf("get path of handle: %w", err) - } - if actualPath != path { - return fmt.Errorf("%w: handle path %q doesn't match expected path %q", errPossibleBreakout, actualPath, path) - } - return nil -} - -// Test hooks used in the procfs tests to verify that the fallback logic works. -// See testing_mocks_linux_test.go and procfs_linux_test.go for more details. -var ( - hookForcePrivateProcRootOpenTree = hookDummyFile - hookForcePrivateProcRootOpenTreeAtRecursive = hookDummyFile - hookForceGetProcRootUnsafe = hookDummy - - hookForceProcSelfTask = hookDummy - hookForceProcSelf = hookDummy -) - -func hookDummy() bool { return false } -func hookDummyFile(_ *os.File) bool { return false } diff --git a/vendor/github.com/cyphar/filepath-securejoin/vfs.go b/vendor/github.com/cyphar/filepath-securejoin/vfs.go deleted file mode 100644 index 36373f8c..00000000 --- a/vendor/github.com/cyphar/filepath-securejoin/vfs.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2017-2024 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package securejoin - -import "os" - -// In future this should be moved into a separate package, because now there -// are several projects (umoci and go-mtree) that are using this sort of -// interface. - -// VFS is the minimal interface necessary to use [SecureJoinVFS]. A nil VFS is -// equivalent to using the standard [os].* family of functions. This is mainly -// used for the purposes of mock testing, but also can be used to otherwise use -// [SecureJoinVFS] with VFS-like system. -type VFS interface { - // Lstat returns an [os.FileInfo] describing the named file. If the - // file is a symbolic link, the returned [os.FileInfo] describes the - // symbolic link. Lstat makes no attempt to follow the link. - // The semantics are identical to [os.Lstat]. - Lstat(name string) (os.FileInfo, error) - - // Readlink returns the destination of the named symbolic link. - // The semantics are identical to [os.Readlink]. - Readlink(name string) (string, error) -} - -// osVFS is the "nil" VFS, in that it just passes everything through to the os -// module. -type osVFS struct{} - -func (o osVFS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } - -func (o osVFS) Readlink(name string) (string, error) { return os.Readlink(name) } diff --git a/vendor/github.com/dennwc/varint/.gitignore b/vendor/github.com/dennwc/varint/.gitignore deleted file mode 100644 index 9385b6db..00000000 --- a/vendor/github.com/dennwc/varint/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.o -*.txt \ No newline at end of file diff --git a/vendor/github.com/dennwc/varint/.travis.yml b/vendor/github.com/dennwc/varint/.travis.yml deleted file mode 100644 index b3da258f..00000000 --- a/vendor/github.com/dennwc/varint/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go - -go: - - 1.12.x - -env: - - GO111MODULE=on \ No newline at end of file diff --git a/vendor/github.com/dennwc/varint/LICENSE b/vendor/github.com/dennwc/varint/LICENSE deleted file mode 100644 index 8b3f6871..00000000 --- a/vendor/github.com/dennwc/varint/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Denys Smirnov - -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/dennwc/varint/README.md b/vendor/github.com/dennwc/varint/README.md deleted file mode 100644 index fe15b3b5..00000000 --- a/vendor/github.com/dennwc/varint/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# varint - -This package provides an optimized implementation of protobuf's varint encoding/decoding. -It has no dependencies. - -Benchmarks comparing to a `binary.Uvarint`: - -``` -benchmark old ns/op new ns/op delta -BenchmarkUvarint/1-8 4.13 2.85 -30.99% -BenchmarkUvarint/1_large-8 4.01 2.28 -43.14% -BenchmarkUvarint/2-8 6.23 2.87 -53.93% -BenchmarkUvarint/2_large-8 5.60 2.86 -48.93% -BenchmarkUvarint/3-8 6.55 3.44 -47.48% -BenchmarkUvarint/3_large-8 6.54 2.86 -56.27% -BenchmarkUvarint/4-8 7.30 3.71 -49.18% -BenchmarkUvarint/4_large-8 7.46 3.10 -58.45% -BenchmarkUvarint/5-8 8.31 4.12 -50.42% -BenchmarkUvarint/5_large-8 8.56 3.48 -59.35% -BenchmarkUvarint/6-8 9.42 4.66 -50.53% -BenchmarkUvarint/6_large-8 9.91 4.07 -58.93% -BenchmarkUvarint/7-8 10.6 5.28 -50.19% -BenchmarkUvarint/7_large-8 11.0 4.70 -57.27% -BenchmarkUvarint/8-8 11.7 6.02 -48.55% -BenchmarkUvarint/8_large-8 12.1 5.19 -57.11% -BenchmarkUvarint/9-8 12.9 6.83 -47.05% -BenchmarkUvarint/9_large-8 13.1 5.71 -56.41% -``` - -It also provides additional functionality like `UvarintSize` (similar to `sov*` in `gogo/protobuf`): - -``` -benchmark old ns/op new ns/op delta -BenchmarkUvarintSize/1-8 1.71 0.43 -74.85% -BenchmarkUvarintSize/2-8 2.56 0.57 -77.73% -BenchmarkUvarintSize/3-8 3.22 0.72 -77.64% -BenchmarkUvarintSize/4-8 3.74 0.72 -80.75% -BenchmarkUvarintSize/5-8 4.29 0.57 -86.71% -BenchmarkUvarintSize/6-8 4.85 0.58 -88.04% -BenchmarkUvarintSize/7-8 5.43 0.71 -86.92% -BenchmarkUvarintSize/8-8 6.01 0.86 -85.69% -BenchmarkUvarintSize/9-8 6.64 1.00 -84.94% -``` - -# License - -MIT \ No newline at end of file diff --git a/vendor/github.com/dennwc/varint/proto.go b/vendor/github.com/dennwc/varint/proto.go deleted file mode 100644 index e3b45854..00000000 --- a/vendor/github.com/dennwc/varint/proto.go +++ /dev/null @@ -1,244 +0,0 @@ -package varint - -// ProtoTag decodes a protobuf's field number and wire type pair -// from buf and returns that value and the number of bytes read (> 0). -// If an error occurred, n = 0 is returned. -func ProtoTag(buf []byte) (num int, typ byte, n int) { - // Same unrolled implementation as in Uvarint. - // - // But this time we can check if the wire type and field num - // are valid when reading the first byte. - // - // Also, the swifts are now different, because first 3 bits - // are for the wire type. - // - // The implementation will stop at 9 bytes, returning an error. - sz := len(buf) - if sz == 0 { - return 0, 0, 0 - } - const ( - bit = 1 << 7 - mask = bit - 1 - step = 7 - - // protobuf - typBits = 3 - typMask = 1<<3 - 1 - ) - if sz >= 9 { // no bound checks - // i == 0 - b := buf[0] - if b == 0 { - return 0, 0, 0 - } - typ = b & typMask - if typ > 5 { - return 0, 0, 0 - } - if b < bit { - num = int(b >> typBits) - if num == 0 { - return 0, 0, 0 - } - n = 1 - return - } - num = int((b & mask) >> typBits) - var s uint = step - typBits - - // i == 1 - b = buf[1] - if b < bit { - num |= int(b) << s - n = 2 - return - } - num |= int(b&mask) << s - s += step - - // i == 2 - b = buf[2] - if b < bit { - num |= int(b) << s - n = 3 - return - } - num |= int(b&mask) << s - s += step - - // i == 3 - b = buf[3] - if b < bit { - num |= int(b) << s - n = 4 - return - } - num |= int(b&mask) << s - s += step - - // i == 4 - b = buf[4] - if b < bit { - num |= int(b) << s - n = 5 - return - } - num |= int(b&mask) << s - s += step - - // i == 5 - b = buf[5] - if b < bit { - num |= int(b) << s - n = 6 - return - } - num |= int(b&mask) << s - s += step - - // i == 6 - b = buf[6] - if b < bit { - num |= int(b) << s - n = 7 - return - } - num |= int(b&mask) << s - s += step - - // i == 7 - b = buf[7] - if b < bit { - num |= int(b) << s - n = 8 - return - } - num |= int(b&mask) << s - s += step - - // i == 8 - b = buf[8] - if b < bit { - num |= int(b) << s - n = 9 - return - } - return 0, 0, 0 // too much - } - - // i == 0 - b := buf[0] - if b == 0 { - return 0, 0, 0 - } - typ = b & typMask - if typ > 5 { - return 0, 0, 0 - } - if b < bit { - num = int(b >> typBits) - if num == 0 { - return 0, 0, 0 - } - n = 1 - return - } else if sz == 1 { - return 0, 0, 0 - } - num = int((b & mask) >> typBits) - var s uint = step - typBits - - // i == 1 - b = buf[1] - if b < bit { - num |= int(b) << s - n = 2 - return - } else if sz == 2 { - return 0, 0, 0 - } - num |= int(b&mask) << s - s += step - - // i == 2 - b = buf[2] - if b < bit { - num |= int(b) << s - n = 3 - return - } else if sz == 3 { - return 0, 0, 0 - } - num |= int(b&mask) << s - s += step - - // i == 3 - b = buf[3] - if b < bit { - num |= int(b) << s - n = 4 - return - } else if sz == 4 { - return 0, 0, 0 - } - num |= int(b&mask) << s - s += step - - // i == 4 - b = buf[4] - if b < bit { - num |= int(b) << s - n = 5 - return - } else if sz == 5 { - return 0, 0, 0 - } - num |= int(b&mask) << s - s += step - - // i == 5 - b = buf[5] - if b < bit { - num |= int(b) << s - n = 6 - return - } else if sz == 6 { - return 0, 0, 0 - } - num |= int(b&mask) << s - s += step - - // i == 6 - b = buf[6] - if b < bit { - num |= int(b) << s - n = 7 - return - } else if sz == 7 { - return 0, 0, 0 - } - num |= int(b&mask) << s - s += step - - // i == 7 - b = buf[7] - if b < bit { - num |= int(b) << s - n = 8 - return - } else if sz == 8 { - return 0, 0, 0 - } - num |= int(b&mask) << s - s += step - - // i == 8 - b = buf[8] - if b < bit { - num |= int(b) << s - n = 9 - return - } - return 0, 0, 0 // too much -} diff --git a/vendor/github.com/dennwc/varint/varint.go b/vendor/github.com/dennwc/varint/varint.go deleted file mode 100644 index 83278c2d..00000000 --- a/vendor/github.com/dennwc/varint/varint.go +++ /dev/null @@ -1,270 +0,0 @@ -package varint - -const maxUint64 = uint64(1<<64 - 1) - -// MaxLenN is the maximum length of a varint-encoded N-bit integer. -const ( - MaxLen8 = 2 - MaxLen16 = 3 - MaxLen32 = 5 - MaxLen64 = 10 -) - -// MaxValN is the maximum varint-encoded integer that fits in N bytes. -const ( - MaxVal9 = maxUint64 >> (1 + iota*7) - MaxVal8 - MaxVal7 - MaxVal6 - MaxVal5 - MaxVal4 - MaxVal3 - MaxVal2 - MaxVal1 -) - -// UvarintSize returns the number of bytes necessary to encode a given uint. -func UvarintSize(x uint64) int { - if x <= MaxVal4 { - if x <= MaxVal1 { - return 1 - } else if x <= MaxVal2 { - return 2 - } else if x <= MaxVal3 { - return 3 - } - return 4 - } - if x <= MaxVal5 { - return 5 - } else if x <= MaxVal6 { - return 6 - } else if x <= MaxVal7 { - return 7 - } else if x <= MaxVal8 { - return 8 - } else if x <= MaxVal9 { - return 9 - } - return 10 -} - -// Uvarint decodes a uint64 from buf and returns that value and the -// number of bytes read (> 0). If an error occurred, the value is 0 -// and the number of bytes n is <= 0 meaning: -// -// n == 0: buf too small -// n < 0: value larger than 64 bits (overflow) -// and -n is the number of bytes read -// -func Uvarint(buf []byte) (uint64, int) { - // Fully unrolled implementation of binary.Uvarint. - // - // It will also eliminate bound checks for buffers larger than 9 bytes. - sz := len(buf) - if sz == 0 { - return 0, 0 - } - const ( - step = 7 - bit = 1 << 7 - mask = bit - 1 - ) - if sz >= 10 { // no bound checks - // i == 0 - b := buf[0] - if b < bit { - return uint64(b), 1 - } - x := uint64(b & mask) - var s uint = step - - // i == 1 - b = buf[1] - if b < bit { - return x | uint64(b)< 1 { - return 0, -10 // overflow - } - return x | uint64(b)< 1 { - return 0, -10 // overflow - } - return x | uint64(b)<re)` | yes | no (yes in RE2 compat mode) | -| .NET-style capture groups `(?re)` or `(?'name're)` | no | yes | -| comments `(?#comment)` | no | yes | -| branch numbering reset `(?\|a\|b)` | no | no | -| possessive match `(?>re)` | no | yes | -| positive lookahead `(?=re)` | no | yes | -| negative lookahead `(?!re)` | no | yes | -| positive lookbehind `(?<=re)` | no | yes | -| negative lookbehind `(?re)`) -* change singleline behavior for `$` to only match end of string (like RE2) (see [#24](https://github.com/dlclark/regexp2/issues/24)) -* change the character classes `\d` `\s` and `\w` to match the same characters as RE2. NOTE: if you also use the `ECMAScript` option then this will change the `\s` character class to match ECMAScript instead of RE2. ECMAScript allows more whitespace characters in `\s` than RE2 (but still fewer than the the default behavior). -* allow character escape sequences to have defaults. For example, by default `\_` isn't a known character escape and will fail to compile, but in RE2 mode it will match the literal character `_` - -```go -re := regexp2.MustCompile(`Your RE2-compatible pattern`, regexp2.RE2) -if isMatch, _ := re.MatchString(`Something to match`); isMatch { - //do something -} -``` - -This feature is a work in progress and I'm open to ideas for more things to put here (maybe more relaxed character escaping rules?). - -## Catastrophic Backtracking and Timeouts - -`regexp2` supports features that can lead to catastrophic backtracking. -`Regexp.MatchTimeout` can be set to to limit the impact of such behavior; the -match will fail with an error after approximately MatchTimeout. No timeout -checks are done by default. - -Timeout checking is not free. The current timeout checking implementation starts -a background worker that updates a clock value approximately once every 100 -milliseconds. The matching code compares this value against the precomputed -deadline for the match. The performance impact is as follows. - -1. A match with a timeout runs almost as fast as a match without a timeout. -2. If any live matches have a timeout, there will be a background CPU load - (`~0.15%` currently on a modern machine). This load will remain constant - regardless of the number of matches done including matches done in parallel. -3. If no live matches are using a timeout, the background load will remain - until the longest deadline (match timeout + the time when the match started) - is reached. E.g., if you set a timeout of one minute the load will persist - for approximately a minute even if the match finishes quickly. - -See [PR #58](https://github.com/dlclark/regexp2/pull/58) for more details and -alternatives considered. - -## Goroutine leak error -If you're using a library during unit tests (e.g. https://github.com/uber-go/goleak) that validates all goroutines are exited then you'll likely get an error if you or any of your dependencies use regex's with a MatchTimeout. -To remedy the problem you'll need to tell the unit test to wait until the backgroup timeout goroutine is exited. - -```go -func TestSomething(t *testing.T) { - defer goleak.VerifyNone(t) - defer regexp2.StopTimeoutClock() - - // ... test -} - -//or - -func TestMain(m *testing.M) { - // setup - // ... - - // run - m.Run() - - //tear down - regexp2.StopTimeoutClock() - goleak.VerifyNone(t) -} -``` - -This will add ~100ms runtime to each test (or TestMain). If that's too much time you can set the clock cycle rate of the timeout goroutine in an init function in a test file. `regexp2.SetTimeoutCheckPeriod` isn't threadsafe so it must be setup before starting any regex's with Timeouts. - -```go -func init() { - //speed up testing by making the timeout clock 1ms - regexp2.SetTimeoutCheckPeriod(time.Millisecond) -} -``` - -## ECMAScript compatibility mode -In this mode the engine provides compatibility with the [regex engine](https://tc39.es/ecma262/multipage/text-processing.html#sec-regexp-regular-expression-objects) described in the ECMAScript specification. - -Additionally a Unicode mode is provided which allows parsing of `\u{CodePoint}` syntax that is only when both are provided. - -## Library features that I'm still working on -- Regex split - -## Potential bugs -I've run a battery of tests against regexp2 from various sources and found the debug output matches the .NET engine, but .NET and Go handle strings very differently. I've attempted to handle these differences, but most of my testing deals with basic ASCII with a little bit of multi-byte Unicode. There's a chance that there are bugs in the string handling related to character sets with supplementary Unicode chars. Right-to-Left support is coded, but not well tested either. - -## Find a bug? -I'm open to new issues and pull requests with tests if you find something odd! diff --git a/vendor/github.com/dlclark/regexp2/fastclock.go b/vendor/github.com/dlclark/regexp2/fastclock.go deleted file mode 100644 index caf2c9d8..00000000 --- a/vendor/github.com/dlclark/regexp2/fastclock.go +++ /dev/null @@ -1,129 +0,0 @@ -package regexp2 - -import ( - "sync" - "sync/atomic" - "time" -) - -// fasttime holds a time value (ticks since clock initialization) -type fasttime int64 - -// fastclock provides a fast clock implementation. -// -// A background goroutine periodically stores the current time -// into an atomic variable. -// -// A deadline can be quickly checked for expiration by comparing -// its value to the clock stored in the atomic variable. -// -// The goroutine automatically stops once clockEnd is reached. -// (clockEnd covers the largest deadline seen so far + some -// extra time). This ensures that if regexp2 with timeouts -// stops being used we will stop background work. -type fastclock struct { - // instances of atomicTime must be at the start of the struct (or at least 64-bit aligned) - // otherwise 32-bit architectures will panic - - current atomicTime // Current time (approximate) - clockEnd atomicTime // When clock updater is supposed to stop (>= any existing deadline) - - // current and clockEnd can be read via atomic loads. - // Reads and writes of other fields require mu to be held. - mu sync.Mutex - start time.Time // Time corresponding to fasttime(0) - running bool // Is a clock updater running? -} - -var fast fastclock - -// reached returns true if current time is at or past t. -func (t fasttime) reached() bool { - return fast.current.read() >= t -} - -// makeDeadline returns a time that is approximately time.Now().Add(d) -func makeDeadline(d time.Duration) fasttime { - // Increase the deadline since the clock we are reading may be - // just about to tick forwards. - end := fast.current.read() + durationToTicks(d+clockPeriod) - - // Start or extend clock if necessary. - if end > fast.clockEnd.read() { - extendClock(end) - } - return end -} - -// extendClock ensures that clock is live and will run until at least end. -func extendClock(end fasttime) { - fast.mu.Lock() - defer fast.mu.Unlock() - - if fast.start.IsZero() { - fast.start = time.Now() - } - - // Extend the running time to cover end as well as a bit of slop. - if shutdown := end + durationToTicks(time.Second); shutdown > fast.clockEnd.read() { - fast.clockEnd.write(shutdown) - } - - // Start clock if necessary - if !fast.running { - fast.running = true - go runClock() - } -} - -// stop the timeout clock in the background -// should only used for unit tests to abandon the background goroutine -func stopClock() { - fast.mu.Lock() - if fast.running { - fast.clockEnd.write(fasttime(0)) - } - fast.mu.Unlock() - - // pause until not running - // get and release the lock - isRunning := true - for isRunning { - time.Sleep(clockPeriod / 2) - fast.mu.Lock() - isRunning = fast.running - fast.mu.Unlock() - } -} - -func durationToTicks(d time.Duration) fasttime { - // Downscale nanoseconds to approximately a millisecond so that we can avoid - // overflow even if the caller passes in math.MaxInt64. - return fasttime(d) >> 20 -} - -const DefaultClockPeriod = 100 * time.Millisecond - -// clockPeriod is the approximate interval between updates of approximateClock. -var clockPeriod = DefaultClockPeriod - -func runClock() { - fast.mu.Lock() - defer fast.mu.Unlock() - - for fast.current.read() <= fast.clockEnd.read() { - // Unlock while sleeping. - fast.mu.Unlock() - time.Sleep(clockPeriod) - fast.mu.Lock() - - newTime := durationToTicks(time.Since(fast.start)) - fast.current.write(newTime) - } - fast.running = false -} - -type atomicTime struct{ v int64 } // Should change to atomic.Int64 when we can use go 1.19 - -func (t *atomicTime) read() fasttime { return fasttime(atomic.LoadInt64(&t.v)) } -func (t *atomicTime) write(v fasttime) { atomic.StoreInt64(&t.v, int64(v)) } diff --git a/vendor/github.com/dlclark/regexp2/match.go b/vendor/github.com/dlclark/regexp2/match.go deleted file mode 100644 index 1871cffe..00000000 --- a/vendor/github.com/dlclark/regexp2/match.go +++ /dev/null @@ -1,347 +0,0 @@ -package regexp2 - -import ( - "bytes" - "fmt" -) - -// Match is a single regex result match that contains groups and repeated captures -// -Groups -// -Capture -type Match struct { - Group //embeded group 0 - - regex *Regexp - otherGroups []Group - - // input to the match - textpos int - textstart int - - capcount int - caps []int - sparseCaps map[int]int - - // output from the match - matches [][]int - matchcount []int - - // whether we've done any balancing with this match. If we - // have done balancing, we'll need to do extra work in Tidy(). - balancing bool -} - -// Group is an explicit or implit (group 0) matched group within the pattern -type Group struct { - Capture // the last capture of this group is embeded for ease of use - - Name string // group name - Captures []Capture // captures of this group -} - -// Capture is a single capture of text within the larger original string -type Capture struct { - // the original string - text []rune - // the position in the original string where the first character of - // captured substring was found. - Index int - // the length of the captured substring. - Length int -} - -// String returns the captured text as a String -func (c *Capture) String() string { - return string(c.text[c.Index : c.Index+c.Length]) -} - -// Runes returns the captured text as a rune slice -func (c *Capture) Runes() []rune { - return c.text[c.Index : c.Index+c.Length] -} - -func newMatch(regex *Regexp, capcount int, text []rune, startpos int) *Match { - m := Match{ - regex: regex, - matchcount: make([]int, capcount), - matches: make([][]int, capcount), - textstart: startpos, - balancing: false, - } - m.Name = "0" - m.text = text - m.matches[0] = make([]int, 2) - return &m -} - -func newMatchSparse(regex *Regexp, caps map[int]int, capcount int, text []rune, startpos int) *Match { - m := newMatch(regex, capcount, text, startpos) - m.sparseCaps = caps - return m -} - -func (m *Match) reset(text []rune, textstart int) { - m.text = text - m.textstart = textstart - for i := 0; i < len(m.matchcount); i++ { - m.matchcount[i] = 0 - } - m.balancing = false -} - -func (m *Match) tidy(textpos int) { - - interval := m.matches[0] - m.Index = interval[0] - m.Length = interval[1] - m.textpos = textpos - m.capcount = m.matchcount[0] - //copy our root capture to the list - m.Group.Captures = []Capture{m.Group.Capture} - - if m.balancing { - // The idea here is that we want to compact all of our unbalanced captures. To do that we - // use j basically as a count of how many unbalanced captures we have at any given time - // (really j is an index, but j/2 is the count). First we skip past all of the real captures - // until we find a balance captures. Then we check each subsequent entry. If it's a balance - // capture (it's negative), we decrement j. If it's a real capture, we increment j and copy - // it down to the last free position. - for cap := 0; cap < len(m.matchcount); cap++ { - limit := m.matchcount[cap] * 2 - matcharray := m.matches[cap] - - var i, j int - - for i = 0; i < limit; i++ { - if matcharray[i] < 0 { - break - } - } - - for j = i; i < limit; i++ { - if matcharray[i] < 0 { - // skip negative values - j-- - } else { - // but if we find something positive (an actual capture), copy it back to the last - // unbalanced position. - if i != j { - matcharray[j] = matcharray[i] - } - j++ - } - } - - m.matchcount[cap] = j / 2 - } - - m.balancing = false - } -} - -// isMatched tells if a group was matched by capnum -func (m *Match) isMatched(cap int) bool { - return cap < len(m.matchcount) && m.matchcount[cap] > 0 && m.matches[cap][m.matchcount[cap]*2-1] != (-3+1) -} - -// matchIndex returns the index of the last specified matched group by capnum -func (m *Match) matchIndex(cap int) int { - i := m.matches[cap][m.matchcount[cap]*2-2] - if i >= 0 { - return i - } - - return m.matches[cap][-3-i] -} - -// matchLength returns the length of the last specified matched group by capnum -func (m *Match) matchLength(cap int) int { - i := m.matches[cap][m.matchcount[cap]*2-1] - if i >= 0 { - return i - } - - return m.matches[cap][-3-i] -} - -// Nonpublic builder: add a capture to the group specified by "c" -func (m *Match) addMatch(c, start, l int) { - - if m.matches[c] == nil { - m.matches[c] = make([]int, 2) - } - - capcount := m.matchcount[c] - - if capcount*2+2 > len(m.matches[c]) { - oldmatches := m.matches[c] - newmatches := make([]int, capcount*8) - copy(newmatches, oldmatches[:capcount*2]) - m.matches[c] = newmatches - } - - m.matches[c][capcount*2] = start - m.matches[c][capcount*2+1] = l - m.matchcount[c] = capcount + 1 - //log.Printf("addMatch: c=%v, i=%v, l=%v ... matches: %v", c, start, l, m.matches) -} - -// Nonpublic builder: Add a capture to balance the specified group. This is used by the -// balanced match construct. (?...) -// -// If there were no such thing as backtracking, this would be as simple as calling RemoveMatch(c). -// However, since we have backtracking, we need to keep track of everything. -func (m *Match) balanceMatch(c int) { - m.balancing = true - - // we'll look at the last capture first - capcount := m.matchcount[c] - target := capcount*2 - 2 - - // first see if it is negative, and therefore is a reference to the next available - // capture group for balancing. If it is, we'll reset target to point to that capture. - if m.matches[c][target] < 0 { - target = -3 - m.matches[c][target] - } - - // move back to the previous capture - target -= 2 - - // if the previous capture is a reference, just copy that reference to the end. Otherwise, point to it. - if target >= 0 && m.matches[c][target] < 0 { - m.addMatch(c, m.matches[c][target], m.matches[c][target+1]) - } else { - m.addMatch(c, -3-target, -4-target /* == -3 - (target + 1) */) - } -} - -// Nonpublic builder: removes a group match by capnum -func (m *Match) removeMatch(c int) { - m.matchcount[c]-- -} - -// GroupCount returns the number of groups this match has matched -func (m *Match) GroupCount() int { - return len(m.matchcount) -} - -// GroupByName returns a group based on the name of the group, or nil if the group name does not exist -func (m *Match) GroupByName(name string) *Group { - num := m.regex.GroupNumberFromName(name) - if num < 0 { - return nil - } - return m.GroupByNumber(num) -} - -// GroupByNumber returns a group based on the number of the group, or nil if the group number does not exist -func (m *Match) GroupByNumber(num int) *Group { - // check our sparse map - if m.sparseCaps != nil { - if newNum, ok := m.sparseCaps[num]; ok { - num = newNum - } - } - if num >= len(m.matchcount) || num < 0 { - return nil - } - - if num == 0 { - return &m.Group - } - - m.populateOtherGroups() - - return &m.otherGroups[num-1] -} - -// Groups returns all the capture groups, starting with group 0 (the full match) -func (m *Match) Groups() []Group { - m.populateOtherGroups() - g := make([]Group, len(m.otherGroups)+1) - g[0] = m.Group - copy(g[1:], m.otherGroups) - return g -} - -func (m *Match) populateOtherGroups() { - // Construct all the Group objects first time called - if m.otherGroups == nil { - m.otherGroups = make([]Group, len(m.matchcount)-1) - for i := 0; i < len(m.otherGroups); i++ { - m.otherGroups[i] = newGroup(m.regex.GroupNameFromNumber(i+1), m.text, m.matches[i+1], m.matchcount[i+1]) - } - } -} - -func (m *Match) groupValueAppendToBuf(groupnum int, buf *bytes.Buffer) { - c := m.matchcount[groupnum] - if c == 0 { - return - } - - matches := m.matches[groupnum] - - index := matches[(c-1)*2] - last := index + matches[(c*2)-1] - - for ; index < last; index++ { - buf.WriteRune(m.text[index]) - } -} - -func newGroup(name string, text []rune, caps []int, capcount int) Group { - g := Group{} - g.text = text - if capcount > 0 { - g.Index = caps[(capcount-1)*2] - g.Length = caps[(capcount*2)-1] - } - g.Name = name - g.Captures = make([]Capture, capcount) - for i := 0; i < capcount; i++ { - g.Captures[i] = Capture{ - text: text, - Index: caps[i*2], - Length: caps[i*2+1], - } - } - //log.Printf("newGroup! capcount %v, %+v", capcount, g) - - return g -} - -func (m *Match) dump() string { - buf := &bytes.Buffer{} - buf.WriteRune('\n') - if len(m.sparseCaps) > 0 { - for k, v := range m.sparseCaps { - fmt.Fprintf(buf, "Slot %v -> %v\n", k, v) - } - } - - for i, g := range m.Groups() { - fmt.Fprintf(buf, "Group %v (%v), %v caps:\n", i, g.Name, len(g.Captures)) - - for _, c := range g.Captures { - fmt.Fprintf(buf, " (%v, %v) %v\n", c.Index, c.Length, c.String()) - } - } - /* - for i := 0; i < len(m.matchcount); i++ { - fmt.Fprintf(buf, "\nGroup %v (%v):\n", i, m.regex.GroupNameFromNumber(i)) - - for j := 0; j < m.matchcount[i]; j++ { - text := "" - - if m.matches[i][j*2] >= 0 { - start := m.matches[i][j*2] - text = m.text[start : start+m.matches[i][j*2+1]] - } - - fmt.Fprintf(buf, " (%v, %v) %v\n", m.matches[i][j*2], m.matches[i][j*2+1], text) - } - } - */ - return buf.String() -} diff --git a/vendor/github.com/dlclark/regexp2/regexp.go b/vendor/github.com/dlclark/regexp2/regexp.go deleted file mode 100644 index a7ddbaf3..00000000 --- a/vendor/github.com/dlclark/regexp2/regexp.go +++ /dev/null @@ -1,395 +0,0 @@ -/* -Package regexp2 is a regexp package that has an interface similar to Go's framework regexp engine but uses a -more feature full regex engine behind the scenes. - -It doesn't have constant time guarantees, but it allows backtracking and is compatible with Perl5 and .NET. -You'll likely be better off with the RE2 engine from the regexp package and should only use this if you -need to write very complex patterns or require compatibility with .NET. -*/ -package regexp2 - -import ( - "errors" - "math" - "strconv" - "sync" - "time" - - "github.com/dlclark/regexp2/syntax" -) - -var ( - // DefaultMatchTimeout used when running regexp matches -- "forever" - DefaultMatchTimeout = time.Duration(math.MaxInt64) - // DefaultUnmarshalOptions used when unmarshaling a regex from text - DefaultUnmarshalOptions = None -) - -// Regexp is the representation of a compiled regular expression. -// A Regexp is safe for concurrent use by multiple goroutines. -type Regexp struct { - // A match will time out if it takes (approximately) more than - // MatchTimeout. This is a safety check in case the match - // encounters catastrophic backtracking. The default value - // (DefaultMatchTimeout) causes all time out checking to be - // suppressed. - MatchTimeout time.Duration - - // read-only after Compile - pattern string // as passed to Compile - options RegexOptions // options - - caps map[int]int // capnum->index - capnames map[string]int //capture group name -> index - capslist []string //sorted list of capture group names - capsize int // size of the capture array - - code *syntax.Code // compiled program - - // cache of machines for running regexp - muRun *sync.Mutex - runner []*runner -} - -// Compile parses a regular expression and returns, if successful, -// a Regexp object that can be used to match against text. -func Compile(expr string, opt RegexOptions) (*Regexp, error) { - // parse it - tree, err := syntax.Parse(expr, syntax.RegexOptions(opt)) - if err != nil { - return nil, err - } - - // translate it to code - code, err := syntax.Write(tree) - if err != nil { - return nil, err - } - - // return it - return &Regexp{ - pattern: expr, - options: opt, - caps: code.Caps, - capnames: tree.Capnames, - capslist: tree.Caplist, - capsize: code.Capsize, - code: code, - MatchTimeout: DefaultMatchTimeout, - muRun: &sync.Mutex{}, - }, nil -} - -// MustCompile is like Compile but panics if the expression cannot be parsed. -// It simplifies safe initialization of global variables holding compiled regular -// expressions. -func MustCompile(str string, opt RegexOptions) *Regexp { - regexp, error := Compile(str, opt) - if error != nil { - panic(`regexp2: Compile(` + quote(str) + `): ` + error.Error()) - } - return regexp -} - -// Escape adds backslashes to any special characters in the input string -func Escape(input string) string { - return syntax.Escape(input) -} - -// Unescape removes any backslashes from previously-escaped special characters in the input string -func Unescape(input string) (string, error) { - return syntax.Unescape(input) -} - -// SetTimeoutPeriod is a debug function that sets the frequency of the timeout goroutine's sleep cycle. -// Defaults to 100ms. The only benefit of setting this lower is that the 1 background goroutine that manages -// timeouts may exit slightly sooner after all the timeouts have expired. See Github issue #63 -func SetTimeoutCheckPeriod(d time.Duration) { - clockPeriod = d -} - -// StopTimeoutClock should only be used in unit tests to prevent the timeout clock goroutine -// from appearing like a leaking goroutine -func StopTimeoutClock() { - stopClock() -} - -// String returns the source text used to compile the regular expression. -func (re *Regexp) String() string { - return re.pattern -} - -func quote(s string) string { - if strconv.CanBackquote(s) { - return "`" + s + "`" - } - return strconv.Quote(s) -} - -// RegexOptions impact the runtime and parsing behavior -// for each specific regex. They are setable in code as well -// as in the regex pattern itself. -type RegexOptions int32 - -const ( - None RegexOptions = 0x0 - IgnoreCase = 0x0001 // "i" - Multiline = 0x0002 // "m" - ExplicitCapture = 0x0004 // "n" - Compiled = 0x0008 // "c" - Singleline = 0x0010 // "s" - IgnorePatternWhitespace = 0x0020 // "x" - RightToLeft = 0x0040 // "r" - Debug = 0x0080 // "d" - ECMAScript = 0x0100 // "e" - RE2 = 0x0200 // RE2 (regexp package) compatibility mode - Unicode = 0x0400 // "u" -) - -func (re *Regexp) RightToLeft() bool { - return re.options&RightToLeft != 0 -} - -func (re *Regexp) Debug() bool { - return re.options&Debug != 0 -} - -// Replace searches the input string and replaces each match found with the replacement text. -// Count will limit the number of matches attempted and startAt will allow -// us to skip past possible matches at the start of the input (left or right depending on RightToLeft option). -// Set startAt and count to -1 to go through the whole string -func (re *Regexp) Replace(input, replacement string, startAt, count int) (string, error) { - data, err := syntax.NewReplacerData(replacement, re.caps, re.capsize, re.capnames, syntax.RegexOptions(re.options)) - if err != nil { - return "", err - } - //TODO: cache ReplacerData - - return replace(re, data, nil, input, startAt, count) -} - -// ReplaceFunc searches the input string and replaces each match found using the string from the evaluator -// Count will limit the number of matches attempted and startAt will allow -// us to skip past possible matches at the start of the input (left or right depending on RightToLeft option). -// Set startAt and count to -1 to go through the whole string. -func (re *Regexp) ReplaceFunc(input string, evaluator MatchEvaluator, startAt, count int) (string, error) { - return replace(re, nil, evaluator, input, startAt, count) -} - -// FindStringMatch searches the input string for a Regexp match -func (re *Regexp) FindStringMatch(s string) (*Match, error) { - // convert string to runes - return re.run(false, -1, getRunes(s)) -} - -// FindRunesMatch searches the input rune slice for a Regexp match -func (re *Regexp) FindRunesMatch(r []rune) (*Match, error) { - return re.run(false, -1, r) -} - -// FindStringMatchStartingAt searches the input string for a Regexp match starting at the startAt index -func (re *Regexp) FindStringMatchStartingAt(s string, startAt int) (*Match, error) { - if startAt > len(s) { - return nil, errors.New("startAt must be less than the length of the input string") - } - r, startAt := re.getRunesAndStart(s, startAt) - if startAt == -1 { - // we didn't find our start index in the string -- that's a problem - return nil, errors.New("startAt must align to the start of a valid rune in the input string") - } - - return re.run(false, startAt, r) -} - -// FindRunesMatchStartingAt searches the input rune slice for a Regexp match starting at the startAt index -func (re *Regexp) FindRunesMatchStartingAt(r []rune, startAt int) (*Match, error) { - return re.run(false, startAt, r) -} - -// FindNextMatch returns the next match in the same input string as the match parameter. -// Will return nil if there is no next match or if given a nil match. -func (re *Regexp) FindNextMatch(m *Match) (*Match, error) { - if m == nil { - return nil, nil - } - - // If previous match was empty, advance by one before matching to prevent - // infinite loop - startAt := m.textpos - if m.Length == 0 { - if m.textpos == len(m.text) { - return nil, nil - } - - if re.RightToLeft() { - startAt-- - } else { - startAt++ - } - } - return re.run(false, startAt, m.text) -} - -// MatchString return true if the string matches the regex -// error will be set if a timeout occurs -func (re *Regexp) MatchString(s string) (bool, error) { - m, err := re.run(true, -1, getRunes(s)) - if err != nil { - return false, err - } - return m != nil, nil -} - -func (re *Regexp) getRunesAndStart(s string, startAt int) ([]rune, int) { - if startAt < 0 { - if re.RightToLeft() { - r := getRunes(s) - return r, len(r) - } - return getRunes(s), 0 - } - ret := make([]rune, len(s)) - i := 0 - runeIdx := -1 - for strIdx, r := range s { - if strIdx == startAt { - runeIdx = i - } - ret[i] = r - i++ - } - if startAt == len(s) { - runeIdx = i - } - return ret[:i], runeIdx -} - -func getRunes(s string) []rune { - return []rune(s) -} - -// MatchRunes return true if the runes matches the regex -// error will be set if a timeout occurs -func (re *Regexp) MatchRunes(r []rune) (bool, error) { - m, err := re.run(true, -1, r) - if err != nil { - return false, err - } - return m != nil, nil -} - -// GetGroupNames Returns the set of strings used to name capturing groups in the expression. -func (re *Regexp) GetGroupNames() []string { - var result []string - - if re.capslist == nil { - result = make([]string, re.capsize) - - for i := 0; i < len(result); i++ { - result[i] = strconv.Itoa(i) - } - } else { - result = make([]string, len(re.capslist)) - copy(result, re.capslist) - } - - return result -} - -// GetGroupNumbers returns the integer group numbers corresponding to a group name. -func (re *Regexp) GetGroupNumbers() []int { - var result []int - - if re.caps == nil { - result = make([]int, re.capsize) - - for i := 0; i < len(result); i++ { - result[i] = i - } - } else { - result = make([]int, len(re.caps)) - - for k, v := range re.caps { - result[v] = k - } - } - - return result -} - -// GroupNameFromNumber retrieves a group name that corresponds to a group number. -// It will return "" for and unknown group number. Unnamed groups automatically -// receive a name that is the decimal string equivalent of its number. -func (re *Regexp) GroupNameFromNumber(i int) string { - if re.capslist == nil { - if i >= 0 && i < re.capsize { - return strconv.Itoa(i) - } - - return "" - } - - if re.caps != nil { - var ok bool - if i, ok = re.caps[i]; !ok { - return "" - } - } - - if i >= 0 && i < len(re.capslist) { - return re.capslist[i] - } - - return "" -} - -// GroupNumberFromName returns a group number that corresponds to a group name. -// Returns -1 if the name is not a recognized group name. Numbered groups -// automatically get a group name that is the decimal string equivalent of its number. -func (re *Regexp) GroupNumberFromName(name string) int { - // look up name if we have a hashtable of names - if re.capnames != nil { - if k, ok := re.capnames[name]; ok { - return k - } - - return -1 - } - - // convert to an int if it looks like a number - result := 0 - for i := 0; i < len(name); i++ { - ch := name[i] - - if ch > '9' || ch < '0' { - return -1 - } - - result *= 10 - result += int(ch - '0') - } - - // return int if it's in range - if result >= 0 && result < re.capsize { - return result - } - - return -1 -} - -// MarshalText implements [encoding.TextMarshaler]. The output -// matches that of calling the [Regexp.String] method. -func (re *Regexp) MarshalText() ([]byte, error) { - return []byte(re.String()), nil -} - -// UnmarshalText implements [encoding.TextUnmarshaler] by calling -// [Compile] on the encoded value. -func (re *Regexp) UnmarshalText(text []byte) error { - newRE, err := Compile(string(text), DefaultUnmarshalOptions) - if err != nil { - return err - } - *re = *newRE - return nil -} diff --git a/vendor/github.com/dlclark/regexp2/replace.go b/vendor/github.com/dlclark/regexp2/replace.go deleted file mode 100644 index 0376bd9d..00000000 --- a/vendor/github.com/dlclark/regexp2/replace.go +++ /dev/null @@ -1,177 +0,0 @@ -package regexp2 - -import ( - "bytes" - "errors" - - "github.com/dlclark/regexp2/syntax" -) - -const ( - replaceSpecials = 4 - replaceLeftPortion = -1 - replaceRightPortion = -2 - replaceLastGroup = -3 - replaceWholeString = -4 -) - -// MatchEvaluator is a function that takes a match and returns a replacement string to be used -type MatchEvaluator func(Match) string - -// Three very similar algorithms appear below: replace (pattern), -// replace (evaluator), and split. - -// Replace Replaces all occurrences of the regex in the string with the -// replacement pattern. -// -// Note that the special case of no matches is handled on its own: -// with no matches, the input string is returned unchanged. -// The right-to-left case is split out because StringBuilder -// doesn't handle right-to-left string building directly very well. -func replace(regex *Regexp, data *syntax.ReplacerData, evaluator MatchEvaluator, input string, startAt, count int) (string, error) { - if count < -1 { - return "", errors.New("Count too small") - } - if count == 0 { - return "", nil - } - - m, err := regex.FindStringMatchStartingAt(input, startAt) - - if err != nil { - return "", err - } - if m == nil { - return input, nil - } - - buf := &bytes.Buffer{} - text := m.text - - if !regex.RightToLeft() { - prevat := 0 - for m != nil { - if m.Index != prevat { - buf.WriteString(string(text[prevat:m.Index])) - } - prevat = m.Index + m.Length - if evaluator == nil { - replacementImpl(data, buf, m) - } else { - buf.WriteString(evaluator(*m)) - } - - count-- - if count == 0 { - break - } - m, err = regex.FindNextMatch(m) - if err != nil { - return "", nil - } - } - - if prevat < len(text) { - buf.WriteString(string(text[prevat:])) - } - } else { - prevat := len(text) - var al []string - - for m != nil { - if m.Index+m.Length != prevat { - al = append(al, string(text[m.Index+m.Length:prevat])) - } - prevat = m.Index - if evaluator == nil { - replacementImplRTL(data, &al, m) - } else { - al = append(al, evaluator(*m)) - } - - count-- - if count == 0 { - break - } - m, err = regex.FindNextMatch(m) - if err != nil { - return "", nil - } - } - - if prevat > 0 { - buf.WriteString(string(text[:prevat])) - } - - for i := len(al) - 1; i >= 0; i-- { - buf.WriteString(al[i]) - } - } - - return buf.String(), nil -} - -// Given a Match, emits into the StringBuilder the evaluated -// substitution pattern. -func replacementImpl(data *syntax.ReplacerData, buf *bytes.Buffer, m *Match) { - for _, r := range data.Rules { - - if r >= 0 { // string lookup - buf.WriteString(data.Strings[r]) - } else if r < -replaceSpecials { // group lookup - m.groupValueAppendToBuf(-replaceSpecials-1-r, buf) - } else { - switch -replaceSpecials - 1 - r { // special insertion patterns - case replaceLeftPortion: - for i := 0; i < m.Index; i++ { - buf.WriteRune(m.text[i]) - } - case replaceRightPortion: - for i := m.Index + m.Length; i < len(m.text); i++ { - buf.WriteRune(m.text[i]) - } - case replaceLastGroup: - m.groupValueAppendToBuf(m.GroupCount()-1, buf) - case replaceWholeString: - for i := 0; i < len(m.text); i++ { - buf.WriteRune(m.text[i]) - } - } - } - } -} - -func replacementImplRTL(data *syntax.ReplacerData, al *[]string, m *Match) { - l := *al - buf := &bytes.Buffer{} - - for _, r := range data.Rules { - buf.Reset() - if r >= 0 { // string lookup - l = append(l, data.Strings[r]) - } else if r < -replaceSpecials { // group lookup - m.groupValueAppendToBuf(-replaceSpecials-1-r, buf) - l = append(l, buf.String()) - } else { - switch -replaceSpecials - 1 - r { // special insertion patterns - case replaceLeftPortion: - for i := 0; i < m.Index; i++ { - buf.WriteRune(m.text[i]) - } - case replaceRightPortion: - for i := m.Index + m.Length; i < len(m.text); i++ { - buf.WriteRune(m.text[i]) - } - case replaceLastGroup: - m.groupValueAppendToBuf(m.GroupCount()-1, buf) - case replaceWholeString: - for i := 0; i < len(m.text); i++ { - buf.WriteRune(m.text[i]) - } - } - l = append(l, buf.String()) - } - } - - *al = l -} diff --git a/vendor/github.com/dlclark/regexp2/runner.go b/vendor/github.com/dlclark/regexp2/runner.go deleted file mode 100644 index 494dcef9..00000000 --- a/vendor/github.com/dlclark/regexp2/runner.go +++ /dev/null @@ -1,1609 +0,0 @@ -package regexp2 - -import ( - "bytes" - "errors" - "fmt" - "math" - "strconv" - "strings" - "time" - "unicode" - - "github.com/dlclark/regexp2/syntax" -) - -type runner struct { - re *Regexp - code *syntax.Code - - runtextstart int // starting point for search - - runtext []rune // text to search - runtextpos int // current position in text - runtextend int - - // The backtracking stack. Opcodes use this to store data regarding - // what they have matched and where to backtrack to. Each "frame" on - // the stack takes the form of [CodePosition Data1 Data2...], where - // CodePosition is the position of the current opcode and - // the data values are all optional. The CodePosition can be negative, and - // these values (also called "back2") are used by the BranchMark family of opcodes - // to indicate whether they are backtracking after a successful or failed - // match. - // When we backtrack, we pop the CodePosition off the stack, set the current - // instruction pointer to that code position, and mark the opcode - // with a backtracking flag ("Back"). Each opcode then knows how to - // handle its own data. - runtrack []int - runtrackpos int - - // This stack is used to track text positions across different opcodes. - // For example, in /(a*b)+/, the parentheses result in a SetMark/CaptureMark - // pair. SetMark records the text position before we match a*b. Then - // CaptureMark uses that position to figure out where the capture starts. - // Opcodes which push onto this stack are always paired with other opcodes - // which will pop the value from it later. A successful match should mean - // that this stack is empty. - runstack []int - runstackpos int - - // The crawl stack is used to keep track of captures. Every time a group - // has a capture, we push its group number onto the runcrawl stack. In - // the case of a balanced match, we push BOTH groups onto the stack. - runcrawl []int - runcrawlpos int - - runtrackcount int // count of states that may do backtracking - - runmatch *Match // result object - - ignoreTimeout bool - timeout time.Duration // timeout in milliseconds (needed for actual) - deadline fasttime - - operator syntax.InstOp - codepos int - rightToLeft bool - caseInsensitive bool -} - -// run searches for matches and can continue from the previous match -// -// quick is usually false, but can be true to not return matches, just put it in caches -// textstart is -1 to start at the "beginning" (depending on Right-To-Left), otherwise an index in input -// input is the string to search for our regex pattern -func (re *Regexp) run(quick bool, textstart int, input []rune) (*Match, error) { - - // get a cached runner - runner := re.getRunner() - defer re.putRunner(runner) - - if textstart < 0 { - if re.RightToLeft() { - textstart = len(input) - } else { - textstart = 0 - } - } - - return runner.scan(input, textstart, quick, re.MatchTimeout) -} - -// Scans the string to find the first match. Uses the Match object -// both to feed text in and as a place to store matches that come out. -// -// All the action is in the Go() method. Our -// responsibility is to load up the class members before -// calling Go. -// -// The optimizer can compute a set of candidate starting characters, -// and we could use a separate method Skip() that will quickly scan past -// any characters that we know can't match. -func (r *runner) scan(rt []rune, textstart int, quick bool, timeout time.Duration) (*Match, error) { - r.timeout = timeout - r.ignoreTimeout = (time.Duration(math.MaxInt64) == timeout) - r.runtextstart = textstart - r.runtext = rt - r.runtextend = len(rt) - - stoppos := r.runtextend - bump := 1 - - if r.re.RightToLeft() { - bump = -1 - stoppos = 0 - } - - r.runtextpos = textstart - initted := false - - r.startTimeoutWatch() - for { - if r.re.Debug() { - //fmt.Printf("\nSearch content: %v\n", string(r.runtext)) - fmt.Printf("\nSearch range: from 0 to %v\n", r.runtextend) - fmt.Printf("Firstchar search starting at %v stopping at %v\n", r.runtextpos, stoppos) - } - - if r.findFirstChar() { - if err := r.checkTimeout(); err != nil { - return nil, err - } - - if !initted { - r.initMatch() - initted = true - } - - if r.re.Debug() { - fmt.Printf("Executing engine starting at %v\n\n", r.runtextpos) - } - - if err := r.execute(); err != nil { - return nil, err - } - - if r.runmatch.matchcount[0] > 0 { - // We'll return a match even if it touches a previous empty match - return r.tidyMatch(quick), nil - } - - // reset state for another go - r.runtrackpos = len(r.runtrack) - r.runstackpos = len(r.runstack) - r.runcrawlpos = len(r.runcrawl) - } - - // failure! - - if r.runtextpos == stoppos { - r.tidyMatch(true) - return nil, nil - } - - // Recognize leading []* and various anchors, and bump on failure accordingly - - // r.bump by one and start again - - r.runtextpos += bump - } - // We never get here -} - -func (r *runner) execute() error { - - r.goTo(0) - - for { - - if r.re.Debug() { - r.dumpState() - } - - if err := r.checkTimeout(); err != nil { - return err - } - - switch r.operator { - case syntax.Stop: - return nil - - case syntax.Nothing: - break - - case syntax.Goto: - r.goTo(r.operand(0)) - continue - - case syntax.Testref: - if !r.runmatch.isMatched(r.operand(0)) { - break - } - r.advance(1) - continue - - case syntax.Lazybranch: - r.trackPush1(r.textPos()) - r.advance(1) - continue - - case syntax.Lazybranch | syntax.Back: - r.trackPop() - r.textto(r.trackPeek()) - r.goTo(r.operand(0)) - continue - - case syntax.Setmark: - r.stackPush(r.textPos()) - r.trackPush() - r.advance(0) - continue - - case syntax.Nullmark: - r.stackPush(-1) - r.trackPush() - r.advance(0) - continue - - case syntax.Setmark | syntax.Back, syntax.Nullmark | syntax.Back: - r.stackPop() - break - - case syntax.Getmark: - r.stackPop() - r.trackPush1(r.stackPeek()) - r.textto(r.stackPeek()) - r.advance(0) - continue - - case syntax.Getmark | syntax.Back: - r.trackPop() - r.stackPush(r.trackPeek()) - break - - case syntax.Capturemark: - if r.operand(1) != -1 && !r.runmatch.isMatched(r.operand(1)) { - break - } - r.stackPop() - if r.operand(1) != -1 { - r.transferCapture(r.operand(0), r.operand(1), r.stackPeek(), r.textPos()) - } else { - r.capture(r.operand(0), r.stackPeek(), r.textPos()) - } - r.trackPush1(r.stackPeek()) - - r.advance(2) - - continue - - case syntax.Capturemark | syntax.Back: - r.trackPop() - r.stackPush(r.trackPeek()) - r.uncapture() - if r.operand(0) != -1 && r.operand(1) != -1 { - r.uncapture() - } - - break - - case syntax.Branchmark: - r.stackPop() - - matched := r.textPos() - r.stackPeek() - - if matched != 0 { // Nonempty match -> loop now - r.trackPush2(r.stackPeek(), r.textPos()) // Save old mark, textpos - r.stackPush(r.textPos()) // Make new mark - r.goTo(r.operand(0)) // Loop - } else { // Empty match -> straight now - r.trackPushNeg1(r.stackPeek()) // Save old mark - r.advance(1) // Straight - } - continue - - case syntax.Branchmark | syntax.Back: - r.trackPopN(2) - r.stackPop() - r.textto(r.trackPeekN(1)) // Recall position - r.trackPushNeg1(r.trackPeek()) // Save old mark - r.advance(1) // Straight - continue - - case syntax.Branchmark | syntax.Back2: - r.trackPop() - r.stackPush(r.trackPeek()) // Recall old mark - break // Backtrack - - case syntax.Lazybranchmark: - { - // We hit this the first time through a lazy loop and after each - // successful match of the inner expression. It simply continues - // on and doesn't loop. - r.stackPop() - - oldMarkPos := r.stackPeek() - - if r.textPos() != oldMarkPos { // Nonempty match -> try to loop again by going to 'back' state - if oldMarkPos != -1 { - r.trackPush2(oldMarkPos, r.textPos()) // Save old mark, textpos - } else { - r.trackPush2(r.textPos(), r.textPos()) - } - } else { - // The inner expression found an empty match, so we'll go directly to 'back2' if we - // backtrack. In this case, we need to push something on the stack, since back2 pops. - // However, in the case of ()+? or similar, this empty match may be legitimate, so push the text - // position associated with that empty match. - r.stackPush(oldMarkPos) - - r.trackPushNeg1(r.stackPeek()) // Save old mark - } - r.advance(1) - continue - } - - case syntax.Lazybranchmark | syntax.Back: - - // After the first time, Lazybranchmark | syntax.Back occurs - // with each iteration of the loop, and therefore with every attempted - // match of the inner expression. We'll try to match the inner expression, - // then go back to Lazybranchmark if successful. If the inner expression - // fails, we go to Lazybranchmark | syntax.Back2 - - r.trackPopN(2) - pos := r.trackPeekN(1) - r.trackPushNeg1(r.trackPeek()) // Save old mark - r.stackPush(pos) // Make new mark - r.textto(pos) // Recall position - r.goTo(r.operand(0)) // Loop - continue - - case syntax.Lazybranchmark | syntax.Back2: - // The lazy loop has failed. We'll do a true backtrack and - // start over before the lazy loop. - r.stackPop() - r.trackPop() - r.stackPush(r.trackPeek()) // Recall old mark - break - - case syntax.Setcount: - r.stackPush2(r.textPos(), r.operand(0)) - r.trackPush() - r.advance(1) - continue - - case syntax.Nullcount: - r.stackPush2(-1, r.operand(0)) - r.trackPush() - r.advance(1) - continue - - case syntax.Setcount | syntax.Back: - r.stackPopN(2) - break - - case syntax.Nullcount | syntax.Back: - r.stackPopN(2) - break - - case syntax.Branchcount: - // r.stackPush: - // 0: Mark - // 1: Count - - r.stackPopN(2) - mark := r.stackPeek() - count := r.stackPeekN(1) - matched := r.textPos() - mark - - if count >= r.operand(1) || (matched == 0 && count >= 0) { // Max loops or empty match -> straight now - r.trackPushNeg2(mark, count) // Save old mark, count - r.advance(2) // Straight - } else { // Nonempty match -> count+loop now - r.trackPush1(mark) // remember mark - r.stackPush2(r.textPos(), count+1) // Make new mark, incr count - r.goTo(r.operand(0)) // Loop - } - continue - - case syntax.Branchcount | syntax.Back: - // r.trackPush: - // 0: Previous mark - // r.stackPush: - // 0: Mark (= current pos, discarded) - // 1: Count - r.trackPop() - r.stackPopN(2) - if r.stackPeekN(1) > 0 { // Positive -> can go straight - r.textto(r.stackPeek()) // Zap to mark - r.trackPushNeg2(r.trackPeek(), r.stackPeekN(1)-1) // Save old mark, old count - r.advance(2) // Straight - continue - } - r.stackPush2(r.trackPeek(), r.stackPeekN(1)-1) // recall old mark, old count - break - - case syntax.Branchcount | syntax.Back2: - // r.trackPush: - // 0: Previous mark - // 1: Previous count - r.trackPopN(2) - r.stackPush2(r.trackPeek(), r.trackPeekN(1)) // Recall old mark, old count - break // Backtrack - - case syntax.Lazybranchcount: - // r.stackPush: - // 0: Mark - // 1: Count - - r.stackPopN(2) - mark := r.stackPeek() - count := r.stackPeekN(1) - - if count < 0 { // Negative count -> loop now - r.trackPushNeg1(mark) // Save old mark - r.stackPush2(r.textPos(), count+1) // Make new mark, incr count - r.goTo(r.operand(0)) // Loop - } else { // Nonneg count -> straight now - r.trackPush3(mark, count, r.textPos()) // Save mark, count, position - r.advance(2) // Straight - } - continue - - case syntax.Lazybranchcount | syntax.Back: - // r.trackPush: - // 0: Mark - // 1: Count - // 2: r.textPos - - r.trackPopN(3) - mark := r.trackPeek() - textpos := r.trackPeekN(2) - - if r.trackPeekN(1) < r.operand(1) && textpos != mark { // Under limit and not empty match -> loop - r.textto(textpos) // Recall position - r.stackPush2(textpos, r.trackPeekN(1)+1) // Make new mark, incr count - r.trackPushNeg1(mark) // Save old mark - r.goTo(r.operand(0)) // Loop - continue - } else { // Max loops or empty match -> backtrack - r.stackPush2(r.trackPeek(), r.trackPeekN(1)) // Recall old mark, count - break // backtrack - } - - case syntax.Lazybranchcount | syntax.Back2: - // r.trackPush: - // 0: Previous mark - // r.stackPush: - // 0: Mark (== current pos, discarded) - // 1: Count - r.trackPop() - r.stackPopN(2) - r.stackPush2(r.trackPeek(), r.stackPeekN(1)-1) // Recall old mark, count - break // Backtrack - - case syntax.Setjump: - r.stackPush2(r.trackpos(), r.crawlpos()) - r.trackPush() - r.advance(0) - continue - - case syntax.Setjump | syntax.Back: - r.stackPopN(2) - break - - case syntax.Backjump: - // r.stackPush: - // 0: Saved trackpos - // 1: r.crawlpos - r.stackPopN(2) - r.trackto(r.stackPeek()) - - for r.crawlpos() != r.stackPeekN(1) { - r.uncapture() - } - - break - - case syntax.Forejump: - // r.stackPush: - // 0: Saved trackpos - // 1: r.crawlpos - r.stackPopN(2) - r.trackto(r.stackPeek()) - r.trackPush1(r.stackPeekN(1)) - r.advance(0) - continue - - case syntax.Forejump | syntax.Back: - // r.trackPush: - // 0: r.crawlpos - r.trackPop() - - for r.crawlpos() != r.trackPeek() { - r.uncapture() - } - - break - - case syntax.Bol: - if r.leftchars() > 0 && r.charAt(r.textPos()-1) != '\n' { - break - } - r.advance(0) - continue - - case syntax.Eol: - if r.rightchars() > 0 && r.charAt(r.textPos()) != '\n' { - break - } - r.advance(0) - continue - - case syntax.Boundary: - if !r.isBoundary(r.textPos(), 0, r.runtextend) { - break - } - r.advance(0) - continue - - case syntax.Nonboundary: - if r.isBoundary(r.textPos(), 0, r.runtextend) { - break - } - r.advance(0) - continue - - case syntax.ECMABoundary: - if !r.isECMABoundary(r.textPos(), 0, r.runtextend) { - break - } - r.advance(0) - continue - - case syntax.NonECMABoundary: - if r.isECMABoundary(r.textPos(), 0, r.runtextend) { - break - } - r.advance(0) - continue - - case syntax.Beginning: - if r.leftchars() > 0 { - break - } - r.advance(0) - continue - - case syntax.Start: - if r.textPos() != r.textstart() { - break - } - r.advance(0) - continue - - case syntax.EndZ: - rchars := r.rightchars() - if rchars > 1 { - break - } - // RE2 and EcmaScript define $ as "asserts position at the end of the string" - // PCRE/.NET adds "or before the line terminator right at the end of the string (if any)" - if (r.re.options & (RE2 | ECMAScript)) != 0 { - // RE2/Ecmascript mode - if rchars > 0 { - break - } - } else if rchars == 1 && r.charAt(r.textPos()) != '\n' { - // "regular" mode - break - } - - r.advance(0) - continue - - case syntax.End: - if r.rightchars() > 0 { - break - } - r.advance(0) - continue - - case syntax.One: - if r.forwardchars() < 1 || r.forwardcharnext() != rune(r.operand(0)) { - break - } - - r.advance(1) - continue - - case syntax.Notone: - if r.forwardchars() < 1 || r.forwardcharnext() == rune(r.operand(0)) { - break - } - - r.advance(1) - continue - - case syntax.Set: - - if r.forwardchars() < 1 || !r.code.Sets[r.operand(0)].CharIn(r.forwardcharnext()) { - break - } - - r.advance(1) - continue - - case syntax.Multi: - if !r.runematch(r.code.Strings[r.operand(0)]) { - break - } - - r.advance(1) - continue - - case syntax.Ref: - - capnum := r.operand(0) - - if r.runmatch.isMatched(capnum) { - if !r.refmatch(r.runmatch.matchIndex(capnum), r.runmatch.matchLength(capnum)) { - break - } - } else { - if (r.re.options & ECMAScript) == 0 { - break - } - } - - r.advance(1) - continue - - case syntax.Onerep: - - c := r.operand(1) - - if r.forwardchars() < c { - break - } - - ch := rune(r.operand(0)) - - for c > 0 { - if r.forwardcharnext() != ch { - goto BreakBackward - } - c-- - } - - r.advance(2) - continue - - case syntax.Notonerep: - - c := r.operand(1) - - if r.forwardchars() < c { - break - } - ch := rune(r.operand(0)) - - for c > 0 { - if r.forwardcharnext() == ch { - goto BreakBackward - } - c-- - } - - r.advance(2) - continue - - case syntax.Setrep: - - c := r.operand(1) - - if r.forwardchars() < c { - break - } - - set := r.code.Sets[r.operand(0)] - - for c > 0 { - if !set.CharIn(r.forwardcharnext()) { - goto BreakBackward - } - c-- - } - - r.advance(2) - continue - - case syntax.Oneloop: - - c := r.operand(1) - - if c > r.forwardchars() { - c = r.forwardchars() - } - - ch := rune(r.operand(0)) - i := c - - for ; i > 0; i-- { - if r.forwardcharnext() != ch { - r.backwardnext() - break - } - } - - if c > i { - r.trackPush2(c-i-1, r.textPos()-r.bump()) - } - - r.advance(2) - continue - - case syntax.Notoneloop: - - c := r.operand(1) - - if c > r.forwardchars() { - c = r.forwardchars() - } - - ch := rune(r.operand(0)) - i := c - - for ; i > 0; i-- { - if r.forwardcharnext() == ch { - r.backwardnext() - break - } - } - - if c > i { - r.trackPush2(c-i-1, r.textPos()-r.bump()) - } - - r.advance(2) - continue - - case syntax.Setloop: - - c := r.operand(1) - - if c > r.forwardchars() { - c = r.forwardchars() - } - - set := r.code.Sets[r.operand(0)] - i := c - - for ; i > 0; i-- { - if !set.CharIn(r.forwardcharnext()) { - r.backwardnext() - break - } - } - - if c > i { - r.trackPush2(c-i-1, r.textPos()-r.bump()) - } - - r.advance(2) - continue - - case syntax.Oneloop | syntax.Back, syntax.Notoneloop | syntax.Back: - - r.trackPopN(2) - i := r.trackPeek() - pos := r.trackPeekN(1) - - r.textto(pos) - - if i > 0 { - r.trackPush2(i-1, pos-r.bump()) - } - - r.advance(2) - continue - - case syntax.Setloop | syntax.Back: - - r.trackPopN(2) - i := r.trackPeek() - pos := r.trackPeekN(1) - - r.textto(pos) - - if i > 0 { - r.trackPush2(i-1, pos-r.bump()) - } - - r.advance(2) - continue - - case syntax.Onelazy, syntax.Notonelazy: - - c := r.operand(1) - - if c > r.forwardchars() { - c = r.forwardchars() - } - - if c > 0 { - r.trackPush2(c-1, r.textPos()) - } - - r.advance(2) - continue - - case syntax.Setlazy: - - c := r.operand(1) - - if c > r.forwardchars() { - c = r.forwardchars() - } - - if c > 0 { - r.trackPush2(c-1, r.textPos()) - } - - r.advance(2) - continue - - case syntax.Onelazy | syntax.Back: - - r.trackPopN(2) - pos := r.trackPeekN(1) - r.textto(pos) - - if r.forwardcharnext() != rune(r.operand(0)) { - break - } - - i := r.trackPeek() - - if i > 0 { - r.trackPush2(i-1, pos+r.bump()) - } - - r.advance(2) - continue - - case syntax.Notonelazy | syntax.Back: - - r.trackPopN(2) - pos := r.trackPeekN(1) - r.textto(pos) - - if r.forwardcharnext() == rune(r.operand(0)) { - break - } - - i := r.trackPeek() - - if i > 0 { - r.trackPush2(i-1, pos+r.bump()) - } - - r.advance(2) - continue - - case syntax.Setlazy | syntax.Back: - - r.trackPopN(2) - pos := r.trackPeekN(1) - r.textto(pos) - - if !r.code.Sets[r.operand(0)].CharIn(r.forwardcharnext()) { - break - } - - i := r.trackPeek() - - if i > 0 { - r.trackPush2(i-1, pos+r.bump()) - } - - r.advance(2) - continue - - default: - return errors.New("unknown state in regex runner") - } - - BreakBackward: - ; - - // "break Backward" comes here: - r.backtrack() - } -} - -// increase the size of stack and track storage -func (r *runner) ensureStorage() { - if r.runstackpos < r.runtrackcount*4 { - doubleIntSlice(&r.runstack, &r.runstackpos) - } - if r.runtrackpos < r.runtrackcount*4 { - doubleIntSlice(&r.runtrack, &r.runtrackpos) - } -} - -func doubleIntSlice(s *[]int, pos *int) { - oldLen := len(*s) - newS := make([]int, oldLen*2) - - copy(newS[oldLen:], *s) - *pos += oldLen - *s = newS -} - -// Save a number on the longjump unrolling stack -func (r *runner) crawl(i int) { - if r.runcrawlpos == 0 { - doubleIntSlice(&r.runcrawl, &r.runcrawlpos) - } - r.runcrawlpos-- - r.runcrawl[r.runcrawlpos] = i -} - -// Remove a number from the longjump unrolling stack -func (r *runner) popcrawl() int { - val := r.runcrawl[r.runcrawlpos] - r.runcrawlpos++ - return val -} - -// Get the height of the stack -func (r *runner) crawlpos() int { - return len(r.runcrawl) - r.runcrawlpos -} - -func (r *runner) advance(i int) { - r.codepos += (i + 1) - r.setOperator(r.code.Codes[r.codepos]) -} - -func (r *runner) goTo(newpos int) { - // when branching backward or in place, ensure storage - if newpos <= r.codepos { - r.ensureStorage() - } - - r.setOperator(r.code.Codes[newpos]) - r.codepos = newpos -} - -func (r *runner) textto(newpos int) { - r.runtextpos = newpos -} - -func (r *runner) trackto(newpos int) { - r.runtrackpos = len(r.runtrack) - newpos -} - -func (r *runner) textstart() int { - return r.runtextstart -} - -func (r *runner) textPos() int { - return r.runtextpos -} - -// push onto the backtracking stack -func (r *runner) trackpos() int { - return len(r.runtrack) - r.runtrackpos -} - -func (r *runner) trackPush() { - r.runtrackpos-- - r.runtrack[r.runtrackpos] = r.codepos -} - -func (r *runner) trackPush1(I1 int) { - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I1 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = r.codepos -} - -func (r *runner) trackPush2(I1, I2 int) { - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I1 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I2 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = r.codepos -} - -func (r *runner) trackPush3(I1, I2, I3 int) { - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I1 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I2 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I3 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = r.codepos -} - -func (r *runner) trackPushNeg1(I1 int) { - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I1 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = -r.codepos -} - -func (r *runner) trackPushNeg2(I1, I2 int) { - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I1 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = I2 - r.runtrackpos-- - r.runtrack[r.runtrackpos] = -r.codepos -} - -func (r *runner) backtrack() { - newpos := r.runtrack[r.runtrackpos] - r.runtrackpos++ - - if r.re.Debug() { - if newpos < 0 { - fmt.Printf(" Backtracking (back2) to code position %v\n", -newpos) - } else { - fmt.Printf(" Backtracking to code position %v\n", newpos) - } - } - - if newpos < 0 { - newpos = -newpos - r.setOperator(r.code.Codes[newpos] | syntax.Back2) - } else { - r.setOperator(r.code.Codes[newpos] | syntax.Back) - } - - // When branching backward, ensure storage - if newpos < r.codepos { - r.ensureStorage() - } - - r.codepos = newpos -} - -func (r *runner) setOperator(op int) { - r.caseInsensitive = (0 != (op & syntax.Ci)) - r.rightToLeft = (0 != (op & syntax.Rtl)) - r.operator = syntax.InstOp(op & ^(syntax.Rtl | syntax.Ci)) -} - -func (r *runner) trackPop() { - r.runtrackpos++ -} - -// pop framesize items from the backtracking stack -func (r *runner) trackPopN(framesize int) { - r.runtrackpos += framesize -} - -// Technically we are actually peeking at items already popped. So if you want to -// get and pop the top item from the stack, you do -// r.trackPop(); -// r.trackPeek(); -func (r *runner) trackPeek() int { - return r.runtrack[r.runtrackpos-1] -} - -// get the ith element down on the backtracking stack -func (r *runner) trackPeekN(i int) int { - return r.runtrack[r.runtrackpos-i-1] -} - -// Push onto the grouping stack -func (r *runner) stackPush(I1 int) { - r.runstackpos-- - r.runstack[r.runstackpos] = I1 -} - -func (r *runner) stackPush2(I1, I2 int) { - r.runstackpos-- - r.runstack[r.runstackpos] = I1 - r.runstackpos-- - r.runstack[r.runstackpos] = I2 -} - -func (r *runner) stackPop() { - r.runstackpos++ -} - -// pop framesize items from the grouping stack -func (r *runner) stackPopN(framesize int) { - r.runstackpos += framesize -} - -// Technically we are actually peeking at items already popped. So if you want to -// get and pop the top item from the stack, you do -// r.stackPop(); -// r.stackPeek(); -func (r *runner) stackPeek() int { - return r.runstack[r.runstackpos-1] -} - -// get the ith element down on the grouping stack -func (r *runner) stackPeekN(i int) int { - return r.runstack[r.runstackpos-i-1] -} - -func (r *runner) operand(i int) int { - return r.code.Codes[r.codepos+i+1] -} - -func (r *runner) leftchars() int { - return r.runtextpos -} - -func (r *runner) rightchars() int { - return r.runtextend - r.runtextpos -} - -func (r *runner) bump() int { - if r.rightToLeft { - return -1 - } - return 1 -} - -func (r *runner) forwardchars() int { - if r.rightToLeft { - return r.runtextpos - } - return r.runtextend - r.runtextpos -} - -func (r *runner) forwardcharnext() rune { - var ch rune - if r.rightToLeft { - r.runtextpos-- - ch = r.runtext[r.runtextpos] - } else { - ch = r.runtext[r.runtextpos] - r.runtextpos++ - } - - if r.caseInsensitive { - return unicode.ToLower(ch) - } - return ch -} - -func (r *runner) runematch(str []rune) bool { - var pos int - - c := len(str) - if !r.rightToLeft { - if r.runtextend-r.runtextpos < c { - return false - } - - pos = r.runtextpos + c - } else { - if r.runtextpos-0 < c { - return false - } - - pos = r.runtextpos - } - - if !r.caseInsensitive { - for c != 0 { - c-- - pos-- - if str[c] != r.runtext[pos] { - return false - } - } - } else { - for c != 0 { - c-- - pos-- - if str[c] != unicode.ToLower(r.runtext[pos]) { - return false - } - } - } - - if !r.rightToLeft { - pos += len(str) - } - - r.runtextpos = pos - - return true -} - -func (r *runner) refmatch(index, len int) bool { - var c, pos, cmpos int - - if !r.rightToLeft { - if r.runtextend-r.runtextpos < len { - return false - } - - pos = r.runtextpos + len - } else { - if r.runtextpos-0 < len { - return false - } - - pos = r.runtextpos - } - cmpos = index + len - - c = len - - if !r.caseInsensitive { - for c != 0 { - c-- - cmpos-- - pos-- - if r.runtext[cmpos] != r.runtext[pos] { - return false - } - - } - } else { - for c != 0 { - c-- - cmpos-- - pos-- - - if unicode.ToLower(r.runtext[cmpos]) != unicode.ToLower(r.runtext[pos]) { - return false - } - } - } - - if !r.rightToLeft { - pos += len - } - - r.runtextpos = pos - - return true -} - -func (r *runner) backwardnext() { - if r.rightToLeft { - r.runtextpos++ - } else { - r.runtextpos-- - } -} - -func (r *runner) charAt(j int) rune { - return r.runtext[j] -} - -func (r *runner) findFirstChar() bool { - - if 0 != (r.code.Anchors & (syntax.AnchorBeginning | syntax.AnchorStart | syntax.AnchorEndZ | syntax.AnchorEnd)) { - if !r.code.RightToLeft { - if (0 != (r.code.Anchors&syntax.AnchorBeginning) && r.runtextpos > 0) || - (0 != (r.code.Anchors&syntax.AnchorStart) && r.runtextpos > r.runtextstart) { - r.runtextpos = r.runtextend - return false - } - if 0 != (r.code.Anchors&syntax.AnchorEndZ) && r.runtextpos < r.runtextend-1 { - r.runtextpos = r.runtextend - 1 - } else if 0 != (r.code.Anchors&syntax.AnchorEnd) && r.runtextpos < r.runtextend { - r.runtextpos = r.runtextend - } - } else { - if (0 != (r.code.Anchors&syntax.AnchorEnd) && r.runtextpos < r.runtextend) || - (0 != (r.code.Anchors&syntax.AnchorEndZ) && (r.runtextpos < r.runtextend-1 || - (r.runtextpos == r.runtextend-1 && r.charAt(r.runtextpos) != '\n'))) || - (0 != (r.code.Anchors&syntax.AnchorStart) && r.runtextpos < r.runtextstart) { - r.runtextpos = 0 - return false - } - if 0 != (r.code.Anchors&syntax.AnchorBeginning) && r.runtextpos > 0 { - r.runtextpos = 0 - } - } - - if r.code.BmPrefix != nil { - return r.code.BmPrefix.IsMatch(r.runtext, r.runtextpos, 0, r.runtextend) - } - - return true // found a valid start or end anchor - } else if r.code.BmPrefix != nil { - r.runtextpos = r.code.BmPrefix.Scan(r.runtext, r.runtextpos, 0, r.runtextend) - - if r.runtextpos == -1 { - if r.code.RightToLeft { - r.runtextpos = 0 - } else { - r.runtextpos = r.runtextend - } - return false - } - - return true - } else if r.code.FcPrefix == nil { - return true - } - - r.rightToLeft = r.code.RightToLeft - r.caseInsensitive = r.code.FcPrefix.CaseInsensitive - - set := r.code.FcPrefix.PrefixSet - if set.IsSingleton() { - ch := set.SingletonChar() - for i := r.forwardchars(); i > 0; i-- { - if ch == r.forwardcharnext() { - r.backwardnext() - return true - } - } - } else { - for i := r.forwardchars(); i > 0; i-- { - n := r.forwardcharnext() - //fmt.Printf("%v in %v: %v\n", string(n), set.String(), set.CharIn(n)) - if set.CharIn(n) { - r.backwardnext() - return true - } - } - } - - return false -} - -func (r *runner) initMatch() { - // Use a hashtable'ed Match object if the capture numbers are sparse - - if r.runmatch == nil { - if r.re.caps != nil { - r.runmatch = newMatchSparse(r.re, r.re.caps, r.re.capsize, r.runtext, r.runtextstart) - } else { - r.runmatch = newMatch(r.re, r.re.capsize, r.runtext, r.runtextstart) - } - } else { - r.runmatch.reset(r.runtext, r.runtextstart) - } - - // note we test runcrawl, because it is the last one to be allocated - // If there is an alloc failure in the middle of the three allocations, - // we may still return to reuse this instance, and we want to behave - // as if the allocations didn't occur. (we used to test _trackcount != 0) - - if r.runcrawl != nil { - r.runtrackpos = len(r.runtrack) - r.runstackpos = len(r.runstack) - r.runcrawlpos = len(r.runcrawl) - return - } - - r.initTrackCount() - - tracksize := r.runtrackcount * 8 - stacksize := r.runtrackcount * 8 - - if tracksize < 32 { - tracksize = 32 - } - if stacksize < 16 { - stacksize = 16 - } - - r.runtrack = make([]int, tracksize) - r.runtrackpos = tracksize - - r.runstack = make([]int, stacksize) - r.runstackpos = stacksize - - r.runcrawl = make([]int, 32) - r.runcrawlpos = 32 -} - -func (r *runner) tidyMatch(quick bool) *Match { - if !quick { - match := r.runmatch - - r.runmatch = nil - - match.tidy(r.runtextpos) - return match - } else { - // send back our match -- it's not leaving the package, so it's safe to not clean it up - // this reduces allocs for frequent calls to the "IsMatch" bool-only functions - return r.runmatch - } -} - -// capture captures a subexpression. Note that the -// capnum used here has already been mapped to a non-sparse -// index (by the code generator RegexWriter). -func (r *runner) capture(capnum, start, end int) { - if end < start { - T := end - end = start - start = T - } - - r.crawl(capnum) - r.runmatch.addMatch(capnum, start, end-start) -} - -// transferCapture captures a subexpression. Note that the -// capnum used here has already been mapped to a non-sparse -// index (by the code generator RegexWriter). -func (r *runner) transferCapture(capnum, uncapnum, start, end int) { - var start2, end2 int - - // these are the two intervals that are cancelling each other - - if end < start { - T := end - end = start - start = T - } - - start2 = r.runmatch.matchIndex(uncapnum) - end2 = start2 + r.runmatch.matchLength(uncapnum) - - // The new capture gets the innermost defined interval - - if start >= end2 { - end = start - start = end2 - } else if end <= start2 { - start = start2 - } else { - if end > end2 { - end = end2 - } - if start2 > start { - start = start2 - } - } - - r.crawl(uncapnum) - r.runmatch.balanceMatch(uncapnum) - - if capnum != -1 { - r.crawl(capnum) - r.runmatch.addMatch(capnum, start, end-start) - } -} - -// revert the last capture -func (r *runner) uncapture() { - capnum := r.popcrawl() - r.runmatch.removeMatch(capnum) -} - -//debug - -func (r *runner) dumpState() { - back := "" - if r.operator&syntax.Back != 0 { - back = " Back" - } - if r.operator&syntax.Back2 != 0 { - back += " Back2" - } - fmt.Printf("Text: %v\nTrack: %v\nStack: %v\n %s%s\n\n", - r.textposDescription(), - r.stackDescription(r.runtrack, r.runtrackpos), - r.stackDescription(r.runstack, r.runstackpos), - r.code.OpcodeDescription(r.codepos), - back) -} - -func (r *runner) stackDescription(a []int, index int) string { - buf := &bytes.Buffer{} - - fmt.Fprintf(buf, "%v/%v", len(a)-index, len(a)) - if buf.Len() < 8 { - buf.WriteString(strings.Repeat(" ", 8-buf.Len())) - } - - buf.WriteRune('(') - for i := index; i < len(a); i++ { - if i > index { - buf.WriteRune(' ') - } - - buf.WriteString(strconv.Itoa(a[i])) - } - - buf.WriteRune(')') - - return buf.String() -} - -func (r *runner) textposDescription() string { - buf := &bytes.Buffer{} - - buf.WriteString(strconv.Itoa(r.runtextpos)) - - if buf.Len() < 8 { - buf.WriteString(strings.Repeat(" ", 8-buf.Len())) - } - - if r.runtextpos > 0 { - buf.WriteString(syntax.CharDescription(r.runtext[r.runtextpos-1])) - } else { - buf.WriteRune('^') - } - - buf.WriteRune('>') - - for i := r.runtextpos; i < r.runtextend; i++ { - buf.WriteString(syntax.CharDescription(r.runtext[i])) - } - if buf.Len() >= 64 { - buf.Truncate(61) - buf.WriteString("...") - } else { - buf.WriteRune('$') - } - - return buf.String() -} - -// decide whether the pos -// at the specified index is a boundary or not. It's just not worth -// emitting inline code for this logic. -func (r *runner) isBoundary(index, startpos, endpos int) bool { - return (index > startpos && syntax.IsWordChar(r.runtext[index-1])) != - (index < endpos && syntax.IsWordChar(r.runtext[index])) -} - -func (r *runner) isECMABoundary(index, startpos, endpos int) bool { - return (index > startpos && syntax.IsECMAWordChar(r.runtext[index-1])) != - (index < endpos && syntax.IsECMAWordChar(r.runtext[index])) -} - -func (r *runner) startTimeoutWatch() { - if r.ignoreTimeout { - return - } - r.deadline = makeDeadline(r.timeout) -} - -func (r *runner) checkTimeout() error { - if r.ignoreTimeout || !r.deadline.reached() { - return nil - } - - if r.re.Debug() { - //Debug.WriteLine("") - //Debug.WriteLine("RegEx match timeout occurred!") - //Debug.WriteLine("Specified timeout: " + TimeSpan.FromMilliseconds(_timeout).ToString()) - //Debug.WriteLine("Timeout check frequency: " + TimeoutCheckFrequency) - //Debug.WriteLine("Search pattern: " + _runregex._pattern) - //Debug.WriteLine("Input: " + r.runtext) - //Debug.WriteLine("About to throw RegexMatchTimeoutException.") - } - - return fmt.Errorf("match timeout after %v on input `%v`", r.timeout, string(r.runtext)) -} - -func (r *runner) initTrackCount() { - r.runtrackcount = r.code.TrackCount -} - -// getRunner returns a run to use for matching re. -// It uses the re's runner cache if possible, to avoid -// unnecessary allocation. -func (re *Regexp) getRunner() *runner { - re.muRun.Lock() - if n := len(re.runner); n > 0 { - z := re.runner[n-1] - re.runner = re.runner[:n-1] - re.muRun.Unlock() - return z - } - re.muRun.Unlock() - z := &runner{ - re: re, - code: re.code, - } - return z -} - -// putRunner returns a runner to the re's cache. -// There is no attempt to limit the size of the cache, so it will -// grow to the maximum number of simultaneous matches -// run using re. (The cache empties when re gets garbage collected.) -func (re *Regexp) putRunner(r *runner) { - re.muRun.Lock() - re.runner = append(re.runner, r) - re.muRun.Unlock() -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/charclass.go b/vendor/github.com/dlclark/regexp2/syntax/charclass.go deleted file mode 100644 index 6881a0e2..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/charclass.go +++ /dev/null @@ -1,865 +0,0 @@ -package syntax - -import ( - "bytes" - "encoding/binary" - "fmt" - "sort" - "unicode" - "unicode/utf8" -) - -// CharSet combines start-end rune ranges and unicode categories representing a set of characters -type CharSet struct { - ranges []singleRange - categories []category - sub *CharSet //optional subtractor - negate bool - anything bool -} - -type category struct { - negate bool - cat string -} - -type singleRange struct { - first rune - last rune -} - -const ( - spaceCategoryText = " " - wordCategoryText = "W" -) - -var ( - ecmaSpace = []rune{0x0009, 0x000e, 0x0020, 0x0021, 0x00a0, 0x00a1, 0x1680, 0x1681, 0x2000, 0x200b, 0x2028, 0x202a, 0x202f, 0x2030, 0x205f, 0x2060, 0x3000, 0x3001, 0xfeff, 0xff00} - ecmaWord = []rune{0x0030, 0x003a, 0x0041, 0x005b, 0x005f, 0x0060, 0x0061, 0x007b} - ecmaDigit = []rune{0x0030, 0x003a} - - re2Space = []rune{0x0009, 0x000b, 0x000c, 0x000e, 0x0020, 0x0021} -) - -var ( - AnyClass = getCharSetFromOldString([]rune{0}, false) - ECMAAnyClass = getCharSetFromOldString([]rune{0, 0x000a, 0x000b, 0x000d, 0x000e}, false) - NoneClass = getCharSetFromOldString(nil, false) - ECMAWordClass = getCharSetFromOldString(ecmaWord, false) - NotECMAWordClass = getCharSetFromOldString(ecmaWord, true) - ECMASpaceClass = getCharSetFromOldString(ecmaSpace, false) - NotECMASpaceClass = getCharSetFromOldString(ecmaSpace, true) - ECMADigitClass = getCharSetFromOldString(ecmaDigit, false) - NotECMADigitClass = getCharSetFromOldString(ecmaDigit, true) - - WordClass = getCharSetFromCategoryString(false, false, wordCategoryText) - NotWordClass = getCharSetFromCategoryString(true, false, wordCategoryText) - SpaceClass = getCharSetFromCategoryString(false, false, spaceCategoryText) - NotSpaceClass = getCharSetFromCategoryString(true, false, spaceCategoryText) - DigitClass = getCharSetFromCategoryString(false, false, "Nd") - NotDigitClass = getCharSetFromCategoryString(false, true, "Nd") - - RE2SpaceClass = getCharSetFromOldString(re2Space, false) - NotRE2SpaceClass = getCharSetFromOldString(re2Space, true) -) - -var unicodeCategories = func() map[string]*unicode.RangeTable { - retVal := make(map[string]*unicode.RangeTable) - for k, v := range unicode.Scripts { - retVal[k] = v - } - for k, v := range unicode.Categories { - retVal[k] = v - } - for k, v := range unicode.Properties { - retVal[k] = v - } - return retVal -}() - -func getCharSetFromCategoryString(negateSet bool, negateCat bool, cats ...string) func() *CharSet { - if negateCat && negateSet { - panic("BUG! You should only negate the set OR the category in a constant setup, but not both") - } - - c := CharSet{negate: negateSet} - - c.categories = make([]category, len(cats)) - for i, cat := range cats { - c.categories[i] = category{cat: cat, negate: negateCat} - } - return func() *CharSet { - //make a copy each time - local := c - //return that address - return &local - } -} - -func getCharSetFromOldString(setText []rune, negate bool) func() *CharSet { - c := CharSet{} - if len(setText) > 0 { - fillFirst := false - l := len(setText) - if negate { - if setText[0] == 0 { - setText = setText[1:] - } else { - l++ - fillFirst = true - } - } - - if l%2 == 0 { - c.ranges = make([]singleRange, l/2) - } else { - c.ranges = make([]singleRange, l/2+1) - } - - first := true - if fillFirst { - c.ranges[0] = singleRange{first: 0} - first = false - } - - i := 0 - for _, r := range setText { - if first { - // lower bound in a new range - c.ranges[i] = singleRange{first: r} - first = false - } else { - c.ranges[i].last = r - 1 - i++ - first = true - } - } - if !first { - c.ranges[i].last = utf8.MaxRune - } - } - - return func() *CharSet { - local := c - return &local - } -} - -// Copy makes a deep copy to prevent accidental mutation of a set -func (c CharSet) Copy() CharSet { - ret := CharSet{ - anything: c.anything, - negate: c.negate, - } - - ret.ranges = append(ret.ranges, c.ranges...) - ret.categories = append(ret.categories, c.categories...) - - if c.sub != nil { - sub := c.sub.Copy() - ret.sub = &sub - } - - return ret -} - -// gets a human-readable description for a set string -func (c CharSet) String() string { - buf := &bytes.Buffer{} - buf.WriteRune('[') - - if c.IsNegated() { - buf.WriteRune('^') - } - - for _, r := range c.ranges { - - buf.WriteString(CharDescription(r.first)) - if r.first != r.last { - if r.last-r.first != 1 { - //groups that are 1 char apart skip the dash - buf.WriteRune('-') - } - buf.WriteString(CharDescription(r.last)) - } - } - - for _, c := range c.categories { - buf.WriteString(c.String()) - } - - if c.sub != nil { - buf.WriteRune('-') - buf.WriteString(c.sub.String()) - } - - buf.WriteRune(']') - - return buf.String() -} - -// mapHashFill converts a charset into a buffer for use in maps -func (c CharSet) mapHashFill(buf *bytes.Buffer) { - if c.negate { - buf.WriteByte(0) - } else { - buf.WriteByte(1) - } - - binary.Write(buf, binary.LittleEndian, len(c.ranges)) - binary.Write(buf, binary.LittleEndian, len(c.categories)) - for _, r := range c.ranges { - buf.WriteRune(r.first) - buf.WriteRune(r.last) - } - for _, ct := range c.categories { - buf.WriteString(ct.cat) - if ct.negate { - buf.WriteByte(1) - } else { - buf.WriteByte(0) - } - } - - if c.sub != nil { - c.sub.mapHashFill(buf) - } -} - -// CharIn returns true if the rune is in our character set (either ranges or categories). -// It handles negations and subtracted sub-charsets. -func (c CharSet) CharIn(ch rune) bool { - val := false - // in s && !s.subtracted - - //check ranges - for _, r := range c.ranges { - if ch < r.first { - continue - } - if ch <= r.last { - val = true - break - } - } - - //check categories if we haven't already found a range - if !val && len(c.categories) > 0 { - for _, ct := range c.categories { - // special categories...then unicode - if ct.cat == spaceCategoryText { - if unicode.IsSpace(ch) { - // we found a space so we're done - // negate means this is a "bad" thing - val = !ct.negate - break - } else if ct.negate { - val = true - break - } - } else if ct.cat == wordCategoryText { - if IsWordChar(ch) { - val = !ct.negate - break - } else if ct.negate { - val = true - break - } - } else if unicode.Is(unicodeCategories[ct.cat], ch) { - // if we're in this unicode category then we're done - // if negate=true on this category then we "failed" our test - // otherwise we're good that we found it - val = !ct.negate - break - } else if ct.negate { - val = true - break - } - } - } - - // negate the whole char set - if c.negate { - val = !val - } - - // get subtracted recurse - if val && c.sub != nil { - val = !c.sub.CharIn(ch) - } - - //log.Printf("Char '%v' in %v == %v", string(ch), c.String(), val) - return val -} - -func (c category) String() string { - switch c.cat { - case spaceCategoryText: - if c.negate { - return "\\S" - } - return "\\s" - case wordCategoryText: - if c.negate { - return "\\W" - } - return "\\w" - } - if _, ok := unicodeCategories[c.cat]; ok { - - if c.negate { - return "\\P{" + c.cat + "}" - } - return "\\p{" + c.cat + "}" - } - return "Unknown category: " + c.cat -} - -// CharDescription Produces a human-readable description for a single character. -func CharDescription(ch rune) string { - /*if ch == '\\' { - return "\\\\" - } - - if ch > ' ' && ch <= '~' { - return string(ch) - } else if ch == '\n' { - return "\\n" - } else if ch == ' ' { - return "\\ " - }*/ - - b := &bytes.Buffer{} - escape(b, ch, false) //fmt.Sprintf("%U", ch) - return b.String() -} - -// According to UTS#18 Unicode Regular Expressions (http://www.unicode.org/reports/tr18/) -// RL 1.4 Simple Word Boundaries The class of includes all Alphabetic -// values from the Unicode character database, from UnicodeData.txt [UData], plus the U+200C -// ZERO WIDTH NON-JOINER and U+200D ZERO WIDTH JOINER. -func IsWordChar(r rune) bool { - //"L", "Mn", "Nd", "Pc" - return unicode.In(r, - unicode.Categories["L"], unicode.Categories["Mn"], - unicode.Categories["Nd"], unicode.Categories["Pc"]) || r == '\u200D' || r == '\u200C' - //return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_' -} - -func IsECMAWordChar(r rune) bool { - return unicode.In(r, - unicode.Categories["L"], unicode.Categories["Mn"], - unicode.Categories["Nd"], unicode.Categories["Pc"]) - - //return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_' -} - -// SingletonChar will return the char from the first range without validation. -// It assumes you have checked for IsSingleton or IsSingletonInverse and will panic given bad input -func (c CharSet) SingletonChar() rune { - return c.ranges[0].first -} - -func (c CharSet) IsSingleton() bool { - return !c.negate && //negated is multiple chars - len(c.categories) == 0 && len(c.ranges) == 1 && // multiple ranges and unicode classes represent multiple chars - c.sub == nil && // subtraction means we've got multiple chars - c.ranges[0].first == c.ranges[0].last // first and last equal means we're just 1 char -} - -func (c CharSet) IsSingletonInverse() bool { - return c.negate && //same as above, but requires negated - len(c.categories) == 0 && len(c.ranges) == 1 && // multiple ranges and unicode classes represent multiple chars - c.sub == nil && // subtraction means we've got multiple chars - c.ranges[0].first == c.ranges[0].last // first and last equal means we're just 1 char -} - -func (c CharSet) IsMergeable() bool { - return !c.IsNegated() && !c.HasSubtraction() -} - -func (c CharSet) IsNegated() bool { - return c.negate -} - -func (c CharSet) HasSubtraction() bool { - return c.sub != nil -} - -func (c CharSet) IsEmpty() bool { - return len(c.ranges) == 0 && len(c.categories) == 0 && c.sub == nil -} - -func (c *CharSet) addDigit(ecma, negate bool, pattern string) { - if ecma { - if negate { - c.addRanges(NotECMADigitClass().ranges) - } else { - c.addRanges(ECMADigitClass().ranges) - } - } else { - c.addCategories(category{cat: "Nd", negate: negate}) - } -} - -func (c *CharSet) addChar(ch rune) { - c.addRange(ch, ch) -} - -func (c *CharSet) addSpace(ecma, re2, negate bool) { - if ecma { - if negate { - c.addRanges(NotECMASpaceClass().ranges) - } else { - c.addRanges(ECMASpaceClass().ranges) - } - } else if re2 { - if negate { - c.addRanges(NotRE2SpaceClass().ranges) - } else { - c.addRanges(RE2SpaceClass().ranges) - } - } else { - c.addCategories(category{cat: spaceCategoryText, negate: negate}) - } -} - -func (c *CharSet) addWord(ecma, negate bool) { - if ecma { - if negate { - c.addRanges(NotECMAWordClass().ranges) - } else { - c.addRanges(ECMAWordClass().ranges) - } - } else { - c.addCategories(category{cat: wordCategoryText, negate: negate}) - } -} - -// Add set ranges and categories into ours -- no deduping or anything -func (c *CharSet) addSet(set CharSet) { - if c.anything { - return - } - if set.anything { - c.makeAnything() - return - } - // just append here to prevent double-canon - c.ranges = append(c.ranges, set.ranges...) - c.addCategories(set.categories...) - c.canonicalize() -} - -func (c *CharSet) makeAnything() { - c.anything = true - c.categories = []category{} - c.ranges = AnyClass().ranges -} - -func (c *CharSet) addCategories(cats ...category) { - // don't add dupes and remove positive+negative - if c.anything { - // if we've had a previous positive+negative group then - // just return, we're as broad as we can get - return - } - - for _, ct := range cats { - found := false - for _, ct2 := range c.categories { - if ct.cat == ct2.cat { - if ct.negate != ct2.negate { - // oposite negations...this mean we just - // take us as anything and move on - c.makeAnything() - return - } - found = true - break - } - } - - if !found { - c.categories = append(c.categories, ct) - } - } -} - -// Merges new ranges to our own -func (c *CharSet) addRanges(ranges []singleRange) { - if c.anything { - return - } - c.ranges = append(c.ranges, ranges...) - c.canonicalize() -} - -// Merges everything but the new ranges into our own -func (c *CharSet) addNegativeRanges(ranges []singleRange) { - if c.anything { - return - } - - var hi rune - - // convert incoming ranges into opposites, assume they are in order - for _, r := range ranges { - if hi < r.first { - c.ranges = append(c.ranges, singleRange{hi, r.first - 1}) - } - hi = r.last + 1 - } - - if hi < utf8.MaxRune { - c.ranges = append(c.ranges, singleRange{hi, utf8.MaxRune}) - } - - c.canonicalize() -} - -func isValidUnicodeCat(catName string) bool { - _, ok := unicodeCategories[catName] - return ok -} - -func (c *CharSet) addCategory(categoryName string, negate, caseInsensitive bool, pattern string) { - if !isValidUnicodeCat(categoryName) { - // unknown unicode category, script, or property "blah" - panic(fmt.Errorf("Unknown unicode category, script, or property '%v'", categoryName)) - - } - - if caseInsensitive && (categoryName == "Ll" || categoryName == "Lu" || categoryName == "Lt") { - // when RegexOptions.IgnoreCase is specified then {Ll} {Lu} and {Lt} cases should all match - c.addCategories( - category{cat: "Ll", negate: negate}, - category{cat: "Lu", negate: negate}, - category{cat: "Lt", negate: negate}) - } - c.addCategories(category{cat: categoryName, negate: negate}) -} - -func (c *CharSet) addSubtraction(sub *CharSet) { - c.sub = sub -} - -func (c *CharSet) addRange(chMin, chMax rune) { - c.ranges = append(c.ranges, singleRange{first: chMin, last: chMax}) - c.canonicalize() -} - -func (c *CharSet) addNamedASCII(name string, negate bool) bool { - var rs []singleRange - - switch name { - case "alnum": - rs = []singleRange{singleRange{'0', '9'}, singleRange{'A', 'Z'}, singleRange{'a', 'z'}} - case "alpha": - rs = []singleRange{singleRange{'A', 'Z'}, singleRange{'a', 'z'}} - case "ascii": - rs = []singleRange{singleRange{0, 0x7f}} - case "blank": - rs = []singleRange{singleRange{'\t', '\t'}, singleRange{' ', ' '}} - case "cntrl": - rs = []singleRange{singleRange{0, 0x1f}, singleRange{0x7f, 0x7f}} - case "digit": - c.addDigit(false, negate, "") - case "graph": - rs = []singleRange{singleRange{'!', '~'}} - case "lower": - rs = []singleRange{singleRange{'a', 'z'}} - case "print": - rs = []singleRange{singleRange{' ', '~'}} - case "punct": //[!-/:-@[-`{-~] - rs = []singleRange{singleRange{'!', '/'}, singleRange{':', '@'}, singleRange{'[', '`'}, singleRange{'{', '~'}} - case "space": - c.addSpace(true, false, negate) - case "upper": - rs = []singleRange{singleRange{'A', 'Z'}} - case "word": - c.addWord(true, negate) - case "xdigit": - rs = []singleRange{singleRange{'0', '9'}, singleRange{'A', 'F'}, singleRange{'a', 'f'}} - default: - return false - } - - if len(rs) > 0 { - if negate { - c.addNegativeRanges(rs) - } else { - c.addRanges(rs) - } - } - - return true -} - -type singleRangeSorter []singleRange - -func (p singleRangeSorter) Len() int { return len(p) } -func (p singleRangeSorter) Less(i, j int) bool { return p[i].first < p[j].first } -func (p singleRangeSorter) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -// Logic to reduce a character class to a unique, sorted form. -func (c *CharSet) canonicalize() { - var i, j int - var last rune - - // - // Find and eliminate overlapping or abutting ranges - // - - if len(c.ranges) > 1 { - sort.Sort(singleRangeSorter(c.ranges)) - - done := false - - for i, j = 1, 0; ; i++ { - for last = c.ranges[j].last; ; i++ { - if i == len(c.ranges) || last == utf8.MaxRune { - done = true - break - } - - CurrentRange := c.ranges[i] - if CurrentRange.first > last+1 { - break - } - - if last < CurrentRange.last { - last = CurrentRange.last - } - } - - c.ranges[j] = singleRange{first: c.ranges[j].first, last: last} - - j++ - - if done { - break - } - - if j < i { - c.ranges[j] = c.ranges[i] - } - } - - c.ranges = append(c.ranges[:j], c.ranges[len(c.ranges):]...) - } -} - -// Adds to the class any lowercase versions of characters already -// in the class. Used for case-insensitivity. -func (c *CharSet) addLowercase() { - if c.anything { - return - } - toAdd := []singleRange{} - for i := 0; i < len(c.ranges); i++ { - r := c.ranges[i] - if r.first == r.last { - lower := unicode.ToLower(r.first) - c.ranges[i] = singleRange{first: lower, last: lower} - } else { - toAdd = append(toAdd, r) - } - } - - for _, r := range toAdd { - c.addLowercaseRange(r.first, r.last) - } - c.canonicalize() -} - -/************************************************************************** - Let U be the set of Unicode character values and let L be the lowercase - function, mapping from U to U. To perform case insensitive matching of - character sets, we need to be able to map an interval I in U, say - - I = [chMin, chMax] = { ch : chMin <= ch <= chMax } - - to a set A such that A contains L(I) and A is contained in the union of - I and L(I). - - The table below partitions U into intervals on which L is non-decreasing. - Thus, for any interval J = [a, b] contained in one of these intervals, - L(J) is contained in [L(a), L(b)]. - - It is also true that for any such J, [L(a), L(b)] is contained in the - union of J and L(J). This does not follow from L being non-decreasing on - these intervals. It follows from the nature of the L on each interval. - On each interval, L has one of the following forms: - - (1) L(ch) = constant (LowercaseSet) - (2) L(ch) = ch + offset (LowercaseAdd) - (3) L(ch) = ch | 1 (LowercaseBor) - (4) L(ch) = ch + (ch & 1) (LowercaseBad) - - It is easy to verify that for any of these forms [L(a), L(b)] is - contained in the union of [a, b] and L([a, b]). -***************************************************************************/ - -const ( - LowercaseSet = 0 // Set to arg. - LowercaseAdd = 1 // Add arg. - LowercaseBor = 2 // Bitwise or with 1. - LowercaseBad = 3 // Bitwise and with 1 and add original. -) - -type lcMap struct { - chMin, chMax rune - op, data int32 -} - -var lcTable = []lcMap{ - lcMap{'\u0041', '\u005A', LowercaseAdd, 32}, - lcMap{'\u00C0', '\u00DE', LowercaseAdd, 32}, - lcMap{'\u0100', '\u012E', LowercaseBor, 0}, - lcMap{'\u0130', '\u0130', LowercaseSet, 0x0069}, - lcMap{'\u0132', '\u0136', LowercaseBor, 0}, - lcMap{'\u0139', '\u0147', LowercaseBad, 0}, - lcMap{'\u014A', '\u0176', LowercaseBor, 0}, - lcMap{'\u0178', '\u0178', LowercaseSet, 0x00FF}, - lcMap{'\u0179', '\u017D', LowercaseBad, 0}, - lcMap{'\u0181', '\u0181', LowercaseSet, 0x0253}, - lcMap{'\u0182', '\u0184', LowercaseBor, 0}, - lcMap{'\u0186', '\u0186', LowercaseSet, 0x0254}, - lcMap{'\u0187', '\u0187', LowercaseSet, 0x0188}, - lcMap{'\u0189', '\u018A', LowercaseAdd, 205}, - lcMap{'\u018B', '\u018B', LowercaseSet, 0x018C}, - lcMap{'\u018E', '\u018E', LowercaseSet, 0x01DD}, - lcMap{'\u018F', '\u018F', LowercaseSet, 0x0259}, - lcMap{'\u0190', '\u0190', LowercaseSet, 0x025B}, - lcMap{'\u0191', '\u0191', LowercaseSet, 0x0192}, - lcMap{'\u0193', '\u0193', LowercaseSet, 0x0260}, - lcMap{'\u0194', '\u0194', LowercaseSet, 0x0263}, - lcMap{'\u0196', '\u0196', LowercaseSet, 0x0269}, - lcMap{'\u0197', '\u0197', LowercaseSet, 0x0268}, - lcMap{'\u0198', '\u0198', LowercaseSet, 0x0199}, - lcMap{'\u019C', '\u019C', LowercaseSet, 0x026F}, - lcMap{'\u019D', '\u019D', LowercaseSet, 0x0272}, - lcMap{'\u019F', '\u019F', LowercaseSet, 0x0275}, - lcMap{'\u01A0', '\u01A4', LowercaseBor, 0}, - lcMap{'\u01A7', '\u01A7', LowercaseSet, 0x01A8}, - lcMap{'\u01A9', '\u01A9', LowercaseSet, 0x0283}, - lcMap{'\u01AC', '\u01AC', LowercaseSet, 0x01AD}, - lcMap{'\u01AE', '\u01AE', LowercaseSet, 0x0288}, - lcMap{'\u01AF', '\u01AF', LowercaseSet, 0x01B0}, - lcMap{'\u01B1', '\u01B2', LowercaseAdd, 217}, - lcMap{'\u01B3', '\u01B5', LowercaseBad, 0}, - lcMap{'\u01B7', '\u01B7', LowercaseSet, 0x0292}, - lcMap{'\u01B8', '\u01B8', LowercaseSet, 0x01B9}, - lcMap{'\u01BC', '\u01BC', LowercaseSet, 0x01BD}, - lcMap{'\u01C4', '\u01C5', LowercaseSet, 0x01C6}, - lcMap{'\u01C7', '\u01C8', LowercaseSet, 0x01C9}, - lcMap{'\u01CA', '\u01CB', LowercaseSet, 0x01CC}, - lcMap{'\u01CD', '\u01DB', LowercaseBad, 0}, - lcMap{'\u01DE', '\u01EE', LowercaseBor, 0}, - lcMap{'\u01F1', '\u01F2', LowercaseSet, 0x01F3}, - lcMap{'\u01F4', '\u01F4', LowercaseSet, 0x01F5}, - lcMap{'\u01FA', '\u0216', LowercaseBor, 0}, - lcMap{'\u0386', '\u0386', LowercaseSet, 0x03AC}, - lcMap{'\u0388', '\u038A', LowercaseAdd, 37}, - lcMap{'\u038C', '\u038C', LowercaseSet, 0x03CC}, - lcMap{'\u038E', '\u038F', LowercaseAdd, 63}, - lcMap{'\u0391', '\u03AB', LowercaseAdd, 32}, - lcMap{'\u03E2', '\u03EE', LowercaseBor, 0}, - lcMap{'\u0401', '\u040F', LowercaseAdd, 80}, - lcMap{'\u0410', '\u042F', LowercaseAdd, 32}, - lcMap{'\u0460', '\u0480', LowercaseBor, 0}, - lcMap{'\u0490', '\u04BE', LowercaseBor, 0}, - lcMap{'\u04C1', '\u04C3', LowercaseBad, 0}, - lcMap{'\u04C7', '\u04C7', LowercaseSet, 0x04C8}, - lcMap{'\u04CB', '\u04CB', LowercaseSet, 0x04CC}, - lcMap{'\u04D0', '\u04EA', LowercaseBor, 0}, - lcMap{'\u04EE', '\u04F4', LowercaseBor, 0}, - lcMap{'\u04F8', '\u04F8', LowercaseSet, 0x04F9}, - lcMap{'\u0531', '\u0556', LowercaseAdd, 48}, - lcMap{'\u10A0', '\u10C5', LowercaseAdd, 48}, - lcMap{'\u1E00', '\u1EF8', LowercaseBor, 0}, - lcMap{'\u1F08', '\u1F0F', LowercaseAdd, -8}, - lcMap{'\u1F18', '\u1F1F', LowercaseAdd, -8}, - lcMap{'\u1F28', '\u1F2F', LowercaseAdd, -8}, - lcMap{'\u1F38', '\u1F3F', LowercaseAdd, -8}, - lcMap{'\u1F48', '\u1F4D', LowercaseAdd, -8}, - lcMap{'\u1F59', '\u1F59', LowercaseSet, 0x1F51}, - lcMap{'\u1F5B', '\u1F5B', LowercaseSet, 0x1F53}, - lcMap{'\u1F5D', '\u1F5D', LowercaseSet, 0x1F55}, - lcMap{'\u1F5F', '\u1F5F', LowercaseSet, 0x1F57}, - lcMap{'\u1F68', '\u1F6F', LowercaseAdd, -8}, - lcMap{'\u1F88', '\u1F8F', LowercaseAdd, -8}, - lcMap{'\u1F98', '\u1F9F', LowercaseAdd, -8}, - lcMap{'\u1FA8', '\u1FAF', LowercaseAdd, -8}, - lcMap{'\u1FB8', '\u1FB9', LowercaseAdd, -8}, - lcMap{'\u1FBA', '\u1FBB', LowercaseAdd, -74}, - lcMap{'\u1FBC', '\u1FBC', LowercaseSet, 0x1FB3}, - lcMap{'\u1FC8', '\u1FCB', LowercaseAdd, -86}, - lcMap{'\u1FCC', '\u1FCC', LowercaseSet, 0x1FC3}, - lcMap{'\u1FD8', '\u1FD9', LowercaseAdd, -8}, - lcMap{'\u1FDA', '\u1FDB', LowercaseAdd, -100}, - lcMap{'\u1FE8', '\u1FE9', LowercaseAdd, -8}, - lcMap{'\u1FEA', '\u1FEB', LowercaseAdd, -112}, - lcMap{'\u1FEC', '\u1FEC', LowercaseSet, 0x1FE5}, - lcMap{'\u1FF8', '\u1FF9', LowercaseAdd, -128}, - lcMap{'\u1FFA', '\u1FFB', LowercaseAdd, -126}, - lcMap{'\u1FFC', '\u1FFC', LowercaseSet, 0x1FF3}, - lcMap{'\u2160', '\u216F', LowercaseAdd, 16}, - lcMap{'\u24B6', '\u24D0', LowercaseAdd, 26}, - lcMap{'\uFF21', '\uFF3A', LowercaseAdd, 32}, -} - -func (c *CharSet) addLowercaseRange(chMin, chMax rune) { - var i, iMax, iMid int - var chMinT, chMaxT rune - var lc lcMap - - for i, iMax = 0, len(lcTable); i < iMax; { - iMid = (i + iMax) / 2 - if lcTable[iMid].chMax < chMin { - i = iMid + 1 - } else { - iMax = iMid - } - } - - for ; i < len(lcTable); i++ { - lc = lcTable[i] - if lc.chMin > chMax { - return - } - chMinT = lc.chMin - if chMinT < chMin { - chMinT = chMin - } - - chMaxT = lc.chMax - if chMaxT > chMax { - chMaxT = chMax - } - - switch lc.op { - case LowercaseSet: - chMinT = rune(lc.data) - chMaxT = rune(lc.data) - break - case LowercaseAdd: - chMinT += lc.data - chMaxT += lc.data - break - case LowercaseBor: - chMinT |= 1 - chMaxT |= 1 - break - case LowercaseBad: - chMinT += (chMinT & 1) - chMaxT += (chMaxT & 1) - break - } - - if chMinT < chMin || chMaxT > chMax { - c.addRange(chMinT, chMaxT) - } - } -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/code.go b/vendor/github.com/dlclark/regexp2/syntax/code.go deleted file mode 100644 index 686e822a..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/code.go +++ /dev/null @@ -1,274 +0,0 @@ -package syntax - -import ( - "bytes" - "fmt" - "math" -) - -// similar to prog.go in the go regex package...also with comment 'may not belong in this package' - -// File provides operator constants for use by the Builder and the Machine. - -// Implementation notes: -// -// Regexps are built into RegexCodes, which contain an operation array, -// a string table, and some constants. -// -// Each operation is one of the codes below, followed by the integer -// operands specified for each op. -// -// Strings and sets are indices into a string table. - -type InstOp int - -const ( - // lef/back operands description - - Onerep InstOp = 0 // lef,back char,min,max a {n} - Notonerep = 1 // lef,back char,min,max .{n} - Setrep = 2 // lef,back set,min,max [\d]{n} - - Oneloop = 3 // lef,back char,min,max a {,n} - Notoneloop = 4 // lef,back char,min,max .{,n} - Setloop = 5 // lef,back set,min,max [\d]{,n} - - Onelazy = 6 // lef,back char,min,max a {,n}? - Notonelazy = 7 // lef,back char,min,max .{,n}? - Setlazy = 8 // lef,back set,min,max [\d]{,n}? - - One = 9 // lef char a - Notone = 10 // lef char [^a] - Set = 11 // lef set [a-z\s] \w \s \d - - Multi = 12 // lef string abcd - Ref = 13 // lef group \# - - Bol = 14 // ^ - Eol = 15 // $ - Boundary = 16 // \b - Nonboundary = 17 // \B - Beginning = 18 // \A - Start = 19 // \G - EndZ = 20 // \Z - End = 21 // \Z - - Nothing = 22 // Reject! - - // Primitive control structures - - Lazybranch = 23 // back jump straight first - Branchmark = 24 // back jump branch first for loop - Lazybranchmark = 25 // back jump straight first for loop - Nullcount = 26 // back val set counter, null mark - Setcount = 27 // back val set counter, make mark - Branchcount = 28 // back jump,limit branch++ if zero<=c impl group slots - Capsize int // number of impl group slots - FcPrefix *Prefix // the set of candidate first characters (may be null) - BmPrefix *BmPrefix // the fixed prefix string as a Boyer-Moore machine (may be null) - Anchors AnchorLoc // the set of zero-length start anchors (RegexFCD.Bol, etc) - RightToLeft bool // true if right to left -} - -func opcodeBacktracks(op InstOp) bool { - op &= Mask - - switch op { - case Oneloop, Notoneloop, Setloop, Onelazy, Notonelazy, Setlazy, Lazybranch, Branchmark, Lazybranchmark, - Nullcount, Setcount, Branchcount, Lazybranchcount, Setmark, Capturemark, Getmark, Setjump, Backjump, - Forejump, Goto: - return true - - default: - return false - } -} - -func opcodeSize(op InstOp) int { - op &= Mask - - switch op { - case Nothing, Bol, Eol, Boundary, Nonboundary, ECMABoundary, NonECMABoundary, Beginning, Start, EndZ, - End, Nullmark, Setmark, Getmark, Setjump, Backjump, Forejump, Stop: - return 1 - - case One, Notone, Multi, Ref, Testref, Goto, Nullcount, Setcount, Lazybranch, Branchmark, Lazybranchmark, - Prune, Set: - return 2 - - case Capturemark, Branchcount, Lazybranchcount, Onerep, Notonerep, Oneloop, Notoneloop, Onelazy, Notonelazy, - Setlazy, Setrep, Setloop: - return 3 - - default: - panic(fmt.Errorf("Unexpected op code: %v", op)) - } -} - -var codeStr = []string{ - "Onerep", "Notonerep", "Setrep", - "Oneloop", "Notoneloop", "Setloop", - "Onelazy", "Notonelazy", "Setlazy", - "One", "Notone", "Set", - "Multi", "Ref", - "Bol", "Eol", "Boundary", "Nonboundary", "Beginning", "Start", "EndZ", "End", - "Nothing", - "Lazybranch", "Branchmark", "Lazybranchmark", - "Nullcount", "Setcount", "Branchcount", "Lazybranchcount", - "Nullmark", "Setmark", "Capturemark", "Getmark", - "Setjump", "Backjump", "Forejump", "Testref", "Goto", - "Prune", "Stop", - "ECMABoundary", "NonECMABoundary", -} - -func operatorDescription(op InstOp) string { - desc := codeStr[op&Mask] - if (op & Ci) != 0 { - desc += "-Ci" - } - if (op & Rtl) != 0 { - desc += "-Rtl" - } - if (op & Back) != 0 { - desc += "-Back" - } - if (op & Back2) != 0 { - desc += "-Back2" - } - - return desc -} - -// OpcodeDescription is a humman readable string of the specific offset -func (c *Code) OpcodeDescription(offset int) string { - buf := &bytes.Buffer{} - - op := InstOp(c.Codes[offset]) - fmt.Fprintf(buf, "%06d ", offset) - - if opcodeBacktracks(op & Mask) { - buf.WriteString("*") - } else { - buf.WriteString(" ") - } - buf.WriteString(operatorDescription(op)) - buf.WriteString("(") - op &= Mask - - switch op { - case One, Notone, Onerep, Notonerep, Oneloop, Notoneloop, Onelazy, Notonelazy: - buf.WriteString("Ch = ") - buf.WriteString(CharDescription(rune(c.Codes[offset+1]))) - - case Set, Setrep, Setloop, Setlazy: - buf.WriteString("Set = ") - buf.WriteString(c.Sets[c.Codes[offset+1]].String()) - - case Multi: - fmt.Fprintf(buf, "String = %s", string(c.Strings[c.Codes[offset+1]])) - - case Ref, Testref: - fmt.Fprintf(buf, "Index = %d", c.Codes[offset+1]) - - case Capturemark: - fmt.Fprintf(buf, "Index = %d", c.Codes[offset+1]) - if c.Codes[offset+2] != -1 { - fmt.Fprintf(buf, ", Unindex = %d", c.Codes[offset+2]) - } - - case Nullcount, Setcount: - fmt.Fprintf(buf, "Value = %d", c.Codes[offset+1]) - - case Goto, Lazybranch, Branchmark, Lazybranchmark, Branchcount, Lazybranchcount: - fmt.Fprintf(buf, "Addr = %d", c.Codes[offset+1]) - } - - switch op { - case Onerep, Notonerep, Oneloop, Notoneloop, Onelazy, Notonelazy, Setrep, Setloop, Setlazy: - buf.WriteString(", Rep = ") - if c.Codes[offset+2] == math.MaxInt32 { - buf.WriteString("inf") - } else { - fmt.Fprintf(buf, "%d", c.Codes[offset+2]) - } - - case Branchcount, Lazybranchcount: - buf.WriteString(", Limit = ") - if c.Codes[offset+2] == math.MaxInt32 { - buf.WriteString("inf") - } else { - fmt.Fprintf(buf, "%d", c.Codes[offset+2]) - } - - } - - buf.WriteString(")") - - return buf.String() -} - -func (c *Code) Dump() string { - buf := &bytes.Buffer{} - - if c.RightToLeft { - fmt.Fprintln(buf, "Direction: right-to-left") - } else { - fmt.Fprintln(buf, "Direction: left-to-right") - } - if c.FcPrefix == nil { - fmt.Fprintln(buf, "Firstchars: n/a") - } else { - fmt.Fprintf(buf, "Firstchars: %v\n", c.FcPrefix.PrefixSet.String()) - } - - if c.BmPrefix == nil { - fmt.Fprintln(buf, "Prefix: n/a") - } else { - fmt.Fprintf(buf, "Prefix: %v\n", Escape(c.BmPrefix.String())) - } - - fmt.Fprintf(buf, "Anchors: %v\n", c.Anchors) - fmt.Fprintln(buf) - - if c.BmPrefix != nil { - fmt.Fprintln(buf, "BoyerMoore:") - fmt.Fprintln(buf, c.BmPrefix.Dump(" ")) - } - for i := 0; i < len(c.Codes); i += opcodeSize(InstOp(c.Codes[i])) { - fmt.Fprintln(buf, c.OpcodeDescription(i)) - } - - return buf.String() -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/escape.go b/vendor/github.com/dlclark/regexp2/syntax/escape.go deleted file mode 100644 index 609df107..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/escape.go +++ /dev/null @@ -1,94 +0,0 @@ -package syntax - -import ( - "bytes" - "strconv" - "strings" - "unicode" -) - -func Escape(input string) string { - b := &bytes.Buffer{} - for _, r := range input { - escape(b, r, false) - } - return b.String() -} - -const meta = `\.+*?()|[]{}^$# ` - -func escape(b *bytes.Buffer, r rune, force bool) { - if unicode.IsPrint(r) { - if strings.IndexRune(meta, r) >= 0 || force { - b.WriteRune('\\') - } - b.WriteRune(r) - return - } - - switch r { - case '\a': - b.WriteString(`\a`) - case '\f': - b.WriteString(`\f`) - case '\n': - b.WriteString(`\n`) - case '\r': - b.WriteString(`\r`) - case '\t': - b.WriteString(`\t`) - case '\v': - b.WriteString(`\v`) - default: - if r < 0x100 { - b.WriteString(`\x`) - s := strconv.FormatInt(int64(r), 16) - if len(s) == 1 { - b.WriteRune('0') - } - b.WriteString(s) - break - } - b.WriteString(`\u`) - b.WriteString(strconv.FormatInt(int64(r), 16)) - } -} - -func Unescape(input string) (string, error) { - idx := strings.IndexRune(input, '\\') - // no slashes means no unescape needed - if idx == -1 { - return input, nil - } - - buf := bytes.NewBufferString(input[:idx]) - // get the runes for the rest of the string -- we're going full parser scan on this - - p := parser{} - p.setPattern(input[idx+1:]) - for { - if p.rightMost() { - return "", p.getErr(ErrIllegalEndEscape) - } - r, err := p.scanCharEscape() - if err != nil { - return "", err - } - buf.WriteRune(r) - // are we done? - if p.rightMost() { - return buf.String(), nil - } - - r = p.moveRightGetChar() - for r != '\\' { - buf.WriteRune(r) - if p.rightMost() { - // we're done, no more slashes - return buf.String(), nil - } - // keep scanning until we get another slash - r = p.moveRightGetChar() - } - } -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/fuzz.go b/vendor/github.com/dlclark/regexp2/syntax/fuzz.go deleted file mode 100644 index ee863866..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/fuzz.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build gofuzz - -package syntax - -// Fuzz is the input point for go-fuzz -func Fuzz(data []byte) int { - sdata := string(data) - tree, err := Parse(sdata, RegexOptions(0)) - if err != nil { - return 0 - } - - // translate it to code - _, err = Write(tree) - if err != nil { - panic(err) - } - - return 1 -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/parser.go b/vendor/github.com/dlclark/regexp2/syntax/parser.go deleted file mode 100644 index b6c3670c..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/parser.go +++ /dev/null @@ -1,2262 +0,0 @@ -package syntax - -import ( - "fmt" - "math" - "os" - "sort" - "strconv" - "unicode" -) - -type RegexOptions int32 - -const ( - IgnoreCase RegexOptions = 0x0001 // "i" - Multiline = 0x0002 // "m" - ExplicitCapture = 0x0004 // "n" - Compiled = 0x0008 // "c" - Singleline = 0x0010 // "s" - IgnorePatternWhitespace = 0x0020 // "x" - RightToLeft = 0x0040 // "r" - Debug = 0x0080 // "d" - ECMAScript = 0x0100 // "e" - RE2 = 0x0200 // RE2 compat mode - Unicode = 0x0400 // "u" -) - -func optionFromCode(ch rune) RegexOptions { - // case-insensitive - switch ch { - case 'i', 'I': - return IgnoreCase - case 'r', 'R': - return RightToLeft - case 'm', 'M': - return Multiline - case 'n', 'N': - return ExplicitCapture - case 's', 'S': - return Singleline - case 'x', 'X': - return IgnorePatternWhitespace - case 'd', 'D': - return Debug - case 'e', 'E': - return ECMAScript - case 'u', 'U': - return Unicode - default: - return 0 - } -} - -// An Error describes a failure to parse a regular expression -// and gives the offending expression. -type Error struct { - Code ErrorCode - Expr string - Args []interface{} -} - -func (e *Error) Error() string { - if len(e.Args) == 0 { - return "error parsing regexp: " + e.Code.String() + " in `" + e.Expr + "`" - } - return "error parsing regexp: " + fmt.Sprintf(e.Code.String(), e.Args...) + " in `" + e.Expr + "`" -} - -// An ErrorCode describes a failure to parse a regular expression. -type ErrorCode string - -const ( - // internal issue - ErrInternalError ErrorCode = "regexp/syntax: internal error" - // Parser errors - ErrUnterminatedComment = "unterminated comment" - ErrInvalidCharRange = "invalid character class range" - ErrInvalidRepeatSize = "invalid repeat count" - ErrInvalidUTF8 = "invalid UTF-8" - ErrCaptureGroupOutOfRange = "capture group number out of range" - ErrUnexpectedParen = "unexpected )" - ErrMissingParen = "missing closing )" - ErrMissingBrace = "missing closing }" - ErrInvalidRepeatOp = "invalid nested repetition operator" - ErrMissingRepeatArgument = "missing argument to repetition operator" - ErrConditionalExpression = "illegal conditional (?(...)) expression" - ErrTooManyAlternates = "too many | in (?()|)" - ErrUnrecognizedGrouping = "unrecognized grouping construct: (%v" - ErrInvalidGroupName = "invalid group name: group names must begin with a word character and have a matching terminator" - ErrCapNumNotZero = "capture number cannot be zero" - ErrUndefinedBackRef = "reference to undefined group number %v" - ErrUndefinedNameRef = "reference to undefined group name %v" - ErrAlternationCantCapture = "alternation conditions do not capture and cannot be named" - ErrAlternationCantHaveComment = "alternation conditions cannot be comments" - ErrMalformedReference = "(?(%v) ) malformed" - ErrUndefinedReference = "(?(%v) ) reference to undefined group" - ErrIllegalEndEscape = "illegal \\ at end of pattern" - ErrMalformedSlashP = "malformed \\p{X} character escape" - ErrIncompleteSlashP = "incomplete \\p{X} character escape" - ErrUnknownSlashP = "unknown unicode category, script, or property '%v'" - ErrUnrecognizedEscape = "unrecognized escape sequence \\%v" - ErrMissingControl = "missing control character" - ErrUnrecognizedControl = "unrecognized control character" - ErrTooFewHex = "insufficient hexadecimal digits" - ErrInvalidHex = "hex values may not be larger than 0x10FFFF" - ErrMalformedNameRef = "malformed \\k<...> named back reference" - ErrBadClassInCharRange = "cannot include class \\%v in character range" - ErrUnterminatedBracket = "unterminated [] set" - ErrSubtractionMustBeLast = "a subtraction must be the last element in a character class" - ErrReversedCharRange = "[%c-%c] range in reverse order" -) - -func (e ErrorCode) String() string { - return string(e) -} - -type parser struct { - stack *regexNode - group *regexNode - alternation *regexNode - concatenation *regexNode - unit *regexNode - - patternRaw string - pattern []rune - - currentPos int - specialCase *unicode.SpecialCase - - autocap int - capcount int - captop int - capsize int - - caps map[int]int - capnames map[string]int - - capnumlist []int - capnamelist []string - - options RegexOptions - optionsStack []RegexOptions - ignoreNextParen bool -} - -const ( - maxValueDiv10 int = math.MaxInt32 / 10 - maxValueMod10 = math.MaxInt32 % 10 -) - -// Parse converts a regex string into a parse tree -func Parse(re string, op RegexOptions) (*RegexTree, error) { - p := parser{ - options: op, - caps: make(map[int]int), - } - p.setPattern(re) - - if err := p.countCaptures(); err != nil { - return nil, err - } - - p.reset(op) - root, err := p.scanRegex() - - if err != nil { - return nil, err - } - tree := &RegexTree{ - root: root, - caps: p.caps, - capnumlist: p.capnumlist, - captop: p.captop, - Capnames: p.capnames, - Caplist: p.capnamelist, - options: op, - } - - if tree.options&Debug > 0 { - os.Stdout.WriteString(tree.Dump()) - } - - return tree, nil -} - -func (p *parser) setPattern(pattern string) { - p.patternRaw = pattern - p.pattern = make([]rune, 0, len(pattern)) - - //populate our rune array to handle utf8 encoding - for _, r := range pattern { - p.pattern = append(p.pattern, r) - } -} -func (p *parser) getErr(code ErrorCode, args ...interface{}) error { - return &Error{Code: code, Expr: p.patternRaw, Args: args} -} - -func (p *parser) noteCaptureSlot(i, pos int) { - if _, ok := p.caps[i]; !ok { - // the rhs of the hashtable isn't used in the parser - p.caps[i] = pos - p.capcount++ - - if p.captop <= i { - if i == math.MaxInt32 { - p.captop = i - } else { - p.captop = i + 1 - } - } - } -} - -func (p *parser) noteCaptureName(name string, pos int) { - if p.capnames == nil { - p.capnames = make(map[string]int) - } - - if _, ok := p.capnames[name]; !ok { - p.capnames[name] = pos - p.capnamelist = append(p.capnamelist, name) - } -} - -func (p *parser) assignNameSlots() { - if p.capnames != nil { - for _, name := range p.capnamelist { - for p.isCaptureSlot(p.autocap) { - p.autocap++ - } - pos := p.capnames[name] - p.capnames[name] = p.autocap - p.noteCaptureSlot(p.autocap, pos) - - p.autocap++ - } - } - - // if the caps array has at least one gap, construct the list of used slots - if p.capcount < p.captop { - p.capnumlist = make([]int, p.capcount) - i := 0 - - for k := range p.caps { - p.capnumlist[i] = k - i++ - } - - sort.Ints(p.capnumlist) - } - - // merge capsnumlist into capnamelist - if p.capnames != nil || p.capnumlist != nil { - var oldcapnamelist []string - var next int - var k int - - if p.capnames == nil { - oldcapnamelist = nil - p.capnames = make(map[string]int) - p.capnamelist = []string{} - next = -1 - } else { - oldcapnamelist = p.capnamelist - p.capnamelist = []string{} - next = p.capnames[oldcapnamelist[0]] - } - - for i := 0; i < p.capcount; i++ { - j := i - if p.capnumlist != nil { - j = p.capnumlist[i] - } - - if next == j { - p.capnamelist = append(p.capnamelist, oldcapnamelist[k]) - k++ - - if k == len(oldcapnamelist) { - next = -1 - } else { - next = p.capnames[oldcapnamelist[k]] - } - - } else { - //feature: culture? - str := strconv.Itoa(j) - p.capnamelist = append(p.capnamelist, str) - p.capnames[str] = j - } - } - } -} - -func (p *parser) consumeAutocap() int { - r := p.autocap - p.autocap++ - return r -} - -// CountCaptures is a prescanner for deducing the slots used for -// captures by doing a partial tokenization of the pattern. -func (p *parser) countCaptures() error { - var ch rune - - p.noteCaptureSlot(0, 0) - - p.autocap = 1 - - for p.charsRight() > 0 { - pos := p.textpos() - ch = p.moveRightGetChar() - switch ch { - case '\\': - if p.charsRight() > 0 { - p.scanBackslash(true) - } - - case '#': - if p.useOptionX() { - p.moveLeft() - p.scanBlank() - } - - case '[': - p.scanCharSet(false, true) - - case ')': - if !p.emptyOptionsStack() { - p.popOptions() - } - - case '(': - if p.charsRight() >= 2 && p.rightChar(1) == '#' && p.rightChar(0) == '?' { - p.moveLeft() - p.scanBlank() - } else { - p.pushOptions() - if p.charsRight() > 0 && p.rightChar(0) == '?' { - // we have (?... - p.moveRight(1) - - if p.charsRight() > 1 && (p.rightChar(0) == '<' || p.rightChar(0) == '\'') { - // named group: (?<... or (?'... - - p.moveRight(1) - ch = p.rightChar(0) - - if ch != '0' && IsWordChar(ch) { - if ch >= '1' && ch <= '9' { - dec, err := p.scanDecimal() - if err != nil { - return err - } - p.noteCaptureSlot(dec, pos) - } else { - p.noteCaptureName(p.scanCapname(), pos) - } - } - } else if p.useRE2() && p.charsRight() > 2 && (p.rightChar(0) == 'P' && p.rightChar(1) == '<') { - // RE2-compat (?P<) - p.moveRight(2) - ch = p.rightChar(0) - if IsWordChar(ch) { - p.noteCaptureName(p.scanCapname(), pos) - } - - } else { - // (?... - - // get the options if it's an option construct (?cimsx-cimsx...) - p.scanOptions() - - if p.charsRight() > 0 { - if p.rightChar(0) == ')' { - // (?cimsx-cimsx) - p.moveRight(1) - p.popKeepOptions() - } else if p.rightChar(0) == '(' { - // alternation construct: (?(foo)yes|no) - // ignore the next paren so we don't capture the condition - p.ignoreNextParen = true - - // break from here so we don't reset ignoreNextParen - continue - } - } - } - } else { - if !p.useOptionN() && !p.ignoreNextParen { - p.noteCaptureSlot(p.consumeAutocap(), pos) - } - } - } - - p.ignoreNextParen = false - - } - } - - p.assignNameSlots() - return nil -} - -func (p *parser) reset(topopts RegexOptions) { - p.currentPos = 0 - p.autocap = 1 - p.ignoreNextParen = false - - if len(p.optionsStack) > 0 { - p.optionsStack = p.optionsStack[:0] - } - - p.options = topopts - p.stack = nil -} - -func (p *parser) scanRegex() (*regexNode, error) { - ch := '@' // nonspecial ch, means at beginning - isQuant := false - - p.startGroup(newRegexNodeMN(ntCapture, p.options, 0, -1)) - - for p.charsRight() > 0 { - wasPrevQuantifier := isQuant - isQuant = false - - if err := p.scanBlank(); err != nil { - return nil, err - } - - startpos := p.textpos() - - // move past all of the normal characters. We'll stop when we hit some kind of control character, - // or if IgnorePatternWhiteSpace is on, we'll stop when we see some whitespace. - if p.useOptionX() { - for p.charsRight() > 0 { - ch = p.rightChar(0) - //UGLY: clean up, this is ugly - if !(!isStopperX(ch) || (ch == '{' && !p.isTrueQuantifier())) { - break - } - p.moveRight(1) - } - } else { - for p.charsRight() > 0 { - ch = p.rightChar(0) - if !(!isSpecial(ch) || ch == '{' && !p.isTrueQuantifier()) { - break - } - p.moveRight(1) - } - } - - endpos := p.textpos() - - p.scanBlank() - - if p.charsRight() == 0 { - ch = '!' // nonspecial, means at end - } else if ch = p.rightChar(0); isSpecial(ch) { - isQuant = isQuantifier(ch) - p.moveRight(1) - } else { - ch = ' ' // nonspecial, means at ordinary char - } - - if startpos < endpos { - cchUnquantified := endpos - startpos - if isQuant { - cchUnquantified-- - } - wasPrevQuantifier = false - - if cchUnquantified > 0 { - p.addToConcatenate(startpos, cchUnquantified, false) - } - - if isQuant { - p.addUnitOne(p.charAt(endpos - 1)) - } - } - - switch ch { - case '!': - goto BreakOuterScan - - case ' ': - goto ContinueOuterScan - - case '[': - cc, err := p.scanCharSet(p.useOptionI(), false) - if err != nil { - return nil, err - } - p.addUnitSet(cc) - - case '(': - p.pushOptions() - - if grouper, err := p.scanGroupOpen(); err != nil { - return nil, err - } else if grouper == nil { - p.popKeepOptions() - } else { - p.pushGroup() - p.startGroup(grouper) - } - - continue - - case '|': - p.addAlternate() - goto ContinueOuterScan - - case ')': - if p.emptyStack() { - return nil, p.getErr(ErrUnexpectedParen) - } - - if err := p.addGroup(); err != nil { - return nil, err - } - if err := p.popGroup(); err != nil { - return nil, err - } - p.popOptions() - - if p.unit == nil { - goto ContinueOuterScan - } - - case '\\': - n, err := p.scanBackslash(false) - if err != nil { - return nil, err - } - p.addUnitNode(n) - - case '^': - if p.useOptionM() { - p.addUnitType(ntBol) - } else { - p.addUnitType(ntBeginning) - } - - case '$': - if p.useOptionM() { - p.addUnitType(ntEol) - } else { - p.addUnitType(ntEndZ) - } - - case '.': - if p.useOptionE() { - p.addUnitSet(ECMAAnyClass()) - } else if p.useOptionS() { - p.addUnitSet(AnyClass()) - } else { - p.addUnitNotone('\n') - } - - case '{', '*', '+', '?': - if p.unit == nil { - if wasPrevQuantifier { - return nil, p.getErr(ErrInvalidRepeatOp) - } else { - return nil, p.getErr(ErrMissingRepeatArgument) - } - } - p.moveLeft() - - default: - return nil, p.getErr(ErrInternalError) - } - - if err := p.scanBlank(); err != nil { - return nil, err - } - - if p.charsRight() > 0 { - isQuant = p.isTrueQuantifier() - } - if p.charsRight() == 0 || !isQuant { - //maintain odd C# assignment order -- not sure if required, could clean up? - p.addConcatenate() - goto ContinueOuterScan - } - - ch = p.moveRightGetChar() - - // Handle quantifiers - for p.unit != nil { - var min, max int - var lazy bool - - switch ch { - case '*': - min = 0 - max = math.MaxInt32 - - case '?': - min = 0 - max = 1 - - case '+': - min = 1 - max = math.MaxInt32 - - case '{': - { - var err error - startpos = p.textpos() - if min, err = p.scanDecimal(); err != nil { - return nil, err - } - max = min - if startpos < p.textpos() { - if p.charsRight() > 0 && p.rightChar(0) == ',' { - p.moveRight(1) - if p.charsRight() == 0 || p.rightChar(0) == '}' { - max = math.MaxInt32 - } else { - if max, err = p.scanDecimal(); err != nil { - return nil, err - } - } - } - } - - if startpos == p.textpos() || p.charsRight() == 0 || p.moveRightGetChar() != '}' { - p.addConcatenate() - p.textto(startpos - 1) - goto ContinueOuterScan - } - } - - default: - return nil, p.getErr(ErrInternalError) - } - - if err := p.scanBlank(); err != nil { - return nil, err - } - - if p.charsRight() == 0 || p.rightChar(0) != '?' { - lazy = false - } else { - p.moveRight(1) - lazy = true - } - - if min > max { - return nil, p.getErr(ErrInvalidRepeatSize) - } - - p.addConcatenate3(lazy, min, max) - } - - ContinueOuterScan: - } - -BreakOuterScan: - ; - - if !p.emptyStack() { - return nil, p.getErr(ErrMissingParen) - } - - if err := p.addGroup(); err != nil { - return nil, err - } - - return p.unit, nil - -} - -/* - * Simple parsing for replacement patterns - */ -func (p *parser) scanReplacement() (*regexNode, error) { - var c, startpos int - - p.concatenation = newRegexNode(ntConcatenate, p.options) - - for { - c = p.charsRight() - if c == 0 { - break - } - - startpos = p.textpos() - - for c > 0 && p.rightChar(0) != '$' { - p.moveRight(1) - c-- - } - - p.addToConcatenate(startpos, p.textpos()-startpos, true) - - if c > 0 { - if p.moveRightGetChar() == '$' { - n, err := p.scanDollar() - if err != nil { - return nil, err - } - p.addUnitNode(n) - } - p.addConcatenate() - } - } - - return p.concatenation, nil -} - -/* - * Scans $ patterns recognized within replacement patterns - */ -func (p *parser) scanDollar() (*regexNode, error) { - if p.charsRight() == 0 { - return newRegexNodeCh(ntOne, p.options, '$'), nil - } - - ch := p.rightChar(0) - angled := false - backpos := p.textpos() - lastEndPos := backpos - - // Note angle - - if ch == '{' && p.charsRight() > 1 { - angled = true - p.moveRight(1) - ch = p.rightChar(0) - } - - // Try to parse backreference: \1 or \{1} or \{cap} - - if ch >= '0' && ch <= '9' { - if !angled && p.useOptionE() { - capnum := -1 - newcapnum := int(ch - '0') - p.moveRight(1) - if p.isCaptureSlot(newcapnum) { - capnum = newcapnum - lastEndPos = p.textpos() - } - - for p.charsRight() > 0 { - ch = p.rightChar(0) - if ch < '0' || ch > '9' { - break - } - digit := int(ch - '0') - if newcapnum > maxValueDiv10 || (newcapnum == maxValueDiv10 && digit > maxValueMod10) { - return nil, p.getErr(ErrCaptureGroupOutOfRange) - } - - newcapnum = newcapnum*10 + digit - - p.moveRight(1) - if p.isCaptureSlot(newcapnum) { - capnum = newcapnum - lastEndPos = p.textpos() - } - } - p.textto(lastEndPos) - if capnum >= 0 { - return newRegexNodeM(ntRef, p.options, capnum), nil - } - } else { - capnum, err := p.scanDecimal() - if err != nil { - return nil, err - } - if !angled || p.charsRight() > 0 && p.moveRightGetChar() == '}' { - if p.isCaptureSlot(capnum) { - return newRegexNodeM(ntRef, p.options, capnum), nil - } - } - } - } else if angled && IsWordChar(ch) { - capname := p.scanCapname() - - if p.charsRight() > 0 && p.moveRightGetChar() == '}' { - if p.isCaptureName(capname) { - return newRegexNodeM(ntRef, p.options, p.captureSlotFromName(capname)), nil - } - } - } else if !angled { - capnum := 1 - - switch ch { - case '$': - p.moveRight(1) - return newRegexNodeCh(ntOne, p.options, '$'), nil - case '&': - capnum = 0 - case '`': - capnum = replaceLeftPortion - case '\'': - capnum = replaceRightPortion - case '+': - capnum = replaceLastGroup - case '_': - capnum = replaceWholeString - } - - if capnum != 1 { - p.moveRight(1) - return newRegexNodeM(ntRef, p.options, capnum), nil - } - } - - // unrecognized $: literalize - - p.textto(backpos) - return newRegexNodeCh(ntOne, p.options, '$'), nil -} - -// scanGroupOpen scans chars following a '(' (not counting the '('), and returns -// a RegexNode for the type of group scanned, or nil if the group -// simply changed options (?cimsx-cimsx) or was a comment (#...). -func (p *parser) scanGroupOpen() (*regexNode, error) { - var ch rune - var nt nodeType - var err error - close := '>' - start := p.textpos() - - // just return a RegexNode if we have: - // 1. "(" followed by nothing - // 2. "(x" where x != ? - // 3. "(?)" - if p.charsRight() == 0 || p.rightChar(0) != '?' || (p.rightChar(0) == '?' && (p.charsRight() > 1 && p.rightChar(1) == ')')) { - if p.useOptionN() || p.ignoreNextParen { - p.ignoreNextParen = false - return newRegexNode(ntGroup, p.options), nil - } - return newRegexNodeMN(ntCapture, p.options, p.consumeAutocap(), -1), nil - } - - p.moveRight(1) - - for { - if p.charsRight() == 0 { - break - } - - switch ch = p.moveRightGetChar(); ch { - case ':': - nt = ntGroup - - case '=': - p.options &= ^RightToLeft - nt = ntRequire - - case '!': - p.options &= ^RightToLeft - nt = ntPrevent - - case '>': - nt = ntGreedy - - case '\'': - close = '\'' - fallthrough - - case '<': - if p.charsRight() == 0 { - goto BreakRecognize - } - - switch ch = p.moveRightGetChar(); ch { - case '=': - if close == '\'' { - goto BreakRecognize - } - - p.options |= RightToLeft - nt = ntRequire - - case '!': - if close == '\'' { - goto BreakRecognize - } - - p.options |= RightToLeft - nt = ntPrevent - - default: - p.moveLeft() - capnum := -1 - uncapnum := -1 - proceed := false - - // grab part before - - - if ch >= '0' && ch <= '9' { - if capnum, err = p.scanDecimal(); err != nil { - return nil, err - } - - if !p.isCaptureSlot(capnum) { - capnum = -1 - } - - // check if we have bogus characters after the number - if p.charsRight() > 0 && !(p.rightChar(0) == close || p.rightChar(0) == '-') { - return nil, p.getErr(ErrInvalidGroupName) - } - if capnum == 0 { - return nil, p.getErr(ErrCapNumNotZero) - } - } else if IsWordChar(ch) { - capname := p.scanCapname() - - if p.isCaptureName(capname) { - capnum = p.captureSlotFromName(capname) - } - - // check if we have bogus character after the name - if p.charsRight() > 0 && !(p.rightChar(0) == close || p.rightChar(0) == '-') { - return nil, p.getErr(ErrInvalidGroupName) - } - } else if ch == '-' { - proceed = true - } else { - // bad group name - starts with something other than a word character and isn't a number - return nil, p.getErr(ErrInvalidGroupName) - } - - // grab part after - if any - - if (capnum != -1 || proceed == true) && p.charsRight() > 0 && p.rightChar(0) == '-' { - p.moveRight(1) - - //no more chars left, no closing char, etc - if p.charsRight() == 0 { - return nil, p.getErr(ErrInvalidGroupName) - } - - ch = p.rightChar(0) - if ch >= '0' && ch <= '9' { - if uncapnum, err = p.scanDecimal(); err != nil { - return nil, err - } - - if !p.isCaptureSlot(uncapnum) { - return nil, p.getErr(ErrUndefinedBackRef, uncapnum) - } - - // check if we have bogus characters after the number - if p.charsRight() > 0 && p.rightChar(0) != close { - return nil, p.getErr(ErrInvalidGroupName) - } - } else if IsWordChar(ch) { - uncapname := p.scanCapname() - - if !p.isCaptureName(uncapname) { - return nil, p.getErr(ErrUndefinedNameRef, uncapname) - } - uncapnum = p.captureSlotFromName(uncapname) - - // check if we have bogus character after the name - if p.charsRight() > 0 && p.rightChar(0) != close { - return nil, p.getErr(ErrInvalidGroupName) - } - } else { - // bad group name - starts with something other than a word character and isn't a number - return nil, p.getErr(ErrInvalidGroupName) - } - } - - // actually make the node - - if (capnum != -1 || uncapnum != -1) && p.charsRight() > 0 && p.moveRightGetChar() == close { - return newRegexNodeMN(ntCapture, p.options, capnum, uncapnum), nil - } - goto BreakRecognize - } - - case '(': - // alternation construct (?(...) | ) - - parenPos := p.textpos() - if p.charsRight() > 0 { - ch = p.rightChar(0) - - // check if the alternation condition is a backref - if ch >= '0' && ch <= '9' { - var capnum int - if capnum, err = p.scanDecimal(); err != nil { - return nil, err - } - if p.charsRight() > 0 && p.moveRightGetChar() == ')' { - if p.isCaptureSlot(capnum) { - return newRegexNodeM(ntTestref, p.options, capnum), nil - } - return nil, p.getErr(ErrUndefinedReference, capnum) - } - - return nil, p.getErr(ErrMalformedReference, capnum) - - } else if IsWordChar(ch) { - capname := p.scanCapname() - - if p.isCaptureName(capname) && p.charsRight() > 0 && p.moveRightGetChar() == ')' { - return newRegexNodeM(ntTestref, p.options, p.captureSlotFromName(capname)), nil - } - } - } - // not a backref - nt = ntTestgroup - p.textto(parenPos - 1) // jump to the start of the parentheses - p.ignoreNextParen = true // but make sure we don't try to capture the insides - - charsRight := p.charsRight() - if charsRight >= 3 && p.rightChar(1) == '?' { - rightchar2 := p.rightChar(2) - // disallow comments in the condition - if rightchar2 == '#' { - return nil, p.getErr(ErrAlternationCantHaveComment) - } - - // disallow named capture group (?<..>..) in the condition - if rightchar2 == '\'' { - return nil, p.getErr(ErrAlternationCantCapture) - } - - if charsRight >= 4 && (rightchar2 == '<' && p.rightChar(3) != '!' && p.rightChar(3) != '=') { - return nil, p.getErr(ErrAlternationCantCapture) - } - } - - case 'P': - if p.useRE2() { - // support for P syntax - if p.charsRight() < 3 { - goto BreakRecognize - } - - ch = p.moveRightGetChar() - if ch != '<' { - goto BreakRecognize - } - - ch = p.moveRightGetChar() - p.moveLeft() - - if IsWordChar(ch) { - capnum := -1 - capname := p.scanCapname() - - if p.isCaptureName(capname) { - capnum = p.captureSlotFromName(capname) - } - - // check if we have bogus character after the name - if p.charsRight() > 0 && p.rightChar(0) != '>' { - return nil, p.getErr(ErrInvalidGroupName) - } - - // actually make the node - - if capnum != -1 && p.charsRight() > 0 && p.moveRightGetChar() == '>' { - return newRegexNodeMN(ntCapture, p.options, capnum, -1), nil - } - goto BreakRecognize - - } else { - // bad group name - starts with something other than a word character and isn't a number - return nil, p.getErr(ErrInvalidGroupName) - } - } - // if we're not using RE2 compat mode then - // we just behave like normal - fallthrough - - default: - p.moveLeft() - - nt = ntGroup - // disallow options in the children of a testgroup node - if p.group.t != ntTestgroup { - p.scanOptions() - } - if p.charsRight() == 0 { - goto BreakRecognize - } - - if ch = p.moveRightGetChar(); ch == ')' { - return nil, nil - } - - if ch != ':' { - goto BreakRecognize - } - - } - - return newRegexNode(nt, p.options), nil - } - -BreakRecognize: - - // break Recognize comes here - - return nil, p.getErr(ErrUnrecognizedGrouping, string(p.pattern[start:p.textpos()])) -} - -// scans backslash specials and basics -func (p *parser) scanBackslash(scanOnly bool) (*regexNode, error) { - - if p.charsRight() == 0 { - return nil, p.getErr(ErrIllegalEndEscape) - } - - switch ch := p.rightChar(0); ch { - case 'b', 'B', 'A', 'G', 'Z', 'z': - p.moveRight(1) - return newRegexNode(p.typeFromCode(ch), p.options), nil - - case 'w': - p.moveRight(1) - if p.useOptionE() || p.useRE2() { - return newRegexNodeSet(ntSet, p.options, ECMAWordClass()), nil - } - return newRegexNodeSet(ntSet, p.options, WordClass()), nil - - case 'W': - p.moveRight(1) - if p.useOptionE() || p.useRE2() { - return newRegexNodeSet(ntSet, p.options, NotECMAWordClass()), nil - } - return newRegexNodeSet(ntSet, p.options, NotWordClass()), nil - - case 's': - p.moveRight(1) - if p.useOptionE() { - return newRegexNodeSet(ntSet, p.options, ECMASpaceClass()), nil - } else if p.useRE2() { - return newRegexNodeSet(ntSet, p.options, RE2SpaceClass()), nil - } - return newRegexNodeSet(ntSet, p.options, SpaceClass()), nil - - case 'S': - p.moveRight(1) - if p.useOptionE() { - return newRegexNodeSet(ntSet, p.options, NotECMASpaceClass()), nil - } else if p.useRE2() { - return newRegexNodeSet(ntSet, p.options, NotRE2SpaceClass()), nil - } - return newRegexNodeSet(ntSet, p.options, NotSpaceClass()), nil - - case 'd': - p.moveRight(1) - if p.useOptionE() || p.useRE2() { - return newRegexNodeSet(ntSet, p.options, ECMADigitClass()), nil - } - return newRegexNodeSet(ntSet, p.options, DigitClass()), nil - - case 'D': - p.moveRight(1) - if p.useOptionE() || p.useRE2() { - return newRegexNodeSet(ntSet, p.options, NotECMADigitClass()), nil - } - return newRegexNodeSet(ntSet, p.options, NotDigitClass()), nil - - case 'p', 'P': - p.moveRight(1) - prop, err := p.parseProperty() - if err != nil { - return nil, err - } - cc := &CharSet{} - cc.addCategory(prop, (ch != 'p'), p.useOptionI(), p.patternRaw) - if p.useOptionI() { - cc.addLowercase() - } - - return newRegexNodeSet(ntSet, p.options, cc), nil - - default: - return p.scanBasicBackslash(scanOnly) - } -} - -// Scans \-style backreferences and character escapes -func (p *parser) scanBasicBackslash(scanOnly bool) (*regexNode, error) { - if p.charsRight() == 0 { - return nil, p.getErr(ErrIllegalEndEscape) - } - angled := false - k := false - close := '\x00' - - backpos := p.textpos() - ch := p.rightChar(0) - - // Allow \k instead of \, which is now deprecated. - - // According to ECMAScript specification, \k is only parsed as a named group reference if - // there is at least one group name in the regexp. - // See https://www.ecma-international.org/ecma-262/#sec-isvalidregularexpressionliteral, step 7. - // Note, during the first (scanOnly) run we may not have all group names scanned, but that's ok. - if ch == 'k' && (!p.useOptionE() || len(p.capnames) > 0) { - if p.charsRight() >= 2 { - p.moveRight(1) - ch = p.moveRightGetChar() - - if ch == '<' || (!p.useOptionE() && ch == '\'') { // No support for \k'name' in ECMAScript - angled = true - if ch == '\'' { - close = '\'' - } else { - close = '>' - } - } - } - - if !angled || p.charsRight() <= 0 { - return nil, p.getErr(ErrMalformedNameRef) - } - - ch = p.rightChar(0) - k = true - - } else if !p.useOptionE() && (ch == '<' || ch == '\'') && p.charsRight() > 1 { // Note angle without \g - angled = true - if ch == '\'' { - close = '\'' - } else { - close = '>' - } - - p.moveRight(1) - ch = p.rightChar(0) - } - - // Try to parse backreference: \<1> or \ - - if angled && ch >= '0' && ch <= '9' { - capnum, err := p.scanDecimal() - if err != nil { - return nil, err - } - - if p.charsRight() > 0 && p.moveRightGetChar() == close { - if p.isCaptureSlot(capnum) { - return newRegexNodeM(ntRef, p.options, capnum), nil - } - return nil, p.getErr(ErrUndefinedBackRef, capnum) - } - } else if !angled && ch >= '1' && ch <= '9' { // Try to parse backreference or octal: \1 - capnum, err := p.scanDecimal() - if err != nil { - return nil, err - } - - if scanOnly { - return nil, nil - } - - if p.isCaptureSlot(capnum) { - return newRegexNodeM(ntRef, p.options, capnum), nil - } - if capnum <= 9 && !p.useOptionE() { - return nil, p.getErr(ErrUndefinedBackRef, capnum) - } - - } else if angled { - capname := p.scanCapname() - - if capname != "" && p.charsRight() > 0 && p.moveRightGetChar() == close { - - if scanOnly { - return nil, nil - } - - if p.isCaptureName(capname) { - return newRegexNodeM(ntRef, p.options, p.captureSlotFromName(capname)), nil - } - return nil, p.getErr(ErrUndefinedNameRef, capname) - } else { - if k { - return nil, p.getErr(ErrMalformedNameRef) - } - } - } - - // Not backreference: must be char code - - p.textto(backpos) - ch, err := p.scanCharEscape() - if err != nil { - return nil, err - } - - if scanOnly { - return nil, nil - } - - if p.useOptionI() { - ch = unicode.ToLower(ch) - } - - return newRegexNodeCh(ntOne, p.options, ch), nil -} - -// Scans X for \p{X} or \P{X} -func (p *parser) parseProperty() (string, error) { - // RE2 and PCRE supports \pX syntax (no {} and only 1 letter unicode cats supported) - // since this is purely additive syntax it's not behind a flag - if p.charsRight() >= 1 && p.rightChar(0) != '{' { - ch := string(p.moveRightGetChar()) - // check if it's a valid cat - if !isValidUnicodeCat(ch) { - return "", p.getErr(ErrUnknownSlashP, ch) - } - return ch, nil - } - - if p.charsRight() < 3 { - return "", p.getErr(ErrIncompleteSlashP) - } - ch := p.moveRightGetChar() - if ch != '{' { - return "", p.getErr(ErrMalformedSlashP) - } - - startpos := p.textpos() - for p.charsRight() > 0 { - ch = p.moveRightGetChar() - if !(IsWordChar(ch) || ch == '-') { - p.moveLeft() - break - } - } - capname := string(p.pattern[startpos:p.textpos()]) - - if p.charsRight() == 0 || p.moveRightGetChar() != '}' { - return "", p.getErr(ErrIncompleteSlashP) - } - - if !isValidUnicodeCat(capname) { - return "", p.getErr(ErrUnknownSlashP, capname) - } - - return capname, nil -} - -// Returns ReNode type for zero-length assertions with a \ code. -func (p *parser) typeFromCode(ch rune) nodeType { - switch ch { - case 'b': - if p.useOptionE() { - return ntECMABoundary - } - return ntBoundary - case 'B': - if p.useOptionE() { - return ntNonECMABoundary - } - return ntNonboundary - case 'A': - return ntBeginning - case 'G': - return ntStart - case 'Z': - return ntEndZ - case 'z': - return ntEnd - default: - return ntNothing - } -} - -// Scans whitespace or x-mode comments. -func (p *parser) scanBlank() error { - if p.useOptionX() { - for { - for p.charsRight() > 0 && isSpace(p.rightChar(0)) { - p.moveRight(1) - } - - if p.charsRight() == 0 { - break - } - - if p.rightChar(0) == '#' { - for p.charsRight() > 0 && p.rightChar(0) != '\n' { - p.moveRight(1) - } - } else if p.charsRight() >= 3 && p.rightChar(2) == '#' && - p.rightChar(1) == '?' && p.rightChar(0) == '(' { - for p.charsRight() > 0 && p.rightChar(0) != ')' { - p.moveRight(1) - } - if p.charsRight() == 0 { - return p.getErr(ErrUnterminatedComment) - } - p.moveRight(1) - } else { - break - } - } - } else { - for { - if p.charsRight() < 3 || p.rightChar(2) != '#' || - p.rightChar(1) != '?' || p.rightChar(0) != '(' { - return nil - } - - for p.charsRight() > 0 && p.rightChar(0) != ')' { - p.moveRight(1) - } - if p.charsRight() == 0 { - return p.getErr(ErrUnterminatedComment) - } - p.moveRight(1) - } - } - return nil -} - -func (p *parser) scanCapname() string { - startpos := p.textpos() - - for p.charsRight() > 0 { - if !IsWordChar(p.moveRightGetChar()) { - p.moveLeft() - break - } - } - - return string(p.pattern[startpos:p.textpos()]) -} - -// Scans contents of [] (not including []'s), and converts to a set. -func (p *parser) scanCharSet(caseInsensitive, scanOnly bool) (*CharSet, error) { - ch := '\x00' - chPrev := '\x00' - inRange := false - firstChar := true - closed := false - - var cc *CharSet - if !scanOnly { - cc = &CharSet{} - } - - if p.charsRight() > 0 && p.rightChar(0) == '^' { - p.moveRight(1) - if !scanOnly { - cc.negate = true - } - } - - for ; p.charsRight() > 0; firstChar = false { - fTranslatedChar := false - ch = p.moveRightGetChar() - if ch == ']' { - if !firstChar { - closed = true - break - } else if p.useOptionE() { - if !scanOnly { - cc.addRanges(NoneClass().ranges) - } - closed = true - break - } - - } else if ch == '\\' && p.charsRight() > 0 { - switch ch = p.moveRightGetChar(); ch { - case 'D', 'd': - if !scanOnly { - if inRange { - return nil, p.getErr(ErrBadClassInCharRange, ch) - } - cc.addDigit(p.useOptionE() || p.useRE2(), ch == 'D', p.patternRaw) - } - continue - - case 'S', 's': - if !scanOnly { - if inRange { - return nil, p.getErr(ErrBadClassInCharRange, ch) - } - cc.addSpace(p.useOptionE(), p.useRE2(), ch == 'S') - } - continue - - case 'W', 'w': - if !scanOnly { - if inRange { - return nil, p.getErr(ErrBadClassInCharRange, ch) - } - - cc.addWord(p.useOptionE() || p.useRE2(), ch == 'W') - } - continue - - case 'p', 'P': - if !scanOnly { - if inRange { - return nil, p.getErr(ErrBadClassInCharRange, ch) - } - prop, err := p.parseProperty() - if err != nil { - return nil, err - } - cc.addCategory(prop, (ch != 'p'), caseInsensitive, p.patternRaw) - } else { - p.parseProperty() - } - - continue - - case '-': - if !scanOnly { - cc.addRange(ch, ch) - } - continue - - default: - p.moveLeft() - var err error - ch, err = p.scanCharEscape() // non-literal character - if err != nil { - return nil, err - } - fTranslatedChar = true - break // this break will only break out of the switch - } - } else if ch == '[' { - // This is code for Posix style properties - [:Ll:] or [:IsTibetan:]. - // It currently doesn't do anything other than skip the whole thing! - if p.charsRight() > 0 && p.rightChar(0) == ':' && !inRange { - savePos := p.textpos() - - p.moveRight(1) - negate := false - if p.charsRight() > 1 && p.rightChar(0) == '^' { - negate = true - p.moveRight(1) - } - - nm := p.scanCapname() // snag the name - if !scanOnly && p.useRE2() { - // look up the name since these are valid for RE2 - // add the group based on the name - if ok := cc.addNamedASCII(nm, negate); !ok { - return nil, p.getErr(ErrInvalidCharRange) - } - } - if p.charsRight() < 2 || p.moveRightGetChar() != ':' || p.moveRightGetChar() != ']' { - p.textto(savePos) - } else if p.useRE2() { - // move on - continue - } - } - } - - if inRange { - inRange = false - if !scanOnly { - if ch == '[' && !fTranslatedChar && !firstChar { - // We thought we were in a range, but we're actually starting a subtraction. - // In that case, we'll add chPrev to our char class, skip the opening [, and - // scan the new character class recursively. - cc.addChar(chPrev) - sub, err := p.scanCharSet(caseInsensitive, false) - if err != nil { - return nil, err - } - cc.addSubtraction(sub) - - if p.charsRight() > 0 && p.rightChar(0) != ']' { - return nil, p.getErr(ErrSubtractionMustBeLast) - } - } else { - // a regular range, like a-z - if chPrev > ch { - return nil, p.getErr(ErrReversedCharRange, chPrev, ch) - } - cc.addRange(chPrev, ch) - } - } - } else if p.charsRight() >= 2 && p.rightChar(0) == '-' && p.rightChar(1) != ']' { - // this could be the start of a range - chPrev = ch - inRange = true - p.moveRight(1) - } else if p.charsRight() >= 1 && ch == '-' && !fTranslatedChar && p.rightChar(0) == '[' && !firstChar { - // we aren't in a range, and now there is a subtraction. Usually this happens - // only when a subtraction follows a range, like [a-z-[b]] - if !scanOnly { - p.moveRight(1) - sub, err := p.scanCharSet(caseInsensitive, false) - if err != nil { - return nil, err - } - cc.addSubtraction(sub) - - if p.charsRight() > 0 && p.rightChar(0) != ']' { - return nil, p.getErr(ErrSubtractionMustBeLast) - } - } else { - p.moveRight(1) - p.scanCharSet(caseInsensitive, true) - } - } else { - if !scanOnly { - cc.addRange(ch, ch) - } - } - } - - if !closed { - return nil, p.getErr(ErrUnterminatedBracket) - } - - if !scanOnly && caseInsensitive { - cc.addLowercase() - } - - return cc, nil -} - -// Scans any number of decimal digits (pegs value at 2^31-1 if too large) -func (p *parser) scanDecimal() (int, error) { - i := 0 - var d int - - for p.charsRight() > 0 { - d = int(p.rightChar(0) - '0') - if d < 0 || d > 9 { - break - } - p.moveRight(1) - - if i > maxValueDiv10 || (i == maxValueDiv10 && d > maxValueMod10) { - return 0, p.getErr(ErrCaptureGroupOutOfRange) - } - - i *= 10 - i += d - } - - return int(i), nil -} - -// Returns true for options allowed only at the top level -func isOnlyTopOption(option RegexOptions) bool { - return option == RightToLeft || option == ECMAScript || option == RE2 -} - -// Scans cimsx-cimsx option string, stops at the first unrecognized char. -func (p *parser) scanOptions() { - - for off := false; p.charsRight() > 0; p.moveRight(1) { - ch := p.rightChar(0) - - if ch == '-' { - off = true - } else if ch == '+' { - off = false - } else { - option := optionFromCode(ch) - if option == 0 || isOnlyTopOption(option) { - return - } - - if off { - p.options &= ^option - } else { - p.options |= option - } - } - } -} - -// Scans \ code for escape codes that map to single unicode chars. -func (p *parser) scanCharEscape() (r rune, err error) { - - ch := p.moveRightGetChar() - - if ch >= '0' && ch <= '7' { - p.moveLeft() - return p.scanOctal(), nil - } - - pos := p.textpos() - - switch ch { - case 'x': - // support for \x{HEX} syntax from Perl and PCRE - if p.charsRight() > 0 && p.rightChar(0) == '{' { - if p.useOptionE() { - return ch, nil - } - p.moveRight(1) - return p.scanHexUntilBrace() - } else { - r, err = p.scanHex(2) - } - case 'u': - // ECMAscript suppot \u{HEX} only if `u` is also set - if p.useOptionE() && p.useOptionU() && p.charsRight() > 0 && p.rightChar(0) == '{' { - p.moveRight(1) - return p.scanHexUntilBrace() - } else { - r, err = p.scanHex(4) - } - case 'a': - return '\u0007', nil - case 'b': - return '\b', nil - case 'e': - return '\u001B', nil - case 'f': - return '\f', nil - case 'n': - return '\n', nil - case 'r': - return '\r', nil - case 't': - return '\t', nil - case 'v': - return '\u000B', nil - case 'c': - r, err = p.scanControl() - default: - if !p.useOptionE() && !p.useRE2() && IsWordChar(ch) { - return 0, p.getErr(ErrUnrecognizedEscape, string(ch)) - } - return ch, nil - } - if err != nil && p.useOptionE() { - p.textto(pos) - return ch, nil - } - return -} - -// Grabs and converts an ascii control character -func (p *parser) scanControl() (rune, error) { - if p.charsRight() <= 0 { - return 0, p.getErr(ErrMissingControl) - } - - ch := p.moveRightGetChar() - - // \ca interpreted as \cA - - if ch >= 'a' && ch <= 'z' { - ch = (ch - ('a' - 'A')) - } - ch = (ch - '@') - if ch >= 0 && ch < ' ' { - return ch, nil - } - - return 0, p.getErr(ErrUnrecognizedControl) - -} - -// Scan hex digits until we hit a closing brace. -// Non-hex digits, hex value too large for UTF-8, or running out of chars are errors -func (p *parser) scanHexUntilBrace() (rune, error) { - // PCRE spec reads like unlimited hex digits are allowed, but unicode has a limit - // so we can enforce that - i := 0 - hasContent := false - - for p.charsRight() > 0 { - ch := p.moveRightGetChar() - if ch == '}' { - // hit our close brace, we're done here - // prevent \x{} - if !hasContent { - return 0, p.getErr(ErrTooFewHex) - } - return rune(i), nil - } - hasContent = true - // no brace needs to be hex digit - d := hexDigit(ch) - if d < 0 { - return 0, p.getErr(ErrMissingBrace) - } - - i *= 0x10 - i += d - - if i > unicode.MaxRune { - return 0, p.getErr(ErrInvalidHex) - } - } - - // we only make it here if we run out of digits without finding the brace - return 0, p.getErr(ErrMissingBrace) -} - -// Scans exactly c hex digits (c=2 for \xFF, c=4 for \uFFFF) -func (p *parser) scanHex(c int) (rune, error) { - - i := 0 - - if p.charsRight() >= c { - for c > 0 { - d := hexDigit(p.moveRightGetChar()) - if d < 0 { - break - } - i *= 0x10 - i += d - c-- - } - } - - if c > 0 { - return 0, p.getErr(ErrTooFewHex) - } - - return rune(i), nil -} - -// Returns n <= 0xF for a hex digit. -func hexDigit(ch rune) int { - - if d := uint(ch - '0'); d <= 9 { - return int(d) - } - - if d := uint(ch - 'a'); d <= 5 { - return int(d + 0xa) - } - - if d := uint(ch - 'A'); d <= 5 { - return int(d + 0xa) - } - - return -1 -} - -// Scans up to three octal digits (stops before exceeding 0377). -func (p *parser) scanOctal() rune { - // Consume octal chars only up to 3 digits and value 0377 - - c := 3 - - if c > p.charsRight() { - c = p.charsRight() - } - - //we know the first char is good because the caller had to check - i := 0 - d := int(p.rightChar(0) - '0') - for c > 0 && d <= 7 && d >= 0 { - if i >= 0x20 && p.useOptionE() { - break - } - i *= 8 - i += d - c-- - - p.moveRight(1) - if !p.rightMost() { - d = int(p.rightChar(0) - '0') - } - } - - // Octal codes only go up to 255. Any larger and the behavior that Perl follows - // is simply to truncate the high bits. - i &= 0xFF - - return rune(i) -} - -// Returns the current parsing position. -func (p *parser) textpos() int { - return p.currentPos -} - -// Zaps to a specific parsing position. -func (p *parser) textto(pos int) { - p.currentPos = pos -} - -// Returns the char at the right of the current parsing position and advances to the right. -func (p *parser) moveRightGetChar() rune { - ch := p.pattern[p.currentPos] - p.currentPos++ - return ch -} - -// Moves the current position to the right. -func (p *parser) moveRight(i int) { - // default would be 1 - p.currentPos += i -} - -// Moves the current parsing position one to the left. -func (p *parser) moveLeft() { - p.currentPos-- -} - -// Returns the char left of the current parsing position. -func (p *parser) charAt(i int) rune { - return p.pattern[i] -} - -// Returns the char i chars right of the current parsing position. -func (p *parser) rightChar(i int) rune { - // default would be 0 - return p.pattern[p.currentPos+i] -} - -// Number of characters to the right of the current parsing position. -func (p *parser) charsRight() int { - return len(p.pattern) - p.currentPos -} - -func (p *parser) rightMost() bool { - return p.currentPos == len(p.pattern) -} - -// Looks up the slot number for a given name -func (p *parser) captureSlotFromName(capname string) int { - return p.capnames[capname] -} - -// True if the capture slot was noted -func (p *parser) isCaptureSlot(i int) bool { - if p.caps != nil { - _, ok := p.caps[i] - return ok - } - - return (i >= 0 && i < p.capsize) -} - -// Looks up the slot number for a given name -func (p *parser) isCaptureName(capname string) bool { - if p.capnames == nil { - return false - } - - _, ok := p.capnames[capname] - return ok -} - -// option shortcuts - -// True if N option disabling '(' autocapture is on. -func (p *parser) useOptionN() bool { - return (p.options & ExplicitCapture) != 0 -} - -// True if I option enabling case-insensitivity is on. -func (p *parser) useOptionI() bool { - return (p.options & IgnoreCase) != 0 -} - -// True if M option altering meaning of $ and ^ is on. -func (p *parser) useOptionM() bool { - return (p.options & Multiline) != 0 -} - -// True if S option altering meaning of . is on. -func (p *parser) useOptionS() bool { - return (p.options & Singleline) != 0 -} - -// True if X option enabling whitespace/comment mode is on. -func (p *parser) useOptionX() bool { - return (p.options & IgnorePatternWhitespace) != 0 -} - -// True if E option enabling ECMAScript behavior on. -func (p *parser) useOptionE() bool { - return (p.options & ECMAScript) != 0 -} - -// true to use RE2 compatibility parsing behavior. -func (p *parser) useRE2() bool { - return (p.options & RE2) != 0 -} - -// True if U option enabling ECMAScript's Unicode behavior on. -func (p *parser) useOptionU() bool { - return (p.options & Unicode) != 0 -} - -// True if options stack is empty. -func (p *parser) emptyOptionsStack() bool { - return len(p.optionsStack) == 0 -} - -// Finish the current quantifiable (when a quantifier is not found or is not possible) -func (p *parser) addConcatenate() { - // The first (| inside a Testgroup group goes directly to the group - p.concatenation.addChild(p.unit) - p.unit = nil -} - -// Finish the current quantifiable (when a quantifier is found) -func (p *parser) addConcatenate3(lazy bool, min, max int) { - p.concatenation.addChild(p.unit.makeQuantifier(lazy, min, max)) - p.unit = nil -} - -// Sets the current unit to a single char node -func (p *parser) addUnitOne(ch rune) { - if p.useOptionI() { - ch = unicode.ToLower(ch) - } - - p.unit = newRegexNodeCh(ntOne, p.options, ch) -} - -// Sets the current unit to a single inverse-char node -func (p *parser) addUnitNotone(ch rune) { - if p.useOptionI() { - ch = unicode.ToLower(ch) - } - - p.unit = newRegexNodeCh(ntNotone, p.options, ch) -} - -// Sets the current unit to a single set node -func (p *parser) addUnitSet(set *CharSet) { - p.unit = newRegexNodeSet(ntSet, p.options, set) -} - -// Sets the current unit to a subtree -func (p *parser) addUnitNode(node *regexNode) { - p.unit = node -} - -// Sets the current unit to an assertion of the specified type -func (p *parser) addUnitType(t nodeType) { - p.unit = newRegexNode(t, p.options) -} - -// Finish the current group (in response to a ')' or end) -func (p *parser) addGroup() error { - if p.group.t == ntTestgroup || p.group.t == ntTestref { - p.group.addChild(p.concatenation.reverseLeft()) - if (p.group.t == ntTestref && len(p.group.children) > 2) || len(p.group.children) > 3 { - return p.getErr(ErrTooManyAlternates) - } - } else { - p.alternation.addChild(p.concatenation.reverseLeft()) - p.group.addChild(p.alternation) - } - - p.unit = p.group - return nil -} - -// Pops the option stack, but keeps the current options unchanged. -func (p *parser) popKeepOptions() { - lastIdx := len(p.optionsStack) - 1 - p.optionsStack = p.optionsStack[:lastIdx] -} - -// Recalls options from the stack. -func (p *parser) popOptions() { - lastIdx := len(p.optionsStack) - 1 - // get the last item on the stack and then remove it by reslicing - p.options = p.optionsStack[lastIdx] - p.optionsStack = p.optionsStack[:lastIdx] -} - -// Saves options on a stack. -func (p *parser) pushOptions() { - p.optionsStack = append(p.optionsStack, p.options) -} - -// Add a string to the last concatenate. -func (p *parser) addToConcatenate(pos, cch int, isReplacement bool) { - var node *regexNode - - if cch == 0 { - return - } - - if cch > 1 { - str := make([]rune, cch) - copy(str, p.pattern[pos:pos+cch]) - - if p.useOptionI() && !isReplacement { - // We do the ToLower character by character for consistency. With surrogate chars, doing - // a ToLower on the entire string could actually change the surrogate pair. This is more correct - // linguistically, but since Regex doesn't support surrogates, it's more important to be - // consistent. - for i := 0; i < len(str); i++ { - str[i] = unicode.ToLower(str[i]) - } - } - - node = newRegexNodeStr(ntMulti, p.options, str) - } else { - ch := p.charAt(pos) - - if p.useOptionI() && !isReplacement { - ch = unicode.ToLower(ch) - } - - node = newRegexNodeCh(ntOne, p.options, ch) - } - - p.concatenation.addChild(node) -} - -// Push the parser state (in response to an open paren) -func (p *parser) pushGroup() { - p.group.next = p.stack - p.alternation.next = p.group - p.concatenation.next = p.alternation - p.stack = p.concatenation -} - -// Remember the pushed state (in response to a ')') -func (p *parser) popGroup() error { - p.concatenation = p.stack - p.alternation = p.concatenation.next - p.group = p.alternation.next - p.stack = p.group.next - - // The first () inside a Testgroup group goes directly to the group - if p.group.t == ntTestgroup && len(p.group.children) == 0 { - if p.unit == nil { - return p.getErr(ErrConditionalExpression) - } - - p.group.addChild(p.unit) - p.unit = nil - } - return nil -} - -// True if the group stack is empty. -func (p *parser) emptyStack() bool { - return p.stack == nil -} - -// Start a new round for the parser state (in response to an open paren or string start) -func (p *parser) startGroup(openGroup *regexNode) { - p.group = openGroup - p.alternation = newRegexNode(ntAlternate, p.options) - p.concatenation = newRegexNode(ntConcatenate, p.options) -} - -// Finish the current concatenation (in response to a |) -func (p *parser) addAlternate() { - // The | parts inside a Testgroup group go directly to the group - - if p.group.t == ntTestgroup || p.group.t == ntTestref { - p.group.addChild(p.concatenation.reverseLeft()) - } else { - p.alternation.addChild(p.concatenation.reverseLeft()) - } - - p.concatenation = newRegexNode(ntConcatenate, p.options) -} - -// For categorizing ascii characters. - -const ( - Q byte = 5 // quantifier - S = 4 // ordinary stopper - Z = 3 // ScanBlank stopper - X = 2 // whitespace - E = 1 // should be escaped -) - -var _category = []byte{ - //01 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 0, 0, 0, 0, 0, 0, 0, 0, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - X, 0, 0, Z, S, 0, 0, 0, S, S, Q, Q, 0, 0, S, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Q, - //@A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, S, 0, - //'a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Q, S, 0, 0, 0, -} - -func isSpace(ch rune) bool { - return (ch <= ' ' && _category[ch] == X) -} - -// Returns true for those characters that terminate a string of ordinary chars. -func isSpecial(ch rune) bool { - return (ch <= '|' && _category[ch] >= S) -} - -// Returns true for those characters that terminate a string of ordinary chars. -func isStopperX(ch rune) bool { - return (ch <= '|' && _category[ch] >= X) -} - -// Returns true for those characters that begin a quantifier. -func isQuantifier(ch rune) bool { - return (ch <= '{' && _category[ch] >= Q) -} - -func (p *parser) isTrueQuantifier() bool { - nChars := p.charsRight() - if nChars == 0 { - return false - } - - startpos := p.textpos() - ch := p.charAt(startpos) - if ch != '{' { - return ch <= '{' && _category[ch] >= Q - } - - //UGLY: this is ugly -- the original code was ugly too - pos := startpos - for { - nChars-- - if nChars <= 0 { - break - } - pos++ - ch = p.charAt(pos) - if ch < '0' || ch > '9' { - break - } - } - - if nChars == 0 || pos-startpos == 1 { - return false - } - if ch == '}' { - return true - } - if ch != ',' { - return false - } - for { - nChars-- - if nChars <= 0 { - break - } - pos++ - ch = p.charAt(pos) - if ch < '0' || ch > '9' { - break - } - } - - return nChars > 0 && ch == '}' -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/prefix.go b/vendor/github.com/dlclark/regexp2/syntax/prefix.go deleted file mode 100644 index f6716886..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/prefix.go +++ /dev/null @@ -1,896 +0,0 @@ -package syntax - -import ( - "bytes" - "fmt" - "strconv" - "unicode" - "unicode/utf8" -) - -type Prefix struct { - PrefixStr []rune - PrefixSet CharSet - CaseInsensitive bool -} - -// It takes a RegexTree and computes the set of chars that can start it. -func getFirstCharsPrefix(tree *RegexTree) *Prefix { - s := regexFcd{ - fcStack: make([]regexFc, 32), - intStack: make([]int, 32), - } - fc := s.regexFCFromRegexTree(tree) - - if fc == nil || fc.nullable || fc.cc.IsEmpty() { - return nil - } - fcSet := fc.getFirstChars() - return &Prefix{PrefixSet: fcSet, CaseInsensitive: fc.caseInsensitive} -} - -type regexFcd struct { - intStack []int - intDepth int - fcStack []regexFc - fcDepth int - skipAllChildren bool // don't process any more children at the current level - skipchild bool // don't process the current child. - failed bool -} - -/* - * The main FC computation. It does a shortcutted depth-first walk - * through the tree and calls CalculateFC to emits code before - * and after each child of an interior node, and at each leaf. - */ -func (s *regexFcd) regexFCFromRegexTree(tree *RegexTree) *regexFc { - curNode := tree.root - curChild := 0 - - for { - if len(curNode.children) == 0 { - // This is a leaf node - s.calculateFC(curNode.t, curNode, 0) - } else if curChild < len(curNode.children) && !s.skipAllChildren { - // This is an interior node, and we have more children to analyze - s.calculateFC(curNode.t|beforeChild, curNode, curChild) - - if !s.skipchild { - curNode = curNode.children[curChild] - // this stack is how we get a depth first walk of the tree. - s.pushInt(curChild) - curChild = 0 - } else { - curChild++ - s.skipchild = false - } - continue - } - - // This is an interior node where we've finished analyzing all the children, or - // the end of a leaf node. - s.skipAllChildren = false - - if s.intIsEmpty() { - break - } - - curChild = s.popInt() - curNode = curNode.next - - s.calculateFC(curNode.t|afterChild, curNode, curChild) - if s.failed { - return nil - } - - curChild++ - } - - if s.fcIsEmpty() { - return nil - } - - return s.popFC() -} - -// To avoid recursion, we use a simple integer stack. -// This is the push. -func (s *regexFcd) pushInt(I int) { - if s.intDepth >= len(s.intStack) { - expanded := make([]int, s.intDepth*2) - copy(expanded, s.intStack) - s.intStack = expanded - } - - s.intStack[s.intDepth] = I - s.intDepth++ -} - -// True if the stack is empty. -func (s *regexFcd) intIsEmpty() bool { - return s.intDepth == 0 -} - -// This is the pop. -func (s *regexFcd) popInt() int { - s.intDepth-- - return s.intStack[s.intDepth] -} - -// We also use a stack of RegexFC objects. -// This is the push. -func (s *regexFcd) pushFC(fc regexFc) { - if s.fcDepth >= len(s.fcStack) { - expanded := make([]regexFc, s.fcDepth*2) - copy(expanded, s.fcStack) - s.fcStack = expanded - } - - s.fcStack[s.fcDepth] = fc - s.fcDepth++ -} - -// True if the stack is empty. -func (s *regexFcd) fcIsEmpty() bool { - return s.fcDepth == 0 -} - -// This is the pop. -func (s *regexFcd) popFC() *regexFc { - s.fcDepth-- - return &s.fcStack[s.fcDepth] -} - -// This is the top. -func (s *regexFcd) topFC() *regexFc { - return &s.fcStack[s.fcDepth-1] -} - -// Called in Beforechild to prevent further processing of the current child -func (s *regexFcd) skipChild() { - s.skipchild = true -} - -// FC computation and shortcut cases for each node type -func (s *regexFcd) calculateFC(nt nodeType, node *regexNode, CurIndex int) { - //fmt.Printf("NodeType: %v, CurIndex: %v, Desc: %v\n", nt, CurIndex, node.description()) - ci := false - rtl := false - - if nt <= ntRef { - if (node.options & IgnoreCase) != 0 { - ci = true - } - if (node.options & RightToLeft) != 0 { - rtl = true - } - } - - switch nt { - case ntConcatenate | beforeChild, ntAlternate | beforeChild, ntTestref | beforeChild, ntLoop | beforeChild, ntLazyloop | beforeChild: - break - - case ntTestgroup | beforeChild: - if CurIndex == 0 { - s.skipChild() - } - break - - case ntEmpty: - s.pushFC(regexFc{nullable: true}) - break - - case ntConcatenate | afterChild: - if CurIndex != 0 { - child := s.popFC() - cumul := s.topFC() - - s.failed = !cumul.addFC(*child, true) - } - - fc := s.topFC() - if !fc.nullable { - s.skipAllChildren = true - } - break - - case ntTestgroup | afterChild: - if CurIndex > 1 { - child := s.popFC() - cumul := s.topFC() - - s.failed = !cumul.addFC(*child, false) - } - break - - case ntAlternate | afterChild, ntTestref | afterChild: - if CurIndex != 0 { - child := s.popFC() - cumul := s.topFC() - - s.failed = !cumul.addFC(*child, false) - } - break - - case ntLoop | afterChild, ntLazyloop | afterChild: - if node.m == 0 { - fc := s.topFC() - fc.nullable = true - } - break - - case ntGroup | beforeChild, ntGroup | afterChild, ntCapture | beforeChild, ntCapture | afterChild, ntGreedy | beforeChild, ntGreedy | afterChild: - break - - case ntRequire | beforeChild, ntPrevent | beforeChild: - s.skipChild() - s.pushFC(regexFc{nullable: true}) - break - - case ntRequire | afterChild, ntPrevent | afterChild: - break - - case ntOne, ntNotone: - s.pushFC(newRegexFc(node.ch, nt == ntNotone, false, ci)) - break - - case ntOneloop, ntOnelazy: - s.pushFC(newRegexFc(node.ch, false, node.m == 0, ci)) - break - - case ntNotoneloop, ntNotonelazy: - s.pushFC(newRegexFc(node.ch, true, node.m == 0, ci)) - break - - case ntMulti: - if len(node.str) == 0 { - s.pushFC(regexFc{nullable: true}) - } else if !rtl { - s.pushFC(newRegexFc(node.str[0], false, false, ci)) - } else { - s.pushFC(newRegexFc(node.str[len(node.str)-1], false, false, ci)) - } - break - - case ntSet: - s.pushFC(regexFc{cc: node.set.Copy(), nullable: false, caseInsensitive: ci}) - break - - case ntSetloop, ntSetlazy: - s.pushFC(regexFc{cc: node.set.Copy(), nullable: node.m == 0, caseInsensitive: ci}) - break - - case ntRef: - s.pushFC(regexFc{cc: *AnyClass(), nullable: true, caseInsensitive: false}) - break - - case ntNothing, ntBol, ntEol, ntBoundary, ntNonboundary, ntECMABoundary, ntNonECMABoundary, ntBeginning, ntStart, ntEndZ, ntEnd: - s.pushFC(regexFc{nullable: true}) - break - - default: - panic(fmt.Sprintf("unexpected op code: %v", nt)) - } -} - -type regexFc struct { - cc CharSet - nullable bool - caseInsensitive bool -} - -func newRegexFc(ch rune, not, nullable, caseInsensitive bool) regexFc { - r := regexFc{ - caseInsensitive: caseInsensitive, - nullable: nullable, - } - if not { - if ch > 0 { - r.cc.addRange('\x00', ch-1) - } - if ch < 0xFFFF { - r.cc.addRange(ch+1, utf8.MaxRune) - } - } else { - r.cc.addRange(ch, ch) - } - return r -} - -func (r *regexFc) getFirstChars() CharSet { - if r.caseInsensitive { - r.cc.addLowercase() - } - - return r.cc -} - -func (r *regexFc) addFC(fc regexFc, concatenate bool) bool { - if !r.cc.IsMergeable() || !fc.cc.IsMergeable() { - return false - } - - if concatenate { - if !r.nullable { - return true - } - - if !fc.nullable { - r.nullable = false - } - } else { - if fc.nullable { - r.nullable = true - } - } - - r.caseInsensitive = r.caseInsensitive || fc.caseInsensitive - r.cc.addSet(fc.cc) - - return true -} - -// This is a related computation: it takes a RegexTree and computes the -// leading substring if it sees one. It's quite trivial and gives up easily. -func getPrefix(tree *RegexTree) *Prefix { - var concatNode *regexNode - nextChild := 0 - - curNode := tree.root - - for { - switch curNode.t { - case ntConcatenate: - if len(curNode.children) > 0 { - concatNode = curNode - nextChild = 0 - } - - case ntGreedy, ntCapture: - curNode = curNode.children[0] - concatNode = nil - continue - - case ntOneloop, ntOnelazy: - if curNode.m > 0 { - return &Prefix{ - PrefixStr: repeat(curNode.ch, curNode.m), - CaseInsensitive: (curNode.options & IgnoreCase) != 0, - } - } - return nil - - case ntOne: - return &Prefix{ - PrefixStr: []rune{curNode.ch}, - CaseInsensitive: (curNode.options & IgnoreCase) != 0, - } - - case ntMulti: - return &Prefix{ - PrefixStr: curNode.str, - CaseInsensitive: (curNode.options & IgnoreCase) != 0, - } - - case ntBol, ntEol, ntBoundary, ntECMABoundary, ntBeginning, ntStart, - ntEndZ, ntEnd, ntEmpty, ntRequire, ntPrevent: - - default: - return nil - } - - if concatNode == nil || nextChild >= len(concatNode.children) { - return nil - } - - curNode = concatNode.children[nextChild] - nextChild++ - } -} - -// repeat the rune r, c times... up to the max of MaxPrefixSize -func repeat(r rune, c int) []rune { - if c > MaxPrefixSize { - c = MaxPrefixSize - } - - ret := make([]rune, c) - - // binary growth using copy for speed - ret[0] = r - bp := 1 - for bp < len(ret) { - copy(ret[bp:], ret[:bp]) - bp *= 2 - } - - return ret -} - -// BmPrefix precomputes the Boyer-Moore -// tables for fast string scanning. These tables allow -// you to scan for the first occurrence of a string within -// a large body of text without examining every character. -// The performance of the heuristic depends on the actual -// string and the text being searched, but usually, the longer -// the string that is being searched for, the fewer characters -// need to be examined. -type BmPrefix struct { - positive []int - negativeASCII []int - negativeUnicode [][]int - pattern []rune - lowASCII rune - highASCII rune - rightToLeft bool - caseInsensitive bool -} - -func newBmPrefix(pattern []rune, caseInsensitive, rightToLeft bool) *BmPrefix { - - b := &BmPrefix{ - rightToLeft: rightToLeft, - caseInsensitive: caseInsensitive, - pattern: pattern, - } - - if caseInsensitive { - for i := 0; i < len(b.pattern); i++ { - // We do the ToLower character by character for consistency. With surrogate chars, doing - // a ToLower on the entire string could actually change the surrogate pair. This is more correct - // linguistically, but since Regex doesn't support surrogates, it's more important to be - // consistent. - - b.pattern[i] = unicode.ToLower(b.pattern[i]) - } - } - - var beforefirst, last, bump int - var scan, match int - - if !rightToLeft { - beforefirst = -1 - last = len(b.pattern) - 1 - bump = 1 - } else { - beforefirst = len(b.pattern) - last = 0 - bump = -1 - } - - // PART I - the good-suffix shift table - // - // compute the positive requirement: - // if char "i" is the first one from the right that doesn't match, - // then we know the matcher can advance by _positive[i]. - // - // This algorithm is a simplified variant of the standard - // Boyer-Moore good suffix calculation. - - b.positive = make([]int, len(b.pattern)) - - examine := last - ch := b.pattern[examine] - b.positive[examine] = bump - examine -= bump - -Outerloop: - for { - // find an internal char (examine) that matches the tail - - for { - if examine == beforefirst { - break Outerloop - } - if b.pattern[examine] == ch { - break - } - examine -= bump - } - - match = last - scan = examine - - // find the length of the match - for { - if scan == beforefirst || b.pattern[match] != b.pattern[scan] { - // at the end of the match, note the difference in _positive - // this is not the length of the match, but the distance from the internal match - // to the tail suffix. - if b.positive[match] == 0 { - b.positive[match] = match - scan - } - - // System.Diagnostics.Debug.WriteLine("Set positive[" + match + "] to " + (match - scan)); - - break - } - - scan -= bump - match -= bump - } - - examine -= bump - } - - match = last - bump - - // scan for the chars for which there are no shifts that yield a different candidate - - // The inside of the if statement used to say - // "_positive[match] = last - beforefirst;" - // This is slightly less aggressive in how much we skip, but at worst it - // should mean a little more work rather than skipping a potential match. - for match != beforefirst { - if b.positive[match] == 0 { - b.positive[match] = bump - } - - match -= bump - } - - // PART II - the bad-character shift table - // - // compute the negative requirement: - // if char "ch" is the reject character when testing position "i", - // we can slide up by _negative[ch]; - // (_negative[ch] = str.Length - 1 - str.LastIndexOf(ch)) - // - // the lookup table is divided into ASCII and Unicode portions; - // only those parts of the Unicode 16-bit code set that actually - // appear in the string are in the table. (Maximum size with - // Unicode is 65K; ASCII only case is 512 bytes.) - - b.negativeASCII = make([]int, 128) - - for i := 0; i < len(b.negativeASCII); i++ { - b.negativeASCII[i] = last - beforefirst - } - - b.lowASCII = 127 - b.highASCII = 0 - - for examine = last; examine != beforefirst; examine -= bump { - ch = b.pattern[examine] - - switch { - case ch < 128: - if b.lowASCII > ch { - b.lowASCII = ch - } - - if b.highASCII < ch { - b.highASCII = ch - } - - if b.negativeASCII[ch] == last-beforefirst { - b.negativeASCII[ch] = last - examine - } - case ch <= 0xffff: - i, j := ch>>8, ch&0xFF - - if b.negativeUnicode == nil { - b.negativeUnicode = make([][]int, 256) - } - - if b.negativeUnicode[i] == nil { - newarray := make([]int, 256) - - for k := 0; k < len(newarray); k++ { - newarray[k] = last - beforefirst - } - - if i == 0 { - copy(newarray, b.negativeASCII) - //TODO: this line needed? - b.negativeASCII = newarray - } - - b.negativeUnicode[i] = newarray - } - - if b.negativeUnicode[i][j] == last-beforefirst { - b.negativeUnicode[i][j] = last - examine - } - default: - // we can't do the filter because this algo doesn't support - // unicode chars >0xffff - return nil - } - } - - return b -} - -func (b *BmPrefix) String() string { - return string(b.pattern) -} - -// Dump returns the contents of the filter as a human readable string -func (b *BmPrefix) Dump(indent string) string { - buf := &bytes.Buffer{} - - fmt.Fprintf(buf, "%sBM Pattern: %s\n%sPositive: ", indent, string(b.pattern), indent) - for i := 0; i < len(b.positive); i++ { - buf.WriteString(strconv.Itoa(b.positive[i])) - buf.WriteRune(' ') - } - buf.WriteRune('\n') - - if b.negativeASCII != nil { - buf.WriteString(indent) - buf.WriteString("Negative table\n") - for i := 0; i < len(b.negativeASCII); i++ { - if b.negativeASCII[i] != len(b.pattern) { - fmt.Fprintf(buf, "%s %s %s\n", indent, Escape(string(rune(i))), strconv.Itoa(b.negativeASCII[i])) - } - } - } - - return buf.String() -} - -// Scan uses the Boyer-Moore algorithm to find the first occurrence -// of the specified string within text, beginning at index, and -// constrained within beglimit and endlimit. -// -// The direction and case-sensitivity of the match is determined -// by the arguments to the RegexBoyerMoore constructor. -func (b *BmPrefix) Scan(text []rune, index, beglimit, endlimit int) int { - var ( - defadv, test, test2 int - match, startmatch, endmatch int - bump, advance int - chTest rune - unicodeLookup []int - ) - - if !b.rightToLeft { - defadv = len(b.pattern) - startmatch = len(b.pattern) - 1 - endmatch = 0 - test = index + defadv - 1 - bump = 1 - } else { - defadv = -len(b.pattern) - startmatch = 0 - endmatch = -defadv - 1 - test = index + defadv - bump = -1 - } - - chMatch := b.pattern[startmatch] - - for { - if test >= endlimit || test < beglimit { - return -1 - } - - chTest = text[test] - - if b.caseInsensitive { - chTest = unicode.ToLower(chTest) - } - - if chTest != chMatch { - if chTest < 128 { - advance = b.negativeASCII[chTest] - } else if chTest < 0xffff && len(b.negativeUnicode) > 0 { - unicodeLookup = b.negativeUnicode[chTest>>8] - if len(unicodeLookup) > 0 { - advance = unicodeLookup[chTest&0xFF] - } else { - advance = defadv - } - } else { - advance = defadv - } - - test += advance - } else { // if (chTest == chMatch) - test2 = test - match = startmatch - - for { - if match == endmatch { - if b.rightToLeft { - return test2 + 1 - } else { - return test2 - } - } - - match -= bump - test2 -= bump - - chTest = text[test2] - - if b.caseInsensitive { - chTest = unicode.ToLower(chTest) - } - - if chTest != b.pattern[match] { - advance = b.positive[match] - if chTest < 128 { - test2 = (match - startmatch) + b.negativeASCII[chTest] - } else if chTest < 0xffff && len(b.negativeUnicode) > 0 { - unicodeLookup = b.negativeUnicode[chTest>>8] - if len(unicodeLookup) > 0 { - test2 = (match - startmatch) + unicodeLookup[chTest&0xFF] - } else { - test += advance - break - } - } else { - test += advance - break - } - - if b.rightToLeft { - if test2 < advance { - advance = test2 - } - } else if test2 > advance { - advance = test2 - } - - test += advance - break - } - } - } - } -} - -// When a regex is anchored, we can do a quick IsMatch test instead of a Scan -func (b *BmPrefix) IsMatch(text []rune, index, beglimit, endlimit int) bool { - if !b.rightToLeft { - if index < beglimit || endlimit-index < len(b.pattern) { - return false - } - - return b.matchPattern(text, index) - } else { - if index > endlimit || index-beglimit < len(b.pattern) { - return false - } - - return b.matchPattern(text, index-len(b.pattern)) - } -} - -func (b *BmPrefix) matchPattern(text []rune, index int) bool { - if len(text)-index < len(b.pattern) { - return false - } - - if b.caseInsensitive { - for i := 0; i < len(b.pattern); i++ { - //Debug.Assert(textinfo.ToLower(_pattern[i]) == _pattern[i], "pattern should be converted to lower case in constructor!"); - if unicode.ToLower(text[index+i]) != b.pattern[i] { - return false - } - } - return true - } else { - for i := 0; i < len(b.pattern); i++ { - if text[index+i] != b.pattern[i] { - return false - } - } - return true - } -} - -type AnchorLoc int16 - -// where the regex can be pegged -const ( - AnchorBeginning AnchorLoc = 0x0001 - AnchorBol = 0x0002 - AnchorStart = 0x0004 - AnchorEol = 0x0008 - AnchorEndZ = 0x0010 - AnchorEnd = 0x0020 - AnchorBoundary = 0x0040 - AnchorECMABoundary = 0x0080 -) - -func getAnchors(tree *RegexTree) AnchorLoc { - - var concatNode *regexNode - nextChild, result := 0, AnchorLoc(0) - - curNode := tree.root - - for { - switch curNode.t { - case ntConcatenate: - if len(curNode.children) > 0 { - concatNode = curNode - nextChild = 0 - } - - case ntGreedy, ntCapture: - curNode = curNode.children[0] - concatNode = nil - continue - - case ntBol, ntEol, ntBoundary, ntECMABoundary, ntBeginning, - ntStart, ntEndZ, ntEnd: - return result | anchorFromType(curNode.t) - - case ntEmpty, ntRequire, ntPrevent: - - default: - return result - } - - if concatNode == nil || nextChild >= len(concatNode.children) { - return result - } - - curNode = concatNode.children[nextChild] - nextChild++ - } -} - -func anchorFromType(t nodeType) AnchorLoc { - switch t { - case ntBol: - return AnchorBol - case ntEol: - return AnchorEol - case ntBoundary: - return AnchorBoundary - case ntECMABoundary: - return AnchorECMABoundary - case ntBeginning: - return AnchorBeginning - case ntStart: - return AnchorStart - case ntEndZ: - return AnchorEndZ - case ntEnd: - return AnchorEnd - default: - return 0 - } -} - -// anchorDescription returns a human-readable description of the anchors -func (anchors AnchorLoc) String() string { - buf := &bytes.Buffer{} - - if 0 != (anchors & AnchorBeginning) { - buf.WriteString(", Beginning") - } - if 0 != (anchors & AnchorStart) { - buf.WriteString(", Start") - } - if 0 != (anchors & AnchorBol) { - buf.WriteString(", Bol") - } - if 0 != (anchors & AnchorBoundary) { - buf.WriteString(", Boundary") - } - if 0 != (anchors & AnchorECMABoundary) { - buf.WriteString(", ECMABoundary") - } - if 0 != (anchors & AnchorEol) { - buf.WriteString(", Eol") - } - if 0 != (anchors & AnchorEnd) { - buf.WriteString(", End") - } - if 0 != (anchors & AnchorEndZ) { - buf.WriteString(", EndZ") - } - - // trim off comma - if buf.Len() >= 2 { - return buf.String()[2:] - } - return "None" -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/replacerdata.go b/vendor/github.com/dlclark/regexp2/syntax/replacerdata.go deleted file mode 100644 index bcf4d3f2..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/replacerdata.go +++ /dev/null @@ -1,87 +0,0 @@ -package syntax - -import ( - "bytes" - "errors" -) - -type ReplacerData struct { - Rep string - Strings []string - Rules []int -} - -const ( - replaceSpecials = 4 - replaceLeftPortion = -1 - replaceRightPortion = -2 - replaceLastGroup = -3 - replaceWholeString = -4 -) - -//ErrReplacementError is a general error during parsing the replacement text -var ErrReplacementError = errors.New("Replacement pattern error.") - -// NewReplacerData will populate a reusable replacer data struct based on the given replacement string -// and the capture group data from a regexp -func NewReplacerData(rep string, caps map[int]int, capsize int, capnames map[string]int, op RegexOptions) (*ReplacerData, error) { - p := parser{ - options: op, - caps: caps, - capsize: capsize, - capnames: capnames, - } - p.setPattern(rep) - concat, err := p.scanReplacement() - if err != nil { - return nil, err - } - - if concat.t != ntConcatenate { - panic(ErrReplacementError) - } - - sb := &bytes.Buffer{} - var ( - strings []string - rules []int - ) - - for _, child := range concat.children { - switch child.t { - case ntMulti: - child.writeStrToBuf(sb) - - case ntOne: - sb.WriteRune(child.ch) - - case ntRef: - if sb.Len() > 0 { - rules = append(rules, len(strings)) - strings = append(strings, sb.String()) - sb.Reset() - } - slot := child.m - - if len(caps) > 0 && slot >= 0 { - slot = caps[slot] - } - - rules = append(rules, -replaceSpecials-1-slot) - - default: - panic(ErrReplacementError) - } - } - - if sb.Len() > 0 { - rules = append(rules, len(strings)) - strings = append(strings, sb.String()) - } - - return &ReplacerData{ - Rep: rep, - Strings: strings, - Rules: rules, - }, nil -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/tree.go b/vendor/github.com/dlclark/regexp2/syntax/tree.go deleted file mode 100644 index ea288293..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/tree.go +++ /dev/null @@ -1,654 +0,0 @@ -package syntax - -import ( - "bytes" - "fmt" - "math" - "strconv" -) - -type RegexTree struct { - root *regexNode - caps map[int]int - capnumlist []int - captop int - Capnames map[string]int - Caplist []string - options RegexOptions -} - -// It is built into a parsed tree for a regular expression. - -// Implementation notes: -// -// Since the node tree is a temporary data structure only used -// during compilation of the regexp to integer codes, it's -// designed for clarity and convenience rather than -// space efficiency. -// -// RegexNodes are built into a tree, linked by the n.children list. -// Each node also has a n.parent and n.ichild member indicating -// its parent and which child # it is in its parent's list. -// -// RegexNodes come in as many types as there are constructs in -// a regular expression, for example, "concatenate", "alternate", -// "one", "rept", "group". There are also node types for basic -// peephole optimizations, e.g., "onerep", "notsetrep", etc. -// -// Because perl 5 allows "lookback" groups that scan backwards, -// each node also gets a "direction". Normally the value of -// boolean n.backward = false. -// -// During parsing, top-level nodes are also stacked onto a parse -// stack (a stack of trees). For this purpose we have a n.next -// pointer. [Note that to save a few bytes, we could overload the -// n.parent pointer instead.] -// -// On the parse stack, each tree has a "role" - basically, the -// nonterminal in the grammar that the parser has currently -// assigned to the tree. That code is stored in n.role. -// -// Finally, some of the different kinds of nodes have data. -// Two integers (for the looping constructs) are stored in -// n.operands, an an object (either a string or a set) -// is stored in n.data -type regexNode struct { - t nodeType - children []*regexNode - str []rune - set *CharSet - ch rune - m int - n int - options RegexOptions - next *regexNode -} - -type nodeType int32 - -const ( - // The following are leaves, and correspond to primitive operations - - ntOnerep nodeType = 0 // lef,back char,min,max a {n} - ntNotonerep = 1 // lef,back char,min,max .{n} - ntSetrep = 2 // lef,back set,min,max [\d]{n} - ntOneloop = 3 // lef,back char,min,max a {,n} - ntNotoneloop = 4 // lef,back char,min,max .{,n} - ntSetloop = 5 // lef,back set,min,max [\d]{,n} - ntOnelazy = 6 // lef,back char,min,max a {,n}? - ntNotonelazy = 7 // lef,back char,min,max .{,n}? - ntSetlazy = 8 // lef,back set,min,max [\d]{,n}? - ntOne = 9 // lef char a - ntNotone = 10 // lef char [^a] - ntSet = 11 // lef set [a-z\s] \w \s \d - ntMulti = 12 // lef string abcd - ntRef = 13 // lef group \# - ntBol = 14 // ^ - ntEol = 15 // $ - ntBoundary = 16 // \b - ntNonboundary = 17 // \B - ntBeginning = 18 // \A - ntStart = 19 // \G - ntEndZ = 20 // \Z - ntEnd = 21 // \Z - - // Interior nodes do not correspond to primitive operations, but - // control structures compositing other operations - - // Concat and alternate take n children, and can run forward or backwards - - ntNothing = 22 // [] - ntEmpty = 23 // () - ntAlternate = 24 // a|b - ntConcatenate = 25 // ab - ntLoop = 26 // m,x * + ? {,} - ntLazyloop = 27 // m,x *? +? ?? {,}? - ntCapture = 28 // n () - ntGroup = 29 // (?:) - ntRequire = 30 // (?=) (?<=) - ntPrevent = 31 // (?!) (?) (?<) - ntTestref = 33 // (?(n) | ) - ntTestgroup = 34 // (?(...) | ) - - ntECMABoundary = 41 // \b - ntNonECMABoundary = 42 // \B -) - -func newRegexNode(t nodeType, opt RegexOptions) *regexNode { - return ®exNode{ - t: t, - options: opt, - } -} - -func newRegexNodeCh(t nodeType, opt RegexOptions, ch rune) *regexNode { - return ®exNode{ - t: t, - options: opt, - ch: ch, - } -} - -func newRegexNodeStr(t nodeType, opt RegexOptions, str []rune) *regexNode { - return ®exNode{ - t: t, - options: opt, - str: str, - } -} - -func newRegexNodeSet(t nodeType, opt RegexOptions, set *CharSet) *regexNode { - return ®exNode{ - t: t, - options: opt, - set: set, - } -} - -func newRegexNodeM(t nodeType, opt RegexOptions, m int) *regexNode { - return ®exNode{ - t: t, - options: opt, - m: m, - } -} -func newRegexNodeMN(t nodeType, opt RegexOptions, m, n int) *regexNode { - return ®exNode{ - t: t, - options: opt, - m: m, - n: n, - } -} - -func (n *regexNode) writeStrToBuf(buf *bytes.Buffer) { - for i := 0; i < len(n.str); i++ { - buf.WriteRune(n.str[i]) - } -} - -func (n *regexNode) addChild(child *regexNode) { - reduced := child.reduce() - n.children = append(n.children, reduced) - reduced.next = n -} - -func (n *regexNode) insertChildren(afterIndex int, nodes []*regexNode) { - newChildren := make([]*regexNode, 0, len(n.children)+len(nodes)) - n.children = append(append(append(newChildren, n.children[:afterIndex]...), nodes...), n.children[afterIndex:]...) -} - -// removes children including the start but not the end index -func (n *regexNode) removeChildren(startIndex, endIndex int) { - n.children = append(n.children[:startIndex], n.children[endIndex:]...) -} - -// Pass type as OneLazy or OneLoop -func (n *regexNode) makeRep(t nodeType, min, max int) { - n.t += (t - ntOne) - n.m = min - n.n = max -} - -func (n *regexNode) reduce() *regexNode { - switch n.t { - case ntAlternate: - return n.reduceAlternation() - - case ntConcatenate: - return n.reduceConcatenation() - - case ntLoop, ntLazyloop: - return n.reduceRep() - - case ntGroup: - return n.reduceGroup() - - case ntSet, ntSetloop: - return n.reduceSet() - - default: - return n - } -} - -// Basic optimization. Single-letter alternations can be replaced -// by faster set specifications, and nested alternations with no -// intervening operators can be flattened: -// -// a|b|c|def|g|h -> [a-c]|def|[gh] -// apple|(?:orange|pear)|grape -> apple|orange|pear|grape -func (n *regexNode) reduceAlternation() *regexNode { - if len(n.children) == 0 { - return newRegexNode(ntNothing, n.options) - } - - wasLastSet := false - lastNodeCannotMerge := false - var optionsLast RegexOptions - var i, j int - - for i, j = 0, 0; i < len(n.children); i, j = i+1, j+1 { - at := n.children[i] - - if j < i { - n.children[j] = at - } - - for { - if at.t == ntAlternate { - for k := 0; k < len(at.children); k++ { - at.children[k].next = n - } - n.insertChildren(i+1, at.children) - - j-- - } else if at.t == ntSet || at.t == ntOne { - // Cannot merge sets if L or I options differ, or if either are negated. - optionsAt := at.options & (RightToLeft | IgnoreCase) - - if at.t == ntSet { - if !wasLastSet || optionsLast != optionsAt || lastNodeCannotMerge || !at.set.IsMergeable() { - wasLastSet = true - lastNodeCannotMerge = !at.set.IsMergeable() - optionsLast = optionsAt - break - } - } else if !wasLastSet || optionsLast != optionsAt || lastNodeCannotMerge { - wasLastSet = true - lastNodeCannotMerge = false - optionsLast = optionsAt - break - } - - // The last node was a Set or a One, we're a Set or One and our options are the same. - // Merge the two nodes. - j-- - prev := n.children[j] - - var prevCharClass *CharSet - if prev.t == ntOne { - prevCharClass = &CharSet{} - prevCharClass.addChar(prev.ch) - } else { - prevCharClass = prev.set - } - - if at.t == ntOne { - prevCharClass.addChar(at.ch) - } else { - prevCharClass.addSet(*at.set) - } - - prev.t = ntSet - prev.set = prevCharClass - } else if at.t == ntNothing { - j-- - } else { - wasLastSet = false - lastNodeCannotMerge = false - } - break - } - } - - if j < i { - n.removeChildren(j, i) - } - - return n.stripEnation(ntNothing) -} - -// Basic optimization. Adjacent strings can be concatenated. -// -// (?:abc)(?:def) -> abcdef -func (n *regexNode) reduceConcatenation() *regexNode { - // Eliminate empties and concat adjacent strings/chars - - var optionsLast RegexOptions - var optionsAt RegexOptions - var i, j int - - if len(n.children) == 0 { - return newRegexNode(ntEmpty, n.options) - } - - wasLastString := false - - for i, j = 0, 0; i < len(n.children); i, j = i+1, j+1 { - var at, prev *regexNode - - at = n.children[i] - - if j < i { - n.children[j] = at - } - - if at.t == ntConcatenate && - ((at.options & RightToLeft) == (n.options & RightToLeft)) { - for k := 0; k < len(at.children); k++ { - at.children[k].next = n - } - - //insert at.children at i+1 index in n.children - n.insertChildren(i+1, at.children) - - j-- - } else if at.t == ntMulti || at.t == ntOne { - // Cannot merge strings if L or I options differ - optionsAt = at.options & (RightToLeft | IgnoreCase) - - if !wasLastString || optionsLast != optionsAt { - wasLastString = true - optionsLast = optionsAt - continue - } - - j-- - prev = n.children[j] - - if prev.t == ntOne { - prev.t = ntMulti - prev.str = []rune{prev.ch} - } - - if (optionsAt & RightToLeft) == 0 { - if at.t == ntOne { - prev.str = append(prev.str, at.ch) - } else { - prev.str = append(prev.str, at.str...) - } - } else { - if at.t == ntOne { - // insert at the front by expanding our slice, copying the data over, and then setting the value - prev.str = append(prev.str, 0) - copy(prev.str[1:], prev.str) - prev.str[0] = at.ch - } else { - //insert at the front...this one we'll make a new slice and copy both into it - merge := make([]rune, len(prev.str)+len(at.str)) - copy(merge, at.str) - copy(merge[len(at.str):], prev.str) - prev.str = merge - } - } - } else if at.t == ntEmpty { - j-- - } else { - wasLastString = false - } - } - - if j < i { - // remove indices j through i from the children - n.removeChildren(j, i) - } - - return n.stripEnation(ntEmpty) -} - -// Nested repeaters just get multiplied with each other if they're not -// too lumpy -func (n *regexNode) reduceRep() *regexNode { - - u := n - t := n.t - min := n.m - max := n.n - - for { - if len(u.children) == 0 { - break - } - - child := u.children[0] - - // multiply reps of the same type only - if child.t != t { - childType := child.t - - if !(childType >= ntOneloop && childType <= ntSetloop && t == ntLoop || - childType >= ntOnelazy && childType <= ntSetlazy && t == ntLazyloop) { - break - } - } - - // child can be too lumpy to blur, e.g., (a {100,105}) {3} or (a {2,})? - // [but things like (a {2,})+ are not too lumpy...] - if u.m == 0 && child.m > 1 || child.n < child.m*2 { - break - } - - u = child - if u.m > 0 { - if (math.MaxInt32-1)/u.m < min { - u.m = math.MaxInt32 - } else { - u.m = u.m * min - } - } - if u.n > 0 { - if (math.MaxInt32-1)/u.n < max { - u.n = math.MaxInt32 - } else { - u.n = u.n * max - } - } - } - - if math.MaxInt32 == min { - return newRegexNode(ntNothing, n.options) - } - return u - -} - -// Simple optimization. If a concatenation or alternation has only -// one child strip out the intermediate node. If it has zero children, -// turn it into an empty. -func (n *regexNode) stripEnation(emptyType nodeType) *regexNode { - switch len(n.children) { - case 0: - return newRegexNode(emptyType, n.options) - case 1: - return n.children[0] - default: - return n - } -} - -func (n *regexNode) reduceGroup() *regexNode { - u := n - - for u.t == ntGroup { - u = u.children[0] - } - - return u -} - -// Simple optimization. If a set is a singleton, an inverse singleton, -// or empty, it's transformed accordingly. -func (n *regexNode) reduceSet() *regexNode { - // Extract empty-set, one and not-one case as special - - if n.set == nil { - n.t = ntNothing - } else if n.set.IsSingleton() { - n.ch = n.set.SingletonChar() - n.set = nil - n.t += (ntOne - ntSet) - } else if n.set.IsSingletonInverse() { - n.ch = n.set.SingletonChar() - n.set = nil - n.t += (ntNotone - ntSet) - } - - return n -} - -func (n *regexNode) reverseLeft() *regexNode { - if n.options&RightToLeft != 0 && n.t == ntConcatenate && len(n.children) > 0 { - //reverse children order - for left, right := 0, len(n.children)-1; left < right; left, right = left+1, right-1 { - n.children[left], n.children[right] = n.children[right], n.children[left] - } - } - - return n -} - -func (n *regexNode) makeQuantifier(lazy bool, min, max int) *regexNode { - if min == 0 && max == 0 { - return newRegexNode(ntEmpty, n.options) - } - - if min == 1 && max == 1 { - return n - } - - switch n.t { - case ntOne, ntNotone, ntSet: - if lazy { - n.makeRep(Onelazy, min, max) - } else { - n.makeRep(Oneloop, min, max) - } - return n - - default: - var t nodeType - if lazy { - t = ntLazyloop - } else { - t = ntLoop - } - result := newRegexNodeMN(t, n.options, min, max) - result.addChild(n) - return result - } -} - -// debug functions - -var typeStr = []string{ - "Onerep", "Notonerep", "Setrep", - "Oneloop", "Notoneloop", "Setloop", - "Onelazy", "Notonelazy", "Setlazy", - "One", "Notone", "Set", - "Multi", "Ref", - "Bol", "Eol", "Boundary", "Nonboundary", - "Beginning", "Start", "EndZ", "End", - "Nothing", "Empty", - "Alternate", "Concatenate", - "Loop", "Lazyloop", - "Capture", "Group", "Require", "Prevent", "Greedy", - "Testref", "Testgroup", - "Unknown", "Unknown", "Unknown", - "Unknown", "Unknown", "Unknown", - "ECMABoundary", "NonECMABoundary", -} - -func (n *regexNode) description() string { - buf := &bytes.Buffer{} - - buf.WriteString(typeStr[n.t]) - - if (n.options & ExplicitCapture) != 0 { - buf.WriteString("-C") - } - if (n.options & IgnoreCase) != 0 { - buf.WriteString("-I") - } - if (n.options & RightToLeft) != 0 { - buf.WriteString("-L") - } - if (n.options & Multiline) != 0 { - buf.WriteString("-M") - } - if (n.options & Singleline) != 0 { - buf.WriteString("-S") - } - if (n.options & IgnorePatternWhitespace) != 0 { - buf.WriteString("-X") - } - if (n.options & ECMAScript) != 0 { - buf.WriteString("-E") - } - - switch n.t { - case ntOneloop, ntNotoneloop, ntOnelazy, ntNotonelazy, ntOne, ntNotone: - buf.WriteString("(Ch = " + CharDescription(n.ch) + ")") - break - case ntCapture: - buf.WriteString("(index = " + strconv.Itoa(n.m) + ", unindex = " + strconv.Itoa(n.n) + ")") - break - case ntRef, ntTestref: - buf.WriteString("(index = " + strconv.Itoa(n.m) + ")") - break - case ntMulti: - fmt.Fprintf(buf, "(String = %s)", string(n.str)) - break - case ntSet, ntSetloop, ntSetlazy: - buf.WriteString("(Set = " + n.set.String() + ")") - break - } - - switch n.t { - case ntOneloop, ntNotoneloop, ntOnelazy, ntNotonelazy, ntSetloop, ntSetlazy, ntLoop, ntLazyloop: - buf.WriteString("(Min = ") - buf.WriteString(strconv.Itoa(n.m)) - buf.WriteString(", Max = ") - if n.n == math.MaxInt32 { - buf.WriteString("inf") - } else { - buf.WriteString(strconv.Itoa(n.n)) - } - buf.WriteString(")") - - break - } - - return buf.String() -} - -var padSpace = []byte(" ") - -func (t *RegexTree) Dump() string { - return t.root.dump() -} - -func (n *regexNode) dump() string { - var stack []int - CurNode := n - CurChild := 0 - - buf := bytes.NewBufferString(CurNode.description()) - buf.WriteRune('\n') - - for { - if CurNode.children != nil && CurChild < len(CurNode.children) { - stack = append(stack, CurChild+1) - CurNode = CurNode.children[CurChild] - CurChild = 0 - - Depth := len(stack) - if Depth > 32 { - Depth = 32 - } - buf.Write(padSpace[:Depth]) - buf.WriteString(CurNode.description()) - buf.WriteRune('\n') - } else { - if len(stack) == 0 { - break - } - - CurChild = stack[len(stack)-1] - stack = stack[:len(stack)-1] - CurNode = CurNode.next - } - } - return buf.String() -} diff --git a/vendor/github.com/dlclark/regexp2/syntax/writer.go b/vendor/github.com/dlclark/regexp2/syntax/writer.go deleted file mode 100644 index a5aa11ca..00000000 --- a/vendor/github.com/dlclark/regexp2/syntax/writer.go +++ /dev/null @@ -1,500 +0,0 @@ -package syntax - -import ( - "bytes" - "fmt" - "math" - "os" -) - -func Write(tree *RegexTree) (*Code, error) { - w := writer{ - intStack: make([]int, 0, 32), - emitted: make([]int, 2), - stringhash: make(map[string]int), - sethash: make(map[string]int), - } - - code, err := w.codeFromTree(tree) - - if tree.options&Debug > 0 && code != nil { - os.Stdout.WriteString(code.Dump()) - os.Stdout.WriteString("\n") - } - - return code, err -} - -type writer struct { - emitted []int - - intStack []int - curpos int - stringhash map[string]int - stringtable [][]rune - sethash map[string]int - settable []*CharSet - counting bool - count int - trackcount int - caps map[int]int -} - -const ( - beforeChild nodeType = 64 - afterChild = 128 - //MaxPrefixSize is the largest number of runes we'll use for a BoyerMoyer prefix - MaxPrefixSize = 50 -) - -// The top level RegexCode generator. It does a depth-first walk -// through the tree and calls EmitFragment to emits code before -// and after each child of an interior node, and at each leaf. -// -// It runs two passes, first to count the size of the generated -// code, and second to generate the code. -// -// We should time it against the alternative, which is -// to just generate the code and grow the array as we go. -func (w *writer) codeFromTree(tree *RegexTree) (*Code, error) { - var ( - curNode *regexNode - curChild int - capsize int - ) - // construct sparse capnum mapping if some numbers are unused - - if tree.capnumlist == nil || tree.captop == len(tree.capnumlist) { - capsize = tree.captop - w.caps = nil - } else { - capsize = len(tree.capnumlist) - w.caps = tree.caps - for i := 0; i < len(tree.capnumlist); i++ { - w.caps[tree.capnumlist[i]] = i - } - } - - w.counting = true - - for { - if !w.counting { - w.emitted = make([]int, w.count) - } - - curNode = tree.root - curChild = 0 - - w.emit1(Lazybranch, 0) - - for { - if len(curNode.children) == 0 { - w.emitFragment(curNode.t, curNode, 0) - } else if curChild < len(curNode.children) { - w.emitFragment(curNode.t|beforeChild, curNode, curChild) - - curNode = curNode.children[curChild] - - w.pushInt(curChild) - curChild = 0 - continue - } - - if w.emptyStack() { - break - } - - curChild = w.popInt() - curNode = curNode.next - - w.emitFragment(curNode.t|afterChild, curNode, curChild) - curChild++ - } - - w.patchJump(0, w.curPos()) - w.emit(Stop) - - if !w.counting { - break - } - - w.counting = false - } - - fcPrefix := getFirstCharsPrefix(tree) - prefix := getPrefix(tree) - rtl := (tree.options & RightToLeft) != 0 - - var bmPrefix *BmPrefix - //TODO: benchmark string prefixes - if prefix != nil && len(prefix.PrefixStr) > 0 && MaxPrefixSize > 0 { - if len(prefix.PrefixStr) > MaxPrefixSize { - // limit prefix changes to 10k - prefix.PrefixStr = prefix.PrefixStr[:MaxPrefixSize] - } - bmPrefix = newBmPrefix(prefix.PrefixStr, prefix.CaseInsensitive, rtl) - } else { - bmPrefix = nil - } - - return &Code{ - Codes: w.emitted, - Strings: w.stringtable, - Sets: w.settable, - TrackCount: w.trackcount, - Caps: w.caps, - Capsize: capsize, - FcPrefix: fcPrefix, - BmPrefix: bmPrefix, - Anchors: getAnchors(tree), - RightToLeft: rtl, - }, nil -} - -// The main RegexCode generator. It does a depth-first walk -// through the tree and calls EmitFragment to emits code before -// and after each child of an interior node, and at each leaf. -func (w *writer) emitFragment(nodetype nodeType, node *regexNode, curIndex int) error { - bits := InstOp(0) - - if nodetype <= ntRef { - if (node.options & RightToLeft) != 0 { - bits |= Rtl - } - if (node.options & IgnoreCase) != 0 { - bits |= Ci - } - } - ntBits := nodeType(bits) - - switch nodetype { - case ntConcatenate | beforeChild, ntConcatenate | afterChild, ntEmpty: - break - - case ntAlternate | beforeChild: - if curIndex < len(node.children)-1 { - w.pushInt(w.curPos()) - w.emit1(Lazybranch, 0) - } - - case ntAlternate | afterChild: - if curIndex < len(node.children)-1 { - lbPos := w.popInt() - w.pushInt(w.curPos()) - w.emit1(Goto, 0) - w.patchJump(lbPos, w.curPos()) - } else { - for i := 0; i < curIndex; i++ { - w.patchJump(w.popInt(), w.curPos()) - } - } - break - - case ntTestref | beforeChild: - if curIndex == 0 { - w.emit(Setjump) - w.pushInt(w.curPos()) - w.emit1(Lazybranch, 0) - w.emit1(Testref, w.mapCapnum(node.m)) - w.emit(Forejump) - } - - case ntTestref | afterChild: - if curIndex == 0 { - branchpos := w.popInt() - w.pushInt(w.curPos()) - w.emit1(Goto, 0) - w.patchJump(branchpos, w.curPos()) - w.emit(Forejump) - if len(node.children) <= 1 { - w.patchJump(w.popInt(), w.curPos()) - } - } else if curIndex == 1 { - w.patchJump(w.popInt(), w.curPos()) - } - - case ntTestgroup | beforeChild: - if curIndex == 0 { - w.emit(Setjump) - w.emit(Setmark) - w.pushInt(w.curPos()) - w.emit1(Lazybranch, 0) - } - - case ntTestgroup | afterChild: - if curIndex == 0 { - w.emit(Getmark) - w.emit(Forejump) - } else if curIndex == 1 { - Branchpos := w.popInt() - w.pushInt(w.curPos()) - w.emit1(Goto, 0) - w.patchJump(Branchpos, w.curPos()) - w.emit(Getmark) - w.emit(Forejump) - if len(node.children) <= 2 { - w.patchJump(w.popInt(), w.curPos()) - } - } else if curIndex == 2 { - w.patchJump(w.popInt(), w.curPos()) - } - - case ntLoop | beforeChild, ntLazyloop | beforeChild: - - if node.n < math.MaxInt32 || node.m > 1 { - if node.m == 0 { - w.emit1(Nullcount, 0) - } else { - w.emit1(Setcount, 1-node.m) - } - } else if node.m == 0 { - w.emit(Nullmark) - } else { - w.emit(Setmark) - } - - if node.m == 0 { - w.pushInt(w.curPos()) - w.emit1(Goto, 0) - } - w.pushInt(w.curPos()) - - case ntLoop | afterChild, ntLazyloop | afterChild: - - startJumpPos := w.curPos() - lazy := (nodetype - (ntLoop | afterChild)) - - if node.n < math.MaxInt32 || node.m > 1 { - if node.n == math.MaxInt32 { - w.emit2(InstOp(Branchcount+lazy), w.popInt(), math.MaxInt32) - } else { - w.emit2(InstOp(Branchcount+lazy), w.popInt(), node.n-node.m) - } - } else { - w.emit1(InstOp(Branchmark+lazy), w.popInt()) - } - - if node.m == 0 { - w.patchJump(w.popInt(), startJumpPos) - } - - case ntGroup | beforeChild, ntGroup | afterChild: - - case ntCapture | beforeChild: - w.emit(Setmark) - - case ntCapture | afterChild: - w.emit2(Capturemark, w.mapCapnum(node.m), w.mapCapnum(node.n)) - - case ntRequire | beforeChild: - // NOTE: the following line causes lookahead/lookbehind to be - // NON-BACKTRACKING. It can be commented out with (*) - w.emit(Setjump) - - w.emit(Setmark) - - case ntRequire | afterChild: - w.emit(Getmark) - - // NOTE: the following line causes lookahead/lookbehind to be - // NON-BACKTRACKING. It can be commented out with (*) - w.emit(Forejump) - - case ntPrevent | beforeChild: - w.emit(Setjump) - w.pushInt(w.curPos()) - w.emit1(Lazybranch, 0) - - case ntPrevent | afterChild: - w.emit(Backjump) - w.patchJump(w.popInt(), w.curPos()) - w.emit(Forejump) - - case ntGreedy | beforeChild: - w.emit(Setjump) - - case ntGreedy | afterChild: - w.emit(Forejump) - - case ntOne, ntNotone: - w.emit1(InstOp(node.t|ntBits), int(node.ch)) - - case ntNotoneloop, ntNotonelazy, ntOneloop, ntOnelazy: - if node.m > 0 { - if node.t == ntOneloop || node.t == ntOnelazy { - w.emit2(Onerep|bits, int(node.ch), node.m) - } else { - w.emit2(Notonerep|bits, int(node.ch), node.m) - } - } - if node.n > node.m { - if node.n == math.MaxInt32 { - w.emit2(InstOp(node.t|ntBits), int(node.ch), math.MaxInt32) - } else { - w.emit2(InstOp(node.t|ntBits), int(node.ch), node.n-node.m) - } - } - - case ntSetloop, ntSetlazy: - if node.m > 0 { - w.emit2(Setrep|bits, w.setCode(node.set), node.m) - } - if node.n > node.m { - if node.n == math.MaxInt32 { - w.emit2(InstOp(node.t|ntBits), w.setCode(node.set), math.MaxInt32) - } else { - w.emit2(InstOp(node.t|ntBits), w.setCode(node.set), node.n-node.m) - } - } - - case ntMulti: - w.emit1(InstOp(node.t|ntBits), w.stringCode(node.str)) - - case ntSet: - w.emit1(InstOp(node.t|ntBits), w.setCode(node.set)) - - case ntRef: - w.emit1(InstOp(node.t|ntBits), w.mapCapnum(node.m)) - - case ntNothing, ntBol, ntEol, ntBoundary, ntNonboundary, ntECMABoundary, ntNonECMABoundary, ntBeginning, ntStart, ntEndZ, ntEnd: - w.emit(InstOp(node.t)) - - default: - return fmt.Errorf("unexpected opcode in regular expression generation: %v", nodetype) - } - - return nil -} - -// To avoid recursion, we use a simple integer stack. -// This is the push. -func (w *writer) pushInt(i int) { - w.intStack = append(w.intStack, i) -} - -// Returns true if the stack is empty. -func (w *writer) emptyStack() bool { - return len(w.intStack) == 0 -} - -// This is the pop. -func (w *writer) popInt() int { - //get our item - idx := len(w.intStack) - 1 - i := w.intStack[idx] - //trim our slice - w.intStack = w.intStack[:idx] - return i -} - -// Returns the current position in the emitted code. -func (w *writer) curPos() int { - return w.curpos -} - -// Fixes up a jump instruction at the specified offset -// so that it jumps to the specified jumpDest. -func (w *writer) patchJump(offset, jumpDest int) { - w.emitted[offset+1] = jumpDest -} - -// Returns an index in the set table for a charset -// uses a map to eliminate duplicates. -func (w *writer) setCode(set *CharSet) int { - if w.counting { - return 0 - } - - buf := &bytes.Buffer{} - - set.mapHashFill(buf) - hash := buf.String() - i, ok := w.sethash[hash] - if !ok { - i = len(w.sethash) - w.sethash[hash] = i - w.settable = append(w.settable, set) - } - return i -} - -// Returns an index in the string table for a string. -// uses a map to eliminate duplicates. -func (w *writer) stringCode(str []rune) int { - if w.counting { - return 0 - } - - hash := string(str) - i, ok := w.stringhash[hash] - if !ok { - i = len(w.stringhash) - w.stringhash[hash] = i - w.stringtable = append(w.stringtable, str) - } - - return i -} - -// When generating code on a regex that uses a sparse set -// of capture slots, we hash them to a dense set of indices -// for an array of capture slots. Instead of doing the hash -// at match time, it's done at compile time, here. -func (w *writer) mapCapnum(capnum int) int { - if capnum == -1 { - return -1 - } - - if w.caps != nil { - return w.caps[capnum] - } - - return capnum -} - -// Emits a zero-argument operation. Note that the emit -// functions all run in two modes: they can emit code, or -// they can just count the size of the code. -func (w *writer) emit(op InstOp) { - if w.counting { - w.count++ - if opcodeBacktracks(op) { - w.trackcount++ - } - return - } - w.emitted[w.curpos] = int(op) - w.curpos++ -} - -// Emits a one-argument operation. -func (w *writer) emit1(op InstOp, opd1 int) { - if w.counting { - w.count += 2 - if opcodeBacktracks(op) { - w.trackcount++ - } - return - } - w.emitted[w.curpos] = int(op) - w.curpos++ - w.emitted[w.curpos] = opd1 - w.curpos++ -} - -// Emits a two-argument operation. -func (w *writer) emit2(op InstOp, opd1, opd2 int) { - if w.counting { - w.count += 3 - if opcodeBacktracks(op) { - w.trackcount++ - } - return - } - w.emitted[w.curpos] = int(op) - w.curpos++ - w.emitted[w.curpos] = opd1 - w.curpos++ - w.emitted[w.curpos] = opd2 - w.curpos++ -} diff --git a/vendor/github.com/dlclark/regexp2/testoutput1 b/vendor/github.com/dlclark/regexp2/testoutput1 deleted file mode 100644 index fbf63fdf..00000000 --- a/vendor/github.com/dlclark/regexp2/testoutput1 +++ /dev/null @@ -1,7061 +0,0 @@ -# This set of tests is for features that are compatible with all versions of -# Perl >= 5.10, in non-UTF mode. It should run clean for the 8-bit, 16-bit, and -# 32-bit PCRE libraries, and also using the perltest.pl script. - -#forbid_utf -#newline_default lf any anycrlf -#perltest - -/the quick brown fox/ - the quick brown fox - 0: the quick brown fox - What do you know about the quick brown fox? - 0: the quick brown fox -\= Expect no match - The quick brown FOX -No match - What do you know about THE QUICK BROWN FOX? -No match - -/The quick brown fox/i - the quick brown fox - 0: the quick brown fox - The quick brown FOX - 0: The quick brown FOX - What do you know about the quick brown fox? - 0: the quick brown fox - What do you know about THE QUICK BROWN FOX? - 0: THE QUICK BROWN FOX - -/abcd\t\n\r\f\a\e\071\x3b\$\\\?caxyz/ - abcd\t\n\r\f\a\e9;\$\\?caxyz - 0: abcd\x09\x0a\x0d\x0c\x07\x1b9;$\?caxyz - -/a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/ - abxyzpqrrrabbxyyyypqAzz - 0: abxyzpqrrrabbxyyyypqAzz - abxyzpqrrrabbxyyyypqAzz - 0: abxyzpqrrrabbxyyyypqAzz - aabxyzpqrrrabbxyyyypqAzz - 0: aabxyzpqrrrabbxyyyypqAzz - aaabxyzpqrrrabbxyyyypqAzz - 0: aaabxyzpqrrrabbxyyyypqAzz - aaaabxyzpqrrrabbxyyyypqAzz - 0: aaaabxyzpqrrrabbxyyyypqAzz - abcxyzpqrrrabbxyyyypqAzz - 0: abcxyzpqrrrabbxyyyypqAzz - aabcxyzpqrrrabbxyyyypqAzz - 0: aabcxyzpqrrrabbxyyyypqAzz - aaabcxyzpqrrrabbxyyyypAzz - 0: aaabcxyzpqrrrabbxyyyypAzz - aaabcxyzpqrrrabbxyyyypqAzz - 0: aaabcxyzpqrrrabbxyyyypqAzz - aaabcxyzpqrrrabbxyyyypqqAzz - 0: aaabcxyzpqrrrabbxyyyypqqAzz - aaabcxyzpqrrrabbxyyyypqqqAzz - 0: aaabcxyzpqrrrabbxyyyypqqqAzz - aaabcxyzpqrrrabbxyyyypqqqqAzz - 0: aaabcxyzpqrrrabbxyyyypqqqqAzz - aaabcxyzpqrrrabbxyyyypqqqqqAzz - 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz - aaabcxyzpqrrrabbxyyyypqqqqqqAzz - 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz - aaaabcxyzpqrrrabbxyyyypqAzz - 0: aaaabcxyzpqrrrabbxyyyypqAzz - abxyzzpqrrrabbxyyyypqAzz - 0: abxyzzpqrrrabbxyyyypqAzz - aabxyzzzpqrrrabbxyyyypqAzz - 0: aabxyzzzpqrrrabbxyyyypqAzz - aaabxyzzzzpqrrrabbxyyyypqAzz - 0: aaabxyzzzzpqrrrabbxyyyypqAzz - aaaabxyzzzzpqrrrabbxyyyypqAzz - 0: aaaabxyzzzzpqrrrabbxyyyypqAzz - abcxyzzpqrrrabbxyyyypqAzz - 0: abcxyzzpqrrrabbxyyyypqAzz - aabcxyzzzpqrrrabbxyyyypqAzz - 0: aabcxyzzzpqrrrabbxyyyypqAzz - aaabcxyzzzzpqrrrabbxyyyypqAzz - 0: aaabcxyzzzzpqrrrabbxyyyypqAzz - aaaabcxyzzzzpqrrrabbxyyyypqAzz - 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz - aaaabcxyzzzzpqrrrabbbxyyyypqAzz - 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz - aaaabcxyzzzzpqrrrabbbxyyyyypqAzz - 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz - aaabcxyzpqrrrabbxyyyypABzz - 0: aaabcxyzpqrrrabbxyyyypABzz - aaabcxyzpqrrrabbxyyyypABBzz - 0: aaabcxyzpqrrrabbxyyyypABBzz - >>>aaabxyzpqrrrabbxyyyypqAzz - 0: aaabxyzpqrrrabbxyyyypqAzz - >aaaabxyzpqrrrabbxyyyypqAzz - 0: aaaabxyzpqrrrabbxyyyypqAzz - >>>>abcxyzpqrrrabbxyyyypqAzz - 0: abcxyzpqrrrabbxyyyypqAzz -\= Expect no match - abxyzpqrrabbxyyyypqAzz -No match - abxyzpqrrrrabbxyyyypqAzz -No match - abxyzpqrrrabxyyyypqAzz -No match - aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz -No match - aaaabcxyzzzzpqrrrabbbxyyypqAzz -No match - aaabcxyzpqrrrabbxyyyypqqqqqqqAzz -No match - -/^(abc){1,2}zz/ - abczz - 0: abczz - 1: abc - abcabczz - 0: abcabczz - 1: abc -\= Expect no match - zz -No match - abcabcabczz -No match - >>abczz -No match - -/^(b+?|a){1,2}?c/ - bc - 0: bc - 1: b - bbc - 0: bbc - 1: b - bbbc - 0: bbbc - 1: bb - bac - 0: bac - 1: a - bbac - 0: bbac - 1: a - aac - 0: aac - 1: a - abbbbbbbbbbbc - 0: abbbbbbbbbbbc - 1: bbbbbbbbbbb - bbbbbbbbbbbac - 0: bbbbbbbbbbbac - 1: a -\= Expect no match - aaac -No match - abbbbbbbbbbbac -No match - -/^(b+|a){1,2}c/ - bc - 0: bc - 1: b - bbc - 0: bbc - 1: bb - bbbc - 0: bbbc - 1: bbb - bac - 0: bac - 1: a - bbac - 0: bbac - 1: a - aac - 0: aac - 1: a - abbbbbbbbbbbc - 0: abbbbbbbbbbbc - 1: bbbbbbbbbbb - bbbbbbbbbbbac - 0: bbbbbbbbbbbac - 1: a -\= Expect no match - aaac -No match - abbbbbbbbbbbac -No match - -/^(b+|a){1,2}?bc/ - bbc - 0: bbc - 1: b - -/^(b*|ba){1,2}?bc/ - babc - 0: babc - 1: ba - bbabc - 0: bbabc - 1: ba - bababc - 0: bababc - 1: ba -\= Expect no match - bababbc -No match - babababc -No match - -/^(ba|b*){1,2}?bc/ - babc - 0: babc - 1: ba - bbabc - 0: bbabc - 1: ba - bababc - 0: bababc - 1: ba -\= Expect no match - bababbc -No match - babababc -No match - -#/^\ca\cA\c[;\c:/ -# \x01\x01\e;z -# 0: \x01\x01\x1b;z - -/^[ab\]cde]/ - athing - 0: a - bthing - 0: b - ]thing - 0: ] - cthing - 0: c - dthing - 0: d - ething - 0: e -\= Expect no match - fthing -No match - [thing -No match - \\thing -No match - -/^[]cde]/ - ]thing - 0: ] - cthing - 0: c - dthing - 0: d - ething - 0: e -\= Expect no match - athing -No match - fthing -No match - -/^[^ab\]cde]/ - fthing - 0: f - [thing - 0: [ - \\thing - 0: \ -\= Expect no match - athing -No match - bthing -No match - ]thing -No match - cthing -No match - dthing -No match - ething -No match - -/^[^]cde]/ - athing - 0: a - fthing - 0: f -\= Expect no match - ]thing -No match - cthing -No match - dthing -No match - ething -No match - -# DLC - I don't get this one -#/^\/ -#  -# 0: \x81 - -#updated to handle 16-bits utf8 -/^ÿ/ - ÿ - 0: \xc3\xbf - -/^[0-9]+$/ - 0 - 0: 0 - 1 - 0: 1 - 2 - 0: 2 - 3 - 0: 3 - 4 - 0: 4 - 5 - 0: 5 - 6 - 0: 6 - 7 - 0: 7 - 8 - 0: 8 - 9 - 0: 9 - 10 - 0: 10 - 100 - 0: 100 -\= Expect no match - abc -No match - -/^.*nter/ - enter - 0: enter - inter - 0: inter - uponter - 0: uponter - -/^xxx[0-9]+$/ - xxx0 - 0: xxx0 - xxx1234 - 0: xxx1234 -\= Expect no match - xxx -No match - -/^.+[0-9][0-9][0-9]$/ - x123 - 0: x123 - x1234 - 0: x1234 - xx123 - 0: xx123 - 123456 - 0: 123456 -\= Expect no match - 123 -No match - -/^.+?[0-9][0-9][0-9]$/ - x123 - 0: x123 - x1234 - 0: x1234 - xx123 - 0: xx123 - 123456 - 0: 123456 -\= Expect no match - 123 -No match - -/^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ - abc!pqr=apquxz.ixr.zzz.ac.uk - 0: abc!pqr=apquxz.ixr.zzz.ac.uk - 1: abc - 2: pqr -\= Expect no match - !pqr=apquxz.ixr.zzz.ac.uk -No match - abc!=apquxz.ixr.zzz.ac.uk -No match - abc!pqr=apquxz:ixr.zzz.ac.uk -No match - abc!pqr=apquxz.ixr.zzz.ac.ukk -No match - -/:/ - Well, we need a colon: somewhere - 0: : -\= Expect no match - Fail without a colon -No match - -/([\da-f:]+)$/i - 0abc - 0: 0abc - 1: 0abc - abc - 0: abc - 1: abc - fed - 0: fed - 1: fed - E - 0: E - 1: E - :: - 0: :: - 1: :: - 5f03:12C0::932e - 0: 5f03:12C0::932e - 1: 5f03:12C0::932e - fed def - 0: def - 1: def - Any old stuff - 0: ff - 1: ff -\= Expect no match - 0zzz -No match - gzzz -No match - fed\x20 -No match - Any old rubbish -No match - -/^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ - .1.2.3 - 0: .1.2.3 - 1: 1 - 2: 2 - 3: 3 - A.12.123.0 - 0: A.12.123.0 - 1: 12 - 2: 123 - 3: 0 -\= Expect no match - .1.2.3333 -No match - 1.2.3 -No match - 1234.2.3 -No match - -/^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ - 1 IN SOA non-sp1 non-sp2( - 0: 1 IN SOA non-sp1 non-sp2( - 1: 1 - 2: non-sp1 - 3: non-sp2 - 1 IN SOA non-sp1 non-sp2 ( - 0: 1 IN SOA non-sp1 non-sp2 ( - 1: 1 - 2: non-sp1 - 3: non-sp2 -\= Expect no match - 1IN SOA non-sp1 non-sp2( -No match - -/^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ - a. - 0: a. - Z. - 0: Z. - 2. - 0: 2. - ab-c.pq-r. - 0: ab-c.pq-r. - 1: .pq-r - sxk.zzz.ac.uk. - 0: sxk.zzz.ac.uk. - 1: .uk - x-.y-. - 0: x-.y-. - 1: .y- -\= Expect no match - -abc.peq. -No match - -/^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ - *.a - 0: *.a - *.b0-a - 0: *.b0-a - 1: 0-a - *.c3-b.c - 0: *.c3-b.c - 1: 3-b - 2: .c - *.c-a.b-c - 0: *.c-a.b-c - 1: -a - 2: .b-c - 3: -c -\= Expect no match - *.0 -No match - *.a- -No match - *.a-b.c- -No match - *.c-a.0-c -No match - -/^(?=ab(de))(abd)(e)/ - abde - 0: abde - 1: de - 2: abd - 3: e - -/^(?!(ab)de|x)(abd)(f)/ - abdf - 0: abdf - 1: - 2: abd - 3: f - -/^(?=(ab(cd)))(ab)/ - abcd - 0: ab - 1: abcd - 2: cd - 3: ab - -/^[\da-f](\.[\da-f])*$/i - a.b.c.d - 0: a.b.c.d - 1: .d - A.B.C.D - 0: A.B.C.D - 1: .D - a.b.c.1.2.3.C - 0: a.b.c.1.2.3.C - 1: .C - -/^\".*\"\s*(;.*)?$/ - \"1234\" - 0: "1234" - \"abcd\" ; - 0: "abcd" ; - 1: ; - \"\" ; rhubarb - 0: "" ; rhubarb - 1: ; rhubarb -\= Expect no match - \"1234\" : things -No match - -/^$/ - \ - 0: -\= Expect no match - A non-empty line -No match - -/ ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x - ab c - 0: ab c -\= Expect no match - abc -No match - ab cde -No match - -/(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ - ab c - 0: ab c -\= Expect no match - abc -No match - ab cde -No match - -/^ a\ b[c ]d $/x - a bcd - 0: a bcd - a b d - 0: a b d -\= Expect no match - abcd -No match - ab d -No match - -/^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ - abcdefhijklm - 0: abcdefhijklm - 1: abc - 2: bc - 3: c - 4: def - 5: ef - 6: f - 7: hij - 8: ij - 9: j -10: klm -11: lm -12: m - -/^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ - abcdefhijklm - 0: abcdefhijklm - 1: bc - 2: c - 3: ef - 4: f - 5: ij - 6: j - 7: lm - 8: m - -#/^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ -# a+ Z0+\x08\n\x1d\x12 -# 0: a+ Z0+\x08\x0a\x1d\x12 - -/^[.^$|()*+?{,}]+/ - .^\$(*+)|{?,?} - 0: .^$(*+)|{?,?} - -/^a*\w/ - z - 0: z - az - 0: az - aaaz - 0: aaaz - a - 0: a - aa - 0: aa - aaaa - 0: aaaa - a+ - 0: a - aa+ - 0: aa - -/^a*?\w/ - z - 0: z - az - 0: a - aaaz - 0: a - a - 0: a - aa - 0: a - aaaa - 0: a - a+ - 0: a - aa+ - 0: a - -/^a+\w/ - az - 0: az - aaaz - 0: aaaz - aa - 0: aa - aaaa - 0: aaaa - aa+ - 0: aa - -/^a+?\w/ - az - 0: az - aaaz - 0: aa - aa - 0: aa - aaaa - 0: aa - aa+ - 0: aa - -/^\d{8}\w{2,}/ - 1234567890 - 0: 1234567890 - 12345678ab - 0: 12345678ab - 12345678__ - 0: 12345678__ -\= Expect no match - 1234567 -No match - -/^[aeiou\d]{4,5}$/ - uoie - 0: uoie - 1234 - 0: 1234 - 12345 - 0: 12345 - aaaaa - 0: aaaaa -\= Expect no match - 123456 -No match - -/^[aeiou\d]{4,5}?/ - uoie - 0: uoie - 1234 - 0: 1234 - 12345 - 0: 1234 - aaaaa - 0: aaaa - 123456 - 0: 1234 - -/\A(abc|def)=(\1){2,3}\Z/ - abc=abcabc - 0: abc=abcabc - 1: abc - 2: abc - def=defdefdef - 0: def=defdefdef - 1: def - 2: def -\= Expect no match - abc=defdef -No match - -/^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\11*(\3\4)\1(?#)2$/ - abcdefghijkcda2 - 0: abcdefghijkcda2 - 1: a - 2: b - 3: c - 4: d - 5: e - 6: f - 7: g - 8: h - 9: i -10: j -11: k -12: cd - abcdefghijkkkkcda2 - 0: abcdefghijkkkkcda2 - 1: a - 2: b - 3: c - 4: d - 5: e - 6: f - 7: g - 8: h - 9: i -10: j -11: k -12: cd - -/(cat(a(ract|tonic)|erpillar)) \1()2(3)/ - cataract cataract23 - 0: cataract cataract23 - 1: cataract - 2: aract - 3: ract - 4: - 5: 3 - catatonic catatonic23 - 0: catatonic catatonic23 - 1: catatonic - 2: atonic - 3: tonic - 4: - 5: 3 - caterpillar caterpillar23 - 0: caterpillar caterpillar23 - 1: caterpillar - 2: erpillar - 3: - 4: - 5: 3 - - -/^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ - From abcd Mon Sep 01 12:33:02 1997 - 0: From abcd Mon Sep 01 12:33 - 1: abcd - -/^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ - From abcd Mon Sep 01 12:33:02 1997 - 0: From abcd Mon Sep 01 12:33 - 1: Sep - From abcd Mon Sep 1 12:33:02 1997 - 0: From abcd Mon Sep 1 12:33 - 1: Sep -\= Expect no match - From abcd Sep 01 12:33:02 1997 -No match - -/^12.34/s - 12\n34 - 0: 12\x0a34 - 12\r34 - 0: 12\x0d34 - -/\w+(?=\t)/ - the quick brown\t fox - 0: brown - -/foo(?!bar)(.*)/ - foobar is foolish see? - 0: foolish see? - 1: lish see? - -/(?:(?!foo)...|^.{0,2})bar(.*)/ - foobar crowbar etc - 0: rowbar etc - 1: etc - barrel - 0: barrel - 1: rel - 2barrel - 0: 2barrel - 1: rel - A barrel - 0: A barrel - 1: rel - -/^(\D*)(?=\d)(?!123)/ - abc456 - 0: abc - 1: abc -\= Expect no match - abc123 -No match - -/^1234(?# test newlines - inside)/ - 1234 - 0: 1234 - -/^1234 #comment in extended re - /x - 1234 - 0: 1234 - -/#rhubarb - abcd/x - abcd - 0: abcd - -/^abcd#rhubarb/x - abcd - 0: abcd - -/^(a)\1{2,3}(.)/ - aaab - 0: aaab - 1: a - 2: b - aaaab - 0: aaaab - 1: a - 2: b - aaaaab - 0: aaaaa - 1: a - 2: a - aaaaaab - 0: aaaaa - 1: a - 2: a - -/(?!^)abc/ - the abc - 0: abc -\= Expect no match - abc -No match - -/(?=^)abc/ - abc - 0: abc -\= Expect no match - the abc -No match - -/^[ab]{1,3}(ab*|b)/ - aabbbbb - 0: aabb - 1: b - -/^[ab]{1,3}?(ab*|b)/ - aabbbbb - 0: aabbbbb - 1: abbbbb - -/^[ab]{1,3}?(ab*?|b)/ - aabbbbb - 0: aa - 1: a - -/^[ab]{1,3}(ab*?|b)/ - aabbbbb - 0: aabb - 1: b - -/ (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* # optional leading comment -(?: (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -" (?: # opening quote... -[^\\\x80-\xff\n\015"] # Anything except backslash and quote -| # or -\\ [^\x80-\xff] # Escaped something (something != CR) -)* " # closing quote -) # initial word -(?: (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* \. (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -" (?: # opening quote... -[^\\\x80-\xff\n\015"] # Anything except backslash and quote -| # or -\\ [^\x80-\xff] # Escaped something (something != CR) -)* " # closing quote -) )* # further okay, if led by a period -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* @ (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # initial subdomain -(?: # -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* \. # if led by a period... -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # ...further okay -)* -# address -| # or -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -" (?: # opening quote... -[^\\\x80-\xff\n\015"] # Anything except backslash and quote -| # or -\\ [^\x80-\xff] # Escaped something (something != CR) -)* " # closing quote -) # one word, optionally followed by.... -(?: -[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... -\( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) | # comments, or... - -" (?: # opening quote... -[^\\\x80-\xff\n\015"] # Anything except backslash and quote -| # or -\\ [^\x80-\xff] # Escaped something (something != CR) -)* " # closing quote -# quoted strings -)* -< (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* # leading < -(?: @ (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # initial subdomain -(?: # -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* \. # if led by a period... -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # ...further okay -)* - -(?: (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* , (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* @ (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # initial subdomain -(?: # -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* \. # if led by a period... -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # ...further okay -)* -)* # further okay, if led by comma -: # closing colon -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* )? # optional route -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -" (?: # opening quote... -[^\\\x80-\xff\n\015"] # Anything except backslash and quote -| # or -\\ [^\x80-\xff] # Escaped something (something != CR) -)* " # closing quote -) # initial word -(?: (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* \. (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -" (?: # opening quote... -[^\\\x80-\xff\n\015"] # Anything except backslash and quote -| # or -\\ [^\x80-\xff] # Escaped something (something != CR) -)* " # closing quote -) )* # further okay, if led by a period -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* @ (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # initial subdomain -(?: # -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* \. # if led by a period... -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* (?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| \[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) # ...further okay -)* -# address spec -(?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* > # trailing > -# name and address -) (?: [\040\t] | \( -(?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* -\) )* # optional trailing comment -/x - Alan Other - 0: Alan Other - - 0: user@dom.ain - user\@dom.ain - 0: user@dom.ain - \"A. Other\" (a comment) - 0: "A. Other" (a comment) - A. Other (a comment) - 0: Other (a comment) - \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay - 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay - A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -# Atom -| # or -" # " -[^\\\x80-\xff\n\015"] * # normal -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* -" # " -# Quoted string -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -\. -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -# Atom -| # or -" # " -[^\\\x80-\xff\n\015"] * # normal -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* -" # " -# Quoted string -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# additional words -)* -@ -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -(?: -\. -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -)* -# address -| # or -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -# Atom -| # or -" # " -[^\\\x80-\xff\n\015"] * # normal -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* -" # " -# Quoted string -) -# leading word -[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces -(?: -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -| -" # " -[^\\\x80-\xff\n\015"] * # normal -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* -" # " -) # "special" comment or quoted string -[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" -)* -< -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# < -(?: -@ -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -(?: -\. -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -)* -(?: , -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -@ -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -(?: -\. -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -)* -)* # additional domains -: -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -)? # optional route -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -# Atom -| # or -" # " -[^\\\x80-\xff\n\015"] * # normal -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* -" # " -# Quoted string -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -\. -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -# Atom -| # or -" # " -[^\\\x80-\xff\n\015"] * # normal -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* -" # " -# Quoted string -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# additional words -)* -@ -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -(?: -\. -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -(?: -[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... -(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom -| -\[ # [ -(?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff -\] # ] -) -[\040\t]* # Nab whitespace. -(?: -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: # ( -(?: \\ [^\x80-\xff] | -\( # ( -[^\\\x80-\xff\n\015()] * # normal* -(?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* -\) # ) -) # special -[^\\\x80-\xff\n\015()] * # normal* -)* # )* -\) # ) -[\040\t]* )* # If comment found, allow more spaces. -# optional trailing comments -)* -# address spec -> # > -# name and address -) -/x - Alan Other - 0: Alan Other - - 0: user@dom.ain - user\@dom.ain - 0: user@dom.ain - \"A. Other\" (a comment) - 0: "A. Other" - A. Other (a comment) - 0: Other - \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay - 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay - A missing angle ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f - -/P[^*]TAIRE[^*]{1,6}?LL/ - xxxxxxxxxxxPSTAIREISLLxxxxxxxxx - 0: PSTAIREISLL - -/P[^*]TAIRE[^*]{1,}?LL/ - xxxxxxxxxxxPSTAIREISLLxxxxxxxxx - 0: PSTAIREISLL - -/(\.\d\d[1-9]?)\d+/ - 1.230003938 - 0: .230003938 - 1: .23 - 1.875000282 - 0: .875000282 - 1: .875 - 1.235 - 0: .235 - 1: .23 - -/(\.\d\d((?=0)|\d(?=\d)))/ - 1.230003938 - 0: .23 - 1: .23 - 2: - 1.875000282 - 0: .875 - 1: .875 - 2: 5 -\= Expect no match - 1.235 -No match - -/\b(foo)\s+(\w+)/i - Food is on the foo table - 0: foo table - 1: foo - 2: table - -/foo(.*)bar/ - The food is under the bar in the barn. - 0: food is under the bar in the bar - 1: d is under the bar in the - -/foo(.*?)bar/ - The food is under the bar in the barn. - 0: food is under the bar - 1: d is under the - -/(.*)(\d*)/ - I have 2 numbers: 53147 - 0: I have 2 numbers: 53147 - 1: I have 2 numbers: 53147 - 2: - -/(.*)(\d+)/ - I have 2 numbers: 53147 - 0: I have 2 numbers: 53147 - 1: I have 2 numbers: 5314 - 2: 7 - -/(.*?)(\d*)/ - I have 2 numbers: 53147 - 0: - 1: - 2: - -/(.*?)(\d+)/ - I have 2 numbers: 53147 - 0: I have 2 - 1: I have - 2: 2 - -/(.*)(\d+)$/ - I have 2 numbers: 53147 - 0: I have 2 numbers: 53147 - 1: I have 2 numbers: 5314 - 2: 7 - -/(.*?)(\d+)$/ - I have 2 numbers: 53147 - 0: I have 2 numbers: 53147 - 1: I have 2 numbers: - 2: 53147 - -/(.*)\b(\d+)$/ - I have 2 numbers: 53147 - 0: I have 2 numbers: 53147 - 1: I have 2 numbers: - 2: 53147 - -/(.*\D)(\d+)$/ - I have 2 numbers: 53147 - 0: I have 2 numbers: 53147 - 1: I have 2 numbers: - 2: 53147 - -/^\D*(?!123)/ - ABC123 - 0: AB - -/^(\D*)(?=\d)(?!123)/ - ABC445 - 0: ABC - 1: ABC -\= Expect no match - ABC123 -No match - -/^[W-]46]/ - W46]789 - 0: W46] - -46]789 - 0: -46] -\= Expect no match - Wall -No match - Zebra -No match - 42 -No match - [abcd] -No match - ]abcd[ -No match - -/^[W-\]46]/ - W46]789 - 0: W - Wall - 0: W - Zebra - 0: Z - Xylophone - 0: X - 42 - 0: 4 - [abcd] - 0: [ - ]abcd[ - 0: ] - \\backslash - 0: \ -\= Expect no match - -46]789 -No match - well -No match - -/\d\d\/\d\d\/\d\d\d\d/ - 01/01/2000 - 0: 01/01/2000 - -/word (?:[a-zA-Z0-9]+ ){0,10}otherword/ - word cat dog elephant mussel cow horse canary baboon snake shark otherword - 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword -\= Expect no match - word cat dog elephant mussel cow horse canary baboon snake shark -No match - -/word (?:[a-zA-Z0-9]+ ){0,300}otherword/ -\= Expect no match - word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope -No match - -/^(a){0,0}/ - bcd - 0: - abc - 0: - aab - 0: - -/^(a){0,1}/ - bcd - 0: - abc - 0: a - 1: a - aab - 0: a - 1: a - -/^(a){0,2}/ - bcd - 0: - abc - 0: a - 1: a - aab - 0: aa - 1: a - -/^(a){0,3}/ - bcd - 0: - abc - 0: a - 1: a - aab - 0: aa - 1: a - aaa - 0: aaa - 1: a - -/^(a){0,}/ - bcd - 0: - abc - 0: a - 1: a - aab - 0: aa - 1: a - aaa - 0: aaa - 1: a - aaaaaaaa - 0: aaaaaaaa - 1: a - -/^(a){1,1}/ - abc - 0: a - 1: a - aab - 0: a - 1: a -\= Expect no match - bcd -No match - -/^(a){1,2}/ - abc - 0: a - 1: a - aab - 0: aa - 1: a -\= Expect no match - bcd -No match - -/^(a){1,3}/ - abc - 0: a - 1: a - aab - 0: aa - 1: a - aaa - 0: aaa - 1: a -\= Expect no match - bcd -No match - -/^(a){1,}/ - abc - 0: a - 1: a - aab - 0: aa - 1: a - aaa - 0: aaa - 1: a - aaaaaaaa - 0: aaaaaaaa - 1: a -\= Expect no match - bcd -No match - -/.*\.gif/ - borfle\nbib.gif\nno - 0: bib.gif - -/.{0,}\.gif/ - borfle\nbib.gif\nno - 0: bib.gif - -/.*\.gif/m - borfle\nbib.gif\nno - 0: bib.gif - -/.*\.gif/s - borfle\nbib.gif\nno - 0: borfle\x0abib.gif - -/.*\.gif/ms - borfle\nbib.gif\nno - 0: borfle\x0abib.gif - -/.*$/ - borfle\nbib.gif\nno - 0: no - -/.*$/m - borfle\nbib.gif\nno - 0: borfle - -/.*$/s - borfle\nbib.gif\nno - 0: borfle\x0abib.gif\x0ano - -/.*$/ms - borfle\nbib.gif\nno - 0: borfle\x0abib.gif\x0ano - -/.*$/ - borfle\nbib.gif\nno\n - 0: no - -/.*$/m - borfle\nbib.gif\nno\n - 0: borfle - -/.*$/s - borfle\nbib.gif\nno\n - 0: borfle\x0abib.gif\x0ano\x0a - -/.*$/ms - borfle\nbib.gif\nno\n - 0: borfle\x0abib.gif\x0ano\x0a - -/(.*X|^B)/ - abcde\n1234Xyz - 0: 1234X - 1: 1234X - BarFoo - 0: B - 1: B -\= Expect no match - abcde\nBar -No match - -/(.*X|^B)/m - abcde\n1234Xyz - 0: 1234X - 1: 1234X - BarFoo - 0: B - 1: B - abcde\nBar - 0: B - 1: B - -/(.*X|^B)/s - abcde\n1234Xyz - 0: abcde\x0a1234X - 1: abcde\x0a1234X - BarFoo - 0: B - 1: B -\= Expect no match - abcde\nBar -No match - -/(.*X|^B)/ms - abcde\n1234Xyz - 0: abcde\x0a1234X - 1: abcde\x0a1234X - BarFoo - 0: B - 1: B - abcde\nBar - 0: B - 1: B - -/(?s)(.*X|^B)/ - abcde\n1234Xyz - 0: abcde\x0a1234X - 1: abcde\x0a1234X - BarFoo - 0: B - 1: B -\= Expect no match - abcde\nBar -No match - -/(?s:.*X|^B)/ - abcde\n1234Xyz - 0: abcde\x0a1234X - BarFoo - 0: B -\= Expect no match - abcde\nBar -No match - -/^.*B/ -\= Expect no match - abc\nB -No match - -/(?s)^.*B/ - abc\nB - 0: abc\x0aB - -/(?m)^.*B/ - abc\nB - 0: B - -/(?ms)^.*B/ - abc\nB - 0: abc\x0aB - -/(?ms)^B/ - abc\nB - 0: B - -/(?s)B$/ - B\n - 0: B - -/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/ - 123456654321 - 0: 123456654321 - -/^\d\d\d\d\d\d\d\d\d\d\d\d/ - 123456654321 - 0: 123456654321 - -/^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]/ - 123456654321 - 0: 123456654321 - -/^[abc]{12}/ - abcabcabcabc - 0: abcabcabcabc - -/^[a-c]{12}/ - abcabcabcabc - 0: abcabcabcabc - -/^(a|b|c){12}/ - abcabcabcabc - 0: abcabcabcabc - 1: c - -/^[abcdefghijklmnopqrstuvwxy0123456789]/ - n - 0: n -\= Expect no match - z -No match - -/abcde{0,0}/ - abcd - 0: abcd -\= Expect no match - abce -No match - -/ab[cd]{0,0}e/ - abe - 0: abe -\= Expect no match - abcde -No match - -/ab(c){0,0}d/ - abd - 0: abd -\= Expect no match - abcd -No match - -/a(b*)/ - a - 0: a - 1: - ab - 0: ab - 1: b - abbbb - 0: abbbb - 1: bbbb -\= Expect no match - bbbbb -No match - -/ab\d{0}e/ - abe - 0: abe -\= Expect no match - ab1e -No match - -/"([^\\"]+|\\.)*"/ - the \"quick\" brown fox - 0: "quick" - 1: quick - \"the \\\"quick\\\" brown fox\" - 0: "the \"quick\" brown fox" - 1: brown fox - -/]{0,})>]{0,})>([\d]{0,}\.)(.*)((
([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is - 43.Word Processor
(N-1286)
Lega lstaff.comCA - Statewide - 0: 43.Word Processor
(N-1286)
Lega lstaff.comCA - Statewide - 1: BGCOLOR='#DBE9E9' - 2: align=left valign=top - 3: 43. - 4: Word Processor
(N-1286) - 5: - 6: - 7: - 8: align=left valign=top - 9: Lega lstaff.com -10: align=left valign=top -11: CA - Statewide - -/a[^a]b/ - acb - 0: acb - a\nb - 0: a\x0ab - -/a.b/ - acb - 0: acb -\= Expect no match - a\nb -No match - -/a[^a]b/s - acb - 0: acb - a\nb - 0: a\x0ab - -/a.b/s - acb - 0: acb - a\nb - 0: a\x0ab - -/^(b+?|a){1,2}?c/ - bac - 0: bac - 1: a - bbac - 0: bbac - 1: a - bbbac - 0: bbbac - 1: a - bbbbac - 0: bbbbac - 1: a - bbbbbac - 0: bbbbbac - 1: a - -/^(b+|a){1,2}?c/ - bac - 0: bac - 1: a - bbac - 0: bbac - 1: a - bbbac - 0: bbbac - 1: a - bbbbac - 0: bbbbac - 1: a - bbbbbac - 0: bbbbbac - 1: a - -/(?!\A)x/m - a\bx\n - 0: x - a\nx\n - 0: x -\= Expect no match - x\nb\n -No match - -/(A|B)*?CD/ - CD - 0: CD - -/(A|B)*CD/ - CD - 0: CD - -/(AB)*?\1/ - ABABAB - 0: ABAB - 1: AB - -/(AB)*\1/ - ABABAB - 0: ABABAB - 1: AB - -/(?.*/)foo" - /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo - 0: /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo -\= Expect no match - /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ -No match - -/(?>(\.\d\d[1-9]?))\d+/ - 1.230003938 - 0: .230003938 - 1: .23 - 1.875000282 - 0: .875000282 - 1: .875 -\= Expect no match - 1.235 -No match - -/^((?>\w+)|(?>\s+))*$/ - now is the time for all good men to come to the aid of the party - 0: now is the time for all good men to come to the aid of the party - 1: party -\= Expect no match - this is not a line with only words and spaces! -No match - -/(\d+)(\w)/ - 12345a - 0: 12345a - 1: 12345 - 2: a - 12345+ - 0: 12345 - 1: 1234 - 2: 5 - -/((?>\d+))(\w)/ - 12345a - 0: 12345a - 1: 12345 - 2: a -\= Expect no match - 12345+ -No match - -/(?>a+)b/ - aaab - 0: aaab - -/((?>a+)b)/ - aaab - 0: aaab - 1: aaab - -/(?>(a+))b/ - aaab - 0: aaab - 1: aaa - -/(?>b)+/ - aaabbbccc - 0: bbb - -/(?>a+|b+|c+)*c/ - aaabbbbccccd - 0: aaabbbbc - -/((?>[^()]+)|\([^()]*\))+/ - ((abc(ade)ufh()()x - 0: abc(ade)ufh()()x - 1: x - -/\(((?>[^()]+)|\([^()]+\))+\)/ - (abc) - 0: (abc) - 1: abc - (abc(def)xyz) - 0: (abc(def)xyz) - 1: xyz -\= Expect no match - ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -No match - -/a(?-i)b/i - ab - 0: ab - Ab - 0: Ab -\= Expect no match - aB -No match - AB -No match - -/(a (?x)b c)d e/ - a bcd e - 0: a bcd e - 1: a bc -\= Expect no match - a b cd e -No match - abcd e -No match - a bcde -No match - -/(a b(?x)c d (?-x)e f)/ - a bcde f - 0: a bcde f - 1: a bcde f -\= Expect no match - abcdef -No match - -/(a(?i)b)c/ - abc - 0: abc - 1: ab - aBc - 0: aBc - 1: aB -\= Expect no match - abC -No match - aBC -No match - Abc -No match - ABc -No match - ABC -No match - AbC -No match - -/a(?i:b)c/ - abc - 0: abc - aBc - 0: aBc -\= Expect no match - ABC -No match - abC -No match - aBC -No match - -/a(?i:b)*c/ - aBc - 0: aBc - aBBc - 0: aBBc -\= Expect no match - aBC -No match - aBBC -No match - -/a(?=b(?i)c)\w\wd/ - abcd - 0: abcd - abCd - 0: abCd -\= Expect no match - aBCd -No match - abcD -No match - -/(?s-i:more.*than).*million/i - more than million - 0: more than million - more than MILLION - 0: more than MILLION - more \n than Million - 0: more \x0a than Million -\= Expect no match - MORE THAN MILLION -No match - more \n than \n million -No match - -/(?:(?s-i)more.*than).*million/i - more than million - 0: more than million - more than MILLION - 0: more than MILLION - more \n than Million - 0: more \x0a than Million -\= Expect no match - MORE THAN MILLION -No match - more \n than \n million -No match - -/(?>a(?i)b+)+c/ - abc - 0: abc - aBbc - 0: aBbc - aBBc - 0: aBBc -\= Expect no match - Abc -No match - abAb -No match - abbC -No match - -/(?=a(?i)b)\w\wc/ - abc - 0: abc - aBc - 0: aBc -\= Expect no match - Ab -No match - abC -No match - aBC -No match - -/(?<=a(?i)b)(\w\w)c/ - abxxc - 0: xxc - 1: xx - aBxxc - 0: xxc - 1: xx -\= Expect no match - Abxxc -No match - ABxxc -No match - abxxC -No match - -/(?:(a)|b)(?(1)A|B)/ - aA - 0: aA - 1: a - bB - 0: bB -\= Expect no match - aB -No match - bA -No match - -/^(a)?(?(1)a|b)+$/ - aa - 0: aa - 1: a - b - 0: b - bb - 0: bb -\= Expect no match - ab -No match - -# Perl gets this next one wrong if the pattern ends with $; in that case it -# fails to match "12". - -/^(?(?=abc)\w{3}:|\d\d)/ - abc: - 0: abc: - 12 - 0: 12 - 123 - 0: 12 -\= Expect no match - xyz -No match - -/^(?(?!abc)\d\d|\w{3}:)$/ - abc: - 0: abc: - 12 - 0: 12 -\= Expect no match - 123 -No match - xyz -No match - -/(?(?<=foo)bar|cat)/ - foobar - 0: bar - cat - 0: cat - fcat - 0: cat - focat - 0: cat -\= Expect no match - foocat -No match - -/(?(?a*)*/ - a - 0: a - aa - 0: aa - aaaa - 0: aaaa - -/(abc|)+/ - abc - 0: abc - 1: - abcabc - 0: abcabc - 1: - abcabcabc - 0: abcabcabc - 1: - xyz - 0: - 1: - -/([a]*)*/ - a - 0: a - 1: - aaaaa - 0: aaaaa - 1: - -/([ab]*)*/ - a - 0: a - 1: - b - 0: b - 1: - ababab - 0: ababab - 1: - aaaabcde - 0: aaaab - 1: - bbbb - 0: bbbb - 1: - -/([^a]*)*/ - b - 0: b - 1: - bbbb - 0: bbbb - 1: - aaa - 0: - 1: - -/([^ab]*)*/ - cccc - 0: cccc - 1: - abab - 0: - 1: - -/([a]*?)*/ - a - 0: - 1: - aaaa - 0: - 1: - -/([ab]*?)*/ - a - 0: - 1: - b - 0: - 1: - abab - 0: - 1: - baba - 0: - 1: - -/([^a]*?)*/ - b - 0: - 1: - bbbb - 0: - 1: - aaa - 0: - 1: - -/([^ab]*?)*/ - c - 0: - 1: - cccc - 0: - 1: - baba - 0: - 1: - -/(?>a*)*/ - a - 0: a - aaabcde - 0: aaa - -/((?>a*))*/ - aaaaa - 0: aaaaa - 1: - aabbaa - 0: aa - 1: - -/((?>a*?))*/ - aaaaa - 0: - 1: - aabbaa - 0: - 1: - -/(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x - 12-sep-98 - 0: 12-sep-98 - 12-09-98 - 0: 12-09-98 -\= Expect no match - sep-12-98 -No match - -/(?<=(foo))bar\1/ - foobarfoo - 0: barfoo - 1: foo - foobarfootling - 0: barfoo - 1: foo -\= Expect no match - foobar -No match - barfoo -No match - -/(?i:saturday|sunday)/ - saturday - 0: saturday - sunday - 0: sunday - Saturday - 0: Saturday - Sunday - 0: Sunday - SATURDAY - 0: SATURDAY - SUNDAY - 0: SUNDAY - SunDay - 0: SunDay - -/(a(?i)bc|BB)x/ - abcx - 0: abcx - 1: abc - aBCx - 0: aBCx - 1: aBC - bbx - 0: bbx - 1: bb - BBx - 0: BBx - 1: BB -\= Expect no match - abcX -No match - aBCX -No match - bbX -No match - BBX -No match - -/^([ab](?i)[cd]|[ef])/ - ac - 0: ac - 1: ac - aC - 0: aC - 1: aC - bD - 0: bD - 1: bD - elephant - 0: e - 1: e - Europe - 0: E - 1: E - frog - 0: f - 1: f - France - 0: F - 1: F -\= Expect no match - Africa -No match - -/^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ - ab - 0: ab - 1: ab - aBd - 0: aBd - 1: aBd - xy - 0: xy - 1: xy - xY - 0: xY - 1: xY - zebra - 0: z - 1: z - Zambesi - 0: Z - 1: Z -\= Expect no match - aCD -No match - XY -No match - -/(?<=foo\n)^bar/m - foo\nbar - 0: bar -\= Expect no match - bar -No match - baz\nbar -No match - -/(?<=(?]&/ - <&OUT - 0: <& - -/^(a\1?){4}$/ - aaaaaaaaaa - 0: aaaaaaaaaa - 1: aaaa -\= Expect no match - AB -No match - aaaaaaaaa -No match - aaaaaaaaaaa -No match - -/^(a(?(1)\1)){4}$/ - aaaaaaaaaa - 0: aaaaaaaaaa - 1: aaaa -\= Expect no match - aaaaaaaaa -No match - aaaaaaaaaaa -No match - -/(?:(f)(o)(o)|(b)(a)(r))*/ - foobar - 0: foobar - 1: f - 2: o - 3: o - 4: b - 5: a - 6: r - -/(?<=a)b/ - ab - 0: b -\= Expect no match - cb -No match - b -No match - -/(? - 2: abcd - xy:z:::abcd - 0: xy:z:::abcd - 1: xy:z::: - 2: abcd - -/^[^bcd]*(c+)/ - aexycd - 0: aexyc - 1: c - -/(a*)b+/ - caab - 0: aab - 1: aa - -/([\w:]+::)?(\w+)$/ - abcd - 0: abcd - 1: - 2: abcd - xy:z:::abcd - 0: xy:z:::abcd - 1: xy:z::: - 2: abcd -\= Expect no match - abcd: -No match - abcd: -No match - -/^[^bcd]*(c+)/ - aexycd - 0: aexyc - 1: c - -/(>a+)ab/ - -/(?>a+)b/ - aaab - 0: aaab - -/([[:]+)/ - a:[b]: - 0: :[ - 1: :[ - -/([[=]+)/ - a=[b]= - 0: =[ - 1: =[ - -/([[.]+)/ - a.[b]. - 0: .[ - 1: .[ - -/((?>a+)b)/ - aaab - 0: aaab - 1: aaab - -/(?>(a+))b/ - aaab - 0: aaab - 1: aaa - -/((?>[^()]+)|\([^()]*\))+/ - ((abc(ade)ufh()()x - 0: abc(ade)ufh()()x - 1: x - -/a\Z/ -\= Expect no match - aaab -No match - a\nb\n -No match - -/b\Z/ - a\nb\n - 0: b - -/b\z/ - -/b\Z/ - a\nb - 0: b - -/b\z/ - a\nb - 0: b - -/^(?>(?(1)\.|())[^\W_](?>[a-z0-9-]*[^\W_])?)+$/ - a - 0: a - 1: - abc - 0: abc - 1: - a-b - 0: a-b - 1: - 0-9 - 0: 0-9 - 1: - a.b - 0: a.b - 1: - 5.6.7 - 0: 5.6.7 - 1: - the.quick.brown.fox - 0: the.quick.brown.fox - 1: - a100.b200.300c - 0: a100.b200.300c - 1: - 12-ab.1245 - 0: 12-ab.1245 - 1: -\= Expect no match - \ -No match - .a -No match - -a -No match - a- -No match - a. -No match - a_b -No match - a.- -No match - a.. -No match - ab..bc -No match - the.quick.brown.fox- -No match - the.quick.brown.fox. -No match - the.quick.brown.fox_ -No match - the.quick.brown.fox+ -No match - -/(?>.*)(?<=(abcd|wxyz))/ - alphabetabcd - 0: alphabetabcd - 1: abcd - endingwxyz - 0: endingwxyz - 1: wxyz -\= Expect no match - a rather long string that doesn't end with one of them -No match - -/word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ - word cat dog elephant mussel cow horse canary baboon snake shark otherword - 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword -\= Expect no match - word cat dog elephant mussel cow horse canary baboon snake shark -No match - -/word (?>[a-zA-Z0-9]+ ){0,30}otherword/ -\= Expect no match - word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope -No match - -/(?<=\d{3}(?!999))foo/ - 999foo - 0: foo - 123999foo - 0: foo -\= Expect no match - 123abcfoo -No match - -/(?<=(?!...999)\d{3})foo/ - 999foo - 0: foo - 123999foo - 0: foo -\= Expect no match - 123abcfoo -No match - -/(?<=\d{3}(?!999)...)foo/ - 123abcfoo - 0: foo - 123456foo - 0: foo -\= Expect no match - 123999foo -No match - -/(?<=\d{3}...)(? - 2: - 3: abcd -
- 2: - 3: abcd - \s*)=(?>\s*) # find - 2: - 3: abcd - Z)+|A)*/ - ZABCDEFG - 0: ZA - 1: A - -/((?>)+|A)*/ - ZABCDEFG - 0: - 1: - -/^[\d-a]/ - abcde - 0: a - -things - 0: - - 0digit - 0: 0 -\= Expect no match - bcdef -No match - -/[\s]+/ - > \x09\x0a\x0c\x0d\x0b< - 0: \x09\x0a\x0c\x0d\x0b - -/\s+/ - > \x09\x0a\x0c\x0d\x0b< - 0: \x09\x0a\x0c\x0d\x0b - -/a b/x - ab - 0: ab - -/(?!\A)x/m - a\nxb\n - 0: x - -/(?!^)x/m -\= Expect no match - a\nxb\n -No match - -#/abc\Qabc\Eabc/ -# abcabcabc -# 0: abcabcabc - -#/abc\Q(*+|\Eabc/ -# abc(*+|abc -# 0: abc(*+|abc - -#/ abc\Q abc\Eabc/x -# abc abcabc -# 0: abc abcabc -#\= Expect no match -# abcabcabc -#No match - -#/abc#comment -# \Q#not comment -# literal\E/x -# abc#not comment\n literal -# 0: abc#not comment\x0a literal - -#/abc#comment -# \Q#not comment -# literal/x -# abc#not comment\n literal -# 0: abc#not comment\x0a literal - -#/abc#comment -# \Q#not comment -# literal\E #more comment -# /x -# abc#not comment\n literal -# 0: abc#not comment\x0a literal - -#/abc#comment -# \Q#not comment -# literal\E #more comment/x -# abc#not comment\n literal -# 0: abc#not comment\x0a literal - -#/\Qabc\$xyz\E/ -# abc\\\$xyz -# 0: abc\$xyz - -#/\Qabc\E\$\Qxyz\E/ -# abc\$xyz -# 0: abc$xyz - -/\Gabc/ - abc - 0: abc -\= Expect no match - xyzabc -No match - -/a(?x: b c )d/ - XabcdY - 0: abcd -\= Expect no match - Xa b c d Y -No match - -/((?x)x y z | a b c)/ - XabcY - 0: abc - 1: abc - AxyzB - 0: xyz - 1: xyz - -/(?i)AB(?-i)C/ - XabCY - 0: abC -\= Expect no match - XabcY -No match - -/((?i)AB(?-i)C|D)E/ - abCE - 0: abCE - 1: abC - DE - 0: DE - 1: D -\= Expect no match - abcE -No match - abCe -No match - dE -No match - De -No match - -/(.*)\d+\1/ - abc123abc - 0: abc123abc - 1: abc - abc123bc - 0: bc123bc - 1: bc - -/(.*)\d+\1/s - abc123abc - 0: abc123abc - 1: abc - abc123bc - 0: bc123bc - 1: bc - -/((.*))\d+\1/ - abc123abc - 0: abc123abc - 1: abc - 2: abc - abc123bc - 0: bc123bc - 1: bc - 2: bc - -# This tests for an IPv6 address in the form where it can have up to -# eight components, one and only one of which is empty. This must be -# an internal component. - -/^(?!:) # colon disallowed at start - (?: # start of item - (?: [0-9a-f]{1,4} | # 1-4 hex digits or - (?(1)0 | () ) ) # if null previously matched, fail; else null - : # followed by colon - ){1,7} # end item; 1-7 of them required - [0-9a-f]{1,4} $ # final hex number at end of string - (?(1)|.) # check that there was an empty component - /ix - a123::a123 - 0: a123::a123 - 1: - a123:b342::abcd - 0: a123:b342::abcd - 1: - a123:b342::324e:abcd - 0: a123:b342::324e:abcd - 1: - a123:ddde:b342::324e:abcd - 0: a123:ddde:b342::324e:abcd - 1: - a123:ddde:b342::324e:dcba:abcd - 0: a123:ddde:b342::324e:dcba:abcd - 1: - a123:ddde:9999:b342::324e:dcba:abcd - 0: a123:ddde:9999:b342::324e:dcba:abcd - 1: -\= Expect no match - 1:2:3:4:5:6:7:8 -No match - a123:bce:ddde:9999:b342::324e:dcba:abcd -No match - a123::9999:b342::324e:dcba:abcd -No match - abcde:2:3:4:5:6:7:8 -No match - ::1 -No match - abcd:fee0:123:: -No match - :1 -No match - 1: -No match - -#/[z\Qa-d]\E]/ -# z -# 0: z -# a -# 0: a -# - -# 0: - -# d -# 0: d -# ] -# 0: ] -#\= Expect no match -# b -#No match - -#TODO: PCRE has an optimization to make this workable, .NET does not -#/(a+)*b/ -#\= Expect no match -# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -#No match - -# All these had to be updated because we understand unicode -# and this looks like it's expecting single byte matches - -# .NET generates \xe4...not sure what's up, might just be different code pages -/(?i)reg(?:ul(?:[aä]|ae)r|ex)/ - REGular - 0: REGular - regulaer - 0: regulaer - Regex - 0: Regex - regulär - 0: regul\xc3\xa4r - -#/Åæåä[à-ÿÀ-ß]+/ -# Åæåäà -# 0: \xc5\xe6\xe5\xe4\xe0 -# Åæåäÿ -# 0: \xc5\xe6\xe5\xe4\xff -# ÅæåäÀ -# 0: \xc5\xe6\xe5\xe4\xc0 -# Åæåäß -# 0: \xc5\xe6\xe5\xe4\xdf - -/(?<=Z)X./ - \x84XAZXB - 0: XB - -/ab cd (?x) de fg/ - ab cd defg - 0: ab cd defg - -/ab cd(?x) de fg/ - ab cddefg - 0: ab cddefg -\= Expect no match - abcddefg -No match - -/(? - 2: - D - 0: D - 1: - 2: - -# this is really long with debug -- removing for now -#/(a|)*\d/ -# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 -# 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 -# 1: -#\= Expect no match -# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -#No match - -/(?>a|)*\d/ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 - 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 -\= Expect no match - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -No match - -/(?:a|)*\d/ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 - 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 -\= Expect no match - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -No match - -/^(?s)(?>.*)(? - 2: a - -/(?>(a))b|(a)c/ - ac - 0: ac - 1: - 2: a - -/(?=(a))ab|(a)c/ - ac - 0: ac - 1: - 2: a - -/((?>(a))b|(a)c)/ - ac - 0: ac - 1: ac - 2: - 3: a - -/(?=(?>(a))b|(a)c)(..)/ - ac - 0: ac - 1: - 2: a - 3: ac - -/(?>(?>(a))b|(a)c)/ - ac - 0: ac - 1: - 2: a - -/((?>(a+)b)+(aabab))/ - aaaabaaabaabab - 0: aaaabaaabaabab - 1: aaaabaaabaabab - 2: aaa - 3: aabab - -/(?>a+|ab)+?c/ -\= Expect no match - aabc -No match - -/(?>a+|ab)+c/ -\= Expect no match - aabc -No match - -/(?:a+|ab)+c/ - aabc - 0: aabc - -/^(?:a|ab)+c/ - aaaabc - 0: aaaabc - -/(?=abc){0}xyz/ - xyz - 0: xyz - -/(?=abc){1}xyz/ -\= Expect no match - xyz -No match - -/(?=(a))?./ - ab - 0: a - 1: a - bc - 0: b - -/(?=(a))??./ - ab - 0: a - bc - 0: b - -/^(?!a){0}\w+/ - aaaaa - 0: aaaaa - -/(?<=(abc))?xyz/ - abcxyz - 0: xyz - 1: abc - pqrxyz - 0: xyz - -/^[g]+/ - ggg<<>> - 0: ggg<<>> -\= Expect no match - \\ga -No match - -/^[ga]+/ - gggagagaxyz - 0: gggagaga - -/[:a]xxx[b:]/ - :xxx: - 0: :xxx: - -/(?<=a{2})b/i - xaabc - 0: b -\= Expect no match - xabc -No match - -/(? -# 4: -# 5: c -# 6: d -# 7: Y - -#/^X(?7)(a)(?|(b|(?|(r)|(t))(s))|(q))(c)(d)(Y)/ -# XYabcdY -# 0: XYabcdY -# 1: a -# 2: b -# 3: -# 4: -# 5: c -# 6: d -# 7: Y - -/(?'abc'\w+):\k{2}/ - a:aaxyz - 0: a:aa - 1: a - ab:ababxyz - 0: ab:abab - 1: ab -\= Expect no match - a:axyz -No match - ab:abxyz -No match - -/^(?a)? (?(ab)b|c) (?(ab)d|e)/x - abd - 0: abd - 1: a - ce - 0: ce - -# .NET has more consistent grouping numbers with these dupe groups for the two options -/(?:a(? (?')|(?")) |b(? (?')|(?")) ) (?(quote)[a-z]+|[0-9]+)/x,dupnames - a\"aaaaa - 0: a"aaaaa - 1: " - 2: - 3: " - b\"aaaaa - 0: b"aaaaa - 1: " - 2: - 3: " -\= Expect no match - b\"11111 -No match - -#/(?P(?P0)(?P>L1)|(?P>L2))/ -# 0 -# 0: 0 -# 1: 0 -# 00 -# 0: 00 -# 1: 00 -# 2: 0 -# 0000 -# 0: 0000 -# 1: 0000 -# 2: 0 - -#/(?P(?P0)|(?P>L2)(?P>L1))/ -# 0 -# 0: 0 -# 1: 0 -# 2: 0 -# 00 -# 0: 0 -# 1: 0 -# 2: 0 -# 0000 -# 0: 0 -# 1: 0 -# 2: 0 - -# Check the use of names for failure - -# Check opening parens in comment when seeking forward reference. - -#/(?P(?P=abn)xxx|)+/ -# xxx -# 0: -# 1: - -#Posses -/^(a)?(\w)/ - aaaaX - 0: aa - 1: a - 2: a - YZ - 0: Y - 1: - 2: Y - -#Posses -/^(?:a)?(\w)/ - aaaaX - 0: aa - 1: a - YZ - 0: Y - 1: Y - -/\A.*?(a|bc)/ - ba - 0: ba - 1: a - -/\A.*?(?:a|bc|d)/ - ba - 0: ba - -# -------------------------- - -/(another)?(\1?)test/ - hello world test - 0: test - 1: - 2: - -/(another)?(\1+)test/ -\= Expect no match - hello world test -No match - -/((?:a?)*)*c/ - aac - 0: aac - 1: - -/((?>a?)*)*c/ - aac - 0: aac - 1: - -/(?>.*?a)(?<=ba)/ - aba - 0: ba - -/(?:.*?a)(?<=ba)/ - aba - 0: aba - -/(?>.*?a)b/s - aab - 0: ab - -/(?>.*?a)b/ - aab - 0: ab - -/(?>^a)b/s -\= Expect no match - aab -No match - -/(?>.*?)(?<=(abcd)|(wxyz))/ - alphabetabcd - 0: - 1: abcd - endingwxyz - 0: - 1: - 2: wxyz - -/(?>.*)(?<=(abcd)|(wxyz))/ - alphabetabcd - 0: alphabetabcd - 1: abcd - endingwxyz - 0: endingwxyz - 1: - 2: wxyz - -"(?>.*)foo" -\= Expect no match - abcdfooxyz -No match - -"(?>.*?)foo" - abcdfooxyz - 0: foo - -# Tests that try to figure out how Perl works. My hypothesis is that the first -# verb that is backtracked onto is the one that acts. This seems to be the case -# almost all the time, but there is one exception that is perhaps a bug. - -/a(?=bc).|abd/ - abd - 0: abd - abc - 0: ab - -/a(?>bc)d|abd/ - abceabd - 0: abd - -# These tests were formerly in test 2, but changes in PCRE and Perl have -# made them compatible. - -/^(a)?(?(1)a|b)+$/ -\= Expect no match - a -No match - -# ---- - -/^\d*\w{4}/ - 1234 - 0: 1234 -\= Expect no match - 123 -No match - -/^[^b]*\w{4}/ - aaaa - 0: aaaa -\= Expect no match - aaa -No match - -/^[^b]*\w{4}/i - aaaa - 0: aaaa -\= Expect no match - aaa -No match - -/^a*\w{4}/ - aaaa - 0: aaaa -\= Expect no match - aaa -No match - -/^a*\w{4}/i - aaaa - 0: aaaa -\= Expect no match - aaa -No match - -/(?:(?foo)|(?bar))\k/dupnames - foofoo - 0: foofoo - 1: foo - barbar - 0: barbar - 1: bar - -# A notable difference between PCRE and .NET. According to -# the PCRE docs: -# If you make a subroutine call to a non-unique named -# subpattern, the one that corresponds to the first -# occurrence of the name is used. In the absence of -# duplicate numbers (see the previous section) this is -# the one with the lowest number. -# .NET takes the most recently captured number according to MSDN: -# A backreference refers to the most recent definition of -# a group (the definition most immediately to the left, -# when matching left to right). When a group makes multiple -# captures, a backreference refers to the most recent capture. - -#/(?A)(?:(?foo)|(?bar))\k/dupnames -# AfooA -# 0: AfooA -# 1: A -# 2: foo -# AbarA -# 0: AbarA -# 1: A -# 2: -# 3: bar -#\= Expect no match -# Afoofoo -#No match -# Abarbar -#No match - -/^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ - 1 IN SOA non-sp1 non-sp2( - 0: 1 IN SOA non-sp1 non-sp2( - 1: 1 - 2: non-sp1 - 3: non-sp2 - -# TODO: .NET's group number ordering here in the second example is a bit odd -/^ (?:(?A)|(?'B'B)(?A)) (?(A)x) (?(B)y)$/x,dupnames - Ax - 0: Ax - 1: A - BAxy - 0: BAxy - 1: A - 2: B - -/ ^ a + b $ /x - aaaab - 0: aaaab - -/ ^ a + #comment - b $ /x - aaaab - 0: aaaab - -/ ^ a + #comment - #comment - b $ /x - aaaab - 0: aaaab - -/ ^ (?> a + ) b $ /x - aaaab - 0: aaaab - -/ ^ ( a + ) + \w $ /x - aaaab - 0: aaaab - 1: aaaa - -/(?:x|(?:(xx|yy)+|x|x|x|x|x)|a|a|a)bc/ -\= Expect no match - acb -No match - -#Posses -#/\A(?:[^\"]+|\"(?:[^\"]*|\"\")*\")+/ -# NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED -# 0: NON QUOTED "QUOT""ED" AFTER - -#Posses -#/\A(?:[^\"]+|\"(?:[^\"]+|\"\")*\")+/ -# NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED -# 0: NON QUOTED "QUOT""ED" AFTER - -#Posses -#/\A(?:[^\"]+|\"(?:[^\"]+|\"\")+\")+/ -# NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED -# 0: NON QUOTED "QUOT""ED" AFTER - -#Posses -#/\A([^\"1]+|[\"2]([^\"3]*|[\"4][\"5])*[\"6])+/ -# NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED -# 0: NON QUOTED "QUOT""ED" AFTER -# 1: AFTER -# 2: - -/^\w+(?>\s*)(?<=\w)/ - test test - 0: tes - -#/(?Pa)?(?Pb)?(?()c|d)*l/ -# acl -# 0: acl -# 1: a -# bdl -# 0: bdl -# 1: -# 2: b -# adl -# 0: dl -# bcl -# 0: l - -/\sabc/ - \x0babc - 0: \x0babc - -#/[\Qa]\E]+/ -# aa]] -# 0: aa]] - -#/[\Q]a\E]+/ -# aa]] -# 0: aa]] - -/A((((((((a))))))))\8B/ - AaaB - 0: AaaB - 1: a - 2: a - 3: a - 4: a - 5: a - 6: a - 7: a - 8: a - -/A(((((((((a)))))))))\9B/ - AaaB - 0: AaaB - 1: a - 2: a - 3: a - 4: a - 5: a - 6: a - 7: a - 8: a - 9: a - -/(|ab)*?d/ - abd - 0: abd - 1: ab - xyd - 0: d - -/(\2|a)(\1)/ - aaa - 0: aa - 1: a - 2: a - -/(\2)(\1)/ - -"Z*(|d*){216}" - -/((((((((((((x))))))))))))\12/ - xx - 0: xx - 1: x - 2: x - 3: x - 4: x - 5: x - 6: x - 7: x - 8: x - 9: x -10: x -11: x -12: x - -#"(?|(\k'Pm')|(?'Pm'))" -# abcd -# 0: -# 1: - -#/(?|(aaa)|(b))\g{1}/ -# aaaaaa -# 0: aaaaaa -# 1: aaa -# bb -# 0: bb -# 1: b - -#/(?|(aaa)|(b))(?1)/ -# aaaaaa -# 0: aaaaaa -# 1: aaa -# baaa -# 0: baaa -# 1: b -#\= Expect no match -# bb -#No match - -#/(?|(aaa)|(b))/ -# xaaa -# 0: aaa -# 1: aaa -# xbc -# 0: b -# 1: b - -#/(?|(?'a'aaa)|(?'a'b))\k'a'/ -# aaaaaa -# 0: aaaaaa -# 1: aaa -# bb -# 0: bb -# 1: b - -#/(?|(?'a'aaa)|(?'a'b))(?'a'cccc)\k'a'/dupnames -# aaaccccaaa -# 0: aaaccccaaa -# 1: aaa -# 2: cccc -# bccccb -# 0: bccccb -# 1: b -# 2: cccc - -# End of testinput1 diff --git a/vendor/github.com/dustin/go-humanize/.travis.yml b/vendor/github.com/dustin/go-humanize/.travis.yml deleted file mode 100644 index ac12e485..00000000 --- a/vendor/github.com/dustin/go-humanize/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -sudo: false -language: go -go_import_path: github.com/dustin/go-humanize -go: - - 1.13.x - - 1.14.x - - 1.15.x - - 1.16.x - - stable - - 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: - - diff -u <(echo -n) <(gofmt -d -s .) - - go vet . - - go install -v -race ./... - - go test -v -race ./... diff --git a/vendor/github.com/dustin/go-humanize/LICENSE b/vendor/github.com/dustin/go-humanize/LICENSE deleted file mode 100644 index 8d9a94a9..00000000 --- a/vendor/github.com/dustin/go-humanize/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2005-2008 Dustin Sallings - -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/dustin/go-humanize/README.markdown b/vendor/github.com/dustin/go-humanize/README.markdown deleted file mode 100644 index 7d0b16b3..00000000 --- a/vendor/github.com/dustin/go-humanize/README.markdown +++ /dev/null @@ -1,124 +0,0 @@ -# Humane Units [![Build Status](https://travis-ci.org/dustin/go-humanize.svg?branch=master)](https://travis-ci.org/dustin/go-humanize) [![GoDoc](https://godoc.org/github.com/dustin/go-humanize?status.svg)](https://godoc.org/github.com/dustin/go-humanize) - -Just a few functions for helping humanize times and sizes. - -`go get` it as `github.com/dustin/go-humanize`, import it as -`"github.com/dustin/go-humanize"`, use it as `humanize`. - -See [godoc](https://pkg.go.dev/github.com/dustin/go-humanize) for -complete documentation. - -## Sizes - -This lets you take numbers like `82854982` and convert them to useful -strings like, `83 MB` or `79 MiB` (whichever you prefer). - -Example: - -```go -fmt.Printf("That file is %s.", humanize.Bytes(82854982)) // That file is 83 MB. -``` - -## Times - -This lets you take a `time.Time` and spit it out in relative terms. -For example, `12 seconds ago` or `3 days from now`. - -Example: - -```go -fmt.Printf("This was touched %s.", humanize.Time(someTimeInstance)) // This was touched 7 hours ago. -``` - -Thanks to Kyle Lemons for the time implementation from an IRC -conversation one day. It's pretty neat. - -## Ordinals - -From a [mailing list discussion][odisc] where a user wanted to be able -to label ordinals. - - 0 -> 0th - 1 -> 1st - 2 -> 2nd - 3 -> 3rd - 4 -> 4th - [...] - -Example: - -```go -fmt.Printf("You're my %s best friend.", humanize.Ordinal(193)) // You are my 193rd best friend. -``` - -## Commas - -Want to shove commas into numbers? Be my guest. - - 0 -> 0 - 100 -> 100 - 1000 -> 1,000 - 1000000000 -> 1,000,000,000 - -100000 -> -100,000 - -Example: - -```go -fmt.Printf("You owe $%s.\n", humanize.Comma(6582491)) // You owe $6,582,491. -``` - -## Ftoa - -Nicer float64 formatter that removes trailing zeros. - -```go -fmt.Printf("%f", 2.24) // 2.240000 -fmt.Printf("%s", humanize.Ftoa(2.24)) // 2.24 -fmt.Printf("%f", 2.0) // 2.000000 -fmt.Printf("%s", humanize.Ftoa(2.0)) // 2 -``` - -## SI notation - -Format numbers with [SI notation][sinotation]. - -Example: - -```go -humanize.SI(0.00000000223, "M") // 2.23 nM -``` - -## English-specific functions - -The following functions are in the `humanize/english` subpackage. - -### Plurals - -Simple English pluralization - -```go -english.PluralWord(1, "object", "") // object -english.PluralWord(42, "object", "") // objects -english.PluralWord(2, "bus", "") // buses -english.PluralWord(99, "locus", "loci") // loci - -english.Plural(1, "object", "") // 1 object -english.Plural(42, "object", "") // 42 objects -english.Plural(2, "bus", "") // 2 buses -english.Plural(99, "locus", "loci") // 99 loci -``` - -### Word series - -Format comma-separated words lists with conjuctions: - -```go -english.WordSeries([]string{"foo"}, "and") // foo -english.WordSeries([]string{"foo", "bar"}, "and") // foo and bar -english.WordSeries([]string{"foo", "bar", "baz"}, "and") // foo, bar and baz - -english.OxfordWordSeries([]string{"foo", "bar", "baz"}, "and") // foo, bar, and baz -``` - -[odisc]: https://groups.google.com/d/topic/golang-nuts/l8NhI74jl-4/discussion -[sinotation]: http://en.wikipedia.org/wiki/Metric_prefix diff --git a/vendor/github.com/dustin/go-humanize/big.go b/vendor/github.com/dustin/go-humanize/big.go deleted file mode 100644 index f49dc337..00000000 --- a/vendor/github.com/dustin/go-humanize/big.go +++ /dev/null @@ -1,31 +0,0 @@ -package humanize - -import ( - "math/big" -) - -// order of magnitude (to a max order) -func oomm(n, b *big.Int, maxmag int) (float64, int) { - mag := 0 - m := &big.Int{} - for n.Cmp(b) >= 0 { - n.DivMod(n, b, m) - mag++ - if mag == maxmag && maxmag >= 0 { - break - } - } - return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag -} - -// total order of magnitude -// (same as above, but with no upper limit) -func oom(n, b *big.Int) (float64, int) { - mag := 0 - m := &big.Int{} - for n.Cmp(b) >= 0 { - n.DivMod(n, b, m) - mag++ - } - return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag -} diff --git a/vendor/github.com/dustin/go-humanize/bigbytes.go b/vendor/github.com/dustin/go-humanize/bigbytes.go deleted file mode 100644 index 3b015fd5..00000000 --- a/vendor/github.com/dustin/go-humanize/bigbytes.go +++ /dev/null @@ -1,189 +0,0 @@ -package humanize - -import ( - "fmt" - "math/big" - "strings" - "unicode" -) - -var ( - bigIECExp = big.NewInt(1024) - - // BigByte is one byte in bit.Ints - BigByte = big.NewInt(1) - // BigKiByte is 1,024 bytes in bit.Ints - BigKiByte = (&big.Int{}).Mul(BigByte, bigIECExp) - // BigMiByte is 1,024 k bytes in bit.Ints - BigMiByte = (&big.Int{}).Mul(BigKiByte, bigIECExp) - // BigGiByte is 1,024 m bytes in bit.Ints - BigGiByte = (&big.Int{}).Mul(BigMiByte, bigIECExp) - // BigTiByte is 1,024 g bytes in bit.Ints - BigTiByte = (&big.Int{}).Mul(BigGiByte, bigIECExp) - // BigPiByte is 1,024 t bytes in bit.Ints - BigPiByte = (&big.Int{}).Mul(BigTiByte, bigIECExp) - // BigEiByte is 1,024 p bytes in bit.Ints - BigEiByte = (&big.Int{}).Mul(BigPiByte, bigIECExp) - // BigZiByte is 1,024 e bytes in bit.Ints - BigZiByte = (&big.Int{}).Mul(BigEiByte, bigIECExp) - // BigYiByte is 1,024 z bytes in bit.Ints - BigYiByte = (&big.Int{}).Mul(BigZiByte, bigIECExp) - // BigRiByte is 1,024 y bytes in bit.Ints - BigRiByte = (&big.Int{}).Mul(BigYiByte, bigIECExp) - // BigQiByte is 1,024 r bytes in bit.Ints - BigQiByte = (&big.Int{}).Mul(BigRiByte, bigIECExp) -) - -var ( - bigSIExp = big.NewInt(1000) - - // BigSIByte is one SI byte in big.Ints - BigSIByte = big.NewInt(1) - // BigKByte is 1,000 SI bytes in big.Ints - BigKByte = (&big.Int{}).Mul(BigSIByte, bigSIExp) - // BigMByte is 1,000 SI k bytes in big.Ints - BigMByte = (&big.Int{}).Mul(BigKByte, bigSIExp) - // BigGByte is 1,000 SI m bytes in big.Ints - BigGByte = (&big.Int{}).Mul(BigMByte, bigSIExp) - // BigTByte is 1,000 SI g bytes in big.Ints - BigTByte = (&big.Int{}).Mul(BigGByte, bigSIExp) - // BigPByte is 1,000 SI t bytes in big.Ints - BigPByte = (&big.Int{}).Mul(BigTByte, bigSIExp) - // BigEByte is 1,000 SI p bytes in big.Ints - BigEByte = (&big.Int{}).Mul(BigPByte, bigSIExp) - // BigZByte is 1,000 SI e bytes in big.Ints - BigZByte = (&big.Int{}).Mul(BigEByte, bigSIExp) - // BigYByte is 1,000 SI z bytes in big.Ints - BigYByte = (&big.Int{}).Mul(BigZByte, bigSIExp) - // BigRByte is 1,000 SI y bytes in big.Ints - BigRByte = (&big.Int{}).Mul(BigYByte, bigSIExp) - // BigQByte is 1,000 SI r bytes in big.Ints - BigQByte = (&big.Int{}).Mul(BigRByte, bigSIExp) -) - -var bigBytesSizeTable = map[string]*big.Int{ - "b": BigByte, - "kib": BigKiByte, - "kb": BigKByte, - "mib": BigMiByte, - "mb": BigMByte, - "gib": BigGiByte, - "gb": BigGByte, - "tib": BigTiByte, - "tb": BigTByte, - "pib": BigPiByte, - "pb": BigPByte, - "eib": BigEiByte, - "eb": BigEByte, - "zib": BigZiByte, - "zb": BigZByte, - "yib": BigYiByte, - "yb": BigYByte, - "rib": BigRiByte, - "rb": BigRByte, - "qib": BigQiByte, - "qb": BigQByte, - // Without suffix - "": BigByte, - "ki": BigKiByte, - "k": BigKByte, - "mi": BigMiByte, - "m": BigMByte, - "gi": BigGiByte, - "g": BigGByte, - "ti": BigTiByte, - "t": BigTByte, - "pi": BigPiByte, - "p": BigPByte, - "ei": BigEiByte, - "e": BigEByte, - "z": BigZByte, - "zi": BigZiByte, - "y": BigYByte, - "yi": BigYiByte, - "r": BigRByte, - "ri": BigRiByte, - "q": BigQByte, - "qi": BigQiByte, -} - -var ten = big.NewInt(10) - -func humanateBigBytes(s, base *big.Int, sizes []string) string { - if s.Cmp(ten) < 0 { - return fmt.Sprintf("%d B", s) - } - c := (&big.Int{}).Set(s) - val, mag := oomm(c, base, len(sizes)-1) - suffix := sizes[mag] - f := "%.0f %s" - if val < 10 { - f = "%.1f %s" - } - - return fmt.Sprintf(f, val, suffix) - -} - -// BigBytes produces a human readable representation of an SI size. -// -// See also: ParseBigBytes. -// -// BigBytes(82854982) -> 83 MB -func BigBytes(s *big.Int) string { - sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "RB", "QB"} - return humanateBigBytes(s, bigSIExp, sizes) -} - -// BigIBytes produces a human readable representation of an IEC size. -// -// See also: ParseBigBytes. -// -// BigIBytes(82854982) -> 79 MiB -func BigIBytes(s *big.Int) string { - sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"} - return humanateBigBytes(s, bigIECExp, sizes) -} - -// ParseBigBytes parses a string representation of bytes into the number -// of bytes it represents. -// -// See also: BigBytes, BigIBytes. -// -// ParseBigBytes("42 MB") -> 42000000, nil -// ParseBigBytes("42 mib") -> 44040192, nil -func ParseBigBytes(s string) (*big.Int, error) { - lastDigit := 0 - hasComma := false - for _, r := range s { - if !(unicode.IsDigit(r) || r == '.' || r == ',') { - break - } - if r == ',' { - hasComma = true - } - lastDigit++ - } - - num := s[:lastDigit] - if hasComma { - num = strings.Replace(num, ",", "", -1) - } - - val := &big.Rat{} - _, err := fmt.Sscanf(num, "%f", val) - if err != nil { - return nil, err - } - - extra := strings.ToLower(strings.TrimSpace(s[lastDigit:])) - if m, ok := bigBytesSizeTable[extra]; ok { - mv := (&big.Rat{}).SetInt(m) - val.Mul(val, mv) - rv := &big.Int{} - rv.Div(val.Num(), val.Denom()) - return rv, nil - } - - return nil, fmt.Errorf("unhandled size name: %v", extra) -} diff --git a/vendor/github.com/dustin/go-humanize/bytes.go b/vendor/github.com/dustin/go-humanize/bytes.go deleted file mode 100644 index 0b498f48..00000000 --- a/vendor/github.com/dustin/go-humanize/bytes.go +++ /dev/null @@ -1,143 +0,0 @@ -package humanize - -import ( - "fmt" - "math" - "strconv" - "strings" - "unicode" -) - -// IEC Sizes. -// kibis of bits -const ( - Byte = 1 << (iota * 10) - KiByte - MiByte - GiByte - TiByte - PiByte - EiByte -) - -// SI Sizes. -const ( - IByte = 1 - KByte = IByte * 1000 - MByte = KByte * 1000 - GByte = MByte * 1000 - TByte = GByte * 1000 - PByte = TByte * 1000 - EByte = PByte * 1000 -) - -var bytesSizeTable = map[string]uint64{ - "b": Byte, - "kib": KiByte, - "kb": KByte, - "mib": MiByte, - "mb": MByte, - "gib": GiByte, - "gb": GByte, - "tib": TiByte, - "tb": TByte, - "pib": PiByte, - "pb": PByte, - "eib": EiByte, - "eb": EByte, - // Without suffix - "": Byte, - "ki": KiByte, - "k": KByte, - "mi": MiByte, - "m": MByte, - "gi": GiByte, - "g": GByte, - "ti": TiByte, - "t": TByte, - "pi": PiByte, - "p": PByte, - "ei": EiByte, - "e": EByte, -} - -func logn(n, b float64) float64 { - return math.Log(n) / math.Log(b) -} - -func humanateBytes(s uint64, base float64, sizes []string) string { - if s < 10 { - return fmt.Sprintf("%d B", s) - } - e := math.Floor(logn(float64(s), base)) - suffix := sizes[int(e)] - val := math.Floor(float64(s)/math.Pow(base, e)*10+0.5) / 10 - f := "%.0f %s" - if val < 10 { - f = "%.1f %s" - } - - return fmt.Sprintf(f, val, suffix) -} - -// Bytes produces a human readable representation of an SI size. -// -// See also: ParseBytes. -// -// Bytes(82854982) -> 83 MB -func Bytes(s uint64) string { - sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB"} - return humanateBytes(s, 1000, sizes) -} - -// IBytes produces a human readable representation of an IEC size. -// -// See also: ParseBytes. -// -// IBytes(82854982) -> 79 MiB -func IBytes(s uint64) string { - sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"} - return humanateBytes(s, 1024, sizes) -} - -// ParseBytes parses a string representation of bytes into the number -// of bytes it represents. -// -// See Also: Bytes, IBytes. -// -// ParseBytes("42 MB") -> 42000000, nil -// ParseBytes("42 mib") -> 44040192, nil -func ParseBytes(s string) (uint64, error) { - lastDigit := 0 - hasComma := false - for _, r := range s { - if !(unicode.IsDigit(r) || r == '.' || r == ',') { - break - } - if r == ',' { - hasComma = true - } - lastDigit++ - } - - num := s[:lastDigit] - if hasComma { - num = strings.Replace(num, ",", "", -1) - } - - f, err := strconv.ParseFloat(num, 64) - if err != nil { - return 0, err - } - - extra := strings.ToLower(strings.TrimSpace(s[lastDigit:])) - if m, ok := bytesSizeTable[extra]; ok { - f *= float64(m) - if f >= math.MaxUint64 { - return 0, fmt.Errorf("too large: %v", s) - } - return uint64(f), nil - } - - return 0, fmt.Errorf("unhandled size name: %v", extra) -} diff --git a/vendor/github.com/dustin/go-humanize/comma.go b/vendor/github.com/dustin/go-humanize/comma.go deleted file mode 100644 index 520ae3e5..00000000 --- a/vendor/github.com/dustin/go-humanize/comma.go +++ /dev/null @@ -1,116 +0,0 @@ -package humanize - -import ( - "bytes" - "math" - "math/big" - "strconv" - "strings" -) - -// Comma produces a string form of the given number in base 10 with -// commas after every three orders of magnitude. -// -// e.g. Comma(834142) -> 834,142 -func Comma(v int64) string { - sign := "" - - // Min int64 can't be negated to a usable value, so it has to be special cased. - if v == math.MinInt64 { - return "-9,223,372,036,854,775,808" - } - - if v < 0 { - sign = "-" - v = 0 - v - } - - parts := []string{"", "", "", "", "", "", ""} - j := len(parts) - 1 - - for v > 999 { - parts[j] = strconv.FormatInt(v%1000, 10) - switch len(parts[j]) { - case 2: - parts[j] = "0" + parts[j] - case 1: - parts[j] = "00" + parts[j] - } - v = v / 1000 - j-- - } - parts[j] = strconv.Itoa(int(v)) - return sign + strings.Join(parts[j:], ",") -} - -// Commaf produces a string form of the given number in base 10 with -// commas after every three orders of magnitude. -// -// e.g. Commaf(834142.32) -> 834,142.32 -func Commaf(v float64) string { - buf := &bytes.Buffer{} - if v < 0 { - buf.Write([]byte{'-'}) - v = 0 - v - } - - comma := []byte{','} - - parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".") - pos := 0 - if len(parts[0])%3 != 0 { - pos += len(parts[0]) % 3 - buf.WriteString(parts[0][:pos]) - buf.Write(comma) - } - for ; pos < len(parts[0]); pos += 3 { - buf.WriteString(parts[0][pos : pos+3]) - buf.Write(comma) - } - buf.Truncate(buf.Len() - 1) - - if len(parts) > 1 { - buf.Write([]byte{'.'}) - buf.WriteString(parts[1]) - } - return buf.String() -} - -// CommafWithDigits works like the Commaf but limits the resulting -// string to the given number of decimal places. -// -// e.g. CommafWithDigits(834142.32, 1) -> 834,142.3 -func CommafWithDigits(f float64, decimals int) string { - return stripTrailingDigits(Commaf(f), decimals) -} - -// BigComma produces a string form of the given big.Int in base 10 -// with commas after every three orders of magnitude. -func BigComma(b *big.Int) string { - sign := "" - if b.Sign() < 0 { - sign = "-" - b.Abs(b) - } - - athousand := big.NewInt(1000) - c := (&big.Int{}).Set(b) - _, m := oom(c, athousand) - parts := make([]string, m+1) - j := len(parts) - 1 - - mod := &big.Int{} - for b.Cmp(athousand) >= 0 { - b.DivMod(b, athousand, mod) - parts[j] = strconv.FormatInt(mod.Int64(), 10) - switch len(parts[j]) { - case 2: - parts[j] = "0" + parts[j] - case 1: - parts[j] = "00" + parts[j] - } - j-- - } - parts[j] = strconv.Itoa(int(b.Int64())) - return sign + strings.Join(parts[j:], ",") -} diff --git a/vendor/github.com/dustin/go-humanize/commaf.go b/vendor/github.com/dustin/go-humanize/commaf.go deleted file mode 100644 index 2bc83a03..00000000 --- a/vendor/github.com/dustin/go-humanize/commaf.go +++ /dev/null @@ -1,41 +0,0 @@ -//go:build go1.6 -// +build go1.6 - -package humanize - -import ( - "bytes" - "math/big" - "strings" -) - -// BigCommaf produces a string form of the given big.Float in base 10 -// with commas after every three orders of magnitude. -func BigCommaf(v *big.Float) string { - buf := &bytes.Buffer{} - if v.Sign() < 0 { - buf.Write([]byte{'-'}) - v.Abs(v) - } - - comma := []byte{','} - - parts := strings.Split(v.Text('f', -1), ".") - pos := 0 - if len(parts[0])%3 != 0 { - pos += len(parts[0]) % 3 - buf.WriteString(parts[0][:pos]) - buf.Write(comma) - } - for ; pos < len(parts[0]); pos += 3 { - buf.WriteString(parts[0][pos : pos+3]) - buf.Write(comma) - } - buf.Truncate(buf.Len() - 1) - - if len(parts) > 1 { - buf.Write([]byte{'.'}) - buf.WriteString(parts[1]) - } - return buf.String() -} diff --git a/vendor/github.com/dustin/go-humanize/ftoa.go b/vendor/github.com/dustin/go-humanize/ftoa.go deleted file mode 100644 index bce923f3..00000000 --- a/vendor/github.com/dustin/go-humanize/ftoa.go +++ /dev/null @@ -1,49 +0,0 @@ -package humanize - -import ( - "strconv" - "strings" -) - -func stripTrailingZeros(s string) string { - if !strings.ContainsRune(s, '.') { - return s - } - offset := len(s) - 1 - for offset > 0 { - if s[offset] == '.' { - offset-- - break - } - if s[offset] != '0' { - break - } - offset-- - } - return s[:offset+1] -} - -func stripTrailingDigits(s string, digits int) string { - if i := strings.Index(s, "."); i >= 0 { - if digits <= 0 { - return s[:i] - } - i++ - if i+digits >= len(s) { - return s - } - return s[:i+digits] - } - return s -} - -// Ftoa converts a float to a string with no trailing zeros. -func Ftoa(num float64) string { - return stripTrailingZeros(strconv.FormatFloat(num, 'f', 6, 64)) -} - -// FtoaWithDigits converts a float to a string but limits the resulting string -// to the given number of decimal places, and no trailing zeros. -func FtoaWithDigits(num float64, digits int) string { - return stripTrailingZeros(stripTrailingDigits(strconv.FormatFloat(num, 'f', 6, 64), digits)) -} diff --git a/vendor/github.com/dustin/go-humanize/humanize.go b/vendor/github.com/dustin/go-humanize/humanize.go deleted file mode 100644 index a2c2da31..00000000 --- a/vendor/github.com/dustin/go-humanize/humanize.go +++ /dev/null @@ -1,8 +0,0 @@ -/* -Package humanize converts boring ugly numbers to human-friendly strings and back. - -Durations can be turned into strings such as "3 days ago", numbers -representing sizes like 82854982 into useful strings like, "83 MB" or -"79 MiB" (whichever you prefer). -*/ -package humanize diff --git a/vendor/github.com/dustin/go-humanize/number.go b/vendor/github.com/dustin/go-humanize/number.go deleted file mode 100644 index 6470d0d4..00000000 --- a/vendor/github.com/dustin/go-humanize/number.go +++ /dev/null @@ -1,192 +0,0 @@ -package humanize - -/* -Slightly adapted from the source to fit go-humanize. - -Author: https://github.com/gorhill -Source: https://gist.github.com/gorhill/5285193 - -*/ - -import ( - "math" - "strconv" -) - -var ( - renderFloatPrecisionMultipliers = [...]float64{ - 1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - } - - renderFloatPrecisionRounders = [...]float64{ - 0.5, - 0.05, - 0.005, - 0.0005, - 0.00005, - 0.000005, - 0.0000005, - 0.00000005, - 0.000000005, - 0.0000000005, - } -) - -// FormatFloat produces a formatted number as string based on the following user-specified criteria: -// * thousands separator -// * decimal separator -// * decimal precision -// -// Usage: s := RenderFloat(format, n) -// The format parameter tells how to render the number n. -// -// See examples: http://play.golang.org/p/LXc1Ddm1lJ -// -// Examples of format strings, given n = 12345.6789: -// "#,###.##" => "12,345.67" -// "#,###." => "12,345" -// "#,###" => "12345,678" -// "#\u202F###,##" => "12 345,68" -// "#.###,###### => 12.345,678900 -// "" (aka default format) => 12,345.67 -// -// The highest precision allowed is 9 digits after the decimal symbol. -// There is also a version for integer number, FormatInteger(), -// which is convenient for calls within template. -func FormatFloat(format string, n float64) string { - // Special cases: - // NaN = "NaN" - // +Inf = "+Infinity" - // -Inf = "-Infinity" - if math.IsNaN(n) { - return "NaN" - } - if n > math.MaxFloat64 { - return "Infinity" - } - if n < (0.0 - math.MaxFloat64) { - return "-Infinity" - } - - // default format - precision := 2 - decimalStr := "." - thousandStr := "," - positiveStr := "" - negativeStr := "-" - - if len(format) > 0 { - format := []rune(format) - - // If there is an explicit format directive, - // then default values are these: - precision = 9 - thousandStr = "" - - // collect indices of meaningful formatting directives - formatIndx := []int{} - for i, char := range format { - if char != '#' && char != '0' { - formatIndx = append(formatIndx, i) - } - } - - if len(formatIndx) > 0 { - // Directive at index 0: - // Must be a '+' - // Raise an error if not the case - // index: 0123456789 - // +0.000,000 - // +000,000.0 - // +0000.00 - // +0000 - if formatIndx[0] == 0 { - if format[formatIndx[0]] != '+' { - panic("RenderFloat(): invalid positive sign directive") - } - positiveStr = "+" - formatIndx = formatIndx[1:] - } - - // Two directives: - // First is thousands separator - // Raise an error if not followed by 3-digit - // 0123456789 - // 0.000,000 - // 000,000.00 - if len(formatIndx) == 2 { - if (formatIndx[1] - formatIndx[0]) != 4 { - panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers") - } - thousandStr = string(format[formatIndx[0]]) - formatIndx = formatIndx[1:] - } - - // One directive: - // Directive is decimal separator - // The number of digit-specifier following the separator indicates wanted precision - // 0123456789 - // 0.00 - // 000,0000 - if len(formatIndx) == 1 { - decimalStr = string(format[formatIndx[0]]) - precision = len(format) - formatIndx[0] - 1 - } - } - } - - // generate sign part - var signStr string - if n >= 0.000000001 { - signStr = positiveStr - } else if n <= -0.000000001 { - signStr = negativeStr - n = -n - } else { - signStr = "" - n = 0.0 - } - - // split number into integer and fractional parts - intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision]) - - // generate integer part string - intStr := strconv.FormatInt(int64(intf), 10) - - // add thousand separator if required - if len(thousandStr) > 0 { - for i := len(intStr); i > 3; { - i -= 3 - intStr = intStr[:i] + thousandStr + intStr[i:] - } - } - - // no fractional part, we can leave now - if precision == 0 { - return signStr + intStr - } - - // generate fractional part - fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision])) - // may need padding - if len(fracStr) < precision { - fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr - } - - return signStr + intStr + decimalStr + fracStr -} - -// FormatInteger produces a formatted number as string. -// See FormatFloat. -func FormatInteger(format string, n int) string { - return FormatFloat(format, float64(n)) -} diff --git a/vendor/github.com/dustin/go-humanize/ordinals.go b/vendor/github.com/dustin/go-humanize/ordinals.go deleted file mode 100644 index 43d88a86..00000000 --- a/vendor/github.com/dustin/go-humanize/ordinals.go +++ /dev/null @@ -1,25 +0,0 @@ -package humanize - -import "strconv" - -// Ordinal gives you the input number in a rank/ordinal format. -// -// Ordinal(3) -> 3rd -func Ordinal(x int) string { - suffix := "th" - switch x % 10 { - case 1: - if x%100 != 11 { - suffix = "st" - } - case 2: - if x%100 != 12 { - suffix = "nd" - } - case 3: - if x%100 != 13 { - suffix = "rd" - } - } - return strconv.Itoa(x) + suffix -} diff --git a/vendor/github.com/dustin/go-humanize/si.go b/vendor/github.com/dustin/go-humanize/si.go deleted file mode 100644 index 8b850198..00000000 --- a/vendor/github.com/dustin/go-humanize/si.go +++ /dev/null @@ -1,127 +0,0 @@ -package humanize - -import ( - "errors" - "math" - "regexp" - "strconv" -) - -var siPrefixTable = map[float64]string{ - -30: "q", // quecto - -27: "r", // ronto - -24: "y", // yocto - -21: "z", // zepto - -18: "a", // atto - -15: "f", // femto - -12: "p", // pico - -9: "n", // nano - -6: "µ", // micro - -3: "m", // milli - 0: "", - 3: "k", // kilo - 6: "M", // mega - 9: "G", // giga - 12: "T", // tera - 15: "P", // peta - 18: "E", // exa - 21: "Z", // zetta - 24: "Y", // yotta - 27: "R", // ronna - 30: "Q", // quetta -} - -var revSIPrefixTable = revfmap(siPrefixTable) - -// revfmap reverses the map and precomputes the power multiplier -func revfmap(in map[float64]string) map[string]float64 { - rv := map[string]float64{} - for k, v := range in { - rv[v] = math.Pow(10, k) - } - return rv -} - -var riParseRegex *regexp.Regexp - -func init() { - ri := `^([\-0-9.]+)\s?([` - for _, v := range siPrefixTable { - ri += v - } - ri += `]?)(.*)` - - riParseRegex = regexp.MustCompile(ri) -} - -// ComputeSI finds the most appropriate SI prefix for the given number -// and returns the prefix along with the value adjusted to be within -// that prefix. -// -// See also: SI, ParseSI. -// -// e.g. ComputeSI(2.2345e-12) -> (2.2345, "p") -func ComputeSI(input float64) (float64, string) { - if input == 0 { - return 0, "" - } - mag := math.Abs(input) - exponent := math.Floor(logn(mag, 10)) - exponent = math.Floor(exponent/3) * 3 - - value := mag / math.Pow(10, exponent) - - // Handle special case where value is exactly 1000.0 - // Should return 1 M instead of 1000 k - if value == 1000.0 { - exponent += 3 - value = mag / math.Pow(10, exponent) - } - - value = math.Copysign(value, input) - - prefix := siPrefixTable[exponent] - return value, prefix -} - -// SI returns a string with default formatting. -// -// SI uses Ftoa to format float value, removing trailing zeros. -// -// See also: ComputeSI, ParseSI. -// -// e.g. SI(1000000, "B") -> 1 MB -// e.g. SI(2.2345e-12, "F") -> 2.2345 pF -func SI(input float64, unit string) string { - value, prefix := ComputeSI(input) - return Ftoa(value) + " " + prefix + unit -} - -// SIWithDigits works like SI but limits the resulting string to the -// given number of decimal places. -// -// e.g. SIWithDigits(1000000, 0, "B") -> 1 MB -// e.g. SIWithDigits(2.2345e-12, 2, "F") -> 2.23 pF -func SIWithDigits(input float64, decimals int, unit string) string { - value, prefix := ComputeSI(input) - return FtoaWithDigits(value, decimals) + " " + prefix + unit -} - -var errInvalid = errors.New("invalid input") - -// ParseSI parses an SI string back into the number and unit. -// -// See also: SI, ComputeSI. -// -// e.g. ParseSI("2.2345 pF") -> (2.2345e-12, "F", nil) -func ParseSI(input string) (float64, string, error) { - found := riParseRegex.FindStringSubmatch(input) - if len(found) != 4 { - return 0, "", errInvalid - } - mag := revSIPrefixTable[found[2]] - unit := found[3] - - base, err := strconv.ParseFloat(found[1], 64) - return base * mag, unit, err -} diff --git a/vendor/github.com/dustin/go-humanize/times.go b/vendor/github.com/dustin/go-humanize/times.go deleted file mode 100644 index dd3fbf5e..00000000 --- a/vendor/github.com/dustin/go-humanize/times.go +++ /dev/null @@ -1,117 +0,0 @@ -package humanize - -import ( - "fmt" - "math" - "sort" - "time" -) - -// Seconds-based time units -const ( - Day = 24 * time.Hour - Week = 7 * Day - Month = 30 * Day - Year = 12 * Month - LongTime = 37 * Year -) - -// Time formats a time into a relative string. -// -// Time(someT) -> "3 weeks ago" -func Time(then time.Time) string { - return RelTime(then, time.Now(), "ago", "from now") -} - -// A RelTimeMagnitude struct contains a relative time point at which -// the relative format of time will switch to a new format string. A -// slice of these in ascending order by their "D" field is passed to -// CustomRelTime to format durations. -// -// The Format field is a string that may contain a "%s" which will be -// replaced with the appropriate signed label (e.g. "ago" or "from -// now") and a "%d" that will be replaced by the quantity. -// -// The DivBy field is the amount of time the time difference must be -// divided by in order to display correctly. -// -// e.g. if D is 2*time.Minute and you want to display "%d minutes %s" -// DivBy should be time.Minute so whatever the duration is will be -// expressed in minutes. -type RelTimeMagnitude struct { - D time.Duration - Format string - DivBy time.Duration -} - -var defaultMagnitudes = []RelTimeMagnitude{ - {time.Second, "now", time.Second}, - {2 * time.Second, "1 second %s", 1}, - {time.Minute, "%d seconds %s", time.Second}, - {2 * time.Minute, "1 minute %s", 1}, - {time.Hour, "%d minutes %s", time.Minute}, - {2 * time.Hour, "1 hour %s", 1}, - {Day, "%d hours %s", time.Hour}, - {2 * Day, "1 day %s", 1}, - {Week, "%d days %s", Day}, - {2 * Week, "1 week %s", 1}, - {Month, "%d weeks %s", Week}, - {2 * Month, "1 month %s", 1}, - {Year, "%d months %s", Month}, - {18 * Month, "1 year %s", 1}, - {2 * Year, "2 years %s", 1}, - {LongTime, "%d years %s", Year}, - {math.MaxInt64, "a long while %s", 1}, -} - -// RelTime formats a time into a relative string. -// -// It takes two times and two labels. In addition to the generic time -// delta string (e.g. 5 minutes), the labels are used applied so that -// the label corresponding to the smaller time is applied. -// -// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier" -func RelTime(a, b time.Time, albl, blbl string) string { - return CustomRelTime(a, b, albl, blbl, defaultMagnitudes) -} - -// CustomRelTime formats a time into a relative string. -// -// It takes two times two labels and a table of relative time formats. -// In addition to the generic time delta string (e.g. 5 minutes), the -// labels are used applied so that the label corresponding to the -// smaller time is applied. -func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string { - lbl := albl - diff := b.Sub(a) - - if a.After(b) { - lbl = blbl - diff = a.Sub(b) - } - - n := sort.Search(len(magnitudes), func(i int) bool { - return magnitudes[i].D > diff - }) - - if n >= len(magnitudes) { - n = len(magnitudes) - 1 - } - mag := magnitudes[n] - args := []interface{}{} - escaped := false - for _, ch := range mag.Format { - if escaped { - switch ch { - case 's': - args = append(args, lbl) - case 'd': - args = append(args, diff/mag.DivBy) - } - escaped = false - } else { - escaped = ch == '%' - } - } - return fmt.Sprintf(mag.Format, args...) -} diff --git a/vendor/github.com/edsrzf/mmap-go/.gitignore b/vendor/github.com/edsrzf/mmap-go/.gitignore deleted file mode 100644 index 6c694e4b..00000000 --- a/vendor/github.com/edsrzf/mmap-go/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.out -*.5 -*.6 -*.8 -*.swp -_obj -_test -testdata -/.idea -*.iml -/notes.txt diff --git a/vendor/github.com/edsrzf/mmap-go/LICENSE b/vendor/github.com/edsrzf/mmap-go/LICENSE deleted file mode 100644 index 8f05f338..00000000 --- a/vendor/github.com/edsrzf/mmap-go/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2011, Evan Shaw -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/vendor/github.com/edsrzf/mmap-go/README.md b/vendor/github.com/edsrzf/mmap-go/README.md deleted file mode 100644 index 5df62b8e..00000000 --- a/vendor/github.com/edsrzf/mmap-go/README.md +++ /dev/null @@ -1,14 +0,0 @@ -mmap-go -======= -![Build Status](https://github.com/edsrzf/mmap-go/actions/workflows/build-test.yml/badge.svg) -[![Go Reference](https://pkg.go.dev/badge/github.com/edsrzf/mmap-go.svg)](https://pkg.go.dev/github.com/edsrzf/mmap-go) - -mmap-go is a portable mmap package for the [Go programming language](http://golang.org). - -Operating System Support -======================== -This package is tested using GitHub Actions on Linux, macOS, and Windows. It should also work on other Unix-like platforms, but hasn't been tested with them. I'm interested to hear about the results. - -This package compiles for Plan 9 and WebAssembly, but its functions always return errors. - -Related functions such as `mprotect` and `mincore` aren't included. I haven't found a way to implement them on Windows without introducing significant complexity. If you're running on a Unix-like platform and really need these features, it should still be possible to implement them on top of this package via `syscall`. diff --git a/vendor/github.com/edsrzf/mmap-go/mmap.go b/vendor/github.com/edsrzf/mmap-go/mmap.go deleted file mode 100644 index 29655bd2..00000000 --- a/vendor/github.com/edsrzf/mmap-go/mmap.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2011 Evan Shaw. 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 defines the common package interface and contains a little bit of -// factored out logic. - -// Package mmap allows mapping files into memory. It tries to provide a simple, reasonably portable interface, -// but doesn't go out of its way to abstract away every little platform detail. -// This specifically means: -// * forked processes may or may not inherit mappings -// * a file's timestamp may or may not be updated by writes through mappings -// * specifying a size larger than the file's actual size can increase the file's size -// * If the mapped file is being modified by another process while your program's running, don't expect consistent results between platforms -package mmap - -import ( - "errors" - "os" - "reflect" - "unsafe" -) - -const ( - // RDONLY maps the memory read-only. - // Attempts to write to the MMap object will result in undefined behavior. - RDONLY = 0 - // RDWR maps the memory as read-write. Writes to the MMap object will update the - // underlying file. - RDWR = 1 << iota - // COPY maps the memory as copy-on-write. Writes to the MMap object will affect - // memory, but the underlying file will remain unchanged. - COPY - // If EXEC is set, the mapped memory is marked as executable. - EXEC -) - -const ( - // If the ANON flag is set, the mapped memory will not be backed by a file. - ANON = 1 << iota -) - -// MMap represents a file mapped into memory. -type MMap []byte - -// Map maps an entire file into memory. -// If ANON is set in flags, f is ignored. -func Map(f *os.File, prot, flags int) (MMap, error) { - return MapRegion(f, -1, prot, flags, 0) -} - -// MapRegion maps part of a file into memory. -// The offset parameter must be a multiple of the system's page size. -// If length < 0, the entire file will be mapped. -// If ANON is set in flags, f is ignored. -func MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) { - if offset%int64(os.Getpagesize()) != 0 { - return nil, errors.New("offset parameter must be a multiple of the system's page size") - } - - var fd uintptr - if flags&ANON == 0 { - fd = uintptr(f.Fd()) - if length < 0 { - fi, err := f.Stat() - if err != nil { - return nil, err - } - length = int(fi.Size()) - } - } else { - if length <= 0 { - return nil, errors.New("anonymous mapping requires non-zero length") - } - fd = ^uintptr(0) - } - return mmap(length, uintptr(prot), uintptr(flags), fd, offset) -} - -func (m *MMap) header() *reflect.SliceHeader { - return (*reflect.SliceHeader)(unsafe.Pointer(m)) -} - -func (m *MMap) addrLen() (uintptr, uintptr) { - header := m.header() - return header.Data, uintptr(header.Len) -} - -// Lock keeps the mapped region in physical memory, ensuring that it will not be -// swapped out. -func (m MMap) Lock() error { - return m.lock() -} - -// Unlock reverses the effect of Lock, allowing the mapped region to potentially -// be swapped out. -// If m is already unlocked, aan error will result. -func (m MMap) Unlock() error { - return m.unlock() -} - -// Flush synchronizes the mapping's contents to the file's contents on disk. -func (m MMap) Flush() error { - return m.flush() -} - -// Unmap deletes the memory mapped region, flushes any remaining changes, and sets -// m to nil. -// Trying to read or write any remaining references to m after Unmap is called will -// result in undefined behavior. -// Unmap should only be called on the slice value that was originally returned from -// a call to Map. Calling Unmap on a derived slice may cause errors. -func (m *MMap) Unmap() error { - err := m.unmap() - *m = nil - return err -} diff --git a/vendor/github.com/edsrzf/mmap-go/mmap_plan9.go b/vendor/github.com/edsrzf/mmap-go/mmap_plan9.go deleted file mode 100644 index e4c33d39..00000000 --- a/vendor/github.com/edsrzf/mmap-go/mmap_plan9.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mmap - -import "syscall" - -func mmap(len int, inprot, inflags, fd uintptr, off int64) ([]byte, error) { - return nil, syscall.EPLAN9 -} - -func (m MMap) flush() error { - return syscall.EPLAN9 -} - -func (m MMap) lock() error { - return syscall.EPLAN9 -} - -func (m MMap) unlock() error { - return syscall.EPLAN9 -} - -func (m MMap) unmap() error { - return syscall.EPLAN9 -} diff --git a/vendor/github.com/edsrzf/mmap-go/mmap_unix.go b/vendor/github.com/edsrzf/mmap-go/mmap_unix.go deleted file mode 100644 index 25b13e51..00000000 --- a/vendor/github.com/edsrzf/mmap-go/mmap_unix.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2011 Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux openbsd solaris netbsd - -package mmap - -import ( - "golang.org/x/sys/unix" -) - -func mmap(len int, inprot, inflags, fd uintptr, off int64) ([]byte, error) { - flags := unix.MAP_SHARED - prot := unix.PROT_READ - switch { - case inprot© != 0: - prot |= unix.PROT_WRITE - flags = unix.MAP_PRIVATE - case inprot&RDWR != 0: - prot |= unix.PROT_WRITE - } - if inprot&EXEC != 0 { - prot |= unix.PROT_EXEC - } - if inflags&ANON != 0 { - flags |= unix.MAP_ANON - } - - b, err := unix.Mmap(int(fd), off, len, prot, flags) - if err != nil { - return nil, err - } - return b, nil -} - -func (m MMap) flush() error { - return unix.Msync([]byte(m), unix.MS_SYNC) -} - -func (m MMap) lock() error { - return unix.Mlock([]byte(m)) -} - -func (m MMap) unlock() error { - return unix.Munlock([]byte(m)) -} - -func (m MMap) unmap() error { - return unix.Munmap([]byte(m)) -} diff --git a/vendor/github.com/edsrzf/mmap-go/mmap_wasm.go b/vendor/github.com/edsrzf/mmap-go/mmap_wasm.go deleted file mode 100644 index cfe1c50b..00000000 --- a/vendor/github.com/edsrzf/mmap-go/mmap_wasm.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2024 Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mmap - -import "syscall" - -func mmap(len int, inprot, inflags, fd uintptr, off int64) ([]byte, error) { - return nil, syscall.ENOTSUP -} - -func (m MMap) flush() error { - return syscall.ENOTSUP -} - -func (m MMap) lock() error { - return syscall.ENOTSUP -} - -func (m MMap) unlock() error { - return syscall.ENOTSUP -} - -func (m MMap) unmap() error { - return syscall.ENOTSUP -} diff --git a/vendor/github.com/edsrzf/mmap-go/mmap_windows.go b/vendor/github.com/edsrzf/mmap-go/mmap_windows.go deleted file mode 100644 index e0d986f7..00000000 --- a/vendor/github.com/edsrzf/mmap-go/mmap_windows.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2011 Evan Shaw. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mmap - -import ( - "errors" - "os" - "sync" - - "golang.org/x/sys/windows" -) - -// mmap on Windows is a two-step process. -// First, we call CreateFileMapping to get a handle. -// Then, we call MapviewToFile to get an actual pointer into memory. -// Because we want to emulate a POSIX-style mmap, we don't want to expose -// the handle -- only the pointer. We also want to return only a byte slice, -// not a struct, so it's convenient to manipulate. - -// We keep this map so that we can get back the original handle from the memory address. - -type addrinfo struct { - file windows.Handle - mapview windows.Handle - writable bool -} - -var handleLock sync.Mutex -var handleMap = map[uintptr]*addrinfo{} - -func mmap(len int, prot, flags, hfile uintptr, off int64) ([]byte, error) { - flProtect := uint32(windows.PAGE_READONLY) - dwDesiredAccess := uint32(windows.FILE_MAP_READ) - writable := false - switch { - case prot© != 0: - flProtect = windows.PAGE_WRITECOPY - dwDesiredAccess = windows.FILE_MAP_COPY - writable = true - case prot&RDWR != 0: - flProtect = windows.PAGE_READWRITE - dwDesiredAccess = windows.FILE_MAP_WRITE - writable = true - } - if prot&EXEC != 0 { - flProtect <<= 4 - dwDesiredAccess |= windows.FILE_MAP_EXECUTE - } - - // The maximum size is the area of the file, starting from 0, - // that we wish to allow to be mappable. It is the sum of - // the length the user requested, plus the offset where that length - // is starting from. This does not map the data into memory. - maxSizeHigh := uint32((off + int64(len)) >> 32) - maxSizeLow := uint32((off + int64(len)) & 0xFFFFFFFF) - // TODO: Do we need to set some security attributes? It might help portability. - h, errno := windows.CreateFileMapping(windows.Handle(hfile), nil, flProtect, maxSizeHigh, maxSizeLow, nil) - if h == 0 { - return nil, os.NewSyscallError("CreateFileMapping", errno) - } - - // Actually map a view of the data into memory. The view's size - // is the length the user requested. - fileOffsetHigh := uint32(off >> 32) - fileOffsetLow := uint32(off & 0xFFFFFFFF) - addr, errno := windows.MapViewOfFile(h, dwDesiredAccess, fileOffsetHigh, fileOffsetLow, uintptr(len)) - if addr == 0 { - windows.CloseHandle(windows.Handle(h)) - return nil, os.NewSyscallError("MapViewOfFile", errno) - } - handleLock.Lock() - handleMap[addr] = &addrinfo{ - file: windows.Handle(hfile), - mapview: h, - writable: writable, - } - handleLock.Unlock() - - m := MMap{} - dh := m.header() - dh.Data = addr - dh.Len = len - dh.Cap = dh.Len - - return m, nil -} - -func (m MMap) flush() error { - addr, len := m.addrLen() - errno := windows.FlushViewOfFile(addr, len) - if errno != nil { - return os.NewSyscallError("FlushViewOfFile", errno) - } - - handleLock.Lock() - defer handleLock.Unlock() - handle, ok := handleMap[addr] - if !ok { - // should be impossible; we would've errored above - return errors.New("unknown base address") - } - - if handle.writable && handle.file != windows.Handle(^uintptr(0)) { - if err := windows.FlushFileBuffers(handle.file); err != nil { - return os.NewSyscallError("FlushFileBuffers", err) - } - } - - return nil -} - -func (m MMap) lock() error { - addr, len := m.addrLen() - errno := windows.VirtualLock(addr, len) - return os.NewSyscallError("VirtualLock", errno) -} - -func (m MMap) unlock() error { - addr, len := m.addrLen() - errno := windows.VirtualUnlock(addr, len) - return os.NewSyscallError("VirtualUnlock", errno) -} - -func (m MMap) unmap() error { - err := m.flush() - if err != nil { - return err - } - - addr := m.header().Data - // Lock the UnmapViewOfFile along with the handleMap deletion. - // As soon as we unmap the view, the OS is free to give the - // same addr to another new map. We don't want another goroutine - // to insert and remove the same addr into handleMap while - // we're trying to remove our old addr/handle pair. - handleLock.Lock() - defer handleLock.Unlock() - err = windows.UnmapViewOfFile(addr) - if err != nil { - return err - } - - handle, ok := handleMap[addr] - if !ok { - // should be impossible; we would've errored above - return errors.New("unknown base address") - } - delete(handleMap, addr) - - e := windows.CloseHandle(windows.Handle(handle.mapview)) - return os.NewSyscallError("CloseHandle", e) -} diff --git a/vendor/github.com/emirpasic/gods/LICENSE b/vendor/github.com/emirpasic/gods/LICENSE deleted file mode 100644 index e5e449b6..00000000 --- a/vendor/github.com/emirpasic/gods/LICENSE +++ /dev/null @@ -1,41 +0,0 @@ -Copyright (c) 2015, Emir Pasic -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------------------- - -AVL Tree: - -Copyright (c) 2017 Benjamin Scher Purcell - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/emirpasic/gods/containers/containers.go b/vendor/github.com/emirpasic/gods/containers/containers.go deleted file mode 100644 index a512a3cb..00000000 --- a/vendor/github.com/emirpasic/gods/containers/containers.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package containers provides core interfaces and functions for data structures. -// -// Container is the base interface for all data structures to implement. -// -// Iterators provide stateful iterators. -// -// Enumerable provides Ruby inspired (each, select, map, find, any?, etc.) container functions. -// -// Serialization provides serializers (marshalers) and deserializers (unmarshalers). -package containers - -import "github.com/emirpasic/gods/utils" - -// Container is base interface that all data structures implement. -type Container interface { - Empty() bool - Size() int - Clear() - Values() []interface{} - String() string -} - -// GetSortedValues returns sorted container's elements with respect to the passed comparator. -// Does not affect the ordering of elements within the container. -func GetSortedValues(container Container, comparator utils.Comparator) []interface{} { - values := container.Values() - if len(values) < 2 { - return values - } - utils.Sort(values, comparator) - return values -} diff --git a/vendor/github.com/emirpasic/gods/containers/enumerable.go b/vendor/github.com/emirpasic/gods/containers/enumerable.go deleted file mode 100644 index 70660054..00000000 --- a/vendor/github.com/emirpasic/gods/containers/enumerable.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package containers - -// EnumerableWithIndex provides functions for ordered containers whose values can be fetched by an index. -type EnumerableWithIndex interface { - // Each calls the given function once for each element, passing that element's index and value. - Each(func(index int, value interface{})) - - // Map invokes the given function once for each element and returns a - // container containing the values returned by the given function. - // Map(func(index int, value interface{}) interface{}) Container - - // Select returns a new container containing all elements for which the given function returns a true value. - // Select(func(index int, value interface{}) bool) Container - - // Any passes each element of the container to the given function and - // returns true if the function ever returns true for any element. - Any(func(index int, value interface{}) bool) bool - - // All passes each element of the container to the given function and - // returns true if the function returns true for all elements. - All(func(index int, value interface{}) bool) bool - - // Find passes each element of the container to the given function and returns - // the first (index,value) for which the function is true or -1,nil otherwise - // if no element matches the criteria. - Find(func(index int, value interface{}) bool) (int, interface{}) -} - -// EnumerableWithKey provides functions for ordered containers whose values whose elements are key/value pairs. -type EnumerableWithKey interface { - // Each calls the given function once for each element, passing that element's key and value. - Each(func(key interface{}, value interface{})) - - // Map invokes the given function once for each element and returns a container - // containing the values returned by the given function as key/value pairs. - // Map(func(key interface{}, value interface{}) (interface{}, interface{})) Container - - // Select returns a new container containing all elements for which the given function returns a true value. - // Select(func(key interface{}, value interface{}) bool) Container - - // Any passes each element of the container to the given function and - // returns true if the function ever returns true for any element. - Any(func(key interface{}, value interface{}) bool) bool - - // All passes each element of the container to the given function and - // returns true if the function returns true for all elements. - All(func(key interface{}, value interface{}) bool) bool - - // Find passes each element of the container to the given function and returns - // the first (key,value) for which the function is true or nil,nil otherwise if no element - // matches the criteria. - Find(func(key interface{}, value interface{}) bool) (interface{}, interface{}) -} diff --git a/vendor/github.com/emirpasic/gods/containers/iterator.go b/vendor/github.com/emirpasic/gods/containers/iterator.go deleted file mode 100644 index 73994ec8..00000000 --- a/vendor/github.com/emirpasic/gods/containers/iterator.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package containers - -// IteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index. -type IteratorWithIndex interface { - // Next moves the iterator to the next element and returns true if there was a next element in the container. - // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). - // If Next() was called for the first time, then it will point the iterator to the first element if it exists. - // Modifies the state of the iterator. - Next() bool - - // Value returns the current element's value. - // Does not modify the state of the iterator. - Value() interface{} - - // Index returns the current element's index. - // Does not modify the state of the iterator. - Index() int - - // Begin resets the iterator to its initial state (one-before-first) - // Call Next() to fetch the first element if any. - Begin() - - // First moves the iterator to the first element and returns true if there was a first element in the container. - // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). - // Modifies the state of the iterator. - First() bool - - // NextTo moves the iterator to the next element from current position that satisfies the condition given by the - // passed function, and returns true if there was a next element in the container. - // If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value(). - // Modifies the state of the iterator. - NextTo(func(index int, value interface{}) bool) bool -} - -// IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. -type IteratorWithKey interface { - // Next moves the iterator to the next element and returns true if there was a next element in the container. - // If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). - // If Next() was called for the first time, then it will point the iterator to the first element if it exists. - // Modifies the state of the iterator. - Next() bool - - // Value returns the current element's value. - // Does not modify the state of the iterator. - Value() interface{} - - // Key returns the current element's key. - // Does not modify the state of the iterator. - Key() interface{} - - // Begin resets the iterator to its initial state (one-before-first) - // Call Next() to fetch the first element if any. - Begin() - - // First moves the iterator to the first element and returns true if there was a first element in the container. - // If First() returns true, then first element's key and value can be retrieved by Key() and Value(). - // Modifies the state of the iterator. - First() bool - - // NextTo moves the iterator to the next element from current position that satisfies the condition given by the - // passed function, and returns true if there was a next element in the container. - // If NextTo() returns true, then next element's key and value can be retrieved by Key() and Value(). - // Modifies the state of the iterator. - NextTo(func(key interface{}, value interface{}) bool) bool -} - -// ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index. -// -// Essentially it is the same as IteratorWithIndex, but provides additional: -// -// Prev() function to enable traversal in reverse -// -// Last() function to move the iterator to the last element. -// -// End() function to move the iterator past the last element (one-past-the-end). -type ReverseIteratorWithIndex interface { - // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. - // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). - // Modifies the state of the iterator. - Prev() bool - - // End moves the iterator past the last element (one-past-the-end). - // Call Prev() to fetch the last element if any. - End() - - // Last moves the iterator to the last element and returns true if there was a last element in the container. - // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). - // Modifies the state of the iterator. - Last() bool - - // PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the - // passed function, and returns true if there was a next element in the container. - // If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value(). - // Modifies the state of the iterator. - PrevTo(func(index int, value interface{}) bool) bool - - IteratorWithIndex -} - -// ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs. -// -// Essentially it is the same as IteratorWithKey, but provides additional: -// -// Prev() function to enable traversal in reverse -// -// Last() function to move the iterator to the last element. -type ReverseIteratorWithKey interface { - // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. - // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). - // Modifies the state of the iterator. - Prev() bool - - // End moves the iterator past the last element (one-past-the-end). - // Call Prev() to fetch the last element if any. - End() - - // Last moves the iterator to the last element and returns true if there was a last element in the container. - // If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). - // Modifies the state of the iterator. - Last() bool - - // PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the - // passed function, and returns true if there was a next element in the container. - // If PrevTo() returns true, then next element's key and value can be retrieved by Key() and Value(). - // Modifies the state of the iterator. - PrevTo(func(key interface{}, value interface{}) bool) bool - - IteratorWithKey -} diff --git a/vendor/github.com/emirpasic/gods/containers/serialization.go b/vendor/github.com/emirpasic/gods/containers/serialization.go deleted file mode 100644 index fd9cbe23..00000000 --- a/vendor/github.com/emirpasic/gods/containers/serialization.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package containers - -// JSONSerializer provides JSON serialization -type JSONSerializer interface { - // ToJSON outputs the JSON representation of containers's elements. - ToJSON() ([]byte, error) - // MarshalJSON @implements json.Marshaler - MarshalJSON() ([]byte, error) -} - -// JSONDeserializer provides JSON deserialization -type JSONDeserializer interface { - // FromJSON populates containers's elements from the input JSON representation. - FromJSON([]byte) error - // UnmarshalJSON @implements json.Unmarshaler - UnmarshalJSON([]byte) error -} diff --git a/vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go b/vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go deleted file mode 100644 index 60ce4583..00000000 --- a/vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package arraylist implements the array list. -// -// Structure is not thread safe. -// -// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 -package arraylist - -import ( - "fmt" - "strings" - - "github.com/emirpasic/gods/lists" - "github.com/emirpasic/gods/utils" -) - -// Assert List implementation -var _ lists.List = (*List)(nil) - -// List holds the elements in a slice -type List struct { - elements []interface{} - size int -} - -const ( - growthFactor = float32(2.0) // growth by 100% - shrinkFactor = float32(0.25) // shrink when size is 25% of capacity (0 means never shrink) -) - -// New instantiates a new list and adds the passed values, if any, to the list -func New(values ...interface{}) *List { - list := &List{} - if len(values) > 0 { - list.Add(values...) - } - return list -} - -// Add appends a value at the end of the list -func (list *List) Add(values ...interface{}) { - list.growBy(len(values)) - for _, value := range values { - list.elements[list.size] = value - list.size++ - } -} - -// Get returns the element at index. -// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false. -func (list *List) Get(index int) (interface{}, bool) { - - if !list.withinRange(index) { - return nil, false - } - - return list.elements[index], true -} - -// Remove removes the element at the given index from the list. -func (list *List) Remove(index int) { - - if !list.withinRange(index) { - return - } - - list.elements[index] = nil // cleanup reference - copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this) - list.size-- - - list.shrink() -} - -// Contains checks if elements (one or more) are present in the set. -// All elements have to be present in the set for the method to return true. -// Performance time complexity of n^2. -// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set. -func (list *List) Contains(values ...interface{}) bool { - - for _, searchValue := range values { - found := false - for index := 0; index < list.size; index++ { - if list.elements[index] == searchValue { - found = true - break - } - } - if !found { - return false - } - } - return true -} - -// Values returns all elements in the list. -func (list *List) Values() []interface{} { - newElements := make([]interface{}, list.size, list.size) - copy(newElements, list.elements[:list.size]) - return newElements -} - -//IndexOf returns index of provided element -func (list *List) IndexOf(value interface{}) int { - if list.size == 0 { - return -1 - } - for index, element := range list.elements { - if element == value { - return index - } - } - return -1 -} - -// Empty returns true if list does not contain any elements. -func (list *List) Empty() bool { - return list.size == 0 -} - -// Size returns number of elements within the list. -func (list *List) Size() int { - return list.size -} - -// Clear removes all elements from the list. -func (list *List) Clear() { - list.size = 0 - list.elements = []interface{}{} -} - -// Sort sorts values (in-place) using. -func (list *List) Sort(comparator utils.Comparator) { - if len(list.elements) < 2 { - return - } - utils.Sort(list.elements[:list.size], comparator) -} - -// Swap swaps the two values at the specified positions. -func (list *List) Swap(i, j int) { - if list.withinRange(i) && list.withinRange(j) { - list.elements[i], list.elements[j] = list.elements[j], list.elements[i] - } -} - -// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. -// Does not do anything if position is negative or bigger than list's size -// Note: position equal to list's size is valid, i.e. append. -func (list *List) Insert(index int, values ...interface{}) { - - if !list.withinRange(index) { - // Append - if index == list.size { - list.Add(values...) - } - return - } - - l := len(values) - list.growBy(l) - list.size += l - copy(list.elements[index+l:], list.elements[index:list.size-l]) - copy(list.elements[index:], values) -} - -// Set the value at specified index -// Does not do anything if position is negative or bigger than list's size -// Note: position equal to list's size is valid, i.e. append. -func (list *List) Set(index int, value interface{}) { - - if !list.withinRange(index) { - // Append - if index == list.size { - list.Add(value) - } - return - } - - list.elements[index] = value -} - -// String returns a string representation of container -func (list *List) String() string { - str := "ArrayList\n" - values := []string{} - for _, value := range list.elements[:list.size] { - values = append(values, fmt.Sprintf("%v", value)) - } - str += strings.Join(values, ", ") - return str -} - -// Check that the index is within bounds of the list -func (list *List) withinRange(index int) bool { - return index >= 0 && index < list.size -} - -func (list *List) resize(cap int) { - newElements := make([]interface{}, cap, cap) - copy(newElements, list.elements) - list.elements = newElements -} - -// Expand the array if necessary, i.e. capacity will be reached if we add n elements -func (list *List) growBy(n int) { - // When capacity is reached, grow by a factor of growthFactor and add number of elements - currentCapacity := cap(list.elements) - if list.size+n >= currentCapacity { - newCapacity := int(growthFactor * float32(currentCapacity+n)) - list.resize(newCapacity) - } -} - -// Shrink the array if necessary, i.e. when size is shrinkFactor percent of current capacity -func (list *List) shrink() { - if shrinkFactor == 0.0 { - return - } - // Shrink when size is at shrinkFactor * capacity - currentCapacity := cap(list.elements) - if list.size <= int(float32(currentCapacity)*shrinkFactor) { - list.resize(list.size) - } -} diff --git a/vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go b/vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go deleted file mode 100644 index 8bd60b0a..00000000 --- a/vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package arraylist - -import "github.com/emirpasic/gods/containers" - -// Assert Enumerable implementation -var _ containers.EnumerableWithIndex = (*List)(nil) - -// Each calls the given function once for each element, passing that element's index and value. -func (list *List) Each(f func(index int, value interface{})) { - iterator := list.Iterator() - for iterator.Next() { - f(iterator.Index(), iterator.Value()) - } -} - -// Map invokes the given function once for each element and returns a -// container containing the values returned by the given function. -func (list *List) Map(f func(index int, value interface{}) interface{}) *List { - newList := &List{} - iterator := list.Iterator() - for iterator.Next() { - newList.Add(f(iterator.Index(), iterator.Value())) - } - return newList -} - -// Select returns a new container containing all elements for which the given function returns a true value. -func (list *List) Select(f func(index int, value interface{}) bool) *List { - newList := &List{} - iterator := list.Iterator() - for iterator.Next() { - if f(iterator.Index(), iterator.Value()) { - newList.Add(iterator.Value()) - } - } - return newList -} - -// Any passes each element of the collection to the given function and -// returns true if the function ever returns true for any element. -func (list *List) Any(f func(index int, value interface{}) bool) bool { - iterator := list.Iterator() - for iterator.Next() { - if f(iterator.Index(), iterator.Value()) { - return true - } - } - return false -} - -// All passes each element of the collection to the given function and -// returns true if the function returns true for all elements. -func (list *List) All(f func(index int, value interface{}) bool) bool { - iterator := list.Iterator() - for iterator.Next() { - if !f(iterator.Index(), iterator.Value()) { - return false - } - } - return true -} - -// Find passes each element of the container to the given function and returns -// the first (index,value) for which the function is true or -1,nil otherwise -// if no element matches the criteria. -func (list *List) Find(f func(index int, value interface{}) bool) (int, interface{}) { - iterator := list.Iterator() - for iterator.Next() { - if f(iterator.Index(), iterator.Value()) { - return iterator.Index(), iterator.Value() - } - } - return -1, nil -} diff --git a/vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go b/vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go deleted file mode 100644 index f9efe20c..00000000 --- a/vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package arraylist - -import "github.com/emirpasic/gods/containers" - -// Assert Iterator implementation -var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil) - -// Iterator holding the iterator's state -type Iterator struct { - list *List - index int -} - -// Iterator returns a stateful iterator whose values can be fetched by an index. -func (list *List) Iterator() Iterator { - return Iterator{list: list, index: -1} -} - -// Next moves the iterator to the next element and returns true if there was a next element in the container. -// If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). -// If Next() was called for the first time, then it will point the iterator to the first element if it exists. -// Modifies the state of the iterator. -func (iterator *Iterator) Next() bool { - if iterator.index < iterator.list.size { - iterator.index++ - } - return iterator.list.withinRange(iterator.index) -} - -// Prev moves the iterator to the previous element and returns true if there was a previous element in the container. -// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) Prev() bool { - if iterator.index >= 0 { - iterator.index-- - } - return iterator.list.withinRange(iterator.index) -} - -// Value returns the current element's value. -// Does not modify the state of the iterator. -func (iterator *Iterator) Value() interface{} { - return iterator.list.elements[iterator.index] -} - -// Index returns the current element's index. -// Does not modify the state of the iterator. -func (iterator *Iterator) Index() int { - return iterator.index -} - -// Begin resets the iterator to its initial state (one-before-first) -// Call Next() to fetch the first element if any. -func (iterator *Iterator) Begin() { - iterator.index = -1 -} - -// End moves the iterator past the last element (one-past-the-end). -// Call Prev() to fetch the last element if any. -func (iterator *Iterator) End() { - iterator.index = iterator.list.size -} - -// First moves the iterator to the first element and returns true if there was a first element in the container. -// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) First() bool { - iterator.Begin() - return iterator.Next() -} - -// Last moves the iterator to the last element and returns true if there was a last element in the container. -// If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) Last() bool { - iterator.End() - return iterator.Prev() -} - -// NextTo moves the iterator to the next element from current position that satisfies the condition given by the -// passed function, and returns true if there was a next element in the container. -// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool { - for iterator.Next() { - index, value := iterator.Index(), iterator.Value() - if f(index, value) { - return true - } - } - return false -} - -// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the -// passed function, and returns true if there was a next element in the container. -// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool { - for iterator.Prev() { - index, value := iterator.Index(), iterator.Value() - if f(index, value) { - return true - } - } - return false -} diff --git a/vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go b/vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go deleted file mode 100644 index 5e86fe96..00000000 --- a/vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package arraylist - -import ( - "encoding/json" - "github.com/emirpasic/gods/containers" -) - -// Assert Serialization implementation -var _ containers.JSONSerializer = (*List)(nil) -var _ containers.JSONDeserializer = (*List)(nil) - -// ToJSON outputs the JSON representation of list's elements. -func (list *List) ToJSON() ([]byte, error) { - return json.Marshal(list.elements[:list.size]) -} - -// FromJSON populates list's elements from the input JSON representation. -func (list *List) FromJSON(data []byte) error { - err := json.Unmarshal(data, &list.elements) - if err == nil { - list.size = len(list.elements) - } - return err -} - -// UnmarshalJSON @implements json.Unmarshaler -func (list *List) UnmarshalJSON(bytes []byte) error { - return list.FromJSON(bytes) -} - -// MarshalJSON @implements json.Marshaler -func (list *List) MarshalJSON() ([]byte, error) { - return list.ToJSON() -} diff --git a/vendor/github.com/emirpasic/gods/lists/lists.go b/vendor/github.com/emirpasic/gods/lists/lists.go deleted file mode 100644 index 55bd619e..00000000 --- a/vendor/github.com/emirpasic/gods/lists/lists.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package lists provides an abstract List interface. -// -// In computer science, a list or sequence is an abstract data type that represents an ordered sequence of values, where the same value may occur more than once. An instance of a list is a computer representation of the mathematical concept of a finite sequence; the (potentially) infinite analog of a list is a stream. Lists are a basic example of containers, as they contain other values. If the same value occurs multiple times, each occurrence is considered a distinct item. -// -// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 -package lists - -import ( - "github.com/emirpasic/gods/containers" - "github.com/emirpasic/gods/utils" -) - -// List interface that all lists implement -type List interface { - Get(index int) (interface{}, bool) - Remove(index int) - Add(values ...interface{}) - Contains(values ...interface{}) bool - Sort(comparator utils.Comparator) - Swap(index1, index2 int) - Insert(index int, values ...interface{}) - Set(index int, value interface{}) - - containers.Container - // Empty() bool - // Size() int - // Clear() - // Values() []interface{} - // String() string -} diff --git a/vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap.go b/vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap.go deleted file mode 100644 index e658f257..00000000 --- a/vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package binaryheap implements a binary heap backed by array list. -// -// Comparator defines this heap as either min or max heap. -// -// Structure is not thread safe. -// -// References: http://en.wikipedia.org/wiki/Binary_heap -package binaryheap - -import ( - "fmt" - "github.com/emirpasic/gods/lists/arraylist" - "github.com/emirpasic/gods/trees" - "github.com/emirpasic/gods/utils" - "strings" -) - -// Assert Tree implementation -var _ trees.Tree = (*Heap)(nil) - -// Heap holds elements in an array-list -type Heap struct { - list *arraylist.List - Comparator utils.Comparator -} - -// NewWith instantiates a new empty heap tree with the custom comparator. -func NewWith(comparator utils.Comparator) *Heap { - return &Heap{list: arraylist.New(), Comparator: comparator} -} - -// NewWithIntComparator instantiates a new empty heap with the IntComparator, i.e. elements are of type int. -func NewWithIntComparator() *Heap { - return &Heap{list: arraylist.New(), Comparator: utils.IntComparator} -} - -// NewWithStringComparator instantiates a new empty heap with the StringComparator, i.e. elements are of type string. -func NewWithStringComparator() *Heap { - return &Heap{list: arraylist.New(), Comparator: utils.StringComparator} -} - -// Push adds a value onto the heap and bubbles it up accordingly. -func (heap *Heap) Push(values ...interface{}) { - if len(values) == 1 { - heap.list.Add(values[0]) - heap.bubbleUp() - } else { - // Reference: https://en.wikipedia.org/wiki/Binary_heap#Building_a_heap - for _, value := range values { - heap.list.Add(value) - } - size := heap.list.Size()/2 + 1 - for i := size; i >= 0; i-- { - heap.bubbleDownIndex(i) - } - } -} - -// Pop removes top element on heap and returns it, or nil if heap is empty. -// Second return parameter is true, unless the heap was empty and there was nothing to pop. -func (heap *Heap) Pop() (value interface{}, ok bool) { - value, ok = heap.list.Get(0) - if !ok { - return - } - lastIndex := heap.list.Size() - 1 - heap.list.Swap(0, lastIndex) - heap.list.Remove(lastIndex) - heap.bubbleDown() - return -} - -// Peek returns top element on the heap without removing it, or nil if heap is empty. -// Second return parameter is true, unless the heap was empty and there was nothing to peek. -func (heap *Heap) Peek() (value interface{}, ok bool) { - return heap.list.Get(0) -} - -// Empty returns true if heap does not contain any elements. -func (heap *Heap) Empty() bool { - return heap.list.Empty() -} - -// Size returns number of elements within the heap. -func (heap *Heap) Size() int { - return heap.list.Size() -} - -// Clear removes all elements from the heap. -func (heap *Heap) Clear() { - heap.list.Clear() -} - -// Values returns all elements in the heap. -func (heap *Heap) Values() []interface{} { - values := make([]interface{}, heap.list.Size(), heap.list.Size()) - for it := heap.Iterator(); it.Next(); { - values[it.Index()] = it.Value() - } - return values -} - -// String returns a string representation of container -func (heap *Heap) String() string { - str := "BinaryHeap\n" - values := []string{} - for it := heap.Iterator(); it.Next(); { - values = append(values, fmt.Sprintf("%v", it.Value())) - } - str += strings.Join(values, ", ") - return str -} - -// Performs the "bubble down" operation. This is to place the element that is at the root -// of the heap in its correct place so that the heap maintains the min/max-heap order property. -func (heap *Heap) bubbleDown() { - heap.bubbleDownIndex(0) -} - -// Performs the "bubble down" operation. This is to place the element that is at the index -// of the heap in its correct place so that the heap maintains the min/max-heap order property. -func (heap *Heap) bubbleDownIndex(index int) { - size := heap.list.Size() - for leftIndex := index<<1 + 1; leftIndex < size; leftIndex = index<<1 + 1 { - rightIndex := index<<1 + 2 - smallerIndex := leftIndex - leftValue, _ := heap.list.Get(leftIndex) - rightValue, _ := heap.list.Get(rightIndex) - if rightIndex < size && heap.Comparator(leftValue, rightValue) > 0 { - smallerIndex = rightIndex - } - indexValue, _ := heap.list.Get(index) - smallerValue, _ := heap.list.Get(smallerIndex) - if heap.Comparator(indexValue, smallerValue) > 0 { - heap.list.Swap(index, smallerIndex) - } else { - break - } - index = smallerIndex - } -} - -// Performs the "bubble up" operation. This is to place a newly inserted -// element (i.e. last element in the list) in its correct place so that -// the heap maintains the min/max-heap order property. -func (heap *Heap) bubbleUp() { - index := heap.list.Size() - 1 - for parentIndex := (index - 1) >> 1; index > 0; parentIndex = (index - 1) >> 1 { - indexValue, _ := heap.list.Get(index) - parentValue, _ := heap.list.Get(parentIndex) - if heap.Comparator(parentValue, indexValue) <= 0 { - break - } - heap.list.Swap(index, parentIndex) - index = parentIndex - } -} - -// Check that the index is within bounds of the list -func (heap *Heap) withinRange(index int) bool { - return index >= 0 && index < heap.list.Size() -} diff --git a/vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go b/vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go deleted file mode 100644 index f2179633..00000000 --- a/vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package binaryheap - -import ( - "github.com/emirpasic/gods/containers" -) - -// Assert Iterator implementation -var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil) - -// Iterator returns a stateful iterator whose values can be fetched by an index. -type Iterator struct { - heap *Heap - index int -} - -// Iterator returns a stateful iterator whose values can be fetched by an index. -func (heap *Heap) Iterator() Iterator { - return Iterator{heap: heap, index: -1} -} - -// Next moves the iterator to the next element and returns true if there was a next element in the container. -// If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). -// If Next() was called for the first time, then it will point the iterator to the first element if it exists. -// Modifies the state of the iterator. -func (iterator *Iterator) Next() bool { - if iterator.index < iterator.heap.Size() { - iterator.index++ - } - return iterator.heap.withinRange(iterator.index) -} - -// Prev moves the iterator to the previous element and returns true if there was a previous element in the container. -// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) Prev() bool { - if iterator.index >= 0 { - iterator.index-- - } - return iterator.heap.withinRange(iterator.index) -} - -// Value returns the current element's value. -// Does not modify the state of the iterator. -func (iterator *Iterator) Value() interface{} { - start, end := evaluateRange(iterator.index) - if end > iterator.heap.Size() { - end = iterator.heap.Size() - } - tmpHeap := NewWith(iterator.heap.Comparator) - for n := start; n < end; n++ { - value, _ := iterator.heap.list.Get(n) - tmpHeap.Push(value) - } - for n := 0; n < iterator.index-start; n++ { - tmpHeap.Pop() - } - value, _ := tmpHeap.Pop() - return value -} - -// Index returns the current element's index. -// Does not modify the state of the iterator. -func (iterator *Iterator) Index() int { - return iterator.index -} - -// Begin resets the iterator to its initial state (one-before-first) -// Call Next() to fetch the first element if any. -func (iterator *Iterator) Begin() { - iterator.index = -1 -} - -// End moves the iterator past the last element (one-past-the-end). -// Call Prev() to fetch the last element if any. -func (iterator *Iterator) End() { - iterator.index = iterator.heap.Size() -} - -// First moves the iterator to the first element and returns true if there was a first element in the container. -// If First() returns true, then first element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) First() bool { - iterator.Begin() - return iterator.Next() -} - -// Last moves the iterator to the last element and returns true if there was a last element in the container. -// If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) Last() bool { - iterator.End() - return iterator.Prev() -} - -// NextTo moves the iterator to the next element from current position that satisfies the condition given by the -// passed function, and returns true if there was a next element in the container. -// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool { - for iterator.Next() { - index, value := iterator.Index(), iterator.Value() - if f(index, value) { - return true - } - } - return false -} - -// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the -// passed function, and returns true if there was a next element in the container. -// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value(). -// Modifies the state of the iterator. -func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool { - for iterator.Prev() { - index, value := iterator.Index(), iterator.Value() - if f(index, value) { - return true - } - } - return false -} - -// numOfBits counts the number of bits of an int -func numOfBits(n int) uint { - var count uint - for n != 0 { - count++ - n >>= 1 - } - return count -} - -// evaluateRange evaluates the index range [start,end) of same level nodes in the heap as the index -func evaluateRange(index int) (start int, end int) { - bits := numOfBits(index+1) - 1 - start = 1< b -type Comparator func(a, b interface{}) int - -// StringComparator provides a fast comparison on strings -func StringComparator(a, b interface{}) int { - s1 := a.(string) - s2 := b.(string) - min := len(s2) - if len(s1) < len(s2) { - min = len(s1) - } - diff := 0 - for i := 0; i < min && diff == 0; i++ { - diff = int(s1[i]) - int(s2[i]) - } - if diff == 0 { - diff = len(s1) - len(s2) - } - if diff < 0 { - return -1 - } - if diff > 0 { - return 1 - } - return 0 -} - -// IntComparator provides a basic comparison on int -func IntComparator(a, b interface{}) int { - aAsserted := a.(int) - bAsserted := b.(int) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// Int8Comparator provides a basic comparison on int8 -func Int8Comparator(a, b interface{}) int { - aAsserted := a.(int8) - bAsserted := b.(int8) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// Int16Comparator provides a basic comparison on int16 -func Int16Comparator(a, b interface{}) int { - aAsserted := a.(int16) - bAsserted := b.(int16) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// Int32Comparator provides a basic comparison on int32 -func Int32Comparator(a, b interface{}) int { - aAsserted := a.(int32) - bAsserted := b.(int32) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// Int64Comparator provides a basic comparison on int64 -func Int64Comparator(a, b interface{}) int { - aAsserted := a.(int64) - bAsserted := b.(int64) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// UIntComparator provides a basic comparison on uint -func UIntComparator(a, b interface{}) int { - aAsserted := a.(uint) - bAsserted := b.(uint) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// UInt8Comparator provides a basic comparison on uint8 -func UInt8Comparator(a, b interface{}) int { - aAsserted := a.(uint8) - bAsserted := b.(uint8) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// UInt16Comparator provides a basic comparison on uint16 -func UInt16Comparator(a, b interface{}) int { - aAsserted := a.(uint16) - bAsserted := b.(uint16) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// UInt32Comparator provides a basic comparison on uint32 -func UInt32Comparator(a, b interface{}) int { - aAsserted := a.(uint32) - bAsserted := b.(uint32) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// UInt64Comparator provides a basic comparison on uint64 -func UInt64Comparator(a, b interface{}) int { - aAsserted := a.(uint64) - bAsserted := b.(uint64) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// Float32Comparator provides a basic comparison on float32 -func Float32Comparator(a, b interface{}) int { - aAsserted := a.(float32) - bAsserted := b.(float32) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// Float64Comparator provides a basic comparison on float64 -func Float64Comparator(a, b interface{}) int { - aAsserted := a.(float64) - bAsserted := b.(float64) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// ByteComparator provides a basic comparison on byte -func ByteComparator(a, b interface{}) int { - aAsserted := a.(byte) - bAsserted := b.(byte) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// RuneComparator provides a basic comparison on rune -func RuneComparator(a, b interface{}) int { - aAsserted := a.(rune) - bAsserted := b.(rune) - switch { - case aAsserted > bAsserted: - return 1 - case aAsserted < bAsserted: - return -1 - default: - return 0 - } -} - -// TimeComparator provides a basic comparison on time.Time -func TimeComparator(a, b interface{}) int { - aAsserted := a.(time.Time) - bAsserted := b.(time.Time) - - switch { - case aAsserted.After(bAsserted): - return 1 - case aAsserted.Before(bAsserted): - return -1 - default: - return 0 - } -} diff --git a/vendor/github.com/emirpasic/gods/utils/sort.go b/vendor/github.com/emirpasic/gods/utils/sort.go deleted file mode 100644 index 79ced1f5..00000000 --- a/vendor/github.com/emirpasic/gods/utils/sort.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package utils - -import "sort" - -// Sort sorts values (in-place) with respect to the given comparator. -// -// Uses Go's sort (hybrid of quicksort for large and then insertion sort for smaller slices). -func Sort(values []interface{}, comparator Comparator) { - sort.Sort(sortable{values, comparator}) -} - -type sortable struct { - values []interface{} - comparator Comparator -} - -func (s sortable) Len() int { - return len(s.values) -} -func (s sortable) Swap(i, j int) { - s.values[i], s.values[j] = s.values[j], s.values[i] -} -func (s sortable) Less(i, j int) bool { - return s.comparator(s.values[i], s.values[j]) < 0 -} diff --git a/vendor/github.com/emirpasic/gods/utils/utils.go b/vendor/github.com/emirpasic/gods/utils/utils.go deleted file mode 100644 index 262c6257..00000000 --- a/vendor/github.com/emirpasic/gods/utils/utils.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2015, Emir Pasic. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package utils provides common utility functions. -// -// Provided functionalities: -// - sorting -// - comparators -package utils - -import ( - "fmt" - "strconv" -) - -// ToString converts a value to string. -func ToString(value interface{}) string { - switch value := value.(type) { - case string: - return value - case int8: - return strconv.FormatInt(int64(value), 10) - case int16: - return strconv.FormatInt(int64(value), 10) - case int32: - return strconv.FormatInt(int64(value), 10) - case int64: - return strconv.FormatInt(value, 10) - case uint8: - return strconv.FormatUint(uint64(value), 10) - case uint16: - return strconv.FormatUint(uint64(value), 10) - case uint32: - return strconv.FormatUint(uint64(value), 10) - case uint64: - return strconv.FormatUint(value, 10) - case float32: - return strconv.FormatFloat(float64(value), 'g', -1, 64) - case float64: - return strconv.FormatFloat(value, 'g', -1, 64) - case bool: - return strconv.FormatBool(value) - default: - return fmt.Sprintf("%+v", value) - } -} diff --git a/vendor/github.com/erikgeiser/coninput/.gitignore b/vendor/github.com/erikgeiser/coninput/.gitignore deleted file mode 100644 index 66fd13c9..00000000 --- a/vendor/github.com/erikgeiser/coninput/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ diff --git a/vendor/github.com/erikgeiser/coninput/.golangci.yml b/vendor/github.com/erikgeiser/coninput/.golangci.yml deleted file mode 100644 index d3ed7103..00000000 --- a/vendor/github.com/erikgeiser/coninput/.golangci.yml +++ /dev/null @@ -1,24 +0,0 @@ -linters: - enable-all: true - disable: - - golint - - interfacer - - scopelint - - maligned - - rowserrcheck - - funlen - - depguard - - goerr113 - - exhaustivestruct - - testpackage - - gochecknoglobals - - wrapcheck - - forbidigo - - ifshort - - cyclop - - gomoddirectives -linters-settings: - exhaustive: - default-signifies-exhaustive: true -issues: - exclude-use-default: false diff --git a/vendor/github.com/erikgeiser/coninput/LICENSE b/vendor/github.com/erikgeiser/coninput/LICENSE deleted file mode 100644 index 83c24408..00000000 --- a/vendor/github.com/erikgeiser/coninput/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 Erik G. - -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/erikgeiser/coninput/README.md b/vendor/github.com/erikgeiser/coninput/README.md deleted file mode 100644 index 22619d13..00000000 --- a/vendor/github.com/erikgeiser/coninput/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# coninput -Go library for input handling using Windows Console API diff --git a/vendor/github.com/erikgeiser/coninput/keycodes.go b/vendor/github.com/erikgeiser/coninput/keycodes.go deleted file mode 100644 index 902ee1b7..00000000 --- a/vendor/github.com/erikgeiser/coninput/keycodes.go +++ /dev/null @@ -1,205 +0,0 @@ -package coninput - -// VirtualKeyCode holds a virtual key code (see -// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes). -type VirtualKeyCode uint16 - -const ( - VK_LBUTTON VirtualKeyCode = 0x01 - VK_RBUTTON VirtualKeyCode = 0x02 - VK_CANCEL VirtualKeyCode = 0x03 - VK_MBUTTON VirtualKeyCode = 0x04 - VK_XBUTTON1 VirtualKeyCode = 0x05 - VK_XBUTTON2 VirtualKeyCode = 0x06 - VK_BACK VirtualKeyCode = 0x08 - VK_TAB VirtualKeyCode = 0x09 - VK_CLEAR VirtualKeyCode = 0x0C - VK_RETURN VirtualKeyCode = 0x0D - VK_SHIFT VirtualKeyCode = 0x10 - VK_CONTROL VirtualKeyCode = 0x11 - VK_MENU VirtualKeyCode = 0x12 - VK_PAUSE VirtualKeyCode = 0x13 - VK_CAPITAL VirtualKeyCode = 0x14 - VK_KANA VirtualKeyCode = 0x15 - VK_HANGEUL VirtualKeyCode = 0x15 - VK_HANGUL VirtualKeyCode = 0x15 - VK_IME_ON VirtualKeyCode = 0x16 - VK_JUNJA VirtualKeyCode = 0x17 - VK_FINAL VirtualKeyCode = 0x18 - VK_HANJA VirtualKeyCode = 0x19 - VK_KANJI VirtualKeyCode = 0x19 - VK_IME_OFF VirtualKeyCode = 0x1A - VK_ESCAPE VirtualKeyCode = 0x1B - VK_CONVERT VirtualKeyCode = 0x1C - VK_NONCONVERT VirtualKeyCode = 0x1D - VK_ACCEPT VirtualKeyCode = 0x1E - VK_MODECHANGE VirtualKeyCode = 0x1F - VK_SPACE VirtualKeyCode = 0x20 - VK_PRIOR VirtualKeyCode = 0x21 - VK_NEXT VirtualKeyCode = 0x22 - VK_END VirtualKeyCode = 0x23 - VK_HOME VirtualKeyCode = 0x24 - VK_LEFT VirtualKeyCode = 0x25 - VK_UP VirtualKeyCode = 0x26 - VK_RIGHT VirtualKeyCode = 0x27 - VK_DOWN VirtualKeyCode = 0x28 - VK_SELECT VirtualKeyCode = 0x29 - VK_PRINT VirtualKeyCode = 0x2A - VK_EXECUTE VirtualKeyCode = 0x2B - VK_SNAPSHOT VirtualKeyCode = 0x2C - VK_INSERT VirtualKeyCode = 0x2D - VK_DELETE VirtualKeyCode = 0x2E - VK_HELP VirtualKeyCode = 0x2F - VK_0 VirtualKeyCode = 0x30 - VK_1 VirtualKeyCode = 0x31 - VK_2 VirtualKeyCode = 0x32 - VK_3 VirtualKeyCode = 0x33 - VK_4 VirtualKeyCode = 0x34 - VK_5 VirtualKeyCode = 0x35 - VK_6 VirtualKeyCode = 0x36 - VK_7 VirtualKeyCode = 0x37 - VK_8 VirtualKeyCode = 0x38 - VK_9 VirtualKeyCode = 0x39 - VK_A VirtualKeyCode = 0x41 - VK_B VirtualKeyCode = 0x42 - VK_C VirtualKeyCode = 0x43 - VK_D VirtualKeyCode = 0x44 - VK_E VirtualKeyCode = 0x45 - VK_F VirtualKeyCode = 0x46 - VK_G VirtualKeyCode = 0x47 - VK_H VirtualKeyCode = 0x48 - VK_I VirtualKeyCode = 0x49 - VK_J VirtualKeyCode = 0x4A - VK_K VirtualKeyCode = 0x4B - VK_L VirtualKeyCode = 0x4C - VK_M VirtualKeyCode = 0x4D - VK_N VirtualKeyCode = 0x4E - VK_O VirtualKeyCode = 0x4F - VK_P VirtualKeyCode = 0x50 - VK_Q VirtualKeyCode = 0x51 - VK_R VirtualKeyCode = 0x52 - VK_S VirtualKeyCode = 0x53 - VK_T VirtualKeyCode = 0x54 - VK_U VirtualKeyCode = 0x55 - VK_V VirtualKeyCode = 0x56 - VK_W VirtualKeyCode = 0x57 - VK_X VirtualKeyCode = 0x58 - VK_Y VirtualKeyCode = 0x59 - VK_Z VirtualKeyCode = 0x5A - VK_LWIN VirtualKeyCode = 0x5B - VK_RWIN VirtualKeyCode = 0x5C - VK_APPS VirtualKeyCode = 0x5D - VK_SLEEP VirtualKeyCode = 0x5F - VK_NUMPAD0 VirtualKeyCode = 0x60 - VK_NUMPAD1 VirtualKeyCode = 0x61 - VK_NUMPAD2 VirtualKeyCode = 0x62 - VK_NUMPAD3 VirtualKeyCode = 0x63 - VK_NUMPAD4 VirtualKeyCode = 0x64 - VK_NUMPAD5 VirtualKeyCode = 0x65 - VK_NUMPAD6 VirtualKeyCode = 0x66 - VK_NUMPAD7 VirtualKeyCode = 0x67 - VK_NUMPAD8 VirtualKeyCode = 0x68 - VK_NUMPAD9 VirtualKeyCode = 0x69 - VK_MULTIPLY VirtualKeyCode = 0x6A - VK_ADD VirtualKeyCode = 0x6B - VK_SEPARATOR VirtualKeyCode = 0x6C - VK_SUBTRACT VirtualKeyCode = 0x6D - VK_DECIMAL VirtualKeyCode = 0x6E - VK_DIVIDE VirtualKeyCode = 0x6F - VK_F1 VirtualKeyCode = 0x70 - VK_F2 VirtualKeyCode = 0x71 - VK_F3 VirtualKeyCode = 0x72 - VK_F4 VirtualKeyCode = 0x73 - VK_F5 VirtualKeyCode = 0x74 - VK_F6 VirtualKeyCode = 0x75 - VK_F7 VirtualKeyCode = 0x76 - VK_F8 VirtualKeyCode = 0x77 - VK_F9 VirtualKeyCode = 0x78 - VK_F10 VirtualKeyCode = 0x79 - VK_F11 VirtualKeyCode = 0x7A - VK_F12 VirtualKeyCode = 0x7B - VK_F13 VirtualKeyCode = 0x7C - VK_F14 VirtualKeyCode = 0x7D - VK_F15 VirtualKeyCode = 0x7E - VK_F16 VirtualKeyCode = 0x7F - VK_F17 VirtualKeyCode = 0x80 - VK_F18 VirtualKeyCode = 0x81 - VK_F19 VirtualKeyCode = 0x82 - VK_F20 VirtualKeyCode = 0x83 - VK_F21 VirtualKeyCode = 0x84 - VK_F22 VirtualKeyCode = 0x85 - VK_F23 VirtualKeyCode = 0x86 - VK_F24 VirtualKeyCode = 0x87 - VK_NUMLOCK VirtualKeyCode = 0x90 - VK_SCROLL VirtualKeyCode = 0x91 - VK_OEM_NEC_EQUAL VirtualKeyCode = 0x92 - VK_OEM_FJ_JISHO VirtualKeyCode = 0x92 - VK_OEM_FJ_MASSHOU VirtualKeyCode = 0x93 - VK_OEM_FJ_TOUROKU VirtualKeyCode = 0x94 - VK_OEM_FJ_LOYA VirtualKeyCode = 0x95 - VK_OEM_FJ_ROYA VirtualKeyCode = 0x96 - VK_LSHIFT VirtualKeyCode = 0xA0 - VK_RSHIFT VirtualKeyCode = 0xA1 - VK_LCONTROL VirtualKeyCode = 0xA2 - VK_RCONTROL VirtualKeyCode = 0xA3 - VK_LMENU VirtualKeyCode = 0xA4 - VK_RMENU VirtualKeyCode = 0xA5 - VK_BROWSER_BACK VirtualKeyCode = 0xA6 - VK_BROWSER_FORWARD VirtualKeyCode = 0xA7 - VK_BROWSER_REFRESH VirtualKeyCode = 0xA8 - VK_BROWSER_STOP VirtualKeyCode = 0xA9 - VK_BROWSER_SEARCH VirtualKeyCode = 0xAA - VK_BROWSER_FAVORITES VirtualKeyCode = 0xAB - VK_BROWSER_HOME VirtualKeyCode = 0xAC - VK_VOLUME_MUTE VirtualKeyCode = 0xAD - VK_VOLUME_DOWN VirtualKeyCode = 0xAE - VK_VOLUME_UP VirtualKeyCode = 0xAF - VK_MEDIA_NEXT_TRACK VirtualKeyCode = 0xB0 - VK_MEDIA_PREV_TRACK VirtualKeyCode = 0xB1 - VK_MEDIA_STOP VirtualKeyCode = 0xB2 - VK_MEDIA_PLAY_PAUSE VirtualKeyCode = 0xB3 - VK_LAUNCH_MAIL VirtualKeyCode = 0xB4 - VK_LAUNCH_MEDIA_SELECT VirtualKeyCode = 0xB5 - VK_LAUNCH_APP1 VirtualKeyCode = 0xB6 - VK_LAUNCH_APP2 VirtualKeyCode = 0xB7 - VK_OEM_1 VirtualKeyCode = 0xBA - VK_OEM_PLUS VirtualKeyCode = 0xBB - VK_OEM_COMMA VirtualKeyCode = 0xBC - VK_OEM_MINUS VirtualKeyCode = 0xBD - VK_OEM_PERIOD VirtualKeyCode = 0xBE - VK_OEM_2 VirtualKeyCode = 0xBF - VK_OEM_3 VirtualKeyCode = 0xC0 - VK_OEM_4 VirtualKeyCode = 0xDB - VK_OEM_5 VirtualKeyCode = 0xDC - VK_OEM_6 VirtualKeyCode = 0xDD - VK_OEM_7 VirtualKeyCode = 0xDE - VK_OEM_8 VirtualKeyCode = 0xDF - VK_OEM_AX VirtualKeyCode = 0xE1 - VK_OEM_102 VirtualKeyCode = 0xE2 - VK_ICO_HELP VirtualKeyCode = 0xE3 - VK_ICO_00 VirtualKeyCode = 0xE4 - VK_PROCESSKEY VirtualKeyCode = 0xE5 - VK_ICO_CLEAR VirtualKeyCode = 0xE6 - VK_OEM_RESET VirtualKeyCode = 0xE9 - VK_OEM_JUMP VirtualKeyCode = 0xEA - VK_OEM_PA1 VirtualKeyCode = 0xEB - VK_OEM_PA2 VirtualKeyCode = 0xEC - VK_OEM_PA3 VirtualKeyCode = 0xED - VK_OEM_WSCTRL VirtualKeyCode = 0xEE - VK_OEM_CUSEL VirtualKeyCode = 0xEF - VK_OEM_ATTN VirtualKeyCode = 0xF0 - VK_OEM_FINISH VirtualKeyCode = 0xF1 - VK_OEM_COPY VirtualKeyCode = 0xF2 - VK_OEM_AUTO VirtualKeyCode = 0xF3 - VK_OEM_ENLW VirtualKeyCode = 0xF4 - VK_OEM_BACKTAB VirtualKeyCode = 0xF5 - VK_ATTN VirtualKeyCode = 0xF6 - VK_CRSEL VirtualKeyCode = 0xF7 - VK_EXSEL VirtualKeyCode = 0xF8 - VK_EREOF VirtualKeyCode = 0xF9 - VK_PLAY VirtualKeyCode = 0xFA - VK_ZOOM VirtualKeyCode = 0xFB - VK_NONAME VirtualKeyCode = 0xFC - VK_PA1 VirtualKeyCode = 0xFD - VK_OEM_CLEAR VirtualKeyCode = 0xFE -) diff --git a/vendor/github.com/erikgeiser/coninput/mode.go b/vendor/github.com/erikgeiser/coninput/mode.go deleted file mode 100644 index e6d8bf44..00000000 --- a/vendor/github.com/erikgeiser/coninput/mode.go +++ /dev/null @@ -1,82 +0,0 @@ -//go:build windows -// +build windows - -package coninput - -import ( - "strings" - - "golang.org/x/sys/windows" -) - -// AddInputModes returns the given mode with one or more additional modes enabled. -func AddInputModes(mode uint32, enableModes ...uint32) uint32 { - for _, enableMode := range enableModes { - mode |= enableMode - } - - return mode -} - -// RemoveInputModes returns the given mode with one or more additional modes disabled. -func RemoveInputModes(mode uint32, disableModes ...uint32) uint32 { - for _, disableMode := range disableModes { - mode &^= disableMode - } - - return mode -} - -// ToggleInputModes returns the given mode with one or more additional modes toggeled. -func ToggleInputModes(mode uint32, toggleModes ...uint32) uint32 { - for _, toggeMode := range toggleModes { - mode ^= toggeMode - } - - return mode -} - -var inputModes = []struct { - mode uint32 - name string -}{ - {mode: windows.ENABLE_ECHO_INPUT, name: "ENABLE_ECHO_INPUT"}, - {mode: windows.ENABLE_INSERT_MODE, name: "ENABLE_INSERT_MODE"}, - {mode: windows.ENABLE_LINE_INPUT, name: "ENABLE_LINE_INPUT"}, - {mode: windows.ENABLE_MOUSE_INPUT, name: "ENABLE_MOUSE_INPUT"}, - {mode: windows.ENABLE_PROCESSED_INPUT, name: "ENABLE_PROCESSED_INPUT"}, - {mode: windows.ENABLE_QUICK_EDIT_MODE, name: "ENABLE_QUICK_EDIT_MODE"}, - {mode: windows.ENABLE_WINDOW_INPUT, name: "ENABLE_WINDOW_INPUT"}, - {mode: windows.ENABLE_VIRTUAL_TERMINAL_INPUT, name: "ENABLE_VIRTUAL_TERMINAL_INPUT"}, -} - -// ListInputMode returnes the isolated enabled input modes as a list. -func ListInputModes(mode uint32) []uint32 { - modes := []uint32{} - - for _, inputMode := range inputModes { - if mode&inputMode.mode > 0 { - modes = append(modes, inputMode.mode) - } - } - - return modes -} - -// ListInputMode returnes the isolated enabled input mode names as a list. -func ListInputModeNames(mode uint32) []string { - modes := []string{} - - for _, inputMode := range inputModes { - if mode&inputMode.mode > 0 { - modes = append(modes, inputMode.name) - } - } - - return modes -} - -// DescribeInputMode returns a string containing the names of each enabled input mode. -func DescribeInputMode(mode uint32) string { - return strings.Join(ListInputModeNames(mode), "|") -} diff --git a/vendor/github.com/erikgeiser/coninput/read.go b/vendor/github.com/erikgeiser/coninput/read.go deleted file mode 100644 index b2dd82f1..00000000 --- a/vendor/github.com/erikgeiser/coninput/read.go +++ /dev/null @@ -1,154 +0,0 @@ -//go:build windows -// +build windows - -package coninput - -import ( - "fmt" - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -var ( - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - procReadConsoleInputW = modkernel32.NewProc("ReadConsoleInputW") - procPeekConsoleInputW = modkernel32.NewProc("PeekConsoleInputW") - procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents") - procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer") -) - -// NewStdinHandle is a shortcut for windows.GetStdHandle(windows.STD_INPUT_HANDLE). -func NewStdinHandle() (windows.Handle, error) { - return windows.GetStdHandle(windows.STD_INPUT_HANDLE) -} - -// WinReadConsoleInput is a thin wrapper around the Windows console API function -// ReadConsoleInput (see -// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). In most -// cases it is more practical to either use ReadConsoleInput or -// ReadNConsoleInputs. -func WinReadConsoleInput(consoleInput windows.Handle, buffer *InputRecord, - length uint32, numberOfEventsRead *uint32) error { - r, _, e := syscall.Syscall6(procReadConsoleInputW.Addr(), 4, - uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length), - uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0) - if r == 0 { - return error(e) - } - - return nil -} - -// ReadNConsoleInputs is a wrapper around ReadConsoleInput (see -// https://docs.microsoft.com/en-us/windows/console/readconsoleinput) that -// automates the event buffer allocation in oder to provide io.Reader-like -// sematics. maxEvents must be greater than zero. -func ReadNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) { - if maxEvents == 0 { - return nil, fmt.Errorf("maxEvents cannot be zero") - } - - var inputRecords = make([]InputRecord, maxEvents) - n, err := ReadConsoleInput(console, inputRecords) - - return inputRecords[:n], err -} - -// ReadConsoleInput provides an ideomatic interface to the Windows console API -// function ReadConsoleInput (see -// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). The size -// of inputRecords must be greater than zero. -func ReadConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) { - if len(inputRecords) == 0 { - return 0, fmt.Errorf("size of input record buffer cannot be zero") - } - - var read uint32 - err := WinReadConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read) - - return read, err -} - -// WinPeekConsoleInput is a thin wrapper around the Windows console API function -// PeekConsoleInput (see -// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). In most -// cases it is more practical to either use PeekConsoleInput or -// PeekNConsoleInputs. -func WinPeekConsoleInput(consoleInput windows.Handle, buffer *InputRecord, - length uint32, numberOfEventsRead *uint32) error { - r, _, e := syscall.Syscall6(procPeekConsoleInputW.Addr(), 4, - uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length), - uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0) - if r == 0 { - return error(e) - } - - return nil - -} - -// PeekNConsoleInputs is a wrapper around PeekConsoleInput (see -// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput) that -// automates the event buffer allocation in oder to provide io.Reader-like -// sematics. maxEvents must be greater than zero. -func PeekNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) { - if maxEvents == 0 { - return nil, fmt.Errorf("maxEvents cannot be zero") - } - - var inputRecords = make([]InputRecord, maxEvents) - n, err := PeekConsoleInput(console, inputRecords) - - return inputRecords[:n], err -} - -// PeekConsoleInput provides an ideomatic interface to the Windows console API -// function PeekConsoleInput (see -// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). The size -// of inputRecords must be greater than zero. -func PeekConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) { - if len(inputRecords) == 0 { - return 0, fmt.Errorf("size of input record buffer cannot be zero") - } - - var read uint32 - - err := WinPeekConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read) - - return read, err -} - -// WinGetNumberOfConsoleInputEvents provides an ideomatic interface to the -// Windows console API function GetNumberOfConsoleInputEvents (see -// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents). -func WinGetNumberOfConsoleInputEvents(consoleInput windows.Handle, numberOfEvents *uint32) error { - r, _, e := syscall.Syscall6(procGetNumberOfConsoleInputEvents.Addr(), 2, - uintptr(consoleInput), uintptr(unsafe.Pointer(numberOfEvents)), 0, - 0, 0, 0) - if r == 0 { - return error(e) - } - - return nil -} - -// GetNumberOfConsoleInputEvents provides an ideomatic interface to the Windows -// console API function GetNumberOfConsoleInputEvents (see -// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents). -func GetNumberOfConsoleInputEvents(console windows.Handle) (uint32, error) { - var nEvents uint32 - err := WinGetNumberOfConsoleInputEvents(console, &nEvents) - - return nEvents, err -} - -func FlushConsoleInputBuffer(consoleInput windows.Handle) error { - r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1, uintptr(consoleInput), 0, 0) - if r == 0 { - return error(e) - } - - return nil -} diff --git a/vendor/github.com/erikgeiser/coninput/records.go b/vendor/github.com/erikgeiser/coninput/records.go deleted file mode 100644 index cccf7fbf..00000000 --- a/vendor/github.com/erikgeiser/coninput/records.go +++ /dev/null @@ -1,486 +0,0 @@ -package coninput - -import ( - "encoding/binary" - "fmt" - "strconv" - "strings" -) - -const ( - maxEventSize = 16 - wordPaddingBytes = 2 -) - -// EventType denots the type of an event -type EventType uint16 - -// EventUnion is the union data type that contains the data for any event. -type EventUnion [maxEventSize]byte - -// InputRecord corresponds to the INPUT_RECORD structure from the Windows -// console API (see -// https://docs.microsoft.com/en-us/windows/console/input-record-str). -type InputRecord struct { - // EventType specifies the type of event that helt in Event. - EventType EventType - - // Padding of the 16-bit EventType to a whole 32-bit dword. - _ [wordPaddingBytes]byte - - // Event holds the actual event data. Use Unrap to access it as its - // respective event type. - Event EventUnion -} - -// String implements fmt.Stringer for InputRecord. -func (ir InputRecord) String() string { - return ir.Unwrap().String() -} - -// Unwrap parses the event data into an EventRecord of the respective event -// type. The data in the returned EventRecord does not contain any references to -// the passed InputRecord. -func (ir InputRecord) Unwrap() EventRecord { - switch ir.EventType { - case FocusEventType: - return FocusEventRecord{SetFocus: ir.Event[0] > 0} - case KeyEventType: - return KeyEventRecord{ - KeyDown: binary.LittleEndian.Uint32(ir.Event[0:4]) > 0, - RepeatCount: binary.LittleEndian.Uint16(ir.Event[4:6]), - VirtualKeyCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[6:8])), - VirtualScanCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[8:10])), - Char: rune(binary.LittleEndian.Uint16(ir.Event[10:12])), - ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[12:16])), - } - case MouseEventType: - m := MouseEventRecord{ - MousePositon: Coord{ - X: binary.LittleEndian.Uint16(ir.Event[0:2]), - Y: binary.LittleEndian.Uint16(ir.Event[2:4]), - }, - ButtonState: ButtonState(binary.LittleEndian.Uint32(ir.Event[4:8])), - ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[8:12])), - EventFlags: EventFlags(binary.LittleEndian.Uint32(ir.Event[12:16])), - } - - if (m.EventFlags&MOUSE_WHEELED > 0) || (m.EventFlags&MOUSE_HWHEELED > 0) { - if int16(highWord(uint32(m.ButtonState))) > 0 { - m.WheelDirection = 1 - } else { - m.WheelDirection = -1 - } - } - - return m - case WindowBufferSizeEventType: - return WindowBufferSizeEventRecord{ - Size: Coord{ - X: binary.LittleEndian.Uint16(ir.Event[0:2]), - Y: binary.LittleEndian.Uint16(ir.Event[2:4]), - }, - } - case MenuEventType: - return MenuEventRecord{ - CommandID: binary.LittleEndian.Uint32(ir.Event[0:4]), - } - default: - return &UnknownEvent{InputRecord: ir} - } -} - -// EventRecord represents one of the following event types: -// TypeFocusEventRecord, TypeKeyEventRecord, TypeMouseEventRecord, -// TypeWindowBufferSizeEvent, TypeMenuEventRecord and UnknownEvent. -type EventRecord interface { - Type() string - fmt.Stringer -} - -// FocusEventType is the event type for a FocusEventRecord (see -// https://docs.microsoft.com/en-us/windows/console/input-record-str). -const FocusEventType EventType = 0x0010 - -// FocusEventRecord represent the FOCUS_EVENT_RECORD structure from the Windows -// console API (see -// https://docs.microsoft.com/en-us/windows/console/focus-event-record-str). -// These events are used internally by the Windows console API and should be -// ignored. -type FocusEventRecord struct { - // SetFocus is reserved and should not be used. - SetFocus bool -} - -// Ensure that FocusEventRecord satisfies EventRecord interface. -var _ EventRecord = FocusEventRecord{} - -// Type ensures that FocusEventRecord satisfies EventRecord interface. -func (e FocusEventRecord) Type() string { return "FocusEvent" } - -// String ensures that FocusEventRecord satisfies EventRecord and fmt.Stringer -// interfaces. -func (e FocusEventRecord) String() string { return fmt.Sprintf("%s[%v]", e.Type(), e.SetFocus) } - -// KeyEventType is the event type for a KeyEventRecord (see -// https://docs.microsoft.com/en-us/windows/console/input-record-str). -const KeyEventType EventType = 0x0001 - -// KeyEventRecord represent the KEY_EVENT_RECORD structure from the Windows -// console API (see -// https://docs.microsoft.com/en-us/windows/console/key-event-record-str). -type KeyEventRecord struct { - // KeyDown specified whether the key is pressed or released. - KeyDown bool - - // RepeatCount indicates that a key is being held down. For example, when a - // key is held down, five events with RepeatCount equal to 1 may be - // generated, one event with RepeatCount equal to 5, or multiple events - // with RepeatCount greater than or equal to 1. - RepeatCount uint16 - - // VirtualKeyCode identifies the given key in a device-independent manner - // (see - // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes). - VirtualKeyCode VirtualKeyCode - - // VirtualScanCode represents the device-dependent value generated by the - // keyboard hardware. - VirtualScanCode VirtualKeyCode - - // Char is the character that corresponds to the pressed key. Char can be - // zero for some keys. - Char rune - - //ControlKeyState holds the state of the control keys. - ControlKeyState ControlKeyState -} - -// Ensure that KeyEventRecord satisfies EventRecord interface. -var _ EventRecord = KeyEventRecord{} - -// Type ensures that KeyEventRecord satisfies EventRecord interface. -func (e KeyEventRecord) Type() string { return "KeyEvent" } - -// String ensures that KeyEventRecord satisfies EventRecord and fmt.Stringer -// interfaces. -func (e KeyEventRecord) String() string { - infos := []string{} - - repeat := "" - if e.RepeatCount > 1 { - repeat = "x" + strconv.Itoa(int(e.RepeatCount)) - } - - infos = append(infos, fmt.Sprintf("%q%s", e.Char, repeat)) - - direction := "up" - if e.KeyDown { - direction = "down" - } - - infos = append(infos, direction) - - if e.ControlKeyState != NO_CONTROL_KEY { - infos = append(infos, e.ControlKeyState.String()) - } - - infos = append(infos, fmt.Sprintf("KeyCode: %d", e.VirtualKeyCode)) - infos = append(infos, fmt.Sprintf("ScanCode: %d", e.VirtualScanCode)) - - return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", ")) -} - -// MenuEventType is the event type for a MenuEventRecord (see -// https://docs.microsoft.com/en-us/windows/console/input-record-str). -const MenuEventType EventType = 0x0008 - -// MenuEventRecord represent the MENU_EVENT_RECORD structure from the Windows -// console API (see -// https://docs.microsoft.com/en-us/windows/console/menu-event-record-str). -// These events are deprecated by the Windows console API and should be ignored. -type MenuEventRecord struct { - CommandID uint32 -} - -// Ensure that MenuEventRecord satisfies EventRecord interface. -var _ EventRecord = MenuEventRecord{} - -// Type ensures that MenuEventRecord satisfies EventRecord interface. -func (e MenuEventRecord) Type() string { return "MenuEvent" } - -// String ensures that MenuEventRecord satisfies EventRecord and fmt.Stringer -// interfaces. -func (e MenuEventRecord) String() string { return fmt.Sprintf("MenuEvent[%d]", e.CommandID) } - -// MouseEventType is the event type for a MouseEventRecord (see -// https://docs.microsoft.com/en-us/windows/console/input-record-str). -const MouseEventType EventType = 0x0002 - -// MouseEventRecord represent the MOUSE_EVENT_RECORD structure from the Windows -// console API (see -// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). -type MouseEventRecord struct { - // MousePosition contains the location of the cursor, in terms of the - // console screen buffer's character-cell coordinates. - MousePositon Coord - - // ButtonState holds the status of the mouse buttons. - ButtonState ButtonState - - // ControlKeyState holds the state of the control keys. - ControlKeyState ControlKeyState - - // EventFlags specify tge type of mouse event. - EventFlags EventFlags - - // WheelDirection specified the direction in which the mouse wheel is - // spinning when EventFlags contains MOUSE_HWHEELED or MOUSE_WHEELED. When - // the event flags specify MOUSE_WHEELED it is 1 if the wheel rotated - // forward (away from the user) or -1 when it rotates backwards. When - // MOUSE_HWHEELED is specified it is 1 when the wheel rotates right and -1 - // when it rotates left. When the EventFlags do not indicate a mouse wheel - // event it is 0. - WheelDirection int -} - -// Ensure that MouseEventRecord satisfies EventRecord interface. -var _ EventRecord = MouseEventRecord{} - -func (e MouseEventRecord) WheelDirectionName() string { - if e.EventFlags&MOUSE_WHEELED > 0 { - if e.WheelDirection > 0 { - return "Forward" - } - - return "Backward" - } else if e.EventFlags&MOUSE_HWHEELED > 0 { - if e.WheelDirection > 0 { - return "Right" - } - - return "Left" - } - - return "" -} - -// Type ensures that MouseEventRecord satisfies EventRecord interface. -func (e MouseEventRecord) Type() string { return "MouseEvent" } - -// String ensures that MouseEventRecord satisfies EventRecord and fmt.Stringer -// interfaces. -func (e MouseEventRecord) String() string { - infos := []string{e.MousePositon.String()} - - if e.ButtonState&0xFF != 0 { - infos = append(infos, e.ButtonState.String()) - } - - eventDescription := e.EventFlags.String() - - wheelDirection := e.WheelDirectionName() - if wheelDirection != "" { - eventDescription += "(" + wheelDirection + ")" - } - - infos = append(infos, eventDescription) - - if e.ControlKeyState != NO_CONTROL_KEY { - infos = append(infos, e.ControlKeyState.String()) - } - - return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", ")) -} - -// WindowBufferSizeEventType is the event type for a WindowBufferSizeEventRecord -// (see https://docs.microsoft.com/en-us/windows/console/input-record-str). -const WindowBufferSizeEventType EventType = 0x0004 - -// WindowBufferSizeEventRecord represent the WINDOW_BUFFER_SIZE_RECORD structure -// from the Windows console API (see -// https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str). -type WindowBufferSizeEventRecord struct { - // Size contains the size of the console screen buffer, in character cell columns and rows. - Size Coord -} - -// Ensure that WindowBufferSizeEventRecord satisfies EventRecord interface. -var _ EventRecord = WindowBufferSizeEventRecord{} - -// Type ensures that WindowBufferSizeEventRecord satisfies EventRecord interface. -func (e WindowBufferSizeEventRecord) Type() string { return "WindowBufferSizeEvent" } - -// String ensures that WindowBufferSizeEventRecord satisfies EventRecord and fmt.Stringer -// interfaces. -func (e WindowBufferSizeEventRecord) String() string { - return fmt.Sprintf("WindowBufferSizeEvent[%s]", e.Size) -} - -// UnknownEvent is generated when the event type does not match one of the -// following types: TypeFocusEventRecord, TypeKeyEventRecord, -// TypeMouseEventRecord, TypeWindowBufferSizeEvent, TypeMenuEventRecord and -// UnknownEvent. -type UnknownEvent struct { - InputRecord -} - -// Ensure that UnknownEvent satisfies EventRecord interface. -var _ EventRecord = UnknownEvent{} - -// Type ensures that UnknownEvent satisfies EventRecord interface. -func (e UnknownEvent) Type() string { return "UnknownEvent" } - -// String ensures that UnknownEvent satisfies EventRecord and fmt.Stringer -// interfaces. -func (e UnknownEvent) String() string { - return fmt.Sprintf("%s[Type: %d, Data: %v]", e.Type(), e.InputRecord.EventType, e.InputRecord.Event[:]) -} - -// Coord represent the COORD structure from the Windows -// console API (see https://docs.microsoft.com/en-us/windows/console/coord-str). -type Coord struct { - // X is the horizontal coordinate or column value. The units depend on the function call. - X uint16 - // Y is the vertical coordinate or row value. The units depend on the function call. - Y uint16 -} - -// String ensures that Coord satisfies the fmt.Stringer interface. -func (c Coord) String() string { - return fmt.Sprintf("(%d, %d)", c.X, c.Y) -} - -// ButtonState holds the state of the mouse buttons (see -// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). -type ButtonState uint32 - -func (bs ButtonState) Contains(state ButtonState) bool { - return bs&state > 0 -} - -// String ensures that ButtonState satisfies the fmt.Stringer interface. -func (bs ButtonState) String() string { - switch { - case bs&FROM_LEFT_1ST_BUTTON_PRESSED > 0: - return "Left" - case bs&FROM_LEFT_2ND_BUTTON_PRESSED > 0: - return "2" - case bs&FROM_LEFT_3RD_BUTTON_PRESSED > 0: - return "3" - case bs&FROM_LEFT_4TH_BUTTON_PRESSED > 0: - return "4" - case bs&RIGHTMOST_BUTTON_PRESSED > 0: - return "Right" - case bs&0xFF == 0: - return "No Button" - default: - return fmt.Sprintf("Unknown(%d)", bs) - } -} - -func (bs ButtonState) IsReleased() bool { - return bs&0xff > 0 -} - -// Valid values for ButtonState. -const ( - FROM_LEFT_1ST_BUTTON_PRESSED ButtonState = 0x0001 - RIGHTMOST_BUTTON_PRESSED ButtonState = 0x0002 - FROM_LEFT_2ND_BUTTON_PRESSED ButtonState = 0x0004 - FROM_LEFT_3RD_BUTTON_PRESSED ButtonState = 0x0008 - FROM_LEFT_4TH_BUTTON_PRESSED ButtonState = 0x0010 -) - -// ControlKeyState holds the state of the control keys for key and mouse events -// (see https://docs.microsoft.com/en-us/windows/console/key-event-record-str -// and https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). -type ControlKeyState uint32 - -func (cks ControlKeyState) Contains(state ControlKeyState) bool { - return cks&state > 0 -} - -// Valid values for ControlKeyState. -const ( - CAPSLOCK_ON ControlKeyState = 0x0080 - ENHANCED_KEY ControlKeyState = 0x0100 - LEFT_ALT_PRESSED ControlKeyState = 0x0002 - LEFT_CTRL_PRESSED ControlKeyState = 0x0008 - NUMLOCK_ON ControlKeyState = 0x0020 - RIGHT_ALT_PRESSED ControlKeyState = 0x0001 - RIGHT_CTRL_PRESSED ControlKeyState = 0x0004 - SCROLLLOCK_ON ControlKeyState = 0x0040 - SHIFT_PRESSED ControlKeyState = 0x0010 - NO_CONTROL_KEY ControlKeyState = 0x0000 -) - -// String ensures that ControlKeyState satisfies the fmt.Stringer interface. -func (cks ControlKeyState) String() string { - controlKeys := []string{} - - switch { - case cks&CAPSLOCK_ON > 0: - controlKeys = append(controlKeys, "CapsLock") - case cks&ENHANCED_KEY > 0: - controlKeys = append(controlKeys, "Enhanced") - case cks&LEFT_ALT_PRESSED > 0: - controlKeys = append(controlKeys, "Alt") - case cks&LEFT_CTRL_PRESSED > 0: - controlKeys = append(controlKeys, "CTRL") - case cks&NUMLOCK_ON > 0: - controlKeys = append(controlKeys, "NumLock") - case cks&RIGHT_ALT_PRESSED > 0: - controlKeys = append(controlKeys, "RightAlt") - case cks&RIGHT_CTRL_PRESSED > 0: - controlKeys = append(controlKeys, "RightCTRL") - case cks&SCROLLLOCK_ON > 0: - controlKeys = append(controlKeys, "ScrollLock") - case cks&SHIFT_PRESSED > 0: - controlKeys = append(controlKeys, "Shift") - case cks == NO_CONTROL_KEY: - default: - return fmt.Sprintf("Unknown(%d)", cks) - } - - return strings.Join(controlKeys, ",") -} - -// EventFlags specifies the type of a mouse event (see -// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). -type EventFlags uint32 - -// String ensures that EventFlags satisfies the fmt.Stringer interface. -func (ef EventFlags) String() string { - switch { - case ef&DOUBLE_CLICK > 0: - return "DoubleClick" - case ef&MOUSE_WHEELED > 0: - return "Wheeled" - case ef&MOUSE_MOVED > 0: - return "Moved" - case ef&MOUSE_HWHEELED > 0: - return "HWheeld" - case ef == CLICK: - return "Click" - default: - return fmt.Sprintf("Unknown(%d)", ef) - } -} - -func (ef EventFlags) Contains(flag EventFlags) bool { - return ef&flag > 0 -} - -// Valid values for EventFlags. -const ( - CLICK EventFlags = 0x0000 - MOUSE_MOVED EventFlags = 0x0001 - DOUBLE_CLICK EventFlags = 0x0002 - MOUSE_WHEELED EventFlags = 0x0004 - MOUSE_HWHEELED EventFlags = 0x0008 -) - -func highWord(data uint32) uint16 { - return uint16((data & 0xFFFF0000) >> 16) -} diff --git a/vendor/github.com/facette/natsort/LICENSE b/vendor/github.com/facette/natsort/LICENSE deleted file mode 100644 index cc8f232b..00000000 --- a/vendor/github.com/facette/natsort/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2015, Vincent Batoufflet and Marc Falzon -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the authors nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/facette/natsort/README.md b/vendor/github.com/facette/natsort/README.md deleted file mode 100644 index a4362b72..00000000 --- a/vendor/github.com/facette/natsort/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# natsort: natural strings sorting in Go - -This is an implementation of the "Alphanum Algorithm" by [Dave Koelle][0] in Go. - -[![GoDoc](https://godoc.org/facette.io/natsort?status.svg)](https://godoc.org/facette.io/natsort) - -## Usage - -```go -package main - -import ( - "fmt" - "strings" - - "facette.io/natsort" -) - -func main() { - list := []string{ - "1000X Radonius Maximus", - "10X Radonius", - "200X Radonius", - "20X Radonius", - "20X Radonius Prime", - "30X Radonius", - "40X Radonius", - "Allegia 50 Clasteron", - "Allegia 500 Clasteron", - "Allegia 50B Clasteron", - "Allegia 51 Clasteron", - "Allegia 6R Clasteron", - "Alpha 100", - "Alpha 2", - "Alpha 200", - "Alpha 2A", - "Alpha 2A-8000", - "Alpha 2A-900", - "Callisto Morphamax", - "Callisto Morphamax 500", - "Callisto Morphamax 5000", - "Callisto Morphamax 600", - "Callisto Morphamax 6000 SE", - "Callisto Morphamax 6000 SE2", - "Callisto Morphamax 700", - "Callisto Morphamax 7000", - "Xiph Xlater 10000", - "Xiph Xlater 2000", - "Xiph Xlater 300", - "Xiph Xlater 40", - "Xiph Xlater 5", - "Xiph Xlater 50", - "Xiph Xlater 500", - "Xiph Xlater 5000", - "Xiph Xlater 58", - } - - natsort.Sort(list) - - fmt.Println(strings.Join(list, "\n")) -} -``` - -Output: - -``` -10X Radonius -20X Radonius -20X Radonius Prime -30X Radonius -40X Radonius -200X Radonius -1000X Radonius Maximus -Allegia 6R Clasteron -Allegia 50 Clasteron -Allegia 50B Clasteron -Allegia 51 Clasteron -Allegia 500 Clasteron -Alpha 2 -Alpha 2A -Alpha 2A-900 -Alpha 2A-8000 -Alpha 100 -Alpha 200 -Callisto Morphamax -Callisto Morphamax 500 -Callisto Morphamax 600 -Callisto Morphamax 700 -Callisto Morphamax 5000 -Callisto Morphamax 6000 SE -Callisto Morphamax 6000 SE2 -Callisto Morphamax 7000 -Xiph Xlater 5 -Xiph Xlater 40 -Xiph Xlater 50 -Xiph Xlater 58 -Xiph Xlater 300 -Xiph Xlater 500 -Xiph Xlater 2000 -Xiph Xlater 5000 -Xiph Xlater 10000 -``` - -[0]: http://davekoelle.com/alphanum.html diff --git a/vendor/github.com/facette/natsort/natsort.go b/vendor/github.com/facette/natsort/natsort.go deleted file mode 100644 index 5c3c28d5..00000000 --- a/vendor/github.com/facette/natsort/natsort.go +++ /dev/null @@ -1,85 +0,0 @@ -// Package natsort implements natural strings sorting -package natsort - -import ( - "regexp" - "sort" - "strconv" -) - -type stringSlice []string - -func (s stringSlice) Len() int { - return len(s) -} - -func (s stringSlice) Less(a, b int) bool { - return Compare(s[a], s[b]) -} - -func (s stringSlice) Swap(a, b int) { - s[a], s[b] = s[b], s[a] -} - -var chunkifyRegexp = regexp.MustCompile(`(\d+|\D+)`) - -func chunkify(s string) []string { - return chunkifyRegexp.FindAllString(s, -1) -} - -// Sort sorts a list of strings in a natural order -func Sort(l []string) { - sort.Sort(stringSlice(l)) -} - -// Compare returns true if the first string precedes the second one according to natural order -func Compare(a, b string) bool { - chunksA := chunkify(a) - chunksB := chunkify(b) - - nChunksA := len(chunksA) - nChunksB := len(chunksB) - - for i := range chunksA { - if i >= nChunksB { - return false - } - - aInt, aErr := strconv.Atoi(chunksA[i]) - bInt, bErr := strconv.Atoi(chunksB[i]) - - // If both chunks are numeric, compare them as integers - if aErr == nil && bErr == nil { - if aInt == bInt { - if i == nChunksA-1 { - // We reached the last chunk of A, thus B is greater than A - return true - } else if i == nChunksB-1 { - // We reached the last chunk of B, thus A is greater than B - return false - } - - continue - } - - return aInt < bInt - } - - // So far both strings are equal, continue to next chunk - if chunksA[i] == chunksB[i] { - if i == nChunksA-1 { - // We reached the last chunk of A, thus B is greater than A - return true - } else if i == nChunksB-1 { - // We reached the last chunk of B, thus A is greater than B - return false - } - - continue - } - - return chunksA[i] < chunksB[i] - } - - return false -} diff --git a/vendor/github.com/felixge/httpsnoop/.gitignore b/vendor/github.com/felixge/httpsnoop/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/vendor/github.com/felixge/httpsnoop/LICENSE.txt b/vendor/github.com/felixge/httpsnoop/LICENSE.txt deleted file mode 100644 index e028b46a..00000000 --- a/vendor/github.com/felixge/httpsnoop/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016 Felix Geisendörfer (felix@debuggable.com) - - 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/felixge/httpsnoop/Makefile b/vendor/github.com/felixge/httpsnoop/Makefile deleted file mode 100644 index 4e12afdd..00000000 --- a/vendor/github.com/felixge/httpsnoop/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -.PHONY: ci generate clean - -ci: clean generate - go test -race -v ./... - -generate: - go generate . - -clean: - rm -rf *_generated*.go diff --git a/vendor/github.com/felixge/httpsnoop/README.md b/vendor/github.com/felixge/httpsnoop/README.md deleted file mode 100644 index cf6b42f3..00000000 --- a/vendor/github.com/felixge/httpsnoop/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# httpsnoop - -Package httpsnoop provides an easy way to capture http related metrics (i.e. -response time, bytes written, and http status code) from your application's -http.Handlers. - -Doing this requires non-trivial wrapping of the http.ResponseWriter interface, -which is also exposed for users interested in a more low-level API. - -[![Go Reference](https://pkg.go.dev/badge/github.com/felixge/httpsnoop.svg)](https://pkg.go.dev/github.com/felixge/httpsnoop) -[![Build Status](https://github.com/felixge/httpsnoop/actions/workflows/main.yaml/badge.svg)](https://github.com/felixge/httpsnoop/actions/workflows/main.yaml) - -## Usage Example - -```go -// myH is your app's http handler, perhaps a http.ServeMux or similar. -var myH http.Handler -// wrappedH wraps myH in order to log every request. -wrappedH := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - m := httpsnoop.CaptureMetrics(myH, w, r) - log.Printf( - "%s %s (code=%d dt=%s written=%d)", - r.Method, - r.URL, - m.Code, - m.Duration, - m.Written, - ) -}) -http.ListenAndServe(":8080", wrappedH) -``` - -## Why this package exists - -Instrumenting an application's http.Handler is surprisingly difficult. - -However if you google for e.g. "capture ResponseWriter status code" you'll find -lots of advise and code examples that suggest it to be a fairly trivial -undertaking. Unfortunately everything I've seen so far has a high chance of -breaking your application. - -The main problem is that a `http.ResponseWriter` often implements additional -interfaces such as `http.Flusher`, `http.CloseNotifier`, `http.Hijacker`, `http.Pusher`, and -`io.ReaderFrom`. So the naive approach of just wrapping `http.ResponseWriter` -in your own struct that also implements the `http.ResponseWriter` interface -will hide the additional interfaces mentioned above. This has a high change of -introducing subtle bugs into any non-trivial application. - -Another approach I've seen people take is to return a struct that implements -all of the interfaces above. However, that's also problematic, because it's -difficult to fake some of these interfaces behaviors when the underlying -`http.ResponseWriter` doesn't have an implementation. It's also dangerous, -because an application may choose to operate differently, merely because it -detects the presence of these additional interfaces. - -This package solves this problem by checking which additional interfaces a -`http.ResponseWriter` implements, returning a wrapped version implementing the -exact same set of interfaces. - -Additionally this package properly handles edge cases such as `WriteHeader` not -being called, or called more than once, as well as concurrent calls to -`http.ResponseWriter` methods, and even calls happening after the wrapped -`ServeHTTP` has already returned. - -Unfortunately this package is not perfect either. It's possible that it is -still missing some interfaces provided by the go core (let me know if you find -one), and it won't work for applications adding their own interfaces into the -mix. You can however use `httpsnoop.Unwrap(w)` to access the underlying -`http.ResponseWriter` and type-assert the result to its other interfaces. - -However, hopefully the explanation above has sufficiently scared you of rolling -your own solution to this problem. httpsnoop may still break your application, -but at least it tries to avoid it as much as possible. - -Anyway, the real problem here is that smuggling additional interfaces inside -`http.ResponseWriter` is a problematic design choice, but it probably goes as -deep as the Go language specification itself. But that's okay, I still prefer -Go over the alternatives ;). - -## Performance - -``` -BenchmarkBaseline-8 20000 94912 ns/op -BenchmarkCaptureMetrics-8 20000 95461 ns/op -``` - -As you can see, using `CaptureMetrics` on a vanilla http.Handler introduces an -overhead of ~500 ns per http request on my machine. However, the margin of -error appears to be larger than that, therefor it should be reasonable to -assume that the overhead introduced by `CaptureMetrics` is absolutely -negligible. - -## License - -MIT diff --git a/vendor/github.com/felixge/httpsnoop/capture_metrics.go b/vendor/github.com/felixge/httpsnoop/capture_metrics.go deleted file mode 100644 index bec7b71b..00000000 --- a/vendor/github.com/felixge/httpsnoop/capture_metrics.go +++ /dev/null @@ -1,86 +0,0 @@ -package httpsnoop - -import ( - "io" - "net/http" - "time" -) - -// Metrics holds metrics captured from CaptureMetrics. -type Metrics struct { - // Code is the first http response code passed to the WriteHeader func of - // the ResponseWriter. If no such call is made, a default code of 200 is - // assumed instead. - Code int - // Duration is the time it took to execute the handler. - Duration time.Duration - // Written is the number of bytes successfully written by the Write or - // ReadFrom function of the ResponseWriter. ResponseWriters may also write - // data to their underlaying connection directly (e.g. headers), but those - // are not tracked. Therefor the number of Written bytes will usually match - // the size of the response body. - Written int64 -} - -// CaptureMetrics wraps the given hnd, executes it with the given w and r, and -// returns the metrics it captured from it. -func CaptureMetrics(hnd http.Handler, w http.ResponseWriter, r *http.Request) Metrics { - return CaptureMetricsFn(w, func(ww http.ResponseWriter) { - hnd.ServeHTTP(ww, r) - }) -} - -// CaptureMetricsFn wraps w and calls fn with the wrapped w and returns the -// resulting metrics. This is very similar to CaptureMetrics (which is just -// sugar on top of this func), but is a more usable interface if your -// application doesn't use the Go http.Handler interface. -func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metrics { - m := Metrics{Code: http.StatusOK} - m.CaptureMetrics(w, fn) - return m -} - -// CaptureMetrics wraps w and calls fn with the wrapped w and updates -// Metrics m with the resulting metrics. This is similar to CaptureMetricsFn, -// but allows one to customize starting Metrics object. -func (m *Metrics) CaptureMetrics(w http.ResponseWriter, fn func(http.ResponseWriter)) { - var ( - start = time.Now() - headerWritten bool - hooks = Hooks{ - WriteHeader: func(next WriteHeaderFunc) WriteHeaderFunc { - return func(code int) { - next(code) - - if !(code >= 100 && code <= 199) && !headerWritten { - m.Code = code - headerWritten = true - } - } - }, - - Write: func(next WriteFunc) WriteFunc { - return func(p []byte) (int, error) { - n, err := next(p) - - m.Written += int64(n) - headerWritten = true - return n, err - } - }, - - ReadFrom: func(next ReadFromFunc) ReadFromFunc { - return func(src io.Reader) (int64, error) { - n, err := next(src) - - headerWritten = true - m.Written += n - return n, err - } - }, - } - ) - - fn(Wrap(w, hooks)) - m.Duration += time.Since(start) -} diff --git a/vendor/github.com/felixge/httpsnoop/docs.go b/vendor/github.com/felixge/httpsnoop/docs.go deleted file mode 100644 index 203c35b3..00000000 --- a/vendor/github.com/felixge/httpsnoop/docs.go +++ /dev/null @@ -1,10 +0,0 @@ -// Package httpsnoop provides an easy way to capture http related metrics (i.e. -// response time, bytes written, and http status code) from your application's -// http.Handlers. -// -// Doing this requires non-trivial wrapping of the http.ResponseWriter -// interface, which is also exposed for users interested in a more low-level -// API. -package httpsnoop - -//go:generate go run codegen/main.go diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go deleted file mode 100644 index 101cedde..00000000 --- a/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go +++ /dev/null @@ -1,436 +0,0 @@ -// +build go1.8 -// Code generated by "httpsnoop/codegen"; DO NOT EDIT. - -package httpsnoop - -import ( - "bufio" - "io" - "net" - "net/http" -) - -// HeaderFunc is part of the http.ResponseWriter interface. -type HeaderFunc func() http.Header - -// WriteHeaderFunc is part of the http.ResponseWriter interface. -type WriteHeaderFunc func(code int) - -// WriteFunc is part of the http.ResponseWriter interface. -type WriteFunc func(b []byte) (int, error) - -// FlushFunc is part of the http.Flusher interface. -type FlushFunc func() - -// CloseNotifyFunc is part of the http.CloseNotifier interface. -type CloseNotifyFunc func() <-chan bool - -// HijackFunc is part of the http.Hijacker interface. -type HijackFunc func() (net.Conn, *bufio.ReadWriter, error) - -// ReadFromFunc is part of the io.ReaderFrom interface. -type ReadFromFunc func(src io.Reader) (int64, error) - -// PushFunc is part of the http.Pusher interface. -type PushFunc func(target string, opts *http.PushOptions) error - -// Hooks defines a set of method interceptors for methods included in -// http.ResponseWriter as well as some others. You can think of them as -// middleware for the function calls they target. See Wrap for more details. -type Hooks struct { - Header func(HeaderFunc) HeaderFunc - WriteHeader func(WriteHeaderFunc) WriteHeaderFunc - Write func(WriteFunc) WriteFunc - Flush func(FlushFunc) FlushFunc - CloseNotify func(CloseNotifyFunc) CloseNotifyFunc - Hijack func(HijackFunc) HijackFunc - ReadFrom func(ReadFromFunc) ReadFromFunc - Push func(PushFunc) PushFunc -} - -// Wrap returns a wrapped version of w that provides the exact same interface -// as w. Specifically if w implements any combination of: -// -// - http.Flusher -// - http.CloseNotifier -// - http.Hijacker -// - io.ReaderFrom -// - http.Pusher -// -// The wrapped version will implement the exact same combination. If no hooks -// are set, the wrapped version also behaves exactly as w. Hooks targeting -// methods not supported by w are ignored. Any other hooks will intercept the -// method they target and may modify the call's arguments and/or return values. -// The CaptureMetrics implementation serves as a working example for how the -// hooks can be used. -func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter { - rw := &rw{w: w, h: hooks} - _, i0 := w.(http.Flusher) - _, i1 := w.(http.CloseNotifier) - _, i2 := w.(http.Hijacker) - _, i3 := w.(io.ReaderFrom) - _, i4 := w.(http.Pusher) - switch { - // combination 1/32 - case !i0 && !i1 && !i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - }{rw, rw} - // combination 2/32 - case !i0 && !i1 && !i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Pusher - }{rw, rw, rw} - // combination 3/32 - case !i0 && !i1 && !i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - io.ReaderFrom - }{rw, rw, rw} - // combination 4/32 - case !i0 && !i1 && !i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw} - // combination 5/32 - case !i0 && !i1 && i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Hijacker - }{rw, rw, rw} - // combination 6/32 - case !i0 && !i1 && i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Hijacker - http.Pusher - }{rw, rw, rw, rw} - // combination 7/32 - case !i0 && !i1 && i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw} - // combination 8/32 - case !i0 && !i1 && i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Hijacker - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw, rw} - // combination 9/32 - case !i0 && i1 && !i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - }{rw, rw, rw} - // combination 10/32 - case !i0 && i1 && !i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - http.Pusher - }{rw, rw, rw, rw} - // combination 11/32 - case !i0 && i1 && !i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - io.ReaderFrom - }{rw, rw, rw, rw} - // combination 12/32 - case !i0 && i1 && !i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw, rw} - // combination 13/32 - case !i0 && i1 && i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - http.Hijacker - }{rw, rw, rw, rw} - // combination 14/32 - case !i0 && i1 && i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - http.Hijacker - http.Pusher - }{rw, rw, rw, rw, rw} - // combination 15/32 - case !i0 && i1 && i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw, rw} - // combination 16/32 - case !i0 && i1 && i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - http.Hijacker - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw, rw, rw} - // combination 17/32 - case i0 && !i1 && !i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - }{rw, rw, rw} - // combination 18/32 - case i0 && !i1 && !i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.Pusher - }{rw, rw, rw, rw} - // combination 19/32 - case i0 && !i1 && !i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - io.ReaderFrom - }{rw, rw, rw, rw} - // combination 20/32 - case i0 && !i1 && !i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw, rw} - // combination 21/32 - case i0 && !i1 && i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.Hijacker - }{rw, rw, rw, rw} - // combination 22/32 - case i0 && !i1 && i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.Hijacker - http.Pusher - }{rw, rw, rw, rw, rw} - // combination 23/32 - case i0 && !i1 && i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw, rw} - // combination 24/32 - case i0 && !i1 && i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.Hijacker - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw, rw, rw} - // combination 25/32 - case i0 && i1 && !i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - }{rw, rw, rw, rw} - // combination 26/32 - case i0 && i1 && !i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - http.Pusher - }{rw, rw, rw, rw, rw} - // combination 27/32 - case i0 && i1 && !i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - io.ReaderFrom - }{rw, rw, rw, rw, rw} - // combination 28/32 - case i0 && i1 && !i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw, rw, rw} - // combination 29/32 - case i0 && i1 && i2 && !i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - http.Hijacker - }{rw, rw, rw, rw, rw} - // combination 30/32 - case i0 && i1 && i2 && !i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - http.Hijacker - http.Pusher - }{rw, rw, rw, rw, rw, rw} - // combination 31/32 - case i0 && i1 && i2 && i3 && !i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw, rw, rw} - // combination 32/32 - case i0 && i1 && i2 && i3 && i4: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - http.Hijacker - io.ReaderFrom - http.Pusher - }{rw, rw, rw, rw, rw, rw, rw} - } - panic("unreachable") -} - -type rw struct { - w http.ResponseWriter - h Hooks -} - -func (w *rw) Unwrap() http.ResponseWriter { - return w.w -} - -func (w *rw) Header() http.Header { - f := w.w.(http.ResponseWriter).Header - if w.h.Header != nil { - f = w.h.Header(f) - } - return f() -} - -func (w *rw) WriteHeader(code int) { - f := w.w.(http.ResponseWriter).WriteHeader - if w.h.WriteHeader != nil { - f = w.h.WriteHeader(f) - } - f(code) -} - -func (w *rw) Write(b []byte) (int, error) { - f := w.w.(http.ResponseWriter).Write - if w.h.Write != nil { - f = w.h.Write(f) - } - return f(b) -} - -func (w *rw) Flush() { - f := w.w.(http.Flusher).Flush - if w.h.Flush != nil { - f = w.h.Flush(f) - } - f() -} - -func (w *rw) CloseNotify() <-chan bool { - f := w.w.(http.CloseNotifier).CloseNotify - if w.h.CloseNotify != nil { - f = w.h.CloseNotify(f) - } - return f() -} - -func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) { - f := w.w.(http.Hijacker).Hijack - if w.h.Hijack != nil { - f = w.h.Hijack(f) - } - return f() -} - -func (w *rw) ReadFrom(src io.Reader) (int64, error) { - f := w.w.(io.ReaderFrom).ReadFrom - if w.h.ReadFrom != nil { - f = w.h.ReadFrom(f) - } - return f(src) -} - -func (w *rw) Push(target string, opts *http.PushOptions) error { - f := w.w.(http.Pusher).Push - if w.h.Push != nil { - f = w.h.Push(f) - } - return f(target, opts) -} - -type Unwrapper interface { - Unwrap() http.ResponseWriter -} - -// Unwrap returns the underlying http.ResponseWriter from within zero or more -// layers of httpsnoop wrappers. -func Unwrap(w http.ResponseWriter) http.ResponseWriter { - if rw, ok := w.(Unwrapper); ok { - // recurse until rw.Unwrap() returns a non-Unwrapper - return Unwrap(rw.Unwrap()) - } else { - return w - } -} diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go deleted file mode 100644 index e0951df1..00000000 --- a/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go +++ /dev/null @@ -1,278 +0,0 @@ -// +build !go1.8 -// Code generated by "httpsnoop/codegen"; DO NOT EDIT. - -package httpsnoop - -import ( - "bufio" - "io" - "net" - "net/http" -) - -// HeaderFunc is part of the http.ResponseWriter interface. -type HeaderFunc func() http.Header - -// WriteHeaderFunc is part of the http.ResponseWriter interface. -type WriteHeaderFunc func(code int) - -// WriteFunc is part of the http.ResponseWriter interface. -type WriteFunc func(b []byte) (int, error) - -// FlushFunc is part of the http.Flusher interface. -type FlushFunc func() - -// CloseNotifyFunc is part of the http.CloseNotifier interface. -type CloseNotifyFunc func() <-chan bool - -// HijackFunc is part of the http.Hijacker interface. -type HijackFunc func() (net.Conn, *bufio.ReadWriter, error) - -// ReadFromFunc is part of the io.ReaderFrom interface. -type ReadFromFunc func(src io.Reader) (int64, error) - -// Hooks defines a set of method interceptors for methods included in -// http.ResponseWriter as well as some others. You can think of them as -// middleware for the function calls they target. See Wrap for more details. -type Hooks struct { - Header func(HeaderFunc) HeaderFunc - WriteHeader func(WriteHeaderFunc) WriteHeaderFunc - Write func(WriteFunc) WriteFunc - Flush func(FlushFunc) FlushFunc - CloseNotify func(CloseNotifyFunc) CloseNotifyFunc - Hijack func(HijackFunc) HijackFunc - ReadFrom func(ReadFromFunc) ReadFromFunc -} - -// Wrap returns a wrapped version of w that provides the exact same interface -// as w. Specifically if w implements any combination of: -// -// - http.Flusher -// - http.CloseNotifier -// - http.Hijacker -// - io.ReaderFrom -// -// The wrapped version will implement the exact same combination. If no hooks -// are set, the wrapped version also behaves exactly as w. Hooks targeting -// methods not supported by w are ignored. Any other hooks will intercept the -// method they target and may modify the call's arguments and/or return values. -// The CaptureMetrics implementation serves as a working example for how the -// hooks can be used. -func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter { - rw := &rw{w: w, h: hooks} - _, i0 := w.(http.Flusher) - _, i1 := w.(http.CloseNotifier) - _, i2 := w.(http.Hijacker) - _, i3 := w.(io.ReaderFrom) - switch { - // combination 1/16 - case !i0 && !i1 && !i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - }{rw, rw} - // combination 2/16 - case !i0 && !i1 && !i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - io.ReaderFrom - }{rw, rw, rw} - // combination 3/16 - case !i0 && !i1 && i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - http.Hijacker - }{rw, rw, rw} - // combination 4/16 - case !i0 && !i1 && i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw} - // combination 5/16 - case !i0 && i1 && !i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - }{rw, rw, rw} - // combination 6/16 - case !i0 && i1 && !i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - io.ReaderFrom - }{rw, rw, rw, rw} - // combination 7/16 - case !i0 && i1 && i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - http.Hijacker - }{rw, rw, rw, rw} - // combination 8/16 - case !i0 && i1 && i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - http.CloseNotifier - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw, rw} - // combination 9/16 - case i0 && !i1 && !i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - }{rw, rw, rw} - // combination 10/16 - case i0 && !i1 && !i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - io.ReaderFrom - }{rw, rw, rw, rw} - // combination 11/16 - case i0 && !i1 && i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.Hijacker - }{rw, rw, rw, rw} - // combination 12/16 - case i0 && !i1 && i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw, rw} - // combination 13/16 - case i0 && i1 && !i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - }{rw, rw, rw, rw} - // combination 14/16 - case i0 && i1 && !i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - io.ReaderFrom - }{rw, rw, rw, rw, rw} - // combination 15/16 - case i0 && i1 && i2 && !i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - http.Hijacker - }{rw, rw, rw, rw, rw} - // combination 16/16 - case i0 && i1 && i2 && i3: - return struct { - Unwrapper - http.ResponseWriter - http.Flusher - http.CloseNotifier - http.Hijacker - io.ReaderFrom - }{rw, rw, rw, rw, rw, rw} - } - panic("unreachable") -} - -type rw struct { - w http.ResponseWriter - h Hooks -} - -func (w *rw) Unwrap() http.ResponseWriter { - return w.w -} - -func (w *rw) Header() http.Header { - f := w.w.(http.ResponseWriter).Header - if w.h.Header != nil { - f = w.h.Header(f) - } - return f() -} - -func (w *rw) WriteHeader(code int) { - f := w.w.(http.ResponseWriter).WriteHeader - if w.h.WriteHeader != nil { - f = w.h.WriteHeader(f) - } - f(code) -} - -func (w *rw) Write(b []byte) (int, error) { - f := w.w.(http.ResponseWriter).Write - if w.h.Write != nil { - f = w.h.Write(f) - } - return f(b) -} - -func (w *rw) Flush() { - f := w.w.(http.Flusher).Flush - if w.h.Flush != nil { - f = w.h.Flush(f) - } - f() -} - -func (w *rw) CloseNotify() <-chan bool { - f := w.w.(http.CloseNotifier).CloseNotify - if w.h.CloseNotify != nil { - f = w.h.CloseNotify(f) - } - return f() -} - -func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) { - f := w.w.(http.Hijacker).Hijack - if w.h.Hijack != nil { - f = w.h.Hijack(f) - } - return f() -} - -func (w *rw) ReadFrom(src io.Reader) (int64, error) { - f := w.w.(io.ReaderFrom).ReadFrom - if w.h.ReadFrom != nil { - f = w.h.ReadFrom(f) - } - return f(src) -} - -type Unwrapper interface { - Unwrap() http.ResponseWriter -} - -// Unwrap returns the underlying http.ResponseWriter from within zero or more -// layers of httpsnoop wrappers. -func Unwrap(w http.ResponseWriter) http.ResponseWriter { - if rw, ok := w.(Unwrapper); ok { - // recurse until rw.Unwrap() returns a non-Unwrapper - return Unwrap(rw.Unwrap()) - } else { - return w - } -} diff --git a/vendor/github.com/gen2brain/beeep/LICENSE b/vendor/github.com/gen2brain/beeep/LICENSE deleted file mode 100644 index 9d4a9221..00000000 --- a/vendor/github.com/gen2brain/beeep/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2017, Milan Nikolic -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gen2brain/beeep/README.md b/vendor/github.com/gen2brain/beeep/README.md deleted file mode 100644 index 68b878af..00000000 --- a/vendor/github.com/gen2brain/beeep/README.md +++ /dev/null @@ -1,37 +0,0 @@ -## beeep -[![Build Status](https://github.com/gen2brain/beeep/actions/workflows/build.yml/badge.svg)](https://github.com/gen2brain/beeep/actions) -[![Go Reference](https://pkg.go.dev/badge/github.com/gen2brain/beeep.svg)](https://pkg.go.dev/github.com/gen2brain/beeep) -[![Go Report Card](https://goreportcard.com/badge/github.com/gen2brain/beeep?branch=master)](https://goreportcard.com/report/github.com/gen2brain/beeep) - -`beeep` provides a cross-platform library for sending desktop notifications, alerts and beeps. - -### Installation - - go get -u github.com/gen2brain/beeep - -### Build tags - -* `nodbus` - disable `godbus/dbus` and use only `notify-send` - -### Examples - -```go -err := beeep.Beep(beeep.DefaultFreq, beeep.DefaultDuration) -if err != nil { - panic(err) -} -``` - -```go -err := beeep.Notify("Title", "Message body", "assets/information.png") -if err != nil { - panic(err) -} -``` - -```go -err := beeep.Alert("Title", "Message body", "assets/warning.png") -if err != nil { - panic(err) -} -``` diff --git a/vendor/github.com/gen2brain/beeep/alert_darwin.go b/vendor/github.com/gen2brain/beeep/alert_darwin.go deleted file mode 100644 index 328785e3..00000000 --- a/vendor/github.com/gen2brain/beeep/alert_darwin.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build darwin && !linux && !freebsd && !netbsd && !openbsd && !windows && !js -// +build darwin,!linux,!freebsd,!netbsd,!openbsd,!windows,!js - -package beeep - -import ( - "fmt" - "os/exec" -) - -// Alert displays a desktop notification and plays a default system sound. -func Alert(title, message, appIcon string) error { - osa, err := exec.LookPath("osascript") - if err != nil { - return err - } - - script := fmt.Sprintf("display notification %q with title %q sound name \"default\"", message, title) - cmd := exec.Command(osa, "-e", script) - return cmd.Run() -} diff --git a/vendor/github.com/gen2brain/beeep/alert_js.go b/vendor/github.com/gen2brain/beeep/alert_js.go deleted file mode 100644 index fdb55565..00000000 --- a/vendor/github.com/gen2brain/beeep/alert_js.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build js -// +build js - -package beeep - -// Alert displays a desktop notification and plays a beep. -func Alert(title, message, appIcon string) error { - if err := Notify(title, message, appIcon); err != nil { - return err - } - return Beep(DefaultFreq, DefaultDuration) -} diff --git a/vendor/github.com/gen2brain/beeep/alert_unix.go b/vendor/github.com/gen2brain/beeep/alert_unix.go deleted file mode 100644 index 0406bbd9..00000000 --- a/vendor/github.com/gen2brain/beeep/alert_unix.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build linux || freebsd || netbsd || openbsd || illumos -// +build linux freebsd netbsd openbsd illumos - -package beeep - -// Alert displays a desktop notification and plays a beep. -func Alert(title, message, appIcon string) error { - if err := Notify(title, message, appIcon); err != nil { - return err - } - return Beep(DefaultFreq, DefaultDuration) -} diff --git a/vendor/github.com/gen2brain/beeep/alert_unsupported.go b/vendor/github.com/gen2brain/beeep/alert_unsupported.go deleted file mode 100644 index 12c1e055..00000000 --- a/vendor/github.com/gen2brain/beeep/alert_unsupported.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !linux && !freebsd && !netbsd && !openbsd && !windows && !darwin && !illumos && !js -// +build !linux,!freebsd,!netbsd,!openbsd,!windows,!darwin,!illumos,!js - -package beeep - -// Alert displays a desktop notification and plays a beep. -func Alert(title, message, appIcon string) error { - return ErrUnsupported -} diff --git a/vendor/github.com/gen2brain/beeep/alert_windows.go b/vendor/github.com/gen2brain/beeep/alert_windows.go deleted file mode 100644 index 825b147e..00000000 --- a/vendor/github.com/gen2brain/beeep/alert_windows.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build windows && !linux && !freebsd && !netbsd && !openbsd && !darwin && !js -// +build windows,!linux,!freebsd,!netbsd,!openbsd,!darwin,!js - -package beeep - -import ( - toast "github.com/go-toast/toast" -) - -// Alert displays a desktop notification and plays a default system sound. -func Alert(title, message, appIcon string) error { - if isWindows10 { - note := toastNotification(title, message, pathAbs(appIcon)) - note.Audio = toast.Default - return note.Push() - } - - if err := Notify(title, message, appIcon); err != nil { - return err - } - return Beep(DefaultFreq, DefaultDuration) -} diff --git a/vendor/github.com/gen2brain/beeep/beeep.go b/vendor/github.com/gen2brain/beeep/beeep.go deleted file mode 100644 index b0e66d46..00000000 --- a/vendor/github.com/gen2brain/beeep/beeep.go +++ /dev/null @@ -1,27 +0,0 @@ -// Package beeep provides a cross-platform library for sending desktop notifications and beeps. -package beeep - -import ( - "errors" - "path/filepath" - "runtime" -) - -var ( - // ErrUnsupported is returned when operating system is not supported. - ErrUnsupported = errors.New("beeep: unsupported operating system: " + runtime.GOOS) -) - -func pathAbs(path string) string { - var err error - var abs string - - if path != "" { - abs, err = filepath.Abs(path) - if err != nil { - abs = path - } - } - - return abs -} diff --git a/vendor/github.com/gen2brain/beeep/beep_darwin.go b/vendor/github.com/gen2brain/beeep/beep_darwin.go deleted file mode 100644 index 93cf608e..00000000 --- a/vendor/github.com/gen2brain/beeep/beep_darwin.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build darwin && !linux && !freebsd && !netbsd && !openbsd && !windows && !js -// +build darwin,!linux,!freebsd,!netbsd,!openbsd,!windows,!js - -package beeep - -import ( - "os" - "os/exec" -) - -var ( - // DefaultFreq - frequency, in Hz, middle A - DefaultFreq = 0.0 - // DefaultDuration - duration in milliseconds - DefaultDuration = 0 -) - -// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker). -func Beep(freq float64, duration int) error { - osa, err := exec.LookPath("osascript") - if err != nil { - // Output the only beep we can - _, err = os.Stdout.Write([]byte{7}) - return err - } - - cmd := exec.Command(osa, "-e", `beep`) - return cmd.Run() -} diff --git a/vendor/github.com/gen2brain/beeep/beep_js.go b/vendor/github.com/gen2brain/beeep/beep_js.go deleted file mode 100644 index 690f196a..00000000 --- a/vendor/github.com/gen2brain/beeep/beep_js.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build js -// +build js - -package beeep - -import ( - "syscall/js" -) - -var ( - // DefaultFreq - frequency, in Hz, middle A - DefaultFreq = 0.0 - // DefaultDuration - duration in milliseconds - DefaultDuration = 0 -) - -// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker). -func Beep(freq float64, duration int) (err error) { - defer func() { - e := recover() - - if e == nil { - return - } - - if e, ok := e.(*js.Error); ok { - err = e - } else { - panic(e) - } - }() - - a := js.Global().Get("document").Call("createElement", "audio") - a.Set("src", `data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=`) - a.Call("play") - - return -} diff --git a/vendor/github.com/gen2brain/beeep/beep_unix.go b/vendor/github.com/gen2brain/beeep/beep_unix.go deleted file mode 100644 index 8a496be9..00000000 --- a/vendor/github.com/gen2brain/beeep/beep_unix.go +++ /dev/null @@ -1,139 +0,0 @@ -//go:build linux || freebsd || netbsd || openbsd || illumos -// +build linux freebsd netbsd openbsd illumos - -package beeep - -import ( - "errors" - "os" - "syscall" - "time" - "unsafe" -) - -// Constants -const ( - // This number represents the fixed frequency of the original PC XT's timer chip, which is approximately 1.193 MHz. This number - // is divided with the desired frequency to obtain a counter value, that is subsequently fed into the timer chip, tied to the PC speaker. - clockTickRate = 1193180 - - // linux/kd.h, start sound generation (0 for off) - kiocsound = 0x4B2F - - // linux/input-event-codes.h - evSnd = 0x12 // Event type - sndTone = 0x02 // Sound -) - -var ( - // DefaultFreq - frequency, in Hz, middle A - DefaultFreq = 440.0 - // DefaultDuration - duration in milliseconds - DefaultDuration = 200 -) - -// inputEvent represents linux/input.h event structure. -type inputEvent struct { - Time syscall.Timeval // time in seconds since epoch at which event occurred - Type uint16 // event type - Code uint16 // event code related to the event type - Value int32 // event value related to the event type -} - -// ioctl system call manipulates the underlying device parameters of special files. -func ioctl(fd, name, data uintptr) error { - _, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, name, data) - if e != 0 { - return e - } - - return nil -} - -// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker). -// -// On Linux it needs permission to access `/dev/tty0` or `/dev/input/by-path/platform-pcspkr-event-spkr` files for writing, -// and `pcspkr` module must be loaded. User must be in correct groups, usually `input` and/or `tty`. -// -// If it can not open device files, it will fallback to sending Bell character (https://en.wikipedia.org/wiki/Bell_character). -// For bell character in X11 terminals you can enable bell with `xset b on`. For console check `setterm` and `--blength` or `--bfreq` options. -// -// On macOS this just sends bell character. Enable `Audible bell` in Terminal --> Preferences --> Settings --> Advanced. -// -// On Windows it uses Beep function via syscall. -// -// On Web it plays hard coded beep sound. -func Beep(freq float64, duration int) error { - if freq == 0 { - freq = DefaultFreq - } else if freq > 20000 { - freq = 20000 - } else if freq < 0 { - freq = DefaultFreq - } - - if duration == 0 { - duration = DefaultDuration - } - - period := int(float64(clockTickRate) / freq) - - var evdev bool - - f, err := os.OpenFile("/dev/tty0", os.O_WRONLY, 0644) - if err != nil { - e := err - f, err = os.OpenFile("/dev/input/by-path/platform-pcspkr-event-spkr", os.O_WRONLY, 0644) - if err != nil { - e = errors.New("beeep: " + e.Error() + "; " + err.Error()) - - // Output the only beep we can - _, err = os.Stdout.Write([]byte{7}) - if err != nil { - return errors.New(e.Error() + "; " + err.Error()) - } - - return nil - } - - evdev = true - } - - defer f.Close() - - if evdev { // Use Linux evdev API - ev := inputEvent{} - ev.Type = evSnd - ev.Code = sndTone - ev.Value = int32(freq) - - d := *(*[unsafe.Sizeof(ev)]byte)(unsafe.Pointer(&ev)) - - // Start beep - f.Write(d[:]) - - time.Sleep(time.Duration(duration) * time.Millisecond) - - ev.Value = 0 - d = *(*[unsafe.Sizeof(ev)]byte)(unsafe.Pointer(&ev)) - - // Stop beep - f.Write(d[:]) - } else { // Use ioctl - // Start beep - err = ioctl(f.Fd(), kiocsound, uintptr(period)) - if err != nil { - return err - } - - time.Sleep(time.Duration(duration) * time.Millisecond) - - // Stop beep - err = ioctl(f.Fd(), kiocsound, uintptr(0)) - if err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/gen2brain/beeep/beep_unsupported.go b/vendor/github.com/gen2brain/beeep/beep_unsupported.go deleted file mode 100644 index 6d432722..00000000 --- a/vendor/github.com/gen2brain/beeep/beep_unsupported.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !linux && !freebsd && !netbsd && !openbsd && !windows && !darwin && !illumos && !js -// +build !linux,!freebsd,!netbsd,!openbsd,!windows,!darwin,!illumos,!js - -package beeep - -var ( - // DefaultFreq - frequency, in Hz, middle A - DefaultFreq = 0.0 - // DefaultDuration - duration in milliseconds - DefaultDuration = 0 -) - -// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker). -func Beep(freq float64, duration int) error { - return ErrUnsupported -} diff --git a/vendor/github.com/gen2brain/beeep/beep_windows.go b/vendor/github.com/gen2brain/beeep/beep_windows.go deleted file mode 100644 index ad213458..00000000 --- a/vendor/github.com/gen2brain/beeep/beep_windows.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build windows && !linux && !freebsd && !netbsd && !openbsd && !darwin && !js -// +build windows,!linux,!freebsd,!netbsd,!openbsd,!darwin,!js - -package beeep - -import ( - "syscall" -) - -var ( - // DefaultFreq - frequency, in Hz, middle A - DefaultFreq = 587.0 - // DefaultDuration - duration in milliseconds - DefaultDuration = 500 -) - -// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker). -func Beep(freq float64, duration int) error { - if freq == 0 { - freq = DefaultFreq - } else if freq > 32767 { - freq = 32767 - } else if freq < 37 { - freq = DefaultFreq - } - - if duration == 0 { - duration = DefaultDuration - } - - kernel32, _ := syscall.LoadLibrary("kernel32.dll") - beep32, _ := syscall.GetProcAddress(kernel32, "Beep") - - defer syscall.FreeLibrary(kernel32) - - _, _, e := syscall.Syscall(uintptr(beep32), uintptr(2), uintptr(int(freq)), uintptr(duration), 0) - if e != 0 { - return e - } - - return nil -} diff --git a/vendor/github.com/gen2brain/beeep/notify_darwin.go b/vendor/github.com/gen2brain/beeep/notify_darwin.go deleted file mode 100644 index b510af28..00000000 --- a/vendor/github.com/gen2brain/beeep/notify_darwin.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:build darwin && !linux && !freebsd && !netbsd && !openbsd && !windows && !js -// +build darwin,!linux,!freebsd,!netbsd,!openbsd,!windows,!js - -package beeep - -import ( - "fmt" - "os/exec" -) - -// Notify sends desktop notification. -// -// On macOS this executes AppleScript with `osascript` binary. -func Notify(title, message, appIcon string) error { - osa, err := exec.LookPath("osascript") - if err != nil { - return err - } - - script := fmt.Sprintf("display notification %q with title %q", message, title) - cmd := exec.Command(osa, "-e", script) - return cmd.Run() -} diff --git a/vendor/github.com/gen2brain/beeep/notify_js.go b/vendor/github.com/gen2brain/beeep/notify_js.go deleted file mode 100644 index f88d7fcc..00000000 --- a/vendor/github.com/gen2brain/beeep/notify_js.go +++ /dev/null @@ -1,51 +0,0 @@ -//go:build js -// +build js - -package beeep - -import ( - "syscall/js" -) - -// Notify sends desktop notification. -// -// On Web, in Firefox it just works, in Chrome you must call it from some "user gesture" like `onclick`, -// and you must use TLS certificate, it doesn't work with plain http. -func Notify(title, message, appIcon string) (err error) { - defer func() { - e := recover() - - if e == nil { - return - } - - if e, ok := e.(*js.Error); ok { - err = e - } else { - panic(e) - } - }() - - n := js.Global().Get("Notification") - - opts := js.Global().Get("Object").Invoke() - opts.Set("body", message) - opts.Set("icon", pathAbs(appIcon)) - - if n.Get("permission").String() == "granted" { - n.New(js.ValueOf(title), opts) - } else { - var f js.Func - f = js.FuncOf(func(this js.Value, args []js.Value) interface{} { - if args[0].String() == "granted" { - n.New(js.ValueOf(title), opts) - } - f.Release() - return nil - }) - - n.Call("requestPermission", f) - } - - return -} diff --git a/vendor/github.com/gen2brain/beeep/notify_unix.go b/vendor/github.com/gen2brain/beeep/notify_unix.go deleted file mode 100644 index 04dffd6d..00000000 --- a/vendor/github.com/gen2brain/beeep/notify_unix.go +++ /dev/null @@ -1,59 +0,0 @@ -//go:build (linux && !nodbus) || (freebsd && !nodbus) || (netbsd && !nodbus) || (openbsd && !nodbus) -// +build linux,!nodbus freebsd,!nodbus netbsd,!nodbus openbsd,!nodbus - -package beeep - -import ( - "errors" - "os/exec" - - "github.com/godbus/dbus/v5" -) - -// Notify sends desktop notification. -// -// On Linux it tries to send notification via D-Bus and it will fallback to `notify-send` binary. -func Notify(title, message, appIcon string) error { - appIcon = pathAbs(appIcon) - - cmd := func() error { - send, err := exec.LookPath("sw-notify-send") - if err != nil { - send, err = exec.LookPath("notify-send") - if err != nil { - return err - } - } - - c := exec.Command(send, title, message, "-i", appIcon) - return c.Run() - } - - knotify := func() error { - send, err := exec.LookPath("kdialog") - if err != nil { - return err - } - c := exec.Command(send, "--title", title, "--passivepopup", message, "10", "--icon", appIcon) - return c.Run() - } - - conn, err := dbus.SessionBus() - if err != nil { - return cmd() - } - obj := conn.Object("org.freedesktop.Notifications", dbus.ObjectPath("/org/freedesktop/Notifications")) - - call := obj.Call("org.freedesktop.Notifications.Notify", 0, "", uint32(0), appIcon, title, message, []string{}, map[string]dbus.Variant{}, int32(-1)) - if call.Err != nil { - e := cmd() - if e != nil { - e := knotify() - if e != nil { - return errors.New("beeep: " + call.Err.Error() + "; " + e.Error()) - } - } - } - - return nil -} diff --git a/vendor/github.com/gen2brain/beeep/notify_unix_nodbus.go b/vendor/github.com/gen2brain/beeep/notify_unix_nodbus.go deleted file mode 100644 index 8daff291..00000000 --- a/vendor/github.com/gen2brain/beeep/notify_unix_nodbus.go +++ /dev/null @@ -1,46 +0,0 @@ -//go:build (linux && nodbus) || (freebsd && nodbus) || (netbsd && nodbus) || (openbsd && nodbus) || illumos -// +build linux,nodbus freebsd,nodbus netbsd,nodbus openbsd,nodbus illumos - -package beeep - -import ( - "errors" - "os/exec" -) - -// Notify sends desktop notification. -func Notify(title, message, appIcon string) error { - appIcon = pathAbs(appIcon) - - cmd := func() error { - send, err := exec.LookPath("sw-notify-send") - if err != nil { - send, err = exec.LookPath("notify-send") - if err != nil { - return err - } - } - - c := exec.Command(send, title, message, "-i", appIcon) - return c.Run() - } - - knotify := func() error { - send, err := exec.LookPath("kdialog") - if err != nil { - return err - } - c := exec.Command(send, "--title", title, "--passivepopup", message, "10", "--icon", appIcon) - return c.Run() - } - - err := cmd() - if err != nil { - e := knotify() - if e != nil { - return errors.New("beeep: " + err.Error() + "; " + e.Error()) - } - } - - return nil -} diff --git a/vendor/github.com/gen2brain/beeep/notify_unsupported.go b/vendor/github.com/gen2brain/beeep/notify_unsupported.go deleted file mode 100644 index 6ad401b6..00000000 --- a/vendor/github.com/gen2brain/beeep/notify_unsupported.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !linux && !freebsd && !netbsd && !openbsd && !windows && !darwin && !illumos && !js -// +build !linux,!freebsd,!netbsd,!openbsd,!windows,!darwin,!illumos,!js - -package beeep - -// Notify sends desktop notification. -func Notify(title, message, appIcon string) error { - return ErrUnsupported -} diff --git a/vendor/github.com/gen2brain/beeep/notify_windows.go b/vendor/github.com/gen2brain/beeep/notify_windows.go deleted file mode 100644 index fa145840..00000000 --- a/vendor/github.com/gen2brain/beeep/notify_windows.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build windows && !linux && !freebsd && !netbsd && !openbsd && !darwin && !js -// +build windows,!linux,!freebsd,!netbsd,!openbsd,!darwin,!js - -package beeep - -import ( - "bufio" - "bytes" - "errors" - "os/exec" - "strings" - "syscall" - "time" - - toast "github.com/go-toast/toast" - "github.com/tadvi/systray" - "golang.org/x/sys/windows/registry" -) - -var isWindows10 bool -var applicationID string - -func init() { - k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) - if err != nil { - return - } - defer k.Close() - - maj, _, err := k.GetIntegerValue("CurrentMajorVersionNumber") - if err != nil { - return - } - - isWindows10 = maj == 10 - - if isWindows10 { - applicationID = appID() - } -} - -// Notify sends desktop notification. -func Notify(title, message, appIcon string) error { - if isWindows10 { - return toastNotify(title, message, appIcon) - } - - err := baloonNotify(title, message, appIcon, false) - if err != nil { - e := msgNotify(title, message) - if e != nil { - return errors.New("beeep: " + err.Error() + "; " + e.Error()) - } - } - - return nil - -} - -func msgNotify(title, message string) error { - msg, err := exec.LookPath("msg") - if err != nil { - return err - } - cmd := exec.Command(msg, "*", "/TIME:3", title+"\n\n"+message) - cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - return cmd.Run() -} - -func baloonNotify(title, message, appIcon string, bigIcon bool) error { - tray, err := systray.New() - if err != nil { - return err - } - - err = tray.ShowCustom(pathAbs(appIcon), title) - if err != nil { - return err - } - - go func() { - go func() { - _ = tray.Run() - }() - time.Sleep(3 * time.Second) - _ = tray.Stop() - }() - - return tray.ShowMessage(title, message, bigIcon) -} - -func toastNotify(title, message, appIcon string) error { - notification := toastNotification(title, message, pathAbs(appIcon)) - return notification.Push() -} - -func toastNotification(title, message, appIcon string) toast.Notification { - return toast.Notification{ - AppID: applicationID, - Title: title, - Message: message, - Icon: appIcon, - } -} - -func appID() string { - defID := "{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe" - cmd := exec.Command("powershell", "-NoProfile", "Get-StartApps") - cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} - out, err := cmd.Output() - if err != nil { - return defID - } - - scanner := bufio.NewScanner(bytes.NewReader(out)) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.Contains(line, "powershell.exe") { - sp := strings.Split(line, " ") - if len(sp) > 0 { - return sp[len(sp)-1] - } - } - } - - return defID -} diff --git a/vendor/github.com/getlantern/context/.travis.yml b/vendor/github.com/getlantern/context/.travis.yml deleted file mode 100644 index cc2835a0..00000000 --- a/vendor/github.com/getlantern/context/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go - -go: - - 1.6.2 - -install: - - go get -d -t -v ./... - - go build -v ./... - - go get golang.org/x/tools/cmd/cover - - go get -v github.com/axw/gocov/gocov - - go get -v github.com/mattn/goveralls - -script: - - go test -race -v -covermode=atomic -coverprofile=profile.cov - - $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci diff --git a/vendor/github.com/getlantern/context/LICENSE b/vendor/github.com/getlantern/context/LICENSE deleted file mode 100644 index 5dc6c268..00000000 --- a/vendor/github.com/getlantern/context/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/context/README.md b/vendor/github.com/getlantern/context/README.md deleted file mode 100644 index 978c9e05..00000000 --- a/vendor/github.com/getlantern/context/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# context [![Travis CI Status](https://travis-ci.org/getlantern/context.svg?branch=master)](https://travis-ci.org/getlantern/context) [![Coverage Status](https://coveralls.io/repos/getlantern/context/badge.png?branch=master)](https://coveralls.io/r/getlantern/context) - -Provides goroutine-based context state inspired by https://github.com/tylerb/gls -and https://github.com/jtolds/gls. It uses the same basic hack as tylerb's -library, but adds a stack abstraction that allows nested contexts similar to -jtolds' library, but using `Enter()` and `Exit()` instead of callback functions. diff --git a/vendor/github.com/getlantern/context/context.go b/vendor/github.com/getlantern/context/context.go deleted file mode 100644 index c77f1297..00000000 --- a/vendor/github.com/getlantern/context/context.go +++ /dev/null @@ -1,309 +0,0 @@ -// Package context provides a mechanism for transparently tracking contextual -// state associated to the current goroutine and even across goroutines. -package context - -import ( - "sync" -) - -// Manager provides the ability to create and access Contexts. -type Manager interface { - // Enter enters a new level on the current Context stack, creating a new Context - // if necessary. - Enter() Context - - // Go starts the given function on a new goroutine but sharing the context of - // the current goroutine (if it has one). - Go(func()) - - // PutGlobal puts the given key->value pair into the global context. - PutGlobal(key string, value interface{}) - - // PutGlobalDynamic puts a key->value pair into the global context where the - // value is generated by a function that gets evaluated at every Read. If the - // value is a map[string]interface{}, we will unpack the map and set each - // contained key->value pair independently. - PutGlobalDynamic(key string, valueFN func() interface{}) - - // AsMap returns a map containing all values from the supplied obj if it is a - // Contextual, plus any addition values from along the stack, plus globals if so - // specified. - AsMap(obj interface{}, includeGlobals bool) Map -} - -type manager struct { - contexts map[uint64]*context - mxContexts sync.RWMutex - global Map - mxGlobal sync.RWMutex -} - -// NewManager creates a new Manager -func NewManager() Manager { - return &manager{ - contexts: make(map[uint64]*context), - global: make(Map), - } -} - -// Contextual is an interface for anything that maintains its own context. -type Contextual interface { - // Fill fills the given Map with all of this Contextual's context - Fill(m Map) -} - -// Map is a map of key->value pairs. -type Map map[string]interface{} - -// Fill implements the method from the Contextual interface. -func (_m Map) Fill(m Map) { - for key, value := range _m { - m[key] = value - } -} - -// Context is a context containing key->value pairs -type Context interface { - // Enter enters a new level on this Context stack. - Enter() Context - - // Go starts the given function on a new goroutine. - Go(fn func()) - - // Exit exits the current level on this Context stack. - Exit() - - // Put puts a key->value pair into the current level of the context stack. - Put(key string, value interface{}) Context - - // PutIfAbsent puts the given key->value pair into the current level of the - // context stack if and only if that key is defined nowhere within the context - // stack (including parent contexts). - PutIfAbsent(key string, value interface{}) Context - - // PutDynamic puts a key->value pair into the current level of the context - // stack where the value is generated by a function that gets evaluated at - // every Read. If the value is a map[string]interface{}, we will unpack the - // map and set each contained key->value pair independently. - PutDynamic(key string, valueFN func() interface{}) Context - - // Fill fills the given map with data from this Context - Fill(m Map) - - // AsMap returns a map containing all values from the supplied obj if it is a - // Contextual, plus any addition values from along the stack, plus globals if - // so specified. - AsMap(obj interface{}, includeGlobals bool) Map -} - -type context struct { - cm *manager - id uint64 - parent *context - branchedFrom *context - data Map - mx sync.RWMutex -} - -type dynval struct { - fn func() interface{} -} - -func (cm *manager) Enter() Context { - return cm.enter(curGoroutineID()) -} - -func (cm *manager) enter(id uint64) *context { - cm.mxContexts.Lock() - parentOrNil := cm.contexts[id] - c := cm.makeContext(id, parentOrNil, nil) - cm.contexts[id] = c - cm.mxContexts.Unlock() - return c -} - -func (cm *manager) exit(id uint64, parent *context) { - cm.mxContexts.Lock() - if parent == nil { - delete(cm.contexts, id) - } else { - cm.contexts[id] = parent - } - cm.mxContexts.Unlock() -} - -func (cm *manager) branch(id uint64, from *context) { - next := cm.makeContext(id, nil, from) - cm.mxContexts.Lock() - cm.contexts[id] = next - cm.mxContexts.Unlock() -} - -func (cm *manager) merge(id uint64) { - cm.mxContexts.Lock() - delete(cm.contexts, id) - cm.mxContexts.Unlock() -} - -func (c *context) Enter() Context { - c.mx.RLock() - id := c.id - c.mx.RUnlock() - return c.cm.enter(id) -} - -func (c *context) Go(fn func()) { - go func() { - id := curGoroutineID() - c.cm.branch(id, c) - fn() - c.cm.merge(id) - }() -} - -func (cm *manager) Go(fn func()) { - c := cm.currentContext() - if c != nil { - c.Go(fn) - } else { - go fn() - } -} - -func (cm *manager) makeContext(id uint64, parent *context, branchedFrom *context) *context { - return &context{ - cm: cm, - id: id, - parent: parent, - branchedFrom: branchedFrom, - data: make(Map), - } -} - -func (c *context) Exit() { - c.mx.RLock() - id := c.id - parent := c.parent - c.mx.RUnlock() - c.cm.exit(id, parent) -} - -func (c *context) Put(key string, value interface{}) Context { - c.mx.Lock() - c.data[key] = value - c.mx.Unlock() - return c -} - -func (c *context) PutIfAbsent(key string, value interface{}) Context { - for ctx := c; ctx != nil; { - ctx.mx.RLock() - _, exists := ctx.data[key] - next := ctx.parent - if next == nil { - next = ctx.branchedFrom - } - ctx.mx.RUnlock() - if exists { - return c - } - ctx = next - } - - // Value not set, set it - return c.Put(key, value) -} - -func (c *context) PutDynamic(key string, valueFN func() interface{}) Context { - value := &dynval{valueFN} - c.mx.Lock() - c.data[key] = value - c.mx.Unlock() - return c -} - -func (cm *manager) PutGlobal(key string, value interface{}) { - cm.mxGlobal.Lock() - cm.global[key] = value - cm.mxGlobal.Unlock() -} - -func (cm *manager) PutGlobalDynamic(key string, valueFN func() interface{}) { - value := &dynval{valueFN} - cm.mxGlobal.Lock() - cm.global[key] = value - cm.mxGlobal.Unlock() -} - -func (c *context) Fill(m Map) { - for ctx := c; ctx != nil; { - ctx.mx.RLock() - fill(m, ctx.data) - next := ctx.parent - if next == nil { - next = ctx.branchedFrom - } - ctx.mx.RUnlock() - ctx = next - } -} - -func (cm *manager) AsMap(obj interface{}, includeGlobals bool) Map { - return cm.currentContext().asMap(cm, obj, includeGlobals) -} - -func (c *context) AsMap(obj interface{}, includeGlobals bool) Map { - return c.asMap(c.cm, obj, includeGlobals) -} - -func (c *context) asMap(cm *manager, obj interface{}, includeGlobals bool) Map { - result := make(Map, 0) - cl, ok := obj.(Contextual) - if ok { - cl.Fill(result) - } - if c != nil { - c.Fill(result) - } - if includeGlobals { - cm.mxGlobal.RLock() - fill(result, cm.global) - cm.mxGlobal.RUnlock() - } - return result -} - -func fill(m Map, from Map) { - if m != nil { - doFill := func(key string, _value interface{}) { - switch value := _value.(type) { - case map[string]interface{}: - for k, v := range value { - m[k] = v - } - default: - m[key] = value - } - } - - for key, value := range from { - _, alreadyRead := m[key] - if !alreadyRead { - switch v := value.(type) { - case *dynval: - doFill(key, v.fn()) - default: - doFill(key, v) - } - } - } - } -} - -func (cm *manager) currentContext() *context { - id := curGoroutineID() - cm.mxContexts.RLock() - c := cm.contexts[id] - cm.mxContexts.RUnlock() - return c -} diff --git a/vendor/github.com/getlantern/context/gotrack.go b/vendor/github.com/getlantern/context/gotrack.go deleted file mode 100644 index 7f923467..00000000 --- a/vendor/github.com/getlantern/context/gotrack.go +++ /dev/null @@ -1,130 +0,0 @@ -package context - -import ( - "bytes" - "errors" - "fmt" - "runtime" - "strconv" - "sync" -) - -// Sourced https://github.com/bradfitz/http2/blob/dc0c5c000ec33e263612939744d51a3b68b9cece/gotrack.go -var goroutineSpace = []byte("goroutine ") -var littleBuf = sync.Pool{ - New: func() interface{} { - buf := make([]byte, 64) - return &buf - }, -} - -func curGoroutineID() uint64 { - bp := littleBuf.Get().(*[]byte) - defer littleBuf.Put(bp) - b := *bp - b = b[:runtime.Stack(b, false)] - // Parse the 4707 out of "goroutine 4707 [" - b = bytes.TrimPrefix(b, goroutineSpace) - i := bytes.IndexByte(b, ' ') - if i < 0 { - panic(fmt.Sprintf("No space found in %q", b)) - } - b = b[:i] - n, err := parseUintBytes(b, 10, 64) - if err != nil { - panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err)) - } - return n -} - -// parseUintBytes is like strconv.ParseUint, but using a []byte. -func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) { - var cutoff, maxVal uint64 - - if bitSize == 0 { - bitSize = int(strconv.IntSize) - } - - s0 := s - switch { - case len(s) < 1: - err = strconv.ErrSyntax - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - - case 2 <= base && base <= 36: - // valid base; nothing to do - - case base == 0: - // Look for octal, hex prefix. - switch { - case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): - base = 16 - s = s[2:] - if len(s) < 1 { - err = strconv.ErrSyntax - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - case s[0] == '0': - base = 8 - default: - base = 10 - } - - default: - err = errors.New("invalid base " + strconv.Itoa(base)) - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - - n = 0 - cutoff = cutoff64(base) - maxVal = 1<= base { - n = 0 - err = strconv.ErrSyntax - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - - if n >= cutoff { - // n*base overflows - n = 1<<64 - 1 - err = strconv.ErrRange - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - n *= uint64(base) - - n1 := n + uint64(v) - if n1 < n || n1 > maxVal { - // n+v overflows - n = 1<<64 - 1 - err = strconv.ErrRange - return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} - } - n = n1 - } - - return n, nil -} - -// Return the first number n such that n*base >= 1<<64. -func cutoff64(base int) uint64 { - if base < 2 { - return 0 - } - return (1<<64-1)/uint64(base) + 1 -} diff --git a/vendor/github.com/getlantern/errors/LICENSE b/vendor/github.com/getlantern/errors/LICENSE deleted file mode 100644 index 416dd694..00000000 --- a/vendor/github.com/getlantern/errors/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/errors/errors.go b/vendor/github.com/getlantern/errors/errors.go deleted file mode 100644 index 8b2b84fd..00000000 --- a/vendor/github.com/getlantern/errors/errors.go +++ /dev/null @@ -1,566 +0,0 @@ -/* -Package errors defines error types used across Lantern project. - - n, err := Foo() - if err != nil { - return n, errors.New("Unable to do Foo: %v", err) - } - -or - - n, err := Foo() - return n, errors.Wrap(err) - -New() method will create a new error with err as its cause. Wrap will wrap err, -returning nil if err is nil. If err is an error from Go's standard library, -errors will extract details from that error, at least the Go type name and the -return value of err.Error(). - -One can record the operation on which the error occurred using Op(): - - return n, errors.New("Unable to do Foo: %v", err).Op("FooDooer") - -One can also record additional data: - - return n, errors. - New("Unable to do Foo: %v", err). - Op("FooDooer"). - With("mydata", "myvalue"). - With("moredata", 5) - -When used with github.com/getlantern/ops, Error captures its current context -and propagates that data for use in calling layers. - -When used with github.com/getlantern/golog, Error provides stacktraces: - - Hello World - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: World - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: orld - Caused by: ld - at github.com/getlantern/errors.buildSubSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: d - -It's the caller's responsibility to avoid race conditions accessing the same -error instance from multiple goroutines. -*/ -package errors - -import ( - "bufio" - "bytes" - "crypto/tls" - "crypto/x509" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net" - "net/http" - "net/textproto" - "net/url" - "os" - "os/exec" - "reflect" - "runtime" - "strconv" - "strings" - "syscall" - "time" - "unicode" - - "github.com/getlantern/context" - "github.com/getlantern/hidden" - "github.com/getlantern/ops" - "github.com/go-stack/stack" -) - -// Error wraps system and application defined errors in unified structure for -// reporting and logging. It's not meant to be created directly. User New(), -// Wrap() and Report() instead. -type Error interface { - error - context.Contextual - - // ErrorClean returns a non-parameterized version of the error whenever - // possible. For example, if the error text is: - // - // unable to dial www.google.com caused by: i/o timeout - // - // ErrorClean might return: - // - // unable to dial %v caused by: %v - // - // This can be useful when performing analytics on the error. - ErrorClean() string - - // MultiLinePrinter implements the interface golog.MultiLine - MultiLinePrinter() func(buf *bytes.Buffer) bool - - // Op attaches a hint of the operation triggers this Error. Many error types - // returned by net and os package have Op pre-filled. - Op(op string) Error - - // With attaches arbitrary field to the error. keys will be normalized as - // underscore_divided_words, so all characters except letters and numbers will - // be replaced with underscores, and all letters will be lowercased. - With(key string, value interface{}) Error - - // RootCause returns the bottom-most cause of this Error. If the Error - // resulted from wrapping a plain error, the wrapped error will be returned as - // the cause. - RootCause() error -} - -type structured struct { - id uint64 - hiddenID string - data context.Map - context context.Map - wrapped error - cause Error - callStack stack.CallStack -} - -// New creates an Error with supplied description and format arguments to the -// description. If any of the arguments is an error, we use that as the cause. -func New(desc string, args ...interface{}) Error { - return NewOffset(1, desc, args...) -} - -// NewOffset is like New but offsets the stack by the given offset. This is -// useful for utilities like golog that may create errors on behalf of others. -func NewOffset(offset int, desc string, args ...interface{}) Error { - var cause error - for _, arg := range args { - err, isError := arg.(error) - if isError { - cause = err - break - } - } - e := buildError(desc, fmt.Sprintf(desc, args...), nil, Wrap(cause)) - e.attachStack(2 + offset) - return e -} - -// Wrap creates an Error based on the information in an error instance. It -// returns nil if the error passed in is nil, so we can simply call -// errors.Wrap(s.l.Close()) regardless there's an error or not. If the error is -// already wrapped, it is returned as is. -func Wrap(err error) Error { - return wrapSkipFrames(err, 1) -} - -// Fill implements the method from the context.Contextual interface. -func (e *structured) Fill(m context.Map) { - if e != nil { - if e.cause != nil { - // Include data from cause, which supercedes context - e.cause.Fill(m) - } - // Include the context, which supercedes the cause - for key, value := range e.context { - m[key] = value - } - // Now include the error's data, which supercedes everything - for key, value := range e.data { - m[key] = value - } - } -} - -func (e *structured) Op(op string) Error { - e.data["error_op"] = op - return e -} - -func (e *structured) With(key string, value interface{}) Error { - parts := strings.FieldsFunc(key, func(c rune) bool { - return !unicode.IsLetter(c) && !unicode.IsNumber(c) - }) - k := strings.ToLower(strings.Join(parts, "_")) - if k == "error" || k == "error_op" { - // Never overwrite these - return e - } - switch actual := value.(type) { - case string, int, bool, time.Time: - e.data[k] = actual - default: - e.data[k] = fmt.Sprint(actual) - } - return e -} - -func (e *structured) RootCause() error { - if e.cause == nil { - if e.wrapped != nil { - return e.wrapped - } - return e - } - return e.cause.RootCause() -} - -func (e *structured) ErrorClean() string { - return e.data["error"].(string) -} - -// Error satisfies the error interface -func (e *structured) Error() string { - return e.data["error_text"].(string) + e.hiddenID -} - -func (e *structured) MultiLinePrinter() func(buf *bytes.Buffer) bool { - first := true - indent := false - err := e - stackPosition := 0 - switchedCause := false - return func(buf *bytes.Buffer) bool { - if indent { - buf.WriteString(" ") - } - if first { - buf.WriteString(e.Error()) - first = false - indent = true - return true - } - if switchedCause { - fmt.Fprintf(buf, "Caused by: %v", err) - if err.callStack != nil && len(err.callStack) > 0 { - switchedCause = false - indent = true - return true - } - if err.cause == nil { - return false - } - err = err.cause.(*structured) - return true - } - if stackPosition < len(err.callStack) { - buf.WriteString("at ") - call := err.callStack[stackPosition] - fmt.Fprintf(buf, "%+n (%s:%d)", call, call, call) - stackPosition++ - } - if stackPosition >= len(err.callStack) { - switch cause := err.cause.(type) { - case *structured: - err = cause - indent = false - stackPosition = 0 - switchedCause = true - default: - return false - } - } - return err != nil - } -} - -func wrapSkipFrames(err error, skip int) Error { - if err == nil { - return nil - } - - // Look for *structureds - if e, ok := err.(*structured); ok { - return e - } - - var cause Error - // Look for hidden *structureds - hiddenIDs, err2 := hidden.Extract(err.Error()) - if err2 == nil && len(hiddenIDs) > 0 { - // Take the first hidden ID as our cause - cause = get(hiddenIDs[0]) - } - - // Create a new *structured - return buildError("", "", err, cause) -} - -func (e *structured) attachStack(skip int) { - call := stack.Caller(skip) - e.callStack = stack.Trace().TrimBelow(call) - e.data["error_location"] = fmt.Sprintf("%+n (%s:%d)", call, call, call) -} - -func buildError(desc string, fullText string, wrapped error, cause Error) *structured { - e := &structured{ - data: make(context.Map), - // We capture the current context to allow it to propagate to higher layers. - context: ops.AsMap(nil, false), - wrapped: wrapped, - cause: cause, - } - e.save() - - errorType := "errors.Error" - if wrapped != nil { - op, goType, wrappedDesc, extra := parseError(wrapped) - if desc == "" { - desc = wrappedDesc - } - e.Op(op) - errorType = goType - if extra != nil { - for key, value := range extra { - e.data[key] = value - } - } - } - - cleanedDesc := hidden.Clean(desc) - e.data["error"] = cleanedDesc - if fullText != "" { - e.data["error_text"] = hidden.Clean(fullText) - } else { - e.data["error_text"] = cleanedDesc - } - e.data["error_type"] = errorType - - return e -} - -func parseError(err error) (op string, goType string, desc string, extra map[string]string) { - extra = make(map[string]string) - - // interfaces - if _, ok := err.(net.Error); ok { - if opError, ok := err.(*net.OpError); ok { - op = opError.Op - if opError.Source != nil { - extra["remote_addr"] = opError.Source.String() - } - if opError.Addr != nil { - extra["local_addr"] = opError.Addr.String() - } - extra["network"] = opError.Net - err = opError.Err - } - switch actual := err.(type) { - case *net.AddrError: - goType = "net.AddrError" - desc = actual.Err - extra["addr"] = actual.Addr - case *net.DNSError: - goType = "net.DNSError" - desc = actual.Err - extra["domain"] = actual.Name - if actual.Server != "" { - extra["dns_server"] = actual.Server - } - case *net.InvalidAddrError: - goType = "net.InvalidAddrError" - desc = actual.Error() - case *net.ParseError: - goType = "net.ParseError" - desc = "invalid " + actual.Type - extra["text_to_parse"] = actual.Text - case net.UnknownNetworkError: - goType = "net.UnknownNetworkError" - desc = "unknown network" - case syscall.Errno: - goType = "syscall.Errno" - desc = actual.Error() - case *url.Error: - goType = "url.Error" - desc = actual.Err.Error() - op = actual.Op - default: - goType = reflect.TypeOf(err).String() - desc = err.Error() - } - return - } - if _, ok := err.(runtime.Error); ok { - desc = err.Error() - switch err.(type) { - case *runtime.TypeAssertionError: - goType = "runtime.TypeAssertionError" - default: - goType = reflect.TypeOf(err).String() - } - return - } - - // structs - switch actual := err.(type) { - case *http.ProtocolError: - desc = actual.ErrorString - if name, ok := httpProtocolErrors[err]; ok { - goType = name - } else { - goType = "http.ProtocolError" - } - case url.EscapeError, *url.EscapeError: - goType = "url.EscapeError" - desc = "invalid URL escape" - case url.InvalidHostError, *url.InvalidHostError: - goType = "url.InvalidHostError" - desc = "invalid character in host name" - case *textproto.Error: - goType = "textproto.Error" - desc = actual.Error() - case textproto.ProtocolError, *textproto.ProtocolError: - goType = "textproto.ProtocolError" - desc = actual.Error() - - case tls.RecordHeaderError: - goType = "tls.RecordHeaderError" - desc = actual.Msg - extra["header"] = hex.EncodeToString(actual.RecordHeader[:]) - case x509.CertificateInvalidError: - goType = "x509.CertificateInvalidError" - desc = actual.Error() - case x509.ConstraintViolationError: - goType = "x509.ConstraintViolationError" - desc = actual.Error() - case x509.HostnameError: - goType = "x509.HostnameError" - desc = actual.Error() - extra["host"] = actual.Host - case x509.InsecureAlgorithmError: - goType = "x509.InsecureAlgorithmError" - desc = actual.Error() - case x509.SystemRootsError: - goType = "x509.SystemRootsError" - desc = actual.Error() - case x509.UnhandledCriticalExtension: - goType = "x509.UnhandledCriticalExtension" - desc = actual.Error() - case x509.UnknownAuthorityError: - goType = "x509.UnknownAuthorityError" - desc = actual.Error() - case hex.InvalidByteError: - goType = "hex.InvalidByteError" - desc = "invalid byte" - case *json.InvalidUTF8Error: - goType = "json.InvalidUTF8Error" - desc = "invalid UTF-8 in string" - case *json.InvalidUnmarshalError: - goType = "json.InvalidUnmarshalError" - desc = actual.Error() - case *json.MarshalerError: - goType = "json.MarshalerError" - desc = actual.Error() - case *json.SyntaxError: - goType = "json.SyntaxError" - desc = actual.Error() - case *json.UnmarshalFieldError: - goType = "json.UnmarshalFieldError" - desc = actual.Error() - case *json.UnmarshalTypeError: - goType = "json.UnmarshalTypeError" - desc = actual.Error() - case *json.UnsupportedTypeError: - goType = "json.UnsupportedTypeError" - desc = actual.Error() - case *json.UnsupportedValueError: - goType = "json.UnsupportedValueError" - desc = actual.Error() - - case *os.LinkError: - goType = "os.LinkError" - desc = actual.Error() - case *os.PathError: - goType = "os.PathError" - op = actual.Op - desc = actual.Err.Error() - case *os.SyscallError: - goType = "os.SyscallError" - op = actual.Syscall - desc = actual.Err.Error() - case *exec.Error: - goType = "exec.Error" - desc = actual.Err.Error() - case *exec.ExitError: - goType = "exec.ExitError" - desc = actual.Error() - // TODO: limit the length - extra["stderr"] = string(actual.Stderr) - case *strconv.NumError: - goType = "strconv.NumError" - desc = actual.Err.Error() - extra["function"] = actual.Func - case *time.ParseError: - goType = "time.ParseError" - desc = actual.Message - default: - desc = err.Error() - if t, ok := miscErrors[err]; ok { - goType = t - return - } - goType = reflect.TypeOf(err).String() - } - return -} - -var httpProtocolErrors = map[error]string{ - http.ErrHeaderTooLong: "http.ErrHeaderTooLong", - http.ErrShortBody: "http.ErrShortBody", - http.ErrNotSupported: "http.ErrNotSupported", - http.ErrUnexpectedTrailer: "http.ErrUnexpectedTrailer", - http.ErrMissingContentLength: "http.ErrMissingContentLength", - http.ErrNotMultipart: "http.ErrNotMultipart", - http.ErrMissingBoundary: "http.ErrMissingBoundary", -} - -var miscErrors = map[error]string{ - bufio.ErrInvalidUnreadByte: "bufio.ErrInvalidUnreadByte", - bufio.ErrInvalidUnreadRune: "bufio.ErrInvalidUnreadRune", - bufio.ErrBufferFull: "bufio.ErrBufferFull", - bufio.ErrNegativeCount: "bufio.ErrNegativeCount", - bufio.ErrTooLong: "bufio.ErrTooLong", - bufio.ErrNegativeAdvance: "bufio.ErrNegativeAdvance", - bufio.ErrAdvanceTooFar: "bufio.ErrAdvanceTooFar", - bufio.ErrFinalToken: "bufio.ErrFinalToken", - - http.ErrWriteAfterFlush: "http.ErrWriteAfterFlush", - http.ErrBodyNotAllowed: "http.ErrBodyNotAllowed", - http.ErrHijacked: "http.ErrHijacked", - http.ErrContentLength: "http.ErrContentLength", - http.ErrBodyReadAfterClose: "http.ErrBodyReadAfterClose", - http.ErrHandlerTimeout: "http.ErrHandlerTimeout", - http.ErrLineTooLong: "http.ErrLineTooLong", - http.ErrMissingFile: "http.ErrMissingFile", - http.ErrNoCookie: "http.ErrNoCookie", - http.ErrNoLocation: "http.ErrNoLocation", - http.ErrSkipAltProtocol: "http.ErrSkipAltProtocol", - - io.EOF: "io.EOF", - io.ErrClosedPipe: "io.ErrClosedPipe", - io.ErrNoProgress: "io.ErrNoProgress", - io.ErrShortBuffer: "io.ErrShortBuffer", - io.ErrShortWrite: "io.ErrShortWrite", - io.ErrUnexpectedEOF: "io.ErrUnexpectedEOF", - - os.ErrInvalid: "os.ErrInvalid", - os.ErrPermission: "os.ErrPermission", - os.ErrExist: "os.ErrExist", - os.ErrNotExist: "os.ErrNotExist", - - exec.ErrNotFound: "exec.ErrNotFound", - - x509.ErrUnsupportedAlgorithm: "x509.ErrUnsupportedAlgorithm", - x509.IncorrectPasswordError: "x509.IncorrectPasswordError", - - hex.ErrLength: "hex.ErrLength", -} diff --git a/vendor/github.com/getlantern/errors/hide.go b/vendor/github.com/getlantern/errors/hide.go deleted file mode 100644 index f10d863f..00000000 --- a/vendor/github.com/getlantern/errors/hide.go +++ /dev/null @@ -1,50 +0,0 @@ -package errors - -import ( - "encoding/binary" - "sync" - - "github.com/getlantern/hidden" -) - -var ( - hiddenErrors = make([]*structured, 100) - nextID = uint64(0) - hiddenMutex sync.RWMutex -) - -// This trick saves the error to a ring buffer and embeds a non-printing -// hiddenID in the error's description, so that if the errors is later wrapped -// by a standard error using something like -// fmt.Errorf("An error occurred: %v", thisError), we can subsequently extract -// the error simply using the hiddenID in the string. -func (e *structured) save() { - hiddenMutex.Lock() - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, nextID) - e.id = nextID - e.hiddenID = hidden.ToString(b) - hiddenErrors[idxForID(nextID)] = e - nextID++ - hiddenMutex.Unlock() -} - -func get(hiddenID []byte) Error { - if len(hiddenID) != 8 { - return nil - } - id := binary.BigEndian.Uint64(hiddenID) - hiddenMutex.RLock() - err := hiddenErrors[idxForID(id)] - hiddenMutex.RUnlock() - if err != nil && err.id == id { - // Found it! - return err - } - // buffer has rolled over - return nil -} - -func idxForID(id uint64) int { - return int(id % uint64(len(hiddenErrors))) -} diff --git a/vendor/github.com/getlantern/golog/.travis.yml b/vendor/github.com/getlantern/golog/.travis.yml deleted file mode 100644 index ab6a7f91..00000000 --- a/vendor/github.com/getlantern/golog/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go - -go: - - 1.4.1 - -install: - - go get -d -t -v ./... - - go build -v ./... - - go get golang.org/x/tools/cmd/cover - - go get -v github.com/axw/gocov/gocov - - go get -v github.com/mattn/goveralls - -script: - - $HOME/gopath/bin/goveralls -v -service travis-ci github.com/getlantern/golog \ No newline at end of file diff --git a/vendor/github.com/getlantern/golog/LICENSE b/vendor/github.com/getlantern/golog/LICENSE deleted file mode 100644 index 3ee01626..00000000 --- a/vendor/github.com/getlantern/golog/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2014 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/golog/README.md b/vendor/github.com/getlantern/golog/README.md deleted file mode 100644 index 88fe677d..00000000 --- a/vendor/github.com/getlantern/golog/README.md +++ /dev/null @@ -1,6 +0,0 @@ -golog [![Travis CI Status](https://travis-ci.org/getlantern/golog.svg?branch=master)](https://travis-ci.org/getlantern/golog) [![Coverage Status](https://coveralls.io/repos/getlantern/golog/badge.png)](https://coveralls.io/r/getlantern/golog) [![GoDoc](https://godoc.org/github.com/getlantern/golog?status.png)](http://godoc.org/github.com/getlantern/golog) -========== -Provides logging used in many getlantern components. - -[GoDoc](https://godoc.org/github.com/getlantern/golog) - diff --git a/vendor/github.com/getlantern/golog/golog.go b/vendor/github.com/getlantern/golog/golog.go deleted file mode 100644 index 78683410..00000000 --- a/vendor/github.com/getlantern/golog/golog.go +++ /dev/null @@ -1,473 +0,0 @@ -// Package golog implements logging functions that log errors to stderr and -// debug messages to stdout. Trace logging is also supported. -// Trace logs go to stdout as well, but they are only written if the program -// is run with environment variable "TRACE=true". -// A stack dump will be printed after the message if "PRINT_STACK=true". -package golog - -import ( - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "log" - "os" - "path/filepath" - "runtime" - "sort" - "strconv" - "strings" - "sync" - "sync/atomic" - - "github.com/getlantern/errors" - "github.com/getlantern/hidden" - "github.com/getlantern/ops" - "github.com/oxtoacart/bpool" -) - -const ( - // ERROR is an error Severity - ERROR = 500 - - // FATAL is an error Severity - FATAL = 600 -) - -var ( - outs atomic.Value - prepender atomic.Value - reporters []ErrorReporter - reportersMutex sync.RWMutex - - bufferPool = bpool.NewBufferPool(200) - - onFatal atomic.Value -) - -// Severity is a level of error (higher values are more severe) -type Severity int - -func (s Severity) String() string { - switch s { - case ERROR: - return "ERROR" - case FATAL: - return "FATAL" - default: - return "UNKNOWN" - } -} - -func init() { - DefaultOnFatal() - ResetOutputs() - ResetPrepender() -} - -// SetPrepender sets a function to write something, e.g., the timestamp, before -// each line of the log. -func SetPrepender(p func(io.Writer)) { - prepender.Store(p) -} - -func ResetPrepender() { - SetPrepender(func(io.Writer) {}) -} - -func GetPrepender() func(io.Writer) { - return prepender.Load().(func(io.Writer)) -} - -func SetOutputs(errorOut io.Writer, debugOut io.Writer) { - outs.Store(&outputs{ - ErrorOut: errorOut, - DebugOut: debugOut, - }) -} - -func ResetOutputs() { - SetOutputs(os.Stderr, os.Stdout) -} - -func GetOutputs() *outputs { - return outs.Load().(*outputs) -} - -// RegisterReporter registers the given ErrorReporter. All logged Errors are -// sent to this reporter. -func RegisterReporter(reporter ErrorReporter) { - reportersMutex.Lock() - reporters = append(reporters, reporter) - reportersMutex.Unlock() -} - -// OnFatal configures golog to call the given function on any FATAL error. By -// default, golog calls os.Exit(1) on any FATAL error. -func OnFatal(fn func(err error)) { - onFatal.Store(fn) -} - -// DefaultOnFatal enables the default behavior for OnFatal -func DefaultOnFatal() { - onFatal.Store(func(err error) { - os.Exit(1) - }) -} - -type outputs struct { - ErrorOut io.Writer - DebugOut io.Writer -} - -// MultiLine is an interface for arguments that support multi-line output. -type MultiLine interface { - // MultiLinePrinter returns a function that can be used to print the - // multi-line output. The returned function writes one line to the buffer and - // returns true if there are more lines to write. This function does not need - // to take care of trailing carriage returns, golog handles that - // automatically. - MultiLinePrinter() func(buf *bytes.Buffer) bool -} - -// ErrorReporter is a function to which the logger will report errors. -// It the given error and corresponding message along with associated ops -// context. This should return quickly as it executes on the critical code -// path. The recommended approach is to buffer as much as possible and discard -// new reports if the buffer becomes saturated. -type ErrorReporter func(err error, severity Severity, ctx map[string]interface{}) - -type Logger interface { - // Debug logs to stdout - Debug(arg interface{}) - // Debugf logs to stdout - Debugf(message string, args ...interface{}) - - // Error logs to stderr - Error(arg interface{}) error - // Errorf logs to stderr. It returns the first argument that's an error, or - // a new error built using fmt.Errorf if none of the arguments are errors. - Errorf(message string, args ...interface{}) error - - // Fatal logs to stderr and then exits with status 1 - Fatal(arg interface{}) - // Fatalf logs to stderr and then exits with status 1 - Fatalf(message string, args ...interface{}) - - // Trace logs to stderr only if TRACE=true - Trace(arg interface{}) - // Tracef logs to stderr only if TRACE=true - Tracef(message string, args ...interface{}) - - // TraceOut provides access to an io.Writer to which trace information can - // be streamed. If running with environment variable "TRACE=true", TraceOut - // will point to os.Stderr, otherwise it will point to a ioutil.Discared. - // Each line of trace information will be prefixed with this Logger's - // prefix. - TraceOut() io.Writer - - // IsTraceEnabled() indicates whether or not tracing is enabled for this - // logger. - IsTraceEnabled() bool - - // AsStdLogger returns an standard logger - AsStdLogger() *log.Logger -} - -func LoggerFor(prefix string) Logger { - l := &logger{ - prefix: prefix + ": ", - pc: make([]uintptr, 10), - } - - trace := os.Getenv("TRACE") - l.traceOn, _ = strconv.ParseBool(trace) - if !l.traceOn { - prefixes := strings.Split(trace, ",") - for _, p := range prefixes { - if prefix == strings.Trim(p, " ") { - l.traceOn = true - break - } - } - } - if l.traceOn { - l.traceOut = l.newTraceWriter() - } else { - l.traceOut = ioutil.Discard - } - - printStack := os.Getenv("PRINT_STACK") - l.printStack, _ = strconv.ParseBool(printStack) - - return l -} - -type logger struct { - prefix string - traceOn bool - traceOut io.Writer - printStack bool - outs atomic.Value - pc []uintptr - funcForPc *runtime.Func -} - -// attaches the file and line number corresponding to -// the log message -func (l *logger) linePrefix(skipFrames int) string { - runtime.Callers(skipFrames, l.pc) - funcForPc := runtime.FuncForPC(l.pc[0]) - file, line := funcForPc.FileLine(l.pc[0] - 1) - return fmt.Sprintf("%s%s:%d ", l.prefix, filepath.Base(file), line) -} - -func (l *logger) print(out io.Writer, skipFrames int, severity string, arg interface{}) { - buf := bufferPool.Get() - defer bufferPool.Put(buf) - - GetPrepender()(buf) - linePrefix := l.linePrefix(skipFrames) - writeHeader := func() { - buf.WriteString(severity) - buf.WriteString(" ") - buf.WriteString(linePrefix) - } - if arg != nil { - ml, isMultiline := arg.(MultiLine) - if !isMultiline { - writeHeader() - fmt.Fprintf(buf, "%v", arg) - printContext(buf, arg) - buf.WriteByte('\n') - } else { - mlp := ml.MultiLinePrinter() - first := true - for { - writeHeader() - more := mlp(buf) - if first { - printContext(buf, arg) - first = false - } - buf.WriteByte('\n') - if !more { - break - } - } - } - } - b := []byte(hidden.Clean(buf.String())) - _, err := out.Write(b) - if err != nil { - errorOnLogging(err) - } - if l.printStack { - l.doPrintStack() - } -} - -func (l *logger) printf(out io.Writer, skipFrames int, severity string, err error, message string, args ...interface{}) { - buf := bufferPool.Get() - defer bufferPool.Put(buf) - - GetPrepender()(buf) - linePrefix := l.linePrefix(skipFrames) - buf.WriteString(severity) - buf.WriteString(" ") - buf.WriteString(linePrefix) - fmt.Fprintf(buf, message, args...) - printContext(buf, err) - buf.WriteByte('\n') - b := []byte(hidden.Clean(buf.String())) - _, err2 := out.Write(b) - if err2 != nil { - errorOnLogging(err2) - } - if l.printStack { - l.doPrintStack() - } -} - -func (l *logger) Debug(arg interface{}) { - l.print(GetOutputs().DebugOut, 4, "DEBUG", arg) -} - -func (l *logger) Debugf(message string, args ...interface{}) { - l.printf(GetOutputs().DebugOut, 4, "DEBUG", nil, message, args...) -} - -func (l *logger) Error(arg interface{}) error { - return l.errorSkipFrames(arg, 1, ERROR) -} - -func (l *logger) Errorf(message string, args ...interface{}) error { - return l.errorSkipFrames(errors.NewOffset(1, message, args...), 1, ERROR) -} - -func (l *logger) Fatal(arg interface{}) { - fatal(l.errorSkipFrames(arg, 1, FATAL)) -} - -func (l *logger) Fatalf(message string, args ...interface{}) { - fatal(l.errorSkipFrames(errors.NewOffset(1, message, args...), 1, FATAL)) -} - -func fatal(err error) { - fn := onFatal.Load().(func(err error)) - fn(err) -} - -func (l *logger) errorSkipFrames(arg interface{}, skipFrames int, severity Severity) error { - var err error - switch e := arg.(type) { - case error: - err = e - default: - err = fmt.Errorf("%v", e) - } - l.print(GetOutputs().ErrorOut, skipFrames+4, severity.String(), err) - return report(err, severity) -} - -func (l *logger) Trace(arg interface{}) { - if l.traceOn { - l.print(GetOutputs().DebugOut, 4, "TRACE", arg) - } -} - -func (l *logger) Tracef(message string, args ...interface{}) { - if l.traceOn { - l.printf(GetOutputs().DebugOut, 4, "TRACE", nil, message, args...) - } -} - -func (l *logger) TraceOut() io.Writer { - return l.traceOut -} - -func (l *logger) IsTraceEnabled() bool { - return l.traceOn -} - -func (l *logger) newTraceWriter() io.Writer { - pr, pw := io.Pipe() - br := bufio.NewReader(pr) - - if !l.traceOn { - return pw - } - go func() { - defer func() { - if err := pr.Close(); err != nil { - errorOnLogging(err) - } - }() - defer func() { - if err := pw.Close(); err != nil { - errorOnLogging(err) - } - }() - - for { - line, err := br.ReadString('\n') - if err == nil { - // Log the line (minus the trailing newline) - l.print(GetOutputs().DebugOut, 6, "TRACE", line[:len(line)-1]) - } else { - l.printf(GetOutputs().DebugOut, 6, "TRACE", nil, "TraceWriter closed due to unexpected error: %v", err) - return - } - } - }() - - return pw -} - -type errorWriter struct { - l *logger -} - -// Write implements method of io.Writer, due to different call depth, -// it will not log correct file and line prefix -func (w *errorWriter) Write(p []byte) (n int, err error) { - s := string(p) - if s[len(s)-1] == '\n' { - s = s[:len(s)-1] - } - w.l.print(GetOutputs().ErrorOut, 6, "ERROR", s) - return len(p), nil -} - -func (l *logger) AsStdLogger() *log.Logger { - return log.New(&errorWriter{l}, "", 0) -} - -func (l *logger) doPrintStack() { - var b []byte - buf := bytes.NewBuffer(b) - for _, pc := range l.pc { - funcForPc := runtime.FuncForPC(pc) - if funcForPc == nil { - break - } - name := funcForPc.Name() - if strings.HasPrefix(name, "runtime.") { - break - } - file, line := funcForPc.FileLine(pc) - fmt.Fprintf(buf, "\t%s\t%s: %d\n", name, file, line) - } - if _, err := buf.WriteTo(os.Stderr); err != nil { - errorOnLogging(err) - } -} - -func errorOnLogging(err error) { - fmt.Fprintf(os.Stderr, "Unable to log: %v\n", err) -} - -func printContext(buf *bytes.Buffer, err interface{}) { - // Note - we don't include globals when printing in order to avoid polluting the text log - values := ops.AsMap(err, false) - if len(values) == 0 { - return - } - buf.WriteString(" [") - var keys []string - for key := range values { - keys = append(keys, key) - } - sort.Strings(keys) - for i, key := range keys { - value := values[key] - if i > 0 { - buf.WriteString(" ") - } - buf.WriteString(key) - buf.WriteString("=") - fmt.Fprintf(buf, "%v", value) - } - buf.WriteByte(']') -} - -func report(err error, severity Severity) error { - var reportersCopy []ErrorReporter - reportersMutex.RLock() - if len(reporters) > 0 { - reportersCopy = make([]ErrorReporter, len(reporters)) - copy(reportersCopy, reporters) - } - reportersMutex.RUnlock() - - if len(reportersCopy) > 0 { - ctx := ops.AsMap(err, true) - ctx["severity"] = severity.String() - for _, reporter := range reportersCopy { - // We include globals when reporting - reporter(err, severity, ctx) - } - } - return err -} diff --git a/vendor/github.com/getlantern/hex/LICENSE b/vendor/github.com/getlantern/hex/LICENSE deleted file mode 100644 index 966192d2..00000000 --- a/vendor/github.com/getlantern/hex/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2009 The Go Authors. -Copyright (c) 2016 Brave New Software Project, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/getlantern/hex/hex.go b/vendor/github.com/getlantern/hex/hex.go deleted file mode 100644 index dc9c5462..00000000 --- a/vendor/github.com/getlantern/hex/hex.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2009 The Go Authors. -// Copyright 2016 Brave New Software Project, Inc. -// All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package hex implements hexadecimal encoding and decoding. It's taken almost -// verbatim from golang/encoding/hex, however it allows using a different set -// of encoding characters than the standard 0-F. -package hex - -import ( - "errors" - "fmt" -) - -// DefaultEncoding behaves just like golang/encoding/hex. -var DefaultEncoding = NewEncoding("0123456789abcdef") - -// An Encoding that uses a specific table of encoding characters. -type Encoding struct { - hextable string -} - -// NewEncoding constructs an Encoding using the given hextable. -func NewEncoding(hextable string) *Encoding { - return &Encoding{hextable} -} - -// EncodedLen returns the length of an encoding of n source bytes. -func EncodedLen(n int) int { return n * 2 } - -// Encode encodes src into EncodedLen(len(src)) -// bytes of dst. As a convenience, it returns the number -// of bytes written to dst, but this value is always EncodedLen(len(src)). -// Encode implements hexadecimal encoding. -func (e *Encoding) Encode(dst, src []byte) int { - for i, v := range src { - dst[i*2] = e.hextable[v>>4] - dst[i*2+1] = e.hextable[v&0x0f] - } - - return len(src) * 2 -} - -// ErrLength results from decoding an odd length slice. -var ErrLength = errors.New("encoding/hex: odd length hex string") - -// InvalidByteError values describe errors resulting from an invalid byte in a hex string. -type InvalidByteError byte - -func (e InvalidByteError) Error() string { - return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e)) -} - -func DecodedLen(x int) int { return x / 2 } - -// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual -// number of bytes written to dst. -// -// If Decode encounters invalid input, it returns an error describing the failure. -func (e *Encoding) Decode(dst, src []byte) (int, error) { - if len(src)%2 == 1 { - return 0, ErrLength - } - - for i := 0; i < len(src)/2; i++ { - a, ok := e.fromHexChar(src[i*2]) - if !ok { - return 0, InvalidByteError(src[i*2]) - } - b, ok := e.fromHexChar(src[i*2+1]) - if !ok { - return 0, InvalidByteError(src[i*2+1]) - } - dst[i] = (a << 4) | b - } - - return len(src) / 2, nil -} - -// fromHexChar converts a hex character into its value and a success flag. -func (e *Encoding) fromHexChar(c byte) (byte, bool) { - for i, ch := range []byte(e.hextable) { - if ch == c { - return byte(i), true - } - } - - return 0, false -} - -// EncodeToString returns the hexadecimal encoding of src. -func (e *Encoding) EncodeToString(src []byte) string { - dst := make([]byte, EncodedLen(len(src))) - e.Encode(dst, src) - return string(dst) -} - -// DecodeString returns the bytes represented by the hexadecimal string s. -func (e *Encoding) DecodeString(s string) ([]byte, error) { - src := []byte(s) - dst := make([]byte, DecodedLen(len(src))) - _, err := e.Decode(dst, src) - if err != nil { - return nil, err - } - return dst, nil -} diff --git a/vendor/github.com/getlantern/hidden/LICENSE b/vendor/github.com/getlantern/hidden/LICENSE deleted file mode 100644 index 5dc6c268..00000000 --- a/vendor/github.com/getlantern/hidden/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2016 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/hidden/hidden.go b/vendor/github.com/getlantern/hidden/hidden.go deleted file mode 100644 index 0c52b08e..00000000 --- a/vendor/github.com/getlantern/hidden/hidden.go +++ /dev/null @@ -1,66 +0,0 @@ -// Package hidden provides the ability to "hide" binary data in a string using -// a hex encoding with non-printing characters. Hidden data is demarcated with -// a leading and trailing NUL character. -package hidden - -import ( - "bytes" - "fmt" - "regexp" - - "github.com/getlantern/hex" -) - -// 16 non-printing characters -const hextable = "\x01\x02\x03\x04\x05\x06\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17" - -var ( - hexencoding = hex.NewEncoding(hextable) - - re *regexp.Regexp -) - -func init() { - var err error - re, err = regexp.Compile(fmt.Sprintf("\x00[%v]+\x00", hextable)) - if err != nil { - panic(err) - } -} - -// ToString encodes the given data as a hidden string, including leadnig and -// trailing NULs. -func ToString(data []byte) string { - buf := bytes.NewBuffer(make([]byte, 0, 2+hex.EncodedLen(len(data)))) - // Leading NUL - buf.WriteByte(0) - buf.WriteString(hexencoding.EncodeToString(data)) - // Trailing NUL - buf.WriteByte(0) - return buf.String() -} - -// FromString extracts the hidden data from a string, which is expected to -// contain leading and trailing NULs. -func FromString(str string) ([]byte, error) { - return hexencoding.DecodeString(str[1 : len(str)-1]) -} - -// Extract extracts all hidden data from an arbitrary string. -func Extract(str string) ([][]byte, error) { - m := re.FindAllString(str, -1) - result := make([][]byte, 0, len(m)) - for _, s := range m { - b, err := FromString(s) - if err != nil { - return nil, err - } - result = append(result, b) - } - return result, nil -} - -// Clean removes any hidden data from an arbitrary string. -func Clean(str string) string { - return re.ReplaceAllString(str, "") -} diff --git a/vendor/github.com/getlantern/ops/LICENSE b/vendor/github.com/getlantern/ops/LICENSE deleted file mode 100644 index 0c6ff7d3..00000000 --- a/vendor/github.com/getlantern/ops/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2017 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/ops/ops.go b/vendor/github.com/getlantern/ops/ops.go deleted file mode 100644 index 136302db..00000000 --- a/vendor/github.com/getlantern/ops/ops.go +++ /dev/null @@ -1,154 +0,0 @@ -// Package ops provides a facility for tracking the processing of operations, -// including contextual metadata about the operation and their final success or -// failure. An op is assumed to have succeeded if by the time of calling Exit() -// no errors have been reported. The final status can be reported to a metrics -// facility. -package ops - -import ( - "sync" - "sync/atomic" - - "github.com/getlantern/context" -) - -var ( - cm = context.NewManager() - reporters []Reporter - reportersMutex sync.RWMutex -) - -// Reporter is a function that reports the success or failure of an Op. If -// failure is nil, the Op can be considered successful. -type Reporter func(failure error, ctx map[string]interface{}) - -// Op represents an operation that's being performed. It mimics the API of -// context.Context. -type Op interface { - // Begin marks the beginning of an Op under this Op. - Begin(name string) Op - - // Go starts the given function on a new goroutine. - Go(fn func()) - - // End marks the end of this op, at which point the Op will report its success - // or failure to all registered Reporters. - End() - - // Cancel cancels this op so that even if End() is called later, it will not - // report its success or failure. - Cancel() - - // Set puts a key->value pair into the current Op's context. - Set(key string, value interface{}) Op - - // SetDynamic puts a key->value pair into the current Op's context, where the - // value is generated by a function that gets evaluated at every Read. - SetDynamic(key string, valueFN func() interface{}) Op - - // FailIf marks this Op as failed if the given err is not nil. If FailIf is - // called multiple times, the latest error will be reported as the failure. - // Returns the original error for convenient chaining. - FailIf(err error) error -} - -type op struct { - ctx context.Context - canceled bool - failure atomic.Value -} - -// RegisterReporter registers the given reporter. -func RegisterReporter(reporter Reporter) { - reportersMutex.Lock() - reporters = append(reporters, reporter) - reportersMutex.Unlock() -} - -// Begin marks the beginning of a new Op. -func Begin(name string) Op { - return &op{ctx: cm.Enter().Put("op", name).PutIfAbsent("root_op", name)} -} - -func (o *op) Begin(name string) Op { - return &op{ctx: o.ctx.Enter().Put("op", name).PutIfAbsent("root_op", name)} -} - -func (o *op) Go(fn func()) { - o.ctx.Go(fn) -} - -// Go mimics the method from context.Manager. -func Go(fn func()) { - cm.Go(fn) -} - -func (o *op) Cancel() { - o.canceled = true -} - -func (o *op) End() { - if o.canceled { - return - } - - var reportersCopy []Reporter - reportersMutex.RLock() - if len(reporters) > 0 { - reportersCopy = make([]Reporter, len(reporters)) - copy(reportersCopy, reporters) - } - reportersMutex.RUnlock() - - if len(reportersCopy) > 0 { - var failure error - _failure := o.failure.Load() - ctx := o.ctx.AsMap(_failure, true) - if _failure != nil { - failure = _failure.(error) - _, errorSet := ctx["error"] - if !errorSet { - ctx["error"] = failure.Error() - } - } - for _, reporter := range reportersCopy { - reporter(failure, ctx) - } - } - - o.ctx.Exit() -} - -func (o *op) Set(key string, value interface{}) Op { - o.ctx.Put(key, value) - return o -} - -// SetGlobal puts a key->value pair into the global context, which is inherited -// by all Ops. -func SetGlobal(key string, value interface{}) { - cm.PutGlobal(key, value) -} - -func (o *op) SetDynamic(key string, valueFN func() interface{}) Op { - o.ctx.PutDynamic(key, valueFN) - return o -} - -// SetGlobalDynamic is like SetGlobal but uses a function to derive the value -// at read time. -func SetGlobalDynamic(key string, valueFN func() interface{}) { - cm.PutGlobalDynamic(key, valueFN) -} - -// AsMap mimics the method from context.Manager. -func AsMap(obj interface{}, includeGlobals bool) context.Map { - return cm.AsMap(obj, includeGlobals) -} - -func (o *op) FailIf(err error) error { - if err != nil { - o.failure.Store(err) - } - return err -} diff --git a/vendor/github.com/getlantern/systray/.gitignore b/vendor/github.com/getlantern/systray/.gitignore deleted file mode 100644 index 2e85ef69..00000000 --- a/vendor/github.com/getlantern/systray/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -example/example -webview_example/webview_example -*~ -*.swp -**/*.exe -Release -Debug -*.sdf -dll/systray_unsigned.dll -out.txt -.vs -on_exit*.txt diff --git a/vendor/github.com/getlantern/systray/CHANGELOG.md b/vendor/github.com/getlantern/systray/CHANGELOG.md deleted file mode 100644 index 6eaf134b..00000000 --- a/vendor/github.com/getlantern/systray/CHANGELOG.md +++ /dev/null @@ -1,137 +0,0 @@ -# Changelog - -## [v1.2.0](https://github.com/getlantern/systray/tree/v1.2.0) (2022-02-24) - -[Full Changelog](https://github.com/getlantern/systray/compare/v1.1.0...v1.2.0) - -** Merged pull requests:** - -- On Linux, set the title in addition to the label [\#200](https://github.com/getlantern/systray/pull/200) ([cocotyty](https://github.com/cocotyty)) -- Fix hiding/showing items with submenus on Windows [\#204](https://github.com/getlantern/systray/pull/204) ([simonlindholm](https://github.com/simonlindholm)) -- Fix delFromVisibleItems [\#205](https://github.com/getlantern/systray/pull/205) ([simonlindholm](https://github.com/simonlindholm)) -- Create menu before calling onReady on Windows [\#206](https://github.com/getlantern/systray/pull/206) ([simonlindholm](https://github.com/simonlindholm)) -- Support libayatana-appindicator on Linux [\#225](https://github.com/getlantern/systray/pull/225) ([Crosse](https://github.com/Crosse)) - -## [v1.1.0](https://github.com/getlantern/systray/tree/v1.1.0) (2020-11-18) - -[Full Changelog](https://github.com/getlantern/systray/compare/v1.0.5...v1.1.0) - -**Merged pull requests:** - -- Add submenu support for Linux [\#183](https://github.com/getlantern/systray/pull/183) ([fbrinker](https://github.com/fbrinker)) -- Add checkbox support for Linux [\#181](https://github.com/getlantern/systray/pull/181) ([fbrinker](https://github.com/fbrinker)) -- fix SetTitle documentation [\#179](https://github.com/getlantern/systray/pull/179) ([delthas](https://github.com/delthas)) - -## [v1.0.5](https://github.com/getlantern/systray/tree/v1.0.5) (2020-10-19) - -[Full Changelog](https://github.com/getlantern/systray/compare/v1.0.4...v1.0.5) - -**Merged pull requests:** - -- start menu ID with positive, and change the type to uint32 [\#173](https://github.com/getlantern/systray/pull/173) ([joesis](https://github.com/joesis)) -- Allows disabling items in submenu on macOS [\#172](https://github.com/getlantern/systray/pull/172) ([joesis](https://github.com/joesis)) -- Does not use the template icon for regular icons [\#171](https://github.com/getlantern/systray/pull/171) ([sithembiso](https://github.com/sithembiso)) - -## [v1.0.4](https://github.com/getlantern/systray/tree/v1.0.4) (2020-07-21) - -[Full Changelog](https://github.com/getlantern/systray/compare/1.0.3...v1.0.4) - -**Merged pull requests:** - -- protect shared data structures with proper mutexes [\#162](https://github.com/getlantern/systray/pull/162) ([joesis](https://github.com/joesis)) - -## [1.0.3](https://github.com/getlantern/systray/tree/1.0.3) (2020-06-11) - -[Full Changelog](https://github.com/getlantern/systray/compare/v1.0.3...1.0.3) - -## [v1.0.3](https://github.com/getlantern/systray/tree/v1.0.3) (2020-06-11) - -[Full Changelog](https://github.com/getlantern/systray/compare/v1.0.2...v1.0.3) - -**Merged pull requests:** - -- have a workaround to avoid crash on old macOS versions [\#153](https://github.com/getlantern/systray/pull/153) ([joesis](https://github.com/joesis)) -- Fix bug on darwin of setting icon for menu [\#147](https://github.com/getlantern/systray/pull/147) ([mangalaman93](https://github.com/mangalaman93)) - -## [v1.0.2](https://github.com/getlantern/systray/tree/v1.0.2) (2020-05-19) - -[Full Changelog](https://github.com/getlantern/systray/compare/v1.0.1...v1.0.2) - -**Merged pull requests:** - -- remove unused dependencies [\#145](https://github.com/getlantern/systray/pull/145) ([joesis](https://github.com/joesis)) - -## [v1.0.1](https://github.com/getlantern/systray/tree/v1.0.1) (2020-05-18) - -[Full Changelog](https://github.com/getlantern/systray/compare/1.0.1...v1.0.1) - -## [1.0.1](https://github.com/getlantern/systray/tree/1.0.1) (2020-05-18) - -[Full Changelog](https://github.com/getlantern/systray/compare/1.0.0...1.0.1) - -**Merged pull requests:** - -- Unlock menuItemsLock before changing UI [\#144](https://github.com/getlantern/systray/pull/144) ([joesis](https://github.com/joesis)) - -## [1.0.0](https://github.com/getlantern/systray/tree/1.0.0) (2020-05-18) - -[Full Changelog](https://github.com/getlantern/systray/compare/v1.0.0...1.0.0) - -## [v1.0.0](https://github.com/getlantern/systray/tree/v1.0.0) (2020-05-18) - -[Full Changelog](https://github.com/getlantern/systray/compare/0.9.0...v1.0.0) - -**Merged pull requests:** - -- Check if the menu item is nil [\#137](https://github.com/getlantern/systray/pull/137) ([myleshorton](https://github.com/myleshorton)) - -## [0.9.0](https://github.com/getlantern/systray/tree/0.9.0) (2020-03-24) - -[Full Changelog](https://github.com/getlantern/systray/compare/v0.9.0...0.9.0) - -## [v0.9.0](https://github.com/getlantern/systray/tree/v0.9.0) (2020-03-24) - -[Full Changelog](https://github.com/getlantern/systray/compare/8e63b37ef27d94f6db79c4ffb941608e8f0dc2f9...v0.9.0) - -**Merged pull requests:** - -- Backport all features and fixes from master [\#140](https://github.com/getlantern/systray/pull/140) ([joesis](https://github.com/joesis)) -- Nested menu windows [\#132](https://github.com/getlantern/systray/pull/132) ([joesis](https://github.com/joesis)) -- Support for nested sub-menus on OS X [\#131](https://github.com/getlantern/systray/pull/131) ([oxtoacart](https://github.com/oxtoacart)) -- Use temp directory for walk resource manager [\#129](https://github.com/getlantern/systray/pull/129) ([max-b](https://github.com/max-b)) -- Added support for template icons on macOS [\#119](https://github.com/getlantern/systray/pull/119) ([oxtoacart](https://github.com/oxtoacart)) -- When launching app window on macOS, make application a foreground app… [\#118](https://github.com/getlantern/systray/pull/118) ([oxtoacart](https://github.com/oxtoacart)) -- Include stdlib.h in systray\_browser\_linux to explicitly declare funct… [\#114](https://github.com/getlantern/systray/pull/114) ([oxtoacart](https://github.com/oxtoacart)) -- Fix panic when resources root path is not the working directory [\#112](https://github.com/getlantern/systray/pull/112) ([ksubileau](https://github.com/ksubileau)) -- Don't print close reason to console [\#111](https://github.com/getlantern/systray/pull/111) ([ksubileau](https://github.com/ksubileau)) -- Systray icon could not be changed dynamically [\#110](https://github.com/getlantern/systray/pull/110) ([ksubileau](https://github.com/ksubileau)) -- Preventing deadlock on menu item ClickeCh when no one is listening, c… [\#105](https://github.com/getlantern/systray/pull/105) ([oxtoacart](https://github.com/oxtoacart)) -- Reverted deadlock fix \(Affected other receivers\) [\#104](https://github.com/getlantern/systray/pull/104) ([ldstein](https://github.com/ldstein)) -- Fix Deadlock and item ordering in Windows [\#103](https://github.com/getlantern/systray/pull/103) ([ldstein](https://github.com/ldstein)) -- Minor README improvements \(go modules, example app, screenshot\) [\#98](https://github.com/getlantern/systray/pull/98) ([tstromberg](https://github.com/tstromberg)) -- Add support for app window [\#97](https://github.com/getlantern/systray/pull/97) ([oxtoacart](https://github.com/oxtoacart)) -- systray\_darwin.m: Compare Mac OS min version with value instead of macro [\#94](https://github.com/getlantern/systray/pull/94) ([teddywing](https://github.com/teddywing)) -- Attempt to fix https://github.com/getlantern/systray/issues/75 [\#92](https://github.com/getlantern/systray/pull/92) ([mikeschinkel](https://github.com/mikeschinkel)) -- Fix application path for MacOS in README [\#91](https://github.com/getlantern/systray/pull/91) ([zereraz](https://github.com/zereraz)) -- Document cross-platform console window details [\#81](https://github.com/getlantern/systray/pull/81) ([michaelsanford](https://github.com/michaelsanford)) -- Fix bad-looking system tray icon in Windows [\#78](https://github.com/getlantern/systray/pull/78) ([juja256](https://github.com/juja256)) -- Add the separator to the visible items [\#76](https://github.com/getlantern/systray/pull/76) ([meskio](https://github.com/meskio)) -- keep track of hidden items [\#74](https://github.com/getlantern/systray/pull/74) ([kalikaneko](https://github.com/kalikaneko)) -- Support macOS older than 10.13 [\#73](https://github.com/getlantern/systray/pull/73) ([swznd](https://github.com/swznd)) -- define ERROR\_SUCCESS as syscall.Errno [\#69](https://github.com/getlantern/systray/pull/69) ([joesis](https://github.com/joesis)) -- Bug/fix broken menuitem show [\#68](https://github.com/getlantern/systray/pull/68) ([kalikaneko](https://github.com/kalikaneko)) -- Fix mac deprecations [\#66](https://github.com/getlantern/systray/pull/66) ([jefvel](https://github.com/jefvel)) -- Made it possible to add icons to menu items on Mac [\#65](https://github.com/getlantern/systray/pull/65) ([jefvel](https://github.com/jefvel)) -- linux: delete temp files as soon as they are not needed [\#63](https://github.com/getlantern/systray/pull/63) ([meskio](https://github.com/meskio)) -- Merge changes from amkulikov to remove DLL for windows [\#56](https://github.com/getlantern/systray/pull/56) ([oxtoacart](https://github.com/oxtoacart)) -- Revert "Use templated icons for the menu bar in macOS" [\#51](https://github.com/getlantern/systray/pull/51) ([stoggi](https://github.com/stoggi)) -- Use templated icons for the menu bar in macOS [\#46](https://github.com/getlantern/systray/pull/46) ([stoggi](https://github.com/stoggi)) -- Syscalls instead of custom DLLs [\#44](https://github.com/getlantern/systray/pull/44) ([amkulikov](https://github.com/amkulikov)) -- On quit exit main loop on linux [\#41](https://github.com/getlantern/systray/pull/41) ([meskio](https://github.com/meskio)) -- Fixed hide show in linux \(\#37\) [\#39](https://github.com/getlantern/systray/pull/39) ([meskio](https://github.com/meskio)) -- fix: linux compilation warning [\#36](https://github.com/getlantern/systray/pull/36) ([novln](https://github.com/novln)) -- Added separator functionality [\#32](https://github.com/getlantern/systray/pull/32) ([oxtoacart](https://github.com/oxtoacart)) - - - -\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/vendor/github.com/getlantern/systray/LICENSE b/vendor/github.com/getlantern/systray/LICENSE deleted file mode 100644 index 3ee01626..00000000 --- a/vendor/github.com/getlantern/systray/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2014 Brave New Software Project, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/getlantern/systray/Makefile b/vendor/github.com/getlantern/systray/Makefile deleted file mode 100644 index 12f3d221..00000000 --- a/vendor/github.com/getlantern/systray/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -tag-changelog: require-version require-gh-token - echo "Tagging..." && \ - git tag -a "$$VERSION" -f --annotate -m"Tagged $$VERSION" && \ - git push --tags -f && \ - git checkout master && \ - git pull && \ - github_changelog_generator --no-issues --max-issues 100 --token "${GH_TOKEN}" --user getlantern --project systray && \ - git add CHANGELOG.md && \ - git commit -m "Updated changelog for $$VERSION" && \ - git push origin HEAD && \ - git checkout - - -guard-%: - @ if [ -z '${${*}}' ]; then echo 'Environment variable $* not set' && exit 1; fi - -require-version: guard-VERSION - -require-gh-token: guard-GH_TOKEN diff --git a/vendor/github.com/getlantern/systray/README.md b/vendor/github.com/getlantern/systray/README.md deleted file mode 100644 index 4cf166ed..00000000 --- a/vendor/github.com/getlantern/systray/README.md +++ /dev/null @@ -1,129 +0,0 @@ -systray is a cross-platform Go library to place an icon and menu in the notification area. - -## Features - -* Supported on Windows, macOS, and Linux -* Menu items can be checked and/or disabled -* Methods may be called from any Goroutine - -## API - -```go -func main() { - systray.Run(onReady, onExit) -} - -func onReady() { - systray.SetIcon(icon.Data) - systray.SetTitle("Awesome App") - systray.SetTooltip("Pretty awesome超级棒") - mQuit := systray.AddMenuItem("Quit", "Quit the whole app") - - // Sets the icon of a menu item. Only available on Mac and Windows. - mQuit.SetIcon(icon.Data) -} - -func onExit() { - // clean up here -} -``` - -See [full API](https://pkg.go.dev/github.com/getlantern/systray?tab=doc) as well as [CHANGELOG](https://github.com/getlantern/systray/tree/master/CHANGELOG.md). - -Note: this package requires cgo, so make sure you set `CGO_ENABLED=1` before building. - -## Try the example app! - -Have go v1.12+ or higher installed? Here's an example to get started on macOS: - -```sh -git clone https://github.com/getlantern/systray -cd example -env GO111MODULE=on go build -./example -``` - -On Windows, you should build like this: - -``` -env GO111MODULE=on go build -ldflags "-H=windowsgui" -``` - -The following text will then appear on the console: - - -```sh -go: finding github.com/skratchdot/open-golang latest -go: finding github.com/getlantern/systray latest -go: finding github.com/getlantern/golog latest -``` - -Now look for *Awesome App* in your menu bar! - -![Awesome App screenshot](example/screenshot.png) - -## The Webview example - -The code under `webview_example` is to demostrate how it can co-exist with other UI elements. Note that the example doesn't work on macOS versions older than 10.15 Catalina. - -## Platform notes - -### Linux - -* Building apps requires gcc as well as the `gtk3` and `libayatana-appindicator3` development headers to be installed. For Debian or Ubuntu, you may install these using: - -```sh -sudo apt-get install gcc libgtk-3-dev libayatana-appindicator3-dev -``` - -On Linux Mint, `libxapp-dev` is also required. - -If you need to support the older `libappindicator3` library instead, you can pass the build flag `legacy_appindicator` -when building. For example: - -``` -go build -tags=legacy_appindicator -``` - -To build `webview_example`, you also need to install `libwebkit2gtk-4.0-dev` and remove `webview_example/rsrc.syso` which is required on Windows. - -### Windows - -* To avoid opening a console at application startup, use these compile flags: - -```sh -go build -ldflags -H=windowsgui -``` - -### macOS - -On macOS, you will need to create an application bundle to wrap the binary; simply folders with the following minimal structure and assets: - -``` -SystrayApp.app/ - Contents/ - Info.plist - MacOS/ - go-executable - Resources/ - SystrayApp.icns -``` - -When running as an app bundle, you may want to add one or both of the following to your Info.plist: - -```xml - - NSHighResolutionCapable - True - - - LSUIElement - 1 -``` - -Consult the [Official Apple Documentation here](https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1). - -## Credits - -- https://github.com/xilp/systray -- https://github.com/cratonica/trayhost diff --git a/vendor/github.com/getlantern/systray/systray.go b/vendor/github.com/getlantern/systray/systray.go deleted file mode 100644 index 8fe9d163..00000000 --- a/vendor/github.com/getlantern/systray/systray.go +++ /dev/null @@ -1,236 +0,0 @@ -/* -Package systray is a cross-platform Go library to place an icon and menu in the notification area. -*/ -package systray - -import ( - "fmt" - "runtime" - "sync" - "sync/atomic" - - "github.com/getlantern/golog" -) - -var ( - log = golog.LoggerFor("systray") - - systrayReady func() - systrayExit func() - menuItems = make(map[uint32]*MenuItem) - menuItemsLock sync.RWMutex - - currentID = uint32(0) - quitOnce sync.Once -) - -func init() { - runtime.LockOSThread() -} - -// MenuItem is used to keep track each menu item of systray. -// Don't create it directly, use the one systray.AddMenuItem() returned -type MenuItem struct { - // ClickedCh is the channel which will be notified when the menu item is clicked - ClickedCh chan struct{} - - // id uniquely identify a menu item, not supposed to be modified - id uint32 - // title is the text shown on menu item - title string - // tooltip is the text shown when pointing to menu item - tooltip string - // disabled menu item is grayed out and has no effect when clicked - disabled bool - // checked menu item has a tick before the title - checked bool - // has the menu item a checkbox (Linux) - isCheckable bool - // parent item, for sub menus - parent *MenuItem -} - -func (item *MenuItem) String() string { - if item.parent == nil { - return fmt.Sprintf("MenuItem[%d, %q]", item.id, item.title) - } - return fmt.Sprintf("MenuItem[%d, parent %d, %q]", item.id, item.parent.id, item.title) -} - -// newMenuItem returns a populated MenuItem object -func newMenuItem(title string, tooltip string, parent *MenuItem) *MenuItem { - return &MenuItem{ - ClickedCh: make(chan struct{}), - id: atomic.AddUint32(¤tID, 1), - title: title, - tooltip: tooltip, - disabled: false, - checked: false, - isCheckable: false, - parent: parent, - } -} - -// Run initializes GUI and starts the event loop, then invokes the onReady -// callback. It blocks until systray.Quit() is called. -func Run(onReady func(), onExit func()) { - Register(onReady, onExit) - nativeLoop() -} - -// Register initializes GUI and registers the callbacks but relies on the -// caller to run the event loop somewhere else. It's useful if the program -// needs to show other UI elements, for example, webview. -// To overcome some OS weirdness, On macOS versions before Catalina, calling -// this does exactly the same as Run(). -func Register(onReady func(), onExit func()) { - if onReady == nil { - systrayReady = func() {} - } else { - // Run onReady on separate goroutine to avoid blocking event loop - readyCh := make(chan interface{}) - go func() { - <-readyCh - onReady() - }() - systrayReady = func() { - close(readyCh) - } - } - // unlike onReady, onExit runs in the event loop to make sure it has time to - // finish before the process terminates - if onExit == nil { - onExit = func() {} - } - systrayExit = onExit - registerSystray() -} - -// Quit the systray -func Quit() { - quitOnce.Do(quit) -} - -// AddMenuItem adds a menu item with the designated title and tooltip. -// It can be safely invoked from different goroutines. -// Created menu items are checkable on Windows and OSX by default. For Linux you have to use AddMenuItemCheckbox -func AddMenuItem(title string, tooltip string) *MenuItem { - item := newMenuItem(title, tooltip, nil) - item.update() - return item -} - -// AddMenuItemCheckbox adds a menu item with the designated title and tooltip and a checkbox for Linux. -// It can be safely invoked from different goroutines. -// On Windows and OSX this is the same as calling AddMenuItem -func AddMenuItemCheckbox(title string, tooltip string, checked bool) *MenuItem { - item := newMenuItem(title, tooltip, nil) - item.isCheckable = true - item.checked = checked - item.update() - return item -} - -// AddSeparator adds a separator bar to the menu -func AddSeparator() { - addSeparator(atomic.AddUint32(¤tID, 1)) -} - -// AddSubMenuItem adds a nested sub-menu item with the designated title and tooltip. -// It can be safely invoked from different goroutines. -// Created menu items are checkable on Windows and OSX by default. For Linux you have to use AddSubMenuItemCheckbox -func (item *MenuItem) AddSubMenuItem(title string, tooltip string) *MenuItem { - child := newMenuItem(title, tooltip, item) - child.update() - return child -} - -// AddSubMenuItemCheckbox adds a nested sub-menu item with the designated title and tooltip and a checkbox for Linux. -// It can be safely invoked from different goroutines. -// On Windows and OSX this is the same as calling AddSubMenuItem -func (item *MenuItem) AddSubMenuItemCheckbox(title string, tooltip string, checked bool) *MenuItem { - child := newMenuItem(title, tooltip, item) - child.isCheckable = true - child.checked = checked - child.update() - return child -} - -// SetTitle set the text to display on a menu item -func (item *MenuItem) SetTitle(title string) { - item.title = title - item.update() -} - -// SetTooltip set the tooltip to show when mouse hover -func (item *MenuItem) SetTooltip(tooltip string) { - item.tooltip = tooltip - item.update() -} - -// Disabled checks if the menu item is disabled -func (item *MenuItem) Disabled() bool { - return item.disabled -} - -// Enable a menu item regardless if it's previously enabled or not -func (item *MenuItem) Enable() { - item.disabled = false - item.update() -} - -// Disable a menu item regardless if it's previously disabled or not -func (item *MenuItem) Disable() { - item.disabled = true - item.update() -} - -// Hide hides a menu item -func (item *MenuItem) Hide() { - hideMenuItem(item) -} - -// Show shows a previously hidden menu item -func (item *MenuItem) Show() { - showMenuItem(item) -} - -// Checked returns if the menu item has a check mark -func (item *MenuItem) Checked() bool { - return item.checked -} - -// Check a menu item regardless if it's previously checked or not -func (item *MenuItem) Check() { - item.checked = true - item.update() -} - -// Uncheck a menu item regardless if it's previously unchecked or not -func (item *MenuItem) Uncheck() { - item.checked = false - item.update() -} - -// update propagates changes on a menu item to systray -func (item *MenuItem) update() { - menuItemsLock.Lock() - menuItems[item.id] = item - menuItemsLock.Unlock() - addOrUpdateMenuItem(item) -} - -func systrayMenuItemSelected(id uint32) { - menuItemsLock.RLock() - item, ok := menuItems[id] - menuItemsLock.RUnlock() - if !ok { - log.Errorf("No menu item with ID %v", id) - return - } - select { - case item.ClickedCh <- struct{}{}: - // in case no one waiting for the channel - default: - } -} diff --git a/vendor/github.com/getlantern/systray/systray.h b/vendor/github.com/getlantern/systray/systray.h deleted file mode 100644 index 888c8290..00000000 --- a/vendor/github.com/getlantern/systray/systray.h +++ /dev/null @@ -1,17 +0,0 @@ -#include "stdbool.h" - -extern void systray_ready(); -extern void systray_on_exit(); -extern void systray_menu_item_selected(int menu_id); -void registerSystray(void); -int nativeLoop(void); - -void setIcon(const char* iconBytes, int length, bool template); -void setMenuItemIcon(const char* iconBytes, int length, int menuId, bool template); -void setTitle(char* title); -void setTooltip(char* tooltip); -void add_or_update_menu_item(int menuId, int parentMenuId, char* title, char* tooltip, short disabled, short checked, short isCheckable); -void add_separator(int menuId); -void hide_menu_item(int menuId); -void show_menu_item(int menuId); -void quit(); diff --git a/vendor/github.com/getlantern/systray/systray_darwin.go b/vendor/github.com/getlantern/systray/systray_darwin.go deleted file mode 100644 index 740ec5b5..00000000 --- a/vendor/github.com/getlantern/systray/systray_darwin.go +++ /dev/null @@ -1,38 +0,0 @@ -package systray - -/* -#cgo darwin CFLAGS: -DDARWIN -x objective-c -fobjc-arc -#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit - -#include "systray.h" -*/ -import "C" - -import ( - "unsafe" -) - -// SetTemplateIcon sets the systray icon as a template icon (on Mac), falling back -// to a regular icon on other platforms. -// templateIconBytes and regularIconBytes should be the content of .ico for windows and -// .ico/.jpg/.png for other platforms. -func SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) { - cstr := (*C.char)(unsafe.Pointer(&templateIconBytes[0])) - C.setIcon(cstr, (C.int)(len(templateIconBytes)), true) -} - -// SetIcon sets the icon of a menu item. Only works on macOS and Windows. -// iconBytes should be the content of .ico/.jpg/.png -func (item *MenuItem) SetIcon(iconBytes []byte) { - cstr := (*C.char)(unsafe.Pointer(&iconBytes[0])) - C.setMenuItemIcon(cstr, (C.int)(len(iconBytes)), C.int(item.id), false) -} - -// SetTemplateIcon sets the icon of a menu item as a template icon (on macOS). On Windows, it -// falls back to the regular icon bytes and on Linux it does nothing. -// templateIconBytes and regularIconBytes should be the content of .ico for windows and -// .ico/.jpg/.png for other platforms. -func (item *MenuItem) SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) { - cstr := (*C.char)(unsafe.Pointer(&templateIconBytes[0])) - C.setMenuItemIcon(cstr, (C.int)(len(templateIconBytes)), C.int(item.id), true) -} diff --git a/vendor/github.com/getlantern/systray/systray_darwin.m b/vendor/github.com/getlantern/systray/systray_darwin.m deleted file mode 100644 index 884fa432..00000000 --- a/vendor/github.com/getlantern/systray/systray_darwin.m +++ /dev/null @@ -1,293 +0,0 @@ -#import -#include "systray.h" - -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101400 - - #ifndef NSControlStateValueOff - #define NSControlStateValueOff NSOffState - #endif - - #ifndef NSControlStateValueOn - #define NSControlStateValueOn NSOnState - #endif - -#endif - -@interface MenuItem : NSObject -{ - @public - NSNumber* menuId; - NSNumber* parentMenuId; - NSString* title; - NSString* tooltip; - short disabled; - short checked; -} --(id) initWithId: (int)theMenuId -withParentMenuId: (int)theParentMenuId - withTitle: (const char*)theTitle - withTooltip: (const char*)theTooltip - withDisabled: (short)theDisabled - withChecked: (short)theChecked; - @end - @implementation MenuItem - -(id) initWithId: (int)theMenuId - withParentMenuId: (int)theParentMenuId - withTitle: (const char*)theTitle - withTooltip: (const char*)theTooltip - withDisabled: (short)theDisabled - withChecked: (short)theChecked -{ - menuId = [NSNumber numberWithInt:theMenuId]; - parentMenuId = [NSNumber numberWithInt:theParentMenuId]; - title = [[NSString alloc] initWithCString:theTitle - encoding:NSUTF8StringEncoding]; - tooltip = [[NSString alloc] initWithCString:theTooltip - encoding:NSUTF8StringEncoding]; - disabled = theDisabled; - checked = theChecked; - return self; -} -@end - -@interface AppDelegate: NSObject - - (void) add_or_update_menu_item:(MenuItem*) item; - - (IBAction)menuHandler:(id)sender; - @property (assign) IBOutlet NSWindow *window; - @end - - @implementation AppDelegate -{ - NSStatusItem *statusItem; - NSMenu *menu; - NSCondition* cond; -} - -@synthesize window = _window; - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - self->statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; - self->menu = [[NSMenu alloc] init]; - [self->menu setAutoenablesItems: FALSE]; - [self->statusItem setMenu:self->menu]; - systray_ready(); -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification -{ - systray_on_exit(); -} - -- (void)setIcon:(NSImage *)image { - statusItem.button.image = image; - [self updateTitleButtonStyle]; -} - -- (void)setTitle:(NSString *)title { - statusItem.button.title = title; - [self updateTitleButtonStyle]; -} - --(void)updateTitleButtonStyle { - if (statusItem.button.image != nil) { - if ([statusItem.button.title length] == 0) { - statusItem.button.imagePosition = NSImageOnly; - } else { - statusItem.button.imagePosition = NSImageLeft; - } - } else { - statusItem.button.imagePosition = NSNoImage; - } -} - - -- (void)setTooltip:(NSString *)tooltip { - statusItem.button.toolTip = tooltip; -} - -- (IBAction)menuHandler:(id)sender -{ - NSNumber* menuId = [sender representedObject]; - systray_menu_item_selected(menuId.intValue); -} - -- (void)add_or_update_menu_item:(MenuItem *)item { - NSMenu *theMenu = self->menu; - NSMenuItem *parentItem; - if ([item->parentMenuId integerValue] > 0) { - parentItem = find_menu_item(menu, item->parentMenuId); - if (parentItem.hasSubmenu) { - theMenu = parentItem.submenu; - } else { - theMenu = [[NSMenu alloc] init]; - [theMenu setAutoenablesItems:NO]; - [parentItem setSubmenu:theMenu]; - } - } - - NSMenuItem *menuItem; - menuItem = find_menu_item(theMenu, item->menuId); - if (menuItem == NULL) { - menuItem = [theMenu addItemWithTitle:item->title - action:@selector(menuHandler:) - keyEquivalent:@""]; - [menuItem setRepresentedObject:item->menuId]; - } - [menuItem setTitle:item->title]; - [menuItem setTag:[item->menuId integerValue]]; - [menuItem setTarget:self]; - [menuItem setToolTip:item->tooltip]; - if (item->disabled == 1) { - menuItem.enabled = FALSE; - } else { - menuItem.enabled = TRUE; - } - if (item->checked == 1) { - menuItem.state = NSControlStateValueOn; - } else { - menuItem.state = NSControlStateValueOff; - } -} - -NSMenuItem *find_menu_item(NSMenu *ourMenu, NSNumber *menuId) { - NSMenuItem *foundItem = [ourMenu itemWithTag:[menuId integerValue]]; - if (foundItem != NULL) { - return foundItem; - } - NSArray *menu_items = ourMenu.itemArray; - int i; - for (i = 0; i < [menu_items count]; i++) { - NSMenuItem *i_item = [menu_items objectAtIndex:i]; - if (i_item.hasSubmenu) { - foundItem = find_menu_item(i_item.submenu, menuId); - if (foundItem != NULL) { - return foundItem; - } - } - } - - return NULL; -}; - -- (void) add_separator:(NSNumber*) menuId -{ - [menu addItem: [NSMenuItem separatorItem]]; -} - -- (void) hide_menu_item:(NSNumber*) menuId -{ - NSMenuItem* menuItem = find_menu_item(menu, menuId); - if (menuItem != NULL) { - [menuItem setHidden:TRUE]; - } -} - -- (void) setMenuItemIcon:(NSArray*)imageAndMenuId { - NSImage* image = [imageAndMenuId objectAtIndex:0]; - NSNumber* menuId = [imageAndMenuId objectAtIndex:1]; - - NSMenuItem* menuItem; - menuItem = find_menu_item(menu, menuId); - if (menuItem == NULL) { - return; - } - menuItem.image = image; -} - -- (void) show_menu_item:(NSNumber*) menuId -{ - NSMenuItem* menuItem = find_menu_item(menu, menuId); - if (menuItem != NULL) { - [menuItem setHidden:FALSE]; - } -} - -- (void) quit -{ - [NSApp terminate:self]; -} - -@end - -void registerSystray(void) { - AppDelegate *delegate = [[AppDelegate alloc] init]; - [[NSApplication sharedApplication] setDelegate:delegate]; - // A workaround to avoid crashing on macOS versions before Catalina. Somehow - // SIGSEGV would happen inside AppKit if [NSApp run] is called from a - // different function, even if that function is called right after this. - if (floor(NSAppKitVersionNumber) <= /*NSAppKitVersionNumber10_14*/ 1671){ - [NSApp run]; - } -} - -int nativeLoop(void) { - if (floor(NSAppKitVersionNumber) > /*NSAppKitVersionNumber10_14*/ 1671){ - [NSApp run]; - } - return EXIT_SUCCESS; -} - -void runInMainThread(SEL method, id object) { - [(AppDelegate*)[NSApp delegate] - performSelectorOnMainThread:method - withObject:object - waitUntilDone: YES]; -} - -void setIcon(const char* iconBytes, int length, bool template) { - NSData* buffer = [NSData dataWithBytes: iconBytes length:length]; - NSImage *image = [[NSImage alloc] initWithData:buffer]; - [image setSize:NSMakeSize(16, 16)]; - image.template = template; - runInMainThread(@selector(setIcon:), (id)image); -} - -void setMenuItemIcon(const char* iconBytes, int length, int menuId, bool template) { - NSData* buffer = [NSData dataWithBytes: iconBytes length:length]; - NSImage *image = [[NSImage alloc] initWithData:buffer]; - [image setSize:NSMakeSize(16, 16)]; - image.template = template; - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(setMenuItemIcon:), @[image, (id)mId]); -} - -void setTitle(char* ctitle) { - NSString* title = [[NSString alloc] initWithCString:ctitle - encoding:NSUTF8StringEncoding]; - free(ctitle); - runInMainThread(@selector(setTitle:), (id)title); -} - -void setTooltip(char* ctooltip) { - NSString* tooltip = [[NSString alloc] initWithCString:ctooltip - encoding:NSUTF8StringEncoding]; - free(ctooltip); - runInMainThread(@selector(setTooltip:), (id)tooltip); -} - -void add_or_update_menu_item(int menuId, int parentMenuId, char* title, char* tooltip, short disabled, short checked, short isCheckable) { - MenuItem* item = [[MenuItem alloc] initWithId: menuId withParentMenuId: parentMenuId withTitle: title withTooltip: tooltip withDisabled: disabled withChecked: checked]; - free(title); - free(tooltip); - runInMainThread(@selector(add_or_update_menu_item:), (id)item); -} - -void add_separator(int menuId) { - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(add_separator:), (id)mId); -} - -void hide_menu_item(int menuId) { - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(hide_menu_item:), (id)mId); -} - -void show_menu_item(int menuId) { - NSNumber *mId = [NSNumber numberWithInt:menuId]; - runInMainThread(@selector(show_menu_item:), (id)mId); -} - -void quit() { - runInMainThread(@selector(quit), nil); -} diff --git a/vendor/github.com/getlantern/systray/systray_linux.c b/vendor/github.com/getlantern/systray/systray_linux.c deleted file mode 100644 index 9e14ba01..00000000 --- a/vendor/github.com/getlantern/systray/systray_linux.c +++ /dev/null @@ -1,275 +0,0 @@ -#include -#include -#include -#include - -#ifdef USE_LEGACY_APPINDICATOR -#include -#else -#include -#endif - -#include "systray.h" - -static AppIndicator *global_app_indicator; -static GtkWidget *global_tray_menu = NULL; -static GList *global_menu_items = NULL; -static char temp_file_name[PATH_MAX] = ""; - -typedef struct { - GtkWidget *menu_item; - int menu_id; - long signalHandlerId; -} MenuItemNode; - -typedef struct { - int menu_id; - int parent_menu_id; - char* title; - char* tooltip; - short disabled; - short checked; - short isCheckable; -} MenuItemInfo; - -void registerSystray(void) { - gtk_init(0, NULL); - global_app_indicator = app_indicator_new("systray", "", APP_INDICATOR_CATEGORY_APPLICATION_STATUS); - app_indicator_set_status(global_app_indicator, APP_INDICATOR_STATUS_ACTIVE); - global_tray_menu = gtk_menu_new(); - app_indicator_set_menu(global_app_indicator, GTK_MENU(global_tray_menu)); - systray_ready(); -} - -int nativeLoop(void) { - gtk_main(); - systray_on_exit(); - return 0; -} - -void _unlink_temp_file() { - if (strlen(temp_file_name) != 0) { - int ret = unlink(temp_file_name); - if (ret == -1) { - printf("failed to remove temp icon file %s: %s\n", temp_file_name, strerror(errno)); - } - temp_file_name[0] = '\0'; - } -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_set_icon(gpointer data) { - _unlink_temp_file(); - char *tmpdir = getenv("TMPDIR"); - if (NULL == tmpdir) { - tmpdir = "/tmp"; - } - strncpy(temp_file_name, tmpdir, PATH_MAX-1); - strncat(temp_file_name, "/systray_XXXXXX", PATH_MAX-1); - temp_file_name[PATH_MAX-1] = '\0'; - - GBytes* bytes = (GBytes*)data; - int fd = mkstemp(temp_file_name); - if (fd == -1) { - printf("failed to create temp icon file %s: %s\n", temp_file_name, strerror(errno)); - return FALSE; - } - gsize size = 0; - gconstpointer icon_data = g_bytes_get_data(bytes, &size); - ssize_t written = write(fd, icon_data, size); - close(fd); - if(written != size) { - printf("failed to write temp icon file %s: %s\n", temp_file_name, strerror(errno)); - return FALSE; - } - app_indicator_set_icon_full(global_app_indicator, temp_file_name, ""); - app_indicator_set_attention_icon_full(global_app_indicator, temp_file_name, ""); - g_bytes_unref(bytes); - return FALSE; -} - -void _systray_menu_item_selected(int *id) { - systray_menu_item_selected(*id); -} - -GtkMenuItem* find_menu_by_id(int id) { - GList* it; - for(it = global_menu_items; it != NULL; it = it->next) { - MenuItemNode* item = (MenuItemNode*)(it->data); - if(item->menu_id == id) { - return GTK_MENU_ITEM(item->menu_item); - } - } - return NULL; -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_add_or_update_menu_item(gpointer data) { - MenuItemInfo *mii = (MenuItemInfo*)data; - GList* it; - for(it = global_menu_items; it != NULL; it = it->next) { - MenuItemNode* item = (MenuItemNode*)(it->data); - if(item->menu_id == mii->menu_id) { - gtk_menu_item_set_label(GTK_MENU_ITEM(item->menu_item), mii->title); - - if (mii->isCheckable) { - // We need to block the "activate" event, to emulate the same behaviour as in the windows version - // A Check/Uncheck does change the checkbox, but does not trigger the checkbox menuItem channel - g_signal_handler_block(GTK_CHECK_MENU_ITEM(item->menu_item), item->signalHandlerId); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->menu_item), mii->checked == 1); - g_signal_handler_unblock(GTK_CHECK_MENU_ITEM(item->menu_item), item->signalHandlerId); - } - break; - } - } - - // menu id doesn't exist, add new item - if(it == NULL) { - GtkWidget *menu_item; - if (mii->isCheckable) { - menu_item = gtk_check_menu_item_new_with_label(mii->title); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), mii->checked == 1); - } else { - menu_item = gtk_menu_item_new_with_label(mii->title); - } - int *id = malloc(sizeof(int)); - *id = mii->menu_id; - long signalHandlerId = g_signal_connect_swapped( - G_OBJECT(menu_item), - "activate", - G_CALLBACK(_systray_menu_item_selected), - id - ); - - if (mii->parent_menu_id == 0) { - gtk_menu_shell_append(GTK_MENU_SHELL(global_tray_menu), menu_item); - } else { - GtkMenuItem* parentMenuItem = find_menu_by_id(mii->parent_menu_id); - GtkWidget* parentMenu = gtk_menu_item_get_submenu(parentMenuItem); - - if(parentMenu == NULL) { - parentMenu = gtk_menu_new(); - gtk_menu_item_set_submenu(parentMenuItem, parentMenu); - } - - gtk_menu_shell_append(GTK_MENU_SHELL(parentMenu), menu_item); - } - - MenuItemNode* new_item = malloc(sizeof(MenuItemNode)); - new_item->menu_id = mii->menu_id; - new_item->signalHandlerId = signalHandlerId; - new_item->menu_item = menu_item; - GList* new_node = malloc(sizeof(GList)); - new_node->data = new_item; - new_node->next = global_menu_items; - if(global_menu_items != NULL) { - global_menu_items->prev = new_node; - } - global_menu_items = new_node; - it = new_node; - } - GtkWidget* menu_item = GTK_WIDGET(((MenuItemNode*)(it->data))->menu_item); - gtk_widget_set_sensitive(menu_item, mii->disabled != 1); - gtk_widget_show(menu_item); - - free(mii->title); - free(mii->tooltip); - free(mii); - return FALSE; -} - -gboolean do_add_separator(gpointer data) { - GtkWidget *separator = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(global_tray_menu), separator); - gtk_widget_show(separator); - return FALSE; -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_hide_menu_item(gpointer data) { - MenuItemInfo *mii = (MenuItemInfo*)data; - GList* it; - for(it = global_menu_items; it != NULL; it = it->next) { - MenuItemNode* item = (MenuItemNode*)(it->data); - if(item->menu_id == mii->menu_id){ - gtk_widget_hide(GTK_WIDGET(item->menu_item)); - break; - } - } - return FALSE; -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_show_menu_item(gpointer data) { - MenuItemInfo *mii = (MenuItemInfo*)data; - GList* it; - for(it = global_menu_items; it != NULL; it = it->next) { - MenuItemNode* item = (MenuItemNode*)(it->data); - if(item->menu_id == mii->menu_id){ - gtk_widget_show(GTK_WIDGET(item->menu_item)); - break; - } - } - return FALSE; -} - -// runs in main thread, should always return FALSE to prevent gtk to execute it again -gboolean do_quit(gpointer data) { - _unlink_temp_file(); - // app indicator doesn't provide a way to remove it, hide it as a workaround - app_indicator_set_status(global_app_indicator, APP_INDICATOR_STATUS_PASSIVE); - gtk_main_quit(); - return FALSE; -} - -void setIcon(const char* iconBytes, int length, bool template) { - GBytes* bytes = g_bytes_new_static(iconBytes, length); - g_idle_add(do_set_icon, bytes); -} - -void setTitle(char* ctitle) { - app_indicator_set_title(global_app_indicator, ctitle); - app_indicator_set_label(global_app_indicator, ctitle, ""); - free(ctitle); -} - -void setTooltip(char* ctooltip) { - free(ctooltip); -} - -void setMenuItemIcon(const char* iconBytes, int length, int menuId, bool template) { -} - -void add_or_update_menu_item(int menu_id, int parent_menu_id, char* title, char* tooltip, short disabled, short checked, short isCheckable) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - mii->parent_menu_id = parent_menu_id; - mii->title = title; - mii->tooltip = tooltip; - mii->disabled = disabled; - mii->checked = checked; - mii->isCheckable = isCheckable; - g_idle_add(do_add_or_update_menu_item, mii); -} - -void add_separator(int menu_id) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - g_idle_add(do_add_separator, mii); -} - -void hide_menu_item(int menu_id) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - g_idle_add(do_hide_menu_item, mii); -} - -void show_menu_item(int menu_id) { - MenuItemInfo *mii = malloc(sizeof(MenuItemInfo)); - mii->menu_id = menu_id; - g_idle_add(do_show_menu_item, mii); -} - -void quit() { - g_idle_add(do_quit, NULL); -} diff --git a/vendor/github.com/getlantern/systray/systray_linux.go b/vendor/github.com/getlantern/systray/systray_linux.go deleted file mode 100644 index ec0b751f..00000000 --- a/vendor/github.com/getlantern/systray/systray_linux.go +++ /dev/null @@ -1,21 +0,0 @@ -package systray - -// SetTemplateIcon sets the systray icon as a template icon (on macOS), falling back -// to a regular icon on other platforms. -// templateIconBytes and iconBytes should be the content of .ico for windows and -// .ico/.jpg/.png for other platforms. -func SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) { - SetIcon(regularIconBytes) -} - -// SetIcon sets the icon of a menu item. Only works on macOS and Windows. -// iconBytes should be the content of .ico/.jpg/.png -func (item *MenuItem) SetIcon(iconBytes []byte) { -} - -// SetTemplateIcon sets the icon of a menu item as a template icon (on macOS). On Windows, it -// falls back to the regular icon bytes and on Linux it does nothing. -// templateIconBytes and regularIconBytes should be the content of .ico for windows and -// .ico/.jpg/.png for other platforms. -func (item *MenuItem) SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) { -} diff --git a/vendor/github.com/getlantern/systray/systray_linux_appindicator.go b/vendor/github.com/getlantern/systray/systray_linux_appindicator.go deleted file mode 100644 index dde0e23d..00000000 --- a/vendor/github.com/getlantern/systray/systray_linux_appindicator.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build linux,legacy_appindicator -//go:build linux && legacy_appindicator - -package systray - -/* -#cgo linux pkg-config: appindicator3-0.1 -#cgo linux CFLAGS: -DUSE_LEGACY_APPINDICATOR - -#include "systray.h" -*/ -import "C" diff --git a/vendor/github.com/getlantern/systray/systray_linux_ayatana.go b/vendor/github.com/getlantern/systray/systray_linux_ayatana.go deleted file mode 100644 index 2547f2e5..00000000 --- a/vendor/github.com/getlantern/systray/systray_linux_ayatana.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build linux,!legacy_appindicator -//go:build linux && !legacy_appindicator - -package systray - -/* -#cgo linux pkg-config: ayatana-appindicator3-0.1 - -#include "systray.h" -*/ -import "C" diff --git a/vendor/github.com/getlantern/systray/systray_nonwindows.go b/vendor/github.com/getlantern/systray/systray_nonwindows.go deleted file mode 100644 index 12eacdfa..00000000 --- a/vendor/github.com/getlantern/systray/systray_nonwindows.go +++ /dev/null @@ -1,101 +0,0 @@ -// +build !windows -// go:build !windows - -package systray - -// #include "systray.h" -import "C" - -import ( - "unsafe" -) - -func registerSystray() { - C.registerSystray() -} - -func nativeLoop() { - C.nativeLoop() -} - -func quit() { - C.quit() -} - -// SetIcon sets the systray icon. -// iconBytes should be the content of .ico for windows and .ico/.jpg/.png -// for other platforms. -func SetIcon(iconBytes []byte) { - cstr := (*C.char)(unsafe.Pointer(&iconBytes[0])) - C.setIcon(cstr, (C.int)(len(iconBytes)), false) -} - -// SetTitle sets the systray title, only available on Mac and Linux. -func SetTitle(title string) { - C.setTitle(C.CString(title)) -} - -// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon, -// only available on Mac and Windows. -func SetTooltip(tooltip string) { - C.setTooltip(C.CString(tooltip)) -} - -func addOrUpdateMenuItem(item *MenuItem) { - var disabled C.short - if item.disabled { - disabled = 1 - } - var checked C.short - if item.checked { - checked = 1 - } - var isCheckable C.short - if item.isCheckable { - isCheckable = 1 - } - var parentID uint32 = 0 - if item.parent != nil { - parentID = item.parent.id - } - C.add_or_update_menu_item( - C.int(item.id), - C.int(parentID), - C.CString(item.title), - C.CString(item.tooltip), - disabled, - checked, - isCheckable, - ) -} - -func addSeparator(id uint32) { - C.add_separator(C.int(id)) -} - -func hideMenuItem(item *MenuItem) { - C.hide_menu_item( - C.int(item.id), - ) -} - -func showMenuItem(item *MenuItem) { - C.show_menu_item( - C.int(item.id), - ) -} - -//export systray_ready -func systray_ready() { - systrayReady() -} - -//export systray_on_exit -func systray_on_exit() { - systrayExit() -} - -//export systray_menu_item_selected -func systray_menu_item_selected(cID C.int) { - systrayMenuItemSelected(uint32(cID)) -} diff --git a/vendor/github.com/getlantern/systray/systray_windows.go b/vendor/github.com/getlantern/systray/systray_windows.go deleted file mode 100644 index 6bdc803d..00000000 --- a/vendor/github.com/getlantern/systray/systray_windows.go +++ /dev/null @@ -1,944 +0,0 @@ -// +build windows - -package systray - -import ( - "crypto/md5" - "encoding/hex" - "io/ioutil" - "os" - "path/filepath" - "sort" - "sync" - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -// Helpful sources: https://github.com/golang/exp/blob/master/shiny/driver/internal/win32 - -var ( - g32 = windows.NewLazySystemDLL("Gdi32.dll") - pCreateCompatibleBitmap = g32.NewProc("CreateCompatibleBitmap") - pCreateCompatibleDC = g32.NewProc("CreateCompatibleDC") - pDeleteDC = g32.NewProc("DeleteDC") - pSelectObject = g32.NewProc("SelectObject") - - k32 = windows.NewLazySystemDLL("Kernel32.dll") - pGetModuleHandle = k32.NewProc("GetModuleHandleW") - - s32 = windows.NewLazySystemDLL("Shell32.dll") - pShellNotifyIcon = s32.NewProc("Shell_NotifyIconW") - - u32 = windows.NewLazySystemDLL("User32.dll") - pCreateMenu = u32.NewProc("CreateMenu") - pCreatePopupMenu = u32.NewProc("CreatePopupMenu") - pCreateWindowEx = u32.NewProc("CreateWindowExW") - pDefWindowProc = u32.NewProc("DefWindowProcW") - pRemoveMenu = u32.NewProc("RemoveMenu") - pDestroyWindow = u32.NewProc("DestroyWindow") - pDispatchMessage = u32.NewProc("DispatchMessageW") - pDrawIconEx = u32.NewProc("DrawIconEx") - pGetCursorPos = u32.NewProc("GetCursorPos") - pGetDC = u32.NewProc("GetDC") - pGetMessage = u32.NewProc("GetMessageW") - pGetSystemMetrics = u32.NewProc("GetSystemMetrics") - pInsertMenuItem = u32.NewProc("InsertMenuItemW") - pLoadCursor = u32.NewProc("LoadCursorW") - pLoadIcon = u32.NewProc("LoadIconW") - pLoadImage = u32.NewProc("LoadImageW") - pPostMessage = u32.NewProc("PostMessageW") - pPostQuitMessage = u32.NewProc("PostQuitMessage") - pRegisterClass = u32.NewProc("RegisterClassExW") - pRegisterWindowMessage = u32.NewProc("RegisterWindowMessageW") - pReleaseDC = u32.NewProc("ReleaseDC") - pSetForegroundWindow = u32.NewProc("SetForegroundWindow") - pSetMenuInfo = u32.NewProc("SetMenuInfo") - pSetMenuItemInfo = u32.NewProc("SetMenuItemInfoW") - pShowWindow = u32.NewProc("ShowWindow") - pTrackPopupMenu = u32.NewProc("TrackPopupMenu") - pTranslateMessage = u32.NewProc("TranslateMessage") - pUnregisterClass = u32.NewProc("UnregisterClassW") - pUpdateWindow = u32.NewProc("UpdateWindow") -) - -// Contains window class information. -// It is used with the RegisterClassEx and GetClassInfoEx functions. -// https://msdn.microsoft.com/en-us/library/ms633577.aspx -type wndClassEx struct { - Size, Style uint32 - WndProc uintptr - ClsExtra, WndExtra int32 - Instance, Icon, Cursor, Background windows.Handle - MenuName, ClassName *uint16 - IconSm windows.Handle -} - -// Registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function. -// https://msdn.microsoft.com/en-us/library/ms633587.aspx -func (w *wndClassEx) register() error { - w.Size = uint32(unsafe.Sizeof(*w)) - res, _, err := pRegisterClass.Call(uintptr(unsafe.Pointer(w))) - if res == 0 { - return err - } - return nil -} - -// Unregisters a window class, freeing the memory required for the class. -// https://msdn.microsoft.com/en-us/library/ms644899.aspx -func (w *wndClassEx) unregister() error { - res, _, err := pUnregisterClass.Call( - uintptr(unsafe.Pointer(w.ClassName)), - uintptr(w.Instance), - ) - if res == 0 { - return err - } - return nil -} - -// Contains information that the system needs to display notifications in the notification area. -// Used by Shell_NotifyIcon. -// https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352(v=vs.85).aspx -// https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159 -type notifyIconData struct { - Size uint32 - Wnd windows.Handle - ID, Flags, CallbackMessage uint32 - Icon windows.Handle - Tip [128]uint16 - State, StateMask uint32 - Info [256]uint16 - Timeout, Version uint32 - InfoTitle [64]uint16 - InfoFlags uint32 - GuidItem windows.GUID - BalloonIcon windows.Handle -} - -func (nid *notifyIconData) add() error { - const NIM_ADD = 0x00000000 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_ADD), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -func (nid *notifyIconData) modify() error { - const NIM_MODIFY = 0x00000001 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_MODIFY), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -func (nid *notifyIconData) delete() error { - const NIM_DELETE = 0x00000002 - res, _, err := pShellNotifyIcon.Call( - uintptr(NIM_DELETE), - uintptr(unsafe.Pointer(nid)), - ) - if res == 0 { - return err - } - return nil -} - -// Contains information about a menu item. -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx -type menuItemInfo struct { - Size, Mask, Type, State uint32 - ID uint32 - SubMenu, Checked, Unchecked windows.Handle - ItemData uintptr - TypeData *uint16 - Cch uint32 - BMPItem windows.Handle -} - -// The POINT structure defines the x- and y- coordinates of a point. -// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx -type point struct { - X, Y int32 -} - -// Contains information about loaded resources -type winTray struct { - instance, - icon, - cursor, - window windows.Handle - - loadedImages map[string]windows.Handle - muLoadedImages sync.RWMutex - // menus keeps track of the submenus keyed by the menu item ID, plus 0 - // which corresponds to the main popup menu. - menus map[uint32]windows.Handle - muMenus sync.RWMutex - // menuOf keeps track of the menu each menu item belongs to. - menuOf map[uint32]windows.Handle - muMenuOf sync.RWMutex - // menuItemIcons maintains the bitmap of each menu item (if applies). It's - // needed to show the icon correctly when showing a previously hidden menu - // item again. - menuItemIcons map[uint32]windows.Handle - muMenuItemIcons sync.RWMutex - visibleItems map[uint32][]uint32 - muVisibleItems sync.RWMutex - - nid *notifyIconData - muNID sync.RWMutex - wcex *wndClassEx - - wmSystrayMessage, - wmTaskbarCreated uint32 -} - -// Loads an image from file and shows it in tray. -// Shell_NotifyIcon: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159(v=vs.85).aspx -func (t *winTray) setIcon(src string) error { - const NIF_ICON = 0x00000002 - - h, err := t.loadIconFrom(src) - if err != nil { - return err - } - - t.muNID.Lock() - defer t.muNID.Unlock() - t.nid.Icon = h - t.nid.Flags |= NIF_ICON - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.modify() -} - -// Sets tooltip on icon. -// Shell_NotifyIcon: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762159(v=vs.85).aspx -func (t *winTray) setTooltip(src string) error { - const NIF_TIP = 0x00000004 - b, err := windows.UTF16FromString(src) - if err != nil { - return err - } - - t.muNID.Lock() - defer t.muNID.Unlock() - copy(t.nid.Tip[:], b[:]) - t.nid.Flags |= NIF_TIP - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.modify() -} - -var wt winTray - -// WindowProc callback function that processes messages sent to a window. -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx -func (t *winTray) wndProc(hWnd windows.Handle, message uint32, wParam, lParam uintptr) (lResult uintptr) { - const ( - WM_RBUTTONUP = 0x0205 - WM_LBUTTONUP = 0x0202 - WM_COMMAND = 0x0111 - WM_ENDSESSION = 0x0016 - WM_CLOSE = 0x0010 - WM_DESTROY = 0x0002 - ) - switch message { - case WM_COMMAND: - menuItemId := int32(wParam) - // https://docs.microsoft.com/en-us/windows/win32/menurc/wm-command#menus - if menuItemId != -1 { - systrayMenuItemSelected(uint32(wParam)) - } - case WM_CLOSE: - pDestroyWindow.Call(uintptr(t.window)) - t.wcex.unregister() - case WM_DESTROY: - // same as WM_ENDSESSION, but throws 0 exit code after all - defer pPostQuitMessage.Call(uintptr(int32(0))) - fallthrough - case WM_ENDSESSION: - t.muNID.Lock() - if t.nid != nil { - t.nid.delete() - } - t.muNID.Unlock() - systrayExit() - case t.wmSystrayMessage: - switch lParam { - case WM_RBUTTONUP, WM_LBUTTONUP: - t.showMenu() - } - case t.wmTaskbarCreated: // on explorer.exe restarts - t.muNID.Lock() - t.nid.add() - t.muNID.Unlock() - default: - // Calls the default window procedure to provide default processing for any window messages that an application does not process. - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms633572(v=vs.85).aspx - lResult, _, _ = pDefWindowProc.Call( - uintptr(hWnd), - uintptr(message), - uintptr(wParam), - uintptr(lParam), - ) - } - return -} - -func (t *winTray) initInstance() error { - const IDI_APPLICATION = 32512 - const IDC_ARROW = 32512 // Standard arrow - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx - const SW_HIDE = 0 - const CW_USEDEFAULT = 0x80000000 - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx - const ( - WS_CAPTION = 0x00C00000 - WS_MAXIMIZEBOX = 0x00010000 - WS_MINIMIZEBOX = 0x00020000 - WS_OVERLAPPED = 0x00000000 - WS_SYSMENU = 0x00080000 - WS_THICKFRAME = 0x00040000 - - WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX - ) - // https://msdn.microsoft.com/en-us/library/windows/desktop/ff729176 - const ( - CS_HREDRAW = 0x0002 - CS_VREDRAW = 0x0001 - ) - const NIF_MESSAGE = 0x00000001 - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644931(v=vs.85).aspx - const WM_USER = 0x0400 - - const ( - className = "SystrayClass" - windowName = "" - ) - - t.wmSystrayMessage = WM_USER + 1 - t.visibleItems = make(map[uint32][]uint32) - t.menus = make(map[uint32]windows.Handle) - t.menuOf = make(map[uint32]windows.Handle) - t.menuItemIcons = make(map[uint32]windows.Handle) - - taskbarEventNamePtr, _ := windows.UTF16PtrFromString("TaskbarCreated") - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644947 - res, _, err := pRegisterWindowMessage.Call( - uintptr(unsafe.Pointer(taskbarEventNamePtr)), - ) - t.wmTaskbarCreated = uint32(res) - - t.loadedImages = make(map[string]windows.Handle) - - instanceHandle, _, err := pGetModuleHandle.Call(0) - if instanceHandle == 0 { - return err - } - t.instance = windows.Handle(instanceHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms648072(v=vs.85).aspx - iconHandle, _, err := pLoadIcon.Call(0, uintptr(IDI_APPLICATION)) - if iconHandle == 0 { - return err - } - t.icon = windows.Handle(iconHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms648391(v=vs.85).aspx - cursorHandle, _, err := pLoadCursor.Call(0, uintptr(IDC_ARROW)) - if cursorHandle == 0 { - return err - } - t.cursor = windows.Handle(cursorHandle) - - classNamePtr, err := windows.UTF16PtrFromString(className) - if err != nil { - return err - } - - windowNamePtr, err := windows.UTF16PtrFromString(windowName) - if err != nil { - return err - } - - t.wcex = &wndClassEx{ - Style: CS_HREDRAW | CS_VREDRAW, - WndProc: windows.NewCallback(t.wndProc), - Instance: t.instance, - Icon: t.icon, - Cursor: t.cursor, - Background: windows.Handle(6), // (COLOR_WINDOW + 1) - ClassName: classNamePtr, - IconSm: t.icon, - } - if err := t.wcex.register(); err != nil { - return err - } - - windowHandle, _, err := pCreateWindowEx.Call( - uintptr(0), - uintptr(unsafe.Pointer(classNamePtr)), - uintptr(unsafe.Pointer(windowNamePtr)), - uintptr(WS_OVERLAPPEDWINDOW), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(CW_USEDEFAULT), - uintptr(0), - uintptr(0), - uintptr(t.instance), - uintptr(0), - ) - if windowHandle == 0 { - return err - } - t.window = windows.Handle(windowHandle) - - pShowWindow.Call( - uintptr(t.window), - uintptr(SW_HIDE), - ) - - pUpdateWindow.Call( - uintptr(t.window), - ) - - t.muNID.Lock() - defer t.muNID.Unlock() - t.nid = ¬ifyIconData{ - Wnd: windows.Handle(t.window), - ID: 100, - Flags: NIF_MESSAGE, - CallbackMessage: t.wmSystrayMessage, - } - t.nid.Size = uint32(unsafe.Sizeof(*t.nid)) - - return t.nid.add() -} - -func (t *winTray) createMenu() error { - const MIM_APPLYTOSUBMENUS = 0x80000000 // Settings apply to the menu and all of its submenus - - menuHandle, _, err := pCreatePopupMenu.Call() - if menuHandle == 0 { - return err - } - t.menus[0] = windows.Handle(menuHandle) - - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647575(v=vs.85).aspx - mi := struct { - Size, Mask, Style, Max uint32 - Background windows.Handle - ContextHelpID uint32 - MenuData uintptr - }{ - Mask: MIM_APPLYTOSUBMENUS, - } - mi.Size = uint32(unsafe.Sizeof(mi)) - - res, _, err := pSetMenuInfo.Call( - uintptr(t.menus[0]), - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - return err - } - return nil -} - -func (t *winTray) convertToSubMenu(menuItemId uint32) (windows.Handle, error) { - const MIIM_SUBMENU = 0x00000004 - - res, _, err := pCreateMenu.Call() - if res == 0 { - return 0, err - } - menu := windows.Handle(res) - - mi := menuItemInfo{Mask: MIIM_SUBMENU, SubMenu: menu} - mi.Size = uint32(unsafe.Sizeof(mi)) - t.muMenuOf.RLock() - hMenu := t.menuOf[menuItemId] - t.muMenuOf.RUnlock() - res, _, err = pSetMenuItemInfo.Call( - uintptr(hMenu), - uintptr(menuItemId), - 0, - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - return 0, err - } - t.muMenus.Lock() - t.menus[menuItemId] = menu - t.muMenus.Unlock() - return menu, nil -} - -func (t *winTray) addOrUpdateMenuItem(menuItemId uint32, parentId uint32, title string, disabled, checked bool) error { - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx - const ( - MIIM_FTYPE = 0x00000100 - MIIM_BITMAP = 0x00000080 - MIIM_STRING = 0x00000040 - MIIM_SUBMENU = 0x00000004 - MIIM_ID = 0x00000002 - MIIM_STATE = 0x00000001 - ) - const MFT_STRING = 0x00000000 - const ( - MFS_CHECKED = 0x00000008 - MFS_DISABLED = 0x00000003 - ) - titlePtr, err := windows.UTF16PtrFromString(title) - if err != nil { - return err - } - - mi := menuItemInfo{ - Mask: MIIM_FTYPE | MIIM_STRING | MIIM_ID | MIIM_STATE, - Type: MFT_STRING, - ID: uint32(menuItemId), - TypeData: titlePtr, - Cch: uint32(len(title)), - } - mi.Size = uint32(unsafe.Sizeof(mi)) - if disabled { - mi.State |= MFS_DISABLED - } - if checked { - mi.State |= MFS_CHECKED - } - t.muMenuItemIcons.RLock() - hIcon := t.menuItemIcons[menuItemId] - t.muMenuItemIcons.RUnlock() - if hIcon > 0 { - mi.Mask |= MIIM_BITMAP - mi.BMPItem = hIcon - } - - var res uintptr - t.muMenus.RLock() - menu, exists := t.menus[parentId] - t.muMenus.RUnlock() - if !exists { - menu, err = t.convertToSubMenu(parentId) - if err != nil { - return err - } - t.muMenus.Lock() - t.menus[parentId] = menu - t.muMenus.Unlock() - } else if t.getVisibleItemIndex(parentId, menuItemId) != -1 { - // We set the menu item info based on the menuID - res, _, err = pSetMenuItemInfo.Call( - uintptr(menu), - uintptr(menuItemId), - 0, - uintptr(unsafe.Pointer(&mi)), - ) - } - - if res == 0 { - // Menu item does not already exist, create it - t.muMenus.RLock() - submenu, exists := t.menus[menuItemId] - t.muMenus.RUnlock() - if exists { - mi.Mask |= MIIM_SUBMENU - mi.SubMenu = submenu - } - t.addToVisibleItems(parentId, menuItemId) - position := t.getVisibleItemIndex(parentId, menuItemId) - res, _, err = pInsertMenuItem.Call( - uintptr(menu), - uintptr(position), - 1, - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - t.delFromVisibleItems(parentId, menuItemId) - return err - } - t.muMenuOf.Lock() - t.menuOf[menuItemId] = menu - t.muMenuOf.Unlock() - } - - return nil -} - -func (t *winTray) addSeparatorMenuItem(menuItemId, parentId uint32) error { - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx - const ( - MIIM_FTYPE = 0x00000100 - MIIM_ID = 0x00000002 - MIIM_STATE = 0x00000001 - ) - const MFT_SEPARATOR = 0x00000800 - - mi := menuItemInfo{ - Mask: MIIM_FTYPE | MIIM_ID | MIIM_STATE, - Type: MFT_SEPARATOR, - ID: uint32(menuItemId), - } - - mi.Size = uint32(unsafe.Sizeof(mi)) - - t.addToVisibleItems(parentId, menuItemId) - position := t.getVisibleItemIndex(parentId, menuItemId) - t.muMenus.RLock() - menu := uintptr(t.menus[parentId]) - t.muMenus.RUnlock() - res, _, err := pInsertMenuItem.Call( - menu, - uintptr(position), - 1, - uintptr(unsafe.Pointer(&mi)), - ) - if res == 0 { - return err - } - - return nil -} - -func (t *winTray) hideMenuItem(menuItemId, parentId uint32) error { - // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-removemenu - const MF_BYCOMMAND = 0x00000000 - const ERROR_SUCCESS syscall.Errno = 0 - - t.muMenus.RLock() - menu := uintptr(t.menus[parentId]) - t.muMenus.RUnlock() - res, _, err := pRemoveMenu.Call( - menu, - uintptr(menuItemId), - MF_BYCOMMAND, - ) - if res == 0 && err.(syscall.Errno) != ERROR_SUCCESS { - return err - } - t.delFromVisibleItems(parentId, menuItemId) - - return nil -} - -func (t *winTray) showMenu() error { - const ( - TPM_BOTTOMALIGN = 0x0020 - TPM_LEFTALIGN = 0x0000 - ) - p := point{} - res, _, err := pGetCursorPos.Call(uintptr(unsafe.Pointer(&p))) - if res == 0 { - return err - } - pSetForegroundWindow.Call(uintptr(t.window)) - - res, _, err = pTrackPopupMenu.Call( - uintptr(t.menus[0]), - TPM_BOTTOMALIGN|TPM_LEFTALIGN, - uintptr(p.X), - uintptr(p.Y), - 0, - uintptr(t.window), - 0, - ) - if res == 0 { - return err - } - - return nil -} - -func (t *winTray) delFromVisibleItems(parent, val uint32) { - t.muVisibleItems.Lock() - defer t.muVisibleItems.Unlock() - visibleItems := t.visibleItems[parent] - for i, itemval := range visibleItems { - if val == itemval { - t.visibleItems[parent] = append(visibleItems[:i], visibleItems[i+1:]...) - break - } - } -} - -func (t *winTray) addToVisibleItems(parent, val uint32) { - t.muVisibleItems.Lock() - defer t.muVisibleItems.Unlock() - if visibleItems, exists := t.visibleItems[parent]; !exists { - t.visibleItems[parent] = []uint32{val} - } else { - newvisible := append(visibleItems, val) - sort.Slice(newvisible, func(i, j int) bool { return newvisible[i] < newvisible[j] }) - t.visibleItems[parent] = newvisible - } -} - -func (t *winTray) getVisibleItemIndex(parent, val uint32) int { - t.muVisibleItems.RLock() - defer t.muVisibleItems.RUnlock() - for i, itemval := range t.visibleItems[parent] { - if val == itemval { - return i - } - } - return -1 -} - -// Loads an image from file to be shown in tray or menu item. -// LoadImage: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx -func (t *winTray) loadIconFrom(src string) (windows.Handle, error) { - const IMAGE_ICON = 1 // Loads an icon - const LR_LOADFROMFILE = 0x00000010 // Loads the stand-alone image from the file - const LR_DEFAULTSIZE = 0x00000040 // Loads default-size icon for windows(SM_CXICON x SM_CYICON) if cx, cy are set to zero - - // Save and reuse handles of loaded images - t.muLoadedImages.RLock() - h, ok := t.loadedImages[src] - t.muLoadedImages.RUnlock() - if !ok { - srcPtr, err := windows.UTF16PtrFromString(src) - if err != nil { - return 0, err - } - res, _, err := pLoadImage.Call( - 0, - uintptr(unsafe.Pointer(srcPtr)), - IMAGE_ICON, - 0, - 0, - LR_LOADFROMFILE|LR_DEFAULTSIZE, - ) - if res == 0 { - return 0, err - } - h = windows.Handle(res) - t.muLoadedImages.Lock() - t.loadedImages[src] = h - t.muLoadedImages.Unlock() - } - return h, nil -} - -func (t *winTray) iconToBitmap(hIcon windows.Handle) (windows.Handle, error) { - const SM_CXSMICON = 49 - const SM_CYSMICON = 50 - const DI_NORMAL = 0x3 - hDC, _, err := pGetDC.Call(uintptr(0)) - if hDC == 0 { - return 0, err - } - defer pReleaseDC.Call(uintptr(0), hDC) - hMemDC, _, err := pCreateCompatibleDC.Call(hDC) - if hMemDC == 0 { - return 0, err - } - defer pDeleteDC.Call(hMemDC) - cx, _, _ := pGetSystemMetrics.Call(SM_CXSMICON) - cy, _, _ := pGetSystemMetrics.Call(SM_CYSMICON) - hMemBmp, _, err := pCreateCompatibleBitmap.Call(hDC, cx, cy) - if hMemBmp == 0 { - return 0, err - } - hOriginalBmp, _, _ := pSelectObject.Call(hMemDC, hMemBmp) - defer pSelectObject.Call(hMemDC, hOriginalBmp) - res, _, err := pDrawIconEx.Call(hMemDC, 0, 0, uintptr(hIcon), cx, cy, 0, uintptr(0), DI_NORMAL) - if res == 0 { - return 0, err - } - return windows.Handle(hMemBmp), nil -} - -func registerSystray() { - if err := wt.initInstance(); err != nil { - log.Errorf("Unable to init instance: %v", err) - return - } - - if err := wt.createMenu(); err != nil { - log.Errorf("Unable to create menu: %v", err) - return - } - - systrayReady() -} - -func nativeLoop() { - // Main message pump. - m := &struct { - WindowHandle windows.Handle - Message uint32 - Wparam uintptr - Lparam uintptr - Time uint32 - Pt point - }{} - for { - ret, _, err := pGetMessage.Call(uintptr(unsafe.Pointer(m)), 0, 0, 0) - - // If the function retrieves a message other than WM_QUIT, the return value is nonzero. - // If the function retrieves the WM_QUIT message, the return value is zero. - // If there is an error, the return value is -1 - // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx - switch int32(ret) { - case -1: - log.Errorf("Error at message loop: %v", err) - return - case 0: - return - default: - pTranslateMessage.Call(uintptr(unsafe.Pointer(m))) - pDispatchMessage.Call(uintptr(unsafe.Pointer(m))) - } - } -} - -func quit() { - const WM_CLOSE = 0x0010 - - pPostMessage.Call( - uintptr(wt.window), - WM_CLOSE, - 0, - 0, - ) -} - -func iconBytesToFilePath(iconBytes []byte) (string, error) { - bh := md5.Sum(iconBytes) - dataHash := hex.EncodeToString(bh[:]) - iconFilePath := filepath.Join(os.TempDir(), "systray_temp_icon_"+dataHash) - - if _, err := os.Stat(iconFilePath); os.IsNotExist(err) { - if err := ioutil.WriteFile(iconFilePath, iconBytes, 0644); err != nil { - return "", err - } - } - return iconFilePath, nil -} - -// SetIcon sets the systray icon. -// iconBytes should be the content of .ico for windows and .ico/.jpg/.png -// for other platforms. -func SetIcon(iconBytes []byte) { - iconFilePath, err := iconBytesToFilePath(iconBytes) - if err != nil { - log.Errorf("Unable to write icon data to temp file: %v", err) - return - } - if err := wt.setIcon(iconFilePath); err != nil { - log.Errorf("Unable to set icon: %v", err) - return - } -} - -// SetTemplateIcon sets the systray icon as a template icon (on macOS), falling back -// to a regular icon on other platforms. -// templateIconBytes and iconBytes should be the content of .ico for windows and -// .ico/.jpg/.png for other platforms. -func SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) { - SetIcon(regularIconBytes) -} - -// SetTitle sets the systray title, only available on Mac and Linux. -func SetTitle(title string) { - // do nothing -} - -func (item *MenuItem) parentId() uint32 { - if item.parent != nil { - return uint32(item.parent.id) - } - return 0 -} - -// SetIcon sets the icon of a menu item. Only works on macOS and Windows. -// iconBytes should be the content of .ico/.jpg/.png -func (item *MenuItem) SetIcon(iconBytes []byte) { - iconFilePath, err := iconBytesToFilePath(iconBytes) - if err != nil { - log.Errorf("Unable to write icon data to temp file: %v", err) - return - } - - h, err := wt.loadIconFrom(iconFilePath) - if err != nil { - log.Errorf("Unable to load icon from temp file: %v", err) - return - } - - h, err = wt.iconToBitmap(h) - if err != nil { - log.Errorf("Unable to convert icon to bitmap: %v", err) - return - } - wt.muMenuItemIcons.Lock() - wt.menuItemIcons[uint32(item.id)] = h - wt.muMenuItemIcons.Unlock() - - err = wt.addOrUpdateMenuItem(uint32(item.id), item.parentId(), item.title, item.disabled, item.checked) - if err != nil { - log.Errorf("Unable to addOrUpdateMenuItem: %v", err) - return - } -} - -// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon, -// only available on Mac and Windows. -func SetTooltip(tooltip string) { - if err := wt.setTooltip(tooltip); err != nil { - log.Errorf("Unable to set tooltip: %v", err) - return - } -} - -func addOrUpdateMenuItem(item *MenuItem) { - err := wt.addOrUpdateMenuItem(uint32(item.id), item.parentId(), item.title, item.disabled, item.checked) - if err != nil { - log.Errorf("Unable to addOrUpdateMenuItem: %v", err) - return - } -} - -// SetTemplateIcon sets the icon of a menu item as a template icon (on macOS). On Windows, it -// falls back to the regular icon bytes and on Linux it does nothing. -// templateIconBytes and regularIconBytes should be the content of .ico for windows and -// .ico/.jpg/.png for other platforms. -func (item *MenuItem) SetTemplateIcon(templateIconBytes []byte, regularIconBytes []byte) { - item.SetIcon(regularIconBytes) -} - -func addSeparator(id uint32) { - err := wt.addSeparatorMenuItem(id, 0) - if err != nil { - log.Errorf("Unable to addSeparator: %v", err) - return - } -} - -func hideMenuItem(item *MenuItem) { - err := wt.hideMenuItem(uint32(item.id), item.parentId()) - if err != nil { - log.Errorf("Unable to hideMenuItem: %v", err) - return - } -} - -func showMenuItem(item *MenuItem) { - addOrUpdateMenuItem(item) -} diff --git a/vendor/github.com/getlantern/systray/webview_example/webview.h b/vendor/github.com/getlantern/systray/webview_example/webview.h deleted file mode 100644 index 2e39c6a8..00000000 --- a/vendor/github.com/getlantern/systray/webview_example/webview.h +++ /dev/null @@ -1,3 +0,0 @@ -void configureAppWindow(char* title, int width, int height); -void showAppWindow(char* url); - diff --git a/vendor/github.com/go-git/gcfg/v2/.gitignore b/vendor/github.com/go-git/gcfg/v2/.gitignore deleted file mode 100644 index 2d830686..00000000 --- a/vendor/github.com/go-git/gcfg/v2/.gitignore +++ /dev/null @@ -1 +0,0 @@ -coverage.out diff --git a/vendor/github.com/go-git/gcfg/v2/LICENSE b/vendor/github.com/go-git/gcfg/v2/LICENSE deleted file mode 100644 index 87a5cede..00000000 --- a/vendor/github.com/go-git/gcfg/v2/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2012 Péter Surányi. Portions Copyright (c) 2009 The Go -Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/go-git/gcfg/v2/Makefile b/vendor/github.com/go-git/gcfg/v2/Makefile deleted file mode 100644 index e8d7cc1e..00000000 --- a/vendor/github.com/go-git/gcfg/v2/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# General -WORKDIR = $(PWD) - -# Go parameters -GOCMD = go -GOTEST = $(GOCMD) test - -# Coverage -COVERAGE_REPORT = coverage.out -COVERAGE_MODE = count - -test: - $(GOTEST) -race ./... - -test-coverage: - echo "" > $(COVERAGE_REPORT); \ - $(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./... diff --git a/vendor/github.com/go-git/gcfg/v2/README b/vendor/github.com/go-git/gcfg/v2/README deleted file mode 100644 index 1ff233a5..00000000 --- a/vendor/github.com/go-git/gcfg/v2/README +++ /dev/null @@ -1,4 +0,0 @@ -Gcfg reads INI-style configuration files into Go structs; -supports user-defined types and subsections. - -Package docs: https://godoc.org/gopkg.in/gcfg.v1 diff --git a/vendor/github.com/go-git/gcfg/v2/doc.go b/vendor/github.com/go-git/gcfg/v2/doc.go deleted file mode 100644 index dfefb405..00000000 --- a/vendor/github.com/go-git/gcfg/v2/doc.go +++ /dev/null @@ -1,142 +0,0 @@ -// Package gcfg reads "INI-style" text-based configuration files with -// "name=value" pairs grouped into sections (gcfg files). -// -// This package is still a work in progress; see the sections below for planned -// changes. -// -// # Syntax -// -// The syntax is based on that used by git config: -// http://git-scm.com/docs/git-config#_syntax . -// There are some (planned) differences compared to the git config format: -// - improve data portability: -// - must be encoded in UTF-8 (for now) and must not contain the 0 byte -// - include and "path" type is not supported -// (path type may be implementable as a user-defined type) -// - internationalization -// - section and variable names can contain unicode letters, unicode digits -// (as defined in http://golang.org/ref/spec#Characters ) and hyphens -// (U+002D), starting with a unicode letter -// - disallow potentially ambiguous or misleading definitions: -// - `[sec.sub]` format is not allowed (deprecated in gitconfig) -// - `[sec ""]` is not allowed -// - use `[sec]` for section name "sec" and empty subsection name -// - (planned) within a single file, definitions must be contiguous for each: -// - section: '[secA]' -> '[secB]' -> '[secA]' is an error -// - subsection: '[sec "A"]' -> '[sec "B"]' -> '[sec "A"]' is an error -// - multivalued variable: 'multi=a' -> 'other=x' -> 'multi=b' is an error -// -// # Data structure -// -// The functions in this package read values into a user-defined struct. -// Each section corresponds to a struct field in the config struct, and each -// variable in a section corresponds to a data field in the section struct. -// The mapping of each section or variable name to fields is done either based -// on the "gcfg" struct tag or by matching the name of the section or variable, -// ignoring case. In the latter case, hyphens '-' in section and variable names -// correspond to underscores '_' in field names. -// Fields must be exported; to use a section or variable name starting with a -// letter that is neither upper- or lower-case, prefix the field name with 'X'. -// (See https://code.google.com/p/go/issues/detail?id=5763#c4 .) -// -// For sections with subsections, the corresponding field in config must be a -// map, rather than a struct, with string keys and pointer-to-struct values. -// Values for subsection variables are stored in the map with the subsection -// name used as the map key. -// (Note that unlike section and variable names, subsection names are case -// sensitive.) -// When using a map, and there is a section with the same section name but -// without a subsection name, its values are stored with the empty string used -// as the key. -// It is possible to provide default values for subsections in the section -// "default-" (or by setting values in the corresponding struct -// field "Default_"). -// -// The functions in this package error if config is not a pointer to a struct, -// or when a field is not of a suitable type (either a struct or a map with -// string keys and pointer-to-struct values). -// -// # Parsing of values -// -// The section structs in the config struct may contain single-valued or -// multi-valued variables. Variables of unnamed slice type (that is, a type -// starting with `[]`) are treated as multi-value; all others (including named -// slice types) are treated as single-valued variables. -// -// Single-valued variables are handled based on the type as follows. -// Unnamed pointer types (that is, types starting with `*`) are dereferenced, -// and if necessary, a new instance is allocated. -// -// For types implementing the encoding.TextUnmarshaler interface, the -// UnmarshalText method is used to set the value. Implementing this method is -// the recommended way for parsing user-defined types. -// -// For fields of string kind, the value string is assigned to the field, after -// unquoting and unescaping as needed. -// For fields of bool kind, the field is set to true if the value is "true", -// "yes", "on" or "1", and set to false if the value is "false", "no", "off" or -// "0", ignoring case. In addition, single-valued bool fields can be specified -// with a "blank" value (variable name without equals sign and value); in such -// case the value is set to true. -// -// Predefined integer types [u]int(|8|16|32|64) and big.Int are parsed as -// decimal or hexadecimal (if having '0x' prefix). (This is to prevent -// unintuitively handling zero-padded numbers as octal.) Other types having -// [u]int* as the underlying type, such as os.FileMode and uintptr allow -// decimal, hexadecimal, or octal values. -// Parsing mode for integer types can be overridden using the struct tag option -// ",int=mode" where mode is a combination of the 'd', 'h', and 'o' characters -// (each standing for decimal, hexadecimal, and octal, respectively.) -// -// All other types are parsed using fmt.Sscanf with the "%v" verb. -// -// For multi-valued variables, each individual value is parsed as above and -// appended to the slice. If the first value is specified as a "blank" value -// (variable name without equals sign and value), a new slice is allocated; -// that is any values previously set in the slice will be ignored. -// -// The types subpackage for provides helpers for parsing "enum-like" and integer -// types. -// -// # Error handling -// -// There are 3 types of errors: -// -// 1. Logic errors: invalid configuration structure. -// 2. Data errors (fatal): invalid configuration syntax. -// 3. Data errors (warning): data that doesn't belong to any part of the config -// structure. - -// All errors are handled via Go's built-in error convention. Warnings regarding -// data errors are wrapped around ErrSyntaxWarning, so that it can be more easily -// identified by consumers. This library do not cause panics. -// -// Data errors cause gcfg to return a non-nil error value. This includes the -// case when there are extra unknown key-value definitions in the configuration -// data (extra data). -// However, in some occasions it is desirable to be able to proceed in -// situations when the only data error is that of extra data. -// These errors are handled at a different (warning) priority and can be -// filtered out programmatically. To ignore extra data warnings, wrap the -// gcfg.Read*Into invocation into a call to gcfg.FatalOnly. -// -// # TODO -// -// The following is a list of changes under consideration: -// - documentation -// - self-contained syntax documentation -// - more practical examples -// - move TODOs to issue tracker (eventually) -// - syntax -// - reconsider valid escape sequences -// (gitconfig doesn't support \r in value, \t in subsection name, etc.) -// - reading / parsing gcfg files -// - define internal representation structure -// - support multiple inputs (readers, strings, files) -// - support declaring encoding (?) -// - support varying fields sets for subsections (?) -// - writing gcfg files -// - error handling -// - make error context accessible programmatically? -// - limit input size? -package gcfg diff --git a/vendor/github.com/go-git/gcfg/v2/errors.go b/vendor/github.com/go-git/gcfg/v2/errors.go deleted file mode 100644 index b1d444c1..00000000 --- a/vendor/github.com/go-git/gcfg/v2/errors.go +++ /dev/null @@ -1,50 +0,0 @@ -package gcfg - -import ( - "errors" - "fmt" -) - -var ( - ErrSyntaxWarning = errors.New("syntax warning") - - ErrMissingEscapeSequence = errors.New("missing escape sequence") - ErrMissingEndQuote = errors.New("missing end quote") -) - -// FatalOnly filters the results of a Read*Into invocation and returns only -// fatal errors. That is, errors (warnings) indicating data for unknown -// sections / variables is ignored. Example invocation: -// -// err := gcfg.FatalOnly(gcfg.ReadFileInto(&cfg, configFile)) -// if err != nil { -// ... -func FatalOnly(err error) error { - for { - if err == nil { - return nil - } - err = errors.Unwrap(err) - if !errors.Is(err, ErrSyntaxWarning) { - return err - } - } -} - -func newSyntaxWarning(sec, sub, variable string) error { - msg := fmt.Sprintf("can't store data in section %q", sec) - if sub != "" { - msg += fmt.Sprintf(", subsection %q", sub) - } - if variable != "" { - msg += fmt.Sprintf(", variable %q", variable) - } - return fmt.Errorf("%w: %s", ErrSyntaxWarning, msg) -} - -func joinNonFatal(prev, cur error) (error, bool) { - if !errors.Is(cur, ErrSyntaxWarning) { - return cur, true - } - return errors.Join(prev, cur), false -} diff --git a/vendor/github.com/go-git/gcfg/v2/read.go b/vendor/github.com/go-git/gcfg/v2/read.go deleted file mode 100644 index 2879e7a6..00000000 --- a/vendor/github.com/go-git/gcfg/v2/read.go +++ /dev/null @@ -1,301 +0,0 @@ -package gcfg - -import ( - "fmt" - "io" - "os" - "strings" - - "github.com/go-git/gcfg/v2/scanner" - "github.com/go-git/gcfg/v2/token" -) - -var unescape = map[rune]rune{'\\': '\\', '"': '"', 'n': '\n', 't': '\t', 'b': '\b', '\n': '\n'} - -// no error: invalid literals should be caught by scanner -func unquote(s string) (string, error) { - u, q, esc := make([]rune, 0, len(s)), false, false - for _, c := range s { - if esc { - uc, ok := unescape[c] - switch { - case ok: - u = append(u, uc) - fallthrough - case !q && c == '\n': - esc = false - continue - } - return "", ErrMissingEscapeSequence - } - switch c { - case '"': - q = !q - case '\\': - esc = true - default: - u = append(u, c) - } - } - if q { - return "", ErrMissingEndQuote - } - if esc { - return "", ErrMissingEscapeSequence - } - return string(u), nil -} - -func read(callback func(string, string, string, string, bool) error, - fset *token.FileSet, file *token.File, src []byte) error { - // - var s scanner.Scanner - var errs scanner.ErrorList - s.Init(file, src, func(p token.Position, m string) { errs.Add(p, m) }, 0) - sect, sectsub := "", "" - pos, tok, lit, err := s.Scan() - errfn := func(msg string) error { - return fmt.Errorf("%s: %s", fset.Position(pos), msg) - } - if err != nil { - return err - } - var accErr error - for { - if errs.Len() > 0 { - if err, fatal := joinNonFatal(accErr, errs.Err()); fatal { - return err - } - } - switch tok { - case token.EOF: - return nil - case token.EOL, token.COMMENT: - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - case token.LBRACK: - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - if errs.Len() > 0 { - if err, fatal := joinNonFatal(accErr, errs.Err()); fatal { - return err - } - } - if tok != token.IDENT { - if err, fatal := joinNonFatal(accErr, errfn("expected section name")); fatal { - return err - } - } - sect, sectsub = lit, "" - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - if errs.Len() > 0 { - if err, fatal := joinNonFatal(accErr, errs.Err()); fatal { - return err - } - } - if tok == token.STRING { - ss, err := unquote(lit) - if err != nil { - return err - } - - sectsub = ss - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - if errs.Len() > 0 { - if err, fatal := joinNonFatal(accErr, errs.Err()); fatal { - return err - } - } - } - if tok != token.RBRACK { - if err, fatal := joinNonFatal(accErr, errfn("expected right bracket")); fatal { - return err - } - } - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - if tok != token.EOL && tok != token.EOF && tok != token.COMMENT { - if err, fatal := joinNonFatal(accErr, errfn("expected EOL, EOF, or comment")); fatal { - return err - } - } - // If a section/subsection header was found, ensure a - // container object is created, even if there are no - // variables further down. - err := callback(sect, sectsub, "", "", true) - if err != nil { - return err - } - case token.IDENT: - if sect == "" { - if err, fatal := joinNonFatal(accErr, errfn("expected section header")); fatal { - return err - } - } - n := lit - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - if errs.Len() > 0 { - return errs.Err() - } - blank, v := tok == token.EOF || tok == token.EOL || tok == token.COMMENT, "" - if !blank { - if tok != token.ASSIGN { - if err, fatal := joinNonFatal(accErr, errfn("expected '='")); fatal { - return err - } - } - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - if errs.Len() > 0 { - if err, fatal := joinNonFatal(accErr, errs.Err()); fatal { - return err - } - } - if tok != token.STRING { - if err, fatal := joinNonFatal(accErr, errfn("expected value")); fatal { - return err - } - } - unq, err := unquote(lit) - if err != nil { - return err - } - - v = unq - pos, tok, lit, err = s.Scan() - if err != nil { - return err - } - if errs.Len() > 0 { - if err, fatal := joinNonFatal(accErr, errs.Err()); fatal { - return err - } - } - if tok != token.EOL && tok != token.EOF && tok != token.COMMENT { - if err, fatal := joinNonFatal(accErr, errfn("expected EOL, EOF, or comment")); fatal { - return err - } - } - } - err := callback(sect, sectsub, n, v, blank) - if err != nil { - return err - } - default: - if sect == "" { - if err, fatal := joinNonFatal(accErr, errfn("expected section header")); fatal { - return err - } - } - if err, fatal := joinNonFatal(accErr, errfn("expected section header or variable declaration")); fatal { - return err - } - } - } -} - -func readInto(config interface{}, fset *token.FileSet, file *token.File, - src []byte) error { - // - firstPassCallback := func(s string, ss string, k string, v string, bv bool) error { - return set(config, s, ss, k, v, bv, false) - } - err := read(firstPassCallback, fset, file, src) - if err != nil { - return err - } - secondPassCallback := func(s string, ss string, k string, v string, bv bool) error { - return set(config, s, ss, k, v, bv, true) - } - return read(secondPassCallback, fset, file, src) -} - -// ReadWithCallback reads gcfg formatted data from reader and calls -// callback with each section and option found. -// -// Callback is called with section, subsection, option key, option value -// and blank value flag as arguments. -// -// When a section is found, callback is called with nil subsection, option key -// and option value. -// -// When a subsection is found, callback is called with nil option key and -// option value. -// -// If blank value flag is true, it means that the value was not set for an option -// (as opposed to set to empty string). -// -// If callback returns an error, ReadWithCallback terminates with an error too. -func ReadWithCallback(reader io.Reader, callback func(string, string, string, string, bool) error) error { - src, err := io.ReadAll(reader) - if err != nil { - return err - } - - fset := token.NewFileSet() - file, err := fset.AddFile("", fset.Base(), len(src)) - if err != nil { - return err - } - - return read(callback, fset, file, src) -} - -// ReadInto reads gcfg formatted data from reader and sets the values into the -// corresponding fields in config. -func ReadInto(config interface{}, reader io.Reader) error { - src, err := io.ReadAll(reader) - if err != nil { - return err - } - fset := token.NewFileSet() - file, err := fset.AddFile("", fset.Base(), len(src)) - if err != nil { - return err - } - return readInto(config, fset, file, src) -} - -// ReadStringInto reads gcfg formatted data from str and sets the values into -// the corresponding fields in config. -func ReadStringInto(config interface{}, str string) error { - r := strings.NewReader(str) - return ReadInto(config, r) -} - -// ReadFileInto reads gcfg formatted data from the file filename and sets the -// values into the corresponding fields in config. -func ReadFileInto(config interface{}, filename string) error { - f, err := os.Open(filename) - if err != nil { - return err - } - defer f.Close() - src, err := io.ReadAll(f) - if err != nil { - return err - } - fset := token.NewFileSet() - file, err := fset.AddFile(filename, fset.Base(), len(src)) - if err != nil { - return err - } - return readInto(config, fset, file, src) -} diff --git a/vendor/github.com/go-git/gcfg/v2/scanner/errors.go b/vendor/github.com/go-git/gcfg/v2/scanner/errors.go deleted file mode 100644 index 6d42210f..00000000 --- a/vendor/github.com/go-git/gcfg/v2/scanner/errors.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2009 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 scanner - -import ( - "fmt" - "io" - "sort" - - "github.com/go-git/gcfg/v2/token" -) - -// In an ErrorList, an error is represented by an *Error. -// The position Pos, if valid, points to the beginning of -// the offending token, and the error condition is described -// by Msg. -type Error struct { - Pos token.Position - Msg string -} - -// Error implements the error interface. -func (e Error) Error() string { - if e.Pos.Filename != "" || e.Pos.IsValid() { - // don't print "" - // TODO(gri) reconsider the semantics of Position.IsValid - return e.Pos.String() + ": " + e.Msg - } - return e.Msg -} - -// ErrorList is a list of *Errors. -// The zero value for an ErrorList is an empty ErrorList ready to use. -type ErrorList []*Error - -// Add adds an Error with given position and error message to an ErrorList. -func (p *ErrorList) Add(pos token.Position, msg string) { - *p = append(*p, &Error{pos, msg}) -} - -// Reset resets an ErrorList to no errors. -func (p *ErrorList) Reset() { *p = (*p)[0:0] } - -// ErrorList implements the sort Interface. -func (p ErrorList) Len() int { return len(p) } -func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -func (p ErrorList) Less(i, j int) bool { - e := &p[i].Pos - f := &p[j].Pos - if e.Filename < f.Filename { - return true - } - if e.Filename == f.Filename { - return e.Offset < f.Offset - } - return false -} - -// Sort sorts an ErrorList. *Error entries are sorted by position, -// other errors are sorted by error message, and before any *Error -// entry. -func (p ErrorList) Sort() { - sort.Sort(p) -} - -// RemoveMultiples sorts an ErrorList and removes all but the first error per line. -func (p *ErrorList) RemoveMultiples() { - sort.Sort(p) - var last token.Position // initial last.Line is != any legal error line - i := 0 - for _, e := range *p { - if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line { - last = e.Pos - (*p)[i] = e - i++ - } - } - (*p) = (*p)[0:i] -} - -// An ErrorList implements the error interface. -func (p ErrorList) Error() string { - switch len(p) { - case 0: - return "no errors" - case 1: - return p[0].Error() - } - return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1) -} - -// Err returns an error equivalent to this error list. -// If the list is empty, Err returns nil. -func (p ErrorList) Err() error { - if len(p) == 0 { - return nil - } - return p -} - -// PrintError is a utility function that prints a list of errors to w, -// one error per line, if the err parameter is an ErrorList. Otherwise -// it prints the err string. -func PrintError(w io.Writer, err error) { - if list, ok := err.(ErrorList); ok { - for _, e := range list { - fmt.Fprintf(w, "%s\n", e) - } - } else if err != nil { - fmt.Fprintf(w, "%s\n", err) - } -} diff --git a/vendor/github.com/go-git/gcfg/v2/scanner/scanner.go b/vendor/github.com/go-git/gcfg/v2/scanner/scanner.go deleted file mode 100644 index d5813c00..00000000 --- a/vendor/github.com/go-git/gcfg/v2/scanner/scanner.go +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright 2009 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 scanner implements a scanner for gcfg configuration text. -// It takes a []byte as source which can then be tokenized -// through repeated calls to the Scan method. -// -// Note that the API for the scanner package may change to accommodate new -// features or implementation changes in gcfg. -package scanner - -import ( - "errors" - "fmt" - "path/filepath" - "unicode" - "unicode/utf8" - - "github.com/go-git/gcfg/v2/token" -) - -var ErrSourceLenAndSizeMismatch = errors.New("source length and file size mismatch") - -// An ErrorHandler may be provided to Scanner.Init. If a syntax error is -// encountered and a handler was installed, the handler is called with a -// position and an error message. The position points to the beginning of -// the offending token. -type ErrorHandler func(pos token.Position, msg string) - -// A Scanner holds the scanner's internal state while processing -// a given text. It can be allocated as part of another data -// structure but must be initialized via Init before use. -type Scanner struct { - // immutable state - file *token.File // source file handle - dir string // directory portion of file.Name() - src []byte // source - err ErrorHandler // error reporting; or nil - mode Mode // scanning mode - - // scanning state - ch rune // current character - offset int // character offset - rdOffset int // reading offset (position after current character) - lineOffset int // current line offset - nextVal bool // next token is expected to be a value - - // public state - ok to modify - ErrorCount int // number of errors encountered -} - -// Read the next Unicode char into s.ch. -// s.ch < 0 means end-of-file. -func (s *Scanner) next() error { - if s.rdOffset < len(s.src) { - s.offset = s.rdOffset - if s.ch == '\n' { - s.lineOffset = s.offset - s.file.AddLine(s.offset) - } - r, w := rune(s.src[s.rdOffset]), 1 - switch { - case r == 0: - err := s.error(s.offset, "illegal character NUL") - if err != nil { - return err - } - case r >= 0x80: - // not ASCII - r, w = utf8.DecodeRune(s.src[s.rdOffset:]) - if r == utf8.RuneError && w == 1 { - err := s.error(s.offset, "illegal UTF-8 encoding") - if err != nil { - return err - } - } - } - s.rdOffset += w - s.ch = r - } else { - s.offset = len(s.src) - if s.ch == '\n' { - s.lineOffset = s.offset - s.file.AddLine(s.offset) - } - s.ch = -1 // eof - } - return nil -} - -// A mode value is a set of flags (or 0). -// They control scanner behavior. -type Mode uint - -const ( - ScanComments Mode = 1 << iota // return comments as COMMENT tokens -) - -// Init prepares the scanner s to tokenize the text src by setting the -// scanner at the beginning of src. The scanner uses the file set file -// for position information and it adds line information for each line. -// It is ok to re-use the same file when re-scanning the same file as -// line information which is already present is ignored. Init returns -// ErrSourceLenAndSizeMismatch if the file size does not match the src -// size. -// -// Calls to Scan will invoke the error handler err if they encounter a -// syntax error and err is not nil. Also, for each error encountered, -// the Scanner field ErrorCount is incremented by one. The mode parameter -// determines how comments are handled. -// -// Note that Init may call err if there is an error in the first character -// of the file. -func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) error { - // Explicitly initialize all fields since a scanner may be reused. - if file.Size() != len(src) { - return fmt.Errorf("%w: file size (%d) src len (%d)", - ErrSourceLenAndSizeMismatch, file.Size(), len(src)) - } - s.file = file - s.dir, _ = filepath.Split(file.Name()) - s.src = src - s.err = err - s.mode = mode - - s.ch = ' ' - s.offset = 0 - s.rdOffset = 0 - s.lineOffset = 0 - s.ErrorCount = 0 - s.nextVal = false - - s.next() - return nil -} - -func (s *Scanner) error(offs int, msg string) error { - if s.err != nil { - pos, err := s.file.Pos(offs) - if err != nil { - return err - } - position, err := s.file.Position(pos) - if err != nil { - return err - } - s.err(position, msg) - } - s.ErrorCount++ - return nil -} - -func (s *Scanner) scanComment() string { - // initial [;#] already consumed - offs := s.offset - 1 // position of initial [;#] - - for s.ch != '\n' && s.ch >= 0 { - s.next() - } - return string(s.src[offs:s.offset]) -} - -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch >= 0x80 && unicode.IsLetter(ch) -} - -func isDigit(ch rune) bool { - return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) -} - -func (s *Scanner) scanIdentifier() string { - offs := s.offset - for isLetter(s.ch) || isDigit(s.ch) || s.ch == '-' { - s.next() - } - return string(s.src[offs:s.offset]) -} - -// val indicate if we are scanning a value (vs a header) -func (s *Scanner) scanEscape(val bool) error { - offs := s.offset - ch := s.ch - s.next() // always make progress - switch ch { - case '\\', '"', '\n': - // ok - case 'n', 't', 'b': - if val { - break // ok - } - fallthrough - default: - err := s.error(offs, "unknown escape sequence") - if err != nil { - return err - } - } - return nil -} - -func (s *Scanner) scanString() (string, error) { - // '"' opening already consumed - offs := s.offset - 1 - - for s.ch != '"' { - ch := s.ch - s.next() - if ch == '\n' || ch < 0 { - err := s.error(offs, "string not terminated") - if err != nil { - return "", err - } - break - } - if ch == '\\' { - s.scanEscape(false) - } - } - - err := s.next() - if err != nil { - return "", err - } - - return string(s.src[offs:s.offset]), nil -} - -func stripCR(b []byte) []byte { - c := make([]byte, len(b)) - i := 0 - for _, ch := range b { - if ch != '\r' { - c[i] = ch - i++ - } - } - return c[:i] -} - -func (s *Scanner) scanValString() (string, error) { - offs := s.offset - - hasCR := false - end := offs - inQuote := false -loop: - for inQuote || s.ch >= 0 && s.ch != '\n' && s.ch != ';' && s.ch != '#' { - ch := s.ch - s.next() - switch { - case inQuote && ch == '\\': - s.scanEscape(true) - case !inQuote && ch == '\\': - if s.ch == '\r' { - hasCR = true - s.next() - } - if s.ch != '\n' { - s.scanEscape(true) - } else { - s.next() - } - case ch == '"': - inQuote = !inQuote - case ch == '\r': - hasCR = true - case ch < 0 || inQuote && ch == '\n': - err := s.error(offs, "string not terminated") - if err != nil { - return "", err - } - break loop - } - if inQuote || !isWhiteSpace(ch) { - end = s.offset - } - } - - lit := s.src[offs:end] - if hasCR { - lit = stripCR(lit) - } - - return string(lit), nil -} - -func isWhiteSpace(ch rune) bool { - return ch == ' ' || ch == '\t' || ch == '\r' -} - -func (s *Scanner) skipWhitespace() { - for isWhiteSpace(s.ch) { - s.next() - } -} - -// Scan scans the next token and returns the token position, the token, -// and its literal string if applicable. The source end is indicated by -// token.EOF. -// -// If the returned token is a literal (token.IDENT, token.STRING) or -// token.COMMENT, the literal string has the corresponding value. -// -// If the returned token is token.ILLEGAL, the literal string is the -// offending character. -// -// In all other cases, Scan returns an empty literal string. -// -// For more tolerant parsing, Scan will return a valid token if -// possible even if a syntax error was encountered. Thus, even -// if the resulting token sequence contains no illegal tokens, -// a client may not assume that no error occurred. Instead it -// must check the scanner's ErrorCount or the number of calls -// of the error handler, if there was one installed. -// -// Scan adds line information to the file added to the file -// set with Init. Token positions are relative to that file -// and thus relative to the file set. -func (s *Scanner) Scan() (pos token.Pos, tok token.Token, lit string, err error) { -scanAgain: - s.skipWhitespace() - - // current token start - p, err2 := s.file.Pos(s.offset) - if err2 != nil { - err = fmt.Errorf("unexpected error at pos %v offset %d: %w", p, s.offset, err2) - return - } - pos = p - - // determine token value - switch ch := s.ch; { - case s.nextVal: - l, err2 := s.scanValString() - if err2 != nil { - err = fmt.Errorf("unexpected error at ch %v: %w", ch, err2) - return - } - lit = l - tok = token.STRING - s.nextVal = false - case isLetter(ch): - lit = s.scanIdentifier() - tok = token.IDENT - default: - s.next() // always make progress - switch ch { - case -1: - tok = token.EOF - case '\n': - tok = token.EOL - case '"': - tok = token.STRING - l, err2 := s.scanString() - if err2 != nil { - err = fmt.Errorf("unexpected error at ch %v: %w", ch, err2) - return - } - lit = l - case '[': - tok = token.LBRACK - case ']': - tok = token.RBRACK - case ';', '#': - // comment - lit = s.scanComment() - if s.mode&ScanComments == 0 { - // skip comment - goto scanAgain - } - tok = token.COMMENT - case '=': - tok = token.ASSIGN - s.nextVal = true - default: - offset, err2 := s.file.Offset(pos) - if err2 != nil { - err = fmt.Errorf("unexpected error at pos %v: %w", pos, err2) - return - } - - err2 = s.error(offset, fmt.Sprintf("illegal character %#U", ch)) - if err2 != nil { - err = fmt.Errorf("unexpected error at ch %v offset %d: %w", ch, s.offset, err2) - return - } - tok = token.ILLEGAL - lit = string(ch) - } - } - - return -} diff --git a/vendor/github.com/go-git/gcfg/v2/set.go b/vendor/github.com/go-git/gcfg/v2/set.go deleted file mode 100644 index 725dec17..00000000 --- a/vendor/github.com/go-git/gcfg/v2/set.go +++ /dev/null @@ -1,337 +0,0 @@ -package gcfg - -import ( - "bytes" - "encoding" - "encoding/gob" - "errors" - "fmt" - "math/big" - "reflect" - "strings" - "unicode" - "unicode/utf8" - - "github.com/go-git/gcfg/v2/types" -) - -var ( - ErrUnsupportedType = errors.New("unsupported type") - ErrBlankUnsupported = errors.New("blank value not supported for type") - ErrConfigMustBePointerToStruct = errors.New("config must be a pointer to a struct") - ErrInvalidMapFieldForSection = errors.New("map field for section must have string keys and pointer-to-struct values") - ErrInvalidFieldForSection = errors.New("field for section must be a map or a struct") -) - -type tag struct { - ident string - intMode string -} - -func newTag(ts string) tag { - t := tag{} - s := strings.Split(ts, ",") - t.ident = s[0] - for _, tse := range s[1:] { - if strings.HasPrefix(tse, "int=") { - t.intMode = tse[len("int="):] - } - } - return t -} - -func fieldFold(v reflect.Value, name string) (reflect.Value, tag) { - var n string - r0, _ := utf8.DecodeRuneInString(name) - if unicode.IsLetter(r0) && !unicode.IsLower(r0) && !unicode.IsUpper(r0) { - n = "X" - } - n += strings.Replace(name, "-", "_", -1) - f, ok := v.Type().FieldByNameFunc(func(fieldName string) bool { - if !v.FieldByName(fieldName).CanSet() { - return false - } - f, _ := v.Type().FieldByName(fieldName) - t := newTag(f.Tag.Get("gcfg")) - if t.ident != "" { - return strings.EqualFold(t.ident, name) - } - return strings.EqualFold(n, fieldName) - }) - if !ok { - return reflect.Value{}, tag{} - } - return v.FieldByName(f.Name), newTag(f.Tag.Get("gcfg")) -} - -type setter func(destp interface{}, blank bool, val string, t tag) error - -var setters = []setter{ - typeSetter, textUnmarshalerSetter, kindSetter, scanSetter, -} - -func textUnmarshalerSetter(d interface{}, blank bool, val string, t tag) error { - dtu, ok := d.(encoding.TextUnmarshaler) - if !ok { - return ErrUnsupportedType - } - if blank { - return ErrBlankUnsupported - } - return dtu.UnmarshalText([]byte(val)) -} - -func boolSetter(d interface{}, blank bool, val string, t tag) error { - if blank { - reflect.ValueOf(d).Elem().Set(reflect.ValueOf(true)) - return nil - } - b, err := types.ParseBool(val) - if err == nil { - reflect.ValueOf(d).Elem().Set(reflect.ValueOf(b)) - } - return err -} - -func intMode(mode string) types.IntMode { - var m types.IntMode - if strings.ContainsAny(mode, "dD") { - m |= types.Dec - } - if strings.ContainsAny(mode, "hH") { - m |= types.Hex - } - if strings.ContainsAny(mode, "oO") { - m |= types.Oct - } - return m -} - -var typeModes = map[reflect.Type]types.IntMode{ - reflect.TypeOf(int(0)): types.Dec | types.Hex, - reflect.TypeOf(int8(0)): types.Dec | types.Hex, - reflect.TypeOf(int16(0)): types.Dec | types.Hex, - reflect.TypeOf(int32(0)): types.Dec | types.Hex, - reflect.TypeOf(int64(0)): types.Dec | types.Hex, - reflect.TypeOf(uint(0)): types.Dec | types.Hex, - reflect.TypeOf(uint8(0)): types.Dec | types.Hex, - reflect.TypeOf(uint16(0)): types.Dec | types.Hex, - reflect.TypeOf(uint32(0)): types.Dec | types.Hex, - reflect.TypeOf(uint64(0)): types.Dec | types.Hex, - // use default mode (allow dec/hex/oct) for uintptr type - reflect.TypeOf(big.Int{}): types.Dec | types.Hex, -} - -func intModeDefault(t reflect.Type) types.IntMode { - m, ok := typeModes[t] - if !ok { - m = types.Dec | types.Hex | types.Oct - } - return m -} - -func intSetter(d interface{}, blank bool, val string, t tag) error { - if blank { - return ErrBlankUnsupported - } - mode := intMode(t.intMode) - if mode == 0 { - mode = intModeDefault(reflect.TypeOf(d).Elem()) - } - return types.ParseInt(d, val, mode) -} - -func stringSetter(d interface{}, blank bool, val string, t tag) error { - if blank { - return ErrBlankUnsupported - } - dsp, ok := d.(*string) - if !ok { - return ErrUnsupportedType - } - *dsp = val - return nil -} - -var kindSetters = map[reflect.Kind]setter{ - reflect.String: stringSetter, - reflect.Bool: boolSetter, - reflect.Int: intSetter, - reflect.Int8: intSetter, - reflect.Int16: intSetter, - reflect.Int32: intSetter, - reflect.Int64: intSetter, - reflect.Uint: intSetter, - reflect.Uint8: intSetter, - reflect.Uint16: intSetter, - reflect.Uint32: intSetter, - reflect.Uint64: intSetter, - reflect.Uintptr: intSetter, -} - -var typeSetters = map[reflect.Type]setter{ - reflect.TypeOf(big.Int{}): intSetter, -} - -func typeSetter(d interface{}, blank bool, val string, tt tag) error { - t := reflect.ValueOf(d).Type().Elem() - setter, ok := typeSetters[t] - if !ok { - return ErrUnsupportedType - } - return setter(d, blank, val, tt) -} - -func kindSetter(d interface{}, blank bool, val string, tt tag) error { - k := reflect.ValueOf(d).Type().Elem().Kind() - setter, ok := kindSetters[k] - if !ok { - return ErrUnsupportedType - } - return setter(d, blank, val, tt) -} - -func scanSetter(d interface{}, blank bool, val string, tt tag) error { - if blank { - return ErrBlankUnsupported - } - return types.ScanFully(d, val, 'v') -} - -func newValue(sect string, vCfg reflect.Value, - vType reflect.Type) (reflect.Value, error) { - // - pv := reflect.New(vType) - dfltName := "default-" + sect - dfltField, _ := fieldFold(vCfg, dfltName) - var err error - if dfltField.IsValid() { - b := bytes.NewBuffer(nil) - ge := gob.NewEncoder(b) - err = ge.EncodeValue(dfltField) - if err != nil && errors.Is(err, ErrSyntaxWarning) { - return pv, err - } - - gd := gob.NewDecoder(bytes.NewReader(b.Bytes())) - err = gd.DecodeValue(pv.Elem()) - if err != nil && errors.Is(err, ErrSyntaxWarning) { - return pv, err - } - } - return pv, nil -} - -func set(cfg interface{}, sect, sub, name string, - value string, blankValue bool, subsectPass bool) error { - // - vPCfg := reflect.ValueOf(cfg) - if vPCfg.Kind() != reflect.Ptr || vPCfg.Elem().Kind() != reflect.Struct { - return ErrConfigMustBePointerToStruct - } - vCfg := vPCfg.Elem() - vSect, _ := fieldFold(vCfg, sect) - if !vSect.IsValid() { - return newSyntaxWarning(sect, "", "") - } - isSubsect := vSect.Kind() == reflect.Map - if subsectPass != isSubsect { - return nil - } - if isSubsect { - vst := vSect.Type() - if vst.Key().Kind() != reflect.String || - vst.Elem().Kind() != reflect.Ptr || - vst.Elem().Elem().Kind() != reflect.Struct { - return fmt.Errorf("%w: section %q", ErrInvalidMapFieldForSection, sect) - } - if vSect.IsNil() { - vSect.Set(reflect.MakeMap(vst)) - } - k := reflect.ValueOf(sub) - pv := vSect.MapIndex(k) - if !pv.IsValid() { - vType := vSect.Type().Elem().Elem() - var err error - if pv, err = newValue(sect, vCfg, vType); err != nil { - return err - } - vSect.SetMapIndex(k, pv) - } - vSect = pv.Elem() - } else if vSect.Kind() != reflect.Struct { - return fmt.Errorf("%w: section %q", ErrInvalidFieldForSection, sect) - } else if sub != "" { - return newSyntaxWarning(sect, sub, "") - } - // Empty name is a special value, meaning that only the - // section/subsection object is to be created, with no values set. - if name == "" { - return nil - } - vVar, t := fieldFold(vSect, name) - if !vVar.IsValid() { - var err error - if isSubsect { - err = newSyntaxWarning(sect, sub, name) - } else { - err = newSyntaxWarning(sect, "", name) - } - return err - } - // vVal is either single-valued var, or newly allocated value within multi-valued var - var vVal reflect.Value - // multi-value if unnamed slice type - isMulti := vVar.Type().Name() == "" && vVar.Kind() == reflect.Slice || - vVar.Type().Name() == "" && vVar.Kind() == reflect.Ptr && vVar.Type().Elem().Name() == "" && vVar.Type().Elem().Kind() == reflect.Slice - if isMulti && vVar.Kind() == reflect.Ptr { - if vVar.IsNil() { - vVar.Set(reflect.New(vVar.Type().Elem())) - } - vVar = vVar.Elem() - } - if isMulti && blankValue { - vVar.Set(reflect.Zero(vVar.Type())) - return nil - } - if isMulti { - vVal = reflect.New(vVar.Type().Elem()).Elem() - } else { - vVal = vVar - } - isDeref := vVal.Type().Name() == "" && vVal.Type().Kind() == reflect.Ptr - isNew := isDeref && vVal.IsNil() - // vAddr is address of value to set (dereferenced & allocated as needed) - var vAddr reflect.Value - switch { - case isNew: - vAddr = reflect.New(vVal.Type().Elem()) - case isDeref && !isNew: - vAddr = vVal - default: - vAddr = vVal.Addr() - } - vAddrI := vAddr.Interface() - err, ok := error(nil), false - for _, s := range setters { - err = s(vAddrI, blankValue, value, t) - if err == nil { - ok = true - break - } - if !errors.Is(err, ErrUnsupportedType) { - return err - } - } - if !ok { - // in case all setters returned ErrUnsupportedType - return err - } - if isNew { // set reference if it was dereferenced and newly allocated - vVal.Set(vAddr) - } - if isMulti { // append if multi-valued - vVar.Set(reflect.Append(vVar, vVal)) - } - return nil -} diff --git a/vendor/github.com/go-git/gcfg/v2/token/position.go b/vendor/github.com/go-git/gcfg/v2/token/position.go deleted file mode 100644 index 9aa68b56..00000000 --- a/vendor/github.com/go-git/gcfg/v2/token/position.go +++ /dev/null @@ -1,430 +0,0 @@ -// Copyright 2010 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. - -// TODO(gri) consider making this a separate package outside the go directory. - -package token - -import ( - "errors" - "fmt" - "sort" - "sync" -) - -var ( - ErrIllegalFileOffset = errors.New("illegal file offset") - ErrIllegalPosValue = errors.New("illegal Pos value") - ErrIllegalBaseOrValue = errors.New("illegal base or value") - ErrPosOffsetOverflow = errors.New("token.Pos offset overflow (> 2G of source code in file set)") -) - -// ----------------------------------------------------------------------------- -// Positions - -// Position describes an arbitrary source position -// including the file, line, and column location. -// A Position is valid if the line number is > 0. -type Position struct { - Filename string // filename, if any - Offset int // offset, starting at 0 - Line int // line number, starting at 1 - Column int // column number, starting at 1 (character count) -} - -// IsValid returns true if the position is valid. -func (pos *Position) IsValid() bool { return pos.Line > 0 } - -// String returns a string in one of several forms: -// -// file:line:column valid position with file name -// line:column valid position without file name -// file invalid position with file name -// - invalid position without file name -func (pos Position) String() string { - s := pos.Filename - if pos.IsValid() { - if s != "" { - s += ":" - } - s += fmt.Sprintf("%d:%d", pos.Line, pos.Column) - } - if s == "" { - s = "-" - } - return s -} - -// Pos is a compact encoding of a source position within a file set. -// It can be converted into a Position for a more convenient, but much -// larger, representation. -// -// The Pos value for a given file is a number in the range [base, base+size], -// where base and size are specified when adding the file to the file set via -// AddFile. -// -// To create the Pos value for a specific source offset, first add -// the respective file to the current file set (via FileSet.AddFile) -// and then call File.Pos(offset) for that file. Given a Pos value p -// for a specific file set fset, the corresponding Position value is -// obtained by calling fset.Position(p). -// -// Pos values can be compared directly with the usual comparison operators: -// If two Pos values p and q are in the same file, comparing p and q is -// equivalent to comparing the respective source file offsets. If p and q -// are in different files, p < q is true if the file implied by p was added -// to the respective file set before the file implied by q. -type Pos int - -// The zero value for Pos is NoPos; there is no file and line information -// associated with it, and NoPos().IsValid() is false. NoPos is always -// smaller than any other Pos value. The corresponding Position value -// for NoPos is the zero value for Position. -const NoPos Pos = 0 - -// IsValid returns true if the position is valid. -func (p Pos) IsValid() bool { - return p != NoPos -} - -// ----------------------------------------------------------------------------- -// File - -// A File is a handle for a file belonging to a FileSet. -// A File has a name, size, and line offset table. -type File struct { - set *FileSet - name string // file name as provided to AddFile - base int // Pos value range for this file is [base...base+size] - size int // file size as provided to AddFile - - // lines and infos are protected by set.mutex - lines []int - infos []lineInfo -} - -// Name returns the file name of file f as registered with AddFile. -func (f *File) Name() string { - return f.name -} - -// Base returns the base offset of file f as registered with AddFile. -func (f *File) Base() int { - return f.base -} - -// Size returns the size of file f as registered with AddFile. -func (f *File) Size() int { - return f.size -} - -// LineCount returns the number of lines in file f. -func (f *File) LineCount() int { - f.set.mutex.RLock() - n := len(f.lines) - f.set.mutex.RUnlock() - return n -} - -// AddLine adds the line offset for a new line. -// The line offset must be larger than the offset for the previous line -// and smaller than the file size; otherwise the line offset is ignored. -func (f *File) AddLine(offset int) { - f.set.mutex.Lock() - if i := len(f.lines); (i == 0 || f.lines[i-1] < offset) && offset < f.size { - f.lines = append(f.lines, offset) - } - f.set.mutex.Unlock() -} - -// SetLines sets the line offsets for a file and returns true if successful. -// The line offsets are the offsets of the first character of each line; -// for instance for the content "ab\nc\n" the line offsets are {0, 3}. -// An empty file has an empty line offset table. -// Each line offset must be larger than the offset for the previous line -// and smaller than the file size; otherwise SetLines fails and returns -// false. -func (f *File) SetLines(lines []int) bool { - // verify validity of lines table - size := f.size - for i, offset := range lines { - if i > 0 && offset <= lines[i-1] || size <= offset { - return false - } - } - - // set lines table - f.set.mutex.Lock() - f.lines = lines - f.set.mutex.Unlock() - return true -} - -// SetLinesForContent sets the line offsets for the given file content. -func (f *File) SetLinesForContent(content []byte) { - var lines []int - line := 0 - for offset, b := range content { - if line >= 0 { - lines = append(lines, line) - } - line = -1 - if b == '\n' { - line = offset + 1 - } - } - - // set lines table - f.set.mutex.Lock() - f.lines = lines - f.set.mutex.Unlock() -} - -// A lineInfo object describes alternative file and line number -// information (such as provided via a //line comment in a .go -// file) for a given file offset. -type lineInfo struct { - // fields are exported to make them accessible to gob - Offset int - Filename string - Line int -} - -// AddLineInfo adds alternative file and line number information for -// a given file offset. The offset must be larger than the offset for -// the previously added alternative line info and smaller than the -// file size; otherwise the information is ignored. -// -// AddLineInfo is typically used to register alternative position -// information for //line filename:line comments in source files. -func (f *File) AddLineInfo(offset int, filename string, line int) { - f.set.mutex.Lock() - if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size { - f.infos = append(f.infos, lineInfo{offset, filename, line}) - } - f.set.mutex.Unlock() -} - -// Pos returns the Pos value for the given file offset; -// the offset must be <= f.Size(). -// f.Pos(f.Offset(p)) == p. -func (f *File) Pos(offset int) (Pos, error) { - if offset > f.size { - return 0, ErrIllegalFileOffset - } - return Pos(f.base + offset), nil -} - -// Offset returns the offset for the given file position p; -// p must be a valid Pos value in that file. -// f.Offset(f.Pos(offset)) == offset. -func (f *File) Offset(p Pos) (int, error) { - if int(p) < f.base || int(p) > f.base+f.size { - return 0, ErrIllegalPosValue - } - return int(p) - f.base, nil -} - -// Line returns the line number for the given file position p; -// p must be a Pos value in that file or NoPos. -func (f *File) Line(p Pos) (int, error) { - // TODO(gri) this can be implemented much more efficiently - position, err := f.Position(p) - if err != nil { - return 0, err - } - return position.Line, nil -} - -func searchLineInfos(a []lineInfo, x int) int { - return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1 -} - -// info returns the file name, line, and column number for a file offset. -func (f *File) info(offset int) (filename string, line, column int) { - filename = f.name - if i := searchInts(f.lines, offset); i >= 0 { - line, column = i+1, offset-f.lines[i]+1 - } - if len(f.infos) > 0 { - // almost no files have extra line infos - if i := searchLineInfos(f.infos, offset); i >= 0 { - alt := &f.infos[i] - filename = alt.Filename - if i := searchInts(f.lines, alt.Offset); i >= 0 { - line += alt.Line - i - 1 - } - } - } - return -} - -func (f *File) position(p Pos) (pos Position) { - offset := int(p) - f.base - pos.Offset = offset - pos.Filename, pos.Line, pos.Column = f.info(offset) - return -} - -// Position returns the Position value for the given file position p; -// p must be a Pos value in that file or NoPos. -func (f *File) Position(p Pos) (Position, error) { - if p != NoPos { - if int(p) < f.base || int(p) > f.base+f.size { - return Position{}, ErrIllegalPosValue - } - return f.position(p), nil - } - return Position{}, nil -} - -// ----------------------------------------------------------------------------- -// FileSet - -// A FileSet represents a set of source files. -// Methods of file sets are synchronized; multiple goroutines -// may invoke them concurrently. -type FileSet struct { - mutex sync.RWMutex // protects the file set - base int // base offset for the next file - files []*File // list of files in the order added to the set - last *File // cache of last file looked up -} - -// NewFileSet creates a new file set. -func NewFileSet() *FileSet { - s := new(FileSet) - s.base = 1 // 0 == NoPos - return s -} - -// Base returns the minimum base offset that must be provided to -// AddFile when adding the next file. -func (s *FileSet) Base() int { - s.mutex.RLock() - b := s.base - s.mutex.RUnlock() - return b - -} - -// AddFile adds a new file with a given filename, base offset, and file size -// to the file set s and returns the file. Multiple files may have the same -// name. The base offset must not be smaller than the FileSet's Base(), and -// size must not be negative. -// -// Adding the file will set the file set's Base() value to base + size + 1 -// as the minimum base value for the next file. The following relationship -// exists between a Pos value p for a given file offset offs: -// -// int(p) = base + offs -// -// with offs in the range [0, size] and thus p in the range [base, base+size]. -// For convenience, File.Pos may be used to create file-specific position -// values from a file offset. -func (s *FileSet) AddFile(filename string, base, size int) (*File, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - if base < s.base || size < 0 { - return nil, ErrIllegalBaseOrValue - } - // base >= s.base && size >= 0 - f := &File{s, filename, base, size, []int{0}, nil} - base += size + 1 // +1 because EOF also has a position - if base < 0 { - return nil, ErrPosOffsetOverflow - } - // add the file to the file set - s.base = base - s.files = append(s.files, f) - s.last = f - return f, nil -} - -// Iterate calls f for the files in the file set in the order they were added -// until f returns false. -func (s *FileSet) Iterate(f func(*File) bool) { - for i := 0; ; i++ { - var file *File - s.mutex.RLock() - if i < len(s.files) { - file = s.files[i] - } - s.mutex.RUnlock() - if file == nil || !f(file) { - break - } - } -} - -func searchFiles(a []*File, x int) int { - return sort.Search(len(a), func(i int) bool { return a[i].base > x }) - 1 -} - -func (s *FileSet) file(p Pos) *File { - // common case: p is in last file - if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size { - return f - } - // p is not in last file - search all files - if i := searchFiles(s.files, int(p)); i >= 0 { - f := s.files[i] - // f.base <= int(p) by definition of searchFiles - if int(p) <= f.base+f.size { - s.last = f - return f - } - } - return nil -} - -// File returns the file that contains the position p. -// If no such file is found (for instance for p == NoPos), -// the result is nil. -func (s *FileSet) File(p Pos) (f *File) { - if p != NoPos { - s.mutex.RLock() - f = s.file(p) - s.mutex.RUnlock() - } - return -} - -// Position converts a Pos in the fileset into a general Position. -func (s *FileSet) Position(p Pos) (pos Position) { - if p != NoPos { - s.mutex.RLock() - if f := s.file(p); f != nil { - pos = f.position(p) - } - s.mutex.RUnlock() - } - return -} - -// ----------------------------------------------------------------------------- -// Helper functions - -func searchInts(a []int, x int) int { - // This function body is a manually inlined version of: - // - // return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1 - // - // With better compiler optimizations, this may not be needed in the - // future, but at the moment this change improves the go/printer - // benchmark performance by ~30%. This has a direct impact on the - // speed of gofmt and thus seems worthwhile (2011-04-29). - // TODO(gri): Remove this when compilers have caught up. - i, j := 0, len(a) - for i < j { - h := i + (j-i)/2 // avoid overflow when computing h - // i ≤ h < j - if a[h] <= x { - i = h + 1 - } else { - j = h - } - } - return i - 1 -} diff --git a/vendor/github.com/go-git/gcfg/v2/token/serialize.go b/vendor/github.com/go-git/gcfg/v2/token/serialize.go deleted file mode 100644 index 4adc8f9e..00000000 --- a/vendor/github.com/go-git/gcfg/v2/token/serialize.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2011 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 token - -type serializedFile struct { - // fields correspond 1:1 to fields with same (lower-case) name in File - Name string - Base int - Size int - Lines []int - Infos []lineInfo -} - -type serializedFileSet struct { - Base int - Files []serializedFile -} - -// Read calls decode to deserialize a file set into s; s must not be nil. -func (s *FileSet) Read(decode func(interface{}) error) error { - var ss serializedFileSet - if err := decode(&ss); err != nil { - return err - } - - s.mutex.Lock() - s.base = ss.Base - files := make([]*File, len(ss.Files)) - for i := 0; i < len(ss.Files); i++ { - f := &ss.Files[i] - files[i] = &File{s, f.Name, f.Base, f.Size, f.Lines, f.Infos} - } - s.files = files - s.last = nil - s.mutex.Unlock() - - return nil -} - -// Write calls encode to serialize the file set s. -func (s *FileSet) Write(encode func(interface{}) error) error { - var ss serializedFileSet - - s.mutex.Lock() - ss.Base = s.base - files := make([]serializedFile, len(s.files)) - for i, f := range s.files { - files[i] = serializedFile{f.name, f.base, f.size, f.lines, f.infos} - } - ss.Files = files - s.mutex.Unlock() - - return encode(ss) -} diff --git a/vendor/github.com/go-git/gcfg/v2/token/token.go b/vendor/github.com/go-git/gcfg/v2/token/token.go deleted file mode 100644 index 102df388..00000000 --- a/vendor/github.com/go-git/gcfg/v2/token/token.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2009 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 token defines constants representing the lexical tokens of the gcfg -// configuration syntax and basic operations on tokens (printing, predicates). -// -// Note that the API for the token package may change to accommodate new -// features or implementation changes in gcfg. -package token - -import "strconv" - -// Token is the set of lexical tokens of the gcfg configuration syntax. -type Token int - -// The list of tokens. -const ( - // Special tokens - ILLEGAL Token = iota - EOF - COMMENT - - literal_beg - // Identifiers and basic type literals - // (these tokens stand for classes of literals) - IDENT // section-name, variable-name - STRING // "subsection-name", variable value - literal_end - - operator_beg - // Operators and delimiters - ASSIGN // = - LBRACK // [ - RBRACK // ] - EOL // \n - operator_end -) - -var tokens = [...]string{ - ILLEGAL: "ILLEGAL", - - EOF: "EOF", - COMMENT: "COMMENT", - - IDENT: "IDENT", - STRING: "STRING", - - ASSIGN: "=", - LBRACK: "[", - RBRACK: "]", - EOL: "\n", -} - -// String returns the string corresponding to the token tok. -// For operators and delimiters, the string is the actual token character -// sequence (e.g., for the token ASSIGN, the string is "="). For all other -// tokens the string corresponds to the token constant name (e.g. for the -// token IDENT, the string is "IDENT"). -func (tok Token) String() string { - s := "" - if 0 <= tok && tok < Token(len(tokens)) { - s = tokens[tok] - } - if s == "" { - s = "token(" + strconv.Itoa(int(tok)) + ")" - } - return s -} - -// Predicates - -// IsLiteral returns true for tokens corresponding to identifiers -// and basic type literals; it returns false otherwise. -func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end } - -// IsOperator returns true for tokens corresponding to operators and -// delimiters; it returns false otherwise. -func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end } diff --git a/vendor/github.com/go-git/gcfg/v2/types/bool.go b/vendor/github.com/go-git/gcfg/v2/types/bool.go deleted file mode 100644 index 8dcae0d8..00000000 --- a/vendor/github.com/go-git/gcfg/v2/types/bool.go +++ /dev/null @@ -1,23 +0,0 @@ -package types - -// BoolValues defines the name and value mappings for ParseBool. -var BoolValues = map[string]interface{}{ - "true": true, "yes": true, "on": true, "1": true, - "false": false, "no": false, "off": false, "0": false, -} - -var boolParser = func() *EnumParser { - ep := &EnumParser{} - ep.AddVals(BoolValues) - return ep -}() - -// ParseBool parses bool values according to the definitions in BoolValues. -// Parsing is case-insensitive. -func ParseBool(s string) (bool, error) { - v, err := boolParser.Parse(s) - if err != nil { - return false, err - } - return v.(bool), nil -} diff --git a/vendor/github.com/go-git/gcfg/v2/types/doc.go b/vendor/github.com/go-git/gcfg/v2/types/doc.go deleted file mode 100644 index 9f9c345f..00000000 --- a/vendor/github.com/go-git/gcfg/v2/types/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package types defines helpers for type conversions. -// -// The API for this package is not finalized yet. -package types diff --git a/vendor/github.com/go-git/gcfg/v2/types/enum.go b/vendor/github.com/go-git/gcfg/v2/types/enum.go deleted file mode 100644 index 1a0c7ef4..00000000 --- a/vendor/github.com/go-git/gcfg/v2/types/enum.go +++ /dev/null @@ -1,44 +0,0 @@ -package types - -import ( - "fmt" - "reflect" - "strings" -) - -// EnumParser parses "enum" values; i.e. a predefined set of strings to -// predefined values. -type EnumParser struct { - Type string // type name; if not set, use type of first value added - CaseMatch bool // if true, matching of strings is case-sensitive - // PrefixMatch bool - vals map[string]interface{} -} - -// AddVals adds strings and values to an EnumParser. -func (ep *EnumParser) AddVals(vals map[string]interface{}) { - if ep.vals == nil { - ep.vals = make(map[string]interface{}) - } - for k, v := range vals { - if ep.Type == "" { - ep.Type = reflect.TypeOf(v).Name() - } - if !ep.CaseMatch { - k = strings.ToLower(k) - } - ep.vals[k] = v - } -} - -// Parse parses the string and returns the value or an error. -func (ep EnumParser) Parse(s string) (interface{}, error) { - if !ep.CaseMatch { - s = strings.ToLower(s) - } - v, ok := ep.vals[s] - if !ok { - return false, fmt.Errorf("failed to parse %s %#q", ep.Type, s) - } - return v, nil -} diff --git a/vendor/github.com/go-git/gcfg/v2/types/int.go b/vendor/github.com/go-git/gcfg/v2/types/int.go deleted file mode 100644 index 61c101c7..00000000 --- a/vendor/github.com/go-git/gcfg/v2/types/int.go +++ /dev/null @@ -1,90 +0,0 @@ -package types - -import ( - "errors" - "fmt" - "strings" -) - -var ( - ErrAmbiguousInt = fmt.Errorf("ambiguous integer value; must include '0' prefix") - ErrUnsupportedMode = errors.New("unsupported mode") -) - -// An IntMode is a mode for parsing integer values, representing a set of -// accepted bases. -type IntMode uint8 - -// IntMode values for ParseInt; can be combined using binary or. -const ( - Dec IntMode = 1 << iota - Hex - Oct -) - -// String returns a string representation of IntMode; e.g. `IntMode(Dec|Hex)`. -func (m IntMode) String() string { - var modes []string - if m&Dec != 0 { - modes = append(modes, "Dec") - } - if m&Hex != 0 { - modes = append(modes, "Hex") - } - if m&Oct != 0 { - modes = append(modes, "Oct") - } - return "IntMode(" + strings.Join(modes, "|") + ")" -} - -func prefix0(val string) bool { - return strings.HasPrefix(val, "0") || strings.HasPrefix(val, "-0") -} - -func prefix0x(val string) bool { - return strings.HasPrefix(val, "0x") || strings.HasPrefix(val, "-0x") -} - -// ParseInt parses val using mode into intptr, which must be a pointer to an -// integer kind type. Non-decimal value require prefix `0` or `0x` in the cases -// when mode permits ambiguity of base; otherwise the prefix can be omitted. -func ParseInt(intptr interface{}, val string, mode IntMode) error { - val = strings.TrimSpace(val) - verb := byte(0) - switch mode { - case Dec: - verb = 'd' - case Dec + Hex: - if prefix0x(val) { - verb = 'v' - } else { - verb = 'd' - } - case Dec + Oct: - if prefix0(val) && !prefix0x(val) { - verb = 'v' - } else { - verb = 'd' - } - case Dec + Hex + Oct: - verb = 'v' - case Hex: - if prefix0x(val) { - verb = 'v' - } else { - verb = 'x' - } - case Oct: - verb = 'o' - case Hex + Oct: - if prefix0(val) { - verb = 'v' - } else { - return ErrAmbiguousInt - } - } - if verb == 0 { - return ErrUnsupportedMode - } - return ScanFully(intptr, val, verb) -} diff --git a/vendor/github.com/go-git/gcfg/v2/types/scan.go b/vendor/github.com/go-git/gcfg/v2/types/scan.go deleted file mode 100644 index db2f6ed3..00000000 --- a/vendor/github.com/go-git/gcfg/v2/types/scan.go +++ /dev/null @@ -1,23 +0,0 @@ -package types - -import ( - "fmt" - "io" - "reflect" -) - -// ScanFully uses fmt.Sscanf with verb to fully scan val into ptr. -func ScanFully(ptr interface{}, val string, verb byte) error { - t := reflect.ValueOf(ptr).Elem().Type() - // attempt to read extra bytes to make sure the value is consumed - var b []byte - n, err := fmt.Sscanf(val, "%"+string(verb)+"%s", ptr, &b) - switch { - case n < 1 || n == 1 && err != io.EOF: - return fmt.Errorf("failed to parse %q as %v: %v", val, t, err) - case n > 1: - return fmt.Errorf("failed to parse %q as %v: extra characters %q", val, t, string(b)) - } - // n == 1 && err == io.EOF - return nil -} diff --git a/vendor/github.com/go-git/go-billy/v6/.gitignore b/vendor/github.com/go-git/go-billy/v6/.gitignore deleted file mode 100644 index 0159b577..00000000 --- a/vendor/github.com/go-git/go-billy/v6/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/coverage.txt -/vendor -/build/ diff --git a/vendor/github.com/go-git/go-billy/v6/.golangci.yaml b/vendor/github.com/go-git/go-billy/v6/.golangci.yaml deleted file mode 100644 index f233aa23..00000000 --- a/vendor/github.com/go-git/go-billy/v6/.golangci.yaml +++ /dev/null @@ -1,75 +0,0 @@ -version: "2" -linters: - default: none - enable: - - asasalint - - asciicheck - - bidichk - - bodyclose - - containedctx - - contextcheck - - decorder - - dogsled - - dupl - - dupword - - durationcheck - - errcheck - - errchkjson - - errname - - errorlint - - exhaustive - - ginkgolinter - - gocheckcompilerdirectives - - gochecknoinits - - gochecksumtype - - goheader - - gomodguard - - goprintffuncname - - gosmopolitan - - govet - - grouper - - importas - - ineffassign - - loggercheck - - makezero - - mirror - - misspell - - noctx - - nosprintfhostport - - promlinter - - reassign - - revive - - rowserrcheck - - sloglint - - spancheck - - sqlclosecheck - - staticcheck - - tagalign - - tagliatelle - - testableexamples - - unconvert - - unused - - usestdlibvars - - wastedassign - - whitespace - - zerologlint - exclusions: - generated: lax - presets: - - comments - - common-false-positives - - legacy - - std-error-handling - paths: - - third_party$ - - builtin$ - - examples$ -formatters: - enable: - - goimports - exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ diff --git a/vendor/github.com/go-git/go-billy/v6/LICENSE b/vendor/github.com/go-git/go-billy/v6/LICENSE deleted file mode 100644 index 9d607568..00000000 --- a/vendor/github.com/go-git/go-billy/v6/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2017 Sourced Technologies S.L. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-git/go-billy/v6/Makefile b/vendor/github.com/go-git/go-billy/v6/Makefile deleted file mode 100644 index f0b04aec..00000000 --- a/vendor/github.com/go-git/go-billy/v6/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# Go parameters -GOCMD = go -GOTEST = $(GOCMD) test -WASIRUN_WRAPPER := $(CURDIR)/scripts/wasirun-wrapper - -GOLANGCI_VERSION ?= v2.1.6 -TOOLS_BIN := $(shell mkdir -p build/tools && realpath build/tools) - -GOLANGCI = $(TOOLS_BIN)/golangci-lint-$(GOLANGCI_VERSION) -$(GOLANGCI): - rm -f $(TOOLS_BIN)/golangci-lint* - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_VERSION)/install.sh | sh -s -- -b $(TOOLS_BIN) $(GOLANGCI_VERSION) - mv $(TOOLS_BIN)/golangci-lint $(TOOLS_BIN)/golangci-lint-$(GOLANGCI_VERSION) - -.PHONY: test -test: - $(GOTEST) -race -timeout 300s ./... - -test-coverage: - echo "" > $(COVERAGE_REPORT); \ - $(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./... - -.PHONY: wasitest -wasitest: export GOARCH=wasm -wasitest: export GOOS=wasip1 -wasitest: - $(GOTEST) -exec $(WASIRUN_WRAPPER) ./... - -validate: validate-lint validate-dirty ## Run validation checks. - -validate-lint: $(GOLANGCI) - $(GOLANGCI) run - -define go-install-tool -@[ -f $(1) ] || { \ -set -e ;\ -echo "Downloading $(2)" ;\ -GOBIN=$(TOOLS_BIN) go install $(2) ;\ -} -endef - -validate-dirty: -ifneq ($(shell git status --porcelain --untracked-files=no),) - @echo worktree is dirty - @git --no-pager status - @git --no-pager diff - @exit 1 -endif diff --git a/vendor/github.com/go-git/go-billy/v6/README.md b/vendor/github.com/go-git/go-billy/v6/README.md deleted file mode 100644 index eba48265..00000000 --- a/vendor/github.com/go-git/go-billy/v6/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# go-billy [![GoDoc](https://godoc.org/gopkg.in/go-git/go-billy.v6?status.svg)](https://pkg.go.dev/github.com/go-git/go-billy/v6) [![Test](https://github.com/go-git/go-billy/workflows/Test/badge.svg)](https://github.com/go-git/go-billy/actions?query=workflow%3ATest) [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/go-git/go-billy/badge)](https://scorecard.dev/viewer/?uri=github.com/go-git/go-billy) - -The missing interface filesystem abstraction for Go. -Billy implements an interface based on the `os` standard library, allowing to develop applications without dependency on the underlying storage. Makes it virtually free to implement mocks and testing over filesystem operations. - -Billy was born as part of [go-git/go-git](https://github.com/go-git/go-git) project. - -## Installation - -```go -import "github.com/go-git/go-billy/v6" // with go modules enabled (GO111MODULE=on or outside GOPATH) -import "github.com/go-git/go-billy" // with go modules disabled -``` - -## Usage - -Billy exposes filesystems using the -[`Filesystem` interface](https://pkg.go.dev/github.com/go-git/go-billy/v6?tab=doc#Filesystem). -Each filesystem implementation gives you a `New` method, whose arguments depend on -the implementation itself, that returns a new `Filesystem`. - -The following example caches in memory all readable files in a directory from any -billy's filesystem implementation. - -```go -func LoadToMemory(origin billy.Filesystem, path string) (*memory.Memory, error) { - memory := memory.New() - - files, err := origin.ReadDir("/") - if err != nil { - return nil, err - } - - for _, file := range files { - if file.IsDir() { - continue - } - - src, err := origin.Open(file.Name()) - if err != nil { - return nil, err - } - - dst, err := memory.Create(file.Name()) - if err != nil { - return nil, err - } - - if _, err = io.Copy(dst, src); err != nil { - return nil, err - } - - if err := dst.Close(); err != nil { - return nil, err - } - - if err := src.Close(); err != nil { - return nil, err - } - } - - return memory, nil -} -``` - -## Why billy? - -The library billy deals with storage systems and Billy is the name of a well-known, IKEA -bookcase. That's it. - -## License - -Apache License Version 2.0, see [LICENSE](LICENSE) diff --git a/vendor/github.com/go-git/go-billy/v6/fs.go b/vendor/github.com/go-git/go-billy/v6/fs.go deleted file mode 100644 index fe660990..00000000 --- a/vendor/github.com/go-git/go-billy/v6/fs.go +++ /dev/null @@ -1,205 +0,0 @@ -package billy - -import ( - "errors" - "io" - "io/fs" - "time" -) - -var ( - ErrReadOnly = errors.New("read-only filesystem") - ErrNotSupported = errors.New("feature not supported") - ErrCrossedBoundary = errors.New("chroot boundary crossed") - ErrBaseDirCannotBeRemoved = errors.New("base dir cannot be removed") - ErrBaseDirCannotBeRenamed = errors.New("base dir cannot be renamed") -) - -// Capability holds the supported features of a billy filesystem. This does -// not mean that the capability has to be supported by the underlying storage. -// For example, a billy filesystem may support WriteCapability but the -// storage be mounted in read only mode. -type Capability uint64 - -const ( - // WriteCapability means that the fs is writable. - WriteCapability Capability = 1 << iota - // ReadCapability means that the fs is readable. - ReadCapability - // ReadAndWriteCapability is the ability to open a file in read and write mode. - ReadAndWriteCapability - // SeekCapability means it is able to move position inside the file. - SeekCapability - // TruncateCapability means that a file can be truncated. - TruncateCapability - // LockCapability is the ability to lock a file. - LockCapability - - // DefaultCapabilities lists all capable features supported by filesystems - // without Capability interface. This list should not be changed until a - // major version is released. - DefaultCapabilities Capability = WriteCapability | ReadCapability | - ReadAndWriteCapability | SeekCapability | TruncateCapability | - LockCapability - - // AllCapabilities lists all capable features. - AllCapabilities Capability = WriteCapability | ReadCapability | - ReadAndWriteCapability | SeekCapability | TruncateCapability | - LockCapability -) - -// Filesystem abstract the operations in a storage-agnostic interface. -// Each method implementation mimics the behavior of the equivalent functions -// at the os package from the standard library. -type Filesystem interface { - Basic - TempFile - Dir - Symlink - Chroot -} - -// Basic abstract the basic operations in a storage-agnostic interface as -// an extension to the Basic interface. -type Basic interface { - // Create creates the named file with mode 0666 (before umask), truncating - // it if it already exists. If successful, methods on the returned File can - // be used for I/O; the associated file descriptor has mode O_RDWR. - Create(filename string) (File, error) - // Open opens the named file for reading. If successful, methods on the - // returned file can be used for reading; the associated file descriptor has - // mode O_RDONLY. - Open(filename string) (File, error) - // OpenFile is the generalized open call; most users will use Open or Create - // instead. It opens the named file with specified flag (O_RDONLY etc.) and - // perm, (0666 etc.) if applicable. If successful, methods on the returned - // File can be used for I/O. - OpenFile(filename string, flag int, perm fs.FileMode) (File, error) - // Stat returns a FileInfo describing the named file. - Stat(filename string) (fs.FileInfo, error) - // Rename renames (moves) oldpath to newpath. If newpath already exists and - // is not a directory, Rename replaces it. OS-specific restrictions may - // apply when oldpath and newpath are in different directories. - Rename(oldpath, newpath string) error - // Remove removes the named file or directory. - Remove(filename string) error - // Join joins any number of path elements into a single path, adding a - // Separator if necessary. Join calls filepath.Clean on the result; in - // particular, all empty strings are ignored. On Windows, the result is a - // UNC path if and only if the first path element is a UNC path. - Join(elem ...string) string -} - -type TempFile interface { - // TempFile creates a new temporary file in the directory dir with a name - // beginning with prefix, opens the file for reading and writing, and - // returns the resulting *os.File. If dir is the empty string, TempFile - // uses the default directory for temporary files (see os.TempDir). - // Multiple programs calling TempFile simultaneously will not choose the - // same file. The caller can use f.Name() to find the pathname of the file. - // It is the caller's responsibility to remove the file when no longer - // needed. - TempFile(dir, prefix string) (File, error) -} - -// Dir abstract the dir related operations in a storage-agnostic interface as -// an extension to the Basic interface. -type Dir interface { - // ReadDir reads the directory named by dirname and returns a list of - // directory entries sorted by filename. - ReadDir(path string) ([]fs.FileInfo, error) - // MkdirAll creates a directory named path, along with any necessary - // parents, and returns nil, or else returns an error. The permission bits - // perm are used for all directories that MkdirAll creates. If path is/ - // already a directory, MkdirAll does nothing and returns nil. - MkdirAll(filename string, perm fs.FileMode) error -} - -// Symlink abstract the symlink related operations in a storage-agnostic -// interface as an extension to the Basic interface. -type Symlink interface { - // Lstat returns a FileInfo describing the named file. If the file is a - // symbolic link, the returned FileInfo describes the symbolic link. Lstat - // makes no attempt to follow the link. - Lstat(filename string) (fs.FileInfo, error) - // Symlink creates a symbolic-link from link to target. target may be an - // absolute or relative path, and need not refer to an existing node. - // Parent directories of link are created as necessary. - Symlink(target, link string) error - // Readlink returns the target path of link. - Readlink(link string) (string, error) -} - -// Change abstract the FileInfo change related operations in a storage-agnostic -// interface as an extension to the Basic interface -type Change interface { - // Chmod changes the mode of the named file to mode. If the file is a - // symbolic link, it changes the mode of the link's target. - Chmod(name string, mode fs.FileMode) error - // Lchown changes the numeric uid and gid of the named file. If the file is - // a symbolic link, it changes the uid and gid of the link itself. - Lchown(name string, uid, gid int) error - // Chown changes the numeric uid and gid of the named file. If the file is a - // symbolic link, it changes the uid and gid of the link's target. - Chown(name string, uid, gid int) error - // Chtimes changes the access and modification times of the named file, - // similar to the Unix utime() or utimes() functions. - // - // The underlying filesystem may truncate or round the values to a less - // precise time unit. - Chtimes(name string, atime time.Time, mtime time.Time) error -} - -// Chroot abstract the chroot related operations in a storage-agnostic interface -// as an extension to the Basic interface. -type Chroot interface { - // Chroot returns a new filesystem from the same type where the new root is - // the given path. Files outside of the designated directory tree cannot be - // accessed. - Chroot(path string) (Filesystem, error) - // Root returns the root path of the filesystem. - Root() string -} - -// File represent a file, being a subset of the os.File -type File interface { - fs.File - - // Name returns the name of the file as presented to Open. - Name() string - io.Writer - io.WriterAt - io.ReaderAt - io.Seeker - // Lock locks the file like e.g. flock. It protects against access from - // other processes. - Lock() error - // Unlock unlocks the file. - Unlock() error - // Truncate the file. - Truncate(size int64) error -} - -// Capable interface can return the available features of a filesystem. -type Capable interface { - // Capabilities returns the capabilities of a filesystem in bit flags. - Capabilities() Capability -} - -// Capabilities returns the features supported by a filesystem. If the FS -// does not implement Capable interface it returns all features. -func Capabilities(fs Basic) Capability { - capable, ok := fs.(Capable) - if !ok { - return DefaultCapabilities - } - - return capable.Capabilities() -} - -// CapabilityCheck tests the filesystem for the provided capabilities and -// returns true in case it supports all of them. -func CapabilityCheck(fs Basic, capabilities Capability) bool { - fsCaps := Capabilities(fs) - return fsCaps&capabilities == capabilities -} diff --git a/vendor/github.com/go-git/go-billy/v6/helper/chroot/chroot.go b/vendor/github.com/go-git/go-billy/v6/helper/chroot/chroot.go deleted file mode 100644 index eca87917..00000000 --- a/vendor/github.com/go-git/go-billy/v6/helper/chroot/chroot.go +++ /dev/null @@ -1,243 +0,0 @@ -package chroot - -import ( - "io/fs" - "os" - "path/filepath" - "strings" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/helper/polyfill" -) - -// ChrootHelper is a helper to implement billy.Chroot. -type ChrootHelper struct { //nolint - underlying billy.Filesystem - base string -} - -// New creates a new filesystem wrapping up the given 'fs'. -// The created filesystem has its base in the given ChrootHelperectory of the -// underlying filesystem. -func New(fs billy.Basic, base string) billy.Filesystem { - return &ChrootHelper{ - underlying: polyfill.New(fs), - base: base, - } -} - -func (fs *ChrootHelper) underlyingPath(filename string) (string, error) { - if isCrossBoundaries(filename) { - return "", billy.ErrCrossedBoundary - } - - return fs.Join(fs.Root(), filename), nil -} - -func isCrossBoundaries(path string) bool { - path = filepath.ToSlash(path) - path = filepath.Clean(path) - - return strings.HasPrefix(path, ".."+string(filepath.Separator)) -} - -func (fs *ChrootHelper) Create(filename string) (billy.File, error) { - fullpath, err := fs.underlyingPath(filename) - if err != nil { - return nil, err - } - - f, err := fs.underlying.Create(fullpath) - if err != nil { - return nil, err - } - - return newFile(fs, f, filename), nil -} - -func (fs *ChrootHelper) Open(filename string) (billy.File, error) { - fullpath, err := fs.underlyingPath(filename) - if err != nil { - return nil, err - } - - f, err := fs.underlying.Open(fullpath) - if err != nil { - return nil, err - } - - return newFile(fs, f, filename), nil -} - -func (fs *ChrootHelper) OpenFile(filename string, flag int, mode fs.FileMode) (billy.File, error) { - fullpath, err := fs.underlyingPath(filename) - if err != nil { - return nil, err - } - - f, err := fs.underlying.OpenFile(fullpath, flag, mode) - if err != nil { - return nil, err - } - - return newFile(fs, f, filename), nil -} - -func (fs *ChrootHelper) Stat(filename string) (os.FileInfo, error) { - fullpath, err := fs.underlyingPath(filename) - if err != nil { - return nil, err - } - - return fs.underlying.Stat(fullpath) -} - -func (fs *ChrootHelper) Rename(from, to string) error { - var err error - from, err = fs.underlyingPath(from) - if err != nil { - return err - } - - to, err = fs.underlyingPath(to) - if err != nil { - return err - } - - return fs.underlying.Rename(from, to) -} - -func (fs *ChrootHelper) Remove(path string) error { - fullpath, err := fs.underlyingPath(path) - if err != nil { - return err - } - - return fs.underlying.Remove(fullpath) -} - -func (fs *ChrootHelper) Join(elem ...string) string { - return fs.underlying.Join(elem...) -} - -func (fs *ChrootHelper) TempFile(dir, prefix string) (billy.File, error) { - fullpath, err := fs.underlyingPath(dir) - if err != nil { - return nil, err - } - - f, err := fs.underlying.(billy.TempFile).TempFile(fullpath, prefix) - if err != nil { - return nil, err - } - - return newFile(fs, f, fs.Join(dir, filepath.Base(f.Name()))), nil -} - -func (fs *ChrootHelper) ReadDir(path string) ([]os.FileInfo, error) { - fullpath, err := fs.underlyingPath(path) - if err != nil { - return nil, err - } - - return fs.underlying.(billy.Dir).ReadDir(fullpath) -} - -func (fs *ChrootHelper) MkdirAll(filename string, perm fs.FileMode) error { - fullpath, err := fs.underlyingPath(filename) - if err != nil { - return err - } - - return fs.underlying.(billy.Dir).MkdirAll(fullpath, perm) -} - -func (fs *ChrootHelper) Lstat(filename string) (os.FileInfo, error) { - fullpath, err := fs.underlyingPath(filename) - if err != nil { - return nil, err - } - - return fs.underlying.(billy.Symlink).Lstat(fullpath) -} - -func (fs *ChrootHelper) Symlink(target, link string) error { - target = filepath.FromSlash(target) - - // only rewrite target if it's already absolute - if filepath.IsAbs(target) || strings.HasPrefix(target, string(filepath.Separator)) { - target = fs.Join(fs.Root(), target) - target = filepath.Clean(filepath.FromSlash(target)) - } - - link, err := fs.underlyingPath(link) - if err != nil { - return err - } - - return fs.underlying.(billy.Symlink).Symlink(target, link) -} - -func (fs *ChrootHelper) Readlink(link string) (string, error) { - fullpath, err := fs.underlyingPath(link) - if err != nil { - return "", err - } - - target, err := fs.underlying.(billy.Symlink).Readlink(fullpath) - if err != nil { - return "", err - } - - if !filepath.IsAbs(target) && !strings.HasPrefix(target, string(filepath.Separator)) { - return target, nil - } - - target, err = filepath.Rel(fs.base, target) - if err != nil { - return "", err - } - - return string(os.PathSeparator) + target, nil -} - -func (fs *ChrootHelper) Chroot(path string) (billy.Filesystem, error) { - fullpath, err := fs.underlyingPath(path) - if err != nil { - return nil, err - } - - return New(fs.underlying, fullpath), nil -} - -func (fs *ChrootHelper) Root() string { - return fs.base -} - -func (fs *ChrootHelper) Underlying() billy.Basic { - return fs.underlying -} - -// Capabilities implements the Capable interface. -func (fs *ChrootHelper) Capabilities() billy.Capability { - return billy.Capabilities(fs.underlying) -} - -type file struct { - billy.File - name string -} - -func newFile(fs billy.Filesystem, f billy.File, filename string) billy.File { - filename = fs.Join(fs.Root(), filename) - filename, _ = filepath.Rel(fs.Root(), filename) - - return &file{ - File: f, - name: filename, - } -} - -func (f *file) Name() string { - return f.name -} diff --git a/vendor/github.com/go-git/go-billy/v6/helper/polyfill/polyfill.go b/vendor/github.com/go-git/go-billy/v6/helper/polyfill/polyfill.go deleted file mode 100644 index 901ec619..00000000 --- a/vendor/github.com/go-git/go-billy/v6/helper/polyfill/polyfill.go +++ /dev/null @@ -1,106 +0,0 @@ -package polyfill - -import ( - "io/fs" - "os" - "path/filepath" - - "github.com/go-git/go-billy/v6" -) - -// Polyfill is a helper that implements all missing method from billy.Filesystem. -type Polyfill struct { - billy.Basic - c capabilities -} - -type capabilities struct{ tempfile, dir, symlink, chroot bool } - -// New creates a new filesystem wrapping up 'fs' the intercepts all the calls -// made and errors if fs doesn't implement any of the billy interfaces. -func New(fs billy.Basic) billy.Filesystem { - if original, ok := fs.(billy.Filesystem); ok { - return original - } - - h := &Polyfill{Basic: fs} - - _, h.c.tempfile = h.Basic.(billy.TempFile) - _, h.c.dir = h.Basic.(billy.Dir) - _, h.c.symlink = h.Basic.(billy.Symlink) - _, h.c.chroot = h.Basic.(billy.Chroot) - return h -} - -func (h *Polyfill) TempFile(dir, prefix string) (billy.File, error) { - if !h.c.tempfile { - return nil, billy.ErrNotSupported - } - - return h.Basic.(billy.TempFile).TempFile(dir, prefix) -} - -func (h *Polyfill) ReadDir(path string) ([]os.FileInfo, error) { - if !h.c.dir { - return nil, billy.ErrNotSupported - } - - return h.Basic.(billy.Dir).ReadDir(path) -} - -func (h *Polyfill) MkdirAll(filename string, perm fs.FileMode) error { - if !h.c.dir { - return billy.ErrNotSupported - } - - return h.Basic.(billy.Dir).MkdirAll(filename, perm) -} - -func (h *Polyfill) Symlink(target, link string) error { - if !h.c.symlink { - return billy.ErrNotSupported - } - - return h.Basic.(billy.Symlink).Symlink(target, link) -} - -func (h *Polyfill) Readlink(link string) (string, error) { - if !h.c.symlink { - return "", billy.ErrNotSupported - } - - return h.Basic.(billy.Symlink).Readlink(link) -} - -func (h *Polyfill) Lstat(path string) (os.FileInfo, error) { - if !h.c.symlink { - return nil, billy.ErrNotSupported - } - - return h.Basic.(billy.Symlink).Lstat(path) -} - -func (h *Polyfill) Chroot(path string) (billy.Filesystem, error) { - if !h.c.chroot { - return nil, billy.ErrNotSupported - } - - return h.Basic.(billy.Chroot).Chroot(path) -} - -func (h *Polyfill) Root() string { - if !h.c.chroot { - return string(filepath.Separator) - } - - return h.Basic.(billy.Chroot).Root() -} - -func (h *Polyfill) Underlying() billy.Basic { - return h.Basic -} - -// Capabilities implements the Capable interface. -func (h *Polyfill) Capabilities() billy.Capability { - return billy.Capabilities(h.Basic) -} diff --git a/vendor/github.com/go-git/go-billy/v6/memfs/file.go b/vendor/github.com/go-git/go-billy/v6/memfs/file.go deleted file mode 100644 index 7ebe76bc..00000000 --- a/vendor/github.com/go-git/go-billy/v6/memfs/file.go +++ /dev/null @@ -1,243 +0,0 @@ -package memfs - -import ( - "errors" - "io" - "io/fs" - "os" - "sync" - "time" - - "github.com/go-git/go-billy/v6" -) - -type file struct { - name string - content *content - position int64 - flag int - mode os.FileMode - modTime time.Time - - isClosed bool -} - -func (f *file) Name() string { - return f.name -} - -func (f *file) Read(b []byte) (int, error) { - n, err := f.ReadAt(b, f.position) - f.position += int64(n) - - if errors.Is(err, io.EOF) && n != 0 { - err = nil - } - - return n, err -} - -func (f *file) ReadAt(b []byte, off int64) (int, error) { - if f.isClosed { - return 0, os.ErrClosed - } - - if !isReadAndWrite(f.flag) && !isReadOnly(f.flag) { - return 0, errors.New("read not supported") - } - - n, err := f.content.ReadAt(b, off) - - return n, err -} - -func (f *file) Seek(offset int64, whence int) (int64, error) { - if f.isClosed { - return 0, os.ErrClosed - } - - switch whence { - case io.SeekCurrent: - f.position += offset - case io.SeekStart: - f.position = offset - case io.SeekEnd: - f.position = int64(f.content.Len()) + offset - } - - return f.position, nil -} - -func (f *file) Write(p []byte) (int, error) { - return f.WriteAt(p, f.position) -} - -func (f *file) WriteAt(p []byte, off int64) (int, error) { - if f.isClosed { - return 0, os.ErrClosed - } - - if !isReadAndWrite(f.flag) && !isWriteOnly(f.flag) { - return 0, errors.New("write not supported") - } - - f.modTime = time.Now() - n, err := f.content.WriteAt(p, off) - f.position = off + int64(n) - - return n, err -} - -func (f *file) Close() error { - if f.isClosed { - return os.ErrClosed - } - - f.isClosed = true - return nil -} - -func (f *file) Truncate(size int64) error { - if size < int64(len(f.content.bytes)) { - f.content.bytes = f.content.bytes[:size] - } else if more := int(size) - len(f.content.bytes); more > 0 { - f.content.bytes = append(f.content.bytes, make([]byte, more)...) - } - - return nil -} - -func (f *file) Duplicate(filename string, mode fs.FileMode, flag int) billy.File { - n := &file{ - name: filename, - content: f.content, - mode: mode, - flag: flag, - modTime: f.modTime, - } - - if isTruncate(flag) { - n.content.Truncate() - } - - if isAppend(flag) { - n.position = int64(n.content.Len()) - } - - return n -} - -func (f *file) Stat() (os.FileInfo, error) { - return &fileInfo{ - name: f.Name(), - mode: f.mode, - size: f.content.Len(), - modTime: f.modTime, - }, nil -} - -// Lock is a no-op in memfs. -func (f *file) Lock() error { - return nil -} - -// Unlock is a no-op in memfs. -func (f *file) Unlock() error { - return nil -} - -type fileInfo struct { - name string - size int - mode os.FileMode - modTime time.Time -} - -func (fi *fileInfo) Name() string { - return fi.name -} - -func (fi *fileInfo) Size() int64 { - return int64(fi.size) -} - -func (fi *fileInfo) Mode() fs.FileMode { - return fi.mode -} - -func (fi *fileInfo) ModTime() time.Time { - return fi.modTime -} - -func (fi *fileInfo) IsDir() bool { - return fi.mode.IsDir() -} - -func (*fileInfo) Sys() interface{} { - return nil -} - -type content struct { - name string - bytes []byte - - m sync.RWMutex -} - -func (c *content) WriteAt(p []byte, off int64) (int, error) { - if off < 0 { - return 0, &os.PathError{ - Op: "writeat", - Path: c.name, - Err: errors.New("negative offset"), - } - } - - c.m.Lock() - prev := len(c.bytes) - - diff := int(off) - prev - if diff > 0 { - c.bytes = append(c.bytes, make([]byte, diff)...) - } - - c.bytes = append(c.bytes[:off], p...) - if len(c.bytes) < prev { - c.bytes = c.bytes[:prev] - } - c.m.Unlock() - - return len(p), nil -} - -func (c *content) ReadAt(b []byte, off int64) (n int, err error) { - if off < 0 { - return 0, &os.PathError{ - Op: "readat", - Path: c.name, - Err: errors.New("negative offset"), - } - } - - c.m.RLock() - size := int64(len(c.bytes)) - if off >= size { - c.m.RUnlock() - return 0, io.EOF - } - - l := int64(len(b)) - if off+l > size { - l = size - off - } - - btr := c.bytes[off : off+l] - n = copy(b, btr) - - if len(btr) < len(b) { - err = io.EOF - } - c.m.RUnlock() - - return -} diff --git a/vendor/github.com/go-git/go-billy/v6/memfs/memory.go b/vendor/github.com/go-git/go-billy/v6/memfs/memory.go deleted file mode 100644 index fbf6c299..00000000 --- a/vendor/github.com/go-git/go-billy/v6/memfs/memory.go +++ /dev/null @@ -1,263 +0,0 @@ -// Package memfs provides a billy filesystem base on memory. -package memfs // import "github.com/go-git/go-billy/v6/memfs" - -import ( - "errors" - "fmt" - "io/fs" - "log" - "os" - "path/filepath" - "sort" - "strings" - "syscall" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/helper/chroot" - "github.com/go-git/go-billy/v6/util" -) - -const separator = filepath.Separator - -// Memory a very convenient filesystem based on memory files. -type Memory struct { - s *storage -} - -// New returns a new Memory filesystem. -func New(opts ...Option) billy.Filesystem { - o := &options{} - for _, opt := range opts { - opt(o) - } - - fs := &Memory{ - s: newStorage(), - } - _, err := fs.s.New("/", 0755|os.ModeDir, 0) - if err != nil { - log.Printf("failed to create root dir: %v", err) - } - return chroot.New(fs, string(separator)) -} - -func (fs *Memory) Create(filename string) (billy.File, error) { - return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) -} - -func (fs *Memory) Open(filename string) (billy.File, error) { - return fs.OpenFile(filename, os.O_RDONLY, 0) -} - -func (fs *Memory) OpenFile(filename string, flag int, perm fs.FileMode) (billy.File, error) { - f, has := fs.s.Get(filename) - if !has { - if !isCreate(flag) { - return nil, os.ErrNotExist - } - - var err error - f, err = fs.s.New(filename, perm, flag) - if err != nil { - return nil, err - } - } else { - if isExclusive(flag) { - return nil, os.ErrExist - } - - if target, isLink := fs.resolveLink(filename, f); isLink { - if target != filename { - return fs.OpenFile(target, flag, perm) - } - } - } - - if f.mode.IsDir() { - return nil, fmt.Errorf("cannot open directory: %s", filename) - } - - return f.Duplicate(filename, perm, flag), nil -} - -func (fs *Memory) resolveLink(fullpath string, f *file) (target string, isLink bool) { - if !isSymlink(f.mode) { - return fullpath, false - } - - target = string(f.content.bytes) - if !isAbs(target) { - target = fs.Join(filepath.Dir(fullpath), target) - } - - return target, true -} - -// On Windows OS, IsAbs validates if a path is valid based on if stars with a -// unit (eg.: `C:\`) to assert that is absolute, but in this mem implementation -// any path starting by `separator` is also considered absolute. -func isAbs(path string) bool { - return filepath.IsAbs(path) || strings.HasPrefix(path, string(separator)) -} - -func (fs *Memory) Stat(filename string) (os.FileInfo, error) { - f, has := fs.s.Get(filename) - if !has { - return nil, os.ErrNotExist - } - - fi, _ := f.Stat() - - var err error - if target, isLink := fs.resolveLink(filename, f); isLink { - fi, err = fs.Stat(target) - if err != nil { - return nil, err - } - } - - // the name of the file should always the name of the stated file, so we - // overwrite the Stat returned from the storage with it, since the - // filename may belong to a link. - fi.(*fileInfo).name = filepath.Base(filename) - return fi, nil -} - -func (fs *Memory) Lstat(filename string) (os.FileInfo, error) { - f, has := fs.s.Get(filename) - if !has { - return nil, os.ErrNotExist - } - - return f.Stat() -} - -type ByName []os.FileInfo - -func (a ByName) Len() int { return len(a) } -func (a ByName) Less(i, j int) bool { return a[i].Name() < a[j].Name() } -func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func (fs *Memory) ReadDir(path string) ([]os.FileInfo, error) { - if f, has := fs.s.Get(path); has { - if target, isLink := fs.resolveLink(path, f); isLink { - if target != path { - return fs.ReadDir(target) - } - } - } else { - return nil, &os.PathError{Op: "open", Path: path, Err: syscall.ENOENT} - } - - var entries []os.FileInfo - for _, f := range fs.s.Children(path) { - fi, _ := f.Stat() - entries = append(entries, fi) - } - - sort.Sort(ByName(entries)) - - return entries, nil -} - -func (fs *Memory) MkdirAll(path string, perm fs.FileMode) error { - _, err := fs.s.New(path, perm|os.ModeDir, 0) - return err -} - -func (fs *Memory) TempFile(dir, prefix string) (billy.File, error) { - return util.TempFile(fs, dir, prefix) -} - -func (fs *Memory) Rename(from, to string) error { - return fs.s.Rename(from, to) -} - -func (fs *Memory) Remove(filename string) error { - return fs.s.Remove(filename) -} - -// Falls back to Go's filepath.Join, which works differently depending on the -// OS where the code is being executed. -func (fs *Memory) Join(elem ...string) string { - return filepath.Join(elem...) -} - -func (fs *Memory) Symlink(target, link string) error { - _, err := fs.Lstat(link) - if err == nil { - return os.ErrExist - } - - if !errors.Is(err, os.ErrNotExist) { - return err - } - - return util.WriteFile(fs, link, []byte(target), 0777|os.ModeSymlink) -} - -func (fs *Memory) Readlink(link string) (string, error) { - f, has := fs.s.Get(link) - if !has { - return "", os.ErrNotExist - } - - if !isSymlink(f.mode) { - return "", &os.PathError{ - Op: "readlink", - Path: link, - Err: fmt.Errorf("not a symlink"), - } - } - - return string(f.content.bytes), nil -} - -// Capabilities implements the Capable interface. -func (fs *Memory) Capabilities() billy.Capability { - return billy.WriteCapability | - billy.ReadCapability | - billy.ReadAndWriteCapability | - billy.SeekCapability | - billy.TruncateCapability -} - -func (c *content) Truncate() { - c.bytes = make([]byte, 0) -} - -func (c *content) Len() int { - return len(c.bytes) -} - -func isCreate(flag int) bool { - return flag&os.O_CREATE != 0 -} - -func isExclusive(flag int) bool { - return flag&os.O_EXCL != 0 -} - -func isAppend(flag int) bool { - return flag&os.O_APPEND != 0 -} - -func isTruncate(flag int) bool { - return flag&os.O_TRUNC != 0 -} - -func isReadAndWrite(flag int) bool { - return flag&os.O_RDWR != 0 -} - -func isReadOnly(flag int) bool { - return flag == os.O_RDONLY -} - -func isWriteOnly(flag int) bool { - return flag&os.O_WRONLY != 0 -} - -func isSymlink(m fs.FileMode) bool { - return m&os.ModeSymlink != 0 -} diff --git a/vendor/github.com/go-git/go-billy/v6/memfs/memory_option.go b/vendor/github.com/go-git/go-billy/v6/memfs/memory_option.go deleted file mode 100644 index bbdd22d7..00000000 --- a/vendor/github.com/go-git/go-billy/v6/memfs/memory_option.go +++ /dev/null @@ -1,6 +0,0 @@ -package memfs - -type Option func(*options) - -type options struct { -} diff --git a/vendor/github.com/go-git/go-billy/v6/memfs/storage.go b/vendor/github.com/go-git/go-billy/v6/memfs/storage.go deleted file mode 100644 index f939e568..00000000 --- a/vendor/github.com/go-git/go-billy/v6/memfs/storage.go +++ /dev/null @@ -1,225 +0,0 @@ -package memfs - -import ( - "fmt" - "io/fs" - "os" - "path/filepath" - "strings" - "sync" - "time" - - "github.com/go-git/go-billy/v6" -) - -type storage struct { - files map[string]*file - children map[string]map[string]*file - - mf sync.RWMutex - mc sync.RWMutex -} - -func newStorage() *storage { - return &storage{ - files: make(map[string]*file, 0), - children: make(map[string]map[string]*file, 0), - } -} - -func (s *storage) Has(path string) bool { - _, ok := s.get(path) - return ok -} - -func (s *storage) New(path string, mode fs.FileMode, flag int) (*file, error) { - path = clean(path) - if f, ok := s.get(path); ok { - if !f.mode.IsDir() { - return nil, fmt.Errorf("file already exists %q", path) - } - - return nil, nil - } - - name := filepath.Base(path) - f := &file{ - name: name, - content: &content{name: name}, - mode: mode, - flag: flag, - modTime: time.Now(), - } - - s.mf.Lock() - s.files[path] = f - s.mf.Unlock() - - err := s.createParent(path, mode, f) - if err != nil { - return nil, fmt.Errorf("failed to create parent: %w", err) - } - - return f, nil -} - -func (s *storage) createParent(path string, mode fs.FileMode, f *file) error { - base := filepath.Dir(path) - base = clean(base) - if f.Name() == string(separator) { - return nil - } - - if _, err := s.New(base, mode.Perm()|os.ModeDir, 0); err != nil { - return err - } - - s.mc.Lock() - if _, ok := s.children[base]; !ok { - s.children[base] = make(map[string]*file, 0) - } - - s.children[base][f.Name()] = f - s.mc.Unlock() - - return nil -} - -func (s *storage) Children(path string) []*file { - path = clean(path) - - s.mc.RLock() - l := make([]*file, 0, len(s.children)) - for _, f := range s.children[path] { - l = append(l, f) - } - s.mc.RUnlock() - - return l -} - -func (s *storage) MustGet(path string) *file { - f, ok := s.get(path) - if !ok { - panic(fmt.Errorf("couldn't find %q", path)) - } - - return f -} - -func (s *storage) Get(path string) (*file, bool) { - return s.get(path) -} - -func (s *storage) get(path string) (*file, bool) { - path = clean(path) - - s.mf.RLock() - file, ok := s.files[path] - s.mf.RUnlock() - if !ok { - return nil, false - } - - return file, ok -} - -func (s *storage) Rename(from, to string) error { - from = clean(from) - to = clean(to) - - if from == "/" || from == "." { - return billy.ErrBaseDirCannotBeRenamed - } - - if !s.Has(from) { - return os.ErrNotExist - } - - move := [][2]string{{from, to}} - s.mf.RLock() - for pathFrom := range s.files { - if pathFrom == from || !strings.HasPrefix(pathFrom, from) { - continue - } - - rel, _ := filepath.Rel(from, pathFrom) - pathTo := filepath.Join(to, rel) - - move = append(move, [2]string{pathFrom, pathTo}) - } - s.mf.RUnlock() - - for _, ops := range move { - from := ops[0] - to := ops[1] - - if err := s.move(from, to); err != nil { - return err - } - } - - return nil -} - -func (s *storage) move(from, to string) error { - s.mf.Lock() - s.files[to] = s.files[from] - s.files[to].name = filepath.Base(to) - file := s.files[to] - s.mf.Unlock() - - s.mc.Lock() - s.children[to] = s.children[from] - s.mc.Unlock() - - defer func() { - s.mf.Lock() - delete(s.files, from) - s.mf.Unlock() - - s.mc.Lock() - delete(s.children, from) - delete(s.children[filepath.Dir(from)], filepath.Base(from)) - s.mc.Unlock() - }() - - return s.createParent(to, 0644, file) -} - -func (s *storage) Remove(path string) error { - path = clean(path) - if path == "/" || path == "." { - return billy.ErrBaseDirCannotBeRemoved - } - - f, has := s.get(path) - if !has { - return os.ErrNotExist - } - - if f.mode.IsDir() { - s.mc.RLock() - if len(s.children[path]) != 0 { - s.mc.RUnlock() - return fmt.Errorf("dir: %s contains files", path) - } - s.mc.RUnlock() - } - - base, file := filepath.Split(path) - base = filepath.Clean(base) - - s.mf.Lock() - delete(s.files, path) - s.mf.Unlock() - - s.mc.Lock() - delete(s.children[base], file) - s.mc.Unlock() - return nil -} - -func clean(path string) string { - return filepath.Clean(filepath.FromSlash(path)) -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os.go b/vendor/github.com/go-git/go-billy/v6/osfs/os.go deleted file mode 100644 index 75e7c855..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build !js -// +build !js - -// Package osfs provides a billy filesystem for the OS. -package osfs - -import ( - "fmt" - "io/fs" - "os" - "sync" - - "github.com/go-git/go-billy/v6" -) - -const ( - defaultDirectoryMode = 0o755 - defaultCreateMode = 0o666 -) - -// Default Filesystem representing the root of the os filesystem. -var Default = &ChrootOS{} - -// New returns a new OS filesystem. -// By default paths are deduplicated, but still enforced -// under baseDir. For more info refer to WithDeduplicatePath. -func New(baseDir string, opts ...Option) billy.Filesystem { - o := &options{ - deduplicatePath: true, - } - for _, opt := range opts { - opt(o) - } - - if o.Type == BoundOSFS { - return newBoundOS(baseDir, o.deduplicatePath) - } - - return newChrootOS(baseDir) -} - -// WithBoundOS returns the option of using a Bound filesystem OS. -func WithBoundOS() Option { - return func(o *options) { - o.Type = BoundOSFS - } -} - -// WithChrootOS returns the option of using a Chroot filesystem OS. -func WithChrootOS() Option { - return func(o *options) { - o.Type = ChrootOSFS - } -} - -// WithDeduplicatePath toggles the deduplication of the base dir in the path. -// This occurs when absolute links are being used. -// Assuming base dir /base/dir and an absolute symlink /base/dir/target: -// -// With DeduplicatePath (default): /base/dir/target -// Without DeduplicatePath: /base/dir/base/dir/target -// -// This option is only used by the BoundOS OS type. -func WithDeduplicatePath(enabled bool) Option { - return func(o *options) { - o.deduplicatePath = enabled - } -} - -type options struct { - Type - deduplicatePath bool -} - -type Type int - -const ( - ChrootOSFS Type = iota - BoundOSFS -) - -func readDir(dir string) ([]os.FileInfo, error) { - entries, err := os.ReadDir(dir) - if err != nil { - return nil, err - } - infos := make([]fs.FileInfo, 0, len(entries)) - for _, entry := range entries { - fi, err := entry.Info() - if err != nil { - return nil, err - } - infos = append(infos, fi) - } - return infos, nil -} - -func tempFile(dir, prefix string) (billy.File, error) { - f, err := os.CreateTemp(dir, prefix) - if err != nil { - return nil, err - } - return &file{File: f}, nil -} - -func openFile(fn string, flag int, perm fs.FileMode, createDir func(string) error) (billy.File, error) { - if flag&os.O_CREATE != 0 { - if createDir == nil { - return nil, fmt.Errorf("createDir func cannot be nil if file needs to be opened in create mode") - } - if err := createDir(fn); err != nil { - return nil, err - } - } - - f, err := os.OpenFile(fn, flag, perm) - if err != nil { - return nil, err - } - return &file{File: f}, err -} - -// file is a wrapper for an os.File which adds support for file locking. -type file struct { - *os.File - m sync.Mutex -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_bound.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_bound.go deleted file mode 100644 index 953cafc6..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_bound.go +++ /dev/null @@ -1,298 +0,0 @@ -//go:build !js -// +build !js - -/* - Copyright 2022 The Flux 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 osfs - -import ( - "fmt" - "io/fs" - "os" - "path/filepath" - "strings" - - securejoin "github.com/cyphar/filepath-securejoin" - "github.com/go-git/go-billy/v6" -) - -var ( - dotPrefixes = []string{"./", ".\\"} -) - -// BoundOS is a fs implementation based on the OS filesystem which is bound to -// a base dir. -// Prefer this fs implementation over ChrootOS. -// -// Behaviours of note: -// 1. Read and write operations can only be directed to files which descends -// from the base dir. -// 2. Symlinks don't have their targets modified, and therefore can point -// to locations outside the base dir or to non-existent paths. -// 3. Readlink and Lstat ensures that the link file is located within the base -// dir, evaluating any symlinks that file or base dir may contain. -type BoundOS struct { - baseDir string - deduplicatePath bool -} - -func newBoundOS(d string, deduplicatePath bool) billy.Filesystem { - return &BoundOS{baseDir: d, deduplicatePath: deduplicatePath} -} - -func (fs *BoundOS) Create(filename string) (billy.File, error) { - return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, defaultCreateMode) -} - -func (fs *BoundOS) OpenFile(filename string, flag int, perm fs.FileMode) (billy.File, error) { - filename = fs.expandDot(filename) - fn, err := fs.abs(filename) - if err != nil { - return nil, err - } - - return openFile(fn, flag, perm, fs.createDir) -} - -func (fs *BoundOS) ReadDir(path string) ([]os.FileInfo, error) { - path = fs.expandDot(path) - dir, err := fs.abs(path) - if err != nil { - return nil, err - } - - return readDir(dir) -} - -func (fs *BoundOS) Rename(from, to string) error { - if from == "." || from == fs.baseDir { - return billy.ErrBaseDirCannotBeRenamed - } - - from = fs.expandDot(from) - _, err := fs.Lstat(from) - if err != nil { - return err - } - - f, err := fs.abs(from) - if err != nil { - return err - } - - to = fs.expandDot(to) - t, err := fs.abs(to) - if err != nil { - return err - } - - // MkdirAll for target name. - if err := fs.createDir(t); err != nil { - return err - } - - return os.Rename(f, t) -} - -func (fs *BoundOS) MkdirAll(path string, perm fs.FileMode) error { - path = fs.expandDot(path) - dir, err := fs.abs(path) - if err != nil { - return err - } - return os.MkdirAll(dir, perm) -} - -func (fs *BoundOS) Open(filename string) (billy.File, error) { - return fs.OpenFile(filename, os.O_RDONLY, 0) -} - -func (fs *BoundOS) Stat(filename string) (os.FileInfo, error) { - filename = fs.expandDot(filename) - filename, err := fs.abs(filename) - if err != nil { - return nil, err - } - return os.Stat(filename) -} - -func (fs *BoundOS) Remove(filename string) error { - if filename == "." || filename == fs.baseDir { - return billy.ErrBaseDirCannotBeRemoved - } - - fn, err := fs.abs(filename) - if err != nil { - return err - } - return os.Remove(fn) -} - -// TempFile creates a temporary file. If dir is empty, the file -// will be created within the OS Temporary dir. If dir is provided -// it must descend from the current base dir. -func (fs *BoundOS) TempFile(dir, prefix string) (billy.File, error) { - if dir != "" { - var err error - dir, err = fs.abs(dir) - if err != nil { - return nil, err - } - } - - return tempFile(dir, prefix) -} - -func (fs *BoundOS) Join(elem ...string) string { - return filepath.Join(elem...) -} - -func (fs *BoundOS) RemoveAll(path string) error { - if path == "." || path == fs.baseDir { - return billy.ErrBaseDirCannotBeRemoved - } - - path = fs.expandDot(path) - dir, err := fs.abs(path) - if err != nil { - return err - } - return os.RemoveAll(dir) -} - -func (fs *BoundOS) Symlink(target, link string) error { - link = fs.expandDot(link) - ln, err := fs.abs(link) - if err != nil { - return err - } - // MkdirAll for containing dir. - if err := fs.createDir(ln); err != nil { - return err - } - return os.Symlink(target, ln) -} - -func (fs *BoundOS) expandDot(p string) string { - if p == "." { - return fs.baseDir - } - for _, prefix := range dotPrefixes { - if strings.HasPrefix(p, prefix) { - return filepath.Join(fs.baseDir, strings.TrimPrefix(p, prefix)) - } - } - return p -} - -func (fs *BoundOS) Lstat(filename string) (os.FileInfo, error) { - filename = fs.expandDot(filename) - filename = filepath.Clean(filename) - if !filepath.IsAbs(filename) { - filename = filepath.Join(fs.baseDir, filename) - } - if ok, err := fs.insideBaseDirEval(filename); !ok { - return nil, err - } - return os.Lstat(filename) -} - -func (fs *BoundOS) Readlink(link string) (string, error) { - link = fs.expandDot(link) - if !filepath.IsAbs(link) { - link = filepath.Clean(filepath.Join(fs.baseDir, link)) - } - if ok, err := fs.insideBaseDirEval(link); !ok { - return "", err - } - return os.Readlink(link) -} - -// Chroot returns a new BoundOS filesystem, with the base dir set to the -// result of joining the provided path with the underlying base dir. -func (fs *BoundOS) Chroot(path string) (billy.Filesystem, error) { - joined, err := securejoin.SecureJoin(fs.baseDir, path) - if err != nil { - return nil, err - } - return New(joined, WithBoundOS()), nil -} - -// Root returns the current base dir of the billy.Filesystem. -// This is required in order for this implementation to be a drop-in -// replacement for other upstream implementations (e.g. memory and osfs). -func (fs *BoundOS) Root() string { - return fs.baseDir -} - -func (fs *BoundOS) createDir(fullpath string) error { - dir := filepath.Dir(fullpath) - if dir != "." { - if err := os.MkdirAll(dir, defaultDirectoryMode); err != nil { - return err - } - } - - return nil -} - -// abs transforms filename to an absolute path, taking into account the base dir. -// Relative paths won't be allowed to ascend the base dir, so `../file` will become -// `/working-dir/file`. -// -// Note that if filename is a symlink, the returned address will be the target of the -// symlink. -func (fs *BoundOS) abs(filename string) (string, error) { - if filename == fs.baseDir { - filename = string(filepath.Separator) - } - - path, err := securejoin.SecureJoin(fs.baseDir, filename) - if err != nil { - return "", err - } - - if fs.deduplicatePath { - vol := filepath.VolumeName(fs.baseDir) - dup := filepath.Join(fs.baseDir, fs.baseDir[len(vol):]) - if strings.HasPrefix(path, dup+string(filepath.Separator)) { - return fs.abs(path[len(dup):]) - } - } - return path, nil -} - -// insideBaseDirEval checks whether filename is contained within -// a dir that is within the fs.baseDir, by first evaluating any symlinks -// that either filename or fs.baseDir may contain. -func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) { - if fs.baseDir == "/" || fs.baseDir == "" || fs.baseDir == filename { - return true, nil - } - dir, err := filepath.EvalSymlinks(filepath.Dir(filename)) - if dir == "" || os.IsNotExist(err) { - dir = filepath.Dir(filename) - } - wd, err := filepath.EvalSymlinks(fs.baseDir) - if wd == "" || os.IsNotExist(err) { - wd = fs.baseDir - } - if filename != wd && dir != wd && !strings.HasPrefix(dir, wd+string(filepath.Separator)) { - return false, fmt.Errorf("%q: path outside base dir %q: %w", filename, fs.baseDir, os.ErrNotExist) - } - return true, nil -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_chroot.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_chroot.go deleted file mode 100644 index aefd3415..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_chroot.go +++ /dev/null @@ -1,118 +0,0 @@ -//go:build !js -// +build !js - -package osfs - -import ( - "io/fs" - "os" - "path/filepath" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/helper/chroot" -) - -// ChrootOS is a legacy filesystem based on a "soft chroot" of the os filesystem. -// Although this is still the default os filesystem, consider using BoundOS instead. -// -// Behaviours of note: -// 1. A "soft chroot" translates the base dir to "/" for the purposes of the -// fs abstraction. -// 2. Symlinks targets may be modified to be kept within the chroot bounds. -// 3. Some file modes does not pass-through the fs abstraction. -// 4. The combination of 1 and 2 may cause go-git to think that a Git repository -// is dirty, when in fact it isn't. -type ChrootOS struct{} - -func newChrootOS(baseDir string) billy.Filesystem { - return chroot.New(&ChrootOS{}, baseDir) -} - -func (fs *ChrootOS) Create(filename string) (billy.File, error) { - return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, defaultCreateMode) -} - -func (fs *ChrootOS) OpenFile(filename string, flag int, perm fs.FileMode) (billy.File, error) { - return openFile(filename, flag, perm, fs.createDir) -} - -func (fs *ChrootOS) createDir(fullpath string) error { - dir := filepath.Dir(fullpath) - if dir != "." { - if err := os.MkdirAll(dir, defaultDirectoryMode); err != nil { - return err - } - } - - return nil -} - -func (fs *ChrootOS) ReadDir(dir string) ([]os.FileInfo, error) { - return readDir(dir) -} - -func (fs *ChrootOS) Rename(from, to string) error { - _, err := fs.Lstat(from) - if err != nil { - return err - } - - if err = fs.createDir(to); err != nil { - return err - } - - return rename(from, to) -} - -func (fs *ChrootOS) MkdirAll(path string, _ os.FileMode) error { - return os.MkdirAll(path, defaultDirectoryMode) -} - -func (fs *ChrootOS) Open(filename string) (billy.File, error) { - return fs.OpenFile(filename, os.O_RDONLY, 0) -} - -func (fs *ChrootOS) Stat(filename string) (os.FileInfo, error) { - return os.Stat(filename) -} - -func (fs *ChrootOS) Remove(filename string) error { - return os.Remove(filename) -} - -func (fs *ChrootOS) TempFile(dir, prefix string) (billy.File, error) { - if err := fs.createDir(dir + string(os.PathSeparator)); err != nil { - return nil, err - } - - return tempFile(dir, prefix) -} - -func (fs *ChrootOS) Join(elem ...string) string { - return filepath.Join(elem...) -} - -func (fs *ChrootOS) RemoveAll(path string) error { - return os.RemoveAll(filepath.Clean(path)) -} - -func (fs *ChrootOS) Lstat(filename string) (os.FileInfo, error) { - return os.Lstat(filepath.Clean(filename)) -} - -func (fs *ChrootOS) Symlink(target, link string) error { - if err := fs.createDir(link); err != nil { - return err - } - - return os.Symlink(target, link) -} - -func (fs *ChrootOS) Readlink(link string) (string, error) { - return os.Readlink(link) -} - -// Capabilities implements the Capable interface. -func (fs *ChrootOS) Capabilities() billy.Capability { - return billy.DefaultCapabilities -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_js.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_js.go deleted file mode 100644 index 170c480a..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_js.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build js -// +build js - -package osfs - -import ( - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/helper/chroot" - "github.com/go-git/go-billy/v6/memfs" -) - -// globalMemFs is the global memory fs -var globalMemFs = memfs.New() - -// Default Filesystem representing the root of in-memory filesystem for a -// js/wasm environment. -var Default = memfs.New() - -// New returns a new OS filesystem. -func New(baseDir string, _ ...Option) billy.Filesystem { - return chroot.New(Default, Default.Join("/", baseDir)) -} - -type options struct { -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_options.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_options.go deleted file mode 100644 index 2f235c6d..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_options.go +++ /dev/null @@ -1,3 +0,0 @@ -package osfs - -type Option func(*options) diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_plan9.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_plan9.go deleted file mode 100644 index 84020b52..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_plan9.go +++ /dev/null @@ -1,91 +0,0 @@ -//go:build plan9 -// +build plan9 - -package osfs - -import ( - "io" - "os" - "path/filepath" - "syscall" -) - -func (f *file) Lock() error { - // Plan 9 uses a mode bit instead of explicit lock/unlock syscalls. - // - // Per http://man.cat-v.org/plan_9/5/stat: “Exclusive use files may be open - // for I/O by only one fid at a time across all clients of the server. If a - // second open is attempted, it draws an error.” - // - // There is no obvious way to implement this function using the exclusive use bit. - // See https://golang.org/src/cmd/go/internal/lockedfile/lockedfile_plan9.go - // for how file locking is done by the go tool on Plan 9. - return nil -} - -func (f *file) Unlock() error { - return nil -} - -func rename(from, to string) error { - // If from and to are in different directories, copy the file - // since Plan 9 does not support cross-directory rename. - if filepath.Dir(from) != filepath.Dir(to) { - fi, err := os.Stat(from) - if err != nil { - return &os.LinkError{"rename", from, to, err} - } - if fi.Mode().IsDir() { - return &os.LinkError{"rename", from, to, syscall.EISDIR} - } - fromFile, err := os.Open(from) - if err != nil { - return &os.LinkError{"rename", from, to, err} - } - toFile, err := os.OpenFile(to, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fi.Mode()) - if err != nil { - return &os.LinkError{"rename", from, to, err} - } - _, err = io.Copy(toFile, fromFile) - if err != nil { - return &os.LinkError{"rename", from, to, err} - } - - // Copy mtime and mode from original file. - // We need only one syscall if we avoid os.Chmod and os.Chtimes. - dir := fi.Sys().(*syscall.Dir) - var d syscall.Dir - d.Null() - d.Mtime = dir.Mtime - d.Mode = dir.Mode - if err = dirwstat(to, &d); err != nil { - return &os.LinkError{"rename", from, to, err} - } - - // Remove original file. - err = os.Remove(from) - if err != nil { - return &os.LinkError{"rename", from, to, err} - } - return nil - } - return os.Rename(from, to) -} - -func dirwstat(name string, d *syscall.Dir) error { - var buf [syscall.STATFIXLEN]byte - - n, err := d.Marshal(buf[:]) - if err != nil { - return &os.PathError{"dirwstat", name, err} - } - if err = syscall.Wstat(name, buf[:n]); err != nil { - return &os.PathError{"dirwstat", name, err} - } - return nil -} - -func umask(new int) func() { - return func() { - } -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_posix.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_posix.go deleted file mode 100644 index 7dd20621..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_posix.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build !plan9 && !windows && !wasm -// +build !plan9,!windows,!wasm - -package osfs - -import ( - "os" - "syscall" - - "golang.org/x/sys/unix" -) - -func (f *file) Lock() error { - f.m.Lock() - defer f.m.Unlock() - - return unix.Flock(int(f.Fd()), unix.LOCK_EX) -} - -func (f *file) Unlock() error { - f.m.Lock() - defer f.m.Unlock() - - return unix.Flock(int(f.Fd()), unix.LOCK_UN) -} - -func rename(from, to string) error { - return os.Rename(from, to) -} - -// umask sets umask to a new value, and returns a func which allows the -// caller to reset it back to what it was originally. -func umask(m int) func() { - old := syscall.Umask(m) - return func() { - syscall.Umask(old) - } -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_wasip1.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_wasip1.go deleted file mode 100644 index 79e6e331..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_wasip1.go +++ /dev/null @@ -1,34 +0,0 @@ -//go:build wasip1 -// +build wasip1 - -package osfs - -import ( - "os" - "syscall" -) - -func (f *file) Lock() error { - f.m.Lock() - defer f.m.Unlock() - return nil -} - -func (f *file) Unlock() error { - f.m.Lock() - defer f.m.Unlock() - return nil -} - -func rename(from, to string) error { - return os.Rename(from, to) -} - -// umask sets umask to a new value, and returns a func which allows the -// caller to reset it back to what it was originally. -func umask(new int) func() { - old := syscall.Umask(new) - return func() { - syscall.Umask(old) - } -} diff --git a/vendor/github.com/go-git/go-billy/v6/osfs/os_windows.go b/vendor/github.com/go-git/go-billy/v6/osfs/os_windows.go deleted file mode 100644 index e23cede7..00000000 --- a/vendor/github.com/go-git/go-billy/v6/osfs/os_windows.go +++ /dev/null @@ -1,58 +0,0 @@ -//go:build windows -// +build windows - -package osfs - -import ( - "os" - "runtime" - "unsafe" - - "golang.org/x/sys/windows" -) - -var ( - kernel32DLL = windows.NewLazySystemDLL("kernel32.dll") - lockFileExProc = kernel32DLL.NewProc("LockFileEx") - unlockFileProc = kernel32DLL.NewProc("UnlockFile") -) - -const ( - lockfileExclusiveLock = 0x2 -) - -func (f *file) Lock() error { - f.m.Lock() - defer f.m.Unlock() - - var overlapped windows.Overlapped - // err is always non-nil as per sys/windows semantics. - ret, _, err := lockFileExProc.Call(f.File.Fd(), lockfileExclusiveLock, 0, 0xFFFFFFFF, 0, - uintptr(unsafe.Pointer(&overlapped))) - runtime.KeepAlive(&overlapped) - if ret == 0 { - return err - } - return nil -} - -func (f *file) Unlock() error { - f.m.Lock() - defer f.m.Unlock() - - // err is always non-nil as per sys/windows semantics. - ret, _, err := unlockFileProc.Call(f.File.Fd(), 0, 0, 0xFFFFFFFF, 0) - if ret == 0 { - return err - } - return nil -} - -func rename(from, to string) error { - return os.Rename(from, to) -} - -func umask(_ int) func() { - return func() { - } -} diff --git a/vendor/github.com/go-git/go-billy/v6/util/glob.go b/vendor/github.com/go-git/go-billy/v6/util/glob.go deleted file mode 100644 index 7de47789..00000000 --- a/vendor/github.com/go-git/go-billy/v6/util/glob.go +++ /dev/null @@ -1,111 +0,0 @@ -package util - -import ( - "path/filepath" - "sort" - "strings" - - "github.com/go-git/go-billy/v6" -) - -// Glob returns the names of all files matching pattern or nil -// if there is no matching file. The syntax of patterns is the same -// as in Match. The pattern may describe hierarchical names such as -// /usr/*/bin/ed (assuming the Separator is '/'). -// -// Glob ignores file system errors such as I/O errors reading directories. -// The only possible returned error is ErrBadPattern, when pattern -// is malformed. -// -// Function originally from https://golang.org/src/path/filepath/match_test.go -func Glob(fs billy.Filesystem, pattern string) (matches []string, err error) { - if !hasMeta(pattern) { - if _, err = fs.Lstat(pattern); err != nil { - return nil, nil - } - return []string{pattern}, nil - } - - dir, file := filepath.Split(pattern) - // Prevent infinite recursion. See issue 15879. - if dir == pattern { - return nil, filepath.ErrBadPattern - } - - var m []string - m, err = Glob(fs, cleanGlobPath(dir)) - if err != nil { - return - } - for _, d := range m { - matches, err = glob(fs, d, file, matches) - if err != nil { - return - } - } - return -} - -// cleanGlobPath prepares path for glob matching. -func cleanGlobPath(path string) string { - switch path { - case "": - return "." - case string(filepath.Separator): - // do nothing to the path - return path - default: - return path[0 : len(path)-1] // chop off trailing separator - } -} - -// glob searches for files matching pattern in the directory dir -// and appends them to matches. If the directory cannot be -// opened, it returns the existing matches. New matches are -// added in lexicographical order. -func glob(fs billy.Filesystem, dir, pattern string, matches []string) (m []string, e error) { - m = matches - fi, err := fs.Stat(dir) - if err != nil { - return - } - - if !fi.IsDir() { - return - } - - names, _ := readdirnames(fs, dir) - sort.Strings(names) - - for _, n := range names { - matched, err := filepath.Match(pattern, n) - if err != nil { - return m, err - } - if matched { - m = append(m, filepath.Join(dir, n)) - } - } - return -} - -// hasMeta reports whether path contains any of the magic characters -// recognized by Match. -func hasMeta(path string) bool { - // TODO(niemeyer): Should other magic characters be added here? - return strings.ContainsAny(path, "*?[") -} - -func readdirnames(fs billy.Filesystem, dir string) ([]string, error) { - files, err := fs.ReadDir(dir) - if err != nil { - return nil, err - } - - names := make([]string, 0, len(files)) - for _, file := range files { - names = append(names, file.Name()) - } - - return names, nil -} diff --git a/vendor/github.com/go-git/go-billy/v6/util/util.go b/vendor/github.com/go-git/go-billy/v6/util/util.go deleted file mode 100644 index 24b84fa6..00000000 --- a/vendor/github.com/go-git/go-billy/v6/util/util.go +++ /dev/null @@ -1,291 +0,0 @@ -package util - -import ( - "errors" - "fmt" - "io" - "io/fs" - "os" - "path/filepath" - "strconv" - "sync" - "time" - - "github.com/go-git/go-billy/v6" -) - -// RemoveAll removes path and any children it contains. It removes everything it -// can but returns the first error it encounters. If the path does not exist, -// RemoveAll returns nil (no error). -func RemoveAll(fs billy.Basic, path string) error { - fs, path = getUnderlyingAndPath(fs, path) - - if r, ok := fs.(removerAll); ok { - return r.RemoveAll(path) - } - - return removeAll(fs, path) -} - -type removerAll interface { - RemoveAll(string) error -} - -func removeAll(fs billy.Basic, path string) error { - // This implementation is adapted from os.RemoveAll. - - // Simple case: if Remove works, we're done. - err := fs.Remove(path) - if err == nil || errors.Is(err, os.ErrNotExist) { - return nil - } - - // Otherwise, is this a directory we need to recurse into? - dir, serr := fs.Stat(path) - if serr != nil { - if errors.Is(serr, os.ErrNotExist) { - return nil - } - - return serr - } - - if !dir.IsDir() { - // Not a directory; return the error from Remove. - return err - } - - dirfs, ok := fs.(billy.Dir) - if !ok { - return billy.ErrNotSupported - } - - // Directory. - fis, err := dirfs.ReadDir(path) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - // Race. It was deleted between the Lstat and Open. - // Return nil per RemoveAll's docs. - return nil - } - - return err - } - - // Remove contents & return first error. - err = nil - for _, fi := range fis { - cpath := fs.Join(path, fi.Name()) - err1 := removeAll(fs, cpath) - if err == nil { - err = err1 - } - } - - // Remove directory. - err1 := fs.Remove(path) - if err1 == nil || errors.Is(err1, os.ErrNotExist) { - return nil - } - - if err == nil { - err = err1 - } - - return err -} - -// WriteFile writes data to a file named by filename in the given filesystem. -// If the file does not exist, WriteFile creates it with permissions perm; -// otherwise WriteFile truncates it before writing. -func WriteFile(fs billy.Basic, filename string, data []byte, perm fs.FileMode) (err error) { - f, err := fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) - if err != nil { - return err - } - defer func() { - if f != nil { - err1 := f.Close() - if err == nil { - err = err1 - } - } - }() - - n, err := f.Write(data) - if err == nil && n < len(data) { - err = io.ErrShortWrite - } - - return nil -} - -// Random number state. -// We generate random temporary file names so that there's a good -// chance the file doesn't exist yet - keeps the number of tries in -// TempFile to a minimum. -var rand uint32 -var randmu sync.Mutex - -func reseed() uint32 { - return uint32(time.Now().UnixNano() + int64(os.Getpid())) -} - -func nextSuffix() string { - randmu.Lock() - r := rand - if r == 0 { - r = reseed() - } - r = r*1664525 + 1013904223 // constants from Numerical Recipes - rand = r - randmu.Unlock() - return strconv.Itoa(int(1e9 + r%1e9))[1:] -} - -// TempFile creates a new temporary file in the directory dir with a name -// beginning with prefix, opens the file for reading and writing, and returns -// the resulting *os.File. If dir is the empty string, TempFile uses the default -// directory for temporary files (see os.TempDir). Multiple programs calling -// TempFile simultaneously will not choose the same file. The caller can use -// f.Name() to find the pathname of the file. It is the caller's responsibility -// to remove the file when no longer needed. -func TempFile(fs billy.Basic, dir, prefix string) (f billy.File, err error) { - // This implementation is based on stdlib ioutil.TempFile. - if dir == "" { - dir = getTempDir(fs) - } - - nconflict := 0 - for i := 0; i < 10000; i++ { - name := filepath.Join(dir, prefix+nextSuffix()) - f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if errors.Is(err, os.ErrExist) { - if nconflict++; nconflict > 10 { - randmu.Lock() - rand = reseed() - randmu.Unlock() - } - continue - } - break - } - return -} - -// TempDir creates a new temporary directory in the directory dir -// with a name beginning with prefix and returns the path of the -// new directory. If dir is the empty string, TempDir uses the -// default directory for temporary files (see os.TempDir). -// Multiple programs calling TempDir simultaneously -// will not choose the same directory. It is the caller's responsibility -// to remove the directory when no longer needed. -func TempDir(fs billy.Dir, dir, prefix string) (name string, err error) { - // This implementation is based on stdlib ioutil.TempDir - if dir == "" { - base, ok := fs.(billy.Basic) - if !ok { - return "", fmt.Errorf("fs does not implement billy.Basic") - } - dir = getTempDir(base) - } - - nconflict := 0 - for i := 0; i < 10000; i++ { - try := filepath.Join(dir, prefix+nextSuffix()) - err = fs.MkdirAll(try, 0700) - if errors.Is(err, os.ErrExist) { - if nconflict++; nconflict > 10 { - randmu.Lock() - rand = reseed() - randmu.Unlock() - } - continue - } - if errors.Is(err, os.ErrNotExist) { - if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) { - return "", err - } - } - if err == nil { - name = try - } - break - } - return -} - -func getTempDir(fs billy.Basic) string { - ch, ok := fs.(billy.Chroot) - if !ok || ch.Root() == "" || ch.Root() == "/" || ch.Root() == string(filepath.Separator) { - return os.TempDir() - } - - return ".tmp" -} - -type underlying interface { - Underlying() billy.Basic -} - -func getUnderlyingAndPath(fs billy.Basic, path string) (billy.Basic, string) { - u, ok := fs.(underlying) - if !ok { - return fs, path - } - if ch, ok := fs.(billy.Chroot); ok { - path = fs.Join(ch.Root(), path) - } - - return u.Underlying(), path -} - -// ReadFile reads the named file and returns the contents from the given filesystem. -// A successful call returns err == nil, not err == EOF. -// Because ReadFile reads the whole file, it does not treat an EOF from Read -// as an error to be reported. -func ReadFile(fs billy.Basic, name string) ([]byte, error) { - f, err := fs.Open(name) - if err != nil { - return nil, err - } - - defer f.Close() - - var size int - if info, err := fs.Stat(name); err == nil { - size64 := info.Size() - if int64(int(size64)) == size64 { - size = int(size64) - } - } - - size++ // one byte for final read at EOF - // If a file claims a small size, read at least 512 bytes. - // In particular, files in Linux's /proc claim size 0 but - // then do not work right if read in small pieces, - // so an initial read of 1 byte would not work correctly. - - if size < 512 { - size = 512 - } - - data := make([]byte, 0, size) - for { - if len(data) >= cap(data) { - d := append(data[:cap(data)], 0) - data = d[:len(data)] - } - - n, err := f.Read(data[len(data):cap(data)]) - data = data[:len(data)+n] - - if err != nil { - if errors.Is(err, io.EOF) { - err = nil - } - - return data, err - } - } -} diff --git a/vendor/github.com/go-git/go-billy/v6/util/walk.go b/vendor/github.com/go-git/go-billy/v6/util/walk.go deleted file mode 100644 index 982b92f1..00000000 --- a/vendor/github.com/go-git/go-billy/v6/util/walk.go +++ /dev/null @@ -1,73 +0,0 @@ -package util - -import ( - "errors" - "os" - "path/filepath" - - "github.com/go-git/go-billy/v6" -) - -// walk recursively descends path, calling walkFn -// adapted from https://golang.org/src/path/filepath/path.go -func walk(fs billy.Filesystem, path string, info os.FileInfo, walkFn filepath.WalkFunc) error { - if !info.IsDir() { - return walkFn(path, info, nil) - } - - names, err := readdirnames(fs, path) - err1 := walkFn(path, info, err) - // If err != nil, walk can't walk into this directory. - // err1 != nil means walkFn want walk to skip this directory or stop walking. - // Therefore, if one of err and err1 isn't nil, walk will return. - if err != nil || err1 != nil { - // The caller's behavior is controlled by the return value, which is decided - // by walkFn. walkFn may ignore err and return nil. - // If walkFn returns SkipDir, it will be handled by the caller. - // So walk should return whatever walkFn returns. - return err1 - } - - for _, name := range names { - filename := filepath.Join(path, name) - fileInfo, err := fs.Lstat(filename) - if err != nil { - if err := walkFn(filename, fileInfo, err); err != nil && !errors.Is(err, filepath.SkipDir) { - return err - } - } else { - err = walk(fs, filename, fileInfo, walkFn) - if err != nil { - if !fileInfo.IsDir() || !errors.Is(err, filepath.SkipDir) { - return err - } - } - } - } - return nil -} - -// Walk walks the file tree rooted at root, calling fn for each file or -// directory in the tree, including root. All errors that arise visiting files -// and directories are filtered by fn: see the WalkFunc documentation for -// details. -// -// The files are walked in lexical order, which makes the output deterministic -// but requires Walk to read an entire directory into memory before proceeding -// to walk that directory. Walk does not follow symbolic links. -// -// Function adapted from https://github.com/golang/go/blob/3b770f2ccb1fa6fecc22ea822a19447b10b70c5c/src/path/filepath/path.go#L500 -func Walk(fs billy.Filesystem, root string, walkFn filepath.WalkFunc) error { - info, err := fs.Lstat(root) - if err != nil { - err = walkFn(root, nil, err) - } else { - err = walk(fs, root, info, walkFn) - } - - if errors.Is(err, filepath.SkipDir) { - return nil - } - - return err -} diff --git a/vendor/github.com/go-git/go-git/v6/.gitignore b/vendor/github.com/go-git/go-git/v6/.gitignore deleted file mode 100644 index b7f2c580..00000000 --- a/vendor/github.com/go-git/go-git/v6/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -coverage.out -*~ -coverage.txt -profile.out -.tmp/ -.git-dist/ -.vscode diff --git a/vendor/github.com/go-git/go-git/v6/CODE_OF_CONDUCT.md b/vendor/github.com/go-git/go-git/v6/CODE_OF_CONDUCT.md deleted file mode 100644 index a689fa3c..00000000 --- a/vendor/github.com/go-git/go-git/v6/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,74 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, race, -religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at conduct@sourced.tech. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html - -[homepage]: https://www.contributor-covenant.org - diff --git a/vendor/github.com/go-git/go-git/v6/COMPATIBILITY.md b/vendor/github.com/go-git/go-git/v6/COMPATIBILITY.md deleted file mode 100644 index ba1fb90a..00000000 --- a/vendor/github.com/go-git/go-git/v6/COMPATIBILITY.md +++ /dev/null @@ -1,234 +0,0 @@ -# Supported Features - -Here is a non-comprehensive table of git commands and features and their -compatibility status with go-git. - -## Getting and creating repositories - -| Feature | Sub-feature | Status | Notes | Examples | -| ------- | ------------------------------------------------------------------------------------------------------------------ | ------ | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `init` | | ✅ | | | -| `init` | `--bare` | ✅ | | | -| `init` | `--template`
`--separate-git-dir`
`--shared` | ❌ | | | -| `clone` | | ✅ | | - [PlainClone](_examples/clone/main.go) | -| `clone` | Authentication:
- none
- access token
- username + password
- ssh | ✅ | | - [clone ssh (private_key)](_examples/clone/auth/ssh/private_key/main.go)
- [clone ssh (ssh_agent)](_examples/clone/auth/ssh/ssh_agent/main.go)
- [clone access token](_examples/clone/auth/basic/access_token/main.go)
- [clone user + password](_examples/clone/auth/basic/username_password/main.go) | -| `clone` | `--progress`
`--single-branch`
`--depth`
`--origin`
`--recurse-submodules`
`--shared` | ✅ | | - [recurse submodules](_examples/clone/main.go)
- [progress](_examples/progress/main.go) | - -## Basic snapshotting - -| Feature | Sub-feature | Status | Notes | Examples | -| -------- | ----------- | ------ | -------------------------------------------------------- | ------------------------------------ | -| `add` | | ✅ | Plain add is supported. Any other flags aren't supported | | -| `status` | | ✅ | | | -| `commit` | | ✅ | | - [commit](_examples/commit/main.go) | -| `reset` | | ✅ | | | -| `rm` | | ✅ | | | -| `mv` | | ✅ | | | - -## Branching and merging - -| Feature | Sub-feature | Status | Notes | Examples | -| ----------- | ----------- | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------- | -| `branch` | | ✅ | | - [branch](_examples/branch/main.go) | -| `checkout` | | ✅ | Basic usages of checkout are supported. | - [checkout](_examples/checkout/main.go) | -| `merge` | | ⚠️ (partial) | Fast-forward only | | -| `mergetool` | | ❌ | | | -| `stash` | | ❌ | | | -| `sparse-checkout` | | ✅ | | - [sparse-checkout](_examples/sparse-checkout/main.go) | -| `tag` | | ✅ | | - [tag](_examples/tag/main.go)
- [tag create and push](_examples/tag-create-push/main.go) | - -## Sharing and updating projects - -| Feature | Sub-feature | Status | Notes | Examples | -| ----------- | ----------- | ------ | ----------------------------------------------------------------------- | ------------------------------------------ | -| `fetch` | | ✅ | | | -| `pull` | | ✅ | Only supports merges where the merge can be resolved as a fast-forward. | - [pull](_examples/pull/main.go) | -| `push` | | ✅ | | - [push](_examples/push/main.go) | -| `remote` | | ✅ | | - [remotes](_examples/remotes/main.go) | -| `submodule` | | ✅ | | - [submodule](_examples/submodule/main.go) | -| `submodule` | deinit | ❌ | | | - -## Inspection and comparison - -| Feature | Sub-feature | Status | Notes | Examples | -| ---------- | ----------- | --------- | ----- | ------------------------------ | -| `show` | | ✅ | | | -| `log` | | ✅ | | - [log](_examples/log/main.go) | -| `shortlog` | | (see log) | | | -| `describe` | | ❌ | | | - -## Patching - -| Feature | Sub-feature | Status | Notes | Examples | -| ------------- | ----------- | ------ | ---------------------------------------------------- | -------- | -| `apply` | | ❌ | | | -| `cherry-pick` | | ❌ | | | -| `diff` | | ✅ | Patch object with UnifiedDiff output representation. | | -| `rebase` | | ❌ | | | -| `revert` | | ❌ | | | - -## Debugging - -| Feature | Sub-feature | Status | Notes | Examples | -| -------- | ----------- | ------ | ----- | ---------------------------------- | -| `bisect` | | ❌ | | | -| `blame` | | ✅ | | - [blame](_examples/blame/main.go) | -| `grep` | | ✅ | | | - -## Email - -| Feature | Sub-feature | Status | Notes | Examples | -| -------------- | ----------- | ------ | ----- | -------- | -| `am` | | ❌ | | | -| `apply` | | ❌ | | | -| `format-patch` | | ❌ | | | -| `send-email` | | ❌ | | | -| `request-pull` | | ❌ | | | - -## External systems - -| Feature | Sub-feature | Status | Notes | Examples | -| ------------- | ----------- | ------ | ----- | -------- | -| `svn` | | ❌ | | | -| `fast-import` | | ❌ | | | -| `lfs` | | ❌ | | | - -## Administration - -| Feature | Sub-feature | Status | Notes | Examples | -| --------------- | ----------- | ------ | ----- | -------- | -| `clean` | | ✅ | | | -| `gc` | | ❌ | | | -| `fsck` | | ❌ | | | -| `reflog` | | ❌ | | | -| `filter-branch` | | ❌ | | | -| `instaweb` | | ❌ | | | -| `archive` | | ❌ | | | -| `bundle` | | ❌ | | | -| `prune` | | ❌ | | | -| `repack` | | ❌ | | | - -## Server admin - -| Feature | Sub-feature | Status | Notes | Examples | -| -------------------- | ----------- | ------ | ----- | ----------------------------------------- | -| `daemon` | | ❌ | | | -| `update-server-info` | | ✅ | | [cli](./cli/go-git/update_server_info.go) | - -## Advanced - -| Feature | Sub-feature | Status | Notes | Examples | -| ---------- | ----------- | ----------- | ----- | -------- | -| `notes` | | ❌ | | | -| `replace` | | ❌ | | | -| `worktree` | | ❌ | | | -| `annotate` | | (see blame) | | | - -## GPG - -| Feature | Sub-feature | Status | Notes | Examples | -| ------------------- | ----------- | ------ | ----- | -------- | -| `git-verify-commit` | | ✅ | | | -| `git-verify-tag` | | ✅ | | | - -## Plumbing commands - -| Feature | Sub-feature | Status | Notes | Examples | -| --------------- | ------------------------------------- | ------------ | --------------------------------------------------- | -------------------------------------------- | -| `cat-file` | | ✅ | | | -| `check-ignore` | | ❌ | | | -| `commit-tree` | | ❌ | | | -| `count-objects` | | ❌ | | | -| `diff-index` | | ❌ | | | -| `for-each-ref` | | ✅ | | | -| `hash-object` | | ✅ | | | -| `ls-files` | | ✅ | | | -| `ls-remote` | | ✅ | | - [ls-remote](_examples/ls-remote/main.go) | -| `merge-base` | `--independent`
`--is-ancestor` | ⚠️ (partial) | Calculates the merge-base only between two commits. | - [merge-base](_examples/merge_base/main.go) | -| `merge-base` | `--fork-point`
`--octopus` | ❌ | | | -| `read-tree` | | ❌ | | | -| `rev-list` | | ✅ | | | -| `rev-parse` | | ❌ | | | -| `show-ref` | | ✅ | | | -| `symbolic-ref` | | ✅ | | | -| `update-index` | | ❌ | | | -| `update-ref` | | ❌ | | | -| `verify-pack` | | ❌ | | | -| `write-tree` | | ❌ | | | - -## Indexes and Git Protocols - -| Feature | Version | Status | Notes | -| -------------------- | ------------------------------------------------------------------------------- | ------ | ----- | -| index | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-index.txt) | ❌ | | -| index | [v2](https://github.com/git/git/blob/master/Documentation/gitformat-index.txt) | ✅ | | -| index | [v3](https://github.com/git/git/blob/master/Documentation/gitformat-index.txt) | ❌ | | -| pack-protocol | [v1](https://github.com/git/git/blob/master/Documentation/gitprotocol-pack.txt) | ✅ | | -| pack-protocol | [v2](https://github.com/git/git/blob/master/Documentation/gitprotocol-v2.txt) | ❌ | | -| multi-pack-index | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt) | ❌ | | -| pack-\*.rev files | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt) | ❌ | | -| pack-\*.mtimes files | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt) | ❌ | | -| cruft packs | | ❌ | | - -## Capabilities - -| Feature | Status | Notes | -| ------------------------------ | ------------ | ----- | -| `multi_ack` | ❌ | | -| `multi_ack_detailed` | ❌ | | -| `no-done` | ❌ | | -| `thin-pack` | ❌ | | -| `side-band` | ⚠️ (partial) | | -| `side-band-64k` | ⚠️ (partial) | | -| `ofs-delta` | ✅ | | -| `agent` | ✅ | | -| `object-format` | ❌ | | -| `symref` | ✅ | | -| `shallow` | ✅ | | -| `deepen-since` | ✅ | | -| `deepen-not` | ❌ | | -| `deepen-relative` | ❌ | | -| `no-progress` | ✅ | | -| `include-tag` | ✅ | | -| `report-status` | ✅ | | -| `report-status-v2` | ❌ | | -| `delete-refs` | ✅ | | -| `quiet` | ❌ | | -| `atomic` | ✅ | | -| `push-options` | ✅ | | -| `allow-tip-sha1-in-want` | ✅ | | -| `allow-reachable-sha1-in-want` | ❌ | | -| `push-cert=` | ❌ | | -| `filter` | ❌ | | -| `session-id=` | ❌ | | - -## Transport Schemes - -| Scheme | Status | Notes | Examples | -| -------------------- | ------------ | ---------------------------------------------------------------------- | ---------------------------------------------- | -| `http(s)://` (dumb) | ❌ | | | -| `http(s)://` (smart) | ✅ | | | -| `git://` | ✅ | | | -| `ssh://` | ✅ | | | -| `file://` | ⚠️ (partial) | Warning: this is not pure Golang. This shells out to the `git` binary. | | -| Custom | ✅ | All existing schemes can be replaced by custom implementations. | - [custom_http](_examples/custom_http/main.go) | - -## SHA256 - -| Feature | Sub-feature | Status | Notes | Examples | -| -------- | ----------- | ------ | ---------------------------------- | ------------------------------------ | -| `init` | | ✅ | Requires building with tag sha256. | - [init](_examples/sha256/main.go) | -| `commit` | | ✅ | Requires building with tag sha256. | - [commit](_examples/sha256/main.go) | -| `pull` | | ❌ | | | -| `fetch` | | ❌ | | | -| `push` | | ❌ | | | - -## Other features - -| Feature | Sub-feature | Status | Notes | Examples | -| --------------- | --------------------------- | ------ | ---------------------------------------------- | -------- | -| `config` | `--local` | ✅ | Read and write per-repository (`.git/config`). | | -| `config` | `--global`
`--system` | ✅ | Read-only. | | -| `gitignore` | | ✅ | | | -| `gitattributes` | | ✅ | | | -| `git-worktree` | | ❌ | Multiple worktrees are not supported. | | diff --git a/vendor/github.com/go-git/go-git/v6/CONTRIBUTING.md b/vendor/github.com/go-git/go-git/v6/CONTRIBUTING.md deleted file mode 100644 index 0c0b9797..00000000 --- a/vendor/github.com/go-git/go-git/v6/CONTRIBUTING.md +++ /dev/null @@ -1,84 +0,0 @@ -# Contributing Guidelines - -The go-git project is [Apache 2.0 licensed](LICENSE) and accepts -contributions via GitHub pull requests. This document outlines some of the -conventions on development workflow, commit message formatting, contact points, -and other resources to make it easier to get your contribution accepted. - -## Support Channels - -The official support channels, for users are: - -- [StackOverflow go-git tag] for user questions. -- GitHub [Issues]* for bug reports and feature requests. - -*Before opening a new issue or submitting a new pull request, it's helpful to -search the project - it's likely that another user has already reported the -issue you're facing, or it's a known issue that we're already aware of. - -In addition to the channels above, contributors are also able to join the go-git [discord server]. - -## How to Contribute - -### RFC Process for Major Changes - -For substantial changes to go-git's public APIs, architecture, process, or functionality, please consider using our [RFC (Request for Comments) process](rfcs/README.md). This includes: - -- New public APIs or significant changes to existing APIs -- Changes to storage interfaces or backends -- New plumbing or porcelain operations -- The processes around merging PRs or releasing changes -- Changes that would require migration guides for users - -The RFC process helps ensure that major changes are well-designed and have community consensus before implementation begins. - -### Pull Requests - -Pull Requests (PRs) are the main and exclusive way to contribute to the official go-git project. -In order for a PR to be accepted it needs to pass a list of requirements: - -- You should be able to run the same query using `git`. We don't accept features that are not implemented in the official git implementation. -- The expected behavior must match the [official git implementation]. -- The actual behavior must be correctly explained with natural language and providing a minimum working example in Go that reproduces it. -- All PRs must be written in idiomatic Go, formatted according to [gofmt], and without any warnings from [go vet]. -- They should in general include tests, and those shall pass. -- If the PR is a bug fix, it has to include a suite of unit tests for the new functionality. -- If the PR is a new feature, it has to come with a suite of unit tests, that tests the new functionality. -- In any case, all the PRs have to pass the personal evaluation of at least one of the maintainers of go-git. - -### Branches - -The development branch is `main`, where all development takes place. -All new features and bug fixes should target it. This was formely known -as `v6-exp` or `v6-transport`. This branch contains all the changes for -`v6` - the next major release. -From time to time this branch will contain breaking changes, as the API -for `v6` is being refined. - -The `releases/v5.x` branch is the branch for changes to the `v5` version, -which is now in maintaince mode. To avoid having to divert efforts from `v6`, -we will only be accepting bug fixes or CVE related dependency bumps for the -`v5` release. - -Bug fixes that also impact `main`, should be fixed there first, and then backported to `v5`. - -### Format of the commit message - -Every commit message should describe what was changed, under which context and, if applicable, the GitHub issue it relates to: - -``` -plumbing: packp, Skip argument validations for unknown capabilities. Fixes #623 -``` - -The format can be described more formally as follows: - -``` -: , . [Fixes #] -``` - -[discord server]: https://discord.gg/8hrxYEVPE5 -[StackOverflow go-git tag]: https://stackoverflow.com/questions/tagged/go-git -[Issues]: https://github.com/go-git/go-git/issues -[official git implementation]: https://github.com/git/git -[gofmt]: https://golang.org/cmd/gofmt/ -[go vet]: https://golang.org/cmd/vet/ diff --git a/vendor/github.com/go-git/go-git/v6/EXTENDING.md b/vendor/github.com/go-git/go-git/v6/EXTENDING.md deleted file mode 100644 index 254ef7d9..00000000 --- a/vendor/github.com/go-git/go-git/v6/EXTENDING.md +++ /dev/null @@ -1,78 +0,0 @@ -# Extending go-git - -`go-git` was built in a highly extensible manner, which enables some of its functionalities to be changed or extended without the need of changing its codebase. Here are the key extensibility features: - -## Dot Git Storers - -Dot git storers are the components responsible for storing the Git internal files, including objects and references. - -The built-in storer implementations include [memory](storage/memory) and [filesystem](storage/filesystem). The `memory` storer stores all the data in memory, and its use look like this: - -```go - r, err := git.Init(memory.NewStorage(), nil) -``` - -The `filesystem` storer stores the data in the OS filesystem, and can be used as follows: - -```go - r, err := git.Init(filesystem.NewStorage(osfs.New("/tmp/foo")), nil) -``` - -New implementations can be created by implementing the [storage.Storer interface](storage/storer.go#L16). - -## Filesystem - -Git repository worktrees are managed using a filesystem abstraction based on [go-billy](https://github.com/go-git/go-billy). The Git operations will take place against the specific filesystem implementation. Initialising a repository in Memory can be done as follows: - -```go - fs := memfs.New() - r, err := git.Init(memory.NewStorage(), fs) -``` - -The same operation can be done against the OS filesystem: - -```go - fs := osfs.New("/tmp/foo") - r, err := git.Init(memory.NewStorage(), fs) -``` - -New filesystems (e.g. cloud based storage) could be created by implementing `go-billy`'s [Filesystem interface](https://github.com/go-git/go-billy/blob/326c59f064021b821a55371d57794fbfb86d4cb3/fs.go#L52). - -## Transport Schemes - -Git supports various transport schemes, including `http`, `https`, `ssh`, `git`, `file`. `go-git` defines the [transport.Transport interface](plumbing/transport/common.go#L48) to represent them. - -The built-in implementations can be replaced by calling `transport.Register`. - -An example of changing the built-in `https` implementation to skip TLS could look like this: - -```go - customClient := &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - }, - } - - transport.Register("https", githttp.NewTransport(&githttp.TransportOptions{Client: customClient})) -``` - -Some internal implementations enables code reuse amongst the different transport implementations. Some of these may be made public in the future (e.g. `plumbing/transport/internal/common`). - -## Cache - -Several different operations across `go-git` lean on caching of objects in order to achieve optimal performance. The caching functionality is defined by the [cache.Object interface](plumbing/cache/common.go#L17). - -Two built-in implementations are `cache.ObjectLRU` and `cache.BufferLRU`. However, the caching functionality can be customized by implementing the interface `cache.Object` interface. - -## Hash - -`go-git` uses the `crypto.Hash` interface to represent hash functions. The built-in implementations are `github.com/pjbgf/sha1cd` for SHA1 and Go's `crypto/SHA256`. - -The default hash functions can be changed by calling `hash.RegisterHash`. -```go - func init() { - hash.RegisterHash(crypto.SHA1, sha1.New) - } -``` - -New `SHA1` or `SHA256` hash functions that implement the `hash.RegisterHash` interface can be registered by calling `RegisterHash`. diff --git a/vendor/github.com/go-git/go-git/v6/LICENSE b/vendor/github.com/go-git/go-git/v6/LICENSE deleted file mode 100644 index 8aa3d854..00000000 --- a/vendor/github.com/go-git/go-git/v6/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018 Sourced Technologies, S.L. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-git/go-git/v6/Makefile b/vendor/github.com/go-git/go-git/v6/Makefile deleted file mode 100644 index 5cd13e7d..00000000 --- a/vendor/github.com/go-git/go-git/v6/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# General -WORKDIR = $(PWD) - -# Go parameters -GOCMD = go -GOTEST = $(GOCMD) test - -# Git config -GIT_VERSION ?= -GIT_DIST_PATH ?= $(PWD)/.git-dist -GIT_REPOSITORY = http://github.com/git/git.git - -# Coverage -COVERAGE_REPORT = coverage.out -COVERAGE_MODE = count - -# Defines the maximum time each fuzz target will be executed for. -FUZZ_TIME ?= 10s -FUZZ_PKGS = $(shell grep -r --include='**_test.go' --files-with-matches 'func Fuzz' . | xargs -I{} dirname {}) - -build-git: - @if [ -f $(GIT_DIST_PATH)/git ]; then \ - echo "nothing to do, using cache $(GIT_DIST_PATH)"; \ - else \ - git clone $(GIT_REPOSITORY) -b $(GIT_VERSION) --depth 1 --single-branch $(GIT_DIST_PATH); \ - cd $(GIT_DIST_PATH); \ - make configure; \ - ./configure; \ - make all; \ - fi - -test: - @echo "running against `git version`"; \ - $(GOTEST) -race ./... - $(GOTEST) -v _examples/common_test.go _examples/common.go --examples - -test-coverage: - @echo "running against `git version`"; \ - echo "" > $(COVERAGE_REPORT); \ - $(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./... - -clean: - rm -rf $(GIT_DIST_PATH) - -fuzz: - @for path in $(FUZZ_PKGS); do \ - go test -fuzz=Fuzz -fuzztime=$(FUZZ_TIME) $$path; \ - done diff --git a/vendor/github.com/go-git/go-git/v6/README.md b/vendor/github.com/go-git/go-git/v6/README.md deleted file mode 100644 index 8ba4150d..00000000 --- a/vendor/github.com/go-git/go-git/v6/README.md +++ /dev/null @@ -1,131 +0,0 @@ -![go-git logo](https://cdn.rawgit.com/src-d/artwork/02036484/go-git/files/go-git-github-readme-header.png) -[![GoDoc](https://godoc.org/github.com/go-git/go-git/v6?status.svg)](https://pkg.go.dev/github.com/go-git/go-git/v6) [![Build Status](https://github.com/go-git/go-git/workflows/Test/badge.svg)](https://github.com/go-git/go-git/actions) [![Go Report Card](https://goreportcard.com/badge/github.com/go-git/go-git)](https://goreportcard.com/report/github.com/go-git/go-git) - -*go-git* is a highly extensible git implementation library written in **pure Go**. - -It can be used to manipulate git repositories at low level *(plumbing)* or high level *(porcelain)*, through an idiomatic Go API. It also supports several types of storage, such as in-memory filesystems, or custom implementations, thanks to the [`Storer`](https://pkg.go.dev/github.com/go-git/go-git/v6/plumbing/storer) interface. - -It's being actively developed since 2015 and is being used extensively by [Keybase](https://keybase.io/blog/encrypted-git-for-everyone), [Gitea](https://gitea.io/en-us/) or [Pulumi](https://github.com/search?q=org%3Apulumi+go-git&type=Code), and by many other libraries and tools. - -Project Status --------------- - -After the [legal issues](https://github.com/src-d/go-git/issues/1295#issuecomment-592965250) with the [`src-d`](https://github.com/src-d) organization, the lack of update for four months and the requirement to make a hard fork, the project is **now back to normality**. - -The project is currently actively maintained by individual contributors, including several of the original authors, but also backed by a new company, [gitsight](https://github.com/gitsight), where `go-git` is a critical component used at scale. - - -Comparison with git -------------------- - -*go-git* aims to be fully compatible with [git](https://github.com/git/git), all the *porcelain* operations are implemented to work exactly as *git* does. - -*git* is a humongous project with years of development by thousands of contributors, making it challenging for *go-git* to implement all the features. You can find a comparison of *go-git* vs *git* in the [compatibility documentation](COMPATIBILITY.md). - - -Installation ------------- - -The recommended way to install *go-git* is: - -```go -import "github.com/go-git/go-git/v6" // with go modules enabled (GO111MODULE=on or outside GOPATH) -import "github.com/go-git/go-git" // with go modules disabled -``` - - -Examples --------- - -> Please note that the `CheckIfError` and `Info` functions used in the examples are from the [examples package](https://github.com/go-git/go-git/blob/master/_examples/common.go#L19) just to be used in the examples. - - -### Basic example - -A basic example that mimics the standard `git clone` command - -```go -// Clone the given repository to the given directory -Info("git clone https://github.com/go-git/go-git") - -_, err := git.PlainClone("/tmp/foo", &git.CloneOptions{ - URL: "https://github.com/go-git/go-git", - Progress: os.Stdout, -}) - -CheckIfError(err) -``` - -Outputs: -``` -Counting objects: 4924, done. -Compressing objects: 100% (1333/1333), done. -Total 4924 (delta 530), reused 6 (delta 6), pack-reused 3533 -``` - -### In-memory example - -Cloning a repository into memory and printing the history of HEAD, just like `git log` does - - -```go -// Clones the given repository in memory, creating the remote, the local -// branches and fetching the objects, exactly as: -Info("git clone https://github.com/go-git/go-billy") - -r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{ - URL: "https://github.com/go-git/go-billy", -}) - -CheckIfError(err) - -// Gets the HEAD history from HEAD, just like this command: -Info("git log") - -// ... retrieves the branch pointed by HEAD -ref, err := r.Head() -CheckIfError(err) - - -// ... retrieves the commit history -cIter, err := r.Log(&git.LogOptions{From: ref.Hash()}) -CheckIfError(err) - -// ... just iterates over the commits, printing it -err = cIter.ForEach(func(c *object.Commit) error { - fmt.Println(c) - return nil -}) -CheckIfError(err) -``` - -Outputs: -``` -commit ded8054fd0c3994453e9c8aacaf48d118d42991e -Author: Santiago M. Mola -Date: Sat Nov 12 21:18:41 2016 +0100 - - index: ReadFrom/WriteTo returns IndexReadError/IndexWriteError. (#9) - -commit df707095626f384ce2dc1a83b30f9a21d69b9dfc -Author: Santiago M. Mola -Date: Fri Nov 11 13:23:22 2016 +0100 - - readwriter: fix bug when writing index. (#10) - - When using ReadWriter on an existing siva file, absolute offset for - index entries was not being calculated correctly. -... -``` - -You can find this [example](_examples/log/main.go) and many others in the [examples](_examples) folder. - -Contribute ----------- - -[Contributions](https://github.com/go-git/go-git/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) are more than welcome, if you are interested please take a look to -our [Contributing Guidelines](CONTRIBUTING.md). - -License -------- -Apache License Version 2.0, see [LICENSE](LICENSE) diff --git a/vendor/github.com/go-git/go-git/v6/SECURITY.md b/vendor/github.com/go-git/go-git/v6/SECURITY.md deleted file mode 100644 index 0d2f8d03..00000000 --- a/vendor/github.com/go-git/go-git/v6/SECURITY.md +++ /dev/null @@ -1,38 +0,0 @@ -# go-git Security Policy - -The purpose of this security policy is to outline `go-git`'s process -for reporting, handling and disclosing security sensitive information. - -## Supported Versions - -The project follows a version support policy where only the latest minor -release is actively supported. Therefore, only issues that impact the latest -minor release will be fixed. Users are encouraged to upgrade to the latest -minor/patch release to benefit from the most up-to-date features, bug fixes, -and security enhancements.​ - -The supported versions policy applies to both the `go-git` library and its -associated repositories within the `go-git` org. - -## Reporting Security Issues - -Please report any security vulnerabilities or potential weaknesses in `go-git` -privately via go-git-security@googlegroups.com. Do not publicly disclose the -details of the vulnerability until a fix has been implemented and released. - -During the process the project maintainers will investigate the report, so please -provide detailed information, including steps to reproduce, affected versions, and any mitigations if known. - -The project maintainers will acknowledge the receipt of the report and work with -the reporter to validate and address the issue. - -Please note that `go-git` does not have any bounty programs, and therefore do -not provide financial compensation for disclosures. - -## Security Disclosure Process - -The project maintainers will make every effort to promptly address security issues. - -Once a security vulnerability is fixed, a security advisory will be published to notify users and provide appropriate mitigation measures. - -All `go-git` advisories can be found at https://github.com/go-git/go-git/security/advisories. diff --git a/vendor/github.com/go-git/go-git/v6/blame.go b/vendor/github.com/go-git/go-git/v6/blame.go deleted file mode 100644 index 264d236a..00000000 --- a/vendor/github.com/go-git/go-git/v6/blame.go +++ /dev/null @@ -1,584 +0,0 @@ -package git - -import ( - "bytes" - "container/heap" - "errors" - "fmt" - "io" - "strconv" - "time" - "unicode/utf8" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/utils/diff" - "github.com/sergi/go-diff/diffmatchpatch" -) - -// BlameResult represents the result of a Blame operation. -type BlameResult struct { - // Path is the path of the File that we're blaming. - Path string - // Rev (Revision) is the hash of the specified Commit used to generate this result. - Rev plumbing.Hash - // Lines contains every line with its authorship. - Lines []*Line -} - -// Blame returns a BlameResult with the information about the last author of -// each line from file `path` at commit `c`. -func Blame(c *object.Commit, path string) (*BlameResult, error) { - // The file to blame is identified by the input arguments: - // commit and path. commit is a Commit object obtained from a Repository. Path - // represents a path to a specific file contained in the repository. - // - // Blaming a file is done by walking the tree in reverse order trying to find where each line was last modified. - // - // When a diff is found it cannot immediately assume it came from that commit, as it may have come from 1 of its - // parents, so it will first try to resolve those diffs from its parents, if it couldn't find the change in its - // parents then it will assign the change to itself. - // - // When encountering 2 parents that have made the same change to a file it will choose the parent that was merged - // into the current branch first (this is determined by the order of the parents inside the commit). - // - // This currently works on a line by line basis, if performance becomes an issue it could be changed to work with - // hunks rather than lines. Then when encountering diff hunks it would need to split them where necessary. - - b := new(blame) - b.fRev = c - b.path = path - b.q = new(priorityQueue) - - file, err := b.fRev.File(path) - if err != nil { - return nil, err - } - finalLines, err := file.Lines() - if err != nil { - return nil, err - } - finalLength := len(finalLines) - - needsMap := make([]lineMap, finalLength) - for i := range needsMap { - needsMap[i] = lineMap{i, i, nil, -1} - } - contents, err := file.Contents() - if err != nil { - return nil, err - } - b.q.Push(&queueItem{ - nil, - nil, - c, - path, - contents, - needsMap, - 0, - false, - 0, - }) - items := make([]*queueItem, 0) - for { - items = items[:0] - for { - if b.q.Len() == 0 { - return nil, errors.New("invalid state: no items left on the blame queue") - } - item := b.q.Pop() - items = append(items, item) - next := b.q.Peek() - if next == nil || next.Hash != item.Commit.Hash { - break - } - } - finished, err := b.addBlames(items) - if err != nil { - return nil, err - } - if finished { - break - } - } - - b.lineToCommit = make([]*object.Commit, finalLength) - for i := range needsMap { - b.lineToCommit[i] = needsMap[i].Commit - } - - lines := newLines(finalLines, b.lineToCommit) - - return &BlameResult{ - Path: path, - Rev: c.Hash, - Lines: lines, - }, nil -} - -// Line values represent the contents and author of a line in BlamedResult values. -type Line struct { - // Author is the email address of the last author that modified the line. - Author string - // AuthorName is the name of the last author that modified the line. - AuthorName string - // Text is the original text of the line. - Text string - // Date is when the original text of the line was introduced - Date time.Time - // Hash is the commit hash that introduced the original line - Hash plumbing.Hash -} - -func newLine(author, authorName, text string, date time.Time, hash plumbing.Hash) *Line { - return &Line{ - Author: author, - AuthorName: authorName, - Text: text, - Hash: hash, - Date: date, - } -} - -func newLines(contents []string, commits []*object.Commit) []*Line { - result := make([]*Line, 0, len(contents)) - for i := range contents { - result = append(result, newLine( - commits[i].Author.Email, commits[i].Author.Name, contents[i], - commits[i].Author.When, commits[i].Hash, - )) - } - - return result -} - -// this struct is internally used by the blame function to hold its -// inputs, outputs and state. -type blame struct { - // the path of the file to blame - path string - // the commit of the final revision of the file to blame - fRev *object.Commit - // resolved lines - lineToCommit []*object.Commit - // queue of commits that need resolving - q *priorityQueue -} - -type lineMap struct { - Orig, Cur int - Commit *object.Commit - FromParentNo int -} - -func (b *blame) addBlames(curItems []*queueItem) (bool, error) { - curItem := curItems[0] - - // Simple optimisation to merge paths, there is potential to go a bit further here and check for any duplicates - // not only if they are all the same. - if len(curItems) == 1 { - curItems = nil - } else if curItem.IdenticalToChild { - allSame := true - lenCurItems := len(curItems) - lowestParentNo := curItem.ParentNo - for i := 1; i < lenCurItems; i++ { - if !curItems[i].IdenticalToChild || curItem.Child != curItems[i].Child { - allSame = false - break - } - lowestParentNo = min(lowestParentNo, curItems[i].ParentNo) - } - if allSame { - curItem.Child.numParentsNeedResolving = curItem.Child.numParentsNeedResolving - lenCurItems + 1 - curItems = nil // free the memory - curItem.ParentNo = lowestParentNo - - // Now check if we can remove the parent completely - for curItem.Child.IdenticalToChild && curItem.Child.MergedChildren == nil && curItem.Child.numParentsNeedResolving == 1 { - oldChild := curItem.Child - curItem.Child = oldChild.Child - curItem.ParentNo = oldChild.ParentNo - } - } - } - - // if we have more than 1 item for this commit, create a single needsMap - if len(curItems) > 1 { - curItem.MergedChildren = make([]childToNeedsMap, len(curItems)) - for i, c := range curItems { - curItem.MergedChildren[i] = childToNeedsMap{c.Child, c.NeedsMap, c.IdenticalToChild, c.ParentNo} - } - newNeedsMap := make([]lineMap, 0, len(curItem.NeedsMap)) - newNeedsMap = append(newNeedsMap, curItems[0].NeedsMap...) - - for i := 1; i < len(curItems); i++ { - cur := curItems[i].NeedsMap - n := 0 // position in newNeedsMap - c := 0 // position in current list - for c < len(cur) { - if n == len(newNeedsMap) { - newNeedsMap = append(newNeedsMap, cur[c:]...) - break - } else if newNeedsMap[n].Cur == cur[c].Cur { - n++ - c++ - } else if newNeedsMap[n].Cur < cur[c].Cur { - n++ - } else { - newNeedsMap = append(newNeedsMap, cur[c]) - newPos := len(newNeedsMap) - 1 - for newPos > n { - newNeedsMap[newPos-1], newNeedsMap[newPos] = newNeedsMap[newPos], newNeedsMap[newPos-1] - newPos-- - } - } - } - } - curItem.NeedsMap = newNeedsMap - curItem.IdenticalToChild = false - curItem.Child = nil - curItems = nil // free the memory - } - - parents, err := parentsContainingPath(curItem.path, curItem.Commit) - if err != nil { - return false, err - } - - anyPushed := false - for parnetNo, prev := range parents { - currentHash, err := blobHash(curItem.path, curItem.Commit) - if err != nil { - return false, err - } - prevHash, err := blobHash(prev.Path, prev.Commit) - if err != nil { - return false, err - } - if currentHash == prevHash { - if len(parents) == 1 && curItem.MergedChildren == nil && curItem.IdenticalToChild { - // commit that has 1 parent and 1 child and is the same as both, bypass it completely - b.q.Push(&queueItem{ - Child: curItem.Child, - Commit: prev.Commit, - path: prev.Path, - Contents: curItem.Contents, - NeedsMap: curItem.NeedsMap, // reuse the NeedsMap as we are throwing away this item - IdenticalToChild: true, - ParentNo: curItem.ParentNo, - }) - } else { - b.q.Push(&queueItem{ - Child: curItem, - Commit: prev.Commit, - path: prev.Path, - Contents: curItem.Contents, - NeedsMap: append([]lineMap(nil), curItem.NeedsMap...), // create new slice and copy - IdenticalToChild: true, - ParentNo: parnetNo, - }) - curItem.numParentsNeedResolving++ - } - anyPushed = true - continue - } - - // get the contents of the file - file, err := prev.Commit.File(prev.Path) - if err != nil { - return false, err - } - prevContents, err := file.Contents() - if err != nil { - return false, err - } - - hunks := diff.Do(prevContents, curItem.Contents) - prevl := -1 - curl := -1 - need := 0 - getFromParent := make([]lineMap, 0) - out: - for h := range hunks { - hLines := countLines(hunks[h].Text) - for hl := 0; hl < hLines; hl++ { - switch hunks[h].Type { - case diffmatchpatch.DiffEqual: - prevl++ - curl++ - if curl == curItem.NeedsMap[need].Cur { - // add to needs - getFromParent = append(getFromParent, lineMap{curl, prevl, nil, -1}) - // move to next need - need++ - if need >= len(curItem.NeedsMap) { - break out - } - } - case diffmatchpatch.DiffInsert: - curl++ - if curl == curItem.NeedsMap[need].Cur { - // the line we want is added, it may have been added here (or by another parent), skip it for now - need++ - if need >= len(curItem.NeedsMap) { - break out - } - } - case diffmatchpatch.DiffDelete: - prevl += hLines - continue out - default: - return false, errors.New("invalid state: invalid hunk Type") - } - } - } - - if len(getFromParent) > 0 { - b.q.Push(&queueItem{ - curItem, - nil, - prev.Commit, - prev.Path, - prevContents, - getFromParent, - 0, - false, - parnetNo, - }) - curItem.numParentsNeedResolving++ - anyPushed = true - } - } - - curItem.Contents = "" // no longer need, free the memory - - if !anyPushed { - return finishNeeds(curItem) - } - - return false, nil -} - -func finishNeeds(curItem *queueItem) (bool, error) { - // any needs left in the needsMap must have come from this revision - for i := range curItem.NeedsMap { - if curItem.NeedsMap[i].Commit == nil { - curItem.NeedsMap[i].Commit = curItem.Commit - curItem.NeedsMap[i].FromParentNo = -1 - } - } - - if curItem.Child == nil && curItem.MergedChildren == nil { - return true, nil - } - - if curItem.MergedChildren == nil { - return applyNeeds(curItem.Child, curItem.NeedsMap, curItem.IdenticalToChild, curItem.ParentNo) - } - - for _, ctn := range curItem.MergedChildren { - m := 0 // position in merged needs map - p := 0 // position in parent needs map - for p < len(ctn.NeedsMap) { - if ctn.NeedsMap[p].Cur == curItem.NeedsMap[m].Cur { - ctn.NeedsMap[p].Commit = curItem.NeedsMap[m].Commit - m++ - p++ - } else if ctn.NeedsMap[p].Cur < curItem.NeedsMap[m].Cur { - p++ - } else { - m++ - } - } - finished, err := applyNeeds(ctn.Child, ctn.NeedsMap, ctn.IdenticalToChild, ctn.ParentNo) - if finished || err != nil { - return finished, err - } - } - - return false, nil -} - -func applyNeeds(child *queueItem, needsMap []lineMap, identicalToChild bool, parentNo int) (bool, error) { - if identicalToChild { - for i := range child.NeedsMap { - l := &child.NeedsMap[i] - if l.Cur != needsMap[i].Cur || l.Orig != needsMap[i].Orig { - return false, errors.New("needsMap isn't the same? Why not??") - } - if l.Commit == nil || parentNo < l.FromParentNo { - l.Commit = needsMap[i].Commit - l.FromParentNo = parentNo - } - } - } else { - i := 0 - out: - for j := range child.NeedsMap { - l := &child.NeedsMap[j] - for needsMap[i].Orig < l.Cur { - i++ - if i == len(needsMap) { - break out - } - } - if l.Cur == needsMap[i].Orig { - if l.Commit == nil || parentNo < l.FromParentNo { - l.Commit = needsMap[i].Commit - l.FromParentNo = parentNo - } - } - } - } - child.numParentsNeedResolving-- - if child.numParentsNeedResolving == 0 { - finished, err := finishNeeds(child) - if finished || err != nil { - return finished, err - } - } - - return false, nil -} - -// String prints the results of a Blame using git-blame's style. -func (b BlameResult) String() string { - var buf bytes.Buffer - - // max line number length - mlnl := len(strconv.Itoa(len(b.Lines))) - // max author length - mal := b.maxAuthorLength() - format := fmt.Sprintf("%%s (%%-%ds %%s %%%dd) %%s\n", mal, mlnl) - - for ln := range b.Lines { - _, _ = fmt.Fprintf(&buf, format, b.Lines[ln].Hash.String()[:8], - b.Lines[ln].AuthorName, b.Lines[ln].Date.Format("2006-01-02 15:04:05 -0700"), ln+1, b.Lines[ln].Text) - } - return buf.String() -} - -// utility function to calculate the number of runes needed -// to print the longest author name in the blame of a file. -func (b BlameResult) maxAuthorLength() int { - m := 0 - for ln := range b.Lines { - m = max(m, utf8.RuneCountInString(b.Lines[ln].AuthorName)) - } - return m -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -type childToNeedsMap struct { - Child *queueItem - NeedsMap []lineMap - IdenticalToChild bool - ParentNo int -} - -type queueItem struct { - Child *queueItem - MergedChildren []childToNeedsMap - Commit *object.Commit - path string - Contents string - NeedsMap []lineMap - numParentsNeedResolving int - IdenticalToChild bool - ParentNo int -} - -type priorityQueueImp []*queueItem - -func (pq *priorityQueueImp) Len() int { return len(*pq) } -func (pq *priorityQueueImp) Less(i, j int) bool { - return !(*pq)[i].Commit.Less((*pq)[j].Commit) -} -func (pq *priorityQueueImp) Swap(i, j int) { (*pq)[i], (*pq)[j] = (*pq)[j], (*pq)[i] } -func (pq *priorityQueueImp) Push(x any) { *pq = append(*pq, x.(*queueItem)) } -func (pq *priorityQueueImp) Pop() any { - n := len(*pq) - ret := (*pq)[n-1] - (*pq)[n-1] = nil // ovoid memory leak - *pq = (*pq)[0 : n-1] - - return ret -} -func (pq *priorityQueueImp) Peek() *object.Commit { - if len(*pq) == 0 { - return nil - } - return (*pq)[0].Commit -} - -type priorityQueue priorityQueueImp - -func (pq *priorityQueue) Init() { heap.Init((*priorityQueueImp)(pq)) } -func (pq *priorityQueue) Len() int { return (*priorityQueueImp)(pq).Len() } -func (pq *priorityQueue) Push(c *queueItem) { - heap.Push((*priorityQueueImp)(pq), c) -} -func (pq *priorityQueue) Pop() *queueItem { - return heap.Pop((*priorityQueueImp)(pq)).(*queueItem) -} -func (pq *priorityQueue) Peek() *object.Commit { return (*priorityQueueImp)(pq).Peek() } - -type parentCommit struct { - Commit *object.Commit - Path string -} - -func parentsContainingPath(path string, c *object.Commit) ([]parentCommit, error) { - // TODO: benchmark this method making git.object.Commit.parent public instead of using - // an iterator - var result []parentCommit - iter := c.Parents() - for { - parent, err := iter.Next() - if err == io.EOF { - return result, nil - } - if err != nil { - return nil, err - } - if _, err := parent.File(path); err == nil { - result = append(result, parentCommit{parent, path}) - } else { - // look for renames - patch, err := parent.Patch(c) - if err != nil { - return nil, err - } else if patch != nil { - for _, fp := range patch.FilePatches() { - from, to := fp.Files() - if from != nil && to != nil && to.Path() == path { - result = append(result, parentCommit{parent, from.Path()}) - break - } - } - } - } - } -} - -func blobHash(path string, commit *object.Commit) (plumbing.Hash, error) { - file, err := commit.File(path) - if err != nil { - return plumbing.ZeroHash, err - } - return file.Hash, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/common.go b/vendor/github.com/go-git/go-git/v6/common.go deleted file mode 100644 index 6174339a..00000000 --- a/vendor/github.com/go-git/go-git/v6/common.go +++ /dev/null @@ -1,20 +0,0 @@ -package git - -import "strings" - -// countLines returns the number of lines in a string à la git, this is -// The newline character is assumed to be '\n'. The empty string -// contains 0 lines. If the last line of the string doesn't end with a -// newline, it will still be considered a line. -func countLines(s string) int { - if s == "" { - return 0 - } - - nEOL := strings.Count(s, "\n") - if strings.HasSuffix(s, "\n") { - return nEOL - } - - return nEOL + 1 -} diff --git a/vendor/github.com/go-git/go-git/v6/config/branch.go b/vendor/github.com/go-git/go-git/v6/config/branch.go deleted file mode 100644 index 749eb873..00000000 --- a/vendor/github.com/go-git/go-git/v6/config/branch.go +++ /dev/null @@ -1,123 +0,0 @@ -package config - -import ( - "errors" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" -) - -var ( - errBranchEmptyName = errors.New("branch config: empty name") - errBranchInvalidMerge = errors.New("branch config: invalid merge") - errBranchInvalidRebase = errors.New("branch config: rebase must be one of 'true' or 'interactive'") -) - -// Branch contains information on the -// local branches and which remote to track -type Branch struct { - // Name of branch - Name string - // Remote name of remote to track - Remote string - // Merge is the local refspec for the branch - Merge plumbing.ReferenceName - // Rebase instead of merge when pulling. Valid values are - // "true" and "interactive". "false" is undocumented and - // typically represented by the non-existence of this field - Rebase string - // Description explains what the branch is for. - // Multi-line explanations may be used. - // - // Original git command to edit: - // git branch --edit-description - Description string - - raw *format.Subsection -} - -// Validate validates fields of branch -func (b *Branch) Validate() error { - if b.Name == "" { - return errBranchEmptyName - } - - if b.Merge != "" && !b.Merge.IsBranch() { - return errBranchInvalidMerge - } - - if b.Rebase != "" && - b.Rebase != "true" && - b.Rebase != "interactive" && - b.Rebase != "false" { - return errBranchInvalidRebase - } - - return plumbing.NewBranchReferenceName(b.Name).Validate() -} - -func (b *Branch) marshal() *format.Subsection { - if b.raw == nil { - b.raw = &format.Subsection{} - } - - b.raw.Name = b.Name - - if b.Remote == "" { - b.raw.RemoveOption(remoteSection) - } else { - b.raw.SetOption(remoteSection, b.Remote) - } - - if b.Merge == "" { - b.raw.RemoveOption(mergeKey) - } else { - b.raw.SetOption(mergeKey, string(b.Merge)) - } - - if b.Rebase == "" { - b.raw.RemoveOption(rebaseKey) - } else { - b.raw.SetOption(rebaseKey, b.Rebase) - } - - if b.Description == "" { - b.raw.RemoveOption(descriptionKey) - } else { - desc := quoteDescription(b.Description) - b.raw.SetOption(descriptionKey, desc) - } - - return b.raw -} - -// hack to trigger conditional quoting in the -// plumbing/format/config/Encoder.encodeOptions -// -// Current Encoder implementation uses Go %q format if value contains a backslash character, -// which is not consistent with reference git implementation. -// git just replaces newline characters with \n, while Encoder prints them directly. -// Until value quoting fix, we should escape description value by replacing newline characters with \n. -func quoteDescription(desc string) string { - return strings.ReplaceAll(desc, "\n", `\n`) -} - -func (b *Branch) unmarshal(s *format.Subsection) error { - b.raw = s - - b.Name = b.raw.Name - b.Remote = b.raw.Options.Get(remoteSection) - b.Merge = plumbing.ReferenceName(b.raw.Options.Get(mergeKey)) - b.Rebase = b.raw.Options.Get(rebaseKey) - b.Description = unquoteDescription(b.raw.Options.Get(descriptionKey)) - - return b.Validate() -} - -// hack to enable conditional quoting in the -// plumbing/format/config/Encoder.encodeOptions -// goto quoteDescription for details. -func unquoteDescription(desc string) string { - return strings.ReplaceAll(desc, `\n`, "\n") -} diff --git a/vendor/github.com/go-git/go-git/v6/config/config.go b/vendor/github.com/go-git/go-git/v6/config/config.go deleted file mode 100644 index caaed6c6..00000000 --- a/vendor/github.com/go-git/go-git/v6/config/config.go +++ /dev/null @@ -1,833 +0,0 @@ -// Package config contains the abstraction of multiple config files -package config - -import ( - "bytes" - "errors" - "fmt" - "io" - "os" - "path/filepath" - "reflect" - "sort" - "strconv" - - "github.com/go-git/go-billy/v6/osfs" - "github.com/go-git/go-git/v6/internal/url" - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/plumbing/protocol" -) - -const ( - // DefaultFetchRefSpec is the default refspec used for fetch. - DefaultFetchRefSpec = "+refs/heads/*:refs/remotes/%s/*" - // DefaultPushRefSpec is the default refspec used for push. - DefaultPushRefSpec = "refs/heads/*:refs/heads/*" - // DefaultProtocolVersion is the value assumed if none is defined - // at the config file. This value is used to define when this section - // should be marshalled or not. - // Note that this does not need to align with the default protocol - // version from plumbing/protocol. - DefaultProtocolVersion = protocol.V0 // go-git only supports V0 at the moment -) - -// ConfigStorer generic storage of Config object -type ConfigStorer interface { - Config() (*Config, error) - SetConfig(*Config) error -} - -var ( - ErrInvalid = errors.New("config invalid key in remote or branch") - ErrRemoteConfigNotFound = errors.New("remote config not found") - ErrRemoteConfigEmptyURL = errors.New("remote config: empty URL") - ErrRemoteConfigEmptyName = errors.New("remote config: empty name") -) - -// Scope defines the scope of a config file, such as local, global or system. -type Scope int - -// Available ConfigScope's -const ( - LocalScope Scope = iota - GlobalScope - SystemScope -) - -// Config contains the repository configuration -// https://www.kernel.org/pub/software/scm/git/docs/git-config.html#FILES -type Config struct { - Core struct { - // IsBare if true this repository is assumed to be bare and has no - // working directory associated with it. - IsBare bool - // Worktree is the path to the root of the working tree. - Worktree string - // CommentChar is the character indicating the start of a - // comment for commands like commit and tag - CommentChar string - // RepositoryFormatVersion identifies the repository format and layout version. - RepositoryFormatVersion format.RepositoryFormatVersion - // AutoCRLF if "true", all the CRLF line endings in the worktree will be - // converted to LF when added to the repository, and vice versa on checkout. - // If set to "input", only worktree-to-repository conversion is performed. - AutoCRLF string - } - - User struct { - // Name is the personal name of the author and the committer of a commit. - Name string - // Email is the email of the author and the committer of a commit. - Email string - } - - Author struct { - // Name is the personal name of the author of a commit. - Name string - // Email is the email of the author of a commit. - Email string - } - - Committer struct { - // Name is the personal name of the committer of a commit. - Name string - // Email is the email of the committer of a commit. - Email string - } - - Pack struct { - // Window controls the size of the sliding window for delta - // compression. The default is 10. A value of 0 turns off - // delta compression entirely. - Window uint - } - - Init struct { - // DefaultBranch Allows overriding the default branch name - // e.g. when initializing a new repository or when cloning - // an empty repository. - DefaultBranch string - } - - Extensions struct { - // ObjectFormat specifies the hash algorithm to use. The - // acceptable values are sha1 and sha256. If not specified, - // sha1 is assumed. It is an error to specify this key unless - // core.repositoryFormatVersion is 1. - // - // This setting must not be changed after repository initialization - // (e.g. clone or init). - ObjectFormat format.ObjectFormat - } - - Protocol struct { - // Version sets the preferred version for the Git wire protocol. - // When set, clients will attempt to communicate with a server - // using the specified protocol version. If the server does not - // support it, communication falls back to version 0. If unset, - // the default version will be used. Supported versions: - // - // 0 - the original wire protocol. - // 1 - the original wire protocol with the addition of a - // version string in the initial response from the server. - // 2 - Wire protocol version 2. - Version protocol.Version - } - - // Remotes list of repository remotes, the key of the map is the name - // of the remote, should equal to RemoteConfig.Name. - Remotes map[string]*RemoteConfig - // Submodules list of repository submodules, the key of the map is the name - // of the submodule, should equal to Submodule.Name. - Submodules map[string]*Submodule - // Branches list of branches, the key is the branch name and should - // equal Branch.Name - Branches map[string]*Branch - // URLs list of url rewrite rules, if repo url starts with URL.InsteadOf value, it will be replaced with the - // key instead. - URLs map[string]*URL - // Raw contains the raw information of a config file. The main goal is - // preserve the parsed information from the original format, to avoid - // dropping unsupported fields. - Raw *format.Config -} - -// Merge combines all the src Config objects into one. -// The objects are processed in the order they are passed on, and will -// override any existing values. Empty configs are ignored. -func Merge(src ...*Config) Config { - var final Config - - for _, c := range src { - if c == nil { - continue - } - - merge(&final, c) - } - - return final -} - -func merge(dst, src any) { - tv := reflect.ValueOf(dst).Elem() - sv := reflect.ValueOf(src).Elem() - - for i := 0; i < tv.NumField(); i++ { - df := tv.Field(i) - sf := sv.Field(i) - - if !df.CanSet() || sf.IsZero() { - continue - } - - switch df.Kind() { - case reflect.Struct: - // Handle nested fields which are based off structs. - merge(df.Addr().Interface(), sf.Addr().Interface()) - - case reflect.Ptr: - if sf.IsNil() { - continue - } - if df.IsNil() { - df.Set(reflect.New(df.Type().Elem())) - } - // Same as per reflect.Struct, but for a struct pointer. - if df.Elem().Kind() == reflect.Struct { - merge(df.Interface(), sf.Interface()) - } else { - df.Set(sf) - } - - default: - df.Set(sf) - } - } -} - -// NewConfig returns a new empty Config. -func NewConfig() *Config { - config := &Config{ - Remotes: make(map[string]*RemoteConfig), - Submodules: make(map[string]*Submodule), - Branches: make(map[string]*Branch), - URLs: make(map[string]*URL), - Raw: format.New(), - } - - config.Pack.Window = DefaultPackWindow - config.Protocol.Version = DefaultProtocolVersion - - return config -} - -// ReadConfig reads a config file from a io.Reader. -func ReadConfig(r io.Reader) (*Config, error) { - b, err := io.ReadAll(r) - if err != nil { - return nil, err - } - - cfg := NewConfig() - if err = cfg.Unmarshal(b); err != nil { - return nil, err - } - - return cfg, nil -} - -// LoadConfig loads a config file from a given scope. The returned Config, -// contains exclusively information from the given scope. If it couldn't find a -// config file to the given scope, an empty one is returned. -func LoadConfig(scope Scope) (*Config, error) { - if scope == LocalScope { - return nil, fmt.Errorf("LocalScope should be read from the a ConfigStorer") - } - - files, err := Paths(scope) - if err != nil { - return nil, err - } - - for _, file := range files { - f, err := osfs.Default.Open(file) - if err != nil { - if os.IsNotExist(err) { - continue - } - - return nil, err - } - - defer f.Close() - return ReadConfig(f) - } - - return NewConfig(), nil -} - -// Paths returns the config file location for a given scope. -func Paths(scope Scope) ([]string, error) { - var files []string - switch scope { - case GlobalScope: - xdg := os.Getenv("XDG_CONFIG_HOME") - if xdg != "" { - files = append(files, filepath.Join(xdg, "git/config")) - } - - home, err := os.UserHomeDir() - if err != nil { - return nil, err - } - - files = append(files, - filepath.Join(home, ".gitconfig"), - filepath.Join(home, ".config/git/config"), - ) - case SystemScope: - files = append(files, "/etc/gitconfig") - } - - return files, nil -} - -// Validate validates the fields and sets the default values. -func (c *Config) Validate() error { - for name, r := range c.Remotes { - if r.Name != name { - return ErrInvalid - } - - if err := r.Validate(); err != nil { - return err - } - } - - for name, b := range c.Branches { - if b.Name != name { - return ErrInvalid - } - - if err := b.Validate(); err != nil { - return err - } - } - - return nil -} - -const ( - remoteSection = "remote" - submoduleSection = "submodule" - branchSection = "branch" - coreSection = "core" - packSection = "pack" - userSection = "user" - authorSection = "author" - committerSection = "committer" - initSection = "init" - urlSection = "url" - extensionsSection = "extensions" - protocolSection = "protocol" - fetchKey = "fetch" - urlKey = "url" - pushurlKey = "pushurl" - bareKey = "bare" - worktreeKey = "worktree" - commentCharKey = "commentChar" - windowKey = "window" - mergeKey = "merge" - rebaseKey = "rebase" - nameKey = "name" - emailKey = "email" - descriptionKey = "description" - defaultBranchKey = "defaultBranch" - repositoryFormatVersionKey = "repositoryformatversion" - objectFormat = "objectformat" - mirrorKey = "mirror" - versionKey = "version" - autoCRLFKey = "autocrlf" - - // DefaultPackWindow holds the number of previous objects used to - // generate deltas. The value 10 is the same used by git command. - DefaultPackWindow = uint(10) -) - -// Unmarshal parses a git-config file and stores it. -func (c *Config) Unmarshal(b []byte) error { - r := bytes.NewBuffer(b) - d := format.NewDecoder(r) - - c.Raw = format.New() - if err := d.Decode(c.Raw); err != nil { - return err - } - - c.unmarshalCore() - c.unmarshalUser() - c.unmarshalInit() - if err := c.unmarshalPack(); err != nil { - return err - } - unmarshalSubmodules(c.Raw, c.Submodules) - - if err := c.unmarshalBranches(); err != nil { - return err - } - - if err := c.unmarshalURLs(); err != nil { - return err - } - - if err := c.unmarshalProtocol(); err != nil { - return err - } - - return c.unmarshalRemotes() -} - -func (c *Config) unmarshalCore() { - s := c.Raw.Section(coreSection) - if s.Options.Get(bareKey) == "true" { - c.Core.IsBare = true - } - - c.Core.Worktree = s.Options.Get(worktreeKey) - c.Core.CommentChar = s.Options.Get(commentCharKey) - c.Core.AutoCRLF = s.Options.Get(autoCRLFKey) -} - -func (c *Config) unmarshalUser() { - s := c.Raw.Section(userSection) - c.User.Name = s.Options.Get(nameKey) - c.User.Email = s.Options.Get(emailKey) - - s = c.Raw.Section(authorSection) - c.Author.Name = s.Options.Get(nameKey) - c.Author.Email = s.Options.Get(emailKey) - - s = c.Raw.Section(committerSection) - c.Committer.Name = s.Options.Get(nameKey) - c.Committer.Email = s.Options.Get(emailKey) -} - -func (c *Config) unmarshalPack() error { - s := c.Raw.Section(packSection) - window := s.Options.Get(windowKey) - if window == "" { - c.Pack.Window = DefaultPackWindow - } else { - winUint, err := strconv.ParseUint(window, 10, 32) - if err != nil { - return err - } - c.Pack.Window = uint(winUint) - } - return nil -} - -func (c *Config) unmarshalRemotes() error { - s := c.Raw.Section(remoteSection) - for _, sub := range s.Subsections { - r := &RemoteConfig{} - if err := r.unmarshal(sub); err != nil { - return err - } - - c.Remotes[r.Name] = r - } - - // Check if the main remote section still has options - // after unmarshaling named subsections - this indicates an empty subsection name - if len(s.Options) > 0 { - emptySubsection := &format.Subsection{ - Name: "", - Options: s.Options, - } - - r := &RemoteConfig{} - if err := r.unmarshal(emptySubsection); err != nil { - return err - } - - c.Remotes[r.Name] = r - } - // Apply insteadOf url rules - for _, r := range c.Remotes { - r.applyURLRules(c.URLs) - } - - return nil -} - -func (c *Config) unmarshalURLs() error { - s := c.Raw.Section(urlSection) - for _, sub := range s.Subsections { - r := &URL{} - if err := r.unmarshal(sub); err != nil { - return err - } - - c.URLs[r.Name] = r - } - - return nil -} - -func unmarshalSubmodules(fc *format.Config, submodules map[string]*Submodule) { - s := fc.Section(submoduleSection) - for _, sub := range s.Subsections { - m := &Submodule{} - m.unmarshal(sub) - - if m.Validate() == ErrModuleBadPath { - continue - } - - submodules[m.Name] = m - } -} - -func (c *Config) unmarshalBranches() error { - bs := c.Raw.Section(branchSection) - for _, sub := range bs.Subsections { - b := &Branch{} - - if err := b.unmarshal(sub); err != nil { - return err - } - - c.Branches[b.Name] = b - } - return nil -} - -func (c *Config) unmarshalProtocol() error { - s := c.Raw.Section(protocolSection) - - c.Protocol.Version = DefaultProtocolVersion - - // If empty, don't try to parse and instead fallback - // to default protocol version. - if rv := s.Options.Get(versionKey); rv != "" { - v, err := protocol.Parse(rv) - if err != nil { - return err - } - c.Protocol.Version = v - } - - return nil -} - -func (c *Config) unmarshalInit() { - s := c.Raw.Section(initSection) - c.Init.DefaultBranch = s.Options.Get(defaultBranchKey) -} - -// Marshal returns Config encoded as a git-config file. -func (c *Config) Marshal() ([]byte, error) { - c.marshalCore() - c.marshalExtensions() - c.marshalUser() - c.marshalPack() - c.marshalRemotes() - c.marshalSubmodules() - c.marshalBranches() - c.marshalURLs() - c.marshalProtocol() - c.marshalInit() - - buf := bytes.NewBuffer(nil) - if err := format.NewEncoder(buf).Encode(c.Raw); err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func (c *Config) marshalCore() { - s := c.Raw.Section(coreSection) - s.SetOption(bareKey, fmt.Sprintf("%t", c.Core.IsBare)) - if string(c.Core.RepositoryFormatVersion) != "" { - s.SetOption(repositoryFormatVersionKey, string(c.Core.RepositoryFormatVersion)) - } - - if c.Core.Worktree != "" { - s.SetOption(worktreeKey, c.Core.Worktree) - } - - if c.Core.AutoCRLF != "" { - s.SetOption(autoCRLFKey, c.Core.AutoCRLF) - } -} - -func (c *Config) marshalExtensions() { - // Extensions are only supported on Version 1, therefore - // ignore them otherwise. - if c.Core.RepositoryFormatVersion == format.Version_1 { - s := c.Raw.Section(extensionsSection) - s.SetOption(objectFormat, c.Extensions.ObjectFormat.String()) - } -} - -func (c *Config) marshalUser() { - s := c.Raw.Section(userSection) - if c.User.Name != "" { - s.SetOption(nameKey, c.User.Name) - } - - if c.User.Email != "" { - s.SetOption(emailKey, c.User.Email) - } - - s = c.Raw.Section(authorSection) - if c.Author.Name != "" { - s.SetOption(nameKey, c.Author.Name) - } - - if c.Author.Email != "" { - s.SetOption(emailKey, c.Author.Email) - } - - s = c.Raw.Section(committerSection) - if c.Committer.Name != "" { - s.SetOption(nameKey, c.Committer.Name) - } - - if c.Committer.Email != "" { - s.SetOption(emailKey, c.Committer.Email) - } -} - -func (c *Config) marshalPack() { - s := c.Raw.Section(packSection) - if c.Pack.Window != DefaultPackWindow { - s.SetOption(windowKey, fmt.Sprintf("%d", c.Pack.Window)) - } -} - -func (c *Config) marshalRemotes() { - s := c.Raw.Section(remoteSection) - newSubsections := make(format.Subsections, 0, len(c.Remotes)) - added := make(map[string]bool) - for _, subsection := range s.Subsections { - if remote, ok := c.Remotes[subsection.Name]; ok { - newSubsections = append(newSubsections, remote.marshal()) - added[subsection.Name] = true - } - } - - remoteNames := make([]string, 0, len(c.Remotes)) - for name := range c.Remotes { - remoteNames = append(remoteNames, name) - } - - sort.Strings(remoteNames) - - for _, name := range remoteNames { - if !added[name] { - newSubsections = append(newSubsections, c.Remotes[name].marshal()) - } - } - - s.Subsections = newSubsections -} - -func (c *Config) marshalSubmodules() { - s := c.Raw.Section(submoduleSection) - s.Subsections = make(format.Subsections, len(c.Submodules)) - - var i int - for _, r := range c.Submodules { - section := r.marshal() - // the submodule section at config is a subset of the .gitmodule file - // we should remove the non-valid options for the config file. - section.RemoveOption(pathKey) - s.Subsections[i] = section - i++ - } -} - -func (c *Config) marshalBranches() { - s := c.Raw.Section(branchSection) - newSubsections := make(format.Subsections, 0, len(c.Branches)) - added := make(map[string]bool) - for _, subsection := range s.Subsections { - if branch, ok := c.Branches[subsection.Name]; ok { - newSubsections = append(newSubsections, branch.marshal()) - added[subsection.Name] = true - } - } - - branchNames := make([]string, 0, len(c.Branches)) - for name := range c.Branches { - branchNames = append(branchNames, name) - } - - sort.Strings(branchNames) - - for _, name := range branchNames { - if !added[name] { - newSubsections = append(newSubsections, c.Branches[name].marshal()) - } - } - - s.Subsections = newSubsections -} - -func (c *Config) marshalURLs() { - s := c.Raw.Section(urlSection) - s.Subsections = make(format.Subsections, len(c.URLs)) - - var i int - for _, r := range c.URLs { - section := r.marshal() - // the submodule section at config is a subset of the .gitmodule file - // we should remove the non-valid options for the config file. - s.Subsections[i] = section - i++ - } -} - -func (c *Config) marshalProtocol() { - // Only marshal protocol section if a version was set. - if c.Protocol.Version != DefaultProtocolVersion { - s := c.Raw.Section(protocolSection) - s.SetOption(versionKey, c.Protocol.Version.String()) - } -} - -func (c *Config) marshalInit() { - s := c.Raw.Section(initSection) - if c.Init.DefaultBranch != "" { - s.SetOption(defaultBranchKey, c.Init.DefaultBranch) - } -} - -// RemoteConfig contains the configuration for a given remote repository. -type RemoteConfig struct { - // Name of the remote - Name string - // URLs the URLs of a remote repository. It must be non-empty. Fetch will - // always use the first URL, while push will use all of them. - URLs []string - // Mirror indicates that the repository is a mirror of remote. - Mirror bool - - // insteadOfRulesApplied have urls been modified - insteadOfRulesApplied bool - // originalURLs are the urls before applying insteadOf rules - originalURLs []string - - // Fetch the default set of "refspec" for fetch operation - Fetch []RefSpec - - // raw representation of the subsection, filled by marshal or unmarshal are - // called - raw *format.Subsection -} - -// Validate validates the fields and sets the default values. -func (c *RemoteConfig) Validate() error { - if c.Name == "" { - return ErrRemoteConfigEmptyName - } - - if len(c.URLs) == 0 { - return ErrRemoteConfigEmptyURL - } - - for _, r := range c.Fetch { - if err := r.Validate(); err != nil { - return err - } - } - - if len(c.Fetch) == 0 { - c.Fetch = []RefSpec{RefSpec(fmt.Sprintf(DefaultFetchRefSpec, c.Name))} - } - - return plumbing.NewRemoteHEADReferenceName(c.Name).Validate() -} - -func (c *RemoteConfig) unmarshal(s *format.Subsection) error { - c.raw = s - - fetch := []RefSpec{} - for _, f := range c.raw.Options.GetAll(fetchKey) { - rs := RefSpec(f) - if err := rs.Validate(); err != nil { - return err - } - - fetch = append(fetch, rs) - } - - c.Name = c.raw.Name - c.URLs = append([]string(nil), c.raw.Options.GetAll(urlKey)...) - c.URLs = append(c.URLs, c.raw.Options.GetAll(pushurlKey)...) - c.Fetch = fetch - c.Mirror = c.raw.Options.Get(mirrorKey) == "true" - - return nil -} - -func (c *RemoteConfig) marshal() *format.Subsection { - if c.raw == nil { - c.raw = &format.Subsection{} - } - - c.raw.Name = c.Name - if len(c.URLs) == 0 { - c.raw.RemoveOption(urlKey) - } else { - urls := c.URLs - if c.insteadOfRulesApplied { - urls = c.originalURLs - } - - c.raw.SetOption(urlKey, urls...) - } - - if len(c.Fetch) == 0 { - c.raw.RemoveOption(fetchKey) - } else { - var values []string - for _, rs := range c.Fetch { - values = append(values, rs.String()) - } - - c.raw.SetOption(fetchKey, values...) - } - - if c.Mirror { - c.raw.SetOption(mirrorKey, strconv.FormatBool(c.Mirror)) - } - - return c.raw -} - -func (c *RemoteConfig) IsFirstURLLocal() bool { - return url.IsLocalEndpoint(c.URLs[0]) -} - -func (c *RemoteConfig) applyURLRules(urlRules map[string]*URL) { - // save original urls - originalURLs := make([]string, len(c.URLs)) - copy(originalURLs, c.URLs) - - for i, url := range c.URLs { - if matchingURLRule := findLongestInsteadOfMatch(url, urlRules); matchingURLRule != nil { - c.URLs[i] = matchingURLRule.ApplyInsteadOf(c.URLs[i]) - c.insteadOfRulesApplied = true - } - } - - if c.insteadOfRulesApplied { - c.originalURLs = originalURLs - } -} diff --git a/vendor/github.com/go-git/go-git/v6/config/modules.go b/vendor/github.com/go-git/go-git/v6/config/modules.go deleted file mode 100644 index a5e8b344..00000000 --- a/vendor/github.com/go-git/go-git/v6/config/modules.go +++ /dev/null @@ -1,139 +0,0 @@ -package config - -import ( - "bytes" - "errors" - "regexp" - - format "github.com/go-git/go-git/v6/plumbing/format/config" -) - -var ( - ErrModuleEmptyURL = errors.New("module config: empty URL") - ErrModuleEmptyPath = errors.New("module config: empty path") - ErrModuleBadPath = errors.New("submodule has an invalid path") -) - -var ( - // Matches module paths with dotdot ".." components. - dotdotPath = regexp.MustCompile(`(^|[/\\])\.\.([/\\]|$)`) -) - -// Modules defines the submodules properties, represents a .gitmodules file -// https://www.kernel.org/pub/software/scm/git/docs/gitmodules.html -type Modules struct { - // Submodules is a map of submodules being the key the name of the submodule. - Submodules map[string]*Submodule - - raw *format.Config -} - -// NewModules returns a new empty Modules -func NewModules() *Modules { - return &Modules{ - Submodules: make(map[string]*Submodule), - raw: format.New(), - } -} - -const ( - pathKey = "path" - branchKey = "branch" -) - -// Unmarshal parses a git-config file and stores it. -func (m *Modules) Unmarshal(b []byte) error { - r := bytes.NewBuffer(b) - d := format.NewDecoder(r) - - m.raw = format.New() - if err := d.Decode(m.raw); err != nil { - return err - } - - unmarshalSubmodules(m.raw, m.Submodules) - return nil -} - -// Marshal returns Modules encoded as a git-config file. -func (m *Modules) Marshal() ([]byte, error) { - s := m.raw.Section(submoduleSection) - s.Subsections = make(format.Subsections, len(m.Submodules)) - - var i int - for _, r := range m.Submodules { - s.Subsections[i] = r.marshal() - i++ - } - - buf := bytes.NewBuffer(nil) - if err := format.NewEncoder(buf).Encode(m.raw); err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -// Submodule defines a submodule. -type Submodule struct { - // Name module name - Name string - // Path defines the path, relative to the top-level directory of the Git - // working tree. - Path string - // URL defines a URL from which the submodule repository can be cloned. - URL string - // Branch is a remote branch name for tracking updates in the upstream - // submodule. Optional value. - Branch string - - // raw representation of the subsection, filled by marshal or unmarshal are - // called. - raw *format.Subsection -} - -// Validate validates the fields and sets the default values. -func (m *Submodule) Validate() error { - if m.Path == "" { - return ErrModuleEmptyPath - } - - if m.URL == "" { - return ErrModuleEmptyURL - } - - if dotdotPath.MatchString(m.Path) { - return ErrModuleBadPath - } - - return nil -} - -func (m *Submodule) unmarshal(s *format.Subsection) { - m.raw = s - - m.Name = m.raw.Name - m.Path = m.raw.Option(pathKey) - m.URL = m.raw.Option(urlKey) - m.Branch = m.raw.Option(branchKey) -} - -func (m *Submodule) marshal() *format.Subsection { - if m.raw == nil { - m.raw = &format.Subsection{} - } - - m.raw.Name = m.Name - if m.raw.Name == "" { - m.raw.Name = m.Path - } - - m.raw.SetOption(pathKey, m.Path) - m.raw.SetOption(urlKey, m.URL) - - if m.Branch != "" { - m.raw.SetOption(branchKey, m.Branch) - } - - return m.raw -} diff --git a/vendor/github.com/go-git/go-git/v6/config/refspec.go b/vendor/github.com/go-git/go-git/v6/config/refspec.go deleted file mode 100644 index 6da90bc3..00000000 --- a/vendor/github.com/go-git/go-git/v6/config/refspec.go +++ /dev/null @@ -1,155 +0,0 @@ -package config - -import ( - "errors" - "strings" - - "github.com/go-git/go-git/v6/plumbing" -) - -const ( - refSpecWildcard = "*" - refSpecForce = "+" - refSpecSeparator = ":" -) - -var ( - ErrRefSpecMalformedSeparator = errors.New("malformed refspec, separators are wrong") - ErrRefSpecMalformedWildcard = errors.New("malformed refspec, mismatched number of wildcards") -) - -// RefSpec is a mapping from local branches to remote references. -// The format of the refspec is an optional +, followed by :, where -// is the pattern for references on the remote side and is where -// those references will be written locally. The + tells Git to update the -// reference even if it isn’t a fast-forward. -// eg.: "+refs/heads/*:refs/remotes/origin/*" -// -// https://git-scm.com/book/en/v2/Git-Internals-The-Refspec -type RefSpec string - -// Validate validates the RefSpec -func (s RefSpec) Validate() error { - spec := string(s) - if strings.Count(spec, refSpecSeparator) != 1 { - return ErrRefSpecMalformedSeparator - } - - sep := strings.Index(spec, refSpecSeparator) - if sep == len(spec)-1 { - return ErrRefSpecMalformedSeparator - } - - ws := strings.Count(spec[0:sep], refSpecWildcard) - wd := strings.Count(spec[sep+1:], refSpecWildcard) - if ws == wd && ws < 2 && wd < 2 { - return nil - } - - return ErrRefSpecMalformedWildcard -} - -// IsForceUpdate returns if update is allowed in non fast-forward merges. -func (s RefSpec) IsForceUpdate() bool { - return s[0] == refSpecForce[0] -} - -// IsDelete returns true if the refspec indicates a delete (empty src). -func (s RefSpec) IsDelete() bool { - return s[0] == refSpecSeparator[0] -} - -// IsExactSHA1 returns true if the source is a SHA1 hash. -func (s RefSpec) IsExactSHA1() bool { - return plumbing.IsHash(s.Src()) -} - -// Src returns the src side. -func (s RefSpec) Src() string { - spec := string(s) - - var start int - if s.IsForceUpdate() { - start = 1 - } else { - start = 0 - } - - end := strings.Index(spec, refSpecSeparator) - return spec[start:end] -} - -// Match match the given plumbing.ReferenceName against the source. -func (s RefSpec) Match(n plumbing.ReferenceName) bool { - if !s.IsWildcard() { - return s.matchExact(n) - } - - return s.matchGlob(n) -} - -// IsWildcard returns true if the RefSpec contains a wildcard. -func (s RefSpec) IsWildcard() bool { - return strings.Contains(string(s), refSpecWildcard) -} - -func (s RefSpec) matchExact(n plumbing.ReferenceName) bool { - return s.Src() == n.String() -} - -func (s RefSpec) matchGlob(n plumbing.ReferenceName) bool { - src := s.Src() - name := n.String() - wildcard := strings.Index(src, refSpecWildcard) - - var prefix, suffix string - prefix = src[0:wildcard] - if len(src) > wildcard+1 { - suffix = src[wildcard+1:] - } - - return len(name) >= len(prefix)+len(suffix) && - strings.HasPrefix(name, prefix) && - strings.HasSuffix(name, suffix) -} - -// Dst returns the destination for the given remote reference. -func (s RefSpec) Dst(n plumbing.ReferenceName) plumbing.ReferenceName { - spec := string(s) - start := strings.Index(spec, refSpecSeparator) + 1 - dst := spec[start:] - src := s.Src() - - if !s.IsWildcard() { - return plumbing.ReferenceName(dst) - } - - name := n.String() - ws := strings.Index(src, refSpecWildcard) - wd := strings.Index(dst, refSpecWildcard) - match := name[ws : len(name)-(len(src)-(ws+1))] - - return plumbing.ReferenceName(dst[0:wd] + match + dst[wd+1:]) -} - -func (s RefSpec) Reverse() RefSpec { - spec := string(s) - separator := strings.Index(spec, refSpecSeparator) - - return RefSpec(spec[separator+1:] + refSpecSeparator + spec[:separator]) -} - -func (s RefSpec) String() string { - return string(s) -} - -// MatchAny returns true if any of the RefSpec match with the given ReferenceName. -func MatchAny(l []RefSpec, n plumbing.ReferenceName) bool { - for _, r := range l { - if r.Match(n) { - return true - } - } - - return false -} diff --git a/vendor/github.com/go-git/go-git/v6/config/url.go b/vendor/github.com/go-git/go-git/v6/config/url.go deleted file mode 100644 index 5ec2969b..00000000 --- a/vendor/github.com/go-git/go-git/v6/config/url.go +++ /dev/null @@ -1,90 +0,0 @@ -package config - -import ( - "errors" - "strings" - - format "github.com/go-git/go-git/v6/plumbing/format/config" -) - -var ( - errURLEmptyInsteadOf = errors.New("url config: empty insteadOf") -) - -// Url defines Url rewrite rules -type URL struct { - // Name new base url - Name string - // Any URL that starts with this value will be rewritten to start, instead, with . - // When more than one insteadOf strings match a given URL, the longest match is used. - InsteadOfs []string - - // raw representation of the subsection, filled by marshal or unmarshal are - // called. - raw *format.Subsection -} - -// Validate validates fields of branch -func (b *URL) Validate() error { - if len(b.InsteadOfs) == 0 { - return errURLEmptyInsteadOf - } - - return nil -} - -const ( - insteadOfKey = "insteadOf" -) - -func (u *URL) unmarshal(s *format.Subsection) error { - u.raw = s - - u.Name = s.Name - u.InsteadOfs = u.raw.OptionAll(insteadOfKey) - return nil -} - -func (u *URL) marshal() *format.Subsection { - if u.raw == nil { - u.raw = &format.Subsection{} - } - - u.raw.Name = u.Name - u.raw.SetOption(insteadOfKey, u.InsteadOfs...) - - return u.raw -} - -func findLongestInsteadOfMatch(remoteURL string, urls map[string]*URL) *URL { - var longestMatch *URL - var longestMatchLength int - - for _, u := range urls { - for _, currentInsteadOf := range u.InsteadOfs { - if !strings.HasPrefix(remoteURL, currentInsteadOf) { - continue - } - - lengthCurrentInsteadOf := len(currentInsteadOf) - - // according to spec if there is more than one match, take the longest - if longestMatch == nil || longestMatchLength < lengthCurrentInsteadOf { - longestMatch = u - longestMatchLength = lengthCurrentInsteadOf - } - } - } - - return longestMatch -} - -func (u *URL) ApplyInsteadOf(url string) string { - for _, j := range u.InsteadOfs { - if strings.HasPrefix(url, j) { - return u.Name + url[len(j):] - } - } - - return url -} diff --git a/vendor/github.com/go-git/go-git/v6/crypto.go b/vendor/github.com/go-git/go-git/v6/crypto.go deleted file mode 100644 index 780fd6cc..00000000 --- a/vendor/github.com/go-git/go-git/v6/crypto.go +++ /dev/null @@ -1,7 +0,0 @@ -package git - -import ( - _ "crypto/sha256" // Register Go's SHA256 implementation. - - _ "github.com/pjbgf/sha1cd" // Register sha1cd implementation. -) diff --git a/vendor/github.com/go-git/go-git/v6/doc.go b/vendor/github.com/go-git/go-git/v6/doc.go deleted file mode 100644 index 3d817fe9..00000000 --- a/vendor/github.com/go-git/go-git/v6/doc.go +++ /dev/null @@ -1,10 +0,0 @@ -// A highly extensible git implementation in pure Go. -// -// go-git aims to reach the completeness of libgit2 or jgit, nowadays covers the -// majority of the plumbing read operations and some of the main write -// operations, but lacks the main porcelain operations such as merges. -// -// It is highly extensible, we have been following the open/close principle in -// its design to facilitate extensions, mainly focusing the efforts on the -// persistence of the objects. -package git diff --git a/vendor/github.com/go-git/go-git/v6/internal/path_util/path_util.go b/vendor/github.com/go-git/go-git/v6/internal/path_util/path_util.go deleted file mode 100644 index 48e4a3d0..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/path_util/path_util.go +++ /dev/null @@ -1,29 +0,0 @@ -package path_util - -import ( - "os" - "os/user" - "strings" -) - -func ReplaceTildeWithHome(path string) (string, error) { - if strings.HasPrefix(path, "~") { - firstSlash := strings.Index(path, "/") - if firstSlash == 1 { - home, err := os.UserHomeDir() - if err != nil { - return path, err - } - return strings.Replace(path, "~", home, 1), nil - } else if firstSlash > 1 { - username := path[1:firstSlash] - userAccount, err := user.Lookup(username) - if err != nil { - return path, err - } - return strings.Replace(path, path[:firstSlash], userAccount.HomeDir, 1), nil - } - } - - return path, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/internal/reference/refs.go b/vendor/github.com/go-git/go-git/v6/internal/reference/refs.go deleted file mode 100644 index 501d9012..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/reference/refs.go +++ /dev/null @@ -1,33 +0,0 @@ -package reference - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/storage" -) - -// References returns all references from the storage. -func References(st storage.Storer) ([]*plumbing.Reference, error) { - var localRefs []*plumbing.Reference - - iter, err := st.IterReferences() - if err != nil { - return nil, err - } - - for { - ref, err := iter.Next() - if err == io.EOF { - break - } - - if err != nil { - return nil, err - } - - localRefs = append(localRefs, ref) - } - - return localRefs, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/internal/reference/sort.go b/vendor/github.com/go-git/go-git/v6/internal/reference/sort.go deleted file mode 100644 index 39170c15..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/reference/sort.go +++ /dev/null @@ -1,14 +0,0 @@ -package reference - -import ( - "sort" - - "github.com/go-git/go-git/v6/plumbing" -) - -// Sort sorts the references by name to ensure a consistent order. -func Sort(refs []*plumbing.Reference) { - sort.Slice(refs, func(i, j int) bool { - return refs[i].Name() < refs[j].Name() - }) -} diff --git a/vendor/github.com/go-git/go-git/v6/internal/repository/refs.go b/vendor/github.com/go-git/go-git/v6/internal/repository/refs.go deleted file mode 100644 index f5b3c7fd..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/repository/refs.go +++ /dev/null @@ -1,103 +0,0 @@ -package repository - -import ( - "fmt" - "io" - - "github.com/go-git/go-git/v6/internal/reference" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" -) - -func ExpandRef(s storer.ReferenceStorer, ref plumbing.ReferenceName) (*plumbing.Reference, error) { - // For improving troubleshooting, this preserves the error for the provided `ref`, - // and returns the error for that specific ref in case all parse rules fails. - var ret error - for _, rule := range plumbing.RefRevParseRules { - resolvedRef, err := storer.ResolveReference(s, plumbing.ReferenceName(fmt.Sprintf(rule, ref))) - - if err == nil { - return resolvedRef, nil - } else if ret == nil { - ret = err - } - } - - return nil, ret -} - -// WriteInfoRefs writes the info/refs file to the given writer. -// It generates a list of available refs for the repository. -// Used by git http transport (dumb), for more information refer to: -// https://git-scm.com/book/id/v2/Git-Internals-Transfer-Protocols#_the_dumb_protocol -func WriteInfoRefs(w io.Writer, s storage.Storer) error { - refsIter, err := s.IterReferences() - if err != nil { - return err - } - - var refs []*plumbing.Reference - if err := refsIter.ForEach(func(ref *plumbing.Reference) error { - refs = append(refs, ref) - return nil - }); err != nil { - return err - } - - reference.Sort(refs) - for _, ref := range refs { - name := ref.Name() - hash := ref.Hash() - switch ref.Type() { - case plumbing.SymbolicReference: - if name == plumbing.HEAD { - continue - } - ref, err := s.Reference(ref.Target()) - if err != nil { - return err - } - - hash = ref.Hash() - fallthrough - case plumbing.HashReference: - if _, err :=fmt.Fprintf(w, "%s\t%s\n", hash, name); err != nil { - return fmt.Errorf("writing info reference: %w", err) - } - if name.IsTag() { - tag, err := object.GetTag(s, hash) - if err == nil { - if _, err := fmt.Fprintf(w, "%s\t%s^{}\n", tag.Target, name); err != nil { - return fmt.Errorf("writing info tag reference: %w", err) - } - } - } - } - } - - return nil -} - -// WriteObjectsInfoPacks writes the objects/info/packs file to the given writer. -// It generates a list of available packs for the repository. -// Used by git http transport (dumb), for more information refer to: -// https://git-scm.com/book/id/v2/Git-Internals-Transfer-Protocols#_the_dumb_protocol -func WriteObjectsInfoPacks(w io.Writer, s storer.PackedObjectStorer) error { - packs, err := s.ObjectPacks() - if err != nil { - return err - } - - for _, p := range packs { - if _, err := fmt.Fprintf(w, "P pack-%s.pack\n", p); err != nil { - return fmt.Errorf("writing pack line reference: %w", err) - } - } - - if _, err := fmt.Fprintln(w); err != nil { - return fmt.Errorf("writing pack line final newline: %w", err) - } - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/internal/revision/parser.go b/vendor/github.com/go-git/go-git/v6/internal/revision/parser.go deleted file mode 100644 index 8a2a7190..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/revision/parser.go +++ /dev/null @@ -1,626 +0,0 @@ -// Package revision extracts git revision from string -// More information about revision : https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html -package revision - -import ( - "bytes" - "fmt" - "io" - "regexp" - "strconv" - "time" -) - -// ErrInvalidRevision is emitted if string doesn't match valid revision -type ErrInvalidRevision struct { - s string -} - -func (e *ErrInvalidRevision) Error() string { - return "Revision invalid : " + e.s -} - -// Revisioner represents a revision component. -// A revision is made of multiple revision components -// obtained after parsing a revision string, -// for instance revision "master~" will be converted in -// two revision components Ref and TildePath -type Revisioner interface { -} - -// Ref represents a reference name : HEAD, master, -type Ref string - -// TildePath represents ~, ~{n} -type TildePath struct { - Depth int -} - -// CaretPath represents ^, ^{n} -type CaretPath struct { - Depth int -} - -// CaretReg represents ^{/foo bar} -type CaretReg struct { - Regexp *regexp.Regexp - Negate bool -} - -// CaretType represents ^{commit} -type CaretType struct { - ObjectType string -} - -// AtReflog represents @{n} -type AtReflog struct { - Depth int -} - -// AtCheckout represents @{-n} -type AtCheckout struct { - Depth int -} - -// AtUpstream represents @{upstream}, @{u} -type AtUpstream struct { - BranchName string -} - -// AtPush represents @{push} -type AtPush struct { - BranchName string -} - -// AtDate represents @{"2006-01-02T15:04:05Z"} -type AtDate struct { - Date time.Time -} - -// ColonReg represents :/foo bar -type ColonReg struct { - Regexp *regexp.Regexp - Negate bool -} - -// ColonPath represents :./ : -type ColonPath struct { - Path string -} - -// ColonStagePath represents ::/ -type ColonStagePath struct { - Path string - Stage int -} - -// Parser represents a parser -// use to tokenize and transform to revisioner chunks -// a given string -type Parser struct { - s *scanner - currentParsedChar struct { - tok token - lit string - } - unreadLastChar bool -} - -// NewParserFromString returns a new instance of parser from a string. -func NewParserFromString(s string) *Parser { - return NewParser(bytes.NewBufferString(s)) -} - -// NewParser returns a new instance of parser. -func NewParser(r io.Reader) *Parser { - return &Parser{s: newScanner(r)} -} - -// scan returns the next token from the underlying scanner -// or the last scanned token if an unscan was requested -func (p *Parser) scan() (token, string, error) { - if p.unreadLastChar { - p.unreadLastChar = false - return p.currentParsedChar.tok, p.currentParsedChar.lit, nil - } - - tok, lit, err := p.s.scan() - - p.currentParsedChar.tok, p.currentParsedChar.lit = tok, lit - - return tok, lit, err -} - -// unscan pushes the previously read token back onto the buffer. -func (p *Parser) unscan() { p.unreadLastChar = true } - -// Parse explode a revision string into revisioner chunks -func (p *Parser) Parse() ([]Revisioner, error) { - var rev Revisioner - var revs []Revisioner - var tok token - var err error - - for { - tok, _, err = p.scan() - - if err != nil { - return nil, err - } - - switch tok { - case at: - rev, err = p.parseAt() - case tilde: - rev, err = p.parseTilde() - case caret: - rev, err = p.parseCaret() - case colon: - rev, err = p.parseColon() - case eof: - err = p.validateFullRevision(&revs) - - if err != nil { - return []Revisioner{}, err - } - - return revs, nil - default: - p.unscan() - rev, err = p.parseRef() - } - - if err != nil { - return []Revisioner{}, err - } - - revs = append(revs, rev) - } -} - -// validateFullRevision ensures all revisioner chunks make a valid revision -func (p *Parser) validateFullRevision(chunks *[]Revisioner) error { - var hasReference bool - - for i, chunk := range *chunks { - switch chunk.(type) { - case Ref: - if i == 0 { - hasReference = true - } else { - return &ErrInvalidRevision{`reference must be defined once at the beginning`} - } - case AtDate: - if len(*chunks) == 1 || hasReference && len(*chunks) == 2 { - return nil - } - - return &ErrInvalidRevision{`"@" statement is not valid, could be : @{}, @{}`} - case AtReflog: - if len(*chunks) == 1 || hasReference && len(*chunks) == 2 { - return nil - } - - return &ErrInvalidRevision{`"@" statement is not valid, could be : @{}, @{}`} - case AtCheckout: - if len(*chunks) == 1 { - return nil - } - - return &ErrInvalidRevision{`"@" statement is not valid, could be : @{-}`} - case AtUpstream: - if len(*chunks) == 1 || hasReference && len(*chunks) == 2 { - return nil - } - - return &ErrInvalidRevision{`"@" statement is not valid, could be : @{upstream}, @{upstream}, @{u}, @{u}`} - case AtPush: - if len(*chunks) == 1 || hasReference && len(*chunks) == 2 { - return nil - } - - return &ErrInvalidRevision{`"@" statement is not valid, could be : @{push}, @{push}`} - case TildePath, CaretPath, CaretReg: - if !hasReference { - return &ErrInvalidRevision{`"~" or "^" statement must have a reference defined at the beginning`} - } - case ColonReg: - if len(*chunks) == 1 { - return nil - } - - return &ErrInvalidRevision{`":" statement is not valid, could be : :/`} - case ColonPath: - if i == len(*chunks)-1 && hasReference || len(*chunks) == 1 { - return nil - } - - return &ErrInvalidRevision{`":" statement is not valid, could be : :`} - case ColonStagePath: - if len(*chunks) == 1 { - return nil - } - - return &ErrInvalidRevision{`":" statement is not valid, could be : ::`} - } - } - - return nil -} - -// parseAt extract @ statements -func (p *Parser) parseAt() (Revisioner, error) { - var tok, nextTok token - var lit, nextLit string - var err error - - tok, _, err = p.scan() - - if err != nil { - return nil, err - } - - if tok != obrace { - p.unscan() - - return Ref("HEAD"), nil - } - - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - nextTok, nextLit, err = p.scan() - - if err != nil { - return nil, err - } - - switch { - case tok == word && (lit == "u" || lit == "upstream") && nextTok == cbrace: - return AtUpstream{}, nil - case tok == word && lit == "push" && nextTok == cbrace: - return AtPush{}, nil - case tok == number && nextTok == cbrace: - n, _ := strconv.Atoi(lit) - - return AtReflog{n}, nil - case tok == minus && nextTok == number: - n, _ := strconv.Atoi(nextLit) - - t, _, err := p.scan() - - if err != nil { - return nil, err - } - - if t != cbrace { - return nil, &ErrInvalidRevision{s: `missing "}" in @{-n} structure`} - } - - return AtCheckout{n}, nil - default: - p.unscan() - - date := lit - - for { - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - switch { - case tok == cbrace: - t, err := time.Parse("2006-01-02T15:04:05Z", date) - - if err != nil { - return nil, &ErrInvalidRevision{fmt.Sprintf(`wrong date "%s" must fit ISO-8601 format : 2006-01-02T15:04:05Z`, date)} - } - - return AtDate{t}, nil - case tok == eof: - return nil, &ErrInvalidRevision{s: `missing "}" in @{} structure`} - default: - date += lit - } - } - } -} - -// parseTilde extract ~ statements -func (p *Parser) parseTilde() (Revisioner, error) { - var tok token - var lit string - var err error - - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - switch { - case tok == number: - n, _ := strconv.Atoi(lit) - - return TildePath{n}, nil - default: - p.unscan() - return TildePath{1}, nil - } -} - -// parseCaret extract ^ statements -func (p *Parser) parseCaret() (Revisioner, error) { - var tok token - var lit string - var err error - - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - switch { - case tok == obrace: - r, err := p.parseCaretBraces() - - if err != nil { - return nil, err - } - - return r, nil - case tok == number: - n, _ := strconv.Atoi(lit) - - if n > 2 { - return nil, &ErrInvalidRevision{fmt.Sprintf(`"%s" found must be 0, 1 or 2 after "^"`, lit)} - } - - return CaretPath{n}, nil - default: - p.unscan() - return CaretPath{1}, nil - } -} - -// parseCaretBraces extract ^{} statements -func (p *Parser) parseCaretBraces() (Revisioner, error) { - var tok, nextTok token - var lit, _ string - start := true - var re string - var negate bool - var err error - - for { - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - nextTok, _, err = p.scan() - - if err != nil { - return nil, err - } - - switch { - case tok == word && nextTok == cbrace && (lit == "commit" || lit == "tree" || lit == "blob" || lit == "tag" || lit == "object"): - return CaretType{lit}, nil - case re == "" && tok == cbrace: - return CaretType{"tag"}, nil - case re == "" && tok == emark && nextTok == emark: - re += lit - case re == "" && tok == emark && nextTok == minus: - negate = true - case re == "" && tok == emark: - return nil, &ErrInvalidRevision{s: `revision suffix brace component sequences starting with "/!" others than those defined are reserved`} - case re == "" && tok == slash: - p.unscan() - case tok != slash && start: - return nil, &ErrInvalidRevision{fmt.Sprintf(`"%s" is not a valid revision suffix brace component`, lit)} - case tok == eof: - return nil, &ErrInvalidRevision{s: `missing "}" in ^{} structure`} - case tok != cbrace: - p.unscan() - re += lit - case tok == cbrace: - p.unscan() - - reg, err := regexp.Compile(re) - - if err != nil { - return CaretReg{}, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component, %s`, err.Error())} - } - - return CaretReg{reg, negate}, nil - } - - start = false - } -} - -// parseColon extract : statements -func (p *Parser) parseColon() (Revisioner, error) { - var tok token - var err error - - tok, _, err = p.scan() - - if err != nil { - return nil, err - } - - switch tok { - case slash: - return p.parseColonSlash() - default: - p.unscan() - return p.parseColonDefault() - } -} - -// parseColonSlash extract :/ statements -func (p *Parser) parseColonSlash() (Revisioner, error) { - var tok, nextTok token - var lit string - var re string - var negate bool - var err error - - for { - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - nextTok, _, err = p.scan() - - if err != nil { - return nil, err - } - - switch { - case tok == emark && nextTok == emark: - re += lit - case re == "" && tok == emark && nextTok == minus: - negate = true - case re == "" && tok == emark: - return nil, &ErrInvalidRevision{s: `revision suffix brace component sequences starting with "/!" others than those defined are reserved`} - case tok == eof: - p.unscan() - reg, err := regexp.Compile(re) - - if err != nil { - return ColonReg{}, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component, %s`, err.Error())} - } - - return ColonReg{reg, negate}, nil - default: - p.unscan() - re += lit - } - } -} - -// parseColonDefault extract : statements -func (p *Parser) parseColonDefault() (Revisioner, error) { - var tok token - var lit string - var path string - var stage int - var err error - var n = -1 - - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - nextTok, _, err := p.scan() - - if err != nil { - return nil, err - } - - if tok == number && nextTok == colon { - n, _ = strconv.Atoi(lit) - } - - switch n { - case 0, 1, 2, 3: - stage = n - default: - path += lit - p.unscan() - } - - for { - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - switch { - case tok == eof && n == -1: - return ColonPath{path}, nil - case tok == eof: - return ColonStagePath{path, stage}, nil - default: - path += lit - } - } -} - -// parseRef extract reference name -func (p *Parser) parseRef() (Revisioner, error) { - var tok, prevTok token - var lit, buf string - var endOfRef bool - var err error - - for { - tok, lit, err = p.scan() - - if err != nil { - return nil, err - } - - switch tok { - case eof, at, colon, tilde, caret: - endOfRef = true - } - - err := p.checkRefFormat(tok, lit, prevTok, buf, endOfRef) - - if err != nil { - return "", err - } - - if endOfRef { - p.unscan() - return Ref(buf), nil - } - - buf += lit - prevTok = tok - } -} - -// checkRefFormat ensure reference name follow rules defined here : -// https://git-scm.com/docs/git-check-ref-format -func (p *Parser) checkRefFormat(token token, literal string, previousToken token, buffer string, endOfRef bool) error { - switch token { - case aslash, space, control, qmark, asterisk, obracket: - return &ErrInvalidRevision{fmt.Sprintf(`must not contains "%s"`, literal)} - } - - switch { - case (token == dot || token == slash) && buffer == "": - return &ErrInvalidRevision{fmt.Sprintf(`must not start with "%s"`, literal)} - case previousToken == slash && endOfRef: - return &ErrInvalidRevision{`must not end with "/"`} - case previousToken == dot && endOfRef: - return &ErrInvalidRevision{`must not end with "."`} - case token == dot && previousToken == slash: - return &ErrInvalidRevision{`must not contains "/."`} - case previousToken == dot && token == dot: - return &ErrInvalidRevision{`must not contains ".."`} - case previousToken == slash && token == slash: - return &ErrInvalidRevision{`must not contains consecutively "/"`} - case (token == slash || endOfRef) && len(buffer) > 4 && buffer[len(buffer)-5:] == ".lock": - return &ErrInvalidRevision{"cannot end with .lock"} - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/internal/revision/scanner.go b/vendor/github.com/go-git/go-git/v6/internal/revision/scanner.go deleted file mode 100644 index 2444f33e..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/revision/scanner.go +++ /dev/null @@ -1,122 +0,0 @@ -package revision - -import ( - "bufio" - "io" - "unicode" -) - -// runeCategoryValidator takes a rune as input and -// validates it belongs to a rune category -type runeCategoryValidator func(r rune) bool - -// tokenizeExpression aggregates a series of runes matching check predicate into a single -// string and provides given tokenType as token type -func tokenizeExpression(ch rune, tokenType token, check runeCategoryValidator, r *bufio.Reader) (token, string, error) { - var data []rune - data = append(data, ch) - - for { - c, _, err := r.ReadRune() - - if c == zeroRune { - break - } - - if err != nil { - return tokenError, "", err - } - - if check(c) { - data = append(data, c) - } else { - err := r.UnreadRune() - - if err != nil { - return tokenError, "", err - } - - return tokenType, string(data), nil - } - } - - return tokenType, string(data), nil -} - -// maxRevisionLength holds the maximum length that will be parsed for a -// revision. Git itself doesn't enforce a max length, but rather leans on -// the OS to enforce it via its ARG_MAX. -const maxRevisionLength = 128 * 1024 // 128kb - -var zeroRune = rune(0) - -// scanner represents a lexical scanner. -type scanner struct { - r *bufio.Reader -} - -// newScanner returns a new instance of scanner. -func newScanner(r io.Reader) *scanner { - return &scanner{r: bufio.NewReader(io.LimitReader(r, maxRevisionLength))} -} - -// Scan extracts tokens and their strings counterpart -// from the reader -func (s *scanner) scan() (token, string, error) { - ch, _, err := s.r.ReadRune() - - if err != nil && err != io.EOF { - return tokenError, "", err - } - - switch ch { - case zeroRune: - return eof, "", nil - case ':': - return colon, string(ch), nil - case '~': - return tilde, string(ch), nil - case '^': - return caret, string(ch), nil - case '.': - return dot, string(ch), nil - case '/': - return slash, string(ch), nil - case '{': - return obrace, string(ch), nil - case '}': - return cbrace, string(ch), nil - case '-': - return minus, string(ch), nil - case '@': - return at, string(ch), nil - case '\\': - return aslash, string(ch), nil - case '?': - return qmark, string(ch), nil - case '*': - return asterisk, string(ch), nil - case '[': - return obracket, string(ch), nil - case '!': - return emark, string(ch), nil - } - - if unicode.IsSpace(ch) { - return space, string(ch), nil - } - - if unicode.IsControl(ch) { - return control, string(ch), nil - } - - if unicode.IsLetter(ch) { - return tokenizeExpression(ch, word, unicode.IsLetter, s.r) - } - - if unicode.IsNumber(ch) { - return tokenizeExpression(ch, number, unicode.IsNumber, s.r) - } - - return tokenError, string(ch), nil -} diff --git a/vendor/github.com/go-git/go-git/v6/internal/revision/token.go b/vendor/github.com/go-git/go-git/v6/internal/revision/token.go deleted file mode 100644 index abc40488..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/revision/token.go +++ /dev/null @@ -1,28 +0,0 @@ -package revision - -// token represents a entity extracted from string parsing -type token int - -const ( - eof token = iota - - aslash - asterisk - at - caret - cbrace - colon - control - dot - emark - minus - number - obrace - obracket - qmark - slash - space - tilde - tokenError - word -) diff --git a/vendor/github.com/go-git/go-git/v6/internal/url/url.go b/vendor/github.com/go-git/go-git/v6/internal/url/url.go deleted file mode 100644 index 26624486..00000000 --- a/vendor/github.com/go-git/go-git/v6/internal/url/url.go +++ /dev/null @@ -1,39 +0,0 @@ -package url - -import ( - "regexp" -) - -var ( - isSchemeRegExp = regexp.MustCompile(`^[^:]+://`) - - // Ref: https://github.com/git/git/blob/master/Documentation/urls.txt#L37 - scpLikeUrlRegExp = regexp.MustCompile(`^(?:(?P[^@]+)@)?(?P[^:\s]+):(?:(?P[0-9]{1,5}):)?(?P[^\\].*)$`) -) - -// MatchesScheme returns true if the given string matches a URL-like -// format scheme. -func MatchesScheme(url string) bool { - return isSchemeRegExp.MatchString(url) -} - -// MatchesScpLike returns true if the given string matches an SCP-like -// format scheme. -func MatchesScpLike(url string) bool { - return scpLikeUrlRegExp.MatchString(url) -} - -// FindScpLikeComponents returns the user, host, port and path of the -// given SCP-like URL. -func FindScpLikeComponents(url string) (user, host, port, path string) { - m := scpLikeUrlRegExp.FindStringSubmatch(url) - return m[1], m[2], m[3], m[4] -} - -// IsLocalEndpoint returns true if the given URL string specifies a -// local file endpoint. For example, on a Linux machine, -// `/home/user/src/go-git` would match as a local endpoint, but -// `https://github.com/src-d/go-git` would not. -func IsLocalEndpoint(url string) bool { - return !MatchesScheme(url) && !MatchesScpLike(url) -} diff --git a/vendor/github.com/go-git/go-git/v6/object_walker.go b/vendor/github.com/go-git/go-git/v6/object_walker.go deleted file mode 100644 index ed499d48..00000000 --- a/vendor/github.com/go-git/go-git/v6/object_walker.go +++ /dev/null @@ -1,104 +0,0 @@ -package git - -import ( - "fmt" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/storage" -) - -type objectWalker struct { - Storer storage.Storer - // seen is the set of objects seen in the repo. - // seen map can become huge if walking over large - // repos. Thus using struct{} as the value type. - seen map[plumbing.Hash]struct{} -} - -func newObjectWalker(s storage.Storer) *objectWalker { - return &objectWalker{s, map[plumbing.Hash]struct{}{}} -} - -// walkAllRefs walks all (hash) references from the repo. -func (p *objectWalker) walkAllRefs() error { - // Walk over all the references in the repo. - it, err := p.Storer.IterReferences() - if err != nil { - return err - } - defer it.Close() - err = it.ForEach(func(ref *plumbing.Reference) error { - // Exit this iteration early for non-hash references. - if ref.Type() != plumbing.HashReference { - return nil - } - return p.walkObjectTree(ref.Hash()) - }) - return err -} - -func (p *objectWalker) isSeen(hash plumbing.Hash) bool { - _, seen := p.seen[hash] - return seen -} - -func (p *objectWalker) add(hash plumbing.Hash) { - p.seen[hash] = struct{}{} -} - -// walkObjectTree walks over all objects and remembers references -// to them in the objectWalker. This is used instead of the revlist -// walks because memory usage is tight with huge repos. -func (p *objectWalker) walkObjectTree(hash plumbing.Hash) error { - // Check if we have already seen, and mark this object - if p.isSeen(hash) { - return nil - } - p.add(hash) - // Fetch the object. - obj, err := object.GetObject(p.Storer, hash) - if err != nil { - return fmt.Errorf("getting object %s failed: %v", hash, err) - } - // Walk all children depending on object type. - switch obj := obj.(type) { - case *object.Commit: - err = p.walkObjectTree(obj.TreeHash) - if err != nil { - return err - } - for _, h := range obj.ParentHashes { - err = p.walkObjectTree(h) - if err != nil { - return err - } - } - case *object.Tree: - for i := range obj.Entries { - // Shortcut for blob objects: - // 'or' the lower bits of a mode and check that it - // it matches a filemode.Executable. The type information - // is in the higher bits, but this is the cleanest way - // to handle plain files with different modes. - // Other non-tree objects are somewhat rare, so they - // are not special-cased. - if obj.Entries[i].Mode|0755 == filemode.Executable { - p.add(obj.Entries[i].Hash) - continue - } - // Normal walk for sub-trees (and symlinks etc). - err = p.walkObjectTree(obj.Entries[i].Hash) - if err != nil { - return err - } - } - case *object.Tag: - return p.walkObjectTree(obj.Target) - default: - // Error out on unhandled object types. - return fmt.Errorf("unknown object %X %s %T", obj.ID(), obj.Type(), obj) - } - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/options.go b/vendor/github.com/go-git/go-git/v6/options.go deleted file mode 100644 index a19c5de8..00000000 --- a/vendor/github.com/go-git/go-git/v6/options.go +++ /dev/null @@ -1,819 +0,0 @@ -package git - -import ( - "errors" - "fmt" - "regexp" - "strings" - "time" - - "github.com/ProtonMail/go-crypto/openpgp" - "github.com/go-git/go-git/v6/config" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband" - "github.com/go-git/go-git/v6/plumbing/transport" -) - -// SubmoduleRecursivity defines how depth will affect any submodule recursive -// operation. -type SubmoduleRecursivity uint - -const ( - // DefaultRemoteName name of the default Remote, just like git command. - DefaultRemoteName = "origin" - - // NoRecurseSubmodules disables the recursion for a submodule operation. - NoRecurseSubmodules SubmoduleRecursivity = 0 - // DefaultSubmoduleRecursionDepth allow recursion in a submodule operation. - DefaultSubmoduleRecursionDepth SubmoduleRecursivity = 10 -) - -var ErrMissingURL = errors.New("URL field is required") - -// CloneOptions describes how a clone should be performed. -type CloneOptions struct { - // The (possibly remote) repository URL to clone from. - URL string - // Auth credentials, if required, to use with the remote repository. - Auth transport.AuthMethod - // Name of the remote to be added, by default `origin`. - RemoteName string - // Remote branch to clone. - ReferenceName plumbing.ReferenceName - // Fetch only ReferenceName if true. - SingleBranch bool - // Mirror clones the repository as a mirror. - // - // Compared to a bare clone, mirror not only maps local branches of the - // source to local branches of the target, it maps all refs (including - // remote-tracking branches, notes etc.) and sets up a refspec configuration - // such that all these refs are overwritten by a git remote update in the - // target repository. - Mirror bool - // No checkout of HEAD after clone if true. - NoCheckout bool - // Limit fetching to the specified number of commits. - Depth int - // RecurseSubmodules after the clone is created, initialize all submodules - // within, using their default settings. This option is ignored if the - // cloned repository does not have a worktree. - RecurseSubmodules SubmoduleRecursivity - // ShallowSubmodules limit cloning submodules to the 1 level of depth. - // It matches the git command --shallow-submodules. - ShallowSubmodules bool - // Progress is where the human readable information sent by the server is - // stored, if nil nothing is stored and the capability (if supported) - // no-progress, is sent to the server to avoid send this information. - Progress sideband.Progress - // Tags describe how the tags will be fetched from the remote repository, - // by default is AllTags. - Tags plumbing.TagMode - // InsecureSkipTLS skips ssl verify if protocol is https - InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool - CABundle []byte - // ProxyOptions provides info required for connecting to a proxy. - ProxyOptions transport.ProxyOptions - // When the repository to clone is on the local machine, instead of - // using hard links, automatically setup .git/objects/info/alternates - // to share the objects with the source repository. - // The resulting repository starts out without any object of its own. - // NOTE: this is a possibly dangerous operation; do not use it unless - // you understand what it does. - // - // [Reference]: https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---shared - Shared bool - // Filter requests that the server to send only a subset of the objects. - // See https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-code--filterltfilter-specgtcode - Filter packp.Filter - // Bare determines whether the repository will have a worktree (non-bare) - // or not (bare). - Bare bool -} - -// MergeOptions describes how a merge should be performed. -type MergeOptions struct { - // Strategy defines the merge strategy to be used. - Strategy MergeStrategy -} - -// MergeStrategy represents the different types of merge strategies. -type MergeStrategy int8 - -const ( - // FastForwardMerge represents a Git merge strategy where the current - // branch can be simply updated to point to the HEAD of the branch being - // merged. This is only possible if the history of the branch being merged - // is a linear descendant of the current branch, with no conflicting commits. - // - // This is the default option. - FastForwardMerge MergeStrategy = iota -) - -// Validate validates the fields and sets the default values. -func (o *CloneOptions) Validate() error { - if o.URL == "" { - return ErrMissingURL - } - - if o.RemoteName == "" { - o.RemoteName = DefaultRemoteName - } - - if o.ReferenceName == "" { - o.ReferenceName = plumbing.HEAD - } - - if o.Tags == plumbing.InvalidTagMode { - o.Tags = plumbing.AllTags - } - - return nil -} - -// PullOptions describes how a pull should be performed. -type PullOptions struct { - // Name of the remote to be pulled. If empty, uses the default. - RemoteName string - // RemoteURL overrides the remote repo address with a custom URL - RemoteURL string - // Remote branch to clone. If empty, uses HEAD. - ReferenceName plumbing.ReferenceName - // Fetch only ReferenceName if true. - SingleBranch bool - // Limit fetching to the specified number of commits. - Depth int - // Auth credentials, if required, to use with the remote repository. - Auth transport.AuthMethod - // RecurseSubmodules controls if new commits of all populated submodules - // should be fetched too. - RecurseSubmodules SubmoduleRecursivity - // Progress is where the human readable information sent by the server is - // stored, if nil nothing is stored and the capability (if supported) - // no-progress, is sent to the server to avoid send this information. - Progress sideband.Progress - // Force allows the pull to update a local branch even when the remote - // branch does not descend from it. - Force bool - // InsecureSkipTLS skips ssl verify if protocol is https - InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool - CABundle []byte - // ProxyOptions provides info required for connecting to a proxy. - ProxyOptions transport.ProxyOptions -} - -// Validate validates the fields and sets the default values. -func (o *PullOptions) Validate() error { - if o.RemoteName == "" { - o.RemoteName = DefaultRemoteName - } - - if o.ReferenceName == "" { - o.ReferenceName = plumbing.HEAD - } - - return nil -} - -const ( - InvalidTagMode = plumbing.InvalidTagMode - // TagFollowing any tag that points into the histories being fetched is also - // fetched. TagFollowing requires a server with `include-tag` capability - // in order to fetch the annotated tags objects. - TagFollowing = plumbing.TagFollowing - // AllTags fetch all tags from the remote (i.e., fetch remote tags - // refs/tags/* into local tags with the same name) - AllTags = plumbing.AllTags - // NoTags fetch no tags from the remote at all - NoTags = plumbing.NoTags -) - -// FetchOptions describes how a fetch should be performed -type FetchOptions struct { - // Name of the remote to fetch from. Defaults to origin. - RemoteName string - // RemoteURL overrides the remote repo address with a custom URL - RemoteURL string - RefSpecs []config.RefSpec - // Depth limit fetching to the specified number of commits from the tip of - // each remote branch history. - Depth int - // Auth credentials, if required, to use with the remote repository. - Auth transport.AuthMethod - // Progress is where the human readable information sent by the server is - // stored, if nil nothing is stored and the capability (if supported) - // no-progress, is sent to the server to avoid send this information. - Progress sideband.Progress - // Tags describe how the tags will be fetched from the remote repository, - // by default is TagFollowing. - Tags plumbing.TagMode - // Force allows the fetch to update a local branch even when the remote - // branch does not descend from it. - Force bool - // InsecureSkipTLS skips ssl verify if protocol is https - InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool - CABundle []byte - // ProxyOptions provides info required for connecting to a proxy. - ProxyOptions transport.ProxyOptions - // Prune specify that local refs that match given RefSpecs and that do - // not exist remotely will be removed. - Prune bool - // Filter requests that the server to send only a subset of the objects. - // See https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-code--filterltfilter-specgtcode - Filter packp.Filter -} - -// Validate validates the fields and sets the default values. -func (o *FetchOptions) Validate() error { - if o.RemoteName == "" { - o.RemoteName = DefaultRemoteName - } - - if o.Tags == plumbing.InvalidTagMode { - o.Tags = plumbing.TagFollowing - } - - for _, r := range o.RefSpecs { - if err := r.Validate(); err != nil { - return err - } - } - - return nil -} - -// PushOptions describes how a push should be performed. -type PushOptions struct { - // RemoteName is the name of the remote to be pushed to. - RemoteName string - // RemoteURL overrides the remote repo address with a custom URL - RemoteURL string - // RefSpecs specify what destination ref to update with what source object. - // - // The format of a parameter is an optional plus +, followed by - // the source object , followed by a colon :, followed by the destination ref . - // The is often the name of the branch you would want to push, but it can be a SHA-1. - // The tells which ref on the remote side is updated with this push. - // - // A refspec with empty src can be used to delete a reference. - RefSpecs []config.RefSpec - // Auth credentials, if required, to use with the remote repository. - Auth transport.AuthMethod - // Progress is where the human readable information sent by the server is - // stored, if nil nothing is stored. - Progress sideband.Progress - // Prune specify that remote refs that match given RefSpecs and that do - // not exist locally will be removed. - Prune bool - // Force allows the push to update a remote branch even when the local - // branch does not descend from it. - Force bool - // InsecureSkipTLS skips ssl verify if protocol is https - InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool - CABundle []byte - // RequireRemoteRefs only allows a remote ref to be updated if its current - // value is the one specified here. - RequireRemoteRefs []config.RefSpec - // FollowTags will send any annotated tags with a commit target reachable from - // the refs already being pushed - FollowTags bool - // ForceWithLease allows a force push as long as the remote ref adheres to a "lease" - ForceWithLease *ForceWithLease - // PushOptions sets options to be transferred to the server during push. - Options []string - // Atomic sets option to be an atomic push - Atomic bool - // ProxyOptions provides info required for connecting to a proxy. - ProxyOptions transport.ProxyOptions -} - -// ForceWithLease sets fields on the lease -// If neither RefName nor Hash are set, ForceWithLease protects -// all refs in the refspec by ensuring the ref of the remote in the local repsitory -// matches the one in the ref advertisement. -type ForceWithLease struct { - // RefName, when set will protect the ref by ensuring it matches the - // hash in the ref advertisement. - RefName plumbing.ReferenceName - // Hash is the expected object id of RefName. The push will be rejected unless this - // matches the corresponding object id of RefName in the refs advertisement. - Hash plumbing.Hash -} - -// Validate validates the fields and sets the default values. -func (o *PushOptions) Validate() error { - if o.RemoteName == "" { - o.RemoteName = DefaultRemoteName - } - - if len(o.RefSpecs) == 0 { - o.RefSpecs = []config.RefSpec{ - config.RefSpec(config.DefaultPushRefSpec), - } - } - - for _, r := range o.RefSpecs { - if err := r.Validate(); err != nil { - return err - } - } - - return nil -} - -// SubmoduleUpdateOptions describes how a submodule update should be performed. -type SubmoduleUpdateOptions struct { - // Init, if true initializes the submodules recorded in the index. - Init bool - // NoFetch tell to the update command to not fetch new objects from the - // remote site. - NoFetch bool - // RecurseSubmodules the update is performed not only in the submodules of - // the current repository but also in any nested submodules inside those - // submodules (and so on). Until the SubmoduleRecursivity is reached. - RecurseSubmodules SubmoduleRecursivity - // Auth credentials, if required, to use with the remote repository. - Auth transport.AuthMethod - // Depth limit fetching to the specified number of commits from the tip of - // each remote branch history. - Depth int -} - -var ( - ErrBranchHashExclusive = errors.New("Branch and Hash are mutually exclusive") - ErrCreateRequiresBranch = errors.New("Branch is mandatory when Create is used") -) - -// CheckoutOptions describes how a checkout operation should be performed. -type CheckoutOptions struct { - // Hash is the hash of a commit or tag to be checked out. If used, HEAD - // will be in detached mode. If Create is not used, Branch and Hash are - // mutually exclusive. - Hash plumbing.Hash - // Branch to be checked out, if Branch and Hash are empty is set to `master`. - Branch plumbing.ReferenceName - // Create a new branch named Branch and start it at Hash. - Create bool - // Force, if true when switching branches, proceed even if the index or the - // working tree differs from HEAD. This is used to throw away local changes - Force bool - // Keep, if true when switching branches, local changes (the index or the - // working tree changes) will be kept so that they can be committed to the - // target branch. Force and Keep are mutually exclusive, should not be both - // set to true. - Keep bool - // SparseCheckoutDirectories - SparseCheckoutDirectories []string -} - -// Validate validates the fields and sets the default values. -func (o *CheckoutOptions) Validate() error { - if !o.Create && !o.Hash.IsZero() && o.Branch != "" { - return ErrBranchHashExclusive - } - - if o.Create && o.Branch == "" { - return ErrCreateRequiresBranch - } - - if o.Branch == "" { - o.Branch = plumbing.Master - } - - return nil -} - -// ResetMode defines the mode of a reset operation. -type ResetMode int8 - -const ( - // MixedReset resets the index but not the working tree (i.e., the changed - // files are preserved but not marked for commit) and reports what has not - // been updated. This is the default action. - MixedReset ResetMode = iota - // HardReset resets the index and working tree. Any changes to tracked files - // in the working tree are discarded. - HardReset - // MergeReset resets the index and updates the files in the working tree - // that are different between Commit and HEAD, but keeps those which are - // different between the index and working tree (i.e. which have changes - // which have not been added). - // - // If a file that is different between Commit and the index has unstaged - // changes, reset is aborted. - MergeReset - // SoftReset does not touch the index file or the working tree at all (but - // resets the head to , just like all modes do). This leaves all - // your changed files "Changes to be committed", as git status would put it. - SoftReset -) - -// ResetOptions describes how a reset operation should be performed. -type ResetOptions struct { - // Commit, if commit is present set the current branch head (HEAD) to it. - Commit plumbing.Hash - // Mode, form resets the current branch head to Commit and possibly updates - // the index (resetting it to the tree of Commit) and the working tree - // depending on Mode. If empty MixedReset is used. - Mode ResetMode - // Files, if not empty will constrain the reseting the index to only files - // specified in this list. - Files []string - - // SparseDirs specifies which directories should be checked out. - // Directories not listed here will not appear in the worktree. - SparseDirs []string - - // SkipSparseDirValidation will skip the validation for SparseDirs. - SkipSparseDirValidation bool -} - -// Validate validates the fields and sets the default values. -func (o *ResetOptions) Validate(r *Repository) error { - if o.Commit == plumbing.ZeroHash { - ref, err := r.Head() - if err != nil { - return err - } - - o.Commit = ref.Hash() - } else { - _, err := r.CommitObject(o.Commit) - if err != nil { - return fmt.Errorf("invalid reset option: %w", err) - } - } - - return nil -} - -type LogOrder int8 - -const ( - LogOrderDefault LogOrder = iota - LogOrderDFS - LogOrderDFSPost - LogOrderBSF - LogOrderCommitterTime - LogOrderDFSPostFirstParent -) - -// LogOptions describes how a log action should be performed. -type LogOptions struct { - // When the From option is set the log will only contain commits - // reachable from it. If this option is not set, HEAD will be used as - // the default From. - From plumbing.Hash - - // When To is set the log will go down until it reaches to the commit with the - // specified hash. The default value for this field in nil - To plumbing.Hash - - // The default traversal algorithm is Depth-first search - // set Order=LogOrderCommitterTime for ordering by committer time (more compatible with `git log`) - // set Order=LogOrderBSF for Breadth-first search - Order LogOrder - - // Show only those commits in which the specified file was inserted/updated. - // It is equivalent to running `git log -- `. - // this field is kept for compatibility, it can be replaced with PathFilter - FileName *string - - // Filter commits based on the path of files that are updated - // takes file path as argument and should return true if the file is desired - // It can be used to implement `git log -- ` - // either is a file path, or directory path, or a regexp of file/directory path - PathFilter func(string) bool - - // Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as . - // It is equivalent to running `git log --all`. - // If set on true, the From option will be ignored. - All bool - - // Show commits more recent than a specific date. - // It is equivalent to running `git log --since ` or `git log --after `. - Since *time.Time - - // Show commits older than a specific date. - // It is equivalent to running `git log --until ` or `git log --before `. - Until *time.Time -} - -var ErrMissingAuthor = errors.New("author field is required") - -// AddOptions describes how an `add` operation should be performed -type AddOptions struct { - // All equivalent to `git add -A`, update the index not only where the - // working tree has a file matching `Path` but also where the index already - // has an entry. This adds, modifies, and removes index entries to match the - // working tree. If no `Path` nor `Glob` is given when `All` option is - // used, all files in the entire working tree are updated. - All bool - // Path is the exact filepath to the file or directory to be added. - Path string - // Glob adds all paths, matching pattern, to the index. If pattern matches a - // directory path, all directory contents are added to the index recursively. - Glob string - // SkipStatus adds the path with no status check. This option is relevant only - // when the `Path` option is specified and does not apply when the `All` option is used. - // Notice that when passing an ignored path it will be added anyway. - // When true it can speed up adding files to the worktree in very large repositories. - SkipStatus bool -} - -// Validate validates the fields and sets the default values. -func (o *AddOptions) Validate(r *Repository) error { - if o.Path != "" && o.Glob != "" { - return fmt.Errorf("fields Path and Glob are mutual exclusive") - } - - return nil -} - -// CommitOptions describes how a commit operation should be performed. -type CommitOptions struct { - // All automatically stage files that have been modified and deleted, but - // new files you have not told Git about are not affected. - All bool - // AllowEmptyCommits enable empty commits to be created. An empty commit - // is when no changes to the tree were made, but a new commit message is - // provided. The default behavior is false, which results in ErrEmptyCommit. - AllowEmptyCommits bool - // Author is the author's signature of the commit. If Author is empty the - // Name and Email is read from the config, and time.Now it's used as When. - Author *object.Signature - // Committer is the committer's signature of the commit. If Committer is - // nil the Author signature is used. - Committer *object.Signature - // Parents are the parents commits for the new commit, by default when - // len(Parents) is zero, the hash of HEAD reference is used. - Parents []plumbing.Hash - // SignKey denotes a key to sign the commit with. A nil value here means the - // commit will not be signed. The private key must be present and already - // decrypted. - SignKey *openpgp.Entity - // Signer denotes a cryptographic signer to sign the commit with. - // A nil value here means the commit will not be signed. - // Takes precedence over SignKey. - Signer Signer - // Amend will create a new commit object and replace the commit that HEAD currently - // points to. Cannot be used with All nor Parents. - Amend bool -} - -// Validate validates the fields and sets the default values. -func (o *CommitOptions) Validate(r *Repository) error { - if o.All && o.Amend { - return errors.New("all and amend cannot be used together") - } - - if o.Amend && len(o.Parents) > 0 { - return errors.New("parents cannot be used with amend") - } - - if o.Author == nil { - if err := o.loadConfigAuthorAndCommitter(r); err != nil { - return err - } - } - - if o.Committer == nil { - o.Committer = o.Author - } - - if len(o.Parents) == 0 { - head, err := r.Head() - if err != nil && err != plumbing.ErrReferenceNotFound { - return err - } - - if head != nil { - o.Parents = []plumbing.Hash{head.Hash()} - } - } - - return nil -} - -func (o *CommitOptions) loadConfigAuthorAndCommitter(r *Repository) error { - cfg, err := r.ConfigScoped(config.SystemScope) - if err != nil { - return err - } - - if o.Author == nil && cfg.Author.Email != "" && cfg.Author.Name != "" { - o.Author = &object.Signature{ - Name: cfg.Author.Name, - Email: cfg.Author.Email, - When: time.Now(), - } - } - - if o.Committer == nil && cfg.Committer.Email != "" && cfg.Committer.Name != "" { - o.Committer = &object.Signature{ - Name: cfg.Committer.Name, - Email: cfg.Committer.Email, - When: time.Now(), - } - } - - if o.Author == nil && cfg.User.Email != "" && cfg.User.Name != "" { - o.Author = &object.Signature{ - Name: cfg.User.Name, - Email: cfg.User.Email, - When: time.Now(), - } - } - - if o.Author == nil { - return ErrMissingAuthor - } - - return nil -} - -var ( - ErrMissingName = errors.New("name field is required") - ErrMissingTagger = errors.New("tagger field is required") - ErrMissingMessage = errors.New("message field is required") -) - -// CreateTagOptions describes how a tag object should be created. -type CreateTagOptions struct { - // Tagger defines the signature of the tag creator. If Tagger is empty the - // Name and Email is read from the config, and time.Now it's used as When. - Tagger *object.Signature - // Message defines the annotation of the tag. It is canonicalized during - // validation into the format expected by git - no leading whitespace and - // ending in a newline. - Message string - // SignKey denotes a key to sign the tag with. A nil value here means the tag - // will not be signed. The private key must be present and already decrypted. - SignKey *openpgp.Entity -} - -// Validate validates the fields and sets the default values. -func (o *CreateTagOptions) Validate(r *Repository, hash plumbing.Hash) error { - if o.Tagger == nil { - if err := o.loadConfigTagger(r); err != nil { - return err - } - } - - if o.Message == "" { - return ErrMissingMessage - } - - // Canonicalize the message into the expected message format. - o.Message = strings.TrimSpace(o.Message) + "\n" - - return nil -} - -func (o *CreateTagOptions) loadConfigTagger(r *Repository) error { - cfg, err := r.ConfigScoped(config.SystemScope) - if err != nil { - return err - } - - if o.Tagger == nil && cfg.Author.Email != "" && cfg.Author.Name != "" { - o.Tagger = &object.Signature{ - Name: cfg.Author.Name, - Email: cfg.Author.Email, - When: time.Now(), - } - } - - if o.Tagger == nil && cfg.User.Email != "" && cfg.User.Name != "" { - o.Tagger = &object.Signature{ - Name: cfg.User.Name, - Email: cfg.User.Email, - When: time.Now(), - } - } - - if o.Tagger == nil { - return ErrMissingTagger - } - - return nil -} - -// ListOptions describes how a remote list should be performed. -type ListOptions struct { - // Auth credentials, if required, to use with the remote repository. - Auth transport.AuthMethod - // InsecureSkipTLS skips ssl verify if protocol is https - InsecureSkipTLS bool - // CABundle specify additional ca bundle with system cert pool - CABundle []byte - // PeelingOption defines how peeled objects are handled during a - // remote list. - PeelingOption PeelingOption - // ProxyOptions provides info required for connecting to a proxy. - ProxyOptions transport.ProxyOptions - // Timeout specifies the timeout in seconds for list operations - Timeout int -} - -// PeelingOption represents the different ways to handle peeled references. -// -// Peeled references represent the underlying object of an annotated -// (or signed) tag. Refer to upstream documentation for more info: -// https://github.com/git/git/blob/master/Documentation/technical/reftable.txt -type PeelingOption uint8 - -const ( - // IgnorePeeled ignores all peeled reference names. This is the default behavior. - IgnorePeeled PeelingOption = 0 - // OnlyPeeled returns only peeled reference names. - OnlyPeeled PeelingOption = 1 - // AppendPeeled appends peeled reference names to the reference list. - AppendPeeled PeelingOption = 2 -) - -// CleanOptions describes how a clean should be performed. -type CleanOptions struct { - Dir bool -} - -// GrepOptions describes how a grep should be performed. -type GrepOptions struct { - // Patterns are compiled Regexp objects to be matched. - Patterns []*regexp.Regexp - // InvertMatch selects non-matching lines. - InvertMatch bool - // CommitHash is the hash of the commit from which worktree should be derived. - CommitHash plumbing.Hash - // ReferenceName is the branch or tag name from which worktree should be derived. - ReferenceName plumbing.ReferenceName - // PathSpecs are compiled Regexp objects of pathspec to use in the matching. - PathSpecs []*regexp.Regexp -} - -var ErrHashOrReference = errors.New("ambiguous options, only one of CommitHash or ReferenceName can be passed") - -// Validate validates the fields and sets the default values. -// -// TODO: deprecate in favor of Validate(r *Repository) in v6. -func (o *GrepOptions) Validate(w *Worktree) error { - return o.validate(w.r) -} - -func (o *GrepOptions) validate(r *Repository) error { - if !o.CommitHash.IsZero() && o.ReferenceName != "" { - return ErrHashOrReference - } - - // If none of CommitHash and ReferenceName are provided, set commit hash of - // the repository's head. - if o.CommitHash.IsZero() && o.ReferenceName == "" { - ref, err := r.Head() - if err != nil { - return err - } - o.CommitHash = ref.Hash() - } - - return nil -} - -// PlainOpenOptions describes how opening a plain repository should be -// performed. -type PlainOpenOptions struct { - // DetectDotGit defines whether parent directories should be - // walked until a .git directory or file is found. - DetectDotGit bool - // Enable .git/commondir support (see https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt). - // NOTE: This option will only work with the filesystem storage. - EnableDotGitCommonDir bool -} - -// Validate validates the fields and sets the default values. -func (o *PlainOpenOptions) Validate() error { return nil } - -var ErrNoRestorePaths = errors.New("you must specify path(s) to restore") - -// RestoreOptions describes how a restore should be performed. -type RestoreOptions struct { - // Marks to restore the content in the index - Staged bool - // Marks to restore the content of the working tree - Worktree bool - // List of file paths that will be restored - Files []string -} - -// Validate validates the fields and sets the default values. -func (o *RestoreOptions) Validate() error { - if len(o.Files) == 0 { - return ErrNoRestorePaths - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/cache/buffer_lru.go b/vendor/github.com/go-git/go-git/v6/plumbing/cache/buffer_lru.go deleted file mode 100644 index acaf1952..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/cache/buffer_lru.go +++ /dev/null @@ -1,98 +0,0 @@ -package cache - -import ( - "container/list" - "sync" -) - -// BufferLRU implements an object cache with an LRU eviction policy and a -// maximum size (measured in object size). -type BufferLRU struct { - MaxSize FileSize - - actualSize FileSize - ll *list.List - cache map[int64]*list.Element - mut sync.Mutex -} - -// NewBufferLRU creates a new BufferLRU with the given maximum size. The maximum -// size will never be exceeded. -func NewBufferLRU(maxSize FileSize) *BufferLRU { - return &BufferLRU{MaxSize: maxSize} -} - -// NewBufferLRUDefault creates a new BufferLRU with the default cache size. -func NewBufferLRUDefault() *BufferLRU { - return &BufferLRU{MaxSize: DefaultMaxSize} -} - -type buffer struct { - Key int64 - Slice []byte -} - -// Put puts a buffer into the cache. If the buffer is already in the cache, it -// will be marked as used. Otherwise, it will be inserted. A buffers might -// be evicted to make room for the new one. -func (c *BufferLRU) Put(key int64, slice []byte) { - c.mut.Lock() - defer c.mut.Unlock() - - if c.cache == nil { - c.actualSize = 0 - c.cache = make(map[int64]*list.Element, 1000) - c.ll = list.New() - } - - bufSize := FileSize(len(slice)) - if ee, ok := c.cache[key]; ok { - oldBuf := ee.Value.(buffer) - // in this case bufSize is a delta: new size - old size - bufSize -= FileSize(len(oldBuf.Slice)) - c.ll.MoveToFront(ee) - ee.Value = buffer{key, slice} - } else { - if bufSize > c.MaxSize { - return - } - ee := c.ll.PushFront(buffer{key, slice}) - c.cache[key] = ee - } - - c.actualSize += bufSize - for c.actualSize > c.MaxSize { - last := c.ll.Back() - lastObj := last.Value.(buffer) - lastSize := FileSize(len(lastObj.Slice)) - - c.ll.Remove(last) - delete(c.cache, lastObj.Key) - c.actualSize -= lastSize - } -} - -// Get returns a buffer by its key. It marks the buffer as used. If the buffer -// is not in the cache, (nil, false) will be returned. -func (c *BufferLRU) Get(key int64) ([]byte, bool) { - c.mut.Lock() - defer c.mut.Unlock() - - ee, ok := c.cache[key] - if !ok { - return nil, false - } - - c.ll.MoveToFront(ee) - return ee.Value.(buffer).Slice, true -} - -// Clear the content of this buffer cache. -func (c *BufferLRU) Clear() { - c.mut.Lock() - defer c.mut.Unlock() - - c.ll = nil - c.cache = nil - c.actualSize = 0 -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/cache/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/cache/common.go deleted file mode 100644 index 40843bd3..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/cache/common.go +++ /dev/null @@ -1,39 +0,0 @@ -package cache - -import "github.com/go-git/go-git/v6/plumbing" - -const ( - Byte FileSize = 1 << (iota * 10) - KiByte - MiByte - GiByte -) - -type FileSize int64 - -const DefaultMaxSize FileSize = 96 * MiByte - -// Object is an interface to a object cache. -type Object interface { - // Put puts the given object into the cache. Whether this object will - // actually be put into the cache or not is implementation specific. - Put(o plumbing.EncodedObject) - // Get gets an object from the cache given its hash. The second return value - // is true if the object was returned, and false otherwise. - Get(k plumbing.Hash) (plumbing.EncodedObject, bool) - // Clear clears every object from the cache. - Clear() -} - -// Buffer is an interface to a buffer cache. -type Buffer interface { - // Put puts a buffer into the cache. If the buffer is already in the cache, - // it will be marked as used. Otherwise, it will be inserted. Buffer might - // be evicted to make room for the new one. - Put(key int64, slice []byte) - // Get returns a buffer by its key. It marks the buffer as used. If the - // buffer is not in the cache, (nil, false) will be returned. - Get(key int64) ([]byte, bool) - // Clear clears every object from the cache. - Clear() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/cache/object_lru.go b/vendor/github.com/go-git/go-git/v6/plumbing/cache/object_lru.go deleted file mode 100644 index e1c8a631..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/cache/object_lru.go +++ /dev/null @@ -1,101 +0,0 @@ -package cache - -import ( - "container/list" - "sync" - - "github.com/go-git/go-git/v6/plumbing" -) - -// ObjectLRU implements an object cache with an LRU eviction policy and a -// maximum size (measured in object size). -type ObjectLRU struct { - MaxSize FileSize - - actualSize FileSize - ll *list.List - cache map[interface{}]*list.Element - mut sync.Mutex -} - -// NewObjectLRU creates a new ObjectLRU with the given maximum size. The maximum -// size will never be exceeded. -func NewObjectLRU(maxSize FileSize) *ObjectLRU { - return &ObjectLRU{MaxSize: maxSize} -} - -// NewObjectLRUDefault creates a new ObjectLRU with the default cache size. -func NewObjectLRUDefault() *ObjectLRU { - return &ObjectLRU{MaxSize: DefaultMaxSize} -} - -// Put puts an object into the cache. If the object is already in the cache, it -// will be marked as used. Otherwise, it will be inserted. A single object might -// be evicted to make room for the new object. -func (c *ObjectLRU) Put(obj plumbing.EncodedObject) { - c.mut.Lock() - defer c.mut.Unlock() - - if c.cache == nil { - c.actualSize = 0 - c.cache = make(map[interface{}]*list.Element, 1000) - c.ll = list.New() - } - - objSize := FileSize(obj.Size()) - key := obj.Hash() - if ee, ok := c.cache[key]; ok { - oldObj := ee.Value.(plumbing.EncodedObject) - // in this case objSize is a delta: new size - old size - objSize -= FileSize(oldObj.Size()) - c.ll.MoveToFront(ee) - ee.Value = obj - } else { - if objSize > c.MaxSize { - return - } - ee := c.ll.PushFront(obj) - c.cache[key] = ee - } - - c.actualSize += objSize - for c.actualSize > c.MaxSize { - last := c.ll.Back() - if last == nil { - c.actualSize = 0 - break - } - - lastObj := last.Value.(plumbing.EncodedObject) - lastSize := FileSize(lastObj.Size()) - - c.ll.Remove(last) - delete(c.cache, lastObj.Hash()) - c.actualSize -= lastSize - } -} - -// Get returns an object by its hash. It marks the object as used. If the object -// is not in the cache, (nil, false) will be returned. -func (c *ObjectLRU) Get(k plumbing.Hash) (plumbing.EncodedObject, bool) { - c.mut.Lock() - defer c.mut.Unlock() - - ee, ok := c.cache[k] - if !ok { - return nil, false - } - - c.ll.MoveToFront(ee) - return ee.Value.(plumbing.EncodedObject), true -} - -// Clear the content of this object cache. -func (c *ObjectLRU) Clear() { - c.mut.Lock() - defer c.mut.Unlock() - - c.ll = nil - c.cache = nil - c.actualSize = 0 -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/color/color.go b/vendor/github.com/go-git/go-git/v6/plumbing/color/color.go deleted file mode 100644 index 2cd74bdc..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/color/color.go +++ /dev/null @@ -1,38 +0,0 @@ -package color - -// TODO read colors from a github.com/go-git/go-git/plumbing/format/config.Config struct -// TODO implement color parsing, see https://github.com/git/git/blob/v2.26.2/color.c - -// Colors. See https://github.com/git/git/blob/v2.26.2/color.h#L24-L53. -const ( - Normal = "" - Reset = "\033[m" - Bold = "\033[1m" - Red = "\033[31m" - Green = "\033[32m" - Yellow = "\033[33m" - Blue = "\033[34m" - Magenta = "\033[35m" - Cyan = "\033[36m" - BoldRed = "\033[1;31m" - BoldGreen = "\033[1;32m" - BoldYellow = "\033[1;33m" - BoldBlue = "\033[1;34m" - BoldMagenta = "\033[1;35m" - BoldCyan = "\033[1;36m" - FaintRed = "\033[2;31m" - FaintGreen = "\033[2;32m" - FaintYellow = "\033[2;33m" - FaintBlue = "\033[2;34m" - FaintMagenta = "\033[2;35m" - FaintCyan = "\033[2;36m" - BgRed = "\033[41m" - BgGreen = "\033[42m" - BgYellow = "\033[43m" - BgBlue = "\033[44m" - BgMagenta = "\033[45m" - BgCyan = "\033[46m" - Faint = "\033[2m" - FaintItalic = "\033[2;3m" - Reverse = "\033[7m" -) diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/error.go b/vendor/github.com/go-git/go-git/v6/plumbing/error.go deleted file mode 100644 index a3ebed3f..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/error.go +++ /dev/null @@ -1,35 +0,0 @@ -package plumbing - -import "fmt" - -type PermanentError struct { - Err error -} - -func NewPermanentError(err error) *PermanentError { - if err == nil { - return nil - } - - return &PermanentError{Err: err} -} - -func (e *PermanentError) Error() string { - return fmt.Sprintf("permanent client error: %s", e.Err.Error()) -} - -type UnexpectedError struct { - Err error -} - -func NewUnexpectedError(err error) *UnexpectedError { - if err == nil { - return nil - } - - return &UnexpectedError{Err: err} -} - -func (e *UnexpectedError) Error() string { - return fmt.Sprintf("unexpected client error: %s", e.Err.Error()) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/filemode/filemode.go b/vendor/github.com/go-git/go-git/v6/plumbing/filemode/filemode.go deleted file mode 100644 index ea1a4575..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/filemode/filemode.go +++ /dev/null @@ -1,188 +0,0 @@ -package filemode - -import ( - "encoding/binary" - "fmt" - "os" - "strconv" -) - -// A FileMode represents the kind of tree entries used by git. It -// resembles regular file systems modes, although FileModes are -// considerably simpler (there are not so many), and there are some, -// like Submodule that has no file system equivalent. -type FileMode uint32 - -const ( - // Empty is used as the FileMode of tree elements when comparing - // trees in the following situations: - // - // - the mode of tree elements before their creation. - the mode of - // tree elements after their deletion. - the mode of unmerged - // elements when checking the index. - // - // Empty has no file system equivalent. As Empty is the zero value - // of FileMode, it is also returned by New and - // NewFromOsNewFromOSFileMode along with an error, when they fail. - Empty FileMode = 0 - // Dir represent a Directory. - Dir FileMode = 0040000 - // Regular represent non-executable files. Please note this is not - // the same as golang regular files, which include executable files. - Regular FileMode = 0100644 - // Deprecated represent non-executable files with the group writable - // bit set. This mode was supported by the first versions of git, - // but it has been deprecated nowadays. This library uses them - // internally, so you can read old packfiles, but will treat them as - // Regulars when interfacing with the outside world. This is the - // standard git behaviour. - Deprecated FileMode = 0100664 - // Executable represents executable files. - Executable FileMode = 0100755 - // Symlink represents symbolic links to files. - Symlink FileMode = 0120000 - // Submodule represents git submodules. This mode has no file system - // equivalent. - Submodule FileMode = 0160000 -) - -// New takes the octal string representation of a FileMode and returns -// the FileMode and a nil error. If the string can not be parsed to a -// 32 bit unsigned octal number, it returns Empty and the parsing error. -// -// Example: "40000" means Dir, "100644" means Regular. -// -// Please note this function does not check if the returned FileMode -// is valid in git or if it is malformed. For instance, "1" will -// return the malformed FileMode(1) and a nil error. -func New(s string) (FileMode, error) { - n, err := strconv.ParseUint(s, 8, 32) - if err != nil { - return Empty, err - } - - return FileMode(n), nil -} - -// NewFromOSFileMode returns the FileMode used by git to represent -// the provided file system modes and a nil error on success. If the -// file system mode cannot be mapped to any valid git mode (as with -// sockets or named pipes), it will return Empty and an error. -// -// Note that some git modes cannot be generated from os.FileModes, like -// Deprecated and Submodule; while Empty will be returned, along with an -// error, only when the method fails. -func NewFromOSFileMode(m os.FileMode) (FileMode, error) { - if m.IsRegular() { - if isSetTemporary(m) { - return Empty, fmt.Errorf("no equivalent git mode for %s", m) - } - if isSetCharDevice(m) { - return Empty, fmt.Errorf("no equivalent git mode for %s", m) - } - if isSetUserExecutable(m) { - return Executable, nil - } - return Regular, nil - } - - if m.IsDir() { - return Dir, nil - } - - if isSetSymLink(m) { - return Symlink, nil - } - - return Empty, fmt.Errorf("no equivalent git mode for %s", m) -} - -func isSetCharDevice(m os.FileMode) bool { - return m&os.ModeCharDevice != 0 -} - -func isSetTemporary(m os.FileMode) bool { - return m&os.ModeTemporary != 0 -} - -func isSetUserExecutable(m os.FileMode) bool { - return m&0100 != 0 -} - -func isSetSymLink(m os.FileMode) bool { - return m&os.ModeSymlink != 0 -} - -// Bytes return a slice of 4 bytes with the mode in little endian -// encoding. -func (m FileMode) Bytes() []byte { - ret := make([]byte, 4) - binary.LittleEndian.PutUint32(ret, uint32(m)) - return ret -} - -// IsMalformed returns if the FileMode should not appear in a git packfile, -// this is: Empty and any other mode not mentioned as a constant in this -// package. -func (m FileMode) IsMalformed() bool { - return m != Dir && - m != Regular && - m != Deprecated && - m != Executable && - m != Symlink && - m != Submodule -} - -// String returns the FileMode as a string in the standard git format, -// this is, an octal number padded with ceros to 7 digits. Malformed -// modes are printed in that same format, for easier debugging. -// -// Example: Regular is "0100644", Empty is "0000000". -func (m FileMode) String() string { - return fmt.Sprintf("%07o", uint32(m)) -} - -// IsRegular returns if the FileMode represents that of a regular file, -// this is, either Regular or Deprecated. Please note that Executable -// are not regular even though in the UNIX tradition, they usually are: -// See the IsFile method. -func (m FileMode) IsRegular() bool { - return m == Regular || - m == Deprecated -} - -// IsFile returns if the FileMode represents that of a file, this is, -// Regular, Deprecated, Executable or Link. -func (m FileMode) IsFile() bool { - return m == Regular || - m == Deprecated || - m == Executable || - m == Symlink -} - -// ToOSFileMode returns the os.FileMode to be used when creating file -// system elements with the given git mode and a nil error on success. -// -// When the provided mode cannot be mapped to a valid file system mode -// (e.g. Submodule) it returns os.FileMode(0) and an error. -// -// The returned file mode does not take into account the umask. -func (m FileMode) ToOSFileMode() (os.FileMode, error) { - switch m { - case Dir: - return os.ModePerm | os.ModeDir, nil - case Submodule: - return os.ModePerm | os.ModeDir, nil - case Regular: - return os.FileMode(0644), nil - // Deprecated is no longer allowed: treated as a Regular instead - case Deprecated: - return os.FileMode(0644), nil - case Executable: - return os.FileMode(0755), nil - case Symlink: - return os.ModePerm | os.ModeSymlink, nil - } - - return os.FileMode(0), fmt.Errorf("malformed mode (%s)", m) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/config/common.go deleted file mode 100644 index 6d689ea1..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/common.go +++ /dev/null @@ -1,109 +0,0 @@ -package config - -// New creates a new config instance. -func New() *Config { - return &Config{} -} - -// Config contains all the sections, comments and includes from a config file. -type Config struct { - Comment *Comment - Sections Sections - Includes Includes -} - -// Includes is a list of Includes in a config file. -type Includes []*Include - -// Include is a reference to an included config file. -type Include struct { - Path string - Config *Config -} - -// Comment string without the prefix '#' or ';'. -type Comment string - -const ( - // NoSubsection token is passed to Config.Section and Config.SetSection to - // represent the absence of a section. - NoSubsection = "" -) - -// Section returns a existing section with the given name or creates a new one. -func (c *Config) Section(name string) *Section { - for i := len(c.Sections) - 1; i >= 0; i-- { - s := c.Sections[i] - if s.IsName(name) { - return s - } - } - - s := &Section{Name: name} - c.Sections = append(c.Sections, s) - return s -} - -// HasSection checks if the Config has a section with the specified name. -func (c *Config) HasSection(name string) bool { - for _, s := range c.Sections { - if s.IsName(name) { - return true - } - } - return false -} - -// RemoveSection removes a section from a config file. -func (c *Config) RemoveSection(name string) *Config { - result := Sections{} - for _, s := range c.Sections { - if !s.IsName(name) { - result = append(result, s) - } - } - - c.Sections = result - return c -} - -// RemoveSubsection remove a subsection from a config file. -func (c *Config) RemoveSubsection(section string, subsection string) *Config { - for _, s := range c.Sections { - if s.IsName(section) { - result := Subsections{} - for _, ss := range s.Subsections { - if !ss.IsName(subsection) { - result = append(result, ss) - } - } - s.Subsections = result - } - } - - return c -} - -// AddOption adds an option to a given section and subsection. Use the -// NoSubsection constant for the subsection argument if no subsection is wanted. -func (c *Config) AddOption(section string, subsection string, key string, value string) *Config { - if subsection == "" { - c.Section(section).AddOption(key, value) - } else { - c.Section(section).Subsection(subsection).AddOption(key, value) - } - - return c -} - -// SetOption sets an option to a given section and subsection. Use the -// NoSubsection constant for the subsection argument if no subsection is wanted. -func (c *Config) SetOption(section string, subsection string, key string, value string) *Config { - if subsection == "" { - c.Section(section).SetOption(key, value) - } else { - c.Section(section).Subsection(subsection).SetOption(key, value) - } - - return c -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/decoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/config/decoder.go deleted file mode 100644 index db87799e..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/decoder.go +++ /dev/null @@ -1,37 +0,0 @@ -package config - -import ( - "io" - - "github.com/go-git/gcfg/v2" -) - -// A Decoder reads and decodes config files from an input stream. -type Decoder struct { - io.Reader -} - -// NewDecoder returns a new decoder that reads from r. -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{r} -} - -// Decode reads the whole config from its input and stores it in the -// value pointed to by config. -func (d *Decoder) Decode(config *Config) error { - cb := func(s string, ss string, k string, v string, bv bool) error { - if ss == "" && k == "" { - config.Section(s) - return nil - } - - if ss != "" && k == "" { - config.Section(s).Subsection(ss) - return nil - } - - config.AddOption(s, ss, k, v) - return nil - } - return gcfg.ReadWithCallback(d, cb) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/config/doc.go deleted file mode 100644 index 3986c836..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/doc.go +++ /dev/null @@ -1,122 +0,0 @@ -// Package config implements encoding and decoding of git config files. -// -// Configuration File -// ------------------ -// -// The Git configuration file contains a number of variables that affect -// the Git commands' behavior. The `.git/config` file in each repository -// is used to store the configuration for that repository, and -// `$HOME/.gitconfig` is used to store a per-user configuration as -// fallback values for the `.git/config` file. The file `/etc/gitconfig` -// can be used to store a system-wide default configuration. -// -// The configuration variables are used by both the Git plumbing -// and the porcelains. The variables are divided into sections, wherein -// the fully qualified variable name of the variable itself is the last -// dot-separated segment and the section name is everything before the last -// dot. The variable names are case-insensitive, allow only alphanumeric -// characters and `-`, and must start with an alphabetic character. Some -// variables may appear multiple times; we say then that the variable is -// multivalued. -// -// Syntax -// ~~~~~~ -// -// The syntax is fairly flexible and permissive; whitespaces are mostly -// ignored. The '#' and ';' characters begin comments to the end of line, -// blank lines are ignored. -// -// The file consists of sections and variables. A section begins with -// the name of the section in square brackets and continues until the next -// section begins. Section names are case-insensitive. Only alphanumeric -// characters, `-` and `.` are allowed in section names. Each variable -// must belong to some section, which means that there must be a section -// header before the first setting of a variable. -// -// Sections can be further divided into subsections. To begin a subsection -// put its name in double quotes, separated by space from the section name, -// in the section header, like in the example below: -// -// -------- -// [section "subsection"] -// -// -------- -// -// Subsection names are case sensitive and can contain any characters except -// newline (doublequote `"` and backslash can be included by escaping them -// as `\"` and `\\`, respectively). Section headers cannot span multiple -// lines. Variables may belong directly to a section or to a given subsection. -// You can have `[section]` if you have `[section "subsection"]`, but you -// don't need to. -// -// There is also a deprecated `[section.subsection]` syntax. With this -// syntax, the subsection name is converted to lower-case and is also -// compared case sensitively. These subsection names follow the same -// restrictions as section names. -// -// All the other lines (and the remainder of the line after the section -// header) are recognized as setting variables, in the form -// 'name = value' (or just 'name', which is a short-hand to say that -// the variable is the boolean "true"). -// The variable names are case-insensitive, allow only alphanumeric characters -// and `-`, and must start with an alphabetic character. -// -// A line that defines a value can be continued to the next line by -// ending it with a `\`; the backquote and the end-of-line are -// stripped. Leading whitespaces after 'name =', the remainder of the -// line after the first comment character '#' or ';', and trailing -// whitespaces of the line are discarded unless they are enclosed in -// double quotes. Internal whitespaces within the value are retained -// verbatim. -// -// Inside double quotes, double quote `"` and backslash `\` characters -// must be escaped: use `\"` for `"` and `\\` for `\`. -// -// The following escape sequences (beside `\"` and `\\`) are recognized: -// `\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB) -// and `\b` for backspace (BS). Other char escape sequences (including octal -// escape sequences) are invalid. -// -// Includes -// ~~~~~~~~ -// -// You can include one config file from another by setting the special -// `include.path` variable to the name of the file to be included. The -// variable takes a pathname as its value, and is subject to tilde -// expansion. -// -// The included file is expanded immediately, as if its contents had been -// found at the location of the include directive. If the value of the -// `include.path` variable is a relative path, the path is considered to be -// relative to the configuration file in which the include directive was -// found. See below for examples. -// -// -// Example -// ~~~~~~~ -// -// # Core variables -// [core] -// ; Don't trust file modes -// filemode = false -// -// # Our diff algorithm -// [diff] -// external = /usr/local/bin/diff-wrapper -// renames = true -// -// [branch "devel"] -// remote = origin -// merge = refs/heads/devel -// -// # Proxy settings -// [core] -// gitProxy="ssh" for "kernel.org" -// gitProxy=default-proxy ; for the rest -// -// [include] -// path = /path/to/foo.inc ; include by absolute path -// path = foo ; expand "foo" relative to the current file -// path = ~/foo ; expand "foo" in your `$HOME` directory -// -package config diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/encoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/config/encoder.go deleted file mode 100644 index de069aed..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/encoder.go +++ /dev/null @@ -1,82 +0,0 @@ -package config - -import ( - "fmt" - "io" - "strings" -) - -// An Encoder writes config files to an output stream. -type Encoder struct { - w io.Writer -} - -var ( - subsectionReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`) - valueReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`, "\n", `\n`, "\t", `\t`, "\b", `\b`) -) -// NewEncoder returns a new encoder that writes to w. -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{w} -} - -// Encode writes the config in git config format to the stream of the encoder. -func (e *Encoder) Encode(cfg *Config) error { - for _, s := range cfg.Sections { - if err := e.encodeSection(s); err != nil { - return err - } - } - - return nil -} - -func (e *Encoder) encodeSection(s *Section) error { - if len(s.Options) > 0 { - if err := e.printf("[%s]\n", s.Name); err != nil { - return err - } - - if err := e.encodeOptions(s.Options); err != nil { - return err - } - } - - for _, ss := range s.Subsections { - if err := e.encodeSubsection(s.Name, ss); err != nil { - return err - } - } - - return nil -} - -func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error { - if err := e.printf("[%s \"%s\"]\n", sectionName, subsectionReplacer.Replace(s.Name)); err != nil { - return err - } - - return e.encodeOptions(s.Options) -} - -func (e *Encoder) encodeOptions(opts Options) error { - for _, o := range opts { - var value string - if strings.ContainsAny(o.Value, "#;\"\t\n\\") || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") { - value = `"`+valueReplacer.Replace(o.Value)+`"` - } else { - value = o.Value - } - - if err := e.printf("\t%s = %s\n", o.Key, value); err != nil { - return err - } - } - - return nil -} - -func (e *Encoder) printf(msg string, args ...interface{}) error { - _, err := fmt.Fprintf(e.w, msg, args...) - return err -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/format.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/config/format.go deleted file mode 100644 index 26118e36..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/format.go +++ /dev/null @@ -1,105 +0,0 @@ -package config - -import "errors" - -// RepositoryFormatVersion represents the repository format version, -// as per defined at: -// -// https://git-scm.com/docs/repository-version -type RepositoryFormatVersion string - -const ( - // Version_0 is the format defined by the initial version of git, - // including but not limited to the format of the repository - // directory, the repository configuration file, and the object - // and ref storage. - // - // Specifying the complete behavior of git is beyond the scope - // of this document. - Version_0 = "0" - - // Version_1 is identical to version 0, with the following exceptions: - // - // 1. When reading the core.repositoryformatversion variable, a git - // implementation which supports version 1 MUST also read any - // configuration keys found in the extensions section of the - // configuration file. - // - // 2. If a version-1 repository specifies any extensions.* keys that - // the running git has not implemented, the operation MUST NOT proceed. - // Similarly, if the value of any known key is not understood by the - // implementation, the operation MUST NOT proceed. - // - // Note that if no extensions are specified in the config file, then - // core.repositoryformatversion SHOULD be set to 0 (setting it to 1 provides - // no benefit, and makes the repository incompatible with older - // implementations of git). - Version_1 = "1" - - // DefaultRepositoryFormatVersion holds the default repository format version. - DefaultRepositoryFormatVersion = Version_0 -) - -// ObjectFormat defines the object format. -type ObjectFormat int - -const ( - // SHA1 represents the object format used for SHA1. - SHA1 ObjectFormat = iota - - // SHA256 represents the object format used for SHA256. - SHA256 - - // DefaultObjectFormat holds the default object format. - DefaultObjectFormat = SHA1 -) - -// String returns the string representation of the ObjectFormat. -func (f ObjectFormat) String() string { - switch f { - case SHA1: - return "sha1" - case SHA256: - return "sha256" - default: - return "" - } -} - -// Size returns the hash size of the ObjectFormat. -func (f ObjectFormat) Size() int { - switch f { - case SHA1: - return SHA1Size - case SHA256: - return SHA256Size - default: - return 0 - } -} - -// HexSize returns the hash size in hexadecimal format of the ObjectFormat. -func (f ObjectFormat) HexSize() int { - switch f { - case SHA1: - return SHA1HexSize - case SHA256: - return SHA256HexSize - default: - return 0 - } -} - -// ErrInvalidObjectFormat is returned when an invalid ObjectFormat is used. -var ErrInvalidObjectFormat = errors.New("invalid object format") - -const ( - // SHA1Size is the size of SHA1 hash. - SHA1Size = 20 - // SHA256Size is the size of SHA256 hash. - SHA256Size = 32 - // SHA1HexSize is the size of SHA1 hash in hexadecimal format. - SHA1HexSize = SHA1Size * 2 - // SHA256HexSize is the size of SHA256 hash in hexadecimal format. - SHA256HexSize = SHA256Size * 2 -) diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/option.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/config/option.go deleted file mode 100644 index cad39481..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/option.go +++ /dev/null @@ -1,127 +0,0 @@ -package config - -import ( - "fmt" - "strings" -) - -// Option defines a key/value entity in a config file. -type Option struct { - // Key preserving original caseness. - // Use IsKey instead to compare key regardless of caseness. - Key string - // Original value as string, could be not normalized. - Value string -} - -type Options []*Option - -// IsKey returns true if the given key matches -// this option's key in a case-insensitive comparison. -func (o *Option) IsKey(key string) bool { - return strings.EqualFold(o.Key, key) -} - -func (opts Options) GoString() string { - var strs []string - for _, opt := range opts { - strs = append(strs, fmt.Sprintf("%#v", opt)) - } - - return strings.Join(strs, ", ") -} - -// Get gets the value for the given key if set, -// otherwise it returns the empty string. -// -// Note that there is no difference -// -// This matches git behaviour since git v1.8.1-rc1, -// if there are multiple definitions of a key, the -// last one wins. -// -// See: http://article.gmane.org/gmane.linux.kernel/1407184 -// -// In order to get all possible values for the same key, -// use GetAll. -func (opts Options) Get(key string) string { - for i := len(opts) - 1; i >= 0; i-- { - o := opts[i] - if o.IsKey(key) { - return o.Value - } - } - return "" -} - -// Has checks if an Option exist with the given key. -func (opts Options) Has(key string) bool { - for _, o := range opts { - if o.IsKey(key) { - return true - } - } - return false -} - -// GetAll returns all possible values for the same key. -func (opts Options) GetAll(key string) []string { - result := []string{} - for _, o := range opts { - if o.IsKey(key) { - result = append(result, o.Value) - } - } - return result -} - -func (opts Options) withoutOption(key string) Options { - result := Options{} - for _, o := range opts { - if !o.IsKey(key) { - result = append(result, o) - } - } - return result -} - -func (opts Options) withAddedOption(key string, value string) Options { - return append(opts, &Option{key, value}) -} - -func (opts Options) withSettedOption(key string, values ...string) Options { - var result Options - var added []string - for _, o := range opts { - if !o.IsKey(key) { - result = append(result, o) - continue - } - - if contains(values, o.Value) { - added = append(added, o.Value) - result = append(result, o) - continue - } - } - - for _, value := range values { - if contains(added, value) { - continue - } - - result = result.withAddedOption(key, value) - } - - return result -} - -func contains(haystack []string, needle string) bool { - for _, s := range haystack { - if s == needle { - return true - } - } - - return false -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/section.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/config/section.go deleted file mode 100644 index 4625ac58..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/config/section.go +++ /dev/null @@ -1,181 +0,0 @@ -package config - -import ( - "fmt" - "strings" -) - -// Section is the representation of a section inside git configuration files. -// Each Section contains Options that are used by both the Git plumbing -// and the porcelains. -// Sections can be further divided into subsections. To begin a subsection -// put its name in double quotes, separated by space from the section name, -// in the section header, like in the example below: -// -// [section "subsection"] -// -// All the other lines (and the remainder of the line after the section header) -// are recognized as option variables, in the form "name = value" (or just name, -// which is a short-hand to say that the variable is the boolean "true"). -// The variable names are case-insensitive, allow only alphanumeric characters -// and -, and must start with an alphabetic character: -// -// [section "subsection1"] -// option1 = value1 -// option2 -// [section "subsection2"] -// option3 = value2 -// -type Section struct { - Name string - Options Options - Subsections Subsections -} - -type Subsection struct { - Name string - Options Options -} - -type Sections []*Section - -func (s Sections) GoString() string { - var strs []string - for _, ss := range s { - strs = append(strs, fmt.Sprintf("%#v", ss)) - } - - return strings.Join(strs, ", ") -} - -type Subsections []*Subsection - -func (s Subsections) GoString() string { - var strs []string - for _, ss := range s { - strs = append(strs, fmt.Sprintf("%#v", ss)) - } - - return strings.Join(strs, ", ") -} - -// IsName checks if the name provided is equals to the Section name, case insensitive. -func (s *Section) IsName(name string) bool { - return strings.EqualFold(s.Name, name) -} - -// Subsection returns a Subsection from the specified Section. If the -// Subsection does not exists, new one is created and added to Section. -func (s *Section) Subsection(name string) *Subsection { - for i := len(s.Subsections) - 1; i >= 0; i-- { - ss := s.Subsections[i] - if ss.IsName(name) { - return ss - } - } - - ss := &Subsection{Name: name} - s.Subsections = append(s.Subsections, ss) - return ss -} - -// HasSubsection checks if the Section has a Subsection with the specified name. -func (s *Section) HasSubsection(name string) bool { - for _, ss := range s.Subsections { - if ss.IsName(name) { - return true - } - } - - return false -} - -// RemoveSubsection removes a subsection from a Section. -func (s *Section) RemoveSubsection(name string) *Section { - result := Subsections{} - for _, s := range s.Subsections { - if !s.IsName(name) { - result = append(result, s) - } - } - - s.Subsections = result - return s -} - -// Option returns the value for the specified key. Empty string is returned if -// key does not exists. -func (s *Section) Option(key string) string { - return s.Options.Get(key) -} - -// OptionAll returns all possible values for an option with the specified key. -// If the option does not exists, an empty slice will be returned. -func (s *Section) OptionAll(key string) []string { - return s.Options.GetAll(key) -} - -// HasOption checks if the Section has an Option with the given key. -func (s *Section) HasOption(key string) bool { - return s.Options.Has(key) -} - -// AddOption adds a new Option to the Section. The updated Section is returned. -func (s *Section) AddOption(key string, value string) *Section { - s.Options = s.Options.withAddedOption(key, value) - return s -} - -// SetOption adds a new Option to the Section. If the option already exists, is replaced. -// The updated Section is returned. -func (s *Section) SetOption(key string, value string) *Section { - s.Options = s.Options.withSettedOption(key, value) - return s -} - -// Remove an option with the specified key. The updated Section is returned. -func (s *Section) RemoveOption(key string) *Section { - s.Options = s.Options.withoutOption(key) - return s -} - -// IsName checks if the name of the subsection is exactly the specified name. -func (s *Subsection) IsName(name string) bool { - return s.Name == name -} - -// Option returns an option with the specified key. If the option does not exists, -// empty spring will be returned. -func (s *Subsection) Option(key string) string { - return s.Options.Get(key) -} - -// OptionAll returns all possible values for an option with the specified key. -// If the option does not exists, an empty slice will be returned. -func (s *Subsection) OptionAll(key string) []string { - return s.Options.GetAll(key) -} - -// HasOption checks if the Subsection has an Option with the given key. -func (s *Subsection) HasOption(key string) bool { - return s.Options.Has(key) -} - -// AddOption adds a new Option to the Subsection. The updated Subsection is returned. -func (s *Subsection) AddOption(key string, value string) *Subsection { - s.Options = s.Options.withAddedOption(key, value) - return s -} - -// SetOption adds a new Option to the Subsection. If the option already exists, is replaced. -// The updated Subsection is returned. -func (s *Subsection) SetOption(key string, value ...string) *Subsection { - s.Options = s.Options.withSettedOption(key, value...) - return s -} - -// RemoveOption removes the option with the specified key. The updated Subsection is returned. -func (s *Subsection) RemoveOption(key string) *Subsection { - s.Options = s.Options.withoutOption(key) - return s -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/colorconfig.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/colorconfig.go deleted file mode 100644 index c8f0b0de..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/colorconfig.go +++ /dev/null @@ -1,97 +0,0 @@ -package diff - -import "github.com/go-git/go-git/v6/plumbing/color" - -// A ColorKey is a key into a ColorConfig map and also equal to the key in the -// diff.color subsection of the config. See -// https://github.com/git/git/blob/v2.26.2/diff.c#L83-L106. -type ColorKey string - -// ColorKeys. -const ( - Context ColorKey = "context" - Meta ColorKey = "meta" - Frag ColorKey = "frag" - Old ColorKey = "old" - New ColorKey = "new" - Commit ColorKey = "commit" - Whitespace ColorKey = "whitespace" - Func ColorKey = "func" - OldMoved ColorKey = "oldMoved" - OldMovedAlternative ColorKey = "oldMovedAlternative" - OldMovedDimmed ColorKey = "oldMovedDimmed" - OldMovedAlternativeDimmed ColorKey = "oldMovedAlternativeDimmed" - NewMoved ColorKey = "newMoved" - NewMovedAlternative ColorKey = "newMovedAlternative" - NewMovedDimmed ColorKey = "newMovedDimmed" - NewMovedAlternativeDimmed ColorKey = "newMovedAlternativeDimmed" - ContextDimmed ColorKey = "contextDimmed" - OldDimmed ColorKey = "oldDimmed" - NewDimmed ColorKey = "newDimmed" - ContextBold ColorKey = "contextBold" - OldBold ColorKey = "oldBold" - NewBold ColorKey = "newBold" -) - -// A ColorConfig is a color configuration. A nil or empty ColorConfig -// corresponds to no color. -type ColorConfig map[ColorKey]string - -// A ColorConfigOption sets an option on a ColorConfig. -type ColorConfigOption func(ColorConfig) - -// WithColor sets the color for key. -func WithColor(key ColorKey, color string) ColorConfigOption { - return func(cc ColorConfig) { - cc[key] = color - } -} - -// defaultColorConfig is the default color configuration. See -// https://github.com/git/git/blob/v2.26.2/diff.c#L57-L81. -var defaultColorConfig = ColorConfig{ - Context: color.Normal, - Meta: color.Bold, - Frag: color.Cyan, - Old: color.Red, - New: color.Green, - Commit: color.Yellow, - Whitespace: color.BgRed, - Func: color.Normal, - OldMoved: color.BoldMagenta, - OldMovedAlternative: color.BoldBlue, - OldMovedDimmed: color.Faint, - OldMovedAlternativeDimmed: color.FaintItalic, - NewMoved: color.BoldCyan, - NewMovedAlternative: color.BoldYellow, - NewMovedDimmed: color.Faint, - NewMovedAlternativeDimmed: color.FaintItalic, - ContextDimmed: color.Faint, - OldDimmed: color.FaintRed, - NewDimmed: color.FaintGreen, - ContextBold: color.Bold, - OldBold: color.BoldRed, - NewBold: color.BoldGreen, -} - -// NewColorConfig returns a new ColorConfig. -func NewColorConfig(options ...ColorConfigOption) ColorConfig { - cc := make(ColorConfig) - for key, value := range defaultColorConfig { - cc[key] = value - } - for _, option := range options { - option(cc) - } - return cc -} - -// Reset returns the ANSI escape sequence to reset the color with key set from -// cc. If no color was set then no reset is needed so it returns the empty -// string. -func (cc ColorConfig) Reset(key ColorKey) string { - if cc[key] == "" { - return "" - } - return color.Reset -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/patch.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/patch.go deleted file mode 100644 index 32070b94..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/patch.go +++ /dev/null @@ -1,58 +0,0 @@ -package diff - -import ( - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" -) - -// Operation defines the operation of a diff item. -type Operation int - -const ( - // Equal item represents an equals diff. - Equal Operation = iota - // Add item represents an insert diff. - Add - // Delete item represents a delete diff. - Delete -) - -// Patch represents a collection of steps to transform several files. -type Patch interface { - // FilePatches returns a slice of patches per file. - FilePatches() []FilePatch - // Message returns an optional message that can be at the top of the - // Patch representation. - Message() string -} - -// FilePatch represents the necessary steps to transform one file into another. -type FilePatch interface { - // IsBinary returns true if this patch is representing a binary file. - IsBinary() bool - // Files returns the from and to Files, with all the necessary metadata - // about them. If the patch creates a new file, "from" will be nil. - // If the patch deletes a file, "to" will be nil. - Files() (from, to File) - // Chunks returns a slice of ordered changes to transform "from" File into - // "to" File. If the file is a binary one, Chunks will be empty. - Chunks() []Chunk -} - -// File contains all the file metadata necessary to print some patch formats. -type File interface { - // Hash returns the File Hash. - Hash() plumbing.Hash - // Mode returns the FileMode. - Mode() filemode.FileMode - // Path returns the complete Path to the file, including the filename. - Path() string -} - -// Chunk represents a portion of a file transformation into another. -type Chunk interface { - // Content contains the portion of the file. - Content() string - // Type contains the Operation to do with this Chunk. - Type() Operation -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/unified_encoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/unified_encoder.go deleted file mode 100644 index 9db63ef4..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/diff/unified_encoder.go +++ /dev/null @@ -1,395 +0,0 @@ -package diff - -import ( - "fmt" - "io" - "regexp" - "strconv" - "strings" - - "github.com/go-git/go-git/v6/plumbing" -) - -// DefaultContextLines is the default number of context lines. -const DefaultContextLines = 3 - -var ( - splitLinesRegexp = regexp.MustCompile(`[^\n]*(\n|$)`) - - operationChar = map[Operation]byte{ - Add: '+', - Delete: '-', - Equal: ' ', - } - - operationColorKey = map[Operation]ColorKey{ - Add: New, - Delete: Old, - Equal: Context, - } -) - -// UnifiedEncoder encodes an unified diff into the provided Writer. It does not -// support similarity index for renames or sorting hash representations. -type UnifiedEncoder struct { - io.Writer - - // contextLines is the count of unchanged lines that will appear surrounding - // a change. - contextLines int - - // srcPrefix and dstPrefix are prepended to file paths when encoding a diff. - srcPrefix string - dstPrefix string - - // colorConfig is the color configuration. The default is no color. - color ColorConfig -} - -// NewUnifiedEncoder returns a new UnifiedEncoder that writes to w. -func NewUnifiedEncoder(w io.Writer, contextLines int) *UnifiedEncoder { - return &UnifiedEncoder{ - Writer: w, - srcPrefix: "a/", - dstPrefix: "b/", - contextLines: contextLines, - } -} - -// SetColor sets e's color configuration and returns e. -func (e *UnifiedEncoder) SetColor(colorConfig ColorConfig) *UnifiedEncoder { - e.color = colorConfig - return e -} - -// SetSrcPrefix sets e's srcPrefix and returns e. -func (e *UnifiedEncoder) SetSrcPrefix(prefix string) *UnifiedEncoder { - e.srcPrefix = prefix - return e -} - -// SetDstPrefix sets e's dstPrefix and returns e. -func (e *UnifiedEncoder) SetDstPrefix(prefix string) *UnifiedEncoder { - e.dstPrefix = prefix - return e -} - -// Encode encodes patch. -func (e *UnifiedEncoder) Encode(patch Patch) error { - sb := &strings.Builder{} - - if message := patch.Message(); message != "" { - sb.WriteString(message) - if !strings.HasSuffix(message, "\n") { - sb.WriteByte('\n') - } - } - - for _, filePatch := range patch.FilePatches() { - e.writeFilePatchHeader(sb, filePatch) - g := newHunksGenerator(filePatch.Chunks(), e.contextLines) - for _, hunk := range g.Generate() { - hunk.writeTo(sb, e.color) - } - } - - _, err := e.Write([]byte(sb.String())) - return err -} - -func (e *UnifiedEncoder) writeFilePatchHeader(sb *strings.Builder, filePatch FilePatch) { - from, to := filePatch.Files() - if from == nil && to == nil { - return - } - isBinary := filePatch.IsBinary() - - var lines []string - switch { - case from != nil && to != nil: - hashEquals := from.Hash() == to.Hash() - lines = append(lines, - fmt.Sprintf("diff --git %s%s %s%s", - e.srcPrefix, from.Path(), e.dstPrefix, to.Path()), - ) - if from.Mode() != to.Mode() { - lines = append(lines, - fmt.Sprintf("old mode %o", from.Mode()), - fmt.Sprintf("new mode %o", to.Mode()), - ) - } - if from.Path() != to.Path() { - lines = append(lines, - fmt.Sprintf("rename from %s", from.Path()), - fmt.Sprintf("rename to %s", to.Path()), - ) - } - if from.Mode() != to.Mode() && !hashEquals { - lines = append(lines, - fmt.Sprintf("index %s..%s", from.Hash(), to.Hash()), - ) - } else if !hashEquals { - lines = append(lines, - fmt.Sprintf("index %s..%s %o", from.Hash(), to.Hash(), from.Mode()), - ) - } - if !hashEquals { - lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), e.dstPrefix+to.Path(), isBinary) - } - case from == nil: - lines = append(lines, - fmt.Sprintf("diff --git %s %s", e.srcPrefix+to.Path(), e.dstPrefix+to.Path()), - fmt.Sprintf("new file mode %o", to.Mode()), - fmt.Sprintf("index %s..%s", plumbing.ZeroHash, to.Hash()), - ) - lines = e.appendPathLines(lines, "/dev/null", e.dstPrefix+to.Path(), isBinary) - case to == nil: - lines = append(lines, - fmt.Sprintf("diff --git %s %s", e.srcPrefix+from.Path(), e.dstPrefix+from.Path()), - fmt.Sprintf("deleted file mode %o", from.Mode()), - fmt.Sprintf("index %s..%s", from.Hash(), plumbing.ZeroHash), - ) - lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), "/dev/null", isBinary) - } - - sb.WriteString(e.color[Meta]) - sb.WriteString(lines[0]) - for _, line := range lines[1:] { - sb.WriteByte('\n') - sb.WriteString(line) - } - sb.WriteString(e.color.Reset(Meta)) - sb.WriteByte('\n') -} - -func (e *UnifiedEncoder) appendPathLines(lines []string, fromPath, toPath string, isBinary bool) []string { - if isBinary { - return append(lines, - fmt.Sprintf("Binary files %s and %s differ", fromPath, toPath), - ) - } - return append(lines, - fmt.Sprintf("--- %s", fromPath), - fmt.Sprintf("+++ %s", toPath), - ) -} - -type hunksGenerator struct { - fromLine, toLine int - ctxLines int - chunks []Chunk - current *hunk - hunks []*hunk - beforeContext, afterContext []string -} - -func newHunksGenerator(chunks []Chunk, ctxLines int) *hunksGenerator { - return &hunksGenerator{ - chunks: chunks, - ctxLines: ctxLines, - } -} - -func (g *hunksGenerator) Generate() []*hunk { - for i, chunk := range g.chunks { - lines := splitLines(chunk.Content()) - nLines := len(lines) - - switch chunk.Type() { - case Equal: - g.fromLine += nLines - g.toLine += nLines - g.processEqualsLines(lines, i) - case Delete: - if nLines != 0 { - g.fromLine++ - } - - g.processHunk(i, chunk.Type()) - g.fromLine += nLines - 1 - g.current.AddOp(chunk.Type(), lines...) - case Add: - if nLines != 0 { - g.toLine++ - } - g.processHunk(i, chunk.Type()) - g.toLine += nLines - 1 - g.current.AddOp(chunk.Type(), lines...) - } - - if i == len(g.chunks)-1 && g.current != nil { - g.hunks = append(g.hunks, g.current) - } - } - - return g.hunks -} - -func (g *hunksGenerator) processHunk(i int, op Operation) { - if g.current != nil { - return - } - - var ctxPrefix string - linesBefore := len(g.beforeContext) - if linesBefore > g.ctxLines { - ctxPrefix = g.beforeContext[linesBefore-g.ctxLines-1] - g.beforeContext = g.beforeContext[linesBefore-g.ctxLines:] - linesBefore = g.ctxLines - } - - g.current = &hunk{ctxPrefix: strings.TrimSuffix(ctxPrefix, "\n")} - g.current.AddOp(Equal, g.beforeContext...) - - switch op { - case Delete: - g.current.fromLine, g.current.toLine = - g.addLineNumbers(g.fromLine, g.toLine, linesBefore, i, Add) - case Add: - g.current.toLine, g.current.fromLine = - g.addLineNumbers(g.toLine, g.fromLine, linesBefore, i, Delete) - } - - g.beforeContext = nil -} - -// addLineNumbers obtains the line numbers in a new chunk. -func (g *hunksGenerator) addLineNumbers(la, lb int, linesBefore int, i int, op Operation) (cla, clb int) { - cla = la - linesBefore - // we need to search for a reference for the next diff - switch { - case linesBefore != 0 && g.ctxLines != 0: - if lb > g.ctxLines { - clb = lb - g.ctxLines + 1 - } else { - clb = 1 - } - case g.ctxLines == 0: - clb = lb - case i != len(g.chunks)-1: - next := g.chunks[i+1] - if next.Type() == op || next.Type() == Equal { - // this diff will be into this chunk - clb = lb + 1 - } - } - - return -} - -func (g *hunksGenerator) processEqualsLines(ls []string, i int) { - if g.current == nil { - g.beforeContext = append(g.beforeContext, ls...) - return - } - - g.afterContext = append(g.afterContext, ls...) - if len(g.afterContext) <= g.ctxLines*2 && i != len(g.chunks)-1 { - g.current.AddOp(Equal, g.afterContext...) - g.afterContext = nil - } else { - ctxLines := g.ctxLines - if ctxLines > len(g.afterContext) { - ctxLines = len(g.afterContext) - } - g.current.AddOp(Equal, g.afterContext[:ctxLines]...) - g.hunks = append(g.hunks, g.current) - - g.current = nil - g.beforeContext = g.afterContext[ctxLines:] - g.afterContext = nil - } -} - -func splitLines(s string) []string { - out := splitLinesRegexp.FindAllString(s, -1) - if out[len(out)-1] == "" { - out = out[:len(out)-1] - } - return out -} - -type hunk struct { - fromLine int - toLine int - - fromCount int - toCount int - - ctxPrefix string - ops []*op -} - -func (h *hunk) writeTo(sb *strings.Builder, color ColorConfig) { - sb.WriteString(color[Frag]) - sb.WriteString("@@ -") - - if h.fromCount == 1 { - sb.WriteString(strconv.Itoa(h.fromLine)) - } else { - sb.WriteString(strconv.Itoa(h.fromLine)) - sb.WriteByte(',') - sb.WriteString(strconv.Itoa(h.fromCount)) - } - - sb.WriteString(" +") - - if h.toCount == 1 { - sb.WriteString(strconv.Itoa(h.toLine)) - } else { - sb.WriteString(strconv.Itoa(h.toLine)) - sb.WriteByte(',') - sb.WriteString(strconv.Itoa(h.toCount)) - } - - sb.WriteString(" @@") - sb.WriteString(color.Reset(Frag)) - - if h.ctxPrefix != "" { - sb.WriteByte(' ') - sb.WriteString(color[Func]) - sb.WriteString(h.ctxPrefix) - sb.WriteString(color.Reset(Func)) - } - - sb.WriteByte('\n') - - for _, op := range h.ops { - op.writeTo(sb, color) - } -} - -func (h *hunk) AddOp(t Operation, ss ...string) { - n := len(ss) - switch t { - case Add: - h.toCount += n - case Delete: - h.fromCount += n - case Equal: - h.toCount += n - h.fromCount += n - } - - for _, s := range ss { - h.ops = append(h.ops, &op{s, t}) - } -} - -type op struct { - text string - t Operation -} - -func (o *op) writeTo(sb *strings.Builder, color ColorConfig) { - colorKey := operationColorKey[o.t] - sb.WriteString(color[colorKey]) - sb.WriteByte(operationChar[o.t]) - if strings.HasSuffix(o.text, "\n") { - sb.WriteString(strings.TrimSuffix(o.text, "\n")) - } else { - sb.WriteString(o.text + "\n\\ No newline at end of file") - } - sb.WriteString(color.Reset(colorKey)) - sb.WriteByte('\n') -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/dir.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/dir.go deleted file mode 100644 index cff6cd45..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/dir.go +++ /dev/null @@ -1,148 +0,0 @@ -package gitignore - -import ( - "bufio" - "bytes" - "io" - "os" - "strings" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/internal/path_util" - "github.com/go-git/go-git/v6/plumbing/format/config" - gioutil "github.com/go-git/go-git/v6/utils/ioutil" -) - -const ( - commentPrefix = "#" - coreSection = "core" - excludesfile = "excludesfile" - gitDir = ".git" - gitignoreFile = ".gitignore" - gitconfigFile = ".gitconfig" - systemFile = "/etc/gitconfig" - infoExcludeFile = gitDir + "/info/exclude" -) - -// readIgnoreFile reads a specific git ignore file. -func readIgnoreFile(fs billy.Filesystem, path []string, ignoreFile string) (ps []Pattern, err error) { - - ignoreFile, _ = path_util.ReplaceTildeWithHome(ignoreFile) - - f, err := fs.Open(fs.Join(append(path, ignoreFile)...)) - if err == nil { - defer f.Close() - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - s := scanner.Text() - if !strings.HasPrefix(s, commentPrefix) && len(strings.TrimSpace(s)) > 0 { - ps = append(ps, ParsePattern(s, path)) - } - } - } else if !os.IsNotExist(err) { - return nil, err - } - - return -} - -// ReadPatterns reads the .git/info/exclude and then the gitignore patterns -// recursively traversing through the directory structure. The result is in -// the ascending order of priority (last higher). -func ReadPatterns(fs billy.Filesystem, path []string) (ps []Pattern, err error) { - ps, _ = readIgnoreFile(fs, path, infoExcludeFile) - - subps, _ := readIgnoreFile(fs, path, gitignoreFile) - ps = append(ps, subps...) - - var fis []os.FileInfo - fis, err = fs.ReadDir(fs.Join(path...)) - if err != nil { - return - } - - for _, fi := range fis { - if fi.IsDir() && fi.Name() != gitDir { - if NewMatcher(ps).Match(append(path, fi.Name()), true) { - continue - } - - var subps []Pattern - subps, err = ReadPatterns(fs, append(path, fi.Name())) - if err != nil { - return - } - - if len(subps) > 0 { - ps = append(ps, subps...) - } - } - } - - return -} - -func loadPatterns(fs billy.Filesystem, path string) (ps []Pattern, err error) { - f, err := fs.Open(path) - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - return nil, err - } - - defer gioutil.CheckClose(f, &err) - - b, err := io.ReadAll(f) - if err != nil { - return - } - - d := config.NewDecoder(bytes.NewBuffer(b)) - - raw := config.New() - if err = d.Decode(raw); err != nil { - return - } - - s := raw.Section(coreSection) - efo := s.Options.Get(excludesfile) - if efo == "" { - return nil, nil - } - - ps, err = readIgnoreFile(fs, nil, efo) - if os.IsNotExist(err) { - return nil, nil - } - - return -} - -// LoadGlobalPatterns loads gitignore patterns from the gitignore file -// declared in a user's ~/.gitconfig file. If the ~/.gitconfig file does not -// exist the function will return nil. If the core.excludesfile property -// is not declared, the function will return nil. If the file pointed to by -// the core.excludesfile property does not exist, the function will return nil. -// -// The function assumes fs is rooted at the root filesystem. -func LoadGlobalPatterns(fs billy.Filesystem) (ps []Pattern, err error) { - home, err := os.UserHomeDir() - if err != nil { - return - } - - return loadPatterns(fs, fs.Join(home, gitconfigFile)) -} - -// LoadSystemPatterns loads gitignore patterns from the gitignore file -// declared in a system's /etc/gitconfig file. If the /etc/gitconfig file does -// not exist the function will return nil. If the core.excludesfile property -// is not declared, the function will return nil. If the file pointed to by -// the core.excludesfile property does not exist, the function will return nil. -// -// The function assumes fs is rooted at the root filesystem. -func LoadSystemPatterns(fs billy.Filesystem) (ps []Pattern, err error) { - return loadPatterns(fs, systemFile) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/doc.go deleted file mode 100644 index eecd4bac..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/doc.go +++ /dev/null @@ -1,70 +0,0 @@ -// Package gitignore implements matching file system paths to gitignore patterns that -// can be automatically read from a git repository tree in the order of definition -// priorities. It support all pattern formats as specified in the original gitignore -// documentation, copied below: -// -// Pattern format -// ============== -// -// - A blank line matches no files, so it can serve as a separator for readability. -// -// - A line starting with # serves as a comment. Put a backslash ("\") in front of -// the first hash for patterns that begin with a hash. -// -// - Trailing spaces are ignored unless they are quoted with backslash ("\"). -// -// - An optional prefix "!" which negates the pattern; any matching file excluded -// by a previous pattern will become included again. It is not possible to -// re-include a file if a parent directory of that file is excluded. -// Git doesn’t list excluded directories for performance reasons, so -// any patterns on contained files have no effect, no matter where they are -// defined. Put a backslash ("\") in front of the first "!" for patterns -// that begin with a literal "!", for example, "\!important!.txt". -// -// - If the pattern ends with a slash, it is removed for the purpose of the -// following description, but it would only find a match with a directory. -// In other words, foo/ will match a directory foo and paths underneath it, -// but will not match a regular file or a symbolic link foo (this is consistent -// with the way how pathspec works in general in Git). -// -// - If the pattern does not contain a slash /, Git treats it as a shell glob -// pattern and checks for a match against the pathname relative to the location -// of the .gitignore file (relative to the toplevel of the work tree if not -// from a .gitignore file). -// -// - Otherwise, Git treats the pattern as a shell glob suitable for consumption -// by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will -// not match a / in the pathname. For example, "Documentation/*.html" matches -// "Documentation/git.html" but not "Documentation/ppc/ppc.html" or -// "tools/perf/Documentation/perf.html". -// -// - A leading slash matches the beginning of the pathname. For example, -// "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". -// -// Two consecutive asterisks ("**") in patterns matched against full pathname -// may have special meaning: -// -// - A leading "**" followed by a slash means match in all directories. -// For example, "**/foo" matches file or directory "foo" anywhere, the same as -// pattern "foo". "**/foo/bar" matches file or directory "bar" -// anywhere that is directly under directory "foo". -// -// - A trailing "/**" matches everything inside. For example, "abc/**" matches -// all files inside directory "abc", relative to the location of the -// .gitignore file, with infinite depth. -// -// - A slash followed by two consecutive asterisks then a slash matches -// zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b", -// "a/x/y/b" and so on. -// -// - Other consecutive asterisks are considered invalid. -// -// Copyright and license -// ===================== -// -// Copyright (c) Oleg Sklyar, Silvertern and source{d} -// -// The package code was donated to source{d} to include, modify and develop -// further as a part of the `go-git` project, release it on the license of -// the whole project or delete it from the project. -package gitignore diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/matcher.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/matcher.go deleted file mode 100644 index bd1e9e2d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/matcher.go +++ /dev/null @@ -1,30 +0,0 @@ -package gitignore - -// Matcher defines a global multi-pattern matcher for gitignore patterns -type Matcher interface { - // Match matches patterns in the order of priorities. As soon as an inclusion or - // exclusion is found, not further matching is performed. - Match(path []string, isDir bool) bool -} - -// NewMatcher constructs a new global matcher. Patterns must be given in the order of -// increasing priority. That is most generic settings files first, then the content of -// the repo .gitignore, then content of .gitignore down the path or the repo and then -// the content command line arguments. -func NewMatcher(ps []Pattern) Matcher { - return &matcher{ps} -} - -type matcher struct { - patterns []Pattern -} - -func (m *matcher) Match(path []string, isDir bool) bool { - n := len(m.patterns) - for i := n - 1; i >= 0; i-- { - if match := m.patterns[i].Match(path, isDir); match > NoMatch { - return match == Exclude - } - } - return false -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/pattern.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/pattern.go deleted file mode 100644 index c80e8417..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/gitignore/pattern.go +++ /dev/null @@ -1,159 +0,0 @@ -package gitignore - -import ( - "path/filepath" - "strings" -) - -// MatchResult defines outcomes of a match, no match, exclusion or inclusion. -type MatchResult int - -const ( - // NoMatch defines the no match outcome of a match check - NoMatch MatchResult = iota - // Exclude defines an exclusion of a file as a result of a match check - Exclude - // Include defines an explicit inclusion of a file as a result of a match check - Include -) - -const ( - inclusionPrefix = "!" - zeroToManyDirs = "**" - patternDirSep = "/" -) - -// Pattern defines a single gitignore pattern. -type Pattern interface { - // Match matches the given path to the pattern. - Match(path []string, isDir bool) MatchResult -} - -type pattern struct { - domain []string - pattern []string - inclusion bool - dirOnly bool - isGlob bool -} - -// ParsePattern parses a gitignore pattern string into the Pattern structure. -func ParsePattern(p string, domain []string) Pattern { - // storing domain, copy it to ensure it isn't changed externally - domain = append([]string(nil), domain...) - res := pattern{domain: domain} - - if strings.HasPrefix(p, inclusionPrefix) { - res.inclusion = true - p = p[1:] - } - - if !strings.HasSuffix(p, "\\ ") { - p = strings.TrimRight(p, " ") - } - - if strings.HasSuffix(p, patternDirSep) { - res.dirOnly = true - p = p[:len(p)-1] - } - - if strings.Contains(p, patternDirSep) { - res.isGlob = true - } - - res.pattern = strings.Split(p, patternDirSep) - return &res -} - -func (p *pattern) Match(path []string, isDir bool) MatchResult { - if len(path) <= len(p.domain) { - return NoMatch - } - for i, e := range p.domain { - if path[i] != e { - return NoMatch - } - } - - path = path[len(p.domain):] - if p.isGlob && !p.globMatch(path, isDir) { - return NoMatch - } else if !p.isGlob && !p.simpleNameMatch(path, isDir) { - return NoMatch - } - - if p.inclusion { - return Include - } else { - return Exclude - } -} - -func (p *pattern) simpleNameMatch(path []string, isDir bool) bool { - for i, name := range path { - if match, err := filepath.Match(p.pattern[0], name); err != nil { - return false - } else if !match { - continue - } - if p.dirOnly && !isDir && i == len(path)-1 { - return false - } - return true - } - return false -} - -func (p *pattern) globMatch(path []string, isDir bool) bool { - matched := false - canTraverse := false - for i, pattern := range p.pattern { - if pattern == "" { - canTraverse = false - continue - } - if pattern == zeroToManyDirs { - if i == len(p.pattern)-1 { - break - } - canTraverse = true - continue - } - if strings.Contains(pattern, zeroToManyDirs) { - return false - } - if len(path) == 0 { - return false - } - if canTraverse { - canTraverse = false - for len(path) > 0 { - e := path[0] - path = path[1:] - if match, err := filepath.Match(pattern, e); err != nil { - return false - } else if match { - matched = true - break - } else if len(path) == 0 { - // if nothing left then fail - matched = false - } - } - } else { - if match, err := filepath.Match(pattern, path[0]); err != nil || !match { - return false - } - matched = true - path = path[1:] - // files matching dir globs, don't match - if len(path) == 0 && i < len(p.pattern)-1 { - matched = false - } - } - } - if matched && p.dirOnly && !isDir && len(path) == 0 { - matched = false - } - return matched -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/decoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/decoder.go deleted file mode 100644 index b2de1e44..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/decoder.go +++ /dev/null @@ -1,178 +0,0 @@ -package idxfile - -import ( - "bufio" - "bytes" - "errors" - "io" - - "github.com/go-git/go-git/v6/utils/binary" -) - -var ( - // ErrUnsupportedVersion is returned by Decode when the idx file version - // is not supported. - ErrUnsupportedVersion = errors.New("unsupported version") - // ErrMalformedIdxFile is returned by Decode when the idx file is corrupted. - ErrMalformedIdxFile = errors.New("malformed IDX file") -) - -const ( - fanout = 256 -) - -// Decoder reads and decodes idx files from an input stream. -type Decoder struct { - *bufio.Reader -} - -// NewDecoder builds a new idx stream decoder, that reads from r. -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{bufio.NewReader(r)} -} - -// Decode reads from the stream and decode the content into the MemoryIndex struct. -func (d *Decoder) Decode(idx *MemoryIndex) error { - if err := validateHeader(d); err != nil { - return err - } - - flow := []func(*MemoryIndex, io.Reader) error{ - readVersion, - readFanout, - readObjectNames, - readCRC32, - readOffsets, - readChecksums, - } - - for _, f := range flow { - if err := f(idx, d); err != nil { - return err - } - } - - return nil -} - -func validateHeader(r io.Reader) error { - var h = make([]byte, 4) - if _, err := io.ReadFull(r, h); err != nil { - return err - } - - if !bytes.Equal(h, idxHeader) { - return ErrMalformedIdxFile - } - - return nil -} - -func readVersion(idx *MemoryIndex, r io.Reader) error { - v, err := binary.ReadUint32(r) - if err != nil { - return err - } - - if v > VersionSupported { - return ErrUnsupportedVersion - } - - idx.Version = v - return nil -} - -func readFanout(idx *MemoryIndex, r io.Reader) error { - for k := 0; k < fanout; k++ { - n, err := binary.ReadUint32(r) - if err != nil { - return err - } - - idx.Fanout[k] = n - idx.FanoutMapping[k] = noMapping - } - - return nil -} - -func readObjectNames(idx *MemoryIndex, r io.Reader) error { - for k := 0; k < fanout; k++ { - var buckets uint32 - if k == 0 { - buckets = idx.Fanout[k] - } else { - buckets = idx.Fanout[k] - idx.Fanout[k-1] - } - - if buckets == 0 { - continue - } - - idx.FanoutMapping[k] = len(idx.Names) - - nameLen := int(buckets * uint32(idx.idSize())) - bin := make([]byte, nameLen) - if _, err := io.ReadFull(r, bin); err != nil { - return err - } - - idx.Names = append(idx.Names, bin) - idx.Offset32 = append(idx.Offset32, make([]byte, buckets*4)) - idx.CRC32 = append(idx.CRC32, make([]byte, buckets*4)) - } - - return nil -} - -func readCRC32(idx *MemoryIndex, r io.Reader) error { - for k := 0; k < fanout; k++ { - if pos := idx.FanoutMapping[k]; pos != noMapping { - if _, err := io.ReadFull(r, idx.CRC32[pos]); err != nil { - return err - } - } - } - - return nil -} - -func readOffsets(idx *MemoryIndex, r io.Reader) error { - var o64cnt int - for k := 0; k < fanout; k++ { - if pos := idx.FanoutMapping[k]; pos != noMapping { - if _, err := io.ReadFull(r, idx.Offset32[pos]); err != nil { - return err - } - - for p := 0; p < len(idx.Offset32[pos]); p += 4 { - if idx.Offset32[pos][p]&(byte(1)<<7) > 0 { - o64cnt++ - } - } - } - } - - if o64cnt > 0 { - idx.Offset64 = make([]byte, o64cnt*8) - if _, err := io.ReadFull(r, idx.Offset64); err != nil { - return err - } - } - - return nil -} - -func readChecksums(idx *MemoryIndex, r io.Reader) error { - idx.PackfileChecksum.ResetBySize(idx.idSize()) - if _, err := idx.PackfileChecksum.ReadFrom(r); err != nil { - return err - } - - idx.IdxChecksum.ResetBySize(idx.idSize()) - if _, err := idx.IdxChecksum.ReadFrom(r); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/doc.go deleted file mode 100644 index 1e628ab4..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/doc.go +++ /dev/null @@ -1,128 +0,0 @@ -// Package idxfile implements encoding and decoding of packfile idx files. -// -// == Original (version 1) pack-*.idx files have the following format: -// -// - The header consists of 256 4-byte network byte order -// integers. N-th entry of this table records the number of -// objects in the corresponding pack, the first byte of whose -// object name is less than or equal to N. This is called the -// 'first-level fan-out' table. -// -// - The header is followed by sorted 24-byte entries, one entry -// per object in the pack. Each entry is: -// -// 4-byte network byte order integer, recording where the -// object is stored in the packfile as the offset from the -// beginning. -// -// 20-byte object name. -// -// - The file is concluded with a trailer: -// -// A copy of the 20-byte SHA1 checksum at the end of -// corresponding packfile. -// -// 20-byte SHA1-checksum of all of the above. -// -// Pack Idx file: -// -// -- +--------------------------------+ -// fanout | fanout[0] = 2 (for example) |-. -// table +--------------------------------+ | -// | fanout[1] | | -// +--------------------------------+ | -// | fanout[2] | | -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | -// | fanout[255] = total objects |---. -// -- +--------------------------------+ | | -// main | offset | | | -// index | object name 00XXXXXXXXXXXXXXXX | | | -// tab +--------------------------------+ | | -// | offset | | | -// | object name 00XXXXXXXXXXXXXXXX | | | -// +--------------------------------+<+ | -// .-| offset | | -// | | object name 01XXXXXXXXXXXXXXXX | | -// | +--------------------------------+ | -// | | offset | | -// | | object name 01XXXXXXXXXXXXXXXX | | -// | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | -// | | offset | | -// | | object name FFXXXXXXXXXXXXXXXX | | -// --| +--------------------------------+<--+ -// trailer | | packfile checksum | -// | +--------------------------------+ -// | | idxfile checksum | -// | +--------------------------------+ -// .---------. -// | -// Pack file entry: <+ -// -// packed object header: -// 1-byte size extension bit (MSB) -// type (next 3 bit) -// size0 (lower 4-bit) -// n-byte sizeN (as long as MSB is set, each 7-bit) -// size0..sizeN form 4+7+7+..+7 bit integer, size0 -// is the least significant part, and sizeN is the -// most significant part. -// packed object data: -// If it is not DELTA, then deflated bytes (the size above -// is the size before compression). -// If it is REF_DELTA, then -// 20-byte base object name SHA1 (the size above is the -// size of the delta data that follows). -// delta data, deflated. -// If it is OFS_DELTA, then -// n-byte offset (see below) interpreted as a negative -// offset from the type-byte of the header of the -// ofs-delta entry (the size above is the size of -// the delta data that follows). -// delta data, deflated. -// -// offset encoding: -// n bytes with MSB set in all but the last one. -// The offset is then the number constructed by -// concatenating the lower 7 bit of each byte, and -// for n >= 2 adding 2^7 + 2^14 + ... + 2^(7*(n-1)) -// to the result. -// -// == Version 2 pack-*.idx files support packs larger than 4 GiB, and -// have some other reorganizations. They have the format: -// -// - A 4-byte magic number '\377tOc' which is an unreasonable -// fanout[0] value. -// -// - A 4-byte version number (= 2) -// -// - A 256-entry fan-out table just like v1. -// -// - A table of sorted 20-byte SHA1 object names. These are -// packed together without offset values to reduce the cache -// footprint of the binary search for a specific object name. -// -// - A table of 4-byte CRC32 values of the packed object data. -// This is new in v2 so compressed data can be copied directly -// from pack to pack during repacking without undetected -// data corruption. -// -// - A table of 4-byte offset values (in network byte order). -// These are usually 31-bit pack file offsets, but large -// offsets are encoded as an index into the next table with -// the msbit set. -// -// - A table of 8-byte offset entries (empty for pack files less -// than 2 GiB). Pack files are organized with heavily used -// objects toward the front, so most object references should -// not need to refer to this table. -// -// - The same trailer as a v1 pack file: -// -// A copy of the 20-byte SHA1 checksum at the end of -// corresponding packfile. -// -// 20-byte SHA1-checksum of all of the above. -// -// Source: -// https://www.kernel.org/pub/software/scm/git/docs/v1.7.5/technical/pack-format.txt -package idxfile diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/encoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/encoder.go deleted file mode 100644 index f5af3c72..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/encoder.go +++ /dev/null @@ -1,148 +0,0 @@ -package idxfile - -import ( - "crypto" - "io" - - "github.com/go-git/go-git/v6/plumbing/hash" - "github.com/go-git/go-git/v6/utils/binary" -) - -// Encoder writes MemoryIndex structs to an output stream. -type Encoder struct { - io.Writer - hash hash.Hash -} - -// NewEncoder returns a new stream encoder that writes to w. -func NewEncoder(w io.Writer) *Encoder { - // TODO: Support passing an ObjectFormat (sha256) - h := hash.New(crypto.SHA1) - mw := io.MultiWriter(w, h) - return &Encoder{mw, h} -} - -// Encode encodes an MemoryIndex to the encoder writer. -func (e *Encoder) Encode(idx *MemoryIndex) (int, error) { - flow := []func(*MemoryIndex) (int, error){ - e.encodeHeader, - e.encodeFanout, - e.encodeHashes, - e.encodeCRC32, - e.encodeOffsets, - e.encodeChecksums, - } - - sz := 0 - for _, f := range flow { - i, err := f(idx) - sz += i - - if err != nil { - return sz, err - } - } - - return sz, nil -} - -func (e *Encoder) encodeHeader(idx *MemoryIndex) (int, error) { - c, err := e.Write(idxHeader) - if err != nil { - return c, err - } - - return c + 4, binary.WriteUint32(e, idx.Version) -} - -func (e *Encoder) encodeFanout(idx *MemoryIndex) (int, error) { - for _, c := range idx.Fanout { - if err := binary.WriteUint32(e, c); err != nil { - return 0, err - } - } - - return fanout * 4, nil -} - -func (e *Encoder) encodeHashes(idx *MemoryIndex) (int, error) { - var size int - for k := 0; k < fanout; k++ { - pos := idx.FanoutMapping[k] - if pos == noMapping { - continue - } - - n, err := e.Write(idx.Names[pos]) - if err != nil { - return size, err - } - size += n - } - return size, nil -} - -func (e *Encoder) encodeCRC32(idx *MemoryIndex) (int, error) { - var size int - for k := 0; k < fanout; k++ { - pos := idx.FanoutMapping[k] - if pos == noMapping { - continue - } - - n, err := e.Write(idx.CRC32[pos]) - if err != nil { - return size, err - } - - size += n - } - - return size, nil -} - -func (e *Encoder) encodeOffsets(idx *MemoryIndex) (int, error) { - var size int - for k := 0; k < fanout; k++ { - pos := idx.FanoutMapping[k] - if pos == noMapping { - continue - } - - n, err := e.Write(idx.Offset32[pos]) - if err != nil { - return size, err - } - - size += n - } - - if len(idx.Offset64) > 0 { - n, err := e.Write(idx.Offset64) - if err != nil { - return size, err - } - - size += n - } - - return size, nil -} - -func (e *Encoder) encodeChecksums(idx *MemoryIndex) (int, error) { - n1, err := e.Write(idx.PackfileChecksum.Bytes()) - if err != nil { - return 0, err - } - - if _, err := idx.IdxChecksum.Write(e.hash.Sum(nil)[:e.hash.Size()]); err != nil { - return 0, err - } - - n2, err := e.Write(idx.IdxChecksum.Bytes()) - if err != nil { - return 0, err - } - - return n1 + n2, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/idxfile.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/idxfile.go deleted file mode 100644 index 3c507b94..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/idxfile.go +++ /dev/null @@ -1,366 +0,0 @@ -package idxfile - -import ( - "crypto" - "io" - "sort" - "sync" - - encbin "encoding/binary" - - "github.com/go-git/go-git/v6/plumbing" -) - -const ( - // VersionSupported is the only idx version supported. - VersionSupported = 2 - - noMapping = -1 -) - -var ( - idxHeader = []byte{255, 't', 'O', 'c'} -) - -// Index represents an index of a packfile. -type Index interface { - // Contains checks whether the given hash is in the index. - Contains(h plumbing.Hash) (bool, error) - // FindOffset finds the offset in the packfile for the object with - // the given hash. - FindOffset(h plumbing.Hash) (int64, error) - // FindCRC32 finds the CRC32 of the object with the given hash. - FindCRC32(h plumbing.Hash) (uint32, error) - // FindHash finds the hash for the object with the given offset. - FindHash(o int64) (plumbing.Hash, error) - // Count returns the number of entries in the index. - Count() (int64, error) - // Entries returns an iterator to retrieve all index entries. - Entries() (EntryIter, error) - // EntriesByOffset returns an iterator to retrieve all index entries ordered - // by offset. - EntriesByOffset() (EntryIter, error) -} - -// MemoryIndex is the in memory representation of an idx file. -type MemoryIndex struct { - Version uint32 - Fanout [256]uint32 - // FanoutMapping maps the position in the fanout table to the position - // in the Names, Offset32 and CRC32 slices. This improves the memory - // usage by not needing an array with unnecessary empty slots. - FanoutMapping [256]int - Names [][]byte - Offset32 [][]byte - CRC32 [][]byte - Offset64 []byte - PackfileChecksum plumbing.Hash - IdxChecksum plumbing.Hash - - offsetHash map[int64]plumbing.Hash - offsetHashIsFull bool - mu sync.RWMutex - - objectIDSize int -} - -var _ Index = (*MemoryIndex)(nil) - -// NewMemoryIndex returns an instance of a new MemoryIndex. -func NewMemoryIndex(objectIDSize int) *MemoryIndex { - return &MemoryIndex{objectIDSize: objectIDSize} -} - -func (idx *MemoryIndex) findHashIndex(h plumbing.Hash) (int, bool) { - k := idx.FanoutMapping[h.Bytes()[0]] - if k == noMapping { - return 0, false - } - - if len(idx.Names) <= k { - return 0, false - } - - data := idx.Names[k] - high := uint64(len(idx.Offset32[k])) >> 2 - if high == 0 { - return 0, false - } - - low := uint64(0) - for { - mid := (low + high) >> 1 - offset := mid * uint64(idx.idSize()) - - cmp := h.Compare(data[offset : offset+uint64(idx.idSize())]) - if cmp < 0 { - high = mid - } else if cmp == 0 { - return int(mid), true - } else { - low = mid + 1 - } - - if low >= high { - break - } - } - - return 0, false -} - -// Contains implements the Index interface. -func (idx *MemoryIndex) Contains(h plumbing.Hash) (bool, error) { - _, ok := idx.findHashIndex(h) - return ok, nil -} - -// FindOffset implements the Index interface. -func (idx *MemoryIndex) FindOffset(h plumbing.Hash) (int64, error) { - fo := h.Bytes()[0] - if len(idx.FanoutMapping) <= int(fo) { - return 0, plumbing.ErrObjectNotFound - } - - k := idx.FanoutMapping[fo] - i, ok := idx.findHashIndex(h) - if !ok { - return 0, plumbing.ErrObjectNotFound - } - - offset := idx.getOffset(k, i) - - if !idx.offsetHashIsFull { - // Save the offset for reverse lookup - idx.mu.Lock() - if idx.offsetHash == nil { - idx.offsetHash = make(map[int64]plumbing.Hash) - } - idx.offsetHash[int64(offset)] = h - idx.mu.Unlock() - } - - return int64(offset), nil -} - -const isO64Mask = uint64(1) << 31 - -func (idx *MemoryIndex) getOffset(firstLevel, secondLevel int) uint64 { - offset := secondLevel << 2 - ofs := encbin.BigEndian.Uint32(idx.Offset32[firstLevel][offset : offset+4]) - - if (uint64(ofs) & isO64Mask) != 0 { - offset := 8 * (uint64(ofs) & ^isO64Mask) - n := encbin.BigEndian.Uint64(idx.Offset64[offset : offset+8]) - return n - } - - return uint64(ofs) -} - -// FindCRC32 implements the Index interface. -func (idx *MemoryIndex) FindCRC32(h plumbing.Hash) (uint32, error) { - k := idx.FanoutMapping[h.Bytes()[0]] - i, ok := idx.findHashIndex(h) - if !ok { - return 0, plumbing.ErrObjectNotFound - } - - return idx.getCRC32(k, i), nil -} - -func (idx *MemoryIndex) getCRC32(firstLevel, secondLevel int) uint32 { - offset := secondLevel << 2 - return encbin.BigEndian.Uint32(idx.CRC32[firstLevel][offset : offset+4]) -} - -// FindHash implements the Index interface. -func (idx *MemoryIndex) FindHash(o int64) (plumbing.Hash, error) { - var hash plumbing.Hash - var ok bool - - idx.mu.RLock() - if idx.offsetHash != nil { - if hash, ok = idx.offsetHash[o]; ok { - idx.mu.RUnlock() - return hash, nil - } - } - idx.mu.RUnlock() - - // Lazily generate the reverse offset/hash map if required. - if !idx.offsetHashIsFull || idx.offsetHash == nil { - if err := idx.genOffsetHash(); err != nil { - return plumbing.ZeroHash, err - } - - hash, ok = idx.offsetHash[o] - } - - if !ok { - return plumbing.ZeroHash, plumbing.ErrObjectNotFound - } - - return hash, nil -} - -// genOffsetHash generates the offset/hash mapping for reverse search. -func (idx *MemoryIndex) genOffsetHash() error { - defer idx.mu.Unlock() - idx.mu.Lock() - - count, err := idx.Count() - if err != nil { - return err - } - - idx.offsetHash = make(map[int64]plumbing.Hash, count) - idx.offsetHashIsFull = true - - var hash plumbing.Hash - i := uint32(0) - for firstLevel, fanoutValue := range idx.Fanout { - mappedFirstLevel := idx.FanoutMapping[firstLevel] - for secondLevel := uint32(0); i < fanoutValue; i++ { - hash.Write(idx.Names[mappedFirstLevel][secondLevel*uint32(idx.idSize()):]) - offset := int64(idx.getOffset(mappedFirstLevel, int(secondLevel))) - idx.offsetHash[offset] = hash - secondLevel++ - } - } - - return nil -} - -// Count implements the Index interface. -func (idx *MemoryIndex) Count() (int64, error) { - return int64(idx.Fanout[fanout-1]), nil -} - -// Entries implements the Index interface. -func (idx *MemoryIndex) Entries() (EntryIter, error) { - return &idxfileEntryIter{idx, 0, 0, 0}, nil -} - -// EntriesByOffset implements the Index interface. -func (idx *MemoryIndex) EntriesByOffset() (EntryIter, error) { - count, err := idx.Count() - if err != nil { - return nil, err - } - - iter := &idxfileEntryOffsetIter{ - entries: make(entriesByOffset, count), - } - - entries, err := idx.Entries() - if err != nil { - return nil, err - } - - for pos := 0; int64(pos) < count; pos++ { - entry, err := entries.Next() - if err != nil { - return nil, err - } - - iter.entries[pos] = entry - } - - sort.Sort(iter.entries) - - return iter, nil -} - -func (idx *MemoryIndex) idSize() int { - if idx.objectIDSize != 0 { - return idx.objectIDSize - } - return crypto.SHA1.Size() -} - -// EntryIter is an iterator that will return the entries in a packfile index. -type EntryIter interface { - // Next returns the next entry in the packfile index. - Next() (*Entry, error) - // Close closes the iterator. - Close() error -} - -type idxfileEntryIter struct { - idx *MemoryIndex - total int - firstLevel, secondLevel int -} - -func (i *idxfileEntryIter) Next() (*Entry, error) { - for { - if i.firstLevel >= fanout { - return nil, io.EOF - } - - if i.total >= int(i.idx.Fanout[i.firstLevel]) { - i.firstLevel++ - i.secondLevel = 0 - continue - } - - mappedFirstLevel := i.idx.FanoutMapping[i.firstLevel] - entry := new(Entry) - entry.Hash.Write(i.idx.Names[mappedFirstLevel][i.secondLevel*i.idx.idSize():]) - entry.Offset = i.idx.getOffset(mappedFirstLevel, i.secondLevel) - entry.CRC32 = i.idx.getCRC32(mappedFirstLevel, i.secondLevel) - - i.secondLevel++ - i.total++ - - return entry, nil - } -} - -func (i *idxfileEntryIter) Close() error { - i.firstLevel = fanout - return nil -} - -// Entry is the in memory representation of an object entry in the idx file. -type Entry struct { - Hash plumbing.Hash - CRC32 uint32 - Offset uint64 -} - -type idxfileEntryOffsetIter struct { - entries entriesByOffset - pos int -} - -func (i *idxfileEntryOffsetIter) Next() (*Entry, error) { - if i.pos >= len(i.entries) { - return nil, io.EOF - } - - entry := i.entries[i.pos] - i.pos++ - - return entry, nil -} - -func (i *idxfileEntryOffsetIter) Close() error { - i.pos = len(i.entries) + 1 - return nil -} - -type entriesByOffset []*Entry - -func (o entriesByOffset) Len() int { - return len(o) -} - -func (o entriesByOffset) Less(i int, j int) bool { - return o[i].Offset < o[j].Offset -} - -func (o entriesByOffset) Swap(i int, j int) { - o[i], o[j] = o[j], o[i] -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/writer.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/writer.go deleted file mode 100644 index 9d46dc8c..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/idxfile/writer.go +++ /dev/null @@ -1,193 +0,0 @@ -package idxfile - -import ( - "bytes" - "fmt" - "math" - "sort" - "sync" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/utils/binary" -) - -// objects implements sort.Interface and uses hash as sorting key. -type objects []Entry - -// Writer implements a packfile Observer interface and is used to generate -// indexes. -type Writer struct { - m sync.Mutex - - count uint32 - checksum plumbing.Hash - objects objects - offset64 uint32 - finished bool - index *MemoryIndex - added map[plumbing.Hash]struct{} -} - -// Index returns a previously created MemoryIndex or creates a new one if -// needed. -func (w *Writer) Index() (*MemoryIndex, error) { - w.m.Lock() - defer w.m.Unlock() - - if w.index == nil { - return w.createIndex() - } - - return w.index, nil -} - -// Add appends new object data. -func (w *Writer) Add(h plumbing.Hash, pos uint64, crc uint32) { - w.m.Lock() - defer w.m.Unlock() - - if w.added == nil { - w.added = make(map[plumbing.Hash]struct{}) - } - - if _, ok := w.added[h]; !ok { - w.added[h] = struct{}{} - w.objects = append(w.objects, Entry{h, crc, pos}) - } - -} - -func (w *Writer) Finished() bool { - return w.finished -} - -// OnHeader implements packfile.Observer interface. -func (w *Writer) OnHeader(count uint32) error { - w.count = count - w.objects = make(objects, 0, count) - return nil -} - -// OnInflatedObjectHeader implements packfile.Observer interface. -func (w *Writer) OnInflatedObjectHeader(t plumbing.ObjectType, objSize int64, pos int64) error { - return nil -} - -// OnInflatedObjectContent implements packfile.Observer interface. -func (w *Writer) OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, _ []byte) error { - w.Add(h, uint64(pos), crc) - return nil -} - -// OnFooter implements packfile.Observer interface. -func (w *Writer) OnFooter(h plumbing.Hash) error { - w.checksum = h - w.finished = true - _, err := w.createIndex() - - return err -} - -// creatIndex returns a filled MemoryIndex with the information filled by -// the observer callbacks. -func (w *Writer) createIndex() (*MemoryIndex, error) { - if !w.finished { - return nil, fmt.Errorf("the index still hasn't finished building") - } - - idx := new(MemoryIndex) - w.index = idx - - sort.Sort(w.objects) - - // unmap all fans by default - for i := range idx.FanoutMapping { - idx.FanoutMapping[i] = noMapping - } - - buf := new(bytes.Buffer) - - last := -1 - bucket := -1 - for i, o := range w.objects { - fan := o.Hash.Bytes()[0] - - // fill the gaps between fans - for j := last + 1; j < int(fan); j++ { - idx.Fanout[j] = uint32(i) - } - - // update the number of objects for this position - idx.Fanout[fan] = uint32(i + 1) - - // we move from one bucket to another, update counters and allocate - // memory - if last != int(fan) { - bucket++ - idx.FanoutMapping[fan] = bucket - last = int(fan) - - idx.Names = append(idx.Names, make([]byte, 0)) - idx.Offset32 = append(idx.Offset32, make([]byte, 0)) - idx.CRC32 = append(idx.CRC32, make([]byte, 0)) - } - - idx.Names[bucket] = append(idx.Names[bucket], o.Hash.Bytes()...) - - offset := o.Offset - if offset > math.MaxInt32 { - var err error - offset, err = w.addOffset64(offset) - if err != nil { - return nil, err - } - } - - buf.Truncate(0) - if err := binary.WriteUint32(buf, uint32(offset)); err != nil { - return nil, err - } - idx.Offset32[bucket] = append(idx.Offset32[bucket], buf.Bytes()...) - - buf.Truncate(0) - if err := binary.WriteUint32(buf, o.CRC32); err != nil { - return nil, err - } - idx.CRC32[bucket] = append(idx.CRC32[bucket], buf.Bytes()...) - } - - for j := last + 1; j < 256; j++ { - idx.Fanout[j] = uint32(len(w.objects)) - } - - idx.Version = VersionSupported - idx.PackfileChecksum = w.checksum - - return idx, nil -} - -func (w *Writer) addOffset64(pos uint64) (uint64, error) { - buf := new(bytes.Buffer) - if err := binary.WriteUint64(buf, pos); err != nil { - return 0, err - } - - w.index.Offset64 = append(w.index.Offset64, buf.Bytes()...) - index := uint64(w.offset64 | (1 << 31)) - w.offset64++ - - return index, nil -} - -func (o objects) Len() int { - return len(o) -} - -func (o objects) Less(i int, j int) bool { - cmp := o[i].Hash.Compare(o[j].Hash.Bytes()) - return cmp < 0 -} - -func (o objects) Swap(i int, j int) { - o[i], o[j] = o[j], o[i] -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/decoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/index/decoder.go deleted file mode 100644 index 3550b1a8..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/decoder.go +++ /dev/null @@ -1,511 +0,0 @@ -package index - -import ( - "bufio" - "bytes" - "crypto" - "errors" - "io" - - "strconv" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/hash" - "github.com/go-git/go-git/v6/utils/binary" -) - -var ( - // DecodeVersionSupported is the range of supported index versions - DecodeVersionSupported = struct{ Min, Max uint32 }{Min: 2, Max: 4} - - // ErrMalformedSignature is returned by Decode when the index header file is - // malformed - ErrMalformedSignature = errors.New("malformed index signature file") - // ErrInvalidChecksum is returned by Decode if the SHA1 hash mismatch with - // the read content - ErrInvalidChecksum = errors.New("invalid checksum") - // ErrUnknownExtension is returned when an index extension is encountered that is considered mandatory - ErrUnknownExtension = errors.New("unknown extension") -) - -const ( - entryHeaderLength = 62 - entryExtended = 0x4000 - entryValid = 0x8000 - nameMask = 0xfff - intentToAddMask = 1 << 13 - skipWorkTreeMask = 1 << 14 -) - -// A Decoder reads and decodes index files from an input stream. -type Decoder struct { - buf *bufio.Reader - r io.Reader - hash hash.Hash - lastEntry *Entry - - extReader *bufio.Reader -} - -// NewDecoder returns a new decoder that reads from r. -func NewDecoder(r io.Reader) *Decoder { - // TODO: Support passing an ObjectFormat (sha256) - h := hash.New(crypto.SHA1) - buf := bufio.NewReader(r) - return &Decoder{ - buf: buf, - r: io.TeeReader(buf, h), - hash: h, - extReader: bufio.NewReader(nil), - } -} - -// Decode reads the whole index object from its input and stores it in the -// value pointed to by idx. -func (d *Decoder) Decode(idx *Index) error { - var err error - idx.Version, err = validateHeader(d.r) - if err != nil { - return err - } - - entryCount, err := binary.ReadUint32(d.r) - if err != nil { - return err - } - - if err := d.readEntries(idx, int(entryCount)); err != nil { - return err - } - - return d.readExtensions(idx) -} - -func (d *Decoder) readEntries(idx *Index, count int) error { - for i := 0; i < count; i++ { - e, err := d.readEntry(idx) - if err != nil { - return err - } - - d.lastEntry = e - idx.Entries = append(idx.Entries, e) - } - - return nil -} - -func (d *Decoder) readEntry(idx *Index) (*Entry, error) { - e := &Entry{} - - var msec, mnsec, sec, nsec uint32 - var flags uint16 - - flow := []interface{}{ - &sec, &nsec, - &msec, &mnsec, - &e.Dev, - &e.Inode, - &e.Mode, - &e.UID, - &e.GID, - &e.Size, - } - - if err := binary.Read(d.r, flow...); err != nil { - return nil, err - } - - if _, err := e.Hash.ReadFrom(d.r); err != nil { - return nil, err - } - - if err := binary.Read(d.r, &flags); err != nil { - return nil, err - } - - read := entryHeaderLength - - if sec != 0 || nsec != 0 { - e.CreatedAt = time.Unix(int64(sec), int64(nsec)) - } - - if msec != 0 || mnsec != 0 { - e.ModifiedAt = time.Unix(int64(msec), int64(mnsec)) - } - - e.Stage = Stage(flags>>12) & 0x3 - - if flags&entryExtended != 0 { - extended, err := binary.ReadUint16(d.r) - if err != nil { - return nil, err - } - - read += 2 - e.IntentToAdd = extended&intentToAddMask != 0 - e.SkipWorktree = extended&skipWorkTreeMask != 0 - } - - if err := d.readEntryName(idx, e, flags); err != nil { - return nil, err - } - - return e, d.padEntry(idx, e, read) -} - -func (d *Decoder) readEntryName(idx *Index, e *Entry, flags uint16) error { - var name string - var err error - - switch idx.Version { - case 2, 3: - len := flags & nameMask - name, err = d.doReadEntryName(len) - case 4: - name, err = d.doReadEntryNameV4() - default: - return ErrUnsupportedVersion - } - - if err != nil { - return err - } - - e.Name = name - return nil -} - -func (d *Decoder) doReadEntryNameV4() (string, error) { - l, err := binary.ReadVariableWidthInt(d.r) - if err != nil { - return "", err - } - - var base string - if d.lastEntry != nil { - base = d.lastEntry.Name[:len(d.lastEntry.Name)-int(l)] - } - - name, err := binary.ReadUntil(d.r, '\x00') - if err != nil { - return "", err - } - - return base + string(name), nil -} - -func (d *Decoder) doReadEntryName(len uint16) (string, error) { - name := make([]byte, len) - _, err := io.ReadFull(d.r, name) - - return string(name), err -} - -// Index entries are padded out to the next 8 byte alignment -// for historical reasons related to how C Git read the files. -func (d *Decoder) padEntry(idx *Index, e *Entry, read int) error { - if idx.Version == 4 { - return nil - } - - entrySize := read + len(e.Name) - padLen := 8 - entrySize%8 - _, err := io.CopyN(io.Discard, d.r, int64(padLen)) - return err -} - -func (d *Decoder) readExtensions(idx *Index) error { - // TODO: support 'Split index' and 'Untracked cache' extensions, take in - // count that they are not supported by jgit or libgit - - var expected []byte - var peeked []byte - var err error - - // we should always be able to peek for 4 bytes (header) + 4 bytes (extlen) + final hash - // if this fails, we know that we're at the end of the index - peekLen := 4 + 4 + d.hash.Size() - - for { - expected = d.hash.Sum(nil) - peeked, err = d.buf.Peek(peekLen) - if len(peeked) < peekLen { - // there can't be an extension at this point, so let's bail out - break - } - if err != nil { - return err - } - - err = d.readExtension(idx) - if err != nil { - return err - } - } - - return d.readChecksum(expected) -} - -func (d *Decoder) readExtension(idx *Index) error { - var header [4]byte - - if _, err := io.ReadFull(d.r, header[:]); err != nil { - return err - } - - r, err := d.getExtensionReader() - if err != nil { - return err - } - - switch { - case bytes.Equal(header[:], treeExtSignature): - idx.Cache = &Tree{} - d := &treeExtensionDecoder{r} - if err := d.Decode(idx.Cache); err != nil { - return err - } - case bytes.Equal(header[:], resolveUndoExtSignature): - idx.ResolveUndo = &ResolveUndo{} - d := &resolveUndoDecoder{r} - if err := d.Decode(idx.ResolveUndo); err != nil { - return err - } - case bytes.Equal(header[:], endOfIndexEntryExtSignature): - idx.EndOfIndexEntry = &EndOfIndexEntry{} - d := &endOfIndexEntryDecoder{r} - if err := d.Decode(idx.EndOfIndexEntry); err != nil { - return err - } - default: - // See https://git-scm.com/docs/index-format, which says: - // If the first byte is 'A'..'Z' the extension is optional and can be ignored. - if header[0] < 'A' || header[0] > 'Z' { - return ErrUnknownExtension - } - - d := &unknownExtensionDecoder{r} - if err := d.Decode(); err != nil { - return err - } - } - - return nil -} - -func (d *Decoder) getExtensionReader() (*bufio.Reader, error) { - len, err := binary.ReadUint32(d.r) - if err != nil { - return nil, err - } - - d.extReader.Reset(&io.LimitedReader{R: d.r, N: int64(len)}) - return d.extReader, nil -} - -func (d *Decoder) readChecksum(expected []byte) error { - var h plumbing.Hash - - if _, err := h.ReadFrom(d.r); err != nil { - return err - } - - if h.Compare(expected) != 0 { - return ErrInvalidChecksum - } - - return nil -} - -func validateHeader(r io.Reader) (version uint32, err error) { - var s = make([]byte, 4) - if _, err := io.ReadFull(r, s); err != nil { - return 0, err - } - - if !bytes.Equal(s, indexSignature) { - return 0, ErrMalformedSignature - } - - version, err = binary.ReadUint32(r) - if err != nil { - return 0, err - } - - if version < DecodeVersionSupported.Min || version > DecodeVersionSupported.Max { - return 0, ErrUnsupportedVersion - } - - return -} - -type treeExtensionDecoder struct { - r *bufio.Reader -} - -func (d *treeExtensionDecoder) Decode(t *Tree) error { - for { - e, err := d.readEntry() - if err != nil { - if err == io.EOF { - return nil - } - - return err - } - - if e == nil { - continue - } - - t.Entries = append(t.Entries, *e) - } -} - -func (d *treeExtensionDecoder) readEntry() (*TreeEntry, error) { - e := &TreeEntry{} - - path, err := binary.ReadUntil(d.r, '\x00') - if err != nil { - return nil, err - } - - e.Path = string(path) - - count, err := binary.ReadUntil(d.r, ' ') - if err != nil { - return nil, err - } - - i, err := strconv.Atoi(string(count)) - if err != nil { - return nil, err - } - - // An entry can be in an invalidated state and is represented by having a - // negative number in the entry_count field. - if i == -1 { - return nil, nil - } - - e.Entries = i - trees, err := binary.ReadUntil(d.r, '\n') - if err != nil { - return nil, err - } - - i, err = strconv.Atoi(string(trees)) - if err != nil { - return nil, err - } - - e.Trees = i - _, err = e.Hash.ReadFrom(d.r) - if err != nil { - return nil, err - } - return e, nil -} - -type resolveUndoDecoder struct { - r *bufio.Reader -} - -func (d *resolveUndoDecoder) Decode(ru *ResolveUndo) error { - for { - e, err := d.readEntry() - if err != nil { - if err == io.EOF { - return nil - } - - return err - } - - ru.Entries = append(ru.Entries, *e) - } -} - -func (d *resolveUndoDecoder) readEntry() (*ResolveUndoEntry, error) { - e := &ResolveUndoEntry{ - Stages: make(map[Stage]plumbing.Hash), - } - - path, err := binary.ReadUntil(d.r, '\x00') - if err != nil { - return nil, err - } - - e.Path = string(path) - - for i := 0; i < 3; i++ { - if err := d.readStage(e, Stage(i+1)); err != nil { - return nil, err - } - } - - for s := range e.Stages { - var h plumbing.Hash - if _, err := h.ReadFrom(d.r); err != nil { - return nil, err - } - - e.Stages[s] = h - } - - return e, nil -} - -func (d *resolveUndoDecoder) readStage(e *ResolveUndoEntry, s Stage) error { - ascii, err := binary.ReadUntil(d.r, '\x00') - if err != nil { - return err - } - - stage, err := strconv.ParseInt(string(ascii), 8, 64) - if err != nil { - return err - } - - if stage != 0 { - e.Stages[s] = plumbing.ZeroHash - } - - return nil -} - -type endOfIndexEntryDecoder struct { - r *bufio.Reader -} - -func (d *endOfIndexEntryDecoder) Decode(e *EndOfIndexEntry) error { - var err error - e.Offset, err = binary.ReadUint32(d.r) - if err != nil { - return err - } - - _, err = e.Hash.ReadFrom(d.r) - return err -} - -type unknownExtensionDecoder struct { - r *bufio.Reader -} - -func (d *unknownExtensionDecoder) Decode() error { - var buf [1024]byte - - for { - _, err := d.r.Read(buf[:]) - if err == io.EOF { - break - } - if err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/index/doc.go deleted file mode 100644 index 39ae6ad5..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/doc.go +++ /dev/null @@ -1,360 +0,0 @@ -// Package index implements encoding and decoding of index format files. -// -// Git index format -// ================ -// -// == The Git index file has the following format -// -// All binary numbers are in network byte order. Version 2 is described -// here unless stated otherwise. -// -// - A 12-byte header consisting of -// -// 4-byte signature: -// The signature is { 'D', 'I', 'R', 'C' } (stands for "dircache") -// -// 4-byte version number: -// The current supported versions are 2, 3 and 4. -// -// 32-bit number of index entries. -// -// - A number of sorted index entries (see below). -// -// - Extensions -// -// Extensions are identified by signature. Optional extensions can -// be ignored if Git does not understand them. -// -// Git currently supports cached tree and resolve undo extensions. -// -// 4-byte extension signature. If the first byte is 'A'..'Z' the -// extension is optional and can be ignored. -// -// 32-bit size of the extension -// -// Extension data -// -// - 160-bit SHA-1 over the content of the index file before this -// checksum. -// -// == Index entry -// -// Index entries are sorted in ascending order on the name field, -// interpreted as a string of unsigned bytes (i.e. memcmp() order, no -// localization, no special casing of directory separator '/'). Entries -// with the same name are sorted by their stage field. -// -// 32-bit ctime seconds, the last time a file's metadata changed -// this is stat(2) data -// -// 32-bit ctime nanosecond fractions -// this is stat(2) data -// -// 32-bit mtime seconds, the last time a file's data changed -// this is stat(2) data -// -// 32-bit mtime nanosecond fractions -// this is stat(2) data -// -// 32-bit dev -// this is stat(2) data -// -// 32-bit ino -// this is stat(2) data -// -// 32-bit mode, split into (high to low bits) -// -// 4-bit object type -// valid values in binary are 1000 (regular file), 1010 (symbolic link) -// and 1110 (gitlink) -// -// 3-bit unused -// -// 9-bit unix permission. Only 0755 and 0644 are valid for regular files. -// Symbolic links and gitlinks have value 0 in this field. -// -// 32-bit uid -// this is stat(2) data -// -// 32-bit gid -// this is stat(2) data -// -// 32-bit file size -// This is the on-disk size from stat(2), truncated to 32-bit. -// -// 160-bit SHA-1 for the represented object -// -// A 16-bit 'flags' field split into (high to low bits) -// -// 1-bit assume-valid flag -// -// 1-bit extended flag (must be zero in version 2) -// -// 2-bit stage (during merge) -// -// 12-bit name length if the length is less than 0xFFF; otherwise 0xFFF -// is stored in this field. -// -// (Version 3 or later) A 16-bit field, only applicable if the -// "extended flag" above is 1, split into (high to low bits). -// -// 1-bit reserved for future -// -// 1-bit skip-worktree flag (used by sparse checkout) -// -// 1-bit intent-to-add flag (used by "git add -N") -// -// 13-bit unused, must be zero -// -// Entry path name (variable length) relative to top level directory -// (without leading slash). '/' is used as path separator. The special -// path components ".", ".." and ".git" (without quotes) are disallowed. -// Trailing slash is also disallowed. -// -// The exact encoding is undefined, but the '.' and '/' characters -// are encoded in 7-bit ASCII and the encoding cannot contain a NUL -// byte (iow, this is a UNIX pathname). -// -// (Version 4) In version 4, the entry path name is prefix-compressed -// relative to the path name for the previous entry (the very first -// entry is encoded as if the path name for the previous entry is an -// empty string). At the beginning of an entry, an integer N in the -// variable width encoding (the same encoding as the offset is encoded -// for OFS_DELTA pack entries; see pack-format.txt) is stored, followed -// by a NUL-terminated string S. Removing N bytes from the end of the -// path name for the previous entry, and replacing it with the string S -// yields the path name for this entry. -// -// 1-8 nul bytes as necessary to pad the entry to a multiple of eight bytes -// while keeping the name NUL-terminated. -// -// (Version 4) In version 4, the padding after the pathname does not -// exist. -// -// Interpretation of index entries in split index mode is completely -// different. See below for details. -// -// == Extensions -// -// === Cached tree -// -// Cached tree extension contains pre-computed hashes for trees that can -// be derived from the index. It helps speed up tree object generation -// from index for a new commit. -// -// When a path is updated in index, the path must be invalidated and -// removed from tree cache. -// -// The signature for this extension is { 'T', 'R', 'E', 'E' }. -// -// A series of entries fill the entire extension; each of which -// consists of: -// -// - NUL-terminated path component (relative to its parent directory); -// -// - ASCII decimal number of entries in the index that is covered by the -// tree this entry represents (entry_count); -// -// - A space (ASCII 32); -// -// - ASCII decimal number that represents the number of subtrees this -// tree has; -// -// - A newline (ASCII 10); and -// -// - 160-bit object name for the object that would result from writing -// this span of index as a tree. -// -// An entry can be in an invalidated state and is represented by having -// a negative number in the entry_count field. In this case, there is no -// object name and the next entry starts immediately after the newline. -// When writing an invalid entry, -1 should always be used as entry_count. -// -// The entries are written out in the top-down, depth-first order. The -// first entry represents the root level of the repository, followed by the -// first subtree--let's call this A--of the root level (with its name -// relative to the root level), followed by the first subtree of A (with -// its name relative to A), ... -// -// === Resolve undo -// -// A conflict is represented in the index as a set of higher stage entries. -// When a conflict is resolved (e.g. with "git add path"), these higher -// stage entries will be removed and a stage-0 entry with proper resolution -// is added. -// -// When these higher stage entries are removed, they are saved in the -// resolve undo extension, so that conflicts can be recreated (e.g. with -// "git checkout -m"), in case users want to redo a conflict resolution -// from scratch. -// -// The signature for this extension is { 'R', 'E', 'U', 'C' }. -// -// A series of entries fill the entire extension; each of which -// consists of: -// -// - NUL-terminated pathname the entry describes (relative to the root of -// the repository, i.e. full pathname); -// -// - Three NUL-terminated ASCII octal numbers, entry mode of entries in -// stage 1 to 3 (a missing stage is represented by "0" in this field); -// and -// -// - At most three 160-bit object names of the entry in stages from 1 to 3 -// (nothing is written for a missing stage). -// -// === Split index -// -// In split index mode, the majority of index entries could be stored -// in a separate file. This extension records the changes to be made on -// top of that to produce the final index. -// -// The signature for this extension is { 'l', 'i', 'n', 'k' }. -// -// The extension consists of: -// -// - 160-bit SHA-1 of the shared index file. The shared index file path -// is $GIT_DIR/sharedindex.. If all 160 bits are zero, the -// index does not require a shared index file. -// -// - An ewah-encoded delete bitmap, each bit represents an entry in the -// shared index. If a bit is set, its corresponding entry in the -// shared index will be removed from the final index. Note, because -// a delete operation changes index entry positions, but we do need -// original positions in replace phase, it's best to just mark -// entries for removal, then do a mass deletion after replacement. -// -// - An ewah-encoded replace bitmap, each bit represents an entry in -// the shared index. If a bit is set, its corresponding entry in the -// shared index will be replaced with an entry in this index -// file. All replaced entries are stored in sorted order in this -// index. The first "1" bit in the replace bitmap corresponds to the -// first index entry, the second "1" bit to the second entry and so -// on. Replaced entries may have empty path names to save space. -// -// The remaining index entries after replaced ones will be added to the -// final index. These added entries are also sorted by entry name then -// stage. -// -// == Untracked cache -// -// Untracked cache saves the untracked file list and necessary data to -// verify the cache. The signature for this extension is { 'U', 'N', -// 'T', 'R' }. -// -// The extension starts with -// -// - A sequence of NUL-terminated strings, preceded by the size of the -// sequence in variable width encoding. Each string describes the -// environment where the cache can be used. -// -// - Stat data of $GIT_DIR/info/exclude. See "Index entry" section from -// ctime field until "file size". -// -// - Stat data of plumbing.excludesfile -// -// - 32-bit dir_flags (see struct dir_struct) -// -// - 160-bit SHA-1 of $GIT_DIR/info/exclude. Null SHA-1 means the file -// does not exist. -// -// - 160-bit SHA-1 of plumbing.excludesfile. Null SHA-1 means the file does -// not exist. -// -// - NUL-terminated string of per-dir exclude file name. This usually -// is ".gitignore". -// -// - The number of following directory blocks, variable width -// encoding. If this number is zero, the extension ends here with a -// following NUL. -// -// - A number of directory blocks in depth-first-search order, each -// consists of -// -// - The number of untracked entries, variable width encoding. -// -// - The number of sub-directory blocks, variable width encoding. -// -// - The directory name terminated by NUL. -// -// - A number of untracked file/dir names terminated by NUL. -// -// The remaining data of each directory block is grouped by type: -// -// - An ewah bitmap, the n-th bit marks whether the n-th directory has -// valid untracked cache entries. -// -// - An ewah bitmap, the n-th bit records "check-only" bit of -// read_directory_recursive() for the n-th directory. -// -// - An ewah bitmap, the n-th bit indicates whether SHA-1 and stat data -// is valid for the n-th directory and exists in the next data. -// -// - An array of stat data. The n-th data corresponds with the n-th -// "one" bit in the previous ewah bitmap. -// -// - An array of SHA-1. The n-th SHA-1 corresponds with the n-th "one" bit -// in the previous ewah bitmap. -// -// - One NUL. -// -// == File System Monitor cache -// -// The file system monitor cache tracks files for which the core.fsmonitor -// hook has told us about changes. The signature for this extension is -// { 'F', 'S', 'M', 'N' }. -// -// The extension starts with -// -// - 32-bit version number: the current supported version is 1. -// -// - 64-bit time: the extension data reflects all changes through the given -// time which is stored as the nanoseconds elapsed since midnight, -// January 1, 1970. -// -// - 32-bit bitmap size: the size of the CE_FSMONITOR_VALID bitmap. -// -// - An ewah bitmap, the n-th bit indicates whether the n-th index entry -// is not CE_FSMONITOR_VALID. -// -// == End of Index Entry -// -// The End of Index Entry (EOIE) is used to locate the end of the variable -// length index entries and the beginning of the extensions. Code can take -// advantage of this to quickly locate the index extensions without having -// to parse through all of the index entries. -// -// Because it must be able to be loaded before the variable length cache -// entries and other index extensions, this extension must be written last. -// The signature for this extension is { 'E', 'O', 'I', 'E' }. -// -// The extension consists of: -// -// - 32-bit offset to the end of the index entries -// -// - 160-bit SHA-1 over the extension types and their sizes (but not -// their contents). E.g. if we have "TREE" extension that is N-bytes -// long, "REUC" extension that is M-bytes long, followed by "EOIE", -// then the hash would be: -// -// SHA-1("TREE" + + -// "REUC" + ) -// -// == Index Entry Offset Table -// -// The Index Entry Offset Table (IEOT) is used to help address the CPU -// cost of loading the index by enabling multi-threading the process of -// converting cache entries from the on-disk format to the in-memory format. -// The signature for this extension is { 'I', 'E', 'O', 'T' }. -// -// The extension consists of: -// -// - 32-bit version (currently 1) -// -// - A number of index offset entries each consisting of: -// -// - 32-bit offset from the beginning of the file to the first cache entry -// in this block of entries. -// -// - 32-bit count of cache entries in this blockpackage index -package index diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/encoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/index/encoder.go deleted file mode 100644 index 5bb21c4d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/encoder.go +++ /dev/null @@ -1,240 +0,0 @@ -package index - -import ( - "bytes" - "crypto" - "errors" - "fmt" - "io" - "path" - "sort" - "strings" - "time" - - "github.com/go-git/go-git/v6/plumbing/hash" - "github.com/go-git/go-git/v6/utils/binary" -) - -var ( - // EncodeVersionSupported is the range of supported index versions - EncodeVersionSupported uint32 = 4 - - // ErrInvalidTimestamp is returned by Encode if a Index with a Entry with - // negative timestamp values - ErrInvalidTimestamp = errors.New("negative timestamps are not allowed") -) - -// An Encoder writes an Index to an output stream. -type Encoder struct { - w io.Writer - hash hash.Hash - lastEntry *Entry -} - -// NewEncoder returns a new encoder that writes to w. -func NewEncoder(w io.Writer) *Encoder { - // TODO: Support passing an ObjectFormat (sha256) - h := hash.New(crypto.SHA1) - mw := io.MultiWriter(w, h) - return &Encoder{mw, h, nil} -} - -// Encode writes the Index to the stream of the encoder. -func (e *Encoder) Encode(idx *Index) error { - return e.encode(idx, true) -} - -func (e *Encoder) encode(idx *Index, footer bool) error { - // TODO: support extensions - if idx.Version > EncodeVersionSupported { - return ErrUnsupportedVersion - } - - if err := e.encodeHeader(idx); err != nil { - return err - } - - if err := e.encodeEntries(idx); err != nil { - return err - } - - if footer { - return e.encodeFooter() - } - return nil -} - -func (e *Encoder) encodeHeader(idx *Index) error { - return binary.Write(e.w, - indexSignature, - idx.Version, - uint32(len(idx.Entries)), - ) -} - -func (e *Encoder) encodeEntries(idx *Index) error { - sort.Sort(byName(idx.Entries)) - - for _, entry := range idx.Entries { - if err := e.encodeEntry(idx, entry); err != nil { - return err - } - entryLength := entryHeaderLength - if entry.IntentToAdd || entry.SkipWorktree { - entryLength += 2 - } - - wrote := entryLength + len(entry.Name) - if err := e.padEntry(idx, wrote); err != nil { - return err - } - } - - return nil -} - -func (e *Encoder) encodeEntry(idx *Index, entry *Entry) error { - sec, nsec, err := e.timeToUint32(&entry.CreatedAt) - if err != nil { - return err - } - - msec, mnsec, err := e.timeToUint32(&entry.ModifiedAt) - if err != nil { - return err - } - - flags := uint16(entry.Stage&0x3) << 12 - if l := len(entry.Name); l < nameMask { - flags |= uint16(l) - } else { - flags |= nameMask - } - - flow := []interface{}{ - sec, nsec, - msec, mnsec, - entry.Dev, - entry.Inode, - entry.Mode, - entry.UID, - entry.GID, - entry.Size, - entry.Hash.Bytes(), - } - - flagsFlow := []interface{}{flags} - - if entry.IntentToAdd || entry.SkipWorktree { - var extendedFlags uint16 - - if entry.IntentToAdd { - extendedFlags |= intentToAddMask - } - if entry.SkipWorktree { - extendedFlags |= skipWorkTreeMask - } - - flagsFlow = []interface{}{flags | entryExtended, extendedFlags} - } - - flow = append(flow, flagsFlow...) - - if err := binary.Write(e.w, flow...); err != nil { - return err - } - - switch idx.Version { - case 2, 3: - err = e.encodeEntryName(entry) - case 4: - err = e.encodeEntryNameV4(entry) - default: - err = ErrUnsupportedVersion - } - - return err -} - -func (e *Encoder) encodeEntryName(entry *Entry) error { - return binary.Write(e.w, []byte(entry.Name)) -} - -func (e *Encoder) encodeEntryNameV4(entry *Entry) error { - name := entry.Name - l := 0 - if e.lastEntry != nil { - dir := path.Dir(e.lastEntry.Name) + "/" - if strings.HasPrefix(entry.Name, dir) { - l = len(e.lastEntry.Name) - len(dir) - name = strings.TrimPrefix(entry.Name, dir) - } else { - l = len(e.lastEntry.Name) - } - } - - e.lastEntry = entry - - err := binary.WriteVariableWidthInt(e.w, int64(l)) - if err != nil { - return err - } - - return binary.Write(e.w, []byte(name+string('\x00'))) -} - -func (e *Encoder) encodeRawExtension(signature string, data []byte) error { - if len(signature) != 4 { - return fmt.Errorf("invalid signature length") - } - - _, err := e.w.Write([]byte(signature)) - if err != nil { - return err - } - - err = binary.WriteUint32(e.w, uint32(len(data))) - if err != nil { - return err - } - - _, err = e.w.Write(data) - if err != nil { - return err - } - - return nil -} - -func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) { - if t.IsZero() { - return 0, 0, nil - } - - if t.Unix() < 0 || t.UnixNano() < 0 { - return 0, 0, ErrInvalidTimestamp - } - - return uint32(t.Unix()), uint32(t.Nanosecond()), nil -} - -func (e *Encoder) padEntry(idx *Index, wrote int) error { - if idx.Version == 4 { - return nil - } - - padLen := 8 - wrote%8 - - _, err := e.w.Write(bytes.Repeat([]byte{'\x00'}, padLen)) - return err -} - -func (e *Encoder) encodeFooter() error { - return binary.Write(e.w, e.hash.Sum(nil)) -} - -type byName []*Entry - -func (l byName) Len() int { return len(l) } -func (l byName) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l byName) Less(i, j int) bool { return l[i].Name < l[j].Name } diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/index.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/index/index.go deleted file mode 100644 index c4894f1b..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/index.go +++ /dev/null @@ -1,231 +0,0 @@ -package index - -import ( - "bytes" - "errors" - "fmt" - "path/filepath" - "strings" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" -) - -var ( - // ErrUnsupportedVersion is returned by Decode when the index file version - // is not supported. - ErrUnsupportedVersion = errors.New("unsupported version") - // ErrEntryNotFound is returned by Index.Entry, if an entry is not found. - ErrEntryNotFound = errors.New("entry not found") - - indexSignature = []byte{'D', 'I', 'R', 'C'} - treeExtSignature = []byte{'T', 'R', 'E', 'E'} - resolveUndoExtSignature = []byte{'R', 'E', 'U', 'C'} - endOfIndexEntryExtSignature = []byte{'E', 'O', 'I', 'E'} -) - -// Stage during merge -type Stage int - -const ( - // Merged is the default stage, fully merged - Merged Stage = 1 - // AncestorMode is the base revision - AncestorMode Stage = 1 - // OurMode is the first tree revision, ours - OurMode Stage = 2 - // TheirMode is the second tree revision, theirs - TheirMode Stage = 3 -) - -// Index contains the information about which objects are currently checked out -// in the worktree, having information about the working files. Changes in -// worktree are detected using this Index. The Index is also used during merges -type Index struct { - // Version is index version - Version uint32 - // Entries collection of entries represented by this Index. The order of - // this collection is not guaranteed - Entries []*Entry - // Cache represents the 'Cached tree' extension - Cache *Tree - // ResolveUndo represents the 'Resolve undo' extension - ResolveUndo *ResolveUndo - // EndOfIndexEntry represents the 'End of Index Entry' extension - EndOfIndexEntry *EndOfIndexEntry -} - -// Add creates a new Entry and returns it. The caller should first check that -// another entry with the same path does not exist. -func (i *Index) Add(path string) *Entry { - e := &Entry{ - Name: filepath.ToSlash(path), - } - - i.Entries = append(i.Entries, e) - return e -} - -// Entry returns the entry that match the given path, if any. -func (i *Index) Entry(path string) (*Entry, error) { - path = filepath.ToSlash(path) - for _, e := range i.Entries { - if e.Name == path { - return e, nil - } - } - - return nil, ErrEntryNotFound -} - -// Remove remove the entry that match the give path and returns deleted entry. -func (i *Index) Remove(path string) (*Entry, error) { - path = filepath.ToSlash(path) - for index, e := range i.Entries { - if e.Name == path { - i.Entries = append(i.Entries[:index], i.Entries[index+1:]...) - return e, nil - } - } - - return nil, ErrEntryNotFound -} - -// Glob returns the all entries matching pattern or nil if there is no matching -// entry. The syntax of patterns is the same as in filepath.Glob. -func (i *Index) Glob(pattern string) (matches []*Entry, err error) { - pattern = filepath.ToSlash(pattern) - for _, e := range i.Entries { - m, err := match(pattern, e.Name) - if err != nil { - return nil, err - } - - if m { - matches = append(matches, e) - } - } - - return -} - -// String is equivalent to `git ls-files --stage --debug` -func (i *Index) String() string { - buf := bytes.NewBuffer(nil) - for _, e := range i.Entries { - buf.WriteString(e.String()) - } - - return buf.String() -} - -// Entry represents a single file (or stage of a file) in the cache. An entry -// represents exactly one stage of a file. If a file path is unmerged then -// multiple Entry instances may appear for the same path name. -type Entry struct { - // Hash is the SHA1 of the represented file - Hash plumbing.Hash - // Name is the Entry path name relative to top level directory - Name string - // CreatedAt time when the tracked path was created - CreatedAt time.Time - // ModifiedAt time when the tracked path was changed - ModifiedAt time.Time - // Dev and Inode of the tracked path - Dev, Inode uint32 - // Mode of the path - Mode filemode.FileMode - // UID and GID, userid and group id of the owner - UID, GID uint32 - // Size is the length in bytes for regular files - Size uint32 - // Stage on a merge is defines what stage is representing this entry - // https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging - Stage Stage - // SkipWorktree used in sparse checkouts - // https://git-scm.com/docs/git-read-tree#_sparse_checkout - SkipWorktree bool - // IntentToAdd record only the fact that the path will be added later - // https://git-scm.com/docs/git-add ("git add -N") - IntentToAdd bool -} - -func (e Entry) String() string { - buf := bytes.NewBuffer(nil) - - fmt.Fprintf(buf, "%06o %s %d\t%s\n", e.Mode, e.Hash, e.Stage, e.Name) - fmt.Fprintf(buf, " ctime: %d:%d\n", e.CreatedAt.Unix(), e.CreatedAt.Nanosecond()) - fmt.Fprintf(buf, " mtime: %d:%d\n", e.ModifiedAt.Unix(), e.ModifiedAt.Nanosecond()) - fmt.Fprintf(buf, " dev: %d\tino: %d\n", e.Dev, e.Inode) - fmt.Fprintf(buf, " uid: %d\tgid: %d\n", e.UID, e.GID) - fmt.Fprintf(buf, " size: %d\tflags: %x\n", e.Size, 0) - - return buf.String() -} - -// Tree contains pre-computed hashes for trees that can be derived from the -// index. It helps speed up tree object generation from index for a new commit. -type Tree struct { - Entries []TreeEntry -} - -// TreeEntry entry of a cached Tree -type TreeEntry struct { - // Path component (relative to its parent directory) - Path string - // Entries is the number of entries in the index that is covered by the tree - // this entry represents. - Entries int - // Trees is the number that represents the number of subtrees this tree has - Trees int - // Hash object name for the object that would result from writing this span - // of index as a tree. - Hash plumbing.Hash -} - -// ResolveUndo is used when a conflict is resolved (e.g. with "git add path"), -// these higher stage entries are removed and a stage-0 entry with proper -// resolution is added. When these higher stage entries are removed, they are -// saved in the resolve undo extension. -type ResolveUndo struct { - Entries []ResolveUndoEntry -} - -// ResolveUndoEntry contains the information about a conflict when is resolved -type ResolveUndoEntry struct { - Path string - Stages map[Stage]plumbing.Hash -} - -// EndOfIndexEntry is the End of Index Entry (EOIE) is used to locate the end of -// the variable length index entries and the beginning of the extensions. Code -// can take advantage of this to quickly locate the index extensions without -// having to parse through all of the index entries. -// -// Because it must be able to be loaded before the variable length cache -// entries and other index extensions, this extension must be written last. -type EndOfIndexEntry struct { - // Offset to the end of the index entries - Offset uint32 - // Hash is a SHA-1 over the extension types and their sizes (but not - // their contents). - Hash plumbing.Hash -} - -// SkipUnless applies patterns in the form of A, A/B, A/B/C -// to the index to prevent the files from being checked out -func (i *Index) SkipUnless(patterns []string) { - for _, e := range i.Entries { - var include bool - for _, pattern := range patterns { - if strings.HasPrefix(e.Name, pattern) { - include = true - break - } - } - if !include { - e.SkipWorktree = true - } - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/match.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/index/match.go deleted file mode 100644 index 2891d7d3..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/index/match.go +++ /dev/null @@ -1,186 +0,0 @@ -package index - -import ( - "path/filepath" - "runtime" - "unicode/utf8" -) - -// match is filepath.Match with support to match fullpath and not only filenames -// code from: -// https://github.com/golang/go/blob/39852bf4cce6927e01d0136c7843f65a801738cb/src/path/filepath/match.go#L44-L224 -func match(pattern, name string) (matched bool, err error) { -Pattern: - for len(pattern) > 0 { - var star bool - var chunk string - star, chunk, pattern = scanChunk(pattern) - - // Look for match at current position. - t, ok, err := matchChunk(chunk, name) - // if we're the last chunk, make sure we've exhausted the name - // otherwise we'll give a false result even if we could still match - // using the star - if ok && (len(t) == 0 || len(pattern) > 0) { - name = t - continue - } - if err != nil { - return false, err - } - if star { - // Look for match skipping i+1 bytes. - // Cannot skip /. - for i := 0; i < len(name); i++ { - t, ok, err := matchChunk(chunk, name[i+1:]) - if ok { - // if we're the last chunk, make sure we exhausted the name - if len(pattern) == 0 && len(t) > 0 { - continue - } - name = t - continue Pattern - } - if err != nil { - return false, err - } - } - } - return false, nil - } - return len(name) == 0, nil -} - -// scanChunk gets the next segment of pattern, which is a non-star string -// possibly preceded by a star. -func scanChunk(pattern string) (star bool, chunk, rest string) { - for len(pattern) > 0 && pattern[0] == '*' { - pattern = pattern[1:] - star = true - } - inrange := false - var i int -Scan: - for i = 0; i < len(pattern); i++ { - switch pattern[i] { - case '\\': - if runtime.GOOS != "windows" { - // error check handled in matchChunk: bad pattern. - if i+1 < len(pattern) { - i++ - } - } - case '[': - inrange = true - case ']': - inrange = false - case '*': - if !inrange { - break Scan - } - } - } - return star, pattern[0:i], pattern[i:] -} - -// matchChunk checks whether chunk matches the beginning of s. -// If so, it returns the remainder of s (after the match). -// Chunk is all single-character operators: literals, char classes, and ?. -func matchChunk(chunk, s string) (rest string, ok bool, err error) { - for len(chunk) > 0 { - if len(s) == 0 { - return - } - switch chunk[0] { - case '[': - // character class - r, n := utf8.DecodeRuneInString(s) - s = s[n:] - chunk = chunk[1:] - // We can't end right after '[', we're expecting at least - // a closing bracket and possibly a caret. - if len(chunk) == 0 { - err = filepath.ErrBadPattern - return - } - // possibly negated - negated := chunk[0] == '^' - if negated { - chunk = chunk[1:] - } - // parse all ranges - match := false - nrange := 0 - for { - if len(chunk) > 0 && chunk[0] == ']' && nrange > 0 { - chunk = chunk[1:] - break - } - var lo, hi rune - if lo, chunk, err = getEsc(chunk); err != nil { - return - } - hi = lo - if chunk[0] == '-' { - if hi, chunk, err = getEsc(chunk[1:]); err != nil { - return - } - } - if lo <= r && r <= hi { - match = true - } - nrange++ - } - if match == negated { - return - } - - case '?': - _, n := utf8.DecodeRuneInString(s) - s = s[n:] - chunk = chunk[1:] - - case '\\': - if runtime.GOOS != "windows" { - chunk = chunk[1:] - if len(chunk) == 0 { - err = filepath.ErrBadPattern - return - } - } - fallthrough - - default: - if chunk[0] != s[0] { - return - } - s = s[1:] - chunk = chunk[1:] - } - } - return s, true, nil -} - -// getEsc gets a possibly-escaped character from chunk, for a character class. -func getEsc(chunk string) (r rune, nchunk string, err error) { - if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' { - err = filepath.ErrBadPattern - return - } - if chunk[0] == '\\' && runtime.GOOS != "windows" { - chunk = chunk[1:] - if len(chunk) == 0 { - err = filepath.ErrBadPattern - return - } - } - r, n := utf8.DecodeRuneInString(chunk) - if r == utf8.RuneError && n == 1 { - err = filepath.ErrBadPattern - } - nchunk = chunk[n:] - if len(nchunk) == 0 { - err = filepath.ErrBadPattern - } - return -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/doc.go deleted file mode 100644 index a7145160..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package objfile implements encoding and decoding of object files. -package objfile diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/reader.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/reader.go deleted file mode 100644 index 9accb105..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/reader.go +++ /dev/null @@ -1,123 +0,0 @@ -package objfile - -import ( - "errors" - "io" - "strconv" - - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/utils/sync" -) - -var ( - ErrClosed = errors.New("objfile: already closed") - ErrHeader = errors.New("objfile: invalid header") - ErrNegativeSize = errors.New("objfile: negative object size") -) - -// Reader reads and decodes compressed objfile data from a provided io.Reader. -// Reader implements io.ReadCloser. Close should be called when finished with -// the Reader. Close will not close the underlying io.Reader. -type Reader struct { - multi io.Reader - zlib io.Reader - zlibref sync.ZLibReader - hasher plumbing.Hasher - closed bool -} - -// NewReader returns a new Reader reading from r. -func NewReader(r io.Reader) (*Reader, error) { - zlib, err := sync.GetZlibReader(r) - if err != nil { - return nil, packfile.ErrZLib.AddDetails(err.Error()) - } - - return &Reader{ - zlib: zlib.Reader, - zlibref: zlib, - }, nil -} - -// Header reads the type and the size of object, and prepares the reader for read -func (r *Reader) Header() (t plumbing.ObjectType, size int64, err error) { - var raw []byte - raw, err = r.readUntil(' ') - if err != nil { - return - } - - t, err = plumbing.ParseObjectType(string(raw)) - if err != nil { - return - } - - raw, err = r.readUntil(0) - if err != nil { - return - } - - size, err = strconv.ParseInt(string(raw), 10, 64) - if err != nil { - err = ErrHeader - return - } - - defer r.prepareForRead(t, size) - return -} - -// readSlice reads one byte at a time from r until it encounters delim or an -// error. -func (r *Reader) readUntil(delim byte) ([]byte, error) { - var buf [1]byte - value := make([]byte, 0, 16) - for { - if n, err := r.zlib.Read(buf[:]); err != nil && (err != io.EOF || n == 0) { - if err == io.EOF { - return nil, ErrHeader - } - return nil, err - } - - if buf[0] == delim { - return value, nil - } - - value = append(value, buf[0]) - } -} - -func (r *Reader) prepareForRead(t plumbing.ObjectType, size int64) { - r.hasher = plumbing.NewHasher(format.SHA1, t, size) - r.multi = io.TeeReader(r.zlib, r.hasher) -} - -// Read reads len(p) bytes into p from the object data stream. It returns -// the number of bytes read (0 <= n <= len(p)) and any error encountered. Even -// if Read returns n < len(p), it may use all of p as scratch space during the -// call. -// -// If Read encounters the end of the data stream it will return err == io.EOF, -// either in the current call if n > 0 or in a subsequent call. -func (r *Reader) Read(p []byte) (n int, err error) { - return r.multi.Read(p) -} - -// Hash returns the hash of the object data stream that has been read so far. -func (r *Reader) Hash() plumbing.Hash { - return r.hasher.Sum() -} - -// Close releases any resources consumed by the Reader. Calling Close does not -// close the wrapped io.Reader originally passed to NewReader. -func (r *Reader) Close() error { - if r.closed { - return nil - } - r.closed = true - sync.PutZlibReader(r.zlibref) - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/writer.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/writer.go deleted file mode 100644 index 45159b07..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/objfile/writer.go +++ /dev/null @@ -1,121 +0,0 @@ -package objfile - -import ( - "compress/zlib" - "errors" - "io" - "strconv" - - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/utils/sync" -) - -var ErrOverflow = errors.New("objfile: declared data length exceeded (overflow)") - -// Writer writes and encodes data in compressed objfile format to a provided -// io.Writer. Close should be called when finished with the Writer. Close will -// not close the underlying io.Writer. -type Writer struct { - raw io.Writer - hasher plumbing.Hasher - multi io.Writer - zlib *zlib.Writer - - closed bool - pending int64 // number of unwritten bytes - - closeErr error -} - -// NewWriter returns a new Writer writing to w. -// -// The returned Writer implements io.WriteCloser. Close should be called when -// finished with the Writer. Close will not close the underlying io.Writer. -func NewWriter(w io.Writer) *Writer { - zlib := sync.GetZlibWriter(w) - return &Writer{ - raw: w, - zlib: zlib, - } -} - -// WriteHeader writes the type and the size and prepares to accept the object's -// contents. If an invalid t is provided, plumbing.ErrInvalidType is returned. If a -// negative size is provided, ErrNegativeSize is returned. -func (w *Writer) WriteHeader(t plumbing.ObjectType, size int64) error { - if !t.Valid() { - return plumbing.ErrInvalidType - } - if size < 0 { - return ErrNegativeSize - } - - b := t.Bytes() - b = append(b, ' ') - b = append(b, []byte(strconv.FormatInt(size, 10))...) - b = append(b, 0) - - defer w.prepareForWrite(t, size) - _, err := w.zlib.Write(b) - - return err -} - -func (w *Writer) prepareForWrite(t plumbing.ObjectType, size int64) { - w.pending = size - - w.hasher = plumbing.NewHasher(format.SHA1, t, size) - w.multi = io.MultiWriter(w.zlib, w.hasher) -} - -// Write writes the object's contents. Write returns the error ErrOverflow if -// more than size bytes are written after WriteHeader. -func (w *Writer) Write(p []byte) (n int, err error) { - if w.closed { - return 0, ErrClosed - } - - overwrite := false - if int64(len(p)) > w.pending { - p = p[0:w.pending] - overwrite = true - } - - n, err = w.multi.Write(p) - w.pending -= int64(n) - if err == nil && overwrite { - err = ErrOverflow - return - } - - return -} - -// Hash returns the hash of the object data stream that has been written so far. -// It can be called before or after Close. -func (w *Writer) Hash() plumbing.Hash { - return w.hasher.Sum() // Not yet closed, return hash of data written so far -} - -// Close releases any resources consumed by the Writer. -// -// Calling Close does not close the wrapped io.Writer originally passed to -// NewWriter. -// -// It returns an error, if any. Close will return the same error if called -// multiple times. -func (w *Writer) Close() error { - if w.closed { - return w.closeErr - } - - defer sync.PutZlibWriter(w.zlib) - if err := w.zlib.Close(); err != nil { - w.closeErr = err - return err - } - - w.closed = true - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/common.go deleted file mode 100644 index 647357ac..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/common.go +++ /dev/null @@ -1,63 +0,0 @@ -package packfile - -import ( - "io" - "time" - - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/trace" -) - -var signature = []byte{'P', 'A', 'C', 'K'} - -const ( - // VersionSupported is the packfile version supported by this package - VersionSupported uint32 = 2 - - firstLengthBits = uint8(4) // the first byte into object header has 4 bits to store the length - lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length - maskFirstLength = 15 // 0000 1111 - maskContinue = 0x80 // 1000 0000 - maskLength = uint8(127) // 0111 1111 - maskType = uint8(112) // 0111 0000 -) - -// UpdateObjectStorage updates the storer with the objects in the given -// packfile. -func UpdateObjectStorage(s storer.Storer, packfile io.Reader) error { - start := time.Now() - defer func() { - trace.Performance.Printf("performance: %.9f s: update_obj_storage", time.Since(start).Seconds()) - }() - - if pw, ok := s.(storer.PackfileWriter); ok { - return WritePackfileToObjectStorage(pw, packfile) - } - - p := NewParser(packfile, WithStorage(s)) - - _, err := p.Parse() - return err -} - -// WritePackfileToObjectStorage writes all the packfile objects into the given -// object storage. -func WritePackfileToObjectStorage( - sw storer.PackfileWriter, - packfile io.Reader, -) (err error) { - w, err := sw.PackfileWriter() - if err != nil { - return err - } - - defer ioutil.CheckClose(w, &err) - - n, err := ioutil.CopyBufferPool(w, packfile) - if err == nil && n == 0 { - return ErrEmptyPackfile - } - - return err -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_index.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_index.go deleted file mode 100644 index a60ec0b2..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_index.go +++ /dev/null @@ -1,295 +0,0 @@ -package packfile - -const blksz = 16 -const maxChainLength = 64 - -// deltaIndex is a modified version of JGit's DeltaIndex adapted to our current -// design. -type deltaIndex struct { - table []int - entries []int - mask int -} - -func (idx *deltaIndex) init(buf []byte) { - scanner := newDeltaIndexScanner(buf, len(buf)) - idx.mask = scanner.mask - idx.table = scanner.table - idx.entries = make([]int, countEntries(scanner)+1) - idx.copyEntries(scanner) -} - -// findMatch returns the offset of src where the block starting at tgtOffset -// is and the length of the match. A length of 0 means there was no match. A -// length of -1 means the src length is lower than the blksz and whatever -// other positive length is the length of the match in bytes. -func (idx *deltaIndex) findMatch(src, tgt []byte, tgtOffset int) (srcOffset, l int) { - if len(tgt) < tgtOffset+s { - return 0, len(tgt) - tgtOffset - } - - if len(src) < blksz { - return 0, -1 - } - - h := hashBlock(tgt, tgtOffset) - tIdx := h & idx.mask - eIdx := idx.table[tIdx] - if eIdx == 0 { - return - } - - srcOffset = idx.entries[eIdx] - - l = matchLength(src, tgt, tgtOffset, srcOffset) - - return -} - -func matchLength(src, tgt []byte, otgt, osrc int) (l int) { - lensrc := len(src) - lentgt := len(tgt) - for (osrc < lensrc && otgt < lentgt) && src[osrc] == tgt[otgt] { - l++ - osrc++ - otgt++ - } - return -} - -func countEntries(scan *deltaIndexScanner) (cnt int) { - // Figure out exactly how many entries we need. As we do the - // enumeration truncate any delta chains longer than what we - // are willing to scan during encode. This keeps the encode - // logic linear in the size of the input rather than quadratic. - for i := 0; i < len(scan.table); i++ { - h := scan.table[i] - if h == 0 { - continue - } - - size := 0 - for { - size++ - if size == maxChainLength { - scan.next[h] = 0 - break - } - h = scan.next[h] - - if h == 0 { - break - } - } - cnt += size - } - - return -} - -func (idx *deltaIndex) copyEntries(scanner *deltaIndexScanner) { - // Rebuild the entries list from the scanner, positioning all - // blocks in the same hash chain next to each other. We can - // then later discard the next list, along with the scanner. - // - next := 1 - for i := 0; i < len(idx.table); i++ { - h := idx.table[i] - if h == 0 { - continue - } - - idx.table[i] = next - for { - idx.entries[next] = scanner.entries[h] - next++ - h = scanner.next[h] - - if h == 0 { - break - } - } - } -} - -type deltaIndexScanner struct { - table []int - entries []int - next []int - mask int - count int -} - -func newDeltaIndexScanner(buf []byte, size int) *deltaIndexScanner { - size -= size % blksz - worstCaseBlockCnt := size / blksz - if worstCaseBlockCnt < 1 { - return new(deltaIndexScanner) - } - - tableSize := tableSize(worstCaseBlockCnt) - scanner := &deltaIndexScanner{ - table: make([]int, tableSize), - mask: tableSize - 1, - entries: make([]int, worstCaseBlockCnt+1), - next: make([]int, worstCaseBlockCnt+1), - } - - scanner.scan(buf, size) - return scanner -} - -// slightly modified version of JGit's DeltaIndexScanner. We store the offset on the entries -// instead of the entries and the key, so we avoid operations to retrieve the offset later, as -// we don't use the key. -// See: https://github.com/eclipse/jgit/blob/005e5feb4ecd08c4e4d141a38b9e7942accb3212/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaIndexScanner.java -func (s *deltaIndexScanner) scan(buf []byte, end int) { - lastHash := 0 - ptr := end - blksz - - for { - key := hashBlock(buf, ptr) - tIdx := key & s.mask - head := s.table[tIdx] - if head != 0 && lastHash == key { - s.entries[head] = ptr - } else { - s.count++ - eIdx := s.count - s.entries[eIdx] = ptr - s.next[eIdx] = head - s.table[tIdx] = eIdx - } - - lastHash = key - ptr -= blksz - - if 0 > ptr { - break - } - } -} - -func tableSize(worstCaseBlockCnt int) int { - shift := 32 - leadingZeros(uint32(worstCaseBlockCnt)) - sz := 1 << uint(shift-1) - if sz < worstCaseBlockCnt { - sz <<= 1 - } - return sz -} - -// use https://golang.org/pkg/math/bits/#LeadingZeros32 in the future -func leadingZeros(x uint32) (n int) { - if x >= 1<<16 { - x >>= 16 - n = 16 - } - if x >= 1<<8 { - x >>= 8 - n += 8 - } - n += int(len8tab[x]) - return 32 - n -} - -var len8tab = [256]uint8{ - 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, -} - -func hashBlock(raw []byte, ptr int) int { - // The first 4 steps collapse out into a 4 byte big-endian decode, - // with a larger right shift as we combined shift lefts together. - // - hash := ((uint32(raw[ptr]) & 0xff) << 24) | - ((uint32(raw[ptr+1]) & 0xff) << 16) | - ((uint32(raw[ptr+2]) & 0xff) << 8) | - (uint32(raw[ptr+3]) & 0xff) - hash ^= T[hash>>31] - - hash = ((hash << 8) | (uint32(raw[ptr+4]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+5]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+6]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+7]) & 0xff)) ^ T[hash>>23] - - hash = ((hash << 8) | (uint32(raw[ptr+8]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+9]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+10]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+11]) & 0xff)) ^ T[hash>>23] - - hash = ((hash << 8) | (uint32(raw[ptr+12]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+13]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+14]) & 0xff)) ^ T[hash>>23] - hash = ((hash << 8) | (uint32(raw[ptr+15]) & 0xff)) ^ T[hash>>23] - - return int(hash) -} - -var T = []uint32{0x00000000, 0xd4c6b32d, 0x7d4bd577, - 0xa98d665a, 0x2e5119c3, 0xfa97aaee, 0x531accb4, 0x87dc7f99, - 0x5ca23386, 0x886480ab, 0x21e9e6f1, 0xf52f55dc, 0x72f32a45, - 0xa6359968, 0x0fb8ff32, 0xdb7e4c1f, 0x6d82d421, 0xb944670c, - 0x10c90156, 0xc40fb27b, 0x43d3cde2, 0x97157ecf, 0x3e981895, - 0xea5eabb8, 0x3120e7a7, 0xe5e6548a, 0x4c6b32d0, 0x98ad81fd, - 0x1f71fe64, 0xcbb74d49, 0x623a2b13, 0xb6fc983e, 0x0fc31b6f, - 0xdb05a842, 0x7288ce18, 0xa64e7d35, 0x219202ac, 0xf554b181, - 0x5cd9d7db, 0x881f64f6, 0x536128e9, 0x87a79bc4, 0x2e2afd9e, - 0xfaec4eb3, 0x7d30312a, 0xa9f68207, 0x007be45d, 0xd4bd5770, - 0x6241cf4e, 0xb6877c63, 0x1f0a1a39, 0xcbcca914, 0x4c10d68d, - 0x98d665a0, 0x315b03fa, 0xe59db0d7, 0x3ee3fcc8, 0xea254fe5, - 0x43a829bf, 0x976e9a92, 0x10b2e50b, 0xc4745626, 0x6df9307c, - 0xb93f8351, 0x1f8636de, 0xcb4085f3, 0x62cde3a9, 0xb60b5084, - 0x31d72f1d, 0xe5119c30, 0x4c9cfa6a, 0x985a4947, 0x43240558, - 0x97e2b675, 0x3e6fd02f, 0xeaa96302, 0x6d751c9b, 0xb9b3afb6, - 0x103ec9ec, 0xc4f87ac1, 0x7204e2ff, 0xa6c251d2, 0x0f4f3788, - 0xdb8984a5, 0x5c55fb3c, 0x88934811, 0x211e2e4b, 0xf5d89d66, - 0x2ea6d179, 0xfa606254, 0x53ed040e, 0x872bb723, 0x00f7c8ba, - 0xd4317b97, 0x7dbc1dcd, 0xa97aaee0, 0x10452db1, 0xc4839e9c, - 0x6d0ef8c6, 0xb9c84beb, 0x3e143472, 0xead2875f, 0x435fe105, - 0x97995228, 0x4ce71e37, 0x9821ad1a, 0x31accb40, 0xe56a786d, - 0x62b607f4, 0xb670b4d9, 0x1ffdd283, 0xcb3b61ae, 0x7dc7f990, - 0xa9014abd, 0x008c2ce7, 0xd44a9fca, 0x5396e053, 0x8750537e, - 0x2edd3524, 0xfa1b8609, 0x2165ca16, 0xf5a3793b, 0x5c2e1f61, - 0x88e8ac4c, 0x0f34d3d5, 0xdbf260f8, 0x727f06a2, 0xa6b9b58f, - 0x3f0c6dbc, 0xebcade91, 0x4247b8cb, 0x96810be6, 0x115d747f, - 0xc59bc752, 0x6c16a108, 0xb8d01225, 0x63ae5e3a, 0xb768ed17, - 0x1ee58b4d, 0xca233860, 0x4dff47f9, 0x9939f4d4, 0x30b4928e, - 0xe47221a3, 0x528eb99d, 0x86480ab0, 0x2fc56cea, 0xfb03dfc7, - 0x7cdfa05e, 0xa8191373, 0x01947529, 0xd552c604, 0x0e2c8a1b, - 0xdaea3936, 0x73675f6c, 0xa7a1ec41, 0x207d93d8, 0xf4bb20f5, - 0x5d3646af, 0x89f0f582, 0x30cf76d3, 0xe409c5fe, 0x4d84a3a4, - 0x99421089, 0x1e9e6f10, 0xca58dc3d, 0x63d5ba67, 0xb713094a, - 0x6c6d4555, 0xb8abf678, 0x11269022, 0xc5e0230f, 0x423c5c96, - 0x96faefbb, 0x3f7789e1, 0xebb13acc, 0x5d4da2f2, 0x898b11df, - 0x20067785, 0xf4c0c4a8, 0x731cbb31, 0xa7da081c, 0x0e576e46, - 0xda91dd6b, 0x01ef9174, 0xd5292259, 0x7ca44403, 0xa862f72e, - 0x2fbe88b7, 0xfb783b9a, 0x52f55dc0, 0x8633eeed, 0x208a5b62, - 0xf44ce84f, 0x5dc18e15, 0x89073d38, 0x0edb42a1, 0xda1df18c, - 0x739097d6, 0xa75624fb, 0x7c2868e4, 0xa8eedbc9, 0x0163bd93, - 0xd5a50ebe, 0x52797127, 0x86bfc20a, 0x2f32a450, 0xfbf4177d, - 0x4d088f43, 0x99ce3c6e, 0x30435a34, 0xe485e919, 0x63599680, - 0xb79f25ad, 0x1e1243f7, 0xcad4f0da, 0x11aabcc5, 0xc56c0fe8, - 0x6ce169b2, 0xb827da9f, 0x3ffba506, 0xeb3d162b, 0x42b07071, - 0x9676c35c, 0x2f49400d, 0xfb8ff320, 0x5202957a, 0x86c42657, - 0x011859ce, 0xd5deeae3, 0x7c538cb9, 0xa8953f94, 0x73eb738b, - 0xa72dc0a6, 0x0ea0a6fc, 0xda6615d1, 0x5dba6a48, 0x897cd965, - 0x20f1bf3f, 0xf4370c12, 0x42cb942c, 0x960d2701, 0x3f80415b, - 0xeb46f276, 0x6c9a8def, 0xb85c3ec2, 0x11d15898, 0xc517ebb5, - 0x1e69a7aa, 0xcaaf1487, 0x632272dd, 0xb7e4c1f0, 0x3038be69, - 0xe4fe0d44, 0x4d736b1e, 0x99b5d833, -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_selector.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_selector.go deleted file mode 100644 index 520be0a1..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/delta_selector.go +++ /dev/null @@ -1,369 +0,0 @@ -package packfile - -import ( - "sort" - "sync" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -const ( - // deltas based on deltas, how many steps we can do. - // 50 is the default value used in JGit - maxDepth = int64(50) -) - -// applyDelta is the set of object types that we should apply deltas -var applyDelta = map[plumbing.ObjectType]bool{ - plumbing.BlobObject: true, - plumbing.TreeObject: true, -} - -type deltaSelector struct { - storer storer.EncodedObjectStorer -} - -func newDeltaSelector(s storer.EncodedObjectStorer) *deltaSelector { - return &deltaSelector{s} -} - -// ObjectsToPack creates a list of ObjectToPack from the hashes -// provided, creating deltas if it's suitable, using an specific -// internal logic. `packWindow` specifies the size of the sliding -// window used to compare objects for delta compression; 0 turns off -// delta compression entirely. -func (dw *deltaSelector) ObjectsToPack( - hashes []plumbing.Hash, - packWindow uint, -) ([]*ObjectToPack, error) { - otp, err := dw.objectsToPack(hashes, packWindow) - if err != nil { - return nil, err - } - - if packWindow == 0 { - return otp, nil - } - - dw.sort(otp) - - var objectGroups [][]*ObjectToPack - var prev *ObjectToPack - i := -1 - for _, obj := range otp { - if prev == nil || prev.Type() != obj.Type() { - objectGroups = append(objectGroups, []*ObjectToPack{obj}) - i++ - prev = obj - } else { - objectGroups[i] = append(objectGroups[i], obj) - } - } - - var wg sync.WaitGroup - var once sync.Once - for _, objs := range objectGroups { - objs := objs - wg.Add(1) - go func() { - if walkErr := dw.walk(objs, packWindow); walkErr != nil { - once.Do(func() { - err = walkErr - }) - } - wg.Done() - }() - } - wg.Wait() - - if err != nil { - return nil, err - } - - return otp, nil -} - -func (dw *deltaSelector) objectsToPack( - hashes []plumbing.Hash, - packWindow uint, -) ([]*ObjectToPack, error) { - var objectsToPack []*ObjectToPack - for _, h := range hashes { - var o plumbing.EncodedObject - var err error - if packWindow == 0 { - o, err = dw.encodedObject(h) - } else { - o, err = dw.encodedDeltaObject(h) - } - if err != nil { - return nil, err - } - - otp := newObjectToPack(o) - if _, ok := o.(plumbing.DeltaObject); ok { - otp.CleanOriginal() - } - - objectsToPack = append(objectsToPack, otp) - } - - if packWindow == 0 { - return objectsToPack, nil - } - - if err := dw.fixAndBreakChains(objectsToPack); err != nil { - return nil, err - } - - return objectsToPack, nil -} - -func (dw *deltaSelector) encodedDeltaObject(h plumbing.Hash) (plumbing.EncodedObject, error) { - edos, ok := dw.storer.(storer.DeltaObjectStorer) - if !ok { - return dw.encodedObject(h) - } - - return edos.DeltaObject(plumbing.AnyObject, h) -} - -func (dw *deltaSelector) encodedObject(h plumbing.Hash) (plumbing.EncodedObject, error) { - return dw.storer.EncodedObject(plumbing.AnyObject, h) -} - -func (dw *deltaSelector) fixAndBreakChains(objectsToPack []*ObjectToPack) error { - m := make(map[plumbing.Hash]*ObjectToPack, len(objectsToPack)) - for _, otp := range objectsToPack { - m[otp.Hash()] = otp - } - - for _, otp := range objectsToPack { - if err := dw.fixAndBreakChainsOne(m, otp); err != nil { - return err - } - } - - return nil -} - -func (dw *deltaSelector) fixAndBreakChainsOne(objectsToPack map[plumbing.Hash]*ObjectToPack, otp *ObjectToPack) error { - if !otp.Object.Type().IsDelta() { - return nil - } - - // Initial ObjectToPack instances might have a delta assigned to Object - // but no actual base initially. Once Base is assigned to a delta, it means - // we already fixed it. - if otp.Base != nil { - return nil - } - - do, ok := otp.Object.(plumbing.DeltaObject) - if !ok { - // if this is not a DeltaObject, then we cannot retrieve its base, - // so we have to break the delta chain here. - return dw.undeltify(otp) - } - - base, ok := objectsToPack[do.BaseHash()] - if !ok { - // The base of the delta is not in our list of objects to pack, so - // we break the chain. - return dw.undeltify(otp) - } - - if err := dw.fixAndBreakChainsOne(objectsToPack, base); err != nil { - return err - } - - otp.SetDelta(base, otp.Object) - return nil -} - -func (dw *deltaSelector) restoreOriginal(otp *ObjectToPack) error { - if otp.Original != nil { - return nil - } - - if !otp.Object.Type().IsDelta() { - return nil - } - - obj, err := dw.encodedObject(otp.Hash()) - if err != nil { - return err - } - - otp.SetOriginal(obj) - - return nil -} - -// undeltify undeltifies an *ObjectToPack by retrieving the original object from -// the storer and resetting it. -func (dw *deltaSelector) undeltify(otp *ObjectToPack) error { - if err := dw.restoreOriginal(otp); err != nil { - return err - } - - otp.Object = otp.Original - otp.Depth = 0 - return nil -} - -func (dw *deltaSelector) sort(objectsToPack []*ObjectToPack) { - sort.Sort(byTypeAndSize(objectsToPack)) -} - -func (dw *deltaSelector) walk( - objectsToPack []*ObjectToPack, - packWindow uint, -) error { - indexMap := make(map[plumbing.Hash]*deltaIndex) - for i := 0; i < len(objectsToPack); i++ { - // Clean up the index map and reconstructed delta objects for anything - // outside our pack window, to save memory. - if i > int(packWindow) { - obj := objectsToPack[i-int(packWindow)] - - delete(indexMap, obj.Hash()) - - if obj.IsDelta() { - obj.SaveOriginalMetadata() - obj.CleanOriginal() - } - } - - target := objectsToPack[i] - - // If we already have a delta, we don't try to find a new one for this - // object. This happens when a delta is set to be reused from an existing - // packfile. - if target.IsDelta() { - continue - } - - // We only want to create deltas from specific types. - if !applyDelta[target.Type()] { - continue - } - - for j := i - 1; j >= 0 && i-j < int(packWindow); j-- { - base := objectsToPack[j] - // Objects must use only the same type as their delta base. - // Since objectsToPack is sorted by type and size, once we find - // a different type, we know we won't find more of them. - if base.Type() != target.Type() { - break - } - - if err := dw.tryToDeltify(indexMap, base, target); err != nil { - return err - } - } - } - - return nil -} - -func (dw *deltaSelector) tryToDeltify(indexMap map[plumbing.Hash]*deltaIndex, base, target *ObjectToPack) error { - // Original object might not be present if we're reusing a delta, so we - // ensure it is restored. - if err := dw.restoreOriginal(target); err != nil { - return err - } - - if err := dw.restoreOriginal(base); err != nil { - return err - } - - // If the sizes are radically different, this is a bad pairing. - if target.Size() < base.Size()>>4 { - return nil - } - - msz := dw.deltaSizeLimit( - target.Object.Size(), - base.Depth, - target.Depth, - target.IsDelta(), - ) - - // Nearly impossible to fit useful delta. - if msz <= 8 { - return nil - } - - // If we have to insert a lot to make this work, find another. - if base.Size()-target.Size() > msz { - return nil - } - - if _, ok := indexMap[base.Hash()]; !ok { - indexMap[base.Hash()] = new(deltaIndex) - } - - // Now we can generate the delta using originals - delta, err := getDelta(indexMap[base.Hash()], base.Original, target.Original) - if err != nil { - return err - } - - // if delta better than target - if delta.Size() < msz { - target.SetDelta(base, delta) - } - - return nil -} - -func (dw *deltaSelector) deltaSizeLimit(targetSize int64, baseDepth int, - targetDepth int, targetDelta bool) int64 { - if !targetDelta { - // Any delta should be no more than 50% of the original size - // (for text files deflate of whole form should shrink 50%). - n := targetSize >> 1 - - // Evenly distribute delta size limits over allowed depth. - // If src is non-delta (depth = 0), delta <= 50% of original. - // If src is almost at limit (9/10), delta <= 10% of original. - return n * (maxDepth - int64(baseDepth)) / maxDepth - } - - // With a delta base chosen any new delta must be "better". - // Retain the distribution described above. - d := int64(targetDepth) - n := targetSize - - // If target depth is bigger than maxDepth, this delta is not suitable to be used. - if d >= maxDepth { - return 0 - } - - // If src is whole (depth=0) and base is near limit (depth=9/10) - // any delta using src can be 10x larger and still be better. - // - // If src is near limit (depth=9/10) and base is whole (depth=0) - // a new delta dependent on src must be 1/10th the size. - return n * (maxDepth - int64(baseDepth)) / (maxDepth - d) -} - -type byTypeAndSize []*ObjectToPack - -func (a byTypeAndSize) Len() int { return len(a) } - -func (a byTypeAndSize) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -func (a byTypeAndSize) Less(i, j int) bool { - if a[i].Type() < a[j].Type() { - return false - } - - if a[i].Type() > a[j].Type() { - return true - } - - return a[i].Size() > a[j].Size() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/diff_delta.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/diff_delta.go deleted file mode 100644 index 57201326..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/diff_delta.go +++ /dev/null @@ -1,204 +0,0 @@ -package packfile - -import ( - "bytes" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/sync" -) - -// See https://github.com/jelmer/dulwich/blob/master/dulwich/pack.py and -// https://github.com/tarruda/node-git-core/blob/master/src/js/delta.js -// for more info - -const ( - // Standard chunk size used to generate fingerprints - s = 16 - - // https://github.com/git/git/blob/f7466e94375b3be27f229c78873f0acf8301c0a5/diff-delta.c#L428 - // Max size of a copy operation (64KB). - maxCopySize = 64 * 1024 - - // Min size of a copy operation. - minCopySize = 4 -) - -// GetDelta returns an EncodedObject of type OFSDeltaObject. Base and Target object, -// will be loaded into memory to be able to create the delta object. -// To generate target again, you will need the obtained object and "base" one. -// Error will be returned if base or target object cannot be read. -func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, error) { - return getDelta(new(deltaIndex), base, target) -} - -func getDelta(index *deltaIndex, base, target plumbing.EncodedObject) (o plumbing.EncodedObject, err error) { - br, err := base.Reader() - if err != nil { - return nil, err - } - - defer ioutil.CheckClose(br, &err) - - tr, err := target.Reader() - if err != nil { - return nil, err - } - - defer ioutil.CheckClose(tr, &err) - - bb := sync.GetBytesBuffer() - defer sync.PutBytesBuffer(bb) - - _, err = bb.ReadFrom(br) - if err != nil { - return nil, err - } - - tb := sync.GetBytesBuffer() - defer sync.PutBytesBuffer(tb) - - _, err = tb.ReadFrom(tr) - if err != nil { - return nil, err - } - - db := diffDelta(index, bb.Bytes(), tb.Bytes()) - delta := &plumbing.MemoryObject{} - _, err = delta.Write(db) - if err != nil { - return nil, err - } - - delta.SetSize(int64(len(db))) - delta.SetType(plumbing.OFSDeltaObject) - - return delta, nil -} - -// DiffDelta returns the delta that transforms src into tgt. -func DiffDelta(src, tgt []byte) []byte { - return diffDelta(new(deltaIndex), src, tgt) -} - -func diffDelta(index *deltaIndex, src []byte, tgt []byte) []byte { - buf := sync.GetBytesBuffer() - defer sync.PutBytesBuffer(buf) - buf.Write(deltaEncodeSize(len(src))) - buf.Write(deltaEncodeSize(len(tgt))) - - if len(index.entries) == 0 { - index.init(src) - } - - ibuf := sync.GetBytesBuffer() - defer sync.PutBytesBuffer(ibuf) - for i := 0; i < len(tgt); i++ { - offset, l := index.findMatch(src, tgt, i) - - if l == 0 { - // couldn't find a match, just write the current byte and continue - ibuf.WriteByte(tgt[i]) - } else if l < 0 { - // src is less than blksz, copy the rest of the target to avoid - // calls to findMatch - for ; i < len(tgt); i++ { - ibuf.WriteByte(tgt[i]) - } - } else if l < s { - // remaining target is less than blksz, copy what's left of it - // and avoid calls to findMatch - for j := i; j < i+l; j++ { - ibuf.WriteByte(tgt[j]) - } - i += l - 1 - } else { - encodeInsertOperation(ibuf, buf) - - rl := l - aOffset := offset - for rl > 0 { - if rl < maxCopySize { - buf.Write(encodeCopyOperation(aOffset, rl)) - break - } - - buf.Write(encodeCopyOperation(aOffset, maxCopySize)) - rl -= maxCopySize - aOffset += maxCopySize - } - - i += l - 1 - } - } - - encodeInsertOperation(ibuf, buf) - - // buf.Bytes() is only valid until the next modifying operation on the buffer. Copy it. - return append([]byte{}, buf.Bytes()...) -} - -func encodeInsertOperation(ibuf, buf *bytes.Buffer) { - if ibuf.Len() == 0 { - return - } - - b := ibuf.Bytes() - s := ibuf.Len() - o := 0 - for { - if s <= 127 { - break - } - buf.WriteByte(byte(127)) - buf.Write(b[o : o+127]) - s -= 127 - o += 127 - } - buf.WriteByte(byte(s)) - buf.Write(b[o : o+s]) - - ibuf.Reset() -} - -func deltaEncodeSize(size int) []byte { - var ret []byte - c := size & 0x7f - size >>= 7 - for { - if size == 0 { - break - } - - ret = append(ret, byte(c|0x80)) - c = size & 0x7f - size >>= 7 - } - ret = append(ret, byte(c)) - - return ret -} - -func encodeCopyOperation(offset, length int) []byte { - code := 0x80 - var opcodes []byte - - var i uint - for i = 0; i < 4; i++ { - f := 0xff << (i * 8) - if offset&f != 0 { - opcodes = append(opcodes, byte(offset&f>>(i*8))) - code |= 0x01 << i - } - } - - for i = 0; i < 3; i++ { - f := 0xff << (i * 8) - if length&f != 0 { - opcodes = append(opcodes, byte(length&f>>(i*8))) - code |= 0x10 << i - } - } - - return append([]byte{byte(code)}, opcodes...) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/doc.go deleted file mode 100644 index 2882a7f3..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/doc.go +++ /dev/null @@ -1,39 +0,0 @@ -// Package packfile implements encoding and decoding of packfile format. -// -// == pack-*.pack files have the following format: -// -// - A header appears at the beginning and consists of the following: -// -// 4-byte signature: -// The signature is: {'P', 'A', 'C', 'K'} -// -// 4-byte version number (network byte order): -// GIT currently accepts version number 2 or 3 but -// generates version 2 only. -// -// 4-byte number of objects contained in the pack (network byte order) -// -// Observation: we cannot have more than 4G versions ;-) and -// more than 4G objects in a pack. -// -// - The header is followed by number of object entries, each of -// which looks like this: -// -// (undeltified representation) -// n-byte type and length (3-bit type, (n-1)*7+4-bit length) -// compressed data -// -// (deltified representation) -// n-byte type and length (3-bit type, (n-1)*7+4-bit length) -// 20-byte base object name -// compressed delta data -// -// Observation: length of each object is encoded in a variable -// length format and is not constrained to 32-bit or anything. -// -// - The trailer records 20-byte SHA1 checksum of all of the above. -// -// -// Source: -// https://www.kernel.org/pub/software/scm/git/docs/v1.7.5/technical/pack-protocol.txt -package packfile diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/encoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/encoder.go deleted file mode 100644 index ada04313..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/encoder.go +++ /dev/null @@ -1,225 +0,0 @@ -package packfile - -import ( - "compress/zlib" - "crypto" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/hash" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/binary" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// Encoder gets the data from the storage and write it into the writer in PACK -// format -type Encoder struct { - selector *deltaSelector - w *offsetWriter - zw *zlib.Writer - hasher plumbing.Hasher - - useRefDeltas bool -} - -// NewEncoder creates a new packfile encoder using a specific Writer and -// EncodedObjectStorer. By default deltas used to generate the packfile will be -// OFSDeltaObject. To use Reference deltas, set useRefDeltas to true. -func NewEncoder(w io.Writer, s storer.EncodedObjectStorer, useRefDeltas bool) *Encoder { - h := plumbing.Hasher{ - // TODO: Support passing an ObjectFormat (sha256) - Hash: hash.New(crypto.SHA1), - } - mw := io.MultiWriter(w, h) - ow := newOffsetWriter(mw) - zw := zlib.NewWriter(mw) - return &Encoder{ - selector: newDeltaSelector(s), - w: ow, - zw: zw, - hasher: h, - useRefDeltas: useRefDeltas, - } -} - -// Encode creates a packfile containing all the objects referenced in -// hashes and writes it to the writer in the Encoder. `packWindow` -// specifies the size of the sliding window used to compare objects -// for delta compression; 0 turns off delta compression entirely. -func (e *Encoder) Encode( - hashes []plumbing.Hash, - packWindow uint, -) (plumbing.Hash, error) { - objects, err := e.selector.ObjectsToPack(hashes, packWindow) - if err != nil { - return plumbing.ZeroHash, err - } - - return e.encode(objects) -} - -func (e *Encoder) encode(objects []*ObjectToPack) (plumbing.Hash, error) { - if err := e.head(len(objects)); err != nil { - return plumbing.ZeroHash, err - } - - for _, o := range objects { - if err := e.entry(o); err != nil { - return plumbing.ZeroHash, err - } - } - - return e.footer() -} - -func (e *Encoder) head(numEntries int) error { - return binary.Write( - e.w, - signature, - int32(VersionSupported), - int32(numEntries), - ) -} - -func (e *Encoder) entry(o *ObjectToPack) (err error) { - if o.WantWrite() { - // A cycle exists in this delta chain. This should only occur if a - // selected object representation disappeared during writing - // (for example due to a concurrent repack) and a different base - // was chosen, forcing a cycle. Select something other than a - // delta, and write this object. - e.selector.restoreOriginal(o) - o.BackToOriginal() - } - - if o.IsWritten() { - return nil - } - - o.MarkWantWrite() - - if err := e.writeBaseIfDelta(o); err != nil { - return err - } - - // We need to check if we already write that object due a cyclic delta chain - if o.IsWritten() { - return nil - } - - o.Offset = e.w.Offset() - - if o.IsDelta() { - if err := e.writeDeltaHeader(o); err != nil { - return err - } - } else { - if err := e.entryHead(o.Type(), o.Size()); err != nil { - return err - } - } - - e.zw.Reset(e.w) - - defer ioutil.CheckClose(e.zw, &err) - - or, err := o.Object.Reader() - if err != nil { - return err - } - - defer ioutil.CheckClose(or, &err) - - _, err = ioutil.CopyBufferPool(e.zw, or) - return err -} - -func (e *Encoder) writeBaseIfDelta(o *ObjectToPack) error { - if o.IsDelta() && !o.Base.IsWritten() { - // We must write base first - return e.entry(o.Base) - } - - return nil -} - -func (e *Encoder) writeDeltaHeader(o *ObjectToPack) error { - // Write offset deltas by default - t := plumbing.OFSDeltaObject - if e.useRefDeltas { - t = plumbing.REFDeltaObject - } - - if err := e.entryHead(t, o.Object.Size()); err != nil { - return err - } - - if e.useRefDeltas { - return e.writeRefDeltaHeader(o.Base.Hash()) - } else { - return e.writeOfsDeltaHeader(o) - } -} - -func (e *Encoder) writeRefDeltaHeader(base plumbing.Hash) error { - _, err := base.WriteTo(e.w) - return err -} - -func (e *Encoder) writeOfsDeltaHeader(o *ObjectToPack) error { - // for OFS_DELTA, offset of the base is interpreted as negative offset - // relative to the type-byte of the header of the ofs-delta entry. - relativeOffset := o.Offset - o.Base.Offset - if relativeOffset <= 0 { - return fmt.Errorf("bad offset for OFS_DELTA entry: %d", relativeOffset) - } - - return binary.WriteVariableWidthInt(e.w, relativeOffset) -} - -func (e *Encoder) entryHead(typeNum plumbing.ObjectType, size int64) error { - t := int64(typeNum) - header := []byte{} - c := (t << firstLengthBits) | (size & maskFirstLength) - size >>= firstLengthBits - for { - if size == 0 { - break - } - header = append(header, byte(c|maskContinue)) - c = size & int64(maskLength) - size >>= lengthBits - } - - header = append(header, byte(c)) - _, err := e.w.Write(header) - - return err -} - -func (e *Encoder) footer() (plumbing.Hash, error) { - h := e.hasher.Sum() - _, err := h.WriteTo(e.w) - return h, err -} - -type offsetWriter struct { - w io.Writer - offset int64 -} - -func newOffsetWriter(w io.Writer) *offsetWriter { - return &offsetWriter{w: w} -} - -func (ow *offsetWriter) Write(p []byte) (n int, err error) { - n, err = ow.w.Write(p) - ow.offset += int64(n) - return n, err -} - -func (ow *offsetWriter) Offset() int64 { - return ow.offset -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/error.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/error.go deleted file mode 100644 index c0b91633..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/error.go +++ /dev/null @@ -1,30 +0,0 @@ -package packfile - -import "fmt" - -// Error specifies errors returned during packfile parsing. -type Error struct { - reason, details string -} - -// NewError returns a new error. -func NewError(reason string) *Error { - return &Error{reason: reason} -} - -// Error returns a text representation of the error. -func (e *Error) Error() string { - if e.details == "" { - return e.reason - } - - return fmt.Sprintf("%s: %s", e.reason, e.details) -} - -// AddDetails adds details to an error, with additional text. -func (e *Error) AddDetails(format string, args ...interface{}) *Error { - return &Error{ - reason: e.reason, - details: fmt.Sprintf(format, args...), - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/fsobject.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/fsobject.go deleted file mode 100644 index 21227d41..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/fsobject.go +++ /dev/null @@ -1,138 +0,0 @@ -package packfile - -import ( - "errors" - "io" - "os" - - billy "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" - "github.com/go-git/go-git/v6/utils/sync" -) - -// FSObject is an object from the packfile on the filesystem. -type FSObject struct { - hash plumbing.Hash - offset int64 - size int64 - typ plumbing.ObjectType - index idxfile.Index - fs billy.Filesystem - pack billy.File - packPath string - cache cache.Object -} - -// NewFSObject creates a new filesystem object. -func NewFSObject( - hash plumbing.Hash, - finalType plumbing.ObjectType, - offset int64, - contentSize int64, - index idxfile.Index, - fs billy.Filesystem, - pack billy.File, - packPath string, - cache cache.Object, -) *FSObject { - return &FSObject{ - hash: hash, - offset: offset, - size: contentSize, - typ: finalType, - index: index, - fs: fs, - pack: pack, - packPath: packPath, - cache: cache, - } -} - -// Reader implements the plumbing.EncodedObject interface. -func (o *FSObject) Reader() (io.ReadCloser, error) { - obj, ok := o.cache.Get(o.hash) - if ok && obj != o { - reader, err := obj.Reader() - if err != nil { - return nil, err - } - - return reader, nil - } - - var closer io.Closer - _, err := o.pack.Seek(o.offset, io.SeekStart) - // fsobject aims to reuse an existing file descriptor to the packfile. - // In some cases that descriptor would already be closed, in such cases, - // open the packfile again and close it when the reader is closed. - if err != nil && errors.Is(err, os.ErrClosed) { - o.pack, err = o.fs.Open(o.packPath) - if err != nil { - return nil, err - } - closer = o.pack - _, err = o.pack.Seek(o.offset, io.SeekStart) - } - if err != nil { - return nil, err - } - - dict := sync.GetByteSlice() - zr := sync.NewZlibReader(dict) - err = zr.Reset(o.pack) - if err != nil { - return nil, err - } - return &zlibReadCloser{zr, dict, closer, false}, nil -} - -type zlibReadCloser struct { - r sync.ZLibReader - dict *[]byte - f io.Closer - closed bool -} - -// Read reads up to len(p) bytes into p from the data. -func (r *zlibReadCloser) Read(p []byte) (int, error) { - return r.r.Reader.Read(p) -} - -func (r *zlibReadCloser) Close() error { - if r.closed { - return nil - } - r.closed = true - sync.PutZlibReader(r.r) - if r.f != nil { - r.f.Close() - } - return nil -} - -// SetSize implements the plumbing.EncodedObject interface. This method -// is a noop. -func (o *FSObject) SetSize(int64) {} - -// SetType implements the plumbing.EncodedObject interface. This method is -// a noop. -func (o *FSObject) SetType(plumbing.ObjectType) {} - -// Hash implements the plumbing.EncodedObject interface. -func (o *FSObject) Hash() plumbing.Hash { return o.hash } - -// Size implements the plumbing.EncodedObject interface. -func (o *FSObject) Size() int64 { return o.size } - -// Type implements the plumbing.EncodedObject interface. -func (o *FSObject) Type() plumbing.ObjectType { - return o.typ -} - -// Writer implements the plumbing.EncodedObject interface. This method always -// returns a nil writer. -func (o *FSObject) Writer() (io.WriteCloser, error) { - return nil, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/object_pack.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/object_pack.go deleted file mode 100644 index 791c9029..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/object_pack.go +++ /dev/null @@ -1,164 +0,0 @@ -package packfile - -import ( - "github.com/go-git/go-git/v6/plumbing" -) - -// ObjectToPack is a representation of an object that is going to be into a -// pack file. -type ObjectToPack struct { - // The main object to pack, it could be any object, including deltas. - Object plumbing.EncodedObject - // Base is the object that a delta is based on, which could also be another delta. - // Nil when the main object is not a delta. - Base *ObjectToPack - // Original is the object that we can generate applying the delta to - // Base, or the same object as Object in the case of a non-delta - // object. - Original plumbing.EncodedObject - // Depth is the amount of deltas needed to resolve to obtain Original - // (delta based on delta based on ...) - Depth int - - // offset in pack when object has been already written, or 0 if it - // has not been written yet - Offset int64 - - // Information from the original object - resolvedOriginal bool - originalType plumbing.ObjectType - originalSize int64 - originalHash plumbing.Hash -} - -// newObjectToPack creates a correct ObjectToPack based on a non-delta object -func newObjectToPack(o plumbing.EncodedObject) *ObjectToPack { - return &ObjectToPack{ - Object: o, - Original: o, - } -} - -// newDeltaObjectToPack creates a correct ObjectToPack for a delta object, based on -// his base (could be another delta), the delta target (in this case called original), -// and the delta Object itself -func newDeltaObjectToPack(base *ObjectToPack, original, delta plumbing.EncodedObject) *ObjectToPack { - return &ObjectToPack{ - Object: delta, - Base: base, - Original: original, - Depth: base.Depth + 1, - } -} - -// BackToOriginal converts that ObjectToPack to a non-deltified object if it was one -func (o *ObjectToPack) BackToOriginal() { - if o.IsDelta() && o.Original != nil { - o.Object = o.Original - o.Base = nil - o.Depth = 0 - } -} - -// IsWritten returns if that ObjectToPack was -// already written into the packfile or not -func (o *ObjectToPack) IsWritten() bool { - return o.Offset > 1 -} - -// MarkWantWrite marks this ObjectToPack as WantWrite -// to avoid delta chain loops -func (o *ObjectToPack) MarkWantWrite() { - o.Offset = 1 -} - -// WantWrite checks if this ObjectToPack was marked as WantWrite before -func (o *ObjectToPack) WantWrite() bool { - return o.Offset == 1 -} - -// SetOriginal sets both Original and saves size, type and hash. If object -// is nil Original is set but previous resolved values are kept -func (o *ObjectToPack) SetOriginal(obj plumbing.EncodedObject) { - o.Original = obj - o.SaveOriginalMetadata() -} - -// SaveOriginalMetadata saves size, type and hash of Original object -func (o *ObjectToPack) SaveOriginalMetadata() { - if o.Original != nil { - o.originalSize = o.Original.Size() - o.originalType = o.Original.Type() - o.originalHash = o.Original.Hash() - o.resolvedOriginal = true - } -} - -// CleanOriginal sets Original to nil -func (o *ObjectToPack) CleanOriginal() { - o.Original = nil -} - -func (o *ObjectToPack) Type() plumbing.ObjectType { - if o.Original != nil { - return o.Original.Type() - } - - if o.resolvedOriginal { - return o.originalType - } - - if o.Base != nil { - return o.Base.Type() - } - - if o.Object != nil { - return o.Object.Type() - } - - panic("cannot get type") -} - -func (o *ObjectToPack) Hash() plumbing.Hash { - if o.Original != nil { - return o.Original.Hash() - } - - if o.resolvedOriginal { - return o.originalHash - } - - do, ok := o.Object.(plumbing.DeltaObject) - if ok { - return do.ActualHash() - } - - panic("cannot get hash") -} - -func (o *ObjectToPack) Size() int64 { - if o.Original != nil { - return o.Original.Size() - } - - if o.resolvedOriginal { - return o.originalSize - } - - do, ok := o.Object.(plumbing.DeltaObject) - if ok { - return do.ActualSize() - } - - panic("cannot get ObjectToPack size") -} - -func (o *ObjectToPack) IsDelta() bool { - return o.Base != nil -} - -func (o *ObjectToPack) SetDelta(base *ObjectToPack, delta plumbing.EncodedObject) { - o.Object = delta - o.Base = base - o.Depth = base.Depth + 1 -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile.go deleted file mode 100644 index b52ac780..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile.go +++ /dev/null @@ -1,350 +0,0 @@ -package packfile - -import ( - "crypto" - "fmt" - "io" - "sync" - - billy "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/cache" - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/ioutil" - gogitsync "github.com/go-git/go-git/v6/utils/sync" -) - -var ( - // ErrInvalidObject is returned by Decode when an invalid object is - // found in the packfile. - ErrInvalidObject = NewError("invalid git object") - // ErrZLib is returned by Decode when there was an error unzipping - // the packfile contents. - ErrZLib = NewError("zlib reading error") -) - -// Packfile allows retrieving information from inside a packfile. -type Packfile struct { - idxfile.Index - fs billy.Filesystem - file billy.File - scanner *Scanner - - cache cache.Object - - id plumbing.Hash - m sync.Mutex - objectIdSize int - - once sync.Once - onceErr error -} - -// NewPackfile returns a packfile representation for the given packfile file -// and packfile idx. -// If the filesystem is provided, the packfile will return FSObjects, otherwise -// it will return MemoryObjects. -func NewPackfile( - file billy.File, - opts ...PackfileOption, -) *Packfile { - p := &Packfile{ - file: file, - objectIdSize: crypto.SHA1.Size(), - } - for _, opt := range opts { - opt(p) - } - - return p -} - -// Get retrieves the encoded object in the packfile with the given hash. -func (p *Packfile) Get(h plumbing.Hash) (plumbing.EncodedObject, error) { - if err := p.init(); err != nil { - return nil, err - } - p.m.Lock() - defer p.m.Unlock() - - return p.get(h) -} - -// GetByOffset retrieves the encoded object from the packfile at the given -// offset. -func (p *Packfile) GetByOffset(offset int64) (plumbing.EncodedObject, error) { - if err := p.init(); err != nil { - return nil, err - } - p.m.Lock() - defer p.m.Unlock() - - return p.getByOffset(offset) -} - -// GetSizeByOffset retrieves the size of the encoded object from the -// packfile with the given offset. -func (p *Packfile) GetSizeByOffset(offset int64) (size int64, err error) { - if err := p.init(); err != nil { - return 0, err - } - - d, err := p.GetByOffset(offset) - if err != nil { - return 0, err - } - - return d.Size(), nil -} - -// GetAll returns an iterator with all encoded objects in the packfile. -// The iterator returned is not thread-safe, it should be used in the same -// thread as the Packfile instance. -func (p *Packfile) GetAll() (storer.EncodedObjectIter, error) { - return p.GetByType(plumbing.AnyObject) -} - -// GetByType returns all the objects of the given type. -func (p *Packfile) GetByType(typ plumbing.ObjectType) (storer.EncodedObjectIter, error) { - if err := p.init(); err != nil { - return nil, err - } - - switch typ { - case plumbing.AnyObject, - plumbing.BlobObject, - plumbing.TreeObject, - plumbing.CommitObject, - plumbing.TagObject: - entries, err := p.EntriesByOffset() - if err != nil { - return nil, err - } - - return &objectIter{ - p: p, - iter: entries, - typ: typ, - }, nil - default: - return nil, plumbing.ErrInvalidType - } -} - -// Returns the Packfile's inner scanner. -// -// Deprecated: this will be removed in future versions of the packfile package -// to avoid exposing the package internals and to improve its thread-safety. -// TODO: Remove Scanner method -func (p *Packfile) Scanner() (*Scanner, error) { - if err := p.init(); err != nil { - return nil, err - } - - return p.scanner, nil -} - -// ID returns the ID of the packfile, which is the checksum at the end of it. -func (p *Packfile) ID() (plumbing.Hash, error) { - if err := p.init(); err != nil { - return plumbing.ZeroHash, err - } - - return p.id, nil -} - -// get is not threat-safe, and should only be called within packfile.go. -func (p *Packfile) get(h plumbing.Hash) (plumbing.EncodedObject, error) { - if obj, ok := p.cache.Get(h); ok { - return obj, nil - } - - offset, err := p.Index.FindOffset(h) - if err != nil { - return nil, err - } - - oh, err := p.headerFromOffset(offset) - if err != nil { - return nil, err - } - - return p.objectFromHeader(oh) -} - -// getByOffset is not threat-safe, and should only be called within packfile.go. -func (p *Packfile) getByOffset(offset int64) (plumbing.EncodedObject, error) { - h, err := p.FindHash(offset) - if err != nil { - return nil, err - } - - if obj, ok := p.cache.Get(h); ok { - return obj, nil - } - - oh, err := p.headerFromOffset(offset) - if err != nil { - return nil, err - } - - return p.objectFromHeader(oh) -} - -func (p *Packfile) init() error { - p.once.Do(func() { - if p.file == nil { - p.onceErr = fmt.Errorf("file is not set") - return - } - - if p.Index == nil { - p.onceErr = fmt.Errorf("index is not set") - return - } - - var opts []ScannerOption - if p.objectIdSize == format.SHA256Size { - opts = append(opts, WithSHA256()) - } - - p.scanner = NewScanner(p.file, opts...) - // Validate packfile signature. - if !p.scanner.Scan() { - p.onceErr = p.scanner.Error() - return - } - - _, err := p.scanner.Seek(-int64(p.objectIdSize), io.SeekEnd) - if err != nil { - p.onceErr = err - return - } - - p.id.ResetBySize(p.objectIdSize) - _, err = p.id.ReadFrom(p.scanner) - if err != nil { - p.onceErr = err - } - - if p.cache == nil { - p.cache = cache.NewObjectLRUDefault() - } - }) - - return p.onceErr -} - -func (p *Packfile) headerFromOffset(offset int64) (*ObjectHeader, error) { - err := p.scanner.SeekFromStart(offset) - if err != nil { - return nil, err - } - - if !p.scanner.Scan() { - return nil, plumbing.ErrObjectNotFound - } - - oh := p.scanner.Data().Value().(ObjectHeader) - return &oh, nil -} - -// Close the packfile and its resources. -func (p *Packfile) Close() error { - p.m.Lock() - defer p.m.Unlock() - - closer, ok := p.file.(io.Closer) - if !ok { - return nil - } - - return closer.Close() -} - -func (p *Packfile) objectFromHeader(oh *ObjectHeader) (plumbing.EncodedObject, error) { - if oh == nil { - return nil, plumbing.ErrObjectNotFound - } - - // If we have filesystem, and the object is not a delta type, return a FSObject. - // This avoids having to inflate the object more than once. - if !oh.Type.IsDelta() && p.fs != nil { - fs := NewFSObject( - oh.ID(), - oh.Type, - oh.ContentOffset, - oh.Size, - p.Index, - p.fs, - p.file, - p.file.Name(), - p.cache, - ) - - p.cache.Put(fs) - return fs, nil - } - - return p.getMemoryObject(oh) -} - -func (p *Packfile) getMemoryObject(oh *ObjectHeader) (plumbing.EncodedObject, error) { - var obj = new(plumbing.MemoryObject) - obj.SetSize(oh.Size) - obj.SetType(oh.Type) - - w, err := obj.Writer() - if err != nil { - return nil, err - } - defer ioutil.CheckClose(w, &err) - - switch oh.Type { - case plumbing.CommitObject, plumbing.TreeObject, plumbing.BlobObject, plumbing.TagObject: - err = p.scanner.inflateContent(oh.ContentOffset, w) - - case plumbing.REFDeltaObject, plumbing.OFSDeltaObject: - var parent plumbing.EncodedObject - - switch oh.Type { - case plumbing.REFDeltaObject: - var ok bool - parent, ok = p.cache.Get(oh.Reference) - if !ok { - parent, err = p.get(oh.Reference) - } - case plumbing.OFSDeltaObject: - parent, err = p.getByOffset(oh.OffsetReference) - } - - if err != nil { - return nil, fmt.Errorf("cannot find base object: %w", err) - } - - if oh.content == nil { - oh.content = gogitsync.GetBytesBuffer() - } - - err = p.scanner.inflateContent(oh.ContentOffset, oh.content) - if err != nil { - return nil, fmt.Errorf("cannot inflate content: %w", err) - } - - obj.SetType(parent.Type()) - err = ApplyDelta(obj, parent, oh.content) //nolint:ineffassign - - default: - err = ErrInvalidObject.AddDetails("type %q", oh.Type) - } - - if err != nil { - return nil, err - } - - p.cache.Put(obj) - - return obj, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_iter.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_iter.go deleted file mode 100644 index 2a1bf770..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_iter.go +++ /dev/null @@ -1,90 +0,0 @@ -package packfile - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" -) - -type objectIter struct { - p *Packfile - typ plumbing.ObjectType - iter idxfile.EntryIter -} - -func (i *objectIter) Next() (plumbing.EncodedObject, error) { - if err := i.p.init(); err != nil { - return nil, err - } - - i.p.m.Lock() - defer i.p.m.Unlock() - - return i.next() -} - -func (i *objectIter) next() (plumbing.EncodedObject, error) { - for { - e, err := i.iter.Next() - if err != nil { - return nil, err - } - - oh, err := i.p.headerFromOffset(int64(e.Offset)) - if err != nil { - return nil, err - } - - if i.typ == plumbing.AnyObject { - return i.p.objectFromHeader(oh) - } - - // Current object header type is a delta, get the actual object to - // assess the actual type. - if oh.Type.IsDelta() { - o, err := i.p.objectFromHeader(oh) - if o.Type() == i.typ { - return o, err - } - - continue - } - - if oh.Type == i.typ { - return i.p.objectFromHeader(oh) - } - - continue - } -} - -func (i *objectIter) ForEach(f func(plumbing.EncodedObject) error) error { - if err := i.p.init(); err != nil { - return err - } - - i.p.m.Lock() - defer i.p.m.Unlock() - - for { - o, err := i.next() - if err != nil { - if err == io.EOF { - return nil - } - return err - } - - if err := f(o); err != nil { - return err - } - } -} - -func (i *objectIter) Close() { - i.p.m.Lock() - defer i.p.m.Unlock() - - i.iter.Close() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_options.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_options.go deleted file mode 100644 index 5acd3651..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/packfile_options.go +++ /dev/null @@ -1,42 +0,0 @@ -package packfile - -import ( - billy "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" -) - -type PackfileOption func(*Packfile) - -// WithCache sets the cache to be used throughout Packfile operations. -// Use this to share existing caches with the Packfile. If not used, a -// new cache instance will be created. -func WithCache(cache cache.Object) PackfileOption { - return func(p *Packfile) { - p.cache = cache - } -} - -// WithIdx sets the idxfile for the packfile. -func WithIdx(idx idxfile.Index) PackfileOption { - return func(p *Packfile) { - p.Index = idx - } -} - -// WithFs sets the filesystem to be used. -func WithFs(fs billy.Filesystem) PackfileOption { - return func(p *Packfile) { - p.fs = fs - } -} - -// WithObjectIDSize sets the size of the object IDs inside the packfile. -// Valid options are hash.SHA1Size and hash.SHA256Size. -// -// When no object ID size is set, hash.SHA1Size will be used. -func WithObjectIDSize(sz int) PackfileOption { - return func(p *Packfile) { - p.objectIdSize = sz - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser.go deleted file mode 100644 index fab0708e..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser.go +++ /dev/null @@ -1,404 +0,0 @@ -package packfile - -import ( - "bytes" - "errors" - "fmt" - "io" - stdsync "sync" - - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/sync" -) - -var ( - // ErrReferenceDeltaNotFound is returned when the reference delta is not - // found. - ErrReferenceDeltaNotFound = errors.New("reference delta not found") - - // ErrNotSeekableSource is returned when the source for the parser is not - // seekable and a storage was not provided, so it can't be parsed. - ErrNotSeekableSource = errors.New("parser source is not seekable and storage was not provided") - - // ErrDeltaNotCached is returned when the delta could not be found in cache. - ErrDeltaNotCached = errors.New("delta could not be found in cache") -) - -// Parser decodes a packfile and calls any observer associated to it. Is used -// to generate indexes. -type Parser struct { - storage storer.EncodedObjectStorer - cache *parserCache - lowMemoryMode bool - - scanner *Scanner - observers []Observer - hasher plumbing.Hasher - - checksum plumbing.Hash - m stdsync.Mutex -} - -// LowMemoryCapable is implemented by storage types that are capable of -// operating in low-memory mode. -type LowMemoryCapable interface { - // LowMemoryMode defines whether the storage is able and willing for - // the parser to operate in low-memory mode. - LowMemoryMode() bool -} - -// NewParser creates a new Parser. -// When a storage is set, the objects are written to storage as they -// are parsed. -func NewParser(data io.Reader, opts ...ParserOption) *Parser { - p := &Parser{ - hasher: plumbing.NewHasher(format.SHA1, plumbing.AnyObject, 0), - } - for _, opt := range opts { - if opt != nil { - opt(p) - } - } - - p.scanner = NewScanner(data) - - if p.storage != nil { - p.scanner.storage = p.storage - - lm, ok := p.storage.(LowMemoryCapable) - p.lowMemoryMode = ok && lm.LowMemoryMode() - } - - if p.scanner.seeker == nil { - p.lowMemoryMode = false - } - p.scanner.lowMemoryMode = p.lowMemoryMode - p.cache = newParserCache() - - return p -} - -func (p *Parser) storeOrCache(oh *ObjectHeader) error { - // Only need to store deltas, as the scanner already stored non-delta - // objects. - if p.storage != nil && oh.diskType.IsDelta() { - w, err := p.storage.RawObjectWriter(oh.Type, oh.Size) - if err != nil { - return err - } - - defer w.Close() - - _, err = ioutil.CopyBufferPool(w, oh.content) - if err != nil { - return err - } - } - - if p.cache != nil { - o := oh - for p.lowMemoryMode && o.content != nil { - sync.PutBytesBuffer(o.content) - o.content = nil - - if o.parent == nil || o.parent.content == nil { - break - } - o = o.parent - } - p.cache.Add(oh) - } - - if err := p.onInflatedObjectHeader(oh.Type, oh.Size, oh.Offset); err != nil { - return err - } - - if err := p.onInflatedObjectContent(oh.Hash, oh.Offset, oh.Crc32, nil); err != nil { - return err - } - - return nil -} - -func (p *Parser) resetCache(qty int) { - if p.cache != nil { - p.cache.Reset(qty) - } -} - -// Parse start decoding phase of the packfile. -func (p *Parser) Parse() (plumbing.Hash, error) { - p.m.Lock() - defer p.m.Unlock() - - var pendingDeltas []*ObjectHeader - var pendingDeltaREFs []*ObjectHeader - - for p.scanner.Scan() { - data := p.scanner.Data() - switch data.Section { - case HeaderSection: - header := data.Value().(Header) - - p.resetCache(int(header.ObjectsQty)) - p.onHeader(header.ObjectsQty) - - case ObjectSection: - oh := data.Value().(ObjectHeader) - if oh.Type.IsDelta() { - if oh.Type == plumbing.OFSDeltaObject { - pendingDeltas = append(pendingDeltas, &oh) - } else if oh.Type == plumbing.REFDeltaObject { - pendingDeltaREFs = append(pendingDeltaREFs, &oh) - } - continue - } - - if p.lowMemoryMode && oh.content != nil { - sync.PutBytesBuffer(oh.content) - oh.content = nil - } - - p.storeOrCache(&oh) - - case FooterSection: - p.checksum = data.Value().(plumbing.Hash) - } - } - - if p.scanner.objects == 0 { - return plumbing.ZeroHash, ErrEmptyPackfile - } - - for _, oh := range pendingDeltaREFs { - err := p.processDelta(oh) - if err != nil { - return plumbing.ZeroHash, fmt.Errorf("processing ref-delta at offset %v: %w", oh.Offset, err) - } - } - - for _, oh := range pendingDeltas { - err := p.processDelta(oh) - if err != nil { - return plumbing.ZeroHash, fmt.Errorf("processing ofs-delta at offset %v: %w", oh.Offset, err) - } - } - - // Return to pool all objects used. - go func() { - for _, oh := range p.cache.oi { - if oh.content != nil { - sync.PutBytesBuffer(oh.content) - oh.content = nil - } - } - }() - - return p.checksum, p.onFooter(p.checksum) -} - -func (p *Parser) ensureContent(oh *ObjectHeader) error { - // Skip if this object already has the correct content. - if oh.content != nil && oh.content.Len() == int(oh.Size) && !oh.Hash.IsZero() { - return nil - } - - if oh.content == nil { - oh.content = sync.GetBytesBuffer() - } - - var err error - if !p.lowMemoryMode && oh.content != nil && oh.content.Len() > 0 { - source := oh.content - oh.content = sync.GetBytesBuffer() - - defer sync.PutBytesBuffer(source) - - err = p.applyPatchBaseHeader(oh, source, oh.content, nil) - } else if p.scanner.scannerReader.seeker != nil { - deltaData := sync.GetBytesBuffer() - defer sync.PutBytesBuffer(deltaData) - - err = p.scanner.inflateContent(oh.ContentOffset, deltaData) - if err != nil { - return fmt.Errorf("inflating content at offset %v: %w", oh.ContentOffset, err) - } - - err = p.applyPatchBaseHeader(oh, deltaData, oh.content, nil) - } else { - return fmt.Errorf("can't ensure content: %w", plumbing.ErrObjectNotFound) - } - - if err != nil { - return fmt.Errorf("apply delta patch: %w", err) - } - return nil -} - -func (p *Parser) processDelta(oh *ObjectHeader) error { - switch oh.Type { - case plumbing.OFSDeltaObject: - pa, ok := p.cache.oiByOffset[oh.OffsetReference] - if !ok { - return plumbing.ErrObjectNotFound - } - oh.parent = pa - - case plumbing.REFDeltaObject: - pa, ok := p.cache.oiByHash[oh.Reference] - if !ok { - // can't find referenced object in this pack file - // this must be a "thin" pack. - oh.parent = &ObjectHeader{ // Placeholder parent - Hash: oh.Reference, - externalRef: true, // mark as an external reference that must be resolved - Type: plumbing.AnyObject, - diskType: plumbing.AnyObject, - } - } else { - oh.parent = pa - } - p.cache.oiByHash[oh.Reference] = oh.parent - - default: - return fmt.Errorf("unsupported delta type: %v", oh.Type) - } - - if err := p.ensureContent(oh); err != nil { - return err - } - - return p.storeOrCache(oh) -} - -// parentReader returns a [io.ReaderAt] for the decompressed contents -// of the parent. -func (p *Parser) parentReader(parent *ObjectHeader) (io.ReaderAt, error) { - if parent.content != nil && parent.content.Len() > 0 { - return bytes.NewReader(parent.content.Bytes()), nil - } - - // If parent is a Delta object, the inflated object must come - // from either cache or storage, else we would need to inflate - // it to then inflate the current object, which could go on - // indefinitely. - if p.storage != nil && parent.Hash != plumbing.ZeroHash { - obj, err := p.storage.EncodedObject(parent.Type, parent.Hash) - if err == nil { - // Ensure that external references have the correct type and size. - parent.Type = obj.Type() - parent.Size = obj.Size() - r, err := obj.Reader() - if err == nil { - defer r.Close() - - if parent.content == nil { - parent.content = sync.GetBytesBuffer() - } - parent.content.Grow(int(parent.Size)) - - _, err = ioutil.CopyBufferPool(parent.content, r) - if err == nil { - return bytes.NewReader(parent.content.Bytes()), nil - } - } - } - } - - // If the parent is not an external ref and we don't have the - // content offset, we won't be able to inflate via seeking through - // the packfile. - if !parent.externalRef && parent.ContentOffset == 0 { - return nil, plumbing.ErrObjectNotFound - } - - // Not a seeker data source, so avoid seeking the content. - if p.scanner.seeker == nil { - return nil, plumbing.ErrObjectNotFound - } - - if parent.content == nil { - parent.content = sync.GetBytesBuffer() - } - parent.content.Grow(int(parent.Size)) - - err := p.scanner.inflateContent(parent.ContentOffset, parent.content) - if err != nil { - return nil, ErrReferenceDeltaNotFound - } - return bytes.NewReader(parent.content.Bytes()), nil -} - -func (p *Parser) applyPatchBaseHeader(ota *ObjectHeader, delta io.Reader, target io.Writer, wh objectHeaderWriter) error { - if target == nil { - return fmt.Errorf("cannot apply patch against nil target") - } - - parentContents, err := p.parentReader(ota.parent) - if err != nil { - return err - } - - typ := ota.Type - if ota.Hash == plumbing.ZeroHash { - typ = ota.parent.Type - } - - sz, h, err := patchDeltaWriter(target, parentContents, delta, typ, wh) - if err != nil { - return err - } - - if ota.Hash == plumbing.ZeroHash { - ota.Type = typ - ota.Size = int64(sz) - ota.Hash = h - } - - return nil -} - -func (p *Parser) forEachObserver(f func(o Observer) error) error { - for _, o := range p.observers { - if err := f(o); err != nil { - return err - } - } - return nil -} - -func (p *Parser) onHeader(count uint32) error { - return p.forEachObserver(func(o Observer) error { - return o.OnHeader(count) - }) -} - -func (p *Parser) onInflatedObjectHeader( - t plumbing.ObjectType, - objSize int64, - pos int64, -) error { - return p.forEachObserver(func(o Observer) error { - return o.OnInflatedObjectHeader(t, objSize, pos) - }) -} - -func (p *Parser) onInflatedObjectContent( - h plumbing.Hash, - pos int64, - crc uint32, - content []byte, -) error { - return p.forEachObserver(func(o Observer) error { - return o.OnInflatedObjectContent(h, pos, crc, content) - }) -} - -func (p *Parser) onFooter(h plumbing.Hash) error { - return p.forEachObserver(func(o Observer) error { - return o.OnFooter(h) - }) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_cache.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_cache.go deleted file mode 100644 index a00a3aab..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_cache.go +++ /dev/null @@ -1,41 +0,0 @@ -package packfile - -import ( - "slices" - - "github.com/go-git/go-git/v6/plumbing" -) - -func newParserCache() *parserCache { - c := &parserCache{} - return c -} - -// parserCache defines the cache used within the parser. -// This is not thread safe by itself, and relies on the parser to -// enforce thread-safety. -type parserCache struct { - oi []*ObjectHeader - oiByHash map[plumbing.Hash]*ObjectHeader - oiByOffset map[int64]*ObjectHeader -} - -func (c *parserCache) Add(oh *ObjectHeader) { - c.oiByHash[oh.Hash] = oh - c.oiByOffset[oh.Offset] = oh - c.oi = append(c.oi, oh) -} - -func (c *parserCache) Reset(n int) { - if c.oi == nil { - c.oi = make([]*ObjectHeader, 0, n) - c.oiByHash = make(map[plumbing.Hash]*ObjectHeader, n) - c.oiByOffset = make(map[int64]*ObjectHeader, n) - } else { - c.oi = c.oi[:0] - c.oi = slices.Grow(c.oi, n) - - clear(c.oiByHash) - clear(c.oiByOffset) - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_options.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_options.go deleted file mode 100644 index 1dcded04..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_options.go +++ /dev/null @@ -1,47 +0,0 @@ -package packfile - -import ( - "github.com/go-git/go-git/v6/plumbing/storer" -) - -type ParserOption func(*Parser) - -// WithStorage sets the storage to be used while parsing a pack file. -func WithStorage(storage storer.EncodedObjectStorer) ParserOption { - return func(p *Parser) { - p.storage = storage - } -} - -// WithScannerObservers sets the observers to be notified during the -// scanning or parsing of a pack file. The scanner is responsible for -// notifying observers around general pack file information, such as -// header and footer. The scanner also notifies object headers for -// non-delta objects. -// -// Delta objects are notified as part of the parser logic. -func WithScannerObservers(ob ...Observer) ParserOption { - return func(p *Parser) { - p.observers = ob - } -} - -// WithHighMemoryMode optimises the parser for speed rather than -// for memory consumption, making the Parser faster from an execution -// time perspective, but yielding much more allocations, which in the -// long run could make the application slower due to GC pressure. -// -// When the parser is being used without a storage, this is enabled -// automatically, as it can't operate without it. Some storage types -// may no support low memory mode (i.e. memory storage), for storage -// types that do support it, this becomes an opt-in feature. -// -// When enabled the inflated content of all delta objects (ofs and ref) -// will be loaded into cache, making it faster to navigate through them. -// If the reader provided to the parser does not implement io.Seeker, -// full objects may also be loaded into memory. -func WithHighMemoryMode() ParserOption { - return func(p *Parser) { - p.lowMemoryMode = false - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_types.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_types.go deleted file mode 100644 index 17e9a0f9..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/parser_types.go +++ /dev/null @@ -1,19 +0,0 @@ -package packfile - -import ( - "github.com/go-git/go-git/v6/plumbing" -) - -// Observer interface is implemented by index encoders. -type Observer interface { - // OnHeader is called when a new packfile is opened. - OnHeader(count uint32) error - // OnInflatedObjectHeader is called for each object header read. - OnInflatedObjectHeader(t plumbing.ObjectType, objSize int64, pos int64) error - // OnInflatedObjectContent is called for each decoded object. - OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, content []byte) error - // OnFooter is called when decoding is done. - OnFooter(h plumbing.Hash) error -} - -type objectHeaderWriter func(typ plumbing.ObjectType, sz int64) error diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/patch_delta.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/patch_delta.go deleted file mode 100644 index bc7e974d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/patch_delta.go +++ /dev/null @@ -1,548 +0,0 @@ -package packfile - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "math" - - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/sync" -) - -// See https://github.com/git/git/blob/49fa3dc76179e04b0833542fa52d0f287a4955ac/delta.h -// https://github.com/git/git/blob/c2c5f6b1e479f2c38e0e01345350620944e3527f/patch-delta.c, -// and https://github.com/tarruda/node-git-core/blob/master/src/js/delta.js -// for details about the delta format. - -var ( - ErrInvalidDelta = errors.New("invalid delta") - ErrDeltaCmd = errors.New("wrong delta command") -) - -const ( - payload = 0x7f // 0111 1111 - continuation = 0x80 // 1000 0000 - - // maxPatchPreemptionSize defines what is the max size of bytes to be - // premptively made available for a patch operation. - maxPatchPreemptionSize uint = 65536 - - // minDeltaSize defines the smallest size for a delta. - minDeltaSize = 4 -) - -type offset struct { - mask byte - shift uint -} - -var offsets = []offset{ - {mask: 0x01, shift: 0}, - {mask: 0x02, shift: 8}, - {mask: 0x04, shift: 16}, - {mask: 0x08, shift: 24}, -} - -var sizes = []offset{ - {mask: 0x10, shift: 0}, - {mask: 0x20, shift: 8}, - {mask: 0x40, shift: 16}, -} - -// ApplyDelta writes to target the result of applying the modification deltas in delta to base. -func ApplyDelta(target, base plumbing.EncodedObject, delta *bytes.Buffer) (err error) { - r, err := base.Reader() - if err != nil { - return err - } - - defer ioutil.CheckClose(r, &err) - - w, err := target.Writer() - if err != nil { - return err - } - - defer ioutil.CheckClose(w, &err) - - buf := sync.GetBytesBuffer() - defer sync.PutBytesBuffer(buf) - _, err = buf.ReadFrom(r) - if err != nil { - return err - } - src := buf.Bytes() - - dst := sync.GetBytesBuffer() - defer sync.PutBytesBuffer(dst) - err = patchDelta(dst, src, delta.Bytes()) - if err != nil { - return err - } - - target.SetSize(int64(dst.Len())) - - _, err = ioutil.CopyBufferPool(w, dst) - return err -} - -// PatchDelta returns the result of applying the modification deltas in delta to src. -// An error will be returned if delta is corrupted (ErrInvalidDelta) or an action command -// is not copy from source or copy from delta (ErrDeltaCmd). -func PatchDelta(src, delta []byte) ([]byte, error) { - if len(src) == 0 || len(delta) < minDeltaSize { - return nil, ErrInvalidDelta - } - - b := &bytes.Buffer{} - if err := patchDelta(b, src, delta); err != nil { - return nil, err - } - return b.Bytes(), nil -} - -func ReaderFromDelta(base plumbing.EncodedObject, deltaRC io.Reader) (io.ReadCloser, error) { - deltaBuf := bufio.NewReaderSize(deltaRC, 1024) - srcSz, err := decodeLEB128ByteReader(deltaBuf) - if err != nil { - if err == io.EOF { - return nil, ErrInvalidDelta - } - return nil, err - } - if srcSz != uint(base.Size()) { - return nil, ErrInvalidDelta - } - - targetSz, err := decodeLEB128ByteReader(deltaBuf) - if err != nil { - if err == io.EOF { - return nil, ErrInvalidDelta - } - return nil, err - } - remainingTargetSz := targetSz - - dstRd, dstWr := io.Pipe() - - go func() { - baseRd, err := base.Reader() - if err != nil { - _ = dstWr.CloseWithError(ErrInvalidDelta) - return - } - defer baseRd.Close() - - baseBuf := bufio.NewReader(baseRd) - basePos := uint(0) - - for { - cmd, err := deltaBuf.ReadByte() - if err == io.EOF { - _ = dstWr.CloseWithError(ErrInvalidDelta) - return - } - if err != nil { - _ = dstWr.CloseWithError(err) - return - } - - switch { - case isCopyFromSrc(cmd): - offset, err := decodeOffsetByteReader(cmd, deltaBuf) - if err != nil { - _ = dstWr.CloseWithError(err) - return - } - sz, err := decodeSizeByteReader(cmd, deltaBuf) - if err != nil { - _ = dstWr.CloseWithError(err) - return - } - - if invalidSize(sz, targetSz) || - invalidOffsetSize(offset, sz, srcSz) { - _ = dstWr.Close() - return - } - - discard := offset - basePos - if basePos > offset { - _ = baseRd.Close() - baseRd, err = base.Reader() - if err != nil { - _ = dstWr.CloseWithError(ErrInvalidDelta) - return - } - baseBuf.Reset(baseRd) - discard = offset - } - for discard > math.MaxInt32 { - n, err := baseBuf.Discard(math.MaxInt32) - if err != nil { - _ = dstWr.CloseWithError(err) - return - } - basePos += uint(n) - discard -= uint(n) - } - for discard > 0 { - n, err := baseBuf.Discard(int(discard)) - if err != nil { - _ = dstWr.CloseWithError(err) - return - } - basePos += uint(n) - discard -= uint(n) - } - if _, err := ioutil.CopyBufferPool(dstWr, io.LimitReader(baseBuf, int64(sz))); err != nil { - _ = dstWr.CloseWithError(err) - return - } - remainingTargetSz -= sz - basePos += sz - - case isCopyFromDelta(cmd): - sz := uint(cmd) // cmd is the size itself - if invalidSize(sz, targetSz) { - _ = dstWr.CloseWithError(ErrInvalidDelta) - return - } - if _, err := ioutil.CopyBufferPool(dstWr, io.LimitReader(deltaBuf, int64(sz))); err != nil { - _ = dstWr.CloseWithError(err) - return - } - - remainingTargetSz -= sz - - default: - _ = dstWr.CloseWithError(ErrDeltaCmd) - return - } - - if remainingTargetSz <= 0 { - _ = dstWr.Close() - return - } - } - }() - - return dstRd, nil -} - -func patchDelta(dst *bytes.Buffer, src, delta []byte) error { - if len(delta) < minCopySize { - return ErrInvalidDelta - } - - srcSz, delta := decodeLEB128(delta) - if srcSz != uint(len(src)) { - return ErrInvalidDelta - } - - targetSz, delta := decodeLEB128(delta) - remainingTargetSz := targetSz - - var cmd byte - - growSz := min(targetSz, maxPatchPreemptionSize) - dst.Grow(int(growSz)) - for { - if len(delta) == 0 { - return ErrInvalidDelta - } - - cmd = delta[0] - delta = delta[1:] - - switch { - case isCopyFromSrc(cmd): - var offset, sz uint - var err error - offset, delta, err = decodeOffset(cmd, delta) - if err != nil { - return err - } - - sz, delta, err = decodeSize(cmd, delta) - if err != nil { - return err - } - - if invalidSize(sz, targetSz) || - invalidOffsetSize(offset, sz, srcSz) { - break - } - dst.Write(src[offset : offset+sz]) - remainingTargetSz -= sz - - case isCopyFromDelta(cmd): - sz := uint(cmd) // cmd is the size itself - if invalidSize(sz, targetSz) { - return ErrInvalidDelta - } - - if uint(len(delta)) < sz { - return ErrInvalidDelta - } - - dst.Write(delta[0:sz]) - remainingTargetSz -= sz - delta = delta[sz:] - - default: - return ErrDeltaCmd - } - - if remainingTargetSz <= 0 { - break - } - } - - return nil -} - -func patchDeltaWriter(dst io.Writer, base io.ReaderAt, delta io.Reader, - typ plumbing.ObjectType, writeHeader objectHeaderWriter) (uint, plumbing.Hash, error) { - deltaBuf := bufio.NewReader(delta) - srcSz, err := decodeLEB128ByteReader(deltaBuf) - if err != nil { - if err == io.EOF { - return 0, plumbing.ZeroHash, ErrInvalidDelta - } - return 0, plumbing.ZeroHash, err - } - - if r, ok := base.(*bytes.Reader); ok && srcSz != uint(r.Size()) { - return 0, plumbing.ZeroHash, ErrInvalidDelta - } - - targetSz, err := decodeLEB128ByteReader(deltaBuf) - if err != nil { - if err == io.EOF { - return 0, plumbing.ZeroHash, ErrInvalidDelta - } - return 0, plumbing.ZeroHash, err - } - - // Avoid several iteractions expanding the buffer, which can be quite - // inefficient on large deltas. - if b, ok := dst.(*bytes.Buffer); ok { - b.Grow(int(targetSz)) - } - - // If header still needs to be written, caller will provide - // a LazyObjectWriterHeader. This seems to be the case when - // dealing with thin-packs. - if writeHeader != nil { - err = writeHeader(typ, int64(targetSz)) - if err != nil { - return 0, plumbing.ZeroHash, fmt.Errorf("could not lazy write header: %w", err) - } - } - - remainingTargetSz := targetSz - - hasher := plumbing.NewHasher(format.SHA1, typ, int64(targetSz)) - mw := io.MultiWriter(dst, hasher) - - bufp := sync.GetByteSlice() - defer sync.PutByteSlice(bufp) - - sr := io.NewSectionReader(base, int64(0), int64(srcSz)) - // Keep both the io.LimitedReader types, so we can reset N. - baselr := io.LimitReader(sr, 0).(*io.LimitedReader) - deltalr := io.LimitReader(deltaBuf, 0).(*io.LimitedReader) - - for { - buf := *bufp - cmd, err := deltaBuf.ReadByte() - if err == io.EOF { - return 0, plumbing.ZeroHash, ErrInvalidDelta - } - if err != nil { - return 0, plumbing.ZeroHash, err - } - - if isCopyFromSrc(cmd) { - offset, err := decodeOffsetByteReader(cmd, deltaBuf) - if err != nil { - return 0, plumbing.ZeroHash, err - } - sz, err := decodeSizeByteReader(cmd, deltaBuf) - if err != nil { - return 0, plumbing.ZeroHash, err - } - - if invalidSize(sz, targetSz) || - invalidOffsetSize(offset, sz, srcSz) { - return 0, plumbing.ZeroHash, err - } - - if _, err := sr.Seek(int64(offset), io.SeekStart); err != nil { - return 0, plumbing.ZeroHash, err - } - baselr.N = int64(sz) - if _, err := io.CopyBuffer(mw, baselr, buf); err != nil { - return 0, plumbing.ZeroHash, err - } - remainingTargetSz -= sz - } else if isCopyFromDelta(cmd) { - sz := uint(cmd) // cmd is the size itself - if invalidSize(sz, targetSz) { - return 0, plumbing.ZeroHash, ErrInvalidDelta - } - deltalr.N = int64(sz) - if _, err := io.CopyBuffer(mw, deltalr, buf); err != nil { - return 0, plumbing.ZeroHash, err - } - - remainingTargetSz -= sz - } else { - return 0, plumbing.ZeroHash, err - } - if remainingTargetSz <= 0 { - break - } - } - - return targetSz, hasher.Sum(), nil -} - -// Decodes a number encoded as an unsigned LEB128 at the start of some -// binary data and returns the decoded number and the rest of the -// stream. -// -// This must be called twice on the delta data buffer, first to get the -// expected source buffer size, and again to get the target buffer size. -func decodeLEB128(input []byte) (uint, []byte) { - if len(input) == 0 { - return 0, input - } - - var num, sz uint - var b byte - for { - b = input[sz] - num |= (uint(b) & payload) << (sz * 7) // concats 7 bits chunks - sz++ - - if uint(b)&continuation == 0 || sz == uint(len(input)) { - break - } - } - - return num, input[sz:] -} - -func decodeLEB128ByteReader(input io.ByteReader) (uint, error) { - var num, sz uint - for { - b, err := input.ReadByte() - if err != nil { - return 0, err - } - - num |= (uint(b) & payload) << (sz * 7) // concats 7 bits chunks - sz++ - - if uint(b)&continuation == 0 { - break - } - } - - return num, nil -} - -func isCopyFromSrc(cmd byte) bool { - return (cmd & continuation) != 0 -} - -func isCopyFromDelta(cmd byte) bool { - return (cmd&continuation) == 0 && cmd != 0 -} - -func decodeOffsetByteReader(cmd byte, delta io.ByteReader) (uint, error) { - var offset uint - for _, o := range offsets { - if (cmd & o.mask) != 0 { - next, err := delta.ReadByte() - if err != nil { - return 0, err - } - offset |= uint(next) << o.shift - } - } - - return offset, nil -} - -func decodeOffset(cmd byte, delta []byte) (uint, []byte, error) { - var offset uint - for _, o := range offsets { - if (cmd & o.mask) != 0 { - if len(delta) == 0 { - return 0, nil, ErrInvalidDelta - } - offset |= uint(delta[0]) << o.shift - delta = delta[1:] - } - } - - return offset, delta, nil -} - -func decodeSizeByteReader(cmd byte, delta io.ByteReader) (uint, error) { - var sz uint - for _, s := range sizes { - if (cmd & s.mask) != 0 { - next, err := delta.ReadByte() - if err != nil { - return 0, err - } - sz |= uint(next) << s.shift - } - } - - if sz == 0 { - sz = maxCopySize - } - - return sz, nil -} - -func decodeSize(cmd byte, delta []byte) (uint, []byte, error) { - var sz uint - for _, s := range sizes { - if (cmd & s.mask) != 0 { - if len(delta) == 0 { - return 0, nil, ErrInvalidDelta - } - sz |= uint(delta[0]) << s.shift - delta = delta[1:] - } - } - if sz == 0 { - sz = maxCopySize - } - - return sz, delta, nil -} - -func invalidSize(sz, targetSz uint) bool { - return sz > targetSz -} - -func invalidOffsetSize(offset, sz, srcSz uint) bool { - return sumOverflows(offset, sz) || - offset+sz > srcSz -} - -func sumOverflows(a, b uint) bool { - return a+b < a -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner.go deleted file mode 100644 index c5c0cb95..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner.go +++ /dev/null @@ -1,517 +0,0 @@ -package packfile - -import ( - "bytes" - "crypto" - "encoding/hex" - "fmt" - - "hash" - "hash/crc32" - "io" - "sync" - - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" - gogithash "github.com/go-git/go-git/v6/plumbing/hash" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/binary" - "github.com/go-git/go-git/v6/utils/ioutil" - gogitsync "github.com/go-git/go-git/v6/utils/sync" -) - -var ( - // ErrEmptyPackfile is returned by ReadHeader when no data is found in the packfile. - ErrEmptyPackfile = NewError("empty packfile") - // ErrBadSignature is returned by ReadHeader when the signature in the packfile is incorrect. - ErrBadSignature = NewError("malformed pack file signature") - // ErrMalformedPackfile is returned when the packfile format is incorrect. - ErrMalformedPackfile = NewError("malformed pack file") - // ErrUnsupportedVersion is returned by ReadHeader when the packfile version is - // different than VersionSupported. - ErrUnsupportedVersion = NewError("unsupported packfile version") - // ErrSeekNotSupported returned if seek is not support. - ErrSeekNotSupported = NewError("not seek support") -) - -// Scanner provides sequential access to the data stored in a Git packfile. -// -// A Git packfile is a compressed binary format that stores multiple Git objects, -// such as commits, trees, delta objects and blobs. These packfiles are used to -// reduce the size of data when transferring or storing Git repositories. -// -// A Git packfile is structured as follows: -// -// +----------------------------------------------------+ -// | PACK File Header | -// +----------------------------------------------------+ -// | "PACK" | Version Number | Number of Objects | -// | (4 bytes) | (4 bytes) | (4 bytes) | -// +----------------------------------------------------+ -// | Object Entry #1 | -// +----------------------------------------------------+ -// | Object Header | Compressed Object Data / Delta | -// | (type + size) | (var-length, zlib compressed) | -// +----------------------------------------------------+ -// | ... | -// +----------------------------------------------------+ -// | PACK File Footer | -// +----------------------------------------------------+ -// | SHA-1 Checksum (20 bytes) | -// +----------------------------------------------------+ -// -// For upstream docs, refer to https://git-scm.com/docs/gitformat-pack. -type Scanner struct { - // version holds the packfile version. - version Version - // objects holds the quantiy of objects within the packfile. - objects uint32 - // objIndex is the current index when going through the packfile objects. - objIndex int - // hasher is used to hash non-delta objects. - hasher plumbing.Hasher - // hasher256 is optional and used to hash the non-delta objects using SHA256. - hasher256 *plumbing.Hasher - // crc is used to generate the CRC-32 checksum of each object's content. - crc hash.Hash32 - // packhash hashes the pack contents so that at the end it is able to - // validate the packfile's footer checksum against the calculated hash. - packhash gogithash.Hash - // objectIdSize holds the object ID size. - objectIDSize int - - // next holds what state function should be executed on the next - // call to Scan(). - nextFn stateFn - // packData holds the data for the last successful call to Scan(). - packData PackData - // err holds the first error that occurred. - err error - - m sync.Mutex - - // storage is optional, and when set is used to store full objects found. - // Note that delta objects are not stored. - storage storer.EncodedObjectStorer - - *scannerReader - zr gogitsync.ZLibReader - lowMemoryMode bool -} - -// NewScanner creates a new instance of Scanner. -func NewScanner(rs io.Reader, opts ...ScannerOption) *Scanner { - dict := make([]byte, 16*1024) - crc := crc32.NewIEEE() - packhash := gogithash.New(crypto.SHA1) - - r := &Scanner{ - scannerReader: newScannerReader(rs, io.MultiWriter(crc, packhash)), - zr: gogitsync.NewZlibReader(&dict), - objIndex: -1, - hasher: plumbing.NewHasher(format.SHA1, plumbing.AnyObject, 0), - crc: crc, - packhash: packhash, - nextFn: packHeaderSignature, - // Set the default size, which can be overriden by opts. - objectIDSize: packhash.Size(), - } - - for _, opt := range opts { - opt(r) - } - - return r -} - -// Scan scans a Packfile sequently. Each call will navigate from a section -// to the next, until the entire file is read. -// -// The section data can be accessed via calls to Data(). Example: -// -// for scanner.Scan() { -// v := scanner.Data().Value() -// -// switch scanner.Data().Section { -// case HeaderSection: -// header := v.(Header) -// fmt.Println("[Header] Objects Qty:", header.ObjectsQty) -// case ObjectSection: -// oh := v.(ObjectHeader) -// fmt.Println("[Object] Object Type:", oh.Type) -// case FooterSection: -// checksum := v.(plumbing.Hash) -// fmt.Println("[Footer] Checksum:", checksum) -// } -// } -func (r *Scanner) Scan() bool { - r.m.Lock() - defer r.m.Unlock() - - if r.err != nil || r.nextFn == nil { - return false - } - - if err := scan(r); err != nil { - r.err = err - return false - } - - return true -} - -// Reset resets the current scanner, enabling it to be used to scan the -// same Packfile again. -func (r *Scanner) Reset() { - r.scannerReader.Flush() - r.scannerReader.Seek(0, io.SeekStart) - r.packhash.Reset() - - r.objIndex = -1 - r.version = 0 - r.objects = 0 - r.packData = PackData{} - r.err = nil - r.nextFn = packHeaderSignature -} - -// Data returns the pack data based on the last call to Scan(). -func (r *Scanner) Data() PackData { - return r.packData -} - -// Data returns the first error that occurred on the last call to Scan(). -// Once an error occurs, calls to Scan() becomes a no-op. -func (r *Scanner) Error() error { - return r.err -} - -func (r *Scanner) SeekFromStart(offset int64) error { - r.Reset() - - if !r.Scan() { - return fmt.Errorf("failed to reset and read header") - } - - _, err := r.scannerReader.Seek(offset, io.SeekStart) - return err -} - -func (s *Scanner) WriteObject(oh *ObjectHeader, writer io.Writer) error { - if oh.content != nil && oh.content.Len() > 0 { - _, err := ioutil.CopyBufferPool(writer, oh.content) - return err - } - - // If the oh is not an external ref and we don't have the - // content offset, we won't be able to inflate via seeking through - // the packfile. - if oh.externalRef && oh.ContentOffset == 0 { - return plumbing.ErrObjectNotFound - } - - // Not a seeker data source. - if s.seeker == nil { - return plumbing.ErrObjectNotFound - } - - err := s.inflateContent(oh.ContentOffset, writer) - if err != nil { - return ErrReferenceDeltaNotFound - } - - return nil -} - -func (s *Scanner) inflateContent(contentOffset int64, writer io.Writer) error { - _, err := s.scannerReader.Seek(contentOffset, io.SeekStart) - if err != nil { - return err - } - - err = s.zr.Reset(s.scannerReader) - if err != nil { - return fmt.Errorf("zlib reset error: %s", err) - } - - _, err = ioutil.CopyBufferPool(writer, s.zr.Reader) - if err != nil { - return err - } - - return nil -} - -// scan goes through the next stateFn. -// -// State functions are chained by returning a non-nil value for stateFn. -// In such cases, the returned stateFn will be called immediately after -// the current func. -func scan(r *Scanner) error { - var err error - for state := r.nextFn; state != nil; { - state, err = state(r) - if err != nil { - return err - } - } - return nil -} - -// stateFn defines each individual state within the state machine that -// represents a packfile. -type stateFn func(*Scanner) (stateFn, error) - -// packHeaderSignature validates the packfile's header signature and -// returns [ErrBadSignature] if the value provided is invalid. -// -// This is always the first state of a packfile and starts the chain -// that handles the entire packfile header. -func packHeaderSignature(r *Scanner) (stateFn, error) { - start := make([]byte, 4) - _, err := r.Read(start) - if err != nil { - return nil, fmt.Errorf("%w: %w", ErrBadSignature, err) - } - - if bytes.Equal(start, signature) { - return packVersion, nil - } - - return nil, ErrBadSignature -} - -// packVersion parses the packfile version. It returns [ErrMalformedPackfile] -// when the version cannot be parsed. If a valid version is parsed, but it is -// not currently supported, it returns [ErrUnsupportedVersion] instead. -func packVersion(r *Scanner) (stateFn, error) { - version, err := binary.ReadUint32(r.scannerReader) - if err != nil { - return nil, fmt.Errorf("%w: cannot read version", ErrMalformedPackfile) - } - - v := Version(version) - if !v.Supported() { - return nil, ErrUnsupportedVersion - } - - r.version = v - return packObjectsQty, nil -} - -// packObjectsQty parses the quantity of objects that the packfile contains. -// If the value cannot be parsed, [ErrMalformedPackfile] is returned. -// -// This state ends the packfile header chain. -func packObjectsQty(r *Scanner) (stateFn, error) { - qty, err := binary.ReadUint32(r.scannerReader) - if err != nil { - return nil, fmt.Errorf("%w: cannot read number of objects", ErrMalformedPackfile) - } - if qty == 0 { - return packFooter, nil - } - - r.objects = qty - r.packData = PackData{ - Section: HeaderSection, - header: Header{Version: r.version, ObjectsQty: r.objects}, - } - r.nextFn = objectEntry - - return nil, nil -} - -// objectEntry handles the object entries within a packfile. This is generally -// split between object headers and their contents. -// -// The object header contains the object type and size. If the type cannot be parsed, -// [ErrMalformedPackfile] is returned. -// -// When SHA256 is enabled, the scanner will also calculate the SHA256 for each object. -func objectEntry(r *Scanner) (stateFn, error) { - if r.objIndex+1 >= int(r.objects) { - return packFooter, nil - } - r.objIndex++ - - offset := r.scannerReader.offset - - r.scannerReader.Flush() - r.crc.Reset() - - b := []byte{0} - _, err := r.Read(b) - if err != nil { - return nil, err - } - - typ := parseType(b[0]) - if !typ.Valid() { - return nil, fmt.Errorf("%w: invalid object type: %v", ErrMalformedPackfile, b[0]) - } - - size, err := readVariableLengthSize(b[0], r) - if err != nil { - return nil, err - } - - oh := ObjectHeader{ - Offset: offset, - Type: typ, - diskType: typ, - Size: int64(size), - } - - switch oh.Type { - case plumbing.OFSDeltaObject, plumbing.REFDeltaObject: - // For delta objects, we need to skip the base reference - if oh.Type == plumbing.OFSDeltaObject { - no, err := binary.ReadVariableWidthInt(r.scannerReader) - if err != nil { - return nil, err - } - oh.OffsetReference = oh.Offset - no - } else { - oh.Reference.ResetBySize(r.objectIDSize) - _, err := oh.Reference.ReadFrom(r.scannerReader) - if err != nil { - return nil, err - } - } - } - - oh.ContentOffset = r.scannerReader.offset - err = r.zr.Reset(r.scannerReader) - if err != nil { - return nil, fmt.Errorf("zlib reset error: %s", err) - } - - if !oh.Type.IsDelta() { - r.hasher.Reset(oh.Type, oh.Size) - - var mw io.Writer = r.hasher - if r.storage != nil { - w, err := r.storage.RawObjectWriter(oh.Type, oh.Size) - if err != nil { - return nil, err - } - - defer w.Close() - mw = io.MultiWriter(r.hasher, w) - } - - // If the reader isn't seekable, and low memory mode - // isn't supported, keep the contents of the objects in - // memory. - if !r.lowMemoryMode && r.seeker == nil { - oh.content = gogitsync.GetBytesBuffer() - mw = io.MultiWriter(mw, oh.content) - } - if r.hasher256 != nil { - r.hasher256.Reset(oh.Type, oh.Size) - mw = io.MultiWriter(mw, r.hasher256) - } - - // For non delta objects, simply calculate the hash of each object. - _, err = ioutil.CopyBufferPool(mw, r.zr.Reader) - if err != nil { - return nil, err - } - - oh.Hash = r.hasher.Sum() - if r.hasher256 != nil { - h := r.hasher256.Sum() - oh.Hash256 = &h - } - } else { - // If data source is not io.Seeker, keep the content - // in the cache, so that it can be accessed by the Parser. - if !r.lowMemoryMode { - oh.content = gogitsync.GetBytesBuffer() - _, err = oh.content.ReadFrom(r.zr.Reader) - if err != nil { - return nil, err - } - } else { - // We don't know the compressed length, so we can't seek to - // the next object, we must discard the data instead. - _, err = ioutil.CopyBufferPool(io.Discard, r.zr.Reader) - if err != nil { - return nil, err - } - } - } - r.scannerReader.Flush() - oh.Crc32 = r.crc.Sum32() - - r.packData.Section = ObjectSection - r.packData.objectHeader = oh - - return nil, nil -} - -// packFooter parses the packfile checksum. -// If the checksum cannot be parsed, or it does not match the checksum -// calculated during the scanning process, an [ErrMalformedPackfile] is -// returned. -func packFooter(r *Scanner) (stateFn, error) { - r.scannerReader.Flush() - - actual := r.packhash.Sum(nil) - - var checksum plumbing.Hash - _, err := checksum.ReadFrom(r.scannerReader) - if err != nil { - return nil, fmt.Errorf("cannot read PACK checksum: %w", ErrMalformedPackfile) - } - - if checksum.Compare(actual) != 0 { - return nil, fmt.Errorf("checksum mismatch expected %q but found %q: %w", - hex.EncodeToString(actual), checksum, ErrMalformedPackfile) - } - - r.packData.Section = FooterSection - r.packData.checksum = checksum - r.nextFn = nil - - return nil, nil -} - -func readVariableLengthSize(first byte, reader io.ByteReader) (uint64, error) { - // Extract the first part of the size (last 3 bits of the first byte). - size := uint64(first & 0x0F) - - // | 001xxxx | xxxxxxxx | xxxxxxxx | ... - // - // ^^^ ^^^^^^^^ ^^^^^^^^ - // Type Size Part 1 Size Part 2 - // - // Check if more bytes are needed to fully determine the size. - if first&maskContinue != 0 { - shift := uint(4) - - for { - b, err := reader.ReadByte() - if err != nil { - return 0, err - } - - // Add the next 7 bits to the size. - size |= uint64(b&0x7F) << shift - - // Check if the continuation bit is set. - if b&maskContinue == 0 { - break - } - - // Prepare for the next byte. - shift += 7 - } - } - return size, nil -} - -func parseType(b byte) plumbing.ObjectType { - return plumbing.ObjectType((b & maskType) >> firstLengthBits) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_options.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_options.go deleted file mode 100644 index 166cb387..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_options.go +++ /dev/null @@ -1,17 +0,0 @@ -package packfile - -import ( - "github.com/go-git/go-git/v6/plumbing" - format "github.com/go-git/go-git/v6/plumbing/format/config" -) - -type ScannerOption func(*Scanner) - -// WithSHA256 enables the SHA256 hashing while scanning a pack file. -func WithSHA256() ScannerOption { - return func(s *Scanner) { - h := plumbing.NewHasher(format.SHA256, plumbing.AnyObject, 0) - s.objectIDSize = format.SHA256Size - s.hasher256 = &h - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_reader.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_reader.go deleted file mode 100644 index 130f2144..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/scanner_reader.go +++ /dev/null @@ -1,99 +0,0 @@ -package packfile - -import ( - "bufio" - "io" -) - -// scannerReader has the following characteristics: -// - Provides an io.SeekReader impl for bufio.Reader, when the underlying -// reader supports it. -// - Keeps track of the current read position, for when the underlying reader -// isn't an io.SeekReader, but we still want to know the current offset. -// - Writes to the hash writer what it reads, with the aid of a smaller buffer. -// The buffer helps avoid a performance penalty for performing small writes -// to the crc32 hash writer. -// -// Note that this is passed on to zlib, and it mmust support io.BytesReader, else -// it won't be able to just read the content of the current object, but rather it -// will read the entire packfile. -// -// scannerReader is not thread-safe. -type scannerReader struct { - reader io.Reader - crc io.Writer - rbuf *bufio.Reader - wbuf *bufio.Writer - offset int64 - seeker io.Seeker -} - -func newScannerReader(r io.Reader, h io.Writer) *scannerReader { - sr := &scannerReader{ - rbuf: bufio.NewReader(nil), - wbuf: bufio.NewWriterSize(nil, 64), - crc: h, - } - sr.Reset(r) - - return sr -} - -func (r *scannerReader) Reset(reader io.Reader) { - r.reader = reader - r.rbuf.Reset(r.reader) - r.wbuf.Reset(r.crc) - - r.offset = 0 - - seeker, ok := r.reader.(io.ReadSeeker) - r.seeker = seeker - - if ok { - r.offset, _ = seeker.Seek(0, io.SeekStart) - } -} - -func (r *scannerReader) Read(p []byte) (n int, err error) { - n, err = r.rbuf.Read(p) - - r.offset += int64(n) - if _, err := r.wbuf.Write(p[:n]); err != nil { - return n, err - } - return -} - -func (r *scannerReader) ReadByte() (b byte, err error) { - b, err = r.rbuf.ReadByte() - if err == nil { - r.offset++ - return b, r.wbuf.WriteByte(b) - } - return -} - -func (r *scannerReader) Flush() error { - return r.wbuf.Flush() -} - -// Seek seeks to a location. If the underlying reader is not an io.ReadSeeker, -// then only whence=io.SeekCurrent is supported, any other operation fails. -func (r *scannerReader) Seek(offset int64, whence int) (int64, error) { - var err error - - if r.seeker == nil { - if whence != io.SeekCurrent || offset != 0 { - return -1, ErrSeekNotSupported - } - } - - if whence == io.SeekCurrent && offset == 0 { - return r.offset, nil - } - - r.offset, err = r.seeker.Seek(offset, whence) - r.rbuf.Reset(r.reader) - - return r.offset, err -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/types.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/types.go deleted file mode 100644 index 1c192975..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/packfile/types.go +++ /dev/null @@ -1,82 +0,0 @@ -package packfile - -import ( - "bytes" - - "github.com/go-git/go-git/v6/plumbing" -) - -type Version uint32 - -const ( - V2 Version = 2 -) - -func (v Version) Supported() bool { - switch v { - case V2: - return true - default: - return false - } -} - -// ObjectHeader contains the information related to the object, this information -// is collected from the previous bytes to the content of the object. -type ObjectHeader struct { - Type plumbing.ObjectType - Offset int64 - ContentOffset int64 - Size int64 - Reference plumbing.Hash - OffsetReference int64 - Crc32 uint32 - Hash plumbing.Hash - Hash256 *plumbing.Hash - - content *bytes.Buffer - parent *ObjectHeader - diskType plumbing.ObjectType - externalRef bool -} - -// ID returns the preferred object ID. -func (oh *ObjectHeader) ID() plumbing.Hash { - if oh.Hash256 != nil { - return *oh.Hash256 - } - return oh.Hash -} - -type SectionType int - -const ( - HeaderSection SectionType = iota - ObjectSection - FooterSection -) - -type Header struct { - Version Version - ObjectsQty uint32 -} - -type PackData struct { - Section SectionType - header Header - objectHeader ObjectHeader - checksum plumbing.Hash -} - -func (p PackData) Value() interface{} { - switch p.Section { - case HeaderSection: - return p.header - case ObjectSection: - return p.objectHeader - case FooterSection: - return p.checksum - default: - return nil - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/common.go deleted file mode 100644 index 8407b3b7..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/common.go +++ /dev/null @@ -1,58 +0,0 @@ -package pktline - -import ( - "errors" -) - -const ( - // Err is returned when the pktline has encountered an error. - Err = iota - 1 - - // Flush is the numeric value of a flush packet. It is returned when the - // pktline is a flush packet. - Flush - - // Delim is the numeric value of a delim packet. It is returned when the - // pktline is a delim packet. - Delim - - // ResponseEnd is the numeric value of a response-end packet. It is - // returned when the pktline is a response-end packet. - ResponseEnd -) - -const ( - // MaxPayloadSize is the maximum payload size of a pkt-line in bytes. - // See https://git-scm.com/docs/protocol-common#_pkt_line_format - MaxPayloadSize = MaxSize - LenSize - - // MaxSize is the maximum packet size of a pkt-line in bytes. - // See https://git-scm.com/docs/protocol-common#_pkt_line_format - MaxSize = 65520 - - // LenSize is the size of the packet length in bytes. - LenSize = 4 -) - -var ( - // ErrPayloadTooLong is returned by the Encode methods when any of the - // provided payloads is bigger than MaxPayloadSize. - ErrPayloadTooLong = errors.New("payload is too long") - - // ErrInvalidPktLen is returned by Err() when an invalid pkt-len is found. - ErrInvalidPktLen = errors.New("invalid pkt-len found") -) - -var ( - // flushPkt are the contents of a flush-pkt pkt-line. - flushPkt = []byte{'0', '0', '0', '0'} - - // delimPkt are the contents of a delim-pkt pkt-line. - delimPkt = []byte{'0', '0', '0', '1'} - - // responseEndPkt are the contents of a response-end-pkt pkt-line. - responseEndPkt = []byte{'0', '0', '0', '2'} - - // emptyPkt is an empty string pkt-line payload. - emptyPkt = []byte{'0', '0', '0', '4'} -) diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/error.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/error.go deleted file mode 100644 index 852b47d0..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/error.go +++ /dev/null @@ -1,51 +0,0 @@ -package pktline - -import ( - "errors" - "io" -) - -var ( - // ErrInvalidErrorLine is returned by Decode when the packet line is not an - // error line. - ErrInvalidErrorLine = errors.New("expected an error-line") - - // ErrNilWriter is returned when a nil writer is passed to WritePacket. - ErrNilWriter = errors.New("nil writer") - - errPrefix = []byte("ERR ") -) - -const ( - errPrefixSize = LenSize -) - -// ErrorLine is a packet line that contains an error message. -// Once this packet is sent by client or server, the data transfer process is -// terminated. -// See https://git-scm.com/docs/pack-protocol#_pkt_line_format -type ErrorLine struct { - Text string -} - -// Error implements the error interface. -func (e *ErrorLine) Error() string { - return e.Text -} - -// Encode encodes the ErrorLine into a packet line. -func (e *ErrorLine) Encode(w io.Writer) error { - _, err := Writef(w, "%s%s\n", errPrefix, e.Text) - return err -} - -// Decode decodes a packet line into an ErrorLine. -func (e *ErrorLine) Decode(r io.Reader) error { - _, _, err := ReadLine(r) - var el *ErrorLine - if !errors.As(err, &el) { - return ErrInvalidErrorLine - } - e.Text = el.Text - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/length.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/length.go deleted file mode 100644 index 9b152dd6..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/length.go +++ /dev/null @@ -1,89 +0,0 @@ -package pktline - -import "fmt" - -// ParseLength parses a four digit hexadecimal number from the given byte slice -// into its integer representation. If the byte slice contains non-hexadecimal, -// it will return an error. -func ParseLength(b []byte) (int, error) { - if b == nil { - return Err, fmt.Errorf("%w: missing pkt-line", ErrInvalidPktLen) - } - - n, err := hexDecode(b) - if err != nil { - return Err, err - } - - if n == 3 { - return Err, fmt.Errorf("%w: %04x", ErrInvalidPktLen, n) - } - - // Limit the maximum size of a pkt-line to 65520 bytes. - // Fixes: b4177b89c08b (plumbing: format: pktline, Accept oversized pkt-lines up to 65524 bytes) - // See https://github.com/git/git/commit/7841c4801ce51f1f62d376d164372e8677c6bc94 - if n > MaxSize { - return Err, fmt.Errorf("%w: %04x is too big", ErrInvalidPktLen, n) - } - - return n, nil -} - -// Turns the hexadecimal representation of a number in a byte slice into -// a number. This function substitute strconv.ParseUint(string(buf), 16, -// 16) and/or hex.Decode, to avoid generating new strings, thus helping the -// GC. -func hexDecode(buf []byte) (int, error) { - if len(buf) < 4 { - return 0, fmt.Errorf("%w: small pkt-line buffer", ErrInvalidPktLen) - } - - var ret int - for i := 0; i < LenSize; i++ { - n, err := asciiHexToByte(buf[i]) - if err != nil { - return 0, fmt.Errorf("%w: %w", ErrInvalidPktLen, err) - } - ret = 16*ret + int(n) - } - return ret, nil -} - -// turns the hexadecimal ascii representation of a byte into its -// numerical value. Example: from 'b' to 11 (0xb). -func asciiHexToByte(b byte) (byte, error) { - switch { - case b >= '0' && b <= '9': - return b - '0', nil - case b >= 'a' && b <= 'f': - return b - 'a' + 10, nil - case b >= 'A' && b <= 'F': - return b - 'A' + 10, nil - default: - return 0, fmt.Errorf("not a hexadecimal byte %q", b) - } -} - -// Returns the hexadecimal ascii representation of the 16 less -// significant bits of n. The length of the returned slice will always -// be 4. Example: if n is 1234 (0x4d2), the return value will be -// []byte{'0', '4', 'd', '2'}. -func asciiHex16(n int) []byte { - var ret [4]byte - ret[0] = byteToASCIIHex(byte(n & 0xf000 >> 12)) - ret[1] = byteToASCIIHex(byte(n & 0x0f00 >> 8)) - ret[2] = byteToASCIIHex(byte(n & 0x00f0 >> 4)) - ret[3] = byteToASCIIHex(byte(n & 0x000f)) - - return ret[:] -} - -// turns a byte into its hexadecimal ascii representation. Example: -// from 11 (0xb) to 'b'. -func byteToASCIIHex(n byte) byte { - if n < 10 { - return '0' + n - } - - return 'a' - 10 + n -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/pktline.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/pktline.go deleted file mode 100644 index b5697fde..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/pktline.go +++ /dev/null @@ -1,234 +0,0 @@ -package pktline - -import ( - "bytes" - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/trace" -) - -// Write writes a pktline packet. -func Write(w io.Writer, p []byte) (n int, err error) { - if w == nil { - return 0, ErrNilWriter - } - - defer func() { - if err == nil { - maskPackDataTrace(true, n, p) - } - }() - - if len(p) == 0 { - return w.Write(emptyPkt) - } - - if len(p) > MaxPayloadSize { - return 0, ErrPayloadTooLong - } - - pktlen := len(p) + LenSize - n, err = w.Write(asciiHex16(pktlen)) - if err != nil { - return - } - - n2, err := w.Write(p) - n += n2 - return -} - -// Writef writes a pktline packet from a format string. -func Writef(w io.Writer, format string, a ...interface{}) (n int, err error) { - if len(a) == 0 { - return Write(w, []byte(format)) - } - return Write(w, fmt.Appendf(nil, format, a...)) -} - -// Writeln writes a pktline packet from a string and appends a newline. -func Writeln(w io.Writer, s string) (n int, err error) { - return Write(w, []byte(s+"\n")) -} - -// WriteString writes a pktline packet from a string. -func WriteString(w io.Writer, s string) (n int, err error) { - return Write(w, []byte(s)) -} - -// WriteError writes an error packet. -func WriteError(w io.Writer, e error) (n int, err error) { - return Writef(w, "%s%s\n", errPrefix, e.Error()) -} - -// WriteFlush writes a flush packet. -// This always writes 4 bytes. -func WriteFlush(w io.Writer) (err error) { - defer func() { - if err == nil { - trace.Packet.Printf("packet: > 0000") - } - }() - - _, err = w.Write(flushPkt) - return err -} - -// WriteDelim writes a delimiter packet. -// This always writes 4 bytes. -func WriteDelim(w io.Writer) (err error) { - defer func() { - if err == nil { - trace.Packet.Printf("packet: > 0001") - } - }() - - _, err = w.Write(delimPkt) - return err -} - -// WriteResponseEnd writes a response-end packet. -// This always writes 4 bytes. -func WriteResponseEnd(w io.Writer) (err error) { - defer func() { - if err == nil { - trace.Packet.Printf("packet: > 0002") - } - }() - - _, err = w.Write(responseEndPkt) - return err -} - -// Read reads a pktline packet payload into p and returns the packet full -// length. -// -// If p is less than 4 bytes, Read returns ErrInvalidPktLen. If p cannot hold -// the entire packet, Read returns io.ErrUnexpectedEOF. -// The error can be of type *ErrorLine if the packet is an error packet. -// -// Use packet length to determine the type of packet i.e. 0 is a flush packet, -// 1 is a delim packet, 2 is a response-end packet, and a length greater or -// equal to 4 is a data packet. -func Read(r io.Reader, p []byte) (l int, err error) { - _, err = io.ReadFull(r, p[:LenSize]) - if err != nil { - if errors.Is(err, io.ErrUnexpectedEOF) { - return Err, fmt.Errorf("%w: short pkt-line %d", ErrInvalidPktLen, len(p[:LenSize])) - } - return Err, err - } - - length, err := ParseLength(p) - if err != nil { - return Err, err - } - - switch length { - case Flush, Delim, ResponseEnd: - trace.Packet.Printf("packet: < %04x", length) - return length, nil - case LenSize: // empty line - trace.Packet.Printf("packet: < %04x", length) - return length, nil - } - - _, err = io.ReadFull(r, p[LenSize:length]) - if err != nil { - return Err, err - } - - if bytes.HasPrefix(p[LenSize:], errPrefix) { - err = &ErrorLine{ - Text: string(bytes.TrimSpace(p[LenSize+errPrefixSize : length])), - } - } - - maskPackDataTrace(false, length, p[LenSize:length]) - - return length, err -} - -// ReadLine reads a packet line into a temporary shared buffer and -// returns the packet length and payload. -// Subsequent calls to ReadLine may overwrite the buffer. -// -// Use packet length to determine the type of packet i.e. 0 is a flush packet, -// 1 is a delim packet, 2 is a response-end packet, and a length greater or -// equal to 4 is a data packet. -// -// The error can be of type *ErrorLine if the packet is an error packet. -func ReadLine(r io.Reader) (l int, p []byte, err error) { - buf := GetBuffer() - defer PutBuffer(buf) - - l, err = Read(r, (*buf)[:]) - if l < LenSize { - return l, nil, err - } - - return l, (*buf)[LenSize:l], err -} - -// PeekLine reads a packet line without consuming it. -// -// Use packet length to determine the type of packet i.e. 0 is a flush packet, -// 1 is a delim packet, 2 is a response-end packet, and a length greater or -// equal to 4 is a data packet. -// -// The error can be of type *ErrorLine if the packet is an error packet. -func PeekLine(r ioutil.ReadPeeker) (l int, p []byte, err error) { - n, err := r.Peek(LenSize) - if err != nil { - return Err, nil, err - } - - length, err := ParseLength(n) - if err != nil { - return Err, nil, err - } - - switch length { - case Flush, Delim, ResponseEnd: - trace.Packet.Printf("packet: < %04x", length) - return length, nil, nil - case LenSize: // empty line - trace.Packet.Printf("packet: < %04x", length) - return length, []byte{}, nil - } - - data, err := r.Peek(length) - if err != nil { - return Err, nil, err - } - - buf := data[LenSize:length] - if bytes.HasPrefix(buf, errPrefix) { - err = &ErrorLine{ - Text: string(bytes.TrimSpace(buf[errPrefixSize:])), - } - } - - maskPackDataTrace(false, length, buf) - - return length, buf, err -} - -func maskPackDataTrace(out bool, l int, data []byte) { - if !trace.Packet.Enabled() { - return - } - - output := []byte("[ PACKDATA ]") - if l < 400 && len(data) > 0 && data[0] != 1 { // [sideband.PackData] - output = data - } - arrow := '<' - if out { - arrow = '>' - } - trace.Packet.Printf("packet: %c %04x %q", arrow, l, output) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/scanner.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/scanner.go deleted file mode 100644 index ad6b2a5d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/scanner.go +++ /dev/null @@ -1,75 +0,0 @@ -package pktline - -import ( - "errors" - "io" -) - -// Scanner provides a convenient interface for reading the payloads of a -// series of pkt-lines. It takes an io.Reader providing the source, -// which then can be tokenized through repeated calls to the Scan -// method. -// -// After each Scan call, the Bytes method will return the payload of the -// corresponding pkt-line on a shared buffer, which will be 65516 bytes -// or smaller. Flush pkt-lines are represented by empty byte slices. -// -// Scanning stops at EOF or the first I/O error. -type Scanner struct { - r io.Reader // The reader provided by the client - err error // Sticky error - buf [MaxSize]byte // Buffer used to read the pktlines - n int // Number of bytes read in the last read -} - -// NewScanner returns a new Scanner to read from r. -func NewScanner(r io.Reader) *Scanner { - return &Scanner{ - r: r, - } -} - -// Err returns the first error encountered by the Scanner. -func (s *Scanner) Err() error { - return s.err -} - -// Scan advances the Scanner to the next pkt-line, whose payload will -// then be available through the Bytes method. Scanning stops at EOF -// or the first I/O error. After Scan returns false, the Err method -// will return any error that occurred during scanning, except that if -// it was io.EOF, Err will return nil. -func (s *Scanner) Scan() bool { - if s.r == nil { - return false - } - s.n, s.err = Read(s.r, s.buf[:]) - if errors.Is(s.err, io.EOF) { - s.err = nil - return false - } - return s.err == nil -} - -// Bytes returns the most recent packet generated by a call to Scan. -// The underlying array may point to data that will be overwritten by a -// subsequent call to Scan. It does no allocation. -// This returns nil if the last scan was a special packet such as a [Flush], -// [Delim], or [ResponseEnd]. -func (s *Scanner) Bytes() []byte { - if s.n >= LenSize { - return s.buf[LenSize:s.n] - } - return nil -} - -// Text returns the most recent packet generated by a call to Scan. -func (s *Scanner) Text() string { - return string(s.Bytes()) -} - -// Len returns the length of the most recent packet generated by a call to -// Scan. -func (s *Scanner) Len() int { - return s.n -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/sync.go b/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/sync.go deleted file mode 100644 index 55fe7db3..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/format/pktline/sync.go +++ /dev/null @@ -1,25 +0,0 @@ -package pktline - -import "sync" - -var pktBuffer = sync.Pool{ - New: func() interface{} { - var b [MaxSize]byte - return &b - }, -} - -// GetBuffer returns a *[MaxSize]byte that is managed by a sync.Pool. The -// initial slice length will be 65520 (65kb). -// -// After use, the *[MaxSize]byte should be put back into the sync.Pool by -// calling PutBuffer. -func GetBuffer() *[MaxSize]byte { - buf := pktBuffer.Get().(*[MaxSize]byte) - return buf -} - -// PutBuffer puts buf back into its sync.Pool. -func PutBuffer(buf *[MaxSize]byte) { - pktBuffer.Put(buf) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/hash.go b/vendor/github.com/go-git/go-git/v6/plumbing/hash.go deleted file mode 100644 index 61aeca7d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/hash.go +++ /dev/null @@ -1,93 +0,0 @@ -package plumbing - -import ( - "crypto" - "encoding/hex" - "hash" - "sort" - "strconv" - - format "github.com/go-git/go-git/v6/plumbing/format/config" -) - -// Hash SHA1 hashed content -type Hash = ObjectID - -// ZeroHash is an ObjectID with value zero. -var ZeroHash ObjectID - -// ComputeHash compute the hash for a given ObjectType and content -func ComputeHash(t ObjectType, content []byte) Hash { - ha, err := newHasher(format.SHA1) - if err != nil { - return ZeroHash - } - h, _ := ha.Compute(t, content) - return h -} - -// NewHash return a new Hash based on a hexadecimal hash representation. -// Invalid input results into an empty hash. -// -// deprecated: Use the new FromHex instead. -func NewHash(s string) Hash { - h, _ := FromHex(s) - return h -} - -type Hasher struct { - hash.Hash - format format.ObjectFormat -} - -func NewHasher(f format.ObjectFormat, t ObjectType, size int64) Hasher { - h := Hasher{format: f} - switch f { - case format.SHA256: - h.Hash = crypto.SHA256.New() - default: - // Use SHA1 by default - // TODO: return error when format is not supported - h.Hash = crypto.SHA1.New() - } - h.Reset(t, size) - return h -} - -func (h Hasher) Reset(t ObjectType, size int64) { - h.Hash.Reset() - h.Write(t.Bytes()) - h.Write([]byte(" ")) - h.Write([]byte(strconv.FormatInt(size, 10))) - h.Write([]byte{0}) -} - -func (h Hasher) Sum() (hash Hash) { - hash.format = h.format - hash.Write(h.Hash.Sum(nil)) - return -} - -// HashesSort sorts a slice of Hashes in increasing order. -func HashesSort(a []Hash) { - sort.Sort(HashSlice(a)) -} - -// HashSlice attaches the methods of sort.Interface to []Hash, sorting in -// increasing order. -type HashSlice []Hash - -func (p HashSlice) Len() int { return len(p) } -func (p HashSlice) Less(i, j int) bool { return p[i].Compare(p[j].Bytes()) < 0 } -func (p HashSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -// IsHash returns true if the given string is a valid hash. -func IsHash(s string) bool { - switch len(s) { - case format.SHA1HexSize, format.SHA256HexSize: - _, err := hex.DecodeString(s) - return err == nil - default: - return false - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/hash/hash.go b/vendor/github.com/go-git/go-git/v6/plumbing/hash/hash.go deleted file mode 100644 index f76a9324..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/hash/hash.go +++ /dev/null @@ -1,80 +0,0 @@ -// package hash provides a way for managing the -// underlying hash implementations used across go-git. -package hash - -import ( - "crypto" - "errors" - "fmt" - "hash" - - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/pjbgf/sha1cd" -) - -var ( - ErrUnsupportedHashFunction = errors.New("unsupported hash function") -) - -// algos is a map of hash algorithms. -var algos = map[crypto.Hash]func() hash.Hash{} - -func init() { - reset() -} - -// reset resets the default algos value. Can be used after running tests -// that registers new algorithms to avoid side effects. -func reset() { - algos[crypto.SHA1] = sha1cd.New - algos[crypto.SHA256] = crypto.SHA256.New -} - -// RegisterHash allows for the hash algorithm used to be overridden. -// This ensures the hash selection for go-git must be explicit, when -// overriding the default value. -func RegisterHash(h crypto.Hash, f func() hash.Hash) error { - if f == nil { - return fmt.Errorf("cannot register hash: f is nil") - } - - switch h { - case crypto.SHA1: - algos[h] = f - case crypto.SHA256: - algos[h] = f - default: - return fmt.Errorf("%w: %v", ErrUnsupportedHashFunction, h) - } - return nil -} - -// Hash is the same as hash.Hash. This allows consumers -// to not having to import this package alongside "hash". -type Hash interface { - hash.Hash -} - -// New returns a new Hash for the given hash function. -// It panics if the hash function is not registered. -func New(h crypto.Hash) Hash { - hh, ok := algos[h] - if !ok { - panic(fmt.Sprintf("hash algorithm not registered: %v", h)) - } - return hh() -} - -// FromObjectFormat returns the correct Hash to be used based on the -// ObjectFormat being used. -// If the ObjectFormat is not recognised, returns ErrInvalidObjectFormat. -func FromObjectFormat(f format.ObjectFormat) (hash.Hash, error) { - switch f { - case format.SHA1: - return New(crypto.SHA1), nil - case format.SHA256: - return New(crypto.SHA256), nil - default: - return nil, format.ErrInvalidObjectFormat - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/hasher.go b/vendor/github.com/go-git/go-git/v6/plumbing/hasher.go deleted file mode 100644 index e82312b4..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/hasher.go +++ /dev/null @@ -1,109 +0,0 @@ -package plumbing - -import ( - "crypto" - "fmt" - "hash" - "strconv" - "sync" - - format "github.com/go-git/go-git/v6/plumbing/format/config" -) - -// ObjectHasher computes hashes for Git objects. A few differences -// it has when compared to Hasher: -// -// - ObjectType awareness: produces either SHA1 or SHA256 hashes -// depending on the format needed. -// - Thread-safety. -// - API restricts ability of generating invalid hashes. -type ObjectHasher struct { - hasher hash.Hash - m sync.Mutex - format format.ObjectFormat -} - -func (h *ObjectHasher) Size() int { - return h.hasher.Size() -} - -func (h *ObjectHasher) Write(p []byte) (int, error) { - return h.hasher.Write(p) -} - -func (h *ObjectHasher) Compute(ot ObjectType, d []byte) (ObjectID, error) { - h.m.Lock() - h.hasher.Reset() - - out := ObjectID{format: h.format} - writeHeader(h.hasher, ot, int64(len(d))) - _, err := h.hasher.Write(d) - if err != nil { - h.m.Unlock() - return out, fmt.Errorf("failed to compute hash: %w", err) - } - - copy(out.hash[:], h.hasher.Sum(out.hash[:0])) - h.m.Unlock() - return out, nil -} - -// newHasher returns a new ObjectHasher for the given -// ObjectFormat. -func newHasher(f format.ObjectFormat) (*ObjectHasher, error) { - var hasher hash.Hash - switch f { - case format.SHA1: - hasher = crypto.SHA1.New() - case format.SHA256: - hasher = crypto.SHA256.New() - default: - return nil, fmt.Errorf("unsupported object format: %s", f) - } - return &ObjectHasher{ - hasher: hasher, - format: f, - }, nil -} - -// FromObjectFormat returns the correct ObjectHasher for the given -// ObjectFormat. -// -// If the format is not recognised, an ErrInvalidObjectFormat error -// is returned. -func FromObjectFormat(f format.ObjectFormat) (*ObjectHasher, error) { - switch f { - case format.SHA1, format.SHA256: - return newHasher(f) - default: - return nil, format.ErrInvalidObjectFormat - } -} - -// FromHash returns the correct ObjectHasher for the given -// Hash. -// -// If the hash type is not recognised, an ErrUnsupportedHashFunction -// error is returned. -func FromHash(h hash.Hash) (*ObjectHasher, error) { - var f format.ObjectFormat - switch h.Size() { - case format.SHA1Size: - f = format.SHA1 - case format.SHA256Size: - f = format.SHA256 - default: - return nil, fmt.Errorf("unsupported hash function: %T", h) - } - return newHasher(f) -} - -func writeHeader(h hash.Hash, ot ObjectType, sz int64) { - // TODO: Optimise hasher.Write calls. - // Writing into hash in amounts smaller than oh.BlockSize() is - // sub-optimal. - h.Write(ot.Bytes()) - h.Write([]byte(" ")) - h.Write([]byte(strconv.FormatInt(sz, 10))) - h.Write([]byte{0}) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/memory.go b/vendor/github.com/go-git/go-git/v6/plumbing/memory.go deleted file mode 100644 index 4e3acf98..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/memory.go +++ /dev/null @@ -1,78 +0,0 @@ -package plumbing - -import ( - "bytes" - "io" -) - -// MemoryObject on memory Object implementation -type MemoryObject struct { - t ObjectType - h Hash - cont []byte - sz int64 -} - -// Hash returns the object Hash, the hash is calculated on-the-fly the first -// time it's called, in all subsequent calls the same Hash is returned even -// if the type or the content have changed. The Hash is only generated if the -// size of the content is exactly the object size. -func (o *MemoryObject) Hash() Hash { - if o.h.IsZero() && int64(len(o.cont)) == o.sz { - o.h = ComputeHash(o.t, o.cont) - } - - if o.h.IsZero() { - return ZeroHash - } - - return o.h -} - -// Type returns the ObjectType -func (o *MemoryObject) Type() ObjectType { return o.t } - -// SetType sets the ObjectType -func (o *MemoryObject) SetType(t ObjectType) { o.t = t } - -// Size returns the size of the object -func (o *MemoryObject) Size() int64 { return o.sz } - -// SetSize set the object size, a content of the given size should be written -// afterwards -func (o *MemoryObject) SetSize(s int64) { - o.sz = s -} - -// Reader returns an io.ReadCloser used to read the object's content. -// -// For a MemoryObject, this reader is seekable. -func (o *MemoryObject) Reader() (io.ReadCloser, error) { - return nopCloser{bytes.NewReader(o.cont)}, nil -} - -// Writer returns a ObjectWriter used to write the object's content. -func (o *MemoryObject) Writer() (io.WriteCloser, error) { - return o, nil -} - -func (o *MemoryObject) Write(p []byte) (n int, err error) { - o.cont = append(o.cont, p...) - o.sz = int64(len(o.cont)) - - return len(p), nil -} - -// Close releases any resources consumed by the object when it is acting as a -// ObjectWriter. -func (o *MemoryObject) Close() error { return nil } - -// nopCloser exposes the extra methods of bytes.Reader while nopping Close(). -// -// This allows clients to attempt seeking in a cached Blob's Reader. -type nopCloser struct { - *bytes.Reader -} - -// Close does nothing. -func (nc nopCloser) Close() error { return nil } diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object.go b/vendor/github.com/go-git/go-git/v6/plumbing/object.go deleted file mode 100644 index 3ee9de9f..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object.go +++ /dev/null @@ -1,111 +0,0 @@ -// package plumbing implement the core interfaces and structs used by go-git -package plumbing - -import ( - "errors" - "io" -) - -var ( - ErrObjectNotFound = errors.New("object not found") - // ErrInvalidType is returned when an invalid object type is provided. - ErrInvalidType = errors.New("invalid object type") -) - -// Object is a generic representation of any git object -type EncodedObject interface { - Hash() Hash - Type() ObjectType - SetType(ObjectType) - Size() int64 - SetSize(int64) - Reader() (io.ReadCloser, error) - Writer() (io.WriteCloser, error) -} - -// DeltaObject is an EncodedObject representing a delta. -type DeltaObject interface { - EncodedObject - // BaseHash returns the hash of the object used as base for this delta. - BaseHash() Hash - // ActualHash returns the hash of the object after applying the delta. - ActualHash() Hash - // Size returns the size of the object after applying the delta. - ActualSize() int64 -} - -// ObjectType internal object type -// Integer values from 0 to 7 map to those exposed by git. -// AnyObject is used to represent any from 0 to 7. -type ObjectType int8 - -const ( - InvalidObject ObjectType = 0 - CommitObject ObjectType = 1 - TreeObject ObjectType = 2 - BlobObject ObjectType = 3 - TagObject ObjectType = 4 - // 5 reserved for future expansion - OFSDeltaObject ObjectType = 6 - REFDeltaObject ObjectType = 7 - - AnyObject ObjectType = -127 -) - -func (t ObjectType) String() string { - switch t { - case CommitObject: - return "commit" - case TreeObject: - return "tree" - case BlobObject: - return "blob" - case TagObject: - return "tag" - case OFSDeltaObject: - return "ofs-delta" - case REFDeltaObject: - return "ref-delta" - case AnyObject: - return "any" - default: - return "unknown" - } -} - -func (t ObjectType) Bytes() []byte { - return []byte(t.String()) -} - -// Valid returns true if t is a valid ObjectType. -func (t ObjectType) Valid() bool { - return t >= CommitObject && t <= REFDeltaObject -} - -// IsDelta returns true for any ObjectType that represents a delta (i.e. -// REFDeltaObject or OFSDeltaObject). -func (t ObjectType) IsDelta() bool { - return t == REFDeltaObject || t == OFSDeltaObject -} - -// ParseObjectType parses a string representation of ObjectType. It returns an -// error on parse failure. -func ParseObjectType(value string) (typ ObjectType, err error) { - switch value { - case "commit": - typ = CommitObject - case "tree": - typ = TreeObject - case "blob": - typ = BlobObject - case "tag": - typ = TagObject - case "ofs-delta": - typ = OFSDeltaObject - case "ref-delta": - typ = REFDeltaObject - default: - err = ErrInvalidType - } - return -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/blob.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/blob.go deleted file mode 100644 index 02e438bb..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/blob.go +++ /dev/null @@ -1,144 +0,0 @@ -package object - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// Blob is used to store arbitrary data - it is generally a file. -type Blob struct { - // Hash of the blob. - Hash plumbing.Hash - // Size of the (uncompressed) blob. - Size int64 - - obj plumbing.EncodedObject -} - -// GetBlob gets a blob from an object storer and decodes it. -func GetBlob(s storer.EncodedObjectStorer, h plumbing.Hash) (*Blob, error) { - o, err := s.EncodedObject(plumbing.BlobObject, h) - if err != nil { - return nil, err - } - - return DecodeBlob(o) -} - -// DecodeObject decodes an encoded object into a *Blob. -func DecodeBlob(o plumbing.EncodedObject) (*Blob, error) { - b := &Blob{} - if err := b.Decode(o); err != nil { - return nil, err - } - - return b, nil -} - -// ID returns the object ID of the blob. The returned value will always match -// the current value of Blob.Hash. -// -// ID is present to fulfill the Object interface. -func (b *Blob) ID() plumbing.Hash { - return b.Hash -} - -// Type returns the type of object. It always returns plumbing.BlobObject. -// -// Type is present to fulfill the Object interface. -func (b *Blob) Type() plumbing.ObjectType { - return plumbing.BlobObject -} - -// Decode transforms a plumbing.EncodedObject into a Blob struct. -func (b *Blob) Decode(o plumbing.EncodedObject) error { - if o.Type() != plumbing.BlobObject { - return ErrUnsupportedObject - } - - b.Hash = o.Hash() - b.Size = o.Size() - b.obj = o - - return nil -} - -// Encode transforms a Blob into a plumbing.EncodedObject. -func (b *Blob) Encode(o plumbing.EncodedObject) (err error) { - o.SetType(plumbing.BlobObject) - - w, err := o.Writer() - if err != nil { - return err - } - - defer ioutil.CheckClose(w, &err) - - r, err := b.Reader() - if err != nil { - return err - } - - defer ioutil.CheckClose(r, &err) - - _, err = ioutil.CopyBufferPool(w, r) - return err -} - -// Reader returns a reader allow the access to the content of the blob -func (b *Blob) Reader() (io.ReadCloser, error) { - return b.obj.Reader() -} - -// BlobIter provides an iterator for a set of blobs. -type BlobIter struct { - storer.EncodedObjectIter - s storer.EncodedObjectStorer -} - -// NewBlobIter takes a storer.EncodedObjectStorer and a -// storer.EncodedObjectIter and returns a *BlobIter that iterates over all -// blobs contained in the storer.EncodedObjectIter. -// -// Any non-blob object returned by the storer.EncodedObjectIter is skipped. -func NewBlobIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *BlobIter { - return &BlobIter{iter, s} -} - -// Next moves the iterator to the next blob and returns a pointer to it. If -// there are no more blobs, it returns io.EOF. -func (iter *BlobIter) Next() (*Blob, error) { - for { - obj, err := iter.EncodedObjectIter.Next() - if err != nil { - return nil, err - } - - if obj.Type() != plumbing.BlobObject { - continue - } - - return DecodeBlob(obj) - } -} - -// ForEach call the cb function for each blob contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *BlobIter) ForEach(cb func(*Blob) error) error { - return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { - if obj.Type() != plumbing.BlobObject { - return nil - } - - b, err := DecodeBlob(obj) - if err != nil { - return err - } - - return cb(b) - }) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/change.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/change.go deleted file mode 100644 index 23caf5e8..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/change.go +++ /dev/null @@ -1,159 +0,0 @@ -package object - -import ( - "bytes" - "context" - "fmt" - "strings" - - "github.com/go-git/go-git/v6/utils/merkletrie" -) - -// Change values represent a detected change between two git trees. For -// modifications, From is the original status of the node and To is its -// final status. For insertions, From is the zero value and for -// deletions To is the zero value. -type Change struct { - From ChangeEntry - To ChangeEntry -} - -var empty ChangeEntry - -// Action returns the kind of action represented by the change, an -// insertion, a deletion or a modification. -func (c *Change) Action() (merkletrie.Action, error) { - if c.From == empty && c.To == empty { - return merkletrie.Action(0), - fmt.Errorf("malformed change: empty from and to") - } - - if c.From == empty { - return merkletrie.Insert, nil - } - - if c.To == empty { - return merkletrie.Delete, nil - } - - return merkletrie.Modify, nil -} - -// Files returns the files before and after a change. -// For insertions from will be nil. For deletions to will be nil. -func (c *Change) Files() (from, to *File, err error) { - action, err := c.Action() - if err != nil { - return - } - - if action == merkletrie.Insert || action == merkletrie.Modify { - to, err = c.To.Tree.TreeEntryFile(&c.To.TreeEntry) - if !c.To.TreeEntry.Mode.IsFile() { - return nil, nil, nil - } - - if err != nil { - return - } - } - - if action == merkletrie.Delete || action == merkletrie.Modify { - from, err = c.From.Tree.TreeEntryFile(&c.From.TreeEntry) - if !c.From.TreeEntry.Mode.IsFile() { - return nil, nil, nil - } - - if err != nil { - return - } - } - - return -} - -func (c *Change) String() string { - action, err := c.Action() - if err != nil { - return "malformed change" - } - - return fmt.Sprintf("", action, c.name()) -} - -// Patch returns a Patch with all the file changes in chunks. This -// representation can be used to create several diff outputs. -func (c *Change) Patch() (*Patch, error) { - return c.PatchContext(context.Background()) -} - -// Patch returns a Patch with all the file changes in chunks. This -// representation can be used to create several diff outputs. -// If context expires, an non-nil error will be returned -// Provided context must be non-nil -func (c *Change) PatchContext(ctx context.Context) (*Patch, error) { - return getPatchContext(ctx, "", c) -} - -func (c *Change) name() string { - if c.From != empty { - return c.From.Name - } - - return c.To.Name -} - -// ChangeEntry values represent a node that has suffered a change. -type ChangeEntry struct { - // Full path of the node using "/" as separator. - Name string - // Parent tree of the node that has changed. - Tree *Tree - // The entry of the node. - TreeEntry TreeEntry -} - -// Changes represents a collection of changes between two git trees. -// Implements sort.Interface lexicographically over the path of the -// changed files. -type Changes []*Change - -func (c Changes) Len() int { - return len(c) -} - -func (c Changes) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -func (c Changes) Less(i, j int) bool { - return strings.Compare(c[i].name(), c[j].name()) < 0 -} - -func (c Changes) String() string { - var buffer bytes.Buffer - buffer.WriteString("[") - comma := "" - for _, v := range c { - buffer.WriteString(comma) - buffer.WriteString(v.String()) - comma = ", " - } - buffer.WriteString("]") - - return buffer.String() -} - -// Patch returns a Patch with all the changes in chunks. This -// representation can be used to create several diff outputs. -func (c Changes) Patch() (*Patch, error) { - return c.PatchContext(context.Background()) -} - -// Patch returns a Patch with all the changes in chunks. This -// representation can be used to create several diff outputs. -// If context expires, an non-nil error will be returned -// Provided context must be non-nil -func (c Changes) PatchContext(ctx context.Context) (*Patch, error) { - return getPatchContext(ctx, "", c...) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/change_adaptor.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/change_adaptor.go deleted file mode 100644 index d9504a6c..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/change_adaptor.go +++ /dev/null @@ -1,61 +0,0 @@ -package object - -import ( - "errors" - "fmt" - - "github.com/go-git/go-git/v6/utils/merkletrie" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// The following functions transform changes types form the merkletrie -// package to changes types from this package. - -func newChange(c merkletrie.Change) (*Change, error) { - ret := &Change{} - - var err error - if ret.From, err = newChangeEntry(c.From); err != nil { - return nil, fmt.Errorf("from field: %s", err) - } - - if ret.To, err = newChangeEntry(c.To); err != nil { - return nil, fmt.Errorf("to field: %s", err) - } - - return ret, nil -} - -func newChangeEntry(p noder.Path) (ChangeEntry, error) { - if p == nil { - return empty, nil - } - - asTreeNoder, ok := p.Last().(*treeNoder) - if !ok { - return ChangeEntry{}, errors.New("cannot transform non-TreeNoders") - } - - return ChangeEntry{ - Name: p.String(), - Tree: asTreeNoder.parent, - TreeEntry: TreeEntry{ - Name: asTreeNoder.name, - Mode: asTreeNoder.mode, - Hash: asTreeNoder.hash, - }, - }, nil -} - -func newChanges(src merkletrie.Changes) (Changes, error) { - ret := make(Changes, len(src)) - var err error - for i, e := range src { - ret[i], err = newChange(e) - if err != nil { - return nil, fmt.Errorf("change #%d: %s", i, err) - } - } - - return ret, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/commit.go deleted file mode 100644 index 97e52e59..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit.go +++ /dev/null @@ -1,579 +0,0 @@ -package object - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "strings" - - "github.com/ProtonMail/go-crypto/openpgp" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/sync" -) - -const ( - beginpgp string = "-----BEGIN PGP SIGNATURE-----" - endpgp string = "-----END PGP SIGNATURE-----" - headerpgp string = "gpgsig" - headerencoding string = "encoding" - - // https://github.com/git/git/blob/bcb6cae2966cc407ca1afc77413b3ef11103c175/Documentation/gitformat-signature.txt#L153 - // When a merge commit is created from a signed tag, the tag is embedded in - // the commit with the "mergetag" header. - headermergetag string = "mergetag" - - defaultUtf8CommitMessageEncoding MessageEncoding = "UTF-8" -) - -// Hash represents the hash of an object -type Hash plumbing.Hash - -// MessageEncoding represents the encoding of a commit -type MessageEncoding string - -// Commit points to a single tree, marking it as what the project looked like -// at a certain point in time. It contains meta-information about that point -// in time, such as a timestamp, the author of the changes since the last -// commit, a pointer to the previous commit(s), etc. -// http://shafiulazam.com/gitbook/1_the_git_object_model.html -type Commit struct { - // Hash of the commit object. - Hash plumbing.Hash - // Author is the original author of the commit. - Author Signature - // Committer is the one performing the commit, might be different from - // Author. - Committer Signature - // MergeTag is the embedded tag object when a merge commit is created by - // merging a signed tag. - MergeTag string - // PGPSignature is the PGP signature of the commit. - PGPSignature string - // Message is the commit message, contains arbitrary text. - Message string - // TreeHash is the hash of the root tree of the commit. - TreeHash plumbing.Hash - // ParentHashes are the hashes of the parent commits of the commit. - ParentHashes []plumbing.Hash - // Encoding is the encoding of the commit. - Encoding MessageEncoding - // List of extra headers of the commit - ExtraHeaders []ExtraHeader - - s storer.EncodedObjectStorer -} - -// ExtraHeader holds any non-standard header -type ExtraHeader struct { - // Header name - Key string - // Value of the header - Value string -} - -// Implement fmt.Formatter for ExtraHeader -func (h ExtraHeader) Format(f fmt.State, verb rune) { - switch verb { - case 'v': - fmt.Fprintf(f, "ExtraHeader{Key: %v, Value: %v}", h.Key, h.Value) - default: - fmt.Fprintf(f, "%s", h.Key) - if len(h.Value) > 0 { - fmt.Fprint(f, " ") - // Content may be spread on multiple lines, if so we need to - // prepend each of them with a space for "continuation". - value := strings.TrimSuffix(h.Value, "\n") - lines := strings.Split(value, "\n") - fmt.Fprint(f, strings.Join(lines, "\n ")) - } - } -} - -// Parse an extra header and indicate whether it may be continue on the next line -func parseExtraHeader(line []byte) (ExtraHeader, bool) { - split := bytes.SplitN(line, []byte{' '}, 2) - - out := ExtraHeader { - Key: string(bytes.TrimRight(split[0], "\n")), - Value: "", - } - - if len(split) == 2 { - out.Value += string(split[1]) - return out, true - } else { - return out, false - } -} - -// GetCommit gets a commit from an object storer and decodes it. -func GetCommit(s storer.EncodedObjectStorer, h plumbing.Hash) (*Commit, error) { - o, err := s.EncodedObject(plumbing.CommitObject, h) - if err != nil { - return nil, err - } - - return DecodeCommit(s, o) -} - -// DecodeCommit decodes an encoded object into a *Commit and associates it to -// the given object storer. -func DecodeCommit(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Commit, error) { - c := &Commit{s: s} - if err := c.Decode(o); err != nil { - return nil, err - } - - return c, nil -} - -// Tree returns the Tree from the commit. -func (c *Commit) Tree() (*Tree, error) { - return GetTree(c.s, c.TreeHash) -} - -// PatchContext returns the Patch between the actual commit and the provided one. -// Error will be return if context expires. Provided context must be non-nil. -// -// NOTE: Since version 5.1.0 the renames are correctly handled, the settings -// used are the recommended options DefaultDiffTreeOptions. -func (c *Commit) PatchContext(ctx context.Context, to *Commit) (*Patch, error) { - fromTree, err := c.Tree() - if err != nil { - return nil, err - } - - var toTree *Tree - if to != nil { - toTree, err = to.Tree() - if err != nil { - return nil, err - } - } - - return fromTree.PatchContext(ctx, toTree) -} - -// Patch returns the Patch between the actual commit and the provided one. -// -// NOTE: Since version 5.1.0 the renames are correctly handled, the settings -// used are the recommended options DefaultDiffTreeOptions. -func (c *Commit) Patch(to *Commit) (*Patch, error) { - return c.PatchContext(context.Background(), to) -} - -// Parents return a CommitIter to the parent Commits. -func (c *Commit) Parents() CommitIter { - return NewCommitIter(c.s, - storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, c.ParentHashes), - ) -} - -// NumParents returns the number of parents in a commit. -func (c *Commit) NumParents() int { - return len(c.ParentHashes) -} - -var ErrParentNotFound = errors.New("commit parent not found") - -// Parent returns the ith parent of a commit. -func (c *Commit) Parent(i int) (*Commit, error) { - if len(c.ParentHashes) == 0 || i > len(c.ParentHashes)-1 { - return nil, ErrParentNotFound - } - - return GetCommit(c.s, c.ParentHashes[i]) -} - -// File returns the file with the specified "path" in the commit and a -// nil error if the file exists. If the file does not exist, it returns -// a nil file and the ErrFileNotFound error. -func (c *Commit) File(path string) (*File, error) { - tree, err := c.Tree() - if err != nil { - return nil, err - } - - return tree.File(path) -} - -// Files returns a FileIter allowing to iterate over the Tree -func (c *Commit) Files() (*FileIter, error) { - tree, err := c.Tree() - if err != nil { - return nil, err - } - - return tree.Files(), nil -} - -// ID returns the object ID of the commit. The returned value will always match -// the current value of Commit.Hash. -// -// ID is present to fulfill the Object interface. -func (c *Commit) ID() plumbing.Hash { - return c.Hash -} - -// Type returns the type of object. It always returns plumbing.CommitObject. -// -// Type is present to fulfill the Object interface. -func (c *Commit) Type() plumbing.ObjectType { - return plumbing.CommitObject -} - -// Decode transforms a plumbing.EncodedObject into a Commit struct. -func (c *Commit) Decode(o plumbing.EncodedObject) (err error) { - if o.Type() != plumbing.CommitObject { - return ErrUnsupportedObject - } - - c.Hash = o.Hash() - c.Encoding = defaultUtf8CommitMessageEncoding - - reader, err := o.Reader() - if err != nil { - return err - } - defer ioutil.CheckClose(reader, &err) - - r := sync.GetBufioReader(reader) - defer sync.PutBufioReader(r) - - var message bool - var mergetag bool - var pgpsig bool - var msgbuf bytes.Buffer - var extraheader *ExtraHeader = nil - for { - line, err := r.ReadBytes('\n') - if err != nil && err != io.EOF { - return err - } - - if mergetag { - if len(line) > 0 && line[0] == ' ' { - line = bytes.TrimLeft(line, " ") - c.MergeTag += string(line) - continue - } else { - mergetag = false - } - } - - if pgpsig { - if len(line) > 0 && line[0] == ' ' { - line = bytes.TrimLeft(line, " ") - c.PGPSignature += string(line) - continue - } else { - pgpsig = false - } - } - - if extraheader != nil { - if len(line) > 0 && line[0] == ' ' { - extraheader.Value += string(line[1:]) - continue - } else { - extraheader.Value = strings.TrimRight(extraheader.Value, "\n") - c.ExtraHeaders = append(c.ExtraHeaders, *extraheader) - extraheader = nil - } - } - - if !message { - original_line := line - line = bytes.TrimSpace(line) - if len(line) == 0 { - message = true - continue - } - - split := bytes.SplitN(line, []byte{' '}, 2) - - var data []byte - if len(split) == 2 { - data = split[1] - } - - switch string(split[0]) { - case "tree": - c.TreeHash = plumbing.NewHash(string(data)) - case "parent": - c.ParentHashes = append(c.ParentHashes, plumbing.NewHash(string(data))) - case "author": - c.Author.Decode(data) - case "committer": - c.Committer.Decode(data) - case headermergetag: - c.MergeTag += string(data) + "\n" - mergetag = true - case headerencoding: - c.Encoding = MessageEncoding(data) - case headerpgp: - c.PGPSignature += string(data) + "\n" - pgpsig = true - default: - h, maybecontinued := parseExtraHeader(original_line) - if maybecontinued { - extraheader = &h - } else { - c.ExtraHeaders = append(c.ExtraHeaders, h) - } - } - } else { - msgbuf.Write(line) - } - - if err == io.EOF { - break - } - } - c.Message = msgbuf.String() - return nil -} - -// Encode transforms a Commit into a plumbing.EncodedObject. -func (c *Commit) Encode(o plumbing.EncodedObject) error { - return c.encode(o, true) -} - -// EncodeWithoutSignature export a Commit into a plumbing.EncodedObject without the signature (correspond to the payload of the PGP signature). -func (c *Commit) EncodeWithoutSignature(o plumbing.EncodedObject) error { - return c.encode(o, false) -} - -func (c *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) { - o.SetType(plumbing.CommitObject) - w, err := o.Writer() - if err != nil { - return err - } - - defer ioutil.CheckClose(w, &err) - - if _, err = fmt.Fprintf(w, "tree %s\n", c.TreeHash.String()); err != nil { - return err - } - - for _, parent := range c.ParentHashes { - if _, err = fmt.Fprintf(w, "parent %s\n", parent.String()); err != nil { - return err - } - } - - if _, err = fmt.Fprint(w, "author "); err != nil { - return err - } - - if err = c.Author.Encode(w); err != nil { - return err - } - - if _, err = fmt.Fprint(w, "\ncommitter "); err != nil { - return err - } - - if err = c.Committer.Encode(w); err != nil { - return err - } - - if c.MergeTag != "" { - if _, err = fmt.Fprint(w, "\n"+headermergetag+" "); err != nil { - return err - } - - // Split tag information lines and re-write with a left padding and - // newline. Use join for this so it's clear that a newline should not be - // added after this section. The newline will be added either as part of - // the PGP signature or the commit message. - mergetag := strings.TrimSuffix(c.MergeTag, "\n") - lines := strings.Split(mergetag, "\n") - if _, err = fmt.Fprint(w, strings.Join(lines, "\n ")); err != nil { - return err - } - } - - if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMessageEncoding { - if _, err = fmt.Fprintf(w, "\n%s %s", headerencoding, c.Encoding); err != nil { - return err - } - } - - for _, header := range c.ExtraHeaders { - - if _, err = fmt.Fprintf(w, "\n%s", header); err != nil { - return err - } - } - - if c.PGPSignature != "" && includeSig { - if _, err = fmt.Fprint(w, "\n"+headerpgp+" "); err != nil { - return err - } - - // Split all the signature lines and re-write with a left padding and - // newline. Use join for this so it's clear that a newline should not be - // added after this section, as it will be added when the message is - // printed. - signature := strings.TrimSuffix(c.PGPSignature, "\n") - lines := strings.Split(signature, "\n") - if _, err = fmt.Fprint(w, strings.Join(lines, "\n ")); err != nil { - return err - } - } - - if _, err = fmt.Fprintf(w, "\n\n%s", c.Message); err != nil { - return err - } - - return err -} - -// Stats returns the stats of a commit. -func (c *Commit) Stats() (FileStats, error) { - return c.StatsContext(context.Background()) -} - -// StatsContext returns the stats of a commit. Error will be return if context -// expires. Provided context must be non-nil. -func (c *Commit) StatsContext(ctx context.Context) (FileStats, error) { - fromTree, err := c.Tree() - if err != nil { - return nil, err - } - - toTree := &Tree{} - if c.NumParents() != 0 { - firstParent, err := c.Parents().Next() - if err != nil { - return nil, err - } - - toTree, err = firstParent.Tree() - if err != nil { - return nil, err - } - } - - patch, err := toTree.PatchContext(ctx, fromTree) - if err != nil { - return nil, err - } - - return getFileStatsFromFilePatches(patch.FilePatches()), nil -} - -func (c *Commit) String() string { - return fmt.Sprintf( - "%s %s\nAuthor: %s\nDate: %s\n\n%s\n", - plumbing.CommitObject, c.Hash, c.Author.String(), - c.Author.When.Format(DateFormat), indent(c.Message), - ) -} - -// Verify performs PGP verification of the commit with a provided armored -// keyring and returns openpgp.Entity associated with verifying key on success. -func (c *Commit) Verify(armoredKeyRing string) (*openpgp.Entity, error) { - keyRingReader := strings.NewReader(armoredKeyRing) - keyring, err := openpgp.ReadArmoredKeyRing(keyRingReader) - if err != nil { - return nil, err - } - - // Extract signature. - signature := strings.NewReader(c.PGPSignature) - - encoded := &plumbing.MemoryObject{} - // Encode commit components, excluding signature and get a reader object. - if err := c.EncodeWithoutSignature(encoded); err != nil { - return nil, err - } - er, err := encoded.Reader() - if err != nil { - return nil, err - } - - return openpgp.CheckArmoredDetachedSignature(keyring, er, signature, nil) -} - -// Less defines a compare function to determine which commit is 'earlier' by: -// - First use Committer.When -// - If Committer.When are equal then use Author.When -// - If Author.When also equal then compare the string value of the hash -func (c *Commit) Less(rhs *Commit) bool { - return c.Committer.When.Before(rhs.Committer.When) || - (c.Committer.When.Equal(rhs.Committer.When) && - (c.Author.When.Before(rhs.Author.When) || - (c.Author.When.Equal(rhs.Author.When) && c.Hash.Compare(rhs.Hash.Bytes()) < 0))) -} - -func indent(t string) string { - var output []string - for _, line := range strings.Split(t, "\n") { - if len(line) != 0 { - line = " " + line - } - - output = append(output, line) - } - - return strings.Join(output, "\n") -} - -// CommitIter is a generic closable interface for iterating over commits. -type CommitIter interface { - Next() (*Commit, error) - ForEach(func(*Commit) error) error - Close() -} - -// storerCommitIter provides an iterator from commits in an EncodedObjectStorer. -type storerCommitIter struct { - storer.EncodedObjectIter - s storer.EncodedObjectStorer -} - -// NewCommitIter takes a storer.EncodedObjectStorer and a -// storer.EncodedObjectIter and returns a CommitIter that iterates over all -// commits contained in the storer.EncodedObjectIter. -// -// Any non-commit object returned by the storer.EncodedObjectIter is skipped. -func NewCommitIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) CommitIter { - return &storerCommitIter{iter, s} -} - -// Next moves the iterator to the next commit and returns a pointer to it. If -// there are no more commits, it returns io.EOF. -func (iter *storerCommitIter) Next() (*Commit, error) { - obj, err := iter.EncodedObjectIter.Next() - if err != nil { - return nil, err - } - - return DecodeCommit(iter.s, obj) -} - -// ForEach call the cb function for each commit contained on this iter until -// an error appends or the end of the iter is reached. If ErrStop is sent -// the iteration is stopped but no error is returned. The iterator is closed. -func (iter *storerCommitIter) ForEach(cb func(*Commit) error) error { - return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { - c, err := DecodeCommit(iter.s, obj) - if err != nil { - return err - } - - return cb(c) - }) -} - -func (iter *storerCommitIter) Close() { - iter.EncodedObjectIter.Close() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker.go deleted file mode 100644 index 06a7f2ad..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker.go +++ /dev/null @@ -1,349 +0,0 @@ -package object - -import ( - "container/list" - "errors" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" -) - -type commitPreIterator struct { - seenExternal map[plumbing.Hash]bool - seen map[plumbing.Hash]bool - stack []CommitIter - start *Commit -} - - -func forEachCommit(next func() (*Commit, error), cb func(*Commit) error) error { - for { - c, err := next() - if errors.Is(err, io.EOF) { - break - } - if err != nil { - return err - } - - err = cb(c) - if err == storer.ErrStop { - break - } - if err != nil { - return err - } - } - return nil -} - -// NewCommitPreorderIter returns a CommitIter that walks the commit history, -// starting at the given commit and visiting its parents in pre-order. -// The given callback will be called for each visited commit. Each commit will -// be visited only once. If the callback returns an error, walking will stop -// and will return the error. Other errors might be returned if the history -// cannot be traversed (e.g. missing objects). Ignore allows to skip some -// commits from being iterated. -func NewCommitPreorderIter( - c *Commit, - seenExternal map[plumbing.Hash]bool, - ignore []plumbing.Hash, -) CommitIter { - seen := make(map[plumbing.Hash]bool) - for _, h := range ignore { - seen[h] = true - } - - return &commitPreIterator{ - seenExternal: seenExternal, - seen: seen, - stack: make([]CommitIter, 0), - start: c, - } -} - -func (w *commitPreIterator) Next() (*Commit, error) { - var c *Commit - for { - if w.start != nil { - c = w.start - w.start = nil - } else { - current := len(w.stack) - 1 - if current < 0 { - return nil, io.EOF - } - - var err error - c, err = w.stack[current].Next() - if err == io.EOF { - w.stack = w.stack[:current] - continue - } - - if err != nil { - return nil, err - } - } - - if w.seen[c.Hash] || w.seenExternal[c.Hash] { - continue - } - - w.seen[c.Hash] = true - - if c.NumParents() > 0 { - w.stack = append(w.stack, filteredParentIter(c, w.seen)) - } - - return c, nil - } -} - -func filteredParentIter(c *Commit, seen map[plumbing.Hash]bool) CommitIter { - var hashes []plumbing.Hash - for _, h := range c.ParentHashes { - if !seen[h] { - hashes = append(hashes, h) - } - } - - return NewCommitIter(c.s, - storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, hashes), - ) -} - -func (w *commitPreIterator) ForEach(cb func(*Commit) error) error { - return forEachCommit(w.Next, cb) -} - -func (w *commitPreIterator) Close() {} - -type commitPostIterator struct { - stack []*Commit - seen map[plumbing.Hash]bool -} - -// NewCommitPostorderIter returns a CommitIter that walks the commit -// history like WalkCommitHistory but in post-order. This means that after -// walking a merge commit, the merged commit will be walked before the base -// it was merged on. This can be useful if you wish to see the history in -// chronological order. Ignore allows to skip some commits from being iterated. -func NewCommitPostorderIter(c *Commit, ignore []plumbing.Hash) CommitIter { - seen := make(map[plumbing.Hash]bool) - for _, h := range ignore { - seen[h] = true - } - - return &commitPostIterator{ - stack: []*Commit{c}, - seen: seen, - } -} - -func (w *commitPostIterator) Next() (*Commit, error) { - for { - if len(w.stack) == 0 { - return nil, io.EOF - } - - c := w.stack[len(w.stack)-1] - w.stack = w.stack[:len(w.stack)-1] - - if w.seen[c.Hash] { - continue - } - - w.seen[c.Hash] = true - - return c, c.Parents().ForEach(func(p *Commit) error { - w.stack = append(w.stack, p) - return nil - }) - } -} - -func (w *commitPostIterator) ForEach(cb func(*Commit) error) error { - return forEachCommit(w.Next, cb) -} - -func (w *commitPostIterator) Close() {} - -type commitPostIteratorFirstParent struct { - stack []*Commit - seen map[plumbing.Hash]bool -} - -// NewCommitPostorderIterFirstParent returns a CommitIter that walks the commit -// history like WalkCommitHistory but in post-order. -// -// This option acts like the git log --first-parent flag, skipping intermediate -// commits that were brought in via a merge commit. -// Ignore allows to skip some commits from being iterated. -func NewCommitPostorderIterFirstParent(c *Commit, ignore []plumbing.Hash) CommitIter { - seen := make(map[plumbing.Hash]bool) - for _, h := range ignore { - seen[h] = true - } - - return &commitPostIteratorFirstParent{ - stack: []*Commit{c}, - seen: seen, - } -} - -func (w *commitPostIteratorFirstParent) Next() (*Commit, error) { - for { - if len(w.stack) == 0 { - return nil, io.EOF - } - - c := w.stack[len(w.stack)-1] - w.stack = w.stack[:len(w.stack)-1] - - if w.seen[c.Hash] { - continue - } - - w.seen[c.Hash] = true - - return c, c.Parents().ForEach(func(p *Commit) error { - if len(c.ParentHashes) > 0 && p.Hash == c.ParentHashes[0] { - w.stack = append(w.stack, p) - } - return nil - }) - } -} - -func (w *commitPostIteratorFirstParent) ForEach(cb func(*Commit) error) error { - return forEachCommit(w.Next, cb) -} - -func (w *commitPostIteratorFirstParent) Close() {} - -// commitAllIterator stands for commit iterator for all refs. -type commitAllIterator struct { - // currCommit points to the current commit. - currCommit *list.Element -} - -// NewCommitAllIter returns a new commit iterator for all refs. -// repoStorer is a repo Storer used to get commits and references. -// commitIterFunc is a commit iterator function, used to iterate through ref commits in chosen order -func NewCommitAllIter(repoStorer storage.Storer, commitIterFunc func(*Commit) CommitIter) (CommitIter, error) { - commitsPath := list.New() - commitsLookup := make(map[plumbing.Hash]*list.Element) - head, err := storer.ResolveReference(repoStorer, plumbing.HEAD) - if err == nil { - err = addReference(repoStorer, commitIterFunc, head, commitsPath, commitsLookup) - } - - if err != nil && err != plumbing.ErrReferenceNotFound { - return nil, err - } - - // add all references along with the HEAD - refIter, err := repoStorer.IterReferences() - if err != nil { - return nil, err - } - defer refIter.Close() - - for { - ref, err := refIter.Next() - if err == io.EOF { - break - } - - if err == plumbing.ErrReferenceNotFound { - continue - } - - if err != nil { - return nil, err - } - - if err = addReference(repoStorer, commitIterFunc, ref, commitsPath, commitsLookup); err != nil { - return nil, err - } - } - - return &commitAllIterator{commitsPath.Front()}, nil -} - -func addReference( - repoStorer storage.Storer, - commitIterFunc func(*Commit) CommitIter, - ref *plumbing.Reference, - commitsPath *list.List, - commitsLookup map[plumbing.Hash]*list.Element) error { - - _, exists := commitsLookup[ref.Hash()] - if exists { - // we already have it - skip the reference. - return nil - } - - refCommit, _ := GetCommit(repoStorer, ref.Hash()) - if refCommit == nil { - // if it's not a commit - skip it. - return nil - } - - var ( - refCommits []*Commit - parent *list.Element - ) - // collect all ref commits to add - commitIter := commitIterFunc(refCommit) - for c, e := commitIter.Next(); e == nil; { - parent, exists = commitsLookup[c.Hash] - if exists { - break - } - refCommits = append(refCommits, c) - c, e = commitIter.Next() - } - commitIter.Close() - - if parent == nil { - // common parent - not found - // add all commits to the path from this ref (maybe it's a HEAD and we don't have anything, yet) - for _, c := range refCommits { - parent = commitsPath.PushBack(c) - commitsLookup[c.Hash] = parent - } - } else { - // add ref's commits to the path in reverse order (from the latest) - for i := len(refCommits) - 1; i >= 0; i-- { - c := refCommits[i] - // insert before found common parent - parent = commitsPath.InsertBefore(c, parent) - commitsLookup[c.Hash] = parent - } - } - - return nil -} - -func (it *commitAllIterator) Next() (*Commit, error) { - if it.currCommit == nil { - return nil, io.EOF - } - - c := it.currCommit.Value.(*Commit) - it.currCommit = it.currCommit.Next() - - return c, nil -} - -func (it *commitAllIterator) ForEach(cb func(*Commit) error) error { - return forEachCommit(it.Next, cb) -} - -func (it *commitAllIterator) Close() { - it.currCommit = nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs.go deleted file mode 100644 index ffdecf00..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs.go +++ /dev/null @@ -1,100 +0,0 @@ -package object - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -type bfsCommitIterator struct { - seenExternal map[plumbing.Hash]bool - seen map[plumbing.Hash]bool - queue []*Commit -} - -// NewCommitIterBSF returns a CommitIter that walks the commit history, -// starting at the given commit and visiting its parents in pre-order. -// The given callback will be called for each visited commit. Each commit will -// be visited only once. If the callback returns an error, walking will stop -// and will return the error. Other errors might be returned if the history -// cannot be traversed (e.g. missing objects). Ignore allows to skip some -// commits from being iterated. -func NewCommitIterBSF( - c *Commit, - seenExternal map[plumbing.Hash]bool, - ignore []plumbing.Hash, -) CommitIter { - seen := make(map[plumbing.Hash]bool) - for _, h := range ignore { - seen[h] = true - } - - return &bfsCommitIterator{ - seenExternal: seenExternal, - seen: seen, - queue: []*Commit{c}, - } -} - -func (w *bfsCommitIterator) appendHash(store storer.EncodedObjectStorer, h plumbing.Hash) error { - if w.seen[h] || w.seenExternal[h] { - return nil - } - c, err := GetCommit(store, h) - if err != nil { - return err - } - w.queue = append(w.queue, c) - return nil -} - -func (w *bfsCommitIterator) Next() (*Commit, error) { - var c *Commit - for { - if len(w.queue) == 0 { - return nil, io.EOF - } - c = w.queue[0] - w.queue = w.queue[1:] - - if w.seen[c.Hash] || w.seenExternal[c.Hash] { - continue - } - - w.seen[c.Hash] = true - - for _, h := range c.ParentHashes { - err := w.appendHash(c.s, h) - if err != nil { - return nil, err - } - } - - return c, nil - } -} - -func (w *bfsCommitIterator) ForEach(cb func(*Commit) error) error { - for { - c, err := w.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - err = cb(c) - if err == storer.ErrStop { - break - } - if err != nil { - return err - } - } - - return nil -} - -func (w *bfsCommitIterator) Close() {} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs_filtered.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs_filtered.go deleted file mode 100644 index d7ac015a..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_bfs_filtered.go +++ /dev/null @@ -1,175 +0,0 @@ -package object - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -// NewFilterCommitIter returns a CommitIter that walks the commit history, -// starting at the passed commit and visiting its parents in Breadth-first order. -// The commits returned by the CommitIter will validate the passed CommitFilter. -// The history won't be transversed beyond a commit if isLimit is true for it. -// Each commit will be visited only once. -// If the commit history can not be traversed, or the Close() method is called, -// the CommitIter won't return more commits. -// If no isValid is passed, all ancestors of from commit will be valid. -// If no isLimit is limit, all ancestors of all commits will be visited. -func NewFilterCommitIter( - from *Commit, - isValid *CommitFilter, - isLimit *CommitFilter, -) CommitIter { - var validFilter CommitFilter - if isValid == nil { - validFilter = func(_ *Commit) bool { - return true - } - } else { - validFilter = *isValid - } - - var limitFilter CommitFilter - if isLimit == nil { - limitFilter = func(_ *Commit) bool { - return false - } - } else { - limitFilter = *isLimit - } - - return &filterCommitIter{ - isValid: validFilter, - isLimit: limitFilter, - visited: map[plumbing.Hash]struct{}{}, - queue: []*Commit{from}, - } -} - -// CommitFilter returns a boolean for the passed Commit -type CommitFilter func(*Commit) bool - -// filterCommitIter implements CommitIter -type filterCommitIter struct { - isValid CommitFilter - isLimit CommitFilter - visited map[plumbing.Hash]struct{} - queue []*Commit - lastErr error -} - -// Next returns the next commit of the CommitIter. -// It will return io.EOF if there are no more commits to visit, -// or an error if the history could not be traversed. -func (w *filterCommitIter) Next() (*Commit, error) { - var commit *Commit - var err error - for { - commit, err = w.popNewFromQueue() - if err != nil { - return nil, w.close(err) - } - - w.visited[commit.Hash] = struct{}{} - - if !w.isLimit(commit) { - err = w.addToQueue(commit.s, commit.ParentHashes...) - if err != nil { - return nil, w.close(err) - } - } - - if w.isValid(commit) { - return commit, nil - } - } -} - -// ForEach runs the passed callback over each Commit returned by the CommitIter -// until the callback returns an error or there is no more commits to traverse. -func (w *filterCommitIter) ForEach(cb func(*Commit) error) error { - for { - commit, err := w.Next() - if err == io.EOF { - break - } - - if err != nil { - return err - } - - if err := cb(commit); err == storer.ErrStop { - break - } else if err != nil { - return err - } - } - - return nil -} - -// Error returns the error that caused that the CommitIter is no longer returning commits -func (w *filterCommitIter) Error() error { - return w.lastErr -} - -// Close closes the CommitIter -func (w *filterCommitIter) Close() { - w.visited = map[plumbing.Hash]struct{}{} - w.queue = []*Commit{} - w.isLimit = nil - w.isValid = nil -} - -// close closes the CommitIter with an error -func (w *filterCommitIter) close(err error) error { - w.Close() - w.lastErr = err - return err -} - -// popNewFromQueue returns the first new commit from the internal fifo queue, -// or an io.EOF error if the queue is empty -func (w *filterCommitIter) popNewFromQueue() (*Commit, error) { - var first *Commit - for { - if len(w.queue) == 0 { - if w.lastErr != nil { - return nil, w.lastErr - } - - return nil, io.EOF - } - - first = w.queue[0] - w.queue = w.queue[1:] - if _, ok := w.visited[first.Hash]; ok { - continue - } - - return first, nil - } -} - -// addToQueue adds the passed commits to the internal fifo queue if they weren't seen -// or returns an error if the passed hashes could not be used to get valid commits -func (w *filterCommitIter) addToQueue( - store storer.EncodedObjectStorer, - hashes ...plumbing.Hash, -) error { - for _, hash := range hashes { - if _, ok := w.visited[hash]; ok { - continue - } - - commit, err := GetCommit(store, hash) - if err != nil { - return err - } - - w.queue = append(w.queue, commit) - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_ctime.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_ctime.go deleted file mode 100644 index f3254b94..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_ctime.go +++ /dev/null @@ -1,103 +0,0 @@ -package object - -import ( - "io" - - "github.com/emirpasic/gods/trees/binaryheap" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -type commitIteratorByCTime struct { - seenExternal map[plumbing.Hash]bool - seen map[plumbing.Hash]bool - heap *binaryheap.Heap -} - -// NewCommitIterCTime returns a CommitIter that walks the commit history, -// starting at the given commit and visiting its parents while preserving Committer Time order. -// this appears to be the closest order to `git log` -// The given callback will be called for each visited commit. Each commit will -// be visited only once. If the callback returns an error, walking will stop -// and will return the error. Other errors might be returned if the history -// cannot be traversed (e.g. missing objects). Ignore allows to skip some -// commits from being iterated. -func NewCommitIterCTime( - c *Commit, - seenExternal map[plumbing.Hash]bool, - ignore []plumbing.Hash, -) CommitIter { - seen := make(map[plumbing.Hash]bool) - for _, h := range ignore { - seen[h] = true - } - - heap := binaryheap.NewWith(func(a, b interface{}) int { - if a.(*Commit).Committer.When.Before(b.(*Commit).Committer.When) { - return 1 - } - return -1 - }) - heap.Push(c) - - return &commitIteratorByCTime{ - seenExternal: seenExternal, - seen: seen, - heap: heap, - } -} - -func (w *commitIteratorByCTime) Next() (*Commit, error) { - var c *Commit - for { - cIn, ok := w.heap.Pop() - if !ok { - return nil, io.EOF - } - c = cIn.(*Commit) - - if w.seen[c.Hash] || w.seenExternal[c.Hash] { - continue - } - - w.seen[c.Hash] = true - - for _, h := range c.ParentHashes { - if w.seen[h] || w.seenExternal[h] { - continue - } - pc, err := GetCommit(c.s, h) - if err != nil { - return nil, err - } - w.heap.Push(pc) - } - - return c, nil - } -} - -func (w *commitIteratorByCTime) ForEach(cb func(*Commit) error) error { - for { - c, err := w.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - err = cb(c) - if err == storer.ErrStop { - break - } - if err != nil { - return err - } - } - - return nil -} - -func (w *commitIteratorByCTime) Close() {} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_limit.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_limit.go deleted file mode 100644 index cce89f9d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_limit.go +++ /dev/null @@ -1,70 +0,0 @@ -package object - -import ( - "io" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -type commitLimitIter struct { - sourceIter CommitIter - limitOptions LogLimitOptions -} - -type LogLimitOptions struct { - Since *time.Time - Until *time.Time - TailHash plumbing.Hash -} - -func NewCommitLimitIterFromIter(commitIter CommitIter, limitOptions LogLimitOptions) CommitIter { - iterator := new(commitLimitIter) - iterator.sourceIter = commitIter - iterator.limitOptions = limitOptions - return iterator -} - -func (c *commitLimitIter) Next() (*Commit, error) { - for { - commit, err := c.sourceIter.Next() - if err != nil { - return nil, err - } - - if c.limitOptions.Since != nil && commit.Committer.When.Before(*c.limitOptions.Since) { - continue - } - if c.limitOptions.Until != nil && commit.Committer.When.After(*c.limitOptions.Until) { - continue - } - if c.limitOptions.TailHash == commit.Hash { - return commit, storer.ErrStop - } - return commit, nil - } -} - -func (c *commitLimitIter) ForEach(cb func(*Commit) error) error { - for { - commit, nextErr := c.Next() - if nextErr == io.EOF { - break - } - if nextErr != nil && nextErr != storer.ErrStop { - return nextErr - } - err := cb(commit) - if err == storer.ErrStop || nextErr == storer.ErrStop { - return nil - } else if err != nil { - return err - } - } - return nil -} - -func (c *commitLimitIter) Close() { - c.sourceIter.Close() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_path.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_path.go deleted file mode 100644 index f1185312..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/commit_walker_path.go +++ /dev/null @@ -1,167 +0,0 @@ -package object - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -type commitPathIter struct { - pathFilter func(string) bool - sourceIter CommitIter - currentCommit *Commit - checkParent bool -} - -// NewCommitPathIterFromIter returns a commit iterator which performs diffTree between -// successive trees returned from the commit iterator from the argument. The purpose of this is -// to find the commits that explain how the files that match the path came to be. -// If checkParent is true then the function double checks if potential parent (next commit in a path) -// is one of the parents in the tree (it's used by `git log --all`). -// pathFilter is a function that takes path of file as argument and returns true if we want it -func NewCommitPathIterFromIter(pathFilter func(string) bool, commitIter CommitIter, checkParent bool) CommitIter { - iterator := new(commitPathIter) - iterator.sourceIter = commitIter - iterator.pathFilter = pathFilter - iterator.checkParent = checkParent - return iterator -} - -// NewCommitFileIterFromIter is kept for compatibility, can be replaced with NewCommitPathIterFromIter -func NewCommitFileIterFromIter(fileName string, commitIter CommitIter, checkParent bool) CommitIter { - return NewCommitPathIterFromIter( - func(path string) bool { - return path == fileName - }, - commitIter, - checkParent, - ) -} - -func (c *commitPathIter) Next() (*Commit, error) { - if c.currentCommit == nil { - var err error - c.currentCommit, err = c.sourceIter.Next() - if err != nil { - return nil, err - } - } - commit, commitErr := c.getNextFileCommit() - - // Setting current-commit to nil to prevent unwanted states when errors are raised - if commitErr != nil { - c.currentCommit = nil - } - return commit, commitErr -} - -func (c *commitPathIter) getNextFileCommit() (*Commit, error) { - var parentTree, currentTree *Tree - - for { - // Parent-commit can be nil if the current-commit is the initial commit - parentCommit, parentCommitErr := c.sourceIter.Next() - if parentCommitErr != nil { - // If the parent-commit is beyond the initial commit, keep it nil - if parentCommitErr != io.EOF { - return nil, parentCommitErr - } - parentCommit = nil - } - - if parentTree == nil { - var currTreeErr error - currentTree, currTreeErr = c.currentCommit.Tree() - if currTreeErr != nil { - return nil, currTreeErr - } - } else { - currentTree = parentTree - parentTree = nil - } - - if parentCommit != nil { - var parentTreeErr error - parentTree, parentTreeErr = parentCommit.Tree() - if parentTreeErr != nil { - return nil, parentTreeErr - } - } - - // Find diff between current and parent trees - changes, diffErr := DiffTree(currentTree, parentTree) - if diffErr != nil { - return nil, diffErr - } - - found := c.hasFileChange(changes, parentCommit) - - // Storing the current-commit in-case a change is found, and - // Updating the current-commit for the next-iteration - prevCommit := c.currentCommit - c.currentCommit = parentCommit - - if found { - return prevCommit, nil - } - - // If not matches found and if parent-commit is beyond the initial commit, then return with EOF - if parentCommit == nil { - return nil, io.EOF - } - } -} - -func (c *commitPathIter) hasFileChange(changes Changes, parent *Commit) bool { - for _, change := range changes { - if !c.pathFilter(change.name()) { - continue - } - - // filename matches, now check if source iterator contains all commits (from all refs) - if c.checkParent { - // Check if parent is beyond the initial commit - if parent == nil || isParentHash(parent.Hash, c.currentCommit) { - return true - } - continue - } - - return true - } - - return false -} - -func isParentHash(hash plumbing.Hash, commit *Commit) bool { - for _, h := range commit.ParentHashes { - if h == hash { - return true - } - } - return false -} - -func (c *commitPathIter) ForEach(cb func(*Commit) error) error { - for { - commit, nextErr := c.Next() - if nextErr == io.EOF { - break - } - if nextErr != nil { - return nextErr - } - err := cb(commit) - if err == storer.ErrStop { - return nil - } else if err != nil { - return err - } - } - return nil -} - -func (c *commitPathIter) Close() { - c.sourceIter.Close() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/difftree.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/difftree.go deleted file mode 100644 index d9f35f2c..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/difftree.go +++ /dev/null @@ -1,98 +0,0 @@ -package object - -import ( - "bytes" - "context" - - "github.com/go-git/go-git/v6/utils/merkletrie" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// DiffTree compares the content and mode of the blobs found via two -// tree objects. -// DiffTree does not perform rename detection, use DiffTreeWithOptions -// instead to detect renames. -func DiffTree(a, b *Tree) (Changes, error) { - return DiffTreeContext(context.Background(), a, b) -} - -// DiffTreeContext compares the content and mode of the blobs found via two -// tree objects. Provided context must be non-nil. -// An error will be returned if context expires. -func DiffTreeContext(ctx context.Context, a, b *Tree) (Changes, error) { - return DiffTreeWithOptions(ctx, a, b, nil) -} - -// DiffTreeOptions are the configurable options when performing a diff tree. -type DiffTreeOptions struct { - // DetectRenames is whether the diff tree will use rename detection. - DetectRenames bool - // RenameScore is the threshold to of similarity between files to consider - // that a pair of delete and insert are a rename. The number must be - // exactly between 0 and 100. - RenameScore uint - // RenameLimit is the maximum amount of files that can be compared when - // detecting renames. The number of comparisons that have to be performed - // is equal to the number of deleted files * the number of added files. - // That means, that if 100 files were deleted and 50 files were added, 5000 - // file comparisons may be needed. So, if the rename limit is 50, the number - // of both deleted and added needs to be equal or less than 50. - // A value of 0 means no limit. - RenameLimit uint - // OnlyExactRenames performs only detection of exact renames and will not perform - // any detection of renames based on file similarity. - OnlyExactRenames bool -} - -// DefaultDiffTreeOptions are the default and recommended options for the -// diff tree. -var DefaultDiffTreeOptions = &DiffTreeOptions{ - DetectRenames: true, - RenameScore: 60, - RenameLimit: 0, - OnlyExactRenames: false, -} - -// DiffTreeWithOptions compares the content and mode of the blobs found -// via two tree objects with the given options. The provided context -// must be non-nil. -// If no options are passed, no rename detection will be performed. The -// recommended options are DefaultDiffTreeOptions. -// An error will be returned if the context expires. -// This function will be deprecated and removed in v6 so the default -// behaviour of DiffTree is to detect renames. -func DiffTreeWithOptions( - ctx context.Context, - a, b *Tree, - opts *DiffTreeOptions, -) (Changes, error) { - from := NewTreeRootNode(a) - to := NewTreeRootNode(b) - - hashEqual := func(a, b noder.Hasher) bool { - return bytes.Equal(a.Hash(), b.Hash()) - } - - merkletrieChanges, err := merkletrie.DiffTreeContext(ctx, from, to, hashEqual) - if err != nil { - if err == merkletrie.ErrCanceled { - return nil, ErrCanceled - } - return nil, err - } - - changes, err := newChanges(merkletrieChanges) - if err != nil { - return nil, err - } - - if opts == nil { - opts = new(DiffTreeOptions) - } - - if opts.DetectRenames { - return DetectRenames(changes, opts) - } - - return changes, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/file.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/file.go deleted file mode 100644 index 189ac615..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/file.go +++ /dev/null @@ -1,137 +0,0 @@ -package object - -import ( - "bytes" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/binary" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// File represents git file objects. -type File struct { - // Name is the path of the file. It might be relative to a tree, - // depending of the function that generates it. - Name string - // Mode is the file mode. - Mode filemode.FileMode - // Blob with the contents of the file. - Blob -} - -// NewFile returns a File based on the given blob object -func NewFile(name string, m filemode.FileMode, b *Blob) *File { - return &File{Name: name, Mode: m, Blob: *b} -} - -// Contents returns the contents of a file as a string. -func (f *File) Contents() (content string, err error) { - reader, err := f.Reader() - if err != nil { - return "", err - } - defer ioutil.CheckClose(reader, &err) - - buf := new(bytes.Buffer) - if _, err := buf.ReadFrom(reader); err != nil { - return "", err - } - - return buf.String(), nil -} - -// IsBinary returns if the file is binary or not -func (f *File) IsBinary() (bin bool, err error) { - reader, err := f.Reader() - if err != nil { - return false, err - } - defer ioutil.CheckClose(reader, &err) - - return binary.IsBinary(reader) -} - -// Lines returns a slice of lines from the contents of a file, stripping -// all end of line characters. If the last line is empty (does not end -// in an end of line), it is also stripped. -func (f *File) Lines() ([]string, error) { - content, err := f.Contents() - if err != nil { - return nil, err - } - - splits := strings.Split(content, "\n") - // remove the last line if it is empty - if splits[len(splits)-1] == "" { - return splits[:len(splits)-1], nil - } - - return splits, nil -} - -// FileIter provides an iterator for the files in a tree. -type FileIter struct { - s storer.EncodedObjectStorer - w TreeWalker -} - -// NewFileIter takes a storer.EncodedObjectStorer and a Tree and returns a -// *FileIter that iterates over all files contained in the tree, recursively. -func NewFileIter(s storer.EncodedObjectStorer, t *Tree) *FileIter { - return &FileIter{s: s, w: *NewTreeWalker(t, true, nil)} -} - -// Next moves the iterator to the next file and returns a pointer to it. If -// there are no more files, it returns io.EOF. -func (iter *FileIter) Next() (*File, error) { - for { - name, entry, err := iter.w.Next() - if err != nil { - return nil, err - } - - if entry.Mode == filemode.Dir || entry.Mode == filemode.Submodule { - continue - } - - blob, err := GetBlob(iter.s, entry.Hash) - if err != nil { - return nil, err - } - - return NewFile(name, entry.Mode, blob), nil - } -} - -// ForEach call the cb function for each file contained in this iter until -// an error happens or the end of the iter is reached. If plumbing.ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *FileIter) ForEach(cb func(*File) error) error { - defer iter.Close() - - for { - f, err := iter.Next() - if err != nil { - if err == io.EOF { - return nil - } - - return err - } - - if err := cb(f); err != nil { - if err == storer.ErrStop { - return nil - } - - return err - } - } -} - -func (iter *FileIter) Close() { - iter.w.Close() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/merge_base.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/merge_base.go deleted file mode 100644 index dc31a140..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/merge_base.go +++ /dev/null @@ -1,210 +0,0 @@ -package object - -import ( - "fmt" - "sort" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -// errIsReachable is thrown when first commit is an ancestor of the second -var errIsReachable = fmt.Errorf("first is reachable from second") - -// MergeBase mimics the behavior of `git merge-base actual other`, returning the -// best common ancestor between the actual and the passed one. -// The best common ancestors can not be reached from other common ancestors. -func (c *Commit) MergeBase(other *Commit) ([]*Commit, error) { - // use sortedByCommitDateDesc strategy - sorted := sortByCommitDateDesc(c, other) - newer := sorted[0] - older := sorted[1] - - newerHistory, err := ancestorsIndex(older, newer) - if err == errIsReachable { - return []*Commit{older}, nil - } - - if err != nil { - return nil, err - } - - var res []*Commit - inNewerHistory := isInIndexCommitFilter(newerHistory) - resIter := NewFilterCommitIter(older, &inNewerHistory, &inNewerHistory) - _ = resIter.ForEach(func(commit *Commit) error { - res = append(res, commit) - return nil - }) - - return Independents(res) -} - -// IsAncestor returns true if the actual commit is ancestor of the passed one. -// It returns an error if the history is not transversable -// It mimics the behavior of `git merge --is-ancestor actual other` -func (c *Commit) IsAncestor(other *Commit) (bool, error) { - found := false - iter := NewCommitPreorderIter(other, nil, nil) - err := iter.ForEach(func(comm *Commit) error { - if comm.Hash != c.Hash { - return nil - } - - found = true - return storer.ErrStop - }) - - return found, err -} - -// ancestorsIndex returns a map with the ancestors of the starting commit if the -// excluded one is not one of them. It returns errIsReachable if the excluded commit -// is ancestor of the starting, or another error if the history is not traversable. -func ancestorsIndex(excluded, starting *Commit) (map[plumbing.Hash]struct{}, error) { - if excluded.Hash.String() == starting.Hash.String() { - return nil, errIsReachable - } - - startingHistory := map[plumbing.Hash]struct{}{} - startingIter := NewCommitIterBSF(starting, nil, nil) - err := startingIter.ForEach(func(commit *Commit) error { - if commit.Hash == excluded.Hash { - return errIsReachable - } - - startingHistory[commit.Hash] = struct{}{} - return nil - }) - - if err != nil { - return nil, err - } - - return startingHistory, nil -} - -// Independents returns a subset of the passed commits, that are not reachable the others -// It mimics the behavior of `git merge-base --independent commit...`. -func Independents(commits []*Commit) ([]*Commit, error) { - // use sortedByCommitDateDesc strategy - candidates := sortByCommitDateDesc(commits...) - candidates = removeDuplicated(candidates) - - seen := map[plumbing.Hash]struct{}{} - var isLimit CommitFilter = func(commit *Commit) bool { - _, ok := seen[commit.Hash] - return ok - } - - if len(candidates) < 2 { - return candidates, nil - } - - pos := 0 - for { - from := candidates[pos] - others := remove(candidates, from) - fromHistoryIter := NewFilterCommitIter(from, nil, &isLimit) - err := fromHistoryIter.ForEach(func(fromAncestor *Commit) error { - for _, other := range others { - if fromAncestor.Hash == other.Hash { - candidates = remove(candidates, other) - others = remove(others, other) - } - } - - if len(candidates) == 1 { - return storer.ErrStop - } - - seen[fromAncestor.Hash] = struct{}{} - return nil - }) - - if err != nil { - return nil, err - } - - nextPos := indexOf(candidates, from) + 1 - if nextPos >= len(candidates) { - break - } - - pos = nextPos - } - - return candidates, nil -} - -// sortByCommitDateDesc returns the passed commits, sorted by `committer.When desc` -// -// Following this strategy, it is tried to reduce the time needed when walking -// the history from one commit to reach the others. It is assumed that ancestors -// use to be committed before its descendant; -// That way `Independents(A^, A)` will be processed as being `Independents(A, A^)`; -// so starting by `A` it will be reached `A^` way sooner than walking from `A^` -// to the initial commit, and then from `A` to `A^`. -func sortByCommitDateDesc(commits ...*Commit) []*Commit { - sorted := make([]*Commit, len(commits)) - copy(sorted, commits) - sort.Slice(sorted, func(i, j int) bool { - return sorted[i].Committer.When.After(sorted[j].Committer.When) - }) - - return sorted -} - -// indexOf returns the first position where target was found in the passed commits -func indexOf(commits []*Commit, target *Commit) int { - for i, commit := range commits { - if target.Hash == commit.Hash { - return i - } - } - - return -1 -} - -// remove returns the passed commits excluding the commit toDelete -func remove(commits []*Commit, toDelete *Commit) []*Commit { - res := make([]*Commit, len(commits)) - j := 0 - for _, commit := range commits { - if commit.Hash == toDelete.Hash { - continue - } - - res[j] = commit - j++ - } - - return res[:j] -} - -// removeDuplicated removes duplicated commits from the passed slice of commits -func removeDuplicated(commits []*Commit) []*Commit { - seen := make(map[plumbing.Hash]struct{}, len(commits)) - res := make([]*Commit, len(commits)) - j := 0 - for _, commit := range commits { - if _, ok := seen[commit.Hash]; ok { - continue - } - - seen[commit.Hash] = struct{}{} - res[j] = commit - j++ - } - - return res[:j] -} - -// isInIndexCommitFilter returns a commitFilter that returns true -// if the commit is in the passed index. -func isInIndexCommitFilter(index map[plumbing.Hash]struct{}) CommitFilter { - return func(c *Commit) bool { - _, ok := index[c.Hash] - return ok - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/object.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/object.go deleted file mode 100644 index 0a4d5db8..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/object.go +++ /dev/null @@ -1,239 +0,0 @@ -// Package object contains implementations of all Git objects and utility -// functions to work with them. -package object - -import ( - "bytes" - "errors" - "fmt" - "io" - "strconv" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -// ErrUnsupportedObject trigger when a non-supported object is being decoded. -var ErrUnsupportedObject = errors.New("unsupported object type") - -// Object is a generic representation of any git object. It is implemented by -// Commit, Tree, Blob, and Tag, and includes the functions that are common to -// them. -// -// Object is returned when an object can be of any type. It is frequently used -// with a type cast to acquire the specific type of object: -// -// func process(obj Object) { -// switch o := obj.(type) { -// case *Commit: -// // o is a Commit -// case *Tree: -// // o is a Tree -// case *Blob: -// // o is a Blob -// case *Tag: -// // o is a Tag -// } -// } -// -// This interface is intentionally different from plumbing.EncodedObject, which -// is a lower level interface used by storage implementations to read and write -// objects in its encoded form. -type Object interface { - ID() plumbing.Hash - Type() plumbing.ObjectType - Decode(plumbing.EncodedObject) error - Encode(plumbing.EncodedObject) error -} - -// GetObject gets an object from an object storer and decodes it. -func GetObject(s storer.EncodedObjectStorer, h plumbing.Hash) (Object, error) { - o, err := s.EncodedObject(plumbing.AnyObject, h) - if err != nil { - return nil, err - } - - return DecodeObject(s, o) -} - -// DecodeObject decodes an encoded object into an Object and associates it to -// the given object storer. -func DecodeObject(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (Object, error) { - switch o.Type() { - case plumbing.CommitObject: - return DecodeCommit(s, o) - case plumbing.TreeObject: - return DecodeTree(s, o) - case plumbing.BlobObject: - return DecodeBlob(o) - case plumbing.TagObject: - return DecodeTag(s, o) - default: - return nil, plumbing.ErrInvalidType - } -} - -// DateFormat is the format being used in the original git implementation -const DateFormat = "Mon Jan 02 15:04:05 2006 -0700" - -// Signature is used to identify who and when created a commit or tag. -type Signature struct { - // Name represents a person name. It is an arbitrary string. - Name string - // Email is an email, but it cannot be assumed to be well-formed. - Email string - // When is the timestamp of the signature. - When time.Time -} - -// Decode decodes a byte slice into a signature -func (s *Signature) Decode(b []byte) { - open := bytes.LastIndexByte(b, '<') - close := bytes.LastIndexByte(b, '>') - if open == -1 || close == -1 { - return - } - - if close < open { - return - } - - s.Name = string(bytes.Trim(b[:open], " ")) - s.Email = string(b[open+1 : close]) - - hasTime := close+2 < len(b) - if hasTime { - s.decodeTimeAndTimeZone(b[close+2:]) - } -} - -// Encode encodes a Signature into a writer. -func (s *Signature) Encode(w io.Writer) error { - if _, err := fmt.Fprintf(w, "%s <%s> ", s.Name, s.Email); err != nil { - return err - } - if err := s.encodeTimeAndTimeZone(w); err != nil { - return err - } - return nil -} - -var timeZoneLength = 5 - -func (s *Signature) decodeTimeAndTimeZone(b []byte) { - space := bytes.IndexByte(b, ' ') - if space == -1 { - space = len(b) - } - - ts, err := strconv.ParseInt(string(b[:space]), 10, 64) - if err != nil { - return - } - - s.When = time.Unix(ts, 0).In(time.UTC) - var tzStart = space + 1 - if tzStart >= len(b) || tzStart+timeZoneLength > len(b) { - return - } - - timezone := string(b[tzStart : tzStart+timeZoneLength]) - tzhours, err1 := strconv.ParseInt(timezone[0:3], 10, 64) - tzmins, err2 := strconv.ParseInt(timezone[3:], 10, 64) - if err1 != nil || err2 != nil { - return - } - if tzhours < 0 { - tzmins *= -1 - } - - tz := time.FixedZone("", int(tzhours*60*60+tzmins*60)) - - s.When = s.When.In(tz) -} - -func (s *Signature) encodeTimeAndTimeZone(w io.Writer) error { - u := s.When.Unix() - if u < 0 { - u = 0 - } - _, err := fmt.Fprintf(w, "%d %s", u, s.When.Format("-0700")) - return err -} - -func (s *Signature) String() string { - return fmt.Sprintf("%s <%s>", s.Name, s.Email) -} - -// ObjectIter provides an iterator for a set of objects. -type ObjectIter struct { - storer.EncodedObjectIter - s storer.EncodedObjectStorer -} - -// NewObjectIter takes a storer.EncodedObjectStorer and a -// storer.EncodedObjectIter and returns an *ObjectIter that iterates over all -// objects contained in the storer.EncodedObjectIter. -func NewObjectIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *ObjectIter { - return &ObjectIter{iter, s} -} - -// Next moves the iterator to the next object and returns a pointer to it. If -// there are no more objects, it returns io.EOF. -func (iter *ObjectIter) Next() (Object, error) { - for { - obj, err := iter.EncodedObjectIter.Next() - if err != nil { - return nil, err - } - - o, err := iter.toObject(obj) - if err == plumbing.ErrInvalidType { - continue - } - - if err != nil { - return nil, err - } - - return o, nil - } -} - -// ForEach call the cb function for each object contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *ObjectIter) ForEach(cb func(Object) error) error { - return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { - o, err := iter.toObject(obj) - if err == plumbing.ErrInvalidType { - return nil - } - - if err != nil { - return err - } - - return cb(o) - }) -} - -func (iter *ObjectIter) toObject(obj plumbing.EncodedObject) (Object, error) { - switch obj.Type() { - case plumbing.BlobObject: - blob := &Blob{} - return blob, blob.Decode(obj) - case plumbing.TreeObject: - tree := &Tree{s: iter.s} - return tree, tree.Decode(obj) - case plumbing.CommitObject: - commit := &Commit{} - return commit, commit.Decode(obj) - case plumbing.TagObject: - tag := &Tag{} - return tag, tag.Decode(obj) - default: - return nil, plumbing.ErrInvalidType - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/patch.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/patch.go deleted file mode 100644 index 75e1b40b..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/patch.go +++ /dev/null @@ -1,337 +0,0 @@ -package object - -import ( - "bytes" - "context" - "errors" - "fmt" - "io" - "strconv" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - fdiff "github.com/go-git/go-git/v6/plumbing/format/diff" - "github.com/go-git/go-git/v6/utils/diff" - - dmp "github.com/sergi/go-diff/diffmatchpatch" -) - -var ( - ErrCanceled = errors.New("operation canceled") -) - -func getPatch(message string, changes ...*Change) (*Patch, error) { - ctx := context.Background() - return getPatchContext(ctx, message, changes...) -} - -func getPatchContext(ctx context.Context, message string, changes ...*Change) (*Patch, error) { - var filePatches []fdiff.FilePatch - for _, c := range changes { - select { - case <-ctx.Done(): - return nil, ErrCanceled - default: - } - - fp, err := filePatchWithContext(ctx, c) - if err != nil { - return nil, err - } - - filePatches = append(filePatches, fp) - } - - return &Patch{message, filePatches}, nil -} - -func filePatchWithContext(ctx context.Context, c *Change) (fdiff.FilePatch, error) { - from, to, err := c.Files() - if err != nil { - return nil, err - } - fromContent, fIsBinary, err := fileContent(from) - if err != nil { - return nil, err - } - - toContent, tIsBinary, err := fileContent(to) - if err != nil { - return nil, err - } - - if fIsBinary || tIsBinary { - return &textFilePatch{from: c.From, to: c.To}, nil - } - - diffs := diff.Do(fromContent, toContent) - - var chunks []fdiff.Chunk - for _, d := range diffs { - select { - case <-ctx.Done(): - return nil, ErrCanceled - default: - } - - var op fdiff.Operation - switch d.Type { - case dmp.DiffEqual: - op = fdiff.Equal - case dmp.DiffDelete: - op = fdiff.Delete - case dmp.DiffInsert: - op = fdiff.Add - } - - chunks = append(chunks, &textChunk{d.Text, op}) - } - - return &textFilePatch{ - chunks: chunks, - from: c.From, - to: c.To, - }, nil - -} - -func fileContent(f *File) (content string, isBinary bool, err error) { - if f == nil { - return - } - - isBinary, err = f.IsBinary() - if err != nil || isBinary { - return - } - - content, err = f.Contents() - - return -} - -// Patch is an implementation of fdiff.Patch interface -type Patch struct { - message string - filePatches []fdiff.FilePatch -} - -func (p *Patch) FilePatches() []fdiff.FilePatch { - return p.filePatches -} - -func (p *Patch) Message() string { - return p.message -} - -func (p *Patch) Encode(w io.Writer) error { - ue := fdiff.NewUnifiedEncoder(w, fdiff.DefaultContextLines) - - return ue.Encode(p) -} - -func (p *Patch) Stats() FileStats { - return getFileStatsFromFilePatches(p.FilePatches()) -} - -func (p *Patch) String() string { - buf := bytes.NewBuffer(nil) - err := p.Encode(buf) - if err != nil { - return fmt.Sprintf("malformed patch: %s", err.Error()) - } - - return buf.String() -} - -// changeEntryWrapper is an implementation of fdiff.File interface -type changeEntryWrapper struct { - ce ChangeEntry -} - -func (f *changeEntryWrapper) Hash() plumbing.Hash { - if !f.ce.TreeEntry.Mode.IsFile() { - return plumbing.ZeroHash - } - - return f.ce.TreeEntry.Hash -} - -func (f *changeEntryWrapper) Mode() filemode.FileMode { - return f.ce.TreeEntry.Mode -} -func (f *changeEntryWrapper) Path() string { - if !f.ce.TreeEntry.Mode.IsFile() { - return "" - } - - return f.ce.Name -} - -func (f *changeEntryWrapper) Empty() bool { - return !f.ce.TreeEntry.Mode.IsFile() -} - -// textFilePatch is an implementation of fdiff.FilePatch interface -type textFilePatch struct { - chunks []fdiff.Chunk - from, to ChangeEntry -} - -func (tf *textFilePatch) Files() (from fdiff.File, to fdiff.File) { - f := &changeEntryWrapper{tf.from} - t := &changeEntryWrapper{tf.to} - - if !f.Empty() { - from = f - } - - if !t.Empty() { - to = t - } - - return -} - -func (tf *textFilePatch) IsBinary() bool { - return len(tf.chunks) == 0 -} - -func (tf *textFilePatch) Chunks() []fdiff.Chunk { - return tf.chunks -} - -// textChunk is an implementation of fdiff.Chunk interface -type textChunk struct { - content string - op fdiff.Operation -} - -func (t *textChunk) Content() string { - return t.content -} - -func (t *textChunk) Type() fdiff.Operation { - return t.op -} - -// FileStat stores the status of changes in content of a file. -type FileStat struct { - Name string - Addition int - Deletion int -} - -func (fs FileStat) String() string { - return printStat([]FileStat{fs}) -} - -// FileStats is a collection of FileStat. -type FileStats []FileStat - -func (fileStats FileStats) String() string { - return printStat(fileStats) -} - -// printStat prints the stats of changes in content of files. -// Original implementation: https://github.com/git/git/blob/1a87c842ece327d03d08096395969aca5e0a6996/diff.c#L2615 -// Parts of the output: -// |<+++/---> -// example: " main.go | 10 +++++++--- " -func printStat(fileStats []FileStat) string { - maxGraphWidth := uint(53) - maxNameLen := 0 - maxChangeLen := 0 - - scaleLinear := func(it, width, max uint) uint { - if it == 0 || max == 0 { - return 0 - } - - return 1 + (it * (width - 1) / max) - } - - for _, fs := range fileStats { - if len(fs.Name) > maxNameLen { - maxNameLen = len(fs.Name) - } - - changes := strconv.Itoa(fs.Addition + fs.Deletion) - if len(changes) > maxChangeLen { - maxChangeLen = len(changes) - } - } - - result := "" - for _, fs := range fileStats { - add := uint(fs.Addition) - del := uint(fs.Deletion) - np := maxNameLen - len(fs.Name) - cp := maxChangeLen - len(strconv.Itoa(fs.Addition+fs.Deletion)) - - total := add + del - if total > maxGraphWidth { - add = scaleLinear(add, maxGraphWidth, total) - del = scaleLinear(del, maxGraphWidth, total) - } - - adds := strings.Repeat("+", int(add)) - dels := strings.Repeat("-", int(del)) - namePad := strings.Repeat(" ", np) - changePad := strings.Repeat(" ", cp) - - result += fmt.Sprintf(" %s%s | %s%d %s%s\n", fs.Name, namePad, changePad, total, adds, dels) - } - return result -} - -func getFileStatsFromFilePatches(filePatches []fdiff.FilePatch) FileStats { - var fileStats FileStats - - for _, fp := range filePatches { - // ignore empty patches (binary files, submodule refs updates) - if len(fp.Chunks()) == 0 { - continue - } - - cs := FileStat{} - from, to := fp.Files() - if from == nil { - // New File is created. - cs.Name = to.Path() - } else if to == nil { - // File is deleted. - cs.Name = from.Path() - } else if from.Path() != to.Path() { - // File is renamed. - cs.Name = fmt.Sprintf("%s => %s", from.Path(), to.Path()) - } else { - cs.Name = from.Path() - } - - for _, chunk := range fp.Chunks() { - s := chunk.Content() - if len(s) == 0 { - continue - } - - switch chunk.Type() { - case fdiff.Add: - cs.Addition += strings.Count(s, "\n") - if s[len(s)-1] != '\n' { - cs.Addition++ - } - case fdiff.Delete: - cs.Deletion += strings.Count(s, "\n") - if s[len(s)-1] != '\n' { - cs.Deletion++ - } - } - } - - fileStats = append(fileStats, cs) - } - - return fileStats -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/rename.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/rename.go deleted file mode 100644 index 24607a94..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/rename.go +++ /dev/null @@ -1,816 +0,0 @@ -package object - -import ( - "errors" - "io" - "sort" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/merkletrie" -) - -// DetectRenames detects the renames in the given changes on two trees with -// the given options. It will return the given changes grouping additions and -// deletions into modifications when possible. -// If options is nil, the default diff tree options will be used. -func DetectRenames( - changes Changes, - opts *DiffTreeOptions, -) (Changes, error) { - if opts == nil { - opts = DefaultDiffTreeOptions - } - - detector := &renameDetector{ - renameScore: int(opts.RenameScore), - renameLimit: int(opts.RenameLimit), - onlyExact: opts.OnlyExactRenames, - } - - for _, c := range changes { - action, err := c.Action() - if err != nil { - return nil, err - } - - switch action { - case merkletrie.Insert: - detector.added = append(detector.added, c) - case merkletrie.Delete: - detector.deleted = append(detector.deleted, c) - default: - detector.modified = append(detector.modified, c) - } - } - - return detector.detect() -} - -// renameDetector will detect and resolve renames in a set of changes. -// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java -type renameDetector struct { - added []*Change - deleted []*Change - modified []*Change - - renameScore int - renameLimit int - onlyExact bool -} - -// detectExactRenames detects matches files that were deleted with files that -// were added where the hash is the same on both. If there are multiple targets -// the one with the most similar path will be chosen as the rename and the -// rest as either deletions or additions. -func (d *renameDetector) detectExactRenames() { - added := groupChangesByHash(d.added) - deletes := groupChangesByHash(d.deleted) - var uniqueAdds []*Change - var nonUniqueAdds [][]*Change - var addedLeft []*Change - - for _, cs := range added { - if len(cs) == 1 { - uniqueAdds = append(uniqueAdds, cs[0]) - } else { - nonUniqueAdds = append(nonUniqueAdds, cs) - } - } - - for _, c := range uniqueAdds { - hash := changeHash(c) - deleted := deletes[hash] - - if len(deleted) == 1 { - if sameMode(c, deleted[0]) { - d.modified = append(d.modified, &Change{From: deleted[0].From, To: c.To}) - delete(deletes, hash) - } else { - addedLeft = append(addedLeft, c) - } - } else if len(deleted) > 1 { - bestMatch := bestNameMatch(c, deleted) - if bestMatch != nil && sameMode(c, bestMatch) { - d.modified = append(d.modified, &Change{From: bestMatch.From, To: c.To}) - delete(deletes, hash) - - var newDeletes = make([]*Change, 0, len(deleted)-1) - for _, d := range deleted { - if d != bestMatch { - newDeletes = append(newDeletes, d) - } - } - deletes[hash] = newDeletes - } - } else { - addedLeft = append(addedLeft, c) - } - } - - for _, added := range nonUniqueAdds { - hash := changeHash(added[0]) - deleted := deletes[hash] - - if len(deleted) == 1 { - deleted := deleted[0] - bestMatch := bestNameMatch(deleted, added) - if bestMatch != nil && sameMode(deleted, bestMatch) { - d.modified = append(d.modified, &Change{From: deleted.From, To: bestMatch.To}) - delete(deletes, hash) - - for _, c := range added { - if c != bestMatch { - addedLeft = append(addedLeft, c) - } - } - } else { - addedLeft = append(addedLeft, added...) - } - } else if len(deleted) > 1 { - maxSize := len(deleted) * len(added) - if d.renameLimit > 0 && d.renameLimit < maxSize { - maxSize = d.renameLimit - } - - matrix := make(similarityMatrix, 0, maxSize) - - for delIdx, del := range deleted { - deletedName := changeName(del) - - for addIdx, add := range added { - addedName := changeName(add) - - score := nameSimilarityScore(addedName, deletedName) - matrix = append(matrix, similarityPair{added: addIdx, deleted: delIdx, score: score}) - - if len(matrix) >= maxSize { - break - } - } - - if len(matrix) >= maxSize { - break - } - } - - sort.Stable(matrix) - - usedAdds := make(map[*Change]struct{}) - usedDeletes := make(map[*Change]struct{}) - for i := len(matrix) - 1; i >= 0; i-- { - del := deleted[matrix[i].deleted] - add := added[matrix[i].added] - - if add == nil || del == nil { - // it was already matched - continue - } - - usedAdds[add] = struct{}{} - usedDeletes[del] = struct{}{} - d.modified = append(d.modified, &Change{From: del.From, To: add.To}) - added[matrix[i].added] = nil - deleted[matrix[i].deleted] = nil - } - - for _, c := range added { - if _, ok := usedAdds[c]; !ok && c != nil { - addedLeft = append(addedLeft, c) - } - } - - var newDeletes = make([]*Change, 0, len(deleted)-len(usedDeletes)) - for _, c := range deleted { - if _, ok := usedDeletes[c]; !ok && c != nil { - newDeletes = append(newDeletes, c) - } - } - deletes[hash] = newDeletes - } else { - addedLeft = append(addedLeft, added...) - } - } - - d.added = addedLeft - d.deleted = nil - for _, dels := range deletes { - d.deleted = append(d.deleted, dels...) - } -} - -// detectContentRenames detects renames based on the similarity of the content -// in the files by building a matrix of pairs between sources and destinations -// and matching by the highest score. -// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java -func (d *renameDetector) detectContentRenames() error { - cnt := max(len(d.added), len(d.deleted)) - if d.renameLimit > 0 && cnt > d.renameLimit { - return nil - } - - srcs, dsts := d.deleted, d.added - matrix, err := buildSimilarityMatrix(srcs, dsts, d.renameScore) - if err != nil { - return err - } - renames := make([]*Change, 0, min(len(matrix), len(dsts))) - - // Match rename pairs on a first come, first serve basis until - // we have looked at everything that is above the minimum score. - for i := len(matrix) - 1; i >= 0; i-- { - pair := matrix[i] - src := srcs[pair.deleted] - dst := dsts[pair.added] - - if dst == nil || src == nil { - // It was already matched before - continue - } - - renames = append(renames, &Change{From: src.From, To: dst.To}) - - // Claim destination and source as matched - dsts[pair.added] = nil - srcs[pair.deleted] = nil - } - - d.modified = append(d.modified, renames...) - d.added = compactChanges(dsts) - d.deleted = compactChanges(srcs) - - return nil -} - -func (d *renameDetector) detect() (Changes, error) { - if len(d.added) > 0 && len(d.deleted) > 0 { - d.detectExactRenames() - - if !d.onlyExact { - if err := d.detectContentRenames(); err != nil { - return nil, err - } - } - } - - result := make(Changes, 0, len(d.added)+len(d.deleted)+len(d.modified)) - result = append(result, d.added...) - result = append(result, d.deleted...) - result = append(result, d.modified...) - - sort.Stable(result) - - return result, nil -} - -func bestNameMatch(change *Change, changes []*Change) *Change { - var best *Change - var bestScore int - - cname := changeName(change) - - for _, c := range changes { - score := nameSimilarityScore(cname, changeName(c)) - if score > bestScore { - bestScore = score - best = c - } - } - - return best -} - -func nameSimilarityScore(a, b string) int { - aDirLen := strings.LastIndexByte(a, '/') + 1 - bDirLen := strings.LastIndexByte(b, '/') + 1 - - dirMin := min(aDirLen, bDirLen) - dirMax := max(aDirLen, bDirLen) - - var dirScoreLtr, dirScoreRtl int - if dirMax == 0 { - dirScoreLtr = 100 - dirScoreRtl = 100 - } else { - var dirSim int - - for ; dirSim < dirMin; dirSim++ { - if a[dirSim] != b[dirSim] { - break - } - } - - dirScoreLtr = dirSim * 100 / dirMax - - if dirScoreLtr == 100 { - dirScoreRtl = 100 - } else { - for dirSim = 0; dirSim < dirMin; dirSim++ { - if a[aDirLen-1-dirSim] != b[bDirLen-1-dirSim] { - break - } - } - dirScoreRtl = dirSim * 100 / dirMax - } - } - - fileMin := min(len(a)-aDirLen, len(b)-bDirLen) - fileMax := max(len(a)-aDirLen, len(b)-bDirLen) - - fileSim := 0 - for ; fileSim < fileMin; fileSim++ { - if a[len(a)-1-fileSim] != b[len(b)-1-fileSim] { - break - } - } - fileScore := fileSim * 100 / fileMax - - return (((dirScoreLtr + dirScoreRtl) * 25) + (fileScore * 50)) / 100 -} - -func changeName(c *Change) string { - if c.To != empty { - return c.To.Name - } - return c.From.Name -} - -func changeHash(c *Change) plumbing.Hash { - if c.To != empty { - return c.To.TreeEntry.Hash - } - - return c.From.TreeEntry.Hash -} - -func changeMode(c *Change) filemode.FileMode { - if c.To != empty { - return c.To.TreeEntry.Mode - } - - return c.From.TreeEntry.Mode -} - -func sameMode(a, b *Change) bool { - return changeMode(a) == changeMode(b) -} - -func groupChangesByHash(changes []*Change) map[plumbing.Hash][]*Change { - var result = make(map[plumbing.Hash][]*Change) - for _, c := range changes { - hash := changeHash(c) - result[hash] = append(result[hash], c) - } - return result -} - -type similarityMatrix []similarityPair - -func (m similarityMatrix) Len() int { return len(m) } -func (m similarityMatrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m similarityMatrix) Less(i, j int) bool { - if m[i].score == m[j].score { - if m[i].added == m[j].added { - return m[i].deleted < m[j].deleted - } - return m[i].added < m[j].added - } - return m[i].score < m[j].score -} - -type similarityPair struct { - // index of the added file - added int - // index of the deleted file - deleted int - // similarity score - score int -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -const maxMatrixSize = 10000 - -func buildSimilarityMatrix(srcs, dsts []*Change, renameScore int) (similarityMatrix, error) { - // Allocate for the worst-case scenario where every pair has a score - // that we need to consider. We might not need that many. - matrixSize := len(srcs) * len(dsts) - if matrixSize > maxMatrixSize { - matrixSize = maxMatrixSize - } - matrix := make(similarityMatrix, 0, matrixSize) - srcSizes := make([]int64, len(srcs)) - dstSizes := make([]int64, len(dsts)) - dstTooLarge := make(map[int]bool) - - // Consider each pair of files, if the score is above the minimum - // threshold we need to record that scoring in the matrix so we can - // later find the best matches. -outerLoop: - for srcIdx, src := range srcs { - if changeMode(src) != filemode.Regular { - continue - } - - // Declare the from file and the similarity index here to be able to - // reuse it inside the inner loop. The reason to not initialize them - // here is so we can skip the initialization in case they happen to - // not be needed later. They will be initialized inside the inner - // loop if and only if they're needed and reused in subsequent passes. - var from *File - var s *similarityIndex - var err error - for dstIdx, dst := range dsts { - if changeMode(dst) != filemode.Regular { - continue - } - - if dstTooLarge[dstIdx] { - continue - } - - var to *File - srcSize := srcSizes[srcIdx] - if srcSize == 0 { - from, _, err = src.Files() - if err != nil { - return nil, err - } - srcSize = from.Size + 1 - srcSizes[srcIdx] = srcSize - } - - dstSize := dstSizes[dstIdx] - if dstSize == 0 { - _, to, err = dst.Files() - if err != nil { - return nil, err - } - dstSize = to.Size + 1 - dstSizes[dstIdx] = dstSize - } - - min, max := srcSize, dstSize - if dstSize < srcSize { - min = dstSize - max = srcSize - } - - if int(min*100/max) < renameScore { - // File sizes are too different to be a match - continue - } - - if s == nil { - s, err = fileSimilarityIndex(from) - if err != nil { - if err == errIndexFull { - continue outerLoop - } - return nil, err - } - } - - if to == nil { - _, to, err = dst.Files() - if err != nil { - return nil, err - } - } - - di, err := fileSimilarityIndex(to) - if err != nil { - if err == errIndexFull { - dstTooLarge[dstIdx] = true - } - - return nil, err - } - - contentScore := s.score(di, 10000) - // The name score returns a value between 0 and 100, so we need to - // convert it to the same range as the content score. - nameScore := nameSimilarityScore(src.From.Name, dst.To.Name) * 100 - score := (contentScore*99 + nameScore*1) / 10000 - - if score < renameScore { - continue - } - - matrix = append(matrix, similarityPair{added: dstIdx, deleted: srcIdx, score: score}) - } - } - - sort.Stable(matrix) - - return matrix, nil -} - -func compactChanges(changes []*Change) []*Change { - var result []*Change - for _, c := range changes { - if c != nil { - result = append(result, c) - } - } - return result -} - -const ( - keyShift = 32 - maxCountValue = (1 << keyShift) - 1 -) - -var errIndexFull = errors.New("index is full") - -// similarityIndex is an index structure of lines/blocks in one file. -// This structure can be used to compute an approximation of the similarity -// between two files. -// To save space in memory, this index uses a space efficient encoding which -// will not exceed 1MiB per instance. The index starts out at a smaller size -// (closer to 2KiB), but may grow as more distinct blocks within the scanned -// file are discovered. -// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java -type similarityIndex struct { - hashed uint64 - // number of non-zero entries in hashes - numHashes int - growAt int - hashes []keyCountPair - hashBits int -} - -func fileSimilarityIndex(f *File) (*similarityIndex, error) { - idx := newSimilarityIndex() - if err := idx.hash(f); err != nil { - return nil, err - } - - sort.Stable(keyCountPairs(idx.hashes)) - - return idx, nil -} - -func newSimilarityIndex() *similarityIndex { - return &similarityIndex{ - hashBits: 8, - hashes: make([]keyCountPair, 1<<8), - growAt: shouldGrowAt(8), - } -} - -func (i *similarityIndex) hash(f *File) error { - isBin, err := f.IsBinary() - if err != nil { - return err - } - - r, err := f.Reader() - if err != nil { - return err - } - - defer ioutil.CheckClose(r, &err) - - return i.hashContent(r, f.Size, isBin) -} - -func (i *similarityIndex) hashContent(r io.Reader, size int64, isBin bool) error { - var buf = make([]byte, 4096) - var ptr, cnt int - remaining := size - - for 0 < remaining { - hash := 5381 - var blockHashedCnt uint64 - - // Hash one line or block, whatever happens first - n := int64(0) - for { - if ptr == cnt { - ptr = 0 - var err error - cnt, err = io.ReadFull(r, buf) - if err != nil && err != io.ErrUnexpectedEOF { - return err - } - - if cnt == 0 { - return io.EOF - } - } - n++ - c := buf[ptr] & 0xff - ptr++ - - // Ignore CR in CRLF sequence if it's text - if !isBin && c == '\r' && ptr < cnt && buf[ptr] == '\n' { - continue - } - blockHashedCnt++ - - if c == '\n' { - break - } - - hash = (hash << 5) + hash + int(c) - - if n >= 64 || n >= remaining { - break - } - } - i.hashed += blockHashedCnt - if err := i.add(hash, blockHashedCnt); err != nil { - return err - } - remaining -= n - } - - return nil -} - -// score computes the similarity score between this index and another one. -// A region of a file is defined as a line in a text file or a fixed-size -// block in a binary file. To prepare an index, each region in the file is -// hashed; the values and counts of hashes are retained in a sorted table. -// Define the similarity fraction F as the count of matching regions between -// the two files divided between the maximum count of regions in either file. -// The similarity score is F multiplied by the maxScore constant, yielding a -// range [0, maxScore]. It is defined as maxScore for the degenerate case of -// two empty files. -// The similarity score is symmetrical; i.e. a.score(b) == b.score(a). -func (i *similarityIndex) score(other *similarityIndex, maxScore int) int { - var maxHashed = i.hashed - if maxHashed < other.hashed { - maxHashed = other.hashed - } - if maxHashed == 0 { - return maxScore - } - - return int(i.common(other) * uint64(maxScore) / maxHashed) -} - -func (i *similarityIndex) common(dst *similarityIndex) uint64 { - srcIdx, dstIdx := 0, 0 - if i.numHashes == 0 || dst.numHashes == 0 { - return 0 - } - - var common uint64 - srcKey, dstKey := i.hashes[srcIdx].key(), dst.hashes[dstIdx].key() - - for { - if srcKey == dstKey { - srcCnt, dstCnt := i.hashes[srcIdx].count(), dst.hashes[dstIdx].count() - if srcCnt < dstCnt { - common += srcCnt - } else { - common += dstCnt - } - - srcIdx++ - if srcIdx == len(i.hashes) { - break - } - srcKey = i.hashes[srcIdx].key() - - dstIdx++ - if dstIdx == len(dst.hashes) { - break - } - dstKey = dst.hashes[dstIdx].key() - } else if srcKey < dstKey { - // Region of src that is not in dst - srcIdx++ - if srcIdx == len(i.hashes) { - break - } - srcKey = i.hashes[srcIdx].key() - } else { - // Region of dst that is not in src - dstIdx++ - if dstIdx == len(dst.hashes) { - break - } - dstKey = dst.hashes[dstIdx].key() - } - } - - return common -} - -func (i *similarityIndex) add(key int, cnt uint64) error { - key = int(uint32(key) * 0x9e370001 >> 1) - - j := i.slot(key) - for { - v := i.hashes[j] - if v == 0 { - // It's an empty slot, so we can store it here. - if i.growAt <= i.numHashes { - if err := i.grow(); err != nil { - return err - } - j = i.slot(key) - continue - } - - var err error - i.hashes[j], err = newKeyCountPair(key, cnt) - if err != nil { - return err - } - i.numHashes++ - return nil - } else if v.key() == key { - // It's the same key, so increment the counter. - var err error - i.hashes[j], err = newKeyCountPair(key, v.count()+cnt) - return err - } else if j+1 >= len(i.hashes) { - j = 0 - } else { - j++ - } - } -} - -type keyCountPair uint64 - -func newKeyCountPair(key int, cnt uint64) (keyCountPair, error) { - if cnt > maxCountValue { - return 0, errIndexFull - } - - return keyCountPair((uint64(key) << keyShift) | cnt), nil -} - -func (p keyCountPair) key() int { - return int(p >> keyShift) -} - -func (p keyCountPair) count() uint64 { - return uint64(p) & maxCountValue -} - -func (i *similarityIndex) slot(key int) int { - // We use 31 - hashBits because the upper bit was already forced - // to be 0 and we want the remaining high bits to be used as the - // table slot. - return int(uint32(key) >> uint(31-i.hashBits)) -} - -func shouldGrowAt(hashBits int) int { - return (1 << uint(hashBits)) * (hashBits - 3) / hashBits -} - -func (i *similarityIndex) grow() error { - if i.hashBits == 30 { - return errIndexFull - } - - old := i.hashes - - i.hashBits++ - i.growAt = shouldGrowAt(i.hashBits) - - // TODO(erizocosmico): find a way to check if it will OOM and return - // errIndexFull instead. - i.hashes = make([]keyCountPair, 1<= len(i.hashes) { - j = 0 - } - } - i.hashes[j] = v - } - } - - return nil -} - -type keyCountPairs []keyCountPair - -func (p keyCountPairs) Len() int { return len(p) } -func (p keyCountPairs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } -func (p keyCountPairs) Less(i, j int) bool { return p[i] < p[j] } diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/signature.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/signature.go deleted file mode 100644 index f9c3d306..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/signature.go +++ /dev/null @@ -1,102 +0,0 @@ -package object - -import "bytes" - -const ( - signatureTypeUnknown signatureType = iota - signatureTypeOpenPGP - signatureTypeX509 - signatureTypeSSH -) - -var ( - // openPGPSignatureFormat is the format of an OpenPGP signature. - openPGPSignatureFormat = signatureFormat{ - []byte("-----BEGIN PGP SIGNATURE-----"), - []byte("-----BEGIN PGP MESSAGE-----"), - } - // x509SignatureFormat is the format of an X509 signature, which is - // a PKCS#7 (S/MIME) signature. - x509SignatureFormat = signatureFormat{ - []byte("-----BEGIN CERTIFICATE-----"), - []byte("-----BEGIN SIGNED MESSAGE-----"), - } - - // sshSignatureFormat is the format of an SSH signature. - sshSignatureFormat = signatureFormat{ - []byte("-----BEGIN SSH SIGNATURE-----"), - } -) - -var ( - // knownSignatureFormats is a map of known signature formats, indexed by - // their signatureType. - knownSignatureFormats = map[signatureType]signatureFormat{ - signatureTypeOpenPGP: openPGPSignatureFormat, - signatureTypeX509: x509SignatureFormat, - signatureTypeSSH: sshSignatureFormat, - } -) - -// signatureType represents the type of the signature. -type signatureType int8 - -// signatureFormat represents the beginning of a signature. -type signatureFormat [][]byte - -// typeForSignature returns the type of the signature based on its format. -func typeForSignature(b []byte) signatureType { - for t, i := range knownSignatureFormats { - for _, begin := range i { - if bytes.HasPrefix(b, begin) { - return t - } - } - } - return signatureTypeUnknown -} - -// parseSignedBytes returns the position of the last signature block found in -// the given bytes. If no signature block is found, it returns -1. -// -// When multiple signature blocks are found, the position of the last one is -// returned. Any tailing bytes after this signature block start should be -// considered part of the signature. -// -// Given this, it would be safe to use the returned position to split the bytes -// into two parts: the first part containing the message, the second part -// containing the signature. -// -// Example: -// -// message := []byte(`Message with signature -// -// -----BEGIN SSH SIGNATURE----- -// ...`) -// -// var signature string -// if pos, _ := parseSignedBytes(message); pos != -1 { -// signature = string(message[pos:]) -// message = message[:pos] -// } -// -// This logic is on par with git's gpg-interface.c:parse_signed_buffer(). -// https://github.com/git/git/blob/7c2ef319c52c4997256f5807564523dfd4acdfc7/gpg-interface.c#L668 -func parseSignedBytes(b []byte) (int, signatureType) { - var n, match = 0, -1 - var t signatureType - for n < len(b) { - var i = b[n:] - if st := typeForSignature(i); st != signatureTypeUnknown { - match = n - t = st - } - if eol := bytes.IndexByte(i, '\n'); eol >= 0 { - n += eol + 1 - continue - } - // If we reach this point, we've reached the end. - break - } - return match, t -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/tag.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/tag.go deleted file mode 100644 index 4f2864e9..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/tag.go +++ /dev/null @@ -1,330 +0,0 @@ -package object - -import ( - "bytes" - "fmt" - "io" - "strings" - - "github.com/ProtonMail/go-crypto/openpgp" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/sync" -) - -// Tag represents an annotated tag object. It points to a single git object of -// any type, but tags typically are applied to commit or blob objects. It -// provides a reference that associates the target with a tag name. It also -// contains meta-information about the tag, including the tagger, tag date and -// message. -// -// Note that this is not used for lightweight tags. -// -// https://git-scm.com/book/en/v2/Git-Internals-Git-References#Tags -type Tag struct { - // Hash of the tag. - Hash plumbing.Hash - // Name of the tag. - Name string - // Tagger is the one who created the tag. - Tagger Signature - // Message is an arbitrary text message. - Message string - // PGPSignature is the PGP signature of the tag. - PGPSignature string - // TargetType is the object type of the target. - TargetType plumbing.ObjectType - // Target is the hash of the target object. - Target plumbing.Hash - - s storer.EncodedObjectStorer -} - -// GetTag gets a tag from an object storer and decodes it. -func GetTag(s storer.EncodedObjectStorer, h plumbing.Hash) (*Tag, error) { - o, err := s.EncodedObject(plumbing.TagObject, h) - if err != nil { - return nil, err - } - - return DecodeTag(s, o) -} - -// DecodeTag decodes an encoded object into a *Commit and associates it to the -// given object storer. -func DecodeTag(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Tag, error) { - t := &Tag{s: s} - if err := t.Decode(o); err != nil { - return nil, err - } - - return t, nil -} - -// ID returns the object ID of the tag, not the object that the tag references. -// The returned value will always match the current value of Tag.Hash. -// -// ID is present to fulfill the Object interface. -func (t *Tag) ID() plumbing.Hash { - return t.Hash -} - -// Type returns the type of object. It always returns plumbing.TagObject. -// -// Type is present to fulfill the Object interface. -func (t *Tag) Type() plumbing.ObjectType { - return plumbing.TagObject -} - -// Decode transforms a plumbing.EncodedObject into a Tag struct. -func (t *Tag) Decode(o plumbing.EncodedObject) (err error) { - if o.Type() != plumbing.TagObject { - return ErrUnsupportedObject - } - - t.Hash = o.Hash() - - reader, err := o.Reader() - if err != nil { - return err - } - defer ioutil.CheckClose(reader, &err) - - r := sync.GetBufioReader(reader) - defer sync.PutBufioReader(r) - - for { - var line []byte - line, err = r.ReadBytes('\n') - if err != nil && err != io.EOF { - return err - } - - line = bytes.TrimSpace(line) - if len(line) == 0 { - break // Start of message - } - - split := bytes.SplitN(line, []byte{' '}, 2) - switch string(split[0]) { - case "object": - t.Target = plumbing.NewHash(string(split[1])) - case "type": - t.TargetType, err = plumbing.ParseObjectType(string(split[1])) - if err != nil { - return err - } - case "tag": - t.Name = string(split[1]) - case "tagger": - t.Tagger.Decode(split[1]) - } - - if err == io.EOF { - return nil - } - } - - data, err := io.ReadAll(r) - if err != nil { - return err - } - if sm, _ := parseSignedBytes(data); sm >= 0 { - t.PGPSignature = string(data[sm:]) - data = data[:sm] - } - t.Message = string(data) - - return nil -} - -// Encode transforms a Tag into a plumbing.EncodedObject. -func (t *Tag) Encode(o plumbing.EncodedObject) error { - return t.encode(o, true) -} - -// EncodeWithoutSignature export a Tag into a plumbing.EncodedObject without the signature (correspond to the payload of the PGP signature). -func (t *Tag) EncodeWithoutSignature(o plumbing.EncodedObject) error { - return t.encode(o, false) -} - -func (t *Tag) encode(o plumbing.EncodedObject, includeSig bool) (err error) { - o.SetType(plumbing.TagObject) - w, err := o.Writer() - if err != nil { - return err - } - defer ioutil.CheckClose(w, &err) - - if _, err = fmt.Fprintf(w, - "object %s\ntype %s\ntag %s\ntagger ", - t.Target.String(), t.TargetType.Bytes(), t.Name); err != nil { - return err - } - - if err = t.Tagger.Encode(w); err != nil { - return err - } - - if _, err = fmt.Fprint(w, "\n\n"); err != nil { - return err - } - - if _, err = fmt.Fprint(w, t.Message); err != nil { - return err - } - - // Note that this is highly sensitive to what it sent along in the message. - // Message *always* needs to end with a newline, or else the message and the - // signature will be concatenated into a corrupt object. Since this is a - // lower-level method, we assume you know what you are doing and have already - // done the needful on the message in the caller. - if includeSig { - if _, err = fmt.Fprint(w, t.PGPSignature); err != nil { - return err - } - } - - return err -} - -// Commit returns the commit pointed to by the tag. If the tag points to a -// different type of object ErrUnsupportedObject will be returned. -func (t *Tag) Commit() (*Commit, error) { - if t.TargetType != plumbing.CommitObject { - return nil, ErrUnsupportedObject - } - - o, err := t.s.EncodedObject(plumbing.CommitObject, t.Target) - if err != nil { - return nil, err - } - - return DecodeCommit(t.s, o) -} - -// Tree returns the tree pointed to by the tag. If the tag points to a commit -// object the tree of that commit will be returned. If the tag does not point -// to a commit or tree object ErrUnsupportedObject will be returned. -func (t *Tag) Tree() (*Tree, error) { - switch t.TargetType { - case plumbing.CommitObject: - c, err := t.Commit() - if err != nil { - return nil, err - } - - return c.Tree() - case plumbing.TreeObject: - return GetTree(t.s, t.Target) - default: - return nil, ErrUnsupportedObject - } -} - -// Blob returns the blob pointed to by the tag. If the tag points to a -// different type of object ErrUnsupportedObject will be returned. -func (t *Tag) Blob() (*Blob, error) { - if t.TargetType != plumbing.BlobObject { - return nil, ErrUnsupportedObject - } - - return GetBlob(t.s, t.Target) -} - -// Object returns the object pointed to by the tag. -func (t *Tag) Object() (Object, error) { - o, err := t.s.EncodedObject(t.TargetType, t.Target) - if err != nil { - return nil, err - } - - return DecodeObject(t.s, o) -} - -// String returns the meta information contained in the tag as a formatted -// string. -func (t *Tag) String() string { - obj, _ := t.Object() - - return fmt.Sprintf( - "%s %s\nTagger: %s\nDate: %s\n\n%s\n%s", - plumbing.TagObject, t.Name, t.Tagger.String(), t.Tagger.When.Format(DateFormat), - t.Message, objectAsString(obj), - ) -} - -// Verify performs PGP verification of the tag with a provided armored -// keyring and returns openpgp.Entity associated with verifying key on success. -func (t *Tag) Verify(armoredKeyRing string) (*openpgp.Entity, error) { - keyRingReader := strings.NewReader(armoredKeyRing) - keyring, err := openpgp.ReadArmoredKeyRing(keyRingReader) - if err != nil { - return nil, err - } - - // Extract signature. - signature := strings.NewReader(t.PGPSignature) - - encoded := &plumbing.MemoryObject{} - // Encode tag components, excluding signature and get a reader object. - if err := t.EncodeWithoutSignature(encoded); err != nil { - return nil, err - } - er, err := encoded.Reader() - if err != nil { - return nil, err - } - - return openpgp.CheckArmoredDetachedSignature(keyring, er, signature, nil) -} - -// TagIter provides an iterator for a set of tags. -type TagIter struct { - storer.EncodedObjectIter - s storer.EncodedObjectStorer -} - -// NewTagIter takes a storer.EncodedObjectStorer and a -// storer.EncodedObjectIter and returns a *TagIter that iterates over all -// tags contained in the storer.EncodedObjectIter. -// -// Any non-tag object returned by the storer.EncodedObjectIter is skipped. -func NewTagIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *TagIter { - return &TagIter{iter, s} -} - -// Next moves the iterator to the next tag and returns a pointer to it. If -// there are no more tags, it returns io.EOF. -func (iter *TagIter) Next() (*Tag, error) { - obj, err := iter.EncodedObjectIter.Next() - if err != nil { - return nil, err - } - - return DecodeTag(iter.s, obj) -} - -// ForEach call the cb function for each tag contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *TagIter) ForEach(cb func(*Tag) error) error { - return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { - t, err := DecodeTag(iter.s, obj) - if err != nil { - return err - } - - return cb(t) - }) -} - -func objectAsString(obj Object) string { - switch o := obj.(type) { - case *Commit: - return o.String() - default: - return "" - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/tree.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/tree.go deleted file mode 100644 index c2eefb56..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/tree.go +++ /dev/null @@ -1,558 +0,0 @@ -package object - -import ( - "context" - "errors" - "fmt" - "io" - "path" - "path/filepath" - "sort" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/sync" -) - -const ( - maxTreeDepth = 1024 - startingStackSize = 8 -) - -// New errors defined by this package. -var ( - ErrMaxTreeDepth = errors.New("maximum tree depth exceeded") - ErrFileNotFound = errors.New("file not found") - ErrDirectoryNotFound = errors.New("directory not found") - ErrEntryNotFound = errors.New("entry not found") - ErrEntriesNotSorted = errors.New("entries in tree are not sorted") -) - -// Tree is basically like a directory - it references a bunch of other trees -// and/or blobs (i.e. files and sub-directories) -type Tree struct { - Entries []TreeEntry - Hash plumbing.Hash - - s storer.EncodedObjectStorer - m map[string]*TreeEntry - t map[string]*Tree // tree path cache -} - -// GetTree gets a tree from an object storer and decodes it. -func GetTree(s storer.EncodedObjectStorer, h plumbing.Hash) (*Tree, error) { - o, err := s.EncodedObject(plumbing.TreeObject, h) - if err != nil { - return nil, err - } - - return DecodeTree(s, o) -} - -// DecodeTree decodes an encoded object into a *Tree and associates it to the -// given object storer. -func DecodeTree(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Tree, error) { - t := &Tree{s: s} - if err := t.Decode(o); err != nil { - return nil, err - } - - return t, nil -} - -// TreeEntry represents a file -type TreeEntry struct { - Name string - Mode filemode.FileMode - Hash plumbing.Hash -} - -// File returns the hash of the file identified by the `path` argument. -// The path is interpreted as relative to the tree receiver. -func (t *Tree) File(path string) (*File, error) { - e, err := t.FindEntry(path) - if err != nil { - return nil, ErrFileNotFound - } - - blob, err := GetBlob(t.s, e.Hash) - if err != nil { - if errors.Is(err, plumbing.ErrObjectNotFound) { - return nil, ErrFileNotFound - } - return nil, err - } - - return NewFile(path, e.Mode, blob), nil -} - -// Size returns the plaintext size of an object, without reading it -// into memory. -func (t *Tree) Size(path string) (int64, error) { - e, err := t.FindEntry(path) - if err != nil { - return 0, ErrEntryNotFound - } - - return t.s.EncodedObjectSize(e.Hash) -} - -// Tree returns the tree identified by the `path` argument. -// The path is interpreted as relative to the tree receiver. -func (t *Tree) Tree(path string) (*Tree, error) { - e, err := t.FindEntry(path) - if err != nil { - return nil, ErrDirectoryNotFound - } - - tree, err := GetTree(t.s, e.Hash) - if errors.Is(err, plumbing.ErrObjectNotFound) { - return nil, ErrDirectoryNotFound - } - - return tree, err -} - -// TreeEntryFile returns the *File for a given *TreeEntry. -func (t *Tree) TreeEntryFile(e *TreeEntry) (*File, error) { - blob, err := GetBlob(t.s, e.Hash) - if err != nil { - return nil, err - } - - return NewFile(e.Name, e.Mode, blob), nil -} - -// FindEntry search a TreeEntry in this tree or any subtree. -func (t *Tree) FindEntry(path string) (*TreeEntry, error) { - if t.t == nil { - t.t = make(map[string]*Tree) - } - - pathParts := strings.Split(path, "/") - startingTree := t - pathCurrent := "" - - // search for the longest path in the tree path cache - for i := len(pathParts) - 1; i > 1; i-- { - path := filepath.Join(pathParts[:i]...) - - tree, ok := t.t[path] - if ok { - startingTree = tree - pathParts = pathParts[i:] - pathCurrent = path - - break - } - } - - var tree *Tree - var err error - for tree = startingTree; len(pathParts) > 1; pathParts = pathParts[1:] { - if tree, err = tree.dir(pathParts[0]); err != nil { - return nil, err - } - - pathCurrent = filepath.Join(pathCurrent, pathParts[0]) - t.t[pathCurrent] = tree - } - - return tree.entry(pathParts[0]) -} - -func (t *Tree) dir(baseName string) (*Tree, error) { - entry, err := t.entry(baseName) - if err != nil { - return nil, ErrDirectoryNotFound - } - - obj, err := t.s.EncodedObject(plumbing.TreeObject, entry.Hash) - if err != nil { - return nil, err - } - - tree := &Tree{s: t.s} - err = tree.Decode(obj) - - return tree, err -} - -func (t *Tree) entry(baseName string) (*TreeEntry, error) { - if t.m == nil { - t.buildMap() - } - - entry, ok := t.m[baseName] - if !ok { - return nil, ErrEntryNotFound - } - - return entry, nil -} - -// Files returns a FileIter allowing to iterate over the Tree -func (t *Tree) Files() *FileIter { - return NewFileIter(t.s, t) -} - -// ID returns the object ID of the tree. The returned value will always match -// the current value of Tree.Hash. -// -// ID is present to fulfill the Object interface. -func (t *Tree) ID() plumbing.Hash { - return t.Hash -} - -// Type returns the type of object. It always returns plumbing.TreeObject. -func (t *Tree) Type() plumbing.ObjectType { - return plumbing.TreeObject -} - -// Decode transform an plumbing.EncodedObject into a Tree struct -func (t *Tree) Decode(o plumbing.EncodedObject) (err error) { - if o.Type() != plumbing.TreeObject { - return ErrUnsupportedObject - } - - t.Hash = o.Hash() - if o.Size() == 0 { - return nil - } - - t.Entries = nil - t.m = nil - - reader, err := o.Reader() - if err != nil { - return err - } - defer ioutil.CheckClose(reader, &err) - - r := sync.GetBufioReader(reader) - defer sync.PutBufioReader(r) - - for { - str, err := r.ReadString(' ') - if err != nil { - if err == io.EOF { - break - } - - return err - } - str = str[:len(str)-1] // strip last byte (' ') - - mode, err := filemode.New(str) - if err != nil { - return err - } - - name, err := r.ReadString(0) - if err != nil && err != io.EOF { - return err - } - - var hash plumbing.Hash - if _, err = hash.ReadFrom(r); err != nil { - return err - } - - baseName := name[:len(name)-1] - t.Entries = append(t.Entries, TreeEntry{ - Hash: hash, - Mode: mode, - Name: baseName, - }) - } - - return nil -} - -type TreeEntrySorter []TreeEntry - -func (s TreeEntrySorter) Len() int { - return len(s) -} - -func (s TreeEntrySorter) Less(i, j int) bool { - name1 := s[i].Name - name2 := s[j].Name - if s[i].Mode == filemode.Dir { - name1 += "/" - } - if s[j].Mode == filemode.Dir { - name2 += "/" - } - return name1 < name2 -} - -func (s TreeEntrySorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// Encode transforms a Tree into a plumbing.EncodedObject. -// The tree entries must be sorted by name. -func (t *Tree) Encode(o plumbing.EncodedObject) (err error) { - o.SetType(plumbing.TreeObject) - w, err := o.Writer() - if err != nil { - return err - } - - defer ioutil.CheckClose(w, &err) - - if !sort.IsSorted(TreeEntrySorter(t.Entries)) { - return ErrEntriesNotSorted - } - - for _, entry := range t.Entries { - if strings.IndexByte(entry.Name, 0) != -1 { - return fmt.Errorf("malformed filename %q", entry.Name) - } - if _, err = fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil { - return err - } - - if _, err = w.Write([]byte{0x00}); err != nil { - return err - } - - if _, err = entry.Hash.WriteTo(w); err != nil { - return err - } - } - - return err -} - -func (t *Tree) buildMap() { - t.m = make(map[string]*TreeEntry) - for i := 0; i < len(t.Entries); i++ { - t.m[t.Entries[i].Name] = &t.Entries[i] - } -} - -// Diff returns a list of changes between this tree and the provided one -func (t *Tree) Diff(to *Tree) (Changes, error) { - return t.DiffContext(context.Background(), to) -} - -// DiffContext returns a list of changes between this tree and the provided one -// Error will be returned if context expires. Provided context must be non nil. -// -// NOTE: Since version 5.1.0 the renames are correctly handled, the settings -// used are the recommended options DefaultDiffTreeOptions. -func (t *Tree) DiffContext(ctx context.Context, to *Tree) (Changes, error) { - return DiffTreeWithOptions(ctx, t, to, DefaultDiffTreeOptions) -} - -// Patch returns a slice of Patch objects with all the changes between trees -// in chunks. This representation can be used to create several diff outputs. -func (t *Tree) Patch(to *Tree) (*Patch, error) { - return t.PatchContext(context.Background(), to) -} - -// PatchContext returns a slice of Patch objects with all the changes between -// trees in chunks. This representation can be used to create several diff -// outputs. If context expires, an error will be returned. Provided context must -// be non-nil. -// -// NOTE: Since version 5.1.0 the renames are correctly handled, the settings -// used are the recommended options DefaultDiffTreeOptions. -func (t *Tree) PatchContext(ctx context.Context, to *Tree) (*Patch, error) { - changes, err := t.DiffContext(ctx, to) - if err != nil { - return nil, err - } - - return changes.PatchContext(ctx) -} - -// treeEntryIter facilitates iterating through the TreeEntry objects in a Tree. -type treeEntryIter struct { - t *Tree - pos int -} - -func (iter *treeEntryIter) Next() (TreeEntry, error) { - if iter.pos >= len(iter.t.Entries) { - return TreeEntry{}, io.EOF - } - iter.pos++ - return iter.t.Entries[iter.pos-1], nil -} - -// TreeWalker provides a means of walking through all of the entries in a Tree. -type TreeWalker struct { - stack []*treeEntryIter - base string - recursive bool - seen map[plumbing.Hash]bool - - s storer.EncodedObjectStorer - t *Tree -} - -// NewTreeWalker returns a new TreeWalker for the given tree. -// -// It is the caller's responsibility to call Close() when finished with the -// tree walker. -func NewTreeWalker(t *Tree, recursive bool, seen map[plumbing.Hash]bool) *TreeWalker { - stack := make([]*treeEntryIter, 0, startingStackSize) - stack = append(stack, &treeEntryIter{t, 0}) - - return &TreeWalker{ - stack: stack, - recursive: recursive, - seen: seen, - - s: t.s, - t: t, - } -} - -// Next returns the next object from the tree. Objects are returned in order -// and subtrees are included. After the last object has been returned further -// calls to Next() will return io.EOF. -// -// In the current implementation any objects which cannot be found in the -// underlying repository will be skipped automatically. It is possible that this -// may change in future versions. -func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) { - var obj *Tree - for { - current := len(w.stack) - 1 - if current < 0 { - // Nothing left on the stack so we're finished - err = io.EOF - return - } - - if current > maxTreeDepth { - // We're probably following bad data or some self-referencing tree - err = ErrMaxTreeDepth - return - } - - entry, err = w.stack[current].Next() - if err == io.EOF { - // Finished with the current tree, move back up to the parent - w.stack = w.stack[:current] - w.base, _ = path.Split(w.base) - w.base = strings.TrimSuffix(w.base, "/") - continue - } - - if err != nil { - return - } - - if w.seen[entry.Hash] { - continue - } - - if entry.Mode == filemode.Dir { - obj, err = GetTree(w.s, entry.Hash) - } - - name = simpleJoin(w.base, entry.Name) - - if err != nil { - err = io.EOF - return - } - - break - } - - if !w.recursive { - return - } - - if obj != nil { - w.stack = append(w.stack, &treeEntryIter{obj, 0}) - w.base = simpleJoin(w.base, entry.Name) - } - - return -} - -// Tree returns the tree that the tree walker most recently operated on. -func (w *TreeWalker) Tree() *Tree { - current := len(w.stack) - 1 - if w.stack[current].pos == 0 { - current-- - } - - if current < 0 { - return nil - } - - return w.stack[current].t -} - -// Close releases any resources used by the TreeWalker. -func (w *TreeWalker) Close() { - w.stack = nil -} - -// TreeIter provides an iterator for a set of trees. -type TreeIter struct { - storer.EncodedObjectIter - s storer.EncodedObjectStorer -} - -// NewTreeIter takes a storer.EncodedObjectStorer and a -// storer.EncodedObjectIter and returns a *TreeIter that iterates over all -// tree contained in the storer.EncodedObjectIter. -// -// Any non-tree object returned by the storer.EncodedObjectIter is skipped. -func NewTreeIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *TreeIter { - return &TreeIter{iter, s} -} - -// Next moves the iterator to the next tree and returns a pointer to it. If -// there are no more trees, it returns io.EOF. -func (iter *TreeIter) Next() (*Tree, error) { - for { - obj, err := iter.EncodedObjectIter.Next() - if err != nil { - return nil, err - } - - if obj.Type() != plumbing.TreeObject { - continue - } - - return DecodeTree(iter.s, obj) - } -} - -// ForEach call the cb function for each tree contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *TreeIter) ForEach(cb func(*Tree) error) error { - return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { - if obj.Type() != plumbing.TreeObject { - return nil - } - - t, err := DecodeTree(iter.s, obj) - if err != nil { - return err - } - - return cb(t) - }) -} - -func simpleJoin(parent, child string) string { - if len(parent) > 0 { - return parent + "/" + child - } - return child -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/object/treenoder.go b/vendor/github.com/go-git/go-git/v6/plumbing/object/treenoder.go deleted file mode 100644 index 155fb735..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/object/treenoder.go +++ /dev/null @@ -1,142 +0,0 @@ -package object - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// A treenoder is a helper type that wraps git trees into merkletrie -// noders. -// -// As a merkletrie noder doesn't understand the concept of modes (e.g. -// file permissions), the treenoder includes the mode of the git tree in -// the hash, so changes in the modes will be detected as modifications -// to the file contents by the merkletrie difftree algorithm. This is -// consistent with how the "git diff-tree" command works. -type treeNoder struct { - parent *Tree // the root node is its own parent - name string // empty string for the root node - mode filemode.FileMode - hash plumbing.Hash - children []noder.Noder // memoized -} - -// NewTreeRootNode returns the root node of a Tree -func NewTreeRootNode(t *Tree) noder.Noder { - if t == nil { - return &treeNoder{} - } - - return &treeNoder{ - parent: t, - name: "", - mode: filemode.Dir, - hash: t.Hash, - } -} - -func (t *treeNoder) Skip() bool { - return false -} - -func (t *treeNoder) isRoot() bool { - return t.name == "" -} - -func (t *treeNoder) String() string { - return "treeNoder <" + t.name + ">" -} - -func (t *treeNoder) Hash() []byte { - if t.mode == filemode.Deprecated { - return append(t.hash.Bytes(), filemode.Regular.Bytes()...) - } - return append(t.hash.Bytes(), t.mode.Bytes()...) -} - -func (t *treeNoder) Name() string { - return t.name -} - -func (t *treeNoder) IsDir() bool { - return t.mode == filemode.Dir -} - -// Children will return the children of a treenoder as treenoders, -// building them from the children of the wrapped git tree. -func (t *treeNoder) Children() ([]noder.Noder, error) { - if t.mode != filemode.Dir { - return noder.NoChildren, nil - } - - // children are memoized for efficiency - if t.children != nil { - return t.children, nil - } - - // the parent of the returned children will be ourself as a tree if - // we are a not the root treenoder. The root is special as it - // is is own parent. - parent := t.parent - if !t.isRoot() { - var err error - if parent, err = t.parent.Tree(t.name); err != nil { - return nil, err - } - } - - var err error - t.children, err = transformChildren(parent) - return t.children, err -} - -// Returns the children of a tree as treenoders. -// Efficiency is key here. -func transformChildren(t *Tree) ([]noder.Noder, error) { - var err error - var e TreeEntry - - // there will be more tree entries than children in the tree, - // due to submodules and empty directories, but I think it is still - // worth it to pre-allocate the whole array now, even if sometimes - // is bigger than needed. - ret := make([]noder.Noder, 0, len(t.Entries)) - - walker := NewTreeWalker(t, false, nil) // don't recurse - // don't defer walker.Close() for efficiency reasons. - for { - _, e, err = walker.Next() - if err == io.EOF { - break - } - if err != nil { - walker.Close() - return nil, err - } - - ret = append(ret, &treeNoder{ - parent: t, - name: e.Name, - mode: e.Mode, - hash: e.Hash, - }) - } - walker.Close() - - return ret, nil -} - -// len(t.tree.Entries) != the number of elements walked by treewalker -// for some reason because of empty directories, submodules, etc, so we -// have to walk here. -func (t *treeNoder) NumChildren() (int, error) { - children, err := t.Children() - if err != nil { - return 0, err - } - - return len(children), nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/objectid.go b/vendor/github.com/go-git/go-git/v6/plumbing/objectid.go deleted file mode 100644 index 63f3444c..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/objectid.go +++ /dev/null @@ -1,154 +0,0 @@ -package plumbing - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "fmt" - "io" - - format "github.com/go-git/go-git/v6/plumbing/format/config" -) - -var empty = make([]byte, format.SHA256Size) - -// FromHex parses a hexadecimal string and returns an ObjectID -// and a boolean confirming whether the operation was successful. -// The object format is inferred from the length of the input. -// -// For backwards compatibility, partial hashes will be handled as -// being SHA1. -func FromHex(in string) (ObjectID, bool) { - var id ObjectID - - switch len(in) { - case format.SHA256HexSize: - id.format = format.SHA256 - } - - out, err := hex.DecodeString(in) - if err != nil { - return id, false - } - - id.Write(out) - return id, true -} - -// FromBytes creates an ObjectID based off its hex representation in bytes. -// The object format is inferred from the length of the input. -// -// If the size of [in] does not match the supported object formats, -// an empty ObjectID will be returned. -func FromBytes(in []byte) (ObjectID, bool) { - var id ObjectID - - switch len(in) { - case format.SHA1Size: - id.format = format.SHA1 - - case format.SHA256Size: - id.format = format.SHA256 - - default: - return id, false - } - - copy(id.hash[:], in) - return id, true -} - -// ObjectID represents the ID of a Git object. The object data is kept -// in its hexadecimal form. -type ObjectID struct { - hash [format.SHA256Size]byte - format format.ObjectFormat -} - -// HexSize returns the size for the hex representation of the current -// object. -func (s ObjectID) HexSize() int { - return s.format.HexSize() -} - -// Size returns the length of the resulting hash. -func (s ObjectID) Size() int { - return s.format.Size() -} - -// Compare compares the hash's sum with a slice of bytes. -func (s ObjectID) Compare(b []byte) int { - return bytes.Compare(s.hash[:s.Size()], b) -} - -// Equal returns true if [in] equals the current object. -func (s ObjectID) Equal(in ObjectID) bool { - return bytes.Equal(s.hash[:], in.hash[:]) -} - -// Bytes returns the slice of bytes representing the hash in hexadecimal. -func (s ObjectID) Bytes() []byte { - if len(s.hash) == 0 { - v := make([]byte, s.Size()) - return v - } - return s.hash[:s.Size()] -} - -// HasPrefix checks whether the ObjectID starts with [prefix]. -func (s ObjectID) HasPrefix(prefix []byte) bool { - return bytes.HasPrefix(s.hash[:s.Size()], prefix) -} - -// IsZero returns true if the hash is zero. -func (s ObjectID) IsZero() bool { - return bytes.Equal(s.hash[:], empty) -} - -// String returns the hexadecimal representation of the ObjectID. -func (s ObjectID) String() string { - val := s.hash[:s.Size()] - return hex.EncodeToString(val) -} - -// Write writes the hexadecimal representation of the ObjectID from [in] -// directly into the current object. -func (s *ObjectID) Write(in []byte) (int, error) { - n := copy(s.hash[:], in[:]) - return n, nil -} - -// ReadFrom reads the Big Endian representation of the ObjectID from -// reader [r]. -func (s *ObjectID) ReadFrom(r io.Reader) (int64, error) { - err := binary.Read(r, binary.BigEndian, s.hash[:s.Size()]) - if err != nil { - return 0, fmt.Errorf("read hash from binary: %w", err) - } - return int64(s.Size()), nil -} - -// WriteTo writes the Big Endian representation of the ObjectID -// into the writer [w]. -func (s *ObjectID) WriteTo(w io.Writer) (int64, error) { - err := binary.Write(w, binary.BigEndian, s.hash[:s.Size()]) - if err != nil { - return 0, err - } - return int64(s.Size()), nil -} - -// ResetBySize resets the current ObjectID. It sets the -// underlying format based on the [idSize], which defaults -// to SHA1 for backwards compatibility. -// -// This enable complete reuse of this object without needing -// to create a new instance of ObjectID. -func (s *ObjectID) ResetBySize(idSize int) { - if idSize == format.SHA256Size { - s.format = format.SHA256 - } else { - s.format = format.SHA1 - } - copy(s.hash[:], s.hash[:0]) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs.go deleted file mode 100644 index f9dea869..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs.go +++ /dev/null @@ -1,225 +0,0 @@ -package packp - -import ( - "fmt" - "sort" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage/memory" -) - -// AdvRefs values represent the information transmitted on an -// advertised-refs message. Values from this type are not zero-value -// safe, use the New function instead. -type AdvRefs struct { - // Head stores the resolved HEAD reference if present. - // This can be present with git-upload-pack, not with git-receive-pack. - Head *plumbing.Hash - // Capabilities are the capabilities. - Capabilities *capability.List - // References are the hash references. - References map[string]plumbing.Hash - // Peeled are the peeled hash references. - Peeled map[string]plumbing.Hash - // Shallows are the shallow object ids. - Shallows []plumbing.Hash -} - -// NewAdvRefs returns a pointer to a new AdvRefs value, ready to be used. -func NewAdvRefs() *AdvRefs { - return &AdvRefs{ - Capabilities: capability.NewList(), - References: make(map[string]plumbing.Hash), - Peeled: make(map[string]plumbing.Hash), - Shallows: []plumbing.Hash{}, - } -} - -func (a *AdvRefs) AddReference(r *plumbing.Reference) error { - switch r.Type() { - case plumbing.SymbolicReference: - v := fmt.Sprintf("%s:%s", r.Name().String(), r.Target().String()) - return a.Capabilities.Add(capability.SymRef, v) - case plumbing.HashReference: - a.References[r.Name().String()] = r.Hash() - default: - return plumbing.ErrInvalidType - } - - return nil -} - -// XXX: AllReferences doesn't return all the references advertised by the -// server, instead, it only returns non-peeled references. -// Use MakeReferenceSlice to get all the references, their peeled values, and -// symrefs. -func (a *AdvRefs) AllReferences() (memory.ReferenceStorage, error) { - s := memory.ReferenceStorage{} - if err := a.addRefs(s); err != nil { - return s, plumbing.NewUnexpectedError(err) - } - - return s, nil -} - -func (a *AdvRefs) addRefs(s storer.ReferenceStorer) error { - for name, hash := range a.References { - ref := plumbing.NewReferenceFromStrings(name, hash.String()) - if err := s.SetReference(ref); err != nil { - return err - } - } - - if a.supportSymrefs() { - return a.addSymbolicRefs(s) - } - - return a.resolveHead(s) -} - -// If the server does not support symrefs capability, -// we need to guess the reference where HEAD is pointing to. -// -// Git versions prior to 1.8.4.3 has an special procedure to get -// the reference where is pointing to HEAD: -// - Check if a reference called master exists. If exists and it -// has the same hash as HEAD hash, we can say that HEAD is pointing to master -// - If master does not exists or does not have the same hash as HEAD, -// order references and check in that order if that reference has the same -// hash than HEAD. If yes, set HEAD pointing to that branch hash -// - If no reference is found, throw an error -func (a *AdvRefs) resolveHead(s storer.ReferenceStorer) error { - if a.Head == nil { - return nil - } - - ref, err := s.Reference(plumbing.Master) - - // check first if HEAD is pointing to master - if err == nil { - ok, err := a.createHeadIfCorrectReference(ref, s) - if err != nil { - return err - } - - if ok { - return nil - } - } - - if err != nil && err != plumbing.ErrReferenceNotFound { - return err - } - - // From here we are trying to guess the branch that HEAD is pointing - refIter, err := s.IterReferences() - if err != nil { - return err - } - - var refNames []string - err = refIter.ForEach(func(r *plumbing.Reference) error { - refNames = append(refNames, string(r.Name())) - return nil - }) - if err != nil { - return err - } - - sort.Strings(refNames) - - var headSet bool - for _, refName := range refNames { - ref, err := s.Reference(plumbing.ReferenceName(refName)) - if err != nil { - return err - } - ok, err := a.createHeadIfCorrectReference(ref, s) - if err != nil { - return err - } - if ok { - headSet = true - break - } - } - - if !headSet { - return plumbing.ErrReferenceNotFound - } - - return nil -} - -func (a *AdvRefs) createHeadIfCorrectReference( - reference *plumbing.Reference, - s storer.ReferenceStorer, -) (bool, error) { - if reference.Hash() == *a.Head { - headRef := plumbing.NewSymbolicReference(plumbing.HEAD, reference.Name()) - if err := s.SetReference(headRef); err != nil { - return false, err - } - - return true, nil - } - - return false, nil -} - -func (a *AdvRefs) addSymbolicRefs(s storer.ReferenceStorer) error { - for _, symref := range a.Capabilities.Get(capability.SymRef) { - chunks := strings.Split(symref, ":") - if len(chunks) != 2 { - err := fmt.Errorf("bad number of `:` in symref value (%q)", symref) - return plumbing.NewUnexpectedError(err) - } - name := plumbing.ReferenceName(chunks[0]) - target := plumbing.ReferenceName(chunks[1]) - ref := plumbing.NewSymbolicReference(name, target) - if err := s.SetReference(ref); err != nil { - return nil - } - } - - return nil -} - -func (a *AdvRefs) supportSymrefs() bool { - return a.Capabilities.Supports(capability.SymRef) -} - -// IsEmpty returns true if doesn't contain any reference. -func (a *AdvRefs) IsEmpty() bool { - return (a.Head == nil || a.Head.IsZero()) && - len(a.References) == 0 && - len(a.Peeled) == 0 && - len(a.Shallows) == 0 -} - -// MakeReferenceSlice returns a sorted slice with all the references, their -// peeled values, and symrefs. -func (a *AdvRefs) MakeReferenceSlice() ([]*plumbing.Reference, error) { - refs, err := a.AllReferences() - if err != nil { - return nil, err - } - allRefs := make([]*plumbing.Reference, 0, len(refs)) - - for _, ref := range refs { - allRefs = append(allRefs, ref) - if peeled, ok := a.Peeled[ref.Name().String()]; ok { - peeledRef := plumbing.NewReferenceFromStrings(ref.Name().String()+"^{}", peeled.String()) - allRefs = append(allRefs, peeledRef) - } - } - - sort.Slice(allRefs, func(i, j int) bool { - return allRefs[i].Name() < allRefs[j].Name() - }) - - return allRefs, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_decode.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_decode.go deleted file mode 100644 index 4437b061..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_decode.go +++ /dev/null @@ -1,263 +0,0 @@ -package packp - -import ( - "bytes" - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// Decode reads the next advertised-refs message form its input and -// stores it in the AdvRefs. -func (a *AdvRefs) Decode(r io.Reader) error { - d := newAdvRefsDecoder(r) - return d.Decode(a) -} - -type advRefsDecoder struct { - s io.Reader // a pkt-line reader from the input stream - line []byte // current pkt-line contents, use parser.nextLine() to make it advance - nLine int // current pkt-line number for debugging, begins at 1 - hash plumbing.Hash // last hash read - err error // sticky error, use the parser.error() method to fill this out - data *AdvRefs // parsed data is stored here -} - -var ( - // ErrEmptyAdvRefs is returned by Decode if it gets an empty advertised - // references message. - ErrEmptyAdvRefs = errors.New("empty advertised-ref message") - // ErrEmptyInput is returned by Decode if the input is empty. - ErrEmptyInput = errors.New("empty input") -) - -func newAdvRefsDecoder(r io.Reader) *advRefsDecoder { - return &advRefsDecoder{ - s: r, - } -} - -func (d *advRefsDecoder) Decode(v *AdvRefs) error { - d.data = v - - for state := decodeFirstHash; state != nil; { - state = state(d) - } - - return d.err -} - -type decoderStateFn func(*advRefsDecoder) decoderStateFn - -// fills out the parser sticky error -func (d *advRefsDecoder) error(format string, a ...interface{}) { - msg := fmt.Sprintf( - "pkt-line %d: %s", d.nLine, - fmt.Sprintf(format, a...), - ) - - d.err = NewErrUnexpectedData(msg, d.line) -} - -// Reads a new pkt-line from the scanner, makes its payload available as -// p.line and increments p.nLine. A successful invocation returns true, -// otherwise, false is returned and the sticky error is filled out -// accordingly. Trims eols at the end of the payloads. -func (d *advRefsDecoder) nextLine() bool { - d.nLine++ - - _, p, err := pktline.ReadLine(d.s) - if err != nil { - if !errors.Is(err, io.EOF) { - d.err = err - return false - } - - if d.nLine == 1 { - d.err = ErrEmptyInput - return false - } - - d.error("EOF") - return false - } - - d.line = p - d.line = bytes.TrimSuffix(d.line, eol) - - return true -} - -// If the first hash is zero, then a no-refs is coming. Otherwise, a -// list-of-refs is coming, and the hash will be followed by the first -// advertised ref. -func decodeFirstHash(p *advRefsDecoder) decoderStateFn { - if ok := p.nextLine(); !ok { - return nil - } - - // If the repository is empty, we receive a flush here (HTTP). - if isFlush(p.line) { - p.err = ErrEmptyAdvRefs - return nil - } - - // TODO: Use object-format (when available) for hash size. Git 2.41+ - if len(p.line) < hashSize { - p.error("cannot read hash, pkt-line too short") - return nil - } - - h, ok := plumbing.FromHex(string(p.line[:hashSize])) - if !ok { - p.error("invalid hash text: %s", p.line[:hashSize]) - return nil - } - - p.hash = h - p.line = p.line[hashSize:] - - if p.hash.IsZero() { - return decodeSkipNoRefs - } - - return decodeFirstRef -} - -// Skips SP "capabilities^{}" NUL -func decodeSkipNoRefs(p *advRefsDecoder) decoderStateFn { - if len(p.line) < len(noHeadMark) { - p.error("too short zero-id ref") - return nil - } - - if !bytes.HasPrefix(p.line, noHeadMark) { - p.error("malformed zero-id ref") - return nil - } - - p.line = p.line[len(noHeadMark):] - - return decodeCaps -} - -// decode the refname, expects SP refname NULL -func decodeFirstRef(l *advRefsDecoder) decoderStateFn { - if len(l.line) < 3 { - l.error("line too short after hash") - return nil - } - - if !bytes.HasPrefix(l.line, sp) { - l.error("no space after hash") - return nil - } - l.line = l.line[1:] - - chunks := bytes.SplitN(l.line, null, 2) - if len(chunks) < 2 { - l.error("NULL not found") - return nil - } - ref := chunks[0] - l.line = chunks[1] - - if bytes.Equal(ref, []byte(head)) { - l.data.Head = &l.hash - } else { - l.data.References[string(ref)] = l.hash - } - - return decodeCaps -} - -func decodeCaps(p *advRefsDecoder) decoderStateFn { - if err := p.data.Capabilities.Decode(p.line); err != nil { - p.error("invalid capabilities: %s", err) - return nil - } - - return decodeOtherRefs -} - -// The refs are either tips (obj-id SP refname) or a peeled (obj-id SP refname^{}). -// If there are no refs, then there might be a shallow or flush-ptk. -func decodeOtherRefs(p *advRefsDecoder) decoderStateFn { - if ok := p.nextLine(); !ok { - return nil - } - - if bytes.HasPrefix(p.line, shallow) { - return decodeShallow - } - - if len(p.line) == 0 { - return nil - } - - saveTo := p.data.References - if bytes.HasSuffix(p.line, peeled) { - p.line = bytes.TrimSuffix(p.line, peeled) - saveTo = p.data.Peeled - } - - ref, hash, err := readRef(p.line) - if err != nil { - p.error("%s", err) - return nil - } - saveTo[ref] = hash - - return decodeOtherRefs -} - -// Reads a ref-name -func readRef(data []byte) (string, plumbing.Hash, error) { - chunks := bytes.Split(data, sp) - switch { - case len(chunks) == 1: - return "", plumbing.ZeroHash, fmt.Errorf("malformed ref data: no space was found") - case len(chunks) > 2: - return "", plumbing.ZeroHash, fmt.Errorf("malformed ref data: more than one space found") - default: - return string(chunks[1]), plumbing.NewHash(string(chunks[0])), nil - } -} - -// Keeps reading shallows until a flush-pkt is found -func decodeShallow(p *advRefsDecoder) decoderStateFn { - if !bytes.HasPrefix(p.line, shallow) { - p.error("malformed shallow prefix, found %q... instead", p.line[:len(shallow)]) - return nil - } - p.line = bytes.TrimPrefix(p.line, shallow) - - if len(p.line) != hashSize { - p.error(fmt.Sprintf( - "malformed shallow hash: wrong length, expected 40 bytes, read %d bytes", - len(p.line))) - return nil - } - - text := p.line[:hashSize] - h, ok := plumbing.FromHex(string(text)) - if !ok { - p.error("invalid hash text: %s", string(text)) - return nil - } - - p.data.Shallows = append(p.data.Shallows, h) - - if ok := p.nextLine(); !ok { - return nil - } - - if len(p.line) == 0 { - return nil // successful parse of the advertised-refs message - } - - return decodeShallow -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_encode.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_encode.go deleted file mode 100644 index c6ad6f9d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/advrefs_encode.go +++ /dev/null @@ -1,163 +0,0 @@ -package packp - -import ( - "fmt" - "io" - "sort" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" -) - -// Encode writes the AdvRefs encoding to a writer. -// -// All the payloads will end with a newline character. Capabilities, -// references and shallows are written in alphabetical order, except for -// peeled references that always follow their corresponding references. -func (a *AdvRefs) Encode(w io.Writer) error { - e := newAdvRefsEncoder(w) - return e.Encode(a) -} - -type advRefsEncoder struct { - data *AdvRefs // data to encode - w io.Writer // where to write the encoded data - firstRefName string // reference name to encode in the first pkt-line (HEAD if present) - firstRefHash plumbing.Hash // hash referenced to encode in the first pkt-line (HEAD if present) - sortedRefs []string // hash references to encode ordered by increasing order - err error // sticky error -} - -func newAdvRefsEncoder(w io.Writer) *advRefsEncoder { - return &advRefsEncoder{ - w: w, - } -} - -func (e *advRefsEncoder) Encode(v *AdvRefs) error { - e.data = v - e.sortRefs() - e.setFirstRef() - - for state := encodeFirstLine; state != nil; { - state = state(e) - } - - return e.err -} - -// sortRefs returns a sorted slice of reference names by name. -func sortRefs(refs map[string]plumbing.Hash) []string { - if len(refs) > 0 { - sortedRefs := make([]string, 0, len(refs)) - for refName := range refs { - sortedRefs = append(sortedRefs, refName) - } - - sort.Strings(sortedRefs) - return sortedRefs - } - return nil -} - -func (e *advRefsEncoder) sortRefs() { - e.sortedRefs = sortRefs(e.data.References) -} - -func (e *advRefsEncoder) setFirstRef() { - if e.data.Head != nil { - e.firstRefName = head - e.firstRefHash = *e.data.Head - return - } - - if len(e.sortedRefs) > 0 { - refName := e.sortedRefs[0] - e.firstRefName = refName - e.firstRefHash = e.data.References[refName] - } -} - -type encoderStateFn func(*advRefsEncoder) encoderStateFn - -// Adds the first pkt-line payload: head hash, head ref and capabilities. -// If HEAD ref is not found, the first reference ordered in increasing order will be used. -// If there aren't HEAD neither refs, the first line will be "PKT-LINE(zero-id SP "capabilities^{}" NUL capability-list)". -// See: https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt -// See: https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt -func encodeFirstLine(e *advRefsEncoder) encoderStateFn { - const formatFirstLine = "%s %s\x00%s\n" - var firstLine string - capabilities := formatCaps(e.data.Capabilities) - - if e.firstRefName == "" { - firstLine = fmt.Sprintf(formatFirstLine, plumbing.ZeroHash.String(), "capabilities^{}", capabilities) - } else { - firstLine = fmt.Sprintf(formatFirstLine, e.firstRefHash.String(), e.firstRefName, capabilities) - } - - if _, e.err = pktline.WriteString(e.w, firstLine); e.err != nil { - return nil - } - - return encodeRefs -} - -func formatCaps(c *capability.List) string { - if c == nil { - return "" - } - - return c.String() -} - -// Adds the (sorted) refs: hash SP refname EOL -// and their peeled refs if any. -func encodeRefs(e *advRefsEncoder) encoderStateFn { - for _, r := range e.sortedRefs { - if r == e.firstRefName { - continue - } - - hash := e.data.References[r] - if _, e.err = pktline.Writef(e.w, "%s %s\n", hash.String(), r); e.err != nil { - return nil - } - - if hash, ok := e.data.Peeled[r]; ok { - if _, e.err = pktline.Writef(e.w, "%s %s^{}\n", hash.String(), r); e.err != nil { - return nil - } - } - } - - return encodeShallow -} - -// Adds the (sorted) shallows: "shallow" SP hash EOL -func encodeShallow(e *advRefsEncoder) encoderStateFn { - sorted := sortShallows(e.data.Shallows) - for _, hash := range sorted { - if _, e.err = pktline.Writef(e.w, "shallow %s\n", hash); e.err != nil { - return nil - } - } - - return encodeFlush -} - -func sortShallows(c []plumbing.Hash) []string { - ret := []string{} - for _, h := range c { - ret = append(ret, h.String()) - } - sort.Strings(ret) - - return ret -} - -func encodeFlush(e *advRefsEncoder) encoderStateFn { - e.err = pktline.WriteFlush(e.w) - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/capability.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/capability.go deleted file mode 100644 index b09c02ab..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/capability.go +++ /dev/null @@ -1,279 +0,0 @@ -// Package capability defines the server and client capabilities. -package capability - -import ( - "fmt" - "os" -) - -// Capability describes a server or client capability. -type Capability string - -func (n Capability) String() string { - return string(n) -} - -const ( - // MultiACK capability allows the server to return "ACK obj-id continue" as - // soon as it finds a commit that it can use as a common base, between the - // client's wants and the client's have set. - // - // By sending this early, the server can potentially head off the client - // from walking any further down that particular branch of the client's - // repository history. The client may still need to walk down other - // branches, sending have lines for those, until the server has a - // complete cut across the DAG, or the client has said "done". - // - // Without multi_ack, a client sends have lines in --date-order until - // the server has found a common base. That means the client will send - // have lines that are already known by the server to be common, because - // they overlap in time with another branch that the server hasn't found - // a common base on yet. - // - // For example suppose the client has commits in caps that the server - // doesn't and the server has commits in lower case that the client - // doesn't, as in the following diagram: - // - // +---- u ---------------------- x - // / +----- y - // / / - // a -- b -- c -- d -- E -- F - // \ - // +--- Q -- R -- S - // - // If the client wants x,y and starts out by saying have F,S, the server - // doesn't know what F,S is. Eventually the client says "have d" and - // the server sends "ACK d continue" to let the client know to stop - // walking down that line (so don't send c-b-a), but it's not done yet, - // it needs a base for x. The client keeps going with S-R-Q, until a - // gets reached, at which point the server has a clear base and it all - // ends. - // - // Without multi_ack the client would have sent that c-b-a chain anyway, - // interleaved with S-R-Q. - MultiACK Capability = "multi_ack" - // MultiACKDetailed is an extension of multi_ack that permits client to - // better understand the server's in-memory state. - MultiACKDetailed Capability = "multi_ack_detailed" - // NoDone should only be used with the smart HTTP protocol. If - // multi_ack_detailed and no-done are both present, then the sender is - // free to immediately send a pack following its first "ACK obj-id ready" - // message. - // - // Without no-done in the smart HTTP protocol, the server session would - // end and the client has to make another trip to send "done" before - // the server can send the pack. no-done removes the last round and - // thus slightly reduces latency. - NoDone Capability = "no-done" - // ThinPack is one with deltas which reference base objects not - // contained within the pack (but are known to exist at the receiving - // end). This can reduce the network traffic significantly, but it - // requires the receiving end to know how to "thicken" these packs by - // adding the missing bases to the pack. - // - // The upload-pack server advertises 'thin-pack' when it can generate - // and send a thin pack. A client requests the 'thin-pack' capability - // when it understands how to "thicken" it, notifying the server that - // it can receive such a pack. A client MUST NOT request the - // 'thin-pack' capability if it cannot turn a thin pack into a - // self-contained pack. - // - // Receive-pack, on the other hand, is assumed by default to be able to - // handle thin packs, but can ask the client not to use the feature by - // advertising the 'no-thin' capability. A client MUST NOT send a thin - // pack if the server advertises the 'no-thin' capability. - // - // The reasons for this asymmetry are historical. The receive-pack - // program did not exist until after the invention of thin packs, so - // historically the reference implementation of receive-pack always - // understood thin packs. Adding 'no-thin' later allowed receive-pack - // to disable the feature in a backwards-compatible manner. - ThinPack, NoThin Capability = "thin-pack", "no-thin" - // Sideband means that server can send, and client understand multiplexed - // progress reports and error info interleaved with the packfile itself. - // - // These two options are mutually exclusive. A modern client always - // favors Sideband64k. - // - // Either mode indicates that the packfile data will be streamed broken - // up into packets of up to either 1000 bytes in the case of 'side_band', - // or 65520 bytes in the case of 'side_band_64k'. Each packet is made up - // of a leading 4-byte pkt-line length of how much data is in the packet, - // followed by a 1-byte stream code, followed by the actual data. - // - // The stream code can be one of: - // - // 1 - pack data - // 2 - progress messages - // 3 - fatal error message just before stream aborts - // - // The "side-band-64k" capability came about as a way for newer clients - // that can handle much larger packets to request packets that are - // actually crammed nearly full, while maintaining backward compatibility - // for the older clients. - // - // Further, with side-band and its up to 1000-byte messages, it's actually - // 999 bytes of payload and 1 byte for the stream code. With side-band-64k, - // same deal, you have up to 65519 bytes of data and 1 byte for the stream - // code. - // - // The client MUST send only maximum of one of "side-band" and "side- - // band-64k". Server MUST diagnose it as an error if client requests - // both. - Sideband Capability = "side-band" - Sideband64k Capability = "side-band-64k" - // OFSDelta server can send, and client understand PACKv2 with delta - // referring to its base by position in pack rather than by an obj-id. That - // is, they can send/read OBJ_OFS_DELTA (aka type 6) in a packfile. - OFSDelta Capability = "ofs-delta" - // Agent the server may optionally send this capability to notify the client - // that the server is running version `X`. The client may optionally return - // its own agent string by responding with an `agent=Y` capability (but it - // MUST NOT do so if the server did not mention the agent capability). The - // `X` and `Y` strings may contain any printable ASCII characters except - // space (i.e., the byte range 32 < x < 127), and are typically of the form - // "package/version" (e.g., "git/1.8.3.1"). The agent strings are purely - // informative for statistics and debugging purposes, and MUST NOT be used - // to programmatically assume the presence or absence of particular features. - Agent Capability = "agent" - // Shallow capability adds "deepen", "shallow" and "unshallow" commands to - // the fetch-pack/upload-pack protocol so clients can request shallow - // clones. - Shallow Capability = "shallow" - // DeepenSince adds "deepen-since" command to fetch-pack/upload-pack - // protocol so the client can request shallow clones that are cut at a - // specific time, instead of depth. Internally it's equivalent of doing - // "rev-list --max-age=" on the server side. "deepen-since" - // cannot be used with "deepen". - DeepenSince Capability = "deepen-since" - // DeepenNot adds "deepen-not" command to fetch-pack/upload-pack - // protocol so the client can request shallow clones that are cut at a - // specific revision, instead of depth. Internally it's equivalent of - // doing "rev-list --not " on the server side. "deepen-not" - // cannot be used with "deepen", but can be used with "deepen-since". - DeepenNot Capability = "deepen-not" - // DeepenRelative if this capability is requested by the client, the - // semantics of "deepen" command is changed. The "depth" argument is the - // depth from the current shallow boundary, instead of the depth from - // remote refs. - DeepenRelative Capability = "deepen-relative" - // NoProgress the client was started with "git clone -q" or something, and - // doesn't want that side band 2. Basically the client just says "I do not - // wish to receive stream 2 on sideband, so do not send it to me, and if - // you did, I will drop it on the floor anyway". However, the sideband - // channel 3 is still used for error responses. - NoProgress Capability = "no-progress" - // IncludeTag capability is about sending annotated tags if we are - // sending objects they point to. If we pack an object to the client, and - // a tag object points exactly at that object, we pack the tag object too. - // In general this allows a client to get all new annotated tags when it - // fetches a branch, in a single network connection. - // - // Clients MAY always send include-tag, hardcoding it into a request when - // the server advertises this capability. The decision for a client to - // request include-tag only has to do with the client's desires for tag - // data, whether or not a server had advertised objects in the - // refs/tags/* namespace. - // - // Servers MUST pack the tags if their referrant is packed and the client - // has requested include-tags. - // - // Clients MUST be prepared for the case where a server has ignored - // include-tag and has not actually sent tags in the pack. In such - // cases the client SHOULD issue a subsequent fetch to acquire the tags - // that include-tag would have otherwise given the client. - // - // The server SHOULD send include-tag, if it supports it, regardless - // of whether or not there are tags available. - IncludeTag Capability = "include-tag" - // ReportStatus the receive-pack process can receive a 'report-status' - // capability, which tells it that the client wants a report of what - // happened after a packfile upload and reference update. If the pushing - // client requests this capability, after unpacking and updating references - // the server will respond with whether the packfile unpacked successfully - // and if each reference was updated successfully. If any of those were not - // successful, it will send back an error message. See pack-protocol.txt - // for example messages. - ReportStatus Capability = "report-status" - // ReportStatusV2 extends capability report-status by adding new "option" - // directives in order to support reference rewritten by the "proc-receive" - // hook. The "proc-receive" hook may handle a command for a - // pseudo-reference which may create or update a reference with different - // name, new-oid, and old-oid. While the capability report-status cannot - // report for such case. See gitprotocol-pack[5] for details. - ReportStatusV2 Capability = "report-status-v2" - // DeleteRefs If the server sends back this capability, it means that - // it is capable of accepting a zero-id value as the target - // value of a reference update. It is not sent back by the client, it - // simply informs the client that it can be sent zero-id values - // to delete references - DeleteRefs Capability = "delete-refs" - // Quiet If the receive-pack server advertises this capability, it is - // capable of silencing human-readable progress output which otherwise may - // be shown when processing the received pack. A send-pack client should - // respond with the 'quiet' capability to suppress server-side progress - // reporting if the local progress reporting is also being suppressed - // (e.g., via `push -q`, or if stderr does not go to a tty). - Quiet Capability = "quiet" - // Atomic If the server sends this capability it is capable of accepting - // atomic pushes. If the pushing client requests this capability, the server - // will update the refs in one atomic transaction. Either all refs are - // updated or none. - Atomic Capability = "atomic" - // PushOptions If the server sends this capability it is able to accept - // push options after the update commands have been sent, but before the - // packfile is streamed. If the pushing client requests this capability, - // the server will pass the options to the pre- and post- receive hooks - // that process this push request. - PushOptions Capability = "push-options" - // AllowTipSHA1InWant if the upload-pack server advertises this capability, - // fetch-pack may send "want" lines with SHA-1s that exist at the server but - // are not advertised by upload-pack. - AllowTipSHA1InWant Capability = "allow-tip-sha1-in-want" - // AllowReachableSHA1InWant if the upload-pack server advertises this - // capability, fetch-pack may send "want" lines with SHA-1s that exist at - // the server but are not advertised by upload-pack. - AllowReachableSHA1InWant Capability = "allow-reachable-sha1-in-want" - // PushCert the receive-pack server that advertises this capability is - // willing to accept a signed push certificate, and asks the to be - // included in the push certificate. A send-pack client MUST NOT - // send a push-cert packet unless the receive-pack server advertises - // this capability. - PushCert Capability = "push-cert" - // SymRef symbolic reference support for better negotiation. - SymRef Capability = "symref" - // ObjectFormat takes a hash algorithm as an argument, indicates that the - // server supports the given hash algorithms. - ObjectFormat Capability = "object-format" - // Filter if present, fetch-pack may send "filter" commands to request a - // partial clone or partial fetch and request that the server omit various objects from the packfile - Filter Capability = "filter" -) - -const userAgent = "go-git/6.x" - -// DefaultAgent provides the user agent string. -func DefaultAgent() string { - if envUserAgent, ok := os.LookupEnv("GO_GIT_USER_AGENT_EXTRA"); ok { - return fmt.Sprintf("%s %s", userAgent, envUserAgent) - } - return userAgent -} - -var known = map[Capability]bool{ - MultiACK: true, MultiACKDetailed: true, NoDone: true, ThinPack: true, - Sideband: true, Sideband64k: true, OFSDelta: true, Agent: true, - Shallow: true, DeepenSince: true, DeepenNot: true, DeepenRelative: true, - NoProgress: true, IncludeTag: true, ReportStatus: true, DeleteRefs: true, - Quiet: true, Atomic: true, PushOptions: true, AllowTipSHA1InWant: true, - AllowReachableSHA1InWant: true, PushCert: true, SymRef: true, - ObjectFormat: true, Filter: true, -} - -var requiresArgument = map[Capability]bool{ - Agent: true, PushCert: true, SymRef: true, ObjectFormat: true, -} - -var multipleArgument = map[Capability]bool{ - SymRef: true, -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/list.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/list.go deleted file mode 100644 index 553d81cb..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/capability/list.go +++ /dev/null @@ -1,195 +0,0 @@ -package capability - -import ( - "bytes" - "errors" - "fmt" - "strings" -) - -var ( - // ErrArgumentsRequired is returned if no arguments are giving with a - // capability that requires arguments - ErrArgumentsRequired = errors.New("arguments required") - // ErrArguments is returned if arguments are given with a capabilities that - // not supports arguments - ErrArguments = errors.New("arguments not allowed") - // ErrEmptyArgument is returned when an empty value is given - ErrEmptyArgument = errors.New("empty argument") - // ErrMultipleArguments multiple argument given to a capabilities that not - // support it - ErrMultipleArguments = errors.New("multiple arguments not allowed") -) - -// List represents a list of capabilities -type List struct { - m map[Capability]*entry - sort []string -} - -type entry struct { - Name Capability - Values []string -} - -// NewList returns a new List of capabilities -func NewList() *List { - return &List{ - m: make(map[Capability]*entry), - } -} - -// IsEmpty returns true if the List is empty -func (l *List) IsEmpty() bool { - return len(l.sort) == 0 -} - -// Decode decodes list of capabilities from raw into the list -func (l *List) Decode(raw []byte) error { - // git 1.x receive pack used to send a leading space on its - // git-receive-pack capabilities announcement. We just trim space to be - // tolerant to space changes in different versions. - raw = bytes.TrimSpace(raw) - - if len(raw) == 0 { - return nil - } - - for _, data := range bytes.Split(raw, []byte{' '}) { - pair := bytes.SplitN(data, []byte{'='}, 2) - - c := Capability(pair[0]) - if len(pair) == 1 { - if err := l.Add(c); err != nil { - return err - } - - continue - } - - if err := l.Add(c, string(pair[1])); err != nil { - return err - } - } - - return nil -} - -// Get returns the values for a capability -func (l *List) Get(capability Capability) []string { - if _, ok := l.m[capability]; !ok { - return nil - } - - return l.m[capability].Values -} - -// Set sets a capability removing the previous values -func (l *List) Set(capability Capability, values ...string) error { - if _, ok := l.m[capability]; ok { - l.m[capability].Values = l.m[capability].Values[:0] - } - return l.Add(capability, values...) -} - -// Add adds a capability, values are optional -func (l *List) Add(c Capability, values ...string) error { - if err := l.validate(c, values); err != nil { - return err - } - - if !l.Supports(c) { - l.m[c] = &entry{Name: c} - l.sort = append(l.sort, c.String()) - } - - if len(values) == 0 { - return nil - } - - if known[c] && !multipleArgument[c] && len(l.m[c].Values) > 0 { - return ErrMultipleArguments - } - - l.m[c].Values = append(l.m[c].Values, values...) - return nil -} - -func (l *List) validateNoEmptyArgs(values []string) error { - for _, v := range values { - if v == "" { - return ErrEmptyArgument - } - } - return nil -} - -func (l *List) validate(c Capability, values []string) error { - if !known[c] { - return l.validateNoEmptyArgs(values) - } - if requiresArgument[c] && len(values) == 0 { - return ErrArgumentsRequired - } - - if !requiresArgument[c] && len(values) != 0 { - return ErrArguments - } - - if !multipleArgument[c] && len(values) > 1 { - return ErrMultipleArguments - } - return l.validateNoEmptyArgs(values) -} - -// Supports returns true if capability is present -func (l *List) Supports(capability Capability) bool { - _, ok := l.m[capability] - return ok -} - -// Delete deletes a capability from the List -func (l *List) Delete(capability Capability) { - if !l.Supports(capability) { - return - } - - delete(l.m, capability) - for i, c := range l.sort { - if c != string(capability) { - continue - } - - l.sort = append(l.sort[:i], l.sort[i+1:]...) - return - } -} - -// All returns a slice with all defined capabilities. -func (l *List) All() []Capability { - var cs []Capability - for _, key := range l.sort { - cs = append(cs, Capability(key)) - } - - return cs -} - -// String generates the capabilities strings, the capabilities are sorted in -// insertion order -func (l *List) String() string { - var o []string - for _, key := range l.sort { - cap := l.m[Capability(key)] - if len(cap.Values) == 0 { - o = append(o, key) - continue - } - - for _, value := range cap.Values { - o = append(o, fmt.Sprintf("%s=%s", key, value)) - } - } - - return strings.Join(o, " ") -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/common.go deleted file mode 100644 index a858323e..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/common.go +++ /dev/null @@ -1,74 +0,0 @@ -package packp - -import ( - "fmt" -) - -type stateFn func() stateFn - -const ( - // common - hashSize = 40 - - // advrefs - head = "HEAD" - noHead = "capabilities^{}" -) - -var ( - // common - sp = []byte(" ") - eol = []byte("\n") - - // advertised-refs - null = []byte("\x00") - peeled = []byte("^{}") - noHeadMark = []byte(" capabilities^{}\x00") - - // upload-request - want = []byte("want ") - shallow = []byte("shallow ") - deepen = []byte("deepen") - deepenCommits = []byte("deepen ") - deepenSince = []byte("deepen-since ") - deepenReference = []byte("deepen-not ") - - // shallow-update - unshallow = []byte("unshallow ") - - // server-response - ack = []byte("ACK") - nak = []byte("NAK") - - // updreq - shallowNoSp = []byte("shallow") -) - -func isFlush(payload []byte) bool { - return len(payload) == 0 -} - -var ( - // ErrNilWriter is returned when a nil writer is passed to the encoder. - ErrNilWriter = fmt.Errorf("nil writer") -) - -// ErrUnexpectedData represents an unexpected data decoding a message -type ErrUnexpectedData struct { - Msg string - Data []byte -} - -// NewErrUnexpectedData returns a new ErrUnexpectedData containing the data and -// the message given -func NewErrUnexpectedData(msg string, data []byte) error { - return &ErrUnexpectedData{Msg: msg, Data: data} -} - -func (err *ErrUnexpectedData) Error() string { - if len(err.Data) == 0 { - return err.Msg - } - - return fmt.Sprintf("%s (%s)", err.Msg, err.Data) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/doc.go deleted file mode 100644 index 4950d1d6..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/doc.go +++ /dev/null @@ -1,724 +0,0 @@ -package packp - -/* - -A nice way to trace the real data transmitted and received by git, use: - -GIT_TRACE_PACKET=true git ls-remote http://github.com/src-d/go-git -GIT_TRACE_PACKET=true git clone http://github.com/src-d/go-git - -Here follows a copy of the current protocol specification at the time of -this writing. - -(Please notice that most http git servers will add a flush-pkt after the -first pkt-line when using HTTP smart.) - - -Documentation Common to Pack and Http Protocols -=============================================== - -ABNF Notation -------------- - -ABNF notation as described by RFC 5234 is used within the protocol documents, -except the following replacement core rules are used: ----- - HEXDIG = DIGIT / "a" / "b" / "c" / "d" / "e" / "f" ----- - -We also define the following common rules: ----- - NUL = %x00 - zero-id = 40*"0" - obj-id = 40*(HEXDIGIT) - - refname = "HEAD" - refname /= "refs/" ----- - -A refname is a hierarchical octet string beginning with "refs/" and -not violating the 'git-check-ref-format' command's validation rules. -More specifically, they: - -. They can include slash `/` for hierarchical (directory) - grouping, but no slash-separated component can begin with a - dot `.`. - -. They must contain at least one `/`. This enforces the presence of a - category like `heads/`, `tags/` etc. but the actual names are not - restricted. - -. They cannot have two consecutive dots `..` anywhere. - -. They cannot have ASCII control characters (i.e. bytes whose - values are lower than \040, or \177 `DEL`), space, tilde `~`, - caret `^`, colon `:`, question-mark `?`, asterisk `*`, - or open bracket `[` anywhere. - -. They cannot end with a slash `/` or a dot `.`. - -. They cannot end with the sequence `.lock`. - -. They cannot contain a sequence `@{`. - -. They cannot contain a `\\`. - - -pkt-line Format ---------------- - -Much (but not all) of the payload is described around pkt-lines. - -A pkt-line is a variable length binary string. The first four bytes -of the line, the pkt-len, indicates the total length of the line, -in hexadecimal. The pkt-len includes the 4 bytes used to contain -the length's hexadecimal representation. - -A pkt-line MAY contain binary data, so implementors MUST ensure -pkt-line parsing/formatting routines are 8-bit clean. - -A non-binary line SHOULD BE terminated by an LF, which if present -MUST be included in the total length. Receivers MUST treat pkt-lines -with non-binary data the same whether or not they contain the trailing -LF (stripping the LF if present, and not complaining when it is -missing). - -The maximum length of a pkt-line's data component is 65516 bytes. -Implementations MUST NOT send pkt-line whose length exceeds 65520 -(65516 bytes of payload + 4 bytes of length data). - -Implementations SHOULD NOT send an empty pkt-line ("0004"). - -A pkt-line with a length field of 0 ("0000"), called a flush-pkt, -is a special case and MUST be handled differently than an empty -pkt-line ("0004"). - ----- - pkt-line = data-pkt / flush-pkt - - data-pkt = pkt-len pkt-payload - pkt-len = 4*(HEXDIG) - pkt-payload = (pkt-len - 4)*(OCTET) - - flush-pkt = "0000" ----- - -Examples (as C-style strings): - ----- - pkt-line actual value - --------------------------------- - "0006a\n" "a\n" - "0005a" "a" - "000bfoobar\n" "foobar\n" - "0004" "" ----- - -Packfile transfer protocols -=========================== - -Git supports transferring data in packfiles over the ssh://, git://, http:// and -file:// transports. There exist two sets of protocols, one for pushing -data from a client to a server and another for fetching data from a -server to a client. The three transports (ssh, git, file) use the same -protocol to transfer data. http is documented in http-protocol.txt. - -The processes invoked in the canonical Git implementation are 'upload-pack' -on the server side and 'fetch-pack' on the client side for fetching data; -then 'receive-pack' on the server and 'send-pack' on the client for pushing -data. The protocol functions to have a server tell a client what is -currently on the server, then for the two to negotiate the smallest amount -of data to send in order to fully update one or the other. - -pkt-line Format ---------------- - -The descriptions below build on the pkt-line format described in -protocol-common.txt. When the grammar indicate `PKT-LINE(...)`, unless -otherwise noted the usual pkt-line LF rules apply: the sender SHOULD -include a LF, but the receiver MUST NOT complain if it is not present. - -Transports ----------- -There are three transports over which the packfile protocol is -initiated. The Git transport is a simple, unauthenticated server that -takes the command (almost always 'upload-pack', though Git -servers can be configured to be globally writable, in which 'receive- -pack' initiation is also allowed) with which the client wishes to -communicate and executes it and connects it to the requesting -process. - -In the SSH transport, the client just runs the 'upload-pack' -or 'receive-pack' process on the server over the SSH protocol and then -communicates with that invoked process over the SSH connection. - -The file:// transport runs the 'upload-pack' or 'receive-pack' -process locally and communicates with it over a pipe. - -Git Transport -------------- - -The Git transport starts off by sending the command and repository -on the wire using the pkt-line format, followed by a NUL byte and a -hostname parameter, terminated by a NUL byte. - - 0032git-upload-pack /project.git\0host=myserver.com\0 - --- - git-proto-request = request-command SP pathname NUL [ host-parameter NUL ] - request-command = "git-upload-pack" / "git-receive-pack" / - "git-upload-archive" ; case sensitive - pathname = *( %x01-ff ) ; exclude NUL - host-parameter = "host=" hostname [ ":" port ] --- - -Only host-parameter is allowed in the git-proto-request. Clients -MUST NOT attempt to send additional parameters. It is used for the -git-daemon name based virtual hosting. See --interpolated-path -option to git daemon, with the %H/%CH format characters. - -Basically what the Git client is doing to connect to an 'upload-pack' -process on the server side over the Git protocol is this: - - $ echo -e -n \ - "0039git-upload-pack /schacon/gitbook.git\0host=example.com\0" | - nc -v example.com 9418 - -If the server refuses the request for some reasons, it could abort -gracefully with an error message. - ----- - error-line = PKT-LINE("ERR" SP explanation-text) ----- - - -SSH Transport -------------- - -Initiating the upload-pack or receive-pack processes over SSH is -executing the binary on the server via SSH remote execution. -It is basically equivalent to running this: - - $ ssh git.example.com "git-upload-pack '/project.git'" - -For a server to support Git pushing and pulling for a given user over -SSH, that user needs to be able to execute one or both of those -commands via the SSH shell that they are provided on login. On some -systems, that shell access is limited to only being able to run those -two commands, or even just one of them. - -In an ssh:// format URI, it's absolute in the URI, so the '/' after -the host name (or port number) is sent as an argument, which is then -read by the remote git-upload-pack exactly as is, so it's effectively -an absolute path in the remote filesystem. - - git clone ssh://user@example.com/project.git - | - v - ssh user@example.com "git-upload-pack '/project.git'" - -In a "user@host:path" format URI, its relative to the user's home -directory, because the Git client will run: - - git clone user@example.com:project.git - | - v - ssh user@example.com "git-upload-pack 'project.git'" - -The exception is if a '~' is used, in which case -we execute it without the leading '/'. - - ssh://user@example.com/~alice/project.git, - | - v - ssh user@example.com "git-upload-pack '~alice/project.git'" - -A few things to remember here: - -- The "command name" is spelled with dash (e.g. git-upload-pack), but - this can be overridden by the client; - -- The repository path is always quoted with single quotes. - -Fetching Data From a Server ---------------------------- - -When one Git repository wants to get data that a second repository -has, the first can 'fetch' from the second. This operation determines -what data the server has that the client does not then streams that -data down to the client in packfile format. - - -Reference Discovery -------------------- - -When the client initially connects the server will immediately respond -with a listing of each reference it has (all branches and tags) along -with the object name that each reference currently points to. - - $ echo -e -n "0039git-upload-pack /schacon/gitbook.git\0host=example.com\0" | - nc -v example.com 9418 - 00887217a7c7e582c46cec22a130adf4b9d7d950fba0 HEAD\0multi_ack thin-pack - side-band side-band-64k ofs-delta shallow no-progress include-tag - 00441d3fcd5ced445d1abc402225c0b8a1299641f497 refs/heads/integration - 003f7217a7c7e582c46cec22a130adf4b9d7d950fba0 refs/heads/master - 003cb88d2441cac0977faf98efc80305012112238d9d refs/tags/v0.9 - 003c525128480b96c89e6418b1e40909bf6c5b2d580f refs/tags/v1.0 - 003fe92df48743b7bc7d26bcaabfddde0a1e20cae47c refs/tags/v1.0^{} - 0000 - -The returned response is a pkt-line stream describing each ref and -its current value. The stream MUST be sorted by name according to -the C locale ordering. - -If HEAD is a valid ref, HEAD MUST appear as the first advertised -ref. If HEAD is not a valid ref, HEAD MUST NOT appear in the -advertisement list at all, but other refs may still appear. - -The stream MUST include capability declarations behind a NUL on the -first ref. The peeled value of a ref (that is "ref^{}") MUST be -immediately after the ref itself, if presented. A conforming server -MUST peel the ref if it's an annotated tag. - ----- - advertised-refs = (no-refs / list-of-refs) - *shallow - flush-pkt - - no-refs = PKT-LINE(zero-id SP "capabilities^{}" - NUL capability-list) - - list-of-refs = first-ref *other-ref - first-ref = PKT-LINE(obj-id SP refname - NUL capability-list) - - other-ref = PKT-LINE(other-tip / other-peeled) - other-tip = obj-id SP refname - other-peeled = obj-id SP refname "^{}" - - shallow = PKT-LINE("shallow" SP obj-id) - - capability-list = capability *(SP capability) - capability = 1*(LC_ALPHA / DIGIT / "-" / "_") - LC_ALPHA = %x61-7A ----- - -Server and client MUST use lowercase for obj-id, both MUST treat obj-id -as case-insensitive. - -See protocol-capabilities.txt for a list of allowed server capabilities -and descriptions. - -Packfile Negotiation --------------------- -After reference and capabilities discovery, the client can decide to -terminate the connection by sending a flush-pkt, telling the server it can -now gracefully terminate, and disconnect, when it does not need any pack -data. This can happen with the ls-remote command, and also can happen when -the client already is up-to-date. - -Otherwise, it enters the negotiation phase, where the client and -server determine what the minimal packfile necessary for transport is, -by telling the server what objects it wants, its shallow objects -(if any), and the maximum commit depth it wants (if any). The client -will also send a list of the capabilities it wants to be in effect, -out of what the server said it could do with the first 'want' line. - ----- - upload-request = want-list - *shallow-line - *1depth-request - flush-pkt - - want-list = first-want - *additional-want - - shallow-line = PKT-LINE("shallow" SP obj-id) - - depth-request = PKT-LINE("deepen" SP depth) / - PKT-LINE("deepen-since" SP timestamp) / - PKT-LINE("deepen-not" SP ref) - - first-want = PKT-LINE("want" SP obj-id SP capability-list) - additional-want = PKT-LINE("want" SP obj-id) - - depth = 1*DIGIT ----- - -Clients MUST send all the obj-ids it wants from the reference -discovery phase as 'want' lines. Clients MUST send at least one -'want' command in the request body. Clients MUST NOT mention an -obj-id in a 'want' command which did not appear in the response -obtained through ref discovery. - -The client MUST write all obj-ids which it only has shallow copies -of (meaning that it does not have the parents of a commit) as -'shallow' lines so that the server is aware of the limitations of -the client's history. - -The client now sends the maximum commit history depth it wants for -this transaction, which is the number of commits it wants from the -tip of the history, if any, as a 'deepen' line. A depth of 0 is the -same as not making a depth request. The client does not want to receive -any commits beyond this depth, nor does it want objects needed only to -complete those commits. Commits whose parents are not received as a -result are defined as shallow and marked as such in the server. This -information is sent back to the client in the next step. - -Once all the 'want's and 'shallow's (and optional 'deepen') are -transferred, clients MUST send a flush-pkt, to tell the server side -that it is done sending the list. - -Otherwise, if the client sent a positive depth request, the server -will determine which commits will and will not be shallow and -send this information to the client. If the client did not request -a positive depth, this step is skipped. - ----- - shallow-update = *shallow-line - *unshallow-line - flush-pkt - - shallow-line = PKT-LINE("shallow" SP obj-id) - - unshallow-line = PKT-LINE("unshallow" SP obj-id) ----- - -If the client has requested a positive depth, the server will compute -the set of commits which are no deeper than the desired depth. The set -of commits start at the client's wants. - -The server writes 'shallow' lines for each -commit whose parents will not be sent as a result. The server writes -an 'unshallow' line for each commit which the client has indicated is -shallow, but is no longer shallow at the currently requested depth -(that is, its parents will now be sent). The server MUST NOT mark -as unshallow anything which the client has not indicated was shallow. - -Now the client will send a list of the obj-ids it has using 'have' -lines, so the server can make a packfile that only contains the objects -that the client needs. In multi_ack mode, the canonical implementation -will send up to 32 of these at a time, then will send a flush-pkt. The -canonical implementation will skip ahead and send the next 32 immediately, -so that there is always a block of 32 "in-flight on the wire" at a time. - ----- - upload-haves = have-list - compute-end - - have-list = *have-line - have-line = PKT-LINE("have" SP obj-id) - compute-end = flush-pkt / PKT-LINE("done") ----- - -If the server reads 'have' lines, it then will respond by ACKing any -of the obj-ids the client said it had that the server also has. The -server will ACK obj-ids differently depending on which ack mode is -chosen by the client. - -In multi_ack mode: - - * the server will respond with 'ACK obj-id continue' for any common - commits. - - * once the server has found an acceptable common base commit and is - ready to make a packfile, it will blindly ACK all 'have' obj-ids - back to the client. - - * the server will then send a 'NAK' and then wait for another response - from the client - either a 'done' or another list of 'have' lines. - -In multi_ack_detailed mode: - - * the server will differentiate the ACKs where it is signaling - that it is ready to send data with 'ACK obj-id ready' lines, and - signals the identified common commits with 'ACK obj-id common' lines. - -Without either multi_ack or multi_ack_detailed: - - * upload-pack sends "ACK obj-id" on the first common object it finds. - After that it says nothing until the client gives it a "done". - - * upload-pack sends "NAK" on a flush-pkt if no common object - has been found yet. If one has been found, and thus an ACK - was already sent, it's silent on the flush-pkt. - -After the client has gotten enough ACK responses that it can determine -that the server has enough information to send an efficient packfile -(in the canonical implementation, this is determined when it has received -enough ACKs that it can color everything left in the --date-order queue -as common with the server, or the --date-order queue is empty), or the -client determines that it wants to give up (in the canonical implementation, -this is determined when the client sends 256 'have' lines without getting -any of them ACKed by the server - meaning there is nothing in common and -the server should just send all of its objects), then the client will send -a 'done' command. The 'done' command signals to the server that the client -is ready to receive its packfile data. - -However, the 256 limit *only* turns on in the canonical client -implementation if we have received at least one "ACK %s continue" -during a prior round. This helps to ensure that at least one common -ancestor is found before we give up entirely. - -Once the 'done' line is read from the client, the server will either -send a final 'ACK obj-id' or it will send a 'NAK'. 'obj-id' is the object -name of the last commit determined to be common. The server only sends -ACK after 'done' if there is at least one common base and multi_ack or -multi_ack_detailed is enabled. The server always sends NAK after 'done' -if there is no common base found. - -Then the server will start sending its packfile data. - ----- - server-response = *ack_multi ack / nak - ack_multi = PKT-LINE("ACK" SP obj-id ack_status) - ack_status = "continue" / "common" / "ready" - ack = PKT-LINE("ACK" SP obj-id) - nak = PKT-LINE("NAK") ----- - -A simple clone may look like this (with no 'have' lines): - ----- - C: 0054want 74730d410fcb6603ace96f1dc55ea6196122532d multi_ack \ - side-band-64k ofs-delta\n - C: 0032want 7d1665144a3a975c05f1f43902ddaf084e784dbe\n - C: 0032want 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a\n - C: 0032want 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n - C: 0032want 74730d410fcb6603ace96f1dc55ea6196122532d\n - C: 0000 - C: 0009done\n - - S: 0008NAK\n - S: [PACKFILE] ----- - -An incremental update (fetch) response might look like this: - ----- - C: 0054want 74730d410fcb6603ace96f1dc55ea6196122532d multi_ack \ - side-band-64k ofs-delta\n - C: 0032want 7d1665144a3a975c05f1f43902ddaf084e784dbe\n - C: 0032want 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a\n - C: 0000 - C: 0032have 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n - C: [30 more have lines] - C: 0032have 74730d410fcb6603ace96f1dc55ea6196122532d\n - C: 0000 - - S: 003aACK 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01 continue\n - S: 003aACK 74730d410fcb6603ace96f1dc55ea6196122532d continue\n - S: 0008NAK\n - - C: 0009done\n - - S: 0031ACK 74730d410fcb6603ace96f1dc55ea6196122532d\n - S: [PACKFILE] ----- - - -Packfile Data -------------- - -Now that the client and server have finished negotiation about what -the minimal amount of data that needs to be sent to the client is, the server -will construct and send the required data in packfile format. - -See pack-format.txt for what the packfile itself actually looks like. - -If 'side-band' or 'side-band-64k' capabilities have been specified by -the client, the server will send the packfile data multiplexed. - -Each packet starting with the packet-line length of the amount of data -that follows, followed by a single byte specifying the sideband the -following data is coming in on. - -In 'side-band' mode, it will send up to 999 data bytes plus 1 control -code, for a total of up to 1000 bytes in a pkt-line. In 'side-band-64k' -mode it will send up to 65519 data bytes plus 1 control code, for a -total of up to 65520 bytes in a pkt-line. - -The sideband byte will be a '1', '2' or a '3'. Sideband '1' will contain -packfile data, sideband '2' will be used for progress information that the -client will generally print to stderr and sideband '3' is used for error -information. - -If no 'side-band' capability was specified, the server will stream the -entire packfile without multiplexing. - - -Pushing Data To a Server ------------------------- - -Pushing data to a server will invoke the 'receive-pack' process on the -server, which will allow the client to tell it which references it should -update and then send all the data the server will need for those new -references to be complete. Once all the data is received and validated, -the server will then update its references to what the client specified. - -Authentication --------------- - -The protocol itself contains no authentication mechanisms. That is to be -handled by the transport, such as SSH, before the 'receive-pack' process is -invoked. If 'receive-pack' is configured over the Git transport, those -repositories will be writable by anyone who can access that port (9418) as -that transport is unauthenticated. - -Reference Discovery -------------------- - -The reference discovery phase is done nearly the same way as it is in the -fetching protocol. Each reference obj-id and name on the server is sent -in packet-line format to the client, followed by a flush-pkt. The only -real difference is that the capability listing is different - the only -possible values are 'report-status', 'delete-refs', 'ofs-delta' and -'push-options'. - -Reference Update Request and Packfile Transfer ----------------------------------------------- - -Once the client knows what references the server is at, it can send a -list of reference update requests. For each reference on the server -that it wants to update, it sends a line listing the obj-id currently on -the server, the obj-id the client would like to update it to and the name -of the reference. - -This list is followed by a flush-pkt. Then the push options are transmitted -one per packet followed by another flush-pkt. After that the packfile that -should contain all the objects that the server will need to complete the new -references will be sent. - ----- - update-request = *shallow ( command-list | push-cert ) [packfile] - - shallow = PKT-LINE("shallow" SP obj-id) - - command-list = PKT-LINE(command NUL capability-list) - *PKT-LINE(command) - flush-pkt - - command = create / delete / update - create = zero-id SP new-id SP name - delete = old-id SP zero-id SP name - update = old-id SP new-id SP name - - old-id = obj-id - new-id = obj-id - - push-cert = PKT-LINE("push-cert" NUL capability-list LF) - PKT-LINE("certificate version 0.1" LF) - PKT-LINE("pusher" SP ident LF) - PKT-LINE("pushee" SP url LF) - PKT-LINE("nonce" SP nonce LF) - PKT-LINE(LF) - *PKT-LINE(command LF) - *PKT-LINE(gpg-signature-lines LF) - PKT-LINE("push-cert-end" LF) - - packfile = "PACK" 28*(OCTET) ----- - -If the receiving end does not support delete-refs, the sending end MUST -NOT ask for delete command. - -If the receiving end does not support push-cert, the sending end -MUST NOT send a push-cert command. When a push-cert command is -sent, command-list MUST NOT be sent; the commands recorded in the -push certificate is used instead. - -The packfile MUST NOT be sent if the only command used is 'delete'. - -A packfile MUST be sent if either create or update command is used, -even if the server already has all the necessary objects. In this -case the client MUST send an empty packfile. The only time this -is likely to happen is if the client is creating -a new branch or a tag that points to an existing obj-id. - -The server will receive the packfile, unpack it, then validate each -reference that is being updated that it hasn't changed while the request -was being processed (the obj-id is still the same as the old-id), and -it will run any update hooks to make sure that the update is acceptable. -If all of that is fine, the server will then update the references. - -Push Certificate ----------------- - -A push certificate begins with a set of header lines. After the -header and an empty line, the protocol commands follow, one per -line. Note that the trailing LF in push-cert PKT-LINEs is _not_ -optional; it must be present. - -Currently, the following header fields are defined: - -`pusher` ident:: - Identify the GPG key in "Human Readable Name " - format. - -`pushee` url:: - The repository URL (anonymized, if the URL contains - authentication material) the user who ran `git push` - intended to push into. - -`nonce` nonce:: - The 'nonce' string the receiving repository asked the - pushing user to include in the certificate, to prevent - replay attacks. - -The GPG signature lines are a detached signature for the contents -recorded in the push certificate before the signature block begins. -The detached signature is used to certify that the commands were -given by the pusher, who must be the signer. - -Report Status -------------- - -After receiving the pack data from the sender, the receiver sends a -report if 'report-status' capability is in effect. -It is a short listing of what happened in that update. It will first -list the status of the packfile unpacking as either 'unpack ok' or -'unpack [error]'. Then it will list the status for each of the references -that it tried to update. Each line is either 'ok [refname]' if the -update was successful, or 'ng [refname] [error]' if the update was not. - ----- - report-status = unpack-status - 1*(command-status) - flush-pkt - - unpack-status = PKT-LINE("unpack" SP unpack-result) - unpack-result = "ok" / error-msg - - command-status = command-ok / command-fail - command-ok = PKT-LINE("ok" SP refname) - command-fail = PKT-LINE("ng" SP refname SP error-msg) - - error-msg = 1*(OCTECT) ; where not "ok" ----- - -Updates can be unsuccessful for a number of reasons. The reference can have -changed since the reference discovery phase was originally sent, meaning -someone pushed in the meantime. The reference being pushed could be a -non-fast-forward reference and the update hooks or configuration could be -set to not allow that, etc. Also, some references can be updated while others -can be rejected. - -An example client/server communication might look like this: - ----- - S: 007c74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/local\0report-status delete-refs ofs-delta\n - S: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe refs/heads/debug\n - S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/master\n - S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/team\n - S: 0000 - - C: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe 74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/debug\n - C: 003e74730d410fcb6603ace96f1dc55ea6196122532d 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/master\n - C: 0000 - C: [PACKDATA] - - S: 000eunpack ok\n - S: 0018ok refs/heads/debug\n - S: 002ang refs/heads/master non-fast-forward\n ----- -*/ diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/filter.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/filter.go deleted file mode 100644 index 40fb3ee6..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/filter.go +++ /dev/null @@ -1,77 +0,0 @@ -package packp - -import ( - "errors" - "fmt" - "net/url" - "strings" - - "github.com/go-git/go-git/v6/plumbing" -) - -var ErrUnsupportedObjectFilterType = errors.New("unsupported object filter type") - -// Filter values enable the partial clone capability which causes -// the server to omit objects that match the filter. -// -// See [Git's documentation] for more details. -// -// [Git's documentation]: https://github.com/git/git/blob/e02ecfcc534e2021aae29077a958dd11c3897e4c/Documentation/rev-list-options.txt#L948 -type Filter string - -type BlobLimitPrefix string - -const ( - BlobLimitPrefixNone BlobLimitPrefix = "" - BlobLimitPrefixKibi BlobLimitPrefix = "k" - BlobLimitPrefixMebi BlobLimitPrefix = "m" - BlobLimitPrefixGibi BlobLimitPrefix = "g" -) - -// FilterBlobNone omits all blobs. -func FilterBlobNone() Filter { - return "blob:none" -} - -// FilterBlobLimit omits blobs of size at least n bytes (when prefix is -// BlobLimitPrefixNone), n kibibytes (when prefix is BlobLimitPrefixKibi), -// n mebibytes (when prefix is BlobLimitPrefixMebi) or n gibibytes (when -// prefix is BlobLimitPrefixGibi). n can be zero, in which case all blobs -// will be omitted. -func FilterBlobLimit(n uint64, prefix BlobLimitPrefix) Filter { - return Filter(fmt.Sprintf("blob:limit=%d%s", n, prefix)) -} - -// FilterTreeDepth omits all blobs and trees whose depth from the root tree -// is larger or equal to depth. -func FilterTreeDepth(depth uint64) Filter { - return Filter(fmt.Sprintf("tree:%d", depth)) -} - -// FilterObjectType omits all objects which are not of the requested type t. -// Supported types are TagObject, CommitObject, TreeObject and BlobObject. -func FilterObjectType(t plumbing.ObjectType) (Filter, error) { - switch t { - case plumbing.TagObject: - fallthrough - case plumbing.CommitObject: - fallthrough - case plumbing.TreeObject: - fallthrough - case plumbing.BlobObject: - return Filter(fmt.Sprintf("object:type=%s", t.String())), nil - default: - return "", fmt.Errorf("%w: %s", ErrUnsupportedObjectFilterType, t.String()) - } -} - -// FilterCombine combines multiple Filter values together. -func FilterCombine(filters ...Filter) Filter { - var escapedFilters []string - - for _, filter := range filters { - escapedFilters = append(escapedFilters, url.QueryEscape(string(filter))) - } - - return Filter(fmt.Sprintf("combine:%s", strings.Join(escapedFilters, "+"))) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/gitproto.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/gitproto.go deleted file mode 100644 index 51b30664..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/gitproto.go +++ /dev/null @@ -1,117 +0,0 @@ -package packp - -import ( - "errors" - "fmt" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// ErrInvalidGitProtoRequest is returned by Decode if the input is not a -// valid git protocol request. -var ErrInvalidGitProtoRequest = fmt.Errorf("invalid git protocol request") - -// GitProtoRequest is a command request for the git protocol. -// It is used to send the command, endpoint, and extra parameters to the -// remote. -// See https://git-scm.com/docs/pack-protocol#_git_transport -type GitProtoRequest struct { - RequestCommand string - Pathname string - - // Optional - Host string - - // Optional - ExtraParams []string -} - -// validate validates the request. -func (g *GitProtoRequest) validate() error { - if g.RequestCommand == "" { - return fmt.Errorf("%w: empty request command", ErrInvalidGitProtoRequest) - } - - if g.Pathname == "" { - return fmt.Errorf("%w: empty pathname", ErrInvalidGitProtoRequest) - } - - return nil -} - -// Encode encodes the request into the writer. -func (g *GitProtoRequest) Encode(w io.Writer) error { - if w == nil { - return ErrNilWriter - } - - if err := g.validate(); err != nil { - return err - } - - req := fmt.Sprintf("%s %s\x00", g.RequestCommand, g.Pathname) - if host := g.Host; host != "" { - req += fmt.Sprintf("host=%s\x00", host) - } - - if len(g.ExtraParams) > 0 { - req += "\x00" - for _, param := range g.ExtraParams { - req += param + "\x00" - } - } - - if _, err := pktline.Writef(w, req); err != nil { - return err - } - - return nil -} - -// Decode decodes the request from the reader. -func (g *GitProtoRequest) Decode(r io.Reader) error { - _, p, err := pktline.ReadLine(r) - if errors.Is(err, io.EOF) { - return ErrInvalidGitProtoRequest - } - if err != nil { - return err - } - - line := string(p) - if len(line) == 0 { - return io.EOF - } - - if line[len(line)-1] != 0 { - return fmt.Errorf("%w: missing null terminator", ErrInvalidGitProtoRequest) - } - - parts := strings.SplitN(line, " ", 2) - if len(parts) != 2 { - return fmt.Errorf("%w: short request", ErrInvalidGitProtoRequest) - } - - g.RequestCommand = parts[0] - params := strings.Split(parts[1], string(null)) - if len(params) < 1 { - return fmt.Errorf("%w: missing pathname", ErrInvalidGitProtoRequest) - } - - g.Pathname = params[0] - if len(params) > 1 { - g.Host = strings.TrimPrefix(params[1], "host=") - } - - if len(params) > 2 { - for _, param := range params[2:] { - if param != "" { - g.ExtraParams = append(g.ExtraParams, param) - } - } - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/inforefs.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/inforefs.go deleted file mode 100644 index 93ac000f..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/inforefs.go +++ /dev/null @@ -1,67 +0,0 @@ -package packp - -import ( - "bufio" - "fmt" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing" -) - -// InfoRefs represents the information of the references advertised by an -// HTTP dumb server. -type InfoRefs struct { - // References are the hash references. - References map[string]plumbing.Hash - // Peeled are the peeled hash references. - Peeled map[string]plumbing.Hash -} - -func (i *InfoRefs) init() { - if i.References == nil { - i.References = make(map[string]plumbing.Hash) - } - if i.Peeled == nil { - i.Peeled = make(map[string]plumbing.Hash) - } -} - -// Decode decodes an InfoRefs from reader. -func (i *InfoRefs) Decode(r io.Reader) error { - i.init() - s := bufio.NewScanner(r) - for s.Scan() { - parts := strings.SplitN(s.Text(), "\t", 2) - if len(parts) != 2 { - continue - } - - hash := plumbing.NewHash(parts[0]) - refname := parts[1] - if strings.HasSuffix(refname, string(peeled)) { - i.Peeled[strings.TrimSuffix(refname, string(peeled))] = hash - } else { - i.References[refname] = hash - } - } - - return s.Err() -} - -// Encode encodes an InfoRefs to writer. -func (i *InfoRefs) Encode(w io.Writer) error { - sortedRefs := sortRefs(i.References) - for _, ref := range sortedRefs { - hash := i.References[ref] - if _, err := fmt.Fprintf(w, "%s\t%s\n", hash.String(), ref); err != nil { - return err - } - if peeled, ok := i.Peeled[ref]; ok { - if _, err := fmt.Fprintf(w, "%s\t%s%s\n", peeled.String(), ref, peeled); err != nil { - return err - } - } - } - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/packp.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/packp.go deleted file mode 100644 index a32370e5..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/packp.go +++ /dev/null @@ -1,15 +0,0 @@ -package packp - -import "io" - -// Encoder is the interface implemented by an object that can encode itself -// into a [io.Writer]. -type Encoder interface { - Encode(w io.Writer) error -} - -// Decoder is the interface implemented by an object that can decode itself -// from a [io.Reader]. -type Decoder interface { - Decode(r io.Reader) error -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/pushopts.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/pushopts.go deleted file mode 100644 index 6606fa71..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/pushopts.go +++ /dev/null @@ -1,50 +0,0 @@ -package packp - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// PushOptions represents a list of update request push-options. -// -// See https://git-scm.com/docs/gitprotocol-pack#_reference_update_request_and_packfile_transfer -type PushOptions struct { - Options []string -} - -// Encode encodes the push options into the given writer. -func (opts *PushOptions) Encode(w io.Writer) error { - if len(opts.Options) == 0 { - return nil - } - - for _, opt := range opts.Options { - if _, err := pktline.Writef(w, "%s", opt); err != nil { - return err - } - } - - return pktline.WriteFlush(w) -} - -// Decode decodes the push options from the given reader. -func (opts *PushOptions) Decode(r io.Reader) error { - if opts.Options == nil { - opts.Options = make([]string, 0) - } - - for { - l, line, err := pktline.ReadLine(r) - if err != nil { - return err - } - if l == pktline.Flush { - break - } - - opts.Options = append(opts.Options, string(line)) - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/report_status.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/report_status.go deleted file mode 100644 index 0927b37c..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/report_status.go +++ /dev/null @@ -1,203 +0,0 @@ -package packp - -import ( - "bytes" - "errors" - "fmt" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -const ( - ok = "ok" -) - -// UnpackStatusErr is the error returned when the report status is not ok. -type UnpackStatusErr struct { - Status string -} - -// Error implements the error interface. -func (e UnpackStatusErr) Error() string { - return fmt.Sprintf("unpack error: %s", e.Status) -} - -// CommandStatusErr is the error returned when the command status is not ok. -type CommandStatusErr struct { - ReferenceName plumbing.ReferenceName - Status string -} - -// Error implements the error interface. -func (e CommandStatusErr) Error() string { - return fmt.Sprintf("command error on %s: %s", e.ReferenceName.String(), e.Status) -} - -// ReportStatus is a report status message, as used in the git-receive-pack -// process whenever the 'report-status' capability is negotiated. -type ReportStatus struct { - UnpackStatus string - CommandStatuses []*CommandStatus -} - -// NewReportStatus creates a new ReportStatus message. -func NewReportStatus() *ReportStatus { - return &ReportStatus{} -} - -// Error returns the first error if any. -func (s *ReportStatus) Error() error { - if s.UnpackStatus != ok { - return UnpackStatusErr{s.UnpackStatus} - } - - for _, cs := range s.CommandStatuses { - if err := cs.Error(); err != nil { - // XXX: Here, we only return the first error following canonical - // Git behavior. - return err - } - } - - return nil -} - -// Encode writes the report status to a writer. -func (s *ReportStatus) Encode(w io.Writer) error { - if _, err := pktline.Writef(w, "unpack %s\n", s.UnpackStatus); err != nil { - return err - } - - for _, cs := range s.CommandStatuses { - if err := cs.encode(w); err != nil { - return err - } - } - - return pktline.WriteFlush(w) -} - -// Decode reads from the given reader and decodes a report-status message. It -// does not read more input than what is needed to fill the report status. -func (s *ReportStatus) Decode(r io.Reader) error { - b, err := s.scanFirstLine(r) - if err != nil { - return err - } - - if err := s.decodeReportStatus(b); err != nil { - return err - } - - var l int - flushed := false - for { - l, b, err = pktline.ReadLine(r) - if err != nil { - break - } - - if l == pktline.Flush { - flushed = true - break - } - - if err := s.decodeCommandStatus(b); err != nil { - return err - } - } - - if !flushed { - return fmt.Errorf("missing flush: %w", err) - } - - if err != nil && !errors.Is(err, io.EOF) { - // TODO: We should not ignore EOF errors here. Decoding a report-status - // message ends with a flush-pkt, an EOF indicates that the flush-pkt - // was not received. - return err - } - - return nil -} - -func (s *ReportStatus) scanFirstLine(r io.Reader) ([]byte, error) { - _, p, err := pktline.ReadLine(r) - if errors.Is(err, io.EOF) { - return p, io.ErrUnexpectedEOF - } - if err != nil { - return nil, err - } - - return p, nil -} - -func (s *ReportStatus) decodeReportStatus(b []byte) error { - if isFlush(b) { - return fmt.Errorf("premature flush") - } - - b = bytes.TrimSuffix(b, eol) - - line := string(b) - fields := strings.SplitN(line, " ", 2) - if len(fields) != 2 || fields[0] != "unpack" { - return fmt.Errorf("malformed unpack status: %s", line) - } - - s.UnpackStatus = fields[1] - return nil -} - -func (s *ReportStatus) decodeCommandStatus(b []byte) error { - b = bytes.TrimSuffix(b, eol) - - line := string(b) - fields := strings.SplitN(line, " ", 3) - status := ok - if len(fields) == 3 && fields[0] == "ng" { - status = fields[2] - } else if len(fields) != 2 || fields[0] != "ok" { - return fmt.Errorf("malformed command status: %s", line) - } - - cs := &CommandStatus{ - ReferenceName: plumbing.ReferenceName(fields[1]), - Status: status, - } - s.CommandStatuses = append(s.CommandStatuses, cs) - return nil -} - -// CommandStatus is the status of a reference in a report status. -// See ReportStatus struct. -type CommandStatus struct { - ReferenceName plumbing.ReferenceName - Status string -} - -// Error returns the error, if any. -func (s *CommandStatus) Error() error { - if s.Status == ok { - return nil - } - - return CommandStatusErr{ - ReferenceName: s.ReferenceName, - Status: s.Status, - } -} - -func (s *CommandStatus) encode(w io.Writer) error { - if s.Error() == nil { - _, err := pktline.Writef(w, "ok %s\n", s.ReferenceName.String()) - return err - } - - _, err := pktline.Writef(w, "ng %s %s\n", s.ReferenceName.String(), s.Status) - return err -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/shallowupd.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/shallowupd.go deleted file mode 100644 index 4262d195..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/shallowupd.go +++ /dev/null @@ -1,101 +0,0 @@ -package packp - -import ( - "bytes" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -const ( - shallowLineLen = 48 - unshallowLineLen = 50 -) - -type ShallowUpdate struct { - Shallows []plumbing.Hash - Unshallows []plumbing.Hash -} - -func (r *ShallowUpdate) Decode(reader io.Reader) error { - var ( - p []byte - err error - l int - ) - for { - l, p, err = pktline.ReadLine(reader) - if err != nil { - break - } - - line := bytes.TrimSpace(p) - switch { - case bytes.HasPrefix(line, shallow): - err = r.decodeShallowLine(line) - case bytes.HasPrefix(line, unshallow): - err = r.decodeUnshallowLine(line) - case l == pktline.Flush: - return nil - default: - err = fmt.Errorf("unexpected shallow line: %q", line) - } - - if err != nil { - return err - } - } - - if err != nil && err != io.EOF { - return err - } - - return nil -} - -func (r *ShallowUpdate) decodeShallowLine(line []byte) error { - hash, err := r.decodeLine(line, shallow, shallowLineLen) - if err != nil { - return err - } - - r.Shallows = append(r.Shallows, hash) - return nil -} - -func (r *ShallowUpdate) decodeUnshallowLine(line []byte) error { - hash, err := r.decodeLine(line, unshallow, unshallowLineLen) - if err != nil { - return err - } - - r.Unshallows = append(r.Unshallows, hash) - return nil -} - -func (r *ShallowUpdate) decodeLine(line, prefix []byte, expLen int) (plumbing.Hash, error) { - if len(line) != expLen { - return plumbing.ZeroHash, fmt.Errorf("malformed %s%q", prefix, line) - } - - raw := string(line[expLen-40 : expLen]) - return plumbing.NewHash(raw), nil -} - -func (r *ShallowUpdate) Encode(w io.Writer) error { - for _, h := range r.Shallows { - if _, err := pktline.Writef(w, "%s%s\n", shallow, h.String()); err != nil { - return err - } - } - - for _, h := range r.Unshallows { - if _, err := pktline.Writef(w, "%s%s\n", unshallow, h.String()); err != nil { - return err - } - } - - return pktline.WriteFlush(w) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/common.go deleted file mode 100644 index de500128..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/common.go +++ /dev/null @@ -1,33 +0,0 @@ -package sideband - -// Type sideband type "side-band" or "side-band-64k" -type Type int8 - -const ( - // Sideband legacy sideband type up to 1000-byte messages - Sideband Type = iota - // Sideband64k sideband type up to 65519-byte messages - Sideband64k Type = iota - - // MaxPackedSize for Sideband type - MaxPackedSize = 1000 - // MaxPackedSize64k for Sideband64k type - MaxPackedSize64k = 65520 -) - -// Channel sideband channel -type Channel byte - -// WithPayload encode the payload as a message -func (ch Channel) WithPayload(payload []byte) []byte { - return append([]byte{byte(ch)}, payload...) -} - -const ( - // PackData packfile content - PackData Channel = 1 - // ProgressMessage progress messages - ProgressMessage Channel = 2 - // ErrorMessage fatal error message just before stream aborts - ErrorMessage Channel = 3 -) diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/demux.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/demux.go deleted file mode 100644 index 4724ea70..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/demux.go +++ /dev/null @@ -1,148 +0,0 @@ -package sideband - -import ( - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// ErrMaxPackedExceeded returned by Read, if the maximum packed size is exceeded -var ErrMaxPackedExceeded = errors.New("max. packed size exceeded") - -// Progress where the progress information is stored -type Progress interface { - io.Writer -} - -// Demuxer demultiplexes the progress reports and error info interleaved with the -// packfile itself. -// -// A sideband has three different channels the main one, called PackData, contains -// the packfile data; the ErrorMessage channel, that contains server errors; and -// the last one, ProgressMessage channel, containing information about the ongoing -// task happening in the server (optional, can be suppressed sending NoProgress -// or Quiet capabilities to the server) -// -// In order to demultiplex the data stream, method `Read` should be called to -// retrieve the PackData channel, the incoming data from the ProgressMessage is -// written at `Progress` (if any), if any message is retrieved from the -// ErrorMessage channel an error is returned and we can assume that the -// connection has been closed. -type Demuxer struct { - t Type - r io.Reader - - max int - pending []byte - - // Progress is where the progress messages are stored - Progress Progress -} - -// NewDemuxer returns a new Demuxer for the given t and read from r -func NewDemuxer(t Type, r io.Reader) *Demuxer { - max := MaxPackedSize64k - if t == Sideband { - max = MaxPackedSize - } - - return &Demuxer{ - t: t, - r: r, - max: max, - } -} - -// Read reads up to len(p) bytes from the PackData channel into p, an error can -// be return if an error happens when reading or if a message is sent in the -// ErrorMessage channel. -// -// When a ProgressMessage is read, is not copy to b, instead of this is written -// to the Progress -// -// Read will return io.EOF when a flush packet is received after reading all -// the PackData channel data. -func (d *Demuxer) Read(b []byte) (read int, err error) { - req := len(b) - for read < req { - n, err := d.doRead(b[read:req]) - read += n - - if err != nil { - return read, err - } - } - - return read, nil -} - -func (d *Demuxer) doRead(b []byte) (int, error) { - read, err := d.nextPackData() - size := len(read) - wanted := len(b) - - if size > wanted { - d.pending = read[wanted:] - } - - if wanted > size { - wanted = size - } - - size = copy(b, read[:wanted]) - return size, err -} - -func (d *Demuxer) nextPackData() ([]byte, error) { - content := d.getPending() - if len(content) != 0 { - return content, nil - } - - l, p, err := pktline.ReadLine(d.r) - if err != nil { - return nil, err - } - - content = p - if l == pktline.Flush { - // Done demultiplex sidebands. Use io.EOF to indicate the end of - // sideband packets. - return nil, io.EOF - } else if l > d.max { - return nil, ErrMaxPackedExceeded - } - - if len(content) < 1 { - return nil, fmt.Errorf("invalid sideband pktline %04x %q", l, content) - } - - switch Channel(content[0]) { - case PackData: - return content[1:], nil - case ProgressMessage: - if d.Progress != nil { - _, err := d.Progress.Write(content[1:]) - return nil, err - } - case ErrorMessage: - return nil, fmt.Errorf("unexpected error: %s", content[1:]) - default: - return nil, fmt.Errorf("unknown channel %s", content) - } - - return nil, nil -} - -func (d *Demuxer) getPending() (b []byte) { - if len(d.pending) == 0 { - return nil - } - - content := d.pending - d.pending = nil - - return content -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/doc.go deleted file mode 100644 index c5d24295..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/doc.go +++ /dev/null @@ -1,31 +0,0 @@ -// Package sideband implements a sideband mutiplex/demultiplexer -package sideband - -// If 'side-band' or 'side-band-64k' capabilities have been specified by -// the client, the server will send the packfile data multiplexed. -// -// Either mode indicates that the packfile data will be streamed broken -// up into packets of up to either 1000 bytes in the case of 'side_band', -// or 65520 bytes in the case of 'side_band_64k'. Each packet is made up -// of a leading 4-byte pkt-line length of how much data is in the packet, -// followed by a 1-byte stream code, followed by the actual data. -// -// The stream code can be one of: -// -// 1 - pack data -// 2 - progress messages -// 3 - fatal error message just before stream aborts -// -// The "side-band-64k" capability came about as a way for newer clients -// that can handle much larger packets to request packets that are -// actually crammed nearly full, while maintaining backward compatibility -// for the older clients. -// -// Further, with side-band and its up to 1000-byte messages, it's actually -// 999 bytes of payload and 1 byte for the stream code. With side-band-64k, -// same deal, you have up to 65519 bytes of data and 1 byte for the stream -// code. -// -// The client MUST send only maximum of one of "side-band" and "side- -// band-64k". Server MUST diagnose it as an error if client requests -// both. diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/muxer.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/muxer.go deleted file mode 100644 index 2df790d4..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband/muxer.go +++ /dev/null @@ -1,66 +0,0 @@ -package sideband - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// Muxer multiplex the packfile along with the progress messages and the error -// information. The multiplex is perform using pktline format. -type Muxer struct { - max int - w io.Writer -} - -const chLen = 1 - -// NewMuxer returns a new Muxer for the given t that writes on w. -// -// If t is equal to `Sideband` the max pack size is set to MaxPackedSize, in any -// other value is given, max pack is set to MaxPackedSize64k, that is the -// maximum length of a line in pktline format. -func NewMuxer(t Type, w io.Writer) *Muxer { - max := MaxPackedSize64k - if t == Sideband { - max = MaxPackedSize - } - - return &Muxer{ - max: max - chLen, - w: w, - } -} - -// Write writes p in the PackData channel -func (m *Muxer) Write(p []byte) (int, error) { - return m.WriteChannel(PackData, p) -} - -// WriteChannel writes p in the given channel. This method can be used with any -// channel, but is recommend use it only for the ProgressMessage and -// ErrorMessage channels and use Write for the PackData channel -func (m *Muxer) WriteChannel(t Channel, p []byte) (int, error) { - wrote := 0 - size := len(p) - for wrote < size { - n, err := m.doWrite(t, p[wrote:]) - wrote += n - - if err != nil { - return wrote, err - } - } - - return wrote, nil -} - -func (m *Muxer) doWrite(ch Channel, p []byte) (int, error) { - sz := len(p) - if sz > m.max { - sz = m.max - } - - _, err := pktline.Write(m.w, ch.WithPayload(p[:sz])) - return sz, err -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/smart.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/smart.go deleted file mode 100644 index b71cbf04..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/smart.go +++ /dev/null @@ -1,60 +0,0 @@ -package packp - -import ( - "bytes" - "errors" - "fmt" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// ErrInvalidSmartReply is returned when a SmartReply is invalid. -var ErrInvalidSmartReply = errors.New("invalid smart reply") - -// SmartReply represents Git HTTP smart protocol service payload. -// -// When sending a message over (smart) HTTP, you have to add a pktline before -// the whole thing with the following payload: -// -// '# service=$servicename" LF -// -// Moreover, some if not all, git HTTP smart servers will send a flush-pkt just -// after the first pkt-line. -type SmartReply struct { - Service string -} - -// Decode decodes a SmartReply from reader. -func (s *SmartReply) Decode(r io.Reader) error { - _, p, err := pktline.ReadLine(r) - if err != nil { - return err - } - - if len(p) == 0 || !bytes.HasPrefix(p, []byte("# service=")) { - return fmt.Errorf("%w: %q", ErrInvalidSmartReply, p) - } - - s.Service = strings.TrimSpace(string(p[10:])) - l, _, err := pktline.ReadLine(r) - if err != nil { - return err - } - - if l != pktline.Flush { - return fmt.Errorf("%w: expected flush-pkt", ErrInvalidSmartReply) - } - - return nil -} - -// Encode encodes a SmartReply to writer. -func (s *SmartReply) Encode(w io.Writer) error { - if _, err := pktline.Writef(w, "# service=%s\n", s.Service); err != nil { - return err - } - - return pktline.WriteFlush(w) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/srvresp.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/srvresp.go deleted file mode 100644 index c6fee714..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/srvresp.go +++ /dev/null @@ -1,150 +0,0 @@ -package packp - -import ( - "bytes" - "errors" - "fmt" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -const ackLineLen = 44 - -// ServerResponse object acknowledgement from upload-pack service -type ServerResponse struct { - ACKs []ACK -} - -// ACKStatus represents the status of an object acknowledgement. -type ACKStatus byte - -// String returns the string representation of the ACKStatus. -func (s ACKStatus) String() string { - switch s { - case ACKContinue: - return "continue" - case ACKCommon: - return "common" - case ACKReady: - return "ready" - } - - return "" -} - -// ACKStatus values -const ( - ACKContinue ACKStatus = iota + 1 - ACKCommon - ACKReady -) - -// ACK represents an object acknowledgement. A status can be zero when the -// response doesn't support multi_ack and multi_ack_detailed capabilities. -type ACK struct { - Hash plumbing.Hash - Status ACKStatus -} - -// Decode decodes the response into the struct. -func (r *ServerResponse) Decode(reader io.Reader) error { - var err error - for err == nil { - var p []byte - _, p, err = pktline.ReadLine(reader) - if err != nil { - break - } - - err = r.decodeLine(p) - } - - if errors.Is(err, io.EOF) { - return nil - } - - return err -} - -func (r *ServerResponse) decodeLine(line []byte) error { - if len(line) == 0 { - return fmt.Errorf("unexpected flush") - } - - if len(line) >= 3 { - if bytes.Equal(line[0:3], ack) { - return r.decodeACKLine(line) - } - - if bytes.Equal(line[0:3], nak) { - return io.EOF - } - } - - return fmt.Errorf("unexpected content %q", string(line)) -} - -func (r *ServerResponse) decodeACKLine(line []byte) (err error) { - parts := bytes.Split(line, []byte(" ")) - if len(line) < ackLineLen || len(parts) < 2 { - return fmt.Errorf("malformed ACK %q", line) - } - - var ack ACK - // TODO: Dynamic hash size and sha256 support - ack.Hash = plumbing.NewHash(string(bytes.TrimSuffix(parts[1], []byte("\n")))) - err = io.EOF - - if len(parts) > 2 { - err = nil - switch status := strings.TrimSpace(string(parts[2])); status { - case "continue": - ack.Status = ACKContinue - case "common": - ack.Status = ACKCommon - case "ready": - ack.Status = ACKReady - } - } - - r.ACKs = append(r.ACKs, ack) - return -} - -// Encode encodes the ServerResponse into a writer. -func (r *ServerResponse) Encode(w io.Writer) error { - return encodeServerResponse(w, r.ACKs) -} - -// encodeServerResponse encodes the ServerResponse into a writer. -func encodeServerResponse(w io.Writer, acks []ACK) error { - if len(acks) == 0 { - _, err := pktline.WriteString(w, string(nak)+"\n") - return err - } - - var multiAck bool - for _, a := range acks { - var err error - if a.Status > 0 { - _, err = pktline.Writef(w, "%s %s %s\n", ack, a.Hash, a.Status) - if !multiAck { - multiAck = true - } - } else { - _, err = pktline.Writef(w, "%s %s\n", ack, acks[0].Hash) - } - if err != nil { - return err - } - - if !multiAck { - break - } - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq.go deleted file mode 100644 index 2953915e..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq.go +++ /dev/null @@ -1,81 +0,0 @@ -package packp - -import ( - "fmt" - "strconv" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" -) - -// UploadRequest values represent the information transmitted on a -// upload-request message. Values from this type are not zero-value -// safe, use the New function instead. -type UploadRequest struct { - Capabilities *capability.List - Wants []plumbing.Hash - Shallows []plumbing.Hash - Depth Depth - Filter Filter -} - -// Depth values stores the desired depth of the requested packfile: see -// DepthCommit, DepthSince and DepthReference. -type Depth interface { - fmt.Stringer - IsZero() bool -} - -// DepthCommits values stores the maximum number of requested commits in -// the packfile. Zero means infinite. A negative value will have -// undefined consequences. -type DepthCommits int - -func (d DepthCommits) isDepth() {} - -func (d DepthCommits) IsZero() bool { - return d == 0 -} - -func (d DepthCommits) String() string { - return strconv.Itoa(int(d)) -} - -// DepthSince values requests only commits newer than the specified time. -type DepthSince time.Time - -func (d DepthSince) isDepth() {} - -func (d DepthSince) IsZero() bool { - return time.Time(d).IsZero() -} - -func (d DepthSince) String() string { - return time.Time(d).Format(time.RFC3339) -} - -// DepthReference requests only commits not to found in the specified reference. -type DepthReference string - -func (d DepthReference) isDepth() {} - -func (d DepthReference) IsZero() bool { - return string(d) == "" -} - -func (d DepthReference) String() string { - return string(d) -} - -// NewUploadRequest returns a pointer to a new UploadRequest value, ready to be -// used. It has no capabilities, wants or shallows and an infinite depth. Please -// note that to encode an upload-request it has to have at least one wanted hash. -func NewUploadRequest() *UploadRequest { - return &UploadRequest{ - Capabilities: capability.NewList(), - Wants: []plumbing.Hash{}, - Shallows: []plumbing.Hash{}, - Depth: DepthCommits(0), - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_decode.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_decode.go deleted file mode 100644 index c99da0b5..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_decode.go +++ /dev/null @@ -1,257 +0,0 @@ -package packp - -import ( - "bytes" - "fmt" - "io" - "strconv" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// Decode reads the next upload-request form its input and -// stores it in the UploadRequest. -func (req *UploadRequest) Decode(r io.Reader) error { - d := newUlReqDecoder(r) - return d.Decode(req) -} - -type ulReqDecoder struct { - r io.Reader // a pkt-line scanner from the input stream - line []byte // current pkt-line contents, use parser.nextLine() to make it advance - nLine int // current pkt-line number for debugging, begins at 1 - err error // sticky error, use the parser.error() method to fill this out - data *UploadRequest // parsed data is stored here -} - -func newUlReqDecoder(r io.Reader) *ulReqDecoder { - return &ulReqDecoder{ - r: r, - } -} - -func (d *ulReqDecoder) Decode(v *UploadRequest) error { - d.data = v - - for state := d.decodeFirstWant; state != nil; { - state = state() - } - - return d.err -} - -// fills out the parser sticky error -func (d *ulReqDecoder) error(format string, a ...interface{}) { - msg := fmt.Sprintf( - "pkt-line %d: %s", d.nLine, - fmt.Sprintf(format, a...), - ) - - d.err = NewErrUnexpectedData(msg, d.line) -} - -// Reads a new pkt-line from the scanner, makes its payload available as -// p.line and increments p.nLine. A successful invocation returns true, -// otherwise, false is returned and the sticky error is filled out -// accordingly. Trims eols at the end of the payloads. -func (d *ulReqDecoder) nextLine() bool { - d.nLine++ - - _, p, err := pktline.ReadLine(d.r) - if err == io.EOF { - d.error("EOF") - return false - } - if err != nil { - d.err = err - return false - } - - d.line = p - d.line = bytes.TrimSuffix(d.line, eol) - - return true -} - -// Expected format: want [ capabilities] -func (d *ulReqDecoder) decodeFirstWant() stateFn { - if ok := d.nextLine(); !ok { - return nil - } - - if !bytes.HasPrefix(d.line, want) { - d.error("missing 'want ' prefix") - return nil - } - d.line = bytes.TrimPrefix(d.line, want) - - hash, ok := d.readHash() - if !ok { - return nil - } - d.data.Wants = append(d.data.Wants, hash) - - return d.decodeCaps -} - -func (d *ulReqDecoder) readHash() (plumbing.Hash, bool) { - if len(d.line) < hashSize { - d.err = fmt.Errorf("malformed hash: %v", d.line) - return plumbing.ZeroHash, false - } - - h, ok := plumbing.FromHex(string(d.line[:hashSize])) - if !ok { - d.error("invalid hash text: %s", d.line[:hashSize]) - return plumbing.ZeroHash, false - } - d.line = d.line[hashSize:] - - return h, true -} - -// Expected format: sp cap1 sp cap2 sp cap3... -func (d *ulReqDecoder) decodeCaps() stateFn { - d.line = bytes.TrimPrefix(d.line, sp) - if err := d.data.Capabilities.Decode(d.line); err != nil { - d.error("invalid capabilities: %s", err) - } - - return d.decodeOtherWants -} - -// Expected format: want -func (d *ulReqDecoder) decodeOtherWants() stateFn { - if ok := d.nextLine(); !ok { - return nil - } - - if bytes.HasPrefix(d.line, shallow) { - return d.decodeShallow - } - - if bytes.HasPrefix(d.line, deepen) { - return d.decodeDeepen - } - - if len(d.line) == 0 { - return nil - } - - if !bytes.HasPrefix(d.line, want) { - d.error("unexpected payload while expecting a want: %q", d.line) - return nil - } - d.line = bytes.TrimPrefix(d.line, want) - - hash, ok := d.readHash() - if !ok { - return nil - } - d.data.Wants = append(d.data.Wants, hash) - - return d.decodeOtherWants -} - -// Expected format: shallow -func (d *ulReqDecoder) decodeShallow() stateFn { - if bytes.HasPrefix(d.line, deepen) { - return d.decodeDeepen - } - - if len(d.line) == 0 { - return nil - } - - if !bytes.HasPrefix(d.line, shallow) { - d.error("unexpected payload while expecting a shallow: %q", d.line) - return nil - } - d.line = bytes.TrimPrefix(d.line, shallow) - - hash, ok := d.readHash() - if !ok { - return nil - } - d.data.Shallows = append(d.data.Shallows, hash) - - if ok := d.nextLine(); !ok { - return nil - } - - return d.decodeShallow -} - -// Expected format: deepen / deepen-since
    / deepen-not -func (d *ulReqDecoder) decodeDeepen() stateFn { - if bytes.HasPrefix(d.line, deepenCommits) { - return d.decodeDeepenCommits - } - - if bytes.HasPrefix(d.line, deepenSince) { - return d.decodeDeepenSince - } - - if bytes.HasPrefix(d.line, deepenReference) { - return d.decodeDeepenReference - } - - if len(d.line) == 0 { - return nil - } - - d.error("unexpected deepen specification: %q", d.line) - return nil -} - -func (d *ulReqDecoder) decodeDeepenCommits() stateFn { - d.line = bytes.TrimPrefix(d.line, deepenCommits) - - var n int - if n, d.err = strconv.Atoi(string(d.line)); d.err != nil { - return nil - } - if n < 0 { - d.err = fmt.Errorf("negative depth") - return nil - } - d.data.Depth = DepthCommits(n) - - return d.decodeFlush -} - -func (d *ulReqDecoder) decodeDeepenSince() stateFn { - d.line = bytes.TrimPrefix(d.line, deepenSince) - - var secs int64 - secs, d.err = strconv.ParseInt(string(d.line), 10, 64) - if d.err != nil { - return nil - } - t := time.Unix(secs, 0).UTC() - d.data.Depth = DepthSince(t) - - return d.decodeFlush -} - -func (d *ulReqDecoder) decodeDeepenReference() stateFn { - d.line = bytes.TrimPrefix(d.line, deepenReference) - - d.data.Depth = DepthReference(string(d.line)) - - return d.decodeFlush -} - -func (d *ulReqDecoder) decodeFlush() stateFn { - if ok := d.nextLine(); !ok { - return nil - } - - if len(d.line) != 0 { - d.err = fmt.Errorf("unexpected payload while expecting a flush-pkt: %q", d.line) - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_encode.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_encode.go deleted file mode 100644 index 2ff4e0f1..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/ulreq_encode.go +++ /dev/null @@ -1,154 +0,0 @@ -package packp - -import ( - "fmt" - "io" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// Encode writes the UlReq encoding of u to the stream. -// -// All the payloads will end with a newline character. Wants and -// shallows are sorted alphabetically. A depth of 0 means no depth -// request is sent. -func (req *UploadRequest) Encode(w io.Writer) error { - e := newUlReqEncoder(w) - return e.Encode(req) -} - -type ulReqEncoder struct { - w io.Writer // where to write the encoded data - data *UploadRequest // the data to encode - err error // sticky error -} - -func newUlReqEncoder(w io.Writer) *ulReqEncoder { - return &ulReqEncoder{ - w: w, - } -} - -func (e *ulReqEncoder) Encode(v *UploadRequest) error { - e.data = v - - if len(v.Wants) == 0 { - return fmt.Errorf("empty wants provided") - } - - plumbing.HashesSort(e.data.Wants) - for state := e.encodeFirstWant; state != nil; { - state = state() - } - - return e.err -} - -func (e *ulReqEncoder) encodeFirstWant() stateFn { - var err error - if e.data.Capabilities.IsEmpty() { - _, err = pktline.Writef(e.w, "want %s\n", e.data.Wants[0]) - } else { - _, err = pktline.Writef(e.w, "want %s %s\n", - e.data.Wants[0], - e.data.Capabilities.String(), - ) - } - - if err != nil { - e.err = fmt.Errorf("encoding first want line: %s", err) - return nil - } - - return e.encodeAdditionalWants -} - -func (e *ulReqEncoder) encodeAdditionalWants() stateFn { - last := e.data.Wants[0] - for _, w := range e.data.Wants[1:] { - if last.Compare(w.Bytes()) == 0 { - continue - } - - if _, err := pktline.Writef(e.w, "want %s\n", w); err != nil { - e.err = fmt.Errorf("encoding want %q: %s", w, err) - return nil - } - - last = w - } - - return e.encodeShallows -} - -func (e *ulReqEncoder) encodeShallows() stateFn { - plumbing.HashesSort(e.data.Shallows) - - var last plumbing.Hash - for _, s := range e.data.Shallows { - if last.Compare(s.Bytes()) == 0 { - continue - } - - if _, err := pktline.Writef(e.w, "shallow %s\n", s); err != nil { - e.err = fmt.Errorf("encoding shallow %q: %s", s, err) - return nil - } - - last = s - } - - return e.encodeDepth -} - -func (e *ulReqEncoder) encodeDepth() stateFn { - switch depth := e.data.Depth.(type) { - case DepthCommits: - if depth != 0 { - commits := int(depth) - if _, err := pktline.Writef(e.w, "deepen %d\n", commits); err != nil { - e.err = fmt.Errorf("encoding depth %d: %s", depth, err) - return nil - } - } - case DepthSince: - when := time.Time(depth).UTC() - if _, err := pktline.Writef(e.w, "deepen-since %d\n", when.Unix()); err != nil { - e.err = fmt.Errorf("encoding depth %s: %s", when, err) - return nil - } - case DepthReference: - reference := string(depth) - if _, err := pktline.Writef(e.w, "deepen-not %s\n", reference); err != nil { - e.err = fmt.Errorf("encoding depth %s: %s", reference, err) - return nil - } - default: - e.err = fmt.Errorf("unsupported depth type") - return nil - } - - return e.encodeFilter -} - -func (e *ulReqEncoder) encodeFilter() stateFn { - if filter := e.data.Filter; filter != "" { - if _, err := pktline.Writef(e.w, "filter %s\n", filter); err != nil { - e.err = fmt.Errorf("encoding filter %s: %s", filter, err) - return nil - } - } - - return e.encodeFlush -} - -func (e *ulReqEncoder) encodeFlush() stateFn { - if err := pktline.WriteFlush(e.w); err != nil { - e.err = fmt.Errorf("encoding flush-pkt: %s", err) - return nil - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq.go deleted file mode 100644 index e52f2748..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq.go +++ /dev/null @@ -1,83 +0,0 @@ -package packp - -import ( - "errors" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" -) - -var ( - ErrEmptyCommands = errors.New("commands cannot be empty") - ErrMalformedCommand = errors.New("malformed command") -) - -// UpdateRequests values represent reference upload requests. -// Values from this type are not zero-value safe, use the New function instead. -type UpdateRequests struct { - Capabilities *capability.List - Commands []*Command - Shallow *plumbing.Hash - // TODO: Support push-cert -} - -// NewUpdateRequests returns a new UpdateRequests. -func NewUpdateRequests() *UpdateRequests { - // TODO: Add support for push-cert - return &UpdateRequests{ - Capabilities: capability.NewList(), - } -} - -func (req *UpdateRequests) validate() error { - if len(req.Commands) == 0 { - return ErrEmptyCommands - } - - for _, c := range req.Commands { - if err := c.validate(); err != nil { - return err - } - } - - return nil -} - -type Action string - -const ( - Create Action = "create" - Update Action = "update" - Delete Action = "delete" - Invalid Action = "invalid" -) - -type Command struct { - Name plumbing.ReferenceName - Old plumbing.Hash - New plumbing.Hash -} - -func (c *Command) Action() Action { - if c.Old == plumbing.ZeroHash && c.New == plumbing.ZeroHash { - return Invalid - } - - if c.Old == plumbing.ZeroHash { - return Create - } - - if c.New == plumbing.ZeroHash { - return Delete - } - - return Update -} - -func (c *Command) validate() error { - if c.Action() == Invalid { - return ErrMalformedCommand - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_decode.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_decode.go deleted file mode 100644 index 60adf951..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_decode.go +++ /dev/null @@ -1,252 +0,0 @@ -package packp - -import ( - "bytes" - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -var ( - shallowLineLength = len(shallow) + hashSize - minCommandLength = hashSize*2 + 2 + 1 - minCommandAndCapsLength = minCommandLength + 1 -) - -var ( - ErrEmpty = errors.New("empty update-request message") - errNoCommands = errors.New("unexpected EOF before any command") - errMissingCapabilitiesDelimiter = errors.New("capabilities delimiter not found") - errNoFlush = errors.New("unexpected EOF before flush line") -) - -func errMalformedRequest(reason string) error { - return fmt.Errorf("malformed request: %s", reason) -} - -func errInvalidHashSize(got int) error { - return fmt.Errorf("invalid hash size: expected %d, got %d", - hashSize, got) -} - -func errInvalidHash(hash string) error { - return fmt.Errorf("invalid hash: %s", hash) -} - -func errInvalidShallowLineLength(got int) error { - return errMalformedRequest(fmt.Sprintf( - "invalid shallow line length: expected %d, got %d", - shallowLineLength, got)) -} - -func errInvalidCommandCapabilitiesLineLength(got int) error { - return errMalformedRequest(fmt.Sprintf( - "invalid command and capabilities line length: expected at least %d, got %d", - minCommandAndCapsLength, got)) -} - -func errInvalidCommandLineLength(got int) error { - return errMalformedRequest(fmt.Sprintf( - "invalid command line length: expected at least %d, got %d", - minCommandLength, got)) -} - -func errInvalidShallowObjId(err error) error { - return errMalformedRequest( - fmt.Sprintf("invalid shallow object id: %s", err.Error())) -} - -func errInvalidOldObjId(err error) error { - return errMalformedRequest( - fmt.Sprintf("invalid old object id: %s", err.Error())) -} - -func errInvalidNewObjId(err error) error { - return errMalformedRequest( - fmt.Sprintf("invalid new object id: %s", err.Error())) -} - -func errMalformedCommand(err error) error { - return errMalformedRequest(fmt.Sprintf( - "malformed command: %s", err.Error())) -} - -// Decode reads the next update-request message form the reader and wr -func (req *UpdateRequests) Decode(r io.Reader) error { - var rc io.ReadCloser - var ok bool - rc, ok = r.(io.ReadCloser) - if !ok { - rc = io.NopCloser(r) - } - - d := &updReqDecoder{r: rc, pr: r} - return d.Decode(req) -} - -type updReqDecoder struct { - r io.ReadCloser - pr io.Reader - req *UpdateRequests - - payload []byte - length int // length of the pktline payload -} - -func (d *updReqDecoder) Decode(req *UpdateRequests) error { - d.req = req - funcs := []func() error{ - d.scanLine, - d.decodeShallow, - d.decodeCommands, - d.decodeFlush, - req.validate, - } - - for _, f := range funcs { - if err := f(); err != nil { - return err - } - } - - return nil -} - -func (d *updReqDecoder) readLine(e error) error { - l, p, err := pktline.ReadLine(d.pr) - if errors.Is(err, io.EOF) { - return e - } - if err != nil { - return err - } - - d.payload = p - d.length = l - - return nil -} - -func (d *updReqDecoder) scanLine() error { - return d.readLine(ErrEmpty) -} - -func (d *updReqDecoder) decodeShallow() error { - b := d.payload - - if !bytes.HasPrefix(b, shallowNoSp) { - return nil - } - - if len(b) != shallowLineLength { - return errInvalidShallowLineLength(len(b)) - } - - h, err := parseHash(string(b[len(shallow):])) - if err != nil { - return errInvalidShallowObjId(err) - } - - if err := d.readLine(errNoCommands); err != nil { - return err - } - - d.req.Shallow = &h - - return nil -} - -func (d *updReqDecoder) decodeCommands() error { - // Process the first line which contains both command and capabilities - payload := d.payload - - // The first line must contain capabilities separated by a null byte - sep := bytes.IndexByte(payload, 0) - if sep == -1 { - return errMissingCapabilitiesDelimiter - } - - if len(payload) < minCommandAndCapsLength { - return errInvalidCommandCapabilitiesLineLength(len(payload)) - } - - // Extract and decode capabilities (everything after the null byte) - if err := d.req.Capabilities.Decode(payload[sep+1:]); err != nil { - return err - } - - // Extract the command (everything before the null byte) - payload = payload[:sep] - - // Read and process commands - for { - // Parse and add the command - cmd, err := parseCommand(payload) - if err != nil { - return err - } - d.req.Commands = append(d.req.Commands, cmd) - - // Read the next line - if err := d.readLine(errNoFlush); err != nil { - return err - } - payload = d.payload - - // Stop reading once we reach the flush line - if d.length == pktline.Flush { - return nil - } - } -} - -func (d *updReqDecoder) decodeFlush() error { - // We should always have a flush line at the end of the request. - if len(d.payload) != 0 || d.length != pktline.Flush { - return errMalformedRequest("unexpected data after flush") - } - - return nil -} - -func parseCommand(b []byte) (*Command, error) { - if len(b) < minCommandLength { - return nil, errInvalidCommandLineLength(len(b)) - } - - var ( - os, ns string - n plumbing.ReferenceName - ) - if _, err := fmt.Sscanf(string(b), "%s %s %s", &os, &ns, &n); err != nil { - return nil, errMalformedCommand(err) - } - - oh, err := parseHash(os) - if err != nil { - return nil, errInvalidOldObjId(err) - } - - nh, err := parseHash(ns) - if err != nil { - return nil, errInvalidNewObjId(err) - } - - return &Command{Old: oh, New: nh, Name: n}, nil -} - -func parseHash(s string) (plumbing.Hash, error) { - if len(s) != hashSize { - return plumbing.ZeroHash, errInvalidHashSize(len(s)) - } - - h, ok := plumbing.FromHex(s) - if !ok { - return plumbing.ZeroHash, errInvalidHash(s) - } - - return h, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_encode.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_encode.go deleted file mode 100644 index 507c97c0..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/updreq_encode.go +++ /dev/null @@ -1,62 +0,0 @@ -package packp - -import ( - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" -) - -// Encode writes the ReferenceUpdateRequest encoding to the stream. -func (req *UpdateRequests) Encode(w io.Writer) error { - if err := req.validate(); err != nil { - return err - } - - if err := req.encodeShallow(w, req.Shallow); err != nil { - return err - } - - if err := req.encodeCommands(w, req.Commands, req.Capabilities); err != nil { - return err - } - - return nil -} - -func (req *UpdateRequests) encodeShallow(w io.Writer, - h *plumbing.Hash, -) error { - if h == nil { - return nil - } - - objId := []byte(h.String()) - _, err := pktline.Writef(w, "%s%s", shallow, objId) - return err -} - -func (req *UpdateRequests) encodeCommands(w io.Writer, - cmds []*Command, cap *capability.List, -) error { - if _, err := pktline.Writef(w, "%s\x00%s", - formatCommand(cmds[0]), cap.String()); err != nil { - return err - } - - for _, cmd := range cmds[1:] { - if _, err := pktline.Writef(w, formatCommand(cmd)); err != nil { - return err - } - } - - return pktline.WriteFlush(w) -} - -func formatCommand(cmd *Command) string { - o := cmd.Old.String() - n := cmd.New.String() - return fmt.Sprintf("%s %s %s", o, n, cmd.Name) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/uphav.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/uphav.go deleted file mode 100644 index 43e37988..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/packp/uphav.go +++ /dev/null @@ -1,83 +0,0 @@ -package packp - -import ( - "bytes" - "fmt" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" -) - -// UploadHaves is a message to signal the references that a client has in a -// upload-pack. Done is true when the client has sent a "done" message. -// Otherwise, it means that the client has more haves to send and this request -// was completed with a flush. -type UploadHaves struct { - Haves []plumbing.Hash - Done bool -} - -// Encode encodes the UploadHaves into the Writer. -func (u *UploadHaves) Encode(w io.Writer) error { - plumbing.HashesSort(u.Haves) - - var last plumbing.Hash - for _, have := range u.Haves { - if last.Compare(have.Bytes()) == 0 { - continue - } - - if _, err := pktline.Writef(w, "have %s\n", have); err != nil { - return fmt.Errorf("sending haves for %q: %w", have, err) - } - - last = have - } - - if u.Done { - if _, err := pktline.Writeln(w, "done"); err != nil { - return fmt.Errorf("sending done: %w", err) - } - } else { - if err := pktline.WriteFlush(w); err != nil { - return fmt.Errorf("sending flush-pkt: %w", err) - } - } - return nil -} - -// Decode decodes the UploadHaves from the Reader. -func (u *UploadHaves) Decode(r io.Reader) error { - u.Haves = make([]plumbing.Hash, 0) - - for { - l, line, err := pktline.ReadLine(r) - if err != nil { - if err == io.EOF { - break - } - - return fmt.Errorf("decoding haves: %w", err) - } - - if l == pktline.Flush { - break - } - - if bytes.HasPrefix(line, []byte("done")) { - u.Done = true - break - } - - if !bytes.HasPrefix(line, []byte("have ")) { - return fmt.Errorf("invalid have line: %q", line) - } - - have := plumbing.NewHash(strings.TrimSpace(string(line[5:]))) - u.Haves = append(u.Haves, have) - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/version.go b/vendor/github.com/go-git/go-git/v6/plumbing/protocol/version.go deleted file mode 100644 index 48245a60..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/protocol/version.go +++ /dev/null @@ -1,52 +0,0 @@ -package protocol - -import ( - "errors" - "fmt" -) - -var ErrUnknownProtocol = errors.New("unknown Git Wire protocol") - -// Version sets the preferred version for the Git wire protocol. -type Version int - -const ( - // V0 represents the original Wire protocol. - V0 Version = iota - // V1 represents the version V1 of the Wire protocol. - V1 - // V2 represents the version V2 of the Wire protocol. - V2 - - Undefined Version = -1 -) - -// String converts a Version into string. -// The Unknown version is converted to empty string. -func (v Version) String() string { - switch v { - case V0: - return "0" - case V1: - return "1" - case V2: - return "2" - } - - return "" -} - -// Parse parses a string and returns the matching protocol version. -// Unrecognised strings will return a ErrUnknownProtocol. -func Parse(v string) (Version, error) { - switch v { - case "0": - return V0, nil - case "1": - return V1, nil - case "2": - return V2, nil - } - - return Undefined, fmt.Errorf("cannot parse %q: %w", v, ErrUnknownProtocol) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/reference.go b/vendor/github.com/go-git/go-git/v6/plumbing/reference.go deleted file mode 100644 index 4daa3416..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/reference.go +++ /dev/null @@ -1,315 +0,0 @@ -package plumbing - -import ( - "errors" - "fmt" - "regexp" - "strings" -) - -const ( - refPrefix = "refs/" - refHeadPrefix = refPrefix + "heads/" - refTagPrefix = refPrefix + "tags/" - refRemotePrefix = refPrefix + "remotes/" - refNotePrefix = refPrefix + "notes/" - symrefPrefix = "ref: " -) - -// RefRevParseRules are a set of rules to parse references into short names, or expand into a full reference. -// These are the same rules as used by git in shorten_unambiguous_ref and expand_ref. -// See: https://github.com/git/git/blob/e0aaa1b6532cfce93d87af9bc813fb2e7a7ce9d7/refs.c#L417 -var RefRevParseRules = []string{ - "%s", - "refs/%s", - "refs/tags/%s", - "refs/heads/%s", - "refs/remotes/%s", - "refs/remotes/%s/HEAD", -} - -var ( - ErrReferenceNotFound = errors.New("reference not found") - - // ErrInvalidReferenceName is returned when a reference name is invalid. - ErrInvalidReferenceName = errors.New("invalid reference name") -) - -// ReferenceType reference type's -type ReferenceType int8 - -const ( - InvalidReference ReferenceType = 0 - HashReference ReferenceType = 1 - SymbolicReference ReferenceType = 2 -) - -func (r ReferenceType) String() string { - switch r { - case InvalidReference: - return "invalid-reference" - case HashReference: - return "hash-reference" - case SymbolicReference: - return "symbolic-reference" - } - - return "" -} - -// ReferenceName reference name's -type ReferenceName string - -// NewBranchReferenceName returns a reference name describing a branch based on -// his short name. -func NewBranchReferenceName(name string) ReferenceName { - return ReferenceName(refHeadPrefix + name) -} - -// NewNoteReferenceName returns a reference name describing a note based on his -// short name. -func NewNoteReferenceName(name string) ReferenceName { - return ReferenceName(refNotePrefix + name) -} - -// NewRemoteReferenceName returns a reference name describing a remote branch -// based on his short name and the remote name. -func NewRemoteReferenceName(remote, name string) ReferenceName { - return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, name)) -} - -// NewRemoteHEADReferenceName returns a reference name describing a the HEAD -// branch of a remote. -func NewRemoteHEADReferenceName(remote string) ReferenceName { - return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, HEAD)) -} - -// NewTagReferenceName returns a reference name describing a tag based on short -// his name. -func NewTagReferenceName(name string) ReferenceName { - return ReferenceName(refTagPrefix + name) -} - -// IsBranch check if a reference is a branch -func (r ReferenceName) IsBranch() bool { - return strings.HasPrefix(string(r), refHeadPrefix) -} - -// IsNote check if a reference is a note -func (r ReferenceName) IsNote() bool { - return strings.HasPrefix(string(r), refNotePrefix) -} - -// IsRemote check if a reference is a remote -func (r ReferenceName) IsRemote() bool { - return strings.HasPrefix(string(r), refRemotePrefix) -} - -// IsTag check if a reference is a tag -func (r ReferenceName) IsTag() bool { - return strings.HasPrefix(string(r), refTagPrefix) -} - -func (r ReferenceName) String() string { - return string(r) -} - -// Short returns the short name of a ReferenceName -func (r ReferenceName) Short() string { - s := string(r) - res := s - for _, format := range RefRevParseRules[1:] { - _, err := fmt.Sscanf(s, format, &res) - if err == nil { - continue - } - } - - return res -} - -var ( - ctrlSeqs = regexp.MustCompile(`[\000-\037\177]`) -) - -// Validate validates a reference name. -// This follows the git-check-ref-format rules. -// See https://git-scm.com/docs/git-check-ref-format -// -// It is important to note that this function does not check if the reference -// exists in the repository. -// It only checks if the reference name is valid. -// This functions does not support the --refspec-pattern, --normalize, and -// --allow-onelevel options. -// -// Git imposes the following rules on how references are named: -// -// 1. They can include slash / for hierarchical (directory) grouping, but no -// slash-separated component can begin with a dot . or end with the -// sequence .lock. -// 2. They must contain at least one /. This enforces the presence of a -// category like heads/, tags/ etc. but the actual names are not -// restricted. If the --allow-onelevel option is used, this rule is -// waived. -// 3. They cannot have two consecutive dots .. anywhere. -// 4. They cannot have ASCII control characters (i.e. bytes whose values are -// lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : -// anywhere. -// 5. They cannot have question-mark ?, asterisk *, or open bracket [ -// anywhere. See the --refspec-pattern option below for an exception to this -// rule. -// 6. They cannot begin or end with a slash / or contain multiple consecutive -// slashes (see the --normalize option below for an exception to this rule). -// 7. They cannot end with a dot .. -// 8. They cannot contain a sequence @{. -// 9. They cannot be the single character @. -// 10. They cannot contain a \. -func (r ReferenceName) Validate() error { - s := string(r) - if len(s) == 0 { - return ErrInvalidReferenceName - } - - // HEAD is a special case - if r == HEAD { - return nil - } - - // rule 7 - if strings.HasSuffix(s, ".") { - return ErrInvalidReferenceName - } - - // rule 2 - parts := strings.Split(s, "/") - if len(parts) < 2 { - return ErrInvalidReferenceName - } - - isBranch := r.IsBranch() - isTag := r.IsTag() - for i, part := range parts { - // rule 6 - if len(part) == 0 { - return ErrInvalidReferenceName - } - - if strings.HasPrefix(part, ".") || // rule 1 - strings.Contains(part, "..") || // rule 3 - ctrlSeqs.MatchString(part) || // rule 4 - strings.ContainsAny(part, "~^:?*[ \t\n") || // rule 4 & 5 - strings.Contains(part, "@{") || // rule 8 - part == "@" || // rule 9 - strings.Contains(part, "\\") || // rule 10 - strings.HasSuffix(part, ".lock") { // rule 1 - return ErrInvalidReferenceName - } - - if (isBranch || isTag) && strings.HasPrefix(part, "-") && (i == 2) { // branches & tags can't start with - - return ErrInvalidReferenceName - } - } - - return nil -} - -const ( - HEAD ReferenceName = "HEAD" - Master ReferenceName = "refs/heads/master" - Main ReferenceName = "refs/heads/main" -) - -// Reference is a representation of git reference -type Reference struct { - t ReferenceType - n ReferenceName - h Hash - target ReferenceName -} - -// NewReferenceFromStrings creates a reference from name and target as string, -// the resulting reference can be a SymbolicReference or a HashReference base -// on the target provided -func NewReferenceFromStrings(name, target string) *Reference { - n := ReferenceName(name) - - if strings.HasPrefix(target, symrefPrefix) { - target := ReferenceName(target[len(symrefPrefix):]) - return NewSymbolicReference(n, target) - } - - return NewHashReference(n, NewHash(target)) -} - -// NewSymbolicReference creates a new SymbolicReference reference -func NewSymbolicReference(n, target ReferenceName) *Reference { - return &Reference{ - t: SymbolicReference, - n: n, - target: target, - } -} - -// NewHashReference creates a new HashReference reference -func NewHashReference(n ReferenceName, h Hash) *Reference { - return &Reference{ - t: HashReference, - n: n, - h: h, - } -} - -// Type returns the type of a reference -func (r *Reference) Type() ReferenceType { - return r.t -} - -// Name returns the name of a reference -func (r *Reference) Name() ReferenceName { - return r.n -} - -// Hash returns the hash of a hash reference -func (r *Reference) Hash() Hash { - return r.h -} - -// Target returns the target of a symbolic reference -func (r *Reference) Target() ReferenceName { - return r.target -} - -// Strings dump a reference as a [2]string -func (r *Reference) Strings() [2]string { - var o [2]string - o[0] = r.Name().String() - - switch r.Type() { - case HashReference: - o[1] = r.Hash().String() - case SymbolicReference: - o[1] = symrefPrefix + r.Target().String() - } - - return o -} - -func (r *Reference) String() string { - ref := "" - switch r.Type() { - case HashReference: - ref = r.Hash().String() - case SymbolicReference: - ref = symrefPrefix + r.Target().String() - default: - return "" - } - - name := r.Name().String() - var v strings.Builder - v.Grow(len(ref) + len(name) + 1) - v.WriteString(ref) - v.WriteString(" ") - v.WriteString(name) - return v.String() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/revision.go b/vendor/github.com/go-git/go-git/v6/plumbing/revision.go deleted file mode 100644 index 5f053b20..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/revision.go +++ /dev/null @@ -1,11 +0,0 @@ -package plumbing - -// Revision represents a git revision -// to get more details about git revisions -// please check git manual page : -// https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html -type Revision string - -func (r Revision) String() string { - return string(r) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/revlist/revlist.go b/vendor/github.com/go-git/go-git/v6/plumbing/revlist/revlist.go deleted file mode 100644 index 26e9cd69..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/revlist/revlist.go +++ /dev/null @@ -1,254 +0,0 @@ -// Package revlist provides support to access the ancestors of commits, in a -// similar way as the git-rev-list command. -package revlist - -import ( - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -// Objects applies a complementary set. It gets all the hashes from all -// the reachable objects from the given objects. Ignore param are object hashes -// that we want to ignore on the result. All that objects must be accessible -// from the object storer. -func Objects( - s storer.EncodedObjectStorer, - objs, - ignore []plumbing.Hash, -) ([]plumbing.Hash, error) { - return ObjectsWithStorageForIgnores(s, s, objs, ignore) -} - -// ObjectsWithStorageForIgnores is the same as Objects, but a -// secondary storage layer can be provided, to be used to finding the -// full set of objects to be ignored while finding the reachable -// objects. This is useful when the main `s` storage layer is slow -// and/or remote, while the ignore list is available somewhere local. -func ObjectsWithStorageForIgnores( - s, ignoreStore storer.EncodedObjectStorer, - objs, - ignore []plumbing.Hash, -) ([]plumbing.Hash, error) { - ignore, err := objects(ignoreStore, ignore, nil, true) - if err != nil { - return nil, err - } - - return objects(s, objs, ignore, false) -} - -func objects( - s storer.EncodedObjectStorer, - objects, - ignore []plumbing.Hash, - allowMissingObjects bool, -) ([]plumbing.Hash, error) { - seen := hashListToSet(ignore) - result := make(map[plumbing.Hash]bool) - visited := make(map[plumbing.Hash]bool) - - walkerFunc := func(h plumbing.Hash) { - if !seen[h] { - result[h] = true - seen[h] = true - } - } - - for _, h := range objects { - if err := processObject(s, h, seen, visited, ignore, walkerFunc); err != nil { - if allowMissingObjects && errors.Is(err, plumbing.ErrObjectNotFound) { - continue - } - - return nil, err - } - } - - return hashSetToList(result), nil -} - -// processObject obtains the object using the hash an process it depending of its type -func processObject( - s storer.EncodedObjectStorer, - h plumbing.Hash, - seen map[plumbing.Hash]bool, - visited map[plumbing.Hash]bool, - ignore []plumbing.Hash, - walkerFunc func(h plumbing.Hash), -) error { - if seen[h] { - return nil - } - - o, err := s.EncodedObject(plumbing.AnyObject, h) - if err != nil { - return fmt.Errorf("getting object: %w", err) - } - - do, err := object.DecodeObject(s, o) - if err != nil { - return fmt.Errorf("decoding object: %w", err) - } - - switch do := do.(type) { - case *object.Commit: - return reachableObjects(do, seen, visited, ignore, walkerFunc) - case *object.Tree: - return iterateCommitTrees(seen, do, walkerFunc) - case *object.Tag: - walkerFunc(do.Hash) - return processObject(s, do.Target, seen, visited, ignore, walkerFunc) - case *object.Blob: - walkerFunc(do.Hash) - default: - return fmt.Errorf("object type not valid: %s. "+ - "Object reference: %s", o.Type(), o.Hash()) - } - - return nil -} - -// reachableObjects returns, using the callback function, all the reachable -// objects from the specified commit. To avoid to iterate over seen commits, -// if a commit hash is into the 'seen' set, we will not iterate all his trees -// and blobs objects. -func reachableObjects( - commit *object.Commit, - seen map[plumbing.Hash]bool, - visited map[plumbing.Hash]bool, - ignore []plumbing.Hash, - cb func(h plumbing.Hash), -) error { - i := object.NewCommitPreorderIter(commit, seen, ignore) - pending := make(map[plumbing.Hash]bool) - addPendingParents(pending, visited, commit) - for { - commit, err := i.Next() - if err == io.EOF { - break - } - - if err != nil { - return err - } - - if pending[commit.Hash] { - delete(pending, commit.Hash) - } - - addPendingParents(pending, visited, commit) - - if visited[commit.Hash] && len(pending) == 0 { - break - } - - if seen[commit.Hash] { - continue - } - - cb(commit.Hash) - - tree, err := commit.Tree() - if err != nil { - return err - } - - if err := iterateCommitTrees(seen, tree, cb); err != nil { - return err - } - } - - return nil -} - -func addPendingParents(pending, visited map[plumbing.Hash]bool, commit *object.Commit) { - for _, p := range commit.ParentHashes { - if !visited[p] { - pending[p] = true - } - } -} - -// iterateCommitTrees iterate all reachable trees from the given commit -func iterateCommitTrees( - seen map[plumbing.Hash]bool, - tree *object.Tree, - cb func(h plumbing.Hash), -) error { - if seen[tree.Hash] { - return nil - } - - cb(tree.Hash) - - treeWalker := object.NewTreeWalker(tree, true, seen) - - for { - _, e, err := treeWalker.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - if e.Mode == filemode.Submodule { - continue - } - - if seen[e.Hash] { - continue - } - - cb(e.Hash) - } - - return nil -} - -func hashSetToList(hashes map[plumbing.Hash]bool) []plumbing.Hash { - var result []plumbing.Hash - for key := range hashes { - result = append(result, key) - } - - return result -} - -func hashListToSet(hashes []plumbing.Hash) map[plumbing.Hash]bool { - result := make(map[plumbing.Hash]bool) - for _, h := range hashes { - result[h] = true - } - - return result -} - -// ObjectsWithRef find all hashes linked to objs -// return a map of hashes containing an array of hash objs -func ObjectsWithRef( - s storer.EncodedObjectStorer, - objs, - ignore []plumbing.Hash, -) (map[plumbing.Hash][]plumbing.Hash, error) { - all := map[plumbing.Hash][]plumbing.Hash{} - for _, obj := range objs { - walkerFunc := func(h plumbing.Hash) { - if hashes, ok := all[h]; ok { - all[h] = append(hashes, obj) - } else { - all[h] = []plumbing.Hash{obj} - } - } - if err := processObject(s, obj, map[plumbing.Hash]bool{}, map[plumbing.Hash]bool{}, ignore, walkerFunc); err != nil { - return nil, err - } - } - return all, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/storer/doc.go b/vendor/github.com/go-git/go-git/v6/plumbing/storer/doc.go deleted file mode 100644 index 4d4f179c..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/storer/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package storer defines the interfaces to store objects, references, etc. -package storer diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/storer/index.go b/vendor/github.com/go-git/go-git/v6/plumbing/storer/index.go deleted file mode 100644 index 64d4beb4..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/storer/index.go +++ /dev/null @@ -1,9 +0,0 @@ -package storer - -import "github.com/go-git/go-git/v6/plumbing/format/index" - -// IndexStorer generic storage of index.Index -type IndexStorer interface { - SetIndex(*index.Index) error - Index() (*index.Index, error) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/storer/object.go b/vendor/github.com/go-git/go-git/v6/plumbing/storer/object.go deleted file mode 100644 index e148097f..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/storer/object.go +++ /dev/null @@ -1,292 +0,0 @@ -package storer - -import ( - "errors" - "io" - "time" - - "github.com/go-git/go-git/v6/plumbing" -) - -var ( - //ErrStop is used to stop a ForEach function in an Iter - ErrStop = errors.New("stop iter") -) - -// EncodedObjectStorer generic storage of objects -type EncodedObjectStorer interface { - // RawObjectWriter returns a io.WriterCloser to write the object without the - // need of providing a plumbing.EncodedObject. - RawObjectWriter(typ plumbing.ObjectType, sz int64) (w io.WriteCloser, err error) - // NewEncodedObject returns a new plumbing.EncodedObject, the real type - // of the object can be a custom implementation or the default one, - // plumbing.MemoryObject. - NewEncodedObject() plumbing.EncodedObject - // SetEncodedObject saves an object into the storage, the object should - // be created with the NewEncodedObject, method, and file if the type is - // not supported. - SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error) - // EncodedObject gets an object by hash with the given - // plumbing.ObjectType. Implementors should return - // (nil, plumbing.ErrObjectNotFound) if an object doesn't exist with - // both the given hash and object type. - // - // Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject, - // TreeObject and AnyObject. If plumbing.AnyObject is given, the object must - // be looked up regardless of its type. - EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error) - // IterObjects returns a custom EncodedObjectStorer over all the object - // on the storage. - // - // Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject, - IterEncodedObjects(plumbing.ObjectType) (EncodedObjectIter, error) - // HasEncodedObject returns ErrObjNotFound if the object doesn't - // exist. If the object does exist, it returns nil. - HasEncodedObject(plumbing.Hash) error - // EncodedObjectSize returns the plaintext size of the encoded object. - EncodedObjectSize(plumbing.Hash) (int64, error) - AddAlternate(remote string) error -} - -// DeltaObjectStorer is an EncodedObjectStorer that can return delta -// objects. -type DeltaObjectStorer interface { - // DeltaObject is the same as EncodedObject but without resolving deltas. - // Deltas will be returned as plumbing.DeltaObject instances. - DeltaObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error) -} - -// Transactioner is a optional method for ObjectStorer, it enables transactional read and write -// operations. -type Transactioner interface { - // Begin starts a transaction. - Begin() Transaction -} - -// LooseObjectStorer is an optional interface for managing "loose" -// objects, i.e. those not in packfiles. -type LooseObjectStorer interface { - // ForEachObjectHash iterates over all the (loose) object hashes - // in the repository without necessarily having to read those objects. - // Objects only inside pack files may be omitted. - // If ErrStop is sent the iteration is stop but no error is returned. - ForEachObjectHash(func(plumbing.Hash) error) error - // LooseObjectTime looks up the (m)time associated with the - // loose object (that is not in a pack file). Some - // implementations (e.g. without loose objects) - // always return an error. - LooseObjectTime(plumbing.Hash) (time.Time, error) - // DeleteLooseObject deletes a loose object if it exists. - DeleteLooseObject(plumbing.Hash) error -} - -// PackedObjectStorer is an optional interface for managing objects in -// packfiles. -type PackedObjectStorer interface { - // ObjectPacks returns hashes of object packs if the underlying - // implementation has pack files. - ObjectPacks() ([]plumbing.Hash, error) - // DeleteOldObjectPackAndIndex deletes an object pack and the corresponding index file if they exist. - // Deletion is only performed if the pack is older than the supplied time (or the time is zero). - DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) error -} - -// PackfileWriter is an optional method for ObjectStorer, it enables directly writing -// a packfile to storage. -type PackfileWriter interface { - // PackfileWriter returns a writer for writing a packfile to the storage - // - // If the Storer not implements PackfileWriter the objects should be written - // using the Set method. - PackfileWriter() (io.WriteCloser, error) -} - -// EncodedObjectIter is a generic closable interface for iterating over objects. -type EncodedObjectIter interface { - Next() (plumbing.EncodedObject, error) - ForEach(func(plumbing.EncodedObject) error) error - Close() -} - -// Transaction is an in-progress storage transaction. A transaction must end -// with a call to Commit or Rollback. -type Transaction interface { - SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error) - EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error) - Commit() error - Rollback() error -} - -// EncodedObjectLookupIter implements EncodedObjectIter. It iterates over a -// series of object hashes and yields their associated objects by retrieving -// each one from object storage. The retrievals are lazy and only occur when the -// iterator moves forward with a call to Next(). -// -// The EncodedObjectLookupIter must be closed with a call to Close() when it is -// no longer needed. -type EncodedObjectLookupIter struct { - storage EncodedObjectStorer - series []plumbing.Hash - t plumbing.ObjectType - pos int -} - -// NewEncodedObjectLookupIter returns an object iterator given an object storage -// and a slice of object hashes. -func NewEncodedObjectLookupIter( - storage EncodedObjectStorer, t plumbing.ObjectType, series []plumbing.Hash) *EncodedObjectLookupIter { - return &EncodedObjectLookupIter{ - storage: storage, - series: series, - t: t, - } -} - -// Next returns the next object from the iterator. If the iterator has reached -// the end it will return io.EOF as an error. If the object can't be found in -// the object storage, it will return plumbing.ErrObjectNotFound as an error. -// If the object is retrieved successfully error will be nil. -func (iter *EncodedObjectLookupIter) Next() (plumbing.EncodedObject, error) { - if iter.pos >= len(iter.series) { - return nil, io.EOF - } - - hash := iter.series[iter.pos] - obj, err := iter.storage.EncodedObject(iter.t, hash) - if err == nil { - iter.pos++ - } - - return obj, err -} - -// ForEach call the cb function for each object contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *EncodedObjectLookupIter) ForEach(cb func(plumbing.EncodedObject) error) error { - return ForEachIterator(iter, cb) -} - -// Close releases any resources used by the iterator. -func (iter *EncodedObjectLookupIter) Close() { - iter.pos = len(iter.series) -} - -// EncodedObjectSliceIter implements EncodedObjectIter. It iterates over a -// series of objects stored in a slice and yields each one in turn when Next() -// is called. -// -// The EncodedObjectSliceIter must be closed with a call to Close() when it is -// no longer needed. -type EncodedObjectSliceIter struct { - series []plumbing.EncodedObject -} - -// NewEncodedObjectSliceIter returns an object iterator for the given slice of -// objects. -func NewEncodedObjectSliceIter(series []plumbing.EncodedObject) *EncodedObjectSliceIter { - return &EncodedObjectSliceIter{ - series: series, - } -} - -// Next returns the next object from the iterator. If the iterator has reached -// the end it will return io.EOF as an error. If the object is retrieved -// successfully error will be nil. -func (iter *EncodedObjectSliceIter) Next() (plumbing.EncodedObject, error) { - if len(iter.series) == 0 { - return nil, io.EOF - } - - obj := iter.series[0] - iter.series = iter.series[1:] - - return obj, nil -} - -// ForEach call the cb function for each object contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *EncodedObjectSliceIter) ForEach(cb func(plumbing.EncodedObject) error) error { - return ForEachIterator(iter, cb) -} - -// Close releases any resources used by the iterator. -func (iter *EncodedObjectSliceIter) Close() { - iter.series = []plumbing.EncodedObject{} -} - -// MultiEncodedObjectIter implements EncodedObjectIter. It iterates over several -// EncodedObjectIter, -// -// The MultiObjectIter must be closed with a call to Close() when it is no -// longer needed. -type MultiEncodedObjectIter struct { - iters []EncodedObjectIter -} - -// NewMultiEncodedObjectIter returns an object iterator for the given slice of -// EncodedObjectIters. -func NewMultiEncodedObjectIter(iters []EncodedObjectIter) EncodedObjectIter { - return &MultiEncodedObjectIter{iters: iters} -} - -// Next returns the next object from the iterator, if one iterator reach io.EOF -// is removed and the next one is used. -func (iter *MultiEncodedObjectIter) Next() (plumbing.EncodedObject, error) { - if len(iter.iters) == 0 { - return nil, io.EOF - } - - obj, err := iter.iters[0].Next() - if err == io.EOF { - iter.iters[0].Close() - iter.iters = iter.iters[1:] - return iter.Next() - } - - return obj, err -} - -// ForEach call the cb function for each object contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *MultiEncodedObjectIter) ForEach(cb func(plumbing.EncodedObject) error) error { - return ForEachIterator(iter, cb) -} - -// Close releases any resources used by the iterator. -func (iter *MultiEncodedObjectIter) Close() { - for _, i := range iter.iters { - i.Close() - } -} - -type bareIterator interface { - Next() (plumbing.EncodedObject, error) - Close() -} - -// ForEachIterator is a helper function to build iterators without need to -// rewrite the same ForEach function each time. -func ForEachIterator(iter bareIterator, cb func(plumbing.EncodedObject) error) error { - defer iter.Close() - for { - obj, err := iter.Next() - if err != nil { - if err == io.EOF { - return nil - } - - return err - } - - if err := cb(obj); err != nil { - if err == ErrStop { - return nil - } - - return err - } - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/storer/reference.go b/vendor/github.com/go-git/go-git/v6/plumbing/storer/reference.go deleted file mode 100644 index fa973347..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/storer/reference.go +++ /dev/null @@ -1,243 +0,0 @@ -package storer - -import ( - "errors" - "io" - - "github.com/go-git/go-git/v6/plumbing" -) - -const MaxResolveRecursion = 1024 - -// ErrMaxResolveRecursion is returned by ResolveReference is MaxResolveRecursion -// is exceeded -var ErrMaxResolveRecursion = errors.New("max. recursion level reached") - -// ReferenceStorer is a generic storage of references. -type ReferenceStorer interface { - SetReference(*plumbing.Reference) error - // CheckAndSetReference sets the reference `new`, but if `old` is - // not `nil`, it first checks that the current stored value for - // `old.Name()` matches the given reference value in `old`. If - // not, it returns an error and doesn't update `new`. - CheckAndSetReference(new, old *plumbing.Reference) error - Reference(plumbing.ReferenceName) (*plumbing.Reference, error) - IterReferences() (ReferenceIter, error) - RemoveReference(plumbing.ReferenceName) error - CountLooseRefs() (int, error) - PackRefs() error -} - -// ReferenceIter is a generic closable interface for iterating over references. -type ReferenceIter interface { - Next() (*plumbing.Reference, error) - ForEach(func(*plumbing.Reference) error) error - Close() -} - -type referenceFilteredIter struct { - ff func(r *plumbing.Reference) bool - iter ReferenceIter -} - -// NewReferenceFilteredIter returns a reference iterator for the given reference -// Iterator. This iterator will iterate only references that accomplish the -// provided function. -func NewReferenceFilteredIter( - ff func(r *plumbing.Reference) bool, iter ReferenceIter) ReferenceIter { - return &referenceFilteredIter{ff, iter} -} - -// Next returns the next reference from the iterator. If the iterator has reached -// the end it will return io.EOF as an error. -func (iter *referenceFilteredIter) Next() (*plumbing.Reference, error) { - for { - r, err := iter.iter.Next() - if err != nil { - return nil, err - } - - if iter.ff(r) { - return r, nil - } - - continue - } -} - -// ForEach call the cb function for each reference contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stopped but no error is returned. The iterator is closed. -func (iter *referenceFilteredIter) ForEach(cb func(*plumbing.Reference) error) error { - defer iter.Close() - for { - r, err := iter.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - if err := cb(r); err != nil { - if err == ErrStop { - break - } - - return err - } - } - - return nil -} - -// Close releases any resources used by the iterator. -func (iter *referenceFilteredIter) Close() { - iter.iter.Close() -} - -// ReferenceSliceIter implements ReferenceIter. It iterates over a series of -// references stored in a slice and yields each one in turn when Next() is -// called. -// -// The ReferenceSliceIter must be closed with a call to Close() when it is no -// longer needed. -type ReferenceSliceIter struct { - series []*plumbing.Reference - pos int -} - -// NewReferenceSliceIter returns a reference iterator for the given slice of -// objects. -func NewReferenceSliceIter(series []*plumbing.Reference) ReferenceIter { - return &ReferenceSliceIter{ - series: series, - } -} - -// Next returns the next reference from the iterator. If the iterator has -// reached the end it will return io.EOF as an error. -func (iter *ReferenceSliceIter) Next() (*plumbing.Reference, error) { - if iter.pos >= len(iter.series) { - return nil, io.EOF - } - - obj := iter.series[iter.pos] - iter.pos++ - return obj, nil -} - -// ForEach call the cb function for each reference contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *ReferenceSliceIter) ForEach(cb func(*plumbing.Reference) error) error { - return forEachReferenceIter(iter, cb) -} - -type bareReferenceIterator interface { - Next() (*plumbing.Reference, error) - Close() -} - -func forEachReferenceIter(iter bareReferenceIterator, cb func(*plumbing.Reference) error) error { - defer iter.Close() - for { - obj, err := iter.Next() - if err != nil { - if err == io.EOF { - return nil - } - - return err - } - - if err := cb(obj); err != nil { - if err == ErrStop { - return nil - } - - return err - } - } -} - -// Close releases any resources used by the iterator. -func (iter *ReferenceSliceIter) Close() { - iter.pos = len(iter.series) -} - -// MultiReferenceIter implements ReferenceIter. It iterates over several -// ReferenceIter, -// -// The MultiReferenceIter must be closed with a call to Close() when it is no -// longer needed. -type MultiReferenceIter struct { - iters []ReferenceIter -} - -// NewMultiReferenceIter returns an reference iterator for the given slice of -// EncodedObjectIters. -func NewMultiReferenceIter(iters []ReferenceIter) ReferenceIter { - return &MultiReferenceIter{iters: iters} -} - -// Next returns the next reference from the iterator, if one iterator reach -// io.EOF is removed and the next one is used. -func (iter *MultiReferenceIter) Next() (*plumbing.Reference, error) { - if len(iter.iters) == 0 { - return nil, io.EOF - } - - obj, err := iter.iters[0].Next() - if err == io.EOF { - iter.iters[0].Close() - iter.iters = iter.iters[1:] - return iter.Next() - } - - return obj, err -} - -// ForEach call the cb function for each reference contained on this iter until -// an error happens or the end of the iter is reached. If ErrStop is sent -// the iteration is stop but no error is returned. The iterator is closed. -func (iter *MultiReferenceIter) ForEach(cb func(*plumbing.Reference) error) error { - return forEachReferenceIter(iter, cb) -} - -// Close releases any resources used by the iterator. -func (iter *MultiReferenceIter) Close() { - for _, i := range iter.iters { - i.Close() - } -} - -// ResolveReference resolves a SymbolicReference to a HashReference. -func ResolveReference(s ReferenceStorer, n plumbing.ReferenceName) (*plumbing.Reference, error) { - r, err := s.Reference(n) - if err != nil { - return nil, err - } - if r == nil { - return nil, plumbing.ErrReferenceNotFound - } - return resolveReference(s, r, 0) -} - -func resolveReference(s ReferenceStorer, r *plumbing.Reference, recursion int) (*plumbing.Reference, error) { - if r.Type() != plumbing.SymbolicReference { - return r, nil - } - - if recursion > MaxResolveRecursion { - return nil, ErrMaxResolveRecursion - } - - t, err := s.Reference(r.Target()) - if err != nil { - return nil, err - } - - recursion++ - return resolveReference(s, t, recursion) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/storer/shallow.go b/vendor/github.com/go-git/go-git/v6/plumbing/storer/shallow.go deleted file mode 100644 index 59f4865e..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/storer/shallow.go +++ /dev/null @@ -1,10 +0,0 @@ -package storer - -import "github.com/go-git/go-git/v6/plumbing" - -// ShallowStorer is a storage of references to shallow commits by hash, -// meaning that these commits have missing parents because of a shallow fetch. -type ShallowStorer interface { - SetShallow([]plumbing.Hash) error - Shallow() ([]plumbing.Hash, error) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/storer/storer.go b/vendor/github.com/go-git/go-git/v6/plumbing/storer/storer.go deleted file mode 100644 index cd95c793..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/storer/storer.go +++ /dev/null @@ -1,23 +0,0 @@ -package storer - -import "github.com/go-git/go-billy/v6" - -// Storer is a basic storer for encoded objects and references. -type Storer interface { - EncodedObjectStorer - ReferenceStorer -} - -// Initializer should be implemented by storers that require to perform any -// operation when creating a new repository (i.e. git init). -type Initializer interface { - // Init performs initialization of the storer and returns the error, if - // any. - Init() error -} - -// FilesystemStorer is a storer that can be used to store objects and references -// in a filesystem. It is used by the filesystem storage. -type FilesystemStorer interface { - Filesystem() billy.Filesystem -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/tag.go b/vendor/github.com/go-git/go-git/v6/plumbing/tag.go deleted file mode 100644 index cde8f4d9..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/tag.go +++ /dev/null @@ -1,17 +0,0 @@ -package plumbing - -// TagMode defines how the tags will be fetched from the remote repository. -type TagMode int - -const ( - InvalidTagMode TagMode = iota - // TagFollowing any tag that points into the histories being fetched is also - // fetched. TagFollowing requires a server with `include-tag` capability - // in order to fetch the annotated tags objects. - TagFollowing - // AllTags fetch all tags from the remote (i.e., fetch remote tags - // refs/tags/* into local tags with the same name) - AllTags - // NoTags fetch no tags from the remote at all - NoTags -) diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/common.go deleted file mode 100644 index c3ff3a7b..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/common.go +++ /dev/null @@ -1,215 +0,0 @@ -// Package transport implements the git pack protocol with a pluggable -// This is a low-level package to implement new transports. Use a concrete -// implementation instead (e.g. http, file, ssh). -// -// A simple example of usage can be found in the file package. -package transport - -import ( - "context" - "errors" - "io" - "regexp" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/protocol" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband" - "github.com/go-git/go-git/v6/storage" -) - -const ( - readErrorSecondsTimeout = 10 -) - -var ( - // ErrUnsupportedVersion is returned when the protocol version is not - // supported. - ErrUnsupportedVersion = errors.New("unsupported protocol version") - // ErrUnsupportedService is returned when the service is not supported. - ErrUnsupportedService = errors.New("unsupported service") - // ErrInvalidResponse is returned when the response is invalid. - ErrInvalidResponse = errors.New("invalid response") - // ErrTimeoutExceeded is returned when the timeout is exceeded. - ErrTimeoutExceeded = errors.New("timeout exceeded") - // ErrPackedObjectsNotSupported is returned when the server does not support - // packed objects. - ErrPackedObjectsNotSupported = errors.New("packed objects not supported") - // stdErrSkipPattern is used for skipping lines from a command's stderr output. - // Any line matching this pattern will be skipped from further - // processing and not be returned to calling code. - stdErrSkipPattern = regexp.MustCompile("^remote:( =*){0,1}$") -) - -// RemoteError represents an error returned by the remote. -// TODO: embed error -type RemoteError struct { - Reason string -} - -// Error implements the error interface. -func (e *RemoteError) Error() string { - return e.Reason -} - -// NewRemoteError creates a new RemoteError. -func NewRemoteError(reason string) error { - return &RemoteError{Reason: reason} -} - -// Connection represents a session endpoint connection. -type Connection interface { - // Close closes the connection. - Close() error - - // Capabilities returns the list of capabilities supported by the server. - Capabilities() *capability.List - - // Version returns the Git protocol version the server supports. - Version() protocol.Version - - // StatelessRPC indicates that the connection is a half-duplex connection - // and should operate in half-duplex mode i.e. performs a single read-write - // cycle. This fits with the HTTP POST request process where session may - // read the request, write a response, and exit. - StatelessRPC() bool - - // GetRemoteRefs returns the references advertised by the remote. - // Using protocol v0 or v1, this returns the references advertised by the - // remote during the handshake. Using protocol v2, this runs the ls-refs - // command on the remote. - // This will error if the session is not already established using - // Handshake. - GetRemoteRefs(ctx context.Context) ([]*plumbing.Reference, error) - - // Fetch sends a fetch-pack request to the server. - Fetch(ctx context.Context, req *FetchRequest) error - - // Push sends a send-pack request to the server. - Push(ctx context.Context, req *PushRequest) error -} - -var _ io.Closer = Connection(nil) - -// FetchRequest contains the parameters for a fetch-pack request. -// This is used during the pack negotiation phase of the fetch operation. -// See https://git-scm.com/docs/pack-protocol#_packfile_negotiation -type FetchRequest struct { - // Progress is the progress sideband. - Progress sideband.Progress - - // Wants is the list of references to fetch. - // TODO: Build this slice in the transport package. - Wants []plumbing.Hash - - // Haves is the list of references the client already has. - // TODO: Build this slice in the transport package. - Haves []plumbing.Hash - - // Depth is the depth of the fetch. - Depth int - - // Filter holds the filters to be applied when deciding what - // objects will be added to the packfile. - Filter packp.Filter - - // IncludeTags indicates whether tags should be fetched. - IncludeTags bool -} - -// PushRequest contains the parameters for a push request. -type PushRequest struct { - // Packfile is the packfile reader. - Packfile io.ReadCloser - - // Commands is the list of push commands to be sent to the server. - // TODO: build the Commands slice in the transport package. - Commands []*packp.Command - - // Progress is the progress sideband. - Progress sideband.Progress - - // Options is a set of push-options to be sent to the server during push. - Options []string - - // Atomic indicates an atomic push. - // If the server supports atomic push, it will update the refs in one - // atomic transaction. Either all refs are updated or none. - Atomic bool -} - -// Session is a Git protocol transfer session. -// This is used by all protocols. -type Session interface { - // Handshake starts the negotiation with the remote to get version if not - // already connected. - // Params are the optional extra parameters to be sent to the server. Use - // this to send the protocol version of the client and any other extra parameters. - Handshake(ctx context.Context, service Service, params ...string) (Connection, error) -} - -// Commander creates Command instances. This is the main entry point for -// transport implementations. -type Commander interface { - // Connect creates a new Command for the given git command and - // endpoint. cmd can be git-upload-pack or git-receive-pack. An - // error should be returned if the endpoint is not supported or the - // command cannot be created (e.g. binary does not exist, connection - // cannot be established). - Command(ctx context.Context, cmd string, ep *Endpoint, auth AuthMethod, params ...string) (Command, error) -} - -// Command is used for a single command execution. -// This interface is modeled after exec.Cmd and ssh.Session in the standard -// library. -type Command interface { - // StderrPipe returns a pipe that will be connected to the command's - // standard error when the command starts. It should not be called after - // Start. - StderrPipe() (io.Reader, error) - // StdinPipe returns a pipe that will be connected to the command's - // standard input when the command starts. It should not be called after - // Start. The pipe should be closed when no more input is expected. - StdinPipe() (io.WriteCloser, error) - // StdoutPipe returns a pipe that will be connected to the command's - // standard output when the command starts. It should not be called after - // Start. - StdoutPipe() (io.Reader, error) - // Start starts the specified command. It does not wait for it to - // complete. - Start() error - // Close closes the command and releases any resources used by it. It - // will block until the command exits. - Close() error -} - -// CommandKiller expands the Command interface, enabling it for being killed. -type CommandKiller interface { - // Kill and close the session whatever the state it is. It will block until - // the command is terminated. - Kill() error -} - -type client struct { - cmdr Commander -} - -// NewPackTransport creates a new client using the given Commander. -func NewPackTransport(runner Commander) Transport { - return &client{runner} -} - -// NewSession returns a new session for an endpoint. -func (c *client) NewSession(st storage.Storer, ep *Endpoint, auth AuthMethod) (Session, error) { - return NewPackSession(st, ep, auth, c.cmdr) -} - -// SupportedProtocols returns a list of supported Git protocol versions by -// the transport client. -func (c *client) SupportedProtocols() []protocol.Version { - return []protocol.Version{ - protocol.V0, - protocol.V1, - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/fetch.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/fetch.go deleted file mode 100644 index 1083bd12..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/fetch.go +++ /dev/null @@ -1,87 +0,0 @@ -package transport - -import ( - "context" - "io" - - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// FetchPack fetches a packfile from the remote connection into the given -// storage repository and updates the shallow information. -func FetchPack( - ctx context.Context, - st storage.Storer, - conn Connection, - packf io.ReadCloser, - shallowInfo *packp.ShallowUpdate, - req *FetchRequest, -) (err error) { - packf = ioutil.NewContextReadCloser(ctx, packf) - - // Do we have sideband enabled? - var demuxer *sideband.Demuxer - var reader io.Reader = packf - caps := conn.Capabilities() - if caps.Supports(capability.Sideband64k) { - demuxer = sideband.NewDemuxer(sideband.Sideband64k, reader) - } else if caps.Supports(capability.Sideband) { - demuxer = sideband.NewDemuxer(sideband.Sideband, reader) - } - - if demuxer != nil && req.Progress != nil { - demuxer.Progress = req.Progress - reader = demuxer - } - - if err := packfile.UpdateObjectStorage(st, reader); err != nil { - return err - } - - if err := packf.Close(); err != nil { - return err - } - - // Update shallow - if shallowInfo != nil { - if err := updateShallow(st, shallowInfo); err != nil { - return err - } - } - - return nil -} - -func updateShallow(st storage.Storer, shallowInfo *packp.ShallowUpdate) error { - shallows, err := st.Shallow() - if err != nil { - return err - } - -outer: - for _, s := range shallowInfo.Shallows { - for _, oldS := range shallows { - if s == oldS { - continue outer - } - } - shallows = append(shallows, s) - } - - // unshallow commits - for _, s := range shallowInfo.Unshallows { - for i, oldS := range shallows { - if s == oldS { - shallows = append(shallows[:i], shallows[i+1:]...) - break - } - } - } - - return st.SetShallow(shallows) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/file/client.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/file/client.go deleted file mode 100644 index 3fd1a3fd..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/file/client.go +++ /dev/null @@ -1,165 +0,0 @@ -// Package file implements the file transport protocol. -package file - -import ( - "context" - "fmt" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing/transport" -) - -func init() { - transport.Register("file", DefaultTransport) -} - -// DefaultTransport is the default local client. -var DefaultTransport = NewTransport(nil) - -type runner struct { - loader transport.Loader -} - -// NewTransport returns a new file transport that users go-git built-in server -// implementation to serve repositories. -func NewTransport(loader transport.Loader) transport.Transport { - if loader == nil { - loader = transport.DefaultLoader - } - return transport.NewPackTransport(&runner{loader}) -} - -func (r *runner) Command(ctx context.Context, cmd string, ep *transport.Endpoint, auth transport.AuthMethod, params ...string) (transport.Command, error) { - switch transport.Service(cmd) { - case transport.UploadPackService, transport.ReceivePackService: - // do nothing - default: - return nil, transport.ErrUnsupportedService - } - gitProtocol := strings.Join(params, ":") - - return &command{ - ctx: ctx, - loader: r.loader, - ep: ep, - service: cmd, - errc: make(chan error, 1), - gitProtocol: gitProtocol, - }, nil -} - -type command struct { - ctx context.Context - ep *transport.Endpoint - loader transport.Loader - service string - gitProtocol string - - stdin *io.PipeReader - stdinW *io.PipeWriter - stdout *io.PipeWriter - stderr *io.PipeWriter - - childIOFiles []io.Closer - parentIOFiles []io.Closer - - closed bool - errc chan error -} - -func (c *command) Start() error { - st, err := c.loader.Load(c.ep) - if err != nil { - return err - } - - switch transport.Service(c.service) { - case transport.UploadPackService: - opts := &transport.UploadPackOptions{ - GitProtocol: c.gitProtocol, - } - go func() { - if err := transport.UploadPack( - c.ctx, - st, - io.NopCloser(c.stdin), - c.stdout, - opts, - ); err != nil { - // Write the error to the stderr pipe and close the command. - _, _ = fmt.Fprintln(c.stderr, err) - _ = c.Close() - } - }() - return nil - case transport.ReceivePackService: - opts := &transport.ReceivePackOptions{ - GitProtocol: c.gitProtocol, - } - go func() { - if err := transport.ReceivePack( - c.ctx, - st, - io.NopCloser(c.stdin), - c.stdout, - opts, - ); err != nil { - _, _ = fmt.Fprintln(c.stderr, err) - _ = c.Close() - } - }() - return nil - } - return fmt.Errorf("unsupported service: %s", c.service) -} - -func (c *command) StderrPipe() (io.Reader, error) { - pr, pw := io.Pipe() - - c.stderr = pw - c.childIOFiles = append(c.childIOFiles, pw) - c.parentIOFiles = append(c.parentIOFiles, pr) - - return pr, nil -} - -func (c *command) StdinPipe() (io.WriteCloser, error) { - pr, pw := io.Pipe() - - c.stdin = pr - c.stdinW = pw - c.childIOFiles = append(c.childIOFiles, pr) - c.parentIOFiles = append(c.parentIOFiles, pw) - - return pw, nil -} - -func (c *command) StdoutPipe() (io.Reader, error) { - pr, pw := io.Pipe() - - c.stdout = pw - c.childIOFiles = append(c.childIOFiles, pw) - c.parentIOFiles = append(c.parentIOFiles, pr) - - return pr, nil -} - -// Close waits for the command to exit. -func (c *command) Close() (err error) { - if c.closed { - return nil - } - - closeDiscriptors(c.childIOFiles) - closeDiscriptors(c.parentIOFiles) - c.closed = true - - return -} - -func closeDiscriptors(fds []io.Closer) { - for _, fd := range fds { - fd.Close() - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/git/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/git/common.go deleted file mode 100644 index 35a6a963..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/git/common.go +++ /dev/null @@ -1,112 +0,0 @@ -// Package git implements the git transport protocol. -package git - -import ( - "context" - "io" - "net" - "strconv" - - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/transport" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -func init() { - transport.Register("git", DefaultClient) -} - -// DefaultClient is the default git client. -var DefaultClient = transport.NewPackTransport(&runner{}) - -const DefaultPort = 9418 - -type runner struct{} - -// Command returns a new Command for the given cmd in the given Endpoint -func (r *runner) Command(ctx context.Context, cmd string, ep *transport.Endpoint, _ transport.AuthMethod, params ...string) (transport.Command, error) { - c := &command{command: cmd, endpoint: ep, params: params} - if err := c.connect(); err != nil { - return nil, err - } - - return c, nil -} - -type command struct { - conn net.Conn - connected bool - command string - endpoint *transport.Endpoint - params []string -} - -// Start executes the command sending the required message to the TCP connection -func (c *command) Start() error { - req := packp.GitProtoRequest{ - RequestCommand: c.command, - Pathname: c.endpoint.Path, - ExtraParams: c.params, - } - - host := c.endpoint.Host - if c.endpoint.Port != DefaultPort { - host = net.JoinHostPort(c.endpoint.Host, strconv.Itoa(c.endpoint.Port)) - } - - req.Host = host - - return req.Encode(c.conn) -} - -func (c *command) connect() error { - if c.connected { - return transport.ErrAlreadyConnected - } - - var err error - c.conn, err = net.Dial("tcp", c.getHostWithPort()) - if err != nil { - return err - } - - c.connected = true - return nil -} - -func (c *command) getHostWithPort() string { - host := c.endpoint.Host - port := c.endpoint.Port - if port <= 0 { - port = DefaultPort - } - - return net.JoinHostPort(host, strconv.Itoa(port)) -} - -// StderrPipe git protocol doesn't have any dedicated error channel -func (c *command) StderrPipe() (io.Reader, error) { - return nil, nil -} - -// StdinPipe returns the underlying connection as WriteCloser, wrapped to prevent -// call to the Close function from the connection, a command execution in git -// protocol can't be closed or killed -func (c *command) StdinPipe() (io.WriteCloser, error) { - return ioutil.WriteNopCloser(c.conn), nil -} - -// StdoutPipe returns the underlying connection as Reader -func (c *command) StdoutPipe() (io.Reader, error) { - return c.conn, nil -} - -// Close closes the TCP connection and connection. -func (c *command) Close() error { - if !c.connected { - return nil - } - - c.connected = false - return c.conn.Close() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/common.go deleted file mode 100644 index 44d58f28..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/common.go +++ /dev/null @@ -1,741 +0,0 @@ -// Package http implements the HTTP transport protocol. -package http - -import ( - "bufio" - "bytes" - "context" - "crypto/tls" - "crypto/x509" - "fmt" - "io" - "net" - "net/http" - "net/url" - "reflect" - "strconv" - "strings" - "sync" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" - "github.com/go-git/go-git/v6/plumbing/protocol" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/transport" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/trace" - "github.com/golang/groupcache/lru" -) - -func init() { - transport.Register("http", DefaultTransport) - transport.Register("https", DefaultTransport) -} - -func applyHeaders( - req *http.Request, - service string, - ep *transport.Endpoint, - auth AuthMethod, - protocol string, - useSmart bool, -) { - // Add headers - req.Header.Set("User-Agent", capability.DefaultAgent()) - req.Header.Set("Host", ep.Host) // host:port - - if useSmart { - req.Header.Set("Content-Type", fmt.Sprintf("application/x-%s-request", service)) - req.Header.Set("Accept", fmt.Sprintf("application/x-%s-result", service)) // smart protocol - } - - if protocol != "" { - req.Header.Set("Git-Protocol", protocol) - } - - // Set auth headers - if auth != nil { - auth.SetAuth(req) - } -} - -// doRequest applies the auth and headers, then performs a request to the -// server and returns the response. -func doRequest( - client *http.Client, - req *http.Request, -) (*http.Response, error) { - traceHTTP := trace.HTTP.Enabled() - if traceHTTP { - trace.HTTP.Printf("requesting %s %s %v", req.Method, req.URL.String(), req.Header) - } - - res, err := client.Do(req) - if err != nil { - return nil, err - } - - if traceHTTP { - trace.HTTP.Printf("response %s %s %s %v", res.Proto, res.Status, res.Request.URL.String(), res.Header) - } - - if res.StatusCode >= http.StatusOK && res.StatusCode < http.StatusMultipleChoices { - return res, nil - } - - return res, checkError(res) -} - -// modifyRedirect modifies the endpoint based on the redirect response. -func modifyRedirect(res *http.Response, ep *transport.Endpoint) { - if res.Request == nil { - return - } - - r := res.Request - if !strings.HasSuffix(r.URL.Path, infoRefsPath) { - return - } - - h, p, err := net.SplitHostPort(r.URL.Host) - if err != nil { - h = r.URL.Host - } - if p != "" { - port, err := strconv.Atoi(p) - if err == nil { - ep.Port = port - } - } - - ep.Host = h - ep.Protocol = r.URL.Scheme - ep.Path = r.URL.Path[:len(r.URL.Path)-len(infoRefsPath)] -} - -const infoRefsPath = "/info/refs" - -type client struct { - client *http.Client - transports *lru.Cache - mutex sync.RWMutex - useDumb bool // When true, the client will always use the dumb protocol. -} - -// TransportOptions holds user configurable options for the client. -type TransportOptions struct { - // Client is the http client that the transport will use to make requests. - // If nil, [http.DefaultTransport] will be used. - Client *http.Client - - // CacheMaxEntries is the max no. of entries that the transport objects - // cache will hold at any given point of time. It must be a positive integer. - // Calling `client.addTransport()` after the cache has reached the specified - // size, will result in the least recently used transport getting deleted - // before the provided transport is added to the cache. - CacheMaxEntries int - - // UseDumb is a flag that when set to true, the client will always use the - // dumb protocol. - UseDumb bool -} - -var ( - // defaultTransportCacheSize is the default capacity of the transport objects cache. - // Its value is 0 because transport caching is turned off by default and is an - // opt-in feature. - defaultTransportCacheSize = 0 - - // DefaultTransport is the default HTTP client, which uses a net/http client configured - // with http.DefaultTransport. - DefaultTransport = NewTransport(nil) -) - -// NewTransport creates a new HTTP transport with a custom net/http client and -// options. -// -// See `InstallProtocol` to install and override default http client. -// If the net/http client is nil or empty, it will use a net/http client configured -// with http.DefaultTransport. -// -// Note that for HTTP client cannot distinguish between private repositories and -// unexistent repositories on GitHub. So it returns `ErrAuthorizationRequired` -// for both. -func NewTransport(opts *TransportOptions) transport.Transport { - if opts == nil { - opts = &TransportOptions{ - CacheMaxEntries: defaultTransportCacheSize, - } - } - if opts.Client == nil { - opts.Client = &http.Client{ - Transport: http.DefaultTransport, - } - } - - cl := &client{ - client: opts.Client, - useDumb: opts.UseDumb, - } - if opts.CacheMaxEntries > 0 { - cl.transports = lru.New(opts.CacheMaxEntries) - } - - return cl -} - -// NewSession creates a new session for the client. -func (c *client) NewSession(st storage.Storer, ep *transport.Endpoint, auth transport.AuthMethod) (transport.Session, error) { - return newSession(st, c, ep, auth, c.useDumb) -} - -// SupportedProtocols returns the supported protocols by the client. -func (c *client) SupportedProtocols() []protocol.Version { - return []protocol.Version{ - protocol.V0, - protocol.V1, - } -} - -// HTTPSession represents a transport session that uses the HTTP protocol. -type HTTPSession struct { - st storage.Storer - auth AuthMethod - client *http.Client - ep *transport.Endpoint - refs *packp.AdvRefs - svc transport.Service // the service we're using for this session - gitProtocol string // the Git-Protocol header to send - version protocol.Version // the server's protocol version - useDumb bool // When true, the client will always use the dumb protocol - isSmart bool // This is true if the session is using the smart protocol -} - -// IsSmart returns true if the session is using the smart protocol. -func (s *HTTPSession) IsSmart() bool { - return s.isSmart && !s.useDumb -} - -var _ transport.Session = (*HTTPSession)(nil) - -func transportWithInsecureTLS(transport *http.Transport) { - if transport.TLSClientConfig == nil { - transport.TLSClientConfig = &tls.Config{} - } - transport.TLSClientConfig.InsecureSkipVerify = true -} - -func transportWithCABundle(transport *http.Transport, caBundle []byte) error { - rootCAs, err := x509.SystemCertPool() - if err != nil { - return err - } - if rootCAs == nil { - rootCAs = x509.NewCertPool() - } - rootCAs.AppendCertsFromPEM(caBundle) - if transport.TLSClientConfig == nil { - transport.TLSClientConfig = &tls.Config{} - } - transport.TLSClientConfig.RootCAs = rootCAs - return nil -} - -func transportWithProxy(transport *http.Transport, proxyURL *url.URL) { - transport.Proxy = http.ProxyURL(proxyURL) -} - -func configureTransport(transport *http.Transport, ep *transport.Endpoint) error { - if len(ep.CaBundle) > 0 { - if err := transportWithCABundle(transport, ep.CaBundle); err != nil { - return err - } - } - if ep.InsecureSkipTLS { - transportWithInsecureTLS(transport) - } - - if ep.Proxy.URL != "" { - proxyURL, err := ep.Proxy.FullURL() - if err != nil { - return err - } - transportWithProxy(transport, proxyURL) - } - return nil -} - -func newSession(st storage.Storer, c *client, ep *transport.Endpoint, auth transport.AuthMethod, useDumb bool) (*HTTPSession, error) { - var httpClient *http.Client - - // We need to configure the http transport if there are transport specific - // options present in the endpoint. - if len(ep.CaBundle) > 0 || ep.InsecureSkipTLS || ep.Proxy.URL != "" { - var transport *http.Transport - // if the client wasn't configured to have a cache for transports then just configure - // the transport and use it directly, otherwise try to use the cache. - if c.transports == nil { - tr, ok := c.client.Transport.(*http.Transport) - if !ok { - return nil, fmt.Errorf("expected underlying client transport to be of type: %s; got: %s", - reflect.TypeOf(transport), reflect.TypeOf(c.client.Transport)) - } - - transport = tr.Clone() - configureTransport(transport, ep) - } else { - transportOpts := transportOptions{ - caBundle: string(ep.CaBundle), - insecureSkipTLS: ep.InsecureSkipTLS, - } - if ep.Proxy.URL != "" { - proxyURL, err := ep.Proxy.FullURL() - if err != nil { - return nil, err - } - transportOpts.proxyURL = *proxyURL - } - var found bool - transport, found = c.fetchTransport(transportOpts) - - if !found { - transport = c.client.Transport.(*http.Transport).Clone() - configureTransport(transport, ep) - c.addTransport(transportOpts, transport) - } - } - - httpClient = &http.Client{ - Transport: transport, - CheckRedirect: c.client.CheckRedirect, - Jar: c.client.Jar, - Timeout: c.client.Timeout, - } - } else { - httpClient = c.client - } - - s := &HTTPSession{ - st: st, - auth: basicAuthFromEndpoint(ep), - client: httpClient, - ep: ep, - useDumb: useDumb, - } - if auth != nil { - a, ok := auth.(AuthMethod) - if !ok { - return nil, transport.ErrInvalidAuthMethod - } - - s.auth = a - } - - return s, nil -} - -// Handshake implements transport.PackSession. -func (s *HTTPSession) Handshake(ctx context.Context, service transport.Service, params ...string) (transport.Connection, error) { - url, err := url.JoinPath(s.ep.String(), infoRefsPath) - if err != nil { - return nil, err - } - if !s.useDumb { - url += "?service=" + service.String() - } - - s.svc = service - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return nil, err - } - - if len(params) > 0 { - s.gitProtocol = strings.Join(params, ":") - } - - applyHeaders(req, service.String(), s.ep, s.auth, s.gitProtocol, !s.useDumb) - res, err := doRequest(s.client, req) - if err != nil { - return nil, err - } - - if contentType := res.Header.Get("Content-Type"); !s.useDumb { - s.isSmart = contentType == fmt.Sprintf("application/x-%s-advertisement", service) - } - - modifyRedirect(res, s.ep) - defer ioutil.CheckClose(res.Body, &err) - - rd := bufio.NewReader(res.Body) - ar := packp.NewAdvRefs() - if s.IsSmart() { - _, prefix, err := pktline.PeekLine(rd) - if err != nil { - return nil, err - } - - // Consumes the prefix - // # service=\n - // 0000 - if bytes.HasPrefix(prefix, []byte("# service=")) { - var reply packp.SmartReply - err := reply.Decode(rd) - if err != nil { - return nil, err - } - - if reply.Service != service.String() { - return nil, fmt.Errorf("unexpected service name: %w", transport.ErrInvalidResponse) - } - } - - s.version, _ = transport.DiscoverVersion(rd) - switch s.version { - case protocol.V2: - return nil, transport.ErrUnsupportedVersion - case protocol.V1: - // Read the version line - fallthrough - case protocol.V0: - } - - if err = ar.Decode(rd); err != nil { - if err == packp.ErrEmptyAdvRefs { - err = transport.ErrEmptyRemoteRepository - } - - return nil, err - } - } else { - var infoRefs packp.InfoRefs - if err := infoRefs.Decode(rd); err != nil { - return nil, err - } - - ar.References = infoRefs.References - ar.Peeled = infoRefs.Peeled - - walker := newFetchWalker(s, ctx, nil) - head, err := walker.getHead() - if err != nil { - return nil, err - } - - var hash plumbing.Hash - switch head.Type() { - case plumbing.SymbolicReference: - for name, refHash := range ar.References { - if name == head.Target().String() { - hash = refHash - break - } - } - default: - hash = head.Hash() - } - ar.Head = &hash - } - - s.refs = ar - - return s, nil -} - -var _ transport.Connection = &HTTPSession{} - -// Capabilities implements transport.Connection. -func (s *HTTPSession) Capabilities() *capability.List { - return s.refs.Capabilities -} - -// StatelessRPC implements transport.Connection. -func (*HTTPSession) StatelessRPC() bool { - return true -} - -// Fetch implements transport.Connection. -func (s *HTTPSession) Fetch(ctx context.Context, req *transport.FetchRequest) (err error) { - if !s.IsSmart() { - return s.fetchDumb(ctx, req) - } - - rwc := newRequester(ctx, s, transport.UploadPackService) - - // XXX: packfile will be populated and accessible once rwc.Close() is - // called in NegotiatePack. - packfile := rwc.BodyCloser() - shallows, err := transport.NegotiatePack(ctx, s.st, s, packfile, rwc, req) - if err != nil { - if rwc.res != nil { - // Make sure the response body is closed. - defer packfile.Close() // nolint: errcheck - } - return err - } - - return transport.FetchPack(ctx, s.st, s, packfile, shallows, req) -} - -// GetRemoteRefs implements transport.Connection. -func (s *HTTPSession) GetRemoteRefs(ctx context.Context) ([]*plumbing.Reference, error) { - if s.refs == nil { - return nil, transport.ErrEmptyRemoteRepository - } - - // Git 2.41+ returns a zero-id plus capabilities when an empty - // repository is being cloned. This skips the existing logic within - // advrefs_decode.decodeFirstHash, which expects a flush-pkt instead. - // - // This logic aligns with plumbing/transport/common/common.go. - forPush := s.svc == transport.ReceivePackService - if s.refs.IsEmpty() && !forPush { - // Empty repositories are valid for git-receive-pack. - return nil, transport.ErrEmptyRemoteRepository - } - - return s.refs.MakeReferenceSlice() -} - -// Push implements transport.Connection. -func (s *HTTPSession) Push(ctx context.Context, req *transport.PushRequest) (err error) { - rwc := newRequester(ctx, s, transport.ReceivePackService) - return transport.SendPack(ctx, s.st, s, rwc, rwc.BodyCloser(), req) -} - -// Version implements transport.Connection. -func (s *HTTPSession) Version() protocol.Version { - return s.version -} - -// requester is a io.WriteCloser that sends an HTTP request to on close and -// reads the response into the struct. -type requester struct { - *HTTPSession - - reqBuf bytes.Buffer - ctx context.Context - req *http.Request // the last request made - res *http.Response // the last response received - - service string -} - -func newRequester(ctx context.Context, s *HTTPSession, service transport.Service) *requester { - return &requester{ - ctx: ctx, - HTTPSession: s, - service: service.String(), - } -} - -var _ io.ReadWriteCloser = &requester{} - -// BodyCloser returns the response body as an io.ReadCloser. -func (r *requester) BodyCloser() io.ReadCloser { - return ioutil.NewReadCloser(r, ioutil.CloserFunc(func() error { - if r.res == nil { - panic("http: requester.res is accessed before requester.Close") - } - return r.res.Body.Close() - })) -} - -// Read implements io.ReadWriteCloser. -func (r *requester) Read(p []byte) (n int, err error) { - if r.res == nil { - panic("http: requester.Read called before requester.Close") - } - return r.res.Body.Read(p) -} - -// Close implements io.ReadWriteCloser. -func (r *requester) Close() (err error) { - defer r.reqBuf.Reset() - - url := fmt.Sprintf("%s/%s", r.ep.String(), r.service) - r.req, err = http.NewRequestWithContext(r.ctx, http.MethodPost, url, &r.reqBuf) - if err != nil { - return err - } - - applyHeaders(r.req, r.service, r.ep, r.auth, r.gitProtocol, r.IsSmart()) - r.res, err = doRequest(r.client, r.req) - if err != nil { - return err - } - - return nil -} - -// Write implements io.ReadWriteCloser. -func (r *requester) Write(p []byte) (n int, err error) { - return r.reqBuf.Write(p) -} - -func (s *HTTPSession) ApplyAuthToRequest(req *http.Request) { - if s.auth == nil { - return - } - - s.auth.SetAuth(req) -} - -func (s *HTTPSession) ModifyEndpointIfRedirect(res *http.Response) { - if res.Request == nil { - return - } - - r := res.Request - if !strings.HasSuffix(r.URL.Path, infoRefsPath) { - return - } - - h, p, err := net.SplitHostPort(r.URL.Host) - if err != nil { - h = r.URL.Host - } - if p != "" { - port, err := strconv.Atoi(p) - if err == nil { - s.ep.Port = port - } - } - s.ep.Host = h - - s.ep.Protocol = r.URL.Scheme - s.ep.Path = r.URL.Path[:len(r.URL.Path)-len(infoRefsPath)] -} - -func (*HTTPSession) Close() error { - return nil -} - -// AuthMethod is concrete implementation of common.AuthMethod for HTTP services -type AuthMethod interface { - transport.AuthMethod - SetAuth(r *http.Request) -} - -func basicAuthFromEndpoint(ep *transport.Endpoint) *BasicAuth { - u := ep.User - if u == "" { - return nil - } - - return &BasicAuth{u, ep.Password} -} - -// BasicAuth represent a HTTP basic auth -type BasicAuth struct { - Username, Password string -} - -func (a *BasicAuth) SetAuth(r *http.Request) { - if a == nil { - return - } - - r.SetBasicAuth(a.Username, a.Password) -} - -// Name is name of the auth -func (a *BasicAuth) Name() string { - return "http-basic-auth" -} - -func (a *BasicAuth) String() string { - masked := "*******" - if a.Password == "" { - masked = "" - } - - return fmt.Sprintf("%s - %s:%s", a.Name(), a.Username, masked) -} - -// TokenAuth implements an http.AuthMethod that can be used with http transport -// to authenticate with HTTP token authentication (also known as bearer -// authentication). -// -// IMPORTANT: If you are looking to use OAuth tokens with popular servers (e.g. -// GitHub, Bitbucket, GitLab) you should use BasicAuth instead. These servers -// use basic HTTP authentication, with the OAuth token as user or password. -// Check the documentation of your git server for details. -type TokenAuth struct { - Token string -} - -func (a *TokenAuth) SetAuth(r *http.Request) { - if a == nil { - return - } - r.Header.Add("Authorization", fmt.Sprintf("Bearer %s", a.Token)) -} - -// Name is name of the auth -func (a *TokenAuth) Name() string { - return "http-token-auth" -} - -func (a *TokenAuth) String() string { - masked := "*******" - if a.Token == "" { - masked = "" - } - return fmt.Sprintf("%s - %s", a.Name(), masked) -} - -// Err is a dedicated error to return errors based on status code -type Err struct { - URL *url.URL - Status int - Reason string -} - -// checkError returns a new Err based on a http response. -func checkError(r *http.Response) error { - if r.StatusCode >= http.StatusOK && r.StatusCode < http.StatusMultipleChoices { - return nil - } - - var reason string - - // If a response message is present, add it to error - var messageBuffer bytes.Buffer - if r.Body != nil { - messageLength, _ := messageBuffer.ReadFrom(r.Body) - if messageLength > 0 { - reason = messageBuffer.String() - } - } - - switch r.StatusCode { - case http.StatusUnauthorized: - return transport.ErrAuthenticationRequired - case http.StatusForbidden: - return transport.ErrAuthorizationFailed - case http.StatusNotFound: - return transport.ErrRepositoryNotFound - } - - return plumbing.NewUnexpectedError(&Err{ - URL: r.Request.URL, - Status: r.StatusCode, - Reason: reason, - }) -} - -// StatusCode returns the status code of the response -func (e *Err) StatusCode() int { - return e.Status -} - -func (e *Err) Error() string { - format := "unexpected requesting %q status code: %d" - if e.Reason != "" { - return fmt.Sprintf(format+": %s", e.URL, e.Status, e.Reason) - } - return fmt.Sprintf(format, e.URL, e.Status) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/dumb.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/dumb.go deleted file mode 100644 index dcf3b07d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/dumb.go +++ /dev/null @@ -1,476 +0,0 @@ -package http - -import ( - "bufio" - "context" - "errors" - "fmt" - "io" - "io/fs" - "net/http" - "net/url" - "path" - "path/filepath" - "strings" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" - "github.com/go-git/go-git/v6/plumbing/format/objfile" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/transport" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -func (s *HTTPSession) fetchDumb(ctx context.Context, req *transport.FetchRequest) error { - if req.Depth != 0 { - return errors.New("dumb http protocol does not support shallow capabilities") - } - - fsi, ok := s.st.(interface { - Filesystem() billy.Filesystem - }) - if !ok { - return errors.New("dumb http protocol requires a filesystem") - } - - repoFs := fsi.Filesystem() - r := newFetchWalker(s, ctx, repoFs) - if err := r.process(); err != nil { - return err - } - - if err := r.fetch(); err != nil { - return fmt.Errorf("error fetching objects: %w", err) - } - - return nil -} - -// fetchWalker implements the Dumb protocol for fetching objects. -type fetchWalker struct { - *HTTPSession - ctx context.Context - fs billy.Filesystem - queue []plumbing.Hash - packIdx map[plumbing.Hash]string -} - -func newFetchWalker(s *HTTPSession, ctx context.Context, fs billy.Filesystem) *fetchWalker { - walker := new(fetchWalker) - walker.HTTPSession = s - walker.ctx = ctx - walker.fs = fs - walker.queue = make([]plumbing.Hash, 0) - walker.packIdx = make(map[plumbing.Hash]string) - return walker -} - -func (r *fetchWalker) getInfoPacks() ([]string, error) { - url, err := url.JoinPath(r.ep.String(), "objects", "info", "packs") - if err != nil { - return nil, err - } - req, err := http.NewRequestWithContext(r.ctx, http.MethodGet, url, nil) - if err != nil { - return nil, err - } - - applyHeaders(req, "", r.ep, r.auth, "", false) - res, err := doRequest(r.client, req) - if err != nil { - return nil, err - } - - defer res.Body.Close() - switch res.StatusCode { - case http.StatusOK: - // continue - case http.StatusNotFound: - return nil, transport.ErrRepositoryNotFound - default: - return nil, fmt.Errorf("unexpected status code: %d", res.StatusCode) - } - - var packs []string - s := bufio.NewScanner(res.Body) - for s.Scan() { - line := s.Text() - hash := strings.TrimPrefix(line, "P pack-") - hash = strings.TrimSuffix(hash, ".pack") - packs = append(packs, hash) - } - - return packs, s.Err() -} - -// downloadFile downloads a file from the server and saves it to the filesystem. -func (r *fetchWalker) downloadFile(fp string) (rErr error) { - url, err := url.JoinPath(r.ep.String(), fp) - if err != nil { - return err - } - req, err := http.NewRequestWithContext(r.ctx, http.MethodGet, url, nil) - if err != nil { - return err - } - - applyHeaders(req, "", r.ep, r.auth, "", false) - res, err := doRequest(r.client, req) - if err != nil { - return err - } - - if res.StatusCode != http.StatusOK { - return fmt.Errorf("unexpected status code: %d", res.StatusCode) - } - - copy := func(w io.Writer) error { - if _, err := ioutil.CopyBufferPool(w, res.Body); err != nil { - return err - } - - if err := res.Body.Close(); err != nil { - return err - } - - if closer, ok := w.(io.Closer); ok { - return closer.Close() - } - - return nil - } - - f, err := r.fs.TempFile(filepath.Dir(fp), filepath.Base(fp)+".temp") - if err != nil { - copy(io.Discard) - return err - } - - defer func() { - if err := f.Close(); err != nil { - rErr = err - } - }() - - if err := copy(f); err != nil { - return err - } - - // TODO: support hardlinks and "core.createobject" configuration - return r.fs.Rename(f.Name(), fp) -} - -// getHead returns the HEAD reference from the server. -func (r *fetchWalker) getHead() (ref *plumbing.Reference, err error) { - url, err := url.JoinPath(r.ep.String(), "HEAD") - if err != nil { - return nil, err - } - req, err := http.NewRequestWithContext(r.ctx, http.MethodGet, url, nil) - if err != nil { - return nil, err - } - - applyHeaders(req, "", r.ep, r.auth, "", false) - res, err := doRequest(r.client, req) - if err != nil { - return nil, err - } - - defer func() { - if res.Body == nil { - return - } - bodyErr := res.Body.Close() - if err == nil { - err = bodyErr - } - }() - switch res.StatusCode { - case http.StatusOK: - // continue - case http.StatusNotFound: - return nil, transport.ErrRepositoryNotFound - default: - return nil, fmt.Errorf("unexpected status code: %d", res.StatusCode) - } - - s := bufio.NewScanner(res.Body) - if !s.Scan() { - if err := s.Err(); err != nil { - return nil, err - } - // EOF, no data - return nil, transport.ErrRepositoryNotFound - } - - line := s.Text() - if strings.HasPrefix(line, "ref: ") { - target := strings.TrimPrefix(line, "ref: ") - return plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.ReferenceName(target)), nil - } - - return plumbing.NewHashReference(plumbing.HEAD, plumbing.NewHash(line)), nil -} - -// process calculates the objects to fetch and downloads them. -func (r *fetchWalker) process() error { - var head plumbing.Hash - if r.refs.Head == nil { - hash, err := r.getHead() - if err != nil { - return err - } - - switch hash.Type() { - case plumbing.HashReference: - head = hash.Hash() - r.refs.Head = &head - case plumbing.SymbolicReference: - for name, h := range r.refs.References { - if name == hash.Target().String() { - head = h - break - } - } - } - } else { - head = *r.refs.Head - } - - if head.IsZero() { - // TODO: better error message? - return transport.ErrRepositoryNotFound - } - - infoPacks, err := r.getInfoPacks() - if err != nil { - return err - } - - for _, hash := range infoPacks { - h := plumbing.NewHash(hash) - if h.IsZero() { - continue - } - - // XXX: we need to check if the index file exists. Currently, there is - // no way to do so using the storer interfaces except useing - // HasEncodedObject which might be an expensive operation. - packIdx := path.Join("objects", "pack", fmt.Sprintf("pack-%s.idx", hash)) - if _, err := r.fs.Stat(packIdx); errors.Is(err, fs.ErrExist) { - r.packIdx[h] = packIdx - } else { - if err := r.downloadFile(packIdx); err != nil { - return err - } - - // TODO: parse and checksum the index file - r.packIdx[h] = packIdx - } - } - - r.queue = append(r.queue, head) - for name, hash := range r.refs.References { - peeled, hasPeeled := r.refs.Peeled[name] - if r.st.HasEncodedObject(hash) != nil { - r.queue = append(r.queue, hash) - } - if hasPeeled && r.st.HasEncodedObject(peeled) != nil { - r.queue = append(r.queue, peeled) - } - } - - r.queue = append(r.queue, head) - - return nil -} - -func (r *fetchWalker) fetchObject(hash plumbing.Hash, obj plumbing.EncodedObject) (err error) { - if r.st.HasEncodedObject(hash) == nil { - return nil - } - - h := hash.String() - url, err := url.JoinPath(r.ep.String(), "objects", h[:2], h[2:]) - if err != nil { - return err - } - req, err := http.NewRequestWithContext(r.ctx, http.MethodGet, url, nil) - if err != nil { - return err - } - - applyHeaders(req, "", r.ep, r.auth, "", false) - res, err := doRequest(r.client, req) - if errors.Is(err, transport.ErrRepositoryNotFound) { - // TODO: better error handling - return io.EOF - } - if err != nil { - return err - } - - defer res.Body.Close() - switch res.StatusCode { - case http.StatusOK: - case http.StatusNotFound: - return io.EOF - default: - return fmt.Errorf("unexpected status code: %d", res.StatusCode) - } - - rd, err := objfile.NewReader(res.Body) - if err != nil { - return err - } - - ioutil.CheckClose(rd, &err) - - t, size, err := rd.Header() - if err != nil { - return err - } - - obj.SetType(t) - obj.SetSize(size) - - w, err := obj.Writer() - if err != nil { - return err - } - - ioutil.CheckClose(w, &err) - - if _, err := ioutil.CopyBufferPool(w, rd); err != nil { - return err - } - - return nil -} - -func (r *fetchWalker) fetch() error { - packs := map[string]struct{}{} - processed := map[string]struct{}{} - indicies := []*idxfile.MemoryIndex{} - -LOOP: - for len(r.queue) > 0 { - objHash := r.queue[0] - r.queue = r.queue[1:] - if _, ok := processed[objHash.String()]; ok { - continue - } - - for _, idx := range indicies { - if ok, err := idx.Contains(objHash); err == nil && ok { - continue LOOP - } - } - - obj := r.st.NewEncodedObject() - err := r.fetchObject(objHash, obj) - if errors.Is(err, io.EOF) { - // TODO: support http-alternates - for packHash, packIdxPath := range r.packIdx { - idxFile, err := r.fs.Open(packIdxPath) - if err != nil { - return fmt.Errorf("error opening index file: %w", err) - } - - idx := idxfile.NewMemoryIndex(packHash.Size()) - d := idxfile.NewDecoder(idxFile) - if err := d.Decode(idx); err != nil { - _ = idxFile.Close() - return fmt.Errorf("error decoding index file: %w", err) - } - - indicies = append(indicies, idx) - packPath := path.Join("objects", "pack", fmt.Sprintf("pack-%s.pack", packHash.String())) - if ok, err := idx.Contains(objHash); err == nil && ok { - processed[objHash.String()] = struct{}{} - if _, ok := packs[packPath]; ok { - continue LOOP - } - - if _, err := r.fs.Stat(packPath); errors.Is(err, fs.ErrExist) { - packs[packPath] = struct{}{} - continue LOOP - } - - if err := r.downloadFile(packPath); err != nil { - return fmt.Errorf("error downloading pack file: %w", err) - } - - packs[packPath] = struct{}{} - continue LOOP - } - } - } else if err != nil { - return err - } - - switch obj.Type() { - case plumbing.CommitObject: - commit, err := object.DecodeCommit(r.st, obj) - if err != nil { - return err - } - - r.queue = append(r.queue, commit.ParentHashes...) - r.queue = append(r.queue, commit.TreeHash) - case plumbing.TreeObject: - tree, err := object.DecodeTree(r.st, obj) - if err != nil { - return err - } - - r.queue = append(r.queue, tree.Hash) - for _, e := range tree.Entries { - r.queue = append(r.queue, e.Hash) - } - case plumbing.TagObject: - tag, err := object.DecodeTag(r.st, obj) - if err != nil { - return err - } - - r.queue = append(r.queue, tag.Hash) - r.queue = append(r.queue, tag.Target) - case plumbing.BlobObject: - blob, err := object.DecodeBlob(obj) - if err != nil { - return err - } - - r.queue = append(r.queue, blob.Hash) - default: - return plumbing.ErrInvalidType - } - - if _, err := r.st.SetEncodedObject(obj); err != nil { - return err - } - processed[objHash.String()] = struct{}{} - } - - for packPath := range packs { - f, err := r.fs.Open(packPath) - if err != nil { - return err - } - - if err := packfile.UpdateObjectStorage(r.st, f); err != nil { - _ = f.Close() - return err - } - - if err := f.Close(); err != nil { - return err - } - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/transport.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/transport.go deleted file mode 100644 index c8db3892..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/http/transport.go +++ /dev/null @@ -1,40 +0,0 @@ -package http - -import ( - "net/http" - "net/url" -) - -// transportOptions contains transport specific configuration. -type transportOptions struct { - insecureSkipTLS bool - // []byte is not comparable. - caBundle string - proxyURL url.URL -} - -func (c *client) addTransport(opts transportOptions, transport *http.Transport) { - c.mutex.Lock() - c.transports.Add(opts, transport) - c.mutex.Unlock() -} - -func (c *client) removeTransport(opts transportOptions) { - c.mutex.Lock() - c.transports.Remove(opts) - c.mutex.Unlock() -} - -func (c *client) fetchTransport(opts transportOptions) (*http.Transport, bool) { - c.mutex.RLock() - t, ok := c.transports.Get(opts) - c.mutex.RUnlock() - if !ok { - return nil, false - } - transport, ok := t.(*http.Transport) - if !ok { - return nil, false - } - return transport, true -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/loader.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/loader.go deleted file mode 100644 index 859a23d8..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/loader.go +++ /dev/null @@ -1,83 +0,0 @@ -package transport - -import ( - "path/filepath" - - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/storage/filesystem" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/osfs" -) - -// DefaultLoader is a filesystem loader ignoring host and resolving paths to /. -var DefaultLoader = NewFilesystemLoader(osfs.New(""), false) - -// Loader loads repository's storer.Storer based on an optional host and a path. -type Loader interface { - // Load loads a storer.Storer given a transport.Endpoint. - // Returns transport.ErrRepositoryNotFound if the repository does not - // exist. - Load(ep *Endpoint) (storage.Storer, error) -} - -// FilesystemLoader is a Loader that uses a billy.Filesystem to load -// repositories from the file system. It ignores the host and resolves paths to -// the given base filesystem. -type FilesystemLoader struct { - base billy.Filesystem - strict bool -} - -// NewFilesystemLoader creates a Loader that ignores host and resolves paths -// with a given base filesystem. -func NewFilesystemLoader(base billy.Filesystem, strict bool) Loader { - return &FilesystemLoader{base, strict} -} - -// Load looks up the endpoint's path in the base file system and returns a -// storer for it. Returns transport.ErrRepositoryNotFound if a repository does -// not exist in the given path. -func (l *FilesystemLoader) Load(ep *Endpoint) (storage.Storer, error) { - return l.load(ep.Path, false) -} - -func (l *FilesystemLoader) load(path string, tried bool) (storage.Storer, error) { - fs, err := l.base.Chroot(path) - if err != nil { - return nil, err - } - - if _, err := fs.Stat("config"); err != nil { - if !l.strict && !tried { - tried = true - if fi, err := fs.Stat(".git"); err == nil && fi.IsDir() { - path = filepath.Join(path, ".git") - } else { - path = path + ".git" - } - return l.load(path, tried) - } - return nil, ErrRepositoryNotFound - } - - return filesystem.NewStorageWithOptions(fs, cache.NewObjectLRUDefault(), filesystem.Options{}), nil -} - -// MapLoader is a Loader that uses a lookup map of storer.Storer by -// transport.Endpoint. -type MapLoader map[string]storer.Storer - -// Load returns a storer.Storer for given a transport.Endpoint by looking it up -// in the map. Returns transport.ErrRepositoryNotFound if the endpoint does not -// exist. -func (l MapLoader) Load(ep *Endpoint) (storer.Storer, error) { - s, ok := l[ep.String()] - if !ok { - return nil, ErrRepositoryNotFound - } - - return s, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/mocks.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/mocks.go deleted file mode 100644 index e1df50b7..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/mocks.go +++ /dev/null @@ -1,45 +0,0 @@ -package transport - -import ( - "bytes" - "context" - "io" - - "github.com/go-git/go-git/v6/utils/ioutil" -) - -type mockCommand struct { - stdin bytes.Buffer - stdout bytes.Buffer - stderr bytes.Buffer -} - -func (c mockCommand) StderrPipe() (io.Reader, error) { - return &c.stderr, nil -} - -func (c mockCommand) StdinPipe() (io.WriteCloser, error) { - return ioutil.WriteNopCloser(&c.stdin), nil -} - -func (c mockCommand) StdoutPipe() (io.Reader, error) { - return &c.stdout, nil -} - -func (c mockCommand) Start() error { - return nil -} - -func (c mockCommand) Close() error { - return nil -} - -type mockCommander struct { - stderr string -} - -func (c mockCommander) Command(_ context.Context, cmd string, ep *Endpoint, auth AuthMethod, _ ...string) (Command, error) { - return &mockCommand{ - stderr: *bytes.NewBufferString(c.stderr), - }, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/negotiate.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/negotiate.go deleted file mode 100644 index 87af5054..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/negotiate.go +++ /dev/null @@ -1,267 +0,0 @@ -package transport - -import ( - "context" - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/pktline" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -var ( - ErrFilterNotSupported = errors.New("server does not support filters") - ErrShallowNotSupported = errors.New("server does not support shallow clients") -) - -// NegotiatePack returns the result of the pack negotiation phase of the fetch operation. -// See https://git-scm.com/docs/pack-protocol#_packfile_negotiation -func NegotiatePack( - ctx context.Context, - st storage.Storer, - conn Connection, - reader io.Reader, - writer io.WriteCloser, - req *FetchRequest, -) (shallowInfo *packp.ShallowUpdate, err error) { - reader = ioutil.NewContextReader(ctx, reader) - writer = ioutil.NewContextWriteCloser(ctx, writer) - caps := conn.Capabilities() - - // Create upload-request - upreq := packp.NewUploadRequest() - multiAck := caps.Supports(capability.MultiACK) - multiAckDetailed := caps.Supports(capability.MultiACKDetailed) - if multiAckDetailed { - upreq.Capabilities.Set(capability.MultiACKDetailed) // nolint: errcheck - } else if multiAck { - upreq.Capabilities.Set(capability.MultiACK) // nolint: errcheck - } - - if req.Progress != nil { - if caps.Supports(capability.Sideband64k) { - upreq.Capabilities.Set(capability.Sideband64k) // nolint: errcheck - } else if caps.Supports(capability.Sideband) { - upreq.Capabilities.Set(capability.Sideband) // nolint: errcheck - } - } else if caps.Supports(capability.NoProgress) { - upreq.Capabilities.Set(capability.NoProgress) // nolint: errcheck - } - - // TODO: support thin-pack - // if caps.Supports(capability.ThinPack) { - // upreq.Capabilities.Set(capability.ThinPack) // nolint: errcheck - // } - - if caps.Supports(capability.OFSDelta) { - upreq.Capabilities.Set(capability.OFSDelta) // nolint: errcheck - } - - if caps.Supports(capability.Agent) { - upreq.Capabilities.Set(capability.Agent, capability.DefaultAgent()) // nolint: errcheck - } - - if req.IncludeTags && caps.Supports(capability.IncludeTag) { - upreq.Capabilities.Set(capability.IncludeTag) // nolint: errcheck - } - - if req.Filter != "" { - if caps.Supports(capability.Filter) { - upreq.Filter = req.Filter - if err := upreq.Capabilities.Set(capability.Filter); err != nil { - return nil, err - } - } else { - return nil, ErrFilterNotSupported - } - } - - upreq.Wants = req.Wants - - if req.Depth > 0 { - if !caps.Supports(capability.Shallow) { - return nil, ErrShallowNotSupported - } - - upreq.Depth = packp.DepthCommits(req.Depth) - upreq.Shallows, err = st.Shallow() - if err != nil { - return nil, err - } - } - - // Note: empty request means haves are a subset of wants, in that case we have - // everything we asked for. Close the connection and return nil. - if isSubset(req.Wants, req.Haves) && len(upreq.Shallows) == 0 { - if err := pktline.WriteFlush(writer); err != nil { - return nil, err - } - - // Close the writer to signal the end of the request - if err := writer.Close(); err != nil { - return nil, fmt.Errorf("closing writer: %s", err) - } - - return nil, ErrNoChange - } - - // Create upload-haves - common := map[plumbing.Hash]struct{}{} - - var inVein int - var done bool - var gotContinue bool // whether we got a continue from the server - firstRound := true - for !done { - // Pop the last 32 or depth have commits from the pending list and - // insert their parents into the pending list. - // TODO: Properly build and implement haves negotiation, and move it - // from remote.go to this package. - var uphav packp.UploadHaves - for i := 0; i < 32 && len(req.Haves) > 0; i++ { - uphav.Haves = append(uphav.Haves, req.Haves[len(req.Haves)-1]) - req.Haves = req.Haves[:len(req.Haves)-1] - inVein++ - } - - // Let the server know we're done - const maxInVein = 256 - done = len(req.Haves) == 0 || (gotContinue && inVein >= maxInVein) - uphav.Done = done - - // Note: empty request means haves are a subset of wants, in that case we have - // everything we asked for. Close the connection and return nil. - if isSubset(req.Wants, uphav.Haves) && len(upreq.Shallows) == 0 { - if err := pktline.WriteFlush(writer); err != nil { - return nil, err - } - - // Close the writer to signal the end of the request - if err := writer.Close(); err != nil { - return nil, fmt.Errorf("closing writer: %s", err) - } - - return nil, ErrNoChange - } - - // Begin the upload-pack negotiation - if firstRound || conn.StatelessRPC() { - if err := upreq.Encode(writer); err != nil { - return nil, fmt.Errorf("sending upload-request: %w", err) - } - } - - readc := make(chan error) - if !conn.StatelessRPC() { - go func() { readc <- readShallows(conn, reader, req, &shallowInfo, firstRound) }() - } - - // Encode upload-haves - if err := uphav.Encode(writer); err != nil { - return nil, fmt.Errorf("sending upload-haves: %w", err) - } - - // Close the writer to signal the end of the request - if conn.StatelessRPC() { - if err := writer.Close(); err != nil { - return nil, fmt.Errorf("closing writer: %w", err) - } - - if err := readShallows(conn, reader, req, &shallowInfo, firstRound); err != nil { - return nil, err - } - } else { - // Wait for the read channel to be closed - if err := <-readc; err != nil { - return nil, err - } - } - - go func() { - defer close(readc) - - if done || len(uphav.Haves) > 0 { - var srvrs packp.ServerResponse - if err := srvrs.Decode(reader); err != nil { - readc <- fmt.Errorf("decoding server-response: %w", err) - return - } - - for _, ack := range srvrs.ACKs { - if !gotContinue && ack.Status > 0 { - gotContinue = true - } - if ack.Status == packp.ACKCommon { - common[ack.Hash] = struct{}{} - } - } - } - - readc <- nil - }() - - // Wait for the read channel to be closed - if err := <-readc; err != nil { - return nil, err - } - - firstRound = false - } - - if !conn.StatelessRPC() { - if err := writer.Close(); err != nil { - return nil, fmt.Errorf("closing writer: %w", err) - } - } - - return shallowInfo, nil -} - -func isSubset(needle []plumbing.Hash, haystack []plumbing.Hash) bool { - for _, h := range needle { - found := false - for _, oh := range haystack { - if h == oh { - found = true - break - } - } - - if !found { - return false - } - } - - return true -} - -func readShallows( - conn Connection, - r io.Reader, - req *FetchRequest, - shallowInfo **packp.ShallowUpdate, - firstRound bool, -) error { - // Decode shallow-update - // If depth is not zero, then we expect a shallow update from the - // server. - if (firstRound || conn.StatelessRPC()) && req.Depth > 0 { - var shupd packp.ShallowUpdate - if err := shupd.Decode(r); err != nil { - return fmt.Errorf("decoding shallow-update: %w", err) - } - - // Only return the first shallow update - if shallowInfo == nil { - shallowInfo = new(*packp.ShallowUpdate) - *shallowInfo = &shupd - } - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/pack.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/pack.go deleted file mode 100644 index 0e3cbd3c..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/pack.go +++ /dev/null @@ -1,213 +0,0 @@ -package transport - -import ( - "bufio" - "bytes" - "context" - "io" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/protocol" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// NewPackSession creates a new session that implements a full-duplex Git pack protocol. -func NewPackSession( - st storage.Storer, - ep *Endpoint, - auth AuthMethod, - cmdr Commander, -) (Session, error) { - ps := &PackSession{ - ep: ep, - auth: auth, - cmdr: cmdr, - st: st, - } - return ps, nil -} - -// PackSession is a session that implements a full-duplex Git pack transport. -type PackSession struct { - cmdr Commander - ep *Endpoint - auth AuthMethod - st storage.Storer -} - -var _ Session = &PackSession{} - -// Handshake implements Session. -func (p *PackSession) Handshake(ctx context.Context, service Service, params ...string) (conn Connection, err error) { - switch service { - case UploadPackService, ReceivePackService: - // do nothing - default: - return nil, ErrUnsupportedService - } - cmd, err := p.cmdr.Command(ctx, service.String(), p.ep, p.auth, params...) - if err != nil { - return nil, err - } - - c := &packConnection{ - st: p.st, - cmd: cmd, - svc: service, - } - - // Check if the context is already done before starting the command. - if ctx.Err() != nil { - return nil, ctx.Err() - } - - stdin, err := cmd.StdinPipe() - if err != nil { - return nil, err - } - - c.w = stdin - - stdout, err := cmd.StdoutPipe() - if err != nil { - return nil, err - } - - cr := ioutil.NewContextReaderWithCloser(ctx, stdout, cmd) - c.r = bufio.NewReader(cr) - - stderr, err := cmd.StderrPipe() - if err != nil { - return nil, err - } - - // Some transports like Git doesn't support stderr, so we need to check if - // it's not nil before starting to read it. - if stderr != nil { - go ioutil.CopyBufferPool(&c.stderrBuf, stderr) // nolint: errcheck - } - - // Check if stderr is not empty before returning. - defer func() { checkError(c.stderr(), &err) }() - - if err := cmd.Start(); err != nil { - _ = cmd.Close() - return nil, err - } - - c.version, err = DiscoverVersion(c.r) - if err != nil { - return nil, err - } - - switch c.version { - case protocol.V2: - return nil, ErrUnsupportedVersion - case protocol.V1: - // Read the version line - fallthrough - case protocol.V0: - } - - ar := packp.NewAdvRefs() - if err := ar.Decode(c.r); err != nil { - return nil, err - } - - c.refs = ar - c.caps = ar.Capabilities - - return c, nil -} - -// packConnection is a convenience type that implements io.ReadWriteCloser. -type packConnection struct { - st storage.Storer - cmd Command - svc Service - w io.WriteCloser // stdin - r *bufio.Reader // stdout - stderrBuf bytes.Buffer - - version protocol.Version - caps *capability.List - refs *packp.AdvRefs -} - -var _ Connection = &packConnection{} - -// stderr returns stderr of the command if it's not empty. This will always -// return a RemoteError. -func (p *packConnection) stderr() error { - s := strings.TrimSpace(p.stderrBuf.String()) - if s == "" { - return nil - } - - return NewRemoteError(s) -} - -// Close implements Connection. -func (p *packConnection) Close() error { - return p.cmd.Close() -} - -// Capabilities implements Connection. -func (p *packConnection) Capabilities() *capability.List { - return p.caps -} - -// GetRemoteRefs implements Connection. -func (p *packConnection) GetRemoteRefs(ctx context.Context) ([]*plumbing.Reference, error) { - if p.refs == nil { - // TODO: return appropriate error - return nil, ErrEmptyRemoteRepository - } - - // Some servers like jGit, announce capabilities instead of returning an - // packp message with a flush. This verifies that we received a empty - // adv-refs, even if it contains capabilities. - forPush := p.svc == ReceivePackService - if !forPush && p.refs.IsEmpty() { - return nil, ErrEmptyRemoteRepository - } - - return p.refs.MakeReferenceSlice() -} - -// Version implements Connection. -func (p *packConnection) Version() protocol.Version { - return p.version -} - -// StatelessRPC implements Connection. -func (*packConnection) StatelessRPC() bool { - return false -} - -// Fetch implements Connection. -func (p *packConnection) Fetch(ctx context.Context, req *FetchRequest) (err error) { - shallows, err := NegotiatePack(ctx, p.st, p, p.r, p.w, req) - if err != nil { - return err - } - - return FetchPack(ctx, p.st, p, io.NopCloser(p.r), shallows, req) -} - -// Push implements Connection. -func (p *packConnection) Push(ctx context.Context, req *PushRequest) (err error) { - return SendPack(ctx, p.st, p, p.w, io.NopCloser(p.r), req) -} - -// checkError checks if the error is not nil updates the pointer with the -// error. -func checkError(err error, perr *error) { - if err != nil { - *perr = err - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/push.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/push.go deleted file mode 100644 index c5189426..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/push.go +++ /dev/null @@ -1,158 +0,0 @@ -package transport - -import ( - "context" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// buildUpdateRequests constructs a new update-requests object for the given -// connection and push request. -func buildUpdateRequests(caps *capability.List, req *PushRequest) *packp.UpdateRequests { - upreq := packp.NewUpdateRequests() - - // The atomic, report-status, report-status-v2, delete-refs, quiet, and - // push-cert capabilities are sent and recognized by the receive-pack (push - // to server) process. - // - // The ofs-delta and side-band-64k capabilities are sent and recognized by - // both upload-pack and receive-pack protocols. The agent and session-id - // capabilities may optionally be sent in both protocols. - // - // All other capabilities are only recognized by the upload-pack (fetch - // from server) process. - // - // In addition to the ones listed above, receive-pack special capabilities - // include object-format and push-options. - // - // However, upstream Git does *not* send all of these capabilities by - // client side. See - // https://github.com/git/git/blob/485f5f863615e670fd97ae40af744e14072cfe18/send-pack.c#L589 - // for more details. - // - // See https://git-scm.com/docs/gitprotocol-capabilities for more details. - if caps.Supports(capability.ReportStatus) { - upreq.Capabilities.Set(capability.ReportStatus) //nolint:errcheck - } - if req.Progress != nil { - if caps.Supports(capability.Sideband64k) { - upreq.Capabilities.Set(capability.Sideband64k) //nolint:errcheck - } else if caps.Supports(capability.Sideband) { - upreq.Capabilities.Set(capability.Sideband) //nolint:errcheck - } - if caps.Supports(capability.Quiet) { - upreq.Capabilities.Set(capability.Quiet) //nolint:errcheck - } - } - if req.Atomic && caps.Supports(capability.Atomic) { - upreq.Capabilities.Set(capability.Atomic) //nolint:errcheck - } - if len(req.Options) > 0 && caps.Supports(capability.PushOptions) { - upreq.Capabilities.Set(capability.PushOptions) //nolint:errcheck - } - if caps.Supports(capability.Agent) { - upreq.Capabilities.Set(capability.Agent, capability.DefaultAgent()) //nolint:errcheck - } - - upreq.Commands = req.Commands - - return upreq -} - -// SendPack is a function that sends a packfile to a remote server. -func SendPack( - ctx context.Context, - st storage.Storer, - conn Connection, - writer io.WriteCloser, - reader io.ReadCloser, - req *PushRequest, -) error { - writer = ioutil.NewContextWriteCloser(ctx, writer) - reader = ioutil.NewContextReadCloser(ctx, reader) - - var needPackfile bool - for _, cmd := range req.Commands { - if cmd.Action() != packp.Delete { - needPackfile = true - break - } - } - - if !needPackfile && req.Packfile != nil { - return fmt.Errorf("packfile is not accepted for push request without new objects") - } - if needPackfile && req.Packfile == nil { - return fmt.Errorf("packfile is required for push request with new objects") - } - - caps := conn.Capabilities() - upreq := buildUpdateRequests(caps, req) - if err := upreq.Encode(writer); err != nil { - return err - } - - if upreq.Capabilities.Supports(capability.PushOptions) { - var opts packp.PushOptions - opts.Options = req.Options - if err := opts.Encode(writer); err != nil { - return fmt.Errorf("encoding push-options: %w", err) - } - } - - // Send the packfile. - if req.Packfile != nil { - if _, err := ioutil.CopyBufferPool(writer, req.Packfile); err != nil { - return err - } - - if err := req.Packfile.Close(); err != nil { - return fmt.Errorf("closing packfile: %w", err) - } - } - - // Close the write pipe to signal the end of the request. - if err := writer.Close(); err != nil { - return err - } - - if !upreq.Capabilities.Supports(capability.ReportStatus) { - // If we don't have report-status, we're done here. - return nil - } - - var r io.Reader = reader - if req.Progress != nil { - var d *sideband.Demuxer - if upreq.Capabilities.Supports(capability.Sideband64k) { - d = sideband.NewDemuxer(sideband.Sideband64k, reader) - } else if upreq.Capabilities.Supports(capability.Sideband) { - d = sideband.NewDemuxer(sideband.Sideband, reader) - } - if d != nil { - if !upreq.Capabilities.Supports(capability.Quiet) { - // If we want quiet mode, we don't report progress messages - // which means the demuxer won't have a progress writer. - d.Progress = req.Progress - } - r = d - } - } - - report := packp.NewReportStatus() - if err := report.Decode(r); err != nil { - return fmt.Errorf("decode report-status: %w", err) - } - - if err := reader.Close(); err != nil { - return fmt.Errorf("closing reader: %w", err) - } - - return report.Error() -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/receive_pack.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/receive_pack.go deleted file mode 100644 index 183b6dd4..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/receive_pack.go +++ /dev/null @@ -1,256 +0,0 @@ -package transport - -import ( - "bufio" - "context" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/format/pktline" - "github.com/go-git/go-git/v6/plumbing/protocol" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// ReceivePackOptions is a set of options for the ReceivePack service. -type ReceivePackOptions struct { - GitProtocol string - AdvertiseRefs bool - StatelessRPC bool -} - -// ReceivePack is a server command that serves the receive-pack service. -// TODO: support hooks -func ReceivePack( - ctx context.Context, - st storage.Storer, - r io.ReadCloser, - w io.WriteCloser, - opts *ReceivePackOptions, -) error { - if w == nil { - return fmt.Errorf("nil writer") - } - - w = ioutil.NewContextWriteCloser(ctx, w) - - if opts == nil { - opts = &ReceivePackOptions{} - } - - if opts.AdvertiseRefs || !opts.StatelessRPC { - switch version := ProtocolVersion(opts.GitProtocol); version { - case protocol.V1: - if _, err := pktline.Writef(w, "version %d\n", version); err != nil { - return err - } - // TODO: support version 2 - case protocol.V0, protocol.V2: - default: - return fmt.Errorf("%w: %q", ErrUnsupportedVersion, version) - } - - if err := AdvertiseReferences(ctx, st, w, ReceivePackService, opts.StatelessRPC); err != nil { - return err - } - } - - if opts.AdvertiseRefs { - // Done, there's nothing else to do - return nil - } - - if r == nil { - return fmt.Errorf("nil reader") - } - - r = ioutil.NewContextReadCloser(ctx, r) - - rd := bufio.NewReader(r) - l, _, err := pktline.PeekLine(rd) - if err != nil { - return err - } - - // At this point, if we get a flush packet, it means the client - // has nothing to send, so we can return early. - if l == pktline.Flush { - return nil - } - - updreq := packp.NewUpdateRequests() - if err := updreq.Decode(rd); err != nil { - return err - } - - var ( - caps = updreq.Capabilities - needPackfile bool - pushOpts packp.PushOptions - ) - - // TODO: Pass the options to the server-side hooks. - if updreq.Capabilities.Supports(capability.PushOptions) { - if err := pushOpts.Decode(rd); err != nil { - return fmt.Errorf("decoding push-options: %w", err) - } - } - - // Should we expect a packfile? - for _, cmd := range updreq.Commands { - if cmd.Action() != packp.Delete { - needPackfile = true - break - } - } - - // Receive the packfile - var unpackErr error - if needPackfile { - unpackErr = packfile.UpdateObjectStorage(st, rd) - } - - // Done with the request, now close the reader - // to indicate that we are done reading from it. - if err := r.Close(); err != nil { - return fmt.Errorf("closing reader: %w", err) - } - - // Report status if the client supports it - if !updreq.Capabilities.Supports(capability.ReportStatus) { - return unpackErr - } - - var ( - useSideband bool - writer io.Writer = w - ) - if !caps.Supports(capability.NoProgress) { - if caps.Supports(capability.Sideband64k) { - writer = sideband.NewMuxer(sideband.Sideband64k, w) - useSideband = true - } else if caps.Supports(capability.Sideband) { - writer = sideband.NewMuxer(sideband.Sideband, w) - useSideband = true - } - } - - writeCloser := ioutil.NewWriteCloser(writer, w) - if unpackErr != nil { - res := sendReportStatus(writeCloser, unpackErr, nil) - closeWriter(w) - return res - } - - var firstErr error - cmdStatus := make(map[plumbing.ReferenceName]error) - updateReferences(st, updreq, cmdStatus, &firstErr) - - if err := sendReportStatus(writeCloser, firstErr, cmdStatus); err != nil { - return err - } - - if useSideband { - if err := pktline.WriteFlush(w); err != nil { - return fmt.Errorf("flushing sideband: %w", err) - } - } - if firstErr != nil { - return firstErr - } - return closeWriter(w) -} - -func closeWriter(w io.WriteCloser) error { - if err := w.Close(); err != nil { - return fmt.Errorf("closing writer: %w", err) - } - return nil -} - -func sendReportStatus(w io.WriteCloser, unpackErr error, cmdStatus map[plumbing.ReferenceName]error) error { - rs := packp.NewReportStatus() - rs.UnpackStatus = "ok" - if unpackErr != nil { - rs.UnpackStatus = unpackErr.Error() - } - - for ref, err := range cmdStatus { - msg := "ok" - if err != nil { - msg = err.Error() - } - status := &packp.CommandStatus{ - ReferenceName: ref, - Status: msg, - } - rs.CommandStatuses = append(rs.CommandStatuses, status) - } - - if err := rs.Encode(w); err != nil { - return err - } - - return nil -} - -func setStatus(cmdStatus map[plumbing.ReferenceName]error, firstErr *error, ref plumbing.ReferenceName, err error) { - cmdStatus[ref] = err - if *firstErr == nil && err != nil { - *firstErr = err - } -} - -func referenceExists(s storer.ReferenceStorer, n plumbing.ReferenceName) (bool, error) { - _, err := s.Reference(n) - if err == plumbing.ErrReferenceNotFound { - return false, nil - } - - return err == nil, err -} - -func updateReferences(st storage.Storer, req *packp.UpdateRequests, cmdStatus map[plumbing.ReferenceName]error, firstErr *error) { - for _, cmd := range req.Commands { - exists, err := referenceExists(st, cmd.Name) - if err != nil { - setStatus(cmdStatus, firstErr, cmd.Name, err) - continue - } - - switch cmd.Action() { - case packp.Create: - if exists { - setStatus(cmdStatus, firstErr, cmd.Name, ErrUpdateReference) - continue - } - - ref := plumbing.NewHashReference(cmd.Name, cmd.New) - err := st.SetReference(ref) - setStatus(cmdStatus, firstErr, cmd.Name, err) - case packp.Delete: - if !exists { - setStatus(cmdStatus, firstErr, cmd.Name, ErrUpdateReference) - continue - } - - err := st.RemoveReference(cmd.Name) - setStatus(cmdStatus, firstErr, cmd.Name, err) - case packp.Update: - if !exists { - setStatus(cmdStatus, firstErr, cmd.Name, ErrUpdateReference) - continue - } - - ref := plumbing.NewHashReference(cmd.Name, cmd.New) - err := st.SetReference(ref) - setStatus(cmdStatus, firstErr, cmd.Name, err) - } - } -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/registry.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/registry.go deleted file mode 100644 index 20849466..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/registry.go +++ /dev/null @@ -1,42 +0,0 @@ -package transport - -import ( - "fmt" - "sync" -) - -// registry are the protocols supported by default. -var ( - registry = map[string]Transport{} - mtx sync.RWMutex -) - -// Register adds or modifies an existing protocol. -// Equivalent to client.InstallProtocol in go-git before V6. -func Register(protocol string, c Transport) { - mtx.Lock() - registry[protocol] = c - mtx.Unlock() -} - -// Unregister removes a protocol from the list of supported protocols. -func Unregister(scheme string) { - mtx.Lock() - delete(registry, scheme) - mtx.Unlock() -} - -// Get returns the appropriate client for the given protocol. -func Get(p string) (Transport, error) { - mtx.RLock() - defer mtx.RUnlock() - f, ok := registry[p] - if !ok { - return nil, fmt.Errorf("unsupported scheme %q", p) - } - - if f == nil { - return nil, fmt.Errorf("malformed client for scheme %q, client is defined as nil", p) - } - return f, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/serve.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/serve.go deleted file mode 100644 index 41fca696..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/serve.go +++ /dev/null @@ -1,119 +0,0 @@ -package transport - -import ( - "context" - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" -) - -var ErrUpdateReference = errors.New("failed to update ref") - -// AdvertiseReferences is a server command that implements the reference -// discovery phase of the Git transfer protocol. -func AdvertiseReferences( - ctx context.Context, - st storage.Storer, - w io.Writer, - service Service, - smart bool, -) error { - switch service { - case UploadPackService, ReceivePackService: - default: - return fmt.Errorf("%w: %s", ErrUnsupportedService, service) - } - - forPush := service == ReceivePackService - ar := packp.NewAdvRefs() - - // Set server default capabilities - ar.Capabilities.Set(capability.Agent, capability.DefaultAgent()) //nolint:errcheck - ar.Capabilities.Set(capability.OFSDelta) //nolint:errcheck - ar.Capabilities.Set(capability.Sideband64k) //nolint:errcheck - if forPush { - // TODO: support thin-pack - ar.Capabilities.Set(capability.NoThin) //nolint:errcheck - // TODO: support atomic - ar.Capabilities.Set(capability.DeleteRefs) //nolint:errcheck - ar.Capabilities.Set(capability.ReportStatus) //nolint:errcheck - ar.Capabilities.Set(capability.PushOptions) //nolint:errcheck - ar.Capabilities.Set(capability.Quiet) //nolint:errcheck - } else { - // TODO: support include-tag - // TODO: support deepen - // TODO: support deepen-since - ar.Capabilities.Set(capability.MultiACK) //nolint:errcheck - ar.Capabilities.Set(capability.MultiACKDetailed) //nolint:errcheck - ar.Capabilities.Set(capability.Sideband) //nolint:errcheck - ar.Capabilities.Set(capability.NoProgress) //nolint:errcheck - ar.Capabilities.Set(capability.SymRef) //nolint:errcheck - ar.Capabilities.Set(capability.Shallow) //nolint:errcheck - } - - // Set references - if err := addReferences(st, ar, !forPush); err != nil { - return err - } - - if smart { - smartReply := packp.SmartReply{ - Service: service.String(), - } - - if err := smartReply.Encode(w); err != nil { - return fmt.Errorf("failed to encode smart reply: %w", err) - } - } - - return ar.Encode(w) -} - -func addReferences(st storage.Storer, ar *packp.AdvRefs, addHead bool) error { - iter, err := st.IterReferences() - if err != nil { - return err - } - - // Add references and their peeled values - if err := iter.ForEach(func(r *plumbing.Reference) error { - hash, name := r.Hash(), r.Name() - switch r.Type() { - case plumbing.SymbolicReference: - ref, err := storer.ResolveReference(st, r.Target()) - if errors.Is(err, plumbing.ErrReferenceNotFound) { - return nil - } - if err != nil { - return err - } - hash = ref.Hash() - } - if name == plumbing.HEAD { - if !addHead { - return nil - } - // Add default branch HEAD symref - ar.Capabilities.Add(capability.SymRef, fmt.Sprintf("%s:%s", name, r.Target())) //nolint:errcheck - ar.Head = &hash - } - ar.References[name.String()] = hash - if r.Name().IsTag() { - if tag, err := object.GetTag(st, hash); err == nil { - ar.Peeled[name.String()] = tag.Target - } - } - return nil - }); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/serverinfo.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/serverinfo.go deleted file mode 100644 index 8a102913..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/serverinfo.go +++ /dev/null @@ -1,53 +0,0 @@ -package transport - -import ( - "fmt" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/internal/repository" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" -) - -// UpdateServerInfo updates the server info files in the repository. -// -// It generates a list of available refs for the repository. -// Used by git http transport (dumb), for more information refer to: -// https://git-scm.com/book/id/v2/Git-Internals-Transfer-Protocols#_the_dumb_protocol -func UpdateServerInfo(s storage.Storer, fs billy.Filesystem) error { - pos, ok := s.(storer.PackedObjectStorer) - if !ok { - return ErrPackedObjectsNotSupported - } - - infoRefs, err := fs.Create("info/refs") - if err != nil { - return err - } - - defer infoRefs.Close() //nolint:errcheck - - refsIter, err := s.IterReferences() - if err != nil { - return err - } - - defer refsIter.Close() - - if err := repository.WriteInfoRefs(infoRefs, s); err != nil { - return fmt.Errorf("failed to write info/refs: %w", err) - } - - infoPacks, err := fs.Create("objects/info/packs") - if err != nil { - return err - } - - defer infoPacks.Close() //nolint:errcheck - - if err := repository.WriteObjectsInfoPacks(infoPacks, pos); err != nil { - return fmt.Errorf("failed to write objects/info/packs: %w", err) - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/service.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/service.go deleted file mode 100644 index 5c7fec1e..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/service.go +++ /dev/null @@ -1,24 +0,0 @@ -package transport - -import "strings" - -// Service represents a Git transport service. -// All services are prefixed with "git-". -type Service string - -// String returns the string representation of the service. -func (s Service) String() string { - return string(s) -} - -// Name returns the name of the service without the "git-" prefix. -func (s Service) Name() string { - return strings.TrimPrefix(string(s), "git-") -} - -// Git service names. -const ( - UploadPackService Service = "git-upload-pack" - UploadArchiveService Service = "git-upload-archive" - ReceivePackService Service = "git-receive-pack" -) diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/auth_method.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/auth_method.go deleted file mode 100644 index a03d3c3d..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/auth_method.go +++ /dev/null @@ -1,353 +0,0 @@ -package ssh - -import ( - "errors" - "fmt" - "net" - "os" - "os/user" - "path/filepath" - - "github.com/go-git/go-git/v6/plumbing/transport" - "github.com/go-git/go-git/v6/plumbing/transport/ssh/knownhosts" - "github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent" - "github.com/go-git/go-git/v6/utils/trace" - - "golang.org/x/crypto/ssh" -) - -const DefaultUsername = "git" - -// AuthMethod is the interface all auth methods for the ssh client -// must implement. The clientConfig method returns the ssh client -// configuration needed to establish an ssh connection. -type AuthMethod interface { - transport.AuthMethod - // ClientConfig should return a valid ssh.ClientConfig to be used to create - // a connection to the SSH server. - ClientConfig() (*ssh.ClientConfig, error) -} - -// The names of the AuthMethod implementations. To be returned by the -// Name() method. Most git servers only allow PublicKeysName and -// PublicKeysCallbackName. -const ( - KeyboardInteractiveName = "ssh-keyboard-interactive" - PasswordName = "ssh-password" - PasswordCallbackName = "ssh-password-callback" - PublicKeysName = "ssh-public-keys" - PublicKeysCallbackName = "ssh-public-key-callback" -) - -// KeyboardInteractive implements AuthMethod by using a -// prompt/response sequence controlled by the server. -type KeyboardInteractive struct { - User string - Challenge ssh.KeyboardInteractiveChallenge - HostKeyCallbackHelper -} - -func (a *KeyboardInteractive) Name() string { - return KeyboardInteractiveName -} - -func (a *KeyboardInteractive) String() string { - return fmt.Sprintf("user: %s, name: %s", a.User, a.Name()) -} - -func (a *KeyboardInteractive) ClientConfig() (*ssh.ClientConfig, error) { - trace.SSH.Printf("ssh: %s user=%s", KeyboardInteractiveName, a.User) - return a.SetHostKeyCallback(&ssh.ClientConfig{ - User: a.User, - Auth: []ssh.AuthMethod{ - a.Challenge, - }, - }) -} - -// Password implements AuthMethod by using the given password. -type Password struct { - User string - Password string - HostKeyCallbackHelper -} - -func (a *Password) Name() string { - return PasswordName -} - -func (a *Password) String() string { - return fmt.Sprintf("user: %s, name: %s", a.User, a.Name()) -} - -func (a *Password) ClientConfig() (*ssh.ClientConfig, error) { - trace.SSH.Printf("ssh: %s user=%s", PasswordName, a.User) - return a.SetHostKeyCallback(&ssh.ClientConfig{ - User: a.User, - Auth: []ssh.AuthMethod{ssh.Password(a.Password)}, - }) -} - -// PasswordCallback implements AuthMethod by using a callback -// to fetch the password. -type PasswordCallback struct { - User string - Callback func() (pass string, err error) - HostKeyCallbackHelper -} - -func (a *PasswordCallback) Name() string { - return PasswordCallbackName -} - -func (a *PasswordCallback) String() string { - return fmt.Sprintf("user: %s, name: %s", a.User, a.Name()) -} - -func (a *PasswordCallback) ClientConfig() (*ssh.ClientConfig, error) { - trace.SSH.Printf("ssh: %s user=%s", PasswordCallbackName, a.User) - return a.SetHostKeyCallback(&ssh.ClientConfig{ - User: a.User, - Auth: []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)}, - }) -} - -// PublicKeys implements AuthMethod by using the given key pairs. -type PublicKeys struct { - User string - Signer ssh.Signer - HostKeyCallbackHelper -} - -// NewPublicKeys returns a PublicKeys from a PEM encoded private key. An -// encryption password should be given if the pemBytes contains a password -// encrypted PEM block otherwise password should be empty. It supports RSA -// (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. -func NewPublicKeys(user string, pemBytes []byte, password string) (*PublicKeys, error) { - signer, err := ssh.ParsePrivateKey(pemBytes) - if _, ok := err.(*ssh.PassphraseMissingError); ok { - signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(password)) - } - if err != nil { - return nil, err - } - return &PublicKeys{User: user, Signer: signer}, nil -} - -// NewPublicKeysFromFile returns a PublicKeys from a file containing a PEM -// encoded private key. An encryption password should be given if the pemBytes -// contains a password encrypted PEM block otherwise password should be empty. -func NewPublicKeysFromFile(user, pemFile, password string) (*PublicKeys, error) { - bytes, err := os.ReadFile(pemFile) - if err != nil { - return nil, err - } - - return NewPublicKeys(user, bytes, password) -} - -func (a *PublicKeys) Name() string { - return PublicKeysName -} - -func (a *PublicKeys) String() string { - return fmt.Sprintf("user: %s, name: %s", a.User, a.Name()) -} - -func (a *PublicKeys) ClientConfig() (*ssh.ClientConfig, error) { - trace.SSH.Printf("ssh: %s user=%s signer=\"%s %s\"", PublicKeysName, a.User, - a.Signer.PublicKey().Type(), - ssh.FingerprintSHA256(a.Signer.PublicKey())) - return a.SetHostKeyCallback(&ssh.ClientConfig{ - User: a.User, - Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)}, - }) -} - -func username() (string, error) { - var username string - if user, err := user.Current(); err == nil { - username = user.Username - trace.SSH.Printf("ssh: Falling back to current user name %q", username) - } else { - username = os.Getenv("USER") - trace.SSH.Printf("ssh: Falling back to environment variable USER %q", username) - } - - if username == "" { - return "", errors.New("failed to get username") - } - - return username, nil -} - -// PublicKeysCallback implements AuthMethod by asking a -// ssh.agent.Agent to act as a signer. -type PublicKeysCallback struct { - User string - Callback func() (signers []ssh.Signer, err error) - HostKeyCallbackHelper -} - -// NewSSHAgentAuth returns a PublicKeysCallback based on a SSH agent, it opens -// a pipe with the SSH agent and uses the pipe as the implementer of the public -// key callback function. -func NewSSHAgentAuth(u string) (*PublicKeysCallback, error) { - var err error - if u == "" { - u, err = username() - if err != nil { - return nil, err - } - } - - a, _, err := sshagent.New() - if err != nil { - return nil, fmt.Errorf("error creating SSH agent: %q", err) - } - - return &PublicKeysCallback{ - User: u, - Callback: a.Signers, - }, nil -} - -func (a *PublicKeysCallback) Name() string { - return PublicKeysCallbackName -} - -func (a *PublicKeysCallback) String() string { - return fmt.Sprintf("user: %s, name: %s", a.User, a.Name()) -} - -func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) { - trace.SSH.Printf("ssh: %s user=%s", PublicKeysCallbackName, a.User) - return a.SetHostKeyCallback(&ssh.ClientConfig{ - User: a.User, - Auth: []ssh.AuthMethod{tracePublicKeysCallback(a.Callback)}, - }) -} - -// NewKnownHostsCallback returns ssh.HostKeyCallback based on a file based on a -// known_hosts file. http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT -// -// If list of files is empty, then it will be read from the SSH_KNOWN_HOSTS -// environment variable, example: -// -// /home/foo/custom_known_hosts_file:/etc/custom_known/hosts_file -// -// If SSH_KNOWN_HOSTS is not set the following file locations will be used: -// -// ~/.ssh/known_hosts -// /etc/ssh/ssh_known_hosts -func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) { - db, err := newKnownHostsDb(files...) - return db.HostKeyCallback(), err -} - -func newKnownHostsDb(files ...string) (*knownhosts.HostKeyDB, error) { - var err error - if len(files) == 0 { - if files, err = getDefaultKnownHostsFiles(); err != nil { - return nil, err - } - } - trace.SSH.Printf("ssh: known_hosts sources %s", files) - - if files, err = filterKnownHostsFiles(files...); err != nil { - return nil, err - } - trace.SSH.Printf("ssh: filtered known_hosts sources %s", files) - - return knownhosts.NewDB(files...) -} - -func getDefaultKnownHostsFiles() ([]string, error) { - files := filepath.SplitList(os.Getenv("SSH_KNOWN_HOSTS")) - if len(files) != 0 { - trace.SSH.Printf("ssh: loading known_hosts from SSH_KNOWN_HOSTS") - return files, nil - } - - homeDirPath, err := os.UserHomeDir() - if err != nil { - return nil, err - } - - return []string{ - filepath.Join(homeDirPath, "/.ssh/known_hosts"), - "/etc/ssh/ssh_known_hosts", - }, nil -} - -func filterKnownHostsFiles(files ...string) ([]string, error) { - var out []string - for _, file := range files { - _, err := os.Stat(file) - if err == nil { - out = append(out, file) - continue - } - - if !os.IsNotExist(err) { - return nil, err - } - } - - if len(out) == 0 { - return nil, fmt.Errorf("unable to find any valid known_hosts file, set SSH_KNOWN_HOSTS env variable") - } - - return out, nil -} - -// HostKeyCallbackHelper is a helper that provides common functionality to -// configure HostKeyCallback into a ssh.ClientConfig. -type HostKeyCallbackHelper struct { - // HostKeyCallback is the function type used for verifying server keys. - // If nil default callback will be create using NewKnownHostsCallback - // without argument. - HostKeyCallback ssh.HostKeyCallback -} - -// SetHostKeyCallback sets the field HostKeyCallback in the given cfg. If -// HostKeyCallback is empty a default callback is created using -// NewKnownHostsCallback. -func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) { - if m.HostKeyCallback == nil { - db, err := newKnownHostsDb() - if err != nil { - return cfg, err - } - m.HostKeyCallback = db.HostKeyCallback() - } - - cfg.HostKeyCallback = m.traceHostKeyCallback - return cfg, nil -} - -func (m *HostKeyCallbackHelper) traceHostKeyCallback(hostname string, remote net.Addr, key ssh.PublicKey) error { - trace.SSH.Printf( - `ssh: hostkey callback hostname=%s remote=%s pubkey="%s %s"`, - hostname, remote, key.Type(), ssh.FingerprintSHA256(key)) - return m.HostKeyCallback(hostname, remote, key) -} - -func tracePublicKeysCallback(getSigners func() ([]ssh.Signer, error)) ssh.AuthMethod { - signers, err := getSigners() - if err != nil { - trace.SSH.Printf("ssh: error calling getSigners: %v", err) - } - if len(signers) == 0 { - trace.SSH.Printf("ssh: no signers found") - } - for _, s := range signers { - trace.SSH.Printf("ssh: found key: %s %s", s.PublicKey().Type(), - ssh.FingerprintSHA256(s.PublicKey())) - } - - cb := func() ([]ssh.Signer, error) { - return signers, err - } - return ssh.PublicKeysCallback(cb) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/common.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/common.go deleted file mode 100644 index 15361f29..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/common.go +++ /dev/null @@ -1,295 +0,0 @@ -// Package ssh implements the SSH transport protocol. -package ssh - -import ( - "context" - "errors" - "fmt" - "net" - "reflect" - "strconv" - "strings" - - "github.com/go-git/go-git/v6/plumbing/transport" - "github.com/go-git/go-git/v6/utils/trace" - - "github.com/kevinburke/ssh_config" - "golang.org/x/crypto/ssh" - "golang.org/x/net/proxy" -) - -func init() { - transport.Register("ssh", DefaultTransport) -} - -// DefaultTransport is the default SSH client. -var DefaultTransport = NewTransport(nil) - -// DefaultSSHConfig is the reader used to access parameters stored in the -// system's ssh_config files. If nil all the ssh_config are ignored. -var DefaultSSHConfig sshConfig = ssh_config.DefaultUserSettings - -type sshConfig interface { - Get(alias, key string) string -} - -// NewTransport creates a new SSH client with an optional *ssh.ClientConfig. -func NewTransport(config *ssh.ClientConfig) transport.Transport { - return transport.NewPackTransport(&runner{config: config}) -} - -// DefaultAuthBuilder is the function used to create a default AuthMethod, when -// the user doesn't provide any. -var DefaultAuthBuilder = func(user string) (AuthMethod, error) { - trace.SSH.Printf("ssh: Using default auth builder (user: %s)", user) - return NewSSHAgentAuth(user) -} - -const DefaultPort = 22 - -type runner struct { - config *ssh.ClientConfig -} - -func (r *runner) Command(ctx context.Context, cmd string, ep *transport.Endpoint, auth transport.AuthMethod, params ...string) (transport.Command, error) { - c := &command{command: cmd, endpoint: ep, config: r.config} - if auth != nil { - if err := c.setAuth(auth); err != nil { - return nil, err - } - } - - gitProtocol := strings.Join(params, ":") - if err := c.connect(ctx); err != nil { - return nil, err - } - - if gitProtocol != "" { - c.Session.Setenv("GIT_PROTOCOL", gitProtocol) - } - - return c, nil -} - -type command struct { - *ssh.Session - connected bool - command string - endpoint *transport.Endpoint - client *ssh.Client - auth AuthMethod - config *ssh.ClientConfig -} - -func (c *command) setAuth(auth transport.AuthMethod) error { - a, ok := auth.(AuthMethod) - if !ok { - return transport.ErrInvalidAuthMethod - } - - c.auth = a - return nil -} - -func (c *command) Start() error { - cmd := endpointToCommand(c.command, c.endpoint) - return c.Session.Start(cmd) -} - -// Close closes the SSH session and connection. -func (c *command) Close() error { - if !c.connected { - return nil - } - - c.connected = false - - // XXX: If did read the full packfile, then the session might be already - // closed. - _ = c.Session.Close() - err := c.client.Close() - if errors.Is(err, net.ErrClosed) { - return nil - } - - return err -} - -// connect connects to the SSH server, unless a AuthMethod was set with -// SetAuth method, by default uses an auth method based on PublicKeysCallback, -// it connects to a SSH agent, using the address stored in the SSH_AUTH_SOCK -// environment var. -func (c *command) connect(ctx context.Context) error { - if c.connected { - return transport.ErrAlreadyConnected - } - - if c.auth == nil { - if err := c.setAuthFromEndpoint(); err != nil { - return err - } - } - - var err error - config, err := c.auth.ClientConfig() - if err != nil { - return err - } - hostWithPort := c.getHostWithPort() - if config.HostKeyCallback == nil { - db, err := newKnownHostsDb() - if err != nil { - return err - } - - config.HostKeyCallback = db.HostKeyCallback() - config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort) - } else if len(config.HostKeyAlgorithms) == 0 { - // Set the HostKeyAlgorithms based on HostKeyCallback. - // For background see https://github.com/go-git/go-git/issues/411 as well as - // https://github.com/golang/go/issues/29286 for root cause. - db, err := newKnownHostsDb() - if err != nil { - return err - } - - // Note that the knownhost database is used, as it provides additional functionality - // to handle ssh cert-authorities. - config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort) - } - - trace.SSH.Printf("ssh: host key algorithms %s", config.HostKeyAlgorithms) - - overrideConfig(c.config, config) - - c.client, err = dial(ctx, "tcp", hostWithPort, c.endpoint.Proxy, config) - if err != nil { - return err - } - - c.Session, err = c.client.NewSession() - if err != nil { - _ = c.client.Close() - return err - } - - c.connected = true - return nil -} - -func dial(ctx context.Context, network, addr string, proxyOpts transport.ProxyOptions, config *ssh.ClientConfig) (*ssh.Client, error) { - var cancel context.CancelFunc - if config.Timeout > 0 { - ctx, cancel = context.WithTimeout(ctx, config.Timeout) - } else { - ctx, cancel = context.WithCancel(ctx) - } - defer cancel() - - var conn net.Conn - var dialErr error - - if proxyOpts.URL != "" { - proxyUrl, err := proxyOpts.FullURL() - if err != nil { - return nil, err - } - - trace.SSH.Printf("ssh: using proxyURL=%s", proxyUrl) - dialer, err := proxy.FromURL(proxyUrl, proxy.Direct) - if err != nil { - return nil, err - } - - // Try to use a ContextDialer, but fall back to a Dialer if that goes south. - ctxDialer, ok := dialer.(proxy.ContextDialer) - if !ok { - return nil, fmt.Errorf("expected ssh proxy dialer to be of type %s; got %s", - reflect.TypeOf(ctxDialer), reflect.TypeOf(dialer)) - } - conn, dialErr = ctxDialer.DialContext(ctx, "tcp", addr) - } else { - conn, dialErr = proxy.Dial(ctx, network, addr) - } - if dialErr != nil { - return nil, dialErr - } - - c, chans, reqs, err := ssh.NewClientConn(conn, addr, config) - if err != nil { - return nil, err - } - return ssh.NewClient(c, chans, reqs), nil -} - -func (c *command) getHostWithPort() string { - if addr, found := c.doGetHostWithPortFromSSHConfig(); found { - return addr - } - - host := c.endpoint.Host - port := c.endpoint.Port - if port <= 0 { - port = DefaultPort - } - - return net.JoinHostPort(host, strconv.Itoa(port)) -} - -func (c *command) doGetHostWithPortFromSSHConfig() (addr string, found bool) { - if DefaultSSHConfig == nil { - return - } - - host := c.endpoint.Host - port := c.endpoint.Port - - configHost := DefaultSSHConfig.Get(c.endpoint.Host, "Hostname") - if configHost != "" { - host = configHost - found = true - } - - if !found { - return - } - - configPort := DefaultSSHConfig.Get(c.endpoint.Host, "Port") - if configPort != "" { - if i, err := strconv.Atoi(configPort); err == nil { - port = i - } - } - - addr = net.JoinHostPort(host, strconv.Itoa(port)) - return -} - -func (c *command) setAuthFromEndpoint() error { - var err error - c.auth, err = DefaultAuthBuilder(c.endpoint.User) - return err -} - -func endpointToCommand(cmd string, ep *transport.Endpoint) string { - return fmt.Sprintf("%s '%s'", cmd, ep.Path) -} - -func overrideConfig(overrides *ssh.ClientConfig, c *ssh.ClientConfig) { - if overrides == nil { - return - } - - t := reflect.TypeOf(*c) - vc := reflect.ValueOf(c).Elem() - vo := reflect.ValueOf(overrides).Elem() - - for i := 0; i < t.NumField(); i++ { - f := t.Field(i) - vcf := vc.FieldByName(f.Name) - vof := vo.FieldByName(f.Name) - vcf.Set(vof) - } - - *c = vc.Interface().(ssh.ClientConfig) -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/knownhosts/knownhosts.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/knownhosts/knownhosts.go deleted file mode 100644 index 2ceae1af..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/knownhosts/knownhosts.go +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright 2024 Skeema LLC and the Skeema Knownhosts 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. - -// Originally from: https://github.com/skeema/knownhosts/blob/main/knownhosts.go - -// Package knownhosts is a thin wrapper around golang.org/x/crypto/ssh/knownhosts, -// adding the ability to obtain the list of host key algorithms for a known host. -package knownhosts - -import ( - "bufio" - "bytes" - "encoding/base64" - "errors" - "fmt" - "io" - "net" - "os" - "sort" - "strings" - - "github.com/go-git/go-git/v6/utils/trace" - "golang.org/x/crypto/ssh" - xknownhosts "golang.org/x/crypto/ssh/knownhosts" -) - -// HostKeyDB wraps logic in golang.org/x/crypto/ssh/knownhosts with additional -// behaviors, such as the ability to perform host key/algorithm lookups from -// known_hosts entries. -type HostKeyDB struct { - callback ssh.HostKeyCallback - isCert map[string]bool // keyed by "filename:line" - isWildcard map[string]bool // keyed by "filename:line" -} - -// NewDB creates a HostKeyDB from the given OpenSSH known_hosts file(s). It -// reads and parses the provided files one additional time (beyond logic in -// golang.org/x/crypto/ssh/knownhosts) in order to: -// -// - Handle CA lines properly and return ssh.CertAlgo* values when calling the -// HostKeyAlgorithms method, for use in ssh.ClientConfig.HostKeyAlgorithms -// - Allow * wildcards in hostnames to match on non-standard ports, providing -// a workaround for https://github.com/golang/go/issues/52056 in order to -// align with OpenSSH's wildcard behavior -// -// When supplying multiple files, their order does not matter. -func NewDB(files ...string) (*HostKeyDB, error) { - cb, err := xknownhosts.New(files...) - if err != nil { - return nil, err - } - hkdb := &HostKeyDB{ - callback: cb, - isCert: make(map[string]bool), - isWildcard: make(map[string]bool), - } - - // Re-read each file a single time, looking for @cert-authority lines. The - // logic for reading the file is designed to mimic hostKeyDB.Read from - // golang.org/x/crypto/ssh/knownhosts - for _, filename := range files { - f, err := os.Open(filename) - if err != nil { - return nil, err - } - defer f.Close() - scanner := bufio.NewScanner(f) - lineNum := 0 - for scanner.Scan() { - lineNum++ - line := scanner.Bytes() - line = bytes.TrimSpace(line) - // Does the line start with "@cert-authority" followed by whitespace? - if len(line) > 15 && bytes.HasPrefix(line, []byte("@cert-authority")) && (line[15] == ' ' || line[15] == '\t') { - mapKey := fmt.Sprintf("%s:%d", filename, lineNum) - hkdb.isCert[mapKey] = true - line = bytes.TrimSpace(line[16:]) - } - // truncate line to just the host pattern field - if i := bytes.IndexAny(line, "\t "); i >= 0 { - line = line[:i] - } - // Does the host pattern contain a * wildcard and no specific port? - if i := bytes.IndexRune(line, '*'); i >= 0 && !bytes.Contains(line[i:], []byte("]:")) { - mapKey := fmt.Sprintf("%s:%d", filename, lineNum) - hkdb.isWildcard[mapKey] = true - } - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("knownhosts: %s:%d: %w", filename, lineNum, err) - } - } - return hkdb, nil -} - -// HostKeyCallback returns an ssh.HostKeyCallback. This can be used directly in -// ssh.ClientConfig.HostKeyCallback, as shown in the example for NewDB. -// Alternatively, you can wrap it with an outer callback to potentially handle -// appending a new entry to the known_hosts file; see example in WriteKnownHost. -func (hkdb *HostKeyDB) HostKeyCallback() ssh.HostKeyCallback { - // Either NewDB found no wildcard host patterns, or hkdb was created from - // HostKeyCallback.ToDB in which case we didn't scan known_hosts for them: - // return the callback (which came from x/crypto/ssh/knownhosts) as-is - if len(hkdb.isWildcard) == 0 { - return hkdb.callback - } - - // If we scanned for wildcards and found at least one, return a wrapped - // callback with extra behavior: if the host lookup found no matches, and the - // host arg had a non-standard port, re-do the lookup on standard port 22. If - // that second call returns a *xknownhosts.KeyError, filter down any resulting - // Want keys to known wildcard entries. - f := func(hostname string, remote net.Addr, key ssh.PublicKey) error { - trace.SSH.Printf( - `ssh: wildcard knownhosts for hostname=%s pubkey="%s %s"`, - hostname, key.Type(), ssh.FingerprintSHA256(key)) - - callbackErr := hkdb.callback(hostname, remote, key) - if callbackErr == nil || IsHostKeyChanged(callbackErr) { // hostname has known_host entries as-is - return callbackErr - } - justHost, port, splitErr := net.SplitHostPort(hostname) - if splitErr != nil || port == "" || port == "22" { // hostname already using standard port - return callbackErr - } - // If we reach here, the port was non-standard and no known_host entries - // were found for the non-standard port. Try again with standard port. - if tcpAddr, ok := remote.(*net.TCPAddr); ok && tcpAddr.Port != 22 { - remote = &net.TCPAddr{ - IP: tcpAddr.IP, - Port: 22, - Zone: tcpAddr.Zone, - } - } - callbackErr = hkdb.callback(justHost+":22", remote, key) - var keyErr *xknownhosts.KeyError - if errors.As(callbackErr, &keyErr) && len(keyErr.Want) > 0 { - wildcardKeys := make([]xknownhosts.KnownKey, 0, len(keyErr.Want)) - for _, wantKey := range keyErr.Want { - if hkdb.isWildcard[fmt.Sprintf("%s:%d", wantKey.Filename, wantKey.Line)] { - wildcardKeys = append(wildcardKeys, wantKey) - } - } - callbackErr = &xknownhosts.KeyError{ - Want: wildcardKeys, - } - } - return callbackErr - } - return ssh.HostKeyCallback(f) -} - -// PublicKey wraps ssh.PublicKey with an additional field, to identify -// whether the key corresponds to a certificate authority. -type PublicKey struct { - ssh.PublicKey - Cert bool -} - -// HostKeys returns a slice of known host public keys for the supplied host:port -// found in the known_hosts file(s), or an empty slice if the host is not -// already known. For hosts that have multiple known_hosts entries (for -// different key types), the result will be sorted by known_hosts filename and -// line number. -// If hkdb was originally created by calling NewDB, the Cert boolean field of -// each result entry reports whether the key corresponded to a @cert-authority -// line. If hkdb was NOT obtained from NewDB, then Cert will always be false. -func (hkdb *HostKeyDB) HostKeys(hostWithPort string) (keys []PublicKey) { - var keyErr *xknownhosts.KeyError - placeholderAddr := &net.TCPAddr{IP: []byte{0, 0, 0, 0}} - placeholderPubKey := &fakePublicKey{} - var kkeys []xknownhosts.KnownKey - callback := hkdb.HostKeyCallback() - if hkcbErr := callback(hostWithPort, placeholderAddr, placeholderPubKey); errors.As(hkcbErr, &keyErr) { - kkeys = append(kkeys, keyErr.Want...) - knownKeyLess := func(i, j int) bool { - if kkeys[i].Filename < kkeys[j].Filename { - return true - } - return (kkeys[i].Filename == kkeys[j].Filename && kkeys[i].Line < kkeys[j].Line) - } - sort.Slice(kkeys, knownKeyLess) - keys = make([]PublicKey, len(kkeys)) - for n := range kkeys { - keys[n] = PublicKey{ - PublicKey: kkeys[n].Key, - } - if len(hkdb.isCert) > 0 { - keys[n].Cert = hkdb.isCert[fmt.Sprintf("%s:%d", kkeys[n].Filename, kkeys[n].Line)] - } - } - } - return keys -} - -// HostKeyAlgorithms returns a slice of host key algorithms for the supplied -// host:port found in the known_hosts file(s), or an empty slice if the host -// is not already known. The result may be used in ssh.ClientConfig's -// HostKeyAlgorithms field, either as-is or after filtering (if you wish to -// ignore or prefer particular algorithms). For hosts that have multiple -// known_hosts entries (of different key types), the result will be sorted by -// known_hosts filename and line number. -// If hkdb was originally created by calling NewDB, any @cert-authority lines -// in the known_hosts file will properly be converted to the corresponding -// ssh.CertAlgo* values. -func (hkdb *HostKeyDB) HostKeyAlgorithms(hostWithPort string) (algos []string) { - // We ensure that algos never contains duplicates. This is done for robustness - // even though currently golang.org/x/crypto/ssh/knownhosts never exposes - // multiple keys of the same type. This way our behavior here is unaffected - // even if https://github.com/golang/go/issues/28870 is implemented, for - // example by https://github.com/golang/crypto/pull/254. - hostKeys := hkdb.HostKeys(hostWithPort) - seen := make(map[string]struct{}, len(hostKeys)) - addAlgo := func(typ string, cert bool) { - if cert { - typ = keyTypeToCertAlgo(typ) - } - if _, already := seen[typ]; !already { - algos = append(algos, typ) - seen[typ] = struct{}{} - } - } - for _, key := range hostKeys { - typ := key.Type() - if typ == ssh.KeyAlgoRSA { - // KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, - // not public key formats, so they can't appear as a PublicKey.Type. - // The corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2. - addAlgo(ssh.KeyAlgoRSASHA512, key.Cert) - addAlgo(ssh.KeyAlgoRSASHA256, key.Cert) - } - addAlgo(typ, key.Cert) - } - return algos -} - -func keyTypeToCertAlgo(keyType string) string { - switch keyType { - case ssh.KeyAlgoRSA: - return ssh.CertAlgoRSAv01 - case ssh.KeyAlgoRSASHA256: - return ssh.CertAlgoRSASHA256v01 - case ssh.KeyAlgoRSASHA512: - return ssh.CertAlgoRSASHA512v01 - case ssh.KeyAlgoDSA: - return ssh.CertAlgoDSAv01 - case ssh.KeyAlgoECDSA256: - return ssh.CertAlgoECDSA256v01 - case ssh.KeyAlgoSKECDSA256: - return ssh.CertAlgoSKECDSA256v01 - case ssh.KeyAlgoECDSA384: - return ssh.CertAlgoECDSA384v01 - case ssh.KeyAlgoECDSA521: - return ssh.CertAlgoECDSA521v01 - case ssh.KeyAlgoED25519: - return ssh.CertAlgoED25519v01 - case ssh.KeyAlgoSKED25519: - return ssh.CertAlgoSKED25519v01 - } - return "" -} - -// HostKeyCallback wraps ssh.HostKeyCallback with additional methods to -// perform host key and algorithm lookups from the known_hosts entries. It is -// otherwise identical to ssh.HostKeyCallback, and does not introduce any file- -// parsing behavior beyond what is in golang.org/x/crypto/ssh/knownhosts. -// -// In most situations, use HostKeyDB and its constructor NewDB instead of using -// the HostKeyCallback type. The HostKeyCallback type is only provided for -// backwards compatibility with older versions of this package, as well as for -// very strict situations where any extra known_hosts file-parsing is -// undesirable. -// -// Methods of HostKeyCallback do not provide any special treatment for -// @cert-authority lines, which will (incorrectly) look like normal non-CA host -// keys. Additionally, HostKeyCallback lacks the fix for applying * wildcard -// known_host entries to all ports, like OpenSSH's behavior. -type HostKeyCallback ssh.HostKeyCallback - -// New creates a HostKeyCallback from the given OpenSSH known_hosts file(s). The -// returned value may be used in ssh.ClientConfig.HostKeyCallback by casting it -// to ssh.HostKeyCallback, or using its HostKeyCallback method. Otherwise, it -// operates the same as the New function in golang.org/x/crypto/ssh/knownhosts. -// When supplying multiple files, their order does not matter. -// -// In most situations, you should avoid this function, as the returned value -// lacks several enhanced behaviors. See doc comment for HostKeyCallback for -// more information. Instead, most callers should use NewDB to create a -// HostKeyDB, which includes these enhancements. -func New(files ...string) (HostKeyCallback, error) { - cb, err := xknownhosts.New(files...) - return HostKeyCallback(cb), err -} - -// HostKeyCallback simply casts the receiver back to ssh.HostKeyCallback, for -// use in ssh.ClientConfig.HostKeyCallback. -func (hkcb HostKeyCallback) HostKeyCallback() ssh.HostKeyCallback { - return ssh.HostKeyCallback(hkcb) -} - -// ToDB converts the receiver into a HostKeyDB. However, the returned HostKeyDB -// lacks the enhanced behaviors described in the doc comment for NewDB: proper -// CA support, and wildcard matching on nonstandard ports. -// -// It is generally preferable to create a HostKeyDB by using NewDB. The ToDB -// method is only provided for situations in which the calling code needs to -// make the extra NewDB behaviors optional / user-configurable, perhaps for -// reasons of performance or code trust (since NewDB reads the known_host file -// an extra time, which may be undesirable in some strict situations). This way, -// callers can conditionally create a non-enhanced HostKeyDB by using New and -// ToDB. See code example. -func (hkcb HostKeyCallback) ToDB() *HostKeyDB { - // This intentionally leaves the isCert and isWildcard map fields as nil, as - // there is no way to retroactively populate them from just a HostKeyCallback. - // Methods of HostKeyDB will skip any related enhanced behaviors accordingly. - return &HostKeyDB{callback: ssh.HostKeyCallback(hkcb)} -} - -// HostKeys returns a slice of known host public keys for the supplied host:port -// found in the known_hosts file(s), or an empty slice if the host is not -// already known. For hosts that have multiple known_hosts entries (for -// different key types), the result will be sorted by known_hosts filename and -// line number. -// In the returned values, there is no way to distinguish between CA keys -// (known_hosts lines beginning with @cert-authority) and regular keys. To do -// so, see NewDB and HostKeyDB.HostKeys instead. -func (hkcb HostKeyCallback) HostKeys(hostWithPort string) []ssh.PublicKey { - annotatedKeys := hkcb.ToDB().HostKeys(hostWithPort) - rawKeys := make([]ssh.PublicKey, len(annotatedKeys)) - for n, ak := range annotatedKeys { - rawKeys[n] = ak.PublicKey - } - return rawKeys -} - -// HostKeyAlgorithms returns a slice of host key algorithms for the supplied -// host:port found in the known_hosts file(s), or an empty slice if the host -// is not already known. The result may be used in ssh.ClientConfig's -// HostKeyAlgorithms field, either as-is or after filtering (if you wish to -// ignore or prefer particular algorithms). For hosts that have multiple -// known_hosts entries (for different key types), the result will be sorted by -// known_hosts filename and line number. -// The returned values will not include ssh.CertAlgo* values. If any -// known_hosts lines had @cert-authority prefixes, their original key algo will -// be returned instead. For proper CA support, see NewDB and -// HostKeyDB.HostKeyAlgorithms instead. -func (hkcb HostKeyCallback) HostKeyAlgorithms(hostWithPort string) (algos []string) { - return hkcb.ToDB().HostKeyAlgorithms(hostWithPort) -} - -// HostKeyAlgorithms is a convenience function for performing host key algorithm -// lookups on an ssh.HostKeyCallback directly. It is intended for use in code -// paths that stay with the New method of golang.org/x/crypto/ssh/knownhosts -// rather than this package's New or NewDB methods. -// The returned values will not include ssh.CertAlgo* values. If any -// known_hosts lines had @cert-authority prefixes, their original key algo will -// be returned instead. For proper CA support, see NewDB and -// HostKeyDB.HostKeyAlgorithms instead. -func HostKeyAlgorithms(cb ssh.HostKeyCallback, hostWithPort string) []string { - return HostKeyCallback(cb).HostKeyAlgorithms(hostWithPort) -} - -// IsHostKeyChanged returns a boolean indicating whether the error indicates -// the host key has changed. It is intended to be called on the error returned -// from invoking a host key callback, to check whether an SSH host is known. -func IsHostKeyChanged(err error) bool { - var keyErr *xknownhosts.KeyError - return errors.As(err, &keyErr) && len(keyErr.Want) > 0 -} - -// IsHostUnknown returns a boolean indicating whether the error represents an -// unknown host. It is intended to be called on the error returned from invoking -// a host key callback to check whether an SSH host is known. -func IsHostUnknown(err error) bool { - var keyErr *xknownhosts.KeyError - return errors.As(err, &keyErr) && len(keyErr.Want) == 0 -} - -// Normalize normalizes an address into the form used in known_hosts. This -// implementation includes a fix for https://github.com/golang/go/issues/53463 -// and will omit brackets around ipv6 addresses on standard port 22. -func Normalize(address string) string { - host, port, err := net.SplitHostPort(address) - if err != nil { - host = address - port = "22" - } - entry := host - if port != "22" { - entry = "[" + entry + "]:" + port - } else if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") { - entry = entry[1 : len(entry)-1] - } - return entry -} - -// Line returns a line to append to the known_hosts files. This implementation -// uses the local patched implementation of Normalize in order to solve -// https://github.com/golang/go/issues/53463. -func Line(addresses []string, key ssh.PublicKey) string { - var trimmed []string - for _, a := range addresses { - trimmed = append(trimmed, Normalize(a)) - } - - return strings.Join([]string{ - strings.Join(trimmed, ","), - key.Type(), - base64.StdEncoding.EncodeToString(key.Marshal()), - }, " ") -} - -// WriteKnownHost writes a known_hosts line to w for the supplied hostname, -// remote, and key. This is useful when writing a custom hostkey callback which -// wraps a callback obtained from this package to provide additional known_hosts -// management functionality. The hostname, remote, and key typically correspond -// to the callback's args. This function does not support writing -// @cert-authority lines. -func WriteKnownHost(w io.Writer, hostname string, remote net.Addr, key ssh.PublicKey) error { - // Always include hostname; only also include remote if it isn't a zero value - // and doesn't normalize to the same string as hostname. - hostnameNormalized := Normalize(hostname) - if strings.ContainsAny(hostnameNormalized, "\t ") { - return fmt.Errorf("knownhosts: hostname '%s' contains spaces", hostnameNormalized) - } - addresses := []string{hostnameNormalized} - remoteStrNormalized := Normalize(remote.String()) - if remoteStrNormalized != "[0.0.0.0]:0" && remoteStrNormalized != hostnameNormalized && - !strings.ContainsAny(remoteStrNormalized, "\t ") { - addresses = append(addresses, remoteStrNormalized) - } - line := Line(addresses, key) + "\n" - _, err := w.Write([]byte(line)) - return err -} - -// WriteKnownHostCA writes a @cert-authority line to w for the supplied host -// name/pattern and key. -func WriteKnownHostCA(w io.Writer, hostPattern string, key ssh.PublicKey) error { - encodedKey := base64.StdEncoding.EncodeToString(key.Marshal()) - _, err := fmt.Fprintf(w, "@cert-authority %s %s %s\n", hostPattern, key.Type(), encodedKey) - return err -} - -// fakePublicKey is used as part of the work-around for -// https://github.com/golang/go/issues/29286 -type fakePublicKey struct{} - -func (fakePublicKey) Type() string { - return "fake-public-key" -} - -func (fakePublicKey) Marshal() []byte { - return []byte("fake public key") -} - -func (fakePublicKey) Verify(_ []byte, _ *ssh.Signature) error { - return errors.New("Verify called on placeholder key") -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/pageant_windows.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/pageant_windows.go deleted file mode 100644 index a05a2d11..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/pageant_windows.go +++ /dev/null @@ -1,152 +0,0 @@ -// -// Copyright (c) 2014 David Mzareulyan -// -// 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. -// - -// Originally from: https://github.com/xanzy/ssh-agent/blob/main/pageant_windows.go -// MIT LICENSE: https://github.com/davidmz/go-pageant/blob/master/LICENSE.txt - -//go:build windows -// +build windows - -package sshagent - -// see https://github.com/Yasushi/putty/blob/master/windows/winpgntc.c#L155 -// see https://github.com/paramiko/paramiko/blob/master/paramiko/win_pageant.py - -import ( - "encoding/binary" - "errors" - "fmt" - "sync" - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -// Maximum size of message can be sent to pageant -const MaxMessageLen = 8192 - -var ( - ErrPageantNotFound = errors.New("pageant process not found") - ErrSendMessage = errors.New("error sending message") - - ErrMessageTooLong = errors.New("message too long") - ErrInvalidMessageFormat = errors.New("invalid message format") - ErrResponseTooLong = errors.New("response too long") -) - -const ( - agentCopydataID = 0x804e50ba - wmCopydata = 74 -) - -type copyData struct { - dwData uintptr - cbData uint32 - lpData unsafe.Pointer -} - -var ( - lock sync.Mutex - - user32dll = windows.NewLazySystemDLL("user32.dll") - winFindWindow = winAPI(user32dll, "FindWindowW") - winSendMessage = winAPI(user32dll, "SendMessageW") - - kernel32dll = windows.NewLazySystemDLL("kernel32.dll") - winGetCurrentThreadID = winAPI(kernel32dll, "GetCurrentThreadId") -) - -func winAPI(dll *windows.LazyDLL, funcName string) func(...uintptr) (uintptr, uintptr, error) { - proc := dll.NewProc(funcName) - return func(a ...uintptr) (uintptr, uintptr, error) { return proc.Call(a...) } -} - -// Query sends message msg to Pageant and returns response or error. -// 'msg' is raw agent request with length prefix -// Response is raw agent response with length prefix -func query(msg []byte) ([]byte, error) { - if len(msg) > MaxMessageLen { - return nil, ErrMessageTooLong - } - - msgLen := binary.BigEndian.Uint32(msg[:4]) - if len(msg) != int(msgLen)+4 { - return nil, ErrInvalidMessageFormat - } - - lock.Lock() - defer lock.Unlock() - - paWin := pageantWindow() - - if paWin == 0 { - return nil, ErrPageantNotFound - } - - thID, _, _ := winGetCurrentThreadID() - mapName := fmt.Sprintf("PageantRequest%08x", thID) - pMapName, _ := syscall.UTF16PtrFromString(mapName) - - mmap, err := syscall.CreateFileMapping(syscall.InvalidHandle, nil, syscall.PAGE_READWRITE, 0, MaxMessageLen+4, pMapName) - if err != nil { - return nil, err - } - defer syscall.CloseHandle(mmap) - - ptr, err := syscall.MapViewOfFile(mmap, syscall.FILE_MAP_WRITE, 0, 0, 0) - if err != nil { - return nil, err - } - defer syscall.UnmapViewOfFile(ptr) - - mmSlice := (*(*[MaxMessageLen]byte)(unsafe.Pointer(ptr)))[:] - - copy(mmSlice, msg) - - mapNameBytesZ := append([]byte(mapName), 0) - - cds := copyData{ - dwData: agentCopydataID, - cbData: uint32(len(mapNameBytesZ)), - lpData: unsafe.Pointer(&(mapNameBytesZ[0])), - } - - resp, _, _ := winSendMessage(paWin, wmCopydata, 0, uintptr(unsafe.Pointer(&cds))) - - if resp == 0 { - return nil, ErrSendMessage - } - - respLen := binary.BigEndian.Uint32(mmSlice[:4]) - if respLen > MaxMessageLen-4 { - return nil, ErrResponseTooLong - } - - respData := make([]byte, respLen+4) - copy(respData, mmSlice) - - return respData, nil -} - -func pageantWindow() uintptr { - nameP, _ := syscall.UTF16PtrFromString("Pageant") - h, _, _ := winFindWindow(uintptr(unsafe.Pointer(nameP)), uintptr(unsafe.Pointer(nameP))) - return h -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent.go deleted file mode 100644 index d0bf22b5..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent.go +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2015, Sander van Harmelen -// -// 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. -// - -// Originally from: https://github.com/xanzy/ssh-agent/blob/main/sshagent.go - -//go:build !windows -// +build !windows - -package sshagent - -import ( - "errors" - "fmt" - "net" - "os" - - "github.com/go-git/go-git/v6/utils/trace" - "golang.org/x/crypto/ssh/agent" -) - -// New returns a new agent.Agent that uses a unix socket -func New() (agent.Agent, net.Conn, error) { - if !Available() { - return nil, nil, errors.New("SSH agent requested but SSH_AUTH_SOCK not-specified") - } - - sshAuthSock := os.Getenv("SSH_AUTH_SOCK") - - trace.SSH.Printf("ssh: net.Dial unix sock %s", sshAuthSock) - conn, err := net.Dial("unix", sshAuthSock) - if err != nil { - return nil, nil, fmt.Errorf("error connecting to SSH_AUTH_SOCK: %v", err) - } - - return agent.NewClient(conn), conn, nil -} - -// Available returns true is a auth socket is defined -func Available() bool { - return os.Getenv("SSH_AUTH_SOCK") != "" -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent_windows.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent_windows.go deleted file mode 100644 index 979a8f02..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent/sshagent_windows.go +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2014 David Mzareulyan -// -// 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. -// - -// Originally from: https://github.com/xanzy/ssh-agent/blob/main/sshagent_windows.go -// MIT LICENSE: https://github.com/davidmz/go-pageant/blob/master/LICENSE.txt - -//go:build windows -// +build windows - -package sshagent - -import ( - "errors" - "io" - "net" - "sync" - - "github.com/Microsoft/go-winio" - "github.com/go-git/go-git/v6/utils/trace" - "golang.org/x/crypto/ssh/agent" -) - -const ( - sshAgentPipe = `\\.\pipe\openssh-ssh-agent` -) - -// Available returns true if Pageant is running -func Available() bool { - if pageantWindow() != 0 { - return true - } - - conn, err := winio.DialPipe(sshAgentPipe, nil) - if err != nil { - return false - } - conn.Close() - return true -} - -// New returns a new agent.Agent and the (custom) connection it uses -// to communicate with a running pagent.exe instance (see README.md) -func New() (agent.Agent, net.Conn, error) { - if pageantWindow() != 0 { - return agent.NewClient(&conn{}), nil, nil - } - trace.SSH.Printf("ssh: winio.DialPipe %s", sshAgentPipe) - conn, err := winio.DialPipe(sshAgentPipe, nil) - if err != nil { - return nil, nil, errors.New( - "SSH agent requested, but could not detect Pageant or Windows native SSH agent", - ) - } - return agent.NewClient(conn), nil, nil -} - -type conn struct { - sync.Mutex - buf []byte -} - -func (c *conn) Close() { - c.Lock() - defer c.Unlock() - c.buf = nil -} - -func (c *conn) Write(p []byte) (int, error) { - c.Lock() - defer c.Unlock() - - resp, err := query(p) - if err != nil { - return 0, err - } - - c.buf = append(c.buf, resp...) - - return len(p), nil -} - -func (c *conn) Read(p []byte) (int, error) { - c.Lock() - defer c.Unlock() - - if len(c.buf) == 0 { - return 0, io.EOF - } - - n := copy(p, c.buf) - c.buf = c.buf[n:] - - return n, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/transport.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/transport.go deleted file mode 100644 index 16f6d9a7..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/transport.go +++ /dev/null @@ -1,279 +0,0 @@ -// Package transport includes the implementation for different transport -// protocols. -// -// `Client` can be used to fetch and send packfiles to a git server. -// The `client` package provides higher level functions to instantiate the -// appropriate `Client` based on the repository URL. -// -// go-git supports HTTP and SSH (see `Protocols`), but you can also install -// your own protocols (see the `client` package). -// -// Each protocol has its own implementation of `Client`, but you should -// generally not use them directly, use `client.NewClient` instead. -package transport - -import ( - "bytes" - "errors" - "fmt" - "net/url" - "regexp" - "runtime" - "strconv" - "strings" - - giturl "github.com/go-git/go-git/v6/internal/url" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/protocol" - "github.com/go-git/go-git/v6/storage" -) - -var ( - ErrRepositoryNotFound = errors.New("repository not found") - ErrEmptyRemoteRepository = errors.New("remote repository is empty") - ErrNoChange = errors.New("no change") - ErrAuthenticationRequired = errors.New("authentication required") - ErrAuthorizationFailed = errors.New("authorization failed") - ErrEmptyUploadPackRequest = errors.New("empty git-upload-pack given") - ErrInvalidAuthMethod = errors.New("invalid auth method") - ErrAlreadyConnected = errors.New("session already established") - ErrInvalidRequest = errors.New("invalid request") -) - -// Transport can initiate git-upload-pack and git-receive-pack processes. -// It is implemented both by the client and the server, making this a RPC. -type Transport interface { - // NewSession returns a new session for an endpoint. - NewSession(storage.Storer, *Endpoint, AuthMethod) (Session, error) - - // SupportedProtocols returns a list of supported Git protocol versions by - // the transport client. - SupportedProtocols() []protocol.Version -} - -type AuthMethod interface { - fmt.Stringer - Name() string -} - -// Endpoint represents a Git URL in any supported protocol. -type Endpoint struct { - // Protocol is the protocol of the endpoint (e.g. git, https, file). - Protocol string - // User is the user. - User string - // Password is the password. - Password string - // Host is the host. - Host string - // Port is the port to connect, if 0 the default port for the given protocol - // will be used. - Port int - // Path is the repository path. - Path string - // InsecureSkipTLS skips ssl verify if protocol is https - InsecureSkipTLS bool - // CaBundle specify additional ca bundle with system cert pool - CaBundle []byte - // Proxy provides info required for connecting to a proxy. - Proxy ProxyOptions -} - -type ProxyOptions struct { - URL string - Username string - Password string -} - -func (o *ProxyOptions) Validate() error { - if o.URL != "" { - _, err := url.Parse(o.URL) - return err - } - return nil -} - -func (o *ProxyOptions) FullURL() (*url.URL, error) { - proxyURL, err := url.Parse(o.URL) - if err != nil { - return nil, err - } - if o.Username != "" { - if o.Password != "" { - proxyURL.User = url.UserPassword(o.Username, o.Password) - } else { - proxyURL.User = url.User(o.Username) - } - } - return proxyURL, nil -} - -var defaultPorts = map[string]int{ - "http": 80, - "https": 443, - "git": 9418, - "ssh": 22, -} - -var fileIssueWindows = regexp.MustCompile(`^/[A-Za-z]:(/|\\)`) - -// String returns a string representation of the Git URL. -func (u *Endpoint) String() string { - var buf bytes.Buffer - if u.Protocol != "" { - buf.WriteString(u.Protocol) - buf.WriteByte(':') - } - - if u.Protocol != "" || u.Host != "" || u.User != "" || u.Password != "" { - buf.WriteString("//") - - if u.User != "" || u.Password != "" { - buf.WriteString(url.PathEscape(u.User)) - if u.Password != "" { - buf.WriteByte(':') - buf.WriteString(url.PathEscape(u.Password)) - } - - buf.WriteByte('@') - } - - if u.Host != "" { - buf.WriteString(u.Host) - - if u.Port != 0 { - port, ok := defaultPorts[strings.ToLower(u.Protocol)] - if !ok || ok && port != u.Port { - fmt.Fprintf(&buf, ":%d", u.Port) - } - } - } - } - - if u.Path != "" && u.Path[0] != '/' && u.Host != "" { - buf.WriteByte('/') - } - - buf.WriteString(u.Path) - return buf.String() -} - -func NewEndpoint(endpoint string) (*Endpoint, error) { - if e, ok := parseSCPLike(endpoint); ok { - return e, nil - } - - if e, ok := parseFile(endpoint); ok { - return e, nil - } - - return parseURL(endpoint) -} - -func parseURL(endpoint string) (*Endpoint, error) { - if strings.HasPrefix(endpoint, "file://") { - endpoint = strings.TrimPrefix(endpoint, "file://") - - // When triple / is used, the path in Windows may end up having an - // additional / resulting in "/C:/Dir". - if runtime.GOOS == "windows" && - fileIssueWindows.MatchString(endpoint) { - endpoint = endpoint[1:] - } - return &Endpoint{ - Protocol: "file", - Path: endpoint, - }, nil - } - - u, err := url.Parse(endpoint) - if err != nil { - return nil, err - } - - if !u.IsAbs() { - return nil, plumbing.NewPermanentError(fmt.Errorf( - "invalid endpoint: %s", endpoint, - )) - } - - var user, pass string - if u.User != nil { - user = u.User.Username() - pass, _ = u.User.Password() - } - - host := u.Hostname() - if strings.Contains(host, ":") { - // IPv6 address - host = "[" + host + "]" - } - - return &Endpoint{ - Protocol: u.Scheme, - User: user, - Password: pass, - Host: host, - Port: getPort(u), - Path: getPath(u), - }, nil -} - -func getPort(u *url.URL) int { - p := u.Port() - if p == "" { - return 0 - } - - i, err := strconv.Atoi(p) - if err != nil { - return 0 - } - - return i -} - -func getPath(u *url.URL) string { - var res string = u.Path - if u.RawQuery != "" { - res += "?" + u.RawQuery - } - - if u.Fragment != "" { - res += "#" + u.Fragment - } - - return res -} - -func parseSCPLike(endpoint string) (*Endpoint, bool) { - if giturl.MatchesScheme(endpoint) || !giturl.MatchesScpLike(endpoint) { - return nil, false - } - - user, host, portStr, path := giturl.FindScpLikeComponents(endpoint) - port, err := strconv.Atoi(portStr) - if err != nil { - port = 22 - } - - return &Endpoint{ - Protocol: "ssh", - User: user, - Host: host, - Port: port, - Path: path, - }, true -} - -func parseFile(endpoint string) (*Endpoint, bool) { - if giturl.MatchesScheme(endpoint) { - return nil, false - } - - path := endpoint - return &Endpoint{ - Protocol: "file", - Path: path, - }, true -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/upload_pack.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/upload_pack.go deleted file mode 100644 index 17e8eda5..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/upload_pack.go +++ /dev/null @@ -1,358 +0,0 @@ -package transport - -import ( - "bufio" - "context" - "fmt" - "io" - "math" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/format/pktline" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/protocol" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband" - "github.com/go-git/go-git/v6/plumbing/revlist" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// UploadPackOptions is a set of options for the UploadPack service. -type UploadPackOptions struct { - GitProtocol string - AdvertiseRefs bool - StatelessRPC bool -} - -// UploadPack is a server command that serves the upload-pack service. -func UploadPack( - ctx context.Context, - st storage.Storer, - r io.ReadCloser, - w io.WriteCloser, - opts *UploadPackOptions, -) error { - if w == nil { - return fmt.Errorf("nil writer") - } - - w = ioutil.NewContextWriteCloser(ctx, w) - - if opts == nil { - opts = &UploadPackOptions{} - } - - if opts.AdvertiseRefs || !opts.StatelessRPC { - switch version := ProtocolVersion(opts.GitProtocol); version { - case protocol.V1: - if _, err := pktline.Writef(w, "version %d\n", version); err != nil { - return err - } - // TODO: support version 2 - case protocol.V0, protocol.V2: - default: - return fmt.Errorf("%w: %q", ErrUnsupportedVersion, version) - } - - if err := AdvertiseReferences(ctx, st, w, UploadPackService, opts.StatelessRPC); err != nil { - return fmt.Errorf("advertising references: %w", err) - } - } - - if opts.AdvertiseRefs { - // Done, there's nothing else to do - return nil - } - - if r == nil { - return fmt.Errorf("nil reader") - } - - r = ioutil.NewContextReadCloser(ctx, r) - - rd := bufio.NewReader(r) - l, _, err := pktline.PeekLine(rd) - if err != nil { - return fmt.Errorf("peeking line: %w", err) - } - - // In case the client has nothing to send, it sends a flush packet to - // indicate that it is done sending data. In that case, we're done - // here. - if l == pktline.Flush { - return nil - } - - var done bool - var haves []plumbing.Hash - var upreq *packp.UploadRequest - var havesWithRef map[plumbing.Hash][]plumbing.Hash - var multiAck, multiAckDetailed bool - var caps *capability.List - var wants []plumbing.Hash - firstRound := true - for !done { - writec := make(chan error) - if firstRound || opts.StatelessRPC { - upreq = packp.NewUploadRequest() - if err := upreq.Decode(rd); err != nil { - return fmt.Errorf("decoding upload-request: %w", err) - } - - wants = upreq.Wants - caps = upreq.Capabilities - - if err := r.Close(); err != nil { - return fmt.Errorf("closing reader: %w", err) - } - - // Find common commits/objects - havesWithRef, err = revlist.ObjectsWithRef(st, wants, nil) - if err != nil { - return fmt.Errorf("getting objects with ref: %w", err) - } - - // Encode objects to packfile and write to client - multiAck = caps.Supports(capability.MultiACK) - multiAckDetailed = caps.Supports(capability.MultiACKDetailed) - - go func() { - // TODO: support deepen-since, and deepen-not - var shupd packp.ShallowUpdate - if !upreq.Depth.IsZero() { - switch depth := upreq.Depth.(type) { - case packp.DepthCommits: - if err := getShallowCommits(st, wants, int(depth), &shupd); err != nil { - writec <- fmt.Errorf("getting shallow commits: %w", err) - return - } - default: - writec <- fmt.Errorf("unsupported depth type %T", upreq.Depth) - return - } - - if err := shupd.Encode(w); err != nil { - writec <- fmt.Errorf("sending shallow-update: %w", err) - return - } - } - - writec <- nil - }() - } - - if err := <-writec; err != nil { - return err - } - - var uphav packp.UploadHaves - if err := uphav.Decode(rd); err != nil { - return fmt.Errorf("decoding upload-haves: %w", err) - } - - if err := r.Close(); err != nil { - return fmt.Errorf("closing reader: %w", err) - } - - haves = append(haves, uphav.Haves...) - done = uphav.Done - - common := map[plumbing.Hash]struct{}{} - var ack packp.ACK - var acks []packp.ACK - for _, hu := range uphav.Haves { - refs, ok := havesWithRef[hu] - if ok { - for _, ref := range refs { - common[ref] = struct{}{} - } - } - - var status packp.ACKStatus - if multiAckDetailed { - status = packp.ACKCommon - if !ok { - status = packp.ACKReady - } - } else if multiAck { - status = packp.ACKContinue - } - - if ok || multiAck || multiAckDetailed { - ack = packp.ACK{Hash: hu, Status: status} - acks = append(acks, ack) - if !multiAck && !multiAckDetailed { - break - } - } - } - - go func() { - defer close(writec) - - if len(haves) > 0 { - // Encode ACKs to client when we have haves - srvrsp := packp.ServerResponse{ACKs: acks} - if err := srvrsp.Encode(w); err != nil { - writec <- fmt.Errorf("sending acks server-response: %w", err) - return - } - } - - if !done { - if multiAck || multiAckDetailed { - // Encode a NAK for multi-ack - srvrsp := packp.ServerResponse{} - if err := srvrsp.Encode(w); err != nil { - writec <- fmt.Errorf("sending nak server-response: %w", err) - return - } - } - } else if !ack.Hash.IsZero() && (multiAck || multiAckDetailed) { - // We're done, send the final ACK - ack.Status = 0 - srvrsp := packp.ServerResponse{ACKs: []packp.ACK{ack}} - if err := srvrsp.Encode(w); err != nil { - writec <- fmt.Errorf("sending final ack server-response: %w", err) - return - } - } else if ack.Hash.IsZero() { - // We don't have multi-ack and there are no haves. Encode a NAK. - srvrsp := packp.ServerResponse{} - if err := srvrsp.Encode(w); err != nil { - writec <- fmt.Errorf("sending final nak server-response: %w", err) - return - } - } - - writec <- nil - }() - - if err := <-writec; err != nil { - return err - } - - firstRound = false - } - - // Done with the request, now close the reader - // to indicate that we are done reading from it. - if err := r.Close(); err != nil { - return fmt.Errorf("closing reader: %w", err) - } - - objs, err := objectsToUpload(st, wants, haves) - if err != nil { - w.Close() //nolint:errcheck - return fmt.Errorf("getting objects to upload: %w", err) - } - - var ( - useSideband bool - writer io.Writer = w - ) - if caps.Supports(capability.Sideband64k) { - writer = sideband.NewMuxer(sideband.Sideband64k, w) - useSideband = true - } else if caps.Supports(capability.Sideband) { - writer = sideband.NewMuxer(sideband.Sideband, w) - useSideband = true - } - - // TODO: Support shallow-file - // TODO: Support thin-pack - e := packfile.NewEncoder(writer, st, false) - _, err = e.Encode(objs, 10) - if err != nil { - return fmt.Errorf("encoding packfile: %w", err) - } - - if useSideband { - if err := pktline.WriteFlush(w); err != nil { - return fmt.Errorf("flushing sideband: %w", err) - } - } - - if err := w.Close(); err != nil { - return fmt.Errorf("closing writer: %w", err) - } - - return nil -} - -func objectsToUpload(st storage.Storer, wants, haves []plumbing.Hash) ([]plumbing.Hash, error) { - return revlist.Objects(st, wants, haves) -} - -func getShallowCommits(st storage.Storer, heads []plumbing.Hash, depth int, upd *packp.ShallowUpdate) error { - var i, curDepth int - var commit *object.Commit - depths := map[*object.Commit]int{} - stack := []object.Object{} - - for commit != nil || i < len(heads) || len(stack) > 0 { - if commit == nil { - if i < len(heads) { - obj, err := st.EncodedObject(plumbing.CommitObject, heads[i]) - i++ - if err != nil { - continue - } - - commit, err = object.DecodeCommit(st, obj) - if err != nil { - commit = nil - continue - } - - depths[commit] = 0 - curDepth = 0 - } else if len(stack) > 0 { - commit = stack[len(stack)-1].(*object.Commit) - stack = stack[:len(stack)-1] - curDepth = depths[commit] - } - } - - curDepth++ - - if depth != math.MaxInt && curDepth >= depth { - upd.Shallows = append(upd.Shallows, commit.Hash) - commit = nil - continue - } - - upd.Unshallows = append(upd.Unshallows, commit.Hash) - - parents := commit.Parents() - commit = nil - for { - parent, err := parents.Next() - if err == io.EOF { - break - } - if err != nil { - return err - } - - if depths[parent] != 0 && curDepth >= depths[parent] { - continue - } - - depths[parent] = curDepth - - if _, err := parents.Next(); err == nil { - stack = append(stack, parent) - } else { - commit = parent - curDepth = depths[commit] - } - } - - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/plumbing/transport/version.go b/vendor/github.com/go-git/go-git/v6/plumbing/transport/version.go deleted file mode 100644 index d68c31ef..00000000 --- a/vendor/github.com/go-git/go-git/v6/plumbing/transport/version.go +++ /dev/null @@ -1,47 +0,0 @@ -package transport - -import ( - "strings" - - "github.com/go-git/go-git/v6/plumbing/format/pktline" - "github.com/go-git/go-git/v6/plumbing/protocol" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// DiscoverVersion reads the first pktline from the reader to determine the -// protocol version. This is used by the client to determine the protocol -// version of the server. -func DiscoverVersion(r ioutil.ReadPeeker) (protocol.Version, error) { - ver := protocol.V0 - _, pktb, err := pktline.PeekLine(r) - if err != nil { - return ver, err - } - - pkt := strings.TrimSpace(string(pktb)) - if strings.HasPrefix(pkt, "version ") { - // Consume the version packet - pktline.ReadLine(r) // nolint:errcheck - if v, _ := protocol.Parse(pkt[8:]); v > ver { - ver = protocol.Version(v) - } - } - - return ver, nil -} - -// ProtocolVersion tries to find the version parameter in the protocol string. -// This expects the protocol string from the GIT_PROTOCOL environment variable. -// This is used by the server to determine the protocol version requested by -// the client. -func ProtocolVersion(p string) protocol.Version { - var ver protocol.Version - for _, param := range strings.Split(p, ":") { - if strings.HasPrefix(param, "version=") { - if v, _ := protocol.Parse(param[8:]); v > ver { - ver = protocol.Version(v) - } - } - } - return ver -} diff --git a/vendor/github.com/go-git/go-git/v6/prune.go b/vendor/github.com/go-git/go-git/v6/prune.go deleted file mode 100644 index 0aee67ab..00000000 --- a/vendor/github.com/go-git/go-git/v6/prune.go +++ /dev/null @@ -1,66 +0,0 @@ -package git - -import ( - "errors" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -type PruneHandler func(unreferencedObjectHash plumbing.Hash) error -type PruneOptions struct { - // OnlyObjectsOlderThan if set to non-zero value - // selects only objects older than the time provided. - OnlyObjectsOlderThan time.Time - // Handler is called on matching objects - Handler PruneHandler -} - -var ErrLooseObjectsNotSupported = errors.New("loose objects not supported") - -// DeleteObject deletes an object from a repository. -// The type conveniently matches PruneHandler. -func (r *Repository) DeleteObject(hash plumbing.Hash) error { - los, ok := r.Storer.(storer.LooseObjectStorer) - if !ok { - return ErrLooseObjectsNotSupported - } - - return los.DeleteLooseObject(hash) -} - -func (r *Repository) Prune(opt PruneOptions) error { - los, ok := r.Storer.(storer.LooseObjectStorer) - if !ok { - return ErrLooseObjectsNotSupported - } - - pw := newObjectWalker(r.Storer) - err := pw.walkAllRefs() - if err != nil { - return err - } - // Now walk all (loose) objects in storage. - return los.ForEachObjectHash(func(hash plumbing.Hash) error { - // Get out if we have seen this object. - if pw.isSeen(hash) { - return nil - } - // Otherwise it is a candidate for pruning. - // Check out for too new objects next. - if !opt.OnlyObjectsOlderThan.IsZero() { - // Errors here are non-fatal. The object may be e.g. packed. - // Or concurrently deleted. Skip such objects. - t, err := los.LooseObjectTime(hash) - if err != nil { - return nil - } - // Skip too new objects. - if !t.Before(opt.OnlyObjectsOlderThan) { - return nil - } - } - return opt.Handler(hash) - }) -} diff --git a/vendor/github.com/go-git/go-git/v6/remote.go b/vendor/github.com/go-git/go-git/v6/remote.go deleted file mode 100644 index eaf91e1a..00000000 --- a/vendor/github.com/go-git/go-git/v6/remote.go +++ /dev/null @@ -1,1384 +0,0 @@ -package git - -import ( - "context" - "errors" - "fmt" - "io" - "strings" - "time" - - "github.com/go-git/go-billy/v6/osfs" - "github.com/go-git/go-git/v6/config" - "github.com/go-git/go-git/v6/internal/reference" - "github.com/go-git/go-git/v6/internal/repository" - "github.com/go-git/go-git/v6/internal/url" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/protocol/packp" - "github.com/go-git/go-git/v6/plumbing/protocol/packp/capability" - "github.com/go-git/go-git/v6/plumbing/revlist" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/plumbing/transport" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/storage/filesystem" - "github.com/go-git/go-git/v6/storage/memory" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -var ( - NoErrAlreadyUpToDate = errors.New("already up-to-date") - ErrDeleteRefNotSupported = errors.New("server does not support delete-refs") - ErrForceNeeded = errors.New("some refs were not updated") - ErrExactSHA1NotSupported = errors.New("server does not support exact SHA1 refspec") - ErrEmptyUrls = errors.New("URLs cannot be empty") - ErrRemoteRefNotFound = errors.New("couldn't find remote ref") -) - -const ( - // This describes the maximum number of commits to walk when - // computing the haves to send to a server, for each ref in the - // repo containing this remote, when not using the multi-ack - // protocol. Setting this to 0 means there is no limit. - maxHavesToVisitPerRef = 100 - - // peeledSuffix is the suffix used to build peeled reference names. - peeledSuffix = "^{}" -) - -// Remote represents a connection to a remote repository. -type Remote struct { - c *config.RemoteConfig - s storage.Storer -} - -// NewRemote creates a new Remote. -// The intended purpose is to use the Remote for tasks such as listing remote references (like using git ls-remote). -// Otherwise Remotes should be created via the use of a Repository. -func NewRemote(s storage.Storer, c *config.RemoteConfig) *Remote { - return &Remote{s: s, c: c} -} - -// Config returns the RemoteConfig object used to instantiate this Remote. -func (r *Remote) Config() *config.RemoteConfig { - return r.c -} - -func (r *Remote) String() string { - var fetch, push string - if len(r.c.URLs) > 0 { - fetch = r.c.URLs[0] - push = r.c.URLs[len(r.c.URLs)-1] - } - - return fmt.Sprintf("%s\t%s (fetch)\n%[1]s\t%[3]s (push)", r.c.Name, fetch, push) -} - -// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if the -// remote was already up-to-date. -func (r *Remote) Push(o *PushOptions) error { - return r.PushContext(context.Background(), o) -} - -// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if -// the remote was already up-to-date. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) { - if err := o.Validate(); err != nil { - return err - } - - if o.RemoteName != r.c.Name { - return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name) - } - - if o.RemoteURL == "" && len(r.c.URLs) > 0 { - o.RemoteURL = r.c.URLs[len(r.c.URLs)-1] - } - - c, ep, err := newClient(o.RemoteURL, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions) - if err != nil { - return err - } - - s, err := c.NewSession(r.s, ep, o.Auth) - if err != nil { - return err - } - - conn, err := s.Handshake(ctx, transport.ReceivePackService) - if err != nil { - return err - } - - rRefs, err := conn.GetRemoteRefs(ctx) - if err != nil { - return err - } - - remoteRefs := referenceStorageFromRefs(rRefs, true) - if err := r.checkRequireRemoteRefs(o.RequireRemoteRefs, remoteRefs); err != nil { - return err - } - - return r.sendPack(ctx, conn, remoteRefs, o) -} - -func (r *Remote) sendPack(ctx context.Context, conn transport.Connection, remoteRefs storer.ReferenceStorer, o *PushOptions) error { - isDelete := false - allDelete := true - for _, rs := range o.RefSpecs { - if rs.IsDelete() { - isDelete = true - } else { - allDelete = false - } - if isDelete && !allDelete { - break - } - } - - // TODO: support delete-refs - caps := conn.Capabilities() // server capabilities - if isDelete && !caps.Supports(capability.DeleteRefs) { - return ErrDeleteRefNotSupported - } - - if o.Force { - for i := 0; i < len(o.RefSpecs); i++ { - rs := &o.RefSpecs[i] - if !rs.IsForceUpdate() && !rs.IsDelete() { - o.RefSpecs[i] = config.RefSpec("+" + rs.String()) - } - } - } - - localRefs, err := reference.References(r.s) - if err != nil { - return err - } - - cmds := make([]*packp.Command, 0) - if err := r.addReferencesToUpdate(o.RefSpecs, localRefs, remoteRefs, &cmds, o.Prune, o.ForceWithLease); err != nil { - return err - } - - if o.FollowTags { - if err := r.addReachableTags(localRefs, remoteRefs, &cmds); err != nil { - return err - } - } - - if len(cmds) == 0 { - return NoErrAlreadyUpToDate - } - - objects := objectsToPush(cmds) - haves, err := referencesToHashes(remoteRefs) - if err != nil { - return err - } - - stop, err := r.s.Shallow() - if err != nil { - return err - } - - // if we have shallow we should include this as part of the objects that - // we are aware. - haves = append(haves, stop...) - - var hashesToPush []plumbing.Hash - // Avoid the expensive revlist operation if we're only doing deletes. - if !allDelete { - if url.IsLocalEndpoint(o.RemoteURL) { - // If we're are pushing to a local repo, it might be much - // faster to use a local storage layer to get the commits - // to ignore, when calculating the object revlist. - localStorer := filesystem.NewStorage( - osfs.New(o.RemoteURL, osfs.WithBoundOS()), cache.NewObjectLRUDefault()) - hashesToPush, err = revlist.ObjectsWithStorageForIgnores( - r.s, localStorer, objects, haves) - } else { - hashesToPush, err = revlist.Objects(r.s, objects, haves) - } - if err != nil { - return err - } - } - - if len(hashesToPush) == 0 { - allDelete = true - for _, command := range cmds { - if command.Action() != packp.Delete { - allDelete = false - break - } - } - } - - if err := pushHashes(ctx, conn, r.s, cmds, hashesToPush, allDelete, o); err != nil { - return err - } - - return r.updateRemoteReferenceStorage(cmds) -} - -func (r *Remote) useRefDeltas(ar *packp.AdvRefs) bool { - return !ar.Capabilities.Supports(capability.OFSDelta) -} - -func (r *Remote) addReachableTags(localRefs []*plumbing.Reference, remoteRefs storer.ReferenceStorer, cmds *[]*packp.Command) error { - tags := make(map[plumbing.Reference]struct{}) - // get a list of all tags locally - for _, ref := range localRefs { - if strings.HasPrefix(string(ref.Name()), "refs/tags") { - tags[*ref] = struct{}{} - } - } - - remoteRefIter, err := remoteRefs.IterReferences() - if err != nil { - return err - } - - // remove any that are already on the remote - if err := remoteRefIter.ForEach(func(reference *plumbing.Reference) error { - delete(tags, *reference) - return nil - }); err != nil { - return err - } - - for tag := range tags { - tagObject, err := object.GetObject(r.s, tag.Hash()) - var tagCommit *object.Commit - if err != nil { - return fmt.Errorf("get tag object: %w", err) - } - - if tagObject.Type() != plumbing.TagObject { - continue - } - - annotatedTag, ok := tagObject.(*object.Tag) - if !ok { - return errors.New("could not get annotated tag object") - } - - tagCommit, err = object.GetCommit(r.s, annotatedTag.Target) - if err != nil { - return fmt.Errorf("get annotated tag commit: %w", err) - } - - // only include tags that are reachable from one of the refs - // already being pushed - for _, cmd := range *cmds { - if tag.Name() == cmd.Name { - continue - } - - if strings.HasPrefix(cmd.Name.String(), "refs/tags") { - continue - } - - c, err := object.GetCommit(r.s, cmd.New) - if err != nil { - return fmt.Errorf("get commit %v: %w", cmd.Name, err) - } - - if isAncestor, err := tagCommit.IsAncestor(c); err == nil && isAncestor { - *cmds = append(*cmds, &packp.Command{Name: tag.Name(), New: tag.Hash()}) - } - } - } - - return nil -} - -func (r *Remote) updateRemoteReferenceStorage( - cmds []*packp.Command, -) error { - for _, spec := range r.c.Fetch { - for _, c := range cmds { - if !spec.Match(c.Name) { - continue - } - - local := spec.Dst(c.Name) - ref := plumbing.NewHashReference(local, c.New) - switch c.Action() { - case packp.Create, packp.Update: - if err := r.s.SetReference(ref); err != nil { - return err - } - case packp.Delete: - if err := r.s.RemoveReference(local); err != nil { - return err - } - } - } - } - - return nil -} - -// FetchContext fetches references along with the objects necessary to complete -// their histories. -// -// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are -// no changes to be fetched, or an error. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func (r *Remote) FetchContext(ctx context.Context, o *FetchOptions) error { - _, err := r.fetch(ctx, o) - return err -} - -// Fetch fetches references along with the objects necessary to complete their -// histories. -// -// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are -// no changes to be fetched, or an error. -func (r *Remote) Fetch(o *FetchOptions) error { - return r.FetchContext(context.Background(), o) -} - -func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.ReferenceStorer, err error) { - if o.RemoteName == "" { - o.RemoteName = r.c.Name - } - - if err = o.Validate(); err != nil { - return nil, err - } - - if len(o.RefSpecs) == 0 { - o.RefSpecs = r.c.Fetch - } - - if o.RemoteURL == "" { - o.RemoteURL = r.c.URLs[0] - } - - c, ep, err := newClient(o.RemoteURL, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions) - if err != nil { - return nil, err - } - - sess, err := c.NewSession(r.s, ep, o.Auth) - if err != nil { - return nil, err - } - - conn, err := sess.Handshake(ctx, transport.UploadPackService) - if err != nil { - return nil, err - } - - if err := r.isSupportedRefSpec(o.RefSpecs, conn.Capabilities()); err != nil { - return nil, err - } - - rRefs, err := conn.GetRemoteRefs(ctx) - if err != nil { - return nil, err - } - - remoteRefs := referenceStorageFromRefs(rRefs, true) - localRefs, err := reference.References(r.s) - if err != nil { - return nil, err - } - refs, specToRefs, err := calculateRefs(o.RefSpecs, remoteRefs, o.Tags) - if err != nil { - return nil, err - } - - var shallows []plumbing.Hash - if o.Depth != 0 { - shallows, err = r.s.Shallow() - if err != nil { - return nil, err - } - } - - isWildcard := true - for _, s := range o.RefSpecs { - if !s.IsWildcard() { - isWildcard = false - break - } - } - - var haves []plumbing.Hash - wants, _ := getWants(r.s, refs, o.Depth) - if len(wants) > 0 { - haves, err = getHaves(localRefs, remoteRefs, r.s, o.Depth) - if err != nil { - return nil, err - } - - req := &transport.FetchRequest{ - Wants: wants, - Haves: haves, - Depth: o.Depth, - Progress: o.Progress, - IncludeTags: isWildcard && o.Tags == plumbing.TagFollowing, - Filter: o.Filter, - } - - if err := conn.Fetch(ctx, req); err != nil && !errors.Is(err, transport.ErrNoChange) { - // Note: We receive ErrNoChange when remote is the same as local. At - // this point, we have everything we're asking for. - return nil, err - } - } - - if err := conn.Close(); err != nil { - return nil, fmt.Errorf("error closing connection: %w", err) - } - - var updatedPrune bool - if o.Prune { - updatedPrune, err = r.pruneRemotes(o.RefSpecs, localRefs, remoteRefs) - if err != nil { - return nil, err - } - } - - updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, specToRefs, o.Tags, o.Force) - if err != nil { - return nil, err - } - - if !updated { - updated, err = depthChanged(shallows, r.s) - if err != nil { - return nil, fmt.Errorf("error checking depth change: %v", err) - } - } - - if !updated && !updatedPrune { - // No references updated, but may have fetched new objects, check if we now have any of our wants - for _, hash := range wants { - exists, _ := objectExists(r.s, hash) - if exists { - updated = true - break - } - } - - if !updated { - return remoteRefs, NoErrAlreadyUpToDate - } - } - - return remoteRefs, nil -} - -func referenceStorageFromRefs(refs []*plumbing.Reference, filterPeeled bool) memory.ReferenceStorage { - refStore := memory.ReferenceStorage{} - for _, ref := range refs { - if filterPeeled && strings.HasSuffix(ref.Name().String(), peeledSuffix) { - continue - } - refStore.SetReference(ref) // nolint: errcheck - } - return refStore -} - -func depthChanged(before []plumbing.Hash, s storage.Storer) (bool, error) { - after, err := s.Shallow() - if err != nil { - return false, err - } - - if len(before) != len(after) { - return true, nil - } - - bm := make(map[plumbing.Hash]bool, len(before)) - for _, b := range before { - bm[b] = true - } - for _, a := range after { - if _, ok := bm[a]; !ok { - return true, nil - } - } - - return false, nil -} - -func newClient(url string, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.Transport, *transport.Endpoint, error) { - ep, err := transport.NewEndpoint(url) - if err != nil { - return nil, nil, err - } - ep.InsecureSkipTLS = insecure - ep.CaBundle = cabundle - ep.Proxy = proxyOpts - - c, err := transport.Get(ep.Protocol) - if err != nil { - return nil, nil, err - } - - return c, ep, err -} - -func (r *Remote) pruneRemotes(specs []config.RefSpec, localRefs []*plumbing.Reference, remoteRefs storer.ReferenceStorer) (bool, error) { - var updatedPrune bool - for _, spec := range specs { - rev := spec.Reverse() - for _, ref := range localRefs { - if !rev.Match(ref.Name()) { - continue - } - _, err := remoteRefs.Reference(rev.Dst(ref.Name())) - if errors.Is(err, plumbing.ErrReferenceNotFound) { - updatedPrune = true - err := r.s.RemoveReference(ref.Name()) - if err != nil { - return false, err - } - } - } - } - return updatedPrune, nil -} - -func (r *Remote) addReferencesToUpdate( - refspecs []config.RefSpec, - localRefs []*plumbing.Reference, - remoteRefs storer.ReferenceStorer, - cmds *[]*packp.Command, - prune bool, - forceWithLease *ForceWithLease, -) error { - // This references dictionary will be used to search references by name. - refsDict := make(map[string]*plumbing.Reference) - for _, ref := range localRefs { - refsDict[ref.Name().String()] = ref - } - - for _, rs := range refspecs { - if rs.IsDelete() { - if err := r.deleteReferences(rs, remoteRefs, refsDict, cmds, false); err != nil { - return err - } - } else { - err := r.addOrUpdateReferences(rs, localRefs, refsDict, remoteRefs, cmds, forceWithLease) - if err != nil { - return err - } - - if prune { - if err := r.deleteReferences(rs, remoteRefs, refsDict, cmds, true); err != nil { - return err - } - } - } - } - - return nil -} - -func (r *Remote) addOrUpdateReferences( - rs config.RefSpec, - localRefs []*plumbing.Reference, - refsDict map[string]*plumbing.Reference, - remoteRefs storer.ReferenceStorer, - cmds *[]*packp.Command, - forceWithLease *ForceWithLease, -) error { - // If it is not a wildcard refspec we can directly search for the reference - // in the references dictionary. - if !rs.IsWildcard() { - ref, ok := refsDict[rs.Src()] - if !ok { - object, err := object.GetObject(r.s, plumbing.NewHash(rs.Src())) - if err == nil { - return r.addObject(rs, remoteRefs, object.ID(), cmds) - } - return nil - } - - return r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, cmds, forceWithLease) - } - - for _, ref := range localRefs { - err := r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, cmds, forceWithLease) - if err != nil { - return err - } - } - - return nil -} - -func (r *Remote) deleteReferences(rs config.RefSpec, - remoteRefs storer.ReferenceStorer, - refsDict map[string]*plumbing.Reference, - cmds *[]*packp.Command, - prune bool, -) error { - iter, err := remoteRefs.IterReferences() - if err != nil { - return err - } - - return iter.ForEach(func(ref *plumbing.Reference) error { - if ref.Type() != plumbing.HashReference { - return nil - } - - if prune { - rs := rs.Reverse() - if !rs.Match(ref.Name()) { - return nil - } - - if _, ok := refsDict[rs.Dst(ref.Name()).String()]; ok { - return nil - } - } else if rs.Dst("") != ref.Name() { - return nil - } - - cmd := &packp.Command{ - Name: ref.Name(), - Old: ref.Hash(), - New: plumbing.ZeroHash, - } - *cmds = append(*cmds, cmd) - return nil - }) -} - -func (r *Remote) addObject(rs config.RefSpec, - remoteRefs storer.ReferenceStorer, localObject plumbing.Hash, - cmds *[]*packp.Command, -) error { - if rs.IsWildcard() { - return errors.New("can't use wildcard together with hash refspecs") - } - - cmd := &packp.Command{ - Name: rs.Dst(""), - Old: plumbing.ZeroHash, - New: localObject, - } - remoteRef, err := remoteRefs.Reference(cmd.Name) - if err == nil { - if remoteRef.Type() != plumbing.HashReference { - // TODO: check actual git behavior here - return nil - } - - cmd.Old = remoteRef.Hash() - } else if err != plumbing.ErrReferenceNotFound { - return err - } - if cmd.Old == cmd.New { - return nil - } - if !rs.IsForceUpdate() { - if err := checkFastForwardUpdate(r.s, remoteRefs, cmd); err != nil { - return err - } - } - - *cmds = append(*cmds, cmd) - return nil -} - -func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec, - remoteRefs storer.ReferenceStorer, localRef *plumbing.Reference, - cmds *[]*packp.Command, forceWithLease *ForceWithLease, -) error { - if localRef.Type() != plumbing.HashReference { - return nil - } - - if !rs.Match(localRef.Name()) { - return nil - } - - cmd := &packp.Command{ - Name: rs.Dst(localRef.Name()), - Old: plumbing.ZeroHash, - New: localRef.Hash(), - } - - remoteRef, err := remoteRefs.Reference(cmd.Name) - if err == nil { - if remoteRef.Type() != plumbing.HashReference { - // TODO: check actual git behavior here - return nil - } - - cmd.Old = remoteRef.Hash() - } else if err != plumbing.ErrReferenceNotFound { - return err - } - - if cmd.Old == cmd.New { - return nil - } - - if forceWithLease != nil { - if err = r.checkForceWithLease(localRef, cmd, forceWithLease); err != nil { - return err - } - } else if !rs.IsForceUpdate() { - if err := checkFastForwardUpdate(r.s, remoteRefs, cmd); err != nil { - return err - } - } - - *cmds = append(*cmds, cmd) - return nil -} - -func (r *Remote) checkForceWithLease(localRef *plumbing.Reference, cmd *packp.Command, forceWithLease *ForceWithLease) error { - remotePrefix := fmt.Sprintf("refs/remotes/%s/", r.Config().Name) - - ref, err := storer.ResolveReference( - r.s, - plumbing.ReferenceName(remotePrefix+strings.ReplaceAll(localRef.Name().String(), "refs/heads/", ""))) - if err != nil { - return err - } - - if forceWithLease.RefName.String() == "" || (forceWithLease.RefName == cmd.Name) { - expectedOID := ref.Hash() - - if !forceWithLease.Hash.IsZero() { - expectedOID = forceWithLease.Hash - } - - if cmd.Old != expectedOID { - return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String()) - } - } - - return nil -} - -func getRemoteRefsFromStorer(remoteRefStorer storer.ReferenceStorer) ( - map[plumbing.Hash]bool, error, -) { - remoteRefs := map[plumbing.Hash]bool{} - iter, err := remoteRefStorer.IterReferences() - if err != nil { - return nil, err - } - err = iter.ForEach(func(ref *plumbing.Reference) error { - if ref.Type() != plumbing.HashReference { - return nil - } - remoteRefs[ref.Hash()] = true - return nil - }) - if err != nil { - return nil, err - } - return remoteRefs, nil -} - -// getHavesFromRef populates the given `haves` map with the given -// reference, and up to `maxHavesToVisitPerRef` ancestor commits. -func getHavesFromRef( - ref *plumbing.Reference, - remoteRefs map[plumbing.Hash]bool, - s storage.Storer, - haves map[plumbing.Hash]bool, - depth int, -) error { - h := ref.Hash() - if haves[h] { - return nil - } - - commit, err := object.GetCommit(s, h) - if err != nil { - if !errors.Is(err, plumbing.ErrObjectNotFound) { - // Ignore the error if this isn't a commit. - haves[ref.Hash()] = true - } - return nil - } - - // Until go-git supports proper commit negotiation during an - // upload pack request, include up to `maxHavesToVisitPerRef` - // commits from the history of each ref. - walker := object.NewCommitPreorderIter(commit, haves, nil) - toVisit := maxHavesToVisitPerRef - // But only need up to the requested depth - if depth > 0 && depth < maxHavesToVisitPerRef { - toVisit = depth - } - // It is safe to ignore any error here as we are just trying to find the references that we already have - // An example of a legitimate failure is we have a shallow clone and don't have the previous commit(s) - _ = walker.ForEach(func(c *object.Commit) error { - haves[c.Hash] = true - toVisit-- - // If toVisit starts out at 0 (indicating there is no - // max), then it will be negative here and we won't stop - // early. - if toVisit == 0 || remoteRefs[c.Hash] { - return storer.ErrStop - } - return nil - }) - - return nil -} - -func getHaves( - localRefs []*plumbing.Reference, - remoteRefStorer storer.ReferenceStorer, - s storage.Storer, - depth int, -) ([]plumbing.Hash, error) { - haves := map[plumbing.Hash]bool{} - - // Build a map of all the remote references, to avoid loading too - // many parent commits for references we know don't need to be - // transferred. - remoteRefs, err := getRemoteRefsFromStorer(remoteRefStorer) - if err != nil { - return nil, err - } - - for _, ref := range localRefs { - if haves[ref.Hash()] { - continue - } - - if ref.Type() != plumbing.HashReference { - continue - } - - err = getHavesFromRef(ref, remoteRefs, s, haves, depth) - if err != nil { - return nil, err - } - } - - var result []plumbing.Hash - for h := range haves { - result = append(result, h) - } - - return result, nil -} - -const refspecAllTags = "+refs/tags/*:refs/tags/*" - -func calculateRefs( - spec []config.RefSpec, - remoteRefs storer.ReferenceStorer, - tagMode plumbing.TagMode, -) (memory.ReferenceStorage, [][]*plumbing.Reference, error) { - if tagMode == plumbing.AllTags { - spec = append(spec, refspecAllTags) - } - - refs := make(memory.ReferenceStorage) - // list of references matched for each spec - specToRefs := make([][]*plumbing.Reference, len(spec)) - for i := range spec { - var err error - specToRefs[i], err = doCalculateRefs(spec[i], remoteRefs, refs) - if err != nil { - return nil, nil, err - } - } - - return refs, specToRefs, nil -} - -func doCalculateRefs( - s config.RefSpec, - remoteRefs storer.ReferenceStorer, - refs memory.ReferenceStorage, -) ([]*plumbing.Reference, error) { - var refList []*plumbing.Reference - - if s.IsExactSHA1() { - ref := plumbing.NewHashReference(s.Dst(""), plumbing.NewHash(s.Src())) - - refList = append(refList, ref) - return refList, refs.SetReference(ref) - } - - var matched bool - onMatched := func(ref *plumbing.Reference) error { - if ref.Type() == plumbing.SymbolicReference { - target, err := storer.ResolveReference(remoteRefs, ref.Name()) - if err != nil { - return err - } - - ref = plumbing.NewHashReference(ref.Name(), target.Hash()) - } - - if ref.Type() != plumbing.HashReference { - return nil - } - - matched = true - refList = append(refList, ref) - return refs.SetReference(ref) - } - - var ret error - if s.IsWildcard() { - iter, err := remoteRefs.IterReferences() - if err != nil { - return nil, err - } - ret = iter.ForEach(func(ref *plumbing.Reference) error { - if !s.Match(ref.Name()) { - return nil - } - - return onMatched(ref) - }) - } else { - var resolvedRef *plumbing.Reference - src := s.Src() - resolvedRef, ret = repository.ExpandRef(remoteRefs, plumbing.ReferenceName(src)) - if ret == nil { - ret = onMatched(resolvedRef) - } - } - - if !matched && !s.IsWildcard() { - return nil, fmt.Errorf("%w: %s", ErrRemoteRefNotFound, s.Src()) - } - - return refList, ret -} - -func getWants(localStorer storage.Storer, refs memory.ReferenceStorage, depth int) ([]plumbing.Hash, error) { - // If depth is anything other than 1 and the repo has shallow commits then just because we have the commit - // at the reference doesn't mean that we don't still need to fetch the parents - shallow := false - if depth != 1 { - if s, _ := localStorer.Shallow(); len(s) > 0 { - shallow = true - } - } - - wants := map[plumbing.Hash]bool{} - for _, ref := range refs { - hash := ref.Hash() - exists, err := objectExists(localStorer, ref.Hash()) - if err != nil { - return nil, err - } - - if !exists || shallow { - wants[hash] = true - } - } - - var result []plumbing.Hash - for h := range wants { - result = append(result, h) - } - - return result, nil -} - -func objectExists(s storer.EncodedObjectStorer, h plumbing.Hash) (bool, error) { - _, err := s.EncodedObject(plumbing.AnyObject, h) - if errors.Is(err, plumbing.ErrObjectNotFound) { - return false, nil - } - - return true, err -} - -func checkFastForwardUpdate(s storer.EncodedObjectStorer, remoteRefs storer.ReferenceStorer, cmd *packp.Command) error { - if cmd.Old == plumbing.ZeroHash { - _, err := remoteRefs.Reference(cmd.Name) - if err == plumbing.ErrReferenceNotFound { - return nil - } - - if err != nil { - return err - } - - return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String()) - } - - ff, err := isFastForward(s, cmd.Old, cmd.New, nil) - if err != nil { - return err - } - - if !ff { - return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String()) - } - - return nil -} - -func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash, earliestShallow *plumbing.Hash) (bool, error) { - c, err := object.GetCommit(s, new) - if err != nil { - return false, err - } - - parentsToIgnore := []plumbing.Hash{} - if earliestShallow != nil { - earliestCommit, err := object.GetCommit(s, *earliestShallow) - if err != nil { - return false, err - } - - parentsToIgnore = earliestCommit.ParentHashes - } - - found := false - // stop iterating at the earliest shallow commit, ignoring its parents - // note: when pull depth is smaller than the number of new changes on the remote, this fails due to missing parents. - // as far as i can tell, without the commits in-between the shallow pull and the earliest shallow, there's no - // real way of telling whether it will be a fast-forward merge. - iter := object.NewCommitPreorderIter(c, nil, parentsToIgnore) - err = iter.ForEach(func(c *object.Commit) error { - if c.Hash != old { - return nil - } - - found = true - return storer.ErrStop - }) - return found, err -} - -func (r *Remote) isSupportedRefSpec(refs []config.RefSpec, caps *capability.List) error { - var containsIsExact bool - for _, ref := range refs { - if ref.IsExactSHA1() { - containsIsExact = true - } - } - - if !containsIsExact { - return nil - } - - if caps.Supports(capability.AllowReachableSHA1InWant) || - caps.Supports(capability.AllowTipSHA1InWant) { - return nil - } - - return ErrExactSHA1NotSupported -} - -func (r *Remote) updateLocalReferenceStorage( - specs []config.RefSpec, - fetchedRefs, remoteRefs memory.ReferenceStorage, - specToRefs [][]*plumbing.Reference, - tagMode plumbing.TagMode, - force bool, -) (updated bool, err error) { - isWildcard := true - forceNeeded := false - - for i, spec := range specs { - if !spec.IsWildcard() { - isWildcard = false - } - - for _, ref := range specToRefs[i] { - if ref.Type() != plumbing.HashReference { - continue - } - - localName := spec.Dst(ref.Name()) - // If localName doesn't start with "refs/" then treat as a branch. - if !strings.HasPrefix(localName.String(), "refs/") { - localName = plumbing.NewBranchReferenceName(localName.String()) - } - old, _ := storer.ResolveReference(r.s, localName) - new := plumbing.NewHashReference(localName, ref.Hash()) - - // If the ref exists locally as a non-tag and force is not - // specified, only update if the new ref is an ancestor of the old - if old != nil && !old.Name().IsTag() && !force && !spec.IsForceUpdate() { - ff, err := isFastForward(r.s, old.Hash(), new.Hash(), nil) - if err != nil { - return updated, err - } - - if !ff { - forceNeeded = true - continue - } - } - - refUpdated, err := checkAndUpdateReferenceStorerIfNeeded(r.s, new, old) - if err != nil { - return updated, err - } - - if refUpdated { - updated = true - } - } - } - - if tagMode == plumbing.NoTags { - return updated, nil - } - - tags := fetchedRefs - if isWildcard { - tags = remoteRefs - } - tagUpdated, err := r.buildFetchedTags(tags) - if err != nil { - return updated, err - } - - if tagUpdated { - updated = true - } - - if forceNeeded { - err = ErrForceNeeded - } - - return -} - -func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) (updated bool, err error) { - for _, ref := range refs { - if !ref.Name().IsTag() { - continue - } - - _, err := r.s.EncodedObject(plumbing.AnyObject, ref.Hash()) - if errors.Is(err, plumbing.ErrObjectNotFound) { - continue - } - - if err != nil { - return false, err - } - - refUpdated, err := updateReferenceStorerIfNeeded(r.s, ref) - if err != nil { - return updated, err - } - - if refUpdated { - updated = true - } - } - - return -} - -// List the references on the remote repository. -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects to the -// transport operations. -func (r *Remote) ListContext(ctx context.Context, o *ListOptions) (rfs []*plumbing.Reference, err error) { - return r.list(ctx, o) -} - -func (r *Remote) List(o *ListOptions) (rfs []*plumbing.Reference, err error) { - timeout := o.Timeout - // Default to the old hardcoded 10s value if a timeout is not explicitly set. - if timeout == 0 { - timeout = 10 - } - if timeout < 0 { - return nil, fmt.Errorf("invalid timeout: %d", timeout) - } - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) - defer cancel() - return r.ListContext(ctx, o) -} - -func (r *Remote) list(ctx context.Context, o *ListOptions) (rfs []*plumbing.Reference, err error) { - if r.c == nil || len(r.c.URLs) == 0 { - return nil, ErrEmptyUrls - } - - c, ep, err := newClient(r.c.URLs[0], o.InsecureSkipTLS, o.CABundle, o.ProxyOptions) - if err != nil { - return nil, err - } - - s, err := c.NewSession(r.s, ep, o.Auth) - if err != nil { - return nil, err - } - - conn, err := s.Handshake(ctx, transport.UploadPackService) - if err != nil { - return nil, err - } - - defer ioutil.CheckClose(conn, &err) - - allRefs, err := conn.GetRemoteRefs(ctx) - if err != nil { - return nil, err - } - - var resultRefs []*plumbing.Reference - for _, ref := range allRefs { - isPeeled := strings.HasSuffix(ref.Name().String(), peeledSuffix) - switch o.PeelingOption { - case IgnorePeeled: - if !isPeeled { - resultRefs = append(resultRefs, ref) - } - case OnlyPeeled: - if isPeeled { - resultRefs = append(resultRefs, ref) - } - case AppendPeeled: - resultRefs = append(resultRefs, ref) - } - } - - return resultRefs, nil -} - -func objectsToPush(commands []*packp.Command) []plumbing.Hash { - objects := make([]plumbing.Hash, 0, len(commands)) - for _, cmd := range commands { - if cmd.New == plumbing.ZeroHash { - continue - } - objects = append(objects, cmd.New) - } - return objects -} - -func referencesToHashes(refs storer.ReferenceStorer) ([]plumbing.Hash, error) { - iter, err := refs.IterReferences() - if err != nil { - return nil, err - } - - var hs []plumbing.Hash - err = iter.ForEach(func(ref *plumbing.Reference) error { - if ref.Type() != plumbing.HashReference { - return nil - } - - hs = append(hs, ref.Hash()) - return nil - }) - if err != nil { - return nil, err - } - - return hs, nil -} - -func pushHashes( - ctx context.Context, - conn transport.Connection, - s storage.Storer, - cmds []*packp.Command, - hs []plumbing.Hash, - allDelete bool, - o *PushOptions, -) error { - useRefDeltas := !conn.Capabilities().Supports(capability.OFSDelta) - rd, wr := io.Pipe() - - config, err := s.Config() - if err != nil { - return err - } - - // Set buffer size to 1 so the error message can be written when - // ReceivePack fails. Otherwise the goroutine will be blocked writing - // to the channel. - done := make(chan error, 1) - req := &transport.PushRequest{ - Commands: cmds, - Progress: o.Progress, - Options: o.Options, - Atomic: o.Atomic, - } - - if !allDelete { - req.Packfile = rd - go func() { - e := packfile.NewEncoder(wr, s, useRefDeltas) - if _, err := e.Encode(hs, config.Pack.Window); err != nil { - done <- wr.CloseWithError(err) - return - } - - done <- wr.Close() - }() - } else { - close(done) - } - - if err := conn.Push(ctx, req); err != nil { - // close the pipe to unlock encode write - _ = rd.Close() - return err - } - - if err := <-done; err != nil { - return err - } - - return nil -} - -func (r *Remote) checkRequireRemoteRefs(requires []config.RefSpec, remoteRefs storer.ReferenceStorer) error { - for _, require := range requires { - if require.IsWildcard() { - return fmt.Errorf("wildcards not supported in RequireRemoteRefs, got %s", require.String()) - } - - name := require.Dst("") - remote, err := remoteRefs.Reference(name) - if err != nil { - return fmt.Errorf("remote ref %s required to be %s but is absent", name.String(), require.Src()) - } - - var requireHash string - if require.IsExactSHA1() { - requireHash = require.Src() - } else { - target, err := storer.ResolveReference(remoteRefs, plumbing.ReferenceName(require.Src())) - if err != nil { - return fmt.Errorf("could not resolve ref %s in RequireRemoteRefs", require.Src()) - } - requireHash = target.Hash().String() - } - - if remote.Hash().String() != requireHash { - return fmt.Errorf("remote ref %s required to be %s but is %s", name.String(), requireHash, remote.Hash().String()) - } - } - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/repository.go b/vendor/github.com/go-git/go-git/v6/repository.go deleted file mode 100644 index deab64bc..00000000 --- a/vendor/github.com/go-git/go-git/v6/repository.go +++ /dev/null @@ -1,1911 +0,0 @@ -package git - -import ( - "bytes" - "context" - "encoding/hex" - "errors" - "fmt" - "io" - "os" - "path" - "path/filepath" - "strings" - "time" - - "github.com/ProtonMail/go-crypto/openpgp" - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/osfs" - "github.com/go-git/go-git/v6/config" - "github.com/go-git/go-git/v6/internal/path_util" - "github.com/go-git/go-git/v6/internal/revision" - "github.com/go-git/go-git/v6/internal/url" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/cache" - formatcfg "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/storage/filesystem" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/trace" -) - -// GitDirName this is a special folder where all the git stuff is. -const GitDirName = ".git" - -var ( - // ErrBranchExists an error stating the specified branch already exists - ErrBranchExists = errors.New("branch already exists") - // ErrBranchNotFound an error stating the specified branch does not exist - ErrBranchNotFound = errors.New("branch not found") - // ErrTagExists an error stating the specified tag already exists - ErrTagExists = errors.New("tag already exists") - // ErrTagNotFound an error stating the specified tag does not exist - ErrTagNotFound = errors.New("tag not found") - // ErrFetching is returned when the packfile could not be downloaded - ErrFetching = errors.New("unable to fetch packfile") - - ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch") - ErrRepositoryNotExists = errors.New("repository does not exist") - ErrRepositoryIncomplete = errors.New("repository's commondir path does not exist") - ErrRemoteNotFound = errors.New("remote not found") - ErrRemoteExists = errors.New("remote already exists") - ErrAnonymousRemoteName = errors.New("anonymous remote name must be 'anonymous'") - ErrWorktreeNotProvided = errors.New("worktree should be provided") - ErrIsBareRepository = errors.New("worktree not available in a bare repository") - ErrUnableToResolveCommit = errors.New("unable to resolve commit") - ErrPackedObjectsNotSupported = errors.New("packed objects not supported") - ErrSHA256NotSupported = errors.New("go-git was not compiled with SHA256 support") - ErrAlternatePathNotSupported = errors.New("alternate path must use the file scheme") - ErrUnsupportedMergeStrategy = errors.New("unsupported merge strategy") - ErrFastForwardMergeNotPossible = errors.New("not possible to fast-forward merge changes") - ErrTargetDirNotEmpty = errors.New("destination path already exists and is not empty") -) - -// Repository represents a git repository -type Repository struct { - Storer storage.Storer - - r map[string]*Remote - wt billy.Filesystem -} - -type initOptions struct { - defaultBranch plumbing.ReferenceName - workTree billy.Filesystem - objectFormat formatcfg.ObjectFormat -} - -func newInitOptions() initOptions { - return initOptions{ - defaultBranch: plumbing.Master, - workTree: nil, - objectFormat: formatcfg.SHA1, - } -} - -type InitOption func(*initOptions) - -// WithDefaultBranch sets the default branch for the new repo (e.g. "refs/heads/master"). -func WithDefaultBranch(b plumbing.ReferenceName) InitOption { - return func(o *initOptions) { - o.defaultBranch = b - } -} - -// WithWorkTree sets the worktree filesystem for the repo. If not used, or a `nil` is -// passed as argument, will result in a bare repository. -func WithWorkTree(worktree billy.Filesystem) InitOption { - return func(o *initOptions) { - o.workTree = worktree - } -} - -// WithObjectFormat sets the repository's object format. -func WithObjectFormat(of formatcfg.ObjectFormat) InitOption { - return func(o *initOptions) { - o.objectFormat = of - } -} - -// Init creates an empty git repository, based on the given Storer and worktree. -// The worktree Filesystem is optional, if nil a bare repository is created. If -// the given storer is not empty ErrTargetDirNotEmpty is returned -func Init(s storage.Storer, opts ...InitOption) (*Repository, error) { - options := newInitOptions() - for _, oFn := range opts { - if oFn != nil { - oFn(&options) - } - } - - if err := initStorer(s); err != nil { - return nil, err - } - - if err := options.defaultBranch.Validate(); err != nil { - return nil, err - } - - r := newRepository(s, options.workTree) - _, err := r.Reference(plumbing.HEAD, false) - switch err { - case plumbing.ErrReferenceNotFound: - case nil: - return nil, ErrTargetDirNotEmpty - default: - return nil, err - } - - h := plumbing.NewSymbolicReference(plumbing.HEAD, options.defaultBranch) - if err := s.SetReference(h); err != nil { - return nil, err - } - - if options.workTree == nil { - _ = r.setIsBare(true) - return r, nil - } - - return r, setWorktreeAndStoragePaths(r, options.workTree) -} - -func initStorer(s storer.Storer) error { - i, ok := s.(storer.Initializer) - if !ok { - return nil - } - - return i.Init() -} - -func setWorktreeAndStoragePaths(r *Repository, worktree billy.Filesystem) error { - type fsBased interface { - Filesystem() billy.Filesystem - } - - // .git file is only created if the storage is file based and the file - // system is osfs.OS - fs, isFSBased := r.Storer.(fsBased) - if !isFSBased { - return nil - } - - if err := createDotGitFile(worktree, fs.Filesystem()); err != nil { - return err - } - - return setConfigWorktree(r, worktree, fs.Filesystem()) -} - -func createDotGitFile(worktree, storage billy.Filesystem) error { - path, err := filepath.Rel(worktree.Root(), storage.Root()) - if err != nil { - path = storage.Root() - } - - if path == GitDirName { - // not needed, since the folder is the default place - return nil - } - - f, err := worktree.Create(GitDirName) - if err != nil { - return err - } - - defer f.Close() - _, err = fmt.Fprintf(f, "gitdir: %s\n", path) - return err -} - -func setConfigWorktree(r *Repository, worktree, storage billy.Filesystem) error { - path, err := filepath.Rel(storage.Root(), worktree.Root()) - if err != nil { - path = worktree.Root() - } - - if path == ".." { - // not needed, since the folder is the default place - return nil - } - - cfg, err := r.Config() - if err != nil { - return err - } - - cfg.Core.Worktree = path - return r.Storer.SetConfig(cfg) -} - -// Open opens a git repository using the given Storer and worktree filesystem, -// if the given storer is complete empty ErrRepositoryNotExists is returned. -// The worktree can be nil when the repository being opened is bare, if the -// repository is a normal one (not bare) and worktree is nil the err -// ErrWorktreeNotProvided is returned -func Open(s storage.Storer, worktree billy.Filesystem) (*Repository, error) { - _, err := s.Reference(plumbing.HEAD) - if err == plumbing.ErrReferenceNotFound { - return nil, ErrRepositoryNotExists - } - - if err != nil { - return nil, err - } - - return newRepository(s, worktree), nil -} - -// Clone a repository into the given Storer and worktree Filesystem with the -// given options, if worktree is nil a bare repository is created. If the given -// storer is not empty ErrTargetDirNotEmpty is returned. -func Clone(s storage.Storer, worktree billy.Filesystem, o *CloneOptions) (*Repository, error) { - return CloneContext(context.Background(), s, worktree, o) -} - -// CloneContext a repository into the given Storer and worktree Filesystem with -// the given options, if worktree is nil a bare repository is created. If the -// given storer is not empty ErrTargetDirNotEmpty is returned. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func CloneContext( - ctx context.Context, s storage.Storer, worktree billy.Filesystem, o *CloneOptions, -) (*Repository, error) { - start := time.Now() - defer func() { - url := "" - if o != nil { - url = o.URL - } - trace.Performance.Printf("performance: %.9f s: git command: git clone %s", time.Since(start).Seconds(), url) - }() - - r, err := Init(s, - WithWorkTree(worktree), - ) - if err != nil { - return nil, err - } - - return r, r.clone(ctx, o) -} - -// PlainInit create an empty git repository at the given path. isBare defines -// if the repository will have worktree (non-bare) or not (bare), if the path -// is not empty ErrTargetDirNotEmpty is returned. -func PlainInit(path string, isBare bool, options ...InitOption) (*Repository, error) { - var wt, dot billy.Filesystem - var initFn func(s *filesystem.Storage) (*Repository, error) - - o := newInitOptions() - for _, oFn := range options { - oFn(&o) - } - - var err error - // go-git/go-git#1610 - if !filepath.IsAbs(path) { - path, err = filepath.Abs(path) - if err != nil { - return nil, err - } - } - - if isBare { - dot = osfs.New(path, osfs.WithBoundOS()) - initFn = func(s *filesystem.Storage) (*Repository, error) { - return Init(s, options...) - } - } else { - wt = osfs.New(path, osfs.WithBoundOS()) - dot, _ = wt.Chroot(GitDirName) - initFn = func(s *filesystem.Storage) (*Repository, error) { - oo := []InitOption{WithWorkTree(wt)} - oo = append(oo, options...) - return Init(s, oo...) - } - } - s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault()) - r, err := initFn(s) - if err != nil { - return nil, err - } - - cfg, err := r.Config() - if err != nil { - return nil, err - } - - if o.objectFormat != formatcfg.SHA1 { - cfg.Core.RepositoryFormatVersion = formatcfg.Version_1 - cfg.Extensions.ObjectFormat = o.objectFormat - } - - err = r.Storer.SetConfig(cfg) - if err != nil { - return nil, err - } - - return r, err -} - -// PlainOpen opens a git repository from the given path. It detects if the -// repository is bare or a normal one. If the path doesn't contain a valid -// repository ErrRepositoryNotExists is returned -func PlainOpen(path string) (*Repository, error) { - return PlainOpenWithOptions(path, &PlainOpenOptions{}) -} - -// PlainOpenWithOptions opens a git repository from the given path with specific -// options. See PlainOpen for more info. -func PlainOpenWithOptions(path string, o *PlainOpenOptions) (*Repository, error) { - dot, wt, err := dotGitToOSFilesystems(path, o.DetectDotGit) - if err != nil { - return nil, err - } - - if _, err := dot.Stat(""); err != nil { - if os.IsNotExist(err) { - return nil, ErrRepositoryNotExists - } - - return nil, err - } - - var repositoryFs billy.Filesystem - - if o.EnableDotGitCommonDir { - dotGitCommon, err := dotGitCommonDirectory(dot) - if err != nil { - return nil, err - } - repositoryFs = dotgit.NewRepositoryFilesystem(dot, dotGitCommon) - } else { - repositoryFs = dot - } - - s := filesystem.NewStorage(repositoryFs, cache.NewObjectLRUDefault()) - - return Open(s, wt) -} - -func dotGitToOSFilesystems(path string, detect bool) (dot, wt billy.Filesystem, err error) { - path, err = path_util.ReplaceTildeWithHome(path) - if err != nil { - return nil, nil, err - } - - if path, err = filepath.Abs(path); err != nil { - return nil, nil, err - } - - var fs billy.Filesystem - var fi os.FileInfo - for { - fs = osfs.New(path, osfs.WithBoundOS()) - - pathinfo, err := fs.Stat("/") - if !os.IsNotExist(err) { - if pathinfo == nil { - return nil, nil, err - } - if !pathinfo.IsDir() && detect { - fs = osfs.New(filepath.Dir(path), osfs.WithBoundOS()) - } - } - - fi, err = fs.Stat(GitDirName) - if err == nil { - // no error; stop - break - } - if !os.IsNotExist(err) { - // unknown error; stop - return nil, nil, err - } - if detect { - // try its parent as long as we haven't reached - // the root dir - if dir := filepath.Dir(path); dir != path { - path = dir - continue - } - } - // not detecting via parent dirs and the dir does not exist; - // stop - return fs, nil, nil - } - - if fi.IsDir() { - dot, err = fs.Chroot(GitDirName) - return dot, fs, err - } - - dot, err = dotGitFileToOSFilesystem(path, fs) - if err != nil { - return nil, nil, err - } - - return dot, fs, nil -} - -func dotGitFileToOSFilesystem(path string, fs billy.Filesystem) (bfs billy.Filesystem, err error) { - f, err := fs.Open(GitDirName) - if err != nil { - return nil, err - } - defer ioutil.CheckClose(f, &err) - - b, err := io.ReadAll(f) - if err != nil { - return nil, err - } - - line := string(b) - const prefix = "gitdir: " - if !strings.HasPrefix(line, prefix) { - return nil, fmt.Errorf(".git file has no %s prefix", prefix) - } - - gitdir := strings.Split(line[len(prefix):], "\n")[0] - gitdir = strings.TrimSpace(gitdir) - if filepath.IsAbs(gitdir) { - return osfs.New(gitdir, osfs.WithBoundOS()), nil - } - - return osfs.New(fs.Join(path, gitdir), osfs.WithBoundOS()), nil -} - -func dotGitCommonDirectory(fs billy.Filesystem) (commonDir billy.Filesystem, err error) { - f, err := fs.Open("commondir") - if os.IsNotExist(err) { - return nil, nil - } - if err != nil { - return nil, err - } - defer ioutil.CheckClose(f, &err) - - b, err := io.ReadAll(f) - if err != nil { - return nil, err - } - if len(b) > 0 { - path := strings.TrimSpace(string(b)) - if filepath.IsAbs(path) { - commonDir = osfs.New(path, osfs.WithBoundOS()) - } else { - commonDir = osfs.New(filepath.Join(fs.Root(), path), osfs.WithBoundOS()) - } - if _, err := commonDir.Stat(""); err != nil { - if os.IsNotExist(err) { - return nil, ErrRepositoryIncomplete - } - - return nil, err - } - } - - return commonDir, nil -} - -// PlainClone a repository into the path with the given options, isBare defines -// if the new repository will be bare or normal. If the path is not empty -// ErrTargetDirNotEmpty is returned. -func PlainClone(path string, o *CloneOptions) (*Repository, error) { - return PlainCloneContext(context.Background(), path, o) -} - -// PlainCloneContext a repository into the path with the given options, isBare -// defines if the new repository will be bare or normal. If the path is not empty -// ErrTargetDirNotEmpty is returned. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func PlainCloneContext(ctx context.Context, path string, o *CloneOptions) (*Repository, error) { - empty, err := checkTargetDirIsEmpty(path) - if err != nil { - return nil, err - } - if !empty { - return nil, fmt.Errorf("%w %s", ErrTargetDirNotEmpty, path) - } - start := time.Now() - defer func() { - url := "" - if o != nil { - url = o.URL - } - trace.Performance.Printf("performance: %.9f s: git command: git clone %s", time.Since(start).Seconds(), url) - }() - - isBare := o.Bare - if o.Mirror { - isBare = true - } - r, err := PlainInit(path, isBare) - if err != nil { - return nil, err - } - - err = r.clone(ctx, o) - return r, err -} - -func newRepository(s storage.Storer, worktree billy.Filesystem) *Repository { - return &Repository{ - Storer: s, - wt: worktree, - r: make(map[string]*Remote), - } -} - -func checkTargetDirIsEmpty(path string) (empty bool, err error) { - fi, err := osfs.Default.Stat(path) - if err != nil { - if os.IsNotExist(err) { - return true, nil - } - - return false, err - } - - if !fi.IsDir() { - return false, fmt.Errorf("path is not a directory: %s", path) - } - - files, err := osfs.Default.ReadDir(path) - if err != nil { - return false, err - } - - if len(files) == 0 { - return true, nil - } - - return false, nil -} - -// Config return the repository config. In a filesystem backed repository this -// means read the `.git/config`. -func (r *Repository) Config() (*config.Config, error) { - return r.Storer.Config() -} - -// SetConfig marshall and writes the repository config. In a filesystem backed -// repository this means write the `.git/config`. This function should be called -// with the result of `Repository.Config` and never with the output of -// `Repository.ConfigScoped`. -func (r *Repository) SetConfig(cfg *config.Config) error { - return r.Storer.SetConfig(cfg) -} - -// ConfigScoped returns the repository config, merged with requested scope and -// lower. For example if, config.GlobalScope is given the local and global config -// are returned merged in one config value. -func (r *Repository) ConfigScoped(scope config.Scope) (*config.Config, error) { - // TODO(mcuadros): v6, add this as ConfigOptions.Scoped - - var err error - system := config.NewConfig() - if scope >= config.SystemScope { - system, err = config.LoadConfig(config.SystemScope) - if err != nil { - return nil, err - } - } - - global := config.NewConfig() - if scope >= config.GlobalScope { - global, err = config.LoadConfig(config.GlobalScope) - if err != nil { - return nil, err - } - } - - local, err := r.Storer.Config() - if err != nil { - return nil, err - } - - cfg := config.Merge(system, global, local) - return &cfg, nil -} - -// Remote return a remote if exists -func (r *Repository) Remote(name string) (*Remote, error) { - cfg, err := r.Config() - if err != nil { - return nil, err - } - - c, ok := cfg.Remotes[name] - if !ok { - return nil, ErrRemoteNotFound - } - - return NewRemote(r.Storer, c), nil -} - -// Remotes returns a list with all the remotes -func (r *Repository) Remotes() ([]*Remote, error) { - cfg, err := r.Config() - if err != nil { - return nil, err - } - - remotes := make([]*Remote, len(cfg.Remotes)) - - var i int - for _, c := range cfg.Remotes { - remotes[i] = NewRemote(r.Storer, c) - i++ - } - - return remotes, nil -} - -// CreateRemote creates a new remote -func (r *Repository) CreateRemote(c *config.RemoteConfig) (*Remote, error) { - if err := c.Validate(); err != nil { - return nil, err - } - - remote := NewRemote(r.Storer, c) - - cfg, err := r.Config() - if err != nil { - return nil, err - } - - if _, ok := cfg.Remotes[c.Name]; ok { - return nil, ErrRemoteExists - } - - cfg.Remotes[c.Name] = c - return remote, r.Storer.SetConfig(cfg) -} - -// CreateRemoteAnonymous creates a new anonymous remote. c.Name must be "anonymous". -// It's used like 'git fetch git@github.com:src-d/go-git.git master:master'. -func (r *Repository) CreateRemoteAnonymous(c *config.RemoteConfig) (*Remote, error) { - if err := c.Validate(); err != nil { - return nil, err - } - - if c.Name != "anonymous" { - return nil, ErrAnonymousRemoteName - } - - remote := NewRemote(r.Storer, c) - - return remote, nil -} - -// DeleteRemote delete a remote from the repository and delete the config -func (r *Repository) DeleteRemote(name string) error { - cfg, err := r.Config() - if err != nil { - return err - } - - if _, ok := cfg.Remotes[name]; !ok { - return ErrRemoteNotFound - } - - delete(cfg.Remotes, name) - return r.Storer.SetConfig(cfg) -} - -// Branch return a Branch if exists -func (r *Repository) Branch(name string) (*config.Branch, error) { - cfg, err := r.Config() - if err != nil { - return nil, err - } - - b, ok := cfg.Branches[name] - if !ok { - return nil, ErrBranchNotFound - } - - return b, nil -} - -// CreateBranch creates a new Branch -func (r *Repository) CreateBranch(c *config.Branch) error { - if err := c.Validate(); err != nil { - return err - } - - cfg, err := r.Config() - if err != nil { - return err - } - - if _, ok := cfg.Branches[c.Name]; ok { - return ErrBranchExists - } - - cfg.Branches[c.Name] = c - return r.Storer.SetConfig(cfg) -} - -// DeleteBranch delete a Branch from the repository and delete the config -func (r *Repository) DeleteBranch(name string) error { - cfg, err := r.Config() - if err != nil { - return err - } - - if _, ok := cfg.Branches[name]; !ok { - return ErrBranchNotFound - } - - delete(cfg.Branches, name) - return r.Storer.SetConfig(cfg) -} - -// CreateTag creates a tag. If opts is included, the tag is an annotated tag, -// otherwise a lightweight tag is created. -func (r *Repository) CreateTag(name string, hash plumbing.Hash, opts *CreateTagOptions) (*plumbing.Reference, error) { - rname := plumbing.NewTagReferenceName(name) - if err := rname.Validate(); err != nil { - return nil, err - } - - _, err := r.Storer.Reference(rname) - switch err { - case nil: - // Tag exists, this is an error - return nil, ErrTagExists - case plumbing.ErrReferenceNotFound: - // Tag missing, available for creation, pass this - default: - // Some other error - return nil, err - } - - var target plumbing.Hash - if opts != nil { - target, err = r.createTagObject(name, hash, opts) - if err != nil { - return nil, err - } - } else { - target = hash - } - - ref := plumbing.NewHashReference(rname, target) - if err = r.Storer.SetReference(ref); err != nil { - return nil, err - } - - return ref, nil -} - -func (r *Repository) createTagObject(name string, hash plumbing.Hash, opts *CreateTagOptions) (plumbing.Hash, error) { - if err := opts.Validate(r, hash); err != nil { - return plumbing.ZeroHash, err - } - - rawobj, err := object.GetObject(r.Storer, hash) - if err != nil { - return plumbing.ZeroHash, err - } - - tag := &object.Tag{ - Name: name, - Tagger: *opts.Tagger, - Message: opts.Message, - TargetType: rawobj.Type(), - Target: hash, - } - - if opts.SignKey != nil { - sig, err := r.buildTagSignature(tag, opts.SignKey) - if err != nil { - return plumbing.ZeroHash, err - } - - tag.PGPSignature = sig - } - - obj := r.Storer.NewEncodedObject() - if err := tag.Encode(obj); err != nil { - return plumbing.ZeroHash, err - } - - return r.Storer.SetEncodedObject(obj) -} - -func (r *Repository) buildTagSignature(tag *object.Tag, signKey *openpgp.Entity) (string, error) { - encoded := &plumbing.MemoryObject{} - if err := tag.Encode(encoded); err != nil { - return "", err - } - - rdr, err := encoded.Reader() - if err != nil { - return "", err - } - - var b bytes.Buffer - if err := openpgp.ArmoredDetachSign(&b, signKey, rdr, nil); err != nil { - return "", err - } - - return b.String(), nil -} - -// Tag returns a tag from the repository. -// -// If you want to check to see if the tag is an annotated tag, you can call -// TagObject on the hash of the reference in ForEach: -// -// ref, err := r.Tag("v0.1.0") -// if err != nil { -// // Handle error -// } -// -// obj, err := r.TagObject(ref.Hash()) -// switch err { -// case nil: -// // Tag object present -// case plumbing.ErrObjectNotFound: -// // Not a tag object -// default: -// // Some other error -// } -func (r *Repository) Tag(name string) (*plumbing.Reference, error) { - ref, err := r.Reference(plumbing.ReferenceName(path.Join("refs", "tags", name)), false) - if err != nil { - if err == plumbing.ErrReferenceNotFound { - // Return a friendly error for this one, versus just ReferenceNotFound. - return nil, ErrTagNotFound - } - - return nil, err - } - - return ref, nil -} - -// DeleteTag deletes a tag from the repository. -func (r *Repository) DeleteTag(name string) error { - _, err := r.Tag(name) - if err != nil { - return err - } - - return r.Storer.RemoveReference(plumbing.ReferenceName(path.Join("refs", "tags", name))) -} - -func (r *Repository) resolveToCommitHash(h plumbing.Hash) (plumbing.Hash, error) { - obj, err := r.Storer.EncodedObject(plumbing.AnyObject, h) - if err != nil { - return plumbing.ZeroHash, err - } - switch obj.Type() { - case plumbing.TagObject: - t, err := object.DecodeTag(r.Storer, obj) - if err != nil { - return plumbing.ZeroHash, err - } - return r.resolveToCommitHash(t.Target) - case plumbing.CommitObject: - return h, nil - default: - return plumbing.ZeroHash, ErrUnableToResolveCommit - } -} - -// Clone clones a remote repository -func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { - if err := o.Validate(); err != nil { - return err - } - - c := &config.RemoteConfig{ - Name: o.RemoteName, - URLs: []string{o.URL}, - Fetch: r.cloneRefSpec(o), - Mirror: o.Mirror, - } - - if _, err := r.CreateRemote(c); err != nil { - return err - } - - // When the repository to clone is on the local machine, - // instead of using hard links, automatically setup .git/objects/info/alternates - // to share the objects with the source repository - if o.Shared { - if !url.IsLocalEndpoint(o.URL) { - return ErrAlternatePathNotSupported - } - altpath := o.URL - remoteRepo, err := PlainOpen(o.URL) - if err != nil { - return fmt.Errorf("failed to open remote repository: %w", err) - } - conf, err := remoteRepo.Config() - if err != nil { - return fmt.Errorf("failed to read remote repository configuration: %w", err) - } - if !conf.Core.IsBare { - altpath = path.Join(altpath, GitDirName) - } - if err := r.Storer.AddAlternate(altpath); err != nil { - return fmt.Errorf("failed to add alternate file to git objects dir: %w", err) - } - } - - ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{ - RefSpecs: c.Fetch, - Depth: o.Depth, - Auth: o.Auth, - Progress: o.Progress, - Tags: o.Tags, - RemoteName: o.RemoteName, - InsecureSkipTLS: o.InsecureSkipTLS, - CABundle: o.CABundle, - ProxyOptions: o.ProxyOptions, - Filter: o.Filter, - }, o.ReferenceName) - if err != nil { - return err - } - - if r.wt != nil && !o.NoCheckout { - w, err := r.Worktree() - if err != nil { - return err - } - - head, err := r.Head() - if err != nil { - return err - } - - if err := w.Reset(&ResetOptions{ - Mode: MergeReset, - Commit: head.Hash(), - }); err != nil { - return err - } - - if o.RecurseSubmodules != NoRecurseSubmodules { - if err := w.updateSubmodules(ctx, &SubmoduleUpdateOptions{ - RecurseSubmodules: o.RecurseSubmodules, - Depth: func() int { - if o.ShallowSubmodules { - return 1 - } - return 0 - }(), - Auth: o.Auth, - }); err != nil { - return err - } - } - } - - if err := r.updateRemoteConfigIfNeeded(o, c, ref); err != nil { - return err - } - - if !o.Mirror && ref.Name().IsBranch() { - branchRef := ref.Name() - branchName := strings.Split(string(branchRef), "refs/heads/")[1] - - b := &config.Branch{ - Name: branchName, - Merge: branchRef, - } - - if o.RemoteName == "" { - b.Remote = "origin" - } else { - b.Remote = o.RemoteName - } - - if err := r.CreateBranch(b); err != nil { - return err - } - } - - return nil -} - -const ( - refspecTag = "+refs/tags/%s:refs/tags/%[1]s" - refspecSingleBranch = "+refs/heads/%s:refs/remotes/%s/%[1]s" - refspecSingleBranchHEAD = "+HEAD:refs/remotes/%s/HEAD" -) - -func (r *Repository) cloneRefSpec(o *CloneOptions) []config.RefSpec { - switch { - case o.Mirror: - return []config.RefSpec{"+refs/*:refs/*"} - case o.ReferenceName.IsTag(): - return []config.RefSpec{ - config.RefSpec(fmt.Sprintf(refspecTag, o.ReferenceName.Short())), - } - case o.SingleBranch && o.ReferenceName == plumbing.HEAD: - return []config.RefSpec{ - config.RefSpec(fmt.Sprintf(refspecSingleBranchHEAD, o.RemoteName)), - } - case o.SingleBranch: - return []config.RefSpec{ - config.RefSpec(fmt.Sprintf(refspecSingleBranch, o.ReferenceName.Short(), o.RemoteName)), - } - default: - return []config.RefSpec{ - config.RefSpec(fmt.Sprintf(config.DefaultFetchRefSpec, o.RemoteName)), - } - } -} - -func (r *Repository) setIsBare(isBare bool) error { - cfg, err := r.Config() - if err != nil { - return err - } - - cfg.Core.IsBare = isBare - return r.Storer.SetConfig(cfg) -} - -func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, _ *plumbing.Reference) error { - if !o.SingleBranch { - return nil - } - - c.Fetch = r.cloneRefSpec(o) - - cfg, err := r.Config() - if err != nil { - return err - } - - cfg.Remotes[c.Name] = c - return r.Storer.SetConfig(cfg) -} - -func (r *Repository) fetchAndUpdateReferences( - ctx context.Context, o *FetchOptions, ref plumbing.ReferenceName, -) (*plumbing.Reference, error) { - if err := o.Validate(); err != nil { - return nil, err - } - - remote, err := r.Remote(o.RemoteName) - if err != nil { - return nil, err - } - - objsUpdated := true - remoteRefs, err := remote.fetch(ctx, o) - if err == NoErrAlreadyUpToDate { - objsUpdated = false - } else if err == packfile.ErrEmptyPackfile { - return nil, ErrFetching - } else if err != nil { - return nil, err - } - - resolvedRef, err := expand_ref(remoteRefs, ref) - if err != nil { - return nil, err - } - - refsUpdated, err := r.updateReferences(remote.c.Fetch, resolvedRef) - if err != nil { - return nil, err - } - - if !objsUpdated && !refsUpdated { - return nil, NoErrAlreadyUpToDate - } - - return resolvedRef, nil -} - -func (r *Repository) updateReferences(spec []config.RefSpec, - resolvedRef *plumbing.Reference, -) (updated bool, err error) { - if !resolvedRef.Name().IsBranch() { - // Detached HEAD mode - h, err := r.resolveToCommitHash(resolvedRef.Hash()) - if err != nil { - return false, err - } - head := plumbing.NewHashReference(plumbing.HEAD, h) - return updateReferenceStorerIfNeeded(r.Storer, head) - } - - refs := []*plumbing.Reference{ - // Create local reference for the resolved ref - resolvedRef, - // Create local symbolic HEAD - plumbing.NewSymbolicReference(plumbing.HEAD, resolvedRef.Name()), - } - - refs = append(refs, r.calculateRemoteHeadReference(spec, resolvedRef)...) - - for _, ref := range refs { - u, err := updateReferenceStorerIfNeeded(r.Storer, ref) - if err != nil { - return updated, err - } - - if u { - updated = true - } - } - - return -} - -func (r *Repository) calculateRemoteHeadReference(spec []config.RefSpec, - resolvedHead *plumbing.Reference, -) []*plumbing.Reference { - var refs []*plumbing.Reference - - // Create resolved HEAD reference with remote prefix if it does not - // exist. This is needed when using single branch and HEAD. - for _, rs := range spec { - name := resolvedHead.Name() - if !rs.Match(name) { - continue - } - - name = rs.Dst(name) - _, err := r.Storer.Reference(name) - if err == plumbing.ErrReferenceNotFound { - refs = append(refs, plumbing.NewHashReference(name, resolvedHead.Hash())) - } - } - - return refs -} - -func checkAndUpdateReferenceStorerIfNeeded( - s storer.ReferenceStorer, r, old *plumbing.Reference) ( - updated bool, err error, -) { - p, err := s.Reference(r.Name()) - if err != nil && err != plumbing.ErrReferenceNotFound { - return false, err - } - - // we use the string method to compare references, is the easiest way - if err == plumbing.ErrReferenceNotFound || r.String() != p.String() { - if err := s.CheckAndSetReference(r, old); err != nil { - return false, err - } - - return true, nil - } - - return false, nil -} - -func updateReferenceStorerIfNeeded( - s storer.ReferenceStorer, r *plumbing.Reference, -) (updated bool, err error) { - return checkAndUpdateReferenceStorerIfNeeded(s, r, nil) -} - -// Fetch fetches references along with the objects necessary to complete -// their histories, from the remote named as FetchOptions.RemoteName. -// -// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are -// no changes to be fetched, or an error. -func (r *Repository) Fetch(o *FetchOptions) error { - return r.FetchContext(context.Background(), o) -} - -// FetchContext fetches references along with the objects necessary to complete -// their histories, from the remote named as FetchOptions.RemoteName. -// -// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are -// no changes to be fetched, or an error. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func (r *Repository) FetchContext(ctx context.Context, o *FetchOptions) error { - if err := o.Validate(); err != nil { - return err - } - - remote, err := r.Remote(o.RemoteName) - if err != nil { - return err - } - - return remote.FetchContext(ctx, o) -} - -// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if -// the remote was already up-to-date, from the remote named as -// FetchOptions.RemoteName. -func (r *Repository) Push(o *PushOptions) error { - return r.PushContext(context.Background(), o) -} - -// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if -// the remote was already up-to-date, from the remote named as -// FetchOptions.RemoteName. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error { - if err := o.Validate(); err != nil { - return err - } - - remote, err := r.Remote(o.RemoteName) - if err != nil { - return err - } - - return remote.PushContext(ctx, o) -} - -// Log returns the commit history from the given LogOptions. -func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) { - fn := commitIterFunc(o.Order) - if fn == nil { - return nil, fmt.Errorf("invalid Order=%v", o.Order) - } - - var ( - it object.CommitIter - err error - ) - if o.All { - it, err = r.logAll(fn) - } else { - it, err = r.log(o.From, fn) - } - - if err != nil { - return nil, err - } - - if o.FileName != nil { - // for `git log --all` also check parent (if the next commit comes from the real parent) - it = r.logWithFile(*o.FileName, it, o.All) - } - if o.PathFilter != nil { - it = r.logWithPathFilter(o.PathFilter, it, o.All) - } - - if o.Since != nil || o.Until != nil || !o.To.IsZero() { - limitOptions := object.LogLimitOptions{Since: o.Since, Until: o.Until, TailHash: o.To} - it = r.logWithLimit(it, limitOptions) - } - - return it, nil -} - -func (r *Repository) log(from plumbing.Hash, commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) { - h := from - if from == plumbing.ZeroHash { - head, err := r.Head() - if err != nil { - return nil, err - } - - h = head.Hash() - } - - commit, err := r.CommitObject(h) - if err != nil { - return nil, err - } - return commitIterFunc(commit), nil -} - -func (r *Repository) logAll(commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) { - return object.NewCommitAllIter(r.Storer, commitIterFunc) -} - -func (*Repository) logWithFile(fileName string, commitIter object.CommitIter, checkParent bool) object.CommitIter { - return object.NewCommitPathIterFromIter( - func(path string) bool { - return path == fileName - }, - commitIter, - checkParent, - ) -} - -func (*Repository) logWithPathFilter(pathFilter func(string) bool, commitIter object.CommitIter, checkParent bool) object.CommitIter { - return object.NewCommitPathIterFromIter( - pathFilter, - commitIter, - checkParent, - ) -} - -func (*Repository) logWithLimit(commitIter object.CommitIter, limitOptions object.LogLimitOptions) object.CommitIter { - return object.NewCommitLimitIterFromIter(commitIter, limitOptions) -} - -func commitIterFunc(order LogOrder) func(c *object.Commit) object.CommitIter { - switch order { - case LogOrderDefault: - return func(c *object.Commit) object.CommitIter { - return object.NewCommitPreorderIter(c, nil, nil) - } - case LogOrderDFS: - return func(c *object.Commit) object.CommitIter { - return object.NewCommitPreorderIter(c, nil, nil) - } - case LogOrderDFSPost: - return func(c *object.Commit) object.CommitIter { - return object.NewCommitPostorderIter(c, nil) - } - case LogOrderBSF: - return func(c *object.Commit) object.CommitIter { - return object.NewCommitIterBSF(c, nil, nil) - } - case LogOrderCommitterTime: - return func(c *object.Commit) object.CommitIter { - return object.NewCommitIterCTime(c, nil, nil) - } - case LogOrderDFSPostFirstParent: - return func(c *object.Commit) object.CommitIter { - return object.NewCommitPostorderIterFirstParent(c, nil) - } - } - return nil -} - -// Tags returns all the tag References in a repository. -// -// If you want to check to see if the tag is an annotated tag, you can call -// TagObject on the hash Reference passed in through ForEach: -// -// iter, err := r.Tags() -// if err != nil { -// // Handle error -// } -// -// if err := iter.ForEach(func (ref *plumbing.Reference) error { -// obj, err := r.TagObject(ref.Hash()) -// switch err { -// case nil: -// // Tag object present -// case plumbing.ErrObjectNotFound: -// // Not a tag object -// default: -// // Some other error -// return err -// } -// }); err != nil { -// // Handle outer iterator error -// } -func (r *Repository) Tags() (storer.ReferenceIter, error) { - refIter, err := r.Storer.IterReferences() - if err != nil { - return nil, err - } - - return storer.NewReferenceFilteredIter( - func(r *plumbing.Reference) bool { - return r.Name().IsTag() - }, refIter), nil -} - -// Branches returns all the References that are Branches. -func (r *Repository) Branches() (storer.ReferenceIter, error) { - refIter, err := r.Storer.IterReferences() - if err != nil { - return nil, err - } - - return storer.NewReferenceFilteredIter( - func(r *plumbing.Reference) bool { - return r.Name().IsBranch() - }, refIter), nil -} - -// Notes returns all the References that are notes. For more information: -// https://git-scm.com/docs/git-notes -func (r *Repository) Notes() (storer.ReferenceIter, error) { - refIter, err := r.Storer.IterReferences() - if err != nil { - return nil, err - } - - return storer.NewReferenceFilteredIter( - func(r *plumbing.Reference) bool { - return r.Name().IsNote() - }, refIter), nil -} - -// TreeObject return a Tree with the given hash. If not found -// plumbing.ErrObjectNotFound is returned -func (r *Repository) TreeObject(h plumbing.Hash) (*object.Tree, error) { - return object.GetTree(r.Storer, h) -} - -// TreeObjects returns an unsorted TreeIter with all the trees in the repository -func (r *Repository) TreeObjects() (*object.TreeIter, error) { - iter, err := r.Storer.IterEncodedObjects(plumbing.TreeObject) - if err != nil { - return nil, err - } - - return object.NewTreeIter(r.Storer, iter), nil -} - -// CommitObject return a Commit with the given hash. If not found -// plumbing.ErrObjectNotFound is returned. -func (r *Repository) CommitObject(h plumbing.Hash) (*object.Commit, error) { - return object.GetCommit(r.Storer, h) -} - -// CommitObjects returns an unsorted CommitIter with all the commits in the repository. -func (r *Repository) CommitObjects() (object.CommitIter, error) { - iter, err := r.Storer.IterEncodedObjects(plumbing.CommitObject) - if err != nil { - return nil, err - } - - return object.NewCommitIter(r.Storer, iter), nil -} - -// BlobObject returns a Blob with the given hash. If not found -// plumbing.ErrObjectNotFound is returned. -func (r *Repository) BlobObject(h plumbing.Hash) (*object.Blob, error) { - return object.GetBlob(r.Storer, h) -} - -// BlobObjects returns an unsorted BlobIter with all the blobs in the repository. -func (r *Repository) BlobObjects() (*object.BlobIter, error) { - iter, err := r.Storer.IterEncodedObjects(plumbing.BlobObject) - if err != nil { - return nil, err - } - - return object.NewBlobIter(r.Storer, iter), nil -} - -// TagObject returns a Tag with the given hash. If not found -// plumbing.ErrObjectNotFound is returned. This method only returns -// annotated Tags, no lightweight Tags. -func (r *Repository) TagObject(h plumbing.Hash) (*object.Tag, error) { - return object.GetTag(r.Storer, h) -} - -// TagObjects returns a unsorted TagIter that can step through all of the annotated -// tags in the repository. -func (r *Repository) TagObjects() (*object.TagIter, error) { - iter, err := r.Storer.IterEncodedObjects(plumbing.TagObject) - if err != nil { - return nil, err - } - - return object.NewTagIter(r.Storer, iter), nil -} - -// Object returns an Object with the given hash. If not found -// plumbing.ErrObjectNotFound is returned. -func (r *Repository) Object(t plumbing.ObjectType, h plumbing.Hash) (object.Object, error) { - obj, err := r.Storer.EncodedObject(t, h) - if err != nil { - return nil, err - } - - return object.DecodeObject(r.Storer, obj) -} - -// Objects returns an unsorted ObjectIter with all the objects in the repository. -func (r *Repository) Objects() (*object.ObjectIter, error) { - iter, err := r.Storer.IterEncodedObjects(plumbing.AnyObject) - if err != nil { - return nil, err - } - - return object.NewObjectIter(r.Storer, iter), nil -} - -// Head returns the reference where HEAD is pointing to. -func (r *Repository) Head() (*plumbing.Reference, error) { - return storer.ResolveReference(r.Storer, plumbing.HEAD) -} - -// Reference returns the reference for a given reference name. If resolved is -// true, any symbolic reference will be resolved. -func (r *Repository) Reference(name plumbing.ReferenceName, resolved bool) ( - *plumbing.Reference, error, -) { - if resolved { - return storer.ResolveReference(r.Storer, name) - } - - return r.Storer.Reference(name) -} - -// References returns an unsorted ReferenceIter for all references. -func (r *Repository) References() (storer.ReferenceIter, error) { - return r.Storer.IterReferences() -} - -// Worktree returns a worktree based on the given fs, if nil the default -// worktree will be used. -func (r *Repository) Worktree() (*Worktree, error) { - if r.wt == nil { - return nil, ErrIsBareRepository - } - - return &Worktree{r: r, Filesystem: r.wt}, nil -} - -func expand_ref(s storer.ReferenceStorer, ref plumbing.ReferenceName) (*plumbing.Reference, error) { - // For improving troubleshooting, this preserves the error for the provided `ref`, - // and returns the error for that specific ref in case all parse rules fails. - var ret error - for _, rule := range plumbing.RefRevParseRules { - resolvedRef, err := storer.ResolveReference(s, plumbing.ReferenceName(fmt.Sprintf(rule, ref))) - - if err == nil { - return resolvedRef, nil - } else if ret == nil { - ret = err - } - } - - return nil, ret -} - -// ResolveRevision resolves revision to corresponding hash. It will always -// resolve to a commit hash, not a tree or annotated tag. -// -// Implemented resolvers : HEAD, branch, tag, heads/branch, refs/heads/branch, -// refs/tags/tag, refs/remotes/origin/branch, refs/remotes/origin/HEAD, tilde and caret (HEAD~1, master~^, tag~2, ref/heads/master~1, ...), selection by text (HEAD^{/fix nasty bug}), hash (prefix and full) -func (r *Repository) ResolveRevision(in plumbing.Revision) (*plumbing.Hash, error) { - rev := in.String() - if rev == "" { - return &plumbing.ZeroHash, plumbing.ErrReferenceNotFound - } - - p := revision.NewParserFromString(rev) - items, err := p.Parse() - if err != nil { - return nil, err - } - - var commit *object.Commit - - for _, item := range items { - switch item := item.(type) { - case revision.Ref: - revisionRef := item - - var tryHashes []plumbing.Hash - - tryHashes = append(tryHashes, r.resolveHashPrefix(string(revisionRef))...) - - ref, err := expand_ref(r.Storer, plumbing.ReferenceName(revisionRef)) - if err == nil { - tryHashes = append(tryHashes, ref.Hash()) - } - - // in ambiguous cases, `git rev-parse` will emit a warning, but - // will always return the oid in preference to a ref; we don't have - // the ability to emit a warning here, so (for speed purposes) - // don't bother to detect the ambiguity either, just return in the - // priority that git would. - gotOne := false - for _, hash := range tryHashes { - commitObj, err := r.CommitObject(hash) - if err == nil { - commit = commitObj - gotOne = true - break - } - - tagObj, err := r.TagObject(hash) - if err == nil { - // If the tag target lookup fails here, this most likely - // represents some sort of repo corruption, so let the - // error bubble up. - tagCommit, err := tagObj.Commit() - if err != nil { - return &plumbing.ZeroHash, err - } - commit = tagCommit - gotOne = true - break - } - } - - if !gotOne { - return &plumbing.ZeroHash, plumbing.ErrReferenceNotFound - } - - case revision.CaretPath: - depth := item.Depth - - if depth == 0 { - break - } - - iter := commit.Parents() - - c, err := iter.Next() - if err != nil { - return &plumbing.ZeroHash, err - } - - if depth == 1 { - commit = c - - break - } - - c, err = iter.Next() - if err != nil { - return &plumbing.ZeroHash, err - } - - commit = c - case revision.TildePath: - for i := 0; i < item.Depth; i++ { - c, err := commit.Parents().Next() - if err != nil { - return &plumbing.ZeroHash, err - } - - commit = c - } - case revision.CaretReg: - history := object.NewCommitPreorderIter(commit, nil, nil) - - re := item.Regexp - negate := item.Negate - - var c *object.Commit - - err := history.ForEach(func(hc *object.Commit) error { - if !negate && re.MatchString(hc.Message) { - c = hc - return storer.ErrStop - } - - if negate && !re.MatchString(hc.Message) { - c = hc - return storer.ErrStop - } - - return nil - }) - if err != nil { - return &plumbing.ZeroHash, err - } - - if c == nil { - return &plumbing.ZeroHash, fmt.Errorf("no commit message match regexp: %q", re.String()) - } - - commit = c - } - } - - if commit == nil { - return &plumbing.ZeroHash, plumbing.ErrReferenceNotFound - } - - return &commit.Hash, nil -} - -// resolveHashPrefix returns a list of potential hashes that the given string -// is a prefix of. It quietly swallows errors, returning nil. -func (r *Repository) resolveHashPrefix(hashStr string) []plumbing.Hash { - // Handle complete and partial hashes. - // plumbing.NewHash forces args into a full 20 byte hash, which isn't suitable - // for partial hashes since they will become zero-filled. - - if hashStr == "" { - return nil - } - if len(hashStr) == plumbing.ZeroHash.HexSize() { - h, ok := plumbing.FromHex(hashStr) - if !ok { - return nil - } - return []plumbing.Hash{h} - } - - // Partial hash. - // hex.DecodeString only decodes to complete bytes, so only works with pairs of hex digits. - evenHex := hashStr[:len(hashStr)&^1] - hexb, err := hex.DecodeString(evenHex) - if err != nil { - return nil - } - candidates := expandPartialHash(r.Storer, hexb) - if len(evenHex) == len(hashStr) { - // The prefix was an exact number of bytes. - return candidates - } - // Do another prefix check to ensure the dangling nybble is correct. - var hashes []plumbing.Hash - for _, h := range candidates { - if strings.HasPrefix(h.String(), hashStr) { - hashes = append(hashes, h) - } - } - return hashes -} - -type RepackConfig struct { - // UseRefDeltas configures whether packfile encoder will use reference deltas. - // By default OFSDeltaObject is used. - UseRefDeltas bool - // OnlyDeletePacksOlderThan if set to non-zero value - // selects only objects older than the time provided. - OnlyDeletePacksOlderThan time.Time -} - -func (r *Repository) RepackObjects(cfg *RepackConfig) (err error) { - pos, ok := r.Storer.(storer.PackedObjectStorer) - if !ok { - return ErrPackedObjectsNotSupported - } - - // Get the existing object packs. - hs, err := pos.ObjectPacks() - if err != nil { - return err - } - - // Create a new pack. - nh, err := r.createNewObjectPack(cfg) - if err != nil { - return err - } - - // Delete old packs. - for _, h := range hs { - // Skip if new hash is the same as an old one. - if h == nh { - continue - } - err = pos.DeleteOldObjectPackAndIndex(h, cfg.OnlyDeletePacksOlderThan) - if err != nil { - return err - } - } - - return nil -} - -// Merge merges the reference branch into the current branch. -// -// If the merge is not possible (or supported) returns an error without changing -// the HEAD for the current branch. Possible errors include: -// - The merge strategy is not supported. -// - The specific strategy cannot be used (e.g. using FastForwardMerge when one is not possible). -func (r *Repository) Merge(ref plumbing.Reference, opts MergeOptions) error { - if opts.Strategy != FastForwardMerge { - return ErrUnsupportedMergeStrategy - } - - // Ignore error as not having a shallow list is optional here. - shallowList, _ := r.Storer.Shallow() - var earliestShallow *plumbing.Hash - if len(shallowList) > 0 { - earliestShallow = &shallowList[0] - } - - head, err := r.Head() - if err != nil { - return err - } - - ff, err := isFastForward(r.Storer, head.Hash(), ref.Hash(), earliestShallow) - if err != nil { - return err - } - - if !ff { - return ErrFastForwardMergeNotPossible - } - - return r.Storer.SetReference(plumbing.NewHashReference(head.Name(), ref.Hash())) -} - -// createNewObjectPack is a helper for RepackObjects taking care -// of creating a new pack. It is used so the PackfileWriter -// deferred close has the right scope. -func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, err error) { - ow := newObjectWalker(r.Storer) - err = ow.walkAllRefs() - if err != nil { - return h, err - } - objs := make([]plumbing.Hash, 0, len(ow.seen)) - for h := range ow.seen { - objs = append(objs, h) - } - pfw, ok := r.Storer.(storer.PackfileWriter) - if !ok { - return h, fmt.Errorf("Repository storer is not a storer.PackfileWriter") - } - wc, err := pfw.PackfileWriter() - if err != nil { - return h, err - } - defer ioutil.CheckClose(wc, &err) - scfg, err := r.Config() - if err != nil { - return h, err - } - enc := packfile.NewEncoder(wc, r.Storer, cfg.UseRefDeltas) - h, err = enc.Encode(objs, scfg.Pack.Window) - if err != nil { - return h, err - } - - // Delete the packed, loose objects. - if los, ok := r.Storer.(storer.LooseObjectStorer); ok { - err = los.ForEachObjectHash(func(hash plumbing.Hash) error { - if ow.isSeen(hash) { - err = los.DeleteLooseObject(hash) - if err != nil { - return err - } - } - return nil - }) - if err != nil { - return h, err - } - } - - return h, err -} - -func expandPartialHash(st storer.EncodedObjectStorer, prefix []byte) (hashes []plumbing.Hash) { - // The fast version is implemented by storage/filesystem.ObjectStorage. - type fastIter interface { - HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error) - } - if fi, ok := st.(fastIter); ok { - h, err := fi.HashesWithPrefix(prefix) - if err != nil { - return nil - } - return h - } - - // Slow path. - iter, err := st.IterEncodedObjects(plumbing.AnyObject) - if err != nil { - return nil - } - iter.ForEach(func(obj plumbing.EncodedObject) error { - h := obj.Hash() - if h.HasPrefix(prefix) { - hashes = append(hashes, h) - } - return nil - }) - return -} diff --git a/vendor/github.com/go-git/go-git/v6/signer.go b/vendor/github.com/go-git/go-git/v6/signer.go deleted file mode 100644 index b4f2b514..00000000 --- a/vendor/github.com/go-git/go-git/v6/signer.go +++ /dev/null @@ -1,33 +0,0 @@ -package git - -import ( - "io" - - "github.com/go-git/go-git/v6/plumbing" -) - -// signableObject is an object which can be signed. -type signableObject interface { - EncodeWithoutSignature(o plumbing.EncodedObject) error -} - -// Signer is an interface for signing git objects. -// message is a reader containing the encoded object to be signed. -// Implementors should return the encoded signature and an error if any. -// See https://git-scm.com/docs/gitformat-signature for more information. -type Signer interface { - Sign(message io.Reader) ([]byte, error) -} - -func signObject(signer Signer, obj signableObject) ([]byte, error) { - encoded := &plumbing.MemoryObject{} - if err := obj.EncodeWithoutSignature(encoded); err != nil { - return nil, err - } - r, err := encoded.Reader() - if err != nil { - return nil, err - } - - return signer.Sign(r) -} diff --git a/vendor/github.com/go-git/go-git/v6/status.go b/vendor/github.com/go-git/go-git/v6/status.go deleted file mode 100644 index 653728a6..00000000 --- a/vendor/github.com/go-git/go-git/v6/status.go +++ /dev/null @@ -1,148 +0,0 @@ -package git - -import ( - "bytes" - "fmt" - "path/filepath" - - mindex "github.com/go-git/go-git/v6/utils/merkletrie/index" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// Status represents the current status of a Worktree. -// The key of the map is the path of the file. -type Status map[string]*FileStatus - -// File returns the FileStatus for a given path, if the FileStatus doesn't -// exists a new FileStatus is added to the map using the path as key. -func (s Status) File(path string) *FileStatus { - if _, ok := (s)[path]; !ok { - s[path] = &FileStatus{Worktree: Untracked, Staging: Untracked} - } - - return s[path] -} - -// IsUntracked checks if file for given path is 'Untracked' -func (s Status) IsUntracked(path string) bool { - stat, ok := (s)[filepath.ToSlash(path)] - return ok && stat.Worktree == Untracked -} - -// IsClean returns true if all the files are in Unmodified status. -func (s Status) IsClean() bool { - for _, status := range s { - if status.Worktree != Unmodified || status.Staging != Unmodified { - return false - } - } - - return true -} - -func (s Status) String() string { - buf := bytes.NewBuffer(nil) - for path, status := range s { - if status.Staging == Unmodified && status.Worktree == Unmodified { - continue - } - - if status.Staging == Renamed { - path = fmt.Sprintf("%s -> %s", path, status.Extra) - } - - fmt.Fprintf(buf, "%c%c %s\n", status.Staging, status.Worktree, path) - } - - return buf.String() -} - -// FileStatus contains the status of a file in the worktree -type FileStatus struct { - // Staging is the status of a file in the staging area - Staging StatusCode - // Worktree is the status of a file in the worktree - Worktree StatusCode - // Extra contains extra information, such as the previous name in a rename - Extra string -} - -// StatusCode status code of a file in the Worktree -type StatusCode byte - -const ( - Unmodified StatusCode = ' ' - Untracked StatusCode = '?' - Modified StatusCode = 'M' - Added StatusCode = 'A' - Deleted StatusCode = 'D' - Renamed StatusCode = 'R' - Copied StatusCode = 'C' - UpdatedButUnmerged StatusCode = 'U' -) - -// StatusStrategy defines the different types of strategies when processing -// the worktree status. -type StatusStrategy int - -const ( - // TODO: (V6) Review the default status strategy. - // TODO: (V6) Review the type used to represent Status, to enable lazy - // processing of statuses going direct to the backing filesystem. - defaultStatusStrategy = Empty - - // Empty starts its status map from empty. Missing entries for a given - // path means that the file is untracked. This causes a known issue (#119) - // whereby unmodified files can be incorrectly reported as untracked. - // - // This can be used when returning the changed state within a modified Worktree. - // For example, to check whether the current worktree is clean. - Empty StatusStrategy = 0 - // Preload goes through all existing nodes from the index and add them to the - // status map as unmodified. This is currently the most reliable strategy - // although it comes at a performance cost in large repositories. - // - // This method is recommended when fetching the status of unmodified files. - // For example, to confirm the status of a specific file that is either - // untracked or unmodified. - Preload StatusStrategy = 1 -) - -func (s StatusStrategy) new(w *Worktree) (Status, error) { - switch s { - case Preload: - return preloadStatus(w) - case Empty: - return make(Status), nil - } - return nil, fmt.Errorf("%w: %+v", ErrUnsupportedStatusStrategy, s) -} - -func preloadStatus(w *Worktree) (Status, error) { - idx, err := w.r.Storer.Index() - if err != nil { - return nil, err - } - - idxRoot := mindex.NewRootNode(idx) - nodes := []noder.Noder{idxRoot} - - status := make(Status) - for len(nodes) > 0 { - var node noder.Noder - node, nodes = nodes[0], nodes[1:] - if node.IsDir() { - children, err := node.Children() - if err != nil { - return nil, err - } - nodes = append(nodes, children...) - continue - } - fs := status.File(node.Name()) - fs.Worktree = Unmodified - fs.Staging = Unmodified - } - - return status, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/config.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/config.go deleted file mode 100644 index 1bc2ba30..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/config.go +++ /dev/null @@ -1,48 +0,0 @@ -package filesystem - -import ( - "os" - - "github.com/go-git/go-git/v6/config" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -type ConfigStorage struct { - dir *dotgit.DotGit -} - -func (c *ConfigStorage) Config() (conf *config.Config, err error) { - f, err := c.dir.Config() - if err != nil { - if os.IsNotExist(err) { - return config.NewConfig(), nil - } - - return nil, err - } - - defer ioutil.CheckClose(f, &err) - return config.ReadConfig(f) -} - -func (c *ConfigStorage) SetConfig(cfg *config.Config) (err error) { - if err = cfg.Validate(); err != nil { - return err - } - - f, err := c.dir.ConfigWriter() - if err != nil { - return err - } - - defer ioutil.CheckClose(f, &err) - - b, err := cfg.Marshal() - if err != nil { - return err - } - - _, err = f.Write(b) - return err -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/deltaobject.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/deltaobject.go deleted file mode 100644 index 41982521..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/deltaobject.go +++ /dev/null @@ -1,37 +0,0 @@ -package filesystem - -import ( - "github.com/go-git/go-git/v6/plumbing" -) - -type deltaObject struct { - plumbing.EncodedObject - base plumbing.Hash - hash plumbing.Hash - size int64 -} - -func newDeltaObject( - obj plumbing.EncodedObject, - hash plumbing.Hash, - base plumbing.Hash, - size int64) plumbing.DeltaObject { - return &deltaObject{ - EncodedObject: obj, - hash: hash, - base: base, - size: size, - } -} - -func (o *deltaObject) BaseHash() plumbing.Hash { - return o.base -} - -func (o *deltaObject) ActualSize() int64 { - return o.size -} - -func (o *deltaObject) ActualHash() plumbing.Hash { - return o.hash -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit.go deleted file mode 100644 index f68575b4..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit.go +++ /dev/null @@ -1,1279 +0,0 @@ -// https://github.com/git/git/blob/master/Documentation/gitrepository-layout.txt -package dotgit - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "os" - "path" - "path/filepath" - "reflect" - "runtime" - "sort" - "strings" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/helper/chroot" -) - -const ( - suffix = ".git" - packedRefsPath = "packed-refs" - configPath = "config" - indexPath = "index" - shallowPath = "shallow" - modulePath = "modules" - objectsPath = "objects" - packPath = "pack" - refsPath = "refs" - branchesPath = "branches" - hooksPath = "hooks" - infoPath = "info" - remotesPath = "remotes" - logsPath = "logs" - worktreesPath = "worktrees" - alternatesPath = "alternates" - - tmpPackedRefsPrefix = "._packed-refs" - - packPrefix = "pack-" - packExt = ".pack" - idxExt = ".idx" -) - -var ( - // ErrNotFound is returned by New when the path is not found. - ErrNotFound = errors.New("path not found") - // ErrIdxNotFound is returned by Idxfile when the idx file is not found - ErrIdxNotFound = errors.New("idx file not found") - // ErrPackfileNotFound is returned by Packfile when the packfile is not found - ErrPackfileNotFound = errors.New("packfile not found") - // ErrConfigNotFound is returned by Config when the config is not found - ErrConfigNotFound = errors.New("config file not found") - // ErrPackedRefsDuplicatedRef is returned when a duplicated reference is - // found in the packed-ref file. This is usually the case for corrupted git - // repositories. - ErrPackedRefsDuplicatedRef = errors.New("duplicated ref found in packed-ref file") - // ErrPackedRefsBadFormat is returned when the packed-ref file corrupt. - ErrPackedRefsBadFormat = errors.New("malformed packed-ref") - // ErrSymRefTargetNotFound is returned when a symbolic reference is - // targeting a non-existing object. This usually means the repository - // is corrupt. - ErrSymRefTargetNotFound = errors.New("symbolic reference target not found") - // ErrIsDir is returned when a reference file is attempting to be read, - // but the path specified is a directory. - ErrIsDir = errors.New("reference path is a directory") - // ErrEmptyRefFile is returned when a reference file is attempted to be read, - // but the file is empty - ErrEmptyRefFile = errors.New("ref file is empty") -) - -// Options holds configuration for the storage. -type Options struct { - // ExclusiveAccess means that the filesystem is not modified externally - // while the repo is open. - ExclusiveAccess bool - // KeepDescriptors makes the file descriptors to be reused but they will - // need to be manually closed calling Close(). - KeepDescriptors bool - // AlternatesFS provides the billy filesystem to be used for Git Alternates. - // If none is provided, it falls back to using the underlying instance used for - // DotGit. - AlternatesFS billy.Filesystem -} - -// The DotGit type represents a local git repository on disk. This -// type is not zero-value-safe, use the New function to initialize it. -type DotGit struct { - options Options - fs billy.Filesystem - - // incoming object directory information - incomingChecked bool - incomingDirName string - - objectList []plumbing.Hash // sorted - objectMap map[plumbing.Hash]struct{} - packList []plumbing.Hash - packMap map[plumbing.Hash]struct{} - - files map[plumbing.Hash]billy.File -} - -// New returns a DotGit value ready to be used. The path argument must -// be the absolute path of a git repository directory (e.g. -// "/foo/bar/.git"). -func New(fs billy.Filesystem) *DotGit { - return NewWithOptions(fs, Options{}) -} - -// NewWithOptions sets non default configuration options. -// See New for complete help. -func NewWithOptions(fs billy.Filesystem, o Options) *DotGit { - return &DotGit{ - options: o, - fs: fs, - } -} - -// Initialize creates all the folder scaffolding. -func (d *DotGit) Initialize() error { - mustExists := []string{ - d.fs.Join("objects", "info"), - d.fs.Join("objects", "pack"), - d.fs.Join("refs", "heads"), - d.fs.Join("refs", "tags"), - } - - for _, path := range mustExists { - _, err := d.fs.Stat(path) - if err == nil { - continue - } - - if !os.IsNotExist(err) { - return err - } - - if err := d.fs.MkdirAll(path, os.ModeDir|os.ModePerm); err != nil { - return err - } - } - - return nil -} - -// Close closes all opened files. -func (d *DotGit) Close() error { - var firstError error - if d.files != nil { - for _, f := range d.files { - err := f.Close() - if err != nil && firstError == nil { - firstError = err - continue - } - } - - d.files = nil - } - - if firstError != nil { - return firstError - } - - return nil -} - -// ConfigWriter returns a file pointer for write to the config file -func (d *DotGit) ConfigWriter() (billy.File, error) { - return d.fs.Create(configPath) -} - -// Config returns a file pointer for read to the config file -func (d *DotGit) Config() (billy.File, error) { - return d.fs.Open(configPath) -} - -// IndexWriter returns a file pointer for write to the index file -func (d *DotGit) IndexWriter() (billy.File, error) { - return d.fs.Create(indexPath) -} - -// Index returns a file pointer for read to the index file -func (d *DotGit) Index() (billy.File, error) { - return d.fs.Open(indexPath) -} - -// ShallowWriter returns a file pointer for write to the shallow file -func (d *DotGit) ShallowWriter() (billy.File, error) { - return d.fs.Create(shallowPath) -} - -// Shallow returns a file pointer for read to the shallow file -func (d *DotGit) Shallow() (billy.File, error) { - f, err := d.fs.Open(shallowPath) - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - - return nil, err - } - - return f, nil -} - -// NewObjectPack return a writer for a new packfile, it saves the packfile to -// disk and also generates and save the index for the given packfile. -func (d *DotGit) NewObjectPack() (*PackWriter, error) { - d.cleanPackList() - return newPackWrite(d.fs) -} - -// ObjectPacks returns the list of availables packfiles -func (d *DotGit) ObjectPacks() ([]plumbing.Hash, error) { - if !d.options.ExclusiveAccess { - return d.objectPacks() - } - - err := d.genPackList() - if err != nil { - return nil, err - } - - return d.packList, nil -} - -func (d *DotGit) objectPacks() ([]plumbing.Hash, error) { - packDir := d.fs.Join(objectsPath, packPath) - files, err := d.fs.ReadDir(packDir) - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - - return nil, err - } - - var packs []plumbing.Hash - for _, f := range files { - n := f.Name() - if !strings.HasSuffix(n, packExt) || !strings.HasPrefix(n, packPrefix) { - continue - } - - h := plumbing.NewHash(n[5 : len(n)-5]) // pack-(hash).pack - if h.IsZero() { - // Ignore files with badly-formatted names. - continue - } - packs = append(packs, h) - } - - return packs, nil -} - -func (d *DotGit) objectPackPath(hash plumbing.Hash, extension string) string { - return d.fs.Join(objectsPath, packPath, fmt.Sprintf("pack-%s.%s", hash.String(), extension)) -} - -func (d *DotGit) objectPackOpen(hash plumbing.Hash, extension string) (billy.File, error) { - if d.options.KeepDescriptors && extension == "pack" { - if d.files == nil { - d.files = make(map[plumbing.Hash]billy.File) - } - - f, ok := d.files[hash] - if ok { - return f, nil - } - } - - err := d.hasPack(hash) - if err != nil { - return nil, err - } - - path := d.objectPackPath(hash, extension) - pack, err := d.fs.Open(path) - if err != nil { - if os.IsNotExist(err) { - return nil, ErrPackfileNotFound - } - - return nil, err - } - - if d.options.KeepDescriptors && extension == "pack" { - d.files[hash] = pack - } - - return pack, nil -} - -// ObjectPack returns a fs.File of the given packfile -func (d *DotGit) ObjectPack(hash plumbing.Hash) (billy.File, error) { - err := d.hasPack(hash) - if err != nil { - return nil, err - } - - return d.objectPackOpen(hash, `pack`) -} - -// ObjectPackIdx returns a fs.File of the index file for a given packfile -func (d *DotGit) ObjectPackIdx(hash plumbing.Hash) (billy.File, error) { - err := d.hasPack(hash) - if err != nil { - return nil, err - } - - return d.objectPackOpen(hash, `idx`) -} - -func (d *DotGit) DeleteOldObjectPackAndIndex(hash plumbing.Hash, t time.Time) error { - d.cleanPackList() - - path := d.objectPackPath(hash, `pack`) - if !t.IsZero() { - fi, err := d.fs.Stat(path) - if err != nil { - return err - } - // too new, skip deletion. - if !fi.ModTime().Before(t) { - return nil - } - } - err := d.fs.Remove(path) - if err != nil { - return err - } - return d.fs.Remove(d.objectPackPath(hash, `idx`)) -} - -// NewObject return a writer for a new object file. -func (d *DotGit) NewObject() (*ObjectWriter, error) { - d.cleanObjectList() - - return newObjectWriter(d.fs) -} - -// ObjectsWithPrefix returns the hashes of objects that have the given prefix. -func (d *DotGit) ObjectsWithPrefix(prefix []byte) ([]plumbing.Hash, error) { - // Handle edge cases. - if len(prefix) < 1 { - return d.Objects() - } else if len(prefix) > plumbing.ZeroHash.Size() { - return nil, nil - } - - if d.options.ExclusiveAccess { - err := d.genObjectList() - if err != nil { - return nil, err - } - - // Rely on d.objectList being sorted. - // Figure out the half-open interval defined by the prefix. - first := sort.Search(len(d.objectList), func(i int) bool { - // Same as plumbing.HashSlice.Less. - return bytes.Compare(d.objectList[i].Bytes(), prefix) >= 0 - }) - lim := len(d.objectList) - if limPrefix, overflow := incBytes(prefix); !overflow { - lim = sort.Search(len(d.objectList), func(i int) bool { - // Same as plumbing.HashSlice.Less. - return bytes.Compare(d.objectList[i].Bytes(), limPrefix) >= 0 - }) - } - return d.objectList[first:lim], nil - } - - // This is the slow path. - var objects []plumbing.Hash - var n int - err := d.ForEachObjectHash(func(hash plumbing.Hash) error { - n++ - if bytes.HasPrefix(hash.Bytes(), prefix) { - objects = append(objects, hash) - } - return nil - }) - if err != nil { - return nil, err - } - return objects, nil -} - -// Objects returns a slice with the hashes of objects found under the -// .git/objects/ directory. -func (d *DotGit) Objects() ([]plumbing.Hash, error) { - if d.options.ExclusiveAccess { - err := d.genObjectList() - if err != nil { - return nil, err - } - - return d.objectList, nil - } - - var objects []plumbing.Hash - err := d.ForEachObjectHash(func(hash plumbing.Hash) error { - objects = append(objects, hash) - return nil - }) - if err != nil { - return nil, err - } - return objects, nil -} - -// ForEachObjectHash iterates over the hashes of objects found under the -// .git/objects/ directory and executes the provided function. -func (d *DotGit) ForEachObjectHash(fun func(plumbing.Hash) error) error { - if !d.options.ExclusiveAccess { - return d.forEachObjectHash(fun) - } - - err := d.genObjectList() - if err != nil { - return err - } - - for _, h := range d.objectList { - err := fun(h) - if err != nil { - return err - } - } - - return nil -} - -func (d *DotGit) forEachObjectHash(fun func(plumbing.Hash) error) error { - files, err := d.fs.ReadDir(objectsPath) - if err != nil { - if os.IsNotExist(err) { - return nil - } - - return err - } - - for _, f := range files { - if f.IsDir() && len(f.Name()) == 2 && isHex(f.Name()) { - base := f.Name() - d, err := d.fs.ReadDir(d.fs.Join(objectsPath, base)) - if err != nil { - return err - } - - for _, o := range d { - h := plumbing.NewHash(base + o.Name()) - if h.IsZero() { - // Ignore files with badly-formatted names. - continue - } - err = fun(h) - if err != nil { - return err - } - } - } - } - - return nil -} - -func (d *DotGit) cleanObjectList() { - d.objectMap = nil - d.objectList = nil -} - -func (d *DotGit) genObjectList() error { - if d.objectMap != nil { - return nil - } - - d.objectMap = make(map[plumbing.Hash]struct{}) - populate := func(h plumbing.Hash) error { - d.objectList = append(d.objectList, h) - d.objectMap[h] = struct{}{} - - return nil - } - if err := d.forEachObjectHash(populate); err != nil { - return err - } - plumbing.HashesSort(d.objectList) - return nil -} - -func (d *DotGit) hasObject(h plumbing.Hash) error { - if !d.options.ExclusiveAccess { - return nil - } - - err := d.genObjectList() - if err != nil { - return err - } - - _, ok := d.objectMap[h] - if !ok { - return plumbing.ErrObjectNotFound - } - - return nil -} - -func (d *DotGit) cleanPackList() { - d.packMap = nil - d.packList = nil -} - -func (d *DotGit) genPackList() error { - if d.packMap != nil { - return nil - } - - op, err := d.objectPacks() - if err != nil { - return err - } - - d.packMap = make(map[plumbing.Hash]struct{}) - d.packList = nil - - for _, h := range op { - d.packList = append(d.packList, h) - d.packMap[h] = struct{}{} - } - - return nil -} - -func (d *DotGit) hasPack(h plumbing.Hash) error { - if !d.options.ExclusiveAccess { - return nil - } - - err := d.genPackList() - if err != nil { - return err - } - - _, ok := d.packMap[h] - if !ok { - return ErrPackfileNotFound - } - - return nil -} - -func (d *DotGit) objectPath(h plumbing.Hash) string { - hex := h.String() - return d.fs.Join(objectsPath, hex[0:2], hex[2:h.HexSize()]) -} - -// incomingObjectPath is intended to add support for a git pre-receive hook -// to be written it adds support for go-git to find objects in an "incoming" -// directory, so that the library can be used to write a pre-receive hook -// that deals with the incoming objects. -// -// More on git hooks found here : https://git-scm.com/docs/githooks -// More on 'quarantine'/incoming directory here: -// -// https://git-scm.com/docs/git-receive-pack -func (d *DotGit) incomingObjectPath(h plumbing.Hash) string { - hString := h.String() - - if d.incomingDirName == "" { - return d.fs.Join(objectsPath, hString[0:2], hString[2:h.HexSize()]) - } - - return d.fs.Join(objectsPath, d.incomingDirName, hString[0:2], hString[2:h.HexSize()]) -} - -// hasIncomingObjects searches for an incoming directory and keeps its name -// so it doesn't have to be found each time an object is accessed. -func (d *DotGit) hasIncomingObjects() bool { - if !d.incomingChecked { - directoryContents, err := d.fs.ReadDir(objectsPath) - if err == nil { - for _, file := range directoryContents { - if file.IsDir() && (strings.HasPrefix(file.Name(), "tmp_objdir-incoming-") || - // Before Git 2.35 incoming commits directory had another prefix - strings.HasPrefix(file.Name(), "incoming-")) { - d.incomingDirName = file.Name() - } - } - } - - d.incomingChecked = true - } - - return d.incomingDirName != "" -} - -// Object returns a fs.File pointing the object file, if exists -func (d *DotGit) Object(h plumbing.Hash) (billy.File, error) { - err := d.hasObject(h) - if err != nil { - return nil, err - } - - obj1, err1 := d.fs.Open(d.objectPath(h)) - if os.IsNotExist(err1) && d.hasIncomingObjects() { - obj2, err2 := d.fs.Open(d.incomingObjectPath(h)) - if err2 != nil { - return obj1, err1 - } - return obj2, err2 - } - return obj1, err1 -} - -// ObjectStat returns a os.FileInfo pointing the object file, if exists -func (d *DotGit) ObjectStat(h plumbing.Hash) (os.FileInfo, error) { - err := d.hasObject(h) - if err != nil { - return nil, err - } - - obj1, err1 := d.fs.Stat(d.objectPath(h)) - if os.IsNotExist(err1) && d.hasIncomingObjects() { - obj2, err2 := d.fs.Stat(d.incomingObjectPath(h)) - if err2 != nil { - return obj1, err1 - } - return obj2, err2 - } - return obj1, err1 -} - -// ObjectDelete removes the object file, if exists -func (d *DotGit) ObjectDelete(h plumbing.Hash) error { - d.cleanObjectList() - - err1 := d.fs.Remove(d.objectPath(h)) - if os.IsNotExist(err1) && d.hasIncomingObjects() { - err2 := d.fs.Remove(d.incomingObjectPath(h)) - if err2 != nil { - return err1 - } - return err2 - } - return err1 -} - -func (d *DotGit) readReferenceFrom(rd io.Reader, name string) (ref *plumbing.Reference, err error) { - b, err := io.ReadAll(rd) - if err != nil { - return nil, err - } - - if len(b) == 0 { - return nil, ErrEmptyRefFile - } - - line := strings.TrimSpace(string(b)) - return plumbing.NewReferenceFromStrings(name, line), nil -} - -// checkReferenceAndTruncate reads the reference from the given file, or the `pack-refs` file if -// the file was empty. Then it checks that the old reference matches the stored reference and -// truncates the file. -func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference) error { - if old == nil { - return nil - } - - ref, err := d.readReferenceFrom(f, old.Name().String()) - if errors.Is(err, ErrEmptyRefFile) { - // This may happen if the reference is being read from a newly created file. - // In that case, try getting the reference from the packed refs file. - ref, err = d.packedRef(old.Name()) - } - - if err != nil { - return err - } - - if ref.Hash() != old.Hash() { - return storage.ErrReferenceHasChanged - } - _, err = f.Seek(0, io.SeekStart) - if err != nil { - return err - } - return f.Truncate(0) -} - -func (d *DotGit) SetRef(r, old *plumbing.Reference) error { - var content string - switch r.Type() { - case plumbing.SymbolicReference: - content = fmt.Sprintf("ref: %s\n", r.Target()) - case plumbing.HashReference: - content = fmt.Sprintln(r.Hash().String()) - } - - fileName := r.Name().String() - - return d.setRef(fileName, content, old) -} - -// Refs scans the git directory collecting references, which it returns. -// Symbolic references are resolved and included in the output. -func (d *DotGit) Refs() ([]*plumbing.Reference, error) { - var refs []*plumbing.Reference - seen := make(map[plumbing.ReferenceName]bool) - if err := d.addRefFromHEAD(&refs); err != nil { - return nil, err - } - - if err := d.addRefsFromRefDir(&refs, seen); err != nil { - return nil, err - } - - if err := d.addRefsFromPackedRefs(&refs, seen); err != nil { - return nil, err - } - - return refs, nil -} - -// Ref returns the reference for a given reference name. -func (d *DotGit) Ref(name plumbing.ReferenceName) (*plumbing.Reference, error) { - ref, err := d.readReferenceFile(".", name.String()) - if err == nil { - return ref, nil - } - - return d.packedRef(name) -} - -func (d *DotGit) findPackedRefsInFile(f billy.File, recv refsRecv) error { - s := bufio.NewScanner(f) - for s.Scan() { - ref, err := d.processLine(s.Text()) - if err != nil { - return err - } - - if !recv(ref) { - // skip parse - return nil - } - } - if err := s.Err(); err != nil { - return err - } - return nil -} - -// refsRecv: returning true means that the reference continues to be resolved, otherwise it is stopped, which will speed up the lookup of a single reference. -type refsRecv func(*plumbing.Reference) bool - -func (d *DotGit) findPackedRefs(recv refsRecv) error { - f, err := d.fs.Open(packedRefsPath) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - - defer ioutil.CheckClose(f, &err) - return d.findPackedRefsInFile(f, recv) -} - -func (d *DotGit) packedRef(name plumbing.ReferenceName) (*plumbing.Reference, error) { - var ref *plumbing.Reference - if err := d.findPackedRefs(func(r *plumbing.Reference) bool { - if r != nil && r.Name() == name { - ref = r - // ref found - return false - } - return true - }); err != nil { - return nil, err - } - if ref != nil { - return ref, nil - } - return nil, plumbing.ErrReferenceNotFound -} - -// RemoveRef removes a reference by name. -func (d *DotGit) RemoveRef(name plumbing.ReferenceName) error { - path := d.fs.Join(".", name.String()) - _, err := d.fs.Stat(path) - if err == nil { - err = d.fs.Remove(path) - // Drop down to remove it from the packed refs file, too. - } - - if err != nil && !os.IsNotExist(err) { - return err - } - - return d.rewritePackedRefsWithoutRef(name) -} - -func refsRecvFunc(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) refsRecv { - return func(r *plumbing.Reference) bool { - if r != nil && !seen[r.Name()] { - *refs = append(*refs, r) - seen[r.Name()] = true - } - return true - } -} - -func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) (err error) { - return d.findPackedRefs(refsRecvFunc(refs, seen)) -} - -func (d *DotGit) addRefsFromPackedRefsFile(refs *[]*plumbing.Reference, f billy.File, seen map[plumbing.ReferenceName]bool) (err error) { - return d.findPackedRefsInFile(f, refsRecvFunc(refs, seen)) -} - -func (d *DotGit) openAndLockPackedRefs(doCreate bool) ( - pr billy.File, err error, -) { - var f billy.File - defer func() { - if err != nil && f != nil { - ioutil.CheckClose(f, &err) - } - }() - - // File mode is retrieved from a constant defined in the target specific - // files (dotgit_rewrite_packed_refs_*). Some modes are not available - // in all filesystems. - openFlags := d.openAndLockPackedRefsMode() - if doCreate { - openFlags |= os.O_CREATE - } - - start := time.Now() - // Keep trying to open and lock the file until we're sure the file - // didn't change between the open and the lock. - for { - // The arbitrary timeout should eventually be replaced with - // context-based check. - if time.Since(start) > 15*time.Second { - return nil, errors.New("timeout trying to lock packed refs") - } - f, err = d.fs.OpenFile(packedRefsPath, openFlags, 0600) - if err != nil { - if os.IsNotExist(err) && !doCreate { - return nil, nil - } - - return nil, err - } - fi, err := d.fs.Stat(packedRefsPath) - if err != nil { - return nil, err - } - mtime := fi.ModTime() - - err = f.Lock() - if err != nil { - return nil, err - } - - fi, err = d.fs.Stat(packedRefsPath) - if err != nil { - return nil, err - } - if mtime.Equal(fi.ModTime()) { - break - } - // The file has changed since we opened it. Close and retry. - err = f.Close() - if err != nil { - return nil, err - } - } - return f, nil -} - -func (d *DotGit) rewritePackedRefsWithoutRef(name plumbing.ReferenceName) (err error) { - pr, err := d.openAndLockPackedRefs(false) - if err != nil { - return err - } - if pr == nil { - return nil - } - defer ioutil.CheckClose(pr, &err) - - // Creating the temp file in the same directory as the target file - // improves our chances for rename operation to be atomic. - tmp, err := d.fs.TempFile("", tmpPackedRefsPrefix) - if err != nil { - return err - } - tmpName := tmp.Name() - defer func() { - ioutil.CheckClose(tmp, &err) - _ = d.fs.Remove(tmpName) // don't check err, we might have renamed it - }() - - s := bufio.NewScanner(pr) - found := false - for s.Scan() { - line := s.Text() - ref, err := d.processLine(line) - if err != nil { - return err - } - - if ref != nil && ref.Name() == name { - found = true - continue - } - - if _, err := fmt.Fprintln(tmp, line); err != nil { - return err - } - } - - if err := s.Err(); err != nil { - return err - } - - if !found { - return nil - } - - return d.rewritePackedRefsWhileLocked(tmp, pr) -} - -// process lines from a packed-refs file -func (d *DotGit) processLine(line string) (*plumbing.Reference, error) { - if len(line) == 0 { - return nil, nil - } - - switch line[0] { - case '#': // comment - ignore - return nil, nil - case '^': // annotated tag commit of the previous line - ignore - return nil, nil - default: - ws := strings.Split(line, " ") // hash then ref - if len(ws) != 2 { - return nil, ErrPackedRefsBadFormat - } - - return plumbing.NewReferenceFromStrings(ws[1], ws[0]), nil - } -} - -func (d *DotGit) addRefsFromRefDir(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) error { - return d.walkReferencesTree(refs, []string{refsPath}, seen) -} - -func (d *DotGit) walkReferencesTree(refs *[]*plumbing.Reference, relPath []string, seen map[plumbing.ReferenceName]bool) error { - files, err := d.fs.ReadDir(d.fs.Join(relPath...)) - if err != nil { - if os.IsNotExist(err) { - // a race happened, and our directory is gone now - return nil - } - - return err - } - - for _, f := range files { - newRelPath := append(append([]string(nil), relPath...), f.Name()) - if f.IsDir() { - if err = d.walkReferencesTree(refs, newRelPath, seen); err != nil { - return err - } - - continue - } - - ref, err := d.readReferenceFile(".", strings.Join(newRelPath, "/")) - if os.IsNotExist(err) { - // a race happened, and our file is gone now - continue - } - if err != nil { - return err - } - - if ref != nil && !seen[ref.Name()] { - *refs = append(*refs, ref) - seen[ref.Name()] = true - } - } - - return nil -} - -func (d *DotGit) addRefFromHEAD(refs *[]*plumbing.Reference) error { - ref, err := d.readReferenceFile(".", "HEAD") - if err != nil { - if os.IsNotExist(err) { - return nil - } - - return err - } - - *refs = append(*refs, ref) - return nil -} - -func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference, err error) { - path = d.fs.Join(path, d.fs.Join(strings.Split(name, "/")...)) - st, err := d.fs.Stat(path) - if err != nil { - return nil, err - } - if st.IsDir() { - return nil, ErrIsDir - } - - f, err := d.fs.Open(path) - if err != nil { - return nil, err - } - defer ioutil.CheckClose(f, &err) - - return d.readReferenceFrom(f, name) -} - -func (d *DotGit) CountLooseRefs() (int, error) { - var refs []*plumbing.Reference - seen := make(map[plumbing.ReferenceName]bool) - if err := d.addRefsFromRefDir(&refs, seen); err != nil { - return 0, err - } - - return len(refs), nil -} - -// PackRefs packs all loose refs into the packed-refs file. -// -// This implementation only works under the assumption that the view -// of the file system won't be updated during this operation. This -// strategy would not work on a general file system though, without -// locking each loose reference and checking it again before deleting -// the file, because otherwise an updated reference could sneak in and -// then be deleted by the packed-refs process. Alternatively, every -// ref update could also lock packed-refs, so only one lock is -// required during ref-packing. But that would worsen performance in -// the common case. -// -// TODO: add an "all" boolean like the `git pack-refs --all` flag. -// When `all` is false, it would only pack refs that have already been -// packed, plus all tags. -func (d *DotGit) PackRefs() (err error) { - // Lock packed-refs, and create it if it doesn't exist yet. - f, err := d.openAndLockPackedRefs(true) - if err != nil { - return err - } - defer ioutil.CheckClose(f, &err) - - // Gather all refs using addRefsFromRefDir and addRefsFromPackedRefs. - var refs []*plumbing.Reference - seen := make(map[plumbing.ReferenceName]bool) - if err = d.addRefsFromRefDir(&refs, seen); err != nil { - return err - } - if len(refs) == 0 { - // Nothing to do! - return nil - } - numLooseRefs := len(refs) - if err = d.addRefsFromPackedRefsFile(&refs, f, seen); err != nil { - return err - } - - // Write them all to a new temp packed-refs file. - tmp, err := d.fs.TempFile("", tmpPackedRefsPrefix) - if err != nil { - return err - } - tmpName := tmp.Name() - defer func() { - ioutil.CheckClose(tmp, &err) - _ = d.fs.Remove(tmpName) // don't check err, we might have renamed it - }() - - w := bufio.NewWriter(tmp) - for _, ref := range refs { - _, err = w.WriteString(ref.String() + "\n") - if err != nil { - return err - } - } - err = w.Flush() - if err != nil { - return err - } - - // Rename the temp packed-refs file. - err = d.rewritePackedRefsWhileLocked(tmp, f) - if err != nil { - return err - } - - // Delete all the loose refs, while still holding the packed-refs - // lock. - for _, ref := range refs[:numLooseRefs] { - path := d.fs.Join(".", ref.Name().String()) - err = d.fs.Remove(path) - if err != nil && !os.IsNotExist(err) { - return err - } - } - - return nil -} - -// Module return a billy.Filesystem pointing to the module folder -func (d *DotGit) Module(name string) (billy.Filesystem, error) { - return d.fs.Chroot(d.fs.Join(modulePath, name)) -} - -func (d *DotGit) AddAlternate(remote string) error { - altpath := d.fs.Join(objectsPath, infoPath, alternatesPath) - - f, err := d.fs.OpenFile(altpath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0640) - if err != nil { - return fmt.Errorf("cannot open file: %w", err) - } - defer f.Close() - - // locking in windows throws an error, based on comments - // https://github.com/go-git/go-git/pull/860#issuecomment-1751823044 - // do not lock on windows platform. - if runtime.GOOS != "windows" { - if err = f.Lock(); err != nil { - return fmt.Errorf("cannot lock file: %w", err) - } - defer f.Unlock() - } - - line := path.Join(remote, objectsPath) + "\n" - _, err = io.WriteString(f, line) - if err != nil { - return fmt.Errorf("error writing 'alternates' file: %w", err) - } - - return nil -} - -// Alternates returns DotGit(s) based off paths in objects/info/alternates if -// available. This can be used to checks if it's a shared repository. -func (d *DotGit) Alternates() ([]*DotGit, error) { - altpath := d.fs.Join(objectsPath, infoPath, alternatesPath) - f, err := d.fs.Open(altpath) - if err != nil { - return nil, err - } - defer f.Close() - - fs := d.options.AlternatesFS - if fs == nil { - fs = d.fs - } - - var alternates []*DotGit - seen := make(map[string]struct{}) - - // Read alternate paths line-by-line and create DotGit objects. - scanner := bufio.NewScanner(f) - for scanner.Scan() { - path := scanner.Text() - - // Avoid creating multiple dotgits for the same alternative path. - if _, ok := seen[path]; ok { - continue - } - - seen[path] = struct{}{} - - if filepath.IsAbs(path) { - // Handling absolute paths should be straight-forward. However, the default osfs (Chroot) - // tries to concatenate an abs path with the root path in some operations (e.g. Stat), - // which leads to unexpected errors. Therefore, make the path relative to the current FS instead. - if reflect.TypeOf(fs) == reflect.TypeOf(&chroot.ChrootHelper{}) { - path, err = filepath.Rel(fs.Root(), path) - if err != nil { - return nil, fmt.Errorf("cannot make path %q relative: %w", path, err) - } - } - } else { - // By Git conventions, relative paths should be based on the object database (.git/objects/info) - // location as per: https://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html - // However, due to the nature of go-git and its filesystem handling via Billy, paths cannot - // cross its "chroot boundaries". Therefore, ignore any "../" and treat the path from the - // fs root. If this is not correct based on the dotgit fs, set a different one via AlternatesFS. - abs := filepath.Join(string(filepath.Separator), filepath.ToSlash(path)) - path = filepath.FromSlash(abs) - } - - // Aligns with upstream behavior: exit if target path is not a valid directory. - if fi, err := fs.Stat(path); err != nil || !fi.IsDir() { - return nil, fmt.Errorf("invalid object directory %q: %w", path, err) - } - afs, err := fs.Chroot(filepath.Dir(path)) - if err != nil { - return nil, fmt.Errorf("cannot chroot %q: %w", path, err) - } - alternates = append(alternates, New(afs)) - } - - if err = scanner.Err(); err != nil { - return nil, err - } - - return alternates, nil -} - -// Fs returns the underlying filesystem of the DotGit folder. -func (d *DotGit) Fs() billy.Filesystem { - return d.fs -} - -func isHex(s string) bool { - for _, b := range []byte(s) { - if isNum(b) { - continue - } - if isHexAlpha(b) { - continue - } - - return false - } - - return true -} - -func isNum(b byte) bool { - return b >= '0' && b <= '9' -} - -func isHexAlpha(b byte) bool { - return b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F' -} - -// incBytes increments a byte slice, which involves incrementing the -// right-most byte, and following carry leftward. -// It makes a copy so that the provided slice's underlying array is not modified. -// If the overall operation overflows (e.g. incBytes(0xff, 0xff)), the second return parameter indicates that. -func incBytes(in []byte) (out []byte, overflow bool) { - out = make([]byte, len(in)) - copy(out, in) - for i := len(out) - 1; i >= 0; i-- { - out[i]++ - if out[i] != 0 { - return // Didn't overflow. - } - } - overflow = true - return -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go deleted file mode 100644 index 03ad5309..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go +++ /dev/null @@ -1,81 +0,0 @@ -package dotgit - -import ( - "io" - "os" - "runtime" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -func (d *DotGit) openAndLockPackedRefsMode() int { - if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) { - return os.O_RDWR - } - - return os.O_RDONLY -} - -func (d *DotGit) rewritePackedRefsWhileLocked( - tmp billy.File, pr billy.File) error { - // Try plain rename. If we aren't using the bare Windows filesystem as the - // storage layer, we might be able to get away with a rename over a locked - // file. - err := d.fs.Rename(tmp.Name(), pr.Name()) - if err == nil { - return nil - } - - // If we are in a filesystem that does not support rename (e.g. sivafs) - // a full copy is done. - if err == billy.ErrNotSupported { - return d.copyNewFile(tmp, pr) - } - - if runtime.GOOS != "windows" { - return err - } - - // Otherwise, Windows doesn't let us rename over a locked file, so - // we have to do a straight copy. Unfortunately this could result - // in a partially-written file if the process fails before the - // copy completes. - return d.copyToExistingFile(tmp, pr) -} - -func (d *DotGit) copyToExistingFile(tmp, pr billy.File) error { - _, err := pr.Seek(0, io.SeekStart) - if err != nil { - return err - } - err = pr.Truncate(0) - if err != nil { - return err - } - _, err = tmp.Seek(0, io.SeekStart) - if err != nil { - return err - } - _, err = ioutil.CopyBufferPool(pr, tmp) - - return err -} - -func (d *DotGit) copyNewFile(tmp billy.File, pr billy.File) (err error) { - prWrite, err := d.fs.Create(pr.Name()) - if err != nil { - return err - } - - defer ioutil.CheckClose(prWrite, &err) - - _, err = tmp.Seek(0, io.SeekStart) - if err != nil { - return err - } - - _, err = ioutil.CopyBufferPool(prWrite, tmp) - - return err -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_setref.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_setref.go deleted file mode 100644 index 871526fe..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/dotgit_setref.go +++ /dev/null @@ -1,90 +0,0 @@ -package dotgit - -import ( - "fmt" - "os" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/utils/ioutil" - - "github.com/go-git/go-billy/v6" -) - -func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err error) { - if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) { - return d.setRefRwfs(fileName, content, old) - } - - return d.setRefNorwfs(fileName, content, old) -} - -func (d *DotGit) setRefRwfs(fileName, content string, old *plumbing.Reference) (err error) { - // If we are not checking an old ref, just truncate the file. - mode := os.O_RDWR | os.O_CREATE - if old == nil { - mode |= os.O_TRUNC - } - - f, err := d.fs.OpenFile(fileName, mode, 0666) - if err != nil { - return err - } - - defer ioutil.CheckClose(f, &err) - - // Lock is unlocked by the deferred Close above. This is because Unlock - // does not imply a fsync and thus there would be a race between - // Unlock+Close and other concurrent writers. Adding Sync to go-billy - // could work, but this is better (and avoids superfluous syncs). - err = f.Lock() - if err != nil { - return err - } - - // this is a no-op to call even when old is nil. - err = d.checkReferenceAndTruncate(f, old) - if err != nil { - return err - } - - _, err = f.Write([]byte(content)) - return err -} - -// There are some filesystems that don't support opening files in RDWD mode. -// In these filesystems the standard SetRef function can not be used as it -// reads the reference file to check that it's not modified before updating it. -// -// This version of the function writes the reference without extra checks -// making it compatible with these simple filesystems. This is usually not -// a problem as they should be accessed by only one process at a time. -func (d *DotGit) setRefNorwfs(fileName, content string, old *plumbing.Reference) error { - _, err := d.fs.Stat(fileName) - if err == nil && old != nil { - fRead, err := d.fs.Open(fileName) - if err != nil { - return err - } - - ref, err := d.readReferenceFrom(fRead, old.Name().String()) - fRead.Close() - - if err != nil { - return err - } - - if ref.Hash() != old.Hash() { - return fmt.Errorf("reference has changed concurrently") - } - } - - f, err := d.fs.Create(fileName) - if err != nil { - return err - } - - defer f.Close() - - _, err = f.Write([]byte(content)) - return err -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/reader.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/reader.go deleted file mode 100644 index 5a910326..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/reader.go +++ /dev/null @@ -1,79 +0,0 @@ -package dotgit - -import ( - "fmt" - "io" - "os" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/objfile" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -var _ (plumbing.EncodedObject) = &EncodedObject{} - -type EncodedObject struct { - dir *DotGit - h plumbing.Hash - t plumbing.ObjectType - sz int64 -} - -func (e *EncodedObject) Hash() plumbing.Hash { - return e.h -} - -func (e *EncodedObject) Reader() (io.ReadCloser, error) { - f, err := e.dir.Object(e.h) - if err != nil { - if os.IsNotExist(err) { - return nil, plumbing.ErrObjectNotFound - } - - return nil, err - } - r, err := objfile.NewReader(f) - if err != nil { - return nil, err - } - - t, size, err := r.Header() - if err != nil { - _ = r.Close() - return nil, err - } - if t != e.t { - _ = r.Close() - return nil, objfile.ErrHeader - } - if size != e.sz { - _ = r.Close() - return nil, objfile.ErrHeader - } - return ioutil.NewReadCloserWithCloser(r, f.Close), nil -} - -func (e *EncodedObject) SetType(plumbing.ObjectType) {} - -func (e *EncodedObject) Type() plumbing.ObjectType { - return e.t -} - -func (e *EncodedObject) Size() int64 { - return e.sz -} - -func (e *EncodedObject) SetSize(int64) {} - -func (e *EncodedObject) Writer() (io.WriteCloser, error) { - return nil, fmt.Errorf("not supported") -} - -func NewEncodedObject(dir *DotGit, h plumbing.Hash, t plumbing.ObjectType, size int64) *EncodedObject { - return &EncodedObject{ - dir: dir, - h: h, - t: t, - sz: size, - } -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/repository_filesystem.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/repository_filesystem.go deleted file mode 100644 index 85cba0c0..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/repository_filesystem.go +++ /dev/null @@ -1,111 +0,0 @@ -package dotgit - -import ( - "os" - "path/filepath" - "strings" - - "github.com/go-git/go-billy/v6" -) - -// RepositoryFilesystem is a billy.Filesystem compatible object wrapper -// which handles dot-git filesystem operations and supports commondir according to git scm layout: -// https://github.com/git/git/blob/master/Documentation/gitrepository-layout.txt -type RepositoryFilesystem struct { - dotGitFs billy.Filesystem - commonDotGitFs billy.Filesystem -} - -func NewRepositoryFilesystem(dotGitFs, commonDotGitFs billy.Filesystem) *RepositoryFilesystem { - return &RepositoryFilesystem{ - dotGitFs: dotGitFs, - commonDotGitFs: commonDotGitFs, - } -} - -func (fs *RepositoryFilesystem) mapToRepositoryFsByPath(path string) billy.Filesystem { - // Nothing to decide if commondir not defined - if fs.commonDotGitFs == nil { - return fs.dotGitFs - } - - cleanPath := filepath.Clean(path) - - // Check exceptions for commondir (https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt) - switch cleanPath { - case fs.dotGitFs.Join(logsPath, "HEAD"): - return fs.dotGitFs - case fs.dotGitFs.Join(refsPath, "bisect"), fs.dotGitFs.Join(refsPath, "rewritten"), fs.dotGitFs.Join(refsPath, "worktree"): - return fs.dotGitFs - } - - // Determine dot-git root by first path element. - // There are some elements which should always use commondir when commondir defined. - // Usual dot-git root will be used for the rest of files. - switch strings.Split(cleanPath, string(filepath.Separator))[0] { - case objectsPath, refsPath, packedRefsPath, configPath, branchesPath, hooksPath, infoPath, remotesPath, logsPath, shallowPath, worktreesPath: - return fs.commonDotGitFs - default: - return fs.dotGitFs - } -} - -func (fs *RepositoryFilesystem) Create(filename string) (billy.File, error) { - return fs.mapToRepositoryFsByPath(filename).Create(filename) -} - -func (fs *RepositoryFilesystem) Open(filename string) (billy.File, error) { - return fs.mapToRepositoryFsByPath(filename).Open(filename) -} - -func (fs *RepositoryFilesystem) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) { - return fs.mapToRepositoryFsByPath(filename).OpenFile(filename, flag, perm) -} - -func (fs *RepositoryFilesystem) Stat(filename string) (os.FileInfo, error) { - return fs.mapToRepositoryFsByPath(filename).Stat(filename) -} - -func (fs *RepositoryFilesystem) Rename(oldpath, newpath string) error { - return fs.mapToRepositoryFsByPath(oldpath).Rename(oldpath, newpath) -} - -func (fs *RepositoryFilesystem) Remove(filename string) error { - return fs.mapToRepositoryFsByPath(filename).Remove(filename) -} - -func (fs *RepositoryFilesystem) Join(elem ...string) string { - return fs.dotGitFs.Join(elem...) -} - -func (fs *RepositoryFilesystem) TempFile(dir, prefix string) (billy.File, error) { - return fs.mapToRepositoryFsByPath(dir).TempFile(dir, prefix) -} - -func (fs *RepositoryFilesystem) ReadDir(path string) ([]os.FileInfo, error) { - return fs.mapToRepositoryFsByPath(path).ReadDir(path) -} - -func (fs *RepositoryFilesystem) MkdirAll(filename string, perm os.FileMode) error { - return fs.mapToRepositoryFsByPath(filename).MkdirAll(filename, perm) -} - -func (fs *RepositoryFilesystem) Lstat(filename string) (os.FileInfo, error) { - return fs.mapToRepositoryFsByPath(filename).Lstat(filename) -} - -func (fs *RepositoryFilesystem) Symlink(target, link string) error { - return fs.mapToRepositoryFsByPath(target).Symlink(target, link) -} - -func (fs *RepositoryFilesystem) Readlink(link string) (string, error) { - return fs.mapToRepositoryFsByPath(link).Readlink(link) -} - -func (fs *RepositoryFilesystem) Chroot(path string) (billy.Filesystem, error) { - return fs.mapToRepositoryFsByPath(path).Chroot(path) -} - -func (fs *RepositoryFilesystem) Root() string { - return fs.dotGitFs.Root() -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/writers.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/writers.go deleted file mode 100644 index f8e1983c..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/dotgit/writers.go +++ /dev/null @@ -1,281 +0,0 @@ -package dotgit - -import ( - "fmt" - "io" - "sync/atomic" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" - "github.com/go-git/go-git/v6/plumbing/format/objfile" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - - "github.com/go-git/go-billy/v6" -) - -// PackWriter is a io.Writer that generates the packfile index simultaneously, -// a packfile.Decoder is used with a file reader to read the file being written -// this operation is synchronized with the write operations. -// The packfile is written in a temp file, when Close is called this file -// is renamed/moved (depends on the Filesystem implementation) to the final -// location, if the PackWriter is not used, nothing is written. -type PackWriter struct { - Notify func(plumbing.Hash, *idxfile.Writer) - - fs billy.Filesystem - fr, fw billy.File - synced *syncedReader - checksum plumbing.Hash - parser *packfile.Parser - writer *idxfile.Writer - result chan error -} - -func newPackWrite(fs billy.Filesystem) (*PackWriter, error) { - fw, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_pack_") - if err != nil { - return nil, err - } - - fr, err := fs.Open(fw.Name()) - if err != nil { - return nil, err - } - - writer := &PackWriter{ - fs: fs, - fw: fw, - fr: fr, - synced: newSyncedReader(fw, fr), - result: make(chan error), - } - - go writer.buildIndex() - return writer, nil -} - -func (w *PackWriter) buildIndex() { - w.writer = new(idxfile.Writer) - var err error - - w.parser = packfile.NewParser(w.synced, packfile.WithScannerObservers(w.writer)) - - h, err := w.parser.Parse() - if err != nil { - w.result <- err - return - } - - w.checksum = h - w.result <- nil -} - -// waitBuildIndex waits until buildIndex function finishes, this can terminate -// with a packfile.ErrEmptyPackfile, this means that nothing was written so we -// ignore the error -func (w *PackWriter) waitBuildIndex() error { - err := <-w.result - if err == packfile.ErrEmptyPackfile { - return nil - } - - return err -} - -func (w *PackWriter) Write(p []byte) (int, error) { - return w.synced.Write(p) -} - -// Close closes all the file descriptors and save the final packfile, if nothing -// was written, the tempfiles are deleted without writing a packfile. -func (w *PackWriter) Close() error { - defer func() { - if w.Notify != nil && w.writer != nil && w.writer.Finished() { - w.Notify(w.checksum, w.writer) - } - - close(w.result) - }() - - if err := w.synced.Close(); err != nil { - return err - } - - if err := w.waitBuildIndex(); err != nil { - return err - } - - if err := w.fr.Close(); err != nil { - return err - } - - if err := w.fw.Close(); err != nil { - return err - } - - if w.writer == nil || !w.writer.Finished() { - return w.clean() - } - - return w.save() -} - -func (w *PackWriter) clean() error { - return w.fs.Remove(w.fw.Name()) -} - -func (w *PackWriter) save() error { - base := w.fs.Join(objectsPath, packPath, fmt.Sprintf("pack-%s", w.checksum)) - idx, err := w.fs.Create(fmt.Sprintf("%s.idx", base)) - if err != nil { - return err - } - - if err := w.encodeIdx(idx); err != nil { - return err - } - - if err := idx.Close(); err != nil { - return err - } - - return w.fs.Rename(w.fw.Name(), fmt.Sprintf("%s.pack", base)) -} - -func (w *PackWriter) encodeIdx(writer io.Writer) error { - idx, err := w.writer.Index() - if err != nil { - return err - } - - e := idxfile.NewEncoder(writer) - _, err = e.Encode(idx) - return err -} - -type syncedReader struct { - w io.Writer - r io.ReadSeeker - - blocked, done uint32 - written, read uint64 - news chan bool -} - -func newSyncedReader(w io.Writer, r io.ReadSeeker) *syncedReader { - return &syncedReader{ - w: w, - r: r, - news: make(chan bool), - } -} - -func (s *syncedReader) Write(p []byte) (n int, err error) { - defer func() { - written := atomic.AddUint64(&s.written, uint64(n)) - read := atomic.LoadUint64(&s.read) - if written > read { - s.wake() - } - }() - - n, err = s.w.Write(p) - return -} - -func (s *syncedReader) Read(p []byte) (n int, err error) { - defer func() { atomic.AddUint64(&s.read, uint64(n)) }() - - for { - s.sleep() - n, err = s.r.Read(p) - if err == io.EOF && !s.isDone() && n == 0 { - continue - } - - break - } - - return -} - -func (s *syncedReader) isDone() bool { - return atomic.LoadUint32(&s.done) == 1 -} - -func (s *syncedReader) isBlocked() bool { - return atomic.LoadUint32(&s.blocked) == 1 -} - -func (s *syncedReader) wake() { - if s.isBlocked() { - atomic.StoreUint32(&s.blocked, 0) - s.news <- true - } -} - -func (s *syncedReader) sleep() { - read := atomic.LoadUint64(&s.read) - written := atomic.LoadUint64(&s.written) - if read >= written { - atomic.StoreUint32(&s.blocked, 1) - <-s.news - } - -} - -func (s *syncedReader) Seek(offset int64, whence int) (int64, error) { - if whence == io.SeekCurrent { - return s.r.Seek(offset, whence) - } - - p, err := s.r.Seek(offset, whence) - atomic.StoreUint64(&s.read, uint64(p)) - - return p, err -} - -func (s *syncedReader) Close() error { - atomic.StoreUint32(&s.done, 1) - close(s.news) - return nil -} - -type ObjectWriter struct { - objfile.Writer - fs billy.Filesystem - f billy.File -} - -func newObjectWriter(fs billy.Filesystem) (*ObjectWriter, error) { - f, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_obj_") - if err != nil { - return nil, err - } - - return &ObjectWriter{ - Writer: (*objfile.NewWriter(f)), - fs: fs, - f: f, - }, nil -} - -func (w *ObjectWriter) Close() error { - if err := w.Writer.Close(); err != nil { - return err - } - - if err := w.f.Close(); err != nil { - return err - } - - return w.save() -} - -func (w *ObjectWriter) save() error { - h := w.Hash() - hex := h.String() - file := w.fs.Join(objectsPath, hex[0:2], hex[2:h.HexSize()]) - - return w.fs.Rename(w.f.Name(), file) -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/index.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/index.go deleted file mode 100644 index 0bd33204..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/index.go +++ /dev/null @@ -1,54 +0,0 @@ -package filesystem - -import ( - "bufio" - "os" - - "github.com/go-git/go-git/v6/plumbing/format/index" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -type IndexStorage struct { - dir *dotgit.DotGit -} - -func (s *IndexStorage) SetIndex(idx *index.Index) (err error) { - f, err := s.dir.IndexWriter() - if err != nil { - return err - } - - defer ioutil.CheckClose(f, &err) - bw := bufio.NewWriter(f) - defer func() { - if e := bw.Flush(); err == nil && e != nil { - err = e - } - }() - - e := index.NewEncoder(bw) - err = e.Encode(idx) - return err -} - -func (s *IndexStorage) Index() (i *index.Index, err error) { - idx := &index.Index{ - Version: 2, - } - - f, err := s.dir.Index() - if err != nil { - if os.IsNotExist(err) { - return idx, nil - } - - return nil, err - } - - defer ioutil.CheckClose(f, &err) - - d := index.NewDecoder(f) - err = d.Decode(idx) - return idx, err -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/module.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/module.go deleted file mode 100644 index 5aaf8f29..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/module.go +++ /dev/null @@ -1,20 +0,0 @@ -package filesystem - -import ( - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" -) - -type ModuleStorage struct { - dir *dotgit.DotGit -} - -func (s *ModuleStorage) Module(name string) (storage.Storer, error) { - fs, err := s.dir.Module(name) - if err != nil { - return nil, err - } - - return NewStorage(fs, cache.NewObjectLRUDefault()), nil -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/object.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/object.go deleted file mode 100644 index 3a71f304..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/object.go +++ /dev/null @@ -1,709 +0,0 @@ -package filesystem - -import ( - "crypto" - "errors" - "fmt" - "io" - "os" - "sync" - "time" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" - "github.com/go-git/go-git/v6/plumbing/format/objfile" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -type ObjectStorage struct { - options Options - - // objectCache is an object cache used to cache delta's bases and also recently - // loaded loose objects. - objectCache cache.Object - - dir *dotgit.DotGit - index map[plumbing.Hash]idxfile.Index - - packList []plumbing.Hash - packListIdx int - packfiles map[plumbing.Hash]*packfile.Packfile - muI sync.RWMutex - muP sync.RWMutex -} - -// NewObjectStorage creates a new ObjectStorage with the given .git directory and cache. -func NewObjectStorage(dir *dotgit.DotGit, objectCache cache.Object) *ObjectStorage { - return NewObjectStorageWithOptions(dir, objectCache, Options{}) -} - -// NewObjectStorageWithOptions creates a new ObjectStorage with the given .git directory, cache and extra options -func NewObjectStorageWithOptions(dir *dotgit.DotGit, objectCache cache.Object, ops Options) *ObjectStorage { - return &ObjectStorage{ - options: ops, - objectCache: objectCache, - dir: dir, - } -} - -func (s *ObjectStorage) requireIndex() error { - s.muI.RLock() - if s.index != nil { - s.muI.RUnlock() - return nil - } - s.muI.RUnlock() - - s.muI.Lock() - defer s.muI.Unlock() - - s.index = make(map[plumbing.Hash]idxfile.Index) - packs, err := s.dir.ObjectPacks() - if err != nil { - return err - } - - for _, h := range packs { - if err := s.loadIdxFile(h); err != nil { - return err - } - } - - return nil -} - -// Reindex indexes again all packfiles. Useful if git changed packfiles externally -func (s *ObjectStorage) Reindex() { - s.index = nil -} - -func (s *ObjectStorage) loadIdxFile(h plumbing.Hash) (err error) { - f, err := s.dir.ObjectPackIdx(h) - if err != nil { - return err - } - - defer ioutil.CheckClose(f, &err) - - idxf := idxfile.NewMemoryIndex(h.Size()) - d := idxfile.NewDecoder(f) - if err = d.Decode(idxf); err != nil { - return err - } - - s.index[h] = idxf - return err -} - -func (s *ObjectStorage) RawObjectWriter(typ plumbing.ObjectType, sz int64) (w io.WriteCloser, err error) { - ow, err := s.dir.NewObject() - if err != nil { - return nil, err - } - - err = ow.WriteHeader(typ, sz) - if err != nil { - return nil, err - } - - return ow, nil -} - -func (s *ObjectStorage) NewEncodedObject() plumbing.EncodedObject { - return &plumbing.MemoryObject{} -} - -func (s *ObjectStorage) PackfileWriter() (io.WriteCloser, error) { - if err := s.requireIndex(); err != nil { - return nil, err - } - - w, err := s.dir.NewObjectPack() - if err != nil { - return nil, err - } - - w.Notify = func(h plumbing.Hash, writer *idxfile.Writer) { - index, err := writer.Index() - if err == nil { - s.index[h] = index - } - } - - return w, nil -} - -// SetEncodedObject adds a new object to the storage. -func (s *ObjectStorage) SetEncodedObject(o plumbing.EncodedObject) (h plumbing.Hash, err error) { - if o.Type() == plumbing.OFSDeltaObject || o.Type() == plumbing.REFDeltaObject { - return plumbing.ZeroHash, plumbing.ErrInvalidType - } - - ow, err := s.dir.NewObject() - if err != nil { - return plumbing.ZeroHash, err - } - - defer ioutil.CheckClose(ow, &err) - - or, err := o.Reader() - if err != nil { - return plumbing.ZeroHash, err - } - - defer ioutil.CheckClose(or, &err) - - if err = ow.WriteHeader(o.Type(), o.Size()); err != nil { - return plumbing.ZeroHash, err - } - - if _, err = ioutil.CopyBufferPool(ow, or); err != nil { - return plumbing.ZeroHash, err - } - - return o.Hash(), err -} - -// LazyWriter returns a lazy ObjectWriter that is bound to a DotGit file. -// It first write the header passing on the object type and size, so -// that the object contents can be written later, without the need to -// create a MemoryObject and buffering its entire contents into memory. -func (s *ObjectStorage) LazyWriter() (w io.WriteCloser, wh func(typ plumbing.ObjectType, sz int64) error, err error) { - ow, err := s.dir.NewObject() - if err != nil { - return nil, nil, err - } - - return ow, ow.WriteHeader, nil -} - -// HasEncodedObject returns nil if the object exists, without actually -// reading the object data from storage. -func (s *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) { - // Check unpacked objects - f, err := s.dir.Object(h) - if err != nil { - if !os.IsNotExist(err) { - return err - } - // Fall through to check packed objects. - } else { - defer ioutil.CheckClose(f, &err) - return nil - } - - // Check packed objects. - if err := s.requireIndex(); err != nil { - return err - } - _, _, offset := s.findObjectInPackfile(h) - if offset == -1 { - return plumbing.ErrObjectNotFound - } - return nil -} - -func (s *ObjectStorage) encodedObjectSizeFromUnpacked(h plumbing.Hash) (size int64, err error) { - f, err := s.dir.Object(h) - if err != nil { - if os.IsNotExist(err) { - return 0, plumbing.ErrObjectNotFound - } - - return 0, err - } - - r, err := objfile.NewReader(f) - if err != nil { - return 0, err - } - defer ioutil.CheckClose(r, &err) - - _, size, err = r.Header() - return size, err -} - -func (s *ObjectStorage) packfile(idx idxfile.Index, pack plumbing.Hash) (*packfile.Packfile, error) { - if p := s.packfileFromCache(pack); p != nil { - return p, nil - } - - f, err := s.dir.ObjectPack(pack) - if err != nil { - return nil, err - } - - p := packfile.NewPackfile(f, - packfile.WithIdx(idx), - packfile.WithFs(s.dir.Fs()), - packfile.WithCache(s.objectCache), - packfile.WithObjectIDSize(pack.Size()), - ) - return p, s.storePackfileInCache(pack, p) -} - -func (s *ObjectStorage) packfileFromCache(hash plumbing.Hash) *packfile.Packfile { - s.muP.Lock() - defer s.muP.Unlock() - - if s.packfiles == nil { - if s.options.KeepDescriptors { - s.packfiles = make(map[plumbing.Hash]*packfile.Packfile) - } else if s.options.MaxOpenDescriptors > 0 { - s.packList = make([]plumbing.Hash, s.options.MaxOpenDescriptors) - s.packfiles = make(map[plumbing.Hash]*packfile.Packfile, s.options.MaxOpenDescriptors) - } - } - - return s.packfiles[hash] -} - -func (s *ObjectStorage) storePackfileInCache(hash plumbing.Hash, p *packfile.Packfile) error { - s.muP.Lock() - defer s.muP.Unlock() - - if s.options.KeepDescriptors { - s.packfiles[hash] = p - return nil - } - - if s.options.MaxOpenDescriptors <= 0 { - return nil - } - - // start over as the limit of packList is hit - if s.packListIdx >= len(s.packList) { - s.packListIdx = 0 - } - - // close the existing packfile if open - if next := s.packList[s.packListIdx]; !next.IsZero() { - open := s.packfiles[next] - delete(s.packfiles, next) - if open != nil { - if err := open.Close(); err != nil { - return err - } - } - } - - // cache newly open packfile - s.packList[s.packListIdx] = hash - s.packfiles[hash] = p - s.packListIdx++ - - return nil -} - -func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) (size int64, err error) { - if err := s.requireIndex(); err != nil { - return 0, err - } - - pack, _, offset := s.findObjectInPackfile(h) - if offset == -1 { - return 0, plumbing.ErrObjectNotFound - } - - idx := s.index[pack] - hash, err := idx.FindHash(offset) - if err == nil { - obj, ok := s.objectCache.Get(hash) - if ok { - return obj.Size(), nil - } - } else if err != nil && !errors.Is(err, plumbing.ErrObjectNotFound) { - return 0, err - } - - p, err := s.packfile(idx, pack) - if err != nil { - return 0, err - } - - if !s.options.KeepDescriptors && s.options.MaxOpenDescriptors == 0 { - defer ioutil.CheckClose(p, &err) - } - - return p.GetSizeByOffset(offset) -} - -// EncodedObjectSize returns the plaintext size of the given object, -// without actually reading the full object data from storage. -func (s *ObjectStorage) EncodedObjectSize(h plumbing.Hash) (size int64, err error) { - size, err = s.encodedObjectSizeFromUnpacked(h) - if err != nil && !errors.Is(err, plumbing.ErrObjectNotFound) { - return 0, err - } else if err == nil { - return size, nil - } - - return s.encodedObjectSizeFromPackfile(h) -} - -// EncodedObject returns the object with the given hash, by searching for it in -// the packfile and the git object directories. -func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { - var obj plumbing.EncodedObject - var err error - - if s.index != nil { - obj, err = s.getFromPackfile(h, false) - if errors.Is(err, plumbing.ErrObjectNotFound) { - obj, err = s.getFromUnpacked(h) - } - } else { - obj, err = s.getFromUnpacked(h) - if errors.Is(err, plumbing.ErrObjectNotFound) { - obj, err = s.getFromPackfile(h, false) - } - } - - // If the error is still object not found, check if it's a shared object - // repository. - if errors.Is(err, plumbing.ErrObjectNotFound) { - dotgits, e := s.dir.Alternates() - if e == nil { - // Create a new object storage with the DotGit(s) and check for the - // required hash object. Skip when not found. - for _, dg := range dotgits { - o := NewObjectStorage(dg, s.objectCache) - enobj, enerr := o.EncodedObject(t, h) - if enerr != nil { - continue - } - return enobj, nil - } - } - } - - if err != nil { - return nil, err - } - - if obj == nil || (plumbing.AnyObject != t && obj.Type() != t) { - return nil, plumbing.ErrObjectNotFound - } - - return obj, nil -} - -// DeltaObject returns the object with the given hash, by searching for -// it in the packfile and the git object directories. -func (s *ObjectStorage) DeltaObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { - obj, err := s.getFromUnpacked(h) - if errors.Is(err, plumbing.ErrObjectNotFound) { - obj, err = s.getFromPackfile(h, true) - } - - if err != nil { - return nil, err - } - - if plumbing.AnyObject != t && obj.Type() != t { - return nil, plumbing.ErrObjectNotFound - } - - return obj, nil -} - -func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedObject, err error) { - f, err := s.dir.Object(h) - if err != nil { - if os.IsNotExist(err) { - return nil, plumbing.ErrObjectNotFound - } - - return nil, err - } - defer ioutil.CheckClose(f, &err) - - if cacheObj, found := s.objectCache.Get(h); found { - return cacheObj, nil - } - - r, err := objfile.NewReader(f) - if err != nil { - return nil, err - } - - defer ioutil.CheckClose(r, &err) - - t, size, err := r.Header() - if err != nil { - return nil, err - } - - if s.options.LargeObjectThreshold > 0 && size > s.options.LargeObjectThreshold { - obj = dotgit.NewEncodedObject(s.dir, h, t, size) - return obj, nil - } - - obj = s.NewEncodedObject() - - obj.SetType(t) - obj.SetSize(size) - w, err := obj.Writer() - if err != nil { - return nil, err - } - - defer ioutil.CheckClose(w, &err) - - _, err = ioutil.CopyBufferPool(w, r) - if err != nil { - return nil, err - } - - s.objectCache.Put(obj) - - return obj, nil -} - -// Get returns the object with the given hash, by searching for it in -// the packfile. -func (s *ObjectStorage) getFromPackfile(h plumbing.Hash, canBeDelta bool) (plumbing.EncodedObject, error) { - if err := s.requireIndex(); err != nil { - return nil, err - } - - pack, hash, offset := s.findObjectInPackfile(h) - if offset == -1 { - return nil, plumbing.ErrObjectNotFound - } - - s.muI.RLock() - idx := s.index[pack] - s.muI.RUnlock() - - p, err := s.packfile(idx, pack) - if err != nil { - return nil, err - } - - if !s.options.KeepDescriptors && s.options.MaxOpenDescriptors == 0 { - defer ioutil.CheckClose(p, &err) - } - - if canBeDelta { - return s.decodeDeltaObjectAt(p, offset, hash) - } - - return p.GetByOffset(offset) -} - -// TODO: refactor this logic into packfile package. -func (s *ObjectStorage) decodeDeltaObjectAt( - p *packfile.Packfile, - offset int64, - hash plumbing.Hash, -) (plumbing.EncodedObject, error) { - scan, err := p.Scanner() - if err != nil { - return nil, err - } - err = scan.SeekFromStart(offset) - if err != nil { - return nil, err - } - - if !scan.Scan() { - return nil, fmt.Errorf("failed to decode delta object") - } - - header := scan.Data().Value().(packfile.ObjectHeader) - - var base plumbing.Hash - - switch header.Type { - case plumbing.REFDeltaObject: - base = header.Reference - case plumbing.OFSDeltaObject: - base, err = p.FindHash(header.OffsetReference) - if err != nil { - return nil, err - } - default: - return p.GetByOffset(offset) - } - - obj := &plumbing.MemoryObject{} - obj.SetType(header.Type) - w, err := obj.Writer() - if err != nil { - return nil, err - } - - if err := scan.WriteObject(&header, w); err != nil { - return nil, err - } - - return newDeltaObject(obj, hash, base, header.Size), nil -} - -func (s *ObjectStorage) findObjectInPackfile(h plumbing.Hash) (plumbing.Hash, plumbing.Hash, int64) { - defer s.muI.Unlock() - s.muI.Lock() - - for packfile, index := range s.index { - offset, err := index.FindOffset(h) - if err == nil { - return packfile, h, offset - } - } - - return plumbing.ZeroHash, plumbing.ZeroHash, -1 -} - -// HashesWithPrefix returns all objects with a hash that starts with a prefix by searching for -// them in the packfile and the git object directories. -func (s *ObjectStorage) HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error) { - hashes, err := s.dir.ObjectsWithPrefix(prefix) - if err != nil { - return nil, err - } - - seen := hashListAsMap(hashes) - - // TODO: This could be faster with some idxfile changes, - // or diving into the packfile. - if err := s.requireIndex(); err != nil { - return nil, err - } - for _, index := range s.index { - ei, err := index.Entries() - if err != nil { - return nil, err - } - for { - e, err := ei.Next() - if err == io.EOF { - break - } else if err != nil { - return nil, err - } - if e.Hash.HasPrefix(prefix) { - if _, ok := seen[e.Hash]; ok { - continue - } - hashes = append(hashes, e.Hash) - } - } - ei.Close() - } - - return hashes, nil -} - -// IterEncodedObjects returns an iterator for all the objects in the packfile -// with the given type. -func (s *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) { - objects, err := s.dir.Objects() - if err != nil { - return nil, err - } - - seen := make(map[plumbing.Hash]struct{}) - var iters []storer.EncodedObjectIter - if len(objects) != 0 { - iters = append(iters, &objectsIter{s: s, t: t, h: objects}) - seen = hashListAsMap(objects) - } - - packi, err := s.buildPackfileIters(t, seen) - if err != nil { - return nil, err - } - - iters = append(iters, packi) - return storer.NewMultiEncodedObjectIter(iters), nil -} - -func (s *ObjectStorage) buildPackfileIters( - t plumbing.ObjectType, - seen map[plumbing.Hash]struct{}, -) (storer.EncodedObjectIter, error) { - if err := s.requireIndex(); err != nil { - return nil, err - } - - packs, err := s.dir.ObjectPacks() - if err != nil { - return nil, err - } - return &lazyPackfilesIter{ - hashes: packs, - open: func(h plumbing.Hash) (storer.EncodedObjectIter, error) { - pack, err := s.dir.ObjectPack(h) - if err != nil { - return nil, err - } - return newPackfileIter( - s.dir.Fs(), pack, t, seen, s.index[h], - s.objectCache, s.options.KeepDescriptors, crypto.SHA1.Size(), - ) - }, - }, nil -} - -// Close closes all opened files. -func (s *ObjectStorage) Close() error { - var firstError error - - s.muP.RLock() - defer s.muP.RUnlock() - - if s.options.KeepDescriptors || s.options.MaxOpenDescriptors > 0 { - for _, packfile := range s.packfiles { - err := packfile.Close() - if firstError == nil && err != nil { - firstError = err - } - } - } - - s.packfiles = nil - s.dir.Close() - - return firstError -} - -func hashListAsMap(l []plumbing.Hash) map[plumbing.Hash]struct{} { - m := make(map[plumbing.Hash]struct{}, len(l)) - for _, h := range l { - m[h] = struct{}{} - } - return m -} - -func (s *ObjectStorage) ForEachObjectHash(fun func(plumbing.Hash) error) error { - err := s.dir.ForEachObjectHash(fun) - if err == storer.ErrStop { - return nil - } - return err -} - -func (s *ObjectStorage) LooseObjectTime(hash plumbing.Hash) (time.Time, error) { - fi, err := s.dir.ObjectStat(hash) - if err != nil { - return time.Time{}, err - } - return fi.ModTime(), nil -} - -func (s *ObjectStorage) DeleteLooseObject(hash plumbing.Hash) error { - return s.dir.ObjectDelete(hash) -} - -func (s *ObjectStorage) ObjectPacks() ([]plumbing.Hash, error) { - return s.dir.ObjectPacks() -} - -func (s *ObjectStorage) DeleteOldObjectPackAndIndex(h plumbing.Hash, t time.Time) error { - return s.dir.DeleteOldObjectPackAndIndex(h, t) -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/object_iter.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/object_iter.go deleted file mode 100644 index 5d321801..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/object_iter.go +++ /dev/null @@ -1,208 +0,0 @@ -package filesystem - -import ( - "io" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/plumbing/format/idxfile" - "github.com/go-git/go-git/v6/plumbing/format/packfile" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -type lazyPackfilesIter struct { - hashes []plumbing.Hash - open func(h plumbing.Hash) (storer.EncodedObjectIter, error) - cur storer.EncodedObjectIter -} - -func (it *lazyPackfilesIter) Next() (plumbing.EncodedObject, error) { - for { - if it.cur == nil { - if len(it.hashes) == 0 { - return nil, io.EOF - } - h := it.hashes[0] - it.hashes = it.hashes[1:] - - sub, err := it.open(h) - if err == io.EOF { - continue - } else if err != nil { - return nil, err - } - it.cur = sub - } - ob, err := it.cur.Next() - if err == io.EOF { - it.cur.Close() - it.cur = nil - continue - } else if err != nil { - return nil, err - } - return ob, nil - } -} - -func (it *lazyPackfilesIter) ForEach(cb func(plumbing.EncodedObject) error) error { - return storer.ForEachIterator(it, cb) -} - -func (it *lazyPackfilesIter) Close() { - if it.cur != nil { - it.cur.Close() - it.cur = nil - } - it.hashes = nil -} - -type packfileIter struct { - pack billy.File - iter storer.EncodedObjectIter - seen map[plumbing.Hash]struct{} - - // tells whether the pack file should be left open after iteration or not - keepPack bool -} - -// NewPackfileIter returns a new EncodedObjectIter for the provided packfile -// and object type. Packfile and index file will be closed after they're -// used. If keepPack is true the packfile won't be closed after the iteration -// finished. -func NewPackfileIter( - fs billy.Filesystem, - f billy.File, - idxFile billy.File, - t plumbing.ObjectType, - keepPack bool, - largeObjectThreshold int64, - objectIDSize int, -) (storer.EncodedObjectIter, error) { - idx := idxfile.NewMemoryIndex(objectIDSize) - if err := idxfile.NewDecoder(idxFile).Decode(idx); err != nil { - return nil, err - } - - if err := idxFile.Close(); err != nil { - return nil, err - } - - seen := make(map[plumbing.Hash]struct{}) - return newPackfileIter(fs, f, t, seen, idx, nil, keepPack, objectIDSize) -} - -func newPackfileIter( - fs billy.Filesystem, - f billy.File, - t plumbing.ObjectType, - seen map[plumbing.Hash]struct{}, - index idxfile.Index, - cache cache.Object, - keepPack bool, - objectIDSize int, -) (storer.EncodedObjectIter, error) { - p := packfile.NewPackfile(f, - packfile.WithFs(fs), - packfile.WithCache(cache), - packfile.WithIdx(index), - packfile.WithObjectIDSize(objectIDSize), - ) - - iter, err := p.GetByType(t) - if err != nil { - return nil, err - } - - return &packfileIter{ - pack: f, - iter: iter, - seen: seen, - keepPack: keepPack, - }, nil -} - -func (iter *packfileIter) Next() (plumbing.EncodedObject, error) { - for { - obj, err := iter.iter.Next() - if err != nil { - return nil, err - } - - if _, ok := iter.seen[obj.Hash()]; ok { - continue - } - - return obj, nil - } -} - -func (iter *packfileIter) ForEach(cb func(plumbing.EncodedObject) error) error { - for { - o, err := iter.Next() - if err != nil { - if err == io.EOF { - iter.Close() - return nil - } - return err - } - - if err := cb(o); err != nil { - return err - } - } -} - -func (iter *packfileIter) Close() { - iter.iter.Close() - if !iter.keepPack { - _ = iter.pack.Close() - } -} - -type objectsIter struct { - s *ObjectStorage - t plumbing.ObjectType - h []plumbing.Hash -} - -func (iter *objectsIter) Next() (plumbing.EncodedObject, error) { - if len(iter.h) == 0 { - return nil, io.EOF - } - - obj, err := iter.s.getFromUnpacked(iter.h[0]) - iter.h = iter.h[1:] - - if err != nil { - return nil, err - } - - if iter.t != plumbing.AnyObject && iter.t != obj.Type() { - return iter.Next() - } - - return obj, err -} - -func (iter *objectsIter) ForEach(cb func(plumbing.EncodedObject) error) error { - for { - o, err := iter.Next() - if err != nil { - if err == io.EOF { - return nil - } - return err - } - - if err := cb(o); err != nil { - return err - } - } -} - -func (iter *objectsIter) Close() { - iter.h = []plumbing.Hash{} -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/reference.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/reference.go deleted file mode 100644 index 002346e3..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/reference.go +++ /dev/null @@ -1,44 +0,0 @@ -package filesystem - -import ( - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" -) - -type ReferenceStorage struct { - dir *dotgit.DotGit -} - -func (r *ReferenceStorage) SetReference(ref *plumbing.Reference) error { - return r.dir.SetRef(ref, nil) -} - -func (r *ReferenceStorage) CheckAndSetReference(ref, old *plumbing.Reference) error { - return r.dir.SetRef(ref, old) -} - -func (r *ReferenceStorage) Reference(n plumbing.ReferenceName) (*plumbing.Reference, error) { - return r.dir.Ref(n) -} - -func (r *ReferenceStorage) IterReferences() (storer.ReferenceIter, error) { - refs, err := r.dir.Refs() - if err != nil { - return nil, err - } - - return storer.NewReferenceSliceIter(refs), nil -} - -func (r *ReferenceStorage) RemoveReference(n plumbing.ReferenceName) error { - return r.dir.RemoveRef(n) -} - -func (r *ReferenceStorage) CountLooseRefs() (int, error) { - return r.dir.CountLooseRefs() -} - -func (r *ReferenceStorage) PackRefs() error { - return r.dir.PackRefs() -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/shallow.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/shallow.go deleted file mode 100644 index 3f64ce57..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/shallow.go +++ /dev/null @@ -1,54 +0,0 @@ -package filesystem - -import ( - "bufio" - "fmt" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -// ShallowStorage where the shallow commits are stored, an internal to -// manipulate the shallow file -type ShallowStorage struct { - dir *dotgit.DotGit -} - -// SetShallow save the shallows in the shallow file in the .git folder as one -// commit per line represented by 40-byte hexadecimal object terminated by a -// newline. -func (s *ShallowStorage) SetShallow(commits []plumbing.Hash) error { - f, err := s.dir.ShallowWriter() - if err != nil { - return err - } - - defer ioutil.CheckClose(f, &err) - for _, h := range commits { - if _, err := fmt.Fprintf(f, "%s\n", h); err != nil { - return err - } - } - - return err -} - -// Shallow returns the shallow commits reading from shallo file from .git -func (s *ShallowStorage) Shallow() ([]plumbing.Hash, error) { - f, err := s.dir.Shallow() - if f == nil || err != nil { - return nil, err - } - - defer ioutil.CheckClose(f, &err) - - var hash []plumbing.Hash - - scn := bufio.NewScanner(f) - for scn.Scan() { - hash = append(hash, plumbing.NewHash(scn.Text())) - } - - return hash, scn.Err() -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/filesystem/storage.go b/vendor/github.com/go-git/go-git/v6/storage/filesystem/storage.go deleted file mode 100644 index 5f25f04d..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/filesystem/storage.go +++ /dev/null @@ -1,98 +0,0 @@ -// Package filesystem is a storage backend base on filesystems -package filesystem - -import ( - "github.com/go-git/go-git/v6/plumbing/cache" - "github.com/go-git/go-git/v6/storage/filesystem/dotgit" - - "github.com/go-git/go-billy/v6" -) - -// Storage is an implementation of git.Storer that stores data on disk in the -// standard git format (this is, the .git directory). Zero values of this type -// are not safe to use, see the NewStorage function below. -type Storage struct { - fs billy.Filesystem - dir *dotgit.DotGit - - ObjectStorage - ReferenceStorage - IndexStorage - ShallowStorage - ConfigStorage - ModuleStorage -} - -// Options holds configuration for the storage. -type Options struct { - // ExclusiveAccess means that the filesystem is not modified externally - // while the repo is open. - ExclusiveAccess bool - // KeepDescriptors makes the file descriptors to be reused but they will - // need to be manually closed calling Close(). - KeepDescriptors bool - // MaxOpenDescriptors is the max number of file descriptors to keep - // open. If KeepDescriptors is true, all file descriptors will remain open. - MaxOpenDescriptors int - // LargeObjectThreshold maximum object size (in bytes) that will be read in to memory. - // If left unset or set to 0 there is no limit - LargeObjectThreshold int64 - // AlternatesFS provides the billy filesystem to be used for Git Alternates. - // If none is provided, it falls back to using the underlying instance used for - // DotGit. - AlternatesFS billy.Filesystem - // HighMemoryMode defines whether the storage will operate in high-memory - // mode. This defaults to false. For more information refer to packfile's Parser - // WithHighMemoryMode option. - HighMemoryMode bool -} - -// NewStorage returns a new Storage backed by a given `fs.Filesystem` and cache. -func NewStorage(fs billy.Filesystem, cache cache.Object) *Storage { - return NewStorageWithOptions(fs, cache, Options{}) -} - -// NewStorageWithOptions returns a new Storage with extra options, -// backed by a given `fs.Filesystem` and cache. -func NewStorageWithOptions(fs billy.Filesystem, c cache.Object, ops Options) *Storage { - dirOps := dotgit.Options{ - ExclusiveAccess: ops.ExclusiveAccess, - AlternatesFS: ops.AlternatesFS, - KeepDescriptors: ops.KeepDescriptors, - } - dir := dotgit.NewWithOptions(fs, dirOps) - - if c == nil { - c = cache.NewObjectLRUDefault() - } - - return &Storage{ - fs: fs, - dir: dir, - - ObjectStorage: *NewObjectStorageWithOptions(dir, c, ops), - ReferenceStorage: ReferenceStorage{dir: dir}, - IndexStorage: IndexStorage{dir: dir}, - ShallowStorage: ShallowStorage{dir: dir}, - ConfigStorage: ConfigStorage{dir: dir}, - ModuleStorage: ModuleStorage{dir: dir}, - } -} - -// Filesystem returns the underlying filesystem -func (s *Storage) Filesystem() billy.Filesystem { - return s.fs -} - -// Init initializes .git directory -func (s *Storage) Init() error { - return s.dir.Initialize() -} - -func (s *Storage) AddAlternate(remote string) error { - return s.dir.AddAlternate(remote) -} - -func (s *Storage) LowMemoryMode() bool { - return !s.options.HighMemoryMode -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/memory/storage.go b/vendor/github.com/go-git/go-git/v6/storage/memory/storage.go deleted file mode 100644 index c81b83b7..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/memory/storage.go +++ /dev/null @@ -1,359 +0,0 @@ -// Package memory is a storage backend base on memory -package memory - -import ( - "fmt" - "io" - "time" - - "github.com/go-git/go-git/v6/config" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/index" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/storage" - "github.com/go-git/go-git/v6/utils/ioutil" -) - -var ErrUnsupportedObjectType = fmt.Errorf("unsupported object type") - -// Storage is an implementation of git.Storer that stores data on memory, being -// ephemeral. The use of this storage should be done in controlled environments, -// since the representation in memory of some repository can fill the machine -// memory. in the other hand this storage has the best performance. -type Storage struct { - ConfigStorage - ObjectStorage - ShallowStorage - IndexStorage - ReferenceStorage - ModuleStorage -} - -// NewStorage returns a new Storage base on memory -func NewStorage() *Storage { - return &Storage{ - ReferenceStorage: make(ReferenceStorage), - ConfigStorage: ConfigStorage{}, - ShallowStorage: ShallowStorage{}, - ObjectStorage: ObjectStorage{ - Objects: make(map[plumbing.Hash]plumbing.EncodedObject), - Commits: make(map[plumbing.Hash]plumbing.EncodedObject), - Trees: make(map[plumbing.Hash]plumbing.EncodedObject), - Blobs: make(map[plumbing.Hash]plumbing.EncodedObject), - Tags: make(map[plumbing.Hash]plumbing.EncodedObject), - }, - ModuleStorage: make(ModuleStorage), - } -} - -type ConfigStorage struct { - config *config.Config -} - -func (c *ConfigStorage) SetConfig(cfg *config.Config) error { - if err := cfg.Validate(); err != nil { - return err - } - - c.config = cfg - return nil -} - -func (c *ConfigStorage) Config() (*config.Config, error) { - if c.config == nil { - c.config = config.NewConfig() - } - - return c.config, nil -} - -type IndexStorage struct { - index *index.Index -} - -func (c *IndexStorage) SetIndex(idx *index.Index) error { - c.index = idx - return nil -} - -func (c *IndexStorage) Index() (*index.Index, error) { - if c.index == nil { - c.index = &index.Index{Version: 2} - } - - return c.index, nil -} - -type ObjectStorage struct { - Objects map[plumbing.Hash]plumbing.EncodedObject - Commits map[plumbing.Hash]plumbing.EncodedObject - Trees map[plumbing.Hash]plumbing.EncodedObject - Blobs map[plumbing.Hash]plumbing.EncodedObject - Tags map[plumbing.Hash]plumbing.EncodedObject -} - -type lazyCloser struct { - storage *ObjectStorage - obj plumbing.EncodedObject - closer io.Closer -} - -func (c *lazyCloser) Close() error { - err := c.closer.Close() - if err != nil { - return fmt.Errorf("failed to close memory encoded object: %w", err) - } - - _, err = c.storage.SetEncodedObject(c.obj) - return err -} - -func (o *ObjectStorage) RawObjectWriter(typ plumbing.ObjectType, sz int64) (w io.WriteCloser, err error) { - obj := o.NewEncodedObject() - obj.SetType(typ) - obj.SetSize(sz) - - w, err = obj.Writer() - if err != nil { - return nil, err - } - - wc := ioutil.NewWriteCloser(w, - &lazyCloser{storage: o, obj: obj, closer: w}, - ) - - return wc, nil -} - -func (o *ObjectStorage) NewEncodedObject() plumbing.EncodedObject { - return &plumbing.MemoryObject{} -} - -func (o *ObjectStorage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) { - h := obj.Hash() - o.Objects[h] = obj - - switch obj.Type() { - case plumbing.CommitObject: - o.Commits[h] = o.Objects[h] - case plumbing.TreeObject: - o.Trees[h] = o.Objects[h] - case plumbing.BlobObject: - o.Blobs[h] = o.Objects[h] - case plumbing.TagObject: - o.Tags[h] = o.Objects[h] - default: - return h, ErrUnsupportedObjectType - } - - return h, nil -} - -func (o *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) { - if _, ok := o.Objects[h]; !ok { - return plumbing.ErrObjectNotFound - } - return nil -} - -func (o *ObjectStorage) EncodedObjectSize(h plumbing.Hash) ( - size int64, err error) { - obj, ok := o.Objects[h] - if !ok { - return 0, plumbing.ErrObjectNotFound - } - - return obj.Size(), nil -} - -func (o *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { - obj, ok := o.Objects[h] - if !ok || (plumbing.AnyObject != t && obj.Type() != t) { - return nil, plumbing.ErrObjectNotFound - } - - return obj, nil -} - -func (o *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) { - var series []plumbing.EncodedObject - switch t { - case plumbing.AnyObject: - series = flattenObjectMap(o.Objects) - case plumbing.CommitObject: - series = flattenObjectMap(o.Commits) - case plumbing.TreeObject: - series = flattenObjectMap(o.Trees) - case plumbing.BlobObject: - series = flattenObjectMap(o.Blobs) - case plumbing.TagObject: - series = flattenObjectMap(o.Tags) - } - - return storer.NewEncodedObjectSliceIter(series), nil -} - -func flattenObjectMap(m map[plumbing.Hash]plumbing.EncodedObject) []plumbing.EncodedObject { - objects := make([]plumbing.EncodedObject, 0, len(m)) - for _, obj := range m { - objects = append(objects, obj) - } - return objects -} - -func (o *ObjectStorage) Begin() storer.Transaction { - return &TxObjectStorage{ - Storage: o, - Objects: make(map[plumbing.Hash]plumbing.EncodedObject), - } -} - -func (o *ObjectStorage) ForEachObjectHash(fun func(plumbing.Hash) error) error { - for h := range o.Objects { - err := fun(h) - if err != nil { - if err == storer.ErrStop { - return nil - } - return err - } - } - return nil -} - -func (o *ObjectStorage) ObjectPacks() ([]plumbing.Hash, error) { - return nil, nil -} -func (o *ObjectStorage) DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) error { - return nil -} - -var errNotSupported = fmt.Errorf("not supported") - -func (o *ObjectStorage) LooseObjectTime(hash plumbing.Hash) (time.Time, error) { - return time.Time{}, errNotSupported -} -func (o *ObjectStorage) DeleteLooseObject(plumbing.Hash) error { - return errNotSupported -} - -func (o *ObjectStorage) AddAlternate(remote string) error { - return errNotSupported -} - -type TxObjectStorage struct { - Storage *ObjectStorage - Objects map[plumbing.Hash]plumbing.EncodedObject -} - -func (tx *TxObjectStorage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) { - h := obj.Hash() - tx.Objects[h] = obj - - return h, nil -} - -func (tx *TxObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { - obj, ok := tx.Objects[h] - if !ok || (plumbing.AnyObject != t && obj.Type() != t) { - return nil, plumbing.ErrObjectNotFound - } - - return obj, nil -} - -func (tx *TxObjectStorage) Commit() error { - for h, obj := range tx.Objects { - delete(tx.Objects, h) - if _, err := tx.Storage.SetEncodedObject(obj); err != nil { - return err - } - } - - return nil -} - -func (tx *TxObjectStorage) Rollback() error { - tx.Objects = make(map[plumbing.Hash]plumbing.EncodedObject) - return nil -} - -type ReferenceStorage map[plumbing.ReferenceName]*plumbing.Reference - -func (r ReferenceStorage) SetReference(ref *plumbing.Reference) error { - if ref != nil { - r[ref.Name()] = ref - } - - return nil -} - -func (r ReferenceStorage) CheckAndSetReference(ref, old *plumbing.Reference) error { - if ref == nil { - return nil - } - - if old != nil { - tmp := r[ref.Name()] - if tmp != nil && tmp.Hash() != old.Hash() { - return storage.ErrReferenceHasChanged - } - } - r[ref.Name()] = ref - return nil -} - -func (r ReferenceStorage) Reference(n plumbing.ReferenceName) (*plumbing.Reference, error) { - ref, ok := r[n] - if !ok { - return nil, plumbing.ErrReferenceNotFound - } - - return ref, nil -} - -func (r ReferenceStorage) IterReferences() (storer.ReferenceIter, error) { - var refs []*plumbing.Reference - for _, ref := range r { - refs = append(refs, ref) - } - - return storer.NewReferenceSliceIter(refs), nil -} - -func (r ReferenceStorage) CountLooseRefs() (int, error) { - return len(r), nil -} - -func (r ReferenceStorage) PackRefs() error { - return nil -} - -func (r ReferenceStorage) RemoveReference(n plumbing.ReferenceName) error { - delete(r, n) - return nil -} - -type ShallowStorage []plumbing.Hash - -func (s *ShallowStorage) SetShallow(commits []plumbing.Hash) error { - *s = commits - return nil -} - -func (s ShallowStorage) Shallow() ([]plumbing.Hash, error) { - return s, nil -} - -type ModuleStorage map[string]*Storage - -func (s ModuleStorage) Module(name string) (storage.Storer, error) { - if m, ok := s[name]; ok { - return m, nil - } - - m := NewStorage() - s[name] = m - - return m, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/storage/storer.go b/vendor/github.com/go-git/go-git/v6/storage/storer.go deleted file mode 100644 index 139cc67e..00000000 --- a/vendor/github.com/go-git/go-git/v6/storage/storer.go +++ /dev/null @@ -1,30 +0,0 @@ -package storage - -import ( - "errors" - - "github.com/go-git/go-git/v6/config" - "github.com/go-git/go-git/v6/plumbing/storer" -) - -var ErrReferenceHasChanged = errors.New("reference has changed concurrently") - -// Storer is a generic storage of objects, references and any information -// related to a particular repository. The package github.com/go-git/go-git/v6/storage -// contains two implementation a filesystem base implementation (such as `.git`) -// and a memory implementations being ephemeral -type Storer interface { - storer.EncodedObjectStorer - storer.ReferenceStorer - storer.ShallowStorer - storer.IndexStorer - config.ConfigStorer - ModuleStorer -} - -// ModuleStorer allows interact with the modules' Storers -type ModuleStorer interface { - // Module returns a Storer representing a submodule, if not exists returns a - // new empty Storer is returned - Module(name string) (Storer, error) -} diff --git a/vendor/github.com/go-git/go-git/v6/submodule.go b/vendor/github.com/go-git/go-git/v6/submodule.go deleted file mode 100644 index e0441c7f..00000000 --- a/vendor/github.com/go-git/go-git/v6/submodule.go +++ /dev/null @@ -1,398 +0,0 @@ -package git - -import ( - "bytes" - "context" - "errors" - "fmt" - "path" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-git/v6/config" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/format/index" - "github.com/go-git/go-git/v6/plumbing/transport" -) - -var ( - ErrSubmoduleAlreadyInitialized = errors.New("submodule already initialized") - ErrSubmoduleNotInitialized = errors.New("submodule not initialized") -) - -// Submodule a submodule allows you to keep another Git repository in a -// subdirectory of your repository. -type Submodule struct { - // initialized defines if a submodule was already initialized. - initialized bool - - c *config.Submodule - w *Worktree -} - -// Config returns the submodule config -func (s *Submodule) Config() *config.Submodule { - return s.c -} - -// Init initialize the submodule reading the recorded Entry in the index for -// the given submodule -func (s *Submodule) Init() error { - cfg, err := s.w.r.Config() - if err != nil { - return err - } - - _, ok := cfg.Submodules[s.c.Name] - if ok { - return ErrSubmoduleAlreadyInitialized - } - - s.initialized = true - - cfg.Submodules[s.c.Name] = s.c - return s.w.r.Storer.SetConfig(cfg) -} - -// Status returns the status of the submodule. -func (s *Submodule) Status() (*SubmoduleStatus, error) { - idx, err := s.w.r.Storer.Index() - if err != nil { - return nil, err - } - - return s.status(idx) -} - -func (s *Submodule) status(idx *index.Index) (*SubmoduleStatus, error) { - status := &SubmoduleStatus{ - Path: s.c.Path, - } - - e, err := idx.Entry(s.c.Path) - if err != nil && err != index.ErrEntryNotFound { - return nil, err - } - - if e != nil { - status.Expected = e.Hash - } - - if !s.initialized { - return status, nil - } - - r, err := s.Repository() - if err != nil { - return nil, err - } - - head, err := r.Head() - if err == nil { - status.Current = head.Hash() - } - - if err != nil && err == plumbing.ErrReferenceNotFound { - err = nil - } - - return status, err -} - -// Repository returns the Repository represented by this submodule -func (s *Submodule) Repository() (*Repository, error) { - if !s.initialized { - return nil, ErrSubmoduleNotInitialized - } - - storer, err := s.w.r.Storer.Module(s.c.Name) - if err != nil { - return nil, err - } - - _, err = storer.Reference(plumbing.HEAD) - if err != nil && err != plumbing.ErrReferenceNotFound { - return nil, err - } - - var exists bool - if err == nil { - exists = true - } - - var worktree billy.Filesystem - if worktree, err = s.w.Filesystem.Chroot(s.c.Path); err != nil { - return nil, err - } - - if exists { - return Open(storer, worktree) - } - - r, err := Init(storer, WithWorkTree(worktree)) - if err != nil { - return nil, err - } - - moduleEndpoint, err := transport.NewEndpoint(s.c.URL) - if err != nil { - return nil, err - } - - if !path.IsAbs(moduleEndpoint.Path) && moduleEndpoint.Protocol == "file" { - remotes, err := s.w.r.Remotes() - if err != nil { - return nil, err - } - - rootEndpoint, err := transport.NewEndpoint(remotes[0].c.URLs[0]) - if err != nil { - return nil, err - } - - rootEndpoint.Path = path.Join(rootEndpoint.Path, moduleEndpoint.Path) - *moduleEndpoint = *rootEndpoint - } - - _, err = r.CreateRemote(&config.RemoteConfig{ - Name: DefaultRemoteName, - URLs: []string{moduleEndpoint.String()}, - }) - - return r, err -} - -// Update the registered submodule to match what the superproject expects, the -// submodule should be initialized first calling the Init method or setting in -// the options SubmoduleUpdateOptions.Init equals true -func (s *Submodule) Update(o *SubmoduleUpdateOptions) error { - return s.UpdateContext(context.Background(), o) -} - -// UpdateContext the registered submodule to match what the superproject -// expects, the submodule should be initialized first calling the Init method or -// setting in the options SubmoduleUpdateOptions.Init equals true. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func (s *Submodule) UpdateContext(ctx context.Context, o *SubmoduleUpdateOptions) error { - return s.update(ctx, o, plumbing.ZeroHash) -} - -func (s *Submodule) update(ctx context.Context, o *SubmoduleUpdateOptions, forceHash plumbing.Hash) error { - if !s.initialized && !o.Init { - return ErrSubmoduleNotInitialized - } - - if !s.initialized && o.Init { - if err := s.Init(); err != nil { - return err - } - } - - idx, err := s.w.r.Storer.Index() - if err != nil { - return err - } - - hash := forceHash - if hash.IsZero() { - e, err := idx.Entry(s.c.Path) - if err != nil { - return err - } - - hash = e.Hash - } - - r, err := s.Repository() - if err != nil { - return err - } - - if err := s.fetchAndCheckout(ctx, r, o, hash); err != nil { - return err - } - - return s.doRecursiveUpdate(ctx, r, o) -} - -func (s *Submodule) doRecursiveUpdate(ctx context.Context, r *Repository, o *SubmoduleUpdateOptions) error { - if o.RecurseSubmodules == NoRecurseSubmodules { - return nil - } - - w, err := r.Worktree() - if err != nil { - return err - } - - l, err := w.Submodules() - if err != nil { - return err - } - - new := &SubmoduleUpdateOptions{} - *new = *o - - new.RecurseSubmodules-- - return l.UpdateContext(ctx, new) -} - -func (s *Submodule) fetchAndCheckout( - ctx context.Context, r *Repository, o *SubmoduleUpdateOptions, hash plumbing.Hash, -) error { - if !o.NoFetch { - err := r.FetchContext(ctx, &FetchOptions{Auth: o.Auth, Depth: o.Depth}) - if err != nil && err != NoErrAlreadyUpToDate { - return err - } - } - - w, err := r.Worktree() - if err != nil { - return err - } - - // Handle a case when submodule refers to an orphaned commit that's still reachable - // through Git server using a special protocol capability[1]. - // - // [1]: https://git-scm.com/docs/protocol-capabilities#_allow_reachable_sha1_in_want - if !o.NoFetch { - if _, err := w.r.Object(plumbing.AnyObject, hash); err != nil { - refSpec := config.RefSpec("+" + hash.String() + ":" + hash.String()) - - err := r.FetchContext(ctx, &FetchOptions{ - Auth: o.Auth, - RefSpecs: []config.RefSpec{refSpec}, - Depth: o.Depth, - }) - if err != nil && !errors.Is(err, NoErrAlreadyUpToDate) && !errors.Is(err, ErrExactSHA1NotSupported) { - return err - } - } - } - - if err := w.Checkout(&CheckoutOptions{Hash: hash}); err != nil { - return err - } - - head := plumbing.NewHashReference(plumbing.HEAD, hash) - return r.Storer.SetReference(head) -} - -// Submodules list of several submodules from the same repository. -type Submodules []*Submodule - -// Init initializes the submodules in this list. -func (s Submodules) Init() error { - for _, sub := range s { - if err := sub.Init(); err != nil { - return err - } - } - - return nil -} - -// Update updates all the submodules in this list. -func (s Submodules) Update(o *SubmoduleUpdateOptions) error { - return s.UpdateContext(context.Background(), o) -} - -// UpdateContext updates all the submodules in this list. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func (s Submodules) UpdateContext(ctx context.Context, o *SubmoduleUpdateOptions) error { - for _, sub := range s { - if err := sub.UpdateContext(ctx, o); err != nil { - return err - } - } - - return nil -} - -// Status returns the status of the submodules. -func (s Submodules) Status() (SubmodulesStatus, error) { - var list SubmodulesStatus - - var r *Repository - for _, sub := range s { - if r == nil { - r = sub.w.r - } - - idx, err := r.Storer.Index() - if err != nil { - return nil, err - } - - status, err := sub.status(idx) - if err != nil { - return nil, err - } - - list = append(list, status) - } - - return list, nil -} - -// SubmodulesStatus contains the status for all submodiles in the worktree -type SubmodulesStatus []*SubmoduleStatus - -// String is equivalent to `git submodule status` -func (s SubmodulesStatus) String() string { - buf := bytes.NewBuffer(nil) - for _, sub := range s { - fmt.Fprintln(buf, sub) - } - - return buf.String() -} - -// SubmoduleStatus contains the status for a submodule in the worktree -type SubmoduleStatus struct { - Path string - Current plumbing.Hash - Expected plumbing.Hash - Branch plumbing.ReferenceName -} - -// IsClean is the HEAD of the submodule is equals to the expected commit -func (s *SubmoduleStatus) IsClean() bool { - return s.Current == s.Expected -} - -// String is equivalent to `git submodule status ` -// -// This will print the SHA-1 of the currently checked out commit for a -// submodule, along with the submodule path and the output of git describe fo -// the SHA-1. Each SHA-1 will be prefixed with - if the submodule is not -// initialized, + if the currently checked out submodule commit does not match -// the SHA-1 found in the index of the containing repository. -func (s *SubmoduleStatus) String() string { - var extra string - status := ' ' - - if s.Current.IsZero() { - status = '-' - } else if !s.IsClean() { - status = '+' - } - - if len(s.Branch) != 0 { - extra = string(s.Branch[5:]) - } else if !s.Current.IsZero() { - extra = s.Current.String()[:7] - } - - if extra != "" { - extra = fmt.Sprintf(" (%s)", extra) - } - - return fmt.Sprintf("%c%s %s%s", status, s.Expected, s.Path, extra) -} diff --git a/vendor/github.com/go-git/go-git/v6/transport.go b/vendor/github.com/go-git/go-git/v6/transport.go deleted file mode 100644 index c0142868..00000000 --- a/vendor/github.com/go-git/go-git/v6/transport.go +++ /dev/null @@ -1,9 +0,0 @@ -package git - -// Default supported transports. -import ( - _ "github.com/go-git/go-git/v6/plumbing/transport/file" // file transport - _ "github.com/go-git/go-git/v6/plumbing/transport/git" // git transport - _ "github.com/go-git/go-git/v6/plumbing/transport/http" // http transport - _ "github.com/go-git/go-git/v6/plumbing/transport/ssh" // ssh transport -) diff --git a/vendor/github.com/go-git/go-git/v6/utils/binary/read.go b/vendor/github.com/go-git/go-git/v6/utils/binary/read.go deleted file mode 100644 index d0652003..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/binary/read.go +++ /dev/null @@ -1,167 +0,0 @@ -// Package binary implements syntax-sugar functions on top of the standard -// library binary package -package binary - -import ( - "bufio" - "encoding/binary" - "io" -) - -// Read reads structured binary data from r into data. Bytes are read and -// decoded in BigEndian order -// https://golang.org/pkg/encoding/binary/#Read -func Read(r io.Reader, data ...interface{}) error { - for _, v := range data { - if err := binary.Read(r, binary.BigEndian, v); err != nil { - return err - } - } - - return nil -} - -// ReadUntil reads from r untin delim is found -func ReadUntil(r io.Reader, delim byte) ([]byte, error) { - if bufr, ok := r.(*bufio.Reader); ok { - return ReadUntilFromBufioReader(bufr, delim) - } - - var buf [1]byte - value := make([]byte, 0, 16) - for { - if _, err := io.ReadFull(r, buf[:]); err != nil { - if err == io.EOF { - return nil, err - } - - return nil, err - } - - if buf[0] == delim { - return value, nil - } - - value = append(value, buf[0]) - } -} - -// ReadUntilFromBufioReader is like bufio.ReadBytes but drops the delimiter -// from the result. -func ReadUntilFromBufioReader(r *bufio.Reader, delim byte) ([]byte, error) { - value, err := r.ReadBytes(delim) - if err != nil || len(value) == 0 { - return nil, err - } - - return value[:len(value)-1], nil -} - -// ReadVariableWidthInt reads and returns an int in Git VLQ special format: -// -// Ordinary VLQ has some redundancies, example: the number 358 can be -// encoded as the 2-octet VLQ 0x8166 or the 3-octet VLQ 0x808166 or the -// 4-octet VLQ 0x80808166 and so forth. -// -// To avoid these redundancies, the VLQ format used in Git removes this -// prepending redundancy and extends the representable range of shorter -// VLQs by adding an offset to VLQs of 2 or more octets in such a way -// that the lowest possible value for such an (N+1)-octet VLQ becomes -// exactly one more than the maximum possible value for an N-octet VLQ. -// In particular, since a 1-octet VLQ can store a maximum value of 127, -// the minimum 2-octet VLQ (0x8000) is assigned the value 128 instead of -// 0. Conversely, the maximum value of such a 2-octet VLQ (0xff7f) is -// 16511 instead of just 16383. Similarly, the minimum 3-octet VLQ -// (0x808000) has a value of 16512 instead of zero, which means -// that the maximum 3-octet VLQ (0xffff7f) is 2113663 instead of -// just 2097151. And so forth. -// -// This is how the offset is saved in C: -// -// dheader[pos] = ofs & 127; -// while (ofs >>= 7) -// dheader[--pos] = 128 | (--ofs & 127); -func ReadVariableWidthInt(r io.Reader) (int64, error) { - var c byte - if err := Read(r, &c); err != nil { - return 0, err - } - - var v = int64(c & maskLength) - for c&maskContinue > 0 { - v++ - if err := Read(r, &c); err != nil { - return 0, err - } - - v = (v << lengthBits) + int64(c&maskLength) - } - - return v, nil -} - -const ( - maskContinue = uint8(128) // 1000 000 - maskLength = uint8(127) // 0111 1111 - lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length -) - -// ReadUint64 reads 8 bytes and returns them as a BigEndian uint32 -func ReadUint64(r io.Reader) (uint64, error) { - var v uint64 - if err := binary.Read(r, binary.BigEndian, &v); err != nil { - return 0, err - } - - return v, nil -} - -// ReadUint32 reads 4 bytes and returns them as a BigEndian uint32 -func ReadUint32(r io.Reader) (uint32, error) { - var v uint32 - if err := binary.Read(r, binary.BigEndian, &v); err != nil { - return 0, err - } - - return v, nil -} - -// ReadUint16 reads 2 bytes and returns them as a BigEndian uint16 -func ReadUint16(r io.Reader) (uint16, error) { - var v uint16 - if err := binary.Read(r, binary.BigEndian, &v); err != nil { - return 0, err - } - - return v, nil -} - -const sniffLen = 8000 - -// IsBinary detects if data is a binary value based on: -// http://git.kernel.org/cgit/git/git.git/tree/xdiff-interface.c?id=HEAD#n198 -func IsBinary(r io.Reader) (bool, error) { - reader := bufio.NewReader(r) - c := 0 - for { - if c == sniffLen { - break - } - - b, err := reader.ReadByte() - if err == io.EOF { - break - } - if err != nil { - return false, err - } - - if b == byte(0) { - return true, nil - } - - c++ - } - - return false, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/binary/write.go b/vendor/github.com/go-git/go-git/v6/utils/binary/write.go deleted file mode 100644 index c08c73a0..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/binary/write.go +++ /dev/null @@ -1,50 +0,0 @@ -package binary - -import ( - "encoding/binary" - "io" -) - -// Write writes the binary representation of data into w, using BigEndian order -// https://golang.org/pkg/encoding/binary/#Write -func Write(w io.Writer, data ...interface{}) error { - for _, v := range data { - if err := binary.Write(w, binary.BigEndian, v); err != nil { - return err - } - } - - return nil -} - -func WriteVariableWidthInt(w io.Writer, n int64) error { - buf := []byte{byte(n & 0x7f)} - n >>= 7 - for n != 0 { - n-- - buf = append([]byte{0x80 | (byte(n & 0x7f))}, buf...) - n >>= 7 - } - - _, err := w.Write(buf) - - return err -} - -// WriteUint64 writes the binary representation of a uint64 into w, in BigEndian -// order -func WriteUint64(w io.Writer, value uint64) error { - return binary.Write(w, binary.BigEndian, value) -} - -// WriteUint32 writes the binary representation of a uint32 into w, in BigEndian -// order -func WriteUint32(w io.Writer, value uint32) error { - return binary.Write(w, binary.BigEndian, value) -} - -// WriteUint16 writes the binary representation of a uint16 into w, in BigEndian -// order -func WriteUint16(w io.Writer, value uint16) error { - return binary.Write(w, binary.BigEndian, value) -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/convert/eol.go b/vendor/github.com/go-git/go-git/v6/utils/convert/eol.go deleted file mode 100644 index 06e46099..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/convert/eol.go +++ /dev/null @@ -1,108 +0,0 @@ -package convert - -import ( - "bytes" - "io" -) - -type crlfToLFWriter struct { - w io.Writer -} - -// NewLFWriter wraps a writer to convert CRLF line endings into LF line endings. -// It assumes that data is text; not binary. See [Stat.IsBinary]. -func NewLFWriter(w io.Writer) io.Writer { - return &crlfToLFWriter{w: w} -} - -func (conv *crlfToLFWriter) Write(data []byte) (int, error) { - if len(data) == 0 { - return 0, nil - } - - var n int - for { - window := data[n:] - - idx := bytes.Index(window, []byte{'\r', '\n'}) - if idx == -1 { - break - } - - w, err := conv.w.Write(window[:idx]) - if err != nil { - return n + w, err - } - _, err = conv.w.Write([]byte{'\n'}) - if err != nil { - return n + w, err - } - - n += idx + 2 - } - - if data[len(data)-1] == '\r' { - // Lone CR woudn't exist. So it's CRLF. - rest, err := conv.w.Write(data[n : len(data)-1]) - if err != nil { - return n + rest, err - } - return n + rest + 1, nil - } - - rest, err := conv.w.Write(data[n:]) - return n + rest, err -} - -type lfToCRLFWriter struct { - w io.Writer - hadCR bool -} - -// NewCRLFWriter wraps a writer to convert LF line endings into CRLF line endings. -// It assumes that data is text; not binary. See [Stat.IsBinary]. -func NewCRLFWriter(w io.Writer) io.Writer { - return &lfToCRLFWriter{w: w} -} - -func (conv *lfToCRLFWriter) Write(data []byte) (int, error) { - if len(data) == 0 { - return 0, nil - } - - var n int - for { - window := data[n:] - - idx := bytes.IndexByte(window, '\n') - if idx == -1 { - break - } - - switch { - case idx == 0 && conv.hadCR: - fallthrough - case idx > 0 && window[idx-1] == '\r': - w, err := conv.w.Write(window[:idx+1]) - if err != nil { - return n + w, err - } - default: - w, err := conv.w.Write(window[:idx]) - if err != nil { - return n + w, err - } - _, err = conv.w.Write([]byte{'\r', '\n'}) - if err != nil { - return n + w, err - } - } - - n += idx + 1 - } - - conv.hadCR = data[len(data)-1] == '\r' - - rest, err := conv.w.Write(data[n:]) - return n + rest, err -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/convert/stat.go b/vendor/github.com/go-git/go-git/v6/utils/convert/stat.go deleted file mode 100644 index 2c703225..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/convert/stat.go +++ /dev/null @@ -1,85 +0,0 @@ -package convert - -import "io" - -type Stat struct { - NUL, LoneCR, LoneLF, CRLF uint - Printable, NonPrintable uint -} - -// IsBinary detects if data is binary based on: -// https://git.kernel.org/pub/scm/git/git.git/tree/convert.c?id=HEAD#n94 -func (s Stat) IsBinary() bool { - if s.NUL > 0 { - return true - } - if s.LoneCR > 0 { - return true - } - - mostlyPrintable := (s.Printable >> 7) >= s.NonPrintable - - return !mostlyPrintable -} - -// GetStat returns [Stat] of the reader based on: -// https://git.kernel.org/pub/scm/git/git.git/tree/convert.c?id=HEAD#n45 -func GetStat(r io.Reader) (stat Stat, err error) { - var hadCR bool - - buf := make([]byte, 1) - - for { - if _, err := r.Read(buf); err != nil { - if err == io.EOF { - break - } - return Stat{}, err - } - - b := buf[0] - - if b != '\n' && hadCR { - // CR not followed by LF. Lone CR is considered binary. - stat.LoneCR++ - hadCR = false - } - - switch { - case b == '\n': - if hadCR { - stat.CRLF++ - hadCR = false - } else { - stat.LoneLF++ - } - case b == '\r': - hadCR = true - case b == 127: // DEL - stat.NonPrintable++ - case b < 32: - switch b { - case '\b', '\t', '\033', '\014': // BS, HT, ESC and FF - stat.Printable++ - case 0: - stat.NUL++ - default: - stat.NonPrintable++ - } - default: - stat.Printable++ - } - } - - if hadCR { - // Last byte is lone CR. - stat.LoneCR++ - } - - // If file ends with EOF then don't count this EOF as non-printable. - if buf[0] == '\032' { - stat.NonPrintable-- - } - - return stat, nil -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/diff/diff.go b/vendor/github.com/go-git/go-git/v6/utils/diff/diff.go deleted file mode 100644 index 70054949..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/diff/diff.go +++ /dev/null @@ -1,61 +0,0 @@ -// Package diff implements line oriented diffs, similar to the ancient -// Unix diff command. -// -// The current implementation is just a wrapper around Sergi's -// go-diff/diffmatchpatch library, which is a go port of Neil -// Fraser's google-diff-match-patch code -package diff - -import ( - "bytes" - "time" - - "github.com/sergi/go-diff/diffmatchpatch" -) - -// Do computes the (line oriented) modifications needed to turn the src -// string into the dst string. The underlying algorithm is Meyers, -// its complexity is O(N*d) where N is min(lines(src), lines(dst)) and d -// is the size of the diff. -func Do(src, dst string) (diffs []diffmatchpatch.Diff) { - // the default timeout is time.Second which may be too small under heavy load - return DoWithTimeout(src, dst, time.Hour) -} - -// DoWithTimeout computes the (line oriented) modifications needed to turn the src -// string into the dst string. The `timeout` argument specifies the maximum -// amount of time it is allowed to spend in this function. If the timeout -// is exceeded, the parts of the strings which were not considered are turned into -// a bulk delete+insert and the half-baked suboptimal result is returned at once. -// The underlying algorithm is Meyers, its complexity is O(N*d) where N is -// min(lines(src), lines(dst)) and d is the size of the diff. -func DoWithTimeout(src, dst string, timeout time.Duration) (diffs []diffmatchpatch.Diff) { - dmp := diffmatchpatch.New() - dmp.DiffTimeout = timeout - wSrc, wDst, warray := dmp.DiffLinesToRunes(src, dst) - diffs = dmp.DiffMainRunes(wSrc, wDst, false) - diffs = dmp.DiffCharsToLines(diffs, warray) - return diffs -} - -// Dst computes and returns the destination text. -func Dst(diffs []diffmatchpatch.Diff) string { - var text bytes.Buffer - for _, d := range diffs { - if d.Type != diffmatchpatch.DiffDelete { - text.WriteString(d.Text) - } - } - return text.String() -} - -// Src computes and returns the source text -func Src(diffs []diffmatchpatch.Diff) string { - var text bytes.Buffer - for _, d := range diffs { - if d.Type != diffmatchpatch.DiffInsert { - text.WriteString(d.Text) - } - } - return text.String() -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/ioutil/common.go b/vendor/github.com/go-git/go-git/v6/utils/ioutil/common.go deleted file mode 100644 index 1fb0786f..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/ioutil/common.go +++ /dev/null @@ -1,211 +0,0 @@ -// Package ioutil implements some I/O utility functions. -package ioutil - -import ( - "bufio" - "context" - "errors" - "io" -) - -// Peeker is an interface for types that can peek at the next bytes. -type Peeker interface { - Peek(int) ([]byte, error) -} - -// ReadPeeker is an interface that groups the basic Read and Peek methods. -type ReadPeeker interface { - io.Reader - Peeker -} - -var ErrEmptyReader = errors.New("reader is empty") - -// NonEmptyReader takes a reader and returns it if it is not empty, or -// `ErrEmptyReader` if it is empty. If there is an error when reading the first -// byte of the given reader, it will be propagated. -func NonEmptyReader(r io.Reader) (io.Reader, error) { - pr, ok := r.(ReadPeeker) - if !ok { - pr = bufio.NewReader(r) - } - - _, err := pr.Peek(1) - if err == io.EOF { - return nil, ErrEmptyReader - } - - if err != nil { - return nil, err - } - - return pr, nil -} - -type readCloser struct { - io.Reader - closer io.Closer -} - -func (r *readCloser) Close() error { - return r.closer.Close() -} - -// NewReadCloser creates an `io.ReadCloser` with the given `io.Reader` and -// `io.Closer`. -func NewReadCloser(r io.Reader, c io.Closer) io.ReadCloser { - return &readCloser{Reader: r, closer: c} -} - -type readCloserCloser struct { - io.ReadCloser - closer func() error -} - -func (r *readCloserCloser) Close() (err error) { - defer func() { - if err == nil { - err = r.closer() - return - } - _ = r.closer() - }() - return r.ReadCloser.Close() -} - -// NewReadCloserWithCloser creates an `io.ReadCloser` with the given `io.ReaderCloser` and -// `io.Closer` that ensures that the closer is closed on close -func NewReadCloserWithCloser(r io.ReadCloser, c func() error) io.ReadCloser { - return &readCloserCloser{ReadCloser: r, closer: c} -} - -type writeCloser struct { - io.Writer - closer io.Closer -} - -func (r *writeCloser) Close() error { - if r.closer == nil { - return nil - } - return r.closer.Close() -} - -// NewWriteCloser creates an `io.WriteCloser` with the given `io.Writer` and -// `io.Closer`. -func NewWriteCloser(w io.Writer, c io.Closer) io.WriteCloser { - return &writeCloser{Writer: w, closer: c} -} - -type writeNopCloser struct { - io.Writer -} - -func (writeNopCloser) Close() error { return nil } - -// WriteNopCloser returns a WriteCloser with a no-op Close method wrapping -// the provided Writer w. -func WriteNopCloser(w io.Writer) io.WriteCloser { - return writeNopCloser{w} -} - -type readerAtAsReader struct { - io.ReaderAt - offset int64 -} - -func (r *readerAtAsReader) Read(bs []byte) (int, error) { - n, err := r.ReaderAt.ReadAt(bs, r.offset) - r.offset += int64(n) - return n, err -} - -func NewReaderUsingReaderAt(r io.ReaderAt, offset int64) io.Reader { - return &readerAtAsReader{ - ReaderAt: r, - offset: offset, - } -} - -// CheckClose calls Close on the given io.Closer. If the given *error points to -// nil, it will be assigned the error returned by Close. Otherwise, any error -// returned by Close will be ignored. CheckClose is usually called with defer. -func CheckClose(c io.Closer, err *error) { - if cerr := c.Close(); cerr != nil && *err == nil { - *err = cerr - } -} - -// NewContextWriteCloser as NewContextWriter but with io.Closer interface. -func NewContextWriteCloser(ctx context.Context, w io.WriteCloser) io.WriteCloser { - ctxw := NewContextWriter(ctx, w) - return NewWriteCloser(ctxw, w) -} - -// NewContextReadCloser as NewContextReader but with io.Closer interface. -func NewContextReadCloser(ctx context.Context, r io.ReadCloser) io.ReadCloser { - ctxr := NewContextReader(ctx, r) - return NewReadCloser(ctxr, r) -} - -type readerOnError struct { - io.Reader - notify func(error) -} - -// NewReaderOnError returns a io.Reader that call the notify function when an -// unexpected (!io.EOF) error happens, after call Read function. -func NewReaderOnError(r io.Reader, notify func(error)) io.Reader { - return &readerOnError{r, notify} -} - -// NewReadCloserOnError returns a io.ReadCloser that call the notify function -// when an unexpected (!io.EOF) error happens, after call Read function. -func NewReadCloserOnError(r io.ReadCloser, notify func(error)) io.ReadCloser { - return NewReadCloser(NewReaderOnError(r, notify), r) -} - -func (r *readerOnError) Read(buf []byte) (n int, err error) { - n, err = r.Reader.Read(buf) - if err != nil && err != io.EOF { - r.notify(err) - } - - return -} - -type writerOnError struct { - io.Writer - notify func(error) -} - -// NewWriterOnError returns a io.Writer that call the notify function when an -// unexpected (!io.EOF) error happens, after call Write function. -func NewWriterOnError(w io.Writer, notify func(error)) io.Writer { - return &writerOnError{w, notify} -} - -// NewWriteCloserOnError returns a io.WriteCloser that call the notify function -// when an unexpected (!io.EOF) error happens, after call Write function. -func NewWriteCloserOnError(w io.WriteCloser, notify func(error)) io.WriteCloser { - return NewWriteCloser(NewWriterOnError(w, notify), w) -} - -func (r *writerOnError) Write(p []byte) (n int, err error) { - n, err = r.Writer.Write(p) - if err != nil && err != io.EOF { - r.notify(err) - } - - return -} - -// CloserFunc implements the io.Closer interface with a function. -type CloserFunc func() error - -var _ io.Closer = CloserFunc(nil) - -// Close calls the function. -func (f CloserFunc) Close() error { - return f() -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/ioutil/context.go b/vendor/github.com/go-git/go-git/v6/utils/ioutil/context.go deleted file mode 100644 index 49bcd565..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/ioutil/context.go +++ /dev/null @@ -1,123 +0,0 @@ -package ioutil - -import ( - "context" - "io" - "slices" -) - -type ioret struct { - err error - n int -} - -type Writer interface { - io.Writer -} - -type ctxWriter struct { - w io.Writer - ctx context.Context -} - -// NewContextWriter wraps a writer to make it respect the given Context. -// If there is a blocking write, the returned Writer will return -// whenever the context is cancelled (the return values are n=0 -// and err=ctx.Err().) -// -// Note that this wrapper DOES NOT ACTUALLY cancel the underlying -// write, as there is no way to do that with the standard Go io -// interface. So the read and write _will_ happen or hang. Use -// this sparingly, make sure to cancel the read or write as necessary -// (e.g. closing a connection whose context is up, etc.) -// -// Furthermore, in order to protect your memory from being read -// _after_ you've cancelled the context, this io.Writer will -// first make a **copy** of the buffer. -func NewContextWriter(ctx context.Context, w io.Writer) *ctxWriter { - if ctx == nil { - ctx = context.Background() - } - return &ctxWriter{ctx: ctx, w: w} -} - -func (w *ctxWriter) Write(buf []byte) (int, error) { - buf2 := slices.Clone(buf) - - c := make(chan ioret, 1) - - go func() { - n, err := w.w.Write(buf2) - c <- ioret{err, n} - close(c) - }() - - select { - case r := <-c: - if err := w.ctx.Err(); err != nil { - return 0, err - } - return r.n, r.err - case <-w.ctx.Done(): - return 0, w.ctx.Err() - } -} - -type Reader interface { - io.Reader -} - -type ctxReader struct { - r io.Reader - ctx context.Context - closer io.Closer -} - -// NewContextReader wraps a reader to make it respect given Context. -// If there is a blocking read, the returned Reader will return -// whenever the context is cancelled (the return values are n=0 -// and err=ctx.Err().) -// -// Note well: this wrapper DOES NOT ACTUALLY cancel the underlying -// write-- there is no way to do that with the standard go io -// interface. So the read and write _will_ happen or hang. So, use -// this sparingly, make sure to cancel the read or write as necesary -// (e.g. closing a connection whose context is up, etc.) -// -// Furthermore, in order to protect your memory from being read -// _before_ you've cancelled the context, this io.Reader will -// allocate a buffer of the same size, and **copy** into the client's -// if the read succeeds in time. -func NewContextReader(ctx context.Context, r io.Reader) *ctxReader { - return &ctxReader{ctx: ctx, r: r} -} - -func (r *ctxReader) Read(buf []byte) (int, error) { - buf2 := make([]byte, len(buf)) - - c := make(chan ioret, 1) - - go func() { - n, err := r.r.Read(buf2) - c <- ioret{err, n} - close(c) - }() - - select { - case ret := <-c: - if err := r.ctx.Err(); err != nil { - return 0, err - } - copy(buf, buf2) - return ret.n, ret.err - case <-r.ctx.Done(): - if r.closer != nil { - r.closer.Close() - } - return 0, r.ctx.Err() - } -} - -func NewContextReaderWithCloser(ctx context.Context, r io.Reader, closer io.Closer) *ctxReader { - return &ctxReader{ctx: ctx, r: r, closer: closer} -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/ioutil/sync.go b/vendor/github.com/go-git/go-git/v6/utils/ioutil/sync.go deleted file mode 100644 index d97017fb..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/ioutil/sync.go +++ /dev/null @@ -1,18 +0,0 @@ -package ioutil - -import ( - "io" - - "github.com/go-git/go-git/v6/utils/sync" -) - -// CopyBufferPool calls io.CopyBuffer and uses a buffer from sync.GetByteSlice, -// to reduce the complexity when using it while avoiding the allocation -// of a new buffer per call. -func CopyBufferPool(dst io.Writer, src io.Reader) (n int64, err error) { - buf := sync.GetByteSlice() - n, err = io.CopyBuffer(dst, src, *buf) - sync.PutByteSlice(buf) - - return -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/change.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/change.go deleted file mode 100644 index d18662ac..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/change.go +++ /dev/null @@ -1,160 +0,0 @@ -package merkletrie - -import ( - "errors" - "fmt" - "io" - - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -var ( - ErrEmptyFileName = errors.New("empty filename in tree entry") -) - -// Action values represent the kind of things a Change can represent: -// insertion, deletions or modifications of files. -type Action int - -// The set of possible actions in a change. -const ( - _ Action = iota - Insert - Delete - Modify -) - -// String returns the action as a human readable text. -func (a Action) String() string { - switch a { - case Insert: - return "Insert" - case Delete: - return "Delete" - case Modify: - return "Modify" - default: - panic(fmt.Sprintf("unsupported action: %d", a)) - } -} - -// A Change value represent how a noder has change between to merkletries. -type Change struct { - // The noder before the change or nil if it was inserted. - From noder.Path - // The noder after the change or nil if it was deleted. - To noder.Path -} - -// Action is convenience method that returns what Action c represents. -func (c *Change) Action() (Action, error) { - if c.From == nil && c.To == nil { - return Action(0), fmt.Errorf("malformed change: nil from and to") - } - if c.From == nil { - return Insert, nil - } - if c.To == nil { - return Delete, nil - } - - return Modify, nil -} - -// NewInsert returns a new Change representing the insertion of n. -func NewInsert(n noder.Path) Change { return Change{To: n} } - -// NewDelete returns a new Change representing the deletion of n. -func NewDelete(n noder.Path) Change { return Change{From: n} } - -// NewModify returns a new Change representing that a has been modified and -// it is now b. -func NewModify(a, b noder.Path) Change { - return Change{ - From: a, - To: b, - } -} - -// String returns a single change in human readable form, using the -// format: '<' + action + space + path + '>'. The contents of the file -// before or after the change are not included in this format. -// -// Example: inserting a file at the path a/b/c.txt will return "". -func (c Change) String() string { - action, err := c.Action() - if err != nil { - panic(err) - } - - var path string - if action == Delete { - path = c.From.String() - } else { - path = c.To.String() - } - - return fmt.Sprintf("<%s %s>", action, path) -} - -// Changes is a list of changes between to merkletries. -type Changes []Change - -// NewChanges returns an empty list of changes. -func NewChanges() Changes { - return Changes{} -} - -// Add adds the change c to the list of changes. -func (l *Changes) Add(c Change) { - *l = append(*l, c) -} - -// AddRecursiveInsert adds the required changes to insert all the -// file-like noders found in root, recursively. -func (l *Changes) AddRecursiveInsert(root noder.Path) error { - return l.addRecursive(root, NewInsert) -} - -// AddRecursiveDelete adds the required changes to delete all the -// file-like noders found in root, recursively. -func (l *Changes) AddRecursiveDelete(root noder.Path) error { - return l.addRecursive(root, NewDelete) -} - -type noderToChangeFn func(noder.Path) Change // NewInsert or NewDelete - -func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error { - if root.String() == "" { - return ErrEmptyFileName - } - - if !root.IsDir() { - if !root.Skip() { - l.Add(ctor(root)) - } - return nil - } - - i, err := NewIterFromPath(root) - if err != nil { - return err - } - - var current noder.Path - for { - if current, err = i.Step(); err != nil { - if err == io.EOF { - break - } - return err - } - if current.IsDir() || current.Skip() { - continue - } - l.Add(ctor(current)) - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/difftree.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/difftree.go deleted file mode 100644 index ced7c595..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/difftree.go +++ /dev/null @@ -1,450 +0,0 @@ -package merkletrie - -// The focus of this difftree implementation is to save time by -// skipping whole directories if their hash is the same in both -// trees. -// -// The diff algorithm implemented here is based on the doubleiter -// type defined in this same package; we will iterate over both -// trees at the same time, while comparing the current noders in -// each iterator. Depending on how they differ we will output the -// corresponding changes and move the iterators further over both -// trees. -// -// The table below shows all the possible comparison results, along -// with what changes should we produce and how to advance the -// iterators. -// -// The table is implemented by the switches in this function, -// diffTwoNodes, diffTwoNodesSameName and diffTwoDirs. -// -// Many Bothans died to bring us this information, make sure you -// understand the table before modifying this code. - -// # Cases -// -// When comparing noders in both trees you will find yourself in -// one of 169 possible cases, but if we ignore moves, we can -// simplify a lot the search space into the following table: -// -// - "-": nothing, no file or directory -// - a<>: an empty file named "a". -// - a<1>: a file named "a", with "1" as its contents. -// - a<2>: a file named "a", with "2" as its contents. -// - a(): an empty dir named "a". -// - a(...): a dir named "a", with some files and/or dirs inside (possibly -// empty). -// - a(;;;): a dir named "a", with some other files and/or dirs inside -// (possibly empty), which different from the ones in "a(...)". -// -// \ to - a<> a<1> a<2> a() a(...) a(;;;) -// from \ -// - 00 01 02 03 04 05 06 -// a<> 10 11 12 13 14 15 16 -// a<1> 20 21 22 23 24 25 26 -// a<2> 30 31 32 33 34 35 36 -// a() 40 41 42 43 44 45 46 -// a(...) 50 51 52 53 54 55 56 -// a(;;;) 60 61 62 63 64 65 66 -// -// Every (from, to) combination in the table is a special case, but -// some of them can be merged into some more general cases, for -// instance 11 and 22 can be merged into the general case: both -// noders are equal. -// -// Here is a full list of all the cases that are similar and how to -// merge them together into more general cases. Each general case -// is labeled with an uppercase letter for further reference, and it -// is followed by the pseudocode of the checks you have to perform -// on both noders to see if you are in such a case, the actions to -// perform (i.e. what changes to output) and how to advance the -// iterators of each tree to continue the comparison process. -// -// ## A. Impossible: 00 -// -// ## B. Same thing on both sides: 11, 22, 33, 44, 55, 66 -// - check: `SameName() && SameHash()` -// - action: do nothing. -// - advance: `FromNext(); ToNext()` -// -// ### C. To was created: 01, 02, 03, 04, 05, 06 -// - check: `DifferentName() && ToBeforeFrom()` -// - action: insertRecursively(to) -// - advance: `ToNext()` -// -// ### D. From was deleted: 10, 20, 30, 40, 50, 60 -// - check: `DifferentName() && FromBeforeTo()` -// - action: `DeleteRecursively(from)` -// - advance: `FromNext()` -// -// ### E. Empty file to file with contents: 12, 13 -// - check: `SameName() && DifferentHash() && FromIsFile() && -// ToIsFile() && FromIsEmpty()` -// - action: `modifyFile(from, to)` -// - advance: `FromNext()` or `FromStep()` -// -// ### E'. file with contents to empty file: 21, 31 -// - check: `SameName() && DifferentHash() && FromIsFile() && -// ToIsFile() && ToIsEmpty()` -// - action: `modifyFile(from, to)` -// - advance: `FromNext()` or `FromStep()` -// -// ### F. empty file to empty dir with the same name: 14 -// - check: `SameName() && FromIsFile() && FromIsEmpty() && -// ToIsDir() && ToIsEmpty()` -// - action: `DeleteFile(from); InsertEmptyDir(to)` -// - advance: `FromNext(); ToNext()` -// -// ### F'. empty dir to empty file of the same name: 41 -// - check: `SameName() && FromIsDir() && FromIsEmpty && -// ToIsFile() && ToIsEmpty()` -// - action: `DeleteEmptyDir(from); InsertFile(to)` -// - advance: `FromNext(); ToNext()` or step for any of them. -// -// ### G. empty file to non-empty dir of the same name: 15, 16 -// - check: `SameName() && FromIsFile() && ToIsDir() && -// FromIsEmpty() && ToIsNotEmpty()` -// - action: `DeleteFile(from); InsertDirRecursively(to)` -// - advance: `FromNext(); ToNext()` -// -// ### G'. non-empty dir to empty file of the same name: 51, 61 -// - check: `SameName() && FromIsDir() && FromIsNotEmpty() && -// ToIsFile() && FromIsEmpty()` -// - action: `DeleteDirRecursively(from); InsertFile(to)` -// - advance: `FromNext(); ToNext()` -// -// ### H. modify file contents: 23, 32 -// - check: `SameName() && FromIsFile() && ToIsFile() && -// FromIsNotEmpty() && ToIsNotEmpty()` -// - action: `ModifyFile(from, to)` -// - advance: `FromNext(); ToNext()` -// -// ### I. file with contents to empty dir: 24, 34 -// - check: `SameName() && DifferentHash() && FromIsFile() && -// FromIsNotEmpty() && ToIsDir() && ToIsEmpty()` -// - action: `DeleteFile(from); InsertEmptyDir(to)` -// - advance: `FromNext(); ToNext()` -// -// ### I'. empty dir to file with contents: 42, 43 -// - check: `SameName() && DifferentHash() && FromIsDir() && -// FromIsEmpty() && ToIsFile() && ToIsEmpty()` -// - action: `DeleteDir(from); InsertFile(to)` -// - advance: `FromNext(); ToNext()` -// -// ### J. file with contents to dir with contents: 25, 26, 35, 36 -// - check: `SameName() && DifferentHash() && FromIsFile() && -// FromIsNotEmpty() && ToIsDir() && ToIsNotEmpty()` -// - action: `DeleteFile(from); InsertDirRecursively(to)` -// - advance: `FromNext(); ToNext()` -// -// ### J'. dir with contents to file with contents: 52, 62, 53, 63 -// - check: `SameName() && DifferentHash() && FromIsDir() && -// FromIsNotEmpty() && ToIsFile() && ToIsNotEmpty()` -// - action: `DeleteDirRecursively(from); InsertFile(to)` -// - advance: `FromNext(); ToNext()` -// -// ### K. empty dir to dir with contents: 45, 46 -// - check: `SameName() && DifferentHash() && FromIsDir() && -// FromIsEmpty() && ToIsDir() && ToIsNotEmpty()` -// - action: `InsertChildrenRecursively(to)` -// - advance: `FromNext(); ToNext()` -// -// ### K'. dir with contents to empty dir: 54, 64 -// - check: `SameName() && DifferentHash() && FromIsDir() && -// FromIsEmpty() && ToIsDir() && ToIsNotEmpty()` -// - action: `DeleteChildrenRecursively(from)` -// - advance: `FromNext(); ToNext()` -// -// ### L. dir with contents to dir with different contents: 56, 65 -// - check: `SameName() && DifferentHash() && FromIsDir() && -// FromIsNotEmpty() && ToIsDir() && ToIsNotEmpty()` -// - action: nothing -// - advance: `FromStep(); ToStep()` -// -// - -// All these cases can be further simplified by a truth table -// reduction process, in which we gather similar checks together to -// make the final code easier to read and understand. -// -// The first 6 columns are the outputs of the checks to perform on -// both noders. I have labeled them 1 to 6, this is what they mean: -// -// 1: SameName() -// 2: SameHash() -// 3: FromIsDir() -// 4: ToIsDir() -// 5: FromIsEmpty() -// 6: ToIsEmpty() -// -// The from and to columns are a fsnoder example of the elements -// that you will find on each tree under the specified comparison -// results (columns 1 to 6). -// -// The type column identifies the case we are into, from the list above. -// -// The type' column identifies the new set of reduced cases, using -// lowercase letters, and they are explained after the table. -// -// The last column is the set of actions and advances for each case. -// -// "---" means impossible except in case of hash collision. -// -// advance meaning: -// - NN: from.Next(); to.Next() -// - SS: from.Step(); to.Step() -// -// 1 2 3 4 5 6 | from | to |type|type'|action ; advance -// ------------+--------+--------+----+------------------------------------ -// 0 0 0 0 0 0 | | | | | if !SameName() { -// . | | | | | if FromBeforeTo() { -// . | | | D | d | delete(from); from.Next() -// . | | | | | } else { -// . | | | C | c | insert(to); to.Next() -// . | | | | | } -// 0 1 1 1 1 1 | | | | | } -// 1 0 0 0 0 0 | a<1> | a<2> | H | e | modify(from, to); NN -// 1 0 0 0 0 1 | a<1> | a<> | E' | e | modify(from, to); NN -// 1 0 0 0 1 0 | a<> | a<1> | E | e | modify(from, to); NN -// 1 0 0 0 1 1 | ---- | ---- | | e | -// 1 0 0 1 0 0 | a<1> | a(...) | J | f | delete(from); insert(to); NN -// 1 0 0 1 0 1 | a<1> | a() | I | f | delete(from); insert(to); NN -// 1 0 0 1 1 0 | a<> | a(...) | G | f | delete(from); insert(to); NN -// 1 0 0 1 1 1 | a<> | a() | F | f | delete(from); insert(to); NN -// 1 0 1 0 0 0 | a(...) | a<1> | J' | f | delete(from); insert(to); NN -// 1 0 1 0 0 1 | a(...) | a<> | G' | f | delete(from); insert(to); NN -// 1 0 1 0 1 0 | a() | a<1> | I' | f | delete(from); insert(to); NN -// 1 0 1 0 1 1 | a() | a<> | F' | f | delete(from); insert(to); NN -// 1 0 1 1 0 0 | a(...) | a(;;;) | L | g | nothing; SS -// 1 0 1 1 0 1 | a(...) | a() | K' | h | deleteChildren(from); NN -// 1 0 1 1 1 0 | a() | a(...) | K | i | insertChildren(to); NN -// 1 0 1 1 1 1 | ---- | ---- | | | -// 1 1 0 0 0 0 | a<1> | a<1> | B | b | nothing; NN -// 1 1 0 0 0 1 | ---- | ---- | | b | -// 1 1 0 0 1 0 | ---- | ---- | | b | -// 1 1 0 0 1 1 | a<> | a<> | B | b | nothing; NN -// 1 1 0 1 0 0 | ---- | ---- | | b | -// 1 1 0 1 0 1 | ---- | ---- | | b | -// 1 1 0 1 1 0 | ---- | ---- | | b | -// 1 1 0 1 1 1 | ---- | ---- | | b | -// 1 1 1 0 0 0 | ---- | ---- | | b | -// 1 1 1 0 0 1 | ---- | ---- | | b | -// 1 1 1 0 1 0 | ---- | ---- | | b | -// 1 1 1 0 1 1 | ---- | ---- | | b | -// 1 1 1 1 0 0 | a(...) | a(...) | B | b | nothing; NN -// 1 1 1 1 0 1 | ---- | ---- | | b | -// 1 1 1 1 1 0 | ---- | ---- | | b | -// 1 1 1 1 1 1 | a() | a() | B | b | nothing; NN -// -// c and d: -// if !SameName() -// d if FromBeforeTo() -// c else -// b: SameName) && sameHash() -// e: SameName() && !sameHash() && BothAreFiles() -// f: SameName() && !sameHash() && FileAndDir() -// g: SameName() && !sameHash() && BothAreDirs() && NoneIsEmpty -// i: SameName() && !sameHash() && BothAreDirs() && FromIsEmpty -// h: else of i - -import ( - "context" - "errors" - "fmt" - - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -var ( - // ErrCanceled is returned whenever the operation is canceled. - ErrCanceled = errors.New("operation canceled") -) - -// DiffTree calculates the list of changes between two merkletries. It -// uses the provided hashEqual callback to compare noders. -func DiffTree( - fromTree, - toTree noder.Noder, - hashEqual noder.Equal, -) (Changes, error) { - return DiffTreeContext(context.Background(), fromTree, toTree, hashEqual) -} - -// DiffTreeContext calculates the list of changes between two merkletries. It -// uses the provided hashEqual callback to compare noders. -// Error will be returned if context expires -// Provided context must be non nil -func DiffTreeContext(ctx context.Context, fromTree, toTree noder.Noder, - hashEqual noder.Equal) (Changes, error) { - ret := NewChanges() - - ii, err := newDoubleIter(fromTree, toTree, hashEqual) - if err != nil { - return nil, err - } - - for { - select { - case <-ctx.Done(): - return nil, ErrCanceled - default: - } - - from := ii.from.current - to := ii.to.current - - switch r := ii.remaining(); r { - case noMoreNoders: - return ret, nil - case onlyFromRemains: - if !from.Skip() { - if err = ret.AddRecursiveDelete(from); err != nil { - return nil, err - } - } - if err = ii.nextFrom(); err != nil { - return nil, err - } - case onlyToRemains: - if !to.Skip() { - if err = ret.AddRecursiveInsert(to); err != nil { - return nil, err - } - } - if err = ii.nextTo(); err != nil { - return nil, err - } - case bothHaveNodes: - var err error - switch { - case from.Skip(): - if from.Name() == to.Name() { - err = ii.nextBoth() - } else { - err = ii.nextFrom() - } - case to.Skip(): - if from.Name() == to.Name() { - err = ii.nextBoth() - } else { - err = ii.nextTo() - } - default: - err = diffNodes(&ret, ii) - } - - if err != nil { - return nil, err - } - default: - panic(fmt.Sprintf("unknown remaining value: %d", r)) - } - } -} - -func diffNodes(changes *Changes, ii *doubleIter) error { - from := ii.from.current - to := ii.to.current - var err error - - // compare their full paths as strings - switch from.Compare(to) { - case -1: - if err = changes.AddRecursiveDelete(from); err != nil { - return err - } - if err = ii.nextFrom(); err != nil { - return err - } - case 1: - if err = changes.AddRecursiveInsert(to); err != nil { - return err - } - if err = ii.nextTo(); err != nil { - return err - } - default: - if err := diffNodesSameName(changes, ii); err != nil { - return err - } - } - - return nil -} - -func diffNodesSameName(changes *Changes, ii *doubleIter) error { - from := ii.from.current - to := ii.to.current - - status, err := ii.compare() - if err != nil { - return err - } - - switch { - case status.sameHash: - // do nothing - if err = ii.nextBoth(); err != nil { - return err - } - case status.bothAreFiles: - changes.Add(NewModify(from, to)) - if err = ii.nextBoth(); err != nil { - return err - } - case status.fileAndDir: - if err = changes.AddRecursiveDelete(from); err != nil { - return err - } - if err = changes.AddRecursiveInsert(to); err != nil { - return err - } - if err = ii.nextBoth(); err != nil { - return err - } - case status.bothAreDirs: - if err = diffDirs(changes, ii); err != nil { - return err - } - default: - return fmt.Errorf("bad status from double iterator") - } - - return nil -} - -func diffDirs(changes *Changes, ii *doubleIter) error { - from := ii.from.current - to := ii.to.current - - status, err := ii.compare() - if err != nil { - return err - } - - switch { - case status.fromIsEmptyDir: - if err = changes.AddRecursiveInsert(to); err != nil { - return err - } - if err = ii.nextBoth(); err != nil { - return err - } - case status.toIsEmptyDir: - if err = changes.AddRecursiveDelete(from); err != nil { - return err - } - if err = ii.nextBoth(); err != nil { - return err - } - case !status.fromIsEmptyDir && !status.toIsEmptyDir: - // do nothing - if err = ii.stepBoth(); err != nil { - return err - } - default: - return fmt.Errorf("both dirs are empty but has different hash") - } - - return nil -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/doc.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/doc.go deleted file mode 100644 index 5204024a..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/doc.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -Package merkletrie provides support for n-ary trees that are at the same -time Merkle trees and Radix trees (tries). - -Git trees are Radix n-ary trees in virtue of the names of their -tree entries. At the same time, git trees are Merkle trees thanks to -their hashes. - -This package defines Merkle tries as nodes that should have: - -- a hash: the Merkle part of the Merkle trie - -- a key: the Radix part of the Merkle trie - -The Merkle hash condition is not enforced by this package though. This -means that the hash of a node doesn't have to take into account the hashes of -their children, which is good for testing purposes. - -Nodes in the Merkle trie are abstracted by the Noder interface. The -intended use is that git trees implements this interface, either -directly or using a simple wrapper. - -This package provides an iterator for merkletries that can skip whole -directory-like noders and an efficient merkletrie comparison algorithm. - -When comparing git trees, the simple approach of alphabetically sorting -their elements and comparing the resulting lists is too slow as it -depends linearly on the number of files in the trees: When a directory -has lots of files but none of them has been modified, this approach is -very expensive. We can do better by prunning whole directories that -have not change, just by looking at their hashes. This package provides -the tools to do exactly that. -*/ -package merkletrie diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/doubleiter.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/doubleiter.go deleted file mode 100644 index b9137680..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/doubleiter.go +++ /dev/null @@ -1,187 +0,0 @@ -package merkletrie - -import ( - "fmt" - "io" - - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// A doubleIter is a convenience type to keep track of the current -// noders in two merkletries that are going to be iterated in parallel. -// It has methods for: -// -// - iterating over the merkletries, both at the same time or -// individually: nextFrom, nextTo, nextBoth, stepBoth -// -// - checking if there are noders left in one or both of them with the -// remaining method and its associated returned type. -// -// - comparing the current noders of both merkletries in several ways, -// with the compare method and its associated returned type. -type doubleIter struct { - from struct { - iter *Iter - current noder.Path // nil if no more nodes - } - to struct { - iter *Iter - current noder.Path // nil if no more nodes - } - hashEqual noder.Equal -} - -// NewdoubleIter returns a new doubleIter for the merkletries "from" and -// "to". The hashEqual callback function will be used by the doubleIter -// to compare the hash of the noders in the merkletries. The doubleIter -// will be initialized to the first elements in each merkletrie if any. -func newDoubleIter(from, to noder.Noder, hashEqual noder.Equal) ( - *doubleIter, error) { - var ii doubleIter - var err error - - if ii.from.iter, err = NewIter(from); err != nil { - return nil, fmt.Errorf("from: %s", err) - } - if ii.from.current, err = ii.from.iter.Next(); turnEOFIntoNil(err) != nil { - return nil, fmt.Errorf("from: %s", err) - } - - if ii.to.iter, err = NewIter(to); err != nil { - return nil, fmt.Errorf("to: %s", err) - } - if ii.to.current, err = ii.to.iter.Next(); turnEOFIntoNil(err) != nil { - return nil, fmt.Errorf("to: %s", err) - } - - ii.hashEqual = hashEqual - - return &ii, nil -} - -func turnEOFIntoNil(e error) error { - if e != nil && e != io.EOF { - return e - } - return nil -} - -// NextBoth makes d advance to the next noder in both merkletries. If -// any of them is a directory, it skips its contents. -func (d *doubleIter) nextBoth() error { - if err := d.nextFrom(); err != nil { - return err - } - if err := d.nextTo(); err != nil { - return err - } - - return nil -} - -// NextFrom makes d advance to the next noder in the "from" merkletrie, -// skipping its contents if it is a directory. -func (d *doubleIter) nextFrom() (err error) { - d.from.current, err = d.from.iter.Next() - return turnEOFIntoNil(err) -} - -// NextTo makes d advance to the next noder in the "to" merkletrie, -// skipping its contents if it is a directory. -func (d *doubleIter) nextTo() (err error) { - d.to.current, err = d.to.iter.Next() - return turnEOFIntoNil(err) -} - -// StepBoth makes d advance to the next noder in both merkletries, -// getting deeper into directories if that is the case. -func (d *doubleIter) stepBoth() (err error) { - if d.from.current, err = d.from.iter.Step(); turnEOFIntoNil(err) != nil { - return err - } - if d.to.current, err = d.to.iter.Step(); turnEOFIntoNil(err) != nil { - return err - } - return nil -} - -// Remaining returns if there are no more noders in the tree, if both -// have noders or if one of them doesn't. -func (d *doubleIter) remaining() remaining { - if d.from.current == nil && d.to.current == nil { - return noMoreNoders - } - - if d.from.current == nil && d.to.current != nil { - return onlyToRemains - } - - if d.from.current != nil && d.to.current == nil { - return onlyFromRemains - } - - return bothHaveNodes -} - -// Remaining values tells you whether both trees still have noders, or -// only one of them or none of them. -type remaining int - -const ( - noMoreNoders remaining = iota - onlyToRemains - onlyFromRemains - bothHaveNodes -) - -// Compare returns the comparison between the current elements in the -// merkletries. -func (d *doubleIter) compare() (s comparison, err error) { - s.sameHash = d.hashEqual(d.from.current, d.to.current) - - fromIsDir := d.from.current.IsDir() - toIsDir := d.to.current.IsDir() - - s.bothAreDirs = fromIsDir && toIsDir - s.bothAreFiles = !fromIsDir && !toIsDir - s.fileAndDir = !s.bothAreDirs && !s.bothAreFiles - - fromNumChildren, err := d.from.current.NumChildren() - if err != nil { - return comparison{}, fmt.Errorf("from: %s", err) - } - - toNumChildren, err := d.to.current.NumChildren() - if err != nil { - return comparison{}, fmt.Errorf("to: %s", err) - } - - s.fromIsEmptyDir = fromIsDir && fromNumChildren == 0 - s.toIsEmptyDir = toIsDir && toNumChildren == 0 - - return -} - -// Answers to a lot of questions you can ask about how to noders are -// equal or different. -type comparison struct { - // the following are only valid if both nodes have the same name - // (i.e. nameComparison == 0) - - // Do both nodes have the same hash? - sameHash bool - // Are both nodes files? - bothAreFiles bool - - // the following are only valid if any of the noders are dirs, - // this is, if !bothAreFiles - - // Is one a file and the other a dir? - fileAndDir bool - // Are both nodes dirs? - bothAreDirs bool - // Is the from node an empty dir? - fromIsEmptyDir bool - // Is the to Node an empty dir? - toIsEmptyDir bool -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/filesystem/node.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/filesystem/node.go deleted file mode 100644 index 9fb18ab5..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/filesystem/node.go +++ /dev/null @@ -1,250 +0,0 @@ -package filesystem - -import ( - "io" - "os" - "path" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - format "github.com/go-git/go-git/v6/plumbing/format/config" - "github.com/go-git/go-git/v6/utils/convert" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" - "github.com/go-git/go-git/v6/utils/sync" - - "github.com/go-git/go-billy/v6" -) - -var ignore = map[string]bool{ - ".git": true, -} - -type Options struct { - // AutoCRLF converts CRLF line endings in text files into LF line endings. - AutoCRLF bool -} - -// The node represents a file or a directory in a billy.Filesystem. It -// implements the interface noder.Noder of merkletrie package. -// -// This implementation implements a "standard" hash method being able to be -// compared with any other noder.Noder implementation inside of go-git. -type node struct { - fs billy.Filesystem - submodules map[string]plumbing.Hash - - options *Options - - path string - hash []byte - children []noder.Noder - isDir bool - mode os.FileMode - size int64 -} - -// NewRootNode returns the root node based on a given billy.Filesystem. -// -// In order to provide the submodule hash status, a map[string]plumbing.Hash -// should be provided where the key is the path of the submodule and the commit -// of the submodule HEAD -func NewRootNode( - fs billy.Filesystem, - submodules map[string]plumbing.Hash, -) noder.Noder { - return &node{fs: fs, submodules: submodules, isDir: true} -} - -func NewRootNodeWithOptions( - fs billy.Filesystem, - submodules map[string]plumbing.Hash, - options Options, -) noder.Noder { - return &node{ - fs: fs, - submodules: submodules, - options: &options, - isDir: true, - } -} - -// Hash the hash of a filesystem is the result of concatenating the computed -// plumbing.Hash of the file as a Blob and its plumbing.FileMode; that way the -// difftree algorithm will detect changes in the contents of files and also in -// their mode. -// -// Please note that the hash is calculated on first invocation of Hash(), -// meaning that it will not update when the underlying file changes -// between invocations. -// -// The hash of a directory is always a 24-bytes slice of zero values -func (n *node) Hash() []byte { - if n.hash == nil { - n.calculateHash() - } - return n.hash -} - -func (n *node) Name() string { - return path.Base(n.path) -} - -func (n *node) IsDir() bool { - return n.isDir -} - -func (n *node) Skip() bool { - return false -} - -func (n *node) Children() ([]noder.Noder, error) { - if err := n.calculateChildren(); err != nil { - return nil, err - } - - return n.children, nil -} - -func (n *node) NumChildren() (int, error) { - if err := n.calculateChildren(); err != nil { - return -1, err - } - - return len(n.children), nil -} - -func (n *node) calculateChildren() error { - if !n.IsDir() { - return nil - } - - if len(n.children) != 0 { - return nil - } - - files, err := n.fs.ReadDir(n.path) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - - for _, file := range files { - if _, ok := ignore[file.Name()]; ok { - continue - } - - if file.Mode()&os.ModeSocket != 0 { - continue - } - - c, err := n.newChildNode(file) - if err != nil { - return err - } - - n.children = append(n.children, c) - } - - return nil -} - -func (n *node) newChildNode(file os.FileInfo) (*node, error) { - path := path.Join(n.path, file.Name()) - - node := &node{ - fs: n.fs, - submodules: n.submodules, - options: n.options, - - path: path, - isDir: file.IsDir(), - size: file.Size(), - mode: file.Mode(), - } - - if _, isSubmodule := n.submodules[path]; isSubmodule { - node.isDir = false - } - - return node, nil -} - -func (n *node) calculateHash() { - if n.isDir { - n.hash = make([]byte, 24) - return - } - mode, err := filemode.NewFromOSFileMode(n.mode) - if err != nil { - n.hash = plumbing.ZeroHash.Bytes() - return - } - if submoduleHash, isSubmodule := n.submodules[n.path]; isSubmodule { - n.hash = append(submoduleHash.Bytes(), filemode.Submodule.Bytes()...) - return - } - var hash plumbing.Hash - if n.mode&os.ModeSymlink != 0 { - hash = n.doCalculateHashForSymlink() - } else { - hash = n.doCalculateHashForRegular() - } - n.hash = append(hash.Bytes(), mode.Bytes()...) -} - -func (n *node) doCalculateHashForRegular() plumbing.Hash { - f, err := n.fs.Open(n.path) - if err != nil { - return plumbing.ZeroHash - } - defer f.Close() - - h := plumbing.NewHasher(format.SHA1, plumbing.BlobObject, n.size) - var dst io.Writer = h - - if n.options != nil && n.options.AutoCRLF { - br := sync.GetBufioReader(f) - defer sync.PutBufioReader(br) - - stat, err := convert.GetStat(br) - if err != nil { - return plumbing.ZeroHash - } - - if _, err := f.Seek(0, io.SeekStart); err != nil { - return plumbing.ZeroHash - } - - if !stat.IsBinary() { - h.Reset(plumbing.BlobObject, n.size-int64(stat.CRLF)) - dst = convert.NewLFWriter(dst) - } - } - - if _, err := ioutil.CopyBufferPool(dst, f); err != nil { - return plumbing.ZeroHash - } - - return h.Sum() -} - -func (n *node) doCalculateHashForSymlink() plumbing.Hash { - target, err := n.fs.Readlink(n.path) - if err != nil { - return plumbing.ZeroHash - } - - h := plumbing.NewHasher(format.SHA1, plumbing.BlobObject, n.size) - if _, err := h.Write([]byte(target)); err != nil { - return plumbing.ZeroHash - } - - return h.Sum() -} - -func (n *node) String() string { - return n.path -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/index/node.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/index/node.go deleted file mode 100644 index c205eb6e..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/index/node.go +++ /dev/null @@ -1,103 +0,0 @@ -package index - -import ( - "path" - "strings" - - "github.com/go-git/go-git/v6/plumbing/format/index" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// The node represents a index.Entry or a directory inferred from the path -// of all entries. It implements the interface noder.Noder of merkletrie -// package. -// -// This implementation implements a "standard" hash method being able to be -// compared with any other noder.Noder implementation inside of go-git -type node struct { - path string - entry *index.Entry - children []noder.Noder - isDir bool - skip bool -} - -// NewRootNode returns the root node of a computed tree from a index.Index, -func NewRootNode(idx *index.Index) noder.Noder { - const rootNode = "" - - m := map[string]*node{rootNode: {isDir: true}} - - for _, e := range idx.Entries { - parts := strings.Split(e.Name, string("/")) - - var fullpath string - for _, part := range parts { - parent := fullpath - fullpath = path.Join(fullpath, part) - - // It's possible that the first occurrence of subdirectory is skipped. - // The parent node can be created with SkipWorktree set to true, but - // if any future children do not skip their subtree, the entire lineage - // of the tree needs to have this value set to false so that subdirectories - // are not ignored. - if parentNode, ok := m[fullpath]; ok { - if e.SkipWorktree == false { - parentNode.skip = false - } - continue - } - - n := &node{path: fullpath, skip: e.SkipWorktree} - if fullpath == e.Name { - n.entry = e - } else { - n.isDir = true - } - - m[n.path] = n - m[parent].children = append(m[parent].children, n) - } - } - - return m[rootNode] -} - -func (n *node) String() string { - return n.path -} - -func (n *node) Skip() bool { - return n.skip -} - -// Hash the hash of a filesystem is a 24-byte slice, is the result of -// concatenating the computed plumbing.Hash of the file as a Blob and its -// plumbing.FileMode; that way the difftree algorithm will detect changes in the -// contents of files and also in their mode. -// -// If the node is computed and not based on a index.Entry the hash is equals -// to a 24-bytes slices of zero values. -func (n *node) Hash() []byte { - if n.entry == nil { - return make([]byte, 24) - } - - return append(n.entry.Hash.Bytes(), n.entry.Mode.Bytes()...) -} - -func (n *node) Name() string { - return path.Base(n.path) -} - -func (n *node) IsDir() bool { - return n.isDir -} - -func (n *node) Children() ([]noder.Noder, error) { - return n.children, nil -} - -func (n *node) NumChildren() (int, error) { - return len(n.children), nil -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/internal/frame/frame.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/internal/frame/frame.go deleted file mode 100644 index cb4f5742..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/internal/frame/frame.go +++ /dev/null @@ -1,92 +0,0 @@ -package frame - -import ( - "bytes" - "fmt" - "sort" - "strings" - - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// A Frame is a collection of siblings in a trie, sorted alphabetically -// by name. -type Frame struct { - // siblings, sorted in reverse alphabetical order by name - stack []noder.Noder -} - -type byName []noder.Noder - -func (a byName) Len() int { return len(a) } -func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byName) Less(i, j int) bool { - return strings.Compare(a[i].Name(), a[j].Name()) < 0 -} - -// New returns a frame with the children of the provided node. -func New(n noder.Noder) (*Frame, error) { - children, err := n.Children() - if err != nil { - return nil, err - } - - sort.Sort(sort.Reverse(byName(children))) - return &Frame{ - stack: children, - }, nil -} - -// String returns the quoted names of the noders in the frame sorted in -// alphabetical order by name, surrounded by square brackets and -// separated by comas. -// -// Examples: -// -// [] -// ["a", "b"] -func (f *Frame) String() string { - var buf bytes.Buffer - _ = buf.WriteByte('[') - - sep := "" - for i := f.Len() - 1; i >= 0; i-- { - _, _ = buf.WriteString(sep) - sep = ", " - _, _ = buf.WriteString(fmt.Sprintf("%q", f.stack[i].Name())) - } - - _ = buf.WriteByte(']') - - return buf.String() -} - -// First returns, but dont extract, the noder with the alphabetically -// smaller name in the frame and true if the frame was not empty. -// Otherwise it returns nil and false. -func (f *Frame) First() (noder.Noder, bool) { - if f.Len() == 0 { - return nil, false - } - - top := f.Len() - 1 - - return f.stack[top], true -} - -// Drop extracts the noder with the alphabetically smaller name in the -// frame or does nothing if the frame was empty. -func (f *Frame) Drop() { - if f.Len() == 0 { - return - } - - top := f.Len() - 1 - f.stack[top] = nil - f.stack = f.stack[:top] -} - -// Len returns the number of noders in the frame. -func (f *Frame) Len() int { - return len(f.stack) -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/iter.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/iter.go deleted file mode 100644 index e87663ce..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/iter.go +++ /dev/null @@ -1,215 +0,0 @@ -package merkletrie - -import ( - "fmt" - "io" - - "github.com/go-git/go-git/v6/utils/merkletrie/internal/frame" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" -) - -// Iter is an iterator for merkletries (only the trie part of the -// merkletrie is relevant here, it does not use the Hasher interface). -// -// The iteration is performed in depth-first pre-order. Entries at each -// depth are traversed in (case-sensitive) alphabetical order. -// -// This is the kind of traversal you will expect when listing ordinary -// files and directories recursively, for example: -// -// Trie Traversal order -// ---- --------------- -// . -// / | \ c -// / | \ d/ -// d c z ===> d/a -// / \ d/b -// b a z -// -// This iterator is somewhat especial as you can chose to skip whole -// "directories" when iterating: -// -// - The Step method will iterate normally. -// -// - the Next method will not descend deeper into the tree. -// -// For example, if the iterator is at `d/`, the Step method will return -// `d/a` while the Next would have returned `z` instead (skipping `d/` -// and its descendants). The name of the these two methods are based on -// the well known "next" and "step" operations, quite common in -// debuggers, like gdb. -// -// The paths returned by the iterator will be relative, if the iterator -// was created from a single node, or absolute, if the iterator was -// created from the path to the node (the path will be prefixed to all -// returned paths). -type Iter struct { - // Tells if the iteration has started. - hasStarted bool - // The top of this stack has the current node and its siblings. The - // rest of the stack keeps the ancestors of the current node and - // their corresponding siblings. The current element is always the - // top element of the top frame. - // - // When "step"ping into a node, its children are pushed as a new - // frame. - // - // When "next"ing pass a node, the current element is dropped by - // popping the top frame. - frameStack []*frame.Frame - // The base path used to turn the relative paths used internally by - // the iterator into absolute paths used by external applications. - // For relative iterator this will be nil. - base noder.Path -} - -// NewIter returns a new relative iterator using the provider noder as -// its unnamed root. When iterating, all returned paths will be -// relative to node. -func NewIter(n noder.Noder) (*Iter, error) { - return newIter(n, nil) -} - -// NewIterFromPath returns a new absolute iterator from the noder at the -// end of the path p. When iterating, all returned paths will be -// absolute, using the root of the path p as their root. -func NewIterFromPath(p noder.Path) (*Iter, error) { - return newIter(p, p) // Path implements Noder -} - -func newIter(root noder.Noder, base noder.Path) (*Iter, error) { - ret := &Iter{ - base: base, - } - - if root == nil { - return ret, nil - } - - frame, err := frame.New(root) - if err != nil { - return nil, err - } - ret.push(frame) - - return ret, nil -} - -func (iter *Iter) top() (*frame.Frame, bool) { - if len(iter.frameStack) == 0 { - return nil, false - } - top := len(iter.frameStack) - 1 - - return iter.frameStack[top], true -} - -func (iter *Iter) push(f *frame.Frame) { - iter.frameStack = append(iter.frameStack, f) -} - -const ( - doDescend = true - dontDescend = false -) - -// Next returns the path of the next node without descending deeper into -// the trie and nil. If there are no more entries in the trie it -// returns nil and io.EOF. In case of error, it will return nil and the -// error. -func (iter *Iter) Next() (noder.Path, error) { - return iter.advance(dontDescend) -} - -// Step returns the path to the next node in the trie, descending deeper -// into it if needed, and nil. If there are no more nodes in the trie, -// it returns nil and io.EOF. In case of error, it will return nil and -// the error. -func (iter *Iter) Step() (noder.Path, error) { - return iter.advance(doDescend) -} - -// Advances the iterator in the desired direction: descend or -// dontDescend. -// -// Returns the new current element and a nil error on success. If there -// are no more elements in the trie below the base, it returns nil, and -// io.EOF. Returns nil and an error in case of errors. -func (iter *Iter) advance(wantDescend bool) (noder.Path, error) { - current, err := iter.current() - if err != nil { - return nil, err - } - - // The first time we just return the current node. - if !iter.hasStarted { - iter.hasStarted = true - return current, nil - } - - // Advances means getting a next current node, either its first child or - // its next sibling, depending if we must descend or not. - numChildren, err := current.NumChildren() - if err != nil { - return nil, err - } - - mustDescend := numChildren != 0 && wantDescend - if mustDescend { - // descend: add a new frame with the current's children. - frame, err := frame.New(current) - if err != nil { - return nil, err - } - iter.push(frame) - } else { - // don't descend: just drop the current node - iter.drop() - } - - return iter.current() -} - -// Returns the path to the current node, adding the base if there was -// one, and a nil error. If there were no noders left, it returns nil -// and io.EOF. If an error occurred, it returns nil and the error. -func (iter *Iter) current() (noder.Path, error) { - if topFrame, ok := iter.top(); !ok { - return nil, io.EOF - } else if _, ok := topFrame.First(); !ok { - return nil, io.EOF - } - - ret := make(noder.Path, 0, len(iter.base)+len(iter.frameStack)) - - // concat the base... - ret = append(ret, iter.base...) - // ... and the current node and all its ancestors - for i, f := range iter.frameStack { - t, ok := f.First() - if !ok { - panic(fmt.Sprintf("frame %d is empty", i)) - } - ret = append(ret, t) - } - - return ret, nil -} - -// removes the current node if any, and all the frames that become empty as a -// consequence of this action. -func (iter *Iter) drop() { - frame, ok := iter.top() - if !ok { - return - } - - frame.Drop() - // if the frame is empty, remove it and its parent, recursively - if frame.Len() == 0 { - top := len(iter.frameStack) - 1 - iter.frameStack[top] = nil - iter.frameStack = iter.frameStack[:top] - iter.drop() - } -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/noder.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/noder.go deleted file mode 100644 index 6d22b8c1..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/noder.go +++ /dev/null @@ -1,60 +0,0 @@ -// Package noder provide an interface for defining nodes in a -// merkletrie, their hashes and their paths (a noders and its -// ancestors). -// -// The hasher interface is easy to implement naively by elements that -// already have a hash, like git blobs and trees. More sophisticated -// implementations can implement the Equal function in exotic ways -// though: for instance, comparing the modification time of directories -// in a filesystem. -package noder - -import "fmt" - -// Hasher interface is implemented by types that can tell you -// their hash. -type Hasher interface { - Hash() []byte -} - -// Equal functions take two hashers and return if they are equal. -// -// These functions are expected to be faster than reflect.Equal or -// reflect.DeepEqual because they can compare just the hash of the -// objects, instead of their contents, so they are expected to be O(1). -type Equal func(a, b Hasher) bool - -// The Noder interface is implemented by the elements of a Merkle Trie. -// -// There are two types of elements in a Merkle Trie: -// -// - file-like nodes: they cannot have children. -// -// - directory-like nodes: they can have 0 or more children and their -// hash is calculated by combining their children hashes. -type Noder interface { - Hasher - fmt.Stringer // for testing purposes - // Name returns the name of an element (relative, not its full - // path). - Name() string - // IsDir returns true if the element is a directory-like node or - // false if it is a file-like node. - IsDir() bool - // Children returns the children of the element. Note that empty - // directory-like noders and file-like noders will both return - // NoChildren. - Children() ([]Noder, error) - // NumChildren returns the number of children this element has. - // - // This method is an optimization: the number of children is easily - // calculated as the length of the value returned by the Children - // method (above); yet, some implementations will be able to - // implement NumChildren in O(1) while Children is usually more - // complex. - NumChildren() (int, error) - Skip() bool -} - -// NoChildren represents the children of a noder without children. -var NoChildren = []Noder{} diff --git a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/path.go b/vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/path.go deleted file mode 100644 index 6c1d3633..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/merkletrie/noder/path.go +++ /dev/null @@ -1,98 +0,0 @@ -package noder - -import ( - "bytes" - "strings" -) - -// Path values represent a noder and its ancestors. The root goes first -// and the actual final noder the path is referring to will be the last. -// -// A path implements the Noder interface, redirecting all the interface -// calls to its final noder. -// -// Paths build from an empty Noder slice are not valid paths and should -// not be used. -type Path []Noder - -func (p Path) Skip() bool { - if len(p) > 0 { - return p.Last().Skip() - } - - return false -} - -// String returns the full path of the final noder as a string, using -// "/" as the separator. -func (p Path) String() string { - var buf bytes.Buffer - sep := "" - for _, e := range p { - _, _ = buf.WriteString(sep) - sep = "/" - _, _ = buf.WriteString(e.Name()) - } - - return buf.String() -} - -// Last returns the final noder in the path. -func (p Path) Last() Noder { - return p[len(p)-1] -} - -// Hash returns the hash of the final noder of the path. -func (p Path) Hash() []byte { - return p.Last().Hash() -} - -// Name returns the name of the final noder of the path. -func (p Path) Name() string { - return p.Last().Name() -} - -// IsDir returns if the final noder of the path is a directory-like -// noder. -func (p Path) IsDir() bool { - return p.Last().IsDir() -} - -// Children returns the children of the final noder in the path. -func (p Path) Children() ([]Noder, error) { - return p.Last().Children() -} - -// NumChildren returns the number of children the final noder of the -// path has. -func (p Path) NumChildren() (int, error) { - return p.Last().NumChildren() -} - -// Compare returns -1, 0 or 1 if the path p is smaller, equal or bigger -// than other, in "directory order"; for example: -// -// "a" < "b" -// "a/b/c/d/z" < "b" -// "a/b/a" > "a/b" -func (p Path) Compare(other Path) int { - i := 0 - for { - switch { - case len(other) == len(p) && i == len(p): - return 0 - case i == len(other): - return 1 - case i == len(p): - return -1 - default: - // We do *not* normalize Unicode here. CGit doesn't. - // https://github.com/src-d/go-git/issues/1057 - cmp := strings.Compare(p[i].Name(), other[i].Name()) - if cmp != 0 { - return cmp - } - } - i++ - } -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/sync/bufio.go b/vendor/github.com/go-git/go-git/v6/utils/sync/bufio.go deleted file mode 100644 index 42f60f7e..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/sync/bufio.go +++ /dev/null @@ -1,29 +0,0 @@ -package sync - -import ( - "bufio" - "io" - "sync" -) - -var bufioReader = sync.Pool{ - New: func() interface{} { - return bufio.NewReader(nil) - }, -} - -// GetBufioReader returns a *bufio.Reader that is managed by a sync.Pool. -// Returns a bufio.Reader that is reset with reader and ready for use. -// -// After use, the *bufio.Reader should be put back into the sync.Pool -// by calling PutBufioReader. -func GetBufioReader(reader io.Reader) *bufio.Reader { - r := bufioReader.Get().(*bufio.Reader) - r.Reset(reader) - return r -} - -// PutBufioReader puts reader back into its sync.Pool. -func PutBufioReader(reader *bufio.Reader) { - bufioReader.Put(reader) -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/sync/bytes.go b/vendor/github.com/go-git/go-git/v6/utils/sync/bytes.go deleted file mode 100644 index 37aa8fe3..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/sync/bytes.go +++ /dev/null @@ -1,70 +0,0 @@ -package sync - -import ( - "bytes" - "sync" -) - -var ( - size = 32 * 1024 - - byteSlice = sync.Pool{ - New: func() interface{} { - b := make([]byte, size) - return &b - }, - } - bytesBuffer = sync.Pool{ - New: func() interface{} { - return bytes.NewBuffer(nil) - }, - } -) - -// GetByteSlice returns a *[]byte that is managed by a sync.Pool. -// The initial slice length will be 32768 (32kb). -// -// After use, the *[]byte should be put back into the sync.Pool -// by calling PutByteSlice. -func GetByteSlice() *[]byte { - buf := byteSlice.Get().(*[]byte) - b := *buf - if len(b) < size { - b = b[:cap(b)] - } - - // zero out the array contents. - for i := 0; i < len(b); i++ { - b[i] = 0 - } - - return &b -} - -// PutByteSlice puts buf back into its sync.Pool. -func PutByteSlice(buf *[]byte) { - if buf == nil { - return - } - - byteSlice.Put(buf) -} - -// GetBytesBuffer returns a *bytes.Buffer that is managed by a sync.Pool. -// Returns a buffer that is reset and ready for use. -// -// After use, the *bytes.Buffer should be put back into the sync.Pool -// by calling PutBytesBuffer. -func GetBytesBuffer() *bytes.Buffer { - buf := bytesBuffer.Get().(*bytes.Buffer) - buf.Reset() - return buf -} - -// PutBytesBuffer puts buf back into its sync.Pool. -func PutBytesBuffer(buf *bytes.Buffer) { - if buf == nil { - return - } - bytesBuffer.Put(buf) -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/sync/zlib.go b/vendor/github.com/go-git/go-git/v6/utils/sync/zlib.go deleted file mode 100644 index 28e1b8a5..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/sync/zlib.go +++ /dev/null @@ -1,87 +0,0 @@ -package sync - -import ( - "bytes" - "compress/zlib" - "io" - "sync" -) - -var ( - zlibInitBytes = []byte{0x78, 0x9c, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01} - zlibReader = sync.Pool{ - New: func() interface{} { - return NewZlibReader(nil) - }, - } - zlibWriter = sync.Pool{ - New: func() interface{} { - return zlib.NewWriter(nil) - }, - } -) - -type zlibReadCloser interface { - io.ReadCloser - zlib.Resetter -} - -func NewZlibReader(dict *[]byte) ZLibReader { - r, _ := zlib.NewReader(bytes.NewReader(zlibInitBytes)) - return ZLibReader{ - Reader: r.(zlibReadCloser), - dict: dict, - } -} - -type ZLibReader struct { - dict *[]byte - Reader zlibReadCloser -} - -func (z ZLibReader) Reset(r io.Reader) error { - var dict []byte - if z.dict != nil { - dict = *z.dict - } - return z.Reader.Reset(r, dict) -} - -// GetZlibReader returns a ZLibReader that is managed by a sync.Pool. -// Returns a ZLibReader that is reset using a dictionary that is -// also managed by a sync.Pool. -// -// After use, the ZLibReader should be put back into the sync.Pool -// by calling PutZlibReader. -func GetZlibReader(r io.Reader) (ZLibReader, error) { - z := zlibReader.Get().(ZLibReader) - z.dict = GetByteSlice() - - err := z.Reader.Reset(r, *z.dict) - - return z, err -} - -// PutZlibReader puts z back into its sync.Pool, first closing the reader. -// The Byte slice dictionary is also put back into its sync.Pool. -func PutZlibReader(z ZLibReader) { - z.Reader.Close() - PutByteSlice(z.dict) - zlibReader.Put(z) -} - -// GetZlibWriter returns a *zlib.Writer that is managed by a sync.Pool. -// Returns a writer that is reset with w and ready for use. -// -// After use, the *zlib.Writer should be put back into the sync.Pool -// by calling PutZlibWriter. -func GetZlibWriter(w io.Writer) *zlib.Writer { - z := zlibWriter.Get().(*zlib.Writer) - z.Reset(w) - return z -} - -// PutZlibWriter puts w back into its sync.Pool. -func PutZlibWriter(w *zlib.Writer) { - zlibWriter.Put(w) -} diff --git a/vendor/github.com/go-git/go-git/v6/utils/trace/trace.go b/vendor/github.com/go-git/go-git/v6/utils/trace/trace.go deleted file mode 100644 index 93a1c7f3..00000000 --- a/vendor/github.com/go-git/go-git/v6/utils/trace/trace.go +++ /dev/null @@ -1,75 +0,0 @@ -package trace - -import ( - "fmt" - "log" - "os" - "sync/atomic" -) - -var ( - // logger is the logger to use for tracing. - logger = newLogger() - - // current is the targets that are enabled for tracing. - current atomic.Int32 -) - -func newLogger() *log.Logger { - return log.New(os.Stderr, "", log.Ltime|log.Lmicroseconds|log.Lshortfile) -} - -// Target is a tracing target. -type Target int32 - -const ( - // General traces general operations. - General Target = 1 << iota - - // Packet traces git packets. - Packet - - // SSH traces SSH handshake operations. This does not have - // a direct translation to an upstream trace option. - SSH - - // Performance traces performance of go-git components. - Performance - - // HTTP traces HTTP operations and requests. - HTTP -) - -// SetTarget sets the tracing targets. -func SetTarget(target Target) { - current.Store(int32(target)) -} - -// SetLogger sets the logger to use for tracing. -func SetLogger(l *log.Logger) { - logger = l -} - -// Print prints the given message only if the target is enabled. -func (t Target) Print(args ...interface{}) { - if t.Enabled() { - logger.Output(2, fmt.Sprint(args...)) // nolint: errcheck - } -} - -// Printf prints the given message only if the target is enabled. -func (t Target) Printf(format string, args ...interface{}) { - if t.Enabled() { - logger.Output(2, fmt.Sprintf(format, args...)) // nolint: errcheck - } -} - -// Enabled returns true if the target is enabled. -func (t Target) Enabled() bool { - return int32(t)¤t.Load() != 0 -} - -// GetTarget returns the current tracing target. -func GetTarget() Target { - return Target(current.Load()) -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree.go b/vendor/github.com/go-git/go-git/v6/worktree.go deleted file mode 100644 index 64e47388..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree.go +++ /dev/null @@ -1,1312 +0,0 @@ -package git - -import ( - "context" - "errors" - "fmt" - "io" - "net/url" - "os" - "path" - "path/filepath" - "runtime" - "strings" - "time" - - "github.com/go-git/go-billy/v6" - "github.com/go-git/go-billy/v6/util" - "github.com/go-git/go-git/v6/config" - giturl "github.com/go-git/go-git/v6/internal/url" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/plumbing/format/gitignore" - "github.com/go-git/go-git/v6/plumbing/format/index" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/plumbing/storer" - "github.com/go-git/go-git/v6/utils/convert" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/merkletrie" - "github.com/go-git/go-git/v6/utils/sync" - "github.com/go-git/go-git/v6/utils/trace" -) - -var ( - ErrWorktreeNotClean = errors.New("worktree is not clean") - ErrSubmoduleNotFound = errors.New("submodule not found") - ErrUnstagedChanges = errors.New("worktree contains unstaged changes") - ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink") - ErrNonFastForwardUpdate = errors.New("non-fast-forward update") - ErrRestoreWorktreeOnlyNotSupported = errors.New("worktree only is not supported") - ErrSparseResetDirectoryNotFound = errors.New("sparse-reset directory not found on commit") -) - -// Worktree represents a git worktree. -type Worktree struct { - // Filesystem underlying filesystem. - Filesystem billy.Filesystem - // External excludes not found in the repository .gitignore - Excludes []gitignore.Pattern - - r *Repository -} - -// Pull incorporates changes from a remote repository into the current branch. -// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are -// no changes to be fetched, or an error. -// -// Pull only supports merges where the can be resolved as a fast-forward. -func (w *Worktree) Pull(o *PullOptions) error { - return w.PullContext(context.Background(), o) -} - -// PullContext incorporates changes from a remote repository into the current -// branch. Returns nil if the operation is successful, NoErrAlreadyUpToDate if -// there are no changes to be fetched, or an error. -// -// Pull only supports merges where the can be resolved as a fast-forward. -// -// The provided Context must be non-nil. If the context expires before the -// operation is complete, an error is returned. The context only affects the -// transport operations. -func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error { - if err := o.Validate(); err != nil { - return err - } - - remote, err := w.r.Remote(o.RemoteName) - if err != nil { - return err - } - - fetchHead, err := remote.fetch(ctx, &FetchOptions{ - RemoteName: o.RemoteName, - RemoteURL: o.RemoteURL, - Depth: o.Depth, - Auth: o.Auth, - Progress: o.Progress, - Force: o.Force, - InsecureSkipTLS: o.InsecureSkipTLS, - CABundle: o.CABundle, - ProxyOptions: o.ProxyOptions, - }) - - updated := true - if err == NoErrAlreadyUpToDate { - updated = false - } else if err != nil { - return err - } - - ref, err := storer.ResolveReference(fetchHead, o.ReferenceName) - if err != nil { - return err - } - - head, err := w.r.Head() - if err == nil { - // if we don't have a shallows list, just ignore it - shallowList, _ := w.r.Storer.Shallow() - - var earliestShallow *plumbing.Hash - if len(shallowList) > 0 { - earliestShallow = &shallowList[0] - } - - headAheadOfRef, err := isFastForward(w.r.Storer, ref.Hash(), head.Hash(), earliestShallow) - if err != nil { - return err - } - - if !updated && headAheadOfRef { - return NoErrAlreadyUpToDate - } - - ff, err := isFastForward(w.r.Storer, head.Hash(), ref.Hash(), earliestShallow) - if err != nil { - return err - } - - if !ff { - return ErrNonFastForwardUpdate - } - } - - if err != nil && err != plumbing.ErrReferenceNotFound { - return err - } - - if err := w.updateHEAD(ref.Hash()); err != nil { - return err - } - - if err := w.Reset(&ResetOptions{ - Mode: MergeReset, - Commit: ref.Hash(), - }); err != nil { - return err - } - - if o.RecurseSubmodules != NoRecurseSubmodules { - return w.updateSubmodules(ctx, &SubmoduleUpdateOptions{ - RecurseSubmodules: o.RecurseSubmodules, - Auth: o.Auth, - }) - } - - return nil -} - -func (w *Worktree) updateSubmodules(ctx context.Context, o *SubmoduleUpdateOptions) error { - s, err := w.Submodules() - if err != nil { - return err - } - o.Init = true - return s.UpdateContext(ctx, o) -} - -// Checkout switch branches or restore working tree files. -func (w *Worktree) Checkout(opts *CheckoutOptions) error { - if err := opts.Validate(); err != nil { - return err - } - - if opts.Create { - if err := w.createBranch(opts); err != nil { - return err - } - } - - c, err := w.getCommitFromCheckoutOptions(opts) - if err != nil { - return err - } - - ro := &ResetOptions{ - Commit: c, - Mode: MergeReset, - SparseDirs: opts.SparseCheckoutDirectories, - } - if opts.Force { - ro.Mode = HardReset - } else if opts.Keep { - ro.Mode = SoftReset - } - - if !opts.Hash.IsZero() && !opts.Create { - err = w.setHEADToCommit(opts.Hash) - } else { - err = w.setHEADToBranch(opts.Branch, c) - } - - if err != nil { - return err - } - - return w.Reset(ro) -} - -func (w *Worktree) createBranch(opts *CheckoutOptions) error { - if err := opts.Branch.Validate(); err != nil { - return err - } - - _, err := w.r.Storer.Reference(opts.Branch) - if err == nil { - return fmt.Errorf("a branch named %q already exists", opts.Branch) - } - - if err != plumbing.ErrReferenceNotFound { - return err - } - - if opts.Hash.IsZero() { - ref, err := w.r.Head() - if err != nil { - return err - } - - opts.Hash = ref.Hash() - } - - return w.r.Storer.SetReference( - plumbing.NewHashReference(opts.Branch, opts.Hash), - ) -} - -func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing.Hash, error) { - hash := opts.Hash - if hash.IsZero() { - b, err := w.r.Reference(opts.Branch, true) - if err != nil { - return plumbing.ZeroHash, err - } - - hash = b.Hash() - } - - o, err := w.r.Object(plumbing.AnyObject, hash) - if err != nil { - return plumbing.ZeroHash, err - } - - switch o := o.(type) { - case *object.Tag: - if o.TargetType != plumbing.CommitObject { - return plumbing.ZeroHash, fmt.Errorf("%w: tag target %q", object.ErrUnsupportedObject, o.TargetType) - } - - return o.Target, nil - case *object.Commit: - return o.Hash, nil - } - - return plumbing.ZeroHash, fmt.Errorf("%w: %q", object.ErrUnsupportedObject, o.Type()) -} - -func (w *Worktree) setHEADToCommit(commit plumbing.Hash) error { - head := plumbing.NewHashReference(plumbing.HEAD, commit) - return w.r.Storer.SetReference(head) -} - -func (w *Worktree) setHEADToBranch(branch plumbing.ReferenceName, commit plumbing.Hash) error { - target, err := w.r.Storer.Reference(branch) - if err != nil { - return err - } - - var head *plumbing.Reference - if target.Name().IsBranch() { - head = plumbing.NewSymbolicReference(plumbing.HEAD, target.Name()) - } else { - head = plumbing.NewHashReference(plumbing.HEAD, commit) - } - - return w.r.Storer.SetReference(head) -} - -// Reset the worktree to a specified state. -func (w *Worktree) Reset(opts *ResetOptions) error { - start := time.Now() - defer func() { - trace.Performance.Printf("performance: %.9f s: reset_worktree", time.Since(start).Seconds()) - }() - - if err := opts.Validate(w.r); err != nil { - return err - } - - if opts.Mode == MergeReset { - unstaged, err := w.containsUnstagedChanges() - if err != nil { - return err - } - - if unstaged { - return ErrUnstagedChanges - } - } - - if opts.Mode == SoftReset { - return w.setHEADCommit(opts.Commit) - } - - t, err := w.r.getTreeFromCommitHash(opts.Commit) - if err != nil { - return err - } - - if len(opts.SparseDirs) > 0 && !opts.SkipSparseDirValidation { - if !treeContainsDirs(t, opts.SparseDirs) { - return ErrSparseResetDirectoryNotFound - } - } - - if err := w.setHEADCommit(opts.Commit); err != nil { - return err - } - - var removedFiles []string - if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset { - if removedFiles, err = w.resetIndex(t, opts.SparseDirs, opts.Files); err != nil { - return err - } - } - - if opts.Mode == MergeReset && len(removedFiles) > 0 { - if err := w.resetWorktree(t, removedFiles); err != nil { - return err - } - } - - if opts.Mode == HardReset { - if err := w.resetWorktree(t, opts.Files); err != nil { - return err - } - } - - return nil -} - -// treeContainsDirs checks if the given tree contains all the directories. -// if dirs is empty, it returns false. -func treeContainsDirs(tree *object.Tree, dirs []string) bool { - if len(dirs) == 0 { - return false - } - - for _, dir := range dirs { - entry, err := tree.FindEntry(dir) - if err != nil { - return false - } - if entry.Mode != filemode.Dir { - return false - } - } - - return true -} - -// Restore restores specified files in the working tree or stage with contents from -// a restore source. If a path is tracked but does not exist in the restore, -// source, it will be removed to match the source. -// -// If Staged and Worktree are true, then the restore source will be the index. -// If only Staged is true, then the restore source will be HEAD. -// If only Worktree is true or neither Staged nor Worktree are true, will -// result in ErrRestoreWorktreeOnlyNotSupported because restoring the working -// tree while leaving the stage untouched is not currently supported. -// -// Restore with no files specified will return ErrNoRestorePaths. -func (w *Worktree) Restore(o *RestoreOptions) error { - if err := o.Validate(); err != nil { - return err - } - - if o.Staged { - opts := &ResetOptions{ - Files: o.Files, - } - - if o.Worktree { - // If we are doing both Worktree and Staging then it is a hard reset - opts.Mode = HardReset - } else { - // If we are doing just staging then it is a mixed reset - opts.Mode = MixedReset - } - - return w.Reset(opts) - } - - return ErrRestoreWorktreeOnlyNotSupported -} - -func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) ([]string, error) { - idx, err := w.r.Storer.Index() - if err != nil { - return nil, err - } - - b := newIndexBuilder(idx) - - changes, err := w.diffTreeWithStaging(t, true) - if err != nil { - return nil, err - } - - var removedFiles []string - for _, ch := range changes { - a, err := ch.Action() - if err != nil { - return nil, err - } - - var name string - var e *object.TreeEntry - - switch a { - case merkletrie.Modify, merkletrie.Insert: - name = ch.To.String() - e, err = t.FindEntry(name) - if err != nil { - return nil, err - } - case merkletrie.Delete: - name = ch.From.String() - } - - if len(files) > 0 { - contains := inFiles(files, name) - if !contains { - continue - } - } - - b.Remove(name) - removedFiles = append(removedFiles, name) - if e == nil { - continue - } - - b.Add(&index.Entry{ - Name: name, - Hash: e.Hash, - Mode: e.Mode, - }) - - } - - b.Write(idx) - - if len(dirs) > 0 { - idx.SkipUnless(dirs) - } - - return removedFiles, w.r.Storer.SetIndex(idx) -} - -func inFiles(files []string, v string) bool { - v = filepath.Clean(v) - for _, s := range files { - if filepath.Clean(s) == v { - return true - } - } - - return false -} - -func (w *Worktree) resetWorktree(t *object.Tree, files []string) error { - changes, err := w.diffStagingWithWorktree(true, false) - if err != nil { - return err - } - - idx, err := w.r.Storer.Index() - if err != nil { - return err - } - b := newIndexBuilder(idx) - - for _, ch := range changes { - if err := w.validChange(ch); err != nil { - return err - } - - if len(files) > 0 { - file := "" - if ch.From != nil { - file = ch.From.String() - } else if ch.To != nil { - file = ch.To.String() - } - - if file == "" { - continue - } - - contains := inFiles(files, file) - if !contains { - continue - } - } - - if err := w.checkoutChange(ch, t, b); err != nil { - return err - } - } - - b.Write(idx) - return w.r.Storer.SetIndex(idx) -} - -// worktreeDeny is a list of paths that are not allowed -// to be used when resetting the worktree. -var worktreeDeny = map[string]struct{}{ - // .git - GitDirName: {}, - - // For other historical reasons, file names that do not conform to the 8.3 - // format (up to eight characters for the basename, three for the file - // extension, certain characters not allowed such as `+`, etc) are associated - // with a so-called "short name", at least on the `C:` drive by default. - // Which means that `git~1/` is a valid way to refer to `.git/`. - "git~1": {}, -} - -// validPath checks whether paths are valid. -// The rules around invalid paths could differ from upstream based on how -// filesystems are managed within go-git, but they are largely the same. -// -// For upstream rules: -// https://github.com/git/git/blob/564d0252ca632e0264ed670534a51d18a689ef5d/read-cache.c#L946 -// https://github.com/git/git/blob/564d0252ca632e0264ed670534a51d18a689ef5d/path.c#L1383 -func validPath(paths ...string) error { - for _, p := range paths { - parts := strings.FieldsFunc(p, func(r rune) bool { return (r == '\\' || r == '/') }) - if len(parts) == 0 { - return fmt.Errorf("invalid path: %q", p) - } - - if _, denied := worktreeDeny[strings.ToLower(parts[0])]; denied { - return fmt.Errorf("invalid path prefix: %q", p) - } - - if runtime.GOOS == "windows" { - // Volume names are not supported, in both formats: \\ and :. - if vol := filepath.VolumeName(p); vol != "" { - return fmt.Errorf("invalid path: %q", p) - } - - if !windowsValidPath(parts[0]) { - return fmt.Errorf("invalid path: %q", p) - } - } - - for _, part := range parts { - if part == ".." { - return fmt.Errorf("invalid path %q: cannot use '..'", p) - } - } - } - return nil -} - -// windowsPathReplacer defines the chars that need to be replaced -// as part of windowsValidPath. -var windowsPathReplacer *strings.Replacer - -func init() { - windowsPathReplacer = strings.NewReplacer(" ", "", ".", "") -} - -func windowsValidPath(part string) bool { - if len(part) > 3 && strings.EqualFold(part[:4], GitDirName) { - // For historical reasons, file names that end in spaces or periods are - // automatically trimmed. Therefore, `.git . . ./` is a valid way to refer - // to `.git/`. - if windowsPathReplacer.Replace(part[4:]) == "" { - return false - } - - // For yet other historical reasons, NTFS supports so-called "Alternate Data - // Streams", i.e. metadata associated with a given file, referred to via - // `::`. There exists a default stream - // type for directories, allowing `.git/` to be accessed via - // `.git::$INDEX_ALLOCATION/`. - // - // For performance reasons, _all_ Alternate Data Streams of `.git/` are - // forbidden, not just `::$INDEX_ALLOCATION`. - if len(part) > 4 && part[4:5] == ":" { - return false - } - } - return true -} - -func (w *Worktree) validChange(ch merkletrie.Change) error { - action, err := ch.Action() - if err != nil { - return nil - } - - switch action { - case merkletrie.Delete: - return validPath(ch.From.String()) - case merkletrie.Insert: - return validPath(ch.To.String()) - case merkletrie.Modify: - return validPath(ch.From.String(), ch.To.String()) - } - - return nil -} - -func (w *Worktree) checkoutChange(ch merkletrie.Change, t *object.Tree, idx *indexBuilder) error { - a, err := ch.Action() - if err != nil { - return err - } - - var e *object.TreeEntry - var name string - var isSubmodule bool - - switch a { - case merkletrie.Modify, merkletrie.Insert: - name = ch.To.String() - e, err = t.FindEntry(name) - if err != nil { - return err - } - - isSubmodule = e.Mode == filemode.Submodule - case merkletrie.Delete: - return rmFileAndDirsIfEmpty(w.Filesystem, ch.From.String()) - } - - if isSubmodule { - return w.checkoutChangeSubmodule(name, a, e, idx) - } - - return w.checkoutChangeRegularFile(name, a, t, e, idx) -} - -func (w *Worktree) containsUnstagedChanges() (bool, error) { - ch, err := w.diffStagingWithWorktree(false, true) - if err != nil { - return false, err - } - - for _, c := range ch { - a, err := c.Action() - if err != nil { - return false, err - } - - if a == merkletrie.Insert { - continue - } - - return true, nil - } - - return false, nil -} - -func (w *Worktree) setHEADCommit(commit plumbing.Hash) error { - head, err := w.r.Reference(plumbing.HEAD, false) - if err != nil { - return err - } - - if head.Type() == plumbing.HashReference { - head = plumbing.NewHashReference(plumbing.HEAD, commit) - return w.r.Storer.SetReference(head) - } - - branch, err := w.r.Reference(head.Target(), false) - if err != nil { - return err - } - - if !branch.Name().IsBranch() { - return fmt.Errorf("invalid HEAD target should be a branch, found %s", branch.Type()) - } - - branch = plumbing.NewHashReference(branch.Name(), commit) - return w.r.Storer.SetReference(branch) -} - -func (w *Worktree) checkoutChangeSubmodule(name string, - a merkletrie.Action, - e *object.TreeEntry, - idx *indexBuilder, -) error { - switch a { - case merkletrie.Modify: - sub, err := w.Submodule(name) - if err != nil { - return err - } - - if !sub.initialized { - return nil - } - - return w.addIndexFromTreeEntry(name, e, idx) - case merkletrie.Insert: - mode, err := e.Mode.ToOSFileMode() - if err != nil { - return err - } - - if err := w.Filesystem.MkdirAll(name, mode); err != nil { - return err - } - - return w.addIndexFromTreeEntry(name, e, idx) - } - - return nil -} - -func (w *Worktree) checkoutChangeRegularFile(name string, - a merkletrie.Action, - t *object.Tree, - e *object.TreeEntry, - idx *indexBuilder, -) error { - switch a { - case merkletrie.Modify: - idx.Remove(name) - - // to apply perm changes the file is deleted, billy doesn't implement - // chmod - if err := w.Filesystem.Remove(name); err != nil { - return err - } - - fallthrough - case merkletrie.Insert: - f, err := t.File(name) - if err != nil { - return err - } - - if err := w.checkoutFile(f); err != nil { - return err - } - - return w.addIndexFromFile(name, e.Hash, idx) - } - - return nil -} - -func (w *Worktree) checkoutFile(f *object.File) (err error) { - mode, err := f.Mode.ToOSFileMode() - if err != nil { - return - } - - if mode&os.ModeSymlink != 0 { - return w.checkoutFileSymlink(f) - } - - dstFile, err := w.Filesystem.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm()) - if err != nil { - return - } - defer ioutil.CheckClose(dstFile, &err) - - return w.copyObjectToWorktree(f, dstFile) -} - -func (w *Worktree) copyObjectToWorktree(object *object.File, file billy.File) (err error) { - cfg, err := w.r.Config() - if err != nil { - return err - } - - var src io.ReadCloser - var dst io.Writer = file - - src, err = object.Reader() - if err != nil { - return err - } - defer ioutil.CheckClose(src, &err) - - if cfg.Core.AutoCRLF == "true" { - br := sync.GetBufioReader(src) - defer sync.PutBufioReader(br) - - stat, err := convert.GetStat(br) - if err != nil { - return err - } - - src, err = object.Reader() - if err != nil { - return err - } - defer ioutil.CheckClose(src, &err) - - if !stat.IsBinary() { - dst = convert.NewCRLFWriter(dst) - } - } - - _, err = ioutil.CopyBufferPool(dst, src) - return err -} - -func (w *Worktree) checkoutFileSymlink(f *object.File) (err error) { - // https://github.com/git/git/commit/10ecfa76491e4923988337b2e2243b05376b40de - if strings.EqualFold(f.Name, gitmodulesFile) { - return ErrGitModulesSymlink - } - - from, err := f.Reader() - if err != nil { - return - } - - defer ioutil.CheckClose(from, &err) - - bytes, err := io.ReadAll(from) - if err != nil { - return - } - - err = w.Filesystem.Symlink(string(bytes), f.Name) - - // On windows, this might fail. - // Follow Git on Windows behavior by writing the link as it is. - if err != nil && isSymlinkWindowsNonAdmin(err) { - mode, _ := f.Mode.ToOSFileMode() - - to, err := w.Filesystem.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm()) - if err != nil { - return err - } - - defer ioutil.CheckClose(to, &err) - - _, err = to.Write(bytes) - return err - } - return -} - -func (w *Worktree) addIndexFromTreeEntry(name string, f *object.TreeEntry, idx *indexBuilder) error { - idx.Remove(name) - idx.Add(&index.Entry{ - Hash: f.Hash, - Name: name, - Mode: filemode.Submodule, - }) - return nil -} - -func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, idx *indexBuilder) error { - idx.Remove(name) - fi, err := w.Filesystem.Lstat(name) - if err != nil { - return err - } - - mode, err := filemode.NewFromOSFileMode(fi.Mode()) - if err != nil { - return err - } - - e := &index.Entry{ - Hash: h, - Name: name, - Mode: mode, - ModifiedAt: fi.ModTime(), - Size: uint32(fi.Size()), - } - - // if the FileInfo.Sys() comes from os the ctime, dev, inode, uid and gid - // can be retrieved, otherwise this doesn't apply - if fillSystemInfo != nil { - fillSystemInfo(e, fi.Sys()) - } - idx.Add(e) - return nil -} - -func (r *Repository) getTreeFromCommitHash(commit plumbing.Hash) (*object.Tree, error) { - c, err := r.CommitObject(commit) - if err != nil { - return nil, err - } - - return c.Tree() -} - -var fillSystemInfo func(e *index.Entry, sys interface{}) - -const gitmodulesFile = ".gitmodules" - -// Submodule returns the submodule with the given name -func (w *Worktree) Submodule(name string) (*Submodule, error) { - l, err := w.Submodules() - if err != nil { - return nil, err - } - - for _, m := range l { - if m.Config().Name == name { - return m, nil - } - } - - return nil, ErrSubmoduleNotFound -} - -// resolveModuleURL resolves relative URLs based on the originURL. -// The moduleURL is returned verbatim when originURL is empty or moduleURL is an absolute URL. -func resolveModuleURL(originURL, moduleURL string) (string, error) { - if originURL == "" { - return moduleURL, nil - } - if !strings.HasPrefix(moduleURL, "../") && !strings.HasPrefix(moduleURL, "./") { - return moduleURL, nil - } - if !giturl.MatchesScheme(originURL) && giturl.MatchesScpLike(originURL) { - user, host, portStr, p := giturl.FindScpLikeComponents(originURL) - p = path.Join(p, moduleURL) - if portStr != "" { - portStr += ":" - } - return fmt.Sprintf("%s@%s:%s%s", user, host, portStr, p), nil - } - base, err := url.Parse(originURL) - if err != nil { - return "", err - } - base.Path = path.Join(base.Path, moduleURL) - return base.String(), nil -} - -// Submodules returns all the available submodules -func (w *Worktree) Submodules() (Submodules, error) { - l := make(Submodules, 0) - m, err := w.readGitmodulesFile() - if err != nil || m == nil { - return l, err - } - - c, err := w.r.Config() - if err != nil { - return nil, err - } - - var originURL string - if origin, err := w.r.Remote(DefaultRemoteName); err == nil { - if origin.c != nil && len(origin.c.URLs) > 0 { - originURL = origin.c.URLs[0] - } - } - - for _, s := range m.Submodules { - sub := w.newSubmodule(s, c.Submodules[s.Name]) - cfg := sub.Config() - resolvedURL, err := resolveModuleURL(originURL, cfg.URL) - if err != nil { - return nil, fmt.Errorf("failed to resolve submodule URL %q: %w", s.URL, err) - } - cfg.URL = resolvedURL - l = append(l, sub) - } - - return l, nil -} - -func (w *Worktree) newSubmodule(fromModules, fromConfig *config.Submodule) *Submodule { - m := &Submodule{w: w} - m.initialized = fromConfig != nil - - if !m.initialized { - m.c = fromModules - return m - } - - m.c = fromConfig - m.c.Path = fromModules.Path - return m -} - -func (w *Worktree) isSymlink(path string) bool { - if s, err := w.Filesystem.Lstat(path); err == nil { - return s.Mode()&os.ModeSymlink != 0 - } - return false -} - -func (w *Worktree) readGitmodulesFile() (*config.Modules, error) { - if w.isSymlink(gitmodulesFile) { - return nil, ErrGitModulesSymlink - } - - f, err := w.Filesystem.Open(gitmodulesFile) - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - - return nil, err - } - - defer f.Close() - input, err := io.ReadAll(f) - if err != nil { - return nil, err - } - - m := config.NewModules() - if err := m.Unmarshal(input); err != nil { - return m, err - } - - return m, nil -} - -// Clean the worktree by removing untracked files. -// An empty dir could be removed - this is what `git clean -f -d .` does. -func (w *Worktree) Clean(opts *CleanOptions) error { - s, err := w.Status() - if err != nil { - return err - } - - root := "" - files, err := w.Filesystem.ReadDir(root) - if err != nil { - return err - } - return w.doClean(s, opts, root, files) -} - -func (w *Worktree) doClean(status Status, opts *CleanOptions, dir string, files []os.FileInfo) error { - for _, fi := range files { - if fi.Name() == GitDirName { - continue - } - - // relative path under the root - path := filepath.Join(dir, fi.Name()) - if fi.IsDir() { - if !opts.Dir { - continue - } - - subfiles, err := w.Filesystem.ReadDir(path) - if err != nil { - return err - } - err = w.doClean(status, opts, path, subfiles) - if err != nil { - return err - } - } else { - if status.IsUntracked(path) { - if err := w.Filesystem.Remove(path); err != nil { - return err - } - } - } - } - - if opts.Dir && dir != "" { - _, err := removeDirIfEmpty(w.Filesystem, dir) - return err - } - - return nil -} - -// GrepResult is structure of a grep result. -type GrepResult struct { - // FileName is the name of file which contains match. - FileName string - // LineNumber is the line number of a file at which a match was found. - LineNumber int - // Content is the content of the file at the matching line. - Content string - // TreeName is the name of the tree (reference name/commit hash) at - // which the match was performed. - TreeName string -} - -func (gr GrepResult) String() string { - return fmt.Sprintf("%s:%s:%d:%s", gr.TreeName, gr.FileName, gr.LineNumber, gr.Content) -} - -// Grep performs grep on a repository. -func (r *Repository) Grep(opts *GrepOptions) ([]GrepResult, error) { - if err := opts.validate(r); err != nil { - return nil, err - } - - // Obtain commit hash from options (CommitHash or ReferenceName). - var commitHash plumbing.Hash - // treeName contains the value of TreeName in GrepResult. - var treeName string - - if opts.ReferenceName != "" { - ref, err := r.Reference(opts.ReferenceName, true) - if err != nil { - return nil, err - } - commitHash = ref.Hash() - treeName = opts.ReferenceName.String() - } else if !opts.CommitHash.IsZero() { - commitHash = opts.CommitHash - treeName = opts.CommitHash.String() - } - - // Obtain a tree from the commit hash and get a tracked files iterator from - // the tree. - tree, err := r.getTreeFromCommitHash(commitHash) - if err != nil { - return nil, err - } - fileiter := tree.Files() - - return findMatchInFiles(fileiter, treeName, opts) -} - -// Grep performs grep on a worktree. -func (w *Worktree) Grep(opts *GrepOptions) ([]GrepResult, error) { - return w.r.Grep(opts) -} - -// findMatchInFiles takes a FileIter, worktree name and GrepOptions, and -// returns a slice of GrepResult containing the result of regex pattern matching -// in content of all the files. -func findMatchInFiles(fileiter *object.FileIter, treeName string, opts *GrepOptions) ([]GrepResult, error) { - var results []GrepResult - - err := fileiter.ForEach(func(file *object.File) error { - var fileInPathSpec bool - - // When no pathspecs are provided, search all the files. - if len(opts.PathSpecs) == 0 { - fileInPathSpec = true - } - - // Check if the file name matches with the pathspec. Break out of the - // loop once a match is found. - for _, pathSpec := range opts.PathSpecs { - if pathSpec != nil && pathSpec.MatchString(file.Name) { - fileInPathSpec = true - break - } - } - - // If the file does not match with any of the pathspec, skip it. - if !fileInPathSpec { - return nil - } - - grepResults, err := findMatchInFile(file, treeName, opts) - if err != nil { - return err - } - results = append(results, grepResults...) - - return nil - }) - - return results, err -} - -// findMatchInFile takes a single File, worktree name and GrepOptions, -// and returns a slice of GrepResult containing the result of regex pattern -// matching in the given file. -func findMatchInFile(file *object.File, treeName string, opts *GrepOptions) ([]GrepResult, error) { - var grepResults []GrepResult - - content, err := file.Contents() - if err != nil { - return grepResults, err - } - - // Split the file content and parse line-by-line. - contentByLine := strings.Split(content, "\n") - for lineNum, cnt := range contentByLine { - addToResult := false - - // Match the patterns and content. Break out of the loop once a - // match is found. - for _, pattern := range opts.Patterns { - if pattern != nil && pattern.MatchString(cnt) { - // Add to result only if invert match is not enabled. - if !opts.InvertMatch { - addToResult = true - break - } - } else if opts.InvertMatch { - // If matching fails, and invert match is enabled, add to - // results. - addToResult = true - break - } - } - - if addToResult { - grepResults = append(grepResults, GrepResult{ - FileName: file.Name, - LineNumber: lineNum + 1, - Content: cnt, - TreeName: treeName, - }) - } - } - - return grepResults, nil -} - -// will walk up the directory tree removing all encountered empty -// directories, not just the one containing this file -func rmFileAndDirsIfEmpty(fs billy.Filesystem, name string) error { - if err := util.RemoveAll(fs, name); err != nil { - return err - } - - dir := filepath.Dir(name) - for { - removed, err := removeDirIfEmpty(fs, dir) - if err != nil && !os.IsNotExist(err) { - return err - } - - if !removed { - // directory was not empty and not removed, - // stop checking parents - break - } - - // move to parent directory - dir = filepath.Dir(dir) - } - - return nil -} - -// removeDirIfEmpty will remove the supplied directory `dir` if -// `dir` is empty -// returns true if the directory was removed -func removeDirIfEmpty(fs billy.Filesystem, dir string) (bool, error) { - files, err := fs.ReadDir(dir) - if err != nil { - return false, err - } - - if len(files) > 0 { - return false, nil - } - - err = fs.Remove(dir) - if err != nil { - return false, err - } - - return true, nil -} - -type indexBuilder struct { - entries map[string]*index.Entry -} - -func newIndexBuilder(idx *index.Index) *indexBuilder { - entries := make(map[string]*index.Entry, len(idx.Entries)) - for _, e := range idx.Entries { - entries[e.Name] = e - } - return &indexBuilder{ - entries: entries, - } -} - -func (b *indexBuilder) Write(idx *index.Index) { - idx.Entries = idx.Entries[:0] - for _, e := range b.entries { - idx.Entries = append(idx.Entries, e) - } -} - -func (b *indexBuilder) Add(e *index.Entry) { - b.entries[e.Name] = e -} - -func (b *indexBuilder) Remove(name string) { - delete(b.entries, filepath.ToSlash(name)) -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_bsd.go b/vendor/github.com/go-git/go-git/v6/worktree_bsd.go deleted file mode 100644 index 9608cc49..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_bsd.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build darwin || freebsd || netbsd -// +build darwin freebsd netbsd - -package git - -import ( - "syscall" - "time" - - "github.com/go-git/go-git/v6/plumbing/format/index" -) - -func init() { - fillSystemInfo = func(e *index.Entry, sys interface{}) { - if os, ok := sys.(*syscall.Stat_t); ok { - e.CreatedAt = time.Unix(os.Atimespec.Unix()) - e.Dev = uint32(os.Dev) - e.Inode = uint32(os.Ino) - e.GID = os.Gid - e.UID = os.Uid - } - } -} - -func isSymlinkWindowsNonAdmin(err error) bool { - return false -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_commit.go b/vendor/github.com/go-git/go-git/v6/worktree_commit.go deleted file mode 100644 index 060889ec..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_commit.go +++ /dev/null @@ -1,293 +0,0 @@ -package git - -import ( - "bytes" - "errors" - "io" - "path" - "regexp" - "sort" - "strings" - - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/plumbing/format/index" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/storage" - - "github.com/ProtonMail/go-crypto/openpgp" - "github.com/ProtonMail/go-crypto/openpgp/packet" - "github.com/go-git/go-billy/v6" -) - -var ( - // ErrEmptyCommit occurs when a commit is attempted using a clean - // working tree, with no changes to be committed. - ErrEmptyCommit = errors.New("cannot create empty commit: clean working tree") - - // characters to be removed from user name and/or email before using them to build a commit object - // See https://git-scm.com/docs/git-commit#_commit_information - invalidCharactersRe = regexp.MustCompile(`[<>\n]`) -) - -// Commit stores the current contents of the index in a new commit along with -// a log message from the user describing the changes. -func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error) { - if err := opts.Validate(w.r); err != nil { - return plumbing.ZeroHash, err - } - - if opts.All { - if err := w.autoAddModifiedAndDeleted(); err != nil { - return plumbing.ZeroHash, err - } - } - - if opts.Amend { - head, err := w.r.Head() - if err != nil { - return plumbing.ZeroHash, err - } - headCommit, err := w.r.CommitObject(head.Hash()) - if err != nil { - return plumbing.ZeroHash, err - } - - opts.Parents = headCommit.ParentHashes - } - - idx, err := w.r.Storer.Index() - if err != nil { - return plumbing.ZeroHash, err - } - - // First handle the case of the first commit in the repository being empty. - if len(opts.Parents) == 0 && len(idx.Entries) == 0 && !opts.AllowEmptyCommits { - return plumbing.ZeroHash, ErrEmptyCommit - } - - h := &buildTreeHelper{ - fs: w.Filesystem, - s: w.r.Storer, - } - - treeHash, err := h.BuildTree(idx, opts) - if err != nil { - return plumbing.ZeroHash, err - } - - previousTree := plumbing.ZeroHash - if len(opts.Parents) > 0 { - parentCommit, err := w.r.CommitObject(opts.Parents[0]) - if err != nil { - return plumbing.ZeroHash, err - } - previousTree = parentCommit.TreeHash - } - - if treeHash == previousTree && !opts.AllowEmptyCommits { - return plumbing.ZeroHash, ErrEmptyCommit - } - - commit, err := w.buildCommitObject(msg, opts, treeHash) - if err != nil { - return plumbing.ZeroHash, err - } - - return commit, w.updateHEAD(commit) -} - -func (w *Worktree) autoAddModifiedAndDeleted() error { - s, err := w.Status() - if err != nil { - return err - } - - idx, err := w.r.Storer.Index() - if err != nil { - return err - } - - for path, fs := range s { - if fs.Worktree != Modified && fs.Worktree != Deleted { - continue - } - - if _, _, err := w.doAddFile(idx, s, path, nil); err != nil { - return err - } - - } - - return w.r.Storer.SetIndex(idx) -} - -func (w *Worktree) updateHEAD(commit plumbing.Hash) error { - head, err := w.r.Storer.Reference(plumbing.HEAD) - if err != nil { - return err - } - - name := plumbing.HEAD - if head.Type() != plumbing.HashReference { - name = head.Target() - } - - ref := plumbing.NewHashReference(name, commit) - return w.r.Storer.SetReference(ref) -} - -func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) { - commit := &object.Commit{ - Author: w.sanitize(*opts.Author), - Committer: w.sanitize(*opts.Committer), - Message: msg, - TreeHash: tree, - ParentHashes: opts.Parents, - } - - // Convert SignKey into a Signer if set. Existing Signer should take priority. - signer := opts.Signer - if signer == nil && opts.SignKey != nil { - signer = &gpgSigner{key: opts.SignKey} - } - if signer != nil { - sig, err := signObject(signer, commit) - if err != nil { - return plumbing.ZeroHash, err - } - commit.PGPSignature = string(sig) - } - - obj := w.r.Storer.NewEncodedObject() - if err := commit.Encode(obj); err != nil { - return plumbing.ZeroHash, err - } - return w.r.Storer.SetEncodedObject(obj) -} - -func (w *Worktree) sanitize(signature object.Signature) object.Signature { - return object.Signature{ - Name: invalidCharactersRe.ReplaceAllString(signature.Name, ""), - Email: invalidCharactersRe.ReplaceAllString(signature.Email, ""), - When: signature.When, - } -} - -type gpgSigner struct { - key *openpgp.Entity - cfg *packet.Config -} - -func (s *gpgSigner) Sign(message io.Reader) ([]byte, error) { - var b bytes.Buffer - if err := openpgp.ArmoredDetachSign(&b, s.key, message, s.cfg); err != nil { - return nil, err - } - return b.Bytes(), nil -} - -// buildTreeHelper converts a given index.Index file into multiple git objects -// reading the blobs from the given filesystem and creating the trees from the -// index structure. The created objects are pushed to a given Storer. -type buildTreeHelper struct { - fs billy.Filesystem - s storage.Storer - - trees map[string]*object.Tree - entries map[string]*object.TreeEntry -} - -// BuildTree builds the tree objects and push its to the storer, the hash -// of the root tree is returned. -func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) { - const rootNode = "" - h.trees = map[string]*object.Tree{rootNode: {}} - h.entries = map[string]*object.TreeEntry{} - - for _, e := range idx.Entries { - if err := h.commitIndexEntry(e); err != nil { - return plumbing.ZeroHash, err - } - } - - return h.copyTreeToStorageRecursive(rootNode, h.trees[rootNode]) -} - -func (h *buildTreeHelper) commitIndexEntry(e *index.Entry) error { - parts := strings.Split(e.Name, "/") - - var fullpath string - for _, part := range parts { - parent := fullpath - fullpath = path.Join(fullpath, part) - - h.doBuildTree(e, parent, fullpath) - } - - return nil -} - -func (h *buildTreeHelper) doBuildTree(e *index.Entry, parent, fullpath string) { - if _, ok := h.trees[fullpath]; ok { - return - } - - if _, ok := h.entries[fullpath]; ok { - return - } - - te := object.TreeEntry{Name: path.Base(fullpath)} - - if fullpath == e.Name { - te.Mode = e.Mode - te.Hash = e.Hash - } else { - te.Mode = filemode.Dir - h.trees[fullpath] = &object.Tree{} - } - - h.trees[parent].Entries = append(h.trees[parent].Entries, te) -} - -type sortableEntries []object.TreeEntry - -func (sortableEntries) sortName(te object.TreeEntry) string { - if te.Mode == filemode.Dir { - return te.Name + "/" - } - return te.Name -} -func (se sortableEntries) Len() int { return len(se) } -func (se sortableEntries) Less(i int, j int) bool { return se.sortName(se[i]) < se.sortName(se[j]) } -func (se sortableEntries) Swap(i int, j int) { se[i], se[j] = se[j], se[i] } - -func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tree) (plumbing.Hash, error) { - sort.Sort(sortableEntries(t.Entries)) - for i, e := range t.Entries { - if e.Mode != filemode.Dir && !e.Hash.IsZero() { - continue - } - - path := path.Join(parent, e.Name) - - var err error - e.Hash, err = h.copyTreeToStorageRecursive(path, h.trees[path]) - if err != nil { - return plumbing.ZeroHash, err - } - - t.Entries[i] = e - } - - o := h.s.NewEncodedObject() - if err := t.Encode(o); err != nil { - return plumbing.ZeroHash, err - } - - hash := o.Hash() - if h.s.HasEncodedObject(hash) == nil { - return hash, nil - } - return h.s.SetEncodedObject(o) -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_js.go b/vendor/github.com/go-git/go-git/v6/worktree_js.go deleted file mode 100644 index 61bce90a..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_js.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build js -// +build js - -package git - -import ( - "syscall" - "time" - - "github.com/go-git/go-git/v6/plumbing/format/index" -) - -func init() { - fillSystemInfo = func(e *index.Entry, sys interface{}) { - if os, ok := sys.(*syscall.Stat_t); ok { - e.CreatedAt = time.Unix(int64(os.Ctime), int64(os.CtimeNsec)) - e.Dev = uint32(os.Dev) - e.Inode = uint32(os.Ino) - e.GID = os.Gid - e.UID = os.Uid - } - } -} - -func isSymlinkWindowsNonAdmin(err error) bool { - return false -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_linux.go b/vendor/github.com/go-git/go-git/v6/worktree_linux.go deleted file mode 100644 index b021edf5..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_linux.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build linux -// +build linux - -package git - -import ( - "syscall" - "time" - - "github.com/go-git/go-git/v6/plumbing/format/index" -) - -func init() { - fillSystemInfo = func(e *index.Entry, sys interface{}) { - if os, ok := sys.(*syscall.Stat_t); ok { - e.CreatedAt = time.Unix(os.Ctim.Unix()) - e.Dev = uint32(os.Dev) - e.Inode = uint32(os.Ino) - e.GID = os.Gid - e.UID = os.Uid - } - } -} - -func isSymlinkWindowsNonAdmin(_ error) bool { - return false -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_plan9.go b/vendor/github.com/go-git/go-git/v6/worktree_plan9.go deleted file mode 100644 index 333995bc..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_plan9.go +++ /dev/null @@ -1,31 +0,0 @@ -package git - -import ( - "syscall" - "time" - - "github.com/go-git/go-git/v6/plumbing/format/index" -) - -func init() { - fillSystemInfo = func(e *index.Entry, sys interface{}) { - if os, ok := sys.(*syscall.Dir); ok { - // Plan 9 doesn't have a CreatedAt field. - e.CreatedAt = time.Unix(int64(os.Mtime), 0) - - e.Dev = uint32(os.Dev) - - // Plan 9 has no Inode. - // ext2srv(4) appears to store Inode in Qid.Path. - e.Inode = uint32(os.Qid.Path) - - // Plan 9 has string UID/GID - e.GID = 0 - e.UID = 0 - } - } -} - -func isSymlinkWindowsNonAdmin(err error) bool { - return true -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_status.go b/vendor/github.com/go-git/go-git/v6/worktree_status.go deleted file mode 100644 index b7043fab..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_status.go +++ /dev/null @@ -1,764 +0,0 @@ -package git - -import ( - "bytes" - "errors" - "io" - "os" - "path" - "path/filepath" - "strings" - - "github.com/go-git/go-billy/v6/util" - "github.com/go-git/go-git/v6/plumbing" - "github.com/go-git/go-git/v6/plumbing/filemode" - "github.com/go-git/go-git/v6/plumbing/format/gitignore" - "github.com/go-git/go-git/v6/plumbing/format/index" - "github.com/go-git/go-git/v6/plumbing/object" - "github.com/go-git/go-git/v6/utils/convert" - "github.com/go-git/go-git/v6/utils/ioutil" - "github.com/go-git/go-git/v6/utils/merkletrie" - "github.com/go-git/go-git/v6/utils/merkletrie/filesystem" - mindex "github.com/go-git/go-git/v6/utils/merkletrie/index" - "github.com/go-git/go-git/v6/utils/merkletrie/noder" - "github.com/go-git/go-git/v6/utils/sync" -) - -var ( - // ErrDestinationExists in an Move operation means that the target exists on - // the worktree. - ErrDestinationExists = errors.New("destination exists") - // ErrGlobNoMatches in an AddGlob if the glob pattern does not match any - // files in the worktree. - ErrGlobNoMatches = errors.New("glob pattern did not match any files") - // ErrUnsupportedStatusStrategy occurs when an invalid StatusStrategy is used - // when processing the Worktree status. - ErrUnsupportedStatusStrategy = errors.New("unsupported status strategy") -) - -// Status returns the working tree status. -func (w *Worktree) Status() (Status, error) { - return w.StatusWithOptions(StatusOptions{Strategy: defaultStatusStrategy}) -} - -// StatusOptions defines the options for Worktree.StatusWithOptions(). -type StatusOptions struct { - Strategy StatusStrategy -} - -// StatusWithOptions returns the working tree status. -func (w *Worktree) StatusWithOptions(o StatusOptions) (Status, error) { - var hash plumbing.Hash - - ref, err := w.r.Head() - if err != nil && err != plumbing.ErrReferenceNotFound { - return nil, err - } - - if err == nil { - hash = ref.Hash() - } - - return w.status(o.Strategy, hash) -} - -func (w *Worktree) status(ss StatusStrategy, commit plumbing.Hash) (Status, error) { - s, err := ss.new(w) - if err != nil { - return nil, err - } - - left, err := w.diffCommitWithStaging(commit, false) - if err != nil { - return nil, err - } - - for _, ch := range left { - a, err := ch.Action() - if err != nil { - return nil, err - } - - fs := s.File(nameFromAction(&ch)) - fs.Worktree = Unmodified - - switch a { - case merkletrie.Delete: - s.File(ch.From.String()).Staging = Deleted - case merkletrie.Insert: - s.File(ch.To.String()).Staging = Added - case merkletrie.Modify: - s.File(ch.To.String()).Staging = Modified - } - } - - right, err := w.diffStagingWithWorktree(false, true) - if err != nil { - return nil, err - } - - for _, ch := range right { - a, err := ch.Action() - if err != nil { - return nil, err - } - - fs := s.File(nameFromAction(&ch)) - if fs.Staging == Untracked { - fs.Staging = Unmodified - } - - switch a { - case merkletrie.Delete: - fs.Worktree = Deleted - case merkletrie.Insert: - fs.Worktree = Untracked - fs.Staging = Untracked - case merkletrie.Modify: - fs.Worktree = Modified - } - } - - return s, nil -} - -func nameFromAction(ch *merkletrie.Change) string { - name := ch.To.String() - if name == "" { - return ch.From.String() - } - - return name -} - -func (w *Worktree) diffStagingWithWorktree(reverse, excludeIgnoredChanges bool) (merkletrie.Changes, error) { - idx, err := w.r.Storer.Index() - if err != nil { - return nil, err - } - - from := mindex.NewRootNode(idx) - submodules, err := w.getSubmodulesStatus() - if err != nil { - return nil, err - } - - cfg, err := w.r.Config() - if err != nil { - return nil, err - } - - fsOpts := filesystem.Options{ - AutoCRLF: cfg.Core.AutoCRLF == "true" || cfg.Core.AutoCRLF == "input", - } - - to := filesystem.NewRootNodeWithOptions(w.Filesystem, submodules, fsOpts) - - var c merkletrie.Changes - if reverse { - c, err = merkletrie.DiffTree(to, from, diffTreeIsEquals) - } else { - c, err = merkletrie.DiffTree(from, to, diffTreeIsEquals) - } - - if err != nil { - return nil, err - } - - if excludeIgnoredChanges { - return w.excludeIgnoredChanges(c), nil - } - return c, nil -} - -func (w *Worktree) excludeIgnoredChanges(changes merkletrie.Changes) merkletrie.Changes { - patterns, err := gitignore.ReadPatterns(w.Filesystem, nil) - if err != nil { - return changes - } - - patterns = append(patterns, w.Excludes...) - - if len(patterns) == 0 { - return changes - } - - m := gitignore.NewMatcher(patterns) - - var res merkletrie.Changes - for _, ch := range changes { - var path []string - for _, n := range ch.To { - path = append(path, n.Name()) - } - if len(path) == 0 { - for _, n := range ch.From { - path = append(path, n.Name()) - } - } - if len(path) != 0 { - isDir := (len(ch.To) > 0 && ch.To.IsDir()) || (len(ch.From) > 0 && ch.From.IsDir()) - if m.Match(path, isDir) { - if len(ch.From) == 0 { - continue - } - } - } - res = append(res, ch) - } - return res -} - -func (w *Worktree) getSubmodulesStatus() (map[string]plumbing.Hash, error) { - o := map[string]plumbing.Hash{} - - sub, err := w.Submodules() - if err != nil { - return nil, err - } - - status, err := sub.Status() - if err != nil { - return nil, err - } - - for _, s := range status { - if s.Current.IsZero() { - o[s.Path] = s.Expected - continue - } - - o[s.Path] = s.Current - } - - return o, nil -} - -func (w *Worktree) diffCommitWithStaging(commit plumbing.Hash, reverse bool) (merkletrie.Changes, error) { - var t *object.Tree - if !commit.IsZero() { - c, err := w.r.CommitObject(commit) - if err != nil { - return nil, err - } - - t, err = c.Tree() - if err != nil { - return nil, err - } - } - - return w.diffTreeWithStaging(t, reverse) -} - -func (w *Worktree) diffTreeWithStaging(t *object.Tree, reverse bool) (merkletrie.Changes, error) { - var from noder.Noder - if t != nil { - from = object.NewTreeRootNode(t) - } - - idx, err := w.r.Storer.Index() - if err != nil { - return nil, err - } - - to := mindex.NewRootNode(idx) - - if reverse { - return merkletrie.DiffTree(to, from, diffTreeIsEquals) - } - - return merkletrie.DiffTree(from, to, diffTreeIsEquals) -} - -var emptyNoderHash = make([]byte, 24) - -// diffTreeIsEquals is a implementation of noder.Equals, used to compare -// noder.Noder, it compare the content and the length of the hashes. -// -// Since some of the noder.Noder implementations doesn't compute a hash for -// some directories, if any of the hashes is a 24-byte slice of zero values -// the comparison is not done and the hashes are take as different. -func diffTreeIsEquals(a, b noder.Hasher) bool { - hashA := a.Hash() - hashB := b.Hash() - - if bytes.Equal(hashA, emptyNoderHash) || bytes.Equal(hashB, emptyNoderHash) { - return false - } - - return bytes.Equal(hashA, hashB) -} - -// Add adds the file contents of a file in the worktree to the index. if the -// file is already staged in the index no error is returned. If a file deleted -// from the Workspace is given, the file is removed from the index. If a -// directory given, adds the files and all his sub-directories recursively in -// the worktree to the index. If any of the files is already staged in the index -// no error is returned. When path is a file, the blob.Hash is returned. -func (w *Worktree) Add(path string) (plumbing.Hash, error) { - // TODO(mcuadros): deprecate in favor of AddWithOption in v6. - return w.doAdd(path, make([]gitignore.Pattern, 0), false) -} - -func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) { - if len(ignorePattern) > 0 { - m := gitignore.NewMatcher(ignorePattern) - matchPath := strings.Split(directory, string(os.PathSeparator)) - if m.Match(matchPath, true) { - // ignore - return false, nil - } - } - - directory = filepath.ToSlash(filepath.Clean(directory)) - - for name := range s { - if !isPathInDirectory(name, directory) { - continue - } - - var a bool - a, _, err = w.doAddFile(idx, s, name, ignorePattern) - if err != nil { - return - } - - added = added || a - } - - return -} - -func isPathInDirectory(path, directory string) bool { - return directory == "." || strings.HasPrefix(path, directory+"/") -} - -// AddWithOptions file contents to the index, updates the index using the -// current content found in the working tree, to prepare the content staged for -// the next commit. -// -// It typically adds the current content of existing paths as a whole, but with -// some options it can also be used to add content with only part of the changes -// made to the working tree files applied, or remove paths that do not exist in -// the working tree anymore. -func (w *Worktree) AddWithOptions(opts *AddOptions) error { - if err := opts.Validate(w.r); err != nil { - return err - } - - if opts.All { - _, err := w.doAdd(".", w.Excludes, false) - return err - } - - if opts.Glob != "" { - return w.AddGlob(opts.Glob) - } - - _, err := w.doAdd(opts.Path, make([]gitignore.Pattern, 0), opts.SkipStatus) - return err -} - -func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern, skipStatus bool) (plumbing.Hash, error) { - idx, err := w.r.Storer.Index() - if err != nil { - return plumbing.ZeroHash, err - } - - var h plumbing.Hash - var added bool - - fi, err := w.Filesystem.Lstat(path) - - // status is required for doAddDirectory - var s Status - var err2 error - if !skipStatus || fi == nil || fi.IsDir() { - s, err2 = w.Status() - if err2 != nil { - return plumbing.ZeroHash, err2 - } - } - - path = filepath.Clean(path) - - if err != nil || !fi.IsDir() { - added, h, err = w.doAddFile(idx, s, path, ignorePattern) - } else { - added, err = w.doAddDirectory(idx, s, path, ignorePattern) - } - - if err != nil { - return h, err - } - - if !added { - return h, nil - } - - return h, w.r.Storer.SetIndex(idx) -} - -// AddGlob adds all paths, matching pattern, to the index. If pattern matches a -// directory path, all directory contents are added to the index recursively. No -// error is returned if all matching paths are already staged in index. -func (w *Worktree) AddGlob(pattern string) error { - // TODO(mcuadros): deprecate in favor of AddWithOption in v6. - files, err := util.Glob(w.Filesystem, pattern) - if err != nil { - return err - } - - if len(files) == 0 { - return ErrGlobNoMatches - } - - s, err := w.Status() - if err != nil { - return err - } - - idx, err := w.r.Storer.Index() - if err != nil { - return err - } - - var saveIndex bool - for _, file := range files { - fi, err := w.Filesystem.Lstat(file) - if err != nil { - return err - } - - var added bool - if fi.IsDir() { - added, err = w.doAddDirectory(idx, s, file, make([]gitignore.Pattern, 0)) - } else { - added, _, err = w.doAddFile(idx, s, file, make([]gitignore.Pattern, 0)) - } - - if err != nil { - return err - } - - if !saveIndex && added { - saveIndex = true - } - } - - if saveIndex { - return w.r.Storer.SetIndex(idx) - } - - return nil -} - -// doAddFile create a new blob from path and update the index, added is true if -// the file added is different from the index. -// if s status is nil will skip the status check and update the index anyway -func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) { - if s != nil && s.File(path).Worktree == Unmodified { - return false, h, nil - } - if len(ignorePattern) > 0 { - m := gitignore.NewMatcher(ignorePattern) - matchPath := strings.Split(path, string(os.PathSeparator)) - if m.Match(matchPath, true) { - // ignore - return false, h, nil - } - } - - h, err = w.copyFileToStorage(path) - if err != nil { - if os.IsNotExist(err) { - added = true - h, err = w.deleteFromIndex(idx, path) - } - - return - } - - if err := w.addOrUpdateFileToIndex(idx, path, h); err != nil { - return false, h, err - } - - return true, h, err -} - -func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error) { - fi, err := w.Filesystem.Lstat(path) - if err != nil { - return plumbing.ZeroHash, err - } - - obj := w.r.Storer.NewEncodedObject() - obj.SetType(plumbing.BlobObject) - obj.SetSize(fi.Size()) - - writer, err := obj.Writer() - if err != nil { - return plumbing.ZeroHash, err - } - - defer ioutil.CheckClose(writer, &err) - - if fi.Mode()&os.ModeSymlink != 0 { - err = w.fillEncodedObjectFromSymlink(writer, path, fi) - } else { - err = w.fillEncodedObjectFromFile(writer, path, fi) - } - - if err != nil { - return plumbing.ZeroHash, err - } - - return w.r.Storer.SetEncodedObject(obj) -} - -func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, _ os.FileInfo) (err error) { - file, err := w.Filesystem.Open(path) - if err != nil { - return err - } - defer ioutil.CheckClose(file, &err) - - cfg, err := w.r.Config() - if err != nil { - return err - } - - switch cfg.Core.AutoCRLF { - case "true", "input": - br := sync.GetBufioReader(file) - defer sync.PutBufioReader(br) - - stat, err := convert.GetStat(br) - if err != nil { - return err - } - - if _, err = file.Seek(0, io.SeekStart); err != nil { - return err - } - - if !stat.IsBinary() { - dst = convert.NewLFWriter(dst) - } - } - - _, err = ioutil.CopyBufferPool(dst, file) - return err -} - -func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, _ os.FileInfo) error { - target, err := w.Filesystem.Readlink(path) - if err != nil { - return err - } - - _, err = dst.Write([]byte(target)) - return err -} - -func (w *Worktree) addOrUpdateFileToIndex(idx *index.Index, filename string, h plumbing.Hash) error { - e, err := idx.Entry(filename) - if err != nil && err != index.ErrEntryNotFound { - return err - } - - if err == index.ErrEntryNotFound { - return w.doAddFileToIndex(idx, filename, h) - } - - return w.doUpdateFileToIndex(e, filename, h) -} - -func (w *Worktree) doAddFileToIndex(idx *index.Index, filename string, h plumbing.Hash) error { - return w.doUpdateFileToIndex(idx.Add(filename), filename, h) -} - -func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbing.Hash) error { - info, err := w.Filesystem.Lstat(filename) - if err != nil { - return err - } - - e.Hash = h - e.ModifiedAt = info.ModTime() - e.Mode, err = filemode.NewFromOSFileMode(info.Mode()) - if err != nil { - return err - } - - // The entry size must always reflect the current state, otherwise - // it will cause go-git's Worktree.Status() to divert from "git status". - // The size of a symlink is the length of the path to the target. - // The size of Regular and Executable files is the size of the files. - e.Size = uint32(info.Size()) - - fillSystemInfo(e, info.Sys()) - return nil -} - -// Remove removes files from the working tree and from the index. -func (w *Worktree) Remove(path string) (plumbing.Hash, error) { - // TODO(mcuadros): remove plumbing.Hash from signature at v5. - idx, err := w.r.Storer.Index() - if err != nil { - return plumbing.ZeroHash, err - } - - var h plumbing.Hash - - fi, err := w.Filesystem.Lstat(path) - if err != nil || !fi.IsDir() { - h, err = w.doRemoveFile(idx, path) - } else { - _, err = w.doRemoveDirectory(idx, path) - } - if err != nil { - return h, err - } - - return h, w.r.Storer.SetIndex(idx) -} - -func (w *Worktree) doRemoveDirectory(idx *index.Index, directory string) (removed bool, err error) { - files, err := w.Filesystem.ReadDir(directory) - if err != nil { - return false, err - } - - for _, file := range files { - name := path.Join(directory, file.Name()) - - var r bool - if file.IsDir() { - r, err = w.doRemoveDirectory(idx, name) - } else { - _, err = w.doRemoveFile(idx, name) - if err == index.ErrEntryNotFound { - err = nil - } - } - - if err != nil { - return - } - - if !removed && r { - removed = true - } - } - - err = w.removeEmptyDirectory(directory) - return -} - -func (w *Worktree) removeEmptyDirectory(path string) error { - files, err := w.Filesystem.ReadDir(path) - if err != nil { - return err - } - - if len(files) != 0 { - return nil - } - - return w.Filesystem.Remove(path) -} - -func (w *Worktree) doRemoveFile(idx *index.Index, path string) (plumbing.Hash, error) { - hash, err := w.deleteFromIndex(idx, path) - if err != nil { - return plumbing.ZeroHash, err - } - - return hash, w.deleteFromFilesystem(path) -} - -func (w *Worktree) deleteFromIndex(idx *index.Index, path string) (plumbing.Hash, error) { - e, err := idx.Remove(path) - if err != nil { - return plumbing.ZeroHash, err - } - - return e.Hash, nil -} - -func (w *Worktree) deleteFromFilesystem(path string) error { - err := w.Filesystem.Remove(path) - if os.IsNotExist(err) { - return nil - } - - return err -} - -// RemoveGlob removes all paths, matching pattern, from the index. If pattern -// matches a directory path, all directory contents are removed from the index -// recursively. -func (w *Worktree) RemoveGlob(pattern string) error { - idx, err := w.r.Storer.Index() - if err != nil { - return err - } - - entries, err := idx.Glob(pattern) - if err != nil { - return err - } - - for _, e := range entries { - file := filepath.FromSlash(e.Name) - if _, err := w.Filesystem.Lstat(file); err != nil && !os.IsNotExist(err) { - return err - } - - if _, err := w.doRemoveFile(idx, file); err != nil { - return err - } - - dir, _ := filepath.Split(file) - if err := w.removeEmptyDirectory(dir); err != nil { - return err - } - } - - return w.r.Storer.SetIndex(idx) -} - -// Move moves or rename a file in the worktree and the index, directories are -// not supported. -func (w *Worktree) Move(from, to string) (plumbing.Hash, error) { - // TODO(mcuadros): support directories and/or implement support for glob - if _, err := w.Filesystem.Lstat(from); err != nil { - return plumbing.ZeroHash, err - } - - if _, err := w.Filesystem.Lstat(to); err == nil { - return plumbing.ZeroHash, ErrDestinationExists - } - - idx, err := w.r.Storer.Index() - if err != nil { - return plumbing.ZeroHash, err - } - - hash, err := w.deleteFromIndex(idx, from) - if err != nil { - return plumbing.ZeroHash, err - } - - if err := w.Filesystem.Rename(from, to); err != nil { - return hash, err - } - - if err := w.addOrUpdateFileToIndex(idx, to, hash); err != nil { - return hash, err - } - - return hash, w.r.Storer.SetIndex(idx) -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_unix_other.go b/vendor/github.com/go-git/go-git/v6/worktree_unix_other.go deleted file mode 100644 index 2a7f17cf..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_unix_other.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build openbsd || dragonfly || solaris -// +build openbsd dragonfly solaris - -package git - -import ( - "syscall" - "time" - - "github.com/go-git/go-git/v6/plumbing/format/index" -) - -func init() { - fillSystemInfo = func(e *index.Entry, sys interface{}) { - if os, ok := sys.(*syscall.Stat_t); ok { - e.CreatedAt = time.Unix(os.Atim.Unix()) - e.Dev = uint32(os.Dev) - e.Inode = uint32(os.Ino) - e.GID = os.Gid - e.UID = os.Uid - } - } -} - -func isSymlinkWindowsNonAdmin(err error) bool { - return false -} diff --git a/vendor/github.com/go-git/go-git/v6/worktree_windows.go b/vendor/github.com/go-git/go-git/v6/worktree_windows.go deleted file mode 100644 index 7a15846c..00000000 --- a/vendor/github.com/go-git/go-git/v6/worktree_windows.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build windows -// +build windows - -package git - -import ( - "os" - "syscall" - "time" - - "github.com/go-git/go-git/v6/plumbing/format/index" -) - -func init() { - fillSystemInfo = func(e *index.Entry, sys interface{}) { - if os, ok := sys.(*syscall.Win32FileAttributeData); ok { - seconds := os.CreationTime.Nanoseconds() / 1000000000 - nanoseconds := os.CreationTime.Nanoseconds() - seconds*1000000000 - e.CreatedAt = time.Unix(seconds, nanoseconds) - } - } -} - -func isSymlinkWindowsNonAdmin(err error) bool { - const ERROR_PRIVILEGE_NOT_HELD syscall.Errno = 1314 - - if err != nil { - if errLink, ok := err.(*os.LinkError); ok { - if errNo, ok := errLink.Err.(syscall.Errno); ok { - return errNo == ERROR_PRIVILEGE_NOT_HELD - } - } - } - - return false -} diff --git a/vendor/github.com/go-jose/go-jose/v4/.gitignore b/vendor/github.com/go-jose/go-jose/v4/.gitignore deleted file mode 100644 index eb29ebae..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -jose-util/jose-util -jose-util.t.err \ No newline at end of file diff --git a/vendor/github.com/go-jose/go-jose/v4/.golangci.yml b/vendor/github.com/go-jose/go-jose/v4/.golangci.yml deleted file mode 100644 index 2a577a8f..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/.golangci.yml +++ /dev/null @@ -1,53 +0,0 @@ -# https://github.com/golangci/golangci-lint - -run: - skip-files: - - doc_test.go - modules-download-mode: readonly - -linters: - enable-all: true - disable: - - gochecknoglobals - - goconst - - lll - - maligned - - nakedret - - scopelint - - unparam - - funlen # added in 1.18 (requires go-jose changes before it can be enabled) - -linters-settings: - gocyclo: - min-complexity: 35 - -issues: - exclude-rules: - - text: "don't use ALL_CAPS in Go names" - linters: - - golint - - text: "hardcoded credentials" - linters: - - gosec - - text: "weak cryptographic primitive" - linters: - - gosec - - path: json/ - linters: - - dupl - - errcheck - - gocritic - - gocyclo - - golint - - govet - - ineffassign - - staticcheck - - structcheck - - stylecheck - - unused - - path: _test\.go - linters: - - scopelint - - path: jwk.go - linters: - - gocyclo diff --git a/vendor/github.com/go-jose/go-jose/v4/.travis.yml b/vendor/github.com/go-jose/go-jose/v4/.travis.yml deleted file mode 100644 index 48de631b..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: go - -matrix: - fast_finish: true - allow_failures: - - go: tip - -go: - - "1.13.x" - - "1.14.x" - - tip - -before_script: - - export PATH=$HOME/.local/bin:$PATH - -before_install: - - go get -u github.com/mattn/goveralls github.com/wadey/gocovmerge - - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.18.0 - - pip install cram --user - -script: - - go test -v -covermode=count -coverprofile=profile.cov . - - go test -v -covermode=count -coverprofile=cryptosigner/profile.cov ./cryptosigner - - go test -v -covermode=count -coverprofile=cipher/profile.cov ./cipher - - go test -v -covermode=count -coverprofile=jwt/profile.cov ./jwt - - go test -v ./json # no coverage for forked encoding/json package - - golangci-lint run - - cd jose-util && go build && PATH=$PWD:$PATH cram -v jose-util.t # cram tests jose-util - - cd .. - -after_success: - - gocovmerge *.cov */*.cov > merged.coverprofile - - goveralls -coverprofile merged.coverprofile -service=travis-ci diff --git a/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md b/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md deleted file mode 100644 index 66a8a0f8..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/CHANGELOG.md +++ /dev/null @@ -1,101 +0,0 @@ -## Changed - - - Defined a custom error, ErrUnexpectedSignatureAlgorithm, returned when a JWS - header contains an unsupported signature algorithm. - -# v4.0.4 - -## Fixed - - - Reverted "Allow unmarshalling JSONWebKeySets with unsupported key types" as a - breaking change. See #136 / #137. - -# v4.0.3 - -## Changed - - - Allow unmarshalling JSONWebKeySets with unsupported key types (#130) - - Document that OpaqueKeyEncrypter can't be implemented (for now) (#129) - - Dependency updates - -# v4.0.2 - -## Changed - - - Improved documentation of Verify() to note that JSONWebKeySet is a supported - argument type (#104) - - Defined exported error values for missing x5c header and unsupported elliptic - curves error cases (#117) - -# v4.0.1 - -## Fixed - - - An attacker could send a JWE containing compressed data that used large - amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`. - Those functions now return an error if the decompressed data would exceed - 250kB or 10x the compressed size (whichever is larger). Thanks to - Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj) - for reporting. - -# v4.0.0 - -This release makes some breaking changes in order to more thoroughly -address the vulnerabilities discussed in [Three New Attacks Against JSON Web -Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot -token". - -## Changed - - - Limit JWT encryption types (exclude password or public key types) (#78) - - Enforce minimum length for HMAC keys (#85) - - jwt: match any audience in a list, rather than requiring all audiences (#81) - - jwt: accept only Compact Serialization (#75) - - jws: Add expected algorithms for signatures (#74) - - Require specifying expected algorithms for ParseEncrypted, - ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned, - jwt.ParseSignedAndEncrypted (#69, #74) - - Usually there is a small, known set of appropriate algorithms for a program - to use and it's a mistake to allow unexpected algorithms. For instance the - "billion hash attack" relies in part on programs accepting the PBES2 - encryption algorithm and doing the necessary work even if they weren't - specifically configured to allow PBES2. - - Revert "Strip padding off base64 strings" (#82) - - The specs require base64url encoding without padding. - - Minimum supported Go version is now 1.21 - -## Added - - - ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON. - - These allow parsing a specific serialization, as opposed to ParseSigned and - ParseEncrypted, which try to automatically detect which serialization was - provided. It's common to require a specific serialization for a specific - protocol - for instance JWT requires Compact serialization. - -[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf - -# v3.0.2 - -## Fixed - - - DecryptMulti: handle decompression error (#19) - -## Changed - - - jwe/CompactSerialize: improve performance (#67) - - Increase the default number of PBKDF2 iterations to 600k (#48) - - Return the proper algorithm for ECDSA keys (#45) - -## Added - - - Add Thumbprint support for opaque signers (#38) - -# v3.0.1 - -## Fixed - - - Security issue: an attacker specifying a large "p2c" value can cause - JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large - amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the - disclosure and to Tom Tervoort for originally publishing the category of attack. - https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf diff --git a/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md b/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md deleted file mode 100644 index 4b4805ad..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/CONTRIBUTING.md +++ /dev/null @@ -1,9 +0,0 @@ -# Contributing - -If you would like to contribute code to go-jose you can do so through GitHub by -forking the repository and sending a pull request. - -When submitting code, please make every effort to follow existing conventions -and style in order to keep the code as readable as possible. Please also make -sure all tests pass by running `go test`, and format your code with `go fmt`. -We also recommend using `golint` and `errcheck`. diff --git a/vendor/github.com/go-jose/go-jose/v4/LICENSE b/vendor/github.com/go-jose/go-jose/v4/LICENSE deleted file mode 100644 index d6456956..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/go-jose/go-jose/v4/README.md b/vendor/github.com/go-jose/go-jose/v4/README.md deleted file mode 100644 index 02b57495..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# Go JOSE - -[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4) -[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt) -[![license](https://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/go-jose/go-jose/master/LICENSE) -[![test](https://img.shields.io/github/checks-status/go-jose/go-jose/v4)](https://github.com/go-jose/go-jose/actions) - -Package jose aims to provide an implementation of the Javascript Object Signing -and Encryption set of standards. This includes support for JSON Web Encryption, -JSON Web Signature, and JSON Web Token standards. - -## Overview - -The implementation follows the -[JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516), -[JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and -[JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications. -Tables of supported algorithms are shown below. The library supports both -the compact and JWS/JWE JSON Serialization formats, and has optional support for -multiple recipients. It also comes with a small command-line utility -([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util)) -for dealing with JOSE messages in a shell. - -**Note**: We use a forked version of the `encoding/json` package from the Go -standard library which uses case-sensitive matching for member names (instead -of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html)). -This is to avoid differences in interpretation of messages between go-jose and -libraries in other languages. - -### Versions - -[Version 4](https://github.com/go-jose/go-jose) -([branch](https://github.com/go-jose/go-jose/tree/main), -[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version: - - import "github.com/go-jose/go-jose/v4" - -The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which -are still useable but not actively developed anymore. - -Version 3, in this repo, is still receiving security fixes but not functionality -updates. - -### Supported algorithms - -See below for a table of supported algorithms. Algorithm identifiers match -the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518) -standard where possible. The Godoc reference has a list of constants. - - Key encryption | Algorithm identifier(s) - :------------------------- | :------------------------------ - RSA-PKCS#1v1.5 | RSA1_5 - RSA-OAEP | RSA-OAEP, RSA-OAEP-256 - AES key wrap | A128KW, A192KW, A256KW - AES-GCM key wrap | A128GCMKW, A192GCMKW, A256GCMKW - ECDH-ES + AES key wrap | ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW - ECDH-ES (direct) | ECDH-ES1 - Direct encryption | dir1 - -1. Not supported in multi-recipient mode - - Signing / MAC | Algorithm identifier(s) - :------------------------- | :------------------------------ - RSASSA-PKCS#1v1.5 | RS256, RS384, RS512 - RSASSA-PSS | PS256, PS384, PS512 - HMAC | HS256, HS384, HS512 - ECDSA | ES256, ES384, ES512 - Ed25519 | EdDSA2 - -2. Only available in version 2 of the package - - Content encryption | Algorithm identifier(s) - :------------------------- | :------------------------------ - AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 - AES-GCM | A128GCM, A192GCM, A256GCM - - Compression | Algorithm identifiers(s) - :------------------------- | ------------------------------- - DEFLATE (RFC 1951) | DEF - -### Supported key types - -See below for a table of supported key types. These are understood by the -library, and can be passed to corresponding functions such as `NewEncrypter` or -`NewSigner`. Each of these keys can also be wrapped in a JWK if desired, which -allows attaching a key id. - - Algorithm(s) | Corresponding types - :------------------------- | ------------------------------- - RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey) - ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey) - EdDSA1 | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey) - AES, HMAC | []byte - -1. Only available in version 2 or later of the package - -## Examples - -[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4) -[![godoc](https://pkg.go.dev/badge/github.com/go-jose/go-jose/v4/jwt.svg)](https://pkg.go.dev/github.com/go-jose/go-jose/v4/jwt) - -Examples can be found in the Godoc -reference for this package. The -[`jose-util`](https://github.com/go-jose/go-jose/tree/main/jose-util) -subdirectory also contains a small command-line utility which might be useful -as an example as well. diff --git a/vendor/github.com/go-jose/go-jose/v4/SECURITY.md b/vendor/github.com/go-jose/go-jose/v4/SECURITY.md deleted file mode 100644 index 2f18a75a..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/SECURITY.md +++ /dev/null @@ -1,13 +0,0 @@ -# Security Policy -This document explains how to contact the Let's Encrypt security team to report security vulnerabilities. - -## Supported Versions -| Version | Supported | -| ------- | ----------| -| >= v3 | ✓ | -| v2 | ✗ | -| v1 | ✗ | - -## Reporting a vulnerability - -Please see [https://letsencrypt.org/contact/#security](https://letsencrypt.org/contact/#security) for the email address to report a vulnerability. Ensure that the subject line for your report contains the word `vulnerability` and is descriptive. Your email should be acknowledged within 24 hours. If you do not receive a response within 24 hours, please follow-up again with another email. diff --git a/vendor/github.com/go-jose/go-jose/v4/asymmetric.go b/vendor/github.com/go-jose/go-jose/v4/asymmetric.go deleted file mode 100644 index f8d5774e..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/asymmetric.go +++ /dev/null @@ -1,595 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "crypto" - "crypto/aes" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rand" - "crypto/rsa" - "crypto/sha1" - "crypto/sha256" - "errors" - "fmt" - "math/big" - - josecipher "github.com/go-jose/go-jose/v4/cipher" - "github.com/go-jose/go-jose/v4/json" -) - -// A generic RSA-based encrypter/verifier -type rsaEncrypterVerifier struct { - publicKey *rsa.PublicKey -} - -// A generic RSA-based decrypter/signer -type rsaDecrypterSigner struct { - privateKey *rsa.PrivateKey -} - -// A generic EC-based encrypter/verifier -type ecEncrypterVerifier struct { - publicKey *ecdsa.PublicKey -} - -type edEncrypterVerifier struct { - publicKey ed25519.PublicKey -} - -// A key generator for ECDH-ES -type ecKeyGenerator struct { - size int - algID string - publicKey *ecdsa.PublicKey -} - -// A generic EC-based decrypter/signer -type ecDecrypterSigner struct { - privateKey *ecdsa.PrivateKey -} - -type edDecrypterSigner struct { - privateKey ed25519.PrivateKey -} - -// newRSARecipient creates recipientKeyInfo based on the given key. -func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) { - // Verify that key management algorithm is supported by this encrypter - switch keyAlg { - case RSA1_5, RSA_OAEP, RSA_OAEP_256: - default: - return recipientKeyInfo{}, ErrUnsupportedAlgorithm - } - - if publicKey == nil { - return recipientKeyInfo{}, errors.New("invalid public key") - } - - return recipientKeyInfo{ - keyAlg: keyAlg, - keyEncrypter: &rsaEncrypterVerifier{ - publicKey: publicKey, - }, - }, nil -} - -// newRSASigner creates a recipientSigInfo based on the given key. -func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipientSigInfo, error) { - // Verify that key management algorithm is supported by this encrypter - switch sigAlg { - case RS256, RS384, RS512, PS256, PS384, PS512: - default: - return recipientSigInfo{}, ErrUnsupportedAlgorithm - } - - if privateKey == nil { - return recipientSigInfo{}, errors.New("invalid private key") - } - - return recipientSigInfo{ - sigAlg: sigAlg, - publicKey: staticPublicKey(&JSONWebKey{ - Key: privateKey.Public(), - }), - signer: &rsaDecrypterSigner{ - privateKey: privateKey, - }, - }, nil -} - -func newEd25519Signer(sigAlg SignatureAlgorithm, privateKey ed25519.PrivateKey) (recipientSigInfo, error) { - if sigAlg != EdDSA { - return recipientSigInfo{}, ErrUnsupportedAlgorithm - } - - if privateKey == nil { - return recipientSigInfo{}, errors.New("invalid private key") - } - return recipientSigInfo{ - sigAlg: sigAlg, - publicKey: staticPublicKey(&JSONWebKey{ - Key: privateKey.Public(), - }), - signer: &edDecrypterSigner{ - privateKey: privateKey, - }, - }, nil -} - -// newECDHRecipient creates recipientKeyInfo based on the given key. -func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) { - // Verify that key management algorithm is supported by this encrypter - switch keyAlg { - case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW: - default: - return recipientKeyInfo{}, ErrUnsupportedAlgorithm - } - - if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { - return recipientKeyInfo{}, errors.New("invalid public key") - } - - return recipientKeyInfo{ - keyAlg: keyAlg, - keyEncrypter: &ecEncrypterVerifier{ - publicKey: publicKey, - }, - }, nil -} - -// newECDSASigner creates a recipientSigInfo based on the given key. -func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (recipientSigInfo, error) { - // Verify that key management algorithm is supported by this encrypter - switch sigAlg { - case ES256, ES384, ES512: - default: - return recipientSigInfo{}, ErrUnsupportedAlgorithm - } - - if privateKey == nil { - return recipientSigInfo{}, errors.New("invalid private key") - } - - return recipientSigInfo{ - sigAlg: sigAlg, - publicKey: staticPublicKey(&JSONWebKey{ - Key: privateKey.Public(), - }), - signer: &ecDecrypterSigner{ - privateKey: privateKey, - }, - }, nil -} - -// Encrypt the given payload and update the object. -func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { - encryptedKey, err := ctx.encrypt(cek, alg) - if err != nil { - return recipientInfo{}, err - } - - return recipientInfo{ - encryptedKey: encryptedKey, - header: &rawHeader{}, - }, nil -} - -// Encrypt the given payload. Based on the key encryption algorithm, -// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256). -func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) { - switch alg { - case RSA1_5: - return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek) - case RSA_OAEP: - return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{}) - case RSA_OAEP_256: - return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{}) - } - - return nil, ErrUnsupportedAlgorithm -} - -// Decrypt the given payload and return the content encryption key. -func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { - return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator) -} - -// Decrypt the given payload. Based on the key encryption algorithm, -// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256). -func (ctx rsaDecrypterSigner) decrypt(jek []byte, alg KeyAlgorithm, generator keyGenerator) ([]byte, error) { - // Note: The random reader on decrypt operations is only used for blinding, - // so stubbing is meanlingless (hence the direct use of rand.Reader). - switch alg { - case RSA1_5: - defer func() { - // DecryptPKCS1v15SessionKey sometimes panics on an invalid payload - // because of an index out of bounds error, which we want to ignore. - // This has been fixed in Go 1.3.1 (released 2014/08/13), the recover() - // only exists for preventing crashes with unpatched versions. - // See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k - // See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33 - _ = recover() - }() - - // Perform some input validation. - keyBytes := ctx.privateKey.PublicKey.N.BitLen() / 8 - if keyBytes != len(jek) { - // Input size is incorrect, the encrypted payload should always match - // the size of the public modulus (e.g. using a 2048 bit key will - // produce 256 bytes of output). Reject this since it's invalid input. - return nil, ErrCryptoFailure - } - - cek, _, err := generator.genKey() - if err != nil { - return nil, ErrCryptoFailure - } - - // When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to - // prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing - // the Million Message Attack on Cryptographic Message Syntax". We are - // therefore deliberately ignoring errors here. - _ = rsa.DecryptPKCS1v15SessionKey(rand.Reader, ctx.privateKey, jek, cek) - - return cek, nil - case RSA_OAEP: - // Use rand.Reader for RSA blinding - return rsa.DecryptOAEP(sha1.New(), rand.Reader, ctx.privateKey, jek, []byte{}) - case RSA_OAEP_256: - // Use rand.Reader for RSA blinding - return rsa.DecryptOAEP(sha256.New(), rand.Reader, ctx.privateKey, jek, []byte{}) - } - - return nil, ErrUnsupportedAlgorithm -} - -// Sign the given payload -func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { - var hash crypto.Hash - - switch alg { - case RS256, PS256: - hash = crypto.SHA256 - case RS384, PS384: - hash = crypto.SHA384 - case RS512, PS512: - hash = crypto.SHA512 - default: - return Signature{}, ErrUnsupportedAlgorithm - } - - hasher := hash.New() - - // According to documentation, Write() on hash never fails - _, _ = hasher.Write(payload) - hashed := hasher.Sum(nil) - - var out []byte - var err error - - switch alg { - case RS256, RS384, RS512: - // TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the - // random parameter is legacy and ignored, and it can be nil. - // https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1 - out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed) - case PS256, PS384, PS512: - out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - }) - } - - if err != nil { - return Signature{}, err - } - - return Signature{ - Signature: out, - protected: &rawHeader{}, - }, nil -} - -// Verify the given payload -func (ctx rsaEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { - var hash crypto.Hash - - switch alg { - case RS256, PS256: - hash = crypto.SHA256 - case RS384, PS384: - hash = crypto.SHA384 - case RS512, PS512: - hash = crypto.SHA512 - default: - return ErrUnsupportedAlgorithm - } - - hasher := hash.New() - - // According to documentation, Write() on hash never fails - _, _ = hasher.Write(payload) - hashed := hasher.Sum(nil) - - switch alg { - case RS256, RS384, RS512: - return rsa.VerifyPKCS1v15(ctx.publicKey, hash, hashed, signature) - case PS256, PS384, PS512: - return rsa.VerifyPSS(ctx.publicKey, hash, hashed, signature, nil) - } - - return ErrUnsupportedAlgorithm -} - -// Encrypt the given payload and update the object. -func (ctx ecEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { - switch alg { - case ECDH_ES: - // ECDH-ES mode doesn't wrap a key, the shared secret is used directly as the key. - return recipientInfo{ - header: &rawHeader{}, - }, nil - case ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW: - default: - return recipientInfo{}, ErrUnsupportedAlgorithm - } - - generator := ecKeyGenerator{ - algID: string(alg), - publicKey: ctx.publicKey, - } - - switch alg { - case ECDH_ES_A128KW: - generator.size = 16 - case ECDH_ES_A192KW: - generator.size = 24 - case ECDH_ES_A256KW: - generator.size = 32 - } - - kek, header, err := generator.genKey() - if err != nil { - return recipientInfo{}, err - } - - block, err := aes.NewCipher(kek) - if err != nil { - return recipientInfo{}, err - } - - jek, err := josecipher.KeyWrap(block, cek) - if err != nil { - return recipientInfo{}, err - } - - return recipientInfo{ - encryptedKey: jek, - header: &header, - }, nil -} - -// Get key size for EC key generator -func (ctx ecKeyGenerator) keySize() int { - return ctx.size -} - -// Get a content encryption key for ECDH-ES -func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) { - priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader) - if err != nil { - return nil, rawHeader{}, err - } - - out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size) - - b, err := json.Marshal(&JSONWebKey{ - Key: &priv.PublicKey, - }) - if err != nil { - return nil, nil, err - } - - headers := rawHeader{ - headerEPK: makeRawMessage(b), - } - - return out, headers, nil -} - -// Decrypt the given payload and return the content encryption key. -func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { - epk, err := headers.getEPK() - if err != nil { - return nil, errors.New("go-jose/go-jose: invalid epk header") - } - if epk == nil { - return nil, errors.New("go-jose/go-jose: missing epk header") - } - - publicKey, ok := epk.Key.(*ecdsa.PublicKey) - if publicKey == nil || !ok { - return nil, errors.New("go-jose/go-jose: invalid epk header") - } - - if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) { - return nil, errors.New("go-jose/go-jose: invalid public key in epk header") - } - - apuData, err := headers.getAPU() - if err != nil { - return nil, errors.New("go-jose/go-jose: invalid apu header") - } - apvData, err := headers.getAPV() - if err != nil { - return nil, errors.New("go-jose/go-jose: invalid apv header") - } - - deriveKey := func(algID string, size int) []byte { - return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size) - } - - var keySize int - - algorithm := headers.getAlgorithm() - switch algorithm { - case ECDH_ES: - // ECDH-ES uses direct key agreement, no key unwrapping necessary. - return deriveKey(string(headers.getEncryption()), generator.keySize()), nil - case ECDH_ES_A128KW: - keySize = 16 - case ECDH_ES_A192KW: - keySize = 24 - case ECDH_ES_A256KW: - keySize = 32 - default: - return nil, ErrUnsupportedAlgorithm - } - - key := deriveKey(string(algorithm), keySize) - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - - return josecipher.KeyUnwrap(block, recipient.encryptedKey) -} - -func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { - if alg != EdDSA { - return Signature{}, ErrUnsupportedAlgorithm - } - - sig, err := ctx.privateKey.Sign(RandReader, payload, crypto.Hash(0)) - if err != nil { - return Signature{}, err - } - - return Signature{ - Signature: sig, - protected: &rawHeader{}, - }, nil -} - -func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { - if alg != EdDSA { - return ErrUnsupportedAlgorithm - } - ok := ed25519.Verify(ctx.publicKey, payload, signature) - if !ok { - return errors.New("go-jose/go-jose: ed25519 signature failed to verify") - } - return nil -} - -// Sign the given payload -func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { - var expectedBitSize int - var hash crypto.Hash - - switch alg { - case ES256: - expectedBitSize = 256 - hash = crypto.SHA256 - case ES384: - expectedBitSize = 384 - hash = crypto.SHA384 - case ES512: - expectedBitSize = 521 - hash = crypto.SHA512 - } - - curveBits := ctx.privateKey.Curve.Params().BitSize - if expectedBitSize != curveBits { - return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits) - } - - hasher := hash.New() - - // According to documentation, Write() on hash never fails - _, _ = hasher.Write(payload) - hashed := hasher.Sum(nil) - - r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed) - if err != nil { - return Signature{}, err - } - - keyBytes := curveBits / 8 - if curveBits%8 > 0 { - keyBytes++ - } - - // We serialize the outputs (r and s) into big-endian byte arrays and pad - // them with zeros on the left to make sure the sizes work out. Both arrays - // must be keyBytes long, and the output must be 2*keyBytes long. - rBytes := r.Bytes() - rBytesPadded := make([]byte, keyBytes) - copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) - - sBytes := s.Bytes() - sBytesPadded := make([]byte, keyBytes) - copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) - - out := append(rBytesPadded, sBytesPadded...) - - return Signature{ - Signature: out, - protected: &rawHeader{}, - }, nil -} - -// Verify the given payload -func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error { - var keySize int - var hash crypto.Hash - - switch alg { - case ES256: - keySize = 32 - hash = crypto.SHA256 - case ES384: - keySize = 48 - hash = crypto.SHA384 - case ES512: - keySize = 66 - hash = crypto.SHA512 - default: - return ErrUnsupportedAlgorithm - } - - if len(signature) != 2*keySize { - return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize) - } - - hasher := hash.New() - - // According to documentation, Write() on hash never fails - _, _ = hasher.Write(payload) - hashed := hasher.Sum(nil) - - r := big.NewInt(0).SetBytes(signature[:keySize]) - s := big.NewInt(0).SetBytes(signature[keySize:]) - - match := ecdsa.Verify(ctx.publicKey, hashed, r, s) - if !match { - return errors.New("go-jose/go-jose: ecdsa signature failed to verify") - } - - return nil -} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go b/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go deleted file mode 100644 index af029cec..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/cipher/cbc_hmac.go +++ /dev/null @@ -1,196 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "bytes" - "crypto/cipher" - "crypto/hmac" - "crypto/sha256" - "crypto/sha512" - "crypto/subtle" - "encoding/binary" - "errors" - "hash" -) - -const ( - nonceBytes = 16 -) - -// NewCBCHMAC instantiates a new AEAD based on CBC+HMAC. -func NewCBCHMAC(key []byte, newBlockCipher func([]byte) (cipher.Block, error)) (cipher.AEAD, error) { - keySize := len(key) / 2 - integrityKey := key[:keySize] - encryptionKey := key[keySize:] - - blockCipher, err := newBlockCipher(encryptionKey) - if err != nil { - return nil, err - } - - var hash func() hash.Hash - switch keySize { - case 16: - hash = sha256.New - case 24: - hash = sha512.New384 - case 32: - hash = sha512.New - } - - return &cbcAEAD{ - hash: hash, - blockCipher: blockCipher, - authtagBytes: keySize, - integrityKey: integrityKey, - }, nil -} - -// An AEAD based on CBC+HMAC -type cbcAEAD struct { - hash func() hash.Hash - authtagBytes int - integrityKey []byte - blockCipher cipher.Block -} - -func (ctx *cbcAEAD) NonceSize() int { - return nonceBytes -} - -func (ctx *cbcAEAD) Overhead() int { - // Maximum overhead is block size (for padding) plus auth tag length, where - // the length of the auth tag is equivalent to the key size. - return ctx.blockCipher.BlockSize() + ctx.authtagBytes -} - -// Seal encrypts and authenticates the plaintext. -func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte { - // Output buffer -- must take care not to mangle plaintext input. - ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)] - copy(ciphertext, plaintext) - ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize()) - - cbc := cipher.NewCBCEncrypter(ctx.blockCipher, nonce) - - cbc.CryptBlocks(ciphertext, ciphertext) - authtag := ctx.computeAuthTag(data, nonce, ciphertext) - - ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag))) - copy(out, ciphertext) - copy(out[len(ciphertext):], authtag) - - return ret -} - -// Open decrypts and authenticates the ciphertext. -func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { - if len(ciphertext) < ctx.authtagBytes { - return nil, errors.New("go-jose/go-jose: invalid ciphertext (too short)") - } - - offset := len(ciphertext) - ctx.authtagBytes - expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset]) - match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:]) - if match != 1 { - return nil, errors.New("go-jose/go-jose: invalid ciphertext (auth tag mismatch)") - } - - cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce) - - // Make copy of ciphertext buffer, don't want to modify in place - buffer := append([]byte{}, ciphertext[:offset]...) - - if len(buffer)%ctx.blockCipher.BlockSize() > 0 { - return nil, errors.New("go-jose/go-jose: invalid ciphertext (invalid length)") - } - - cbc.CryptBlocks(buffer, buffer) - - // Remove padding - plaintext, err := unpadBuffer(buffer, ctx.blockCipher.BlockSize()) - if err != nil { - return nil, err - } - - ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext))) - copy(out, plaintext) - - return ret, nil -} - -// Compute an authentication tag -func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte { - buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8) - n := 0 - n += copy(buffer, aad) - n += copy(buffer[n:], nonce) - n += copy(buffer[n:], ciphertext) - binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8) - - // According to documentation, Write() on hash.Hash never fails. - hmac := hmac.New(ctx.hash, ctx.integrityKey) - _, _ = hmac.Write(buffer) - - return hmac.Sum(nil)[:ctx.authtagBytes] -} - -// resize ensures that the given slice has a capacity of at least n bytes. -// If the capacity of the slice is less than n, a new slice is allocated -// and the existing data will be copied. -func resize(in []byte, n uint64) (head, tail []byte) { - if uint64(cap(in)) >= n { - head = in[:n] - } else { - head = make([]byte, n) - copy(head, in) - } - - tail = head[len(in):] - return -} - -// Apply padding -func padBuffer(buffer []byte, blockSize int) []byte { - missing := blockSize - (len(buffer) % blockSize) - ret, out := resize(buffer, uint64(len(buffer))+uint64(missing)) - padding := bytes.Repeat([]byte{byte(missing)}, missing) - copy(out, padding) - return ret -} - -// Remove padding -func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) { - if len(buffer)%blockSize != 0 { - return nil, errors.New("go-jose/go-jose: invalid padding") - } - - last := buffer[len(buffer)-1] - count := int(last) - - if count == 0 || count > blockSize || count > len(buffer) { - return nil, errors.New("go-jose/go-jose: invalid padding") - } - - padding := bytes.Repeat([]byte{last}, count) - if !bytes.HasSuffix(buffer, padding) { - return nil, errors.New("go-jose/go-jose: invalid padding") - } - - return buffer[:len(buffer)-count], nil -} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go b/vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go deleted file mode 100644 index f62c3bdb..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/cipher/concat_kdf.go +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "crypto" - "encoding/binary" - "hash" - "io" -) - -type concatKDF struct { - z, info []byte - i uint32 - cache []byte - hasher hash.Hash -} - -// NewConcatKDF builds a KDF reader based on the given inputs. -func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader { - buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo))) - n := 0 - n += copy(buffer, algID) - n += copy(buffer[n:], ptyUInfo) - n += copy(buffer[n:], ptyVInfo) - n += copy(buffer[n:], supPubInfo) - copy(buffer[n:], supPrivInfo) - - hasher := hash.New() - - return &concatKDF{ - z: z, - info: buffer, - hasher: hasher, - cache: []byte{}, - i: 1, - } -} - -func (ctx *concatKDF) Read(out []byte) (int, error) { - copied := copy(out, ctx.cache) - ctx.cache = ctx.cache[copied:] - - for copied < len(out) { - ctx.hasher.Reset() - - // Write on a hash.Hash never fails - _ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i) - _, _ = ctx.hasher.Write(ctx.z) - _, _ = ctx.hasher.Write(ctx.info) - - hash := ctx.hasher.Sum(nil) - chunkCopied := copy(out[copied:], hash) - copied += chunkCopied - ctx.cache = hash[chunkCopied:] - - ctx.i++ - } - - return copied, nil -} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go b/vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go deleted file mode 100644 index 093c6467..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/cipher/ecdh_es.go +++ /dev/null @@ -1,86 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "bytes" - "crypto" - "crypto/ecdsa" - "crypto/elliptic" - "encoding/binary" -) - -// DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA. -// It is an error to call this function with a private/public key that are not on the same -// curve. Callers must ensure that the keys are valid before calling this function. Output -// size may be at most 1<<16 bytes (64 KiB). -func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte { - if size > 1<<16 { - panic("ECDH-ES output size too large, must be less than or equal to 1<<16") - } - - // algId, partyUInfo, partyVInfo inputs must be prefixed with the length - algID := lengthPrefixed([]byte(alg)) - ptyUInfo := lengthPrefixed(apuData) - ptyVInfo := lengthPrefixed(apvData) - - // suppPubInfo is the encoded length of the output size in bits - supPubInfo := make([]byte, 4) - binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8) - - if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) { - panic("public key not on same curve as private key") - } - - z, _ := priv.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes()) - zBytes := z.Bytes() - - // Note that calling z.Bytes() on a big.Int may strip leading zero bytes from - // the returned byte array. This can lead to a problem where zBytes will be - // shorter than expected which breaks the key derivation. Therefore we must pad - // to the full length of the expected coordinate here before calling the KDF. - octSize := dSize(priv.Curve) - if len(zBytes) != octSize { - zBytes = append(bytes.Repeat([]byte{0}, octSize-len(zBytes)), zBytes...) - } - - reader := NewConcatKDF(crypto.SHA256, zBytes, algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{}) - key := make([]byte, size) - - // Read on the KDF will never fail - _, _ = reader.Read(key) - - return key -} - -// dSize returns the size in octets for a coordinate on a elliptic curve. -func dSize(curve elliptic.Curve) int { - order := curve.Params().P - bitLen := order.BitLen() - size := bitLen / 8 - if bitLen%8 != 0 { - size++ - } - return size -} - -func lengthPrefixed(data []byte) []byte { - out := make([]byte, len(data)+4) - binary.BigEndian.PutUint32(out, uint32(len(data))) - copy(out[4:], data) - return out -} diff --git a/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go b/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go deleted file mode 100644 index b9effbca..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/cipher/key_wrap.go +++ /dev/null @@ -1,109 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package josecipher - -import ( - "crypto/cipher" - "crypto/subtle" - "encoding/binary" - "errors" -) - -var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6} - -// KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher. -func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { - if len(cek)%8 != 0 { - return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks") - } - - n := len(cek) / 8 - r := make([][]byte, n) - - for i := range r { - r[i] = make([]byte, 8) - copy(r[i], cek[i*8:]) - } - - buffer := make([]byte, 16) - tBytes := make([]byte, 8) - copy(buffer, defaultIV) - - for t := 0; t < 6*n; t++ { - copy(buffer[8:], r[t%n]) - - block.Encrypt(buffer, buffer) - - binary.BigEndian.PutUint64(tBytes, uint64(t+1)) - - for i := 0; i < 8; i++ { - buffer[i] ^= tBytes[i] - } - copy(r[t%n], buffer[8:]) - } - - out := make([]byte, (n+1)*8) - copy(out, buffer[:8]) - for i := range r { - copy(out[(i+1)*8:], r[i]) - } - - return out, nil -} - -// KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher. -func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) { - if len(ciphertext)%8 != 0 { - return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks") - } - - n := (len(ciphertext) / 8) - 1 - r := make([][]byte, n) - - for i := range r { - r[i] = make([]byte, 8) - copy(r[i], ciphertext[(i+1)*8:]) - } - - buffer := make([]byte, 16) - tBytes := make([]byte, 8) - copy(buffer[:8], ciphertext[:8]) - - for t := 6*n - 1; t >= 0; t-- { - binary.BigEndian.PutUint64(tBytes, uint64(t+1)) - - for i := 0; i < 8; i++ { - buffer[i] ^= tBytes[i] - } - copy(buffer[8:], r[t%n]) - - block.Decrypt(buffer, buffer) - - copy(r[t%n], buffer[8:]) - } - - if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 { - return nil, errors.New("go-jose/go-jose: failed to unwrap key") - } - - out := make([]byte, n*8) - for i := range r { - copy(out[i*8:], r[i]) - } - - return out, nil -} diff --git a/vendor/github.com/go-jose/go-jose/v4/crypter.go b/vendor/github.com/go-jose/go-jose/v4/crypter.go deleted file mode 100644 index d81b03b4..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/crypter.go +++ /dev/null @@ -1,599 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "crypto/ecdsa" - "crypto/rsa" - "errors" - "fmt" - - "github.com/go-jose/go-jose/v4/json" -) - -// Encrypter represents an encrypter which produces an encrypted JWE object. -type Encrypter interface { - Encrypt(plaintext []byte) (*JSONWebEncryption, error) - EncryptWithAuthData(plaintext []byte, aad []byte) (*JSONWebEncryption, error) - Options() EncrypterOptions -} - -// A generic content cipher -type contentCipher interface { - keySize() int - encrypt(cek []byte, aad, plaintext []byte) (*aeadParts, error) - decrypt(cek []byte, aad []byte, parts *aeadParts) ([]byte, error) -} - -// A key generator (for generating/getting a CEK) -type keyGenerator interface { - keySize() int - genKey() ([]byte, rawHeader, error) -} - -// A generic key encrypter -type keyEncrypter interface { - encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) // Encrypt a key -} - -// A generic key decrypter -type keyDecrypter interface { - decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) // Decrypt a key -} - -// A generic encrypter based on the given key encrypter and content cipher. -type genericEncrypter struct { - contentAlg ContentEncryption - compressionAlg CompressionAlgorithm - cipher contentCipher - recipients []recipientKeyInfo - keyGenerator keyGenerator - extraHeaders map[HeaderKey]interface{} -} - -type recipientKeyInfo struct { - keyID string - keyAlg KeyAlgorithm - keyEncrypter keyEncrypter -} - -// EncrypterOptions represents options that can be set on new encrypters. -type EncrypterOptions struct { - Compression CompressionAlgorithm - - // Optional map of name/value pairs to be inserted into the protected - // header of a JWS object. Some specifications which make use of - // JWS require additional values here. - // - // Values will be serialized by [json.Marshal] and must be valid inputs to - // that function. - // - // [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal - ExtraHeaders map[HeaderKey]interface{} -} - -// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it -// if necessary, and returns the updated EncrypterOptions. -// -// The v parameter will be serialized by [json.Marshal] and must be a valid -// input to that function. -// -// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal -func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions { - if eo.ExtraHeaders == nil { - eo.ExtraHeaders = map[HeaderKey]interface{}{} - } - eo.ExtraHeaders[k] = v - return eo -} - -// WithContentType adds a content type ("cty") header and returns the updated -// EncrypterOptions. -func (eo *EncrypterOptions) WithContentType(contentType ContentType) *EncrypterOptions { - return eo.WithHeader(HeaderContentType, contentType) -} - -// WithType adds a type ("typ") header and returns the updated EncrypterOptions. -func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions { - return eo.WithHeader(HeaderType, typ) -} - -// Recipient represents an algorithm/key to encrypt messages to. -// -// PBES2Count and PBES2Salt correspond with the "p2c" and "p2s" headers used -// on the password-based encryption algorithms PBES2-HS256+A128KW, -// PBES2-HS384+A192KW, and PBES2-HS512+A256KW. If they are not provided a safe -// default of 100000 will be used for the count and a 128-bit random salt will -// be generated. -type Recipient struct { - Algorithm KeyAlgorithm - // Key must have one of these types: - // - ed25519.PublicKey - // - *ecdsa.PublicKey - // - *rsa.PublicKey - // - *JSONWebKey - // - JSONWebKey - // - []byte (a symmetric key) - // - Any type that satisfies the OpaqueKeyEncrypter interface - // - // The type of Key must match the value of Algorithm. - Key interface{} - KeyID string - PBES2Count int - PBES2Salt []byte -} - -// NewEncrypter creates an appropriate encrypter based on the key type -func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions) (Encrypter, error) { - encrypter := &genericEncrypter{ - contentAlg: enc, - recipients: []recipientKeyInfo{}, - cipher: getContentCipher(enc), - } - if opts != nil { - encrypter.compressionAlg = opts.Compression - encrypter.extraHeaders = opts.ExtraHeaders - } - - if encrypter.cipher == nil { - return nil, ErrUnsupportedAlgorithm - } - - var keyID string - var rawKey interface{} - switch encryptionKey := rcpt.Key.(type) { - case JSONWebKey: - keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key - case *JSONWebKey: - keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key - case OpaqueKeyEncrypter: - keyID, rawKey = encryptionKey.KeyID(), encryptionKey - default: - rawKey = encryptionKey - } - - switch rcpt.Algorithm { - case DIRECT: - // Direct encryption mode must be treated differently - keyBytes, ok := rawKey.([]byte) - if !ok { - return nil, ErrUnsupportedKeyType - } - if encrypter.cipher.keySize() != len(keyBytes) { - return nil, ErrInvalidKeySize - } - encrypter.keyGenerator = staticKeyGenerator{ - key: keyBytes, - } - recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes) - recipientInfo.keyID = keyID - if rcpt.KeyID != "" { - recipientInfo.keyID = rcpt.KeyID - } - encrypter.recipients = []recipientKeyInfo{recipientInfo} - return encrypter, nil - case ECDH_ES: - // ECDH-ES (w/o key wrapping) is similar to DIRECT mode - keyDSA, ok := rawKey.(*ecdsa.PublicKey) - if !ok { - return nil, ErrUnsupportedKeyType - } - encrypter.keyGenerator = ecKeyGenerator{ - size: encrypter.cipher.keySize(), - algID: string(enc), - publicKey: keyDSA, - } - recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA) - recipientInfo.keyID = keyID - if rcpt.KeyID != "" { - recipientInfo.keyID = rcpt.KeyID - } - encrypter.recipients = []recipientKeyInfo{recipientInfo} - return encrypter, nil - default: - // Can just add a standard recipient - encrypter.keyGenerator = randomKeyGenerator{ - size: encrypter.cipher.keySize(), - } - err := encrypter.addRecipient(rcpt) - return encrypter, err - } -} - -// NewMultiEncrypter creates a multi-encrypter based on the given parameters -func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *EncrypterOptions) (Encrypter, error) { - cipher := getContentCipher(enc) - - if cipher == nil { - return nil, ErrUnsupportedAlgorithm - } - if len(rcpts) == 0 { - return nil, fmt.Errorf("go-jose/go-jose: recipients is nil or empty") - } - - encrypter := &genericEncrypter{ - contentAlg: enc, - recipients: []recipientKeyInfo{}, - cipher: cipher, - keyGenerator: randomKeyGenerator{ - size: cipher.keySize(), - }, - } - - if opts != nil { - encrypter.compressionAlg = opts.Compression - encrypter.extraHeaders = opts.ExtraHeaders - } - - for _, recipient := range rcpts { - err := encrypter.addRecipient(recipient) - if err != nil { - return nil, err - } - } - - return encrypter, nil -} - -func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) { - var recipientInfo recipientKeyInfo - - switch recipient.Algorithm { - case DIRECT, ECDH_ES: - return fmt.Errorf("go-jose/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm) - } - - recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key) - if recipient.KeyID != "" { - recipientInfo.keyID = recipient.KeyID - } - - switch recipient.Algorithm { - case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW: - if sr, ok := recipientInfo.keyEncrypter.(*symmetricKeyCipher); ok { - sr.p2c = recipient.PBES2Count - sr.p2s = recipient.PBES2Salt - } - } - - if err == nil { - ctx.recipients = append(ctx.recipients, recipientInfo) - } - return err -} - -func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKeyInfo, error) { - switch encryptionKey := encryptionKey.(type) { - case *rsa.PublicKey: - return newRSARecipient(alg, encryptionKey) - case *ecdsa.PublicKey: - return newECDHRecipient(alg, encryptionKey) - case []byte: - return newSymmetricRecipient(alg, encryptionKey) - case string: - return newSymmetricRecipient(alg, []byte(encryptionKey)) - case *JSONWebKey: - recipient, err := makeJWERecipient(alg, encryptionKey.Key) - recipient.keyID = encryptionKey.KeyID - return recipient, err - case OpaqueKeyEncrypter: - return newOpaqueKeyEncrypter(alg, encryptionKey) - } - return recipientKeyInfo{}, ErrUnsupportedKeyType -} - -// newDecrypter creates an appropriate decrypter based on the key type -func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) { - switch decryptionKey := decryptionKey.(type) { - case *rsa.PrivateKey: - return &rsaDecrypterSigner{ - privateKey: decryptionKey, - }, nil - case *ecdsa.PrivateKey: - return &ecDecrypterSigner{ - privateKey: decryptionKey, - }, nil - case []byte: - return &symmetricKeyCipher{ - key: decryptionKey, - }, nil - case string: - return &symmetricKeyCipher{ - key: []byte(decryptionKey), - }, nil - case JSONWebKey: - return newDecrypter(decryptionKey.Key) - case *JSONWebKey: - return newDecrypter(decryptionKey.Key) - case OpaqueKeyDecrypter: - return &opaqueKeyDecrypter{decrypter: decryptionKey}, nil - default: - return nil, ErrUnsupportedKeyType - } -} - -// Implementation of encrypt method producing a JWE object. -func (ctx *genericEncrypter) Encrypt(plaintext []byte) (*JSONWebEncryption, error) { - return ctx.EncryptWithAuthData(plaintext, nil) -} - -// Implementation of encrypt method producing a JWE object. -func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWebEncryption, error) { - obj := &JSONWebEncryption{} - obj.aad = aad - - obj.protected = &rawHeader{} - err := obj.protected.set(headerEncryption, ctx.contentAlg) - if err != nil { - return nil, err - } - - obj.recipients = make([]recipientInfo, len(ctx.recipients)) - - if len(ctx.recipients) == 0 { - return nil, fmt.Errorf("go-jose/go-jose: no recipients to encrypt to") - } - - cek, headers, err := ctx.keyGenerator.genKey() - if err != nil { - return nil, err - } - - obj.protected.merge(&headers) - - for i, info := range ctx.recipients { - recipient, err := info.keyEncrypter.encryptKey(cek, info.keyAlg) - if err != nil { - return nil, err - } - - err = recipient.header.set(headerAlgorithm, info.keyAlg) - if err != nil { - return nil, err - } - - if info.keyID != "" { - err = recipient.header.set(headerKeyID, info.keyID) - if err != nil { - return nil, err - } - } - obj.recipients[i] = recipient - } - - if len(ctx.recipients) == 1 { - // Move per-recipient headers into main protected header if there's - // only a single recipient. - obj.protected.merge(obj.recipients[0].header) - obj.recipients[0].header = nil - } - - if ctx.compressionAlg != NONE { - plaintext, err = compress(ctx.compressionAlg, plaintext) - if err != nil { - return nil, err - } - - err = obj.protected.set(headerCompression, ctx.compressionAlg) - if err != nil { - return nil, err - } - } - - for k, v := range ctx.extraHeaders { - b, err := json.Marshal(v) - if err != nil { - return nil, err - } - (*obj.protected)[k] = makeRawMessage(b) - } - - authData := obj.computeAuthData() - parts, err := ctx.cipher.encrypt(cek, authData, plaintext) - if err != nil { - return nil, err - } - - obj.iv = parts.iv - obj.ciphertext = parts.ciphertext - obj.tag = parts.tag - - return obj, nil -} - -func (ctx *genericEncrypter) Options() EncrypterOptions { - return EncrypterOptions{ - Compression: ctx.compressionAlg, - ExtraHeaders: ctx.extraHeaders, - } -} - -// Decrypt and validate the object and return the plaintext. This -// function does not support multi-recipient. If you desire multi-recipient -// decryption use DecryptMulti instead. -// -// The decryptionKey argument must contain a private or symmetric key -// and must have one of these types: -// - *ecdsa.PrivateKey -// - *rsa.PrivateKey -// - *JSONWebKey -// - JSONWebKey -// - *JSONWebKeySet -// - JSONWebKeySet -// - []byte (a symmetric key) -// - string (a symmetric key) -// - Any type that satisfies the OpaqueKeyDecrypter interface. -// -// Note that ed25519 is only available for signatures, not encryption, so is -// not an option here. -// -// Automatically decompresses plaintext, but returns an error if the decompressed -// data would be >250kB or >10x the size of the compressed data, whichever is larger. -func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) { - headers := obj.mergedHeaders(nil) - - if len(obj.recipients) > 1 { - return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one") - } - - critical, err := headers.getCritical() - if err != nil { - return nil, fmt.Errorf("go-jose/go-jose: invalid crit header") - } - - if len(critical) > 0 { - return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") - } - - key, err := tryJWKS(decryptionKey, obj.Header) - if err != nil { - return nil, err - } - decrypter, err := newDecrypter(key) - if err != nil { - return nil, err - } - - cipher := getContentCipher(headers.getEncryption()) - if cipher == nil { - return nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(headers.getEncryption())) - } - - generator := randomKeyGenerator{ - size: cipher.keySize(), - } - - parts := &aeadParts{ - iv: obj.iv, - ciphertext: obj.ciphertext, - tag: obj.tag, - } - - authData := obj.computeAuthData() - - var plaintext []byte - recipient := obj.recipients[0] - recipientHeaders := obj.mergedHeaders(&recipient) - - cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator) - if err == nil { - // Found a valid CEK -- let's try to decrypt. - plaintext, err = cipher.decrypt(cek, authData, parts) - } - - if plaintext == nil { - return nil, ErrCryptoFailure - } - - // The "zip" header parameter may only be present in the protected header. - if comp := obj.protected.getCompression(); comp != "" { - plaintext, err = decompress(comp, plaintext) - if err != nil { - return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err) - } - } - - return plaintext, nil -} - -// DecryptMulti decrypts and validates the object and returns the plaintexts, -// with support for multiple recipients. It returns the index of the recipient -// for which the decryption was successful, the merged headers for that recipient, -// and the plaintext. -// -// The decryptionKey argument must have one of the types allowed for the -// decryptionKey argument of Decrypt(). -// -// Automatically decompresses plaintext, but returns an error if the decompressed -// data would be >250kB or >3x the size of the compressed data, whichever is larger. -func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) { - globalHeaders := obj.mergedHeaders(nil) - - critical, err := globalHeaders.getCritical() - if err != nil { - return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header") - } - - if len(critical) > 0 { - return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header") - } - - key, err := tryJWKS(decryptionKey, obj.Header) - if err != nil { - return -1, Header{}, nil, err - } - decrypter, err := newDecrypter(key) - if err != nil { - return -1, Header{}, nil, err - } - - encryption := globalHeaders.getEncryption() - cipher := getContentCipher(encryption) - if cipher == nil { - return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(encryption)) - } - - generator := randomKeyGenerator{ - size: cipher.keySize(), - } - - parts := &aeadParts{ - iv: obj.iv, - ciphertext: obj.ciphertext, - tag: obj.tag, - } - - authData := obj.computeAuthData() - - index := -1 - var plaintext []byte - var headers rawHeader - - for i, recipient := range obj.recipients { - recipientHeaders := obj.mergedHeaders(&recipient) - - cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator) - if err == nil { - // Found a valid CEK -- let's try to decrypt. - plaintext, err = cipher.decrypt(cek, authData, parts) - if err == nil { - index = i - headers = recipientHeaders - break - } - } - } - - if plaintext == nil { - return -1, Header{}, nil, ErrCryptoFailure - } - - // The "zip" header parameter may only be present in the protected header. - if comp := obj.protected.getCompression(); comp != "" { - plaintext, err = decompress(comp, plaintext) - if err != nil { - return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err) - } - } - - sanitized, err := headers.sanitized() - if err != nil { - return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to sanitize header: %v", err) - } - - return index, sanitized, plaintext, err -} diff --git a/vendor/github.com/go-jose/go-jose/v4/doc.go b/vendor/github.com/go-jose/go-jose/v4/doc.go deleted file mode 100644 index 0ad40ca0..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/doc.go +++ /dev/null @@ -1,25 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -Package jose aims to provide an implementation of the Javascript Object Signing -and Encryption set of standards. It implements encryption and signing based on -the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web -Token support available in a sub-package. The library supports both the compact -and JWS/JWE JSON Serialization formats, and has optional support for multiple -recipients. -*/ -package jose diff --git a/vendor/github.com/go-jose/go-jose/v4/encoding.go b/vendor/github.com/go-jose/go-jose/v4/encoding.go deleted file mode 100644 index 4f6e0d4a..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/encoding.go +++ /dev/null @@ -1,228 +0,0 @@ -/*- - * Copyright 2014 Square Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package jose - -import ( - "bytes" - "compress/flate" - "encoding/base64" - "encoding/binary" - "fmt" - "io" - "math/big" - "strings" - "unicode" - - "github.com/go-jose/go-jose/v4/json" -) - -// Helper function to serialize known-good objects. -// Precondition: value is not a nil pointer. -func mustSerializeJSON(value interface{}) []byte { - out, err := json.Marshal(value) - if err != nil { - panic(err) - } - // We never want to serialize the top-level value "null," since it's not a - // valid JOSE message. But if a caller passes in a nil pointer to this method, - // MarshalJSON will happily serialize it as the top-level value "null". If - // that value is then embedded in another operation, for instance by being - // base64-encoded and fed as input to a signing algorithm - // (https://github.com/go-jose/go-jose/issues/22), the result will be - // incorrect. Because this method is intended for known-good objects, and a nil - // pointer is not a known-good object, we are free to panic in this case. - // Note: It's not possible to directly check whether the data pointed at by an - // interface is a nil pointer, so we do this hacky workaround. - // https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I - if string(out) == "null" { - panic("Tried to serialize a nil pointer.") - } - return out -} - -// Strip all newlines and whitespace -func stripWhitespace(data string) string { - buf := strings.Builder{} - buf.Grow(len(data)) - for _, r := range data { - if !unicode.IsSpace(r) { - buf.WriteRune(r) - } - } - return buf.String() -} - -// Perform compression based on algorithm -func compress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { - switch algorithm { - case DEFLATE: - return deflate(input) - default: - return nil, ErrUnsupportedAlgorithm - } -} - -// Perform decompression based on algorithm -func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { - switch algorithm { - case DEFLATE: - return inflate(input) - default: - return nil, ErrUnsupportedAlgorithm - } -} - -// deflate compresses the input. -func deflate(input []byte) ([]byte, error) { - output := new(bytes.Buffer) - - // Writing to byte buffer, err is always nil - writer, _ := flate.NewWriter(output, 1) - _, _ = io.Copy(writer, bytes.NewBuffer(input)) - - err := writer.Close() - return output.Bytes(), err -} - -// inflate decompresses the input. -// -// Errors if the decompressed data would be >250kB or >10x the size of the -// compressed data, whichever is larger. -func inflate(input []byte) ([]byte, error) { - output := new(bytes.Buffer) - reader := flate.NewReader(bytes.NewBuffer(input)) - - maxCompressedSize := max(250_000, 10*int64(len(input))) - - limit := maxCompressedSize + 1 - n, err := io.CopyN(output, reader, limit) - if err != nil && err != io.EOF { - return nil, err - } - if n == limit { - return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize) - } - - err = reader.Close() - return output.Bytes(), err -} - -// byteBuffer represents a slice of bytes that can be serialized to url-safe base64. -type byteBuffer struct { - data []byte -} - -func newBuffer(data []byte) *byteBuffer { - if data == nil { - return nil - } - return &byteBuffer{ - data: data, - } -} - -func newFixedSizeBuffer(data []byte, length int) *byteBuffer { - if len(data) > length { - panic("go-jose/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)") - } - pad := make([]byte, length-len(data)) - return newBuffer(append(pad, data...)) -} - -func newBufferFromInt(num uint64) *byteBuffer { - data := make([]byte, 8) - binary.BigEndian.PutUint64(data, num) - return newBuffer(bytes.TrimLeft(data, "\x00")) -} - -func (b *byteBuffer) MarshalJSON() ([]byte, error) { - return json.Marshal(b.base64()) -} - -func (b *byteBuffer) UnmarshalJSON(data []byte) error { - var encoded string - err := json.Unmarshal(data, &encoded) - if err != nil { - return err - } - - if encoded == "" { - return nil - } - - decoded, err := base64.RawURLEncoding.DecodeString(encoded) - if err != nil { - return err - } - - *b = *newBuffer(decoded) - - return nil -} - -func (b *byteBuffer) base64() string { - return base64.RawURLEncoding.EncodeToString(b.data) -} - -func (b *byteBuffer) bytes() []byte { - // Handling nil here allows us to transparently handle nil slices when serializing. - if b == nil { - return nil - } - return b.data -} - -func (b byteBuffer) bigInt() *big.Int { - return new(big.Int).SetBytes(b.data) -} - -func (b byteBuffer) toInt() int { - return int(b.bigInt().Int64()) -} - -func base64EncodeLen(sl []byte) int { - return base64.RawURLEncoding.EncodedLen(len(sl)) -} - -func base64JoinWithDots(inputs ...[]byte) string { - if len(inputs) == 0 { - return "" - } - - // Count of dots. - totalCount := len(inputs) - 1 - - for _, input := range inputs { - totalCount += base64EncodeLen(input) - } - - out := make([]byte, totalCount) - startEncode := 0 - for i, input := range inputs { - base64.RawURLEncoding.Encode(out[startEncode:], input) - - if i == len(inputs)-1 { - continue - } - - startEncode += base64EncodeLen(input) - out[startEncode] = '.' - startEncode++ - } - - return string(out) -} diff --git a/vendor/github.com/go-jose/go-jose/v4/json/LICENSE b/vendor/github.com/go-jose/go-jose/v4/json/LICENSE deleted file mode 100644 index 74487567..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/json/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/go-jose/go-jose/v4/json/README.md b/vendor/github.com/go-jose/go-jose/v4/json/README.md deleted file mode 100644 index 86de5e55..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/json/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Safe JSON - -This repository contains a fork of the `encoding/json` package from Go 1.6. - -The following changes were made: - -* Object deserialization uses case-sensitive member name matching instead of - [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html). - This is to avoid differences in the interpretation of JOSE messages between - go-jose and libraries written in other languages. -* When deserializing a JSON object, we check for duplicate keys and reject the - input whenever we detect a duplicate. Rather than trying to work with malformed - data, we prefer to reject it right away. diff --git a/vendor/github.com/go-jose/go-jose/v4/json/decode.go b/vendor/github.com/go-jose/go-jose/v4/json/decode.go deleted file mode 100644 index 50634dd8..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/json/decode.go +++ /dev/null @@ -1,1216 +0,0 @@ -// Copyright 2010 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. - -// Represents JSON data structure using native Go types: booleans, floats, -// strings, arrays, and maps. - -package json - -import ( - "bytes" - "encoding" - "encoding/base64" - "errors" - "fmt" - "math" - "reflect" - "runtime" - "strconv" - "unicode" - "unicode/utf16" - "unicode/utf8" -) - -// Unmarshal parses the JSON-encoded data and stores the result -// in the value pointed to by v. -// -// Unmarshal uses the inverse of the encodings that -// Marshal uses, allocating maps, slices, and pointers as necessary, -// with the following additional rules: -// -// To unmarshal JSON into a pointer, Unmarshal first handles the case of -// the JSON being the JSON literal null. In that case, Unmarshal sets -// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into -// the value pointed at by the pointer. If the pointer is nil, Unmarshal -// allocates a new value for it to point to. -// -// To unmarshal JSON into a struct, Unmarshal matches incoming object -// keys to the keys used by Marshal (either the struct field name or its tag), -// preferring an exact match but also accepting a case-insensitive match. -// Unmarshal will only set exported fields of the struct. -// -// To unmarshal JSON into an interface value, -// Unmarshal stores one of these in the interface value: -// -// bool, for JSON booleans -// float64, for JSON numbers -// string, for JSON strings -// []interface{}, for JSON arrays -// map[string]interface{}, for JSON objects -// nil for JSON null -// -// To unmarshal a JSON array into a slice, Unmarshal resets the slice length -// to zero and then appends each element to the slice. -// As a special case, to unmarshal an empty JSON array into a slice, -// Unmarshal replaces the slice with a new empty slice. -// -// To unmarshal a JSON array into a Go array, Unmarshal decodes -// JSON array elements into corresponding Go array elements. -// If the Go array is smaller than the JSON array, -// the additional JSON array elements are discarded. -// If the JSON array is smaller than the Go array, -// the additional Go array elements are set to zero values. -// -// To unmarshal a JSON object into a string-keyed map, Unmarshal first -// establishes a map to use, If the map is nil, Unmarshal allocates a new map. -// Otherwise Unmarshal reuses the existing map, keeping existing entries. -// Unmarshal then stores key-value pairs from the JSON object into the map. -// -// If a JSON value is not appropriate for a given target type, -// or if a JSON number overflows the target type, Unmarshal -// skips that field and completes the unmarshaling as best it can. -// If no more serious errors are encountered, Unmarshal returns -// an UnmarshalTypeError describing the earliest such error. -// -// The JSON null value unmarshals into an interface, map, pointer, or slice -// by setting that Go value to nil. Because null is often used in JSON to mean -// “not present,” unmarshaling a JSON null into any other Go type has no effect -// on the value and produces no error. -// -// When unmarshaling quoted strings, invalid UTF-8 or -// invalid UTF-16 surrogate pairs are not treated as an error. -// Instead, they are replaced by the Unicode replacement -// character U+FFFD. -func Unmarshal(data []byte, v interface{}) error { - // Check for well-formedness. - // Avoids filling out half a data structure - // before discovering a JSON syntax error. - var d decodeState - err := checkValid(data, &d.scan) - if err != nil { - return err - } - - d.init(data) - return d.unmarshal(v) -} - -// Unmarshaler is the interface implemented by objects -// that can unmarshal a JSON description of themselves. -// The input can be assumed to be a valid encoding of -// a JSON value. UnmarshalJSON must copy the JSON data -// if it wishes to retain the data after returning. -type Unmarshaler interface { - UnmarshalJSON([]byte) error -} - -// An UnmarshalTypeError describes a JSON value that was -// not appropriate for a value of a specific Go type. -type UnmarshalTypeError struct { - Value string // description of JSON value - "bool", "array", "number -5" - Type reflect.Type // type of Go value it could not be assigned to - Offset int64 // error occurred after reading Offset bytes -} - -func (e *UnmarshalTypeError) Error() string { - return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() -} - -// An UnmarshalFieldError describes a JSON object key that -// led to an unexported (and therefore unwritable) struct field. -// (No longer used; kept for compatibility.) -type UnmarshalFieldError struct { - Key string - Type reflect.Type - Field reflect.StructField -} - -func (e *UnmarshalFieldError) Error() string { - return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() -} - -// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. -// (The argument to Unmarshal must be a non-nil pointer.) -type InvalidUnmarshalError struct { - Type reflect.Type -} - -func (e *InvalidUnmarshalError) Error() string { - if e.Type == nil { - return "json: Unmarshal(nil)" - } - - if e.Type.Kind() != reflect.Ptr { - return "json: Unmarshal(non-pointer " + e.Type.String() + ")" - } - return "json: Unmarshal(nil " + e.Type.String() + ")" -} - -func (d *decodeState) unmarshal(v interface{}) (err error) { - defer func() { - if r := recover(); r != nil { - if _, ok := r.(runtime.Error); ok { - panic(r) - } - err = r.(error) - } - }() - - rv := reflect.ValueOf(v) - if rv.Kind() != reflect.Ptr || rv.IsNil() { - return &InvalidUnmarshalError{reflect.TypeOf(v)} - } - - d.scan.reset() - // We decode rv not rv.Elem because the Unmarshaler interface - // test must be applied at the top level of the value. - d.value(rv) - return d.savedError -} - -// A Number represents a JSON number literal. -type Number string - -// String returns the literal text of the number. -func (n Number) String() string { return string(n) } - -// Float64 returns the number as a float64. -func (n Number) Float64() (float64, error) { - return strconv.ParseFloat(string(n), 64) -} - -// Int64 returns the number as an int64. -func (n Number) Int64() (int64, error) { - return strconv.ParseInt(string(n), 10, 64) -} - -// isValidNumber reports whether s is a valid JSON number literal. -func isValidNumber(s string) bool { - // This function implements the JSON numbers grammar. - // See https://tools.ietf.org/html/rfc7159#section-6 - // and http://json.org/number.gif - - if s == "" { - return false - } - - // Optional - - if s[0] == '-' { - s = s[1:] - if s == "" { - return false - } - } - - // Digits - switch { - default: - return false - - case s[0] == '0': - s = s[1:] - - case '1' <= s[0] && s[0] <= '9': - s = s[1:] - for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - s = s[1:] - } - } - - // . followed by 1 or more digits. - if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' { - s = s[2:] - for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - s = s[1:] - } - } - - // e or E followed by an optional - or + and - // 1 or more digits. - if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { - s = s[1:] - if s[0] == '+' || s[0] == '-' { - s = s[1:] - if s == "" { - return false - } - } - for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { - s = s[1:] - } - } - - // Make sure we are at the end. - return s == "" -} - -type NumberUnmarshalType int - -const ( - // unmarshal a JSON number into an interface{} as a float64 - UnmarshalFloat NumberUnmarshalType = iota - // unmarshal a JSON number into an interface{} as a `json.Number` - UnmarshalJSONNumber - // unmarshal a JSON number into an interface{} as a int64 - // if value is an integer otherwise float64 - UnmarshalIntOrFloat -) - -// decodeState represents the state while decoding a JSON value. -type decodeState struct { - data []byte - off int // read offset in data - scan scanner - nextscan scanner // for calls to nextValue - savedError error - numberType NumberUnmarshalType -} - -// errPhase is used for errors that should not happen unless -// there is a bug in the JSON decoder or something is editing -// the data slice while the decoder executes. -var errPhase = errors.New("JSON decoder out of sync - data changing underfoot?") - -func (d *decodeState) init(data []byte) *decodeState { - d.data = data - d.off = 0 - d.savedError = nil - return d -} - -// error aborts the decoding by panicking with err. -func (d *decodeState) error(err error) { - panic(err) -} - -// saveError saves the first err it is called with, -// for reporting at the end of the unmarshal. -func (d *decodeState) saveError(err error) { - if d.savedError == nil { - d.savedError = err - } -} - -// next cuts off and returns the next full JSON value in d.data[d.off:]. -// The next value is known to be an object or array, not a literal. -func (d *decodeState) next() []byte { - c := d.data[d.off] - item, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) - } - d.off = len(d.data) - len(rest) - - // Our scanner has seen the opening brace/bracket - // and thinks we're still in the middle of the object. - // invent a closing brace/bracket to get it out. - if c == '{' { - d.scan.step(&d.scan, '}') - } else { - d.scan.step(&d.scan, ']') - } - - return item -} - -// scanWhile processes bytes in d.data[d.off:] until it -// receives a scan code not equal to op. -// It updates d.off and returns the new scan code. -func (d *decodeState) scanWhile(op int) int { - var newOp int - for { - if d.off >= len(d.data) { - newOp = d.scan.eof() - d.off = len(d.data) + 1 // mark processed EOF with len+1 - } else { - c := d.data[d.off] - d.off++ - newOp = d.scan.step(&d.scan, c) - } - if newOp != op { - break - } - } - return newOp -} - -// value decodes a JSON value from d.data[d.off:] into the value. -// it updates d.off to point past the decoded value. -func (d *decodeState) value(v reflect.Value) { - if !v.IsValid() { - _, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) - } - d.off = len(d.data) - len(rest) - - // d.scan thinks we're still at the beginning of the item. - // Feed in an empty string - the shortest, simplest value - - // so that it knows we got to the end of the value. - if d.scan.redo { - // rewind. - d.scan.redo = false - d.scan.step = stateBeginValue - } - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '"') - - n := len(d.scan.parseState) - if n > 0 && d.scan.parseState[n-1] == parseObjectKey { - // d.scan thinks we just read an object key; finish the object - d.scan.step(&d.scan, ':') - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '}') - } - - return - } - - switch op := d.scanWhile(scanSkipSpace); op { - default: - d.error(errPhase) - - case scanBeginArray: - d.array(v) - - case scanBeginObject: - d.object(v) - - case scanBeginLiteral: - d.literal(v) - } -} - -type unquotedValue struct{} - -// valueQuoted is like value but decodes a -// quoted string literal or literal null into an interface value. -// If it finds anything other than a quoted string literal or null, -// valueQuoted returns unquotedValue{}. -func (d *decodeState) valueQuoted() interface{} { - switch op := d.scanWhile(scanSkipSpace); op { - default: - d.error(errPhase) - - case scanBeginArray: - d.array(reflect.Value{}) - - case scanBeginObject: - d.object(reflect.Value{}) - - case scanBeginLiteral: - switch v := d.literalInterface().(type) { - case nil, string: - return v - } - } - return unquotedValue{} -} - -// indirect walks down v allocating pointers as needed, -// until it gets to a non-pointer. -// if it encounters an Unmarshaler, indirect stops and returns that. -// if decodingNull is true, indirect stops at the last pointer so it can be set to nil. -func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { - // If v is a named type and is addressable, - // start with its address, so that if the type has pointer methods, - // we find them. - if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { - v = v.Addr() - } - for { - // Load value from interface, but only if the result will be - // usefully addressable. - if v.Kind() == reflect.Interface && !v.IsNil() { - e := v.Elem() - if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { - v = e - continue - } - } - - if v.Kind() != reflect.Ptr { - break - } - - if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { - break - } - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - if v.Type().NumMethod() > 0 { - if u, ok := v.Interface().(Unmarshaler); ok { - return u, nil, reflect.Value{} - } - if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { - return nil, u, reflect.Value{} - } - } - v = v.Elem() - } - return nil, nil, v -} - -// array consumes an array from d.data[d.off-1:], decoding into the value v. -// the first byte of the array ('[') has been read already. -func (d *decodeState) array(v reflect.Value) { - // Check for unmarshaler. - u, ut, pv := d.indirect(v, false) - if u != nil { - d.off-- - err := u.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return - } - if ut != nil { - d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)}) - d.off-- - d.next() - return - } - - v = pv - - // Check type of target. - switch v.Kind() { - case reflect.Interface: - if v.NumMethod() == 0 { - // Decoding into nil interface? Switch to non-reflect code. - v.Set(reflect.ValueOf(d.arrayInterface())) - return - } - // Otherwise it's invalid. - fallthrough - default: - d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)}) - d.off-- - d.next() - return - case reflect.Array: - case reflect.Slice: - break - } - - i := 0 - for { - // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - - // Get element of array, growing if necessary. - if v.Kind() == reflect.Slice { - // Grow slice if necessary - if i >= v.Cap() { - newcap := v.Cap() + v.Cap()/2 - if newcap < 4 { - newcap = 4 - } - newv := reflect.MakeSlice(v.Type(), v.Len(), newcap) - reflect.Copy(newv, v) - v.Set(newv) - } - if i >= v.Len() { - v.SetLen(i + 1) - } - } - - if i < v.Len() { - // Decode into element. - d.value(v.Index(i)) - } else { - // Ran out of fixed array: skip. - d.value(reflect.Value{}) - } - i++ - - // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - if op != scanArrayValue { - d.error(errPhase) - } - } - - if i < v.Len() { - if v.Kind() == reflect.Array { - // Array. Zero the rest. - z := reflect.Zero(v.Type().Elem()) - for ; i < v.Len(); i++ { - v.Index(i).Set(z) - } - } else { - v.SetLen(i) - } - } - if i == 0 && v.Kind() == reflect.Slice { - v.Set(reflect.MakeSlice(v.Type(), 0, 0)) - } -} - -var nullLiteral = []byte("null") - -// object consumes an object from d.data[d.off-1:], decoding into the value v. -// the first byte ('{') of the object has been read already. -func (d *decodeState) object(v reflect.Value) { - // Check for unmarshaler. - u, ut, pv := d.indirect(v, false) - if u != nil { - d.off-- - err := u.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return - } - if ut != nil { - d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)}) - d.off-- - d.next() // skip over { } in input - return - } - v = pv - - // Decoding into nil interface? Switch to non-reflect code. - if v.Kind() == reflect.Interface && v.NumMethod() == 0 { - v.Set(reflect.ValueOf(d.objectInterface())) - return - } - - // Check type of target: struct or map[string]T - switch v.Kind() { - case reflect.Map: - // map must have string kind - t := v.Type() - if t.Key().Kind() != reflect.String { - d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)}) - d.off-- - d.next() // skip over { } in input - return - } - if v.IsNil() { - v.Set(reflect.MakeMap(t)) - } - case reflect.Struct: - - default: - d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)}) - d.off-- - d.next() // skip over { } in input - return - } - - var mapElem reflect.Value - keys := map[string]bool{} - - for { - // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { - // closing } - can only happen on first iteration. - break - } - if op != scanBeginLiteral { - d.error(errPhase) - } - - // Read key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] - key, ok := unquote(item) - if !ok { - d.error(errPhase) - } - - // Check for duplicate keys. - _, ok = keys[key] - if !ok { - keys[key] = true - } else { - d.error(fmt.Errorf("json: duplicate key '%s' in object", key)) - } - - // Figure out field corresponding to key. - var subv reflect.Value - destring := false // whether the value is wrapped in a string to be decoded first - - if v.Kind() == reflect.Map { - elemType := v.Type().Elem() - if !mapElem.IsValid() { - mapElem = reflect.New(elemType).Elem() - } else { - mapElem.Set(reflect.Zero(elemType)) - } - subv = mapElem - } else { - var f *field - fields := cachedTypeFields(v.Type()) - for i := range fields { - ff := &fields[i] - if bytes.Equal(ff.nameBytes, []byte(key)) { - f = ff - break - } - } - if f != nil { - subv = v - destring = f.quoted - for _, i := range f.index { - if subv.Kind() == reflect.Ptr { - if subv.IsNil() { - subv.Set(reflect.New(subv.Type().Elem())) - } - subv = subv.Elem() - } - subv = subv.Field(i) - } - } - } - - // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) - } - if op != scanObjectKey { - d.error(errPhase) - } - - // Read value. - if destring { - switch qv := d.valueQuoted().(type) { - case nil: - d.literalStore(nullLiteral, subv, false) - case string: - d.literalStore([]byte(qv), subv, true) - default: - d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) - } - } else { - d.value(subv) - } - - // Write value back to map; - // if using struct, subv points into struct already. - if v.Kind() == reflect.Map { - kv := reflect.ValueOf(key).Convert(v.Type().Key()) - v.SetMapIndex(kv, subv) - } - - // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { - break - } - if op != scanObjectValue { - d.error(errPhase) - } - } -} - -// literal consumes a literal from d.data[d.off-1:], decoding into the value v. -// The first byte of the literal has been read already -// (that's how the caller knows it's a literal). -func (d *decodeState) literal(v reflect.Value) { - // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) - - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - - d.literalStore(d.data[start:d.off], v, false) -} - -// convertNumber converts the number literal s to a float64, int64 or a Number -// depending on d.numberDecodeType. -func (d *decodeState) convertNumber(s string) (interface{}, error) { - switch d.numberType { - - case UnmarshalJSONNumber: - return Number(s), nil - case UnmarshalIntOrFloat: - v, err := strconv.ParseInt(s, 10, 64) - if err == nil { - return v, nil - } - - // tries to parse integer number in scientific notation - f, err := strconv.ParseFloat(s, 64) - if err != nil { - return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)} - } - - // if it has no decimal value use int64 - if fi, fd := math.Modf(f); fd == 0.0 { - return int64(fi), nil - } - return f, nil - default: - f, err := strconv.ParseFloat(s, 64) - if err != nil { - return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)} - } - return f, nil - } - -} - -var numberType = reflect.TypeOf(Number("")) - -// literalStore decodes a literal stored in item into v. -// -// fromQuoted indicates whether this literal came from unwrapping a -// string from the ",string" struct tag option. this is used only to -// produce more helpful error messages. -func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) { - // Check for unmarshaler. - if len(item) == 0 { - //Empty string given - d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - return - } - wantptr := item[0] == 'n' // null - u, ut, pv := d.indirect(v, wantptr) - if u != nil { - err := u.UnmarshalJSON(item) - if err != nil { - d.error(err) - } - return - } - if ut != nil { - if item[0] != '"' { - if fromQuoted { - d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) - } - return - } - s, ok := unquoteBytes(item) - if !ok { - if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(errPhase) - } - } - err := ut.UnmarshalText(s) - if err != nil { - d.error(err) - } - return - } - - v = pv - - switch c := item[0]; c { - case 'n': // null - switch v.Kind() { - case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: - v.Set(reflect.Zero(v.Type())) - // otherwise, ignore null for primitives/string - } - case 't', 'f': // true, false - value := c == 't' - switch v.Kind() { - default: - if fromQuoted { - d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)}) - } - case reflect.Bool: - v.SetBool(value) - case reflect.Interface: - if v.NumMethod() == 0 { - v.Set(reflect.ValueOf(value)) - } else { - d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)}) - } - } - - case '"': // string - s, ok := unquoteBytes(item) - if !ok { - if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(errPhase) - } - } - switch v.Kind() { - default: - d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) - case reflect.Slice: - if v.Type().Elem().Kind() != reflect.Uint8 { - d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) - break - } - b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) - n, err := base64.StdEncoding.Decode(b, s) - if err != nil { - d.saveError(err) - break - } - v.SetBytes(b[:n]) - case reflect.String: - v.SetString(string(s)) - case reflect.Interface: - if v.NumMethod() == 0 { - v.Set(reflect.ValueOf(string(s))) - } else { - d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) - } - } - - default: // number - if c != '-' && (c < '0' || c > '9') { - if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(errPhase) - } - } - s := string(item) - switch v.Kind() { - default: - if v.Kind() == reflect.String && v.Type() == numberType { - v.SetString(s) - if !isValidNumber(s) { - d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)) - } - break - } - if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) - } - case reflect.Interface: - n, err := d.convertNumber(s) - if err != nil { - d.saveError(err) - break - } - if v.NumMethod() != 0 { - d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) - break - } - v.Set(reflect.ValueOf(n)) - - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - n, err := strconv.ParseInt(s, 10, 64) - if err != nil || v.OverflowInt(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)}) - break - } - v.SetInt(n) - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - n, err := strconv.ParseUint(s, 10, 64) - if err != nil || v.OverflowUint(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)}) - break - } - v.SetUint(n) - - case reflect.Float32, reflect.Float64: - n, err := strconv.ParseFloat(s, v.Type().Bits()) - if err != nil || v.OverflowFloat(n) { - d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)}) - break - } - v.SetFloat(n) - } - } -} - -// The xxxInterface routines build up a value to be stored -// in an empty interface. They are not strictly necessary, -// but they avoid the weight of reflection in this common case. - -// valueInterface is like value but returns interface{} -func (d *decodeState) valueInterface() interface{} { - switch d.scanWhile(scanSkipSpace) { - default: - d.error(errPhase) - panic("unreachable") - case scanBeginArray: - return d.arrayInterface() - case scanBeginObject: - return d.objectInterface() - case scanBeginLiteral: - return d.literalInterface() - } -} - -// arrayInterface is like array but returns []interface{}. -func (d *decodeState) arrayInterface() []interface{} { - var v = make([]interface{}, 0) - for { - // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - - v = append(v, d.valueInterface()) - - // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { - break - } - if op != scanArrayValue { - d.error(errPhase) - } - } - return v -} - -// objectInterface is like object but returns map[string]interface{}. -func (d *decodeState) objectInterface() map[string]interface{} { - m := make(map[string]interface{}) - keys := map[string]bool{} - - for { - // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { - // closing } - can only happen on first iteration. - break - } - if op != scanBeginLiteral { - d.error(errPhase) - } - - // Read string key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] - key, ok := unquote(item) - if !ok { - d.error(errPhase) - } - - // Check for duplicate keys. - _, ok = keys[key] - if !ok { - keys[key] = true - } else { - d.error(fmt.Errorf("json: duplicate key '%s' in object", key)) - } - - // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) - } - if op != scanObjectKey { - d.error(errPhase) - } - - // Read value. - m[key] = d.valueInterface() - - // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { - break - } - if op != scanObjectValue { - d.error(errPhase) - } - } - return m -} - -// literalInterface is like literal but returns an interface value. -func (d *decodeState) literalInterface() interface{} { - // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) - - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - item := d.data[start:d.off] - - switch c := item[0]; c { - case 'n': // null - return nil - - case 't', 'f': // true, false - return c == 't' - - case '"': // string - s, ok := unquote(item) - if !ok { - d.error(errPhase) - } - return s - - default: // number - if c != '-' && (c < '0' || c > '9') { - d.error(errPhase) - } - n, err := d.convertNumber(string(item)) - if err != nil { - d.saveError(err) - } - return n - } -} - -// getu4 decodes \uXXXX from the beginning of s, returning the hex value, -// or it returns -1. -func getu4(s []byte) rune { - if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { - return -1 - } - r, err := strconv.ParseUint(string(s[2:6]), 16, 64) - if err != nil { - return -1 - } - return rune(r) -} - -// unquote converts a quoted JSON string literal s into an actual string t. -// The rules are different than for Go, so cannot use strconv.Unquote. -func unquote(s []byte) (t string, ok bool) { - s, ok = unquoteBytes(s) - t = string(s) - return -} - -func unquoteBytes(s []byte) (t []byte, ok bool) { - if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { - return - } - s = s[1 : len(s)-1] - - // Check for unusual characters. If there are none, - // then no unquoting is needed, so return a slice of the - // original bytes. - r := 0 - for r < len(s) { - c := s[r] - if c == '\\' || c == '"' || c < ' ' { - break - } - if c < utf8.RuneSelf { - r++ - continue - } - rr, size := utf8.DecodeRune(s[r:]) - if rr == utf8.RuneError && size == 1 { - break - } - r += size - } - if r == len(s) { - return s, true - } - - b := make([]byte, len(s)+2*utf8.UTFMax) - w := copy(b, s[0:r]) - for r < len(s) { - // Out of room? Can only happen if s is full of - // malformed UTF-8 and we're replacing each - // byte with RuneError. - if w >= len(b)-2*utf8.UTFMax { - nb := make([]byte, (len(b)+utf8.UTFMax)*2) - copy(nb, b[0:w]) - b = nb - } - switch c := s[r]; { - case c == '\\': - r++ - if r >= len(s) { - return - } - switch s[r] { - default: - return - case '"', '\\', '/', '\'': - b[w] = s[r] - r++ - w++ - case 'b': - b[w] = '\b' - r++ - w++ - case 'f': - b[w] = '\f' - r++ - w++ - case 'n': - b[w] = '\n' - r++ - w++ - case 'r': - b[w] = '\r' - r++ - w++ - case 't': - b[w] = '\t' - r++ - w++ - case 'u': - r-- - rr := getu4(s[r:]) - if rr < 0 { - return - } - r += 6 - if utf16.IsSurrogate(rr) { - rr1 := getu4(s[r:]) - if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { - // A valid pair; consume. - r += 6 - w += utf8.EncodeRune(b[w:], dec) - break - } - // Invalid surrogate; fall back to replacement rune. - rr = unicode.ReplacementChar - } - w += utf8.EncodeRune(b[w:], rr) - } - - // Quote, control characters are invalid. - case c == '"', c < ' ': - return - - // ASCII - case c < utf8.RuneSelf: - b[w] = c - r++ - w++ - - // Coerce to well-formed UTF-8. - default: - rr, size := utf8.DecodeRune(s[r:]) - r += size - w += utf8.EncodeRune(b[w:], rr) - } - } - return b[0:w], true -} diff --git a/vendor/github.com/go-jose/go-jose/v4/json/encode.go b/vendor/github.com/go-jose/go-jose/v4/json/encode.go deleted file mode 100644 index 98de68ce..00000000 --- a/vendor/github.com/go-jose/go-jose/v4/json/encode.go +++ /dev/null @@ -1,1197 +0,0 @@ -// Copyright 2010 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 json implements encoding and decoding of JSON objects as defined in -// RFC 4627. The mapping between JSON objects and Go values is described -// in the documentation for the Marshal and Unmarshal functions. -// -// See "JSON and Go" for an introduction to this package: -// https://golang.org/doc/articles/json_and_go.html -package json - -import ( - "bytes" - "encoding" - "encoding/base64" - "fmt" - "math" - "reflect" - "runtime" - "sort" - "strconv" - "strings" - "sync" - "unicode" - "unicode/utf8" -) - -// Marshal returns the JSON encoding of v. -// -// Marshal traverses the value v recursively. -// If an encountered value implements the Marshaler interface -// and is not a nil pointer, Marshal calls its MarshalJSON method -// to produce JSON. If no MarshalJSON method is present but the -// value implements encoding.TextMarshaler instead, Marshal calls -// its MarshalText method. -// The nil pointer exception is not strictly necessary -// but mimics a similar, necessary exception in the behavior of -// UnmarshalJSON. -// -// Otherwise, Marshal uses the following type-dependent default encodings: -// -// Boolean values encode as JSON booleans. -// -// Floating point, integer, and Number values encode as JSON numbers. -// -// String values encode as JSON strings coerced to valid UTF-8, -// replacing invalid bytes with the Unicode replacement rune. -// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" -// to keep some browsers from misinterpreting JSON output as HTML. -// Ampersand "&" is also escaped to "\u0026" for the same reason. -// -// Array and slice values encode as JSON arrays, except that -// []byte encodes as a base64-encoded string, and a nil slice -// encodes as the null JSON object. -// -// Struct values encode as JSON objects. Each exported struct field -// becomes a member of the object unless -// - the field's tag is "-", or -// - the field is empty and its tag specifies the "omitempty" option. -// -// The empty values are false, 0, any -// nil pointer or interface value, and any array, slice, map, or string of -// length zero. The object's default key string is the struct field name -// but can be specified in the struct field's tag value. The "json" key in -// the struct field's tag value is the key name, followed by an optional comma -// and options. Examples: -// -// // Field is ignored by this package. -// Field int `json:"-"` -// -// // Field appears in JSON as key "myName". -// Field int `json:"myName"` -// -// // Field appears in JSON as key "myName" and -// // the field is omitted from the object if its value is empty, -// // as defined above. -// Field int `json:"myName,omitempty"` -// -// // Field appears in JSON as key "Field" (the default), but -// // the field is skipped if empty. -// // Note the leading comma. -// Field int `json:",omitempty"` -// -// The "string" option signals that a field is stored as JSON inside a -// JSON-encoded string. It applies only to fields of string, floating point, -// integer, or boolean types. This extra level of encoding is sometimes used -// when communicating with JavaScript programs: -// -// Int64String int64 `json:",string"` -// -// The key name will be used if it's a non-empty string consisting of -// only Unicode letters, digits, dollar signs, percent signs, hyphens, -// underscores and slashes. -// -// Anonymous struct fields are usually marshaled as if their inner exported fields -// were fields in the outer struct, subject to the usual Go visibility rules amended -// as described in the next paragraph. -// An anonymous struct field with a name given in its JSON tag is treated as -// having that name, rather than being anonymous. -// An anonymous struct field of interface type is treated the same as having -// that type as its name, rather than being anonymous. -// -// The Go visibility rules for struct fields are amended for JSON when -// deciding which field to marshal or unmarshal. If there are -// multiple fields at the same level, and that level is the least -// nested (and would therefore be the nesting level selected by the -// usual Go rules), the following extra rules apply: -// -// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered, -// even if there are multiple untagged fields that would otherwise conflict. -// 2) If there is exactly one field (tagged or not according to the first rule), that is selected. -// 3) Otherwise there are multiple fields, and all are ignored; no error occurs. -// -// Handling of anonymous struct fields is new in Go 1.1. -// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of -// an anonymous struct field in both current and earlier versions, give the field -// a JSON tag of "-". -// -// Map values encode as JSON objects. -// The map's key type must be string; the map keys are used as JSON object -// keys, subject to the UTF-8 coercion described for string values above. -// -// Pointer values encode as the value pointed to. -// A nil pointer encodes as the null JSON object. -// -// Interface values encode as the value contained in the interface. -// A nil interface value encodes as the null JSON object. -// -// Channel, complex, and function values cannot be encoded in JSON. -// Attempting to encode such a value causes Marshal to return -// an UnsupportedTypeError. -// -// JSON cannot represent cyclic data structures and Marshal does not -// handle them. Passing cyclic structures to Marshal will result in -// an infinite recursion. -func Marshal(v interface{}) ([]byte, error) { - e := &encodeState{} - err := e.marshal(v) - if err != nil { - return nil, err - } - return e.Bytes(), nil -} - -// MarshalIndent is like Marshal but applies Indent to format the output. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { - b, err := Marshal(v) - if err != nil { - return nil, err - } - var buf bytes.Buffer - err = Indent(&buf, b, prefix, indent) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029 -// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029 -// so that the JSON will be safe to embed inside HTML tag. -func (p *Policy) addDefaultSkipElementContent() { - p.init() - - p.setOfElementsToSkipContent["frame"] = struct{}{} - p.setOfElementsToSkipContent["frameset"] = struct{}{} - p.setOfElementsToSkipContent["iframe"] = struct{}{} - p.setOfElementsToSkipContent["noembed"] = struct{}{} - p.setOfElementsToSkipContent["noframes"] = struct{}{} - p.setOfElementsToSkipContent["noscript"] = struct{}{} - p.setOfElementsToSkipContent["nostyle"] = struct{}{} - p.setOfElementsToSkipContent["object"] = struct{}{} - p.setOfElementsToSkipContent["script"] = struct{}{} - p.setOfElementsToSkipContent["style"] = struct{}{} - p.setOfElementsToSkipContent["title"] = struct{}{} -} diff --git a/vendor/github.com/microcosm-cc/bluemonday/sanitize.go b/vendor/github.com/microcosm-cc/bluemonday/sanitize.go deleted file mode 100644 index 47c31f7d..00000000 --- a/vendor/github.com/microcosm-cc/bluemonday/sanitize.go +++ /dev/null @@ -1,1096 +0,0 @@ -// Copyright (c) 2014, David Kitchen -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * Neither the name of the organisation (Microcosm) nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package bluemonday - -import ( - "bytes" - "fmt" - "io" - "net/url" - "regexp" - "strconv" - "strings" - - "golang.org/x/net/html" - - "github.com/aymerick/douceur/parser" -) - -var ( - dataAttribute = regexp.MustCompile("^data-.+") - dataAttributeXMLPrefix = regexp.MustCompile("^xml.+") - dataAttributeInvalidChars = regexp.MustCompile("[A-Z;]+") - cssUnicodeChar = regexp.MustCompile(`\\[0-9a-f]{1,6} ?`) - dataURIbase64Prefix = regexp.MustCompile(`^data:[^,]*;base64,`) -) - -// Sanitize takes a string that contains a HTML fragment or document and applies -// the given policy allowlist. -// -// It returns a HTML string that has been sanitized by the policy or an empty -// string if an error has occurred (most likely as a consequence of extremely -// malformed input) -func (p *Policy) Sanitize(s string) string { - if strings.TrimSpace(s) == "" { - return s - } - - return p.sanitizeWithBuff(strings.NewReader(s)).String() -} - -// SanitizeBytes takes a []byte that contains a HTML fragment or document and applies -// the given policy allowlist. -// -// It returns a []byte containing the HTML that has been sanitized by the policy -// or an empty []byte if an error has occurred (most likely as a consequence of -// extremely malformed input) -func (p *Policy) SanitizeBytes(b []byte) []byte { - if len(bytes.TrimSpace(b)) == 0 { - return b - } - - return p.sanitizeWithBuff(bytes.NewReader(b)).Bytes() -} - -// SanitizeReader takes an io.Reader that contains a HTML fragment or document -// and applies the given policy allowlist. -// -// It returns a bytes.Buffer containing the HTML that has been sanitized by the -// policy. Errors during sanitization will merely return an empty result. -func (p *Policy) SanitizeReader(r io.Reader) *bytes.Buffer { - return p.sanitizeWithBuff(r) -} - -// SanitizeReaderToWriter takes an io.Reader that contains a HTML fragment or document -// and applies the given policy allowlist and writes to the provided writer returning -// an error if there is one. -func (p *Policy) SanitizeReaderToWriter(r io.Reader, w io.Writer) error { - return p.sanitize(r, w) -} - -// Query represents a single part of the query string, a query param -type Query struct { - Key string - Value string - HasValue bool -} - -func parseQuery(query string) (values []Query, err error) { - // This is essentially a copy of parseQuery from - // https://golang.org/src/net/url/url.go but adjusted to build our values - // based on our type, which we need to preserve the ordering of the query - // string - for query != "" { - key := query - if i := strings.IndexAny(key, "&;"); i >= 0 { - key, query = key[:i], key[i+1:] - } else { - query = "" - } - if key == "" { - continue - } - value := "" - hasValue := false - if i := strings.Index(key, "="); i >= 0 { - key, value = key[:i], key[i+1:] - hasValue = true - } - key, err1 := url.QueryUnescape(key) - if err1 != nil { - if err == nil { - err = err1 - } - continue - } - value, err1 = url.QueryUnescape(value) - if err1 != nil { - if err == nil { - err = err1 - } - continue - } - values = append(values, Query{ - Key: key, - Value: value, - HasValue: hasValue, - }) - } - return values, err -} - -func encodeQueries(queries []Query) string { - var buff bytes.Buffer - for i, query := range queries { - buff.WriteString(url.QueryEscape(query.Key)) - if query.HasValue { - buff.WriteString("=") - buff.WriteString(url.QueryEscape(query.Value)) - } - if i < len(queries)-1 { - buff.WriteString("&") - } - } - return buff.String() -} - -func sanitizedURL(val string) (string, error) { - u, err := url.Parse(val) - if err != nil { - return "", err - } - - // we use parseQuery but not u.Query to keep the order not change because - // url.Values is a map which has a random order. - queryValues, err := parseQuery(u.RawQuery) - if err != nil { - return "", err - } - // sanitize the url query params - for i, query := range queryValues { - queryValues[i].Key = html.EscapeString(query.Key) - } - u.RawQuery = encodeQueries(queryValues) - // u.String() will also sanitize host/scheme/user/pass - return u.String(), nil -} - -// Performs the actual sanitization process. -func (p *Policy) sanitizeWithBuff(r io.Reader) *bytes.Buffer { - var buff bytes.Buffer - if err := p.sanitize(r, &buff); err != nil { - return &bytes.Buffer{} - } - return &buff -} - -type asStringWriter struct { - io.Writer -} - -func (a *asStringWriter) WriteString(s string) (int, error) { - return a.Write([]byte(s)) -} - -func (p *Policy) sanitize(r io.Reader, w io.Writer) error { - // It is possible that the developer has created the policy via: - // p := bluemonday.Policy{} - // rather than: - // p := bluemonday.NewPolicy() - // If this is the case, and if they haven't yet triggered an action that - // would initialize the maps, then we need to do that. - p.init() - - buff, ok := w.(stringWriterWriter) - if !ok { - buff = &asStringWriter{w} - } - - var ( - skipElementContent bool - skippingElementsCount int64 - skipClosingTag bool - closingTagToSkipStack []string - mostRecentlyStartedToken string - ) - - tokenizer := html.NewTokenizer(r) - for { - if tokenizer.Next() == html.ErrorToken { - err := tokenizer.Err() - if err == io.EOF { - // End of input means end of processing - return nil - } - - // Raw tokenizer error - return err - } - - token := tokenizer.Token() - switch token.Type { - case html.DoctypeToken: - - // DocType is not handled as there is no safe parsing mechanism - // provided by golang.org/x/net/html for the content, and this can - // be misused to insert HTML tags that are not then sanitized - // - // One might wish to recursively sanitize here using the same policy - // but I will need to do some further testing before considering - // this. - - case html.CommentToken: - - // Comments are ignored by default - if p.allowComments { - // But if allowed then write the comment out as-is - buff.WriteString(token.String()) - } - - case html.StartTagToken: - - mostRecentlyStartedToken = normaliseElementName(token.Data) - - switch normaliseElementName(token.Data) { - case `script`: - if !p.allowUnsafe { - continue - } - case `style`: - if !p.allowUnsafe { - continue - } - } - - aps, ok := p.elsAndAttrs[token.Data] - if !ok { - aa, matched := p.matchRegex(token.Data) - if !matched { - if _, ok := p.setOfElementsToSkipContent[token.Data]; ok { - skipElementContent = true - skippingElementsCount++ - } - if p.addSpaces { - if _, err := buff.WriteString(" "); err != nil { - return err - } - } - break - } - aps = aa - } - if len(token.Attr) != 0 { - token.Attr = p.sanitizeAttrs(token.Data, token.Attr, aps) - } - - if len(token.Attr) == 0 { - if !p.allowNoAttrs(token.Data) { - skipClosingTag = true - closingTagToSkipStack = append(closingTagToSkipStack, token.Data) - if p.addSpaces { - if _, err := buff.WriteString(" "); err != nil { - return err - } - } - break - } - } - - if !skipElementContent { - if _, err := buff.WriteString(token.String()); err != nil { - return err - } - } - - case html.EndTagToken: - - if mostRecentlyStartedToken == normaliseElementName(token.Data) { - mostRecentlyStartedToken = "" - } - - switch normaliseElementName(token.Data) { - case `script`: - if !p.allowUnsafe { - continue - } - case `style`: - if !p.allowUnsafe { - continue - } - } - - if skipClosingTag && closingTagToSkipStack[len(closingTagToSkipStack)-1] == token.Data { - closingTagToSkipStack = closingTagToSkipStack[:len(closingTagToSkipStack)-1] - if len(closingTagToSkipStack) == 0 { - skipClosingTag = false - } - if p.addSpaces { - if _, err := buff.WriteString(" "); err != nil { - return err - } - } - break - } - if _, ok := p.elsAndAttrs[token.Data]; !ok { - match := false - for regex := range p.elsMatchingAndAttrs { - if regex.MatchString(token.Data) { - skipElementContent = false - match = true - break - } - } - if _, ok := p.setOfElementsToSkipContent[token.Data]; ok && !match { - skippingElementsCount-- - if skippingElementsCount == 0 { - skipElementContent = false - } - } - if !match { - if p.addSpaces { - if _, err := buff.WriteString(" "); err != nil { - return err - } - } - break - } - } - - if !skipElementContent { - if _, err := buff.WriteString(token.String()); err != nil { - return err - } - } - - case html.SelfClosingTagToken: - - switch normaliseElementName(token.Data) { - case `script`: - if !p.allowUnsafe { - continue - } - case `style`: - if !p.allowUnsafe { - continue - } - } - - aps, ok := p.elsAndAttrs[token.Data] - if !ok { - aa, matched := p.matchRegex(token.Data) - if !matched { - if p.addSpaces && !matched { - if _, err := buff.WriteString(" "); err != nil { - return err - } - } - break - } - aps = aa - } - - if len(token.Attr) != 0 { - token.Attr = p.sanitizeAttrs(token.Data, token.Attr, aps) - } - - if len(token.Attr) == 0 && !p.allowNoAttrs(token.Data) { - if p.addSpaces { - if _, err := buff.WriteString(" "); err != nil { - return err - } - } - break - } - if !skipElementContent { - if _, err := buff.WriteString(token.String()); err != nil { - return err - } - } - - case html.TextToken: - - if !skipElementContent { - switch mostRecentlyStartedToken { - case `script`: - // not encouraged, but if a policy allows JavaScript we - // should not HTML escape it as that would break the output - // - // requires p.AllowUnsafe() - if p.allowUnsafe { - if _, err := buff.WriteString(token.Data); err != nil { - return err - } - } - case "style": - // not encouraged, but if a policy allows CSS styles we - // should not HTML escape it as that would break the output - // - // requires p.AllowUnsafe() - if p.allowUnsafe { - if _, err := buff.WriteString(token.Data); err != nil { - return err - } - } - default: - // HTML escape the text - if _, err := buff.WriteString(token.String()); err != nil { - return err - } - } - } - - default: - // A token that didn't exist in the html package when we wrote this - return fmt.Errorf("unknown token: %v", token) - } - } -} - -// sanitizeAttrs takes a set of element attribute policies and the global -// attribute policies and applies them to the []html.Attribute returning a set -// of html.Attributes that match the policies -func (p *Policy) sanitizeAttrs( - elementName string, - attrs []html.Attribute, - aps map[string][]attrPolicy, -) []html.Attribute { - - if len(attrs) == 0 { - return attrs - } - - hasStylePolicies := false - sps, elementHasStylePolicies := p.elsAndStyles[elementName] - if len(p.globalStyles) > 0 || (elementHasStylePolicies && len(sps) > 0) { - hasStylePolicies = true - } - // no specific element policy found, look for a pattern match - if !hasStylePolicies { - for k, v := range p.elsMatchingAndStyles { - if k.MatchString(elementName) { - if len(v) > 0 { - hasStylePolicies = true - break - } - } - } - } - - // Builds a new attribute slice based on the whether the attribute has been - // allowed explicitly or globally. - cleanAttrs := []html.Attribute{} -attrsLoop: - for _, htmlAttr := range attrs { - if p.allowDataAttributes { - // If we see a data attribute, let it through. - if isDataAttribute(htmlAttr.Key) { - cleanAttrs = append(cleanAttrs, htmlAttr) - continue - } - } - // Is this a "style" attribute, and if so, do we need to sanitize it? - if htmlAttr.Key == "style" && hasStylePolicies { - htmlAttr = p.sanitizeStyles(htmlAttr, elementName) - if htmlAttr.Val == "" { - // We've sanitized away any and all styles; don't bother to - // output the style attribute (even if it's allowed) - continue - } else { - cleanAttrs = append(cleanAttrs, htmlAttr) - continue - } - } - - // Is there an element specific attribute policy that applies? - if apl, ok := aps[htmlAttr.Key]; ok { - for _, ap := range apl { - if ap.regexp != nil { - if ap.regexp.MatchString(htmlAttr.Val) { - cleanAttrs = append(cleanAttrs, htmlAttr) - continue attrsLoop - } - } else { - cleanAttrs = append(cleanAttrs, htmlAttr) - continue attrsLoop - } - } - } - - // Is there a global attribute policy that applies? - if apl, ok := p.globalAttrs[htmlAttr.Key]; ok { - for _, ap := range apl { - if ap.regexp != nil { - if ap.regexp.MatchString(htmlAttr.Val) { - cleanAttrs = append(cleanAttrs, htmlAttr) - continue attrsLoop - } - } else { - cleanAttrs = append(cleanAttrs, htmlAttr) - continue attrsLoop - } - } - } - } - - if len(cleanAttrs) == 0 { - // If nothing was allowed, let's get out of here - return cleanAttrs - } - // cleanAttrs now contains the attributes that are permitted - - if linkable(elementName) { - if p.requireParseableURLs { - // Ensure URLs are parseable: - // - a.href - // - area.href - // - link.href - // - blockquote.cite - // - q.cite - // - img.src - // - script.src - tmpAttrs := []html.Attribute{} - for _, htmlAttr := range cleanAttrs { - switch elementName { - case "a", "area", "base", "link": - if htmlAttr.Key == "href" { - if u, ok := p.validURL(htmlAttr.Val); ok { - htmlAttr.Val = u - tmpAttrs = append(tmpAttrs, htmlAttr) - } - break - } - tmpAttrs = append(tmpAttrs, htmlAttr) - case "blockquote", "del", "ins", "q": - if htmlAttr.Key == "cite" { - if u, ok := p.validURL(htmlAttr.Val); ok { - htmlAttr.Val = u - tmpAttrs = append(tmpAttrs, htmlAttr) - } - break - } - tmpAttrs = append(tmpAttrs, htmlAttr) - case "audio", "embed", "iframe", "img", "script", "source", "track", "video": - if htmlAttr.Key == "src" { - if u, ok := p.validURL(htmlAttr.Val); ok { - if p.srcRewriter != nil { - parsedURL, err := url.Parse(u) - if err != nil { - fmt.Println(err) - } - p.srcRewriter(parsedURL) - u = parsedURL.String() - } - htmlAttr.Val = u - tmpAttrs = append(tmpAttrs, htmlAttr) - } - break - } - tmpAttrs = append(tmpAttrs, htmlAttr) - default: - tmpAttrs = append(tmpAttrs, htmlAttr) - } - } - cleanAttrs = tmpAttrs - } - - if (p.requireNoFollow || - p.requireNoFollowFullyQualifiedLinks || - p.requireNoReferrer || - p.requireNoReferrerFullyQualifiedLinks || - p.addTargetBlankToFullyQualifiedLinks) && - len(cleanAttrs) > 0 { - - // Add rel="nofollow" if a "href" exists - switch elementName { - case "a", "area", "base", "link": - var hrefFound bool - var externalLink bool - for _, htmlAttr := range cleanAttrs { - if htmlAttr.Key == "href" { - hrefFound = true - - u, err := url.Parse(htmlAttr.Val) - if err != nil { - continue - } - if u.Host != "" { - externalLink = true - } - - continue - } - } - - if hrefFound { - var ( - noFollowFound bool - noReferrerFound bool - targetBlankFound bool - ) - - addNoFollow := (p.requireNoFollow || - externalLink && p.requireNoFollowFullyQualifiedLinks) - - addNoReferrer := (p.requireNoReferrer || - externalLink && p.requireNoReferrerFullyQualifiedLinks) - - addTargetBlank := (externalLink && - p.addTargetBlankToFullyQualifiedLinks) - - tmpAttrs := []html.Attribute{} - for _, htmlAttr := range cleanAttrs { - - var appended bool - if htmlAttr.Key == "rel" && (addNoFollow || addNoReferrer) { - - if addNoFollow && !strings.Contains(htmlAttr.Val, "nofollow") { - htmlAttr.Val += " nofollow" - } - if addNoReferrer && !strings.Contains(htmlAttr.Val, "noreferrer") { - htmlAttr.Val += " noreferrer" - } - noFollowFound = addNoFollow - noReferrerFound = addNoReferrer - tmpAttrs = append(tmpAttrs, htmlAttr) - appended = true - } - - if elementName == "a" && htmlAttr.Key == "target" { - if htmlAttr.Val == "_blank" { - targetBlankFound = true - } - if addTargetBlank && !targetBlankFound { - htmlAttr.Val = "_blank" - targetBlankFound = true - tmpAttrs = append(tmpAttrs, htmlAttr) - appended = true - } - } - - if !appended { - tmpAttrs = append(tmpAttrs, htmlAttr) - } - } - if noFollowFound || noReferrerFound || targetBlankFound { - cleanAttrs = tmpAttrs - } - - if (addNoFollow && !noFollowFound) || (addNoReferrer && !noReferrerFound) { - rel := html.Attribute{} - rel.Key = "rel" - if addNoFollow { - rel.Val = "nofollow" - } - if addNoReferrer { - if rel.Val != "" { - rel.Val += " " - } - rel.Val += "noreferrer" - } - cleanAttrs = append(cleanAttrs, rel) - } - - if elementName == "a" && addTargetBlank && !targetBlankFound { - rel := html.Attribute{} - rel.Key = "target" - rel.Val = "_blank" - targetBlankFound = true - cleanAttrs = append(cleanAttrs, rel) - } - - if targetBlankFound { - // target="_blank" has a security risk that allows the - // opened window/tab to issue JavaScript calls against - // window.opener, which in effect allow the destination - // of the link to control the source: - // https://dev.to/ben/the-targetblank-vulnerability-by-example - // - // To mitigate this risk, we need to add a specific rel - // attribute if it is not already present. - // rel="noopener" - // - // Unfortunately this is processing the rel twice (we - // already looked at it earlier ^^) as we cannot be sure - // of the ordering of the href and rel, and whether we - // have fully satisfied that we need to do this. This - // double processing only happens *if* target="_blank" - // is true. - var noOpenerAdded bool - tmpAttrs := []html.Attribute{} - for _, htmlAttr := range cleanAttrs { - var appended bool - if htmlAttr.Key == "rel" { - if strings.Contains(htmlAttr.Val, "noopener") { - noOpenerAdded = true - tmpAttrs = append(tmpAttrs, htmlAttr) - } else { - htmlAttr.Val += " noopener" - noOpenerAdded = true - tmpAttrs = append(tmpAttrs, htmlAttr) - } - - appended = true - } - if !appended { - tmpAttrs = append(tmpAttrs, htmlAttr) - } - } - if noOpenerAdded { - cleanAttrs = tmpAttrs - } else { - // rel attr was not found, or else noopener would - // have been added already - rel := html.Attribute{} - rel.Key = "rel" - rel.Val = "noopener" - cleanAttrs = append(cleanAttrs, rel) - } - - } - } - default: - } - } - } - - if p.requireCrossOriginAnonymous && len(cleanAttrs) > 0 { - switch elementName { - case "audio", "img", "link", "script", "video": - var crossOriginFound bool - for i, htmlAttr := range cleanAttrs { - if htmlAttr.Key == "crossorigin" { - crossOriginFound = true - cleanAttrs[i].Val = "anonymous" - } - } - - if !crossOriginFound { - crossOrigin := html.Attribute{} - crossOrigin.Key = "crossorigin" - crossOrigin.Val = "anonymous" - cleanAttrs = append(cleanAttrs, crossOrigin) - } - } - } - - if p.requireSandboxOnIFrame != nil && elementName == "iframe" { - var sandboxFound bool - for i, htmlAttr := range cleanAttrs { - if htmlAttr.Key == "sandbox" { - sandboxFound = true - var cleanVals []string - cleanValsSet := make(map[string]bool) - for _, val := range strings.Fields(htmlAttr.Val) { - if p.requireSandboxOnIFrame[val] { - if !cleanValsSet[val] { - cleanVals = append(cleanVals, val) - cleanValsSet[val] = true - } - } - } - cleanAttrs[i].Val = strings.Join(cleanVals, " ") - } - } - - if !sandboxFound { - sandbox := html.Attribute{} - sandbox.Key = "sandbox" - sandbox.Val = "" - cleanAttrs = append(cleanAttrs, sandbox) - } - } - - return cleanAttrs -} - -func (p *Policy) sanitizeStyles(attr html.Attribute, elementName string) html.Attribute { - sps := p.elsAndStyles[elementName] - if len(sps) == 0 { - sps = map[string][]stylePolicy{} - // check for any matching elements, if we don't already have a policy found - // if multiple matches are found they will be overwritten, it's best - // to not have overlapping matchers - for regex, policies := range p.elsMatchingAndStyles { - if regex.MatchString(elementName) { - for k, v := range policies { - sps[k] = append(sps[k], v...) - } - } - } - } - - //Add semi-colon to end to fix parsing issue - attr.Val = strings.TrimRight(attr.Val, " ") - if len(attr.Val) > 0 && attr.Val[len(attr.Val)-1] != ';' { - attr.Val = attr.Val + ";" - } - decs, err := parser.ParseDeclarations(attr.Val) - if err != nil { - attr.Val = "" - return attr - } - clean := []string{} - prefixes := []string{"-webkit-", "-moz-", "-ms-", "-o-", "mso-", "-xv-", "-atsc-", "-wap-", "-khtml-", "prince-", "-ah-", "-hp-", "-ro-", "-rim-", "-tc-"} - -decLoop: - for _, dec := range decs { - tempProperty := strings.ToLower(dec.Property) - tempValue := removeUnicode(strings.ToLower(dec.Value)) - for _, i := range prefixes { - tempProperty = strings.TrimPrefix(tempProperty, i) - } - if spl, ok := sps[tempProperty]; ok { - for _, sp := range spl { - if sp.handler != nil { - if sp.handler(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) - continue decLoop - } - } else if len(sp.enum) > 0 { - if stringInSlice(tempValue, sp.enum) { - clean = append(clean, dec.Property+": "+dec.Value) - continue decLoop - } - } else if sp.regexp != nil { - if sp.regexp.MatchString(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) - continue decLoop - } - } - } - } - if spl, ok := p.globalStyles[tempProperty]; ok { - for _, sp := range spl { - if sp.handler != nil { - if sp.handler(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) - continue decLoop - } - } else if len(sp.enum) > 0 { - if stringInSlice(tempValue, sp.enum) { - clean = append(clean, dec.Property+": "+dec.Value) - continue decLoop - } - } else if sp.regexp != nil { - if sp.regexp.MatchString(tempValue) { - clean = append(clean, dec.Property+": "+dec.Value) - continue decLoop - } - } - } - } - } - if len(clean) > 0 { - attr.Val = strings.Join(clean, "; ") - } else { - attr.Val = "" - } - return attr -} - -func (p *Policy) allowNoAttrs(elementName string) bool { - _, ok := p.setOfElementsAllowedWithoutAttrs[elementName] - if !ok { - for _, r := range p.setOfElementsMatchingAllowedWithoutAttrs { - if r.MatchString(elementName) { - ok = true - break - } - } - } - return ok -} - -func (p *Policy) validURL(rawurl string) (string, bool) { - if p.requireParseableURLs { - // URLs are valid if when space is trimmed the URL is valid - rawurl = strings.TrimSpace(rawurl) - - // URLs cannot contain whitespace, unless it is a data-uri - if strings.Contains(rawurl, " ") || - strings.Contains(rawurl, "\t") || - strings.Contains(rawurl, "\n") { - if !strings.HasPrefix(rawurl, `data:`) { - return "", false - } - - // Remove \r and \n from base64 encoded data to pass url.Parse. - matched := dataURIbase64Prefix.FindString(rawurl) - if matched != "" { - rawurl = matched + strings.Replace( - strings.Replace( - rawurl[len(matched):], - "\r", - "", - -1, - ), - "\n", - "", - -1, - ) - } - } - - // URLs are valid if they parse - u, err := url.Parse(rawurl) - if err != nil { - return "", false - } - - if u.Scheme != "" { - urlPolicies, ok := p.allowURLSchemes[u.Scheme] - if !ok { - for _, r := range p.allowURLSchemeRegexps { - if r.MatchString(u.Scheme) { - return u.String(), true - } - } - - return "", false - } - - if len(urlPolicies) == 0 { - return u.String(), true - } - - for _, urlPolicy := range urlPolicies { - if urlPolicy(u) { - return u.String(), true - } - } - - return "", false - } - - if p.allowRelativeURLs { - if u.String() != "" { - return u.String(), true - } - } - - return "", false - } - - return rawurl, true -} - -func linkable(elementName string) bool { - switch elementName { - case "a", "area", "base", "link": - // elements that allow .href - return true - case "blockquote", "del", "ins", "q": - // elements that allow .cite - return true - case "audio", "embed", "iframe", "img", "input", "script", "track", "video": - // elements that allow .src - return true - default: - return false - } -} - -// stringInSlice returns true if needle exists in haystack -func stringInSlice(needle string, haystack []string) bool { - for _, straw := range haystack { - if strings.EqualFold(straw, needle) { - return true - } - } - return false -} - -func isDataAttribute(val string) bool { - if !dataAttribute.MatchString(val) { - return false - } - rest := strings.Split(val, "data-") - if len(rest) == 1 { - return false - } - // data-xml* is invalid. - if dataAttributeXMLPrefix.MatchString(rest[1]) { - return false - } - // no uppercase or semi-colons allowed. - if dataAttributeInvalidChars.MatchString(rest[1]) { - return false - } - return true -} - -func removeUnicode(value string) string { - substitutedValue := value - currentLoc := cssUnicodeChar.FindStringIndex(substitutedValue) - for currentLoc != nil { - - character := substitutedValue[currentLoc[0]+1 : currentLoc[1]] - character = strings.TrimSpace(character) - if len(character) < 4 { - character = strings.Repeat("0", 4-len(character)) + character - } else { - for len(character) > 4 { - if character[0] != '0' { - character = "" - break - } else { - character = character[1:] - } - } - } - character = "\\u" + character - translatedChar, err := strconv.Unquote(`"` + character + `"`) - translatedChar = strings.TrimSpace(translatedChar) - if err != nil { - return "" - } - substitutedValue = substitutedValue[0:currentLoc[0]] + translatedChar + substitutedValue[currentLoc[1]:] - currentLoc = cssUnicodeChar.FindStringIndex(substitutedValue) - } - return substitutedValue -} - -func (p *Policy) matchRegex(elementName string) (map[string][]attrPolicy, bool) { - aps := make(map[string][]attrPolicy, 0) - matched := false - for regex, attrs := range p.elsMatchingAndAttrs { - if regex.MatchString(elementName) { - matched = true - for k, v := range attrs { - aps[k] = append(aps[k], v...) - } - } - } - return aps, matched -} - -// normaliseElementName takes a HTML element like " that closes the next token. If - // non-empty, the subsequent call to Next will return a raw or RCDATA text - // token: one that treats "

    " as text instead of an element. - // rawTag's contents are lower-cased. - rawTag string - // textIsRaw is whether the current text token's data is not escaped. - textIsRaw bool - // convertNUL is whether NUL bytes in the current token's data should - // be converted into \ufffd replacement characters. - convertNUL bool - // allowCDATA is whether CDATA sections are allowed in the current context. - allowCDATA bool -} - -// AllowCDATA sets whether or not the tokenizer recognizes as -// the text "foo". The default value is false, which means to recognize it as -// a bogus comment "" instead. -// -// Strictly speaking, an HTML5 compliant tokenizer should allow CDATA if and -// only if tokenizing foreign content, such as MathML and SVG. However, -// tracking foreign-contentness is difficult to do purely in the tokenizer, -// as opposed to the parser, due to HTML integration points: an element -// can contain a that is foreign-to-SVG but not foreign-to- -// HTML. For strict compliance with the HTML5 tokenization algorithm, it is the -// responsibility of the user of a tokenizer to call AllowCDATA as appropriate. -// In practice, if using the tokenizer without caring whether MathML or SVG -// CDATA is text or comments, such as tokenizing HTML to find all the anchor -// text, it is acceptable to ignore this responsibility. -func (z *Tokenizer) AllowCDATA(allowCDATA bool) { - z.allowCDATA = allowCDATA -} - -// NextIsNotRawText instructs the tokenizer that the next token should not be -// considered as 'raw text'. Some elements, such as script and title elements, -// normally require the next token after the opening tag to be 'raw text' that -// has no child elements. For example, tokenizing "a<b>c</b>d" -// yields a start tag token for "", a text token for "a<b>c</b>d", and -// an end tag token for "". There are no distinct start tag or end tag -// tokens for the "" and "". -// -// This tokenizer implementation will generally look for raw text at the right -// times. Strictly speaking, an HTML5 compliant tokenizer should not look for -// raw text if in foreign content: generally needs raw text, but a -// <title> inside an <svg> does not. Another example is that a <textarea> -// generally needs raw text, but a <textarea> is not allowed as an immediate -// child of a <select>; in normal parsing, a <textarea> implies </select>, but -// one cannot close the implicit element when parsing a <select>'s InnerHTML. -// Similarly to AllowCDATA, tracking the correct moment to override raw-text- -// ness is difficult to do purely in the tokenizer, as opposed to the parser. -// For strict compliance with the HTML5 tokenization algorithm, it is the -// responsibility of the user of a tokenizer to call NextIsNotRawText as -// appropriate. In practice, like AllowCDATA, it is acceptable to ignore this -// responsibility for basic usage. -// -// Note that this 'raw text' concept is different from the one offered by the -// Tokenizer.Raw method. -func (z *Tokenizer) NextIsNotRawText() { - z.rawTag = "" -} - -// Err returns the error associated with the most recent ErrorToken token. -// This is typically io.EOF, meaning the end of tokenization. -func (z *Tokenizer) Err() error { - if z.tt != ErrorToken { - return nil - } - return z.err -} - -// readByte returns the next byte from the input stream, doing a buffered read -// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte -// slice that holds all the bytes read so far for the current token. -// It sets z.err if the underlying reader returns an error. -// Pre-condition: z.err == nil. -func (z *Tokenizer) readByte() byte { - if z.raw.end >= len(z.buf) { - // Our buffer is exhausted and we have to read from z.r. Check if the - // previous read resulted in an error. - if z.readErr != nil { - z.err = z.readErr - return 0 - } - // We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length - // z.raw.end - z.raw.start is more than half the capacity of z.buf, then we - // allocate a new buffer before the copy. - c := cap(z.buf) - d := z.raw.end - z.raw.start - var buf1 []byte - if 2*d > c { - buf1 = make([]byte, d, 2*c) - } else { - buf1 = z.buf[:d] - } - copy(buf1, z.buf[z.raw.start:z.raw.end]) - if x := z.raw.start; x != 0 { - // Adjust the data/attr spans to refer to the same contents after the copy. - z.data.start -= x - z.data.end -= x - z.pendingAttr[0].start -= x - z.pendingAttr[0].end -= x - z.pendingAttr[1].start -= x - z.pendingAttr[1].end -= x - for i := range z.attr { - z.attr[i][0].start -= x - z.attr[i][0].end -= x - z.attr[i][1].start -= x - z.attr[i][1].end -= x - } - } - z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d] - // Now that we have copied the live bytes to the start of the buffer, - // we read from z.r into the remainder. - var n int - n, z.readErr = readAtLeastOneByte(z.r, buf1[d:cap(buf1)]) - if n == 0 { - z.err = z.readErr - return 0 - } - z.buf = buf1[:d+n] - } - x := z.buf[z.raw.end] - z.raw.end++ - if z.maxBuf > 0 && z.raw.end-z.raw.start >= z.maxBuf { - z.err = ErrBufferExceeded - return 0 - } - return x -} - -// Buffered returns a slice containing data buffered but not yet tokenized. -func (z *Tokenizer) Buffered() []byte { - return z.buf[z.raw.end:] -} - -// readAtLeastOneByte wraps an io.Reader so that reading cannot return (0, nil). -// It returns io.ErrNoProgress if the underlying r.Read method returns (0, nil) -// too many times in succession. -func readAtLeastOneByte(r io.Reader, b []byte) (int, error) { - for i := 0; i < 100; i++ { - if n, err := r.Read(b); n != 0 || err != nil { - return n, err - } - } - return 0, io.ErrNoProgress -} - -// skipWhiteSpace skips past any white space. -func (z *Tokenizer) skipWhiteSpace() { - if z.err != nil { - return - } - for { - c := z.readByte() - if z.err != nil { - return - } - switch c { - case ' ', '\n', '\r', '\t', '\f': - // No-op. - default: - z.raw.end-- - return - } - } -} - -// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and -// is typically something like "script" or "textarea". -func (z *Tokenizer) readRawOrRCDATA() { - if z.rawTag == "script" { - z.readScript() - z.textIsRaw = true - z.rawTag = "" - return - } -loop: - for { - c := z.readByte() - if z.err != nil { - break loop - } - if c != '<' { - continue loop - } - c = z.readByte() - if z.err != nil { - break loop - } - if c != '/' { - z.raw.end-- - continue loop - } - if z.readRawEndTag() || z.err != nil { - break loop - } - } - z.data.end = z.raw.end - // A textarea's or title's RCDATA can contain escaped entities. - z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title" - z.rawTag = "" -} - -// readRawEndTag attempts to read a tag like "</foo>", where "foo" is z.rawTag. -// If it succeeds, it backs up the input position to reconsume the tag and -// returns true. Otherwise it returns false. The opening "</" has already been -// consumed. -func (z *Tokenizer) readRawEndTag() bool { - for i := 0; i < len(z.rawTag); i++ { - c := z.readByte() - if z.err != nil { - return false - } - if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') { - z.raw.end-- - return false - } - } - c := z.readByte() - if z.err != nil { - return false - } - switch c { - case ' ', '\n', '\r', '\t', '\f', '/', '>': - // The 3 is 2 for the leading "</" plus 1 for the trailing character c. - z.raw.end -= 3 + len(z.rawTag) - return true - } - z.raw.end-- - return false -} - -// readScript reads until the next </script> tag, following the byzantine -// rules for escaping/hiding the closing tag. -func (z *Tokenizer) readScript() { - defer func() { - z.data.end = z.raw.end - }() - var c byte - -scriptData: - c = z.readByte() - if z.err != nil { - return - } - if c == '<' { - goto scriptDataLessThanSign - } - goto scriptData - -scriptDataLessThanSign: - c = z.readByte() - if z.err != nil { - return - } - switch c { - case '/': - goto scriptDataEndTagOpen - case '!': - goto scriptDataEscapeStart - } - z.raw.end-- - goto scriptData - -scriptDataEndTagOpen: - if z.readRawEndTag() || z.err != nil { - return - } - goto scriptData - -scriptDataEscapeStart: - c = z.readByte() - if z.err != nil { - return - } - if c == '-' { - goto scriptDataEscapeStartDash - } - z.raw.end-- - goto scriptData - -scriptDataEscapeStartDash: - c = z.readByte() - if z.err != nil { - return - } - if c == '-' { - goto scriptDataEscapedDashDash - } - z.raw.end-- - goto scriptData - -scriptDataEscaped: - c = z.readByte() - if z.err != nil { - return - } - switch c { - case '-': - goto scriptDataEscapedDash - case '<': - goto scriptDataEscapedLessThanSign - } - goto scriptDataEscaped - -scriptDataEscapedDash: - c = z.readByte() - if z.err != nil { - return - } - switch c { - case '-': - goto scriptDataEscapedDashDash - case '<': - goto scriptDataEscapedLessThanSign - } - goto scriptDataEscaped - -scriptDataEscapedDashDash: - c = z.readByte() - if z.err != nil { - return - } - switch c { - case '-': - goto scriptDataEscapedDashDash - case '<': - goto scriptDataEscapedLessThanSign - case '>': - goto scriptData - } - goto scriptDataEscaped - -scriptDataEscapedLessThanSign: - c = z.readByte() - if z.err != nil { - return - } - if c == '/' { - goto scriptDataEscapedEndTagOpen - } - if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' { - goto scriptDataDoubleEscapeStart - } - z.raw.end-- - goto scriptData - -scriptDataEscapedEndTagOpen: - if z.readRawEndTag() || z.err != nil { - return - } - goto scriptDataEscaped - -scriptDataDoubleEscapeStart: - z.raw.end-- - for i := 0; i < len("script"); i++ { - c = z.readByte() - if z.err != nil { - return - } - if c != "script"[i] && c != "SCRIPT"[i] { - z.raw.end-- - goto scriptDataEscaped - } - } - c = z.readByte() - if z.err != nil { - return - } - switch c { - case ' ', '\n', '\r', '\t', '\f', '/', '>': - goto scriptDataDoubleEscaped - } - z.raw.end-- - goto scriptDataEscaped - -scriptDataDoubleEscaped: - c = z.readByte() - if z.err != nil { - return - } - switch c { - case '-': - goto scriptDataDoubleEscapedDash - case '<': - goto scriptDataDoubleEscapedLessThanSign - } - goto scriptDataDoubleEscaped - -scriptDataDoubleEscapedDash: - c = z.readByte() - if z.err != nil { - return - } - switch c { - case '-': - goto scriptDataDoubleEscapedDashDash - case '<': - goto scriptDataDoubleEscapedLessThanSign - } - goto scriptDataDoubleEscaped - -scriptDataDoubleEscapedDashDash: - c = z.readByte() - if z.err != nil { - return - } - switch c { - case '-': - goto scriptDataDoubleEscapedDashDash - case '<': - goto scriptDataDoubleEscapedLessThanSign - case '>': - goto scriptData - } - goto scriptDataDoubleEscaped - -scriptDataDoubleEscapedLessThanSign: - c = z.readByte() - if z.err != nil { - return - } - if c == '/' { - goto scriptDataDoubleEscapeEnd - } - z.raw.end-- - goto scriptDataDoubleEscaped - -scriptDataDoubleEscapeEnd: - if z.readRawEndTag() { - z.raw.end += len("</script>") - goto scriptDataEscaped - } - if z.err != nil { - return - } - goto scriptDataDoubleEscaped -} - -// readComment reads the next comment token starting with "<!--". The opening -// "<!--" has already been consumed. -func (z *Tokenizer) readComment() { - // When modifying this function, consider manually increasing the - // maxSuffixLen constant in func TestComments, from 6 to e.g. 9 or more. - // That increase should only be temporary, not committed, as it - // exponentially affects the test running time. - - z.data.start = z.raw.end - defer func() { - if z.data.end < z.data.start { - // It's a comment with no data, like <!-->. - z.data.end = z.data.start - } - }() - - var dashCount int - beginning := true - for { - c := z.readByte() - if z.err != nil { - z.data.end = z.calculateAbruptCommentDataEnd() - return - } - switch c { - case '-': - dashCount++ - continue - case '>': - if dashCount >= 2 || beginning { - z.data.end = z.raw.end - len("-->") - return - } - case '!': - if dashCount >= 2 { - c = z.readByte() - if z.err != nil { - z.data.end = z.calculateAbruptCommentDataEnd() - return - } else if c == '>' { - z.data.end = z.raw.end - len("--!>") - return - } else if c == '-' { - dashCount = 1 - beginning = false - continue - } - } - } - dashCount = 0 - beginning = false - } -} - -func (z *Tokenizer) calculateAbruptCommentDataEnd() int { - raw := z.Raw() - const prefixLen = len("<!--") - if len(raw) >= prefixLen { - raw = raw[prefixLen:] - if hasSuffix(raw, "--!") { - return z.raw.end - 3 - } else if hasSuffix(raw, "--") { - return z.raw.end - 2 - } else if hasSuffix(raw, "-") { - return z.raw.end - 1 - } - } - return z.raw.end -} - -func hasSuffix(b []byte, suffix string) bool { - if len(b) < len(suffix) { - return false - } - b = b[len(b)-len(suffix):] - for i := range b { - if b[i] != suffix[i] { - return false - } - } - return true -} - -// readUntilCloseAngle reads until the next ">". -func (z *Tokenizer) readUntilCloseAngle() { - z.data.start = z.raw.end - for { - c := z.readByte() - if z.err != nil { - z.data.end = z.raw.end - return - } - if c == '>' { - z.data.end = z.raw.end - len(">") - return - } - } -} - -// readMarkupDeclaration reads the next token starting with "<!". It might be -// a "<!--comment-->", a "<!DOCTYPE foo>", a "<![CDATA[section]]>" or -// "<!a bogus comment". The opening "<!" has already been consumed. -func (z *Tokenizer) readMarkupDeclaration() TokenType { - z.data.start = z.raw.end - var c [2]byte - for i := 0; i < 2; i++ { - c[i] = z.readByte() - if z.err != nil { - z.data.end = z.raw.end - return CommentToken - } - } - if c[0] == '-' && c[1] == '-' { - z.readComment() - return CommentToken - } - z.raw.end -= 2 - if z.readDoctype() { - return DoctypeToken - } - if z.allowCDATA && z.readCDATA() { - z.convertNUL = true - return TextToken - } - // It's a bogus comment. - z.readUntilCloseAngle() - return CommentToken -} - -// readDoctype attempts to read a doctype declaration and returns true if -// successful. The opening "<!" has already been consumed. -func (z *Tokenizer) readDoctype() bool { - const s = "DOCTYPE" - for i := 0; i < len(s); i++ { - c := z.readByte() - if z.err != nil { - z.data.end = z.raw.end - return false - } - if c != s[i] && c != s[i]+('a'-'A') { - // Back up to read the fragment of "DOCTYPE" again. - z.raw.end = z.data.start - return false - } - } - if z.skipWhiteSpace(); z.err != nil { - z.data.start = z.raw.end - z.data.end = z.raw.end - return true - } - z.readUntilCloseAngle() - return true -} - -// readCDATA attempts to read a CDATA section and returns true if -// successful. The opening "<!" has already been consumed. -func (z *Tokenizer) readCDATA() bool { - const s = "[CDATA[" - for i := 0; i < len(s); i++ { - c := z.readByte() - if z.err != nil { - z.data.end = z.raw.end - return false - } - if c != s[i] { - // Back up to read the fragment of "[CDATA[" again. - z.raw.end = z.data.start - return false - } - } - z.data.start = z.raw.end - brackets := 0 - for { - c := z.readByte() - if z.err != nil { - z.data.end = z.raw.end - return true - } - switch c { - case ']': - brackets++ - case '>': - if brackets >= 2 { - z.data.end = z.raw.end - len("]]>") - return true - } - brackets = 0 - default: - brackets = 0 - } - } -} - -// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end] -// case-insensitively matches any element of ss. -func (z *Tokenizer) startTagIn(ss ...string) bool { -loop: - for _, s := range ss { - if z.data.end-z.data.start != len(s) { - continue loop - } - for i := 0; i < len(s); i++ { - c := z.buf[z.data.start+i] - if 'A' <= c && c <= 'Z' { - c += 'a' - 'A' - } - if c != s[i] { - continue loop - } - } - return true - } - return false -} - -// readStartTag reads the next start tag token. The opening "<a" has already -// been consumed, where 'a' means anything in [A-Za-z]. -func (z *Tokenizer) readStartTag() TokenType { - z.readTag(true) - if z.err != nil { - return ErrorToken - } - // Several tags flag the tokenizer's next token as raw. - c, raw := z.buf[z.data.start], false - if 'A' <= c && c <= 'Z' { - c += 'a' - 'A' - } - switch c { - case 'i': - raw = z.startTagIn("iframe") - case 'n': - raw = z.startTagIn("noembed", "noframes", "noscript") - case 'p': - raw = z.startTagIn("plaintext") - case 's': - raw = z.startTagIn("script", "style") - case 't': - raw = z.startTagIn("textarea", "title") - case 'x': - raw = z.startTagIn("xmp") - } - if raw { - z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end])) - } - // Look for a self-closing token (e.g. <br/>). - // - // Originally, we did this by just checking that the last character of the - // tag (ignoring the closing bracket) was a solidus (/) character, but this - // is not always accurate. - // - // We need to be careful that we don't misinterpret a non-self-closing tag - // as self-closing, as can happen if the tag contains unquoted attribute - // values (i.e. <p a=/>). - // - // To avoid this, we check that the last non-bracket character of the tag - // (z.raw.end-2) isn't the same character as the last non-quote character of - // the last attribute of the tag (z.pendingAttr[1].end-1), if the tag has - // attributes. - nAttrs := len(z.attr) - if z.err == nil && z.buf[z.raw.end-2] == '/' && (nAttrs == 0 || z.raw.end-2 != z.attr[nAttrs-1][1].end-1) { - return SelfClosingTagToken - } - return StartTagToken -} - -// readTag reads the next tag token and its attributes. If saveAttr, those -// attributes are saved in z.attr, otherwise z.attr is set to an empty slice. -// The opening "<a" or "</a" has already been consumed, where 'a' means anything -// in [A-Za-z]. -func (z *Tokenizer) readTag(saveAttr bool) { - z.attr = z.attr[:0] - z.nAttrReturned = 0 - // Read the tag name and attribute key/value pairs. - z.readTagName() - if z.skipWhiteSpace(); z.err != nil { - return - } - for { - c := z.readByte() - if z.err != nil || c == '>' { - break - } - z.raw.end-- - z.readTagAttrKey() - z.readTagAttrVal() - // Save pendingAttr if saveAttr and that attribute has a non-empty key. - if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end { - z.attr = append(z.attr, z.pendingAttr) - } - if z.skipWhiteSpace(); z.err != nil { - break - } - } -} - -// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end) -// is positioned such that the first byte of the tag name (the "d" in "<div") -// has already been consumed. -func (z *Tokenizer) readTagName() { - z.data.start = z.raw.end - 1 - for { - c := z.readByte() - if z.err != nil { - z.data.end = z.raw.end - return - } - switch c { - case ' ', '\n', '\r', '\t', '\f': - z.data.end = z.raw.end - 1 - return - case '/', '>': - z.raw.end-- - z.data.end = z.raw.end - return - } - } -} - -// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>". -// Precondition: z.err == nil. -func (z *Tokenizer) readTagAttrKey() { - z.pendingAttr[0].start = z.raw.end - for { - c := z.readByte() - if z.err != nil { - z.pendingAttr[0].end = z.raw.end - return - } - switch c { - case '=': - if z.pendingAttr[0].start+1 == z.raw.end { - // WHATWG 13.2.5.32, if we see an equals sign before the attribute name - // begins, we treat it as a character in the attribute name and continue. - continue - } - fallthrough - case ' ', '\n', '\r', '\t', '\f', '/', '>': - // WHATWG 13.2.5.33 Attribute name state - // We need to reconsume the char in the after attribute name state to support the / character - z.raw.end-- - z.pendingAttr[0].end = z.raw.end - return - } - } -} - -// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>". -func (z *Tokenizer) readTagAttrVal() { - z.pendingAttr[1].start = z.raw.end - z.pendingAttr[1].end = z.raw.end - if z.skipWhiteSpace(); z.err != nil { - return - } - c := z.readByte() - if z.err != nil { - return - } - if c == '/' { - // WHATWG 13.2.5.34 After attribute name state - // U+002F SOLIDUS (/) - Switch to the self-closing start tag state. - return - } - if c != '=' { - z.raw.end-- - return - } - if z.skipWhiteSpace(); z.err != nil { - return - } - quote := z.readByte() - if z.err != nil { - return - } - switch quote { - case '>': - z.raw.end-- - return - - case '\'', '"': - z.pendingAttr[1].start = z.raw.end - for { - c := z.readByte() - if z.err != nil { - z.pendingAttr[1].end = z.raw.end - return - } - if c == quote { - z.pendingAttr[1].end = z.raw.end - 1 - return - } - } - - default: - z.pendingAttr[1].start = z.raw.end - 1 - for { - c := z.readByte() - if z.err != nil { - z.pendingAttr[1].end = z.raw.end - return - } - switch c { - case ' ', '\n', '\r', '\t', '\f': - z.pendingAttr[1].end = z.raw.end - 1 - return - case '>': - z.raw.end-- - z.pendingAttr[1].end = z.raw.end - return - } - } - } -} - -// Next scans the next token and returns its type. -func (z *Tokenizer) Next() TokenType { - z.raw.start = z.raw.end - z.data.start = z.raw.end - z.data.end = z.raw.end - if z.err != nil { - z.tt = ErrorToken - return z.tt - } - if z.rawTag != "" { - if z.rawTag == "plaintext" { - // Read everything up to EOF. - for z.err == nil { - z.readByte() - } - z.data.end = z.raw.end - z.textIsRaw = true - } else { - z.readRawOrRCDATA() - } - if z.data.end > z.data.start { - z.tt = TextToken - z.convertNUL = true - return z.tt - } - } - z.textIsRaw = false - z.convertNUL = false - -loop: - for { - c := z.readByte() - if z.err != nil { - break loop - } - if c != '<' { - continue loop - } - - // Check if the '<' we have just read is part of a tag, comment - // or doctype. If not, it's part of the accumulated text token. - c = z.readByte() - if z.err != nil { - break loop - } - var tokenType TokenType - switch { - case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': - tokenType = StartTagToken - case c == '/': - tokenType = EndTagToken - case c == '!' || c == '?': - // We use CommentToken to mean any of "<!--actual comments-->", - // "<!DOCTYPE declarations>" and "<?xml processing instructions?>". - tokenType = CommentToken - default: - // Reconsume the current character. - z.raw.end-- - continue - } - - // We have a non-text token, but we might have accumulated some text - // before that. If so, we return the text first, and return the non- - // text token on the subsequent call to Next. - if x := z.raw.end - len("<a"); z.raw.start < x { - z.raw.end = x - z.data.end = x - z.tt = TextToken - return z.tt - } - switch tokenType { - case StartTagToken: - z.tt = z.readStartTag() - return z.tt - case EndTagToken: - c = z.readByte() - if z.err != nil { - break loop - } - if c == '>' { - // "</>" does not generate a token at all. Generate an empty comment - // to allow passthrough clients to pick up the data using Raw. - // Reset the tokenizer state and start again. - z.tt = CommentToken - return z.tt - } - if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' { - z.readTag(false) - if z.err != nil { - z.tt = ErrorToken - } else { - z.tt = EndTagToken - } - return z.tt - } - z.raw.end-- - z.readUntilCloseAngle() - z.tt = CommentToken - return z.tt - case CommentToken: - if c == '!' { - z.tt = z.readMarkupDeclaration() - return z.tt - } - z.raw.end-- - z.readUntilCloseAngle() - z.tt = CommentToken - return z.tt - } - } - if z.raw.start < z.raw.end { - z.data.end = z.raw.end - z.tt = TextToken - return z.tt - } - z.tt = ErrorToken - return z.tt -} - -// Raw returns the unmodified text of the current token. Calling Next, Token, -// Text, TagName or TagAttr may change the contents of the returned slice. -// -// The token stream's raw bytes partition the byte stream (up until an -// ErrorToken). There are no overlaps or gaps between two consecutive token's -// raw bytes. One implication is that the byte offset of the current token is -// the sum of the lengths of all previous tokens' raw bytes. -func (z *Tokenizer) Raw() []byte { - return z.buf[z.raw.start:z.raw.end] -} - -// convertNewlines converts "\r" and "\r\n" in s to "\n". -// The conversion happens in place, but the resulting slice may be shorter. -func convertNewlines(s []byte) []byte { - for i, c := range s { - if c != '\r' { - continue - } - - src := i + 1 - if src >= len(s) || s[src] != '\n' { - s[i] = '\n' - continue - } - - dst := i - for src < len(s) { - if s[src] == '\r' { - if src+1 < len(s) && s[src+1] == '\n' { - src++ - } - s[dst] = '\n' - } else { - s[dst] = s[src] - } - src++ - dst++ - } - return s[:dst] - } - return s -} - -var ( - nul = []byte("\x00") - replacement = []byte("\ufffd") -) - -// Text returns the unescaped text of a text, comment or doctype token. The -// contents of the returned slice may change on the next call to Next. -func (z *Tokenizer) Text() []byte { - switch z.tt { - case TextToken, CommentToken, DoctypeToken: - s := z.buf[z.data.start:z.data.end] - z.data.start = z.raw.end - z.data.end = z.raw.end - s = convertNewlines(s) - if (z.convertNUL || z.tt == CommentToken) && bytes.Contains(s, nul) { - s = bytes.Replace(s, nul, replacement, -1) - } - if !z.textIsRaw { - s = unescape(s, false) - } - return s - } - return nil -} - -// TagName returns the lower-cased name of a tag token (the `img` out of -// `<IMG SRC="foo">`) and whether the tag has attributes. -// The contents of the returned slice may change on the next call to Next. -func (z *Tokenizer) TagName() (name []byte, hasAttr bool) { - if z.data.start < z.data.end { - switch z.tt { - case StartTagToken, EndTagToken, SelfClosingTagToken: - s := z.buf[z.data.start:z.data.end] - z.data.start = z.raw.end - z.data.end = z.raw.end - return lower(s), z.nAttrReturned < len(z.attr) - } - } - return nil, false -} - -// TagAttr returns the lower-cased key and unescaped value of the next unparsed -// attribute for the current tag token and whether there are more attributes. -// The contents of the returned slices may change on the next call to Next. -func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) { - if z.nAttrReturned < len(z.attr) { - switch z.tt { - case StartTagToken, SelfClosingTagToken: - x := z.attr[z.nAttrReturned] - z.nAttrReturned++ - key = z.buf[x[0].start:x[0].end] - val = z.buf[x[1].start:x[1].end] - return lower(key), unescape(convertNewlines(val), true), z.nAttrReturned < len(z.attr) - } - } - return nil, nil, false -} - -// Token returns the current Token. The result's Data and Attr values remain -// valid after subsequent Next calls. -func (z *Tokenizer) Token() Token { - t := Token{Type: z.tt} - switch z.tt { - case TextToken, CommentToken, DoctypeToken: - t.Data = string(z.Text()) - case StartTagToken, SelfClosingTagToken, EndTagToken: - name, moreAttr := z.TagName() - for moreAttr { - var key, val []byte - key, val, moreAttr = z.TagAttr() - t.Attr = append(t.Attr, Attribute{"", atom.String(key), string(val)}) - } - if a := atom.Lookup(name); a != 0 { - t.DataAtom, t.Data = a, a.String() - } else { - t.DataAtom, t.Data = 0, string(name) - } - } - return t -} - -// SetMaxBuf sets a limit on the amount of data buffered during tokenization. -// A value of 0 means unlimited. -func (z *Tokenizer) SetMaxBuf(n int) { - z.maxBuf = n -} - -// NewTokenizer returns a new HTML Tokenizer for the given Reader. -// The input is assumed to be UTF-8 encoded. -func NewTokenizer(r io.Reader) *Tokenizer { - return NewTokenizerFragment(r, "") -} - -// NewTokenizerFragment returns a new HTML Tokenizer for the given Reader, for -// tokenizing an existing element's InnerHTML fragment. contextTag is that -// element's tag, such as "div" or "iframe". -// -// For example, how the InnerHTML "a<b" is tokenized depends on whether it is -// for a <p> tag or a <script> tag. -// -// The input is assumed to be UTF-8 encoded. -func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer { - z := &Tokenizer{ - r: r, - buf: make([]byte, 0, 4096), - } - if contextTag != "" { - switch s := strings.ToLower(contextTag); s { - case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp": - z.rawTag = s - } - } - return z -} diff --git a/vendor/golang.org/x/net/http/httpproxy/proxy.go b/vendor/golang.org/x/net/http/httpproxy/proxy.go deleted file mode 100644 index d89c257a..00000000 --- a/vendor/golang.org/x/net/http/httpproxy/proxy.go +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2017 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 httpproxy provides support for HTTP proxy determination -// based on environment variables, as provided by net/http's -// ProxyFromEnvironment function. -// -// The API is not subject to the Go 1 compatibility promise and may change at -// any time. -package httpproxy - -import ( - "errors" - "fmt" - "net" - "net/netip" - "net/url" - "os" - "strings" - "unicode/utf8" - - "golang.org/x/net/idna" -) - -// Config holds configuration for HTTP proxy settings. See -// FromEnvironment for details. -type Config struct { - // HTTPProxy represents the value of the HTTP_PROXY or - // http_proxy environment variable. It will be used as the proxy - // URL for HTTP requests unless overridden by NoProxy. - HTTPProxy string - - // HTTPSProxy represents the HTTPS_PROXY or https_proxy - // environment variable. It will be used as the proxy URL for - // HTTPS requests unless overridden by NoProxy. - HTTPSProxy string - - // NoProxy represents the NO_PROXY or no_proxy environment - // variable. It specifies a string that contains comma-separated values - // specifying hosts that should be excluded from proxying. Each value is - // represented by an IP address prefix (1.2.3.4), an IP address prefix in - // CIDR notation (1.2.3.4/8), a domain name, or a special DNS label (*). - // An IP address prefix and domain name can also include a literal port - // number (1.2.3.4:80). - // A domain name matches that name and all subdomains. A domain name with - // a leading "." matches subdomains only. For example "foo.com" matches - // "foo.com" and "bar.foo.com"; ".y.com" matches "x.y.com" but not "y.com". - // A single asterisk (*) indicates that no proxying should be done. - // A best effort is made to parse the string and errors are - // ignored. - NoProxy string - - // CGI holds whether the current process is running - // as a CGI handler (FromEnvironment infers this from the - // presence of a REQUEST_METHOD environment variable). - // When this is set, ProxyForURL will return an error - // when HTTPProxy applies, because a client could be - // setting HTTP_PROXY maliciously. See https://golang.org/s/cgihttpproxy. - CGI bool -} - -// config holds the parsed configuration for HTTP proxy settings. -type config struct { - // Config represents the original configuration as defined above. - Config - - // httpsProxy is the parsed URL of the HTTPSProxy if defined. - httpsProxy *url.URL - - // httpProxy is the parsed URL of the HTTPProxy if defined. - httpProxy *url.URL - - // ipMatchers represent all values in the NoProxy that are IP address - // prefixes or an IP address in CIDR notation. - ipMatchers []matcher - - // domainMatchers represent all values in the NoProxy that are a domain - // name or hostname & domain name - domainMatchers []matcher -} - -// FromEnvironment returns a Config instance populated from the -// environment variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the -// lowercase versions thereof). -// -// The environment values may be either a complete URL or a -// "host[:port]", in which case the "http" scheme is assumed. An error -// is returned if the value is a different form. -func FromEnvironment() *Config { - return &Config{ - HTTPProxy: getEnvAny("HTTP_PROXY", "http_proxy"), - HTTPSProxy: getEnvAny("HTTPS_PROXY", "https_proxy"), - NoProxy: getEnvAny("NO_PROXY", "no_proxy"), - CGI: os.Getenv("REQUEST_METHOD") != "", - } -} - -func getEnvAny(names ...string) string { - for _, n := range names { - if val := os.Getenv(n); val != "" { - return val - } - } - return "" -} - -// ProxyFunc returns a function that determines the proxy URL to use for -// a given request URL. Changing the contents of cfg will not affect -// proxy functions created earlier. -// -// A nil URL and nil error are returned if no proxy is defined in the -// environment, or a proxy should not be used for the given request, as -// defined by NO_PROXY. -// -// As a special case, if req.URL.Host is "localhost" or a loopback address -// (with or without a port number), then a nil URL and nil error will be returned. -func (cfg *Config) ProxyFunc() func(reqURL *url.URL) (*url.URL, error) { - // Preprocess the Config settings for more efficient evaluation. - cfg1 := &config{ - Config: *cfg, - } - cfg1.init() - return cfg1.proxyForURL -} - -func (cfg *config) proxyForURL(reqURL *url.URL) (*url.URL, error) { - var proxy *url.URL - if reqURL.Scheme == "https" { - proxy = cfg.httpsProxy - } else if reqURL.Scheme == "http" { - proxy = cfg.httpProxy - if proxy != nil && cfg.CGI { - return nil, errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy") - } - } - if proxy == nil { - return nil, nil - } - if !cfg.useProxy(canonicalAddr(reqURL)) { - return nil, nil - } - - return proxy, nil -} - -func parseProxy(proxy string) (*url.URL, error) { - if proxy == "" { - return nil, nil - } - - proxyURL, err := url.Parse(proxy) - if err != nil || proxyURL.Scheme == "" || proxyURL.Host == "" { - // proxy was bogus. Try prepending "http://" to it and - // see if that parses correctly. If not, we fall - // through and complain about the original one. - if proxyURL, err := url.Parse("http://" + proxy); err == nil { - return proxyURL, nil - } - } - if err != nil { - return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err) - } - return proxyURL, nil -} - -// useProxy reports whether requests to addr should use a proxy, -// according to the NO_PROXY or no_proxy environment variable. -// addr is always a canonicalAddr with a host and port. -func (cfg *config) useProxy(addr string) bool { - if len(addr) == 0 { - return true - } - host, port, err := net.SplitHostPort(addr) - if err != nil { - return false - } - if host == "localhost" { - return false - } - nip, err := netip.ParseAddr(host) - var ip net.IP - if err == nil { - ip = net.IP(nip.AsSlice()) - if ip.IsLoopback() { - return false - } - } - - addr = strings.ToLower(strings.TrimSpace(host)) - - if ip != nil { - for _, m := range cfg.ipMatchers { - if m.match(addr, port, ip) { - return false - } - } - } - for _, m := range cfg.domainMatchers { - if m.match(addr, port, ip) { - return false - } - } - return true -} - -func (c *config) init() { - if parsed, err := parseProxy(c.HTTPProxy); err == nil { - c.httpProxy = parsed - } - if parsed, err := parseProxy(c.HTTPSProxy); err == nil { - c.httpsProxy = parsed - } - - for _, p := range strings.Split(c.NoProxy, ",") { - p = strings.ToLower(strings.TrimSpace(p)) - if len(p) == 0 { - continue - } - - if p == "*" { - c.ipMatchers = []matcher{allMatch{}} - c.domainMatchers = []matcher{allMatch{}} - return - } - - // IPv4/CIDR, IPv6/CIDR - if _, pnet, err := net.ParseCIDR(p); err == nil { - c.ipMatchers = append(c.ipMatchers, cidrMatch{cidr: pnet}) - continue - } - - // IPv4:port, [IPv6]:port - phost, pport, err := net.SplitHostPort(p) - if err == nil { - if len(phost) == 0 { - // There is no host part, likely the entry is malformed; ignore. - continue - } - if phost[0] == '[' && phost[len(phost)-1] == ']' { - phost = phost[1 : len(phost)-1] - } - } else { - phost = p - } - // IPv4, IPv6 - if pip := net.ParseIP(phost); pip != nil { - c.ipMatchers = append(c.ipMatchers, ipMatch{ip: pip, port: pport}) - continue - } - - if len(phost) == 0 { - // There is no host part, likely the entry is malformed; ignore. - continue - } - - // domain.com or domain.com:80 - // foo.com matches bar.foo.com - // .domain.com or .domain.com:port - // *.domain.com or *.domain.com:port - if strings.HasPrefix(phost, "*.") { - phost = phost[1:] - } - matchHost := false - if phost[0] != '.' { - matchHost = true - phost = "." + phost - } - if v, err := idnaASCII(phost); err == nil { - phost = v - } - c.domainMatchers = append(c.domainMatchers, domainMatch{host: phost, port: pport, matchHost: matchHost}) - } -} - -var portMap = map[string]string{ - "http": "80", - "https": "443", - "socks5": "1080", -} - -// canonicalAddr returns url.Host but always with a ":port" suffix -func canonicalAddr(url *url.URL) string { - addr := url.Hostname() - if v, err := idnaASCII(addr); err == nil { - addr = v - } - port := url.Port() - if port == "" { - port = portMap[url.Scheme] - } - return net.JoinHostPort(addr, port) -} - -// Given a string of the form "host", "host:port", or "[ipv6::address]:port", -// return true if the string includes a port. -func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } - -func idnaASCII(v string) (string, error) { - // TODO: Consider removing this check after verifying performance is okay. - // Right now punycode verification, length checks, context checks, and the - // permissible character tests are all omitted. It also prevents the ToASCII - // call from salvaging an invalid IDN, when possible. As a result it may be - // possible to have two IDNs that appear identical to the user where the - // ASCII-only version causes an error downstream whereas the non-ASCII - // version does not. - // Note that for correct ASCII IDNs ToASCII will only do considerably more - // work, but it will not cause an allocation. - if isASCII(v) { - return v, nil - } - return idna.Lookup.ToASCII(v) -} - -func isASCII(s string) bool { - for i := 0; i < len(s); i++ { - if s[i] >= utf8.RuneSelf { - return false - } - } - return true -} - -// matcher represents the matching rule for a given value in the NO_PROXY list -type matcher interface { - // match returns true if the host and optional port or ip and optional port - // are allowed - match(host, port string, ip net.IP) bool -} - -// allMatch matches on all possible inputs -type allMatch struct{} - -func (a allMatch) match(host, port string, ip net.IP) bool { - return true -} - -type cidrMatch struct { - cidr *net.IPNet -} - -func (m cidrMatch) match(host, port string, ip net.IP) bool { - return m.cidr.Contains(ip) -} - -type ipMatch struct { - ip net.IP - port string -} - -func (m ipMatch) match(host, port string, ip net.IP) bool { - if m.ip.Equal(ip) { - return m.port == "" || m.port == port - } - return false -} - -type domainMatch struct { - host string - port string - - matchHost bool -} - -func (m domainMatch) match(host, port string, ip net.IP) bool { - if ip != nil { - return false - } - if strings.HasSuffix(host, m.host) || (m.matchHost && host == m.host[1:]) { - return m.port == "" || m.port == port - } - return false -} diff --git a/vendor/golang.org/x/net/http2/h2c/h2c.go b/vendor/golang.org/x/net/http2/h2c/h2c.go deleted file mode 100644 index 19e94791..00000000 --- a/vendor/golang.org/x/net/http2/h2c/h2c.go +++ /dev/null @@ -1,234 +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. - -// Package h2c implements the unencrypted "h2c" form of HTTP/2. -// -// The h2c protocol is the non-TLS version of HTTP/2 which is not available from -// net/http or golang.org/x/net/http2. -package h2c - -import ( - "bufio" - "bytes" - "encoding/base64" - "errors" - "fmt" - "io" - "log" - "net" - "net/http" - "net/textproto" - "os" - "strings" - - "golang.org/x/net/http/httpguts" - "golang.org/x/net/http2" -) - -var ( - http2VerboseLogs bool -) - -func init() { - e := os.Getenv("GODEBUG") - if strings.Contains(e, "http2debug=1") || strings.Contains(e, "http2debug=2") { - http2VerboseLogs = true - } -} - -// h2cHandler is a Handler which implements h2c by hijacking the HTTP/1 traffic -// that should be h2c traffic. There are two ways to begin a h2c connection -// (RFC 7540 Section 3.2 and 3.4): (1) Starting with Prior Knowledge - this -// works by starting an h2c connection with a string of bytes that is valid -// HTTP/1, but unlikely to occur in practice and (2) Upgrading from HTTP/1 to -// h2c - this works by using the HTTP/1 Upgrade header to request an upgrade to -// h2c. When either of those situations occur we hijack the HTTP/1 connection, -// convert it to an HTTP/2 connection and pass the net.Conn to http2.ServeConn. -type h2cHandler struct { - Handler http.Handler - s *http2.Server -} - -// NewHandler returns an http.Handler that wraps h, intercepting any h2c -// traffic. If a request is an h2c connection, it's hijacked and redirected to -// s.ServeConn. Otherwise the returned Handler just forwards requests to h. This -// works because h2c is designed to be parseable as valid HTTP/1, but ignored by -// any HTTP server that does not handle h2c. Therefore we leverage the HTTP/1 -// compatible parts of the Go http library to parse and recognize h2c requests. -// Once a request is recognized as h2c, we hijack the connection and convert it -// to an HTTP/2 connection which is understandable to s.ServeConn. (s.ServeConn -// understands HTTP/2 except for the h2c part of it.) -// -// The first request on an h2c connection is read entirely into memory before -// the Handler is called. To limit the memory consumed by this request, wrap -// the result of NewHandler in an http.MaxBytesHandler. -func NewHandler(h http.Handler, s *http2.Server) http.Handler { - return &h2cHandler{ - Handler: h, - s: s, - } -} - -// extractServer extracts existing http.Server instance from http.Request or create an empty http.Server -func extractServer(r *http.Request) *http.Server { - server, ok := r.Context().Value(http.ServerContextKey).(*http.Server) - if ok { - return server - } - return new(http.Server) -} - -// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler. -func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // Handle h2c with prior knowledge (RFC 7540 Section 3.4) - if r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0" { - if http2VerboseLogs { - log.Print("h2c: attempting h2c with prior knowledge.") - } - conn, err := initH2CWithPriorKnowledge(w) - if err != nil { - if http2VerboseLogs { - log.Printf("h2c: error h2c with prior knowledge: %v", err) - } - return - } - defer conn.Close() - s.s.ServeConn(conn, &http2.ServeConnOpts{ - Context: r.Context(), - BaseConfig: extractServer(r), - Handler: s.Handler, - SawClientPreface: true, - }) - return - } - // Handle Upgrade to h2c (RFC 7540 Section 3.2) - if isH2CUpgrade(r.Header) { - conn, settings, err := h2cUpgrade(w, r) - if err != nil { - if http2VerboseLogs { - log.Printf("h2c: error h2c upgrade: %v", err) - } - w.WriteHeader(http.StatusInternalServerError) - return - } - defer conn.Close() - s.s.ServeConn(conn, &http2.ServeConnOpts{ - Context: r.Context(), - BaseConfig: extractServer(r), - Handler: s.Handler, - UpgradeRequest: r, - Settings: settings, - }) - return - } - s.Handler.ServeHTTP(w, r) - return -} - -// initH2CWithPriorKnowledge implements creating a h2c connection with prior -// knowledge (Section 3.4) and creates a net.Conn suitable for http2.ServeConn. -// All we have to do is look for the client preface that is suppose to be part -// of the body, and reforward the client preface on the net.Conn this function -// creates. -func initH2CWithPriorKnowledge(w http.ResponseWriter) (net.Conn, error) { - rc := http.NewResponseController(w) - conn, rw, err := rc.Hijack() - if err != nil { - return nil, err - } - - const expectedBody = "SM\r\n\r\n" - - buf := make([]byte, len(expectedBody)) - n, err := io.ReadFull(rw, buf) - if err != nil { - return nil, fmt.Errorf("h2c: error reading client preface: %s", err) - } - - if string(buf[:n]) == expectedBody { - return newBufConn(conn, rw), nil - } - - conn.Close() - return nil, errors.New("h2c: invalid client preface") -} - -// h2cUpgrade establishes a h2c connection using the HTTP/1 upgrade (Section 3.2). -func h2cUpgrade(w http.ResponseWriter, r *http.Request) (_ net.Conn, settings []byte, err error) { - settings, err = getH2Settings(r.Header) - if err != nil { - return nil, nil, err - } - - body, err := io.ReadAll(r.Body) - if err != nil { - return nil, nil, err - } - r.Body = io.NopCloser(bytes.NewBuffer(body)) - - rc := http.NewResponseController(w) - conn, rw, err := rc.Hijack() - if err != nil { - return nil, nil, err - } - - rw.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n" + - "Connection: Upgrade\r\n" + - "Upgrade: h2c\r\n\r\n")) - return newBufConn(conn, rw), settings, nil -} - -// isH2CUpgrade returns true if the header properly request an upgrade to h2c -// as specified by Section 3.2. -func isH2CUpgrade(h http.Header) bool { - return httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") && - httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings") -} - -// getH2Settings returns the settings in the HTTP2-Settings header. -func getH2Settings(h http.Header) ([]byte, error) { - vals, ok := h[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")] - if !ok { - return nil, errors.New("missing HTTP2-Settings header") - } - if len(vals) != 1 { - return nil, fmt.Errorf("expected 1 HTTP2-Settings. Got: %v", vals) - } - settings, err := base64.RawURLEncoding.DecodeString(vals[0]) - if err != nil { - return nil, err - } - return settings, nil -} - -func newBufConn(conn net.Conn, rw *bufio.ReadWriter) net.Conn { - rw.Flush() - if rw.Reader.Buffered() == 0 { - // If there's no buffered data to be read, - // we can just discard the bufio.ReadWriter. - return conn - } - return &bufConn{conn, rw.Reader} -} - -// bufConn wraps a net.Conn, but reads drain the bufio.Reader first. -type bufConn struct { - net.Conn - *bufio.Reader -} - -func (c *bufConn) Read(p []byte) (int, error) { - if c.Reader == nil { - return c.Conn.Read(p) - } - n := c.Reader.Buffered() - if n == 0 { - c.Reader = nil - return c.Conn.Read(p) - } - if n < len(p) { - p = p[:n] - } - return c.Reader.Read(p) -} diff --git a/vendor/golang.org/x/net/internal/socks/client.go b/vendor/golang.org/x/net/internal/socks/client.go deleted file mode 100644 index 3d6f516a..00000000 --- a/vendor/golang.org/x/net/internal/socks/client.go +++ /dev/null @@ -1,168 +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. - -package socks - -import ( - "context" - "errors" - "io" - "net" - "strconv" - "time" -) - -var ( - noDeadline = time.Time{} - aLongTimeAgo = time.Unix(1, 0) -) - -func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) { - host, port, err := splitHostPort(address) - if err != nil { - return nil, err - } - if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() { - c.SetDeadline(deadline) - defer c.SetDeadline(noDeadline) - } - if ctx != context.Background() { - errCh := make(chan error, 1) - done := make(chan struct{}) - defer func() { - close(done) - if ctxErr == nil { - ctxErr = <-errCh - } - }() - go func() { - select { - case <-ctx.Done(): - c.SetDeadline(aLongTimeAgo) - errCh <- ctx.Err() - case <-done: - errCh <- nil - } - }() - } - - b := make([]byte, 0, 6+len(host)) // the size here is just an estimate - b = append(b, Version5) - if len(d.AuthMethods) == 0 || d.Authenticate == nil { - b = append(b, 1, byte(AuthMethodNotRequired)) - } else { - ams := d.AuthMethods - if len(ams) > 255 { - return nil, errors.New("too many authentication methods") - } - b = append(b, byte(len(ams))) - for _, am := range ams { - b = append(b, byte(am)) - } - } - if _, ctxErr = c.Write(b); ctxErr != nil { - return - } - - if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil { - return - } - if b[0] != Version5 { - return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) - } - am := AuthMethod(b[1]) - if am == AuthMethodNoAcceptableMethods { - return nil, errors.New("no acceptable authentication methods") - } - if d.Authenticate != nil { - if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil { - return - } - } - - b = b[:0] - b = append(b, Version5, byte(d.cmd), 0) - if ip := net.ParseIP(host); ip != nil { - if ip4 := ip.To4(); ip4 != nil { - b = append(b, AddrTypeIPv4) - b = append(b, ip4...) - } else if ip6 := ip.To16(); ip6 != nil { - b = append(b, AddrTypeIPv6) - b = append(b, ip6...) - } else { - return nil, errors.New("unknown address type") - } - } else { - if len(host) > 255 { - return nil, errors.New("FQDN too long") - } - b = append(b, AddrTypeFQDN) - b = append(b, byte(len(host))) - b = append(b, host...) - } - b = append(b, byte(port>>8), byte(port)) - if _, ctxErr = c.Write(b); ctxErr != nil { - return - } - - if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil { - return - } - if b[0] != Version5 { - return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) - } - if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded { - return nil, errors.New("unknown error " + cmdErr.String()) - } - if b[2] != 0 { - return nil, errors.New("non-zero reserved field") - } - l := 2 - var a Addr - switch b[3] { - case AddrTypeIPv4: - l += net.IPv4len - a.IP = make(net.IP, net.IPv4len) - case AddrTypeIPv6: - l += net.IPv6len - a.IP = make(net.IP, net.IPv6len) - case AddrTypeFQDN: - if _, err := io.ReadFull(c, b[:1]); err != nil { - return nil, err - } - l += int(b[0]) - default: - return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3]))) - } - if cap(b) < l { - b = make([]byte, l) - } else { - b = b[:l] - } - if _, ctxErr = io.ReadFull(c, b); ctxErr != nil { - return - } - if a.IP != nil { - copy(a.IP, b) - } else { - a.Name = string(b[:len(b)-2]) - } - a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1]) - return &a, nil -} - -func splitHostPort(address string) (string, int, error) { - host, port, err := net.SplitHostPort(address) - if err != nil { - return "", 0, err - } - portnum, err := strconv.Atoi(port) - if err != nil { - return "", 0, err - } - if 1 > portnum || portnum > 0xffff { - return "", 0, errors.New("port number out of range " + port) - } - return host, portnum, nil -} diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go deleted file mode 100644 index 84fcc32b..00000000 --- a/vendor/golang.org/x/net/internal/socks/socks.go +++ /dev/null @@ -1,317 +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. - -// Package socks provides a SOCKS version 5 client implementation. -// -// SOCKS protocol version 5 is defined in RFC 1928. -// Username/Password authentication for SOCKS version 5 is defined in -// RFC 1929. -package socks - -import ( - "context" - "errors" - "io" - "net" - "strconv" -) - -// A Command represents a SOCKS command. -type Command int - -func (cmd Command) String() string { - switch cmd { - case CmdConnect: - return "socks connect" - case cmdBind: - return "socks bind" - default: - return "socks " + strconv.Itoa(int(cmd)) - } -} - -// An AuthMethod represents a SOCKS authentication method. -type AuthMethod int - -// A Reply represents a SOCKS command reply code. -type Reply int - -func (code Reply) String() string { - switch code { - case StatusSucceeded: - return "succeeded" - case 0x01: - return "general SOCKS server failure" - case 0x02: - return "connection not allowed by ruleset" - case 0x03: - return "network unreachable" - case 0x04: - return "host unreachable" - case 0x05: - return "connection refused" - case 0x06: - return "TTL expired" - case 0x07: - return "command not supported" - case 0x08: - return "address type not supported" - default: - return "unknown code: " + strconv.Itoa(int(code)) - } -} - -// Wire protocol constants. -const ( - Version5 = 0x05 - - AddrTypeIPv4 = 0x01 - AddrTypeFQDN = 0x03 - AddrTypeIPv6 = 0x04 - - CmdConnect Command = 0x01 // establishes an active-open forward proxy connection - cmdBind Command = 0x02 // establishes a passive-open forward proxy connection - - AuthMethodNotRequired AuthMethod = 0x00 // no authentication required - AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password - AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods - - StatusSucceeded Reply = 0x00 -) - -// An Addr represents a SOCKS-specific address. -// Either Name or IP is used exclusively. -type Addr struct { - Name string // fully-qualified domain name - IP net.IP - Port int -} - -func (a *Addr) Network() string { return "socks" } - -func (a *Addr) String() string { - if a == nil { - return "<nil>" - } - port := strconv.Itoa(a.Port) - if a.IP == nil { - return net.JoinHostPort(a.Name, port) - } - return net.JoinHostPort(a.IP.String(), port) -} - -// A Conn represents a forward proxy connection. -type Conn struct { - net.Conn - - boundAddr net.Addr -} - -// BoundAddr returns the address assigned by the proxy server for -// connecting to the command target address from the proxy server. -func (c *Conn) BoundAddr() net.Addr { - if c == nil { - return nil - } - return c.boundAddr -} - -// A Dialer holds SOCKS-specific options. -type Dialer struct { - cmd Command // either CmdConnect or cmdBind - proxyNetwork string // network between a proxy server and a client - proxyAddress string // proxy server address - - // ProxyDial specifies the optional dial function for - // establishing the transport connection. - ProxyDial func(context.Context, string, string) (net.Conn, error) - - // AuthMethods specifies the list of request authentication - // methods. - // If empty, SOCKS client requests only AuthMethodNotRequired. - AuthMethods []AuthMethod - - // Authenticate specifies the optional authentication - // function. It must be non-nil when AuthMethods is not empty. - // It must return an error when the authentication is failed. - Authenticate func(context.Context, io.ReadWriter, AuthMethod) error -} - -// DialContext connects to the provided address on the provided -// network. -// -// The returned error value may be a net.OpError. When the Op field of -// net.OpError contains "socks", the Source field contains a proxy -// server address and the Addr field contains a command target -// address. -// -// See func Dial of the net package of standard library for a -// description of the network and address parameters. -func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { - if err := d.validateTarget(network, address); err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - if ctx == nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")} - } - var err error - var c net.Conn - if d.ProxyDial != nil { - c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress) - } else { - var dd net.Dialer - c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress) - } - if err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - a, err := d.connect(ctx, c, address) - if err != nil { - c.Close() - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - return &Conn{Conn: c, boundAddr: a}, nil -} - -// DialWithConn initiates a connection from SOCKS server to the target -// network and address using the connection c that is already -// connected to the SOCKS server. -// -// It returns the connection's local address assigned by the SOCKS -// server. -func (d *Dialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) { - if err := d.validateTarget(network, address); err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - if ctx == nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")} - } - a, err := d.connect(ctx, c, address) - if err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - return a, nil -} - -// Dial connects to the provided address on the provided network. -// -// Unlike DialContext, it returns a raw transport connection instead -// of a forward proxy connection. -// -// Deprecated: Use DialContext or DialWithConn instead. -func (d *Dialer) Dial(network, address string) (net.Conn, error) { - if err := d.validateTarget(network, address); err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - var err error - var c net.Conn - if d.ProxyDial != nil { - c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress) - } else { - c, err = net.Dial(d.proxyNetwork, d.proxyAddress) - } - if err != nil { - proxy, dst, _ := d.pathAddrs(address) - return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} - } - if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil { - c.Close() - return nil, err - } - return c, nil -} - -func (d *Dialer) validateTarget(network, address string) error { - switch network { - case "tcp", "tcp6", "tcp4": - default: - return errors.New("network not implemented") - } - switch d.cmd { - case CmdConnect, cmdBind: - default: - return errors.New("command not implemented") - } - return nil -} - -func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) { - for i, s := range []string{d.proxyAddress, address} { - host, port, err := splitHostPort(s) - if err != nil { - return nil, nil, err - } - a := &Addr{Port: port} - a.IP = net.ParseIP(host) - if a.IP == nil { - a.Name = host - } - if i == 0 { - proxy = a - } else { - dst = a - } - } - return -} - -// NewDialer returns a new Dialer that dials through the provided -// proxy server's network and address. -func NewDialer(network, address string) *Dialer { - return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect} -} - -const ( - authUsernamePasswordVersion = 0x01 - authStatusSucceeded = 0x00 -) - -// UsernamePassword are the credentials for the username/password -// authentication method. -type UsernamePassword struct { - Username string - Password string -} - -// Authenticate authenticates a pair of username and password with the -// proxy server. -func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error { - switch auth { - case AuthMethodNotRequired: - return nil - case AuthMethodUsernamePassword: - if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) > 255 { - return errors.New("invalid username/password") - } - b := []byte{authUsernamePasswordVersion} - b = append(b, byte(len(up.Username))) - b = append(b, up.Username...) - b = append(b, byte(len(up.Password))) - b = append(b, up.Password...) - // TODO(mikio): handle IO deadlines and cancelation if - // necessary - if _, err := rw.Write(b); err != nil { - return err - } - if _, err := io.ReadFull(rw, b[:2]); err != nil { - return err - } - if b[0] != authUsernamePasswordVersion { - return errors.New("invalid username/password version") - } - if b[1] != authStatusSucceeded { - return errors.New("username/password authentication failed") - } - return nil - } - return errors.New("unsupported authentication method " + strconv.Itoa(int(auth))) -} diff --git a/vendor/golang.org/x/net/proxy/dial.go b/vendor/golang.org/x/net/proxy/dial.go deleted file mode 100644 index 811c2e4e..00000000 --- a/vendor/golang.org/x/net/proxy/dial.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package proxy - -import ( - "context" - "net" -) - -// A ContextDialer dials using a context. -type ContextDialer interface { - DialContext(ctx context.Context, network, address string) (net.Conn, error) -} - -// Dial works like DialContext on net.Dialer but using a dialer returned by FromEnvironment. -// -// The passed ctx is only used for returning the Conn, not the lifetime of the Conn. -// -// Custom dialers (registered via RegisterDialerType) that do not implement ContextDialer -// can leak a goroutine for as long as it takes the underlying Dialer implementation to timeout. -// -// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. -func Dial(ctx context.Context, network, address string) (net.Conn, error) { - d := FromEnvironment() - if xd, ok := d.(ContextDialer); ok { - return xd.DialContext(ctx, network, address) - } - return dialContext(ctx, d, network, address) -} - -// WARNING: this can leak a goroutine for as long as the underlying Dialer implementation takes to timeout -// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. -func dialContext(ctx context.Context, d Dialer, network, address string) (net.Conn, error) { - var ( - conn net.Conn - done = make(chan struct{}, 1) - err error - ) - go func() { - conn, err = d.Dial(network, address) - close(done) - if conn != nil && ctx.Err() != nil { - conn.Close() - } - }() - select { - case <-ctx.Done(): - err = ctx.Err() - case <-done: - } - return conn, err -} diff --git a/vendor/golang.org/x/net/proxy/direct.go b/vendor/golang.org/x/net/proxy/direct.go deleted file mode 100644 index 3d66bdef..00000000 --- a/vendor/golang.org/x/net/proxy/direct.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2011 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 proxy - -import ( - "context" - "net" -) - -type direct struct{} - -// Direct implements Dialer by making network connections directly using net.Dial or net.DialContext. -var Direct = direct{} - -var ( - _ Dialer = Direct - _ ContextDialer = Direct -) - -// Dial directly invokes net.Dial with the supplied parameters. -func (direct) Dial(network, addr string) (net.Conn, error) { - return net.Dial(network, addr) -} - -// DialContext instantiates a net.Dialer and invokes its DialContext receiver with the supplied parameters. -func (direct) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { - var d net.Dialer - return d.DialContext(ctx, network, addr) -} diff --git a/vendor/golang.org/x/net/proxy/per_host.go b/vendor/golang.org/x/net/proxy/per_host.go deleted file mode 100644 index 32bdf435..00000000 --- a/vendor/golang.org/x/net/proxy/per_host.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2011 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 proxy - -import ( - "context" - "net" - "net/netip" - "strings" -) - -// A PerHost directs connections to a default Dialer unless the host name -// requested matches one of a number of exceptions. -type PerHost struct { - def, bypass Dialer - - bypassNetworks []*net.IPNet - bypassIPs []net.IP - bypassZones []string - bypassHosts []string -} - -// NewPerHost returns a PerHost Dialer that directs connections to either -// defaultDialer or bypass, depending on whether the connection matches one of -// the configured rules. -func NewPerHost(defaultDialer, bypass Dialer) *PerHost { - return &PerHost{ - def: defaultDialer, - bypass: bypass, - } -} - -// Dial connects to the address addr on the given network through either -// defaultDialer or bypass. -func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) { - host, _, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } - - return p.dialerForRequest(host).Dial(network, addr) -} - -// DialContext connects to the address addr on the given network through either -// defaultDialer or bypass. -func (p *PerHost) DialContext(ctx context.Context, network, addr string) (c net.Conn, err error) { - host, _, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } - d := p.dialerForRequest(host) - if x, ok := d.(ContextDialer); ok { - return x.DialContext(ctx, network, addr) - } - return dialContext(ctx, d, network, addr) -} - -func (p *PerHost) dialerForRequest(host string) Dialer { - if nip, err := netip.ParseAddr(host); err == nil { - ip := net.IP(nip.AsSlice()) - for _, net := range p.bypassNetworks { - if net.Contains(ip) { - return p.bypass - } - } - for _, bypassIP := range p.bypassIPs { - if bypassIP.Equal(ip) { - return p.bypass - } - } - return p.def - } - - for _, zone := range p.bypassZones { - if strings.HasSuffix(host, zone) { - return p.bypass - } - if host == zone[1:] { - // For a zone ".example.com", we match "example.com" - // too. - return p.bypass - } - } - for _, bypassHost := range p.bypassHosts { - if bypassHost == host { - return p.bypass - } - } - return p.def -} - -// AddFromString parses a string that contains comma-separated values -// specifying hosts that should use the bypass proxy. Each value is either an -// IP address, a CIDR range, a zone (*.example.com) or a host name -// (localhost). A best effort is made to parse the string and errors are -// ignored. -func (p *PerHost) AddFromString(s string) { - hosts := strings.Split(s, ",") - for _, host := range hosts { - host = strings.TrimSpace(host) - if len(host) == 0 { - continue - } - if strings.Contains(host, "/") { - // We assume that it's a CIDR address like 127.0.0.0/8 - if _, net, err := net.ParseCIDR(host); err == nil { - p.AddNetwork(net) - } - continue - } - if nip, err := netip.ParseAddr(host); err == nil { - p.AddIP(net.IP(nip.AsSlice())) - continue - } - if strings.HasPrefix(host, "*.") { - p.AddZone(host[1:]) - continue - } - p.AddHost(host) - } -} - -// AddIP specifies an IP address that will use the bypass proxy. Note that -// this will only take effect if a literal IP address is dialed. A connection -// to a named host will never match an IP. -func (p *PerHost) AddIP(ip net.IP) { - p.bypassIPs = append(p.bypassIPs, ip) -} - -// AddNetwork specifies an IP range that will use the bypass proxy. Note that -// this will only take effect if a literal IP address is dialed. A connection -// to a named host will never match. -func (p *PerHost) AddNetwork(net *net.IPNet) { - p.bypassNetworks = append(p.bypassNetworks, net) -} - -// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of -// "example.com" matches "example.com" and all of its subdomains. -func (p *PerHost) AddZone(zone string) { - zone = strings.TrimSuffix(zone, ".") - if !strings.HasPrefix(zone, ".") { - zone = "." + zone - } - p.bypassZones = append(p.bypassZones, zone) -} - -// AddHost specifies a host name that will use the bypass proxy. -func (p *PerHost) AddHost(host string) { - host = strings.TrimSuffix(host, ".") - p.bypassHosts = append(p.bypassHosts, host) -} diff --git a/vendor/golang.org/x/net/proxy/proxy.go b/vendor/golang.org/x/net/proxy/proxy.go deleted file mode 100644 index 9ff4b9a7..00000000 --- a/vendor/golang.org/x/net/proxy/proxy.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2011 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 proxy provides support for a variety of protocols to proxy network -// data. -package proxy // import "golang.org/x/net/proxy" - -import ( - "errors" - "net" - "net/url" - "os" - "sync" -) - -// A Dialer is a means to establish a connection. -// Custom dialers should also implement ContextDialer. -type Dialer interface { - // Dial connects to the given address via the proxy. - Dial(network, addr string) (c net.Conn, err error) -} - -// Auth contains authentication parameters that specific Dialers may require. -type Auth struct { - User, Password string -} - -// FromEnvironment returns the dialer specified by the proxy-related -// variables in the environment and makes underlying connections -// directly. -func FromEnvironment() Dialer { - return FromEnvironmentUsing(Direct) -} - -// FromEnvironmentUsing returns the dialer specify by the proxy-related -// variables in the environment and makes underlying connections -// using the provided forwarding Dialer (for instance, a *net.Dialer -// with desired configuration). -func FromEnvironmentUsing(forward Dialer) Dialer { - allProxy := allProxyEnv.Get() - if len(allProxy) == 0 { - return forward - } - - proxyURL, err := url.Parse(allProxy) - if err != nil { - return forward - } - proxy, err := FromURL(proxyURL, forward) - if err != nil { - return forward - } - - noProxy := noProxyEnv.Get() - if len(noProxy) == 0 { - return proxy - } - - perHost := NewPerHost(proxy, forward) - perHost.AddFromString(noProxy) - return perHost -} - -// proxySchemes is a map from URL schemes to a function that creates a Dialer -// from a URL with such a scheme. -var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error) - -// RegisterDialerType takes a URL scheme and a function to generate Dialers from -// a URL with that scheme and a forwarding Dialer. Registered schemes are used -// by FromURL. -func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) { - if proxySchemes == nil { - proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error)) - } - proxySchemes[scheme] = f -} - -// FromURL returns a Dialer given a URL specification and an underlying -// Dialer for it to make network requests. -func FromURL(u *url.URL, forward Dialer) (Dialer, error) { - var auth *Auth - if u.User != nil { - auth = new(Auth) - auth.User = u.User.Username() - if p, ok := u.User.Password(); ok { - auth.Password = p - } - } - - switch u.Scheme { - case "socks5", "socks5h": - addr := u.Hostname() - port := u.Port() - if port == "" { - port = "1080" - } - return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward) - } - - // If the scheme doesn't match any of the built-in schemes, see if it - // was registered by another package. - if proxySchemes != nil { - if f, ok := proxySchemes[u.Scheme]; ok { - return f(u, forward) - } - } - - return nil, errors.New("proxy: unknown scheme: " + u.Scheme) -} - -var ( - allProxyEnv = &envOnce{ - names: []string{"ALL_PROXY", "all_proxy"}, - } - noProxyEnv = &envOnce{ - names: []string{"NO_PROXY", "no_proxy"}, - } -) - -// envOnce looks up an environment variable (optionally by multiple -// names) once. It mitigates expensive lookups on some platforms -// (e.g. Windows). -// (Borrowed from net/http/transport.go) -type envOnce struct { - names []string - once sync.Once - val string -} - -func (e *envOnce) Get() string { - e.once.Do(e.init) - return e.val -} - -func (e *envOnce) init() { - for _, n := range e.names { - e.val = os.Getenv(n) - if e.val != "" { - return - } - } -} - -// reset is used by tests -func (e *envOnce) reset() { - e.once = sync.Once{} - e.val = "" -} diff --git a/vendor/golang.org/x/net/proxy/socks5.go b/vendor/golang.org/x/net/proxy/socks5.go deleted file mode 100644 index c91651f9..00000000 --- a/vendor/golang.org/x/net/proxy/socks5.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2011 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 proxy - -import ( - "context" - "net" - - "golang.org/x/net/internal/socks" -) - -// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given -// address with an optional username and password. -// See RFC 1928 and RFC 1929. -func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) { - d := socks.NewDialer(network, address) - if forward != nil { - if f, ok := forward.(ContextDialer); ok { - d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { - return f.DialContext(ctx, network, address) - } - } else { - d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { - return dialContext(ctx, forward, network, address) - } - } - } - if auth != nil { - up := socks.UsernamePassword{ - Username: auth.User, - Password: auth.Password, - } - d.AuthMethods = []socks.AuthMethod{ - socks.AuthMethodNotRequired, - socks.AuthMethodUsernamePassword, - } - d.Authenticate = up.Authenticate - } - return d, nil -} diff --git a/vendor/golang.org/x/oauth2/.travis.yml b/vendor/golang.org/x/oauth2/.travis.yml deleted file mode 100644 index fa139db2..00000000 --- a/vendor/golang.org/x/oauth2/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - tip - -install: - - export GOPATH="$HOME/gopath" - - mkdir -p "$GOPATH/src/golang.org/x" - - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2" - - go get -v -t -d golang.org/x/oauth2/... - -script: - - go test -v golang.org/x/oauth2/... diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md deleted file mode 100644 index dfbed62c..00000000 --- a/vendor/golang.org/x/oauth2/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - -## Filing issues - -When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE deleted file mode 100644 index 2a7cf70d..00000000 --- a/vendor/golang.org/x/oauth2/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md deleted file mode 100644 index 48dbb9d8..00000000 --- a/vendor/golang.org/x/oauth2/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# OAuth2 for Go - -[![Go Reference](https://pkg.go.dev/badge/golang.org/x/oauth2.svg)](https://pkg.go.dev/golang.org/x/oauth2) -[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2) - -oauth2 package contains a client implementation for OAuth 2.0 spec. - -See pkg.go.dev for further documentation and examples. - -* [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) -* [pkg.go.dev/golang.org/x/oauth2/google](https://pkg.go.dev/golang.org/x/oauth2/google) - -## Policy for new endpoints - -We no longer accept new provider-specific packages in this repo if all -they do is add a single endpoint variable. If you just want to add a -single endpoint, add it to the -[pkg.go.dev/golang.org/x/oauth2/endpoints](https://pkg.go.dev/golang.org/x/oauth2/endpoints) -package. - -## Report Issues / Send Patches - -The main issue tracker for the oauth2 repository is located at -https://github.com/golang/oauth2/issues. - -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://go.dev/doc/contribute. - -The git repository is https://go.googlesource.com/oauth2. - -Note: - -* Excluding trivial changes, all contributions should be connected to an existing issue. -* API changes must go through the [change proposal process](https://go.dev/s/proposal-process) before they can be accepted. -* The code owners are listed at [dev.golang.org/owners](https://dev.golang.org/owners#:~:text=x/oauth2). diff --git a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go deleted file mode 100644 index e86346e8..00000000 --- a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go +++ /dev/null @@ -1,124 +0,0 @@ -// 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 clientcredentials implements the OAuth2.0 "client credentials" token flow, -// also known as the "two-legged OAuth 2.0". -// -// This should be used when the client is acting on its own behalf or when the client -// is the resource owner. It may also be used when requesting access to protected -// resources based on an authorization previously arranged with the authorization -// server. -// -// See https://tools.ietf.org/html/rfc6749#section-4.4 -package clientcredentials // import "golang.org/x/oauth2/clientcredentials" - -import ( - "context" - "fmt" - "net/http" - "net/url" - "strings" - - "golang.org/x/oauth2" - "golang.org/x/oauth2/internal" -) - -// Config describes a 2-legged OAuth2 flow, with both the -// client application information and the server's endpoint URLs. -type Config struct { - // ClientID is the application's ID. - ClientID string - - // ClientSecret is the application's secret. - ClientSecret string - - // TokenURL is the resource server's token endpoint - // URL. This is a constant specific to each server. - TokenURL string - - // Scopes specifies optional requested permissions. - Scopes []string - - // EndpointParams specifies additional parameters for requests to the token endpoint. - EndpointParams url.Values - - // AuthStyle optionally specifies how the endpoint wants the - // client ID & client secret sent. The zero value means to - // auto-detect. - AuthStyle oauth2.AuthStyle - - // authStyleCache caches which auth style to use when Endpoint.AuthStyle is - // the zero value (AuthStyleAutoDetect). - authStyleCache internal.LazyAuthStyleCache -} - -// Token uses client credentials to retrieve a token. -// -// The provided context optionally controls which HTTP client is used. See the [oauth2.HTTPClient] variable. -func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) { - return c.TokenSource(ctx).Token() -} - -// Client returns an HTTP client using the provided token. -// The token will auto-refresh as necessary. -// -// The provided context optionally controls which HTTP client -// is returned. See the [oauth2.HTTPClient] variable. -// -// The returned [http.Client] and its Transport should not be modified. -func (c *Config) Client(ctx context.Context) *http.Client { - return oauth2.NewClient(ctx, c.TokenSource(ctx)) -} - -// TokenSource returns a [oauth2.TokenSource] that returns t until t expires, -// automatically refreshing it as necessary using the provided context and the -// client ID and client secret. -// -// Most users will use [Config.Client] instead. -func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource { - source := &tokenSource{ - ctx: ctx, - conf: c, - } - return oauth2.ReuseTokenSource(nil, source) -} - -type tokenSource struct { - ctx context.Context - conf *Config -} - -// Token refreshes the token by using a new client credentials request. -// tokens received this way do not include a refresh token -func (c *tokenSource) Token() (*oauth2.Token, error) { - v := url.Values{ - "grant_type": {"client_credentials"}, - } - if len(c.conf.Scopes) > 0 { - v.Set("scope", strings.Join(c.conf.Scopes, " ")) - } - for k, p := range c.conf.EndpointParams { - // Allow grant_type to be overridden to allow interoperability with - // non-compliant implementations. - if _, ok := v[k]; ok && k != "grant_type" { - return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k) - } - v[k] = p - } - - tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v, internal.AuthStyle(c.conf.AuthStyle), c.conf.authStyleCache.Get()) - if err != nil { - if rErr, ok := err.(*internal.RetrieveError); ok { - return nil, (*oauth2.RetrieveError)(rErr) - } - return nil, err - } - t := &oauth2.Token{ - AccessToken: tk.AccessToken, - TokenType: tk.TokenType, - RefreshToken: tk.RefreshToken, - Expiry: tk.Expiry, - } - return t.WithExtra(tk.Raw), nil -} diff --git a/vendor/golang.org/x/oauth2/deviceauth.go b/vendor/golang.org/x/oauth2/deviceauth.go deleted file mode 100644 index e99c92f3..00000000 --- a/vendor/golang.org/x/oauth2/deviceauth.go +++ /dev/null @@ -1,198 +0,0 @@ -package oauth2 - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "strings" - "time" - - "golang.org/x/oauth2/internal" -) - -// https://datatracker.ietf.org/doc/html/rfc8628#section-3.5 -const ( - errAuthorizationPending = "authorization_pending" - errSlowDown = "slow_down" - errAccessDenied = "access_denied" - errExpiredToken = "expired_token" -) - -// DeviceAuthResponse describes a successful RFC 8628 Device Authorization Response -// https://datatracker.ietf.org/doc/html/rfc8628#section-3.2 -type DeviceAuthResponse struct { - // DeviceCode - DeviceCode string `json:"device_code"` - // UserCode is the code the user should enter at the verification uri - UserCode string `json:"user_code"` - // VerificationURI is where user should enter the user code - VerificationURI string `json:"verification_uri"` - // VerificationURIComplete (if populated) includes the user code in the verification URI. This is typically shown to the user in non-textual form, such as a QR code. - VerificationURIComplete string `json:"verification_uri_complete,omitempty"` - // Expiry is when the device code and user code expire - Expiry time.Time `json:"expires_in,omitempty"` - // Interval is the duration in seconds that Poll should wait between requests - Interval int64 `json:"interval,omitempty"` -} - -func (d DeviceAuthResponse) MarshalJSON() ([]byte, error) { - type Alias DeviceAuthResponse - var expiresIn int64 - if !d.Expiry.IsZero() { - expiresIn = int64(time.Until(d.Expiry).Seconds()) - } - return json.Marshal(&struct { - ExpiresIn int64 `json:"expires_in,omitempty"` - *Alias - }{ - ExpiresIn: expiresIn, - Alias: (*Alias)(&d), - }) - -} - -func (c *DeviceAuthResponse) UnmarshalJSON(data []byte) error { - type Alias DeviceAuthResponse - aux := &struct { - ExpiresIn int64 `json:"expires_in"` - // workaround misspelling of verification_uri - VerificationURL string `json:"verification_url"` - *Alias - }{ - Alias: (*Alias)(c), - } - if err := json.Unmarshal(data, &aux); err != nil { - return err - } - if aux.ExpiresIn != 0 { - c.Expiry = time.Now().UTC().Add(time.Second * time.Duration(aux.ExpiresIn)) - } - if c.VerificationURI == "" { - c.VerificationURI = aux.VerificationURL - } - return nil -} - -// DeviceAuth returns a device auth struct which contains a device code -// and authorization information provided for users to enter on another device. -func (c *Config) DeviceAuth(ctx context.Context, opts ...AuthCodeOption) (*DeviceAuthResponse, error) { - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.1 - v := url.Values{ - "client_id": {c.ClientID}, - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - for _, opt := range opts { - opt.setValue(v) - } - return retrieveDeviceAuth(ctx, c, v) -} - -func retrieveDeviceAuth(ctx context.Context, c *Config, v url.Values) (*DeviceAuthResponse, error) { - if c.Endpoint.DeviceAuthURL == "" { - return nil, errors.New("endpoint missing DeviceAuthURL") - } - - req, err := http.NewRequest("POST", c.Endpoint.DeviceAuthURL, strings.NewReader(v.Encode())) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.Header.Set("Accept", "application/json") - - t := time.Now() - r, err := internal.ContextClient(ctx).Do(req) - if err != nil { - return nil, err - } - - body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) - if err != nil { - return nil, fmt.Errorf("oauth2: cannot auth device: %v", err) - } - if code := r.StatusCode; code < 200 || code > 299 { - return nil, &RetrieveError{ - Response: r, - Body: body, - } - } - - da := &DeviceAuthResponse{} - err = json.Unmarshal(body, &da) - if err != nil { - return nil, fmt.Errorf("unmarshal %s", err) - } - - if !da.Expiry.IsZero() { - // Make a small adjustment to account for time taken by the request - da.Expiry = da.Expiry.Add(-time.Since(t)) - } - - return da, nil -} - -// DeviceAccessToken polls the server to exchange a device code for a token. -func (c *Config) DeviceAccessToken(ctx context.Context, da *DeviceAuthResponse, opts ...AuthCodeOption) (*Token, error) { - if !da.Expiry.IsZero() { - var cancel context.CancelFunc - ctx, cancel = context.WithDeadline(ctx, da.Expiry) - defer cancel() - } - - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.4 - v := url.Values{ - "client_id": {c.ClientID}, - "grant_type": {"urn:ietf:params:oauth:grant-type:device_code"}, - "device_code": {da.DeviceCode}, - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - for _, opt := range opts { - opt.setValue(v) - } - - // "If no value is provided, clients MUST use 5 as the default." - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.2 - interval := da.Interval - if interval == 0 { - interval = 5 - } - - ticker := time.NewTicker(time.Duration(interval) * time.Second) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-ticker.C: - tok, err := retrieveToken(ctx, c, v) - if err == nil { - return tok, nil - } - - e, ok := err.(*RetrieveError) - if !ok { - return nil, err - } - switch e.ErrorCode { - case errSlowDown: - // https://datatracker.ietf.org/doc/html/rfc8628#section-3.5 - // "the interval MUST be increased by 5 seconds for this and all subsequent requests" - interval += 5 - ticker.Reset(time.Duration(interval) * time.Second) - case errAuthorizationPending: - // Do nothing. - case errAccessDenied, errExpiredToken: - fallthrough - default: - return tok, err - } - } - } -} diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go deleted file mode 100644 index 8c7c475f..00000000 --- a/vendor/golang.org/x/oauth2/internal/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2017 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 internal contains support packages for [golang.org/x/oauth2]. -package internal diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go deleted file mode 100644 index 71ea6ad1..00000000 --- a/vendor/golang.org/x/oauth2/internal/oauth2.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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 internal - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" - "fmt" -) - -// ParseKey converts the binary contents of a private key file -// to an [*rsa.PrivateKey]. It detects whether the private key is in a -// PEM container or not. If so, it extracts the private key -// from PEM container before conversion. It only supports PEM -// containers with no passphrase. -func ParseKey(key []byte) (*rsa.PrivateKey, error) { - block, _ := pem.Decode(key) - if block != nil { - key = block.Bytes - } - parsedKey, err := x509.ParsePKCS8PrivateKey(key) - if err != nil { - parsedKey, err = x509.ParsePKCS1PrivateKey(key) - if err != nil { - return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8; parse error: %v", err) - } - } - parsed, ok := parsedKey.(*rsa.PrivateKey) - if !ok { - return nil, errors.New("private key is invalid") - } - return parsed, nil -} diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go deleted file mode 100644 index 8389f246..00000000 --- a/vendor/golang.org/x/oauth2/internal/token.go +++ /dev/null @@ -1,356 +0,0 @@ -// 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 internal - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "math" - "mime" - "net/http" - "net/url" - "strconv" - "strings" - "sync" - "sync/atomic" - "time" -) - -// Token represents the credentials used to authorize -// the requests to access protected resources on the OAuth 2.0 -// provider's backend. -// -// This type is a mirror of [golang.org/x/oauth2.Token] and exists to break -// an otherwise-circular dependency. Other internal packages -// should convert this Token into an [golang.org/x/oauth2.Token] before use. -type Token struct { - // AccessToken is the token that authorizes and authenticates - // the requests. - AccessToken string - - // TokenType is the type of token. - // The Type method returns either this or "Bearer", the default. - TokenType string - - // RefreshToken is a token that's used by the application - // (as opposed to the user) to refresh the access token - // if it expires. - RefreshToken string - - // Expiry is the optional expiration time of the access token. - // - // If zero, TokenSource implementations will reuse the same - // token forever and RefreshToken or equivalent - // mechanisms for that TokenSource will not be used. - Expiry time.Time - - // ExpiresIn is the OAuth2 wire format "expires_in" field, - // which specifies how many seconds later the token expires, - // relative to an unknown time base approximately around "now". - // It is the application's responsibility to populate - // `Expiry` from `ExpiresIn` when required. - ExpiresIn int64 `json:"expires_in,omitempty"` - - // Raw optionally contains extra metadata from the server - // when updating a token. - Raw any -} - -// tokenJSON is the struct representing the HTTP response from OAuth2 -// providers returning a token or error in JSON form. -// https://datatracker.ietf.org/doc/html/rfc6749#section-5.1 -type tokenJSON struct { - AccessToken string `json:"access_token"` - TokenType string `json:"token_type"` - RefreshToken string `json:"refresh_token"` - ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number - // error fields - // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 - ErrorCode string `json:"error"` - ErrorDescription string `json:"error_description"` - ErrorURI string `json:"error_uri"` -} - -func (e *tokenJSON) expiry() (t time.Time) { - if v := e.ExpiresIn; v != 0 { - return time.Now().Add(time.Duration(v) * time.Second) - } - return -} - -type expirationTime int32 - -func (e *expirationTime) UnmarshalJSON(b []byte) error { - if len(b) == 0 || string(b) == "null" { - return nil - } - var n json.Number - err := json.Unmarshal(b, &n) - if err != nil { - return err - } - i, err := n.Int64() - if err != nil { - return err - } - if i > math.MaxInt32 { - i = math.MaxInt32 - } - *e = expirationTime(i) - return nil -} - -// AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type. -type AuthStyle int - -const ( - AuthStyleUnknown AuthStyle = 0 - AuthStyleInParams AuthStyle = 1 - AuthStyleInHeader AuthStyle = 2 -) - -// LazyAuthStyleCache is a backwards compatibility compromise to let Configs -// have a lazily-initialized AuthStyleCache. -// -// The two users of this, oauth2.Config and oauth2/clientcredentials.Config, -// both would ideally just embed an unexported AuthStyleCache but because both -// were historically allowed to be copied by value we can't retroactively add an -// uncopyable Mutex to them. -// -// We could use an atomic.Pointer, but that was added recently enough (in Go -// 1.18) that we'd break Go 1.17 users where the tests as of 2023-08-03 -// still pass. By using an atomic.Value, it supports both Go 1.17 and -// copying by value, even if that's not ideal. -type LazyAuthStyleCache struct { - v atomic.Value // of *AuthStyleCache -} - -func (lc *LazyAuthStyleCache) Get() *AuthStyleCache { - if c, ok := lc.v.Load().(*AuthStyleCache); ok { - return c - } - c := new(AuthStyleCache) - if !lc.v.CompareAndSwap(nil, c) { - c = lc.v.Load().(*AuthStyleCache) - } - return c -} - -type authStyleCacheKey struct { - url string - clientID string -} - -// AuthStyleCache is the set of tokenURLs we've successfully used via -// RetrieveToken and which style auth we ended up using. -// It's called a cache, but it doesn't (yet?) shrink. It's expected that -// the set of OAuth2 servers a program contacts over time is fixed and -// small. -type AuthStyleCache struct { - mu sync.Mutex - m map[authStyleCacheKey]AuthStyle -} - -// lookupAuthStyle reports which auth style we last used with tokenURL -// when calling RetrieveToken and whether we have ever done so. -func (c *AuthStyleCache) lookupAuthStyle(tokenURL, clientID string) (style AuthStyle, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() - style, ok = c.m[authStyleCacheKey{tokenURL, clientID}] - return -} - -// setAuthStyle adds an entry to authStyleCache, documented above. -func (c *AuthStyleCache) setAuthStyle(tokenURL, clientID string, v AuthStyle) { - c.mu.Lock() - defer c.mu.Unlock() - if c.m == nil { - c.m = make(map[authStyleCacheKey]AuthStyle) - } - c.m[authStyleCacheKey{tokenURL, clientID}] = v -} - -// newTokenRequest returns a new *http.Request to retrieve a new token -// from tokenURL using the provided clientID, clientSecret, and POST -// body parameters. -// -// inParams is whether the clientID & clientSecret should be encoded -// as the POST body. An 'inParams' value of true means to send it in -// the POST body (along with any values in v); false means to send it -// in the Authorization header. -func newTokenRequest(tokenURL, clientID, clientSecret string, v url.Values, authStyle AuthStyle) (*http.Request, error) { - if authStyle == AuthStyleInParams { - v = cloneURLValues(v) - if clientID != "" { - v.Set("client_id", clientID) - } - if clientSecret != "" { - v.Set("client_secret", clientSecret) - } - } - req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode())) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - if authStyle == AuthStyleInHeader { - req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) - } - return req, nil -} - -func cloneURLValues(v url.Values) url.Values { - v2 := make(url.Values, len(v)) - for k, vv := range v { - v2[k] = append([]string(nil), vv...) - } - return v2 -} - -func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, styleCache *AuthStyleCache) (*Token, error) { - needsAuthStyleProbe := authStyle == AuthStyleUnknown - if needsAuthStyleProbe { - if style, ok := styleCache.lookupAuthStyle(tokenURL, clientID); ok { - authStyle = style - needsAuthStyleProbe = false - } else { - authStyle = AuthStyleInHeader // the first way we'll try - } - } - req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) - if err != nil { - return nil, err - } - token, err := doTokenRoundTrip(ctx, req) - if err != nil && needsAuthStyleProbe { - // If we get an error, assume the server wants the - // clientID & clientSecret in a different form. - // See https://code.google.com/p/goauth2/issues/detail?id=31 for background. - // In summary: - // - Reddit only accepts client secret in the Authorization header - // - Dropbox accepts either it in URL param or Auth header, but not both. - // - Google only accepts URL param (not spec compliant?), not Auth header - // - Stripe only accepts client secret in Auth header with Bearer method, not Basic - // - // We used to maintain a big table in this code of all the sites and which way - // they went, but maintaining it didn't scale & got annoying. - // So just try both ways. - authStyle = AuthStyleInParams // the second way we'll try - req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) - token, err = doTokenRoundTrip(ctx, req) - } - if needsAuthStyleProbe && err == nil { - styleCache.setAuthStyle(tokenURL, clientID, authStyle) - } - // Don't overwrite `RefreshToken` with an empty value - // if this was a token refreshing request. - if token != nil && token.RefreshToken == "" { - token.RefreshToken = v.Get("refresh_token") - } - return token, err -} - -func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { - r, err := ContextClient(ctx).Do(req.WithContext(ctx)) - if err != nil { - return nil, err - } - body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) - r.Body.Close() - if err != nil { - return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) - } - - failureStatus := r.StatusCode < 200 || r.StatusCode > 299 - retrieveError := &RetrieveError{ - Response: r, - Body: body, - // attempt to populate error detail below - } - - var token *Token - content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) - switch content { - case "application/x-www-form-urlencoded", "text/plain": - // some endpoints return a query string - vals, err := url.ParseQuery(string(body)) - if err != nil { - if failureStatus { - return nil, retrieveError - } - return nil, fmt.Errorf("oauth2: cannot parse response: %v", err) - } - retrieveError.ErrorCode = vals.Get("error") - retrieveError.ErrorDescription = vals.Get("error_description") - retrieveError.ErrorURI = vals.Get("error_uri") - token = &Token{ - AccessToken: vals.Get("access_token"), - TokenType: vals.Get("token_type"), - RefreshToken: vals.Get("refresh_token"), - Raw: vals, - } - e := vals.Get("expires_in") - expires, _ := strconv.Atoi(e) - if expires != 0 { - token.Expiry = time.Now().Add(time.Duration(expires) * time.Second) - } - default: - var tj tokenJSON - if err = json.Unmarshal(body, &tj); err != nil { - if failureStatus { - return nil, retrieveError - } - return nil, fmt.Errorf("oauth2: cannot parse json: %v", err) - } - retrieveError.ErrorCode = tj.ErrorCode - retrieveError.ErrorDescription = tj.ErrorDescription - retrieveError.ErrorURI = tj.ErrorURI - token = &Token{ - AccessToken: tj.AccessToken, - TokenType: tj.TokenType, - RefreshToken: tj.RefreshToken, - Expiry: tj.expiry(), - ExpiresIn: int64(tj.ExpiresIn), - Raw: make(map[string]any), - } - json.Unmarshal(body, &token.Raw) // no error checks for optional fields - } - // according to spec, servers should respond status 400 in error case - // https://www.rfc-editor.org/rfc/rfc6749#section-5.2 - // but some unorthodox servers respond 200 in error case - if failureStatus || retrieveError.ErrorCode != "" { - return nil, retrieveError - } - if token.AccessToken == "" { - return nil, errors.New("oauth2: server response missing access_token") - } - return token, nil -} - -// mirrors oauth2.RetrieveError -type RetrieveError struct { - Response *http.Response - Body []byte - ErrorCode string - ErrorDescription string - ErrorURI string -} - -func (r *RetrieveError) Error() string { - if r.ErrorCode != "" { - s := fmt.Sprintf("oauth2: %q", r.ErrorCode) - if r.ErrorDescription != "" { - s += fmt.Sprintf(" %q", r.ErrorDescription) - } - if r.ErrorURI != "" { - s += fmt.Sprintf(" %q", r.ErrorURI) - } - return s - } - return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) -} diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go deleted file mode 100644 index afc0aeb2..00000000 --- a/vendor/golang.org/x/oauth2/internal/transport.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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 internal - -import ( - "context" - "net/http" -) - -// HTTPClient is the context key to use with [context.WithValue] -// to associate an [*http.Client] value with a context. -var HTTPClient ContextKey - -// ContextKey is just an empty struct. It exists so HTTPClient can be -// an immutable public variable with a unique type. It's immutable -// because nobody else can create a ContextKey, being unexported. -type ContextKey struct{} - -func ContextClient(ctx context.Context) *http.Client { - if ctx != nil { - if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { - return hc - } - } - return http.DefaultClient -} diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go deleted file mode 100644 index de34feb8..00000000 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ /dev/null @@ -1,424 +0,0 @@ -// 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 oauth2 provides support for making -// OAuth2 authorized and authenticated HTTP requests, -// as specified in RFC 6749. -// It can additionally grant authorization with Bearer JWT. -package oauth2 // import "golang.org/x/oauth2" - -import ( - "bytes" - "context" - "errors" - "net/http" - "net/url" - "strings" - "sync" - "time" - - "golang.org/x/oauth2/internal" -) - -// NoContext is the default context you should supply if not using -// your own [context.Context]. -// -// Deprecated: Use [context.Background] or [context.TODO] instead. -var NoContext = context.TODO() - -// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. -// -// Deprecated: this function no longer does anything. Caller code that -// wants to avoid potential extra HTTP requests made during -// auto-probing of the provider's auth style should set -// Endpoint.AuthStyle. -func RegisterBrokenAuthHeaderProvider(tokenURL string) {} - -// Config describes a typical 3-legged OAuth2 flow, with both the -// client application information and the server's endpoint URLs. -// For the client credentials 2-legged OAuth2 flow, see the -// [golang.org/x/oauth2/clientcredentials] package. -type Config struct { - // ClientID is the application's ID. - ClientID string - - // ClientSecret is the application's secret. - ClientSecret string - - // Endpoint contains the authorization server's token endpoint - // URLs. These are constants specific to each server and are - // often available via site-specific packages, such as - // google.Endpoint or github.Endpoint. - Endpoint Endpoint - - // RedirectURL is the URL to redirect users going through - // the OAuth flow, after the resource owner's URLs. - RedirectURL string - - // Scopes specifies optional requested permissions. - Scopes []string - - // authStyleCache caches which auth style to use when Endpoint.AuthStyle is - // the zero value (AuthStyleAutoDetect). - authStyleCache internal.LazyAuthStyleCache -} - -// A TokenSource is anything that can return a token. -type TokenSource interface { - // Token returns a token or an error. - // Token must be safe for concurrent use by multiple goroutines. - // The returned Token must not be modified. - Token() (*Token, error) -} - -// Endpoint represents an OAuth 2.0 provider's authorization and token -// endpoint URLs. -type Endpoint struct { - AuthURL string - DeviceAuthURL string - TokenURL string - - // AuthStyle optionally specifies how the endpoint wants the - // client ID & client secret sent. The zero value means to - // auto-detect. - AuthStyle AuthStyle -} - -// AuthStyle represents how requests for tokens are authenticated -// to the server. -type AuthStyle int - -const ( - // AuthStyleAutoDetect means to auto-detect which authentication - // style the provider wants by trying both ways and caching - // the successful way for the future. - AuthStyleAutoDetect AuthStyle = 0 - - // AuthStyleInParams sends the "client_id" and "client_secret" - // in the POST body as application/x-www-form-urlencoded parameters. - AuthStyleInParams AuthStyle = 1 - - // AuthStyleInHeader sends the client_id and client_password - // using HTTP Basic Authorization. This is an optional style - // described in the OAuth2 RFC 6749 section 2.3.1. - AuthStyleInHeader AuthStyle = 2 -) - -var ( - // AccessTypeOnline and AccessTypeOffline are options passed - // to the Options.AuthCodeURL method. They modify the - // "access_type" field that gets sent in the URL returned by - // AuthCodeURL. - // - // Online is the default if neither is specified. If your - // application needs to refresh access tokens when the user - // is not present at the browser, then use offline. This will - // result in your application obtaining a refresh token the - // first time your application exchanges an authorization - // code for a user. - AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online") - AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline") - - // ApprovalForce forces the users to view the consent dialog - // and confirm the permissions request at the URL returned - // from AuthCodeURL, even if they've already done so. - ApprovalForce AuthCodeOption = SetAuthURLParam("prompt", "consent") -) - -// An AuthCodeOption is passed to Config.AuthCodeURL. -type AuthCodeOption interface { - setValue(url.Values) -} - -type setParam struct{ k, v string } - -func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) } - -// SetAuthURLParam builds an [AuthCodeOption] which passes key/value parameters -// to a provider's authorization endpoint. -func SetAuthURLParam(key, value string) AuthCodeOption { - return setParam{key, value} -} - -// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page -// that asks for permissions for the required scopes explicitly. -// -// State is an opaque value used by the client to maintain state between the -// request and callback. The authorization server includes this value when -// redirecting the user agent back to the client. -// -// Opts may include [AccessTypeOnline] or [AccessTypeOffline], as well -// as [ApprovalForce]. -// -// To protect against CSRF attacks, opts should include a PKCE challenge -// (S256ChallengeOption). Not all servers support PKCE. An alternative is to -// generate a random state parameter and verify it after exchange. -// See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12 (predating -// PKCE), https://www.oauth.com/oauth2-servers/pkce/ and -// https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.html#name-cross-site-request-forgery (describing both approaches) -func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { - var buf bytes.Buffer - buf.WriteString(c.Endpoint.AuthURL) - v := url.Values{ - "response_type": {"code"}, - "client_id": {c.ClientID}, - } - if c.RedirectURL != "" { - v.Set("redirect_uri", c.RedirectURL) - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - if state != "" { - v.Set("state", state) - } - for _, opt := range opts { - opt.setValue(v) - } - if strings.Contains(c.Endpoint.AuthURL, "?") { - buf.WriteByte('&') - } else { - buf.WriteByte('?') - } - buf.WriteString(v.Encode()) - return buf.String() -} - -// PasswordCredentialsToken converts a resource owner username and password -// pair into a token. -// -// Per the RFC, this grant type should only be used "when there is a high -// degree of trust between the resource owner and the client (e.g., the client -// is part of the device operating system or a highly privileged application), -// and when other authorization grant types are not available." -// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. -// -// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable. -func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { - v := url.Values{ - "grant_type": {"password"}, - "username": {username}, - "password": {password}, - } - if len(c.Scopes) > 0 { - v.Set("scope", strings.Join(c.Scopes, " ")) - } - return retrieveToken(ctx, c, v) -} - -// Exchange converts an authorization code into a token. -// -// It is used after a resource provider redirects the user back -// to the Redirect URI (the URL obtained from AuthCodeURL). -// -// The provided context optionally controls which HTTP client is used. See the [HTTPClient] variable. -// -// The code will be in the [http.Request.FormValue]("code"). Before -// calling Exchange, be sure to validate [http.Request.FormValue]("state") if you are -// using it to protect against CSRF attacks. -// -// If using PKCE to protect against CSRF attacks, opts should include a -// VerifierOption. -func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) { - v := url.Values{ - "grant_type": {"authorization_code"}, - "code": {code}, - } - if c.RedirectURL != "" { - v.Set("redirect_uri", c.RedirectURL) - } - for _, opt := range opts { - opt.setValue(v) - } - return retrieveToken(ctx, c, v) -} - -// Client returns an HTTP client using the provided token. -// The token will auto-refresh as necessary. The underlying -// HTTP transport will be obtained using the provided context. -// The returned client and its Transport should not be modified. -func (c *Config) Client(ctx context.Context, t *Token) *http.Client { - return NewClient(ctx, c.TokenSource(ctx, t)) -} - -// TokenSource returns a [TokenSource] that returns t until t expires, -// automatically refreshing it as necessary using the provided context. -// -// Most users will use [Config.Client] instead. -func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource { - tkr := &tokenRefresher{ - ctx: ctx, - conf: c, - } - if t != nil { - tkr.refreshToken = t.RefreshToken - } - return &reuseTokenSource{ - t: t, - new: tkr, - } -} - -// tokenRefresher is a TokenSource that makes "grant_type=refresh_token" -// HTTP requests to renew a token using a RefreshToken. -type tokenRefresher struct { - ctx context.Context // used to get HTTP requests - conf *Config - refreshToken string -} - -// WARNING: Token is not safe for concurrent access, as it -// updates the tokenRefresher's refreshToken field. -// Within this package, it is used by reuseTokenSource which -// synchronizes calls to this method with its own mutex. -func (tf *tokenRefresher) Token() (*Token, error) { - if tf.refreshToken == "" { - return nil, errors.New("oauth2: token expired and refresh token is not set") - } - - tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{ - "grant_type": {"refresh_token"}, - "refresh_token": {tf.refreshToken}, - }) - - if err != nil { - return nil, err - } - if tf.refreshToken != tk.RefreshToken { - tf.refreshToken = tk.RefreshToken - } - return tk, nil -} - -// reuseTokenSource is a TokenSource that holds a single token in memory -// and validates its expiry before each call to retrieve it with -// Token. If it's expired, it will be auto-refreshed using the -// new TokenSource. -type reuseTokenSource struct { - new TokenSource // called when t is expired. - - mu sync.Mutex // guards t - t *Token - - expiryDelta time.Duration -} - -// Token returns the current token if it's still valid, else will -// refresh the current token and return the new one. -func (s *reuseTokenSource) Token() (*Token, error) { - s.mu.Lock() - defer s.mu.Unlock() - if s.t.Valid() { - return s.t, nil - } - t, err := s.new.Token() - if err != nil { - return nil, err - } - t.expiryDelta = s.expiryDelta - s.t = t - return t, nil -} - -// StaticTokenSource returns a [TokenSource] that always returns the same token. -// Because the provided token t is never refreshed, StaticTokenSource is only -// useful for tokens that never expire. -func StaticTokenSource(t *Token) TokenSource { - return staticTokenSource{t} -} - -// staticTokenSource is a TokenSource that always returns the same Token. -type staticTokenSource struct { - t *Token -} - -func (s staticTokenSource) Token() (*Token, error) { - return s.t, nil -} - -// HTTPClient is the context key to use with [context.WithValue] -// to associate a [*http.Client] value with a context. -var HTTPClient internal.ContextKey - -// NewClient creates an [*http.Client] from a [context.Context] and [TokenSource]. -// The returned client is not valid beyond the lifetime of the context. -// -// Note that if a custom [*http.Client] is provided via the [context.Context] it -// is used only for token acquisition and is not used to configure the -// [*http.Client] returned from NewClient. -// -// As a special case, if src is nil, a non-OAuth2 client is returned -// using the provided context. This exists to support related OAuth2 -// packages. -func NewClient(ctx context.Context, src TokenSource) *http.Client { - if src == nil { - return internal.ContextClient(ctx) - } - cc := internal.ContextClient(ctx) - return &http.Client{ - Transport: &Transport{ - Base: cc.Transport, - Source: ReuseTokenSource(nil, src), - }, - CheckRedirect: cc.CheckRedirect, - Jar: cc.Jar, - Timeout: cc.Timeout, - } -} - -// ReuseTokenSource returns a [TokenSource] which repeatedly returns the -// same token as long as it's valid, starting with t. -// When its cached token is invalid, a new token is obtained from src. -// -// ReuseTokenSource is typically used to reuse tokens from a cache -// (such as a file on disk) between runs of a program, rather than -// obtaining new tokens unnecessarily. -// -// The initial token t may be nil, in which case the [TokenSource] is -// wrapped in a caching version if it isn't one already. This also -// means it's always safe to wrap ReuseTokenSource around any other -// [TokenSource] without adverse effects. -func ReuseTokenSource(t *Token, src TokenSource) TokenSource { - // Don't wrap a reuseTokenSource in itself. That would work, - // but cause an unnecessary number of mutex operations. - // Just build the equivalent one. - if rt, ok := src.(*reuseTokenSource); ok { - if t == nil { - // Just use it directly. - return rt - } - src = rt.new - } - return &reuseTokenSource{ - t: t, - new: src, - } -} - -// ReuseTokenSourceWithExpiry returns a [TokenSource] that acts in the same manner as the -// [TokenSource] returned by [ReuseTokenSource], except the expiry buffer is -// configurable. The expiration time of a token is calculated as -// t.Expiry.Add(-earlyExpiry). -func ReuseTokenSourceWithExpiry(t *Token, src TokenSource, earlyExpiry time.Duration) TokenSource { - // Don't wrap a reuseTokenSource in itself. That would work, - // but cause an unnecessary number of mutex operations. - // Just build the equivalent one. - if rt, ok := src.(*reuseTokenSource); ok { - if t == nil { - // Just use it directly, but set the expiryDelta to earlyExpiry, - // so the behavior matches what the user expects. - rt.expiryDelta = earlyExpiry - return rt - } - src = rt.new - } - if t != nil { - t.expiryDelta = earlyExpiry - } - return &reuseTokenSource{ - t: t, - new: src, - expiryDelta: earlyExpiry, - } -} diff --git a/vendor/golang.org/x/oauth2/pkce.go b/vendor/golang.org/x/oauth2/pkce.go deleted file mode 100644 index cea8374d..00000000 --- a/vendor/golang.org/x/oauth2/pkce.go +++ /dev/null @@ -1,69 +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 oauth2 - -import ( - "crypto/rand" - "crypto/sha256" - "encoding/base64" - "net/url" -) - -const ( - codeChallengeKey = "code_challenge" - codeChallengeMethodKey = "code_challenge_method" - codeVerifierKey = "code_verifier" -) - -// GenerateVerifier generates a PKCE code verifier with 32 octets of randomness. -// This follows recommendations in RFC 7636. -// -// A fresh verifier should be generated for each authorization. -// The resulting verifier should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth] -// with [S256ChallengeOption], and to [Config.Exchange] or [Config.DeviceAccessToken] -// with [VerifierOption]. -func GenerateVerifier() string { - // "RECOMMENDED that the output of a suitable random number generator be - // used to create a 32-octet sequence. The octet sequence is then - // base64url-encoded to produce a 43-octet URL-safe string to use as the - // code verifier." - // https://datatracker.ietf.org/doc/html/rfc7636#section-4.1 - data := make([]byte, 32) - if _, err := rand.Read(data); err != nil { - panic(err) - } - return base64.RawURLEncoding.EncodeToString(data) -} - -// VerifierOption returns a PKCE code verifier [AuthCodeOption]. It should only be -// passed to [Config.Exchange] or [Config.DeviceAccessToken]. -func VerifierOption(verifier string) AuthCodeOption { - return setParam{k: codeVerifierKey, v: verifier} -} - -// S256ChallengeFromVerifier returns a PKCE code challenge derived from verifier with method S256. -// -// Prefer to use [S256ChallengeOption] where possible. -func S256ChallengeFromVerifier(verifier string) string { - sha := sha256.Sum256([]byte(verifier)) - return base64.RawURLEncoding.EncodeToString(sha[:]) -} - -// S256ChallengeOption derives a PKCE code challenge derived from verifier with -// method S256. It should be passed to [Config.AuthCodeURL] or [Config.DeviceAuth] -// only. -func S256ChallengeOption(verifier string) AuthCodeOption { - return challengeOption{ - challenge_method: "S256", - challenge: S256ChallengeFromVerifier(verifier), - } -} - -type challengeOption struct{ challenge_method, challenge string } - -func (p challengeOption) setValue(m url.Values) { - m.Set(codeChallengeMethodKey, p.challenge_method) - m.Set(codeChallengeKey, p.challenge) -} diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go deleted file mode 100644 index 239ec329..00000000 --- a/vendor/golang.org/x/oauth2/token.go +++ /dev/null @@ -1,213 +0,0 @@ -// 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 oauth2 - -import ( - "context" - "fmt" - "net/http" - "net/url" - "strconv" - "strings" - "time" - - "golang.org/x/oauth2/internal" -) - -// defaultExpiryDelta determines how earlier a token should be considered -// expired than its actual expiration time. It is used to avoid late -// expirations due to client-server time mismatches. -const defaultExpiryDelta = 10 * time.Second - -// Token represents the credentials used to authorize -// the requests to access protected resources on the OAuth 2.0 -// provider's backend. -// -// Most users of this package should not access fields of Token -// directly. They're exported mostly for use by related packages -// implementing derivative OAuth2 flows. -type Token struct { - // AccessToken is the token that authorizes and authenticates - // the requests. - AccessToken string `json:"access_token"` - - // TokenType is the type of token. - // The Type method returns either this or "Bearer", the default. - TokenType string `json:"token_type,omitempty"` - - // RefreshToken is a token that's used by the application - // (as opposed to the user) to refresh the access token - // if it expires. - RefreshToken string `json:"refresh_token,omitempty"` - - // Expiry is the optional expiration time of the access token. - // - // If zero, [TokenSource] implementations will reuse the same - // token forever and RefreshToken or equivalent - // mechanisms for that TokenSource will not be used. - Expiry time.Time `json:"expiry,omitempty"` - - // ExpiresIn is the OAuth2 wire format "expires_in" field, - // which specifies how many seconds later the token expires, - // relative to an unknown time base approximately around "now". - // It is the application's responsibility to populate - // `Expiry` from `ExpiresIn` when required. - ExpiresIn int64 `json:"expires_in,omitempty"` - - // raw optionally contains extra metadata from the server - // when updating a token. - raw any - - // expiryDelta is used to calculate when a token is considered - // expired, by subtracting from Expiry. If zero, defaultExpiryDelta - // is used. - expiryDelta time.Duration -} - -// Type returns t.TokenType if non-empty, else "Bearer". -func (t *Token) Type() string { - if strings.EqualFold(t.TokenType, "bearer") { - return "Bearer" - } - if strings.EqualFold(t.TokenType, "mac") { - return "MAC" - } - if strings.EqualFold(t.TokenType, "basic") { - return "Basic" - } - if t.TokenType != "" { - return t.TokenType - } - return "Bearer" -} - -// SetAuthHeader sets the Authorization header to r using the access -// token in t. -// -// This method is unnecessary when using [Transport] or an HTTP Client -// returned by this package. -func (t *Token) SetAuthHeader(r *http.Request) { - r.Header.Set("Authorization", t.Type()+" "+t.AccessToken) -} - -// WithExtra returns a new [Token] that's a clone of t, but using the -// provided raw extra map. This is only intended for use by packages -// implementing derivative OAuth2 flows. -func (t *Token) WithExtra(extra any) *Token { - t2 := new(Token) - *t2 = *t - t2.raw = extra - return t2 -} - -// Extra returns an extra field. -// Extra fields are key-value pairs returned by the server as a -// part of the token retrieval response. -func (t *Token) Extra(key string) any { - if raw, ok := t.raw.(map[string]any); ok { - return raw[key] - } - - vals, ok := t.raw.(url.Values) - if !ok { - return nil - } - - v := vals.Get(key) - switch s := strings.TrimSpace(v); strings.Count(s, ".") { - case 0: // Contains no "."; try to parse as int - if i, err := strconv.ParseInt(s, 10, 64); err == nil { - return i - } - case 1: // Contains a single "."; try to parse as float - if f, err := strconv.ParseFloat(s, 64); err == nil { - return f - } - } - - return v -} - -// timeNow is time.Now but pulled out as a variable for tests. -var timeNow = time.Now - -// expired reports whether the token is expired. -// t must be non-nil. -func (t *Token) expired() bool { - if t.Expiry.IsZero() { - return false - } - - expiryDelta := defaultExpiryDelta - if t.expiryDelta != 0 { - expiryDelta = t.expiryDelta - } - return t.Expiry.Round(0).Add(-expiryDelta).Before(timeNow()) -} - -// Valid reports whether t is non-nil, has an AccessToken, and is not expired. -func (t *Token) Valid() bool { - return t != nil && t.AccessToken != "" && !t.expired() -} - -// tokenFromInternal maps an *internal.Token struct into -// a *Token struct. -func tokenFromInternal(t *internal.Token) *Token { - if t == nil { - return nil - } - return &Token{ - AccessToken: t.AccessToken, - TokenType: t.TokenType, - RefreshToken: t.RefreshToken, - Expiry: t.Expiry, - ExpiresIn: t.ExpiresIn, - raw: t.Raw, - } -} - -// retrieveToken takes a *Config and uses that to retrieve an *internal.Token. -// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along -// with an error. -func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { - tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), c.authStyleCache.Get()) - if err != nil { - if rErr, ok := err.(*internal.RetrieveError); ok { - return nil, (*RetrieveError)(rErr) - } - return nil, err - } - return tokenFromInternal(tk), nil -} - -// RetrieveError is the error returned when the token endpoint returns a -// non-2XX HTTP status code or populates RFC 6749's 'error' parameter. -// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 -type RetrieveError struct { - Response *http.Response - // Body is the body that was consumed by reading Response.Body. - // It may be truncated. - Body []byte - // ErrorCode is RFC 6749's 'error' parameter. - ErrorCode string - // ErrorDescription is RFC 6749's 'error_description' parameter. - ErrorDescription string - // ErrorURI is RFC 6749's 'error_uri' parameter. - ErrorURI string -} - -func (r *RetrieveError) Error() string { - if r.ErrorCode != "" { - s := fmt.Sprintf("oauth2: %q", r.ErrorCode) - if r.ErrorDescription != "" { - s += fmt.Sprintf(" %q", r.ErrorDescription) - } - if r.ErrorURI != "" { - s += fmt.Sprintf(" %q", r.ErrorURI) - } - return s - } - return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) -} diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go deleted file mode 100644 index 8bbebbac..00000000 --- a/vendor/golang.org/x/oauth2/transport.go +++ /dev/null @@ -1,75 +0,0 @@ -// 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 oauth2 - -import ( - "errors" - "log" - "net/http" - "sync" -) - -// Transport is an [http.RoundTripper] that makes OAuth 2.0 HTTP requests, -// wrapping a base [http.RoundTripper] and adding an Authorization header -// with a token from the supplied [TokenSource]. -// -// Transport is a low-level mechanism. Most code will use the -// higher-level [Config.Client] method instead. -type Transport struct { - // Source supplies the token to add to outgoing requests' - // Authorization headers. - Source TokenSource - - // Base is the base RoundTripper used to make HTTP requests. - // If nil, http.DefaultTransport is used. - Base http.RoundTripper -} - -// RoundTrip authorizes and authenticates the request with an -// access token from Transport's Source. -func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { - reqBodyClosed := false - if req.Body != nil { - defer func() { - if !reqBodyClosed { - req.Body.Close() - } - }() - } - - if t.Source == nil { - return nil, errors.New("oauth2: Transport's Source is nil") - } - token, err := t.Source.Token() - if err != nil { - return nil, err - } - - req2 := req.Clone(req.Context()) - token.SetAuthHeader(req2) - - // req.Body is assumed to be closed by the base RoundTripper. - reqBodyClosed = true - return t.base().RoundTrip(req2) -} - -var cancelOnce sync.Once - -// CancelRequest does nothing. It used to be a legacy cancellation mechanism -// but now only it only logs on first use to warn that it's deprecated. -// -// Deprecated: use contexts for cancellation instead. -func (t *Transport) CancelRequest(req *http.Request) { - cancelOnce.Do(func() { - log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts") - }) -} - -func (t *Transport) base() http.RoundTripper { - if t.Base != nil { - return t.Base - } - return http.DefaultTransport -} diff --git a/vendor/golang.org/x/sync/LICENSE b/vendor/golang.org/x/sync/LICENSE deleted file mode 100644 index 2a7cf70d..00000000 --- a/vendor/golang.org/x/sync/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/sync/PATENTS b/vendor/golang.org/x/sync/PATENTS deleted file mode 100644 index 73309904..00000000 --- a/vendor/golang.org/x/sync/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go deleted file mode 100644 index 1d8cffae..00000000 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package errgroup provides synchronization, error propagation, and Context -// cancelation for groups of goroutines working on subtasks of a common task. -// -// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks -// returning errors. -package errgroup - -import ( - "context" - "fmt" - "sync" -) - -type token struct{} - -// A Group is a collection of goroutines working on subtasks that are part of -// the same overall task. A Group should not be reused for different tasks. -// -// A zero Group is valid, has no limit on the number of active goroutines, -// and does not cancel on error. -type Group struct { - cancel func(error) - - wg sync.WaitGroup - - sem chan token - - errOnce sync.Once - err error -} - -func (g *Group) done() { - if g.sem != nil { - <-g.sem - } - g.wg.Done() -} - -// WithContext returns a new Group and an associated Context derived from ctx. -// -// The derived Context is canceled the first time a function passed to Go -// returns a non-nil error or the first time Wait returns, whichever occurs -// first. -func WithContext(ctx context.Context) (*Group, context.Context) { - ctx, cancel := context.WithCancelCause(ctx) - return &Group{cancel: cancel}, ctx -} - -// Wait blocks until all function calls from the Go method have returned, then -// returns the first non-nil error (if any) from them. -func (g *Group) Wait() error { - g.wg.Wait() - if g.cancel != nil { - g.cancel(g.err) - } - return g.err -} - -// Go calls the given function in a new goroutine. -// -// The first call to Go must happen before a Wait. -// It blocks until the new goroutine can be added without the number of -// goroutines in the group exceeding the configured limit. -// -// The first goroutine in the group that returns a non-nil error will -// cancel the associated Context, if any. The error will be returned -// by Wait. -func (g *Group) Go(f func() error) { - if g.sem != nil { - g.sem <- token{} - } - - g.wg.Add(1) - go func() { - defer g.done() - - // It is tempting to propagate panics from f() - // up to the goroutine that calls Wait, but - // it creates more problems than it solves: - // - it delays panics arbitrarily, - // making bugs harder to detect; - // - it turns f's panic stack into a mere value, - // hiding it from crash-monitoring tools; - // - it risks deadlocks that hide the panic entirely, - // if f's panic leaves the program in a state - // that prevents the Wait call from being reached. - // See #53757, #74275, #74304, #74306. - - if err := f(); err != nil { - g.errOnce.Do(func() { - g.err = err - if g.cancel != nil { - g.cancel(g.err) - } - }) - } - }() -} - -// TryGo calls the given function in a new goroutine only if the number of -// active goroutines in the group is currently below the configured limit. -// -// The return value reports whether the goroutine was started. -func (g *Group) TryGo(f func() error) bool { - if g.sem != nil { - select { - case g.sem <- token{}: - // Note: this allows barging iff channels in general allow barging. - default: - return false - } - } - - g.wg.Add(1) - go func() { - defer g.done() - - if err := f(); err != nil { - g.errOnce.Do(func() { - g.err = err - if g.cancel != nil { - g.cancel(g.err) - } - }) - } - }() - return true -} - -// SetLimit limits the number of active goroutines in this group to at most n. -// A negative value indicates no limit. -// A limit of zero will prevent any new goroutines from being added. -// -// Any subsequent call to the Go method will block until it can add an active -// goroutine without exceeding the configured limit. -// -// The limit must not be modified while any goroutines in the group are active. -func (g *Group) SetLimit(n int) { - if n < 0 { - g.sem = nil - return - } - if len(g.sem) != 0 { - panic(fmt.Errorf("errgroup: modify limit while %v goroutines in the group are still active", len(g.sem))) - } - g.sem = make(chan token, n) -} diff --git a/vendor/golang.org/x/sync/singleflight/singleflight.go b/vendor/golang.org/x/sync/singleflight/singleflight.go deleted file mode 100644 index 40518309..00000000 --- a/vendor/golang.org/x/sync/singleflight/singleflight.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package singleflight provides a duplicate function call suppression -// mechanism. -package singleflight // import "golang.org/x/sync/singleflight" - -import ( - "bytes" - "errors" - "fmt" - "runtime" - "runtime/debug" - "sync" -) - -// errGoexit indicates the runtime.Goexit was called in -// the user given function. -var errGoexit = errors.New("runtime.Goexit was called") - -// A panicError is an arbitrary value recovered from a panic -// with the stack trace during the execution of given function. -type panicError struct { - value interface{} - stack []byte -} - -// Error implements error interface. -func (p *panicError) Error() string { - return fmt.Sprintf("%v\n\n%s", p.value, p.stack) -} - -func (p *panicError) Unwrap() error { - err, ok := p.value.(error) - if !ok { - return nil - } - - return err -} - -func newPanicError(v interface{}) error { - stack := debug.Stack() - - // The first line of the stack trace is of the form "goroutine N [status]:" - // but by the time the panic reaches Do the goroutine may no longer exist - // and its status will have changed. Trim out the misleading line. - if line := bytes.IndexByte(stack[:], '\n'); line >= 0 { - stack = stack[line+1:] - } - return &panicError{value: v, stack: stack} -} - -// call is an in-flight or completed singleflight.Do call -type call struct { - wg sync.WaitGroup - - // These fields are written once before the WaitGroup is done - // and are only read after the WaitGroup is done. - val interface{} - err error - - // These fields are read and written with the singleflight - // mutex held before the WaitGroup is done, and are read but - // not written after the WaitGroup is done. - dups int - chans []chan<- Result -} - -// Group represents a class of work and forms a namespace in -// which units of work can be executed with duplicate suppression. -type Group struct { - mu sync.Mutex // protects m - m map[string]*call // lazily initialized -} - -// Result holds the results of Do, so they can be passed -// on a channel. -type Result struct { - Val interface{} - Err error - Shared bool -} - -// Do executes and returns the results of the given function, making -// sure that only one execution is in-flight for a given key at a -// time. If a duplicate comes in, the duplicate caller waits for the -// original to complete and receives the same results. -// The return value shared indicates whether v was given to multiple callers. -func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) { - g.mu.Lock() - if g.m == nil { - g.m = make(map[string]*call) - } - if c, ok := g.m[key]; ok { - c.dups++ - g.mu.Unlock() - c.wg.Wait() - - if e, ok := c.err.(*panicError); ok { - panic(e) - } else if c.err == errGoexit { - runtime.Goexit() - } - return c.val, c.err, true - } - c := new(call) - c.wg.Add(1) - g.m[key] = c - g.mu.Unlock() - - g.doCall(c, key, fn) - return c.val, c.err, c.dups > 0 -} - -// DoChan is like Do but returns a channel that will receive the -// results when they are ready. -// -// The returned channel will not be closed. -func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result { - ch := make(chan Result, 1) - g.mu.Lock() - if g.m == nil { - g.m = make(map[string]*call) - } - if c, ok := g.m[key]; ok { - c.dups++ - c.chans = append(c.chans, ch) - g.mu.Unlock() - return ch - } - c := &call{chans: []chan<- Result{ch}} - c.wg.Add(1) - g.m[key] = c - g.mu.Unlock() - - go g.doCall(c, key, fn) - - return ch -} - -// doCall handles the single call for a key. -func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { - normalReturn := false - recovered := false - - // use double-defer to distinguish panic from runtime.Goexit, - // more details see https://golang.org/cl/134395 - defer func() { - // the given function invoked runtime.Goexit - if !normalReturn && !recovered { - c.err = errGoexit - } - - g.mu.Lock() - defer g.mu.Unlock() - c.wg.Done() - if g.m[key] == c { - delete(g.m, key) - } - - if e, ok := c.err.(*panicError); ok { - // In order to prevent the waiting channels from being blocked forever, - // needs to ensure that this panic cannot be recovered. - if len(c.chans) > 0 { - go panic(e) - select {} // Keep this goroutine around so that it will appear in the crash dump. - } else { - panic(e) - } - } else if c.err == errGoexit { - // Already in the process of goexit, no need to call again - } else { - // Normal return - for _, ch := range c.chans { - ch <- Result{c.val, c.err, c.dups > 0} - } - } - }() - - func() { - defer func() { - if !normalReturn { - // Ideally, we would wait to take a stack trace until we've determined - // whether this is a panic or a runtime.Goexit. - // - // Unfortunately, the only way we can distinguish the two is to see - // whether the recover stopped the goroutine from terminating, and by - // the time we know that, the part of the stack trace relevant to the - // panic has been discarded. - if r := recover(); r != nil { - c.err = newPanicError(r) - } - } - }() - - c.val, c.err = fn() - normalReturn = true - }() - - if !normalReturn { - recovered = true - } -} - -// Forget tells the singleflight to forget about a key. Future calls -// to Do for this key will call the function rather than waiting for -// an earlier call to complete. -func (g *Group) Forget(key string) { - g.mu.Lock() - delete(g.m, key) - g.mu.Unlock() -} diff --git a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s b/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s deleted file mode 100644 index 269e173c..00000000 --- a/vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s +++ /dev/null @@ -1,17 +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 gc - -#include "textflag.h" - -// -// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go -// - -TEXT ·syscall6(SB),NOSPLIT,$0-88 - JMP syscall·syscall6(SB) - -TEXT ·rawSyscall6(SB),NOSPLIT,$0-88 - JMP syscall·rawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s b/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s deleted file mode 100644 index ec2acfe5..00000000 --- a/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s +++ /dev/null @@ -1,17 +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 darwin && amd64 && gc - -#include "textflag.h" - -TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_sysctl(SB) -GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 -DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) - -TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_sysctlbyname(SB) -GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8 -DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/cpu/byteorder.go b/vendor/golang.org/x/sys/cpu/byteorder.go deleted file mode 100644 index 271055be..00000000 --- a/vendor/golang.org/x/sys/cpu/byteorder.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "runtime" -) - -// byteOrder is a subset of encoding/binary.ByteOrder. -type byteOrder interface { - Uint32([]byte) uint32 - Uint64([]byte) uint64 -} - -type littleEndian struct{} -type bigEndian struct{} - -func (littleEndian) Uint32(b []byte) uint32 { - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 -} - -func (littleEndian) Uint64(b []byte) uint64 { - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | - uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 -} - -func (bigEndian) Uint32(b []byte) uint32 { - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 -} - -func (bigEndian) Uint64(b []byte) uint64 { - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | - uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 -} - -// hostByteOrder returns littleEndian on little-endian machines and -// bigEndian on big-endian machines. -func hostByteOrder() byteOrder { - switch runtime.GOARCH { - case "386", "amd64", "amd64p32", - "alpha", - "arm", "arm64", - "loong64", - "mipsle", "mips64le", "mips64p32le", - "nios2", - "ppc64le", - "riscv", "riscv64", - "sh": - return littleEndian{} - case "armbe", "arm64be", - "m68k", - "mips", "mips64", "mips64p32", - "ppc", "ppc64", - "s390", "s390x", - "shbe", - "sparc", "sparc64": - return bigEndian{} - } - panic("unknown architecture") -} diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go deleted file mode 100644 index 63541994..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu.go +++ /dev/null @@ -1,338 +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. - -// Package cpu implements processor feature detection for -// various CPU architectures. -package cpu - -import ( - "os" - "strings" -) - -// Initialized reports whether the CPU features were initialized. -// -// For some GOOS/GOARCH combinations initialization of the CPU features depends -// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm -// Initialized will report false if reading the file fails. -var Initialized bool - -// CacheLinePad is used to pad structs to avoid false sharing. -type CacheLinePad struct{ _ [cacheLineSize]byte } - -// X86 contains the supported CPU features of the -// current X86/AMD64 platform. If the current platform -// is not X86/AMD64 then all feature flags are false. -// -// X86 is padded to avoid false sharing. Further the HasAVX -// and HasAVX2 are only set if the OS supports XMM and YMM -// registers in addition to the CPUID feature bit being set. -var X86 struct { - _ CacheLinePad - HasAES bool // AES hardware implementation (AES NI) - HasADX bool // Multi-precision add-carry instruction extensions - HasAVX bool // Advanced vector extension - HasAVX2 bool // Advanced vector extension 2 - HasAVX512 bool // Advanced vector extension 512 - HasAVX512F bool // Advanced vector extension 512 Foundation Instructions - HasAVX512CD bool // Advanced vector extension 512 Conflict Detection Instructions - HasAVX512ER bool // Advanced vector extension 512 Exponential and Reciprocal Instructions - HasAVX512PF bool // Advanced vector extension 512 Prefetch Instructions - HasAVX512VL bool // Advanced vector extension 512 Vector Length Extensions - HasAVX512BW bool // Advanced vector extension 512 Byte and Word Instructions - HasAVX512DQ bool // Advanced vector extension 512 Doubleword and Quadword Instructions - HasAVX512IFMA bool // Advanced vector extension 512 Integer Fused Multiply Add - HasAVX512VBMI bool // Advanced vector extension 512 Vector Byte Manipulation Instructions - HasAVX5124VNNIW bool // Advanced vector extension 512 Vector Neural Network Instructions Word variable precision - HasAVX5124FMAPS bool // Advanced vector extension 512 Fused Multiply Accumulation Packed Single precision - HasAVX512VPOPCNTDQ bool // Advanced vector extension 512 Double and quad word population count instructions - HasAVX512VPCLMULQDQ bool // Advanced vector extension 512 Vector carry-less multiply operations - HasAVX512VNNI bool // Advanced vector extension 512 Vector Neural Network Instructions - HasAVX512GFNI bool // Advanced vector extension 512 Galois field New Instructions - HasAVX512VAES bool // Advanced vector extension 512 Vector AES instructions - HasAVX512VBMI2 bool // Advanced vector extension 512 Vector Byte Manipulation Instructions 2 - HasAVX512BITALG bool // Advanced vector extension 512 Bit Algorithms - HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions - HasAMXTile bool // Advanced Matrix Extension Tile instructions - HasAMXInt8 bool // Advanced Matrix Extension Int8 instructions - HasAMXBF16 bool // Advanced Matrix Extension BFloat16 instructions - HasBMI1 bool // Bit manipulation instruction set 1 - HasBMI2 bool // Bit manipulation instruction set 2 - HasCX16 bool // Compare and exchange 16 Bytes - HasERMS bool // Enhanced REP for MOVSB and STOSB - HasFMA bool // Fused-multiply-add instructions - HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. - HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM - HasPOPCNT bool // Hamming weight instruction POPCNT. - HasRDRAND bool // RDRAND instruction (on-chip random number generator) - HasRDSEED bool // RDSEED instruction (on-chip random number generator) - HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) - HasSSE3 bool // Streaming SIMD extension 3 - HasSSSE3 bool // Supplemental streaming SIMD extension 3 - HasSSE41 bool // Streaming SIMD extension 4 and 4.1 - HasSSE42 bool // Streaming SIMD extension 4 and 4.2 - HasAVXIFMA bool // Advanced vector extension Integer Fused Multiply Add - HasAVXVNNI bool // Advanced vector extension Vector Neural Network Instructions - HasAVXVNNIInt8 bool // Advanced vector extension Vector Neural Network Int8 instructions - _ CacheLinePad -} - -// ARM64 contains the supported CPU features of the -// current ARMv8(aarch64) platform. If the current platform -// is not arm64 then all feature flags are false. -var ARM64 struct { - _ CacheLinePad - HasFP bool // Floating-point instruction set (always available) - HasASIMD bool // Advanced SIMD (always available) - HasEVTSTRM bool // Event stream support - HasAES bool // AES hardware implementation - HasPMULL bool // Polynomial multiplication instruction set - HasSHA1 bool // SHA1 hardware implementation - HasSHA2 bool // SHA2 hardware implementation - HasCRC32 bool // CRC32 hardware implementation - HasATOMICS bool // Atomic memory operation instruction set - HasFPHP bool // Half precision floating-point instruction set - HasASIMDHP bool // Advanced SIMD half precision instruction set - HasCPUID bool // CPUID identification scheme registers - HasASIMDRDM bool // Rounding double multiply add/subtract instruction set - HasJSCVT bool // Javascript conversion from floating-point to integer - HasFCMA bool // Floating-point multiplication and addition of complex numbers - HasLRCPC bool // Release Consistent processor consistent support - HasDCPOP bool // Persistent memory support - HasSHA3 bool // SHA3 hardware implementation - HasSM3 bool // SM3 hardware implementation - HasSM4 bool // SM4 hardware implementation - HasASIMDDP bool // Advanced SIMD double precision instruction set - HasSHA512 bool // SHA512 hardware implementation - HasSVE bool // Scalable Vector Extensions - HasSVE2 bool // Scalable Vector Extensions 2 - HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 - HasDIT bool // Data Independent Timing support - HasI8MM bool // Advanced SIMD Int8 matrix multiplication instructions - _ CacheLinePad -} - -// ARM contains the supported CPU features of the current ARM (32-bit) platform. -// All feature flags are false if: -// 1. the current platform is not arm, or -// 2. the current operating system is not Linux. -var ARM struct { - _ CacheLinePad - HasSWP bool // SWP instruction support - HasHALF bool // Half-word load and store support - HasTHUMB bool // ARM Thumb instruction set - Has26BIT bool // Address space limited to 26-bits - HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support - HasFPA bool // Floating point arithmetic support - HasVFP bool // Vector floating point support - HasEDSP bool // DSP Extensions support - HasJAVA bool // Java instruction set - HasIWMMXT bool // Intel Wireless MMX technology support - HasCRUNCH bool // MaverickCrunch context switching and handling - HasTHUMBEE bool // Thumb EE instruction set - HasNEON bool // NEON instruction set - HasVFPv3 bool // Vector floating point version 3 support - HasVFPv3D16 bool // Vector floating point version 3 D8-D15 - HasTLS bool // Thread local storage support - HasVFPv4 bool // Vector floating point version 4 support - HasIDIVA bool // Integer divide instruction support in ARM mode - HasIDIVT bool // Integer divide instruction support in Thumb mode - HasVFPD32 bool // Vector floating point version 3 D15-D31 - HasLPAE bool // Large Physical Address Extensions - HasEVTSTRM bool // Event stream support - HasAES bool // AES hardware implementation - HasPMULL bool // Polynomial multiplication instruction set - HasSHA1 bool // SHA1 hardware implementation - HasSHA2 bool // SHA2 hardware implementation - HasCRC32 bool // CRC32 hardware implementation - _ CacheLinePad -} - -// The booleans in Loong64 contain the correspondingly named cpu feature bit. -// The struct is padded to avoid false sharing. -var Loong64 struct { - _ CacheLinePad - HasLSX bool // support 128-bit vector extension - HasLASX bool // support 256-bit vector extension - HasCRC32 bool // support CRC instruction - HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction - HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} instruction - _ CacheLinePad -} - -// MIPS64X contains the supported CPU features of the current mips64/mips64le -// platforms. If the current platform is not mips64/mips64le or the current -// operating system is not Linux then all feature flags are false. -var MIPS64X struct { - _ CacheLinePad - HasMSA bool // MIPS SIMD architecture - _ CacheLinePad -} - -// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. -// If the current platform is not ppc64/ppc64le then all feature flags are false. -// -// For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, -// since there are no optional categories. There are some exceptions that also -// require kernel support to work (DARN, SCV), so there are feature bits for -// those as well. The struct is padded to avoid false sharing. -var PPC64 struct { - _ CacheLinePad - HasDARN bool // Hardware random number generator (requires kernel enablement) - HasSCV bool // Syscall vectored (requires kernel enablement) - IsPOWER8 bool // ISA v2.07 (POWER8) - IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8 - _ CacheLinePad -} - -// S390X contains the supported CPU features of the current IBM Z -// (s390x) platform. If the current platform is not IBM Z then all -// feature flags are false. -// -// S390X is padded to avoid false sharing. Further HasVX is only set -// if the OS supports vector registers in addition to the STFLE -// feature bit being set. -var S390X struct { - _ CacheLinePad - HasZARCH bool // z/Architecture mode is active [mandatory] - HasSTFLE bool // store facility list extended - HasLDISP bool // long (20-bit) displacements - HasEIMM bool // 32-bit immediates - HasDFP bool // decimal floating point - HasETF3EH bool // ETF-3 enhanced - HasMSA bool // message security assist (CPACF) - HasAES bool // KM-AES{128,192,256} functions - HasAESCBC bool // KMC-AES{128,192,256} functions - HasAESCTR bool // KMCTR-AES{128,192,256} functions - HasAESGCM bool // KMA-GCM-AES{128,192,256} functions - HasGHASH bool // KIMD-GHASH function - HasSHA1 bool // K{I,L}MD-SHA-1 functions - HasSHA256 bool // K{I,L}MD-SHA-256 functions - HasSHA512 bool // K{I,L}MD-SHA-512 functions - HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions - HasVX bool // vector facility - HasVXE bool // vector-enhancements facility 1 - _ CacheLinePad -} - -// RISCV64 contains the supported CPU features and performance characteristics for riscv64 -// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate -// the presence of RISC-V extensions. -// -// It is safe to assume that all the RV64G extensions are supported and so they are omitted from -// this structure. As riscv64 Go programs require at least RV64G, the code that populates -// this structure cannot run successfully if some of the RV64G extensions are missing. -// The struct is padded to avoid false sharing. -var RISCV64 struct { - _ CacheLinePad - HasFastMisaligned bool // Fast misaligned accesses - HasC bool // Compressed instruction-set extension - HasV bool // Vector extension compatible with RVV 1.0 - HasZba bool // Address generation instructions extension - HasZbb bool // Basic bit-manipulation extension - HasZbs bool // Single-bit instructions extension - HasZvbb bool // Vector Basic Bit-manipulation - HasZvbc bool // Vector Carryless Multiplication - HasZvkb bool // Vector Cryptography Bit-manipulation - HasZvkt bool // Vector Data-Independent Execution Latency - HasZvkg bool // Vector GCM/GMAC - HasZvkn bool // NIST Algorithm Suite (AES/SHA256/SHA512) - HasZvknc bool // NIST Algorithm Suite with carryless multiply - HasZvkng bool // NIST Algorithm Suite with GCM - HasZvks bool // ShangMi Algorithm Suite - HasZvksc bool // ShangMi Algorithm Suite with carryless multiplication - HasZvksg bool // ShangMi Algorithm Suite with GCM - _ CacheLinePad -} - -func init() { - archInit() - initOptions() - processOptions() -} - -// options contains the cpu debug options that can be used in GODEBUG. -// Options are arch dependent and are added by the arch specific initOptions functions. -// Features that are mandatory for the specific GOARCH should have the Required field set -// (e.g. SSE2 on amd64). -var options []option - -// Option names should be lower case. e.g. avx instead of AVX. -type option struct { - Name string - Feature *bool - Specified bool // whether feature value was specified in GODEBUG - Enable bool // whether feature should be enabled - Required bool // whether feature is mandatory and can not be disabled -} - -func processOptions() { - env := os.Getenv("GODEBUG") -field: - for env != "" { - field := "" - i := strings.IndexByte(env, ',') - if i < 0 { - field, env = env, "" - } else { - field, env = env[:i], env[i+1:] - } - if len(field) < 4 || field[:4] != "cpu." { - continue - } - i = strings.IndexByte(field, '=') - if i < 0 { - print("GODEBUG sys/cpu: no value specified for \"", field, "\"\n") - continue - } - key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on" - - var enable bool - switch value { - case "on": - enable = true - case "off": - enable = false - default: - print("GODEBUG sys/cpu: value \"", value, "\" not supported for cpu option \"", key, "\"\n") - continue field - } - - if key == "all" { - for i := range options { - options[i].Specified = true - options[i].Enable = enable || options[i].Required - } - continue field - } - - for i := range options { - if options[i].Name == key { - options[i].Specified = true - options[i].Enable = enable - continue field - } - } - - print("GODEBUG sys/cpu: unknown cpu feature \"", key, "\"\n") - } - - for _, o := range options { - if !o.Specified { - continue - } - - if o.Enable && !*o.Feature { - print("GODEBUG sys/cpu: can not enable \"", o.Name, "\", missing CPU support\n") - continue - } - - if !o.Enable && o.Required { - print("GODEBUG sys/cpu: can not disable \"", o.Name, "\", required CPU feature\n") - continue - } - - *o.Feature = o.Enable - } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_aix.go b/vendor/golang.org/x/sys/cpu/cpu_aix.go deleted file mode 100644 index 9bf0c32e..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_aix.go +++ /dev/null @@ -1,33 +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 aix - -package cpu - -const ( - // getsystemcfg constants - _SC_IMPL = 2 - _IMPL_POWER8 = 0x10000 - _IMPL_POWER9 = 0x20000 -) - -func archInit() { - impl := getsystemcfg(_SC_IMPL) - if impl&_IMPL_POWER8 != 0 { - PPC64.IsPOWER8 = true - } - if impl&_IMPL_POWER9 != 0 { - PPC64.IsPOWER8 = true - PPC64.IsPOWER9 = true - } - - Initialized = true -} - -func getsystemcfg(label int) (n uint64) { - r0, _ := callgetsystemcfg(label) - n = uint64(r0) - return -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm.go b/vendor/golang.org/x/sys/cpu/cpu_arm.go deleted file mode 100644 index 301b752e..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_arm.go +++ /dev/null @@ -1,73 +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. - -package cpu - -const cacheLineSize = 32 - -// HWCAP/HWCAP2 bits. -// These are specific to Linux. -const ( - hwcap_SWP = 1 << 0 - hwcap_HALF = 1 << 1 - hwcap_THUMB = 1 << 2 - hwcap_26BIT = 1 << 3 - hwcap_FAST_MULT = 1 << 4 - hwcap_FPA = 1 << 5 - hwcap_VFP = 1 << 6 - hwcap_EDSP = 1 << 7 - hwcap_JAVA = 1 << 8 - hwcap_IWMMXT = 1 << 9 - hwcap_CRUNCH = 1 << 10 - hwcap_THUMBEE = 1 << 11 - hwcap_NEON = 1 << 12 - hwcap_VFPv3 = 1 << 13 - hwcap_VFPv3D16 = 1 << 14 - hwcap_TLS = 1 << 15 - hwcap_VFPv4 = 1 << 16 - hwcap_IDIVA = 1 << 17 - hwcap_IDIVT = 1 << 18 - hwcap_VFPD32 = 1 << 19 - hwcap_LPAE = 1 << 20 - hwcap_EVTSTRM = 1 << 21 - - hwcap2_AES = 1 << 0 - hwcap2_PMULL = 1 << 1 - hwcap2_SHA1 = 1 << 2 - hwcap2_SHA2 = 1 << 3 - hwcap2_CRC32 = 1 << 4 -) - -func initOptions() { - options = []option{ - {Name: "pmull", Feature: &ARM.HasPMULL}, - {Name: "sha1", Feature: &ARM.HasSHA1}, - {Name: "sha2", Feature: &ARM.HasSHA2}, - {Name: "swp", Feature: &ARM.HasSWP}, - {Name: "thumb", Feature: &ARM.HasTHUMB}, - {Name: "thumbee", Feature: &ARM.HasTHUMBEE}, - {Name: "tls", Feature: &ARM.HasTLS}, - {Name: "vfp", Feature: &ARM.HasVFP}, - {Name: "vfpd32", Feature: &ARM.HasVFPD32}, - {Name: "vfpv3", Feature: &ARM.HasVFPv3}, - {Name: "vfpv3d16", Feature: &ARM.HasVFPv3D16}, - {Name: "vfpv4", Feature: &ARM.HasVFPv4}, - {Name: "half", Feature: &ARM.HasHALF}, - {Name: "26bit", Feature: &ARM.Has26BIT}, - {Name: "fastmul", Feature: &ARM.HasFASTMUL}, - {Name: "fpa", Feature: &ARM.HasFPA}, - {Name: "edsp", Feature: &ARM.HasEDSP}, - {Name: "java", Feature: &ARM.HasJAVA}, - {Name: "iwmmxt", Feature: &ARM.HasIWMMXT}, - {Name: "crunch", Feature: &ARM.HasCRUNCH}, - {Name: "neon", Feature: &ARM.HasNEON}, - {Name: "idivt", Feature: &ARM.HasIDIVT}, - {Name: "idiva", Feature: &ARM.HasIDIVA}, - {Name: "lpae", Feature: &ARM.HasLPAE}, - {Name: "evtstrm", Feature: &ARM.HasEVTSTRM}, - {Name: "aes", Feature: &ARM.HasAES}, - {Name: "crc32", Feature: &ARM.HasCRC32}, - } - -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go deleted file mode 100644 index af2aa99f..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_arm64.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import "runtime" - -// cacheLineSize is used to prevent false sharing of cache lines. -// We choose 128 because Apple Silicon, a.k.a. M1, has 128-byte cache line size. -// It doesn't cost much and is much more future-proof. -const cacheLineSize = 128 - -func initOptions() { - options = []option{ - {Name: "fp", Feature: &ARM64.HasFP}, - {Name: "asimd", Feature: &ARM64.HasASIMD}, - {Name: "evstrm", Feature: &ARM64.HasEVTSTRM}, - {Name: "aes", Feature: &ARM64.HasAES}, - {Name: "fphp", Feature: &ARM64.HasFPHP}, - {Name: "jscvt", Feature: &ARM64.HasJSCVT}, - {Name: "lrcpc", Feature: &ARM64.HasLRCPC}, - {Name: "pmull", Feature: &ARM64.HasPMULL}, - {Name: "sha1", Feature: &ARM64.HasSHA1}, - {Name: "sha2", Feature: &ARM64.HasSHA2}, - {Name: "sha3", Feature: &ARM64.HasSHA3}, - {Name: "sha512", Feature: &ARM64.HasSHA512}, - {Name: "sm3", Feature: &ARM64.HasSM3}, - {Name: "sm4", Feature: &ARM64.HasSM4}, - {Name: "sve", Feature: &ARM64.HasSVE}, - {Name: "sve2", Feature: &ARM64.HasSVE2}, - {Name: "crc32", Feature: &ARM64.HasCRC32}, - {Name: "atomics", Feature: &ARM64.HasATOMICS}, - {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, - {Name: "cpuid", Feature: &ARM64.HasCPUID}, - {Name: "asimrdm", Feature: &ARM64.HasASIMDRDM}, - {Name: "fcma", Feature: &ARM64.HasFCMA}, - {Name: "dcpop", Feature: &ARM64.HasDCPOP}, - {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, - {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, - {Name: "dit", Feature: &ARM64.HasDIT}, - {Name: "i8mm", Feature: &ARM64.HasI8MM}, - } -} - -func archInit() { - switch runtime.GOOS { - case "freebsd": - readARM64Registers() - case "linux", "netbsd", "openbsd": - doinit() - default: - // Many platforms don't seem to allow reading these registers. - setMinimalFeatures() - } -} - -// setMinimalFeatures fakes the minimal ARM64 features expected by -// TestARM64minimalFeatures. -func setMinimalFeatures() { - ARM64.HasASIMD = true - ARM64.HasFP = true -} - -func readARM64Registers() { - Initialized = true - - parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0()) -} - -func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { - // ID_AA64ISAR0_EL1 - switch extractBits(isar0, 4, 7) { - case 1: - ARM64.HasAES = true - case 2: - ARM64.HasAES = true - ARM64.HasPMULL = true - } - - switch extractBits(isar0, 8, 11) { - case 1: - ARM64.HasSHA1 = true - } - - switch extractBits(isar0, 12, 15) { - case 1: - ARM64.HasSHA2 = true - case 2: - ARM64.HasSHA2 = true - ARM64.HasSHA512 = true - } - - switch extractBits(isar0, 16, 19) { - case 1: - ARM64.HasCRC32 = true - } - - switch extractBits(isar0, 20, 23) { - case 2: - ARM64.HasATOMICS = true - } - - switch extractBits(isar0, 28, 31) { - case 1: - ARM64.HasASIMDRDM = true - } - - switch extractBits(isar0, 32, 35) { - case 1: - ARM64.HasSHA3 = true - } - - switch extractBits(isar0, 36, 39) { - case 1: - ARM64.HasSM3 = true - } - - switch extractBits(isar0, 40, 43) { - case 1: - ARM64.HasSM4 = true - } - - switch extractBits(isar0, 44, 47) { - case 1: - ARM64.HasASIMDDP = true - } - - // ID_AA64ISAR1_EL1 - switch extractBits(isar1, 0, 3) { - case 1: - ARM64.HasDCPOP = true - } - - switch extractBits(isar1, 12, 15) { - case 1: - ARM64.HasJSCVT = true - } - - switch extractBits(isar1, 16, 19) { - case 1: - ARM64.HasFCMA = true - } - - switch extractBits(isar1, 20, 23) { - case 1: - ARM64.HasLRCPC = true - } - - switch extractBits(isar1, 52, 55) { - case 1: - ARM64.HasI8MM = true - } - - // ID_AA64PFR0_EL1 - switch extractBits(pfr0, 16, 19) { - case 0: - ARM64.HasFP = true - case 1: - ARM64.HasFP = true - ARM64.HasFPHP = true - } - - switch extractBits(pfr0, 20, 23) { - case 0: - ARM64.HasASIMD = true - case 1: - ARM64.HasASIMD = true - ARM64.HasASIMDHP = true - } - - switch extractBits(pfr0, 32, 35) { - case 1: - ARM64.HasSVE = true - - parseARM64SVERegister(getzfr0()) - } - - switch extractBits(pfr0, 48, 51) { - case 1: - ARM64.HasDIT = true - } -} - -func parseARM64SVERegister(zfr0 uint64) { - switch extractBits(zfr0, 0, 3) { - case 1: - ARM64.HasSVE2 = true - } -} - -func extractBits(data uint64, start, end uint) uint { - return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_arm64.s deleted file mode 100644 index 22cc9984..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_arm64.s +++ /dev/null @@ -1,39 +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 gc - -#include "textflag.h" - -// func getisar0() uint64 -TEXT ·getisar0(SB),NOSPLIT,$0-8 - // get Instruction Set Attributes 0 into x0 - // mrs x0, ID_AA64ISAR0_EL1 = d5380600 - WORD $0xd5380600 - MOVD R0, ret+0(FP) - RET - -// func getisar1() uint64 -TEXT ·getisar1(SB),NOSPLIT,$0-8 - // get Instruction Set Attributes 1 into x0 - // mrs x0, ID_AA64ISAR1_EL1 = d5380620 - WORD $0xd5380620 - MOVD R0, ret+0(FP) - RET - -// func getpfr0() uint64 -TEXT ·getpfr0(SB),NOSPLIT,$0-8 - // get Processor Feature Register 0 into x0 - // mrs x0, ID_AA64PFR0_EL1 = d5380400 - WORD $0xd5380400 - MOVD R0, ret+0(FP) - RET - -// func getzfr0() uint64 -TEXT ·getzfr0(SB),NOSPLIT,$0-8 - // get SVE Feature Register 0 into x0 - // mrs x0, ID_AA64ZFR0_EL1 = d5380480 - WORD $0xd5380480 - MOVD R0, ret+0(FP) - RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go b/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go deleted file mode 100644 index b838cb9e..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go +++ /dev/null @@ -1,61 +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 darwin && amd64 && gc - -package cpu - -// darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl -// call (see issue 43089). It also restricts AVX512 support for Darwin to -// kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233). -// -// Background: -// Darwin implements a special mechanism to economize on thread state when -// AVX512 specific registers are not in use. This scheme minimizes state when -// preempting threads that haven't yet used any AVX512 instructions, but adds -// special requirements to check for AVX512 hardware support at runtime (e.g. -// via sysctl call or commpage inspection). See issue 43089 and link below for -// full background: -// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240 -// -// Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0 -// (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption -// of the AVX512 mask registers (K0-K7) upon signal return. For this reason -// AVX512 is considered unsafe to use on Darwin for kernel versions prior to -// 21.3.0, where a fix has been confirmed. See issue 49233 for full background. -func darwinSupportsAVX512() bool { - return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0) -} - -// Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies -func darwinKernelVersionCheck(major, minor, patch int) bool { - var release [256]byte - err := darwinOSRelease(&release) - if err != nil { - return false - } - - var mmp [3]int - c := 0 -Loop: - for _, b := range release[:] { - switch { - case b >= '0' && b <= '9': - mmp[c] = 10*mmp[c] + int(b-'0') - case b == '.': - c++ - if c > 2 { - return false - } - case b == 0: - break Loop - default: - return false - } - } - if c != 2 { - return false - } - return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch) -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go deleted file mode 100644 index 6ac6e1ef..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.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 gc - -package cpu - -func getisar0() uint64 -func getisar1() uint64 -func getpfr0() uint64 -func getzfr0() uint64 diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go deleted file mode 100644 index c8ae6ddc..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go +++ /dev/null @@ -1,21 +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 gc - -package cpu - -// haveAsmFunctions reports whether the other functions in this file can -// be safely called. -func haveAsmFunctions() bool { return true } - -// The following feature detection functions are defined in cpu_s390x.s. -// They are likely to be expensive to call so the results should be cached. -func stfle() facilityList -func kmQuery() queryResult -func kmcQuery() queryResult -func kmctrQuery() queryResult -func kmaQuery() queryResult -func kimdQuery() queryResult -func klmdQuery() queryResult diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go deleted file mode 100644 index 32a44514..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ /dev/null @@ -1,15 +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 (386 || amd64 || amd64p32) && gc - -package cpu - -// cpuid is implemented in cpu_gc_x86.s for gc compiler -// and in cpu_gccgo.c for gccgo. -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) - -// xgetbv with ecx = 0 is implemented in cpu_gc_x86.s for gc compiler -// and in cpu_gccgo.c for gccgo. -func xgetbv() (eax, edx uint32) diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s deleted file mode 100644 index ce208ce6..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s +++ /dev/null @@ -1,26 +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 (386 || amd64 || amd64p32) && gc - -#include "textflag.h" - -// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) -TEXT ·cpuid(SB), NOSPLIT, $0-24 - MOVL eaxArg+0(FP), AX - MOVL ecxArg+4(FP), CX - CPUID - MOVL AX, eax+8(FP) - MOVL BX, ebx+12(FP) - MOVL CX, ecx+16(FP) - MOVL DX, edx+20(FP) - RET - -// func xgetbv() (eax, edx uint32) -TEXT ·xgetbv(SB), NOSPLIT, $0-8 - MOVL $0, CX - XGETBV - MOVL AX, eax+0(FP) - MOVL DX, edx+4(FP) - RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go deleted file mode 100644 index 7f194678..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go +++ /dev/null @@ -1,11 +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 gccgo - -package cpu - -func getisar0() uint64 { return 0 } -func getisar1() uint64 { return 0 } -func getpfr0() uint64 { return 0 } diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go deleted file mode 100644 index 9526d2ce..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go +++ /dev/null @@ -1,22 +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 gccgo - -package cpu - -// haveAsmFunctions reports whether the other functions in this file can -// be safely called. -func haveAsmFunctions() bool { return false } - -// TODO(mundaym): the following feature detection functions are currently -// stubs. See https://golang.org/cl/162887 for how to fix this. -// They are likely to be expensive to call so the results should be cached. -func stfle() facilityList { panic("not implemented for gccgo") } -func kmQuery() queryResult { panic("not implemented for gccgo") } -func kmcQuery() queryResult { panic("not implemented for gccgo") } -func kmctrQuery() queryResult { panic("not implemented for gccgo") } -func kmaQuery() queryResult { panic("not implemented for gccgo") } -func kimdQuery() queryResult { panic("not implemented for gccgo") } -func klmdQuery() queryResult { panic("not implemented for gccgo") } diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c deleted file mode 100644 index 3f73a05d..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c +++ /dev/null @@ -1,37 +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 (386 || amd64 || amd64p32) && gccgo - -#include <cpuid.h> -#include <stdint.h> -#include <x86intrin.h> - -// Need to wrap __get_cpuid_count because it's declared as static. -int -gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, - uint32_t *eax, uint32_t *ebx, - uint32_t *ecx, uint32_t *edx) -{ - return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); -} - -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -#pragma GCC push_options -#pragma GCC target("xsave") -#pragma clang attribute push (__attribute__((target("xsave"))), apply_to=function) - -// xgetbv reads the contents of an XCR (Extended Control Register) -// specified in the ECX register into registers EDX:EAX. -// Currently, the only supported value for XCR is 0. -void -gccgoXgetbv(uint32_t *eax, uint32_t *edx) -{ - uint64_t v = _xgetbv(0); - *eax = v & 0xffffffff; - *edx = v >> 32; -} - -#pragma clang attribute pop -#pragma GCC pop_options diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go deleted file mode 100644 index 170d21dd..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go +++ /dev/null @@ -1,25 +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 (386 || amd64 || amd64p32) && gccgo - -package cpu - -//extern gccgoGetCpuidCount -func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) - -func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { - var a, b, c, d uint32 - gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) - return a, b, c, d -} - -//extern gccgoXgetbv -func gccgoXgetbv(eax, edx *uint32) - -func xgetbv() (eax, edx uint32) { - var a, d uint32 - gccgoXgetbv(&a, &d) - return a, d -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux.go b/vendor/golang.org/x/sys/cpu/cpu_linux.go deleted file mode 100644 index 743eb543..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux.go +++ /dev/null @@ -1,15 +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 !386 && !amd64 && !amd64p32 && !arm64 - -package cpu - -func archInit() { - if err := readHWCAP(); err != nil { - return - } - doinit() - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go deleted file mode 100644 index 2057006d..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_arm.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -func doinit() { - ARM.HasSWP = isSet(hwCap, hwcap_SWP) - ARM.HasHALF = isSet(hwCap, hwcap_HALF) - ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB) - ARM.Has26BIT = isSet(hwCap, hwcap_26BIT) - ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT) - ARM.HasFPA = isSet(hwCap, hwcap_FPA) - ARM.HasVFP = isSet(hwCap, hwcap_VFP) - ARM.HasEDSP = isSet(hwCap, hwcap_EDSP) - ARM.HasJAVA = isSet(hwCap, hwcap_JAVA) - ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT) - ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH) - ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE) - ARM.HasNEON = isSet(hwCap, hwcap_NEON) - ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3) - ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16) - ARM.HasTLS = isSet(hwCap, hwcap_TLS) - ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4) - ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA) - ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT) - ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32) - ARM.HasLPAE = isSet(hwCap, hwcap_LPAE) - ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) - ARM.HasAES = isSet(hwCap2, hwcap2_AES) - ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL) - ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1) - ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2) - ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go deleted file mode 100644 index f1caf0f7..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go +++ /dev/null @@ -1,120 +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. - -package cpu - -import ( - "strings" - "syscall" -) - -// HWCAP/HWCAP2 bits. These are exposed by Linux. -const ( - hwcap_FP = 1 << 0 - hwcap_ASIMD = 1 << 1 - hwcap_EVTSTRM = 1 << 2 - hwcap_AES = 1 << 3 - hwcap_PMULL = 1 << 4 - hwcap_SHA1 = 1 << 5 - hwcap_SHA2 = 1 << 6 - hwcap_CRC32 = 1 << 7 - hwcap_ATOMICS = 1 << 8 - hwcap_FPHP = 1 << 9 - hwcap_ASIMDHP = 1 << 10 - hwcap_CPUID = 1 << 11 - hwcap_ASIMDRDM = 1 << 12 - hwcap_JSCVT = 1 << 13 - hwcap_FCMA = 1 << 14 - hwcap_LRCPC = 1 << 15 - hwcap_DCPOP = 1 << 16 - hwcap_SHA3 = 1 << 17 - hwcap_SM3 = 1 << 18 - hwcap_SM4 = 1 << 19 - hwcap_ASIMDDP = 1 << 20 - hwcap_SHA512 = 1 << 21 - hwcap_SVE = 1 << 22 - hwcap_ASIMDFHM = 1 << 23 - hwcap_DIT = 1 << 24 - - hwcap2_SVE2 = 1 << 1 - hwcap2_I8MM = 1 << 13 -) - -// linuxKernelCanEmulateCPUID reports whether we're running -// on Linux 4.11+. Ideally we'd like to ask the question about -// whether the current kernel contains -// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=77c97b4ee21290f5f083173d957843b615abbff2 -// but the version number will have to do. -func linuxKernelCanEmulateCPUID() bool { - var un syscall.Utsname - syscall.Uname(&un) - var sb strings.Builder - for _, b := range un.Release[:] { - if b == 0 { - break - } - sb.WriteByte(byte(b)) - } - major, minor, _, ok := parseRelease(sb.String()) - return ok && (major > 4 || major == 4 && minor >= 11) -} - -func doinit() { - if err := readHWCAP(); err != nil { - // We failed to read /proc/self/auxv. This can happen if the binary has - // been given extra capabilities(7) with /bin/setcap. - // - // When this happens, we have two options. If the Linux kernel is new - // enough (4.11+), we can read the arm64 registers directly which'll - // trap into the kernel and then return back to userspace. - // - // But on older kernels, such as Linux 4.4.180 as used on many Synology - // devices, calling readARM64Registers (specifically getisar0) will - // cause a SIGILL and we'll die. So for older kernels, parse /proc/cpuinfo - // instead. - // - // See golang/go#57336. - if linuxKernelCanEmulateCPUID() { - readARM64Registers() - } else { - readLinuxProcCPUInfo() - } - return - } - - // HWCAP feature bits - ARM64.HasFP = isSet(hwCap, hwcap_FP) - ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD) - ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) - ARM64.HasAES = isSet(hwCap, hwcap_AES) - ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL) - ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1) - ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2) - ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32) - ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS) - ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP) - ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP) - ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID) - ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM) - ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT) - ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA) - ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC) - ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP) - ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3) - ARM64.HasSM3 = isSet(hwCap, hwcap_SM3) - ARM64.HasSM4 = isSet(hwCap, hwcap_SM4) - ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP) - ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) - ARM64.HasSVE = isSet(hwCap, hwcap_SVE) - ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) - ARM64.HasDIT = isSet(hwCap, hwcap_DIT) - - // HWCAP2 feature bits - ARM64.HasSVE2 = isSet(hwCap2, hwcap2_SVE2) - ARM64.HasI8MM = isSet(hwCap2, hwcap2_I8MM) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go deleted file mode 100644 index 4f341143..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -// HWCAP bits. These are exposed by the Linux kernel. -const ( - hwcap_LOONGARCH_LSX = 1 << 4 - hwcap_LOONGARCH_LASX = 1 << 5 -) - -func doinit() { - // TODO: Features that require kernel support like LSX and LASX can - // be detected here once needed in std library or by the compiler. - Loong64.HasLSX = hwcIsSet(hwCap, hwcap_LOONGARCH_LSX) - Loong64.HasLASX = hwcIsSet(hwCap, hwcap_LOONGARCH_LASX) -} - -func hwcIsSet(hwc uint, val uint) bool { - return hwc&val != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go deleted file mode 100644 index 4686c1d5..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && (mips64 || mips64le) - -package cpu - -// HWCAP bits. These are exposed by the Linux kernel 5.4. -const ( - // CPU features - hwcap_MIPS_MSA = 1 << 1 -) - -func doinit() { - // HWCAP feature bits - MIPS64X.HasMSA = isSet(hwCap, hwcap_MIPS_MSA) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go deleted file mode 100644 index a428dec9..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go +++ /dev/null @@ -1,9 +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 linux && !arm && !arm64 && !loong64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 - -package cpu - -func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go deleted file mode 100644 index 197188e6..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go +++ /dev/null @@ -1,30 +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 linux && (ppc64 || ppc64le) - -package cpu - -// HWCAP/HWCAP2 bits. These are exposed by the kernel. -const ( - // ISA Level - _PPC_FEATURE2_ARCH_2_07 = 0x80000000 - _PPC_FEATURE2_ARCH_3_00 = 0x00800000 - - // CPU features - _PPC_FEATURE2_DARN = 0x00200000 - _PPC_FEATURE2_SCV = 0x00100000 -) - -func doinit() { - // HWCAP2 feature bits - PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) - PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) - PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) - PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go deleted file mode 100644 index ad741536..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go +++ /dev/null @@ -1,160 +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 cpu - -import ( - "syscall" - "unsafe" -) - -// RISC-V extension discovery code for Linux. The approach here is to first try the riscv_hwprobe -// syscall falling back to HWCAP to check for the C extension if riscv_hwprobe is not available. -// -// A note on detection of the Vector extension using HWCAP. -// -// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5. -// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe -// syscall is not available then neither is the Vector extension (which needs kernel support). -// The riscv_hwprobe syscall should then be all we need to detect the Vector extension. -// However, some RISC-V board manufacturers ship boards with an older kernel on top of which -// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe -// patches. These kernels advertise support for the Vector extension using HWCAP. Falling -// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not -// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option. -// -// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by -// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board -// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified -// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use -// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector -// extension are binary incompatible. HWCAP can then not be used in isolation to populate the -// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0. -// -// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector -// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype -// register. This check would allow us to safely detect version 1.0 of the Vector extension -// with HWCAP, if riscv_hwprobe were not available. However, the check cannot -// be added until the assembler supports the Vector instructions. -// -// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the -// extensions it advertises support for are explicitly versioned. It's also worth noting that -// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zba. -// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority -// of RISC-V extensions. -// -// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information. - -// golang.org/x/sys/cpu is not allowed to depend on golang.org/x/sys/unix so we must -// reproduce the constants, types and functions needed to make the riscv_hwprobe syscall -// here. - -const ( - // Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. - riscv_HWPROBE_KEY_IMA_EXT_0 = 0x4 - riscv_HWPROBE_IMA_C = 0x2 - riscv_HWPROBE_IMA_V = 0x4 - riscv_HWPROBE_EXT_ZBA = 0x8 - riscv_HWPROBE_EXT_ZBB = 0x10 - riscv_HWPROBE_EXT_ZBS = 0x20 - riscv_HWPROBE_EXT_ZVBB = 0x20000 - riscv_HWPROBE_EXT_ZVBC = 0x40000 - riscv_HWPROBE_EXT_ZVKB = 0x80000 - riscv_HWPROBE_EXT_ZVKG = 0x100000 - riscv_HWPROBE_EXT_ZVKNED = 0x200000 - riscv_HWPROBE_EXT_ZVKNHB = 0x800000 - riscv_HWPROBE_EXT_ZVKSED = 0x1000000 - riscv_HWPROBE_EXT_ZVKSH = 0x2000000 - riscv_HWPROBE_EXT_ZVKT = 0x4000000 - riscv_HWPROBE_KEY_CPUPERF_0 = 0x5 - riscv_HWPROBE_MISALIGNED_FAST = 0x3 - riscv_HWPROBE_MISALIGNED_MASK = 0x7 -) - -const ( - // sys_RISCV_HWPROBE is copied from golang.org/x/sys/unix/zsysnum_linux_riscv64.go. - sys_RISCV_HWPROBE = 258 -) - -// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. -type riscvHWProbePairs struct { - key int64 - value uint64 -} - -const ( - // CPU features - hwcap_RISCV_ISA_C = 1 << ('C' - 'A') -) - -func doinit() { - // A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key - // field should be initialised with one of the key constants defined above, e.g., - // RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value. - // If the kernel does not recognise a key it will set the key field to -1 and the value field to 0. - - pairs := []riscvHWProbePairs{ - {riscv_HWPROBE_KEY_IMA_EXT_0, 0}, - {riscv_HWPROBE_KEY_CPUPERF_0, 0}, - } - - // This call only indicates that extensions are supported if they are implemented on all cores. - if riscvHWProbe(pairs, 0) { - if pairs[0].key != -1 { - v := uint(pairs[0].value) - RISCV64.HasC = isSet(v, riscv_HWPROBE_IMA_C) - RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V) - RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA) - RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) - RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS) - RISCV64.HasZvbb = isSet(v, riscv_HWPROBE_EXT_ZVBB) - RISCV64.HasZvbc = isSet(v, riscv_HWPROBE_EXT_ZVBC) - RISCV64.HasZvkb = isSet(v, riscv_HWPROBE_EXT_ZVKB) - RISCV64.HasZvkg = isSet(v, riscv_HWPROBE_EXT_ZVKG) - RISCV64.HasZvkt = isSet(v, riscv_HWPROBE_EXT_ZVKT) - // Cryptography shorthand extensions - RISCV64.HasZvkn = isSet(v, riscv_HWPROBE_EXT_ZVKNED) && - isSet(v, riscv_HWPROBE_EXT_ZVKNHB) && RISCV64.HasZvkb && RISCV64.HasZvkt - RISCV64.HasZvknc = RISCV64.HasZvkn && RISCV64.HasZvbc - RISCV64.HasZvkng = RISCV64.HasZvkn && RISCV64.HasZvkg - RISCV64.HasZvks = isSet(v, riscv_HWPROBE_EXT_ZVKSED) && - isSet(v, riscv_HWPROBE_EXT_ZVKSH) && RISCV64.HasZvkb && RISCV64.HasZvkt - RISCV64.HasZvksc = RISCV64.HasZvks && RISCV64.HasZvbc - RISCV64.HasZvksg = RISCV64.HasZvks && RISCV64.HasZvkg - } - if pairs[1].key != -1 { - v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK - RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST - } - } - - // Let's double check with HWCAP if the C extension does not appear to be supported. - // This may happen if we're running on a kernel older than 6.4. - - if !RISCV64.HasC { - RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C) - } -} - -func isSet(hwc uint, value uint) bool { - return hwc&value != 0 -} - -// riscvHWProbe is a simplified version of the generated wrapper function found in -// golang.org/x/sys/unix/zsyscall_linux_riscv64.go. We simplify it by removing the -// cpuCount and cpus parameters which we do not need. We always want to pass 0 for -// these parameters here so the kernel only reports the extensions that are present -// on all cores. -func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool { - var _zero uintptr - var p0 unsafe.Pointer - if len(pairs) > 0 { - p0 = unsafe.Pointer(&pairs[0]) - } else { - p0 = unsafe.Pointer(&_zero) - } - - _, _, e1 := syscall.Syscall6(sys_RISCV_HWPROBE, uintptr(p0), uintptr(len(pairs)), uintptr(0), uintptr(0), uintptr(flags), 0) - return e1 == 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go deleted file mode 100644 index 1517ac61..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const ( - // bit mask values from /usr/include/bits/hwcap.h - hwcap_ZARCH = 2 - hwcap_STFLE = 4 - hwcap_MSA = 8 - hwcap_LDISP = 16 - hwcap_EIMM = 32 - hwcap_DFP = 64 - hwcap_ETF3EH = 256 - hwcap_VX = 2048 - hwcap_VXE = 8192 -) - -func initS390Xbase() { - // test HWCAP bit vector - has := func(featureMask uint) bool { - return hwCap&featureMask == featureMask - } - - // mandatory - S390X.HasZARCH = has(hwcap_ZARCH) - - // optional - S390X.HasSTFLE = has(hwcap_STFLE) - S390X.HasLDISP = has(hwcap_LDISP) - S390X.HasEIMM = has(hwcap_EIMM) - S390X.HasETF3EH = has(hwcap_ETF3EH) - S390X.HasDFP = has(hwcap_DFP) - S390X.HasMSA = has(hwcap_MSA) - S390X.HasVX = has(hwcap_VX) - if S390X.HasVX { - S390X.HasVXE = has(hwcap_VXE) - } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_loong64.go b/vendor/golang.org/x/sys/cpu/cpu_loong64.go deleted file mode 100644 index 45ecb29a..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_loong64.go +++ /dev/null @@ -1,50 +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 loong64 - -package cpu - -const cacheLineSize = 64 - -// Bit fields for CPUCFG registers, Related reference documents: -// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg -const ( - // CPUCFG1 bits - cpucfg1_CRC32 = 1 << 25 - - // CPUCFG2 bits - cpucfg2_LAM_BH = 1 << 27 - cpucfg2_LAMCAS = 1 << 28 -) - -func initOptions() { - options = []option{ - {Name: "lsx", Feature: &Loong64.HasLSX}, - {Name: "lasx", Feature: &Loong64.HasLASX}, - {Name: "crc32", Feature: &Loong64.HasCRC32}, - {Name: "lam_bh", Feature: &Loong64.HasLAM_BH}, - {Name: "lamcas", Feature: &Loong64.HasLAMCAS}, - } - - // The CPUCFG data on Loong64 only reflects the hardware capabilities, - // not the kernel support status, so features such as LSX and LASX that - // require kernel support cannot be obtained from the CPUCFG data. - // - // These features only require hardware capability support and do not - // require kernel specific support, so they can be obtained directly - // through CPUCFG - cfg1 := get_cpucfg(1) - cfg2 := get_cpucfg(2) - - Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32) - Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS) - Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH) -} - -func get_cpucfg(reg uint32) uint32 - -func cfgIsSet(cfg uint32, val uint32) bool { - return cfg&val != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_loong64.s b/vendor/golang.org/x/sys/cpu/cpu_loong64.s deleted file mode 100644 index 71cbaf1c..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_loong64.s +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "textflag.h" - -// func get_cpucfg(reg uint32) uint32 -TEXT ·get_cpucfg(SB), NOSPLIT|NOFRAME, $0 - MOVW reg+0(FP), R5 - // CPUCFG R5, R4 = 0x00006ca4 - WORD $0x00006ca4 - MOVW R4, ret+8(FP) - RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_mips64x.go deleted file mode 100644 index fedb00cc..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_mips64x.go +++ /dev/null @@ -1,15 +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 mips64 || mips64le - -package cpu - -const cacheLineSize = 32 - -func initOptions() { - options = []option{ - {Name: "msa", Feature: &MIPS64X.HasMSA}, - } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go b/vendor/golang.org/x/sys/cpu/cpu_mipsx.go deleted file mode 100644 index ffb4ec7e..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_mipsx.go +++ /dev/null @@ -1,11 +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 mips || mipsle - -package cpu - -const cacheLineSize = 32 - -func initOptions() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go deleted file mode 100644 index ebfb3fc8..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "syscall" - "unsafe" -) - -// Minimal copy of functionality from x/sys/unix so the cpu package can call -// sysctl without depending on x/sys/unix. - -const ( - _CTL_QUERY = -2 - - _SYSCTL_VERS_1 = 0x1000000 -) - -var _zero uintptr - -func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, errno := syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(_p0), - uintptr(len(mib)), - uintptr(unsafe.Pointer(old)), - uintptr(unsafe.Pointer(oldlen)), - uintptr(unsafe.Pointer(new)), - uintptr(newlen)) - if errno != 0 { - return errno - } - return nil -} - -type sysctlNode struct { - Flags uint32 - Num int32 - Name [32]int8 - Ver uint32 - __rsvd uint32 - Un [16]byte - _sysctl_size [8]byte - _sysctl_func [8]byte - _sysctl_parent [8]byte - _sysctl_desc [8]byte -} - -func sysctlNodes(mib []int32) ([]sysctlNode, error) { - var olen uintptr - - // Get a list of all sysctl nodes below the given MIB by performing - // a sysctl for the given MIB with CTL_QUERY appended. - mib = append(mib, _CTL_QUERY) - qnode := sysctlNode{Flags: _SYSCTL_VERS_1} - qp := (*byte)(unsafe.Pointer(&qnode)) - sz := unsafe.Sizeof(qnode) - if err := sysctl(mib, nil, &olen, qp, sz); err != nil { - return nil, err - } - - // Now that we know the size, get the actual nodes. - nodes := make([]sysctlNode, olen/sz) - np := (*byte)(unsafe.Pointer(&nodes[0])) - if err := sysctl(mib, np, &olen, qp, sz); err != nil { - return nil, err - } - - return nodes, nil -} - -func nametomib(name string) ([]int32, error) { - // Split name into components. - var parts []string - last := 0 - for i := 0; i < len(name); i++ { - if name[i] == '.' { - parts = append(parts, name[last:i]) - last = i + 1 - } - } - parts = append(parts, name[last:]) - - mib := []int32{} - // Discover the nodes and construct the MIB OID. - for partno, part := range parts { - nodes, err := sysctlNodes(mib) - if err != nil { - return nil, err - } - for _, node := range nodes { - n := make([]byte, 0) - for i := range node.Name { - if node.Name[i] != 0 { - n = append(n, byte(node.Name[i])) - } - } - if string(n) == part { - mib = append(mib, int32(node.Num)) - break - } - } - if len(mib) != partno+1 { - return nil, err - } - } - - return mib, nil -} - -// aarch64SysctlCPUID is struct aarch64_sysctl_cpu_id from NetBSD's <aarch64/armreg.h> -type aarch64SysctlCPUID struct { - midr uint64 /* Main ID Register */ - revidr uint64 /* Revision ID Register */ - mpidr uint64 /* Multiprocessor Affinity Register */ - aa64dfr0 uint64 /* A64 Debug Feature Register 0 */ - aa64dfr1 uint64 /* A64 Debug Feature Register 1 */ - aa64isar0 uint64 /* A64 Instruction Set Attribute Register 0 */ - aa64isar1 uint64 /* A64 Instruction Set Attribute Register 1 */ - aa64mmfr0 uint64 /* A64 Memory Model Feature Register 0 */ - aa64mmfr1 uint64 /* A64 Memory Model Feature Register 1 */ - aa64mmfr2 uint64 /* A64 Memory Model Feature Register 2 */ - aa64pfr0 uint64 /* A64 Processor Feature Register 0 */ - aa64pfr1 uint64 /* A64 Processor Feature Register 1 */ - aa64zfr0 uint64 /* A64 SVE Feature ID Register 0 */ - mvfr0 uint32 /* Media and VFP Feature Register 0 */ - mvfr1 uint32 /* Media and VFP Feature Register 1 */ - mvfr2 uint32 /* Media and VFP Feature Register 2 */ - pad uint32 - clidr uint64 /* Cache Level ID Register */ - ctr uint64 /* Cache Type Register */ -} - -func sysctlCPUID(name string) (*aarch64SysctlCPUID, error) { - mib, err := nametomib(name) - if err != nil { - return nil, err - } - - out := aarch64SysctlCPUID{} - n := unsafe.Sizeof(out) - _, _, errno := syscall.Syscall6( - syscall.SYS___SYSCTL, - uintptr(unsafe.Pointer(&mib[0])), - uintptr(len(mib)), - uintptr(unsafe.Pointer(&out)), - uintptr(unsafe.Pointer(&n)), - uintptr(0), - uintptr(0)) - if errno != 0 { - return nil, errno - } - return &out, nil -} - -func doinit() { - cpuid, err := sysctlCPUID("machdep.cpu0.cpu_id") - if err != nil { - setMinimalFeatures() - return - } - parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0) - - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go deleted file mode 100644 index 85b64d5c..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "syscall" - "unsafe" -) - -// Minimal copy of functionality from x/sys/unix so the cpu package can call -// sysctl without depending on x/sys/unix. - -const ( - // From OpenBSD's sys/sysctl.h. - _CTL_MACHDEP = 7 - - // From OpenBSD's machine/cpu.h. - _CPU_ID_AA64ISAR0 = 2 - _CPU_ID_AA64ISAR1 = 3 -) - -// Implemented in the runtime package (runtime/sys_openbsd3.go) -func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) - -//go:linkname syscall_syscall6 syscall.syscall6 - -func sysctl(mib []uint32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - _, _, errno := syscall_syscall6(libc_sysctl_trampoline_addr, uintptr(unsafe.Pointer(&mib[0])), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if errno != 0 { - return errno - } - return nil -} - -var libc_sysctl_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_sysctl sysctl "libc.so" - -func sysctlUint64(mib []uint32) (uint64, bool) { - var out uint64 - nout := unsafe.Sizeof(out) - if err := sysctl(mib, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); err != nil { - return 0, false - } - return out, true -} - -func doinit() { - setMinimalFeatures() - - // Get ID_AA64ISAR0 and ID_AA64ISAR1 from sysctl. - isar0, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64ISAR0}) - if !ok { - return - } - isar1, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64ISAR1}) - if !ok { - return - } - parseARM64SystemRegisters(isar0, isar1, 0) - - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s deleted file mode 100644 index 054ba05d..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_openbsd_arm64.s +++ /dev/null @@ -1,11 +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. - -#include "textflag.h" - -TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_sysctl(SB) - -GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 -DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm.go deleted file mode 100644 index e9ecf2a4..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_other_arm.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !linux && arm - -package cpu - -func archInit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go deleted file mode 100644 index 5341e7f8..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go +++ /dev/null @@ -1,9 +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 !linux && !netbsd && !openbsd && arm64 - -package cpu - -func doinit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go b/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go deleted file mode 100644 index 5f8f2419..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !linux && (mips64 || mips64le) - -package cpu - -func archInit() { - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go deleted file mode 100644 index 89608fba..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_other_ppc64x.go +++ /dev/null @@ -1,12 +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 !aix && !linux && (ppc64 || ppc64le) - -package cpu - -func archInit() { - PPC64.IsPOWER8 = true - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go deleted file mode 100644 index 5ab87808..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_other_riscv64.go +++ /dev/null @@ -1,11 +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 !linux && riscv64 - -package cpu - -func archInit() { - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_x86.go b/vendor/golang.org/x/sys/cpu/cpu_other_x86.go deleted file mode 100644 index a0fd7e2f..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_other_x86.go +++ /dev/null @@ -1,11 +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 386 || amd64p32 || (amd64 && (!darwin || !gc)) - -package cpu - -func darwinSupportsAVX512() bool { - panic("only implemented for gc && amd64 && darwin") -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go b/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go deleted file mode 100644 index c14f12b1..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_ppc64x.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ppc64 || ppc64le - -package cpu - -const cacheLineSize = 128 - -func initOptions() { - options = []option{ - {Name: "darn", Feature: &PPC64.HasDARN}, - {Name: "scv", Feature: &PPC64.HasSCV}, - } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go deleted file mode 100644 index 0f617aef..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go +++ /dev/null @@ -1,32 +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 riscv64 - -package cpu - -const cacheLineSize = 64 - -func initOptions() { - options = []option{ - {Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned}, - {Name: "c", Feature: &RISCV64.HasC}, - {Name: "v", Feature: &RISCV64.HasV}, - {Name: "zba", Feature: &RISCV64.HasZba}, - {Name: "zbb", Feature: &RISCV64.HasZbb}, - {Name: "zbs", Feature: &RISCV64.HasZbs}, - // RISC-V Cryptography Extensions - {Name: "zvbb", Feature: &RISCV64.HasZvbb}, - {Name: "zvbc", Feature: &RISCV64.HasZvbc}, - {Name: "zvkb", Feature: &RISCV64.HasZvkb}, - {Name: "zvkg", Feature: &RISCV64.HasZvkg}, - {Name: "zvkt", Feature: &RISCV64.HasZvkt}, - {Name: "zvkn", Feature: &RISCV64.HasZvkn}, - {Name: "zvknc", Feature: &RISCV64.HasZvknc}, - {Name: "zvkng", Feature: &RISCV64.HasZvkng}, - {Name: "zvks", Feature: &RISCV64.HasZvks}, - {Name: "zvksc", Feature: &RISCV64.HasZvksc}, - {Name: "zvksg", Feature: &RISCV64.HasZvksg}, - } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_s390x.go deleted file mode 100644 index 5881b883..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_s390x.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -const cacheLineSize = 256 - -func initOptions() { - options = []option{ - {Name: "zarch", Feature: &S390X.HasZARCH, Required: true}, - {Name: "stfle", Feature: &S390X.HasSTFLE, Required: true}, - {Name: "ldisp", Feature: &S390X.HasLDISP, Required: true}, - {Name: "eimm", Feature: &S390X.HasEIMM, Required: true}, - {Name: "dfp", Feature: &S390X.HasDFP}, - {Name: "etf3eh", Feature: &S390X.HasETF3EH}, - {Name: "msa", Feature: &S390X.HasMSA}, - {Name: "aes", Feature: &S390X.HasAES}, - {Name: "aescbc", Feature: &S390X.HasAESCBC}, - {Name: "aesctr", Feature: &S390X.HasAESCTR}, - {Name: "aesgcm", Feature: &S390X.HasAESGCM}, - {Name: "ghash", Feature: &S390X.HasGHASH}, - {Name: "sha1", Feature: &S390X.HasSHA1}, - {Name: "sha256", Feature: &S390X.HasSHA256}, - {Name: "sha3", Feature: &S390X.HasSHA3}, - {Name: "sha512", Feature: &S390X.HasSHA512}, - {Name: "vx", Feature: &S390X.HasVX}, - {Name: "vxe", Feature: &S390X.HasVXE}, - } -} - -// bitIsSet reports whether the bit at index is set. The bit index -// is in big endian order, so bit index 0 is the leftmost bit. -func bitIsSet(bits []uint64, index uint) bool { - return bits[index/64]&((1<<63)>>(index%64)) != 0 -} - -// facility is a bit index for the named facility. -type facility uint8 - -const ( - // mandatory facilities - zarch facility = 1 // z architecture mode is active - stflef facility = 7 // store-facility-list-extended - ldisp facility = 18 // long-displacement - eimm facility = 21 // extended-immediate - - // miscellaneous facilities - dfp facility = 42 // decimal-floating-point - etf3eh facility = 30 // extended-translation 3 enhancement - - // cryptography facilities - msa facility = 17 // message-security-assist - msa3 facility = 76 // message-security-assist extension 3 - msa4 facility = 77 // message-security-assist extension 4 - msa5 facility = 57 // message-security-assist extension 5 - msa8 facility = 146 // message-security-assist extension 8 - msa9 facility = 155 // message-security-assist extension 9 - - // vector facilities - vx facility = 129 // vector facility - vxe facility = 135 // vector-enhancements 1 - vxe2 facility = 148 // vector-enhancements 2 -) - -// facilityList contains the result of an STFLE call. -// Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type facilityList struct { - bits [4]uint64 -} - -// Has reports whether the given facilities are present. -func (s *facilityList) Has(fs ...facility) bool { - if len(fs) == 0 { - panic("no facility bits provided") - } - for _, f := range fs { - if !bitIsSet(s.bits[:], uint(f)) { - return false - } - } - return true -} - -// function is the code for the named cryptographic function. -type function uint8 - -const ( - // KM{,A,C,CTR} function codes - aes128 function = 18 // AES-128 - aes192 function = 19 // AES-192 - aes256 function = 20 // AES-256 - - // K{I,L}MD function codes - sha1 function = 1 // SHA-1 - sha256 function = 2 // SHA-256 - sha512 function = 3 // SHA-512 - sha3_224 function = 32 // SHA3-224 - sha3_256 function = 33 // SHA3-256 - sha3_384 function = 34 // SHA3-384 - sha3_512 function = 35 // SHA3-512 - shake128 function = 36 // SHAKE-128 - shake256 function = 37 // SHAKE-256 - - // KLMD function codes - ghash function = 65 // GHASH -) - -// queryResult contains the result of a Query function -// call. Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type queryResult struct { - bits [2]uint64 -} - -// Has reports whether the given functions are present. -func (q *queryResult) Has(fns ...function) bool { - if len(fns) == 0 { - panic("no function codes provided") - } - for _, f := range fns { - if !bitIsSet(q.bits[:], uint(f)) { - return false - } - } - return true -} - -func doinit() { - initS390Xbase() - - // We need implementations of stfle, km and so on - // to detect cryptographic features. - if !haveAsmFunctions() { - return - } - - // optional cryptographic functions - if S390X.HasMSA { - aes := []function{aes128, aes192, aes256} - - // cipher message - km, kmc := kmQuery(), kmcQuery() - S390X.HasAES = km.Has(aes...) - S390X.HasAESCBC = kmc.Has(aes...) - if S390X.HasSTFLE { - facilities := stfle() - if facilities.Has(msa4) { - kmctr := kmctrQuery() - S390X.HasAESCTR = kmctr.Has(aes...) - } - if facilities.Has(msa8) { - kma := kmaQuery() - S390X.HasAESGCM = kma.Has(aes...) - } - } - - // compute message digest - kimd := kimdQuery() // intermediate (no padding) - klmd := klmdQuery() // last (padding) - S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) - S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) - S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) - S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist - sha3 := []function{ - sha3_224, sha3_256, sha3_384, sha3_512, - shake128, shake256, - } - S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) - } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_s390x.s b/vendor/golang.org/x/sys/cpu/cpu_s390x.s deleted file mode 100644 index 1fb4b701..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_s390x.s +++ /dev/null @@ -1,57 +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 gc - -#include "textflag.h" - -// func stfle() facilityList -TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32 - MOVD $ret+0(FP), R1 - MOVD $3, R0 // last doubleword index to store - XC $32, (R1), (R1) // clear 4 doublewords (32 bytes) - WORD $0xb2b01000 // store facility list extended (STFLE) - RET - -// func kmQuery() queryResult -TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KM-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92E0024 // cipher message (KM) - RET - -// func kmcQuery() queryResult -TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMC-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92F0024 // cipher message with chaining (KMC) - RET - -// func kmctrQuery() queryResult -TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMCTR-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB92D4024 // cipher message with counter (KMCTR) - RET - -// func kmaQuery() queryResult -TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KMA-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xb9296024 // cipher message with authentication (KMA) - RET - -// func kimdQuery() queryResult -TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KIMD-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB93E0024 // compute intermediate message digest (KIMD) - RET - -// func klmdQuery() queryResult -TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16 - MOVD $0, R0 // set function code to 0 (KLMD-Query) - MOVD $ret+0(FP), R1 // address of 16-byte return value - WORD $0xB93F0024 // compute last message digest (KLMD) - RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_wasm.go b/vendor/golang.org/x/sys/cpu/cpu_wasm.go deleted file mode 100644 index 384787ea..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_wasm.go +++ /dev/null @@ -1,17 +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 wasm - -package cpu - -// We're compiling the cpu package for an unknown (software-abstracted) CPU. -// Make CacheLinePad an empty struct and hope that the usual struct alignment -// rules are good enough. - -const cacheLineSize = 0 - -func initOptions() {} - -func archInit() {} diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go deleted file mode 100644 index 1e642f33..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ /dev/null @@ -1,162 +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 386 || amd64 || amd64p32 - -package cpu - -import "runtime" - -const cacheLineSize = 64 - -func initOptions() { - options = []option{ - {Name: "adx", Feature: &X86.HasADX}, - {Name: "aes", Feature: &X86.HasAES}, - {Name: "avx", Feature: &X86.HasAVX}, - {Name: "avx2", Feature: &X86.HasAVX2}, - {Name: "avx512", Feature: &X86.HasAVX512}, - {Name: "avx512f", Feature: &X86.HasAVX512F}, - {Name: "avx512cd", Feature: &X86.HasAVX512CD}, - {Name: "avx512er", Feature: &X86.HasAVX512ER}, - {Name: "avx512pf", Feature: &X86.HasAVX512PF}, - {Name: "avx512vl", Feature: &X86.HasAVX512VL}, - {Name: "avx512bw", Feature: &X86.HasAVX512BW}, - {Name: "avx512dq", Feature: &X86.HasAVX512DQ}, - {Name: "avx512ifma", Feature: &X86.HasAVX512IFMA}, - {Name: "avx512vbmi", Feature: &X86.HasAVX512VBMI}, - {Name: "avx512vnniw", Feature: &X86.HasAVX5124VNNIW}, - {Name: "avx5124fmaps", Feature: &X86.HasAVX5124FMAPS}, - {Name: "avx512vpopcntdq", Feature: &X86.HasAVX512VPOPCNTDQ}, - {Name: "avx512vpclmulqdq", Feature: &X86.HasAVX512VPCLMULQDQ}, - {Name: "avx512vnni", Feature: &X86.HasAVX512VNNI}, - {Name: "avx512gfni", Feature: &X86.HasAVX512GFNI}, - {Name: "avx512vaes", Feature: &X86.HasAVX512VAES}, - {Name: "avx512vbmi2", Feature: &X86.HasAVX512VBMI2}, - {Name: "avx512bitalg", Feature: &X86.HasAVX512BITALG}, - {Name: "avx512bf16", Feature: &X86.HasAVX512BF16}, - {Name: "amxtile", Feature: &X86.HasAMXTile}, - {Name: "amxint8", Feature: &X86.HasAMXInt8}, - {Name: "amxbf16", Feature: &X86.HasAMXBF16}, - {Name: "bmi1", Feature: &X86.HasBMI1}, - {Name: "bmi2", Feature: &X86.HasBMI2}, - {Name: "cx16", Feature: &X86.HasCX16}, - {Name: "erms", Feature: &X86.HasERMS}, - {Name: "fma", Feature: &X86.HasFMA}, - {Name: "osxsave", Feature: &X86.HasOSXSAVE}, - {Name: "pclmulqdq", Feature: &X86.HasPCLMULQDQ}, - {Name: "popcnt", Feature: &X86.HasPOPCNT}, - {Name: "rdrand", Feature: &X86.HasRDRAND}, - {Name: "rdseed", Feature: &X86.HasRDSEED}, - {Name: "sse3", Feature: &X86.HasSSE3}, - {Name: "sse41", Feature: &X86.HasSSE41}, - {Name: "sse42", Feature: &X86.HasSSE42}, - {Name: "ssse3", Feature: &X86.HasSSSE3}, - {Name: "avxifma", Feature: &X86.HasAVXIFMA}, - {Name: "avxvnni", Feature: &X86.HasAVXVNNI}, - {Name: "avxvnniint8", Feature: &X86.HasAVXVNNIInt8}, - - // These capabilities should always be enabled on amd64: - {Name: "sse2", Feature: &X86.HasSSE2, Required: runtime.GOARCH == "amd64"}, - } -} - -func archInit() { - - Initialized = true - - maxID, _, _, _ := cpuid(0, 0) - - if maxID < 1 { - return - } - - _, _, ecx1, edx1 := cpuid(1, 0) - X86.HasSSE2 = isSet(26, edx1) - - X86.HasSSE3 = isSet(0, ecx1) - X86.HasPCLMULQDQ = isSet(1, ecx1) - X86.HasSSSE3 = isSet(9, ecx1) - X86.HasFMA = isSet(12, ecx1) - X86.HasCX16 = isSet(13, ecx1) - X86.HasSSE41 = isSet(19, ecx1) - X86.HasSSE42 = isSet(20, ecx1) - X86.HasPOPCNT = isSet(23, ecx1) - X86.HasAES = isSet(25, ecx1) - X86.HasOSXSAVE = isSet(27, ecx1) - X86.HasRDRAND = isSet(30, ecx1) - - var osSupportsAVX, osSupportsAVX512 bool - // For XGETBV, OSXSAVE bit is required and sufficient. - if X86.HasOSXSAVE { - eax, _ := xgetbv() - // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(1, eax) && isSet(2, eax) - - if runtime.GOOS == "darwin" { - // Darwin requires special AVX512 checks, see cpu_darwin_x86.go - osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() - } else { - // Check if OPMASK and ZMM registers have OS support. - osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) - } - } - - X86.HasAVX = isSet(28, ecx1) && osSupportsAVX - - if maxID < 7 { - return - } - - eax7, ebx7, ecx7, edx7 := cpuid(7, 0) - X86.HasBMI1 = isSet(3, ebx7) - X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX - X86.HasBMI2 = isSet(8, ebx7) - X86.HasERMS = isSet(9, ebx7) - X86.HasRDSEED = isSet(18, ebx7) - X86.HasADX = isSet(19, ebx7) - - X86.HasAVX512 = isSet(16, ebx7) && osSupportsAVX512 // Because avx-512 foundation is the core required extension - if X86.HasAVX512 { - X86.HasAVX512F = true - X86.HasAVX512CD = isSet(28, ebx7) - X86.HasAVX512ER = isSet(27, ebx7) - X86.HasAVX512PF = isSet(26, ebx7) - X86.HasAVX512VL = isSet(31, ebx7) - X86.HasAVX512BW = isSet(30, ebx7) - X86.HasAVX512DQ = isSet(17, ebx7) - X86.HasAVX512IFMA = isSet(21, ebx7) - X86.HasAVX512VBMI = isSet(1, ecx7) - X86.HasAVX5124VNNIW = isSet(2, edx7) - X86.HasAVX5124FMAPS = isSet(3, edx7) - X86.HasAVX512VPOPCNTDQ = isSet(14, ecx7) - X86.HasAVX512VPCLMULQDQ = isSet(10, ecx7) - X86.HasAVX512VNNI = isSet(11, ecx7) - X86.HasAVX512GFNI = isSet(8, ecx7) - X86.HasAVX512VAES = isSet(9, ecx7) - X86.HasAVX512VBMI2 = isSet(6, ecx7) - X86.HasAVX512BITALG = isSet(12, ecx7) - } - - X86.HasAMXTile = isSet(24, edx7) - X86.HasAMXInt8 = isSet(25, edx7) - X86.HasAMXBF16 = isSet(22, edx7) - - // These features depend on the second level of extended features. - if eax7 >= 1 { - eax71, _, _, edx71 := cpuid(7, 1) - if X86.HasAVX512 { - X86.HasAVX512BF16 = isSet(5, eax71) - } - if X86.HasAVX { - X86.HasAVXIFMA = isSet(23, eax71) - X86.HasAVXVNNI = isSet(4, eax71) - X86.HasAVXVNNIInt8 = isSet(4, edx71) - } - } -} - -func isSet(bitpos uint, value uint32) bool { - return value&(1<<bitpos) != 0 -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_zos.go b/vendor/golang.org/x/sys/cpu/cpu_zos.go deleted file mode 100644 index 5f54683a..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_zos.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -func archInit() { - doinit() - Initialized = true -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go b/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go deleted file mode 100644 index ccb1b708..00000000 --- a/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -func initS390Xbase() { - // get the facilities list - facilities := stfle() - - // mandatory - S390X.HasZARCH = facilities.Has(zarch) - S390X.HasSTFLE = facilities.Has(stflef) - S390X.HasLDISP = facilities.Has(ldisp) - S390X.HasEIMM = facilities.Has(eimm) - - // optional - S390X.HasETF3EH = facilities.Has(etf3eh) - S390X.HasDFP = facilities.Has(dfp) - S390X.HasMSA = facilities.Has(msa) - S390X.HasVX = facilities.Has(vx) - if S390X.HasVX { - S390X.HasVXE = facilities.Has(vxe) - } -} diff --git a/vendor/golang.org/x/sys/cpu/endian_big.go b/vendor/golang.org/x/sys/cpu/endian_big.go deleted file mode 100644 index 7fe04b0a..00000000 --- a/vendor/golang.org/x/sys/cpu/endian_big.go +++ /dev/null @@ -1,10 +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 armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64 - -package cpu - -// IsBigEndian records whether the GOARCH's byte order is big endian. -const IsBigEndian = true diff --git a/vendor/golang.org/x/sys/cpu/endian_little.go b/vendor/golang.org/x/sys/cpu/endian_little.go deleted file mode 100644 index 48eccc4c..00000000 --- a/vendor/golang.org/x/sys/cpu/endian_little.go +++ /dev/null @@ -1,10 +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 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh || wasm - -package cpu - -// IsBigEndian records whether the GOARCH's byte order is big endian. -const IsBigEndian = false diff --git a/vendor/golang.org/x/sys/cpu/hwcap_linux.go b/vendor/golang.org/x/sys/cpu/hwcap_linux.go deleted file mode 100644 index 34e49f95..00000000 --- a/vendor/golang.org/x/sys/cpu/hwcap_linux.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import ( - "os" -) - -const ( - _AT_HWCAP = 16 - _AT_HWCAP2 = 26 - - procAuxv = "/proc/self/auxv" - - uintSize = int(32 << (^uint(0) >> 63)) -) - -// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2 -// These are initialized in cpu_$GOARCH.go -// and should not be changed after they are initialized. -var hwCap uint -var hwCap2 uint - -func readHWCAP() error { - // For Go 1.21+, get auxv from the Go runtime. - if a := getAuxv(); len(a) > 0 { - for len(a) >= 2 { - tag, val := a[0], uint(a[1]) - a = a[2:] - switch tag { - case _AT_HWCAP: - hwCap = val - case _AT_HWCAP2: - hwCap2 = val - } - } - return nil - } - - buf, err := os.ReadFile(procAuxv) - if err != nil { - // e.g. on android /proc/self/auxv is not accessible, so silently - // ignore the error and leave Initialized = false. On some - // architectures (e.g. arm64) doinit() implements a fallback - // readout and will set Initialized = true again. - return err - } - bo := hostByteOrder() - for len(buf) >= 2*(uintSize/8) { - var tag, val uint - switch uintSize { - case 32: - tag = uint(bo.Uint32(buf[0:])) - val = uint(bo.Uint32(buf[4:])) - buf = buf[8:] - case 64: - tag = uint(bo.Uint64(buf[0:])) - val = uint(bo.Uint64(buf[8:])) - buf = buf[16:] - } - switch tag { - case _AT_HWCAP: - hwCap = val - case _AT_HWCAP2: - hwCap2 = val - } - } - return nil -} diff --git a/vendor/golang.org/x/sys/cpu/parse.go b/vendor/golang.org/x/sys/cpu/parse.go deleted file mode 100644 index 56a7e1a1..00000000 --- a/vendor/golang.org/x/sys/cpu/parse.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cpu - -import "strconv" - -// parseRelease parses a dot-separated version number. It follows the semver -// syntax, but allows the minor and patch versions to be elided. -// -// This is a copy of the Go runtime's parseRelease from -// https://golang.org/cl/209597. -func parseRelease(rel string) (major, minor, patch int, ok bool) { - // Strip anything after a dash or plus. - for i := range len(rel) { - if rel[i] == '-' || rel[i] == '+' { - rel = rel[:i] - break - } - } - - next := func() (int, bool) { - for i := range len(rel) { - if rel[i] == '.' { - ver, err := strconv.Atoi(rel[:i]) - rel = rel[i+1:] - return ver, err == nil - } - } - ver, err := strconv.Atoi(rel) - rel = "" - return ver, err == nil - } - if major, ok = next(); !ok || rel == "" { - return - } - if minor, ok = next(); !ok || rel == "" { - return - } - patch, ok = next() - return -} diff --git a/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go b/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go deleted file mode 100644 index 4cd64c70..00000000 --- a/vendor/golang.org/x/sys/cpu/proc_cpuinfo_linux.go +++ /dev/null @@ -1,53 +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 linux && arm64 - -package cpu - -import ( - "errors" - "io" - "os" - "strings" -) - -func readLinuxProcCPUInfo() error { - f, err := os.Open("/proc/cpuinfo") - if err != nil { - return err - } - defer f.Close() - - var buf [1 << 10]byte // enough for first CPU - n, err := io.ReadFull(f, buf[:]) - if err != nil && err != io.ErrUnexpectedEOF { - return err - } - in := string(buf[:n]) - const features = "\nFeatures : " - i := strings.Index(in, features) - if i == -1 { - return errors.New("no CPU features found") - } - in = in[i+len(features):] - if i := strings.Index(in, "\n"); i != -1 { - in = in[:i] - } - m := map[string]*bool{} - - initOptions() // need it early here; it's harmless to call twice - for _, o := range options { - m[o.Name] = o.Feature - } - // The EVTSTRM field has alias "evstrm" in Go, but Linux calls it "evtstrm". - m["evtstrm"] = &ARM64.HasEVTSTRM - - for _, f := range strings.Fields(in) { - if p, ok := m[f]; ok { - *p = true - } - } - return nil -} diff --git a/vendor/golang.org/x/sys/cpu/runtime_auxv.go b/vendor/golang.org/x/sys/cpu/runtime_auxv.go deleted file mode 100644 index 5f92ac9a..00000000 --- a/vendor/golang.org/x/sys/cpu/runtime_auxv.go +++ /dev/null @@ -1,16 +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 cpu - -// getAuxvFn is non-nil on Go 1.21+ (via runtime_auxv_go121.go init) -// on platforms that use auxv. -var getAuxvFn func() []uintptr - -func getAuxv() []uintptr { - if getAuxvFn == nil { - return nil - } - return getAuxvFn() -} diff --git a/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go b/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go deleted file mode 100644 index 4c9788ea..00000000 --- a/vendor/golang.org/x/sys/cpu/runtime_auxv_go121.go +++ /dev/null @@ -1,18 +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.21 - -package cpu - -import ( - _ "unsafe" // for linkname -) - -//go:linkname runtime_getAuxv runtime.getAuxv -func runtime_getAuxv() []uintptr - -func init() { - getAuxvFn = runtime_getAuxv -} diff --git a/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go b/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go deleted file mode 100644 index 1b9ccb09..00000000 --- a/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Recreate a getsystemcfg syscall handler instead of -// using the one provided by x/sys/unix to avoid having -// the dependency between them. (See golang.org/issue/32102) -// Moreover, this file will be used during the building of -// gccgo's libgo and thus must not used a CGo method. - -//go:build aix && gccgo - -package cpu - -import ( - "syscall" -) - -//extern getsystemcfg -func gccgoGetsystemcfg(label uint32) (r uint64) - -func callgetsystemcfg(label int) (r1 uintptr, e1 syscall.Errno) { - r1 = uintptr(gccgoGetsystemcfg(uint32(label))) - e1 = syscall.GetErrno() - return -} diff --git a/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go deleted file mode 100644 index e8b6cdbe..00000000 --- a/vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go +++ /dev/null @@ -1,35 +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. - -// Minimal copy of x/sys/unix so the cpu package can make a -// system call on AIX without depending on x/sys/unix. -// (See golang.org/issue/32102) - -//go:build aix && ppc64 && gc - -package cpu - -import ( - "syscall" - "unsafe" -) - -//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o" - -//go:linkname libc_getsystemcfg libc_getsystemcfg - -type syscallFunc uintptr - -var libc_getsystemcfg syscallFunc - -type errno = syscall.Errno - -// Implemented in runtime/syscall_aix.go. -func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) -func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno) - -func callgetsystemcfg(label int) (r1 uintptr, e1 errno) { - r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsystemcfg)), 1, uintptr(label), 0, 0, 0, 0, 0) - return -} diff --git a/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go b/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go deleted file mode 100644 index 4d0888b0..00000000 --- a/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go +++ /dev/null @@ -1,98 +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. - -// Minimal copy of x/sys/unix so the cpu package can make a -// system call on Darwin without depending on x/sys/unix. - -//go:build darwin && amd64 && gc - -package cpu - -import ( - "syscall" - "unsafe" -) - -type _C_int int32 - -// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419 -func darwinOSRelease(release *[256]byte) error { - // from x/sys/unix/zerrors_openbsd_amd64.go - const ( - CTL_KERN = 0x1 - KERN_OSRELEASE = 0x2 - ) - - mib := []_C_int{CTL_KERN, KERN_OSRELEASE} - n := unsafe.Sizeof(*release) - - return sysctl(mib, &release[0], &n, nil, 0) -} - -type Errno = syscall.Errno - -var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes. - -// from x/sys/unix/zsyscall_darwin_amd64.go L791-807 -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - if _, _, err := syscall_syscall6( - libc_sysctl_trampoline_addr, - uintptr(_p0), - uintptr(len(mib)), - uintptr(unsafe.Pointer(old)), - uintptr(unsafe.Pointer(oldlen)), - uintptr(unsafe.Pointer(new)), - uintptr(newlen), - ); err != 0 { - return err - } - - return nil -} - -var libc_sysctl_trampoline_addr uintptr - -// adapted from internal/cpu/cpu_arm64_darwin.go -func darwinSysctlEnabled(name []byte) bool { - out := int32(0) - nout := unsafe.Sizeof(out) - if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil { - return false - } - return out > 0 -} - -//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" - -var libc_sysctlbyname_trampoline_addr uintptr - -// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix -func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { - if _, _, err := syscall_syscall6( - libc_sysctlbyname_trampoline_addr, - uintptr(unsafe.Pointer(name)), - uintptr(unsafe.Pointer(old)), - uintptr(unsafe.Pointer(oldlen)), - uintptr(unsafe.Pointer(new)), - uintptr(newlen), - 0, - ); err != 0 { - return err - } - - return nil -} - -//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib" - -// Implemented in the runtime package (runtime/sys_darwin.go) -func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) - -//go:linkname syscall_syscall6 syscall.syscall6 diff --git a/vendor/golang.org/x/sys/execabs/execabs.go b/vendor/golang.org/x/sys/execabs/execabs.go deleted file mode 100644 index 3bf40fdf..00000000 --- a/vendor/golang.org/x/sys/execabs/execabs.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package execabs is a drop-in replacement for os/exec -// that requires PATH lookups to find absolute paths. -// That is, execabs.Command("cmd") runs the same PATH lookup -// as exec.Command("cmd"), but if the result is a path -// which is relative, the Run and Start methods will report -// an error instead of running the executable. -// -// See https://blog.golang.org/path-security for more information -// about when it may be necessary or appropriate to use this package. -package execabs - -import ( - "context" - "fmt" - "os/exec" - "path/filepath" - "reflect" - "unsafe" -) - -// ErrNotFound is the error resulting if a path search failed to find an executable file. -// It is an alias for exec.ErrNotFound. -var ErrNotFound = exec.ErrNotFound - -// Cmd represents an external command being prepared or run. -// It is an alias for exec.Cmd. -type Cmd = exec.Cmd - -// Error is returned by LookPath when it fails to classify a file as an executable. -// It is an alias for exec.Error. -type Error = exec.Error - -// An ExitError reports an unsuccessful exit by a command. -// It is an alias for exec.ExitError. -type ExitError = exec.ExitError - -func relError(file, path string) error { - return fmt.Errorf("%s resolves to executable in current directory (.%c%s)", file, filepath.Separator, path) -} - -// LookPath searches for an executable named file in the directories -// named by the PATH environment variable. If file contains a slash, -// it is tried directly and the PATH is not consulted. The result will be -// an absolute path. -// -// LookPath differs from exec.LookPath in its handling of PATH lookups, -// which are used for file names without slashes. If exec.LookPath's -// PATH lookup would have returned an executable from the current directory, -// LookPath instead returns an error. -func LookPath(file string) (string, error) { - path, err := exec.LookPath(file) - if err != nil && !isGo119ErrDot(err) { - return "", err - } - if filepath.Base(file) == file && !filepath.IsAbs(path) { - return "", relError(file, path) - } - return path, nil -} - -func fixCmd(name string, cmd *exec.Cmd) { - if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) && !isGo119ErrFieldSet(cmd) { - // exec.Command was called with a bare binary name and - // exec.LookPath returned a path which is not absolute. - // Set cmd.lookPathErr and clear cmd.Path so that it - // cannot be run. - lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer())) - if *lookPathErr == nil { - *lookPathErr = relError(name, cmd.Path) - } - cmd.Path = "" - } -} - -// CommandContext is like Command but includes a context. -// -// The provided context is used to kill the process (by calling os.Process.Kill) -// if the context becomes done before the command completes on its own. -func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd { - cmd := exec.CommandContext(ctx, name, arg...) - fixCmd(name, cmd) - return cmd - -} - -// Command returns the Cmd struct to execute the named program with the given arguments. -// See exec.Command for most details. -// -// Command differs from exec.Command in its handling of PATH lookups, -// which are used when the program name contains no slashes. -// If exec.Command would have returned an exec.Cmd configured to run an -// executable from the current directory, Command instead -// returns an exec.Cmd that will return an error from Start or Run. -func Command(name string, arg ...string) *exec.Cmd { - cmd := exec.Command(name, arg...) - fixCmd(name, cmd) - return cmd -} diff --git a/vendor/golang.org/x/sys/execabs/execabs_go118.go b/vendor/golang.org/x/sys/execabs/execabs_go118.go deleted file mode 100644 index 5627d70e..00000000 --- a/vendor/golang.org/x/sys/execabs/execabs_go118.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.19 - -package execabs - -import "os/exec" - -func isGo119ErrDot(err error) bool { - return false -} - -func isGo119ErrFieldSet(cmd *exec.Cmd) bool { - return false -} diff --git a/vendor/golang.org/x/sys/execabs/execabs_go119.go b/vendor/golang.org/x/sys/execabs/execabs_go119.go deleted file mode 100644 index d60ab1b4..00000000 --- a/vendor/golang.org/x/sys/execabs/execabs_go119.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.19 - -package execabs - -import ( - "errors" - "os/exec" -) - -func isGo119ErrDot(err error) bool { - return errors.Is(err, exec.ErrDot) -} - -func isGo119ErrFieldSet(cmd *exec.Cmd) bool { - return cmd.Err != nil -} diff --git a/vendor/golang.org/x/sys/windows/registry/key.go b/vendor/golang.org/x/sys/windows/registry/key.go deleted file mode 100644 index 39aeeb64..00000000 --- a/vendor/golang.org/x/sys/windows/registry/key.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2015 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 windows - -// Package registry provides access to the Windows registry. -// -// Here is a simple example, opening a registry key and reading a string value from it. -// -// k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) -// if err != nil { -// log.Fatal(err) -// } -// defer k.Close() -// -// s, _, err := k.GetStringValue("SystemRoot") -// if err != nil { -// log.Fatal(err) -// } -// fmt.Printf("Windows system root is %q\n", s) -package registry - -import ( - "io" - "runtime" - "syscall" - "time" -) - -const ( - // Registry key security and access rights. - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724878.aspx - // for details. - ALL_ACCESS = 0xf003f - CREATE_LINK = 0x00020 - CREATE_SUB_KEY = 0x00004 - ENUMERATE_SUB_KEYS = 0x00008 - EXECUTE = 0x20019 - NOTIFY = 0x00010 - QUERY_VALUE = 0x00001 - READ = 0x20019 - SET_VALUE = 0x00002 - WOW64_32KEY = 0x00200 - WOW64_64KEY = 0x00100 - WRITE = 0x20006 -) - -// Key is a handle to an open Windows registry key. -// Keys can be obtained by calling OpenKey; there are -// also some predefined root keys such as CURRENT_USER. -// Keys can be used directly in the Windows API. -type Key syscall.Handle - -const ( - // Windows defines some predefined root keys that are always open. - // An application can use these keys as entry points to the registry. - // Normally these keys are used in OpenKey to open new keys, - // but they can also be used anywhere a Key is required. - CLASSES_ROOT = Key(syscall.HKEY_CLASSES_ROOT) - CURRENT_USER = Key(syscall.HKEY_CURRENT_USER) - LOCAL_MACHINE = Key(syscall.HKEY_LOCAL_MACHINE) - USERS = Key(syscall.HKEY_USERS) - CURRENT_CONFIG = Key(syscall.HKEY_CURRENT_CONFIG) - PERFORMANCE_DATA = Key(syscall.HKEY_PERFORMANCE_DATA) -) - -// Close closes open key k. -func (k Key) Close() error { - return syscall.RegCloseKey(syscall.Handle(k)) -} - -// OpenKey opens a new key with path name relative to key k. -// It accepts any open key, including CURRENT_USER and others, -// and returns the new key and an error. -// The access parameter specifies desired access rights to the -// key to be opened. -func OpenKey(k Key, path string, access uint32) (Key, error) { - p, err := syscall.UTF16PtrFromString(path) - if err != nil { - return 0, err - } - var subkey syscall.Handle - err = syscall.RegOpenKeyEx(syscall.Handle(k), p, 0, access, &subkey) - if err != nil { - return 0, err - } - return Key(subkey), nil -} - -// OpenRemoteKey opens a predefined registry key on another -// computer pcname. The key to be opened is specified by k, but -// can only be one of LOCAL_MACHINE, PERFORMANCE_DATA or USERS. -// If pcname is "", OpenRemoteKey returns local computer key. -func OpenRemoteKey(pcname string, k Key) (Key, error) { - var err error - var p *uint16 - if pcname != "" { - p, err = syscall.UTF16PtrFromString(`\\` + pcname) - if err != nil { - return 0, err - } - } - var remoteKey syscall.Handle - err = regConnectRegistry(p, syscall.Handle(k), &remoteKey) - if err != nil { - return 0, err - } - return Key(remoteKey), nil -} - -// ReadSubKeyNames returns the names of subkeys of key k. -// The parameter n controls the number of returned names, -// analogous to the way os.File.Readdirnames works. -func (k Key) ReadSubKeyNames(n int) ([]string, error) { - // RegEnumKeyEx must be called repeatedly and to completion. - // During this time, this goroutine cannot migrate away from - // its current thread. See https://golang.org/issue/49320 and - // https://golang.org/issue/49466. - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - names := make([]string, 0) - // Registry key size limit is 255 bytes and described there: - // https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx - buf := make([]uint16, 256) //plus extra room for terminating zero byte -loopItems: - for i := uint32(0); ; i++ { - if n > 0 { - if len(names) == n { - return names, nil - } - } - l := uint32(len(buf)) - for { - err := syscall.RegEnumKeyEx(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil) - if err == nil { - break - } - if err == syscall.ERROR_MORE_DATA { - // Double buffer size and try again. - l = uint32(2 * len(buf)) - buf = make([]uint16, l) - continue - } - if err == _ERROR_NO_MORE_ITEMS { - break loopItems - } - return names, err - } - names = append(names, syscall.UTF16ToString(buf[:l])) - } - if n > len(names) { - return names, io.EOF - } - return names, nil -} - -// CreateKey creates a key named path under open key k. -// CreateKey returns the new key and a boolean flag that reports -// whether the key already existed. -// The access parameter specifies the access rights for the key -// to be created. -func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool, err error) { - var h syscall.Handle - var d uint32 - var pathPointer *uint16 - pathPointer, err = syscall.UTF16PtrFromString(path) - if err != nil { - return 0, false, err - } - err = regCreateKeyEx(syscall.Handle(k), pathPointer, - 0, nil, _REG_OPTION_NON_VOLATILE, access, nil, &h, &d) - if err != nil { - return 0, false, err - } - return Key(h), d == _REG_OPENED_EXISTING_KEY, nil -} - -// DeleteKey deletes the subkey path of key k and its values. -func DeleteKey(k Key, path string) error { - pathPointer, err := syscall.UTF16PtrFromString(path) - if err != nil { - return err - } - return regDeleteKey(syscall.Handle(k), pathPointer) -} - -// A KeyInfo describes the statistics of a key. It is returned by Stat. -type KeyInfo struct { - SubKeyCount uint32 - MaxSubKeyLen uint32 // size of the key's subkey with the longest name, in Unicode characters, not including the terminating zero byte - ValueCount uint32 - MaxValueNameLen uint32 // size of the key's longest value name, in Unicode characters, not including the terminating zero byte - MaxValueLen uint32 // longest data component among the key's values, in bytes - lastWriteTime syscall.Filetime -} - -// ModTime returns the key's last write time. -func (ki *KeyInfo) ModTime() time.Time { - return time.Unix(0, ki.lastWriteTime.Nanoseconds()) -} - -// Stat retrieves information about the open key k. -func (k Key) Stat() (*KeyInfo, error) { - var ki KeyInfo - err := syscall.RegQueryInfoKey(syscall.Handle(k), nil, nil, nil, - &ki.SubKeyCount, &ki.MaxSubKeyLen, nil, &ki.ValueCount, - &ki.MaxValueNameLen, &ki.MaxValueLen, nil, &ki.lastWriteTime) - if err != nil { - return nil, err - } - return &ki, nil -} diff --git a/vendor/golang.org/x/sys/windows/registry/mksyscall.go b/vendor/golang.org/x/sys/windows/registry/mksyscall.go deleted file mode 100644 index bbf86ccf..00000000 --- a/vendor/golang.org/x/sys/windows/registry/mksyscall.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2015 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 generate - -package registry - -//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall.go diff --git a/vendor/golang.org/x/sys/windows/registry/syscall.go b/vendor/golang.org/x/sys/windows/registry/syscall.go deleted file mode 100644 index f533091c..00000000 --- a/vendor/golang.org/x/sys/windows/registry/syscall.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 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 windows - -package registry - -import "syscall" - -const ( - _REG_OPTION_NON_VOLATILE = 0 - - _REG_CREATED_NEW_KEY = 1 - _REG_OPENED_EXISTING_KEY = 2 - - _ERROR_NO_MORE_ITEMS syscall.Errno = 259 -) - -func LoadRegLoadMUIString() error { - return procRegLoadMUIStringW.Find() -} - -//sys regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW -//sys regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) = advapi32.RegDeleteKeyW -//sys regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) = advapi32.RegSetValueExW -//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegEnumValueW -//sys regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) = advapi32.RegDeleteValueW -//sys regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) = advapi32.RegLoadMUIStringW -//sys regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) = advapi32.RegConnectRegistryW - -//sys expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW diff --git a/vendor/golang.org/x/sys/windows/registry/value.go b/vendor/golang.org/x/sys/windows/registry/value.go deleted file mode 100644 index a1bcbb23..00000000 --- a/vendor/golang.org/x/sys/windows/registry/value.go +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2015 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 windows - -package registry - -import ( - "errors" - "io" - "syscall" - "unicode/utf16" - "unsafe" -) - -const ( - // Registry value types. - NONE = 0 - SZ = 1 - EXPAND_SZ = 2 - BINARY = 3 - DWORD = 4 - DWORD_BIG_ENDIAN = 5 - LINK = 6 - MULTI_SZ = 7 - RESOURCE_LIST = 8 - FULL_RESOURCE_DESCRIPTOR = 9 - RESOURCE_REQUIREMENTS_LIST = 10 - QWORD = 11 -) - -var ( - // ErrShortBuffer is returned when the buffer was too short for the operation. - ErrShortBuffer = syscall.ERROR_MORE_DATA - - // ErrNotExist is returned when a registry key or value does not exist. - ErrNotExist = syscall.ERROR_FILE_NOT_FOUND - - // ErrUnexpectedType is returned by Get*Value when the value's type was unexpected. - ErrUnexpectedType = errors.New("unexpected key value type") -) - -// GetValue retrieves the type and data for the specified value associated -// with an open key k. It fills up buffer buf and returns the retrieved -// byte count n. If buf is too small to fit the stored value it returns -// ErrShortBuffer error along with the required buffer size n. -// If no buffer is provided, it returns true and actual buffer size n. -// If no buffer is provided, GetValue returns the value's type only. -// If the value does not exist, the error returned is ErrNotExist. -// -// GetValue is a low level function. If value's type is known, use the appropriate -// Get*Value function instead. -func (k Key) GetValue(name string, buf []byte) (n int, valtype uint32, err error) { - pname, err := syscall.UTF16PtrFromString(name) - if err != nil { - return 0, 0, err - } - var pbuf *byte - if len(buf) > 0 { - pbuf = (*byte)(unsafe.Pointer(&buf[0])) - } - l := uint32(len(buf)) - err = syscall.RegQueryValueEx(syscall.Handle(k), pname, nil, &valtype, pbuf, &l) - if err != nil { - return int(l), valtype, err - } - return int(l), valtype, nil -} - -func (k Key) getValue(name string, buf []byte) (data []byte, valtype uint32, err error) { - p, err := syscall.UTF16PtrFromString(name) - if err != nil { - return nil, 0, err - } - var t uint32 - n := uint32(len(buf)) - for { - err = syscall.RegQueryValueEx(syscall.Handle(k), p, nil, &t, (*byte)(unsafe.Pointer(&buf[0])), &n) - if err == nil { - return buf[:n], t, nil - } - if err != syscall.ERROR_MORE_DATA { - return nil, 0, err - } - if n <= uint32(len(buf)) { - return nil, 0, err - } - buf = make([]byte, n) - } -} - -// GetStringValue retrieves the string value for the specified -// value name associated with an open key k. It also returns the value's type. -// If value does not exist, GetStringValue returns ErrNotExist. -// If value is not SZ or EXPAND_SZ, it will return the correct value -// type and ErrUnexpectedType. -func (k Key) GetStringValue(name string) (val string, valtype uint32, err error) { - data, typ, err2 := k.getValue(name, make([]byte, 64)) - if err2 != nil { - return "", typ, err2 - } - switch typ { - case SZ, EXPAND_SZ: - default: - return "", typ, ErrUnexpectedType - } - if len(data) == 0 { - return "", typ, nil - } - u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[: len(data)/2 : len(data)/2] - return syscall.UTF16ToString(u), typ, nil -} - -// GetMUIStringValue retrieves the localized string value for -// the specified value name associated with an open key k. -// If the value name doesn't exist or the localized string value -// can't be resolved, GetMUIStringValue returns ErrNotExist. -// GetMUIStringValue panics if the system doesn't support -// regLoadMUIString; use LoadRegLoadMUIString to check if -// regLoadMUIString is supported before calling this function. -func (k Key) GetMUIStringValue(name string) (string, error) { - pname, err := syscall.UTF16PtrFromString(name) - if err != nil { - return "", err - } - - buf := make([]uint16, 1024) - var buflen uint32 - var pdir *uint16 - - err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir) - if err == syscall.ERROR_FILE_NOT_FOUND { // Try fallback path - - // Try to resolve the string value using the system directory as - // a DLL search path; this assumes the string value is of the form - // @[path]\dllname,-strID but with no path given, e.g. @tzres.dll,-320. - - // This approach works with tzres.dll but may have to be revised - // in the future to allow callers to provide custom search paths. - - var s string - s, err = ExpandString("%SystemRoot%\\system32\\") - if err != nil { - return "", err - } - pdir, err = syscall.UTF16PtrFromString(s) - if err != nil { - return "", err - } - - err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir) - } - - for err == syscall.ERROR_MORE_DATA { // Grow buffer if needed - if buflen <= uint32(len(buf)) { - break // Buffer not growing, assume race; break - } - buf = make([]uint16, buflen) - err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir) - } - - if err != nil { - return "", err - } - - return syscall.UTF16ToString(buf), nil -} - -// ExpandString expands environment-variable strings and replaces -// them with the values defined for the current user. -// Use ExpandString to expand EXPAND_SZ strings. -func ExpandString(value string) (string, error) { - if value == "" { - return "", nil - } - p, err := syscall.UTF16PtrFromString(value) - if err != nil { - return "", err - } - r := make([]uint16, 100) - for { - n, err := expandEnvironmentStrings(p, &r[0], uint32(len(r))) - if err != nil { - return "", err - } - if n <= uint32(len(r)) { - return syscall.UTF16ToString(r[:n]), nil - } - r = make([]uint16, n) - } -} - -// GetStringsValue retrieves the []string value for the specified -// value name associated with an open key k. It also returns the value's type. -// If value does not exist, GetStringsValue returns ErrNotExist. -// If value is not MULTI_SZ, it will return the correct value -// type and ErrUnexpectedType. -func (k Key) GetStringsValue(name string) (val []string, valtype uint32, err error) { - data, typ, err2 := k.getValue(name, make([]byte, 64)) - if err2 != nil { - return nil, typ, err2 - } - if typ != MULTI_SZ { - return nil, typ, ErrUnexpectedType - } - if len(data) == 0 { - return nil, typ, nil - } - p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[: len(data)/2 : len(data)/2] - if len(p) == 0 { - return nil, typ, nil - } - if p[len(p)-1] == 0 { - p = p[:len(p)-1] // remove terminating null - } - val = make([]string, 0, 5) - from := 0 - for i, c := range p { - if c == 0 { - val = append(val, string(utf16.Decode(p[from:i]))) - from = i + 1 - } - } - return val, typ, nil -} - -// GetIntegerValue retrieves the integer value for the specified -// value name associated with an open key k. It also returns the value's type. -// If value does not exist, GetIntegerValue returns ErrNotExist. -// If value is not DWORD or QWORD, it will return the correct value -// type and ErrUnexpectedType. -func (k Key) GetIntegerValue(name string) (val uint64, valtype uint32, err error) { - data, typ, err2 := k.getValue(name, make([]byte, 8)) - if err2 != nil { - return 0, typ, err2 - } - switch typ { - case DWORD: - if len(data) != 4 { - return 0, typ, errors.New("DWORD value is not 4 bytes long") - } - var val32 uint32 - copy((*[4]byte)(unsafe.Pointer(&val32))[:], data) - return uint64(val32), DWORD, nil - case QWORD: - if len(data) != 8 { - return 0, typ, errors.New("QWORD value is not 8 bytes long") - } - copy((*[8]byte)(unsafe.Pointer(&val))[:], data) - return val, QWORD, nil - default: - return 0, typ, ErrUnexpectedType - } -} - -// GetBinaryValue retrieves the binary value for the specified -// value name associated with an open key k. It also returns the value's type. -// If value does not exist, GetBinaryValue returns ErrNotExist. -// If value is not BINARY, it will return the correct value -// type and ErrUnexpectedType. -func (k Key) GetBinaryValue(name string) (val []byte, valtype uint32, err error) { - data, typ, err2 := k.getValue(name, make([]byte, 64)) - if err2 != nil { - return nil, typ, err2 - } - if typ != BINARY { - return nil, typ, ErrUnexpectedType - } - return data, typ, nil -} - -func (k Key) setValue(name string, valtype uint32, data []byte) error { - p, err := syscall.UTF16PtrFromString(name) - if err != nil { - return err - } - if len(data) == 0 { - return regSetValueEx(syscall.Handle(k), p, 0, valtype, nil, 0) - } - return regSetValueEx(syscall.Handle(k), p, 0, valtype, &data[0], uint32(len(data))) -} - -// SetDWordValue sets the data and type of a name value -// under key k to value and DWORD. -func (k Key) SetDWordValue(name string, value uint32) error { - return k.setValue(name, DWORD, (*[4]byte)(unsafe.Pointer(&value))[:]) -} - -// SetQWordValue sets the data and type of a name value -// under key k to value and QWORD. -func (k Key) SetQWordValue(name string, value uint64) error { - return k.setValue(name, QWORD, (*[8]byte)(unsafe.Pointer(&value))[:]) -} - -func (k Key) setStringValue(name string, valtype uint32, value string) error { - v, err := syscall.UTF16FromString(value) - if err != nil { - return err - } - buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[: len(v)*2 : len(v)*2] - return k.setValue(name, valtype, buf) -} - -// SetStringValue sets the data and type of a name value -// under key k to value and SZ. The value must not contain a zero byte. -func (k Key) SetStringValue(name, value string) error { - return k.setStringValue(name, SZ, value) -} - -// SetExpandStringValue sets the data and type of a name value -// under key k to value and EXPAND_SZ. The value must not contain a zero byte. -func (k Key) SetExpandStringValue(name, value string) error { - return k.setStringValue(name, EXPAND_SZ, value) -} - -// SetStringsValue sets the data and type of a name value -// under key k to value and MULTI_SZ. The value strings -// must not contain a zero byte. -func (k Key) SetStringsValue(name string, value []string) error { - ss := "" - for _, s := range value { - for i := 0; i < len(s); i++ { - if s[i] == 0 { - return errors.New("string cannot have 0 inside") - } - } - ss += s + "\x00" - } - v := utf16.Encode([]rune(ss + "\x00")) - buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[: len(v)*2 : len(v)*2] - return k.setValue(name, MULTI_SZ, buf) -} - -// SetBinaryValue sets the data and type of a name value -// under key k to value and BINARY. -func (k Key) SetBinaryValue(name string, value []byte) error { - return k.setValue(name, BINARY, value) -} - -// DeleteValue removes a named value from the key k. -func (k Key) DeleteValue(name string) error { - namePointer, err := syscall.UTF16PtrFromString(name) - if err != nil { - return err - } - return regDeleteValue(syscall.Handle(k), namePointer) -} - -// ReadValueNames returns the value names of key k. -// The parameter n controls the number of returned names, -// analogous to the way os.File.Readdirnames works. -func (k Key) ReadValueNames(n int) ([]string, error) { - ki, err := k.Stat() - if err != nil { - return nil, err - } - names := make([]string, 0, ki.ValueCount) - buf := make([]uint16, ki.MaxValueNameLen+1) // extra room for terminating null character -loopItems: - for i := uint32(0); ; i++ { - if n > 0 { - if len(names) == n { - return names, nil - } - } - l := uint32(len(buf)) - for { - err := regEnumValue(syscall.Handle(k), i, &buf[0], &l, nil, nil, nil, nil) - if err == nil { - break - } - if err == syscall.ERROR_MORE_DATA { - // Double buffer size and try again. - l = uint32(2 * len(buf)) - buf = make([]uint16, l) - continue - } - if err == _ERROR_NO_MORE_ITEMS { - break loopItems - } - return names, err - } - names = append(names, syscall.UTF16ToString(buf[:l])) - } - if n > len(names) { - return names, io.EOF - } - return names, nil -} diff --git a/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go deleted file mode 100644 index bc1ce436..00000000 --- a/vendor/golang.org/x/sys/windows/registry/zsyscall_windows.go +++ /dev/null @@ -1,117 +0,0 @@ -// Code generated by 'go generate'; DO NOT EDIT. - -package registry - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) - errERROR_EINVAL error = syscall.EINVAL -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return errERROR_EINVAL - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) - return e -} - -var ( - modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - - procRegConnectRegistryW = modadvapi32.NewProc("RegConnectRegistryW") - procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW") - procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW") - procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW") - procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW") - procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW") - procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW") - procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW") -) - -func regConnectRegistry(machinename *uint16, key syscall.Handle, result *syscall.Handle) (regerrno error) { - r0, _, _ := syscall.SyscallN(procRegConnectRegistryW.Addr(), uintptr(unsafe.Pointer(machinename)), uintptr(key), uintptr(unsafe.Pointer(result))) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) { - r0, _, _ := syscall.SyscallN(procRegCreateKeyExW.Addr(), uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(reserved), uintptr(unsafe.Pointer(class)), uintptr(options), uintptr(desired), uintptr(unsafe.Pointer(sa)), uintptr(unsafe.Pointer(result)), uintptr(unsafe.Pointer(disposition))) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) { - r0, _, _ := syscall.SyscallN(procRegDeleteKeyW.Addr(), uintptr(key), uintptr(unsafe.Pointer(subkey))) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) { - r0, _, _ := syscall.SyscallN(procRegDeleteValueW.Addr(), uintptr(key), uintptr(unsafe.Pointer(name))) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { - r0, _, _ := syscall.SyscallN(procRegEnumValueW.Addr(), uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) { - r0, _, _ := syscall.SyscallN(procRegLoadMUIStringW.Addr(), uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir))) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) { - r0, _, _ := syscall.SyscallN(procRegSetValueExW.Addr(), uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize)) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.SyscallN(procExpandEnvironmentStringsW.Addr(), uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size)) - n = uint32(r0) - if n == 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/install.go b/vendor/golang.org/x/sys/windows/svc/eventlog/install.go deleted file mode 100644 index 1179c38b..00000000 --- a/vendor/golang.org/x/sys/windows/svc/eventlog/install.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows - -package eventlog - -import ( - "errors" - - "golang.org/x/sys/windows" - "golang.org/x/sys/windows/registry" -) - -const ( - // Log levels. - Info = windows.EVENTLOG_INFORMATION_TYPE - Warning = windows.EVENTLOG_WARNING_TYPE - Error = windows.EVENTLOG_ERROR_TYPE -) - -const addKeyName = `SYSTEM\CurrentControlSet\Services\EventLog\Application` - -// Install modifies PC registry to allow logging with an event source src. -// It adds all required keys and values to the event log registry key. -// Install uses msgFile as the event message file. If useExpandKey is true, -// the event message file is installed as REG_EXPAND_SZ value, -// otherwise as REG_SZ. Use bitwise of log.Error, log.Warning and -// log.Info to specify events supported by the new event source. -func Install(src, msgFile string, useExpandKey bool, eventsSupported uint32) error { - appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.CREATE_SUB_KEY) - if err != nil { - return err - } - defer appkey.Close() - - sk, alreadyExist, err := registry.CreateKey(appkey, src, registry.SET_VALUE) - if err != nil { - return err - } - defer sk.Close() - if alreadyExist { - return errors.New(addKeyName + `\` + src + " registry key already exists") - } - - err = sk.SetDWordValue("CustomSource", 1) - if err != nil { - return err - } - if useExpandKey { - err = sk.SetExpandStringValue("EventMessageFile", msgFile) - } else { - err = sk.SetStringValue("EventMessageFile", msgFile) - } - if err != nil { - return err - } - err = sk.SetDWordValue("TypesSupported", eventsSupported) - if err != nil { - return err - } - return nil -} - -// InstallAsEventCreate is the same as Install, but uses -// %SystemRoot%\System32\EventCreate.exe as the event message file. -func InstallAsEventCreate(src string, eventsSupported uint32) error { - return Install(src, "%SystemRoot%\\System32\\EventCreate.exe", true, eventsSupported) -} - -// Remove deletes all registry elements installed by the correspondent Install. -func Remove(src string) error { - appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.SET_VALUE) - if err != nil { - return err - } - defer appkey.Close() - return registry.DeleteKey(appkey, src) -} diff --git a/vendor/golang.org/x/sys/windows/svc/eventlog/log.go b/vendor/golang.org/x/sys/windows/svc/eventlog/log.go deleted file mode 100644 index ad40c2f4..00000000 --- a/vendor/golang.org/x/sys/windows/svc/eventlog/log.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows - -// Package eventlog implements access to Windows event log. -package eventlog - -import ( - "errors" - "syscall" - - "golang.org/x/sys/windows" -) - -// Log provides access to the system log. -type Log struct { - Handle windows.Handle -} - -// Open retrieves a handle to the specified event log. -func Open(source string) (*Log, error) { - return OpenRemote("", source) -} - -// OpenRemote does the same as Open, but on different computer host. -func OpenRemote(host, source string) (*Log, error) { - if source == "" { - return nil, errors.New("Specify event log source") - } - var hostPointer *uint16 - if host != "" { - var err error - hostPointer, err = syscall.UTF16PtrFromString(host) - if err != nil { - return nil, err - } - } - sourcePointer, err := syscall.UTF16PtrFromString(source) - if err != nil { - return nil, err - } - h, err := windows.RegisterEventSource(hostPointer, sourcePointer) - if err != nil { - return nil, err - } - return &Log{Handle: h}, nil -} - -// Close closes event log l. -func (l *Log) Close() error { - return windows.DeregisterEventSource(l.Handle) -} - -func (l *Log) report(etype uint16, eid uint32, msg string) error { - msgPointer, err := syscall.UTF16PtrFromString(msg) - if err != nil { - return err - } - ss := []*uint16{msgPointer} - return windows.ReportEvent(l.Handle, etype, 0, eid, 0, 1, 0, &ss[0], nil) -} - -// Info writes an information event msg with event id eid to the end of event log l. -// When EventCreate.exe is used, eid must be between 1 and 1000. -func (l *Log) Info(eid uint32, msg string) error { - return l.report(windows.EVENTLOG_INFORMATION_TYPE, eid, msg) -} - -// Warning writes an warning event msg with event id eid to the end of event log l. -// When EventCreate.exe is used, eid must be between 1 and 1000. -func (l *Log) Warning(eid uint32, msg string) error { - return l.report(windows.EVENTLOG_WARNING_TYPE, eid, msg) -} - -// Error writes an error event msg with event id eid to the end of event log l. -// When EventCreate.exe is used, eid must be between 1 and 1000. -func (l *Log) Error(eid uint32, msg string) error { - return l.report(windows.EVENTLOG_ERROR_TYPE, eid, msg) -} diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/config.go b/vendor/golang.org/x/sys/windows/svc/mgr/config.go deleted file mode 100644 index ec01f96e..00000000 --- a/vendor/golang.org/x/sys/windows/svc/mgr/config.go +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows - -package mgr - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -const ( - // Service start types. - StartManual = windows.SERVICE_DEMAND_START // the service must be started manually - StartAutomatic = windows.SERVICE_AUTO_START // the service will start by itself whenever the computer reboots - StartDisabled = windows.SERVICE_DISABLED // the service cannot be started - - // The severity of the error, and action taken, - // if this service fails to start. - ErrorCritical = windows.SERVICE_ERROR_CRITICAL - ErrorIgnore = windows.SERVICE_ERROR_IGNORE - ErrorNormal = windows.SERVICE_ERROR_NORMAL - ErrorSevere = windows.SERVICE_ERROR_SEVERE -) - -// TODO(brainman): Password is not returned by windows.QueryServiceConfig, not sure how to get it. - -type Config struct { - ServiceType uint32 - StartType uint32 - ErrorControl uint32 - BinaryPathName string // fully qualified path to the service binary file, can also include arguments for an auto-start service - LoadOrderGroup string - TagId uint32 - Dependencies []string - ServiceStartName string // name of the account under which the service should run - DisplayName string - Password string - Description string - SidType uint32 // one of SERVICE_SID_TYPE, the type of sid to use for the service - DelayedAutoStart bool // the service is started after other auto-start services are started plus a short delay -} - -func toStringSlice(ps *uint16) []string { - r := make([]string, 0) - p := unsafe.Pointer(ps) - - for { - s := windows.UTF16PtrToString((*uint16)(p)) - if len(s) == 0 { - break - } - - r = append(r, s) - offset := unsafe.Sizeof(uint16(0)) * (uintptr)(len(s)+1) - p = unsafe.Pointer(uintptr(p) + offset) - } - - return r -} - -// Config retrieves service s configuration parameters. -func (s *Service) Config() (Config, error) { - var p *windows.QUERY_SERVICE_CONFIG - n := uint32(1024) - for { - b := make([]byte, n) - p = (*windows.QUERY_SERVICE_CONFIG)(unsafe.Pointer(&b[0])) - err := windows.QueryServiceConfig(s.Handle, p, n, &n) - if err == nil { - break - } - if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { - return Config{}, err - } - if n <= uint32(len(b)) { - return Config{}, err - } - } - - b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_DESCRIPTION) - if err != nil { - return Config{}, err - } - p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0])) - - b, err = s.queryServiceConfig2(windows.SERVICE_CONFIG_DELAYED_AUTO_START_INFO) - if err != nil { - return Config{}, err - } - p3 := (*windows.SERVICE_DELAYED_AUTO_START_INFO)(unsafe.Pointer(&b[0])) - delayedStart := false - if p3.IsDelayedAutoStartUp != 0 { - delayedStart = true - } - - b, err = s.queryServiceConfig2(windows.SERVICE_CONFIG_SERVICE_SID_INFO) - if err != nil { - return Config{}, err - } - sidType := *(*uint32)(unsafe.Pointer(&b[0])) - - return Config{ - ServiceType: p.ServiceType, - StartType: p.StartType, - ErrorControl: p.ErrorControl, - BinaryPathName: windows.UTF16PtrToString(p.BinaryPathName), - LoadOrderGroup: windows.UTF16PtrToString(p.LoadOrderGroup), - TagId: p.TagId, - Dependencies: toStringSlice(p.Dependencies), - ServiceStartName: windows.UTF16PtrToString(p.ServiceStartName), - DisplayName: windows.UTF16PtrToString(p.DisplayName), - Description: windows.UTF16PtrToString(p2.Description), - DelayedAutoStart: delayedStart, - SidType: sidType, - }, nil -} - -func updateDescription(handle windows.Handle, desc string) error { - descPointer, err := toPtr(desc) - if err != nil { - return err - } - d := windows.SERVICE_DESCRIPTION{Description: descPointer} - return windows.ChangeServiceConfig2(handle, - windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d))) -} - -func updateSidType(handle windows.Handle, sidType uint32) error { - return windows.ChangeServiceConfig2(handle, windows.SERVICE_CONFIG_SERVICE_SID_INFO, (*byte)(unsafe.Pointer(&sidType))) -} - -func updateStartUp(handle windows.Handle, isDelayed bool) error { - var d windows.SERVICE_DELAYED_AUTO_START_INFO - if isDelayed { - d.IsDelayedAutoStartUp = 1 - } - return windows.ChangeServiceConfig2(handle, - windows.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, (*byte)(unsafe.Pointer(&d))) -} - -// UpdateConfig updates service s configuration parameters. -func (s *Service) UpdateConfig(c Config) error { - binaryPathNamePointer, err := toPtr(c.BinaryPathName) - if err != nil { - return err - } - loadOrderGroupPointer, err := toPtr(c.LoadOrderGroup) - if err != nil { - return err - } - serviceStartNamePointer, err := toPtr(c.ServiceStartName) - if err != nil { - return err - } - passwordPointer, err := toPtr(c.Password) - if err != nil { - return err - } - displayNamePointer, err := toPtr(c.DisplayName) - if err != nil { - return err - } - err = windows.ChangeServiceConfig(s.Handle, c.ServiceType, c.StartType, - c.ErrorControl, binaryPathNamePointer, loadOrderGroupPointer, - nil, toStringBlock(c.Dependencies), serviceStartNamePointer, - passwordPointer, displayNamePointer) - if err != nil { - return err - } - err = updateSidType(s.Handle, c.SidType) - if err != nil { - return err - } - - err = updateStartUp(s.Handle, c.DelayedAutoStart) - if err != nil { - return err - } - - return updateDescription(s.Handle, c.Description) -} - -// queryServiceConfig2 calls Windows QueryServiceConfig2 with infoLevel parameter and returns retrieved service configuration information. -func (s *Service) queryServiceConfig2(infoLevel uint32) ([]byte, error) { - n := uint32(1024) - for { - b := make([]byte, n) - err := windows.QueryServiceConfig2(s.Handle, infoLevel, &b[0], n, &n) - if err == nil { - return b, nil - } - if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { - return nil, err - } - if n <= uint32(len(b)) { - return nil, err - } - } -} diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go b/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go deleted file mode 100644 index 74755940..00000000 --- a/vendor/golang.org/x/sys/windows/svc/mgr/mgr.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows - -// Package mgr can be used to manage Windows service programs. -// It can be used to install and remove them. It can also start, -// stop and pause them. The package can query / change current -// service state and config parameters. -package mgr - -import ( - "syscall" - "time" - "unicode/utf16" - "unsafe" - - "golang.org/x/sys/windows" -) - -// Mgr is used to manage Windows service. -type Mgr struct { - Handle windows.Handle -} - -// Connect establishes a connection to the service control manager. -func Connect() (*Mgr, error) { - return ConnectRemote("") -} - -// ConnectRemote establishes a connection to the -// service control manager on computer named host. -func ConnectRemote(host string) (*Mgr, error) { - var s *uint16 - if host != "" { - var err error - s, err = syscall.UTF16PtrFromString(host) - if err != nil { - return nil, err - } - } - h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS) - if err != nil { - return nil, err - } - return &Mgr{Handle: h}, nil -} - -// Disconnect closes connection to the service control manager m. -func (m *Mgr) Disconnect() error { - return windows.CloseServiceHandle(m.Handle) -} - -type LockStatus struct { - IsLocked bool // Whether the SCM has been locked. - Age time.Duration // For how long the SCM has been locked. - Owner string // The name of the user who has locked the SCM. -} - -// LockStatus returns whether the service control manager is locked by -// the system, for how long, and by whom. A locked SCM indicates that -// most service actions will block until the system unlocks the SCM. -func (m *Mgr) LockStatus() (*LockStatus, error) { - bytesNeeded := uint32(unsafe.Sizeof(windows.QUERY_SERVICE_LOCK_STATUS{}) + 1024) - for { - bytes := make([]byte, bytesNeeded) - lockStatus := (*windows.QUERY_SERVICE_LOCK_STATUS)(unsafe.Pointer(&bytes[0])) - err := windows.QueryServiceLockStatus(m.Handle, lockStatus, uint32(len(bytes)), &bytesNeeded) - if err == windows.ERROR_INSUFFICIENT_BUFFER && bytesNeeded >= uint32(unsafe.Sizeof(windows.QUERY_SERVICE_LOCK_STATUS{})) { - continue - } - if err != nil { - return nil, err - } - status := &LockStatus{ - IsLocked: lockStatus.IsLocked != 0, - Age: time.Duration(lockStatus.LockDuration) * time.Second, - Owner: windows.UTF16PtrToString(lockStatus.LockOwner), - } - return status, nil - } -} - -func toPtr(s string) (*uint16, error) { - if len(s) == 0 { - return nil, nil - } - return syscall.UTF16PtrFromString(s) -} - -// toStringBlock terminates strings in ss with 0, and then -// concatenates them together. It also adds extra 0 at the end. -func toStringBlock(ss []string) *uint16 { - if len(ss) == 0 { - return nil - } - t := "" - for _, s := range ss { - if s != "" { - t += s + "\x00" - } - } - if t == "" { - return nil - } - t += "\x00" - return &utf16.Encode([]rune(t))[0] -} - -// CreateService installs new service name on the system. -// The service will be executed by running exepath binary. -// Use config c to specify service parameters. -// Any args will be passed as command-line arguments when -// the service is started; these arguments are distinct from -// the arguments passed to Service.Start or via the "Start -// parameters" field in the service's Properties dialog box. -func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Service, error) { - if c.StartType == 0 { - c.StartType = StartManual - } - if c.ServiceType == 0 { - c.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS - } - s := syscall.EscapeArg(exepath) - for _, v := range args { - s += " " + syscall.EscapeArg(v) - } - namePointer, err := toPtr(name) - if err != nil { - return nil, err - } - displayNamePointer, err := toPtr(c.DisplayName) - if err != nil { - return nil, err - } - sPointer, err := toPtr(s) - if err != nil { - return nil, err - } - loadOrderGroupPointer, err := toPtr(c.LoadOrderGroup) - if err != nil { - return nil, err - } - serviceStartNamePointer, err := toPtr(c.ServiceStartName) - if err != nil { - return nil, err - } - passwordPointer, err := toPtr(c.Password) - if err != nil { - return nil, err - } - h, err := windows.CreateService(m.Handle, namePointer, displayNamePointer, - windows.SERVICE_ALL_ACCESS, c.ServiceType, - c.StartType, c.ErrorControl, sPointer, loadOrderGroupPointer, - nil, toStringBlock(c.Dependencies), serviceStartNamePointer, passwordPointer) - if err != nil { - return nil, err - } - if c.SidType != windows.SERVICE_SID_TYPE_NONE { - err = updateSidType(h, c.SidType) - if err != nil { - windows.DeleteService(h) - windows.CloseServiceHandle(h) - return nil, err - } - } - if c.Description != "" { - err = updateDescription(h, c.Description) - if err != nil { - windows.DeleteService(h) - windows.CloseServiceHandle(h) - return nil, err - } - } - if c.DelayedAutoStart { - err = updateStartUp(h, c.DelayedAutoStart) - if err != nil { - windows.DeleteService(h) - windows.CloseServiceHandle(h) - return nil, err - } - } - return &Service{Name: name, Handle: h}, nil -} - -// OpenService retrieves access to service name, so it can -// be interrogated and controlled. -func (m *Mgr) OpenService(name string) (*Service, error) { - namePointer, err := syscall.UTF16PtrFromString(name) - if err != nil { - return nil, err - } - - h, err := windows.OpenService(m.Handle, namePointer, windows.SERVICE_ALL_ACCESS) - if err != nil { - return nil, err - } - return &Service{Name: name, Handle: h}, nil -} - -// ListServices enumerates services in the specified -// service control manager database m. -// If the caller does not have the SERVICE_QUERY_STATUS -// access right to a service, the service is silently -// omitted from the list of services returned. -func (m *Mgr) ListServices() ([]string, error) { - var err error - var bytesNeeded, servicesReturned uint32 - var buf []byte - for { - var p *byte - if len(buf) > 0 { - p = &buf[0] - } - err = windows.EnumServicesStatusEx(m.Handle, windows.SC_ENUM_PROCESS_INFO, - windows.SERVICE_WIN32, windows.SERVICE_STATE_ALL, - p, uint32(len(buf)), &bytesNeeded, &servicesReturned, nil, nil) - if err == nil { - break - } - if err != syscall.ERROR_MORE_DATA { - return nil, err - } - if bytesNeeded <= uint32(len(buf)) { - return nil, err - } - buf = make([]byte, bytesNeeded) - } - if servicesReturned == 0 { - return nil, nil - } - services := unsafe.Slice((*windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0])), int(servicesReturned)) - - var names []string - for _, s := range services { - name := windows.UTF16PtrToString(s.ServiceName) - names = append(names, name) - } - return names, nil -} diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go b/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go deleted file mode 100644 index 1a073748..00000000 --- a/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go +++ /dev/null @@ -1,172 +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 windows - -package mgr - -import ( - "errors" - "syscall" - "time" - "unsafe" - - "golang.org/x/sys/windows" -) - -const ( - // Possible recovery actions that the service control manager can perform. - NoAction = windows.SC_ACTION_NONE // no action - ComputerReboot = windows.SC_ACTION_REBOOT // reboot the computer - ServiceRestart = windows.SC_ACTION_RESTART // restart the service - RunCommand = windows.SC_ACTION_RUN_COMMAND // run a command -) - -// RecoveryAction represents an action that the service control manager can perform when service fails. -// A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller. -type RecoveryAction struct { - Type int // one of NoAction, ComputerReboot, ServiceRestart or RunCommand - Delay time.Duration // the time to wait before performing the specified action -} - -// SetRecoveryActions sets actions that service controller performs when service fails and -// the time after which to reset the service failure count to zero if there are no failures, in seconds. -// Specify INFINITE to indicate that service failure count should never be reset. -func (s *Service) SetRecoveryActions(recoveryActions []RecoveryAction, resetPeriod uint32) error { - if recoveryActions == nil { - return errors.New("recoveryActions cannot be nil") - } - actions := []windows.SC_ACTION{} - for _, a := range recoveryActions { - action := windows.SC_ACTION{ - Type: uint32(a.Type), - Delay: uint32(a.Delay.Nanoseconds() / 1000000), - } - actions = append(actions, action) - } - rActions := windows.SERVICE_FAILURE_ACTIONS{ - ActionsCount: uint32(len(actions)), - Actions: &actions[0], - ResetPeriod: resetPeriod, - } - return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) -} - -// RecoveryActions returns actions that service controller performs when service fails. -// The service control manager counts the number of times service s has failed since the system booted. -// The count is reset to 0 if the service has not failed for ResetPeriod seconds. -// When the service fails for the Nth time, the service controller performs the action specified in element [N-1] of returned slice. -// If N is greater than slice length, the service controller repeats the last action in the slice. -func (s *Service) RecoveryActions() ([]RecoveryAction, error) { - b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS) - if err != nil { - return nil, err - } - p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) - if p.Actions == nil { - return nil, err - } - - actions := unsafe.Slice(p.Actions, int(p.ActionsCount)) - var recoveryActions []RecoveryAction - for _, action := range actions { - recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond}) - } - return recoveryActions, nil -} - -// ResetRecoveryActions deletes both reset period and array of failure actions. -func (s *Service) ResetRecoveryActions() error { - actions := make([]windows.SC_ACTION, 1) - rActions := windows.SERVICE_FAILURE_ACTIONS{ - Actions: &actions[0], - } - return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) -} - -// ResetPeriod is the time after which to reset the service failure -// count to zero if there are no failures, in seconds. -func (s *Service) ResetPeriod() (uint32, error) { - b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS) - if err != nil { - return 0, err - } - p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) - return p.ResetPeriod, nil -} - -// SetRebootMessage sets service s reboot message. -// If msg is "", the reboot message is deleted and no message is broadcast. -func (s *Service) SetRebootMessage(msg string) error { - msgPointer, err := syscall.UTF16PtrFromString(msg) - if err != nil { - return err - } - - rActions := windows.SERVICE_FAILURE_ACTIONS{ - RebootMsg: msgPointer, - } - return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) -} - -// RebootMessage is broadcast to server users before rebooting in response to the ComputerReboot service controller action. -func (s *Service) RebootMessage() (string, error) { - b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS) - if err != nil { - return "", err - } - p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) - return windows.UTF16PtrToString(p.RebootMsg), nil -} - -// SetRecoveryCommand sets the command line of the process to execute in response to the RunCommand service controller action. -// If cmd is "", the command is deleted and no program is run when the service fails. -func (s *Service) SetRecoveryCommand(cmd string) error { - cmdPointer, err := syscall.UTF16PtrFromString(cmd) - if err != nil { - return err - } - - rActions := windows.SERVICE_FAILURE_ACTIONS{ - Command: cmdPointer, - } - return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) -} - -// RecoveryCommand is the command line of the process to execute in response to the RunCommand service controller action. This process runs under the same account as the service. -func (s *Service) RecoveryCommand() (string, error) { - b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS) - if err != nil { - return "", err - } - p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) - return windows.UTF16PtrToString(p.Command), nil -} - -// SetRecoveryActionsOnNonCrashFailures sets the failure actions flag. If the -// flag is set to false, recovery actions will only be performed if the service -// terminates without reporting a status of SERVICE_STOPPED. If the flag is set -// to true, recovery actions are also performed if the service stops with a -// nonzero exit code. -func (s *Service) SetRecoveryActionsOnNonCrashFailures(flag bool) error { - var setting windows.SERVICE_FAILURE_ACTIONS_FLAG - if flag { - setting.FailureActionsOnNonCrashFailures = 1 - } - return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, (*byte)(unsafe.Pointer(&setting))) -} - -// RecoveryActionsOnNonCrashFailures returns the current value of the failure -// actions flag. If the flag is set to false, recovery actions will only be -// performed if the service terminates without reporting a status of -// SERVICE_STOPPED. If the flag is set to true, recovery actions are also -// performed if the service stops with a nonzero exit code. -func (s *Service) RecoveryActionsOnNonCrashFailures() (bool, error) { - b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) - if err != nil { - return false, err - } - p := (*windows.SERVICE_FAILURE_ACTIONS_FLAG)(unsafe.Pointer(&b[0])) - return p.FailureActionsOnNonCrashFailures != 0, nil -} diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/service.go b/vendor/golang.org/x/sys/windows/svc/mgr/service.go deleted file mode 100644 index 9f59eab7..00000000 --- a/vendor/golang.org/x/sys/windows/svc/mgr/service.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows - -package mgr - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" - "golang.org/x/sys/windows/svc" -) - -// Service is used to access Windows service. -type Service struct { - Name string - Handle windows.Handle -} - -// Delete marks service s for deletion from the service control manager database. -func (s *Service) Delete() error { - return windows.DeleteService(s.Handle) -} - -// Close relinquish access to the service s. -func (s *Service) Close() error { - return windows.CloseServiceHandle(s.Handle) -} - -// Start starts service s. -// args will be passed to svc.Handler.Execute. -func (s *Service) Start(args ...string) error { - var p **uint16 - if len(args) > 0 { - vs := make([]*uint16, len(args)) - for i := range vs { - argPointer, err := syscall.UTF16PtrFromString(args[i]) - if err != nil { - return err - } - vs[i] = argPointer - } - p = &vs[0] - } - return windows.StartService(s.Handle, uint32(len(args)), p) -} - -// Control sends state change request c to the service s. It returns the most -// recent status the service reported to the service control manager, and an -// error if the state change request was not accepted. -// Note that the returned service status is only set if the status change -// request succeeded, or if it failed with error ERROR_INVALID_SERVICE_CONTROL, -// ERROR_SERVICE_CANNOT_ACCEPT_CTRL, or ERROR_SERVICE_NOT_ACTIVE. -func (s *Service) Control(c svc.Cmd) (svc.Status, error) { - var t windows.SERVICE_STATUS - err := windows.ControlService(s.Handle, uint32(c), &t) - if err != nil && - err != windows.ERROR_INVALID_SERVICE_CONTROL && - err != windows.ERROR_SERVICE_CANNOT_ACCEPT_CTRL && - err != windows.ERROR_SERVICE_NOT_ACTIVE { - return svc.Status{}, err - } - return svc.Status{ - State: svc.State(t.CurrentState), - Accepts: svc.Accepted(t.ControlsAccepted), - }, err -} - -// Query returns current status of service s. -func (s *Service) Query() (svc.Status, error) { - var t windows.SERVICE_STATUS_PROCESS - var needed uint32 - err := windows.QueryServiceStatusEx(s.Handle, windows.SC_STATUS_PROCESS_INFO, (*byte)(unsafe.Pointer(&t)), uint32(unsafe.Sizeof(t)), &needed) - if err != nil { - return svc.Status{}, err - } - return svc.Status{ - State: svc.State(t.CurrentState), - Accepts: svc.Accepted(t.ControlsAccepted), - ProcessId: t.ProcessId, - Win32ExitCode: t.Win32ExitCode, - ServiceSpecificExitCode: t.ServiceSpecificExitCode, - }, nil -} - -// ListDependentServices returns the names of the services dependent on service s, which match the given status. -func (s *Service) ListDependentServices(status svc.ActivityStatus) ([]string, error) { - var bytesNeeded, returnedServiceCount uint32 - var services []windows.ENUM_SERVICE_STATUS - for { - var servicesPtr *windows.ENUM_SERVICE_STATUS - if len(services) > 0 { - servicesPtr = &services[0] - } - allocatedBytes := uint32(len(services)) * uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{})) - err := windows.EnumDependentServices(s.Handle, uint32(status), servicesPtr, allocatedBytes, &bytesNeeded, - &returnedServiceCount) - if err == nil { - break - } - if err != syscall.ERROR_MORE_DATA { - return nil, err - } - if bytesNeeded <= allocatedBytes { - return nil, err - } - // ERROR_MORE_DATA indicates the provided buffer was too small, run the call again after resizing the buffer - requiredSliceLen := bytesNeeded / uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{})) - if bytesNeeded%uint32(unsafe.Sizeof(windows.ENUM_SERVICE_STATUS{})) != 0 { - requiredSliceLen += 1 - } - services = make([]windows.ENUM_SERVICE_STATUS, requiredSliceLen) - } - if returnedServiceCount == 0 { - return nil, nil - } - - // The slice mutated by EnumDependentServices may have a length greater than returnedServiceCount, any elements - // past that should be ignored. - var dependents []string - for i := 0; i < int(returnedServiceCount); i++ { - dependents = append(dependents, windows.UTF16PtrToString(services[i].ServiceName)) - } - return dependents, nil -} diff --git a/vendor/golang.org/x/sys/windows/svc/security.go b/vendor/golang.org/x/sys/windows/svc/security.go deleted file mode 100644 index 6a1f3c62..00000000 --- a/vendor/golang.org/x/sys/windows/svc/security.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows - -package svc - -import ( - "strings" - "unsafe" - - "golang.org/x/sys/windows" -) - -func allocSid(subAuth0 uint32) (*windows.SID, error) { - var sid *windows.SID - err := windows.AllocateAndInitializeSid(&windows.SECURITY_NT_AUTHORITY, - 1, subAuth0, 0, 0, 0, 0, 0, 0, 0, &sid) - if err != nil { - return nil, err - } - return sid, nil -} - -// IsAnInteractiveSession determines if calling process is running interactively. -// It queries the process token for membership in the Interactive group. -// http://stackoverflow.com/questions/2668851/how-do-i-detect-that-my-application-is-running-as-service-or-in-an-interactive-s -// -// Deprecated: Use IsWindowsService instead. -func IsAnInteractiveSession() (bool, error) { - interSid, err := allocSid(windows.SECURITY_INTERACTIVE_RID) - if err != nil { - return false, err - } - defer windows.FreeSid(interSid) - - serviceSid, err := allocSid(windows.SECURITY_SERVICE_RID) - if err != nil { - return false, err - } - defer windows.FreeSid(serviceSid) - - t, err := windows.OpenCurrentProcessToken() - if err != nil { - return false, err - } - defer t.Close() - - gs, err := t.GetTokenGroups() - if err != nil { - return false, err - } - - for _, g := range gs.AllGroups() { - if windows.EqualSid(g.Sid, interSid) { - return true, nil - } - if windows.EqualSid(g.Sid, serviceSid) { - return false, nil - } - } - return false, nil -} - -// IsWindowsService reports whether the process is currently executing -// as a Windows service. -func IsWindowsService() (bool, error) { - // The below technique looks a bit hairy, but it's actually - // exactly what the .NET framework does for the similarly named function: - // https://github.com/dotnet/extensions/blob/f4066026ca06984b07e90e61a6390ac38152ba93/src/Hosting/WindowsServices/src/WindowsServiceHelpers.cs#L26-L31 - // Specifically, it looks up whether the parent process has session ID zero - // and is called "services". - - var currentProcess windows.PROCESS_BASIC_INFORMATION - infoSize := uint32(unsafe.Sizeof(currentProcess)) - err := windows.NtQueryInformationProcess(windows.CurrentProcess(), windows.ProcessBasicInformation, unsafe.Pointer(¤tProcess), infoSize, &infoSize) - if err != nil { - return false, err - } - var parentProcess *windows.SYSTEM_PROCESS_INFORMATION - for infoSize = uint32((unsafe.Sizeof(*parentProcess) + unsafe.Sizeof(uintptr(0))) * 1024); ; { - parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Pointer(&make([]byte, infoSize)[0])) - err = windows.NtQuerySystemInformation(windows.SystemProcessInformation, unsafe.Pointer(parentProcess), infoSize, &infoSize) - if err == nil { - break - } else if err != windows.STATUS_INFO_LENGTH_MISMATCH { - return false, err - } - } - for ; ; parentProcess = (*windows.SYSTEM_PROCESS_INFORMATION)(unsafe.Pointer(uintptr(unsafe.Pointer(parentProcess)) + uintptr(parentProcess.NextEntryOffset))) { - if parentProcess.UniqueProcessID == currentProcess.InheritedFromUniqueProcessId { - return parentProcess.SessionID == 0 && strings.EqualFold("services.exe", parentProcess.ImageName.String()), nil - } - if parentProcess.NextEntryOffset == 0 { - break - } - } - return false, nil -} diff --git a/vendor/golang.org/x/sys/windows/svc/service.go b/vendor/golang.org/x/sys/windows/svc/service.go deleted file mode 100644 index a9b1c192..00000000 --- a/vendor/golang.org/x/sys/windows/svc/service.go +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows - -// Package svc provides everything required to build Windows service. -package svc - -import ( - "errors" - "sync" - "unsafe" - - "golang.org/x/sys/windows" -) - -// State describes service execution state (Stopped, Running and so on). -type State uint32 - -const ( - Stopped = State(windows.SERVICE_STOPPED) - StartPending = State(windows.SERVICE_START_PENDING) - StopPending = State(windows.SERVICE_STOP_PENDING) - Running = State(windows.SERVICE_RUNNING) - ContinuePending = State(windows.SERVICE_CONTINUE_PENDING) - PausePending = State(windows.SERVICE_PAUSE_PENDING) - Paused = State(windows.SERVICE_PAUSED) -) - -// Cmd represents service state change request. It is sent to a service -// by the service manager, and should be actioned upon by the service. -type Cmd uint32 - -const ( - Stop = Cmd(windows.SERVICE_CONTROL_STOP) - Pause = Cmd(windows.SERVICE_CONTROL_PAUSE) - Continue = Cmd(windows.SERVICE_CONTROL_CONTINUE) - Interrogate = Cmd(windows.SERVICE_CONTROL_INTERROGATE) - Shutdown = Cmd(windows.SERVICE_CONTROL_SHUTDOWN) - ParamChange = Cmd(windows.SERVICE_CONTROL_PARAMCHANGE) - NetBindAdd = Cmd(windows.SERVICE_CONTROL_NETBINDADD) - NetBindRemove = Cmd(windows.SERVICE_CONTROL_NETBINDREMOVE) - NetBindEnable = Cmd(windows.SERVICE_CONTROL_NETBINDENABLE) - NetBindDisable = Cmd(windows.SERVICE_CONTROL_NETBINDDISABLE) - DeviceEvent = Cmd(windows.SERVICE_CONTROL_DEVICEEVENT) - HardwareProfileChange = Cmd(windows.SERVICE_CONTROL_HARDWAREPROFILECHANGE) - PowerEvent = Cmd(windows.SERVICE_CONTROL_POWEREVENT) - SessionChange = Cmd(windows.SERVICE_CONTROL_SESSIONCHANGE) - PreShutdown = Cmd(windows.SERVICE_CONTROL_PRESHUTDOWN) -) - -// Accepted is used to describe commands accepted by the service. -// Note that Interrogate is always accepted. -type Accepted uint32 - -const ( - AcceptStop = Accepted(windows.SERVICE_ACCEPT_STOP) - AcceptShutdown = Accepted(windows.SERVICE_ACCEPT_SHUTDOWN) - AcceptPauseAndContinue = Accepted(windows.SERVICE_ACCEPT_PAUSE_CONTINUE) - AcceptParamChange = Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE) - AcceptNetBindChange = Accepted(windows.SERVICE_ACCEPT_NETBINDCHANGE) - AcceptHardwareProfileChange = Accepted(windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE) - AcceptPowerEvent = Accepted(windows.SERVICE_ACCEPT_POWEREVENT) - AcceptSessionChange = Accepted(windows.SERVICE_ACCEPT_SESSIONCHANGE) - AcceptPreShutdown = Accepted(windows.SERVICE_ACCEPT_PRESHUTDOWN) -) - -// ActivityStatus allows for services to be selected based on active and inactive categories of service state. -type ActivityStatus uint32 - -const ( - Active = ActivityStatus(windows.SERVICE_ACTIVE) - Inactive = ActivityStatus(windows.SERVICE_INACTIVE) - AnyActivity = ActivityStatus(windows.SERVICE_STATE_ALL) -) - -// Status combines State and Accepted commands to fully describe running service. -type Status struct { - State State - Accepts Accepted - CheckPoint uint32 // used to report progress during a lengthy operation - WaitHint uint32 // estimated time required for a pending operation, in milliseconds - ProcessId uint32 // if the service is running, the process identifier of it, and otherwise zero - Win32ExitCode uint32 // set if the service has exited with a win32 exit code - ServiceSpecificExitCode uint32 // set if the service has exited with a service-specific exit code -} - -// StartReason is the reason that the service was started. -type StartReason uint32 - -const ( - StartReasonDemand = StartReason(windows.SERVICE_START_REASON_DEMAND) - StartReasonAuto = StartReason(windows.SERVICE_START_REASON_AUTO) - StartReasonTrigger = StartReason(windows.SERVICE_START_REASON_TRIGGER) - StartReasonRestartOnFailure = StartReason(windows.SERVICE_START_REASON_RESTART_ON_FAILURE) - StartReasonDelayedAuto = StartReason(windows.SERVICE_START_REASON_DELAYEDAUTO) -) - -// ChangeRequest is sent to the service Handler to request service status change. -type ChangeRequest struct { - Cmd Cmd - EventType uint32 - EventData uintptr - CurrentStatus Status - Context uintptr -} - -// Handler is the interface that must be implemented to build Windows service. -type Handler interface { - // Execute will be called by the package code at the start of - // the service, and the service will exit once Execute completes. - // Inside Execute you must read service change requests from r and - // act accordingly. You must keep service control manager up to date - // about state of your service by writing into s as required. - // args contains service name followed by argument strings passed - // to the service. - // You can provide service exit code in exitCode return parameter, - // with 0 being "no error". You can also indicate if exit code, - // if any, is service specific or not by using svcSpecificEC - // parameter. - Execute(args []string, r <-chan ChangeRequest, s chan<- Status) (svcSpecificEC bool, exitCode uint32) -} - -type ctlEvent struct { - cmd Cmd - eventType uint32 - eventData uintptr - context uintptr - errno uint32 -} - -// service provides access to windows service api. -type service struct { - namePointer *uint16 - h windows.Handle - c chan ctlEvent - handler Handler -} - -type exitCode struct { - isSvcSpecific bool - errno uint32 -} - -func (s *service) updateStatus(status *Status, ec *exitCode) error { - if s.h == 0 { - return errors.New("updateStatus with no service status handle") - } - var t windows.SERVICE_STATUS - t.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS - t.CurrentState = uint32(status.State) - if status.Accepts&AcceptStop != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_STOP - } - if status.Accepts&AcceptShutdown != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_SHUTDOWN - } - if status.Accepts&AcceptPauseAndContinue != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_PAUSE_CONTINUE - } - if status.Accepts&AcceptParamChange != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_PARAMCHANGE - } - if status.Accepts&AcceptNetBindChange != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_NETBINDCHANGE - } - if status.Accepts&AcceptHardwareProfileChange != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE - } - if status.Accepts&AcceptPowerEvent != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_POWEREVENT - } - if status.Accepts&AcceptSessionChange != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_SESSIONCHANGE - } - if status.Accepts&AcceptPreShutdown != 0 { - t.ControlsAccepted |= windows.SERVICE_ACCEPT_PRESHUTDOWN - } - if ec.errno == 0 { - t.Win32ExitCode = windows.NO_ERROR - t.ServiceSpecificExitCode = windows.NO_ERROR - } else if ec.isSvcSpecific { - t.Win32ExitCode = uint32(windows.ERROR_SERVICE_SPECIFIC_ERROR) - t.ServiceSpecificExitCode = ec.errno - } else { - t.Win32ExitCode = ec.errno - t.ServiceSpecificExitCode = windows.NO_ERROR - } - t.CheckPoint = status.CheckPoint - t.WaitHint = status.WaitHint - return windows.SetServiceStatus(s.h, &t) -} - -var ( - initCallbacks sync.Once - ctlHandlerCallback uintptr - serviceMainCallback uintptr -) - -func ctlHandler(ctl, evtype, evdata, context uintptr) uintptr { - e := ctlEvent{cmd: Cmd(ctl), eventType: uint32(evtype), eventData: evdata, context: 123456} // Set context to 123456 to test issue #25660. - theService.c <- e - return 0 -} - -var theService service // This is, unfortunately, a global, which means only one service per process. - -// serviceMain is the entry point called by the service manager, registered earlier by -// the call to StartServiceCtrlDispatcher. -func serviceMain(argc uint32, argv **uint16) uintptr { - handle, err := windows.RegisterServiceCtrlHandlerEx(theService.namePointer, ctlHandlerCallback, 0) - if sysErr, ok := err.(windows.Errno); ok { - return uintptr(sysErr) - } else if err != nil { - return uintptr(windows.ERROR_UNKNOWN_EXCEPTION) - } - theService.h = handle - defer func() { - theService.h = 0 - }() - args16 := unsafe.Slice(argv, int(argc)) - - args := make([]string, len(args16)) - for i, a := range args16 { - args[i] = windows.UTF16PtrToString(a) - } - - cmdsToHandler := make(chan ChangeRequest) - changesFromHandler := make(chan Status) - exitFromHandler := make(chan exitCode) - - go func() { - ss, errno := theService.handler.Execute(args, cmdsToHandler, changesFromHandler) - exitFromHandler <- exitCode{ss, errno} - }() - - ec := exitCode{isSvcSpecific: true, errno: 0} - outcr := ChangeRequest{ - CurrentStatus: Status{State: Stopped}, - } - var outch chan ChangeRequest - inch := theService.c -loop: - for { - select { - case r := <-inch: - if r.errno != 0 { - ec.errno = r.errno - break loop - } - inch = nil - outch = cmdsToHandler - outcr.Cmd = r.cmd - outcr.EventType = r.eventType - outcr.EventData = r.eventData - outcr.Context = r.context - case outch <- outcr: - inch = theService.c - outch = nil - case c := <-changesFromHandler: - err := theService.updateStatus(&c, &ec) - if err != nil { - ec.errno = uint32(windows.ERROR_EXCEPTION_IN_SERVICE) - if err2, ok := err.(windows.Errno); ok { - ec.errno = uint32(err2) - } - break loop - } - outcr.CurrentStatus = c - case ec = <-exitFromHandler: - break loop - } - } - - theService.updateStatus(&Status{State: Stopped}, &ec) - - return windows.NO_ERROR -} - -// Run executes service name by calling appropriate handler function. -func Run(name string, handler Handler) error { - // Check to make sure that the service name is valid. - namePointer, err := windows.UTF16PtrFromString(name) - if err != nil { - return err - } - - initCallbacks.Do(func() { - ctlHandlerCallback = windows.NewCallback(ctlHandler) - serviceMainCallback = windows.NewCallback(serviceMain) - }) - theService.namePointer = namePointer - theService.handler = handler - theService.c = make(chan ctlEvent) - t := []windows.SERVICE_TABLE_ENTRY{ - {ServiceName: namePointer, ServiceProc: serviceMainCallback}, - {ServiceName: nil, ServiceProc: 0}, - } - return windows.StartServiceCtrlDispatcher(&t[0]) -} - -// StatusHandle returns service status handle. It is safe to call this function -// from inside the Handler.Execute because then it is guaranteed to be set. -func StatusHandle() windows.Handle { - return theService.h -} - -// DynamicStartReason returns the reason why the service was started. It is safe -// to call this function from inside the Handler.Execute because then it is -// guaranteed to be set. -func DynamicStartReason() (StartReason, error) { - var allocReason *uint32 - err := windows.QueryServiceDynamicInformation(theService.h, windows.SERVICE_DYNAMIC_INFORMATION_LEVEL_START_REASON, unsafe.Pointer(&allocReason)) - if err != nil { - return 0, err - } - reason := StartReason(*allocReason) - windows.LocalFree(windows.Handle(unsafe.Pointer(allocReason))) - return reason, nil -} diff --git a/vendor/golang.org/x/text/cases/cases.go b/vendor/golang.org/x/text/cases/cases.go deleted file mode 100644 index 752cdf03..00000000 --- a/vendor/golang.org/x/text/cases/cases.go +++ /dev/null @@ -1,162 +0,0 @@ -// 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. - -//go:generate go run gen.go gen_trieval.go - -// Package cases provides general and language-specific case mappers. -package cases // import "golang.org/x/text/cases" - -import ( - "golang.org/x/text/language" - "golang.org/x/text/transform" -) - -// References: -// - Unicode Reference Manual Chapter 3.13, 4.2, and 5.18. -// - https://www.unicode.org/reports/tr29/ -// - https://www.unicode.org/Public/6.3.0/ucd/CaseFolding.txt -// - https://www.unicode.org/Public/6.3.0/ucd/SpecialCasing.txt -// - https://www.unicode.org/Public/6.3.0/ucd/DerivedCoreProperties.txt -// - https://www.unicode.org/Public/6.3.0/ucd/auxiliary/WordBreakProperty.txt -// - https://www.unicode.org/Public/6.3.0/ucd/auxiliary/WordBreakTest.txt -// - http://userguide.icu-project.org/transforms/casemappings - -// TODO: -// - Case folding -// - Wide and Narrow? -// - Segmenter option for title casing. -// - ASCII fast paths -// - Encode Soft-Dotted property within trie somehow. - -// A Caser transforms given input to a certain case. It implements -// transform.Transformer. -// -// A Caser may be stateful and should therefore not be shared between -// goroutines. -type Caser struct { - t transform.SpanningTransformer -} - -// Bytes returns a new byte slice with the result of converting b to the case -// form implemented by c. -func (c Caser) Bytes(b []byte) []byte { - b, _, _ = transform.Bytes(c.t, b) - return b -} - -// String returns a string with the result of transforming s to the case form -// implemented by c. -func (c Caser) String(s string) string { - s, _, _ = transform.String(c.t, s) - return s -} - -// Reset resets the Caser to be reused for new input after a previous call to -// Transform. -func (c Caser) Reset() { c.t.Reset() } - -// Transform implements the transform.Transformer interface and transforms the -// given input to the case form implemented by c. -func (c Caser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - return c.t.Transform(dst, src, atEOF) -} - -// Span implements the transform.SpanningTransformer interface. -func (c Caser) Span(src []byte, atEOF bool) (n int, err error) { - return c.t.Span(src, atEOF) -} - -// Upper returns a Caser for language-specific uppercasing. -func Upper(t language.Tag, opts ...Option) Caser { - return Caser{makeUpper(t, getOpts(opts...))} -} - -// Lower returns a Caser for language-specific lowercasing. -func Lower(t language.Tag, opts ...Option) Caser { - return Caser{makeLower(t, getOpts(opts...))} -} - -// Title returns a Caser for language-specific title casing. It uses an -// approximation of the default Unicode Word Break algorithm. -func Title(t language.Tag, opts ...Option) Caser { - return Caser{makeTitle(t, getOpts(opts...))} -} - -// Fold returns a Caser that implements Unicode case folding. The returned Caser -// is stateless and safe to use concurrently by multiple goroutines. -// -// Case folding does not normalize the input and may not preserve a normal form. -// Use the collate or search package for more convenient and linguistically -// sound comparisons. Use golang.org/x/text/secure/precis for string comparisons -// where security aspects are a concern. -func Fold(opts ...Option) Caser { - return Caser{makeFold(getOpts(opts...))} -} - -// An Option is used to modify the behavior of a Caser. -type Option func(o options) options - -// TODO: consider these options to take a boolean as well, like FinalSigma. -// The advantage of using this approach is that other providers of a lower-case -// algorithm could set different defaults by prefixing a user-provided slice -// of options with their own. This is handy, for instance, for the precis -// package which would override the default to not handle the Greek final sigma. - -var ( - // NoLower disables the lowercasing of non-leading letters for a title - // caser. - NoLower Option = noLower - - // Compact omits mappings in case folding for characters that would grow the - // input. (Unimplemented.) - Compact Option = compact -) - -// TODO: option to preserve a normal form, if applicable? - -type options struct { - noLower bool - simple bool - - // TODO: segmenter, max ignorable, alternative versions, etc. - - ignoreFinalSigma bool -} - -func getOpts(o ...Option) (res options) { - for _, f := range o { - res = f(res) - } - return -} - -func noLower(o options) options { - o.noLower = true - return o -} - -func compact(o options) options { - o.simple = true - return o -} - -// HandleFinalSigma specifies whether the special handling of Greek final sigma -// should be enabled. Unicode prescribes handling the Greek final sigma for all -// locales, but standards like IDNA and PRECIS override this default. -func HandleFinalSigma(enable bool) Option { - if enable { - return handleFinalSigma - } - return ignoreFinalSigma -} - -func ignoreFinalSigma(o options) options { - o.ignoreFinalSigma = true - return o -} - -func handleFinalSigma(o options) options { - o.ignoreFinalSigma = false - return o -} diff --git a/vendor/golang.org/x/text/cases/context.go b/vendor/golang.org/x/text/cases/context.go deleted file mode 100644 index e9aa9e19..00000000 --- a/vendor/golang.org/x/text/cases/context.go +++ /dev/null @@ -1,376 +0,0 @@ -// 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 cases - -import "golang.org/x/text/transform" - -// A context is used for iterating over source bytes, fetching case info and -// writing to a destination buffer. -// -// Casing operations may need more than one rune of context to decide how a rune -// should be cased. Casing implementations should call checkpoint on context -// whenever it is known to be safe to return the runes processed so far. -// -// It is recommended for implementations to not allow for more than 30 case -// ignorables as lookahead (analogous to the limit in norm) and to use state if -// unbounded lookahead is needed for cased runes. -type context struct { - dst, src []byte - atEOF bool - - pDst int // pDst points past the last written rune in dst. - pSrc int // pSrc points to the start of the currently scanned rune. - - // checkpoints safe to return in Transform, where nDst <= pDst and nSrc <= pSrc. - nDst, nSrc int - err error - - sz int // size of current rune - info info // case information of currently scanned rune - - // State preserved across calls to Transform. - isMidWord bool // false if next cased letter needs to be title-cased. -} - -func (c *context) Reset() { - c.isMidWord = false -} - -// ret returns the return values for the Transform method. It checks whether -// there were insufficient bytes in src to complete and introduces an error -// accordingly, if necessary. -func (c *context) ret() (nDst, nSrc int, err error) { - if c.err != nil || c.nSrc == len(c.src) { - return c.nDst, c.nSrc, c.err - } - // This point is only reached by mappers if there was no short destination - // buffer. This means that the source buffer was exhausted and that c.sz was - // set to 0 by next. - if c.atEOF && c.pSrc == len(c.src) { - return c.pDst, c.pSrc, nil - } - return c.nDst, c.nSrc, transform.ErrShortSrc -} - -// retSpan returns the return values for the Span method. It checks whether -// there were insufficient bytes in src to complete and introduces an error -// accordingly, if necessary. -func (c *context) retSpan() (n int, err error) { - _, nSrc, err := c.ret() - return nSrc, err -} - -// checkpoint sets the return value buffer points for Transform to the current -// positions. -func (c *context) checkpoint() { - if c.err == nil { - c.nDst, c.nSrc = c.pDst, c.pSrc+c.sz - } -} - -// unreadRune causes the last rune read by next to be reread on the next -// invocation of next. Only one unreadRune may be called after a call to next. -func (c *context) unreadRune() { - c.sz = 0 -} - -func (c *context) next() bool { - c.pSrc += c.sz - if c.pSrc == len(c.src) || c.err != nil { - c.info, c.sz = 0, 0 - return false - } - v, sz := trie.lookup(c.src[c.pSrc:]) - c.info, c.sz = info(v), sz - if c.sz == 0 { - if c.atEOF { - // A zero size means we have an incomplete rune. If we are atEOF, - // this means it is an illegal rune, which we will consume one - // byte at a time. - c.sz = 1 - } else { - c.err = transform.ErrShortSrc - return false - } - } - return true -} - -// writeBytes adds bytes to dst. -func (c *context) writeBytes(b []byte) bool { - if len(c.dst)-c.pDst < len(b) { - c.err = transform.ErrShortDst - return false - } - // This loop is faster than using copy. - for _, ch := range b { - c.dst[c.pDst] = ch - c.pDst++ - } - return true -} - -// writeString writes the given string to dst. -func (c *context) writeString(s string) bool { - if len(c.dst)-c.pDst < len(s) { - c.err = transform.ErrShortDst - return false - } - // This loop is faster than using copy. - for i := 0; i < len(s); i++ { - c.dst[c.pDst] = s[i] - c.pDst++ - } - return true -} - -// copy writes the current rune to dst. -func (c *context) copy() bool { - return c.writeBytes(c.src[c.pSrc : c.pSrc+c.sz]) -} - -// copyXOR copies the current rune to dst and modifies it by applying the XOR -// pattern of the case info. It is the responsibility of the caller to ensure -// that this is a rune with a XOR pattern defined. -func (c *context) copyXOR() bool { - if !c.copy() { - return false - } - if c.info&xorIndexBit == 0 { - // Fast path for 6-bit XOR pattern, which covers most cases. - c.dst[c.pDst-1] ^= byte(c.info >> xorShift) - } else { - // Interpret XOR bits as an index. - // TODO: test performance for unrolling this loop. Verify that we have - // at least two bytes and at most three. - idx := c.info >> xorShift - for p := c.pDst - 1; ; p-- { - c.dst[p] ^= xorData[idx] - idx-- - if xorData[idx] == 0 { - break - } - } - } - return true -} - -// hasPrefix returns true if src[pSrc:] starts with the given string. -func (c *context) hasPrefix(s string) bool { - b := c.src[c.pSrc:] - if len(b) < len(s) { - return false - } - for i, c := range b[:len(s)] { - if c != s[i] { - return false - } - } - return true -} - -// caseType returns an info with only the case bits, normalized to either -// cLower, cUpper, cTitle or cUncased. -func (c *context) caseType() info { - cm := c.info & 0x7 - if cm < 4 { - return cm - } - if cm >= cXORCase { - // xor the last bit of the rune with the case type bits. - b := c.src[c.pSrc+c.sz-1] - return info(b&1) ^ cm&0x3 - } - if cm == cIgnorableCased { - return cLower - } - return cUncased -} - -// lower writes the lowercase version of the current rune to dst. -func lower(c *context) bool { - ct := c.caseType() - if c.info&hasMappingMask == 0 || ct == cLower { - return c.copy() - } - if c.info&exceptionBit == 0 { - return c.copyXOR() - } - e := exceptions[c.info>>exceptionShift:] - offset := 2 + e[0]&lengthMask // size of header + fold string - if nLower := (e[1] >> lengthBits) & lengthMask; nLower != noChange { - return c.writeString(e[offset : offset+nLower]) - } - return c.copy() -} - -func isLower(c *context) bool { - ct := c.caseType() - if c.info&hasMappingMask == 0 || ct == cLower { - return true - } - if c.info&exceptionBit == 0 { - c.err = transform.ErrEndOfSpan - return false - } - e := exceptions[c.info>>exceptionShift:] - if nLower := (e[1] >> lengthBits) & lengthMask; nLower != noChange { - c.err = transform.ErrEndOfSpan - return false - } - return true -} - -// upper writes the uppercase version of the current rune to dst. -func upper(c *context) bool { - ct := c.caseType() - if c.info&hasMappingMask == 0 || ct == cUpper { - return c.copy() - } - if c.info&exceptionBit == 0 { - return c.copyXOR() - } - e := exceptions[c.info>>exceptionShift:] - offset := 2 + e[0]&lengthMask // size of header + fold string - // Get length of first special case mapping. - n := (e[1] >> lengthBits) & lengthMask - if ct == cTitle { - // The first special case mapping is for lower. Set n to the second. - if n == noChange { - n = 0 - } - n, e = e[1]&lengthMask, e[n:] - } - if n != noChange { - return c.writeString(e[offset : offset+n]) - } - return c.copy() -} - -// isUpper writes the isUppercase version of the current rune to dst. -func isUpper(c *context) bool { - ct := c.caseType() - if c.info&hasMappingMask == 0 || ct == cUpper { - return true - } - if c.info&exceptionBit == 0 { - c.err = transform.ErrEndOfSpan - return false - } - e := exceptions[c.info>>exceptionShift:] - // Get length of first special case mapping. - n := (e[1] >> lengthBits) & lengthMask - if ct == cTitle { - n = e[1] & lengthMask - } - if n != noChange { - c.err = transform.ErrEndOfSpan - return false - } - return true -} - -// title writes the title case version of the current rune to dst. -func title(c *context) bool { - ct := c.caseType() - if c.info&hasMappingMask == 0 || ct == cTitle { - return c.copy() - } - if c.info&exceptionBit == 0 { - if ct == cLower { - return c.copyXOR() - } - return c.copy() - } - // Get the exception data. - e := exceptions[c.info>>exceptionShift:] - offset := 2 + e[0]&lengthMask // size of header + fold string - - nFirst := (e[1] >> lengthBits) & lengthMask - if nTitle := e[1] & lengthMask; nTitle != noChange { - if nFirst != noChange { - e = e[nFirst:] - } - return c.writeString(e[offset : offset+nTitle]) - } - if ct == cLower && nFirst != noChange { - // Use the uppercase version instead. - return c.writeString(e[offset : offset+nFirst]) - } - // Already in correct case. - return c.copy() -} - -// isTitle reports whether the current rune is in title case. -func isTitle(c *context) bool { - ct := c.caseType() - if c.info&hasMappingMask == 0 || ct == cTitle { - return true - } - if c.info&exceptionBit == 0 { - if ct == cLower { - c.err = transform.ErrEndOfSpan - return false - } - return true - } - // Get the exception data. - e := exceptions[c.info>>exceptionShift:] - if nTitle := e[1] & lengthMask; nTitle != noChange { - c.err = transform.ErrEndOfSpan - return false - } - nFirst := (e[1] >> lengthBits) & lengthMask - if ct == cLower && nFirst != noChange { - c.err = transform.ErrEndOfSpan - return false - } - return true -} - -// foldFull writes the foldFull version of the current rune to dst. -func foldFull(c *context) bool { - if c.info&hasMappingMask == 0 { - return c.copy() - } - ct := c.caseType() - if c.info&exceptionBit == 0 { - if ct != cLower || c.info&inverseFoldBit != 0 { - return c.copyXOR() - } - return c.copy() - } - e := exceptions[c.info>>exceptionShift:] - n := e[0] & lengthMask - if n == 0 { - if ct == cLower { - return c.copy() - } - n = (e[1] >> lengthBits) & lengthMask - } - return c.writeString(e[2 : 2+n]) -} - -// isFoldFull reports whether the current run is mapped to foldFull -func isFoldFull(c *context) bool { - if c.info&hasMappingMask == 0 { - return true - } - ct := c.caseType() - if c.info&exceptionBit == 0 { - if ct != cLower || c.info&inverseFoldBit != 0 { - c.err = transform.ErrEndOfSpan - return false - } - return true - } - e := exceptions[c.info>>exceptionShift:] - n := e[0] & lengthMask - if n == 0 && ct == cLower { - return true - } - c.err = transform.ErrEndOfSpan - return false -} diff --git a/vendor/golang.org/x/text/cases/fold.go b/vendor/golang.org/x/text/cases/fold.go deleted file mode 100644 index 85cc434f..00000000 --- a/vendor/golang.org/x/text/cases/fold.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package cases - -import "golang.org/x/text/transform" - -type caseFolder struct{ transform.NopResetter } - -// caseFolder implements the Transformer interface for doing case folding. -func (t *caseFolder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - c := context{dst: dst, src: src, atEOF: atEOF} - for c.next() { - foldFull(&c) - c.checkpoint() - } - return c.ret() -} - -func (t *caseFolder) Span(src []byte, atEOF bool) (n int, err error) { - c := context{src: src, atEOF: atEOF} - for c.next() && isFoldFull(&c) { - c.checkpoint() - } - return c.retSpan() -} - -func makeFold(o options) transform.SpanningTransformer { - // TODO: Special case folding, through option Language, Special/Turkic, or - // both. - // TODO: Implement Compact options. - return &caseFolder{} -} diff --git a/vendor/golang.org/x/text/cases/icu.go b/vendor/golang.org/x/text/cases/icu.go deleted file mode 100644 index db7c237c..00000000 --- a/vendor/golang.org/x/text/cases/icu.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build icu - -package cases - -// Ideally these functions would be defined in a test file, but go test doesn't -// allow CGO in tests. The build tag should ensure either way that these -// functions will not end up in the package. - -// TODO: Ensure that the correct ICU version is set. - -/* -#cgo LDFLAGS: -licui18n.57 -licuuc.57 -#include <stdlib.h> -#include <unicode/ustring.h> -#include <unicode/utypes.h> -#include <unicode/localpointer.h> -#include <unicode/ucasemap.h> -*/ -import "C" - -import "unsafe" - -func doICU(tag, caser, input string) string { - err := C.UErrorCode(0) - loc := C.CString(tag) - cm := C.ucasemap_open(loc, C.uint32_t(0), &err) - - buf := make([]byte, len(input)*4) - dst := (*C.char)(unsafe.Pointer(&buf[0])) - src := C.CString(input) - - cn := C.int32_t(0) - - switch caser { - case "fold": - cn = C.ucasemap_utf8FoldCase(cm, - dst, C.int32_t(len(buf)), - src, C.int32_t(len(input)), - &err) - case "lower": - cn = C.ucasemap_utf8ToLower(cm, - dst, C.int32_t(len(buf)), - src, C.int32_t(len(input)), - &err) - case "upper": - cn = C.ucasemap_utf8ToUpper(cm, - dst, C.int32_t(len(buf)), - src, C.int32_t(len(input)), - &err) - case "title": - cn = C.ucasemap_utf8ToTitle(cm, - dst, C.int32_t(len(buf)), - src, C.int32_t(len(input)), - &err) - } - return string(buf[:cn]) -} diff --git a/vendor/golang.org/x/text/cases/info.go b/vendor/golang.org/x/text/cases/info.go deleted file mode 100644 index 87a7c3e9..00000000 --- a/vendor/golang.org/x/text/cases/info.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 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 cases - -func (c info) cccVal() info { - if c&exceptionBit != 0 { - return info(exceptions[c>>exceptionShift]) & cccMask - } - return c & cccMask -} - -func (c info) cccType() info { - ccc := c.cccVal() - if ccc <= cccZero { - return cccZero - } - return ccc -} - -// TODO: Implement full Unicode breaking algorithm: -// 1) Implement breaking in separate package. -// 2) Use the breaker here. -// 3) Compare table size and performance of using the more generic breaker. -// -// Note that we can extend the current algorithm to be much more accurate. This -// only makes sense, though, if the performance and/or space penalty of using -// the generic breaker is big. Extra data will only be needed for non-cased -// runes, which means there are sufficient bits left in the caseType. -// ICU prohibits breaking in such cases as well. - -// For the purpose of title casing we use an approximation of the Unicode Word -// Breaking algorithm defined in Annex #29: -// https://www.unicode.org/reports/tr29/#Default_Grapheme_Cluster_Table. -// -// For our approximation, we group the Word Break types into the following -// categories, with associated rules: -// -// 1) Letter: -// ALetter, Hebrew_Letter, Numeric, ExtendNumLet, Extend, Format_FE, ZWJ. -// Rule: Never break between consecutive runes of this category. -// -// 2) Mid: -// MidLetter, MidNumLet, Single_Quote. -// (Cf. case-ignorable: MidLetter, MidNumLet, Single_Quote or cat is Mn, -// Me, Cf, Lm or Sk). -// Rule: Don't break between Letter and Mid, but break between two Mids. -// -// 3) Break: -// Any other category: NewLine, MidNum, CR, LF, Double_Quote, Katakana, and -// Other. -// These categories should always result in a break between two cased letters. -// Rule: Always break. -// -// Note 1: the Katakana and MidNum categories can, in esoteric cases, result in -// preventing a break between two cased letters. For now we will ignore this -// (e.g. [ALetter] [ExtendNumLet] [Katakana] [ExtendNumLet] [ALetter] and -// [ALetter] [Numeric] [MidNum] [Numeric] [ALetter].) -// -// Note 2: the rule for Mid is very approximate, but works in most cases. To -// improve, we could store the categories in the trie value and use a FA to -// manage breaks. See TODO comment above. -// -// Note 3: according to the spec, it is possible for the Extend category to -// introduce breaks between other categories grouped in Letter. However, this -// is undesirable for our purposes. ICU prevents breaks in such cases as well. - -// isBreak returns whether this rune should introduce a break. -func (c info) isBreak() bool { - return c.cccVal() == cccBreak -} - -// isLetter returns whether the rune is of break type ALetter, Hebrew_Letter, -// Numeric, ExtendNumLet, or Extend. -func (c info) isLetter() bool { - ccc := c.cccVal() - if ccc == cccZero { - return !c.isCaseIgnorable() - } - return ccc != cccBreak -} diff --git a/vendor/golang.org/x/text/cases/map.go b/vendor/golang.org/x/text/cases/map.go deleted file mode 100644 index 0f7c6a14..00000000 --- a/vendor/golang.org/x/text/cases/map.go +++ /dev/null @@ -1,816 +0,0 @@ -// 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 cases - -// This file contains the definitions of case mappings for all supported -// languages. The rules for the language-specific tailorings were taken and -// modified from the CLDR transform definitions in common/transforms. - -import ( - "strings" - "unicode" - "unicode/utf8" - - "golang.org/x/text/internal" - "golang.org/x/text/language" - "golang.org/x/text/transform" - "golang.org/x/text/unicode/norm" -) - -// A mapFunc takes a context set to the current rune and writes the mapped -// version to the same context. It may advance the context to the next rune. It -// returns whether a checkpoint is possible: whether the pDst bytes written to -// dst so far won't need changing as we see more source bytes. -type mapFunc func(*context) bool - -// A spanFunc takes a context set to the current rune and returns whether this -// rune would be altered when written to the output. It may advance the context -// to the next rune. It returns whether a checkpoint is possible. -type spanFunc func(*context) bool - -// maxIgnorable defines the maximum number of ignorables to consider for -// lookahead operations. -const maxIgnorable = 30 - -// supported lists the language tags for which we have tailorings. -const supported = "und af az el lt nl tr" - -func init() { - tags := []language.Tag{} - for _, s := range strings.Split(supported, " ") { - tags = append(tags, language.MustParse(s)) - } - matcher = internal.NewInheritanceMatcher(tags) - Supported = language.NewCoverage(tags) -} - -var ( - matcher *internal.InheritanceMatcher - - Supported language.Coverage - - // We keep the following lists separate, instead of having a single per- - // language struct, to give the compiler a chance to remove unused code. - - // Some uppercase mappers are stateless, so we can precompute the - // Transformers and save a bit on runtime allocations. - upperFunc = []struct { - upper mapFunc - span spanFunc - }{ - {nil, nil}, // und - {nil, nil}, // af - {aztrUpper(upper), isUpper}, // az - {elUpper, noSpan}, // el - {ltUpper(upper), noSpan}, // lt - {nil, nil}, // nl - {aztrUpper(upper), isUpper}, // tr - } - - undUpper transform.SpanningTransformer = &undUpperCaser{} - undLower transform.SpanningTransformer = &undLowerCaser{} - undLowerIgnoreSigma transform.SpanningTransformer = &undLowerIgnoreSigmaCaser{} - - lowerFunc = []mapFunc{ - nil, // und - nil, // af - aztrLower, // az - nil, // el - ltLower, // lt - nil, // nl - aztrLower, // tr - } - - titleInfos = []struct { - title mapFunc - lower mapFunc - titleSpan spanFunc - rewrite func(*context) - }{ - {title, lower, isTitle, nil}, // und - {title, lower, isTitle, afnlRewrite}, // af - {aztrUpper(title), aztrLower, isTitle, nil}, // az - {title, lower, isTitle, nil}, // el - {ltUpper(title), ltLower, noSpan, nil}, // lt - {nlTitle, lower, nlTitleSpan, afnlRewrite}, // nl - {aztrUpper(title), aztrLower, isTitle, nil}, // tr - } -) - -func makeUpper(t language.Tag, o options) transform.SpanningTransformer { - _, i, _ := matcher.Match(t) - f := upperFunc[i].upper - if f == nil { - return undUpper - } - return &simpleCaser{f: f, span: upperFunc[i].span} -} - -func makeLower(t language.Tag, o options) transform.SpanningTransformer { - _, i, _ := matcher.Match(t) - f := lowerFunc[i] - if f == nil { - if o.ignoreFinalSigma { - return undLowerIgnoreSigma - } - return undLower - } - if o.ignoreFinalSigma { - return &simpleCaser{f: f, span: isLower} - } - return &lowerCaser{ - first: f, - midWord: finalSigma(f), - } -} - -func makeTitle(t language.Tag, o options) transform.SpanningTransformer { - _, i, _ := matcher.Match(t) - x := &titleInfos[i] - lower := x.lower - if o.noLower { - lower = (*context).copy - } else if !o.ignoreFinalSigma { - lower = finalSigma(lower) - } - return &titleCaser{ - title: x.title, - lower: lower, - titleSpan: x.titleSpan, - rewrite: x.rewrite, - } -} - -func noSpan(c *context) bool { - c.err = transform.ErrEndOfSpan - return false -} - -// TODO: consider a similar special case for the fast majority lower case. This -// is a bit more involved so will require some more precise benchmarking to -// justify it. - -type undUpperCaser struct{ transform.NopResetter } - -// undUpperCaser implements the Transformer interface for doing an upper case -// mapping for the root locale (und). It eliminates the need for an allocation -// as it prevents escaping by not using function pointers. -func (t undUpperCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - c := context{dst: dst, src: src, atEOF: atEOF} - for c.next() { - upper(&c) - c.checkpoint() - } - return c.ret() -} - -func (t undUpperCaser) Span(src []byte, atEOF bool) (n int, err error) { - c := context{src: src, atEOF: atEOF} - for c.next() && isUpper(&c) { - c.checkpoint() - } - return c.retSpan() -} - -// undLowerIgnoreSigmaCaser implements the Transformer interface for doing -// a lower case mapping for the root locale (und) ignoring final sigma -// handling. This casing algorithm is used in some performance-critical packages -// like secure/precis and x/net/http/idna, which warrants its special-casing. -type undLowerIgnoreSigmaCaser struct{ transform.NopResetter } - -func (t undLowerIgnoreSigmaCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - c := context{dst: dst, src: src, atEOF: atEOF} - for c.next() && lower(&c) { - c.checkpoint() - } - return c.ret() - -} - -// Span implements a generic lower-casing. This is possible as isLower works -// for all lowercasing variants. All lowercase variants only vary in how they -// transform a non-lowercase letter. They will never change an already lowercase -// letter. In addition, there is no state. -func (t undLowerIgnoreSigmaCaser) Span(src []byte, atEOF bool) (n int, err error) { - c := context{src: src, atEOF: atEOF} - for c.next() && isLower(&c) { - c.checkpoint() - } - return c.retSpan() -} - -type simpleCaser struct { - context - f mapFunc - span spanFunc -} - -// simpleCaser implements the Transformer interface for doing a case operation -// on a rune-by-rune basis. -func (t *simpleCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - c := context{dst: dst, src: src, atEOF: atEOF} - for c.next() && t.f(&c) { - c.checkpoint() - } - return c.ret() -} - -func (t *simpleCaser) Span(src []byte, atEOF bool) (n int, err error) { - c := context{src: src, atEOF: atEOF} - for c.next() && t.span(&c) { - c.checkpoint() - } - return c.retSpan() -} - -// undLowerCaser implements the Transformer interface for doing a lower case -// mapping for the root locale (und) ignoring final sigma handling. This casing -// algorithm is used in some performance-critical packages like secure/precis -// and x/net/http/idna, which warrants its special-casing. -type undLowerCaser struct{ transform.NopResetter } - -func (t undLowerCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - c := context{dst: dst, src: src, atEOF: atEOF} - - for isInterWord := true; c.next(); { - if isInterWord { - if c.info.isCased() { - if !lower(&c) { - break - } - isInterWord = false - } else if !c.copy() { - break - } - } else { - if c.info.isNotCasedAndNotCaseIgnorable() { - if !c.copy() { - break - } - isInterWord = true - } else if !c.hasPrefix("Σ") { - if !lower(&c) { - break - } - } else if !finalSigmaBody(&c) { - break - } - } - c.checkpoint() - } - return c.ret() -} - -func (t undLowerCaser) Span(src []byte, atEOF bool) (n int, err error) { - c := context{src: src, atEOF: atEOF} - for c.next() && isLower(&c) { - c.checkpoint() - } - return c.retSpan() -} - -// lowerCaser implements the Transformer interface. The default Unicode lower -// casing requires different treatment for the first and subsequent characters -// of a word, most notably to handle the Greek final Sigma. -type lowerCaser struct { - undLowerIgnoreSigmaCaser - - context - - first, midWord mapFunc -} - -func (t *lowerCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - t.context = context{dst: dst, src: src, atEOF: atEOF} - c := &t.context - - for isInterWord := true; c.next(); { - if isInterWord { - if c.info.isCased() { - if !t.first(c) { - break - } - isInterWord = false - } else if !c.copy() { - break - } - } else { - if c.info.isNotCasedAndNotCaseIgnorable() { - if !c.copy() { - break - } - isInterWord = true - } else if !t.midWord(c) { - break - } - } - c.checkpoint() - } - return c.ret() -} - -// titleCaser implements the Transformer interface. Title casing algorithms -// distinguish between the first letter of a word and subsequent letters of the -// same word. It uses state to avoid requiring a potentially infinite lookahead. -type titleCaser struct { - context - - // rune mappings used by the actual casing algorithms. - title mapFunc - lower mapFunc - titleSpan spanFunc - - rewrite func(*context) -} - -// Transform implements the standard Unicode title case algorithm as defined in -// Chapter 3 of The Unicode Standard: -// toTitlecase(X): Find the word boundaries in X according to Unicode Standard -// Annex #29, "Unicode Text Segmentation." For each word boundary, find the -// first cased character F following the word boundary. If F exists, map F to -// Titlecase_Mapping(F); then map all characters C between F and the following -// word boundary to Lowercase_Mapping(C). -func (t *titleCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { - t.context = context{dst: dst, src: src, atEOF: atEOF, isMidWord: t.isMidWord} - c := &t.context - - if !c.next() { - return c.ret() - } - - for { - p := c.info - if t.rewrite != nil { - t.rewrite(c) - } - - wasMid := p.isMid() - // Break out of this loop on failure to ensure we do not modify the - // state incorrectly. - if p.isCased() { - if !c.isMidWord { - if !t.title(c) { - break - } - c.isMidWord = true - } else if !t.lower(c) { - break - } - } else if !c.copy() { - break - } else if p.isBreak() { - c.isMidWord = false - } - - // As we save the state of the transformer, it is safe to call - // checkpoint after any successful write. - if !(c.isMidWord && wasMid) { - c.checkpoint() - } - - if !c.next() { - break - } - if wasMid && c.info.isMid() { - c.isMidWord = false - } - } - return c.ret() -} - -func (t *titleCaser) Span(src []byte, atEOF bool) (n int, err error) { - t.context = context{src: src, atEOF: atEOF, isMidWord: t.isMidWord} - c := &t.context - - if !c.next() { - return c.retSpan() - } - - for { - p := c.info - if t.rewrite != nil { - t.rewrite(c) - } - - wasMid := p.isMid() - // Break out of this loop on failure to ensure we do not modify the - // state incorrectly. - if p.isCased() { - if !c.isMidWord { - if !t.titleSpan(c) { - break - } - c.isMidWord = true - } else if !isLower(c) { - break - } - } else if p.isBreak() { - c.isMidWord = false - } - // As we save the state of the transformer, it is safe to call - // checkpoint after any successful write. - if !(c.isMidWord && wasMid) { - c.checkpoint() - } - - if !c.next() { - break - } - if wasMid && c.info.isMid() { - c.isMidWord = false - } - } - return c.retSpan() -} - -// finalSigma adds Greek final Sigma handing to another casing function. It -// determines whether a lowercased sigma should be σ or ς, by looking ahead for -// case-ignorables and a cased letters. -func finalSigma(f mapFunc) mapFunc { - return func(c *context) bool { - if !c.hasPrefix("Σ") { - return f(c) - } - return finalSigmaBody(c) - } -} - -func finalSigmaBody(c *context) bool { - // Current rune must be ∑. - - // ::NFD(); - // # 03A3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK CAPITAL LETTER SIGMA - // Σ } [:case-ignorable:]* [:cased:] → σ; - // [:cased:] [:case-ignorable:]* { Σ → ς; - // ::Any-Lower; - // ::NFC(); - - p := c.pDst - c.writeString("ς") - - // TODO: we should do this here, but right now this will never have an - // effect as this is called when the prefix is Sigma, whereas Dutch and - // Afrikaans only test for an apostrophe. - // - // if t.rewrite != nil { - // t.rewrite(c) - // } - - // We need to do one more iteration after maxIgnorable, as a cased - // letter is not an ignorable and may modify the result. - wasMid := false - for i := 0; i < maxIgnorable+1; i++ { - if !c.next() { - return false - } - if !c.info.isCaseIgnorable() { - // All Midword runes are also case ignorable, so we are - // guaranteed to have a letter or word break here. As we are - // unreading the run, there is no need to unset c.isMidWord; - // the title caser will handle this. - if c.info.isCased() { - // p+1 is guaranteed to be in bounds: if writing ς was - // successful, p+1 will contain the second byte of ς. If not, - // this function will have returned after c.next returned false. - c.dst[p+1]++ // ς → σ - } - c.unreadRune() - return true - } - // A case ignorable may also introduce a word break, so we may need - // to continue searching even after detecting a break. - isMid := c.info.isMid() - if (wasMid && isMid) || c.info.isBreak() { - c.isMidWord = false - } - wasMid = isMid - c.copy() - } - return true -} - -// finalSigmaSpan would be the same as isLower. - -// elUpper implements Greek upper casing, which entails removing a predefined -// set of non-blocked modifiers. Note that these accents should not be removed -// for title casing! -// Example: "Οδός" -> "ΟΔΟΣ". -func elUpper(c *context) bool { - // From CLDR: - // [:Greek:] [^[:ccc=Not_Reordered:][:ccc=Above:]]*? { [\u0313\u0314\u0301\u0300\u0306\u0342\u0308\u0304] → ; - // [:Greek:] [^[:ccc=Not_Reordered:][:ccc=Iota_Subscript:]]*? { \u0345 → ; - - r, _ := utf8.DecodeRune(c.src[c.pSrc:]) - oldPDst := c.pDst - if !upper(c) { - return false - } - if !unicode.Is(unicode.Greek, r) { - return true - } - i := 0 - // Take the properties of the uppercased rune that is already written to the - // destination. This saves us the trouble of having to uppercase the - // decomposed rune again. - if b := norm.NFD.Properties(c.dst[oldPDst:]).Decomposition(); b != nil { - // Restore the destination position and process the decomposed rune. - r, sz := utf8.DecodeRune(b) - if r <= 0xFF { // See A.6.1 - return true - } - c.pDst = oldPDst - // Insert the first rune and ignore the modifiers. See A.6.2. - c.writeBytes(b[:sz]) - i = len(b[sz:]) / 2 // Greek modifiers are always of length 2. - } - - for ; i < maxIgnorable && c.next(); i++ { - switch r, _ := utf8.DecodeRune(c.src[c.pSrc:]); r { - // Above and Iota Subscript - case 0x0300, // U+0300 COMBINING GRAVE ACCENT - 0x0301, // U+0301 COMBINING ACUTE ACCENT - 0x0304, // U+0304 COMBINING MACRON - 0x0306, // U+0306 COMBINING BREVE - 0x0308, // U+0308 COMBINING DIAERESIS - 0x0313, // U+0313 COMBINING COMMA ABOVE - 0x0314, // U+0314 COMBINING REVERSED COMMA ABOVE - 0x0342, // U+0342 COMBINING GREEK PERISPOMENI - 0x0345: // U+0345 COMBINING GREEK YPOGEGRAMMENI - // No-op. Gobble the modifier. - - default: - switch v, _ := trie.lookup(c.src[c.pSrc:]); info(v).cccType() { - case cccZero: - c.unreadRune() - return true - - // We don't need to test for IotaSubscript as the only rune that - // qualifies (U+0345) was already excluded in the switch statement - // above. See A.4. - - case cccAbove: - return c.copy() - default: - // Some other modifier. We're still allowed to gobble Greek - // modifiers after this. - c.copy() - } - } - } - return i == maxIgnorable -} - -// TODO: implement elUpperSpan (low-priority: complex and infrequent). - -func ltLower(c *context) bool { - // From CLDR: - // # Introduce an explicit dot above when lowercasing capital I's and J's - // # whenever there are more accents above. - // # (of the accents used in Lithuanian: grave, acute, tilde above, and ogonek) - // # 0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I - // # 004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J - // # 012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK - // # 00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE - // # 00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE - // # 0128; 0069 0307 0303; 0128; 0128; lt; # LATIN CAPITAL LETTER I WITH TILDE - // ::NFD(); - // I } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → i \u0307; - // J } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → j \u0307; - // I \u0328 (Į) } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → i \u0328 \u0307; - // I \u0300 (Ì) → i \u0307 \u0300; - // I \u0301 (Í) → i \u0307 \u0301; - // I \u0303 (Ĩ) → i \u0307 \u0303; - // ::Any-Lower(); - // ::NFC(); - - i := 0 - if r := c.src[c.pSrc]; r < utf8.RuneSelf { - lower(c) - if r != 'I' && r != 'J' { - return true - } - } else { - p := norm.NFD.Properties(c.src[c.pSrc:]) - if d := p.Decomposition(); len(d) >= 3 && (d[0] == 'I' || d[0] == 'J') { - // UTF-8 optimization: the decomposition will only have an above - // modifier if the last rune of the decomposition is in [U+300-U+311]. - // In all other cases, a decomposition starting with I is always - // an I followed by modifiers that are not cased themselves. See A.2. - if d[1] == 0xCC && d[2] <= 0x91 { // A.2.4. - if !c.writeBytes(d[:1]) { - return false - } - c.dst[c.pDst-1] += 'a' - 'A' // lower - - // Assumption: modifier never changes on lowercase. See A.1. - // Assumption: all modifiers added have CCC = Above. See A.2.3. - return c.writeString("\u0307") && c.writeBytes(d[1:]) - } - // In all other cases the additional modifiers will have a CCC - // that is less than 230 (Above). We will insert the U+0307, if - // needed, after these modifiers so that a string in FCD form - // will remain so. See A.2.2. - lower(c) - i = 1 - } else { - return lower(c) - } - } - - for ; i < maxIgnorable && c.next(); i++ { - switch c.info.cccType() { - case cccZero: - c.unreadRune() - return true - case cccAbove: - return c.writeString("\u0307") && c.copy() // See A.1. - default: - c.copy() // See A.1. - } - } - return i == maxIgnorable -} - -// ltLowerSpan would be the same as isLower. - -func ltUpper(f mapFunc) mapFunc { - return func(c *context) bool { - // Unicode: - // 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE - // - // From CLDR: - // # Remove \u0307 following soft-dotteds (i, j, and the like), with possible - // # intervening non-230 marks. - // ::NFD(); - // [:Soft_Dotted:] [^[:ccc=Not_Reordered:][:ccc=Above:]]* { \u0307 → ; - // ::Any-Upper(); - // ::NFC(); - - // TODO: See A.5. A soft-dotted rune never has an exception. This would - // allow us to overload the exception bit and encode this property in - // info. Need to measure performance impact of this. - r, _ := utf8.DecodeRune(c.src[c.pSrc:]) - oldPDst := c.pDst - if !f(c) { - return false - } - if !unicode.Is(unicode.Soft_Dotted, r) { - return true - } - - // We don't need to do an NFD normalization, as a soft-dotted rune never - // contains U+0307. See A.3. - - i := 0 - for ; i < maxIgnorable && c.next(); i++ { - switch c.info.cccType() { - case cccZero: - c.unreadRune() - return true - case cccAbove: - if c.hasPrefix("\u0307") { - // We don't do a full NFC, but rather combine runes for - // some of the common cases. (Returning NFC or - // preserving normal form is neither a requirement nor - // a possibility anyway). - if !c.next() { - return false - } - if c.dst[oldPDst] == 'I' && c.pDst == oldPDst+1 && c.src[c.pSrc] == 0xcc { - s := "" - switch c.src[c.pSrc+1] { - case 0x80: // U+0300 COMBINING GRAVE ACCENT - s = "\u00cc" // U+00CC LATIN CAPITAL LETTER I WITH GRAVE - case 0x81: // U+0301 COMBINING ACUTE ACCENT - s = "\u00cd" // U+00CD LATIN CAPITAL LETTER I WITH ACUTE - case 0x83: // U+0303 COMBINING TILDE - s = "\u0128" // U+0128 LATIN CAPITAL LETTER I WITH TILDE - case 0x88: // U+0308 COMBINING DIAERESIS - s = "\u00cf" // U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS - default: - } - if s != "" { - c.pDst = oldPDst - return c.writeString(s) - } - } - } - return c.copy() - default: - c.copy() - } - } - return i == maxIgnorable - } -} - -// TODO: implement ltUpperSpan (low priority: complex and infrequent). - -func aztrUpper(f mapFunc) mapFunc { - return func(c *context) bool { - // i→İ; - if c.src[c.pSrc] == 'i' { - return c.writeString("İ") - } - return f(c) - } -} - -func aztrLower(c *context) (done bool) { - // From CLDR: - // # I and i-dotless; I-dot and i are case pairs in Turkish and Azeri - // # 0130; 0069; 0130; 0130; tr; # LATIN CAPITAL LETTER I WITH DOT ABOVE - // İ→i; - // # When lowercasing, remove dot_above in the sequence I + dot_above, which will turn into i. - // # This matches the behavior of the canonically equivalent I-dot_above - // # 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE - // # When lowercasing, unless an I is before a dot_above, it turns into a dotless i. - // # 0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I - // I([^[:ccc=Not_Reordered:][:ccc=Above:]]*)\u0307 → i$1 ; - // I→ı ; - // ::Any-Lower(); - if c.hasPrefix("\u0130") { // İ - return c.writeString("i") - } - if c.src[c.pSrc] != 'I' { - return lower(c) - } - - // We ignore the lower-case I for now, but insert it later when we know - // which form we need. - start := c.pSrc + c.sz - - i := 0 -Loop: - // We check for up to n ignorables before \u0307. As \u0307 is an - // ignorable as well, n is maxIgnorable-1. - for ; i < maxIgnorable && c.next(); i++ { - switch c.info.cccType() { - case cccAbove: - if c.hasPrefix("\u0307") { - return c.writeString("i") && c.writeBytes(c.src[start:c.pSrc]) // ignore U+0307 - } - done = true - break Loop - case cccZero: - c.unreadRune() - done = true - break Loop - default: - // We'll write this rune after we know which starter to use. - } - } - if i == maxIgnorable { - done = true - } - return c.writeString("ı") && c.writeBytes(c.src[start:c.pSrc+c.sz]) && done -} - -// aztrLowerSpan would be the same as isLower. - -func nlTitle(c *context) bool { - // From CLDR: - // # Special titlecasing for Dutch initial "ij". - // ::Any-Title(); - // # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29) - // [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ; - if c.src[c.pSrc] != 'I' && c.src[c.pSrc] != 'i' { - return title(c) - } - - if !c.writeString("I") || !c.next() { - return false - } - if c.src[c.pSrc] == 'j' || c.src[c.pSrc] == 'J' { - return c.writeString("J") - } - c.unreadRune() - return true -} - -func nlTitleSpan(c *context) bool { - // From CLDR: - // # Special titlecasing for Dutch initial "ij". - // ::Any-Title(); - // # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29) - // [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ; - if c.src[c.pSrc] != 'I' { - return isTitle(c) - } - if !c.next() || c.src[c.pSrc] == 'j' { - return false - } - if c.src[c.pSrc] != 'J' { - c.unreadRune() - } - return true -} - -// Not part of CLDR, but see https://unicode.org/cldr/trac/ticket/7078. -func afnlRewrite(c *context) { - if c.hasPrefix("'") || c.hasPrefix("’") { - c.isMidWord = true - } -} diff --git a/vendor/golang.org/x/text/cases/tables10.0.0.go b/vendor/golang.org/x/text/cases/tables10.0.0.go deleted file mode 100644 index bd28ae14..00000000 --- a/vendor/golang.org/x/text/cases/tables10.0.0.go +++ /dev/null @@ -1,2255 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -//go:build go1.10 && !go1.13 - -package cases - -// UnicodeVersion is the Unicode version from which the tables in this package are derived. -const UnicodeVersion = "10.0.0" - -var xorData string = "" + // Size: 185 bytes - "\x00\x06\x07\x00\x01?\x00\x0f\x03\x00\x0f\x12\x00\x0f\x1f\x00\x0f\x1d" + - "\x00\x01\x13\x00\x0f\x16\x00\x0f\x0b\x00\x0f3\x00\x0f7\x00\x01#\x00\x0f?" + - "\x00\x0e'\x00\x0f/\x00\x0e>\x00\x0f*\x00\x0c&\x00\x0c*\x00\x0c;\x00\x0c9" + - "\x00\x0c%\x00\x01\x08\x00\x03\x0d\x00\x03\x09\x00\x02\x06\x00\x02\x02" + - "\x00\x02\x0c\x00\x01\x00\x00\x01\x03\x00\x01\x01\x00\x01 \x00\x01\x0c" + - "\x00\x01\x10\x00\x03\x10\x00\x036 \x00\x037 \x00\x0b#\x10\x00\x0b 0\x00" + - "\x0b!\x10\x00\x0b!0\x00\x0b(\x04\x00\x03\x04\x1e\x00\x03\x0a\x00\x02:" + - "\x00\x02>\x00\x02,\x00\x02\x00\x00\x02\x10\x00\x01<\x00\x01&\x00\x01*" + - "\x00\x01.\x00\x010\x003 \x00\x01\x18\x00\x01(\x00\x01\x1e\x00\x01\x22" - -var exceptions string = "" + // Size: 2068 bytes - "\x00\x12\x12μΜΜ\x12\x12ssSSSs\x13\x18i̇i̇\x10\x09II\x13\x1bʼnʼNʼN\x11" + - "\x09sSS\x12\x12dždžDž\x12\x12dždžDŽ\x10\x12DŽDž\x12\x12ljljLj\x12\x12ljljLJ\x10\x12LJLj" + - "\x12\x12njnjNj\x12\x12njnjNJ\x10\x12NJNj\x13\x1bǰJ̌J̌\x12\x12dzdzDz\x12\x12dzdzDZ\x10" + - "\x12DZDz\x13\x18ⱥⱥ\x13\x18ⱦⱦ\x10\x1bⱾⱾ\x10\x1bⱿⱿ\x10\x1bⱯⱯ\x10\x1bⱭⱭ\x10" + - "\x1bⱰⱰ\x10\x1bꞫꞫ\x10\x1bꞬꞬ\x10\x1bꞍꞍ\x10\x1bꞪꞪ\x10\x1bꞮꞮ\x10\x1bⱢⱢ\x10" + - "\x1bꞭꞭ\x10\x1bⱮⱮ\x10\x1bⱤⱤ\x10\x1bꞱꞱ\x10\x1bꞲꞲ\x10\x1bꞰꞰ2\x12ιΙΙ\x166ΐ" + - "Ϊ́Ϊ́\x166ΰΫ́Ϋ́\x12\x12σΣΣ\x12\x12βΒΒ\x12\x12θΘΘ\x12\x12φΦΦ\x12" + - "\x12πΠΠ\x12\x12κΚΚ\x12\x12ρΡΡ\x12\x12εΕΕ\x14$եւԵՒԵւ\x12\x12вВВ\x12\x12дД" + - "Д\x12\x12оОО\x12\x12сСС\x12\x12тТТ\x12\x12тТТ\x12\x12ъЪЪ\x12\x12ѣѢѢ\x13" + - "\x1bꙋꙊꙊ\x13\x1bẖH̱H̱\x13\x1bẗT̈T̈\x13\x1bẘW̊W̊\x13\x1bẙY̊Y̊\x13\x1ba" + - "ʾAʾAʾ\x13\x1bṡṠṠ\x12\x10ssß\x14$ὐΥ̓Υ̓\x166ὒΥ̓̀Υ̓̀\x166ὔΥ̓́Υ̓́\x166" + - "ὖΥ̓͂Υ̓͂\x15+ἀιἈΙᾈ\x15+ἁιἉΙᾉ\x15+ἂιἊΙᾊ\x15+ἃιἋΙᾋ\x15+ἄιἌΙᾌ\x15+ἅιἍΙᾍ" + - "\x15+ἆιἎΙᾎ\x15+ἇιἏΙᾏ\x15\x1dἀιᾀἈΙ\x15\x1dἁιᾁἉΙ\x15\x1dἂιᾂἊΙ\x15\x1dἃιᾃἋΙ" + - "\x15\x1dἄιᾄἌΙ\x15\x1dἅιᾅἍΙ\x15\x1dἆιᾆἎΙ\x15\x1dἇιᾇἏΙ\x15+ἠιἨΙᾘ\x15+ἡιἩΙᾙ" + - "\x15+ἢιἪΙᾚ\x15+ἣιἫΙᾛ\x15+ἤιἬΙᾜ\x15+ἥιἭΙᾝ\x15+ἦιἮΙᾞ\x15+ἧιἯΙᾟ\x15\x1dἠιᾐἨ" + - "Ι\x15\x1dἡιᾑἩΙ\x15\x1dἢιᾒἪΙ\x15\x1dἣιᾓἫΙ\x15\x1dἤιᾔἬΙ\x15\x1dἥιᾕἭΙ\x15" + - "\x1dἦιᾖἮΙ\x15\x1dἧιᾗἯΙ\x15+ὠιὨΙᾨ\x15+ὡιὩΙᾩ\x15+ὢιὪΙᾪ\x15+ὣιὫΙᾫ\x15+ὤιὬΙᾬ" + - "\x15+ὥιὭΙᾭ\x15+ὦιὮΙᾮ\x15+ὧιὯΙᾯ\x15\x1dὠιᾠὨΙ\x15\x1dὡιᾡὩΙ\x15\x1dὢιᾢὪΙ" + - "\x15\x1dὣιᾣὫΙ\x15\x1dὤιᾤὬΙ\x15\x1dὥιᾥὭΙ\x15\x1dὦιᾦὮΙ\x15\x1dὧιᾧὯΙ\x15-ὰι" + - "ᾺΙᾺͅ\x14#αιΑΙᾼ\x14$άιΆΙΆͅ\x14$ᾶΑ͂Α͂\x166ᾶιΑ͂Ιᾼ͂\x14\x1cαιᾳΑΙ\x12" + - "\x12ιΙΙ\x15-ὴιῊΙῊͅ\x14#ηιΗΙῌ\x14$ήιΉΙΉͅ\x14$ῆΗ͂Η͂\x166ῆιΗ͂Ιῌ͂\x14\x1c" + - "ηιῃΗΙ\x166ῒΪ̀Ϊ̀\x166ΐΪ́Ϊ́\x14$ῖΙ͂Ι͂\x166ῗΪ͂Ϊ͂\x166ῢΫ̀Ϋ" + - "̀\x166ΰΫ́Ϋ́\x14$ῤΡ̓Ρ̓\x14$ῦΥ͂Υ͂\x166ῧΫ͂Ϋ͂\x15-ὼιῺΙῺͅ\x14#ωιΩΙ" + - "ῼ\x14$ώιΏΙΏͅ\x14$ῶΩ͂Ω͂\x166ῶιΩ͂Ιῼ͂\x14\x1cωιῳΩΙ\x12\x10ωω\x11\x08kk" + - "\x12\x10åå\x12\x10ɫɫ\x12\x10ɽɽ\x10\x12ȺȺ\x10\x12ȾȾ\x12\x10ɑɑ\x12\x10ɱɱ" + - "\x12\x10ɐɐ\x12\x10ɒɒ\x12\x10ȿȿ\x12\x10ɀɀ\x12\x10ɥɥ\x12\x10ɦɦ\x12\x10ɜɜ" + - "\x12\x10ɡɡ\x12\x10ɬɬ\x12\x10ɪɪ\x12\x10ʞʞ\x12\x10ʇʇ\x12\x10ʝʝ\x12\x12ffFF" + - "Ff\x12\x12fiFIFi\x12\x12flFLFl\x13\x1bffiFFIFfi\x13\x1bfflFFLFfl\x12\x12" + - "stSTSt\x12\x12stSTSt\x14$մնՄՆՄն\x14$մեՄԵՄե\x14$միՄԻՄի\x14$վնՎՆՎն\x14$մխՄ" + - "ԽՄխ" - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookup(s []byte) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupUnsafe(s []byte) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookupString(s string) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupStringUnsafe(s string) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// caseTrie. Total size: 11892 bytes (11.61 KiB). Checksum: c6f15484b7653775. -type caseTrie struct{} - -func newCaseTrie(i int) *caseTrie { - return &caseTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *caseTrie) lookupValue(n uint32, b byte) uint16 { - switch { - case n < 18: - return uint16(caseValues[n<<6+uint32(b)]) - default: - n -= 18 - return uint16(sparse.lookup(n, b)) - } -} - -// caseValues: 20 blocks, 1280 entries, 2560 bytes -// The third block is the zero block. -var caseValues = [1280]uint16{ - // Block 0x0, offset 0x0 - 0x27: 0x0054, - 0x2e: 0x0054, - 0x30: 0x0010, 0x31: 0x0010, 0x32: 0x0010, 0x33: 0x0010, 0x34: 0x0010, 0x35: 0x0010, - 0x36: 0x0010, 0x37: 0x0010, 0x38: 0x0010, 0x39: 0x0010, 0x3a: 0x0054, - // Block 0x1, offset 0x40 - 0x41: 0x2013, 0x42: 0x2013, 0x43: 0x2013, 0x44: 0x2013, 0x45: 0x2013, - 0x46: 0x2013, 0x47: 0x2013, 0x48: 0x2013, 0x49: 0x2013, 0x4a: 0x2013, 0x4b: 0x2013, - 0x4c: 0x2013, 0x4d: 0x2013, 0x4e: 0x2013, 0x4f: 0x2013, 0x50: 0x2013, 0x51: 0x2013, - 0x52: 0x2013, 0x53: 0x2013, 0x54: 0x2013, 0x55: 0x2013, 0x56: 0x2013, 0x57: 0x2013, - 0x58: 0x2013, 0x59: 0x2013, 0x5a: 0x2013, - 0x5e: 0x0004, 0x5f: 0x0010, 0x60: 0x0004, 0x61: 0x2012, 0x62: 0x2012, 0x63: 0x2012, - 0x64: 0x2012, 0x65: 0x2012, 0x66: 0x2012, 0x67: 0x2012, 0x68: 0x2012, 0x69: 0x2012, - 0x6a: 0x2012, 0x6b: 0x2012, 0x6c: 0x2012, 0x6d: 0x2012, 0x6e: 0x2012, 0x6f: 0x2012, - 0x70: 0x2012, 0x71: 0x2012, 0x72: 0x2012, 0x73: 0x2012, 0x74: 0x2012, 0x75: 0x2012, - 0x76: 0x2012, 0x77: 0x2012, 0x78: 0x2012, 0x79: 0x2012, 0x7a: 0x2012, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x0852, 0xc1: 0x0b53, 0xc2: 0x0113, 0xc3: 0x0112, 0xc4: 0x0113, 0xc5: 0x0112, - 0xc6: 0x0b53, 0xc7: 0x0f13, 0xc8: 0x0f12, 0xc9: 0x0e53, 0xca: 0x1153, 0xcb: 0x0713, - 0xcc: 0x0712, 0xcd: 0x0012, 0xce: 0x1453, 0xcf: 0x1753, 0xd0: 0x1a53, 0xd1: 0x0313, - 0xd2: 0x0312, 0xd3: 0x1d53, 0xd4: 0x2053, 0xd5: 0x2352, 0xd6: 0x2653, 0xd7: 0x2653, - 0xd8: 0x0113, 0xd9: 0x0112, 0xda: 0x2952, 0xdb: 0x0012, 0xdc: 0x1d53, 0xdd: 0x2c53, - 0xde: 0x2f52, 0xdf: 0x3253, 0xe0: 0x0113, 0xe1: 0x0112, 0xe2: 0x0113, 0xe3: 0x0112, - 0xe4: 0x0113, 0xe5: 0x0112, 0xe6: 0x3553, 0xe7: 0x0f13, 0xe8: 0x0f12, 0xe9: 0x3853, - 0xea: 0x0012, 0xeb: 0x0012, 0xec: 0x0113, 0xed: 0x0112, 0xee: 0x3553, 0xef: 0x1f13, - 0xf0: 0x1f12, 0xf1: 0x3b53, 0xf2: 0x3e53, 0xf3: 0x0713, 0xf4: 0x0712, 0xf5: 0x0313, - 0xf6: 0x0312, 0xf7: 0x4153, 0xf8: 0x0113, 0xf9: 0x0112, 0xfa: 0x0012, 0xfb: 0x0010, - 0xfc: 0x0113, 0xfd: 0x0112, 0xfe: 0x0012, 0xff: 0x4452, - // Block 0x4, offset 0x100 - 0x100: 0x0010, 0x101: 0x0010, 0x102: 0x0010, 0x103: 0x0010, 0x104: 0x02db, 0x105: 0x0359, - 0x106: 0x03da, 0x107: 0x043b, 0x108: 0x04b9, 0x109: 0x053a, 0x10a: 0x059b, 0x10b: 0x0619, - 0x10c: 0x069a, 0x10d: 0x0313, 0x10e: 0x0312, 0x10f: 0x1f13, 0x110: 0x1f12, 0x111: 0x0313, - 0x112: 0x0312, 0x113: 0x0713, 0x114: 0x0712, 0x115: 0x0313, 0x116: 0x0312, 0x117: 0x0f13, - 0x118: 0x0f12, 0x119: 0x0313, 0x11a: 0x0312, 0x11b: 0x0713, 0x11c: 0x0712, 0x11d: 0x1452, - 0x11e: 0x0113, 0x11f: 0x0112, 0x120: 0x0113, 0x121: 0x0112, 0x122: 0x0113, 0x123: 0x0112, - 0x124: 0x0113, 0x125: 0x0112, 0x126: 0x0113, 0x127: 0x0112, 0x128: 0x0113, 0x129: 0x0112, - 0x12a: 0x0113, 0x12b: 0x0112, 0x12c: 0x0113, 0x12d: 0x0112, 0x12e: 0x0113, 0x12f: 0x0112, - 0x130: 0x06fa, 0x131: 0x07ab, 0x132: 0x0829, 0x133: 0x08aa, 0x134: 0x0113, 0x135: 0x0112, - 0x136: 0x2353, 0x137: 0x4453, 0x138: 0x0113, 0x139: 0x0112, 0x13a: 0x0113, 0x13b: 0x0112, - 0x13c: 0x0113, 0x13d: 0x0112, 0x13e: 0x0113, 0x13f: 0x0112, - // Block 0x5, offset 0x140 - 0x140: 0x0a8a, 0x141: 0x0313, 0x142: 0x0312, 0x143: 0x0853, 0x144: 0x4753, 0x145: 0x4a53, - 0x146: 0x0113, 0x147: 0x0112, 0x148: 0x0113, 0x149: 0x0112, 0x14a: 0x0113, 0x14b: 0x0112, - 0x14c: 0x0113, 0x14d: 0x0112, 0x14e: 0x0113, 0x14f: 0x0112, 0x150: 0x0b0a, 0x151: 0x0b8a, - 0x152: 0x0c0a, 0x153: 0x0b52, 0x154: 0x0b52, 0x155: 0x0012, 0x156: 0x0e52, 0x157: 0x1152, - 0x158: 0x0012, 0x159: 0x1752, 0x15a: 0x0012, 0x15b: 0x1a52, 0x15c: 0x0c8a, 0x15d: 0x0012, - 0x15e: 0x0012, 0x15f: 0x0012, 0x160: 0x1d52, 0x161: 0x0d0a, 0x162: 0x0012, 0x163: 0x2052, - 0x164: 0x0012, 0x165: 0x0d8a, 0x166: 0x0e0a, 0x167: 0x0012, 0x168: 0x2652, 0x169: 0x2652, - 0x16a: 0x0e8a, 0x16b: 0x0f0a, 0x16c: 0x0f8a, 0x16d: 0x0012, 0x16e: 0x0012, 0x16f: 0x1d52, - 0x170: 0x0012, 0x171: 0x100a, 0x172: 0x2c52, 0x173: 0x0012, 0x174: 0x0012, 0x175: 0x3252, - 0x176: 0x0012, 0x177: 0x0012, 0x178: 0x0012, 0x179: 0x0012, 0x17a: 0x0012, 0x17b: 0x0012, - 0x17c: 0x0012, 0x17d: 0x108a, 0x17e: 0x0012, 0x17f: 0x0012, - // Block 0x6, offset 0x180 - 0x180: 0x3552, 0x181: 0x0012, 0x182: 0x0012, 0x183: 0x3852, 0x184: 0x0012, 0x185: 0x0012, - 0x186: 0x0012, 0x187: 0x110a, 0x188: 0x3552, 0x189: 0x4752, 0x18a: 0x3b52, 0x18b: 0x3e52, - 0x18c: 0x4a52, 0x18d: 0x0012, 0x18e: 0x0012, 0x18f: 0x0012, 0x190: 0x0012, 0x191: 0x0012, - 0x192: 0x4152, 0x193: 0x0012, 0x194: 0x0010, 0x195: 0x0012, 0x196: 0x0012, 0x197: 0x0012, - 0x198: 0x0012, 0x199: 0x0012, 0x19a: 0x0012, 0x19b: 0x0012, 0x19c: 0x0012, 0x19d: 0x118a, - 0x19e: 0x120a, 0x19f: 0x0012, 0x1a0: 0x0012, 0x1a1: 0x0012, 0x1a2: 0x0012, 0x1a3: 0x0012, - 0x1a4: 0x0012, 0x1a5: 0x0012, 0x1a6: 0x0012, 0x1a7: 0x0012, 0x1a8: 0x0012, 0x1a9: 0x0012, - 0x1aa: 0x0012, 0x1ab: 0x0012, 0x1ac: 0x0012, 0x1ad: 0x0012, 0x1ae: 0x0012, 0x1af: 0x0012, - 0x1b0: 0x0015, 0x1b1: 0x0015, 0x1b2: 0x0015, 0x1b3: 0x0015, 0x1b4: 0x0015, 0x1b5: 0x0015, - 0x1b6: 0x0015, 0x1b7: 0x0015, 0x1b8: 0x0015, 0x1b9: 0x0014, 0x1ba: 0x0014, 0x1bb: 0x0014, - 0x1bc: 0x0014, 0x1bd: 0x0014, 0x1be: 0x0014, 0x1bf: 0x0014, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x0024, 0x1c1: 0x0024, 0x1c2: 0x0024, 0x1c3: 0x0024, 0x1c4: 0x0024, 0x1c5: 0x128d, - 0x1c6: 0x0024, 0x1c7: 0x0034, 0x1c8: 0x0034, 0x1c9: 0x0034, 0x1ca: 0x0024, 0x1cb: 0x0024, - 0x1cc: 0x0024, 0x1cd: 0x0034, 0x1ce: 0x0034, 0x1cf: 0x0014, 0x1d0: 0x0024, 0x1d1: 0x0024, - 0x1d2: 0x0024, 0x1d3: 0x0034, 0x1d4: 0x0034, 0x1d5: 0x0034, 0x1d6: 0x0034, 0x1d7: 0x0024, - 0x1d8: 0x0034, 0x1d9: 0x0034, 0x1da: 0x0034, 0x1db: 0x0024, 0x1dc: 0x0034, 0x1dd: 0x0034, - 0x1de: 0x0034, 0x1df: 0x0034, 0x1e0: 0x0034, 0x1e1: 0x0034, 0x1e2: 0x0034, 0x1e3: 0x0024, - 0x1e4: 0x0024, 0x1e5: 0x0024, 0x1e6: 0x0024, 0x1e7: 0x0024, 0x1e8: 0x0024, 0x1e9: 0x0024, - 0x1ea: 0x0024, 0x1eb: 0x0024, 0x1ec: 0x0024, 0x1ed: 0x0024, 0x1ee: 0x0024, 0x1ef: 0x0024, - 0x1f0: 0x0113, 0x1f1: 0x0112, 0x1f2: 0x0113, 0x1f3: 0x0112, 0x1f4: 0x0014, 0x1f5: 0x0004, - 0x1f6: 0x0113, 0x1f7: 0x0112, 0x1fa: 0x0015, 0x1fb: 0x4d52, - 0x1fc: 0x5052, 0x1fd: 0x5052, 0x1ff: 0x5353, - // Block 0x8, offset 0x200 - 0x204: 0x0004, 0x205: 0x0004, - 0x206: 0x2a13, 0x207: 0x0054, 0x208: 0x2513, 0x209: 0x2713, 0x20a: 0x2513, - 0x20c: 0x5653, 0x20e: 0x5953, 0x20f: 0x5c53, 0x210: 0x130a, 0x211: 0x2013, - 0x212: 0x2013, 0x213: 0x2013, 0x214: 0x2013, 0x215: 0x2013, 0x216: 0x2013, 0x217: 0x2013, - 0x218: 0x2013, 0x219: 0x2013, 0x21a: 0x2013, 0x21b: 0x2013, 0x21c: 0x2013, 0x21d: 0x2013, - 0x21e: 0x2013, 0x21f: 0x2013, 0x220: 0x5f53, 0x221: 0x5f53, 0x223: 0x5f53, - 0x224: 0x5f53, 0x225: 0x5f53, 0x226: 0x5f53, 0x227: 0x5f53, 0x228: 0x5f53, 0x229: 0x5f53, - 0x22a: 0x5f53, 0x22b: 0x5f53, 0x22c: 0x2a12, 0x22d: 0x2512, 0x22e: 0x2712, 0x22f: 0x2512, - 0x230: 0x144a, 0x231: 0x2012, 0x232: 0x2012, 0x233: 0x2012, 0x234: 0x2012, 0x235: 0x2012, - 0x236: 0x2012, 0x237: 0x2012, 0x238: 0x2012, 0x239: 0x2012, 0x23a: 0x2012, 0x23b: 0x2012, - 0x23c: 0x2012, 0x23d: 0x2012, 0x23e: 0x2012, 0x23f: 0x2012, - // Block 0x9, offset 0x240 - 0x240: 0x5f52, 0x241: 0x5f52, 0x242: 0x158a, 0x243: 0x5f52, 0x244: 0x5f52, 0x245: 0x5f52, - 0x246: 0x5f52, 0x247: 0x5f52, 0x248: 0x5f52, 0x249: 0x5f52, 0x24a: 0x5f52, 0x24b: 0x5f52, - 0x24c: 0x5652, 0x24d: 0x5952, 0x24e: 0x5c52, 0x24f: 0x1813, 0x250: 0x160a, 0x251: 0x168a, - 0x252: 0x0013, 0x253: 0x0013, 0x254: 0x0013, 0x255: 0x170a, 0x256: 0x178a, 0x257: 0x1812, - 0x258: 0x0113, 0x259: 0x0112, 0x25a: 0x0113, 0x25b: 0x0112, 0x25c: 0x0113, 0x25d: 0x0112, - 0x25e: 0x0113, 0x25f: 0x0112, 0x260: 0x0113, 0x261: 0x0112, 0x262: 0x0113, 0x263: 0x0112, - 0x264: 0x0113, 0x265: 0x0112, 0x266: 0x0113, 0x267: 0x0112, 0x268: 0x0113, 0x269: 0x0112, - 0x26a: 0x0113, 0x26b: 0x0112, 0x26c: 0x0113, 0x26d: 0x0112, 0x26e: 0x0113, 0x26f: 0x0112, - 0x270: 0x180a, 0x271: 0x188a, 0x272: 0x0b12, 0x273: 0x5352, 0x274: 0x6253, 0x275: 0x190a, - 0x277: 0x0f13, 0x278: 0x0f12, 0x279: 0x0b13, 0x27a: 0x0113, 0x27b: 0x0112, - 0x27c: 0x0012, 0x27d: 0x4d53, 0x27e: 0x5053, 0x27f: 0x5053, - // Block 0xa, offset 0x280 - 0x280: 0x0812, 0x281: 0x0812, 0x282: 0x0812, 0x283: 0x0812, 0x284: 0x0812, 0x285: 0x0812, - 0x288: 0x0813, 0x289: 0x0813, 0x28a: 0x0813, 0x28b: 0x0813, - 0x28c: 0x0813, 0x28d: 0x0813, 0x290: 0x239a, 0x291: 0x0812, - 0x292: 0x247a, 0x293: 0x0812, 0x294: 0x25ba, 0x295: 0x0812, 0x296: 0x26fa, 0x297: 0x0812, - 0x299: 0x0813, 0x29b: 0x0813, 0x29d: 0x0813, - 0x29f: 0x0813, 0x2a0: 0x0812, 0x2a1: 0x0812, 0x2a2: 0x0812, 0x2a3: 0x0812, - 0x2a4: 0x0812, 0x2a5: 0x0812, 0x2a6: 0x0812, 0x2a7: 0x0812, 0x2a8: 0x0813, 0x2a9: 0x0813, - 0x2aa: 0x0813, 0x2ab: 0x0813, 0x2ac: 0x0813, 0x2ad: 0x0813, 0x2ae: 0x0813, 0x2af: 0x0813, - 0x2b0: 0x8b52, 0x2b1: 0x8b52, 0x2b2: 0x8e52, 0x2b3: 0x8e52, 0x2b4: 0x9152, 0x2b5: 0x9152, - 0x2b6: 0x9452, 0x2b7: 0x9452, 0x2b8: 0x9752, 0x2b9: 0x9752, 0x2ba: 0x9a52, 0x2bb: 0x9a52, - 0x2bc: 0x4d52, 0x2bd: 0x4d52, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x283a, 0x2c1: 0x292a, 0x2c2: 0x2a1a, 0x2c3: 0x2b0a, 0x2c4: 0x2bfa, 0x2c5: 0x2cea, - 0x2c6: 0x2dda, 0x2c7: 0x2eca, 0x2c8: 0x2fb9, 0x2c9: 0x30a9, 0x2ca: 0x3199, 0x2cb: 0x3289, - 0x2cc: 0x3379, 0x2cd: 0x3469, 0x2ce: 0x3559, 0x2cf: 0x3649, 0x2d0: 0x373a, 0x2d1: 0x382a, - 0x2d2: 0x391a, 0x2d3: 0x3a0a, 0x2d4: 0x3afa, 0x2d5: 0x3bea, 0x2d6: 0x3cda, 0x2d7: 0x3dca, - 0x2d8: 0x3eb9, 0x2d9: 0x3fa9, 0x2da: 0x4099, 0x2db: 0x4189, 0x2dc: 0x4279, 0x2dd: 0x4369, - 0x2de: 0x4459, 0x2df: 0x4549, 0x2e0: 0x463a, 0x2e1: 0x472a, 0x2e2: 0x481a, 0x2e3: 0x490a, - 0x2e4: 0x49fa, 0x2e5: 0x4aea, 0x2e6: 0x4bda, 0x2e7: 0x4cca, 0x2e8: 0x4db9, 0x2e9: 0x4ea9, - 0x2ea: 0x4f99, 0x2eb: 0x5089, 0x2ec: 0x5179, 0x2ed: 0x5269, 0x2ee: 0x5359, 0x2ef: 0x5449, - 0x2f0: 0x0812, 0x2f1: 0x0812, 0x2f2: 0x553a, 0x2f3: 0x564a, 0x2f4: 0x571a, - 0x2f6: 0x57fa, 0x2f7: 0x58da, 0x2f8: 0x0813, 0x2f9: 0x0813, 0x2fa: 0x8b53, 0x2fb: 0x8b53, - 0x2fc: 0x5a19, 0x2fd: 0x0004, 0x2fe: 0x5aea, 0x2ff: 0x0004, - // Block 0xc, offset 0x300 - 0x300: 0x0004, 0x301: 0x0004, 0x302: 0x5b6a, 0x303: 0x5c7a, 0x304: 0x5d4a, - 0x306: 0x5e2a, 0x307: 0x5f0a, 0x308: 0x8e53, 0x309: 0x8e53, 0x30a: 0x9153, 0x30b: 0x9153, - 0x30c: 0x6049, 0x30d: 0x0004, 0x30e: 0x0004, 0x30f: 0x0004, 0x310: 0x0812, 0x311: 0x0812, - 0x312: 0x611a, 0x313: 0x625a, 0x316: 0x639a, 0x317: 0x647a, - 0x318: 0x0813, 0x319: 0x0813, 0x31a: 0x9453, 0x31b: 0x9453, 0x31d: 0x0004, - 0x31e: 0x0004, 0x31f: 0x0004, 0x320: 0x0812, 0x321: 0x0812, 0x322: 0x65ba, 0x323: 0x66fa, - 0x324: 0x683a, 0x325: 0x0912, 0x326: 0x691a, 0x327: 0x69fa, 0x328: 0x0813, 0x329: 0x0813, - 0x32a: 0x9a53, 0x32b: 0x9a53, 0x32c: 0x0913, 0x32d: 0x0004, 0x32e: 0x0004, 0x32f: 0x0004, - 0x332: 0x6b3a, 0x333: 0x6c4a, 0x334: 0x6d1a, - 0x336: 0x6dfa, 0x337: 0x6eda, 0x338: 0x9753, 0x339: 0x9753, 0x33a: 0x4d53, 0x33b: 0x4d53, - 0x33c: 0x7019, 0x33d: 0x0004, 0x33e: 0x0004, - // Block 0xd, offset 0x340 - 0x342: 0x0013, - 0x347: 0x0013, 0x34a: 0x0012, 0x34b: 0x0013, - 0x34c: 0x0013, 0x34d: 0x0013, 0x34e: 0x0012, 0x34f: 0x0012, 0x350: 0x0013, 0x351: 0x0013, - 0x352: 0x0013, 0x353: 0x0012, 0x355: 0x0013, - 0x359: 0x0013, 0x35a: 0x0013, 0x35b: 0x0013, 0x35c: 0x0013, 0x35d: 0x0013, - 0x364: 0x0013, 0x366: 0x70eb, 0x368: 0x0013, - 0x36a: 0x714b, 0x36b: 0x718b, 0x36c: 0x0013, 0x36d: 0x0013, 0x36f: 0x0012, - 0x370: 0x0013, 0x371: 0x0013, 0x372: 0x9d53, 0x373: 0x0013, 0x374: 0x0012, 0x375: 0x0010, - 0x376: 0x0010, 0x377: 0x0010, 0x378: 0x0010, 0x379: 0x0012, - 0x37c: 0x0012, 0x37d: 0x0012, 0x37e: 0x0013, 0x37f: 0x0013, - // Block 0xe, offset 0x380 - 0x380: 0x1a13, 0x381: 0x1a13, 0x382: 0x1e13, 0x383: 0x1e13, 0x384: 0x1a13, 0x385: 0x1a13, - 0x386: 0x2613, 0x387: 0x2613, 0x388: 0x2a13, 0x389: 0x2a13, 0x38a: 0x2e13, 0x38b: 0x2e13, - 0x38c: 0x2a13, 0x38d: 0x2a13, 0x38e: 0x2613, 0x38f: 0x2613, 0x390: 0xa052, 0x391: 0xa052, - 0x392: 0xa352, 0x393: 0xa352, 0x394: 0xa652, 0x395: 0xa652, 0x396: 0xa352, 0x397: 0xa352, - 0x398: 0xa052, 0x399: 0xa052, 0x39a: 0x1a12, 0x39b: 0x1a12, 0x39c: 0x1e12, 0x39d: 0x1e12, - 0x39e: 0x1a12, 0x39f: 0x1a12, 0x3a0: 0x2612, 0x3a1: 0x2612, 0x3a2: 0x2a12, 0x3a3: 0x2a12, - 0x3a4: 0x2e12, 0x3a5: 0x2e12, 0x3a6: 0x2a12, 0x3a7: 0x2a12, 0x3a8: 0x2612, 0x3a9: 0x2612, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x6552, 0x3c1: 0x6552, 0x3c2: 0x6552, 0x3c3: 0x6552, 0x3c4: 0x6552, 0x3c5: 0x6552, - 0x3c6: 0x6552, 0x3c7: 0x6552, 0x3c8: 0x6552, 0x3c9: 0x6552, 0x3ca: 0x6552, 0x3cb: 0x6552, - 0x3cc: 0x6552, 0x3cd: 0x6552, 0x3ce: 0x6552, 0x3cf: 0x6552, 0x3d0: 0xa952, 0x3d1: 0xa952, - 0x3d2: 0xa952, 0x3d3: 0xa952, 0x3d4: 0xa952, 0x3d5: 0xa952, 0x3d6: 0xa952, 0x3d7: 0xa952, - 0x3d8: 0xa952, 0x3d9: 0xa952, 0x3da: 0xa952, 0x3db: 0xa952, 0x3dc: 0xa952, 0x3dd: 0xa952, - 0x3de: 0xa952, 0x3e0: 0x0113, 0x3e1: 0x0112, 0x3e2: 0x71eb, 0x3e3: 0x8853, - 0x3e4: 0x724b, 0x3e5: 0x72aa, 0x3e6: 0x730a, 0x3e7: 0x0f13, 0x3e8: 0x0f12, 0x3e9: 0x0313, - 0x3ea: 0x0312, 0x3eb: 0x0713, 0x3ec: 0x0712, 0x3ed: 0x736b, 0x3ee: 0x73cb, 0x3ef: 0x742b, - 0x3f0: 0x748b, 0x3f1: 0x0012, 0x3f2: 0x0113, 0x3f3: 0x0112, 0x3f4: 0x0012, 0x3f5: 0x0313, - 0x3f6: 0x0312, 0x3f7: 0x0012, 0x3f8: 0x0012, 0x3f9: 0x0012, 0x3fa: 0x0012, 0x3fb: 0x0012, - 0x3fc: 0x0015, 0x3fd: 0x0015, 0x3fe: 0x74eb, 0x3ff: 0x754b, - // Block 0x10, offset 0x400 - 0x400: 0x0113, 0x401: 0x0112, 0x402: 0x0113, 0x403: 0x0112, 0x404: 0x0113, 0x405: 0x0112, - 0x406: 0x0113, 0x407: 0x0112, 0x408: 0x0014, 0x409: 0x0014, 0x40a: 0x0014, 0x40b: 0x0713, - 0x40c: 0x0712, 0x40d: 0x75ab, 0x40e: 0x0012, 0x40f: 0x0010, 0x410: 0x0113, 0x411: 0x0112, - 0x412: 0x0113, 0x413: 0x0112, 0x414: 0x0012, 0x415: 0x0012, 0x416: 0x0113, 0x417: 0x0112, - 0x418: 0x0113, 0x419: 0x0112, 0x41a: 0x0113, 0x41b: 0x0112, 0x41c: 0x0113, 0x41d: 0x0112, - 0x41e: 0x0113, 0x41f: 0x0112, 0x420: 0x0113, 0x421: 0x0112, 0x422: 0x0113, 0x423: 0x0112, - 0x424: 0x0113, 0x425: 0x0112, 0x426: 0x0113, 0x427: 0x0112, 0x428: 0x0113, 0x429: 0x0112, - 0x42a: 0x760b, 0x42b: 0x766b, 0x42c: 0x76cb, 0x42d: 0x772b, 0x42e: 0x778b, - 0x430: 0x77eb, 0x431: 0x784b, 0x432: 0x78ab, 0x433: 0xac53, 0x434: 0x0113, 0x435: 0x0112, - 0x436: 0x0113, 0x437: 0x0112, - // Block 0x11, offset 0x440 - 0x440: 0x790a, 0x441: 0x798a, 0x442: 0x7a0a, 0x443: 0x7a8a, 0x444: 0x7b3a, 0x445: 0x7bea, - 0x446: 0x7c6a, - 0x453: 0x7cea, 0x454: 0x7dca, 0x455: 0x7eaa, 0x456: 0x7f8a, 0x457: 0x806a, - 0x45d: 0x0010, - 0x45e: 0x0034, 0x45f: 0x0010, 0x460: 0x0010, 0x461: 0x0010, 0x462: 0x0010, 0x463: 0x0010, - 0x464: 0x0010, 0x465: 0x0010, 0x466: 0x0010, 0x467: 0x0010, 0x468: 0x0010, - 0x46a: 0x0010, 0x46b: 0x0010, 0x46c: 0x0010, 0x46d: 0x0010, 0x46e: 0x0010, 0x46f: 0x0010, - 0x470: 0x0010, 0x471: 0x0010, 0x472: 0x0010, 0x473: 0x0010, 0x474: 0x0010, 0x475: 0x0010, - 0x476: 0x0010, 0x478: 0x0010, 0x479: 0x0010, 0x47a: 0x0010, 0x47b: 0x0010, - 0x47c: 0x0010, 0x47e: 0x0010, - // Block 0x12, offset 0x480 - 0x480: 0x2213, 0x481: 0x2213, 0x482: 0x2613, 0x483: 0x2613, 0x484: 0x2213, 0x485: 0x2213, - 0x486: 0x2e13, 0x487: 0x2e13, 0x488: 0x2213, 0x489: 0x2213, 0x48a: 0x2613, 0x48b: 0x2613, - 0x48c: 0x2213, 0x48d: 0x2213, 0x48e: 0x3e13, 0x48f: 0x3e13, 0x490: 0x2213, 0x491: 0x2213, - 0x492: 0x2613, 0x493: 0x2613, 0x494: 0x2213, 0x495: 0x2213, 0x496: 0x2e13, 0x497: 0x2e13, - 0x498: 0x2213, 0x499: 0x2213, 0x49a: 0x2613, 0x49b: 0x2613, 0x49c: 0x2213, 0x49d: 0x2213, - 0x49e: 0xb553, 0x49f: 0xb553, 0x4a0: 0xb853, 0x4a1: 0xb853, 0x4a2: 0x2212, 0x4a3: 0x2212, - 0x4a4: 0x2612, 0x4a5: 0x2612, 0x4a6: 0x2212, 0x4a7: 0x2212, 0x4a8: 0x2e12, 0x4a9: 0x2e12, - 0x4aa: 0x2212, 0x4ab: 0x2212, 0x4ac: 0x2612, 0x4ad: 0x2612, 0x4ae: 0x2212, 0x4af: 0x2212, - 0x4b0: 0x3e12, 0x4b1: 0x3e12, 0x4b2: 0x2212, 0x4b3: 0x2212, 0x4b4: 0x2612, 0x4b5: 0x2612, - 0x4b6: 0x2212, 0x4b7: 0x2212, 0x4b8: 0x2e12, 0x4b9: 0x2e12, 0x4ba: 0x2212, 0x4bb: 0x2212, - 0x4bc: 0x2612, 0x4bd: 0x2612, 0x4be: 0x2212, 0x4bf: 0x2212, - // Block 0x13, offset 0x4c0 - 0x4c2: 0x0010, - 0x4c7: 0x0010, 0x4c9: 0x0010, 0x4cb: 0x0010, - 0x4cd: 0x0010, 0x4ce: 0x0010, 0x4cf: 0x0010, 0x4d1: 0x0010, - 0x4d2: 0x0010, 0x4d4: 0x0010, 0x4d7: 0x0010, - 0x4d9: 0x0010, 0x4db: 0x0010, 0x4dd: 0x0010, - 0x4df: 0x0010, 0x4e1: 0x0010, 0x4e2: 0x0010, - 0x4e4: 0x0010, 0x4e7: 0x0010, 0x4e8: 0x0010, 0x4e9: 0x0010, - 0x4ea: 0x0010, 0x4ec: 0x0010, 0x4ed: 0x0010, 0x4ee: 0x0010, 0x4ef: 0x0010, - 0x4f0: 0x0010, 0x4f1: 0x0010, 0x4f2: 0x0010, 0x4f4: 0x0010, 0x4f5: 0x0010, - 0x4f6: 0x0010, 0x4f7: 0x0010, 0x4f9: 0x0010, 0x4fa: 0x0010, 0x4fb: 0x0010, - 0x4fc: 0x0010, 0x4fe: 0x0010, -} - -// caseIndex: 25 blocks, 1600 entries, 3200 bytes -// Block 0 is the zero block. -var caseIndex = [1600]uint16{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x12, 0xc3: 0x13, 0xc4: 0x14, 0xc5: 0x15, 0xc6: 0x01, 0xc7: 0x02, - 0xc8: 0x16, 0xc9: 0x03, 0xca: 0x04, 0xcb: 0x17, 0xcc: 0x18, 0xcd: 0x05, 0xce: 0x06, 0xcf: 0x07, - 0xd0: 0x19, 0xd1: 0x1a, 0xd2: 0x1b, 0xd3: 0x1c, 0xd4: 0x1d, 0xd5: 0x1e, 0xd6: 0x1f, 0xd7: 0x20, - 0xd8: 0x21, 0xd9: 0x22, 0xda: 0x23, 0xdb: 0x24, 0xdc: 0x25, 0xdd: 0x26, 0xde: 0x27, 0xdf: 0x28, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, - 0xea: 0x06, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x08, 0xef: 0x09, - 0xf0: 0x14, 0xf3: 0x16, - // Block 0x4, offset 0x100 - 0x120: 0x29, 0x121: 0x2a, 0x122: 0x2b, 0x123: 0x2c, 0x124: 0x2d, 0x125: 0x2e, 0x126: 0x2f, 0x127: 0x30, - 0x128: 0x31, 0x129: 0x32, 0x12a: 0x33, 0x12b: 0x34, 0x12c: 0x35, 0x12d: 0x36, 0x12e: 0x37, 0x12f: 0x38, - 0x130: 0x39, 0x131: 0x3a, 0x132: 0x3b, 0x133: 0x3c, 0x134: 0x3d, 0x135: 0x3e, 0x136: 0x3f, 0x137: 0x40, - 0x138: 0x41, 0x139: 0x42, 0x13a: 0x43, 0x13b: 0x44, 0x13c: 0x45, 0x13d: 0x46, 0x13e: 0x47, 0x13f: 0x48, - // Block 0x5, offset 0x140 - 0x140: 0x49, 0x141: 0x4a, 0x142: 0x4b, 0x143: 0x4c, 0x144: 0x23, 0x145: 0x23, 0x146: 0x23, 0x147: 0x23, - 0x148: 0x23, 0x149: 0x4d, 0x14a: 0x4e, 0x14b: 0x4f, 0x14c: 0x50, 0x14d: 0x51, 0x14e: 0x52, 0x14f: 0x53, - 0x150: 0x54, 0x151: 0x23, 0x152: 0x23, 0x153: 0x23, 0x154: 0x23, 0x155: 0x23, 0x156: 0x23, 0x157: 0x23, - 0x158: 0x23, 0x159: 0x55, 0x15a: 0x56, 0x15b: 0x57, 0x15c: 0x58, 0x15d: 0x59, 0x15e: 0x5a, 0x15f: 0x5b, - 0x160: 0x5c, 0x161: 0x5d, 0x162: 0x5e, 0x163: 0x5f, 0x164: 0x60, 0x165: 0x61, 0x167: 0x62, - 0x168: 0x63, 0x169: 0x64, 0x16a: 0x65, 0x16c: 0x66, 0x16d: 0x67, 0x16e: 0x68, 0x16f: 0x69, - 0x170: 0x6a, 0x171: 0x6b, 0x172: 0x6c, 0x173: 0x6d, 0x174: 0x6e, 0x175: 0x6f, 0x176: 0x70, 0x177: 0x71, - 0x178: 0x72, 0x179: 0x72, 0x17a: 0x73, 0x17b: 0x72, 0x17c: 0x74, 0x17d: 0x08, 0x17e: 0x09, 0x17f: 0x0a, - // Block 0x6, offset 0x180 - 0x180: 0x75, 0x181: 0x76, 0x182: 0x77, 0x183: 0x78, 0x184: 0x0b, 0x185: 0x79, 0x186: 0x7a, - 0x192: 0x7b, 0x193: 0x0c, - 0x1b0: 0x7c, 0x1b1: 0x0d, 0x1b2: 0x72, 0x1b3: 0x7d, 0x1b4: 0x7e, 0x1b5: 0x7f, 0x1b6: 0x80, 0x1b7: 0x81, - 0x1b8: 0x82, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x83, 0x1c2: 0x84, 0x1c3: 0x85, 0x1c4: 0x86, 0x1c5: 0x23, 0x1c6: 0x87, - // Block 0x8, offset 0x200 - 0x200: 0x88, 0x201: 0x23, 0x202: 0x23, 0x203: 0x23, 0x204: 0x23, 0x205: 0x23, 0x206: 0x23, 0x207: 0x23, - 0x208: 0x23, 0x209: 0x23, 0x20a: 0x23, 0x20b: 0x23, 0x20c: 0x23, 0x20d: 0x23, 0x20e: 0x23, 0x20f: 0x23, - 0x210: 0x23, 0x211: 0x23, 0x212: 0x89, 0x213: 0x8a, 0x214: 0x23, 0x215: 0x23, 0x216: 0x23, 0x217: 0x23, - 0x218: 0x8b, 0x219: 0x8c, 0x21a: 0x8d, 0x21b: 0x8e, 0x21c: 0x8f, 0x21d: 0x90, 0x21e: 0x0e, 0x21f: 0x91, - 0x220: 0x92, 0x221: 0x93, 0x222: 0x23, 0x223: 0x94, 0x224: 0x95, 0x225: 0x96, 0x226: 0x97, 0x227: 0x98, - 0x228: 0x99, 0x229: 0x9a, 0x22a: 0x9b, 0x22b: 0x9c, 0x22c: 0x9d, 0x22d: 0x9e, 0x22e: 0x9f, 0x22f: 0xa0, - 0x230: 0x23, 0x231: 0x23, 0x232: 0x23, 0x233: 0x23, 0x234: 0x23, 0x235: 0x23, 0x236: 0x23, 0x237: 0x23, - 0x238: 0x23, 0x239: 0x23, 0x23a: 0x23, 0x23b: 0x23, 0x23c: 0x23, 0x23d: 0x23, 0x23e: 0x23, 0x23f: 0x23, - // Block 0x9, offset 0x240 - 0x240: 0x23, 0x241: 0x23, 0x242: 0x23, 0x243: 0x23, 0x244: 0x23, 0x245: 0x23, 0x246: 0x23, 0x247: 0x23, - 0x248: 0x23, 0x249: 0x23, 0x24a: 0x23, 0x24b: 0x23, 0x24c: 0x23, 0x24d: 0x23, 0x24e: 0x23, 0x24f: 0x23, - 0x250: 0x23, 0x251: 0x23, 0x252: 0x23, 0x253: 0x23, 0x254: 0x23, 0x255: 0x23, 0x256: 0x23, 0x257: 0x23, - 0x258: 0x23, 0x259: 0x23, 0x25a: 0x23, 0x25b: 0x23, 0x25c: 0x23, 0x25d: 0x23, 0x25e: 0x23, 0x25f: 0x23, - 0x260: 0x23, 0x261: 0x23, 0x262: 0x23, 0x263: 0x23, 0x264: 0x23, 0x265: 0x23, 0x266: 0x23, 0x267: 0x23, - 0x268: 0x23, 0x269: 0x23, 0x26a: 0x23, 0x26b: 0x23, 0x26c: 0x23, 0x26d: 0x23, 0x26e: 0x23, 0x26f: 0x23, - 0x270: 0x23, 0x271: 0x23, 0x272: 0x23, 0x273: 0x23, 0x274: 0x23, 0x275: 0x23, 0x276: 0x23, 0x277: 0x23, - 0x278: 0x23, 0x279: 0x23, 0x27a: 0x23, 0x27b: 0x23, 0x27c: 0x23, 0x27d: 0x23, 0x27e: 0x23, 0x27f: 0x23, - // Block 0xa, offset 0x280 - 0x280: 0x23, 0x281: 0x23, 0x282: 0x23, 0x283: 0x23, 0x284: 0x23, 0x285: 0x23, 0x286: 0x23, 0x287: 0x23, - 0x288: 0x23, 0x289: 0x23, 0x28a: 0x23, 0x28b: 0x23, 0x28c: 0x23, 0x28d: 0x23, 0x28e: 0x23, 0x28f: 0x23, - 0x290: 0x23, 0x291: 0x23, 0x292: 0x23, 0x293: 0x23, 0x294: 0x23, 0x295: 0x23, 0x296: 0x23, 0x297: 0x23, - 0x298: 0x23, 0x299: 0x23, 0x29a: 0x23, 0x29b: 0x23, 0x29c: 0x23, 0x29d: 0x23, 0x29e: 0xa1, 0x29f: 0xa2, - // Block 0xb, offset 0x2c0 - 0x2ec: 0x0f, 0x2ed: 0xa3, 0x2ee: 0xa4, 0x2ef: 0xa5, - 0x2f0: 0x23, 0x2f1: 0x23, 0x2f2: 0x23, 0x2f3: 0x23, 0x2f4: 0xa6, 0x2f5: 0xa7, 0x2f6: 0xa8, 0x2f7: 0xa9, - 0x2f8: 0xaa, 0x2f9: 0xab, 0x2fa: 0x23, 0x2fb: 0xac, 0x2fc: 0xad, 0x2fd: 0xae, 0x2fe: 0xaf, 0x2ff: 0xb0, - // Block 0xc, offset 0x300 - 0x300: 0xb1, 0x301: 0xb2, 0x302: 0x23, 0x303: 0xb3, 0x305: 0xb4, 0x307: 0xb5, - 0x30a: 0xb6, 0x30b: 0xb7, 0x30c: 0xb8, 0x30d: 0xb9, 0x30e: 0xba, 0x30f: 0xbb, - 0x310: 0xbc, 0x311: 0xbd, 0x312: 0xbe, 0x313: 0xbf, 0x314: 0xc0, 0x315: 0xc1, - 0x318: 0x23, 0x319: 0x23, 0x31a: 0x23, 0x31b: 0x23, 0x31c: 0xc2, 0x31d: 0xc3, - 0x320: 0xc4, 0x321: 0xc5, 0x322: 0xc6, 0x323: 0xc7, 0x324: 0xc8, 0x326: 0xc9, - 0x328: 0xca, 0x329: 0xcb, 0x32a: 0xcc, 0x32b: 0xcd, 0x32c: 0x5f, 0x32d: 0xce, 0x32e: 0xcf, - 0x330: 0x23, 0x331: 0xd0, 0x332: 0xd1, 0x333: 0xd2, - // Block 0xd, offset 0x340 - 0x340: 0xd3, 0x341: 0xd4, 0x342: 0xd5, 0x343: 0xd6, 0x344: 0xd7, 0x345: 0xd8, 0x346: 0xd9, 0x347: 0xda, - 0x348: 0xdb, 0x34a: 0xdc, 0x34b: 0xdd, 0x34c: 0xde, 0x34d: 0xdf, - 0x350: 0xe0, 0x351: 0xe1, 0x352: 0xe2, 0x353: 0xe3, 0x356: 0xe4, 0x357: 0xe5, - 0x358: 0xe6, 0x359: 0xe7, 0x35a: 0xe8, 0x35b: 0xe9, 0x35c: 0xea, - 0x362: 0xeb, 0x363: 0xec, - 0x368: 0xed, 0x369: 0xee, 0x36a: 0xef, 0x36b: 0xf0, - 0x370: 0xf1, 0x371: 0xf2, 0x372: 0xf3, 0x374: 0xf4, 0x375: 0xf5, - // Block 0xe, offset 0x380 - 0x380: 0x23, 0x381: 0x23, 0x382: 0x23, 0x383: 0x23, 0x384: 0x23, 0x385: 0x23, 0x386: 0x23, 0x387: 0x23, - 0x388: 0x23, 0x389: 0x23, 0x38a: 0x23, 0x38b: 0x23, 0x38c: 0x23, 0x38d: 0x23, 0x38e: 0xf6, - 0x390: 0x23, 0x391: 0xf7, 0x392: 0x23, 0x393: 0x23, 0x394: 0x23, 0x395: 0xf8, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x23, 0x3c1: 0x23, 0x3c2: 0x23, 0x3c3: 0x23, 0x3c4: 0x23, 0x3c5: 0x23, 0x3c6: 0x23, 0x3c7: 0x23, - 0x3c8: 0x23, 0x3c9: 0x23, 0x3ca: 0x23, 0x3cb: 0x23, 0x3cc: 0x23, 0x3cd: 0x23, 0x3ce: 0x23, 0x3cf: 0x23, - 0x3d0: 0xf7, - // Block 0x10, offset 0x400 - 0x410: 0x23, 0x411: 0x23, 0x412: 0x23, 0x413: 0x23, 0x414: 0x23, 0x415: 0x23, 0x416: 0x23, 0x417: 0x23, - 0x418: 0x23, 0x419: 0xf9, - // Block 0x11, offset 0x440 - 0x460: 0x23, 0x461: 0x23, 0x462: 0x23, 0x463: 0x23, 0x464: 0x23, 0x465: 0x23, 0x466: 0x23, 0x467: 0x23, - 0x468: 0xf0, 0x469: 0xfa, 0x46b: 0xfb, 0x46c: 0xfc, 0x46d: 0xfd, 0x46e: 0xfe, - 0x47c: 0x23, 0x47d: 0xff, 0x47e: 0x100, 0x47f: 0x101, - // Block 0x12, offset 0x480 - 0x4b0: 0x23, 0x4b1: 0x102, 0x4b2: 0x103, - // Block 0x13, offset 0x4c0 - 0x4c5: 0x104, 0x4c6: 0x105, - 0x4c9: 0x106, - 0x4d0: 0x107, 0x4d1: 0x108, 0x4d2: 0x109, 0x4d3: 0x10a, 0x4d4: 0x10b, 0x4d5: 0x10c, 0x4d6: 0x10d, 0x4d7: 0x10e, - 0x4d8: 0x10f, 0x4d9: 0x110, 0x4da: 0x111, 0x4db: 0x112, 0x4dc: 0x113, 0x4dd: 0x114, 0x4de: 0x115, 0x4df: 0x116, - 0x4e8: 0x117, 0x4e9: 0x118, 0x4ea: 0x119, - // Block 0x14, offset 0x500 - 0x500: 0x11a, - 0x520: 0x23, 0x521: 0x23, 0x522: 0x23, 0x523: 0x11b, 0x524: 0x10, 0x525: 0x11c, - 0x538: 0x11d, 0x539: 0x11, 0x53a: 0x11e, - // Block 0x15, offset 0x540 - 0x544: 0x11f, 0x545: 0x120, 0x546: 0x121, - 0x54f: 0x122, - // Block 0x16, offset 0x580 - 0x590: 0x0a, 0x591: 0x0b, 0x592: 0x0c, 0x593: 0x0d, 0x594: 0x0e, 0x596: 0x0f, - 0x59b: 0x10, 0x59d: 0x11, 0x59e: 0x12, 0x59f: 0x13, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x123, 0x5c1: 0x124, 0x5c4: 0x124, 0x5c5: 0x124, 0x5c6: 0x124, 0x5c7: 0x125, - // Block 0x18, offset 0x600 - 0x620: 0x15, -} - -// sparseOffsets: 277 entries, 554 bytes -var sparseOffsets = []uint16{0x0, 0x9, 0xf, 0x18, 0x24, 0x2e, 0x35, 0x38, 0x3c, 0x3f, 0x43, 0x4d, 0x4f, 0x54, 0x64, 0x6b, 0x70, 0x7e, 0x7f, 0x8d, 0x9c, 0xa6, 0xa9, 0xaf, 0xb7, 0xba, 0xbc, 0xca, 0xd0, 0xde, 0xe9, 0xf5, 0x100, 0x10c, 0x116, 0x122, 0x12d, 0x139, 0x145, 0x14d, 0x155, 0x15f, 0x16a, 0x176, 0x17d, 0x188, 0x18d, 0x195, 0x198, 0x19d, 0x1a1, 0x1a5, 0x1ac, 0x1b5, 0x1bd, 0x1be, 0x1c7, 0x1ce, 0x1d6, 0x1dc, 0x1e2, 0x1e7, 0x1eb, 0x1ee, 0x1f0, 0x1f3, 0x1f8, 0x1f9, 0x1fb, 0x1fd, 0x1ff, 0x206, 0x20b, 0x20f, 0x218, 0x21b, 0x21e, 0x224, 0x225, 0x230, 0x231, 0x232, 0x237, 0x244, 0x24c, 0x254, 0x25d, 0x266, 0x26f, 0x274, 0x277, 0x280, 0x28d, 0x28f, 0x296, 0x298, 0x2a4, 0x2a5, 0x2b0, 0x2b8, 0x2c0, 0x2c6, 0x2c7, 0x2d5, 0x2da, 0x2dd, 0x2e2, 0x2e6, 0x2ec, 0x2f1, 0x2f4, 0x2f9, 0x2fe, 0x2ff, 0x305, 0x307, 0x308, 0x30a, 0x30c, 0x30f, 0x310, 0x312, 0x315, 0x31b, 0x31f, 0x321, 0x326, 0x32d, 0x331, 0x33a, 0x33b, 0x343, 0x347, 0x34c, 0x354, 0x35a, 0x360, 0x36a, 0x36f, 0x378, 0x37e, 0x385, 0x389, 0x391, 0x393, 0x395, 0x398, 0x39a, 0x39c, 0x39d, 0x39e, 0x3a0, 0x3a2, 0x3a8, 0x3ad, 0x3af, 0x3b5, 0x3b8, 0x3ba, 0x3c0, 0x3c5, 0x3c7, 0x3c8, 0x3c9, 0x3ca, 0x3cc, 0x3ce, 0x3d0, 0x3d3, 0x3d5, 0x3d8, 0x3e0, 0x3e3, 0x3e7, 0x3ef, 0x3f1, 0x3f2, 0x3f3, 0x3f5, 0x3fb, 0x3fd, 0x3fe, 0x400, 0x402, 0x404, 0x411, 0x412, 0x413, 0x417, 0x419, 0x41a, 0x41b, 0x41c, 0x41d, 0x421, 0x425, 0x42b, 0x42d, 0x434, 0x437, 0x43b, 0x441, 0x44a, 0x450, 0x456, 0x460, 0x46a, 0x46c, 0x473, 0x479, 0x47f, 0x485, 0x488, 0x48e, 0x491, 0x499, 0x49a, 0x4a1, 0x4a2, 0x4a5, 0x4af, 0x4b5, 0x4bb, 0x4bc, 0x4c2, 0x4c5, 0x4cd, 0x4d4, 0x4db, 0x4dc, 0x4dd, 0x4de, 0x4df, 0x4e1, 0x4e3, 0x4e5, 0x4e9, 0x4ea, 0x4ec, 0x4ed, 0x4ee, 0x4f0, 0x4f5, 0x4fa, 0x4fe, 0x4ff, 0x502, 0x506, 0x511, 0x515, 0x51d, 0x522, 0x526, 0x529, 0x52d, 0x530, 0x533, 0x538, 0x53c, 0x540, 0x544, 0x548, 0x54a, 0x54c, 0x54f, 0x554, 0x556, 0x55b, 0x564, 0x569, 0x56a, 0x56d, 0x56e, 0x56f, 0x571, 0x572, 0x573} - -// sparseValues: 1395 entries, 5580 bytes -var sparseValues = [1395]valueRange{ - // Block 0x0, offset 0x0 - {value: 0x0004, lo: 0xa8, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xaa}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0004, lo: 0xaf, hi: 0xaf}, - {value: 0x0004, lo: 0xb4, hi: 0xb4}, - {value: 0x001a, lo: 0xb5, hi: 0xb5}, - {value: 0x0054, lo: 0xb7, hi: 0xb7}, - {value: 0x0004, lo: 0xb8, hi: 0xb8}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - // Block 0x1, offset 0x9 - {value: 0x2013, lo: 0x80, hi: 0x96}, - {value: 0x2013, lo: 0x98, hi: 0x9e}, - {value: 0x009a, lo: 0x9f, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xb6}, - {value: 0x2012, lo: 0xb8, hi: 0xbe}, - {value: 0x0252, lo: 0xbf, hi: 0xbf}, - // Block 0x2, offset 0xf - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x011b, lo: 0xb0, hi: 0xb0}, - {value: 0x019a, lo: 0xb1, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb7}, - {value: 0x0012, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x0553, lo: 0xbf, hi: 0xbf}, - // Block 0x3, offset 0x18 - {value: 0x0552, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x01da, lo: 0x89, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xb7}, - {value: 0x0253, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x028a, lo: 0xbf, hi: 0xbf}, - // Block 0x4, offset 0x24 - {value: 0x0117, lo: 0x80, hi: 0x9f}, - {value: 0x2f53, lo: 0xa0, hi: 0xa0}, - {value: 0x0012, lo: 0xa1, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xb3}, - {value: 0x0012, lo: 0xb4, hi: 0xb9}, - {value: 0x090b, lo: 0xba, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x2953, lo: 0xbd, hi: 0xbd}, - {value: 0x098b, lo: 0xbe, hi: 0xbe}, - {value: 0x0a0a, lo: 0xbf, hi: 0xbf}, - // Block 0x5, offset 0x2e - {value: 0x0015, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x97}, - {value: 0x0004, lo: 0x98, hi: 0x9d}, - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0015, lo: 0xa0, hi: 0xa4}, - {value: 0x0004, lo: 0xa5, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xbf}, - // Block 0x6, offset 0x35 - {value: 0x0024, lo: 0x80, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbf}, - // Block 0x7, offset 0x38 - {value: 0x6553, lo: 0x80, hi: 0x8f}, - {value: 0x2013, lo: 0x90, hi: 0x9f}, - {value: 0x5f53, lo: 0xa0, hi: 0xaf}, - {value: 0x2012, lo: 0xb0, hi: 0xbf}, - // Block 0x8, offset 0x3c - {value: 0x5f52, lo: 0x80, hi: 0x8f}, - {value: 0x6552, lo: 0x90, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x9, offset 0x3f - {value: 0x0117, lo: 0x80, hi: 0x81}, - {value: 0x0024, lo: 0x83, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xbf}, - // Block 0xa, offset 0x43 - {value: 0x0f13, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0716, lo: 0x8b, hi: 0x8c}, - {value: 0x0316, lo: 0x8d, hi: 0x8e}, - {value: 0x0f12, lo: 0x8f, hi: 0x8f}, - {value: 0x0117, lo: 0x90, hi: 0xbf}, - // Block 0xb, offset 0x4d - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x6553, lo: 0xb1, hi: 0xbf}, - // Block 0xc, offset 0x4f - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6853, lo: 0x90, hi: 0x96}, - {value: 0x0014, lo: 0x99, hi: 0x99}, - {value: 0x6552, lo: 0xa1, hi: 0xaf}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0xd, offset 0x54 - {value: 0x6852, lo: 0x80, hi: 0x86}, - {value: 0x198a, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0024, lo: 0x92, hi: 0x95}, - {value: 0x0034, lo: 0x96, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x99}, - {value: 0x0034, lo: 0x9a, hi: 0x9b}, - {value: 0x0024, lo: 0x9c, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa7}, - {value: 0x0024, lo: 0xa8, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xbd}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xe, offset 0x64 - {value: 0x0034, lo: 0x81, hi: 0x82}, - {value: 0x0024, lo: 0x84, hi: 0x84}, - {value: 0x0034, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb3}, - {value: 0x0054, lo: 0xb4, hi: 0xb4}, - // Block 0xf, offset 0x6b - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0024, lo: 0x90, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0014, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x10, offset 0x70 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9c}, - {value: 0x0024, lo: 0x9d, hi: 0x9e}, - {value: 0x0034, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x11, offset 0x7e - {value: 0x0010, lo: 0x80, hi: 0xbf}, - // Block 0x12, offset 0x7f - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0024, lo: 0x9f, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x13, offset 0x8d - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0034, lo: 0xb1, hi: 0xb1}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0024, lo: 0xbf, hi: 0xbf}, - // Block 0x14, offset 0x9c - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0024, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x88}, - {value: 0x0024, lo: 0x89, hi: 0x8a}, - {value: 0x0010, lo: 0x8d, hi: 0xbf}, - // Block 0x15, offset 0xa6 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x16, offset 0xa9 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xb1}, - {value: 0x0034, lo: 0xb2, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - // Block 0x17, offset 0xaf - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x99}, - {value: 0x0014, lo: 0x9a, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0xa3}, - {value: 0x0014, lo: 0xa4, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xad}, - // Block 0x18, offset 0xb7 - {value: 0x0010, lo: 0x80, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0xa0, hi: 0xaa}, - // Block 0x19, offset 0xba - {value: 0x0010, lo: 0xa0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbd}, - // Block 0x1a, offset 0xbc - {value: 0x0024, lo: 0x94, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0024, lo: 0xaa, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbf}, - // Block 0x1b, offset 0xca - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1c, offset 0xd0 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0x1d, offset 0xde - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb6, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1e, offset 0xe9 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xb1}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - // Block 0x1f, offset 0xf5 - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x20, offset 0x100 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x99, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x21, offset 0x10c - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x22, offset 0x116 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x85}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xbf}, - // Block 0x23, offset 0x122 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x24, offset 0x12d - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x25, offset 0x139 - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0010, lo: 0xa8, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x26, offset 0x145 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x27, offset 0x14d - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb9}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbf}, - // Block 0x28, offset 0x155 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x88}, - {value: 0x0014, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x29, offset 0x15f - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x2a, offset 0x16a - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb2}, - // Block 0x2b, offset 0x176 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x2c, offset 0x17d - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x94, hi: 0x97}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xba, hi: 0xbf}, - // Block 0x2d, offset 0x188 - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x96}, - {value: 0x0010, lo: 0x9a, hi: 0xb1}, - {value: 0x0010, lo: 0xb3, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x2e, offset 0x18d - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x94}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9f}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - // Block 0x2f, offset 0x195 - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - // Block 0x30, offset 0x198 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x31, offset 0x19d - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xb9}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - // Block 0x32, offset 0x1a1 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x33, offset 0x1a5 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0034, lo: 0x98, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0034, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x34, offset 0x1ac - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xac}, - {value: 0x0034, lo: 0xb1, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xba, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x35, offset 0x1b5 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0024, lo: 0x82, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x86, hi: 0x87}, - {value: 0x0010, lo: 0x88, hi: 0x8c}, - {value: 0x0014, lo: 0x8d, hi: 0x97}, - {value: 0x0014, lo: 0x99, hi: 0xbc}, - // Block 0x36, offset 0x1bd - {value: 0x0034, lo: 0x86, hi: 0x86}, - // Block 0x37, offset 0x1be - {value: 0x0010, lo: 0xab, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbe}, - // Block 0x38, offset 0x1c7 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x96, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x99}, - {value: 0x0014, lo: 0x9e, hi: 0xa0}, - {value: 0x0010, lo: 0xa2, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xad}, - {value: 0x0014, lo: 0xb1, hi: 0xb4}, - // Block 0x39, offset 0x1ce - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x6c53, lo: 0xa0, hi: 0xbf}, - // Block 0x3a, offset 0x1d6 - {value: 0x7053, lo: 0x80, hi: 0x85}, - {value: 0x7053, lo: 0x87, hi: 0x87}, - {value: 0x7053, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xba}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x3b, offset 0x1dc - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x9a, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x3c, offset 0x1e2 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x3d, offset 0x1e7 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x82, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3e, offset 0x1eb - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3f, offset 0x1ee - {value: 0x0010, lo: 0x80, hi: 0x9a}, - {value: 0x0024, lo: 0x9d, hi: 0x9f}, - // Block 0x40, offset 0x1f0 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x7453, lo: 0xa0, hi: 0xaf}, - {value: 0x7853, lo: 0xb0, hi: 0xbf}, - // Block 0x41, offset 0x1f3 - {value: 0x7c53, lo: 0x80, hi: 0x8f}, - {value: 0x8053, lo: 0x90, hi: 0x9f}, - {value: 0x7c53, lo: 0xa0, hi: 0xaf}, - {value: 0x0813, lo: 0xb0, hi: 0xb5}, - {value: 0x0892, lo: 0xb8, hi: 0xbd}, - // Block 0x42, offset 0x1f8 - {value: 0x0010, lo: 0x81, hi: 0xbf}, - // Block 0x43, offset 0x1f9 - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0010, lo: 0xaf, hi: 0xbf}, - // Block 0x44, offset 0x1fb - {value: 0x0010, lo: 0x81, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x45, offset 0x1fd - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb8}, - // Block 0x46, offset 0x1ff - {value: 0x0010, lo: 0x80, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0034, lo: 0x94, hi: 0x94}, - {value: 0x0010, lo: 0xa0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - // Block 0x47, offset 0x206 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xac}, - {value: 0x0010, lo: 0xae, hi: 0xb0}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - // Block 0x48, offset 0x20b - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x49, offset 0x20f - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x89, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0014, lo: 0x93, hi: 0x93}, - {value: 0x0004, lo: 0x97, hi: 0x97}, - {value: 0x0024, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0x4a, offset 0x218 - {value: 0x0014, lo: 0x8b, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x4b, offset 0x21b - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb7}, - // Block 0x4c, offset 0x21e - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x4d, offset 0x224 - {value: 0x0010, lo: 0x80, hi: 0xb5}, - // Block 0x4e, offset 0x225 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbb}, - // Block 0x4f, offset 0x230 - {value: 0x0010, lo: 0x86, hi: 0x8f}, - // Block 0x50, offset 0x231 - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x51, offset 0x232 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - // Block 0x52, offset 0x237 - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x9e}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xac}, - {value: 0x0010, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xbc}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x53, offset 0x244 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xa7, hi: 0xa7}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - {value: 0x0034, lo: 0xb5, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbc}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0x54, offset 0x24c - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x55, offset 0x254 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0030, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xab, hi: 0xab}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - {value: 0x0024, lo: 0xad, hi: 0xb3}, - // Block 0x56, offset 0x25d - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0030, lo: 0xaa, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbf}, - // Block 0x57, offset 0x266 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0030, lo: 0xb2, hi: 0xb3}, - // Block 0x58, offset 0x26f - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0x59, offset 0x274 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8d, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x5a, offset 0x277 - {value: 0x1a6a, lo: 0x80, hi: 0x80}, - {value: 0x1aea, lo: 0x81, hi: 0x81}, - {value: 0x1b6a, lo: 0x82, hi: 0x82}, - {value: 0x1bea, lo: 0x83, hi: 0x83}, - {value: 0x1c6a, lo: 0x84, hi: 0x84}, - {value: 0x1cea, lo: 0x85, hi: 0x85}, - {value: 0x1d6a, lo: 0x86, hi: 0x86}, - {value: 0x1dea, lo: 0x87, hi: 0x87}, - {value: 0x1e6a, lo: 0x88, hi: 0x88}, - // Block 0x5b, offset 0x280 - {value: 0x0024, lo: 0x90, hi: 0x92}, - {value: 0x0034, lo: 0x94, hi: 0x99}, - {value: 0x0024, lo: 0x9a, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9f}, - {value: 0x0024, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xb3}, - {value: 0x0024, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb7}, - {value: 0x0024, lo: 0xb8, hi: 0xb9}, - // Block 0x5c, offset 0x28d - {value: 0x0012, lo: 0x80, hi: 0xab}, - {value: 0x0015, lo: 0xac, hi: 0xbf}, - // Block 0x5d, offset 0x28f - {value: 0x0015, lo: 0x80, hi: 0xaa}, - {value: 0x0012, lo: 0xab, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb8}, - {value: 0x8452, lo: 0xb9, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbc}, - {value: 0x8852, lo: 0xbd, hi: 0xbd}, - {value: 0x0012, lo: 0xbe, hi: 0xbf}, - // Block 0x5e, offset 0x296 - {value: 0x0012, lo: 0x80, hi: 0x9a}, - {value: 0x0015, lo: 0x9b, hi: 0xbf}, - // Block 0x5f, offset 0x298 - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0024, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb9}, - {value: 0x0024, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbd}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x60, offset 0x2a4 - {value: 0x0117, lo: 0x80, hi: 0xbf}, - // Block 0x61, offset 0x2a5 - {value: 0x0117, lo: 0x80, hi: 0x95}, - {value: 0x1f1a, lo: 0x96, hi: 0x96}, - {value: 0x1fca, lo: 0x97, hi: 0x97}, - {value: 0x207a, lo: 0x98, hi: 0x98}, - {value: 0x212a, lo: 0x99, hi: 0x99}, - {value: 0x21da, lo: 0x9a, hi: 0x9a}, - {value: 0x228a, lo: 0x9b, hi: 0x9b}, - {value: 0x0012, lo: 0x9c, hi: 0x9d}, - {value: 0x233b, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0x9f, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x62, offset 0x2b0 - {value: 0x0812, lo: 0x80, hi: 0x87}, - {value: 0x0813, lo: 0x88, hi: 0x8f}, - {value: 0x0812, lo: 0x90, hi: 0x95}, - {value: 0x0813, lo: 0x98, hi: 0x9d}, - {value: 0x0812, lo: 0xa0, hi: 0xa7}, - {value: 0x0813, lo: 0xa8, hi: 0xaf}, - {value: 0x0812, lo: 0xb0, hi: 0xb7}, - {value: 0x0813, lo: 0xb8, hi: 0xbf}, - // Block 0x63, offset 0x2b8 - {value: 0x0004, lo: 0x8b, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8f}, - {value: 0x0054, lo: 0x98, hi: 0x99}, - {value: 0x0054, lo: 0xa4, hi: 0xa4}, - {value: 0x0054, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xaa, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xaf}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x64, offset 0x2c0 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x94, hi: 0x94}, - {value: 0x0014, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa6, hi: 0xaf}, - {value: 0x0015, lo: 0xb1, hi: 0xb1}, - {value: 0x0015, lo: 0xbf, hi: 0xbf}, - // Block 0x65, offset 0x2c6 - {value: 0x0015, lo: 0x90, hi: 0x9c}, - // Block 0x66, offset 0x2c7 - {value: 0x0024, lo: 0x90, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0xa0}, - {value: 0x0024, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa4}, - {value: 0x0034, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - // Block 0x67, offset 0x2d5 - {value: 0x0016, lo: 0x85, hi: 0x86}, - {value: 0x0012, lo: 0x87, hi: 0x89}, - {value: 0x9d52, lo: 0x8e, hi: 0x8e}, - {value: 0x1013, lo: 0xa0, hi: 0xaf}, - {value: 0x1012, lo: 0xb0, hi: 0xbf}, - // Block 0x68, offset 0x2da - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x88}, - // Block 0x69, offset 0x2dd - {value: 0xa053, lo: 0xb6, hi: 0xb7}, - {value: 0xa353, lo: 0xb8, hi: 0xb9}, - {value: 0xa653, lo: 0xba, hi: 0xbb}, - {value: 0xa353, lo: 0xbc, hi: 0xbd}, - {value: 0xa053, lo: 0xbe, hi: 0xbf}, - // Block 0x6a, offset 0x2e2 - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6553, lo: 0x90, hi: 0x9f}, - {value: 0xa953, lo: 0xa0, hi: 0xae}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0x6b, offset 0x2e6 - {value: 0x0117, lo: 0x80, hi: 0xa3}, - {value: 0x0012, lo: 0xa4, hi: 0xa4}, - {value: 0x0716, lo: 0xab, hi: 0xac}, - {value: 0x0316, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb3}, - // Block 0x6c, offset 0x2ec - {value: 0x6c52, lo: 0x80, hi: 0x9f}, - {value: 0x7052, lo: 0xa0, hi: 0xa5}, - {value: 0x7052, lo: 0xa7, hi: 0xa7}, - {value: 0x7052, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x6d, offset 0x2f1 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x6e, offset 0x2f4 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0010, lo: 0xb0, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x6f, offset 0x2f9 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9e}, - {value: 0x0024, lo: 0xa0, hi: 0xbf}, - // Block 0x70, offset 0x2fe - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - // Block 0x71, offset 0x2ff - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0xaa, hi: 0xad}, - {value: 0x0030, lo: 0xae, hi: 0xaf}, - {value: 0x0004, lo: 0xb1, hi: 0xb5}, - {value: 0x0014, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - // Block 0x72, offset 0x305 - {value: 0x0034, lo: 0x99, hi: 0x9a}, - {value: 0x0004, lo: 0x9b, hi: 0x9e}, - // Block 0x73, offset 0x307 - {value: 0x0004, lo: 0xbc, hi: 0xbe}, - // Block 0x74, offset 0x308 - {value: 0x0010, lo: 0x85, hi: 0xae}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x75, offset 0x30a - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0010, lo: 0xa0, hi: 0xba}, - // Block 0x76, offset 0x30c - {value: 0x0010, lo: 0x80, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0xbf}, - // Block 0x77, offset 0x30f - {value: 0x0010, lo: 0x80, hi: 0x8c}, - // Block 0x78, offset 0x310 - {value: 0x0010, lo: 0x90, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x79, offset 0x312 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0xab}, - // Block 0x7a, offset 0x315 - {value: 0x0117, lo: 0x80, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb2}, - {value: 0x0024, lo: 0xb4, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x7b, offset 0x31b - {value: 0x0117, lo: 0x80, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9d}, - {value: 0x0024, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x7c, offset 0x31f - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb1}, - // Block 0x7d, offset 0x321 - {value: 0x0004, lo: 0x80, hi: 0x96}, - {value: 0x0014, lo: 0x97, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xaf}, - {value: 0x0012, lo: 0xb0, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xbf}, - // Block 0x7e, offset 0x326 - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x0015, lo: 0xb0, hi: 0xb0}, - {value: 0x0012, lo: 0xb1, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x8453, lo: 0xbd, hi: 0xbd}, - {value: 0x0117, lo: 0xbe, hi: 0xbf}, - // Block 0x7f, offset 0x32d - {value: 0x0010, lo: 0xb7, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbf}, - // Block 0x80, offset 0x331 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x8c, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - // Block 0x81, offset 0x33a - {value: 0x0010, lo: 0x80, hi: 0xb3}, - // Block 0x82, offset 0x33b - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xa0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb7}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x83, offset 0x343 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x84, offset 0x347 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0x92}, - {value: 0x0030, lo: 0x93, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0x85, offset 0x34c - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x86, offset 0x354 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0004, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x87, offset 0x35a - {value: 0x0010, lo: 0x80, hi: 0xa8}, - {value: 0x0014, lo: 0xa9, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0x88, offset 0x360 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x89, offset 0x36a - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0024, lo: 0xbe, hi: 0xbf}, - // Block 0x8a, offset 0x36f - {value: 0x0024, lo: 0x81, hi: 0x81}, - {value: 0x0004, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - // Block 0x8b, offset 0x378 - {value: 0x0010, lo: 0x81, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x8e}, - {value: 0x0010, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x8c, offset 0x37e - {value: 0x0012, lo: 0x80, hi: 0x92}, - {value: 0xac52, lo: 0x93, hi: 0x93}, - {value: 0x0012, lo: 0x94, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa5}, - {value: 0x74d2, lo: 0xb0, hi: 0xbf}, - // Block 0x8d, offset 0x385 - {value: 0x78d2, lo: 0x80, hi: 0x8f}, - {value: 0x7cd2, lo: 0x90, hi: 0x9f}, - {value: 0x80d2, lo: 0xa0, hi: 0xaf}, - {value: 0x7cd2, lo: 0xb0, hi: 0xbf}, - // Block 0x8e, offset 0x389 - {value: 0x0010, lo: 0x80, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x8f, offset 0x391 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x90, offset 0x393 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x8b, hi: 0xbb}, - // Block 0x91, offset 0x395 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0xbf}, - // Block 0x92, offset 0x398 - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0004, lo: 0xb2, hi: 0xbf}, - // Block 0x93, offset 0x39a - {value: 0x0004, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x93, hi: 0xbf}, - // Block 0x94, offset 0x39c - {value: 0x0010, lo: 0x80, hi: 0xbd}, - // Block 0x95, offset 0x39d - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0x96, offset 0x39e - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0xbf}, - // Block 0x97, offset 0x3a0 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0xb0, hi: 0xbb}, - // Block 0x98, offset 0x3a2 - {value: 0x0014, lo: 0x80, hi: 0x8f}, - {value: 0x0054, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0xa0, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xad}, - {value: 0x0024, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - // Block 0x99, offset 0x3a8 - {value: 0x0010, lo: 0x8d, hi: 0x8f}, - {value: 0x0054, lo: 0x92, hi: 0x92}, - {value: 0x0054, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0xb0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0x9a, offset 0x3ad - {value: 0x0010, lo: 0x80, hi: 0xbc}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x9b, offset 0x3af - {value: 0x0054, lo: 0x87, hi: 0x87}, - {value: 0x0054, lo: 0x8e, hi: 0x8e}, - {value: 0x0054, lo: 0x9a, hi: 0x9a}, - {value: 0x5f53, lo: 0xa1, hi: 0xba}, - {value: 0x0004, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9c, offset 0x3b5 - {value: 0x0004, lo: 0x80, hi: 0x80}, - {value: 0x5f52, lo: 0x81, hi: 0x9a}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - // Block 0x9d, offset 0x3b8 - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbe}, - // Block 0x9e, offset 0x3ba - {value: 0x0010, lo: 0x82, hi: 0x87}, - {value: 0x0010, lo: 0x8a, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0x97}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0004, lo: 0xa3, hi: 0xa3}, - {value: 0x0014, lo: 0xb9, hi: 0xbb}, - // Block 0x9f, offset 0x3c0 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0010, lo: 0x8d, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xba}, - {value: 0x0010, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xa0, offset 0x3c5 - {value: 0x0010, lo: 0x80, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x9d}, - // Block 0xa1, offset 0x3c7 - {value: 0x0010, lo: 0x80, hi: 0xba}, - // Block 0xa2, offset 0x3c8 - {value: 0x0010, lo: 0x80, hi: 0xb4}, - // Block 0xa3, offset 0x3c9 - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0xa4, offset 0x3ca - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa5, offset 0x3cc - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - // Block 0xa6, offset 0x3ce - {value: 0x0010, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xad, hi: 0xbf}, - // Block 0xa7, offset 0x3d0 - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0xb5}, - {value: 0x0024, lo: 0xb6, hi: 0xba}, - // Block 0xa8, offset 0x3d3 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa9, offset 0x3d5 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x91, hi: 0x95}, - // Block 0xaa, offset 0x3d8 - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x97}, - {value: 0xaf53, lo: 0x98, hi: 0x9f}, - {value: 0xb253, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbf}, - // Block 0xab, offset 0x3e0 - {value: 0xaf52, lo: 0x80, hi: 0x87}, - {value: 0xb252, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xac, offset 0x3e3 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0xb253, lo: 0xb0, hi: 0xb7}, - {value: 0xaf53, lo: 0xb8, hi: 0xbf}, - // Block 0xad, offset 0x3e7 - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x93}, - {value: 0xb252, lo: 0x98, hi: 0x9f}, - {value: 0xaf52, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbb}, - // Block 0xae, offset 0x3ef - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xaf, offset 0x3f1 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - // Block 0xb0, offset 0x3f2 - {value: 0x0010, lo: 0x80, hi: 0xb6}, - // Block 0xb1, offset 0x3f3 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - // Block 0xb2, offset 0x3f5 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xb3, offset 0x3fb - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xb4, offset 0x3fd - {value: 0x0010, lo: 0x80, hi: 0x9e}, - // Block 0xb5, offset 0x3fe - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - // Block 0xb6, offset 0x400 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb9}, - // Block 0xb7, offset 0x402 - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0xb8, offset 0x404 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x8e, hi: 0x8e}, - {value: 0x0024, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x99, hi: 0xb3}, - {value: 0x0024, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xb9, offset 0x411 - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0xba, offset 0x412 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - // Block 0xbb, offset 0x413 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - // Block 0xbc, offset 0x417 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - // Block 0xbd, offset 0x419 - {value: 0x0010, lo: 0x80, hi: 0x91}, - // Block 0xbe, offset 0x41a - {value: 0x0010, lo: 0x80, hi: 0x88}, - // Block 0xbf, offset 0x41b - {value: 0x5653, lo: 0x80, hi: 0xb2}, - // Block 0xc0, offset 0x41c - {value: 0x5652, lo: 0x80, hi: 0xb2}, - // Block 0xc1, offset 0x41d - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xc2, offset 0x421 - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xc3, offset 0x425 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - // Block 0xc4, offset 0x42b - {value: 0x0010, lo: 0x90, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc5, offset 0x42d - {value: 0x0024, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0xc6, offset 0x434 - {value: 0x0010, lo: 0x90, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - // Block 0xc7, offset 0x437 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xc8, offset 0x43b - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - // Block 0xc9, offset 0x441 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb4}, - {value: 0x0030, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xb7}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0xca, offset 0x44a - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xcb, offset 0x450 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa2}, - {value: 0x0014, lo: 0xa3, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xcc, offset 0x456 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xcd, offset 0x460 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0030, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9d, hi: 0xa3}, - {value: 0x0024, lo: 0xa6, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - // Block 0xce, offset 0x46a - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xcf, offset 0x46c - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd0, offset 0x473 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xd1, offset 0x479 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd2, offset 0x47f - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd3, offset 0x485 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x98, hi: 0x9b}, - {value: 0x0014, lo: 0x9c, hi: 0x9d}, - // Block 0xd4, offset 0x488 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd5, offset 0x48e - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd6, offset 0x491 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0014, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb5}, - {value: 0x0030, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0xd7, offset 0x499 - {value: 0x0010, lo: 0x80, hi: 0x89}, - // Block 0xd8, offset 0x49a - {value: 0x0014, lo: 0x9d, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xd9, offset 0x4a1 - {value: 0x5f53, lo: 0xa0, hi: 0xbf}, - // Block 0xda, offset 0x4a2 - {value: 0x5f52, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xdb, offset 0x4a5 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x89, hi: 0x8a}, - {value: 0x0010, lo: 0x8b, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbe}, - // Block 0xdc, offset 0x4af - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0014, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x98}, - {value: 0x0014, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0xbf}, - // Block 0xdd, offset 0x4b5 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x86, hi: 0x89}, - {value: 0x0014, lo: 0x8a, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x99}, - // Block 0xde, offset 0x4bb - {value: 0x0010, lo: 0x80, hi: 0xb8}, - // Block 0xdf, offset 0x4bc - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xe0, offset 0x4c2 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0xe1, offset 0x4c5 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0014, lo: 0x92, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xa9}, - {value: 0x0014, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0xe2, offset 0x4cd - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb6}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xe3, offset 0x4d4 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xe4, offset 0x4db - {value: 0x0010, lo: 0x80, hi: 0x99}, - // Block 0xe5, offset 0x4dc - {value: 0x0010, lo: 0x80, hi: 0xae}, - // Block 0xe6, offset 0x4dd - {value: 0x0010, lo: 0x80, hi: 0x83}, - // Block 0xe7, offset 0x4de - {value: 0x0010, lo: 0x80, hi: 0x86}, - // Block 0xe8, offset 0x4df - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xe9, offset 0x4e1 - {value: 0x0010, lo: 0x90, hi: 0xad}, - {value: 0x0034, lo: 0xb0, hi: 0xb4}, - // Block 0xea, offset 0x4e3 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - // Block 0xeb, offset 0x4e5 - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa3, hi: 0xb7}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xec, offset 0x4e9 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - // Block 0xed, offset 0x4ea - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0xbe}, - // Block 0xee, offset 0x4ec - {value: 0x0014, lo: 0x8f, hi: 0x9f}, - // Block 0xef, offset 0x4ed - {value: 0x0014, lo: 0xa0, hi: 0xa1}, - // Block 0xf0, offset 0x4ee - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbc}, - // Block 0xf1, offset 0x4f0 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0034, lo: 0x9e, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa3}, - // Block 0xf2, offset 0x4f5 - {value: 0x0030, lo: 0xa5, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xa9}, - {value: 0x0030, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbf}, - // Block 0xf3, offset 0x4fa - {value: 0x0034, lo: 0x80, hi: 0x82}, - {value: 0x0024, lo: 0x85, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8b}, - {value: 0x0024, lo: 0xaa, hi: 0xad}, - // Block 0xf4, offset 0x4fe - {value: 0x0024, lo: 0x82, hi: 0x84}, - // Block 0xf5, offset 0x4ff - {value: 0x0013, lo: 0x80, hi: 0x99}, - {value: 0x0012, lo: 0x9a, hi: 0xb3}, - {value: 0x0013, lo: 0xb4, hi: 0xbf}, - // Block 0xf6, offset 0x502 - {value: 0x0013, lo: 0x80, hi: 0x8d}, - {value: 0x0012, lo: 0x8e, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0xa7}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0xf7, offset 0x506 - {value: 0x0013, lo: 0x80, hi: 0x81}, - {value: 0x0012, lo: 0x82, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0x9c}, - {value: 0x0013, lo: 0x9e, hi: 0x9f}, - {value: 0x0013, lo: 0xa2, hi: 0xa2}, - {value: 0x0013, lo: 0xa5, hi: 0xa6}, - {value: 0x0013, lo: 0xa9, hi: 0xac}, - {value: 0x0013, lo: 0xae, hi: 0xb5}, - {value: 0x0012, lo: 0xb6, hi: 0xb9}, - {value: 0x0012, lo: 0xbb, hi: 0xbb}, - {value: 0x0012, lo: 0xbd, hi: 0xbf}, - // Block 0xf8, offset 0x511 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0012, lo: 0x85, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0xf9, offset 0x515 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0013, lo: 0x84, hi: 0x85}, - {value: 0x0013, lo: 0x87, hi: 0x8a}, - {value: 0x0013, lo: 0x8d, hi: 0x94}, - {value: 0x0013, lo: 0x96, hi: 0x9c}, - {value: 0x0012, lo: 0x9e, hi: 0xb7}, - {value: 0x0013, lo: 0xb8, hi: 0xb9}, - {value: 0x0013, lo: 0xbb, hi: 0xbe}, - // Block 0xfa, offset 0x51d - {value: 0x0013, lo: 0x80, hi: 0x84}, - {value: 0x0013, lo: 0x86, hi: 0x86}, - {value: 0x0013, lo: 0x8a, hi: 0x90}, - {value: 0x0012, lo: 0x92, hi: 0xab}, - {value: 0x0013, lo: 0xac, hi: 0xbf}, - // Block 0xfb, offset 0x522 - {value: 0x0013, lo: 0x80, hi: 0x85}, - {value: 0x0012, lo: 0x86, hi: 0x9f}, - {value: 0x0013, lo: 0xa0, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbf}, - // Block 0xfc, offset 0x526 - {value: 0x0012, lo: 0x80, hi: 0x93}, - {value: 0x0013, lo: 0x94, hi: 0xad}, - {value: 0x0012, lo: 0xae, hi: 0xbf}, - // Block 0xfd, offset 0x529 - {value: 0x0012, lo: 0x80, hi: 0x87}, - {value: 0x0013, lo: 0x88, hi: 0xa1}, - {value: 0x0012, lo: 0xa2, hi: 0xbb}, - {value: 0x0013, lo: 0xbc, hi: 0xbf}, - // Block 0xfe, offset 0x52d - {value: 0x0013, lo: 0x80, hi: 0x95}, - {value: 0x0012, lo: 0x96, hi: 0xaf}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0xff, offset 0x530 - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0012, lo: 0x8a, hi: 0xa5}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x100, offset 0x533 - {value: 0x0013, lo: 0x80, hi: 0x80}, - {value: 0x0012, lo: 0x82, hi: 0x9a}, - {value: 0x0012, lo: 0x9c, hi: 0xa1}, - {value: 0x0013, lo: 0xa2, hi: 0xba}, - {value: 0x0012, lo: 0xbc, hi: 0xbf}, - // Block 0x101, offset 0x538 - {value: 0x0012, lo: 0x80, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0xb4}, - {value: 0x0012, lo: 0xb6, hi: 0xbf}, - // Block 0x102, offset 0x53c - {value: 0x0012, lo: 0x80, hi: 0x8e}, - {value: 0x0012, lo: 0x90, hi: 0x95}, - {value: 0x0013, lo: 0x96, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x103, offset 0x540 - {value: 0x0012, lo: 0x80, hi: 0x88}, - {value: 0x0012, lo: 0x8a, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x104, offset 0x544 - {value: 0x0012, lo: 0x80, hi: 0x82}, - {value: 0x0012, lo: 0x84, hi: 0x89}, - {value: 0x0017, lo: 0x8a, hi: 0x8b}, - {value: 0x0010, lo: 0x8e, hi: 0xbf}, - // Block 0x105, offset 0x548 - {value: 0x0014, lo: 0x80, hi: 0xb6}, - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x106, offset 0x54a - {value: 0x0014, lo: 0x80, hi: 0xac}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x107, offset 0x54c - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x9b, hi: 0x9f}, - {value: 0x0014, lo: 0xa1, hi: 0xaf}, - // Block 0x108, offset 0x54f - {value: 0x0024, lo: 0x80, hi: 0x86}, - {value: 0x0024, lo: 0x88, hi: 0x98}, - {value: 0x0024, lo: 0x9b, hi: 0xa1}, - {value: 0x0024, lo: 0xa3, hi: 0xa4}, - {value: 0x0024, lo: 0xa6, hi: 0xaa}, - // Block 0x109, offset 0x554 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0034, lo: 0x90, hi: 0x96}, - // Block 0x10a, offset 0x556 - {value: 0xb552, lo: 0x80, hi: 0x81}, - {value: 0xb852, lo: 0x82, hi: 0x83}, - {value: 0x0024, lo: 0x84, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x10b, offset 0x55b - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x9f}, - {value: 0x0010, lo: 0xa1, hi: 0xa2}, - {value: 0x0010, lo: 0xa4, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb7}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - // Block 0x10c, offset 0x564 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x9b}, - {value: 0x0010, lo: 0xa1, hi: 0xa3}, - {value: 0x0010, lo: 0xa5, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xbb}, - // Block 0x10d, offset 0x569 - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x10e, offset 0x56a - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x10f, offset 0x56d - {value: 0x0013, lo: 0x80, hi: 0x89}, - // Block 0x110, offset 0x56e - {value: 0x0004, lo: 0xbb, hi: 0xbf}, - // Block 0x111, offset 0x56f - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0014, lo: 0xa0, hi: 0xbf}, - // Block 0x112, offset 0x571 - {value: 0x0014, lo: 0x80, hi: 0xbf}, - // Block 0x113, offset 0x572 - {value: 0x0014, lo: 0x80, hi: 0xaf}, -} - -// Total table size 14177 bytes (13KiB); checksum: F17D40E8 diff --git a/vendor/golang.org/x/text/cases/tables11.0.0.go b/vendor/golang.org/x/text/cases/tables11.0.0.go deleted file mode 100644 index ce00ce37..00000000 --- a/vendor/golang.org/x/text/cases/tables11.0.0.go +++ /dev/null @@ -1,2316 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -//go:build go1.13 && !go1.14 - -package cases - -// UnicodeVersion is the Unicode version from which the tables in this package are derived. -const UnicodeVersion = "11.0.0" - -var xorData string = "" + // Size: 188 bytes - "\x00\x06\x07\x00\x01?\x00\x0f\x03\x00\x0f\x12\x00\x0f\x1f\x00\x0f\x1d" + - "\x00\x01\x13\x00\x0f\x16\x00\x0f\x0b\x00\x0f3\x00\x0f7\x00\x01#\x00\x0f?" + - "\x00\x0e'\x00\x0f/\x00\x0e>\x00\x0f*\x00\x0c&\x00\x0c*\x00\x0c;\x00\x0c9" + - "\x00\x0c%\x00\x01\x08\x00\x03\x0d\x00\x03\x09\x00\x02\x06\x00\x02\x02" + - "\x00\x02\x0c\x00\x01\x00\x00\x01\x03\x00\x01\x01\x00\x01 \x00\x01\x0c" + - "\x00\x01\x10\x00\x03\x10\x00\x036 \x00\x037 \x00\x0b#\x10\x00\x0b 0\x00" + - "\x0b!\x10\x00\x0b!0\x001\x00\x00\x0b(\x04\x00\x03\x04\x1e\x00\x03\x0a" + - "\x00\x02:\x00\x02>\x00\x02,\x00\x02\x00\x00\x02\x10\x00\x01<\x00\x01&" + - "\x00\x01*\x00\x01.\x00\x010\x003 \x00\x01\x18\x00\x01(\x00\x01\x1e\x00" + - "\x01\x22" - -var exceptions string = "" + // Size: 2436 bytes - "\x00\x12\x12μΜΜ\x12\x12ssSSSs\x13\x18i̇i̇\x10\x09II\x13\x1bʼnʼNʼN\x11" + - "\x09sSS\x12\x12dždžDž\x12\x12dždžDŽ\x10\x12DŽDž\x12\x12ljljLj\x12\x12ljljLJ\x10\x12LJLj" + - "\x12\x12njnjNj\x12\x12njnjNJ\x10\x12NJNj\x13\x1bǰJ̌J̌\x12\x12dzdzDz\x12\x12dzdzDZ\x10" + - "\x12DZDz\x13\x18ⱥⱥ\x13\x18ⱦⱦ\x10\x1bⱾⱾ\x10\x1bⱿⱿ\x10\x1bⱯⱯ\x10\x1bⱭⱭ\x10" + - "\x1bⱰⱰ\x10\x1bꞫꞫ\x10\x1bꞬꞬ\x10\x1bꞍꞍ\x10\x1bꞪꞪ\x10\x1bꞮꞮ\x10\x1bⱢⱢ\x10" + - "\x1bꞭꞭ\x10\x1bⱮⱮ\x10\x1bⱤⱤ\x10\x1bꞱꞱ\x10\x1bꞲꞲ\x10\x1bꞰꞰ2\x12ιΙΙ\x166ΐ" + - "Ϊ́Ϊ́\x166ΰΫ́Ϋ́\x12\x12σΣΣ\x12\x12βΒΒ\x12\x12θΘΘ\x12\x12φΦΦ\x12" + - "\x12πΠΠ\x12\x12κΚΚ\x12\x12ρΡΡ\x12\x12εΕΕ\x14$եւԵՒԵւ\x10\x1bᲐა\x10\x1bᲑბ" + - "\x10\x1bᲒგ\x10\x1bᲓდ\x10\x1bᲔე\x10\x1bᲕვ\x10\x1bᲖზ\x10\x1bᲗთ\x10\x1bᲘი" + - "\x10\x1bᲙკ\x10\x1bᲚლ\x10\x1bᲛმ\x10\x1bᲜნ\x10\x1bᲝო\x10\x1bᲞპ\x10\x1bᲟჟ" + - "\x10\x1bᲠრ\x10\x1bᲡს\x10\x1bᲢტ\x10\x1bᲣუ\x10\x1bᲤფ\x10\x1bᲥქ\x10\x1bᲦღ" + - "\x10\x1bᲧყ\x10\x1bᲨშ\x10\x1bᲩჩ\x10\x1bᲪც\x10\x1bᲫძ\x10\x1bᲬწ\x10\x1bᲭჭ" + - "\x10\x1bᲮხ\x10\x1bᲯჯ\x10\x1bᲰჰ\x10\x1bᲱჱ\x10\x1bᲲჲ\x10\x1bᲳჳ\x10\x1bᲴჴ" + - "\x10\x1bᲵჵ\x10\x1bᲶჶ\x10\x1bᲷჷ\x10\x1bᲸჸ\x10\x1bᲹჹ\x10\x1bᲺჺ\x10\x1bᲽჽ" + - "\x10\x1bᲾჾ\x10\x1bᲿჿ\x12\x12вВВ\x12\x12дДД\x12\x12оОО\x12\x12сСС\x12\x12" + - "тТТ\x12\x12тТТ\x12\x12ъЪЪ\x12\x12ѣѢѢ\x13\x1bꙋꙊꙊ\x13\x1bẖH̱H̱\x13\x1bẗ" + - "T̈T̈\x13\x1bẘW̊W̊\x13\x1bẙY̊Y̊\x13\x1baʾAʾAʾ\x13\x1bṡṠṠ\x12\x10ssß\x14" + - "$ὐΥ̓Υ̓\x166ὒΥ̓̀Υ̓̀\x166ὔΥ̓́Υ̓́\x166ὖΥ̓͂Υ̓͂\x15+ἀιἈΙᾈ\x15+ἁιἉΙᾉ" + - "\x15+ἂιἊΙᾊ\x15+ἃιἋΙᾋ\x15+ἄιἌΙᾌ\x15+ἅιἍΙᾍ\x15+ἆιἎΙᾎ\x15+ἇιἏΙᾏ\x15\x1dἀιᾀἈ" + - "Ι\x15\x1dἁιᾁἉΙ\x15\x1dἂιᾂἊΙ\x15\x1dἃιᾃἋΙ\x15\x1dἄιᾄἌΙ\x15\x1dἅιᾅἍΙ\x15" + - "\x1dἆιᾆἎΙ\x15\x1dἇιᾇἏΙ\x15+ἠιἨΙᾘ\x15+ἡιἩΙᾙ\x15+ἢιἪΙᾚ\x15+ἣιἫΙᾛ\x15+ἤιἬΙᾜ" + - "\x15+ἥιἭΙᾝ\x15+ἦιἮΙᾞ\x15+ἧιἯΙᾟ\x15\x1dἠιᾐἨΙ\x15\x1dἡιᾑἩΙ\x15\x1dἢιᾒἪΙ" + - "\x15\x1dἣιᾓἫΙ\x15\x1dἤιᾔἬΙ\x15\x1dἥιᾕἭΙ\x15\x1dἦιᾖἮΙ\x15\x1dἧιᾗἯΙ\x15+ὠι" + - "ὨΙᾨ\x15+ὡιὩΙᾩ\x15+ὢιὪΙᾪ\x15+ὣιὫΙᾫ\x15+ὤιὬΙᾬ\x15+ὥιὭΙᾭ\x15+ὦιὮΙᾮ\x15+ὧι" + - "ὯΙᾯ\x15\x1dὠιᾠὨΙ\x15\x1dὡιᾡὩΙ\x15\x1dὢιᾢὪΙ\x15\x1dὣιᾣὫΙ\x15\x1dὤιᾤὬΙ" + - "\x15\x1dὥιᾥὭΙ\x15\x1dὦιᾦὮΙ\x15\x1dὧιᾧὯΙ\x15-ὰιᾺΙᾺͅ\x14#αιΑΙᾼ\x14$άιΆΙΆͅ" + - "\x14$ᾶΑ͂Α͂\x166ᾶιΑ͂Ιᾼ͂\x14\x1cαιᾳΑΙ\x12\x12ιΙΙ\x15-ὴιῊΙῊͅ\x14#ηιΗΙῌ" + - "\x14$ήιΉΙΉͅ\x14$ῆΗ͂Η͂\x166ῆιΗ͂Ιῌ͂\x14\x1cηιῃΗΙ\x166ῒΪ̀Ϊ̀\x166ΐΙ" + - "̈́Ϊ́\x14$ῖΙ͂Ι͂\x166ῗΪ͂Ϊ͂\x166ῢΫ̀Ϋ̀\x166ΰΫ́Ϋ́\x14$ῤΡ̓Ρ̓" + - "\x14$ῦΥ͂Υ͂\x166ῧΫ͂Ϋ͂\x15-ὼιῺΙῺͅ\x14#ωιΩΙῼ\x14$ώιΏΙΏͅ\x14$ῶΩ͂Ω͂\x16" + - "6ῶιΩ͂Ιῼ͂\x14\x1cωιῳΩΙ\x12\x10ωω\x11\x08kk\x12\x10åå\x12\x10ɫɫ\x12\x10ɽ" + - "ɽ\x10\x12ȺȺ\x10\x12ȾȾ\x12\x10ɑɑ\x12\x10ɱɱ\x12\x10ɐɐ\x12\x10ɒɒ\x12\x10ȿȿ" + - "\x12\x10ɀɀ\x12\x10ɥɥ\x12\x10ɦɦ\x12\x10ɜɜ\x12\x10ɡɡ\x12\x10ɬɬ\x12\x10ɪɪ" + - "\x12\x10ʞʞ\x12\x10ʇʇ\x12\x10ʝʝ\x12\x12ffFFFf\x12\x12fiFIFi\x12\x12flFLFl" + - "\x13\x1bffiFFIFfi\x13\x1bfflFFLFfl\x12\x12stSTSt\x12\x12stSTSt\x14$մնՄՆՄ" + - "ն\x14$մեՄԵՄե\x14$միՄԻՄի\x14$վնՎՆՎն\x14$մխՄԽՄխ" - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookup(s []byte) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupUnsafe(s []byte) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookupString(s string) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupStringUnsafe(s string) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// caseTrie. Total size: 12250 bytes (11.96 KiB). Checksum: 53ff6cb7321675e1. -type caseTrie struct{} - -func newCaseTrie(i int) *caseTrie { - return &caseTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *caseTrie) lookupValue(n uint32, b byte) uint16 { - switch { - case n < 20: - return uint16(caseValues[n<<6+uint32(b)]) - default: - n -= 20 - return uint16(sparse.lookup(n, b)) - } -} - -// caseValues: 22 blocks, 1408 entries, 2816 bytes -// The third block is the zero block. -var caseValues = [1408]uint16{ - // Block 0x0, offset 0x0 - 0x27: 0x0054, - 0x2e: 0x0054, - 0x30: 0x0010, 0x31: 0x0010, 0x32: 0x0010, 0x33: 0x0010, 0x34: 0x0010, 0x35: 0x0010, - 0x36: 0x0010, 0x37: 0x0010, 0x38: 0x0010, 0x39: 0x0010, 0x3a: 0x0054, - // Block 0x1, offset 0x40 - 0x41: 0x2013, 0x42: 0x2013, 0x43: 0x2013, 0x44: 0x2013, 0x45: 0x2013, - 0x46: 0x2013, 0x47: 0x2013, 0x48: 0x2013, 0x49: 0x2013, 0x4a: 0x2013, 0x4b: 0x2013, - 0x4c: 0x2013, 0x4d: 0x2013, 0x4e: 0x2013, 0x4f: 0x2013, 0x50: 0x2013, 0x51: 0x2013, - 0x52: 0x2013, 0x53: 0x2013, 0x54: 0x2013, 0x55: 0x2013, 0x56: 0x2013, 0x57: 0x2013, - 0x58: 0x2013, 0x59: 0x2013, 0x5a: 0x2013, - 0x5e: 0x0004, 0x5f: 0x0010, 0x60: 0x0004, 0x61: 0x2012, 0x62: 0x2012, 0x63: 0x2012, - 0x64: 0x2012, 0x65: 0x2012, 0x66: 0x2012, 0x67: 0x2012, 0x68: 0x2012, 0x69: 0x2012, - 0x6a: 0x2012, 0x6b: 0x2012, 0x6c: 0x2012, 0x6d: 0x2012, 0x6e: 0x2012, 0x6f: 0x2012, - 0x70: 0x2012, 0x71: 0x2012, 0x72: 0x2012, 0x73: 0x2012, 0x74: 0x2012, 0x75: 0x2012, - 0x76: 0x2012, 0x77: 0x2012, 0x78: 0x2012, 0x79: 0x2012, 0x7a: 0x2012, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x0852, 0xc1: 0x0b53, 0xc2: 0x0113, 0xc3: 0x0112, 0xc4: 0x0113, 0xc5: 0x0112, - 0xc6: 0x0b53, 0xc7: 0x0f13, 0xc8: 0x0f12, 0xc9: 0x0e53, 0xca: 0x1153, 0xcb: 0x0713, - 0xcc: 0x0712, 0xcd: 0x0012, 0xce: 0x1453, 0xcf: 0x1753, 0xd0: 0x1a53, 0xd1: 0x0313, - 0xd2: 0x0312, 0xd3: 0x1d53, 0xd4: 0x2053, 0xd5: 0x2352, 0xd6: 0x2653, 0xd7: 0x2653, - 0xd8: 0x0113, 0xd9: 0x0112, 0xda: 0x2952, 0xdb: 0x0012, 0xdc: 0x1d53, 0xdd: 0x2c53, - 0xde: 0x2f52, 0xdf: 0x3253, 0xe0: 0x0113, 0xe1: 0x0112, 0xe2: 0x0113, 0xe3: 0x0112, - 0xe4: 0x0113, 0xe5: 0x0112, 0xe6: 0x3553, 0xe7: 0x0f13, 0xe8: 0x0f12, 0xe9: 0x3853, - 0xea: 0x0012, 0xeb: 0x0012, 0xec: 0x0113, 0xed: 0x0112, 0xee: 0x3553, 0xef: 0x1f13, - 0xf0: 0x1f12, 0xf1: 0x3b53, 0xf2: 0x3e53, 0xf3: 0x0713, 0xf4: 0x0712, 0xf5: 0x0313, - 0xf6: 0x0312, 0xf7: 0x4153, 0xf8: 0x0113, 0xf9: 0x0112, 0xfa: 0x0012, 0xfb: 0x0010, - 0xfc: 0x0113, 0xfd: 0x0112, 0xfe: 0x0012, 0xff: 0x4452, - // Block 0x4, offset 0x100 - 0x100: 0x0010, 0x101: 0x0010, 0x102: 0x0010, 0x103: 0x0010, 0x104: 0x02db, 0x105: 0x0359, - 0x106: 0x03da, 0x107: 0x043b, 0x108: 0x04b9, 0x109: 0x053a, 0x10a: 0x059b, 0x10b: 0x0619, - 0x10c: 0x069a, 0x10d: 0x0313, 0x10e: 0x0312, 0x10f: 0x1f13, 0x110: 0x1f12, 0x111: 0x0313, - 0x112: 0x0312, 0x113: 0x0713, 0x114: 0x0712, 0x115: 0x0313, 0x116: 0x0312, 0x117: 0x0f13, - 0x118: 0x0f12, 0x119: 0x0313, 0x11a: 0x0312, 0x11b: 0x0713, 0x11c: 0x0712, 0x11d: 0x1452, - 0x11e: 0x0113, 0x11f: 0x0112, 0x120: 0x0113, 0x121: 0x0112, 0x122: 0x0113, 0x123: 0x0112, - 0x124: 0x0113, 0x125: 0x0112, 0x126: 0x0113, 0x127: 0x0112, 0x128: 0x0113, 0x129: 0x0112, - 0x12a: 0x0113, 0x12b: 0x0112, 0x12c: 0x0113, 0x12d: 0x0112, 0x12e: 0x0113, 0x12f: 0x0112, - 0x130: 0x06fa, 0x131: 0x07ab, 0x132: 0x0829, 0x133: 0x08aa, 0x134: 0x0113, 0x135: 0x0112, - 0x136: 0x2353, 0x137: 0x4453, 0x138: 0x0113, 0x139: 0x0112, 0x13a: 0x0113, 0x13b: 0x0112, - 0x13c: 0x0113, 0x13d: 0x0112, 0x13e: 0x0113, 0x13f: 0x0112, - // Block 0x5, offset 0x140 - 0x140: 0x0a8a, 0x141: 0x0313, 0x142: 0x0312, 0x143: 0x0853, 0x144: 0x4753, 0x145: 0x4a53, - 0x146: 0x0113, 0x147: 0x0112, 0x148: 0x0113, 0x149: 0x0112, 0x14a: 0x0113, 0x14b: 0x0112, - 0x14c: 0x0113, 0x14d: 0x0112, 0x14e: 0x0113, 0x14f: 0x0112, 0x150: 0x0b0a, 0x151: 0x0b8a, - 0x152: 0x0c0a, 0x153: 0x0b52, 0x154: 0x0b52, 0x155: 0x0012, 0x156: 0x0e52, 0x157: 0x1152, - 0x158: 0x0012, 0x159: 0x1752, 0x15a: 0x0012, 0x15b: 0x1a52, 0x15c: 0x0c8a, 0x15d: 0x0012, - 0x15e: 0x0012, 0x15f: 0x0012, 0x160: 0x1d52, 0x161: 0x0d0a, 0x162: 0x0012, 0x163: 0x2052, - 0x164: 0x0012, 0x165: 0x0d8a, 0x166: 0x0e0a, 0x167: 0x0012, 0x168: 0x2652, 0x169: 0x2652, - 0x16a: 0x0e8a, 0x16b: 0x0f0a, 0x16c: 0x0f8a, 0x16d: 0x0012, 0x16e: 0x0012, 0x16f: 0x1d52, - 0x170: 0x0012, 0x171: 0x100a, 0x172: 0x2c52, 0x173: 0x0012, 0x174: 0x0012, 0x175: 0x3252, - 0x176: 0x0012, 0x177: 0x0012, 0x178: 0x0012, 0x179: 0x0012, 0x17a: 0x0012, 0x17b: 0x0012, - 0x17c: 0x0012, 0x17d: 0x108a, 0x17e: 0x0012, 0x17f: 0x0012, - // Block 0x6, offset 0x180 - 0x180: 0x3552, 0x181: 0x0012, 0x182: 0x0012, 0x183: 0x3852, 0x184: 0x0012, 0x185: 0x0012, - 0x186: 0x0012, 0x187: 0x110a, 0x188: 0x3552, 0x189: 0x4752, 0x18a: 0x3b52, 0x18b: 0x3e52, - 0x18c: 0x4a52, 0x18d: 0x0012, 0x18e: 0x0012, 0x18f: 0x0012, 0x190: 0x0012, 0x191: 0x0012, - 0x192: 0x4152, 0x193: 0x0012, 0x194: 0x0010, 0x195: 0x0012, 0x196: 0x0012, 0x197: 0x0012, - 0x198: 0x0012, 0x199: 0x0012, 0x19a: 0x0012, 0x19b: 0x0012, 0x19c: 0x0012, 0x19d: 0x118a, - 0x19e: 0x120a, 0x19f: 0x0012, 0x1a0: 0x0012, 0x1a1: 0x0012, 0x1a2: 0x0012, 0x1a3: 0x0012, - 0x1a4: 0x0012, 0x1a5: 0x0012, 0x1a6: 0x0012, 0x1a7: 0x0012, 0x1a8: 0x0012, 0x1a9: 0x0012, - 0x1aa: 0x0012, 0x1ab: 0x0012, 0x1ac: 0x0012, 0x1ad: 0x0012, 0x1ae: 0x0012, 0x1af: 0x0012, - 0x1b0: 0x0015, 0x1b1: 0x0015, 0x1b2: 0x0015, 0x1b3: 0x0015, 0x1b4: 0x0015, 0x1b5: 0x0015, - 0x1b6: 0x0015, 0x1b7: 0x0015, 0x1b8: 0x0015, 0x1b9: 0x0014, 0x1ba: 0x0014, 0x1bb: 0x0014, - 0x1bc: 0x0014, 0x1bd: 0x0014, 0x1be: 0x0014, 0x1bf: 0x0014, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x0024, 0x1c1: 0x0024, 0x1c2: 0x0024, 0x1c3: 0x0024, 0x1c4: 0x0024, 0x1c5: 0x128d, - 0x1c6: 0x0024, 0x1c7: 0x0034, 0x1c8: 0x0034, 0x1c9: 0x0034, 0x1ca: 0x0024, 0x1cb: 0x0024, - 0x1cc: 0x0024, 0x1cd: 0x0034, 0x1ce: 0x0034, 0x1cf: 0x0014, 0x1d0: 0x0024, 0x1d1: 0x0024, - 0x1d2: 0x0024, 0x1d3: 0x0034, 0x1d4: 0x0034, 0x1d5: 0x0034, 0x1d6: 0x0034, 0x1d7: 0x0024, - 0x1d8: 0x0034, 0x1d9: 0x0034, 0x1da: 0x0034, 0x1db: 0x0024, 0x1dc: 0x0034, 0x1dd: 0x0034, - 0x1de: 0x0034, 0x1df: 0x0034, 0x1e0: 0x0034, 0x1e1: 0x0034, 0x1e2: 0x0034, 0x1e3: 0x0024, - 0x1e4: 0x0024, 0x1e5: 0x0024, 0x1e6: 0x0024, 0x1e7: 0x0024, 0x1e8: 0x0024, 0x1e9: 0x0024, - 0x1ea: 0x0024, 0x1eb: 0x0024, 0x1ec: 0x0024, 0x1ed: 0x0024, 0x1ee: 0x0024, 0x1ef: 0x0024, - 0x1f0: 0x0113, 0x1f1: 0x0112, 0x1f2: 0x0113, 0x1f3: 0x0112, 0x1f4: 0x0014, 0x1f5: 0x0004, - 0x1f6: 0x0113, 0x1f7: 0x0112, 0x1fa: 0x0015, 0x1fb: 0x4d52, - 0x1fc: 0x5052, 0x1fd: 0x5052, 0x1ff: 0x5353, - // Block 0x8, offset 0x200 - 0x204: 0x0004, 0x205: 0x0004, - 0x206: 0x2a13, 0x207: 0x0054, 0x208: 0x2513, 0x209: 0x2713, 0x20a: 0x2513, - 0x20c: 0x5653, 0x20e: 0x5953, 0x20f: 0x5c53, 0x210: 0x130a, 0x211: 0x2013, - 0x212: 0x2013, 0x213: 0x2013, 0x214: 0x2013, 0x215: 0x2013, 0x216: 0x2013, 0x217: 0x2013, - 0x218: 0x2013, 0x219: 0x2013, 0x21a: 0x2013, 0x21b: 0x2013, 0x21c: 0x2013, 0x21d: 0x2013, - 0x21e: 0x2013, 0x21f: 0x2013, 0x220: 0x5f53, 0x221: 0x5f53, 0x223: 0x5f53, - 0x224: 0x5f53, 0x225: 0x5f53, 0x226: 0x5f53, 0x227: 0x5f53, 0x228: 0x5f53, 0x229: 0x5f53, - 0x22a: 0x5f53, 0x22b: 0x5f53, 0x22c: 0x2a12, 0x22d: 0x2512, 0x22e: 0x2712, 0x22f: 0x2512, - 0x230: 0x144a, 0x231: 0x2012, 0x232: 0x2012, 0x233: 0x2012, 0x234: 0x2012, 0x235: 0x2012, - 0x236: 0x2012, 0x237: 0x2012, 0x238: 0x2012, 0x239: 0x2012, 0x23a: 0x2012, 0x23b: 0x2012, - 0x23c: 0x2012, 0x23d: 0x2012, 0x23e: 0x2012, 0x23f: 0x2012, - // Block 0x9, offset 0x240 - 0x240: 0x5f52, 0x241: 0x5f52, 0x242: 0x158a, 0x243: 0x5f52, 0x244: 0x5f52, 0x245: 0x5f52, - 0x246: 0x5f52, 0x247: 0x5f52, 0x248: 0x5f52, 0x249: 0x5f52, 0x24a: 0x5f52, 0x24b: 0x5f52, - 0x24c: 0x5652, 0x24d: 0x5952, 0x24e: 0x5c52, 0x24f: 0x1813, 0x250: 0x160a, 0x251: 0x168a, - 0x252: 0x0013, 0x253: 0x0013, 0x254: 0x0013, 0x255: 0x170a, 0x256: 0x178a, 0x257: 0x1812, - 0x258: 0x0113, 0x259: 0x0112, 0x25a: 0x0113, 0x25b: 0x0112, 0x25c: 0x0113, 0x25d: 0x0112, - 0x25e: 0x0113, 0x25f: 0x0112, 0x260: 0x0113, 0x261: 0x0112, 0x262: 0x0113, 0x263: 0x0112, - 0x264: 0x0113, 0x265: 0x0112, 0x266: 0x0113, 0x267: 0x0112, 0x268: 0x0113, 0x269: 0x0112, - 0x26a: 0x0113, 0x26b: 0x0112, 0x26c: 0x0113, 0x26d: 0x0112, 0x26e: 0x0113, 0x26f: 0x0112, - 0x270: 0x180a, 0x271: 0x188a, 0x272: 0x0b12, 0x273: 0x5352, 0x274: 0x6253, 0x275: 0x190a, - 0x277: 0x0f13, 0x278: 0x0f12, 0x279: 0x0b13, 0x27a: 0x0113, 0x27b: 0x0112, - 0x27c: 0x0012, 0x27d: 0x4d53, 0x27e: 0x5053, 0x27f: 0x5053, - // Block 0xa, offset 0x280 - 0x280: 0x6852, 0x281: 0x6852, 0x282: 0x6852, 0x283: 0x6852, 0x284: 0x6852, 0x285: 0x6852, - 0x286: 0x6852, 0x287: 0x198a, 0x288: 0x0012, - 0x291: 0x0034, - 0x292: 0x0024, 0x293: 0x0024, 0x294: 0x0024, 0x295: 0x0024, 0x296: 0x0034, 0x297: 0x0024, - 0x298: 0x0024, 0x299: 0x0024, 0x29a: 0x0034, 0x29b: 0x0034, 0x29c: 0x0024, 0x29d: 0x0024, - 0x29e: 0x0024, 0x29f: 0x0024, 0x2a0: 0x0024, 0x2a1: 0x0024, 0x2a2: 0x0034, 0x2a3: 0x0034, - 0x2a4: 0x0034, 0x2a5: 0x0034, 0x2a6: 0x0034, 0x2a7: 0x0034, 0x2a8: 0x0024, 0x2a9: 0x0024, - 0x2aa: 0x0034, 0x2ab: 0x0024, 0x2ac: 0x0024, 0x2ad: 0x0034, 0x2ae: 0x0034, 0x2af: 0x0024, - 0x2b0: 0x0034, 0x2b1: 0x0034, 0x2b2: 0x0034, 0x2b3: 0x0034, 0x2b4: 0x0034, 0x2b5: 0x0034, - 0x2b6: 0x0034, 0x2b7: 0x0034, 0x2b8: 0x0034, 0x2b9: 0x0034, 0x2ba: 0x0034, 0x2bb: 0x0034, - 0x2bc: 0x0034, 0x2bd: 0x0034, 0x2bf: 0x0034, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x7053, 0x2c1: 0x7053, 0x2c2: 0x7053, 0x2c3: 0x7053, 0x2c4: 0x7053, 0x2c5: 0x7053, - 0x2c7: 0x7053, - 0x2cd: 0x7053, 0x2d0: 0x1a6a, 0x2d1: 0x1aea, - 0x2d2: 0x1b6a, 0x2d3: 0x1bea, 0x2d4: 0x1c6a, 0x2d5: 0x1cea, 0x2d6: 0x1d6a, 0x2d7: 0x1dea, - 0x2d8: 0x1e6a, 0x2d9: 0x1eea, 0x2da: 0x1f6a, 0x2db: 0x1fea, 0x2dc: 0x206a, 0x2dd: 0x20ea, - 0x2de: 0x216a, 0x2df: 0x21ea, 0x2e0: 0x226a, 0x2e1: 0x22ea, 0x2e2: 0x236a, 0x2e3: 0x23ea, - 0x2e4: 0x246a, 0x2e5: 0x24ea, 0x2e6: 0x256a, 0x2e7: 0x25ea, 0x2e8: 0x266a, 0x2e9: 0x26ea, - 0x2ea: 0x276a, 0x2eb: 0x27ea, 0x2ec: 0x286a, 0x2ed: 0x28ea, 0x2ee: 0x296a, 0x2ef: 0x29ea, - 0x2f0: 0x2a6a, 0x2f1: 0x2aea, 0x2f2: 0x2b6a, 0x2f3: 0x2bea, 0x2f4: 0x2c6a, 0x2f5: 0x2cea, - 0x2f6: 0x2d6a, 0x2f7: 0x2dea, 0x2f8: 0x2e6a, 0x2f9: 0x2eea, 0x2fa: 0x2f6a, - 0x2fc: 0x0014, 0x2fd: 0x2fea, 0x2fe: 0x306a, 0x2ff: 0x30ea, - // Block 0xc, offset 0x300 - 0x300: 0x0812, 0x301: 0x0812, 0x302: 0x0812, 0x303: 0x0812, 0x304: 0x0812, 0x305: 0x0812, - 0x308: 0x0813, 0x309: 0x0813, 0x30a: 0x0813, 0x30b: 0x0813, - 0x30c: 0x0813, 0x30d: 0x0813, 0x310: 0x3a9a, 0x311: 0x0812, - 0x312: 0x3b7a, 0x313: 0x0812, 0x314: 0x3cba, 0x315: 0x0812, 0x316: 0x3dfa, 0x317: 0x0812, - 0x319: 0x0813, 0x31b: 0x0813, 0x31d: 0x0813, - 0x31f: 0x0813, 0x320: 0x0812, 0x321: 0x0812, 0x322: 0x0812, 0x323: 0x0812, - 0x324: 0x0812, 0x325: 0x0812, 0x326: 0x0812, 0x327: 0x0812, 0x328: 0x0813, 0x329: 0x0813, - 0x32a: 0x0813, 0x32b: 0x0813, 0x32c: 0x0813, 0x32d: 0x0813, 0x32e: 0x0813, 0x32f: 0x0813, - 0x330: 0x8e52, 0x331: 0x8e52, 0x332: 0x9152, 0x333: 0x9152, 0x334: 0x9452, 0x335: 0x9452, - 0x336: 0x9752, 0x337: 0x9752, 0x338: 0x9a52, 0x339: 0x9a52, 0x33a: 0x9d52, 0x33b: 0x9d52, - 0x33c: 0x4d52, 0x33d: 0x4d52, - // Block 0xd, offset 0x340 - 0x340: 0x3f3a, 0x341: 0x402a, 0x342: 0x411a, 0x343: 0x420a, 0x344: 0x42fa, 0x345: 0x43ea, - 0x346: 0x44da, 0x347: 0x45ca, 0x348: 0x46b9, 0x349: 0x47a9, 0x34a: 0x4899, 0x34b: 0x4989, - 0x34c: 0x4a79, 0x34d: 0x4b69, 0x34e: 0x4c59, 0x34f: 0x4d49, 0x350: 0x4e3a, 0x351: 0x4f2a, - 0x352: 0x501a, 0x353: 0x510a, 0x354: 0x51fa, 0x355: 0x52ea, 0x356: 0x53da, 0x357: 0x54ca, - 0x358: 0x55b9, 0x359: 0x56a9, 0x35a: 0x5799, 0x35b: 0x5889, 0x35c: 0x5979, 0x35d: 0x5a69, - 0x35e: 0x5b59, 0x35f: 0x5c49, 0x360: 0x5d3a, 0x361: 0x5e2a, 0x362: 0x5f1a, 0x363: 0x600a, - 0x364: 0x60fa, 0x365: 0x61ea, 0x366: 0x62da, 0x367: 0x63ca, 0x368: 0x64b9, 0x369: 0x65a9, - 0x36a: 0x6699, 0x36b: 0x6789, 0x36c: 0x6879, 0x36d: 0x6969, 0x36e: 0x6a59, 0x36f: 0x6b49, - 0x370: 0x0812, 0x371: 0x0812, 0x372: 0x6c3a, 0x373: 0x6d4a, 0x374: 0x6e1a, - 0x376: 0x6efa, 0x377: 0x6fda, 0x378: 0x0813, 0x379: 0x0813, 0x37a: 0x8e53, 0x37b: 0x8e53, - 0x37c: 0x7119, 0x37d: 0x0004, 0x37e: 0x71ea, 0x37f: 0x0004, - // Block 0xe, offset 0x380 - 0x380: 0x0004, 0x381: 0x0004, 0x382: 0x726a, 0x383: 0x737a, 0x384: 0x744a, - 0x386: 0x752a, 0x387: 0x760a, 0x388: 0x9153, 0x389: 0x9153, 0x38a: 0x9453, 0x38b: 0x9453, - 0x38c: 0x7749, 0x38d: 0x0004, 0x38e: 0x0004, 0x38f: 0x0004, 0x390: 0x0812, 0x391: 0x0812, - 0x392: 0x781a, 0x393: 0x795a, 0x396: 0x7a9a, 0x397: 0x7b7a, - 0x398: 0x0813, 0x399: 0x0813, 0x39a: 0x9753, 0x39b: 0x9753, 0x39d: 0x0004, - 0x39e: 0x0004, 0x39f: 0x0004, 0x3a0: 0x0812, 0x3a1: 0x0812, 0x3a2: 0x7cba, 0x3a3: 0x7dfa, - 0x3a4: 0x7f3a, 0x3a5: 0x0912, 0x3a6: 0x801a, 0x3a7: 0x80fa, 0x3a8: 0x0813, 0x3a9: 0x0813, - 0x3aa: 0x9d53, 0x3ab: 0x9d53, 0x3ac: 0x0913, 0x3ad: 0x0004, 0x3ae: 0x0004, 0x3af: 0x0004, - 0x3b2: 0x823a, 0x3b3: 0x834a, 0x3b4: 0x841a, - 0x3b6: 0x84fa, 0x3b7: 0x85da, 0x3b8: 0x9a53, 0x3b9: 0x9a53, 0x3ba: 0x4d53, 0x3bb: 0x4d53, - 0x3bc: 0x8719, 0x3bd: 0x0004, 0x3be: 0x0004, - // Block 0xf, offset 0x3c0 - 0x3c2: 0x0013, - 0x3c7: 0x0013, 0x3ca: 0x0012, 0x3cb: 0x0013, - 0x3cc: 0x0013, 0x3cd: 0x0013, 0x3ce: 0x0012, 0x3cf: 0x0012, 0x3d0: 0x0013, 0x3d1: 0x0013, - 0x3d2: 0x0013, 0x3d3: 0x0012, 0x3d5: 0x0013, - 0x3d9: 0x0013, 0x3da: 0x0013, 0x3db: 0x0013, 0x3dc: 0x0013, 0x3dd: 0x0013, - 0x3e4: 0x0013, 0x3e6: 0x87eb, 0x3e8: 0x0013, - 0x3ea: 0x884b, 0x3eb: 0x888b, 0x3ec: 0x0013, 0x3ed: 0x0013, 0x3ef: 0x0012, - 0x3f0: 0x0013, 0x3f1: 0x0013, 0x3f2: 0xa053, 0x3f3: 0x0013, 0x3f4: 0x0012, 0x3f5: 0x0010, - 0x3f6: 0x0010, 0x3f7: 0x0010, 0x3f8: 0x0010, 0x3f9: 0x0012, - 0x3fc: 0x0012, 0x3fd: 0x0012, 0x3fe: 0x0013, 0x3ff: 0x0013, - // Block 0x10, offset 0x400 - 0x400: 0x1a13, 0x401: 0x1a13, 0x402: 0x1e13, 0x403: 0x1e13, 0x404: 0x1a13, 0x405: 0x1a13, - 0x406: 0x2613, 0x407: 0x2613, 0x408: 0x2a13, 0x409: 0x2a13, 0x40a: 0x2e13, 0x40b: 0x2e13, - 0x40c: 0x2a13, 0x40d: 0x2a13, 0x40e: 0x2613, 0x40f: 0x2613, 0x410: 0xa352, 0x411: 0xa352, - 0x412: 0xa652, 0x413: 0xa652, 0x414: 0xa952, 0x415: 0xa952, 0x416: 0xa652, 0x417: 0xa652, - 0x418: 0xa352, 0x419: 0xa352, 0x41a: 0x1a12, 0x41b: 0x1a12, 0x41c: 0x1e12, 0x41d: 0x1e12, - 0x41e: 0x1a12, 0x41f: 0x1a12, 0x420: 0x2612, 0x421: 0x2612, 0x422: 0x2a12, 0x423: 0x2a12, - 0x424: 0x2e12, 0x425: 0x2e12, 0x426: 0x2a12, 0x427: 0x2a12, 0x428: 0x2612, 0x429: 0x2612, - // Block 0x11, offset 0x440 - 0x440: 0x6552, 0x441: 0x6552, 0x442: 0x6552, 0x443: 0x6552, 0x444: 0x6552, 0x445: 0x6552, - 0x446: 0x6552, 0x447: 0x6552, 0x448: 0x6552, 0x449: 0x6552, 0x44a: 0x6552, 0x44b: 0x6552, - 0x44c: 0x6552, 0x44d: 0x6552, 0x44e: 0x6552, 0x44f: 0x6552, 0x450: 0xac52, 0x451: 0xac52, - 0x452: 0xac52, 0x453: 0xac52, 0x454: 0xac52, 0x455: 0xac52, 0x456: 0xac52, 0x457: 0xac52, - 0x458: 0xac52, 0x459: 0xac52, 0x45a: 0xac52, 0x45b: 0xac52, 0x45c: 0xac52, 0x45d: 0xac52, - 0x45e: 0xac52, 0x460: 0x0113, 0x461: 0x0112, 0x462: 0x88eb, 0x463: 0x8b53, - 0x464: 0x894b, 0x465: 0x89aa, 0x466: 0x8a0a, 0x467: 0x0f13, 0x468: 0x0f12, 0x469: 0x0313, - 0x46a: 0x0312, 0x46b: 0x0713, 0x46c: 0x0712, 0x46d: 0x8a6b, 0x46e: 0x8acb, 0x46f: 0x8b2b, - 0x470: 0x8b8b, 0x471: 0x0012, 0x472: 0x0113, 0x473: 0x0112, 0x474: 0x0012, 0x475: 0x0313, - 0x476: 0x0312, 0x477: 0x0012, 0x478: 0x0012, 0x479: 0x0012, 0x47a: 0x0012, 0x47b: 0x0012, - 0x47c: 0x0015, 0x47d: 0x0015, 0x47e: 0x8beb, 0x47f: 0x8c4b, - // Block 0x12, offset 0x480 - 0x480: 0x0113, 0x481: 0x0112, 0x482: 0x0113, 0x483: 0x0112, 0x484: 0x0113, 0x485: 0x0112, - 0x486: 0x0113, 0x487: 0x0112, 0x488: 0x0014, 0x489: 0x0014, 0x48a: 0x0014, 0x48b: 0x0713, - 0x48c: 0x0712, 0x48d: 0x8cab, 0x48e: 0x0012, 0x48f: 0x0010, 0x490: 0x0113, 0x491: 0x0112, - 0x492: 0x0113, 0x493: 0x0112, 0x494: 0x0012, 0x495: 0x0012, 0x496: 0x0113, 0x497: 0x0112, - 0x498: 0x0113, 0x499: 0x0112, 0x49a: 0x0113, 0x49b: 0x0112, 0x49c: 0x0113, 0x49d: 0x0112, - 0x49e: 0x0113, 0x49f: 0x0112, 0x4a0: 0x0113, 0x4a1: 0x0112, 0x4a2: 0x0113, 0x4a3: 0x0112, - 0x4a4: 0x0113, 0x4a5: 0x0112, 0x4a6: 0x0113, 0x4a7: 0x0112, 0x4a8: 0x0113, 0x4a9: 0x0112, - 0x4aa: 0x8d0b, 0x4ab: 0x8d6b, 0x4ac: 0x8dcb, 0x4ad: 0x8e2b, 0x4ae: 0x8e8b, 0x4af: 0x0012, - 0x4b0: 0x8eeb, 0x4b1: 0x8f4b, 0x4b2: 0x8fab, 0x4b3: 0xaf53, 0x4b4: 0x0113, 0x4b5: 0x0112, - 0x4b6: 0x0113, 0x4b7: 0x0112, 0x4b8: 0x0113, 0x4b9: 0x0112, - // Block 0x13, offset 0x4c0 - 0x4c0: 0x900a, 0x4c1: 0x908a, 0x4c2: 0x910a, 0x4c3: 0x918a, 0x4c4: 0x923a, 0x4c5: 0x92ea, - 0x4c6: 0x936a, - 0x4d3: 0x93ea, 0x4d4: 0x94ca, 0x4d5: 0x95aa, 0x4d6: 0x968a, 0x4d7: 0x976a, - 0x4dd: 0x0010, - 0x4de: 0x0034, 0x4df: 0x0010, 0x4e0: 0x0010, 0x4e1: 0x0010, 0x4e2: 0x0010, 0x4e3: 0x0010, - 0x4e4: 0x0010, 0x4e5: 0x0010, 0x4e6: 0x0010, 0x4e7: 0x0010, 0x4e8: 0x0010, - 0x4ea: 0x0010, 0x4eb: 0x0010, 0x4ec: 0x0010, 0x4ed: 0x0010, 0x4ee: 0x0010, 0x4ef: 0x0010, - 0x4f0: 0x0010, 0x4f1: 0x0010, 0x4f2: 0x0010, 0x4f3: 0x0010, 0x4f4: 0x0010, 0x4f5: 0x0010, - 0x4f6: 0x0010, 0x4f8: 0x0010, 0x4f9: 0x0010, 0x4fa: 0x0010, 0x4fb: 0x0010, - 0x4fc: 0x0010, 0x4fe: 0x0010, - // Block 0x14, offset 0x500 - 0x500: 0x2213, 0x501: 0x2213, 0x502: 0x2613, 0x503: 0x2613, 0x504: 0x2213, 0x505: 0x2213, - 0x506: 0x2e13, 0x507: 0x2e13, 0x508: 0x2213, 0x509: 0x2213, 0x50a: 0x2613, 0x50b: 0x2613, - 0x50c: 0x2213, 0x50d: 0x2213, 0x50e: 0x3e13, 0x50f: 0x3e13, 0x510: 0x2213, 0x511: 0x2213, - 0x512: 0x2613, 0x513: 0x2613, 0x514: 0x2213, 0x515: 0x2213, 0x516: 0x2e13, 0x517: 0x2e13, - 0x518: 0x2213, 0x519: 0x2213, 0x51a: 0x2613, 0x51b: 0x2613, 0x51c: 0x2213, 0x51d: 0x2213, - 0x51e: 0xb853, 0x51f: 0xb853, 0x520: 0xbb53, 0x521: 0xbb53, 0x522: 0x2212, 0x523: 0x2212, - 0x524: 0x2612, 0x525: 0x2612, 0x526: 0x2212, 0x527: 0x2212, 0x528: 0x2e12, 0x529: 0x2e12, - 0x52a: 0x2212, 0x52b: 0x2212, 0x52c: 0x2612, 0x52d: 0x2612, 0x52e: 0x2212, 0x52f: 0x2212, - 0x530: 0x3e12, 0x531: 0x3e12, 0x532: 0x2212, 0x533: 0x2212, 0x534: 0x2612, 0x535: 0x2612, - 0x536: 0x2212, 0x537: 0x2212, 0x538: 0x2e12, 0x539: 0x2e12, 0x53a: 0x2212, 0x53b: 0x2212, - 0x53c: 0x2612, 0x53d: 0x2612, 0x53e: 0x2212, 0x53f: 0x2212, - // Block 0x15, offset 0x540 - 0x542: 0x0010, - 0x547: 0x0010, 0x549: 0x0010, 0x54b: 0x0010, - 0x54d: 0x0010, 0x54e: 0x0010, 0x54f: 0x0010, 0x551: 0x0010, - 0x552: 0x0010, 0x554: 0x0010, 0x557: 0x0010, - 0x559: 0x0010, 0x55b: 0x0010, 0x55d: 0x0010, - 0x55f: 0x0010, 0x561: 0x0010, 0x562: 0x0010, - 0x564: 0x0010, 0x567: 0x0010, 0x568: 0x0010, 0x569: 0x0010, - 0x56a: 0x0010, 0x56c: 0x0010, 0x56d: 0x0010, 0x56e: 0x0010, 0x56f: 0x0010, - 0x570: 0x0010, 0x571: 0x0010, 0x572: 0x0010, 0x574: 0x0010, 0x575: 0x0010, - 0x576: 0x0010, 0x577: 0x0010, 0x579: 0x0010, 0x57a: 0x0010, 0x57b: 0x0010, - 0x57c: 0x0010, 0x57e: 0x0010, -} - -// caseIndex: 25 blocks, 1600 entries, 3200 bytes -// Block 0 is the zero block. -var caseIndex = [1600]uint16{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x14, 0xc3: 0x15, 0xc4: 0x16, 0xc5: 0x17, 0xc6: 0x01, 0xc7: 0x02, - 0xc8: 0x18, 0xc9: 0x03, 0xca: 0x04, 0xcb: 0x19, 0xcc: 0x1a, 0xcd: 0x05, 0xce: 0x06, 0xcf: 0x07, - 0xd0: 0x1b, 0xd1: 0x1c, 0xd2: 0x1d, 0xd3: 0x1e, 0xd4: 0x1f, 0xd5: 0x20, 0xd6: 0x08, 0xd7: 0x21, - 0xd8: 0x22, 0xd9: 0x23, 0xda: 0x24, 0xdb: 0x25, 0xdc: 0x26, 0xdd: 0x27, 0xde: 0x28, 0xdf: 0x29, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, - 0xea: 0x06, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x08, 0xef: 0x09, - 0xf0: 0x14, 0xf3: 0x16, - // Block 0x4, offset 0x100 - 0x120: 0x2a, 0x121: 0x2b, 0x122: 0x2c, 0x123: 0x2d, 0x124: 0x2e, 0x125: 0x2f, 0x126: 0x30, 0x127: 0x31, - 0x128: 0x32, 0x129: 0x33, 0x12a: 0x34, 0x12b: 0x35, 0x12c: 0x36, 0x12d: 0x37, 0x12e: 0x38, 0x12f: 0x39, - 0x130: 0x3a, 0x131: 0x3b, 0x132: 0x3c, 0x133: 0x3d, 0x134: 0x3e, 0x135: 0x3f, 0x136: 0x40, 0x137: 0x41, - 0x138: 0x42, 0x139: 0x43, 0x13a: 0x44, 0x13b: 0x45, 0x13c: 0x46, 0x13d: 0x47, 0x13e: 0x48, 0x13f: 0x49, - // Block 0x5, offset 0x140 - 0x140: 0x4a, 0x141: 0x4b, 0x142: 0x4c, 0x143: 0x09, 0x144: 0x24, 0x145: 0x24, 0x146: 0x24, 0x147: 0x24, - 0x148: 0x24, 0x149: 0x4d, 0x14a: 0x4e, 0x14b: 0x4f, 0x14c: 0x50, 0x14d: 0x51, 0x14e: 0x52, 0x14f: 0x53, - 0x150: 0x54, 0x151: 0x24, 0x152: 0x24, 0x153: 0x24, 0x154: 0x24, 0x155: 0x24, 0x156: 0x24, 0x157: 0x24, - 0x158: 0x24, 0x159: 0x55, 0x15a: 0x56, 0x15b: 0x57, 0x15c: 0x58, 0x15d: 0x59, 0x15e: 0x5a, 0x15f: 0x5b, - 0x160: 0x5c, 0x161: 0x5d, 0x162: 0x5e, 0x163: 0x5f, 0x164: 0x60, 0x165: 0x61, 0x167: 0x62, - 0x168: 0x63, 0x169: 0x64, 0x16a: 0x65, 0x16c: 0x66, 0x16d: 0x67, 0x16e: 0x68, 0x16f: 0x69, - 0x170: 0x6a, 0x171: 0x6b, 0x172: 0x6c, 0x173: 0x6d, 0x174: 0x6e, 0x175: 0x6f, 0x176: 0x70, 0x177: 0x71, - 0x178: 0x72, 0x179: 0x72, 0x17a: 0x73, 0x17b: 0x72, 0x17c: 0x74, 0x17d: 0x0a, 0x17e: 0x0b, 0x17f: 0x0c, - // Block 0x6, offset 0x180 - 0x180: 0x75, 0x181: 0x76, 0x182: 0x77, 0x183: 0x78, 0x184: 0x0d, 0x185: 0x79, 0x186: 0x7a, - 0x192: 0x7b, 0x193: 0x0e, - 0x1b0: 0x7c, 0x1b1: 0x0f, 0x1b2: 0x72, 0x1b3: 0x7d, 0x1b4: 0x7e, 0x1b5: 0x7f, 0x1b6: 0x80, 0x1b7: 0x81, - 0x1b8: 0x82, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x83, 0x1c2: 0x84, 0x1c3: 0x85, 0x1c4: 0x86, 0x1c5: 0x24, 0x1c6: 0x87, - // Block 0x8, offset 0x200 - 0x200: 0x88, 0x201: 0x24, 0x202: 0x24, 0x203: 0x24, 0x204: 0x24, 0x205: 0x24, 0x206: 0x24, 0x207: 0x24, - 0x208: 0x24, 0x209: 0x24, 0x20a: 0x24, 0x20b: 0x24, 0x20c: 0x24, 0x20d: 0x24, 0x20e: 0x24, 0x20f: 0x24, - 0x210: 0x24, 0x211: 0x24, 0x212: 0x89, 0x213: 0x8a, 0x214: 0x24, 0x215: 0x24, 0x216: 0x24, 0x217: 0x24, - 0x218: 0x8b, 0x219: 0x8c, 0x21a: 0x8d, 0x21b: 0x8e, 0x21c: 0x8f, 0x21d: 0x90, 0x21e: 0x10, 0x21f: 0x91, - 0x220: 0x92, 0x221: 0x93, 0x222: 0x24, 0x223: 0x94, 0x224: 0x95, 0x225: 0x96, 0x226: 0x97, 0x227: 0x98, - 0x228: 0x99, 0x229: 0x9a, 0x22a: 0x9b, 0x22b: 0x9c, 0x22c: 0x9d, 0x22d: 0x9e, 0x22e: 0x9f, 0x22f: 0xa0, - 0x230: 0x24, 0x231: 0x24, 0x232: 0x24, 0x233: 0x24, 0x234: 0x24, 0x235: 0x24, 0x236: 0x24, 0x237: 0x24, - 0x238: 0x24, 0x239: 0x24, 0x23a: 0x24, 0x23b: 0x24, 0x23c: 0x24, 0x23d: 0x24, 0x23e: 0x24, 0x23f: 0x24, - // Block 0x9, offset 0x240 - 0x240: 0x24, 0x241: 0x24, 0x242: 0x24, 0x243: 0x24, 0x244: 0x24, 0x245: 0x24, 0x246: 0x24, 0x247: 0x24, - 0x248: 0x24, 0x249: 0x24, 0x24a: 0x24, 0x24b: 0x24, 0x24c: 0x24, 0x24d: 0x24, 0x24e: 0x24, 0x24f: 0x24, - 0x250: 0x24, 0x251: 0x24, 0x252: 0x24, 0x253: 0x24, 0x254: 0x24, 0x255: 0x24, 0x256: 0x24, 0x257: 0x24, - 0x258: 0x24, 0x259: 0x24, 0x25a: 0x24, 0x25b: 0x24, 0x25c: 0x24, 0x25d: 0x24, 0x25e: 0x24, 0x25f: 0x24, - 0x260: 0x24, 0x261: 0x24, 0x262: 0x24, 0x263: 0x24, 0x264: 0x24, 0x265: 0x24, 0x266: 0x24, 0x267: 0x24, - 0x268: 0x24, 0x269: 0x24, 0x26a: 0x24, 0x26b: 0x24, 0x26c: 0x24, 0x26d: 0x24, 0x26e: 0x24, 0x26f: 0x24, - 0x270: 0x24, 0x271: 0x24, 0x272: 0x24, 0x273: 0x24, 0x274: 0x24, 0x275: 0x24, 0x276: 0x24, 0x277: 0x24, - 0x278: 0x24, 0x279: 0x24, 0x27a: 0x24, 0x27b: 0x24, 0x27c: 0x24, 0x27d: 0x24, 0x27e: 0x24, 0x27f: 0x24, - // Block 0xa, offset 0x280 - 0x280: 0x24, 0x281: 0x24, 0x282: 0x24, 0x283: 0x24, 0x284: 0x24, 0x285: 0x24, 0x286: 0x24, 0x287: 0x24, - 0x288: 0x24, 0x289: 0x24, 0x28a: 0x24, 0x28b: 0x24, 0x28c: 0x24, 0x28d: 0x24, 0x28e: 0x24, 0x28f: 0x24, - 0x290: 0x24, 0x291: 0x24, 0x292: 0x24, 0x293: 0x24, 0x294: 0x24, 0x295: 0x24, 0x296: 0x24, 0x297: 0x24, - 0x298: 0x24, 0x299: 0x24, 0x29a: 0x24, 0x29b: 0x24, 0x29c: 0x24, 0x29d: 0x24, 0x29e: 0xa1, 0x29f: 0xa2, - // Block 0xb, offset 0x2c0 - 0x2ec: 0x11, 0x2ed: 0xa3, 0x2ee: 0xa4, 0x2ef: 0xa5, - 0x2f0: 0x24, 0x2f1: 0x24, 0x2f2: 0x24, 0x2f3: 0x24, 0x2f4: 0xa6, 0x2f5: 0xa7, 0x2f6: 0xa8, 0x2f7: 0xa9, - 0x2f8: 0xaa, 0x2f9: 0xab, 0x2fa: 0x24, 0x2fb: 0xac, 0x2fc: 0xad, 0x2fd: 0xae, 0x2fe: 0xaf, 0x2ff: 0xb0, - // Block 0xc, offset 0x300 - 0x300: 0xb1, 0x301: 0xb2, 0x302: 0x24, 0x303: 0xb3, 0x305: 0xb4, 0x307: 0xb5, - 0x30a: 0xb6, 0x30b: 0xb7, 0x30c: 0xb8, 0x30d: 0xb9, 0x30e: 0xba, 0x30f: 0xbb, - 0x310: 0xbc, 0x311: 0xbd, 0x312: 0xbe, 0x313: 0xbf, 0x314: 0xc0, 0x315: 0xc1, - 0x318: 0x24, 0x319: 0x24, 0x31a: 0x24, 0x31b: 0x24, 0x31c: 0xc2, 0x31d: 0xc3, - 0x320: 0xc4, 0x321: 0xc5, 0x322: 0xc6, 0x323: 0xc7, 0x324: 0xc8, 0x326: 0xc9, - 0x328: 0xca, 0x329: 0xcb, 0x32a: 0xcc, 0x32b: 0xcd, 0x32c: 0x5f, 0x32d: 0xce, 0x32e: 0xcf, - 0x330: 0x24, 0x331: 0xd0, 0x332: 0xd1, 0x333: 0xd2, 0x334: 0xd3, - 0x33c: 0xd4, 0x33d: 0xd5, - // Block 0xd, offset 0x340 - 0x340: 0xd6, 0x341: 0xd7, 0x342: 0xd8, 0x343: 0xd9, 0x344: 0xda, 0x345: 0xdb, 0x346: 0xdc, 0x347: 0xdd, - 0x348: 0xde, 0x34a: 0xdf, 0x34b: 0xe0, 0x34c: 0xe1, 0x34d: 0xe2, - 0x350: 0xe3, 0x351: 0xe4, 0x352: 0xe5, 0x353: 0xe6, 0x356: 0xe7, 0x357: 0xe8, - 0x358: 0xe9, 0x359: 0xea, 0x35a: 0xeb, 0x35b: 0xec, 0x35c: 0xed, - 0x360: 0xee, 0x362: 0xef, 0x363: 0xf0, - 0x368: 0xf1, 0x369: 0xf2, 0x36a: 0xf3, 0x36b: 0xf4, - 0x370: 0xf5, 0x371: 0xf6, 0x372: 0xf7, 0x374: 0xf8, 0x375: 0xf9, 0x376: 0xfa, - 0x37b: 0xfb, - // Block 0xe, offset 0x380 - 0x380: 0x24, 0x381: 0x24, 0x382: 0x24, 0x383: 0x24, 0x384: 0x24, 0x385: 0x24, 0x386: 0x24, 0x387: 0x24, - 0x388: 0x24, 0x389: 0x24, 0x38a: 0x24, 0x38b: 0x24, 0x38c: 0x24, 0x38d: 0x24, 0x38e: 0xfc, - 0x390: 0x24, 0x391: 0xfd, 0x392: 0x24, 0x393: 0x24, 0x394: 0x24, 0x395: 0xfe, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x24, 0x3c1: 0x24, 0x3c2: 0x24, 0x3c3: 0x24, 0x3c4: 0x24, 0x3c5: 0x24, 0x3c6: 0x24, 0x3c7: 0x24, - 0x3c8: 0x24, 0x3c9: 0x24, 0x3ca: 0x24, 0x3cb: 0x24, 0x3cc: 0x24, 0x3cd: 0x24, 0x3ce: 0x24, 0x3cf: 0x24, - 0x3d0: 0xfd, - // Block 0x10, offset 0x400 - 0x410: 0x24, 0x411: 0x24, 0x412: 0x24, 0x413: 0x24, 0x414: 0x24, 0x415: 0x24, 0x416: 0x24, 0x417: 0x24, - 0x418: 0x24, 0x419: 0xff, - // Block 0x11, offset 0x440 - 0x460: 0x24, 0x461: 0x24, 0x462: 0x24, 0x463: 0x24, 0x464: 0x24, 0x465: 0x24, 0x466: 0x24, 0x467: 0x24, - 0x468: 0xf4, 0x469: 0x100, 0x46b: 0x101, 0x46c: 0x102, 0x46d: 0x103, 0x46e: 0x104, - 0x479: 0x105, 0x47c: 0x24, 0x47d: 0x106, 0x47e: 0x107, 0x47f: 0x108, - // Block 0x12, offset 0x480 - 0x4b0: 0x24, 0x4b1: 0x109, 0x4b2: 0x10a, - // Block 0x13, offset 0x4c0 - 0x4c5: 0x10b, 0x4c6: 0x10c, - 0x4c9: 0x10d, - 0x4d0: 0x10e, 0x4d1: 0x10f, 0x4d2: 0x110, 0x4d3: 0x111, 0x4d4: 0x112, 0x4d5: 0x113, 0x4d6: 0x114, 0x4d7: 0x115, - 0x4d8: 0x116, 0x4d9: 0x117, 0x4da: 0x118, 0x4db: 0x119, 0x4dc: 0x11a, 0x4dd: 0x11b, 0x4de: 0x11c, 0x4df: 0x11d, - 0x4e8: 0x11e, 0x4e9: 0x11f, 0x4ea: 0x120, - // Block 0x14, offset 0x500 - 0x500: 0x121, - 0x520: 0x24, 0x521: 0x24, 0x522: 0x24, 0x523: 0x122, 0x524: 0x12, 0x525: 0x123, - 0x538: 0x124, 0x539: 0x13, 0x53a: 0x125, - // Block 0x15, offset 0x540 - 0x544: 0x126, 0x545: 0x127, 0x546: 0x128, - 0x54f: 0x129, - // Block 0x16, offset 0x580 - 0x590: 0x0a, 0x591: 0x0b, 0x592: 0x0c, 0x593: 0x0d, 0x594: 0x0e, 0x596: 0x0f, - 0x59b: 0x10, 0x59d: 0x11, 0x59e: 0x12, 0x59f: 0x13, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x12a, 0x5c1: 0x12b, 0x5c4: 0x12b, 0x5c5: 0x12b, 0x5c6: 0x12b, 0x5c7: 0x12c, - // Block 0x18, offset 0x600 - 0x620: 0x15, -} - -// sparseOffsets: 282 entries, 564 bytes -var sparseOffsets = []uint16{0x0, 0x9, 0xf, 0x18, 0x24, 0x2e, 0x35, 0x38, 0x3c, 0x3f, 0x43, 0x4d, 0x4f, 0x57, 0x5e, 0x63, 0x71, 0x72, 0x80, 0x8f, 0x99, 0x9c, 0xa3, 0xab, 0xae, 0xb0, 0xbf, 0xc5, 0xd3, 0xde, 0xeb, 0xf6, 0x102, 0x10c, 0x118, 0x123, 0x12f, 0x13b, 0x143, 0x14c, 0x156, 0x161, 0x16d, 0x174, 0x17f, 0x184, 0x18c, 0x18f, 0x194, 0x198, 0x19c, 0x1a3, 0x1ac, 0x1b4, 0x1b5, 0x1be, 0x1c5, 0x1cd, 0x1d3, 0x1d8, 0x1dc, 0x1df, 0x1e1, 0x1e4, 0x1e9, 0x1ea, 0x1ec, 0x1ee, 0x1f0, 0x1f7, 0x1fc, 0x200, 0x209, 0x20c, 0x20f, 0x215, 0x216, 0x221, 0x222, 0x223, 0x228, 0x235, 0x23d, 0x245, 0x24e, 0x257, 0x260, 0x265, 0x268, 0x273, 0x280, 0x282, 0x289, 0x28b, 0x297, 0x298, 0x2a3, 0x2ab, 0x2b3, 0x2b9, 0x2ba, 0x2c8, 0x2cd, 0x2d0, 0x2d5, 0x2d9, 0x2df, 0x2e4, 0x2e7, 0x2ec, 0x2f1, 0x2f2, 0x2f8, 0x2fa, 0x2fb, 0x2fd, 0x2ff, 0x302, 0x303, 0x305, 0x308, 0x30e, 0x312, 0x314, 0x319, 0x320, 0x324, 0x32d, 0x32e, 0x337, 0x33b, 0x340, 0x348, 0x34e, 0x354, 0x35e, 0x363, 0x36c, 0x372, 0x379, 0x37d, 0x385, 0x387, 0x389, 0x38c, 0x38e, 0x390, 0x391, 0x392, 0x394, 0x396, 0x39c, 0x3a1, 0x3a3, 0x3a9, 0x3ac, 0x3ae, 0x3b4, 0x3b9, 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3c0, 0x3c2, 0x3c4, 0x3c7, 0x3c9, 0x3cc, 0x3d4, 0x3d7, 0x3db, 0x3e3, 0x3e5, 0x3e6, 0x3e7, 0x3e9, 0x3ef, 0x3f1, 0x3f2, 0x3f4, 0x3f6, 0x3f8, 0x405, 0x406, 0x407, 0x40b, 0x40d, 0x40e, 0x40f, 0x410, 0x411, 0x414, 0x417, 0x41d, 0x421, 0x425, 0x42b, 0x42e, 0x435, 0x439, 0x43d, 0x444, 0x44d, 0x453, 0x459, 0x463, 0x46d, 0x46f, 0x477, 0x47d, 0x483, 0x489, 0x48c, 0x492, 0x495, 0x49d, 0x49e, 0x4a5, 0x4a9, 0x4aa, 0x4ad, 0x4b5, 0x4bb, 0x4c2, 0x4c3, 0x4c9, 0x4cc, 0x4d4, 0x4db, 0x4e5, 0x4ed, 0x4f0, 0x4f1, 0x4f2, 0x4f3, 0x4f4, 0x4f6, 0x4f8, 0x4fa, 0x4fe, 0x4ff, 0x501, 0x503, 0x504, 0x505, 0x507, 0x50c, 0x511, 0x515, 0x516, 0x519, 0x51d, 0x528, 0x52c, 0x534, 0x539, 0x53d, 0x540, 0x544, 0x547, 0x54a, 0x54f, 0x553, 0x557, 0x55b, 0x55f, 0x561, 0x563, 0x566, 0x56b, 0x56d, 0x572, 0x57b, 0x580, 0x581, 0x584, 0x585, 0x586, 0x588, 0x589, 0x58a} - -// sparseValues: 1418 entries, 5672 bytes -var sparseValues = [1418]valueRange{ - // Block 0x0, offset 0x0 - {value: 0x0004, lo: 0xa8, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xaa}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0004, lo: 0xaf, hi: 0xaf}, - {value: 0x0004, lo: 0xb4, hi: 0xb4}, - {value: 0x001a, lo: 0xb5, hi: 0xb5}, - {value: 0x0054, lo: 0xb7, hi: 0xb7}, - {value: 0x0004, lo: 0xb8, hi: 0xb8}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - // Block 0x1, offset 0x9 - {value: 0x2013, lo: 0x80, hi: 0x96}, - {value: 0x2013, lo: 0x98, hi: 0x9e}, - {value: 0x009a, lo: 0x9f, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xb6}, - {value: 0x2012, lo: 0xb8, hi: 0xbe}, - {value: 0x0252, lo: 0xbf, hi: 0xbf}, - // Block 0x2, offset 0xf - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x011b, lo: 0xb0, hi: 0xb0}, - {value: 0x019a, lo: 0xb1, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb7}, - {value: 0x0012, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x0553, lo: 0xbf, hi: 0xbf}, - // Block 0x3, offset 0x18 - {value: 0x0552, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x01da, lo: 0x89, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xb7}, - {value: 0x0253, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x028a, lo: 0xbf, hi: 0xbf}, - // Block 0x4, offset 0x24 - {value: 0x0117, lo: 0x80, hi: 0x9f}, - {value: 0x2f53, lo: 0xa0, hi: 0xa0}, - {value: 0x0012, lo: 0xa1, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xb3}, - {value: 0x0012, lo: 0xb4, hi: 0xb9}, - {value: 0x090b, lo: 0xba, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x2953, lo: 0xbd, hi: 0xbd}, - {value: 0x098b, lo: 0xbe, hi: 0xbe}, - {value: 0x0a0a, lo: 0xbf, hi: 0xbf}, - // Block 0x5, offset 0x2e - {value: 0x0015, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x97}, - {value: 0x0004, lo: 0x98, hi: 0x9d}, - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0015, lo: 0xa0, hi: 0xa4}, - {value: 0x0004, lo: 0xa5, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xbf}, - // Block 0x6, offset 0x35 - {value: 0x0024, lo: 0x80, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbf}, - // Block 0x7, offset 0x38 - {value: 0x6553, lo: 0x80, hi: 0x8f}, - {value: 0x2013, lo: 0x90, hi: 0x9f}, - {value: 0x5f53, lo: 0xa0, hi: 0xaf}, - {value: 0x2012, lo: 0xb0, hi: 0xbf}, - // Block 0x8, offset 0x3c - {value: 0x5f52, lo: 0x80, hi: 0x8f}, - {value: 0x6552, lo: 0x90, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x9, offset 0x3f - {value: 0x0117, lo: 0x80, hi: 0x81}, - {value: 0x0024, lo: 0x83, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xbf}, - // Block 0xa, offset 0x43 - {value: 0x0f13, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0716, lo: 0x8b, hi: 0x8c}, - {value: 0x0316, lo: 0x8d, hi: 0x8e}, - {value: 0x0f12, lo: 0x8f, hi: 0x8f}, - {value: 0x0117, lo: 0x90, hi: 0xbf}, - // Block 0xb, offset 0x4d - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x6553, lo: 0xb1, hi: 0xbf}, - // Block 0xc, offset 0x4f - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6853, lo: 0x90, hi: 0x96}, - {value: 0x0014, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9b, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0xa0, hi: 0xa0}, - {value: 0x6552, lo: 0xa1, hi: 0xaf}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0xd, offset 0x57 - {value: 0x0034, lo: 0x81, hi: 0x82}, - {value: 0x0024, lo: 0x84, hi: 0x84}, - {value: 0x0034, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xaa}, - {value: 0x0010, lo: 0xaf, hi: 0xb3}, - {value: 0x0054, lo: 0xb4, hi: 0xb4}, - // Block 0xe, offset 0x5e - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0024, lo: 0x90, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0014, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xf, offset 0x63 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9c}, - {value: 0x0024, lo: 0x9d, hi: 0x9e}, - {value: 0x0034, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x10, offset 0x71 - {value: 0x0010, lo: 0x80, hi: 0xbf}, - // Block 0x11, offset 0x72 - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0024, lo: 0x9f, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x12, offset 0x80 - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0034, lo: 0xb1, hi: 0xb1}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0024, lo: 0xbf, hi: 0xbf}, - // Block 0x13, offset 0x8f - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0024, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x88}, - {value: 0x0024, lo: 0x89, hi: 0x8a}, - {value: 0x0010, lo: 0x8d, hi: 0xbf}, - // Block 0x14, offset 0x99 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x15, offset 0x9c - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xb1}, - {value: 0x0034, lo: 0xb2, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0x16, offset 0xa3 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x99}, - {value: 0x0014, lo: 0x9a, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0xa3}, - {value: 0x0014, lo: 0xa4, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xad}, - // Block 0x17, offset 0xab - {value: 0x0010, lo: 0x80, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0xa0, hi: 0xaa}, - // Block 0x18, offset 0xae - {value: 0x0010, lo: 0xa0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbd}, - // Block 0x19, offset 0xb0 - {value: 0x0034, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0024, lo: 0xaa, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbf}, - // Block 0x1a, offset 0xbf - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1b, offset 0xc5 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0x1c, offset 0xd3 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb6, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1d, offset 0xde - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xb1}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - // Block 0x1e, offset 0xeb - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x1f, offset 0xf6 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x99, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x20, offset 0x102 - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x21, offset 0x10c - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x85}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xbf}, - // Block 0x22, offset 0x118 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x23, offset 0x123 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x24, offset 0x12f - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0010, lo: 0xa8, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x25, offset 0x13b - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x26, offset 0x143 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb9}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbf}, - // Block 0x27, offset 0x14c - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x88}, - {value: 0x0014, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x28, offset 0x156 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x29, offset 0x161 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb2}, - // Block 0x2a, offset 0x16d - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x2b, offset 0x174 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x94, hi: 0x97}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xba, hi: 0xbf}, - // Block 0x2c, offset 0x17f - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x96}, - {value: 0x0010, lo: 0x9a, hi: 0xb1}, - {value: 0x0010, lo: 0xb3, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x2d, offset 0x184 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x94}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9f}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - // Block 0x2e, offset 0x18c - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - // Block 0x2f, offset 0x18f - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x30, offset 0x194 - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xb9}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - // Block 0x31, offset 0x198 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x32, offset 0x19c - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0034, lo: 0x98, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0034, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x33, offset 0x1a3 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xac}, - {value: 0x0034, lo: 0xb1, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xba, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x34, offset 0x1ac - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0024, lo: 0x82, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x86, hi: 0x87}, - {value: 0x0010, lo: 0x88, hi: 0x8c}, - {value: 0x0014, lo: 0x8d, hi: 0x97}, - {value: 0x0014, lo: 0x99, hi: 0xbc}, - // Block 0x35, offset 0x1b4 - {value: 0x0034, lo: 0x86, hi: 0x86}, - // Block 0x36, offset 0x1b5 - {value: 0x0010, lo: 0xab, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbe}, - // Block 0x37, offset 0x1be - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x96, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x99}, - {value: 0x0014, lo: 0x9e, hi: 0xa0}, - {value: 0x0010, lo: 0xa2, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xad}, - {value: 0x0014, lo: 0xb1, hi: 0xb4}, - // Block 0x38, offset 0x1c5 - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x6c53, lo: 0xa0, hi: 0xbf}, - // Block 0x39, offset 0x1cd - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x9a, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x3a, offset 0x1d3 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x3b, offset 0x1d8 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x82, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3c, offset 0x1dc - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3d, offset 0x1df - {value: 0x0010, lo: 0x80, hi: 0x9a}, - {value: 0x0024, lo: 0x9d, hi: 0x9f}, - // Block 0x3e, offset 0x1e1 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x7453, lo: 0xa0, hi: 0xaf}, - {value: 0x7853, lo: 0xb0, hi: 0xbf}, - // Block 0x3f, offset 0x1e4 - {value: 0x7c53, lo: 0x80, hi: 0x8f}, - {value: 0x8053, lo: 0x90, hi: 0x9f}, - {value: 0x7c53, lo: 0xa0, hi: 0xaf}, - {value: 0x0813, lo: 0xb0, hi: 0xb5}, - {value: 0x0892, lo: 0xb8, hi: 0xbd}, - // Block 0x40, offset 0x1e9 - {value: 0x0010, lo: 0x81, hi: 0xbf}, - // Block 0x41, offset 0x1ea - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0010, lo: 0xaf, hi: 0xbf}, - // Block 0x42, offset 0x1ec - {value: 0x0010, lo: 0x81, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x43, offset 0x1ee - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb8}, - // Block 0x44, offset 0x1f0 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0034, lo: 0x94, hi: 0x94}, - {value: 0x0010, lo: 0xa0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - // Block 0x45, offset 0x1f7 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xac}, - {value: 0x0010, lo: 0xae, hi: 0xb0}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - // Block 0x46, offset 0x1fc - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x47, offset 0x200 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x89, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0014, lo: 0x93, hi: 0x93}, - {value: 0x0004, lo: 0x97, hi: 0x97}, - {value: 0x0024, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0x48, offset 0x209 - {value: 0x0014, lo: 0x8b, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x49, offset 0x20c - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb8}, - // Block 0x4a, offset 0x20f - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x4b, offset 0x215 - {value: 0x0010, lo: 0x80, hi: 0xb5}, - // Block 0x4c, offset 0x216 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbb}, - // Block 0x4d, offset 0x221 - {value: 0x0010, lo: 0x86, hi: 0x8f}, - // Block 0x4e, offset 0x222 - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x4f, offset 0x223 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - // Block 0x50, offset 0x228 - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x9e}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xac}, - {value: 0x0010, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xbc}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x51, offset 0x235 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xa7, hi: 0xa7}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - {value: 0x0034, lo: 0xb5, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbc}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0x52, offset 0x23d - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x53, offset 0x245 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0030, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xab, hi: 0xab}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - {value: 0x0024, lo: 0xad, hi: 0xb3}, - // Block 0x54, offset 0x24e - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0030, lo: 0xaa, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbf}, - // Block 0x55, offset 0x257 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0030, lo: 0xb2, hi: 0xb3}, - // Block 0x56, offset 0x260 - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0x57, offset 0x265 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8d, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x58, offset 0x268 - {value: 0x316a, lo: 0x80, hi: 0x80}, - {value: 0x31ea, lo: 0x81, hi: 0x81}, - {value: 0x326a, lo: 0x82, hi: 0x82}, - {value: 0x32ea, lo: 0x83, hi: 0x83}, - {value: 0x336a, lo: 0x84, hi: 0x84}, - {value: 0x33ea, lo: 0x85, hi: 0x85}, - {value: 0x346a, lo: 0x86, hi: 0x86}, - {value: 0x34ea, lo: 0x87, hi: 0x87}, - {value: 0x356a, lo: 0x88, hi: 0x88}, - {value: 0x8353, lo: 0x90, hi: 0xba}, - {value: 0x8353, lo: 0xbd, hi: 0xbf}, - // Block 0x59, offset 0x273 - {value: 0x0024, lo: 0x90, hi: 0x92}, - {value: 0x0034, lo: 0x94, hi: 0x99}, - {value: 0x0024, lo: 0x9a, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9f}, - {value: 0x0024, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xb3}, - {value: 0x0024, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb7}, - {value: 0x0024, lo: 0xb8, hi: 0xb9}, - // Block 0x5a, offset 0x280 - {value: 0x0012, lo: 0x80, hi: 0xab}, - {value: 0x0015, lo: 0xac, hi: 0xbf}, - // Block 0x5b, offset 0x282 - {value: 0x0015, lo: 0x80, hi: 0xaa}, - {value: 0x0012, lo: 0xab, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb8}, - {value: 0x8752, lo: 0xb9, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbc}, - {value: 0x8b52, lo: 0xbd, hi: 0xbd}, - {value: 0x0012, lo: 0xbe, hi: 0xbf}, - // Block 0x5c, offset 0x289 - {value: 0x0012, lo: 0x80, hi: 0x9a}, - {value: 0x0015, lo: 0x9b, hi: 0xbf}, - // Block 0x5d, offset 0x28b - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0024, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb9}, - {value: 0x0024, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbd}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x5e, offset 0x297 - {value: 0x0117, lo: 0x80, hi: 0xbf}, - // Block 0x5f, offset 0x298 - {value: 0x0117, lo: 0x80, hi: 0x95}, - {value: 0x361a, lo: 0x96, hi: 0x96}, - {value: 0x36ca, lo: 0x97, hi: 0x97}, - {value: 0x377a, lo: 0x98, hi: 0x98}, - {value: 0x382a, lo: 0x99, hi: 0x99}, - {value: 0x38da, lo: 0x9a, hi: 0x9a}, - {value: 0x398a, lo: 0x9b, hi: 0x9b}, - {value: 0x0012, lo: 0x9c, hi: 0x9d}, - {value: 0x3a3b, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0x9f, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x60, offset 0x2a3 - {value: 0x0812, lo: 0x80, hi: 0x87}, - {value: 0x0813, lo: 0x88, hi: 0x8f}, - {value: 0x0812, lo: 0x90, hi: 0x95}, - {value: 0x0813, lo: 0x98, hi: 0x9d}, - {value: 0x0812, lo: 0xa0, hi: 0xa7}, - {value: 0x0813, lo: 0xa8, hi: 0xaf}, - {value: 0x0812, lo: 0xb0, hi: 0xb7}, - {value: 0x0813, lo: 0xb8, hi: 0xbf}, - // Block 0x61, offset 0x2ab - {value: 0x0004, lo: 0x8b, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8f}, - {value: 0x0054, lo: 0x98, hi: 0x99}, - {value: 0x0054, lo: 0xa4, hi: 0xa4}, - {value: 0x0054, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xaa, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xaf}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x62, offset 0x2b3 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x94, hi: 0x94}, - {value: 0x0014, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa6, hi: 0xaf}, - {value: 0x0015, lo: 0xb1, hi: 0xb1}, - {value: 0x0015, lo: 0xbf, hi: 0xbf}, - // Block 0x63, offset 0x2b9 - {value: 0x0015, lo: 0x90, hi: 0x9c}, - // Block 0x64, offset 0x2ba - {value: 0x0024, lo: 0x90, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0xa0}, - {value: 0x0024, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa4}, - {value: 0x0034, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - // Block 0x65, offset 0x2c8 - {value: 0x0016, lo: 0x85, hi: 0x86}, - {value: 0x0012, lo: 0x87, hi: 0x89}, - {value: 0xa052, lo: 0x8e, hi: 0x8e}, - {value: 0x1013, lo: 0xa0, hi: 0xaf}, - {value: 0x1012, lo: 0xb0, hi: 0xbf}, - // Block 0x66, offset 0x2cd - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x88}, - // Block 0x67, offset 0x2d0 - {value: 0xa353, lo: 0xb6, hi: 0xb7}, - {value: 0xa653, lo: 0xb8, hi: 0xb9}, - {value: 0xa953, lo: 0xba, hi: 0xbb}, - {value: 0xa653, lo: 0xbc, hi: 0xbd}, - {value: 0xa353, lo: 0xbe, hi: 0xbf}, - // Block 0x68, offset 0x2d5 - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6553, lo: 0x90, hi: 0x9f}, - {value: 0xac53, lo: 0xa0, hi: 0xae}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0x69, offset 0x2d9 - {value: 0x0117, lo: 0x80, hi: 0xa3}, - {value: 0x0012, lo: 0xa4, hi: 0xa4}, - {value: 0x0716, lo: 0xab, hi: 0xac}, - {value: 0x0316, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb3}, - // Block 0x6a, offset 0x2df - {value: 0x6c52, lo: 0x80, hi: 0x9f}, - {value: 0x7052, lo: 0xa0, hi: 0xa5}, - {value: 0x7052, lo: 0xa7, hi: 0xa7}, - {value: 0x7052, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x6b, offset 0x2e4 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x6c, offset 0x2e7 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0010, lo: 0xb0, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x6d, offset 0x2ec - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9e}, - {value: 0x0024, lo: 0xa0, hi: 0xbf}, - // Block 0x6e, offset 0x2f1 - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - // Block 0x6f, offset 0x2f2 - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0xaa, hi: 0xad}, - {value: 0x0030, lo: 0xae, hi: 0xaf}, - {value: 0x0004, lo: 0xb1, hi: 0xb5}, - {value: 0x0014, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - // Block 0x70, offset 0x2f8 - {value: 0x0034, lo: 0x99, hi: 0x9a}, - {value: 0x0004, lo: 0x9b, hi: 0x9e}, - // Block 0x71, offset 0x2fa - {value: 0x0004, lo: 0xbc, hi: 0xbe}, - // Block 0x72, offset 0x2fb - {value: 0x0010, lo: 0x85, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x73, offset 0x2fd - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0010, lo: 0xa0, hi: 0xba}, - // Block 0x74, offset 0x2ff - {value: 0x0010, lo: 0x80, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0xbf}, - // Block 0x75, offset 0x302 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - // Block 0x76, offset 0x303 - {value: 0x0010, lo: 0x90, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x77, offset 0x305 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0xab}, - // Block 0x78, offset 0x308 - {value: 0x0117, lo: 0x80, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb2}, - {value: 0x0024, lo: 0xb4, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x79, offset 0x30e - {value: 0x0117, lo: 0x80, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9d}, - {value: 0x0024, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x7a, offset 0x312 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb1}, - // Block 0x7b, offset 0x314 - {value: 0x0004, lo: 0x80, hi: 0x96}, - {value: 0x0014, lo: 0x97, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xaf}, - {value: 0x0012, lo: 0xb0, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xbf}, - // Block 0x7c, offset 0x319 - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x0015, lo: 0xb0, hi: 0xb0}, - {value: 0x0012, lo: 0xb1, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x8753, lo: 0xbd, hi: 0xbd}, - {value: 0x0117, lo: 0xbe, hi: 0xbf}, - // Block 0x7d, offset 0x320 - {value: 0x0010, lo: 0xb7, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbf}, - // Block 0x7e, offset 0x324 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x8c, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - // Block 0x7f, offset 0x32d - {value: 0x0010, lo: 0x80, hi: 0xb3}, - // Block 0x80, offset 0x32e - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xa0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb7}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x81, offset 0x337 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x82, offset 0x33b - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0x92}, - {value: 0x0030, lo: 0x93, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0x83, offset 0x340 - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x84, offset 0x348 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0004, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x85, offset 0x34e - {value: 0x0010, lo: 0x80, hi: 0xa8}, - {value: 0x0014, lo: 0xa9, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0x86, offset 0x354 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x87, offset 0x35e - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0024, lo: 0xbe, hi: 0xbf}, - // Block 0x88, offset 0x363 - {value: 0x0024, lo: 0x81, hi: 0x81}, - {value: 0x0004, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - // Block 0x89, offset 0x36c - {value: 0x0010, lo: 0x81, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x8e}, - {value: 0x0010, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x8a, offset 0x372 - {value: 0x0012, lo: 0x80, hi: 0x92}, - {value: 0xaf52, lo: 0x93, hi: 0x93}, - {value: 0x0012, lo: 0x94, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa5}, - {value: 0x74d2, lo: 0xb0, hi: 0xbf}, - // Block 0x8b, offset 0x379 - {value: 0x78d2, lo: 0x80, hi: 0x8f}, - {value: 0x7cd2, lo: 0x90, hi: 0x9f}, - {value: 0x80d2, lo: 0xa0, hi: 0xaf}, - {value: 0x7cd2, lo: 0xb0, hi: 0xbf}, - // Block 0x8c, offset 0x37d - {value: 0x0010, lo: 0x80, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x8d, offset 0x385 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x8e, offset 0x387 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x8b, hi: 0xbb}, - // Block 0x8f, offset 0x389 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0xbf}, - // Block 0x90, offset 0x38c - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0004, lo: 0xb2, hi: 0xbf}, - // Block 0x91, offset 0x38e - {value: 0x0004, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x93, hi: 0xbf}, - // Block 0x92, offset 0x390 - {value: 0x0010, lo: 0x80, hi: 0xbd}, - // Block 0x93, offset 0x391 - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0x94, offset 0x392 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0xbf}, - // Block 0x95, offset 0x394 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0xb0, hi: 0xbb}, - // Block 0x96, offset 0x396 - {value: 0x0014, lo: 0x80, hi: 0x8f}, - {value: 0x0054, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0xa0, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xad}, - {value: 0x0024, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - // Block 0x97, offset 0x39c - {value: 0x0010, lo: 0x8d, hi: 0x8f}, - {value: 0x0054, lo: 0x92, hi: 0x92}, - {value: 0x0054, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0xb0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0x98, offset 0x3a1 - {value: 0x0010, lo: 0x80, hi: 0xbc}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x99, offset 0x3a3 - {value: 0x0054, lo: 0x87, hi: 0x87}, - {value: 0x0054, lo: 0x8e, hi: 0x8e}, - {value: 0x0054, lo: 0x9a, hi: 0x9a}, - {value: 0x5f53, lo: 0xa1, hi: 0xba}, - {value: 0x0004, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9a, offset 0x3a9 - {value: 0x0004, lo: 0x80, hi: 0x80}, - {value: 0x5f52, lo: 0x81, hi: 0x9a}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - // Block 0x9b, offset 0x3ac - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbe}, - // Block 0x9c, offset 0x3ae - {value: 0x0010, lo: 0x82, hi: 0x87}, - {value: 0x0010, lo: 0x8a, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0x97}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0004, lo: 0xa3, hi: 0xa3}, - {value: 0x0014, lo: 0xb9, hi: 0xbb}, - // Block 0x9d, offset 0x3b4 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0010, lo: 0x8d, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xba}, - {value: 0x0010, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9e, offset 0x3b9 - {value: 0x0010, lo: 0x80, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x9d}, - // Block 0x9f, offset 0x3bb - {value: 0x0010, lo: 0x80, hi: 0xba}, - // Block 0xa0, offset 0x3bc - {value: 0x0010, lo: 0x80, hi: 0xb4}, - // Block 0xa1, offset 0x3bd - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0xa2, offset 0x3be - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa3, offset 0x3c0 - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - // Block 0xa4, offset 0x3c2 - {value: 0x0010, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xad, hi: 0xbf}, - // Block 0xa5, offset 0x3c4 - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0xb5}, - {value: 0x0024, lo: 0xb6, hi: 0xba}, - // Block 0xa6, offset 0x3c7 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa7, offset 0x3c9 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x91, hi: 0x95}, - // Block 0xa8, offset 0x3cc - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x97}, - {value: 0xb253, lo: 0x98, hi: 0x9f}, - {value: 0xb553, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbf}, - // Block 0xa9, offset 0x3d4 - {value: 0xb252, lo: 0x80, hi: 0x87}, - {value: 0xb552, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xaa, offset 0x3d7 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0xb553, lo: 0xb0, hi: 0xb7}, - {value: 0xb253, lo: 0xb8, hi: 0xbf}, - // Block 0xab, offset 0x3db - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x93}, - {value: 0xb552, lo: 0x98, hi: 0x9f}, - {value: 0xb252, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbb}, - // Block 0xac, offset 0x3e3 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xad, offset 0x3e5 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - // Block 0xae, offset 0x3e6 - {value: 0x0010, lo: 0x80, hi: 0xb6}, - // Block 0xaf, offset 0x3e7 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - // Block 0xb0, offset 0x3e9 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xb1, offset 0x3ef - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xb2, offset 0x3f1 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - // Block 0xb3, offset 0x3f2 - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - // Block 0xb4, offset 0x3f4 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb9}, - // Block 0xb5, offset 0x3f6 - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0xb6, offset 0x3f8 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x8e, hi: 0x8e}, - {value: 0x0024, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x99, hi: 0xb5}, - {value: 0x0024, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xb7, offset 0x405 - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0xb8, offset 0x406 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - // Block 0xb9, offset 0x407 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - // Block 0xba, offset 0x40b - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - // Block 0xbb, offset 0x40d - {value: 0x0010, lo: 0x80, hi: 0x91}, - // Block 0xbc, offset 0x40e - {value: 0x0010, lo: 0x80, hi: 0x88}, - // Block 0xbd, offset 0x40f - {value: 0x5653, lo: 0x80, hi: 0xb2}, - // Block 0xbe, offset 0x410 - {value: 0x5652, lo: 0x80, hi: 0xb2}, - // Block 0xbf, offset 0x411 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc0, offset 0x414 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xc1, offset 0x417 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x87}, - {value: 0x0024, lo: 0x88, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x8b}, - {value: 0x0024, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - // Block 0xc2, offset 0x41d - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xc3, offset 0x421 - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xc4, offset 0x425 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - // Block 0xc5, offset 0x42b - {value: 0x0014, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc6, offset 0x42e - {value: 0x0024, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0xc7, offset 0x435 - {value: 0x0010, lo: 0x84, hi: 0x86}, - {value: 0x0010, lo: 0x90, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - // Block 0xc8, offset 0x439 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xc9, offset 0x43d - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x89, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - // Block 0xca, offset 0x444 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb4}, - {value: 0x0030, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xb7}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0xcb, offset 0x44d - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xcc, offset 0x453 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa2}, - {value: 0x0014, lo: 0xa3, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xcd, offset 0x459 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xce, offset 0x463 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0030, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9d, hi: 0xa3}, - {value: 0x0024, lo: 0xa6, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - // Block 0xcf, offset 0x46d - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xd0, offset 0x46f - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0x9e, hi: 0x9e}, - // Block 0xd1, offset 0x477 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xd2, offset 0x47d - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd3, offset 0x483 - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd4, offset 0x489 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x98, hi: 0x9b}, - {value: 0x0014, lo: 0x9c, hi: 0x9d}, - // Block 0xd5, offset 0x48c - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd6, offset 0x492 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd7, offset 0x495 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0014, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb5}, - {value: 0x0030, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0xd8, offset 0x49d - {value: 0x0010, lo: 0x80, hi: 0x89}, - // Block 0xd9, offset 0x49e - {value: 0x0014, lo: 0x9d, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xda, offset 0x4a5 - {value: 0x0010, lo: 0x80, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - // Block 0xdb, offset 0x4a9 - {value: 0x5f53, lo: 0xa0, hi: 0xbf}, - // Block 0xdc, offset 0x4aa - {value: 0x5f52, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xdd, offset 0x4ad - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x8a}, - {value: 0x0010, lo: 0x8b, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbe}, - // Block 0xde, offset 0x4b5 - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0014, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x98}, - {value: 0x0014, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0xbf}, - // Block 0xdf, offset 0x4bb - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x86, hi: 0x89}, - {value: 0x0014, lo: 0x8a, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9d, hi: 0x9d}, - // Block 0xe0, offset 0x4c2 - {value: 0x0010, lo: 0x80, hi: 0xb8}, - // Block 0xe1, offset 0x4c3 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xe2, offset 0x4c9 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0xe3, offset 0x4cc - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0014, lo: 0x92, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xa9}, - {value: 0x0014, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0xe4, offset 0x4d4 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb6}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xe5, offset 0x4db - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa5}, - {value: 0x0010, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xbf}, - // Block 0xe6, offset 0x4e5 - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0014, lo: 0x90, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0x96}, - {value: 0x0034, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xe7, offset 0x4ed - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - // Block 0xe8, offset 0x4f0 - {value: 0x0010, lo: 0x80, hi: 0x99}, - // Block 0xe9, offset 0x4f1 - {value: 0x0010, lo: 0x80, hi: 0xae}, - // Block 0xea, offset 0x4f2 - {value: 0x0010, lo: 0x80, hi: 0x83}, - // Block 0xeb, offset 0x4f3 - {value: 0x0010, lo: 0x80, hi: 0x86}, - // Block 0xec, offset 0x4f4 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xed, offset 0x4f6 - {value: 0x0010, lo: 0x90, hi: 0xad}, - {value: 0x0034, lo: 0xb0, hi: 0xb4}, - // Block 0xee, offset 0x4f8 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - // Block 0xef, offset 0x4fa - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa3, hi: 0xb7}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xf0, offset 0x4fe - {value: 0x0010, lo: 0x80, hi: 0x8f}, - // Block 0xf1, offset 0x4ff - {value: 0x2013, lo: 0x80, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xbf}, - // Block 0xf2, offset 0x501 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0xbe}, - // Block 0xf3, offset 0x503 - {value: 0x0014, lo: 0x8f, hi: 0x9f}, - // Block 0xf4, offset 0x504 - {value: 0x0014, lo: 0xa0, hi: 0xa1}, - // Block 0xf5, offset 0x505 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbc}, - // Block 0xf6, offset 0x507 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0034, lo: 0x9e, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa3}, - // Block 0xf7, offset 0x50c - {value: 0x0030, lo: 0xa5, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xa9}, - {value: 0x0030, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbf}, - // Block 0xf8, offset 0x511 - {value: 0x0034, lo: 0x80, hi: 0x82}, - {value: 0x0024, lo: 0x85, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8b}, - {value: 0x0024, lo: 0xaa, hi: 0xad}, - // Block 0xf9, offset 0x515 - {value: 0x0024, lo: 0x82, hi: 0x84}, - // Block 0xfa, offset 0x516 - {value: 0x0013, lo: 0x80, hi: 0x99}, - {value: 0x0012, lo: 0x9a, hi: 0xb3}, - {value: 0x0013, lo: 0xb4, hi: 0xbf}, - // Block 0xfb, offset 0x519 - {value: 0x0013, lo: 0x80, hi: 0x8d}, - {value: 0x0012, lo: 0x8e, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0xa7}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0xfc, offset 0x51d - {value: 0x0013, lo: 0x80, hi: 0x81}, - {value: 0x0012, lo: 0x82, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0x9c}, - {value: 0x0013, lo: 0x9e, hi: 0x9f}, - {value: 0x0013, lo: 0xa2, hi: 0xa2}, - {value: 0x0013, lo: 0xa5, hi: 0xa6}, - {value: 0x0013, lo: 0xa9, hi: 0xac}, - {value: 0x0013, lo: 0xae, hi: 0xb5}, - {value: 0x0012, lo: 0xb6, hi: 0xb9}, - {value: 0x0012, lo: 0xbb, hi: 0xbb}, - {value: 0x0012, lo: 0xbd, hi: 0xbf}, - // Block 0xfd, offset 0x528 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0012, lo: 0x85, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0xfe, offset 0x52c - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0013, lo: 0x84, hi: 0x85}, - {value: 0x0013, lo: 0x87, hi: 0x8a}, - {value: 0x0013, lo: 0x8d, hi: 0x94}, - {value: 0x0013, lo: 0x96, hi: 0x9c}, - {value: 0x0012, lo: 0x9e, hi: 0xb7}, - {value: 0x0013, lo: 0xb8, hi: 0xb9}, - {value: 0x0013, lo: 0xbb, hi: 0xbe}, - // Block 0xff, offset 0x534 - {value: 0x0013, lo: 0x80, hi: 0x84}, - {value: 0x0013, lo: 0x86, hi: 0x86}, - {value: 0x0013, lo: 0x8a, hi: 0x90}, - {value: 0x0012, lo: 0x92, hi: 0xab}, - {value: 0x0013, lo: 0xac, hi: 0xbf}, - // Block 0x100, offset 0x539 - {value: 0x0013, lo: 0x80, hi: 0x85}, - {value: 0x0012, lo: 0x86, hi: 0x9f}, - {value: 0x0013, lo: 0xa0, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbf}, - // Block 0x101, offset 0x53d - {value: 0x0012, lo: 0x80, hi: 0x93}, - {value: 0x0013, lo: 0x94, hi: 0xad}, - {value: 0x0012, lo: 0xae, hi: 0xbf}, - // Block 0x102, offset 0x540 - {value: 0x0012, lo: 0x80, hi: 0x87}, - {value: 0x0013, lo: 0x88, hi: 0xa1}, - {value: 0x0012, lo: 0xa2, hi: 0xbb}, - {value: 0x0013, lo: 0xbc, hi: 0xbf}, - // Block 0x103, offset 0x544 - {value: 0x0013, lo: 0x80, hi: 0x95}, - {value: 0x0012, lo: 0x96, hi: 0xaf}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x104, offset 0x547 - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0012, lo: 0x8a, hi: 0xa5}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x105, offset 0x54a - {value: 0x0013, lo: 0x80, hi: 0x80}, - {value: 0x0012, lo: 0x82, hi: 0x9a}, - {value: 0x0012, lo: 0x9c, hi: 0xa1}, - {value: 0x0013, lo: 0xa2, hi: 0xba}, - {value: 0x0012, lo: 0xbc, hi: 0xbf}, - // Block 0x106, offset 0x54f - {value: 0x0012, lo: 0x80, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0xb4}, - {value: 0x0012, lo: 0xb6, hi: 0xbf}, - // Block 0x107, offset 0x553 - {value: 0x0012, lo: 0x80, hi: 0x8e}, - {value: 0x0012, lo: 0x90, hi: 0x95}, - {value: 0x0013, lo: 0x96, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x108, offset 0x557 - {value: 0x0012, lo: 0x80, hi: 0x88}, - {value: 0x0012, lo: 0x8a, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x109, offset 0x55b - {value: 0x0012, lo: 0x80, hi: 0x82}, - {value: 0x0012, lo: 0x84, hi: 0x89}, - {value: 0x0017, lo: 0x8a, hi: 0x8b}, - {value: 0x0010, lo: 0x8e, hi: 0xbf}, - // Block 0x10a, offset 0x55f - {value: 0x0014, lo: 0x80, hi: 0xb6}, - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x10b, offset 0x561 - {value: 0x0014, lo: 0x80, hi: 0xac}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x10c, offset 0x563 - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x9b, hi: 0x9f}, - {value: 0x0014, lo: 0xa1, hi: 0xaf}, - // Block 0x10d, offset 0x566 - {value: 0x0024, lo: 0x80, hi: 0x86}, - {value: 0x0024, lo: 0x88, hi: 0x98}, - {value: 0x0024, lo: 0x9b, hi: 0xa1}, - {value: 0x0024, lo: 0xa3, hi: 0xa4}, - {value: 0x0024, lo: 0xa6, hi: 0xaa}, - // Block 0x10e, offset 0x56b - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0034, lo: 0x90, hi: 0x96}, - // Block 0x10f, offset 0x56d - {value: 0xb852, lo: 0x80, hi: 0x81}, - {value: 0xbb52, lo: 0x82, hi: 0x83}, - {value: 0x0024, lo: 0x84, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x110, offset 0x572 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x9f}, - {value: 0x0010, lo: 0xa1, hi: 0xa2}, - {value: 0x0010, lo: 0xa4, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb7}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - // Block 0x111, offset 0x57b - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x9b}, - {value: 0x0010, lo: 0xa1, hi: 0xa3}, - {value: 0x0010, lo: 0xa5, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xbb}, - // Block 0x112, offset 0x580 - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x113, offset 0x581 - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x114, offset 0x584 - {value: 0x0013, lo: 0x80, hi: 0x89}, - // Block 0x115, offset 0x585 - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x116, offset 0x586 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0014, lo: 0xa0, hi: 0xbf}, - // Block 0x117, offset 0x588 - {value: 0x0014, lo: 0x80, hi: 0xbf}, - // Block 0x118, offset 0x589 - {value: 0x0014, lo: 0x80, hi: 0xaf}, -} - -// Total table size 14906 bytes (14KiB); checksum: 362795C7 diff --git a/vendor/golang.org/x/text/cases/tables12.0.0.go b/vendor/golang.org/x/text/cases/tables12.0.0.go deleted file mode 100644 index 84d841b1..00000000 --- a/vendor/golang.org/x/text/cases/tables12.0.0.go +++ /dev/null @@ -1,2359 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -//go:build go1.14 && !go1.16 - -package cases - -// UnicodeVersion is the Unicode version from which the tables in this package are derived. -const UnicodeVersion = "12.0.0" - -var xorData string = "" + // Size: 192 bytes - "\x00\x06\x07\x00\x01?\x00\x0f\x03\x00\x0f\x12\x00\x0f\x1f\x00\x0f\x1d" + - "\x00\x01\x13\x00\x0f\x16\x00\x0f\x0b\x00\x0f3\x00\x0f7\x00\x01#\x00\x0f?" + - "\x00\x0e'\x00\x0f/\x00\x0e>\x00\x0f*\x00\x0c&\x00\x0c*\x00\x0c;\x00\x0c9" + - "\x00\x0c%\x00\x01\x08\x00\x03\x0d\x00\x03\x09\x00\x02\x06\x00\x02\x02" + - "\x00\x02\x0c\x00\x01\x00\x00\x01\x03\x00\x01\x01\x00\x01 \x00\x01\x0c" + - "\x00\x01\x10\x00\x03\x10\x00\x036 \x00\x037 \x00\x0b#\x10\x00\x0b 0\x00" + - "\x0b!\x10\x00\x0b!0\x001\x00\x00\x0b(\x04\x00\x03\x04\x1e\x00\x0b)\x08" + - "\x00\x03\x0a\x00\x02:\x00\x02>\x00\x02,\x00\x02\x00\x00\x02\x10\x00\x01<" + - "\x00\x01&\x00\x01*\x00\x01.\x00\x010\x003 \x00\x01\x18\x00\x01(\x00\x01" + - "\x1e\x00\x01\x22" - -var exceptions string = "" + // Size: 2450 bytes - "\x00\x12\x12μΜΜ\x12\x12ssSSSs\x13\x18i̇i̇\x10\x09II\x13\x1bʼnʼNʼN\x11" + - "\x09sSS\x12\x12dždžDž\x12\x12dždžDŽ\x10\x12DŽDž\x12\x12ljljLj\x12\x12ljljLJ\x10\x12LJLj" + - "\x12\x12njnjNj\x12\x12njnjNJ\x10\x12NJNj\x13\x1bǰJ̌J̌\x12\x12dzdzDz\x12\x12dzdzDZ\x10" + - "\x12DZDz\x13\x18ⱥⱥ\x13\x18ⱦⱦ\x10\x1bⱾⱾ\x10\x1bⱿⱿ\x10\x1bⱯⱯ\x10\x1bⱭⱭ\x10" + - "\x1bⱰⱰ\x10\x1bꞫꞫ\x10\x1bꞬꞬ\x10\x1bꞍꞍ\x10\x1bꞪꞪ\x10\x1bꞮꞮ\x10\x1bⱢⱢ\x10" + - "\x1bꞭꞭ\x10\x1bⱮⱮ\x10\x1bⱤⱤ\x10\x1bꟅꟅ\x10\x1bꞱꞱ\x10\x1bꞲꞲ\x10\x1bꞰꞰ2\x12ι" + - "ΙΙ\x166ΐΪ́Ϊ́\x166ΰΫ́Ϋ́\x12\x12σΣΣ\x12\x12βΒΒ\x12\x12θΘΘ\x12\x12" + - "φΦΦ\x12\x12πΠΠ\x12\x12κΚΚ\x12\x12ρΡΡ\x12\x12εΕΕ\x14$եւԵՒԵւ\x10\x1bᲐა" + - "\x10\x1bᲑბ\x10\x1bᲒგ\x10\x1bᲓდ\x10\x1bᲔე\x10\x1bᲕვ\x10\x1bᲖზ\x10\x1bᲗთ" + - "\x10\x1bᲘი\x10\x1bᲙკ\x10\x1bᲚლ\x10\x1bᲛმ\x10\x1bᲜნ\x10\x1bᲝო\x10\x1bᲞპ" + - "\x10\x1bᲟჟ\x10\x1bᲠრ\x10\x1bᲡს\x10\x1bᲢტ\x10\x1bᲣუ\x10\x1bᲤფ\x10\x1bᲥქ" + - "\x10\x1bᲦღ\x10\x1bᲧყ\x10\x1bᲨშ\x10\x1bᲩჩ\x10\x1bᲪც\x10\x1bᲫძ\x10\x1bᲬწ" + - "\x10\x1bᲭჭ\x10\x1bᲮხ\x10\x1bᲯჯ\x10\x1bᲰჰ\x10\x1bᲱჱ\x10\x1bᲲჲ\x10\x1bᲳჳ" + - "\x10\x1bᲴჴ\x10\x1bᲵჵ\x10\x1bᲶჶ\x10\x1bᲷჷ\x10\x1bᲸჸ\x10\x1bᲹჹ\x10\x1bᲺჺ" + - "\x10\x1bᲽჽ\x10\x1bᲾჾ\x10\x1bᲿჿ\x12\x12вВВ\x12\x12дДД\x12\x12оОО\x12\x12с" + - "СС\x12\x12тТТ\x12\x12тТТ\x12\x12ъЪЪ\x12\x12ѣѢѢ\x13\x1bꙋꙊꙊ\x13\x1bẖH̱H̱" + - "\x13\x1bẗT̈T̈\x13\x1bẘW̊W̊\x13\x1bẙY̊Y̊\x13\x1baʾAʾAʾ\x13\x1bṡṠṠ\x12" + - "\x10ssß\x14$ὐΥ̓Υ̓\x166ὒΥ̓̀Υ̓̀\x166ὔΥ̓́Υ̓́\x166ὖΥ̓͂Υ̓͂\x15+ἀιἈΙᾈ" + - "\x15+ἁιἉΙᾉ\x15+ἂιἊΙᾊ\x15+ἃιἋΙᾋ\x15+ἄιἌΙᾌ\x15+ἅιἍΙᾍ\x15+ἆιἎΙᾎ\x15+ἇιἏΙᾏ" + - "\x15\x1dἀιᾀἈΙ\x15\x1dἁιᾁἉΙ\x15\x1dἂιᾂἊΙ\x15\x1dἃιᾃἋΙ\x15\x1dἄιᾄἌΙ\x15" + - "\x1dἅιᾅἍΙ\x15\x1dἆιᾆἎΙ\x15\x1dἇιᾇἏΙ\x15+ἠιἨΙᾘ\x15+ἡιἩΙᾙ\x15+ἢιἪΙᾚ\x15+ἣι" + - "ἫΙᾛ\x15+ἤιἬΙᾜ\x15+ἥιἭΙᾝ\x15+ἦιἮΙᾞ\x15+ἧιἯΙᾟ\x15\x1dἠιᾐἨΙ\x15\x1dἡιᾑἩΙ" + - "\x15\x1dἢιᾒἪΙ\x15\x1dἣιᾓἫΙ\x15\x1dἤιᾔἬΙ\x15\x1dἥιᾕἭΙ\x15\x1dἦιᾖἮΙ\x15" + - "\x1dἧιᾗἯΙ\x15+ὠιὨΙᾨ\x15+ὡιὩΙᾩ\x15+ὢιὪΙᾪ\x15+ὣιὫΙᾫ\x15+ὤιὬΙᾬ\x15+ὥιὭΙᾭ" + - "\x15+ὦιὮΙᾮ\x15+ὧιὯΙᾯ\x15\x1dὠιᾠὨΙ\x15\x1dὡιᾡὩΙ\x15\x1dὢιᾢὪΙ\x15\x1dὣιᾣὫΙ" + - "\x15\x1dὤιᾤὬΙ\x15\x1dὥιᾥὭΙ\x15\x1dὦιᾦὮΙ\x15\x1dὧιᾧὯΙ\x15-ὰιᾺΙᾺͅ\x14#αιΑΙ" + - "ᾼ\x14$άιΆΙΆͅ\x14$ᾶΑ͂Α͂\x166ᾶιΑ͂Ιᾼ͂\x14\x1cαιᾳΑΙ\x12\x12ιΙΙ\x15-ὴιῊΙ" + - "Ὴͅ\x14#ηιΗΙῌ\x14$ήιΉΙΉͅ\x14$ῆΗ͂Η͂\x166ῆιΗ͂Ιῌ͂\x14\x1cηιῃΗΙ\x166ῒΙ" + - "̈̀Ϊ̀\x166ΐΪ́Ϊ́\x14$ῖΙ͂Ι͂\x166ῗΪ͂Ϊ͂\x166ῢΫ̀Ϋ̀\x166ΰΫ́Ϋ" + - "́\x14$ῤΡ̓Ρ̓\x14$ῦΥ͂Υ͂\x166ῧΫ͂Ϋ͂\x15-ὼιῺΙῺͅ\x14#ωιΩΙῼ\x14$ώιΏΙΏͅ" + - "\x14$ῶΩ͂Ω͂\x166ῶιΩ͂Ιῼ͂\x14\x1cωιῳΩΙ\x12\x10ωω\x11\x08kk\x12\x10åå\x12" + - "\x10ɫɫ\x12\x10ɽɽ\x10\x12ȺȺ\x10\x12ȾȾ\x12\x10ɑɑ\x12\x10ɱɱ\x12\x10ɐɐ\x12" + - "\x10ɒɒ\x12\x10ȿȿ\x12\x10ɀɀ\x12\x10ɥɥ\x12\x10ɦɦ\x12\x10ɜɜ\x12\x10ɡɡ\x12" + - "\x10ɬɬ\x12\x10ɪɪ\x12\x10ʞʞ\x12\x10ʇʇ\x12\x10ʝʝ\x12\x10ʂʂ\x12\x12ffFFFf" + - "\x12\x12fiFIFi\x12\x12flFLFl\x13\x1bffiFFIFfi\x13\x1bfflFFLFfl\x12\x12st" + - "STSt\x12\x12stSTSt\x14$մնՄՆՄն\x14$մեՄԵՄե\x14$միՄԻՄի\x14$վնՎՆՎն\x14$մխՄԽՄ" + - "խ" - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookup(s []byte) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupUnsafe(s []byte) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookupString(s string) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupStringUnsafe(s string) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// caseTrie. Total size: 12396 bytes (12.11 KiB). Checksum: c0656238384c3da1. -type caseTrie struct{} - -func newCaseTrie(i int) *caseTrie { - return &caseTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *caseTrie) lookupValue(n uint32, b byte) uint16 { - switch { - case n < 20: - return uint16(caseValues[n<<6+uint32(b)]) - default: - n -= 20 - return uint16(sparse.lookup(n, b)) - } -} - -// caseValues: 22 blocks, 1408 entries, 2816 bytes -// The third block is the zero block. -var caseValues = [1408]uint16{ - // Block 0x0, offset 0x0 - 0x27: 0x0054, - 0x2e: 0x0054, - 0x30: 0x0010, 0x31: 0x0010, 0x32: 0x0010, 0x33: 0x0010, 0x34: 0x0010, 0x35: 0x0010, - 0x36: 0x0010, 0x37: 0x0010, 0x38: 0x0010, 0x39: 0x0010, 0x3a: 0x0054, - // Block 0x1, offset 0x40 - 0x41: 0x2013, 0x42: 0x2013, 0x43: 0x2013, 0x44: 0x2013, 0x45: 0x2013, - 0x46: 0x2013, 0x47: 0x2013, 0x48: 0x2013, 0x49: 0x2013, 0x4a: 0x2013, 0x4b: 0x2013, - 0x4c: 0x2013, 0x4d: 0x2013, 0x4e: 0x2013, 0x4f: 0x2013, 0x50: 0x2013, 0x51: 0x2013, - 0x52: 0x2013, 0x53: 0x2013, 0x54: 0x2013, 0x55: 0x2013, 0x56: 0x2013, 0x57: 0x2013, - 0x58: 0x2013, 0x59: 0x2013, 0x5a: 0x2013, - 0x5e: 0x0004, 0x5f: 0x0010, 0x60: 0x0004, 0x61: 0x2012, 0x62: 0x2012, 0x63: 0x2012, - 0x64: 0x2012, 0x65: 0x2012, 0x66: 0x2012, 0x67: 0x2012, 0x68: 0x2012, 0x69: 0x2012, - 0x6a: 0x2012, 0x6b: 0x2012, 0x6c: 0x2012, 0x6d: 0x2012, 0x6e: 0x2012, 0x6f: 0x2012, - 0x70: 0x2012, 0x71: 0x2012, 0x72: 0x2012, 0x73: 0x2012, 0x74: 0x2012, 0x75: 0x2012, - 0x76: 0x2012, 0x77: 0x2012, 0x78: 0x2012, 0x79: 0x2012, 0x7a: 0x2012, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x0852, 0xc1: 0x0b53, 0xc2: 0x0113, 0xc3: 0x0112, 0xc4: 0x0113, 0xc5: 0x0112, - 0xc6: 0x0b53, 0xc7: 0x0f13, 0xc8: 0x0f12, 0xc9: 0x0e53, 0xca: 0x1153, 0xcb: 0x0713, - 0xcc: 0x0712, 0xcd: 0x0012, 0xce: 0x1453, 0xcf: 0x1753, 0xd0: 0x1a53, 0xd1: 0x0313, - 0xd2: 0x0312, 0xd3: 0x1d53, 0xd4: 0x2053, 0xd5: 0x2352, 0xd6: 0x2653, 0xd7: 0x2653, - 0xd8: 0x0113, 0xd9: 0x0112, 0xda: 0x2952, 0xdb: 0x0012, 0xdc: 0x1d53, 0xdd: 0x2c53, - 0xde: 0x2f52, 0xdf: 0x3253, 0xe0: 0x0113, 0xe1: 0x0112, 0xe2: 0x0113, 0xe3: 0x0112, - 0xe4: 0x0113, 0xe5: 0x0112, 0xe6: 0x3553, 0xe7: 0x0f13, 0xe8: 0x0f12, 0xe9: 0x3853, - 0xea: 0x0012, 0xeb: 0x0012, 0xec: 0x0113, 0xed: 0x0112, 0xee: 0x3553, 0xef: 0x1f13, - 0xf0: 0x1f12, 0xf1: 0x3b53, 0xf2: 0x3e53, 0xf3: 0x0713, 0xf4: 0x0712, 0xf5: 0x0313, - 0xf6: 0x0312, 0xf7: 0x4153, 0xf8: 0x0113, 0xf9: 0x0112, 0xfa: 0x0012, 0xfb: 0x0010, - 0xfc: 0x0113, 0xfd: 0x0112, 0xfe: 0x0012, 0xff: 0x4452, - // Block 0x4, offset 0x100 - 0x100: 0x0010, 0x101: 0x0010, 0x102: 0x0010, 0x103: 0x0010, 0x104: 0x02db, 0x105: 0x0359, - 0x106: 0x03da, 0x107: 0x043b, 0x108: 0x04b9, 0x109: 0x053a, 0x10a: 0x059b, 0x10b: 0x0619, - 0x10c: 0x069a, 0x10d: 0x0313, 0x10e: 0x0312, 0x10f: 0x1f13, 0x110: 0x1f12, 0x111: 0x0313, - 0x112: 0x0312, 0x113: 0x0713, 0x114: 0x0712, 0x115: 0x0313, 0x116: 0x0312, 0x117: 0x0f13, - 0x118: 0x0f12, 0x119: 0x0313, 0x11a: 0x0312, 0x11b: 0x0713, 0x11c: 0x0712, 0x11d: 0x1452, - 0x11e: 0x0113, 0x11f: 0x0112, 0x120: 0x0113, 0x121: 0x0112, 0x122: 0x0113, 0x123: 0x0112, - 0x124: 0x0113, 0x125: 0x0112, 0x126: 0x0113, 0x127: 0x0112, 0x128: 0x0113, 0x129: 0x0112, - 0x12a: 0x0113, 0x12b: 0x0112, 0x12c: 0x0113, 0x12d: 0x0112, 0x12e: 0x0113, 0x12f: 0x0112, - 0x130: 0x06fa, 0x131: 0x07ab, 0x132: 0x0829, 0x133: 0x08aa, 0x134: 0x0113, 0x135: 0x0112, - 0x136: 0x2353, 0x137: 0x4453, 0x138: 0x0113, 0x139: 0x0112, 0x13a: 0x0113, 0x13b: 0x0112, - 0x13c: 0x0113, 0x13d: 0x0112, 0x13e: 0x0113, 0x13f: 0x0112, - // Block 0x5, offset 0x140 - 0x140: 0x0a8a, 0x141: 0x0313, 0x142: 0x0312, 0x143: 0x0853, 0x144: 0x4753, 0x145: 0x4a53, - 0x146: 0x0113, 0x147: 0x0112, 0x148: 0x0113, 0x149: 0x0112, 0x14a: 0x0113, 0x14b: 0x0112, - 0x14c: 0x0113, 0x14d: 0x0112, 0x14e: 0x0113, 0x14f: 0x0112, 0x150: 0x0b0a, 0x151: 0x0b8a, - 0x152: 0x0c0a, 0x153: 0x0b52, 0x154: 0x0b52, 0x155: 0x0012, 0x156: 0x0e52, 0x157: 0x1152, - 0x158: 0x0012, 0x159: 0x1752, 0x15a: 0x0012, 0x15b: 0x1a52, 0x15c: 0x0c8a, 0x15d: 0x0012, - 0x15e: 0x0012, 0x15f: 0x0012, 0x160: 0x1d52, 0x161: 0x0d0a, 0x162: 0x0012, 0x163: 0x2052, - 0x164: 0x0012, 0x165: 0x0d8a, 0x166: 0x0e0a, 0x167: 0x0012, 0x168: 0x2652, 0x169: 0x2652, - 0x16a: 0x0e8a, 0x16b: 0x0f0a, 0x16c: 0x0f8a, 0x16d: 0x0012, 0x16e: 0x0012, 0x16f: 0x1d52, - 0x170: 0x0012, 0x171: 0x100a, 0x172: 0x2c52, 0x173: 0x0012, 0x174: 0x0012, 0x175: 0x3252, - 0x176: 0x0012, 0x177: 0x0012, 0x178: 0x0012, 0x179: 0x0012, 0x17a: 0x0012, 0x17b: 0x0012, - 0x17c: 0x0012, 0x17d: 0x108a, 0x17e: 0x0012, 0x17f: 0x0012, - // Block 0x6, offset 0x180 - 0x180: 0x3552, 0x181: 0x0012, 0x182: 0x110a, 0x183: 0x3852, 0x184: 0x0012, 0x185: 0x0012, - 0x186: 0x0012, 0x187: 0x118a, 0x188: 0x3552, 0x189: 0x4752, 0x18a: 0x3b52, 0x18b: 0x3e52, - 0x18c: 0x4a52, 0x18d: 0x0012, 0x18e: 0x0012, 0x18f: 0x0012, 0x190: 0x0012, 0x191: 0x0012, - 0x192: 0x4152, 0x193: 0x0012, 0x194: 0x0010, 0x195: 0x0012, 0x196: 0x0012, 0x197: 0x0012, - 0x198: 0x0012, 0x199: 0x0012, 0x19a: 0x0012, 0x19b: 0x0012, 0x19c: 0x0012, 0x19d: 0x120a, - 0x19e: 0x128a, 0x19f: 0x0012, 0x1a0: 0x0012, 0x1a1: 0x0012, 0x1a2: 0x0012, 0x1a3: 0x0012, - 0x1a4: 0x0012, 0x1a5: 0x0012, 0x1a6: 0x0012, 0x1a7: 0x0012, 0x1a8: 0x0012, 0x1a9: 0x0012, - 0x1aa: 0x0012, 0x1ab: 0x0012, 0x1ac: 0x0012, 0x1ad: 0x0012, 0x1ae: 0x0012, 0x1af: 0x0012, - 0x1b0: 0x0015, 0x1b1: 0x0015, 0x1b2: 0x0015, 0x1b3: 0x0015, 0x1b4: 0x0015, 0x1b5: 0x0015, - 0x1b6: 0x0015, 0x1b7: 0x0015, 0x1b8: 0x0015, 0x1b9: 0x0014, 0x1ba: 0x0014, 0x1bb: 0x0014, - 0x1bc: 0x0014, 0x1bd: 0x0014, 0x1be: 0x0014, 0x1bf: 0x0014, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x0024, 0x1c1: 0x0024, 0x1c2: 0x0024, 0x1c3: 0x0024, 0x1c4: 0x0024, 0x1c5: 0x130d, - 0x1c6: 0x0024, 0x1c7: 0x0034, 0x1c8: 0x0034, 0x1c9: 0x0034, 0x1ca: 0x0024, 0x1cb: 0x0024, - 0x1cc: 0x0024, 0x1cd: 0x0034, 0x1ce: 0x0034, 0x1cf: 0x0014, 0x1d0: 0x0024, 0x1d1: 0x0024, - 0x1d2: 0x0024, 0x1d3: 0x0034, 0x1d4: 0x0034, 0x1d5: 0x0034, 0x1d6: 0x0034, 0x1d7: 0x0024, - 0x1d8: 0x0034, 0x1d9: 0x0034, 0x1da: 0x0034, 0x1db: 0x0024, 0x1dc: 0x0034, 0x1dd: 0x0034, - 0x1de: 0x0034, 0x1df: 0x0034, 0x1e0: 0x0034, 0x1e1: 0x0034, 0x1e2: 0x0034, 0x1e3: 0x0024, - 0x1e4: 0x0024, 0x1e5: 0x0024, 0x1e6: 0x0024, 0x1e7: 0x0024, 0x1e8: 0x0024, 0x1e9: 0x0024, - 0x1ea: 0x0024, 0x1eb: 0x0024, 0x1ec: 0x0024, 0x1ed: 0x0024, 0x1ee: 0x0024, 0x1ef: 0x0024, - 0x1f0: 0x0113, 0x1f1: 0x0112, 0x1f2: 0x0113, 0x1f3: 0x0112, 0x1f4: 0x0014, 0x1f5: 0x0004, - 0x1f6: 0x0113, 0x1f7: 0x0112, 0x1fa: 0x0015, 0x1fb: 0x4d52, - 0x1fc: 0x5052, 0x1fd: 0x5052, 0x1ff: 0x5353, - // Block 0x8, offset 0x200 - 0x204: 0x0004, 0x205: 0x0004, - 0x206: 0x2a13, 0x207: 0x0054, 0x208: 0x2513, 0x209: 0x2713, 0x20a: 0x2513, - 0x20c: 0x5653, 0x20e: 0x5953, 0x20f: 0x5c53, 0x210: 0x138a, 0x211: 0x2013, - 0x212: 0x2013, 0x213: 0x2013, 0x214: 0x2013, 0x215: 0x2013, 0x216: 0x2013, 0x217: 0x2013, - 0x218: 0x2013, 0x219: 0x2013, 0x21a: 0x2013, 0x21b: 0x2013, 0x21c: 0x2013, 0x21d: 0x2013, - 0x21e: 0x2013, 0x21f: 0x2013, 0x220: 0x5f53, 0x221: 0x5f53, 0x223: 0x5f53, - 0x224: 0x5f53, 0x225: 0x5f53, 0x226: 0x5f53, 0x227: 0x5f53, 0x228: 0x5f53, 0x229: 0x5f53, - 0x22a: 0x5f53, 0x22b: 0x5f53, 0x22c: 0x2a12, 0x22d: 0x2512, 0x22e: 0x2712, 0x22f: 0x2512, - 0x230: 0x14ca, 0x231: 0x2012, 0x232: 0x2012, 0x233: 0x2012, 0x234: 0x2012, 0x235: 0x2012, - 0x236: 0x2012, 0x237: 0x2012, 0x238: 0x2012, 0x239: 0x2012, 0x23a: 0x2012, 0x23b: 0x2012, - 0x23c: 0x2012, 0x23d: 0x2012, 0x23e: 0x2012, 0x23f: 0x2012, - // Block 0x9, offset 0x240 - 0x240: 0x5f52, 0x241: 0x5f52, 0x242: 0x160a, 0x243: 0x5f52, 0x244: 0x5f52, 0x245: 0x5f52, - 0x246: 0x5f52, 0x247: 0x5f52, 0x248: 0x5f52, 0x249: 0x5f52, 0x24a: 0x5f52, 0x24b: 0x5f52, - 0x24c: 0x5652, 0x24d: 0x5952, 0x24e: 0x5c52, 0x24f: 0x1813, 0x250: 0x168a, 0x251: 0x170a, - 0x252: 0x0013, 0x253: 0x0013, 0x254: 0x0013, 0x255: 0x178a, 0x256: 0x180a, 0x257: 0x1812, - 0x258: 0x0113, 0x259: 0x0112, 0x25a: 0x0113, 0x25b: 0x0112, 0x25c: 0x0113, 0x25d: 0x0112, - 0x25e: 0x0113, 0x25f: 0x0112, 0x260: 0x0113, 0x261: 0x0112, 0x262: 0x0113, 0x263: 0x0112, - 0x264: 0x0113, 0x265: 0x0112, 0x266: 0x0113, 0x267: 0x0112, 0x268: 0x0113, 0x269: 0x0112, - 0x26a: 0x0113, 0x26b: 0x0112, 0x26c: 0x0113, 0x26d: 0x0112, 0x26e: 0x0113, 0x26f: 0x0112, - 0x270: 0x188a, 0x271: 0x190a, 0x272: 0x0b12, 0x273: 0x5352, 0x274: 0x6253, 0x275: 0x198a, - 0x277: 0x0f13, 0x278: 0x0f12, 0x279: 0x0b13, 0x27a: 0x0113, 0x27b: 0x0112, - 0x27c: 0x0012, 0x27d: 0x4d53, 0x27e: 0x5053, 0x27f: 0x5053, - // Block 0xa, offset 0x280 - 0x280: 0x6852, 0x281: 0x6852, 0x282: 0x6852, 0x283: 0x6852, 0x284: 0x6852, 0x285: 0x6852, - 0x286: 0x6852, 0x287: 0x1a0a, 0x288: 0x0012, - 0x291: 0x0034, - 0x292: 0x0024, 0x293: 0x0024, 0x294: 0x0024, 0x295: 0x0024, 0x296: 0x0034, 0x297: 0x0024, - 0x298: 0x0024, 0x299: 0x0024, 0x29a: 0x0034, 0x29b: 0x0034, 0x29c: 0x0024, 0x29d: 0x0024, - 0x29e: 0x0024, 0x29f: 0x0024, 0x2a0: 0x0024, 0x2a1: 0x0024, 0x2a2: 0x0034, 0x2a3: 0x0034, - 0x2a4: 0x0034, 0x2a5: 0x0034, 0x2a6: 0x0034, 0x2a7: 0x0034, 0x2a8: 0x0024, 0x2a9: 0x0024, - 0x2aa: 0x0034, 0x2ab: 0x0024, 0x2ac: 0x0024, 0x2ad: 0x0034, 0x2ae: 0x0034, 0x2af: 0x0024, - 0x2b0: 0x0034, 0x2b1: 0x0034, 0x2b2: 0x0034, 0x2b3: 0x0034, 0x2b4: 0x0034, 0x2b5: 0x0034, - 0x2b6: 0x0034, 0x2b7: 0x0034, 0x2b8: 0x0034, 0x2b9: 0x0034, 0x2ba: 0x0034, 0x2bb: 0x0034, - 0x2bc: 0x0034, 0x2bd: 0x0034, 0x2bf: 0x0034, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x7053, 0x2c1: 0x7053, 0x2c2: 0x7053, 0x2c3: 0x7053, 0x2c4: 0x7053, 0x2c5: 0x7053, - 0x2c7: 0x7053, - 0x2cd: 0x7053, 0x2d0: 0x1aea, 0x2d1: 0x1b6a, - 0x2d2: 0x1bea, 0x2d3: 0x1c6a, 0x2d4: 0x1cea, 0x2d5: 0x1d6a, 0x2d6: 0x1dea, 0x2d7: 0x1e6a, - 0x2d8: 0x1eea, 0x2d9: 0x1f6a, 0x2da: 0x1fea, 0x2db: 0x206a, 0x2dc: 0x20ea, 0x2dd: 0x216a, - 0x2de: 0x21ea, 0x2df: 0x226a, 0x2e0: 0x22ea, 0x2e1: 0x236a, 0x2e2: 0x23ea, 0x2e3: 0x246a, - 0x2e4: 0x24ea, 0x2e5: 0x256a, 0x2e6: 0x25ea, 0x2e7: 0x266a, 0x2e8: 0x26ea, 0x2e9: 0x276a, - 0x2ea: 0x27ea, 0x2eb: 0x286a, 0x2ec: 0x28ea, 0x2ed: 0x296a, 0x2ee: 0x29ea, 0x2ef: 0x2a6a, - 0x2f0: 0x2aea, 0x2f1: 0x2b6a, 0x2f2: 0x2bea, 0x2f3: 0x2c6a, 0x2f4: 0x2cea, 0x2f5: 0x2d6a, - 0x2f6: 0x2dea, 0x2f7: 0x2e6a, 0x2f8: 0x2eea, 0x2f9: 0x2f6a, 0x2fa: 0x2fea, - 0x2fc: 0x0014, 0x2fd: 0x306a, 0x2fe: 0x30ea, 0x2ff: 0x316a, - // Block 0xc, offset 0x300 - 0x300: 0x0812, 0x301: 0x0812, 0x302: 0x0812, 0x303: 0x0812, 0x304: 0x0812, 0x305: 0x0812, - 0x308: 0x0813, 0x309: 0x0813, 0x30a: 0x0813, 0x30b: 0x0813, - 0x30c: 0x0813, 0x30d: 0x0813, 0x310: 0x3b1a, 0x311: 0x0812, - 0x312: 0x3bfa, 0x313: 0x0812, 0x314: 0x3d3a, 0x315: 0x0812, 0x316: 0x3e7a, 0x317: 0x0812, - 0x319: 0x0813, 0x31b: 0x0813, 0x31d: 0x0813, - 0x31f: 0x0813, 0x320: 0x0812, 0x321: 0x0812, 0x322: 0x0812, 0x323: 0x0812, - 0x324: 0x0812, 0x325: 0x0812, 0x326: 0x0812, 0x327: 0x0812, 0x328: 0x0813, 0x329: 0x0813, - 0x32a: 0x0813, 0x32b: 0x0813, 0x32c: 0x0813, 0x32d: 0x0813, 0x32e: 0x0813, 0x32f: 0x0813, - 0x330: 0x9252, 0x331: 0x9252, 0x332: 0x9552, 0x333: 0x9552, 0x334: 0x9852, 0x335: 0x9852, - 0x336: 0x9b52, 0x337: 0x9b52, 0x338: 0x9e52, 0x339: 0x9e52, 0x33a: 0xa152, 0x33b: 0xa152, - 0x33c: 0x4d52, 0x33d: 0x4d52, - // Block 0xd, offset 0x340 - 0x340: 0x3fba, 0x341: 0x40aa, 0x342: 0x419a, 0x343: 0x428a, 0x344: 0x437a, 0x345: 0x446a, - 0x346: 0x455a, 0x347: 0x464a, 0x348: 0x4739, 0x349: 0x4829, 0x34a: 0x4919, 0x34b: 0x4a09, - 0x34c: 0x4af9, 0x34d: 0x4be9, 0x34e: 0x4cd9, 0x34f: 0x4dc9, 0x350: 0x4eba, 0x351: 0x4faa, - 0x352: 0x509a, 0x353: 0x518a, 0x354: 0x527a, 0x355: 0x536a, 0x356: 0x545a, 0x357: 0x554a, - 0x358: 0x5639, 0x359: 0x5729, 0x35a: 0x5819, 0x35b: 0x5909, 0x35c: 0x59f9, 0x35d: 0x5ae9, - 0x35e: 0x5bd9, 0x35f: 0x5cc9, 0x360: 0x5dba, 0x361: 0x5eaa, 0x362: 0x5f9a, 0x363: 0x608a, - 0x364: 0x617a, 0x365: 0x626a, 0x366: 0x635a, 0x367: 0x644a, 0x368: 0x6539, 0x369: 0x6629, - 0x36a: 0x6719, 0x36b: 0x6809, 0x36c: 0x68f9, 0x36d: 0x69e9, 0x36e: 0x6ad9, 0x36f: 0x6bc9, - 0x370: 0x0812, 0x371: 0x0812, 0x372: 0x6cba, 0x373: 0x6dca, 0x374: 0x6e9a, - 0x376: 0x6f7a, 0x377: 0x705a, 0x378: 0x0813, 0x379: 0x0813, 0x37a: 0x9253, 0x37b: 0x9253, - 0x37c: 0x7199, 0x37d: 0x0004, 0x37e: 0x726a, 0x37f: 0x0004, - // Block 0xe, offset 0x380 - 0x380: 0x0004, 0x381: 0x0004, 0x382: 0x72ea, 0x383: 0x73fa, 0x384: 0x74ca, - 0x386: 0x75aa, 0x387: 0x768a, 0x388: 0x9553, 0x389: 0x9553, 0x38a: 0x9853, 0x38b: 0x9853, - 0x38c: 0x77c9, 0x38d: 0x0004, 0x38e: 0x0004, 0x38f: 0x0004, 0x390: 0x0812, 0x391: 0x0812, - 0x392: 0x789a, 0x393: 0x79da, 0x396: 0x7b1a, 0x397: 0x7bfa, - 0x398: 0x0813, 0x399: 0x0813, 0x39a: 0x9b53, 0x39b: 0x9b53, 0x39d: 0x0004, - 0x39e: 0x0004, 0x39f: 0x0004, 0x3a0: 0x0812, 0x3a1: 0x0812, 0x3a2: 0x7d3a, 0x3a3: 0x7e7a, - 0x3a4: 0x7fba, 0x3a5: 0x0912, 0x3a6: 0x809a, 0x3a7: 0x817a, 0x3a8: 0x0813, 0x3a9: 0x0813, - 0x3aa: 0xa153, 0x3ab: 0xa153, 0x3ac: 0x0913, 0x3ad: 0x0004, 0x3ae: 0x0004, 0x3af: 0x0004, - 0x3b2: 0x82ba, 0x3b3: 0x83ca, 0x3b4: 0x849a, - 0x3b6: 0x857a, 0x3b7: 0x865a, 0x3b8: 0x9e53, 0x3b9: 0x9e53, 0x3ba: 0x4d53, 0x3bb: 0x4d53, - 0x3bc: 0x8799, 0x3bd: 0x0004, 0x3be: 0x0004, - // Block 0xf, offset 0x3c0 - 0x3c2: 0x0013, - 0x3c7: 0x0013, 0x3ca: 0x0012, 0x3cb: 0x0013, - 0x3cc: 0x0013, 0x3cd: 0x0013, 0x3ce: 0x0012, 0x3cf: 0x0012, 0x3d0: 0x0013, 0x3d1: 0x0013, - 0x3d2: 0x0013, 0x3d3: 0x0012, 0x3d5: 0x0013, - 0x3d9: 0x0013, 0x3da: 0x0013, 0x3db: 0x0013, 0x3dc: 0x0013, 0x3dd: 0x0013, - 0x3e4: 0x0013, 0x3e6: 0x886b, 0x3e8: 0x0013, - 0x3ea: 0x88cb, 0x3eb: 0x890b, 0x3ec: 0x0013, 0x3ed: 0x0013, 0x3ef: 0x0012, - 0x3f0: 0x0013, 0x3f1: 0x0013, 0x3f2: 0xa453, 0x3f3: 0x0013, 0x3f4: 0x0012, 0x3f5: 0x0010, - 0x3f6: 0x0010, 0x3f7: 0x0010, 0x3f8: 0x0010, 0x3f9: 0x0012, - 0x3fc: 0x0012, 0x3fd: 0x0012, 0x3fe: 0x0013, 0x3ff: 0x0013, - // Block 0x10, offset 0x400 - 0x400: 0x1a13, 0x401: 0x1a13, 0x402: 0x1e13, 0x403: 0x1e13, 0x404: 0x1a13, 0x405: 0x1a13, - 0x406: 0x2613, 0x407: 0x2613, 0x408: 0x2a13, 0x409: 0x2a13, 0x40a: 0x2e13, 0x40b: 0x2e13, - 0x40c: 0x2a13, 0x40d: 0x2a13, 0x40e: 0x2613, 0x40f: 0x2613, 0x410: 0xa752, 0x411: 0xa752, - 0x412: 0xaa52, 0x413: 0xaa52, 0x414: 0xad52, 0x415: 0xad52, 0x416: 0xaa52, 0x417: 0xaa52, - 0x418: 0xa752, 0x419: 0xa752, 0x41a: 0x1a12, 0x41b: 0x1a12, 0x41c: 0x1e12, 0x41d: 0x1e12, - 0x41e: 0x1a12, 0x41f: 0x1a12, 0x420: 0x2612, 0x421: 0x2612, 0x422: 0x2a12, 0x423: 0x2a12, - 0x424: 0x2e12, 0x425: 0x2e12, 0x426: 0x2a12, 0x427: 0x2a12, 0x428: 0x2612, 0x429: 0x2612, - // Block 0x11, offset 0x440 - 0x440: 0x6552, 0x441: 0x6552, 0x442: 0x6552, 0x443: 0x6552, 0x444: 0x6552, 0x445: 0x6552, - 0x446: 0x6552, 0x447: 0x6552, 0x448: 0x6552, 0x449: 0x6552, 0x44a: 0x6552, 0x44b: 0x6552, - 0x44c: 0x6552, 0x44d: 0x6552, 0x44e: 0x6552, 0x44f: 0x6552, 0x450: 0xb052, 0x451: 0xb052, - 0x452: 0xb052, 0x453: 0xb052, 0x454: 0xb052, 0x455: 0xb052, 0x456: 0xb052, 0x457: 0xb052, - 0x458: 0xb052, 0x459: 0xb052, 0x45a: 0xb052, 0x45b: 0xb052, 0x45c: 0xb052, 0x45d: 0xb052, - 0x45e: 0xb052, 0x460: 0x0113, 0x461: 0x0112, 0x462: 0x896b, 0x463: 0x8b53, - 0x464: 0x89cb, 0x465: 0x8a2a, 0x466: 0x8a8a, 0x467: 0x0f13, 0x468: 0x0f12, 0x469: 0x0313, - 0x46a: 0x0312, 0x46b: 0x0713, 0x46c: 0x0712, 0x46d: 0x8aeb, 0x46e: 0x8b4b, 0x46f: 0x8bab, - 0x470: 0x8c0b, 0x471: 0x0012, 0x472: 0x0113, 0x473: 0x0112, 0x474: 0x0012, 0x475: 0x0313, - 0x476: 0x0312, 0x477: 0x0012, 0x478: 0x0012, 0x479: 0x0012, 0x47a: 0x0012, 0x47b: 0x0012, - 0x47c: 0x0015, 0x47d: 0x0015, 0x47e: 0x8c6b, 0x47f: 0x8ccb, - // Block 0x12, offset 0x480 - 0x480: 0x0113, 0x481: 0x0112, 0x482: 0x0113, 0x483: 0x0112, 0x484: 0x0113, 0x485: 0x0112, - 0x486: 0x0113, 0x487: 0x0112, 0x488: 0x0014, 0x489: 0x0014, 0x48a: 0x0014, 0x48b: 0x0713, - 0x48c: 0x0712, 0x48d: 0x8d2b, 0x48e: 0x0012, 0x48f: 0x0010, 0x490: 0x0113, 0x491: 0x0112, - 0x492: 0x0113, 0x493: 0x0112, 0x494: 0x6552, 0x495: 0x0012, 0x496: 0x0113, 0x497: 0x0112, - 0x498: 0x0113, 0x499: 0x0112, 0x49a: 0x0113, 0x49b: 0x0112, 0x49c: 0x0113, 0x49d: 0x0112, - 0x49e: 0x0113, 0x49f: 0x0112, 0x4a0: 0x0113, 0x4a1: 0x0112, 0x4a2: 0x0113, 0x4a3: 0x0112, - 0x4a4: 0x0113, 0x4a5: 0x0112, 0x4a6: 0x0113, 0x4a7: 0x0112, 0x4a8: 0x0113, 0x4a9: 0x0112, - 0x4aa: 0x8d8b, 0x4ab: 0x8deb, 0x4ac: 0x8e4b, 0x4ad: 0x8eab, 0x4ae: 0x8f0b, 0x4af: 0x0012, - 0x4b0: 0x8f6b, 0x4b1: 0x8fcb, 0x4b2: 0x902b, 0x4b3: 0xb353, 0x4b4: 0x0113, 0x4b5: 0x0112, - 0x4b6: 0x0113, 0x4b7: 0x0112, 0x4b8: 0x0113, 0x4b9: 0x0112, 0x4ba: 0x0113, 0x4bb: 0x0112, - 0x4bc: 0x0113, 0x4bd: 0x0112, 0x4be: 0x0113, 0x4bf: 0x0112, - // Block 0x13, offset 0x4c0 - 0x4c0: 0x90ea, 0x4c1: 0x916a, 0x4c2: 0x91ea, 0x4c3: 0x926a, 0x4c4: 0x931a, 0x4c5: 0x93ca, - 0x4c6: 0x944a, - 0x4d3: 0x94ca, 0x4d4: 0x95aa, 0x4d5: 0x968a, 0x4d6: 0x976a, 0x4d7: 0x984a, - 0x4dd: 0x0010, - 0x4de: 0x0034, 0x4df: 0x0010, 0x4e0: 0x0010, 0x4e1: 0x0010, 0x4e2: 0x0010, 0x4e3: 0x0010, - 0x4e4: 0x0010, 0x4e5: 0x0010, 0x4e6: 0x0010, 0x4e7: 0x0010, 0x4e8: 0x0010, - 0x4ea: 0x0010, 0x4eb: 0x0010, 0x4ec: 0x0010, 0x4ed: 0x0010, 0x4ee: 0x0010, 0x4ef: 0x0010, - 0x4f0: 0x0010, 0x4f1: 0x0010, 0x4f2: 0x0010, 0x4f3: 0x0010, 0x4f4: 0x0010, 0x4f5: 0x0010, - 0x4f6: 0x0010, 0x4f8: 0x0010, 0x4f9: 0x0010, 0x4fa: 0x0010, 0x4fb: 0x0010, - 0x4fc: 0x0010, 0x4fe: 0x0010, - // Block 0x14, offset 0x500 - 0x500: 0x2213, 0x501: 0x2213, 0x502: 0x2613, 0x503: 0x2613, 0x504: 0x2213, 0x505: 0x2213, - 0x506: 0x2e13, 0x507: 0x2e13, 0x508: 0x2213, 0x509: 0x2213, 0x50a: 0x2613, 0x50b: 0x2613, - 0x50c: 0x2213, 0x50d: 0x2213, 0x50e: 0x3e13, 0x50f: 0x3e13, 0x510: 0x2213, 0x511: 0x2213, - 0x512: 0x2613, 0x513: 0x2613, 0x514: 0x2213, 0x515: 0x2213, 0x516: 0x2e13, 0x517: 0x2e13, - 0x518: 0x2213, 0x519: 0x2213, 0x51a: 0x2613, 0x51b: 0x2613, 0x51c: 0x2213, 0x51d: 0x2213, - 0x51e: 0xbc53, 0x51f: 0xbc53, 0x520: 0xbf53, 0x521: 0xbf53, 0x522: 0x2212, 0x523: 0x2212, - 0x524: 0x2612, 0x525: 0x2612, 0x526: 0x2212, 0x527: 0x2212, 0x528: 0x2e12, 0x529: 0x2e12, - 0x52a: 0x2212, 0x52b: 0x2212, 0x52c: 0x2612, 0x52d: 0x2612, 0x52e: 0x2212, 0x52f: 0x2212, - 0x530: 0x3e12, 0x531: 0x3e12, 0x532: 0x2212, 0x533: 0x2212, 0x534: 0x2612, 0x535: 0x2612, - 0x536: 0x2212, 0x537: 0x2212, 0x538: 0x2e12, 0x539: 0x2e12, 0x53a: 0x2212, 0x53b: 0x2212, - 0x53c: 0x2612, 0x53d: 0x2612, 0x53e: 0x2212, 0x53f: 0x2212, - // Block 0x15, offset 0x540 - 0x542: 0x0010, - 0x547: 0x0010, 0x549: 0x0010, 0x54b: 0x0010, - 0x54d: 0x0010, 0x54e: 0x0010, 0x54f: 0x0010, 0x551: 0x0010, - 0x552: 0x0010, 0x554: 0x0010, 0x557: 0x0010, - 0x559: 0x0010, 0x55b: 0x0010, 0x55d: 0x0010, - 0x55f: 0x0010, 0x561: 0x0010, 0x562: 0x0010, - 0x564: 0x0010, 0x567: 0x0010, 0x568: 0x0010, 0x569: 0x0010, - 0x56a: 0x0010, 0x56c: 0x0010, 0x56d: 0x0010, 0x56e: 0x0010, 0x56f: 0x0010, - 0x570: 0x0010, 0x571: 0x0010, 0x572: 0x0010, 0x574: 0x0010, 0x575: 0x0010, - 0x576: 0x0010, 0x577: 0x0010, 0x579: 0x0010, 0x57a: 0x0010, 0x57b: 0x0010, - 0x57c: 0x0010, 0x57e: 0x0010, -} - -// caseIndex: 25 blocks, 1600 entries, 3200 bytes -// Block 0 is the zero block. -var caseIndex = [1600]uint16{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x14, 0xc3: 0x15, 0xc4: 0x16, 0xc5: 0x17, 0xc6: 0x01, 0xc7: 0x02, - 0xc8: 0x18, 0xc9: 0x03, 0xca: 0x04, 0xcb: 0x19, 0xcc: 0x1a, 0xcd: 0x05, 0xce: 0x06, 0xcf: 0x07, - 0xd0: 0x1b, 0xd1: 0x1c, 0xd2: 0x1d, 0xd3: 0x1e, 0xd4: 0x1f, 0xd5: 0x20, 0xd6: 0x08, 0xd7: 0x21, - 0xd8: 0x22, 0xd9: 0x23, 0xda: 0x24, 0xdb: 0x25, 0xdc: 0x26, 0xdd: 0x27, 0xde: 0x28, 0xdf: 0x29, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, - 0xea: 0x06, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x08, 0xef: 0x09, - 0xf0: 0x14, 0xf3: 0x16, - // Block 0x4, offset 0x100 - 0x120: 0x2a, 0x121: 0x2b, 0x122: 0x2c, 0x123: 0x2d, 0x124: 0x2e, 0x125: 0x2f, 0x126: 0x30, 0x127: 0x31, - 0x128: 0x32, 0x129: 0x33, 0x12a: 0x34, 0x12b: 0x35, 0x12c: 0x36, 0x12d: 0x37, 0x12e: 0x38, 0x12f: 0x39, - 0x130: 0x3a, 0x131: 0x3b, 0x132: 0x3c, 0x133: 0x3d, 0x134: 0x3e, 0x135: 0x3f, 0x136: 0x40, 0x137: 0x41, - 0x138: 0x42, 0x139: 0x43, 0x13a: 0x44, 0x13b: 0x45, 0x13c: 0x46, 0x13d: 0x47, 0x13e: 0x48, 0x13f: 0x49, - // Block 0x5, offset 0x140 - 0x140: 0x4a, 0x141: 0x4b, 0x142: 0x4c, 0x143: 0x09, 0x144: 0x24, 0x145: 0x24, 0x146: 0x24, 0x147: 0x24, - 0x148: 0x24, 0x149: 0x4d, 0x14a: 0x4e, 0x14b: 0x4f, 0x14c: 0x50, 0x14d: 0x51, 0x14e: 0x52, 0x14f: 0x53, - 0x150: 0x54, 0x151: 0x24, 0x152: 0x24, 0x153: 0x24, 0x154: 0x24, 0x155: 0x24, 0x156: 0x24, 0x157: 0x24, - 0x158: 0x24, 0x159: 0x55, 0x15a: 0x56, 0x15b: 0x57, 0x15c: 0x58, 0x15d: 0x59, 0x15e: 0x5a, 0x15f: 0x5b, - 0x160: 0x5c, 0x161: 0x5d, 0x162: 0x5e, 0x163: 0x5f, 0x164: 0x60, 0x165: 0x61, 0x167: 0x62, - 0x168: 0x63, 0x169: 0x64, 0x16a: 0x65, 0x16c: 0x66, 0x16d: 0x67, 0x16e: 0x68, 0x16f: 0x69, - 0x170: 0x6a, 0x171: 0x6b, 0x172: 0x6c, 0x173: 0x6d, 0x174: 0x6e, 0x175: 0x6f, 0x176: 0x70, 0x177: 0x71, - 0x178: 0x72, 0x179: 0x72, 0x17a: 0x73, 0x17b: 0x72, 0x17c: 0x74, 0x17d: 0x0a, 0x17e: 0x0b, 0x17f: 0x0c, - // Block 0x6, offset 0x180 - 0x180: 0x75, 0x181: 0x76, 0x182: 0x77, 0x183: 0x78, 0x184: 0x0d, 0x185: 0x79, 0x186: 0x7a, - 0x192: 0x7b, 0x193: 0x0e, - 0x1b0: 0x7c, 0x1b1: 0x0f, 0x1b2: 0x72, 0x1b3: 0x7d, 0x1b4: 0x7e, 0x1b5: 0x7f, 0x1b6: 0x80, 0x1b7: 0x81, - 0x1b8: 0x82, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x83, 0x1c2: 0x84, 0x1c3: 0x85, 0x1c4: 0x86, 0x1c5: 0x24, 0x1c6: 0x87, - // Block 0x8, offset 0x200 - 0x200: 0x88, 0x201: 0x24, 0x202: 0x24, 0x203: 0x24, 0x204: 0x24, 0x205: 0x24, 0x206: 0x24, 0x207: 0x24, - 0x208: 0x24, 0x209: 0x24, 0x20a: 0x24, 0x20b: 0x24, 0x20c: 0x24, 0x20d: 0x24, 0x20e: 0x24, 0x20f: 0x24, - 0x210: 0x24, 0x211: 0x24, 0x212: 0x89, 0x213: 0x8a, 0x214: 0x24, 0x215: 0x24, 0x216: 0x24, 0x217: 0x24, - 0x218: 0x8b, 0x219: 0x8c, 0x21a: 0x8d, 0x21b: 0x8e, 0x21c: 0x8f, 0x21d: 0x90, 0x21e: 0x10, 0x21f: 0x91, - 0x220: 0x92, 0x221: 0x93, 0x222: 0x24, 0x223: 0x94, 0x224: 0x95, 0x225: 0x96, 0x226: 0x97, 0x227: 0x98, - 0x228: 0x99, 0x229: 0x9a, 0x22a: 0x9b, 0x22b: 0x9c, 0x22c: 0x9d, 0x22d: 0x9e, 0x22e: 0x9f, 0x22f: 0xa0, - 0x230: 0x24, 0x231: 0x24, 0x232: 0x24, 0x233: 0x24, 0x234: 0x24, 0x235: 0x24, 0x236: 0x24, 0x237: 0x24, - 0x238: 0x24, 0x239: 0x24, 0x23a: 0x24, 0x23b: 0x24, 0x23c: 0x24, 0x23d: 0x24, 0x23e: 0x24, 0x23f: 0x24, - // Block 0x9, offset 0x240 - 0x240: 0x24, 0x241: 0x24, 0x242: 0x24, 0x243: 0x24, 0x244: 0x24, 0x245: 0x24, 0x246: 0x24, 0x247: 0x24, - 0x248: 0x24, 0x249: 0x24, 0x24a: 0x24, 0x24b: 0x24, 0x24c: 0x24, 0x24d: 0x24, 0x24e: 0x24, 0x24f: 0x24, - 0x250: 0x24, 0x251: 0x24, 0x252: 0x24, 0x253: 0x24, 0x254: 0x24, 0x255: 0x24, 0x256: 0x24, 0x257: 0x24, - 0x258: 0x24, 0x259: 0x24, 0x25a: 0x24, 0x25b: 0x24, 0x25c: 0x24, 0x25d: 0x24, 0x25e: 0x24, 0x25f: 0x24, - 0x260: 0x24, 0x261: 0x24, 0x262: 0x24, 0x263: 0x24, 0x264: 0x24, 0x265: 0x24, 0x266: 0x24, 0x267: 0x24, - 0x268: 0x24, 0x269: 0x24, 0x26a: 0x24, 0x26b: 0x24, 0x26c: 0x24, 0x26d: 0x24, 0x26e: 0x24, 0x26f: 0x24, - 0x270: 0x24, 0x271: 0x24, 0x272: 0x24, 0x273: 0x24, 0x274: 0x24, 0x275: 0x24, 0x276: 0x24, 0x277: 0x24, - 0x278: 0x24, 0x279: 0x24, 0x27a: 0x24, 0x27b: 0x24, 0x27c: 0x24, 0x27d: 0x24, 0x27e: 0x24, 0x27f: 0x24, - // Block 0xa, offset 0x280 - 0x280: 0x24, 0x281: 0x24, 0x282: 0x24, 0x283: 0x24, 0x284: 0x24, 0x285: 0x24, 0x286: 0x24, 0x287: 0x24, - 0x288: 0x24, 0x289: 0x24, 0x28a: 0x24, 0x28b: 0x24, 0x28c: 0x24, 0x28d: 0x24, 0x28e: 0x24, 0x28f: 0x24, - 0x290: 0x24, 0x291: 0x24, 0x292: 0x24, 0x293: 0x24, 0x294: 0x24, 0x295: 0x24, 0x296: 0x24, 0x297: 0x24, - 0x298: 0x24, 0x299: 0x24, 0x29a: 0x24, 0x29b: 0x24, 0x29c: 0x24, 0x29d: 0x24, 0x29e: 0xa1, 0x29f: 0xa2, - // Block 0xb, offset 0x2c0 - 0x2ec: 0x11, 0x2ed: 0xa3, 0x2ee: 0xa4, 0x2ef: 0xa5, - 0x2f0: 0x24, 0x2f1: 0x24, 0x2f2: 0x24, 0x2f3: 0x24, 0x2f4: 0xa6, 0x2f5: 0xa7, 0x2f6: 0xa8, 0x2f7: 0xa9, - 0x2f8: 0xaa, 0x2f9: 0xab, 0x2fa: 0x24, 0x2fb: 0xac, 0x2fc: 0xad, 0x2fd: 0xae, 0x2fe: 0xaf, 0x2ff: 0xb0, - // Block 0xc, offset 0x300 - 0x300: 0xb1, 0x301: 0xb2, 0x302: 0x24, 0x303: 0xb3, 0x305: 0xb4, 0x307: 0xb5, - 0x30a: 0xb6, 0x30b: 0xb7, 0x30c: 0xb8, 0x30d: 0xb9, 0x30e: 0xba, 0x30f: 0xbb, - 0x310: 0xbc, 0x311: 0xbd, 0x312: 0xbe, 0x313: 0xbf, 0x314: 0xc0, 0x315: 0xc1, - 0x318: 0x24, 0x319: 0x24, 0x31a: 0x24, 0x31b: 0x24, 0x31c: 0xc2, 0x31d: 0xc3, - 0x320: 0xc4, 0x321: 0xc5, 0x322: 0xc6, 0x323: 0xc7, 0x324: 0xc8, 0x326: 0xc9, - 0x328: 0xca, 0x329: 0xcb, 0x32a: 0xcc, 0x32b: 0xcd, 0x32c: 0x5f, 0x32d: 0xce, 0x32e: 0xcf, - 0x330: 0x24, 0x331: 0xd0, 0x332: 0xd1, 0x333: 0xd2, 0x334: 0xd3, - 0x33c: 0xd4, 0x33d: 0xd5, 0x33f: 0xd6, - // Block 0xd, offset 0x340 - 0x340: 0xd7, 0x341: 0xd8, 0x342: 0xd9, 0x343: 0xda, 0x344: 0xdb, 0x345: 0xdc, 0x346: 0xdd, 0x347: 0xde, - 0x348: 0xdf, 0x34a: 0xe0, 0x34b: 0xe1, 0x34c: 0xe2, 0x34d: 0xe3, - 0x350: 0xe4, 0x351: 0xe5, 0x352: 0xe6, 0x353: 0xe7, 0x356: 0xe8, 0x357: 0xe9, - 0x358: 0xea, 0x359: 0xeb, 0x35a: 0xec, 0x35b: 0xed, 0x35c: 0xee, - 0x360: 0xef, 0x362: 0xf0, 0x363: 0xf1, 0x366: 0xf2, 0x367: 0xf3, - 0x368: 0xf4, 0x369: 0xf5, 0x36a: 0xf6, 0x36b: 0xf7, - 0x370: 0xf8, 0x371: 0xf9, 0x372: 0xfa, 0x374: 0xfb, 0x375: 0xfc, 0x376: 0xfd, - 0x37b: 0xfe, - // Block 0xe, offset 0x380 - 0x380: 0x24, 0x381: 0x24, 0x382: 0x24, 0x383: 0x24, 0x384: 0x24, 0x385: 0x24, 0x386: 0x24, 0x387: 0x24, - 0x388: 0x24, 0x389: 0x24, 0x38a: 0x24, 0x38b: 0x24, 0x38c: 0x24, 0x38d: 0x24, 0x38e: 0xff, - 0x390: 0x24, 0x391: 0x100, 0x392: 0x24, 0x393: 0x24, 0x394: 0x24, 0x395: 0x101, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x24, 0x3c1: 0x24, 0x3c2: 0x24, 0x3c3: 0x24, 0x3c4: 0x24, 0x3c5: 0x24, 0x3c6: 0x24, 0x3c7: 0x24, - 0x3c8: 0x24, 0x3c9: 0x24, 0x3ca: 0x24, 0x3cb: 0x24, 0x3cc: 0x24, 0x3cd: 0x24, 0x3ce: 0x24, 0x3cf: 0x24, - 0x3d0: 0x102, - // Block 0x10, offset 0x400 - 0x410: 0x24, 0x411: 0x24, 0x412: 0x24, 0x413: 0x24, 0x414: 0x24, 0x415: 0x24, 0x416: 0x24, 0x417: 0x24, - 0x418: 0x24, 0x419: 0x103, - // Block 0x11, offset 0x440 - 0x460: 0x24, 0x461: 0x24, 0x462: 0x24, 0x463: 0x24, 0x464: 0x24, 0x465: 0x24, 0x466: 0x24, 0x467: 0x24, - 0x468: 0xf7, 0x469: 0x104, 0x46b: 0x105, 0x46c: 0x106, 0x46d: 0x107, 0x46e: 0x108, - 0x479: 0x109, 0x47c: 0x24, 0x47d: 0x10a, 0x47e: 0x10b, 0x47f: 0x10c, - // Block 0x12, offset 0x480 - 0x4b0: 0x24, 0x4b1: 0x10d, 0x4b2: 0x10e, - // Block 0x13, offset 0x4c0 - 0x4c5: 0x10f, 0x4c6: 0x110, - 0x4c9: 0x111, - 0x4d0: 0x112, 0x4d1: 0x113, 0x4d2: 0x114, 0x4d3: 0x115, 0x4d4: 0x116, 0x4d5: 0x117, 0x4d6: 0x118, 0x4d7: 0x119, - 0x4d8: 0x11a, 0x4d9: 0x11b, 0x4da: 0x11c, 0x4db: 0x11d, 0x4dc: 0x11e, 0x4dd: 0x11f, 0x4de: 0x120, 0x4df: 0x121, - 0x4e8: 0x122, 0x4e9: 0x123, 0x4ea: 0x124, - // Block 0x14, offset 0x500 - 0x500: 0x125, 0x504: 0x126, 0x505: 0x127, - 0x50b: 0x128, - 0x520: 0x24, 0x521: 0x24, 0x522: 0x24, 0x523: 0x129, 0x524: 0x12, 0x525: 0x12a, - 0x538: 0x12b, 0x539: 0x13, 0x53a: 0x12c, - // Block 0x15, offset 0x540 - 0x544: 0x12d, 0x545: 0x12e, 0x546: 0x12f, - 0x54f: 0x130, - // Block 0x16, offset 0x580 - 0x590: 0x0a, 0x591: 0x0b, 0x592: 0x0c, 0x593: 0x0d, 0x594: 0x0e, 0x596: 0x0f, - 0x59b: 0x10, 0x59d: 0x11, 0x59e: 0x12, 0x59f: 0x13, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x131, 0x5c1: 0x132, 0x5c4: 0x132, 0x5c5: 0x132, 0x5c6: 0x132, 0x5c7: 0x133, - // Block 0x18, offset 0x600 - 0x620: 0x15, -} - -// sparseOffsets: 289 entries, 578 bytes -var sparseOffsets = []uint16{0x0, 0x9, 0xf, 0x18, 0x24, 0x2e, 0x35, 0x38, 0x3c, 0x3f, 0x43, 0x4d, 0x4f, 0x57, 0x5e, 0x63, 0x71, 0x72, 0x80, 0x8f, 0x99, 0x9c, 0xa3, 0xab, 0xae, 0xb0, 0xbf, 0xc5, 0xd3, 0xde, 0xeb, 0xf6, 0x102, 0x10c, 0x118, 0x123, 0x12f, 0x13b, 0x143, 0x14c, 0x156, 0x161, 0x16d, 0x174, 0x17f, 0x184, 0x18c, 0x18f, 0x194, 0x198, 0x19c, 0x1a3, 0x1ac, 0x1b4, 0x1b5, 0x1be, 0x1c5, 0x1cd, 0x1d3, 0x1d8, 0x1dc, 0x1df, 0x1e1, 0x1e4, 0x1e9, 0x1ea, 0x1ec, 0x1ee, 0x1f0, 0x1f7, 0x1fc, 0x200, 0x209, 0x20c, 0x20f, 0x215, 0x216, 0x221, 0x222, 0x223, 0x228, 0x235, 0x23d, 0x245, 0x24e, 0x257, 0x260, 0x265, 0x268, 0x273, 0x281, 0x283, 0x28a, 0x28e, 0x29a, 0x29b, 0x2a6, 0x2ae, 0x2b6, 0x2bc, 0x2bd, 0x2cb, 0x2d0, 0x2d3, 0x2d8, 0x2dc, 0x2e2, 0x2e7, 0x2ea, 0x2ef, 0x2f4, 0x2f5, 0x2fb, 0x2fd, 0x2fe, 0x300, 0x302, 0x305, 0x306, 0x308, 0x30b, 0x311, 0x315, 0x317, 0x31c, 0x323, 0x32b, 0x334, 0x335, 0x33e, 0x342, 0x347, 0x34f, 0x355, 0x35b, 0x365, 0x36a, 0x373, 0x379, 0x380, 0x384, 0x38c, 0x38e, 0x390, 0x393, 0x395, 0x397, 0x398, 0x399, 0x39b, 0x39d, 0x3a3, 0x3a8, 0x3aa, 0x3b1, 0x3b4, 0x3b6, 0x3bc, 0x3c1, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c8, 0x3ca, 0x3cc, 0x3cf, 0x3d1, 0x3d4, 0x3dc, 0x3df, 0x3e3, 0x3eb, 0x3ed, 0x3ee, 0x3ef, 0x3f1, 0x3f7, 0x3f9, 0x3fa, 0x3fc, 0x3fe, 0x400, 0x40d, 0x40e, 0x40f, 0x413, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41c, 0x41f, 0x425, 0x426, 0x42a, 0x42e, 0x434, 0x437, 0x43e, 0x442, 0x446, 0x44d, 0x456, 0x45c, 0x462, 0x46c, 0x476, 0x478, 0x481, 0x487, 0x48d, 0x493, 0x496, 0x49c, 0x49f, 0x4a8, 0x4a9, 0x4b0, 0x4b4, 0x4b5, 0x4b8, 0x4ba, 0x4c1, 0x4c9, 0x4cf, 0x4d5, 0x4d6, 0x4dc, 0x4df, 0x4e7, 0x4ee, 0x4f8, 0x500, 0x503, 0x504, 0x505, 0x506, 0x508, 0x509, 0x50b, 0x50d, 0x50f, 0x513, 0x514, 0x516, 0x519, 0x51b, 0x51d, 0x51f, 0x524, 0x529, 0x52d, 0x52e, 0x531, 0x535, 0x540, 0x544, 0x54c, 0x551, 0x555, 0x558, 0x55c, 0x55f, 0x562, 0x567, 0x56b, 0x56f, 0x573, 0x577, 0x579, 0x57b, 0x57e, 0x583, 0x586, 0x588, 0x58b, 0x58d, 0x593, 0x59c, 0x5a1, 0x5a2, 0x5a5, 0x5a6, 0x5a7, 0x5a9, 0x5aa, 0x5ab} - -// sparseValues: 1451 entries, 5804 bytes -var sparseValues = [1451]valueRange{ - // Block 0x0, offset 0x0 - {value: 0x0004, lo: 0xa8, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xaa}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0004, lo: 0xaf, hi: 0xaf}, - {value: 0x0004, lo: 0xb4, hi: 0xb4}, - {value: 0x001a, lo: 0xb5, hi: 0xb5}, - {value: 0x0054, lo: 0xb7, hi: 0xb7}, - {value: 0x0004, lo: 0xb8, hi: 0xb8}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - // Block 0x1, offset 0x9 - {value: 0x2013, lo: 0x80, hi: 0x96}, - {value: 0x2013, lo: 0x98, hi: 0x9e}, - {value: 0x009a, lo: 0x9f, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xb6}, - {value: 0x2012, lo: 0xb8, hi: 0xbe}, - {value: 0x0252, lo: 0xbf, hi: 0xbf}, - // Block 0x2, offset 0xf - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x011b, lo: 0xb0, hi: 0xb0}, - {value: 0x019a, lo: 0xb1, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb7}, - {value: 0x0012, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x0553, lo: 0xbf, hi: 0xbf}, - // Block 0x3, offset 0x18 - {value: 0x0552, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x01da, lo: 0x89, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xb7}, - {value: 0x0253, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x028a, lo: 0xbf, hi: 0xbf}, - // Block 0x4, offset 0x24 - {value: 0x0117, lo: 0x80, hi: 0x9f}, - {value: 0x2f53, lo: 0xa0, hi: 0xa0}, - {value: 0x0012, lo: 0xa1, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xb3}, - {value: 0x0012, lo: 0xb4, hi: 0xb9}, - {value: 0x090b, lo: 0xba, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x2953, lo: 0xbd, hi: 0xbd}, - {value: 0x098b, lo: 0xbe, hi: 0xbe}, - {value: 0x0a0a, lo: 0xbf, hi: 0xbf}, - // Block 0x5, offset 0x2e - {value: 0x0015, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x97}, - {value: 0x0004, lo: 0x98, hi: 0x9d}, - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0015, lo: 0xa0, hi: 0xa4}, - {value: 0x0004, lo: 0xa5, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xbf}, - // Block 0x6, offset 0x35 - {value: 0x0024, lo: 0x80, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbf}, - // Block 0x7, offset 0x38 - {value: 0x6553, lo: 0x80, hi: 0x8f}, - {value: 0x2013, lo: 0x90, hi: 0x9f}, - {value: 0x5f53, lo: 0xa0, hi: 0xaf}, - {value: 0x2012, lo: 0xb0, hi: 0xbf}, - // Block 0x8, offset 0x3c - {value: 0x5f52, lo: 0x80, hi: 0x8f}, - {value: 0x6552, lo: 0x90, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x9, offset 0x3f - {value: 0x0117, lo: 0x80, hi: 0x81}, - {value: 0x0024, lo: 0x83, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xbf}, - // Block 0xa, offset 0x43 - {value: 0x0f13, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0716, lo: 0x8b, hi: 0x8c}, - {value: 0x0316, lo: 0x8d, hi: 0x8e}, - {value: 0x0f12, lo: 0x8f, hi: 0x8f}, - {value: 0x0117, lo: 0x90, hi: 0xbf}, - // Block 0xb, offset 0x4d - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x6553, lo: 0xb1, hi: 0xbf}, - // Block 0xc, offset 0x4f - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6853, lo: 0x90, hi: 0x96}, - {value: 0x0014, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9b, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0xa0, hi: 0xa0}, - {value: 0x6552, lo: 0xa1, hi: 0xaf}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0xd, offset 0x57 - {value: 0x0034, lo: 0x81, hi: 0x82}, - {value: 0x0024, lo: 0x84, hi: 0x84}, - {value: 0x0034, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xaa}, - {value: 0x0010, lo: 0xaf, hi: 0xb3}, - {value: 0x0054, lo: 0xb4, hi: 0xb4}, - // Block 0xe, offset 0x5e - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0024, lo: 0x90, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0014, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xf, offset 0x63 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9c}, - {value: 0x0024, lo: 0x9d, hi: 0x9e}, - {value: 0x0034, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x10, offset 0x71 - {value: 0x0010, lo: 0x80, hi: 0xbf}, - // Block 0x11, offset 0x72 - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0024, lo: 0x9f, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x12, offset 0x80 - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0034, lo: 0xb1, hi: 0xb1}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0024, lo: 0xbf, hi: 0xbf}, - // Block 0x13, offset 0x8f - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0024, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x88}, - {value: 0x0024, lo: 0x89, hi: 0x8a}, - {value: 0x0010, lo: 0x8d, hi: 0xbf}, - // Block 0x14, offset 0x99 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x15, offset 0x9c - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xb1}, - {value: 0x0034, lo: 0xb2, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0x16, offset 0xa3 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x99}, - {value: 0x0014, lo: 0x9a, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0xa3}, - {value: 0x0014, lo: 0xa4, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xad}, - // Block 0x17, offset 0xab - {value: 0x0010, lo: 0x80, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0xa0, hi: 0xaa}, - // Block 0x18, offset 0xae - {value: 0x0010, lo: 0xa0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbd}, - // Block 0x19, offset 0xb0 - {value: 0x0034, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0024, lo: 0xaa, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbf}, - // Block 0x1a, offset 0xbf - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1b, offset 0xc5 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0x1c, offset 0xd3 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb6, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1d, offset 0xde - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xb1}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - // Block 0x1e, offset 0xeb - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x1f, offset 0xf6 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x99, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x20, offset 0x102 - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x21, offset 0x10c - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x85}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xbf}, - // Block 0x22, offset 0x118 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x23, offset 0x123 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x24, offset 0x12f - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0010, lo: 0xa8, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x25, offset 0x13b - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x26, offset 0x143 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb9}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbf}, - // Block 0x27, offset 0x14c - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x88}, - {value: 0x0014, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x28, offset 0x156 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x29, offset 0x161 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb2}, - // Block 0x2a, offset 0x16d - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x2b, offset 0x174 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x94, hi: 0x97}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xba, hi: 0xbf}, - // Block 0x2c, offset 0x17f - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x96}, - {value: 0x0010, lo: 0x9a, hi: 0xb1}, - {value: 0x0010, lo: 0xb3, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x2d, offset 0x184 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x94}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9f}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - // Block 0x2e, offset 0x18c - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - // Block 0x2f, offset 0x18f - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x30, offset 0x194 - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - // Block 0x31, offset 0x198 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x32, offset 0x19c - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0034, lo: 0x98, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0034, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x33, offset 0x1a3 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xac}, - {value: 0x0034, lo: 0xb1, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xba, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x34, offset 0x1ac - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0024, lo: 0x82, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x86, hi: 0x87}, - {value: 0x0010, lo: 0x88, hi: 0x8c}, - {value: 0x0014, lo: 0x8d, hi: 0x97}, - {value: 0x0014, lo: 0x99, hi: 0xbc}, - // Block 0x35, offset 0x1b4 - {value: 0x0034, lo: 0x86, hi: 0x86}, - // Block 0x36, offset 0x1b5 - {value: 0x0010, lo: 0xab, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbe}, - // Block 0x37, offset 0x1be - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x96, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x99}, - {value: 0x0014, lo: 0x9e, hi: 0xa0}, - {value: 0x0010, lo: 0xa2, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xad}, - {value: 0x0014, lo: 0xb1, hi: 0xb4}, - // Block 0x38, offset 0x1c5 - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x6c53, lo: 0xa0, hi: 0xbf}, - // Block 0x39, offset 0x1cd - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x9a, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x3a, offset 0x1d3 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x3b, offset 0x1d8 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x82, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3c, offset 0x1dc - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3d, offset 0x1df - {value: 0x0010, lo: 0x80, hi: 0x9a}, - {value: 0x0024, lo: 0x9d, hi: 0x9f}, - // Block 0x3e, offset 0x1e1 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x7453, lo: 0xa0, hi: 0xaf}, - {value: 0x7853, lo: 0xb0, hi: 0xbf}, - // Block 0x3f, offset 0x1e4 - {value: 0x7c53, lo: 0x80, hi: 0x8f}, - {value: 0x8053, lo: 0x90, hi: 0x9f}, - {value: 0x7c53, lo: 0xa0, hi: 0xaf}, - {value: 0x0813, lo: 0xb0, hi: 0xb5}, - {value: 0x0892, lo: 0xb8, hi: 0xbd}, - // Block 0x40, offset 0x1e9 - {value: 0x0010, lo: 0x81, hi: 0xbf}, - // Block 0x41, offset 0x1ea - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0010, lo: 0xaf, hi: 0xbf}, - // Block 0x42, offset 0x1ec - {value: 0x0010, lo: 0x81, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x43, offset 0x1ee - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb8}, - // Block 0x44, offset 0x1f0 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0034, lo: 0x94, hi: 0x94}, - {value: 0x0010, lo: 0xa0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - // Block 0x45, offset 0x1f7 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xac}, - {value: 0x0010, lo: 0xae, hi: 0xb0}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - // Block 0x46, offset 0x1fc - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x47, offset 0x200 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x89, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0014, lo: 0x93, hi: 0x93}, - {value: 0x0004, lo: 0x97, hi: 0x97}, - {value: 0x0024, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0x48, offset 0x209 - {value: 0x0014, lo: 0x8b, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x49, offset 0x20c - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb8}, - // Block 0x4a, offset 0x20f - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x4b, offset 0x215 - {value: 0x0010, lo: 0x80, hi: 0xb5}, - // Block 0x4c, offset 0x216 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbb}, - // Block 0x4d, offset 0x221 - {value: 0x0010, lo: 0x86, hi: 0x8f}, - // Block 0x4e, offset 0x222 - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x4f, offset 0x223 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - // Block 0x50, offset 0x228 - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x9e}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xac}, - {value: 0x0010, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xbc}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x51, offset 0x235 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xa7, hi: 0xa7}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - {value: 0x0034, lo: 0xb5, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbc}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0x52, offset 0x23d - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x53, offset 0x245 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0030, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xab, hi: 0xab}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - {value: 0x0024, lo: 0xad, hi: 0xb3}, - // Block 0x54, offset 0x24e - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0030, lo: 0xaa, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbf}, - // Block 0x55, offset 0x257 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0030, lo: 0xb2, hi: 0xb3}, - // Block 0x56, offset 0x260 - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0x57, offset 0x265 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8d, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x58, offset 0x268 - {value: 0x31ea, lo: 0x80, hi: 0x80}, - {value: 0x326a, lo: 0x81, hi: 0x81}, - {value: 0x32ea, lo: 0x82, hi: 0x82}, - {value: 0x336a, lo: 0x83, hi: 0x83}, - {value: 0x33ea, lo: 0x84, hi: 0x84}, - {value: 0x346a, lo: 0x85, hi: 0x85}, - {value: 0x34ea, lo: 0x86, hi: 0x86}, - {value: 0x356a, lo: 0x87, hi: 0x87}, - {value: 0x35ea, lo: 0x88, hi: 0x88}, - {value: 0x8353, lo: 0x90, hi: 0xba}, - {value: 0x8353, lo: 0xbd, hi: 0xbf}, - // Block 0x59, offset 0x273 - {value: 0x0024, lo: 0x90, hi: 0x92}, - {value: 0x0034, lo: 0x94, hi: 0x99}, - {value: 0x0024, lo: 0x9a, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9f}, - {value: 0x0024, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xb3}, - {value: 0x0024, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb7}, - {value: 0x0024, lo: 0xb8, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xba}, - // Block 0x5a, offset 0x281 - {value: 0x0012, lo: 0x80, hi: 0xab}, - {value: 0x0015, lo: 0xac, hi: 0xbf}, - // Block 0x5b, offset 0x283 - {value: 0x0015, lo: 0x80, hi: 0xaa}, - {value: 0x0012, lo: 0xab, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb8}, - {value: 0x8752, lo: 0xb9, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbc}, - {value: 0x8b52, lo: 0xbd, hi: 0xbd}, - {value: 0x0012, lo: 0xbe, hi: 0xbf}, - // Block 0x5c, offset 0x28a - {value: 0x0012, lo: 0x80, hi: 0x8d}, - {value: 0x8f52, lo: 0x8e, hi: 0x8e}, - {value: 0x0012, lo: 0x8f, hi: 0x9a}, - {value: 0x0015, lo: 0x9b, hi: 0xbf}, - // Block 0x5d, offset 0x28e - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0024, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb9}, - {value: 0x0024, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbd}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x5e, offset 0x29a - {value: 0x0117, lo: 0x80, hi: 0xbf}, - // Block 0x5f, offset 0x29b - {value: 0x0117, lo: 0x80, hi: 0x95}, - {value: 0x369a, lo: 0x96, hi: 0x96}, - {value: 0x374a, lo: 0x97, hi: 0x97}, - {value: 0x37fa, lo: 0x98, hi: 0x98}, - {value: 0x38aa, lo: 0x99, hi: 0x99}, - {value: 0x395a, lo: 0x9a, hi: 0x9a}, - {value: 0x3a0a, lo: 0x9b, hi: 0x9b}, - {value: 0x0012, lo: 0x9c, hi: 0x9d}, - {value: 0x3abb, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0x9f, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x60, offset 0x2a6 - {value: 0x0812, lo: 0x80, hi: 0x87}, - {value: 0x0813, lo: 0x88, hi: 0x8f}, - {value: 0x0812, lo: 0x90, hi: 0x95}, - {value: 0x0813, lo: 0x98, hi: 0x9d}, - {value: 0x0812, lo: 0xa0, hi: 0xa7}, - {value: 0x0813, lo: 0xa8, hi: 0xaf}, - {value: 0x0812, lo: 0xb0, hi: 0xb7}, - {value: 0x0813, lo: 0xb8, hi: 0xbf}, - // Block 0x61, offset 0x2ae - {value: 0x0004, lo: 0x8b, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8f}, - {value: 0x0054, lo: 0x98, hi: 0x99}, - {value: 0x0054, lo: 0xa4, hi: 0xa4}, - {value: 0x0054, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xaa, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xaf}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x62, offset 0x2b6 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x94, hi: 0x94}, - {value: 0x0014, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa6, hi: 0xaf}, - {value: 0x0015, lo: 0xb1, hi: 0xb1}, - {value: 0x0015, lo: 0xbf, hi: 0xbf}, - // Block 0x63, offset 0x2bc - {value: 0x0015, lo: 0x90, hi: 0x9c}, - // Block 0x64, offset 0x2bd - {value: 0x0024, lo: 0x90, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0xa0}, - {value: 0x0024, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa4}, - {value: 0x0034, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - // Block 0x65, offset 0x2cb - {value: 0x0016, lo: 0x85, hi: 0x86}, - {value: 0x0012, lo: 0x87, hi: 0x89}, - {value: 0xa452, lo: 0x8e, hi: 0x8e}, - {value: 0x1013, lo: 0xa0, hi: 0xaf}, - {value: 0x1012, lo: 0xb0, hi: 0xbf}, - // Block 0x66, offset 0x2d0 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x88}, - // Block 0x67, offset 0x2d3 - {value: 0xa753, lo: 0xb6, hi: 0xb7}, - {value: 0xaa53, lo: 0xb8, hi: 0xb9}, - {value: 0xad53, lo: 0xba, hi: 0xbb}, - {value: 0xaa53, lo: 0xbc, hi: 0xbd}, - {value: 0xa753, lo: 0xbe, hi: 0xbf}, - // Block 0x68, offset 0x2d8 - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6553, lo: 0x90, hi: 0x9f}, - {value: 0xb053, lo: 0xa0, hi: 0xae}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0x69, offset 0x2dc - {value: 0x0117, lo: 0x80, hi: 0xa3}, - {value: 0x0012, lo: 0xa4, hi: 0xa4}, - {value: 0x0716, lo: 0xab, hi: 0xac}, - {value: 0x0316, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb3}, - // Block 0x6a, offset 0x2e2 - {value: 0x6c52, lo: 0x80, hi: 0x9f}, - {value: 0x7052, lo: 0xa0, hi: 0xa5}, - {value: 0x7052, lo: 0xa7, hi: 0xa7}, - {value: 0x7052, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x6b, offset 0x2e7 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x6c, offset 0x2ea - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0010, lo: 0xb0, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x6d, offset 0x2ef - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9e}, - {value: 0x0024, lo: 0xa0, hi: 0xbf}, - // Block 0x6e, offset 0x2f4 - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - // Block 0x6f, offset 0x2f5 - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0xaa, hi: 0xad}, - {value: 0x0030, lo: 0xae, hi: 0xaf}, - {value: 0x0004, lo: 0xb1, hi: 0xb5}, - {value: 0x0014, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - // Block 0x70, offset 0x2fb - {value: 0x0034, lo: 0x99, hi: 0x9a}, - {value: 0x0004, lo: 0x9b, hi: 0x9e}, - // Block 0x71, offset 0x2fd - {value: 0x0004, lo: 0xbc, hi: 0xbe}, - // Block 0x72, offset 0x2fe - {value: 0x0010, lo: 0x85, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x73, offset 0x300 - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0010, lo: 0xa0, hi: 0xba}, - // Block 0x74, offset 0x302 - {value: 0x0010, lo: 0x80, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0xbf}, - // Block 0x75, offset 0x305 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - // Block 0x76, offset 0x306 - {value: 0x0010, lo: 0x90, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x77, offset 0x308 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0xab}, - // Block 0x78, offset 0x30b - {value: 0x0117, lo: 0x80, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb2}, - {value: 0x0024, lo: 0xb4, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x79, offset 0x311 - {value: 0x0117, lo: 0x80, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9d}, - {value: 0x0024, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x7a, offset 0x315 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb1}, - // Block 0x7b, offset 0x317 - {value: 0x0004, lo: 0x80, hi: 0x96}, - {value: 0x0014, lo: 0x97, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xaf}, - {value: 0x0012, lo: 0xb0, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xbf}, - // Block 0x7c, offset 0x31c - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x0015, lo: 0xb0, hi: 0xb0}, - {value: 0x0012, lo: 0xb1, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x8753, lo: 0xbd, hi: 0xbd}, - {value: 0x0117, lo: 0xbe, hi: 0xbf}, - // Block 0x7d, offset 0x323 - {value: 0x0117, lo: 0x82, hi: 0x83}, - {value: 0x6553, lo: 0x84, hi: 0x84}, - {value: 0x908b, lo: 0x85, hi: 0x85}, - {value: 0x8f53, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0xb7, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbf}, - // Block 0x7e, offset 0x32b - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x8c, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - // Block 0x7f, offset 0x334 - {value: 0x0010, lo: 0x80, hi: 0xb3}, - // Block 0x80, offset 0x335 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xa0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb7}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x81, offset 0x33e - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x82, offset 0x342 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0x92}, - {value: 0x0030, lo: 0x93, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0x83, offset 0x347 - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x84, offset 0x34f - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0004, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x85, offset 0x355 - {value: 0x0010, lo: 0x80, hi: 0xa8}, - {value: 0x0014, lo: 0xa9, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0x86, offset 0x35b - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x87, offset 0x365 - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0024, lo: 0xbe, hi: 0xbf}, - // Block 0x88, offset 0x36a - {value: 0x0024, lo: 0x81, hi: 0x81}, - {value: 0x0004, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - // Block 0x89, offset 0x373 - {value: 0x0010, lo: 0x81, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x8e}, - {value: 0x0010, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x8a, offset 0x379 - {value: 0x0012, lo: 0x80, hi: 0x92}, - {value: 0xb352, lo: 0x93, hi: 0x93}, - {value: 0x0012, lo: 0x94, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa7}, - {value: 0x74d2, lo: 0xb0, hi: 0xbf}, - // Block 0x8b, offset 0x380 - {value: 0x78d2, lo: 0x80, hi: 0x8f}, - {value: 0x7cd2, lo: 0x90, hi: 0x9f}, - {value: 0x80d2, lo: 0xa0, hi: 0xaf}, - {value: 0x7cd2, lo: 0xb0, hi: 0xbf}, - // Block 0x8c, offset 0x384 - {value: 0x0010, lo: 0x80, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x8d, offset 0x38c - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x8e, offset 0x38e - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x8b, hi: 0xbb}, - // Block 0x8f, offset 0x390 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0xbf}, - // Block 0x90, offset 0x393 - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0004, lo: 0xb2, hi: 0xbf}, - // Block 0x91, offset 0x395 - {value: 0x0004, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x93, hi: 0xbf}, - // Block 0x92, offset 0x397 - {value: 0x0010, lo: 0x80, hi: 0xbd}, - // Block 0x93, offset 0x398 - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0x94, offset 0x399 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0xbf}, - // Block 0x95, offset 0x39b - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0xb0, hi: 0xbb}, - // Block 0x96, offset 0x39d - {value: 0x0014, lo: 0x80, hi: 0x8f}, - {value: 0x0054, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0xa0, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xad}, - {value: 0x0024, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - // Block 0x97, offset 0x3a3 - {value: 0x0010, lo: 0x8d, hi: 0x8f}, - {value: 0x0054, lo: 0x92, hi: 0x92}, - {value: 0x0054, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0xb0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0x98, offset 0x3a8 - {value: 0x0010, lo: 0x80, hi: 0xbc}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x99, offset 0x3aa - {value: 0x0054, lo: 0x87, hi: 0x87}, - {value: 0x0054, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0054, lo: 0x9a, hi: 0x9a}, - {value: 0x5f53, lo: 0xa1, hi: 0xba}, - {value: 0x0004, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9a, offset 0x3b1 - {value: 0x0004, lo: 0x80, hi: 0x80}, - {value: 0x5f52, lo: 0x81, hi: 0x9a}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - // Block 0x9b, offset 0x3b4 - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbe}, - // Block 0x9c, offset 0x3b6 - {value: 0x0010, lo: 0x82, hi: 0x87}, - {value: 0x0010, lo: 0x8a, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0x97}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0004, lo: 0xa3, hi: 0xa3}, - {value: 0x0014, lo: 0xb9, hi: 0xbb}, - // Block 0x9d, offset 0x3bc - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0010, lo: 0x8d, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xba}, - {value: 0x0010, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9e, offset 0x3c1 - {value: 0x0010, lo: 0x80, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x9d}, - // Block 0x9f, offset 0x3c3 - {value: 0x0010, lo: 0x80, hi: 0xba}, - // Block 0xa0, offset 0x3c4 - {value: 0x0010, lo: 0x80, hi: 0xb4}, - // Block 0xa1, offset 0x3c5 - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0xa2, offset 0x3c6 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa3, offset 0x3c8 - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - // Block 0xa4, offset 0x3ca - {value: 0x0010, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xad, hi: 0xbf}, - // Block 0xa5, offset 0x3cc - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0xb5}, - {value: 0x0024, lo: 0xb6, hi: 0xba}, - // Block 0xa6, offset 0x3cf - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa7, offset 0x3d1 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x91, hi: 0x95}, - // Block 0xa8, offset 0x3d4 - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x97}, - {value: 0xb653, lo: 0x98, hi: 0x9f}, - {value: 0xb953, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbf}, - // Block 0xa9, offset 0x3dc - {value: 0xb652, lo: 0x80, hi: 0x87}, - {value: 0xb952, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xaa, offset 0x3df - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0xb953, lo: 0xb0, hi: 0xb7}, - {value: 0xb653, lo: 0xb8, hi: 0xbf}, - // Block 0xab, offset 0x3e3 - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x93}, - {value: 0xb952, lo: 0x98, hi: 0x9f}, - {value: 0xb652, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbb}, - // Block 0xac, offset 0x3eb - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xad, offset 0x3ed - {value: 0x0010, lo: 0x80, hi: 0xa3}, - // Block 0xae, offset 0x3ee - {value: 0x0010, lo: 0x80, hi: 0xb6}, - // Block 0xaf, offset 0x3ef - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - // Block 0xb0, offset 0x3f1 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xb1, offset 0x3f7 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xb2, offset 0x3f9 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - // Block 0xb3, offset 0x3fa - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - // Block 0xb4, offset 0x3fc - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb9}, - // Block 0xb5, offset 0x3fe - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0xb6, offset 0x400 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x8e, hi: 0x8e}, - {value: 0x0024, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x99, hi: 0xb5}, - {value: 0x0024, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xb7, offset 0x40d - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0xb8, offset 0x40e - {value: 0x0010, lo: 0x80, hi: 0x9c}, - // Block 0xb9, offset 0x40f - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - // Block 0xba, offset 0x413 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - // Block 0xbb, offset 0x415 - {value: 0x0010, lo: 0x80, hi: 0x91}, - // Block 0xbc, offset 0x416 - {value: 0x0010, lo: 0x80, hi: 0x88}, - // Block 0xbd, offset 0x417 - {value: 0x5653, lo: 0x80, hi: 0xb2}, - // Block 0xbe, offset 0x418 - {value: 0x5652, lo: 0x80, hi: 0xb2}, - // Block 0xbf, offset 0x419 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc0, offset 0x41c - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xc1, offset 0x41f - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x87}, - {value: 0x0024, lo: 0x88, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x8b}, - {value: 0x0024, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - // Block 0xc2, offset 0x425 - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xc3, offset 0x426 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xc4, offset 0x42a - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xc5, offset 0x42e - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - // Block 0xc6, offset 0x434 - {value: 0x0014, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc7, offset 0x437 - {value: 0x0024, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0xc8, offset 0x43e - {value: 0x0010, lo: 0x84, hi: 0x86}, - {value: 0x0010, lo: 0x90, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - // Block 0xc9, offset 0x442 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xca, offset 0x446 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x89, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - // Block 0xcb, offset 0x44d - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb4}, - {value: 0x0030, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xb7}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0xcc, offset 0x456 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xcd, offset 0x45c - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa2}, - {value: 0x0014, lo: 0xa3, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xce, offset 0x462 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xcf, offset 0x46c - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0030, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9d, hi: 0xa3}, - {value: 0x0024, lo: 0xa6, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - // Block 0xd0, offset 0x476 - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xd1, offset 0x478 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0x9f, hi: 0x9f}, - // Block 0xd2, offset 0x481 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xd3, offset 0x487 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd4, offset 0x48d - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd5, offset 0x493 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x98, hi: 0x9b}, - {value: 0x0014, lo: 0x9c, hi: 0x9d}, - // Block 0xd6, offset 0x496 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd7, offset 0x49c - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd8, offset 0x49f - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0014, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb5}, - {value: 0x0030, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - // Block 0xd9, offset 0x4a8 - {value: 0x0010, lo: 0x80, hi: 0x89}, - // Block 0xda, offset 0x4a9 - {value: 0x0014, lo: 0x9d, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xdb, offset 0x4b0 - {value: 0x0010, lo: 0x80, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - // Block 0xdc, offset 0x4b4 - {value: 0x5f53, lo: 0xa0, hi: 0xbf}, - // Block 0xdd, offset 0x4b5 - {value: 0x5f52, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xde, offset 0x4b8 - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - {value: 0x0010, lo: 0xaa, hi: 0xbf}, - // Block 0xdf, offset 0x4ba - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0014, lo: 0x94, hi: 0x97}, - {value: 0x0014, lo: 0x9a, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0x9f}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - // Block 0xe0, offset 0x4c1 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x8a}, - {value: 0x0010, lo: 0x8b, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbe}, - // Block 0xe1, offset 0x4c9 - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0014, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x98}, - {value: 0x0014, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0xbf}, - // Block 0xe2, offset 0x4cf - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0014, lo: 0x8a, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9d, hi: 0x9d}, - // Block 0xe3, offset 0x4d5 - {value: 0x0010, lo: 0x80, hi: 0xb8}, - // Block 0xe4, offset 0x4d6 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xe5, offset 0x4dc - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0xe6, offset 0x4df - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0014, lo: 0x92, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xa9}, - {value: 0x0014, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0xe7, offset 0x4e7 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb6}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xe8, offset 0x4ee - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa5}, - {value: 0x0010, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xbf}, - // Block 0xe9, offset 0x4f8 - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0014, lo: 0x90, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0x96}, - {value: 0x0034, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xea, offset 0x500 - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - // Block 0xeb, offset 0x503 - {value: 0x0010, lo: 0x80, hi: 0x99}, - // Block 0xec, offset 0x504 - {value: 0x0010, lo: 0x80, hi: 0xae}, - // Block 0xed, offset 0x505 - {value: 0x0010, lo: 0x80, hi: 0x83}, - // Block 0xee, offset 0x506 - {value: 0x0010, lo: 0x80, hi: 0xae}, - {value: 0x0014, lo: 0xb0, hi: 0xb8}, - // Block 0xef, offset 0x508 - {value: 0x0010, lo: 0x80, hi: 0x86}, - // Block 0xf0, offset 0x509 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xf1, offset 0x50b - {value: 0x0010, lo: 0x90, hi: 0xad}, - {value: 0x0034, lo: 0xb0, hi: 0xb4}, - // Block 0xf2, offset 0x50d - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - // Block 0xf3, offset 0x50f - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa3, hi: 0xb7}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xf4, offset 0x513 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - // Block 0xf5, offset 0x514 - {value: 0x2013, lo: 0x80, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xbf}, - // Block 0xf6, offset 0x516 - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xf7, offset 0x519 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0014, lo: 0x8f, hi: 0x9f}, - // Block 0xf8, offset 0x51b - {value: 0x0014, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa3, hi: 0xa3}, - // Block 0xf9, offset 0x51d - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbc}, - // Block 0xfa, offset 0x51f - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0034, lo: 0x9e, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa3}, - // Block 0xfb, offset 0x524 - {value: 0x0030, lo: 0xa5, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xa9}, - {value: 0x0030, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbf}, - // Block 0xfc, offset 0x529 - {value: 0x0034, lo: 0x80, hi: 0x82}, - {value: 0x0024, lo: 0x85, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8b}, - {value: 0x0024, lo: 0xaa, hi: 0xad}, - // Block 0xfd, offset 0x52d - {value: 0x0024, lo: 0x82, hi: 0x84}, - // Block 0xfe, offset 0x52e - {value: 0x0013, lo: 0x80, hi: 0x99}, - {value: 0x0012, lo: 0x9a, hi: 0xb3}, - {value: 0x0013, lo: 0xb4, hi: 0xbf}, - // Block 0xff, offset 0x531 - {value: 0x0013, lo: 0x80, hi: 0x8d}, - {value: 0x0012, lo: 0x8e, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0xa7}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x100, offset 0x535 - {value: 0x0013, lo: 0x80, hi: 0x81}, - {value: 0x0012, lo: 0x82, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0x9c}, - {value: 0x0013, lo: 0x9e, hi: 0x9f}, - {value: 0x0013, lo: 0xa2, hi: 0xa2}, - {value: 0x0013, lo: 0xa5, hi: 0xa6}, - {value: 0x0013, lo: 0xa9, hi: 0xac}, - {value: 0x0013, lo: 0xae, hi: 0xb5}, - {value: 0x0012, lo: 0xb6, hi: 0xb9}, - {value: 0x0012, lo: 0xbb, hi: 0xbb}, - {value: 0x0012, lo: 0xbd, hi: 0xbf}, - // Block 0x101, offset 0x540 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0012, lo: 0x85, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x102, offset 0x544 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0013, lo: 0x84, hi: 0x85}, - {value: 0x0013, lo: 0x87, hi: 0x8a}, - {value: 0x0013, lo: 0x8d, hi: 0x94}, - {value: 0x0013, lo: 0x96, hi: 0x9c}, - {value: 0x0012, lo: 0x9e, hi: 0xb7}, - {value: 0x0013, lo: 0xb8, hi: 0xb9}, - {value: 0x0013, lo: 0xbb, hi: 0xbe}, - // Block 0x103, offset 0x54c - {value: 0x0013, lo: 0x80, hi: 0x84}, - {value: 0x0013, lo: 0x86, hi: 0x86}, - {value: 0x0013, lo: 0x8a, hi: 0x90}, - {value: 0x0012, lo: 0x92, hi: 0xab}, - {value: 0x0013, lo: 0xac, hi: 0xbf}, - // Block 0x104, offset 0x551 - {value: 0x0013, lo: 0x80, hi: 0x85}, - {value: 0x0012, lo: 0x86, hi: 0x9f}, - {value: 0x0013, lo: 0xa0, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbf}, - // Block 0x105, offset 0x555 - {value: 0x0012, lo: 0x80, hi: 0x93}, - {value: 0x0013, lo: 0x94, hi: 0xad}, - {value: 0x0012, lo: 0xae, hi: 0xbf}, - // Block 0x106, offset 0x558 - {value: 0x0012, lo: 0x80, hi: 0x87}, - {value: 0x0013, lo: 0x88, hi: 0xa1}, - {value: 0x0012, lo: 0xa2, hi: 0xbb}, - {value: 0x0013, lo: 0xbc, hi: 0xbf}, - // Block 0x107, offset 0x55c - {value: 0x0013, lo: 0x80, hi: 0x95}, - {value: 0x0012, lo: 0x96, hi: 0xaf}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x108, offset 0x55f - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0012, lo: 0x8a, hi: 0xa5}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x109, offset 0x562 - {value: 0x0013, lo: 0x80, hi: 0x80}, - {value: 0x0012, lo: 0x82, hi: 0x9a}, - {value: 0x0012, lo: 0x9c, hi: 0xa1}, - {value: 0x0013, lo: 0xa2, hi: 0xba}, - {value: 0x0012, lo: 0xbc, hi: 0xbf}, - // Block 0x10a, offset 0x567 - {value: 0x0012, lo: 0x80, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0xb4}, - {value: 0x0012, lo: 0xb6, hi: 0xbf}, - // Block 0x10b, offset 0x56b - {value: 0x0012, lo: 0x80, hi: 0x8e}, - {value: 0x0012, lo: 0x90, hi: 0x95}, - {value: 0x0013, lo: 0x96, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x10c, offset 0x56f - {value: 0x0012, lo: 0x80, hi: 0x88}, - {value: 0x0012, lo: 0x8a, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x10d, offset 0x573 - {value: 0x0012, lo: 0x80, hi: 0x82}, - {value: 0x0012, lo: 0x84, hi: 0x89}, - {value: 0x0017, lo: 0x8a, hi: 0x8b}, - {value: 0x0010, lo: 0x8e, hi: 0xbf}, - // Block 0x10e, offset 0x577 - {value: 0x0014, lo: 0x80, hi: 0xb6}, - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x10f, offset 0x579 - {value: 0x0014, lo: 0x80, hi: 0xac}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x110, offset 0x57b - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x9b, hi: 0x9f}, - {value: 0x0014, lo: 0xa1, hi: 0xaf}, - // Block 0x111, offset 0x57e - {value: 0x0024, lo: 0x80, hi: 0x86}, - {value: 0x0024, lo: 0x88, hi: 0x98}, - {value: 0x0024, lo: 0x9b, hi: 0xa1}, - {value: 0x0024, lo: 0xa3, hi: 0xa4}, - {value: 0x0024, lo: 0xa6, hi: 0xaa}, - // Block 0x112, offset 0x583 - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - // Block 0x113, offset 0x586 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - // Block 0x114, offset 0x588 - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0024, lo: 0xac, hi: 0xaf}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x115, offset 0x58b - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0034, lo: 0x90, hi: 0x96}, - // Block 0x116, offset 0x58d - {value: 0xbc52, lo: 0x80, hi: 0x81}, - {value: 0xbf52, lo: 0x82, hi: 0x83}, - {value: 0x0024, lo: 0x84, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x117, offset 0x593 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x9f}, - {value: 0x0010, lo: 0xa1, hi: 0xa2}, - {value: 0x0010, lo: 0xa4, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb7}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - // Block 0x118, offset 0x59c - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x9b}, - {value: 0x0010, lo: 0xa1, hi: 0xa3}, - {value: 0x0010, lo: 0xa5, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xbb}, - // Block 0x119, offset 0x5a1 - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x11a, offset 0x5a2 - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x11b, offset 0x5a5 - {value: 0x0013, lo: 0x80, hi: 0x89}, - // Block 0x11c, offset 0x5a6 - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x11d, offset 0x5a7 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0014, lo: 0xa0, hi: 0xbf}, - // Block 0x11e, offset 0x5a9 - {value: 0x0014, lo: 0x80, hi: 0xbf}, - // Block 0x11f, offset 0x5aa - {value: 0x0014, lo: 0x80, hi: 0xaf}, -} - -// Total table size 15070 bytes (14KiB); checksum: 1EB13752 diff --git a/vendor/golang.org/x/text/cases/tables13.0.0.go b/vendor/golang.org/x/text/cases/tables13.0.0.go deleted file mode 100644 index 6187e6b4..00000000 --- a/vendor/golang.org/x/text/cases/tables13.0.0.go +++ /dev/null @@ -1,2399 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -//go:build go1.16 && !go1.21 - -package cases - -// UnicodeVersion is the Unicode version from which the tables in this package are derived. -const UnicodeVersion = "13.0.0" - -var xorData string = "" + // Size: 192 bytes - "\x00\x06\x07\x00\x01?\x00\x0f\x03\x00\x0f\x12\x00\x0f\x1f\x00\x0f\x1d" + - "\x00\x01\x13\x00\x0f\x16\x00\x0f\x0b\x00\x0f3\x00\x0f7\x00\x01#\x00\x0f?" + - "\x00\x0e'\x00\x0f/\x00\x0e>\x00\x0f*\x00\x0c&\x00\x0c*\x00\x0c;\x00\x0c9" + - "\x00\x0c%\x00\x01\x08\x00\x03\x0d\x00\x03\x09\x00\x02\x06\x00\x02\x02" + - "\x00\x02\x0c\x00\x01\x00\x00\x01\x03\x00\x01\x01\x00\x01 \x00\x01\x0c" + - "\x00\x01\x10\x00\x03\x10\x00\x036 \x00\x037 \x00\x0b#\x10\x00\x0b 0\x00" + - "\x0b!\x10\x00\x0b!0\x001\x00\x00\x0b(\x04\x00\x03\x04\x1e\x00\x0b)\x08" + - "\x00\x03\x0a\x00\x02:\x00\x02>\x00\x02,\x00\x02\x00\x00\x02\x10\x00\x01<" + - "\x00\x01&\x00\x01*\x00\x01.\x00\x010\x003 \x00\x01\x18\x00\x01(\x00\x01" + - "\x1e\x00\x01\x22" - -var exceptions string = "" + // Size: 2450 bytes - "\x00\x12\x12μΜΜ\x12\x12ssSSSs\x13\x18i̇i̇\x10\x09II\x13\x1bʼnʼNʼN\x11" + - "\x09sSS\x12\x12dždžDž\x12\x12dždžDŽ\x10\x12DŽDž\x12\x12ljljLj\x12\x12ljljLJ\x10\x12LJLj" + - "\x12\x12njnjNj\x12\x12njnjNJ\x10\x12NJNj\x13\x1bǰJ̌J̌\x12\x12dzdzDz\x12\x12dzdzDZ\x10" + - "\x12DZDz\x13\x18ⱥⱥ\x13\x18ⱦⱦ\x10\x1bⱾⱾ\x10\x1bⱿⱿ\x10\x1bⱯⱯ\x10\x1bⱭⱭ\x10" + - "\x1bⱰⱰ\x10\x1bꞫꞫ\x10\x1bꞬꞬ\x10\x1bꞍꞍ\x10\x1bꞪꞪ\x10\x1bꞮꞮ\x10\x1bⱢⱢ\x10" + - "\x1bꞭꞭ\x10\x1bⱮⱮ\x10\x1bⱤⱤ\x10\x1bꟅꟅ\x10\x1bꞱꞱ\x10\x1bꞲꞲ\x10\x1bꞰꞰ2\x12ι" + - "ΙΙ\x166ΐΪ́Ϊ́\x166ΰΫ́Ϋ́\x12\x12σΣΣ\x12\x12βΒΒ\x12\x12θΘΘ\x12\x12" + - "φΦΦ\x12\x12πΠΠ\x12\x12κΚΚ\x12\x12ρΡΡ\x12\x12εΕΕ\x14$եւԵՒԵւ\x10\x1bᲐა" + - "\x10\x1bᲑბ\x10\x1bᲒგ\x10\x1bᲓდ\x10\x1bᲔე\x10\x1bᲕვ\x10\x1bᲖზ\x10\x1bᲗთ" + - "\x10\x1bᲘი\x10\x1bᲙკ\x10\x1bᲚლ\x10\x1bᲛმ\x10\x1bᲜნ\x10\x1bᲝო\x10\x1bᲞპ" + - "\x10\x1bᲟჟ\x10\x1bᲠრ\x10\x1bᲡს\x10\x1bᲢტ\x10\x1bᲣუ\x10\x1bᲤფ\x10\x1bᲥქ" + - "\x10\x1bᲦღ\x10\x1bᲧყ\x10\x1bᲨშ\x10\x1bᲩჩ\x10\x1bᲪც\x10\x1bᲫძ\x10\x1bᲬწ" + - "\x10\x1bᲭჭ\x10\x1bᲮხ\x10\x1bᲯჯ\x10\x1bᲰჰ\x10\x1bᲱჱ\x10\x1bᲲჲ\x10\x1bᲳჳ" + - "\x10\x1bᲴჴ\x10\x1bᲵჵ\x10\x1bᲶჶ\x10\x1bᲷჷ\x10\x1bᲸჸ\x10\x1bᲹჹ\x10\x1bᲺჺ" + - "\x10\x1bᲽჽ\x10\x1bᲾჾ\x10\x1bᲿჿ\x12\x12вВВ\x12\x12дДД\x12\x12оОО\x12\x12с" + - "СС\x12\x12тТТ\x12\x12тТТ\x12\x12ъЪЪ\x12\x12ѣѢѢ\x13\x1bꙋꙊꙊ\x13\x1bẖH̱H̱" + - "\x13\x1bẗT̈T̈\x13\x1bẘW̊W̊\x13\x1bẙY̊Y̊\x13\x1baʾAʾAʾ\x13\x1bṡṠṠ\x12" + - "\x10ssß\x14$ὐΥ̓Υ̓\x166ὒΥ̓̀Υ̓̀\x166ὔΥ̓́Υ̓́\x166ὖΥ̓͂Υ̓͂\x15+ἀιἈΙᾈ" + - "\x15+ἁιἉΙᾉ\x15+ἂιἊΙᾊ\x15+ἃιἋΙᾋ\x15+ἄιἌΙᾌ\x15+ἅιἍΙᾍ\x15+ἆιἎΙᾎ\x15+ἇιἏΙᾏ" + - "\x15\x1dἀιᾀἈΙ\x15\x1dἁιᾁἉΙ\x15\x1dἂιᾂἊΙ\x15\x1dἃιᾃἋΙ\x15\x1dἄιᾄἌΙ\x15" + - "\x1dἅιᾅἍΙ\x15\x1dἆιᾆἎΙ\x15\x1dἇιᾇἏΙ\x15+ἠιἨΙᾘ\x15+ἡιἩΙᾙ\x15+ἢιἪΙᾚ\x15+ἣι" + - "ἫΙᾛ\x15+ἤιἬΙᾜ\x15+ἥιἭΙᾝ\x15+ἦιἮΙᾞ\x15+ἧιἯΙᾟ\x15\x1dἠιᾐἨΙ\x15\x1dἡιᾑἩΙ" + - "\x15\x1dἢιᾒἪΙ\x15\x1dἣιᾓἫΙ\x15\x1dἤιᾔἬΙ\x15\x1dἥιᾕἭΙ\x15\x1dἦιᾖἮΙ\x15" + - "\x1dἧιᾗἯΙ\x15+ὠιὨΙᾨ\x15+ὡιὩΙᾩ\x15+ὢιὪΙᾪ\x15+ὣιὫΙᾫ\x15+ὤιὬΙᾬ\x15+ὥιὭΙᾭ" + - "\x15+ὦιὮΙᾮ\x15+ὧιὯΙᾯ\x15\x1dὠιᾠὨΙ\x15\x1dὡιᾡὩΙ\x15\x1dὢιᾢὪΙ\x15\x1dὣιᾣὫΙ" + - "\x15\x1dὤιᾤὬΙ\x15\x1dὥιᾥὭΙ\x15\x1dὦιᾦὮΙ\x15\x1dὧιᾧὯΙ\x15-ὰιᾺΙᾺͅ\x14#αιΑΙ" + - "ᾼ\x14$άιΆΙΆͅ\x14$ᾶΑ͂Α͂\x166ᾶιΑ͂Ιᾼ͂\x14\x1cαιᾳΑΙ\x12\x12ιΙΙ\x15-ὴιῊΙ" + - "Ὴͅ\x14#ηιΗΙῌ\x14$ήιΉΙΉͅ\x14$ῆΗ͂Η͂\x166ῆιΗ͂Ιῌ͂\x14\x1cηιῃΗΙ\x166ῒΙ" + - "̈̀Ϊ̀\x166ΐΪ́Ϊ́\x14$ῖΙ͂Ι͂\x166ῗΪ͂Ϊ͂\x166ῢΫ̀Ϋ̀\x166ΰΫ́Ϋ" + - "́\x14$ῤΡ̓Ρ̓\x14$ῦΥ͂Υ͂\x166ῧΫ͂Ϋ͂\x15-ὼιῺΙῺͅ\x14#ωιΩΙῼ\x14$ώιΏΙΏͅ" + - "\x14$ῶΩ͂Ω͂\x166ῶιΩ͂Ιῼ͂\x14\x1cωιῳΩΙ\x12\x10ωω\x11\x08kk\x12\x10åå\x12" + - "\x10ɫɫ\x12\x10ɽɽ\x10\x12ȺȺ\x10\x12ȾȾ\x12\x10ɑɑ\x12\x10ɱɱ\x12\x10ɐɐ\x12" + - "\x10ɒɒ\x12\x10ȿȿ\x12\x10ɀɀ\x12\x10ɥɥ\x12\x10ɦɦ\x12\x10ɜɜ\x12\x10ɡɡ\x12" + - "\x10ɬɬ\x12\x10ɪɪ\x12\x10ʞʞ\x12\x10ʇʇ\x12\x10ʝʝ\x12\x10ʂʂ\x12\x12ffFFFf" + - "\x12\x12fiFIFi\x12\x12flFLFl\x13\x1bffiFFIFfi\x13\x1bfflFFLFfl\x12\x12st" + - "STSt\x12\x12stSTSt\x14$մնՄՆՄն\x14$մեՄԵՄե\x14$միՄԻՄի\x14$վնՎՆՎն\x14$մխՄԽՄ" + - "խ" - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookup(s []byte) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupUnsafe(s []byte) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookupString(s string) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupStringUnsafe(s string) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// caseTrie. Total size: 12538 bytes (12.24 KiB). Checksum: af4dfa7d60c71d4c. -type caseTrie struct{} - -func newCaseTrie(i int) *caseTrie { - return &caseTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *caseTrie) lookupValue(n uint32, b byte) uint16 { - switch { - case n < 20: - return uint16(caseValues[n<<6+uint32(b)]) - default: - n -= 20 - return uint16(sparse.lookup(n, b)) - } -} - -// caseValues: 22 blocks, 1408 entries, 2816 bytes -// The third block is the zero block. -var caseValues = [1408]uint16{ - // Block 0x0, offset 0x0 - 0x27: 0x0054, - 0x2e: 0x0054, - 0x30: 0x0010, 0x31: 0x0010, 0x32: 0x0010, 0x33: 0x0010, 0x34: 0x0010, 0x35: 0x0010, - 0x36: 0x0010, 0x37: 0x0010, 0x38: 0x0010, 0x39: 0x0010, 0x3a: 0x0054, - // Block 0x1, offset 0x40 - 0x41: 0x2013, 0x42: 0x2013, 0x43: 0x2013, 0x44: 0x2013, 0x45: 0x2013, - 0x46: 0x2013, 0x47: 0x2013, 0x48: 0x2013, 0x49: 0x2013, 0x4a: 0x2013, 0x4b: 0x2013, - 0x4c: 0x2013, 0x4d: 0x2013, 0x4e: 0x2013, 0x4f: 0x2013, 0x50: 0x2013, 0x51: 0x2013, - 0x52: 0x2013, 0x53: 0x2013, 0x54: 0x2013, 0x55: 0x2013, 0x56: 0x2013, 0x57: 0x2013, - 0x58: 0x2013, 0x59: 0x2013, 0x5a: 0x2013, - 0x5e: 0x0004, 0x5f: 0x0010, 0x60: 0x0004, 0x61: 0x2012, 0x62: 0x2012, 0x63: 0x2012, - 0x64: 0x2012, 0x65: 0x2012, 0x66: 0x2012, 0x67: 0x2012, 0x68: 0x2012, 0x69: 0x2012, - 0x6a: 0x2012, 0x6b: 0x2012, 0x6c: 0x2012, 0x6d: 0x2012, 0x6e: 0x2012, 0x6f: 0x2012, - 0x70: 0x2012, 0x71: 0x2012, 0x72: 0x2012, 0x73: 0x2012, 0x74: 0x2012, 0x75: 0x2012, - 0x76: 0x2012, 0x77: 0x2012, 0x78: 0x2012, 0x79: 0x2012, 0x7a: 0x2012, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x0852, 0xc1: 0x0b53, 0xc2: 0x0113, 0xc3: 0x0112, 0xc4: 0x0113, 0xc5: 0x0112, - 0xc6: 0x0b53, 0xc7: 0x0f13, 0xc8: 0x0f12, 0xc9: 0x0e53, 0xca: 0x1153, 0xcb: 0x0713, - 0xcc: 0x0712, 0xcd: 0x0012, 0xce: 0x1453, 0xcf: 0x1753, 0xd0: 0x1a53, 0xd1: 0x0313, - 0xd2: 0x0312, 0xd3: 0x1d53, 0xd4: 0x2053, 0xd5: 0x2352, 0xd6: 0x2653, 0xd7: 0x2653, - 0xd8: 0x0113, 0xd9: 0x0112, 0xda: 0x2952, 0xdb: 0x0012, 0xdc: 0x1d53, 0xdd: 0x2c53, - 0xde: 0x2f52, 0xdf: 0x3253, 0xe0: 0x0113, 0xe1: 0x0112, 0xe2: 0x0113, 0xe3: 0x0112, - 0xe4: 0x0113, 0xe5: 0x0112, 0xe6: 0x3553, 0xe7: 0x0f13, 0xe8: 0x0f12, 0xe9: 0x3853, - 0xea: 0x0012, 0xeb: 0x0012, 0xec: 0x0113, 0xed: 0x0112, 0xee: 0x3553, 0xef: 0x1f13, - 0xf0: 0x1f12, 0xf1: 0x3b53, 0xf2: 0x3e53, 0xf3: 0x0713, 0xf4: 0x0712, 0xf5: 0x0313, - 0xf6: 0x0312, 0xf7: 0x4153, 0xf8: 0x0113, 0xf9: 0x0112, 0xfa: 0x0012, 0xfb: 0x0010, - 0xfc: 0x0113, 0xfd: 0x0112, 0xfe: 0x0012, 0xff: 0x4452, - // Block 0x4, offset 0x100 - 0x100: 0x0010, 0x101: 0x0010, 0x102: 0x0010, 0x103: 0x0010, 0x104: 0x02db, 0x105: 0x0359, - 0x106: 0x03da, 0x107: 0x043b, 0x108: 0x04b9, 0x109: 0x053a, 0x10a: 0x059b, 0x10b: 0x0619, - 0x10c: 0x069a, 0x10d: 0x0313, 0x10e: 0x0312, 0x10f: 0x1f13, 0x110: 0x1f12, 0x111: 0x0313, - 0x112: 0x0312, 0x113: 0x0713, 0x114: 0x0712, 0x115: 0x0313, 0x116: 0x0312, 0x117: 0x0f13, - 0x118: 0x0f12, 0x119: 0x0313, 0x11a: 0x0312, 0x11b: 0x0713, 0x11c: 0x0712, 0x11d: 0x1452, - 0x11e: 0x0113, 0x11f: 0x0112, 0x120: 0x0113, 0x121: 0x0112, 0x122: 0x0113, 0x123: 0x0112, - 0x124: 0x0113, 0x125: 0x0112, 0x126: 0x0113, 0x127: 0x0112, 0x128: 0x0113, 0x129: 0x0112, - 0x12a: 0x0113, 0x12b: 0x0112, 0x12c: 0x0113, 0x12d: 0x0112, 0x12e: 0x0113, 0x12f: 0x0112, - 0x130: 0x06fa, 0x131: 0x07ab, 0x132: 0x0829, 0x133: 0x08aa, 0x134: 0x0113, 0x135: 0x0112, - 0x136: 0x2353, 0x137: 0x4453, 0x138: 0x0113, 0x139: 0x0112, 0x13a: 0x0113, 0x13b: 0x0112, - 0x13c: 0x0113, 0x13d: 0x0112, 0x13e: 0x0113, 0x13f: 0x0112, - // Block 0x5, offset 0x140 - 0x140: 0x0a8a, 0x141: 0x0313, 0x142: 0x0312, 0x143: 0x0853, 0x144: 0x4753, 0x145: 0x4a53, - 0x146: 0x0113, 0x147: 0x0112, 0x148: 0x0113, 0x149: 0x0112, 0x14a: 0x0113, 0x14b: 0x0112, - 0x14c: 0x0113, 0x14d: 0x0112, 0x14e: 0x0113, 0x14f: 0x0112, 0x150: 0x0b0a, 0x151: 0x0b8a, - 0x152: 0x0c0a, 0x153: 0x0b52, 0x154: 0x0b52, 0x155: 0x0012, 0x156: 0x0e52, 0x157: 0x1152, - 0x158: 0x0012, 0x159: 0x1752, 0x15a: 0x0012, 0x15b: 0x1a52, 0x15c: 0x0c8a, 0x15d: 0x0012, - 0x15e: 0x0012, 0x15f: 0x0012, 0x160: 0x1d52, 0x161: 0x0d0a, 0x162: 0x0012, 0x163: 0x2052, - 0x164: 0x0012, 0x165: 0x0d8a, 0x166: 0x0e0a, 0x167: 0x0012, 0x168: 0x2652, 0x169: 0x2652, - 0x16a: 0x0e8a, 0x16b: 0x0f0a, 0x16c: 0x0f8a, 0x16d: 0x0012, 0x16e: 0x0012, 0x16f: 0x1d52, - 0x170: 0x0012, 0x171: 0x100a, 0x172: 0x2c52, 0x173: 0x0012, 0x174: 0x0012, 0x175: 0x3252, - 0x176: 0x0012, 0x177: 0x0012, 0x178: 0x0012, 0x179: 0x0012, 0x17a: 0x0012, 0x17b: 0x0012, - 0x17c: 0x0012, 0x17d: 0x108a, 0x17e: 0x0012, 0x17f: 0x0012, - // Block 0x6, offset 0x180 - 0x180: 0x3552, 0x181: 0x0012, 0x182: 0x110a, 0x183: 0x3852, 0x184: 0x0012, 0x185: 0x0012, - 0x186: 0x0012, 0x187: 0x118a, 0x188: 0x3552, 0x189: 0x4752, 0x18a: 0x3b52, 0x18b: 0x3e52, - 0x18c: 0x4a52, 0x18d: 0x0012, 0x18e: 0x0012, 0x18f: 0x0012, 0x190: 0x0012, 0x191: 0x0012, - 0x192: 0x4152, 0x193: 0x0012, 0x194: 0x0010, 0x195: 0x0012, 0x196: 0x0012, 0x197: 0x0012, - 0x198: 0x0012, 0x199: 0x0012, 0x19a: 0x0012, 0x19b: 0x0012, 0x19c: 0x0012, 0x19d: 0x120a, - 0x19e: 0x128a, 0x19f: 0x0012, 0x1a0: 0x0012, 0x1a1: 0x0012, 0x1a2: 0x0012, 0x1a3: 0x0012, - 0x1a4: 0x0012, 0x1a5: 0x0012, 0x1a6: 0x0012, 0x1a7: 0x0012, 0x1a8: 0x0012, 0x1a9: 0x0012, - 0x1aa: 0x0012, 0x1ab: 0x0012, 0x1ac: 0x0012, 0x1ad: 0x0012, 0x1ae: 0x0012, 0x1af: 0x0012, - 0x1b0: 0x0015, 0x1b1: 0x0015, 0x1b2: 0x0015, 0x1b3: 0x0015, 0x1b4: 0x0015, 0x1b5: 0x0015, - 0x1b6: 0x0015, 0x1b7: 0x0015, 0x1b8: 0x0015, 0x1b9: 0x0014, 0x1ba: 0x0014, 0x1bb: 0x0014, - 0x1bc: 0x0014, 0x1bd: 0x0014, 0x1be: 0x0014, 0x1bf: 0x0014, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x0024, 0x1c1: 0x0024, 0x1c2: 0x0024, 0x1c3: 0x0024, 0x1c4: 0x0024, 0x1c5: 0x130d, - 0x1c6: 0x0024, 0x1c7: 0x0034, 0x1c8: 0x0034, 0x1c9: 0x0034, 0x1ca: 0x0024, 0x1cb: 0x0024, - 0x1cc: 0x0024, 0x1cd: 0x0034, 0x1ce: 0x0034, 0x1cf: 0x0014, 0x1d0: 0x0024, 0x1d1: 0x0024, - 0x1d2: 0x0024, 0x1d3: 0x0034, 0x1d4: 0x0034, 0x1d5: 0x0034, 0x1d6: 0x0034, 0x1d7: 0x0024, - 0x1d8: 0x0034, 0x1d9: 0x0034, 0x1da: 0x0034, 0x1db: 0x0024, 0x1dc: 0x0034, 0x1dd: 0x0034, - 0x1de: 0x0034, 0x1df: 0x0034, 0x1e0: 0x0034, 0x1e1: 0x0034, 0x1e2: 0x0034, 0x1e3: 0x0024, - 0x1e4: 0x0024, 0x1e5: 0x0024, 0x1e6: 0x0024, 0x1e7: 0x0024, 0x1e8: 0x0024, 0x1e9: 0x0024, - 0x1ea: 0x0024, 0x1eb: 0x0024, 0x1ec: 0x0024, 0x1ed: 0x0024, 0x1ee: 0x0024, 0x1ef: 0x0024, - 0x1f0: 0x0113, 0x1f1: 0x0112, 0x1f2: 0x0113, 0x1f3: 0x0112, 0x1f4: 0x0014, 0x1f5: 0x0004, - 0x1f6: 0x0113, 0x1f7: 0x0112, 0x1fa: 0x0015, 0x1fb: 0x4d52, - 0x1fc: 0x5052, 0x1fd: 0x5052, 0x1ff: 0x5353, - // Block 0x8, offset 0x200 - 0x204: 0x0004, 0x205: 0x0004, - 0x206: 0x2a13, 0x207: 0x0054, 0x208: 0x2513, 0x209: 0x2713, 0x20a: 0x2513, - 0x20c: 0x5653, 0x20e: 0x5953, 0x20f: 0x5c53, 0x210: 0x138a, 0x211: 0x2013, - 0x212: 0x2013, 0x213: 0x2013, 0x214: 0x2013, 0x215: 0x2013, 0x216: 0x2013, 0x217: 0x2013, - 0x218: 0x2013, 0x219: 0x2013, 0x21a: 0x2013, 0x21b: 0x2013, 0x21c: 0x2013, 0x21d: 0x2013, - 0x21e: 0x2013, 0x21f: 0x2013, 0x220: 0x5f53, 0x221: 0x5f53, 0x223: 0x5f53, - 0x224: 0x5f53, 0x225: 0x5f53, 0x226: 0x5f53, 0x227: 0x5f53, 0x228: 0x5f53, 0x229: 0x5f53, - 0x22a: 0x5f53, 0x22b: 0x5f53, 0x22c: 0x2a12, 0x22d: 0x2512, 0x22e: 0x2712, 0x22f: 0x2512, - 0x230: 0x14ca, 0x231: 0x2012, 0x232: 0x2012, 0x233: 0x2012, 0x234: 0x2012, 0x235: 0x2012, - 0x236: 0x2012, 0x237: 0x2012, 0x238: 0x2012, 0x239: 0x2012, 0x23a: 0x2012, 0x23b: 0x2012, - 0x23c: 0x2012, 0x23d: 0x2012, 0x23e: 0x2012, 0x23f: 0x2012, - // Block 0x9, offset 0x240 - 0x240: 0x5f52, 0x241: 0x5f52, 0x242: 0x160a, 0x243: 0x5f52, 0x244: 0x5f52, 0x245: 0x5f52, - 0x246: 0x5f52, 0x247: 0x5f52, 0x248: 0x5f52, 0x249: 0x5f52, 0x24a: 0x5f52, 0x24b: 0x5f52, - 0x24c: 0x5652, 0x24d: 0x5952, 0x24e: 0x5c52, 0x24f: 0x1813, 0x250: 0x168a, 0x251: 0x170a, - 0x252: 0x0013, 0x253: 0x0013, 0x254: 0x0013, 0x255: 0x178a, 0x256: 0x180a, 0x257: 0x1812, - 0x258: 0x0113, 0x259: 0x0112, 0x25a: 0x0113, 0x25b: 0x0112, 0x25c: 0x0113, 0x25d: 0x0112, - 0x25e: 0x0113, 0x25f: 0x0112, 0x260: 0x0113, 0x261: 0x0112, 0x262: 0x0113, 0x263: 0x0112, - 0x264: 0x0113, 0x265: 0x0112, 0x266: 0x0113, 0x267: 0x0112, 0x268: 0x0113, 0x269: 0x0112, - 0x26a: 0x0113, 0x26b: 0x0112, 0x26c: 0x0113, 0x26d: 0x0112, 0x26e: 0x0113, 0x26f: 0x0112, - 0x270: 0x188a, 0x271: 0x190a, 0x272: 0x0b12, 0x273: 0x5352, 0x274: 0x6253, 0x275: 0x198a, - 0x277: 0x0f13, 0x278: 0x0f12, 0x279: 0x0b13, 0x27a: 0x0113, 0x27b: 0x0112, - 0x27c: 0x0012, 0x27d: 0x4d53, 0x27e: 0x5053, 0x27f: 0x5053, - // Block 0xa, offset 0x280 - 0x280: 0x6852, 0x281: 0x6852, 0x282: 0x6852, 0x283: 0x6852, 0x284: 0x6852, 0x285: 0x6852, - 0x286: 0x6852, 0x287: 0x1a0a, 0x288: 0x0012, 0x28a: 0x0010, - 0x291: 0x0034, - 0x292: 0x0024, 0x293: 0x0024, 0x294: 0x0024, 0x295: 0x0024, 0x296: 0x0034, 0x297: 0x0024, - 0x298: 0x0024, 0x299: 0x0024, 0x29a: 0x0034, 0x29b: 0x0034, 0x29c: 0x0024, 0x29d: 0x0024, - 0x29e: 0x0024, 0x29f: 0x0024, 0x2a0: 0x0024, 0x2a1: 0x0024, 0x2a2: 0x0034, 0x2a3: 0x0034, - 0x2a4: 0x0034, 0x2a5: 0x0034, 0x2a6: 0x0034, 0x2a7: 0x0034, 0x2a8: 0x0024, 0x2a9: 0x0024, - 0x2aa: 0x0034, 0x2ab: 0x0024, 0x2ac: 0x0024, 0x2ad: 0x0034, 0x2ae: 0x0034, 0x2af: 0x0024, - 0x2b0: 0x0034, 0x2b1: 0x0034, 0x2b2: 0x0034, 0x2b3: 0x0034, 0x2b4: 0x0034, 0x2b5: 0x0034, - 0x2b6: 0x0034, 0x2b7: 0x0034, 0x2b8: 0x0034, 0x2b9: 0x0034, 0x2ba: 0x0034, 0x2bb: 0x0034, - 0x2bc: 0x0034, 0x2bd: 0x0034, 0x2bf: 0x0034, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x7053, 0x2c1: 0x7053, 0x2c2: 0x7053, 0x2c3: 0x7053, 0x2c4: 0x7053, 0x2c5: 0x7053, - 0x2c7: 0x7053, - 0x2cd: 0x7053, 0x2d0: 0x1aea, 0x2d1: 0x1b6a, - 0x2d2: 0x1bea, 0x2d3: 0x1c6a, 0x2d4: 0x1cea, 0x2d5: 0x1d6a, 0x2d6: 0x1dea, 0x2d7: 0x1e6a, - 0x2d8: 0x1eea, 0x2d9: 0x1f6a, 0x2da: 0x1fea, 0x2db: 0x206a, 0x2dc: 0x20ea, 0x2dd: 0x216a, - 0x2de: 0x21ea, 0x2df: 0x226a, 0x2e0: 0x22ea, 0x2e1: 0x236a, 0x2e2: 0x23ea, 0x2e3: 0x246a, - 0x2e4: 0x24ea, 0x2e5: 0x256a, 0x2e6: 0x25ea, 0x2e7: 0x266a, 0x2e8: 0x26ea, 0x2e9: 0x276a, - 0x2ea: 0x27ea, 0x2eb: 0x286a, 0x2ec: 0x28ea, 0x2ed: 0x296a, 0x2ee: 0x29ea, 0x2ef: 0x2a6a, - 0x2f0: 0x2aea, 0x2f1: 0x2b6a, 0x2f2: 0x2bea, 0x2f3: 0x2c6a, 0x2f4: 0x2cea, 0x2f5: 0x2d6a, - 0x2f6: 0x2dea, 0x2f7: 0x2e6a, 0x2f8: 0x2eea, 0x2f9: 0x2f6a, 0x2fa: 0x2fea, - 0x2fc: 0x0014, 0x2fd: 0x306a, 0x2fe: 0x30ea, 0x2ff: 0x316a, - // Block 0xc, offset 0x300 - 0x300: 0x0812, 0x301: 0x0812, 0x302: 0x0812, 0x303: 0x0812, 0x304: 0x0812, 0x305: 0x0812, - 0x308: 0x0813, 0x309: 0x0813, 0x30a: 0x0813, 0x30b: 0x0813, - 0x30c: 0x0813, 0x30d: 0x0813, 0x310: 0x3b1a, 0x311: 0x0812, - 0x312: 0x3bfa, 0x313: 0x0812, 0x314: 0x3d3a, 0x315: 0x0812, 0x316: 0x3e7a, 0x317: 0x0812, - 0x319: 0x0813, 0x31b: 0x0813, 0x31d: 0x0813, - 0x31f: 0x0813, 0x320: 0x0812, 0x321: 0x0812, 0x322: 0x0812, 0x323: 0x0812, - 0x324: 0x0812, 0x325: 0x0812, 0x326: 0x0812, 0x327: 0x0812, 0x328: 0x0813, 0x329: 0x0813, - 0x32a: 0x0813, 0x32b: 0x0813, 0x32c: 0x0813, 0x32d: 0x0813, 0x32e: 0x0813, 0x32f: 0x0813, - 0x330: 0x9252, 0x331: 0x9252, 0x332: 0x9552, 0x333: 0x9552, 0x334: 0x9852, 0x335: 0x9852, - 0x336: 0x9b52, 0x337: 0x9b52, 0x338: 0x9e52, 0x339: 0x9e52, 0x33a: 0xa152, 0x33b: 0xa152, - 0x33c: 0x4d52, 0x33d: 0x4d52, - // Block 0xd, offset 0x340 - 0x340: 0x3fba, 0x341: 0x40aa, 0x342: 0x419a, 0x343: 0x428a, 0x344: 0x437a, 0x345: 0x446a, - 0x346: 0x455a, 0x347: 0x464a, 0x348: 0x4739, 0x349: 0x4829, 0x34a: 0x4919, 0x34b: 0x4a09, - 0x34c: 0x4af9, 0x34d: 0x4be9, 0x34e: 0x4cd9, 0x34f: 0x4dc9, 0x350: 0x4eba, 0x351: 0x4faa, - 0x352: 0x509a, 0x353: 0x518a, 0x354: 0x527a, 0x355: 0x536a, 0x356: 0x545a, 0x357: 0x554a, - 0x358: 0x5639, 0x359: 0x5729, 0x35a: 0x5819, 0x35b: 0x5909, 0x35c: 0x59f9, 0x35d: 0x5ae9, - 0x35e: 0x5bd9, 0x35f: 0x5cc9, 0x360: 0x5dba, 0x361: 0x5eaa, 0x362: 0x5f9a, 0x363: 0x608a, - 0x364: 0x617a, 0x365: 0x626a, 0x366: 0x635a, 0x367: 0x644a, 0x368: 0x6539, 0x369: 0x6629, - 0x36a: 0x6719, 0x36b: 0x6809, 0x36c: 0x68f9, 0x36d: 0x69e9, 0x36e: 0x6ad9, 0x36f: 0x6bc9, - 0x370: 0x0812, 0x371: 0x0812, 0x372: 0x6cba, 0x373: 0x6dca, 0x374: 0x6e9a, - 0x376: 0x6f7a, 0x377: 0x705a, 0x378: 0x0813, 0x379: 0x0813, 0x37a: 0x9253, 0x37b: 0x9253, - 0x37c: 0x7199, 0x37d: 0x0004, 0x37e: 0x726a, 0x37f: 0x0004, - // Block 0xe, offset 0x380 - 0x380: 0x0004, 0x381: 0x0004, 0x382: 0x72ea, 0x383: 0x73fa, 0x384: 0x74ca, - 0x386: 0x75aa, 0x387: 0x768a, 0x388: 0x9553, 0x389: 0x9553, 0x38a: 0x9853, 0x38b: 0x9853, - 0x38c: 0x77c9, 0x38d: 0x0004, 0x38e: 0x0004, 0x38f: 0x0004, 0x390: 0x0812, 0x391: 0x0812, - 0x392: 0x789a, 0x393: 0x79da, 0x396: 0x7b1a, 0x397: 0x7bfa, - 0x398: 0x0813, 0x399: 0x0813, 0x39a: 0x9b53, 0x39b: 0x9b53, 0x39d: 0x0004, - 0x39e: 0x0004, 0x39f: 0x0004, 0x3a0: 0x0812, 0x3a1: 0x0812, 0x3a2: 0x7d3a, 0x3a3: 0x7e7a, - 0x3a4: 0x7fba, 0x3a5: 0x0912, 0x3a6: 0x809a, 0x3a7: 0x817a, 0x3a8: 0x0813, 0x3a9: 0x0813, - 0x3aa: 0xa153, 0x3ab: 0xa153, 0x3ac: 0x0913, 0x3ad: 0x0004, 0x3ae: 0x0004, 0x3af: 0x0004, - 0x3b2: 0x82ba, 0x3b3: 0x83ca, 0x3b4: 0x849a, - 0x3b6: 0x857a, 0x3b7: 0x865a, 0x3b8: 0x9e53, 0x3b9: 0x9e53, 0x3ba: 0x4d53, 0x3bb: 0x4d53, - 0x3bc: 0x8799, 0x3bd: 0x0004, 0x3be: 0x0004, - // Block 0xf, offset 0x3c0 - 0x3c2: 0x0013, - 0x3c7: 0x0013, 0x3ca: 0x0012, 0x3cb: 0x0013, - 0x3cc: 0x0013, 0x3cd: 0x0013, 0x3ce: 0x0012, 0x3cf: 0x0012, 0x3d0: 0x0013, 0x3d1: 0x0013, - 0x3d2: 0x0013, 0x3d3: 0x0012, 0x3d5: 0x0013, - 0x3d9: 0x0013, 0x3da: 0x0013, 0x3db: 0x0013, 0x3dc: 0x0013, 0x3dd: 0x0013, - 0x3e4: 0x0013, 0x3e6: 0x886b, 0x3e8: 0x0013, - 0x3ea: 0x88cb, 0x3eb: 0x890b, 0x3ec: 0x0013, 0x3ed: 0x0013, 0x3ef: 0x0012, - 0x3f0: 0x0013, 0x3f1: 0x0013, 0x3f2: 0xa453, 0x3f3: 0x0013, 0x3f4: 0x0012, 0x3f5: 0x0010, - 0x3f6: 0x0010, 0x3f7: 0x0010, 0x3f8: 0x0010, 0x3f9: 0x0012, - 0x3fc: 0x0012, 0x3fd: 0x0012, 0x3fe: 0x0013, 0x3ff: 0x0013, - // Block 0x10, offset 0x400 - 0x400: 0x1a13, 0x401: 0x1a13, 0x402: 0x1e13, 0x403: 0x1e13, 0x404: 0x1a13, 0x405: 0x1a13, - 0x406: 0x2613, 0x407: 0x2613, 0x408: 0x2a13, 0x409: 0x2a13, 0x40a: 0x2e13, 0x40b: 0x2e13, - 0x40c: 0x2a13, 0x40d: 0x2a13, 0x40e: 0x2613, 0x40f: 0x2613, 0x410: 0xa752, 0x411: 0xa752, - 0x412: 0xaa52, 0x413: 0xaa52, 0x414: 0xad52, 0x415: 0xad52, 0x416: 0xaa52, 0x417: 0xaa52, - 0x418: 0xa752, 0x419: 0xa752, 0x41a: 0x1a12, 0x41b: 0x1a12, 0x41c: 0x1e12, 0x41d: 0x1e12, - 0x41e: 0x1a12, 0x41f: 0x1a12, 0x420: 0x2612, 0x421: 0x2612, 0x422: 0x2a12, 0x423: 0x2a12, - 0x424: 0x2e12, 0x425: 0x2e12, 0x426: 0x2a12, 0x427: 0x2a12, 0x428: 0x2612, 0x429: 0x2612, - // Block 0x11, offset 0x440 - 0x440: 0x6552, 0x441: 0x6552, 0x442: 0x6552, 0x443: 0x6552, 0x444: 0x6552, 0x445: 0x6552, - 0x446: 0x6552, 0x447: 0x6552, 0x448: 0x6552, 0x449: 0x6552, 0x44a: 0x6552, 0x44b: 0x6552, - 0x44c: 0x6552, 0x44d: 0x6552, 0x44e: 0x6552, 0x44f: 0x6552, 0x450: 0xb052, 0x451: 0xb052, - 0x452: 0xb052, 0x453: 0xb052, 0x454: 0xb052, 0x455: 0xb052, 0x456: 0xb052, 0x457: 0xb052, - 0x458: 0xb052, 0x459: 0xb052, 0x45a: 0xb052, 0x45b: 0xb052, 0x45c: 0xb052, 0x45d: 0xb052, - 0x45e: 0xb052, 0x460: 0x0113, 0x461: 0x0112, 0x462: 0x896b, 0x463: 0x8b53, - 0x464: 0x89cb, 0x465: 0x8a2a, 0x466: 0x8a8a, 0x467: 0x0f13, 0x468: 0x0f12, 0x469: 0x0313, - 0x46a: 0x0312, 0x46b: 0x0713, 0x46c: 0x0712, 0x46d: 0x8aeb, 0x46e: 0x8b4b, 0x46f: 0x8bab, - 0x470: 0x8c0b, 0x471: 0x0012, 0x472: 0x0113, 0x473: 0x0112, 0x474: 0x0012, 0x475: 0x0313, - 0x476: 0x0312, 0x477: 0x0012, 0x478: 0x0012, 0x479: 0x0012, 0x47a: 0x0012, 0x47b: 0x0012, - 0x47c: 0x0015, 0x47d: 0x0015, 0x47e: 0x8c6b, 0x47f: 0x8ccb, - // Block 0x12, offset 0x480 - 0x480: 0x0113, 0x481: 0x0112, 0x482: 0x0113, 0x483: 0x0112, 0x484: 0x0113, 0x485: 0x0112, - 0x486: 0x0113, 0x487: 0x0112, 0x488: 0x0014, 0x489: 0x0014, 0x48a: 0x0014, 0x48b: 0x0713, - 0x48c: 0x0712, 0x48d: 0x8d2b, 0x48e: 0x0012, 0x48f: 0x0010, 0x490: 0x0113, 0x491: 0x0112, - 0x492: 0x0113, 0x493: 0x0112, 0x494: 0x6552, 0x495: 0x0012, 0x496: 0x0113, 0x497: 0x0112, - 0x498: 0x0113, 0x499: 0x0112, 0x49a: 0x0113, 0x49b: 0x0112, 0x49c: 0x0113, 0x49d: 0x0112, - 0x49e: 0x0113, 0x49f: 0x0112, 0x4a0: 0x0113, 0x4a1: 0x0112, 0x4a2: 0x0113, 0x4a3: 0x0112, - 0x4a4: 0x0113, 0x4a5: 0x0112, 0x4a6: 0x0113, 0x4a7: 0x0112, 0x4a8: 0x0113, 0x4a9: 0x0112, - 0x4aa: 0x8d8b, 0x4ab: 0x8deb, 0x4ac: 0x8e4b, 0x4ad: 0x8eab, 0x4ae: 0x8f0b, 0x4af: 0x0012, - 0x4b0: 0x8f6b, 0x4b1: 0x8fcb, 0x4b2: 0x902b, 0x4b3: 0xb353, 0x4b4: 0x0113, 0x4b5: 0x0112, - 0x4b6: 0x0113, 0x4b7: 0x0112, 0x4b8: 0x0113, 0x4b9: 0x0112, 0x4ba: 0x0113, 0x4bb: 0x0112, - 0x4bc: 0x0113, 0x4bd: 0x0112, 0x4be: 0x0113, 0x4bf: 0x0112, - // Block 0x13, offset 0x4c0 - 0x4c0: 0x90ea, 0x4c1: 0x916a, 0x4c2: 0x91ea, 0x4c3: 0x926a, 0x4c4: 0x931a, 0x4c5: 0x93ca, - 0x4c6: 0x944a, - 0x4d3: 0x94ca, 0x4d4: 0x95aa, 0x4d5: 0x968a, 0x4d6: 0x976a, 0x4d7: 0x984a, - 0x4dd: 0x0010, - 0x4de: 0x0034, 0x4df: 0x0010, 0x4e0: 0x0010, 0x4e1: 0x0010, 0x4e2: 0x0010, 0x4e3: 0x0010, - 0x4e4: 0x0010, 0x4e5: 0x0010, 0x4e6: 0x0010, 0x4e7: 0x0010, 0x4e8: 0x0010, - 0x4ea: 0x0010, 0x4eb: 0x0010, 0x4ec: 0x0010, 0x4ed: 0x0010, 0x4ee: 0x0010, 0x4ef: 0x0010, - 0x4f0: 0x0010, 0x4f1: 0x0010, 0x4f2: 0x0010, 0x4f3: 0x0010, 0x4f4: 0x0010, 0x4f5: 0x0010, - 0x4f6: 0x0010, 0x4f8: 0x0010, 0x4f9: 0x0010, 0x4fa: 0x0010, 0x4fb: 0x0010, - 0x4fc: 0x0010, 0x4fe: 0x0010, - // Block 0x14, offset 0x500 - 0x500: 0x2213, 0x501: 0x2213, 0x502: 0x2613, 0x503: 0x2613, 0x504: 0x2213, 0x505: 0x2213, - 0x506: 0x2e13, 0x507: 0x2e13, 0x508: 0x2213, 0x509: 0x2213, 0x50a: 0x2613, 0x50b: 0x2613, - 0x50c: 0x2213, 0x50d: 0x2213, 0x50e: 0x3e13, 0x50f: 0x3e13, 0x510: 0x2213, 0x511: 0x2213, - 0x512: 0x2613, 0x513: 0x2613, 0x514: 0x2213, 0x515: 0x2213, 0x516: 0x2e13, 0x517: 0x2e13, - 0x518: 0x2213, 0x519: 0x2213, 0x51a: 0x2613, 0x51b: 0x2613, 0x51c: 0x2213, 0x51d: 0x2213, - 0x51e: 0xbc53, 0x51f: 0xbc53, 0x520: 0xbf53, 0x521: 0xbf53, 0x522: 0x2212, 0x523: 0x2212, - 0x524: 0x2612, 0x525: 0x2612, 0x526: 0x2212, 0x527: 0x2212, 0x528: 0x2e12, 0x529: 0x2e12, - 0x52a: 0x2212, 0x52b: 0x2212, 0x52c: 0x2612, 0x52d: 0x2612, 0x52e: 0x2212, 0x52f: 0x2212, - 0x530: 0x3e12, 0x531: 0x3e12, 0x532: 0x2212, 0x533: 0x2212, 0x534: 0x2612, 0x535: 0x2612, - 0x536: 0x2212, 0x537: 0x2212, 0x538: 0x2e12, 0x539: 0x2e12, 0x53a: 0x2212, 0x53b: 0x2212, - 0x53c: 0x2612, 0x53d: 0x2612, 0x53e: 0x2212, 0x53f: 0x2212, - // Block 0x15, offset 0x540 - 0x542: 0x0010, - 0x547: 0x0010, 0x549: 0x0010, 0x54b: 0x0010, - 0x54d: 0x0010, 0x54e: 0x0010, 0x54f: 0x0010, 0x551: 0x0010, - 0x552: 0x0010, 0x554: 0x0010, 0x557: 0x0010, - 0x559: 0x0010, 0x55b: 0x0010, 0x55d: 0x0010, - 0x55f: 0x0010, 0x561: 0x0010, 0x562: 0x0010, - 0x564: 0x0010, 0x567: 0x0010, 0x568: 0x0010, 0x569: 0x0010, - 0x56a: 0x0010, 0x56c: 0x0010, 0x56d: 0x0010, 0x56e: 0x0010, 0x56f: 0x0010, - 0x570: 0x0010, 0x571: 0x0010, 0x572: 0x0010, 0x574: 0x0010, 0x575: 0x0010, - 0x576: 0x0010, 0x577: 0x0010, 0x579: 0x0010, 0x57a: 0x0010, 0x57b: 0x0010, - 0x57c: 0x0010, 0x57e: 0x0010, -} - -// caseIndex: 25 blocks, 1600 entries, 3200 bytes -// Block 0 is the zero block. -var caseIndex = [1600]uint16{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x14, 0xc3: 0x15, 0xc4: 0x16, 0xc5: 0x17, 0xc6: 0x01, 0xc7: 0x02, - 0xc8: 0x18, 0xc9: 0x03, 0xca: 0x04, 0xcb: 0x19, 0xcc: 0x1a, 0xcd: 0x05, 0xce: 0x06, 0xcf: 0x07, - 0xd0: 0x1b, 0xd1: 0x1c, 0xd2: 0x1d, 0xd3: 0x1e, 0xd4: 0x1f, 0xd5: 0x20, 0xd6: 0x08, 0xd7: 0x21, - 0xd8: 0x22, 0xd9: 0x23, 0xda: 0x24, 0xdb: 0x25, 0xdc: 0x26, 0xdd: 0x27, 0xde: 0x28, 0xdf: 0x29, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, - 0xea: 0x06, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x08, 0xef: 0x09, - 0xf0: 0x14, 0xf3: 0x16, - // Block 0x4, offset 0x100 - 0x120: 0x2a, 0x121: 0x2b, 0x122: 0x2c, 0x123: 0x2d, 0x124: 0x2e, 0x125: 0x2f, 0x126: 0x30, 0x127: 0x31, - 0x128: 0x32, 0x129: 0x33, 0x12a: 0x34, 0x12b: 0x35, 0x12c: 0x36, 0x12d: 0x37, 0x12e: 0x38, 0x12f: 0x39, - 0x130: 0x3a, 0x131: 0x3b, 0x132: 0x3c, 0x133: 0x3d, 0x134: 0x3e, 0x135: 0x3f, 0x136: 0x40, 0x137: 0x41, - 0x138: 0x42, 0x139: 0x43, 0x13a: 0x44, 0x13b: 0x45, 0x13c: 0x46, 0x13d: 0x47, 0x13e: 0x48, 0x13f: 0x49, - // Block 0x5, offset 0x140 - 0x140: 0x4a, 0x141: 0x4b, 0x142: 0x4c, 0x143: 0x09, 0x144: 0x24, 0x145: 0x24, 0x146: 0x24, 0x147: 0x24, - 0x148: 0x24, 0x149: 0x4d, 0x14a: 0x4e, 0x14b: 0x4f, 0x14c: 0x50, 0x14d: 0x51, 0x14e: 0x52, 0x14f: 0x53, - 0x150: 0x54, 0x151: 0x24, 0x152: 0x24, 0x153: 0x24, 0x154: 0x24, 0x155: 0x24, 0x156: 0x24, 0x157: 0x24, - 0x158: 0x24, 0x159: 0x55, 0x15a: 0x56, 0x15b: 0x57, 0x15c: 0x58, 0x15d: 0x59, 0x15e: 0x5a, 0x15f: 0x5b, - 0x160: 0x5c, 0x161: 0x5d, 0x162: 0x5e, 0x163: 0x5f, 0x164: 0x60, 0x165: 0x61, 0x167: 0x62, - 0x168: 0x63, 0x169: 0x64, 0x16a: 0x65, 0x16b: 0x66, 0x16c: 0x67, 0x16d: 0x68, 0x16e: 0x69, 0x16f: 0x6a, - 0x170: 0x6b, 0x171: 0x6c, 0x172: 0x6d, 0x173: 0x6e, 0x174: 0x6f, 0x175: 0x70, 0x176: 0x71, 0x177: 0x72, - 0x178: 0x73, 0x179: 0x73, 0x17a: 0x74, 0x17b: 0x73, 0x17c: 0x75, 0x17d: 0x0a, 0x17e: 0x0b, 0x17f: 0x0c, - // Block 0x6, offset 0x180 - 0x180: 0x76, 0x181: 0x77, 0x182: 0x78, 0x183: 0x79, 0x184: 0x0d, 0x185: 0x7a, 0x186: 0x7b, - 0x192: 0x7c, 0x193: 0x0e, - 0x1b0: 0x7d, 0x1b1: 0x0f, 0x1b2: 0x73, 0x1b3: 0x7e, 0x1b4: 0x7f, 0x1b5: 0x80, 0x1b6: 0x81, 0x1b7: 0x82, - 0x1b8: 0x83, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x84, 0x1c2: 0x85, 0x1c3: 0x86, 0x1c4: 0x87, 0x1c5: 0x24, 0x1c6: 0x88, - // Block 0x8, offset 0x200 - 0x200: 0x89, 0x201: 0x24, 0x202: 0x24, 0x203: 0x24, 0x204: 0x24, 0x205: 0x24, 0x206: 0x24, 0x207: 0x24, - 0x208: 0x24, 0x209: 0x24, 0x20a: 0x24, 0x20b: 0x24, 0x20c: 0x24, 0x20d: 0x24, 0x20e: 0x24, 0x20f: 0x24, - 0x210: 0x24, 0x211: 0x24, 0x212: 0x8a, 0x213: 0x8b, 0x214: 0x24, 0x215: 0x24, 0x216: 0x24, 0x217: 0x24, - 0x218: 0x8c, 0x219: 0x8d, 0x21a: 0x8e, 0x21b: 0x8f, 0x21c: 0x90, 0x21d: 0x91, 0x21e: 0x10, 0x21f: 0x92, - 0x220: 0x93, 0x221: 0x94, 0x222: 0x24, 0x223: 0x95, 0x224: 0x96, 0x225: 0x97, 0x226: 0x98, 0x227: 0x99, - 0x228: 0x9a, 0x229: 0x9b, 0x22a: 0x9c, 0x22b: 0x9d, 0x22c: 0x9e, 0x22d: 0x9f, 0x22e: 0xa0, 0x22f: 0xa1, - 0x230: 0x24, 0x231: 0x24, 0x232: 0x24, 0x233: 0x24, 0x234: 0x24, 0x235: 0x24, 0x236: 0x24, 0x237: 0x24, - 0x238: 0x24, 0x239: 0x24, 0x23a: 0x24, 0x23b: 0x24, 0x23c: 0x24, 0x23d: 0x24, 0x23e: 0x24, 0x23f: 0x24, - // Block 0x9, offset 0x240 - 0x240: 0x24, 0x241: 0x24, 0x242: 0x24, 0x243: 0x24, 0x244: 0x24, 0x245: 0x24, 0x246: 0x24, 0x247: 0x24, - 0x248: 0x24, 0x249: 0x24, 0x24a: 0x24, 0x24b: 0x24, 0x24c: 0x24, 0x24d: 0x24, 0x24e: 0x24, 0x24f: 0x24, - 0x250: 0x24, 0x251: 0x24, 0x252: 0x24, 0x253: 0x24, 0x254: 0x24, 0x255: 0x24, 0x256: 0x24, 0x257: 0x24, - 0x258: 0x24, 0x259: 0x24, 0x25a: 0x24, 0x25b: 0x24, 0x25c: 0x24, 0x25d: 0x24, 0x25e: 0x24, 0x25f: 0x24, - 0x260: 0x24, 0x261: 0x24, 0x262: 0x24, 0x263: 0x24, 0x264: 0x24, 0x265: 0x24, 0x266: 0x24, 0x267: 0x24, - 0x268: 0x24, 0x269: 0x24, 0x26a: 0x24, 0x26b: 0x24, 0x26c: 0x24, 0x26d: 0x24, 0x26e: 0x24, 0x26f: 0x24, - 0x270: 0x24, 0x271: 0x24, 0x272: 0x24, 0x273: 0x24, 0x274: 0x24, 0x275: 0x24, 0x276: 0x24, 0x277: 0x24, - 0x278: 0x24, 0x279: 0x24, 0x27a: 0x24, 0x27b: 0x24, 0x27c: 0x24, 0x27d: 0x24, 0x27e: 0x24, 0x27f: 0x24, - // Block 0xa, offset 0x280 - 0x280: 0x24, 0x281: 0x24, 0x282: 0x24, 0x283: 0x24, 0x284: 0x24, 0x285: 0x24, 0x286: 0x24, 0x287: 0x24, - 0x288: 0x24, 0x289: 0x24, 0x28a: 0x24, 0x28b: 0x24, 0x28c: 0x24, 0x28d: 0x24, 0x28e: 0x24, 0x28f: 0x24, - 0x290: 0x24, 0x291: 0x24, 0x292: 0x24, 0x293: 0x24, 0x294: 0x24, 0x295: 0x24, 0x296: 0x24, 0x297: 0x24, - 0x298: 0x24, 0x299: 0x24, 0x29a: 0x24, 0x29b: 0x24, 0x29c: 0x24, 0x29d: 0x24, 0x29e: 0xa2, 0x29f: 0xa3, - // Block 0xb, offset 0x2c0 - 0x2ec: 0x11, 0x2ed: 0xa4, 0x2ee: 0xa5, 0x2ef: 0xa6, - 0x2f0: 0x24, 0x2f1: 0x24, 0x2f2: 0x24, 0x2f3: 0x24, 0x2f4: 0xa7, 0x2f5: 0xa8, 0x2f6: 0xa9, 0x2f7: 0xaa, - 0x2f8: 0xab, 0x2f9: 0xac, 0x2fa: 0x24, 0x2fb: 0xad, 0x2fc: 0xae, 0x2fd: 0xaf, 0x2fe: 0xb0, 0x2ff: 0xb1, - // Block 0xc, offset 0x300 - 0x300: 0xb2, 0x301: 0xb3, 0x302: 0x24, 0x303: 0xb4, 0x305: 0xb5, 0x307: 0xb6, - 0x30a: 0xb7, 0x30b: 0xb8, 0x30c: 0xb9, 0x30d: 0xba, 0x30e: 0xbb, 0x30f: 0xbc, - 0x310: 0xbd, 0x311: 0xbe, 0x312: 0xbf, 0x313: 0xc0, 0x314: 0xc1, 0x315: 0xc2, - 0x318: 0x24, 0x319: 0x24, 0x31a: 0x24, 0x31b: 0x24, 0x31c: 0xc3, 0x31d: 0xc4, - 0x320: 0xc5, 0x321: 0xc6, 0x322: 0xc7, 0x323: 0xc8, 0x324: 0xc9, 0x326: 0xca, - 0x328: 0xcb, 0x329: 0xcc, 0x32a: 0xcd, 0x32b: 0xce, 0x32c: 0x5f, 0x32d: 0xcf, 0x32e: 0xd0, - 0x330: 0x24, 0x331: 0xd1, 0x332: 0xd2, 0x333: 0xd3, 0x334: 0xd4, - 0x33a: 0xd5, 0x33c: 0xd6, 0x33d: 0xd7, 0x33e: 0xd8, 0x33f: 0xd9, - // Block 0xd, offset 0x340 - 0x340: 0xda, 0x341: 0xdb, 0x342: 0xdc, 0x343: 0xdd, 0x344: 0xde, 0x345: 0xdf, 0x346: 0xe0, 0x347: 0xe1, - 0x348: 0xe2, 0x34a: 0xe3, 0x34b: 0xe4, 0x34c: 0xe5, 0x34d: 0xe6, - 0x350: 0xe7, 0x351: 0xe8, 0x352: 0xe9, 0x353: 0xea, 0x356: 0xeb, 0x357: 0xec, - 0x358: 0xed, 0x359: 0xee, 0x35a: 0xef, 0x35b: 0xf0, 0x35c: 0xf1, - 0x360: 0xf2, 0x362: 0xf3, 0x363: 0xf4, 0x364: 0xf5, 0x365: 0xf6, 0x366: 0xf7, 0x367: 0xf8, - 0x368: 0xf9, 0x369: 0xfa, 0x36a: 0xfb, 0x36b: 0xfc, - 0x370: 0xfd, 0x371: 0xfe, 0x372: 0xff, 0x374: 0x100, 0x375: 0x101, 0x376: 0x102, - 0x37b: 0x103, 0x37e: 0x104, - // Block 0xe, offset 0x380 - 0x380: 0x24, 0x381: 0x24, 0x382: 0x24, 0x383: 0x24, 0x384: 0x24, 0x385: 0x24, 0x386: 0x24, 0x387: 0x24, - 0x388: 0x24, 0x389: 0x24, 0x38a: 0x24, 0x38b: 0x24, 0x38c: 0x24, 0x38d: 0x24, 0x38e: 0x105, - 0x390: 0x24, 0x391: 0x106, 0x392: 0x24, 0x393: 0x24, 0x394: 0x24, 0x395: 0x107, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x24, 0x3c1: 0x24, 0x3c2: 0x24, 0x3c3: 0x24, 0x3c4: 0x24, 0x3c5: 0x24, 0x3c6: 0x24, 0x3c7: 0x24, - 0x3c8: 0x24, 0x3c9: 0x24, 0x3ca: 0x24, 0x3cb: 0x24, 0x3cc: 0x24, 0x3cd: 0x24, 0x3ce: 0x24, 0x3cf: 0x24, - 0x3d0: 0x108, - // Block 0x10, offset 0x400 - 0x410: 0x24, 0x411: 0x24, 0x412: 0x24, 0x413: 0x24, 0x414: 0x24, 0x415: 0x24, 0x416: 0x24, 0x417: 0x24, - 0x418: 0x24, 0x419: 0x109, - // Block 0x11, offset 0x440 - 0x460: 0x24, 0x461: 0x24, 0x462: 0x24, 0x463: 0x24, 0x464: 0x24, 0x465: 0x24, 0x466: 0x24, 0x467: 0x24, - 0x468: 0xfc, 0x469: 0x10a, 0x46b: 0x10b, 0x46c: 0x10c, 0x46d: 0x10d, 0x46e: 0x10e, - 0x479: 0x10f, 0x47c: 0x24, 0x47d: 0x110, 0x47e: 0x111, 0x47f: 0x112, - // Block 0x12, offset 0x480 - 0x4b0: 0x24, 0x4b1: 0x113, 0x4b2: 0x114, - // Block 0x13, offset 0x4c0 - 0x4c5: 0x115, 0x4c6: 0x116, - 0x4c9: 0x117, - 0x4d0: 0x118, 0x4d1: 0x119, 0x4d2: 0x11a, 0x4d3: 0x11b, 0x4d4: 0x11c, 0x4d5: 0x11d, 0x4d6: 0x11e, 0x4d7: 0x11f, - 0x4d8: 0x120, 0x4d9: 0x121, 0x4da: 0x122, 0x4db: 0x123, 0x4dc: 0x124, 0x4dd: 0x125, 0x4de: 0x126, 0x4df: 0x127, - 0x4e8: 0x128, 0x4e9: 0x129, 0x4ea: 0x12a, - // Block 0x14, offset 0x500 - 0x500: 0x12b, 0x504: 0x12c, 0x505: 0x12d, - 0x50b: 0x12e, - 0x520: 0x24, 0x521: 0x24, 0x522: 0x24, 0x523: 0x12f, 0x524: 0x12, 0x525: 0x130, - 0x538: 0x131, 0x539: 0x13, 0x53a: 0x132, - // Block 0x15, offset 0x540 - 0x544: 0x133, 0x545: 0x134, 0x546: 0x135, - 0x54f: 0x136, - 0x56f: 0x137, - // Block 0x16, offset 0x580 - 0x590: 0x0a, 0x591: 0x0b, 0x592: 0x0c, 0x593: 0x0d, 0x594: 0x0e, 0x596: 0x0f, - 0x59b: 0x10, 0x59d: 0x11, 0x59e: 0x12, 0x59f: 0x13, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x138, 0x5c1: 0x139, 0x5c4: 0x139, 0x5c5: 0x139, 0x5c6: 0x139, 0x5c7: 0x13a, - // Block 0x18, offset 0x600 - 0x620: 0x15, -} - -// sparseOffsets: 296 entries, 592 bytes -var sparseOffsets = []uint16{0x0, 0x9, 0xf, 0x18, 0x24, 0x2e, 0x34, 0x37, 0x3b, 0x3e, 0x42, 0x4c, 0x4e, 0x57, 0x5e, 0x63, 0x71, 0x72, 0x80, 0x8f, 0x99, 0x9c, 0xa3, 0xab, 0xae, 0xb0, 0xc0, 0xc6, 0xd4, 0xdf, 0xec, 0xf7, 0x103, 0x10d, 0x119, 0x124, 0x130, 0x13c, 0x144, 0x14d, 0x157, 0x162, 0x16e, 0x174, 0x17f, 0x185, 0x18d, 0x190, 0x195, 0x199, 0x19d, 0x1a4, 0x1ad, 0x1b5, 0x1b6, 0x1bf, 0x1c6, 0x1ce, 0x1d4, 0x1d9, 0x1dd, 0x1e0, 0x1e2, 0x1e5, 0x1ea, 0x1eb, 0x1ed, 0x1ef, 0x1f1, 0x1f8, 0x1fd, 0x201, 0x20a, 0x20d, 0x210, 0x216, 0x217, 0x222, 0x223, 0x224, 0x229, 0x236, 0x23f, 0x240, 0x248, 0x251, 0x25a, 0x263, 0x268, 0x26b, 0x276, 0x284, 0x286, 0x28d, 0x291, 0x29d, 0x29e, 0x2a9, 0x2b1, 0x2b9, 0x2bf, 0x2c0, 0x2ce, 0x2d3, 0x2d6, 0x2db, 0x2df, 0x2e5, 0x2ea, 0x2ed, 0x2f2, 0x2f7, 0x2f8, 0x2fe, 0x300, 0x301, 0x303, 0x305, 0x308, 0x309, 0x30b, 0x30e, 0x314, 0x318, 0x31a, 0x31f, 0x326, 0x331, 0x33b, 0x33c, 0x345, 0x349, 0x34e, 0x356, 0x35c, 0x362, 0x36c, 0x371, 0x37a, 0x380, 0x389, 0x38d, 0x395, 0x397, 0x399, 0x39c, 0x39e, 0x3a0, 0x3a1, 0x3a2, 0x3a4, 0x3a6, 0x3ac, 0x3b1, 0x3b3, 0x3ba, 0x3bd, 0x3bf, 0x3c5, 0x3ca, 0x3cc, 0x3cd, 0x3ce, 0x3cf, 0x3d1, 0x3d3, 0x3d5, 0x3d8, 0x3da, 0x3dd, 0x3e5, 0x3e8, 0x3ec, 0x3f4, 0x3f6, 0x3f7, 0x3f8, 0x3fa, 0x400, 0x402, 0x403, 0x405, 0x407, 0x409, 0x416, 0x417, 0x418, 0x41c, 0x41e, 0x41f, 0x420, 0x421, 0x422, 0x425, 0x428, 0x42b, 0x431, 0x432, 0x434, 0x438, 0x43c, 0x442, 0x445, 0x44c, 0x450, 0x454, 0x45d, 0x466, 0x46c, 0x472, 0x47c, 0x486, 0x488, 0x491, 0x497, 0x49d, 0x4a3, 0x4a6, 0x4ac, 0x4af, 0x4b8, 0x4b9, 0x4c0, 0x4c4, 0x4c5, 0x4c8, 0x4d2, 0x4d5, 0x4d7, 0x4de, 0x4e6, 0x4ec, 0x4f2, 0x4f3, 0x4f9, 0x4fc, 0x504, 0x50b, 0x515, 0x51d, 0x520, 0x521, 0x522, 0x523, 0x524, 0x526, 0x527, 0x529, 0x52b, 0x52d, 0x531, 0x532, 0x534, 0x537, 0x539, 0x53c, 0x53e, 0x543, 0x548, 0x54c, 0x54d, 0x550, 0x554, 0x55f, 0x563, 0x56b, 0x570, 0x574, 0x577, 0x57b, 0x57e, 0x581, 0x586, 0x58a, 0x58e, 0x592, 0x596, 0x598, 0x59a, 0x59d, 0x5a2, 0x5a5, 0x5a7, 0x5aa, 0x5ac, 0x5b2, 0x5bb, 0x5c0, 0x5c1, 0x5c4, 0x5c5, 0x5c6, 0x5c7, 0x5c9, 0x5ca, 0x5cb} - -// sparseValues: 1483 entries, 5932 bytes -var sparseValues = [1483]valueRange{ - // Block 0x0, offset 0x0 - {value: 0x0004, lo: 0xa8, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xaa}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0004, lo: 0xaf, hi: 0xaf}, - {value: 0x0004, lo: 0xb4, hi: 0xb4}, - {value: 0x001a, lo: 0xb5, hi: 0xb5}, - {value: 0x0054, lo: 0xb7, hi: 0xb7}, - {value: 0x0004, lo: 0xb8, hi: 0xb8}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - // Block 0x1, offset 0x9 - {value: 0x2013, lo: 0x80, hi: 0x96}, - {value: 0x2013, lo: 0x98, hi: 0x9e}, - {value: 0x009a, lo: 0x9f, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xb6}, - {value: 0x2012, lo: 0xb8, hi: 0xbe}, - {value: 0x0252, lo: 0xbf, hi: 0xbf}, - // Block 0x2, offset 0xf - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x011b, lo: 0xb0, hi: 0xb0}, - {value: 0x019a, lo: 0xb1, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb7}, - {value: 0x0012, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x0553, lo: 0xbf, hi: 0xbf}, - // Block 0x3, offset 0x18 - {value: 0x0552, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x01da, lo: 0x89, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xb7}, - {value: 0x0253, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x028a, lo: 0xbf, hi: 0xbf}, - // Block 0x4, offset 0x24 - {value: 0x0117, lo: 0x80, hi: 0x9f}, - {value: 0x2f53, lo: 0xa0, hi: 0xa0}, - {value: 0x0012, lo: 0xa1, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xb3}, - {value: 0x0012, lo: 0xb4, hi: 0xb9}, - {value: 0x090b, lo: 0xba, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x2953, lo: 0xbd, hi: 0xbd}, - {value: 0x098b, lo: 0xbe, hi: 0xbe}, - {value: 0x0a0a, lo: 0xbf, hi: 0xbf}, - // Block 0x5, offset 0x2e - {value: 0x0015, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x97}, - {value: 0x0004, lo: 0x98, hi: 0x9d}, - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0015, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xbf}, - // Block 0x6, offset 0x34 - {value: 0x0024, lo: 0x80, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbf}, - // Block 0x7, offset 0x37 - {value: 0x6553, lo: 0x80, hi: 0x8f}, - {value: 0x2013, lo: 0x90, hi: 0x9f}, - {value: 0x5f53, lo: 0xa0, hi: 0xaf}, - {value: 0x2012, lo: 0xb0, hi: 0xbf}, - // Block 0x8, offset 0x3b - {value: 0x5f52, lo: 0x80, hi: 0x8f}, - {value: 0x6552, lo: 0x90, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x9, offset 0x3e - {value: 0x0117, lo: 0x80, hi: 0x81}, - {value: 0x0024, lo: 0x83, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xbf}, - // Block 0xa, offset 0x42 - {value: 0x0f13, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0716, lo: 0x8b, hi: 0x8c}, - {value: 0x0316, lo: 0x8d, hi: 0x8e}, - {value: 0x0f12, lo: 0x8f, hi: 0x8f}, - {value: 0x0117, lo: 0x90, hi: 0xbf}, - // Block 0xb, offset 0x4c - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x6553, lo: 0xb1, hi: 0xbf}, - // Block 0xc, offset 0x4e - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6853, lo: 0x90, hi: 0x96}, - {value: 0x0014, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0054, lo: 0x9f, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa0}, - {value: 0x6552, lo: 0xa1, hi: 0xaf}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0xd, offset 0x57 - {value: 0x0034, lo: 0x81, hi: 0x82}, - {value: 0x0024, lo: 0x84, hi: 0x84}, - {value: 0x0034, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xaa}, - {value: 0x0010, lo: 0xaf, hi: 0xb3}, - {value: 0x0054, lo: 0xb4, hi: 0xb4}, - // Block 0xe, offset 0x5e - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0024, lo: 0x90, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0014, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xf, offset 0x63 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9c}, - {value: 0x0024, lo: 0x9d, hi: 0x9e}, - {value: 0x0034, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x10, offset 0x71 - {value: 0x0010, lo: 0x80, hi: 0xbf}, - // Block 0x11, offset 0x72 - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0024, lo: 0x9f, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x12, offset 0x80 - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0034, lo: 0xb1, hi: 0xb1}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0024, lo: 0xbf, hi: 0xbf}, - // Block 0x13, offset 0x8f - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0024, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x88}, - {value: 0x0024, lo: 0x89, hi: 0x8a}, - {value: 0x0010, lo: 0x8d, hi: 0xbf}, - // Block 0x14, offset 0x99 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x15, offset 0x9c - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xb1}, - {value: 0x0034, lo: 0xb2, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0x16, offset 0xa3 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x99}, - {value: 0x0014, lo: 0x9a, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0xa3}, - {value: 0x0014, lo: 0xa4, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xad}, - // Block 0x17, offset 0xab - {value: 0x0010, lo: 0x80, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0xa0, hi: 0xaa}, - // Block 0x18, offset 0xae - {value: 0x0010, lo: 0xa0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0x19, offset 0xb0 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0034, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0024, lo: 0xaa, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbf}, - // Block 0x1a, offset 0xc0 - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1b, offset 0xc6 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0x1c, offset 0xd4 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb6, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1d, offset 0xdf - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xb1}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - // Block 0x1e, offset 0xec - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x1f, offset 0xf7 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x99, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x20, offset 0x103 - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x21, offset 0x10d - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x85}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xbf}, - // Block 0x22, offset 0x119 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x23, offset 0x124 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x24, offset 0x130 - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0010, lo: 0xa8, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x25, offset 0x13c - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x26, offset 0x144 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb9}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbf}, - // Block 0x27, offset 0x14d - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x88}, - {value: 0x0014, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x28, offset 0x157 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x29, offset 0x162 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb2}, - // Block 0x2a, offset 0x16e - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x2b, offset 0x174 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x94, hi: 0x97}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xba, hi: 0xbf}, - // Block 0x2c, offset 0x17f - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x96}, - {value: 0x0010, lo: 0x9a, hi: 0xb1}, - {value: 0x0010, lo: 0xb3, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x2d, offset 0x185 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x94}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9f}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - // Block 0x2e, offset 0x18d - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - // Block 0x2f, offset 0x190 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x30, offset 0x195 - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - // Block 0x31, offset 0x199 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x32, offset 0x19d - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0034, lo: 0x98, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0034, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x33, offset 0x1a4 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xac}, - {value: 0x0034, lo: 0xb1, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xba, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x34, offset 0x1ad - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0024, lo: 0x82, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x86, hi: 0x87}, - {value: 0x0010, lo: 0x88, hi: 0x8c}, - {value: 0x0014, lo: 0x8d, hi: 0x97}, - {value: 0x0014, lo: 0x99, hi: 0xbc}, - // Block 0x35, offset 0x1b5 - {value: 0x0034, lo: 0x86, hi: 0x86}, - // Block 0x36, offset 0x1b6 - {value: 0x0010, lo: 0xab, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbe}, - // Block 0x37, offset 0x1bf - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x96, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x99}, - {value: 0x0014, lo: 0x9e, hi: 0xa0}, - {value: 0x0010, lo: 0xa2, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xad}, - {value: 0x0014, lo: 0xb1, hi: 0xb4}, - // Block 0x38, offset 0x1c6 - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x6c53, lo: 0xa0, hi: 0xbf}, - // Block 0x39, offset 0x1ce - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x9a, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x3a, offset 0x1d4 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x3b, offset 0x1d9 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x82, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3c, offset 0x1dd - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3d, offset 0x1e0 - {value: 0x0010, lo: 0x80, hi: 0x9a}, - {value: 0x0024, lo: 0x9d, hi: 0x9f}, - // Block 0x3e, offset 0x1e2 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x7453, lo: 0xa0, hi: 0xaf}, - {value: 0x7853, lo: 0xb0, hi: 0xbf}, - // Block 0x3f, offset 0x1e5 - {value: 0x7c53, lo: 0x80, hi: 0x8f}, - {value: 0x8053, lo: 0x90, hi: 0x9f}, - {value: 0x7c53, lo: 0xa0, hi: 0xaf}, - {value: 0x0813, lo: 0xb0, hi: 0xb5}, - {value: 0x0892, lo: 0xb8, hi: 0xbd}, - // Block 0x40, offset 0x1ea - {value: 0x0010, lo: 0x81, hi: 0xbf}, - // Block 0x41, offset 0x1eb - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0010, lo: 0xaf, hi: 0xbf}, - // Block 0x42, offset 0x1ed - {value: 0x0010, lo: 0x81, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x43, offset 0x1ef - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb8}, - // Block 0x44, offset 0x1f1 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0034, lo: 0x94, hi: 0x94}, - {value: 0x0010, lo: 0xa0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - // Block 0x45, offset 0x1f8 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xac}, - {value: 0x0010, lo: 0xae, hi: 0xb0}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - // Block 0x46, offset 0x1fd - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x47, offset 0x201 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x89, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0014, lo: 0x93, hi: 0x93}, - {value: 0x0004, lo: 0x97, hi: 0x97}, - {value: 0x0024, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0x48, offset 0x20a - {value: 0x0014, lo: 0x8b, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x49, offset 0x20d - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb8}, - // Block 0x4a, offset 0x210 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x4b, offset 0x216 - {value: 0x0010, lo: 0x80, hi: 0xb5}, - // Block 0x4c, offset 0x217 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbb}, - // Block 0x4d, offset 0x222 - {value: 0x0010, lo: 0x86, hi: 0x8f}, - // Block 0x4e, offset 0x223 - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x4f, offset 0x224 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - // Block 0x50, offset 0x229 - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x9e}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xac}, - {value: 0x0010, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xbc}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x51, offset 0x236 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xa7, hi: 0xa7}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - {value: 0x0034, lo: 0xb5, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbc}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x52, offset 0x23f - {value: 0x0034, lo: 0x80, hi: 0x80}, - // Block 0x53, offset 0x240 - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x54, offset 0x248 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0030, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xab, hi: 0xab}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - {value: 0x0024, lo: 0xad, hi: 0xb3}, - // Block 0x55, offset 0x251 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0030, lo: 0xaa, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbf}, - // Block 0x56, offset 0x25a - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0030, lo: 0xb2, hi: 0xb3}, - // Block 0x57, offset 0x263 - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0x58, offset 0x268 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8d, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x59, offset 0x26b - {value: 0x31ea, lo: 0x80, hi: 0x80}, - {value: 0x326a, lo: 0x81, hi: 0x81}, - {value: 0x32ea, lo: 0x82, hi: 0x82}, - {value: 0x336a, lo: 0x83, hi: 0x83}, - {value: 0x33ea, lo: 0x84, hi: 0x84}, - {value: 0x346a, lo: 0x85, hi: 0x85}, - {value: 0x34ea, lo: 0x86, hi: 0x86}, - {value: 0x356a, lo: 0x87, hi: 0x87}, - {value: 0x35ea, lo: 0x88, hi: 0x88}, - {value: 0x8353, lo: 0x90, hi: 0xba}, - {value: 0x8353, lo: 0xbd, hi: 0xbf}, - // Block 0x5a, offset 0x276 - {value: 0x0024, lo: 0x90, hi: 0x92}, - {value: 0x0034, lo: 0x94, hi: 0x99}, - {value: 0x0024, lo: 0x9a, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9f}, - {value: 0x0024, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xb3}, - {value: 0x0024, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb7}, - {value: 0x0024, lo: 0xb8, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xba}, - // Block 0x5b, offset 0x284 - {value: 0x0012, lo: 0x80, hi: 0xab}, - {value: 0x0015, lo: 0xac, hi: 0xbf}, - // Block 0x5c, offset 0x286 - {value: 0x0015, lo: 0x80, hi: 0xaa}, - {value: 0x0012, lo: 0xab, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb8}, - {value: 0x8752, lo: 0xb9, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbc}, - {value: 0x8b52, lo: 0xbd, hi: 0xbd}, - {value: 0x0012, lo: 0xbe, hi: 0xbf}, - // Block 0x5d, offset 0x28d - {value: 0x0012, lo: 0x80, hi: 0x8d}, - {value: 0x8f52, lo: 0x8e, hi: 0x8e}, - {value: 0x0012, lo: 0x8f, hi: 0x9a}, - {value: 0x0015, lo: 0x9b, hi: 0xbf}, - // Block 0x5e, offset 0x291 - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0024, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb9}, - {value: 0x0024, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbd}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x5f, offset 0x29d - {value: 0x0117, lo: 0x80, hi: 0xbf}, - // Block 0x60, offset 0x29e - {value: 0x0117, lo: 0x80, hi: 0x95}, - {value: 0x369a, lo: 0x96, hi: 0x96}, - {value: 0x374a, lo: 0x97, hi: 0x97}, - {value: 0x37fa, lo: 0x98, hi: 0x98}, - {value: 0x38aa, lo: 0x99, hi: 0x99}, - {value: 0x395a, lo: 0x9a, hi: 0x9a}, - {value: 0x3a0a, lo: 0x9b, hi: 0x9b}, - {value: 0x0012, lo: 0x9c, hi: 0x9d}, - {value: 0x3abb, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0x9f, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x61, offset 0x2a9 - {value: 0x0812, lo: 0x80, hi: 0x87}, - {value: 0x0813, lo: 0x88, hi: 0x8f}, - {value: 0x0812, lo: 0x90, hi: 0x95}, - {value: 0x0813, lo: 0x98, hi: 0x9d}, - {value: 0x0812, lo: 0xa0, hi: 0xa7}, - {value: 0x0813, lo: 0xa8, hi: 0xaf}, - {value: 0x0812, lo: 0xb0, hi: 0xb7}, - {value: 0x0813, lo: 0xb8, hi: 0xbf}, - // Block 0x62, offset 0x2b1 - {value: 0x0004, lo: 0x8b, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8f}, - {value: 0x0054, lo: 0x98, hi: 0x99}, - {value: 0x0054, lo: 0xa4, hi: 0xa4}, - {value: 0x0054, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xaa, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xaf}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x63, offset 0x2b9 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x94, hi: 0x94}, - {value: 0x0014, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa6, hi: 0xaf}, - {value: 0x0015, lo: 0xb1, hi: 0xb1}, - {value: 0x0015, lo: 0xbf, hi: 0xbf}, - // Block 0x64, offset 0x2bf - {value: 0x0015, lo: 0x90, hi: 0x9c}, - // Block 0x65, offset 0x2c0 - {value: 0x0024, lo: 0x90, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0xa0}, - {value: 0x0024, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa4}, - {value: 0x0034, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - // Block 0x66, offset 0x2ce - {value: 0x0016, lo: 0x85, hi: 0x86}, - {value: 0x0012, lo: 0x87, hi: 0x89}, - {value: 0xa452, lo: 0x8e, hi: 0x8e}, - {value: 0x1013, lo: 0xa0, hi: 0xaf}, - {value: 0x1012, lo: 0xb0, hi: 0xbf}, - // Block 0x67, offset 0x2d3 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x88}, - // Block 0x68, offset 0x2d6 - {value: 0xa753, lo: 0xb6, hi: 0xb7}, - {value: 0xaa53, lo: 0xb8, hi: 0xb9}, - {value: 0xad53, lo: 0xba, hi: 0xbb}, - {value: 0xaa53, lo: 0xbc, hi: 0xbd}, - {value: 0xa753, lo: 0xbe, hi: 0xbf}, - // Block 0x69, offset 0x2db - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6553, lo: 0x90, hi: 0x9f}, - {value: 0xb053, lo: 0xa0, hi: 0xae}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0x6a, offset 0x2df - {value: 0x0117, lo: 0x80, hi: 0xa3}, - {value: 0x0012, lo: 0xa4, hi: 0xa4}, - {value: 0x0716, lo: 0xab, hi: 0xac}, - {value: 0x0316, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb3}, - // Block 0x6b, offset 0x2e5 - {value: 0x6c52, lo: 0x80, hi: 0x9f}, - {value: 0x7052, lo: 0xa0, hi: 0xa5}, - {value: 0x7052, lo: 0xa7, hi: 0xa7}, - {value: 0x7052, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x6c, offset 0x2ea - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x6d, offset 0x2ed - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0010, lo: 0xb0, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x6e, offset 0x2f2 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9e}, - {value: 0x0024, lo: 0xa0, hi: 0xbf}, - // Block 0x6f, offset 0x2f7 - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - // Block 0x70, offset 0x2f8 - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0xaa, hi: 0xad}, - {value: 0x0030, lo: 0xae, hi: 0xaf}, - {value: 0x0004, lo: 0xb1, hi: 0xb5}, - {value: 0x0014, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - // Block 0x71, offset 0x2fe - {value: 0x0034, lo: 0x99, hi: 0x9a}, - {value: 0x0004, lo: 0x9b, hi: 0x9e}, - // Block 0x72, offset 0x300 - {value: 0x0004, lo: 0xbc, hi: 0xbe}, - // Block 0x73, offset 0x301 - {value: 0x0010, lo: 0x85, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x74, offset 0x303 - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x75, offset 0x305 - {value: 0x0010, lo: 0x80, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0xbf}, - // Block 0x76, offset 0x308 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - // Block 0x77, offset 0x309 - {value: 0x0010, lo: 0x90, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x78, offset 0x30b - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0xab}, - // Block 0x79, offset 0x30e - {value: 0x0117, lo: 0x80, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb2}, - {value: 0x0024, lo: 0xb4, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x7a, offset 0x314 - {value: 0x0117, lo: 0x80, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9d}, - {value: 0x0024, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x7b, offset 0x318 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb1}, - // Block 0x7c, offset 0x31a - {value: 0x0004, lo: 0x80, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xaf}, - {value: 0x0012, lo: 0xb0, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xbf}, - // Block 0x7d, offset 0x31f - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x0015, lo: 0xb0, hi: 0xb0}, - {value: 0x0012, lo: 0xb1, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x8753, lo: 0xbd, hi: 0xbd}, - {value: 0x0117, lo: 0xbe, hi: 0xbf}, - // Block 0x7e, offset 0x326 - {value: 0x0117, lo: 0x82, hi: 0x83}, - {value: 0x6553, lo: 0x84, hi: 0x84}, - {value: 0x908b, lo: 0x85, hi: 0x85}, - {value: 0x8f53, lo: 0x86, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0316, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbf}, - // Block 0x7f, offset 0x331 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x8c, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - // Block 0x80, offset 0x33b - {value: 0x0010, lo: 0x80, hi: 0xb3}, - // Block 0x81, offset 0x33c - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xa0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb7}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x82, offset 0x345 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x83, offset 0x349 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0x92}, - {value: 0x0030, lo: 0x93, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0x84, offset 0x34e - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x85, offset 0x356 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0004, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x86, offset 0x35c - {value: 0x0010, lo: 0x80, hi: 0xa8}, - {value: 0x0014, lo: 0xa9, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0x87, offset 0x362 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x88, offset 0x36c - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0024, lo: 0xbe, hi: 0xbf}, - // Block 0x89, offset 0x371 - {value: 0x0024, lo: 0x81, hi: 0x81}, - {value: 0x0004, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - // Block 0x8a, offset 0x37a - {value: 0x0010, lo: 0x81, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x8e}, - {value: 0x0010, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x8b, offset 0x380 - {value: 0x0012, lo: 0x80, hi: 0x92}, - {value: 0xb352, lo: 0x93, hi: 0x93}, - {value: 0x0012, lo: 0x94, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa8}, - {value: 0x0014, lo: 0xa9, hi: 0xa9}, - {value: 0x0004, lo: 0xaa, hi: 0xab}, - {value: 0x74d2, lo: 0xb0, hi: 0xbf}, - // Block 0x8c, offset 0x389 - {value: 0x78d2, lo: 0x80, hi: 0x8f}, - {value: 0x7cd2, lo: 0x90, hi: 0x9f}, - {value: 0x80d2, lo: 0xa0, hi: 0xaf}, - {value: 0x7cd2, lo: 0xb0, hi: 0xbf}, - // Block 0x8d, offset 0x38d - {value: 0x0010, lo: 0x80, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x8e, offset 0x395 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x8f, offset 0x397 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x8b, hi: 0xbb}, - // Block 0x90, offset 0x399 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0xbf}, - // Block 0x91, offset 0x39c - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0004, lo: 0xb2, hi: 0xbf}, - // Block 0x92, offset 0x39e - {value: 0x0004, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x93, hi: 0xbf}, - // Block 0x93, offset 0x3a0 - {value: 0x0010, lo: 0x80, hi: 0xbd}, - // Block 0x94, offset 0x3a1 - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0x95, offset 0x3a2 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0xbf}, - // Block 0x96, offset 0x3a4 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0xb0, hi: 0xbb}, - // Block 0x97, offset 0x3a6 - {value: 0x0014, lo: 0x80, hi: 0x8f}, - {value: 0x0054, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0xa0, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xad}, - {value: 0x0024, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - // Block 0x98, offset 0x3ac - {value: 0x0010, lo: 0x8d, hi: 0x8f}, - {value: 0x0054, lo: 0x92, hi: 0x92}, - {value: 0x0054, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0xb0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0x99, offset 0x3b1 - {value: 0x0010, lo: 0x80, hi: 0xbc}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x9a, offset 0x3b3 - {value: 0x0054, lo: 0x87, hi: 0x87}, - {value: 0x0054, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0054, lo: 0x9a, hi: 0x9a}, - {value: 0x5f53, lo: 0xa1, hi: 0xba}, - {value: 0x0004, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9b, offset 0x3ba - {value: 0x0004, lo: 0x80, hi: 0x80}, - {value: 0x5f52, lo: 0x81, hi: 0x9a}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - // Block 0x9c, offset 0x3bd - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbe}, - // Block 0x9d, offset 0x3bf - {value: 0x0010, lo: 0x82, hi: 0x87}, - {value: 0x0010, lo: 0x8a, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0x97}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0004, lo: 0xa3, hi: 0xa3}, - {value: 0x0014, lo: 0xb9, hi: 0xbb}, - // Block 0x9e, offset 0x3c5 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0010, lo: 0x8d, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xba}, - {value: 0x0010, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9f, offset 0x3ca - {value: 0x0010, lo: 0x80, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x9d}, - // Block 0xa0, offset 0x3cc - {value: 0x0010, lo: 0x80, hi: 0xba}, - // Block 0xa1, offset 0x3cd - {value: 0x0010, lo: 0x80, hi: 0xb4}, - // Block 0xa2, offset 0x3ce - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0xa3, offset 0x3cf - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa4, offset 0x3d1 - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - // Block 0xa5, offset 0x3d3 - {value: 0x0010, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xad, hi: 0xbf}, - // Block 0xa6, offset 0x3d5 - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0xb5}, - {value: 0x0024, lo: 0xb6, hi: 0xba}, - // Block 0xa7, offset 0x3d8 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa8, offset 0x3da - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x91, hi: 0x95}, - // Block 0xa9, offset 0x3dd - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x97}, - {value: 0xb653, lo: 0x98, hi: 0x9f}, - {value: 0xb953, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbf}, - // Block 0xaa, offset 0x3e5 - {value: 0xb652, lo: 0x80, hi: 0x87}, - {value: 0xb952, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xab, offset 0x3e8 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0xb953, lo: 0xb0, hi: 0xb7}, - {value: 0xb653, lo: 0xb8, hi: 0xbf}, - // Block 0xac, offset 0x3ec - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x93}, - {value: 0xb952, lo: 0x98, hi: 0x9f}, - {value: 0xb652, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbb}, - // Block 0xad, offset 0x3f4 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xae, offset 0x3f6 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - // Block 0xaf, offset 0x3f7 - {value: 0x0010, lo: 0x80, hi: 0xb6}, - // Block 0xb0, offset 0x3f8 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - // Block 0xb1, offset 0x3fa - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xb2, offset 0x400 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xb3, offset 0x402 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - // Block 0xb4, offset 0x403 - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - // Block 0xb5, offset 0x405 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb9}, - // Block 0xb6, offset 0x407 - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0xb7, offset 0x409 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x8e, hi: 0x8e}, - {value: 0x0024, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x99, hi: 0xb5}, - {value: 0x0024, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xb8, offset 0x416 - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0xb9, offset 0x417 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - // Block 0xba, offset 0x418 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - // Block 0xbb, offset 0x41c - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - // Block 0xbc, offset 0x41e - {value: 0x0010, lo: 0x80, hi: 0x91}, - // Block 0xbd, offset 0x41f - {value: 0x0010, lo: 0x80, hi: 0x88}, - // Block 0xbe, offset 0x420 - {value: 0x5653, lo: 0x80, hi: 0xb2}, - // Block 0xbf, offset 0x421 - {value: 0x5652, lo: 0x80, hi: 0xb2}, - // Block 0xc0, offset 0x422 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc1, offset 0x425 - {value: 0x0010, lo: 0x80, hi: 0xa9}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - // Block 0xc2, offset 0x428 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xc3, offset 0x42b - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x87}, - {value: 0x0024, lo: 0x88, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x8b}, - {value: 0x0024, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - // Block 0xc4, offset 0x431 - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xc5, offset 0x432 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xc6, offset 0x434 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xc7, offset 0x438 - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xc8, offset 0x43c - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - // Block 0xc9, offset 0x442 - {value: 0x0014, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xca, offset 0x445 - {value: 0x0024, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0xcb, offset 0x44c - {value: 0x0010, lo: 0x84, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - // Block 0xcc, offset 0x450 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xcd, offset 0x454 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x89, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - // Block 0xce, offset 0x45d - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb4}, - {value: 0x0030, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xb7}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0xcf, offset 0x466 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xd0, offset 0x46c - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa2}, - {value: 0x0014, lo: 0xa3, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xd1, offset 0x472 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xd2, offset 0x47c - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0030, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9d, hi: 0xa3}, - {value: 0x0024, lo: 0xa6, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - // Block 0xd3, offset 0x486 - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xd4, offset 0x488 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - // Block 0xd5, offset 0x491 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xd6, offset 0x497 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd7, offset 0x49d - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd8, offset 0x4a3 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x98, hi: 0x9b}, - {value: 0x0014, lo: 0x9c, hi: 0x9d}, - // Block 0xd9, offset 0x4a6 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xda, offset 0x4ac - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xdb, offset 0x4af - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0014, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb5}, - {value: 0x0030, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - // Block 0xdc, offset 0x4b8 - {value: 0x0010, lo: 0x80, hi: 0x89}, - // Block 0xdd, offset 0x4b9 - {value: 0x0014, lo: 0x9d, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xde, offset 0x4c0 - {value: 0x0010, lo: 0x80, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - // Block 0xdf, offset 0x4c4 - {value: 0x5f53, lo: 0xa0, hi: 0xbf}, - // Block 0xe0, offset 0x4c5 - {value: 0x5f52, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xe1, offset 0x4c8 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8c, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - {value: 0x0030, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xe2, offset 0x4d2 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0034, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xe3, offset 0x4d5 - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - {value: 0x0010, lo: 0xaa, hi: 0xbf}, - // Block 0xe4, offset 0x4d7 - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0014, lo: 0x94, hi: 0x97}, - {value: 0x0014, lo: 0x9a, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0x9f}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - // Block 0xe5, offset 0x4de - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x8a}, - {value: 0x0010, lo: 0x8b, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbe}, - // Block 0xe6, offset 0x4e6 - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0014, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x98}, - {value: 0x0014, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0xbf}, - // Block 0xe7, offset 0x4ec - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0014, lo: 0x8a, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9d, hi: 0x9d}, - // Block 0xe8, offset 0x4f2 - {value: 0x0010, lo: 0x80, hi: 0xb8}, - // Block 0xe9, offset 0x4f3 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xea, offset 0x4f9 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0xeb, offset 0x4fc - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0014, lo: 0x92, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xa9}, - {value: 0x0014, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0xec, offset 0x504 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb6}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xed, offset 0x50b - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa5}, - {value: 0x0010, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xbf}, - // Block 0xee, offset 0x515 - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0014, lo: 0x90, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0x96}, - {value: 0x0034, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xef, offset 0x51d - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - // Block 0xf0, offset 0x520 - {value: 0x0010, lo: 0xb0, hi: 0xb0}, - // Block 0xf1, offset 0x521 - {value: 0x0010, lo: 0x80, hi: 0x99}, - // Block 0xf2, offset 0x522 - {value: 0x0010, lo: 0x80, hi: 0xae}, - // Block 0xf3, offset 0x523 - {value: 0x0010, lo: 0x80, hi: 0x83}, - // Block 0xf4, offset 0x524 - {value: 0x0010, lo: 0x80, hi: 0xae}, - {value: 0x0014, lo: 0xb0, hi: 0xb8}, - // Block 0xf5, offset 0x526 - {value: 0x0010, lo: 0x80, hi: 0x86}, - // Block 0xf6, offset 0x527 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xf7, offset 0x529 - {value: 0x0010, lo: 0x90, hi: 0xad}, - {value: 0x0034, lo: 0xb0, hi: 0xb4}, - // Block 0xf8, offset 0x52b - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - // Block 0xf9, offset 0x52d - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa3, hi: 0xb7}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xfa, offset 0x531 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - // Block 0xfb, offset 0x532 - {value: 0x2013, lo: 0x80, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xbf}, - // Block 0xfc, offset 0x534 - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xfd, offset 0x537 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0014, lo: 0x8f, hi: 0x9f}, - // Block 0xfe, offset 0x539 - {value: 0x0014, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa3, hi: 0xa4}, - {value: 0x0030, lo: 0xb0, hi: 0xb1}, - // Block 0xff, offset 0x53c - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbc}, - // Block 0x100, offset 0x53e - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0034, lo: 0x9e, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa3}, - // Block 0x101, offset 0x543 - {value: 0x0030, lo: 0xa5, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xa9}, - {value: 0x0030, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbf}, - // Block 0x102, offset 0x548 - {value: 0x0034, lo: 0x80, hi: 0x82}, - {value: 0x0024, lo: 0x85, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8b}, - {value: 0x0024, lo: 0xaa, hi: 0xad}, - // Block 0x103, offset 0x54c - {value: 0x0024, lo: 0x82, hi: 0x84}, - // Block 0x104, offset 0x54d - {value: 0x0013, lo: 0x80, hi: 0x99}, - {value: 0x0012, lo: 0x9a, hi: 0xb3}, - {value: 0x0013, lo: 0xb4, hi: 0xbf}, - // Block 0x105, offset 0x550 - {value: 0x0013, lo: 0x80, hi: 0x8d}, - {value: 0x0012, lo: 0x8e, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0xa7}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x106, offset 0x554 - {value: 0x0013, lo: 0x80, hi: 0x81}, - {value: 0x0012, lo: 0x82, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0x9c}, - {value: 0x0013, lo: 0x9e, hi: 0x9f}, - {value: 0x0013, lo: 0xa2, hi: 0xa2}, - {value: 0x0013, lo: 0xa5, hi: 0xa6}, - {value: 0x0013, lo: 0xa9, hi: 0xac}, - {value: 0x0013, lo: 0xae, hi: 0xb5}, - {value: 0x0012, lo: 0xb6, hi: 0xb9}, - {value: 0x0012, lo: 0xbb, hi: 0xbb}, - {value: 0x0012, lo: 0xbd, hi: 0xbf}, - // Block 0x107, offset 0x55f - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0012, lo: 0x85, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x108, offset 0x563 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0013, lo: 0x84, hi: 0x85}, - {value: 0x0013, lo: 0x87, hi: 0x8a}, - {value: 0x0013, lo: 0x8d, hi: 0x94}, - {value: 0x0013, lo: 0x96, hi: 0x9c}, - {value: 0x0012, lo: 0x9e, hi: 0xb7}, - {value: 0x0013, lo: 0xb8, hi: 0xb9}, - {value: 0x0013, lo: 0xbb, hi: 0xbe}, - // Block 0x109, offset 0x56b - {value: 0x0013, lo: 0x80, hi: 0x84}, - {value: 0x0013, lo: 0x86, hi: 0x86}, - {value: 0x0013, lo: 0x8a, hi: 0x90}, - {value: 0x0012, lo: 0x92, hi: 0xab}, - {value: 0x0013, lo: 0xac, hi: 0xbf}, - // Block 0x10a, offset 0x570 - {value: 0x0013, lo: 0x80, hi: 0x85}, - {value: 0x0012, lo: 0x86, hi: 0x9f}, - {value: 0x0013, lo: 0xa0, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbf}, - // Block 0x10b, offset 0x574 - {value: 0x0012, lo: 0x80, hi: 0x93}, - {value: 0x0013, lo: 0x94, hi: 0xad}, - {value: 0x0012, lo: 0xae, hi: 0xbf}, - // Block 0x10c, offset 0x577 - {value: 0x0012, lo: 0x80, hi: 0x87}, - {value: 0x0013, lo: 0x88, hi: 0xa1}, - {value: 0x0012, lo: 0xa2, hi: 0xbb}, - {value: 0x0013, lo: 0xbc, hi: 0xbf}, - // Block 0x10d, offset 0x57b - {value: 0x0013, lo: 0x80, hi: 0x95}, - {value: 0x0012, lo: 0x96, hi: 0xaf}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x10e, offset 0x57e - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0012, lo: 0x8a, hi: 0xa5}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x10f, offset 0x581 - {value: 0x0013, lo: 0x80, hi: 0x80}, - {value: 0x0012, lo: 0x82, hi: 0x9a}, - {value: 0x0012, lo: 0x9c, hi: 0xa1}, - {value: 0x0013, lo: 0xa2, hi: 0xba}, - {value: 0x0012, lo: 0xbc, hi: 0xbf}, - // Block 0x110, offset 0x586 - {value: 0x0012, lo: 0x80, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0xb4}, - {value: 0x0012, lo: 0xb6, hi: 0xbf}, - // Block 0x111, offset 0x58a - {value: 0x0012, lo: 0x80, hi: 0x8e}, - {value: 0x0012, lo: 0x90, hi: 0x95}, - {value: 0x0013, lo: 0x96, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x112, offset 0x58e - {value: 0x0012, lo: 0x80, hi: 0x88}, - {value: 0x0012, lo: 0x8a, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x113, offset 0x592 - {value: 0x0012, lo: 0x80, hi: 0x82}, - {value: 0x0012, lo: 0x84, hi: 0x89}, - {value: 0x0017, lo: 0x8a, hi: 0x8b}, - {value: 0x0010, lo: 0x8e, hi: 0xbf}, - // Block 0x114, offset 0x596 - {value: 0x0014, lo: 0x80, hi: 0xb6}, - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x115, offset 0x598 - {value: 0x0014, lo: 0x80, hi: 0xac}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x116, offset 0x59a - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x9b, hi: 0x9f}, - {value: 0x0014, lo: 0xa1, hi: 0xaf}, - // Block 0x117, offset 0x59d - {value: 0x0024, lo: 0x80, hi: 0x86}, - {value: 0x0024, lo: 0x88, hi: 0x98}, - {value: 0x0024, lo: 0x9b, hi: 0xa1}, - {value: 0x0024, lo: 0xa3, hi: 0xa4}, - {value: 0x0024, lo: 0xa6, hi: 0xaa}, - // Block 0x118, offset 0x5a2 - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - // Block 0x119, offset 0x5a5 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - // Block 0x11a, offset 0x5a7 - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0024, lo: 0xac, hi: 0xaf}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x11b, offset 0x5aa - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0034, lo: 0x90, hi: 0x96}, - // Block 0x11c, offset 0x5ac - {value: 0xbc52, lo: 0x80, hi: 0x81}, - {value: 0xbf52, lo: 0x82, hi: 0x83}, - {value: 0x0024, lo: 0x84, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x11d, offset 0x5b2 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x9f}, - {value: 0x0010, lo: 0xa1, hi: 0xa2}, - {value: 0x0010, lo: 0xa4, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb7}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - // Block 0x11e, offset 0x5bb - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x9b}, - {value: 0x0010, lo: 0xa1, hi: 0xa3}, - {value: 0x0010, lo: 0xa5, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xbb}, - // Block 0x11f, offset 0x5c0 - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x120, offset 0x5c1 - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x121, offset 0x5c4 - {value: 0x0013, lo: 0x80, hi: 0x89}, - // Block 0x122, offset 0x5c5 - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x123, offset 0x5c6 - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x124, offset 0x5c7 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0014, lo: 0xa0, hi: 0xbf}, - // Block 0x125, offset 0x5c9 - {value: 0x0014, lo: 0x80, hi: 0xbf}, - // Block 0x126, offset 0x5ca - {value: 0x0014, lo: 0x80, hi: 0xaf}, -} - -// Total table size 15212 bytes (14KiB); checksum: 1EB13752 diff --git a/vendor/golang.org/x/text/cases/tables15.0.0.go b/vendor/golang.org/x/text/cases/tables15.0.0.go deleted file mode 100644 index aee0f310..00000000 --- a/vendor/golang.org/x/text/cases/tables15.0.0.go +++ /dev/null @@ -1,2527 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -//go:build go1.21 - -package cases - -// UnicodeVersion is the Unicode version from which the tables in this package are derived. -const UnicodeVersion = "15.0.0" - -var xorData string = "" + // Size: 213 bytes - "\x00\x06\x07\x00\x01?\x00\x0f\x03\x00\x0f\x12\x00\x0f\x1f\x00\x0f\x1d" + - "\x00\x01\x13\x00\x0f\x16\x00\x0f\x0b\x00\x0f3\x00\x0f7\x00\x01#\x00\x0f?" + - "\x00\x0e'\x00\x0f/\x00\x0e>\x00\x0f*\x00\x0c&\x00\x0c*\x00\x0c;\x00\x0c9" + - "\x00\x0c%\x00\x01\x08\x00\x03\x0d\x00\x03\x09\x00\x02\x06\x00\x02\x02" + - "\x00\x02\x0c\x00\x01\x00\x00\x01\x03\x00\x01\x01\x00\x01 \x00\x01\x0c" + - "\x00\x01\x10\x00\x03\x10\x00\x036 \x00\x037 \x00\x0b#\x10\x00\x0b 0\x00" + - "\x0b!\x10\x00\x0b!0\x001\x00\x00\x0b(\x04\x00\x03\x04\x1e\x00\x0b)\x08" + - "\x00\x03\x0a\x00\x02:\x00\x02>\x00\x02,\x00\x02\x00\x00\x02\x10\x00\x01<" + - "\x00\x01&\x00\x01*\x00\x01.\x00\x010\x003 \x00\x01\x18\x00\x01(\x00\x03'" + - "\x00\x03)\x00\x03+\x00\x03/\x00\x03\x19\x00\x03\x1b\x00\x03\x1f\x00\x01" + - "\x1e\x00\x01\x22" - -var exceptions string = "" + // Size: 2450 bytes - "\x00\x12\x12μΜΜ\x12\x12ssSSSs\x13\x18i̇i̇\x10\x09II\x13\x1bʼnʼNʼN\x11" + - "\x09sSS\x12\x12dždžDž\x12\x12dždžDŽ\x10\x12DŽDž\x12\x12ljljLj\x12\x12ljljLJ\x10\x12LJLj" + - "\x12\x12njnjNj\x12\x12njnjNJ\x10\x12NJNj\x13\x1bǰJ̌J̌\x12\x12dzdzDz\x12\x12dzdzDZ\x10" + - "\x12DZDz\x13\x18ⱥⱥ\x13\x18ⱦⱦ\x10\x1bⱾⱾ\x10\x1bⱿⱿ\x10\x1bⱯⱯ\x10\x1bⱭⱭ\x10" + - "\x1bⱰⱰ\x10\x1bꞫꞫ\x10\x1bꞬꞬ\x10\x1bꞍꞍ\x10\x1bꞪꞪ\x10\x1bꞮꞮ\x10\x1bⱢⱢ\x10" + - "\x1bꞭꞭ\x10\x1bⱮⱮ\x10\x1bⱤⱤ\x10\x1bꟅꟅ\x10\x1bꞱꞱ\x10\x1bꞲꞲ\x10\x1bꞰꞰ2\x12ι" + - "ΙΙ\x166ΐΪ́Ϊ́\x166ΰΫ́Ϋ́\x12\x12σΣΣ\x12\x12βΒΒ\x12\x12θΘΘ\x12\x12" + - "φΦΦ\x12\x12πΠΠ\x12\x12κΚΚ\x12\x12ρΡΡ\x12\x12εΕΕ\x14$եւԵՒԵւ\x10\x1bᲐა" + - "\x10\x1bᲑბ\x10\x1bᲒგ\x10\x1bᲓდ\x10\x1bᲔე\x10\x1bᲕვ\x10\x1bᲖზ\x10\x1bᲗთ" + - "\x10\x1bᲘი\x10\x1bᲙკ\x10\x1bᲚლ\x10\x1bᲛმ\x10\x1bᲜნ\x10\x1bᲝო\x10\x1bᲞპ" + - "\x10\x1bᲟჟ\x10\x1bᲠრ\x10\x1bᲡს\x10\x1bᲢტ\x10\x1bᲣუ\x10\x1bᲤფ\x10\x1bᲥქ" + - "\x10\x1bᲦღ\x10\x1bᲧყ\x10\x1bᲨშ\x10\x1bᲩჩ\x10\x1bᲪც\x10\x1bᲫძ\x10\x1bᲬწ" + - "\x10\x1bᲭჭ\x10\x1bᲮხ\x10\x1bᲯჯ\x10\x1bᲰჰ\x10\x1bᲱჱ\x10\x1bᲲჲ\x10\x1bᲳჳ" + - "\x10\x1bᲴჴ\x10\x1bᲵჵ\x10\x1bᲶჶ\x10\x1bᲷჷ\x10\x1bᲸჸ\x10\x1bᲹჹ\x10\x1bᲺჺ" + - "\x10\x1bᲽჽ\x10\x1bᲾჾ\x10\x1bᲿჿ\x12\x12вВВ\x12\x12дДД\x12\x12оОО\x12\x12с" + - "СС\x12\x12тТТ\x12\x12тТТ\x12\x12ъЪЪ\x12\x12ѣѢѢ\x13\x1bꙋꙊꙊ\x13\x1bẖH̱H̱" + - "\x13\x1bẗT̈T̈\x13\x1bẘW̊W̊\x13\x1bẙY̊Y̊\x13\x1baʾAʾAʾ\x13\x1bṡṠṠ\x12" + - "\x10ssß\x14$ὐΥ̓Υ̓\x166ὒΥ̓̀Υ̓̀\x166ὔΥ̓́Υ̓́\x166ὖΥ̓͂Υ̓͂\x15+ἀιἈΙᾈ" + - "\x15+ἁιἉΙᾉ\x15+ἂιἊΙᾊ\x15+ἃιἋΙᾋ\x15+ἄιἌΙᾌ\x15+ἅιἍΙᾍ\x15+ἆιἎΙᾎ\x15+ἇιἏΙᾏ" + - "\x15\x1dἀιᾀἈΙ\x15\x1dἁιᾁἉΙ\x15\x1dἂιᾂἊΙ\x15\x1dἃιᾃἋΙ\x15\x1dἄιᾄἌΙ\x15" + - "\x1dἅιᾅἍΙ\x15\x1dἆιᾆἎΙ\x15\x1dἇιᾇἏΙ\x15+ἠιἨΙᾘ\x15+ἡιἩΙᾙ\x15+ἢιἪΙᾚ\x15+ἣι" + - "ἫΙᾛ\x15+ἤιἬΙᾜ\x15+ἥιἭΙᾝ\x15+ἦιἮΙᾞ\x15+ἧιἯΙᾟ\x15\x1dἠιᾐἨΙ\x15\x1dἡιᾑἩΙ" + - "\x15\x1dἢιᾒἪΙ\x15\x1dἣιᾓἫΙ\x15\x1dἤιᾔἬΙ\x15\x1dἥιᾕἭΙ\x15\x1dἦιᾖἮΙ\x15" + - "\x1dἧιᾗἯΙ\x15+ὠιὨΙᾨ\x15+ὡιὩΙᾩ\x15+ὢιὪΙᾪ\x15+ὣιὫΙᾫ\x15+ὤιὬΙᾬ\x15+ὥιὭΙᾭ" + - "\x15+ὦιὮΙᾮ\x15+ὧιὯΙᾯ\x15\x1dὠιᾠὨΙ\x15\x1dὡιᾡὩΙ\x15\x1dὢιᾢὪΙ\x15\x1dὣιᾣὫΙ" + - "\x15\x1dὤιᾤὬΙ\x15\x1dὥιᾥὭΙ\x15\x1dὦιᾦὮΙ\x15\x1dὧιᾧὯΙ\x15-ὰιᾺΙᾺͅ\x14#αιΑΙ" + - "ᾼ\x14$άιΆΙΆͅ\x14$ᾶΑ͂Α͂\x166ᾶιΑ͂Ιᾼ͂\x14\x1cαιᾳΑΙ\x12\x12ιΙΙ\x15-ὴιῊΙ" + - "Ὴͅ\x14#ηιΗΙῌ\x14$ήιΉΙΉͅ\x14$ῆΗ͂Η͂\x166ῆιΗ͂Ιῌ͂\x14\x1cηιῃΗΙ\x166ῒΙ" + - "̈̀Ϊ̀\x166ΐΪ́Ϊ́\x14$ῖΙ͂Ι͂\x166ῗΪ͂Ϊ͂\x166ῢΫ̀Ϋ̀\x166ΰΫ́Ϋ" + - "́\x14$ῤΡ̓Ρ̓\x14$ῦΥ͂Υ͂\x166ῧΫ͂Ϋ͂\x15-ὼιῺΙῺͅ\x14#ωιΩΙῼ\x14$ώιΏΙΏͅ" + - "\x14$ῶΩ͂Ω͂\x166ῶιΩ͂Ιῼ͂\x14\x1cωιῳΩΙ\x12\x10ωω\x11\x08kk\x12\x10åå\x12" + - "\x10ɫɫ\x12\x10ɽɽ\x10\x12ȺȺ\x10\x12ȾȾ\x12\x10ɑɑ\x12\x10ɱɱ\x12\x10ɐɐ\x12" + - "\x10ɒɒ\x12\x10ȿȿ\x12\x10ɀɀ\x12\x10ɥɥ\x12\x10ɦɦ\x12\x10ɜɜ\x12\x10ɡɡ\x12" + - "\x10ɬɬ\x12\x10ɪɪ\x12\x10ʞʞ\x12\x10ʇʇ\x12\x10ʝʝ\x12\x10ʂʂ\x12\x12ffFFFf" + - "\x12\x12fiFIFi\x12\x12flFLFl\x13\x1bffiFFIFfi\x13\x1bfflFFLFfl\x12\x12st" + - "STSt\x12\x12stSTSt\x14$մնՄՆՄն\x14$մեՄԵՄե\x14$միՄԻՄի\x14$վնՎՆՎն\x14$մխՄԽՄ" + - "խ" - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookup(s []byte) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupUnsafe(s []byte) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookupString(s string) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupStringUnsafe(s string) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// caseTrie. Total size: 13398 bytes (13.08 KiB). Checksum: 544af6e6b1b70931. -type caseTrie struct{} - -func newCaseTrie(i int) *caseTrie { - return &caseTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *caseTrie) lookupValue(n uint32, b byte) uint16 { - switch { - case n < 22: - return uint16(caseValues[n<<6+uint32(b)]) - default: - n -= 22 - return uint16(sparse.lookup(n, b)) - } -} - -// caseValues: 24 blocks, 1536 entries, 3072 bytes -// The third block is the zero block. -var caseValues = [1536]uint16{ - // Block 0x0, offset 0x0 - 0x27: 0x0054, - 0x2e: 0x0054, - 0x30: 0x0010, 0x31: 0x0010, 0x32: 0x0010, 0x33: 0x0010, 0x34: 0x0010, 0x35: 0x0010, - 0x36: 0x0010, 0x37: 0x0010, 0x38: 0x0010, 0x39: 0x0010, 0x3a: 0x0054, - // Block 0x1, offset 0x40 - 0x41: 0x2013, 0x42: 0x2013, 0x43: 0x2013, 0x44: 0x2013, 0x45: 0x2013, - 0x46: 0x2013, 0x47: 0x2013, 0x48: 0x2013, 0x49: 0x2013, 0x4a: 0x2013, 0x4b: 0x2013, - 0x4c: 0x2013, 0x4d: 0x2013, 0x4e: 0x2013, 0x4f: 0x2013, 0x50: 0x2013, 0x51: 0x2013, - 0x52: 0x2013, 0x53: 0x2013, 0x54: 0x2013, 0x55: 0x2013, 0x56: 0x2013, 0x57: 0x2013, - 0x58: 0x2013, 0x59: 0x2013, 0x5a: 0x2013, - 0x5e: 0x0004, 0x5f: 0x0010, 0x60: 0x0004, 0x61: 0x2012, 0x62: 0x2012, 0x63: 0x2012, - 0x64: 0x2012, 0x65: 0x2012, 0x66: 0x2012, 0x67: 0x2012, 0x68: 0x2012, 0x69: 0x2012, - 0x6a: 0x2012, 0x6b: 0x2012, 0x6c: 0x2012, 0x6d: 0x2012, 0x6e: 0x2012, 0x6f: 0x2012, - 0x70: 0x2012, 0x71: 0x2012, 0x72: 0x2012, 0x73: 0x2012, 0x74: 0x2012, 0x75: 0x2012, - 0x76: 0x2012, 0x77: 0x2012, 0x78: 0x2012, 0x79: 0x2012, 0x7a: 0x2012, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x0852, 0xc1: 0x0b53, 0xc2: 0x0113, 0xc3: 0x0112, 0xc4: 0x0113, 0xc5: 0x0112, - 0xc6: 0x0b53, 0xc7: 0x0f13, 0xc8: 0x0f12, 0xc9: 0x0e53, 0xca: 0x1153, 0xcb: 0x0713, - 0xcc: 0x0712, 0xcd: 0x0012, 0xce: 0x1453, 0xcf: 0x1753, 0xd0: 0x1a53, 0xd1: 0x0313, - 0xd2: 0x0312, 0xd3: 0x1d53, 0xd4: 0x2053, 0xd5: 0x2352, 0xd6: 0x2653, 0xd7: 0x2653, - 0xd8: 0x0113, 0xd9: 0x0112, 0xda: 0x2952, 0xdb: 0x0012, 0xdc: 0x1d53, 0xdd: 0x2c53, - 0xde: 0x2f52, 0xdf: 0x3253, 0xe0: 0x0113, 0xe1: 0x0112, 0xe2: 0x0113, 0xe3: 0x0112, - 0xe4: 0x0113, 0xe5: 0x0112, 0xe6: 0x3553, 0xe7: 0x0f13, 0xe8: 0x0f12, 0xe9: 0x3853, - 0xea: 0x0012, 0xeb: 0x0012, 0xec: 0x0113, 0xed: 0x0112, 0xee: 0x3553, 0xef: 0x1f13, - 0xf0: 0x1f12, 0xf1: 0x3b53, 0xf2: 0x3e53, 0xf3: 0x0713, 0xf4: 0x0712, 0xf5: 0x0313, - 0xf6: 0x0312, 0xf7: 0x4153, 0xf8: 0x0113, 0xf9: 0x0112, 0xfa: 0x0012, 0xfb: 0x0010, - 0xfc: 0x0113, 0xfd: 0x0112, 0xfe: 0x0012, 0xff: 0x4452, - // Block 0x4, offset 0x100 - 0x100: 0x0010, 0x101: 0x0010, 0x102: 0x0010, 0x103: 0x0010, 0x104: 0x02db, 0x105: 0x0359, - 0x106: 0x03da, 0x107: 0x043b, 0x108: 0x04b9, 0x109: 0x053a, 0x10a: 0x059b, 0x10b: 0x0619, - 0x10c: 0x069a, 0x10d: 0x0313, 0x10e: 0x0312, 0x10f: 0x1f13, 0x110: 0x1f12, 0x111: 0x0313, - 0x112: 0x0312, 0x113: 0x0713, 0x114: 0x0712, 0x115: 0x0313, 0x116: 0x0312, 0x117: 0x0f13, - 0x118: 0x0f12, 0x119: 0x0313, 0x11a: 0x0312, 0x11b: 0x0713, 0x11c: 0x0712, 0x11d: 0x1452, - 0x11e: 0x0113, 0x11f: 0x0112, 0x120: 0x0113, 0x121: 0x0112, 0x122: 0x0113, 0x123: 0x0112, - 0x124: 0x0113, 0x125: 0x0112, 0x126: 0x0113, 0x127: 0x0112, 0x128: 0x0113, 0x129: 0x0112, - 0x12a: 0x0113, 0x12b: 0x0112, 0x12c: 0x0113, 0x12d: 0x0112, 0x12e: 0x0113, 0x12f: 0x0112, - 0x130: 0x06fa, 0x131: 0x07ab, 0x132: 0x0829, 0x133: 0x08aa, 0x134: 0x0113, 0x135: 0x0112, - 0x136: 0x2353, 0x137: 0x4453, 0x138: 0x0113, 0x139: 0x0112, 0x13a: 0x0113, 0x13b: 0x0112, - 0x13c: 0x0113, 0x13d: 0x0112, 0x13e: 0x0113, 0x13f: 0x0112, - // Block 0x5, offset 0x140 - 0x140: 0x0a8a, 0x141: 0x0313, 0x142: 0x0312, 0x143: 0x0853, 0x144: 0x4753, 0x145: 0x4a53, - 0x146: 0x0113, 0x147: 0x0112, 0x148: 0x0113, 0x149: 0x0112, 0x14a: 0x0113, 0x14b: 0x0112, - 0x14c: 0x0113, 0x14d: 0x0112, 0x14e: 0x0113, 0x14f: 0x0112, 0x150: 0x0b0a, 0x151: 0x0b8a, - 0x152: 0x0c0a, 0x153: 0x0b52, 0x154: 0x0b52, 0x155: 0x0012, 0x156: 0x0e52, 0x157: 0x1152, - 0x158: 0x0012, 0x159: 0x1752, 0x15a: 0x0012, 0x15b: 0x1a52, 0x15c: 0x0c8a, 0x15d: 0x0012, - 0x15e: 0x0012, 0x15f: 0x0012, 0x160: 0x1d52, 0x161: 0x0d0a, 0x162: 0x0012, 0x163: 0x2052, - 0x164: 0x0012, 0x165: 0x0d8a, 0x166: 0x0e0a, 0x167: 0x0012, 0x168: 0x2652, 0x169: 0x2652, - 0x16a: 0x0e8a, 0x16b: 0x0f0a, 0x16c: 0x0f8a, 0x16d: 0x0012, 0x16e: 0x0012, 0x16f: 0x1d52, - 0x170: 0x0012, 0x171: 0x100a, 0x172: 0x2c52, 0x173: 0x0012, 0x174: 0x0012, 0x175: 0x3252, - 0x176: 0x0012, 0x177: 0x0012, 0x178: 0x0012, 0x179: 0x0012, 0x17a: 0x0012, 0x17b: 0x0012, - 0x17c: 0x0012, 0x17d: 0x108a, 0x17e: 0x0012, 0x17f: 0x0012, - // Block 0x6, offset 0x180 - 0x180: 0x3552, 0x181: 0x0012, 0x182: 0x110a, 0x183: 0x3852, 0x184: 0x0012, 0x185: 0x0012, - 0x186: 0x0012, 0x187: 0x118a, 0x188: 0x3552, 0x189: 0x4752, 0x18a: 0x3b52, 0x18b: 0x3e52, - 0x18c: 0x4a52, 0x18d: 0x0012, 0x18e: 0x0012, 0x18f: 0x0012, 0x190: 0x0012, 0x191: 0x0012, - 0x192: 0x4152, 0x193: 0x0012, 0x194: 0x0010, 0x195: 0x0012, 0x196: 0x0012, 0x197: 0x0012, - 0x198: 0x0012, 0x199: 0x0012, 0x19a: 0x0012, 0x19b: 0x0012, 0x19c: 0x0012, 0x19d: 0x120a, - 0x19e: 0x128a, 0x19f: 0x0012, 0x1a0: 0x0012, 0x1a1: 0x0012, 0x1a2: 0x0012, 0x1a3: 0x0012, - 0x1a4: 0x0012, 0x1a5: 0x0012, 0x1a6: 0x0012, 0x1a7: 0x0012, 0x1a8: 0x0012, 0x1a9: 0x0012, - 0x1aa: 0x0012, 0x1ab: 0x0012, 0x1ac: 0x0012, 0x1ad: 0x0012, 0x1ae: 0x0012, 0x1af: 0x0012, - 0x1b0: 0x0015, 0x1b1: 0x0015, 0x1b2: 0x0015, 0x1b3: 0x0015, 0x1b4: 0x0015, 0x1b5: 0x0015, - 0x1b6: 0x0015, 0x1b7: 0x0015, 0x1b8: 0x0015, 0x1b9: 0x0014, 0x1ba: 0x0014, 0x1bb: 0x0014, - 0x1bc: 0x0014, 0x1bd: 0x0014, 0x1be: 0x0014, 0x1bf: 0x0014, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x0024, 0x1c1: 0x0024, 0x1c2: 0x0024, 0x1c3: 0x0024, 0x1c4: 0x0024, 0x1c5: 0x130d, - 0x1c6: 0x0024, 0x1c7: 0x0034, 0x1c8: 0x0034, 0x1c9: 0x0034, 0x1ca: 0x0024, 0x1cb: 0x0024, - 0x1cc: 0x0024, 0x1cd: 0x0034, 0x1ce: 0x0034, 0x1cf: 0x0014, 0x1d0: 0x0024, 0x1d1: 0x0024, - 0x1d2: 0x0024, 0x1d3: 0x0034, 0x1d4: 0x0034, 0x1d5: 0x0034, 0x1d6: 0x0034, 0x1d7: 0x0024, - 0x1d8: 0x0034, 0x1d9: 0x0034, 0x1da: 0x0034, 0x1db: 0x0024, 0x1dc: 0x0034, 0x1dd: 0x0034, - 0x1de: 0x0034, 0x1df: 0x0034, 0x1e0: 0x0034, 0x1e1: 0x0034, 0x1e2: 0x0034, 0x1e3: 0x0024, - 0x1e4: 0x0024, 0x1e5: 0x0024, 0x1e6: 0x0024, 0x1e7: 0x0024, 0x1e8: 0x0024, 0x1e9: 0x0024, - 0x1ea: 0x0024, 0x1eb: 0x0024, 0x1ec: 0x0024, 0x1ed: 0x0024, 0x1ee: 0x0024, 0x1ef: 0x0024, - 0x1f0: 0x0113, 0x1f1: 0x0112, 0x1f2: 0x0113, 0x1f3: 0x0112, 0x1f4: 0x0014, 0x1f5: 0x0004, - 0x1f6: 0x0113, 0x1f7: 0x0112, 0x1fa: 0x0015, 0x1fb: 0x4d52, - 0x1fc: 0x5052, 0x1fd: 0x5052, 0x1ff: 0x5353, - // Block 0x8, offset 0x200 - 0x204: 0x0004, 0x205: 0x0004, - 0x206: 0x2a13, 0x207: 0x0054, 0x208: 0x2513, 0x209: 0x2713, 0x20a: 0x2513, - 0x20c: 0x5653, 0x20e: 0x5953, 0x20f: 0x5c53, 0x210: 0x138a, 0x211: 0x2013, - 0x212: 0x2013, 0x213: 0x2013, 0x214: 0x2013, 0x215: 0x2013, 0x216: 0x2013, 0x217: 0x2013, - 0x218: 0x2013, 0x219: 0x2013, 0x21a: 0x2013, 0x21b: 0x2013, 0x21c: 0x2013, 0x21d: 0x2013, - 0x21e: 0x2013, 0x21f: 0x2013, 0x220: 0x5f53, 0x221: 0x5f53, 0x223: 0x5f53, - 0x224: 0x5f53, 0x225: 0x5f53, 0x226: 0x5f53, 0x227: 0x5f53, 0x228: 0x5f53, 0x229: 0x5f53, - 0x22a: 0x5f53, 0x22b: 0x5f53, 0x22c: 0x2a12, 0x22d: 0x2512, 0x22e: 0x2712, 0x22f: 0x2512, - 0x230: 0x14ca, 0x231: 0x2012, 0x232: 0x2012, 0x233: 0x2012, 0x234: 0x2012, 0x235: 0x2012, - 0x236: 0x2012, 0x237: 0x2012, 0x238: 0x2012, 0x239: 0x2012, 0x23a: 0x2012, 0x23b: 0x2012, - 0x23c: 0x2012, 0x23d: 0x2012, 0x23e: 0x2012, 0x23f: 0x2012, - // Block 0x9, offset 0x240 - 0x240: 0x5f52, 0x241: 0x5f52, 0x242: 0x160a, 0x243: 0x5f52, 0x244: 0x5f52, 0x245: 0x5f52, - 0x246: 0x5f52, 0x247: 0x5f52, 0x248: 0x5f52, 0x249: 0x5f52, 0x24a: 0x5f52, 0x24b: 0x5f52, - 0x24c: 0x5652, 0x24d: 0x5952, 0x24e: 0x5c52, 0x24f: 0x1813, 0x250: 0x168a, 0x251: 0x170a, - 0x252: 0x0013, 0x253: 0x0013, 0x254: 0x0013, 0x255: 0x178a, 0x256: 0x180a, 0x257: 0x1812, - 0x258: 0x0113, 0x259: 0x0112, 0x25a: 0x0113, 0x25b: 0x0112, 0x25c: 0x0113, 0x25d: 0x0112, - 0x25e: 0x0113, 0x25f: 0x0112, 0x260: 0x0113, 0x261: 0x0112, 0x262: 0x0113, 0x263: 0x0112, - 0x264: 0x0113, 0x265: 0x0112, 0x266: 0x0113, 0x267: 0x0112, 0x268: 0x0113, 0x269: 0x0112, - 0x26a: 0x0113, 0x26b: 0x0112, 0x26c: 0x0113, 0x26d: 0x0112, 0x26e: 0x0113, 0x26f: 0x0112, - 0x270: 0x188a, 0x271: 0x190a, 0x272: 0x0b12, 0x273: 0x5352, 0x274: 0x6253, 0x275: 0x198a, - 0x277: 0x0f13, 0x278: 0x0f12, 0x279: 0x0b13, 0x27a: 0x0113, 0x27b: 0x0112, - 0x27c: 0x0012, 0x27d: 0x4d53, 0x27e: 0x5053, 0x27f: 0x5053, - // Block 0xa, offset 0x280 - 0x280: 0x6852, 0x281: 0x6852, 0x282: 0x6852, 0x283: 0x6852, 0x284: 0x6852, 0x285: 0x6852, - 0x286: 0x6852, 0x287: 0x1a0a, 0x288: 0x0012, 0x28a: 0x0010, - 0x291: 0x0034, - 0x292: 0x0024, 0x293: 0x0024, 0x294: 0x0024, 0x295: 0x0024, 0x296: 0x0034, 0x297: 0x0024, - 0x298: 0x0024, 0x299: 0x0024, 0x29a: 0x0034, 0x29b: 0x0034, 0x29c: 0x0024, 0x29d: 0x0024, - 0x29e: 0x0024, 0x29f: 0x0024, 0x2a0: 0x0024, 0x2a1: 0x0024, 0x2a2: 0x0034, 0x2a3: 0x0034, - 0x2a4: 0x0034, 0x2a5: 0x0034, 0x2a6: 0x0034, 0x2a7: 0x0034, 0x2a8: 0x0024, 0x2a9: 0x0024, - 0x2aa: 0x0034, 0x2ab: 0x0024, 0x2ac: 0x0024, 0x2ad: 0x0034, 0x2ae: 0x0034, 0x2af: 0x0024, - 0x2b0: 0x0034, 0x2b1: 0x0034, 0x2b2: 0x0034, 0x2b3: 0x0034, 0x2b4: 0x0034, 0x2b5: 0x0034, - 0x2b6: 0x0034, 0x2b7: 0x0034, 0x2b8: 0x0034, 0x2b9: 0x0034, 0x2ba: 0x0034, 0x2bb: 0x0034, - 0x2bc: 0x0034, 0x2bd: 0x0034, 0x2bf: 0x0034, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x0010, 0x2c1: 0x0010, 0x2c2: 0x0010, 0x2c3: 0x0010, 0x2c4: 0x0010, 0x2c5: 0x0010, - 0x2c6: 0x0010, 0x2c7: 0x0010, 0x2c8: 0x0010, 0x2c9: 0x0014, 0x2ca: 0x0024, 0x2cb: 0x0024, - 0x2cc: 0x0024, 0x2cd: 0x0024, 0x2ce: 0x0024, 0x2cf: 0x0034, 0x2d0: 0x0034, 0x2d1: 0x0034, - 0x2d2: 0x0034, 0x2d3: 0x0034, 0x2d4: 0x0024, 0x2d5: 0x0024, 0x2d6: 0x0024, 0x2d7: 0x0024, - 0x2d8: 0x0024, 0x2d9: 0x0024, 0x2da: 0x0024, 0x2db: 0x0024, 0x2dc: 0x0024, 0x2dd: 0x0024, - 0x2de: 0x0024, 0x2df: 0x0024, 0x2e0: 0x0024, 0x2e1: 0x0024, 0x2e2: 0x0014, 0x2e3: 0x0034, - 0x2e4: 0x0024, 0x2e5: 0x0024, 0x2e6: 0x0034, 0x2e7: 0x0024, 0x2e8: 0x0024, 0x2e9: 0x0034, - 0x2ea: 0x0024, 0x2eb: 0x0024, 0x2ec: 0x0024, 0x2ed: 0x0034, 0x2ee: 0x0034, 0x2ef: 0x0034, - 0x2f0: 0x0034, 0x2f1: 0x0034, 0x2f2: 0x0034, 0x2f3: 0x0024, 0x2f4: 0x0024, 0x2f5: 0x0024, - 0x2f6: 0x0034, 0x2f7: 0x0024, 0x2f8: 0x0024, 0x2f9: 0x0034, 0x2fa: 0x0034, 0x2fb: 0x0024, - 0x2fc: 0x0024, 0x2fd: 0x0024, 0x2fe: 0x0024, 0x2ff: 0x0024, - // Block 0xc, offset 0x300 - 0x300: 0x7053, 0x301: 0x7053, 0x302: 0x7053, 0x303: 0x7053, 0x304: 0x7053, 0x305: 0x7053, - 0x307: 0x7053, - 0x30d: 0x7053, 0x310: 0x1aea, 0x311: 0x1b6a, - 0x312: 0x1bea, 0x313: 0x1c6a, 0x314: 0x1cea, 0x315: 0x1d6a, 0x316: 0x1dea, 0x317: 0x1e6a, - 0x318: 0x1eea, 0x319: 0x1f6a, 0x31a: 0x1fea, 0x31b: 0x206a, 0x31c: 0x20ea, 0x31d: 0x216a, - 0x31e: 0x21ea, 0x31f: 0x226a, 0x320: 0x22ea, 0x321: 0x236a, 0x322: 0x23ea, 0x323: 0x246a, - 0x324: 0x24ea, 0x325: 0x256a, 0x326: 0x25ea, 0x327: 0x266a, 0x328: 0x26ea, 0x329: 0x276a, - 0x32a: 0x27ea, 0x32b: 0x286a, 0x32c: 0x28ea, 0x32d: 0x296a, 0x32e: 0x29ea, 0x32f: 0x2a6a, - 0x330: 0x2aea, 0x331: 0x2b6a, 0x332: 0x2bea, 0x333: 0x2c6a, 0x334: 0x2cea, 0x335: 0x2d6a, - 0x336: 0x2dea, 0x337: 0x2e6a, 0x338: 0x2eea, 0x339: 0x2f6a, 0x33a: 0x2fea, - 0x33c: 0x0015, 0x33d: 0x306a, 0x33e: 0x30ea, 0x33f: 0x316a, - // Block 0xd, offset 0x340 - 0x340: 0x0812, 0x341: 0x0812, 0x342: 0x0812, 0x343: 0x0812, 0x344: 0x0812, 0x345: 0x0812, - 0x348: 0x0813, 0x349: 0x0813, 0x34a: 0x0813, 0x34b: 0x0813, - 0x34c: 0x0813, 0x34d: 0x0813, 0x350: 0x3b1a, 0x351: 0x0812, - 0x352: 0x3bfa, 0x353: 0x0812, 0x354: 0x3d3a, 0x355: 0x0812, 0x356: 0x3e7a, 0x357: 0x0812, - 0x359: 0x0813, 0x35b: 0x0813, 0x35d: 0x0813, - 0x35f: 0x0813, 0x360: 0x0812, 0x361: 0x0812, 0x362: 0x0812, 0x363: 0x0812, - 0x364: 0x0812, 0x365: 0x0812, 0x366: 0x0812, 0x367: 0x0812, 0x368: 0x0813, 0x369: 0x0813, - 0x36a: 0x0813, 0x36b: 0x0813, 0x36c: 0x0813, 0x36d: 0x0813, 0x36e: 0x0813, 0x36f: 0x0813, - 0x370: 0x9252, 0x371: 0x9252, 0x372: 0x9552, 0x373: 0x9552, 0x374: 0x9852, 0x375: 0x9852, - 0x376: 0x9b52, 0x377: 0x9b52, 0x378: 0x9e52, 0x379: 0x9e52, 0x37a: 0xa152, 0x37b: 0xa152, - 0x37c: 0x4d52, 0x37d: 0x4d52, - // Block 0xe, offset 0x380 - 0x380: 0x3fba, 0x381: 0x40aa, 0x382: 0x419a, 0x383: 0x428a, 0x384: 0x437a, 0x385: 0x446a, - 0x386: 0x455a, 0x387: 0x464a, 0x388: 0x4739, 0x389: 0x4829, 0x38a: 0x4919, 0x38b: 0x4a09, - 0x38c: 0x4af9, 0x38d: 0x4be9, 0x38e: 0x4cd9, 0x38f: 0x4dc9, 0x390: 0x4eba, 0x391: 0x4faa, - 0x392: 0x509a, 0x393: 0x518a, 0x394: 0x527a, 0x395: 0x536a, 0x396: 0x545a, 0x397: 0x554a, - 0x398: 0x5639, 0x399: 0x5729, 0x39a: 0x5819, 0x39b: 0x5909, 0x39c: 0x59f9, 0x39d: 0x5ae9, - 0x39e: 0x5bd9, 0x39f: 0x5cc9, 0x3a0: 0x5dba, 0x3a1: 0x5eaa, 0x3a2: 0x5f9a, 0x3a3: 0x608a, - 0x3a4: 0x617a, 0x3a5: 0x626a, 0x3a6: 0x635a, 0x3a7: 0x644a, 0x3a8: 0x6539, 0x3a9: 0x6629, - 0x3aa: 0x6719, 0x3ab: 0x6809, 0x3ac: 0x68f9, 0x3ad: 0x69e9, 0x3ae: 0x6ad9, 0x3af: 0x6bc9, - 0x3b0: 0x0812, 0x3b1: 0x0812, 0x3b2: 0x6cba, 0x3b3: 0x6dca, 0x3b4: 0x6e9a, - 0x3b6: 0x6f7a, 0x3b7: 0x705a, 0x3b8: 0x0813, 0x3b9: 0x0813, 0x3ba: 0x9253, 0x3bb: 0x9253, - 0x3bc: 0x7199, 0x3bd: 0x0004, 0x3be: 0x726a, 0x3bf: 0x0004, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x0004, 0x3c1: 0x0004, 0x3c2: 0x72ea, 0x3c3: 0x73fa, 0x3c4: 0x74ca, - 0x3c6: 0x75aa, 0x3c7: 0x768a, 0x3c8: 0x9553, 0x3c9: 0x9553, 0x3ca: 0x9853, 0x3cb: 0x9853, - 0x3cc: 0x77c9, 0x3cd: 0x0004, 0x3ce: 0x0004, 0x3cf: 0x0004, 0x3d0: 0x0812, 0x3d1: 0x0812, - 0x3d2: 0x789a, 0x3d3: 0x79da, 0x3d6: 0x7b1a, 0x3d7: 0x7bfa, - 0x3d8: 0x0813, 0x3d9: 0x0813, 0x3da: 0x9b53, 0x3db: 0x9b53, 0x3dd: 0x0004, - 0x3de: 0x0004, 0x3df: 0x0004, 0x3e0: 0x0812, 0x3e1: 0x0812, 0x3e2: 0x7d3a, 0x3e3: 0x7e7a, - 0x3e4: 0x7fba, 0x3e5: 0x0912, 0x3e6: 0x809a, 0x3e7: 0x817a, 0x3e8: 0x0813, 0x3e9: 0x0813, - 0x3ea: 0xa153, 0x3eb: 0xa153, 0x3ec: 0x0913, 0x3ed: 0x0004, 0x3ee: 0x0004, 0x3ef: 0x0004, - 0x3f2: 0x82ba, 0x3f3: 0x83ca, 0x3f4: 0x849a, - 0x3f6: 0x857a, 0x3f7: 0x865a, 0x3f8: 0x9e53, 0x3f9: 0x9e53, 0x3fa: 0x4d53, 0x3fb: 0x4d53, - 0x3fc: 0x8799, 0x3fd: 0x0004, 0x3fe: 0x0004, - // Block 0x10, offset 0x400 - 0x402: 0x0013, - 0x407: 0x0013, 0x40a: 0x0012, 0x40b: 0x0013, - 0x40c: 0x0013, 0x40d: 0x0013, 0x40e: 0x0012, 0x40f: 0x0012, 0x410: 0x0013, 0x411: 0x0013, - 0x412: 0x0013, 0x413: 0x0012, 0x415: 0x0013, - 0x419: 0x0013, 0x41a: 0x0013, 0x41b: 0x0013, 0x41c: 0x0013, 0x41d: 0x0013, - 0x424: 0x0013, 0x426: 0x886b, 0x428: 0x0013, - 0x42a: 0x88cb, 0x42b: 0x890b, 0x42c: 0x0013, 0x42d: 0x0013, 0x42f: 0x0012, - 0x430: 0x0013, 0x431: 0x0013, 0x432: 0xa453, 0x433: 0x0013, 0x434: 0x0012, 0x435: 0x0010, - 0x436: 0x0010, 0x437: 0x0010, 0x438: 0x0010, 0x439: 0x0012, - 0x43c: 0x0012, 0x43d: 0x0012, 0x43e: 0x0013, 0x43f: 0x0013, - // Block 0x11, offset 0x440 - 0x440: 0x1a13, 0x441: 0x1a13, 0x442: 0x1e13, 0x443: 0x1e13, 0x444: 0x1a13, 0x445: 0x1a13, - 0x446: 0x2613, 0x447: 0x2613, 0x448: 0x2a13, 0x449: 0x2a13, 0x44a: 0x2e13, 0x44b: 0x2e13, - 0x44c: 0x2a13, 0x44d: 0x2a13, 0x44e: 0x2613, 0x44f: 0x2613, 0x450: 0xa752, 0x451: 0xa752, - 0x452: 0xaa52, 0x453: 0xaa52, 0x454: 0xad52, 0x455: 0xad52, 0x456: 0xaa52, 0x457: 0xaa52, - 0x458: 0xa752, 0x459: 0xa752, 0x45a: 0x1a12, 0x45b: 0x1a12, 0x45c: 0x1e12, 0x45d: 0x1e12, - 0x45e: 0x1a12, 0x45f: 0x1a12, 0x460: 0x2612, 0x461: 0x2612, 0x462: 0x2a12, 0x463: 0x2a12, - 0x464: 0x2e12, 0x465: 0x2e12, 0x466: 0x2a12, 0x467: 0x2a12, 0x468: 0x2612, 0x469: 0x2612, - // Block 0x12, offset 0x480 - 0x480: 0x6552, 0x481: 0x6552, 0x482: 0x6552, 0x483: 0x6552, 0x484: 0x6552, 0x485: 0x6552, - 0x486: 0x6552, 0x487: 0x6552, 0x488: 0x6552, 0x489: 0x6552, 0x48a: 0x6552, 0x48b: 0x6552, - 0x48c: 0x6552, 0x48d: 0x6552, 0x48e: 0x6552, 0x48f: 0x6552, 0x490: 0xb052, 0x491: 0xb052, - 0x492: 0xb052, 0x493: 0xb052, 0x494: 0xb052, 0x495: 0xb052, 0x496: 0xb052, 0x497: 0xb052, - 0x498: 0xb052, 0x499: 0xb052, 0x49a: 0xb052, 0x49b: 0xb052, 0x49c: 0xb052, 0x49d: 0xb052, - 0x49e: 0xb052, 0x49f: 0xb052, 0x4a0: 0x0113, 0x4a1: 0x0112, 0x4a2: 0x896b, 0x4a3: 0x8b53, - 0x4a4: 0x89cb, 0x4a5: 0x8a2a, 0x4a6: 0x8a8a, 0x4a7: 0x0f13, 0x4a8: 0x0f12, 0x4a9: 0x0313, - 0x4aa: 0x0312, 0x4ab: 0x0713, 0x4ac: 0x0712, 0x4ad: 0x8aeb, 0x4ae: 0x8b4b, 0x4af: 0x8bab, - 0x4b0: 0x8c0b, 0x4b1: 0x0012, 0x4b2: 0x0113, 0x4b3: 0x0112, 0x4b4: 0x0012, 0x4b5: 0x0313, - 0x4b6: 0x0312, 0x4b7: 0x0012, 0x4b8: 0x0012, 0x4b9: 0x0012, 0x4ba: 0x0012, 0x4bb: 0x0012, - 0x4bc: 0x0015, 0x4bd: 0x0015, 0x4be: 0x8c6b, 0x4bf: 0x8ccb, - // Block 0x13, offset 0x4c0 - 0x4c0: 0x0113, 0x4c1: 0x0112, 0x4c2: 0x0113, 0x4c3: 0x0112, 0x4c4: 0x0113, 0x4c5: 0x0112, - 0x4c6: 0x0113, 0x4c7: 0x0112, 0x4c8: 0x0014, 0x4c9: 0x0014, 0x4ca: 0x0014, 0x4cb: 0x0713, - 0x4cc: 0x0712, 0x4cd: 0x8d2b, 0x4ce: 0x0012, 0x4cf: 0x0010, 0x4d0: 0x0113, 0x4d1: 0x0112, - 0x4d2: 0x0113, 0x4d3: 0x0112, 0x4d4: 0x6552, 0x4d5: 0x0012, 0x4d6: 0x0113, 0x4d7: 0x0112, - 0x4d8: 0x0113, 0x4d9: 0x0112, 0x4da: 0x0113, 0x4db: 0x0112, 0x4dc: 0x0113, 0x4dd: 0x0112, - 0x4de: 0x0113, 0x4df: 0x0112, 0x4e0: 0x0113, 0x4e1: 0x0112, 0x4e2: 0x0113, 0x4e3: 0x0112, - 0x4e4: 0x0113, 0x4e5: 0x0112, 0x4e6: 0x0113, 0x4e7: 0x0112, 0x4e8: 0x0113, 0x4e9: 0x0112, - 0x4ea: 0x8d8b, 0x4eb: 0x8deb, 0x4ec: 0x8e4b, 0x4ed: 0x8eab, 0x4ee: 0x8f0b, 0x4ef: 0x0012, - 0x4f0: 0x8f6b, 0x4f1: 0x8fcb, 0x4f2: 0x902b, 0x4f3: 0xb353, 0x4f4: 0x0113, 0x4f5: 0x0112, - 0x4f6: 0x0113, 0x4f7: 0x0112, 0x4f8: 0x0113, 0x4f9: 0x0112, 0x4fa: 0x0113, 0x4fb: 0x0112, - 0x4fc: 0x0113, 0x4fd: 0x0112, 0x4fe: 0x0113, 0x4ff: 0x0112, - // Block 0x14, offset 0x500 - 0x500: 0x90ea, 0x501: 0x916a, 0x502: 0x91ea, 0x503: 0x926a, 0x504: 0x931a, 0x505: 0x93ca, - 0x506: 0x944a, - 0x513: 0x94ca, 0x514: 0x95aa, 0x515: 0x968a, 0x516: 0x976a, 0x517: 0x984a, - 0x51d: 0x0010, - 0x51e: 0x0034, 0x51f: 0x0010, 0x520: 0x0010, 0x521: 0x0010, 0x522: 0x0010, 0x523: 0x0010, - 0x524: 0x0010, 0x525: 0x0010, 0x526: 0x0010, 0x527: 0x0010, 0x528: 0x0010, - 0x52a: 0x0010, 0x52b: 0x0010, 0x52c: 0x0010, 0x52d: 0x0010, 0x52e: 0x0010, 0x52f: 0x0010, - 0x530: 0x0010, 0x531: 0x0010, 0x532: 0x0010, 0x533: 0x0010, 0x534: 0x0010, 0x535: 0x0010, - 0x536: 0x0010, 0x538: 0x0010, 0x539: 0x0010, 0x53a: 0x0010, 0x53b: 0x0010, - 0x53c: 0x0010, 0x53e: 0x0010, - // Block 0x15, offset 0x540 - 0x540: 0x2713, 0x541: 0x2913, 0x542: 0x2b13, 0x543: 0x2913, 0x544: 0x2f13, 0x545: 0x2913, - 0x546: 0x2b13, 0x547: 0x2913, 0x548: 0x2713, 0x549: 0x3913, 0x54a: 0x3b13, - 0x54c: 0x3f13, 0x54d: 0x3913, 0x54e: 0x3b13, 0x54f: 0x3913, 0x550: 0x2713, 0x551: 0x2913, - 0x552: 0x2b13, 0x554: 0x2f13, 0x555: 0x2913, 0x557: 0xbc52, - 0x558: 0xbf52, 0x559: 0xc252, 0x55a: 0xbf52, 0x55b: 0xc552, 0x55c: 0xbf52, 0x55d: 0xc252, - 0x55e: 0xbf52, 0x55f: 0xbc52, 0x560: 0xc852, 0x561: 0xcb52, 0x563: 0xce52, - 0x564: 0xc852, 0x565: 0xcb52, 0x566: 0xc852, 0x567: 0x2712, 0x568: 0x2912, 0x569: 0x2b12, - 0x56a: 0x2912, 0x56b: 0x2f12, 0x56c: 0x2912, 0x56d: 0x2b12, 0x56e: 0x2912, 0x56f: 0x2712, - 0x570: 0x3912, 0x571: 0x3b12, 0x573: 0x3f12, 0x574: 0x3912, 0x575: 0x3b12, - 0x576: 0x3912, 0x577: 0x2712, 0x578: 0x2912, 0x579: 0x2b12, 0x57b: 0x2f12, - 0x57c: 0x2912, - // Block 0x16, offset 0x580 - 0x580: 0x2213, 0x581: 0x2213, 0x582: 0x2613, 0x583: 0x2613, 0x584: 0x2213, 0x585: 0x2213, - 0x586: 0x2e13, 0x587: 0x2e13, 0x588: 0x2213, 0x589: 0x2213, 0x58a: 0x2613, 0x58b: 0x2613, - 0x58c: 0x2213, 0x58d: 0x2213, 0x58e: 0x3e13, 0x58f: 0x3e13, 0x590: 0x2213, 0x591: 0x2213, - 0x592: 0x2613, 0x593: 0x2613, 0x594: 0x2213, 0x595: 0x2213, 0x596: 0x2e13, 0x597: 0x2e13, - 0x598: 0x2213, 0x599: 0x2213, 0x59a: 0x2613, 0x59b: 0x2613, 0x59c: 0x2213, 0x59d: 0x2213, - 0x59e: 0xd153, 0x59f: 0xd153, 0x5a0: 0xd453, 0x5a1: 0xd453, 0x5a2: 0x2212, 0x5a3: 0x2212, - 0x5a4: 0x2612, 0x5a5: 0x2612, 0x5a6: 0x2212, 0x5a7: 0x2212, 0x5a8: 0x2e12, 0x5a9: 0x2e12, - 0x5aa: 0x2212, 0x5ab: 0x2212, 0x5ac: 0x2612, 0x5ad: 0x2612, 0x5ae: 0x2212, 0x5af: 0x2212, - 0x5b0: 0x3e12, 0x5b1: 0x3e12, 0x5b2: 0x2212, 0x5b3: 0x2212, 0x5b4: 0x2612, 0x5b5: 0x2612, - 0x5b6: 0x2212, 0x5b7: 0x2212, 0x5b8: 0x2e12, 0x5b9: 0x2e12, 0x5ba: 0x2212, 0x5bb: 0x2212, - 0x5bc: 0x2612, 0x5bd: 0x2612, 0x5be: 0x2212, 0x5bf: 0x2212, - // Block 0x17, offset 0x5c0 - 0x5c2: 0x0010, - 0x5c7: 0x0010, 0x5c9: 0x0010, 0x5cb: 0x0010, - 0x5cd: 0x0010, 0x5ce: 0x0010, 0x5cf: 0x0010, 0x5d1: 0x0010, - 0x5d2: 0x0010, 0x5d4: 0x0010, 0x5d7: 0x0010, - 0x5d9: 0x0010, 0x5db: 0x0010, 0x5dd: 0x0010, - 0x5df: 0x0010, 0x5e1: 0x0010, 0x5e2: 0x0010, - 0x5e4: 0x0010, 0x5e7: 0x0010, 0x5e8: 0x0010, 0x5e9: 0x0010, - 0x5ea: 0x0010, 0x5ec: 0x0010, 0x5ed: 0x0010, 0x5ee: 0x0010, 0x5ef: 0x0010, - 0x5f0: 0x0010, 0x5f1: 0x0010, 0x5f2: 0x0010, 0x5f4: 0x0010, 0x5f5: 0x0010, - 0x5f6: 0x0010, 0x5f7: 0x0010, 0x5f9: 0x0010, 0x5fa: 0x0010, 0x5fb: 0x0010, - 0x5fc: 0x0010, 0x5fe: 0x0010, -} - -// caseIndex: 27 blocks, 1728 entries, 3456 bytes -// Block 0 is the zero block. -var caseIndex = [1728]uint16{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x16, 0xc3: 0x17, 0xc4: 0x18, 0xc5: 0x19, 0xc6: 0x01, 0xc7: 0x02, - 0xc8: 0x1a, 0xc9: 0x03, 0xca: 0x04, 0xcb: 0x1b, 0xcc: 0x1c, 0xcd: 0x05, 0xce: 0x06, 0xcf: 0x07, - 0xd0: 0x1d, 0xd1: 0x1e, 0xd2: 0x1f, 0xd3: 0x20, 0xd4: 0x21, 0xd5: 0x22, 0xd6: 0x08, 0xd7: 0x23, - 0xd8: 0x24, 0xd9: 0x25, 0xda: 0x26, 0xdb: 0x27, 0xdc: 0x28, 0xdd: 0x29, 0xde: 0x2a, 0xdf: 0x2b, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, - 0xea: 0x06, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x08, 0xef: 0x09, - 0xf0: 0x16, 0xf3: 0x18, - // Block 0x4, offset 0x100 - 0x120: 0x2c, 0x121: 0x2d, 0x122: 0x2e, 0x123: 0x09, 0x124: 0x2f, 0x125: 0x30, 0x126: 0x31, 0x127: 0x32, - 0x128: 0x33, 0x129: 0x34, 0x12a: 0x35, 0x12b: 0x36, 0x12c: 0x37, 0x12d: 0x38, 0x12e: 0x39, 0x12f: 0x3a, - 0x130: 0x3b, 0x131: 0x3c, 0x132: 0x3d, 0x133: 0x3e, 0x134: 0x3f, 0x135: 0x40, 0x136: 0x41, 0x137: 0x42, - 0x138: 0x43, 0x139: 0x44, 0x13a: 0x45, 0x13b: 0x46, 0x13c: 0x47, 0x13d: 0x48, 0x13e: 0x49, 0x13f: 0x4a, - // Block 0x5, offset 0x140 - 0x140: 0x4b, 0x141: 0x4c, 0x142: 0x4d, 0x143: 0x0a, 0x144: 0x26, 0x145: 0x26, 0x146: 0x26, 0x147: 0x26, - 0x148: 0x26, 0x149: 0x4e, 0x14a: 0x4f, 0x14b: 0x50, 0x14c: 0x51, 0x14d: 0x52, 0x14e: 0x53, 0x14f: 0x54, - 0x150: 0x55, 0x151: 0x26, 0x152: 0x26, 0x153: 0x26, 0x154: 0x26, 0x155: 0x26, 0x156: 0x26, 0x157: 0x26, - 0x158: 0x26, 0x159: 0x56, 0x15a: 0x57, 0x15b: 0x58, 0x15c: 0x59, 0x15d: 0x5a, 0x15e: 0x5b, 0x15f: 0x5c, - 0x160: 0x5d, 0x161: 0x5e, 0x162: 0x5f, 0x163: 0x60, 0x164: 0x61, 0x165: 0x62, 0x167: 0x63, - 0x168: 0x64, 0x169: 0x65, 0x16a: 0x66, 0x16b: 0x67, 0x16c: 0x68, 0x16d: 0x69, 0x16e: 0x6a, 0x16f: 0x6b, - 0x170: 0x6c, 0x171: 0x6d, 0x172: 0x6e, 0x173: 0x6f, 0x174: 0x70, 0x175: 0x71, 0x176: 0x72, 0x177: 0x73, - 0x178: 0x74, 0x179: 0x74, 0x17a: 0x75, 0x17b: 0x74, 0x17c: 0x76, 0x17d: 0x0b, 0x17e: 0x0c, 0x17f: 0x0d, - // Block 0x6, offset 0x180 - 0x180: 0x77, 0x181: 0x78, 0x182: 0x79, 0x183: 0x7a, 0x184: 0x0e, 0x185: 0x7b, 0x186: 0x7c, - 0x192: 0x7d, 0x193: 0x0f, - 0x1b0: 0x7e, 0x1b1: 0x10, 0x1b2: 0x74, 0x1b3: 0x7f, 0x1b4: 0x80, 0x1b5: 0x81, 0x1b6: 0x82, 0x1b7: 0x83, - 0x1b8: 0x84, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x85, 0x1c2: 0x86, 0x1c3: 0x87, 0x1c4: 0x88, 0x1c5: 0x26, 0x1c6: 0x89, - // Block 0x8, offset 0x200 - 0x200: 0x8a, 0x201: 0x26, 0x202: 0x26, 0x203: 0x26, 0x204: 0x26, 0x205: 0x26, 0x206: 0x26, 0x207: 0x26, - 0x208: 0x26, 0x209: 0x26, 0x20a: 0x26, 0x20b: 0x26, 0x20c: 0x26, 0x20d: 0x26, 0x20e: 0x26, 0x20f: 0x26, - 0x210: 0x26, 0x211: 0x26, 0x212: 0x8b, 0x213: 0x8c, 0x214: 0x26, 0x215: 0x26, 0x216: 0x26, 0x217: 0x26, - 0x218: 0x8d, 0x219: 0x8e, 0x21a: 0x8f, 0x21b: 0x90, 0x21c: 0x91, 0x21d: 0x92, 0x21e: 0x11, 0x21f: 0x93, - 0x220: 0x94, 0x221: 0x95, 0x222: 0x26, 0x223: 0x96, 0x224: 0x97, 0x225: 0x98, 0x226: 0x99, 0x227: 0x9a, - 0x228: 0x9b, 0x229: 0x9c, 0x22a: 0x9d, 0x22b: 0x9e, 0x22c: 0x9f, 0x22d: 0xa0, 0x22e: 0xa1, 0x22f: 0xa2, - 0x230: 0x26, 0x231: 0x26, 0x232: 0x26, 0x233: 0x26, 0x234: 0x26, 0x235: 0x26, 0x236: 0x26, 0x237: 0x26, - 0x238: 0x26, 0x239: 0x26, 0x23a: 0x26, 0x23b: 0x26, 0x23c: 0x26, 0x23d: 0x26, 0x23e: 0x26, 0x23f: 0x26, - // Block 0x9, offset 0x240 - 0x240: 0x26, 0x241: 0x26, 0x242: 0x26, 0x243: 0x26, 0x244: 0x26, 0x245: 0x26, 0x246: 0x26, 0x247: 0x26, - 0x248: 0x26, 0x249: 0x26, 0x24a: 0x26, 0x24b: 0x26, 0x24c: 0x26, 0x24d: 0x26, 0x24e: 0x26, 0x24f: 0x26, - 0x250: 0x26, 0x251: 0x26, 0x252: 0x26, 0x253: 0x26, 0x254: 0x26, 0x255: 0x26, 0x256: 0x26, 0x257: 0x26, - 0x258: 0x26, 0x259: 0x26, 0x25a: 0x26, 0x25b: 0x26, 0x25c: 0x26, 0x25d: 0x26, 0x25e: 0x26, 0x25f: 0x26, - 0x260: 0x26, 0x261: 0x26, 0x262: 0x26, 0x263: 0x26, 0x264: 0x26, 0x265: 0x26, 0x266: 0x26, 0x267: 0x26, - 0x268: 0x26, 0x269: 0x26, 0x26a: 0x26, 0x26b: 0x26, 0x26c: 0x26, 0x26d: 0x26, 0x26e: 0x26, 0x26f: 0x26, - 0x270: 0x26, 0x271: 0x26, 0x272: 0x26, 0x273: 0x26, 0x274: 0x26, 0x275: 0x26, 0x276: 0x26, 0x277: 0x26, - 0x278: 0x26, 0x279: 0x26, 0x27a: 0x26, 0x27b: 0x26, 0x27c: 0x26, 0x27d: 0x26, 0x27e: 0x26, 0x27f: 0x26, - // Block 0xa, offset 0x280 - 0x280: 0x26, 0x281: 0x26, 0x282: 0x26, 0x283: 0x26, 0x284: 0x26, 0x285: 0x26, 0x286: 0x26, 0x287: 0x26, - 0x288: 0x26, 0x289: 0x26, 0x28a: 0x26, 0x28b: 0x26, 0x28c: 0x26, 0x28d: 0x26, 0x28e: 0x26, 0x28f: 0x26, - 0x290: 0x26, 0x291: 0x26, 0x292: 0x26, 0x293: 0x26, 0x294: 0x26, 0x295: 0x26, 0x296: 0x26, 0x297: 0x26, - 0x298: 0x26, 0x299: 0x26, 0x29a: 0x26, 0x29b: 0x26, 0x29c: 0x26, 0x29d: 0x26, 0x29e: 0xa3, 0x29f: 0xa4, - // Block 0xb, offset 0x2c0 - 0x2ec: 0x12, 0x2ed: 0xa5, 0x2ee: 0xa6, 0x2ef: 0xa7, - 0x2f0: 0x26, 0x2f1: 0x26, 0x2f2: 0x26, 0x2f3: 0x26, 0x2f4: 0xa8, 0x2f5: 0xa9, 0x2f6: 0xaa, 0x2f7: 0xab, - 0x2f8: 0xac, 0x2f9: 0xad, 0x2fa: 0x26, 0x2fb: 0xae, 0x2fc: 0xaf, 0x2fd: 0xb0, 0x2fe: 0xb1, 0x2ff: 0xb2, - // Block 0xc, offset 0x300 - 0x300: 0xb3, 0x301: 0xb4, 0x302: 0x26, 0x303: 0xb5, 0x305: 0xb6, 0x307: 0xb7, - 0x30a: 0xb8, 0x30b: 0xb9, 0x30c: 0xba, 0x30d: 0xbb, 0x30e: 0xbc, 0x30f: 0xbd, - 0x310: 0xbe, 0x311: 0xbf, 0x312: 0xc0, 0x313: 0xc1, 0x314: 0xc2, 0x315: 0xc3, 0x316: 0x13, - 0x318: 0x26, 0x319: 0x26, 0x31a: 0x26, 0x31b: 0x26, 0x31c: 0xc4, 0x31d: 0xc5, 0x31e: 0xc6, - 0x320: 0xc7, 0x321: 0xc8, 0x322: 0xc9, 0x323: 0xca, 0x324: 0xcb, 0x326: 0xcc, - 0x328: 0xcd, 0x329: 0xce, 0x32a: 0xcf, 0x32b: 0xd0, 0x32c: 0x60, 0x32d: 0xd1, 0x32e: 0xd2, - 0x330: 0x26, 0x331: 0xd3, 0x332: 0xd4, 0x333: 0xd5, 0x334: 0xd6, - 0x33a: 0xd7, 0x33b: 0xd8, 0x33c: 0xd9, 0x33d: 0xda, 0x33e: 0xdb, 0x33f: 0xdc, - // Block 0xd, offset 0x340 - 0x340: 0xdd, 0x341: 0xde, 0x342: 0xdf, 0x343: 0xe0, 0x344: 0xe1, 0x345: 0xe2, 0x346: 0xe3, 0x347: 0xe4, - 0x348: 0xe5, 0x349: 0xe6, 0x34a: 0xe7, 0x34b: 0xe8, 0x34c: 0xe9, 0x34d: 0xea, - 0x350: 0xeb, 0x351: 0xec, 0x352: 0xed, 0x353: 0xee, 0x356: 0xef, 0x357: 0xf0, - 0x358: 0xf1, 0x359: 0xf2, 0x35a: 0xf3, 0x35b: 0xf4, 0x35c: 0xf5, - 0x360: 0xf6, 0x362: 0xf7, 0x363: 0xf8, 0x364: 0xf9, 0x365: 0xfa, 0x366: 0xfb, 0x367: 0xfc, - 0x368: 0xfd, 0x369: 0xfe, 0x36a: 0xff, 0x36b: 0x100, - 0x370: 0x101, 0x371: 0x102, 0x372: 0x103, 0x374: 0x104, 0x375: 0x105, 0x376: 0x106, - 0x37b: 0x107, 0x37c: 0x108, 0x37d: 0x109, 0x37e: 0x10a, - // Block 0xe, offset 0x380 - 0x380: 0x26, 0x381: 0x26, 0x382: 0x26, 0x383: 0x26, 0x384: 0x26, 0x385: 0x26, 0x386: 0x26, 0x387: 0x26, - 0x388: 0x26, 0x389: 0x26, 0x38a: 0x26, 0x38b: 0x26, 0x38c: 0x26, 0x38d: 0x26, 0x38e: 0x10b, - 0x390: 0x26, 0x391: 0x10c, 0x392: 0x26, 0x393: 0x26, 0x394: 0x26, 0x395: 0x10d, - 0x3be: 0xa9, 0x3bf: 0x10e, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x26, 0x3c1: 0x26, 0x3c2: 0x26, 0x3c3: 0x26, 0x3c4: 0x26, 0x3c5: 0x26, 0x3c6: 0x26, 0x3c7: 0x26, - 0x3c8: 0x26, 0x3c9: 0x26, 0x3ca: 0x26, 0x3cb: 0x26, 0x3cc: 0x26, 0x3cd: 0x26, 0x3ce: 0x26, 0x3cf: 0x26, - 0x3d0: 0x10f, 0x3d1: 0x110, - // Block 0x10, offset 0x400 - 0x410: 0x26, 0x411: 0x26, 0x412: 0x26, 0x413: 0x26, 0x414: 0x26, 0x415: 0x26, 0x416: 0x26, 0x417: 0x26, - 0x418: 0x26, 0x419: 0x111, - // Block 0x11, offset 0x440 - 0x460: 0x26, 0x461: 0x26, 0x462: 0x26, 0x463: 0x26, 0x464: 0x26, 0x465: 0x26, 0x466: 0x26, 0x467: 0x26, - 0x468: 0x100, 0x469: 0x112, 0x46a: 0x113, 0x46b: 0x114, 0x46c: 0x115, 0x46d: 0x116, 0x46e: 0x117, - 0x479: 0x118, 0x47c: 0x26, 0x47d: 0x119, 0x47e: 0x11a, 0x47f: 0x11b, - // Block 0x12, offset 0x480 - 0x4bf: 0x11c, - // Block 0x13, offset 0x4c0 - 0x4f0: 0x26, 0x4f1: 0x11d, 0x4f2: 0x11e, - // Block 0x14, offset 0x500 - 0x53c: 0x11f, 0x53d: 0x120, - // Block 0x15, offset 0x540 - 0x545: 0x121, 0x546: 0x122, - 0x549: 0x123, - 0x550: 0x124, 0x551: 0x125, 0x552: 0x126, 0x553: 0x127, 0x554: 0x128, 0x555: 0x129, 0x556: 0x12a, 0x557: 0x12b, - 0x558: 0x12c, 0x559: 0x12d, 0x55a: 0x12e, 0x55b: 0x12f, 0x55c: 0x130, 0x55d: 0x131, 0x55e: 0x132, 0x55f: 0x133, - 0x568: 0x134, 0x569: 0x135, 0x56a: 0x136, - 0x57c: 0x137, - // Block 0x16, offset 0x580 - 0x580: 0x138, 0x581: 0x139, 0x582: 0x13a, 0x584: 0x13b, 0x585: 0x13c, - 0x58a: 0x13d, 0x58b: 0x13e, - 0x593: 0x13f, - 0x59f: 0x140, - 0x5a0: 0x26, 0x5a1: 0x26, 0x5a2: 0x26, 0x5a3: 0x141, 0x5a4: 0x14, 0x5a5: 0x142, - 0x5b8: 0x143, 0x5b9: 0x15, 0x5ba: 0x144, - // Block 0x17, offset 0x5c0 - 0x5c4: 0x145, 0x5c5: 0x146, 0x5c6: 0x147, - 0x5cf: 0x148, - 0x5ef: 0x149, - // Block 0x18, offset 0x600 - 0x610: 0x0a, 0x611: 0x0b, 0x612: 0x0c, 0x613: 0x0d, 0x614: 0x0e, 0x616: 0x0f, - 0x61a: 0x10, 0x61b: 0x11, 0x61c: 0x12, 0x61d: 0x13, 0x61e: 0x14, 0x61f: 0x15, - // Block 0x19, offset 0x640 - 0x640: 0x14a, 0x641: 0x14b, 0x644: 0x14b, 0x645: 0x14b, 0x646: 0x14b, 0x647: 0x14c, - // Block 0x1a, offset 0x680 - 0x6a0: 0x17, -} - -// sparseOffsets: 312 entries, 624 bytes -var sparseOffsets = []uint16{0x0, 0x9, 0xf, 0x18, 0x24, 0x2e, 0x34, 0x37, 0x3b, 0x3e, 0x42, 0x4c, 0x4e, 0x57, 0x5e, 0x63, 0x71, 0x72, 0x80, 0x8f, 0x99, 0x9c, 0xa3, 0xab, 0xaf, 0xb7, 0xbd, 0xcb, 0xd6, 0xe3, 0xee, 0xfa, 0x104, 0x110, 0x11b, 0x127, 0x133, 0x13b, 0x145, 0x150, 0x15b, 0x167, 0x16d, 0x178, 0x17e, 0x186, 0x189, 0x18e, 0x192, 0x196, 0x19d, 0x1a6, 0x1ae, 0x1af, 0x1b8, 0x1bf, 0x1c7, 0x1cd, 0x1d2, 0x1d6, 0x1d9, 0x1db, 0x1de, 0x1e3, 0x1e4, 0x1e6, 0x1e8, 0x1ea, 0x1f1, 0x1f6, 0x1fa, 0x203, 0x206, 0x209, 0x20f, 0x210, 0x21b, 0x21c, 0x21d, 0x222, 0x22f, 0x238, 0x23e, 0x246, 0x24f, 0x258, 0x261, 0x266, 0x269, 0x274, 0x282, 0x284, 0x28b, 0x28f, 0x29b, 0x29c, 0x2a7, 0x2af, 0x2b7, 0x2bd, 0x2be, 0x2cc, 0x2d1, 0x2d4, 0x2d9, 0x2dd, 0x2e3, 0x2e8, 0x2eb, 0x2f0, 0x2f5, 0x2f6, 0x2fc, 0x2fe, 0x2ff, 0x301, 0x303, 0x306, 0x307, 0x309, 0x30c, 0x312, 0x316, 0x318, 0x31d, 0x324, 0x334, 0x33e, 0x33f, 0x348, 0x34c, 0x351, 0x359, 0x35f, 0x365, 0x36f, 0x374, 0x37d, 0x383, 0x38c, 0x390, 0x398, 0x39a, 0x39c, 0x39f, 0x3a1, 0x3a3, 0x3a4, 0x3a5, 0x3a7, 0x3a9, 0x3af, 0x3b4, 0x3b6, 0x3bd, 0x3c0, 0x3c2, 0x3c8, 0x3cd, 0x3cf, 0x3d0, 0x3d1, 0x3d2, 0x3d4, 0x3d6, 0x3d8, 0x3db, 0x3dd, 0x3e0, 0x3e8, 0x3eb, 0x3ef, 0x3f7, 0x3f9, 0x409, 0x40a, 0x40c, 0x411, 0x417, 0x419, 0x41a, 0x41c, 0x41e, 0x420, 0x42d, 0x42e, 0x42f, 0x433, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43c, 0x43f, 0x440, 0x443, 0x44a, 0x450, 0x452, 0x456, 0x45e, 0x464, 0x468, 0x46f, 0x473, 0x477, 0x480, 0x48a, 0x48c, 0x492, 0x498, 0x4a2, 0x4ac, 0x4ae, 0x4b7, 0x4bd, 0x4c3, 0x4c9, 0x4cc, 0x4d2, 0x4d5, 0x4de, 0x4df, 0x4e6, 0x4ea, 0x4eb, 0x4ee, 0x4f8, 0x4fb, 0x4fd, 0x504, 0x50c, 0x512, 0x519, 0x51a, 0x520, 0x523, 0x52b, 0x532, 0x53c, 0x544, 0x547, 0x54c, 0x550, 0x551, 0x552, 0x553, 0x554, 0x555, 0x557, 0x55a, 0x55b, 0x55e, 0x55f, 0x562, 0x564, 0x568, 0x569, 0x56b, 0x56e, 0x570, 0x573, 0x576, 0x578, 0x57d, 0x57f, 0x580, 0x585, 0x589, 0x58a, 0x58d, 0x591, 0x59c, 0x5a0, 0x5a8, 0x5ad, 0x5b1, 0x5b4, 0x5b8, 0x5bb, 0x5be, 0x5c3, 0x5c7, 0x5cb, 0x5cf, 0x5d3, 0x5d5, 0x5d7, 0x5da, 0x5de, 0x5e4, 0x5e5, 0x5e6, 0x5e9, 0x5eb, 0x5ed, 0x5f0, 0x5f5, 0x5f9, 0x5fb, 0x601, 0x60a, 0x60f, 0x610, 0x613, 0x614, 0x615, 0x616, 0x618, 0x619, 0x61a} - -// sparseValues: 1562 entries, 6248 bytes -var sparseValues = [1562]valueRange{ - // Block 0x0, offset 0x0 - {value: 0x0004, lo: 0xa8, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xaa}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0004, lo: 0xaf, hi: 0xaf}, - {value: 0x0004, lo: 0xb4, hi: 0xb4}, - {value: 0x001a, lo: 0xb5, hi: 0xb5}, - {value: 0x0054, lo: 0xb7, hi: 0xb7}, - {value: 0x0004, lo: 0xb8, hi: 0xb8}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - // Block 0x1, offset 0x9 - {value: 0x2013, lo: 0x80, hi: 0x96}, - {value: 0x2013, lo: 0x98, hi: 0x9e}, - {value: 0x009a, lo: 0x9f, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xb6}, - {value: 0x2012, lo: 0xb8, hi: 0xbe}, - {value: 0x0252, lo: 0xbf, hi: 0xbf}, - // Block 0x2, offset 0xf - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x011b, lo: 0xb0, hi: 0xb0}, - {value: 0x019a, lo: 0xb1, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb7}, - {value: 0x0012, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x0553, lo: 0xbf, hi: 0xbf}, - // Block 0x3, offset 0x18 - {value: 0x0552, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x01da, lo: 0x89, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xb7}, - {value: 0x0253, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x028a, lo: 0xbf, hi: 0xbf}, - // Block 0x4, offset 0x24 - {value: 0x0117, lo: 0x80, hi: 0x9f}, - {value: 0x2f53, lo: 0xa0, hi: 0xa0}, - {value: 0x0012, lo: 0xa1, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xb3}, - {value: 0x0012, lo: 0xb4, hi: 0xb9}, - {value: 0x090b, lo: 0xba, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x2953, lo: 0xbd, hi: 0xbd}, - {value: 0x098b, lo: 0xbe, hi: 0xbe}, - {value: 0x0a0a, lo: 0xbf, hi: 0xbf}, - // Block 0x5, offset 0x2e - {value: 0x0015, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x97}, - {value: 0x0004, lo: 0x98, hi: 0x9d}, - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0015, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xbf}, - // Block 0x6, offset 0x34 - {value: 0x0024, lo: 0x80, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbf}, - // Block 0x7, offset 0x37 - {value: 0x6553, lo: 0x80, hi: 0x8f}, - {value: 0x2013, lo: 0x90, hi: 0x9f}, - {value: 0x5f53, lo: 0xa0, hi: 0xaf}, - {value: 0x2012, lo: 0xb0, hi: 0xbf}, - // Block 0x8, offset 0x3b - {value: 0x5f52, lo: 0x80, hi: 0x8f}, - {value: 0x6552, lo: 0x90, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x9, offset 0x3e - {value: 0x0117, lo: 0x80, hi: 0x81}, - {value: 0x0024, lo: 0x83, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xbf}, - // Block 0xa, offset 0x42 - {value: 0x0f13, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0716, lo: 0x8b, hi: 0x8c}, - {value: 0x0316, lo: 0x8d, hi: 0x8e}, - {value: 0x0f12, lo: 0x8f, hi: 0x8f}, - {value: 0x0117, lo: 0x90, hi: 0xbf}, - // Block 0xb, offset 0x4c - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x6553, lo: 0xb1, hi: 0xbf}, - // Block 0xc, offset 0x4e - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6853, lo: 0x90, hi: 0x96}, - {value: 0x0014, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0054, lo: 0x9f, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa0}, - {value: 0x6552, lo: 0xa1, hi: 0xaf}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0xd, offset 0x57 - {value: 0x0034, lo: 0x81, hi: 0x82}, - {value: 0x0024, lo: 0x84, hi: 0x84}, - {value: 0x0034, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xaa}, - {value: 0x0010, lo: 0xaf, hi: 0xb3}, - {value: 0x0054, lo: 0xb4, hi: 0xb4}, - // Block 0xe, offset 0x5e - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0024, lo: 0x90, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0014, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xf, offset 0x63 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9c}, - {value: 0x0024, lo: 0x9d, hi: 0x9e}, - {value: 0x0034, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x10, offset 0x71 - {value: 0x0010, lo: 0x80, hi: 0xbf}, - // Block 0x11, offset 0x72 - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0024, lo: 0x9f, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x12, offset 0x80 - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0034, lo: 0xb1, hi: 0xb1}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0024, lo: 0xbf, hi: 0xbf}, - // Block 0x13, offset 0x8f - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0024, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x88}, - {value: 0x0024, lo: 0x89, hi: 0x8a}, - {value: 0x0010, lo: 0x8d, hi: 0xbf}, - // Block 0x14, offset 0x99 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x15, offset 0x9c - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xb1}, - {value: 0x0034, lo: 0xb2, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0x16, offset 0xa3 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x99}, - {value: 0x0014, lo: 0x9a, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0xa3}, - {value: 0x0014, lo: 0xa4, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xad}, - // Block 0x17, offset 0xab - {value: 0x0010, lo: 0x80, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0xa0, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x18, offset 0xaf - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0004, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x8e}, - {value: 0x0014, lo: 0x90, hi: 0x91}, - {value: 0x0024, lo: 0x98, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x9b}, - {value: 0x0024, lo: 0x9c, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x19, offset 0xb7 - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1a, offset 0xbd - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0x1b, offset 0xcb - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb6, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1c, offset 0xd6 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xb1}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - // Block 0x1d, offset 0xe3 - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x1e, offset 0xee - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x99, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x1f, offset 0xfa - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x20, offset 0x104 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x85}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xbf}, - // Block 0x21, offset 0x110 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x22, offset 0x11b - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x23, offset 0x127 - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0010, lo: 0xa8, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x24, offset 0x133 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x25, offset 0x13b - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbf}, - // Block 0x26, offset 0x145 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x88}, - {value: 0x0014, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9a}, - {value: 0x0010, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x27, offset 0x150 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x28, offset 0x15b - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x9d, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb3}, - // Block 0x29, offset 0x167 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x2a, offset 0x16d - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x94, hi: 0x97}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xba, hi: 0xbf}, - // Block 0x2b, offset 0x178 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x96}, - {value: 0x0010, lo: 0x9a, hi: 0xb1}, - {value: 0x0010, lo: 0xb3, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x2c, offset 0x17e - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x94}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9f}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - // Block 0x2d, offset 0x186 - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - // Block 0x2e, offset 0x189 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x2f, offset 0x18e - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - // Block 0x30, offset 0x192 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x31, offset 0x196 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0034, lo: 0x98, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0034, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x32, offset 0x19d - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xac}, - {value: 0x0034, lo: 0xb1, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xba, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x33, offset 0x1a6 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0024, lo: 0x82, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x86, hi: 0x87}, - {value: 0x0010, lo: 0x88, hi: 0x8c}, - {value: 0x0014, lo: 0x8d, hi: 0x97}, - {value: 0x0014, lo: 0x99, hi: 0xbc}, - // Block 0x34, offset 0x1ae - {value: 0x0034, lo: 0x86, hi: 0x86}, - // Block 0x35, offset 0x1af - {value: 0x0010, lo: 0xab, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbe}, - // Block 0x36, offset 0x1b8 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x96, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x99}, - {value: 0x0014, lo: 0x9e, hi: 0xa0}, - {value: 0x0010, lo: 0xa2, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xad}, - {value: 0x0014, lo: 0xb1, hi: 0xb4}, - // Block 0x37, offset 0x1bf - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x6c53, lo: 0xa0, hi: 0xbf}, - // Block 0x38, offset 0x1c7 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x9a, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x39, offset 0x1cd - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x3a, offset 0x1d2 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x82, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3b, offset 0x1d6 - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3c, offset 0x1d9 - {value: 0x0010, lo: 0x80, hi: 0x9a}, - {value: 0x0024, lo: 0x9d, hi: 0x9f}, - // Block 0x3d, offset 0x1db - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x7453, lo: 0xa0, hi: 0xaf}, - {value: 0x7853, lo: 0xb0, hi: 0xbf}, - // Block 0x3e, offset 0x1de - {value: 0x7c53, lo: 0x80, hi: 0x8f}, - {value: 0x8053, lo: 0x90, hi: 0x9f}, - {value: 0x7c53, lo: 0xa0, hi: 0xaf}, - {value: 0x0813, lo: 0xb0, hi: 0xb5}, - {value: 0x0892, lo: 0xb8, hi: 0xbd}, - // Block 0x3f, offset 0x1e3 - {value: 0x0010, lo: 0x81, hi: 0xbf}, - // Block 0x40, offset 0x1e4 - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0010, lo: 0xaf, hi: 0xbf}, - // Block 0x41, offset 0x1e6 - {value: 0x0010, lo: 0x81, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x42, offset 0x1e8 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb8}, - // Block 0x43, offset 0x1ea - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0034, lo: 0x94, hi: 0x94}, - {value: 0x0030, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x9f, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0030, lo: 0xb4, hi: 0xb4}, - // Block 0x44, offset 0x1f1 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xac}, - {value: 0x0010, lo: 0xae, hi: 0xb0}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - // Block 0x45, offset 0x1f6 - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x46, offset 0x1fa - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x89, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0014, lo: 0x93, hi: 0x93}, - {value: 0x0004, lo: 0x97, hi: 0x97}, - {value: 0x0024, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0x47, offset 0x203 - {value: 0x0014, lo: 0x8b, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x48, offset 0x206 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb8}, - // Block 0x49, offset 0x209 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x4a, offset 0x20f - {value: 0x0010, lo: 0x80, hi: 0xb5}, - // Block 0x4b, offset 0x210 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbb}, - // Block 0x4c, offset 0x21b - {value: 0x0010, lo: 0x86, hi: 0x8f}, - // Block 0x4d, offset 0x21c - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x4e, offset 0x21d - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - // Block 0x4f, offset 0x222 - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x9e}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xac}, - {value: 0x0010, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xbc}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x50, offset 0x22f - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xa7, hi: 0xa7}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - {value: 0x0034, lo: 0xb5, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbc}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x51, offset 0x238 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0024, lo: 0x81, hi: 0x82}, - {value: 0x0034, lo: 0x83, hi: 0x84}, - {value: 0x0024, lo: 0x85, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0024, lo: 0x8b, hi: 0x8e}, - // Block 0x52, offset 0x23e - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x53, offset 0x246 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0030, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xab, hi: 0xab}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - {value: 0x0024, lo: 0xad, hi: 0xb3}, - // Block 0x54, offset 0x24f - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0030, lo: 0xaa, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbf}, - // Block 0x55, offset 0x258 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0030, lo: 0xb2, hi: 0xb3}, - // Block 0x56, offset 0x261 - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0x57, offset 0x266 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8d, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x58, offset 0x269 - {value: 0x31ea, lo: 0x80, hi: 0x80}, - {value: 0x326a, lo: 0x81, hi: 0x81}, - {value: 0x32ea, lo: 0x82, hi: 0x82}, - {value: 0x336a, lo: 0x83, hi: 0x83}, - {value: 0x33ea, lo: 0x84, hi: 0x84}, - {value: 0x346a, lo: 0x85, hi: 0x85}, - {value: 0x34ea, lo: 0x86, hi: 0x86}, - {value: 0x356a, lo: 0x87, hi: 0x87}, - {value: 0x35ea, lo: 0x88, hi: 0x88}, - {value: 0x8353, lo: 0x90, hi: 0xba}, - {value: 0x8353, lo: 0xbd, hi: 0xbf}, - // Block 0x59, offset 0x274 - {value: 0x0024, lo: 0x90, hi: 0x92}, - {value: 0x0034, lo: 0x94, hi: 0x99}, - {value: 0x0024, lo: 0x9a, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9f}, - {value: 0x0024, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xb3}, - {value: 0x0024, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb7}, - {value: 0x0024, lo: 0xb8, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xba}, - // Block 0x5a, offset 0x282 - {value: 0x0012, lo: 0x80, hi: 0xab}, - {value: 0x0015, lo: 0xac, hi: 0xbf}, - // Block 0x5b, offset 0x284 - {value: 0x0015, lo: 0x80, hi: 0xaa}, - {value: 0x0012, lo: 0xab, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb8}, - {value: 0x8752, lo: 0xb9, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbc}, - {value: 0x8b52, lo: 0xbd, hi: 0xbd}, - {value: 0x0012, lo: 0xbe, hi: 0xbf}, - // Block 0x5c, offset 0x28b - {value: 0x0012, lo: 0x80, hi: 0x8d}, - {value: 0x8f52, lo: 0x8e, hi: 0x8e}, - {value: 0x0012, lo: 0x8f, hi: 0x9a}, - {value: 0x0015, lo: 0x9b, hi: 0xbf}, - // Block 0x5d, offset 0x28f - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0024, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbd}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x5e, offset 0x29b - {value: 0x0117, lo: 0x80, hi: 0xbf}, - // Block 0x5f, offset 0x29c - {value: 0x0117, lo: 0x80, hi: 0x95}, - {value: 0x369a, lo: 0x96, hi: 0x96}, - {value: 0x374a, lo: 0x97, hi: 0x97}, - {value: 0x37fa, lo: 0x98, hi: 0x98}, - {value: 0x38aa, lo: 0x99, hi: 0x99}, - {value: 0x395a, lo: 0x9a, hi: 0x9a}, - {value: 0x3a0a, lo: 0x9b, hi: 0x9b}, - {value: 0x0012, lo: 0x9c, hi: 0x9d}, - {value: 0x3abb, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0x9f, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x60, offset 0x2a7 - {value: 0x0812, lo: 0x80, hi: 0x87}, - {value: 0x0813, lo: 0x88, hi: 0x8f}, - {value: 0x0812, lo: 0x90, hi: 0x95}, - {value: 0x0813, lo: 0x98, hi: 0x9d}, - {value: 0x0812, lo: 0xa0, hi: 0xa7}, - {value: 0x0813, lo: 0xa8, hi: 0xaf}, - {value: 0x0812, lo: 0xb0, hi: 0xb7}, - {value: 0x0813, lo: 0xb8, hi: 0xbf}, - // Block 0x61, offset 0x2af - {value: 0x0004, lo: 0x8b, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8f}, - {value: 0x0054, lo: 0x98, hi: 0x99}, - {value: 0x0054, lo: 0xa4, hi: 0xa4}, - {value: 0x0054, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xaa, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xaf}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x62, offset 0x2b7 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x94, hi: 0x94}, - {value: 0x0014, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa6, hi: 0xaf}, - {value: 0x0015, lo: 0xb1, hi: 0xb1}, - {value: 0x0015, lo: 0xbf, hi: 0xbf}, - // Block 0x63, offset 0x2bd - {value: 0x0015, lo: 0x90, hi: 0x9c}, - // Block 0x64, offset 0x2be - {value: 0x0024, lo: 0x90, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0xa0}, - {value: 0x0024, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa4}, - {value: 0x0034, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - // Block 0x65, offset 0x2cc - {value: 0x0016, lo: 0x85, hi: 0x86}, - {value: 0x0012, lo: 0x87, hi: 0x89}, - {value: 0xa452, lo: 0x8e, hi: 0x8e}, - {value: 0x1013, lo: 0xa0, hi: 0xaf}, - {value: 0x1012, lo: 0xb0, hi: 0xbf}, - // Block 0x66, offset 0x2d1 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x88}, - // Block 0x67, offset 0x2d4 - {value: 0xa753, lo: 0xb6, hi: 0xb7}, - {value: 0xaa53, lo: 0xb8, hi: 0xb9}, - {value: 0xad53, lo: 0xba, hi: 0xbb}, - {value: 0xaa53, lo: 0xbc, hi: 0xbd}, - {value: 0xa753, lo: 0xbe, hi: 0xbf}, - // Block 0x68, offset 0x2d9 - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6553, lo: 0x90, hi: 0x9f}, - {value: 0xb053, lo: 0xa0, hi: 0xaf}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0x69, offset 0x2dd - {value: 0x0117, lo: 0x80, hi: 0xa3}, - {value: 0x0012, lo: 0xa4, hi: 0xa4}, - {value: 0x0716, lo: 0xab, hi: 0xac}, - {value: 0x0316, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb3}, - // Block 0x6a, offset 0x2e3 - {value: 0x6c52, lo: 0x80, hi: 0x9f}, - {value: 0x7052, lo: 0xa0, hi: 0xa5}, - {value: 0x7052, lo: 0xa7, hi: 0xa7}, - {value: 0x7052, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x6b, offset 0x2e8 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x6c, offset 0x2eb - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0010, lo: 0xb0, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x6d, offset 0x2f0 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9e}, - {value: 0x0024, lo: 0xa0, hi: 0xbf}, - // Block 0x6e, offset 0x2f5 - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - // Block 0x6f, offset 0x2f6 - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0xaa, hi: 0xad}, - {value: 0x0030, lo: 0xae, hi: 0xaf}, - {value: 0x0004, lo: 0xb1, hi: 0xb5}, - {value: 0x0014, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - // Block 0x70, offset 0x2fc - {value: 0x0034, lo: 0x99, hi: 0x9a}, - {value: 0x0004, lo: 0x9b, hi: 0x9e}, - // Block 0x71, offset 0x2fe - {value: 0x0004, lo: 0xbc, hi: 0xbe}, - // Block 0x72, offset 0x2ff - {value: 0x0010, lo: 0x85, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x73, offset 0x301 - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x74, offset 0x303 - {value: 0x0010, lo: 0x80, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0xbf}, - // Block 0x75, offset 0x306 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - // Block 0x76, offset 0x307 - {value: 0x0010, lo: 0x90, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x77, offset 0x309 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0xab}, - // Block 0x78, offset 0x30c - {value: 0x0117, lo: 0x80, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb2}, - {value: 0x0024, lo: 0xb4, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x79, offset 0x312 - {value: 0x0117, lo: 0x80, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9d}, - {value: 0x0024, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x7a, offset 0x316 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb1}, - // Block 0x7b, offset 0x318 - {value: 0x0004, lo: 0x80, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xaf}, - {value: 0x0012, lo: 0xb0, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xbf}, - // Block 0x7c, offset 0x31d - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x0015, lo: 0xb0, hi: 0xb0}, - {value: 0x0012, lo: 0xb1, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x8753, lo: 0xbd, hi: 0xbd}, - {value: 0x0117, lo: 0xbe, hi: 0xbf}, - // Block 0x7d, offset 0x324 - {value: 0x0117, lo: 0x80, hi: 0x83}, - {value: 0x6553, lo: 0x84, hi: 0x84}, - {value: 0x908b, lo: 0x85, hi: 0x85}, - {value: 0x8f53, lo: 0x86, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0117, lo: 0x90, hi: 0x91}, - {value: 0x0012, lo: 0x93, hi: 0x93}, - {value: 0x0012, lo: 0x95, hi: 0x95}, - {value: 0x0117, lo: 0x96, hi: 0x99}, - {value: 0x0015, lo: 0xb2, hi: 0xb4}, - {value: 0x0316, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbf}, - // Block 0x7e, offset 0x334 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x8c, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - // Block 0x7f, offset 0x33e - {value: 0x0010, lo: 0x80, hi: 0xb3}, - // Block 0x80, offset 0x33f - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xa0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb7}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x81, offset 0x348 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x82, offset 0x34c - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0x92}, - {value: 0x0030, lo: 0x93, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0x83, offset 0x351 - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x84, offset 0x359 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0004, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x85, offset 0x35f - {value: 0x0010, lo: 0x80, hi: 0xa8}, - {value: 0x0014, lo: 0xa9, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0x86, offset 0x365 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x87, offset 0x36f - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0024, lo: 0xbe, hi: 0xbf}, - // Block 0x88, offset 0x374 - {value: 0x0024, lo: 0x81, hi: 0x81}, - {value: 0x0004, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - // Block 0x89, offset 0x37d - {value: 0x0010, lo: 0x81, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x8e}, - {value: 0x0010, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x8a, offset 0x383 - {value: 0x0012, lo: 0x80, hi: 0x92}, - {value: 0xb352, lo: 0x93, hi: 0x93}, - {value: 0x0012, lo: 0x94, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa8}, - {value: 0x0015, lo: 0xa9, hi: 0xa9}, - {value: 0x0004, lo: 0xaa, hi: 0xab}, - {value: 0x74d2, lo: 0xb0, hi: 0xbf}, - // Block 0x8b, offset 0x38c - {value: 0x78d2, lo: 0x80, hi: 0x8f}, - {value: 0x7cd2, lo: 0x90, hi: 0x9f}, - {value: 0x80d2, lo: 0xa0, hi: 0xaf}, - {value: 0x7cd2, lo: 0xb0, hi: 0xbf}, - // Block 0x8c, offset 0x390 - {value: 0x0010, lo: 0x80, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x8d, offset 0x398 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x8e, offset 0x39a - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x8b, hi: 0xbb}, - // Block 0x8f, offset 0x39c - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0xbf}, - // Block 0x90, offset 0x39f - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0004, lo: 0xb2, hi: 0xbf}, - // Block 0x91, offset 0x3a1 - {value: 0x0004, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x93, hi: 0xbf}, - // Block 0x92, offset 0x3a3 - {value: 0x0010, lo: 0x80, hi: 0xbd}, - // Block 0x93, offset 0x3a4 - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0x94, offset 0x3a5 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0xbf}, - // Block 0x95, offset 0x3a7 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0xb0, hi: 0xbb}, - // Block 0x96, offset 0x3a9 - {value: 0x0014, lo: 0x80, hi: 0x8f}, - {value: 0x0054, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0xa0, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xad}, - {value: 0x0024, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - // Block 0x97, offset 0x3af - {value: 0x0010, lo: 0x8d, hi: 0x8f}, - {value: 0x0054, lo: 0x92, hi: 0x92}, - {value: 0x0054, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0xb0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0x98, offset 0x3b4 - {value: 0x0010, lo: 0x80, hi: 0xbc}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x99, offset 0x3b6 - {value: 0x0054, lo: 0x87, hi: 0x87}, - {value: 0x0054, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0054, lo: 0x9a, hi: 0x9a}, - {value: 0x5f53, lo: 0xa1, hi: 0xba}, - {value: 0x0004, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9a, offset 0x3bd - {value: 0x0004, lo: 0x80, hi: 0x80}, - {value: 0x5f52, lo: 0x81, hi: 0x9a}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - // Block 0x9b, offset 0x3c0 - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbe}, - // Block 0x9c, offset 0x3c2 - {value: 0x0010, lo: 0x82, hi: 0x87}, - {value: 0x0010, lo: 0x8a, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0x97}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0004, lo: 0xa3, hi: 0xa3}, - {value: 0x0014, lo: 0xb9, hi: 0xbb}, - // Block 0x9d, offset 0x3c8 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0010, lo: 0x8d, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xba}, - {value: 0x0010, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9e, offset 0x3cd - {value: 0x0010, lo: 0x80, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x9d}, - // Block 0x9f, offset 0x3cf - {value: 0x0010, lo: 0x80, hi: 0xba}, - // Block 0xa0, offset 0x3d0 - {value: 0x0010, lo: 0x80, hi: 0xb4}, - // Block 0xa1, offset 0x3d1 - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0xa2, offset 0x3d2 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa3, offset 0x3d4 - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - // Block 0xa4, offset 0x3d6 - {value: 0x0010, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xad, hi: 0xbf}, - // Block 0xa5, offset 0x3d8 - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0xb5}, - {value: 0x0024, lo: 0xb6, hi: 0xba}, - // Block 0xa6, offset 0x3db - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa7, offset 0x3dd - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x91, hi: 0x95}, - // Block 0xa8, offset 0x3e0 - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x97}, - {value: 0xb653, lo: 0x98, hi: 0x9f}, - {value: 0xb953, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbf}, - // Block 0xa9, offset 0x3e8 - {value: 0xb652, lo: 0x80, hi: 0x87}, - {value: 0xb952, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xaa, offset 0x3eb - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0xb953, lo: 0xb0, hi: 0xb7}, - {value: 0xb653, lo: 0xb8, hi: 0xbf}, - // Block 0xab, offset 0x3ef - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x93}, - {value: 0xb952, lo: 0x98, hi: 0x9f}, - {value: 0xb652, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbb}, - // Block 0xac, offset 0x3f7 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xad, offset 0x3f9 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0xbc53, lo: 0xb0, hi: 0xb0}, - {value: 0xbf53, lo: 0xb1, hi: 0xb1}, - {value: 0xc253, lo: 0xb2, hi: 0xb2}, - {value: 0xbf53, lo: 0xb3, hi: 0xb3}, - {value: 0xc553, lo: 0xb4, hi: 0xb4}, - {value: 0xbf53, lo: 0xb5, hi: 0xb5}, - {value: 0xc253, lo: 0xb6, hi: 0xb6}, - {value: 0xbf53, lo: 0xb7, hi: 0xb7}, - {value: 0xbc53, lo: 0xb8, hi: 0xb8}, - {value: 0xc853, lo: 0xb9, hi: 0xb9}, - {value: 0xcb53, lo: 0xba, hi: 0xba}, - {value: 0xce53, lo: 0xbc, hi: 0xbc}, - {value: 0xc853, lo: 0xbd, hi: 0xbd}, - {value: 0xcb53, lo: 0xbe, hi: 0xbe}, - {value: 0xc853, lo: 0xbf, hi: 0xbf}, - // Block 0xae, offset 0x409 - {value: 0x0010, lo: 0x80, hi: 0xb6}, - // Block 0xaf, offset 0x40a - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - // Block 0xb0, offset 0x40c - {value: 0x0015, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0015, lo: 0x83, hi: 0x85}, - {value: 0x0015, lo: 0x87, hi: 0xb0}, - {value: 0x0015, lo: 0xb2, hi: 0xba}, - // Block 0xb1, offset 0x411 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xb2, offset 0x417 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xb3, offset 0x419 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - // Block 0xb4, offset 0x41a - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - // Block 0xb5, offset 0x41c - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb9}, - // Block 0xb6, offset 0x41e - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0xb7, offset 0x420 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x8e, hi: 0x8e}, - {value: 0x0024, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x99, hi: 0xb5}, - {value: 0x0024, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xb8, offset 0x42d - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0xb9, offset 0x42e - {value: 0x0010, lo: 0x80, hi: 0x9c}, - // Block 0xba, offset 0x42f - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - // Block 0xbb, offset 0x433 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - // Block 0xbc, offset 0x435 - {value: 0x0010, lo: 0x80, hi: 0x91}, - // Block 0xbd, offset 0x436 - {value: 0x0010, lo: 0x80, hi: 0x88}, - // Block 0xbe, offset 0x437 - {value: 0x5653, lo: 0x80, hi: 0xb2}, - // Block 0xbf, offset 0x438 - {value: 0x5652, lo: 0x80, hi: 0xb2}, - // Block 0xc0, offset 0x439 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc1, offset 0x43c - {value: 0x0010, lo: 0x80, hi: 0xa9}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - // Block 0xc2, offset 0x43f - {value: 0x0034, lo: 0xbd, hi: 0xbf}, - // Block 0xc3, offset 0x440 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xc4, offset 0x443 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x87}, - {value: 0x0024, lo: 0x88, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x8b}, - {value: 0x0024, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xc5, offset 0x44a - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0024, lo: 0x82, hi: 0x82}, - {value: 0x0034, lo: 0x83, hi: 0x83}, - {value: 0x0024, lo: 0x84, hi: 0x84}, - {value: 0x0034, lo: 0x85, hi: 0x85}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xc6, offset 0x450 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xc7, offset 0x452 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xc8, offset 0x456 - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xc9, offset 0x45e - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - // Block 0xca, offset 0x464 - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xcb, offset 0x468 - {value: 0x0024, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0xcc, offset 0x46f - {value: 0x0010, lo: 0x84, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - // Block 0xcd, offset 0x473 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xce, offset 0x477 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x89, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - // Block 0xcf, offset 0x480 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb4}, - {value: 0x0030, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xb7}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xd0, offset 0x48a - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - // Block 0xd1, offset 0x48c - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xd2, offset 0x492 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa2}, - {value: 0x0014, lo: 0xa3, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xd3, offset 0x498 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xd4, offset 0x4a2 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0030, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9d, hi: 0xa3}, - {value: 0x0024, lo: 0xa6, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - // Block 0xd5, offset 0x4ac - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xd6, offset 0x4ae - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - // Block 0xd7, offset 0x4b7 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xd8, offset 0x4bd - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd9, offset 0x4c3 - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xda, offset 0x4c9 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x98, hi: 0x9b}, - {value: 0x0014, lo: 0x9c, hi: 0x9d}, - // Block 0xdb, offset 0x4cc - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xdc, offset 0x4d2 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xdd, offset 0x4d5 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0014, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb5}, - {value: 0x0030, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - // Block 0xde, offset 0x4de - {value: 0x0010, lo: 0x80, hi: 0x89}, - // Block 0xdf, offset 0x4df - {value: 0x0014, lo: 0x9d, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xe0, offset 0x4e6 - {value: 0x0010, lo: 0x80, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - // Block 0xe1, offset 0x4ea - {value: 0x5f53, lo: 0xa0, hi: 0xbf}, - // Block 0xe2, offset 0x4eb - {value: 0x5f52, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xe3, offset 0x4ee - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8c, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - {value: 0x0030, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xe4, offset 0x4f8 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0034, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xe5, offset 0x4fb - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - {value: 0x0010, lo: 0xaa, hi: 0xbf}, - // Block 0xe6, offset 0x4fd - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0014, lo: 0x94, hi: 0x97}, - {value: 0x0014, lo: 0x9a, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0x9f}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - // Block 0xe7, offset 0x504 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x8a}, - {value: 0x0010, lo: 0x8b, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbb, hi: 0xbe}, - // Block 0xe8, offset 0x50c - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0014, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x98}, - {value: 0x0014, lo: 0x99, hi: 0x9b}, - {value: 0x0010, lo: 0x9c, hi: 0xbf}, - // Block 0xe9, offset 0x512 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0014, lo: 0x8a, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x99}, - {value: 0x0010, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xea, offset 0x519 - {value: 0x0010, lo: 0x80, hi: 0xb8}, - // Block 0xeb, offset 0x51a - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xec, offset 0x520 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0xed, offset 0x523 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0014, lo: 0x92, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xa9}, - {value: 0x0014, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0xee, offset 0x52b - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb6}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xef, offset 0x532 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa5}, - {value: 0x0010, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xbf}, - // Block 0xf0, offset 0x53c - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0014, lo: 0x90, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0x96}, - {value: 0x0034, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xf1, offset 0x544 - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - // Block 0xf2, offset 0x547 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xba}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0xf3, offset 0x54c - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0030, lo: 0x81, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xf4, offset 0x550 - {value: 0x0010, lo: 0xb0, hi: 0xb0}, - // Block 0xf5, offset 0x551 - {value: 0x0010, lo: 0x80, hi: 0x99}, - // Block 0xf6, offset 0x552 - {value: 0x0010, lo: 0x80, hi: 0xae}, - // Block 0xf7, offset 0x553 - {value: 0x0010, lo: 0x80, hi: 0x83}, - // Block 0xf8, offset 0x554 - {value: 0x0010, lo: 0x80, hi: 0xb0}, - // Block 0xf9, offset 0x555 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xbf}, - // Block 0xfa, offset 0x557 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x95}, - // Block 0xfb, offset 0x55a - {value: 0x0010, lo: 0x80, hi: 0x86}, - // Block 0xfc, offset 0x55b - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xfd, offset 0x55e - {value: 0x0010, lo: 0x80, hi: 0xbe}, - // Block 0xfe, offset 0x55f - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x90, hi: 0xad}, - {value: 0x0034, lo: 0xb0, hi: 0xb4}, - // Block 0xff, offset 0x562 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - // Block 0x100, offset 0x564 - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa3, hi: 0xb7}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x101, offset 0x568 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - // Block 0x102, offset 0x569 - {value: 0x2013, lo: 0x80, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xbf}, - // Block 0x103, offset 0x56b - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0x104, offset 0x56e - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0014, lo: 0x8f, hi: 0x9f}, - // Block 0x105, offset 0x570 - {value: 0x0014, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa3, hi: 0xa4}, - {value: 0x0030, lo: 0xb0, hi: 0xb1}, - // Block 0x106, offset 0x573 - {value: 0x0004, lo: 0xb0, hi: 0xb3}, - {value: 0x0004, lo: 0xb5, hi: 0xbb}, - {value: 0x0004, lo: 0xbd, hi: 0xbe}, - // Block 0x107, offset 0x576 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbc}, - // Block 0x108, offset 0x578 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0034, lo: 0x9e, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa3}, - // Block 0x109, offset 0x57d - {value: 0x0014, lo: 0x80, hi: 0xad}, - {value: 0x0014, lo: 0xb0, hi: 0xbf}, - // Block 0x10a, offset 0x57f - {value: 0x0014, lo: 0x80, hi: 0x86}, - // Block 0x10b, offset 0x580 - {value: 0x0030, lo: 0xa5, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xa9}, - {value: 0x0030, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbf}, - // Block 0x10c, offset 0x585 - {value: 0x0034, lo: 0x80, hi: 0x82}, - {value: 0x0024, lo: 0x85, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8b}, - {value: 0x0024, lo: 0xaa, hi: 0xad}, - // Block 0x10d, offset 0x589 - {value: 0x0024, lo: 0x82, hi: 0x84}, - // Block 0x10e, offset 0x58a - {value: 0x0013, lo: 0x80, hi: 0x99}, - {value: 0x0012, lo: 0x9a, hi: 0xb3}, - {value: 0x0013, lo: 0xb4, hi: 0xbf}, - // Block 0x10f, offset 0x58d - {value: 0x0013, lo: 0x80, hi: 0x8d}, - {value: 0x0012, lo: 0x8e, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0xa7}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x110, offset 0x591 - {value: 0x0013, lo: 0x80, hi: 0x81}, - {value: 0x0012, lo: 0x82, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0x9c}, - {value: 0x0013, lo: 0x9e, hi: 0x9f}, - {value: 0x0013, lo: 0xa2, hi: 0xa2}, - {value: 0x0013, lo: 0xa5, hi: 0xa6}, - {value: 0x0013, lo: 0xa9, hi: 0xac}, - {value: 0x0013, lo: 0xae, hi: 0xb5}, - {value: 0x0012, lo: 0xb6, hi: 0xb9}, - {value: 0x0012, lo: 0xbb, hi: 0xbb}, - {value: 0x0012, lo: 0xbd, hi: 0xbf}, - // Block 0x111, offset 0x59c - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0012, lo: 0x85, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x112, offset 0x5a0 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0013, lo: 0x84, hi: 0x85}, - {value: 0x0013, lo: 0x87, hi: 0x8a}, - {value: 0x0013, lo: 0x8d, hi: 0x94}, - {value: 0x0013, lo: 0x96, hi: 0x9c}, - {value: 0x0012, lo: 0x9e, hi: 0xb7}, - {value: 0x0013, lo: 0xb8, hi: 0xb9}, - {value: 0x0013, lo: 0xbb, hi: 0xbe}, - // Block 0x113, offset 0x5a8 - {value: 0x0013, lo: 0x80, hi: 0x84}, - {value: 0x0013, lo: 0x86, hi: 0x86}, - {value: 0x0013, lo: 0x8a, hi: 0x90}, - {value: 0x0012, lo: 0x92, hi: 0xab}, - {value: 0x0013, lo: 0xac, hi: 0xbf}, - // Block 0x114, offset 0x5ad - {value: 0x0013, lo: 0x80, hi: 0x85}, - {value: 0x0012, lo: 0x86, hi: 0x9f}, - {value: 0x0013, lo: 0xa0, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbf}, - // Block 0x115, offset 0x5b1 - {value: 0x0012, lo: 0x80, hi: 0x93}, - {value: 0x0013, lo: 0x94, hi: 0xad}, - {value: 0x0012, lo: 0xae, hi: 0xbf}, - // Block 0x116, offset 0x5b4 - {value: 0x0012, lo: 0x80, hi: 0x87}, - {value: 0x0013, lo: 0x88, hi: 0xa1}, - {value: 0x0012, lo: 0xa2, hi: 0xbb}, - {value: 0x0013, lo: 0xbc, hi: 0xbf}, - // Block 0x117, offset 0x5b8 - {value: 0x0013, lo: 0x80, hi: 0x95}, - {value: 0x0012, lo: 0x96, hi: 0xaf}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x118, offset 0x5bb - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0012, lo: 0x8a, hi: 0xa5}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0x119, offset 0x5be - {value: 0x0013, lo: 0x80, hi: 0x80}, - {value: 0x0012, lo: 0x82, hi: 0x9a}, - {value: 0x0012, lo: 0x9c, hi: 0xa1}, - {value: 0x0013, lo: 0xa2, hi: 0xba}, - {value: 0x0012, lo: 0xbc, hi: 0xbf}, - // Block 0x11a, offset 0x5c3 - {value: 0x0012, lo: 0x80, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0xb4}, - {value: 0x0012, lo: 0xb6, hi: 0xbf}, - // Block 0x11b, offset 0x5c7 - {value: 0x0012, lo: 0x80, hi: 0x8e}, - {value: 0x0012, lo: 0x90, hi: 0x95}, - {value: 0x0013, lo: 0x96, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x11c, offset 0x5cb - {value: 0x0012, lo: 0x80, hi: 0x88}, - {value: 0x0012, lo: 0x8a, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0x11d, offset 0x5cf - {value: 0x0012, lo: 0x80, hi: 0x82}, - {value: 0x0012, lo: 0x84, hi: 0x89}, - {value: 0x0017, lo: 0x8a, hi: 0x8b}, - {value: 0x0010, lo: 0x8e, hi: 0xbf}, - // Block 0x11e, offset 0x5d3 - {value: 0x0014, lo: 0x80, hi: 0xb6}, - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x11f, offset 0x5d5 - {value: 0x0014, lo: 0x80, hi: 0xac}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x120, offset 0x5d7 - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x9b, hi: 0x9f}, - {value: 0x0014, lo: 0xa1, hi: 0xaf}, - // Block 0x121, offset 0x5da - {value: 0x0012, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8a, hi: 0x8a}, - {value: 0x0012, lo: 0x8b, hi: 0x9e}, - {value: 0x0012, lo: 0xa5, hi: 0xaa}, - // Block 0x122, offset 0x5de - {value: 0x0024, lo: 0x80, hi: 0x86}, - {value: 0x0024, lo: 0x88, hi: 0x98}, - {value: 0x0024, lo: 0x9b, hi: 0xa1}, - {value: 0x0024, lo: 0xa3, hi: 0xa4}, - {value: 0x0024, lo: 0xa6, hi: 0xaa}, - {value: 0x0015, lo: 0xb0, hi: 0xbf}, - // Block 0x123, offset 0x5e4 - {value: 0x0015, lo: 0x80, hi: 0xad}, - // Block 0x124, offset 0x5e5 - {value: 0x0024, lo: 0x8f, hi: 0x8f}, - // Block 0x125, offset 0x5e6 - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - // Block 0x126, offset 0x5e9 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - // Block 0x127, offset 0x5eb - {value: 0x0010, lo: 0x90, hi: 0xad}, - {value: 0x0024, lo: 0xae, hi: 0xae}, - // Block 0x128, offset 0x5ed - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0024, lo: 0xac, hi: 0xaf}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x129, offset 0x5f0 - {value: 0x0010, lo: 0x90, hi: 0xaa}, - {value: 0x0014, lo: 0xab, hi: 0xab}, - {value: 0x0034, lo: 0xac, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x12a, offset 0x5f5 - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xab}, - {value: 0x0010, lo: 0xad, hi: 0xae}, - {value: 0x0010, lo: 0xb0, hi: 0xbe}, - // Block 0x12b, offset 0x5f9 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0034, lo: 0x90, hi: 0x96}, - // Block 0x12c, offset 0x5fb - {value: 0xd152, lo: 0x80, hi: 0x81}, - {value: 0xd452, lo: 0x82, hi: 0x83}, - {value: 0x0024, lo: 0x84, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x12d, offset 0x601 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x9f}, - {value: 0x0010, lo: 0xa1, hi: 0xa2}, - {value: 0x0010, lo: 0xa4, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb7}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - // Block 0x12e, offset 0x60a - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x9b}, - {value: 0x0010, lo: 0xa1, hi: 0xa3}, - {value: 0x0010, lo: 0xa5, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xbb}, - // Block 0x12f, offset 0x60f - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x130, offset 0x610 - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x131, offset 0x613 - {value: 0x0013, lo: 0x80, hi: 0x89}, - // Block 0x132, offset 0x614 - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x133, offset 0x615 - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x134, offset 0x616 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0014, lo: 0xa0, hi: 0xbf}, - // Block 0x135, offset 0x618 - {value: 0x0014, lo: 0x80, hi: 0xbf}, - // Block 0x136, offset 0x619 - {value: 0x0014, lo: 0x80, hi: 0xaf}, -} - -// Total table size 16093 bytes (15KiB); checksum: EE91C452 diff --git a/vendor/golang.org/x/text/cases/tables9.0.0.go b/vendor/golang.org/x/text/cases/tables9.0.0.go deleted file mode 100644 index 3aeb7be6..00000000 --- a/vendor/golang.org/x/text/cases/tables9.0.0.go +++ /dev/null @@ -1,2215 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -//go:build !go1.10 - -package cases - -// UnicodeVersion is the Unicode version from which the tables in this package are derived. -const UnicodeVersion = "9.0.0" - -var xorData string = "" + // Size: 185 bytes - "\x00\x06\x07\x00\x01?\x00\x0f\x03\x00\x0f\x12\x00\x0f\x1f\x00\x0f\x1d" + - "\x00\x01\x13\x00\x0f\x16\x00\x0f\x0b\x00\x0f3\x00\x0f7\x00\x01#\x00\x0f?" + - "\x00\x0e'\x00\x0f/\x00\x0e>\x00\x0f*\x00\x0c&\x00\x0c*\x00\x0c;\x00\x0c9" + - "\x00\x0c%\x00\x01\x08\x00\x03\x0d\x00\x03\x09\x00\x02\x06\x00\x02\x02" + - "\x00\x02\x0c\x00\x01\x00\x00\x01\x03\x00\x01\x01\x00\x01 \x00\x01\x0c" + - "\x00\x01\x10\x00\x03\x10\x00\x036 \x00\x037 \x00\x0b#\x10\x00\x0b 0\x00" + - "\x0b!\x10\x00\x0b!0\x00\x0b(\x04\x00\x03\x04\x1e\x00\x03\x0a\x00\x02:" + - "\x00\x02>\x00\x02,\x00\x02\x00\x00\x02\x10\x00\x01<\x00\x01&\x00\x01*" + - "\x00\x01.\x00\x010\x003 \x00\x01\x18\x00\x01(\x00\x01\x1e\x00\x01\x22" - -var exceptions string = "" + // Size: 2068 bytes - "\x00\x12\x12μΜΜ\x12\x12ssSSSs\x13\x18i̇i̇\x10\x09II\x13\x1bʼnʼNʼN\x11" + - "\x09sSS\x12\x12dždžDž\x12\x12dždžDŽ\x10\x12DŽDž\x12\x12ljljLj\x12\x12ljljLJ\x10\x12LJLj" + - "\x12\x12njnjNj\x12\x12njnjNJ\x10\x12NJNj\x13\x1bǰJ̌J̌\x12\x12dzdzDz\x12\x12dzdzDZ\x10" + - "\x12DZDz\x13\x18ⱥⱥ\x13\x18ⱦⱦ\x10\x1bⱾⱾ\x10\x1bⱿⱿ\x10\x1bⱯⱯ\x10\x1bⱭⱭ\x10" + - "\x1bⱰⱰ\x10\x1bꞫꞫ\x10\x1bꞬꞬ\x10\x1bꞍꞍ\x10\x1bꞪꞪ\x10\x1bꞮꞮ\x10\x1bⱢⱢ\x10" + - "\x1bꞭꞭ\x10\x1bⱮⱮ\x10\x1bⱤⱤ\x10\x1bꞱꞱ\x10\x1bꞲꞲ\x10\x1bꞰꞰ2\x12ιΙΙ\x166ΐ" + - "Ϊ́Ϊ́\x166ΰΫ́Ϋ́\x12\x12σΣΣ\x12\x12βΒΒ\x12\x12θΘΘ\x12\x12φΦΦ\x12" + - "\x12πΠΠ\x12\x12κΚΚ\x12\x12ρΡΡ\x12\x12εΕΕ\x14$եւԵՒԵւ\x12\x12вВВ\x12\x12дД" + - "Д\x12\x12оОО\x12\x12сСС\x12\x12тТТ\x12\x12тТТ\x12\x12ъЪЪ\x12\x12ѣѢѢ\x13" + - "\x1bꙋꙊꙊ\x13\x1bẖH̱H̱\x13\x1bẗT̈T̈\x13\x1bẘW̊W̊\x13\x1bẙY̊Y̊\x13\x1ba" + - "ʾAʾAʾ\x13\x1bṡṠṠ\x12\x10ssß\x14$ὐΥ̓Υ̓\x166ὒΥ̓̀Υ̓̀\x166ὔΥ̓́Υ̓́\x166" + - "ὖΥ̓͂Υ̓͂\x15+ἀιἈΙᾈ\x15+ἁιἉΙᾉ\x15+ἂιἊΙᾊ\x15+ἃιἋΙᾋ\x15+ἄιἌΙᾌ\x15+ἅιἍΙᾍ" + - "\x15+ἆιἎΙᾎ\x15+ἇιἏΙᾏ\x15\x1dἀιᾀἈΙ\x15\x1dἁιᾁἉΙ\x15\x1dἂιᾂἊΙ\x15\x1dἃιᾃἋΙ" + - "\x15\x1dἄιᾄἌΙ\x15\x1dἅιᾅἍΙ\x15\x1dἆιᾆἎΙ\x15\x1dἇιᾇἏΙ\x15+ἠιἨΙᾘ\x15+ἡιἩΙᾙ" + - "\x15+ἢιἪΙᾚ\x15+ἣιἫΙᾛ\x15+ἤιἬΙᾜ\x15+ἥιἭΙᾝ\x15+ἦιἮΙᾞ\x15+ἧιἯΙᾟ\x15\x1dἠιᾐἨ" + - "Ι\x15\x1dἡιᾑἩΙ\x15\x1dἢιᾒἪΙ\x15\x1dἣιᾓἫΙ\x15\x1dἤιᾔἬΙ\x15\x1dἥιᾕἭΙ\x15" + - "\x1dἦιᾖἮΙ\x15\x1dἧιᾗἯΙ\x15+ὠιὨΙᾨ\x15+ὡιὩΙᾩ\x15+ὢιὪΙᾪ\x15+ὣιὫΙᾫ\x15+ὤιὬΙᾬ" + - "\x15+ὥιὭΙᾭ\x15+ὦιὮΙᾮ\x15+ὧιὯΙᾯ\x15\x1dὠιᾠὨΙ\x15\x1dὡιᾡὩΙ\x15\x1dὢιᾢὪΙ" + - "\x15\x1dὣιᾣὫΙ\x15\x1dὤιᾤὬΙ\x15\x1dὥιᾥὭΙ\x15\x1dὦιᾦὮΙ\x15\x1dὧιᾧὯΙ\x15-ὰι" + - "ᾺΙᾺͅ\x14#αιΑΙᾼ\x14$άιΆΙΆͅ\x14$ᾶΑ͂Α͂\x166ᾶιΑ͂Ιᾼ͂\x14\x1cαιᾳΑΙ\x12" + - "\x12ιΙΙ\x15-ὴιῊΙῊͅ\x14#ηιΗΙῌ\x14$ήιΉΙΉͅ\x14$ῆΗ͂Η͂\x166ῆιΗ͂Ιῌ͂\x14\x1c" + - "ηιῃΗΙ\x166ῒΪ̀Ϊ̀\x166ΐΪ́Ϊ́\x14$ῖΙ͂Ι͂\x166ῗΪ͂Ϊ͂\x166ῢΫ̀Ϋ" + - "̀\x166ΰΫ́Ϋ́\x14$ῤΡ̓Ρ̓\x14$ῦΥ͂Υ͂\x166ῧΫ͂Ϋ͂\x15-ὼιῺΙῺͅ\x14#ωιΩΙ" + - "ῼ\x14$ώιΏΙΏͅ\x14$ῶΩ͂Ω͂\x166ῶιΩ͂Ιῼ͂\x14\x1cωιῳΩΙ\x12\x10ωω\x11\x08kk" + - "\x12\x10åå\x12\x10ɫɫ\x12\x10ɽɽ\x10\x12ȺȺ\x10\x12ȾȾ\x12\x10ɑɑ\x12\x10ɱɱ" + - "\x12\x10ɐɐ\x12\x10ɒɒ\x12\x10ȿȿ\x12\x10ɀɀ\x12\x10ɥɥ\x12\x10ɦɦ\x12\x10ɜɜ" + - "\x12\x10ɡɡ\x12\x10ɬɬ\x12\x10ɪɪ\x12\x10ʞʞ\x12\x10ʇʇ\x12\x10ʝʝ\x12\x12ffFF" + - "Ff\x12\x12fiFIFi\x12\x12flFLFl\x13\x1bffiFFIFfi\x13\x1bfflFFLFfl\x12\x12" + - "stSTSt\x12\x12stSTSt\x14$մնՄՆՄն\x14$մեՄԵՄե\x14$միՄԻՄի\x14$վնՎՆՎն\x14$մխՄ" + - "ԽՄխ" - -// lookup returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookup(s []byte) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupUnsafe(s []byte) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// lookupString returns the trie value for the first UTF-8 encoding in s and -// the width in bytes of this encoding. The size will be 0 if s does not -// hold enough bytes to complete the encoding. len(s) must be greater than 0. -func (t *caseTrie) lookupString(s string) (v uint16, sz int) { - c0 := s[0] - switch { - case c0 < 0x80: // is ASCII - return caseValues[c0], 1 - case c0 < 0xC2: - return 0, 1 // Illegal UTF-8: not a starter, not ASCII. - case c0 < 0xE0: // 2-byte UTF-8 - if len(s) < 2 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c1), 2 - case c0 < 0xF0: // 3-byte UTF-8 - if len(s) < 3 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c2), 3 - case c0 < 0xF8: // 4-byte UTF-8 - if len(s) < 4 { - return 0, 0 - } - i := caseIndex[c0] - c1 := s[1] - if c1 < 0x80 || 0xC0 <= c1 { - return 0, 1 // Illegal UTF-8: not a continuation byte. - } - o := uint32(i)<<6 + uint32(c1) - i = caseIndex[o] - c2 := s[2] - if c2 < 0x80 || 0xC0 <= c2 { - return 0, 2 // Illegal UTF-8: not a continuation byte. - } - o = uint32(i)<<6 + uint32(c2) - i = caseIndex[o] - c3 := s[3] - if c3 < 0x80 || 0xC0 <= c3 { - return 0, 3 // Illegal UTF-8: not a continuation byte. - } - return t.lookupValue(uint32(i), c3), 4 - } - // Illegal rune - return 0, 1 -} - -// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. -// s must start with a full and valid UTF-8 encoded rune. -func (t *caseTrie) lookupStringUnsafe(s string) uint16 { - c0 := s[0] - if c0 < 0x80 { // is ASCII - return caseValues[c0] - } - i := caseIndex[c0] - if c0 < 0xE0 { // 2-byte UTF-8 - return t.lookupValue(uint32(i), s[1]) - } - i = caseIndex[uint32(i)<<6+uint32(s[1])] - if c0 < 0xF0 { // 3-byte UTF-8 - return t.lookupValue(uint32(i), s[2]) - } - i = caseIndex[uint32(i)<<6+uint32(s[2])] - if c0 < 0xF8 { // 4-byte UTF-8 - return t.lookupValue(uint32(i), s[3]) - } - return 0 -} - -// caseTrie. Total size: 11742 bytes (11.47 KiB). Checksum: 795fe57ee5135873. -type caseTrie struct{} - -func newCaseTrie(i int) *caseTrie { - return &caseTrie{} -} - -// lookupValue determines the type of block n and looks up the value for b. -func (t *caseTrie) lookupValue(n uint32, b byte) uint16 { - switch { - case n < 18: - return uint16(caseValues[n<<6+uint32(b)]) - default: - n -= 18 - return uint16(sparse.lookup(n, b)) - } -} - -// caseValues: 20 blocks, 1280 entries, 2560 bytes -// The third block is the zero block. -var caseValues = [1280]uint16{ - // Block 0x0, offset 0x0 - 0x27: 0x0054, - 0x2e: 0x0054, - 0x30: 0x0010, 0x31: 0x0010, 0x32: 0x0010, 0x33: 0x0010, 0x34: 0x0010, 0x35: 0x0010, - 0x36: 0x0010, 0x37: 0x0010, 0x38: 0x0010, 0x39: 0x0010, 0x3a: 0x0054, - // Block 0x1, offset 0x40 - 0x41: 0x2013, 0x42: 0x2013, 0x43: 0x2013, 0x44: 0x2013, 0x45: 0x2013, - 0x46: 0x2013, 0x47: 0x2013, 0x48: 0x2013, 0x49: 0x2013, 0x4a: 0x2013, 0x4b: 0x2013, - 0x4c: 0x2013, 0x4d: 0x2013, 0x4e: 0x2013, 0x4f: 0x2013, 0x50: 0x2013, 0x51: 0x2013, - 0x52: 0x2013, 0x53: 0x2013, 0x54: 0x2013, 0x55: 0x2013, 0x56: 0x2013, 0x57: 0x2013, - 0x58: 0x2013, 0x59: 0x2013, 0x5a: 0x2013, - 0x5e: 0x0004, 0x5f: 0x0010, 0x60: 0x0004, 0x61: 0x2012, 0x62: 0x2012, 0x63: 0x2012, - 0x64: 0x2012, 0x65: 0x2012, 0x66: 0x2012, 0x67: 0x2012, 0x68: 0x2012, 0x69: 0x2012, - 0x6a: 0x2012, 0x6b: 0x2012, 0x6c: 0x2012, 0x6d: 0x2012, 0x6e: 0x2012, 0x6f: 0x2012, - 0x70: 0x2012, 0x71: 0x2012, 0x72: 0x2012, 0x73: 0x2012, 0x74: 0x2012, 0x75: 0x2012, - 0x76: 0x2012, 0x77: 0x2012, 0x78: 0x2012, 0x79: 0x2012, 0x7a: 0x2012, - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc0: 0x0852, 0xc1: 0x0b53, 0xc2: 0x0113, 0xc3: 0x0112, 0xc4: 0x0113, 0xc5: 0x0112, - 0xc6: 0x0b53, 0xc7: 0x0f13, 0xc8: 0x0f12, 0xc9: 0x0e53, 0xca: 0x1153, 0xcb: 0x0713, - 0xcc: 0x0712, 0xcd: 0x0012, 0xce: 0x1453, 0xcf: 0x1753, 0xd0: 0x1a53, 0xd1: 0x0313, - 0xd2: 0x0312, 0xd3: 0x1d53, 0xd4: 0x2053, 0xd5: 0x2352, 0xd6: 0x2653, 0xd7: 0x2653, - 0xd8: 0x0113, 0xd9: 0x0112, 0xda: 0x2952, 0xdb: 0x0012, 0xdc: 0x1d53, 0xdd: 0x2c53, - 0xde: 0x2f52, 0xdf: 0x3253, 0xe0: 0x0113, 0xe1: 0x0112, 0xe2: 0x0113, 0xe3: 0x0112, - 0xe4: 0x0113, 0xe5: 0x0112, 0xe6: 0x3553, 0xe7: 0x0f13, 0xe8: 0x0f12, 0xe9: 0x3853, - 0xea: 0x0012, 0xeb: 0x0012, 0xec: 0x0113, 0xed: 0x0112, 0xee: 0x3553, 0xef: 0x1f13, - 0xf0: 0x1f12, 0xf1: 0x3b53, 0xf2: 0x3e53, 0xf3: 0x0713, 0xf4: 0x0712, 0xf5: 0x0313, - 0xf6: 0x0312, 0xf7: 0x4153, 0xf8: 0x0113, 0xf9: 0x0112, 0xfa: 0x0012, 0xfb: 0x0010, - 0xfc: 0x0113, 0xfd: 0x0112, 0xfe: 0x0012, 0xff: 0x4452, - // Block 0x4, offset 0x100 - 0x100: 0x0010, 0x101: 0x0010, 0x102: 0x0010, 0x103: 0x0010, 0x104: 0x02db, 0x105: 0x0359, - 0x106: 0x03da, 0x107: 0x043b, 0x108: 0x04b9, 0x109: 0x053a, 0x10a: 0x059b, 0x10b: 0x0619, - 0x10c: 0x069a, 0x10d: 0x0313, 0x10e: 0x0312, 0x10f: 0x1f13, 0x110: 0x1f12, 0x111: 0x0313, - 0x112: 0x0312, 0x113: 0x0713, 0x114: 0x0712, 0x115: 0x0313, 0x116: 0x0312, 0x117: 0x0f13, - 0x118: 0x0f12, 0x119: 0x0313, 0x11a: 0x0312, 0x11b: 0x0713, 0x11c: 0x0712, 0x11d: 0x1452, - 0x11e: 0x0113, 0x11f: 0x0112, 0x120: 0x0113, 0x121: 0x0112, 0x122: 0x0113, 0x123: 0x0112, - 0x124: 0x0113, 0x125: 0x0112, 0x126: 0x0113, 0x127: 0x0112, 0x128: 0x0113, 0x129: 0x0112, - 0x12a: 0x0113, 0x12b: 0x0112, 0x12c: 0x0113, 0x12d: 0x0112, 0x12e: 0x0113, 0x12f: 0x0112, - 0x130: 0x06fa, 0x131: 0x07ab, 0x132: 0x0829, 0x133: 0x08aa, 0x134: 0x0113, 0x135: 0x0112, - 0x136: 0x2353, 0x137: 0x4453, 0x138: 0x0113, 0x139: 0x0112, 0x13a: 0x0113, 0x13b: 0x0112, - 0x13c: 0x0113, 0x13d: 0x0112, 0x13e: 0x0113, 0x13f: 0x0112, - // Block 0x5, offset 0x140 - 0x140: 0x0a8a, 0x141: 0x0313, 0x142: 0x0312, 0x143: 0x0853, 0x144: 0x4753, 0x145: 0x4a53, - 0x146: 0x0113, 0x147: 0x0112, 0x148: 0x0113, 0x149: 0x0112, 0x14a: 0x0113, 0x14b: 0x0112, - 0x14c: 0x0113, 0x14d: 0x0112, 0x14e: 0x0113, 0x14f: 0x0112, 0x150: 0x0b0a, 0x151: 0x0b8a, - 0x152: 0x0c0a, 0x153: 0x0b52, 0x154: 0x0b52, 0x155: 0x0012, 0x156: 0x0e52, 0x157: 0x1152, - 0x158: 0x0012, 0x159: 0x1752, 0x15a: 0x0012, 0x15b: 0x1a52, 0x15c: 0x0c8a, 0x15d: 0x0012, - 0x15e: 0x0012, 0x15f: 0x0012, 0x160: 0x1d52, 0x161: 0x0d0a, 0x162: 0x0012, 0x163: 0x2052, - 0x164: 0x0012, 0x165: 0x0d8a, 0x166: 0x0e0a, 0x167: 0x0012, 0x168: 0x2652, 0x169: 0x2652, - 0x16a: 0x0e8a, 0x16b: 0x0f0a, 0x16c: 0x0f8a, 0x16d: 0x0012, 0x16e: 0x0012, 0x16f: 0x1d52, - 0x170: 0x0012, 0x171: 0x100a, 0x172: 0x2c52, 0x173: 0x0012, 0x174: 0x0012, 0x175: 0x3252, - 0x176: 0x0012, 0x177: 0x0012, 0x178: 0x0012, 0x179: 0x0012, 0x17a: 0x0012, 0x17b: 0x0012, - 0x17c: 0x0012, 0x17d: 0x108a, 0x17e: 0x0012, 0x17f: 0x0012, - // Block 0x6, offset 0x180 - 0x180: 0x3552, 0x181: 0x0012, 0x182: 0x0012, 0x183: 0x3852, 0x184: 0x0012, 0x185: 0x0012, - 0x186: 0x0012, 0x187: 0x110a, 0x188: 0x3552, 0x189: 0x4752, 0x18a: 0x3b52, 0x18b: 0x3e52, - 0x18c: 0x4a52, 0x18d: 0x0012, 0x18e: 0x0012, 0x18f: 0x0012, 0x190: 0x0012, 0x191: 0x0012, - 0x192: 0x4152, 0x193: 0x0012, 0x194: 0x0010, 0x195: 0x0012, 0x196: 0x0012, 0x197: 0x0012, - 0x198: 0x0012, 0x199: 0x0012, 0x19a: 0x0012, 0x19b: 0x0012, 0x19c: 0x0012, 0x19d: 0x118a, - 0x19e: 0x120a, 0x19f: 0x0012, 0x1a0: 0x0012, 0x1a1: 0x0012, 0x1a2: 0x0012, 0x1a3: 0x0012, - 0x1a4: 0x0012, 0x1a5: 0x0012, 0x1a6: 0x0012, 0x1a7: 0x0012, 0x1a8: 0x0012, 0x1a9: 0x0012, - 0x1aa: 0x0012, 0x1ab: 0x0012, 0x1ac: 0x0012, 0x1ad: 0x0012, 0x1ae: 0x0012, 0x1af: 0x0012, - 0x1b0: 0x0015, 0x1b1: 0x0015, 0x1b2: 0x0015, 0x1b3: 0x0015, 0x1b4: 0x0015, 0x1b5: 0x0015, - 0x1b6: 0x0015, 0x1b7: 0x0015, 0x1b8: 0x0015, 0x1b9: 0x0014, 0x1ba: 0x0014, 0x1bb: 0x0014, - 0x1bc: 0x0014, 0x1bd: 0x0014, 0x1be: 0x0014, 0x1bf: 0x0014, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x0024, 0x1c1: 0x0024, 0x1c2: 0x0024, 0x1c3: 0x0024, 0x1c4: 0x0024, 0x1c5: 0x128d, - 0x1c6: 0x0024, 0x1c7: 0x0034, 0x1c8: 0x0034, 0x1c9: 0x0034, 0x1ca: 0x0024, 0x1cb: 0x0024, - 0x1cc: 0x0024, 0x1cd: 0x0034, 0x1ce: 0x0034, 0x1cf: 0x0014, 0x1d0: 0x0024, 0x1d1: 0x0024, - 0x1d2: 0x0024, 0x1d3: 0x0034, 0x1d4: 0x0034, 0x1d5: 0x0034, 0x1d6: 0x0034, 0x1d7: 0x0024, - 0x1d8: 0x0034, 0x1d9: 0x0034, 0x1da: 0x0034, 0x1db: 0x0024, 0x1dc: 0x0034, 0x1dd: 0x0034, - 0x1de: 0x0034, 0x1df: 0x0034, 0x1e0: 0x0034, 0x1e1: 0x0034, 0x1e2: 0x0034, 0x1e3: 0x0024, - 0x1e4: 0x0024, 0x1e5: 0x0024, 0x1e6: 0x0024, 0x1e7: 0x0024, 0x1e8: 0x0024, 0x1e9: 0x0024, - 0x1ea: 0x0024, 0x1eb: 0x0024, 0x1ec: 0x0024, 0x1ed: 0x0024, 0x1ee: 0x0024, 0x1ef: 0x0024, - 0x1f0: 0x0113, 0x1f1: 0x0112, 0x1f2: 0x0113, 0x1f3: 0x0112, 0x1f4: 0x0014, 0x1f5: 0x0004, - 0x1f6: 0x0113, 0x1f7: 0x0112, 0x1fa: 0x0015, 0x1fb: 0x4d52, - 0x1fc: 0x5052, 0x1fd: 0x5052, 0x1ff: 0x5353, - // Block 0x8, offset 0x200 - 0x204: 0x0004, 0x205: 0x0004, - 0x206: 0x2a13, 0x207: 0x0054, 0x208: 0x2513, 0x209: 0x2713, 0x20a: 0x2513, - 0x20c: 0x5653, 0x20e: 0x5953, 0x20f: 0x5c53, 0x210: 0x130a, 0x211: 0x2013, - 0x212: 0x2013, 0x213: 0x2013, 0x214: 0x2013, 0x215: 0x2013, 0x216: 0x2013, 0x217: 0x2013, - 0x218: 0x2013, 0x219: 0x2013, 0x21a: 0x2013, 0x21b: 0x2013, 0x21c: 0x2013, 0x21d: 0x2013, - 0x21e: 0x2013, 0x21f: 0x2013, 0x220: 0x5f53, 0x221: 0x5f53, 0x223: 0x5f53, - 0x224: 0x5f53, 0x225: 0x5f53, 0x226: 0x5f53, 0x227: 0x5f53, 0x228: 0x5f53, 0x229: 0x5f53, - 0x22a: 0x5f53, 0x22b: 0x5f53, 0x22c: 0x2a12, 0x22d: 0x2512, 0x22e: 0x2712, 0x22f: 0x2512, - 0x230: 0x144a, 0x231: 0x2012, 0x232: 0x2012, 0x233: 0x2012, 0x234: 0x2012, 0x235: 0x2012, - 0x236: 0x2012, 0x237: 0x2012, 0x238: 0x2012, 0x239: 0x2012, 0x23a: 0x2012, 0x23b: 0x2012, - 0x23c: 0x2012, 0x23d: 0x2012, 0x23e: 0x2012, 0x23f: 0x2012, - // Block 0x9, offset 0x240 - 0x240: 0x5f52, 0x241: 0x5f52, 0x242: 0x158a, 0x243: 0x5f52, 0x244: 0x5f52, 0x245: 0x5f52, - 0x246: 0x5f52, 0x247: 0x5f52, 0x248: 0x5f52, 0x249: 0x5f52, 0x24a: 0x5f52, 0x24b: 0x5f52, - 0x24c: 0x5652, 0x24d: 0x5952, 0x24e: 0x5c52, 0x24f: 0x1813, 0x250: 0x160a, 0x251: 0x168a, - 0x252: 0x0013, 0x253: 0x0013, 0x254: 0x0013, 0x255: 0x170a, 0x256: 0x178a, 0x257: 0x1812, - 0x258: 0x0113, 0x259: 0x0112, 0x25a: 0x0113, 0x25b: 0x0112, 0x25c: 0x0113, 0x25d: 0x0112, - 0x25e: 0x0113, 0x25f: 0x0112, 0x260: 0x0113, 0x261: 0x0112, 0x262: 0x0113, 0x263: 0x0112, - 0x264: 0x0113, 0x265: 0x0112, 0x266: 0x0113, 0x267: 0x0112, 0x268: 0x0113, 0x269: 0x0112, - 0x26a: 0x0113, 0x26b: 0x0112, 0x26c: 0x0113, 0x26d: 0x0112, 0x26e: 0x0113, 0x26f: 0x0112, - 0x270: 0x180a, 0x271: 0x188a, 0x272: 0x0b12, 0x273: 0x5352, 0x274: 0x6253, 0x275: 0x190a, - 0x277: 0x0f13, 0x278: 0x0f12, 0x279: 0x0b13, 0x27a: 0x0113, 0x27b: 0x0112, - 0x27c: 0x0012, 0x27d: 0x4d53, 0x27e: 0x5053, 0x27f: 0x5053, - // Block 0xa, offset 0x280 - 0x280: 0x0812, 0x281: 0x0812, 0x282: 0x0812, 0x283: 0x0812, 0x284: 0x0812, 0x285: 0x0812, - 0x288: 0x0813, 0x289: 0x0813, 0x28a: 0x0813, 0x28b: 0x0813, - 0x28c: 0x0813, 0x28d: 0x0813, 0x290: 0x239a, 0x291: 0x0812, - 0x292: 0x247a, 0x293: 0x0812, 0x294: 0x25ba, 0x295: 0x0812, 0x296: 0x26fa, 0x297: 0x0812, - 0x299: 0x0813, 0x29b: 0x0813, 0x29d: 0x0813, - 0x29f: 0x0813, 0x2a0: 0x0812, 0x2a1: 0x0812, 0x2a2: 0x0812, 0x2a3: 0x0812, - 0x2a4: 0x0812, 0x2a5: 0x0812, 0x2a6: 0x0812, 0x2a7: 0x0812, 0x2a8: 0x0813, 0x2a9: 0x0813, - 0x2aa: 0x0813, 0x2ab: 0x0813, 0x2ac: 0x0813, 0x2ad: 0x0813, 0x2ae: 0x0813, 0x2af: 0x0813, - 0x2b0: 0x8b52, 0x2b1: 0x8b52, 0x2b2: 0x8e52, 0x2b3: 0x8e52, 0x2b4: 0x9152, 0x2b5: 0x9152, - 0x2b6: 0x9452, 0x2b7: 0x9452, 0x2b8: 0x9752, 0x2b9: 0x9752, 0x2ba: 0x9a52, 0x2bb: 0x9a52, - 0x2bc: 0x4d52, 0x2bd: 0x4d52, - // Block 0xb, offset 0x2c0 - 0x2c0: 0x283a, 0x2c1: 0x292a, 0x2c2: 0x2a1a, 0x2c3: 0x2b0a, 0x2c4: 0x2bfa, 0x2c5: 0x2cea, - 0x2c6: 0x2dda, 0x2c7: 0x2eca, 0x2c8: 0x2fb9, 0x2c9: 0x30a9, 0x2ca: 0x3199, 0x2cb: 0x3289, - 0x2cc: 0x3379, 0x2cd: 0x3469, 0x2ce: 0x3559, 0x2cf: 0x3649, 0x2d0: 0x373a, 0x2d1: 0x382a, - 0x2d2: 0x391a, 0x2d3: 0x3a0a, 0x2d4: 0x3afa, 0x2d5: 0x3bea, 0x2d6: 0x3cda, 0x2d7: 0x3dca, - 0x2d8: 0x3eb9, 0x2d9: 0x3fa9, 0x2da: 0x4099, 0x2db: 0x4189, 0x2dc: 0x4279, 0x2dd: 0x4369, - 0x2de: 0x4459, 0x2df: 0x4549, 0x2e0: 0x463a, 0x2e1: 0x472a, 0x2e2: 0x481a, 0x2e3: 0x490a, - 0x2e4: 0x49fa, 0x2e5: 0x4aea, 0x2e6: 0x4bda, 0x2e7: 0x4cca, 0x2e8: 0x4db9, 0x2e9: 0x4ea9, - 0x2ea: 0x4f99, 0x2eb: 0x5089, 0x2ec: 0x5179, 0x2ed: 0x5269, 0x2ee: 0x5359, 0x2ef: 0x5449, - 0x2f0: 0x0812, 0x2f1: 0x0812, 0x2f2: 0x553a, 0x2f3: 0x564a, 0x2f4: 0x571a, - 0x2f6: 0x57fa, 0x2f7: 0x58da, 0x2f8: 0x0813, 0x2f9: 0x0813, 0x2fa: 0x8b53, 0x2fb: 0x8b53, - 0x2fc: 0x5a19, 0x2fd: 0x0004, 0x2fe: 0x5aea, 0x2ff: 0x0004, - // Block 0xc, offset 0x300 - 0x300: 0x0004, 0x301: 0x0004, 0x302: 0x5b6a, 0x303: 0x5c7a, 0x304: 0x5d4a, - 0x306: 0x5e2a, 0x307: 0x5f0a, 0x308: 0x8e53, 0x309: 0x8e53, 0x30a: 0x9153, 0x30b: 0x9153, - 0x30c: 0x6049, 0x30d: 0x0004, 0x30e: 0x0004, 0x30f: 0x0004, 0x310: 0x0812, 0x311: 0x0812, - 0x312: 0x611a, 0x313: 0x625a, 0x316: 0x639a, 0x317: 0x647a, - 0x318: 0x0813, 0x319: 0x0813, 0x31a: 0x9453, 0x31b: 0x9453, 0x31d: 0x0004, - 0x31e: 0x0004, 0x31f: 0x0004, 0x320: 0x0812, 0x321: 0x0812, 0x322: 0x65ba, 0x323: 0x66fa, - 0x324: 0x683a, 0x325: 0x0912, 0x326: 0x691a, 0x327: 0x69fa, 0x328: 0x0813, 0x329: 0x0813, - 0x32a: 0x9a53, 0x32b: 0x9a53, 0x32c: 0x0913, 0x32d: 0x0004, 0x32e: 0x0004, 0x32f: 0x0004, - 0x332: 0x6b3a, 0x333: 0x6c4a, 0x334: 0x6d1a, - 0x336: 0x6dfa, 0x337: 0x6eda, 0x338: 0x9753, 0x339: 0x9753, 0x33a: 0x4d53, 0x33b: 0x4d53, - 0x33c: 0x7019, 0x33d: 0x0004, 0x33e: 0x0004, - // Block 0xd, offset 0x340 - 0x342: 0x0013, - 0x347: 0x0013, 0x34a: 0x0012, 0x34b: 0x0013, - 0x34c: 0x0013, 0x34d: 0x0013, 0x34e: 0x0012, 0x34f: 0x0012, 0x350: 0x0013, 0x351: 0x0013, - 0x352: 0x0013, 0x353: 0x0012, 0x355: 0x0013, - 0x359: 0x0013, 0x35a: 0x0013, 0x35b: 0x0013, 0x35c: 0x0013, 0x35d: 0x0013, - 0x364: 0x0013, 0x366: 0x70eb, 0x368: 0x0013, - 0x36a: 0x714b, 0x36b: 0x718b, 0x36c: 0x0013, 0x36d: 0x0013, 0x36f: 0x0012, - 0x370: 0x0013, 0x371: 0x0013, 0x372: 0x9d53, 0x373: 0x0013, 0x374: 0x0012, 0x375: 0x0010, - 0x376: 0x0010, 0x377: 0x0010, 0x378: 0x0010, 0x379: 0x0012, - 0x37c: 0x0012, 0x37d: 0x0012, 0x37e: 0x0013, 0x37f: 0x0013, - // Block 0xe, offset 0x380 - 0x380: 0x1a13, 0x381: 0x1a13, 0x382: 0x1e13, 0x383: 0x1e13, 0x384: 0x1a13, 0x385: 0x1a13, - 0x386: 0x2613, 0x387: 0x2613, 0x388: 0x2a13, 0x389: 0x2a13, 0x38a: 0x2e13, 0x38b: 0x2e13, - 0x38c: 0x2a13, 0x38d: 0x2a13, 0x38e: 0x2613, 0x38f: 0x2613, 0x390: 0xa052, 0x391: 0xa052, - 0x392: 0xa352, 0x393: 0xa352, 0x394: 0xa652, 0x395: 0xa652, 0x396: 0xa352, 0x397: 0xa352, - 0x398: 0xa052, 0x399: 0xa052, 0x39a: 0x1a12, 0x39b: 0x1a12, 0x39c: 0x1e12, 0x39d: 0x1e12, - 0x39e: 0x1a12, 0x39f: 0x1a12, 0x3a0: 0x2612, 0x3a1: 0x2612, 0x3a2: 0x2a12, 0x3a3: 0x2a12, - 0x3a4: 0x2e12, 0x3a5: 0x2e12, 0x3a6: 0x2a12, 0x3a7: 0x2a12, 0x3a8: 0x2612, 0x3a9: 0x2612, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x6552, 0x3c1: 0x6552, 0x3c2: 0x6552, 0x3c3: 0x6552, 0x3c4: 0x6552, 0x3c5: 0x6552, - 0x3c6: 0x6552, 0x3c7: 0x6552, 0x3c8: 0x6552, 0x3c9: 0x6552, 0x3ca: 0x6552, 0x3cb: 0x6552, - 0x3cc: 0x6552, 0x3cd: 0x6552, 0x3ce: 0x6552, 0x3cf: 0x6552, 0x3d0: 0xa952, 0x3d1: 0xa952, - 0x3d2: 0xa952, 0x3d3: 0xa952, 0x3d4: 0xa952, 0x3d5: 0xa952, 0x3d6: 0xa952, 0x3d7: 0xa952, - 0x3d8: 0xa952, 0x3d9: 0xa952, 0x3da: 0xa952, 0x3db: 0xa952, 0x3dc: 0xa952, 0x3dd: 0xa952, - 0x3de: 0xa952, 0x3e0: 0x0113, 0x3e1: 0x0112, 0x3e2: 0x71eb, 0x3e3: 0x8853, - 0x3e4: 0x724b, 0x3e5: 0x72aa, 0x3e6: 0x730a, 0x3e7: 0x0f13, 0x3e8: 0x0f12, 0x3e9: 0x0313, - 0x3ea: 0x0312, 0x3eb: 0x0713, 0x3ec: 0x0712, 0x3ed: 0x736b, 0x3ee: 0x73cb, 0x3ef: 0x742b, - 0x3f0: 0x748b, 0x3f1: 0x0012, 0x3f2: 0x0113, 0x3f3: 0x0112, 0x3f4: 0x0012, 0x3f5: 0x0313, - 0x3f6: 0x0312, 0x3f7: 0x0012, 0x3f8: 0x0012, 0x3f9: 0x0012, 0x3fa: 0x0012, 0x3fb: 0x0012, - 0x3fc: 0x0015, 0x3fd: 0x0015, 0x3fe: 0x74eb, 0x3ff: 0x754b, - // Block 0x10, offset 0x400 - 0x400: 0x0113, 0x401: 0x0112, 0x402: 0x0113, 0x403: 0x0112, 0x404: 0x0113, 0x405: 0x0112, - 0x406: 0x0113, 0x407: 0x0112, 0x408: 0x0014, 0x409: 0x0004, 0x40a: 0x0004, 0x40b: 0x0713, - 0x40c: 0x0712, 0x40d: 0x75ab, 0x40e: 0x0012, 0x40f: 0x0010, 0x410: 0x0113, 0x411: 0x0112, - 0x412: 0x0113, 0x413: 0x0112, 0x414: 0x0012, 0x415: 0x0012, 0x416: 0x0113, 0x417: 0x0112, - 0x418: 0x0113, 0x419: 0x0112, 0x41a: 0x0113, 0x41b: 0x0112, 0x41c: 0x0113, 0x41d: 0x0112, - 0x41e: 0x0113, 0x41f: 0x0112, 0x420: 0x0113, 0x421: 0x0112, 0x422: 0x0113, 0x423: 0x0112, - 0x424: 0x0113, 0x425: 0x0112, 0x426: 0x0113, 0x427: 0x0112, 0x428: 0x0113, 0x429: 0x0112, - 0x42a: 0x760b, 0x42b: 0x766b, 0x42c: 0x76cb, 0x42d: 0x772b, 0x42e: 0x778b, - 0x430: 0x77eb, 0x431: 0x784b, 0x432: 0x78ab, 0x433: 0xac53, 0x434: 0x0113, 0x435: 0x0112, - 0x436: 0x0113, 0x437: 0x0112, - // Block 0x11, offset 0x440 - 0x440: 0x790a, 0x441: 0x798a, 0x442: 0x7a0a, 0x443: 0x7a8a, 0x444: 0x7b3a, 0x445: 0x7bea, - 0x446: 0x7c6a, - 0x453: 0x7cea, 0x454: 0x7dca, 0x455: 0x7eaa, 0x456: 0x7f8a, 0x457: 0x806a, - 0x45d: 0x0010, - 0x45e: 0x0034, 0x45f: 0x0010, 0x460: 0x0010, 0x461: 0x0010, 0x462: 0x0010, 0x463: 0x0010, - 0x464: 0x0010, 0x465: 0x0010, 0x466: 0x0010, 0x467: 0x0010, 0x468: 0x0010, - 0x46a: 0x0010, 0x46b: 0x0010, 0x46c: 0x0010, 0x46d: 0x0010, 0x46e: 0x0010, 0x46f: 0x0010, - 0x470: 0x0010, 0x471: 0x0010, 0x472: 0x0010, 0x473: 0x0010, 0x474: 0x0010, 0x475: 0x0010, - 0x476: 0x0010, 0x478: 0x0010, 0x479: 0x0010, 0x47a: 0x0010, 0x47b: 0x0010, - 0x47c: 0x0010, 0x47e: 0x0010, - // Block 0x12, offset 0x480 - 0x480: 0x2213, 0x481: 0x2213, 0x482: 0x2613, 0x483: 0x2613, 0x484: 0x2213, 0x485: 0x2213, - 0x486: 0x2e13, 0x487: 0x2e13, 0x488: 0x2213, 0x489: 0x2213, 0x48a: 0x2613, 0x48b: 0x2613, - 0x48c: 0x2213, 0x48d: 0x2213, 0x48e: 0x3e13, 0x48f: 0x3e13, 0x490: 0x2213, 0x491: 0x2213, - 0x492: 0x2613, 0x493: 0x2613, 0x494: 0x2213, 0x495: 0x2213, 0x496: 0x2e13, 0x497: 0x2e13, - 0x498: 0x2213, 0x499: 0x2213, 0x49a: 0x2613, 0x49b: 0x2613, 0x49c: 0x2213, 0x49d: 0x2213, - 0x49e: 0xb553, 0x49f: 0xb553, 0x4a0: 0xb853, 0x4a1: 0xb853, 0x4a2: 0x2212, 0x4a3: 0x2212, - 0x4a4: 0x2612, 0x4a5: 0x2612, 0x4a6: 0x2212, 0x4a7: 0x2212, 0x4a8: 0x2e12, 0x4a9: 0x2e12, - 0x4aa: 0x2212, 0x4ab: 0x2212, 0x4ac: 0x2612, 0x4ad: 0x2612, 0x4ae: 0x2212, 0x4af: 0x2212, - 0x4b0: 0x3e12, 0x4b1: 0x3e12, 0x4b2: 0x2212, 0x4b3: 0x2212, 0x4b4: 0x2612, 0x4b5: 0x2612, - 0x4b6: 0x2212, 0x4b7: 0x2212, 0x4b8: 0x2e12, 0x4b9: 0x2e12, 0x4ba: 0x2212, 0x4bb: 0x2212, - 0x4bc: 0x2612, 0x4bd: 0x2612, 0x4be: 0x2212, 0x4bf: 0x2212, - // Block 0x13, offset 0x4c0 - 0x4c2: 0x0010, - 0x4c7: 0x0010, 0x4c9: 0x0010, 0x4cb: 0x0010, - 0x4cd: 0x0010, 0x4ce: 0x0010, 0x4cf: 0x0010, 0x4d1: 0x0010, - 0x4d2: 0x0010, 0x4d4: 0x0010, 0x4d7: 0x0010, - 0x4d9: 0x0010, 0x4db: 0x0010, 0x4dd: 0x0010, - 0x4df: 0x0010, 0x4e1: 0x0010, 0x4e2: 0x0010, - 0x4e4: 0x0010, 0x4e7: 0x0010, 0x4e8: 0x0010, 0x4e9: 0x0010, - 0x4ea: 0x0010, 0x4ec: 0x0010, 0x4ed: 0x0010, 0x4ee: 0x0010, 0x4ef: 0x0010, - 0x4f0: 0x0010, 0x4f1: 0x0010, 0x4f2: 0x0010, 0x4f4: 0x0010, 0x4f5: 0x0010, - 0x4f6: 0x0010, 0x4f7: 0x0010, 0x4f9: 0x0010, 0x4fa: 0x0010, 0x4fb: 0x0010, - 0x4fc: 0x0010, 0x4fe: 0x0010, -} - -// caseIndex: 25 blocks, 1600 entries, 3200 bytes -// Block 0 is the zero block. -var caseIndex = [1600]uint16{ - // Block 0x0, offset 0x0 - // Block 0x1, offset 0x40 - // Block 0x2, offset 0x80 - // Block 0x3, offset 0xc0 - 0xc2: 0x12, 0xc3: 0x13, 0xc4: 0x14, 0xc5: 0x15, 0xc6: 0x01, 0xc7: 0x02, - 0xc8: 0x16, 0xc9: 0x03, 0xca: 0x04, 0xcb: 0x17, 0xcc: 0x18, 0xcd: 0x05, 0xce: 0x06, 0xcf: 0x07, - 0xd0: 0x19, 0xd1: 0x1a, 0xd2: 0x1b, 0xd3: 0x1c, 0xd4: 0x1d, 0xd5: 0x1e, 0xd6: 0x1f, 0xd7: 0x20, - 0xd8: 0x21, 0xd9: 0x22, 0xda: 0x23, 0xdb: 0x24, 0xdc: 0x25, 0xdd: 0x26, 0xde: 0x27, 0xdf: 0x28, - 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, - 0xea: 0x06, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x08, 0xef: 0x09, - 0xf0: 0x14, 0xf3: 0x16, - // Block 0x4, offset 0x100 - 0x120: 0x29, 0x121: 0x2a, 0x122: 0x2b, 0x123: 0x2c, 0x124: 0x2d, 0x125: 0x2e, 0x126: 0x2f, 0x127: 0x30, - 0x128: 0x31, 0x129: 0x32, 0x12a: 0x33, 0x12b: 0x34, 0x12c: 0x35, 0x12d: 0x36, 0x12e: 0x37, 0x12f: 0x38, - 0x130: 0x39, 0x131: 0x3a, 0x132: 0x3b, 0x133: 0x3c, 0x134: 0x3d, 0x135: 0x3e, 0x136: 0x3f, 0x137: 0x40, - 0x138: 0x41, 0x139: 0x42, 0x13a: 0x43, 0x13b: 0x44, 0x13c: 0x45, 0x13d: 0x46, 0x13e: 0x47, 0x13f: 0x48, - // Block 0x5, offset 0x140 - 0x140: 0x49, 0x141: 0x4a, 0x142: 0x4b, 0x143: 0x4c, 0x144: 0x23, 0x145: 0x23, 0x146: 0x23, 0x147: 0x23, - 0x148: 0x23, 0x149: 0x4d, 0x14a: 0x4e, 0x14b: 0x4f, 0x14c: 0x50, 0x14d: 0x51, 0x14e: 0x52, 0x14f: 0x53, - 0x150: 0x54, 0x151: 0x23, 0x152: 0x23, 0x153: 0x23, 0x154: 0x23, 0x155: 0x23, 0x156: 0x23, 0x157: 0x23, - 0x158: 0x23, 0x159: 0x55, 0x15a: 0x56, 0x15b: 0x57, 0x15c: 0x58, 0x15d: 0x59, 0x15e: 0x5a, 0x15f: 0x5b, - 0x160: 0x5c, 0x161: 0x5d, 0x162: 0x5e, 0x163: 0x5f, 0x164: 0x60, 0x165: 0x61, 0x167: 0x62, - 0x168: 0x63, 0x169: 0x64, 0x16a: 0x65, 0x16c: 0x66, 0x16d: 0x67, 0x16e: 0x68, 0x16f: 0x69, - 0x170: 0x6a, 0x171: 0x6b, 0x172: 0x6c, 0x173: 0x6d, 0x174: 0x6e, 0x175: 0x6f, 0x176: 0x70, 0x177: 0x71, - 0x178: 0x72, 0x179: 0x72, 0x17a: 0x73, 0x17b: 0x72, 0x17c: 0x74, 0x17d: 0x08, 0x17e: 0x09, 0x17f: 0x0a, - // Block 0x6, offset 0x180 - 0x180: 0x75, 0x181: 0x76, 0x182: 0x77, 0x183: 0x78, 0x184: 0x0b, 0x185: 0x79, 0x186: 0x7a, - 0x192: 0x7b, 0x193: 0x0c, - 0x1b0: 0x7c, 0x1b1: 0x0d, 0x1b2: 0x72, 0x1b3: 0x7d, 0x1b4: 0x7e, 0x1b5: 0x7f, 0x1b6: 0x80, 0x1b7: 0x81, - 0x1b8: 0x82, - // Block 0x7, offset 0x1c0 - 0x1c0: 0x83, 0x1c2: 0x84, 0x1c3: 0x85, 0x1c4: 0x86, 0x1c5: 0x23, 0x1c6: 0x87, - // Block 0x8, offset 0x200 - 0x200: 0x88, 0x201: 0x23, 0x202: 0x23, 0x203: 0x23, 0x204: 0x23, 0x205: 0x23, 0x206: 0x23, 0x207: 0x23, - 0x208: 0x23, 0x209: 0x23, 0x20a: 0x23, 0x20b: 0x23, 0x20c: 0x23, 0x20d: 0x23, 0x20e: 0x23, 0x20f: 0x23, - 0x210: 0x23, 0x211: 0x23, 0x212: 0x89, 0x213: 0x8a, 0x214: 0x23, 0x215: 0x23, 0x216: 0x23, 0x217: 0x23, - 0x218: 0x8b, 0x219: 0x8c, 0x21a: 0x8d, 0x21b: 0x8e, 0x21c: 0x8f, 0x21d: 0x90, 0x21e: 0x0e, 0x21f: 0x91, - 0x220: 0x92, 0x221: 0x93, 0x222: 0x23, 0x223: 0x94, 0x224: 0x95, 0x225: 0x96, 0x226: 0x97, 0x227: 0x98, - 0x228: 0x99, 0x229: 0x9a, 0x22a: 0x9b, 0x22b: 0x9c, 0x22c: 0x9d, 0x22d: 0x9e, 0x22e: 0x9f, 0x22f: 0xa0, - 0x230: 0x23, 0x231: 0x23, 0x232: 0x23, 0x233: 0x23, 0x234: 0x23, 0x235: 0x23, 0x236: 0x23, 0x237: 0x23, - 0x238: 0x23, 0x239: 0x23, 0x23a: 0x23, 0x23b: 0x23, 0x23c: 0x23, 0x23d: 0x23, 0x23e: 0x23, 0x23f: 0x23, - // Block 0x9, offset 0x240 - 0x240: 0x23, 0x241: 0x23, 0x242: 0x23, 0x243: 0x23, 0x244: 0x23, 0x245: 0x23, 0x246: 0x23, 0x247: 0x23, - 0x248: 0x23, 0x249: 0x23, 0x24a: 0x23, 0x24b: 0x23, 0x24c: 0x23, 0x24d: 0x23, 0x24e: 0x23, 0x24f: 0x23, - 0x250: 0x23, 0x251: 0x23, 0x252: 0x23, 0x253: 0x23, 0x254: 0x23, 0x255: 0x23, 0x256: 0x23, 0x257: 0x23, - 0x258: 0x23, 0x259: 0x23, 0x25a: 0x23, 0x25b: 0x23, 0x25c: 0x23, 0x25d: 0x23, 0x25e: 0x23, 0x25f: 0x23, - 0x260: 0x23, 0x261: 0x23, 0x262: 0x23, 0x263: 0x23, 0x264: 0x23, 0x265: 0x23, 0x266: 0x23, 0x267: 0x23, - 0x268: 0x23, 0x269: 0x23, 0x26a: 0x23, 0x26b: 0x23, 0x26c: 0x23, 0x26d: 0x23, 0x26e: 0x23, 0x26f: 0x23, - 0x270: 0x23, 0x271: 0x23, 0x272: 0x23, 0x273: 0x23, 0x274: 0x23, 0x275: 0x23, 0x276: 0x23, 0x277: 0x23, - 0x278: 0x23, 0x279: 0x23, 0x27a: 0x23, 0x27b: 0x23, 0x27c: 0x23, 0x27d: 0x23, 0x27e: 0x23, 0x27f: 0x23, - // Block 0xa, offset 0x280 - 0x280: 0x23, 0x281: 0x23, 0x282: 0x23, 0x283: 0x23, 0x284: 0x23, 0x285: 0x23, 0x286: 0x23, 0x287: 0x23, - 0x288: 0x23, 0x289: 0x23, 0x28a: 0x23, 0x28b: 0x23, 0x28c: 0x23, 0x28d: 0x23, 0x28e: 0x23, 0x28f: 0x23, - 0x290: 0x23, 0x291: 0x23, 0x292: 0x23, 0x293: 0x23, 0x294: 0x23, 0x295: 0x23, 0x296: 0x23, 0x297: 0x23, - 0x298: 0x23, 0x299: 0x23, 0x29a: 0x23, 0x29b: 0x23, 0x29c: 0x23, 0x29d: 0x23, 0x29e: 0xa1, 0x29f: 0xa2, - // Block 0xb, offset 0x2c0 - 0x2ec: 0x0f, 0x2ed: 0xa3, 0x2ee: 0xa4, 0x2ef: 0xa5, - 0x2f0: 0x23, 0x2f1: 0x23, 0x2f2: 0x23, 0x2f3: 0x23, 0x2f4: 0xa6, 0x2f5: 0xa7, 0x2f6: 0xa8, 0x2f7: 0xa9, - 0x2f8: 0xaa, 0x2f9: 0xab, 0x2fa: 0x23, 0x2fb: 0xac, 0x2fc: 0xad, 0x2fd: 0xae, 0x2fe: 0xaf, 0x2ff: 0xb0, - // Block 0xc, offset 0x300 - 0x300: 0xb1, 0x301: 0xb2, 0x302: 0x23, 0x303: 0xb3, 0x305: 0xb4, 0x307: 0xb5, - 0x30a: 0xb6, 0x30b: 0xb7, 0x30c: 0xb8, 0x30d: 0xb9, 0x30e: 0xba, 0x30f: 0xbb, - 0x310: 0xbc, 0x311: 0xbd, 0x312: 0xbe, 0x313: 0xbf, 0x314: 0xc0, 0x315: 0xc1, - 0x318: 0x23, 0x319: 0x23, 0x31a: 0x23, 0x31b: 0x23, 0x31c: 0xc2, 0x31d: 0xc3, - 0x320: 0xc4, 0x321: 0xc5, 0x322: 0xc6, 0x323: 0xc7, 0x324: 0xc8, 0x326: 0xc9, - 0x328: 0xca, 0x329: 0xcb, 0x32a: 0xcc, 0x32b: 0xcd, 0x32c: 0x5f, 0x32d: 0xce, 0x32e: 0xcf, - 0x330: 0x23, 0x331: 0xd0, 0x332: 0xd1, 0x333: 0xd2, - // Block 0xd, offset 0x340 - 0x340: 0xd3, 0x341: 0xd4, 0x342: 0xd5, 0x343: 0xd6, 0x344: 0xd7, 0x345: 0xd8, 0x346: 0xd9, 0x347: 0xda, - 0x348: 0xdb, 0x34a: 0xdc, 0x34b: 0xdd, 0x34c: 0xde, 0x34d: 0xdf, - 0x350: 0xe0, 0x351: 0xe1, 0x352: 0xe2, 0x353: 0xe3, 0x356: 0xe4, 0x357: 0xe5, - 0x358: 0xe6, 0x359: 0xe7, 0x35a: 0xe8, 0x35b: 0xe9, 0x35c: 0xea, - 0x362: 0xeb, 0x363: 0xec, - 0x36b: 0xed, - 0x370: 0xee, 0x371: 0xef, 0x372: 0xf0, - // Block 0xe, offset 0x380 - 0x380: 0x23, 0x381: 0x23, 0x382: 0x23, 0x383: 0x23, 0x384: 0x23, 0x385: 0x23, 0x386: 0x23, 0x387: 0x23, - 0x388: 0x23, 0x389: 0x23, 0x38a: 0x23, 0x38b: 0x23, 0x38c: 0x23, 0x38d: 0x23, 0x38e: 0xf1, - 0x390: 0x23, 0x391: 0xf2, 0x392: 0x23, 0x393: 0x23, 0x394: 0x23, 0x395: 0xf3, - // Block 0xf, offset 0x3c0 - 0x3c0: 0x23, 0x3c1: 0x23, 0x3c2: 0x23, 0x3c3: 0x23, 0x3c4: 0x23, 0x3c5: 0x23, 0x3c6: 0x23, 0x3c7: 0x23, - 0x3c8: 0x23, 0x3c9: 0x23, 0x3ca: 0x23, 0x3cb: 0x23, 0x3cc: 0x23, 0x3cd: 0x23, 0x3ce: 0x23, 0x3cf: 0x23, - 0x3d0: 0xf2, - // Block 0x10, offset 0x400 - 0x410: 0x23, 0x411: 0x23, 0x412: 0x23, 0x413: 0x23, 0x414: 0x23, 0x415: 0x23, 0x416: 0x23, 0x417: 0x23, - 0x418: 0x23, 0x419: 0xf4, - // Block 0x11, offset 0x440 - 0x460: 0x23, 0x461: 0x23, 0x462: 0x23, 0x463: 0x23, 0x464: 0x23, 0x465: 0x23, 0x466: 0x23, 0x467: 0x23, - 0x468: 0xed, 0x469: 0xf5, 0x46b: 0xf6, 0x46c: 0xf7, 0x46d: 0xf8, 0x46e: 0xf9, - 0x47c: 0x23, 0x47d: 0xfa, 0x47e: 0xfb, 0x47f: 0xfc, - // Block 0x12, offset 0x480 - 0x4b0: 0x23, 0x4b1: 0xfd, 0x4b2: 0xfe, - // Block 0x13, offset 0x4c0 - 0x4c5: 0xff, 0x4c6: 0x100, - 0x4c9: 0x101, - 0x4d0: 0x102, 0x4d1: 0x103, 0x4d2: 0x104, 0x4d3: 0x105, 0x4d4: 0x106, 0x4d5: 0x107, 0x4d6: 0x108, 0x4d7: 0x109, - 0x4d8: 0x10a, 0x4d9: 0x10b, 0x4da: 0x10c, 0x4db: 0x10d, 0x4dc: 0x10e, 0x4dd: 0x10f, 0x4de: 0x110, 0x4df: 0x111, - 0x4e8: 0x112, 0x4e9: 0x113, 0x4ea: 0x114, - // Block 0x14, offset 0x500 - 0x500: 0x115, - 0x520: 0x23, 0x521: 0x23, 0x522: 0x23, 0x523: 0x116, 0x524: 0x10, 0x525: 0x117, - 0x538: 0x118, 0x539: 0x11, 0x53a: 0x119, - // Block 0x15, offset 0x540 - 0x544: 0x11a, 0x545: 0x11b, 0x546: 0x11c, - 0x54f: 0x11d, - // Block 0x16, offset 0x580 - 0x590: 0x0a, 0x591: 0x0b, 0x592: 0x0c, 0x593: 0x0d, 0x594: 0x0e, 0x596: 0x0f, - 0x59b: 0x10, 0x59d: 0x11, 0x59e: 0x12, 0x59f: 0x13, - // Block 0x17, offset 0x5c0 - 0x5c0: 0x11e, 0x5c1: 0x11f, 0x5c4: 0x11f, 0x5c5: 0x11f, 0x5c6: 0x11f, 0x5c7: 0x120, - // Block 0x18, offset 0x600 - 0x620: 0x15, -} - -// sparseOffsets: 272 entries, 544 bytes -var sparseOffsets = []uint16{0x0, 0x9, 0xf, 0x18, 0x24, 0x2e, 0x3a, 0x3d, 0x41, 0x44, 0x48, 0x52, 0x54, 0x59, 0x69, 0x70, 0x75, 0x83, 0x84, 0x92, 0xa1, 0xab, 0xae, 0xb4, 0xbc, 0xbe, 0xc0, 0xce, 0xd4, 0xe2, 0xed, 0xf8, 0x103, 0x10f, 0x119, 0x124, 0x12f, 0x13b, 0x147, 0x14f, 0x157, 0x161, 0x16c, 0x178, 0x17e, 0x189, 0x18e, 0x196, 0x199, 0x19e, 0x1a2, 0x1a6, 0x1ad, 0x1b6, 0x1be, 0x1bf, 0x1c8, 0x1cf, 0x1d7, 0x1dd, 0x1e3, 0x1e8, 0x1ec, 0x1ef, 0x1f1, 0x1f4, 0x1f9, 0x1fa, 0x1fc, 0x1fe, 0x200, 0x207, 0x20c, 0x210, 0x219, 0x21c, 0x21f, 0x225, 0x226, 0x231, 0x232, 0x233, 0x238, 0x245, 0x24d, 0x255, 0x25e, 0x267, 0x270, 0x275, 0x278, 0x281, 0x28e, 0x290, 0x297, 0x299, 0x2a4, 0x2a5, 0x2b0, 0x2b8, 0x2c0, 0x2c6, 0x2c7, 0x2d5, 0x2da, 0x2dd, 0x2e2, 0x2e6, 0x2ec, 0x2f1, 0x2f4, 0x2f9, 0x2fe, 0x2ff, 0x305, 0x307, 0x308, 0x30a, 0x30c, 0x30f, 0x310, 0x312, 0x315, 0x31b, 0x31f, 0x321, 0x327, 0x32e, 0x332, 0x33b, 0x33c, 0x344, 0x348, 0x34d, 0x355, 0x35b, 0x361, 0x36b, 0x370, 0x379, 0x37f, 0x386, 0x38a, 0x392, 0x394, 0x396, 0x399, 0x39b, 0x39d, 0x39e, 0x39f, 0x3a1, 0x3a3, 0x3a9, 0x3ae, 0x3b0, 0x3b6, 0x3b9, 0x3bb, 0x3c1, 0x3c6, 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cd, 0x3cf, 0x3d1, 0x3d4, 0x3d6, 0x3d9, 0x3e1, 0x3e4, 0x3e8, 0x3f0, 0x3f2, 0x3f3, 0x3f4, 0x3f6, 0x3fc, 0x3fe, 0x3ff, 0x401, 0x403, 0x405, 0x412, 0x413, 0x414, 0x418, 0x41a, 0x41b, 0x41c, 0x41d, 0x41e, 0x422, 0x426, 0x42c, 0x42e, 0x435, 0x438, 0x43c, 0x442, 0x44b, 0x451, 0x457, 0x461, 0x46b, 0x46d, 0x474, 0x47a, 0x480, 0x486, 0x489, 0x48f, 0x492, 0x49a, 0x49b, 0x4a2, 0x4a3, 0x4a6, 0x4a7, 0x4ad, 0x4b0, 0x4b8, 0x4b9, 0x4ba, 0x4bb, 0x4bc, 0x4be, 0x4c0, 0x4c2, 0x4c6, 0x4c7, 0x4c9, 0x4ca, 0x4cb, 0x4cd, 0x4d2, 0x4d7, 0x4db, 0x4dc, 0x4df, 0x4e3, 0x4ee, 0x4f2, 0x4fa, 0x4ff, 0x503, 0x506, 0x50a, 0x50d, 0x510, 0x515, 0x519, 0x51d, 0x521, 0x525, 0x527, 0x529, 0x52c, 0x531, 0x533, 0x538, 0x541, 0x546, 0x547, 0x54a, 0x54b, 0x54c, 0x54e, 0x54f, 0x550} - -// sparseValues: 1360 entries, 5440 bytes -var sparseValues = [1360]valueRange{ - // Block 0x0, offset 0x0 - {value: 0x0004, lo: 0xa8, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xaa}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0004, lo: 0xaf, hi: 0xaf}, - {value: 0x0004, lo: 0xb4, hi: 0xb4}, - {value: 0x001a, lo: 0xb5, hi: 0xb5}, - {value: 0x0054, lo: 0xb7, hi: 0xb7}, - {value: 0x0004, lo: 0xb8, hi: 0xb8}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - // Block 0x1, offset 0x9 - {value: 0x2013, lo: 0x80, hi: 0x96}, - {value: 0x2013, lo: 0x98, hi: 0x9e}, - {value: 0x009a, lo: 0x9f, hi: 0x9f}, - {value: 0x2012, lo: 0xa0, hi: 0xb6}, - {value: 0x2012, lo: 0xb8, hi: 0xbe}, - {value: 0x0252, lo: 0xbf, hi: 0xbf}, - // Block 0x2, offset 0xf - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x011b, lo: 0xb0, hi: 0xb0}, - {value: 0x019a, lo: 0xb1, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb7}, - {value: 0x0012, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x0553, lo: 0xbf, hi: 0xbf}, - // Block 0x3, offset 0x18 - {value: 0x0552, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x01da, lo: 0x89, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xb7}, - {value: 0x0253, lo: 0xb8, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x0316, lo: 0xbd, hi: 0xbe}, - {value: 0x028a, lo: 0xbf, hi: 0xbf}, - // Block 0x4, offset 0x24 - {value: 0x0117, lo: 0x80, hi: 0x9f}, - {value: 0x2f53, lo: 0xa0, hi: 0xa0}, - {value: 0x0012, lo: 0xa1, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xb3}, - {value: 0x0012, lo: 0xb4, hi: 0xb9}, - {value: 0x090b, lo: 0xba, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x2953, lo: 0xbd, hi: 0xbd}, - {value: 0x098b, lo: 0xbe, hi: 0xbe}, - {value: 0x0a0a, lo: 0xbf, hi: 0xbf}, - // Block 0x5, offset 0x2e - {value: 0x0015, lo: 0x80, hi: 0x81}, - {value: 0x0004, lo: 0x82, hi: 0x85}, - {value: 0x0014, lo: 0x86, hi: 0x91}, - {value: 0x0004, lo: 0x92, hi: 0x96}, - {value: 0x0054, lo: 0x97, hi: 0x97}, - {value: 0x0004, lo: 0x98, hi: 0x9f}, - {value: 0x0015, lo: 0xa0, hi: 0xa4}, - {value: 0x0004, lo: 0xa5, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xac}, - {value: 0x0004, lo: 0xad, hi: 0xad}, - {value: 0x0014, lo: 0xae, hi: 0xae}, - {value: 0x0004, lo: 0xaf, hi: 0xbf}, - // Block 0x6, offset 0x3a - {value: 0x0024, lo: 0x80, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbf}, - // Block 0x7, offset 0x3d - {value: 0x6553, lo: 0x80, hi: 0x8f}, - {value: 0x2013, lo: 0x90, hi: 0x9f}, - {value: 0x5f53, lo: 0xa0, hi: 0xaf}, - {value: 0x2012, lo: 0xb0, hi: 0xbf}, - // Block 0x8, offset 0x41 - {value: 0x5f52, lo: 0x80, hi: 0x8f}, - {value: 0x6552, lo: 0x90, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x9, offset 0x44 - {value: 0x0117, lo: 0x80, hi: 0x81}, - {value: 0x0024, lo: 0x83, hi: 0x87}, - {value: 0x0014, lo: 0x88, hi: 0x89}, - {value: 0x0117, lo: 0x8a, hi: 0xbf}, - // Block 0xa, offset 0x48 - {value: 0x0f13, lo: 0x80, hi: 0x80}, - {value: 0x0316, lo: 0x81, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0316, lo: 0x85, hi: 0x86}, - {value: 0x0f16, lo: 0x87, hi: 0x88}, - {value: 0x0316, lo: 0x89, hi: 0x8a}, - {value: 0x0716, lo: 0x8b, hi: 0x8c}, - {value: 0x0316, lo: 0x8d, hi: 0x8e}, - {value: 0x0f12, lo: 0x8f, hi: 0x8f}, - {value: 0x0117, lo: 0x90, hi: 0xbf}, - // Block 0xb, offset 0x52 - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x6553, lo: 0xb1, hi: 0xbf}, - // Block 0xc, offset 0x54 - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6853, lo: 0x90, hi: 0x96}, - {value: 0x0014, lo: 0x99, hi: 0x99}, - {value: 0x6552, lo: 0xa1, hi: 0xaf}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0xd, offset 0x59 - {value: 0x6852, lo: 0x80, hi: 0x86}, - {value: 0x198a, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0024, lo: 0x92, hi: 0x95}, - {value: 0x0034, lo: 0x96, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x99}, - {value: 0x0034, lo: 0x9a, hi: 0x9b}, - {value: 0x0024, lo: 0x9c, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa7}, - {value: 0x0024, lo: 0xa8, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xbd}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xe, offset 0x69 - {value: 0x0034, lo: 0x81, hi: 0x82}, - {value: 0x0024, lo: 0x84, hi: 0x84}, - {value: 0x0034, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb3}, - {value: 0x0054, lo: 0xb4, hi: 0xb4}, - // Block 0xf, offset 0x70 - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0024, lo: 0x90, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0014, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x10, offset 0x75 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x8a}, - {value: 0x0034, lo: 0x8b, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9c}, - {value: 0x0024, lo: 0x9d, hi: 0x9e}, - {value: 0x0034, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0034, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x11, offset 0x83 - {value: 0x0010, lo: 0x80, hi: 0xbf}, - // Block 0x12, offset 0x84 - {value: 0x0010, lo: 0x80, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0024, lo: 0x9f, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xaa, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x13, offset 0x92 - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0034, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0034, lo: 0xb1, hi: 0xb1}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbc}, - {value: 0x0024, lo: 0xbd, hi: 0xbd}, - {value: 0x0034, lo: 0xbe, hi: 0xbe}, - {value: 0x0024, lo: 0xbf, hi: 0xbf}, - // Block 0x14, offset 0xa1 - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0024, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x88}, - {value: 0x0024, lo: 0x89, hi: 0x8a}, - {value: 0x0010, lo: 0x8d, hi: 0xbf}, - // Block 0x15, offset 0xab - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x16, offset 0xae - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0024, lo: 0xab, hi: 0xb1}, - {value: 0x0034, lo: 0xb2, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - // Block 0x17, offset 0xb4 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0024, lo: 0x96, hi: 0x99}, - {value: 0x0014, lo: 0x9a, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0xa3}, - {value: 0x0014, lo: 0xa4, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xad}, - // Block 0x18, offset 0xbc - {value: 0x0010, lo: 0x80, hi: 0x98}, - {value: 0x0034, lo: 0x99, hi: 0x9b}, - // Block 0x19, offset 0xbe - {value: 0x0010, lo: 0xa0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbd}, - // Block 0x1a, offset 0xc0 - {value: 0x0024, lo: 0x94, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0034, lo: 0xa3, hi: 0xa3}, - {value: 0x0024, lo: 0xa4, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0024, lo: 0xaa, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xb2}, - {value: 0x0024, lo: 0xb3, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbf}, - // Block 0x1b, offset 0xce - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1c, offset 0xd4 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0024, lo: 0x93, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x98, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0x1d, offset 0xe2 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb6, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x1e, offset 0xed - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xb1}, - // Block 0x1f, offset 0xf8 - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x20, offset 0x103 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x91, hi: 0x91}, - {value: 0x0010, lo: 0x99, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x21, offset 0x10f - {value: 0x0014, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x22, offset 0x119 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x85}, - {value: 0x0014, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x89, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - // Block 0x23, offset 0x124 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x24, offset 0x12f - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9c, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - // Block 0x25, offset 0x13b - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8a}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - {value: 0x0010, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0010, lo: 0xa8, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x26, offset 0x147 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x82}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x27, offset 0x14f - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb9}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbf}, - // Block 0x28, offset 0x157 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x88}, - {value: 0x0014, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0034, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - // Block 0x29, offset 0x161 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x2a, offset 0x16c - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x95, hi: 0x96}, - {value: 0x0010, lo: 0x9e, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb1, hi: 0xb2}, - // Block 0x2b, offset 0x178 - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0xba}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x2c, offset 0x17e - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8e, hi: 0x8e}, - {value: 0x0010, lo: 0x94, hi: 0x97}, - {value: 0x0010, lo: 0x9f, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa3}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xba, hi: 0xbf}, - // Block 0x2d, offset 0x189 - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x96}, - {value: 0x0010, lo: 0x9a, hi: 0xb1}, - {value: 0x0010, lo: 0xb3, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x2e, offset 0x18e - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x8f, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x94}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9f}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - // Block 0x2f, offset 0x196 - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xba}, - // Block 0x30, offset 0x199 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x87}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x31, offset 0x19e - {value: 0x0014, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb4, hi: 0xb7}, - {value: 0x0034, lo: 0xb8, hi: 0xb9}, - {value: 0x0014, lo: 0xbb, hi: 0xbc}, - // Block 0x32, offset 0x1a2 - {value: 0x0004, lo: 0x86, hi: 0x86}, - {value: 0x0034, lo: 0x88, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x33, offset 0x1a6 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0034, lo: 0x98, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0034, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x34, offset 0x1ad - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xac}, - {value: 0x0034, lo: 0xb1, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xba, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x35, offset 0x1b6 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0024, lo: 0x82, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0024, lo: 0x86, hi: 0x87}, - {value: 0x0010, lo: 0x88, hi: 0x8c}, - {value: 0x0014, lo: 0x8d, hi: 0x97}, - {value: 0x0014, lo: 0x99, hi: 0xbc}, - // Block 0x36, offset 0x1be - {value: 0x0034, lo: 0x86, hi: 0x86}, - // Block 0x37, offset 0x1bf - {value: 0x0010, lo: 0xab, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - {value: 0x0010, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbe}, - // Block 0x38, offset 0x1c8 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x96, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x99}, - {value: 0x0014, lo: 0x9e, hi: 0xa0}, - {value: 0x0010, lo: 0xa2, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xad}, - {value: 0x0014, lo: 0xb1, hi: 0xb4}, - // Block 0x39, offset 0x1cf - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x6c53, lo: 0xa0, hi: 0xbf}, - // Block 0x3a, offset 0x1d7 - {value: 0x7053, lo: 0x80, hi: 0x85}, - {value: 0x7053, lo: 0x87, hi: 0x87}, - {value: 0x7053, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xba}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x3b, offset 0x1dd - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x9a, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x3c, offset 0x1e3 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x3d, offset 0x1e8 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x82, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3e, offset 0x1ec - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0010, lo: 0x92, hi: 0x95}, - {value: 0x0010, lo: 0x98, hi: 0xbf}, - // Block 0x3f, offset 0x1ef - {value: 0x0010, lo: 0x80, hi: 0x9a}, - {value: 0x0024, lo: 0x9d, hi: 0x9f}, - // Block 0x40, offset 0x1f1 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x7453, lo: 0xa0, hi: 0xaf}, - {value: 0x7853, lo: 0xb0, hi: 0xbf}, - // Block 0x41, offset 0x1f4 - {value: 0x7c53, lo: 0x80, hi: 0x8f}, - {value: 0x8053, lo: 0x90, hi: 0x9f}, - {value: 0x7c53, lo: 0xa0, hi: 0xaf}, - {value: 0x0813, lo: 0xb0, hi: 0xb5}, - {value: 0x0892, lo: 0xb8, hi: 0xbd}, - // Block 0x42, offset 0x1f9 - {value: 0x0010, lo: 0x81, hi: 0xbf}, - // Block 0x43, offset 0x1fa - {value: 0x0010, lo: 0x80, hi: 0xac}, - {value: 0x0010, lo: 0xaf, hi: 0xbf}, - // Block 0x44, offset 0x1fc - {value: 0x0010, lo: 0x81, hi: 0x9a}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x45, offset 0x1fe - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xae, hi: 0xb8}, - // Block 0x46, offset 0x200 - {value: 0x0010, lo: 0x80, hi: 0x8c}, - {value: 0x0010, lo: 0x8e, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0034, lo: 0x94, hi: 0x94}, - {value: 0x0010, lo: 0xa0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - // Block 0x47, offset 0x207 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0014, lo: 0x92, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xac}, - {value: 0x0010, lo: 0xae, hi: 0xb0}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - // Block 0x48, offset 0x20c - {value: 0x0014, lo: 0xb4, hi: 0xb5}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0x49, offset 0x210 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0014, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0014, lo: 0x89, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x92}, - {value: 0x0014, lo: 0x93, hi: 0x93}, - {value: 0x0004, lo: 0x97, hi: 0x97}, - {value: 0x0024, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0x4a, offset 0x219 - {value: 0x0014, lo: 0x8b, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x4b, offset 0x21c - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb7}, - // Block 0x4c, offset 0x21f - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x4d, offset 0x225 - {value: 0x0010, lo: 0x80, hi: 0xb5}, - // Block 0x4e, offset 0x226 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xb9}, - {value: 0x0024, lo: 0xba, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbb}, - // Block 0x4f, offset 0x231 - {value: 0x0010, lo: 0x86, hi: 0x8f}, - // Block 0x50, offset 0x232 - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x51, offset 0x233 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0024, lo: 0x97, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x98}, - {value: 0x0010, lo: 0x99, hi: 0x9a}, - {value: 0x0014, lo: 0x9b, hi: 0x9b}, - // Block 0x52, offset 0x238 - {value: 0x0010, lo: 0x95, hi: 0x95}, - {value: 0x0014, lo: 0x96, hi: 0x96}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0014, lo: 0x98, hi: 0x9e}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa2}, - {value: 0x0010, lo: 0xa3, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xac}, - {value: 0x0010, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0024, lo: 0xb5, hi: 0xbc}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x53, offset 0x245 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xa7, hi: 0xa7}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - {value: 0x0034, lo: 0xb5, hi: 0xba}, - {value: 0x0024, lo: 0xbb, hi: 0xbc}, - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0x54, offset 0x24d - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x55, offset 0x255 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x83}, - {value: 0x0030, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x8b}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xab, hi: 0xab}, - {value: 0x0034, lo: 0xac, hi: 0xac}, - {value: 0x0024, lo: 0xad, hi: 0xb3}, - // Block 0x56, offset 0x25e - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0030, lo: 0xaa, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xbf}, - // Block 0x57, offset 0x267 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa9}, - {value: 0x0010, lo: 0xaa, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0030, lo: 0xb2, hi: 0xb3}, - // Block 0x58, offset 0x270 - {value: 0x0010, lo: 0x80, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0x59, offset 0x275 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8d, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x5a, offset 0x278 - {value: 0x1a6a, lo: 0x80, hi: 0x80}, - {value: 0x1aea, lo: 0x81, hi: 0x81}, - {value: 0x1b6a, lo: 0x82, hi: 0x82}, - {value: 0x1bea, lo: 0x83, hi: 0x83}, - {value: 0x1c6a, lo: 0x84, hi: 0x84}, - {value: 0x1cea, lo: 0x85, hi: 0x85}, - {value: 0x1d6a, lo: 0x86, hi: 0x86}, - {value: 0x1dea, lo: 0x87, hi: 0x87}, - {value: 0x1e6a, lo: 0x88, hi: 0x88}, - // Block 0x5b, offset 0x281 - {value: 0x0024, lo: 0x90, hi: 0x92}, - {value: 0x0034, lo: 0x94, hi: 0x99}, - {value: 0x0024, lo: 0x9a, hi: 0x9b}, - {value: 0x0034, lo: 0x9c, hi: 0x9f}, - {value: 0x0024, lo: 0xa0, hi: 0xa0}, - {value: 0x0010, lo: 0xa1, hi: 0xa1}, - {value: 0x0034, lo: 0xa2, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xb3}, - {value: 0x0024, lo: 0xb4, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb6}, - {value: 0x0024, lo: 0xb8, hi: 0xb9}, - // Block 0x5c, offset 0x28e - {value: 0x0012, lo: 0x80, hi: 0xab}, - {value: 0x0015, lo: 0xac, hi: 0xbf}, - // Block 0x5d, offset 0x290 - {value: 0x0015, lo: 0x80, hi: 0xaa}, - {value: 0x0012, lo: 0xab, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb8}, - {value: 0x8452, lo: 0xb9, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbc}, - {value: 0x8852, lo: 0xbd, hi: 0xbd}, - {value: 0x0012, lo: 0xbe, hi: 0xbf}, - // Block 0x5e, offset 0x297 - {value: 0x0012, lo: 0x80, hi: 0x9a}, - {value: 0x0015, lo: 0x9b, hi: 0xbf}, - // Block 0x5f, offset 0x299 - {value: 0x0024, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0024, lo: 0x83, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0024, lo: 0x8b, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x90}, - {value: 0x0024, lo: 0x91, hi: 0xb5}, - {value: 0x0024, lo: 0xbb, hi: 0xbb}, - {value: 0x0034, lo: 0xbc, hi: 0xbd}, - {value: 0x0024, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x60, offset 0x2a4 - {value: 0x0117, lo: 0x80, hi: 0xbf}, - // Block 0x61, offset 0x2a5 - {value: 0x0117, lo: 0x80, hi: 0x95}, - {value: 0x1f1a, lo: 0x96, hi: 0x96}, - {value: 0x1fca, lo: 0x97, hi: 0x97}, - {value: 0x207a, lo: 0x98, hi: 0x98}, - {value: 0x212a, lo: 0x99, hi: 0x99}, - {value: 0x21da, lo: 0x9a, hi: 0x9a}, - {value: 0x228a, lo: 0x9b, hi: 0x9b}, - {value: 0x0012, lo: 0x9c, hi: 0x9d}, - {value: 0x233b, lo: 0x9e, hi: 0x9e}, - {value: 0x0012, lo: 0x9f, hi: 0x9f}, - {value: 0x0117, lo: 0xa0, hi: 0xbf}, - // Block 0x62, offset 0x2b0 - {value: 0x0812, lo: 0x80, hi: 0x87}, - {value: 0x0813, lo: 0x88, hi: 0x8f}, - {value: 0x0812, lo: 0x90, hi: 0x95}, - {value: 0x0813, lo: 0x98, hi: 0x9d}, - {value: 0x0812, lo: 0xa0, hi: 0xa7}, - {value: 0x0813, lo: 0xa8, hi: 0xaf}, - {value: 0x0812, lo: 0xb0, hi: 0xb7}, - {value: 0x0813, lo: 0xb8, hi: 0xbf}, - // Block 0x63, offset 0x2b8 - {value: 0x0004, lo: 0x8b, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8f}, - {value: 0x0054, lo: 0x98, hi: 0x99}, - {value: 0x0054, lo: 0xa4, hi: 0xa4}, - {value: 0x0054, lo: 0xa7, hi: 0xa7}, - {value: 0x0014, lo: 0xaa, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xaf}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x64, offset 0x2c0 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x94, hi: 0x94}, - {value: 0x0014, lo: 0xa0, hi: 0xa4}, - {value: 0x0014, lo: 0xa6, hi: 0xaf}, - {value: 0x0015, lo: 0xb1, hi: 0xb1}, - {value: 0x0015, lo: 0xbf, hi: 0xbf}, - // Block 0x65, offset 0x2c6 - {value: 0x0015, lo: 0x90, hi: 0x9c}, - // Block 0x66, offset 0x2c7 - {value: 0x0024, lo: 0x90, hi: 0x91}, - {value: 0x0034, lo: 0x92, hi: 0x93}, - {value: 0x0024, lo: 0x94, hi: 0x97}, - {value: 0x0034, lo: 0x98, hi: 0x9a}, - {value: 0x0024, lo: 0x9b, hi: 0x9c}, - {value: 0x0014, lo: 0x9d, hi: 0xa0}, - {value: 0x0024, lo: 0xa1, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa4}, - {value: 0x0034, lo: 0xa5, hi: 0xa6}, - {value: 0x0024, lo: 0xa7, hi: 0xa7}, - {value: 0x0034, lo: 0xa8, hi: 0xa8}, - {value: 0x0024, lo: 0xa9, hi: 0xa9}, - {value: 0x0034, lo: 0xaa, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - // Block 0x67, offset 0x2d5 - {value: 0x0016, lo: 0x85, hi: 0x86}, - {value: 0x0012, lo: 0x87, hi: 0x89}, - {value: 0x9d52, lo: 0x8e, hi: 0x8e}, - {value: 0x1013, lo: 0xa0, hi: 0xaf}, - {value: 0x1012, lo: 0xb0, hi: 0xbf}, - // Block 0x68, offset 0x2da - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0716, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x88}, - // Block 0x69, offset 0x2dd - {value: 0xa053, lo: 0xb6, hi: 0xb7}, - {value: 0xa353, lo: 0xb8, hi: 0xb9}, - {value: 0xa653, lo: 0xba, hi: 0xbb}, - {value: 0xa353, lo: 0xbc, hi: 0xbd}, - {value: 0xa053, lo: 0xbe, hi: 0xbf}, - // Block 0x6a, offset 0x2e2 - {value: 0x3013, lo: 0x80, hi: 0x8f}, - {value: 0x6553, lo: 0x90, hi: 0x9f}, - {value: 0xa953, lo: 0xa0, hi: 0xae}, - {value: 0x3012, lo: 0xb0, hi: 0xbf}, - // Block 0x6b, offset 0x2e6 - {value: 0x0117, lo: 0x80, hi: 0xa3}, - {value: 0x0012, lo: 0xa4, hi: 0xa4}, - {value: 0x0716, lo: 0xab, hi: 0xac}, - {value: 0x0316, lo: 0xad, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xb3}, - // Block 0x6c, offset 0x2ec - {value: 0x6c52, lo: 0x80, hi: 0x9f}, - {value: 0x7052, lo: 0xa0, hi: 0xa5}, - {value: 0x7052, lo: 0xa7, hi: 0xa7}, - {value: 0x7052, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x6d, offset 0x2f1 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0x6e, offset 0x2f4 - {value: 0x0010, lo: 0x80, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0010, lo: 0xb0, hi: 0xb6}, - {value: 0x0010, lo: 0xb8, hi: 0xbe}, - // Block 0x6f, offset 0x2f9 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x8e}, - {value: 0x0010, lo: 0x90, hi: 0x96}, - {value: 0x0010, lo: 0x98, hi: 0x9e}, - {value: 0x0024, lo: 0xa0, hi: 0xbf}, - // Block 0x70, offset 0x2fe - {value: 0x0014, lo: 0xaf, hi: 0xaf}, - // Block 0x71, offset 0x2ff - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0xaa, hi: 0xad}, - {value: 0x0030, lo: 0xae, hi: 0xaf}, - {value: 0x0004, lo: 0xb1, hi: 0xb5}, - {value: 0x0014, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - // Block 0x72, offset 0x305 - {value: 0x0034, lo: 0x99, hi: 0x9a}, - {value: 0x0004, lo: 0x9b, hi: 0x9e}, - // Block 0x73, offset 0x307 - {value: 0x0004, lo: 0xbc, hi: 0xbe}, - // Block 0x74, offset 0x308 - {value: 0x0010, lo: 0x85, hi: 0xad}, - {value: 0x0010, lo: 0xb1, hi: 0xbf}, - // Block 0x75, offset 0x30a - {value: 0x0010, lo: 0x80, hi: 0x8e}, - {value: 0x0010, lo: 0xa0, hi: 0xba}, - // Block 0x76, offset 0x30c - {value: 0x0010, lo: 0x80, hi: 0x94}, - {value: 0x0014, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0x96, hi: 0xbf}, - // Block 0x77, offset 0x30f - {value: 0x0010, lo: 0x80, hi: 0x8c}, - // Block 0x78, offset 0x310 - {value: 0x0010, lo: 0x90, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - // Block 0x79, offset 0x312 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0xab}, - // Block 0x7a, offset 0x315 - {value: 0x0117, lo: 0x80, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xae}, - {value: 0x0024, lo: 0xaf, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb2}, - {value: 0x0024, lo: 0xb4, hi: 0xbd}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x7b, offset 0x31b - {value: 0x0117, lo: 0x80, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9d}, - {value: 0x0024, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0x7c, offset 0x31f - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb1}, - // Block 0x7d, offset 0x321 - {value: 0x0004, lo: 0x80, hi: 0x96}, - {value: 0x0014, lo: 0x97, hi: 0x9f}, - {value: 0x0004, lo: 0xa0, hi: 0xa1}, - {value: 0x0117, lo: 0xa2, hi: 0xaf}, - {value: 0x0012, lo: 0xb0, hi: 0xb1}, - {value: 0x0117, lo: 0xb2, hi: 0xbf}, - // Block 0x7e, offset 0x327 - {value: 0x0117, lo: 0x80, hi: 0xaf}, - {value: 0x0015, lo: 0xb0, hi: 0xb0}, - {value: 0x0012, lo: 0xb1, hi: 0xb8}, - {value: 0x0316, lo: 0xb9, hi: 0xba}, - {value: 0x0716, lo: 0xbb, hi: 0xbc}, - {value: 0x8453, lo: 0xbd, hi: 0xbd}, - {value: 0x0117, lo: 0xbe, hi: 0xbf}, - // Block 0x7f, offset 0x32e - {value: 0x0010, lo: 0xb7, hi: 0xb7}, - {value: 0x0015, lo: 0xb8, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbf}, - // Block 0x80, offset 0x332 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0014, lo: 0x82, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8b}, - {value: 0x0010, lo: 0x8c, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa6}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - // Block 0x81, offset 0x33b - {value: 0x0010, lo: 0x80, hi: 0xb3}, - // Block 0x82, offset 0x33c - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0034, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x85, hi: 0x85}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0024, lo: 0xa0, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb7}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x83, offset 0x344 - {value: 0x0010, lo: 0x80, hi: 0xa5}, - {value: 0x0014, lo: 0xa6, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x84, offset 0x348 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0014, lo: 0x87, hi: 0x91}, - {value: 0x0010, lo: 0x92, hi: 0x92}, - {value: 0x0030, lo: 0x93, hi: 0x93}, - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0x85, offset 0x34d - {value: 0x0014, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xb9}, - {value: 0x0010, lo: 0xba, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0x86, offset 0x355 - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0004, lo: 0xa6, hi: 0xa6}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x87, offset 0x35b - {value: 0x0010, lo: 0x80, hi: 0xa8}, - {value: 0x0014, lo: 0xa9, hi: 0xae}, - {value: 0x0010, lo: 0xaf, hi: 0xb0}, - {value: 0x0014, lo: 0xb1, hi: 0xb2}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0x88, offset 0x361 - {value: 0x0010, lo: 0x80, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x8b}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0010, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbd}, - // Block 0x89, offset 0x36b - {value: 0x0024, lo: 0xb0, hi: 0xb0}, - {value: 0x0024, lo: 0xb2, hi: 0xb3}, - {value: 0x0034, lo: 0xb4, hi: 0xb4}, - {value: 0x0024, lo: 0xb7, hi: 0xb8}, - {value: 0x0024, lo: 0xbe, hi: 0xbf}, - // Block 0x8a, offset 0x370 - {value: 0x0024, lo: 0x81, hi: 0x81}, - {value: 0x0004, lo: 0x9d, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xab}, - {value: 0x0014, lo: 0xac, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb2, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - // Block 0x8b, offset 0x379 - {value: 0x0010, lo: 0x81, hi: 0x86}, - {value: 0x0010, lo: 0x89, hi: 0x8e}, - {value: 0x0010, lo: 0x91, hi: 0x96}, - {value: 0x0010, lo: 0xa0, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0x8c, offset 0x37f - {value: 0x0012, lo: 0x80, hi: 0x92}, - {value: 0xac52, lo: 0x93, hi: 0x93}, - {value: 0x0012, lo: 0x94, hi: 0x9a}, - {value: 0x0004, lo: 0x9b, hi: 0x9b}, - {value: 0x0015, lo: 0x9c, hi: 0x9f}, - {value: 0x0012, lo: 0xa0, hi: 0xa5}, - {value: 0x74d2, lo: 0xb0, hi: 0xbf}, - // Block 0x8d, offset 0x386 - {value: 0x78d2, lo: 0x80, hi: 0x8f}, - {value: 0x7cd2, lo: 0x90, hi: 0x9f}, - {value: 0x80d2, lo: 0xa0, hi: 0xaf}, - {value: 0x7cd2, lo: 0xb0, hi: 0xbf}, - // Block 0x8e, offset 0x38a - {value: 0x0010, lo: 0x80, hi: 0xa4}, - {value: 0x0014, lo: 0xa5, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa7}, - {value: 0x0014, lo: 0xa8, hi: 0xa8}, - {value: 0x0010, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0034, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0x8f, offset 0x392 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0x90, offset 0x394 - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x8b, hi: 0xbb}, - // Block 0x91, offset 0x396 - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x86, hi: 0xbf}, - // Block 0x92, offset 0x399 - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0004, lo: 0xb2, hi: 0xbf}, - // Block 0x93, offset 0x39b - {value: 0x0004, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x93, hi: 0xbf}, - // Block 0x94, offset 0x39d - {value: 0x0010, lo: 0x80, hi: 0xbd}, - // Block 0x95, offset 0x39e - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0x96, offset 0x39f - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0xbf}, - // Block 0x97, offset 0x3a1 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0xb0, hi: 0xbb}, - // Block 0x98, offset 0x3a3 - {value: 0x0014, lo: 0x80, hi: 0x8f}, - {value: 0x0054, lo: 0x93, hi: 0x93}, - {value: 0x0024, lo: 0xa0, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xad}, - {value: 0x0024, lo: 0xae, hi: 0xaf}, - {value: 0x0010, lo: 0xb3, hi: 0xb4}, - // Block 0x99, offset 0x3a9 - {value: 0x0010, lo: 0x8d, hi: 0x8f}, - {value: 0x0054, lo: 0x92, hi: 0x92}, - {value: 0x0054, lo: 0x95, hi: 0x95}, - {value: 0x0010, lo: 0xb0, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0x9a, offset 0x3ae - {value: 0x0010, lo: 0x80, hi: 0xbc}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0x9b, offset 0x3b0 - {value: 0x0054, lo: 0x87, hi: 0x87}, - {value: 0x0054, lo: 0x8e, hi: 0x8e}, - {value: 0x0054, lo: 0x9a, hi: 0x9a}, - {value: 0x5f53, lo: 0xa1, hi: 0xba}, - {value: 0x0004, lo: 0xbe, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0x9c, offset 0x3b6 - {value: 0x0004, lo: 0x80, hi: 0x80}, - {value: 0x5f52, lo: 0x81, hi: 0x9a}, - {value: 0x0004, lo: 0xb0, hi: 0xb0}, - // Block 0x9d, offset 0x3b9 - {value: 0x0014, lo: 0x9e, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xbe}, - // Block 0x9e, offset 0x3bb - {value: 0x0010, lo: 0x82, hi: 0x87}, - {value: 0x0010, lo: 0x8a, hi: 0x8f}, - {value: 0x0010, lo: 0x92, hi: 0x97}, - {value: 0x0010, lo: 0x9a, hi: 0x9c}, - {value: 0x0004, lo: 0xa3, hi: 0xa3}, - {value: 0x0014, lo: 0xb9, hi: 0xbb}, - // Block 0x9f, offset 0x3c1 - {value: 0x0010, lo: 0x80, hi: 0x8b}, - {value: 0x0010, lo: 0x8d, hi: 0xa6}, - {value: 0x0010, lo: 0xa8, hi: 0xba}, - {value: 0x0010, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xa0, offset 0x3c6 - {value: 0x0010, lo: 0x80, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x9d}, - // Block 0xa1, offset 0x3c8 - {value: 0x0010, lo: 0x80, hi: 0xba}, - // Block 0xa2, offset 0x3c9 - {value: 0x0010, lo: 0x80, hi: 0xb4}, - // Block 0xa3, offset 0x3ca - {value: 0x0034, lo: 0xbd, hi: 0xbd}, - // Block 0xa4, offset 0x3cb - {value: 0x0010, lo: 0x80, hi: 0x9c}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa5, offset 0x3cd - {value: 0x0010, lo: 0x80, hi: 0x90}, - {value: 0x0034, lo: 0xa0, hi: 0xa0}, - // Block 0xa6, offset 0x3cf - {value: 0x0010, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xa7, offset 0x3d1 - {value: 0x0010, lo: 0x80, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0xb5}, - {value: 0x0024, lo: 0xb6, hi: 0xba}, - // Block 0xa8, offset 0x3d4 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xbf}, - // Block 0xa9, offset 0x3d6 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x91, hi: 0x95}, - // Block 0xaa, offset 0x3d9 - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x97}, - {value: 0xaf53, lo: 0x98, hi: 0x9f}, - {value: 0xb253, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbf}, - // Block 0xab, offset 0x3e1 - {value: 0xaf52, lo: 0x80, hi: 0x87}, - {value: 0xb252, lo: 0x88, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0xbf}, - // Block 0xac, offset 0x3e4 - {value: 0x0010, lo: 0x80, hi: 0x9d}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0xb253, lo: 0xb0, hi: 0xb7}, - {value: 0xaf53, lo: 0xb8, hi: 0xbf}, - // Block 0xad, offset 0x3e8 - {value: 0x2813, lo: 0x80, hi: 0x87}, - {value: 0x3813, lo: 0x88, hi: 0x8f}, - {value: 0x2813, lo: 0x90, hi: 0x93}, - {value: 0xb252, lo: 0x98, hi: 0x9f}, - {value: 0xaf52, lo: 0xa0, hi: 0xa7}, - {value: 0x2812, lo: 0xa8, hi: 0xaf}, - {value: 0x3812, lo: 0xb0, hi: 0xb7}, - {value: 0x2812, lo: 0xb8, hi: 0xbb}, - // Block 0xae, offset 0x3f0 - {value: 0x0010, lo: 0x80, hi: 0xa7}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xaf, offset 0x3f2 - {value: 0x0010, lo: 0x80, hi: 0xa3}, - // Block 0xb0, offset 0x3f3 - {value: 0x0010, lo: 0x80, hi: 0xb6}, - // Block 0xb1, offset 0x3f4 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xa7}, - // Block 0xb2, offset 0x3f6 - {value: 0x0010, lo: 0x80, hi: 0x85}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xb5}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0010, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xb3, offset 0x3fc - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb6}, - // Block 0xb4, offset 0x3fe - {value: 0x0010, lo: 0x80, hi: 0x9e}, - // Block 0xb5, offset 0x3ff - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb5}, - // Block 0xb6, offset 0x401 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb9}, - // Block 0xb7, offset 0x403 - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0010, lo: 0xbe, hi: 0xbf}, - // Block 0xb8, offset 0x405 - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x83}, - {value: 0x0014, lo: 0x85, hi: 0x86}, - {value: 0x0014, lo: 0x8c, hi: 0x8c}, - {value: 0x0034, lo: 0x8d, hi: 0x8d}, - {value: 0x0014, lo: 0x8e, hi: 0x8e}, - {value: 0x0024, lo: 0x8f, hi: 0x8f}, - {value: 0x0010, lo: 0x90, hi: 0x93}, - {value: 0x0010, lo: 0x95, hi: 0x97}, - {value: 0x0010, lo: 0x99, hi: 0xb3}, - {value: 0x0024, lo: 0xb8, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xb9, offset 0x412 - {value: 0x0010, lo: 0xa0, hi: 0xbc}, - // Block 0xba, offset 0x413 - {value: 0x0010, lo: 0x80, hi: 0x9c}, - // Block 0xbb, offset 0x414 - {value: 0x0010, lo: 0x80, hi: 0x87}, - {value: 0x0010, lo: 0x89, hi: 0xa4}, - {value: 0x0024, lo: 0xa5, hi: 0xa5}, - {value: 0x0034, lo: 0xa6, hi: 0xa6}, - // Block 0xbc, offset 0x418 - {value: 0x0010, lo: 0x80, hi: 0x95}, - {value: 0x0010, lo: 0xa0, hi: 0xb2}, - // Block 0xbd, offset 0x41a - {value: 0x0010, lo: 0x80, hi: 0x91}, - // Block 0xbe, offset 0x41b - {value: 0x0010, lo: 0x80, hi: 0x88}, - // Block 0xbf, offset 0x41c - {value: 0x5653, lo: 0x80, hi: 0xb2}, - // Block 0xc0, offset 0x41d - {value: 0x5652, lo: 0x80, hi: 0xb2}, - // Block 0xc1, offset 0x41e - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xc2, offset 0x422 - {value: 0x0014, lo: 0x80, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0xa6, hi: 0xaf}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xc3, offset 0x426 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb6}, - {value: 0x0010, lo: 0xb7, hi: 0xb8}, - {value: 0x0034, lo: 0xb9, hi: 0xba}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - // Block 0xc4, offset 0x42c - {value: 0x0010, lo: 0x90, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xc5, offset 0x42e - {value: 0x0024, lo: 0x80, hi: 0x82}, - {value: 0x0010, lo: 0x83, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb4}, - {value: 0x0010, lo: 0xb6, hi: 0xbf}, - // Block 0xc6, offset 0x435 - {value: 0x0010, lo: 0x90, hi: 0xb2}, - {value: 0x0034, lo: 0xb3, hi: 0xb3}, - {value: 0x0010, lo: 0xb6, hi: 0xb6}, - // Block 0xc7, offset 0x438 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0xb5}, - {value: 0x0014, lo: 0xb6, hi: 0xbe}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xc8, offset 0x43c - {value: 0x0030, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0014, lo: 0x8b, hi: 0x8c}, - {value: 0x0010, lo: 0x90, hi: 0x9a}, - {value: 0x0010, lo: 0x9c, hi: 0x9c}, - // Block 0xc9, offset 0x442 - {value: 0x0010, lo: 0x80, hi: 0x91}, - {value: 0x0010, lo: 0x93, hi: 0xae}, - {value: 0x0014, lo: 0xaf, hi: 0xb1}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0014, lo: 0xb4, hi: 0xb4}, - {value: 0x0030, lo: 0xb5, hi: 0xb5}, - {value: 0x0034, lo: 0xb6, hi: 0xb6}, - {value: 0x0014, lo: 0xb7, hi: 0xb7}, - {value: 0x0014, lo: 0xbe, hi: 0xbe}, - // Block 0xca, offset 0x44b - {value: 0x0010, lo: 0x80, hi: 0x86}, - {value: 0x0010, lo: 0x88, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0x8d}, - {value: 0x0010, lo: 0x8f, hi: 0x9d}, - {value: 0x0010, lo: 0x9f, hi: 0xa8}, - {value: 0x0010, lo: 0xb0, hi: 0xbf}, - // Block 0xcb, offset 0x451 - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0014, lo: 0x9f, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa2}, - {value: 0x0014, lo: 0xa3, hi: 0xa8}, - {value: 0x0034, lo: 0xa9, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xcc, offset 0x457 - {value: 0x0014, lo: 0x80, hi: 0x81}, - {value: 0x0010, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x8c}, - {value: 0x0010, lo: 0x8f, hi: 0x90}, - {value: 0x0010, lo: 0x93, hi: 0xa8}, - {value: 0x0010, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb5, hi: 0xb9}, - {value: 0x0034, lo: 0xbc, hi: 0xbc}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xcd, offset 0x461 - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x84}, - {value: 0x0010, lo: 0x87, hi: 0x88}, - {value: 0x0010, lo: 0x8b, hi: 0x8c}, - {value: 0x0030, lo: 0x8d, hi: 0x8d}, - {value: 0x0010, lo: 0x90, hi: 0x90}, - {value: 0x0010, lo: 0x97, hi: 0x97}, - {value: 0x0010, lo: 0x9d, hi: 0xa3}, - {value: 0x0024, lo: 0xa6, hi: 0xac}, - {value: 0x0024, lo: 0xb0, hi: 0xb4}, - // Block 0xce, offset 0x46b - {value: 0x0010, lo: 0x80, hi: 0xb7}, - {value: 0x0014, lo: 0xb8, hi: 0xbf}, - // Block 0xcf, offset 0x46d - {value: 0x0010, lo: 0x80, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x82}, - {value: 0x0014, lo: 0x83, hi: 0x84}, - {value: 0x0010, lo: 0x85, hi: 0x85}, - {value: 0x0034, lo: 0x86, hi: 0x86}, - {value: 0x0010, lo: 0x87, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd0, offset 0x474 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xb8}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0014, lo: 0xba, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbe}, - {value: 0x0014, lo: 0xbf, hi: 0xbf}, - // Block 0xd1, offset 0x47a - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x81, hi: 0x81}, - {value: 0x0034, lo: 0x82, hi: 0x83}, - {value: 0x0010, lo: 0x84, hi: 0x85}, - {value: 0x0010, lo: 0x87, hi: 0x87}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd2, offset 0x480 - {value: 0x0010, lo: 0x80, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb5}, - {value: 0x0010, lo: 0xb8, hi: 0xbb}, - {value: 0x0014, lo: 0xbc, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd3, offset 0x486 - {value: 0x0034, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x98, hi: 0x9b}, - {value: 0x0014, lo: 0x9c, hi: 0x9d}, - // Block 0xd4, offset 0x489 - {value: 0x0010, lo: 0x80, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0010, lo: 0xbb, hi: 0xbc}, - {value: 0x0014, lo: 0xbd, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xd5, offset 0x48f - {value: 0x0014, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x84, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0xd6, offset 0x492 - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0014, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xac, hi: 0xac}, - {value: 0x0014, lo: 0xad, hi: 0xad}, - {value: 0x0010, lo: 0xae, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb5}, - {value: 0x0030, lo: 0xb6, hi: 0xb6}, - {value: 0x0034, lo: 0xb7, hi: 0xb7}, - // Block 0xd7, offset 0x49a - {value: 0x0010, lo: 0x80, hi: 0x89}, - // Block 0xd8, offset 0x49b - {value: 0x0014, lo: 0x9d, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa1}, - {value: 0x0014, lo: 0xa2, hi: 0xa5}, - {value: 0x0010, lo: 0xa6, hi: 0xa6}, - {value: 0x0014, lo: 0xa7, hi: 0xaa}, - {value: 0x0034, lo: 0xab, hi: 0xab}, - {value: 0x0010, lo: 0xb0, hi: 0xb9}, - // Block 0xd9, offset 0x4a2 - {value: 0x5f53, lo: 0xa0, hi: 0xbf}, - // Block 0xda, offset 0x4a3 - {value: 0x5f52, lo: 0x80, hi: 0x9f}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - {value: 0x0010, lo: 0xbf, hi: 0xbf}, - // Block 0xdb, offset 0x4a6 - {value: 0x0010, lo: 0x80, hi: 0xb8}, - // Block 0xdc, offset 0x4a7 - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x8a, hi: 0xaf}, - {value: 0x0014, lo: 0xb0, hi: 0xb6}, - {value: 0x0014, lo: 0xb8, hi: 0xbd}, - {value: 0x0010, lo: 0xbe, hi: 0xbe}, - {value: 0x0034, lo: 0xbf, hi: 0xbf}, - // Block 0xdd, offset 0x4ad - {value: 0x0010, lo: 0x80, hi: 0x80}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xb2, hi: 0xbf}, - // Block 0xde, offset 0x4b0 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - {value: 0x0014, lo: 0x92, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xa9}, - {value: 0x0014, lo: 0xaa, hi: 0xb0}, - {value: 0x0010, lo: 0xb1, hi: 0xb1}, - {value: 0x0014, lo: 0xb2, hi: 0xb3}, - {value: 0x0010, lo: 0xb4, hi: 0xb4}, - {value: 0x0014, lo: 0xb5, hi: 0xb6}, - // Block 0xdf, offset 0x4b8 - {value: 0x0010, lo: 0x80, hi: 0x99}, - // Block 0xe0, offset 0x4b9 - {value: 0x0010, lo: 0x80, hi: 0xae}, - // Block 0xe1, offset 0x4ba - {value: 0x0010, lo: 0x80, hi: 0x83}, - // Block 0xe2, offset 0x4bb - {value: 0x0010, lo: 0x80, hi: 0x86}, - // Block 0xe3, offset 0x4bc - {value: 0x0010, lo: 0x80, hi: 0x9e}, - {value: 0x0010, lo: 0xa0, hi: 0xa9}, - // Block 0xe4, offset 0x4be - {value: 0x0010, lo: 0x90, hi: 0xad}, - {value: 0x0034, lo: 0xb0, hi: 0xb4}, - // Block 0xe5, offset 0x4c0 - {value: 0x0010, lo: 0x80, hi: 0xaf}, - {value: 0x0024, lo: 0xb0, hi: 0xb6}, - // Block 0xe6, offset 0x4c2 - {value: 0x0014, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0010, lo: 0xa3, hi: 0xb7}, - {value: 0x0010, lo: 0xbd, hi: 0xbf}, - // Block 0xe7, offset 0x4c6 - {value: 0x0010, lo: 0x80, hi: 0x8f}, - // Block 0xe8, offset 0x4c7 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0010, lo: 0x90, hi: 0xbe}, - // Block 0xe9, offset 0x4c9 - {value: 0x0014, lo: 0x8f, hi: 0x9f}, - // Block 0xea, offset 0x4ca - {value: 0x0014, lo: 0xa0, hi: 0xa0}, - // Block 0xeb, offset 0x4cb - {value: 0x0010, lo: 0x80, hi: 0xaa}, - {value: 0x0010, lo: 0xb0, hi: 0xbc}, - // Block 0xec, offset 0x4cd - {value: 0x0010, lo: 0x80, hi: 0x88}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - {value: 0x0014, lo: 0x9d, hi: 0x9d}, - {value: 0x0034, lo: 0x9e, hi: 0x9e}, - {value: 0x0014, lo: 0xa0, hi: 0xa3}, - // Block 0xed, offset 0x4d2 - {value: 0x0030, lo: 0xa5, hi: 0xa6}, - {value: 0x0034, lo: 0xa7, hi: 0xa9}, - {value: 0x0030, lo: 0xad, hi: 0xb2}, - {value: 0x0014, lo: 0xb3, hi: 0xba}, - {value: 0x0034, lo: 0xbb, hi: 0xbf}, - // Block 0xee, offset 0x4d7 - {value: 0x0034, lo: 0x80, hi: 0x82}, - {value: 0x0024, lo: 0x85, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8b}, - {value: 0x0024, lo: 0xaa, hi: 0xad}, - // Block 0xef, offset 0x4db - {value: 0x0024, lo: 0x82, hi: 0x84}, - // Block 0xf0, offset 0x4dc - {value: 0x0013, lo: 0x80, hi: 0x99}, - {value: 0x0012, lo: 0x9a, hi: 0xb3}, - {value: 0x0013, lo: 0xb4, hi: 0xbf}, - // Block 0xf1, offset 0x4df - {value: 0x0013, lo: 0x80, hi: 0x8d}, - {value: 0x0012, lo: 0x8e, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0xa7}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0xf2, offset 0x4e3 - {value: 0x0013, lo: 0x80, hi: 0x81}, - {value: 0x0012, lo: 0x82, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0x9c}, - {value: 0x0013, lo: 0x9e, hi: 0x9f}, - {value: 0x0013, lo: 0xa2, hi: 0xa2}, - {value: 0x0013, lo: 0xa5, hi: 0xa6}, - {value: 0x0013, lo: 0xa9, hi: 0xac}, - {value: 0x0013, lo: 0xae, hi: 0xb5}, - {value: 0x0012, lo: 0xb6, hi: 0xb9}, - {value: 0x0012, lo: 0xbb, hi: 0xbb}, - {value: 0x0012, lo: 0xbd, hi: 0xbf}, - // Block 0xf3, offset 0x4ee - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0012, lo: 0x85, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0xf4, offset 0x4f2 - {value: 0x0012, lo: 0x80, hi: 0x83}, - {value: 0x0013, lo: 0x84, hi: 0x85}, - {value: 0x0013, lo: 0x87, hi: 0x8a}, - {value: 0x0013, lo: 0x8d, hi: 0x94}, - {value: 0x0013, lo: 0x96, hi: 0x9c}, - {value: 0x0012, lo: 0x9e, hi: 0xb7}, - {value: 0x0013, lo: 0xb8, hi: 0xb9}, - {value: 0x0013, lo: 0xbb, hi: 0xbe}, - // Block 0xf5, offset 0x4fa - {value: 0x0013, lo: 0x80, hi: 0x84}, - {value: 0x0013, lo: 0x86, hi: 0x86}, - {value: 0x0013, lo: 0x8a, hi: 0x90}, - {value: 0x0012, lo: 0x92, hi: 0xab}, - {value: 0x0013, lo: 0xac, hi: 0xbf}, - // Block 0xf6, offset 0x4ff - {value: 0x0013, lo: 0x80, hi: 0x85}, - {value: 0x0012, lo: 0x86, hi: 0x9f}, - {value: 0x0013, lo: 0xa0, hi: 0xb9}, - {value: 0x0012, lo: 0xba, hi: 0xbf}, - // Block 0xf7, offset 0x503 - {value: 0x0012, lo: 0x80, hi: 0x93}, - {value: 0x0013, lo: 0x94, hi: 0xad}, - {value: 0x0012, lo: 0xae, hi: 0xbf}, - // Block 0xf8, offset 0x506 - {value: 0x0012, lo: 0x80, hi: 0x87}, - {value: 0x0013, lo: 0x88, hi: 0xa1}, - {value: 0x0012, lo: 0xa2, hi: 0xbb}, - {value: 0x0013, lo: 0xbc, hi: 0xbf}, - // Block 0xf9, offset 0x50a - {value: 0x0013, lo: 0x80, hi: 0x95}, - {value: 0x0012, lo: 0x96, hi: 0xaf}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0xfa, offset 0x50d - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0012, lo: 0x8a, hi: 0xa5}, - {value: 0x0013, lo: 0xa8, hi: 0xbf}, - // Block 0xfb, offset 0x510 - {value: 0x0013, lo: 0x80, hi: 0x80}, - {value: 0x0012, lo: 0x82, hi: 0x9a}, - {value: 0x0012, lo: 0x9c, hi: 0xa1}, - {value: 0x0013, lo: 0xa2, hi: 0xba}, - {value: 0x0012, lo: 0xbc, hi: 0xbf}, - // Block 0xfc, offset 0x515 - {value: 0x0012, lo: 0x80, hi: 0x94}, - {value: 0x0012, lo: 0x96, hi: 0x9b}, - {value: 0x0013, lo: 0x9c, hi: 0xb4}, - {value: 0x0012, lo: 0xb6, hi: 0xbf}, - // Block 0xfd, offset 0x519 - {value: 0x0012, lo: 0x80, hi: 0x8e}, - {value: 0x0012, lo: 0x90, hi: 0x95}, - {value: 0x0013, lo: 0x96, hi: 0xae}, - {value: 0x0012, lo: 0xb0, hi: 0xbf}, - // Block 0xfe, offset 0x51d - {value: 0x0012, lo: 0x80, hi: 0x88}, - {value: 0x0012, lo: 0x8a, hi: 0x8f}, - {value: 0x0013, lo: 0x90, hi: 0xa8}, - {value: 0x0012, lo: 0xaa, hi: 0xbf}, - // Block 0xff, offset 0x521 - {value: 0x0012, lo: 0x80, hi: 0x82}, - {value: 0x0012, lo: 0x84, hi: 0x89}, - {value: 0x0017, lo: 0x8a, hi: 0x8b}, - {value: 0x0010, lo: 0x8e, hi: 0xbf}, - // Block 0x100, offset 0x525 - {value: 0x0014, lo: 0x80, hi: 0xb6}, - {value: 0x0014, lo: 0xbb, hi: 0xbf}, - // Block 0x101, offset 0x527 - {value: 0x0014, lo: 0x80, hi: 0xac}, - {value: 0x0014, lo: 0xb5, hi: 0xb5}, - // Block 0x102, offset 0x529 - {value: 0x0014, lo: 0x84, hi: 0x84}, - {value: 0x0014, lo: 0x9b, hi: 0x9f}, - {value: 0x0014, lo: 0xa1, hi: 0xaf}, - // Block 0x103, offset 0x52c - {value: 0x0024, lo: 0x80, hi: 0x86}, - {value: 0x0024, lo: 0x88, hi: 0x98}, - {value: 0x0024, lo: 0x9b, hi: 0xa1}, - {value: 0x0024, lo: 0xa3, hi: 0xa4}, - {value: 0x0024, lo: 0xa6, hi: 0xaa}, - // Block 0x104, offset 0x531 - {value: 0x0010, lo: 0x80, hi: 0x84}, - {value: 0x0034, lo: 0x90, hi: 0x96}, - // Block 0x105, offset 0x533 - {value: 0xb552, lo: 0x80, hi: 0x81}, - {value: 0xb852, lo: 0x82, hi: 0x83}, - {value: 0x0024, lo: 0x84, hi: 0x89}, - {value: 0x0034, lo: 0x8a, hi: 0x8a}, - {value: 0x0010, lo: 0x90, hi: 0x99}, - // Block 0x106, offset 0x538 - {value: 0x0010, lo: 0x80, hi: 0x83}, - {value: 0x0010, lo: 0x85, hi: 0x9f}, - {value: 0x0010, lo: 0xa1, hi: 0xa2}, - {value: 0x0010, lo: 0xa4, hi: 0xa4}, - {value: 0x0010, lo: 0xa7, hi: 0xa7}, - {value: 0x0010, lo: 0xa9, hi: 0xb2}, - {value: 0x0010, lo: 0xb4, hi: 0xb7}, - {value: 0x0010, lo: 0xb9, hi: 0xb9}, - {value: 0x0010, lo: 0xbb, hi: 0xbb}, - // Block 0x107, offset 0x541 - {value: 0x0010, lo: 0x80, hi: 0x89}, - {value: 0x0010, lo: 0x8b, hi: 0x9b}, - {value: 0x0010, lo: 0xa1, hi: 0xa3}, - {value: 0x0010, lo: 0xa5, hi: 0xa9}, - {value: 0x0010, lo: 0xab, hi: 0xbb}, - // Block 0x108, offset 0x546 - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x109, offset 0x547 - {value: 0x0013, lo: 0x80, hi: 0x89}, - {value: 0x0013, lo: 0x90, hi: 0xa9}, - {value: 0x0013, lo: 0xb0, hi: 0xbf}, - // Block 0x10a, offset 0x54a - {value: 0x0013, lo: 0x80, hi: 0x89}, - // Block 0x10b, offset 0x54b - {value: 0x0004, lo: 0xbb, hi: 0xbf}, - // Block 0x10c, offset 0x54c - {value: 0x0014, lo: 0x81, hi: 0x81}, - {value: 0x0014, lo: 0xa0, hi: 0xbf}, - // Block 0x10d, offset 0x54e - {value: 0x0014, lo: 0x80, hi: 0xbf}, - // Block 0x10e, offset 0x54f - {value: 0x0014, lo: 0x80, hi: 0xaf}, -} - -// Total table size 14027 bytes (13KiB); checksum: F17D40E8 diff --git a/vendor/golang.org/x/text/cases/trieval.go b/vendor/golang.org/x/text/cases/trieval.go deleted file mode 100644 index 4e4d13fe..00000000 --- a/vendor/golang.org/x/text/cases/trieval.go +++ /dev/null @@ -1,217 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package cases - -// This file contains definitions for interpreting the trie value of the case -// trie generated by "go run gen*.go". It is shared by both the generator -// program and the resultant package. Sharing is achieved by the generator -// copying gen_trieval.go to trieval.go and changing what's above this comment. - -// info holds case information for a single rune. It is the value returned -// by a trie lookup. Most mapping information can be stored in a single 16-bit -// value. If not, for example when a rune is mapped to multiple runes, the value -// stores some basic case data and an index into an array with additional data. -// -// The per-rune values have the following format: -// -// if (exception) { -// 15..4 unsigned exception index -// } else { -// 15..8 XOR pattern or index to XOR pattern for case mapping -// Only 13..8 are used for XOR patterns. -// 7 inverseFold (fold to upper, not to lower) -// 6 index: interpret the XOR pattern as an index -// or isMid if case mode is cIgnorableUncased. -// 5..4 CCC: zero (normal or break), above or other -// } -// 3 exception: interpret this value as an exception index -// (TODO: is this bit necessary? Probably implied from case mode.) -// 2..0 case mode -// -// For the non-exceptional cases, a rune must be either uncased, lowercase or -// uppercase. If the rune is cased, the XOR pattern maps either a lowercase -// rune to uppercase or an uppercase rune to lowercase (applied to the 10 -// least-significant bits of the rune). -// -// See the definitions below for a more detailed description of the various -// bits. -type info uint16 - -const ( - casedMask = 0x0003 - fullCasedMask = 0x0007 - ignorableMask = 0x0006 - ignorableValue = 0x0004 - - inverseFoldBit = 1 << 7 - isMidBit = 1 << 6 - - exceptionBit = 1 << 3 - exceptionShift = 4 - numExceptionBits = 12 - - xorIndexBit = 1 << 6 - xorShift = 8 - - // There is no mapping if all xor bits and the exception bit are zero. - hasMappingMask = 0xff80 | exceptionBit -) - -// The case mode bits encodes the case type of a rune. This includes uncased, -// title, upper and lower case and case ignorable. (For a definition of these -// terms see Chapter 3 of The Unicode Standard Core Specification.) In some rare -// cases, a rune can be both cased and case-ignorable. This is encoded by -// cIgnorableCased. A rune of this type is always lower case. Some runes are -// cased while not having a mapping. -// -// A common pattern for scripts in the Unicode standard is for upper and lower -// case runes to alternate for increasing rune values (e.g. the accented Latin -// ranges starting from U+0100 and U+1E00 among others and some Cyrillic -// characters). We use this property by defining a cXORCase mode, where the case -// mode (always upper or lower case) is derived from the rune value. As the XOR -// pattern for case mappings is often identical for successive runes, using -// cXORCase can result in large series of identical trie values. This, in turn, -// allows us to better compress the trie blocks. -const ( - cUncased info = iota // 000 - cTitle // 001 - cLower // 010 - cUpper // 011 - cIgnorableUncased // 100 - cIgnorableCased // 101 // lower case if mappings exist - cXORCase // 11x // case is cLower | ((rune&1) ^ x) - - maxCaseMode = cUpper -) - -func (c info) isCased() bool { - return c&casedMask != 0 -} - -func (c info) isCaseIgnorable() bool { - return c&ignorableMask == ignorableValue -} - -func (c info) isNotCasedAndNotCaseIgnorable() bool { - return c&fullCasedMask == 0 -} - -func (c info) isCaseIgnorableAndNotCased() bool { - return c&fullCasedMask == cIgnorableUncased -} - -func (c info) isMid() bool { - return c&(fullCasedMask|isMidBit) == isMidBit|cIgnorableUncased -} - -// The case mapping implementation will need to know about various Canonical -// Combining Class (CCC) values. We encode two of these in the trie value: -// cccZero (0) and cccAbove (230). If the value is cccOther, it means that -// CCC(r) > 0, but not 230. A value of cccBreak means that CCC(r) == 0 and that -// the rune also has the break category Break (see below). -const ( - cccBreak info = iota << 4 - cccZero - cccAbove - cccOther - - cccMask = cccBreak | cccZero | cccAbove | cccOther -) - -const ( - starter = 0 - above = 230 - iotaSubscript = 240 -) - -// The exceptions slice holds data that does not fit in a normal info entry. -// The entry is pointed to by the exception index in an entry. It has the -// following format: -// -// Header: -// -// byte 0: -// 7..6 unused -// 5..4 CCC type (same bits as entry) -// 3 unused -// 2..0 length of fold -// -// byte 1: -// 7..6 unused -// 5..3 length of 1st mapping of case type -// 2..0 length of 2nd mapping of case type -// -// case 1st 2nd -// lower -> upper, title -// upper -> lower, title -// title -> lower, upper -// -// Lengths with the value 0x7 indicate no value and implies no change. -// A length of 0 indicates a mapping to zero-length string. -// -// Body bytes: -// -// case folding bytes -// lowercase mapping bytes -// uppercase mapping bytes -// titlecase mapping bytes -// closure mapping bytes (for NFKC_Casefold). (TODO) -// -// Fallbacks: -// -// missing fold -> lower -// missing title -> upper -// all missing -> original rune -// -// exceptions starts with a dummy byte to enforce that there is no zero index -// value. -const ( - lengthMask = 0x07 - lengthBits = 3 - noChange = 0 -) - -// References to generated trie. - -var trie = newCaseTrie(0) - -var sparse = sparseBlocks{ - values: sparseValues[:], - offsets: sparseOffsets[:], -} - -// Sparse block lookup code. - -// valueRange is an entry in a sparse block. -type valueRange struct { - value uint16 - lo, hi byte -} - -type sparseBlocks struct { - values []valueRange - offsets []uint16 -} - -// lookup returns the value from values block n for byte b using binary search. -func (s *sparseBlocks) lookup(n uint32, b byte) uint16 { - lo := s.offsets[n] - hi := s.offsets[n+1] - for lo < hi { - m := lo + (hi-lo)/2 - r := s.values[m] - if r.lo <= b && b <= r.hi { - return r.value - } - if b < r.lo { - hi = m - } else { - lo = m + 1 - } - } - return 0 -} - -// lastRuneForTesting is the last rune used for testing. Everything after this -// is boring. -const lastRuneForTesting = rune(0x1FFFF) diff --git a/vendor/golang.org/x/text/internal/internal.go b/vendor/golang.org/x/text/internal/internal.go deleted file mode 100644 index 3cddbbdd..00000000 --- a/vendor/golang.org/x/text/internal/internal.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 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 internal contains non-exported functionality that are used by -// packages in the text repository. -package internal // import "golang.org/x/text/internal" - -import ( - "sort" - - "golang.org/x/text/language" -) - -// SortTags sorts tags in place. -func SortTags(tags []language.Tag) { - sort.Sort(sorter(tags)) -} - -type sorter []language.Tag - -func (s sorter) Len() int { - return len(s) -} - -func (s sorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s sorter) Less(i, j int) bool { - return s[i].String() < s[j].String() -} - -// UniqueTags sorts and filters duplicate tags in place and returns a slice with -// only unique tags. -func UniqueTags(tags []language.Tag) []language.Tag { - if len(tags) <= 1 { - return tags - } - SortTags(tags) - k := 0 - for i := 1; i < len(tags); i++ { - if tags[k].String() < tags[i].String() { - k++ - tags[k] = tags[i] - } - } - return tags[:k+1] -} diff --git a/vendor/golang.org/x/text/internal/language/common.go b/vendor/golang.org/x/text/internal/language/common.go deleted file mode 100644 index cdfdb749..00000000 --- a/vendor/golang.org/x/text/internal/language/common.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package language - -// This file contains code common to the maketables.go and the package code. - -// AliasType is the type of an alias in AliasMap. -type AliasType int8 - -const ( - Deprecated AliasType = iota - Macro - Legacy - - AliasTypeUnknown AliasType = -1 -) diff --git a/vendor/golang.org/x/text/internal/language/compact.go b/vendor/golang.org/x/text/internal/language/compact.go deleted file mode 100644 index 46a00150..00000000 --- a/vendor/golang.org/x/text/internal/language/compact.go +++ /dev/null @@ -1,29 +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. - -package language - -// CompactCoreInfo is a compact integer with the three core tags encoded. -type CompactCoreInfo uint32 - -// GetCompactCore generates a uint32 value that is guaranteed to be unique for -// different language, region, and script values. -func GetCompactCore(t Tag) (cci CompactCoreInfo, ok bool) { - if t.LangID > langNoIndexOffset { - return 0, false - } - cci |= CompactCoreInfo(t.LangID) << (8 + 12) - cci |= CompactCoreInfo(t.ScriptID) << 12 - cci |= CompactCoreInfo(t.RegionID) - return cci, true -} - -// Tag generates a tag from c. -func (c CompactCoreInfo) Tag() Tag { - return Tag{ - LangID: Language(c >> 20), - RegionID: Region(c & 0x3ff), - ScriptID: Script(c>>12) & 0xff, - } -} diff --git a/vendor/golang.org/x/text/internal/language/compact/compact.go b/vendor/golang.org/x/text/internal/language/compact/compact.go deleted file mode 100644 index 1b36935e..00000000 --- a/vendor/golang.org/x/text/internal/language/compact/compact.go +++ /dev/null @@ -1,61 +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. - -// Package compact defines a compact representation of language tags. -// -// Common language tags (at least all for which locale information is defined -// in CLDR) are assigned a unique index. Each Tag is associated with such an -// ID for selecting language-related resources (such as translations) as well -// as one for selecting regional defaults (currency, number formatting, etc.) -// -// It may want to export this functionality at some point, but at this point -// this is only available for use within x/text. -package compact // import "golang.org/x/text/internal/language/compact" - -import ( - "sort" - "strings" - - "golang.org/x/text/internal/language" -) - -// ID is an integer identifying a single tag. -type ID uint16 - -func getCoreIndex(t language.Tag) (id ID, ok bool) { - cci, ok := language.GetCompactCore(t) - if !ok { - return 0, false - } - i := sort.Search(len(coreTags), func(i int) bool { - return cci <= coreTags[i] - }) - if i == len(coreTags) || coreTags[i] != cci { - return 0, false - } - return ID(i), true -} - -// Parent returns the ID of the parent or the root ID if id is already the root. -func (id ID) Parent() ID { - return parents[id] -} - -// Tag converts id to an internal language Tag. -func (id ID) Tag() language.Tag { - if int(id) >= len(coreTags) { - return specialTags[int(id)-len(coreTags)] - } - return coreTags[id].Tag() -} - -var specialTags []language.Tag - -func init() { - tags := strings.Split(specialTagsStr, " ") - specialTags = make([]language.Tag, len(tags)) - for i, t := range tags { - specialTags[i] = language.MustParse(t) - } -} diff --git a/vendor/golang.org/x/text/internal/language/compact/language.go b/vendor/golang.org/x/text/internal/language/compact/language.go deleted file mode 100644 index 8c1b6666..00000000 --- a/vendor/golang.org/x/text/internal/language/compact/language.go +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen.go gen_index.go -output tables.go -//go:generate go run gen_parents.go - -package compact - -// TODO: Remove above NOTE after: -// - verifying that tables are dropped correctly (most notably matcher tables). - -import ( - "strings" - - "golang.org/x/text/internal/language" -) - -// Tag represents a BCP 47 language tag. It is used to specify an instance of a -// specific language or locale. All language tag values are guaranteed to be -// well-formed. -type Tag struct { - // NOTE: exported tags will become part of the public API. - language ID - locale ID - full fullTag // always a language.Tag for now. -} - -const _und = 0 - -type fullTag interface { - IsRoot() bool - Parent() language.Tag -} - -// Make a compact Tag from a fully specified internal language Tag. -func Make(t language.Tag) (tag Tag) { - if region := t.TypeForKey("rg"); len(region) == 6 && region[2:] == "zzzz" { - if r, err := language.ParseRegion(region[:2]); err == nil { - tFull := t - t, _ = t.SetTypeForKey("rg", "") - // TODO: should we not consider "va" for the language tag? - var exact1, exact2 bool - tag.language, exact1 = FromTag(t) - t.RegionID = r - tag.locale, exact2 = FromTag(t) - if !exact1 || !exact2 { - tag.full = tFull - } - return tag - } - } - lang, ok := FromTag(t) - tag.language = lang - tag.locale = lang - if !ok { - tag.full = t - } - return tag -} - -// Tag returns an internal language Tag version of this tag. -func (t Tag) Tag() language.Tag { - if t.full != nil { - return t.full.(language.Tag) - } - tag := t.language.Tag() - if t.language != t.locale { - loc := t.locale.Tag() - tag, _ = tag.SetTypeForKey("rg", strings.ToLower(loc.RegionID.String())+"zzzz") - } - return tag -} - -// IsCompact reports whether this tag is fully defined in terms of ID. -func (t *Tag) IsCompact() bool { - return t.full == nil -} - -// MayHaveVariants reports whether a tag may have variants. If it returns false -// it is guaranteed the tag does not have variants. -func (t Tag) MayHaveVariants() bool { - return t.full != nil || int(t.language) >= len(coreTags) -} - -// MayHaveExtensions reports whether a tag may have extensions. If it returns -// false it is guaranteed the tag does not have them. -func (t Tag) MayHaveExtensions() bool { - return t.full != nil || - int(t.language) >= len(coreTags) || - t.language != t.locale -} - -// IsRoot returns true if t is equal to language "und". -func (t Tag) IsRoot() bool { - if t.full != nil { - return t.full.IsRoot() - } - return t.language == _und -} - -// Parent returns the CLDR parent of t. In CLDR, missing fields in data for a -// specific language are substituted with fields from the parent language. -// The parent for a language may change for newer versions of CLDR. -func (t Tag) Parent() Tag { - if t.full != nil { - return Make(t.full.Parent()) - } - if t.language != t.locale { - // Simulate stripping -u-rg-xxxxxx - return Tag{language: t.language, locale: t.language} - } - // TODO: use parent lookup table once cycle from internal package is - // removed. Probably by internalizing the table and declaring this fast - // enough. - // lang := compactID(internal.Parent(uint16(t.language))) - lang, _ := FromTag(t.language.Tag().Parent()) - return Tag{language: lang, locale: lang} -} - -// nextToken returns token t and the rest of the string. -func nextToken(s string) (t, tail string) { - p := strings.Index(s[1:], "-") - if p == -1 { - return s[1:], "" - } - p++ - return s[1:p], s[p:] -} - -// LanguageID returns an index, where 0 <= index < NumCompactTags, for tags -// for which data exists in the text repository.The index will change over time -// and should not be stored in persistent storage. If t does not match a compact -// index, exact will be false and the compact index will be returned for the -// first match after repeatedly taking the Parent of t. -func LanguageID(t Tag) (id ID, exact bool) { - return t.language, t.full == nil -} - -// RegionalID returns the ID for the regional variant of this tag. This index is -// used to indicate region-specific overrides, such as default currency, default -// calendar and week data, default time cycle, and default measurement system -// and unit preferences. -// -// For instance, the tag en-GB-u-rg-uszzzz specifies British English with US -// settings for currency, number formatting, etc. The CompactIndex for this tag -// will be that for en-GB, while the RegionalID will be the one corresponding to -// en-US. -func RegionalID(t Tag) (id ID, exact bool) { - return t.locale, t.full == nil -} - -// LanguageTag returns t stripped of regional variant indicators. -// -// At the moment this means it is stripped of a regional and variant subtag "rg" -// and "va" in the "u" extension. -func (t Tag) LanguageTag() Tag { - if t.full == nil { - return Tag{language: t.language, locale: t.language} - } - tt := t.Tag() - tt.SetTypeForKey("rg", "") - tt.SetTypeForKey("va", "") - return Make(tt) -} - -// RegionalTag returns the regional variant of the tag. -// -// At the moment this means that the region is set from the regional subtag -// "rg" in the "u" extension. -func (t Tag) RegionalTag() Tag { - rt := Tag{language: t.locale, locale: t.locale} - if t.full == nil { - return rt - } - b := language.Builder{} - tag := t.Tag() - // tag, _ = tag.SetTypeForKey("rg", "") - b.SetTag(t.locale.Tag()) - if v := tag.Variants(); v != "" { - for _, v := range strings.Split(v, "-") { - b.AddVariant(v) - } - } - for _, e := range tag.Extensions() { - b.AddExt(e) - } - return t -} - -// FromTag reports closest matching ID for an internal language Tag. -func FromTag(t language.Tag) (id ID, exact bool) { - // TODO: perhaps give more frequent tags a lower index. - // TODO: we could make the indexes stable. This will excluded some - // possibilities for optimization, so don't do this quite yet. - exact = true - - b, s, r := t.Raw() - if t.HasString() { - if t.IsPrivateUse() { - // We have no entries for user-defined tags. - return 0, false - } - hasExtra := false - if t.HasVariants() { - if t.HasExtensions() { - build := language.Builder{} - build.SetTag(language.Tag{LangID: b, ScriptID: s, RegionID: r}) - build.AddVariant(t.Variants()) - exact = false - t = build.Make() - } - hasExtra = true - } else if _, ok := t.Extension('u'); ok { - // TODO: va may mean something else. Consider not considering it. - // Strip all but the 'va' entry. - old := t - variant := t.TypeForKey("va") - t = language.Tag{LangID: b, ScriptID: s, RegionID: r} - if variant != "" { - t, _ = t.SetTypeForKey("va", variant) - hasExtra = true - } - exact = old == t - } else { - exact = false - } - if hasExtra { - // We have some variants. - for i, s := range specialTags { - if s == t { - return ID(i + len(coreTags)), exact - } - } - exact = false - } - } - if x, ok := getCoreIndex(t); ok { - return x, exact - } - exact = false - if r != 0 && s == 0 { - // Deal with cases where an extra script is inserted for the region. - t, _ := t.Maximize() - if x, ok := getCoreIndex(t); ok { - return x, exact - } - } - for t = t.Parent(); t != root; t = t.Parent() { - // No variants specified: just compare core components. - // The key has the form lllssrrr, where l, s, and r are nibbles for - // respectively the langID, scriptID, and regionID. - if x, ok := getCoreIndex(t); ok { - return x, exact - } - } - return 0, exact -} - -var root = language.Tag{} diff --git a/vendor/golang.org/x/text/internal/language/compact/parents.go b/vendor/golang.org/x/text/internal/language/compact/parents.go deleted file mode 100644 index 8d810723..00000000 --- a/vendor/golang.org/x/text/internal/language/compact/parents.go +++ /dev/null @@ -1,120 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package compact - -// parents maps a compact index of a tag to the compact index of the parent of -// this tag. -var parents = []ID{ // 775 elements - // Entry 0 - 3F - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0004, 0x0000, 0x0006, - 0x0000, 0x0008, 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, - 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, - 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, - 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, - 0x0000, 0x0028, 0x0000, 0x002a, 0x0000, 0x002c, 0x0000, 0x0000, - 0x002f, 0x002e, 0x002e, 0x0000, 0x0033, 0x0000, 0x0035, 0x0000, - 0x0037, 0x0000, 0x0039, 0x0000, 0x003b, 0x0000, 0x0000, 0x003e, - // Entry 40 - 7F - 0x0000, 0x0040, 0x0040, 0x0000, 0x0043, 0x0043, 0x0000, 0x0046, - 0x0000, 0x0048, 0x0000, 0x0000, 0x004b, 0x004a, 0x004a, 0x0000, - 0x004f, 0x004f, 0x004f, 0x004f, 0x0000, 0x0054, 0x0054, 0x0000, - 0x0057, 0x0000, 0x0059, 0x0000, 0x005b, 0x0000, 0x005d, 0x005d, - 0x0000, 0x0060, 0x0000, 0x0062, 0x0000, 0x0064, 0x0000, 0x0066, - 0x0066, 0x0000, 0x0069, 0x0000, 0x006b, 0x006b, 0x006b, 0x006b, - 0x006b, 0x006b, 0x006b, 0x0000, 0x0073, 0x0000, 0x0075, 0x0000, - 0x0077, 0x0000, 0x0000, 0x007a, 0x0000, 0x007c, 0x0000, 0x007e, - // Entry 80 - BF - 0x0000, 0x0080, 0x0080, 0x0000, 0x0083, 0x0083, 0x0000, 0x0086, - 0x0087, 0x0087, 0x0087, 0x0086, 0x0088, 0x0087, 0x0087, 0x0087, - 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0088, - 0x0087, 0x0087, 0x0087, 0x0087, 0x0088, 0x0087, 0x0088, 0x0087, - 0x0087, 0x0088, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, - 0x0087, 0x0087, 0x0087, 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, - 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, - 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0086, 0x0087, 0x0086, - // Entry C0 - FF - 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, - 0x0088, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, - 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0088, 0x0087, - 0x0087, 0x0088, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, - 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0086, 0x0086, 0x0087, - 0x0087, 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0000, - 0x00ef, 0x0000, 0x00f1, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f2, - 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f1, 0x00f2, 0x00f1, 0x00f1, - // Entry 100 - 13F - 0x00f2, 0x00f2, 0x00f1, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f1, - 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x0000, 0x010e, - 0x0000, 0x0110, 0x0000, 0x0112, 0x0000, 0x0114, 0x0114, 0x0000, - 0x0117, 0x0117, 0x0117, 0x0117, 0x0000, 0x011c, 0x0000, 0x011e, - 0x0000, 0x0120, 0x0120, 0x0000, 0x0123, 0x0123, 0x0123, 0x0123, - 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, - 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, - 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, - // Entry 140 - 17F - 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, - 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, 0x0123, - 0x0123, 0x0123, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156, - 0x0000, 0x0158, 0x0000, 0x015a, 0x0000, 0x015c, 0x015c, 0x015c, - 0x0000, 0x0160, 0x0000, 0x0000, 0x0163, 0x0000, 0x0165, 0x0000, - 0x0167, 0x0167, 0x0167, 0x0000, 0x016b, 0x0000, 0x016d, 0x0000, - 0x016f, 0x0000, 0x0171, 0x0171, 0x0000, 0x0174, 0x0000, 0x0176, - 0x0000, 0x0178, 0x0000, 0x017a, 0x0000, 0x017c, 0x0000, 0x017e, - // Entry 180 - 1BF - 0x0000, 0x0000, 0x0000, 0x0182, 0x0000, 0x0184, 0x0184, 0x0184, - 0x0184, 0x0000, 0x0000, 0x0000, 0x018b, 0x0000, 0x0000, 0x018e, - 0x0000, 0x0000, 0x0191, 0x0000, 0x0000, 0x0000, 0x0195, 0x0000, - 0x0197, 0x0000, 0x0000, 0x019a, 0x0000, 0x0000, 0x019d, 0x0000, - 0x019f, 0x0000, 0x01a1, 0x0000, 0x01a3, 0x0000, 0x01a5, 0x0000, - 0x01a7, 0x0000, 0x01a9, 0x0000, 0x01ab, 0x0000, 0x01ad, 0x0000, - 0x01af, 0x0000, 0x01b1, 0x01b1, 0x0000, 0x01b4, 0x0000, 0x01b6, - 0x0000, 0x01b8, 0x0000, 0x01ba, 0x0000, 0x01bc, 0x0000, 0x0000, - // Entry 1C0 - 1FF - 0x01bf, 0x0000, 0x01c1, 0x0000, 0x01c3, 0x0000, 0x01c5, 0x0000, - 0x01c7, 0x0000, 0x01c9, 0x0000, 0x01cb, 0x01cb, 0x01cb, 0x01cb, - 0x0000, 0x01d0, 0x0000, 0x01d2, 0x01d2, 0x0000, 0x01d5, 0x0000, - 0x01d7, 0x0000, 0x01d9, 0x0000, 0x01db, 0x0000, 0x01dd, 0x0000, - 0x01df, 0x01df, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6, - 0x0000, 0x01e8, 0x0000, 0x01ea, 0x0000, 0x01ec, 0x0000, 0x01ee, - 0x0000, 0x01f0, 0x0000, 0x0000, 0x01f3, 0x0000, 0x01f5, 0x01f5, - 0x01f5, 0x0000, 0x01f9, 0x0000, 0x01fb, 0x0000, 0x01fd, 0x0000, - // Entry 200 - 23F - 0x01ff, 0x0000, 0x0000, 0x0202, 0x0000, 0x0204, 0x0204, 0x0000, - 0x0207, 0x0000, 0x0209, 0x0209, 0x0000, 0x020c, 0x020c, 0x0000, - 0x020f, 0x020f, 0x020f, 0x020f, 0x020f, 0x020f, 0x020f, 0x0000, - 0x0217, 0x0000, 0x0219, 0x0000, 0x021b, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0221, 0x0000, 0x0000, 0x0224, 0x0000, 0x0226, - 0x0226, 0x0000, 0x0229, 0x0000, 0x022b, 0x022b, 0x0000, 0x0000, - 0x022f, 0x022e, 0x022e, 0x0000, 0x0000, 0x0234, 0x0000, 0x0236, - 0x0000, 0x0238, 0x0000, 0x0244, 0x023a, 0x0244, 0x0244, 0x0244, - // Entry 240 - 27F - 0x0244, 0x0244, 0x0244, 0x0244, 0x023a, 0x0244, 0x0244, 0x0000, - 0x0247, 0x0247, 0x0247, 0x0000, 0x024b, 0x0000, 0x024d, 0x0000, - 0x024f, 0x024f, 0x0000, 0x0252, 0x0000, 0x0254, 0x0254, 0x0254, - 0x0254, 0x0254, 0x0254, 0x0000, 0x025b, 0x0000, 0x025d, 0x0000, - 0x025f, 0x0000, 0x0261, 0x0000, 0x0263, 0x0000, 0x0265, 0x0000, - 0x0000, 0x0268, 0x0268, 0x0268, 0x0000, 0x026c, 0x0000, 0x026e, - 0x0000, 0x0270, 0x0000, 0x0000, 0x0000, 0x0274, 0x0273, 0x0273, - 0x0000, 0x0278, 0x0000, 0x027a, 0x0000, 0x027c, 0x0000, 0x0000, - // Entry 280 - 2BF - 0x0000, 0x0000, 0x0281, 0x0000, 0x0000, 0x0284, 0x0000, 0x0286, - 0x0286, 0x0286, 0x0286, 0x0000, 0x028b, 0x028b, 0x028b, 0x0000, - 0x028f, 0x028f, 0x028f, 0x028f, 0x028f, 0x0000, 0x0295, 0x0295, - 0x0295, 0x0295, 0x0000, 0x0000, 0x0000, 0x0000, 0x029d, 0x029d, - 0x029d, 0x0000, 0x02a1, 0x02a1, 0x02a1, 0x02a1, 0x0000, 0x0000, - 0x02a7, 0x02a7, 0x02a7, 0x02a7, 0x0000, 0x02ac, 0x0000, 0x02ae, - 0x02ae, 0x0000, 0x02b1, 0x0000, 0x02b3, 0x0000, 0x02b5, 0x02b5, - 0x0000, 0x0000, 0x02b9, 0x0000, 0x0000, 0x0000, 0x02bd, 0x0000, - // Entry 2C0 - 2FF - 0x02bf, 0x02bf, 0x0000, 0x0000, 0x02c3, 0x0000, 0x02c5, 0x0000, - 0x02c7, 0x0000, 0x02c9, 0x0000, 0x02cb, 0x0000, 0x02cd, 0x02cd, - 0x0000, 0x0000, 0x02d1, 0x0000, 0x02d3, 0x02d0, 0x02d0, 0x0000, - 0x0000, 0x02d8, 0x02d7, 0x02d7, 0x0000, 0x0000, 0x02dd, 0x0000, - 0x02df, 0x0000, 0x02e1, 0x0000, 0x0000, 0x02e4, 0x0000, 0x02e6, - 0x0000, 0x0000, 0x02e9, 0x0000, 0x02eb, 0x0000, 0x02ed, 0x0000, - 0x02ef, 0x02ef, 0x0000, 0x0000, 0x02f3, 0x02f2, 0x02f2, 0x0000, - 0x02f7, 0x0000, 0x02f9, 0x02f9, 0x02f9, 0x02f9, 0x02f9, 0x0000, - // Entry 300 - 33F - 0x02ff, 0x0300, 0x02ff, 0x0000, 0x0303, 0x0051, 0x00e6, -} // Size: 1574 bytes - -// Total table size 1574 bytes (1KiB); checksum: 895AAF0B diff --git a/vendor/golang.org/x/text/internal/language/compact/tables.go b/vendor/golang.org/x/text/internal/language/compact/tables.go deleted file mode 100644 index a09ed198..00000000 --- a/vendor/golang.org/x/text/internal/language/compact/tables.go +++ /dev/null @@ -1,1015 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package compact - -import "golang.org/x/text/internal/language" - -// CLDRVersion is the CLDR version from which the tables in this package are derived. -const CLDRVersion = "32" - -// NumCompactTags is the number of common tags. The maximum tag is -// NumCompactTags-1. -const NumCompactTags = 775 -const ( - undIndex ID = 0 - afIndex ID = 1 - afNAIndex ID = 2 - afZAIndex ID = 3 - agqIndex ID = 4 - agqCMIndex ID = 5 - akIndex ID = 6 - akGHIndex ID = 7 - amIndex ID = 8 - amETIndex ID = 9 - arIndex ID = 10 - ar001Index ID = 11 - arAEIndex ID = 12 - arBHIndex ID = 13 - arDJIndex ID = 14 - arDZIndex ID = 15 - arEGIndex ID = 16 - arEHIndex ID = 17 - arERIndex ID = 18 - arILIndex ID = 19 - arIQIndex ID = 20 - arJOIndex ID = 21 - arKMIndex ID = 22 - arKWIndex ID = 23 - arLBIndex ID = 24 - arLYIndex ID = 25 - arMAIndex ID = 26 - arMRIndex ID = 27 - arOMIndex ID = 28 - arPSIndex ID = 29 - arQAIndex ID = 30 - arSAIndex ID = 31 - arSDIndex ID = 32 - arSOIndex ID = 33 - arSSIndex ID = 34 - arSYIndex ID = 35 - arTDIndex ID = 36 - arTNIndex ID = 37 - arYEIndex ID = 38 - arsIndex ID = 39 - asIndex ID = 40 - asINIndex ID = 41 - asaIndex ID = 42 - asaTZIndex ID = 43 - astIndex ID = 44 - astESIndex ID = 45 - azIndex ID = 46 - azCyrlIndex ID = 47 - azCyrlAZIndex ID = 48 - azLatnIndex ID = 49 - azLatnAZIndex ID = 50 - basIndex ID = 51 - basCMIndex ID = 52 - beIndex ID = 53 - beBYIndex ID = 54 - bemIndex ID = 55 - bemZMIndex ID = 56 - bezIndex ID = 57 - bezTZIndex ID = 58 - bgIndex ID = 59 - bgBGIndex ID = 60 - bhIndex ID = 61 - bmIndex ID = 62 - bmMLIndex ID = 63 - bnIndex ID = 64 - bnBDIndex ID = 65 - bnINIndex ID = 66 - boIndex ID = 67 - boCNIndex ID = 68 - boINIndex ID = 69 - brIndex ID = 70 - brFRIndex ID = 71 - brxIndex ID = 72 - brxINIndex ID = 73 - bsIndex ID = 74 - bsCyrlIndex ID = 75 - bsCyrlBAIndex ID = 76 - bsLatnIndex ID = 77 - bsLatnBAIndex ID = 78 - caIndex ID = 79 - caADIndex ID = 80 - caESIndex ID = 81 - caFRIndex ID = 82 - caITIndex ID = 83 - ccpIndex ID = 84 - ccpBDIndex ID = 85 - ccpINIndex ID = 86 - ceIndex ID = 87 - ceRUIndex ID = 88 - cggIndex ID = 89 - cggUGIndex ID = 90 - chrIndex ID = 91 - chrUSIndex ID = 92 - ckbIndex ID = 93 - ckbIQIndex ID = 94 - ckbIRIndex ID = 95 - csIndex ID = 96 - csCZIndex ID = 97 - cuIndex ID = 98 - cuRUIndex ID = 99 - cyIndex ID = 100 - cyGBIndex ID = 101 - daIndex ID = 102 - daDKIndex ID = 103 - daGLIndex ID = 104 - davIndex ID = 105 - davKEIndex ID = 106 - deIndex ID = 107 - deATIndex ID = 108 - deBEIndex ID = 109 - deCHIndex ID = 110 - deDEIndex ID = 111 - deITIndex ID = 112 - deLIIndex ID = 113 - deLUIndex ID = 114 - djeIndex ID = 115 - djeNEIndex ID = 116 - dsbIndex ID = 117 - dsbDEIndex ID = 118 - duaIndex ID = 119 - duaCMIndex ID = 120 - dvIndex ID = 121 - dyoIndex ID = 122 - dyoSNIndex ID = 123 - dzIndex ID = 124 - dzBTIndex ID = 125 - ebuIndex ID = 126 - ebuKEIndex ID = 127 - eeIndex ID = 128 - eeGHIndex ID = 129 - eeTGIndex ID = 130 - elIndex ID = 131 - elCYIndex ID = 132 - elGRIndex ID = 133 - enIndex ID = 134 - en001Index ID = 135 - en150Index ID = 136 - enAGIndex ID = 137 - enAIIndex ID = 138 - enASIndex ID = 139 - enATIndex ID = 140 - enAUIndex ID = 141 - enBBIndex ID = 142 - enBEIndex ID = 143 - enBIIndex ID = 144 - enBMIndex ID = 145 - enBSIndex ID = 146 - enBWIndex ID = 147 - enBZIndex ID = 148 - enCAIndex ID = 149 - enCCIndex ID = 150 - enCHIndex ID = 151 - enCKIndex ID = 152 - enCMIndex ID = 153 - enCXIndex ID = 154 - enCYIndex ID = 155 - enDEIndex ID = 156 - enDGIndex ID = 157 - enDKIndex ID = 158 - enDMIndex ID = 159 - enERIndex ID = 160 - enFIIndex ID = 161 - enFJIndex ID = 162 - enFKIndex ID = 163 - enFMIndex ID = 164 - enGBIndex ID = 165 - enGDIndex ID = 166 - enGGIndex ID = 167 - enGHIndex ID = 168 - enGIIndex ID = 169 - enGMIndex ID = 170 - enGUIndex ID = 171 - enGYIndex ID = 172 - enHKIndex ID = 173 - enIEIndex ID = 174 - enILIndex ID = 175 - enIMIndex ID = 176 - enINIndex ID = 177 - enIOIndex ID = 178 - enJEIndex ID = 179 - enJMIndex ID = 180 - enKEIndex ID = 181 - enKIIndex ID = 182 - enKNIndex ID = 183 - enKYIndex ID = 184 - enLCIndex ID = 185 - enLRIndex ID = 186 - enLSIndex ID = 187 - enMGIndex ID = 188 - enMHIndex ID = 189 - enMOIndex ID = 190 - enMPIndex ID = 191 - enMSIndex ID = 192 - enMTIndex ID = 193 - enMUIndex ID = 194 - enMWIndex ID = 195 - enMYIndex ID = 196 - enNAIndex ID = 197 - enNFIndex ID = 198 - enNGIndex ID = 199 - enNLIndex ID = 200 - enNRIndex ID = 201 - enNUIndex ID = 202 - enNZIndex ID = 203 - enPGIndex ID = 204 - enPHIndex ID = 205 - enPKIndex ID = 206 - enPNIndex ID = 207 - enPRIndex ID = 208 - enPWIndex ID = 209 - enRWIndex ID = 210 - enSBIndex ID = 211 - enSCIndex ID = 212 - enSDIndex ID = 213 - enSEIndex ID = 214 - enSGIndex ID = 215 - enSHIndex ID = 216 - enSIIndex ID = 217 - enSLIndex ID = 218 - enSSIndex ID = 219 - enSXIndex ID = 220 - enSZIndex ID = 221 - enTCIndex ID = 222 - enTKIndex ID = 223 - enTOIndex ID = 224 - enTTIndex ID = 225 - enTVIndex ID = 226 - enTZIndex ID = 227 - enUGIndex ID = 228 - enUMIndex ID = 229 - enUSIndex ID = 230 - enVCIndex ID = 231 - enVGIndex ID = 232 - enVIIndex ID = 233 - enVUIndex ID = 234 - enWSIndex ID = 235 - enZAIndex ID = 236 - enZMIndex ID = 237 - enZWIndex ID = 238 - eoIndex ID = 239 - eo001Index ID = 240 - esIndex ID = 241 - es419Index ID = 242 - esARIndex ID = 243 - esBOIndex ID = 244 - esBRIndex ID = 245 - esBZIndex ID = 246 - esCLIndex ID = 247 - esCOIndex ID = 248 - esCRIndex ID = 249 - esCUIndex ID = 250 - esDOIndex ID = 251 - esEAIndex ID = 252 - esECIndex ID = 253 - esESIndex ID = 254 - esGQIndex ID = 255 - esGTIndex ID = 256 - esHNIndex ID = 257 - esICIndex ID = 258 - esMXIndex ID = 259 - esNIIndex ID = 260 - esPAIndex ID = 261 - esPEIndex ID = 262 - esPHIndex ID = 263 - esPRIndex ID = 264 - esPYIndex ID = 265 - esSVIndex ID = 266 - esUSIndex ID = 267 - esUYIndex ID = 268 - esVEIndex ID = 269 - etIndex ID = 270 - etEEIndex ID = 271 - euIndex ID = 272 - euESIndex ID = 273 - ewoIndex ID = 274 - ewoCMIndex ID = 275 - faIndex ID = 276 - faAFIndex ID = 277 - faIRIndex ID = 278 - ffIndex ID = 279 - ffCMIndex ID = 280 - ffGNIndex ID = 281 - ffMRIndex ID = 282 - ffSNIndex ID = 283 - fiIndex ID = 284 - fiFIIndex ID = 285 - filIndex ID = 286 - filPHIndex ID = 287 - foIndex ID = 288 - foDKIndex ID = 289 - foFOIndex ID = 290 - frIndex ID = 291 - frBEIndex ID = 292 - frBFIndex ID = 293 - frBIIndex ID = 294 - frBJIndex ID = 295 - frBLIndex ID = 296 - frCAIndex ID = 297 - frCDIndex ID = 298 - frCFIndex ID = 299 - frCGIndex ID = 300 - frCHIndex ID = 301 - frCIIndex ID = 302 - frCMIndex ID = 303 - frDJIndex ID = 304 - frDZIndex ID = 305 - frFRIndex ID = 306 - frGAIndex ID = 307 - frGFIndex ID = 308 - frGNIndex ID = 309 - frGPIndex ID = 310 - frGQIndex ID = 311 - frHTIndex ID = 312 - frKMIndex ID = 313 - frLUIndex ID = 314 - frMAIndex ID = 315 - frMCIndex ID = 316 - frMFIndex ID = 317 - frMGIndex ID = 318 - frMLIndex ID = 319 - frMQIndex ID = 320 - frMRIndex ID = 321 - frMUIndex ID = 322 - frNCIndex ID = 323 - frNEIndex ID = 324 - frPFIndex ID = 325 - frPMIndex ID = 326 - frREIndex ID = 327 - frRWIndex ID = 328 - frSCIndex ID = 329 - frSNIndex ID = 330 - frSYIndex ID = 331 - frTDIndex ID = 332 - frTGIndex ID = 333 - frTNIndex ID = 334 - frVUIndex ID = 335 - frWFIndex ID = 336 - frYTIndex ID = 337 - furIndex ID = 338 - furITIndex ID = 339 - fyIndex ID = 340 - fyNLIndex ID = 341 - gaIndex ID = 342 - gaIEIndex ID = 343 - gdIndex ID = 344 - gdGBIndex ID = 345 - glIndex ID = 346 - glESIndex ID = 347 - gswIndex ID = 348 - gswCHIndex ID = 349 - gswFRIndex ID = 350 - gswLIIndex ID = 351 - guIndex ID = 352 - guINIndex ID = 353 - guwIndex ID = 354 - guzIndex ID = 355 - guzKEIndex ID = 356 - gvIndex ID = 357 - gvIMIndex ID = 358 - haIndex ID = 359 - haGHIndex ID = 360 - haNEIndex ID = 361 - haNGIndex ID = 362 - hawIndex ID = 363 - hawUSIndex ID = 364 - heIndex ID = 365 - heILIndex ID = 366 - hiIndex ID = 367 - hiINIndex ID = 368 - hrIndex ID = 369 - hrBAIndex ID = 370 - hrHRIndex ID = 371 - hsbIndex ID = 372 - hsbDEIndex ID = 373 - huIndex ID = 374 - huHUIndex ID = 375 - hyIndex ID = 376 - hyAMIndex ID = 377 - idIndex ID = 378 - idIDIndex ID = 379 - igIndex ID = 380 - igNGIndex ID = 381 - iiIndex ID = 382 - iiCNIndex ID = 383 - inIndex ID = 384 - ioIndex ID = 385 - isIndex ID = 386 - isISIndex ID = 387 - itIndex ID = 388 - itCHIndex ID = 389 - itITIndex ID = 390 - itSMIndex ID = 391 - itVAIndex ID = 392 - iuIndex ID = 393 - iwIndex ID = 394 - jaIndex ID = 395 - jaJPIndex ID = 396 - jboIndex ID = 397 - jgoIndex ID = 398 - jgoCMIndex ID = 399 - jiIndex ID = 400 - jmcIndex ID = 401 - jmcTZIndex ID = 402 - jvIndex ID = 403 - jwIndex ID = 404 - kaIndex ID = 405 - kaGEIndex ID = 406 - kabIndex ID = 407 - kabDZIndex ID = 408 - kajIndex ID = 409 - kamIndex ID = 410 - kamKEIndex ID = 411 - kcgIndex ID = 412 - kdeIndex ID = 413 - kdeTZIndex ID = 414 - keaIndex ID = 415 - keaCVIndex ID = 416 - khqIndex ID = 417 - khqMLIndex ID = 418 - kiIndex ID = 419 - kiKEIndex ID = 420 - kkIndex ID = 421 - kkKZIndex ID = 422 - kkjIndex ID = 423 - kkjCMIndex ID = 424 - klIndex ID = 425 - klGLIndex ID = 426 - klnIndex ID = 427 - klnKEIndex ID = 428 - kmIndex ID = 429 - kmKHIndex ID = 430 - knIndex ID = 431 - knINIndex ID = 432 - koIndex ID = 433 - koKPIndex ID = 434 - koKRIndex ID = 435 - kokIndex ID = 436 - kokINIndex ID = 437 - ksIndex ID = 438 - ksINIndex ID = 439 - ksbIndex ID = 440 - ksbTZIndex ID = 441 - ksfIndex ID = 442 - ksfCMIndex ID = 443 - kshIndex ID = 444 - kshDEIndex ID = 445 - kuIndex ID = 446 - kwIndex ID = 447 - kwGBIndex ID = 448 - kyIndex ID = 449 - kyKGIndex ID = 450 - lagIndex ID = 451 - lagTZIndex ID = 452 - lbIndex ID = 453 - lbLUIndex ID = 454 - lgIndex ID = 455 - lgUGIndex ID = 456 - lktIndex ID = 457 - lktUSIndex ID = 458 - lnIndex ID = 459 - lnAOIndex ID = 460 - lnCDIndex ID = 461 - lnCFIndex ID = 462 - lnCGIndex ID = 463 - loIndex ID = 464 - loLAIndex ID = 465 - lrcIndex ID = 466 - lrcIQIndex ID = 467 - lrcIRIndex ID = 468 - ltIndex ID = 469 - ltLTIndex ID = 470 - luIndex ID = 471 - luCDIndex ID = 472 - luoIndex ID = 473 - luoKEIndex ID = 474 - luyIndex ID = 475 - luyKEIndex ID = 476 - lvIndex ID = 477 - lvLVIndex ID = 478 - masIndex ID = 479 - masKEIndex ID = 480 - masTZIndex ID = 481 - merIndex ID = 482 - merKEIndex ID = 483 - mfeIndex ID = 484 - mfeMUIndex ID = 485 - mgIndex ID = 486 - mgMGIndex ID = 487 - mghIndex ID = 488 - mghMZIndex ID = 489 - mgoIndex ID = 490 - mgoCMIndex ID = 491 - mkIndex ID = 492 - mkMKIndex ID = 493 - mlIndex ID = 494 - mlINIndex ID = 495 - mnIndex ID = 496 - mnMNIndex ID = 497 - moIndex ID = 498 - mrIndex ID = 499 - mrINIndex ID = 500 - msIndex ID = 501 - msBNIndex ID = 502 - msMYIndex ID = 503 - msSGIndex ID = 504 - mtIndex ID = 505 - mtMTIndex ID = 506 - muaIndex ID = 507 - muaCMIndex ID = 508 - myIndex ID = 509 - myMMIndex ID = 510 - mznIndex ID = 511 - mznIRIndex ID = 512 - nahIndex ID = 513 - naqIndex ID = 514 - naqNAIndex ID = 515 - nbIndex ID = 516 - nbNOIndex ID = 517 - nbSJIndex ID = 518 - ndIndex ID = 519 - ndZWIndex ID = 520 - ndsIndex ID = 521 - ndsDEIndex ID = 522 - ndsNLIndex ID = 523 - neIndex ID = 524 - neINIndex ID = 525 - neNPIndex ID = 526 - nlIndex ID = 527 - nlAWIndex ID = 528 - nlBEIndex ID = 529 - nlBQIndex ID = 530 - nlCWIndex ID = 531 - nlNLIndex ID = 532 - nlSRIndex ID = 533 - nlSXIndex ID = 534 - nmgIndex ID = 535 - nmgCMIndex ID = 536 - nnIndex ID = 537 - nnNOIndex ID = 538 - nnhIndex ID = 539 - nnhCMIndex ID = 540 - noIndex ID = 541 - nqoIndex ID = 542 - nrIndex ID = 543 - nsoIndex ID = 544 - nusIndex ID = 545 - nusSSIndex ID = 546 - nyIndex ID = 547 - nynIndex ID = 548 - nynUGIndex ID = 549 - omIndex ID = 550 - omETIndex ID = 551 - omKEIndex ID = 552 - orIndex ID = 553 - orINIndex ID = 554 - osIndex ID = 555 - osGEIndex ID = 556 - osRUIndex ID = 557 - paIndex ID = 558 - paArabIndex ID = 559 - paArabPKIndex ID = 560 - paGuruIndex ID = 561 - paGuruINIndex ID = 562 - papIndex ID = 563 - plIndex ID = 564 - plPLIndex ID = 565 - prgIndex ID = 566 - prg001Index ID = 567 - psIndex ID = 568 - psAFIndex ID = 569 - ptIndex ID = 570 - ptAOIndex ID = 571 - ptBRIndex ID = 572 - ptCHIndex ID = 573 - ptCVIndex ID = 574 - ptGQIndex ID = 575 - ptGWIndex ID = 576 - ptLUIndex ID = 577 - ptMOIndex ID = 578 - ptMZIndex ID = 579 - ptPTIndex ID = 580 - ptSTIndex ID = 581 - ptTLIndex ID = 582 - quIndex ID = 583 - quBOIndex ID = 584 - quECIndex ID = 585 - quPEIndex ID = 586 - rmIndex ID = 587 - rmCHIndex ID = 588 - rnIndex ID = 589 - rnBIIndex ID = 590 - roIndex ID = 591 - roMDIndex ID = 592 - roROIndex ID = 593 - rofIndex ID = 594 - rofTZIndex ID = 595 - ruIndex ID = 596 - ruBYIndex ID = 597 - ruKGIndex ID = 598 - ruKZIndex ID = 599 - ruMDIndex ID = 600 - ruRUIndex ID = 601 - ruUAIndex ID = 602 - rwIndex ID = 603 - rwRWIndex ID = 604 - rwkIndex ID = 605 - rwkTZIndex ID = 606 - sahIndex ID = 607 - sahRUIndex ID = 608 - saqIndex ID = 609 - saqKEIndex ID = 610 - sbpIndex ID = 611 - sbpTZIndex ID = 612 - sdIndex ID = 613 - sdPKIndex ID = 614 - sdhIndex ID = 615 - seIndex ID = 616 - seFIIndex ID = 617 - seNOIndex ID = 618 - seSEIndex ID = 619 - sehIndex ID = 620 - sehMZIndex ID = 621 - sesIndex ID = 622 - sesMLIndex ID = 623 - sgIndex ID = 624 - sgCFIndex ID = 625 - shIndex ID = 626 - shiIndex ID = 627 - shiLatnIndex ID = 628 - shiLatnMAIndex ID = 629 - shiTfngIndex ID = 630 - shiTfngMAIndex ID = 631 - siIndex ID = 632 - siLKIndex ID = 633 - skIndex ID = 634 - skSKIndex ID = 635 - slIndex ID = 636 - slSIIndex ID = 637 - smaIndex ID = 638 - smiIndex ID = 639 - smjIndex ID = 640 - smnIndex ID = 641 - smnFIIndex ID = 642 - smsIndex ID = 643 - snIndex ID = 644 - snZWIndex ID = 645 - soIndex ID = 646 - soDJIndex ID = 647 - soETIndex ID = 648 - soKEIndex ID = 649 - soSOIndex ID = 650 - sqIndex ID = 651 - sqALIndex ID = 652 - sqMKIndex ID = 653 - sqXKIndex ID = 654 - srIndex ID = 655 - srCyrlIndex ID = 656 - srCyrlBAIndex ID = 657 - srCyrlMEIndex ID = 658 - srCyrlRSIndex ID = 659 - srCyrlXKIndex ID = 660 - srLatnIndex ID = 661 - srLatnBAIndex ID = 662 - srLatnMEIndex ID = 663 - srLatnRSIndex ID = 664 - srLatnXKIndex ID = 665 - ssIndex ID = 666 - ssyIndex ID = 667 - stIndex ID = 668 - svIndex ID = 669 - svAXIndex ID = 670 - svFIIndex ID = 671 - svSEIndex ID = 672 - swIndex ID = 673 - swCDIndex ID = 674 - swKEIndex ID = 675 - swTZIndex ID = 676 - swUGIndex ID = 677 - syrIndex ID = 678 - taIndex ID = 679 - taINIndex ID = 680 - taLKIndex ID = 681 - taMYIndex ID = 682 - taSGIndex ID = 683 - teIndex ID = 684 - teINIndex ID = 685 - teoIndex ID = 686 - teoKEIndex ID = 687 - teoUGIndex ID = 688 - tgIndex ID = 689 - tgTJIndex ID = 690 - thIndex ID = 691 - thTHIndex ID = 692 - tiIndex ID = 693 - tiERIndex ID = 694 - tiETIndex ID = 695 - tigIndex ID = 696 - tkIndex ID = 697 - tkTMIndex ID = 698 - tlIndex ID = 699 - tnIndex ID = 700 - toIndex ID = 701 - toTOIndex ID = 702 - trIndex ID = 703 - trCYIndex ID = 704 - trTRIndex ID = 705 - tsIndex ID = 706 - ttIndex ID = 707 - ttRUIndex ID = 708 - twqIndex ID = 709 - twqNEIndex ID = 710 - tzmIndex ID = 711 - tzmMAIndex ID = 712 - ugIndex ID = 713 - ugCNIndex ID = 714 - ukIndex ID = 715 - ukUAIndex ID = 716 - urIndex ID = 717 - urINIndex ID = 718 - urPKIndex ID = 719 - uzIndex ID = 720 - uzArabIndex ID = 721 - uzArabAFIndex ID = 722 - uzCyrlIndex ID = 723 - uzCyrlUZIndex ID = 724 - uzLatnIndex ID = 725 - uzLatnUZIndex ID = 726 - vaiIndex ID = 727 - vaiLatnIndex ID = 728 - vaiLatnLRIndex ID = 729 - vaiVaiiIndex ID = 730 - vaiVaiiLRIndex ID = 731 - veIndex ID = 732 - viIndex ID = 733 - viVNIndex ID = 734 - voIndex ID = 735 - vo001Index ID = 736 - vunIndex ID = 737 - vunTZIndex ID = 738 - waIndex ID = 739 - waeIndex ID = 740 - waeCHIndex ID = 741 - woIndex ID = 742 - woSNIndex ID = 743 - xhIndex ID = 744 - xogIndex ID = 745 - xogUGIndex ID = 746 - yavIndex ID = 747 - yavCMIndex ID = 748 - yiIndex ID = 749 - yi001Index ID = 750 - yoIndex ID = 751 - yoBJIndex ID = 752 - yoNGIndex ID = 753 - yueIndex ID = 754 - yueHansIndex ID = 755 - yueHansCNIndex ID = 756 - yueHantIndex ID = 757 - yueHantHKIndex ID = 758 - zghIndex ID = 759 - zghMAIndex ID = 760 - zhIndex ID = 761 - zhHansIndex ID = 762 - zhHansCNIndex ID = 763 - zhHansHKIndex ID = 764 - zhHansMOIndex ID = 765 - zhHansSGIndex ID = 766 - zhHantIndex ID = 767 - zhHantHKIndex ID = 768 - zhHantMOIndex ID = 769 - zhHantTWIndex ID = 770 - zuIndex ID = 771 - zuZAIndex ID = 772 - caESvalenciaIndex ID = 773 - enUSuvaposixIndex ID = 774 -) - -var coreTags = []language.CompactCoreInfo{ // 773 elements - // Entry 0 - 1F - 0x00000000, 0x01600000, 0x016000d3, 0x01600162, - 0x01c00000, 0x01c00052, 0x02100000, 0x02100081, - 0x02700000, 0x02700070, 0x03a00000, 0x03a00001, - 0x03a00023, 0x03a00039, 0x03a00063, 0x03a00068, - 0x03a0006c, 0x03a0006d, 0x03a0006e, 0x03a00098, - 0x03a0009c, 0x03a000a2, 0x03a000a9, 0x03a000ad, - 0x03a000b1, 0x03a000ba, 0x03a000bb, 0x03a000ca, - 0x03a000e2, 0x03a000ee, 0x03a000f4, 0x03a00109, - // Entry 20 - 3F - 0x03a0010c, 0x03a00116, 0x03a00118, 0x03a0011d, - 0x03a00121, 0x03a00129, 0x03a0015f, 0x04000000, - 0x04300000, 0x0430009a, 0x04400000, 0x04400130, - 0x04800000, 0x0480006f, 0x05800000, 0x05820000, - 0x05820032, 0x0585b000, 0x0585b032, 0x05e00000, - 0x05e00052, 0x07100000, 0x07100047, 0x07500000, - 0x07500163, 0x07900000, 0x07900130, 0x07e00000, - 0x07e00038, 0x08200000, 0x0a000000, 0x0a0000c4, - // Entry 40 - 5F - 0x0a500000, 0x0a500035, 0x0a50009a, 0x0a900000, - 0x0a900053, 0x0a90009a, 0x0b200000, 0x0b200079, - 0x0b500000, 0x0b50009a, 0x0b700000, 0x0b720000, - 0x0b720033, 0x0b75b000, 0x0b75b033, 0x0d700000, - 0x0d700022, 0x0d70006f, 0x0d700079, 0x0d70009f, - 0x0db00000, 0x0db00035, 0x0db0009a, 0x0dc00000, - 0x0dc00107, 0x0df00000, 0x0df00132, 0x0e500000, - 0x0e500136, 0x0e900000, 0x0e90009c, 0x0e90009d, - // Entry 60 - 7F - 0x0fa00000, 0x0fa0005f, 0x0fe00000, 0x0fe00107, - 0x10000000, 0x1000007c, 0x10100000, 0x10100064, - 0x10100083, 0x10800000, 0x108000a5, 0x10d00000, - 0x10d0002e, 0x10d00036, 0x10d0004e, 0x10d00061, - 0x10d0009f, 0x10d000b3, 0x10d000b8, 0x11700000, - 0x117000d5, 0x11f00000, 0x11f00061, 0x12400000, - 0x12400052, 0x12800000, 0x12b00000, 0x12b00115, - 0x12d00000, 0x12d00043, 0x12f00000, 0x12f000a5, - // Entry 80 - 9F - 0x13000000, 0x13000081, 0x13000123, 0x13600000, - 0x1360005e, 0x13600088, 0x13900000, 0x13900001, - 0x1390001a, 0x13900025, 0x13900026, 0x1390002d, - 0x1390002e, 0x1390002f, 0x13900034, 0x13900036, - 0x1390003a, 0x1390003d, 0x13900042, 0x13900046, - 0x13900048, 0x13900049, 0x1390004a, 0x1390004e, - 0x13900050, 0x13900052, 0x1390005d, 0x1390005e, - 0x13900061, 0x13900062, 0x13900064, 0x13900065, - // Entry A0 - BF - 0x1390006e, 0x13900073, 0x13900074, 0x13900075, - 0x13900076, 0x1390007c, 0x1390007d, 0x13900080, - 0x13900081, 0x13900082, 0x13900084, 0x1390008b, - 0x1390008d, 0x1390008e, 0x13900097, 0x13900098, - 0x13900099, 0x1390009a, 0x1390009b, 0x139000a0, - 0x139000a1, 0x139000a5, 0x139000a8, 0x139000aa, - 0x139000ae, 0x139000b2, 0x139000b5, 0x139000b6, - 0x139000c0, 0x139000c1, 0x139000c7, 0x139000c8, - // Entry C0 - DF - 0x139000cb, 0x139000cc, 0x139000cd, 0x139000cf, - 0x139000d1, 0x139000d3, 0x139000d6, 0x139000d7, - 0x139000da, 0x139000de, 0x139000e0, 0x139000e1, - 0x139000e7, 0x139000e8, 0x139000e9, 0x139000ec, - 0x139000ed, 0x139000f1, 0x13900108, 0x1390010a, - 0x1390010b, 0x1390010c, 0x1390010d, 0x1390010e, - 0x1390010f, 0x13900110, 0x13900113, 0x13900118, - 0x1390011c, 0x1390011e, 0x13900120, 0x13900126, - // Entry E0 - FF - 0x1390012a, 0x1390012d, 0x1390012e, 0x13900130, - 0x13900132, 0x13900134, 0x13900136, 0x1390013a, - 0x1390013d, 0x1390013e, 0x13900140, 0x13900143, - 0x13900162, 0x13900163, 0x13900165, 0x13c00000, - 0x13c00001, 0x13e00000, 0x13e0001f, 0x13e0002c, - 0x13e0003f, 0x13e00041, 0x13e00048, 0x13e00051, - 0x13e00054, 0x13e00057, 0x13e0005a, 0x13e00066, - 0x13e00069, 0x13e0006a, 0x13e0006f, 0x13e00087, - // Entry 100 - 11F - 0x13e0008a, 0x13e00090, 0x13e00095, 0x13e000d0, - 0x13e000d9, 0x13e000e3, 0x13e000e5, 0x13e000e8, - 0x13e000ed, 0x13e000f2, 0x13e0011b, 0x13e00136, - 0x13e00137, 0x13e0013c, 0x14000000, 0x1400006b, - 0x14500000, 0x1450006f, 0x14600000, 0x14600052, - 0x14800000, 0x14800024, 0x1480009d, 0x14e00000, - 0x14e00052, 0x14e00085, 0x14e000ca, 0x14e00115, - 0x15100000, 0x15100073, 0x15300000, 0x153000e8, - // Entry 120 - 13F - 0x15800000, 0x15800064, 0x15800077, 0x15e00000, - 0x15e00036, 0x15e00037, 0x15e0003a, 0x15e0003b, - 0x15e0003c, 0x15e00049, 0x15e0004b, 0x15e0004c, - 0x15e0004d, 0x15e0004e, 0x15e0004f, 0x15e00052, - 0x15e00063, 0x15e00068, 0x15e00079, 0x15e0007b, - 0x15e0007f, 0x15e00085, 0x15e00086, 0x15e00087, - 0x15e00092, 0x15e000a9, 0x15e000b8, 0x15e000bb, - 0x15e000bc, 0x15e000bf, 0x15e000c0, 0x15e000c4, - // Entry 140 - 15F - 0x15e000c9, 0x15e000ca, 0x15e000cd, 0x15e000d4, - 0x15e000d5, 0x15e000e6, 0x15e000eb, 0x15e00103, - 0x15e00108, 0x15e0010b, 0x15e00115, 0x15e0011d, - 0x15e00121, 0x15e00123, 0x15e00129, 0x15e00140, - 0x15e00141, 0x15e00160, 0x16900000, 0x1690009f, - 0x16d00000, 0x16d000da, 0x16e00000, 0x16e00097, - 0x17e00000, 0x17e0007c, 0x19000000, 0x1900006f, - 0x1a300000, 0x1a30004e, 0x1a300079, 0x1a3000b3, - // Entry 160 - 17F - 0x1a400000, 0x1a40009a, 0x1a900000, 0x1ab00000, - 0x1ab000a5, 0x1ac00000, 0x1ac00099, 0x1b400000, - 0x1b400081, 0x1b4000d5, 0x1b4000d7, 0x1b800000, - 0x1b800136, 0x1bc00000, 0x1bc00098, 0x1be00000, - 0x1be0009a, 0x1d100000, 0x1d100033, 0x1d100091, - 0x1d200000, 0x1d200061, 0x1d500000, 0x1d500093, - 0x1d700000, 0x1d700028, 0x1e100000, 0x1e100096, - 0x1e700000, 0x1e7000d7, 0x1ea00000, 0x1ea00053, - // Entry 180 - 19F - 0x1f300000, 0x1f500000, 0x1f800000, 0x1f80009e, - 0x1f900000, 0x1f90004e, 0x1f90009f, 0x1f900114, - 0x1f900139, 0x1fa00000, 0x1fb00000, 0x20000000, - 0x200000a3, 0x20300000, 0x20700000, 0x20700052, - 0x20800000, 0x20a00000, 0x20a00130, 0x20e00000, - 0x20f00000, 0x21000000, 0x2100007e, 0x21200000, - 0x21200068, 0x21600000, 0x21700000, 0x217000a5, - 0x21f00000, 0x22300000, 0x22300130, 0x22700000, - // Entry 1A0 - 1BF - 0x2270005b, 0x23400000, 0x234000c4, 0x23900000, - 0x239000a5, 0x24200000, 0x242000af, 0x24400000, - 0x24400052, 0x24500000, 0x24500083, 0x24600000, - 0x246000a5, 0x24a00000, 0x24a000a7, 0x25100000, - 0x2510009a, 0x25400000, 0x254000ab, 0x254000ac, - 0x25600000, 0x2560009a, 0x26a00000, 0x26a0009a, - 0x26b00000, 0x26b00130, 0x26d00000, 0x26d00052, - 0x26e00000, 0x26e00061, 0x27400000, 0x28100000, - // Entry 1C0 - 1DF - 0x2810007c, 0x28a00000, 0x28a000a6, 0x29100000, - 0x29100130, 0x29500000, 0x295000b8, 0x2a300000, - 0x2a300132, 0x2af00000, 0x2af00136, 0x2b500000, - 0x2b50002a, 0x2b50004b, 0x2b50004c, 0x2b50004d, - 0x2b800000, 0x2b8000b0, 0x2bf00000, 0x2bf0009c, - 0x2bf0009d, 0x2c000000, 0x2c0000b7, 0x2c200000, - 0x2c20004b, 0x2c400000, 0x2c4000a5, 0x2c500000, - 0x2c5000a5, 0x2c700000, 0x2c7000b9, 0x2d100000, - // Entry 1E0 - 1FF - 0x2d1000a5, 0x2d100130, 0x2e900000, 0x2e9000a5, - 0x2ed00000, 0x2ed000cd, 0x2f100000, 0x2f1000c0, - 0x2f200000, 0x2f2000d2, 0x2f400000, 0x2f400052, - 0x2ff00000, 0x2ff000c3, 0x30400000, 0x3040009a, - 0x30b00000, 0x30b000c6, 0x31000000, 0x31b00000, - 0x31b0009a, 0x31f00000, 0x31f0003e, 0x31f000d1, - 0x31f0010e, 0x32000000, 0x320000cc, 0x32500000, - 0x32500052, 0x33100000, 0x331000c5, 0x33a00000, - // Entry 200 - 21F - 0x33a0009d, 0x34100000, 0x34500000, 0x345000d3, - 0x34700000, 0x347000db, 0x34700111, 0x34e00000, - 0x34e00165, 0x35000000, 0x35000061, 0x350000da, - 0x35100000, 0x3510009a, 0x351000dc, 0x36700000, - 0x36700030, 0x36700036, 0x36700040, 0x3670005c, - 0x367000da, 0x36700117, 0x3670011c, 0x36800000, - 0x36800052, 0x36a00000, 0x36a000db, 0x36c00000, - 0x36c00052, 0x36f00000, 0x37500000, 0x37600000, - // Entry 220 - 23F - 0x37a00000, 0x38000000, 0x38000118, 0x38700000, - 0x38900000, 0x38900132, 0x39000000, 0x39000070, - 0x390000a5, 0x39500000, 0x3950009a, 0x39800000, - 0x3980007e, 0x39800107, 0x39d00000, 0x39d05000, - 0x39d050e9, 0x39d36000, 0x39d3609a, 0x3a100000, - 0x3b300000, 0x3b3000ea, 0x3bd00000, 0x3bd00001, - 0x3be00000, 0x3be00024, 0x3c000000, 0x3c00002a, - 0x3c000041, 0x3c00004e, 0x3c00005b, 0x3c000087, - // Entry 240 - 25F - 0x3c00008c, 0x3c0000b8, 0x3c0000c7, 0x3c0000d2, - 0x3c0000ef, 0x3c000119, 0x3c000127, 0x3c400000, - 0x3c40003f, 0x3c40006a, 0x3c4000e5, 0x3d400000, - 0x3d40004e, 0x3d900000, 0x3d90003a, 0x3dc00000, - 0x3dc000bd, 0x3dc00105, 0x3de00000, 0x3de00130, - 0x3e200000, 0x3e200047, 0x3e2000a6, 0x3e2000af, - 0x3e2000bd, 0x3e200107, 0x3e200131, 0x3e500000, - 0x3e500108, 0x3e600000, 0x3e600130, 0x3eb00000, - // Entry 260 - 27F - 0x3eb00107, 0x3ec00000, 0x3ec000a5, 0x3f300000, - 0x3f300130, 0x3fa00000, 0x3fa000e9, 0x3fc00000, - 0x3fd00000, 0x3fd00073, 0x3fd000db, 0x3fd0010d, - 0x3ff00000, 0x3ff000d2, 0x40100000, 0x401000c4, - 0x40200000, 0x4020004c, 0x40700000, 0x40800000, - 0x4085b000, 0x4085b0bb, 0x408eb000, 0x408eb0bb, - 0x40c00000, 0x40c000b4, 0x41200000, 0x41200112, - 0x41600000, 0x41600110, 0x41c00000, 0x41d00000, - // Entry 280 - 29F - 0x41e00000, 0x41f00000, 0x41f00073, 0x42200000, - 0x42300000, 0x42300165, 0x42900000, 0x42900063, - 0x42900070, 0x429000a5, 0x42900116, 0x43100000, - 0x43100027, 0x431000c3, 0x4310014e, 0x43200000, - 0x43220000, 0x43220033, 0x432200be, 0x43220106, - 0x4322014e, 0x4325b000, 0x4325b033, 0x4325b0be, - 0x4325b106, 0x4325b14e, 0x43700000, 0x43a00000, - 0x43b00000, 0x44400000, 0x44400031, 0x44400073, - // Entry 2A0 - 2BF - 0x4440010d, 0x44500000, 0x4450004b, 0x445000a5, - 0x44500130, 0x44500132, 0x44e00000, 0x45000000, - 0x4500009a, 0x450000b4, 0x450000d1, 0x4500010e, - 0x46100000, 0x4610009a, 0x46400000, 0x464000a5, - 0x46400132, 0x46700000, 0x46700125, 0x46b00000, - 0x46b00124, 0x46f00000, 0x46f0006e, 0x46f00070, - 0x47100000, 0x47600000, 0x47600128, 0x47a00000, - 0x48000000, 0x48200000, 0x4820012a, 0x48a00000, - // Entry 2C0 - 2DF - 0x48a0005e, 0x48a0012c, 0x48e00000, 0x49400000, - 0x49400107, 0x4a400000, 0x4a4000d5, 0x4a900000, - 0x4a9000bb, 0x4ac00000, 0x4ac00053, 0x4ae00000, - 0x4ae00131, 0x4b400000, 0x4b40009a, 0x4b4000e9, - 0x4bc00000, 0x4bc05000, 0x4bc05024, 0x4bc20000, - 0x4bc20138, 0x4bc5b000, 0x4bc5b138, 0x4be00000, - 0x4be5b000, 0x4be5b0b5, 0x4bef4000, 0x4bef40b5, - 0x4c000000, 0x4c300000, 0x4c30013f, 0x4c900000, - // Entry 2E0 - 2FF - 0x4c900001, 0x4cc00000, 0x4cc00130, 0x4ce00000, - 0x4cf00000, 0x4cf0004e, 0x4e500000, 0x4e500115, - 0x4f200000, 0x4fb00000, 0x4fb00132, 0x50900000, - 0x50900052, 0x51200000, 0x51200001, 0x51800000, - 0x5180003b, 0x518000d7, 0x51f00000, 0x51f3b000, - 0x51f3b053, 0x51f3c000, 0x51f3c08e, 0x52800000, - 0x528000bb, 0x52900000, 0x5293b000, 0x5293b053, - 0x5293b08e, 0x5293b0c7, 0x5293b10e, 0x5293c000, - // Entry 300 - 31F - 0x5293c08e, 0x5293c0c7, 0x5293c12f, 0x52f00000, - 0x52f00162, -} // Size: 3116 bytes - -const specialTagsStr string = "ca-ES-valencia en-US-u-va-posix" - -// Total table size 3147 bytes (3KiB); checksum: 5A8FFFA5 diff --git a/vendor/golang.org/x/text/internal/language/compact/tags.go b/vendor/golang.org/x/text/internal/language/compact/tags.go deleted file mode 100644 index ca135d29..00000000 --- a/vendor/golang.org/x/text/internal/language/compact/tags.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package compact - -var ( - und = Tag{} - - Und Tag = Tag{} - - Afrikaans Tag = Tag{language: afIndex, locale: afIndex} - Amharic Tag = Tag{language: amIndex, locale: amIndex} - Arabic Tag = Tag{language: arIndex, locale: arIndex} - ModernStandardArabic Tag = Tag{language: ar001Index, locale: ar001Index} - Azerbaijani Tag = Tag{language: azIndex, locale: azIndex} - Bulgarian Tag = Tag{language: bgIndex, locale: bgIndex} - Bengali Tag = Tag{language: bnIndex, locale: bnIndex} - Catalan Tag = Tag{language: caIndex, locale: caIndex} - Czech Tag = Tag{language: csIndex, locale: csIndex} - Danish Tag = Tag{language: daIndex, locale: daIndex} - German Tag = Tag{language: deIndex, locale: deIndex} - Greek Tag = Tag{language: elIndex, locale: elIndex} - English Tag = Tag{language: enIndex, locale: enIndex} - AmericanEnglish Tag = Tag{language: enUSIndex, locale: enUSIndex} - BritishEnglish Tag = Tag{language: enGBIndex, locale: enGBIndex} - Spanish Tag = Tag{language: esIndex, locale: esIndex} - EuropeanSpanish Tag = Tag{language: esESIndex, locale: esESIndex} - LatinAmericanSpanish Tag = Tag{language: es419Index, locale: es419Index} - Estonian Tag = Tag{language: etIndex, locale: etIndex} - Persian Tag = Tag{language: faIndex, locale: faIndex} - Finnish Tag = Tag{language: fiIndex, locale: fiIndex} - Filipino Tag = Tag{language: filIndex, locale: filIndex} - French Tag = Tag{language: frIndex, locale: frIndex} - CanadianFrench Tag = Tag{language: frCAIndex, locale: frCAIndex} - Gujarati Tag = Tag{language: guIndex, locale: guIndex} - Hebrew Tag = Tag{language: heIndex, locale: heIndex} - Hindi Tag = Tag{language: hiIndex, locale: hiIndex} - Croatian Tag = Tag{language: hrIndex, locale: hrIndex} - Hungarian Tag = Tag{language: huIndex, locale: huIndex} - Armenian Tag = Tag{language: hyIndex, locale: hyIndex} - Indonesian Tag = Tag{language: idIndex, locale: idIndex} - Icelandic Tag = Tag{language: isIndex, locale: isIndex} - Italian Tag = Tag{language: itIndex, locale: itIndex} - Japanese Tag = Tag{language: jaIndex, locale: jaIndex} - Georgian Tag = Tag{language: kaIndex, locale: kaIndex} - Kazakh Tag = Tag{language: kkIndex, locale: kkIndex} - Khmer Tag = Tag{language: kmIndex, locale: kmIndex} - Kannada Tag = Tag{language: knIndex, locale: knIndex} - Korean Tag = Tag{language: koIndex, locale: koIndex} - Kirghiz Tag = Tag{language: kyIndex, locale: kyIndex} - Lao Tag = Tag{language: loIndex, locale: loIndex} - Lithuanian Tag = Tag{language: ltIndex, locale: ltIndex} - Latvian Tag = Tag{language: lvIndex, locale: lvIndex} - Macedonian Tag = Tag{language: mkIndex, locale: mkIndex} - Malayalam Tag = Tag{language: mlIndex, locale: mlIndex} - Mongolian Tag = Tag{language: mnIndex, locale: mnIndex} - Marathi Tag = Tag{language: mrIndex, locale: mrIndex} - Malay Tag = Tag{language: msIndex, locale: msIndex} - Burmese Tag = Tag{language: myIndex, locale: myIndex} - Nepali Tag = Tag{language: neIndex, locale: neIndex} - Dutch Tag = Tag{language: nlIndex, locale: nlIndex} - Norwegian Tag = Tag{language: noIndex, locale: noIndex} - Punjabi Tag = Tag{language: paIndex, locale: paIndex} - Polish Tag = Tag{language: plIndex, locale: plIndex} - Portuguese Tag = Tag{language: ptIndex, locale: ptIndex} - BrazilianPortuguese Tag = Tag{language: ptBRIndex, locale: ptBRIndex} - EuropeanPortuguese Tag = Tag{language: ptPTIndex, locale: ptPTIndex} - Romanian Tag = Tag{language: roIndex, locale: roIndex} - Russian Tag = Tag{language: ruIndex, locale: ruIndex} - Sinhala Tag = Tag{language: siIndex, locale: siIndex} - Slovak Tag = Tag{language: skIndex, locale: skIndex} - Slovenian Tag = Tag{language: slIndex, locale: slIndex} - Albanian Tag = Tag{language: sqIndex, locale: sqIndex} - Serbian Tag = Tag{language: srIndex, locale: srIndex} - SerbianLatin Tag = Tag{language: srLatnIndex, locale: srLatnIndex} - Swedish Tag = Tag{language: svIndex, locale: svIndex} - Swahili Tag = Tag{language: swIndex, locale: swIndex} - Tamil Tag = Tag{language: taIndex, locale: taIndex} - Telugu Tag = Tag{language: teIndex, locale: teIndex} - Thai Tag = Tag{language: thIndex, locale: thIndex} - Turkish Tag = Tag{language: trIndex, locale: trIndex} - Ukrainian Tag = Tag{language: ukIndex, locale: ukIndex} - Urdu Tag = Tag{language: urIndex, locale: urIndex} - Uzbek Tag = Tag{language: uzIndex, locale: uzIndex} - Vietnamese Tag = Tag{language: viIndex, locale: viIndex} - Chinese Tag = Tag{language: zhIndex, locale: zhIndex} - SimplifiedChinese Tag = Tag{language: zhHansIndex, locale: zhHansIndex} - TraditionalChinese Tag = Tag{language: zhHantIndex, locale: zhHantIndex} - Zulu Tag = Tag{language: zuIndex, locale: zuIndex} -) diff --git a/vendor/golang.org/x/text/internal/language/compose.go b/vendor/golang.org/x/text/internal/language/compose.go deleted file mode 100644 index 4ae78e0f..00000000 --- a/vendor/golang.org/x/text/internal/language/compose.go +++ /dev/null @@ -1,167 +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. - -package language - -import ( - "sort" - "strings" -) - -// A Builder allows constructing a Tag from individual components. -// Its main user is Compose in the top-level language package. -type Builder struct { - Tag Tag - - private string // the x extension - variants []string - extensions []string -} - -// Make returns a new Tag from the current settings. -func (b *Builder) Make() Tag { - t := b.Tag - - if len(b.extensions) > 0 || len(b.variants) > 0 { - sort.Sort(sortVariants(b.variants)) - sort.Strings(b.extensions) - - if b.private != "" { - b.extensions = append(b.extensions, b.private) - } - n := maxCoreSize + tokenLen(b.variants...) + tokenLen(b.extensions...) - buf := make([]byte, n) - p := t.genCoreBytes(buf) - t.pVariant = byte(p) - p += appendTokens(buf[p:], b.variants...) - t.pExt = uint16(p) - p += appendTokens(buf[p:], b.extensions...) - t.str = string(buf[:p]) - // We may not always need to remake the string, but when or when not - // to do so is rather tricky. - scan := makeScanner(buf[:p]) - t, _ = parse(&scan, "") - return t - - } else if b.private != "" { - t.str = b.private - t.RemakeString() - } - return t -} - -// SetTag copies all the settings from a given Tag. Any previously set values -// are discarded. -func (b *Builder) SetTag(t Tag) { - b.Tag.LangID = t.LangID - b.Tag.RegionID = t.RegionID - b.Tag.ScriptID = t.ScriptID - // TODO: optimize - b.variants = b.variants[:0] - if variants := t.Variants(); variants != "" { - for _, vr := range strings.Split(variants[1:], "-") { - b.variants = append(b.variants, vr) - } - } - b.extensions, b.private = b.extensions[:0], "" - for _, e := range t.Extensions() { - b.AddExt(e) - } -} - -// AddExt adds extension e to the tag. e must be a valid extension as returned -// by Tag.Extension. If the extension already exists, it will be discarded, -// except for a -u extension, where non-existing key-type pairs will added. -func (b *Builder) AddExt(e string) { - if e[0] == 'x' { - if b.private == "" { - b.private = e - } - return - } - for i, s := range b.extensions { - if s[0] == e[0] { - if e[0] == 'u' { - b.extensions[i] += e[1:] - } - return - } - } - b.extensions = append(b.extensions, e) -} - -// SetExt sets the extension e to the tag. e must be a valid extension as -// returned by Tag.Extension. If the extension already exists, it will be -// overwritten, except for a -u extension, where the individual key-type pairs -// will be set. -func (b *Builder) SetExt(e string) { - if e[0] == 'x' { - b.private = e - return - } - for i, s := range b.extensions { - if s[0] == e[0] { - if e[0] == 'u' { - b.extensions[i] = e + s[1:] - } else { - b.extensions[i] = e - } - return - } - } - b.extensions = append(b.extensions, e) -} - -// AddVariant adds any number of variants. -func (b *Builder) AddVariant(v ...string) { - for _, v := range v { - if v != "" { - b.variants = append(b.variants, v) - } - } -} - -// ClearVariants removes any variants previously added, including those -// copied from a Tag in SetTag. -func (b *Builder) ClearVariants() { - b.variants = b.variants[:0] -} - -// ClearExtensions removes any extensions previously added, including those -// copied from a Tag in SetTag. -func (b *Builder) ClearExtensions() { - b.private = "" - b.extensions = b.extensions[:0] -} - -func tokenLen(token ...string) (n int) { - for _, t := range token { - n += len(t) + 1 - } - return -} - -func appendTokens(b []byte, token ...string) int { - p := 0 - for _, t := range token { - b[p] = '-' - copy(b[p+1:], t) - p += 1 + len(t) - } - return p -} - -type sortVariants []string - -func (s sortVariants) Len() int { - return len(s) -} - -func (s sortVariants) Swap(i, j int) { - s[j], s[i] = s[i], s[j] -} - -func (s sortVariants) Less(i, j int) bool { - return variantIndex[s[i]] < variantIndex[s[j]] -} diff --git a/vendor/golang.org/x/text/internal/language/coverage.go b/vendor/golang.org/x/text/internal/language/coverage.go deleted file mode 100644 index 9b20b88f..00000000 --- a/vendor/golang.org/x/text/internal/language/coverage.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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 language - -// BaseLanguages returns the list of all supported base languages. It generates -// the list by traversing the internal structures. -func BaseLanguages() []Language { - base := make([]Language, 0, NumLanguages) - for i := 0; i < langNoIndexOffset; i++ { - // We included "und" already for the value 0. - if i != nonCanonicalUnd { - base = append(base, Language(i)) - } - } - i := langNoIndexOffset - for _, v := range langNoIndex { - for k := 0; k < 8; k++ { - if v&1 == 1 { - base = append(base, Language(i)) - } - v >>= 1 - i++ - } - } - return base -} diff --git a/vendor/golang.org/x/text/internal/language/language.go b/vendor/golang.org/x/text/internal/language/language.go deleted file mode 100644 index 09d41c73..00000000 --- a/vendor/golang.org/x/text/internal/language/language.go +++ /dev/null @@ -1,627 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen.go gen_common.go -output tables.go - -package language // import "golang.org/x/text/internal/language" - -// TODO: Remove above NOTE after: -// - verifying that tables are dropped correctly (most notably matcher tables). - -import ( - "errors" - "fmt" - "strings" -) - -const ( - // maxCoreSize is the maximum size of a BCP 47 tag without variants and - // extensions. Equals max lang (3) + script (4) + max reg (3) + 2 dashes. - maxCoreSize = 12 - - // max99thPercentileSize is a somewhat arbitrary buffer size that presumably - // is large enough to hold at least 99% of the BCP 47 tags. - max99thPercentileSize = 32 - - // maxSimpleUExtensionSize is the maximum size of a -u extension with one - // key-type pair. Equals len("-u-") + key (2) + dash + max value (8). - maxSimpleUExtensionSize = 14 -) - -// Tag represents a BCP 47 language tag. It is used to specify an instance of a -// specific language or locale. All language tag values are guaranteed to be -// well-formed. The zero value of Tag is Und. -type Tag struct { - // TODO: the following fields have the form TagTypeID. This name is chosen - // to allow refactoring the public package without conflicting with its - // Base, Script, and Region methods. Once the transition is fully completed - // the ID can be stripped from the name. - - LangID Language - RegionID Region - // TODO: we will soon run out of positions for ScriptID. Idea: instead of - // storing lang, region, and ScriptID codes, store only the compact index and - // have a lookup table from this code to its expansion. This greatly speeds - // up table lookup, speed up common variant cases. - // This will also immediately free up 3 extra bytes. Also, the pVariant - // field can now be moved to the lookup table, as the compact index uniquely - // determines the offset of a possible variant. - ScriptID Script - pVariant byte // offset in str, includes preceding '-' - pExt uint16 // offset of first extension, includes preceding '-' - - // str is the string representation of the Tag. It will only be used if the - // tag has variants or extensions. - str string -} - -// Make is a convenience wrapper for Parse that omits the error. -// In case of an error, a sensible default is returned. -func Make(s string) Tag { - t, _ := Parse(s) - return t -} - -// Raw returns the raw base language, script and region, without making an -// attempt to infer their values. -// TODO: consider removing -func (t Tag) Raw() (b Language, s Script, r Region) { - return t.LangID, t.ScriptID, t.RegionID -} - -// equalTags compares language, script and region subtags only. -func (t Tag) equalTags(a Tag) bool { - return t.LangID == a.LangID && t.ScriptID == a.ScriptID && t.RegionID == a.RegionID -} - -// IsRoot returns true if t is equal to language "und". -func (t Tag) IsRoot() bool { - if int(t.pVariant) < len(t.str) { - return false - } - return t.equalTags(Und) -} - -// IsPrivateUse reports whether the Tag consists solely of an IsPrivateUse use -// tag. -func (t Tag) IsPrivateUse() bool { - return t.str != "" && t.pVariant == 0 -} - -// RemakeString is used to update t.str in case lang, script or region changed. -// It is assumed that pExt and pVariant still point to the start of the -// respective parts. -func (t *Tag) RemakeString() { - if t.str == "" { - return - } - extra := t.str[t.pVariant:] - if t.pVariant > 0 { - extra = extra[1:] - } - if t.equalTags(Und) && strings.HasPrefix(extra, "x-") { - t.str = extra - t.pVariant = 0 - t.pExt = 0 - return - } - var buf [max99thPercentileSize]byte // avoid extra memory allocation in most cases. - b := buf[:t.genCoreBytes(buf[:])] - if extra != "" { - diff := len(b) - int(t.pVariant) - b = append(b, '-') - b = append(b, extra...) - t.pVariant = uint8(int(t.pVariant) + diff) - t.pExt = uint16(int(t.pExt) + diff) - } else { - t.pVariant = uint8(len(b)) - t.pExt = uint16(len(b)) - } - t.str = string(b) -} - -// genCoreBytes writes a string for the base languages, script and region tags -// to the given buffer and returns the number of bytes written. It will never -// write more than maxCoreSize bytes. -func (t *Tag) genCoreBytes(buf []byte) int { - n := t.LangID.StringToBuf(buf[:]) - if t.ScriptID != 0 { - n += copy(buf[n:], "-") - n += copy(buf[n:], t.ScriptID.String()) - } - if t.RegionID != 0 { - n += copy(buf[n:], "-") - n += copy(buf[n:], t.RegionID.String()) - } - return n -} - -// String returns the canonical string representation of the language tag. -func (t Tag) String() string { - if t.str != "" { - return t.str - } - if t.ScriptID == 0 && t.RegionID == 0 { - return t.LangID.String() - } - buf := [maxCoreSize]byte{} - return string(buf[:t.genCoreBytes(buf[:])]) -} - -// MarshalText implements encoding.TextMarshaler. -func (t Tag) MarshalText() (text []byte, err error) { - if t.str != "" { - text = append(text, t.str...) - } else if t.ScriptID == 0 && t.RegionID == 0 { - text = append(text, t.LangID.String()...) - } else { - buf := [maxCoreSize]byte{} - text = buf[:t.genCoreBytes(buf[:])] - } - return text, nil -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (t *Tag) UnmarshalText(text []byte) error { - tag, err := Parse(string(text)) - *t = tag - return err -} - -// Variants returns the part of the tag holding all variants or the empty string -// if there are no variants defined. -func (t Tag) Variants() string { - if t.pVariant == 0 { - return "" - } - return t.str[t.pVariant:t.pExt] -} - -// VariantOrPrivateUseTags returns variants or private use tags. -func (t Tag) VariantOrPrivateUseTags() string { - if t.pExt > 0 { - return t.str[t.pVariant:t.pExt] - } - return t.str[t.pVariant:] -} - -// HasString reports whether this tag defines more than just the raw -// components. -func (t Tag) HasString() bool { - return t.str != "" -} - -// Parent returns the CLDR parent of t. In CLDR, missing fields in data for a -// specific language are substituted with fields from the parent language. -// The parent for a language may change for newer versions of CLDR. -func (t Tag) Parent() Tag { - if t.str != "" { - // Strip the variants and extensions. - b, s, r := t.Raw() - t = Tag{LangID: b, ScriptID: s, RegionID: r} - if t.RegionID == 0 && t.ScriptID != 0 && t.LangID != 0 { - base, _ := addTags(Tag{LangID: t.LangID}) - if base.ScriptID == t.ScriptID { - return Tag{LangID: t.LangID} - } - } - return t - } - if t.LangID != 0 { - if t.RegionID != 0 { - maxScript := t.ScriptID - if maxScript == 0 { - max, _ := addTags(t) - maxScript = max.ScriptID - } - - for i := range parents { - if Language(parents[i].lang) == t.LangID && Script(parents[i].maxScript) == maxScript { - for _, r := range parents[i].fromRegion { - if Region(r) == t.RegionID { - return Tag{ - LangID: t.LangID, - ScriptID: Script(parents[i].script), - RegionID: Region(parents[i].toRegion), - } - } - } - } - } - - // Strip the script if it is the default one. - base, _ := addTags(Tag{LangID: t.LangID}) - if base.ScriptID != maxScript { - return Tag{LangID: t.LangID, ScriptID: maxScript} - } - return Tag{LangID: t.LangID} - } else if t.ScriptID != 0 { - // The parent for an base-script pair with a non-default script is - // "und" instead of the base language. - base, _ := addTags(Tag{LangID: t.LangID}) - if base.ScriptID != t.ScriptID { - return Und - } - return Tag{LangID: t.LangID} - } - } - return Und -} - -// ParseExtension parses s as an extension and returns it on success. -func ParseExtension(s string) (ext string, err error) { - defer func() { - if recover() != nil { - ext = "" - err = ErrSyntax - } - }() - - scan := makeScannerString(s) - var end int - if n := len(scan.token); n != 1 { - return "", ErrSyntax - } - scan.toLower(0, len(scan.b)) - end = parseExtension(&scan) - if end != len(s) { - return "", ErrSyntax - } - return string(scan.b), nil -} - -// HasVariants reports whether t has variants. -func (t Tag) HasVariants() bool { - return uint16(t.pVariant) < t.pExt -} - -// HasExtensions reports whether t has extensions. -func (t Tag) HasExtensions() bool { - return int(t.pExt) < len(t.str) -} - -// Extension returns the extension of type x for tag t. It will return -// false for ok if t does not have the requested extension. The returned -// extension will be invalid in this case. -func (t Tag) Extension(x byte) (ext string, ok bool) { - for i := int(t.pExt); i < len(t.str)-1; { - var ext string - i, ext = getExtension(t.str, i) - if ext[0] == x { - return ext, true - } - } - return "", false -} - -// Extensions returns all extensions of t. -func (t Tag) Extensions() []string { - e := []string{} - for i := int(t.pExt); i < len(t.str)-1; { - var ext string - i, ext = getExtension(t.str, i) - e = append(e, ext) - } - return e -} - -// TypeForKey returns the type associated with the given key, where key and type -// are of the allowed values defined for the Unicode locale extension ('u') in -// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. -// TypeForKey will traverse the inheritance chain to get the correct value. -// -// If there are multiple types associated with a key, only the first will be -// returned. If there is no type associated with a key, it returns the empty -// string. -func (t Tag) TypeForKey(key string) string { - if _, start, end, _ := t.findTypeForKey(key); end != start { - s := t.str[start:end] - if p := strings.IndexByte(s, '-'); p >= 0 { - s = s[:p] - } - return s - } - return "" -} - -var ( - errPrivateUse = errors.New("cannot set a key on a private use tag") - errInvalidArguments = errors.New("invalid key or type") -) - -// SetTypeForKey returns a new Tag with the key set to type, where key and type -// are of the allowed values defined for the Unicode locale extension ('u') in -// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. -// An empty value removes an existing pair with the same key. -func (t Tag) SetTypeForKey(key, value string) (Tag, error) { - if t.IsPrivateUse() { - return t, errPrivateUse - } - if len(key) != 2 { - return t, errInvalidArguments - } - - // Remove the setting if value is "". - if value == "" { - start, sep, end, _ := t.findTypeForKey(key) - if start != sep { - // Remove a possible empty extension. - switch { - case t.str[start-2] != '-': // has previous elements. - case end == len(t.str), // end of string - end+2 < len(t.str) && t.str[end+2] == '-': // end of extension - start -= 2 - } - if start == int(t.pVariant) && end == len(t.str) { - t.str = "" - t.pVariant, t.pExt = 0, 0 - } else { - t.str = fmt.Sprintf("%s%s", t.str[:start], t.str[end:]) - } - } - return t, nil - } - - if len(value) < 3 || len(value) > 8 { - return t, errInvalidArguments - } - - var ( - buf [maxCoreSize + maxSimpleUExtensionSize]byte - uStart int // start of the -u extension. - ) - - // Generate the tag string if needed. - if t.str == "" { - uStart = t.genCoreBytes(buf[:]) - buf[uStart] = '-' - uStart++ - } - - // Create new key-type pair and parse it to verify. - b := buf[uStart:] - copy(b, "u-") - copy(b[2:], key) - b[4] = '-' - b = b[:5+copy(b[5:], value)] - scan := makeScanner(b) - if parseExtensions(&scan); scan.err != nil { - return t, scan.err - } - - // Assemble the replacement string. - if t.str == "" { - t.pVariant, t.pExt = byte(uStart-1), uint16(uStart-1) - t.str = string(buf[:uStart+len(b)]) - } else { - s := t.str - start, sep, end, hasExt := t.findTypeForKey(key) - if start == sep { - if hasExt { - b = b[2:] - } - t.str = fmt.Sprintf("%s-%s%s", s[:sep], b, s[end:]) - } else { - t.str = fmt.Sprintf("%s-%s%s", s[:start+3], value, s[end:]) - } - } - return t, nil -} - -// findTypeForKey returns the start and end position for the type corresponding -// to key or the point at which to insert the key-value pair if the type -// wasn't found. The hasExt return value reports whether an -u extension was present. -// Note: the extensions are typically very small and are likely to contain -// only one key-type pair. -func (t Tag) findTypeForKey(key string) (start, sep, end int, hasExt bool) { - p := int(t.pExt) - if len(key) != 2 || p == len(t.str) || p == 0 { - return p, p, p, false - } - s := t.str - - // Find the correct extension. - for p++; s[p] != 'u'; p++ { - if s[p] > 'u' { - p-- - return p, p, p, false - } - if p = nextExtension(s, p); p == len(s) { - return len(s), len(s), len(s), false - } - } - // Proceed to the hyphen following the extension name. - p++ - - // curKey is the key currently being processed. - curKey := "" - - // Iterate over keys until we get the end of a section. - for { - end = p - for p++; p < len(s) && s[p] != '-'; p++ { - } - n := p - end - 1 - if n <= 2 && curKey == key { - if sep < end { - sep++ - } - return start, sep, end, true - } - switch n { - case 0, // invalid string - 1: // next extension - return end, end, end, true - case 2: - // next key - curKey = s[end+1 : p] - if curKey > key { - return end, end, end, true - } - start = end - sep = p - } - } -} - -// ParseBase parses a 2- or 3-letter ISO 639 code. -// It returns a ValueError if s is a well-formed but unknown language identifier -// or another error if another error occurred. -func ParseBase(s string) (l Language, err error) { - defer func() { - if recover() != nil { - l = 0 - err = ErrSyntax - } - }() - - if n := len(s); n < 2 || 3 < n { - return 0, ErrSyntax - } - var buf [3]byte - return getLangID(buf[:copy(buf[:], s)]) -} - -// ParseScript parses a 4-letter ISO 15924 code. -// It returns a ValueError if s is a well-formed but unknown script identifier -// or another error if another error occurred. -func ParseScript(s string) (scr Script, err error) { - defer func() { - if recover() != nil { - scr = 0 - err = ErrSyntax - } - }() - - if len(s) != 4 { - return 0, ErrSyntax - } - var buf [4]byte - return getScriptID(script, buf[:copy(buf[:], s)]) -} - -// EncodeM49 returns the Region for the given UN M.49 code. -// It returns an error if r is not a valid code. -func EncodeM49(r int) (Region, error) { - return getRegionM49(r) -} - -// ParseRegion parses a 2- or 3-letter ISO 3166-1 or a UN M.49 code. -// It returns a ValueError if s is a well-formed but unknown region identifier -// or another error if another error occurred. -func ParseRegion(s string) (r Region, err error) { - defer func() { - if recover() != nil { - r = 0 - err = ErrSyntax - } - }() - - if n := len(s); n < 2 || 3 < n { - return 0, ErrSyntax - } - var buf [3]byte - return getRegionID(buf[:copy(buf[:], s)]) -} - -// IsCountry returns whether this region is a country or autonomous area. This -// includes non-standard definitions from CLDR. -func (r Region) IsCountry() bool { - if r == 0 || r.IsGroup() || r.IsPrivateUse() && r != _XK { - return false - } - return true -} - -// IsGroup returns whether this region defines a collection of regions. This -// includes non-standard definitions from CLDR. -func (r Region) IsGroup() bool { - if r == 0 { - return false - } - return int(regionInclusion[r]) < len(regionContainment) -} - -// Contains returns whether Region c is contained by Region r. It returns true -// if c == r. -func (r Region) Contains(c Region) bool { - if r == c { - return true - } - g := regionInclusion[r] - if g >= nRegionGroups { - return false - } - m := regionContainment[g] - - d := regionInclusion[c] - b := regionInclusionBits[d] - - // A contained country may belong to multiple disjoint groups. Matching any - // of these indicates containment. If the contained region is a group, it - // must strictly be a subset. - if d >= nRegionGroups { - return b&m != 0 - } - return b&^m == 0 -} - -var errNoTLD = errors.New("language: region is not a valid ccTLD") - -// TLD returns the country code top-level domain (ccTLD). UK is returned for GB. -// In all other cases it returns either the region itself or an error. -// -// This method may return an error for a region for which there exists a -// canonical form with a ccTLD. To get that ccTLD canonicalize r first. The -// region will already be canonicalized it was obtained from a Tag that was -// obtained using any of the default methods. -func (r Region) TLD() (Region, error) { - // See http://en.wikipedia.org/wiki/Country_code_top-level_domain for the - // difference between ISO 3166-1 and IANA ccTLD. - if r == _GB { - r = _UK - } - if (r.typ() & ccTLD) == 0 { - return 0, errNoTLD - } - return r, nil -} - -// Canonicalize returns the region or a possible replacement if the region is -// deprecated. It will not return a replacement for deprecated regions that -// are split into multiple regions. -func (r Region) Canonicalize() Region { - if cr := normRegion(r); cr != 0 { - return cr - } - return r -} - -// Variant represents a registered variant of a language as defined by BCP 47. -type Variant struct { - ID uint8 - str string -} - -// ParseVariant parses and returns a Variant. An error is returned if s is not -// a valid variant. -func ParseVariant(s string) (v Variant, err error) { - defer func() { - if recover() != nil { - v = Variant{} - err = ErrSyntax - } - }() - - s = strings.ToLower(s) - if id, ok := variantIndex[s]; ok { - return Variant{id, s}, nil - } - return Variant{}, NewValueError([]byte(s)) -} - -// String returns the string representation of the variant. -func (v Variant) String() string { - return v.str -} diff --git a/vendor/golang.org/x/text/internal/language/lookup.go b/vendor/golang.org/x/text/internal/language/lookup.go deleted file mode 100644 index 231b4fbd..00000000 --- a/vendor/golang.org/x/text/internal/language/lookup.go +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "bytes" - "fmt" - "sort" - "strconv" - - "golang.org/x/text/internal/tag" -) - -// findIndex tries to find the given tag in idx and returns a standardized error -// if it could not be found. -func findIndex(idx tag.Index, key []byte, form string) (index int, err error) { - if !tag.FixCase(form, key) { - return 0, ErrSyntax - } - i := idx.Index(key) - if i == -1 { - return 0, NewValueError(key) - } - return i, nil -} - -func searchUint(imap []uint16, key uint16) int { - return sort.Search(len(imap), func(i int) bool { - return imap[i] >= key - }) -} - -type Language uint16 - -// getLangID returns the langID of s if s is a canonical subtag -// or langUnknown if s is not a canonical subtag. -func getLangID(s []byte) (Language, error) { - if len(s) == 2 { - return getLangISO2(s) - } - return getLangISO3(s) -} - -// TODO language normalization as well as the AliasMaps could be moved to the -// higher level package, but it is a bit tricky to separate the generation. - -func (id Language) Canonicalize() (Language, AliasType) { - return normLang(id) -} - -// normLang returns the mapped langID of id according to mapping m. -func normLang(id Language) (Language, AliasType) { - k := sort.Search(len(AliasMap), func(i int) bool { - return AliasMap[i].From >= uint16(id) - }) - if k < len(AliasMap) && AliasMap[k].From == uint16(id) { - return Language(AliasMap[k].To), AliasTypes[k] - } - return id, AliasTypeUnknown -} - -// getLangISO2 returns the langID for the given 2-letter ISO language code -// or unknownLang if this does not exist. -func getLangISO2(s []byte) (Language, error) { - if !tag.FixCase("zz", s) { - return 0, ErrSyntax - } - if i := lang.Index(s); i != -1 && lang.Elem(i)[3] != 0 { - return Language(i), nil - } - return 0, NewValueError(s) -} - -const base = 'z' - 'a' + 1 - -func strToInt(s []byte) uint { - v := uint(0) - for i := 0; i < len(s); i++ { - v *= base - v += uint(s[i] - 'a') - } - return v -} - -// converts the given integer to the original ASCII string passed to strToInt. -// len(s) must match the number of characters obtained. -func intToStr(v uint, s []byte) { - for i := len(s) - 1; i >= 0; i-- { - s[i] = byte(v%base) + 'a' - v /= base - } -} - -// getLangISO3 returns the langID for the given 3-letter ISO language code -// or unknownLang if this does not exist. -func getLangISO3(s []byte) (Language, error) { - if tag.FixCase("und", s) { - // first try to match canonical 3-letter entries - for i := lang.Index(s[:2]); i != -1; i = lang.Next(s[:2], i) { - if e := lang.Elem(i); e[3] == 0 && e[2] == s[2] { - // We treat "und" as special and always translate it to "unspecified". - // Note that ZZ and Zzzz are private use and are not treated as - // unspecified by default. - id := Language(i) - if id == nonCanonicalUnd { - return 0, nil - } - return id, nil - } - } - if i := altLangISO3.Index(s); i != -1 { - return Language(altLangIndex[altLangISO3.Elem(i)[3]]), nil - } - n := strToInt(s) - if langNoIndex[n/8]&(1<<(n%8)) != 0 { - return Language(n) + langNoIndexOffset, nil - } - // Check for non-canonical uses of ISO3. - for i := lang.Index(s[:1]); i != -1; i = lang.Next(s[:1], i) { - if e := lang.Elem(i); e[2] == s[1] && e[3] == s[2] { - return Language(i), nil - } - } - return 0, NewValueError(s) - } - return 0, ErrSyntax -} - -// StringToBuf writes the string to b and returns the number of bytes -// written. cap(b) must be >= 3. -func (id Language) StringToBuf(b []byte) int { - if id >= langNoIndexOffset { - intToStr(uint(id)-langNoIndexOffset, b[:3]) - return 3 - } else if id == 0 { - return copy(b, "und") - } - l := lang[id<<2:] - if l[3] == 0 { - return copy(b, l[:3]) - } - return copy(b, l[:2]) -} - -// String returns the BCP 47 representation of the langID. -// Use b as variable name, instead of id, to ensure the variable -// used is consistent with that of Base in which this type is embedded. -func (b Language) String() string { - if b == 0 { - return "und" - } else if b >= langNoIndexOffset { - b -= langNoIndexOffset - buf := [3]byte{} - intToStr(uint(b), buf[:]) - return string(buf[:]) - } - l := lang.Elem(int(b)) - if l[3] == 0 { - return l[:3] - } - return l[:2] -} - -// ISO3 returns the ISO 639-3 language code. -func (b Language) ISO3() string { - if b == 0 || b >= langNoIndexOffset { - return b.String() - } - l := lang.Elem(int(b)) - if l[3] == 0 { - return l[:3] - } else if l[2] == 0 { - return altLangISO3.Elem(int(l[3]))[:3] - } - // This allocation will only happen for 3-letter ISO codes - // that are non-canonical BCP 47 language identifiers. - return l[0:1] + l[2:4] -} - -// IsPrivateUse reports whether this language code is reserved for private use. -func (b Language) IsPrivateUse() bool { - return langPrivateStart <= b && b <= langPrivateEnd -} - -// SuppressScript returns the script marked as SuppressScript in the IANA -// language tag repository, or 0 if there is no such script. -func (b Language) SuppressScript() Script { - if b < langNoIndexOffset { - return Script(suppressScript[b]) - } - return 0 -} - -type Region uint16 - -// getRegionID returns the region id for s if s is a valid 2-letter region code -// or unknownRegion. -func getRegionID(s []byte) (Region, error) { - if len(s) == 3 { - if isAlpha(s[0]) { - return getRegionISO3(s) - } - if i, err := strconv.ParseUint(string(s), 10, 10); err == nil { - return getRegionM49(int(i)) - } - } - return getRegionISO2(s) -} - -// getRegionISO2 returns the regionID for the given 2-letter ISO country code -// or unknownRegion if this does not exist. -func getRegionISO2(s []byte) (Region, error) { - i, err := findIndex(regionISO, s, "ZZ") - if err != nil { - return 0, err - } - return Region(i) + isoRegionOffset, nil -} - -// getRegionISO3 returns the regionID for the given 3-letter ISO country code -// or unknownRegion if this does not exist. -func getRegionISO3(s []byte) (Region, error) { - if tag.FixCase("ZZZ", s) { - for i := regionISO.Index(s[:1]); i != -1; i = regionISO.Next(s[:1], i) { - if e := regionISO.Elem(i); e[2] == s[1] && e[3] == s[2] { - return Region(i) + isoRegionOffset, nil - } - } - for i := 0; i < len(altRegionISO3); i += 3 { - if tag.Compare(altRegionISO3[i:i+3], s) == 0 { - return Region(altRegionIDs[i/3]), nil - } - } - return 0, NewValueError(s) - } - return 0, ErrSyntax -} - -func getRegionM49(n int) (Region, error) { - if 0 < n && n <= 999 { - const ( - searchBits = 7 - regionBits = 9 - regionMask = 1<<regionBits - 1 - ) - idx := n >> searchBits - buf := fromM49[m49Index[idx]:m49Index[idx+1]] - val := uint16(n) << regionBits // we rely on bits shifting out - i := sort.Search(len(buf), func(i int) bool { - return buf[i] >= val - }) - if r := fromM49[int(m49Index[idx])+i]; r&^regionMask == val { - return Region(r & regionMask), nil - } - } - var e ValueError - fmt.Fprint(bytes.NewBuffer([]byte(e.v[:])), n) - return 0, e -} - -// normRegion returns a region if r is deprecated or 0 otherwise. -// TODO: consider supporting BYS (-> BLR), CSK (-> 200 or CZ), PHI (-> PHL) and AFI (-> DJ). -// TODO: consider mapping split up regions to new most populous one (like CLDR). -func normRegion(r Region) Region { - m := regionOldMap - k := sort.Search(len(m), func(i int) bool { - return m[i].From >= uint16(r) - }) - if k < len(m) && m[k].From == uint16(r) { - return Region(m[k].To) - } - return 0 -} - -const ( - iso3166UserAssigned = 1 << iota - ccTLD - bcp47Region -) - -func (r Region) typ() byte { - return regionTypes[r] -} - -// String returns the BCP 47 representation for the region. -// It returns "ZZ" for an unspecified region. -func (r Region) String() string { - if r < isoRegionOffset { - if r == 0 { - return "ZZ" - } - return fmt.Sprintf("%03d", r.M49()) - } - r -= isoRegionOffset - return regionISO.Elem(int(r))[:2] -} - -// ISO3 returns the 3-letter ISO code of r. -// Note that not all regions have a 3-letter ISO code. -// In such cases this method returns "ZZZ". -func (r Region) ISO3() string { - if r < isoRegionOffset { - return "ZZZ" - } - r -= isoRegionOffset - reg := regionISO.Elem(int(r)) - switch reg[2] { - case 0: - return altRegionISO3[reg[3]:][:3] - case ' ': - return "ZZZ" - } - return reg[0:1] + reg[2:4] -} - -// M49 returns the UN M.49 encoding of r, or 0 if this encoding -// is not defined for r. -func (r Region) M49() int { - return int(m49[r]) -} - -// IsPrivateUse reports whether r has the ISO 3166 User-assigned status. This -// may include private-use tags that are assigned by CLDR and used in this -// implementation. So IsPrivateUse and IsCountry can be simultaneously true. -func (r Region) IsPrivateUse() bool { - return r.typ()&iso3166UserAssigned != 0 -} - -type Script uint16 - -// getScriptID returns the script id for string s. It assumes that s -// is of the format [A-Z][a-z]{3}. -func getScriptID(idx tag.Index, s []byte) (Script, error) { - i, err := findIndex(idx, s, "Zzzz") - return Script(i), err -} - -// String returns the script code in title case. -// It returns "Zzzz" for an unspecified script. -func (s Script) String() string { - if s == 0 { - return "Zzzz" - } - return script.Elem(int(s)) -} - -// IsPrivateUse reports whether this script code is reserved for private use. -func (s Script) IsPrivateUse() bool { - return _Qaaa <= s && s <= _Qabx -} - -const ( - maxAltTaglen = len("en-US-POSIX") - maxLen = maxAltTaglen -) - -var ( - // grandfatheredMap holds a mapping from legacy and grandfathered tags to - // their base language or index to more elaborate tag. - grandfatheredMap = map[[maxLen]byte]int16{ - [maxLen]byte{'a', 'r', 't', '-', 'l', 'o', 'j', 'b', 'a', 'n'}: _jbo, // art-lojban - [maxLen]byte{'i', '-', 'a', 'm', 'i'}: _ami, // i-ami - [maxLen]byte{'i', '-', 'b', 'n', 'n'}: _bnn, // i-bnn - [maxLen]byte{'i', '-', 'h', 'a', 'k'}: _hak, // i-hak - [maxLen]byte{'i', '-', 'k', 'l', 'i', 'n', 'g', 'o', 'n'}: _tlh, // i-klingon - [maxLen]byte{'i', '-', 'l', 'u', 'x'}: _lb, // i-lux - [maxLen]byte{'i', '-', 'n', 'a', 'v', 'a', 'j', 'o'}: _nv, // i-navajo - [maxLen]byte{'i', '-', 'p', 'w', 'n'}: _pwn, // i-pwn - [maxLen]byte{'i', '-', 't', 'a', 'o'}: _tao, // i-tao - [maxLen]byte{'i', '-', 't', 'a', 'y'}: _tay, // i-tay - [maxLen]byte{'i', '-', 't', 's', 'u'}: _tsu, // i-tsu - [maxLen]byte{'n', 'o', '-', 'b', 'o', 'k'}: _nb, // no-bok - [maxLen]byte{'n', 'o', '-', 'n', 'y', 'n'}: _nn, // no-nyn - [maxLen]byte{'s', 'g', 'n', '-', 'b', 'e', '-', 'f', 'r'}: _sfb, // sgn-BE-FR - [maxLen]byte{'s', 'g', 'n', '-', 'b', 'e', '-', 'n', 'l'}: _vgt, // sgn-BE-NL - [maxLen]byte{'s', 'g', 'n', '-', 'c', 'h', '-', 'd', 'e'}: _sgg, // sgn-CH-DE - [maxLen]byte{'z', 'h', '-', 'g', 'u', 'o', 'y', 'u'}: _cmn, // zh-guoyu - [maxLen]byte{'z', 'h', '-', 'h', 'a', 'k', 'k', 'a'}: _hak, // zh-hakka - [maxLen]byte{'z', 'h', '-', 'm', 'i', 'n', '-', 'n', 'a', 'n'}: _nan, // zh-min-nan - [maxLen]byte{'z', 'h', '-', 'x', 'i', 'a', 'n', 'g'}: _hsn, // zh-xiang - - // Grandfathered tags with no modern replacement will be converted as - // follows: - [maxLen]byte{'c', 'e', 'l', '-', 'g', 'a', 'u', 'l', 'i', 's', 'h'}: -1, // cel-gaulish - [maxLen]byte{'e', 'n', '-', 'g', 'b', '-', 'o', 'e', 'd'}: -2, // en-GB-oed - [maxLen]byte{'i', '-', 'd', 'e', 'f', 'a', 'u', 'l', 't'}: -3, // i-default - [maxLen]byte{'i', '-', 'e', 'n', 'o', 'c', 'h', 'i', 'a', 'n'}: -4, // i-enochian - [maxLen]byte{'i', '-', 'm', 'i', 'n', 'g', 'o'}: -5, // i-mingo - [maxLen]byte{'z', 'h', '-', 'm', 'i', 'n'}: -6, // zh-min - - // CLDR-specific tag. - [maxLen]byte{'r', 'o', 'o', 't'}: 0, // root - [maxLen]byte{'e', 'n', '-', 'u', 's', '-', 'p', 'o', 's', 'i', 'x'}: -7, // en_US_POSIX" - } - - altTagIndex = [...]uint8{0, 17, 31, 45, 61, 74, 86, 102} - - altTags = "xtg-x-cel-gaulishen-GB-oxendicten-x-i-defaultund-x-i-enochiansee-x-i-mingonan-x-zh-minen-US-u-va-posix" -) - -func grandfathered(s [maxAltTaglen]byte) (t Tag, ok bool) { - if v, ok := grandfatheredMap[s]; ok { - if v < 0 { - return Make(altTags[altTagIndex[-v-1]:altTagIndex[-v]]), true - } - t.LangID = Language(v) - return t, true - } - return t, false -} diff --git a/vendor/golang.org/x/text/internal/language/match.go b/vendor/golang.org/x/text/internal/language/match.go deleted file mode 100644 index 75a2dbca..00000000 --- a/vendor/golang.org/x/text/internal/language/match.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import "errors" - -type scriptRegionFlags uint8 - -const ( - isList = 1 << iota - scriptInFrom - regionInFrom -) - -func (t *Tag) setUndefinedLang(id Language) { - if t.LangID == 0 { - t.LangID = id - } -} - -func (t *Tag) setUndefinedScript(id Script) { - if t.ScriptID == 0 { - t.ScriptID = id - } -} - -func (t *Tag) setUndefinedRegion(id Region) { - if t.RegionID == 0 || t.RegionID.Contains(id) { - t.RegionID = id - } -} - -// ErrMissingLikelyTagsData indicates no information was available -// to compute likely values of missing tags. -var ErrMissingLikelyTagsData = errors.New("missing likely tags data") - -// addLikelySubtags sets subtags to their most likely value, given the locale. -// In most cases this means setting fields for unknown values, but in some -// cases it may alter a value. It returns an ErrMissingLikelyTagsData error -// if the given locale cannot be expanded. -func (t Tag) addLikelySubtags() (Tag, error) { - id, err := addTags(t) - if err != nil { - return t, err - } else if id.equalTags(t) { - return t, nil - } - id.RemakeString() - return id, nil -} - -// specializeRegion attempts to specialize a group region. -func specializeRegion(t *Tag) bool { - if i := regionInclusion[t.RegionID]; i < nRegionGroups { - x := likelyRegionGroup[i] - if Language(x.lang) == t.LangID && Script(x.script) == t.ScriptID { - t.RegionID = Region(x.region) - } - return true - } - return false -} - -// Maximize returns a new tag with missing tags filled in. -func (t Tag) Maximize() (Tag, error) { - return addTags(t) -} - -func addTags(t Tag) (Tag, error) { - // We leave private use identifiers alone. - if t.IsPrivateUse() { - return t, nil - } - if t.ScriptID != 0 && t.RegionID != 0 { - if t.LangID != 0 { - // already fully specified - specializeRegion(&t) - return t, nil - } - // Search matches for und-script-region. Note that for these cases - // region will never be a group so there is no need to check for this. - list := likelyRegion[t.RegionID : t.RegionID+1] - if x := list[0]; x.flags&isList != 0 { - list = likelyRegionList[x.lang : x.lang+uint16(x.script)] - } - for _, x := range list { - // Deviating from the spec. See match_test.go for details. - if Script(x.script) == t.ScriptID { - t.setUndefinedLang(Language(x.lang)) - return t, nil - } - } - } - if t.LangID != 0 { - // Search matches for lang-script and lang-region, where lang != und. - if t.LangID < langNoIndexOffset { - x := likelyLang[t.LangID] - if x.flags&isList != 0 { - list := likelyLangList[x.region : x.region+uint16(x.script)] - if t.ScriptID != 0 { - for _, x := range list { - if Script(x.script) == t.ScriptID && x.flags&scriptInFrom != 0 { - t.setUndefinedRegion(Region(x.region)) - return t, nil - } - } - } else if t.RegionID != 0 { - count := 0 - goodScript := true - tt := t - for _, x := range list { - // We visit all entries for which the script was not - // defined, including the ones where the region was not - // defined. This allows for proper disambiguation within - // regions. - if x.flags&scriptInFrom == 0 && t.RegionID.Contains(Region(x.region)) { - tt.RegionID = Region(x.region) - tt.setUndefinedScript(Script(x.script)) - goodScript = goodScript && tt.ScriptID == Script(x.script) - count++ - } - } - if count == 1 { - return tt, nil - } - // Even if we fail to find a unique Region, we might have - // an unambiguous script. - if goodScript { - t.ScriptID = tt.ScriptID - } - } - } - } - } else { - // Search matches for und-script. - if t.ScriptID != 0 { - x := likelyScript[t.ScriptID] - if x.region != 0 { - t.setUndefinedRegion(Region(x.region)) - t.setUndefinedLang(Language(x.lang)) - return t, nil - } - } - // Search matches for und-region. If und-script-region exists, it would - // have been found earlier. - if t.RegionID != 0 { - if i := regionInclusion[t.RegionID]; i < nRegionGroups { - x := likelyRegionGroup[i] - if x.region != 0 { - t.setUndefinedLang(Language(x.lang)) - t.setUndefinedScript(Script(x.script)) - t.RegionID = Region(x.region) - } - } else { - x := likelyRegion[t.RegionID] - if x.flags&isList != 0 { - x = likelyRegionList[x.lang] - } - if x.script != 0 && x.flags != scriptInFrom { - t.setUndefinedLang(Language(x.lang)) - t.setUndefinedScript(Script(x.script)) - return t, nil - } - } - } - } - - // Search matches for lang. - if t.LangID < langNoIndexOffset { - x := likelyLang[t.LangID] - if x.flags&isList != 0 { - x = likelyLangList[x.region] - } - if x.region != 0 { - t.setUndefinedScript(Script(x.script)) - t.setUndefinedRegion(Region(x.region)) - } - specializeRegion(&t) - if t.LangID == 0 { - t.LangID = _en // default language - } - return t, nil - } - return t, ErrMissingLikelyTagsData -} - -func (t *Tag) setTagsFrom(id Tag) { - t.LangID = id.LangID - t.ScriptID = id.ScriptID - t.RegionID = id.RegionID -} - -// minimize removes the region or script subtags from t such that -// t.addLikelySubtags() == t.minimize().addLikelySubtags(). -func (t Tag) minimize() (Tag, error) { - t, err := minimizeTags(t) - if err != nil { - return t, err - } - t.RemakeString() - return t, nil -} - -// minimizeTags mimics the behavior of the ICU 51 C implementation. -func minimizeTags(t Tag) (Tag, error) { - if t.equalTags(Und) { - return t, nil - } - max, err := addTags(t) - if err != nil { - return t, err - } - for _, id := range [...]Tag{ - {LangID: t.LangID}, - {LangID: t.LangID, RegionID: t.RegionID}, - {LangID: t.LangID, ScriptID: t.ScriptID}, - } { - if x, err := addTags(id); err == nil && max.equalTags(x) { - t.setTagsFrom(id) - break - } - } - return t, nil -} diff --git a/vendor/golang.org/x/text/internal/language/parse.go b/vendor/golang.org/x/text/internal/language/parse.go deleted file mode 100644 index aad1e0ac..00000000 --- a/vendor/golang.org/x/text/internal/language/parse.go +++ /dev/null @@ -1,608 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "bytes" - "errors" - "fmt" - "sort" - - "golang.org/x/text/internal/tag" -) - -// isAlpha returns true if the byte is not a digit. -// b must be an ASCII letter or digit. -func isAlpha(b byte) bool { - return b > '9' -} - -// isAlphaNum returns true if the string contains only ASCII letters or digits. -func isAlphaNum(s []byte) bool { - for _, c := range s { - if !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9') { - return false - } - } - return true -} - -// ErrSyntax is returned by any of the parsing functions when the -// input is not well-formed, according to BCP 47. -// TODO: return the position at which the syntax error occurred? -var ErrSyntax = errors.New("language: tag is not well-formed") - -// ErrDuplicateKey is returned when a tag contains the same key twice with -// different values in the -u section. -var ErrDuplicateKey = errors.New("language: different values for same key in -u extension") - -// ValueError is returned by any of the parsing functions when the -// input is well-formed but the respective subtag is not recognized -// as a valid value. -type ValueError struct { - v [8]byte -} - -// NewValueError creates a new ValueError. -func NewValueError(tag []byte) ValueError { - var e ValueError - copy(e.v[:], tag) - return e -} - -func (e ValueError) tag() []byte { - n := bytes.IndexByte(e.v[:], 0) - if n == -1 { - n = 8 - } - return e.v[:n] -} - -// Error implements the error interface. -func (e ValueError) Error() string { - return fmt.Sprintf("language: subtag %q is well-formed but unknown", e.tag()) -} - -// Subtag returns the subtag for which the error occurred. -func (e ValueError) Subtag() string { - return string(e.tag()) -} - -// scanner is used to scan BCP 47 tokens, which are separated by _ or -. -type scanner struct { - b []byte - bytes [max99thPercentileSize]byte - token []byte - start int // start position of the current token - end int // end position of the current token - next int // next point for scan - err error - done bool -} - -func makeScannerString(s string) scanner { - scan := scanner{} - if len(s) <= len(scan.bytes) { - scan.b = scan.bytes[:copy(scan.bytes[:], s)] - } else { - scan.b = []byte(s) - } - scan.init() - return scan -} - -// makeScanner returns a scanner using b as the input buffer. -// b is not copied and may be modified by the scanner routines. -func makeScanner(b []byte) scanner { - scan := scanner{b: b} - scan.init() - return scan -} - -func (s *scanner) init() { - for i, c := range s.b { - if c == '_' { - s.b[i] = '-' - } - } - s.scan() -} - -// restToLower converts the string between start and end to lower case. -func (s *scanner) toLower(start, end int) { - for i := start; i < end; i++ { - c := s.b[i] - if 'A' <= c && c <= 'Z' { - s.b[i] += 'a' - 'A' - } - } -} - -func (s *scanner) setError(e error) { - if s.err == nil || (e == ErrSyntax && s.err != ErrSyntax) { - s.err = e - } -} - -// resizeRange shrinks or grows the array at position oldStart such that -// a new string of size newSize can fit between oldStart and oldEnd. -// Sets the scan point to after the resized range. -func (s *scanner) resizeRange(oldStart, oldEnd, newSize int) { - s.start = oldStart - if end := oldStart + newSize; end != oldEnd { - diff := end - oldEnd - var b []byte - if n := len(s.b) + diff; n > cap(s.b) { - b = make([]byte, n) - copy(b, s.b[:oldStart]) - } else { - b = s.b[:n] - } - copy(b[end:], s.b[oldEnd:]) - s.b = b - s.next = end + (s.next - s.end) - s.end = end - } -} - -// replace replaces the current token with repl. -func (s *scanner) replace(repl string) { - s.resizeRange(s.start, s.end, len(repl)) - copy(s.b[s.start:], repl) -} - -// gobble removes the current token from the input. -// Caller must call scan after calling gobble. -func (s *scanner) gobble(e error) { - s.setError(e) - if s.start == 0 { - s.b = s.b[:+copy(s.b, s.b[s.next:])] - s.end = 0 - } else { - s.b = s.b[:s.start-1+copy(s.b[s.start-1:], s.b[s.end:])] - s.end = s.start - 1 - } - s.next = s.start -} - -// deleteRange removes the given range from s.b before the current token. -func (s *scanner) deleteRange(start, end int) { - s.b = s.b[:start+copy(s.b[start:], s.b[end:])] - diff := end - start - s.next -= diff - s.start -= diff - s.end -= diff -} - -// scan parses the next token of a BCP 47 string. Tokens that are larger -// than 8 characters or include non-alphanumeric characters result in an error -// and are gobbled and removed from the output. -// It returns the end position of the last token consumed. -func (s *scanner) scan() (end int) { - end = s.end - s.token = nil - for s.start = s.next; s.next < len(s.b); { - i := bytes.IndexByte(s.b[s.next:], '-') - if i == -1 { - s.end = len(s.b) - s.next = len(s.b) - i = s.end - s.start - } else { - s.end = s.next + i - s.next = s.end + 1 - } - token := s.b[s.start:s.end] - if i < 1 || i > 8 || !isAlphaNum(token) { - s.gobble(ErrSyntax) - continue - } - s.token = token - return end - } - if n := len(s.b); n > 0 && s.b[n-1] == '-' { - s.setError(ErrSyntax) - s.b = s.b[:len(s.b)-1] - } - s.done = true - return end -} - -// acceptMinSize parses multiple tokens of the given size or greater. -// It returns the end position of the last token consumed. -func (s *scanner) acceptMinSize(min int) (end int) { - end = s.end - s.scan() - for ; len(s.token) >= min; s.scan() { - end = s.end - } - return end -} - -// Parse parses the given BCP 47 string and returns a valid Tag. If parsing -// failed it returns an error and any part of the tag that could be parsed. -// If parsing succeeded but an unknown value was found, it returns -// ValueError. The Tag returned in this case is just stripped of the unknown -// value. All other values are preserved. It accepts tags in the BCP 47 format -// and extensions to this standard defined in -// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. -func Parse(s string) (t Tag, err error) { - // TODO: consider supporting old-style locale key-value pairs. - if s == "" { - return Und, ErrSyntax - } - defer func() { - if recover() != nil { - t = Und - err = ErrSyntax - return - } - }() - if len(s) <= maxAltTaglen { - b := [maxAltTaglen]byte{} - for i, c := range s { - // Generating invalid UTF-8 is okay as it won't match. - if 'A' <= c && c <= 'Z' { - c += 'a' - 'A' - } else if c == '_' { - c = '-' - } - b[i] = byte(c) - } - if t, ok := grandfathered(b); ok { - return t, nil - } - } - scan := makeScannerString(s) - return parse(&scan, s) -} - -func parse(scan *scanner, s string) (t Tag, err error) { - t = Und - var end int - if n := len(scan.token); n <= 1 { - scan.toLower(0, len(scan.b)) - if n == 0 || scan.token[0] != 'x' { - return t, ErrSyntax - } - end = parseExtensions(scan) - } else if n >= 4 { - return Und, ErrSyntax - } else { // the usual case - t, end = parseTag(scan, true) - if n := len(scan.token); n == 1 { - t.pExt = uint16(end) - end = parseExtensions(scan) - } else if end < len(scan.b) { - scan.setError(ErrSyntax) - scan.b = scan.b[:end] - } - } - if int(t.pVariant) < len(scan.b) { - if end < len(s) { - s = s[:end] - } - if len(s) > 0 && tag.Compare(s, scan.b) == 0 { - t.str = s - } else { - t.str = string(scan.b) - } - } else { - t.pVariant, t.pExt = 0, 0 - } - return t, scan.err -} - -// parseTag parses language, script, region and variants. -// It returns a Tag and the end position in the input that was parsed. -// If doNorm is true, then <lang>-<extlang> will be normalized to <extlang>. -func parseTag(scan *scanner, doNorm bool) (t Tag, end int) { - var e error - // TODO: set an error if an unknown lang, script or region is encountered. - t.LangID, e = getLangID(scan.token) - scan.setError(e) - scan.replace(t.LangID.String()) - langStart := scan.start - end = scan.scan() - for len(scan.token) == 3 && isAlpha(scan.token[0]) { - // From http://tools.ietf.org/html/bcp47, <lang>-<extlang> tags are equivalent - // to a tag of the form <extlang>. - if doNorm { - lang, e := getLangID(scan.token) - if lang != 0 { - t.LangID = lang - langStr := lang.String() - copy(scan.b[langStart:], langStr) - scan.b[langStart+len(langStr)] = '-' - scan.start = langStart + len(langStr) + 1 - } - scan.gobble(e) - } - end = scan.scan() - } - if len(scan.token) == 4 && isAlpha(scan.token[0]) { - t.ScriptID, e = getScriptID(script, scan.token) - if t.ScriptID == 0 { - scan.gobble(e) - } - end = scan.scan() - } - if n := len(scan.token); n >= 2 && n <= 3 { - t.RegionID, e = getRegionID(scan.token) - if t.RegionID == 0 { - scan.gobble(e) - } else { - scan.replace(t.RegionID.String()) - } - end = scan.scan() - } - scan.toLower(scan.start, len(scan.b)) - t.pVariant = byte(end) - end = parseVariants(scan, end, t) - t.pExt = uint16(end) - return t, end -} - -var separator = []byte{'-'} - -// parseVariants scans tokens as long as each token is a valid variant string. -// Duplicate variants are removed. -func parseVariants(scan *scanner, end int, t Tag) int { - start := scan.start - varIDBuf := [4]uint8{} - variantBuf := [4][]byte{} - varID := varIDBuf[:0] - variant := variantBuf[:0] - last := -1 - needSort := false - for ; len(scan.token) >= 4; scan.scan() { - // TODO: measure the impact of needing this conversion and redesign - // the data structure if there is an issue. - v, ok := variantIndex[string(scan.token)] - if !ok { - // unknown variant - // TODO: allow user-defined variants? - scan.gobble(NewValueError(scan.token)) - continue - } - varID = append(varID, v) - variant = append(variant, scan.token) - if !needSort { - if last < int(v) { - last = int(v) - } else { - needSort = true - // There is no legal combinations of more than 7 variants - // (and this is by no means a useful sequence). - const maxVariants = 8 - if len(varID) > maxVariants { - break - } - } - } - end = scan.end - } - if needSort { - sort.Sort(variantsSort{varID, variant}) - k, l := 0, -1 - for i, v := range varID { - w := int(v) - if l == w { - // Remove duplicates. - continue - } - varID[k] = varID[i] - variant[k] = variant[i] - k++ - l = w - } - if str := bytes.Join(variant[:k], separator); len(str) == 0 { - end = start - 1 - } else { - scan.resizeRange(start, end, len(str)) - copy(scan.b[scan.start:], str) - end = scan.end - } - } - return end -} - -type variantsSort struct { - i []uint8 - v [][]byte -} - -func (s variantsSort) Len() int { - return len(s.i) -} - -func (s variantsSort) Swap(i, j int) { - s.i[i], s.i[j] = s.i[j], s.i[i] - s.v[i], s.v[j] = s.v[j], s.v[i] -} - -func (s variantsSort) Less(i, j int) bool { - return s.i[i] < s.i[j] -} - -type bytesSort struct { - b [][]byte - n int // first n bytes to compare -} - -func (b bytesSort) Len() int { - return len(b.b) -} - -func (b bytesSort) Swap(i, j int) { - b.b[i], b.b[j] = b.b[j], b.b[i] -} - -func (b bytesSort) Less(i, j int) bool { - for k := 0; k < b.n; k++ { - if b.b[i][k] == b.b[j][k] { - continue - } - return b.b[i][k] < b.b[j][k] - } - return false -} - -// parseExtensions parses and normalizes the extensions in the buffer. -// It returns the last position of scan.b that is part of any extension. -// It also trims scan.b to remove excess parts accordingly. -func parseExtensions(scan *scanner) int { - start := scan.start - exts := [][]byte{} - private := []byte{} - end := scan.end - for len(scan.token) == 1 { - extStart := scan.start - ext := scan.token[0] - end = parseExtension(scan) - extension := scan.b[extStart:end] - if len(extension) < 3 || (ext != 'x' && len(extension) < 4) { - scan.setError(ErrSyntax) - end = extStart - continue - } else if start == extStart && (ext == 'x' || scan.start == len(scan.b)) { - scan.b = scan.b[:end] - return end - } else if ext == 'x' { - private = extension - break - } - exts = append(exts, extension) - } - sort.Sort(bytesSort{exts, 1}) - if len(private) > 0 { - exts = append(exts, private) - } - scan.b = scan.b[:start] - if len(exts) > 0 { - scan.b = append(scan.b, bytes.Join(exts, separator)...) - } else if start > 0 { - // Strip trailing '-'. - scan.b = scan.b[:start-1] - } - return end -} - -// parseExtension parses a single extension and returns the position of -// the extension end. -func parseExtension(scan *scanner) int { - start, end := scan.start, scan.end - switch scan.token[0] { - case 'u': // https://www.ietf.org/rfc/rfc6067.txt - attrStart := end - scan.scan() - for last := []byte{}; len(scan.token) > 2; scan.scan() { - if bytes.Compare(scan.token, last) != -1 { - // Attributes are unsorted. Start over from scratch. - p := attrStart + 1 - scan.next = p - attrs := [][]byte{} - for scan.scan(); len(scan.token) > 2; scan.scan() { - attrs = append(attrs, scan.token) - end = scan.end - } - sort.Sort(bytesSort{attrs, 3}) - copy(scan.b[p:], bytes.Join(attrs, separator)) - break - } - last = scan.token - end = scan.end - } - // Scan key-type sequences. A key is of length 2 and may be followed - // by 0 or more "type" subtags from 3 to the maximum of 8 letters. - var last, key []byte - for attrEnd := end; len(scan.token) == 2; last = key { - key = scan.token - end = scan.end - for scan.scan(); end < scan.end && len(scan.token) > 2; scan.scan() { - end = scan.end - } - // TODO: check key value validity - if bytes.Compare(key, last) != 1 || scan.err != nil { - // We have an invalid key or the keys are not sorted. - // Start scanning keys from scratch and reorder. - p := attrEnd + 1 - scan.next = p - keys := [][]byte{} - for scan.scan(); len(scan.token) == 2; { - keyStart := scan.start - end = scan.end - for scan.scan(); end < scan.end && len(scan.token) > 2; scan.scan() { - end = scan.end - } - keys = append(keys, scan.b[keyStart:end]) - } - sort.Stable(bytesSort{keys, 2}) - if n := len(keys); n > 0 { - k := 0 - for i := 1; i < n; i++ { - if !bytes.Equal(keys[k][:2], keys[i][:2]) { - k++ - keys[k] = keys[i] - } else if !bytes.Equal(keys[k], keys[i]) { - scan.setError(ErrDuplicateKey) - } - } - keys = keys[:k+1] - } - reordered := bytes.Join(keys, separator) - if e := p + len(reordered); e < end { - scan.deleteRange(e, end) - end = e - } - copy(scan.b[p:], reordered) - break - } - } - case 't': // https://www.ietf.org/rfc/rfc6497.txt - scan.scan() - if n := len(scan.token); n >= 2 && n <= 3 && isAlpha(scan.token[1]) { - _, end = parseTag(scan, false) - scan.toLower(start, end) - } - for len(scan.token) == 2 && !isAlpha(scan.token[1]) { - end = scan.acceptMinSize(3) - } - case 'x': - end = scan.acceptMinSize(1) - default: - end = scan.acceptMinSize(2) - } - return end -} - -// getExtension returns the name, body and end position of the extension. -func getExtension(s string, p int) (end int, ext string) { - if s[p] == '-' { - p++ - } - if s[p] == 'x' { - return len(s), s[p:] - } - end = nextExtension(s, p) - return end, s[p:end] -} - -// nextExtension finds the next extension within the string, searching -// for the -<char>- pattern from position p. -// In the fast majority of cases, language tags will have at most -// one extension and extensions tend to be small. -func nextExtension(s string, p int) int { - for n := len(s) - 3; p < n; { - if s[p] == '-' { - if s[p+2] == '-' { - return p - } - p += 3 - } else { - p++ - } - } - return len(s) -} diff --git a/vendor/golang.org/x/text/internal/language/tables.go b/vendor/golang.org/x/text/internal/language/tables.go deleted file mode 100644 index 14167e74..00000000 --- a/vendor/golang.org/x/text/internal/language/tables.go +++ /dev/null @@ -1,3494 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package language - -import "golang.org/x/text/internal/tag" - -// CLDRVersion is the CLDR version from which the tables in this package are derived. -const CLDRVersion = "32" - -const NumLanguages = 8798 - -const NumScripts = 261 - -const NumRegions = 358 - -type FromTo struct { - From uint16 - To uint16 -} - -const nonCanonicalUnd = 1201 -const ( - _af = 22 - _am = 39 - _ar = 58 - _az = 88 - _bg = 126 - _bn = 165 - _ca = 215 - _cs = 250 - _da = 257 - _de = 269 - _el = 310 - _en = 313 - _es = 318 - _et = 320 - _fa = 328 - _fi = 337 - _fil = 339 - _fr = 350 - _gu = 420 - _he = 444 - _hi = 446 - _hr = 465 - _hu = 469 - _hy = 471 - _id = 481 - _is = 504 - _it = 505 - _ja = 512 - _ka = 528 - _kk = 578 - _km = 586 - _kn = 593 - _ko = 596 - _ky = 650 - _lo = 696 - _lt = 704 - _lv = 711 - _mk = 767 - _ml = 772 - _mn = 779 - _mo = 784 - _mr = 795 - _ms = 799 - _mul = 806 - _my = 817 - _nb = 839 - _ne = 849 - _nl = 871 - _no = 879 - _pa = 925 - _pl = 947 - _pt = 960 - _ro = 988 - _ru = 994 - _sh = 1031 - _si = 1036 - _sk = 1042 - _sl = 1046 - _sq = 1073 - _sr = 1074 - _sv = 1092 - _sw = 1093 - _ta = 1104 - _te = 1121 - _th = 1131 - _tl = 1146 - _tn = 1152 - _tr = 1162 - _uk = 1198 - _ur = 1204 - _uz = 1212 - _vi = 1219 - _zh = 1321 - _zu = 1327 - _jbo = 515 - _ami = 1650 - _bnn = 2357 - _hak = 438 - _tlh = 14467 - _lb = 661 - _nv = 899 - _pwn = 12055 - _tao = 14188 - _tay = 14198 - _tsu = 14662 - _nn = 874 - _sfb = 13629 - _vgt = 15701 - _sgg = 13660 - _cmn = 3007 - _nan = 835 - _hsn = 467 -) - -const langPrivateStart = 0x2f72 - -const langPrivateEnd = 0x3179 - -// lang holds an alphabetically sorted list of ISO-639 language identifiers. -// All entries are 4 bytes. The index of the identifier (divided by 4) is the language tag. -// For 2-byte language identifiers, the two successive bytes have the following meaning: -// - if the first letter of the 2- and 3-letter ISO codes are the same: -// the second and third letter of the 3-letter ISO code. -// - otherwise: a 0 and a by 2 bits right-shifted index into altLangISO3. -// -// For 3-byte language identifiers the 4th byte is 0. -const lang tag.Index = "" + // Size: 5324 bytes - "---\x00aaaraai\x00aak\x00aau\x00abbkabi\x00abq\x00abr\x00abt\x00aby\x00a" + - "cd\x00ace\x00ach\x00ada\x00ade\x00adj\x00ady\x00adz\x00aeveaeb\x00aey" + - "\x00affragc\x00agd\x00agg\x00agm\x00ago\x00agq\x00aha\x00ahl\x00aho\x00a" + - "jg\x00akkaakk\x00ala\x00ali\x00aln\x00alt\x00ammhamm\x00amn\x00amo\x00am" + - "p\x00anrganc\x00ank\x00ann\x00any\x00aoj\x00aom\x00aoz\x00apc\x00apd\x00" + - "ape\x00apr\x00aps\x00apz\x00arraarc\x00arh\x00arn\x00aro\x00arq\x00ars" + - "\x00ary\x00arz\x00assmasa\x00ase\x00asg\x00aso\x00ast\x00ata\x00atg\x00a" + - "tj\x00auy\x00avvaavl\x00avn\x00avt\x00avu\x00awa\x00awb\x00awo\x00awx" + - "\x00ayymayb\x00azzebaakbal\x00ban\x00bap\x00bar\x00bas\x00bav\x00bax\x00" + - "bba\x00bbb\x00bbc\x00bbd\x00bbj\x00bbp\x00bbr\x00bcf\x00bch\x00bci\x00bc" + - "m\x00bcn\x00bco\x00bcq\x00bcu\x00bdd\x00beelbef\x00beh\x00bej\x00bem\x00" + - "bet\x00bew\x00bex\x00bez\x00bfd\x00bfq\x00bft\x00bfy\x00bgulbgc\x00bgn" + - "\x00bgx\x00bhihbhb\x00bhg\x00bhi\x00bhk\x00bhl\x00bho\x00bhy\x00biisbib" + - "\x00big\x00bik\x00bim\x00bin\x00bio\x00biq\x00bjh\x00bji\x00bjj\x00bjn" + - "\x00bjo\x00bjr\x00bjt\x00bjz\x00bkc\x00bkm\x00bkq\x00bku\x00bkv\x00blt" + - "\x00bmambmh\x00bmk\x00bmq\x00bmu\x00bnenbng\x00bnm\x00bnp\x00boodboj\x00" + - "bom\x00bon\x00bpy\x00bqc\x00bqi\x00bqp\x00bqv\x00brrebra\x00brh\x00brx" + - "\x00brz\x00bsosbsj\x00bsq\x00bss\x00bst\x00bto\x00btt\x00btv\x00bua\x00b" + - "uc\x00bud\x00bug\x00buk\x00bum\x00buo\x00bus\x00buu\x00bvb\x00bwd\x00bwr" + - "\x00bxh\x00bye\x00byn\x00byr\x00bys\x00byv\x00byx\x00bza\x00bze\x00bzf" + - "\x00bzh\x00bzw\x00caatcan\x00cbj\x00cch\x00ccp\x00ceheceb\x00cfa\x00cgg" + - "\x00chhachk\x00chm\x00cho\x00chp\x00chr\x00cja\x00cjm\x00cjv\x00ckb\x00c" + - "kl\x00cko\x00cky\x00cla\x00cme\x00cmg\x00cooscop\x00cps\x00crrecrh\x00cr" + - "j\x00crk\x00crl\x00crm\x00crs\x00csescsb\x00csw\x00ctd\x00cuhucvhvcyymda" + - "andad\x00daf\x00dag\x00dah\x00dak\x00dar\x00dav\x00dbd\x00dbq\x00dcc\x00" + - "ddn\x00deeuded\x00den\x00dga\x00dgh\x00dgi\x00dgl\x00dgr\x00dgz\x00dia" + - "\x00dje\x00dnj\x00dob\x00doi\x00dop\x00dow\x00dri\x00drs\x00dsb\x00dtm" + - "\x00dtp\x00dts\x00dty\x00dua\x00duc\x00dud\x00dug\x00dvivdva\x00dww\x00d" + - "yo\x00dyu\x00dzzodzg\x00ebu\x00eeweefi\x00egl\x00egy\x00eka\x00eky\x00el" + - "llema\x00emi\x00enngenn\x00enq\x00eopoeri\x00es\x00\x05esu\x00etstetr" + - "\x00ett\x00etu\x00etx\x00euusewo\x00ext\x00faasfaa\x00fab\x00fag\x00fai" + - "\x00fan\x00ffulffi\x00ffm\x00fiinfia\x00fil\x00fit\x00fjijflr\x00fmp\x00" + - "foaofod\x00fon\x00for\x00fpe\x00fqs\x00frrafrc\x00frp\x00frr\x00frs\x00f" + - "ub\x00fud\x00fue\x00fuf\x00fuh\x00fuq\x00fur\x00fuv\x00fuy\x00fvr\x00fyr" + - "ygalegaa\x00gaf\x00gag\x00gah\x00gaj\x00gam\x00gan\x00gaw\x00gay\x00gba" + - "\x00gbf\x00gbm\x00gby\x00gbz\x00gcr\x00gdlagde\x00gdn\x00gdr\x00geb\x00g" + - "ej\x00gel\x00gez\x00gfk\x00ggn\x00ghs\x00gil\x00gim\x00gjk\x00gjn\x00gju" + - "\x00gkn\x00gkp\x00gllgglk\x00gmm\x00gmv\x00gnrngnd\x00gng\x00god\x00gof" + - "\x00goi\x00gom\x00gon\x00gor\x00gos\x00got\x00grb\x00grc\x00grt\x00grw" + - "\x00gsw\x00guujgub\x00guc\x00gud\x00gur\x00guw\x00gux\x00guz\x00gvlvgvf" + - "\x00gvr\x00gvs\x00gwc\x00gwi\x00gwt\x00gyi\x00haauhag\x00hak\x00ham\x00h" + - "aw\x00haz\x00hbb\x00hdy\x00heebhhy\x00hiinhia\x00hif\x00hig\x00hih\x00hi" + - "l\x00hla\x00hlu\x00hmd\x00hmt\x00hnd\x00hne\x00hnj\x00hnn\x00hno\x00homo" + - "hoc\x00hoj\x00hot\x00hrrvhsb\x00hsn\x00htathuunhui\x00hyyehzerianaian" + - "\x00iar\x00iba\x00ibb\x00iby\x00ica\x00ich\x00idndidd\x00idi\x00idu\x00i" + - "eleife\x00igboigb\x00ige\x00iiiiijj\x00ikpkikk\x00ikt\x00ikw\x00ikx\x00i" + - "lo\x00imo\x00inndinh\x00iodoiou\x00iri\x00isslittaiukuiw\x00\x03iwm\x00i" + - "ws\x00izh\x00izi\x00japnjab\x00jam\x00jbo\x00jbu\x00jen\x00jgk\x00jgo" + - "\x00ji\x00\x06jib\x00jmc\x00jml\x00jra\x00jut\x00jvavjwavkaatkaa\x00kab" + - "\x00kac\x00kad\x00kai\x00kaj\x00kam\x00kao\x00kbd\x00kbm\x00kbp\x00kbq" + - "\x00kbx\x00kby\x00kcg\x00kck\x00kcl\x00kct\x00kde\x00kdh\x00kdl\x00kdt" + - "\x00kea\x00ken\x00kez\x00kfo\x00kfr\x00kfy\x00kgonkge\x00kgf\x00kgp\x00k" + - "ha\x00khb\x00khn\x00khq\x00khs\x00kht\x00khw\x00khz\x00kiikkij\x00kiu" + - "\x00kiw\x00kjuakjd\x00kjg\x00kjs\x00kjy\x00kkazkkc\x00kkj\x00klalkln\x00" + - "klq\x00klt\x00klx\x00kmhmkmb\x00kmh\x00kmo\x00kms\x00kmu\x00kmw\x00knank" + - "nf\x00knp\x00koorkoi\x00kok\x00kol\x00kos\x00koz\x00kpe\x00kpf\x00kpo" + - "\x00kpr\x00kpx\x00kqb\x00kqf\x00kqs\x00kqy\x00kraukrc\x00kri\x00krj\x00k" + - "rl\x00krs\x00kru\x00ksasksb\x00ksd\x00ksf\x00ksh\x00ksj\x00ksr\x00ktb" + - "\x00ktm\x00kto\x00kuurkub\x00kud\x00kue\x00kuj\x00kum\x00kun\x00kup\x00k" + - "us\x00kvomkvg\x00kvr\x00kvx\x00kw\x00\x01kwj\x00kwo\x00kxa\x00kxc\x00kxm" + - "\x00kxp\x00kxw\x00kxz\x00kyirkye\x00kyx\x00kzr\x00laatlab\x00lad\x00lag" + - "\x00lah\x00laj\x00las\x00lbtzlbe\x00lbu\x00lbw\x00lcm\x00lcp\x00ldb\x00l" + - "ed\x00lee\x00lem\x00lep\x00leq\x00leu\x00lez\x00lguglgg\x00liimlia\x00li" + - "d\x00lif\x00lig\x00lih\x00lij\x00lis\x00ljp\x00lki\x00lkt\x00lle\x00lln" + - "\x00lmn\x00lmo\x00lmp\x00lninlns\x00lnu\x00loaoloj\x00lok\x00lol\x00lor" + - "\x00los\x00loz\x00lrc\x00ltitltg\x00luublua\x00luo\x00luy\x00luz\x00lvav" + - "lwl\x00lzh\x00lzz\x00mad\x00maf\x00mag\x00mai\x00mak\x00man\x00mas\x00ma" + - "w\x00maz\x00mbh\x00mbo\x00mbq\x00mbu\x00mbw\x00mci\x00mcp\x00mcq\x00mcr" + - "\x00mcu\x00mda\x00mde\x00mdf\x00mdh\x00mdj\x00mdr\x00mdx\x00med\x00mee" + - "\x00mek\x00men\x00mer\x00met\x00meu\x00mfa\x00mfe\x00mfn\x00mfo\x00mfq" + - "\x00mglgmgh\x00mgl\x00mgo\x00mgp\x00mgy\x00mhahmhi\x00mhl\x00mirimif\x00" + - "min\x00mis\x00miw\x00mkkdmki\x00mkl\x00mkp\x00mkw\x00mlalmle\x00mlp\x00m" + - "ls\x00mmo\x00mmu\x00mmx\x00mnonmna\x00mnf\x00mni\x00mnw\x00moolmoa\x00mo" + - "e\x00moh\x00mos\x00mox\x00mpp\x00mps\x00mpt\x00mpx\x00mql\x00mrarmrd\x00" + - "mrj\x00mro\x00mssamtltmtc\x00mtf\x00mti\x00mtr\x00mua\x00mul\x00mur\x00m" + - "us\x00mva\x00mvn\x00mvy\x00mwk\x00mwr\x00mwv\x00mxc\x00mxm\x00myyamyk" + - "\x00mym\x00myv\x00myw\x00myx\x00myz\x00mzk\x00mzm\x00mzn\x00mzp\x00mzw" + - "\x00mzz\x00naaunac\x00naf\x00nah\x00nak\x00nan\x00nap\x00naq\x00nas\x00n" + - "bobnca\x00nce\x00ncf\x00nch\x00nco\x00ncu\x00nddendc\x00nds\x00neepneb" + - "\x00new\x00nex\x00nfr\x00ngdonga\x00ngb\x00ngl\x00nhb\x00nhe\x00nhw\x00n" + - "if\x00nii\x00nij\x00nin\x00niu\x00niy\x00niz\x00njo\x00nkg\x00nko\x00nll" + - "dnmg\x00nmz\x00nnnonnf\x00nnh\x00nnk\x00nnm\x00noornod\x00noe\x00non\x00" + - "nop\x00nou\x00nqo\x00nrblnrb\x00nsk\x00nsn\x00nso\x00nss\x00ntm\x00ntr" + - "\x00nui\x00nup\x00nus\x00nuv\x00nux\x00nvavnwb\x00nxq\x00nxr\x00nyyanym" + - "\x00nyn\x00nzi\x00occiogc\x00ojjiokr\x00okv\x00omrmong\x00onn\x00ons\x00" + - "opm\x00orrioro\x00oru\x00osssosa\x00ota\x00otk\x00ozm\x00paanpag\x00pal" + - "\x00pam\x00pap\x00pau\x00pbi\x00pcd\x00pcm\x00pdc\x00pdt\x00ped\x00peo" + - "\x00pex\x00pfl\x00phl\x00phn\x00pilipil\x00pip\x00pka\x00pko\x00plolpla" + - "\x00pms\x00png\x00pnn\x00pnt\x00pon\x00ppo\x00pra\x00prd\x00prg\x00psusp" + - "ss\x00ptorptp\x00puu\x00pwa\x00quuequc\x00qug\x00rai\x00raj\x00rao\x00rc" + - "f\x00rej\x00rel\x00res\x00rgn\x00rhg\x00ria\x00rif\x00rjs\x00rkt\x00rmoh" + - "rmf\x00rmo\x00rmt\x00rmu\x00rnunrna\x00rng\x00roonrob\x00rof\x00roo\x00r" + - "ro\x00rtm\x00ruusrue\x00rug\x00rw\x00\x04rwk\x00rwo\x00ryu\x00saansaf" + - "\x00sah\x00saq\x00sas\x00sat\x00sav\x00saz\x00sba\x00sbe\x00sbp\x00scrds" + - "ck\x00scl\x00scn\x00sco\x00scs\x00sdndsdc\x00sdh\x00semesef\x00seh\x00se" + - "i\x00ses\x00sgagsga\x00sgs\x00sgw\x00sgz\x00sh\x00\x02shi\x00shk\x00shn" + - "\x00shu\x00siinsid\x00sig\x00sil\x00sim\x00sjr\x00sklkskc\x00skr\x00sks" + - "\x00sllvsld\x00sli\x00sll\x00sly\x00smmosma\x00smi\x00smj\x00smn\x00smp" + - "\x00smq\x00sms\x00snnasnc\x00snk\x00snp\x00snx\x00sny\x00soomsok\x00soq" + - "\x00sou\x00soy\x00spd\x00spl\x00sps\x00sqqisrrpsrb\x00srn\x00srr\x00srx" + - "\x00ssswssd\x00ssg\x00ssy\x00stotstk\x00stq\x00suunsua\x00sue\x00suk\x00" + - "sur\x00sus\x00svweswwaswb\x00swc\x00swg\x00swp\x00swv\x00sxn\x00sxw\x00s" + - "yl\x00syr\x00szl\x00taamtaj\x00tal\x00tan\x00taq\x00tbc\x00tbd\x00tbf" + - "\x00tbg\x00tbo\x00tbw\x00tbz\x00tci\x00tcy\x00tdd\x00tdg\x00tdh\x00teelt" + - "ed\x00tem\x00teo\x00tet\x00tfi\x00tggktgc\x00tgo\x00tgu\x00thhathl\x00th" + - "q\x00thr\x00tiirtif\x00tig\x00tik\x00tim\x00tio\x00tiv\x00tkuktkl\x00tkr" + - "\x00tkt\x00tlgltlf\x00tlx\x00tly\x00tmh\x00tmy\x00tnsntnh\x00toontof\x00" + - "tog\x00toq\x00tpi\x00tpm\x00tpz\x00tqo\x00trurtru\x00trv\x00trw\x00tssot" + - "sd\x00tsf\x00tsg\x00tsj\x00tsw\x00ttatttd\x00tte\x00ttj\x00ttr\x00tts" + - "\x00ttt\x00tuh\x00tul\x00tum\x00tuq\x00tvd\x00tvl\x00tvu\x00twwitwh\x00t" + - "wq\x00txg\x00tyahtya\x00tyv\x00tzm\x00ubu\x00udm\x00ugiguga\x00ukkruli" + - "\x00umb\x00und\x00unr\x00unx\x00urrduri\x00urt\x00urw\x00usa\x00utr\x00u" + - "vh\x00uvl\x00uzzbvag\x00vai\x00van\x00veenvec\x00vep\x00viievic\x00viv" + - "\x00vls\x00vmf\x00vmw\x00voolvot\x00vro\x00vun\x00vut\x00walnwae\x00waj" + - "\x00wal\x00wan\x00war\x00wbp\x00wbq\x00wbr\x00wci\x00wer\x00wgi\x00whg" + - "\x00wib\x00wiu\x00wiv\x00wja\x00wji\x00wls\x00wmo\x00wnc\x00wni\x00wnu" + - "\x00woolwob\x00wos\x00wrs\x00wsk\x00wtm\x00wuu\x00wuv\x00wwa\x00xav\x00x" + - "bi\x00xcr\x00xes\x00xhhoxla\x00xlc\x00xld\x00xmf\x00xmn\x00xmr\x00xna" + - "\x00xnr\x00xog\x00xon\x00xpr\x00xrb\x00xsa\x00xsi\x00xsm\x00xsr\x00xwe" + - "\x00yam\x00yao\x00yap\x00yas\x00yat\x00yav\x00yay\x00yaz\x00yba\x00ybb" + - "\x00yby\x00yer\x00ygr\x00ygw\x00yiidyko\x00yle\x00ylg\x00yll\x00yml\x00y" + - "ooryon\x00yrb\x00yre\x00yrl\x00yss\x00yua\x00yue\x00yuj\x00yut\x00yuw" + - "\x00zahazag\x00zbl\x00zdj\x00zea\x00zgh\x00zhhozhx\x00zia\x00zlm\x00zmi" + - "\x00zne\x00zuulzxx\x00zza\x00\xff\xff\xff\xff" - -const langNoIndexOffset = 1330 - -// langNoIndex is a bit vector of all 3-letter language codes that are not used as an index -// in lookup tables. The language ids for these language codes are derived directly -// from the letters and are not consecutive. -// Size: 2197 bytes, 2197 elements -var langNoIndex = [2197]uint8{ - // Entry 0 - 3F - 0xff, 0xf8, 0xed, 0xfe, 0xeb, 0xd3, 0x3b, 0xd2, - 0xfb, 0xbf, 0x7a, 0xfa, 0x37, 0x1d, 0x3c, 0x57, - 0x6e, 0x97, 0x73, 0x38, 0xfb, 0xea, 0xbf, 0x70, - 0xad, 0x03, 0xff, 0xff, 0xcf, 0x05, 0x84, 0x72, - 0xe9, 0xbf, 0xfd, 0xbf, 0xbf, 0xf7, 0xfd, 0x77, - 0x0f, 0xff, 0xef, 0x6f, 0xff, 0xfb, 0xdf, 0xe2, - 0xc9, 0xf8, 0x7f, 0x7e, 0x4d, 0xbc, 0x0a, 0x6a, - 0x7c, 0xea, 0xe3, 0xfa, 0x7a, 0xbf, 0x67, 0xff, - // Entry 40 - 7F - 0xff, 0xff, 0xff, 0xdf, 0x2a, 0x54, 0x91, 0xc0, - 0x5d, 0xe3, 0x97, 0x14, 0x07, 0x20, 0xdd, 0xed, - 0x9f, 0x3f, 0xc9, 0x21, 0xf8, 0x3f, 0x94, 0x35, - 0x7c, 0x5f, 0xff, 0x5f, 0x8e, 0x6e, 0xdf, 0xff, - 0xff, 0xff, 0x55, 0x7c, 0xd3, 0xfd, 0xbf, 0xb5, - 0x7b, 0xdf, 0x7f, 0xf7, 0xca, 0xfe, 0xdb, 0xa3, - 0xa8, 0xff, 0x1f, 0x67, 0x7d, 0xeb, 0xef, 0xce, - 0xff, 0xff, 0x9f, 0xff, 0xb7, 0xef, 0xfe, 0xcf, - // Entry 80 - BF - 0xdb, 0xff, 0xf3, 0xcd, 0xfb, 0x7f, 0xff, 0xff, - 0xbb, 0xee, 0xf7, 0xbd, 0xdb, 0xff, 0x5f, 0xf7, - 0xfd, 0xf2, 0xfd, 0xff, 0x5e, 0x2f, 0x3b, 0xba, - 0x7e, 0xff, 0xff, 0xfe, 0xf7, 0xff, 0xdd, 0xff, - 0xfd, 0xdf, 0xfb, 0xfe, 0x9d, 0xb4, 0xd3, 0xff, - 0xef, 0xff, 0xdf, 0xf7, 0x7f, 0xb7, 0xfd, 0xd5, - 0xa5, 0x77, 0x40, 0xff, 0x9c, 0xc1, 0x41, 0x2c, - 0x08, 0x21, 0x41, 0x00, 0x50, 0x40, 0x00, 0x80, - // Entry C0 - FF - 0xfb, 0x4a, 0xf2, 0x9f, 0xb4, 0x42, 0x41, 0x96, - 0x1b, 0x14, 0x08, 0xf3, 0x2b, 0xe7, 0x17, 0x56, - 0x05, 0x7d, 0x0e, 0x1c, 0x37, 0x7f, 0xf3, 0xef, - 0x97, 0xff, 0x5d, 0x38, 0x64, 0x08, 0x00, 0x10, - 0xbc, 0x85, 0xaf, 0xdf, 0xff, 0xff, 0x7b, 0x35, - 0x3e, 0xc7, 0xc7, 0xdf, 0xff, 0x01, 0x81, 0x00, - 0xb0, 0x05, 0x80, 0x00, 0x20, 0x00, 0x00, 0x03, - 0x40, 0x00, 0x40, 0x92, 0x21, 0x50, 0xb1, 0x5d, - // Entry 100 - 13F - 0xfd, 0xdc, 0xbe, 0x5e, 0x00, 0x00, 0x02, 0x64, - 0x0d, 0x19, 0x41, 0xdf, 0x79, 0x22, 0x00, 0x00, - 0x00, 0x5e, 0x64, 0xdc, 0x24, 0xe5, 0xd9, 0xe3, - 0xfe, 0xff, 0xfd, 0xcb, 0x9f, 0x14, 0x41, 0x0c, - 0x86, 0x00, 0xd1, 0x00, 0xf0, 0xc7, 0x67, 0x5f, - 0x56, 0x99, 0x5e, 0xb5, 0x6c, 0xaf, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xc0, 0x37, 0xda, 0x56, - 0x90, 0x6d, 0x01, 0x2e, 0x96, 0x69, 0x20, 0xfb, - // Entry 140 - 17F - 0xff, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x16, - 0x03, 0x00, 0x00, 0xb0, 0x14, 0x23, 0x50, 0x06, - 0x0a, 0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x09, - 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x44, 0x00, 0x00, 0x10, 0x00, 0x05, - 0x08, 0x00, 0x00, 0x05, 0x00, 0x80, 0x28, 0x04, - 0x00, 0x00, 0x40, 0xd5, 0x2d, 0x00, 0x64, 0x35, - 0x24, 0x52, 0xf4, 0xd5, 0xbf, 0x62, 0xc9, 0x03, - // Entry 180 - 1BF - 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x13, 0x39, 0x01, 0xdd, 0x57, 0x98, - 0x21, 0x18, 0x81, 0x08, 0x00, 0x01, 0x40, 0x82, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x40, 0x00, 0x44, 0x00, 0x00, 0x80, 0xea, - 0xa9, 0x39, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - // Entry 1C0 - 1FF - 0x00, 0x03, 0x28, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x20, 0x04, 0xa6, 0x00, 0x04, 0x00, 0x00, - 0x81, 0x50, 0x00, 0x00, 0x00, 0x11, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x55, - 0x02, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x40, - 0x30, 0x83, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1e, 0xcd, 0xbf, 0x7a, 0xbf, - // Entry 200 - 23F - 0xdf, 0xc3, 0x83, 0x82, 0xc0, 0xfb, 0x57, 0x27, - 0xed, 0x55, 0xe7, 0x01, 0x00, 0x20, 0xb2, 0xc5, - 0xa4, 0x45, 0x25, 0x9b, 0x02, 0xdf, 0xe1, 0xdf, - 0x03, 0x44, 0x08, 0x90, 0x01, 0x04, 0x81, 0xe3, - 0x92, 0x54, 0xdb, 0x28, 0xd3, 0x5f, 0xfe, 0x6d, - 0x79, 0xed, 0x1c, 0x7f, 0x04, 0x08, 0x00, 0x01, - 0x21, 0x12, 0x64, 0x5f, 0xdd, 0x0e, 0x85, 0x4f, - 0x40, 0x40, 0x00, 0x04, 0xf1, 0xfd, 0x3d, 0x54, - // Entry 240 - 27F - 0xe8, 0x03, 0xb4, 0x27, 0x23, 0x0d, 0x00, 0x00, - 0x20, 0x7b, 0x78, 0x02, 0x07, 0x84, 0x00, 0xf0, - 0xbb, 0x7e, 0x5a, 0x00, 0x18, 0x04, 0x81, 0x00, - 0x00, 0x00, 0x80, 0x10, 0x90, 0x1c, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x04, - 0x08, 0xa0, 0x70, 0xa5, 0x0c, 0x40, 0x00, 0x00, - 0x91, 0x24, 0x04, 0x68, 0x00, 0x20, 0x70, 0xff, - 0x7b, 0x7f, 0x70, 0x00, 0x05, 0x9b, 0xdd, 0x66, - // Entry 280 - 2BF - 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x40, 0x05, - 0xb5, 0xb6, 0x80, 0x08, 0x04, 0x00, 0x04, 0x51, - 0xe2, 0xef, 0xfd, 0x3f, 0x05, 0x09, 0x08, 0x05, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x60, - 0xe7, 0x48, 0x00, 0x81, 0x20, 0xc0, 0x05, 0x80, - 0x03, 0x00, 0x00, 0x00, 0x8c, 0x50, 0x40, 0x04, - 0x84, 0x47, 0x84, 0x40, 0x20, 0x10, 0x00, 0x20, - // Entry 2C0 - 2FF - 0x02, 0x50, 0x80, 0x11, 0x00, 0x99, 0x6c, 0xe2, - 0x50, 0x27, 0x1d, 0x11, 0x29, 0x0e, 0x59, 0xe9, - 0x33, 0x08, 0x00, 0x20, 0x04, 0x40, 0x10, 0x00, - 0x00, 0x00, 0x50, 0x44, 0x92, 0x49, 0xd6, 0x5d, - 0xa7, 0x81, 0x47, 0x97, 0xfb, 0x00, 0x10, 0x00, - 0x08, 0x00, 0x80, 0x00, 0x40, 0x04, 0x00, 0x01, - 0x02, 0x00, 0x01, 0x40, 0x80, 0x00, 0x40, 0x08, - 0xd8, 0xeb, 0xf6, 0x39, 0xc4, 0x8d, 0x12, 0x00, - // Entry 300 - 33F - 0x00, 0x0c, 0x04, 0x01, 0x20, 0x20, 0xdd, 0xa0, - 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x04, 0x10, 0xd0, 0x9d, 0x95, 0x13, 0x04, 0x80, - 0x00, 0x01, 0xd0, 0x16, 0x40, 0x00, 0x10, 0xb0, - 0x10, 0x62, 0x4c, 0xd2, 0x02, 0x01, 0x4a, 0x00, - 0x46, 0x04, 0x00, 0x08, 0x02, 0x00, 0x20, 0x80, - 0x00, 0x80, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0xd8, 0x6f, 0x15, 0x02, 0x08, 0x00, - // Entry 340 - 37F - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, - 0x00, 0x10, 0x00, 0x00, 0x00, 0xf0, 0x84, 0xe3, - 0xdd, 0xbf, 0xf9, 0xf9, 0x3b, 0x7f, 0x7f, 0xdb, - 0xfd, 0xfc, 0xfe, 0xdf, 0xff, 0xfd, 0xff, 0xf6, - 0xfb, 0xfc, 0xf7, 0x1f, 0xff, 0xb3, 0x6c, 0xff, - 0xd9, 0xad, 0xdf, 0xfe, 0xef, 0xba, 0xdf, 0xff, - 0xff, 0xff, 0xb7, 0xdd, 0x7d, 0xbf, 0xab, 0x7f, - 0xfd, 0xfd, 0xdf, 0x2f, 0x9c, 0xdf, 0xf3, 0x6f, - // Entry 380 - 3BF - 0xdf, 0xdd, 0xff, 0xfb, 0xee, 0xd2, 0xab, 0x5f, - 0xd5, 0xdf, 0x7f, 0xff, 0xeb, 0xff, 0xe4, 0x4d, - 0xf9, 0xff, 0xfe, 0xf7, 0xfd, 0xdf, 0xfb, 0xbf, - 0xee, 0xdb, 0x6f, 0xef, 0xff, 0x7f, 0xff, 0xff, - 0xf7, 0x5f, 0xd3, 0x3b, 0xfd, 0xd9, 0xdf, 0xeb, - 0xbc, 0x08, 0x05, 0x24, 0xff, 0x07, 0x70, 0xfe, - 0xe6, 0x5e, 0x00, 0x08, 0x00, 0x83, 0x7d, 0x1f, - 0x06, 0xe6, 0x72, 0x60, 0xd1, 0x3c, 0x7f, 0x44, - // Entry 3C0 - 3FF - 0x02, 0x30, 0x9f, 0x7a, 0x16, 0xbd, 0x7f, 0x57, - 0xf2, 0xff, 0x31, 0xff, 0xf2, 0x1e, 0x90, 0xf7, - 0xf1, 0xf9, 0x45, 0x80, 0x01, 0x02, 0x00, 0x20, - 0x40, 0x54, 0x9f, 0x8a, 0xdf, 0xf9, 0x6e, 0x11, - 0x86, 0x51, 0xc0, 0xf3, 0xfb, 0x47, 0x40, 0x03, - 0x05, 0xd1, 0x50, 0x5c, 0x00, 0x40, 0x00, 0x10, - 0x04, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x17, 0xd2, - 0xb9, 0xfd, 0xfc, 0xba, 0xfe, 0xef, 0xc7, 0xbe, - // Entry 400 - 43F - 0x53, 0x6f, 0xdf, 0xe7, 0xdb, 0x65, 0xbb, 0x7f, - 0xfa, 0xff, 0x77, 0xf3, 0xef, 0xbf, 0xfd, 0xf7, - 0xdf, 0xdf, 0x9b, 0x7f, 0xff, 0xff, 0x7f, 0x6f, - 0xf7, 0xfb, 0xeb, 0xdf, 0xbc, 0xff, 0xbf, 0x6b, - 0x7b, 0xfb, 0xff, 0xce, 0x76, 0xbd, 0xf7, 0xf7, - 0xdf, 0xdc, 0xf7, 0xf7, 0xff, 0xdf, 0xf3, 0xfe, - 0xef, 0xff, 0xff, 0xff, 0xb6, 0x7f, 0x7f, 0xde, - 0xf7, 0xb9, 0xeb, 0x77, 0xff, 0xfb, 0xbf, 0xdf, - // Entry 440 - 47F - 0xfd, 0xfe, 0xfb, 0xff, 0xfe, 0xeb, 0x1f, 0x7d, - 0x2f, 0xfd, 0xb6, 0xb5, 0xa5, 0xfc, 0xff, 0xfd, - 0x7f, 0x4e, 0xbf, 0x8f, 0xae, 0xff, 0xee, 0xdf, - 0x7f, 0xf7, 0x73, 0x02, 0x02, 0x04, 0xfc, 0xf7, - 0xff, 0xb7, 0xd7, 0xef, 0xfe, 0xcd, 0xf5, 0xce, - 0xe2, 0x8e, 0xe7, 0xbf, 0xb7, 0xff, 0x56, 0xfd, - 0xcd, 0xff, 0xfb, 0xff, 0xdf, 0xd7, 0xea, 0xff, - 0xe5, 0x5f, 0x6d, 0x0f, 0xa7, 0x51, 0x06, 0xc4, - // Entry 480 - 4BF - 0x93, 0x50, 0x5d, 0xaf, 0xa6, 0xff, 0x99, 0xfb, - 0x63, 0x1d, 0x53, 0xff, 0xef, 0xb7, 0x35, 0x20, - 0x14, 0x00, 0x55, 0x51, 0xc2, 0x65, 0xf5, 0x41, - 0xe2, 0xff, 0xfc, 0xdf, 0x02, 0x85, 0xc5, 0x05, - 0x00, 0x22, 0x00, 0x74, 0x69, 0x10, 0x08, 0x05, - 0x41, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x51, 0x20, 0x05, 0x04, 0x01, 0x00, 0x00, - 0x06, 0x11, 0x20, 0x00, 0x18, 0x01, 0x92, 0xf1, - // Entry 4C0 - 4FF - 0xfd, 0x47, 0x69, 0x06, 0x95, 0x06, 0x57, 0xed, - 0xfb, 0x4d, 0x1c, 0x6b, 0x83, 0x04, 0x62, 0x40, - 0x00, 0x11, 0x42, 0x00, 0x00, 0x00, 0x54, 0x83, - 0xb8, 0x4f, 0x10, 0x8e, 0x89, 0x46, 0xde, 0xf7, - 0x13, 0x31, 0x00, 0x20, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x00, - 0x01, 0x00, 0x00, 0xf0, 0x5b, 0xf4, 0xbe, 0x3d, - 0xbe, 0xcf, 0xf7, 0xaf, 0x42, 0x04, 0x84, 0x41, - // Entry 500 - 53F - 0x30, 0xff, 0x79, 0x72, 0x04, 0x00, 0x00, 0x49, - 0x2d, 0x14, 0x27, 0x5f, 0xed, 0xf1, 0x3f, 0xe7, - 0x3f, 0x00, 0x00, 0x02, 0xc6, 0xa0, 0x1e, 0xf8, - 0xbb, 0xff, 0xfd, 0xfb, 0xb7, 0xfd, 0xe7, 0xf7, - 0xfd, 0xfc, 0xd5, 0xed, 0x47, 0xf4, 0x7e, 0x10, - 0x01, 0x01, 0x84, 0x6d, 0xff, 0xf7, 0xdd, 0xf9, - 0x5b, 0x05, 0x86, 0xed, 0xf5, 0x77, 0xbd, 0x3c, - 0x00, 0x00, 0x00, 0x42, 0x71, 0x42, 0x00, 0x40, - // Entry 540 - 57F - 0x00, 0x00, 0x01, 0x43, 0x19, 0x24, 0x08, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - // Entry 580 - 5BF - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xab, 0xbd, 0xe7, 0x57, 0xee, 0x13, 0x5d, - 0x09, 0xc1, 0x40, 0x21, 0xfa, 0x17, 0x01, 0x80, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xce, 0xfb, 0xbf, - 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x30, 0x15, 0xa3, 0x10, 0x00, 0x00, 0x00, - 0x11, 0x04, 0x16, 0x00, 0x00, 0x02, 0x20, 0x81, - 0xa3, 0x01, 0x50, 0x00, 0x00, 0x83, 0x11, 0x40, - // Entry 5C0 - 5FF - 0x00, 0x00, 0x00, 0xf0, 0xdd, 0x7b, 0xbe, 0x02, - 0xaa, 0x10, 0x5d, 0x98, 0x52, 0x00, 0x80, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x02, - 0x3d, 0x40, 0x10, 0x02, 0x10, 0x61, 0x5a, 0x9d, - 0x31, 0x00, 0x00, 0x00, 0x01, 0x18, 0x02, 0x20, - 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x20, 0x00, - 0x00, 0x1f, 0xdf, 0xd2, 0xb9, 0xff, 0xfd, 0x3f, - 0x1f, 0x98, 0xcf, 0x9c, 0xff, 0xaf, 0x5f, 0xfe, - // Entry 600 - 63F - 0x7b, 0x4b, 0x40, 0x10, 0xe1, 0xfd, 0xaf, 0xd9, - 0xb7, 0xf6, 0xfb, 0xb3, 0xc7, 0xff, 0x6f, 0xf1, - 0x73, 0xb1, 0x7f, 0x9f, 0x7f, 0xbd, 0xfc, 0xb7, - 0xee, 0x1c, 0xfa, 0xcb, 0xef, 0xdd, 0xf9, 0xbd, - 0x6e, 0xae, 0x55, 0xfd, 0x6e, 0x81, 0x76, 0x9f, - 0xd4, 0x77, 0xf5, 0x7d, 0xfb, 0xff, 0xeb, 0xfe, - 0xbe, 0x5f, 0x46, 0x5b, 0xe9, 0x5f, 0x50, 0x18, - 0x02, 0xfa, 0xf7, 0x9d, 0x15, 0x97, 0x05, 0x0f, - // Entry 640 - 67F - 0x75, 0xc4, 0x7d, 0x81, 0x92, 0xf5, 0x57, 0x6c, - 0xff, 0xe4, 0xef, 0x6f, 0xff, 0xfc, 0xdd, 0xde, - 0xfc, 0xfd, 0x76, 0x5f, 0x7a, 0x3f, 0x00, 0x98, - 0x02, 0xfb, 0xa3, 0xef, 0xf3, 0xd6, 0xf2, 0xff, - 0xb9, 0xda, 0x7d, 0xd0, 0x3e, 0x15, 0x7b, 0xb4, - 0xf5, 0x3e, 0xff, 0xff, 0xf1, 0xf7, 0xff, 0xe7, - 0x5f, 0xff, 0xff, 0x9e, 0xdf, 0xf6, 0xd7, 0xb9, - 0xef, 0x27, 0x80, 0xbb, 0xc5, 0xff, 0xff, 0xe3, - // Entry 680 - 6BF - 0x97, 0x9d, 0xbf, 0x9f, 0xf7, 0xc7, 0xfd, 0x37, - 0xce, 0x7f, 0x44, 0x1d, 0x73, 0x7f, 0xf8, 0xda, - 0x5d, 0xce, 0x7d, 0x06, 0xb9, 0xea, 0x79, 0xa0, - 0x1a, 0x20, 0x00, 0x30, 0x02, 0x04, 0x24, 0x08, - 0x04, 0x00, 0x00, 0x40, 0xd4, 0x02, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x04, 0x00, 0x20, 0x09, 0x06, - 0x50, 0x00, 0x08, 0x00, 0x00, 0x00, 0x24, 0x00, - 0x04, 0x00, 0x10, 0xdc, 0x58, 0xd7, 0x0d, 0x0f, - // Entry 6C0 - 6FF - 0x54, 0x4d, 0xf1, 0x16, 0x44, 0xd5, 0x42, 0x08, - 0x40, 0x02, 0x00, 0x40, 0x00, 0x08, 0x00, 0x00, - 0x00, 0xdc, 0xfb, 0xcb, 0x0e, 0x58, 0x48, 0x41, - 0x24, 0x20, 0x04, 0x00, 0x30, 0x12, 0x40, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x80, 0x10, 0x10, 0xab, - 0x6d, 0x93, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x80, 0x25, 0x00, 0x00, - // Entry 700 - 73F - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0x80, 0x86, 0xc2, 0x00, 0x00, 0x01, 0x00, 0x01, - 0xff, 0x18, 0x02, 0x00, 0x02, 0xf0, 0xfd, 0x79, - 0x3b, 0x00, 0x25, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x03, 0x00, 0x09, 0x20, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 740 - 77F - 0x00, 0x00, 0x00, 0xef, 0xd5, 0xfd, 0xcf, 0x7e, - 0xb0, 0x11, 0x00, 0x00, 0x00, 0x92, 0x01, 0x46, - 0xcd, 0xf9, 0x5c, 0x00, 0x01, 0x00, 0x30, 0x04, - 0x04, 0x55, 0x00, 0x01, 0x04, 0xf4, 0x3f, 0x4a, - 0x01, 0x00, 0x00, 0xb0, 0x80, 0x20, 0x55, 0x75, - 0x97, 0x7c, 0xdf, 0x31, 0xcc, 0x68, 0xd1, 0x03, - 0xd5, 0x57, 0x27, 0x14, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x2c, 0xf7, 0xcb, 0x1f, 0x14, 0x60, - // Entry 780 - 7BF - 0x83, 0x68, 0x01, 0x10, 0x8b, 0x38, 0x8a, 0x01, - 0x00, 0x00, 0x20, 0x00, 0x24, 0x44, 0x00, 0x00, - 0x10, 0x03, 0x31, 0x02, 0x01, 0x00, 0x00, 0xf0, - 0xf5, 0xff, 0xd5, 0x97, 0xbc, 0x70, 0xd6, 0x78, - 0x78, 0x15, 0x50, 0x05, 0xa4, 0x84, 0xa9, 0x41, - 0x00, 0x00, 0x00, 0x6b, 0x39, 0x52, 0x74, 0x40, - 0xe8, 0x30, 0x90, 0x6a, 0x92, 0x00, 0x00, 0x02, - 0xff, 0xef, 0xff, 0x4b, 0x85, 0x53, 0xf4, 0xed, - // Entry 7C0 - 7FF - 0xdd, 0xbf, 0xf2, 0x5d, 0xc7, 0x0c, 0xd5, 0x42, - 0xfc, 0xff, 0xf7, 0x1f, 0x00, 0x80, 0x40, 0x56, - 0xcc, 0x16, 0x9e, 0xea, 0x35, 0x7d, 0xef, 0xff, - 0xbd, 0xa4, 0xaf, 0x01, 0x44, 0x18, 0x01, 0x4d, - 0x4e, 0x4a, 0x08, 0x50, 0x28, 0x30, 0xe0, 0x80, - 0x10, 0x20, 0x24, 0x00, 0xff, 0x2f, 0xd3, 0x60, - 0xfe, 0x01, 0x02, 0x88, 0x2a, 0x40, 0x16, 0x01, - 0x01, 0x15, 0x2b, 0x3c, 0x01, 0x00, 0x00, 0x10, - // Entry 800 - 83F - 0x90, 0x49, 0x41, 0x02, 0x02, 0x01, 0xe1, 0xbf, - 0xbf, 0x03, 0x00, 0x00, 0x10, 0xdc, 0xa3, 0xd1, - 0x40, 0x9c, 0x44, 0xdf, 0xf5, 0x8f, 0x66, 0xb3, - 0x55, 0x20, 0xd4, 0xc1, 0xd8, 0x30, 0x3d, 0x80, - 0x00, 0x00, 0x00, 0x04, 0xd4, 0x11, 0xc5, 0x84, - 0x2f, 0x50, 0x00, 0x22, 0x50, 0x6e, 0xbd, 0x93, - 0x07, 0x00, 0x20, 0x10, 0x84, 0xb2, 0x45, 0x10, - 0x06, 0x44, 0x00, 0x00, 0x12, 0x02, 0x11, 0x00, - // Entry 840 - 87F - 0xf0, 0xfb, 0xfd, 0x7f, 0x05, 0x00, 0x16, 0x89, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x02, 0x28, - 0x84, 0x00, 0x21, 0xc0, 0x23, 0x24, 0x00, 0x00, - 0x00, 0xcb, 0xe4, 0x3a, 0x46, 0x88, 0x54, 0xf1, - 0xef, 0xff, 0x7f, 0x12, 0x01, 0x01, 0x84, 0x50, - 0x07, 0xfc, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x40, - 0x10, 0x38, 0x01, 0x01, 0x1c, 0x12, 0x40, 0xe1, - // Entry 880 - 8BF - 0x76, 0x16, 0x08, 0x03, 0x10, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x24, - 0x0a, 0x00, 0x80, 0x00, 0x00, -} - -// altLangISO3 holds an alphabetically sorted list of 3-letter language code alternatives -// to 2-letter language codes that cannot be derived using the method described above. -// Each 3-letter code is followed by its 1-byte langID. -const altLangISO3 tag.Index = "---\x00cor\x00hbs\x01heb\x02kin\x03spa\x04yid\x05\xff\xff\xff\xff" - -// altLangIndex is used to convert indexes in altLangISO3 to langIDs. -// Size: 12 bytes, 6 elements -var altLangIndex = [6]uint16{ - 0x0281, 0x0407, 0x01fb, 0x03e5, 0x013e, 0x0208, -} - -// AliasMap maps langIDs to their suggested replacements. -// Size: 772 bytes, 193 elements -var AliasMap = [193]FromTo{ - 0: {From: 0x82, To: 0x88}, - 1: {From: 0x187, To: 0x1ae}, - 2: {From: 0x1f3, To: 0x1e1}, - 3: {From: 0x1fb, To: 0x1bc}, - 4: {From: 0x208, To: 0x512}, - 5: {From: 0x20f, To: 0x20e}, - 6: {From: 0x310, To: 0x3dc}, - 7: {From: 0x347, To: 0x36f}, - 8: {From: 0x407, To: 0x432}, - 9: {From: 0x47a, To: 0x153}, - 10: {From: 0x490, To: 0x451}, - 11: {From: 0x4a2, To: 0x21}, - 12: {From: 0x53e, To: 0x544}, - 13: {From: 0x58f, To: 0x12d}, - 14: {From: 0x62b, To: 0x34}, - 15: {From: 0x62f, To: 0x14}, - 16: {From: 0x630, To: 0x1eb1}, - 17: {From: 0x651, To: 0x431}, - 18: {From: 0x662, To: 0x431}, - 19: {From: 0x6ed, To: 0x3a}, - 20: {From: 0x6f8, To: 0x1d7}, - 21: {From: 0x709, To: 0x3625}, - 22: {From: 0x73e, To: 0x21a1}, - 23: {From: 0x7b3, To: 0x56}, - 24: {From: 0x7b9, To: 0x299b}, - 25: {From: 0x7c5, To: 0x58}, - 26: {From: 0x7e6, To: 0x145}, - 27: {From: 0x80c, To: 0x5a}, - 28: {From: 0x815, To: 0x8d}, - 29: {From: 0x87e, To: 0x810}, - 30: {From: 0x8a8, To: 0x8b7}, - 31: {From: 0x8c3, To: 0xee3}, - 32: {From: 0x8fa, To: 0x1dc}, - 33: {From: 0x9ef, To: 0x331}, - 34: {From: 0xa36, To: 0x2c5}, - 35: {From: 0xa3d, To: 0xbf}, - 36: {From: 0xabe, To: 0x3322}, - 37: {From: 0xb38, To: 0x529}, - 38: {From: 0xb75, To: 0x265a}, - 39: {From: 0xb7e, To: 0xbc3}, - 40: {From: 0xb9b, To: 0x44e}, - 41: {From: 0xbbc, To: 0x4229}, - 42: {From: 0xbbf, To: 0x529}, - 43: {From: 0xbfe, To: 0x2da7}, - 44: {From: 0xc2e, To: 0x3181}, - 45: {From: 0xcb9, To: 0xf3}, - 46: {From: 0xd08, To: 0xfa}, - 47: {From: 0xdc8, To: 0x11a}, - 48: {From: 0xdd7, To: 0x32d}, - 49: {From: 0xdf8, To: 0xdfb}, - 50: {From: 0xdfe, To: 0x531}, - 51: {From: 0xe01, To: 0xdf3}, - 52: {From: 0xedf, To: 0x205a}, - 53: {From: 0xee9, To: 0x222e}, - 54: {From: 0xeee, To: 0x2e9a}, - 55: {From: 0xf39, To: 0x367}, - 56: {From: 0x10d0, To: 0x140}, - 57: {From: 0x1104, To: 0x2d0}, - 58: {From: 0x11a0, To: 0x1ec}, - 59: {From: 0x1279, To: 0x21}, - 60: {From: 0x1424, To: 0x15e}, - 61: {From: 0x1470, To: 0x14e}, - 62: {From: 0x151f, To: 0xd9b}, - 63: {From: 0x1523, To: 0x390}, - 64: {From: 0x1532, To: 0x19f}, - 65: {From: 0x1580, To: 0x210}, - 66: {From: 0x1583, To: 0x10d}, - 67: {From: 0x15a3, To: 0x3caf}, - 68: {From: 0x1630, To: 0x222e}, - 69: {From: 0x166a, To: 0x19b}, - 70: {From: 0x16c8, To: 0x136}, - 71: {From: 0x1700, To: 0x29f8}, - 72: {From: 0x1718, To: 0x194}, - 73: {From: 0x1727, To: 0xf3f}, - 74: {From: 0x177a, To: 0x178}, - 75: {From: 0x1809, To: 0x17b6}, - 76: {From: 0x1816, To: 0x18f3}, - 77: {From: 0x188a, To: 0x436}, - 78: {From: 0x1979, To: 0x1d01}, - 79: {From: 0x1a74, To: 0x2bb0}, - 80: {From: 0x1a8a, To: 0x1f8}, - 81: {From: 0x1b5a, To: 0x1fa}, - 82: {From: 0x1b86, To: 0x1515}, - 83: {From: 0x1d64, To: 0x2c9b}, - 84: {From: 0x2038, To: 0x37b1}, - 85: {From: 0x203d, To: 0x20dd}, - 86: {From: 0x2042, To: 0x2e00}, - 87: {From: 0x205a, To: 0x30b}, - 88: {From: 0x20e3, To: 0x274}, - 89: {From: 0x20ee, To: 0x263}, - 90: {From: 0x20f2, To: 0x22d}, - 91: {From: 0x20f9, To: 0x256}, - 92: {From: 0x210f, To: 0x21eb}, - 93: {From: 0x2135, To: 0x27d}, - 94: {From: 0x2160, To: 0x913}, - 95: {From: 0x2199, To: 0x121}, - 96: {From: 0x21ce, To: 0x1561}, - 97: {From: 0x21e6, To: 0x504}, - 98: {From: 0x21f4, To: 0x49f}, - 99: {From: 0x21fb, To: 0x269}, - 100: {From: 0x222d, To: 0x121}, - 101: {From: 0x2237, To: 0x121}, - 102: {From: 0x2248, To: 0x217d}, - 103: {From: 0x2262, To: 0x92a}, - 104: {From: 0x2316, To: 0x3226}, - 105: {From: 0x236a, To: 0x2835}, - 106: {From: 0x2382, To: 0x3365}, - 107: {From: 0x2472, To: 0x2c7}, - 108: {From: 0x24e4, To: 0x2ff}, - 109: {From: 0x24f0, To: 0x2fa}, - 110: {From: 0x24fa, To: 0x31f}, - 111: {From: 0x2550, To: 0xb5b}, - 112: {From: 0x25a9, To: 0xe2}, - 113: {From: 0x263e, To: 0x2d0}, - 114: {From: 0x26c9, To: 0x26b4}, - 115: {From: 0x26f9, To: 0x3c8}, - 116: {From: 0x2727, To: 0x3caf}, - 117: {From: 0x2755, To: 0x6a4}, - 118: {From: 0x2765, To: 0x26b4}, - 119: {From: 0x2789, To: 0x4358}, - 120: {From: 0x27c9, To: 0x2001}, - 121: {From: 0x28ea, To: 0x27b1}, - 122: {From: 0x28ef, To: 0x2837}, - 123: {From: 0x28fe, To: 0xaa5}, - 124: {From: 0x2914, To: 0x351}, - 125: {From: 0x2986, To: 0x2da7}, - 126: {From: 0x29f0, To: 0x96b}, - 127: {From: 0x2b1a, To: 0x38d}, - 128: {From: 0x2bfc, To: 0x395}, - 129: {From: 0x2c3f, To: 0x3caf}, - 130: {From: 0x2ce1, To: 0x2201}, - 131: {From: 0x2cfc, To: 0x3be}, - 132: {From: 0x2d13, To: 0x597}, - 133: {From: 0x2d47, To: 0x148}, - 134: {From: 0x2d48, To: 0x148}, - 135: {From: 0x2dff, To: 0x2f1}, - 136: {From: 0x2e08, To: 0x19cc}, - 137: {From: 0x2e10, To: 0xc45}, - 138: {From: 0x2e1a, To: 0x2d95}, - 139: {From: 0x2e21, To: 0x292}, - 140: {From: 0x2e54, To: 0x7d}, - 141: {From: 0x2e65, To: 0x2282}, - 142: {From: 0x2e97, To: 0x1a4}, - 143: {From: 0x2ea0, To: 0x2e9b}, - 144: {From: 0x2eef, To: 0x2ed7}, - 145: {From: 0x3193, To: 0x3c4}, - 146: {From: 0x3366, To: 0x338e}, - 147: {From: 0x342a, To: 0x3dc}, - 148: {From: 0x34ee, To: 0x18d0}, - 149: {From: 0x35c8, To: 0x2c9b}, - 150: {From: 0x35e6, To: 0x412}, - 151: {From: 0x35f5, To: 0x24b}, - 152: {From: 0x360d, To: 0x1dc}, - 153: {From: 0x3658, To: 0x246}, - 154: {From: 0x3676, To: 0x3f4}, - 155: {From: 0x36fd, To: 0x445}, - 156: {From: 0x3747, To: 0x3b42}, - 157: {From: 0x37c0, To: 0x121}, - 158: {From: 0x3816, To: 0x38f2}, - 159: {From: 0x382a, To: 0x2b48}, - 160: {From: 0x382b, To: 0x2c9b}, - 161: {From: 0x382f, To: 0xa9}, - 162: {From: 0x3832, To: 0x3228}, - 163: {From: 0x386c, To: 0x39a6}, - 164: {From: 0x3892, To: 0x3fc0}, - 165: {From: 0x38a0, To: 0x45f}, - 166: {From: 0x38a5, To: 0x39d7}, - 167: {From: 0x38b4, To: 0x1fa4}, - 168: {From: 0x38b5, To: 0x2e9a}, - 169: {From: 0x38fa, To: 0x38f1}, - 170: {From: 0x395c, To: 0x47e}, - 171: {From: 0x3b4e, To: 0xd91}, - 172: {From: 0x3b78, To: 0x137}, - 173: {From: 0x3c99, To: 0x4bc}, - 174: {From: 0x3fbd, To: 0x100}, - 175: {From: 0x4208, To: 0xa91}, - 176: {From: 0x42be, To: 0x573}, - 177: {From: 0x42f9, To: 0x3f60}, - 178: {From: 0x4378, To: 0x25a}, - 179: {From: 0x43b8, To: 0xe6c}, - 180: {From: 0x43cd, To: 0x10f}, - 181: {From: 0x43d4, To: 0x4848}, - 182: {From: 0x44af, To: 0x3322}, - 183: {From: 0x44e3, To: 0x512}, - 184: {From: 0x45ca, To: 0x2409}, - 185: {From: 0x45dd, To: 0x26dc}, - 186: {From: 0x4610, To: 0x48ae}, - 187: {From: 0x46ae, To: 0x46a0}, - 188: {From: 0x473e, To: 0x4745}, - 189: {From: 0x4817, To: 0x3503}, - 190: {From: 0x483b, To: 0x208b}, - 191: {From: 0x4916, To: 0x31f}, - 192: {From: 0x49a7, To: 0x523}, -} - -// Size: 193 bytes, 193 elements -var AliasTypes = [193]AliasType{ - // Entry 0 - 3F - 1, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 1, 0, 0, 0, 0, - 1, 2, 1, 1, 2, 0, 0, 1, 0, 1, 2, 1, 1, 0, 0, 0, - 0, 2, 1, 1, 0, 2, 0, 0, 1, 0, 1, 0, 0, 1, 2, 1, - 1, 1, 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 1, 0, 1, - // Entry 40 - 7F - 1, 2, 2, 0, 0, 1, 2, 0, 1, 0, 1, 1, 1, 1, 0, 0, - 2, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 0, - 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, - // Entry 80 - BF - 1, 0, 0, 1, 0, 2, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 1, 1, 2, 0, 0, 2, 0, 0, 1, 1, 1, 0, 0, 0, 0, - 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 0, - 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, - // Entry C0 - FF - 1, -} - -const ( - _Latn = 91 - _Hani = 57 - _Hans = 59 - _Hant = 60 - _Qaaa = 149 - _Qaai = 157 - _Qabx = 198 - _Zinh = 255 - _Zyyy = 260 - _Zzzz = 261 -) - -// script is an alphabetically sorted list of ISO 15924 codes. The index -// of the script in the string, divided by 4, is the internal scriptID. -const script tag.Index = "" + // Size: 1052 bytes - "----AdlmAfakAghbAhomArabAranArmiArmnAvstBaliBamuBassBatkBengBhksBlisBopo" + - "BrahBraiBugiBuhdCakmCansCariChamCherChrsCirtCoptCpmnCprtCyrlCyrsDevaDiak" + - "DogrDsrtDuplEgydEgyhEgypElbaElymEthiGeokGeorGlagGongGonmGothGranGrekGujr" + - "GuruHanbHangHaniHanoHansHantHatrHebrHiraHluwHmngHmnpHrktHungIndsItalJamo" + - "JavaJpanJurcKaliKanaKawiKharKhmrKhojKitlKitsKndaKoreKpelKthiLanaLaooLatf" + - "LatgLatnLekeLepcLimbLinaLinbLisuLomaLyciLydiMahjMakaMandManiMarcMayaMedf" + - "MendMercMeroMlymModiMongMoonMrooMteiMultMymrNagmNandNarbNbatNewaNkdbNkgb" + - "NkooNshuOgamOlckOrkhOryaOsgeOsmaOugrPalmPaucPcunPelmPermPhagPhliPhlpPhlv" + - "PhnxPiqdPlrdPrtiPsinQaaaQaabQaacQaadQaaeQaafQaagQaahQaaiQaajQaakQaalQaam" + - "QaanQaaoQaapQaaqQaarQaasQaatQaauQaavQaawQaaxQaayQaazQabaQabbQabcQabdQabe" + - "QabfQabgQabhQabiQabjQabkQablQabmQabnQaboQabpQabqQabrQabsQabtQabuQabvQabw" + - "QabxRanjRjngRohgRoroRunrSamrSaraSarbSaurSgnwShawShrdShuiSiddSindSinhSogd" + - "SogoSoraSoyoSundSunuSyloSyrcSyreSyrjSyrnTagbTakrTaleTaluTamlTangTavtTelu" + - "TengTfngTglgThaaThaiTibtTirhTnsaTotoUgarVaiiVispVithWaraWchoWoleXpeoXsux" + - "YeziYiiiZanbZinhZmthZsyeZsymZxxxZyyyZzzz\xff\xff\xff\xff" - -// suppressScript is an index from langID to the dominant script for that language, -// if it exists. If a script is given, it should be suppressed from the language tag. -// Size: 1330 bytes, 1330 elements -var suppressScript = [1330]uint8{ - // Entry 0 - 3F - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 40 - 7F - 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, - // Entry 80 - BF - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry C0 - FF - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 100 - 13F - 0x5b, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xed, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x5b, 0x00, - // Entry 140 - 17F - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x5b, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 180 - 1BF - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5b, 0x35, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x22, 0x00, - // Entry 1C0 - 1FF - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x5b, 0x00, 0x5b, 0x5b, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0x5b, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, - // Entry 200 - 23F - 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 240 - 27F - 0x00, 0x00, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x22, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 280 - 2BF - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 2C0 - 2FF - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - // Entry 300 - 33F - 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x5b, - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, - // Entry 340 - 37F - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x5b, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5b, 0x00, - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 380 - 3BF - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, - // Entry 3C0 - 3FF - 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 400 - 43F - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, - // Entry 440 - 47F - 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5b, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xe9, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x2c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, - // Entry 480 - 4BF - 0x5b, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x5b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 4C0 - 4FF - 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 500 - 53F - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x00, 0x00, -} - -const ( - _001 = 1 - _419 = 31 - _BR = 65 - _CA = 73 - _ES = 111 - _GB = 124 - _MD = 189 - _PT = 239 - _UK = 307 - _US = 310 - _ZZ = 358 - _XA = 324 - _XC = 326 - _XK = 334 -) - -// isoRegionOffset needs to be added to the index of regionISO to obtain the regionID -// for 2-letter ISO codes. (The first isoRegionOffset regionIDs are reserved for -// the UN.M49 codes used for groups.) -const isoRegionOffset = 32 - -// regionTypes defines the status of a region for various standards. -// Size: 359 bytes, 359 elements -var regionTypes = [359]uint8{ - // Entry 0 - 3F - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - // Entry 40 - 7F - 0x06, 0x06, 0x06, 0x06, 0x04, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x04, 0x04, 0x06, - 0x04, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x04, 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x00, - 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x00, 0x06, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, - // Entry 80 - BF - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x00, 0x04, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - // Entry C0 - FF - 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x04, - 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x00, 0x06, 0x06, 0x00, 0x06, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - // Entry 100 - 13F - 0x05, 0x05, 0x05, 0x06, 0x00, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x04, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x02, 0x06, 0x04, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, - // Entry 140 - 17F - 0x06, 0x06, 0x00, 0x06, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, 0x06, - 0x06, 0x04, 0x06, 0x06, 0x04, 0x06, 0x05, -} - -// regionISO holds a list of alphabetically sorted 2-letter ISO region codes. -// Each 2-letter codes is followed by two bytes with the following meaning: -// - [A-Z}{2}: the first letter of the 2-letter code plus these two -// letters form the 3-letter ISO code. -// - 0, n: index into altRegionISO3. -const regionISO tag.Index = "" + // Size: 1312 bytes - "AAAAACSCADNDAEREAFFGAGTGAIIAALLBAMRMANNTAOGOAQTAARRGASSMATUTAUUSAWBWAXLA" + - "AZZEBAIHBBRBBDGDBEELBFFABGGRBHHRBIDIBJENBLLMBMMUBNRNBOOLBQESBRRABSHSBTTN" + - "BUURBVVTBWWABYLRBZLZCAANCCCKCDODCFAFCGOGCHHECIIVCKOKCLHLCMMRCNHNCOOLCPPT" + - "CQ CRRICS\x00\x00CTTECUUBCVPVCWUWCXXRCYYPCZZEDDDRDEEUDGGADJJIDKNKDMMADO" + - "OMDYHYDZZAEA ECCUEESTEGGYEHSHERRIESSPETTHEU\x00\x03EZ FIINFJJIFKLKFMSM" + - "FOROFQ\x00\x18FRRAFXXXGAABGBBRGDRDGEEOGFUFGGGYGHHAGIIBGLRLGMMBGNINGPLPGQ" + - "NQGRRCGS\x00\x06GTTMGUUMGWNBGYUYHKKGHMMDHNNDHRRVHTTIHUUNHVVOIC IDDNIERL" + - "ILSRIMMNINNDIOOTIQRQIRRNISSLITTAJEEYJMAMJOORJPPNJTTNKEENKGGZKHHMKIIRKM" + - "\x00\x09KNNAKP\x00\x0cKRORKWWTKY\x00\x0fKZAZLAAOLBBNLCCALIIELKKALRBRLSSO" + - "LTTULUUXLVVALYBYMAARMCCOMDDAMENEMFAFMGDGMHHLMIIDMKKDMLLIMMMRMNNGMOACMPNP" + - "MQTQMRRTMSSRMTLTMUUSMVDVMWWIMXEXMYYSMZOZNAAMNCCLNEERNFFKNGGANHHBNIICNLLD" + - "NOORNPPLNQ\x00\x1eNRRUNTTZNUIUNZZLOMMNPAANPCCIPEERPFYFPGNGPHHLPKAKPLOLPM" + - "\x00\x12PNCNPRRIPSSEPTRTPUUSPWLWPYRYPZCZQAATQMMMQNNNQOOOQPPPQQQQQRRRQSSS" + - "QTTTQU\x00\x03QVVVQWWWQXXXQYYYQZZZREEURHHOROOURS\x00\x15RUUSRWWASAAUSBLB" + - "SCYCSDDNSEWESGGPSHHNSIVNSJJMSKVKSLLESMMRSNENSOOMSRURSSSDSTTPSUUNSVLVSXXM" + - "SYYRSZWZTAAATCCATDCDTF\x00\x18TGGOTHHATJJKTKKLTLLSTMKMTNUNTOONTPMPTRURTT" + - "TOTVUVTWWNTZZAUAKRUGGAUK UMMIUN USSAUYRYUZZBVAATVCCTVDDRVEENVGGBVIIRVN" + - "NMVUUTWFLFWKAKWSSMXAAAXBBBXCCCXDDDXEEEXFFFXGGGXHHHXIIIXJJJXKKKXLLLXMMMXN" + - "NNXOOOXPPPXQQQXRRRXSSSXTTTXUUUXVVVXWWWXXXXXYYYXZZZYDMDYEEMYT\x00\x1bYUUG" + - "ZAAFZMMBZRARZWWEZZZZ\xff\xff\xff\xff" - -// altRegionISO3 holds a list of 3-letter region codes that cannot be -// mapped to 2-letter codes using the default algorithm. This is a short list. -const altRegionISO3 string = "SCGQUUSGSCOMPRKCYMSPMSRBATFMYTATN" - -// altRegionIDs holds a list of regionIDs the positions of which match those -// of the 3-letter ISO codes in altRegionISO3. -// Size: 22 bytes, 11 elements -var altRegionIDs = [11]uint16{ - 0x0058, 0x0071, 0x0089, 0x00a9, 0x00ab, 0x00ae, 0x00eb, 0x0106, - 0x0122, 0x0160, 0x00dd, -} - -// Size: 80 bytes, 20 elements -var regionOldMap = [20]FromTo{ - 0: {From: 0x44, To: 0xc5}, - 1: {From: 0x59, To: 0xa8}, - 2: {From: 0x60, To: 0x61}, - 3: {From: 0x67, To: 0x3b}, - 4: {From: 0x7a, To: 0x79}, - 5: {From: 0x94, To: 0x37}, - 6: {From: 0xa4, To: 0x134}, - 7: {From: 0xc2, To: 0x134}, - 8: {From: 0xd8, To: 0x140}, - 9: {From: 0xdd, To: 0x2b}, - 10: {From: 0xf0, To: 0x134}, - 11: {From: 0xf3, To: 0xe3}, - 12: {From: 0xfd, To: 0x71}, - 13: {From: 0x104, To: 0x165}, - 14: {From: 0x12b, To: 0x127}, - 15: {From: 0x133, To: 0x7c}, - 16: {From: 0x13b, To: 0x13f}, - 17: {From: 0x142, To: 0x134}, - 18: {From: 0x15e, To: 0x15f}, - 19: {From: 0x164, To: 0x4b}, -} - -// m49 maps regionIDs to UN.M49 codes. The first isoRegionOffset entries are -// codes indicating collections of regions. -// Size: 718 bytes, 359 elements -var m49 = [359]int16{ - // Entry 0 - 3F - 0, 1, 2, 3, 5, 9, 11, 13, - 14, 15, 17, 18, 19, 21, 29, 30, - 34, 35, 39, 53, 54, 57, 61, 142, - 143, 145, 150, 151, 154, 155, 202, 419, - 958, 0, 20, 784, 4, 28, 660, 8, - 51, 530, 24, 10, 32, 16, 40, 36, - 533, 248, 31, 70, 52, 50, 56, 854, - 100, 48, 108, 204, 652, 60, 96, 68, - // Entry 40 - 7F - 535, 76, 44, 64, 104, 74, 72, 112, - 84, 124, 166, 180, 140, 178, 756, 384, - 184, 152, 120, 156, 170, 0, 0, 188, - 891, 296, 192, 132, 531, 162, 196, 203, - 278, 276, 0, 262, 208, 212, 214, 204, - 12, 0, 218, 233, 818, 732, 232, 724, - 231, 967, 0, 246, 242, 238, 583, 234, - 0, 250, 249, 266, 826, 308, 268, 254, - // Entry 80 - BF - 831, 288, 292, 304, 270, 324, 312, 226, - 300, 239, 320, 316, 624, 328, 344, 334, - 340, 191, 332, 348, 854, 0, 360, 372, - 376, 833, 356, 86, 368, 364, 352, 380, - 832, 388, 400, 392, 581, 404, 417, 116, - 296, 174, 659, 408, 410, 414, 136, 398, - 418, 422, 662, 438, 144, 430, 426, 440, - 442, 428, 434, 504, 492, 498, 499, 663, - // Entry C0 - FF - 450, 584, 581, 807, 466, 104, 496, 446, - 580, 474, 478, 500, 470, 480, 462, 454, - 484, 458, 508, 516, 540, 562, 574, 566, - 548, 558, 528, 578, 524, 10, 520, 536, - 570, 554, 512, 591, 0, 604, 258, 598, - 608, 586, 616, 666, 612, 630, 275, 620, - 581, 585, 600, 591, 634, 959, 960, 961, - 962, 963, 964, 965, 966, 967, 968, 969, - // Entry 100 - 13F - 970, 971, 972, 638, 716, 642, 688, 643, - 646, 682, 90, 690, 729, 752, 702, 654, - 705, 744, 703, 694, 674, 686, 706, 740, - 728, 678, 810, 222, 534, 760, 748, 0, - 796, 148, 260, 768, 764, 762, 772, 626, - 795, 788, 776, 626, 792, 780, 798, 158, - 834, 804, 800, 826, 581, 0, 840, 858, - 860, 336, 670, 704, 862, 92, 850, 704, - // Entry 140 - 17F - 548, 876, 581, 882, 973, 974, 975, 976, - 977, 978, 979, 980, 981, 982, 983, 984, - 985, 986, 987, 988, 989, 990, 991, 992, - 993, 994, 995, 996, 997, 998, 720, 887, - 175, 891, 710, 894, 180, 716, 999, -} - -// m49Index gives indexes into fromM49 based on the three most significant bits -// of a 10-bit UN.M49 code. To search an UN.M49 code in fromM49, search in -// -// fromM49[m49Index[msb39(code)]:m49Index[msb3(code)+1]] -// -// for an entry where the first 7 bits match the 7 lsb of the UN.M49 code. -// The region code is stored in the 9 lsb of the indexed value. -// Size: 18 bytes, 9 elements -var m49Index = [9]int16{ - 0, 59, 108, 143, 181, 220, 259, 291, - 333, -} - -// fromM49 contains entries to map UN.M49 codes to regions. See m49Index for details. -// Size: 666 bytes, 333 elements -var fromM49 = [333]uint16{ - // Entry 0 - 3F - 0x0201, 0x0402, 0x0603, 0x0824, 0x0a04, 0x1027, 0x1205, 0x142b, - 0x1606, 0x1868, 0x1a07, 0x1c08, 0x1e09, 0x202d, 0x220a, 0x240b, - 0x260c, 0x2822, 0x2a0d, 0x302a, 0x3825, 0x3a0e, 0x3c0f, 0x3e32, - 0x402c, 0x4410, 0x4611, 0x482f, 0x4e12, 0x502e, 0x5842, 0x6039, - 0x6435, 0x6628, 0x6834, 0x6a13, 0x6c14, 0x7036, 0x7215, 0x783d, - 0x7a16, 0x8043, 0x883f, 0x8c33, 0x9046, 0x9445, 0x9841, 0xa848, - 0xac9b, 0xb50a, 0xb93d, 0xc03e, 0xc838, 0xd0c5, 0xd83a, 0xe047, - 0xe8a7, 0xf052, 0xf849, 0x085b, 0x10ae, 0x184c, 0x1c17, 0x1e18, - // Entry 40 - 7F - 0x20b4, 0x2219, 0x2921, 0x2c1a, 0x2e1b, 0x3051, 0x341c, 0x361d, - 0x3853, 0x3d2f, 0x445d, 0x4c4a, 0x5454, 0x5ca9, 0x5f60, 0x644d, - 0x684b, 0x7050, 0x7857, 0x7e91, 0x805a, 0x885e, 0x941e, 0x965f, - 0x983b, 0xa064, 0xa865, 0xac66, 0xb46a, 0xbd1b, 0xc487, 0xcc70, - 0xce70, 0xd06e, 0xd26b, 0xd477, 0xdc75, 0xde89, 0xe474, 0xec73, - 0xf031, 0xf27a, 0xf479, 0xfc7f, 0x04e6, 0x0922, 0x0c63, 0x147b, - 0x187e, 0x1c84, 0x26ee, 0x2861, 0x2c60, 0x3061, 0x4081, 0x4882, - 0x50a8, 0x5888, 0x6083, 0x687d, 0x7086, 0x788b, 0x808a, 0x8885, - // Entry 80 - BF - 0x908d, 0x9892, 0x9c8f, 0xa139, 0xa890, 0xb08e, 0xb893, 0xc09e, - 0xc89a, 0xd096, 0xd89d, 0xe09c, 0xe897, 0xf098, 0xf89f, 0x004f, - 0x08a1, 0x10a3, 0x1caf, 0x20a2, 0x28a5, 0x30ab, 0x34ac, 0x3cad, - 0x42a6, 0x44b0, 0x461f, 0x4cb1, 0x54b6, 0x58b9, 0x5cb5, 0x64ba, - 0x6cb3, 0x70b7, 0x74b8, 0x7cc7, 0x84c0, 0x8ccf, 0x94d1, 0x9cce, - 0xa4c4, 0xaccc, 0xb4c9, 0xbcca, 0xc0cd, 0xc8d0, 0xd8bc, 0xe0c6, - 0xe4bd, 0xe6be, 0xe8cb, 0xf0bb, 0xf8d2, 0x00e2, 0x08d3, 0x10de, - 0x18dc, 0x20da, 0x2429, 0x265c, 0x2a30, 0x2d1c, 0x2e40, 0x30df, - // Entry C0 - FF - 0x38d4, 0x4940, 0x54e1, 0x5cd9, 0x64d5, 0x6cd7, 0x74e0, 0x7cd6, - 0x84db, 0x88c8, 0x8b34, 0x8e76, 0x90c1, 0x92f1, 0x94e9, 0x9ee3, - 0xace7, 0xb0f2, 0xb8e5, 0xc0e8, 0xc8ec, 0xd0ea, 0xd8ef, 0xe08c, - 0xe527, 0xeced, 0xf4f4, 0xfd03, 0x0505, 0x0707, 0x0d08, 0x183c, - 0x1d0f, 0x26aa, 0x2826, 0x2cb2, 0x2ebf, 0x34eb, 0x3d3a, 0x4514, - 0x4d19, 0x5509, 0x5d15, 0x6106, 0x650b, 0x6d13, 0x7d0e, 0x7f12, - 0x813f, 0x8310, 0x8516, 0x8d62, 0x9965, 0xa15e, 0xa86f, 0xb118, - 0xb30c, 0xb86d, 0xc10c, 0xc917, 0xd111, 0xd91e, 0xe10d, 0xe84e, - // Entry 100 - 13F - 0xf11d, 0xf525, 0xf924, 0x0123, 0x0926, 0x112a, 0x192d, 0x2023, - 0x2929, 0x312c, 0x3728, 0x3920, 0x3d2e, 0x4132, 0x4931, 0x4ec3, - 0x551a, 0x646c, 0x747c, 0x7e80, 0x80a0, 0x8299, 0x8530, 0x9136, - 0xa53e, 0xac37, 0xb537, 0xb938, 0xbd3c, 0xd941, 0xe543, 0xed5f, - 0xef5f, 0xf658, 0xfd63, 0x7c20, 0x7ef5, 0x80f6, 0x82f7, 0x84f8, - 0x86f9, 0x88fa, 0x8afb, 0x8cfc, 0x8e71, 0x90fe, 0x92ff, 0x9500, - 0x9701, 0x9902, 0x9b44, 0x9d45, 0x9f46, 0xa147, 0xa348, 0xa549, - 0xa74a, 0xa94b, 0xab4c, 0xad4d, 0xaf4e, 0xb14f, 0xb350, 0xb551, - // Entry 140 - 17F - 0xb752, 0xb953, 0xbb54, 0xbd55, 0xbf56, 0xc157, 0xc358, 0xc559, - 0xc75a, 0xc95b, 0xcb5c, 0xcd5d, 0xcf66, -} - -// Size: 2128 bytes -var variantIndex = map[string]uint8{ - "1606nict": 0x0, - "1694acad": 0x1, - "1901": 0x2, - "1959acad": 0x3, - "1994": 0x67, - "1996": 0x4, - "abl1943": 0x5, - "akuapem": 0x6, - "alalc97": 0x69, - "aluku": 0x7, - "ao1990": 0x8, - "aranes": 0x9, - "arevela": 0xa, - "arevmda": 0xb, - "arkaika": 0xc, - "asante": 0xd, - "auvern": 0xe, - "baku1926": 0xf, - "balanka": 0x10, - "barla": 0x11, - "basiceng": 0x12, - "bauddha": 0x13, - "bciav": 0x14, - "bcizbl": 0x15, - "biscayan": 0x16, - "biske": 0x62, - "bohoric": 0x17, - "boont": 0x18, - "bornholm": 0x19, - "cisaup": 0x1a, - "colb1945": 0x1b, - "cornu": 0x1c, - "creiss": 0x1d, - "dajnko": 0x1e, - "ekavsk": 0x1f, - "emodeng": 0x20, - "fonipa": 0x6a, - "fonkirsh": 0x6b, - "fonnapa": 0x6c, - "fonupa": 0x6d, - "fonxsamp": 0x6e, - "gallo": 0x21, - "gascon": 0x22, - "grclass": 0x23, - "grital": 0x24, - "grmistr": 0x25, - "hepburn": 0x26, - "heploc": 0x68, - "hognorsk": 0x27, - "hsistemo": 0x28, - "ijekavsk": 0x29, - "itihasa": 0x2a, - "ivanchov": 0x2b, - "jauer": 0x2c, - "jyutping": 0x2d, - "kkcor": 0x2e, - "kociewie": 0x2f, - "kscor": 0x30, - "laukika": 0x31, - "lemosin": 0x32, - "lengadoc": 0x33, - "lipaw": 0x63, - "ltg1929": 0x34, - "ltg2007": 0x35, - "luna1918": 0x36, - "metelko": 0x37, - "monoton": 0x38, - "ndyuka": 0x39, - "nedis": 0x3a, - "newfound": 0x3b, - "nicard": 0x3c, - "njiva": 0x64, - "nulik": 0x3d, - "osojs": 0x65, - "oxendict": 0x3e, - "pahawh2": 0x3f, - "pahawh3": 0x40, - "pahawh4": 0x41, - "pamaka": 0x42, - "peano": 0x43, - "petr1708": 0x44, - "pinyin": 0x45, - "polyton": 0x46, - "provenc": 0x47, - "puter": 0x48, - "rigik": 0x49, - "rozaj": 0x4a, - "rumgr": 0x4b, - "scotland": 0x4c, - "scouse": 0x4d, - "simple": 0x6f, - "solba": 0x66, - "sotav": 0x4e, - "spanglis": 0x4f, - "surmiran": 0x50, - "sursilv": 0x51, - "sutsilv": 0x52, - "synnejyl": 0x53, - "tarask": 0x54, - "tongyong": 0x55, - "tunumiit": 0x56, - "uccor": 0x57, - "ucrcor": 0x58, - "ulster": 0x59, - "unifon": 0x5a, - "vaidika": 0x5b, - "valencia": 0x5c, - "vallader": 0x5d, - "vecdruka": 0x5e, - "vivaraup": 0x5f, - "wadegile": 0x60, - "xsistemo": 0x61, -} - -// variantNumSpecialized is the number of specialized variants in variants. -const variantNumSpecialized = 105 - -// nRegionGroups is the number of region groups. -const nRegionGroups = 33 - -type likelyLangRegion struct { - lang uint16 - region uint16 -} - -// likelyScript is a lookup table, indexed by scriptID, for the most likely -// languages and regions given a script. -// Size: 1052 bytes, 263 elements -var likelyScript = [263]likelyLangRegion{ - 1: {lang: 0x14e, region: 0x85}, - 3: {lang: 0x2a2, region: 0x107}, - 4: {lang: 0x1f, region: 0x9a}, - 5: {lang: 0x3a, region: 0x6c}, - 7: {lang: 0x3b, region: 0x9d}, - 8: {lang: 0x1d7, region: 0x28}, - 9: {lang: 0x13, region: 0x9d}, - 10: {lang: 0x5b, region: 0x96}, - 11: {lang: 0x60, region: 0x52}, - 12: {lang: 0xb9, region: 0xb5}, - 13: {lang: 0x63, region: 0x96}, - 14: {lang: 0xa5, region: 0x35}, - 15: {lang: 0x3e9, region: 0x9a}, - 17: {lang: 0x529, region: 0x12f}, - 18: {lang: 0x3b1, region: 0x9a}, - 19: {lang: 0x15e, region: 0x79}, - 20: {lang: 0xc2, region: 0x96}, - 21: {lang: 0x9d, region: 0xe8}, - 22: {lang: 0xdb, region: 0x35}, - 23: {lang: 0xf3, region: 0x49}, - 24: {lang: 0x4f0, region: 0x12c}, - 25: {lang: 0xe7, region: 0x13f}, - 26: {lang: 0xe5, region: 0x136}, - 29: {lang: 0xf1, region: 0x6c}, - 31: {lang: 0x1a0, region: 0x5e}, - 32: {lang: 0x3e2, region: 0x107}, - 34: {lang: 0x1be, region: 0x9a}, - 38: {lang: 0x15e, region: 0x79}, - 41: {lang: 0x133, region: 0x6c}, - 42: {lang: 0x431, region: 0x27}, - 44: {lang: 0x27, region: 0x70}, - 46: {lang: 0x210, region: 0x7e}, - 47: {lang: 0xfe, region: 0x38}, - 49: {lang: 0x19b, region: 0x9a}, - 50: {lang: 0x19e, region: 0x131}, - 51: {lang: 0x3e9, region: 0x9a}, - 52: {lang: 0x136, region: 0x88}, - 53: {lang: 0x1a4, region: 0x9a}, - 54: {lang: 0x39d, region: 0x9a}, - 55: {lang: 0x529, region: 0x12f}, - 56: {lang: 0x254, region: 0xac}, - 57: {lang: 0x529, region: 0x53}, - 58: {lang: 0x1cb, region: 0xe8}, - 59: {lang: 0x529, region: 0x53}, - 60: {lang: 0x529, region: 0x12f}, - 61: {lang: 0x2fd, region: 0x9c}, - 62: {lang: 0x1bc, region: 0x98}, - 63: {lang: 0x200, region: 0xa3}, - 64: {lang: 0x1c5, region: 0x12c}, - 65: {lang: 0x1ca, region: 0xb0}, - 68: {lang: 0x1d5, region: 0x93}, - 70: {lang: 0x142, region: 0x9f}, - 71: {lang: 0x254, region: 0xac}, - 72: {lang: 0x20e, region: 0x96}, - 73: {lang: 0x200, region: 0xa3}, - 75: {lang: 0x135, region: 0xc5}, - 76: {lang: 0x200, region: 0xa3}, - 78: {lang: 0x3bb, region: 0xe9}, - 79: {lang: 0x24a, region: 0xa7}, - 80: {lang: 0x3fa, region: 0x9a}, - 83: {lang: 0x251, region: 0x9a}, - 84: {lang: 0x254, region: 0xac}, - 86: {lang: 0x88, region: 0x9a}, - 87: {lang: 0x370, region: 0x124}, - 88: {lang: 0x2b8, region: 0xb0}, - 93: {lang: 0x29f, region: 0x9a}, - 94: {lang: 0x2a8, region: 0x9a}, - 95: {lang: 0x28f, region: 0x88}, - 96: {lang: 0x1a0, region: 0x88}, - 97: {lang: 0x2ac, region: 0x53}, - 99: {lang: 0x4f4, region: 0x12c}, - 100: {lang: 0x4f5, region: 0x12c}, - 101: {lang: 0x1be, region: 0x9a}, - 103: {lang: 0x337, region: 0x9d}, - 104: {lang: 0x4f7, region: 0x53}, - 105: {lang: 0xa9, region: 0x53}, - 108: {lang: 0x2e8, region: 0x113}, - 109: {lang: 0x4f8, region: 0x10c}, - 110: {lang: 0x4f8, region: 0x10c}, - 111: {lang: 0x304, region: 0x9a}, - 112: {lang: 0x31b, region: 0x9a}, - 113: {lang: 0x30b, region: 0x53}, - 115: {lang: 0x31e, region: 0x35}, - 116: {lang: 0x30e, region: 0x9a}, - 117: {lang: 0x414, region: 0xe9}, - 118: {lang: 0x331, region: 0xc5}, - 121: {lang: 0x4f9, region: 0x109}, - 122: {lang: 0x3b, region: 0xa2}, - 123: {lang: 0x353, region: 0xdc}, - 126: {lang: 0x2d0, region: 0x85}, - 127: {lang: 0x52a, region: 0x53}, - 128: {lang: 0x403, region: 0x97}, - 129: {lang: 0x3ee, region: 0x9a}, - 130: {lang: 0x39b, region: 0xc6}, - 131: {lang: 0x395, region: 0x9a}, - 132: {lang: 0x399, region: 0x136}, - 133: {lang: 0x429, region: 0x116}, - 135: {lang: 0x3b, region: 0x11d}, - 136: {lang: 0xfd, region: 0xc5}, - 139: {lang: 0x27d, region: 0x107}, - 140: {lang: 0x2c9, region: 0x53}, - 141: {lang: 0x39f, region: 0x9d}, - 142: {lang: 0x39f, region: 0x53}, - 144: {lang: 0x3ad, region: 0xb1}, - 146: {lang: 0x1c6, region: 0x53}, - 147: {lang: 0x4fd, region: 0x9d}, - 200: {lang: 0x3cb, region: 0x96}, - 203: {lang: 0x372, region: 0x10d}, - 204: {lang: 0x420, region: 0x98}, - 206: {lang: 0x4ff, region: 0x15f}, - 207: {lang: 0x3f0, region: 0x9a}, - 208: {lang: 0x45, region: 0x136}, - 209: {lang: 0x139, region: 0x7c}, - 210: {lang: 0x3e9, region: 0x9a}, - 212: {lang: 0x3e9, region: 0x9a}, - 213: {lang: 0x3fa, region: 0x9a}, - 214: {lang: 0x40c, region: 0xb4}, - 217: {lang: 0x433, region: 0x9a}, - 218: {lang: 0xef, region: 0xc6}, - 219: {lang: 0x43e, region: 0x96}, - 221: {lang: 0x44d, region: 0x35}, - 222: {lang: 0x44e, region: 0x9c}, - 226: {lang: 0x45a, region: 0xe8}, - 227: {lang: 0x11a, region: 0x9a}, - 228: {lang: 0x45e, region: 0x53}, - 229: {lang: 0x232, region: 0x53}, - 230: {lang: 0x450, region: 0x9a}, - 231: {lang: 0x4a5, region: 0x53}, - 232: {lang: 0x9f, region: 0x13f}, - 233: {lang: 0x461, region: 0x9a}, - 235: {lang: 0x528, region: 0xbb}, - 236: {lang: 0x153, region: 0xe8}, - 237: {lang: 0x128, region: 0xce}, - 238: {lang: 0x46b, region: 0x124}, - 239: {lang: 0xa9, region: 0x53}, - 240: {lang: 0x2ce, region: 0x9a}, - 243: {lang: 0x4ad, region: 0x11d}, - 244: {lang: 0x4be, region: 0xb5}, - 247: {lang: 0x1ce, region: 0x9a}, - 250: {lang: 0x3a9, region: 0x9d}, - 251: {lang: 0x22, region: 0x9c}, - 253: {lang: 0x1ea, region: 0x53}, - 254: {lang: 0xef, region: 0xc6}, -} - -type likelyScriptRegion struct { - region uint16 - script uint16 - flags uint8 -} - -// likelyLang is a lookup table, indexed by langID, for the most likely -// scripts and regions given incomplete information. If more entries exist for a -// given language, region and script are the index and size respectively -// of the list in likelyLangList. -// Size: 7980 bytes, 1330 elements -var likelyLang = [1330]likelyScriptRegion{ - 0: {region: 0x136, script: 0x5b, flags: 0x0}, - 1: {region: 0x70, script: 0x5b, flags: 0x0}, - 2: {region: 0x166, script: 0x5b, flags: 0x0}, - 3: {region: 0x166, script: 0x5b, flags: 0x0}, - 4: {region: 0x166, script: 0x5b, flags: 0x0}, - 5: {region: 0x7e, script: 0x20, flags: 0x0}, - 6: {region: 0x166, script: 0x5b, flags: 0x0}, - 7: {region: 0x166, script: 0x20, flags: 0x0}, - 8: {region: 0x81, script: 0x5b, flags: 0x0}, - 9: {region: 0x166, script: 0x5b, flags: 0x0}, - 10: {region: 0x166, script: 0x5b, flags: 0x0}, - 11: {region: 0x166, script: 0x5b, flags: 0x0}, - 12: {region: 0x96, script: 0x5b, flags: 0x0}, - 13: {region: 0x132, script: 0x5b, flags: 0x0}, - 14: {region: 0x81, script: 0x5b, flags: 0x0}, - 15: {region: 0x166, script: 0x5b, flags: 0x0}, - 16: {region: 0x166, script: 0x5b, flags: 0x0}, - 17: {region: 0x107, script: 0x20, flags: 0x0}, - 18: {region: 0x166, script: 0x5b, flags: 0x0}, - 19: {region: 0x9d, script: 0x9, flags: 0x0}, - 20: {region: 0x129, script: 0x5, flags: 0x0}, - 21: {region: 0x166, script: 0x5b, flags: 0x0}, - 22: {region: 0x162, script: 0x5b, flags: 0x0}, - 23: {region: 0x166, script: 0x5b, flags: 0x0}, - 24: {region: 0x166, script: 0x5b, flags: 0x0}, - 25: {region: 0x166, script: 0x5b, flags: 0x0}, - 26: {region: 0x166, script: 0x5b, flags: 0x0}, - 27: {region: 0x166, script: 0x5b, flags: 0x0}, - 28: {region: 0x52, script: 0x5b, flags: 0x0}, - 29: {region: 0x166, script: 0x5b, flags: 0x0}, - 30: {region: 0x166, script: 0x5b, flags: 0x0}, - 31: {region: 0x9a, script: 0x4, flags: 0x0}, - 32: {region: 0x166, script: 0x5b, flags: 0x0}, - 33: {region: 0x81, script: 0x5b, flags: 0x0}, - 34: {region: 0x9c, script: 0xfb, flags: 0x0}, - 35: {region: 0x166, script: 0x5b, flags: 0x0}, - 36: {region: 0x166, script: 0x5b, flags: 0x0}, - 37: {region: 0x14e, script: 0x5b, flags: 0x0}, - 38: {region: 0x107, script: 0x20, flags: 0x0}, - 39: {region: 0x70, script: 0x2c, flags: 0x0}, - 40: {region: 0x166, script: 0x5b, flags: 0x0}, - 41: {region: 0x166, script: 0x5b, flags: 0x0}, - 42: {region: 0xd7, script: 0x5b, flags: 0x0}, - 43: {region: 0x166, script: 0x5b, flags: 0x0}, - 45: {region: 0x166, script: 0x5b, flags: 0x0}, - 46: {region: 0x166, script: 0x5b, flags: 0x0}, - 47: {region: 0x166, script: 0x5b, flags: 0x0}, - 48: {region: 0x166, script: 0x5b, flags: 0x0}, - 49: {region: 0x166, script: 0x5b, flags: 0x0}, - 50: {region: 0x166, script: 0x5b, flags: 0x0}, - 51: {region: 0x96, script: 0x5b, flags: 0x0}, - 52: {region: 0x166, script: 0x5, flags: 0x0}, - 53: {region: 0x123, script: 0x5, flags: 0x0}, - 54: {region: 0x166, script: 0x5b, flags: 0x0}, - 55: {region: 0x166, script: 0x5b, flags: 0x0}, - 56: {region: 0x166, script: 0x5b, flags: 0x0}, - 57: {region: 0x166, script: 0x5b, flags: 0x0}, - 58: {region: 0x6c, script: 0x5, flags: 0x0}, - 59: {region: 0x0, script: 0x3, flags: 0x1}, - 60: {region: 0x166, script: 0x5b, flags: 0x0}, - 61: {region: 0x51, script: 0x5b, flags: 0x0}, - 62: {region: 0x3f, script: 0x5b, flags: 0x0}, - 63: {region: 0x68, script: 0x5, flags: 0x0}, - 65: {region: 0xbb, script: 0x5, flags: 0x0}, - 66: {region: 0x6c, script: 0x5, flags: 0x0}, - 67: {region: 0x9a, script: 0xe, flags: 0x0}, - 68: {region: 0x130, script: 0x5b, flags: 0x0}, - 69: {region: 0x136, script: 0xd0, flags: 0x0}, - 70: {region: 0x166, script: 0x5b, flags: 0x0}, - 71: {region: 0x166, script: 0x5b, flags: 0x0}, - 72: {region: 0x6f, script: 0x5b, flags: 0x0}, - 73: {region: 0x166, script: 0x5b, flags: 0x0}, - 74: {region: 0x166, script: 0x5b, flags: 0x0}, - 75: {region: 0x49, script: 0x5b, flags: 0x0}, - 76: {region: 0x166, script: 0x5b, flags: 0x0}, - 77: {region: 0x107, script: 0x20, flags: 0x0}, - 78: {region: 0x166, script: 0x5, flags: 0x0}, - 79: {region: 0x166, script: 0x5b, flags: 0x0}, - 80: {region: 0x166, script: 0x5b, flags: 0x0}, - 81: {region: 0x166, script: 0x5b, flags: 0x0}, - 82: {region: 0x9a, script: 0x22, flags: 0x0}, - 83: {region: 0x166, script: 0x5b, flags: 0x0}, - 84: {region: 0x166, script: 0x5b, flags: 0x0}, - 85: {region: 0x166, script: 0x5b, flags: 0x0}, - 86: {region: 0x3f, script: 0x5b, flags: 0x0}, - 87: {region: 0x166, script: 0x5b, flags: 0x0}, - 88: {region: 0x3, script: 0x5, flags: 0x1}, - 89: {region: 0x107, script: 0x20, flags: 0x0}, - 90: {region: 0xe9, script: 0x5, flags: 0x0}, - 91: {region: 0x96, script: 0x5b, flags: 0x0}, - 92: {region: 0xdc, script: 0x22, flags: 0x0}, - 93: {region: 0x2e, script: 0x5b, flags: 0x0}, - 94: {region: 0x52, script: 0x5b, flags: 0x0}, - 95: {region: 0x166, script: 0x5b, flags: 0x0}, - 96: {region: 0x52, script: 0xb, flags: 0x0}, - 97: {region: 0x166, script: 0x5b, flags: 0x0}, - 98: {region: 0x166, script: 0x5b, flags: 0x0}, - 99: {region: 0x96, script: 0x5b, flags: 0x0}, - 100: {region: 0x166, script: 0x5b, flags: 0x0}, - 101: {region: 0x52, script: 0x5b, flags: 0x0}, - 102: {region: 0x166, script: 0x5b, flags: 0x0}, - 103: {region: 0x166, script: 0x5b, flags: 0x0}, - 104: {region: 0x166, script: 0x5b, flags: 0x0}, - 105: {region: 0x166, script: 0x5b, flags: 0x0}, - 106: {region: 0x4f, script: 0x5b, flags: 0x0}, - 107: {region: 0x166, script: 0x5b, flags: 0x0}, - 108: {region: 0x166, script: 0x5b, flags: 0x0}, - 109: {region: 0x166, script: 0x5b, flags: 0x0}, - 110: {region: 0x166, script: 0x2c, flags: 0x0}, - 111: {region: 0x166, script: 0x5b, flags: 0x0}, - 112: {region: 0x166, script: 0x5b, flags: 0x0}, - 113: {region: 0x47, script: 0x20, flags: 0x0}, - 114: {region: 0x166, script: 0x5b, flags: 0x0}, - 115: {region: 0x166, script: 0x5b, flags: 0x0}, - 116: {region: 0x10c, script: 0x5, flags: 0x0}, - 117: {region: 0x163, script: 0x5b, flags: 0x0}, - 118: {region: 0x166, script: 0x5b, flags: 0x0}, - 119: {region: 0x96, script: 0x5b, flags: 0x0}, - 120: {region: 0x166, script: 0x5b, flags: 0x0}, - 121: {region: 0x130, script: 0x5b, flags: 0x0}, - 122: {region: 0x52, script: 0x5b, flags: 0x0}, - 123: {region: 0x9a, script: 0xe6, flags: 0x0}, - 124: {region: 0xe9, script: 0x5, flags: 0x0}, - 125: {region: 0x9a, script: 0x22, flags: 0x0}, - 126: {region: 0x38, script: 0x20, flags: 0x0}, - 127: {region: 0x9a, script: 0x22, flags: 0x0}, - 128: {region: 0xe9, script: 0x5, flags: 0x0}, - 129: {region: 0x12c, script: 0x34, flags: 0x0}, - 131: {region: 0x9a, script: 0x22, flags: 0x0}, - 132: {region: 0x166, script: 0x5b, flags: 0x0}, - 133: {region: 0x9a, script: 0x22, flags: 0x0}, - 134: {region: 0xe8, script: 0x5b, flags: 0x0}, - 135: {region: 0x166, script: 0x5b, flags: 0x0}, - 136: {region: 0x9a, script: 0x22, flags: 0x0}, - 137: {region: 0x166, script: 0x5b, flags: 0x0}, - 138: {region: 0x140, script: 0x5b, flags: 0x0}, - 139: {region: 0x166, script: 0x5b, flags: 0x0}, - 140: {region: 0x166, script: 0x5b, flags: 0x0}, - 141: {region: 0xe8, script: 0x5b, flags: 0x0}, - 142: {region: 0x166, script: 0x5b, flags: 0x0}, - 143: {region: 0xd7, script: 0x5b, flags: 0x0}, - 144: {region: 0x166, script: 0x5b, flags: 0x0}, - 145: {region: 0x166, script: 0x5b, flags: 0x0}, - 146: {region: 0x166, script: 0x5b, flags: 0x0}, - 147: {region: 0x166, script: 0x2c, flags: 0x0}, - 148: {region: 0x9a, script: 0x22, flags: 0x0}, - 149: {region: 0x96, script: 0x5b, flags: 0x0}, - 150: {region: 0x166, script: 0x5b, flags: 0x0}, - 151: {region: 0x166, script: 0x5b, flags: 0x0}, - 152: {region: 0x115, script: 0x5b, flags: 0x0}, - 153: {region: 0x166, script: 0x5b, flags: 0x0}, - 154: {region: 0x166, script: 0x5b, flags: 0x0}, - 155: {region: 0x52, script: 0x5b, flags: 0x0}, - 156: {region: 0x166, script: 0x5b, flags: 0x0}, - 157: {region: 0xe8, script: 0x5b, flags: 0x0}, - 158: {region: 0x166, script: 0x5b, flags: 0x0}, - 159: {region: 0x13f, script: 0xe8, flags: 0x0}, - 160: {region: 0xc4, script: 0x5b, flags: 0x0}, - 161: {region: 0x166, script: 0x5b, flags: 0x0}, - 162: {region: 0x166, script: 0x5b, flags: 0x0}, - 163: {region: 0xc4, script: 0x5b, flags: 0x0}, - 164: {region: 0x166, script: 0x5b, flags: 0x0}, - 165: {region: 0x35, script: 0xe, flags: 0x0}, - 166: {region: 0x166, script: 0x5b, flags: 0x0}, - 167: {region: 0x166, script: 0x5b, flags: 0x0}, - 168: {region: 0x166, script: 0x5b, flags: 0x0}, - 169: {region: 0x53, script: 0xef, flags: 0x0}, - 170: {region: 0x166, script: 0x5b, flags: 0x0}, - 171: {region: 0x166, script: 0x5b, flags: 0x0}, - 172: {region: 0x166, script: 0x5b, flags: 0x0}, - 173: {region: 0x9a, script: 0xe, flags: 0x0}, - 174: {region: 0x166, script: 0x5b, flags: 0x0}, - 175: {region: 0x9d, script: 0x5, flags: 0x0}, - 176: {region: 0x166, script: 0x5b, flags: 0x0}, - 177: {region: 0x4f, script: 0x5b, flags: 0x0}, - 178: {region: 0x79, script: 0x5b, flags: 0x0}, - 179: {region: 0x9a, script: 0x22, flags: 0x0}, - 180: {region: 0xe9, script: 0x5, flags: 0x0}, - 181: {region: 0x9a, script: 0x22, flags: 0x0}, - 182: {region: 0x166, script: 0x5b, flags: 0x0}, - 183: {region: 0x33, script: 0x5b, flags: 0x0}, - 184: {region: 0x166, script: 0x5b, flags: 0x0}, - 185: {region: 0xb5, script: 0xc, flags: 0x0}, - 186: {region: 0x52, script: 0x5b, flags: 0x0}, - 187: {region: 0x166, script: 0x2c, flags: 0x0}, - 188: {region: 0xe8, script: 0x5b, flags: 0x0}, - 189: {region: 0x166, script: 0x5b, flags: 0x0}, - 190: {region: 0xe9, script: 0x22, flags: 0x0}, - 191: {region: 0x107, script: 0x20, flags: 0x0}, - 192: {region: 0x160, script: 0x5b, flags: 0x0}, - 193: {region: 0x166, script: 0x5b, flags: 0x0}, - 194: {region: 0x96, script: 0x5b, flags: 0x0}, - 195: {region: 0x166, script: 0x5b, flags: 0x0}, - 196: {region: 0x52, script: 0x5b, flags: 0x0}, - 197: {region: 0x166, script: 0x5b, flags: 0x0}, - 198: {region: 0x166, script: 0x5b, flags: 0x0}, - 199: {region: 0x166, script: 0x5b, flags: 0x0}, - 200: {region: 0x87, script: 0x5b, flags: 0x0}, - 201: {region: 0x166, script: 0x5b, flags: 0x0}, - 202: {region: 0x166, script: 0x5b, flags: 0x0}, - 203: {region: 0x166, script: 0x5b, flags: 0x0}, - 204: {region: 0x166, script: 0x5b, flags: 0x0}, - 205: {region: 0x6e, script: 0x2c, flags: 0x0}, - 206: {region: 0x166, script: 0x5b, flags: 0x0}, - 207: {region: 0x166, script: 0x5b, flags: 0x0}, - 208: {region: 0x52, script: 0x5b, flags: 0x0}, - 209: {region: 0x166, script: 0x5b, flags: 0x0}, - 210: {region: 0x166, script: 0x5b, flags: 0x0}, - 211: {region: 0xc4, script: 0x5b, flags: 0x0}, - 212: {region: 0x166, script: 0x5b, flags: 0x0}, - 213: {region: 0x166, script: 0x5b, flags: 0x0}, - 214: {region: 0x166, script: 0x5b, flags: 0x0}, - 215: {region: 0x6f, script: 0x5b, flags: 0x0}, - 216: {region: 0x166, script: 0x5b, flags: 0x0}, - 217: {region: 0x166, script: 0x5b, flags: 0x0}, - 218: {region: 0xd7, script: 0x5b, flags: 0x0}, - 219: {region: 0x35, script: 0x16, flags: 0x0}, - 220: {region: 0x107, script: 0x20, flags: 0x0}, - 221: {region: 0xe8, script: 0x5b, flags: 0x0}, - 222: {region: 0x166, script: 0x5b, flags: 0x0}, - 223: {region: 0x132, script: 0x5b, flags: 0x0}, - 224: {region: 0x8b, script: 0x5b, flags: 0x0}, - 225: {region: 0x76, script: 0x5b, flags: 0x0}, - 226: {region: 0x107, script: 0x20, flags: 0x0}, - 227: {region: 0x136, script: 0x5b, flags: 0x0}, - 228: {region: 0x49, script: 0x5b, flags: 0x0}, - 229: {region: 0x136, script: 0x1a, flags: 0x0}, - 230: {region: 0xa7, script: 0x5, flags: 0x0}, - 231: {region: 0x13f, script: 0x19, flags: 0x0}, - 232: {region: 0x166, script: 0x5b, flags: 0x0}, - 233: {region: 0x9c, script: 0x5, flags: 0x0}, - 234: {region: 0x166, script: 0x5b, flags: 0x0}, - 235: {region: 0x166, script: 0x5b, flags: 0x0}, - 236: {region: 0x166, script: 0x5b, flags: 0x0}, - 237: {region: 0x166, script: 0x5b, flags: 0x0}, - 238: {region: 0x166, script: 0x5b, flags: 0x0}, - 239: {region: 0xc6, script: 0xda, flags: 0x0}, - 240: {region: 0x79, script: 0x5b, flags: 0x0}, - 241: {region: 0x6c, script: 0x1d, flags: 0x0}, - 242: {region: 0xe8, script: 0x5b, flags: 0x0}, - 243: {region: 0x49, script: 0x17, flags: 0x0}, - 244: {region: 0x131, script: 0x20, flags: 0x0}, - 245: {region: 0x49, script: 0x17, flags: 0x0}, - 246: {region: 0x49, script: 0x17, flags: 0x0}, - 247: {region: 0x49, script: 0x17, flags: 0x0}, - 248: {region: 0x49, script: 0x17, flags: 0x0}, - 249: {region: 0x10b, script: 0x5b, flags: 0x0}, - 250: {region: 0x5f, script: 0x5b, flags: 0x0}, - 251: {region: 0xea, script: 0x5b, flags: 0x0}, - 252: {region: 0x49, script: 0x17, flags: 0x0}, - 253: {region: 0xc5, script: 0x88, flags: 0x0}, - 254: {region: 0x8, script: 0x2, flags: 0x1}, - 255: {region: 0x107, script: 0x20, flags: 0x0}, - 256: {region: 0x7c, script: 0x5b, flags: 0x0}, - 257: {region: 0x64, script: 0x5b, flags: 0x0}, - 258: {region: 0x166, script: 0x5b, flags: 0x0}, - 259: {region: 0x166, script: 0x5b, flags: 0x0}, - 260: {region: 0x166, script: 0x5b, flags: 0x0}, - 261: {region: 0x166, script: 0x5b, flags: 0x0}, - 262: {region: 0x136, script: 0x5b, flags: 0x0}, - 263: {region: 0x107, script: 0x20, flags: 0x0}, - 264: {region: 0xa5, script: 0x5b, flags: 0x0}, - 265: {region: 0x166, script: 0x5b, flags: 0x0}, - 266: {region: 0x166, script: 0x5b, flags: 0x0}, - 267: {region: 0x9a, script: 0x5, flags: 0x0}, - 268: {region: 0x166, script: 0x5b, flags: 0x0}, - 269: {region: 0x61, script: 0x5b, flags: 0x0}, - 270: {region: 0x166, script: 0x5b, flags: 0x0}, - 271: {region: 0x49, script: 0x5b, flags: 0x0}, - 272: {region: 0x166, script: 0x5b, flags: 0x0}, - 273: {region: 0x166, script: 0x5b, flags: 0x0}, - 274: {region: 0x166, script: 0x5b, flags: 0x0}, - 275: {region: 0x166, script: 0x5, flags: 0x0}, - 276: {region: 0x49, script: 0x5b, flags: 0x0}, - 277: {region: 0x166, script: 0x5b, flags: 0x0}, - 278: {region: 0x166, script: 0x5b, flags: 0x0}, - 279: {region: 0xd5, script: 0x5b, flags: 0x0}, - 280: {region: 0x4f, script: 0x5b, flags: 0x0}, - 281: {region: 0x166, script: 0x5b, flags: 0x0}, - 282: {region: 0x9a, script: 0x5, flags: 0x0}, - 283: {region: 0x166, script: 0x5b, flags: 0x0}, - 284: {region: 0x166, script: 0x5b, flags: 0x0}, - 285: {region: 0x166, script: 0x5b, flags: 0x0}, - 286: {region: 0x166, script: 0x2c, flags: 0x0}, - 287: {region: 0x61, script: 0x5b, flags: 0x0}, - 288: {region: 0xc4, script: 0x5b, flags: 0x0}, - 289: {region: 0xd1, script: 0x5b, flags: 0x0}, - 290: {region: 0x166, script: 0x5b, flags: 0x0}, - 291: {region: 0xdc, script: 0x22, flags: 0x0}, - 292: {region: 0x52, script: 0x5b, flags: 0x0}, - 293: {region: 0x166, script: 0x5b, flags: 0x0}, - 294: {region: 0x166, script: 0x5b, flags: 0x0}, - 295: {region: 0x166, script: 0x5b, flags: 0x0}, - 296: {region: 0xce, script: 0xed, flags: 0x0}, - 297: {region: 0x166, script: 0x5b, flags: 0x0}, - 298: {region: 0x166, script: 0x5b, flags: 0x0}, - 299: {region: 0x115, script: 0x5b, flags: 0x0}, - 300: {region: 0x37, script: 0x5b, flags: 0x0}, - 301: {region: 0x43, script: 0xef, flags: 0x0}, - 302: {region: 0x166, script: 0x5b, flags: 0x0}, - 303: {region: 0xa5, script: 0x5b, flags: 0x0}, - 304: {region: 0x81, script: 0x5b, flags: 0x0}, - 305: {region: 0xd7, script: 0x5b, flags: 0x0}, - 306: {region: 0x9f, script: 0x5b, flags: 0x0}, - 307: {region: 0x6c, script: 0x29, flags: 0x0}, - 308: {region: 0x166, script: 0x5b, flags: 0x0}, - 309: {region: 0xc5, script: 0x4b, flags: 0x0}, - 310: {region: 0x88, script: 0x34, flags: 0x0}, - 311: {region: 0x166, script: 0x5b, flags: 0x0}, - 312: {region: 0x166, script: 0x5b, flags: 0x0}, - 313: {region: 0xa, script: 0x2, flags: 0x1}, - 314: {region: 0x166, script: 0x5b, flags: 0x0}, - 315: {region: 0x166, script: 0x5b, flags: 0x0}, - 316: {region: 0x1, script: 0x5b, flags: 0x0}, - 317: {region: 0x166, script: 0x5b, flags: 0x0}, - 318: {region: 0x6f, script: 0x5b, flags: 0x0}, - 319: {region: 0x136, script: 0x5b, flags: 0x0}, - 320: {region: 0x6b, script: 0x5b, flags: 0x0}, - 321: {region: 0x166, script: 0x5b, flags: 0x0}, - 322: {region: 0x9f, script: 0x46, flags: 0x0}, - 323: {region: 0x166, script: 0x5b, flags: 0x0}, - 324: {region: 0x166, script: 0x5b, flags: 0x0}, - 325: {region: 0x6f, script: 0x5b, flags: 0x0}, - 326: {region: 0x52, script: 0x5b, flags: 0x0}, - 327: {region: 0x6f, script: 0x5b, flags: 0x0}, - 328: {region: 0x9d, script: 0x5, flags: 0x0}, - 329: {region: 0x166, script: 0x5b, flags: 0x0}, - 330: {region: 0x166, script: 0x5b, flags: 0x0}, - 331: {region: 0x166, script: 0x5b, flags: 0x0}, - 332: {region: 0x166, script: 0x5b, flags: 0x0}, - 333: {region: 0x87, script: 0x5b, flags: 0x0}, - 334: {region: 0xc, script: 0x2, flags: 0x1}, - 335: {region: 0x166, script: 0x5b, flags: 0x0}, - 336: {region: 0xc4, script: 0x5b, flags: 0x0}, - 337: {region: 0x73, script: 0x5b, flags: 0x0}, - 338: {region: 0x10c, script: 0x5, flags: 0x0}, - 339: {region: 0xe8, script: 0x5b, flags: 0x0}, - 340: {region: 0x10d, script: 0x5b, flags: 0x0}, - 341: {region: 0x74, script: 0x5b, flags: 0x0}, - 342: {region: 0x166, script: 0x5b, flags: 0x0}, - 343: {region: 0x166, script: 0x5b, flags: 0x0}, - 344: {region: 0x77, script: 0x5b, flags: 0x0}, - 345: {region: 0x166, script: 0x5b, flags: 0x0}, - 346: {region: 0x3b, script: 0x5b, flags: 0x0}, - 347: {region: 0x166, script: 0x5b, flags: 0x0}, - 348: {region: 0x166, script: 0x5b, flags: 0x0}, - 349: {region: 0x166, script: 0x5b, flags: 0x0}, - 350: {region: 0x79, script: 0x5b, flags: 0x0}, - 351: {region: 0x136, script: 0x5b, flags: 0x0}, - 352: {region: 0x79, script: 0x5b, flags: 0x0}, - 353: {region: 0x61, script: 0x5b, flags: 0x0}, - 354: {region: 0x61, script: 0x5b, flags: 0x0}, - 355: {region: 0x52, script: 0x5, flags: 0x0}, - 356: {region: 0x141, script: 0x5b, flags: 0x0}, - 357: {region: 0x166, script: 0x5b, flags: 0x0}, - 358: {region: 0x85, script: 0x5b, flags: 0x0}, - 359: {region: 0x166, script: 0x5b, flags: 0x0}, - 360: {region: 0xd5, script: 0x5b, flags: 0x0}, - 361: {region: 0x9f, script: 0x5b, flags: 0x0}, - 362: {region: 0xd7, script: 0x5b, flags: 0x0}, - 363: {region: 0x166, script: 0x5b, flags: 0x0}, - 364: {region: 0x10c, script: 0x5b, flags: 0x0}, - 365: {region: 0xda, script: 0x5b, flags: 0x0}, - 366: {region: 0x97, script: 0x5b, flags: 0x0}, - 367: {region: 0x81, script: 0x5b, flags: 0x0}, - 368: {region: 0x166, script: 0x5b, flags: 0x0}, - 369: {region: 0xbd, script: 0x5b, flags: 0x0}, - 370: {region: 0x166, script: 0x5b, flags: 0x0}, - 371: {region: 0x166, script: 0x5b, flags: 0x0}, - 372: {region: 0x166, script: 0x5b, flags: 0x0}, - 373: {region: 0x53, script: 0x3b, flags: 0x0}, - 374: {region: 0x166, script: 0x5b, flags: 0x0}, - 375: {region: 0x96, script: 0x5b, flags: 0x0}, - 376: {region: 0x166, script: 0x5b, flags: 0x0}, - 377: {region: 0x166, script: 0x5b, flags: 0x0}, - 378: {region: 0x9a, script: 0x22, flags: 0x0}, - 379: {region: 0x166, script: 0x5b, flags: 0x0}, - 380: {region: 0x9d, script: 0x5, flags: 0x0}, - 381: {region: 0x7f, script: 0x5b, flags: 0x0}, - 382: {region: 0x7c, script: 0x5b, flags: 0x0}, - 383: {region: 0x166, script: 0x5b, flags: 0x0}, - 384: {region: 0x166, script: 0x5b, flags: 0x0}, - 385: {region: 0x166, script: 0x5b, flags: 0x0}, - 386: {region: 0x166, script: 0x5b, flags: 0x0}, - 387: {region: 0x166, script: 0x5b, flags: 0x0}, - 388: {region: 0x166, script: 0x5b, flags: 0x0}, - 389: {region: 0x70, script: 0x2c, flags: 0x0}, - 390: {region: 0x166, script: 0x5b, flags: 0x0}, - 391: {region: 0xdc, script: 0x22, flags: 0x0}, - 392: {region: 0x166, script: 0x5b, flags: 0x0}, - 393: {region: 0xa8, script: 0x5b, flags: 0x0}, - 394: {region: 0x166, script: 0x5b, flags: 0x0}, - 395: {region: 0xe9, script: 0x5, flags: 0x0}, - 396: {region: 0x166, script: 0x5b, flags: 0x0}, - 397: {region: 0xe9, script: 0x5, flags: 0x0}, - 398: {region: 0x166, script: 0x5b, flags: 0x0}, - 399: {region: 0x166, script: 0x5b, flags: 0x0}, - 400: {region: 0x6f, script: 0x5b, flags: 0x0}, - 401: {region: 0x9d, script: 0x5, flags: 0x0}, - 402: {region: 0x166, script: 0x5b, flags: 0x0}, - 403: {region: 0x166, script: 0x2c, flags: 0x0}, - 404: {region: 0xf2, script: 0x5b, flags: 0x0}, - 405: {region: 0x166, script: 0x5b, flags: 0x0}, - 406: {region: 0x166, script: 0x5b, flags: 0x0}, - 407: {region: 0x166, script: 0x5b, flags: 0x0}, - 408: {region: 0x166, script: 0x2c, flags: 0x0}, - 409: {region: 0x166, script: 0x5b, flags: 0x0}, - 410: {region: 0x9a, script: 0x22, flags: 0x0}, - 411: {region: 0x9a, script: 0xe9, flags: 0x0}, - 412: {region: 0x96, script: 0x5b, flags: 0x0}, - 413: {region: 0xda, script: 0x5b, flags: 0x0}, - 414: {region: 0x131, script: 0x32, flags: 0x0}, - 415: {region: 0x166, script: 0x5b, flags: 0x0}, - 416: {region: 0xe, script: 0x2, flags: 0x1}, - 417: {region: 0x9a, script: 0xe, flags: 0x0}, - 418: {region: 0x166, script: 0x5b, flags: 0x0}, - 419: {region: 0x4e, script: 0x5b, flags: 0x0}, - 420: {region: 0x9a, script: 0x35, flags: 0x0}, - 421: {region: 0x41, script: 0x5b, flags: 0x0}, - 422: {region: 0x54, script: 0x5b, flags: 0x0}, - 423: {region: 0x166, script: 0x5b, flags: 0x0}, - 424: {region: 0x81, script: 0x5b, flags: 0x0}, - 425: {region: 0x166, script: 0x5b, flags: 0x0}, - 426: {region: 0x166, script: 0x5b, flags: 0x0}, - 427: {region: 0xa5, script: 0x5b, flags: 0x0}, - 428: {region: 0x99, script: 0x5b, flags: 0x0}, - 429: {region: 0x166, script: 0x5b, flags: 0x0}, - 430: {region: 0xdc, script: 0x22, flags: 0x0}, - 431: {region: 0x166, script: 0x5b, flags: 0x0}, - 432: {region: 0x166, script: 0x5, flags: 0x0}, - 433: {region: 0x49, script: 0x5b, flags: 0x0}, - 434: {region: 0x166, script: 0x5, flags: 0x0}, - 435: {region: 0x166, script: 0x5b, flags: 0x0}, - 436: {region: 0x10, script: 0x3, flags: 0x1}, - 437: {region: 0x166, script: 0x5b, flags: 0x0}, - 438: {region: 0x53, script: 0x3b, flags: 0x0}, - 439: {region: 0x166, script: 0x5b, flags: 0x0}, - 440: {region: 0x136, script: 0x5b, flags: 0x0}, - 441: {region: 0x24, script: 0x5, flags: 0x0}, - 442: {region: 0x166, script: 0x5b, flags: 0x0}, - 443: {region: 0x166, script: 0x2c, flags: 0x0}, - 444: {region: 0x98, script: 0x3e, flags: 0x0}, - 445: {region: 0x166, script: 0x5b, flags: 0x0}, - 446: {region: 0x9a, script: 0x22, flags: 0x0}, - 447: {region: 0x166, script: 0x5b, flags: 0x0}, - 448: {region: 0x74, script: 0x5b, flags: 0x0}, - 449: {region: 0x166, script: 0x5b, flags: 0x0}, - 450: {region: 0x166, script: 0x5b, flags: 0x0}, - 451: {region: 0xe8, script: 0x5b, flags: 0x0}, - 452: {region: 0x166, script: 0x5b, flags: 0x0}, - 453: {region: 0x12c, script: 0x40, flags: 0x0}, - 454: {region: 0x53, script: 0x92, flags: 0x0}, - 455: {region: 0x166, script: 0x5b, flags: 0x0}, - 456: {region: 0xe9, script: 0x5, flags: 0x0}, - 457: {region: 0x9a, script: 0x22, flags: 0x0}, - 458: {region: 0xb0, script: 0x41, flags: 0x0}, - 459: {region: 0xe8, script: 0x5b, flags: 0x0}, - 460: {region: 0xe9, script: 0x5, flags: 0x0}, - 461: {region: 0xe7, script: 0x5b, flags: 0x0}, - 462: {region: 0x9a, script: 0x22, flags: 0x0}, - 463: {region: 0x9a, script: 0x22, flags: 0x0}, - 464: {region: 0x166, script: 0x5b, flags: 0x0}, - 465: {region: 0x91, script: 0x5b, flags: 0x0}, - 466: {region: 0x61, script: 0x5b, flags: 0x0}, - 467: {region: 0x53, script: 0x3b, flags: 0x0}, - 468: {region: 0x92, script: 0x5b, flags: 0x0}, - 469: {region: 0x93, script: 0x5b, flags: 0x0}, - 470: {region: 0x166, script: 0x5b, flags: 0x0}, - 471: {region: 0x28, script: 0x8, flags: 0x0}, - 472: {region: 0xd3, script: 0x5b, flags: 0x0}, - 473: {region: 0x79, script: 0x5b, flags: 0x0}, - 474: {region: 0x166, script: 0x5b, flags: 0x0}, - 475: {region: 0x166, script: 0x5b, flags: 0x0}, - 476: {region: 0xd1, script: 0x5b, flags: 0x0}, - 477: {region: 0xd7, script: 0x5b, flags: 0x0}, - 478: {region: 0x166, script: 0x5b, flags: 0x0}, - 479: {region: 0x166, script: 0x5b, flags: 0x0}, - 480: {region: 0x166, script: 0x5b, flags: 0x0}, - 481: {region: 0x96, script: 0x5b, flags: 0x0}, - 482: {region: 0x166, script: 0x5b, flags: 0x0}, - 483: {region: 0x166, script: 0x5b, flags: 0x0}, - 484: {region: 0x166, script: 0x5b, flags: 0x0}, - 486: {region: 0x123, script: 0x5b, flags: 0x0}, - 487: {region: 0xd7, script: 0x5b, flags: 0x0}, - 488: {region: 0x166, script: 0x5b, flags: 0x0}, - 489: {region: 0x166, script: 0x5b, flags: 0x0}, - 490: {region: 0x53, script: 0xfd, flags: 0x0}, - 491: {region: 0x166, script: 0x5b, flags: 0x0}, - 492: {region: 0x136, script: 0x5b, flags: 0x0}, - 493: {region: 0x166, script: 0x5b, flags: 0x0}, - 494: {region: 0x49, script: 0x5b, flags: 0x0}, - 495: {region: 0x166, script: 0x5b, flags: 0x0}, - 496: {region: 0x166, script: 0x5b, flags: 0x0}, - 497: {region: 0xe8, script: 0x5b, flags: 0x0}, - 498: {region: 0x166, script: 0x5b, flags: 0x0}, - 499: {region: 0x96, script: 0x5b, flags: 0x0}, - 500: {region: 0x107, script: 0x20, flags: 0x0}, - 501: {region: 0x1, script: 0x5b, flags: 0x0}, - 502: {region: 0x166, script: 0x5b, flags: 0x0}, - 503: {region: 0x166, script: 0x5b, flags: 0x0}, - 504: {region: 0x9e, script: 0x5b, flags: 0x0}, - 505: {region: 0x9f, script: 0x5b, flags: 0x0}, - 506: {region: 0x49, script: 0x17, flags: 0x0}, - 507: {region: 0x98, script: 0x3e, flags: 0x0}, - 508: {region: 0x166, script: 0x5b, flags: 0x0}, - 509: {region: 0x166, script: 0x5b, flags: 0x0}, - 510: {region: 0x107, script: 0x5b, flags: 0x0}, - 511: {region: 0x166, script: 0x5b, flags: 0x0}, - 512: {region: 0xa3, script: 0x49, flags: 0x0}, - 513: {region: 0x166, script: 0x5b, flags: 0x0}, - 514: {region: 0xa1, script: 0x5b, flags: 0x0}, - 515: {region: 0x1, script: 0x5b, flags: 0x0}, - 516: {region: 0x166, script: 0x5b, flags: 0x0}, - 517: {region: 0x166, script: 0x5b, flags: 0x0}, - 518: {region: 0x166, script: 0x5b, flags: 0x0}, - 519: {region: 0x52, script: 0x5b, flags: 0x0}, - 520: {region: 0x131, script: 0x3e, flags: 0x0}, - 521: {region: 0x166, script: 0x5b, flags: 0x0}, - 522: {region: 0x130, script: 0x5b, flags: 0x0}, - 523: {region: 0xdc, script: 0x22, flags: 0x0}, - 524: {region: 0x166, script: 0x5b, flags: 0x0}, - 525: {region: 0x64, script: 0x5b, flags: 0x0}, - 526: {region: 0x96, script: 0x5b, flags: 0x0}, - 527: {region: 0x96, script: 0x5b, flags: 0x0}, - 528: {region: 0x7e, script: 0x2e, flags: 0x0}, - 529: {region: 0x138, script: 0x20, flags: 0x0}, - 530: {region: 0x68, script: 0x5b, flags: 0x0}, - 531: {region: 0xc5, script: 0x5b, flags: 0x0}, - 532: {region: 0x166, script: 0x5b, flags: 0x0}, - 533: {region: 0x166, script: 0x5b, flags: 0x0}, - 534: {region: 0xd7, script: 0x5b, flags: 0x0}, - 535: {region: 0xa5, script: 0x5b, flags: 0x0}, - 536: {region: 0xc4, script: 0x5b, flags: 0x0}, - 537: {region: 0x107, script: 0x20, flags: 0x0}, - 538: {region: 0x166, script: 0x5b, flags: 0x0}, - 539: {region: 0x166, script: 0x5b, flags: 0x0}, - 540: {region: 0x166, script: 0x5b, flags: 0x0}, - 541: {region: 0x166, script: 0x5b, flags: 0x0}, - 542: {region: 0xd5, script: 0x5, flags: 0x0}, - 543: {region: 0xd7, script: 0x5b, flags: 0x0}, - 544: {region: 0x165, script: 0x5b, flags: 0x0}, - 545: {region: 0x166, script: 0x5b, flags: 0x0}, - 546: {region: 0x166, script: 0x5b, flags: 0x0}, - 547: {region: 0x130, script: 0x5b, flags: 0x0}, - 548: {region: 0x123, script: 0x5, flags: 0x0}, - 549: {region: 0x166, script: 0x5b, flags: 0x0}, - 550: {region: 0x124, script: 0xee, flags: 0x0}, - 551: {region: 0x5b, script: 0x5b, flags: 0x0}, - 552: {region: 0x52, script: 0x5b, flags: 0x0}, - 553: {region: 0x166, script: 0x5b, flags: 0x0}, - 554: {region: 0x4f, script: 0x5b, flags: 0x0}, - 555: {region: 0x9a, script: 0x22, flags: 0x0}, - 556: {region: 0x9a, script: 0x22, flags: 0x0}, - 557: {region: 0x4b, script: 0x5b, flags: 0x0}, - 558: {region: 0x96, script: 0x5b, flags: 0x0}, - 559: {region: 0x166, script: 0x5b, flags: 0x0}, - 560: {region: 0x41, script: 0x5b, flags: 0x0}, - 561: {region: 0x9a, script: 0x5b, flags: 0x0}, - 562: {region: 0x53, script: 0xe5, flags: 0x0}, - 563: {region: 0x9a, script: 0x22, flags: 0x0}, - 564: {region: 0xc4, script: 0x5b, flags: 0x0}, - 565: {region: 0x166, script: 0x5b, flags: 0x0}, - 566: {region: 0x9a, script: 0x76, flags: 0x0}, - 567: {region: 0xe9, script: 0x5, flags: 0x0}, - 568: {region: 0x166, script: 0x5b, flags: 0x0}, - 569: {region: 0xa5, script: 0x5b, flags: 0x0}, - 570: {region: 0x166, script: 0x5b, flags: 0x0}, - 571: {region: 0x12c, script: 0x5b, flags: 0x0}, - 572: {region: 0x166, script: 0x5b, flags: 0x0}, - 573: {region: 0xd3, script: 0x5b, flags: 0x0}, - 574: {region: 0x166, script: 0x5b, flags: 0x0}, - 575: {region: 0xb0, script: 0x58, flags: 0x0}, - 576: {region: 0x166, script: 0x5b, flags: 0x0}, - 577: {region: 0x166, script: 0x5b, flags: 0x0}, - 578: {region: 0x13, script: 0x6, flags: 0x1}, - 579: {region: 0x166, script: 0x5b, flags: 0x0}, - 580: {region: 0x52, script: 0x5b, flags: 0x0}, - 581: {region: 0x83, script: 0x5b, flags: 0x0}, - 582: {region: 0xa5, script: 0x5b, flags: 0x0}, - 583: {region: 0x166, script: 0x5b, flags: 0x0}, - 584: {region: 0x166, script: 0x5b, flags: 0x0}, - 585: {region: 0x166, script: 0x5b, flags: 0x0}, - 586: {region: 0xa7, script: 0x4f, flags: 0x0}, - 587: {region: 0x2a, script: 0x5b, flags: 0x0}, - 588: {region: 0x166, script: 0x5b, flags: 0x0}, - 589: {region: 0x166, script: 0x5b, flags: 0x0}, - 590: {region: 0x166, script: 0x5b, flags: 0x0}, - 591: {region: 0x166, script: 0x5b, flags: 0x0}, - 592: {region: 0x166, script: 0x5b, flags: 0x0}, - 593: {region: 0x9a, script: 0x53, flags: 0x0}, - 594: {region: 0x8c, script: 0x5b, flags: 0x0}, - 595: {region: 0x166, script: 0x5b, flags: 0x0}, - 596: {region: 0xac, script: 0x54, flags: 0x0}, - 597: {region: 0x107, script: 0x20, flags: 0x0}, - 598: {region: 0x9a, script: 0x22, flags: 0x0}, - 599: {region: 0x166, script: 0x5b, flags: 0x0}, - 600: {region: 0x76, script: 0x5b, flags: 0x0}, - 601: {region: 0x166, script: 0x5b, flags: 0x0}, - 602: {region: 0xb5, script: 0x5b, flags: 0x0}, - 603: {region: 0x166, script: 0x5b, flags: 0x0}, - 604: {region: 0x166, script: 0x5b, flags: 0x0}, - 605: {region: 0x166, script: 0x5b, flags: 0x0}, - 606: {region: 0x166, script: 0x5b, flags: 0x0}, - 607: {region: 0x166, script: 0x5b, flags: 0x0}, - 608: {region: 0x166, script: 0x5b, flags: 0x0}, - 609: {region: 0x166, script: 0x5b, flags: 0x0}, - 610: {region: 0x166, script: 0x2c, flags: 0x0}, - 611: {region: 0x166, script: 0x5b, flags: 0x0}, - 612: {region: 0x107, script: 0x20, flags: 0x0}, - 613: {region: 0x113, script: 0x5b, flags: 0x0}, - 614: {region: 0xe8, script: 0x5b, flags: 0x0}, - 615: {region: 0x107, script: 0x5b, flags: 0x0}, - 616: {region: 0x166, script: 0x5b, flags: 0x0}, - 617: {region: 0x9a, script: 0x22, flags: 0x0}, - 618: {region: 0x9a, script: 0x5, flags: 0x0}, - 619: {region: 0x130, script: 0x5b, flags: 0x0}, - 620: {region: 0x166, script: 0x5b, flags: 0x0}, - 621: {region: 0x52, script: 0x5b, flags: 0x0}, - 622: {region: 0x61, script: 0x5b, flags: 0x0}, - 623: {region: 0x166, script: 0x5b, flags: 0x0}, - 624: {region: 0x166, script: 0x5b, flags: 0x0}, - 625: {region: 0x166, script: 0x2c, flags: 0x0}, - 626: {region: 0x166, script: 0x5b, flags: 0x0}, - 627: {region: 0x166, script: 0x5b, flags: 0x0}, - 628: {region: 0x19, script: 0x3, flags: 0x1}, - 629: {region: 0x166, script: 0x5b, flags: 0x0}, - 630: {region: 0x166, script: 0x5b, flags: 0x0}, - 631: {region: 0x166, script: 0x5b, flags: 0x0}, - 632: {region: 0x166, script: 0x5b, flags: 0x0}, - 633: {region: 0x107, script: 0x20, flags: 0x0}, - 634: {region: 0x166, script: 0x5b, flags: 0x0}, - 635: {region: 0x166, script: 0x5b, flags: 0x0}, - 636: {region: 0x166, script: 0x5b, flags: 0x0}, - 637: {region: 0x107, script: 0x20, flags: 0x0}, - 638: {region: 0x166, script: 0x5b, flags: 0x0}, - 639: {region: 0x96, script: 0x5b, flags: 0x0}, - 640: {region: 0xe9, script: 0x5, flags: 0x0}, - 641: {region: 0x7c, script: 0x5b, flags: 0x0}, - 642: {region: 0x166, script: 0x5b, flags: 0x0}, - 643: {region: 0x166, script: 0x5b, flags: 0x0}, - 644: {region: 0x166, script: 0x5b, flags: 0x0}, - 645: {region: 0x166, script: 0x2c, flags: 0x0}, - 646: {region: 0x124, script: 0xee, flags: 0x0}, - 647: {region: 0xe9, script: 0x5, flags: 0x0}, - 648: {region: 0x166, script: 0x5b, flags: 0x0}, - 649: {region: 0x166, script: 0x5b, flags: 0x0}, - 650: {region: 0x1c, script: 0x5, flags: 0x1}, - 651: {region: 0x166, script: 0x5b, flags: 0x0}, - 652: {region: 0x166, script: 0x5b, flags: 0x0}, - 653: {region: 0x166, script: 0x5b, flags: 0x0}, - 654: {region: 0x139, script: 0x5b, flags: 0x0}, - 655: {region: 0x88, script: 0x5f, flags: 0x0}, - 656: {region: 0x98, script: 0x3e, flags: 0x0}, - 657: {region: 0x130, script: 0x5b, flags: 0x0}, - 658: {region: 0xe9, script: 0x5, flags: 0x0}, - 659: {region: 0x132, script: 0x5b, flags: 0x0}, - 660: {region: 0x166, script: 0x5b, flags: 0x0}, - 661: {region: 0xb8, script: 0x5b, flags: 0x0}, - 662: {region: 0x107, script: 0x20, flags: 0x0}, - 663: {region: 0x166, script: 0x5b, flags: 0x0}, - 664: {region: 0x96, script: 0x5b, flags: 0x0}, - 665: {region: 0x166, script: 0x5b, flags: 0x0}, - 666: {region: 0x53, script: 0xee, flags: 0x0}, - 667: {region: 0x166, script: 0x5b, flags: 0x0}, - 668: {region: 0x166, script: 0x5b, flags: 0x0}, - 669: {region: 0x166, script: 0x5b, flags: 0x0}, - 670: {region: 0x166, script: 0x5b, flags: 0x0}, - 671: {region: 0x9a, script: 0x5d, flags: 0x0}, - 672: {region: 0x166, script: 0x5b, flags: 0x0}, - 673: {region: 0x166, script: 0x5b, flags: 0x0}, - 674: {region: 0x107, script: 0x20, flags: 0x0}, - 675: {region: 0x132, script: 0x5b, flags: 0x0}, - 676: {region: 0x166, script: 0x5b, flags: 0x0}, - 677: {region: 0xda, script: 0x5b, flags: 0x0}, - 678: {region: 0x166, script: 0x5b, flags: 0x0}, - 679: {region: 0x166, script: 0x5b, flags: 0x0}, - 680: {region: 0x21, script: 0x2, flags: 0x1}, - 681: {region: 0x166, script: 0x5b, flags: 0x0}, - 682: {region: 0x166, script: 0x5b, flags: 0x0}, - 683: {region: 0x9f, script: 0x5b, flags: 0x0}, - 684: {region: 0x53, script: 0x61, flags: 0x0}, - 685: {region: 0x96, script: 0x5b, flags: 0x0}, - 686: {region: 0x9d, script: 0x5, flags: 0x0}, - 687: {region: 0x136, script: 0x5b, flags: 0x0}, - 688: {region: 0x166, script: 0x5b, flags: 0x0}, - 689: {region: 0x166, script: 0x5b, flags: 0x0}, - 690: {region: 0x9a, script: 0xe9, flags: 0x0}, - 691: {region: 0x9f, script: 0x5b, flags: 0x0}, - 692: {region: 0x166, script: 0x5b, flags: 0x0}, - 693: {region: 0x4b, script: 0x5b, flags: 0x0}, - 694: {region: 0x166, script: 0x5b, flags: 0x0}, - 695: {region: 0x166, script: 0x5b, flags: 0x0}, - 696: {region: 0xb0, script: 0x58, flags: 0x0}, - 697: {region: 0x166, script: 0x5b, flags: 0x0}, - 698: {region: 0x166, script: 0x5b, flags: 0x0}, - 699: {region: 0x4b, script: 0x5b, flags: 0x0}, - 700: {region: 0x166, script: 0x5b, flags: 0x0}, - 701: {region: 0x166, script: 0x5b, flags: 0x0}, - 702: {region: 0x163, script: 0x5b, flags: 0x0}, - 703: {region: 0x9d, script: 0x5, flags: 0x0}, - 704: {region: 0xb7, script: 0x5b, flags: 0x0}, - 705: {region: 0xb9, script: 0x5b, flags: 0x0}, - 706: {region: 0x4b, script: 0x5b, flags: 0x0}, - 707: {region: 0x4b, script: 0x5b, flags: 0x0}, - 708: {region: 0xa5, script: 0x5b, flags: 0x0}, - 709: {region: 0xa5, script: 0x5b, flags: 0x0}, - 710: {region: 0x9d, script: 0x5, flags: 0x0}, - 711: {region: 0xb9, script: 0x5b, flags: 0x0}, - 712: {region: 0x124, script: 0xee, flags: 0x0}, - 713: {region: 0x53, script: 0x3b, flags: 0x0}, - 714: {region: 0x12c, script: 0x5b, flags: 0x0}, - 715: {region: 0x96, script: 0x5b, flags: 0x0}, - 716: {region: 0x52, script: 0x5b, flags: 0x0}, - 717: {region: 0x9a, script: 0x22, flags: 0x0}, - 718: {region: 0x9a, script: 0x22, flags: 0x0}, - 719: {region: 0x96, script: 0x5b, flags: 0x0}, - 720: {region: 0x23, script: 0x3, flags: 0x1}, - 721: {region: 0xa5, script: 0x5b, flags: 0x0}, - 722: {region: 0x166, script: 0x5b, flags: 0x0}, - 723: {region: 0xd0, script: 0x5b, flags: 0x0}, - 724: {region: 0x166, script: 0x5b, flags: 0x0}, - 725: {region: 0x166, script: 0x5b, flags: 0x0}, - 726: {region: 0x166, script: 0x5b, flags: 0x0}, - 727: {region: 0x166, script: 0x5b, flags: 0x0}, - 728: {region: 0x166, script: 0x5b, flags: 0x0}, - 729: {region: 0x166, script: 0x5b, flags: 0x0}, - 730: {region: 0x166, script: 0x5b, flags: 0x0}, - 731: {region: 0x166, script: 0x5b, flags: 0x0}, - 732: {region: 0x166, script: 0x5b, flags: 0x0}, - 733: {region: 0x166, script: 0x5b, flags: 0x0}, - 734: {region: 0x166, script: 0x5b, flags: 0x0}, - 735: {region: 0x166, script: 0x5, flags: 0x0}, - 736: {region: 0x107, script: 0x20, flags: 0x0}, - 737: {region: 0xe8, script: 0x5b, flags: 0x0}, - 738: {region: 0x166, script: 0x5b, flags: 0x0}, - 739: {region: 0x96, script: 0x5b, flags: 0x0}, - 740: {region: 0x166, script: 0x2c, flags: 0x0}, - 741: {region: 0x166, script: 0x5b, flags: 0x0}, - 742: {region: 0x166, script: 0x5b, flags: 0x0}, - 743: {region: 0x166, script: 0x5b, flags: 0x0}, - 744: {region: 0x113, script: 0x5b, flags: 0x0}, - 745: {region: 0xa5, script: 0x5b, flags: 0x0}, - 746: {region: 0x166, script: 0x5b, flags: 0x0}, - 747: {region: 0x166, script: 0x5b, flags: 0x0}, - 748: {region: 0x124, script: 0x5, flags: 0x0}, - 749: {region: 0xcd, script: 0x5b, flags: 0x0}, - 750: {region: 0x166, script: 0x5b, flags: 0x0}, - 751: {region: 0x166, script: 0x5b, flags: 0x0}, - 752: {region: 0x166, script: 0x5b, flags: 0x0}, - 753: {region: 0xc0, script: 0x5b, flags: 0x0}, - 754: {region: 0xd2, script: 0x5b, flags: 0x0}, - 755: {region: 0x166, script: 0x5b, flags: 0x0}, - 756: {region: 0x52, script: 0x5b, flags: 0x0}, - 757: {region: 0xdc, script: 0x22, flags: 0x0}, - 758: {region: 0x130, script: 0x5b, flags: 0x0}, - 759: {region: 0xc1, script: 0x5b, flags: 0x0}, - 760: {region: 0x166, script: 0x5b, flags: 0x0}, - 761: {region: 0x166, script: 0x5b, flags: 0x0}, - 762: {region: 0xe1, script: 0x5b, flags: 0x0}, - 763: {region: 0x166, script: 0x5b, flags: 0x0}, - 764: {region: 0x96, script: 0x5b, flags: 0x0}, - 765: {region: 0x9c, script: 0x3d, flags: 0x0}, - 766: {region: 0x166, script: 0x5b, flags: 0x0}, - 767: {region: 0xc3, script: 0x20, flags: 0x0}, - 768: {region: 0x166, script: 0x5, flags: 0x0}, - 769: {region: 0x166, script: 0x5b, flags: 0x0}, - 770: {region: 0x166, script: 0x5b, flags: 0x0}, - 771: {region: 0x166, script: 0x5b, flags: 0x0}, - 772: {region: 0x9a, script: 0x6f, flags: 0x0}, - 773: {region: 0x166, script: 0x5b, flags: 0x0}, - 774: {region: 0x166, script: 0x5b, flags: 0x0}, - 775: {region: 0x10c, script: 0x5b, flags: 0x0}, - 776: {region: 0x166, script: 0x5b, flags: 0x0}, - 777: {region: 0x166, script: 0x5b, flags: 0x0}, - 778: {region: 0x166, script: 0x5b, flags: 0x0}, - 779: {region: 0x26, script: 0x3, flags: 0x1}, - 780: {region: 0x166, script: 0x5b, flags: 0x0}, - 781: {region: 0x166, script: 0x5b, flags: 0x0}, - 782: {region: 0x9a, script: 0xe, flags: 0x0}, - 783: {region: 0xc5, script: 0x76, flags: 0x0}, - 785: {region: 0x166, script: 0x5b, flags: 0x0}, - 786: {region: 0x49, script: 0x5b, flags: 0x0}, - 787: {region: 0x49, script: 0x5b, flags: 0x0}, - 788: {region: 0x37, script: 0x5b, flags: 0x0}, - 789: {region: 0x166, script: 0x5b, flags: 0x0}, - 790: {region: 0x166, script: 0x5b, flags: 0x0}, - 791: {region: 0x166, script: 0x5b, flags: 0x0}, - 792: {region: 0x166, script: 0x5b, flags: 0x0}, - 793: {region: 0x166, script: 0x5b, flags: 0x0}, - 794: {region: 0x166, script: 0x5b, flags: 0x0}, - 795: {region: 0x9a, script: 0x22, flags: 0x0}, - 796: {region: 0xdc, script: 0x22, flags: 0x0}, - 797: {region: 0x107, script: 0x20, flags: 0x0}, - 798: {region: 0x35, script: 0x73, flags: 0x0}, - 799: {region: 0x29, script: 0x3, flags: 0x1}, - 800: {region: 0xcc, script: 0x5b, flags: 0x0}, - 801: {region: 0x166, script: 0x5b, flags: 0x0}, - 802: {region: 0x166, script: 0x5b, flags: 0x0}, - 803: {region: 0x166, script: 0x5b, flags: 0x0}, - 804: {region: 0x9a, script: 0x22, flags: 0x0}, - 805: {region: 0x52, script: 0x5b, flags: 0x0}, - 807: {region: 0x166, script: 0x5b, flags: 0x0}, - 808: {region: 0x136, script: 0x5b, flags: 0x0}, - 809: {region: 0x166, script: 0x5b, flags: 0x0}, - 810: {region: 0x166, script: 0x5b, flags: 0x0}, - 811: {region: 0xe9, script: 0x5, flags: 0x0}, - 812: {region: 0xc4, script: 0x5b, flags: 0x0}, - 813: {region: 0x9a, script: 0x22, flags: 0x0}, - 814: {region: 0x96, script: 0x5b, flags: 0x0}, - 815: {region: 0x165, script: 0x5b, flags: 0x0}, - 816: {region: 0x166, script: 0x5b, flags: 0x0}, - 817: {region: 0xc5, script: 0x76, flags: 0x0}, - 818: {region: 0x166, script: 0x5b, flags: 0x0}, - 819: {region: 0x166, script: 0x2c, flags: 0x0}, - 820: {region: 0x107, script: 0x20, flags: 0x0}, - 821: {region: 0x166, script: 0x5b, flags: 0x0}, - 822: {region: 0x132, script: 0x5b, flags: 0x0}, - 823: {region: 0x9d, script: 0x67, flags: 0x0}, - 824: {region: 0x166, script: 0x5b, flags: 0x0}, - 825: {region: 0x166, script: 0x5b, flags: 0x0}, - 826: {region: 0x9d, script: 0x5, flags: 0x0}, - 827: {region: 0x166, script: 0x5b, flags: 0x0}, - 828: {region: 0x166, script: 0x5b, flags: 0x0}, - 829: {region: 0x166, script: 0x5b, flags: 0x0}, - 830: {region: 0xde, script: 0x5b, flags: 0x0}, - 831: {region: 0x166, script: 0x5b, flags: 0x0}, - 832: {region: 0x166, script: 0x5b, flags: 0x0}, - 834: {region: 0x166, script: 0x5b, flags: 0x0}, - 835: {region: 0x53, script: 0x3b, flags: 0x0}, - 836: {region: 0x9f, script: 0x5b, flags: 0x0}, - 837: {region: 0xd3, script: 0x5b, flags: 0x0}, - 838: {region: 0x166, script: 0x5b, flags: 0x0}, - 839: {region: 0xdb, script: 0x5b, flags: 0x0}, - 840: {region: 0x166, script: 0x5b, flags: 0x0}, - 841: {region: 0x166, script: 0x5b, flags: 0x0}, - 842: {region: 0x166, script: 0x5b, flags: 0x0}, - 843: {region: 0xd0, script: 0x5b, flags: 0x0}, - 844: {region: 0x166, script: 0x5b, flags: 0x0}, - 845: {region: 0x166, script: 0x5b, flags: 0x0}, - 846: {region: 0x165, script: 0x5b, flags: 0x0}, - 847: {region: 0xd2, script: 0x5b, flags: 0x0}, - 848: {region: 0x61, script: 0x5b, flags: 0x0}, - 849: {region: 0xdc, script: 0x22, flags: 0x0}, - 850: {region: 0x166, script: 0x5b, flags: 0x0}, - 851: {region: 0xdc, script: 0x22, flags: 0x0}, - 852: {region: 0x166, script: 0x5b, flags: 0x0}, - 853: {region: 0x166, script: 0x5b, flags: 0x0}, - 854: {region: 0xd3, script: 0x5b, flags: 0x0}, - 855: {region: 0x166, script: 0x5b, flags: 0x0}, - 856: {region: 0x166, script: 0x5b, flags: 0x0}, - 857: {region: 0xd2, script: 0x5b, flags: 0x0}, - 858: {region: 0x166, script: 0x5b, flags: 0x0}, - 859: {region: 0xd0, script: 0x5b, flags: 0x0}, - 860: {region: 0xd0, script: 0x5b, flags: 0x0}, - 861: {region: 0x166, script: 0x5b, flags: 0x0}, - 862: {region: 0x166, script: 0x5b, flags: 0x0}, - 863: {region: 0x96, script: 0x5b, flags: 0x0}, - 864: {region: 0x166, script: 0x5b, flags: 0x0}, - 865: {region: 0xe0, script: 0x5b, flags: 0x0}, - 866: {region: 0x166, script: 0x5b, flags: 0x0}, - 867: {region: 0x166, script: 0x5b, flags: 0x0}, - 868: {region: 0x9a, script: 0x5b, flags: 0x0}, - 869: {region: 0x166, script: 0x5b, flags: 0x0}, - 870: {region: 0x166, script: 0x5b, flags: 0x0}, - 871: {region: 0xda, script: 0x5b, flags: 0x0}, - 872: {region: 0x52, script: 0x5b, flags: 0x0}, - 873: {region: 0x166, script: 0x5b, flags: 0x0}, - 874: {region: 0xdb, script: 0x5b, flags: 0x0}, - 875: {region: 0x166, script: 0x5b, flags: 0x0}, - 876: {region: 0x52, script: 0x5b, flags: 0x0}, - 877: {region: 0x166, script: 0x5b, flags: 0x0}, - 878: {region: 0x166, script: 0x5b, flags: 0x0}, - 879: {region: 0xdb, script: 0x5b, flags: 0x0}, - 880: {region: 0x124, script: 0x57, flags: 0x0}, - 881: {region: 0x9a, script: 0x22, flags: 0x0}, - 882: {region: 0x10d, script: 0xcb, flags: 0x0}, - 883: {region: 0x166, script: 0x5b, flags: 0x0}, - 884: {region: 0x166, script: 0x5b, flags: 0x0}, - 885: {region: 0x85, script: 0x7e, flags: 0x0}, - 886: {region: 0x162, script: 0x5b, flags: 0x0}, - 887: {region: 0x166, script: 0x5b, flags: 0x0}, - 888: {region: 0x49, script: 0x17, flags: 0x0}, - 889: {region: 0x166, script: 0x5b, flags: 0x0}, - 890: {region: 0x162, script: 0x5b, flags: 0x0}, - 891: {region: 0x166, script: 0x5b, flags: 0x0}, - 892: {region: 0x166, script: 0x5b, flags: 0x0}, - 893: {region: 0x166, script: 0x5b, flags: 0x0}, - 894: {region: 0x166, script: 0x5b, flags: 0x0}, - 895: {region: 0x166, script: 0x5b, flags: 0x0}, - 896: {region: 0x118, script: 0x5b, flags: 0x0}, - 897: {region: 0x166, script: 0x5b, flags: 0x0}, - 898: {region: 0x166, script: 0x5b, flags: 0x0}, - 899: {region: 0x136, script: 0x5b, flags: 0x0}, - 900: {region: 0x166, script: 0x5b, flags: 0x0}, - 901: {region: 0x53, script: 0x5b, flags: 0x0}, - 902: {region: 0x166, script: 0x5b, flags: 0x0}, - 903: {region: 0xcf, script: 0x5b, flags: 0x0}, - 904: {region: 0x130, script: 0x5b, flags: 0x0}, - 905: {region: 0x132, script: 0x5b, flags: 0x0}, - 906: {region: 0x81, script: 0x5b, flags: 0x0}, - 907: {region: 0x79, script: 0x5b, flags: 0x0}, - 908: {region: 0x166, script: 0x5b, flags: 0x0}, - 910: {region: 0x166, script: 0x5b, flags: 0x0}, - 911: {region: 0x166, script: 0x5b, flags: 0x0}, - 912: {region: 0x70, script: 0x5b, flags: 0x0}, - 913: {region: 0x166, script: 0x5b, flags: 0x0}, - 914: {region: 0x166, script: 0x5b, flags: 0x0}, - 915: {region: 0x166, script: 0x5b, flags: 0x0}, - 916: {region: 0x166, script: 0x5b, flags: 0x0}, - 917: {region: 0x9a, script: 0x83, flags: 0x0}, - 918: {region: 0x166, script: 0x5b, flags: 0x0}, - 919: {region: 0x166, script: 0x5, flags: 0x0}, - 920: {region: 0x7e, script: 0x20, flags: 0x0}, - 921: {region: 0x136, script: 0x84, flags: 0x0}, - 922: {region: 0x166, script: 0x5, flags: 0x0}, - 923: {region: 0xc6, script: 0x82, flags: 0x0}, - 924: {region: 0x166, script: 0x5b, flags: 0x0}, - 925: {region: 0x2c, script: 0x3, flags: 0x1}, - 926: {region: 0xe8, script: 0x5b, flags: 0x0}, - 927: {region: 0x2f, script: 0x2, flags: 0x1}, - 928: {region: 0xe8, script: 0x5b, flags: 0x0}, - 929: {region: 0x30, script: 0x5b, flags: 0x0}, - 930: {region: 0xf1, script: 0x5b, flags: 0x0}, - 931: {region: 0x166, script: 0x5b, flags: 0x0}, - 932: {region: 0x79, script: 0x5b, flags: 0x0}, - 933: {region: 0xd7, script: 0x5b, flags: 0x0}, - 934: {region: 0x136, script: 0x5b, flags: 0x0}, - 935: {region: 0x49, script: 0x5b, flags: 0x0}, - 936: {region: 0x166, script: 0x5b, flags: 0x0}, - 937: {region: 0x9d, script: 0xfa, flags: 0x0}, - 938: {region: 0x166, script: 0x5b, flags: 0x0}, - 939: {region: 0x61, script: 0x5b, flags: 0x0}, - 940: {region: 0x166, script: 0x5, flags: 0x0}, - 941: {region: 0xb1, script: 0x90, flags: 0x0}, - 943: {region: 0x166, script: 0x5b, flags: 0x0}, - 944: {region: 0x166, script: 0x5b, flags: 0x0}, - 945: {region: 0x9a, script: 0x12, flags: 0x0}, - 946: {region: 0xa5, script: 0x5b, flags: 0x0}, - 947: {region: 0xea, script: 0x5b, flags: 0x0}, - 948: {region: 0x166, script: 0x5b, flags: 0x0}, - 949: {region: 0x9f, script: 0x5b, flags: 0x0}, - 950: {region: 0x166, script: 0x5b, flags: 0x0}, - 951: {region: 0x166, script: 0x5b, flags: 0x0}, - 952: {region: 0x88, script: 0x34, flags: 0x0}, - 953: {region: 0x76, script: 0x5b, flags: 0x0}, - 954: {region: 0x166, script: 0x5b, flags: 0x0}, - 955: {region: 0xe9, script: 0x4e, flags: 0x0}, - 956: {region: 0x9d, script: 0x5, flags: 0x0}, - 957: {region: 0x1, script: 0x5b, flags: 0x0}, - 958: {region: 0x24, script: 0x5, flags: 0x0}, - 959: {region: 0x166, script: 0x5b, flags: 0x0}, - 960: {region: 0x41, script: 0x5b, flags: 0x0}, - 961: {region: 0x166, script: 0x5b, flags: 0x0}, - 962: {region: 0x7b, script: 0x5b, flags: 0x0}, - 963: {region: 0x166, script: 0x5b, flags: 0x0}, - 964: {region: 0xe5, script: 0x5b, flags: 0x0}, - 965: {region: 0x8a, script: 0x5b, flags: 0x0}, - 966: {region: 0x6a, script: 0x5b, flags: 0x0}, - 967: {region: 0x166, script: 0x5b, flags: 0x0}, - 968: {region: 0x9a, script: 0x22, flags: 0x0}, - 969: {region: 0x166, script: 0x5b, flags: 0x0}, - 970: {region: 0x103, script: 0x5b, flags: 0x0}, - 971: {region: 0x96, script: 0x5b, flags: 0x0}, - 972: {region: 0x166, script: 0x5b, flags: 0x0}, - 973: {region: 0x166, script: 0x5b, flags: 0x0}, - 974: {region: 0x9f, script: 0x5b, flags: 0x0}, - 975: {region: 0x166, script: 0x5, flags: 0x0}, - 976: {region: 0x9a, script: 0x5b, flags: 0x0}, - 977: {region: 0x31, script: 0x2, flags: 0x1}, - 978: {region: 0xdc, script: 0x22, flags: 0x0}, - 979: {region: 0x35, script: 0xe, flags: 0x0}, - 980: {region: 0x4e, script: 0x5b, flags: 0x0}, - 981: {region: 0x73, script: 0x5b, flags: 0x0}, - 982: {region: 0x4e, script: 0x5b, flags: 0x0}, - 983: {region: 0x9d, script: 0x5, flags: 0x0}, - 984: {region: 0x10d, script: 0x5b, flags: 0x0}, - 985: {region: 0x3a, script: 0x5b, flags: 0x0}, - 986: {region: 0x166, script: 0x5b, flags: 0x0}, - 987: {region: 0xd2, script: 0x5b, flags: 0x0}, - 988: {region: 0x105, script: 0x5b, flags: 0x0}, - 989: {region: 0x96, script: 0x5b, flags: 0x0}, - 990: {region: 0x130, script: 0x5b, flags: 0x0}, - 991: {region: 0x166, script: 0x5b, flags: 0x0}, - 992: {region: 0x166, script: 0x5b, flags: 0x0}, - 993: {region: 0x74, script: 0x5b, flags: 0x0}, - 994: {region: 0x107, script: 0x20, flags: 0x0}, - 995: {region: 0x131, script: 0x20, flags: 0x0}, - 996: {region: 0x10a, script: 0x5b, flags: 0x0}, - 997: {region: 0x108, script: 0x5b, flags: 0x0}, - 998: {region: 0x130, script: 0x5b, flags: 0x0}, - 999: {region: 0x166, script: 0x5b, flags: 0x0}, - 1000: {region: 0xa3, script: 0x4c, flags: 0x0}, - 1001: {region: 0x9a, script: 0x22, flags: 0x0}, - 1002: {region: 0x81, script: 0x5b, flags: 0x0}, - 1003: {region: 0x107, script: 0x20, flags: 0x0}, - 1004: {region: 0xa5, script: 0x5b, flags: 0x0}, - 1005: {region: 0x96, script: 0x5b, flags: 0x0}, - 1006: {region: 0x9a, script: 0x5b, flags: 0x0}, - 1007: {region: 0x115, script: 0x5b, flags: 0x0}, - 1008: {region: 0x9a, script: 0xcf, flags: 0x0}, - 1009: {region: 0x166, script: 0x5b, flags: 0x0}, - 1010: {region: 0x166, script: 0x5b, flags: 0x0}, - 1011: {region: 0x130, script: 0x5b, flags: 0x0}, - 1012: {region: 0x9f, script: 0x5b, flags: 0x0}, - 1013: {region: 0x9a, script: 0x22, flags: 0x0}, - 1014: {region: 0x166, script: 0x5, flags: 0x0}, - 1015: {region: 0x9f, script: 0x5b, flags: 0x0}, - 1016: {region: 0x7c, script: 0x5b, flags: 0x0}, - 1017: {region: 0x49, script: 0x5b, flags: 0x0}, - 1018: {region: 0x33, script: 0x4, flags: 0x1}, - 1019: {region: 0x9f, script: 0x5b, flags: 0x0}, - 1020: {region: 0x9d, script: 0x5, flags: 0x0}, - 1021: {region: 0xdb, script: 0x5b, flags: 0x0}, - 1022: {region: 0x4f, script: 0x5b, flags: 0x0}, - 1023: {region: 0xd2, script: 0x5b, flags: 0x0}, - 1024: {region: 0xd0, script: 0x5b, flags: 0x0}, - 1025: {region: 0xc4, script: 0x5b, flags: 0x0}, - 1026: {region: 0x4c, script: 0x5b, flags: 0x0}, - 1027: {region: 0x97, script: 0x80, flags: 0x0}, - 1028: {region: 0xb7, script: 0x5b, flags: 0x0}, - 1029: {region: 0x166, script: 0x2c, flags: 0x0}, - 1030: {region: 0x166, script: 0x5b, flags: 0x0}, - 1032: {region: 0xbb, script: 0xeb, flags: 0x0}, - 1033: {region: 0x166, script: 0x5b, flags: 0x0}, - 1034: {region: 0xc5, script: 0x76, flags: 0x0}, - 1035: {region: 0x166, script: 0x5, flags: 0x0}, - 1036: {region: 0xb4, script: 0xd6, flags: 0x0}, - 1037: {region: 0x70, script: 0x5b, flags: 0x0}, - 1038: {region: 0x166, script: 0x5b, flags: 0x0}, - 1039: {region: 0x166, script: 0x5b, flags: 0x0}, - 1040: {region: 0x166, script: 0x5b, flags: 0x0}, - 1041: {region: 0x166, script: 0x5b, flags: 0x0}, - 1042: {region: 0x112, script: 0x5b, flags: 0x0}, - 1043: {region: 0x166, script: 0x5b, flags: 0x0}, - 1044: {region: 0xe9, script: 0x5, flags: 0x0}, - 1045: {region: 0x166, script: 0x5b, flags: 0x0}, - 1046: {region: 0x110, script: 0x5b, flags: 0x0}, - 1047: {region: 0x166, script: 0x5b, flags: 0x0}, - 1048: {region: 0xea, script: 0x5b, flags: 0x0}, - 1049: {region: 0x166, script: 0x5b, flags: 0x0}, - 1050: {region: 0x96, script: 0x5b, flags: 0x0}, - 1051: {region: 0x143, script: 0x5b, flags: 0x0}, - 1052: {region: 0x10d, script: 0x5b, flags: 0x0}, - 1054: {region: 0x10d, script: 0x5b, flags: 0x0}, - 1055: {region: 0x73, script: 0x5b, flags: 0x0}, - 1056: {region: 0x98, script: 0xcc, flags: 0x0}, - 1057: {region: 0x166, script: 0x5b, flags: 0x0}, - 1058: {region: 0x73, script: 0x5b, flags: 0x0}, - 1059: {region: 0x165, script: 0x5b, flags: 0x0}, - 1060: {region: 0x166, script: 0x5b, flags: 0x0}, - 1061: {region: 0xc4, script: 0x5b, flags: 0x0}, - 1062: {region: 0x166, script: 0x5b, flags: 0x0}, - 1063: {region: 0x166, script: 0x5b, flags: 0x0}, - 1064: {region: 0x166, script: 0x5b, flags: 0x0}, - 1065: {region: 0x116, script: 0x5b, flags: 0x0}, - 1066: {region: 0x166, script: 0x5b, flags: 0x0}, - 1067: {region: 0x166, script: 0x5b, flags: 0x0}, - 1068: {region: 0x124, script: 0xee, flags: 0x0}, - 1069: {region: 0x166, script: 0x5b, flags: 0x0}, - 1070: {region: 0x166, script: 0x5b, flags: 0x0}, - 1071: {region: 0x166, script: 0x5b, flags: 0x0}, - 1072: {region: 0x166, script: 0x5b, flags: 0x0}, - 1073: {region: 0x27, script: 0x5b, flags: 0x0}, - 1074: {region: 0x37, script: 0x5, flags: 0x1}, - 1075: {region: 0x9a, script: 0xd9, flags: 0x0}, - 1076: {region: 0x117, script: 0x5b, flags: 0x0}, - 1077: {region: 0x115, script: 0x5b, flags: 0x0}, - 1078: {region: 0x9a, script: 0x22, flags: 0x0}, - 1079: {region: 0x162, script: 0x5b, flags: 0x0}, - 1080: {region: 0x166, script: 0x5b, flags: 0x0}, - 1081: {region: 0x166, script: 0x5b, flags: 0x0}, - 1082: {region: 0x6e, script: 0x5b, flags: 0x0}, - 1083: {region: 0x162, script: 0x5b, flags: 0x0}, - 1084: {region: 0x166, script: 0x5b, flags: 0x0}, - 1085: {region: 0x61, script: 0x5b, flags: 0x0}, - 1086: {region: 0x96, script: 0x5b, flags: 0x0}, - 1087: {region: 0x166, script: 0x5b, flags: 0x0}, - 1088: {region: 0x166, script: 0x5b, flags: 0x0}, - 1089: {region: 0x130, script: 0x5b, flags: 0x0}, - 1090: {region: 0x166, script: 0x5b, flags: 0x0}, - 1091: {region: 0x85, script: 0x5b, flags: 0x0}, - 1092: {region: 0x10d, script: 0x5b, flags: 0x0}, - 1093: {region: 0x130, script: 0x5b, flags: 0x0}, - 1094: {region: 0x160, script: 0x5, flags: 0x0}, - 1095: {region: 0x4b, script: 0x5b, flags: 0x0}, - 1096: {region: 0x61, script: 0x5b, flags: 0x0}, - 1097: {region: 0x166, script: 0x5b, flags: 0x0}, - 1098: {region: 0x9a, script: 0x22, flags: 0x0}, - 1099: {region: 0x96, script: 0x5b, flags: 0x0}, - 1100: {region: 0x166, script: 0x5b, flags: 0x0}, - 1101: {region: 0x35, script: 0xe, flags: 0x0}, - 1102: {region: 0x9c, script: 0xde, flags: 0x0}, - 1103: {region: 0xea, script: 0x5b, flags: 0x0}, - 1104: {region: 0x9a, script: 0xe6, flags: 0x0}, - 1105: {region: 0xdc, script: 0x22, flags: 0x0}, - 1106: {region: 0x166, script: 0x5b, flags: 0x0}, - 1107: {region: 0x166, script: 0x5b, flags: 0x0}, - 1108: {region: 0x166, script: 0x5b, flags: 0x0}, - 1109: {region: 0x166, script: 0x5b, flags: 0x0}, - 1110: {region: 0x166, script: 0x5b, flags: 0x0}, - 1111: {region: 0x166, script: 0x5b, flags: 0x0}, - 1112: {region: 0x166, script: 0x5b, flags: 0x0}, - 1113: {region: 0x166, script: 0x5b, flags: 0x0}, - 1114: {region: 0xe8, script: 0x5b, flags: 0x0}, - 1115: {region: 0x166, script: 0x5b, flags: 0x0}, - 1116: {region: 0x166, script: 0x5b, flags: 0x0}, - 1117: {region: 0x9a, script: 0x53, flags: 0x0}, - 1118: {region: 0x53, script: 0xe4, flags: 0x0}, - 1119: {region: 0xdc, script: 0x22, flags: 0x0}, - 1120: {region: 0xdc, script: 0x22, flags: 0x0}, - 1121: {region: 0x9a, script: 0xe9, flags: 0x0}, - 1122: {region: 0x166, script: 0x5b, flags: 0x0}, - 1123: {region: 0x113, script: 0x5b, flags: 0x0}, - 1124: {region: 0x132, script: 0x5b, flags: 0x0}, - 1125: {region: 0x127, script: 0x5b, flags: 0x0}, - 1126: {region: 0x166, script: 0x5b, flags: 0x0}, - 1127: {region: 0x3c, script: 0x3, flags: 0x1}, - 1128: {region: 0x166, script: 0x5b, flags: 0x0}, - 1129: {region: 0x166, script: 0x5b, flags: 0x0}, - 1130: {region: 0x166, script: 0x5b, flags: 0x0}, - 1131: {region: 0x124, script: 0xee, flags: 0x0}, - 1132: {region: 0xdc, script: 0x22, flags: 0x0}, - 1133: {region: 0xdc, script: 0x22, flags: 0x0}, - 1134: {region: 0xdc, script: 0x22, flags: 0x0}, - 1135: {region: 0x70, script: 0x2c, flags: 0x0}, - 1136: {region: 0x166, script: 0x5b, flags: 0x0}, - 1137: {region: 0x6e, script: 0x2c, flags: 0x0}, - 1138: {region: 0x166, script: 0x5b, flags: 0x0}, - 1139: {region: 0x166, script: 0x5b, flags: 0x0}, - 1140: {region: 0x166, script: 0x5b, flags: 0x0}, - 1141: {region: 0xd7, script: 0x5b, flags: 0x0}, - 1142: {region: 0x128, script: 0x5b, flags: 0x0}, - 1143: {region: 0x126, script: 0x5b, flags: 0x0}, - 1144: {region: 0x32, script: 0x5b, flags: 0x0}, - 1145: {region: 0xdc, script: 0x22, flags: 0x0}, - 1146: {region: 0xe8, script: 0x5b, flags: 0x0}, - 1147: {region: 0x166, script: 0x5b, flags: 0x0}, - 1148: {region: 0x166, script: 0x5b, flags: 0x0}, - 1149: {region: 0x32, script: 0x5b, flags: 0x0}, - 1150: {region: 0xd5, script: 0x5b, flags: 0x0}, - 1151: {region: 0x166, script: 0x5b, flags: 0x0}, - 1152: {region: 0x162, script: 0x5b, flags: 0x0}, - 1153: {region: 0x166, script: 0x5b, flags: 0x0}, - 1154: {region: 0x12a, script: 0x5b, flags: 0x0}, - 1155: {region: 0x166, script: 0x5b, flags: 0x0}, - 1156: {region: 0xcf, script: 0x5b, flags: 0x0}, - 1157: {region: 0x166, script: 0x5b, flags: 0x0}, - 1158: {region: 0xe7, script: 0x5b, flags: 0x0}, - 1159: {region: 0x166, script: 0x5b, flags: 0x0}, - 1160: {region: 0x166, script: 0x5b, flags: 0x0}, - 1161: {region: 0x166, script: 0x5b, flags: 0x0}, - 1162: {region: 0x12c, script: 0x5b, flags: 0x0}, - 1163: {region: 0x12c, script: 0x5b, flags: 0x0}, - 1164: {region: 0x12f, script: 0x5b, flags: 0x0}, - 1165: {region: 0x166, script: 0x5, flags: 0x0}, - 1166: {region: 0x162, script: 0x5b, flags: 0x0}, - 1167: {region: 0x88, script: 0x34, flags: 0x0}, - 1168: {region: 0xdc, script: 0x22, flags: 0x0}, - 1169: {region: 0xe8, script: 0x5b, flags: 0x0}, - 1170: {region: 0x43, script: 0xef, flags: 0x0}, - 1171: {region: 0x166, script: 0x5b, flags: 0x0}, - 1172: {region: 0x107, script: 0x20, flags: 0x0}, - 1173: {region: 0x166, script: 0x5b, flags: 0x0}, - 1174: {region: 0x166, script: 0x5b, flags: 0x0}, - 1175: {region: 0x132, script: 0x5b, flags: 0x0}, - 1176: {region: 0x166, script: 0x5b, flags: 0x0}, - 1177: {region: 0x124, script: 0xee, flags: 0x0}, - 1178: {region: 0x32, script: 0x5b, flags: 0x0}, - 1179: {region: 0x166, script: 0x5b, flags: 0x0}, - 1180: {region: 0x166, script: 0x5b, flags: 0x0}, - 1181: {region: 0xcf, script: 0x5b, flags: 0x0}, - 1182: {region: 0x166, script: 0x5b, flags: 0x0}, - 1183: {region: 0x166, script: 0x5b, flags: 0x0}, - 1184: {region: 0x12e, script: 0x5b, flags: 0x0}, - 1185: {region: 0x166, script: 0x5b, flags: 0x0}, - 1187: {region: 0x166, script: 0x5b, flags: 0x0}, - 1188: {region: 0xd5, script: 0x5b, flags: 0x0}, - 1189: {region: 0x53, script: 0xe7, flags: 0x0}, - 1190: {region: 0xe6, script: 0x5b, flags: 0x0}, - 1191: {region: 0x166, script: 0x5b, flags: 0x0}, - 1192: {region: 0x107, script: 0x20, flags: 0x0}, - 1193: {region: 0xbb, script: 0x5b, flags: 0x0}, - 1194: {region: 0x166, script: 0x5b, flags: 0x0}, - 1195: {region: 0x107, script: 0x20, flags: 0x0}, - 1196: {region: 0x3f, script: 0x4, flags: 0x1}, - 1197: {region: 0x11d, script: 0xf3, flags: 0x0}, - 1198: {region: 0x131, script: 0x20, flags: 0x0}, - 1199: {region: 0x76, script: 0x5b, flags: 0x0}, - 1200: {region: 0x2a, script: 0x5b, flags: 0x0}, - 1202: {region: 0x43, script: 0x3, flags: 0x1}, - 1203: {region: 0x9a, script: 0xe, flags: 0x0}, - 1204: {region: 0xe9, script: 0x5, flags: 0x0}, - 1205: {region: 0x166, script: 0x5b, flags: 0x0}, - 1206: {region: 0x166, script: 0x5b, flags: 0x0}, - 1207: {region: 0x166, script: 0x5b, flags: 0x0}, - 1208: {region: 0x166, script: 0x5b, flags: 0x0}, - 1209: {region: 0x166, script: 0x5b, flags: 0x0}, - 1210: {region: 0x166, script: 0x5b, flags: 0x0}, - 1211: {region: 0x166, script: 0x5b, flags: 0x0}, - 1212: {region: 0x46, script: 0x4, flags: 0x1}, - 1213: {region: 0x166, script: 0x5b, flags: 0x0}, - 1214: {region: 0xb5, script: 0xf4, flags: 0x0}, - 1215: {region: 0x166, script: 0x5b, flags: 0x0}, - 1216: {region: 0x162, script: 0x5b, flags: 0x0}, - 1217: {region: 0x9f, script: 0x5b, flags: 0x0}, - 1218: {region: 0x107, script: 0x5b, flags: 0x0}, - 1219: {region: 0x13f, script: 0x5b, flags: 0x0}, - 1220: {region: 0x11c, script: 0x5b, flags: 0x0}, - 1221: {region: 0x166, script: 0x5b, flags: 0x0}, - 1222: {region: 0x36, script: 0x5b, flags: 0x0}, - 1223: {region: 0x61, script: 0x5b, flags: 0x0}, - 1224: {region: 0xd2, script: 0x5b, flags: 0x0}, - 1225: {region: 0x1, script: 0x5b, flags: 0x0}, - 1226: {region: 0x107, script: 0x5b, flags: 0x0}, - 1227: {region: 0x6b, script: 0x5b, flags: 0x0}, - 1228: {region: 0x130, script: 0x5b, flags: 0x0}, - 1229: {region: 0x166, script: 0x5b, flags: 0x0}, - 1230: {region: 0x36, script: 0x5b, flags: 0x0}, - 1231: {region: 0x4e, script: 0x5b, flags: 0x0}, - 1232: {region: 0x166, script: 0x5b, flags: 0x0}, - 1233: {region: 0x70, script: 0x2c, flags: 0x0}, - 1234: {region: 0x166, script: 0x5b, flags: 0x0}, - 1235: {region: 0xe8, script: 0x5b, flags: 0x0}, - 1236: {region: 0x2f, script: 0x5b, flags: 0x0}, - 1237: {region: 0x9a, script: 0xe9, flags: 0x0}, - 1238: {region: 0x9a, script: 0x22, flags: 0x0}, - 1239: {region: 0x166, script: 0x5b, flags: 0x0}, - 1240: {region: 0x166, script: 0x5b, flags: 0x0}, - 1241: {region: 0x166, script: 0x5b, flags: 0x0}, - 1242: {region: 0x166, script: 0x5b, flags: 0x0}, - 1243: {region: 0x166, script: 0x5b, flags: 0x0}, - 1244: {region: 0x166, script: 0x5b, flags: 0x0}, - 1245: {region: 0x166, script: 0x5b, flags: 0x0}, - 1246: {region: 0x166, script: 0x5b, flags: 0x0}, - 1247: {region: 0x166, script: 0x5b, flags: 0x0}, - 1248: {region: 0x141, script: 0x5b, flags: 0x0}, - 1249: {region: 0x166, script: 0x5b, flags: 0x0}, - 1250: {region: 0x166, script: 0x5b, flags: 0x0}, - 1251: {region: 0xa9, script: 0x5, flags: 0x0}, - 1252: {region: 0x166, script: 0x5b, flags: 0x0}, - 1253: {region: 0x115, script: 0x5b, flags: 0x0}, - 1254: {region: 0x166, script: 0x5b, flags: 0x0}, - 1255: {region: 0x166, script: 0x5b, flags: 0x0}, - 1256: {region: 0x166, script: 0x5b, flags: 0x0}, - 1257: {region: 0x166, script: 0x5b, flags: 0x0}, - 1258: {region: 0x9a, script: 0x22, flags: 0x0}, - 1259: {region: 0x53, script: 0x3b, flags: 0x0}, - 1260: {region: 0x166, script: 0x5b, flags: 0x0}, - 1261: {region: 0x166, script: 0x5b, flags: 0x0}, - 1262: {region: 0x41, script: 0x5b, flags: 0x0}, - 1263: {region: 0x166, script: 0x5b, flags: 0x0}, - 1264: {region: 0x12c, script: 0x18, flags: 0x0}, - 1265: {region: 0x166, script: 0x5b, flags: 0x0}, - 1266: {region: 0x162, script: 0x5b, flags: 0x0}, - 1267: {region: 0x166, script: 0x5b, flags: 0x0}, - 1268: {region: 0x12c, script: 0x63, flags: 0x0}, - 1269: {region: 0x12c, script: 0x64, flags: 0x0}, - 1270: {region: 0x7e, script: 0x2e, flags: 0x0}, - 1271: {region: 0x53, script: 0x68, flags: 0x0}, - 1272: {region: 0x10c, script: 0x6d, flags: 0x0}, - 1273: {region: 0x109, script: 0x79, flags: 0x0}, - 1274: {region: 0x9a, script: 0x22, flags: 0x0}, - 1275: {region: 0x132, script: 0x5b, flags: 0x0}, - 1276: {region: 0x166, script: 0x5b, flags: 0x0}, - 1277: {region: 0x9d, script: 0x93, flags: 0x0}, - 1278: {region: 0x166, script: 0x5b, flags: 0x0}, - 1279: {region: 0x15f, script: 0xce, flags: 0x0}, - 1280: {region: 0x166, script: 0x5b, flags: 0x0}, - 1281: {region: 0x166, script: 0x5b, flags: 0x0}, - 1282: {region: 0xdc, script: 0x22, flags: 0x0}, - 1283: {region: 0x166, script: 0x5b, flags: 0x0}, - 1284: {region: 0x166, script: 0x5b, flags: 0x0}, - 1285: {region: 0xd2, script: 0x5b, flags: 0x0}, - 1286: {region: 0x76, script: 0x5b, flags: 0x0}, - 1287: {region: 0x166, script: 0x5b, flags: 0x0}, - 1288: {region: 0x166, script: 0x5b, flags: 0x0}, - 1289: {region: 0x52, script: 0x5b, flags: 0x0}, - 1290: {region: 0x166, script: 0x5b, flags: 0x0}, - 1291: {region: 0x166, script: 0x5b, flags: 0x0}, - 1292: {region: 0x166, script: 0x5b, flags: 0x0}, - 1293: {region: 0x52, script: 0x5b, flags: 0x0}, - 1294: {region: 0x166, script: 0x5b, flags: 0x0}, - 1295: {region: 0x166, script: 0x5b, flags: 0x0}, - 1296: {region: 0x166, script: 0x5b, flags: 0x0}, - 1297: {region: 0x166, script: 0x5b, flags: 0x0}, - 1298: {region: 0x1, script: 0x3e, flags: 0x0}, - 1299: {region: 0x166, script: 0x5b, flags: 0x0}, - 1300: {region: 0x166, script: 0x5b, flags: 0x0}, - 1301: {region: 0x166, script: 0x5b, flags: 0x0}, - 1302: {region: 0x166, script: 0x5b, flags: 0x0}, - 1303: {region: 0x166, script: 0x5b, flags: 0x0}, - 1304: {region: 0xd7, script: 0x5b, flags: 0x0}, - 1305: {region: 0x166, script: 0x5b, flags: 0x0}, - 1306: {region: 0x166, script: 0x5b, flags: 0x0}, - 1307: {region: 0x166, script: 0x5b, flags: 0x0}, - 1308: {region: 0x41, script: 0x5b, flags: 0x0}, - 1309: {region: 0x166, script: 0x5b, flags: 0x0}, - 1310: {region: 0xd0, script: 0x5b, flags: 0x0}, - 1311: {region: 0x4a, script: 0x3, flags: 0x1}, - 1312: {region: 0x166, script: 0x5b, flags: 0x0}, - 1313: {region: 0x166, script: 0x5b, flags: 0x0}, - 1314: {region: 0x166, script: 0x5b, flags: 0x0}, - 1315: {region: 0x53, script: 0x5b, flags: 0x0}, - 1316: {region: 0x10c, script: 0x5b, flags: 0x0}, - 1318: {region: 0xa9, script: 0x5, flags: 0x0}, - 1319: {region: 0xda, script: 0x5b, flags: 0x0}, - 1320: {region: 0xbb, script: 0xeb, flags: 0x0}, - 1321: {region: 0x4d, script: 0x14, flags: 0x1}, - 1322: {region: 0x53, script: 0x7f, flags: 0x0}, - 1323: {region: 0x166, script: 0x5b, flags: 0x0}, - 1324: {region: 0x123, script: 0x5b, flags: 0x0}, - 1325: {region: 0xd1, script: 0x5b, flags: 0x0}, - 1326: {region: 0x166, script: 0x5b, flags: 0x0}, - 1327: {region: 0x162, script: 0x5b, flags: 0x0}, - 1329: {region: 0x12c, script: 0x5b, flags: 0x0}, -} - -// likelyLangList holds lists info associated with likelyLang. -// Size: 582 bytes, 97 elements -var likelyLangList = [97]likelyScriptRegion{ - 0: {region: 0x9d, script: 0x7, flags: 0x0}, - 1: {region: 0xa2, script: 0x7a, flags: 0x2}, - 2: {region: 0x11d, script: 0x87, flags: 0x2}, - 3: {region: 0x32, script: 0x5b, flags: 0x0}, - 4: {region: 0x9c, script: 0x5, flags: 0x4}, - 5: {region: 0x9d, script: 0x5, flags: 0x4}, - 6: {region: 0x107, script: 0x20, flags: 0x4}, - 7: {region: 0x9d, script: 0x5, flags: 0x2}, - 8: {region: 0x107, script: 0x20, flags: 0x0}, - 9: {region: 0x38, script: 0x2f, flags: 0x2}, - 10: {region: 0x136, script: 0x5b, flags: 0x0}, - 11: {region: 0x7c, script: 0xd1, flags: 0x2}, - 12: {region: 0x115, script: 0x5b, flags: 0x0}, - 13: {region: 0x85, script: 0x1, flags: 0x2}, - 14: {region: 0x5e, script: 0x1f, flags: 0x0}, - 15: {region: 0x88, script: 0x60, flags: 0x2}, - 16: {region: 0xd7, script: 0x5b, flags: 0x0}, - 17: {region: 0x52, script: 0x5, flags: 0x4}, - 18: {region: 0x10c, script: 0x5, flags: 0x4}, - 19: {region: 0xaf, script: 0x20, flags: 0x0}, - 20: {region: 0x24, script: 0x5, flags: 0x4}, - 21: {region: 0x53, script: 0x5, flags: 0x4}, - 22: {region: 0x9d, script: 0x5, flags: 0x4}, - 23: {region: 0xc6, script: 0x5, flags: 0x4}, - 24: {region: 0x53, script: 0x5, flags: 0x2}, - 25: {region: 0x12c, script: 0x5b, flags: 0x0}, - 26: {region: 0xb1, script: 0x5, flags: 0x4}, - 27: {region: 0x9c, script: 0x5, flags: 0x2}, - 28: {region: 0xa6, script: 0x20, flags: 0x0}, - 29: {region: 0x53, script: 0x5, flags: 0x4}, - 30: {region: 0x12c, script: 0x5b, flags: 0x4}, - 31: {region: 0x53, script: 0x5, flags: 0x2}, - 32: {region: 0x12c, script: 0x5b, flags: 0x2}, - 33: {region: 0xdc, script: 0x22, flags: 0x0}, - 34: {region: 0x9a, script: 0x5e, flags: 0x2}, - 35: {region: 0x84, script: 0x5b, flags: 0x0}, - 36: {region: 0x85, script: 0x7e, flags: 0x4}, - 37: {region: 0x85, script: 0x7e, flags: 0x2}, - 38: {region: 0xc6, script: 0x20, flags: 0x0}, - 39: {region: 0x53, script: 0x71, flags: 0x4}, - 40: {region: 0x53, script: 0x71, flags: 0x2}, - 41: {region: 0xd1, script: 0x5b, flags: 0x0}, - 42: {region: 0x4a, script: 0x5, flags: 0x4}, - 43: {region: 0x96, script: 0x5, flags: 0x4}, - 44: {region: 0x9a, script: 0x36, flags: 0x0}, - 45: {region: 0xe9, script: 0x5, flags: 0x4}, - 46: {region: 0xe9, script: 0x5, flags: 0x2}, - 47: {region: 0x9d, script: 0x8d, flags: 0x0}, - 48: {region: 0x53, script: 0x8e, flags: 0x2}, - 49: {region: 0xbb, script: 0xeb, flags: 0x0}, - 50: {region: 0xda, script: 0x5b, flags: 0x4}, - 51: {region: 0xe9, script: 0x5, flags: 0x0}, - 52: {region: 0x9a, script: 0x22, flags: 0x2}, - 53: {region: 0x9a, script: 0x50, flags: 0x2}, - 54: {region: 0x9a, script: 0xd5, flags: 0x2}, - 55: {region: 0x106, script: 0x20, flags: 0x0}, - 56: {region: 0xbe, script: 0x5b, flags: 0x4}, - 57: {region: 0x105, script: 0x5b, flags: 0x4}, - 58: {region: 0x107, script: 0x5b, flags: 0x4}, - 59: {region: 0x12c, script: 0x5b, flags: 0x4}, - 60: {region: 0x125, script: 0x20, flags: 0x0}, - 61: {region: 0xe9, script: 0x5, flags: 0x4}, - 62: {region: 0xe9, script: 0x5, flags: 0x2}, - 63: {region: 0x53, script: 0x5, flags: 0x0}, - 64: {region: 0xaf, script: 0x20, flags: 0x4}, - 65: {region: 0xc6, script: 0x20, flags: 0x4}, - 66: {region: 0xaf, script: 0x20, flags: 0x2}, - 67: {region: 0x9a, script: 0xe, flags: 0x0}, - 68: {region: 0xdc, script: 0x22, flags: 0x4}, - 69: {region: 0xdc, script: 0x22, flags: 0x2}, - 70: {region: 0x138, script: 0x5b, flags: 0x0}, - 71: {region: 0x24, script: 0x5, flags: 0x4}, - 72: {region: 0x53, script: 0x20, flags: 0x4}, - 73: {region: 0x24, script: 0x5, flags: 0x2}, - 74: {region: 0x8e, script: 0x3c, flags: 0x0}, - 75: {region: 0x53, script: 0x3b, flags: 0x4}, - 76: {region: 0x53, script: 0x3b, flags: 0x2}, - 77: {region: 0x53, script: 0x3b, flags: 0x0}, - 78: {region: 0x2f, script: 0x3c, flags: 0x4}, - 79: {region: 0x3e, script: 0x3c, flags: 0x4}, - 80: {region: 0x7c, script: 0x3c, flags: 0x4}, - 81: {region: 0x7f, script: 0x3c, flags: 0x4}, - 82: {region: 0x8e, script: 0x3c, flags: 0x4}, - 83: {region: 0x96, script: 0x3c, flags: 0x4}, - 84: {region: 0xc7, script: 0x3c, flags: 0x4}, - 85: {region: 0xd1, script: 0x3c, flags: 0x4}, - 86: {region: 0xe3, script: 0x3c, flags: 0x4}, - 87: {region: 0xe6, script: 0x3c, flags: 0x4}, - 88: {region: 0xe8, script: 0x3c, flags: 0x4}, - 89: {region: 0x117, script: 0x3c, flags: 0x4}, - 90: {region: 0x124, script: 0x3c, flags: 0x4}, - 91: {region: 0x12f, script: 0x3c, flags: 0x4}, - 92: {region: 0x136, script: 0x3c, flags: 0x4}, - 93: {region: 0x13f, script: 0x3c, flags: 0x4}, - 94: {region: 0x12f, script: 0x11, flags: 0x2}, - 95: {region: 0x12f, script: 0x37, flags: 0x2}, - 96: {region: 0x12f, script: 0x3c, flags: 0x2}, -} - -type likelyLangScript struct { - lang uint16 - script uint16 - flags uint8 -} - -// likelyRegion is a lookup table, indexed by regionID, for the most likely -// languages and scripts given incomplete information. If more entries exist -// for a given regionID, lang and script are the index and size respectively -// of the list in likelyRegionList. -// TODO: exclude containers and user-definable regions from the list. -// Size: 2154 bytes, 359 elements -var likelyRegion = [359]likelyLangScript{ - 34: {lang: 0xd7, script: 0x5b, flags: 0x0}, - 35: {lang: 0x3a, script: 0x5, flags: 0x0}, - 36: {lang: 0x0, script: 0x2, flags: 0x1}, - 39: {lang: 0x2, script: 0x2, flags: 0x1}, - 40: {lang: 0x4, script: 0x2, flags: 0x1}, - 42: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 43: {lang: 0x0, script: 0x5b, flags: 0x0}, - 44: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 45: {lang: 0x41b, script: 0x5b, flags: 0x0}, - 46: {lang: 0x10d, script: 0x5b, flags: 0x0}, - 48: {lang: 0x367, script: 0x5b, flags: 0x0}, - 49: {lang: 0x444, script: 0x5b, flags: 0x0}, - 50: {lang: 0x58, script: 0x5b, flags: 0x0}, - 51: {lang: 0x6, script: 0x2, flags: 0x1}, - 53: {lang: 0xa5, script: 0xe, flags: 0x0}, - 54: {lang: 0x367, script: 0x5b, flags: 0x0}, - 55: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 56: {lang: 0x7e, script: 0x20, flags: 0x0}, - 57: {lang: 0x3a, script: 0x5, flags: 0x0}, - 58: {lang: 0x3d9, script: 0x5b, flags: 0x0}, - 59: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 60: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 62: {lang: 0x31f, script: 0x5b, flags: 0x0}, - 63: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 64: {lang: 0x3a1, script: 0x5b, flags: 0x0}, - 65: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 67: {lang: 0x8, script: 0x2, flags: 0x1}, - 69: {lang: 0x0, script: 0x5b, flags: 0x0}, - 71: {lang: 0x71, script: 0x20, flags: 0x0}, - 73: {lang: 0x512, script: 0x3e, flags: 0x2}, - 74: {lang: 0x31f, script: 0x5, flags: 0x2}, - 75: {lang: 0x445, script: 0x5b, flags: 0x0}, - 76: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 77: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 78: {lang: 0x10d, script: 0x5b, flags: 0x0}, - 79: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 81: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 82: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 83: {lang: 0xa, script: 0x4, flags: 0x1}, - 84: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 85: {lang: 0x0, script: 0x5b, flags: 0x0}, - 87: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 90: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 91: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 92: {lang: 0x3a1, script: 0x5b, flags: 0x0}, - 94: {lang: 0xe, script: 0x2, flags: 0x1}, - 95: {lang: 0xfa, script: 0x5b, flags: 0x0}, - 97: {lang: 0x10d, script: 0x5b, flags: 0x0}, - 99: {lang: 0x1, script: 0x5b, flags: 0x0}, - 100: {lang: 0x101, script: 0x5b, flags: 0x0}, - 102: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 104: {lang: 0x10, script: 0x2, flags: 0x1}, - 105: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 106: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 107: {lang: 0x140, script: 0x5b, flags: 0x0}, - 108: {lang: 0x3a, script: 0x5, flags: 0x0}, - 109: {lang: 0x3a, script: 0x5, flags: 0x0}, - 110: {lang: 0x46f, script: 0x2c, flags: 0x0}, - 111: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 112: {lang: 0x12, script: 0x2, flags: 0x1}, - 114: {lang: 0x10d, script: 0x5b, flags: 0x0}, - 115: {lang: 0x151, script: 0x5b, flags: 0x0}, - 116: {lang: 0x1c0, script: 0x22, flags: 0x2}, - 119: {lang: 0x158, script: 0x5b, flags: 0x0}, - 121: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 123: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 124: {lang: 0x14, script: 0x2, flags: 0x1}, - 126: {lang: 0x16, script: 0x3, flags: 0x1}, - 127: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 129: {lang: 0x21, script: 0x5b, flags: 0x0}, - 131: {lang: 0x245, script: 0x5b, flags: 0x0}, - 133: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 134: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 135: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 136: {lang: 0x19, script: 0x2, flags: 0x1}, - 137: {lang: 0x0, script: 0x5b, flags: 0x0}, - 138: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 140: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 142: {lang: 0x529, script: 0x3c, flags: 0x0}, - 143: {lang: 0x0, script: 0x5b, flags: 0x0}, - 144: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 145: {lang: 0x1d1, script: 0x5b, flags: 0x0}, - 146: {lang: 0x1d4, script: 0x5b, flags: 0x0}, - 147: {lang: 0x1d5, script: 0x5b, flags: 0x0}, - 149: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 150: {lang: 0x1b, script: 0x2, flags: 0x1}, - 152: {lang: 0x1bc, script: 0x3e, flags: 0x0}, - 154: {lang: 0x1d, script: 0x3, flags: 0x1}, - 156: {lang: 0x3a, script: 0x5, flags: 0x0}, - 157: {lang: 0x20, script: 0x2, flags: 0x1}, - 158: {lang: 0x1f8, script: 0x5b, flags: 0x0}, - 159: {lang: 0x1f9, script: 0x5b, flags: 0x0}, - 162: {lang: 0x3a, script: 0x5, flags: 0x0}, - 163: {lang: 0x200, script: 0x49, flags: 0x0}, - 165: {lang: 0x445, script: 0x5b, flags: 0x0}, - 166: {lang: 0x28a, script: 0x20, flags: 0x0}, - 167: {lang: 0x22, script: 0x3, flags: 0x1}, - 169: {lang: 0x25, script: 0x2, flags: 0x1}, - 171: {lang: 0x254, script: 0x54, flags: 0x0}, - 172: {lang: 0x254, script: 0x54, flags: 0x0}, - 173: {lang: 0x3a, script: 0x5, flags: 0x0}, - 175: {lang: 0x3e2, script: 0x20, flags: 0x0}, - 176: {lang: 0x27, script: 0x2, flags: 0x1}, - 177: {lang: 0x3a, script: 0x5, flags: 0x0}, - 179: {lang: 0x10d, script: 0x5b, flags: 0x0}, - 180: {lang: 0x40c, script: 0xd6, flags: 0x0}, - 182: {lang: 0x43b, script: 0x5b, flags: 0x0}, - 183: {lang: 0x2c0, script: 0x5b, flags: 0x0}, - 184: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 185: {lang: 0x2c7, script: 0x5b, flags: 0x0}, - 186: {lang: 0x3a, script: 0x5, flags: 0x0}, - 187: {lang: 0x29, script: 0x2, flags: 0x1}, - 188: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 189: {lang: 0x2b, script: 0x2, flags: 0x1}, - 190: {lang: 0x432, script: 0x5b, flags: 0x0}, - 191: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 192: {lang: 0x2f1, script: 0x5b, flags: 0x0}, - 195: {lang: 0x2d, script: 0x2, flags: 0x1}, - 196: {lang: 0xa0, script: 0x5b, flags: 0x0}, - 197: {lang: 0x2f, script: 0x2, flags: 0x1}, - 198: {lang: 0x31, script: 0x2, flags: 0x1}, - 199: {lang: 0x33, script: 0x2, flags: 0x1}, - 201: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 202: {lang: 0x35, script: 0x2, flags: 0x1}, - 204: {lang: 0x320, script: 0x5b, flags: 0x0}, - 205: {lang: 0x37, script: 0x3, flags: 0x1}, - 206: {lang: 0x128, script: 0xed, flags: 0x0}, - 208: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 209: {lang: 0x31f, script: 0x5b, flags: 0x0}, - 210: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 211: {lang: 0x16, script: 0x5b, flags: 0x0}, - 212: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 213: {lang: 0x1b4, script: 0x5b, flags: 0x0}, - 215: {lang: 0x1b4, script: 0x5, flags: 0x2}, - 217: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 218: {lang: 0x367, script: 0x5b, flags: 0x0}, - 219: {lang: 0x347, script: 0x5b, flags: 0x0}, - 220: {lang: 0x351, script: 0x22, flags: 0x0}, - 226: {lang: 0x3a, script: 0x5, flags: 0x0}, - 227: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 229: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 230: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 231: {lang: 0x486, script: 0x5b, flags: 0x0}, - 232: {lang: 0x153, script: 0x5b, flags: 0x0}, - 233: {lang: 0x3a, script: 0x3, flags: 0x1}, - 234: {lang: 0x3b3, script: 0x5b, flags: 0x0}, - 235: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 237: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 238: {lang: 0x3a, script: 0x5, flags: 0x0}, - 239: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 241: {lang: 0x3a2, script: 0x5b, flags: 0x0}, - 242: {lang: 0x194, script: 0x5b, flags: 0x0}, - 244: {lang: 0x3a, script: 0x5, flags: 0x0}, - 259: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 261: {lang: 0x3d, script: 0x2, flags: 0x1}, - 262: {lang: 0x432, script: 0x20, flags: 0x0}, - 263: {lang: 0x3f, script: 0x2, flags: 0x1}, - 264: {lang: 0x3e5, script: 0x5b, flags: 0x0}, - 265: {lang: 0x3a, script: 0x5, flags: 0x0}, - 267: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 268: {lang: 0x3a, script: 0x5, flags: 0x0}, - 269: {lang: 0x41, script: 0x2, flags: 0x1}, - 272: {lang: 0x416, script: 0x5b, flags: 0x0}, - 273: {lang: 0x347, script: 0x5b, flags: 0x0}, - 274: {lang: 0x43, script: 0x2, flags: 0x1}, - 276: {lang: 0x1f9, script: 0x5b, flags: 0x0}, - 277: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 278: {lang: 0x429, script: 0x5b, flags: 0x0}, - 279: {lang: 0x367, script: 0x5b, flags: 0x0}, - 281: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 283: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 285: {lang: 0x45, script: 0x2, flags: 0x1}, - 289: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 290: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 291: {lang: 0x47, script: 0x2, flags: 0x1}, - 292: {lang: 0x49, script: 0x3, flags: 0x1}, - 293: {lang: 0x4c, script: 0x2, flags: 0x1}, - 294: {lang: 0x477, script: 0x5b, flags: 0x0}, - 295: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 296: {lang: 0x476, script: 0x5b, flags: 0x0}, - 297: {lang: 0x4e, script: 0x2, flags: 0x1}, - 298: {lang: 0x482, script: 0x5b, flags: 0x0}, - 300: {lang: 0x50, script: 0x4, flags: 0x1}, - 302: {lang: 0x4a0, script: 0x5b, flags: 0x0}, - 303: {lang: 0x54, script: 0x2, flags: 0x1}, - 304: {lang: 0x445, script: 0x5b, flags: 0x0}, - 305: {lang: 0x56, script: 0x3, flags: 0x1}, - 306: {lang: 0x445, script: 0x5b, flags: 0x0}, - 310: {lang: 0x512, script: 0x3e, flags: 0x2}, - 311: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 312: {lang: 0x4bc, script: 0x5b, flags: 0x0}, - 313: {lang: 0x1f9, script: 0x5b, flags: 0x0}, - 316: {lang: 0x13e, script: 0x5b, flags: 0x0}, - 319: {lang: 0x4c3, script: 0x5b, flags: 0x0}, - 320: {lang: 0x8a, script: 0x5b, flags: 0x0}, - 321: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 323: {lang: 0x41b, script: 0x5b, flags: 0x0}, - 334: {lang: 0x59, script: 0x2, flags: 0x1}, - 351: {lang: 0x3a, script: 0x5, flags: 0x0}, - 352: {lang: 0x5b, script: 0x2, flags: 0x1}, - 357: {lang: 0x423, script: 0x5b, flags: 0x0}, -} - -// likelyRegionList holds lists info associated with likelyRegion. -// Size: 558 bytes, 93 elements -var likelyRegionList = [93]likelyLangScript{ - 0: {lang: 0x148, script: 0x5, flags: 0x0}, - 1: {lang: 0x476, script: 0x5b, flags: 0x0}, - 2: {lang: 0x431, script: 0x5b, flags: 0x0}, - 3: {lang: 0x2ff, script: 0x20, flags: 0x0}, - 4: {lang: 0x1d7, script: 0x8, flags: 0x0}, - 5: {lang: 0x274, script: 0x5b, flags: 0x0}, - 6: {lang: 0xb7, script: 0x5b, flags: 0x0}, - 7: {lang: 0x432, script: 0x20, flags: 0x0}, - 8: {lang: 0x12d, script: 0xef, flags: 0x0}, - 9: {lang: 0x351, script: 0x22, flags: 0x0}, - 10: {lang: 0x529, script: 0x3b, flags: 0x0}, - 11: {lang: 0x4ac, script: 0x5, flags: 0x0}, - 12: {lang: 0x523, script: 0x5b, flags: 0x0}, - 13: {lang: 0x29a, script: 0xee, flags: 0x0}, - 14: {lang: 0x136, script: 0x34, flags: 0x0}, - 15: {lang: 0x48a, script: 0x5b, flags: 0x0}, - 16: {lang: 0x3a, script: 0x5, flags: 0x0}, - 17: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 18: {lang: 0x27, script: 0x2c, flags: 0x0}, - 19: {lang: 0x139, script: 0x5b, flags: 0x0}, - 20: {lang: 0x26a, script: 0x5, flags: 0x2}, - 21: {lang: 0x512, script: 0x3e, flags: 0x2}, - 22: {lang: 0x210, script: 0x2e, flags: 0x0}, - 23: {lang: 0x5, script: 0x20, flags: 0x0}, - 24: {lang: 0x274, script: 0x5b, flags: 0x0}, - 25: {lang: 0x136, script: 0x34, flags: 0x0}, - 26: {lang: 0x2ff, script: 0x20, flags: 0x0}, - 27: {lang: 0x1e1, script: 0x5b, flags: 0x0}, - 28: {lang: 0x31f, script: 0x5, flags: 0x0}, - 29: {lang: 0x1be, script: 0x22, flags: 0x0}, - 30: {lang: 0x4b4, script: 0x5, flags: 0x0}, - 31: {lang: 0x236, script: 0x76, flags: 0x0}, - 32: {lang: 0x148, script: 0x5, flags: 0x0}, - 33: {lang: 0x476, script: 0x5b, flags: 0x0}, - 34: {lang: 0x24a, script: 0x4f, flags: 0x0}, - 35: {lang: 0xe6, script: 0x5, flags: 0x0}, - 36: {lang: 0x226, script: 0xee, flags: 0x0}, - 37: {lang: 0x3a, script: 0x5, flags: 0x0}, - 38: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 39: {lang: 0x2b8, script: 0x58, flags: 0x0}, - 40: {lang: 0x226, script: 0xee, flags: 0x0}, - 41: {lang: 0x3a, script: 0x5, flags: 0x0}, - 42: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 43: {lang: 0x3dc, script: 0x5b, flags: 0x0}, - 44: {lang: 0x4ae, script: 0x20, flags: 0x0}, - 45: {lang: 0x2ff, script: 0x20, flags: 0x0}, - 46: {lang: 0x431, script: 0x5b, flags: 0x0}, - 47: {lang: 0x331, script: 0x76, flags: 0x0}, - 48: {lang: 0x213, script: 0x5b, flags: 0x0}, - 49: {lang: 0x30b, script: 0x20, flags: 0x0}, - 50: {lang: 0x242, script: 0x5, flags: 0x0}, - 51: {lang: 0x529, script: 0x3c, flags: 0x0}, - 52: {lang: 0x3c0, script: 0x5b, flags: 0x0}, - 53: {lang: 0x3a, script: 0x5, flags: 0x0}, - 54: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 55: {lang: 0x2ed, script: 0x5b, flags: 0x0}, - 56: {lang: 0x4b4, script: 0x5, flags: 0x0}, - 57: {lang: 0x88, script: 0x22, flags: 0x0}, - 58: {lang: 0x4b4, script: 0x5, flags: 0x0}, - 59: {lang: 0x4b4, script: 0x5, flags: 0x0}, - 60: {lang: 0xbe, script: 0x22, flags: 0x0}, - 61: {lang: 0x3dc, script: 0x5b, flags: 0x0}, - 62: {lang: 0x7e, script: 0x20, flags: 0x0}, - 63: {lang: 0x3e2, script: 0x20, flags: 0x0}, - 64: {lang: 0x267, script: 0x5b, flags: 0x0}, - 65: {lang: 0x444, script: 0x5b, flags: 0x0}, - 66: {lang: 0x512, script: 0x3e, flags: 0x0}, - 67: {lang: 0x412, script: 0x5b, flags: 0x0}, - 68: {lang: 0x4ae, script: 0x20, flags: 0x0}, - 69: {lang: 0x3a, script: 0x5, flags: 0x0}, - 70: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 71: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 72: {lang: 0x35, script: 0x5, flags: 0x0}, - 73: {lang: 0x46b, script: 0xee, flags: 0x0}, - 74: {lang: 0x2ec, script: 0x5, flags: 0x0}, - 75: {lang: 0x30f, script: 0x76, flags: 0x0}, - 76: {lang: 0x467, script: 0x20, flags: 0x0}, - 77: {lang: 0x148, script: 0x5, flags: 0x0}, - 78: {lang: 0x3a, script: 0x5, flags: 0x0}, - 79: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 80: {lang: 0x48a, script: 0x5b, flags: 0x0}, - 81: {lang: 0x58, script: 0x5, flags: 0x0}, - 82: {lang: 0x219, script: 0x20, flags: 0x0}, - 83: {lang: 0x81, script: 0x34, flags: 0x0}, - 84: {lang: 0x529, script: 0x3c, flags: 0x0}, - 85: {lang: 0x48c, script: 0x5b, flags: 0x0}, - 86: {lang: 0x4ae, script: 0x20, flags: 0x0}, - 87: {lang: 0x512, script: 0x3e, flags: 0x0}, - 88: {lang: 0x3b3, script: 0x5b, flags: 0x0}, - 89: {lang: 0x431, script: 0x5b, flags: 0x0}, - 90: {lang: 0x432, script: 0x20, flags: 0x0}, - 91: {lang: 0x15e, script: 0x5b, flags: 0x0}, - 92: {lang: 0x446, script: 0x5, flags: 0x0}, -} - -type likelyTag struct { - lang uint16 - region uint16 - script uint16 -} - -// Size: 198 bytes, 33 elements -var likelyRegionGroup = [33]likelyTag{ - 1: {lang: 0x139, region: 0xd7, script: 0x5b}, - 2: {lang: 0x139, region: 0x136, script: 0x5b}, - 3: {lang: 0x3c0, region: 0x41, script: 0x5b}, - 4: {lang: 0x139, region: 0x2f, script: 0x5b}, - 5: {lang: 0x139, region: 0xd7, script: 0x5b}, - 6: {lang: 0x13e, region: 0xd0, script: 0x5b}, - 7: {lang: 0x445, region: 0x130, script: 0x5b}, - 8: {lang: 0x3a, region: 0x6c, script: 0x5}, - 9: {lang: 0x445, region: 0x4b, script: 0x5b}, - 10: {lang: 0x139, region: 0x162, script: 0x5b}, - 11: {lang: 0x139, region: 0x136, script: 0x5b}, - 12: {lang: 0x139, region: 0x136, script: 0x5b}, - 13: {lang: 0x13e, region: 0x5a, script: 0x5b}, - 14: {lang: 0x529, region: 0x53, script: 0x3b}, - 15: {lang: 0x1be, region: 0x9a, script: 0x22}, - 16: {lang: 0x1e1, region: 0x96, script: 0x5b}, - 17: {lang: 0x1f9, region: 0x9f, script: 0x5b}, - 18: {lang: 0x139, region: 0x2f, script: 0x5b}, - 19: {lang: 0x139, region: 0xe7, script: 0x5b}, - 20: {lang: 0x139, region: 0x8b, script: 0x5b}, - 21: {lang: 0x41b, region: 0x143, script: 0x5b}, - 22: {lang: 0x529, region: 0x53, script: 0x3b}, - 23: {lang: 0x4bc, region: 0x138, script: 0x5b}, - 24: {lang: 0x3a, region: 0x109, script: 0x5}, - 25: {lang: 0x3e2, region: 0x107, script: 0x20}, - 26: {lang: 0x3e2, region: 0x107, script: 0x20}, - 27: {lang: 0x139, region: 0x7c, script: 0x5b}, - 28: {lang: 0x10d, region: 0x61, script: 0x5b}, - 29: {lang: 0x139, region: 0xd7, script: 0x5b}, - 30: {lang: 0x13e, region: 0x1f, script: 0x5b}, - 31: {lang: 0x139, region: 0x9b, script: 0x5b}, - 32: {lang: 0x139, region: 0x7c, script: 0x5b}, -} - -// Size: 264 bytes, 33 elements -var regionContainment = [33]uint64{ - // Entry 0 - 1F - 0x00000001ffffffff, 0x00000000200007a2, 0x0000000000003044, 0x0000000000000008, - 0x00000000803c0010, 0x0000000000000020, 0x0000000000000040, 0x0000000000000080, - 0x0000000000000100, 0x0000000000000200, 0x0000000000000400, 0x000000004000384c, - 0x0000000000001000, 0x0000000000002000, 0x0000000000004000, 0x0000000000008000, - 0x0000000000010000, 0x0000000000020000, 0x0000000000040000, 0x0000000000080000, - 0x0000000000100000, 0x0000000000200000, 0x0000000001c1c000, 0x0000000000800000, - 0x0000000001000000, 0x000000001e020000, 0x0000000004000000, 0x0000000008000000, - 0x0000000010000000, 0x00000000200006a0, 0x0000000040002048, 0x0000000080000000, - // Entry 20 - 3F - 0x0000000100000000, -} - -// regionInclusion maps region identifiers to sets of regions in regionInclusionBits, -// where each set holds all groupings that are directly connected in a region -// containment graph. -// Size: 359 bytes, 359 elements -var regionInclusion = [359]uint8{ - // Entry 0 - 3F - 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x23, - 0x24, 0x26, 0x27, 0x22, 0x28, 0x29, 0x2a, 0x2b, - 0x26, 0x2c, 0x24, 0x23, 0x26, 0x25, 0x2a, 0x2d, - 0x2e, 0x24, 0x2f, 0x2d, 0x26, 0x30, 0x31, 0x28, - // Entry 40 - 7F - 0x26, 0x28, 0x26, 0x25, 0x31, 0x22, 0x32, 0x33, - 0x34, 0x30, 0x22, 0x27, 0x27, 0x27, 0x35, 0x2d, - 0x29, 0x28, 0x27, 0x36, 0x28, 0x22, 0x21, 0x34, - 0x23, 0x21, 0x26, 0x2d, 0x26, 0x22, 0x37, 0x2e, - 0x35, 0x2a, 0x22, 0x2f, 0x38, 0x26, 0x26, 0x21, - 0x39, 0x39, 0x28, 0x38, 0x39, 0x39, 0x2f, 0x3a, - 0x2f, 0x20, 0x21, 0x38, 0x3b, 0x28, 0x3c, 0x2c, - 0x21, 0x2a, 0x35, 0x27, 0x38, 0x26, 0x24, 0x28, - // Entry 80 - BF - 0x2c, 0x2d, 0x23, 0x30, 0x2d, 0x2d, 0x26, 0x27, - 0x3a, 0x22, 0x34, 0x3c, 0x2d, 0x28, 0x36, 0x22, - 0x34, 0x3a, 0x26, 0x2e, 0x21, 0x39, 0x31, 0x38, - 0x24, 0x2c, 0x25, 0x22, 0x24, 0x25, 0x2c, 0x3a, - 0x2c, 0x26, 0x24, 0x36, 0x21, 0x2f, 0x3d, 0x31, - 0x3c, 0x2f, 0x26, 0x36, 0x36, 0x24, 0x26, 0x3d, - 0x31, 0x24, 0x26, 0x35, 0x25, 0x2d, 0x32, 0x38, - 0x2a, 0x38, 0x39, 0x39, 0x35, 0x33, 0x23, 0x26, - // Entry C0 - FF - 0x2f, 0x3c, 0x21, 0x23, 0x2d, 0x31, 0x36, 0x36, - 0x3c, 0x26, 0x2d, 0x26, 0x3a, 0x2f, 0x25, 0x2f, - 0x34, 0x31, 0x2f, 0x32, 0x3b, 0x2d, 0x2b, 0x2d, - 0x21, 0x34, 0x2a, 0x2c, 0x25, 0x21, 0x3c, 0x24, - 0x29, 0x2b, 0x24, 0x34, 0x21, 0x28, 0x29, 0x3b, - 0x31, 0x25, 0x2e, 0x30, 0x29, 0x26, 0x24, 0x3a, - 0x21, 0x3c, 0x28, 0x21, 0x24, 0x21, 0x21, 0x1f, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - // Entry 100 - 13F - 0x21, 0x21, 0x21, 0x2f, 0x21, 0x2e, 0x23, 0x33, - 0x2f, 0x24, 0x3b, 0x2f, 0x39, 0x38, 0x31, 0x2d, - 0x3a, 0x2c, 0x2e, 0x2d, 0x23, 0x2d, 0x2f, 0x28, - 0x2f, 0x27, 0x33, 0x34, 0x26, 0x24, 0x32, 0x22, - 0x26, 0x27, 0x22, 0x2d, 0x31, 0x3d, 0x29, 0x31, - 0x3d, 0x39, 0x29, 0x31, 0x24, 0x26, 0x29, 0x36, - 0x2f, 0x33, 0x2f, 0x21, 0x22, 0x21, 0x30, 0x28, - 0x3d, 0x23, 0x26, 0x21, 0x28, 0x26, 0x26, 0x31, - // Entry 140 - 17F - 0x3b, 0x29, 0x21, 0x29, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x23, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x24, 0x24, - 0x2f, 0x23, 0x32, 0x2f, 0x27, 0x2f, 0x21, -} - -// regionInclusionBits is an array of bit vectors where every vector represents -// a set of region groupings. These sets are used to compute the distance -// between two regions for the purpose of language matching. -// Size: 584 bytes, 73 elements -var regionInclusionBits = [73]uint64{ - // Entry 0 - 1F - 0x0000000102400813, 0x00000000200007a3, 0x0000000000003844, 0x0000000040000808, - 0x00000000803c0011, 0x0000000020000022, 0x0000000040000844, 0x0000000020000082, - 0x0000000000000102, 0x0000000020000202, 0x0000000020000402, 0x000000004000384d, - 0x0000000000001804, 0x0000000040002804, 0x0000000000404000, 0x0000000000408000, - 0x0000000000410000, 0x0000000002020000, 0x0000000000040010, 0x0000000000080010, - 0x0000000000100010, 0x0000000000200010, 0x0000000001c1c001, 0x0000000000c00000, - 0x0000000001400000, 0x000000001e020001, 0x0000000006000000, 0x000000000a000000, - 0x0000000012000000, 0x00000000200006a2, 0x0000000040002848, 0x0000000080000010, - // Entry 20 - 3F - 0x0000000100000001, 0x0000000000000001, 0x0000000080000000, 0x0000000000020000, - 0x0000000001000000, 0x0000000000008000, 0x0000000000002000, 0x0000000000000200, - 0x0000000000000008, 0x0000000000200000, 0x0000000110000000, 0x0000000000040000, - 0x0000000008000000, 0x0000000000000020, 0x0000000104000000, 0x0000000000000080, - 0x0000000000001000, 0x0000000000010000, 0x0000000000000400, 0x0000000004000000, - 0x0000000000000040, 0x0000000010000000, 0x0000000000004000, 0x0000000101000000, - 0x0000000108000000, 0x0000000000000100, 0x0000000100020000, 0x0000000000080000, - 0x0000000000100000, 0x0000000000800000, 0x00000001ffffffff, 0x0000000122400fb3, - // Entry 40 - 5F - 0x00000001827c0813, 0x000000014240385f, 0x0000000103c1c813, 0x000000011e420813, - 0x0000000112000001, 0x0000000106000001, 0x0000000101400001, 0x000000010a000001, - 0x0000000102020001, -} - -// regionInclusionNext marks, for each entry in regionInclusionBits, the set of -// all groups that are reachable from the groups set in the respective entry. -// Size: 73 bytes, 73 elements -var regionInclusionNext = [73]uint8{ - // Entry 0 - 3F - 0x3e, 0x3f, 0x0b, 0x0b, 0x40, 0x01, 0x0b, 0x01, - 0x01, 0x01, 0x01, 0x41, 0x0b, 0x0b, 0x16, 0x16, - 0x16, 0x19, 0x04, 0x04, 0x04, 0x04, 0x42, 0x16, - 0x16, 0x43, 0x19, 0x19, 0x19, 0x01, 0x0b, 0x04, - 0x00, 0x00, 0x1f, 0x11, 0x18, 0x0f, 0x0d, 0x09, - 0x03, 0x15, 0x44, 0x12, 0x1b, 0x05, 0x45, 0x07, - 0x0c, 0x10, 0x0a, 0x1a, 0x06, 0x1c, 0x0e, 0x46, - 0x47, 0x08, 0x48, 0x13, 0x14, 0x17, 0x3e, 0x3e, - // Entry 40 - 7F - 0x3e, 0x3e, 0x3e, 0x3e, 0x43, 0x43, 0x42, 0x43, - 0x43, -} - -type parentRel struct { - lang uint16 - script uint16 - maxScript uint16 - toRegion uint16 - fromRegion []uint16 -} - -// Size: 414 bytes, 5 elements -var parents = [5]parentRel{ - 0: {lang: 0x139, script: 0x0, maxScript: 0x5b, toRegion: 0x1, fromRegion: []uint16{0x1a, 0x25, 0x26, 0x2f, 0x34, 0x36, 0x3d, 0x42, 0x46, 0x48, 0x49, 0x4a, 0x50, 0x52, 0x5d, 0x5e, 0x62, 0x65, 0x6e, 0x74, 0x75, 0x76, 0x7c, 0x7d, 0x80, 0x81, 0x82, 0x84, 0x8d, 0x8e, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0xa0, 0xa1, 0xa5, 0xa8, 0xaa, 0xae, 0xb2, 0xb5, 0xb6, 0xc0, 0xc7, 0xcb, 0xcc, 0xcd, 0xcf, 0xd1, 0xd3, 0xd6, 0xd7, 0xde, 0xe0, 0xe1, 0xe7, 0xe8, 0xe9, 0xec, 0xf1, 0x108, 0x10a, 0x10b, 0x10c, 0x10e, 0x10f, 0x113, 0x118, 0x11c, 0x11e, 0x120, 0x126, 0x12a, 0x12d, 0x12e, 0x130, 0x132, 0x13a, 0x13d, 0x140, 0x143, 0x162, 0x163, 0x165}}, - 1: {lang: 0x139, script: 0x0, maxScript: 0x5b, toRegion: 0x1a, fromRegion: []uint16{0x2e, 0x4e, 0x61, 0x64, 0x73, 0xda, 0x10d, 0x110}}, - 2: {lang: 0x13e, script: 0x0, maxScript: 0x5b, toRegion: 0x1f, fromRegion: []uint16{0x2c, 0x3f, 0x41, 0x48, 0x51, 0x54, 0x57, 0x5a, 0x66, 0x6a, 0x8a, 0x90, 0xd0, 0xd9, 0xe3, 0xe5, 0xed, 0xf2, 0x11b, 0x136, 0x137, 0x13c}}, - 3: {lang: 0x3c0, script: 0x0, maxScript: 0x5b, toRegion: 0xef, fromRegion: []uint16{0x2a, 0x4e, 0x5b, 0x87, 0x8c, 0xb8, 0xc7, 0xd2, 0x119, 0x127}}, - 4: {lang: 0x529, script: 0x3c, maxScript: 0x3c, toRegion: 0x8e, fromRegion: []uint16{0xc7}}, -} - -// Total table size 30466 bytes (29KiB); checksum: 7544152B diff --git a/vendor/golang.org/x/text/internal/language/tags.go b/vendor/golang.org/x/text/internal/language/tags.go deleted file mode 100644 index e7afd318..00000000 --- a/vendor/golang.org/x/text/internal/language/tags.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -// MustParse is like Parse, but panics if the given BCP 47 tag cannot be parsed. -// It simplifies safe initialization of Tag values. -func MustParse(s string) Tag { - t, err := Parse(s) - if err != nil { - panic(err) - } - return t -} - -// MustParseBase is like ParseBase, but panics if the given base cannot be parsed. -// It simplifies safe initialization of Base values. -func MustParseBase(s string) Language { - b, err := ParseBase(s) - if err != nil { - panic(err) - } - return b -} - -// MustParseScript is like ParseScript, but panics if the given script cannot be -// parsed. It simplifies safe initialization of Script values. -func MustParseScript(s string) Script { - scr, err := ParseScript(s) - if err != nil { - panic(err) - } - return scr -} - -// MustParseRegion is like ParseRegion, but panics if the given region cannot be -// parsed. It simplifies safe initialization of Region values. -func MustParseRegion(s string) Region { - r, err := ParseRegion(s) - if err != nil { - panic(err) - } - return r -} - -// Und is the root language. -var Und Tag diff --git a/vendor/golang.org/x/text/internal/match.go b/vendor/golang.org/x/text/internal/match.go deleted file mode 100644 index 1cc004a6..00000000 --- a/vendor/golang.org/x/text/internal/match.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 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 internal - -// This file contains matchers that implement CLDR inheritance. -// -// See https://unicode.org/reports/tr35/#Locale_Inheritance. -// -// Some of the inheritance described in this document is already handled by -// the cldr package. - -import ( - "golang.org/x/text/language" -) - -// TODO: consider if (some of the) matching algorithm needs to be public after -// getting some feel about what is generic and what is specific. - -// NewInheritanceMatcher returns a matcher that matches based on the inheritance -// chain. -// -// The matcher uses canonicalization and the parent relationship to find a -// match. The resulting match will always be either Und or a language with the -// same language and script as the requested language. It will not match -// languages for which there is understood to be mutual or one-directional -// intelligibility. -// -// A Match will indicate an Exact match if the language matches after -// canonicalization and High if the matched tag is a parent. -func NewInheritanceMatcher(t []language.Tag) *InheritanceMatcher { - tags := &InheritanceMatcher{make(map[language.Tag]int)} - for i, tag := range t { - ct, err := language.All.Canonicalize(tag) - if err != nil { - ct = tag - } - tags.index[ct] = i - } - return tags -} - -type InheritanceMatcher struct { - index map[language.Tag]int -} - -func (m InheritanceMatcher) Match(want ...language.Tag) (language.Tag, int, language.Confidence) { - for _, t := range want { - ct, err := language.All.Canonicalize(t) - if err != nil { - ct = t - } - conf := language.Exact - for { - if index, ok := m.index[ct]; ok { - return ct, index, conf - } - if ct == language.Und { - break - } - ct = ct.Parent() - conf = language.High - } - } - return language.Und, 0, language.No -} diff --git a/vendor/golang.org/x/text/internal/tag/tag.go b/vendor/golang.org/x/text/internal/tag/tag.go deleted file mode 100644 index b5d34889..00000000 --- a/vendor/golang.org/x/text/internal/tag/tag.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package tag contains functionality handling tags and related data. -package tag // import "golang.org/x/text/internal/tag" - -import "sort" - -// An Index converts tags to a compact numeric value. -// -// All elements are of size 4. Tags may be up to 4 bytes long. Excess bytes can -// be used to store additional information about the tag. -type Index string - -// Elem returns the element data at the given index. -func (s Index) Elem(x int) string { - return string(s[x*4 : x*4+4]) -} - -// Index reports the index of the given key or -1 if it could not be found. -// Only the first len(key) bytes from the start of the 4-byte entries will be -// considered for the search and the first match in Index will be returned. -func (s Index) Index(key []byte) int { - n := len(key) - // search the index of the first entry with an equal or higher value than - // key in s. - index := sort.Search(len(s)/4, func(i int) bool { - return cmp(s[i*4:i*4+n], key) != -1 - }) - i := index * 4 - if cmp(s[i:i+len(key)], key) != 0 { - return -1 - } - return index -} - -// Next finds the next occurrence of key after index x, which must have been -// obtained from a call to Index using the same key. It returns x+1 or -1. -func (s Index) Next(key []byte, x int) int { - if x++; x*4 < len(s) && cmp(s[x*4:x*4+len(key)], key) == 0 { - return x - } - return -1 -} - -// cmp returns an integer comparing a and b lexicographically. -func cmp(a Index, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - for i, c := range b[:n] { - switch { - case a[i] > c: - return 1 - case a[i] < c: - return -1 - } - } - switch { - case len(a) < len(b): - return -1 - case len(a) > len(b): - return 1 - } - return 0 -} - -// Compare returns an integer comparing a and b lexicographically. -func Compare(a string, b []byte) int { - return cmp(Index(a), b) -} - -// FixCase reformats b to the same pattern of cases as form. -// If returns false if string b is malformed. -func FixCase(form string, b []byte) bool { - if len(form) != len(b) { - return false - } - for i, c := range b { - if form[i] <= 'Z' { - if c >= 'a' { - c -= 'z' - 'Z' - } - if c < 'A' || 'Z' < c { - return false - } - } else { - if c <= 'Z' { - c += 'z' - 'Z' - } - if c < 'a' || 'z' < c { - return false - } - } - b[i] = c - } - return true -} diff --git a/vendor/golang.org/x/text/language/coverage.go b/vendor/golang.org/x/text/language/coverage.go deleted file mode 100644 index a24fd1a4..00000000 --- a/vendor/golang.org/x/text/language/coverage.go +++ /dev/null @@ -1,187 +0,0 @@ -// 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 language - -import ( - "fmt" - "sort" - - "golang.org/x/text/internal/language" -) - -// The Coverage interface is used to define the level of coverage of an -// internationalization service. Note that not all types are supported by all -// services. As lists may be generated on the fly, it is recommended that users -// of a Coverage cache the results. -type Coverage interface { - // Tags returns the list of supported tags. - Tags() []Tag - - // BaseLanguages returns the list of supported base languages. - BaseLanguages() []Base - - // Scripts returns the list of supported scripts. - Scripts() []Script - - // Regions returns the list of supported regions. - Regions() []Region -} - -var ( - // Supported defines a Coverage that lists all supported subtags. Tags - // always returns nil. - Supported Coverage = allSubtags{} -) - -// TODO: -// - Support Variants, numbering systems. -// - CLDR coverage levels. -// - Set of common tags defined in this package. - -type allSubtags struct{} - -// Regions returns the list of supported regions. As all regions are in a -// consecutive range, it simply returns a slice of numbers in increasing order. -// The "undefined" region is not returned. -func (s allSubtags) Regions() []Region { - reg := make([]Region, language.NumRegions) - for i := range reg { - reg[i] = Region{language.Region(i + 1)} - } - return reg -} - -// Scripts returns the list of supported scripts. As all scripts are in a -// consecutive range, it simply returns a slice of numbers in increasing order. -// The "undefined" script is not returned. -func (s allSubtags) Scripts() []Script { - scr := make([]Script, language.NumScripts) - for i := range scr { - scr[i] = Script{language.Script(i + 1)} - } - return scr -} - -// BaseLanguages returns the list of all supported base languages. It generates -// the list by traversing the internal structures. -func (s allSubtags) BaseLanguages() []Base { - bs := language.BaseLanguages() - base := make([]Base, len(bs)) - for i, b := range bs { - base[i] = Base{b} - } - return base -} - -// Tags always returns nil. -func (s allSubtags) Tags() []Tag { - return nil -} - -// coverage is used by NewCoverage which is used as a convenient way for -// creating Coverage implementations for partially defined data. Very often a -// package will only need to define a subset of slices. coverage provides a -// convenient way to do this. Moreover, packages using NewCoverage, instead of -// their own implementation, will not break if later new slice types are added. -type coverage struct { - tags func() []Tag - bases func() []Base - scripts func() []Script - regions func() []Region -} - -func (s *coverage) Tags() []Tag { - if s.tags == nil { - return nil - } - return s.tags() -} - -// bases implements sort.Interface and is used to sort base languages. -type bases []Base - -func (b bases) Len() int { - return len(b) -} - -func (b bases) Swap(i, j int) { - b[i], b[j] = b[j], b[i] -} - -func (b bases) Less(i, j int) bool { - return b[i].langID < b[j].langID -} - -// BaseLanguages returns the result from calling s.bases if it is specified or -// otherwise derives the set of supported base languages from tags. -func (s *coverage) BaseLanguages() []Base { - if s.bases == nil { - tags := s.Tags() - if len(tags) == 0 { - return nil - } - a := make([]Base, len(tags)) - for i, t := range tags { - a[i] = Base{language.Language(t.lang())} - } - sort.Sort(bases(a)) - k := 0 - for i := 1; i < len(a); i++ { - if a[k] != a[i] { - k++ - a[k] = a[i] - } - } - return a[:k+1] - } - return s.bases() -} - -func (s *coverage) Scripts() []Script { - if s.scripts == nil { - return nil - } - return s.scripts() -} - -func (s *coverage) Regions() []Region { - if s.regions == nil { - return nil - } - return s.regions() -} - -// NewCoverage returns a Coverage for the given lists. It is typically used by -// packages providing internationalization services to define their level of -// coverage. A list may be of type []T or func() []T, where T is either Tag, -// Base, Script or Region. The returned Coverage derives the value for Bases -// from Tags if no func or slice for []Base is specified. For other unspecified -// types the returned Coverage will return nil for the respective methods. -func NewCoverage(list ...interface{}) Coverage { - s := &coverage{} - for _, x := range list { - switch v := x.(type) { - case func() []Base: - s.bases = v - case func() []Script: - s.scripts = v - case func() []Region: - s.regions = v - case func() []Tag: - s.tags = v - case []Base: - s.bases = func() []Base { return v } - case []Script: - s.scripts = func() []Script { return v } - case []Region: - s.regions = func() []Region { return v } - case []Tag: - s.tags = func() []Tag { return v } - default: - panic(fmt.Sprintf("language: unsupported set type %T", v)) - } - } - return s -} diff --git a/vendor/golang.org/x/text/language/doc.go b/vendor/golang.org/x/text/language/doc.go deleted file mode 100644 index 212b77c9..00000000 --- a/vendor/golang.org/x/text/language/doc.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2017 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 language implements BCP 47 language tags and related functionality. -// -// The most important function of package language is to match a list of -// user-preferred languages to a list of supported languages. -// It alleviates the developer of dealing with the complexity of this process -// and provides the user with the best experience -// (see https://blog.golang.org/matchlang). -// -// # Matching preferred against supported languages -// -// A Matcher for an application that supports English, Australian English, -// Danish, and standard Mandarin can be created as follows: -// -// var matcher = language.NewMatcher([]language.Tag{ -// language.English, // The first language is used as fallback. -// language.MustParse("en-AU"), -// language.Danish, -// language.Chinese, -// }) -// -// This list of supported languages is typically implied by the languages for -// which there exists translations of the user interface. -// -// User-preferred languages usually come as a comma-separated list of BCP 47 -// language tags. -// The MatchString finds best matches for such strings: -// -// handler(w http.ResponseWriter, r *http.Request) { -// lang, _ := r.Cookie("lang") -// accept := r.Header.Get("Accept-Language") -// tag, _ := language.MatchStrings(matcher, lang.String(), accept) -// -// // tag should now be used for the initialization of any -// // locale-specific service. -// } -// -// The Matcher's Match method can be used to match Tags directly. -// -// Matchers are aware of the intricacies of equivalence between languages, such -// as deprecated subtags, legacy tags, macro languages, mutual -// intelligibility between scripts and languages, and transparently passing -// BCP 47 user configuration. -// For instance, it will know that a reader of Bokmål Danish can read Norwegian -// and will know that Cantonese ("yue") is a good match for "zh-HK". -// -// # Using match results -// -// To guarantee a consistent user experience to the user it is important to -// use the same language tag for the selection of any locale-specific services. -// For example, it is utterly confusing to substitute spelled-out numbers -// or dates in one language in text of another language. -// More subtly confusing is using the wrong sorting order or casing -// algorithm for a certain language. -// -// All the packages in x/text that provide locale-specific services -// (e.g. collate, cases) should be initialized with the tag that was -// obtained at the start of an interaction with the user. -// -// Note that Tag that is returned by Match and MatchString may differ from any -// of the supported languages, as it may contain carried over settings from -// the user tags. -// This may be inconvenient when your application has some additional -// locale-specific data for your supported languages. -// Match and MatchString both return the index of the matched supported tag -// to simplify associating such data with the matched tag. -// -// # Canonicalization -// -// If one uses the Matcher to compare languages one does not need to -// worry about canonicalization. -// -// The meaning of a Tag varies per application. The language package -// therefore delays canonicalization and preserves information as much -// as possible. The Matcher, however, will always take into account that -// two different tags may represent the same language. -// -// By default, only legacy and deprecated tags are converted into their -// canonical equivalent. All other information is preserved. This approach makes -// the confidence scores more accurate and allows matchers to distinguish -// between variants that are otherwise lost. -// -// As a consequence, two tags that should be treated as identical according to -// BCP 47 or CLDR, like "en-Latn" and "en", will be represented differently. The -// Matcher handles such distinctions, though, and is aware of the -// equivalence relations. The CanonType type can be used to alter the -// canonicalization form. -// -// # References -// -// BCP 47 - Tags for Identifying Languages http://tools.ietf.org/html/bcp47 -package language // import "golang.org/x/text/language" - -// TODO: explanation on how to match languages for your own locale-specific -// service. diff --git a/vendor/golang.org/x/text/language/language.go b/vendor/golang.org/x/text/language/language.go deleted file mode 100644 index 4d9c6612..00000000 --- a/vendor/golang.org/x/text/language/language.go +++ /dev/null @@ -1,605 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate go run gen.go -output tables.go - -package language - -// TODO: Remove above NOTE after: -// - verifying that tables are dropped correctly (most notably matcher tables). - -import ( - "strings" - - "golang.org/x/text/internal/language" - "golang.org/x/text/internal/language/compact" -) - -// Tag represents a BCP 47 language tag. It is used to specify an instance of a -// specific language or locale. All language tag values are guaranteed to be -// well-formed. -type Tag compact.Tag - -func makeTag(t language.Tag) (tag Tag) { - return Tag(compact.Make(t)) -} - -func (t *Tag) tag() language.Tag { - return (*compact.Tag)(t).Tag() -} - -func (t *Tag) isCompact() bool { - return (*compact.Tag)(t).IsCompact() -} - -// TODO: improve performance. -func (t *Tag) lang() language.Language { return t.tag().LangID } -func (t *Tag) region() language.Region { return t.tag().RegionID } -func (t *Tag) script() language.Script { return t.tag().ScriptID } - -// Make is a convenience wrapper for Parse that omits the error. -// In case of an error, a sensible default is returned. -func Make(s string) Tag { - return Default.Make(s) -} - -// Make is a convenience wrapper for c.Parse that omits the error. -// In case of an error, a sensible default is returned. -func (c CanonType) Make(s string) Tag { - t, _ := c.Parse(s) - return t -} - -// Raw returns the raw base language, script and region, without making an -// attempt to infer their values. -func (t Tag) Raw() (b Base, s Script, r Region) { - tt := t.tag() - return Base{tt.LangID}, Script{tt.ScriptID}, Region{tt.RegionID} -} - -// IsRoot returns true if t is equal to language "und". -func (t Tag) IsRoot() bool { - return compact.Tag(t).IsRoot() -} - -// CanonType can be used to enable or disable various types of canonicalization. -type CanonType int - -const ( - // Replace deprecated base languages with their preferred replacements. - DeprecatedBase CanonType = 1 << iota - // Replace deprecated scripts with their preferred replacements. - DeprecatedScript - // Replace deprecated regions with their preferred replacements. - DeprecatedRegion - // Remove redundant scripts. - SuppressScript - // Normalize legacy encodings. This includes legacy languages defined in - // CLDR as well as bibliographic codes defined in ISO-639. - Legacy - // Map the dominant language of a macro language group to the macro language - // subtag. For example cmn -> zh. - Macro - // The CLDR flag should be used if full compatibility with CLDR is required. - // There are a few cases where language.Tag may differ from CLDR. To follow all - // of CLDR's suggestions, use All|CLDR. - CLDR - - // Raw can be used to Compose or Parse without Canonicalization. - Raw CanonType = 0 - - // Replace all deprecated tags with their preferred replacements. - Deprecated = DeprecatedBase | DeprecatedScript | DeprecatedRegion - - // All canonicalizations recommended by BCP 47. - BCP47 = Deprecated | SuppressScript - - // All canonicalizations. - All = BCP47 | Legacy | Macro - - // Default is the canonicalization used by Parse, Make and Compose. To - // preserve as much information as possible, canonicalizations that remove - // potentially valuable information are not included. The Matcher is - // designed to recognize similar tags that would be the same if - // they were canonicalized using All. - Default = Deprecated | Legacy - - canonLang = DeprecatedBase | Legacy | Macro - - // TODO: LikelyScript, LikelyRegion: suppress similar to ICU. -) - -// canonicalize returns the canonicalized equivalent of the tag and -// whether there was any change. -func canonicalize(c CanonType, t language.Tag) (language.Tag, bool) { - if c == Raw { - return t, false - } - changed := false - if c&SuppressScript != 0 { - if t.LangID.SuppressScript() == t.ScriptID { - t.ScriptID = 0 - changed = true - } - } - if c&canonLang != 0 { - for { - if l, aliasType := t.LangID.Canonicalize(); l != t.LangID { - switch aliasType { - case language.Legacy: - if c&Legacy != 0 { - if t.LangID == _sh && t.ScriptID == 0 { - t.ScriptID = _Latn - } - t.LangID = l - changed = true - } - case language.Macro: - if c&Macro != 0 { - // We deviate here from CLDR. The mapping "nb" -> "no" - // qualifies as a typical Macro language mapping. However, - // for legacy reasons, CLDR maps "no", the macro language - // code for Norwegian, to the dominant variant "nb". This - // change is currently under consideration for CLDR as well. - // See https://unicode.org/cldr/trac/ticket/2698 and also - // https://unicode.org/cldr/trac/ticket/1790 for some of the - // practical implications. TODO: this check could be removed - // if CLDR adopts this change. - if c&CLDR == 0 || t.LangID != _nb { - changed = true - t.LangID = l - } - } - case language.Deprecated: - if c&DeprecatedBase != 0 { - if t.LangID == _mo && t.RegionID == 0 { - t.RegionID = _MD - } - t.LangID = l - changed = true - // Other canonicalization types may still apply. - continue - } - } - } else if c&Legacy != 0 && t.LangID == _no && c&CLDR != 0 { - t.LangID = _nb - changed = true - } - break - } - } - if c&DeprecatedScript != 0 { - if t.ScriptID == _Qaai { - changed = true - t.ScriptID = _Zinh - } - } - if c&DeprecatedRegion != 0 { - if r := t.RegionID.Canonicalize(); r != t.RegionID { - changed = true - t.RegionID = r - } - } - return t, changed -} - -// Canonicalize returns the canonicalized equivalent of the tag. -func (c CanonType) Canonicalize(t Tag) (Tag, error) { - // First try fast path. - if t.isCompact() { - if _, changed := canonicalize(c, compact.Tag(t).Tag()); !changed { - return t, nil - } - } - // It is unlikely that one will canonicalize a tag after matching. So do - // a slow but simple approach here. - if tag, changed := canonicalize(c, t.tag()); changed { - tag.RemakeString() - return makeTag(tag), nil - } - return t, nil - -} - -// Confidence indicates the level of certainty for a given return value. -// For example, Serbian may be written in Cyrillic or Latin script. -// The confidence level indicates whether a value was explicitly specified, -// whether it is typically the only possible value, or whether there is -// an ambiguity. -type Confidence int - -const ( - No Confidence = iota // full confidence that there was no match - Low // most likely value picked out of a set of alternatives - High // value is generally assumed to be the correct match - Exact // exact match or explicitly specified value -) - -var confName = []string{"No", "Low", "High", "Exact"} - -func (c Confidence) String() string { - return confName[c] -} - -// String returns the canonical string representation of the language tag. -func (t Tag) String() string { - return t.tag().String() -} - -// MarshalText implements encoding.TextMarshaler. -func (t Tag) MarshalText() (text []byte, err error) { - return t.tag().MarshalText() -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (t *Tag) UnmarshalText(text []byte) error { - var tag language.Tag - err := tag.UnmarshalText(text) - *t = makeTag(tag) - return err -} - -// Base returns the base language of the language tag. If the base language is -// unspecified, an attempt will be made to infer it from the context. -// It uses a variant of CLDR's Add Likely Subtags algorithm. This is subject to change. -func (t Tag) Base() (Base, Confidence) { - if b := t.lang(); b != 0 { - return Base{b}, Exact - } - tt := t.tag() - c := High - if tt.ScriptID == 0 && !tt.RegionID.IsCountry() { - c = Low - } - if tag, err := tt.Maximize(); err == nil && tag.LangID != 0 { - return Base{tag.LangID}, c - } - return Base{0}, No -} - -// Script infers the script for the language tag. If it was not explicitly given, it will infer -// a most likely candidate. -// If more than one script is commonly used for a language, the most likely one -// is returned with a low confidence indication. For example, it returns (Cyrl, Low) -// for Serbian. -// If a script cannot be inferred (Zzzz, No) is returned. We do not use Zyyy (undetermined) -// as one would suspect from the IANA registry for BCP 47. In a Unicode context Zyyy marks -// common characters (like 1, 2, 3, '.', etc.) and is therefore more like multiple scripts. -// See https://www.unicode.org/reports/tr24/#Values for more details. Zzzz is also used for -// unknown value in CLDR. (Zzzz, Exact) is returned if Zzzz was explicitly specified. -// Note that an inferred script is never guaranteed to be the correct one. Latin is -// almost exclusively used for Afrikaans, but Arabic has been used for some texts -// in the past. Also, the script that is commonly used may change over time. -// It uses a variant of CLDR's Add Likely Subtags algorithm. This is subject to change. -func (t Tag) Script() (Script, Confidence) { - if scr := t.script(); scr != 0 { - return Script{scr}, Exact - } - tt := t.tag() - sc, c := language.Script(_Zzzz), No - if scr := tt.LangID.SuppressScript(); scr != 0 { - // Note: it is not always the case that a language with a suppress - // script value is only written in one script (e.g. kk, ms, pa). - if tt.RegionID == 0 { - return Script{scr}, High - } - sc, c = scr, High - } - if tag, err := tt.Maximize(); err == nil { - if tag.ScriptID != sc { - sc, c = tag.ScriptID, Low - } - } else { - tt, _ = canonicalize(Deprecated|Macro, tt) - if tag, err := tt.Maximize(); err == nil && tag.ScriptID != sc { - sc, c = tag.ScriptID, Low - } - } - return Script{sc}, c -} - -// Region returns the region for the language tag. If it was not explicitly given, it will -// infer a most likely candidate from the context. -// It uses a variant of CLDR's Add Likely Subtags algorithm. This is subject to change. -func (t Tag) Region() (Region, Confidence) { - if r := t.region(); r != 0 { - return Region{r}, Exact - } - tt := t.tag() - if tt, err := tt.Maximize(); err == nil { - return Region{tt.RegionID}, Low // TODO: differentiate between high and low. - } - tt, _ = canonicalize(Deprecated|Macro, tt) - if tag, err := tt.Maximize(); err == nil { - return Region{tag.RegionID}, Low - } - return Region{_ZZ}, No // TODO: return world instead of undetermined? -} - -// Variants returns the variants specified explicitly for this language tag. -// or nil if no variant was specified. -func (t Tag) Variants() []Variant { - if !compact.Tag(t).MayHaveVariants() { - return nil - } - v := []Variant{} - x, str := "", t.tag().Variants() - for str != "" { - x, str = nextToken(str) - v = append(v, Variant{x}) - } - return v -} - -// Parent returns the CLDR parent of t. In CLDR, missing fields in data for a -// specific language are substituted with fields from the parent language. -// The parent for a language may change for newer versions of CLDR. -// -// Parent returns a tag for a less specific language that is mutually -// intelligible or Und if there is no such language. This may not be the same as -// simply stripping the last BCP 47 subtag. For instance, the parent of "zh-TW" -// is "zh-Hant", and the parent of "zh-Hant" is "und". -func (t Tag) Parent() Tag { - return Tag(compact.Tag(t).Parent()) -} - -// nextToken returns token t and the rest of the string. -func nextToken(s string) (t, tail string) { - p := strings.Index(s[1:], "-") - if p == -1 { - return s[1:], "" - } - p++ - return s[1:p], s[p:] -} - -// Extension is a single BCP 47 extension. -type Extension struct { - s string -} - -// String returns the string representation of the extension, including the -// type tag. -func (e Extension) String() string { - return e.s -} - -// ParseExtension parses s as an extension and returns it on success. -func ParseExtension(s string) (e Extension, err error) { - ext, err := language.ParseExtension(s) - return Extension{ext}, err -} - -// Type returns the one-byte extension type of e. It returns 0 for the zero -// exception. -func (e Extension) Type() byte { - if e.s == "" { - return 0 - } - return e.s[0] -} - -// Tokens returns the list of tokens of e. -func (e Extension) Tokens() []string { - return strings.Split(e.s, "-") -} - -// Extension returns the extension of type x for tag t. It will return -// false for ok if t does not have the requested extension. The returned -// extension will be invalid in this case. -func (t Tag) Extension(x byte) (ext Extension, ok bool) { - if !compact.Tag(t).MayHaveExtensions() { - return Extension{}, false - } - e, ok := t.tag().Extension(x) - return Extension{e}, ok -} - -// Extensions returns all extensions of t. -func (t Tag) Extensions() []Extension { - if !compact.Tag(t).MayHaveExtensions() { - return nil - } - e := []Extension{} - for _, ext := range t.tag().Extensions() { - e = append(e, Extension{ext}) - } - return e -} - -// TypeForKey returns the type associated with the given key, where key and type -// are of the allowed values defined for the Unicode locale extension ('u') in -// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. -// TypeForKey will traverse the inheritance chain to get the correct value. -// -// If there are multiple types associated with a key, only the first will be -// returned. If there is no type associated with a key, it returns the empty -// string. -func (t Tag) TypeForKey(key string) string { - if !compact.Tag(t).MayHaveExtensions() { - if key != "rg" && key != "va" { - return "" - } - } - return t.tag().TypeForKey(key) -} - -// SetTypeForKey returns a new Tag with the key set to type, where key and type -// are of the allowed values defined for the Unicode locale extension ('u') in -// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. -// An empty value removes an existing pair with the same key. -func (t Tag) SetTypeForKey(key, value string) (Tag, error) { - tt, err := t.tag().SetTypeForKey(key, value) - return makeTag(tt), err -} - -// NumCompactTags is the number of compact tags. The maximum tag is -// NumCompactTags-1. -const NumCompactTags = compact.NumCompactTags - -// CompactIndex returns an index, where 0 <= index < NumCompactTags, for tags -// for which data exists in the text repository.The index will change over time -// and should not be stored in persistent storage. If t does not match a compact -// index, exact will be false and the compact index will be returned for the -// first match after repeatedly taking the Parent of t. -func CompactIndex(t Tag) (index int, exact bool) { - id, exact := compact.LanguageID(compact.Tag(t)) - return int(id), exact -} - -var root = language.Tag{} - -// Base is an ISO 639 language code, used for encoding the base language -// of a language tag. -type Base struct { - langID language.Language -} - -// ParseBase parses a 2- or 3-letter ISO 639 code. -// It returns a ValueError if s is a well-formed but unknown language identifier -// or another error if another error occurred. -func ParseBase(s string) (Base, error) { - l, err := language.ParseBase(s) - return Base{l}, err -} - -// String returns the BCP 47 representation of the base language. -func (b Base) String() string { - return b.langID.String() -} - -// ISO3 returns the ISO 639-3 language code. -func (b Base) ISO3() string { - return b.langID.ISO3() -} - -// IsPrivateUse reports whether this language code is reserved for private use. -func (b Base) IsPrivateUse() bool { - return b.langID.IsPrivateUse() -} - -// Script is a 4-letter ISO 15924 code for representing scripts. -// It is idiomatically represented in title case. -type Script struct { - scriptID language.Script -} - -// ParseScript parses a 4-letter ISO 15924 code. -// It returns a ValueError if s is a well-formed but unknown script identifier -// or another error if another error occurred. -func ParseScript(s string) (Script, error) { - sc, err := language.ParseScript(s) - return Script{sc}, err -} - -// String returns the script code in title case. -// It returns "Zzzz" for an unspecified script. -func (s Script) String() string { - return s.scriptID.String() -} - -// IsPrivateUse reports whether this script code is reserved for private use. -func (s Script) IsPrivateUse() bool { - return s.scriptID.IsPrivateUse() -} - -// Region is an ISO 3166-1 or UN M.49 code for representing countries and regions. -type Region struct { - regionID language.Region -} - -// EncodeM49 returns the Region for the given UN M.49 code. -// It returns an error if r is not a valid code. -func EncodeM49(r int) (Region, error) { - rid, err := language.EncodeM49(r) - return Region{rid}, err -} - -// ParseRegion parses a 2- or 3-letter ISO 3166-1 or a UN M.49 code. -// It returns a ValueError if s is a well-formed but unknown region identifier -// or another error if another error occurred. -func ParseRegion(s string) (Region, error) { - r, err := language.ParseRegion(s) - return Region{r}, err -} - -// String returns the BCP 47 representation for the region. -// It returns "ZZ" for an unspecified region. -func (r Region) String() string { - return r.regionID.String() -} - -// ISO3 returns the 3-letter ISO code of r. -// Note that not all regions have a 3-letter ISO code. -// In such cases this method returns "ZZZ". -func (r Region) ISO3() string { - return r.regionID.ISO3() -} - -// M49 returns the UN M.49 encoding of r, or 0 if this encoding -// is not defined for r. -func (r Region) M49() int { - return r.regionID.M49() -} - -// IsPrivateUse reports whether r has the ISO 3166 User-assigned status. This -// may include private-use tags that are assigned by CLDR and used in this -// implementation. So IsPrivateUse and IsCountry can be simultaneously true. -func (r Region) IsPrivateUse() bool { - return r.regionID.IsPrivateUse() -} - -// IsCountry returns whether this region is a country or autonomous area. This -// includes non-standard definitions from CLDR. -func (r Region) IsCountry() bool { - return r.regionID.IsCountry() -} - -// IsGroup returns whether this region defines a collection of regions. This -// includes non-standard definitions from CLDR. -func (r Region) IsGroup() bool { - return r.regionID.IsGroup() -} - -// Contains returns whether Region c is contained by Region r. It returns true -// if c == r. -func (r Region) Contains(c Region) bool { - return r.regionID.Contains(c.regionID) -} - -// TLD returns the country code top-level domain (ccTLD). UK is returned for GB. -// In all other cases it returns either the region itself or an error. -// -// This method may return an error for a region for which there exists a -// canonical form with a ccTLD. To get that ccTLD canonicalize r first. The -// region will already be canonicalized it was obtained from a Tag that was -// obtained using any of the default methods. -func (r Region) TLD() (Region, error) { - tld, err := r.regionID.TLD() - return Region{tld}, err -} - -// Canonicalize returns the region or a possible replacement if the region is -// deprecated. It will not return a replacement for deprecated regions that -// are split into multiple regions. -func (r Region) Canonicalize() Region { - return Region{r.regionID.Canonicalize()} -} - -// Variant represents a registered variant of a language as defined by BCP 47. -type Variant struct { - variant string -} - -// ParseVariant parses and returns a Variant. An error is returned if s is not -// a valid variant. -func ParseVariant(s string) (Variant, error) { - v, err := language.ParseVariant(s) - return Variant{v.String()}, err -} - -// String returns the string representation of the variant. -func (v Variant) String() string { - return v.variant -} diff --git a/vendor/golang.org/x/text/language/match.go b/vendor/golang.org/x/text/language/match.go deleted file mode 100644 index 1153baf2..00000000 --- a/vendor/golang.org/x/text/language/match.go +++ /dev/null @@ -1,735 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "errors" - "strings" - - "golang.org/x/text/internal/language" -) - -// A MatchOption configures a Matcher. -type MatchOption func(*matcher) - -// PreferSameScript will, in the absence of a match, result in the first -// preferred tag with the same script as a supported tag to match this supported -// tag. The default is currently true, but this may change in the future. -func PreferSameScript(preferSame bool) MatchOption { - return func(m *matcher) { m.preferSameScript = preferSame } -} - -// TODO(v1.0.0): consider making Matcher a concrete type, instead of interface. -// There doesn't seem to be too much need for multiple types. -// Making it a concrete type allows MatchStrings to be a method, which will -// improve its discoverability. - -// MatchStrings parses and matches the given strings until one of them matches -// the language in the Matcher. A string may be an Accept-Language header as -// handled by ParseAcceptLanguage. The default language is returned if no -// other language matched. -func MatchStrings(m Matcher, lang ...string) (tag Tag, index int) { - for _, accept := range lang { - desired, _, err := ParseAcceptLanguage(accept) - if err != nil { - continue - } - if tag, index, conf := m.Match(desired...); conf != No { - return tag, index - } - } - tag, index, _ = m.Match() - return -} - -// Matcher is the interface that wraps the Match method. -// -// Match returns the best match for any of the given tags, along with -// a unique index associated with the returned tag and a confidence -// score. -type Matcher interface { - Match(t ...Tag) (tag Tag, index int, c Confidence) -} - -// Comprehends reports the confidence score for a speaker of a given language -// to being able to comprehend the written form of an alternative language. -func Comprehends(speaker, alternative Tag) Confidence { - _, _, c := NewMatcher([]Tag{alternative}).Match(speaker) - return c -} - -// NewMatcher returns a Matcher that matches an ordered list of preferred tags -// against a list of supported tags based on written intelligibility, closeness -// of dialect, equivalence of subtags and various other rules. It is initialized -// with the list of supported tags. The first element is used as the default -// value in case no match is found. -// -// Its Match method matches the first of the given Tags to reach a certain -// confidence threshold. The tags passed to Match should therefore be specified -// in order of preference. Extensions are ignored for matching. -// -// The index returned by the Match method corresponds to the index of the -// matched tag in t, but is augmented with the Unicode extension ('u')of the -// corresponding preferred tag. This allows user locale options to be passed -// transparently. -func NewMatcher(t []Tag, options ...MatchOption) Matcher { - return newMatcher(t, options) -} - -func (m *matcher) Match(want ...Tag) (t Tag, index int, c Confidence) { - var tt language.Tag - match, w, c := m.getBest(want...) - if match != nil { - tt, index = match.tag, match.index - } else { - // TODO: this should be an option - tt = m.default_.tag - if m.preferSameScript { - outer: - for _, w := range want { - script, _ := w.Script() - if script.scriptID == 0 { - // Don't do anything if there is no script, such as with - // private subtags. - continue - } - for i, h := range m.supported { - if script.scriptID == h.maxScript { - tt, index = h.tag, i - break outer - } - } - } - } - // TODO: select first language tag based on script. - } - if w.RegionID != tt.RegionID && w.RegionID != 0 { - if w.RegionID != 0 && tt.RegionID != 0 && tt.RegionID.Contains(w.RegionID) { - tt.RegionID = w.RegionID - tt.RemakeString() - } else if r := w.RegionID.String(); len(r) == 2 { - // TODO: also filter macro and deprecated. - tt, _ = tt.SetTypeForKey("rg", strings.ToLower(r)+"zzzz") - } - } - // Copy options from the user-provided tag into the result tag. This is hard - // to do after the fact, so we do it here. - // TODO: add in alternative variants to -u-va-. - // TODO: add preferred region to -u-rg-. - if e := w.Extensions(); len(e) > 0 { - b := language.Builder{} - b.SetTag(tt) - for _, e := range e { - b.AddExt(e) - } - tt = b.Make() - } - return makeTag(tt), index, c -} - -// ErrMissingLikelyTagsData indicates no information was available -// to compute likely values of missing tags. -var ErrMissingLikelyTagsData = errors.New("missing likely tags data") - -// func (t *Tag) setTagsFrom(id Tag) { -// t.LangID = id.LangID -// t.ScriptID = id.ScriptID -// t.RegionID = id.RegionID -// } - -// Tag Matching -// CLDR defines an algorithm for finding the best match between two sets of language -// tags. The basic algorithm defines how to score a possible match and then find -// the match with the best score -// (see https://www.unicode.org/reports/tr35/#LanguageMatching). -// Using scoring has several disadvantages. The scoring obfuscates the importance of -// the various factors considered, making the algorithm harder to understand. Using -// scoring also requires the full score to be computed for each pair of tags. -// -// We will use a different algorithm which aims to have the following properties: -// - clarity on the precedence of the various selection factors, and -// - improved performance by allowing early termination of a comparison. -// -// Matching algorithm (overview) -// Input: -// - supported: a set of supported tags -// - default: the default tag to return in case there is no match -// - desired: list of desired tags, ordered by preference, starting with -// the most-preferred. -// -// Algorithm: -// 1) Set the best match to the lowest confidence level -// 2) For each tag in "desired": -// a) For each tag in "supported": -// 1) compute the match between the two tags. -// 2) if the match is better than the previous best match, replace it -// with the new match. (see next section) -// b) if the current best match is Exact and pin is true the result will be -// frozen to the language found thusfar, although better matches may -// still be found for the same language. -// 3) If the best match so far is below a certain threshold, return "default". -// -// Ranking: -// We use two phases to determine whether one pair of tags are a better match -// than another pair of tags. First, we determine a rough confidence level. If the -// levels are different, the one with the highest confidence wins. -// Second, if the rough confidence levels are identical, we use a set of tie-breaker -// rules. -// -// The confidence level of matching a pair of tags is determined by finding the -// lowest confidence level of any matches of the corresponding subtags (the -// result is deemed as good as its weakest link). -// We define the following levels: -// Exact - An exact match of a subtag, before adding likely subtags. -// MaxExact - An exact match of a subtag, after adding likely subtags. -// [See Note 2]. -// High - High level of mutual intelligibility between different subtag -// variants. -// Low - Low level of mutual intelligibility between different subtag -// variants. -// No - No mutual intelligibility. -// -// The following levels can occur for each type of subtag: -// Base: Exact, MaxExact, High, Low, No -// Script: Exact, MaxExact [see Note 3], Low, No -// Region: Exact, MaxExact, High -// Variant: Exact, High -// Private: Exact, No -// -// Any result with a confidence level of Low or higher is deemed a possible match. -// Once a desired tag matches any of the supported tags with a level of MaxExact -// or higher, the next desired tag is not considered (see Step 2.b). -// Note that CLDR provides languageMatching data that defines close equivalence -// classes for base languages, scripts and regions. -// -// Tie-breaking -// If we get the same confidence level for two matches, we apply a sequence of -// tie-breaking rules. The first that succeeds defines the result. The rules are -// applied in the following order. -// 1) Original language was defined and was identical. -// 2) Original region was defined and was identical. -// 3) Distance between two maximized regions was the smallest. -// 4) Original script was defined and was identical. -// 5) Distance from want tag to have tag using the parent relation [see Note 5.] -// If there is still no winner after these rules are applied, the first match -// found wins. -// -// Notes: -// [2] In practice, as matching of Exact is done in a separate phase from -// matching the other levels, we reuse the Exact level to mean MaxExact in -// the second phase. As a consequence, we only need the levels defined by -// the Confidence type. The MaxExact confidence level is mapped to High in -// the public API. -// [3] We do not differentiate between maximized script values that were derived -// from suppressScript versus most likely tag data. We determined that in -// ranking the two, one ranks just after the other. Moreover, the two cannot -// occur concurrently. As a consequence, they are identical for practical -// purposes. -// [4] In case of deprecated, macro-equivalents and legacy mappings, we assign -// the MaxExact level to allow iw vs he to still be a closer match than -// en-AU vs en-US, for example. -// [5] In CLDR a locale inherits fields that are unspecified for this locale -// from its parent. Therefore, if a locale is a parent of another locale, -// it is a strong measure for closeness, especially when no other tie -// breaker rule applies. One could also argue it is inconsistent, for -// example, when pt-AO matches pt (which CLDR equates with pt-BR), even -// though its parent is pt-PT according to the inheritance rules. -// -// Implementation Details: -// There are several performance considerations worth pointing out. Most notably, -// we preprocess as much as possible (within reason) at the time of creation of a -// matcher. This includes: -// - creating a per-language map, which includes data for the raw base language -// and its canonicalized variant (if applicable), -// - expanding entries for the equivalence classes defined in CLDR's -// languageMatch data. -// The per-language map ensures that typically only a very small number of tags -// need to be considered. The pre-expansion of canonicalized subtags and -// equivalence classes reduces the amount of map lookups that need to be done at -// runtime. - -// matcher keeps a set of supported language tags, indexed by language. -type matcher struct { - default_ *haveTag - supported []*haveTag - index map[language.Language]*matchHeader - passSettings bool - preferSameScript bool -} - -// matchHeader has the lists of tags for exact matches and matches based on -// maximized and canonicalized tags for a given language. -type matchHeader struct { - haveTags []*haveTag - original bool -} - -// haveTag holds a supported Tag and its maximized script and region. The maximized -// or canonicalized language is not stored as it is not needed during matching. -type haveTag struct { - tag language.Tag - - // index of this tag in the original list of supported tags. - index int - - // conf is the maximum confidence that can result from matching this haveTag. - // When conf < Exact this means it was inserted after applying a CLDR equivalence rule. - conf Confidence - - // Maximized region and script. - maxRegion language.Region - maxScript language.Script - - // altScript may be checked as an alternative match to maxScript. If altScript - // matches, the confidence level for this match is Low. Theoretically there - // could be multiple alternative scripts. This does not occur in practice. - altScript language.Script - - // nextMax is the index of the next haveTag with the same maximized tags. - nextMax uint16 -} - -func makeHaveTag(tag language.Tag, index int) (haveTag, language.Language) { - max := tag - if tag.LangID != 0 || tag.RegionID != 0 || tag.ScriptID != 0 { - max, _ = canonicalize(All, max) - max, _ = max.Maximize() - max.RemakeString() - } - return haveTag{tag, index, Exact, max.RegionID, max.ScriptID, altScript(max.LangID, max.ScriptID), 0}, max.LangID -} - -// altScript returns an alternative script that may match the given script with -// a low confidence. At the moment, the langMatch data allows for at most one -// script to map to another and we rely on this to keep the code simple. -func altScript(l language.Language, s language.Script) language.Script { - for _, alt := range matchScript { - // TODO: also match cases where language is not the same. - if (language.Language(alt.wantLang) == l || language.Language(alt.haveLang) == l) && - language.Script(alt.haveScript) == s { - return language.Script(alt.wantScript) - } - } - return 0 -} - -// addIfNew adds a haveTag to the list of tags only if it is a unique tag. -// Tags that have the same maximized values are linked by index. -func (h *matchHeader) addIfNew(n haveTag, exact bool) { - h.original = h.original || exact - // Don't add new exact matches. - for _, v := range h.haveTags { - if equalsRest(v.tag, n.tag) { - return - } - } - // Allow duplicate maximized tags, but create a linked list to allow quickly - // comparing the equivalents and bail out. - for i, v := range h.haveTags { - if v.maxScript == n.maxScript && - v.maxRegion == n.maxRegion && - v.tag.VariantOrPrivateUseTags() == n.tag.VariantOrPrivateUseTags() { - for h.haveTags[i].nextMax != 0 { - i = int(h.haveTags[i].nextMax) - } - h.haveTags[i].nextMax = uint16(len(h.haveTags)) - break - } - } - h.haveTags = append(h.haveTags, &n) -} - -// header returns the matchHeader for the given language. It creates one if -// it doesn't already exist. -func (m *matcher) header(l language.Language) *matchHeader { - if h := m.index[l]; h != nil { - return h - } - h := &matchHeader{} - m.index[l] = h - return h -} - -func toConf(d uint8) Confidence { - if d <= 10 { - return High - } - if d < 30 { - return Low - } - return No -} - -// newMatcher builds an index for the given supported tags and returns it as -// a matcher. It also expands the index by considering various equivalence classes -// for a given tag. -func newMatcher(supported []Tag, options []MatchOption) *matcher { - m := &matcher{ - index: make(map[language.Language]*matchHeader), - preferSameScript: true, - } - for _, o := range options { - o(m) - } - if len(supported) == 0 { - m.default_ = &haveTag{} - return m - } - // Add supported languages to the index. Add exact matches first to give - // them precedence. - for i, tag := range supported { - tt := tag.tag() - pair, _ := makeHaveTag(tt, i) - m.header(tt.LangID).addIfNew(pair, true) - m.supported = append(m.supported, &pair) - } - m.default_ = m.header(supported[0].lang()).haveTags[0] - // Keep these in two different loops to support the case that two equivalent - // languages are distinguished, such as iw and he. - for i, tag := range supported { - tt := tag.tag() - pair, max := makeHaveTag(tt, i) - if max != tt.LangID { - m.header(max).addIfNew(pair, true) - } - } - - // update is used to add indexes in the map for equivalent languages. - // update will only add entries to original indexes, thus not computing any - // transitive relations. - update := func(want, have uint16, conf Confidence) { - if hh := m.index[language.Language(have)]; hh != nil { - if !hh.original { - return - } - hw := m.header(language.Language(want)) - for _, ht := range hh.haveTags { - v := *ht - if conf < v.conf { - v.conf = conf - } - v.nextMax = 0 // this value needs to be recomputed - if v.altScript != 0 { - v.altScript = altScript(language.Language(want), v.maxScript) - } - hw.addIfNew(v, conf == Exact && hh.original) - } - } - } - - // Add entries for languages with mutual intelligibility as defined by CLDR's - // languageMatch data. - for _, ml := range matchLang { - update(ml.want, ml.have, toConf(ml.distance)) - if !ml.oneway { - update(ml.have, ml.want, toConf(ml.distance)) - } - } - - // Add entries for possible canonicalizations. This is an optimization to - // ensure that only one map lookup needs to be done at runtime per desired tag. - // First we match deprecated equivalents. If they are perfect equivalents - // (their canonicalization simply substitutes a different language code, but - // nothing else), the match confidence is Exact, otherwise it is High. - for i, lm := range language.AliasMap { - // If deprecated codes match and there is no fiddling with the script - // or region, we consider it an exact match. - conf := Exact - if language.AliasTypes[i] != language.Macro { - if !isExactEquivalent(language.Language(lm.From)) { - conf = High - } - update(lm.To, lm.From, conf) - } - update(lm.From, lm.To, conf) - } - return m -} - -// getBest gets the best matching tag in m for any of the given tags, taking into -// account the order of preference of the given tags. -func (m *matcher) getBest(want ...Tag) (got *haveTag, orig language.Tag, c Confidence) { - best := bestMatch{} - for i, ww := range want { - w := ww.tag() - var max language.Tag - // Check for exact match first. - h := m.index[w.LangID] - if w.LangID != 0 { - if h == nil { - continue - } - // Base language is defined. - max, _ = canonicalize(Legacy|Deprecated|Macro, w) - // A region that is added through canonicalization is stronger than - // a maximized region: set it in the original (e.g. mo -> ro-MD). - if w.RegionID != max.RegionID { - w.RegionID = max.RegionID - } - // TODO: should we do the same for scripts? - // See test case: en, sr, nl ; sh ; sr - max, _ = max.Maximize() - } else { - // Base language is not defined. - if h != nil { - for i := range h.haveTags { - have := h.haveTags[i] - if equalsRest(have.tag, w) { - return have, w, Exact - } - } - } - if w.ScriptID == 0 && w.RegionID == 0 { - // We skip all tags matching und for approximate matching, including - // private tags. - continue - } - max, _ = w.Maximize() - if h = m.index[max.LangID]; h == nil { - continue - } - } - pin := true - for _, t := range want[i+1:] { - if w.LangID == t.lang() { - pin = false - break - } - } - // Check for match based on maximized tag. - for i := range h.haveTags { - have := h.haveTags[i] - best.update(have, w, max.ScriptID, max.RegionID, pin) - if best.conf == Exact { - for have.nextMax != 0 { - have = h.haveTags[have.nextMax] - best.update(have, w, max.ScriptID, max.RegionID, pin) - } - return best.have, best.want, best.conf - } - } - } - if best.conf <= No { - if len(want) != 0 { - return nil, want[0].tag(), No - } - return nil, language.Tag{}, No - } - return best.have, best.want, best.conf -} - -// bestMatch accumulates the best match so far. -type bestMatch struct { - have *haveTag - want language.Tag - conf Confidence - pinnedRegion language.Region - pinLanguage bool - sameRegionGroup bool - // Cached results from applying tie-breaking rules. - origLang bool - origReg bool - paradigmReg bool - regGroupDist uint8 - origScript bool -} - -// update updates the existing best match if the new pair is considered to be a -// better match. To determine if the given pair is a better match, it first -// computes the rough confidence level. If this surpasses the current match, it -// will replace it and update the tie-breaker rule cache. If there is a tie, it -// proceeds with applying a series of tie-breaker rules. If there is no -// conclusive winner after applying the tie-breaker rules, it leaves the current -// match as the preferred match. -// -// If pin is true and have and tag are a strong match, it will henceforth only -// consider matches for this language. This corresponds to the idea that most -// users have a strong preference for the first defined language. A user can -// still prefer a second language over a dialect of the preferred language by -// explicitly specifying dialects, e.g. "en, nl, en-GB". In this case pin should -// be false. -func (m *bestMatch) update(have *haveTag, tag language.Tag, maxScript language.Script, maxRegion language.Region, pin bool) { - // Bail if the maximum attainable confidence is below that of the current best match. - c := have.conf - if c < m.conf { - return - } - // Don't change the language once we already have found an exact match. - if m.pinLanguage && tag.LangID != m.want.LangID { - return - } - // Pin the region group if we are comparing tags for the same language. - if tag.LangID == m.want.LangID && m.sameRegionGroup { - _, sameGroup := regionGroupDist(m.pinnedRegion, have.maxRegion, have.maxScript, m.want.LangID) - if !sameGroup { - return - } - } - if c == Exact && have.maxScript == maxScript { - // If there is another language and then another entry of this language, - // don't pin anything, otherwise pin the language. - m.pinLanguage = pin - } - if equalsRest(have.tag, tag) { - } else if have.maxScript != maxScript { - // There is usually very little comprehension between different scripts. - // In a few cases there may still be Low comprehension. This possibility - // is pre-computed and stored in have.altScript. - if Low < m.conf || have.altScript != maxScript { - return - } - c = Low - } else if have.maxRegion != maxRegion { - if High < c { - // There is usually a small difference between languages across regions. - c = High - } - } - - // We store the results of the computations of the tie-breaker rules along - // with the best match. There is no need to do the checks once we determine - // we have a winner, but we do still need to do the tie-breaker computations. - // We use "beaten" to keep track if we still need to do the checks. - beaten := false // true if the new pair defeats the current one. - if c != m.conf { - if c < m.conf { - return - } - beaten = true - } - - // Tie-breaker rules: - // We prefer if the pre-maximized language was specified and identical. - origLang := have.tag.LangID == tag.LangID && tag.LangID != 0 - if !beaten && m.origLang != origLang { - if m.origLang { - return - } - beaten = true - } - - // We prefer if the pre-maximized region was specified and identical. - origReg := have.tag.RegionID == tag.RegionID && tag.RegionID != 0 - if !beaten && m.origReg != origReg { - if m.origReg { - return - } - beaten = true - } - - regGroupDist, sameGroup := regionGroupDist(have.maxRegion, maxRegion, maxScript, tag.LangID) - if !beaten && m.regGroupDist != regGroupDist { - if regGroupDist > m.regGroupDist { - return - } - beaten = true - } - - paradigmReg := isParadigmLocale(tag.LangID, have.maxRegion) - if !beaten && m.paradigmReg != paradigmReg { - if !paradigmReg { - return - } - beaten = true - } - - // Next we prefer if the pre-maximized script was specified and identical. - origScript := have.tag.ScriptID == tag.ScriptID && tag.ScriptID != 0 - if !beaten && m.origScript != origScript { - if m.origScript { - return - } - beaten = true - } - - // Update m to the newly found best match. - if beaten { - m.have = have - m.want = tag - m.conf = c - m.pinnedRegion = maxRegion - m.sameRegionGroup = sameGroup - m.origLang = origLang - m.origReg = origReg - m.paradigmReg = paradigmReg - m.origScript = origScript - m.regGroupDist = regGroupDist - } -} - -func isParadigmLocale(lang language.Language, r language.Region) bool { - for _, e := range paradigmLocales { - if language.Language(e[0]) == lang && (r == language.Region(e[1]) || r == language.Region(e[2])) { - return true - } - } - return false -} - -// regionGroupDist computes the distance between two regions based on their -// CLDR grouping. -func regionGroupDist(a, b language.Region, script language.Script, lang language.Language) (dist uint8, same bool) { - const defaultDistance = 4 - - aGroup := uint(regionToGroups[a]) << 1 - bGroup := uint(regionToGroups[b]) << 1 - for _, ri := range matchRegion { - if language.Language(ri.lang) == lang && (ri.script == 0 || language.Script(ri.script) == script) { - group := uint(1 << (ri.group &^ 0x80)) - if 0x80&ri.group == 0 { - if aGroup&bGroup&group != 0 { // Both regions are in the group. - return ri.distance, ri.distance == defaultDistance - } - } else { - if (aGroup|bGroup)&group == 0 { // Both regions are not in the group. - return ri.distance, ri.distance == defaultDistance - } - } - } - } - return defaultDistance, true -} - -// equalsRest compares everything except the language. -func equalsRest(a, b language.Tag) bool { - // TODO: don't include extensions in this comparison. To do this efficiently, - // though, we should handle private tags separately. - return a.ScriptID == b.ScriptID && a.RegionID == b.RegionID && a.VariantOrPrivateUseTags() == b.VariantOrPrivateUseTags() -} - -// isExactEquivalent returns true if canonicalizing the language will not alter -// the script or region of a tag. -func isExactEquivalent(l language.Language) bool { - for _, o := range notEquivalent { - if o == l { - return false - } - } - return true -} - -var notEquivalent []language.Language - -func init() { - // Create a list of all languages for which canonicalization may alter the - // script or region. - for _, lm := range language.AliasMap { - tag := language.Tag{LangID: language.Language(lm.From)} - if tag, _ = canonicalize(All, tag); tag.ScriptID != 0 || tag.RegionID != 0 { - notEquivalent = append(notEquivalent, language.Language(lm.From)) - } - } - // Maximize undefined regions of paradigm locales. - for i, v := range paradigmLocales { - t := language.Tag{LangID: language.Language(v[0])} - max, _ := t.Maximize() - if v[1] == 0 { - paradigmLocales[i][1] = uint16(max.RegionID) - } - if v[2] == 0 { - paradigmLocales[i][2] = uint16(max.RegionID) - } - } -} diff --git a/vendor/golang.org/x/text/language/parse.go b/vendor/golang.org/x/text/language/parse.go deleted file mode 100644 index 053336e2..00000000 --- a/vendor/golang.org/x/text/language/parse.go +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import ( - "errors" - "sort" - "strconv" - "strings" - - "golang.org/x/text/internal/language" -) - -// ValueError is returned by any of the parsing functions when the -// input is well-formed but the respective subtag is not recognized -// as a valid value. -type ValueError interface { - error - - // Subtag returns the subtag for which the error occurred. - Subtag() string -} - -// Parse parses the given BCP 47 string and returns a valid Tag. If parsing -// failed it returns an error and any part of the tag that could be parsed. -// If parsing succeeded but an unknown value was found, it returns -// ValueError. The Tag returned in this case is just stripped of the unknown -// value. All other values are preserved. It accepts tags in the BCP 47 format -// and extensions to this standard defined in -// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. -// The resulting tag is canonicalized using the default canonicalization type. -func Parse(s string) (t Tag, err error) { - return Default.Parse(s) -} - -// Parse parses the given BCP 47 string and returns a valid Tag. If parsing -// failed it returns an error and any part of the tag that could be parsed. -// If parsing succeeded but an unknown value was found, it returns -// ValueError. The Tag returned in this case is just stripped of the unknown -// value. All other values are preserved. It accepts tags in the BCP 47 format -// and extensions to this standard defined in -// https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. -// The resulting tag is canonicalized using the canonicalization type c. -func (c CanonType) Parse(s string) (t Tag, err error) { - defer func() { - if recover() != nil { - t = Tag{} - err = language.ErrSyntax - } - }() - - tt, err := language.Parse(s) - if err != nil { - return makeTag(tt), err - } - tt, changed := canonicalize(c, tt) - if changed { - tt.RemakeString() - } - return makeTag(tt), nil -} - -// Compose creates a Tag from individual parts, which may be of type Tag, Base, -// Script, Region, Variant, []Variant, Extension, []Extension or error. If a -// Base, Script or Region or slice of type Variant or Extension is passed more -// than once, the latter will overwrite the former. Variants and Extensions are -// accumulated, but if two extensions of the same type are passed, the latter -// will replace the former. For -u extensions, though, the key-type pairs are -// added, where later values overwrite older ones. A Tag overwrites all former -// values and typically only makes sense as the first argument. The resulting -// tag is returned after canonicalizing using the Default CanonType. If one or -// more errors are encountered, one of the errors is returned. -func Compose(part ...interface{}) (t Tag, err error) { - return Default.Compose(part...) -} - -// Compose creates a Tag from individual parts, which may be of type Tag, Base, -// Script, Region, Variant, []Variant, Extension, []Extension or error. If a -// Base, Script or Region or slice of type Variant or Extension is passed more -// than once, the latter will overwrite the former. Variants and Extensions are -// accumulated, but if two extensions of the same type are passed, the latter -// will replace the former. For -u extensions, though, the key-type pairs are -// added, where later values overwrite older ones. A Tag overwrites all former -// values and typically only makes sense as the first argument. The resulting -// tag is returned after canonicalizing using CanonType c. If one or more errors -// are encountered, one of the errors is returned. -func (c CanonType) Compose(part ...interface{}) (t Tag, err error) { - defer func() { - if recover() != nil { - t = Tag{} - err = language.ErrSyntax - } - }() - - var b language.Builder - if err = update(&b, part...); err != nil { - return und, err - } - b.Tag, _ = canonicalize(c, b.Tag) - return makeTag(b.Make()), err -} - -var errInvalidArgument = errors.New("invalid Extension or Variant") - -func update(b *language.Builder, part ...interface{}) (err error) { - for _, x := range part { - switch v := x.(type) { - case Tag: - b.SetTag(v.tag()) - case Base: - b.Tag.LangID = v.langID - case Script: - b.Tag.ScriptID = v.scriptID - case Region: - b.Tag.RegionID = v.regionID - case Variant: - if v.variant == "" { - err = errInvalidArgument - break - } - b.AddVariant(v.variant) - case Extension: - if v.s == "" { - err = errInvalidArgument - break - } - b.SetExt(v.s) - case []Variant: - b.ClearVariants() - for _, v := range v { - b.AddVariant(v.variant) - } - case []Extension: - b.ClearExtensions() - for _, e := range v { - b.SetExt(e.s) - } - // TODO: support parsing of raw strings based on morphology or just extensions? - case error: - if v != nil { - err = v - } - } - } - return -} - -var errInvalidWeight = errors.New("ParseAcceptLanguage: invalid weight") -var errTagListTooLarge = errors.New("tag list exceeds max length") - -// ParseAcceptLanguage parses the contents of an Accept-Language header as -// defined in http://www.ietf.org/rfc/rfc2616.txt and returns a list of Tags and -// a list of corresponding quality weights. It is more permissive than RFC 2616 -// and may return non-nil slices even if the input is not valid. -// The Tags will be sorted by highest weight first and then by first occurrence. -// Tags with a weight of zero will be dropped. An error will be returned if the -// input could not be parsed. -func ParseAcceptLanguage(s string) (tag []Tag, q []float32, err error) { - defer func() { - if recover() != nil { - tag = nil - q = nil - err = language.ErrSyntax - } - }() - - if strings.Count(s, "-") > 1000 { - return nil, nil, errTagListTooLarge - } - - var entry string - for s != "" { - if entry, s = split(s, ','); entry == "" { - continue - } - - entry, weight := split(entry, ';') - - // Scan the language. - t, err := Parse(entry) - if err != nil { - id, ok := acceptFallback[entry] - if !ok { - return nil, nil, err - } - t = makeTag(language.Tag{LangID: id}) - } - - // Scan the optional weight. - w := 1.0 - if weight != "" { - weight = consume(weight, 'q') - weight = consume(weight, '=') - // consume returns the empty string when a token could not be - // consumed, resulting in an error for ParseFloat. - if w, err = strconv.ParseFloat(weight, 32); err != nil { - return nil, nil, errInvalidWeight - } - // Drop tags with a quality weight of 0. - if w <= 0 { - continue - } - } - - tag = append(tag, t) - q = append(q, float32(w)) - } - sort.Stable(&tagSort{tag, q}) - return tag, q, nil -} - -// consume removes a leading token c from s and returns the result or the empty -// string if there is no such token. -func consume(s string, c byte) string { - if s == "" || s[0] != c { - return "" - } - return strings.TrimSpace(s[1:]) -} - -func split(s string, c byte) (head, tail string) { - if i := strings.IndexByte(s, c); i >= 0 { - return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+1:]) - } - return strings.TrimSpace(s), "" -} - -// Add hack mapping to deal with a small number of cases that occur -// in Accept-Language (with reasonable frequency). -var acceptFallback = map[string]language.Language{ - "english": _en, - "deutsch": _de, - "italian": _it, - "french": _fr, - "*": _mul, // defined in the spec to match all languages. -} - -type tagSort struct { - tag []Tag - q []float32 -} - -func (s *tagSort) Len() int { - return len(s.q) -} - -func (s *tagSort) Less(i, j int) bool { - return s.q[i] > s.q[j] -} - -func (s *tagSort) Swap(i, j int) { - s.tag[i], s.tag[j] = s.tag[j], s.tag[i] - s.q[i], s.q[j] = s.q[j], s.q[i] -} diff --git a/vendor/golang.org/x/text/language/tables.go b/vendor/golang.org/x/text/language/tables.go deleted file mode 100644 index a6573dcb..00000000 --- a/vendor/golang.org/x/text/language/tables.go +++ /dev/null @@ -1,298 +0,0 @@ -// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. - -package language - -// CLDRVersion is the CLDR version from which the tables in this package are derived. -const CLDRVersion = "32" - -const ( - _de = 269 - _en = 313 - _fr = 350 - _it = 505 - _mo = 784 - _no = 879 - _nb = 839 - _pt = 960 - _sh = 1031 - _mul = 806 - _und = 0 -) -const ( - _001 = 1 - _419 = 31 - _BR = 65 - _CA = 73 - _ES = 111 - _GB = 124 - _MD = 189 - _PT = 239 - _UK = 307 - _US = 310 - _ZZ = 358 - _XA = 324 - _XC = 326 - _XK = 334 -) -const ( - _Latn = 91 - _Hani = 57 - _Hans = 59 - _Hant = 60 - _Qaaa = 149 - _Qaai = 157 - _Qabx = 198 - _Zinh = 255 - _Zyyy = 260 - _Zzzz = 261 -) - -var regionToGroups = []uint8{ // 359 elements - // Entry 0 - 3F - 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, - // Entry 40 - 7F - 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, - 0x08, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, - // Entry 80 - BF - 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x01, 0x00, 0x04, 0x02, 0x00, - 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x04, - // Entry C0 - FF - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x01, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Entry 100 - 13F - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x05, 0x00, - // Entry 140 - 17F - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -} // Size: 383 bytes - -var paradigmLocales = [][3]uint16{ // 3 elements - 0: [3]uint16{0x139, 0x0, 0x7c}, - 1: [3]uint16{0x13e, 0x0, 0x1f}, - 2: [3]uint16{0x3c0, 0x41, 0xef}, -} // Size: 42 bytes - -type mutualIntelligibility struct { - want uint16 - have uint16 - distance uint8 - oneway bool -} -type scriptIntelligibility struct { - wantLang uint16 - haveLang uint16 - wantScript uint8 - haveScript uint8 - distance uint8 -} -type regionIntelligibility struct { - lang uint16 - script uint8 - group uint8 - distance uint8 -} - -// matchLang holds pairs of langIDs of base languages that are typically -// mutually intelligible. Each pair is associated with a confidence and -// whether the intelligibility goes one or both ways. -var matchLang = []mutualIntelligibility{ // 113 elements - 0: {want: 0x1d1, have: 0xb7, distance: 0x4, oneway: false}, - 1: {want: 0x407, have: 0xb7, distance: 0x4, oneway: false}, - 2: {want: 0x407, have: 0x1d1, distance: 0x4, oneway: false}, - 3: {want: 0x407, have: 0x432, distance: 0x4, oneway: false}, - 4: {want: 0x43a, have: 0x1, distance: 0x4, oneway: false}, - 5: {want: 0x1a3, have: 0x10d, distance: 0x4, oneway: true}, - 6: {want: 0x295, have: 0x10d, distance: 0x4, oneway: true}, - 7: {want: 0x101, have: 0x36f, distance: 0x8, oneway: false}, - 8: {want: 0x101, have: 0x347, distance: 0x8, oneway: false}, - 9: {want: 0x5, have: 0x3e2, distance: 0xa, oneway: true}, - 10: {want: 0xd, have: 0x139, distance: 0xa, oneway: true}, - 11: {want: 0x16, have: 0x367, distance: 0xa, oneway: true}, - 12: {want: 0x21, have: 0x139, distance: 0xa, oneway: true}, - 13: {want: 0x56, have: 0x13e, distance: 0xa, oneway: true}, - 14: {want: 0x58, have: 0x3e2, distance: 0xa, oneway: true}, - 15: {want: 0x71, have: 0x3e2, distance: 0xa, oneway: true}, - 16: {want: 0x75, have: 0x139, distance: 0xa, oneway: true}, - 17: {want: 0x82, have: 0x1be, distance: 0xa, oneway: true}, - 18: {want: 0xa5, have: 0x139, distance: 0xa, oneway: true}, - 19: {want: 0xb2, have: 0x15e, distance: 0xa, oneway: true}, - 20: {want: 0xdd, have: 0x153, distance: 0xa, oneway: true}, - 21: {want: 0xe5, have: 0x139, distance: 0xa, oneway: true}, - 22: {want: 0xe9, have: 0x3a, distance: 0xa, oneway: true}, - 23: {want: 0xf0, have: 0x15e, distance: 0xa, oneway: true}, - 24: {want: 0xf9, have: 0x15e, distance: 0xa, oneway: true}, - 25: {want: 0x100, have: 0x139, distance: 0xa, oneway: true}, - 26: {want: 0x130, have: 0x139, distance: 0xa, oneway: true}, - 27: {want: 0x13c, have: 0x139, distance: 0xa, oneway: true}, - 28: {want: 0x140, have: 0x151, distance: 0xa, oneway: true}, - 29: {want: 0x145, have: 0x13e, distance: 0xa, oneway: true}, - 30: {want: 0x158, have: 0x101, distance: 0xa, oneway: true}, - 31: {want: 0x16d, have: 0x367, distance: 0xa, oneway: true}, - 32: {want: 0x16e, have: 0x139, distance: 0xa, oneway: true}, - 33: {want: 0x16f, have: 0x139, distance: 0xa, oneway: true}, - 34: {want: 0x17e, have: 0x139, distance: 0xa, oneway: true}, - 35: {want: 0x190, have: 0x13e, distance: 0xa, oneway: true}, - 36: {want: 0x194, have: 0x13e, distance: 0xa, oneway: true}, - 37: {want: 0x1a4, have: 0x1be, distance: 0xa, oneway: true}, - 38: {want: 0x1b4, have: 0x139, distance: 0xa, oneway: true}, - 39: {want: 0x1b8, have: 0x139, distance: 0xa, oneway: true}, - 40: {want: 0x1d4, have: 0x15e, distance: 0xa, oneway: true}, - 41: {want: 0x1d7, have: 0x3e2, distance: 0xa, oneway: true}, - 42: {want: 0x1d9, have: 0x139, distance: 0xa, oneway: true}, - 43: {want: 0x1e7, have: 0x139, distance: 0xa, oneway: true}, - 44: {want: 0x1f8, have: 0x139, distance: 0xa, oneway: true}, - 45: {want: 0x20e, have: 0x1e1, distance: 0xa, oneway: true}, - 46: {want: 0x210, have: 0x139, distance: 0xa, oneway: true}, - 47: {want: 0x22d, have: 0x15e, distance: 0xa, oneway: true}, - 48: {want: 0x242, have: 0x3e2, distance: 0xa, oneway: true}, - 49: {want: 0x24a, have: 0x139, distance: 0xa, oneway: true}, - 50: {want: 0x251, have: 0x139, distance: 0xa, oneway: true}, - 51: {want: 0x265, have: 0x139, distance: 0xa, oneway: true}, - 52: {want: 0x274, have: 0x48a, distance: 0xa, oneway: true}, - 53: {want: 0x28a, have: 0x3e2, distance: 0xa, oneway: true}, - 54: {want: 0x28e, have: 0x1f9, distance: 0xa, oneway: true}, - 55: {want: 0x2a3, have: 0x139, distance: 0xa, oneway: true}, - 56: {want: 0x2b5, have: 0x15e, distance: 0xa, oneway: true}, - 57: {want: 0x2b8, have: 0x139, distance: 0xa, oneway: true}, - 58: {want: 0x2be, have: 0x139, distance: 0xa, oneway: true}, - 59: {want: 0x2c3, have: 0x15e, distance: 0xa, oneway: true}, - 60: {want: 0x2ed, have: 0x139, distance: 0xa, oneway: true}, - 61: {want: 0x2f1, have: 0x15e, distance: 0xa, oneway: true}, - 62: {want: 0x2fa, have: 0x139, distance: 0xa, oneway: true}, - 63: {want: 0x2ff, have: 0x7e, distance: 0xa, oneway: true}, - 64: {want: 0x304, have: 0x139, distance: 0xa, oneway: true}, - 65: {want: 0x30b, have: 0x3e2, distance: 0xa, oneway: true}, - 66: {want: 0x31b, have: 0x1be, distance: 0xa, oneway: true}, - 67: {want: 0x31f, have: 0x1e1, distance: 0xa, oneway: true}, - 68: {want: 0x320, have: 0x139, distance: 0xa, oneway: true}, - 69: {want: 0x331, have: 0x139, distance: 0xa, oneway: true}, - 70: {want: 0x351, have: 0x139, distance: 0xa, oneway: true}, - 71: {want: 0x36a, have: 0x347, distance: 0xa, oneway: false}, - 72: {want: 0x36a, have: 0x36f, distance: 0xa, oneway: true}, - 73: {want: 0x37a, have: 0x139, distance: 0xa, oneway: true}, - 74: {want: 0x387, have: 0x139, distance: 0xa, oneway: true}, - 75: {want: 0x389, have: 0x139, distance: 0xa, oneway: true}, - 76: {want: 0x38b, have: 0x15e, distance: 0xa, oneway: true}, - 77: {want: 0x390, have: 0x139, distance: 0xa, oneway: true}, - 78: {want: 0x395, have: 0x139, distance: 0xa, oneway: true}, - 79: {want: 0x39d, have: 0x139, distance: 0xa, oneway: true}, - 80: {want: 0x3a5, have: 0x139, distance: 0xa, oneway: true}, - 81: {want: 0x3be, have: 0x139, distance: 0xa, oneway: true}, - 82: {want: 0x3c4, have: 0x13e, distance: 0xa, oneway: true}, - 83: {want: 0x3d4, have: 0x10d, distance: 0xa, oneway: true}, - 84: {want: 0x3d9, have: 0x139, distance: 0xa, oneway: true}, - 85: {want: 0x3e5, have: 0x15e, distance: 0xa, oneway: true}, - 86: {want: 0x3e9, have: 0x1be, distance: 0xa, oneway: true}, - 87: {want: 0x3fa, have: 0x139, distance: 0xa, oneway: true}, - 88: {want: 0x40c, have: 0x139, distance: 0xa, oneway: true}, - 89: {want: 0x423, have: 0x139, distance: 0xa, oneway: true}, - 90: {want: 0x429, have: 0x139, distance: 0xa, oneway: true}, - 91: {want: 0x431, have: 0x139, distance: 0xa, oneway: true}, - 92: {want: 0x43b, have: 0x139, distance: 0xa, oneway: true}, - 93: {want: 0x43e, have: 0x1e1, distance: 0xa, oneway: true}, - 94: {want: 0x445, have: 0x139, distance: 0xa, oneway: true}, - 95: {want: 0x450, have: 0x139, distance: 0xa, oneway: true}, - 96: {want: 0x461, have: 0x139, distance: 0xa, oneway: true}, - 97: {want: 0x467, have: 0x3e2, distance: 0xa, oneway: true}, - 98: {want: 0x46f, have: 0x139, distance: 0xa, oneway: true}, - 99: {want: 0x476, have: 0x3e2, distance: 0xa, oneway: true}, - 100: {want: 0x3883, have: 0x139, distance: 0xa, oneway: true}, - 101: {want: 0x480, have: 0x139, distance: 0xa, oneway: true}, - 102: {want: 0x482, have: 0x139, distance: 0xa, oneway: true}, - 103: {want: 0x494, have: 0x3e2, distance: 0xa, oneway: true}, - 104: {want: 0x49d, have: 0x139, distance: 0xa, oneway: true}, - 105: {want: 0x4ac, have: 0x529, distance: 0xa, oneway: true}, - 106: {want: 0x4b4, have: 0x139, distance: 0xa, oneway: true}, - 107: {want: 0x4bc, have: 0x3e2, distance: 0xa, oneway: true}, - 108: {want: 0x4e5, have: 0x15e, distance: 0xa, oneway: true}, - 109: {want: 0x4f2, have: 0x139, distance: 0xa, oneway: true}, - 110: {want: 0x512, have: 0x139, distance: 0xa, oneway: true}, - 111: {want: 0x518, have: 0x139, distance: 0xa, oneway: true}, - 112: {want: 0x52f, have: 0x139, distance: 0xa, oneway: true}, -} // Size: 702 bytes - -// matchScript holds pairs of scriptIDs where readers of one script -// can typically also read the other. Each is associated with a confidence. -var matchScript = []scriptIntelligibility{ // 26 elements - 0: {wantLang: 0x432, haveLang: 0x432, wantScript: 0x5b, haveScript: 0x20, distance: 0x5}, - 1: {wantLang: 0x432, haveLang: 0x432, wantScript: 0x20, haveScript: 0x5b, distance: 0x5}, - 2: {wantLang: 0x58, haveLang: 0x3e2, wantScript: 0x5b, haveScript: 0x20, distance: 0xa}, - 3: {wantLang: 0xa5, haveLang: 0x139, wantScript: 0xe, haveScript: 0x5b, distance: 0xa}, - 4: {wantLang: 0x1d7, haveLang: 0x3e2, wantScript: 0x8, haveScript: 0x20, distance: 0xa}, - 5: {wantLang: 0x210, haveLang: 0x139, wantScript: 0x2e, haveScript: 0x5b, distance: 0xa}, - 6: {wantLang: 0x24a, haveLang: 0x139, wantScript: 0x4f, haveScript: 0x5b, distance: 0xa}, - 7: {wantLang: 0x251, haveLang: 0x139, wantScript: 0x53, haveScript: 0x5b, distance: 0xa}, - 8: {wantLang: 0x2b8, haveLang: 0x139, wantScript: 0x58, haveScript: 0x5b, distance: 0xa}, - 9: {wantLang: 0x304, haveLang: 0x139, wantScript: 0x6f, haveScript: 0x5b, distance: 0xa}, - 10: {wantLang: 0x331, haveLang: 0x139, wantScript: 0x76, haveScript: 0x5b, distance: 0xa}, - 11: {wantLang: 0x351, haveLang: 0x139, wantScript: 0x22, haveScript: 0x5b, distance: 0xa}, - 12: {wantLang: 0x395, haveLang: 0x139, wantScript: 0x83, haveScript: 0x5b, distance: 0xa}, - 13: {wantLang: 0x39d, haveLang: 0x139, wantScript: 0x36, haveScript: 0x5b, distance: 0xa}, - 14: {wantLang: 0x3be, haveLang: 0x139, wantScript: 0x5, haveScript: 0x5b, distance: 0xa}, - 15: {wantLang: 0x3fa, haveLang: 0x139, wantScript: 0x5, haveScript: 0x5b, distance: 0xa}, - 16: {wantLang: 0x40c, haveLang: 0x139, wantScript: 0xd6, haveScript: 0x5b, distance: 0xa}, - 17: {wantLang: 0x450, haveLang: 0x139, wantScript: 0xe6, haveScript: 0x5b, distance: 0xa}, - 18: {wantLang: 0x461, haveLang: 0x139, wantScript: 0xe9, haveScript: 0x5b, distance: 0xa}, - 19: {wantLang: 0x46f, haveLang: 0x139, wantScript: 0x2c, haveScript: 0x5b, distance: 0xa}, - 20: {wantLang: 0x476, haveLang: 0x3e2, wantScript: 0x5b, haveScript: 0x20, distance: 0xa}, - 21: {wantLang: 0x4b4, haveLang: 0x139, wantScript: 0x5, haveScript: 0x5b, distance: 0xa}, - 22: {wantLang: 0x4bc, haveLang: 0x3e2, wantScript: 0x5b, haveScript: 0x20, distance: 0xa}, - 23: {wantLang: 0x512, haveLang: 0x139, wantScript: 0x3e, haveScript: 0x5b, distance: 0xa}, - 24: {wantLang: 0x529, haveLang: 0x529, wantScript: 0x3b, haveScript: 0x3c, distance: 0xf}, - 25: {wantLang: 0x529, haveLang: 0x529, wantScript: 0x3c, haveScript: 0x3b, distance: 0x13}, -} // Size: 232 bytes - -var matchRegion = []regionIntelligibility{ // 15 elements - 0: {lang: 0x3a, script: 0x0, group: 0x4, distance: 0x4}, - 1: {lang: 0x3a, script: 0x0, group: 0x84, distance: 0x4}, - 2: {lang: 0x139, script: 0x0, group: 0x1, distance: 0x4}, - 3: {lang: 0x139, script: 0x0, group: 0x81, distance: 0x4}, - 4: {lang: 0x13e, script: 0x0, group: 0x3, distance: 0x4}, - 5: {lang: 0x13e, script: 0x0, group: 0x83, distance: 0x4}, - 6: {lang: 0x3c0, script: 0x0, group: 0x3, distance: 0x4}, - 7: {lang: 0x3c0, script: 0x0, group: 0x83, distance: 0x4}, - 8: {lang: 0x529, script: 0x3c, group: 0x2, distance: 0x4}, - 9: {lang: 0x529, script: 0x3c, group: 0x82, distance: 0x4}, - 10: {lang: 0x3a, script: 0x0, group: 0x80, distance: 0x5}, - 11: {lang: 0x139, script: 0x0, group: 0x80, distance: 0x5}, - 12: {lang: 0x13e, script: 0x0, group: 0x80, distance: 0x5}, - 13: {lang: 0x3c0, script: 0x0, group: 0x80, distance: 0x5}, - 14: {lang: 0x529, script: 0x3c, group: 0x80, distance: 0x5}, -} // Size: 114 bytes - -// Total table size 1473 bytes (1KiB); checksum: 7BB90B5C diff --git a/vendor/golang.org/x/text/language/tags.go b/vendor/golang.org/x/text/language/tags.go deleted file mode 100644 index 42ea7926..00000000 --- a/vendor/golang.org/x/text/language/tags.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package language - -import "golang.org/x/text/internal/language/compact" - -// TODO: Various sets of commonly use tags and regions. - -// MustParse is like Parse, but panics if the given BCP 47 tag cannot be parsed. -// It simplifies safe initialization of Tag values. -func MustParse(s string) Tag { - t, err := Parse(s) - if err != nil { - panic(err) - } - return t -} - -// MustParse is like Parse, but panics if the given BCP 47 tag cannot be parsed. -// It simplifies safe initialization of Tag values. -func (c CanonType) MustParse(s string) Tag { - t, err := c.Parse(s) - if err != nil { - panic(err) - } - return t -} - -// MustParseBase is like ParseBase, but panics if the given base cannot be parsed. -// It simplifies safe initialization of Base values. -func MustParseBase(s string) Base { - b, err := ParseBase(s) - if err != nil { - panic(err) - } - return b -} - -// MustParseScript is like ParseScript, but panics if the given script cannot be -// parsed. It simplifies safe initialization of Script values. -func MustParseScript(s string) Script { - scr, err := ParseScript(s) - if err != nil { - panic(err) - } - return scr -} - -// MustParseRegion is like ParseRegion, but panics if the given region cannot be -// parsed. It simplifies safe initialization of Region values. -func MustParseRegion(s string) Region { - r, err := ParseRegion(s) - if err != nil { - panic(err) - } - return r -} - -var ( - und = Tag{} - - Und Tag = Tag{} - - Afrikaans Tag = Tag(compact.Afrikaans) - Amharic Tag = Tag(compact.Amharic) - Arabic Tag = Tag(compact.Arabic) - ModernStandardArabic Tag = Tag(compact.ModernStandardArabic) - Azerbaijani Tag = Tag(compact.Azerbaijani) - Bulgarian Tag = Tag(compact.Bulgarian) - Bengali Tag = Tag(compact.Bengali) - Catalan Tag = Tag(compact.Catalan) - Czech Tag = Tag(compact.Czech) - Danish Tag = Tag(compact.Danish) - German Tag = Tag(compact.German) - Greek Tag = Tag(compact.Greek) - English Tag = Tag(compact.English) - AmericanEnglish Tag = Tag(compact.AmericanEnglish) - BritishEnglish Tag = Tag(compact.BritishEnglish) - Spanish Tag = Tag(compact.Spanish) - EuropeanSpanish Tag = Tag(compact.EuropeanSpanish) - LatinAmericanSpanish Tag = Tag(compact.LatinAmericanSpanish) - Estonian Tag = Tag(compact.Estonian) - Persian Tag = Tag(compact.Persian) - Finnish Tag = Tag(compact.Finnish) - Filipino Tag = Tag(compact.Filipino) - French Tag = Tag(compact.French) - CanadianFrench Tag = Tag(compact.CanadianFrench) - Gujarati Tag = Tag(compact.Gujarati) - Hebrew Tag = Tag(compact.Hebrew) - Hindi Tag = Tag(compact.Hindi) - Croatian Tag = Tag(compact.Croatian) - Hungarian Tag = Tag(compact.Hungarian) - Armenian Tag = Tag(compact.Armenian) - Indonesian Tag = Tag(compact.Indonesian) - Icelandic Tag = Tag(compact.Icelandic) - Italian Tag = Tag(compact.Italian) - Japanese Tag = Tag(compact.Japanese) - Georgian Tag = Tag(compact.Georgian) - Kazakh Tag = Tag(compact.Kazakh) - Khmer Tag = Tag(compact.Khmer) - Kannada Tag = Tag(compact.Kannada) - Korean Tag = Tag(compact.Korean) - Kirghiz Tag = Tag(compact.Kirghiz) - Lao Tag = Tag(compact.Lao) - Lithuanian Tag = Tag(compact.Lithuanian) - Latvian Tag = Tag(compact.Latvian) - Macedonian Tag = Tag(compact.Macedonian) - Malayalam Tag = Tag(compact.Malayalam) - Mongolian Tag = Tag(compact.Mongolian) - Marathi Tag = Tag(compact.Marathi) - Malay Tag = Tag(compact.Malay) - Burmese Tag = Tag(compact.Burmese) - Nepali Tag = Tag(compact.Nepali) - Dutch Tag = Tag(compact.Dutch) - Norwegian Tag = Tag(compact.Norwegian) - Punjabi Tag = Tag(compact.Punjabi) - Polish Tag = Tag(compact.Polish) - Portuguese Tag = Tag(compact.Portuguese) - BrazilianPortuguese Tag = Tag(compact.BrazilianPortuguese) - EuropeanPortuguese Tag = Tag(compact.EuropeanPortuguese) - Romanian Tag = Tag(compact.Romanian) - Russian Tag = Tag(compact.Russian) - Sinhala Tag = Tag(compact.Sinhala) - Slovak Tag = Tag(compact.Slovak) - Slovenian Tag = Tag(compact.Slovenian) - Albanian Tag = Tag(compact.Albanian) - Serbian Tag = Tag(compact.Serbian) - SerbianLatin Tag = Tag(compact.SerbianLatin) - Swedish Tag = Tag(compact.Swedish) - Swahili Tag = Tag(compact.Swahili) - Tamil Tag = Tag(compact.Tamil) - Telugu Tag = Tag(compact.Telugu) - Thai Tag = Tag(compact.Thai) - Turkish Tag = Tag(compact.Turkish) - Ukrainian Tag = Tag(compact.Ukrainian) - Urdu Tag = Tag(compact.Urdu) - Uzbek Tag = Tag(compact.Uzbek) - Vietnamese Tag = Tag(compact.Vietnamese) - Chinese Tag = Tag(compact.Chinese) - SimplifiedChinese Tag = Tag(compact.SimplifiedChinese) - TraditionalChinese Tag = Tag(compact.TraditionalChinese) - Zulu Tag = Tag(compact.Zulu) -) diff --git a/vendor/gonum.org/v1/gonum/AUTHORS b/vendor/gonum.org/v1/gonum/AUTHORS deleted file mode 100644 index 1f0e79b4..00000000 --- a/vendor/gonum.org/v1/gonum/AUTHORS +++ /dev/null @@ -1,141 +0,0 @@ -# This is the official list of Gonum authors for copyright purposes. -# This file is distinct from the CONTRIBUTORS files. -# See the latter for an explanation. - -# Names should be added to this file as -# Name or Organization <email address> -# The email address is not required for organizations. - -# Please keep the list sorted. - -Alexander Egurnov <alexander.egurnov@gmail.com> -Andrei Blinnikov <goofinator@mail.ru> -antichris <chris@u-d13.com> -Bailey Lissington <lissington4@gmail.com> -Bill Gray <wgray@gogray.com> -Bill Noon <noon.bill@gmail.com> -Brendan Tracey <tracey.brendan@gmail.com> -Brent Pedersen <bpederse@gmail.com> -Bulat Khasanov <afti@yandex.ru> -Chad Kunde <kunde21@gmail.com> -Chan Kwan Yin <sofe2038@gmail.com> -Chih-Wei Chang <bert.cwchang@gmail.com> -Chong-Yeol Nah <nahchongyeol@gmail.com> -Chris Tessum <ctessum@gmail.com> -Christophe Meessen <christophe.meessen@gmail.com> -Christopher Waldon <christopher.waldon.dev@gmail.com> -Clayton Northey <clayton.northey@gmail.com> -Coana ApS -Dan Kortschak <dan.kortschak@adelaide.edu.au> <dan@kortschak.io> -Daniel Fireman <danielfireman@gmail.com> -Dario Heinisch <dario.heinisch@gmail.com> -David Kleiven <davidkleiven446@gmail.com> -David Samborski <bloggingarrow@gmail.com> -Davor Kapsa <davor.kapsa@gmail.com> -DeepMind Technologies -Delaney Gillilan <delaneygillilan@gmail.com> -Dezmond Goff <goff.dezmond@gmail.com> -Dirk Müller <dirk@dmllr.de> -Dong-hee Na <donghee.na92@gmail.com> -Dustin Spicuzza <dustin@virtualroadside.com> -Egon Elbre <egonelbre@gmail.com> -Ekaterina Efimova <katerina.efimova@gmail.com> -Eng Zer Jun <engzerjun@gmail.com> -Ethan Burns <burns.ethan@gmail.com> -Ethan Reesor <ethan.reesor@gmail.com> -Evert Lammerts <evert.lammerts@gmail.com> -Evgeny Savinov <notime.sea@gmail.com> -Fabian Wickborn <fabian@wickborn.net> -Facundo Gaich <facugaich@gmail.com> -Fazlul Shahriar <fshahriar@gmail.com> -Francesc Campoy <campoy@golang.org> -Google Inc -Gustaf Johansson <gustaf@pinon.se> -Hossein Zolfi <hossein.zolfi@gmail.com> -Huang Peng Fei <huangpengfei@outlook.com> -Iakov Davydov <iakov.davydov@unil.ch> -Igor Mikushkin <igor.mikushkin@gmail.com> -Iskander Sharipov <quasilyte@gmail.com> -Jack Tudbury -Jalem Raj Rohit <jrajrohit33@gmail.com> -James Bell <james@stellentus.com> -James Bowman <james.edward.bowman@gmail.com> -James Holmes <32bitkid@gmail.com> -Janne Snabb <snabb@epipe.com> -Jeremy Atkinson <jchatkinson@gmail.com> -Jes Cok <xigua67damn@gmail.com> -Jinesi Yelizati <i63888888@163.com> -Jonas Kahler <jonas@derkahler.de> -Jonas Schulze <jonas.schulze@ovgu.de> -Jonathan Bluett-Duncan <jbluettduncan@gmail.com> -Jonathan J Lawlor <jonathan.lawlor@gmail.com> -Jonathan Reiter <jonreiter@gmail.com> -Jonathan Schroeder <jd.schroeder@gmail.com> -Joost van Amersfoort <git@joo.st> -Jordan Stoker <jordan_stoker@hotmail.com> -Joseph Watson <jtwatson@linux-consulting.us> -Josh Wilson <josh.craig.wilson@gmail.com> -Julien Roland <juroland@gmail.com> -Kai Trukenmüller <ktye78@gmail.com> -Kendall Marcus <knowmost@outlook.com> -Kent English <kent.english@gmail.com> -Kevin C. Zimmerman <kevinczimmerman@gmail.com> -Kirill Motkov <motkov.kirill@gmail.com> -Konstantin Shaposhnikov <k.shaposhnikov@gmail.com> -Leonid Kneller <recondite.matter@gmail.com> -Lyron Winderbaum <lyron.winderbaum@student.adelaide.edu.au> <armadilloa16@gmail.com> <lyron.winderbaum@uwa.edu.au> -Marco Leogrande <dark.knight.ita@gmail.com> -Mark Canning <argusdusty@gmail.com> -Mark Skilbeck <markskilbeck@gmail.com> -Martin Diz <github@martindiz.com.ar> -Matthew Connelly <matthew.b.connelly@gmail.com> -Matthieu Di Mercurio <matthieu.dimercurio@gmail.com> -Max Halford <maxhalford25@gmail.com> -Maxim Sergeev <gudvinr@gmail.com> -Microsoft Corporation -MinJae Kwon <k239507@gmail.com> -Nathan Edwards <etaoinshrdluwho@gmail.com> -Nick Potts <nick@the-potts.com> -Nils Wogatzky <odog@netcologne.de> -Olivier Wulveryck <olivier.wulveryck@gmail.com> -Or Rikon <rikonor@gmail.com> -Patricio Whittingslow <graded.sp@gmail.com> -Patrick DeVivo <patrick@tickgit.com> -Pontus Melke <pontusmelke@gmail.com> -Renee French -Rishi Desai <desai.rishi1@gmail.com> -Robert Kleffner <rob.kleffner@gmail.com> -Robin Eklind <r.eklind.87@gmail.com> -Roger Welin <roger.welin@icloud.com> -Rondall Jones <rejones7@gmail.com> -Sam Zaydel <szaydel@gmail.com> -Samuel Kelemen <Samuel@Kelemen.us> -Saran Ahluwalia <ahlusar.ahluwalia@gmail.com> -Scott Holden <scott@sshconnection.com> -Scott Kiesel <kiesel.scott@gmail.com> -Sebastien Binet <seb.binet@gmail.com> -Shawn Smith <shawnpsmith@gmail.com> -Sintela Ltd -source{d} <hello@sourced.tech> -Spencer Lyon <spencerlyon2@gmail.com> -Steve McCoy <mccoyst@gmail.com> -Taesu Pyo <pyotaesu@gmail.com> -Takeshi Yoneda <cz.rk.t0415y.g@gmail.com> -Tamir Hyman <hyman.tamir@gmail.com> -The University of Adelaide -The University of Minnesota -The University of Washington -Thomas Berg <tomfuture@gmail.com> -Tobin Harding <me@tobin.cc> -Tom Payne <twpayne@gmail.com> -Tristan Nicholls <tvk.nicholls@gmail.com> -Valentin Deleplace <deleplace2015@gmail.com> -Vincent Thiery <vjmthiery@gmail.com> -Vladimír Chalupecký <vladimir.chalupecky@gmail.com> -Will Tekulve <tekulve.will@gmail.com> -Yasuhiro Matsumoto <mattn.jp@gmail.com> -Yevgeniy Vahlis <evahlis@gmail.com> -Yucheng Zhu <zyctc000@gmail.com> -Yunomi <ynmtywn@gmail.com> -Zhan Shan Mao <zhanshanmao@outlook.com> -Zoe Juozapaitis diff --git a/vendor/gonum.org/v1/gonum/CONTRIBUTORS b/vendor/gonum.org/v1/gonum/CONTRIBUTORS deleted file mode 100644 index 1fbe736c..00000000 --- a/vendor/gonum.org/v1/gonum/CONTRIBUTORS +++ /dev/null @@ -1,144 +0,0 @@ -# This is the official list of people who can contribute -# (and typically have contributed) code to the Gonum -# project. -# -# The AUTHORS file lists the copyright holders; this file -# lists people. For example, Google employees would be listed here -# but not in AUTHORS, because Google would hold the copyright. -# -# When adding J Random Contributor's name to this file, -# either J's name or J's organization's name should be -# added to the AUTHORS file. -# -# Names should be added to this file like so: -# Name <email address> -# -# Please keep the list sorted. - -Alexander Egurnov <alexander.egurnov@gmail.com> -Andrei Blinnikov <goofinator@mail.ru> -Andrew Brampton <brampton@gmail.com> -antichris <chris@u-d13.com> -Bailey Lissington <lissington4@gmail.com> -Bill Gray <wgray@gogray.com> -Bill Noon <noon.bill@gmail.com> -Brendan Tracey <tracey.brendan@gmail.com> -Brent Pedersen <bpederse@gmail.com> -Bulat Khasanov <afti@yandex.ru> -Chad Kunde <kunde21@gmail.com> -Chan Kwan Yin <sofe2038@gmail.com> -Chih-Wei Chang <bert.cwchang@gmail.com> -Chong-Yeol Nah <nahchongyeol@gmail.com> -Chris Tessum <ctessum@gmail.com> -Christophe Meessen <christophe.meessen@gmail.com> -Christopher Waldon <christopher.waldon.dev@gmail.com> -Clayton Northey <clayton.northey@gmail.com> -Dan Kortschak <dan.kortschak@adelaide.edu.au> <dan@kortschak.io> -Dan Lorenc <lorenc.d@gmail.com> -Daniel Fireman <danielfireman@gmail.com> -Dario Heinisch <dario.heinisch@gmail.com> -David Kleiven <davidkleiven446@gmail.com> -David Samborski <bloggingarrow@gmail.com> -Davor Kapsa <davor.kapsa@gmail.com> -Delaney Gillilan <delaneygillilan@gmail.com> -Dezmond Goff <goff.dezmond@gmail.com> -Dirk Müller <dirk@dmllr.de> -Dong-hee Na <donghee.na92@gmail.com> -Dustin Spicuzza <dustin@virtualroadside.com> -Egon Elbre <egonelbre@gmail.com> -Ekaterina Efimova <katerina.efimova@gmail.com> -Eng Zer Jun <engzerjun@gmail.com> -Ethan Burns <burns.ethan@gmail.com> -Ethan Reesor <ethan.reesor@gmail.com> -Evert Lammerts <evert.lammerts@gmail.com> -Evgeny Savinov <notime.sea@gmail.com> -Fabian Wickborn <fabian@wickborn.net> -Facundo Gaich <facugaich@gmail.com> -Fazlul Shahriar <fshahriar@gmail.com> -Francesc Campoy <campoy@golang.org> -Gustaf Johansson <gustaf@pinon.se> -Hossein Zolfi <hossein.zolfi@gmail.com> -Huang Peng Fei <huangpengfei@outlook.com> -Iakov Davydov <iakov.davydov@unil.ch> -Igor Mikushkin <igor.mikushkin@gmail.com> -Iskander Sharipov <quasilyte@gmail.com> -Jack Tudbury -Jalem Raj Rohit <jrajrohit33@gmail.com> -James Bell <james@stellentus.com> -James Bowman <james.edward.bowman@gmail.com> -James Holmes <32bitkid@gmail.com> -Janne Snabb <snabb@epipe.com> -Jeremy Atkinson <jchatkinson@gmail.com> -Jes Cok <xigua67damn@gmail.com> -Jinesi Yelizati <i63888888@163.com> -Jon Richards <noj.richards@gmail.com> -Jonas Kahler <jonas@derkahler.de> -Jonas Schulze <jonas.schulze@ovgu.de> -Jonathan Bluett-Duncan <jbluettduncan@gmail.com> -Jonathan J Lawlor <jonathan.lawlor@gmail.com> -Jonathan Reiter <jonreiter@gmail.com> -Jonathan Schroeder <jd.schroeder@gmail.com> -Joost van Amersfoort <git@joo.st> -Jordan Stoker <jordan_stoker@hotmail.com> -Joseph Watson <jtwatson@linux-consulting.us> -Josh Wilson <josh.craig.wilson@gmail.com> -Julien Roland <juroland@gmail.com> -Kai Trukenmüller <ktye78@gmail.com> -Kendall Marcus <knowmost@outlook.com> -Kent English <kent.english@gmail.com> -Kevin C. Zimmerman <kevinczimmerman@gmail.com> -Kirill Motkov <motkov.kirill@gmail.com> -Konstantin Shaposhnikov <k.shaposhnikov@gmail.com> -Leonid Kneller <recondite.matter@gmail.com> -Lyron Winderbaum <lyron.winderbaum@student.adelaide.edu.au> <armadilloa16@gmail.com> <lyron.winderbaum@uwa.edu.au> -Marco Leogrande <dark.knight.ita@gmail.com> -Mark Canning <argusdusty@gmail.com> -Mark Skilbeck <markskilbeck@gmail.com> -Martin Diz <github@martindiz.com.ar> -Matthew Connelly <matthew.b.connelly@gmail.com> -Matthieu Di Mercurio <matthieu.dimercurio@gmail.com> -Max Halford <maxhalford25@gmail.com> -Maxim Sergeev <gudvinr@gmail.com> -MinJae Kwon <k239507@gmail.com> -Nathan Edwards <etaoinshrdluwho@gmail.com> -Nick Potts <nick@the-potts.com> -Nils Wogatzky <odog@netcologne.de> -Olivier Wulveryck <olivier.wulveryck@gmail.com> -Or Rikon <rikonor@gmail.com> -Oskar Haarklou Veileborg <ohv1020@hotmail.com> -Patricio Whittingslow <graded.sp@gmail.com> -Patrick DeVivo <patrick@tickgit.com> -Pontus Melke <pontusmelke@gmail.com> -Renee French -Rishi Desai <desai.rishi1@gmail.com> -Robert Kleffner <rob.kleffner@gmail.com> -Robin Eklind <r.eklind.87@gmail.com> -Roger Welin <roger.welin@icloud.com> -Roman Werpachowski <roman.werpachowski@gmail.com> -Rondall Jones <rejones7@gmail.com> -Sam Zaydel <szaydel@gmail.com> -Samuel Kelemen <Samuel@Kelemen.us> -Saran Ahluwalia <ahlusar.ahluwalia@gmail.com> -Scott Holden <scott@sshconnection.com> -Scott Kiesel <kiesel.scott@gmail.com> -Sebastien Binet <seb.binet@gmail.com> -Shawn Smith <shawnpsmith@gmail.com> -Spencer Lyon <spencerlyon2@gmail.com> -Steve McCoy <mccoyst@gmail.com> -Taesu Pyo <pyotaesu@gmail.com> -Takeshi Yoneda <cz.rk.t0415y.g@gmail.com> -Tamir Hyman <hyman.tamir@gmail.com> -Thomas Berg <tomfuture@gmail.com> -Tobin Harding <me@tobin.cc> -Tom Payne <twpayne@gmail.com> -Tristan Nicholls <tvk.nicholls@gmail.com> -Valentin Deleplace <deleplace2015@gmail.com> -Vincent Thiery <vjmthiery@gmail.com> -Vladimír Chalupecký <vladimir.chalupecky@gmail.com> -Will Tekulve <tekulve.will@gmail.com> -Yasuhiro Matsumoto <mattn.jp@gmail.com> -Yevgeniy Vahlis <evahlis@gmail.com> -Yucheng Zhu <zyctc000@gmail.com> -Yunomi <ynmtywn@gmail.com> -Zhan Shan Mao <zhanshanmao@outlook.com> -Zoe Juozapaitis diff --git a/vendor/gonum.org/v1/gonum/LICENSE b/vendor/gonum.org/v1/gonum/LICENSE deleted file mode 100644 index ed477e59..00000000 --- a/vendor/gonum.org/v1/gonum/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright ©2013 The Gonum Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Gonum project nor the names of its authors and - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/gonum.org/v1/gonum/blas/README.md b/vendor/gonum.org/v1/gonum/blas/README.md deleted file mode 100644 index 16d62bd3..00000000 --- a/vendor/gonum.org/v1/gonum/blas/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Gonum BLAS - -[![go.dev reference](https://pkg.go.dev/badge/gonum.org/v1/gonum/blas)](https://pkg.go.dev/gonum.org/v1/gonum/blas) -[![GoDoc](https://godocs.io/gonum.org/v1/gonum/blas?status.svg)](https://godocs.io/gonum.org/v1/gonum/blas) - -A collection of packages to provide BLAS functionality for the [Go programming -language](http://golang.org) - -## Installation -```sh - go get gonum.org/v1/gonum/blas/... -``` - -## Packages - -### blas - -Defines [BLAS API](http://www.netlib.org/blas/blast-forum/cinterface.pdf) split in several -interfaces. - -### blas/gonum - -Go implementation of the BLAS API (incomplete, implements the `float32` and `float64` API). - -### blas/blas64 and blas/blas32 - -Wrappers for an implementation of the double (i.e., `float64`) and single (`float32`) -precision real parts of the BLAS API. - -```Go -package main - -import ( - "fmt" - - "gonum.org/v1/gonum/blas/blas64" -) - -func main() { - v := blas64.Vector{Inc: 1, Data: []float64{1, 1, 1}} - v.N = len(v.Data) - fmt.Println("v has length:", blas64.Nrm2(v)) -} -``` - -### blas/cblas128 and blas/cblas64 - -Wrappers for an implementation of the double (i.e., `complex128`) and single (`complex64`) -precision complex parts of the blas API. - -Currently blas/cblas64 and blas/cblas128 require gonum.org/v1/netlib/blas. diff --git a/vendor/gonum.org/v1/gonum/blas/blas.go b/vendor/gonum.org/v1/gonum/blas/blas.go deleted file mode 100644 index 9b933e3f..00000000 --- a/vendor/gonum.org/v1/gonum/blas/blas.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright ©2013 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate ./conversions.bash - -package blas - -// Flag constants indicate Givens transformation H matrix state. -type Flag int - -const ( - Identity Flag = -2 // H is the identity matrix; no rotation is needed. - Rescaling Flag = -1 // H specifies rescaling. - OffDiagonal Flag = 0 // Off-diagonal elements of H are non-unit. - Diagonal Flag = 1 // Diagonal elements of H are non-unit. -) - -// SrotmParams contains Givens transformation parameters returned -// by the Float32 Srotm method. -type SrotmParams struct { - Flag - H [4]float32 // Column-major 2 by 2 matrix. -} - -// DrotmParams contains Givens transformation parameters returned -// by the Float64 Drotm method. -type DrotmParams struct { - Flag - H [4]float64 // Column-major 2 by 2 matrix. -} - -// Transpose specifies the transposition operation of a matrix. -type Transpose byte - -const ( - NoTrans Transpose = 'N' - Trans Transpose = 'T' - ConjTrans Transpose = 'C' -) - -// Uplo specifies whether a matrix is upper or lower triangular. -type Uplo byte - -const ( - Upper Uplo = 'U' - Lower Uplo = 'L' - All Uplo = 'A' -) - -// Diag specifies whether a matrix is unit triangular. -type Diag byte - -const ( - NonUnit Diag = 'N' - Unit Diag = 'U' -) - -// Side specifies from which side a multiplication operation is performed. -type Side byte - -const ( - Left Side = 'L' - Right Side = 'R' -) - -// Float32 implements the single precision real BLAS routines. -type Float32 interface { - Float32Level1 - Float32Level2 - Float32Level3 -} - -// Float32Level1 implements the single precision real BLAS Level 1 routines. -type Float32Level1 interface { - Sdsdot(n int, alpha float32, x []float32, incX int, y []float32, incY int) float32 - Dsdot(n int, x []float32, incX int, y []float32, incY int) float64 - Sdot(n int, x []float32, incX int, y []float32, incY int) float32 - Snrm2(n int, x []float32, incX int) float32 - Sasum(n int, x []float32, incX int) float32 - Isamax(n int, x []float32, incX int) int - Sswap(n int, x []float32, incX int, y []float32, incY int) - Scopy(n int, x []float32, incX int, y []float32, incY int) - Saxpy(n int, alpha float32, x []float32, incX int, y []float32, incY int) - Srotg(a, b float32) (c, s, r, z float32) - Srotmg(d1, d2, b1, b2 float32) (p SrotmParams, rd1, rd2, rb1 float32) - Srot(n int, x []float32, incX int, y []float32, incY int, c, s float32) - Srotm(n int, x []float32, incX int, y []float32, incY int, p SrotmParams) - Sscal(n int, alpha float32, x []float32, incX int) -} - -// Float32Level2 implements the single precision real BLAS Level 2 routines. -type Float32Level2 interface { - Sgemv(tA Transpose, m, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) - Sgbmv(tA Transpose, m, n, kL, kU int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) - Strmv(ul Uplo, tA Transpose, d Diag, n int, a []float32, lda int, x []float32, incX int) - Stbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []float32, lda int, x []float32, incX int) - Stpmv(ul Uplo, tA Transpose, d Diag, n int, ap []float32, x []float32, incX int) - Strsv(ul Uplo, tA Transpose, d Diag, n int, a []float32, lda int, x []float32, incX int) - Stbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []float32, lda int, x []float32, incX int) - Stpsv(ul Uplo, tA Transpose, d Diag, n int, ap []float32, x []float32, incX int) - Ssymv(ul Uplo, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) - Ssbmv(ul Uplo, n, k int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) - Sspmv(ul Uplo, n int, alpha float32, ap []float32, x []float32, incX int, beta float32, y []float32, incY int) - Sger(m, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) - Ssyr(ul Uplo, n int, alpha float32, x []float32, incX int, a []float32, lda int) - Sspr(ul Uplo, n int, alpha float32, x []float32, incX int, ap []float32) - Ssyr2(ul Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) - Sspr2(ul Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32) -} - -// Float32Level3 implements the single precision real BLAS Level 3 routines. -type Float32Level3 interface { - Sgemm(tA, tB Transpose, m, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) - Ssymm(s Side, ul Uplo, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) - Ssyrk(ul Uplo, t Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32, ldc int) - Ssyr2k(ul Uplo, t Transpose, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) - Strmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) - Strsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) -} - -// Float64 implements the single precision real BLAS routines. -type Float64 interface { - Float64Level1 - Float64Level2 - Float64Level3 -} - -// Float64Level1 implements the double precision real BLAS Level 1 routines. -type Float64Level1 interface { - Ddot(n int, x []float64, incX int, y []float64, incY int) float64 - Dnrm2(n int, x []float64, incX int) float64 - Dasum(n int, x []float64, incX int) float64 - Idamax(n int, x []float64, incX int) int - Dswap(n int, x []float64, incX int, y []float64, incY int) - Dcopy(n int, x []float64, incX int, y []float64, incY int) - Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) - Drotg(a, b float64) (c, s, r, z float64) - Drotmg(d1, d2, b1, b2 float64) (p DrotmParams, rd1, rd2, rb1 float64) - Drot(n int, x []float64, incX int, y []float64, incY int, c float64, s float64) - Drotm(n int, x []float64, incX int, y []float64, incY int, p DrotmParams) - Dscal(n int, alpha float64, x []float64, incX int) -} - -// Float64Level2 implements the double precision real BLAS Level 2 routines. -type Float64Level2 interface { - Dgemv(tA Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) - Dgbmv(tA Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) - Dtrmv(ul Uplo, tA Transpose, d Diag, n int, a []float64, lda int, x []float64, incX int) - Dtbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []float64, lda int, x []float64, incX int) - Dtpmv(ul Uplo, tA Transpose, d Diag, n int, ap []float64, x []float64, incX int) - Dtrsv(ul Uplo, tA Transpose, d Diag, n int, a []float64, lda int, x []float64, incX int) - Dtbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []float64, lda int, x []float64, incX int) - Dtpsv(ul Uplo, tA Transpose, d Diag, n int, ap []float64, x []float64, incX int) - Dsymv(ul Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) - Dsbmv(ul Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) - Dspmv(ul Uplo, n int, alpha float64, ap []float64, x []float64, incX int, beta float64, y []float64, incY int) - Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) - Dsyr(ul Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) - Dspr(ul Uplo, n int, alpha float64, x []float64, incX int, ap []float64) - Dsyr2(ul Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) - Dspr2(ul Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64) -} - -// Float64Level3 implements the double precision real BLAS Level 3 routines. -type Float64Level3 interface { - Dgemm(tA, tB Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) - Dsymm(s Side, ul Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) - Dsyrk(ul Uplo, t Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) - Dsyr2k(ul Uplo, t Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) - Dtrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) - Dtrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) -} - -// Complex64 implements the single precision complex BLAS routines. -type Complex64 interface { - Complex64Level1 - Complex64Level2 - Complex64Level3 -} - -// Complex64Level1 implements the single precision complex BLAS Level 1 routines. -type Complex64Level1 interface { - Cdotu(n int, x []complex64, incX int, y []complex64, incY int) (dotu complex64) - Cdotc(n int, x []complex64, incX int, y []complex64, incY int) (dotc complex64) - Scnrm2(n int, x []complex64, incX int) float32 - Scasum(n int, x []complex64, incX int) float32 - Icamax(n int, x []complex64, incX int) int - Cswap(n int, x []complex64, incX int, y []complex64, incY int) - Ccopy(n int, x []complex64, incX int, y []complex64, incY int) - Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) - Cscal(n int, alpha complex64, x []complex64, incX int) - Csscal(n int, alpha float32, x []complex64, incX int) -} - -// Complex64Level2 implements the single precision complex BLAS routines Level 2 routines. -type Complex64Level2 interface { - Cgemv(tA Transpose, m, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) - Cgbmv(tA Transpose, m, n, kL, kU int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) - Ctrmv(ul Uplo, tA Transpose, d Diag, n int, a []complex64, lda int, x []complex64, incX int) - Ctbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex64, lda int, x []complex64, incX int) - Ctpmv(ul Uplo, tA Transpose, d Diag, n int, ap []complex64, x []complex64, incX int) - Ctrsv(ul Uplo, tA Transpose, d Diag, n int, a []complex64, lda int, x []complex64, incX int) - Ctbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex64, lda int, x []complex64, incX int) - Ctpsv(ul Uplo, tA Transpose, d Diag, n int, ap []complex64, x []complex64, incX int) - Chemv(ul Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) - Chbmv(ul Uplo, n, k int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) - Chpmv(ul Uplo, n int, alpha complex64, ap []complex64, x []complex64, incX int, beta complex64, y []complex64, incY int) - Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) - Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) - Cher(ul Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) - Chpr(ul Uplo, n int, alpha float32, x []complex64, incX int, a []complex64) - Cher2(ul Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) - Chpr2(ul Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) -} - -// Complex64Level3 implements the single precision complex BLAS Level 3 routines. -type Complex64Level3 interface { - Cgemm(tA, tB Transpose, m, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) - Csymm(s Side, ul Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) - Csyrk(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) - Csyr2k(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) - Ctrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) - Ctrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) - Chemm(s Side, ul Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) - Cherk(ul Uplo, t Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) - Cher2k(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta float32, c []complex64, ldc int) -} - -// Complex128 implements the double precision complex BLAS routines. -type Complex128 interface { - Complex128Level1 - Complex128Level2 - Complex128Level3 -} - -// Complex128Level1 implements the double precision complex BLAS Level 1 routines. -type Complex128Level1 interface { - Zdotu(n int, x []complex128, incX int, y []complex128, incY int) (dotu complex128) - Zdotc(n int, x []complex128, incX int, y []complex128, incY int) (dotc complex128) - Dznrm2(n int, x []complex128, incX int) float64 - Dzasum(n int, x []complex128, incX int) float64 - Izamax(n int, x []complex128, incX int) int - Zswap(n int, x []complex128, incX int, y []complex128, incY int) - Zcopy(n int, x []complex128, incX int, y []complex128, incY int) - Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) - Zscal(n int, alpha complex128, x []complex128, incX int) - Zdscal(n int, alpha float64, x []complex128, incX int) -} - -// Complex128Level2 implements the double precision complex BLAS Level 2 routines. -type Complex128Level2 interface { - Zgemv(tA Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) - Zgbmv(tA Transpose, m, n int, kL int, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) - Ztrmv(ul Uplo, tA Transpose, d Diag, n int, a []complex128, lda int, x []complex128, incX int) - Ztbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex128, lda int, x []complex128, incX int) - Ztpmv(ul Uplo, tA Transpose, d Diag, n int, ap []complex128, x []complex128, incX int) - Ztrsv(ul Uplo, tA Transpose, d Diag, n int, a []complex128, lda int, x []complex128, incX int) - Ztbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex128, lda int, x []complex128, incX int) - Ztpsv(ul Uplo, tA Transpose, d Diag, n int, ap []complex128, x []complex128, incX int) - Zhemv(ul Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) - Zhbmv(ul Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) - Zhpmv(ul Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) - Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) - Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) - Zher(ul Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) - Zhpr(ul Uplo, n int, alpha float64, x []complex128, incX int, a []complex128) - Zher2(ul Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) - Zhpr2(ul Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) -} - -// Complex128Level3 implements the double precision complex BLAS Level 3 routines. -type Complex128Level3 interface { - Zgemm(tA, tB Transpose, m, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) - Zsymm(s Side, ul Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) - Zsyrk(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) - Zsyr2k(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) - Ztrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) - Ztrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) - Zhemm(s Side, ul Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) - Zherk(ul Uplo, t Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) - Zher2k(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta float64, c []complex128, ldc int) -} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go b/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go deleted file mode 100644 index 64ac985c..00000000 --- a/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go +++ /dev/null @@ -1,533 +0,0 @@ -// Copyright ©2015 The Gonum 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 blas64 - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/gonum" -) - -var blas64 blas.Float64 = gonum.Implementation{} - -// Use sets the BLAS float64 implementation to be used by subsequent BLAS calls. -// The default implementation is -// gonum.org/v1/gonum/blas/gonum.Implementation. -func Use(b blas.Float64) { - blas64 = b -} - -// Implementation returns the current BLAS float64 implementation. -// -// Implementation allows direct calls to the current BLAS float64 implementation -// giving finer control of parameters. -func Implementation() blas.Float64 { - return blas64 -} - -// Vector represents a vector with an associated element increment. -type Vector struct { - N int - Data []float64 - Inc int -} - -// General represents a matrix using the conventional storage scheme. -type General struct { - Rows, Cols int - Data []float64 - Stride int -} - -// Band represents a band matrix using the band storage scheme. -type Band struct { - Rows, Cols int - KL, KU int - Data []float64 - Stride int -} - -// Triangular represents a triangular matrix using the conventional storage scheme. -type Triangular struct { - Uplo blas.Uplo - Diag blas.Diag - N int - Data []float64 - Stride int -} - -// TriangularBand represents a triangular matrix using the band storage scheme. -type TriangularBand struct { - Uplo blas.Uplo - Diag blas.Diag - N, K int - Data []float64 - Stride int -} - -// TriangularPacked represents a triangular matrix using the packed storage scheme. -type TriangularPacked struct { - Uplo blas.Uplo - Diag blas.Diag - N int - Data []float64 -} - -// Symmetric represents a symmetric matrix using the conventional storage scheme. -type Symmetric struct { - Uplo blas.Uplo - N int - Data []float64 - Stride int -} - -// SymmetricBand represents a symmetric matrix using the band storage scheme. -type SymmetricBand struct { - Uplo blas.Uplo - N, K int - Data []float64 - Stride int -} - -// SymmetricPacked represents a symmetric matrix using the packed storage scheme. -type SymmetricPacked struct { - Uplo blas.Uplo - N int - Data []float64 -} - -// Level 1 - -const ( - negInc = "blas64: negative vector increment" - badLength = "blas64: vector length mismatch" -) - -// Dot computes the dot product of the two vectors: -// -// \sum_i x[i]*y[i]. -// -// Dot will panic if the lengths of x and y do not match. -func Dot(x, y Vector) float64 { - if x.N != y.N { - panic(badLength) - } - return blas64.Ddot(x.N, x.Data, x.Inc, y.Data, y.Inc) -} - -// Nrm2 computes the Euclidean norm of the vector x: -// -// sqrt(\sum_i x[i]*x[i]). -// -// Nrm2 will panic if the vector increment is negative. -func Nrm2(x Vector) float64 { - if x.Inc < 0 { - panic(negInc) - } - return blas64.Dnrm2(x.N, x.Data, x.Inc) -} - -// Asum computes the sum of the absolute values of the elements of x: -// -// \sum_i |x[i]|. -// -// Asum will panic if the vector increment is negative. -func Asum(x Vector) float64 { - if x.Inc < 0 { - panic(negInc) - } - return blas64.Dasum(x.N, x.Data, x.Inc) -} - -// Iamax returns the index of an element of x with the largest absolute value. -// If there are multiple such indices the earliest is returned. -// Iamax returns -1 if n == 0. -// -// Iamax will panic if the vector increment is negative. -func Iamax(x Vector) int { - if x.Inc < 0 { - panic(negInc) - } - return blas64.Idamax(x.N, x.Data, x.Inc) -} - -// Swap exchanges the elements of the two vectors: -// -// x[i], y[i] = y[i], x[i] for all i. -// -// Swap will panic if the lengths of x and y do not match. -func Swap(x, y Vector) { - if x.N != y.N { - panic(badLength) - } - blas64.Dswap(x.N, x.Data, x.Inc, y.Data, y.Inc) -} - -// Copy copies the elements of x into the elements of y: -// -// y[i] = x[i] for all i. -// -// Copy will panic if the lengths of x and y do not match. -func Copy(x, y Vector) { - if x.N != y.N { - panic(badLength) - } - blas64.Dcopy(x.N, x.Data, x.Inc, y.Data, y.Inc) -} - -// Axpy adds x scaled by alpha to y: -// -// y[i] += alpha*x[i] for all i. -// -// Axpy will panic if the lengths of x and y do not match. -func Axpy(alpha float64, x, y Vector) { - if x.N != y.N { - panic(badLength) - } - blas64.Daxpy(x.N, alpha, x.Data, x.Inc, y.Data, y.Inc) -} - -// Rotg computes the parameters of a Givens plane rotation so that -// -// ⎡ c s⎤ ⎡a⎤ ⎡r⎤ -// ⎣-s c⎦ * ⎣b⎦ = ⎣0⎦ -// -// where a and b are the Cartesian coordinates of a given point. -// c, s, and r are defined as -// -// r = ±Sqrt(a^2 + b^2), -// c = a/r, the cosine of the rotation angle, -// s = a/r, the sine of the rotation angle, -// -// and z is defined such that -// -// if |a| > |b|, z = s, -// otherwise if c != 0, z = 1/c, -// otherwise z = 1. -func Rotg(a, b float64) (c, s, r, z float64) { - return blas64.Drotg(a, b) -} - -// Rotmg computes the modified Givens rotation. See -// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html -// for more details. -func Rotmg(d1, d2, b1, b2 float64) (p blas.DrotmParams, rd1, rd2, rb1 float64) { - return blas64.Drotmg(d1, d2, b1, b2) -} - -// Rot applies a plane transformation to n points represented by the vectors x -// and y: -// -// x[i] = c*x[i] + s*y[i], -// y[i] = -s*x[i] + c*y[i], for all i. -func Rot(x, y Vector, c, s float64) { - if x.N != y.N { - panic(badLength) - } - blas64.Drot(x.N, x.Data, x.Inc, y.Data, y.Inc, c, s) -} - -// Rotm applies the modified Givens rotation to n points represented by the -// vectors x and y. -func Rotm(x, y Vector, p blas.DrotmParams) { - if x.N != y.N { - panic(badLength) - } - blas64.Drotm(x.N, x.Data, x.Inc, y.Data, y.Inc, p) -} - -// Scal scales the vector x by alpha: -// -// x[i] *= alpha for all i. -// -// Scal will panic if the vector increment is negative. -func Scal(alpha float64, x Vector) { - if x.Inc < 0 { - panic(negInc) - } - blas64.Dscal(x.N, alpha, x.Data, x.Inc) -} - -// Level 2 - -// Gemv computes -// -// y = alpha * A * x + beta * y if t == blas.NoTrans, -// y = alpha * Aᵀ * x + beta * y if t == blas.Trans or blas.ConjTrans, -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func Gemv(t blas.Transpose, alpha float64, a General, x Vector, beta float64, y Vector) { - blas64.Dgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Gbmv computes -// -// y = alpha * A * x + beta * y if t == blas.NoTrans, -// y = alpha * Aᵀ * x + beta * y if t == blas.Trans or blas.ConjTrans, -// -// where A is an m×n band matrix, x and y are vectors, and alpha and beta are scalars. -func Gbmv(t blas.Transpose, alpha float64, a Band, x Vector, beta float64, y Vector) { - blas64.Dgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Trmv computes -// -// x = A * x if t == blas.NoTrans, -// x = Aᵀ * x if t == blas.Trans or blas.ConjTrans, -// -// where A is an n×n triangular matrix, and x is a vector. -func Trmv(t blas.Transpose, a Triangular, x Vector) { - blas64.Dtrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tbmv computes -// -// x = A * x if t == blas.NoTrans, -// x = Aᵀ * x if t == blas.Trans or blas.ConjTrans, -// -// where A is an n×n triangular band matrix, and x is a vector. -func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { - blas64.Dtbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tpmv computes -// -// x = A * x if t == blas.NoTrans, -// x = Aᵀ * x if t == blas.Trans or blas.ConjTrans, -// -// where A is an n×n triangular matrix in packed format, and x is a vector. -func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { - blas64.Dtpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) -} - -// Trsv solves -// -// A * x = b if t == blas.NoTrans, -// Aᵀ * x = b if t == blas.Trans or blas.ConjTrans, -// -// where A is an n×n triangular matrix, and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func Trsv(t blas.Transpose, a Triangular, x Vector) { - blas64.Dtrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tbsv solves -// -// A * x = b if t == blas.NoTrans, -// Aᵀ * x = b if t == blas.Trans or blas.ConjTrans, -// -// where A is an n×n triangular band matrix, and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { - blas64.Dtbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tpsv solves -// -// A * x = b if t == blas.NoTrans, -// Aᵀ * x = b if t == blas.Trans or blas.ConjTrans, -// -// where A is an n×n triangular matrix in packed format, and x and b are -// vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { - blas64.Dtpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) -} - -// Symv computes -// -// y = alpha * A * x + beta * y, -// -// where A is an n×n symmetric matrix, x and y are vectors, and alpha and -// beta are scalars. -func Symv(alpha float64, a Symmetric, x Vector, beta float64, y Vector) { - blas64.Dsymv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Sbmv performs -// -// y = alpha * A * x + beta * y, -// -// where A is an n×n symmetric band matrix, x and y are vectors, and alpha -// and beta are scalars. -func Sbmv(alpha float64, a SymmetricBand, x Vector, beta float64, y Vector) { - blas64.Dsbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Spmv performs -// -// y = alpha * A * x + beta * y, -// -// where A is an n×n symmetric matrix in packed format, x and y are vectors, -// and alpha and beta are scalars. -func Spmv(alpha float64, a SymmetricPacked, x Vector, beta float64, y Vector) { - blas64.Dspmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Ger performs a rank-1 update -// -// A += alpha * x * yᵀ, -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func Ger(alpha float64, x, y Vector, a General) { - blas64.Dger(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) -} - -// Syr performs a rank-1 update -// -// A += alpha * x * xᵀ, -// -// where A is an n×n symmetric matrix, x is a vector, and alpha is a scalar. -func Syr(alpha float64, x Vector, a Symmetric) { - blas64.Dsyr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) -} - -// Spr performs the rank-1 update -// -// A += alpha * x * xᵀ, -// -// where A is an n×n symmetric matrix in packed format, x is a vector, and -// alpha is a scalar. -func Spr(alpha float64, x Vector, a SymmetricPacked) { - blas64.Dspr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) -} - -// Syr2 performs a rank-2 update -// -// A += alpha * x * yᵀ + alpha * y * xᵀ, -// -// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. -func Syr2(alpha float64, x, y Vector, a Symmetric) { - blas64.Dsyr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) -} - -// Spr2 performs a rank-2 update -// -// A += alpha * x * yᵀ + alpha * y * xᵀ, -// -// where A is an n×n symmetric matrix in packed format, x and y are vectors, -// and alpha is a scalar. -func Spr2(alpha float64, x, y Vector, a SymmetricPacked) { - blas64.Dspr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) -} - -// Level 3 - -// Gemm computes -// -// C = alpha * A * B + beta * C, -// -// where A, B, and C are dense matrices, and alpha and beta are scalars. -// tA and tB specify whether A or B are transposed. -func Gemm(tA, tB blas.Transpose, alpha float64, a, b General, beta float64, c General) { - var m, n, k int - if tA == blas.NoTrans { - m, k = a.Rows, a.Cols - } else { - m, k = a.Cols, a.Rows - } - if tB == blas.NoTrans { - n = b.Cols - } else { - n = b.Rows - } - blas64.Dgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} - -// Symm performs -// -// C = alpha * A * B + beta * C if s == blas.Left, -// C = alpha * B * A + beta * C if s == blas.Right, -// -// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and -// alpha is a scalar. -func Symm(s blas.Side, alpha float64, a Symmetric, b General, beta float64, c General) { - var m, n int - if s == blas.Left { - m, n = a.N, b.Cols - } else { - m, n = b.Rows, a.N - } - blas64.Dsymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} - -// Syrk performs a symmetric rank-k update -// -// C = alpha * A * Aᵀ + beta * C if t == blas.NoTrans, -// C = alpha * Aᵀ * A + beta * C if t == blas.Trans or blas.ConjTrans, -// -// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans and -// a k×n matrix otherwise, and alpha and beta are scalars. -func Syrk(t blas.Transpose, alpha float64, a General, beta float64, c Symmetric) { - var n, k int - if t == blas.NoTrans { - n, k = a.Rows, a.Cols - } else { - n, k = a.Cols, a.Rows - } - blas64.Dsyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) -} - -// Syr2k performs a symmetric rank-2k update -// -// C = alpha * A * Bᵀ + alpha * B * Aᵀ + beta * C if t == blas.NoTrans, -// C = alpha * Aᵀ * B + alpha * Bᵀ * A + beta * C if t == blas.Trans or blas.ConjTrans, -// -// where C is an n×n symmetric matrix, A and B are n×k matrices if t == NoTrans -// and k×n matrices otherwise, and alpha and beta are scalars. -func Syr2k(t blas.Transpose, alpha float64, a, b General, beta float64, c Symmetric) { - var n, k int - if t == blas.NoTrans { - n, k = a.Rows, a.Cols - } else { - n, k = a.Cols, a.Rows - } - blas64.Dsyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} - -// Trmm performs -// -// B = alpha * A * B if tA == blas.NoTrans and s == blas.Left, -// B = alpha * Aᵀ * B if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, -// B = alpha * B * A if tA == blas.NoTrans and s == blas.Right, -// B = alpha * B * Aᵀ if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, -// -// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is -// a scalar. -func Trmm(s blas.Side, tA blas.Transpose, alpha float64, a Triangular, b General) { - blas64.Dtrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) -} - -// Trsm solves -// -// A * X = alpha * B if tA == blas.NoTrans and s == blas.Left, -// Aᵀ * X = alpha * B if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, -// X * A = alpha * B if tA == blas.NoTrans and s == blas.Right, -// X * Aᵀ = alpha * B if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, -// -// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and -// alpha is a scalar. -// -// At entry to the function, X contains the values of B, and the result is -// stored in-place into X. -// -// No check is made that A is invertible. -func Trsm(s blas.Side, tA blas.Transpose, alpha float64, a Triangular, b General) { - blas64.Dtrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) -} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/conv.go b/vendor/gonum.org/v1/gonum/blas/blas64/conv.go deleted file mode 100644 index 695557d1..00000000 --- a/vendor/gonum.org/v1/gonum/blas/blas64/conv.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright ©2015 The Gonum 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 blas64 - -import "gonum.org/v1/gonum/blas" - -// GeneralCols represents a matrix using the conventional column-major storage scheme. -type GeneralCols General - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions as a and have adequate backing -// data storage. -func (t GeneralCols) From(a General) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("blas64: mismatched dimension") - } - if len(t.Data) < (t.Cols-1)*t.Stride+t.Rows { - panic("blas64: short data slice") - } - for i := 0; i < a.Rows; i++ { - for j, v := range a.Data[i*a.Stride : i*a.Stride+a.Cols] { - t.Data[i+j*t.Stride] = v - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions as a and have adequate backing -// data storage. -func (t General) From(a GeneralCols) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("blas64: mismatched dimension") - } - if len(t.Data) < (t.Rows-1)*t.Stride+t.Cols { - panic("blas64: short data slice") - } - for j := 0; j < a.Cols; j++ { - for i, v := range a.Data[j*a.Stride : j*a.Stride+a.Rows] { - t.Data[i*t.Stride+j] = v - } - } -} - -// TriangularCols represents a matrix using the conventional column-major storage scheme. -type TriangularCols Triangular - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, uplo and diag as a and have -// adequate backing data storage. -func (t TriangularCols) From(a Triangular) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("blas64: mismatched BLAS diag") - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - case blas.All: - for i := 0; i < a.N; i++ { - for j := 0; j < a.N; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, uplo and diag as a and have -// adequate backing data storage. -func (t Triangular) From(a TriangularCols) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("blas64: mismatched BLAS diag") - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - case blas.All: - for i := 0; i < a.N; i++ { - for j := 0; j < a.N; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - } -} - -// BandCols represents a matrix using the band column-major storage scheme. -type BandCols Band - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and bandwidth as a and have -// adequate backing data storage. -func (t BandCols) From(a Band) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("blas64: mismatched dimension") - } - if t.KL != a.KL || t.KU != a.KU { - panic("blas64: mismatched bandwidth") - } - if a.Stride < a.KL+a.KU+1 { - panic("blas64: short stride for source") - } - if t.Stride < t.KL+t.KU+1 { - panic("blas64: short stride for destination") - } - for i := 0; i < a.Rows; i++ { - for j := max(0, i-a.KL); j < min(i+a.KU+1, a.Cols); j++ { - t.Data[i+t.KU-j+j*t.Stride] = a.Data[j+a.KL-i+i*a.Stride] - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and bandwidth as a and have -// adequate backing data storage. -func (t Band) From(a BandCols) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("blas64: mismatched dimension") - } - if t.KL != a.KL || t.KU != a.KU { - panic("blas64: mismatched bandwidth") - } - if a.Stride < a.KL+a.KU+1 { - panic("blas64: short stride for source") - } - if t.Stride < t.KL+t.KU+1 { - panic("blas64: short stride for destination") - } - for j := 0; j < a.Cols; j++ { - for i := max(0, j-a.KU); i < min(j+a.KL+1, a.Rows); i++ { - t.Data[j+a.KL-i+i*a.Stride] = a.Data[i+t.KU-j+j*t.Stride] - } - } -} - -// TriangularBandCols represents a triangular matrix using the band column-major storage scheme. -type TriangularBandCols TriangularBand - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t TriangularBandCols) From(a TriangularBand) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.K != a.K { - panic("blas64: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("blas64: short stride for source") - } - if t.Stride < t.K+1 { - panic("blas64: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("blas64: mismatched BLAS diag") - } - dst := BandCols{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := Band{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t TriangularBand) From(a TriangularBandCols) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.K != a.K { - panic("blas64: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("blas64: short stride for source") - } - if t.Stride < t.K+1 { - panic("blas64: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("blas64: mismatched BLAS diag") - } - dst := Band{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := BandCols{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go b/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go deleted file mode 100644 index 5146f1a1..00000000 --- a/vendor/gonum.org/v1/gonum/blas/blas64/conv_symmetric.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright ©2015 The Gonum 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 blas64 - -import "gonum.org/v1/gonum/blas" - -// SymmetricCols represents a matrix using the conventional column-major storage scheme. -type SymmetricCols Symmetric - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and uplo as a and have adequate -// backing data storage. -func (t SymmetricCols) From(a Symmetric) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and uplo as a and have adequate -// backing data storage. -func (t Symmetric) From(a SymmetricCols) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - } -} - -// SymmetricBandCols represents a symmetric matrix using the band column-major storage scheme. -type SymmetricBandCols SymmetricBand - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t SymmetricBandCols) From(a SymmetricBand) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.K != a.K { - panic("blas64: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("blas64: short stride for source") - } - if t.Stride < t.K+1 { - panic("blas64: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - dst := BandCols{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := Band{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t SymmetricBand) From(a SymmetricBandCols) { - if t.N != a.N { - panic("blas64: mismatched dimension") - } - if t.K != a.K { - panic("blas64: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("blas64: short stride for source") - } - if t.Stride < t.K+1 { - panic("blas64: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("blas64: mismatched BLAS uplo") - } - dst := Band{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := BandCols{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("blas64: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/doc.go b/vendor/gonum.org/v1/gonum/blas/blas64/doc.go deleted file mode 100644 index 7410cee4..00000000 --- a/vendor/gonum.org/v1/gonum/blas/blas64/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 blas64 provides a simple interface to the float64 BLAS API. -package blas64 // import "gonum.org/v1/gonum/blas/blas64" diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go b/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go deleted file mode 100644 index 82a6f22e..00000000 --- a/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go +++ /dev/null @@ -1,600 +0,0 @@ -// Copyright ©2015 The Gonum 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 cblas128 - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/gonum" -) - -var cblas128 blas.Complex128 = gonum.Implementation{} - -// Use sets the BLAS complex128 implementation to be used by subsequent BLAS calls. -// The default implementation is -// gonum.org/v1/gonum/blas/gonum.Implementation. -func Use(b blas.Complex128) { - cblas128 = b -} - -// Implementation returns the current BLAS complex128 implementation. -// -// Implementation allows direct calls to the current the BLAS complex128 implementation -// giving finer control of parameters. -func Implementation() blas.Complex128 { - return cblas128 -} - -// Vector represents a vector with an associated element increment. -type Vector struct { - N int - Inc int - Data []complex128 -} - -// General represents a matrix using the conventional storage scheme. -type General struct { - Rows, Cols int - Stride int - Data []complex128 -} - -// Band represents a band matrix using the band storage scheme. -type Band struct { - Rows, Cols int - KL, KU int - Stride int - Data []complex128 -} - -// Triangular represents a triangular matrix using the conventional storage scheme. -type Triangular struct { - N int - Stride int - Data []complex128 - Uplo blas.Uplo - Diag blas.Diag -} - -// TriangularBand represents a triangular matrix using the band storage scheme. -type TriangularBand struct { - N, K int - Stride int - Data []complex128 - Uplo blas.Uplo - Diag blas.Diag -} - -// TriangularPacked represents a triangular matrix using the packed storage scheme. -type TriangularPacked struct { - N int - Data []complex128 - Uplo blas.Uplo - Diag blas.Diag -} - -// Symmetric represents a symmetric matrix using the conventional storage scheme. -type Symmetric struct { - N int - Stride int - Data []complex128 - Uplo blas.Uplo -} - -// SymmetricBand represents a symmetric matrix using the band storage scheme. -type SymmetricBand struct { - N, K int - Stride int - Data []complex128 - Uplo blas.Uplo -} - -// SymmetricPacked represents a symmetric matrix using the packed storage scheme. -type SymmetricPacked struct { - N int - Data []complex128 - Uplo blas.Uplo -} - -// Hermitian represents an Hermitian matrix using the conventional storage scheme. -type Hermitian Symmetric - -// HermitianBand represents an Hermitian matrix using the band storage scheme. -type HermitianBand SymmetricBand - -// HermitianPacked represents an Hermitian matrix using the packed storage scheme. -type HermitianPacked SymmetricPacked - -// Level 1 - -const ( - negInc = "cblas128: negative vector increment" - badLength = "cblas128: vector length mismatch" -) - -// Dotu computes the dot product of the two vectors without -// complex conjugation: -// -// xᵀ * y. -// -// Dotu will panic if the lengths of x and y do not match. -func Dotu(x, y Vector) complex128 { - if x.N != y.N { - panic(badLength) - } - return cblas128.Zdotu(x.N, x.Data, x.Inc, y.Data, y.Inc) -} - -// Dotc computes the dot product of the two vectors with -// complex conjugation: -// -// xᴴ * y. -// -// Dotc will panic if the lengths of x and y do not match. -func Dotc(x, y Vector) complex128 { - if x.N != y.N { - panic(badLength) - } - return cblas128.Zdotc(x.N, x.Data, x.Inc, y.Data, y.Inc) -} - -// Nrm2 computes the Euclidean norm of the vector x: -// -// sqrt(\sum_i x[i] * x[i]). -// -// Nrm2 will panic if the vector increment is negative. -func Nrm2(x Vector) float64 { - if x.Inc < 0 { - panic(negInc) - } - return cblas128.Dznrm2(x.N, x.Data, x.Inc) -} - -// Asum computes the sum of magnitudes of the real and imaginary parts of -// elements of the vector x: -// -// \sum_i (|Re x[i]| + |Im x[i]|). -// -// Asum will panic if the vector increment is negative. -func Asum(x Vector) float64 { - if x.Inc < 0 { - panic(negInc) - } - return cblas128.Dzasum(x.N, x.Data, x.Inc) -} - -// Iamax returns the index of an element of x with the largest sum of -// magnitudes of the real and imaginary parts (|Re x[i]|+|Im x[i]|). -// If there are multiple such indices, the earliest is returned. -// -// Iamax returns -1 if n == 0. -// -// Iamax will panic if the vector increment is negative. -func Iamax(x Vector) int { - if x.Inc < 0 { - panic(negInc) - } - return cblas128.Izamax(x.N, x.Data, x.Inc) -} - -// Swap exchanges the elements of two vectors: -// -// x[i], y[i] = y[i], x[i] for all i. -// -// Swap will panic if the lengths of x and y do not match. -func Swap(x, y Vector) { - if x.N != y.N { - panic(badLength) - } - cblas128.Zswap(x.N, x.Data, x.Inc, y.Data, y.Inc) -} - -// Copy copies the elements of x into the elements of y: -// -// y[i] = x[i] for all i. -// -// Copy will panic if the lengths of x and y do not match. -func Copy(x, y Vector) { - if x.N != y.N { - panic(badLength) - } - cblas128.Zcopy(x.N, x.Data, x.Inc, y.Data, y.Inc) -} - -// Axpy computes -// -// y = alpha * x + y, -// -// where x and y are vectors, and alpha is a scalar. -// Axpy will panic if the lengths of x and y do not match. -func Axpy(alpha complex128, x, y Vector) { - if x.N != y.N { - panic(badLength) - } - cblas128.Zaxpy(x.N, alpha, x.Data, x.Inc, y.Data, y.Inc) -} - -// Scal computes -// -// x = alpha * x, -// -// where x is a vector, and alpha is a scalar. -// -// Scal will panic if the vector increment is negative. -func Scal(alpha complex128, x Vector) { - if x.Inc < 0 { - panic(negInc) - } - cblas128.Zscal(x.N, alpha, x.Data, x.Inc) -} - -// Dscal computes -// -// x = alpha * x, -// -// where x is a vector, and alpha is a real scalar. -// -// Dscal will panic if the vector increment is negative. -func Dscal(alpha float64, x Vector) { - if x.Inc < 0 { - panic(negInc) - } - cblas128.Zdscal(x.N, alpha, x.Data, x.Inc) -} - -// Level 2 - -// Gemv computes -// -// y = alpha * A * x + beta * y if t == blas.NoTrans, -// y = alpha * Aᵀ * x + beta * y if t == blas.Trans, -// y = alpha * Aᴴ * x + beta * y if t == blas.ConjTrans, -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are -// scalars. -func Gemv(t blas.Transpose, alpha complex128, a General, x Vector, beta complex128, y Vector) { - cblas128.Zgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Gbmv computes -// -// y = alpha * A * x + beta * y if t == blas.NoTrans, -// y = alpha * Aᵀ * x + beta * y if t == blas.Trans, -// y = alpha * Aᴴ * x + beta * y if t == blas.ConjTrans, -// -// where A is an m×n band matrix, x and y are vectors, and alpha and beta are -// scalars. -func Gbmv(t blas.Transpose, alpha complex128, a Band, x Vector, beta complex128, y Vector) { - cblas128.Zgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Trmv computes -// -// x = A * x if t == blas.NoTrans, -// x = Aᵀ * x if t == blas.Trans, -// x = Aᴴ * x if t == blas.ConjTrans, -// -// where A is an n×n triangular matrix, and x is a vector. -func Trmv(t blas.Transpose, a Triangular, x Vector) { - cblas128.Ztrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tbmv computes -// -// x = A * x if t == blas.NoTrans, -// x = Aᵀ * x if t == blas.Trans, -// x = Aᴴ * x if t == blas.ConjTrans, -// -// where A is an n×n triangular band matrix, and x is a vector. -func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { - cblas128.Ztbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tpmv computes -// -// x = A * x if t == blas.NoTrans, -// x = Aᵀ * x if t == blas.Trans, -// x = Aᴴ * x if t == blas.ConjTrans, -// -// where A is an n×n triangular matrix in packed format, and x is a vector. -func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { - cblas128.Ztpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) -} - -// Trsv solves -// -// A * x = b if t == blas.NoTrans, -// Aᵀ * x = b if t == blas.Trans, -// Aᴴ * x = b if t == blas.ConjTrans, -// -// where A is an n×n triangular matrix and x is a vector. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func Trsv(t blas.Transpose, a Triangular, x Vector) { - cblas128.Ztrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tbsv solves -// -// A * x = b if t == blas.NoTrans, -// Aᵀ * x = b if t == blas.Trans, -// Aᴴ * x = b if t == blas.ConjTrans, -// -// where A is an n×n triangular band matrix, and x is a vector. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { - cblas128.Ztbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) -} - -// Tpsv solves -// -// A * x = b if t == blas.NoTrans, -// Aᵀ * x = b if t == blas.Trans, -// Aᴴ * x = b if t == blas.ConjTrans, -// -// where A is an n×n triangular matrix in packed format and x is a vector. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { - cblas128.Ztpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) -} - -// Hemv computes -// -// y = alpha * A * x + beta * y, -// -// where A is an n×n Hermitian matrix, x and y are vectors, and alpha and -// beta are scalars. -func Hemv(alpha complex128, a Hermitian, x Vector, beta complex128, y Vector) { - cblas128.Zhemv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Hbmv performs -// -// y = alpha * A * x + beta * y, -// -// where A is an n×n Hermitian band matrix, x and y are vectors, and alpha -// and beta are scalars. -func Hbmv(alpha complex128, a HermitianBand, x Vector, beta complex128, y Vector) { - cblas128.Zhbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Hpmv performs -// -// y = alpha * A * x + beta * y, -// -// where A is an n×n Hermitian matrix in packed format, x and y are vectors, -// and alpha and beta are scalars. -func Hpmv(alpha complex128, a HermitianPacked, x Vector, beta complex128, y Vector) { - cblas128.Zhpmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) -} - -// Geru performs a rank-1 update -// -// A += alpha * x * yᵀ, -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func Geru(alpha complex128, x, y Vector, a General) { - cblas128.Zgeru(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) -} - -// Gerc performs a rank-1 update -// -// A += alpha * x * yᴴ, -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func Gerc(alpha complex128, x, y Vector, a General) { - cblas128.Zgerc(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) -} - -// Her performs a rank-1 update -// -// A += alpha * x * yᵀ, -// -// where A is an m×n Hermitian matrix, x and y are vectors, and alpha is a scalar. -func Her(alpha float64, x Vector, a Hermitian) { - cblas128.Zher(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) -} - -// Hpr performs a rank-1 update -// -// A += alpha * x * xᴴ, -// -// where A is an n×n Hermitian matrix in packed format, x is a vector, and -// alpha is a scalar. -func Hpr(alpha float64, x Vector, a HermitianPacked) { - cblas128.Zhpr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) -} - -// Her2 performs a rank-2 update -// -// A += alpha * x * yᴴ + conj(alpha) * y * xᴴ, -// -// where A is an n×n Hermitian matrix, x and y are vectors, and alpha is a scalar. -func Her2(alpha complex128, x, y Vector, a Hermitian) { - cblas128.Zher2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) -} - -// Hpr2 performs a rank-2 update -// -// A += alpha * x * yᴴ + conj(alpha) * y * xᴴ, -// -// where A is an n×n Hermitian matrix in packed format, x and y are vectors, -// and alpha is a scalar. -func Hpr2(alpha complex128, x, y Vector, a HermitianPacked) { - cblas128.Zhpr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) -} - -// Level 3 - -// Gemm computes -// -// C = alpha * A * B + beta * C, -// -// where A, B, and C are dense matrices, and alpha and beta are scalars. -// tA and tB specify whether A or B are transposed or conjugated. -func Gemm(tA, tB blas.Transpose, alpha complex128, a, b General, beta complex128, c General) { - var m, n, k int - if tA == blas.NoTrans { - m, k = a.Rows, a.Cols - } else { - m, k = a.Cols, a.Rows - } - if tB == blas.NoTrans { - n = b.Cols - } else { - n = b.Rows - } - cblas128.Zgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} - -// Symm performs -// -// C = alpha * A * B + beta * C if s == blas.Left, -// C = alpha * B * A + beta * C if s == blas.Right, -// -// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and -// alpha and beta are scalars. -func Symm(s blas.Side, alpha complex128, a Symmetric, b General, beta complex128, c General) { - var m, n int - if s == blas.Left { - m, n = a.N, b.Cols - } else { - m, n = b.Rows, a.N - } - cblas128.Zsymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} - -// Syrk performs a symmetric rank-k update -// -// C = alpha * A * Aᵀ + beta * C if t == blas.NoTrans, -// C = alpha * Aᵀ * A + beta * C if t == blas.Trans, -// -// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans -// and a k×n matrix otherwise, and alpha and beta are scalars. -func Syrk(t blas.Transpose, alpha complex128, a General, beta complex128, c Symmetric) { - var n, k int - if t == blas.NoTrans { - n, k = a.Rows, a.Cols - } else { - n, k = a.Cols, a.Rows - } - cblas128.Zsyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) -} - -// Syr2k performs a symmetric rank-2k update -// -// C = alpha * A * Bᵀ + alpha * B * Aᵀ + beta * C if t == blas.NoTrans, -// C = alpha * Aᵀ * B + alpha * Bᵀ * A + beta * C if t == blas.Trans, -// -// where C is an n×n symmetric matrix, A and B are n×k matrices if -// t == blas.NoTrans and k×n otherwise, and alpha and beta are scalars. -func Syr2k(t blas.Transpose, alpha complex128, a, b General, beta complex128, c Symmetric) { - var n, k int - if t == blas.NoTrans { - n, k = a.Rows, a.Cols - } else { - n, k = a.Cols, a.Rows - } - cblas128.Zsyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} - -// Trmm performs -// -// B = alpha * A * B if tA == blas.NoTrans and s == blas.Left, -// B = alpha * Aᵀ * B if tA == blas.Trans and s == blas.Left, -// B = alpha * Aᴴ * B if tA == blas.ConjTrans and s == blas.Left, -// B = alpha * B * A if tA == blas.NoTrans and s == blas.Right, -// B = alpha * B * Aᵀ if tA == blas.Trans and s == blas.Right, -// B = alpha * B * Aᴴ if tA == blas.ConjTrans and s == blas.Right, -// -// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is -// a scalar. -func Trmm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) { - cblas128.Ztrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) -} - -// Trsm solves -// -// A * X = alpha * B if tA == blas.NoTrans and s == blas.Left, -// Aᵀ * X = alpha * B if tA == blas.Trans and s == blas.Left, -// Aᴴ * X = alpha * B if tA == blas.ConjTrans and s == blas.Left, -// X * A = alpha * B if tA == blas.NoTrans and s == blas.Right, -// X * Aᵀ = alpha * B if tA == blas.Trans and s == blas.Right, -// X * Aᴴ = alpha * B if tA == blas.ConjTrans and s == blas.Right, -// -// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and -// alpha is a scalar. -// -// At entry to the function, b contains the values of B, and the result is -// stored in-place into b. -// -// No check is made that A is invertible. -func Trsm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) { - cblas128.Ztrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) -} - -// Hemm performs -// -// C = alpha * A * B + beta * C if s == blas.Left, -// C = alpha * B * A + beta * C if s == blas.Right, -// -// where A is an n×n or m×m Hermitian matrix, B and C are m×n matrices, and -// alpha and beta are scalars. -func Hemm(s blas.Side, alpha complex128, a Hermitian, b General, beta complex128, c General) { - var m, n int - if s == blas.Left { - m, n = a.N, b.Cols - } else { - m, n = b.Rows, a.N - } - cblas128.Zhemm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} - -// Herk performs the Hermitian rank-k update -// -// C = alpha * A * Aᴴ + beta*C if t == blas.NoTrans, -// C = alpha * Aᴴ * A + beta*C if t == blas.ConjTrans, -// -// where C is an n×n Hermitian matrix, A is an n×k matrix if t == blas.NoTrans -// and a k×n matrix otherwise, and alpha and beta are scalars. -func Herk(t blas.Transpose, alpha float64, a General, beta float64, c Hermitian) { - var n, k int - if t == blas.NoTrans { - n, k = a.Rows, a.Cols - } else { - n, k = a.Cols, a.Rows - } - cblas128.Zherk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) -} - -// Her2k performs the Hermitian rank-2k update -// -// C = alpha * A * Bᴴ + conj(alpha) * B * Aᴴ + beta * C if t == blas.NoTrans, -// C = alpha * Aᴴ * B + conj(alpha) * Bᴴ * A + beta * C if t == blas.ConjTrans, -// -// where C is an n×n Hermitian matrix, A and B are n×k matrices if t == NoTrans -// and k×n matrices otherwise, and alpha and beta are scalars. -func Her2k(t blas.Transpose, alpha complex128, a, b General, beta float64, c Hermitian) { - var n, k int - if t == blas.NoTrans { - n, k = a.Rows, a.Cols - } else { - n, k = a.Cols, a.Rows - } - cblas128.Zher2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) -} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go deleted file mode 100644 index bfafb96e..00000000 --- a/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go +++ /dev/null @@ -1,265 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. - -// Copyright ©2015 The Gonum 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 cblas128 - -import "gonum.org/v1/gonum/blas" - -// GeneralCols represents a matrix using the conventional column-major storage scheme. -type GeneralCols General - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions as a and have adequate backing -// data storage. -func (t GeneralCols) From(a General) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("cblas128: mismatched dimension") - } - if len(t.Data) < (t.Cols-1)*t.Stride+t.Rows { - panic("cblas128: short data slice") - } - for i := 0; i < a.Rows; i++ { - for j, v := range a.Data[i*a.Stride : i*a.Stride+a.Cols] { - t.Data[i+j*t.Stride] = v - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions as a and have adequate backing -// data storage. -func (t General) From(a GeneralCols) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("cblas128: mismatched dimension") - } - if len(t.Data) < (t.Rows-1)*t.Stride+t.Cols { - panic("cblas128: short data slice") - } - for j := 0; j < a.Cols; j++ { - for i, v := range a.Data[j*a.Stride : j*a.Stride+a.Rows] { - t.Data[i*t.Stride+j] = v - } - } -} - -// TriangularCols represents a matrix using the conventional column-major storage scheme. -type TriangularCols Triangular - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, uplo and diag as a and have -// adequate backing data storage. -func (t TriangularCols) From(a Triangular) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("cblas128: mismatched BLAS diag") - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - case blas.All: - for i := 0; i < a.N; i++ { - for j := 0; j < a.N; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, uplo and diag as a and have -// adequate backing data storage. -func (t Triangular) From(a TriangularCols) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("cblas128: mismatched BLAS diag") - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - case blas.All: - for i := 0; i < a.N; i++ { - for j := 0; j < a.N; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - } -} - -// BandCols represents a matrix using the band column-major storage scheme. -type BandCols Band - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and bandwidth as a and have -// adequate backing data storage. -func (t BandCols) From(a Band) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("cblas128: mismatched dimension") - } - if t.KL != a.KL || t.KU != a.KU { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.KL+a.KU+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.KL+t.KU+1 { - panic("cblas128: short stride for destination") - } - for i := 0; i < a.Rows; i++ { - for j := max(0, i-a.KL); j < min(i+a.KU+1, a.Cols); j++ { - t.Data[i+t.KU-j+j*t.Stride] = a.Data[j+a.KL-i+i*a.Stride] - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and bandwidth as a and have -// adequate backing data storage. -func (t Band) From(a BandCols) { - if t.Rows != a.Rows || t.Cols != a.Cols { - panic("cblas128: mismatched dimension") - } - if t.KL != a.KL || t.KU != a.KU { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.KL+a.KU+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.KL+t.KU+1 { - panic("cblas128: short stride for destination") - } - for j := 0; j < a.Cols; j++ { - for i := max(0, j-a.KU); i < min(j+a.KL+1, a.Rows); i++ { - t.Data[j+a.KL-i+i*a.Stride] = a.Data[i+t.KU-j+j*t.Stride] - } - } -} - -// TriangularBandCols represents a triangular matrix using the band column-major storage scheme. -type TriangularBandCols TriangularBand - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t TriangularBandCols) From(a TriangularBand) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.K != a.K { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.K+1 { - panic("cblas128: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("cblas128: mismatched BLAS diag") - } - dst := BandCols{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := Band{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t TriangularBand) From(a TriangularBandCols) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.K != a.K { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.K+1 { - panic("cblas128: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - if t.Diag != a.Diag { - panic("cblas128: mismatched BLAS diag") - } - dst := Band{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := BandCols{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go deleted file mode 100644 index 51c3a577..00000000 --- a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. - -// Copyright ©2015 The Gonum 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 cblas128 - -import "gonum.org/v1/gonum/blas" - -// HermitianCols represents a matrix using the conventional column-major storage scheme. -type HermitianCols Hermitian - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and uplo as a and have adequate -// backing data storage. -func (t HermitianCols) From(a Hermitian) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and uplo as a and have adequate -// backing data storage. -func (t Hermitian) From(a HermitianCols) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - } -} - -// HermitianBandCols represents an Hermitian matrix using the band column-major storage scheme. -type HermitianBandCols HermitianBand - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t HermitianBandCols) From(a HermitianBand) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.K != a.K { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.K+1 { - panic("cblas128: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - dst := BandCols{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := Band{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t HermitianBand) From(a HermitianBandCols) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.K != a.K { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.K+1 { - panic("cblas128: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - dst := Band{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := BandCols{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go deleted file mode 100644 index f1bf40c2..00000000 --- a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT. - -// Copyright ©2015 The Gonum 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 cblas128 - -import "gonum.org/v1/gonum/blas" - -// SymmetricCols represents a matrix using the conventional column-major storage scheme. -type SymmetricCols Symmetric - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and uplo as a and have adequate -// backing data storage. -func (t SymmetricCols) From(a Symmetric) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] - } - } - } -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions and uplo as a and have adequate -// backing data storage. -func (t Symmetric) From(a SymmetricCols) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - for i := 0; i < a.N; i++ { - for j := i; j < a.N; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - case blas.Lower: - for i := 0; i < a.N; i++ { - for j := 0; j <= i; j++ { - t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] - } - } - } -} - -// SymmetricBandCols represents a symmetric matrix using the band column-major storage scheme. -type SymmetricBandCols SymmetricBand - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t SymmetricBandCols) From(a SymmetricBand) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.K != a.K { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.K+1 { - panic("cblas128: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - dst := BandCols{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := Band{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} - -// From fills the receiver with elements from a. The receiver -// must have the same dimensions, bandwidth and uplo as a and -// have adequate backing data storage. -func (t SymmetricBand) From(a SymmetricBandCols) { - if t.N != a.N { - panic("cblas128: mismatched dimension") - } - if t.K != a.K { - panic("cblas128: mismatched bandwidth") - } - if a.Stride < a.K+1 { - panic("cblas128: short stride for source") - } - if t.Stride < t.K+1 { - panic("cblas128: short stride for destination") - } - if t.Uplo != a.Uplo { - panic("cblas128: mismatched BLAS uplo") - } - dst := Band{ - Rows: t.N, Cols: t.N, - Stride: t.Stride, - Data: t.Data, - } - src := BandCols{ - Rows: a.N, Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } - switch a.Uplo { - default: - panic("cblas128: bad BLAS uplo") - case blas.Upper: - dst.KU = t.K - src.KU = a.K - case blas.Lower: - dst.KL = t.K - src.KL = a.K - } - dst.From(src) -} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go b/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go deleted file mode 100644 index 09719b19..00000000 --- a/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 cblas128 provides a simple interface to the complex128 BLAS API. -package cblas128 // import "gonum.org/v1/gonum/blas/cblas128" diff --git a/vendor/gonum.org/v1/gonum/blas/conversions.bash b/vendor/gonum.org/v1/gonum/blas/conversions.bash deleted file mode 100644 index d1c0ef0d..00000000 --- a/vendor/gonum.org/v1/gonum/blas/conversions.bash +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env bash - -# Copyright ©2017 The Gonum Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# Generate code for blas32. -echo Generating blas32/conv.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv.go -cat blas64/conv.go \ -| gofmt -r 'float64 -> float32' \ -\ -| sed -e 's/blas64/blas32/' \ -\ ->> blas32/conv.go - -echo Generating blas32/conv_test.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv_test.go -cat blas64/conv_test.go \ -| gofmt -r 'float64 -> float32' \ -\ -| sed -e 's/blas64/blas32/' \ - -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ -\ ->> blas32/conv_test.go - -echo Generating blas32/conv_symmetric.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv_symmetric.go -cat blas64/conv_symmetric.go \ -| gofmt -r 'float64 -> float32' \ -\ -| sed -e 's/blas64/blas32/' \ -\ ->> blas32/conv_symmetric.go - -echo Generating blas32/conv_symmetric_test.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > blas32/conv_symmetric_test.go -cat blas64/conv_symmetric_test.go \ -| gofmt -r 'float64 -> float32' \ -\ -| sed -e 's/blas64/blas32/' \ - -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ -\ ->> blas32/conv_symmetric_test.go - - -# Generate code for cblas128. -echo Generating cblas128/conv.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv.go -cat blas64/conv.go \ -| gofmt -r 'float64 -> complex128' \ -\ -| sed -e 's/blas64/cblas128/' \ -\ ->> cblas128/conv.go - -echo Generating cblas128/conv_test.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_test.go -cat blas64/conv_test.go \ -| gofmt -r 'float64 -> complex128' \ -\ -| sed -e 's/blas64/cblas128/' \ - -e 's_"math"_math "math/cmplx"_' \ -\ ->> cblas128/conv_test.go - -echo Generating cblas128/conv_symmetric.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_symmetric.go -cat blas64/conv_symmetric.go \ -| gofmt -r 'float64 -> complex128' \ -\ -| sed -e 's/blas64/cblas128/' \ -\ ->> cblas128/conv_symmetric.go - -echo Generating cblas128/conv_symmetric_test.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_symmetric_test.go -cat blas64/conv_symmetric_test.go \ -| gofmt -r 'float64 -> complex128' \ -\ -| sed -e 's/blas64/cblas128/' \ - -e 's_"math"_math "math/cmplx"_' \ -\ ->> cblas128/conv_symmetric_test.go - -echo Generating cblas128/conv_hermitian.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_hermitian.go -cat blas64/conv_symmetric.go \ -| gofmt -r 'float64 -> complex128' \ -\ -| sed -e 's/blas64/cblas128/' \ - -e 's/Symmetric/Hermitian/g' \ - -e 's/a symmetric/an Hermitian/g' \ - -e 's/symmetric/hermitian/g' \ - -e 's/Sym/Herm/g' \ -\ ->> cblas128/conv_hermitian.go - -echo Generating cblas128/conv_hermitian_test.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas128/conv_hermitian_test.go -cat blas64/conv_symmetric_test.go \ -| gofmt -r 'float64 -> complex128' \ -\ -| sed -e 's/blas64/cblas128/' \ - -e 's/Symmetric/Hermitian/g' \ - -e 's/a symmetric/an Hermitian/g' \ - -e 's/symmetric/hermitian/g' \ - -e 's/Sym/Herm/g' \ - -e 's_"math"_math "math/cmplx"_' \ -\ ->> cblas128/conv_hermitian_test.go - - -# Generate code for cblas64. -echo Generating cblas64/conv.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv.go -cat blas64/conv.go \ -| gofmt -r 'float64 -> complex64' \ -\ -| sed -e 's/blas64/cblas64/' \ -\ ->> cblas64/conv.go - -echo Generating cblas64/conv_test.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv_test.go -cat blas64/conv_test.go \ -| gofmt -r 'float64 -> complex64' \ -\ -| sed -e 's/blas64/cblas64/' \ - -e 's_"math"_math "gonum.org/v1/gonum/internal/cmplx64"_' \ -\ ->> cblas64/conv_test.go - -echo Generating cblas64/conv_hermitian.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv_hermitian.go -cat blas64/conv_symmetric.go \ -| gofmt -r 'float64 -> complex64' \ -\ -| sed -e 's/blas64/cblas64/' \ - -e 's/Symmetric/Hermitian/g' \ - -e 's/a symmetric/an Hermitian/g' \ - -e 's/symmetric/hermitian/g' \ - -e 's/Sym/Herm/g' \ -\ ->> cblas64/conv_hermitian.go - -echo Generating cblas64/conv_hermitian_test.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas”; DO NOT EDIT.\n' > cblas64/conv_hermitian_test.go -cat blas64/conv_symmetric_test.go \ -| gofmt -r 'float64 -> complex64' \ -\ -| sed -e 's/blas64/cblas64/' \ - -e 's/Symmetric/Hermitian/g' \ - -e 's/a symmetric/an Hermitian/g' \ - -e 's/symmetric/hermitian/g' \ - -e 's/Sym/Herm/g' \ - -e 's_"math"_math "gonum.org/v1/gonum/internal/cmplx64"_' \ -\ ->> cblas64/conv_hermitian_test.go diff --git a/vendor/gonum.org/v1/gonum/blas/doc.go b/vendor/gonum.org/v1/gonum/blas/doc.go deleted file mode 100644 index ea4b16c9..00000000 --- a/vendor/gonum.org/v1/gonum/blas/doc.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright ©2017 The Gonum 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 blas provides interfaces for the BLAS linear algebra standard. - -All methods must perform appropriate parameter checking and panic if -provided parameters that do not conform to the requirements specified -by the BLAS standard. - -Quick Reference Guide to the BLAS from http://www.netlib.org/lapack/lug/node145.html - -This version is modified to remove the "order" option. All matrix operations are -on row-order matrices. - -Level 1 BLAS - - dim scalar vector vector scalars 5-element prefixes - struct - - _rotg ( a, b ) S, D - _rotmg( d1, d2, a, b ) S, D - _rot ( n, x, incX, y, incY, c, s ) S, D - _rotm ( n, x, incX, y, incY, param ) S, D - _swap ( n, x, incX, y, incY ) S, D, C, Z - _scal ( n, alpha, x, incX ) S, D, C, Z, Cs, Zd - _copy ( n, x, incX, y, incY ) S, D, C, Z - _axpy ( n, alpha, x, incX, y, incY ) S, D, C, Z - _dot ( n, x, incX, y, incY ) S, D, Ds - _dotu ( n, x, incX, y, incY ) C, Z - _dotc ( n, x, incX, y, incY ) C, Z - __dot ( n, alpha, x, incX, y, incY ) Sds - _nrm2 ( n, x, incX ) S, D, Sc, Dz - _asum ( n, x, incX ) S, D, Sc, Dz - I_amax( n, x, incX ) s, d, c, z - -Level 2 BLAS - - options dim b-width scalar matrix vector scalar vector prefixes - - _gemv ( trans, m, n, alpha, a, lda, x, incX, beta, y, incY ) S, D, C, Z - _gbmv ( trans, m, n, kL, kU, alpha, a, lda, x, incX, beta, y, incY ) S, D, C, Z - _hemv ( uplo, n, alpha, a, lda, x, incX, beta, y, incY ) C, Z - _hbmv ( uplo, n, k, alpha, a, lda, x, incX, beta, y, incY ) C, Z - _hpmv ( uplo, n, alpha, ap, x, incX, beta, y, incY ) C, Z - _symv ( uplo, n, alpha, a, lda, x, incX, beta, y, incY ) S, D - _sbmv ( uplo, n, k, alpha, a, lda, x, incX, beta, y, incY ) S, D - _spmv ( uplo, n, alpha, ap, x, incX, beta, y, incY ) S, D - _trmv ( uplo, trans, diag, n, a, lda, x, incX ) S, D, C, Z - _tbmv ( uplo, trans, diag, n, k, a, lda, x, incX ) S, D, C, Z - _tpmv ( uplo, trans, diag, n, ap, x, incX ) S, D, C, Z - _trsv ( uplo, trans, diag, n, a, lda, x, incX ) S, D, C, Z - _tbsv ( uplo, trans, diag, n, k, a, lda, x, incX ) S, D, C, Z - _tpsv ( uplo, trans, diag, n, ap, x, incX ) S, D, C, Z - - options dim scalar vector vector matrix prefixes - - _ger ( m, n, alpha, x, incX, y, incY, a, lda ) S, D - _geru ( m, n, alpha, x, incX, y, incY, a, lda ) C, Z - _gerc ( m, n, alpha, x, incX, y, incY, a, lda ) C, Z - _her ( uplo, n, alpha, x, incX, a, lda ) C, Z - _hpr ( uplo, n, alpha, x, incX, ap ) C, Z - _her2 ( uplo, n, alpha, x, incX, y, incY, a, lda ) C, Z - _hpr2 ( uplo, n, alpha, x, incX, y, incY, ap ) C, Z - _syr ( uplo, n, alpha, x, incX, a, lda ) S, D - _spr ( uplo, n, alpha, x, incX, ap ) S, D - _syr2 ( uplo, n, alpha, x, incX, y, incY, a, lda ) S, D - _spr2 ( uplo, n, alpha, x, incX, y, incY, ap ) S, D - -Level 3 BLAS - - options dim scalar matrix matrix scalar matrix prefixes - - _gemm ( transA, transB, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z - _symm ( side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z - _hemm ( side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc ) C, Z - _syrk ( uplo, trans, n, k, alpha, a, lda, beta, c, ldc ) S, D, C, Z - _herk ( uplo, trans, n, k, alpha, a, lda, beta, c, ldc ) C, Z - _syr2k( uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z - _her2k( uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) C, Z - _trmm ( side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb ) S, D, C, Z - _trsm ( side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb ) S, D, C, Z - -Meaning of prefixes - - S - float32 C - complex64 - D - float64 Z - complex128 - -Matrix types - - GE - GEneral GB - General Band - SY - SYmmetric SB - Symmetric Band SP - Symmetric Packed - HE - HErmitian HB - Hermitian Band HP - Hermitian Packed - TR - TRiangular TB - Triangular Band TP - Triangular Packed - -Options - - trans = NoTrans, Trans, ConjTrans - uplo = Upper, Lower - diag = Nonunit, Unit - side = Left, Right (A or op(A) on the left, or A or op(A) on the right) - -For real matrices, Trans and ConjTrans have the same meaning. -For Hermitian matrices, trans = Trans is not allowed. -For complex symmetric matrices, trans = ConjTrans is not allowed. -*/ -package blas // import "gonum.org/v1/gonum/blas" diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go b/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go deleted file mode 100644 index 9e74cc1d..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright ©2014 The Gonum 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 gonum - -import ( - "runtime" - "sync" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f64" -) - -// Dgemm performs one of the matrix-matrix operations -// -// C = alpha * A * B + beta * C -// C = alpha * Aᵀ * B + beta * C -// C = alpha * A * Bᵀ + beta * C -// C = alpha * Aᵀ * Bᵀ + beta * C -// -// where A is an m×k or k×m dense matrix, B is an n×k or k×n dense matrix, C is -// an m×n matrix, and alpha and beta are scalars. tA and tB specify whether A or -// B are transposed. -func (Implementation) Dgemm(tA, tB blas.Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { - switch tA { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch tB { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - aTrans := tA == blas.Trans || tA == blas.ConjTrans - if aTrans { - if lda < max(1, m) { - panic(badLdA) - } - } else { - if lda < max(1, k) { - panic(badLdA) - } - } - bTrans := tB == blas.Trans || tB == blas.ConjTrans - if bTrans { - if ldb < max(1, k) { - panic(badLdB) - } - } else { - if ldb < max(1, n) { - panic(badLdB) - } - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if aTrans { - if len(a) < (k-1)*lda+m { - panic(shortA) - } - } else { - if len(a) < (m-1)*lda+k { - panic(shortA) - } - } - if bTrans { - if len(b) < (n-1)*ldb+k { - panic(shortB) - } - } else { - if len(b) < (k-1)*ldb+n { - panic(shortB) - } - } - if len(c) < (m-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - // scale c - if beta != 1 { - if beta == 0 { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := range ctmp { - ctmp[j] *= beta - } - } - } - } - - dgemmParallel(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) -} - -func dgemmParallel(aTrans, bTrans bool, m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { - // dgemmParallel computes a parallel matrix multiplication by partitioning - // a and b into sub-blocks, and updating c with the multiplication of the sub-block - // In all cases, - // A = [ A_11 A_12 ... A_1j - // A_21 A_22 ... A_2j - // ... - // A_i1 A_i2 ... A_ij] - // - // and same for B. All of the submatrix sizes are blockSize×blockSize except - // at the edges. - // - // In all cases, there is one dimension for each matrix along which - // C must be updated sequentially. - // Cij = \sum_k Aik Bki, (A * B) - // Cij = \sum_k Aki Bkj, (Aᵀ * B) - // Cij = \sum_k Aik Bjk, (A * Bᵀ) - // Cij = \sum_k Aki Bjk, (Aᵀ * Bᵀ) - // - // This code computes one {i, j} block sequentially along the k dimension, - // and computes all of the {i, j} blocks concurrently. This - // partitioning allows Cij to be updated in-place without race-conditions. - // Instead of launching a goroutine for each possible concurrent computation, - // a number of worker goroutines are created and channels are used to pass - // available and completed cases. - // - // http://alexkr.com/docs/matrixmult.pdf is a good reference on matrix-matrix - // multiplies, though this code does not copy matrices to attempt to eliminate - // cache misses. - - maxKLen := k - parBlocks := blocks(m, blockSize) * blocks(n, blockSize) - if parBlocks < minParBlock { - // The matrix multiplication is small in the dimensions where it can be - // computed concurrently. Just do it in serial. - dgemmSerial(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - } - - // workerLimit acts a number of maximum concurrent workers, - // with the limit set to the number of procs available. - workerLimit := make(chan struct{}, runtime.GOMAXPROCS(0)) - - // wg is used to wait for all - var wg sync.WaitGroup - wg.Add(parBlocks) - defer wg.Wait() - - for i := 0; i < m; i += blockSize { - for j := 0; j < n; j += blockSize { - workerLimit <- struct{}{} - go func(i, j int) { - defer func() { - wg.Done() - <-workerLimit - }() - - leni := blockSize - if i+leni > m { - leni = m - i - } - lenj := blockSize - if j+lenj > n { - lenj = n - j - } - - cSub := sliceView64(c, ldc, i, j, leni, lenj) - - // Compute A_ik B_kj for all k - for k := 0; k < maxKLen; k += blockSize { - lenk := blockSize - if k+lenk > maxKLen { - lenk = maxKLen - k - } - var aSub, bSub []float64 - if aTrans { - aSub = sliceView64(a, lda, k, i, lenk, leni) - } else { - aSub = sliceView64(a, lda, i, k, leni, lenk) - } - if bTrans { - bSub = sliceView64(b, ldb, j, k, lenj, lenk) - } else { - bSub = sliceView64(b, ldb, k, j, lenk, lenj) - } - dgemmSerial(aTrans, bTrans, leni, lenj, lenk, aSub, lda, bSub, ldb, cSub, ldc, alpha) - } - }(i, j) - } - } -} - -// dgemmSerial is serial matrix multiply -func dgemmSerial(aTrans, bTrans bool, m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { - switch { - case !aTrans && !bTrans: - dgemmSerialNotNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - case aTrans && !bTrans: - dgemmSerialTransNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - case !aTrans && bTrans: - dgemmSerialNotTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - case aTrans && bTrans: - dgemmSerialTransTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - default: - panic("unreachable") - } -} - -// dgemmSerial where neither a nor b are transposed -func dgemmSerialNotNot(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for l, v := range a[i*lda : i*lda+k] { - tmp := alpha * v - if tmp != 0 { - f64.AxpyUnitary(tmp, b[l*ldb:l*ldb+n], ctmp) - } - } - } -} - -// dgemmSerial where neither a is transposed and b is not -func dgemmSerialTransNot(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for l := 0; l < k; l++ { - btmp := b[l*ldb : l*ldb+n] - for i, v := range a[l*lda : l*lda+m] { - tmp := alpha * v - if tmp != 0 { - ctmp := c[i*ldc : i*ldc+n] - f64.AxpyUnitary(tmp, btmp, ctmp) - } - } - } -} - -// dgemmSerial where neither a is not transposed and b is -func dgemmSerialNotTrans(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for i := 0; i < m; i++ { - atmp := a[i*lda : i*lda+k] - ctmp := c[i*ldc : i*ldc+n] - for j := 0; j < n; j++ { - ctmp[j] += alpha * f64.DotUnitary(atmp, b[j*ldb:j*ldb+k]) - } - } -} - -// dgemmSerial where both are transposed -func dgemmSerialTransTrans(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for l := 0; l < k; l++ { - for i, v := range a[l*lda : l*lda+m] { - tmp := alpha * v - if tmp != 0 { - ctmp := c[i*ldc : i*ldc+n] - f64.AxpyInc(tmp, b[l:], ctmp, uintptr(n), uintptr(ldb), 1, 0, 0) - } - } - } -} - -func sliceView64(a []float64, lda, i, j, r, c int) []float64 { - return a[i*lda+j : (i+r-1)*lda+j+c] -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/doc.go b/vendor/gonum.org/v1/gonum/blas/gonum/doc.go deleted file mode 100644 index cbca601d..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/doc.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Ensure changes made to blas/native are reflected in blas/cgo where relevant. - -/* -Package gonum is a Go implementation of the BLAS API. This implementation -panics when the input arguments are invalid as per the standard, for example -if a vector increment is zero. Note that the treatment of NaN values -is not specified, and differs among the BLAS implementations. -gonum.org/v1/gonum/blas/blas64 provides helpful wrapper functions to the BLAS -interface. The rest of this text describes the layout of the data for the input types. - -Note that in the function documentation, x[i] refers to the i^th element -of the vector, which will be different from the i^th element of the slice if -incX != 1. - -See http://www.netlib.org/lapack/explore-html/d4/de1/_l_i_c_e_n_s_e_source.html -for more license information. - -Vector arguments are effectively strided slices. They have two input arguments, -a number of elements, n, and an increment, incX. The increment specifies the -distance between elements of the vector. The actual Go slice may be longer -than necessary. -The increment may be positive or negative, except in functions with only -a single vector argument where the increment may only be positive. If the increment -is negative, s[0] is the last element in the slice. Note that this is not the same -as counting backward from the end of the slice, as len(s) may be longer than -necessary. So, for example, if n = 5 and incX = 3, the elements of s are - - [0 * * 1 * * 2 * * 3 * * 4 * * * ...] - -where ∗ elements are never accessed. If incX = -3, the same elements are -accessed, just in reverse order (4, 3, 2, 1, 0). - -Dense matrices are specified by a number of rows, a number of columns, and a stride. -The stride specifies the number of entries in the slice between the first element -of successive rows. The stride must be at least as large as the number of columns -but may be longer. - - [a00 ... a0n a0* ... a1stride-1 a21 ... amn am* ... amstride-1] - -Thus, dense[i*ld + j] refers to the {i, j}th element of the matrix. - -Symmetric and triangular matrices (non-packed) are stored identically to Dense, -except that only elements in one triangle of the matrix are accessed. - -Packed symmetric and packed triangular matrices are laid out with the entries -condensed such that all of the unreferenced elements are removed. So, the upper triangular -matrix - - [ - 1 2 3 - 0 4 5 - 0 0 6 - ] - -and the lower-triangular matrix - - [ - 1 0 0 - 2 3 0 - 4 5 6 - ] - -will both be compacted as [1 2 3 4 5 6]. The (i, j) element of the original -dense matrix can be found at element i*n - (i-1)*i/2 + j for upper triangular, -and at element i * (i+1) /2 + j for lower triangular. - -Banded matrices are laid out in a compact format, constructed by removing the -zeros in the rows and aligning the diagonals. For example, the matrix - - [ - 1 2 3 0 0 0 - 4 5 6 7 0 0 - 0 8 9 10 11 0 - 0 0 12 13 14 15 - 0 0 0 16 17 18 - 0 0 0 0 19 20 - ] - -implicitly becomes (∗ entries are never accessed) - - [ - * 1 2 3 - 4 5 6 7 - 8 9 10 11 - 12 13 14 15 - 16 17 18 * - 19 20 * * - ] - -which is given to the BLAS routine as [∗ 1 2 3 4 ...]. - -See http://www.crest.iu.edu/research/mtl/reference/html/banded.html -for more information -*/ -package gonum // import "gonum.org/v1/gonum/blas/gonum" diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/errors.go b/vendor/gonum.org/v1/gonum/blas/gonum/errors.go deleted file mode 100644 index e98575d0..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/errors.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -// Panic strings used during parameter checks. -// This list is duplicated in netlib/blas/netlib. Keep in sync. -const ( - zeroIncX = "blas: zero x index increment" - zeroIncY = "blas: zero y index increment" - - mLT0 = "blas: m < 0" - nLT0 = "blas: n < 0" - kLT0 = "blas: k < 0" - kLLT0 = "blas: kL < 0" - kULT0 = "blas: kU < 0" - - badUplo = "blas: illegal triangle" - badTranspose = "blas: illegal transpose" - badDiag = "blas: illegal diagonal" - badSide = "blas: illegal side" - badFlag = "blas: illegal rotm flag" - - badLdA = "blas: bad leading dimension of A" - badLdB = "blas: bad leading dimension of B" - badLdC = "blas: bad leading dimension of C" - - shortX = "blas: insufficient length of x" - shortY = "blas: insufficient length of y" - shortAP = "blas: insufficient length of ap" - shortA = "blas: insufficient length of a" - shortB = "blas: insufficient length of b" - shortC = "blas: insufficient length of c" -) diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go b/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go deleted file mode 100644 index 5a5c1110..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:generate ./single_precision.bash - -package gonum - -import ( - "math" - - "gonum.org/v1/gonum/internal/math32" -) - -type Implementation struct{} - -// [SD]gemm behavior constants. These are kept here to keep them out of the -// way during single precision code generation. -const ( - blockSize = 64 // b x b matrix - minParBlock = 4 // minimum number of blocks needed to go parallel -) - -// blocks returns the number of divisions of the dimension length with the given -// block size. -func blocks(dim, bsize int) int { - return (dim + bsize - 1) / bsize -} - -// dcabs1 returns |real(z)|+|imag(z)|. -func dcabs1(z complex128) float64 { - return math.Abs(real(z)) + math.Abs(imag(z)) -} - -// scabs1 returns |real(z)|+|imag(z)|. -func scabs1(z complex64) float32 { - return math32.Abs(real(z)) + math32.Abs(imag(z)) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go deleted file mode 100644 index 3e3af0db..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go +++ /dev/null @@ -1,454 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/c128" -) - -var _ blas.Complex128Level1 = Implementation{} - -// Dzasum returns the sum of the absolute values of the elements of x -// -// \sum_i |Re(x[i])| + |Im(x[i])| -// -// Dzasum returns 0 if incX is negative. -func (Implementation) Dzasum(n int, x []complex128, incX int) float64 { - if n < 0 { - panic(nLT0) - } - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - var sum float64 - if incX == 1 { - if len(x) < n { - panic(shortX) - } - for _, v := range x[:n] { - sum += dcabs1(v) - } - return sum - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - for i := 0; i < n; i++ { - v := x[i*incX] - sum += dcabs1(v) - } - return sum -} - -// Dznrm2 computes the Euclidean norm of the complex vector x, -// -// ‖x‖_2 = sqrt(\sum_i x[i] * conj(x[i])). -// -// This function returns 0 if incX is negative. -func (Implementation) Dznrm2(n int, x []complex128, incX int) float64 { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - if n < 1 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - var ( - scale float64 - ssq float64 = 1 - ) - if incX == 1 { - for _, v := range x[:n] { - re, im := math.Abs(real(v)), math.Abs(imag(v)) - if re != 0 { - if re > scale { - ssq = 1 + ssq*(scale/re)*(scale/re) - scale = re - } else { - ssq += (re / scale) * (re / scale) - } - } - if im != 0 { - if im > scale { - ssq = 1 + ssq*(scale/im)*(scale/im) - scale = im - } else { - ssq += (im / scale) * (im / scale) - } - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(ssq) - } - for ix := 0; ix < n*incX; ix += incX { - re, im := math.Abs(real(x[ix])), math.Abs(imag(x[ix])) - if re != 0 { - if re > scale { - ssq = 1 + ssq*(scale/re)*(scale/re) - scale = re - } else { - ssq += (re / scale) * (re / scale) - } - } - if im != 0 { - if im > scale { - ssq = 1 + ssq*(scale/im)*(scale/im) - scale = im - } else { - ssq += (im / scale) * (im / scale) - } - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(ssq) -} - -// Izamax returns the index of the first element of x having largest |Re(·)|+|Im(·)|. -// Izamax returns -1 if n is 0 or incX is negative. -func (Implementation) Izamax(n int, x []complex128, incX int) int { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - // Return invalid index. - return -1 - } - if n < 1 { - if n == 0 { - // Return invalid index. - return -1 - } - panic(nLT0) - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - idx := 0 - max := dcabs1(x[0]) - if incX == 1 { - for i, v := range x[1:n] { - absV := dcabs1(v) - if absV > max { - max = absV - idx = i + 1 - } - } - return idx - } - ix := incX - for i := 1; i < n; i++ { - absV := dcabs1(x[ix]) - if absV > max { - max = absV - idx = i - } - ix += incX - } - return idx -} - -// Zaxpy adds alpha times x to y: -// -// y[i] += alpha * x[i] for all i -func (Implementation) Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(shortY) - } - if alpha == 0 { - return - } - if incX == 1 && incY == 1 { - c128.AxpyUnitary(alpha, x[:n], y[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (1 - n) * incX - } - if incY < 0 { - iy = (1 - n) * incY - } - c128.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Zcopy copies the vector x to vector y. -func (Implementation) Zcopy(n int, x []complex128, incX int, y []complex128, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(shortY) - } - if incX == 1 && incY == 1 { - copy(y[:n], x[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - y[iy] = x[ix] - ix += incX - iy += incY - } -} - -// Zdotc computes the dot product -// -// xᴴ · y -// -// of two complex vectors x and y. -func (Implementation) Zdotc(n int, x []complex128, incX int, y []complex128, incY int) complex128 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return c128.DotcUnitary(x[:n], y[:n]) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || (n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || (n-1)*incY >= len(y) { - panic(shortY) - } - return c128.DotcInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Zdotu computes the dot product -// -// xᵀ · y -// -// of two complex vectors x and y. -func (Implementation) Zdotu(n int, x []complex128, incX int, y []complex128, incY int) complex128 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return c128.DotuUnitary(x[:n], y[:n]) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || (n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || (n-1)*incY >= len(y) { - panic(shortY) - } - return c128.DotuInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Zdscal scales the vector x by a real scalar alpha. -// Zdscal has no effect if incX < 0. -func (Implementation) Zdscal(n int, alpha float64, x []complex128, incX int) { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if alpha == 0 { - if incX == 1 { - x = x[:n] - for i := range x { - x[i] = 0 - } - return - } - for ix := 0; ix < n*incX; ix += incX { - x[ix] = 0 - } - return - } - if incX == 1 { - x = x[:n] - for i, v := range x { - x[i] = complex(alpha*real(v), alpha*imag(v)) - } - return - } - for ix := 0; ix < n*incX; ix += incX { - v := x[ix] - x[ix] = complex(alpha*real(v), alpha*imag(v)) - } -} - -// Zscal scales the vector x by a complex scalar alpha. -// Zscal has no effect if incX < 0. -func (Implementation) Zscal(n int, alpha complex128, x []complex128, incX int) { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if alpha == 0 { - if incX == 1 { - x = x[:n] - for i := range x { - x[i] = 0 - } - return - } - for ix := 0; ix < n*incX; ix += incX { - x[ix] = 0 - } - return - } - if incX == 1 { - c128.ScalUnitary(alpha, x[:n]) - return - } - c128.ScalInc(alpha, x, uintptr(n), uintptr(incX)) -} - -// Zswap exchanges the elements of two complex vectors x and y. -func (Implementation) Zswap(n int, x []complex128, incX int, y []complex128, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(shortY) - } - if incX == 1 && incY == 1 { - x = x[:n] - for i, v := range x { - x[i], y[i] = y[i], v - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - x[ix], y[iy] = y[iy], x[ix] - ix += incX - iy += incY - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go deleted file mode 100644 index 249335ca..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go +++ /dev/null @@ -1,476 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2017 The Gonum 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 gonum - -import ( - math "gonum.org/v1/gonum/internal/math32" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/c64" -) - -var _ blas.Complex64Level1 = Implementation{} - -// Scasum returns the sum of the absolute values of the elements of x -// -// \sum_i |Re(x[i])| + |Im(x[i])| -// -// Scasum returns 0 if incX is negative. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Scasum(n int, x []complex64, incX int) float32 { - if n < 0 { - panic(nLT0) - } - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - var sum float32 - if incX == 1 { - if len(x) < n { - panic(shortX) - } - for _, v := range x[:n] { - sum += scabs1(v) - } - return sum - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - for i := 0; i < n; i++ { - v := x[i*incX] - sum += scabs1(v) - } - return sum -} - -// Scnrm2 computes the Euclidean norm of the complex vector x, -// -// ‖x‖_2 = sqrt(\sum_i x[i] * conj(x[i])). -// -// This function returns 0 if incX is negative. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Scnrm2(n int, x []complex64, incX int) float32 { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - if n < 1 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - var ( - scale float32 - ssq float32 = 1 - ) - if incX == 1 { - for _, v := range x[:n] { - re, im := math.Abs(real(v)), math.Abs(imag(v)) - if re != 0 { - if re > scale { - ssq = 1 + ssq*(scale/re)*(scale/re) - scale = re - } else { - ssq += (re / scale) * (re / scale) - } - } - if im != 0 { - if im > scale { - ssq = 1 + ssq*(scale/im)*(scale/im) - scale = im - } else { - ssq += (im / scale) * (im / scale) - } - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(ssq) - } - for ix := 0; ix < n*incX; ix += incX { - re, im := math.Abs(real(x[ix])), math.Abs(imag(x[ix])) - if re != 0 { - if re > scale { - ssq = 1 + ssq*(scale/re)*(scale/re) - scale = re - } else { - ssq += (re / scale) * (re / scale) - } - } - if im != 0 { - if im > scale { - ssq = 1 + ssq*(scale/im)*(scale/im) - scale = im - } else { - ssq += (im / scale) * (im / scale) - } - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(ssq) -} - -// Icamax returns the index of the first element of x having largest |Re(·)|+|Im(·)|. -// Icamax returns -1 if n is 0 or incX is negative. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Icamax(n int, x []complex64, incX int) int { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - // Return invalid index. - return -1 - } - if n < 1 { - if n == 0 { - // Return invalid index. - return -1 - } - panic(nLT0) - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - idx := 0 - max := scabs1(x[0]) - if incX == 1 { - for i, v := range x[1:n] { - absV := scabs1(v) - if absV > max { - max = absV - idx = i + 1 - } - } - return idx - } - ix := incX - for i := 1; i < n; i++ { - absV := scabs1(x[ix]) - if absV > max { - max = absV - idx = i - } - ix += incX - } - return idx -} - -// Caxpy adds alpha times x to y: -// -// y[i] += alpha * x[i] for all i -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(shortY) - } - if alpha == 0 { - return - } - if incX == 1 && incY == 1 { - c64.AxpyUnitary(alpha, x[:n], y[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (1 - n) * incX - } - if incY < 0 { - iy = (1 - n) * incY - } - c64.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Ccopy copies the vector x to vector y. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ccopy(n int, x []complex64, incX int, y []complex64, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(shortY) - } - if incX == 1 && incY == 1 { - copy(y[:n], x[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - y[iy] = x[ix] - ix += incX - iy += incY - } -} - -// Cdotc computes the dot product -// -// xᴴ · y -// -// of two complex vectors x and y. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cdotc(n int, x []complex64, incX int, y []complex64, incY int) complex64 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return c64.DotcUnitary(x[:n], y[:n]) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || (n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || (n-1)*incY >= len(y) { - panic(shortY) - } - return c64.DotcInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Cdotu computes the dot product -// -// xᵀ · y -// -// of two complex vectors x and y. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cdotu(n int, x []complex64, incX int, y []complex64, incY int) complex64 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return c64.DotuUnitary(x[:n], y[:n]) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || (n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || (n-1)*incY >= len(y) { - panic(shortY) - } - return c64.DotuInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Csscal scales the vector x by a real scalar alpha. -// Csscal has no effect if incX < 0. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Csscal(n int, alpha float32, x []complex64, incX int) { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if alpha == 0 { - if incX == 1 { - x = x[:n] - for i := range x { - x[i] = 0 - } - return - } - for ix := 0; ix < n*incX; ix += incX { - x[ix] = 0 - } - return - } - if incX == 1 { - x = x[:n] - for i, v := range x { - x[i] = complex(alpha*real(v), alpha*imag(v)) - } - return - } - for ix := 0; ix < n*incX; ix += incX { - v := x[ix] - x[ix] = complex(alpha*real(v), alpha*imag(v)) - } -} - -// Cscal scales the vector x by a complex scalar alpha. -// Cscal has no effect if incX < 0. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cscal(n int, alpha complex64, x []complex64, incX int) { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if alpha == 0 { - if incX == 1 { - x = x[:n] - for i := range x { - x[i] = 0 - } - return - } - for ix := 0; ix < n*incX; ix += incX { - x[ix] = 0 - } - return - } - if incX == 1 { - c64.ScalUnitary(alpha, x[:n]) - return - } - c64.ScalInc(alpha, x, uintptr(n), uintptr(incX)) -} - -// Cswap exchanges the elements of two complex vectors x and y. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cswap(n int, x []complex64, incX int, y []complex64, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(shortY) - } - if incX == 1 && incY == 1 { - x = x[:n] - for i, v := range x { - x[i], y[i] = y[i], v - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - x[ix], y[iy] = y[iy], x[ix] - ix += incX - iy += incY - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32.go deleted file mode 100644 index a90b88ac..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32.go +++ /dev/null @@ -1,653 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2015 The Gonum 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 gonum - -import ( - math "gonum.org/v1/gonum/internal/math32" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f32" -) - -var _ blas.Float32Level1 = Implementation{} - -// Snrm2 computes the Euclidean norm of a vector, -// -// sqrt(\sum_i x[i] * x[i]). -// -// This function returns 0 if incX is negative. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Snrm2(n int, x []float32, incX int) float32 { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - if n < 2 { - if n == 1 { - return math.Abs(x[0]) - } - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 { - return f32.L2NormUnitary(x[:n]) - } - return f32.L2NormInc(x, uintptr(n), uintptr(incX)) -} - -// Sasum computes the sum of the absolute values of the elements of x. -// -// \sum_i |x[i]| -// -// Sasum returns 0 if incX is negative. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sasum(n int, x []float32, incX int) float32 { - var sum float32 - if n < 0 { - panic(nLT0) - } - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - if incX == 1 { - x = x[:n] - for _, v := range x { - sum += math.Abs(v) - } - return sum - } - for i := 0; i < n; i++ { - sum += math.Abs(x[i*incX]) - } - return sum -} - -// Isamax returns the index of an element of x with the largest absolute value. -// If there are multiple such indices the earliest is returned. -// Isamax returns -1 if n == 0. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Isamax(n int, x []float32, incX int) int { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return -1 - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - if n < 2 { - if n == 1 { - return 0 - } - if n == 0 { - return -1 // Netlib returns invalid index when n == 0. - } - panic(nLT0) - } - idx := 0 - max := math.Abs(x[0]) - if incX == 1 { - for i, v := range x[:n] { - absV := math.Abs(v) - if absV > max { - max = absV - idx = i - } - } - return idx - } - ix := incX - for i := 1; i < n; i++ { - v := x[ix] - absV := math.Abs(v) - if absV > max { - max = absV - idx = i - } - ix += incX - } - return idx -} - -// Sswap exchanges the elements of two vectors. -// -// x[i], y[i] = y[i], x[i] for all i -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sswap(n int, x []float32, incX int, y []float32, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if incX == 1 && incY == 1 { - x = x[:n] - for i, v := range x { - x[i], y[i] = y[i], v - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - x[ix], y[iy] = y[iy], x[ix] - ix += incX - iy += incY - } -} - -// Scopy copies the elements of x into the elements of y. -// -// y[i] = x[i] for all i -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Scopy(n int, x []float32, incX int, y []float32, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if incX == 1 && incY == 1 { - copy(y[:n], x[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - y[iy] = x[ix] - ix += incX - iy += incY - } -} - -// Saxpy adds alpha times x to y -// -// y[i] += alpha * x[i] for all i -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Saxpy(n int, alpha float32, x []float32, incX int, y []float32, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if alpha == 0 { - return - } - if incX == 1 && incY == 1 { - f32.AxpyUnitary(alpha, x[:n], y[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - f32.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Srotg computes a plane rotation -// -// ⎡ c s ⎤ ⎡ a ⎤ = ⎡ r ⎤ -// ⎣ -s c ⎦ ⎣ b ⎦ ⎣ 0 ⎦ -// -// satisfying c^2 + s^2 = 1. -// -// The computation uses the formulas -// -// sigma = sgn(a) if |a| > |b| -// = sgn(b) if |b| >= |a| -// r = sigma*sqrt(a^2 + b^2) -// c = 1; s = 0 if r = 0 -// c = a/r; s = b/r if r != 0 -// c >= 0 if |a| > |b| -// -// The subroutine also computes -// -// z = s if |a| > |b|, -// = 1/c if |b| >= |a| and c != 0 -// = 1 if c = 0 -// -// This allows c and s to be reconstructed from z as follows: -// -// If z = 1, set c = 0, s = 1. -// If |z| < 1, set c = sqrt(1 - z^2) and s = z. -// If |z| > 1, set c = 1/z and s = sqrt(1 - c^2). -// -// NOTE: There is a discrepancy between the reference implementation and the -// BLAS technical manual regarding the sign for r when a or b are zero. Drotg -// agrees with the definition in the manual and other common BLAS -// implementations. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Srotg(a, b float32) (c, s, r, z float32) { - // Implementation based on Supplemental Material to: - // Edward Anderson. 2017. Algorithm 978: Safe Scaling in the Level 1 BLAS. - // ACM Trans. Math. Softw. 44, 1, Article 12 (July 2017), 28 pages. - // DOI: https://doi.org/10.1145/3061665 - const ( - safmin = 0x1p-126 - safmax = 1 / safmin - ) - anorm := math.Abs(a) - bnorm := math.Abs(b) - switch { - case bnorm == 0: - c = 1 - s = 0 - r = a - z = 0 - case anorm == 0: - c = 0 - s = 1 - r = b - z = 1 - default: - maxab := math.Max(anorm, bnorm) - scl := math.Min(math.Max(safmin, maxab), safmax) - var sigma float32 - if anorm > bnorm { - sigma = math.Copysign(1, a) - } else { - sigma = math.Copysign(1, b) - } - ascl := a / scl - bscl := b / scl - r = sigma * (scl * math.Sqrt(ascl*ascl+bscl*bscl)) - c = a / r - s = b / r - switch { - case anorm > bnorm: - z = s - case c != 0: - z = 1 / c - default: - z = 1 - } - } - return c, s, r, z -} - -// Srotmg computes the modified Givens rotation. See -// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html -// for more details. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Srotmg(d1, d2, x1, y1 float32) (p blas.SrotmParams, rd1, rd2, rx1 float32) { - // The implementation of Drotmg used here is taken from Hopkins 1997 - // Appendix A: https://doi.org/10.1145/289251.289253 - // with the exception of the gam constants below. - - const ( - gam = 4096.0 - gamsq = gam * gam - rgamsq = 1.0 / gamsq - ) - - if d1 < 0 { - p.Flag = blas.Rescaling // Error state. - return p, 0, 0, 0 - } - - if d2 == 0 || y1 == 0 { - p.Flag = blas.Identity - return p, d1, d2, x1 - } - - var h11, h12, h21, h22 float32 - if (d1 == 0 || x1 == 0) && d2 > 0 { - p.Flag = blas.Diagonal - h12 = 1 - h21 = -1 - x1 = y1 - d1, d2 = d2, d1 - } else { - p2 := d2 * y1 - p1 := d1 * x1 - q2 := p2 * y1 - q1 := p1 * x1 - if math.Abs(q1) > math.Abs(q2) { - p.Flag = blas.OffDiagonal - h11 = 1 - h22 = 1 - h21 = -y1 / x1 - h12 = p2 / p1 - u := 1 - float32(h12*h21) - if u <= 0 { - p.Flag = blas.Rescaling // Error state. - return p, 0, 0, 0 - } - - d1 /= u - d2 /= u - x1 *= u - } else { - if q2 < 0 { - p.Flag = blas.Rescaling // Error state. - return p, 0, 0, 0 - } - - p.Flag = blas.Diagonal - h21 = -1 - h12 = 1 - h11 = p1 / p2 - h22 = x1 / y1 - u := 1 + float32(h11*h22) - d1, d2 = d2/u, d1/u - x1 = y1 * u - } - } - - for d1 <= rgamsq && d1 != 0 { - p.Flag = blas.Rescaling - d1 = (d1 * gam) * gam - x1 /= gam - h11 /= gam - h12 /= gam - } - for d1 > gamsq { - p.Flag = blas.Rescaling - d1 = (d1 / gam) / gam - x1 *= gam - h11 *= gam - h12 *= gam - } - - for math.Abs(d2) <= rgamsq && d2 != 0 { - p.Flag = blas.Rescaling - d2 = (d2 * gam) * gam - h21 /= gam - h22 /= gam - } - for math.Abs(d2) > gamsq { - p.Flag = blas.Rescaling - d2 = (d2 / gam) / gam - h21 *= gam - h22 *= gam - } - - switch p.Flag { - case blas.Diagonal: - p.H = [4]float32{0: h11, 3: h22} - case blas.OffDiagonal: - p.H = [4]float32{1: h21, 2: h12} - case blas.Rescaling: - p.H = [4]float32{h11, h21, h12, h22} - default: - panic(badFlag) - } - - return p, d1, d2, x1 -} - -// Srot applies a plane transformation. -// -// x[i] = c * x[i] + s * y[i] -// y[i] = c * y[i] - s * x[i] -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Srot(n int, x []float32, incX int, y []float32, incY int, c float32, s float32) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = c*vx+s*vy, c*vy-s*vx - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = c*vx+s*vy, c*vy-s*vx - ix += incX - iy += incY - } -} - -// Srotm applies the modified Givens rotation to the 2×n matrix. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Srotm(n int, x []float32, incX int, y []float32, incY int, p blas.SrotmParams) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - if p.Flag == blas.Identity { - return - } - - switch p.Flag { - case blas.Rescaling: - h11 := p.H[0] - h12 := p.H[2] - h21 := p.H[1] - h22 := p.H[3] - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = float32(vx*h11)+float32(vy*h12), float32(vx*h21)+float32(vy*h22) - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = float32(vx*h11)+float32(vy*h12), float32(vx*h21)+float32(vy*h22) - ix += incX - iy += incY - } - case blas.OffDiagonal: - h12 := p.H[2] - h21 := p.H[1] - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = vx+float32(vy*h12), float32(vx*h21)+vy - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = vx+float32(vy*h12), float32(vx*h21)+vy - ix += incX - iy += incY - } - case blas.Diagonal: - h11 := p.H[0] - h22 := p.H[3] - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = float32(vx*h11)+vy, -vx+float32(vy*h22) - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = float32(vx*h11)+vy, -vx+float32(vy*h22) - ix += incX - iy += incY - } - } -} - -// Sscal scales x by alpha. -// -// x[i] *= alpha -// -// Sscal has no effect if incX < 0. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sscal(n int, alpha float32, x []float32, incX int) { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - if alpha == 0 { - if incX == 1 { - x = x[:n] - for i := range x { - x[i] = 0 - } - return - } - for ix := 0; ix < n*incX; ix += incX { - x[ix] = 0 - } - return - } - if incX == 1 { - f32.ScalUnitary(alpha, x[:n]) - return - } - f32.ScalInc(alpha, x, uintptr(n), uintptr(incX)) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_dsdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_dsdot.go deleted file mode 100644 index cd7df411..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_dsdot.go +++ /dev/null @@ -1,54 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/internal/asm/f32" -) - -// Dsdot computes the dot product of the two vectors -// -// \sum_i x[i]*y[i] -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Dsdot(n int, x []float32, incX int, y []float32, incY int) float64 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return f32.DdotUnitary(x[:n], y[:n]) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(shortY) - } - return f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdot.go deleted file mode 100644 index c4cc1663..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdot.go +++ /dev/null @@ -1,54 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/internal/asm/f32" -) - -// Sdot computes the dot product of the two vectors -// -// \sum_i x[i]*y[i] -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sdot(n int, x []float32, incX int, y []float32, incY int) float32 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return f32.DotUnitary(x[:n], y[:n]) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(shortY) - } - return f32.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdsdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdsdot.go deleted file mode 100644 index eb6b73bd..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdsdot.go +++ /dev/null @@ -1,54 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/internal/asm/f32" -) - -// Sdsdot computes the dot product of the two vectors plus a constant -// -// alpha + \sum_i x[i]*y[i] -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sdsdot(n int, alpha float32, x []float32, incX int, y []float32, incY int) float32 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return alpha + float32(f32.DdotUnitary(x[:n], y[:n])) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(shortY) - } - return alpha + float32(f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1float64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float64.go deleted file mode 100644 index 795769d9..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1float64.go +++ /dev/null @@ -1,629 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f64" -) - -var _ blas.Float64Level1 = Implementation{} - -// Dnrm2 computes the Euclidean norm of a vector, -// -// sqrt(\sum_i x[i] * x[i]). -// -// This function returns 0 if incX is negative. -func (Implementation) Dnrm2(n int, x []float64, incX int) float64 { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - if n < 2 { - if n == 1 { - return math.Abs(x[0]) - } - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 { - return f64.L2NormUnitary(x[:n]) - } - return f64.L2NormInc(x, uintptr(n), uintptr(incX)) -} - -// Dasum computes the sum of the absolute values of the elements of x. -// -// \sum_i |x[i]| -// -// Dasum returns 0 if incX is negative. -func (Implementation) Dasum(n int, x []float64, incX int) float64 { - var sum float64 - if n < 0 { - panic(nLT0) - } - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return 0 - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - if incX == 1 { - x = x[:n] - for _, v := range x { - sum += math.Abs(v) - } - return sum - } - for i := 0; i < n; i++ { - sum += math.Abs(x[i*incX]) - } - return sum -} - -// Idamax returns the index of an element of x with the largest absolute value. -// If there are multiple such indices the earliest is returned. -// Idamax returns -1 if n == 0. -func (Implementation) Idamax(n int, x []float64, incX int) int { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return -1 - } - if len(x) <= (n-1)*incX { - panic(shortX) - } - if n < 2 { - if n == 1 { - return 0 - } - if n == 0 { - return -1 // Netlib returns invalid index when n == 0. - } - panic(nLT0) - } - idx := 0 - max := math.Abs(x[0]) - if incX == 1 { - for i, v := range x[:n] { - absV := math.Abs(v) - if absV > max { - max = absV - idx = i - } - } - return idx - } - ix := incX - for i := 1; i < n; i++ { - v := x[ix] - absV := math.Abs(v) - if absV > max { - max = absV - idx = i - } - ix += incX - } - return idx -} - -// Dswap exchanges the elements of two vectors. -// -// x[i], y[i] = y[i], x[i] for all i -func (Implementation) Dswap(n int, x []float64, incX int, y []float64, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if incX == 1 && incY == 1 { - x = x[:n] - for i, v := range x { - x[i], y[i] = y[i], v - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - x[ix], y[iy] = y[iy], x[ix] - ix += incX - iy += incY - } -} - -// Dcopy copies the elements of x into the elements of y. -// -// y[i] = x[i] for all i -func (Implementation) Dcopy(n int, x []float64, incX int, y []float64, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if incX == 1 && incY == 1 { - copy(y[:n], x[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - y[iy] = x[ix] - ix += incX - iy += incY - } -} - -// Daxpy adds alpha times x to y -// -// y[i] += alpha * x[i] for all i -func (Implementation) Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if alpha == 0 { - return - } - if incX == 1 && incY == 1 { - f64.AxpyUnitary(alpha, x[:n], y[:n]) - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - f64.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} - -// Drotg computes a plane rotation -// -// ⎡ c s ⎤ ⎡ a ⎤ = ⎡ r ⎤ -// ⎣ -s c ⎦ ⎣ b ⎦ ⎣ 0 ⎦ -// -// satisfying c^2 + s^2 = 1. -// -// The computation uses the formulas -// -// sigma = sgn(a) if |a| > |b| -// = sgn(b) if |b| >= |a| -// r = sigma*sqrt(a^2 + b^2) -// c = 1; s = 0 if r = 0 -// c = a/r; s = b/r if r != 0 -// c >= 0 if |a| > |b| -// -// The subroutine also computes -// -// z = s if |a| > |b|, -// = 1/c if |b| >= |a| and c != 0 -// = 1 if c = 0 -// -// This allows c and s to be reconstructed from z as follows: -// -// If z = 1, set c = 0, s = 1. -// If |z| < 1, set c = sqrt(1 - z^2) and s = z. -// If |z| > 1, set c = 1/z and s = sqrt(1 - c^2). -// -// NOTE: There is a discrepancy between the reference implementation and the -// BLAS technical manual regarding the sign for r when a or b are zero. Drotg -// agrees with the definition in the manual and other common BLAS -// implementations. -func (Implementation) Drotg(a, b float64) (c, s, r, z float64) { - // Implementation based on Supplemental Material to: - // Edward Anderson. 2017. Algorithm 978: Safe Scaling in the Level 1 BLAS. - // ACM Trans. Math. Softw. 44, 1, Article 12 (July 2017), 28 pages. - // DOI: https://doi.org/10.1145/3061665 - const ( - safmin = 0x1p-1022 - safmax = 1 / safmin - ) - anorm := math.Abs(a) - bnorm := math.Abs(b) - switch { - case bnorm == 0: - c = 1 - s = 0 - r = a - z = 0 - case anorm == 0: - c = 0 - s = 1 - r = b - z = 1 - default: - maxab := math.Max(anorm, bnorm) - scl := math.Min(math.Max(safmin, maxab), safmax) - var sigma float64 - if anorm > bnorm { - sigma = math.Copysign(1, a) - } else { - sigma = math.Copysign(1, b) - } - ascl := a / scl - bscl := b / scl - r = sigma * (scl * math.Sqrt(ascl*ascl+bscl*bscl)) - c = a / r - s = b / r - switch { - case anorm > bnorm: - z = s - case c != 0: - z = 1 / c - default: - z = 1 - } - } - return c, s, r, z -} - -// Drotmg computes the modified Givens rotation. See -// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html -// for more details. -func (Implementation) Drotmg(d1, d2, x1, y1 float64) (p blas.DrotmParams, rd1, rd2, rx1 float64) { - // The implementation of Drotmg used here is taken from Hopkins 1997 - // Appendix A: https://doi.org/10.1145/289251.289253 - // with the exception of the gam constants below. - - const ( - gam = 4096.0 - gamsq = gam * gam - rgamsq = 1.0 / gamsq - ) - - if d1 < 0 { - p.Flag = blas.Rescaling // Error state. - return p, 0, 0, 0 - } - - if d2 == 0 || y1 == 0 { - p.Flag = blas.Identity - return p, d1, d2, x1 - } - - var h11, h12, h21, h22 float64 - if (d1 == 0 || x1 == 0) && d2 > 0 { - p.Flag = blas.Diagonal - h12 = 1 - h21 = -1 - x1 = y1 - d1, d2 = d2, d1 - } else { - p2 := d2 * y1 - p1 := d1 * x1 - q2 := p2 * y1 - q1 := p1 * x1 - if math.Abs(q1) > math.Abs(q2) { - p.Flag = blas.OffDiagonal - h11 = 1 - h22 = 1 - h21 = -y1 / x1 - h12 = p2 / p1 - u := 1 - float64(h12*h21) - if u <= 0 { - p.Flag = blas.Rescaling // Error state. - return p, 0, 0, 0 - } - - d1 /= u - d2 /= u - x1 *= u - } else { - if q2 < 0 { - p.Flag = blas.Rescaling // Error state. - return p, 0, 0, 0 - } - - p.Flag = blas.Diagonal - h21 = -1 - h12 = 1 - h11 = p1 / p2 - h22 = x1 / y1 - u := 1 + float64(h11*h22) - d1, d2 = d2/u, d1/u - x1 = y1 * u - } - } - - for d1 <= rgamsq && d1 != 0 { - p.Flag = blas.Rescaling - d1 = (d1 * gam) * gam - x1 /= gam - h11 /= gam - h12 /= gam - } - for d1 > gamsq { - p.Flag = blas.Rescaling - d1 = (d1 / gam) / gam - x1 *= gam - h11 *= gam - h12 *= gam - } - - for math.Abs(d2) <= rgamsq && d2 != 0 { - p.Flag = blas.Rescaling - d2 = (d2 * gam) * gam - h21 /= gam - h22 /= gam - } - for math.Abs(d2) > gamsq { - p.Flag = blas.Rescaling - d2 = (d2 / gam) / gam - h21 *= gam - h22 *= gam - } - - switch p.Flag { - case blas.Diagonal: - p.H = [4]float64{0: h11, 3: h22} - case blas.OffDiagonal: - p.H = [4]float64{1: h21, 2: h12} - case blas.Rescaling: - p.H = [4]float64{h11, h21, h12, h22} - default: - panic(badFlag) - } - - return p, d1, d2, x1 -} - -// Drot applies a plane transformation. -// -// x[i] = c * x[i] + s * y[i] -// y[i] = c * y[i] - s * x[i] -func (Implementation) Drot(n int, x []float64, incX int, y []float64, incY int, c float64, s float64) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = c*vx+s*vy, c*vy-s*vx - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = c*vx+s*vy, c*vy-s*vx - ix += incX - iy += incY - } -} - -// Drotm applies the modified Givens rotation to the 2×n matrix. -func (Implementation) Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return - } - panic(nLT0) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - if p.Flag == blas.Identity { - return - } - - switch p.Flag { - case blas.Rescaling: - h11 := p.H[0] - h12 := p.H[2] - h21 := p.H[1] - h22 := p.H[3] - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = float64(vx*h11)+float64(vy*h12), float64(vx*h21)+float64(vy*h22) - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = float64(vx*h11)+float64(vy*h12), float64(vx*h21)+float64(vy*h22) - ix += incX - iy += incY - } - case blas.OffDiagonal: - h12 := p.H[2] - h21 := p.H[1] - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = vx+float64(vy*h12), float64(vx*h21)+vy - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = vx+float64(vy*h12), float64(vx*h21)+vy - ix += incX - iy += incY - } - case blas.Diagonal: - h11 := p.H[0] - h22 := p.H[3] - if incX == 1 && incY == 1 { - x = x[:n] - for i, vx := range x { - vy := y[i] - x[i], y[i] = float64(vx*h11)+vy, -vx+float64(vy*h22) - } - return - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - for i := 0; i < n; i++ { - vx := x[ix] - vy := y[iy] - x[ix], y[iy] = float64(vx*h11)+vy, -vx+float64(vy*h22) - ix += incX - iy += incY - } - } -} - -// Dscal scales x by alpha. -// -// x[i] *= alpha -// -// Dscal has no effect if incX < 0. -func (Implementation) Dscal(n int, alpha float64, x []float64, incX int) { - if incX < 1 { - if incX == 0 { - panic(zeroIncX) - } - return - } - if n < 1 { - if n == 0 { - return - } - panic(nLT0) - } - if (n-1)*incX >= len(x) { - panic(shortX) - } - if alpha == 0 { - if incX == 1 { - x = x[:n] - for i := range x { - x[i] = 0 - } - return - } - for ix := 0; ix < n*incX; ix += incX { - x[ix] = 0 - } - return - } - if incX == 1 { - f64.ScalUnitary(alpha, x[:n]) - return - } - f64.ScalInc(alpha, x, uintptr(n), uintptr(incX)) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1float64_ddot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float64_ddot.go deleted file mode 100644 index 1569656e..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1float64_ddot.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/internal/asm/f64" -) - -// Ddot computes the dot product of the two vectors -// -// \sum_i x[i]*y[i] -func (Implementation) Ddot(n int, x []float64, incX int, y []float64, incY int) float64 { - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - if n <= 0 { - if n == 0 { - return 0 - } - panic(nLT0) - } - if incX == 1 && incY == 1 { - if len(x) < n { - panic(shortX) - } - if len(y) < n { - panic(shortY) - } - return f64.DotUnitary(x[:n], y[:n]) - } - var ix, iy int - if incX < 0 { - ix = (-n + 1) * incX - } - if incY < 0 { - iy = (-n + 1) * incY - } - if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(shortX) - } - if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(shortY) - } - return f64.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go deleted file mode 100644 index fa076d5f..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go +++ /dev/null @@ -1,2940 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math/cmplx" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/c128" -) - -var _ blas.Complex128Level2 = Implementation{} - -// Zgbmv performs one of the matrix-vector operations -// -// y = alpha * A * x + beta * y if trans = blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if trans = blas.Trans -// y = alpha * Aᴴ * x + beta * y if trans = blas.ConjTrans -// -// where alpha and beta are scalars, x and y are vectors, and A is an m×n band matrix -// with kL sub-diagonals and kU super-diagonals. -func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if kL < 0 { - panic(kLLT0) - } - if kU < 0 { - panic(kULT0) - } - if lda < kL+kU+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { - panic(shortA) - } - var lenX, lenY int - if trans == blas.NoTrans { - lenX, lenY = n, m - } else { - lenX, lenY = m, n - } - if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - var kx int - if incX < 0 { - kx = (1 - lenX) * incX - } - var ky int - if incY < 0 { - ky = (1 - lenY) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:lenY] { - y[i] = 0 - } - } else { - c128.ScalUnitary(beta, y[:lenY]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < lenY; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - c128.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) - } else { - c128.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) - } - } - } - } - - nRow := min(m, n+kL) - nCol := kL + 1 + kU - switch trans { - case blas.NoTrans: - iy := ky - if incX == 1 { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) - xtmp := x[off : off+u-l] - var sum complex128 - for j, v := range aRow { - sum += xtmp[j] * v - } - y[iy] += alpha * sum - iy += incY - } - } else { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incX - jx := kx - var sum complex128 - for _, v := range aRow { - sum += x[off+jx] * v - jx += incX - } - y[iy] += alpha * sum - iy += incY - } - } - case blas.Trans: - if incX == 1 { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[i] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * v - jy += incY - } - } - } else { - ix := kx - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[ix] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * v - jy += incY - } - ix += incX - } - } - case blas.ConjTrans: - if incX == 1 { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[i] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - } - } else { - ix := kx - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[ix] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - ix += incX - } - } - } -} - -// Zgemv performs one of the matrix-vector operations -// -// y = alpha * A * x + beta * y if trans = blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if trans = blas.Trans -// y = alpha * Aᴴ * x + beta * y if trans = blas.ConjTrans -// -// where alpha and beta are scalars, x and y are vectors, and A is an m×n dense matrix. -func (Implementation) Zgemv(trans blas.Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - var lenX, lenY int - if trans == blas.NoTrans { - lenX = n - lenY = m - } else { - lenX = m - lenY = n - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - var kx int - if incX < 0 { - kx = (1 - lenX) * incX - } - var ky int - if incY < 0 { - ky = (1 - lenY) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:lenY] { - y[i] = 0 - } - } else { - c128.ScalUnitary(beta, y[:lenY]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < lenY; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - c128.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) - } else { - c128.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - switch trans { - default: - // Form y = alpha*A*x + y. - iy := ky - if incX == 1 { - for i := 0; i < m; i++ { - y[iy] += alpha * c128.DotuUnitary(a[i*lda:i*lda+n], x[:n]) - iy += incY - } - return - } - for i := 0; i < m; i++ { - y[iy] += alpha * c128.DotuInc(a[i*lda:i*lda+n], x, uintptr(n), 1, uintptr(incX), 0, uintptr(kx)) - iy += incY - } - return - - case blas.Trans: - // Form y = alpha*Aᵀ*x + y. - ix := kx - if incY == 1 { - for i := 0; i < m; i++ { - c128.AxpyUnitary(alpha*x[ix], a[i*lda:i*lda+n], y[:n]) - ix += incX - } - return - } - for i := 0; i < m; i++ { - c128.AxpyInc(alpha*x[ix], a[i*lda:i*lda+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) - ix += incX - } - return - - case blas.ConjTrans: - // Form y = alpha*Aᴴ*x + y. - ix := kx - if incY == 1 { - for i := 0; i < m; i++ { - tmp := alpha * x[ix] - for j := 0; j < n; j++ { - y[j] += tmp * cmplx.Conj(a[i*lda+j]) - } - ix += incX - } - return - } - for i := 0; i < m; i++ { - tmp := alpha * x[ix] - jy := ky - for j := 0; j < n; j++ { - y[jy] += tmp * cmplx.Conj(a[i*lda+j]) - jy += incY - } - ix += incX - } - return - } -} - -// Zgerc performs the rank-one operation -// -// A += alpha * x * yᴴ -// -// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, -// and y is an n element vector. -func (Implementation) Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx, jy int - if incX < 0 { - kx = (1 - m) * incX - } - if incY < 0 { - jy = (1 - n) * incY - } - for j := 0; j < n; j++ { - if y[jy] != 0 { - tmp := alpha * cmplx.Conj(y[jy]) - c128.AxpyInc(tmp, x, a[j:], uintptr(m), uintptr(incX), uintptr(lda), uintptr(kx), 0) - } - jy += incY - } -} - -// Zgeru performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, -// and y is an n element vector. -func (Implementation) Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx int - if incX < 0 { - kx = (1 - m) * incX - } - if incY == 1 { - for i := 0; i < m; i++ { - if x[kx] != 0 { - tmp := alpha * x[kx] - c128.AxpyUnitary(tmp, y[:n], a[i*lda:i*lda+n]) - } - kx += incX - } - return - } - var jy int - if incY < 0 { - jy = (1 - n) * incY - } - for i := 0; i < m; i++ { - if x[kx] != 0 { - tmp := alpha * x[kx] - c128.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(jy), 0) - } - kx += incX - } -} - -// Zhbmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where alpha and beta are scalars, x and y are vectors, and A is an n×n -// Hermitian band matrix with k super-diagonals. The imaginary parts of -// the diagonal elements of A are ignored and assumed to be zero. -func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up the start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - for i, v := range y[:n] { - y[i] = beta * v - } - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - for i := 0; i < n; i++ { - y[iy] = beta * y[iy] - iy += incY - } - } - } - } - - if alpha == 0 { - return - } - - // The elements of A are accessed sequentially with one pass through a. - switch uplo { - case blas.Upper: - iy := ky - if incX == 1 { - for i := 0; i < n; i++ { - aRow := a[i*lda:] - alphaxi := alpha * x[i] - sum := alphaxi * complex(real(aRow[0]), 0) - u := min(k+1, n-i) - jy := incY - for j := 1; j < u; j++ { - v := aRow[j] - sum += alpha * x[i+j] * v - y[iy+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - y[iy] += sum - iy += incY - } - } else { - ix := kx - for i := 0; i < n; i++ { - aRow := a[i*lda:] - alphaxi := alpha * x[ix] - sum := alphaxi * complex(real(aRow[0]), 0) - u := min(k+1, n-i) - jx := incX - jy := incY - for j := 1; j < u; j++ { - v := aRow[j] - sum += alpha * x[ix+jx] * v - y[iy+jy] += alphaxi * cmplx.Conj(v) - jx += incX - jy += incY - } - y[iy] += sum - ix += incX - iy += incY - } - } - case blas.Lower: - iy := ky - if incX == 1 { - for i := 0; i < n; i++ { - l := max(0, k-i) - alphaxi := alpha * x[i] - jy := l * incY - aRow := a[i*lda:] - for j := l; j < k; j++ { - v := aRow[j] - y[iy] += alpha * v * x[i-k+j] - y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - y[iy] += alphaxi * complex(real(aRow[k]), 0) - iy += incY - } - } else { - ix := kx - for i := 0; i < n; i++ { - l := max(0, k-i) - alphaxi := alpha * x[ix] - jx := l * incX - jy := l * incY - aRow := a[i*lda:] - for j := l; j < k; j++ { - v := aRow[j] - y[iy] += alpha * v * x[ix-k*incX+jx] - y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) - jx += incX - jy += incY - } - y[iy] += alphaxi * complex(real(aRow[k]), 0) - ix += incX - iy += incY - } - } - } -} - -// Zhemv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where alpha and beta are scalars, x and y are vectors, and A is an n×n -// Hermitian matrix. The imaginary parts of the diagonal elements of A are -// ignored and assumed to be zero. -func (Implementation) Zhemv(uplo blas.Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up the start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - for i, v := range y[:n] { - y[i] = beta * v - } - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - for i := 0; i < n; i++ { - y[iy] = beta * y[iy] - iy += incY - } - } - } - } - - if alpha == 0 { - return - } - - // The elements of A are accessed sequentially with one pass through - // the triangular part of A. - - if uplo == blas.Upper { - // Form y when A is stored in upper triangle. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - var tmp2 complex128 - for j := i + 1; j < n; j++ { - y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[j] - } - aii := complex(real(a[i*lda+i]), 0) - y[i] += tmp1*aii + alpha*tmp2 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - var tmp2 complex128 - jx := ix - jy := iy - for j := i + 1; j < n; j++ { - jx += incX - jy += incY - y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[jx] - } - aii := complex(real(a[i*lda+i]), 0) - y[iy] += tmp1*aii + alpha*tmp2 - ix += incX - iy += incY - } - } - return - } - - // Form y when A is stored in lower triangle. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - var tmp2 complex128 - for j := 0; j < i; j++ { - y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[j] - } - aii := complex(real(a[i*lda+i]), 0) - y[i] += tmp1*aii + alpha*tmp2 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - var tmp2 complex128 - jx := kx - jy := ky - for j := 0; j < i; j++ { - y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[jx] - jx += incX - jy += incY - } - aii := complex(real(a[i*lda+i]), 0) - y[iy] += tmp1*aii + alpha*tmp2 - ix += incX - iy += incY - } - } -} - -// Zher performs the Hermitian rank-one operation -// -// A += alpha * x * xᴴ -// -// where A is an n×n Hermitian matrix, alpha is a real scalar, and x is an n -// element vector. On entry, the imaginary parts of the diagonal elements of A -// are ignored and assumed to be zero, on return they will be set to zero. -func (Implementation) Zher(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 { - tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii+xtmp, 0) - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[j]) - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - - ix := kx - for i := 0; i < n; i++ { - if x[ix] != 0 { - tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii+xtmp, 0) - jx := ix + incX - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - } - return - } - - if incX == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 { - tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) - for j := 0; j < i; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[j]) - } - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii+xtmp, 0) - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - - ix := kx - for i := 0; i < n; i++ { - if x[ix] != 0 { - tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) - jx := kx - for j := 0; j < i; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii+xtmp, 0) - - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - } -} - -// Zher2 performs the Hermitian rank-two operation -// -// A += alpha * x * yᴴ + conj(alpha) * y * xᴴ -// -// where alpha is a scalar, x and y are n element vectors and A is an n×n -// Hermitian matrix. On entry, the imaginary parts of the diagonal elements are -// ignored and assumed to be zero. On return they will be set to zero. -func (Implementation) Zher2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx, ky int - var ix, iy int - if incX != 1 || incY != 1 { - if incX < 0 { - kx = (1 - n) * incX - } - if incY < 0 { - ky = (1 - n) * incY - } - ix = kx - iy = ky - } - if uplo == blas.Upper { - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii, 0) - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii, 0) - jx := ix + incX - jy := iy + incY - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - iy += incY - } - return - } - - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - for j := 0; j < i; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - } - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii, 0) - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - jx := kx - jy := ky - for j := 0; j < i; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii, 0) - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - iy += incY - } -} - -// Zhpmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where alpha and beta are scalars, x and y are vectors, and A is an n×n -// Hermitian matrix in packed form. The imaginary parts of the diagonal -// elements of A are ignored and assumed to be zero. -func (Implementation) Zhpmv(uplo blas.Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up the start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - for i, v := range y[:n] { - y[i] = beta * v - } - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - for i := 0; i < n; i++ { - y[iy] *= beta - iy += incY - } - } - } - } - - if alpha == 0 { - return - } - - // The elements of A are accessed sequentially with one pass through ap. - - var kk int - if uplo == blas.Upper { - // Form y when ap contains the upper triangle. - // Here, kk points to the current diagonal element in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - y[i] += tmp1 * complex(real(ap[kk]), 0) - var tmp2 complex128 - k := kk + 1 - for j := i + 1; j < n; j++ { - y[j] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[j] - k++ - } - y[i] += alpha * tmp2 - kk += n - i - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - y[iy] += tmp1 * complex(real(ap[kk]), 0) - var tmp2 complex128 - jx := ix - jy := iy - for k := kk + 1; k < kk+n-i; k++ { - jx += incX - jy += incY - y[jy] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[jx] - } - y[iy] += alpha * tmp2 - ix += incX - iy += incY - kk += n - i - } - } - return - } - - // Form y when ap contains the lower triangle. - // Here, kk points to the beginning of current row in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - var tmp2 complex128 - k := kk - for j := 0; j < i; j++ { - y[j] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[j] - k++ - } - aii := complex(real(ap[kk+i]), 0) - y[i] += tmp1*aii + alpha*tmp2 - kk += i + 1 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - var tmp2 complex128 - jx := kx - jy := ky - for k := kk; k < kk+i; k++ { - y[jy] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[jx] - jx += incX - jy += incY - } - aii := complex(real(ap[kk+i]), 0) - y[iy] += tmp1*aii + alpha*tmp2 - ix += incX - iy += incY - kk += i + 1 - } - } -} - -// Zhpr performs the Hermitian rank-1 operation -// -// A += alpha * x * xᴴ -// -// where alpha is a real scalar, x is a vector, and A is an n×n hermitian matrix -// in packed form. On entry, the imaginary parts of the diagonal elements are -// assumed to be zero, and on return they are set to zero. -func (Implementation) Zhpr(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, ap []complex128) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through ap. - - var kk int - if uplo == blas.Upper { - // Form A when upper triangle is stored in AP. - // Here, kk points to the current diagonal element in ap. - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if xi != 0 { - aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk] = complex(aii, 0) - - tmp := complex(alpha, 0) * xi - a := ap[kk+1 : kk+n-i] - x := x[i+1 : n] - for j, v := range x { - a[j] += tmp * cmplx.Conj(v) - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - kk += n - i - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - if xi != 0 { - aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk] = complex(aii, 0) - - tmp := complex(alpha, 0) * xi - jx := ix + incX - a := ap[kk+1 : kk+n-i] - for k := range a { - a[k] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - ix += incX - kk += n - i - } - } - return - } - - // Form A when lower triangle is stored in AP. - // Here, kk points to the beginning of current row in ap. - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if xi != 0 { - tmp := complex(alpha, 0) * xi - a := ap[kk : kk+i] - for j, v := range x[:i] { - a[j] += tmp * cmplx.Conj(v) - } - - aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - if xi != 0 { - tmp := complex(alpha, 0) * xi - a := ap[kk : kk+i] - jx := kx - for k := range a { - a[k] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - - aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - ix += incX - kk += i + 1 - } - } -} - -// Zhpr2 performs the Hermitian rank-2 operation -// -// A += alpha * x * yᴴ + conj(alpha) * y * xᴴ -// -// where alpha is a complex scalar, x and y are n element vectors, and A is an -// n×n Hermitian matrix, supplied in packed form. On entry, the imaginary parts -// of the diagonal elements are assumed to be zero, and on return they are set to zero. -func (Implementation) Zhpr2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - // Set up start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // The elements of A are accessed sequentially with one pass through ap. - - var kk int - if uplo == blas.Upper { - // Form A when upper triangle is stored in AP. - // Here, kk points to the current diagonal element in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - ap[kk] = complex(aii, 0) - k := kk + 1 - for j := i + 1; j < n; j++ { - ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - k++ - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - kk += n - i - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - ap[kk] = complex(aii, 0) - jx := ix + incX - jy := iy + incY - for k := kk + 1; k < kk+n-i; k++ { - ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - ix += incX - iy += incY - kk += n - i - } - } - return - } - - // Form A when lower triangle is stored in AP. - // Here, kk points to the beginning of current row in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - k := kk - for j := 0; j < i; j++ { - ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - k++ - } - aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - kk += i + 1 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - jx := kx - jy := ky - for k := kk; k < kk+i; k++ { - ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - ix += incX - iy += incY - kk += i + 1 - } - } -} - -// Ztbmv performs one of the matrix-vector operations -// -// x = A * x if trans = blas.NoTrans -// x = Aᵀ * x if trans = blas.Trans -// x = Aᴴ * x if trans = blas.ConjTrans -// -// where x is an n element vector and A is an n×n triangular band matrix, with -// (k+1) diagonals. -func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - switch trans { - case blas.NoTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if diag == blas.NonUnit { - xi *= a[i*lda] - } - kk := min(k, n-i-1) - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - xi += x[i+j+1] * aij - } - x[i] = xi - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - if diag == blas.NonUnit { - xi *= a[i*lda] - } - kk := min(k, n-i-1) - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - xi += x[jx] * aij - jx += incX - } - x[ix] = xi - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - xi *= a[i*lda+k] - } - kk := min(k, i) - for j, aij := range a[i*lda+k-kk : i*lda+k] { - xi += x[i-kk+j] * aij - } - x[i] = xi - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - xi *= a[i*lda+k] - } - kk := min(k, i) - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - xi += x[jx] * aij - jx += incX - } - x[ix] = xi - ix -= incX - } - } - } - case blas.Trans: - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+j+1] += xi * aij - } - if diag == blas.NonUnit { - x[i] *= a[i*lda] - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - jx := ix + incX - xi := x[ix] - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] += xi * aij - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= a[i*lda] - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] += xi * aij - } - if diag == blas.NonUnit { - x[i] *= a[i*lda+k] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - kk := min(k, i) - jx := ix - kk*incX - xi := x[ix] - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] += xi * aij - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= a[i*lda+k] - } - ix += incX - } - } - } - case blas.ConjTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+j+1] += xi * cmplx.Conj(aij) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - jx := ix + incX - xi := x[ix] - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] += xi * cmplx.Conj(aij) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda]) - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] += xi * cmplx.Conj(aij) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda+k]) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - kk := min(k, i) - jx := ix - kk*incX - xi := x[ix] - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] += xi * cmplx.Conj(aij) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda+k]) - } - ix += incX - } - } - } - } -} - -// Ztbsv solves one of the systems of equations -// -// A * x = b if trans == blas.NoTrans -// Aᵀ * x = b if trans == blas.Trans -// Aᴴ * x = b if trans == blas.ConjTrans -// -// where b and x are n element vectors and A is an n×n triangular band matrix -// with (k+1) diagonals. -// -// On entry, x contains the values of b, and the solution is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - switch trans { - case blas.NoTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - var sum complex128 - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - sum += x[i+1+j] * aij - } - x[i] -= sum - if diag == blas.NonUnit { - x[i] /= a[i*lda] - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - var sum complex128 - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - sum += x[jx] * aij - jx += incX - } - x[ix] -= sum - if diag == blas.NonUnit { - x[ix] /= a[i*lda] - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - kk := min(k, i) - var sum complex128 - for j, aij := range a[i*lda+k-kk : i*lda+k] { - sum += x[i-kk+j] * aij - } - x[i] -= sum - if diag == blas.NonUnit { - x[i] /= a[i*lda+k] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - kk := min(k, i) - var sum complex128 - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - sum += x[jx] * aij - jx += incX - } - x[ix] -= sum - if diag == blas.NonUnit { - x[ix] /= a[i*lda+k] - } - ix += incX - } - } - } - case blas.Trans: - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[i] /= a[i*lda] - } - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+1+j] -= xi * aij - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] /= a[i*lda] - } - kk := min(k, n-i-1) - xi := x[ix] - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] -= xi * aij - jx += incX - } - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] /= a[i*lda+k] - } - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] -= xi * aij - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] /= a[i*lda+k] - } - kk := min(k, i) - xi := x[ix] - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] -= xi * aij - jx += incX - } - ix -= incX - } - } - } - case blas.ConjTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[i] /= cmplx.Conj(a[i*lda]) - } - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+1+j] -= xi * cmplx.Conj(aij) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] /= cmplx.Conj(a[i*lda]) - } - kk := min(k, n-i-1) - xi := x[ix] - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] -= xi * cmplx.Conj(aij) - jx += incX - } - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] /= cmplx.Conj(a[i*lda+k]) - } - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] -= xi * cmplx.Conj(aij) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] /= cmplx.Conj(a[i*lda+k]) - } - kk := min(k, i) - xi := x[ix] - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] -= xi * cmplx.Conj(aij) - jx += incX - } - ix -= incX - } - } - } - } -} - -// Ztpmv performs one of the matrix-vector operations -// -// x = A * x if trans = blas.NoTrans -// x = Aᵀ * x if trans = blas.Trans -// x = Aᴴ * x if trans = blas.ConjTrans -// -// where x is an n element vector and A is an n×n triangular matrix, supplied in -// packed form. -func (Implementation) Ztpmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex128, x []complex128, incX int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through A. - - if trans == blas.NoTrans { - // Form x = A*x. - if uplo == blas.Upper { - // kk points to the current diagonal element in ap. - kk := 0 - if incX == 1 { - x = x[:n] - for i := range x { - if diag == blas.NonUnit { - x[i] *= ap[kk] - } - if n-i-1 > 0 { - x[i] += c128.DotuUnitary(ap[kk+1:kk+n-i], x[i+1:]) - } - kk += n - i - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] *= ap[kk] - } - if n-i-1 > 0 { - x[ix] += c128.DotuInc(ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix += incX - kk += n - i - } - } - } else { - // kk points to the beginning of current row in ap. - kk := n*(n+1)/2 - n - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] *= ap[kk+i] - } - if i > 0 { - x[i] += c128.DotuUnitary(ap[kk:kk+i], x[:i]) - } - kk -= i - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] *= ap[kk+i] - } - if i > 0 { - x[ix] += c128.DotuInc(ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - ix -= incX - kk -= i - } - } - } - return - } - - if trans == blas.Trans { - // Form x = Aᵀ*x. - if uplo == blas.Upper { - // kk points to the current diagonal element in ap. - kk := n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= ap[kk] - } - if n-i-1 > 0 { - c128.AxpyUnitary(xi, ap[kk+1:kk+n-i], x[i+1:n]) - } - kk -= n - i + 1 - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= ap[kk] - } - if n-i-1 > 0 { - c128.AxpyInc(xi, ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix -= incX - kk -= n - i + 1 - } - } - } else { - // kk points to the beginning of current row in ap. - kk := 0 - if incX == 1 { - x = x[:n] - for i := range x { - if i > 0 { - c128.AxpyUnitary(x[i], ap[kk:kk+i], x[:i]) - } - if diag == blas.NonUnit { - x[i] *= ap[kk+i] - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - c128.AxpyInc(x[ix], ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - if diag == blas.NonUnit { - x[ix] *= ap[kk+i] - } - ix += incX - kk += i + 1 - } - } - } - return - } - - // Form x = Aᴴ*x. - if uplo == blas.Upper { - // kk points to the current diagonal element in ap. - kk := n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(ap[kk]) - } - k := kk + 1 - for j := i + 1; j < n; j++ { - x[j] += xi * cmplx.Conj(ap[k]) - k++ - } - kk -= n - i + 1 - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(ap[kk]) - } - jx := ix + incX - k := kk + 1 - for j := i + 1; j < n; j++ { - x[jx] += xi * cmplx.Conj(ap[k]) - jx += incX - k++ - } - ix -= incX - kk -= n - i + 1 - } - } - } else { - // kk points to the beginning of current row in ap. - kk := 0 - if incX == 1 { - x = x[:n] - for i, xi := range x { - for j := 0; j < i; j++ { - x[j] += xi * cmplx.Conj(ap[kk+j]) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(ap[kk+i]) - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - jx := kx - for j := 0; j < i; j++ { - x[jx] += xi * cmplx.Conj(ap[kk+j]) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(ap[kk+i]) - } - ix += incX - kk += i + 1 - } - } - } -} - -// Ztpsv solves one of the systems of equations -// -// A * x = b if trans == blas.NoTrans -// Aᵀ * x = b if trans == blas.Trans -// Aᴴ * x = b if trans == blas.ConjTrans -// -// where b and x are n element vectors and A is an n×n triangular matrix in -// packed form. -// -// On entry, x contains the values of b, and the solution is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func (Implementation) Ztpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex128, x []complex128, incX int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through ap. - - if trans == blas.NoTrans { - // Form x = inv(A)*x. - if uplo == blas.Upper { - kk := n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - aii := ap[kk] - if n-i-1 > 0 { - x[i] -= c128.DotuUnitary(x[i+1:n], ap[kk+1:kk+n-i]) - } - if diag == blas.NonUnit { - x[i] /= aii - } - kk -= n - i + 1 - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - aii := ap[kk] - if n-i-1 > 0 { - x[ix] -= c128.DotuInc(x, ap[kk+1:kk+n-i], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) - } - if diag == blas.NonUnit { - x[ix] /= aii - } - ix -= incX - kk -= n - i + 1 - } - } - } else { - kk := 0 - if incX == 1 { - for i := 0; i < n; i++ { - if i > 0 { - x[i] -= c128.DotuUnitary(x[:i], ap[kk:kk+i]) - } - if diag == blas.NonUnit { - x[i] /= ap[kk+i] - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - x[ix] -= c128.DotuInc(x, ap[kk:kk+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) - } - if diag == blas.NonUnit { - x[ix] /= ap[kk+i] - } - ix += incX - kk += i + 1 - } - } - } - return - } - - if trans == blas.Trans { - // Form x = inv(Aᵀ)*x. - if uplo == blas.Upper { - kk := 0 - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= ap[kk] - } - if n-j-1 > 0 { - c128.AxpyUnitary(-x[j], ap[kk+1:kk+n-j], x[j+1:n]) - } - kk += n - j - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= ap[kk] - } - if n-j-1 > 0 { - c128.AxpyInc(-x[jx], ap[kk+1:kk+n-j], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) - } - jx += incX - kk += n - j - } - } - } else { - kk := n*(n+1)/2 - n - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= ap[kk+j] - } - if j > 0 { - c128.AxpyUnitary(-x[j], ap[kk:kk+j], x[:j]) - } - kk -= j - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= ap[kk+j] - } - if j > 0 { - c128.AxpyInc(-x[jx], ap[kk:kk+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) - } - jx -= incX - kk -= j - } - } - } - return - } - - // Form x = inv(Aᴴ)*x. - if uplo == blas.Upper { - kk := 0 - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(ap[kk]) - } - xj := x[j] - k := kk + 1 - for i := j + 1; i < n; i++ { - x[i] -= xj * cmplx.Conj(ap[k]) - k++ - } - kk += n - j - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(ap[kk]) - } - xj := x[jx] - ix := jx + incX - k := kk + 1 - for i := j + 1; i < n; i++ { - x[ix] -= xj * cmplx.Conj(ap[k]) - ix += incX - k++ - } - jx += incX - kk += n - j - } - } - } else { - kk := n*(n+1)/2 - n - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(ap[kk+j]) - } - xj := x[j] - for i := 0; i < j; i++ { - x[i] -= xj * cmplx.Conj(ap[kk+i]) - } - kk -= j - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(ap[kk+j]) - } - xj := x[jx] - ix := kx - for i := 0; i < j; i++ { - x[ix] -= xj * cmplx.Conj(ap[kk+i]) - ix += incX - } - jx -= incX - kk -= j - } - } - } -} - -// Ztrmv performs one of the matrix-vector operations -// -// x = A * x if trans = blas.NoTrans -// x = Aᵀ * x if trans = blas.Trans -// x = Aᴴ * x if trans = blas.ConjTrans -// -// where x is a vector, and A is an n×n triangular matrix. -func (Implementation) Ztrmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through A. - - if trans == blas.NoTrans { - // Form x = A*x. - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - if n-i-1 > 0 { - x[i] += c128.DotuUnitary(a[i*lda+i+1:i*lda+n], x[i+1:n]) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - if n-i-1 > 0 { - x[ix] += c128.DotuInc(a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - if i > 0 { - x[i] += c128.DotuUnitary(a[i*lda:i*lda+i], x[:i]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - if i > 0 { - x[ix] += c128.DotuInc(a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - ix -= incX - } - } - } - return - } - - if trans == blas.Trans { - // Form x = Aᵀ*x. - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - if n-i-1 > 0 { - c128.AxpyUnitary(xi, a[i*lda+i+1:i*lda+n], x[i+1:n]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - if n-i-1 > 0 { - c128.AxpyInc(xi, a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - if i > 0 { - c128.AxpyUnitary(x[i], a[i*lda:i*lda+i], x[:i]) - } - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - c128.AxpyInc(x[ix], a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - ix += incX - } - } - } - return - } - - // Form x = Aᴴ*x. - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda+i]) - } - for j := i + 1; j < n; j++ { - x[j] += xi * cmplx.Conj(a[i*lda+j]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda+i]) - } - jx := ix + incX - for j := i + 1; j < n; j++ { - x[jx] += xi * cmplx.Conj(a[i*lda+j]) - jx += incX - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - for j := 0; j < i; j++ { - x[j] += x[i] * cmplx.Conj(a[i*lda+j]) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda+i]) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - jx := kx - for j := 0; j < i; j++ { - x[jx] += x[ix] * cmplx.Conj(a[i*lda+j]) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda+i]) - } - ix += incX - } - } - } -} - -// Ztrsv solves one of the systems of equations -// -// A * x = b if trans == blas.NoTrans -// Aᵀ * x = b if trans == blas.Trans -// Aᴴ * x = b if trans == blas.ConjTrans -// -// where b and x are n element vectors and A is an n×n triangular matrix. -// -// On entry, x contains the values of b, and the solution is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func (Implementation) Ztrsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through A. - - if trans == blas.NoTrans { - // Form x = inv(A)*x. - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - aii := a[i*lda+i] - if n-i-1 > 0 { - x[i] -= c128.DotuUnitary(x[i+1:n], a[i*lda+i+1:i*lda+n]) - } - if diag == blas.NonUnit { - x[i] /= aii - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - aii := a[i*lda+i] - if n-i-1 > 0 { - x[ix] -= c128.DotuInc(x, a[i*lda+i+1:i*lda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) - } - if diag == blas.NonUnit { - x[ix] /= aii - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - if i > 0 { - x[i] -= c128.DotuUnitary(x[:i], a[i*lda:i*lda+i]) - } - if diag == blas.NonUnit { - x[i] /= a[i*lda+i] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - x[ix] -= c128.DotuInc(x, a[i*lda:i*lda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) - } - if diag == blas.NonUnit { - x[ix] /= a[i*lda+i] - } - ix += incX - } - } - } - return - } - - if trans == blas.Trans { - // Form x = inv(Aᵀ)*x. - if uplo == blas.Upper { - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= a[j*lda+j] - } - if n-j-1 > 0 { - c128.AxpyUnitary(-x[j], a[j*lda+j+1:j*lda+n], x[j+1:n]) - } - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= a[j*lda+j] - } - if n-j-1 > 0 { - c128.AxpyInc(-x[jx], a[j*lda+j+1:j*lda+n], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) - } - jx += incX - } - } - } else { - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= a[j*lda+j] - } - xj := x[j] - if j > 0 { - c128.AxpyUnitary(-xj, a[j*lda:j*lda+j], x[:j]) - } - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= a[j*lda+j] - } - if j > 0 { - c128.AxpyInc(-x[jx], a[j*lda:j*lda+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) - } - jx -= incX - } - } - } - return - } - - // Form x = inv(Aᴴ)*x. - if uplo == blas.Upper { - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[j] - for i := j + 1; i < n; i++ { - x[i] -= xj * cmplx.Conj(a[j*lda+i]) - } - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[jx] - ix := jx + incX - for i := j + 1; i < n; i++ { - x[ix] -= xj * cmplx.Conj(a[j*lda+i]) - ix += incX - } - jx += incX - } - } - } else { - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[j] - for i := 0; i < j; i++ { - x[i] -= xj * cmplx.Conj(a[j*lda+i]) - } - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[jx] - ix := kx - for i := 0; i < j; i++ { - x[ix] -= xj * cmplx.Conj(a[j*lda+i]) - ix += incX - } - jx -= incX - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go deleted file mode 100644 index 3ce67868..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go +++ /dev/null @@ -1,2976 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2017 The Gonum 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 gonum - -import ( - cmplx "gonum.org/v1/gonum/internal/cmplx64" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/c64" -) - -var _ blas.Complex64Level2 = Implementation{} - -// Cgbmv performs one of the matrix-vector operations -// -// y = alpha * A * x + beta * y if trans = blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if trans = blas.Trans -// y = alpha * Aᴴ * x + beta * y if trans = blas.ConjTrans -// -// where alpha and beta are scalars, x and y are vectors, and A is an m×n band matrix -// with kL sub-diagonals and kU super-diagonals. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cgbmv(trans blas.Transpose, m, n, kL, kU int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if kL < 0 { - panic(kLLT0) - } - if kU < 0 { - panic(kULT0) - } - if lda < kL+kU+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { - panic(shortA) - } - var lenX, lenY int - if trans == blas.NoTrans { - lenX, lenY = n, m - } else { - lenX, lenY = m, n - } - if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - var kx int - if incX < 0 { - kx = (1 - lenX) * incX - } - var ky int - if incY < 0 { - ky = (1 - lenY) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:lenY] { - y[i] = 0 - } - } else { - c64.ScalUnitary(beta, y[:lenY]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < lenY; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - c64.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) - } else { - c64.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) - } - } - } - } - - nRow := min(m, n+kL) - nCol := kL + 1 + kU - switch trans { - case blas.NoTrans: - iy := ky - if incX == 1 { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) - xtmp := x[off : off+u-l] - var sum complex64 - for j, v := range aRow { - sum += xtmp[j] * v - } - y[iy] += alpha * sum - iy += incY - } - } else { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incX - jx := kx - var sum complex64 - for _, v := range aRow { - sum += x[off+jx] * v - jx += incX - } - y[iy] += alpha * sum - iy += incY - } - } - case blas.Trans: - if incX == 1 { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[i] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * v - jy += incY - } - } - } else { - ix := kx - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[ix] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * v - jy += incY - } - ix += incX - } - } - case blas.ConjTrans: - if incX == 1 { - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[i] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - } - } else { - ix := kx - for i := 0; i < nRow; i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - aRow := a[i*lda+l : i*lda+u] - off := max(0, i-kL) * incY - alphaxi := alpha * x[ix] - jy := ky - for _, v := range aRow { - y[off+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - ix += incX - } - } - } -} - -// Cgemv performs one of the matrix-vector operations -// -// y = alpha * A * x + beta * y if trans = blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if trans = blas.Trans -// y = alpha * Aᴴ * x + beta * y if trans = blas.ConjTrans -// -// where alpha and beta are scalars, x and y are vectors, and A is an m×n dense matrix. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cgemv(trans blas.Transpose, m, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - var lenX, lenY int - if trans == blas.NoTrans { - lenX = n - lenY = m - } else { - lenX = m - lenY = n - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - var kx int - if incX < 0 { - kx = (1 - lenX) * incX - } - var ky int - if incY < 0 { - ky = (1 - lenY) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:lenY] { - y[i] = 0 - } - } else { - c64.ScalUnitary(beta, y[:lenY]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < lenY; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - c64.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) - } else { - c64.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - switch trans { - default: - // Form y = alpha*A*x + y. - iy := ky - if incX == 1 { - for i := 0; i < m; i++ { - y[iy] += alpha * c64.DotuUnitary(a[i*lda:i*lda+n], x[:n]) - iy += incY - } - return - } - for i := 0; i < m; i++ { - y[iy] += alpha * c64.DotuInc(a[i*lda:i*lda+n], x, uintptr(n), 1, uintptr(incX), 0, uintptr(kx)) - iy += incY - } - return - - case blas.Trans: - // Form y = alpha*Aᵀ*x + y. - ix := kx - if incY == 1 { - for i := 0; i < m; i++ { - c64.AxpyUnitary(alpha*x[ix], a[i*lda:i*lda+n], y[:n]) - ix += incX - } - return - } - for i := 0; i < m; i++ { - c64.AxpyInc(alpha*x[ix], a[i*lda:i*lda+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) - ix += incX - } - return - - case blas.ConjTrans: - // Form y = alpha*Aᴴ*x + y. - ix := kx - if incY == 1 { - for i := 0; i < m; i++ { - tmp := alpha * x[ix] - for j := 0; j < n; j++ { - y[j] += tmp * cmplx.Conj(a[i*lda+j]) - } - ix += incX - } - return - } - for i := 0; i < m; i++ { - tmp := alpha * x[ix] - jy := ky - for j := 0; j < n; j++ { - y[jy] += tmp * cmplx.Conj(a[i*lda+j]) - jy += incY - } - ix += incX - } - return - } -} - -// Cgerc performs the rank-one operation -// -// A += alpha * x * yᴴ -// -// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, -// and y is an n element vector. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx, jy int - if incX < 0 { - kx = (1 - m) * incX - } - if incY < 0 { - jy = (1 - n) * incY - } - for j := 0; j < n; j++ { - if y[jy] != 0 { - tmp := alpha * cmplx.Conj(y[jy]) - c64.AxpyInc(tmp, x, a[j:], uintptr(m), uintptr(incX), uintptr(lda), uintptr(kx), 0) - } - jy += incY - } -} - -// Cgeru performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, -// and y is an n element vector. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx int - if incX < 0 { - kx = (1 - m) * incX - } - if incY == 1 { - for i := 0; i < m; i++ { - if x[kx] != 0 { - tmp := alpha * x[kx] - c64.AxpyUnitary(tmp, y[:n], a[i*lda:i*lda+n]) - } - kx += incX - } - return - } - var jy int - if incY < 0 { - jy = (1 - n) * incY - } - for i := 0; i < m; i++ { - if x[kx] != 0 { - tmp := alpha * x[kx] - c64.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(jy), 0) - } - kx += incX - } -} - -// Chbmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where alpha and beta are scalars, x and y are vectors, and A is an n×n -// Hermitian band matrix with k super-diagonals. The imaginary parts of -// the diagonal elements of A are ignored and assumed to be zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Chbmv(uplo blas.Uplo, n, k int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up the start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - for i, v := range y[:n] { - y[i] = beta * v - } - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - for i := 0; i < n; i++ { - y[iy] = beta * y[iy] - iy += incY - } - } - } - } - - if alpha == 0 { - return - } - - // The elements of A are accessed sequentially with one pass through a. - switch uplo { - case blas.Upper: - iy := ky - if incX == 1 { - for i := 0; i < n; i++ { - aRow := a[i*lda:] - alphaxi := alpha * x[i] - sum := alphaxi * complex(real(aRow[0]), 0) - u := min(k+1, n-i) - jy := incY - for j := 1; j < u; j++ { - v := aRow[j] - sum += alpha * x[i+j] * v - y[iy+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - y[iy] += sum - iy += incY - } - } else { - ix := kx - for i := 0; i < n; i++ { - aRow := a[i*lda:] - alphaxi := alpha * x[ix] - sum := alphaxi * complex(real(aRow[0]), 0) - u := min(k+1, n-i) - jx := incX - jy := incY - for j := 1; j < u; j++ { - v := aRow[j] - sum += alpha * x[ix+jx] * v - y[iy+jy] += alphaxi * cmplx.Conj(v) - jx += incX - jy += incY - } - y[iy] += sum - ix += incX - iy += incY - } - } - case blas.Lower: - iy := ky - if incX == 1 { - for i := 0; i < n; i++ { - l := max(0, k-i) - alphaxi := alpha * x[i] - jy := l * incY - aRow := a[i*lda:] - for j := l; j < k; j++ { - v := aRow[j] - y[iy] += alpha * v * x[i-k+j] - y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) - jy += incY - } - y[iy] += alphaxi * complex(real(aRow[k]), 0) - iy += incY - } - } else { - ix := kx - for i := 0; i < n; i++ { - l := max(0, k-i) - alphaxi := alpha * x[ix] - jx := l * incX - jy := l * incY - aRow := a[i*lda:] - for j := l; j < k; j++ { - v := aRow[j] - y[iy] += alpha * v * x[ix-k*incX+jx] - y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) - jx += incX - jy += incY - } - y[iy] += alphaxi * complex(real(aRow[k]), 0) - ix += incX - iy += incY - } - } - } -} - -// Chemv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where alpha and beta are scalars, x and y are vectors, and A is an n×n -// Hermitian matrix. The imaginary parts of the diagonal elements of A are -// ignored and assumed to be zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Chemv(uplo blas.Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up the start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - for i, v := range y[:n] { - y[i] = beta * v - } - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - for i := 0; i < n; i++ { - y[iy] = beta * y[iy] - iy += incY - } - } - } - } - - if alpha == 0 { - return - } - - // The elements of A are accessed sequentially with one pass through - // the triangular part of A. - - if uplo == blas.Upper { - // Form y when A is stored in upper triangle. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - var tmp2 complex64 - for j := i + 1; j < n; j++ { - y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[j] - } - aii := complex(real(a[i*lda+i]), 0) - y[i] += tmp1*aii + alpha*tmp2 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - var tmp2 complex64 - jx := ix - jy := iy - for j := i + 1; j < n; j++ { - jx += incX - jy += incY - y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[jx] - } - aii := complex(real(a[i*lda+i]), 0) - y[iy] += tmp1*aii + alpha*tmp2 - ix += incX - iy += incY - } - } - return - } - - // Form y when A is stored in lower triangle. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - var tmp2 complex64 - for j := 0; j < i; j++ { - y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[j] - } - aii := complex(real(a[i*lda+i]), 0) - y[i] += tmp1*aii + alpha*tmp2 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - var tmp2 complex64 - jx := kx - jy := ky - for j := 0; j < i; j++ { - y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) - tmp2 += a[i*lda+j] * x[jx] - jx += incX - jy += incY - } - aii := complex(real(a[i*lda+i]), 0) - y[iy] += tmp1*aii + alpha*tmp2 - ix += incX - iy += incY - } - } -} - -// Cher performs the Hermitian rank-one operation -// -// A += alpha * x * xᴴ -// -// where A is an n×n Hermitian matrix, alpha is a real scalar, and x is an n -// element vector. On entry, the imaginary parts of the diagonal elements of A -// are ignored and assumed to be zero, on return they will be set to zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cher(uplo blas.Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 { - tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii+xtmp, 0) - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[j]) - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - - ix := kx - for i := 0; i < n; i++ { - if x[ix] != 0 { - tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii+xtmp, 0) - jx := ix + incX - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - } - return - } - - if incX == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 { - tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) - for j := 0; j < i; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[j]) - } - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii+xtmp, 0) - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - - ix := kx - for i := 0; i < n; i++ { - if x[ix] != 0 { - tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) - jx := kx - for j := 0; j < i; j++ { - a[i*lda+j] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - aii := real(a[i*lda+i]) - xtmp := real(tmp * cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii+xtmp, 0) - - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - } -} - -// Cher2 performs the Hermitian rank-two operation -// -// A += alpha * x * yᴴ + conj(alpha) * y * xᴴ -// -// where alpha is a scalar, x and y are n element vectors and A is an n×n -// Hermitian matrix. On entry, the imaginary parts of the diagonal elements are -// ignored and assumed to be zero. On return they will be set to zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cher2(uplo blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var kx, ky int - var ix, iy int - if incX != 1 || incY != 1 { - if incX < 0 { - kx = (1 - n) * incX - } - if incY < 0 { - ky = (1 - n) * incY - } - ix = kx - iy = ky - } - if uplo == blas.Upper { - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii, 0) - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii, 0) - jx := ix + incX - jy := iy + incY - for j := i + 1; j < n; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - iy += incY - } - return - } - - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - for j := 0; j < i; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - } - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - a[i*lda+i] = complex(aii, 0) - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - } - return - } - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - jx := kx - jy := ky - for j := 0; j < i; j++ { - a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - a[i*lda+i] = complex(aii, 0) - } else { - aii := real(a[i*lda+i]) - a[i*lda+i] = complex(aii, 0) - } - ix += incX - iy += incY - } -} - -// Chpmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where alpha and beta are scalars, x and y are vectors, and A is an n×n -// Hermitian matrix in packed form. The imaginary parts of the diagonal -// elements of A are ignored and assumed to be zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Chpmv(uplo blas.Uplo, n int, alpha complex64, ap []complex64, x []complex64, incX int, beta complex64, y []complex64, incY int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up the start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // Form y = beta*y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - for i, v := range y[:n] { - y[i] = beta * v - } - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - for i := 0; i < n; i++ { - y[iy] *= beta - iy += incY - } - } - } - } - - if alpha == 0 { - return - } - - // The elements of A are accessed sequentially with one pass through ap. - - var kk int - if uplo == blas.Upper { - // Form y when ap contains the upper triangle. - // Here, kk points to the current diagonal element in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - y[i] += tmp1 * complex(real(ap[kk]), 0) - var tmp2 complex64 - k := kk + 1 - for j := i + 1; j < n; j++ { - y[j] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[j] - k++ - } - y[i] += alpha * tmp2 - kk += n - i - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - y[iy] += tmp1 * complex(real(ap[kk]), 0) - var tmp2 complex64 - jx := ix - jy := iy - for k := kk + 1; k < kk+n-i; k++ { - jx += incX - jy += incY - y[jy] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[jx] - } - y[iy] += alpha * tmp2 - ix += incX - iy += incY - kk += n - i - } - } - return - } - - // Form y when ap contains the lower triangle. - // Here, kk points to the beginning of current row in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - tmp1 := alpha * x[i] - var tmp2 complex64 - k := kk - for j := 0; j < i; j++ { - y[j] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[j] - k++ - } - aii := complex(real(ap[kk+i]), 0) - y[i] += tmp1*aii + alpha*tmp2 - kk += i + 1 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - tmp1 := alpha * x[ix] - var tmp2 complex64 - jx := kx - jy := ky - for k := kk; k < kk+i; k++ { - y[jy] += tmp1 * cmplx.Conj(ap[k]) - tmp2 += ap[k] * x[jx] - jx += incX - jy += incY - } - aii := complex(real(ap[kk+i]), 0) - y[iy] += tmp1*aii + alpha*tmp2 - ix += incX - iy += incY - kk += i + 1 - } - } -} - -// Chpr performs the Hermitian rank-1 operation -// -// A += alpha * x * xᴴ -// -// where alpha is a real scalar, x is a vector, and A is an n×n hermitian matrix -// in packed form. On entry, the imaginary parts of the diagonal elements are -// assumed to be zero, and on return they are set to zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Chpr(uplo blas.Uplo, n int, alpha float32, x []complex64, incX int, ap []complex64) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through ap. - - var kk int - if uplo == blas.Upper { - // Form A when upper triangle is stored in AP. - // Here, kk points to the current diagonal element in ap. - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if xi != 0 { - aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk] = complex(aii, 0) - - tmp := complex(alpha, 0) * xi - a := ap[kk+1 : kk+n-i] - x := x[i+1 : n] - for j, v := range x { - a[j] += tmp * cmplx.Conj(v) - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - kk += n - i - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - if xi != 0 { - aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk] = complex(aii, 0) - - tmp := complex(alpha, 0) * xi - jx := ix + incX - a := ap[kk+1 : kk+n-i] - for k := range a { - a[k] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - ix += incX - kk += n - i - } - } - return - } - - // Form A when lower triangle is stored in AP. - // Here, kk points to the beginning of current row in ap. - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if xi != 0 { - tmp := complex(alpha, 0) * xi - a := ap[kk : kk+i] - for j, v := range x[:i] { - a[j] += tmp * cmplx.Conj(v) - } - - aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - if xi != 0 { - tmp := complex(alpha, 0) * xi - a := ap[kk : kk+i] - jx := kx - for k := range a { - a[k] += tmp * cmplx.Conj(x[jx]) - jx += incX - } - - aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - ix += incX - kk += i + 1 - } - } -} - -// Chpr2 performs the Hermitian rank-2 operation -// -// A += alpha * x * yᴴ + conj(alpha) * y * xᴴ -// -// where alpha is a complex scalar, x and y are n element vectors, and A is an -// n×n Hermitian matrix, supplied in packed form. On entry, the imaginary parts -// of the diagonal elements are assumed to be zero, and on return they are set to zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Chpr2(uplo blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - // Set up start indices in X and Y. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - var ky int - if incY < 0 { - ky = (1 - n) * incY - } - - // The elements of A are accessed sequentially with one pass through ap. - - var kk int - if uplo == blas.Upper { - // Form A when upper triangle is stored in AP. - // Here, kk points to the current diagonal element in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - ap[kk] = complex(aii, 0) - k := kk + 1 - for j := i + 1; j < n; j++ { - ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - k++ - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - kk += n - i - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - ap[kk] = complex(aii, 0) - jx := ix + incX - jy := iy + incY - for k := kk + 1; k < kk+n-i; k++ { - ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - } else { - ap[kk] = complex(real(ap[kk]), 0) - } - ix += incX - iy += incY - kk += n - i - } - } - return - } - - // Form A when lower triangle is stored in AP. - // Here, kk points to the beginning of current row in ap. - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - if x[i] != 0 || y[i] != 0 { - tmp1 := alpha * x[i] - tmp2 := cmplx.Conj(alpha) * y[i] - k := kk - for j := 0; j < i; j++ { - ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) - k++ - } - aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - kk += i + 1 - } - } else { - ix := kx - iy := ky - for i := 0; i < n; i++ { - if x[ix] != 0 || y[iy] != 0 { - tmp1 := alpha * x[ix] - tmp2 := cmplx.Conj(alpha) * y[iy] - jx := kx - jy := ky - for k := kk; k < kk+i; k++ { - ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) - jx += incX - jy += incY - } - aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) - ap[kk+i] = complex(aii, 0) - } else { - ap[kk+i] = complex(real(ap[kk+i]), 0) - } - ix += incX - iy += incY - kk += i + 1 - } - } -} - -// Ctbmv performs one of the matrix-vector operations -// -// x = A * x if trans = blas.NoTrans -// x = Aᵀ * x if trans = blas.Trans -// x = Aᴴ * x if trans = blas.ConjTrans -// -// where x is an n element vector and A is an n×n triangular band matrix, with -// (k+1) diagonals. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - switch trans { - case blas.NoTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if diag == blas.NonUnit { - xi *= a[i*lda] - } - kk := min(k, n-i-1) - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - xi += x[i+j+1] * aij - } - x[i] = xi - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - if diag == blas.NonUnit { - xi *= a[i*lda] - } - kk := min(k, n-i-1) - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - xi += x[jx] * aij - jx += incX - } - x[ix] = xi - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - xi *= a[i*lda+k] - } - kk := min(k, i) - for j, aij := range a[i*lda+k-kk : i*lda+k] { - xi += x[i-kk+j] * aij - } - x[i] = xi - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - xi *= a[i*lda+k] - } - kk := min(k, i) - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - xi += x[jx] * aij - jx += incX - } - x[ix] = xi - ix -= incX - } - } - } - case blas.Trans: - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+j+1] += xi * aij - } - if diag == blas.NonUnit { - x[i] *= a[i*lda] - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - jx := ix + incX - xi := x[ix] - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] += xi * aij - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= a[i*lda] - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] += xi * aij - } - if diag == blas.NonUnit { - x[i] *= a[i*lda+k] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - kk := min(k, i) - jx := ix - kk*incX - xi := x[ix] - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] += xi * aij - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= a[i*lda+k] - } - ix += incX - } - } - } - case blas.ConjTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+j+1] += xi * cmplx.Conj(aij) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - jx := ix + incX - xi := x[ix] - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] += xi * cmplx.Conj(aij) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda]) - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] += xi * cmplx.Conj(aij) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda+k]) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - kk := min(k, i) - jx := ix - kk*incX - xi := x[ix] - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] += xi * cmplx.Conj(aij) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda+k]) - } - ix += incX - } - } - } - } -} - -// Ctbsv solves one of the systems of equations -// -// A * x = b if trans == blas.NoTrans -// Aᵀ * x = b if trans == blas.Trans -// Aᴴ * x = b if trans == blas.ConjTrans -// -// where b and x are n element vectors and A is an n×n triangular band matrix -// with (k+1) diagonals. -// -// On entry, x contains the values of b, and the solution is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - switch trans { - case blas.NoTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - var sum complex64 - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - sum += x[i+1+j] * aij - } - x[i] -= sum - if diag == blas.NonUnit { - x[i] /= a[i*lda] - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - kk := min(k, n-i-1) - var sum complex64 - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - sum += x[jx] * aij - jx += incX - } - x[ix] -= sum - if diag == blas.NonUnit { - x[ix] /= a[i*lda] - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - kk := min(k, i) - var sum complex64 - for j, aij := range a[i*lda+k-kk : i*lda+k] { - sum += x[i-kk+j] * aij - } - x[i] -= sum - if diag == blas.NonUnit { - x[i] /= a[i*lda+k] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - kk := min(k, i) - var sum complex64 - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - sum += x[jx] * aij - jx += incX - } - x[ix] -= sum - if diag == blas.NonUnit { - x[ix] /= a[i*lda+k] - } - ix += incX - } - } - } - case blas.Trans: - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[i] /= a[i*lda] - } - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+1+j] -= xi * aij - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] /= a[i*lda] - } - kk := min(k, n-i-1) - xi := x[ix] - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] -= xi * aij - jx += incX - } - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] /= a[i*lda+k] - } - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] -= xi * aij - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] /= a[i*lda+k] - } - kk := min(k, i) - xi := x[ix] - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] -= xi * aij - jx += incX - } - ix -= incX - } - } - } - case blas.ConjTrans: - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[i] /= cmplx.Conj(a[i*lda]) - } - kk := min(k, n-i-1) - xi := x[i] - for j, aij := range a[i*lda+1 : i*lda+kk+1] { - x[i+1+j] -= xi * cmplx.Conj(aij) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] /= cmplx.Conj(a[i*lda]) - } - kk := min(k, n-i-1) - xi := x[ix] - jx := ix + incX - for _, aij := range a[i*lda+1 : i*lda+kk+1] { - x[jx] -= xi * cmplx.Conj(aij) - jx += incX - } - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] /= cmplx.Conj(a[i*lda+k]) - } - kk := min(k, i) - xi := x[i] - for j, aij := range a[i*lda+k-kk : i*lda+k] { - x[i-kk+j] -= xi * cmplx.Conj(aij) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] /= cmplx.Conj(a[i*lda+k]) - } - kk := min(k, i) - xi := x[ix] - jx := ix - kk*incX - for _, aij := range a[i*lda+k-kk : i*lda+k] { - x[jx] -= xi * cmplx.Conj(aij) - jx += incX - } - ix -= incX - } - } - } - } -} - -// Ctpmv performs one of the matrix-vector operations -// -// x = A * x if trans = blas.NoTrans -// x = Aᵀ * x if trans = blas.Trans -// x = Aᴴ * x if trans = blas.ConjTrans -// -// where x is an n element vector and A is an n×n triangular matrix, supplied in -// packed form. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctpmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex64, x []complex64, incX int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through A. - - if trans == blas.NoTrans { - // Form x = A*x. - if uplo == blas.Upper { - // kk points to the current diagonal element in ap. - kk := 0 - if incX == 1 { - x = x[:n] - for i := range x { - if diag == blas.NonUnit { - x[i] *= ap[kk] - } - if n-i-1 > 0 { - x[i] += c64.DotuUnitary(ap[kk+1:kk+n-i], x[i+1:]) - } - kk += n - i - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] *= ap[kk] - } - if n-i-1 > 0 { - x[ix] += c64.DotuInc(ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix += incX - kk += n - i - } - } - } else { - // kk points to the beginning of current row in ap. - kk := n*(n+1)/2 - n - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] *= ap[kk+i] - } - if i > 0 { - x[i] += c64.DotuUnitary(ap[kk:kk+i], x[:i]) - } - kk -= i - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] *= ap[kk+i] - } - if i > 0 { - x[ix] += c64.DotuInc(ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - ix -= incX - kk -= i - } - } - } - return - } - - if trans == blas.Trans { - // Form x = Aᵀ*x. - if uplo == blas.Upper { - // kk points to the current diagonal element in ap. - kk := n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= ap[kk] - } - if n-i-1 > 0 { - c64.AxpyUnitary(xi, ap[kk+1:kk+n-i], x[i+1:n]) - } - kk -= n - i + 1 - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= ap[kk] - } - if n-i-1 > 0 { - c64.AxpyInc(xi, ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix -= incX - kk -= n - i + 1 - } - } - } else { - // kk points to the beginning of current row in ap. - kk := 0 - if incX == 1 { - x = x[:n] - for i := range x { - if i > 0 { - c64.AxpyUnitary(x[i], ap[kk:kk+i], x[:i]) - } - if diag == blas.NonUnit { - x[i] *= ap[kk+i] - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - c64.AxpyInc(x[ix], ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - if diag == blas.NonUnit { - x[ix] *= ap[kk+i] - } - ix += incX - kk += i + 1 - } - } - } - return - } - - // Form x = Aᴴ*x. - if uplo == blas.Upper { - // kk points to the current diagonal element in ap. - kk := n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(ap[kk]) - } - k := kk + 1 - for j := i + 1; j < n; j++ { - x[j] += xi * cmplx.Conj(ap[k]) - k++ - } - kk -= n - i + 1 - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(ap[kk]) - } - jx := ix + incX - k := kk + 1 - for j := i + 1; j < n; j++ { - x[jx] += xi * cmplx.Conj(ap[k]) - jx += incX - k++ - } - ix -= incX - kk -= n - i + 1 - } - } - } else { - // kk points to the beginning of current row in ap. - kk := 0 - if incX == 1 { - x = x[:n] - for i, xi := range x { - for j := 0; j < i; j++ { - x[j] += xi * cmplx.Conj(ap[kk+j]) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(ap[kk+i]) - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - xi := x[ix] - jx := kx - for j := 0; j < i; j++ { - x[jx] += xi * cmplx.Conj(ap[kk+j]) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(ap[kk+i]) - } - ix += incX - kk += i + 1 - } - } - } -} - -// Ctpsv solves one of the systems of equations -// -// A * x = b if trans == blas.NoTrans -// Aᵀ * x = b if trans == blas.Trans -// Aᴴ * x = b if trans == blas.ConjTrans -// -// where b and x are n element vectors and A is an n×n triangular matrix in -// packed form. -// -// On entry, x contains the values of b, and the solution is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex64, x []complex64, incX int) { - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through ap. - - if trans == blas.NoTrans { - // Form x = inv(A)*x. - if uplo == blas.Upper { - kk := n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - aii := ap[kk] - if n-i-1 > 0 { - x[i] -= c64.DotuUnitary(x[i+1:n], ap[kk+1:kk+n-i]) - } - if diag == blas.NonUnit { - x[i] /= aii - } - kk -= n - i + 1 - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - aii := ap[kk] - if n-i-1 > 0 { - x[ix] -= c64.DotuInc(x, ap[kk+1:kk+n-i], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) - } - if diag == blas.NonUnit { - x[ix] /= aii - } - ix -= incX - kk -= n - i + 1 - } - } - } else { - kk := 0 - if incX == 1 { - for i := 0; i < n; i++ { - if i > 0 { - x[i] -= c64.DotuUnitary(x[:i], ap[kk:kk+i]) - } - if diag == blas.NonUnit { - x[i] /= ap[kk+i] - } - kk += i + 1 - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - x[ix] -= c64.DotuInc(x, ap[kk:kk+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) - } - if diag == blas.NonUnit { - x[ix] /= ap[kk+i] - } - ix += incX - kk += i + 1 - } - } - } - return - } - - if trans == blas.Trans { - // Form x = inv(Aᵀ)*x. - if uplo == blas.Upper { - kk := 0 - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= ap[kk] - } - if n-j-1 > 0 { - c64.AxpyUnitary(-x[j], ap[kk+1:kk+n-j], x[j+1:n]) - } - kk += n - j - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= ap[kk] - } - if n-j-1 > 0 { - c64.AxpyInc(-x[jx], ap[kk+1:kk+n-j], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) - } - jx += incX - kk += n - j - } - } - } else { - kk := n*(n+1)/2 - n - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= ap[kk+j] - } - if j > 0 { - c64.AxpyUnitary(-x[j], ap[kk:kk+j], x[:j]) - } - kk -= j - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= ap[kk+j] - } - if j > 0 { - c64.AxpyInc(-x[jx], ap[kk:kk+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) - } - jx -= incX - kk -= j - } - } - } - return - } - - // Form x = inv(Aᴴ)*x. - if uplo == blas.Upper { - kk := 0 - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(ap[kk]) - } - xj := x[j] - k := kk + 1 - for i := j + 1; i < n; i++ { - x[i] -= xj * cmplx.Conj(ap[k]) - k++ - } - kk += n - j - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(ap[kk]) - } - xj := x[jx] - ix := jx + incX - k := kk + 1 - for i := j + 1; i < n; i++ { - x[ix] -= xj * cmplx.Conj(ap[k]) - ix += incX - k++ - } - jx += incX - kk += n - j - } - } - } else { - kk := n*(n+1)/2 - n - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(ap[kk+j]) - } - xj := x[j] - for i := 0; i < j; i++ { - x[i] -= xj * cmplx.Conj(ap[kk+i]) - } - kk -= j - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(ap[kk+j]) - } - xj := x[jx] - ix := kx - for i := 0; i < j; i++ { - x[ix] -= xj * cmplx.Conj(ap[kk+i]) - ix += incX - } - jx -= incX - kk -= j - } - } - } -} - -// Ctrmv performs one of the matrix-vector operations -// -// x = A * x if trans = blas.NoTrans -// x = Aᵀ * x if trans = blas.Trans -// x = Aᴴ * x if trans = blas.ConjTrans -// -// where x is a vector, and A is an n×n triangular matrix. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctrmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through A. - - if trans == blas.NoTrans { - // Form x = A*x. - if uplo == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - if n-i-1 > 0 { - x[i] += c64.DotuUnitary(a[i*lda+i+1:i*lda+n], x[i+1:n]) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - if n-i-1 > 0 { - x[ix] += c64.DotuInc(a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix += incX - } - } - } else { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - if i > 0 { - x[i] += c64.DotuUnitary(a[i*lda:i*lda+i], x[:i]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - if i > 0 { - x[ix] += c64.DotuInc(a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - ix -= incX - } - } - } - return - } - - if trans == blas.Trans { - // Form x = Aᵀ*x. - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - if n-i-1 > 0 { - c64.AxpyUnitary(xi, a[i*lda+i+1:i*lda+n], x[i+1:n]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - if n-i-1 > 0 { - c64.AxpyInc(xi, a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - if i > 0 { - c64.AxpyUnitary(x[i], a[i*lda:i*lda+i], x[:i]) - } - if diag == blas.NonUnit { - x[i] *= a[i*lda+i] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - c64.AxpyInc(x[ix], a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - } - if diag == blas.NonUnit { - x[ix] *= a[i*lda+i] - } - ix += incX - } - } - } - return - } - - // Form x = Aᴴ*x. - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - xi := x[i] - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda+i]) - } - for j := i + 1; j < n; j++ { - x[j] += xi * cmplx.Conj(a[i*lda+j]) - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - xi := x[ix] - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda+i]) - } - jx := ix + incX - for j := i + 1; j < n; j++ { - x[jx] += xi * cmplx.Conj(a[i*lda+j]) - jx += incX - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - for j := 0; j < i; j++ { - x[j] += x[i] * cmplx.Conj(a[i*lda+j]) - } - if diag == blas.NonUnit { - x[i] *= cmplx.Conj(a[i*lda+i]) - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - jx := kx - for j := 0; j < i; j++ { - x[jx] += x[ix] * cmplx.Conj(a[i*lda+j]) - jx += incX - } - if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(a[i*lda+i]) - } - ix += incX - } - } - } -} - -// Ctrsv solves one of the systems of equations -// -// A * x = b if trans == blas.NoTrans -// Aᵀ * x = b if trans == blas.Trans -// Aᴴ * x = b if trans == blas.ConjTrans -// -// where b and x are n element vectors and A is an n×n triangular matrix. -// -// On entry, x contains the values of b, and the solution is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctrsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { - switch trans { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch uplo { - default: - panic(badUplo) - case blas.Upper, blas.Lower: - } - switch diag { - default: - panic(badDiag) - case blas.NonUnit, blas.Unit: - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - // Set up start index in X. - var kx int - if incX < 0 { - kx = (1 - n) * incX - } - - // The elements of A are accessed sequentially with one pass through A. - - if trans == blas.NoTrans { - // Form x = inv(A)*x. - if uplo == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - aii := a[i*lda+i] - if n-i-1 > 0 { - x[i] -= c64.DotuUnitary(x[i+1:n], a[i*lda+i+1:i*lda+n]) - } - if diag == blas.NonUnit { - x[i] /= aii - } - } - } else { - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - aii := a[i*lda+i] - if n-i-1 > 0 { - x[ix] -= c64.DotuInc(x, a[i*lda+i+1:i*lda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) - } - if diag == blas.NonUnit { - x[ix] /= aii - } - ix -= incX - } - } - } else { - if incX == 1 { - for i := 0; i < n; i++ { - if i > 0 { - x[i] -= c64.DotuUnitary(x[:i], a[i*lda:i*lda+i]) - } - if diag == blas.NonUnit { - x[i] /= a[i*lda+i] - } - } - } else { - ix := kx - for i := 0; i < n; i++ { - if i > 0 { - x[ix] -= c64.DotuInc(x, a[i*lda:i*lda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) - } - if diag == blas.NonUnit { - x[ix] /= a[i*lda+i] - } - ix += incX - } - } - } - return - } - - if trans == blas.Trans { - // Form x = inv(Aᵀ)*x. - if uplo == blas.Upper { - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= a[j*lda+j] - } - if n-j-1 > 0 { - c64.AxpyUnitary(-x[j], a[j*lda+j+1:j*lda+n], x[j+1:n]) - } - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= a[j*lda+j] - } - if n-j-1 > 0 { - c64.AxpyInc(-x[jx], a[j*lda+j+1:j*lda+n], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) - } - jx += incX - } - } - } else { - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= a[j*lda+j] - } - xj := x[j] - if j > 0 { - c64.AxpyUnitary(-xj, a[j*lda:j*lda+j], x[:j]) - } - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= a[j*lda+j] - } - if j > 0 { - c64.AxpyInc(-x[jx], a[j*lda:j*lda+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) - } - jx -= incX - } - } - } - return - } - - // Form x = inv(Aᴴ)*x. - if uplo == blas.Upper { - if incX == 1 { - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[j] - for i := j + 1; i < n; i++ { - x[i] -= xj * cmplx.Conj(a[j*lda+i]) - } - } - } else { - jx := kx - for j := 0; j < n; j++ { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[jx] - ix := jx + incX - for i := j + 1; i < n; i++ { - x[ix] -= xj * cmplx.Conj(a[j*lda+i]) - ix += incX - } - jx += incX - } - } - } else { - if incX == 1 { - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[j] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[j] - for i := 0; i < j; i++ { - x[i] -= xj * cmplx.Conj(a[j*lda+i]) - } - } - } else { - jx := kx + (n-1)*incX - for j := n - 1; j >= 0; j-- { - if diag == blas.NonUnit { - x[jx] /= cmplx.Conj(a[j*lda+j]) - } - xj := x[jx] - ix := kx - for i := 0; i < j; i++ { - x[ix] -= xj * cmplx.Conj(a[j*lda+i]) - ix += incX - } - jx -= incX - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2float32.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2float32.go deleted file mode 100644 index 26e4959d..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level2float32.go +++ /dev/null @@ -1,2400 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2014 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f32" -) - -var _ blas.Float32Level2 = Implementation{} - -// Sger performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sger(m, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - f32.Ger(uintptr(m), uintptr(n), - alpha, - x, uintptr(incX), - y, uintptr(incY), - a, uintptr(lda)) -} - -// Sgbmv performs one of the matrix-vector operations -// -// y = alpha * A * x + beta * y if tA == blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if tA == blas.Trans or blas.ConjTrans -// -// where A is an m×n band matrix with kL sub-diagonals and kU super-diagonals, -// x and y are vectors, and alpha and beta are scalars. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if kL < 0 { - panic(kLLT0) - } - if kU < 0 { - panic(kULT0) - } - if lda < kL+kU+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { - panic(shortA) - } - lenX := m - lenY := n - if tA == blas.NoTrans { - lenX = n - lenY = m - } - if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - var kx, ky int - if incX < 0 { - kx = -(lenX - 1) * incX - } - if incY < 0 { - ky = -(lenY - 1) * incY - } - - // Form y = beta * y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:lenY] { - y[i] = 0 - } - } else { - f32.ScalUnitary(beta, y[:lenY]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < lenY; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f32.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) - } else { - f32.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - // i and j are indices of the compacted banded matrix. - // off is the offset into the dense matrix (off + j = densej) - nCol := kU + 1 + kL - if tA == blas.NoTrans { - iy := ky - if incX == 1 { - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - xtmp := x[off : off+u-l] - var sum float32 - for j, v := range atmp { - sum += xtmp[j] * v - } - y[iy] += sum * alpha - iy += incY - } - return - } - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - jx := kx - var sum float32 - for _, v := range atmp { - sum += x[off*incX+jx] * v - jx += incX - } - y[iy] += sum * alpha - iy += incY - } - return - } - if incX == 1 { - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - tmp := alpha * x[i] - jy := ky - for _, v := range atmp { - y[jy+off*incY] += tmp * v - jy += incY - } - } - return - } - ix := kx - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - tmp := alpha * x[ix] - jy := ky - for _, v := range atmp { - y[jy+off*incY] += tmp * v - jy += incY - } - ix += incX - } -} - -// Sgemv computes -// -// y = alpha * A * x + beta * y if tA = blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if tA = blas.Trans or blas.ConjTrans -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - // Set up indexes - lenX := m - lenY := n - if tA == blas.NoTrans { - lenX = n - lenY = m - } - - // Quick return if possible - if m == 0 || n == 0 { - return - } - - if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible - if alpha == 0 && beta == 1 { - return - } - - if alpha == 0 { - // First form y = beta * y - if incY > 0 { - Implementation{}.Sscal(lenY, beta, y, incY) - } else { - Implementation{}.Sscal(lenY, beta, y, -incY) - } - return - } - - // Form y = alpha * A * x + y - if tA == blas.NoTrans { - f32.GemvN(uintptr(m), uintptr(n), alpha, a, uintptr(lda), x, uintptr(incX), beta, y, uintptr(incY)) - return - } - // Cases where a is transposed. - f32.GemvT(uintptr(m), uintptr(n), alpha, a, uintptr(lda), x, uintptr(incX), beta, y, uintptr(incY)) -} - -// Strmv performs one of the matrix-vector operations -// -// x = A * x if tA == blas.NoTrans -// x = Aᵀ * x if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix, and x is a vector. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - nonUnit := d != blas.Unit - if n == 1 { - if nonUnit { - x[0] *= a[0] - } - return - } - var kx int - if incX <= 0 { - kx = -(n - 1) * incX - } - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - ilda := i * lda - var tmp float32 - if nonUnit { - tmp = a[ilda+i] * x[i] - } else { - tmp = x[i] - } - x[i] = tmp + f32.DotUnitary(a[ilda+i+1:ilda+n], x[i+1:n]) - } - return - } - ix := kx - for i := 0; i < n; i++ { - ilda := i * lda - var tmp float32 - if nonUnit { - tmp = a[ilda+i] * x[ix] - } else { - tmp = x[ix] - } - x[ix] = tmp + f32.DotInc(x, a[ilda+i+1:ilda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - ilda := i * lda - var tmp float32 - if nonUnit { - tmp += a[ilda+i] * x[i] - } else { - tmp = x[i] - } - x[i] = tmp + f32.DotUnitary(a[ilda:ilda+i], x[:i]) - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - ilda := i * lda - var tmp float32 - if nonUnit { - tmp = a[ilda+i] * x[ix] - } else { - tmp = x[ix] - } - x[ix] = tmp + f32.DotInc(x, a[ilda:ilda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) - ix -= incX - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - ilda := i * lda - xi := x[i] - f32.AxpyUnitary(xi, a[ilda+i+1:ilda+n], x[i+1:n]) - if nonUnit { - x[i] *= a[ilda+i] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - ilda := i * lda - xi := x[ix] - f32.AxpyInc(xi, a[ilda+i+1:ilda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(kx+(i+1)*incX)) - if nonUnit { - x[ix] *= a[ilda+i] - } - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - ilda := i * lda - xi := x[i] - f32.AxpyUnitary(xi, a[ilda:ilda+i], x[:i]) - if nonUnit { - x[i] *= a[i*lda+i] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - ilda := i * lda - xi := x[ix] - f32.AxpyInc(xi, a[ilda:ilda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - if nonUnit { - x[ix] *= a[ilda+i] - } - ix += incX - } -} - -// Strsv solves one of the systems of equations -// -// A * x = b if tA == blas.NoTrans -// Aᵀ * x = b if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix, and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Strsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - if n == 1 { - if d == blas.NonUnit { - x[0] /= a[0] - } - return - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - nonUnit := d == blas.NonUnit - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - var sum float32 - atmp := a[i*lda+i+1 : i*lda+n] - for j, v := range atmp { - jv := i + j + 1 - sum += x[jv] * v - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda+i] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - var sum float32 - jx := ix + incX - atmp := a[i*lda+i+1 : i*lda+n] - for _, v := range atmp { - sum += x[jx] * v - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda+i] - } - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - var sum float32 - atmp := a[i*lda : i*lda+i] - for j, v := range atmp { - sum += x[j] * v - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda+i] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx - var sum float32 - atmp := a[i*lda : i*lda+i] - for _, v := range atmp { - sum += x[jx] * v - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda+i] - } - ix += incX - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if nonUnit { - x[i] /= a[i*lda+i] - } - xi := x[i] - atmp := a[i*lda+i+1 : i*lda+n] - for j, v := range atmp { - jv := j + i + 1 - x[jv] -= v * xi - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - if nonUnit { - x[ix] /= a[i*lda+i] - } - xi := x[ix] - jx := kx + (i+1)*incX - atmp := a[i*lda+i+1 : i*lda+n] - for _, v := range atmp { - x[jx] -= v * xi - jx += incX - } - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[i] /= a[i*lda+i] - } - xi := x[i] - atmp := a[i*lda : i*lda+i] - for j, v := range atmp { - x[j] -= v * xi - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[ix] /= a[i*lda+i] - } - xi := x[ix] - jx := kx - atmp := a[i*lda : i*lda+i] - for _, v := range atmp { - x[jx] -= v * xi - jx += incX - } - ix -= incX - } -} - -// Ssymv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where A is an n×n symmetric matrix, x and y are vectors, and alpha and -// beta are scalars. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Ssymv(ul blas.Uplo, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up start points - var kx, ky int - if incX < 0 { - kx = -(n - 1) * incX - } - if incY < 0 { - ky = -(n - 1) * incY - } - - // Form y = beta * y - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - f32.ScalUnitary(beta, y[:n]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f32.ScalInc(beta, y, uintptr(n), uintptr(incY)) - } else { - f32.ScalInc(beta, y, uintptr(n), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - if n == 1 { - y[0] += alpha * a[0] * x[0] - return - } - - if ul == blas.Upper { - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - xv := x[i] * alpha - sum := x[i] * a[i*lda+i] - jy := ky + (i+1)*incY - atmp := a[i*lda+i+1 : i*lda+n] - for j, v := range atmp { - jp := j + i + 1 - sum += x[jp] * v - y[jy] += xv * v - jy += incY - } - y[iy] += alpha * sum - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - xv := x[ix] * alpha - sum := x[ix] * a[i*lda+i] - jx := kx + (i+1)*incX - jy := ky + (i+1)*incY - atmp := a[i*lda+i+1 : i*lda+n] - for _, v := range atmp { - sum += x[jx] * v - y[jy] += xv * v - jx += incX - jy += incY - } - y[iy] += alpha * sum - ix += incX - iy += incY - } - return - } - // Cases where a is lower triangular. - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - jy := ky - xv := alpha * x[i] - atmp := a[i*lda : i*lda+i] - var sum float32 - for j, v := range atmp { - sum += x[j] * v - y[jy] += xv * v - jy += incY - } - sum += x[i] * a[i*lda+i] - sum *= alpha - y[iy] += sum - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx - jy := ky - xv := alpha * x[ix] - atmp := a[i*lda : i*lda+i] - var sum float32 - for _, v := range atmp { - sum += x[jx] * v - y[jy] += xv * v - jx += incX - jy += incY - } - sum += x[ix] * a[i*lda+i] - sum *= alpha - y[iy] += sum - ix += incX - iy += incY - } -} - -// Stbmv performs one of the matrix-vector operations -// -// x = A * x if tA == blas.NoTrans -// x = Aᵀ * x if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular band matrix with k+1 diagonals, and x is a vector. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Stbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - - nonunit := d != blas.Unit - - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - u := min(1+k, n-i) - var sum float32 - atmp := a[i*lda:] - xtmp := x[i:] - for j := 1; j < u; j++ { - sum += xtmp[j] * atmp[j] - } - if nonunit { - sum += xtmp[0] * atmp[0] - } else { - sum += xtmp[0] - } - x[i] = sum - } - return - } - ix := kx - for i := 0; i < n; i++ { - u := min(1+k, n-i) - var sum float32 - atmp := a[i*lda:] - jx := incX - for j := 1; j < u; j++ { - sum += x[ix+jx] * atmp[j] - jx += incX - } - if nonunit { - sum += x[ix] * atmp[0] - } else { - sum += x[ix] - } - x[ix] = sum - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - l := max(0, k-i) - atmp := a[i*lda:] - var sum float32 - for j := l; j < k; j++ { - sum += x[i-k+j] * atmp[j] - } - if nonunit { - sum += x[i] * atmp[k] - } else { - sum += x[i] - } - x[i] = sum - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - l := max(0, k-i) - atmp := a[i*lda:] - var sum float32 - jx := l * incX - for j := l; j < k; j++ { - sum += x[ix-k*incX+jx] * atmp[j] - jx += incX - } - if nonunit { - sum += x[ix] * atmp[k] - } else { - sum += x[ix] - } - x[ix] = sum - ix -= incX - } - return - } - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - u := k + 1 - if i < u { - u = i + 1 - } - var sum float32 - for j := 1; j < u; j++ { - sum += x[i-j] * a[(i-j)*lda+j] - } - if nonunit { - sum += x[i] * a[i*lda] - } else { - sum += x[i] - } - x[i] = sum - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - u := k + 1 - if i < u { - u = i + 1 - } - var sum float32 - jx := incX - for j := 1; j < u; j++ { - sum += x[ix-jx] * a[(i-j)*lda+j] - jx += incX - } - if nonunit { - sum += x[ix] * a[i*lda] - } else { - sum += x[ix] - } - x[ix] = sum - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - u := k - if i+k >= n { - u = n - i - 1 - } - var sum float32 - for j := 0; j < u; j++ { - sum += x[i+j+1] * a[(i+j+1)*lda+k-j-1] - } - if nonunit { - sum += x[i] * a[i*lda+k] - } else { - sum += x[i] - } - x[i] = sum - } - return - } - ix := kx - for i := 0; i < n; i++ { - u := k - if i+k >= n { - u = n - i - 1 - } - var ( - sum float32 - jx int - ) - for j := 0; j < u; j++ { - sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] - jx += incX - } - if nonunit { - sum += x[ix] * a[i*lda+k] - } else { - sum += x[ix] - } - x[ix] = sum - ix += incX - } -} - -// Stpmv performs one of the matrix-vector operations -// -// x = A * x if tA == blas.NoTrans -// x = Aᵀ * x if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix in packed format, and x is a vector. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Stpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float32, x []float32, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - - nonUnit := d == blas.NonUnit - var offset int // Offset is the index of (i,i) - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if nonUnit { - xi *= ap[offset] - } - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - for j, v := range atmp { - xi += v * xtmp[j] - } - x[i] = xi - offset += n - i - } - return - } - ix := kx - for i := 0; i < n; i++ { - xix := x[ix] - if nonUnit { - xix *= ap[offset] - } - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - for _, v := range atmp { - xix += v * x[jx] - jx += incX - } - x[ix] = xix - offset += n - i - ix += incX - } - return - } - if incX == 1 { - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xi := x[i] - if nonUnit { - xi *= ap[offset] - } - atmp := ap[offset-i : offset] - for j, v := range atmp { - xi += v * x[j] - } - x[i] = xi - offset -= i + 1 - } - return - } - ix := kx + (n-1)*incX - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xix := x[ix] - if nonUnit { - xix *= ap[offset] - } - atmp := ap[offset-i : offset] - jx := kx - for _, v := range atmp { - xix += v * x[jx] - jx += incX - } - x[ix] = xix - offset -= i + 1 - ix -= incX - } - return - } - // Cases where ap is transposed. - if ul == blas.Upper { - if incX == 1 { - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xi := x[i] - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - for j, v := range atmp { - xtmp[j] += v * xi - } - if nonUnit { - x[i] *= ap[offset] - } - offset -= n - i + 1 - } - return - } - ix := kx + (n-1)*incX - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xix := x[ix] - jx := kx + (i+1)*incX - atmp := ap[offset+1 : offset+n-i] - for _, v := range atmp { - x[jx] += v * xix - jx += incX - } - if nonUnit { - x[ix] *= ap[offset] - } - offset -= n - i + 1 - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - atmp := ap[offset-i : offset] - for j, v := range atmp { - x[j] += v * xi - } - if nonUnit { - x[i] *= ap[offset] - } - offset += i + 2 - } - return - } - ix := kx - for i := 0; i < n; i++ { - xix := x[ix] - jx := kx - atmp := ap[offset-i : offset] - for _, v := range atmp { - x[jx] += v * xix - jx += incX - } - if nonUnit { - x[ix] *= ap[offset] - } - ix += incX - offset += i + 2 - } -} - -// Stbsv solves one of the systems of equations -// -// A * x = b if tA == blas.NoTrans -// Aᵀ * x = b if tA == blas.Trans or tA == blas.ConjTrans -// -// where A is an n×n triangular band matrix with k+1 diagonals, -// and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Stbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - nonUnit := d == blas.NonUnit - // Form x = A^-1 x. - // Several cases below use subslices for speed improvement. - // The incX != 1 cases usually do not because incX may be negative. - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - bands := k - if i+bands >= n { - bands = n - i - 1 - } - atmp := a[i*lda+1:] - xtmp := x[i+1 : i+bands+1] - var sum float32 - for j, v := range xtmp { - sum += v * atmp[j] - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - max := k + 1 - if i+max > n { - max = n - i - } - atmp := a[i*lda:] - var ( - jx int - sum float32 - ) - for j := 1; j < max; j++ { - jx += incX - sum += x[ix+jx] * atmp[j] - } - x[ix] -= sum - if nonUnit { - x[ix] /= atmp[0] - } - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - atmp := a[i*lda+k-bands:] - xtmp := x[i-bands : i] - var sum float32 - for j, v := range xtmp { - sum += v * atmp[j] - } - x[i] -= sum - if nonUnit { - x[i] /= atmp[bands] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - atmp := a[i*lda+k-bands:] - var ( - sum float32 - jx int - ) - for j := 0; j < bands; j++ { - sum += x[ix-bands*incX+jx] * atmp[j] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= atmp[bands] - } - ix += incX - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - var sum float32 - for j := 0; j < bands; j++ { - sum += x[i-bands+j] * a[(i-bands+j)*lda+bands-j] - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - var ( - sum float32 - jx int - ) - for j := 0; j < bands; j++ { - sum += x[ix-bands*incX+jx] * a[(i-bands+j)*lda+bands-j] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda] - } - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - bands := k - if i+bands >= n { - bands = n - i - 1 - } - var sum float32 - xtmp := x[i+1 : i+1+bands] - for j, v := range xtmp { - sum += v * a[(i+j+1)*lda+k-j-1] - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda+k] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - bands := k - if i+bands >= n { - bands = n - i - 1 - } - var ( - sum float32 - jx int - ) - for j := 0; j < bands; j++ { - sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda+k] - } - ix -= incX - } -} - -// Ssbmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where A is an n×n symmetric band matrix with k super-diagonals, x and y are -// vectors, and alpha and beta are scalars. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Ssbmv(ul blas.Uplo, n, k int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up indexes - lenX := n - lenY := n - var kx, ky int - if incX < 0 { - kx = -(lenX - 1) * incX - } - if incY < 0 { - ky = -(lenY - 1) * incY - } - - // Form y = beta * y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - f32.ScalUnitary(beta, y[:n]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f32.ScalInc(beta, y, uintptr(n), uintptr(incY)) - } else { - f32.ScalInc(beta, y, uintptr(n), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - if ul == blas.Upper { - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - atmp := a[i*lda:] - tmp := alpha * x[i] - sum := tmp * atmp[0] - u := min(k, n-i-1) - jy := incY - for j := 1; j <= u; j++ { - v := atmp[j] - sum += alpha * x[i+j] * v - y[iy+jy] += tmp * v - jy += incY - } - y[iy] += sum - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - atmp := a[i*lda:] - tmp := alpha * x[ix] - sum := tmp * atmp[0] - u := min(k, n-i-1) - jx := incX - jy := incY - for j := 1; j <= u; j++ { - v := atmp[j] - sum += alpha * x[ix+jx] * v - y[iy+jy] += tmp * v - jx += incX - jy += incY - } - y[iy] += sum - ix += incX - iy += incY - } - return - } - - // Cases where a has bands below the diagonal. - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - l := max(0, k-i) - tmp := alpha * x[i] - jy := l * incY - atmp := a[i*lda:] - for j := l; j < k; j++ { - v := atmp[j] - y[iy] += alpha * v * x[i-k+j] - y[iy-k*incY+jy] += tmp * v - jy += incY - } - y[iy] += tmp * atmp[k] - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - l := max(0, k-i) - tmp := alpha * x[ix] - jx := l * incX - jy := l * incY - atmp := a[i*lda:] - for j := l; j < k; j++ { - v := atmp[j] - y[iy] += alpha * v * x[ix-k*incX+jx] - y[iy-k*incY+jy] += tmp * v - jx += incX - jy += incY - } - y[iy] += tmp * atmp[k] - ix += incX - iy += incY - } -} - -// Ssyr performs the symmetric rank-one update -// -// A += alpha * x * xᵀ -// -// where A is an n×n symmetric matrix, and x is a vector. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Ssyr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, a []float32, lda int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - lenX := n - var kx int - if incX < 0 { - kx = -(lenX - 1) * incX - } - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - tmp := x[i] * alpha - if tmp != 0 { - atmp := a[i*lda+i : i*lda+n] - xtmp := x[i:n] - for j, v := range xtmp { - atmp[j] += v * tmp - } - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - tmp := x[ix] * alpha - if tmp != 0 { - jx := ix - atmp := a[i*lda:] - for j := i; j < n; j++ { - atmp[j] += x[jx] * tmp - jx += incX - } - } - ix += incX - } - return - } - // Cases where a is lower triangular. - if incX == 1 { - for i := 0; i < n; i++ { - tmp := x[i] * alpha - if tmp != 0 { - atmp := a[i*lda:] - xtmp := x[:i+1] - for j, v := range xtmp { - atmp[j] += tmp * v - } - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - tmp := x[ix] * alpha - if tmp != 0 { - atmp := a[i*lda:] - jx := kx - for j := 0; j < i+1; j++ { - atmp[j] += tmp * x[jx] - jx += incX - } - } - ix += incX - } -} - -// Ssyr2 performs the symmetric rank-two update -// -// A += alpha * x * yᵀ + alpha * y * xᵀ -// -// where A is an n×n symmetric matrix, x and y are vectors, and alpha is a scalar. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Ssyr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var ky, kx int - if incY < 0 { - ky = -(n - 1) * incY - } - if incX < 0 { - kx = -(n - 1) * incX - } - if ul == blas.Upper { - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - xi := x[i] - yi := y[i] - atmp := a[i*lda:] - for j := i; j < n; j++ { - atmp[j] += alpha * (xi*y[j] + x[j]*yi) - } - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx + i*incX - jy := ky + i*incY - xi := x[ix] - yi := y[iy] - atmp := a[i*lda:] - for j := i; j < n; j++ { - atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) - jx += incX - jy += incY - } - ix += incX - iy += incY - } - return - } - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - xi := x[i] - yi := y[i] - atmp := a[i*lda:] - for j := 0; j <= i; j++ { - atmp[j] += alpha * (xi*y[j] + x[j]*yi) - } - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx - jy := ky - xi := x[ix] - yi := y[iy] - atmp := a[i*lda:] - for j := 0; j <= i; j++ { - atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) - jx += incX - jy += incY - } - ix += incX - iy += incY - } -} - -// Stpsv solves one of the systems of equations -// -// A * x = b if tA == blas.NoTrans -// Aᵀ * x = b if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix in packed format, and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Stpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float32, x []float32, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - - nonUnit := d == blas.NonUnit - var offset int // Offset is the index of (i,i) - if tA == blas.NoTrans { - if ul == blas.Upper { - offset = n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - var sum float32 - for j, v := range atmp { - sum += v * xtmp[j] - } - x[i] -= sum - if nonUnit { - x[i] /= ap[offset] - } - offset -= n - i + 1 - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - var sum float32 - for _, v := range atmp { - sum += v * x[jx] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= ap[offset] - } - ix -= incX - offset -= n - i + 1 - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset-i : offset] - var sum float32 - for j, v := range atmp { - sum += v * x[j] - } - x[i] -= sum - if nonUnit { - x[i] /= ap[offset] - } - offset += i + 2 - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx - atmp := ap[offset-i : offset] - var sum float32 - for _, v := range atmp { - sum += v * x[jx] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= ap[offset] - } - ix += incX - offset += i + 2 - } - return - } - // Cases where ap is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if nonUnit { - x[i] /= ap[offset] - } - xi := x[i] - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - for j, v := range atmp { - xtmp[j] -= v * xi - } - offset += n - i - } - return - } - ix := kx - for i := 0; i < n; i++ { - if nonUnit { - x[ix] /= ap[offset] - } - xix := x[ix] - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - for _, v := range atmp { - x[jx] -= v * xix - jx += incX - } - ix += incX - offset += n - i - } - return - } - if incX == 1 { - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[i] /= ap[offset] - } - xi := x[i] - atmp := ap[offset-i : offset] - for j, v := range atmp { - x[j] -= v * xi - } - offset -= i + 1 - } - return - } - ix := kx + (n-1)*incX - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[ix] /= ap[offset] - } - xix := x[ix] - atmp := ap[offset-i : offset] - jx := kx - for _, v := range atmp { - x[jx] -= v * xix - jx += incX - } - ix -= incX - offset -= i + 1 - } -} - -// Sspmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where A is an n×n symmetric matrix in packed format, x and y are vectors, -// and alpha and beta are scalars. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, ap []float32, x []float32, incX int, beta float32, y []float32, incY int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up start points - var kx, ky int - if incX < 0 { - kx = -(n - 1) * incX - } - if incY < 0 { - ky = -(n - 1) * incY - } - - // Form y = beta * y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - f32.ScalUnitary(beta, y[:n]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f32.ScalInc(beta, y, uintptr(n), uintptr(incY)) - } else { - f32.ScalInc(beta, y, uintptr(n), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - if n == 1 { - y[0] += alpha * ap[0] * x[0] - return - } - var offset int // Offset is the index of (i,i). - if ul == blas.Upper { - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - xv := x[i] * alpha - sum := ap[offset] * x[i] - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - jy := ky + (i+1)*incY - for j, v := range atmp { - sum += v * xtmp[j] - y[jy] += v * xv - jy += incY - } - y[iy] += alpha * sum - iy += incY - offset += n - i - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - xv := x[ix] * alpha - sum := ap[offset] * x[ix] - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - jy := ky + (i+1)*incY - for _, v := range atmp { - sum += v * x[jx] - y[jy] += v * xv - jx += incX - jy += incY - } - y[iy] += alpha * sum - ix += incX - iy += incY - offset += n - i - } - return - } - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - xv := x[i] * alpha - atmp := ap[offset-i : offset] - jy := ky - var sum float32 - for j, v := range atmp { - sum += v * x[j] - y[jy] += v * xv - jy += incY - } - sum += ap[offset] * x[i] - y[iy] += alpha * sum - iy += incY - offset += i + 2 - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - xv := x[ix] * alpha - atmp := ap[offset-i : offset] - jx := kx - jy := ky - var sum float32 - for _, v := range atmp { - sum += v * x[jx] - y[jy] += v * xv - jx += incX - jy += incY - } - - sum += ap[offset] * x[ix] - y[iy] += alpha * sum - ix += incX - iy += incY - offset += i + 2 - } -} - -// Sspr performs the symmetric rank-one operation -// -// A += alpha * x * xᵀ -// -// where A is an n×n symmetric matrix in packed format, x is a vector, and -// alpha is a scalar. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, ap []float32) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - lenX := n - var kx int - if incX < 0 { - kx = -(lenX - 1) * incX - } - var offset int // Offset is the index of (i,i). - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset:] - xv := alpha * x[i] - xtmp := x[i:n] - for j, v := range xtmp { - atmp[j] += xv * v - } - offset += n - i - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx + i*incX - atmp := ap[offset:] - xv := alpha * x[ix] - for j := 0; j < n-i; j++ { - atmp[j] += xv * x[jx] - jx += incX - } - ix += incX - offset += n - i - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset-i:] - xv := alpha * x[i] - xtmp := x[:i+1] - for j, v := range xtmp { - atmp[j] += xv * v - } - offset += i + 2 - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx - atmp := ap[offset-i:] - xv := alpha * x[ix] - for j := 0; j <= i; j++ { - atmp[j] += xv * x[jx] - jx += incX - } - ix += incX - offset += i + 2 - } -} - -// Sspr2 performs the symmetric rank-2 update -// -// A += alpha * x * yᵀ + alpha * y * xᵀ -// -// where A is an n×n symmetric matrix in packed format, x and y are vectors, -// and alpha is a scalar. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sspr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, ap []float32) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var ky, kx int - if incY < 0 { - ky = -(n - 1) * incY - } - if incX < 0 { - kx = -(n - 1) * incX - } - var offset int // Offset is the index of (i,i). - if ul == blas.Upper { - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset:] - xi := x[i] - yi := y[i] - xtmp := x[i:n] - ytmp := y[i:n] - for j, v := range xtmp { - atmp[j] += alpha * (xi*ytmp[j] + v*yi) - } - offset += n - i - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx + i*incX - jy := ky + i*incY - atmp := ap[offset:] - xi := x[ix] - yi := y[iy] - for j := 0; j < n-i; j++ { - atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) - jx += incX - jy += incY - } - ix += incX - iy += incY - offset += n - i - } - return - } - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset-i:] - xi := x[i] - yi := y[i] - xtmp := x[:i+1] - for j, v := range xtmp { - atmp[j] += alpha * (xi*y[j] + v*yi) - } - offset += i + 2 - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx - jy := ky - atmp := ap[offset-i:] - for j := 0; j <= i; j++ { - atmp[j] += alpha * (x[ix]*y[jy] + x[jx]*y[iy]) - jx += incX - jy += incY - } - ix += incX - iy += incY - offset += i + 2 - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2float64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2float64.go deleted file mode 100644 index 19b9c7e1..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level2float64.go +++ /dev/null @@ -1,2366 +0,0 @@ -// Copyright ©2014 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f64" -) - -var _ blas.Float64Level2 = Implementation{} - -// Dger performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func (Implementation) Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - f64.Ger(uintptr(m), uintptr(n), - alpha, - x, uintptr(incX), - y, uintptr(incY), - a, uintptr(lda)) -} - -// Dgbmv performs one of the matrix-vector operations -// -// y = alpha * A * x + beta * y if tA == blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if tA == blas.Trans or blas.ConjTrans -// -// where A is an m×n band matrix with kL sub-diagonals and kU super-diagonals, -// x and y are vectors, and alpha and beta are scalars. -func (Implementation) Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if kL < 0 { - panic(kLLT0) - } - if kU < 0 { - panic(kULT0) - } - if lda < kL+kU+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { - panic(shortA) - } - lenX := m - lenY := n - if tA == blas.NoTrans { - lenX = n - lenY = m - } - if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - var kx, ky int - if incX < 0 { - kx = -(lenX - 1) * incX - } - if incY < 0 { - ky = -(lenY - 1) * incY - } - - // Form y = beta * y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:lenY] { - y[i] = 0 - } - } else { - f64.ScalUnitary(beta, y[:lenY]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < lenY; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f64.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) - } else { - f64.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - // i and j are indices of the compacted banded matrix. - // off is the offset into the dense matrix (off + j = densej) - nCol := kU + 1 + kL - if tA == blas.NoTrans { - iy := ky - if incX == 1 { - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - xtmp := x[off : off+u-l] - var sum float64 - for j, v := range atmp { - sum += xtmp[j] * v - } - y[iy] += sum * alpha - iy += incY - } - return - } - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - jx := kx - var sum float64 - for _, v := range atmp { - sum += x[off*incX+jx] * v - jx += incX - } - y[iy] += sum * alpha - iy += incY - } - return - } - if incX == 1 { - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - tmp := alpha * x[i] - jy := ky - for _, v := range atmp { - y[jy+off*incY] += tmp * v - jy += incY - } - } - return - } - ix := kx - for i := 0; i < min(m, n+kL); i++ { - l := max(0, kL-i) - u := min(nCol, n+kL-i) - off := max(0, i-kL) - atmp := a[i*lda+l : i*lda+u] - tmp := alpha * x[ix] - jy := ky - for _, v := range atmp { - y[jy+off*incY] += tmp * v - jy += incY - } - ix += incX - } -} - -// Dgemv computes -// -// y = alpha * A * x + beta * y if tA = blas.NoTrans -// y = alpha * Aᵀ * x + beta * y if tA = blas.Trans or blas.ConjTrans -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func (Implementation) Dgemv(tA blas.Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - // Set up indexes - lenX := m - lenY := n - if tA == blas.NoTrans { - lenX = n - lenY = m - } - - // Quick return if possible - if m == 0 || n == 0 { - return - } - - if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { - panic(shortX) - } - if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { - panic(shortY) - } - if len(a) < lda*(m-1)+n { - panic(shortA) - } - - // Quick return if possible - if alpha == 0 && beta == 1 { - return - } - - if alpha == 0 { - // First form y = beta * y - if incY > 0 { - Implementation{}.Dscal(lenY, beta, y, incY) - } else { - Implementation{}.Dscal(lenY, beta, y, -incY) - } - return - } - - // Form y = alpha * A * x + y - if tA == blas.NoTrans { - f64.GemvN(uintptr(m), uintptr(n), alpha, a, uintptr(lda), x, uintptr(incX), beta, y, uintptr(incY)) - return - } - // Cases where a is transposed. - f64.GemvT(uintptr(m), uintptr(n), alpha, a, uintptr(lda), x, uintptr(incX), beta, y, uintptr(incY)) -} - -// Dtrmv performs one of the matrix-vector operations -// -// x = A * x if tA == blas.NoTrans -// x = Aᵀ * x if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix, and x is a vector. -func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - nonUnit := d != blas.Unit - if n == 1 { - if nonUnit { - x[0] *= a[0] - } - return - } - var kx int - if incX <= 0 { - kx = -(n - 1) * incX - } - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - ilda := i * lda - var tmp float64 - if nonUnit { - tmp = a[ilda+i] * x[i] - } else { - tmp = x[i] - } - x[i] = tmp + f64.DotUnitary(a[ilda+i+1:ilda+n], x[i+1:n]) - } - return - } - ix := kx - for i := 0; i < n; i++ { - ilda := i * lda - var tmp float64 - if nonUnit { - tmp = a[ilda+i] * x[ix] - } else { - tmp = x[ix] - } - x[ix] = tmp + f64.DotInc(x, a[ilda+i+1:ilda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - ilda := i * lda - var tmp float64 - if nonUnit { - tmp += a[ilda+i] * x[i] - } else { - tmp = x[i] - } - x[i] = tmp + f64.DotUnitary(a[ilda:ilda+i], x[:i]) - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - ilda := i * lda - var tmp float64 - if nonUnit { - tmp = a[ilda+i] * x[ix] - } else { - tmp = x[ix] - } - x[ix] = tmp + f64.DotInc(x, a[ilda:ilda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) - ix -= incX - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - ilda := i * lda - xi := x[i] - f64.AxpyUnitary(xi, a[ilda+i+1:ilda+n], x[i+1:n]) - if nonUnit { - x[i] *= a[ilda+i] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - ilda := i * lda - xi := x[ix] - f64.AxpyInc(xi, a[ilda+i+1:ilda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(kx+(i+1)*incX)) - if nonUnit { - x[ix] *= a[ilda+i] - } - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - ilda := i * lda - xi := x[i] - f64.AxpyUnitary(xi, a[ilda:ilda+i], x[:i]) - if nonUnit { - x[i] *= a[i*lda+i] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - ilda := i * lda - xi := x[ix] - f64.AxpyInc(xi, a[ilda:ilda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) - if nonUnit { - x[ix] *= a[ilda+i] - } - ix += incX - } -} - -// Dtrsv solves one of the systems of equations -// -// A * x = b if tA == blas.NoTrans -// Aᵀ * x = b if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix, and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func (Implementation) Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - if n == 1 { - if d == blas.NonUnit { - x[0] /= a[0] - } - return - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - nonUnit := d == blas.NonUnit - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - var sum float64 - atmp := a[i*lda+i+1 : i*lda+n] - for j, v := range atmp { - jv := i + j + 1 - sum += x[jv] * v - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda+i] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - var sum float64 - jx := ix + incX - atmp := a[i*lda+i+1 : i*lda+n] - for _, v := range atmp { - sum += x[jx] * v - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda+i] - } - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - var sum float64 - atmp := a[i*lda : i*lda+i] - for j, v := range atmp { - sum += x[j] * v - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda+i] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx - var sum float64 - atmp := a[i*lda : i*lda+i] - for _, v := range atmp { - sum += x[jx] * v - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda+i] - } - ix += incX - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if nonUnit { - x[i] /= a[i*lda+i] - } - xi := x[i] - atmp := a[i*lda+i+1 : i*lda+n] - for j, v := range atmp { - jv := j + i + 1 - x[jv] -= v * xi - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - if nonUnit { - x[ix] /= a[i*lda+i] - } - xi := x[ix] - jx := kx + (i+1)*incX - atmp := a[i*lda+i+1 : i*lda+n] - for _, v := range atmp { - x[jx] -= v * xi - jx += incX - } - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[i] /= a[i*lda+i] - } - xi := x[i] - atmp := a[i*lda : i*lda+i] - for j, v := range atmp { - x[j] -= v * xi - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[ix] /= a[i*lda+i] - } - xi := x[ix] - jx := kx - atmp := a[i*lda : i*lda+i] - for _, v := range atmp { - x[jx] -= v * xi - jx += incX - } - ix -= incX - } -} - -// Dsymv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where A is an n×n symmetric matrix, x and y are vectors, and alpha and -// beta are scalars. -func (Implementation) Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+n { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up start points - var kx, ky int - if incX < 0 { - kx = -(n - 1) * incX - } - if incY < 0 { - ky = -(n - 1) * incY - } - - // Form y = beta * y - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - f64.ScalUnitary(beta, y[:n]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f64.ScalInc(beta, y, uintptr(n), uintptr(incY)) - } else { - f64.ScalInc(beta, y, uintptr(n), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - if n == 1 { - y[0] += alpha * a[0] * x[0] - return - } - - if ul == blas.Upper { - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - xv := x[i] * alpha - sum := x[i] * a[i*lda+i] - jy := ky + (i+1)*incY - atmp := a[i*lda+i+1 : i*lda+n] - for j, v := range atmp { - jp := j + i + 1 - sum += x[jp] * v - y[jy] += xv * v - jy += incY - } - y[iy] += alpha * sum - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - xv := x[ix] * alpha - sum := x[ix] * a[i*lda+i] - jx := kx + (i+1)*incX - jy := ky + (i+1)*incY - atmp := a[i*lda+i+1 : i*lda+n] - for _, v := range atmp { - sum += x[jx] * v - y[jy] += xv * v - jx += incX - jy += incY - } - y[iy] += alpha * sum - ix += incX - iy += incY - } - return - } - // Cases where a is lower triangular. - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - jy := ky - xv := alpha * x[i] - atmp := a[i*lda : i*lda+i] - var sum float64 - for j, v := range atmp { - sum += x[j] * v - y[jy] += xv * v - jy += incY - } - sum += x[i] * a[i*lda+i] - sum *= alpha - y[iy] += sum - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx - jy := ky - xv := alpha * x[ix] - atmp := a[i*lda : i*lda+i] - var sum float64 - for _, v := range atmp { - sum += x[jx] * v - y[jy] += xv * v - jx += incX - jy += incY - } - sum += x[ix] * a[i*lda+i] - sum *= alpha - y[iy] += sum - ix += incX - iy += incY - } -} - -// Dtbmv performs one of the matrix-vector operations -// -// x = A * x if tA == blas.NoTrans -// x = Aᵀ * x if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular band matrix with k+1 diagonals, and x is a vector. -func (Implementation) Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - - nonunit := d != blas.Unit - - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - u := min(1+k, n-i) - var sum float64 - atmp := a[i*lda:] - xtmp := x[i:] - for j := 1; j < u; j++ { - sum += xtmp[j] * atmp[j] - } - if nonunit { - sum += xtmp[0] * atmp[0] - } else { - sum += xtmp[0] - } - x[i] = sum - } - return - } - ix := kx - for i := 0; i < n; i++ { - u := min(1+k, n-i) - var sum float64 - atmp := a[i*lda:] - jx := incX - for j := 1; j < u; j++ { - sum += x[ix+jx] * atmp[j] - jx += incX - } - if nonunit { - sum += x[ix] * atmp[0] - } else { - sum += x[ix] - } - x[ix] = sum - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - l := max(0, k-i) - atmp := a[i*lda:] - var sum float64 - for j := l; j < k; j++ { - sum += x[i-k+j] * atmp[j] - } - if nonunit { - sum += x[i] * atmp[k] - } else { - sum += x[i] - } - x[i] = sum - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - l := max(0, k-i) - atmp := a[i*lda:] - var sum float64 - jx := l * incX - for j := l; j < k; j++ { - sum += x[ix-k*incX+jx] * atmp[j] - jx += incX - } - if nonunit { - sum += x[ix] * atmp[k] - } else { - sum += x[ix] - } - x[ix] = sum - ix -= incX - } - return - } - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - u := k + 1 - if i < u { - u = i + 1 - } - var sum float64 - for j := 1; j < u; j++ { - sum += x[i-j] * a[(i-j)*lda+j] - } - if nonunit { - sum += x[i] * a[i*lda] - } else { - sum += x[i] - } - x[i] = sum - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - u := k + 1 - if i < u { - u = i + 1 - } - var sum float64 - jx := incX - for j := 1; j < u; j++ { - sum += x[ix-jx] * a[(i-j)*lda+j] - jx += incX - } - if nonunit { - sum += x[ix] * a[i*lda] - } else { - sum += x[ix] - } - x[ix] = sum - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - u := k - if i+k >= n { - u = n - i - 1 - } - var sum float64 - for j := 0; j < u; j++ { - sum += x[i+j+1] * a[(i+j+1)*lda+k-j-1] - } - if nonunit { - sum += x[i] * a[i*lda+k] - } else { - sum += x[i] - } - x[i] = sum - } - return - } - ix := kx - for i := 0; i < n; i++ { - u := k - if i+k >= n { - u = n - i - 1 - } - var ( - sum float64 - jx int - ) - for j := 0; j < u; j++ { - sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] - jx += incX - } - if nonunit { - sum += x[ix] * a[i*lda+k] - } else { - sum += x[ix] - } - x[ix] = sum - ix += incX - } -} - -// Dtpmv performs one of the matrix-vector operations -// -// x = A * x if tA == blas.NoTrans -// x = Aᵀ * x if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix in packed format, and x is a vector. -func (Implementation) Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - - nonUnit := d == blas.NonUnit - var offset int // Offset is the index of (i,i) - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - if nonUnit { - xi *= ap[offset] - } - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - for j, v := range atmp { - xi += v * xtmp[j] - } - x[i] = xi - offset += n - i - } - return - } - ix := kx - for i := 0; i < n; i++ { - xix := x[ix] - if nonUnit { - xix *= ap[offset] - } - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - for _, v := range atmp { - xix += v * x[jx] - jx += incX - } - x[ix] = xix - offset += n - i - ix += incX - } - return - } - if incX == 1 { - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xi := x[i] - if nonUnit { - xi *= ap[offset] - } - atmp := ap[offset-i : offset] - for j, v := range atmp { - xi += v * x[j] - } - x[i] = xi - offset -= i + 1 - } - return - } - ix := kx + (n-1)*incX - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xix := x[ix] - if nonUnit { - xix *= ap[offset] - } - atmp := ap[offset-i : offset] - jx := kx - for _, v := range atmp { - xix += v * x[jx] - jx += incX - } - x[ix] = xix - offset -= i + 1 - ix -= incX - } - return - } - // Cases where ap is transposed. - if ul == blas.Upper { - if incX == 1 { - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xi := x[i] - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - for j, v := range atmp { - xtmp[j] += v * xi - } - if nonUnit { - x[i] *= ap[offset] - } - offset -= n - i + 1 - } - return - } - ix := kx + (n-1)*incX - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - xix := x[ix] - jx := kx + (i+1)*incX - atmp := ap[offset+1 : offset+n-i] - for _, v := range atmp { - x[jx] += v * xix - jx += incX - } - if nonUnit { - x[ix] *= ap[offset] - } - offset -= n - i + 1 - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - xi := x[i] - atmp := ap[offset-i : offset] - for j, v := range atmp { - x[j] += v * xi - } - if nonUnit { - x[i] *= ap[offset] - } - offset += i + 2 - } - return - } - ix := kx - for i := 0; i < n; i++ { - xix := x[ix] - jx := kx - atmp := ap[offset-i : offset] - for _, v := range atmp { - x[jx] += v * xix - jx += incX - } - if nonUnit { - x[ix] *= ap[offset] - } - ix += incX - offset += i + 2 - } -} - -// Dtbsv solves one of the systems of equations -// -// A * x = b if tA == blas.NoTrans -// Aᵀ * x = b if tA == blas.Trans or tA == blas.ConjTrans -// -// where A is an n×n triangular band matrix with k+1 diagonals, -// and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func (Implementation) Dtbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - nonUnit := d == blas.NonUnit - // Form x = A^-1 x. - // Several cases below use subslices for speed improvement. - // The incX != 1 cases usually do not because incX may be negative. - if tA == blas.NoTrans { - if ul == blas.Upper { - if incX == 1 { - for i := n - 1; i >= 0; i-- { - bands := k - if i+bands >= n { - bands = n - i - 1 - } - atmp := a[i*lda+1:] - xtmp := x[i+1 : i+bands+1] - var sum float64 - for j, v := range xtmp { - sum += v * atmp[j] - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - max := k + 1 - if i+max > n { - max = n - i - } - atmp := a[i*lda:] - var ( - jx int - sum float64 - ) - for j := 1; j < max; j++ { - jx += incX - sum += x[ix+jx] * atmp[j] - } - x[ix] -= sum - if nonUnit { - x[ix] /= atmp[0] - } - ix -= incX - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - atmp := a[i*lda+k-bands:] - xtmp := x[i-bands : i] - var sum float64 - for j, v := range xtmp { - sum += v * atmp[j] - } - x[i] -= sum - if nonUnit { - x[i] /= atmp[bands] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - atmp := a[i*lda+k-bands:] - var ( - sum float64 - jx int - ) - for j := 0; j < bands; j++ { - sum += x[ix-bands*incX+jx] * atmp[j] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= atmp[bands] - } - ix += incX - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - var sum float64 - for j := 0; j < bands; j++ { - sum += x[i-bands+j] * a[(i-bands+j)*lda+bands-j] - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda] - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - bands := k - if i-k < 0 { - bands = i - } - var ( - sum float64 - jx int - ) - for j := 0; j < bands; j++ { - sum += x[ix-bands*incX+jx] * a[(i-bands+j)*lda+bands-j] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda] - } - ix += incX - } - return - } - if incX == 1 { - for i := n - 1; i >= 0; i-- { - bands := k - if i+bands >= n { - bands = n - i - 1 - } - var sum float64 - xtmp := x[i+1 : i+1+bands] - for j, v := range xtmp { - sum += v * a[(i+j+1)*lda+k-j-1] - } - x[i] -= sum - if nonUnit { - x[i] /= a[i*lda+k] - } - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - bands := k - if i+bands >= n { - bands = n - i - 1 - } - var ( - sum float64 - jx int - ) - for j := 0; j < bands; j++ { - sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= a[i*lda+k] - } - ix -= incX - } -} - -// Dsbmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where A is an n×n symmetric band matrix with k super-diagonals, x and y are -// vectors, and alpha and beta are scalars. -func (Implementation) Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if lda < k+1 { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(n-1)+k+1 { - panic(shortA) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up indexes - lenX := n - lenY := n - var kx, ky int - if incX < 0 { - kx = -(lenX - 1) * incX - } - if incY < 0 { - ky = -(lenY - 1) * incY - } - - // Form y = beta * y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - f64.ScalUnitary(beta, y[:n]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f64.ScalInc(beta, y, uintptr(n), uintptr(incY)) - } else { - f64.ScalInc(beta, y, uintptr(n), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - if ul == blas.Upper { - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - atmp := a[i*lda:] - tmp := alpha * x[i] - sum := tmp * atmp[0] - u := min(k, n-i-1) - jy := incY - for j := 1; j <= u; j++ { - v := atmp[j] - sum += alpha * x[i+j] * v - y[iy+jy] += tmp * v - jy += incY - } - y[iy] += sum - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - atmp := a[i*lda:] - tmp := alpha * x[ix] - sum := tmp * atmp[0] - u := min(k, n-i-1) - jx := incX - jy := incY - for j := 1; j <= u; j++ { - v := atmp[j] - sum += alpha * x[ix+jx] * v - y[iy+jy] += tmp * v - jx += incX - jy += incY - } - y[iy] += sum - ix += incX - iy += incY - } - return - } - - // Cases where a has bands below the diagonal. - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - l := max(0, k-i) - tmp := alpha * x[i] - jy := l * incY - atmp := a[i*lda:] - for j := l; j < k; j++ { - v := atmp[j] - y[iy] += alpha * v * x[i-k+j] - y[iy-k*incY+jy] += tmp * v - jy += incY - } - y[iy] += tmp * atmp[k] - iy += incY - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - l := max(0, k-i) - tmp := alpha * x[ix] - jx := l * incX - jy := l * incY - atmp := a[i*lda:] - for j := l; j < k; j++ { - v := atmp[j] - y[iy] += alpha * v * x[ix-k*incX+jx] - y[iy-k*incY+jy] += tmp * v - jx += incX - jy += incY - } - y[iy] += tmp * atmp[k] - ix += incX - iy += incY - } -} - -// Dsyr performs the symmetric rank-one update -// -// A += alpha * x * xᵀ -// -// where A is an n×n symmetric matrix, and x is a vector. -func (Implementation) Dsyr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - lenX := n - var kx int - if incX < 0 { - kx = -(lenX - 1) * incX - } - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - tmp := x[i] * alpha - if tmp != 0 { - atmp := a[i*lda+i : i*lda+n] - xtmp := x[i:n] - for j, v := range xtmp { - atmp[j] += v * tmp - } - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - tmp := x[ix] * alpha - if tmp != 0 { - jx := ix - atmp := a[i*lda:] - for j := i; j < n; j++ { - atmp[j] += x[jx] * tmp - jx += incX - } - } - ix += incX - } - return - } - // Cases where a is lower triangular. - if incX == 1 { - for i := 0; i < n; i++ { - tmp := x[i] * alpha - if tmp != 0 { - atmp := a[i*lda:] - xtmp := x[:i+1] - for j, v := range xtmp { - atmp[j] += tmp * v - } - } - } - return - } - ix := kx - for i := 0; i < n; i++ { - tmp := x[ix] * alpha - if tmp != 0 { - atmp := a[i*lda:] - jx := kx - for j := 0; j < i+1; j++ { - atmp[j] += tmp * x[jx] - jx += incX - } - } - ix += incX - } -} - -// Dsyr2 performs the symmetric rank-two update -// -// A += alpha * x * yᵀ + alpha * y * xᵀ -// -// where A is an n×n symmetric matrix, x and y are vectors, and alpha is a scalar. -func (Implementation) Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic(badLdA) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(a) < lda*(n-1)+n { - panic(shortA) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var ky, kx int - if incY < 0 { - ky = -(n - 1) * incY - } - if incX < 0 { - kx = -(n - 1) * incX - } - if ul == blas.Upper { - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - xi := x[i] - yi := y[i] - atmp := a[i*lda:] - for j := i; j < n; j++ { - atmp[j] += alpha * (xi*y[j] + x[j]*yi) - } - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx + i*incX - jy := ky + i*incY - xi := x[ix] - yi := y[iy] - atmp := a[i*lda:] - for j := i; j < n; j++ { - atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) - jx += incX - jy += incY - } - ix += incX - iy += incY - } - return - } - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - xi := x[i] - yi := y[i] - atmp := a[i*lda:] - for j := 0; j <= i; j++ { - atmp[j] += alpha * (xi*y[j] + x[j]*yi) - } - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx - jy := ky - xi := x[ix] - yi := y[iy] - atmp := a[i*lda:] - for j := 0; j <= i; j++ { - atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) - jx += incX - jy += incY - } - ix += incX - iy += incY - } -} - -// Dtpsv solves one of the systems of equations -// -// A * x = b if tA == blas.NoTrans -// Aᵀ * x = b if tA == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular matrix in packed format, and x and b are vectors. -// -// At entry to the function, x contains the values of b, and the result is -// stored in-place into x. -// -// No test for singularity or near-singularity is included in this -// routine. Such tests must be performed before calling this routine. -func (Implementation) Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - - var kx int - if incX < 0 { - kx = -(n - 1) * incX - } - - nonUnit := d == blas.NonUnit - var offset int // Offset is the index of (i,i) - if tA == blas.NoTrans { - if ul == blas.Upper { - offset = n*(n+1)/2 - 1 - if incX == 1 { - for i := n - 1; i >= 0; i-- { - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - var sum float64 - for j, v := range atmp { - sum += v * xtmp[j] - } - x[i] -= sum - if nonUnit { - x[i] /= ap[offset] - } - offset -= n - i + 1 - } - return - } - ix := kx + (n-1)*incX - for i := n - 1; i >= 0; i-- { - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - var sum float64 - for _, v := range atmp { - sum += v * x[jx] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= ap[offset] - } - ix -= incX - offset -= n - i + 1 - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset-i : offset] - var sum float64 - for j, v := range atmp { - sum += v * x[j] - } - x[i] -= sum - if nonUnit { - x[i] /= ap[offset] - } - offset += i + 2 - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx - atmp := ap[offset-i : offset] - var sum float64 - for _, v := range atmp { - sum += v * x[jx] - jx += incX - } - x[ix] -= sum - if nonUnit { - x[ix] /= ap[offset] - } - ix += incX - offset += i + 2 - } - return - } - // Cases where ap is transposed. - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - if nonUnit { - x[i] /= ap[offset] - } - xi := x[i] - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - for j, v := range atmp { - xtmp[j] -= v * xi - } - offset += n - i - } - return - } - ix := kx - for i := 0; i < n; i++ { - if nonUnit { - x[ix] /= ap[offset] - } - xix := x[ix] - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - for _, v := range atmp { - x[jx] -= v * xix - jx += incX - } - ix += incX - offset += n - i - } - return - } - if incX == 1 { - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[i] /= ap[offset] - } - xi := x[i] - atmp := ap[offset-i : offset] - for j, v := range atmp { - x[j] -= v * xi - } - offset -= i + 1 - } - return - } - ix := kx + (n-1)*incX - offset = n*(n+1)/2 - 1 - for i := n - 1; i >= 0; i-- { - if nonUnit { - x[ix] /= ap[offset] - } - xix := x[ix] - atmp := ap[offset-i : offset] - jx := kx - for _, v := range atmp { - x[jx] -= v * xix - jx += incX - } - ix -= incX - offset -= i + 1 - } -} - -// Dspmv performs the matrix-vector operation -// -// y = alpha * A * x + beta * y -// -// where A is an n×n symmetric matrix in packed format, x and y are vectors, -// and alpha and beta are scalars. -func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, ap []float64, x []float64, incX int, beta float64, y []float64, incY int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - // Set up start points - var kx, ky int - if incX < 0 { - kx = -(n - 1) * incX - } - if incY < 0 { - ky = -(n - 1) * incY - } - - // Form y = beta * y. - if beta != 1 { - if incY == 1 { - if beta == 0 { - for i := range y[:n] { - y[i] = 0 - } - } else { - f64.ScalUnitary(beta, y[:n]) - } - } else { - iy := ky - if beta == 0 { - for i := 0; i < n; i++ { - y[iy] = 0 - iy += incY - } - } else { - if incY > 0 { - f64.ScalInc(beta, y, uintptr(n), uintptr(incY)) - } else { - f64.ScalInc(beta, y, uintptr(n), uintptr(-incY)) - } - } - } - } - - if alpha == 0 { - return - } - - if n == 1 { - y[0] += alpha * ap[0] * x[0] - return - } - var offset int // Offset is the index of (i,i). - if ul == blas.Upper { - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - xv := x[i] * alpha - sum := ap[offset] * x[i] - atmp := ap[offset+1 : offset+n-i] - xtmp := x[i+1:] - jy := ky + (i+1)*incY - for j, v := range atmp { - sum += v * xtmp[j] - y[jy] += v * xv - jy += incY - } - y[iy] += alpha * sum - iy += incY - offset += n - i - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - xv := x[ix] * alpha - sum := ap[offset] * x[ix] - atmp := ap[offset+1 : offset+n-i] - jx := kx + (i+1)*incX - jy := ky + (i+1)*incY - for _, v := range atmp { - sum += v * x[jx] - y[jy] += v * xv - jx += incX - jy += incY - } - y[iy] += alpha * sum - ix += incX - iy += incY - offset += n - i - } - return - } - if incX == 1 { - iy := ky - for i := 0; i < n; i++ { - xv := x[i] * alpha - atmp := ap[offset-i : offset] - jy := ky - var sum float64 - for j, v := range atmp { - sum += v * x[j] - y[jy] += v * xv - jy += incY - } - sum += ap[offset] * x[i] - y[iy] += alpha * sum - iy += incY - offset += i + 2 - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - xv := x[ix] * alpha - atmp := ap[offset-i : offset] - jx := kx - jy := ky - var sum float64 - for _, v := range atmp { - sum += v * x[jx] - y[jy] += v * xv - jx += incX - jy += incY - } - - sum += ap[offset] * x[ix] - y[iy] += alpha * sum - ix += incX - iy += incY - offset += i + 2 - } -} - -// Dspr performs the symmetric rank-one operation -// -// A += alpha * x * xᵀ -// -// where A is an n×n symmetric matrix in packed format, x is a vector, and -// alpha is a scalar. -func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, ap []float64) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - lenX := n - var kx int - if incX < 0 { - kx = -(lenX - 1) * incX - } - var offset int // Offset is the index of (i,i). - if ul == blas.Upper { - if incX == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset:] - xv := alpha * x[i] - xtmp := x[i:n] - for j, v := range xtmp { - atmp[j] += xv * v - } - offset += n - i - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx + i*incX - atmp := ap[offset:] - xv := alpha * x[ix] - for j := 0; j < n-i; j++ { - atmp[j] += xv * x[jx] - jx += incX - } - ix += incX - offset += n - i - } - return - } - if incX == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset-i:] - xv := alpha * x[i] - xtmp := x[:i+1] - for j, v := range xtmp { - atmp[j] += xv * v - } - offset += i + 2 - } - return - } - ix := kx - for i := 0; i < n; i++ { - jx := kx - atmp := ap[offset-i:] - xv := alpha * x[ix] - for j := 0; j <= i; j++ { - atmp[j] += xv * x[jx] - jx += incX - } - ix += incX - offset += i + 2 - } -} - -// Dspr2 performs the symmetric rank-2 update -// -// A += alpha * x * yᵀ + alpha * y * xᵀ -// -// where A is an n×n symmetric matrix in packed format, x and y are vectors, -// and alpha is a scalar. -func (Implementation) Dspr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, ap []float64) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if n < 0 { - panic(nLT0) - } - if incX == 0 { - panic(zeroIncX) - } - if incY == 0 { - panic(zeroIncY) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { - panic(shortX) - } - if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { - panic(shortY) - } - if len(ap) < n*(n+1)/2 { - panic(shortAP) - } - - // Quick return if possible. - if alpha == 0 { - return - } - - var ky, kx int - if incY < 0 { - ky = -(n - 1) * incY - } - if incX < 0 { - kx = -(n - 1) * incX - } - var offset int // Offset is the index of (i,i). - if ul == blas.Upper { - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset:] - xi := x[i] - yi := y[i] - xtmp := x[i:n] - ytmp := y[i:n] - for j, v := range xtmp { - atmp[j] += alpha * (xi*ytmp[j] + v*yi) - } - offset += n - i - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx + i*incX - jy := ky + i*incY - atmp := ap[offset:] - xi := x[ix] - yi := y[iy] - for j := 0; j < n-i; j++ { - atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) - jx += incX - jy += incY - } - ix += incX - iy += incY - offset += n - i - } - return - } - if incX == 1 && incY == 1 { - for i := 0; i < n; i++ { - atmp := ap[offset-i:] - xi := x[i] - yi := y[i] - xtmp := x[:i+1] - for j, v := range xtmp { - atmp[j] += alpha * (xi*y[j] + v*yi) - } - offset += i + 2 - } - return - } - ix := kx - iy := ky - for i := 0; i < n; i++ { - jx := kx - jy := ky - atmp := ap[offset-i:] - for j := 0; j <= i; j++ { - atmp[j] += alpha * (x[ix]*y[jy] + x[jx]*y[iy]) - jx += incX - jy += incY - } - ix += incX - iy += incY - offset += i + 2 - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go deleted file mode 100644 index bfff8c55..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go +++ /dev/null @@ -1,1751 +0,0 @@ -// Copyright ©2019 The Gonum 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 gonum - -import ( - "math/cmplx" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/c128" -) - -var _ blas.Complex128Level3 = Implementation{} - -// Zgemm performs one of the matrix-matrix operations -// -// C = alpha * op(A) * op(B) + beta * C -// -// where op(X) is one of -// -// op(X) = X or op(X) = Xᵀ or op(X) = Xᴴ, -// -// alpha and beta are scalars, and A, B and C are matrices, with op(A) an m×k matrix, -// op(B) a k×n matrix and C an m×n matrix. -func (Implementation) Zgemm(tA, tB blas.Transpose, m, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { - switch tA { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch tB { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - } - rowA, colA := m, k - if tA != blas.NoTrans { - rowA, colA = k, m - } - if lda < max(1, colA) { - panic(badLdA) - } - rowB, colB := k, n - if tB != blas.NoTrans { - rowB, colB = n, k - } - if ldb < max(1, colB) { - panic(badLdB) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (rowA-1)*lda+colA { - panic(shortA) - } - if len(b) < (rowB-1)*ldb+colB { - panic(shortB) - } - if len(c) < (m-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if beta == 0 { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - } - return - } - - switch tA { - case blas.NoTrans: - switch tB { - case blas.NoTrans: - // Form C = alpha * A * B + beta * C. - for i := 0; i < m; i++ { - switch { - case beta == 0: - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - case beta != 1: - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[i*lda+l] - for j := 0; j < n; j++ { - c[i*ldc+j] += tmp * b[l*ldb+j] - } - } - } - case blas.Trans: - // Form C = alpha * A * Bᵀ + beta * C. - for i := 0; i < m; i++ { - switch { - case beta == 0: - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - case beta != 1: - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[i*lda+l] - for j := 0; j < n; j++ { - c[i*ldc+j] += tmp * b[j*ldb+l] - } - } - } - case blas.ConjTrans: - // Form C = alpha * A * Bᴴ + beta * C. - for i := 0; i < m; i++ { - switch { - case beta == 0: - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - case beta != 1: - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[i*lda+l] - for j := 0; j < n; j++ { - c[i*ldc+j] += tmp * cmplx.Conj(b[j*ldb+l]) - } - } - } - } - case blas.Trans: - switch tB { - case blas.NoTrans: - // Form C = alpha * Aᵀ * B + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex128 - for l := 0; l < k; l++ { - tmp += a[l*lda+i] * b[l*ldb+j] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.Trans: - // Form C = alpha * Aᵀ * Bᵀ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex128 - for l := 0; l < k; l++ { - tmp += a[l*lda+i] * b[j*ldb+l] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.ConjTrans: - // Form C = alpha * Aᵀ * Bᴴ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex128 - for l := 0; l < k; l++ { - tmp += a[l*lda+i] * cmplx.Conj(b[j*ldb+l]) - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - case blas.ConjTrans: - switch tB { - case blas.NoTrans: - // Form C = alpha * Aᴴ * B + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex128 - for l := 0; l < k; l++ { - tmp += cmplx.Conj(a[l*lda+i]) * b[l*ldb+j] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.Trans: - // Form C = alpha * Aᴴ * Bᵀ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex128 - for l := 0; l < k; l++ { - tmp += cmplx.Conj(a[l*lda+i]) * b[j*ldb+l] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.ConjTrans: - // Form C = alpha * Aᴴ * Bᴴ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex128 - for l := 0; l < k; l++ { - tmp += cmplx.Conj(a[l*lda+i]) * cmplx.Conj(b[j*ldb+l]) - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - } -} - -// Zhemm performs one of the matrix-matrix operations -// -// C = alpha*A*B + beta*C if side == blas.Left -// C = alpha*B*A + beta*C if side == blas.Right -// -// where alpha and beta are scalars, A is an m×m or n×n hermitian matrix and B -// and C are m×n matrices. The imaginary parts of the diagonal elements of A are -// assumed to be zero. -func (Implementation) Zhemm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(na-1)+na { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - if len(c) < ldc*(m-1)+n { - panic(shortC) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - if alpha == 0 { - if beta == 0 { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - c128.ScalUnitary(beta, ci) - } - } - return - } - - if side == blas.Left { - // Form C = alpha*A*B + beta*C. - for i := 0; i < m; i++ { - atmp := alpha * complex(real(a[i*lda+i]), 0) - bi := b[i*ldb : i*ldb+n] - ci := c[i*ldc : i*ldc+n] - if beta == 0 { - for j, bij := range bi { - ci[j] = atmp * bij - } - } else { - for j, bij := range bi { - ci[j] = atmp*bij + beta*ci[j] - } - } - if uplo == blas.Upper { - for k := 0; k < i; k++ { - atmp = alpha * cmplx.Conj(a[k*lda+i]) - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * a[i*lda+k] - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } else { - for k := 0; k < i; k++ { - atmp = alpha * a[i*lda+k] - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * cmplx.Conj(a[k*lda+i]) - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } - } - } else { - // Form C = alpha*B*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := n - 1; j >= 0; j-- { - abij := alpha * b[i*ldb+j] - aj := a[j*lda+j+1 : j*lda+n] - bi := b[i*ldb+j+1 : i*ldb+n] - ci := c[i*ldc+j+1 : i*ldc+n] - var tmp complex128 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * cmplx.Conj(ajk) - } - ajj := complex(real(a[j*lda+j]), 0) - if beta == 0 { - c[i*ldc+j] = abij*ajj + alpha*tmp - } else { - c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } else { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - abij := alpha * b[i*ldb+j] - aj := a[j*lda : j*lda+j] - bi := b[i*ldb : i*ldb+j] - ci := c[i*ldc : i*ldc+j] - var tmp complex128 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * cmplx.Conj(ajk) - } - ajj := complex(real(a[j*lda+j]), 0) - if beta == 0 { - c[i*ldc+j] = abij*ajj + alpha*tmp - } else { - c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - } -} - -// Zherk performs one of the hermitian rank-k operations -// -// C = alpha*A*Aᴴ + beta*C if trans == blas.NoTrans -// C = alpha*Aᴴ*A + beta*C if trans == blas.ConjTrans -// -// where alpha and beta are real scalars, C is an n×n hermitian matrix and A is -// an n×k matrix in the first case and a k×n matrix in the second case. -// -// The imaginary parts of the diagonal elements of C are assumed to be zero, and -// on return they will be set to zero. -func (Implementation) Zherk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) { - var rowA, colA int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - rowA, colA = n, k - case blas.ConjTrans: - rowA, colA = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, colA): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (rowA-1)*lda+colA { - panic(shortA) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ci[0] = complex(beta*real(ci[0]), 0) - if i != n-1 { - c128.DscalUnitary(beta, ci[1:]) - } - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - if i != 0 { - c128.DscalUnitary(beta, ci[:i]) - } - ci[i] = complex(beta*real(ci[i]), 0) - } - } - } - return - } - - calpha := complex(alpha, 0) - if trans == blas.NoTrans { - // Form C = alpha*A*Aᴴ + beta*C. - cbeta := complex(beta, 0) - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ai := a[i*lda : i*lda+k] - switch { - case beta == 0: - // Handle the i-th diagonal element of C. - ci[0] = complex(alpha*real(c128.DotcUnitary(ai, ai)), 0) - // Handle the remaining elements on the i-th row of C. - for jc := range ci[1:] { - j := i + 1 + jc - ci[jc+1] = calpha * c128.DotcUnitary(a[j*lda:j*lda+k], ai) - } - case beta != 1: - cii := calpha*c128.DotcUnitary(ai, ai) + cbeta*ci[0] - ci[0] = complex(real(cii), 0) - for jc, cij := range ci[1:] { - j := i + 1 + jc - ci[jc+1] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij - } - default: - cii := calpha*c128.DotcUnitary(ai, ai) + ci[0] - ci[0] = complex(real(cii), 0) - for jc, cij := range ci[1:] { - j := i + 1 + jc - ci[jc+1] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cij - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - ai := a[i*lda : i*lda+k] - switch { - case beta == 0: - // Handle the first i-1 elements on the i-th row of C. - for j := range ci[:i] { - ci[j] = calpha * c128.DotcUnitary(a[j*lda:j*lda+k], ai) - } - // Handle the i-th diagonal element of C. - ci[i] = complex(alpha*real(c128.DotcUnitary(ai, ai)), 0) - case beta != 1: - for j, cij := range ci[:i] { - ci[j] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij - } - cii := calpha*c128.DotcUnitary(ai, ai) + cbeta*ci[i] - ci[i] = complex(real(cii), 0) - default: - for j, cij := range ci[:i] { - ci[j] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cij - } - cii := calpha*c128.DotcUnitary(ai, ai) + ci[i] - ci[i] = complex(real(cii), 0) - } - } - } - } else { - // Form C = alpha*Aᴴ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - c128.DscalUnitary(beta, ci) - ci[0] = complex(real(ci[0]), 0) - default: - ci[0] = complex(real(ci[0]), 0) - } - for j := 0; j < k; j++ { - aji := cmplx.Conj(a[j*lda+i]) - if aji != 0 { - c128.AxpyUnitary(calpha*aji, a[j*lda+i:j*lda+n], ci) - } - } - c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - c128.DscalUnitary(beta, ci) - ci[i] = complex(real(ci[i]), 0) - default: - ci[i] = complex(real(ci[i]), 0) - } - for j := 0; j < k; j++ { - aji := cmplx.Conj(a[j*lda+i]) - if aji != 0 { - c128.AxpyUnitary(calpha*aji, a[j*lda:j*lda+i+1], ci) - } - } - c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) - } - } - } -} - -// Zher2k performs one of the hermitian rank-2k operations -// -// C = alpha*A*Bᴴ + conj(alpha)*B*Aᴴ + beta*C if trans == blas.NoTrans -// C = alpha*Aᴴ*B + conj(alpha)*Bᴴ*A + beta*C if trans == blas.ConjTrans -// -// where alpha and beta are scalars with beta real, C is an n×n hermitian matrix -// and A and B are n×k matrices in the first case and k×n matrices in the second case. -// -// The imaginary parts of the diagonal elements of C are assumed to be zero, and -// on return they will be set to zero. -func (Implementation) Zher2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta float64, c []complex128, ldc int) { - var row, col int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - row, col = n, k - case blas.ConjTrans: - row, col = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, col): - panic(badLdA) - case ldb < max(1, col): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (row-1)*lda+col { - panic(shortA) - } - if len(b) < (row-1)*ldb+col { - panic(shortB) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ci[0] = complex(beta*real(ci[0]), 0) - if i != n-1 { - c128.DscalUnitary(beta, ci[1:]) - } - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - if i != 0 { - c128.DscalUnitary(beta, ci[:i]) - } - ci[i] = complex(beta*real(ci[i]), 0) - } - } - } - return - } - - conjalpha := cmplx.Conj(alpha) - cbeta := complex(beta, 0) - if trans == blas.NoTrans { - // Form C = alpha*A*Bᴴ + conj(alpha)*B*Aᴴ + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i+1 : i*ldc+n] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) - c[i*ldc+i] = complex(real(cii), 0) - for jc := range ci { - j := i + 1 + jc - ci[jc] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) - } - } else { - cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] - c[i*ldc+i] = complex(real(cii), 0) - for jc, cij := range ci { - j := i + 1 + jc - ci[jc] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - for j := range ci { - ci[j] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) - } - cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) - c[i*ldc+i] = complex(real(cii), 0) - } else { - for j, cij := range ci { - ci[j] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij - } - cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] - c[i*ldc+i] = complex(real(cii), 0) - } - } - } - } else { - // Form C = alpha*Aᴴ*B + conj(alpha)*Bᴴ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - c128.DscalUnitary(beta, ci) - ci[0] = complex(real(ci[0]), 0) - default: - ci[0] = complex(real(ci[0]), 0) - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c128.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb+i:j*ldb+n], ci) - } - if bji != 0 { - c128.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda+i:j*lda+n], ci) - } - } - ci[0] = complex(real(ci[0]), 0) - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - c128.DscalUnitary(beta, ci) - ci[i] = complex(real(ci[i]), 0) - default: - ci[i] = complex(real(ci[i]), 0) - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c128.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb:j*ldb+i+1], ci) - } - if bji != 0 { - c128.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda:j*lda+i+1], ci) - } - } - ci[i] = complex(real(ci[i]), 0) - } - } - } -} - -// Zsymm performs one of the matrix-matrix operations -// -// C = alpha*A*B + beta*C if side == blas.Left -// C = alpha*B*A + beta*C if side == blas.Right -// -// where alpha and beta are scalars, A is an m×m or n×n symmetric matrix and B -// and C are m×n matrices. -func (Implementation) Zsymm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(na-1)+na { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - if len(c) < ldc*(m-1)+n { - panic(shortC) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - if alpha == 0 { - if beta == 0 { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - c128.ScalUnitary(beta, ci) - } - } - return - } - - if side == blas.Left { - // Form C = alpha*A*B + beta*C. - for i := 0; i < m; i++ { - atmp := alpha * a[i*lda+i] - bi := b[i*ldb : i*ldb+n] - ci := c[i*ldc : i*ldc+n] - if beta == 0 { - for j, bij := range bi { - ci[j] = atmp * bij - } - } else { - for j, bij := range bi { - ci[j] = atmp*bij + beta*ci[j] - } - } - if uplo == blas.Upper { - for k := 0; k < i; k++ { - atmp = alpha * a[k*lda+i] - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * a[i*lda+k] - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } else { - for k := 0; k < i; k++ { - atmp = alpha * a[i*lda+k] - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * a[k*lda+i] - c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } - } - } else { - // Form C = alpha*B*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := n - 1; j >= 0; j-- { - abij := alpha * b[i*ldb+j] - aj := a[j*lda+j+1 : j*lda+n] - bi := b[i*ldb+j+1 : i*ldb+n] - ci := c[i*ldc+j+1 : i*ldc+n] - var tmp complex128 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * ajk - } - if beta == 0 { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp - } else { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } else { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - abij := alpha * b[i*ldb+j] - aj := a[j*lda : j*lda+j] - bi := b[i*ldb : i*ldb+j] - ci := c[i*ldc : i*ldc+j] - var tmp complex128 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * ajk - } - if beta == 0 { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp - } else { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - } -} - -// Zsyrk performs one of the symmetric rank-k operations -// -// C = alpha*A*Aᵀ + beta*C if trans == blas.NoTrans -// C = alpha*Aᵀ*A + beta*C if trans == blas.Trans -// -// where alpha and beta are scalars, C is an n×n symmetric matrix and A is -// an n×k matrix in the first case and a k×n matrix in the second case. -func (Implementation) Zsyrk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) { - var rowA, colA int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - rowA, colA = n, k - case blas.Trans: - rowA, colA = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, colA): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (rowA-1)*lda+colA { - panic(shortA) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - c128.ScalUnitary(beta, ci) - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - c128.ScalUnitary(beta, ci) - } - } - } - return - } - - if trans == blas.NoTrans { - // Form C = alpha*A*Aᵀ + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ai := a[i*lda : i*lda+k] - if beta == 0 { - for jc := range ci { - j := i + jc - ci[jc] = alpha * c128.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } else { - for jc, cij := range ci { - j := i + jc - ci[jc] = beta*cij + alpha*c128.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - ai := a[i*lda : i*lda+k] - if beta == 0 { - for j := range ci { - ci[j] = alpha * c128.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } else { - for j, cij := range ci { - ci[j] = beta*cij + alpha*c128.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } - } - } - } else { - // Form C = alpha*Aᵀ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - for jc := range ci { - ci[jc] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - if aji != 0 { - c128.AxpyUnitary(alpha*aji, a[j*lda+i:j*lda+n], ci) - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - for j := range ci { - ci[j] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - if aji != 0 { - c128.AxpyUnitary(alpha*aji, a[j*lda:j*lda+i+1], ci) - } - } - } - } - } -} - -// Zsyr2k performs one of the symmetric rank-2k operations -// -// C = alpha*A*Bᵀ + alpha*B*Aᵀ + beta*C if trans == blas.NoTrans -// C = alpha*Aᵀ*B + alpha*Bᵀ*A + beta*C if trans == blas.Trans -// -// where alpha and beta are scalars, C is an n×n symmetric matrix and A and B -// are n×k matrices in the first case and k×n matrices in the second case. -func (Implementation) Zsyr2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { - var row, col int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - row, col = n, k - case blas.Trans: - row, col = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, col): - panic(badLdA) - case ldb < max(1, col): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (row-1)*lda+col { - panic(shortA) - } - if len(b) < (row-1)*ldb+col { - panic(shortB) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - c128.ScalUnitary(beta, ci) - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - c128.ScalUnitary(beta, ci) - } - } - } - return - } - - if trans == blas.NoTrans { - // Form C = alpha*A*Bᵀ + alpha*B*Aᵀ + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - for jc := range ci { - j := i + jc - ci[jc] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) - } - } else { - for jc, cij := range ci { - j := i + jc - ci[jc] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - for j := range ci { - ci[j] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) - } - } else { - for j, cij := range ci { - ci[j] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij - } - } - } - } - } else { - // Form C = alpha*Aᵀ*B + alpha*Bᵀ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - for jc := range ci { - ci[jc] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c128.AxpyUnitary(alpha*aji, b[j*ldb+i:j*ldb+n], ci) - } - if bji != 0 { - c128.AxpyUnitary(alpha*bji, a[j*lda+i:j*lda+n], ci) - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - for j := range ci { - ci[j] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c128.AxpyUnitary(alpha*aji, b[j*ldb:j*ldb+i+1], ci) - } - if bji != 0 { - c128.AxpyUnitary(alpha*bji, a[j*lda:j*lda+i+1], ci) - } - } - } - } - } -} - -// Ztrmm performs one of the matrix-matrix operations -// -// B = alpha * op(A) * B if side == blas.Left, -// B = alpha * B * op(A) if side == blas.Right, -// -// where alpha is a scalar, B is an m×n matrix, A is a unit, or non-unit, -// upper or lower triangular matrix and op(A) is one of -// -// op(A) = A if trans == blas.NoTrans, -// op(A) = Aᵀ if trans == blas.Trans, -// op(A) = Aᴴ if trans == blas.ConjTrans. -func (Implementation) Ztrmm(side blas.Side, uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTranspose) - case diag != blas.Unit && diag != blas.NonUnit: - panic(badDiag) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (na-1)*lda+na { - panic(shortA) - } - if len(b) < (m-1)*ldb+n { - panic(shortB) - } - - // Quick return if possible. - if alpha == 0 { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j := range bi { - bi[j] = 0 - } - } - return - } - - noConj := trans != blas.ConjTrans - noUnit := diag == blas.NonUnit - if side == blas.Left { - if trans == blas.NoTrans { - // Form B = alpha*A*B. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - aii := alpha - if noUnit { - aii *= a[i*lda+i] - } - bi := b[i*ldb : i*ldb+n] - for j := range bi { - bi[j] *= aii - } - for ja, aij := range a[i*lda+i+1 : i*lda+m] { - j := ja + i + 1 - if aij != 0 { - c128.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) - } - } - } - } else { - for i := m - 1; i >= 0; i-- { - aii := alpha - if noUnit { - aii *= a[i*lda+i] - } - bi := b[i*ldb : i*ldb+n] - for j := range bi { - bi[j] *= aii - } - for j, aij := range a[i*lda : i*lda+i] { - if aij != 0 { - c128.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) - } - } - } - } - } else { - // Form B = alpha*Aᵀ*B or B = alpha*Aᴴ*B. - if uplo == blas.Upper { - for k := m - 1; k >= 0; k-- { - bk := b[k*ldb : k*ldb+n] - for ja, ajk := range a[k*lda+k+1 : k*lda+m] { - if ajk == 0 { - continue - } - j := k + 1 + ja - if noConj { - c128.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) - } else { - c128.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) - } - } - akk := alpha - if noUnit { - if noConj { - akk *= a[k*lda+k] - } else { - akk *= cmplx.Conj(a[k*lda+k]) - } - } - if akk != 1 { - c128.ScalUnitary(akk, bk) - } - } - } else { - for k := 0; k < m; k++ { - bk := b[k*ldb : k*ldb+n] - for j, ajk := range a[k*lda : k*lda+k] { - if ajk == 0 { - continue - } - if noConj { - c128.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) - } else { - c128.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) - } - } - akk := alpha - if noUnit { - if noConj { - akk *= a[k*lda+k] - } else { - akk *= cmplx.Conj(a[k*lda+k]) - } - } - if akk != 1 { - c128.ScalUnitary(akk, bk) - } - } - } - } - } else { - if trans == blas.NoTrans { - // Form B = alpha*B*A. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for k := n - 1; k >= 0; k-- { - abik := alpha * bi[k] - if abik == 0 { - continue - } - bi[k] = abik - if noUnit { - bi[k] *= a[k*lda+k] - } - c128.AxpyUnitary(abik, a[k*lda+k+1:k*lda+n], bi[k+1:]) - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for k := 0; k < n; k++ { - abik := alpha * bi[k] - if abik == 0 { - continue - } - bi[k] = abik - if noUnit { - bi[k] *= a[k*lda+k] - } - c128.AxpyUnitary(abik, a[k*lda:k*lda+k], bi[:k]) - } - } - } - } else { - // Form B = alpha*B*Aᵀ or B = alpha*B*Aᴴ. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j, bij := range bi { - if noConj { - if noUnit { - bij *= a[j*lda+j] - } - bij += c128.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - } else { - if noUnit { - bij *= cmplx.Conj(a[j*lda+j]) - } - bij += c128.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - } - bi[j] = alpha * bij - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - bij := bi[j] - if noConj { - if noUnit { - bij *= a[j*lda+j] - } - bij += c128.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) - } else { - if noUnit { - bij *= cmplx.Conj(a[j*lda+j]) - } - bij += c128.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) - } - bi[j] = alpha * bij - } - } - } - } - } -} - -// Ztrsm solves one of the matrix equations -// -// op(A) * X = alpha * B if side == blas.Left, -// X * op(A) = alpha * B if side == blas.Right, -// -// where alpha is a scalar, X and B are m×n matrices, A is a unit or -// non-unit, upper or lower triangular matrix and op(A) is one of -// -// op(A) = A if transA == blas.NoTrans, -// op(A) = Aᵀ if transA == blas.Trans, -// op(A) = Aᴴ if transA == blas.ConjTrans. -// -// On return the matrix X is overwritten on B. -func (Implementation) Ztrsm(side blas.Side, uplo blas.Uplo, transA blas.Transpose, diag blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case transA != blas.NoTrans && transA != blas.Trans && transA != blas.ConjTrans: - panic(badTranspose) - case diag != blas.Unit && diag != blas.NonUnit: - panic(badDiag) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (na-1)*lda+na { - panic(shortA) - } - if len(b) < (m-1)*ldb+n { - panic(shortB) - } - - if alpha == 0 { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - b[i*ldb+j] = 0 - } - } - return - } - - noConj := transA != blas.ConjTrans - noUnit := diag == blas.NonUnit - if side == blas.Left { - if transA == blas.NoTrans { - // Form B = alpha*inv(A)*B. - if uplo == blas.Upper { - for i := m - 1; i >= 0; i-- { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c128.ScalUnitary(alpha, bi) - } - for ka, aik := range a[i*lda+i+1 : i*lda+m] { - k := i + 1 + ka - if aik != 0 { - c128.AxpyUnitary(-aik, b[k*ldb:k*ldb+n], bi) - } - } - if noUnit { - c128.ScalUnitary(1/a[i*lda+i], bi) - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c128.ScalUnitary(alpha, bi) - } - for j, aij := range a[i*lda : i*lda+i] { - if aij != 0 { - c128.AxpyUnitary(-aij, b[j*ldb:j*ldb+n], bi) - } - } - if noUnit { - c128.ScalUnitary(1/a[i*lda+i], bi) - } - } - } - } else { - // Form B = alpha*inv(Aᵀ)*B or B = alpha*inv(Aᴴ)*B. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if noUnit { - if noConj { - c128.ScalUnitary(1/a[i*lda+i], bi) - } else { - c128.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) - } - } - for ja, aij := range a[i*lda+i+1 : i*lda+m] { - if aij == 0 { - continue - } - j := i + 1 + ja - if noConj { - c128.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) - } else { - c128.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) - } - } - if alpha != 1 { - c128.ScalUnitary(alpha, bi) - } - } - } else { - for i := m - 1; i >= 0; i-- { - bi := b[i*ldb : i*ldb+n] - if noUnit { - if noConj { - c128.ScalUnitary(1/a[i*lda+i], bi) - } else { - c128.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) - } - } - for j, aij := range a[i*lda : i*lda+i] { - if aij == 0 { - continue - } - if noConj { - c128.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) - } else { - c128.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) - } - } - if alpha != 1 { - c128.ScalUnitary(alpha, bi) - } - } - } - } - } else { - if transA == blas.NoTrans { - // Form B = alpha*B*inv(A). - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c128.ScalUnitary(alpha, bi) - } - for j, bij := range bi { - if bij == 0 { - continue - } - if noUnit { - bi[j] /= a[j*lda+j] - } - c128.AxpyUnitary(-bi[j], a[j*lda+j+1:j*lda+n], bi[j+1:n]) - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c128.ScalUnitary(alpha, bi) - } - for j := n - 1; j >= 0; j-- { - if bi[j] == 0 { - continue - } - if noUnit { - bi[j] /= a[j*lda+j] - } - c128.AxpyUnitary(-bi[j], a[j*lda:j*lda+j], bi[:j]) - } - } - } - } else { - // Form B = alpha*B*inv(Aᵀ) or B = alpha*B*inv(Aᴴ). - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - bij := alpha * bi[j] - if noConj { - bij -= c128.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - if noUnit { - bij /= a[j*lda+j] - } - } else { - bij -= c128.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - if noUnit { - bij /= cmplx.Conj(a[j*lda+j]) - } - } - bi[j] = bij - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j, bij := range bi { - bij *= alpha - if noConj { - bij -= c128.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) - if noUnit { - bij /= a[j*lda+j] - } - } else { - bij -= c128.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) - if noUnit { - bij /= cmplx.Conj(a[j*lda+j]) - } - } - bi[j] = bij - } - } - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go deleted file mode 100644 index b7fb5a2c..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go +++ /dev/null @@ -1,1771 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2019 The Gonum 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 gonum - -import ( - cmplx "gonum.org/v1/gonum/internal/cmplx64" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/c64" -) - -var _ blas.Complex64Level3 = Implementation{} - -// Cgemm performs one of the matrix-matrix operations -// -// C = alpha * op(A) * op(B) + beta * C -// -// where op(X) is one of -// -// op(X) = X or op(X) = Xᵀ or op(X) = Xᴴ, -// -// alpha and beta are scalars, and A, B and C are matrices, with op(A) an m×k matrix, -// op(B) a k×n matrix and C an m×n matrix. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cgemm(tA, tB blas.Transpose, m, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { - switch tA { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch tB { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - } - rowA, colA := m, k - if tA != blas.NoTrans { - rowA, colA = k, m - } - if lda < max(1, colA) { - panic(badLdA) - } - rowB, colB := k, n - if tB != blas.NoTrans { - rowB, colB = n, k - } - if ldb < max(1, colB) { - panic(badLdB) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (rowA-1)*lda+colA { - panic(shortA) - } - if len(b) < (rowB-1)*ldb+colB { - panic(shortB) - } - if len(c) < (m-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if beta == 0 { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - } - return - } - - switch tA { - case blas.NoTrans: - switch tB { - case blas.NoTrans: - // Form C = alpha * A * B + beta * C. - for i := 0; i < m; i++ { - switch { - case beta == 0: - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - case beta != 1: - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[i*lda+l] - for j := 0; j < n; j++ { - c[i*ldc+j] += tmp * b[l*ldb+j] - } - } - } - case blas.Trans: - // Form C = alpha * A * Bᵀ + beta * C. - for i := 0; i < m; i++ { - switch { - case beta == 0: - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - case beta != 1: - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[i*lda+l] - for j := 0; j < n; j++ { - c[i*ldc+j] += tmp * b[j*ldb+l] - } - } - } - case blas.ConjTrans: - // Form C = alpha * A * Bᴴ + beta * C. - for i := 0; i < m; i++ { - switch { - case beta == 0: - for j := 0; j < n; j++ { - c[i*ldc+j] = 0 - } - case beta != 1: - for j := 0; j < n; j++ { - c[i*ldc+j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[i*lda+l] - for j := 0; j < n; j++ { - c[i*ldc+j] += tmp * cmplx.Conj(b[j*ldb+l]) - } - } - } - } - case blas.Trans: - switch tB { - case blas.NoTrans: - // Form C = alpha * Aᵀ * B + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex64 - for l := 0; l < k; l++ { - tmp += a[l*lda+i] * b[l*ldb+j] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.Trans: - // Form C = alpha * Aᵀ * Bᵀ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex64 - for l := 0; l < k; l++ { - tmp += a[l*lda+i] * b[j*ldb+l] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.ConjTrans: - // Form C = alpha * Aᵀ * Bᴴ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex64 - for l := 0; l < k; l++ { - tmp += a[l*lda+i] * cmplx.Conj(b[j*ldb+l]) - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - case blas.ConjTrans: - switch tB { - case blas.NoTrans: - // Form C = alpha * Aᴴ * B + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex64 - for l := 0; l < k; l++ { - tmp += cmplx.Conj(a[l*lda+i]) * b[l*ldb+j] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.Trans: - // Form C = alpha * Aᴴ * Bᵀ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex64 - for l := 0; l < k; l++ { - tmp += cmplx.Conj(a[l*lda+i]) * b[j*ldb+l] - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - case blas.ConjTrans: - // Form C = alpha * Aᴴ * Bᴴ + beta * C. - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - var tmp complex64 - for l := 0; l < k; l++ { - tmp += cmplx.Conj(a[l*lda+i]) * cmplx.Conj(b[j*ldb+l]) - } - if beta == 0 { - c[i*ldc+j] = alpha * tmp - } else { - c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - } -} - -// Chemm performs one of the matrix-matrix operations -// -// C = alpha*A*B + beta*C if side == blas.Left -// C = alpha*B*A + beta*C if side == blas.Right -// -// where alpha and beta are scalars, A is an m×m or n×n hermitian matrix and B -// and C are m×n matrices. The imaginary parts of the diagonal elements of A are -// assumed to be zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Chemm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(na-1)+na { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - if len(c) < ldc*(m-1)+n { - panic(shortC) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - if alpha == 0 { - if beta == 0 { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - c64.ScalUnitary(beta, ci) - } - } - return - } - - if side == blas.Left { - // Form C = alpha*A*B + beta*C. - for i := 0; i < m; i++ { - atmp := alpha * complex(real(a[i*lda+i]), 0) - bi := b[i*ldb : i*ldb+n] - ci := c[i*ldc : i*ldc+n] - if beta == 0 { - for j, bij := range bi { - ci[j] = atmp * bij - } - } else { - for j, bij := range bi { - ci[j] = atmp*bij + beta*ci[j] - } - } - if uplo == blas.Upper { - for k := 0; k < i; k++ { - atmp = alpha * cmplx.Conj(a[k*lda+i]) - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * a[i*lda+k] - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } else { - for k := 0; k < i; k++ { - atmp = alpha * a[i*lda+k] - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * cmplx.Conj(a[k*lda+i]) - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } - } - } else { - // Form C = alpha*B*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := n - 1; j >= 0; j-- { - abij := alpha * b[i*ldb+j] - aj := a[j*lda+j+1 : j*lda+n] - bi := b[i*ldb+j+1 : i*ldb+n] - ci := c[i*ldc+j+1 : i*ldc+n] - var tmp complex64 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * cmplx.Conj(ajk) - } - ajj := complex(real(a[j*lda+j]), 0) - if beta == 0 { - c[i*ldc+j] = abij*ajj + alpha*tmp - } else { - c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } else { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - abij := alpha * b[i*ldb+j] - aj := a[j*lda : j*lda+j] - bi := b[i*ldb : i*ldb+j] - ci := c[i*ldc : i*ldc+j] - var tmp complex64 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * cmplx.Conj(ajk) - } - ajj := complex(real(a[j*lda+j]), 0) - if beta == 0 { - c[i*ldc+j] = abij*ajj + alpha*tmp - } else { - c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - } -} - -// Cherk performs one of the hermitian rank-k operations -// -// C = alpha*A*Aᴴ + beta*C if trans == blas.NoTrans -// C = alpha*Aᴴ*A + beta*C if trans == blas.ConjTrans -// -// where alpha and beta are real scalars, C is an n×n hermitian matrix and A is -// an n×k matrix in the first case and a k×n matrix in the second case. -// -// The imaginary parts of the diagonal elements of C are assumed to be zero, and -// on return they will be set to zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cherk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) { - var rowA, colA int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - rowA, colA = n, k - case blas.ConjTrans: - rowA, colA = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, colA): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (rowA-1)*lda+colA { - panic(shortA) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ci[0] = complex(beta*real(ci[0]), 0) - if i != n-1 { - c64.SscalUnitary(beta, ci[1:]) - } - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - if i != 0 { - c64.SscalUnitary(beta, ci[:i]) - } - ci[i] = complex(beta*real(ci[i]), 0) - } - } - } - return - } - - calpha := complex(alpha, 0) - if trans == blas.NoTrans { - // Form C = alpha*A*Aᴴ + beta*C. - cbeta := complex(beta, 0) - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ai := a[i*lda : i*lda+k] - switch { - case beta == 0: - // Handle the i-th diagonal element of C. - ci[0] = complex(alpha*real(c64.DotcUnitary(ai, ai)), 0) - // Handle the remaining elements on the i-th row of C. - for jc := range ci[1:] { - j := i + 1 + jc - ci[jc+1] = calpha * c64.DotcUnitary(a[j*lda:j*lda+k], ai) - } - case beta != 1: - cii := calpha*c64.DotcUnitary(ai, ai) + cbeta*ci[0] - ci[0] = complex(real(cii), 0) - for jc, cij := range ci[1:] { - j := i + 1 + jc - ci[jc+1] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij - } - default: - cii := calpha*c64.DotcUnitary(ai, ai) + ci[0] - ci[0] = complex(real(cii), 0) - for jc, cij := range ci[1:] { - j := i + 1 + jc - ci[jc+1] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cij - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - ai := a[i*lda : i*lda+k] - switch { - case beta == 0: - // Handle the first i-1 elements on the i-th row of C. - for j := range ci[:i] { - ci[j] = calpha * c64.DotcUnitary(a[j*lda:j*lda+k], ai) - } - // Handle the i-th diagonal element of C. - ci[i] = complex(alpha*real(c64.DotcUnitary(ai, ai)), 0) - case beta != 1: - for j, cij := range ci[:i] { - ci[j] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij - } - cii := calpha*c64.DotcUnitary(ai, ai) + cbeta*ci[i] - ci[i] = complex(real(cii), 0) - default: - for j, cij := range ci[:i] { - ci[j] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cij - } - cii := calpha*c64.DotcUnitary(ai, ai) + ci[i] - ci[i] = complex(real(cii), 0) - } - } - } - } else { - // Form C = alpha*Aᴴ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - c64.SscalUnitary(beta, ci) - ci[0] = complex(real(ci[0]), 0) - default: - ci[0] = complex(real(ci[0]), 0) - } - for j := 0; j < k; j++ { - aji := cmplx.Conj(a[j*lda+i]) - if aji != 0 { - c64.AxpyUnitary(calpha*aji, a[j*lda+i:j*lda+n], ci) - } - } - c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - c64.SscalUnitary(beta, ci) - ci[i] = complex(real(ci[i]), 0) - default: - ci[i] = complex(real(ci[i]), 0) - } - for j := 0; j < k; j++ { - aji := cmplx.Conj(a[j*lda+i]) - if aji != 0 { - c64.AxpyUnitary(calpha*aji, a[j*lda:j*lda+i+1], ci) - } - } - c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) - } - } - } -} - -// Cher2k performs one of the hermitian rank-2k operations -// -// C = alpha*A*Bᴴ + conj(alpha)*B*Aᴴ + beta*C if trans == blas.NoTrans -// C = alpha*Aᴴ*B + conj(alpha)*Bᴴ*A + beta*C if trans == blas.ConjTrans -// -// where alpha and beta are scalars with beta real, C is an n×n hermitian matrix -// and A and B are n×k matrices in the first case and k×n matrices in the second case. -// -// The imaginary parts of the diagonal elements of C are assumed to be zero, and -// on return they will be set to zero. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Cher2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta float32, c []complex64, ldc int) { - var row, col int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - row, col = n, k - case blas.ConjTrans: - row, col = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, col): - panic(badLdA) - case ldb < max(1, col): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (row-1)*lda+col { - panic(shortA) - } - if len(b) < (row-1)*ldb+col { - panic(shortB) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ci[0] = complex(beta*real(ci[0]), 0) - if i != n-1 { - c64.SscalUnitary(beta, ci[1:]) - } - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - if i != 0 { - c64.SscalUnitary(beta, ci[:i]) - } - ci[i] = complex(beta*real(ci[i]), 0) - } - } - } - return - } - - conjalpha := cmplx.Conj(alpha) - cbeta := complex(beta, 0) - if trans == blas.NoTrans { - // Form C = alpha*A*Bᴴ + conj(alpha)*B*Aᴴ + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i+1 : i*ldc+n] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) - c[i*ldc+i] = complex(real(cii), 0) - for jc := range ci { - j := i + 1 + jc - ci[jc] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) - } - } else { - cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] - c[i*ldc+i] = complex(real(cii), 0) - for jc, cij := range ci { - j := i + 1 + jc - ci[jc] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - for j := range ci { - ci[j] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) - } - cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) - c[i*ldc+i] = complex(real(cii), 0) - } else { - for j, cij := range ci { - ci[j] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij - } - cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] - c[i*ldc+i] = complex(real(cii), 0) - } - } - } - } else { - // Form C = alpha*Aᴴ*B + conj(alpha)*Bᴴ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - c64.SscalUnitary(beta, ci) - ci[0] = complex(real(ci[0]), 0) - default: - ci[0] = complex(real(ci[0]), 0) - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c64.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb+i:j*ldb+n], ci) - } - if bji != 0 { - c64.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda+i:j*lda+n], ci) - } - } - ci[0] = complex(real(ci[0]), 0) - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - c64.SscalUnitary(beta, ci) - ci[i] = complex(real(ci[i]), 0) - default: - ci[i] = complex(real(ci[i]), 0) - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c64.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb:j*ldb+i+1], ci) - } - if bji != 0 { - c64.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda:j*lda+i+1], ci) - } - } - ci[i] = complex(real(ci[i]), 0) - } - } - } -} - -// Csymm performs one of the matrix-matrix operations -// -// C = alpha*A*B + beta*C if side == blas.Left -// C = alpha*B*A + beta*C if side == blas.Right -// -// where alpha and beta are scalars, A is an m×m or n×n symmetric matrix and B -// and C are m×n matrices. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Csymm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(na-1)+na { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - if len(c) < ldc*(m-1)+n { - panic(shortC) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - if alpha == 0 { - if beta == 0 { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - c64.ScalUnitary(beta, ci) - } - } - return - } - - if side == blas.Left { - // Form C = alpha*A*B + beta*C. - for i := 0; i < m; i++ { - atmp := alpha * a[i*lda+i] - bi := b[i*ldb : i*ldb+n] - ci := c[i*ldc : i*ldc+n] - if beta == 0 { - for j, bij := range bi { - ci[j] = atmp * bij - } - } else { - for j, bij := range bi { - ci[j] = atmp*bij + beta*ci[j] - } - } - if uplo == blas.Upper { - for k := 0; k < i; k++ { - atmp = alpha * a[k*lda+i] - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * a[i*lda+k] - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } else { - for k := 0; k < i; k++ { - atmp = alpha * a[i*lda+k] - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - for k := i + 1; k < m; k++ { - atmp = alpha * a[k*lda+i] - c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) - } - } - } - } else { - // Form C = alpha*B*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := n - 1; j >= 0; j-- { - abij := alpha * b[i*ldb+j] - aj := a[j*lda+j+1 : j*lda+n] - bi := b[i*ldb+j+1 : i*ldb+n] - ci := c[i*ldc+j+1 : i*ldc+n] - var tmp complex64 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * ajk - } - if beta == 0 { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp - } else { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } else { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - abij := alpha * b[i*ldb+j] - aj := a[j*lda : j*lda+j] - bi := b[i*ldb : i*ldb+j] - ci := c[i*ldc : i*ldc+j] - var tmp complex64 - for k, ajk := range aj { - ci[k] += abij * ajk - tmp += bi[k] * ajk - } - if beta == 0 { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp - } else { - c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] - } - } - } - } - } -} - -// Csyrk performs one of the symmetric rank-k operations -// -// C = alpha*A*Aᵀ + beta*C if trans == blas.NoTrans -// C = alpha*Aᵀ*A + beta*C if trans == blas.Trans -// -// where alpha and beta are scalars, C is an n×n symmetric matrix and A is -// an n×k matrix in the first case and a k×n matrix in the second case. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Csyrk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) { - var rowA, colA int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - rowA, colA = n, k - case blas.Trans: - rowA, colA = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, colA): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (rowA-1)*lda+colA { - panic(shortA) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - c64.ScalUnitary(beta, ci) - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - c64.ScalUnitary(beta, ci) - } - } - } - return - } - - if trans == blas.NoTrans { - // Form C = alpha*A*Aᵀ + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ai := a[i*lda : i*lda+k] - if beta == 0 { - for jc := range ci { - j := i + jc - ci[jc] = alpha * c64.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } else { - for jc, cij := range ci { - j := i + jc - ci[jc] = beta*cij + alpha*c64.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - ai := a[i*lda : i*lda+k] - if beta == 0 { - for j := range ci { - ci[j] = alpha * c64.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } else { - for j, cij := range ci { - ci[j] = beta*cij + alpha*c64.DotuUnitary(ai, a[j*lda:j*lda+k]) - } - } - } - } - } else { - // Form C = alpha*Aᵀ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - for jc := range ci { - ci[jc] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - if aji != 0 { - c64.AxpyUnitary(alpha*aji, a[j*lda+i:j*lda+n], ci) - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - for j := range ci { - ci[j] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - if aji != 0 { - c64.AxpyUnitary(alpha*aji, a[j*lda:j*lda+i+1], ci) - } - } - } - } - } -} - -// Csyr2k performs one of the symmetric rank-2k operations -// -// C = alpha*A*Bᵀ + alpha*B*Aᵀ + beta*C if trans == blas.NoTrans -// C = alpha*Aᵀ*B + alpha*Bᵀ*A + beta*C if trans == blas.Trans -// -// where alpha and beta are scalars, C is an n×n symmetric matrix and A and B -// are n×k matrices in the first case and k×n matrices in the second case. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Csyr2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { - var row, col int - switch trans { - default: - panic(badTranspose) - case blas.NoTrans: - row, col = n, k - case blas.Trans: - row, col = k, n - } - switch { - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case lda < max(1, col): - panic(badLdA) - case ldb < max(1, col): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (row-1)*lda+col { - panic(shortA) - } - if len(b) < (row-1)*ldb+col { - panic(shortB) - } - if len(c) < (n-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - if alpha == 0 { - if uplo == blas.Upper { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - c64.ScalUnitary(beta, ci) - } - } - } else { - if beta == 0 { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - c64.ScalUnitary(beta, ci) - } - } - } - return - } - - if trans == blas.NoTrans { - // Form C = alpha*A*Bᵀ + alpha*B*Aᵀ + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - for jc := range ci { - j := i + jc - ci[jc] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) - } - } else { - for jc, cij := range ci { - j := i + jc - ci[jc] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - ai := a[i*lda : i*lda+k] - bi := b[i*ldb : i*ldb+k] - if beta == 0 { - for j := range ci { - ci[j] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) - } - } else { - for j, cij := range ci { - ci[j] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij - } - } - } - } - } else { - // Form C = alpha*Aᵀ*B + alpha*Bᵀ*A + beta*C. - if uplo == blas.Upper { - for i := 0; i < n; i++ { - ci := c[i*ldc+i : i*ldc+n] - switch { - case beta == 0: - for jc := range ci { - ci[jc] = 0 - } - case beta != 1: - for jc := range ci { - ci[jc] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c64.AxpyUnitary(alpha*aji, b[j*ldb+i:j*ldb+n], ci) - } - if bji != 0 { - c64.AxpyUnitary(alpha*bji, a[j*lda+i:j*lda+n], ci) - } - } - } - } else { - for i := 0; i < n; i++ { - ci := c[i*ldc : i*ldc+i+1] - switch { - case beta == 0: - for j := range ci { - ci[j] = 0 - } - case beta != 1: - for j := range ci { - ci[j] *= beta - } - } - for j := 0; j < k; j++ { - aji := a[j*lda+i] - bji := b[j*ldb+i] - if aji != 0 { - c64.AxpyUnitary(alpha*aji, b[j*ldb:j*ldb+i+1], ci) - } - if bji != 0 { - c64.AxpyUnitary(alpha*bji, a[j*lda:j*lda+i+1], ci) - } - } - } - } - } -} - -// Ctrmm performs one of the matrix-matrix operations -// -// B = alpha * op(A) * B if side == blas.Left, -// B = alpha * B * op(A) if side == blas.Right, -// -// where alpha is a scalar, B is an m×n matrix, A is a unit, or non-unit, -// upper or lower triangular matrix and op(A) is one of -// -// op(A) = A if trans == blas.NoTrans, -// op(A) = Aᵀ if trans == blas.Trans, -// op(A) = Aᴴ if trans == blas.ConjTrans. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctrmm(side blas.Side, uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTranspose) - case diag != blas.Unit && diag != blas.NonUnit: - panic(badDiag) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (na-1)*lda+na { - panic(shortA) - } - if len(b) < (m-1)*ldb+n { - panic(shortB) - } - - // Quick return if possible. - if alpha == 0 { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j := range bi { - bi[j] = 0 - } - } - return - } - - noConj := trans != blas.ConjTrans - noUnit := diag == blas.NonUnit - if side == blas.Left { - if trans == blas.NoTrans { - // Form B = alpha*A*B. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - aii := alpha - if noUnit { - aii *= a[i*lda+i] - } - bi := b[i*ldb : i*ldb+n] - for j := range bi { - bi[j] *= aii - } - for ja, aij := range a[i*lda+i+1 : i*lda+m] { - j := ja + i + 1 - if aij != 0 { - c64.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) - } - } - } - } else { - for i := m - 1; i >= 0; i-- { - aii := alpha - if noUnit { - aii *= a[i*lda+i] - } - bi := b[i*ldb : i*ldb+n] - for j := range bi { - bi[j] *= aii - } - for j, aij := range a[i*lda : i*lda+i] { - if aij != 0 { - c64.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) - } - } - } - } - } else { - // Form B = alpha*Aᵀ*B or B = alpha*Aᴴ*B. - if uplo == blas.Upper { - for k := m - 1; k >= 0; k-- { - bk := b[k*ldb : k*ldb+n] - for ja, ajk := range a[k*lda+k+1 : k*lda+m] { - if ajk == 0 { - continue - } - j := k + 1 + ja - if noConj { - c64.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) - } else { - c64.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) - } - } - akk := alpha - if noUnit { - if noConj { - akk *= a[k*lda+k] - } else { - akk *= cmplx.Conj(a[k*lda+k]) - } - } - if akk != 1 { - c64.ScalUnitary(akk, bk) - } - } - } else { - for k := 0; k < m; k++ { - bk := b[k*ldb : k*ldb+n] - for j, ajk := range a[k*lda : k*lda+k] { - if ajk == 0 { - continue - } - if noConj { - c64.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) - } else { - c64.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) - } - } - akk := alpha - if noUnit { - if noConj { - akk *= a[k*lda+k] - } else { - akk *= cmplx.Conj(a[k*lda+k]) - } - } - if akk != 1 { - c64.ScalUnitary(akk, bk) - } - } - } - } - } else { - if trans == blas.NoTrans { - // Form B = alpha*B*A. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for k := n - 1; k >= 0; k-- { - abik := alpha * bi[k] - if abik == 0 { - continue - } - bi[k] = abik - if noUnit { - bi[k] *= a[k*lda+k] - } - c64.AxpyUnitary(abik, a[k*lda+k+1:k*lda+n], bi[k+1:]) - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for k := 0; k < n; k++ { - abik := alpha * bi[k] - if abik == 0 { - continue - } - bi[k] = abik - if noUnit { - bi[k] *= a[k*lda+k] - } - c64.AxpyUnitary(abik, a[k*lda:k*lda+k], bi[:k]) - } - } - } - } else { - // Form B = alpha*B*Aᵀ or B = alpha*B*Aᴴ. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j, bij := range bi { - if noConj { - if noUnit { - bij *= a[j*lda+j] - } - bij += c64.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - } else { - if noUnit { - bij *= cmplx.Conj(a[j*lda+j]) - } - bij += c64.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - } - bi[j] = alpha * bij - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - bij := bi[j] - if noConj { - if noUnit { - bij *= a[j*lda+j] - } - bij += c64.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) - } else { - if noUnit { - bij *= cmplx.Conj(a[j*lda+j]) - } - bij += c64.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) - } - bi[j] = alpha * bij - } - } - } - } - } -} - -// Ctrsm solves one of the matrix equations -// -// op(A) * X = alpha * B if side == blas.Left, -// X * op(A) = alpha * B if side == blas.Right, -// -// where alpha is a scalar, X and B are m×n matrices, A is a unit or -// non-unit, upper or lower triangular matrix and op(A) is one of -// -// op(A) = A if transA == blas.NoTrans, -// op(A) = Aᵀ if transA == blas.Trans, -// op(A) = Aᴴ if transA == blas.ConjTrans. -// -// On return the matrix X is overwritten on B. -// -// Complex64 implementations are autogenerated and not directly tested. -func (Implementation) Ctrsm(side blas.Side, uplo blas.Uplo, transA blas.Transpose, diag blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { - na := m - if side == blas.Right { - na = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case uplo != blas.Lower && uplo != blas.Upper: - panic(badUplo) - case transA != blas.NoTrans && transA != blas.Trans && transA != blas.ConjTrans: - panic(badTranspose) - case diag != blas.Unit && diag != blas.NonUnit: - panic(badDiag) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, na): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < (na-1)*lda+na { - panic(shortA) - } - if len(b) < (m-1)*ldb+n { - panic(shortB) - } - - if alpha == 0 { - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - b[i*ldb+j] = 0 - } - } - return - } - - noConj := transA != blas.ConjTrans - noUnit := diag == blas.NonUnit - if side == blas.Left { - if transA == blas.NoTrans { - // Form B = alpha*inv(A)*B. - if uplo == blas.Upper { - for i := m - 1; i >= 0; i-- { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c64.ScalUnitary(alpha, bi) - } - for ka, aik := range a[i*lda+i+1 : i*lda+m] { - k := i + 1 + ka - if aik != 0 { - c64.AxpyUnitary(-aik, b[k*ldb:k*ldb+n], bi) - } - } - if noUnit { - c64.ScalUnitary(1/a[i*lda+i], bi) - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c64.ScalUnitary(alpha, bi) - } - for j, aij := range a[i*lda : i*lda+i] { - if aij != 0 { - c64.AxpyUnitary(-aij, b[j*ldb:j*ldb+n], bi) - } - } - if noUnit { - c64.ScalUnitary(1/a[i*lda+i], bi) - } - } - } - } else { - // Form B = alpha*inv(Aᵀ)*B or B = alpha*inv(Aᴴ)*B. - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if noUnit { - if noConj { - c64.ScalUnitary(1/a[i*lda+i], bi) - } else { - c64.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) - } - } - for ja, aij := range a[i*lda+i+1 : i*lda+m] { - if aij == 0 { - continue - } - j := i + 1 + ja - if noConj { - c64.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) - } else { - c64.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) - } - } - if alpha != 1 { - c64.ScalUnitary(alpha, bi) - } - } - } else { - for i := m - 1; i >= 0; i-- { - bi := b[i*ldb : i*ldb+n] - if noUnit { - if noConj { - c64.ScalUnitary(1/a[i*lda+i], bi) - } else { - c64.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) - } - } - for j, aij := range a[i*lda : i*lda+i] { - if aij == 0 { - continue - } - if noConj { - c64.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) - } else { - c64.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) - } - } - if alpha != 1 { - c64.ScalUnitary(alpha, bi) - } - } - } - } - } else { - if transA == blas.NoTrans { - // Form B = alpha*B*inv(A). - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c64.ScalUnitary(alpha, bi) - } - for j, bij := range bi { - if bij == 0 { - continue - } - if noUnit { - bi[j] /= a[j*lda+j] - } - c64.AxpyUnitary(-bi[j], a[j*lda+j+1:j*lda+n], bi[j+1:n]) - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - if alpha != 1 { - c64.ScalUnitary(alpha, bi) - } - for j := n - 1; j >= 0; j-- { - if bi[j] == 0 { - continue - } - if noUnit { - bi[j] /= a[j*lda+j] - } - c64.AxpyUnitary(-bi[j], a[j*lda:j*lda+j], bi[:j]) - } - } - } - } else { - // Form B = alpha*B*inv(Aᵀ) or B = alpha*B*inv(Aᴴ). - if uplo == blas.Upper { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - bij := alpha * bi[j] - if noConj { - bij -= c64.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - if noUnit { - bij /= a[j*lda+j] - } - } else { - bij -= c64.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) - if noUnit { - bij /= cmplx.Conj(a[j*lda+j]) - } - } - bi[j] = bij - } - } - } else { - for i := 0; i < m; i++ { - bi := b[i*ldb : i*ldb+n] - for j, bij := range bi { - bij *= alpha - if noConj { - bij -= c64.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) - if noUnit { - bij /= a[j*lda+j] - } - } else { - bij -= c64.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) - if noUnit { - bij /= cmplx.Conj(a[j*lda+j]) - } - } - bi[j] = bij - } - } - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3float32.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3float32.go deleted file mode 100644 index 4b813fbc..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level3float32.go +++ /dev/null @@ -1,925 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2014 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f32" -) - -var _ blas.Float32Level3 = Implementation{} - -// Strsm solves one of the matrix equations -// -// A * X = alpha * B if tA == blas.NoTrans and side == blas.Left -// Aᵀ * X = alpha * B if tA == blas.Trans or blas.ConjTrans, and side == blas.Left -// X * A = alpha * B if tA == blas.NoTrans and side == blas.Right -// X * Aᵀ = alpha * B if tA == blas.Trans or blas.ConjTrans, and side == blas.Right -// -// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and alpha is a -// scalar. -// -// At entry to the function, X contains the values of B, and the result is -// stored in-place into X. -// -// No check is made that A is invertible. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { - if s != blas.Left && s != blas.Right { - panic(badSide) - } - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - k := n - if s == blas.Left { - k = m - } - if lda < max(1, k) { - panic(badLdA) - } - if ldb < max(1, n) { - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(k-1)+k { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - - if alpha == 0 { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] = 0 - } - } - return - } - nonUnit := d == blas.NonUnit - if s == blas.Left { - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := m - 1; i >= 0; i-- { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f32.ScalUnitary(alpha, btmp) - } - for ka, va := range a[i*lda+i+1 : i*lda+m] { - if va != 0 { - k := ka + i + 1 - f32.AxpyUnitary(-va, b[k*ldb:k*ldb+n], btmp) - } - } - if nonUnit { - tmp := 1 / a[i*lda+i] - f32.ScalUnitary(tmp, btmp) - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f32.ScalUnitary(alpha, btmp) - } - for k, va := range a[i*lda : i*lda+i] { - if va != 0 { - f32.AxpyUnitary(-va, b[k*ldb:k*ldb+n], btmp) - } - } - if nonUnit { - tmp := 1 / a[i*lda+i] - f32.ScalUnitary(tmp, btmp) - } - } - return - } - // Cases where a is transposed - if ul == blas.Upper { - for k := 0; k < m; k++ { - btmpk := b[k*ldb : k*ldb+n] - if nonUnit { - tmp := 1 / a[k*lda+k] - f32.ScalUnitary(tmp, btmpk) - } - for ia, va := range a[k*lda+k+1 : k*lda+m] { - if va != 0 { - i := ia + k + 1 - f32.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) - } - } - if alpha != 1 { - f32.ScalUnitary(alpha, btmpk) - } - } - return - } - for k := m - 1; k >= 0; k-- { - btmpk := b[k*ldb : k*ldb+n] - if nonUnit { - tmp := 1 / a[k*lda+k] - f32.ScalUnitary(tmp, btmpk) - } - for i, va := range a[k*lda : k*lda+k] { - if va != 0 { - f32.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) - } - } - if alpha != 1 { - f32.ScalUnitary(alpha, btmpk) - } - } - return - } - // Cases where a is to the right of X. - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f32.ScalUnitary(alpha, btmp) - } - for k, vb := range btmp { - if vb == 0 { - continue - } - if nonUnit { - btmp[k] /= a[k*lda+k] - } - f32.AxpyUnitary(-btmp[k], a[k*lda+k+1:k*lda+n], btmp[k+1:n]) - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f32.ScalUnitary(alpha, btmp) - } - for k := n - 1; k >= 0; k-- { - if btmp[k] == 0 { - continue - } - if nonUnit { - btmp[k] /= a[k*lda+k] - } - f32.AxpyUnitary(-btmp[k], a[k*lda:k*lda+k], btmp[:k]) - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:]) - if nonUnit { - tmp /= a[j*lda+j] - } - btmp[j] = tmp - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := 0; j < n; j++ { - tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) - if nonUnit { - tmp /= a[j*lda+j] - } - btmp[j] = tmp - } - } -} - -// Ssymm performs one of the matrix-matrix operations -// -// C = alpha * A * B + beta * C if side == blas.Left -// C = alpha * B * A + beta * C if side == blas.Right -// -// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha -// is a scalar. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Ssymm(s blas.Side, ul blas.Uplo, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { - if s != blas.Right && s != blas.Left { - panic(badSide) - } - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - k := n - if s == blas.Left { - k = m - } - if lda < max(1, k) { - panic(badLdA) - } - if ldb < max(1, n) { - panic(badLdB) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(k-1)+k { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - if len(c) < ldc*(m-1)+n { - panic(shortC) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - if beta == 0 { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - } - - if alpha == 0 { - if beta != 0 { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := 0; j < n; j++ { - ctmp[j] *= beta - } - } - } - return - } - - isUpper := ul == blas.Upper - if s == blas.Left { - for i := 0; i < m; i++ { - atmp := alpha * a[i*lda+i] - btmp := b[i*ldb : i*ldb+n] - ctmp := c[i*ldc : i*ldc+n] - for j, v := range btmp { - ctmp[j] *= beta - ctmp[j] += atmp * v - } - - for k := 0; k < i; k++ { - var atmp float32 - if isUpper { - atmp = a[k*lda+i] - } else { - atmp = a[i*lda+k] - } - atmp *= alpha - f32.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) - } - for k := i + 1; k < m; k++ { - var atmp float32 - if isUpper { - atmp = a[i*lda+k] - } else { - atmp = a[k*lda+i] - } - atmp *= alpha - f32.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) - } - } - return - } - if isUpper { - for i := 0; i < m; i++ { - for j := n - 1; j >= 0; j-- { - tmp := alpha * b[i*ldb+j] - var tmp2 float32 - atmp := a[j*lda+j+1 : j*lda+n] - btmp := b[i*ldb+j+1 : i*ldb+n] - ctmp := c[i*ldc+j+1 : i*ldc+n] - for k, v := range atmp { - ctmp[k] += tmp * v - tmp2 += btmp[k] * v - } - c[i*ldc+j] *= beta - c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 - } - } - return - } - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - tmp := alpha * b[i*ldb+j] - var tmp2 float32 - atmp := a[j*lda : j*lda+j] - btmp := b[i*ldb : i*ldb+j] - ctmp := c[i*ldc : i*ldc+j] - for k, v := range atmp { - ctmp[k] += tmp * v - tmp2 += btmp[k] * v - } - c[i*ldc+j] *= beta - c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 - } - } -} - -// Ssyrk performs one of the symmetric rank-k operations -// -// C = alpha * A * Aᵀ + beta * C if tA == blas.NoTrans -// C = alpha * Aᵀ * A + beta * C if tA == blas.Trans or tA == blas.ConjTrans -// -// where A is an n×k or k×n matrix, C is an n×n symmetric matrix, and alpha and -// beta are scalars. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32, ldc int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { - panic(badTranspose) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - row, col := k, n - if tA == blas.NoTrans { - row, col = n, k - } - if lda < max(1, col) { - panic(badLdA) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(row-1)+col { - panic(shortA) - } - if len(c) < ldc*(n-1)+n { - panic(shortC) - } - - if alpha == 0 { - if beta == 0 { - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - atmp := a[i*lda : i*lda+k] - if beta == 0 { - for jc := range ctmp { - j := jc + i - ctmp[jc] = alpha * f32.DotUnitary(atmp, a[j*lda:j*lda+k]) - } - } else { - for jc, vc := range ctmp { - j := jc + i - ctmp[jc] = vc*beta + alpha*f32.DotUnitary(atmp, a[j*lda:j*lda+k]) - } - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - atmp := a[i*lda : i*lda+k] - if beta == 0 { - for j := range ctmp { - ctmp[j] = alpha * f32.DotUnitary(a[j*lda:j*lda+k], atmp) - } - } else { - for j, vc := range ctmp { - ctmp[j] = vc*beta + alpha*f32.DotUnitary(a[j*lda:j*lda+k], atmp) - } - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - if beta == 0 { - for j := range ctmp { - ctmp[j] = 0 - } - } else if beta != 1 { - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[l*lda+i] - if tmp != 0 { - f32.AxpyUnitary(tmp, a[l*lda+i:l*lda+n], ctmp) - } - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - if beta != 1 { - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[l*lda+i] - if tmp != 0 { - f32.AxpyUnitary(tmp, a[l*lda:l*lda+i+1], ctmp) - } - } - } -} - -// Ssyr2k performs one of the symmetric rank 2k operations -// -// C = alpha * A * Bᵀ + alpha * B * Aᵀ + beta * C if tA == blas.NoTrans -// C = alpha * Aᵀ * B + alpha * Bᵀ * A + beta * C if tA == blas.Trans or tA == blas.ConjTrans -// -// where A and B are n×k or k×n matrices, C is an n×n symmetric matrix, and -// alpha and beta are scalars. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Ssyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { - panic(badTranspose) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - row, col := k, n - if tA == blas.NoTrans { - row, col = n, k - } - if lda < max(1, col) { - panic(badLdA) - } - if ldb < max(1, col) { - panic(badLdB) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(row-1)+col { - panic(shortA) - } - if len(b) < ldb*(row-1)+col { - panic(shortB) - } - if len(c) < ldc*(n-1)+n { - panic(shortC) - } - - if alpha == 0 { - if beta == 0 { - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < n; i++ { - atmp := a[i*lda : i*lda+k] - btmp := b[i*ldb : i*ldb+k] - ctmp := c[i*ldc+i : i*ldc+n] - if beta == 0 { - for jc := range ctmp { - j := i + jc - var tmp1, tmp2 float32 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[jc] = alpha * (tmp1 + tmp2) - } - } else { - for jc := range ctmp { - j := i + jc - var tmp1, tmp2 float32 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[jc] *= beta - ctmp[jc] += alpha * (tmp1 + tmp2) - } - } - } - return - } - for i := 0; i < n; i++ { - atmp := a[i*lda : i*lda+k] - btmp := b[i*ldb : i*ldb+k] - ctmp := c[i*ldc : i*ldc+i+1] - if beta == 0 { - for j := 0; j <= i; j++ { - var tmp1, tmp2 float32 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[j] = alpha * (tmp1 + tmp2) - } - } else { - for j := 0; j <= i; j++ { - var tmp1, tmp2 float32 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[j] *= beta - ctmp[j] += alpha * (tmp1 + tmp2) - } - } - } - return - } - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - switch beta { - case 0: - for j := range ctmp { - ctmp[j] = 0 - } - case 1: - default: - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp1 := alpha * b[l*ldb+i] - tmp2 := alpha * a[l*lda+i] - btmp := b[l*ldb+i : l*ldb+n] - if tmp1 != 0 || tmp2 != 0 { - for j, v := range a[l*lda+i : l*lda+n] { - ctmp[j] += v*tmp1 + btmp[j]*tmp2 - } - } - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - switch beta { - case 0: - for j := range ctmp { - ctmp[j] = 0 - } - case 1: - default: - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp1 := alpha * b[l*ldb+i] - tmp2 := alpha * a[l*lda+i] - btmp := b[l*ldb : l*ldb+i+1] - if tmp1 != 0 || tmp2 != 0 { - for j, v := range a[l*lda : l*lda+i+1] { - ctmp[j] += v*tmp1 + btmp[j]*tmp2 - } - } - } - } -} - -// Strmm performs one of the matrix-matrix operations -// -// B = alpha * A * B if tA == blas.NoTrans and side == blas.Left -// B = alpha * Aᵀ * B if tA == blas.Trans or blas.ConjTrans, and side == blas.Left -// B = alpha * B * A if tA == blas.NoTrans and side == blas.Right -// B = alpha * B * Aᵀ if tA == blas.Trans or blas.ConjTrans, and side == blas.Right -// -// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is a scalar. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { - if s != blas.Left && s != blas.Right { - panic(badSide) - } - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - k := n - if s == blas.Left { - k = m - } - if lda < max(1, k) { - panic(badLdA) - } - if ldb < max(1, n) { - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(k-1)+k { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - - if alpha == 0 { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] = 0 - } - } - return - } - - nonUnit := d == blas.NonUnit - if s == blas.Left { - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < m; i++ { - tmp := alpha - if nonUnit { - tmp *= a[i*lda+i] - } - btmp := b[i*ldb : i*ldb+n] - f32.ScalUnitary(tmp, btmp) - for ka, va := range a[i*lda+i+1 : i*lda+m] { - k := ka + i + 1 - if va != 0 { - f32.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) - } - } - } - return - } - for i := m - 1; i >= 0; i-- { - tmp := alpha - if nonUnit { - tmp *= a[i*lda+i] - } - btmp := b[i*ldb : i*ldb+n] - f32.ScalUnitary(tmp, btmp) - for k, va := range a[i*lda : i*lda+i] { - if va != 0 { - f32.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) - } - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for k := m - 1; k >= 0; k-- { - btmpk := b[k*ldb : k*ldb+n] - for ia, va := range a[k*lda+k+1 : k*lda+m] { - i := ia + k + 1 - btmp := b[i*ldb : i*ldb+n] - if va != 0 { - f32.AxpyUnitary(alpha*va, btmpk, btmp) - } - } - tmp := alpha - if nonUnit { - tmp *= a[k*lda+k] - } - if tmp != 1 { - f32.ScalUnitary(tmp, btmpk) - } - } - return - } - for k := 0; k < m; k++ { - btmpk := b[k*ldb : k*ldb+n] - for i, va := range a[k*lda : k*lda+k] { - btmp := b[i*ldb : i*ldb+n] - if va != 0 { - f32.AxpyUnitary(alpha*va, btmpk, btmp) - } - } - tmp := alpha - if nonUnit { - tmp *= a[k*lda+k] - } - if tmp != 1 { - f32.ScalUnitary(tmp, btmpk) - } - } - return - } - // Cases where a is on the right - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for k := n - 1; k >= 0; k-- { - tmp := alpha * btmp[k] - if tmp == 0 { - continue - } - btmp[k] = tmp - if nonUnit { - btmp[k] *= a[k*lda+k] - } - f32.AxpyUnitary(tmp, a[k*lda+k+1:k*lda+n], btmp[k+1:n]) - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for k := 0; k < n; k++ { - tmp := alpha * btmp[k] - if tmp == 0 { - continue - } - btmp[k] = tmp - if nonUnit { - btmp[k] *= a[k*lda+k] - } - f32.AxpyUnitary(tmp, a[k*lda:k*lda+k], btmp[:k]) - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j, vb := range btmp { - tmp := vb - if nonUnit { - tmp *= a[j*lda+j] - } - tmp += f32.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:n]) - btmp[j] = alpha * tmp - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - tmp := btmp[j] - if nonUnit { - tmp *= a[j*lda+j] - } - tmp += f32.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) - btmp[j] = alpha * tmp - } - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3float64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3float64.go deleted file mode 100644 index 0d203513..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level3float64.go +++ /dev/null @@ -1,913 +0,0 @@ -// Copyright ©2014 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f64" -) - -var _ blas.Float64Level3 = Implementation{} - -// Dtrsm solves one of the matrix equations -// -// A * X = alpha * B if tA == blas.NoTrans and side == blas.Left -// Aᵀ * X = alpha * B if tA == blas.Trans or blas.ConjTrans, and side == blas.Left -// X * A = alpha * B if tA == blas.NoTrans and side == blas.Right -// X * Aᵀ = alpha * B if tA == blas.Trans or blas.ConjTrans, and side == blas.Right -// -// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and alpha is a -// scalar. -// -// At entry to the function, X contains the values of B, and the result is -// stored in-place into X. -// -// No check is made that A is invertible. -func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { - if s != blas.Left && s != blas.Right { - panic(badSide) - } - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - k := n - if s == blas.Left { - k = m - } - if lda < max(1, k) { - panic(badLdA) - } - if ldb < max(1, n) { - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(k-1)+k { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - - if alpha == 0 { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] = 0 - } - } - return - } - nonUnit := d == blas.NonUnit - if s == blas.Left { - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := m - 1; i >= 0; i-- { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f64.ScalUnitary(alpha, btmp) - } - for ka, va := range a[i*lda+i+1 : i*lda+m] { - if va != 0 { - k := ka + i + 1 - f64.AxpyUnitary(-va, b[k*ldb:k*ldb+n], btmp) - } - } - if nonUnit { - tmp := 1 / a[i*lda+i] - f64.ScalUnitary(tmp, btmp) - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f64.ScalUnitary(alpha, btmp) - } - for k, va := range a[i*lda : i*lda+i] { - if va != 0 { - f64.AxpyUnitary(-va, b[k*ldb:k*ldb+n], btmp) - } - } - if nonUnit { - tmp := 1 / a[i*lda+i] - f64.ScalUnitary(tmp, btmp) - } - } - return - } - // Cases where a is transposed - if ul == blas.Upper { - for k := 0; k < m; k++ { - btmpk := b[k*ldb : k*ldb+n] - if nonUnit { - tmp := 1 / a[k*lda+k] - f64.ScalUnitary(tmp, btmpk) - } - for ia, va := range a[k*lda+k+1 : k*lda+m] { - if va != 0 { - i := ia + k + 1 - f64.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) - } - } - if alpha != 1 { - f64.ScalUnitary(alpha, btmpk) - } - } - return - } - for k := m - 1; k >= 0; k-- { - btmpk := b[k*ldb : k*ldb+n] - if nonUnit { - tmp := 1 / a[k*lda+k] - f64.ScalUnitary(tmp, btmpk) - } - for i, va := range a[k*lda : k*lda+k] { - if va != 0 { - f64.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) - } - } - if alpha != 1 { - f64.ScalUnitary(alpha, btmpk) - } - } - return - } - // Cases where a is to the right of X. - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f64.ScalUnitary(alpha, btmp) - } - for k, vb := range btmp { - if vb == 0 { - continue - } - if nonUnit { - btmp[k] /= a[k*lda+k] - } - f64.AxpyUnitary(-btmp[k], a[k*lda+k+1:k*lda+n], btmp[k+1:n]) - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - if alpha != 1 { - f64.ScalUnitary(alpha, btmp) - } - for k := n - 1; k >= 0; k-- { - if btmp[k] == 0 { - continue - } - if nonUnit { - btmp[k] /= a[k*lda+k] - } - f64.AxpyUnitary(-btmp[k], a[k*lda:k*lda+k], btmp[:k]) - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:]) - if nonUnit { - tmp /= a[j*lda+j] - } - btmp[j] = tmp - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := 0; j < n; j++ { - tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) - if nonUnit { - tmp /= a[j*lda+j] - } - btmp[j] = tmp - } - } -} - -// Dsymm performs one of the matrix-matrix operations -// -// C = alpha * A * B + beta * C if side == blas.Left -// C = alpha * B * A + beta * C if side == blas.Right -// -// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha -// is a scalar. -func (Implementation) Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { - if s != blas.Right && s != blas.Left { - panic(badSide) - } - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - k := n - if s == blas.Left { - k = m - } - if lda < max(1, k) { - panic(badLdA) - } - if ldb < max(1, n) { - panic(badLdB) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(k-1)+k { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - if len(c) < ldc*(m-1)+n { - panic(shortC) - } - - // Quick return if possible. - if alpha == 0 && beta == 1 { - return - } - - if beta == 0 { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - } - - if alpha == 0 { - if beta != 0 { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := 0; j < n; j++ { - ctmp[j] *= beta - } - } - } - return - } - - isUpper := ul == blas.Upper - if s == blas.Left { - for i := 0; i < m; i++ { - atmp := alpha * a[i*lda+i] - btmp := b[i*ldb : i*ldb+n] - ctmp := c[i*ldc : i*ldc+n] - for j, v := range btmp { - ctmp[j] *= beta - ctmp[j] += atmp * v - } - - for k := 0; k < i; k++ { - var atmp float64 - if isUpper { - atmp = a[k*lda+i] - } else { - atmp = a[i*lda+k] - } - atmp *= alpha - f64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) - } - for k := i + 1; k < m; k++ { - var atmp float64 - if isUpper { - atmp = a[i*lda+k] - } else { - atmp = a[k*lda+i] - } - atmp *= alpha - f64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) - } - } - return - } - if isUpper { - for i := 0; i < m; i++ { - for j := n - 1; j >= 0; j-- { - tmp := alpha * b[i*ldb+j] - var tmp2 float64 - atmp := a[j*lda+j+1 : j*lda+n] - btmp := b[i*ldb+j+1 : i*ldb+n] - ctmp := c[i*ldc+j+1 : i*ldc+n] - for k, v := range atmp { - ctmp[k] += tmp * v - tmp2 += btmp[k] * v - } - c[i*ldc+j] *= beta - c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 - } - } - return - } - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - tmp := alpha * b[i*ldb+j] - var tmp2 float64 - atmp := a[j*lda : j*lda+j] - btmp := b[i*ldb : i*ldb+j] - ctmp := c[i*ldc : i*ldc+j] - for k, v := range atmp { - ctmp[k] += tmp * v - tmp2 += btmp[k] * v - } - c[i*ldc+j] *= beta - c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 - } - } -} - -// Dsyrk performs one of the symmetric rank-k operations -// -// C = alpha * A * Aᵀ + beta * C if tA == blas.NoTrans -// C = alpha * Aᵀ * A + beta * C if tA == blas.Trans or tA == blas.ConjTrans -// -// where A is an n×k or k×n matrix, C is an n×n symmetric matrix, and alpha and -// beta are scalars. -func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { - panic(badTranspose) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - row, col := k, n - if tA == blas.NoTrans { - row, col = n, k - } - if lda < max(1, col) { - panic(badLdA) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(row-1)+col { - panic(shortA) - } - if len(c) < ldc*(n-1)+n { - panic(shortC) - } - - if alpha == 0 { - if beta == 0 { - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - atmp := a[i*lda : i*lda+k] - if beta == 0 { - for jc := range ctmp { - j := jc + i - ctmp[jc] = alpha * f64.DotUnitary(atmp, a[j*lda:j*lda+k]) - } - } else { - for jc, vc := range ctmp { - j := jc + i - ctmp[jc] = vc*beta + alpha*f64.DotUnitary(atmp, a[j*lda:j*lda+k]) - } - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - atmp := a[i*lda : i*lda+k] - if beta == 0 { - for j := range ctmp { - ctmp[j] = alpha * f64.DotUnitary(a[j*lda:j*lda+k], atmp) - } - } else { - for j, vc := range ctmp { - ctmp[j] = vc*beta + alpha*f64.DotUnitary(a[j*lda:j*lda+k], atmp) - } - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - if beta == 0 { - for j := range ctmp { - ctmp[j] = 0 - } - } else if beta != 1 { - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[l*lda+i] - if tmp != 0 { - f64.AxpyUnitary(tmp, a[l*lda+i:l*lda+n], ctmp) - } - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - if beta != 1 { - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp := alpha * a[l*lda+i] - if tmp != 0 { - f64.AxpyUnitary(tmp, a[l*lda:l*lda+i+1], ctmp) - } - } - } -} - -// Dsyr2k performs one of the symmetric rank 2k operations -// -// C = alpha * A * Bᵀ + alpha * B * Aᵀ + beta * C if tA == blas.NoTrans -// C = alpha * Aᵀ * B + alpha * Bᵀ * A + beta * C if tA == blas.Trans or tA == blas.ConjTrans -// -// where A and B are n×k or k×n matrices, C is an n×n symmetric matrix, and -// alpha and beta are scalars. -func (Implementation) Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { - panic(badTranspose) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - row, col := k, n - if tA == blas.NoTrans { - row, col = n, k - } - if lda < max(1, col) { - panic(badLdA) - } - if ldb < max(1, col) { - panic(badLdB) - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(row-1)+col { - panic(shortA) - } - if len(b) < ldb*(row-1)+col { - panic(shortB) - } - if len(c) < ldc*(n-1)+n { - panic(shortC) - } - - if alpha == 0 { - if beta == 0 { - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] = 0 - } - } - return - } - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - for j := range ctmp { - ctmp[j] *= beta - } - } - return - } - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < n; i++ { - atmp := a[i*lda : i*lda+k] - btmp := b[i*ldb : i*ldb+k] - ctmp := c[i*ldc+i : i*ldc+n] - if beta == 0 { - for jc := range ctmp { - j := i + jc - var tmp1, tmp2 float64 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[jc] = alpha * (tmp1 + tmp2) - } - } else { - for jc := range ctmp { - j := i + jc - var tmp1, tmp2 float64 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[jc] *= beta - ctmp[jc] += alpha * (tmp1 + tmp2) - } - } - } - return - } - for i := 0; i < n; i++ { - atmp := a[i*lda : i*lda+k] - btmp := b[i*ldb : i*ldb+k] - ctmp := c[i*ldc : i*ldc+i+1] - if beta == 0 { - for j := 0; j <= i; j++ { - var tmp1, tmp2 float64 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[j] = alpha * (tmp1 + tmp2) - } - } else { - for j := 0; j <= i; j++ { - var tmp1, tmp2 float64 - binner := b[j*ldb : j*ldb+k] - for l, v := range a[j*lda : j*lda+k] { - tmp1 += v * btmp[l] - tmp2 += atmp[l] * binner[l] - } - ctmp[j] *= beta - ctmp[j] += alpha * (tmp1 + tmp2) - } - } - } - return - } - if ul == blas.Upper { - for i := 0; i < n; i++ { - ctmp := c[i*ldc+i : i*ldc+n] - switch beta { - case 0: - for j := range ctmp { - ctmp[j] = 0 - } - case 1: - default: - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp1 := alpha * b[l*ldb+i] - tmp2 := alpha * a[l*lda+i] - btmp := b[l*ldb+i : l*ldb+n] - if tmp1 != 0 || tmp2 != 0 { - for j, v := range a[l*lda+i : l*lda+n] { - ctmp[j] += v*tmp1 + btmp[j]*tmp2 - } - } - } - } - return - } - for i := 0; i < n; i++ { - ctmp := c[i*ldc : i*ldc+i+1] - switch beta { - case 0: - for j := range ctmp { - ctmp[j] = 0 - } - case 1: - default: - for j := range ctmp { - ctmp[j] *= beta - } - } - for l := 0; l < k; l++ { - tmp1 := alpha * b[l*ldb+i] - tmp2 := alpha * a[l*lda+i] - btmp := b[l*ldb : l*ldb+i+1] - if tmp1 != 0 || tmp2 != 0 { - for j, v := range a[l*lda : l*lda+i+1] { - ctmp[j] += v*tmp1 + btmp[j]*tmp2 - } - } - } - } -} - -// Dtrmm performs one of the matrix-matrix operations -// -// B = alpha * A * B if tA == blas.NoTrans and side == blas.Left -// B = alpha * Aᵀ * B if tA == blas.Trans or blas.ConjTrans, and side == blas.Left -// B = alpha * B * A if tA == blas.NoTrans and side == blas.Right -// B = alpha * B * Aᵀ if tA == blas.Trans or blas.ConjTrans, and side == blas.Right -// -// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is a scalar. -func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { - if s != blas.Left && s != blas.Right { - panic(badSide) - } - if ul != blas.Lower && ul != blas.Upper { - panic(badUplo) - } - if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { - panic(badTranspose) - } - if d != blas.NonUnit && d != blas.Unit { - panic(badDiag) - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - k := n - if s == blas.Left { - k = m - } - if lda < max(1, k) { - panic(badLdA) - } - if ldb < max(1, n) { - panic(badLdB) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if len(a) < lda*(k-1)+k { - panic(shortA) - } - if len(b) < ldb*(m-1)+n { - panic(shortB) - } - - if alpha == 0 { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] = 0 - } - } - return - } - - nonUnit := d == blas.NonUnit - if s == blas.Left { - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < m; i++ { - tmp := alpha - if nonUnit { - tmp *= a[i*lda+i] - } - btmp := b[i*ldb : i*ldb+n] - f64.ScalUnitary(tmp, btmp) - for ka, va := range a[i*lda+i+1 : i*lda+m] { - k := ka + i + 1 - if va != 0 { - f64.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) - } - } - } - return - } - for i := m - 1; i >= 0; i-- { - tmp := alpha - if nonUnit { - tmp *= a[i*lda+i] - } - btmp := b[i*ldb : i*ldb+n] - f64.ScalUnitary(tmp, btmp) - for k, va := range a[i*lda : i*lda+i] { - if va != 0 { - f64.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) - } - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for k := m - 1; k >= 0; k-- { - btmpk := b[k*ldb : k*ldb+n] - for ia, va := range a[k*lda+k+1 : k*lda+m] { - i := ia + k + 1 - btmp := b[i*ldb : i*ldb+n] - if va != 0 { - f64.AxpyUnitary(alpha*va, btmpk, btmp) - } - } - tmp := alpha - if nonUnit { - tmp *= a[k*lda+k] - } - if tmp != 1 { - f64.ScalUnitary(tmp, btmpk) - } - } - return - } - for k := 0; k < m; k++ { - btmpk := b[k*ldb : k*ldb+n] - for i, va := range a[k*lda : k*lda+k] { - btmp := b[i*ldb : i*ldb+n] - if va != 0 { - f64.AxpyUnitary(alpha*va, btmpk, btmp) - } - } - tmp := alpha - if nonUnit { - tmp *= a[k*lda+k] - } - if tmp != 1 { - f64.ScalUnitary(tmp, btmpk) - } - } - return - } - // Cases where a is on the right - if tA == blas.NoTrans { - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for k := n - 1; k >= 0; k-- { - tmp := alpha * btmp[k] - if tmp == 0 { - continue - } - btmp[k] = tmp - if nonUnit { - btmp[k] *= a[k*lda+k] - } - f64.AxpyUnitary(tmp, a[k*lda+k+1:k*lda+n], btmp[k+1:n]) - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for k := 0; k < n; k++ { - tmp := alpha * btmp[k] - if tmp == 0 { - continue - } - btmp[k] = tmp - if nonUnit { - btmp[k] *= a[k*lda+k] - } - f64.AxpyUnitary(tmp, a[k*lda:k*lda+k], btmp[:k]) - } - } - return - } - // Cases where a is transposed. - if ul == blas.Upper { - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j, vb := range btmp { - tmp := vb - if nonUnit { - tmp *= a[j*lda+j] - } - tmp += f64.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:n]) - btmp[j] = alpha * tmp - } - } - return - } - for i := 0; i < m; i++ { - btmp := b[i*ldb : i*ldb+n] - for j := n - 1; j >= 0; j-- { - tmp := btmp[j] - if nonUnit { - tmp *= a[j*lda+j] - } - tmp += f64.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) - btmp[j] = alpha * tmp - } - } -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go b/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go deleted file mode 100644 index 7b03ce46..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go +++ /dev/null @@ -1,301 +0,0 @@ -// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. - -// Copyright ©2014 The Gonum 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 gonum - -import ( - "runtime" - "sync" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/internal/asm/f32" -) - -// Sgemm performs one of the matrix-matrix operations -// -// C = alpha * A * B + beta * C -// C = alpha * Aᵀ * B + beta * C -// C = alpha * A * Bᵀ + beta * C -// C = alpha * Aᵀ * Bᵀ + beta * C -// -// where A is an m×k or k×m dense matrix, B is an n×k or k×n dense matrix, C is -// an m×n matrix, and alpha and beta are scalars. tA and tB specify whether A or -// B are transposed. -// -// Float32 implementations are autogenerated and not directly tested. -func (Implementation) Sgemm(tA, tB blas.Transpose, m, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { - switch tA { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - switch tB { - default: - panic(badTranspose) - case blas.NoTrans, blas.Trans, blas.ConjTrans: - } - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - aTrans := tA == blas.Trans || tA == blas.ConjTrans - if aTrans { - if lda < max(1, m) { - panic(badLdA) - } - } else { - if lda < max(1, k) { - panic(badLdA) - } - } - bTrans := tB == blas.Trans || tB == blas.ConjTrans - if bTrans { - if ldb < max(1, k) { - panic(badLdB) - } - } else { - if ldb < max(1, n) { - panic(badLdB) - } - } - if ldc < max(1, n) { - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - // For zero matrix size the following slice length checks are trivially satisfied. - if aTrans { - if len(a) < (k-1)*lda+m { - panic(shortA) - } - } else { - if len(a) < (m-1)*lda+k { - panic(shortA) - } - } - if bTrans { - if len(b) < (n-1)*ldb+k { - panic(shortB) - } - } else { - if len(b) < (k-1)*ldb+n { - panic(shortB) - } - } - if len(c) < (m-1)*ldc+n { - panic(shortC) - } - - // Quick return if possible. - if (alpha == 0 || k == 0) && beta == 1 { - return - } - - // scale c - if beta != 1 { - if beta == 0 { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := range ctmp { - ctmp[j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for j := range ctmp { - ctmp[j] *= beta - } - } - } - } - - sgemmParallel(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) -} - -func sgemmParallel(aTrans, bTrans bool, m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { - // dgemmParallel computes a parallel matrix multiplication by partitioning - // a and b into sub-blocks, and updating c with the multiplication of the sub-block - // In all cases, - // A = [ A_11 A_12 ... A_1j - // A_21 A_22 ... A_2j - // ... - // A_i1 A_i2 ... A_ij] - // - // and same for B. All of the submatrix sizes are blockSize×blockSize except - // at the edges. - // - // In all cases, there is one dimension for each matrix along which - // C must be updated sequentially. - // Cij = \sum_k Aik Bki, (A * B) - // Cij = \sum_k Aki Bkj, (Aᵀ * B) - // Cij = \sum_k Aik Bjk, (A * Bᵀ) - // Cij = \sum_k Aki Bjk, (Aᵀ * Bᵀ) - // - // This code computes one {i, j} block sequentially along the k dimension, - // and computes all of the {i, j} blocks concurrently. This - // partitioning allows Cij to be updated in-place without race-conditions. - // Instead of launching a goroutine for each possible concurrent computation, - // a number of worker goroutines are created and channels are used to pass - // available and completed cases. - // - // http://alexkr.com/docs/matrixmult.pdf is a good reference on matrix-matrix - // multiplies, though this code does not copy matrices to attempt to eliminate - // cache misses. - - maxKLen := k - parBlocks := blocks(m, blockSize) * blocks(n, blockSize) - if parBlocks < minParBlock { - // The matrix multiplication is small in the dimensions where it can be - // computed concurrently. Just do it in serial. - sgemmSerial(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - } - - // workerLimit acts a number of maximum concurrent workers, - // with the limit set to the number of procs available. - workerLimit := make(chan struct{}, runtime.GOMAXPROCS(0)) - - // wg is used to wait for all - var wg sync.WaitGroup - wg.Add(parBlocks) - defer wg.Wait() - - for i := 0; i < m; i += blockSize { - for j := 0; j < n; j += blockSize { - workerLimit <- struct{}{} - go func(i, j int) { - defer func() { - wg.Done() - <-workerLimit - }() - - leni := blockSize - if i+leni > m { - leni = m - i - } - lenj := blockSize - if j+lenj > n { - lenj = n - j - } - - cSub := sliceView32(c, ldc, i, j, leni, lenj) - - // Compute A_ik B_kj for all k - for k := 0; k < maxKLen; k += blockSize { - lenk := blockSize - if k+lenk > maxKLen { - lenk = maxKLen - k - } - var aSub, bSub []float32 - if aTrans { - aSub = sliceView32(a, lda, k, i, lenk, leni) - } else { - aSub = sliceView32(a, lda, i, k, leni, lenk) - } - if bTrans { - bSub = sliceView32(b, ldb, j, k, lenj, lenk) - } else { - bSub = sliceView32(b, ldb, k, j, lenk, lenj) - } - sgemmSerial(aTrans, bTrans, leni, lenj, lenk, aSub, lda, bSub, ldb, cSub, ldc, alpha) - } - }(i, j) - } - } -} - -// sgemmSerial is serial matrix multiply -func sgemmSerial(aTrans, bTrans bool, m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { - switch { - case !aTrans && !bTrans: - sgemmSerialNotNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - case aTrans && !bTrans: - sgemmSerialTransNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - case !aTrans && bTrans: - sgemmSerialNotTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - case aTrans && bTrans: - sgemmSerialTransTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) - return - default: - panic("unreachable") - } -} - -// sgemmSerial where neither a nor b are transposed -func sgemmSerialNotNot(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for i := 0; i < m; i++ { - ctmp := c[i*ldc : i*ldc+n] - for l, v := range a[i*lda : i*lda+k] { - tmp := alpha * v - if tmp != 0 { - f32.AxpyUnitary(tmp, b[l*ldb:l*ldb+n], ctmp) - } - } - } -} - -// sgemmSerial where neither a is transposed and b is not -func sgemmSerialTransNot(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for l := 0; l < k; l++ { - btmp := b[l*ldb : l*ldb+n] - for i, v := range a[l*lda : l*lda+m] { - tmp := alpha * v - if tmp != 0 { - ctmp := c[i*ldc : i*ldc+n] - f32.AxpyUnitary(tmp, btmp, ctmp) - } - } - } -} - -// sgemmSerial where neither a is not transposed and b is -func sgemmSerialNotTrans(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for i := 0; i < m; i++ { - atmp := a[i*lda : i*lda+k] - ctmp := c[i*ldc : i*ldc+n] - for j := 0; j < n; j++ { - ctmp[j] += alpha * f32.DotUnitary(atmp, b[j*ldb:j*ldb+k]) - } - } -} - -// sgemmSerial where both are transposed -func sgemmSerialTransTrans(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { - // This style is used instead of the literal [i*stride +j]) is used because - // approximately 5 times faster as of go 1.3. - for l := 0; l < k; l++ { - for i, v := range a[l*lda : l*lda+m] { - tmp := alpha * v - if tmp != 0 { - ctmp := c[i*ldc : i*ldc+n] - f32.AxpyInc(tmp, b[l:], ctmp, uintptr(n), uintptr(ldb), 1, 0, 0) - } - } - } -} - -func sliceView32(a []float32, lda, i, j, r, c int) []float32 { - return a[i*lda+j : (i+r-1)*lda+j+c] -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash b/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash deleted file mode 100644 index a107fce4..00000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/env bash - -# Copyright ©2015 The Gonum Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -WARNINGF32='//\ -// Float32 implementations are autogenerated and not directly tested.\ -' -WARNINGC64='//\ -// Complex64 implementations are autogenerated and not directly tested.\ -' - -# Level1 routines. - -echo Generating level1float32.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32.go -cat level1float64.go \ -| gofmt -r 'blas.Float64Level1 -> blas.Float32Level1' \ -\ -| gofmt -r 'float64 -> float32' \ -| gofmt -r 'blas.DrotmParams -> blas.SrotmParams' \ -\ -| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ -| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ -| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ -| gofmt -r 'f64.L2NormInc -> f32.L2NormInc' \ -| gofmt -r 'f64.L2NormUnitary -> f32.L2NormUnitary' \ -| gofmt -r 'f64.ScalInc -> f32.ScalInc' \ -| gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ -\ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ - -e 's_^// D_// S_' \ - -e "s_^\(func (Implementation) \)Id\(.*\)\$_$WARNINGF32\1Is\2_" \ - -e 's_^// Id_// Is_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ - -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ - -e 's_safmin = 0x1p-1022_safmin = 0x1p-126_' \ ->> level1float32.go - -echo Generating level1cmplx64.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1cmplx64.go -cat level1cmplx128.go \ -| gofmt -r 'blas.Complex128Level1 -> blas.Complex64Level1' \ -\ -| gofmt -r 'float64 -> float32' \ -| gofmt -r 'complex128 -> complex64' \ -\ -| gofmt -r 'c128.AxpyInc -> c64.AxpyInc' \ -| gofmt -r 'c128.AxpyUnitary -> c64.AxpyUnitary' \ -| gofmt -r 'c128.DotcInc -> c64.DotcInc' \ -| gofmt -r 'c128.DotcUnitary -> c64.DotcUnitary' \ -| gofmt -r 'c128.DotuInc -> c64.DotuInc' \ -| gofmt -r 'c128.DotuUnitary -> c64.DotuUnitary' \ -| gofmt -r 'c128.ScalInc -> c64.ScalInc' \ -| gofmt -r 'c128.ScalUnitary -> c64.ScalUnitary' \ -| gofmt -r 'dcabs1 -> scabs1' \ -\ -| sed -e "s_^\(func (Implementation) \)Zdot\(.*\)\$_$WARNINGC64\1Cdot\2_" \ - -e 's_^// Zdot_// Cdot_' \ - -e "s_^\(func (Implementation) \)Zdscal\(.*\)\$_$WARNINGC64\1Csscal\2_" \ - -e 's_^// Zdscal_// Csscal_' \ - -e "s_^\(func (Implementation) \)Z\(.*\)\$_$WARNINGC64\1C\2_" \ - -e 's_^// Z_// C_' \ - -e "s_^\(func (Implementation) \)Iz\(.*\)\$_$WARNINGC64\1Ic\2_" \ - -e 's_^// Iz_// Ic_' \ - -e "s_^\(func (Implementation) \)Dz\(.*\)\$_$WARNINGC64\1Sc\2_" \ - -e 's_^// Dz_// Sc_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/c128"_"gonum.org/v1/gonum/internal/asm/c64"_' \ - -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ ->> level1cmplx64.go - -echo Generating level1float32_sdot.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32_sdot.go -cat level1float64_ddot.go \ -| gofmt -r 'float64 -> float32' \ -\ -| gofmt -r 'f64.DotInc -> f32.DotInc' \ -| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ -\ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ - -e 's_^// D_// S_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level1float32_sdot.go - -echo Generating level1float32_dsdot.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32_dsdot.go -cat level1float64_ddot.go \ -| gofmt -r '[]float64 -> []float32' \ -\ -| gofmt -r 'f64.DotInc -> f32.DdotInc' \ -| gofmt -r 'f64.DotUnitary -> f32.DdotUnitary' \ -\ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1Ds\2_" \ - -e 's_^// D_// Ds_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level1float32_dsdot.go - -echo Generating level1float32_sdsdot.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32_sdsdot.go -cat level1float64_ddot.go \ -| gofmt -r 'float64 -> float32' \ -\ -| gofmt -r 'f64.DotInc(x, y, f(n), f(incX), f(incY), f(ix), f(iy)) -> alpha + float32(f32.DdotInc(x, y, f(n), f(incX), f(incY), f(ix), f(iy)))' \ -| gofmt -r 'f64.DotUnitary(a, b) -> alpha + float32(f32.DdotUnitary(a, b))' \ -\ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1Sds\2_" \ - -e 's_^// D\(.*\)$_// Sds\1 plus a constant_' \ - -e 's_\\sum_alpha + \\sum_' \ - -e 's/n int/n int, alpha float32/' \ - -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level1float32_sdsdot.go - - -# Level2 routines. - -echo Generating level2float32.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level2float32.go -cat level2float64.go \ -| gofmt -r 'blas.Float64Level2 -> blas.Float32Level2' \ -\ -| gofmt -r 'float64 -> float32' \ -\ -| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ -| gofmt -r 'f64.AxpyIncTo -> f32.AxpyIncTo' \ -| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ -| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ -| gofmt -r 'f64.DotInc -> f32.DotInc' \ -| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ -| gofmt -r 'f64.ScalInc -> f32.ScalInc' \ -| gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ -| gofmt -r 'f64.Ger -> f32.Ger' \ -| gofmt -r 'f64.GemvN -> f32.GemvN' \ -| gofmt -r 'f64.GemvT -> f32.GemvT' \ -| gofmt -r 'Implementation{}.Dscal -> Implementation{}.Sscal' \ -\ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ - -e 's_^// D_// S_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level2float32.go - -echo Generating level2cmplx64.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level2cmplx64.go -cat level2cmplx128.go \ -| gofmt -r 'blas.Complex128Level2 -> blas.Complex64Level2' \ -\ -| gofmt -r 'complex128 -> complex64' \ -| gofmt -r 'float64 -> float32' \ -\ -| gofmt -r 'c128.AxpyInc -> c64.AxpyInc' \ -| gofmt -r 'c128.AxpyUnitary -> c64.AxpyUnitary' \ -| gofmt -r 'c128.DotuInc -> c64.DotuInc' \ -| gofmt -r 'c128.DotuUnitary -> c64.DotuUnitary' \ -| gofmt -r 'c128.ScalInc -> c64.ScalInc' \ -| gofmt -r 'c128.ScalUnitary -> c64.ScalUnitary' \ -\ -| sed -e "s_^\(func (Implementation) \)Z\(.*\)\$_$WARNINGC64\1C\2_" \ - -e 's_^// Z_// C_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/c128"_"gonum.org/v1/gonum/internal/asm/c64"_' \ - -e 's_"math/cmplx"_cmplx "gonum.org/v1/gonum/internal/cmplx64"_' \ ->> level2cmplx64.go - -# Level3 routines. - -echo Generating level3float32.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level3float32.go -cat level3float64.go \ -| gofmt -r 'blas.Float64Level3 -> blas.Float32Level3' \ -\ -| gofmt -r 'float64 -> float32' \ -\ -| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ -| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ -| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ -| gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ -\ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ - -e 's_^// D_// S_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level3float32.go - -echo Generating sgemm.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > sgemm.go -cat dgemm.go \ -| gofmt -r 'float64 -> float32' \ -| gofmt -r 'sliceView64 -> sliceView32' \ -\ -| gofmt -r 'dgemmParallel -> sgemmParallel' \ -| gofmt -r 'computeNumBlocks64 -> computeNumBlocks32' \ -| gofmt -r 'dgemmSerial -> sgemmSerial' \ -| gofmt -r 'dgemmSerialNotNot -> sgemmSerialNotNot' \ -| gofmt -r 'dgemmSerialTransNot -> sgemmSerialTransNot' \ -| gofmt -r 'dgemmSerialNotTrans -> sgemmSerialNotTrans' \ -| gofmt -r 'dgemmSerialTransTrans -> sgemmSerialTransTrans' \ -\ -| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ -| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ -| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ -\ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ - -e 's_^// D_// S_' \ - -e 's_^// d_// s_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> sgemm.go - -echo Generating level3cmplx64.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level3cmplx64.go -cat level3cmplx128.go \ -| gofmt -r 'blas.Complex128Level3 -> blas.Complex64Level3' \ -\ -| gofmt -r 'float64 -> float32' \ -| gofmt -r 'complex128 -> complex64' \ -\ -| gofmt -r 'c128.ScalUnitary -> c64.ScalUnitary' \ -| gofmt -r 'c128.DscalUnitary -> c64.SscalUnitary' \ -| gofmt -r 'c128.DotcUnitary -> c64.DotcUnitary' \ -| gofmt -r 'c128.AxpyUnitary -> c64.AxpyUnitary' \ -| gofmt -r 'c128.DotuUnitary -> c64.DotuUnitary' \ -\ -| sed -e "s_^\(func (Implementation) \)Z\(.*\)\$_$WARNINGC64\1C\2_" \ - -e 's_^// Z_// C_' \ - -e 's_"gonum.org/v1/gonum/internal/asm/c128"_"gonum.org/v1/gonum/internal/asm/c64"_' \ - -e 's_"math/cmplx"_cmplx "gonum.org/v1/gonum/internal/cmplx64"_' \ ->> level3cmplx64.go diff --git a/vendor/gonum.org/v1/gonum/floats/README.md b/vendor/gonum.org/v1/gonum/floats/README.md deleted file mode 100644 index e8ef46d5..00000000 --- a/vendor/gonum.org/v1/gonum/floats/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Gonum floats - -[![go.dev reference](https://pkg.go.dev/badge/gonum.org/v1/gonum/floats)](https://pkg.go.dev/gonum.org/v1/gonum/floats) -[![GoDoc](https://godocs.io/gonum.org/v1/gonum/floats?status.svg)](https://godocs.io/gonum.org/v1/gonum/floats) - -Package floats provides a set of helper routines for dealing with slices of float64. -The functions avoid allocations to allow for use within tight loops without garbage collection overhead. diff --git a/vendor/gonum.org/v1/gonum/floats/doc.go b/vendor/gonum.org/v1/gonum/floats/doc.go deleted file mode 100644 index bfe05c19..00000000 --- a/vendor/gonum.org/v1/gonum/floats/doc.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright ©2017 The Gonum 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 floats provides a set of helper routines for dealing with slices -// of float64. The functions avoid allocations to allow for use within tight -// loops without garbage collection overhead. -// -// The convention used is that when a slice is being modified in place, it has -// the name dst. -package floats // import "gonum.org/v1/gonum/floats" diff --git a/vendor/gonum.org/v1/gonum/floats/floats.go b/vendor/gonum.org/v1/gonum/floats/floats.go deleted file mode 100644 index 68c4e65c..00000000 --- a/vendor/gonum.org/v1/gonum/floats/floats.go +++ /dev/null @@ -1,808 +0,0 @@ -// Copyright ©2013 The Gonum Authors. All rights reserved. -// Use of this code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package floats - -import ( - "errors" - "math" - "slices" - "sort" - - "gonum.org/v1/gonum/floats/scalar" - "gonum.org/v1/gonum/internal/asm/f64" -) - -const ( - zeroLength = "floats: zero length slice" - shortSpan = "floats: slice length less than 2" - badLength = "floats: slice lengths do not match" - badDstLength = "floats: destination slice length does not match input" -) - -// Add adds, element-wise, the elements of s and dst, and stores the result in dst. -// It panics if the argument lengths do not match. -func Add(dst, s []float64) { - if len(dst) != len(s) { - panic(badDstLength) - } - f64.AxpyUnitaryTo(dst, 1, s, dst) -} - -// AddTo adds, element-wise, the elements of s and t and -// stores the result in dst. -// It panics if the argument lengths do not match. -func AddTo(dst, s, t []float64) []float64 { - if len(s) != len(t) { - panic(badLength) - } - if len(dst) != len(s) { - panic(badDstLength) - } - f64.AxpyUnitaryTo(dst, 1, s, t) - return dst -} - -// AddConst adds the scalar c to all of the values in dst. -func AddConst(c float64, dst []float64) { - f64.AddConst(c, dst) -} - -// AddScaled performs dst = dst + alpha * s. -// It panics if the slice argument lengths do not match. -func AddScaled(dst []float64, alpha float64, s []float64) { - if len(dst) != len(s) { - panic(badLength) - } - f64.AxpyUnitaryTo(dst, alpha, s, dst) -} - -// AddScaledTo performs dst = y + alpha * s, where alpha is a scalar, -// and dst, y and s are all slices. -// It panics if the slice argument lengths do not match. -// -// At the return of the function, dst[i] = y[i] + alpha * s[i] -func AddScaledTo(dst, y []float64, alpha float64, s []float64) []float64 { - if len(s) != len(y) { - panic(badLength) - } - if len(dst) != len(y) { - panic(badDstLength) - } - f64.AxpyUnitaryTo(dst, alpha, s, y) - return dst -} - -// argsort is a helper that implements sort.Interface, as used by -// Argsort and ArgsortStable. -type argsort struct { - s []float64 - inds []int -} - -func (a argsort) Len() int { - return len(a.s) -} - -func (a argsort) Less(i, j int) bool { - return a.s[i] < a.s[j] -} - -func (a argsort) Swap(i, j int) { - a.s[i], a.s[j] = a.s[j], a.s[i] - a.inds[i], a.inds[j] = a.inds[j], a.inds[i] -} - -// Argsort sorts the elements of dst while tracking their original order. -// At the conclusion of Argsort, dst will contain the original elements of dst -// but sorted in increasing order, and inds will contain the original position -// of the elements in the slice such that dst[i] = origDst[inds[i]]. -// It panics if the argument lengths do not match. -func Argsort(dst []float64, inds []int) { - if len(dst) != len(inds) { - panic(badDstLength) - } - for i := range dst { - inds[i] = i - } - - a := argsort{s: dst, inds: inds} - sort.Sort(a) -} - -// ArgsortStable sorts the elements of dst while tracking their original order and -// keeping the original order of equal elements. At the conclusion of ArgsortStable, -// dst will contain the original elements of dst but sorted in increasing order, -// and inds will contain the original position of the elements in the slice such -// that dst[i] = origDst[inds[i]]. -// It panics if the argument lengths do not match. -func ArgsortStable(dst []float64, inds []int) { - if len(dst) != len(inds) { - panic(badDstLength) - } - for i := range dst { - inds[i] = i - } - - a := argsort{s: dst, inds: inds} - sort.Stable(a) -} - -// Count applies the function f to every element of s and returns the number -// of times the function returned true. -func Count(f func(float64) bool, s []float64) int { - var n int - for _, val := range s { - if f(val) { - n++ - } - } - return n -} - -// CumProd finds the cumulative product of the first i elements in -// s and puts them in place into the ith element of the -// destination dst. -// It panics if the argument lengths do not match. -// -// At the return of the function, dst[i] = s[i] * s[i-1] * s[i-2] * ... -func CumProd(dst, s []float64) []float64 { - if len(dst) != len(s) { - panic(badDstLength) - } - if len(dst) == 0 { - return dst - } - return f64.CumProd(dst, s) -} - -// CumSum finds the cumulative sum of the first i elements in -// s and puts them in place into the ith element of the -// destination dst. -// It panics if the argument lengths do not match. -// -// At the return of the function, dst[i] = s[i] + s[i-1] + s[i-2] + ... -func CumSum(dst, s []float64) []float64 { - if len(dst) != len(s) { - panic(badDstLength) - } - if len(dst) == 0 { - return dst - } - return f64.CumSum(dst, s) -} - -// Distance computes the L-norm of s - t. See Norm for special cases. -// It panics if the slice argument lengths do not match. -func Distance(s, t []float64, L float64) float64 { - if len(s) != len(t) { - panic(badLength) - } - if len(s) == 0 { - return 0 - } - if L == 2 { - return f64.L2DistanceUnitary(s, t) - } - var norm float64 - if L == 1 { - for i, v := range s { - norm += math.Abs(t[i] - v) - } - return norm - } - if math.IsInf(L, 1) { - for i, v := range s { - absDiff := math.Abs(t[i] - v) - if absDiff > norm { - norm = absDiff - } - } - return norm - } - for i, v := range s { - norm += math.Pow(math.Abs(t[i]-v), L) - } - return math.Pow(norm, 1/L) -} - -// Div performs element-wise division dst / s -// and stores the value in dst. -// It panics if the argument lengths do not match. -func Div(dst, s []float64) { - if len(dst) != len(s) { - panic(badLength) - } - f64.Div(dst, s) -} - -// DivTo performs element-wise division s / t -// and stores the value in dst. -// It panics if the argument lengths do not match. -func DivTo(dst, s, t []float64) []float64 { - if len(s) != len(t) { - panic(badLength) - } - if len(dst) != len(s) { - panic(badDstLength) - } - return f64.DivTo(dst, s, t) -} - -// Dot computes the dot product of s1 and s2, i.e. -// sum_{i = 1}^N s1[i]*s2[i]. -// It panics if the argument lengths do not match. -func Dot(s1, s2 []float64) float64 { - if len(s1) != len(s2) { - panic(badLength) - } - return f64.DotUnitary(s1, s2) -} - -// Equal returns true when the slices have equal lengths and -// all elements are numerically identical. -func Equal(s1, s2 []float64) bool { - if len(s1) != len(s2) { - return false - } - for i, val := range s1 { - if s2[i] != val { - return false - } - } - return true -} - -// EqualApprox returns true when the slices have equal lengths and -// all element pairs have an absolute tolerance less than tol or a -// relative tolerance less than tol. -func EqualApprox(s1, s2 []float64, tol float64) bool { - if len(s1) != len(s2) { - return false - } - for i, a := range s1 { - if !scalar.EqualWithinAbsOrRel(a, s2[i], tol, tol) { - return false - } - } - return true -} - -// EqualFunc returns true when the slices have the same lengths -// and the function returns true for all element pairs. -func EqualFunc(s1, s2 []float64, f func(float64, float64) bool) bool { - if len(s1) != len(s2) { - return false - } - for i, val := range s1 { - if !f(val, s2[i]) { - return false - } - } - return true -} - -// EqualLengths returns true when all of the slices have equal length, -// and false otherwise. It also returns true when there are no input slices. -func EqualLengths(slices ...[]float64) bool { - // This length check is needed: http://play.golang.org/p/sdty6YiLhM - if len(slices) == 0 { - return true - } - l := len(slices[0]) - for i := 1; i < len(slices); i++ { - if len(slices[i]) != l { - return false - } - } - return true -} - -// Find applies f to every element of s and returns the indices of the first -// k elements for which the f returns true, or all such elements -// if k < 0. -// Find will reslice inds to have 0 length, and will append -// found indices to inds. -// If k > 0 and there are fewer than k elements in s satisfying f, -// all of the found elements will be returned along with an error. -// At the return of the function, the input inds will be in an undetermined state. -func Find(inds []int, f func(float64) bool, s []float64, k int) ([]int, error) { - // inds is also returned to allow for calling with nil. - - // Reslice inds to have zero length. - inds = inds[:0] - - // If zero elements requested, can just return. - if k == 0 { - return inds, nil - } - - // If k < 0, return all of the found indices. - if k < 0 { - for i, val := range s { - if f(val) { - inds = append(inds, i) - } - } - return inds, nil - } - - // Otherwise, find the first k elements. - nFound := 0 - for i, val := range s { - if f(val) { - inds = append(inds, i) - nFound++ - if nFound == k { - return inds, nil - } - } - } - // Finished iterating over the loop, which means k elements were not found. - return inds, errors.New("floats: insufficient elements found") -} - -// HasNaN returns true when the slice s has any values that are NaN and false -// otherwise. -func HasNaN(s []float64) bool { - for _, v := range s { - if math.IsNaN(v) { - return true - } - } - return false -} - -// LogSpan returns a set of n equally spaced points in log space between, -// l and u where N is equal to len(dst). The first element of the -// resulting dst will be l and the final element of dst will be u. -// It panics if the length of dst is less than 2. -// Note that this call will return NaNs if either l or u are negative, and -// will return all zeros if l or u is zero. -// Also returns the mutated slice dst, so that it can be used in range, like: -// -// for i, x := range LogSpan(dst, l, u) { ... } -func LogSpan(dst []float64, l, u float64) []float64 { - Span(dst, math.Log(l), math.Log(u)) - for i := range dst { - dst[i] = math.Exp(dst[i]) - } - return dst -} - -// LogSumExp returns the log of the sum of the exponentials of the values in s. -// Panics if s is an empty slice. -func LogSumExp(s []float64) float64 { - // Want to do this in a numerically stable way which avoids - // overflow and underflow - // First, find the maximum value in the slice. - maxval := Max(s) - if math.IsInf(maxval, 0) { - // If it's infinity either way, the logsumexp will be infinity as well - // returning now avoids NaNs - return maxval - } - var lse float64 - // Compute the sumexp part - for _, val := range s { - lse += math.Exp(val - maxval) - } - // Take the log and add back on the constant taken out - return math.Log(lse) + maxval -} - -// Max returns the maximum value in the input slice. If the slice is empty, Max will panic. -func Max(s []float64) float64 { - return s[MaxIdx(s)] -} - -// MaxIdx returns the index of the maximum value in the input slice. If several -// entries have the maximum value, the first such index is returned. -// It panics if s is zero length. -func MaxIdx(s []float64) int { - if len(s) == 0 { - panic(zeroLength) - } - max := math.NaN() - var ind int - for i, v := range s { - if math.IsNaN(v) { - continue - } - if v > max || math.IsNaN(max) { - max = v - ind = i - } - } - return ind -} - -// Min returns the minimum value in the input slice. -// It panics if s is zero length. -func Min(s []float64) float64 { - return s[MinIdx(s)] -} - -// MinIdx returns the index of the minimum value in the input slice. If several -// entries have the minimum value, the first such index is returned. -// It panics if s is zero length. -func MinIdx(s []float64) int { - if len(s) == 0 { - panic(zeroLength) - } - min := math.NaN() - var ind int - for i, v := range s { - if math.IsNaN(v) { - continue - } - if v < min || math.IsNaN(min) { - min = v - ind = i - } - } - return ind -} - -// Mul performs element-wise multiplication between dst -// and s and stores the value in dst. -// It panics if the argument lengths do not match. -func Mul(dst, s []float64) { - if len(dst) != len(s) { - panic(badLength) - } - for i, val := range s { - dst[i] *= val - } -} - -// MulTo performs element-wise multiplication between s -// and t and stores the value in dst. -// It panics if the argument lengths do not match. -func MulTo(dst, s, t []float64) []float64 { - if len(s) != len(t) { - panic(badLength) - } - if len(dst) != len(s) { - panic(badDstLength) - } - for i, val := range t { - dst[i] = val * s[i] - } - return dst -} - -// NearestIdx returns the index of the element in s -// whose value is nearest to v. If several such -// elements exist, the lowest index is returned. -// It panics if s is zero length. -func NearestIdx(s []float64, v float64) int { - if len(s) == 0 { - panic(zeroLength) - } - switch { - case math.IsNaN(v): - return 0 - case math.IsInf(v, 1): - return MaxIdx(s) - case math.IsInf(v, -1): - return MinIdx(s) - } - var ind int - dist := math.NaN() - for i, val := range s { - newDist := math.Abs(v - val) - // A NaN distance will not be closer. - if math.IsNaN(newDist) { - continue - } - if newDist < dist || math.IsNaN(dist) { - dist = newDist - ind = i - } - } - return ind -} - -// NearestIdxForSpan return the index of a hypothetical vector created -// by Span with length n and bounds l and u whose value is closest -// to v. That is, NearestIdxForSpan(n, l, u, v) is equivalent to -// Nearest(Span(make([]float64, n),l,u),v) without an allocation. -// It panics if n is less than two. -func NearestIdxForSpan(n int, l, u float64, v float64) int { - if n < 2 { - panic(shortSpan) - } - if math.IsNaN(v) { - return 0 - } - - // Special cases for Inf and NaN. - switch { - case math.IsNaN(l) && !math.IsNaN(u): - return n - 1 - case math.IsNaN(u): - return 0 - case math.IsInf(l, 0) && math.IsInf(u, 0): - if l == u { - return 0 - } - if n%2 == 1 { - if !math.IsInf(v, 0) { - return n / 2 - } - if math.Copysign(1, v) == math.Copysign(1, l) { - return 0 - } - return n/2 + 1 - } - if math.Copysign(1, v) == math.Copysign(1, l) { - return 0 - } - return n / 2 - case math.IsInf(l, 0): - if v == l { - return 0 - } - return n - 1 - case math.IsInf(u, 0): - if v == u { - return n - 1 - } - return 0 - case math.IsInf(v, -1): - if l <= u { - return 0 - } - return n - 1 - case math.IsInf(v, 1): - if u <= l { - return 0 - } - return n - 1 - } - - // Special cases for v outside (l, u) and (u, l). - switch { - case l < u: - if v <= l { - return 0 - } - if v >= u { - return n - 1 - } - case l > u: - if v >= l { - return 0 - } - if v <= u { - return n - 1 - } - default: - return 0 - } - - // Can't guarantee anything about exactly halfway between - // because of floating point weirdness. - return int((float64(n)-1)/(u-l)*(v-l) + 0.5) -} - -// Norm returns the L norm of the slice S, defined as -// (sum_{i=1}^N s[i]^L)^{1/L} -// Special cases: -// L = math.Inf(1) gives the maximum absolute value. -// Does not correctly compute the zero norm (use Count). -func Norm(s []float64, L float64) float64 { - // Should this complain if L is not positive? - // Should this be done in log space for better numerical stability? - // would be more cost - // maybe only if L is high? - if len(s) == 0 { - return 0 - } - if L == 2 { - return f64.L2NormUnitary(s) - } - var norm float64 - if L == 1 { - for _, val := range s { - norm += math.Abs(val) - } - return norm - } - if math.IsInf(L, 1) { - for _, val := range s { - norm = math.Max(norm, math.Abs(val)) - } - return norm - } - for _, val := range s { - norm += math.Pow(math.Abs(val), L) - } - return math.Pow(norm, 1/L) -} - -// Prod returns the product of the elements of the slice. -// Returns 1 if len(s) = 0. -func Prod(s []float64) float64 { - prod := 1.0 - for _, val := range s { - prod *= val - } - return prod -} - -// Reverse reverses the order of elements in the slice. -// -// Deprecated: This function simply calls [slices.Reverse]. -func Reverse(s []float64) { - slices.Reverse(s) -} - -// Same returns true when the input slices have the same length and all -// elements have the same value with NaN treated as the same. -func Same(s, t []float64) bool { - if len(s) != len(t) { - return false - } - for i, v := range s { - w := t[i] - if v != w && !(math.IsNaN(v) && math.IsNaN(w)) { - return false - } - } - return true -} - -// Scale multiplies every element in dst by the scalar c. -func Scale(c float64, dst []float64) { - if len(dst) > 0 { - f64.ScalUnitary(c, dst) - } -} - -// ScaleTo multiplies the elements in s by c and stores the result in dst. -// It panics if the slice argument lengths do not match. -func ScaleTo(dst []float64, c float64, s []float64) []float64 { - if len(dst) != len(s) { - panic(badDstLength) - } - if len(dst) > 0 { - f64.ScalUnitaryTo(dst, c, s) - } - return dst -} - -// Span returns a set of N equally spaced points between l and u, where N -// is equal to the length of the destination. The first element of the destination -// is l, the final element of the destination is u. -// It panics if the length of dst is less than 2. -// -// Span also returns the mutated slice dst, so that it can be used in range expressions, -// like: -// -// for i, x := range Span(dst, l, u) { ... } -func Span(dst []float64, l, u float64) []float64 { - n := len(dst) - if n < 2 { - panic(shortSpan) - } - - // Special cases for Inf and NaN. - switch { - case math.IsNaN(l): - for i := range dst[:len(dst)-1] { - dst[i] = math.NaN() - } - dst[len(dst)-1] = u - return dst - case math.IsNaN(u): - for i := range dst[1:] { - dst[i+1] = math.NaN() - } - dst[0] = l - return dst - case math.IsInf(l, 0) && math.IsInf(u, 0): - for i := range dst[:len(dst)/2] { - dst[i] = l - dst[len(dst)-i-1] = u - } - if len(dst)%2 == 1 { - if l != u { - dst[len(dst)/2] = 0 - } else { - dst[len(dst)/2] = l - } - } - return dst - case math.IsInf(l, 0): - for i := range dst[:len(dst)-1] { - dst[i] = l - } - dst[len(dst)-1] = u - return dst - case math.IsInf(u, 0): - for i := range dst[1:] { - dst[i+1] = u - } - dst[0] = l - return dst - } - - step := (u - l) / float64(n-1) - for i := range dst { - dst[i] = l + step*float64(i) - } - return dst -} - -// Sub subtracts, element-wise, the elements of s from dst. -// It panics if the argument lengths do not match. -func Sub(dst, s []float64) { - if len(dst) != len(s) { - panic(badLength) - } - f64.AxpyUnitaryTo(dst, -1, s, dst) -} - -// SubTo subtracts, element-wise, the elements of t from s and -// stores the result in dst. -// It panics if the argument lengths do not match. -func SubTo(dst, s, t []float64) []float64 { - if len(s) != len(t) { - panic(badLength) - } - if len(dst) != len(s) { - panic(badDstLength) - } - f64.AxpyUnitaryTo(dst, -1, t, s) - return dst -} - -// Sum returns the sum of the elements of the slice. -func Sum(s []float64) float64 { - return f64.Sum(s) -} - -// Within returns the first index i where s[i] <= v < s[i+1]. Within panics if: -// - len(s) < 2 -// - s is not sorted -func Within(s []float64, v float64) int { - if len(s) < 2 { - panic(shortSpan) - } - if !sort.Float64sAreSorted(s) { - panic("floats: input slice not sorted") - } - if v < s[0] || v >= s[len(s)-1] || math.IsNaN(v) { - return -1 - } - for i, f := range s[1:] { - if v < f { - return i - } - } - return -1 -} - -// SumCompensated returns the sum of the elements of the slice calculated with greater -// accuracy than Sum at the expense of additional computation. -func SumCompensated(s []float64) float64 { - // SumCompensated uses an improved version of Kahan's compensated - // summation algorithm proposed by Neumaier. - // See https://en.wikipedia.org/wiki/Kahan_summation_algorithm for details. - var sum, c float64 - for _, x := range s { - // This type conversion is here to prevent a sufficiently smart compiler - // from optimising away these operations. - t := float64(sum + x) - if math.Abs(sum) >= math.Abs(x) { - c += (sum - t) + x - } else { - c += (x - t) + sum - } - sum = t - } - return sum + c -} diff --git a/vendor/gonum.org/v1/gonum/floats/scalar/doc.go b/vendor/gonum.org/v1/gonum/floats/scalar/doc.go deleted file mode 100644 index 9e69c193..00000000 --- a/vendor/gonum.org/v1/gonum/floats/scalar/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 scalar provides a set of helper routines for dealing with float64 values. -package scalar // import "gonum.org/v1/gonum/floats/scalar" diff --git a/vendor/gonum.org/v1/gonum/floats/scalar/scalar.go b/vendor/gonum.org/v1/gonum/floats/scalar/scalar.go deleted file mode 100644 index 46bf06b3..00000000 --- a/vendor/gonum.org/v1/gonum/floats/scalar/scalar.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright ©2013 The Gonum Authors. All rights reserved. -// Use of this code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package scalar - -import ( - "math" - "strconv" -) - -// EqualWithinAbs returns true when a and b have an absolute difference -// not greater than tol. -func EqualWithinAbs(a, b, tol float64) bool { - return a == b || math.Abs(a-b) <= tol -} - -// minNormalFloat64 is the smallest normal number. For 64 bit IEEE-754 -// floats this is 2^{-1022}. -const minNormalFloat64 = 0x1p-1022 - -// EqualWithinRel returns true when the difference between a and b -// is not greater than tol times the greater absolute value of a and b, -// -// abs(a-b) <= tol * max(abs(a), abs(b)). -func EqualWithinRel(a, b, tol float64) bool { - if a == b { - return true - } - delta := math.Abs(a - b) - if delta <= minNormalFloat64 { - return delta <= tol*minNormalFloat64 - } - // We depend on the division in this relationship to identify - // infinities (we rely on the NaN to fail the test) otherwise - // we compare Infs of the same sign and evaluate Infs as equal - // independent of sign. - return delta/math.Max(math.Abs(a), math.Abs(b)) <= tol -} - -// EqualWithinAbsOrRel returns true when a and b are equal to within -// the absolute or relative tolerances. See EqualWithinAbs and -// EqualWithinRel for details. -func EqualWithinAbsOrRel(a, b, absTol, relTol float64) bool { - return EqualWithinAbs(a, b, absTol) || EqualWithinRel(a, b, relTol) -} - -// EqualWithinULP returns true when a and b are equal to within -// the specified number of floating point units in the last place. -func EqualWithinULP(a, b float64, ulp uint) bool { - if a == b { - return true - } - if math.IsNaN(a) || math.IsNaN(b) { - return false - } - if math.Signbit(a) != math.Signbit(b) { - return math.Float64bits(math.Abs(a))+math.Float64bits(math.Abs(b)) <= uint64(ulp) - } - return ulpDiff(math.Float64bits(a), math.Float64bits(b)) <= uint64(ulp) -} - -func ulpDiff(a, b uint64) uint64 { - if a > b { - return a - b - } - return b - a -} - -const ( - nanBits = 0x7ff8000000000000 - nanMask = 0xfff8000000000000 -) - -// NaNWith returns an IEEE 754 "quiet not-a-number" value with the -// payload specified in the low 51 bits of payload. -// The NaN returned by math.NaN has a bit pattern equal to NaNWith(1). -func NaNWith(payload uint64) float64 { - return math.Float64frombits(nanBits | (payload &^ nanMask)) -} - -// NaNPayload returns the lowest 51 bits payload of an IEEE 754 "quiet -// not-a-number". For values of f other than quiet-NaN, NaNPayload -// returns zero and false. -func NaNPayload(f float64) (payload uint64, ok bool) { - b := math.Float64bits(f) - if b&nanBits != nanBits { - return 0, false - } - return b &^ nanMask, true -} - -// ParseWithNA converts the string s to a float64 in value. -// If s equals missing, weight is returned as 0, otherwise 1. -func ParseWithNA(s, missing string) (value, weight float64, err error) { - if s == missing { - return 0, 0, nil - } - value, err = strconv.ParseFloat(s, 64) - if err == nil { - weight = 1 - } - return value, weight, err -} - -// Round returns the half away from zero rounded value of x with prec precision. -// -// Special cases are: -// -// Round(±0) = +0 -// Round(±Inf) = ±Inf -// Round(NaN) = NaN -func Round(x float64, prec int) float64 { - if x == 0 { - // Make sure zero is returned - // without the negative bit set. - return 0 - } - // Fast path for positive precision on integers. - if prec >= 0 && x == math.Trunc(x) { - return x - } - pow := math.Pow10(prec) - intermed := x * pow - if math.IsInf(intermed, 0) { - return x - } - x = math.Round(intermed) - - if x == 0 { - return 0 - } - - return x / pow -} - -// RoundEven returns the half even rounded value of x with prec precision. -// -// Special cases are: -// -// RoundEven(±0) = +0 -// RoundEven(±Inf) = ±Inf -// RoundEven(NaN) = NaN -func RoundEven(x float64, prec int) float64 { - if x == 0 { - // Make sure zero is returned - // without the negative bit set. - return 0 - } - // Fast path for positive precision on integers. - if prec >= 0 && x == math.Trunc(x) { - return x - } - pow := math.Pow10(prec) - intermed := x * pow - if math.IsInf(intermed, 0) { - return x - } - x = math.RoundToEven(intermed) - - if x == 0 { - return 0 - } - - return x / pow -} - -// Same returns true when the inputs have the same value, allowing NaN equality. -func Same(a, b float64) bool { - return a == b || (math.IsNaN(a) && math.IsNaN(b)) -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s deleted file mode 100644 index d9b71a0d..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyinc_amd64.s +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVDDUP X2, X3 -#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA -// MOVDDUP X4, X5 -#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC -// MOVDDUP X6, X7 -#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE -// MOVDDUP X8, X9 -#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 - -// ADDSUBPD X2, X3 -#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA -// ADDSUBPD X4, X5 -#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC -// ADDSUBPD X6, X7 -#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE -// ADDSUBPD X8, X9 -#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyInc(SB), NOSPLIT, $0 - MOVQ x_base+16(FP), SI // SI = &x - MOVQ y_base+40(FP), DI // DI = &y - MOVQ n+64(FP), CX // CX = n - CMPQ CX, $0 // if n==0 { return } - JE axpyi_end - MOVQ ix+88(FP), R8 // R8 = ix // Load the first index - SHLQ $4, R8 // R8 *= sizeof(complex128) - MOVQ iy+96(FP), R9 // R9 = iy - SHLQ $4, R9 // R9 *= sizeof(complex128) - LEAQ (SI)(R8*1), SI // SI = &(x[ix]) - LEAQ (DI)(R9*1), DI // DI = &(y[iy]) - MOVQ DI, DX // DX = DI // Separate Read/Write pointers - MOVQ incX+72(FP), R8 // R8 = incX - SHLQ $4, R8 // R8 *= sizeof(complex128) - MOVQ incY+80(FP), R9 // R9 = iy - SHLQ $4, R9 // R9 *= sizeof(complex128) - MOVUPS alpha+0(FP), X0 // X0 = { imag(a), real(a) } - MOVAPS X0, X1 - SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } - MOVAPS X0, X10 // Copy X0 and X1 for pipelining - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $3, CX // CX = n % 4 - SHRQ $2, BX // BX = floor( n / 4 ) - JZ axpyi_tail // if BX == 0 { goto axpyi_tail } - -axpyi_loop: // do { - MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVUPS (SI)(R8*1), X4 - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - MOVUPS (SI), X6 - MOVUPS (SI)(R8*1), X8 - - // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_X2_X3 - MOVDDUP_X4_X5 - MOVDDUP_X6_X7 - MOVDDUP_X8_X9 - - // X_i = { imag(x[i]), imag(x[i]) } - SHUFPD $0x3, X2, X2 - SHUFPD $0x3, X4, X4 - SHUFPD $0x3, X6, X6 - SHUFPD $0x3, X8, X8 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X1, X2 - MULPD X0, X3 - MULPD X11, X4 - MULPD X10, X5 - MULPD X1, X6 - MULPD X0, X7 - MULPD X11, X8 - MULPD X10, X9 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DX), X3 - ADDPD (DX)(R9*1), X5 - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - ADDPD (DX), X7 - ADDPD (DX)(R9*1), X9 - MOVUPS X3, (DI) // dst[i] = X_(i+1) - MOVUPS X5, (DI)(R9*1) - LEAQ (DI)(R9*2), DI - MOVUPS X7, (DI) - MOVUPS X9, (DI)(R9*1) - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) - DECQ BX - JNZ axpyi_loop // } while --BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE axpyi_end - -axpyi_tail: // do { - MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } - SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } - MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DI), X3 - MOVUPS X3, (DI) // y[i] = X_i - ADDQ R8, SI // SI = &(SI[incX]) - ADDQ R9, DI // DI = &(DI[incY]) - LOOP axpyi_tail // } while --CX > 0 - -axpyi_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s deleted file mode 100644 index d35e95d9..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyincto_amd64.s +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVDDUP X2, X3 -#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA -// MOVDDUP X4, X5 -#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC -// MOVDDUP X6, X7 -#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE -// MOVDDUP X8, X9 -#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 - -// ADDSUBPD X2, X3 -#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA -// ADDSUBPD X4, X5 -#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC -// ADDSUBPD X6, X7 -#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE -// ADDSUBPD X8, X9 -#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyIncTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ x_base+56(FP), SI // SI = &x - MOVQ y_base+80(FP), DX // DX = &y - MOVQ n+104(FP), CX // CX = n - CMPQ CX, $0 // if n==0 { return } - JE axpyi_end - MOVQ ix+128(FP), R8 // R8 = ix // Load the first index - SHLQ $4, R8 // R8 *= sizeof(complex128) - MOVQ iy+136(FP), R9 // R9 = iy - SHLQ $4, R9 // R9 *= sizeof(complex128) - MOVQ idst+32(FP), R10 // R10 = idst - SHLQ $4, R10 // R10 *= sizeof(complex128) - LEAQ (SI)(R8*1), SI // SI = &(x[ix]) - LEAQ (DX)(R9*1), DX // DX = &(y[iy]) - LEAQ (DI)(R10*1), DI // DI = &(dst[idst]) - MOVQ incX+112(FP), R8 // R8 = incX - SHLQ $4, R8 // R8 *= sizeof(complex128) - MOVQ incY+120(FP), R9 // R9 = incY - SHLQ $4, R9 // R9 *= sizeof(complex128) - MOVQ incDst+24(FP), R10 // R10 = incDst - SHLQ $4, R10 // R10 *= sizeof(complex128) - MOVUPS alpha+40(FP), X0 // X0 = { imag(a), real(a) } - MOVAPS X0, X1 - SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } - MOVAPS X0, X10 // Copy X0 and X1 for pipelining - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $3, CX // CX = n % 4 - SHRQ $2, BX // BX = floor( n / 4 ) - JZ axpyi_tail // if BX == 0 { goto axpyi_tail } - -axpyi_loop: // do { - MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVUPS (SI)(R8*1), X4 - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - - MOVUPS (SI), X6 - MOVUPS (SI)(R8*1), X8 - - // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_X2_X3 - MOVDDUP_X4_X5 - MOVDDUP_X6_X7 - MOVDDUP_X8_X9 - - // X_i = { imag(x[i]), imag(x[i]) } - SHUFPD $0x3, X2, X2 - SHUFPD $0x3, X4, X4 - SHUFPD $0x3, X6, X6 - SHUFPD $0x3, X8, X8 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X1, X2 - MULPD X0, X3 - MULPD X11, X4 - MULPD X10, X5 - MULPD X1, X6 - MULPD X0, X7 - MULPD X11, X8 - MULPD X10, X9 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DX), X3 - ADDPD (DX)(R9*1), X5 - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - ADDPD (DX), X7 - ADDPD (DX)(R9*1), X9 - MOVUPS X3, (DI) // dst[i] = X_(i+1) - MOVUPS X5, (DI)(R10*1) - LEAQ (DI)(R10*2), DI - MOVUPS X7, (DI) - MOVUPS X9, (DI)(R10*1) - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) - DECQ BX - JNZ axpyi_loop // } while --BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE axpyi_end - -axpyi_tail: // do { - MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } - SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } - MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DX), X3 - MOVUPS X3, (DI) // y[i] X_(i+1) - ADDQ R8, SI // SI += incX - ADDQ R9, DX // DX += incY - ADDQ R10, DI // DI += incDst - LOOP axpyi_tail // } while --CX > 0 - -axpyi_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s deleted file mode 100644 index a6783255..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitary_amd64.s +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVDDUP X2, X3 -#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA -// MOVDDUP X4, X5 -#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC -// MOVDDUP X6, X7 -#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE -// MOVDDUP X8, X9 -#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 - -// ADDSUBPD X2, X3 -#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA -// ADDSUBPD X4, X5 -#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC -// ADDSUBPD X6, X7 -#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE -// ADDSUBPD X8, X9 -#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyUnitary(alpha complex128, x, y []complex128) -TEXT ·AxpyUnitary(SB), NOSPLIT, $0 - MOVQ x_base+16(FP), SI // SI = &x - MOVQ y_base+40(FP), DI // DI = &y - MOVQ x_len+24(FP), CX // CX = min( len(x), len(y) ) - CMPQ y_len+48(FP), CX - CMOVQLE y_len+48(FP), CX - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - PXOR X0, X0 // Clear work registers and cache-align loop - PXOR X1, X1 - MOVUPS alpha+0(FP), X0 // X0 = { imag(a), real(a) } - MOVAPS X0, X1 - SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } - XORQ AX, AX // i = 0 - MOVAPS X0, X10 // Copy X0 and X1 for pipelining - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $3, CX // CX = n % 4 - SHRQ $2, BX // BX = floor( n / 4 ) - JZ caxy_tail // if BX == 0 { goto caxy_tail } - -caxy_loop: // do { - MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVUPS 16(SI)(AX*8), X4 - MOVUPS 32(SI)(AX*8), X6 - MOVUPS 48(SI)(AX*8), X8 - - // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_X2_X3 - MOVDDUP_X4_X5 - MOVDDUP_X6_X7 - MOVDDUP_X8_X9 - - // X_i = { imag(x[i]), imag(x[i]) } - SHUFPD $0x3, X2, X2 - SHUFPD $0x3, X4, X4 - SHUFPD $0x3, X6, X6 - SHUFPD $0x3, X8, X8 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X1, X2 - MULPD X0, X3 - MULPD X11, X4 - MULPD X10, X5 - MULPD X1, X6 - MULPD X0, X7 - MULPD X11, X8 - MULPD X10, X9 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DI)(AX*8), X3 - ADDPD 16(DI)(AX*8), X5 - ADDPD 32(DI)(AX*8), X7 - ADDPD 48(DI)(AX*8), X9 - MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) - MOVUPS X5, 16(DI)(AX*8) - MOVUPS X7, 32(DI)(AX*8) - MOVUPS X9, 48(DI)(AX*8) - ADDQ $8, AX // i += 8 - DECQ BX - JNZ caxy_loop // } while --BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - -caxy_tail: // do { - MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } - SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } - MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DI)(AX*8), X3 - MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) - ADDQ $2, AX // i += 2 - LOOP caxy_tail // } while --CX > 0 - -caxy_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s deleted file mode 100644 index 64add688..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/axpyunitaryto_amd64.s +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVDDUP X2, X3 -#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA -// MOVDDUP X4, X5 -#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC -// MOVDDUP X6, X7 -#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE -// MOVDDUP X8, X9 -#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 - -// ADDSUBPD X2, X3 -#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA -// ADDSUBPD X4, X5 -#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC -// ADDSUBPD X6, X7 -#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE -// ADDSUBPD X8, X9 -#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyUnitaryTo(dst []complex128, alpha complex64, x, y []complex128) -TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ x_base+40(FP), SI // SI = &x - MOVQ y_base+64(FP), DX // DX = &y - MOVQ x_len+48(FP), CX // CX = min( len(x), len(y), len(dst) ) - CMPQ y_len+72(FP), CX - CMOVQLE y_len+72(FP), CX - CMPQ dst_len+8(FP), CX - CMOVQLE dst_len+8(FP), CX - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - MOVUPS alpha+24(FP), X0 // X0 = { imag(a), real(a) } - MOVAPS X0, X1 - SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } - XORQ AX, AX // i = 0 - MOVAPS X0, X10 // Copy X0 and X1 for pipelining - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $3, CX // CX = n % 4 - SHRQ $2, BX // BX = floor( n / 4 ) - JZ caxy_tail // if BX == 0 { goto caxy_tail } - -caxy_loop: // do { - MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVUPS 16(SI)(AX*8), X4 - MOVUPS 32(SI)(AX*8), X6 - MOVUPS 48(SI)(AX*8), X8 - - // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_X2_X3 // Load and duplicate imag elements (xi, xi) - MOVDDUP_X4_X5 - MOVDDUP_X6_X7 - MOVDDUP_X8_X9 - - // X_i = { imag(x[i]), imag(x[i]) } - SHUFPD $0x3, X2, X2 // duplicate real elements (xr, xr) - SHUFPD $0x3, X4, X4 - SHUFPD $0x3, X6, X6 - SHUFPD $0x3, X8, X8 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X1, X2 - MULPD X0, X3 - MULPD X11, X4 - MULPD X10, X5 - MULPD X1, X6 - MULPD X0, X7 - MULPD X11, X8 - MULPD X10, X9 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DX)(AX*8), X3 - ADDPD 16(DX)(AX*8), X5 - ADDPD 32(DX)(AX*8), X7 - ADDPD 48(DX)(AX*8), X9 - MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) - MOVUPS X5, 16(DI)(AX*8) - MOVUPS X7, 32(DI)(AX*8) - MOVUPS X9, 48(DI)(AX*8) - ADDQ $8, AX // i += 8 - DECQ BX - JNZ caxy_loop // } while --BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - -caxy_tail: // Same calculation, but read in values to avoid trampling memory - MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } - SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } - MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - - // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - ADDPD (DX)(AX*8), X3 - MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) - ADDQ $2, AX // i += 2 - LOOP caxy_tail // } while --CX > 0 - -caxy_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go deleted file mode 100644 index 8802ff13..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 c128 provides complex128 vector primitives. -package c128 // import "gonum.org/v1/gonum/internal/asm/c128" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotcinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotcinc_amd64.s deleted file mode 100644 index 235f67e7..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotcinc_amd64.s +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVDDUP_XPTR__X3 LONG $0x1E120FF2 // MOVDDUP (SI), X3 -#define MOVDDUP_XPTR_INCX__X5 LONG $0x120F42F2; WORD $0x062C // MOVDDUP (SI)(R8*1), X5 -#define MOVDDUP_XPTR_INCX_2__X7 LONG $0x120F42F2; WORD $0x463C // MOVDDUP (SI)(R8*2), X7 -#define MOVDDUP_XPTR_INCx3X__X9 LONG $0x120F46F2; WORD $0x0E0C // MOVDDUP (SI)(R9*1), X9 - -#define MOVDDUP_8_XPTR__X2 LONG $0x56120FF2; BYTE $0x08 // MOVDDUP 8(SI), X2 -#define MOVDDUP_8_XPTR_INCX__X4 LONG $0x120F42F2; WORD $0x0664; BYTE $0x08 // MOVDDUP 8(SI)(R8*1), X4 -#define MOVDDUP_8_XPTR_INCX_2__X6 LONG $0x120F42F2; WORD $0x4674; BYTE $0x08 // MOVDDUP 8(SI)(R8*2), X6 -#define MOVDDUP_8_XPTR_INCx3X__X8 LONG $0x120F46F2; WORD $0x0E44; BYTE $0x08 // MOVDDUP 8(SI)(R9*1), X8 - -#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 -#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 -#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 -#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define INC_X R8 -#define INCx3_X R9 -#define INC_Y R10 -#define INCx3_Y R11 -#define NEG1 X15 -#define P_NEG1 X14 - -// func DotcInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) -TEXT ·DotcInc(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - MOVQ n+48(FP), LEN // LEN = n - PXOR SUM, SUM // SUM = 0 - CMPQ LEN, $0 // if LEN == 0 { return } - JE dot_end - PXOR P_SUM, P_SUM // P_SUM = 0 - MOVQ ix+72(FP), INC_X // INC_X = ix * sizeof(complex128) - SHLQ $4, INC_X - MOVQ iy+80(FP), INC_Y // INC_Y = iy * sizeof(complex128) - SHLQ $4, INC_Y - LEAQ (X_PTR)(INC_X*1), X_PTR // X_PTR = &(X_PTR[ix]) - LEAQ (Y_PTR)(INC_Y*1), Y_PTR // Y_PTR = &(Y_PTR[iy]) - MOVQ incX+56(FP), INC_X // INC_X = incX - SHLQ $4, INC_X // INC_X *= sizeof(complex128) - MOVQ incY+64(FP), INC_Y // INC_Y = incY - SHLQ $4, INC_Y // INC_Y *= sizeof(complex128) - MOVSD $(-1.0), NEG1 - SHUFPD $0, NEG1, NEG1 // { -1, -1 } - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = n % 4 - SHRQ $2, LEN // LEN = floor( n / 4 ) - JZ dot_tail // if n <= 4 { goto dot_tail } - MOVAPS NEG1, P_NEG1 // Copy NEG1 to P_NEG1 for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = 3 * incX * sizeof(complex128) - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = 3 * incY * sizeof(complex128) - -dot_loop: // do { - MOVDDUP_XPTR__X3 // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_XPTR_INCX__X5 - MOVDDUP_XPTR_INCX_2__X7 - MOVDDUP_XPTR_INCx3X__X9 - - MOVDDUP_8_XPTR__X2 // X_i = { imag(x[i]), imag(x[i]) } - MOVDDUP_8_XPTR_INCX__X4 - MOVDDUP_8_XPTR_INCX_2__X6 - MOVDDUP_8_XPTR_INCx3X__X8 - - // X_i = { -imag(x[i]), -imag(x[i]) } - MULPD NEG1, X2 - MULPD P_NEG1, X4 - MULPD NEG1, X6 - MULPD P_NEG1, X8 - - // X_j = { imag(y[i]), real(y[i]) } - MOVUPS (Y_PTR), X10 - MOVUPS (Y_PTR)(INC_Y*1), X11 - MOVUPS (Y_PTR)(INC_Y*2), X12 - MOVUPS (Y_PTR)(INCx3_Y*1), X13 - - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X10, X3 - MULPD X11, X5 - MULPD X12, X7 - MULPD X13, X9 - - // X_j = { real(y[i]), imag(y[i]) } - SHUFPD $0x1, X10, X10 - SHUFPD $0x1, X11, X11 - SHUFPD $0x1, X12, X12 - SHUFPD $0x1, X13, X13 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X10, X2 - MULPD X11, X4 - MULPD X12, X6 - MULPD X13, X8 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // psum += result[i] - ADDPD X3, SUM - ADDPD X5, P_SUM - ADDPD X7, SUM - ADDPD X9, P_SUM - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) - - DECQ LEN - JNZ dot_loop // } while --LEN > 0 - ADDPD P_SUM, SUM // sum += psum - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail: // do { - MOVDDUP_XPTR__X3 // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_8_XPTR__X2 // X_i = { imag(x[i]), imag(x[i]) } - MULPD NEG1, X2 // X_i = { -imag(x[i]) , -imag(x[i]) } - MOVUPS (Y_PTR), X10 // X_j = { imag(y[i]) , real(y[i]) } - MULPD X10, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - SHUFPD $0x1, X10, X10 // X_j = { real(y[i]) , imag(y[i]) } - MULPD X10, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDPD X3, SUM // sum += result[i] - ADDQ INC_X, X_PTR // X_PTR += incX - ADDQ INC_Y, Y_PTR // Y_PTR += incY - DECQ TAIL - JNZ dot_tail // } while --TAIL > 0 - -dot_end: - MOVUPS SUM, sum+88(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotcunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotcunitary_amd64.s deleted file mode 100644 index 0ffd0f12..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotcunitary_amd64.s +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVDDUP_XPTR_IDX_8__X3 LONG $0x1C120FF2; BYTE $0xC6 // MOVDDUP (SI)(AX*8), X3 -#define MOVDDUP_16_XPTR_IDX_8__X5 LONG $0x6C120FF2; WORD $0x10C6 // MOVDDUP 16(SI)(AX*8), X5 -#define MOVDDUP_32_XPTR_IDX_8__X7 LONG $0x7C120FF2; WORD $0x20C6 // MOVDDUP 32(SI)(AX*8), X7 -#define MOVDDUP_48_XPTR_IDX_8__X9 LONG $0x120F44F2; WORD $0xC64C; BYTE $0x30 // MOVDDUP 48(SI)(AX*8), X9 - -#define MOVDDUP_XPTR_IIDX_8__X2 LONG $0x14120FF2; BYTE $0xD6 // MOVDDUP (SI)(DX*8), X2 -#define MOVDDUP_16_XPTR_IIDX_8__X4 LONG $0x64120FF2; WORD $0x10D6 // MOVDDUP 16(SI)(DX*8), X4 -#define MOVDDUP_32_XPTR_IIDX_8__X6 LONG $0x74120FF2; WORD $0x20D6 // MOVDDUP 32(SI)(DX*8), X6 -#define MOVDDUP_48_XPTR_IIDX_8__X8 LONG $0x120F44F2; WORD $0xD644; BYTE $0x30 // MOVDDUP 48(SI)(DX*8), X8 - -#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 -#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 -#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 -#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define IDX AX -#define I_IDX DX -#define NEG1 X15 -#define P_NEG1 X14 - -// func DotcUnitary(x, y []complex128) (sum complex128) -TEXT ·DotcUnitary(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+32(FP), LEN - CMOVQLE y_len+32(FP), LEN - PXOR SUM, SUM // sum = 0 - CMPQ LEN, $0 // if LEN == 0 { return } - JE dot_end - XORPS P_SUM, P_SUM // psum = 0 - MOVSD $(-1.0), NEG1 - SHUFPD $0, NEG1, NEG1 // { -1, -1 } - XORQ IDX, IDX // i := 0 - MOVQ $1, I_IDX // j := 1 - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = floor( TAIL / 4 ) - SHRQ $2, LEN // LEN = TAIL % 4 - JZ dot_tail // if LEN == 0 { goto dot_tail } - - MOVAPS NEG1, P_NEG1 // Copy NEG1 to P_NEG1 for pipelining - -dot_loop: // do { - MOVDDUP_XPTR_IDX_8__X3 // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_16_XPTR_IDX_8__X5 - MOVDDUP_32_XPTR_IDX_8__X7 - MOVDDUP_48_XPTR_IDX_8__X9 - - MOVDDUP_XPTR_IIDX_8__X2 // X_i = { imag(x[i]), imag(x[i]) } - MOVDDUP_16_XPTR_IIDX_8__X4 - MOVDDUP_32_XPTR_IIDX_8__X6 - MOVDDUP_48_XPTR_IIDX_8__X8 - - // X_i = { -imag(x[i]), -imag(x[i]) } - MULPD NEG1, X2 - MULPD P_NEG1, X4 - MULPD NEG1, X6 - MULPD P_NEG1, X8 - - // X_j = { imag(y[i]), real(y[i]) } - MOVUPS (Y_PTR)(IDX*8), X10 - MOVUPS 16(Y_PTR)(IDX*8), X11 - MOVUPS 32(Y_PTR)(IDX*8), X12 - MOVUPS 48(Y_PTR)(IDX*8), X13 - - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X10, X3 - MULPD X11, X5 - MULPD X12, X7 - MULPD X13, X9 - - // X_j = { real(y[i]), imag(y[i]) } - SHUFPD $0x1, X10, X10 - SHUFPD $0x1, X11, X11 - SHUFPD $0x1, X12, X12 - SHUFPD $0x1, X13, X13 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X10, X2 - MULPD X11, X4 - MULPD X12, X6 - MULPD X13, X8 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // psum += result[i] - ADDPD X3, SUM - ADDPD X5, P_SUM - ADDPD X7, SUM - ADDPD X9, P_SUM - - ADDQ $8, IDX // IDX += 8 - ADDQ $8, I_IDX // I_IDX += 8 - DECQ LEN - JNZ dot_loop // } while --LEN > 0 - ADDPD P_SUM, SUM // sum += psum - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail: // do { - MOVDDUP_XPTR_IDX_8__X3 // X_(i+1) = { real(x[i]) , real(x[i]) } - MOVDDUP_XPTR_IIDX_8__X2 // X_i = { imag(x[i]) , imag(x[i]) } - MULPD NEG1, X2 // X_i = { -imag(x[i]) , -imag(x[i]) } - MOVUPS (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]) , real(y[i]) } - MULPD X10, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - SHUFPD $0x1, X10, X10 // X_j = { real(y[i]) , imag(y[i]) } - MULPD X10, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDPD X3, SUM // SUM += result[i] - ADDQ $2, IDX // IDX += 2 - ADDQ $2, I_IDX // I_IDX += 2 - DECQ TAIL - JNZ dot_tail // } while --TAIL > 0 - -dot_end: - MOVUPS SUM, sum+48(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotuinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotuinc_amd64.s deleted file mode 100644 index 74fe5c3b..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotuinc_amd64.s +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVDDUP_XPTR__X3 LONG $0x1E120FF2 // MOVDDUP (SI), X3 -#define MOVDDUP_XPTR_INCX__X5 LONG $0x120F42F2; WORD $0x062C // MOVDDUP (SI)(R8*1), X5 -#define MOVDDUP_XPTR_INCX_2__X7 LONG $0x120F42F2; WORD $0x463C // MOVDDUP (SI)(R8*2), X7 -#define MOVDDUP_XPTR_INCx3X__X9 LONG $0x120F46F2; WORD $0x0E0C // MOVDDUP (SI)(R9*1), X9 - -#define MOVDDUP_8_XPTR__X2 LONG $0x56120FF2; BYTE $0x08 // MOVDDUP 8(SI), X2 -#define MOVDDUP_8_XPTR_INCX__X4 LONG $0x120F42F2; WORD $0x0664; BYTE $0x08 // MOVDDUP 8(SI)(R8*1), X4 -#define MOVDDUP_8_XPTR_INCX_2__X6 LONG $0x120F42F2; WORD $0x4674; BYTE $0x08 // MOVDDUP 8(SI)(R8*2), X6 -#define MOVDDUP_8_XPTR_INCx3X__X8 LONG $0x120F46F2; WORD $0x0E44; BYTE $0x08 // MOVDDUP 8(SI)(R9*1), X8 - -#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 -#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 -#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 -#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define INC_X R8 -#define INCx3_X R9 -#define INC_Y R10 -#define INCx3_Y R11 - -// func DotuInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) -TEXT ·DotuInc(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - MOVQ n+48(FP), LEN // LEN = n - PXOR SUM, SUM // sum = 0 - CMPQ LEN, $0 // if LEN == 0 { return } - JE dot_end - MOVQ ix+72(FP), INC_X // INC_X = ix * sizeof(complex128) - SHLQ $4, INC_X - MOVQ iy+80(FP), INC_Y // INC_Y = iy * sizeof(complex128) - SHLQ $4, INC_Y - LEAQ (X_PTR)(INC_X*1), X_PTR // X_PTR = &(X_PTR[ix]) - LEAQ (Y_PTR)(INC_Y*1), Y_PTR // Y_PTR = &(Y_PTR[iy]) - MOVQ incX+56(FP), INC_X // INC_X = incX - SHLQ $4, INC_X // INC_X *= sizeof(complex128) - MOVQ incY+64(FP), INC_Y // INC_Y = incY - SHLQ $4, INC_Y // INC_Y *= sizeof(complex128) - MOVQ LEN, TAIL - ANDQ $3, TAIL // LEN = LEN % 4 - SHRQ $2, LEN // LEN = floor( LEN / 4 ) - JZ dot_tail // if LEN <= 4 { goto dot_tail } - PXOR P_SUM, P_SUM // psum = 0 - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = 3 * incX * sizeof(complex128) - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = 3 * incY * sizeof(complex128) - -dot_loop: // do { - MOVDDUP_XPTR__X3 // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_XPTR_INCX__X5 - MOVDDUP_XPTR_INCX_2__X7 - MOVDDUP_XPTR_INCx3X__X9 - - MOVDDUP_8_XPTR__X2 // X_i = { imag(x[i]), imag(x[i]) } - MOVDDUP_8_XPTR_INCX__X4 - MOVDDUP_8_XPTR_INCX_2__X6 - MOVDDUP_8_XPTR_INCx3X__X8 - - // X_j = { imag(y[i]), real(y[i]) } - MOVUPS (Y_PTR), X10 - MOVUPS (Y_PTR)(INC_Y*1), X11 - MOVUPS (Y_PTR)(INC_Y*2), X12 - MOVUPS (Y_PTR)(INCx3_Y*1), X13 - - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X10, X3 - MULPD X11, X5 - MULPD X12, X7 - MULPD X13, X9 - - // X_j = { real(y[i]), imag(y[i]) } - SHUFPD $0x1, X10, X10 - SHUFPD $0x1, X11, X11 - SHUFPD $0x1, X12, X12 - SHUFPD $0x1, X13, X13 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X10, X2 - MULPD X11, X4 - MULPD X12, X6 - MULPD X13, X8 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // psum += result[i] - ADDPD X3, SUM - ADDPD X5, P_SUM - ADDPD X7, SUM - ADDPD X9, P_SUM - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) - - DECQ LEN - JNZ dot_loop // } while --BX > 0 - ADDPD P_SUM, SUM // sum += psum - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail: // do { - MOVDDUP_XPTR__X3 // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_8_XPTR__X2 // X_i = { imag(x[i]), imag(x[i]) } - MOVUPS (Y_PTR), X10 // X_j = { imag(y[i]) , real(y[i]) } - MULPD X10, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - SHUFPD $0x1, X10, X10 // X_j = { real(y[i]) , imag(y[i]) } - MULPD X10, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDPD X3, SUM // sum += result[i] - ADDQ INC_X, X_PTR // X_PTR += incX - ADDQ INC_Y, Y_PTR // Y_PTR += incY - DECQ TAIL // --TAIL - JNZ dot_tail // } while TAIL > 0 - -dot_end: - MOVUPS SUM, sum+88(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotuunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dotuunitary_amd64.s deleted file mode 100644 index 8df01988..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/dotuunitary_amd64.s +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVDDUP_XPTR_IDX_8__X3 LONG $0x1C120FF2; BYTE $0xC6 // MOVDDUP (SI)(AX*8), X3 -#define MOVDDUP_16_XPTR_IDX_8__X5 LONG $0x6C120FF2; WORD $0x10C6 // MOVDDUP 16(SI)(AX*8), X5 -#define MOVDDUP_32_XPTR_IDX_8__X7 LONG $0x7C120FF2; WORD $0x20C6 // MOVDDUP 32(SI)(AX*8), X7 -#define MOVDDUP_48_XPTR_IDX_8__X9 LONG $0x120F44F2; WORD $0xC64C; BYTE $0x30 // MOVDDUP 48(SI)(AX*8), X9 - -#define MOVDDUP_XPTR_IIDX_8__X2 LONG $0x14120FF2; BYTE $0xD6 // MOVDDUP (SI)(DX*8), X2 -#define MOVDDUP_16_XPTR_IIDX_8__X4 LONG $0x64120FF2; WORD $0x10D6 // MOVDDUP 16(SI)(DX*8), X4 -#define MOVDDUP_32_XPTR_IIDX_8__X6 LONG $0x74120FF2; WORD $0x20D6 // MOVDDUP 32(SI)(DX*8), X6 -#define MOVDDUP_48_XPTR_IIDX_8__X8 LONG $0x120F44F2; WORD $0xD644; BYTE $0x30 // MOVDDUP 48(SI)(DX*8), X8 - -#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 -#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 -#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 -#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define IDX AX -#define I_IDX DX - -// func DotuUnitary(x, y []complex128) (sum complex128) -TEXT ·DotuUnitary(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+32(FP), LEN - CMOVQLE y_len+32(FP), LEN - PXOR SUM, SUM // SUM = 0 - CMPQ LEN, $0 // if LEN == 0 { return } - JE dot_end - PXOR P_SUM, P_SUM // P_SUM = 0 - XORQ IDX, IDX // IDX = 0 - MOVQ $1, DX // j = 1 - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = floor( LEN / 4 ) - SHRQ $2, LEN // LEN = LEN % 4 - JZ dot_tail // if LEN == 0 { goto dot_tail } - -dot_loop: // do { - MOVDDUP_XPTR_IDX_8__X3 // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_16_XPTR_IDX_8__X5 - MOVDDUP_32_XPTR_IDX_8__X7 - MOVDDUP_48_XPTR_IDX_8__X9 - - MOVDDUP_XPTR_IIDX_8__X2 // X_i = { imag(x[i]), imag(x[i]) } - MOVDDUP_16_XPTR_IIDX_8__X4 - MOVDDUP_32_XPTR_IIDX_8__X6 - MOVDDUP_48_XPTR_IIDX_8__X8 - - // X_j = { imag(y[i]), real(y[i]) } - MOVUPS (Y_PTR)(IDX*8), X10 - MOVUPS 16(Y_PTR)(IDX*8), X11 - MOVUPS 32(Y_PTR)(IDX*8), X12 - MOVUPS 48(Y_PTR)(IDX*8), X13 - - // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPD X10, X3 - MULPD X11, X5 - MULPD X12, X7 - MULPD X13, X9 - - // X_j = { real(y[i]), imag(y[i]) } - SHUFPD $0x1, X10, X10 - SHUFPD $0x1, X11, X11 - SHUFPD $0x1, X12, X12 - SHUFPD $0x1, X13, X13 - - // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPD X10, X2 - MULPD X11, X4 - MULPD X12, X6 - MULPD X13, X8 - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - // psum += result[i] - ADDPD X3, SUM - ADDPD X5, P_SUM - ADDPD X7, SUM - ADDPD X9, P_SUM - - ADDQ $8, IDX // IDX += 8 - ADDQ $8, I_IDX // I_IDX += 8 - DECQ LEN - JNZ dot_loop // } while --LEN > 0 - ADDPD P_SUM, SUM // SUM += P_SUM - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail: // do { - MOVDDUP_XPTR_IDX_8__X3 // X_(i+1) = { real(x[i] , real(x[i]) } - MOVDDUP_XPTR_IIDX_8__X2 // X_i = { imag(x[i]) , imag(x[i]) } - MOVUPS (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]) , real(y[i]) } - MULPD X10, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } - SHUFPD $0x1, X10, X10 // X_j = { real(y[i]) , imag(y[i]) } - MULPD X10, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDPD X3, SUM // psum += result[i] - ADDQ $2, IDX // IDX += 2 - ADDQ $2, I_IDX // I_IDX += 2 - DECQ TAIL // --TAIL - JNZ dot_tail // } while TAIL > 0 - -dot_end: - MOVUPS SUM, sum+48(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s deleted file mode 100644 index 77a28cce..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalinc_amd64.s +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SRC SI -#define DST SI -#define LEN CX -#define TAIL BX -#define INC R9 -#define INC3 R10 -#define ALPHA X0 -#define ALPHA_2 X1 - -#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x0824 // MOVDDUP 8(SP), X0 - -// func DscalInc(alpha float64, x []complex128, n, inc uintptr) -TEXT ·DscalInc(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), SRC // SRC = &x - MOVQ n+32(FP), LEN // LEN = n - CMPQ LEN, $0 // if LEN == 0 { return } - JE dscal_end - - MOVDDUP_ALPHA // ALPHA = alpha - MOVQ inc+40(FP), INC // INC = inc - SHLQ $4, INC // INC = INC * sizeof(complex128) - LEAQ (INC)(INC*2), INC3 // INC3 = 3 * INC - MOVUPS ALPHA, ALPHA_2 // Copy ALPHA and ALPHA_2 for pipelining - MOVQ LEN, TAIL // TAIL = LEN - SHRQ $2, LEN // LEN = floor( n / 4 ) - JZ dscal_tail // if LEN == 0 { goto dscal_tail } - -dscal_loop: // do { - MOVUPS (SRC), X2 // X_i = x[i] - MOVUPS (SRC)(INC*1), X3 - MOVUPS (SRC)(INC*2), X4 - MOVUPS (SRC)(INC3*1), X5 - - MULPD ALPHA, X2 // X_i *= ALPHA - MULPD ALPHA_2, X3 - MULPD ALPHA, X4 - MULPD ALPHA_2, X5 - - MOVUPS X2, (DST) // x[i] = X_i - MOVUPS X3, (DST)(INC*1) - MOVUPS X4, (DST)(INC*2) - MOVUPS X5, (DST)(INC3*1) - - LEAQ (SRC)(INC*4), SRC // SRC += INC*4 - DECQ LEN - JNZ dscal_loop // } while --LEN > 0 - -dscal_tail: - ANDQ $3, TAIL // TAIL = TAIL % 4 - JE dscal_end // if TAIL == 0 { return } - -dscal_tail_loop: // do { - MOVUPS (SRC), X2 // X_i = x[i] - MULPD ALPHA, X2 // X_i *= ALPHA - MOVUPS X2, (DST) // x[i] = X_i - ADDQ INC, SRC // SRC += INC - DECQ TAIL - JNZ dscal_tail_loop // } while --TAIL > 0 - -dscal_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s deleted file mode 100644 index 9fa91e46..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/dscalunitary_amd64.s +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SRC SI -#define DST SI -#define LEN CX -#define IDX AX -#define TAIL BX -#define ALPHA X0 -#define ALPHA_2 X1 - -#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x0824 // MOVDDUP 8(SP), X0 - -// func DscalUnitary(alpha float64, x []complex128) -TEXT ·DscalUnitary(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), SRC // SRC = &x - MOVQ x_len+16(FP), LEN // LEN = len(x) - CMPQ LEN, $0 // if LEN == 0 { return } - JE dscal_end - - MOVDDUP_ALPHA // ALPHA = alpha - XORQ IDX, IDX // IDX = 0 - MOVUPS ALPHA, ALPHA_2 // Copy ALPHA to ALPHA_2 for pipelining - MOVQ LEN, TAIL // TAIL = LEN - SHRQ $2, LEN // LEN = floor( n / 4 ) - JZ dscal_tail // if LEN == 0 { goto dscal_tail } - -dscal_loop: // do { - MOVUPS (SRC)(IDX*8), X2 // X_i = x[i] - MOVUPS 16(SRC)(IDX*8), X3 - MOVUPS 32(SRC)(IDX*8), X4 - MOVUPS 48(SRC)(IDX*8), X5 - - MULPD ALPHA, X2 // X_i *= ALPHA - MULPD ALPHA_2, X3 - MULPD ALPHA, X4 - MULPD ALPHA_2, X5 - - MOVUPS X2, (DST)(IDX*8) // x[i] = X_i - MOVUPS X3, 16(DST)(IDX*8) - MOVUPS X4, 32(DST)(IDX*8) - MOVUPS X5, 48(DST)(IDX*8) - - ADDQ $8, IDX // IDX += 8 - DECQ LEN - JNZ dscal_loop // } while --LEN > 0 - -dscal_tail: - ANDQ $3, TAIL // TAIL = TAIL % 4 - JZ dscal_end // if TAIL == 0 { return } - -dscal_tail_loop: // do { - MOVUPS (SRC)(IDX*8), X2 // X_i = x[i] - MULPD ALPHA, X2 // X_i *= ALPHA - MOVUPS X2, (DST)(IDX*8) // x[i] = X_i - ADDQ $2, IDX // IDX += 2 - DECQ TAIL - JNZ dscal_tail_loop // } while --TAIL > 0 - -dscal_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go deleted file mode 100644 index 27c35817..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/scal.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright ©2016 The Gonum 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 c128 - -// ScalUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha * v -// } -func ScalUnitaryTo(dst []complex128, alpha complex128, x []complex128) { - for i, v := range x { - dst[i] = alpha * v - } -} - -// ScalIncTo is -// -// var idst, ix uintptr -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha * x[ix] -// ix += incX -// idst += incDst -// } -func ScalIncTo(dst []complex128, incDst uintptr, alpha complex128, x []complex128, n, incX uintptr) { - var idst, ix uintptr - for i := 0; i < int(n); i++ { - dst[idst] = alpha * x[ix] - ix += incX - idst += incDst - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s deleted file mode 100644 index b76037fd..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/scalUnitary_amd64.s +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SRC SI -#define DST SI -#define LEN CX -#define IDX AX -#define TAIL BX -#define ALPHA X0 -#define ALPHA_C X1 -#define ALPHA2 X10 -#define ALPHA_C2 X11 - -#define MOVDDUP_X2_X3 LONG $0xDA120FF2 // MOVDDUP X2, X3 -#define MOVDDUP_X4_X5 LONG $0xEC120FF2 // MOVDDUP X4, X5 -#define MOVDDUP_X6_X7 LONG $0xFE120FF2 // MOVDDUP X6, X7 -#define MOVDDUP_X8_X9 LONG $0x120F45F2; BYTE $0xC8 // MOVDDUP X8, X9 - -#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 -#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 -#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 -#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 - -// func ScalUnitary(alpha complex128, x []complex128) -TEXT ·ScalUnitary(SB), NOSPLIT, $0 - MOVQ x_base+16(FP), SRC // SRC = &x - MOVQ x_len+24(FP), LEN // LEN = len(x) - CMPQ LEN, $0 // if LEN == 0 { return } - JE scal_end - - MOVUPS alpha+0(FP), ALPHA // ALPHA = { imag(alpha), real(alpha) } - MOVAPS ALPHA, ALPHA_C - SHUFPD $0x1, ALPHA_C, ALPHA_C // ALPHA_C = { real(alpha), imag(alpha) } - - XORQ IDX, IDX // IDX = 0 - MOVAPS ALPHA, ALPHA2 // Copy ALPHA and ALPHA_C for pipelining - MOVAPS ALPHA_C, ALPHA_C2 - MOVQ LEN, TAIL - SHRQ $2, LEN // LEN = floor( n / 4 ) - JZ scal_tail // if BX == 0 { goto scal_tail } - -scal_loop: // do { - MOVUPS (SRC)(IDX*8), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVUPS 16(SRC)(IDX*8), X4 - MOVUPS 32(SRC)(IDX*8), X6 - MOVUPS 48(SRC)(IDX*8), X8 - - // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_X2_X3 - MOVDDUP_X4_X5 - MOVDDUP_X6_X7 - MOVDDUP_X8_X9 - - // X_i = { imag(x[i]), imag(x[i]) } - SHUFPD $0x3, X2, X2 - SHUFPD $0x3, X4, X4 - SHUFPD $0x3, X6, X6 - SHUFPD $0x3, X8, X8 - - // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } - // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } - MULPD ALPHA_C, X2 - MULPD ALPHA, X3 - MULPD ALPHA_C2, X4 - MULPD ALPHA2, X5 - MULPD ALPHA_C, X6 - MULPD ALPHA, X7 - MULPD ALPHA_C2, X8 - MULPD ALPHA2, X9 - - // X_(i+1) = { - // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), - // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - MOVUPS X3, (DST)(IDX*8) // x[i] = X_(i+1) - MOVUPS X5, 16(DST)(IDX*8) - MOVUPS X7, 32(DST)(IDX*8) - MOVUPS X9, 48(DST)(IDX*8) - ADDQ $8, IDX // IDX += 8 - DECQ LEN - JNZ scal_loop // } while --LEN > 0 - -scal_tail: - ANDQ $3, TAIL // TAIL = TAIL % 4 - JZ scal_end // if TAIL == 0 { return } - -scal_tail_loop: // do { - MOVUPS (SRC)(IDX*8), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } - SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } - MULPD ALPHA_C, X2 // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } - MULPD ALPHA, X3 // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), - // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - - MOVUPS X3, (DST)(IDX*8) // x[i] = X_(i+1) - ADDQ $2, IDX // IDX += 2 - DECQ TAIL - JNZ scal_tail_loop // } while --LEN > 0 - -scal_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s deleted file mode 100644 index 6e0e51b6..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/scalinc_amd64.s +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SRC SI -#define DST SI -#define LEN CX -#define TAIL BX -#define INC R9 -#define INC3 R10 -#define ALPHA X0 -#define ALPHA_C X1 -#define ALPHA2 X10 -#define ALPHA_C2 X11 - -#define MOVDDUP_X2_X3 LONG $0xDA120FF2 // MOVDDUP X2, X3 -#define MOVDDUP_X4_X5 LONG $0xEC120FF2 // MOVDDUP X4, X5 -#define MOVDDUP_X6_X7 LONG $0xFE120FF2 // MOVDDUP X6, X7 -#define MOVDDUP_X8_X9 LONG $0x120F45F2; BYTE $0xC8 // MOVDDUP X8, X9 - -#define ADDSUBPD_X2_X3 LONG $0xDAD00F66 // ADDSUBPD X2, X3 -#define ADDSUBPD_X4_X5 LONG $0xECD00F66 // ADDSUBPD X4, X5 -#define ADDSUBPD_X6_X7 LONG $0xFED00F66 // ADDSUBPD X6, X7 -#define ADDSUBPD_X8_X9 LONG $0xD00F4566; BYTE $0xC8 // ADDSUBPD X8, X9 - -// func ScalInc(alpha complex128, x []complex128, n, inc uintptr) -TEXT ·ScalInc(SB), NOSPLIT, $0 - MOVQ x_base+16(FP), SRC // SRC = &x - MOVQ n+40(FP), LEN // LEN = len(x) - CMPQ LEN, $0 - JE scal_end // if LEN == 0 { return } - - MOVQ inc+48(FP), INC // INC = inc - SHLQ $4, INC // INC = INC * sizeof(complex128) - LEAQ (INC)(INC*2), INC3 // INC3 = 3 * INC - - MOVUPS alpha+0(FP), ALPHA // ALPHA = { imag(alpha), real(alpha) } - MOVAPS ALPHA, ALPHA_C - SHUFPD $0x1, ALPHA_C, ALPHA_C // ALPHA_C = { real(alpha), imag(alpha) } - - MOVAPS ALPHA, ALPHA2 // Copy ALPHA and ALPHA_C for pipelining - MOVAPS ALPHA_C, ALPHA_C2 - MOVQ LEN, TAIL - SHRQ $2, LEN // LEN = floor( n / 4 ) - JZ scal_tail // if BX == 0 { goto scal_tail } - -scal_loop: // do { - MOVUPS (SRC), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVUPS (SRC)(INC*1), X4 - MOVUPS (SRC)(INC*2), X6 - MOVUPS (SRC)(INC3*1), X8 - - // X_(i+1) = { real(x[i], real(x[i]) } - MOVDDUP_X2_X3 - MOVDDUP_X4_X5 - MOVDDUP_X6_X7 - MOVDDUP_X8_X9 - - // X_i = { imag(x[i]), imag(x[i]) } - SHUFPD $0x3, X2, X2 - SHUFPD $0x3, X4, X4 - SHUFPD $0x3, X6, X6 - SHUFPD $0x3, X8, X8 - - // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } - // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } - MULPD ALPHA_C, X2 - MULPD ALPHA, X3 - MULPD ALPHA_C2, X4 - MULPD ALPHA2, X5 - MULPD ALPHA_C, X6 - MULPD ALPHA, X7 - MULPD ALPHA_C2, X8 - MULPD ALPHA2, X9 - - // X_(i+1) = { - // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), - // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - ADDSUBPD_X4_X5 - ADDSUBPD_X6_X7 - ADDSUBPD_X8_X9 - - MOVUPS X3, (DST) // x[i] = X_(i+1) - MOVUPS X5, (DST)(INC*1) - MOVUPS X7, (DST)(INC*2) - MOVUPS X9, (DST)(INC3*1) - - LEAQ (SRC)(INC*4), SRC // SRC = &(SRC[inc*4]) - DECQ LEN - JNZ scal_loop // } while --BX > 0 - -scal_tail: - ANDQ $3, TAIL // TAIL = TAIL % 4 - JE scal_end // if TAIL == 0 { return } - -scal_tail_loop: // do { - MOVUPS (SRC), X2 // X_i = { imag(x[i]), real(x[i]) } - MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } - SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } - MULPD ALPHA_C, X2 // X_i = { real(ALPHA) * imag(x[i]), imag(ALPHA) * imag(x[i]) } - MULPD ALPHA, X3 // X_(i+1) = { imag(ALPHA) * real(x[i]), real(ALPHA) * real(x[i]) } - - // X_(i+1) = { - // imag(result[i]): imag(ALPHA)*real(x[i]) + real(ALPHA)*imag(x[i]), - // real(result[i]): real(ALPHA)*real(x[i]) - imag(ALPHA)*imag(x[i]) - // } - ADDSUBPD_X2_X3 - - MOVUPS X3, (DST) // x[i] = X_i - ADDQ INC, SRC // SRC = &(SRC[incX]) - DECQ TAIL - JNZ scal_tail_loop // } while --TAIL > 0 - -scal_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs.go deleted file mode 100644 index 9c3a8fb8..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright ©2020 The Gonum 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 c128 - -import ( - "math" - "math/cmplx" -) - -// Add is -// -// for i, v := range s { -// dst[i] += v -// } -func Add(dst, s []complex128) { - for i, v := range s { - dst[i] += v - } -} - -// AddConst is -// -// for i := range x { -// x[i] += alpha -// } -func AddConst(alpha complex128, x []complex128) { - for i := range x { - x[i] += alpha - } -} - -// CumSum is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] + v -// } -// return dst -func CumSum(dst, s []complex128) []complex128 { - if len(s) == 0 { - return dst - } - dst[0] = s[0] - for i, v := range s[1:] { - dst[i+1] = dst[i] + v - } - return dst -} - -// CumProd is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] * v -// } -// return dst -func CumProd(dst, s []complex128) []complex128 { - if len(s) == 0 { - return dst - } - dst[0] = s[0] - for i, v := range s[1:] { - dst[i+1] = dst[i] * v - } - return dst -} - -// Div is -// -// for i, v := range s { -// dst[i] /= v -// } -func Div(dst, s []complex128) { - for i, v := range s { - dst[i] /= v - } -} - -// DivTo is -// -// for i, v := range s { -// dst[i] = v / t[i] -// } -// return dst -func DivTo(dst, s, t []complex128) []complex128 { - for i, v := range s { - dst[i] = v / t[i] - } - return dst -} - -// DotUnitary is -// -// for i, v := range x { -// sum += cmplx.Conj(v) * y[i] -// } -// return sum -func DotUnitary(x, y []complex128) (sum complex128) { - for i, v := range x { - sum += cmplx.Conj(v) * y[i] - } - return sum -} - -// L2DistanceUnitary returns the L2-norm of x-y. -func L2DistanceUnitary(x, y []complex128) (norm float64) { - var scale float64 - sumSquares := 1.0 - for i, v := range x { - v -= y[i] - if v == 0 { - continue - } - absxi := cmplx.Abs(v) - if math.IsNaN(absxi) { - return math.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(sumSquares) -} - -// L2NormUnitary returns the L2-norm of x. -func L2NormUnitary(x []complex128) (norm float64) { - var scale float64 - sumSquares := 1.0 - for _, v := range x { - if v == 0 { - continue - } - absxi := cmplx.Abs(v) - if math.IsNaN(absxi) { - return math.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(sumSquares) -} - -// Sum is -// -// var sum complex128 -// for i := range x { -// sum += x[i] -// } -func Sum(x []complex128) complex128 { - var sum complex128 - for _, v := range x { - sum += v - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go deleted file mode 100644 index c0e26a2f..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_amd64.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright ©2016 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package c128 - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha complex128, x, y []complex128) - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []complex128, alpha complex128, x, y []complex128) - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) - -// DscalUnitary is -// -// for i, v := range x { -// x[i] = complex(real(v)*alpha, imag(v)*alpha) -// } -func DscalUnitary(alpha float64, x []complex128) - -// DscalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) -// ix += inc -// } -func DscalInc(alpha float64, x []complex128, n, inc uintptr) - -// ScalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] *= alpha -// ix += incX -// } -func ScalInc(alpha complex128, x []complex128, n, inc uintptr) - -// ScalUnitary is -// -// for i := range x { -// x[i] *= alpha -// } -func ScalUnitary(alpha complex128, x []complex128) - -// DotcUnitary is -// -// for i, v := range x { -// sum += y[i] * cmplx.Conj(v) -// } -// return sum -func DotcUnitary(x, y []complex128) (sum complex128) - -// DotcInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * cmplx.Conj(x[ix]) -// ix += incX -// iy += incY -// } -// return sum -func DotcInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) - -// DotuUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotuUnitary(x, y []complex128) (sum complex128) - -// DotuInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotuInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go deleted file mode 100644 index 21dfc4a8..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c128/stubs_noasm.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright ©2016 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package c128 - -import "math/cmplx" - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha complex128, x, y []complex128) { - for i, v := range x { - y[i] += alpha * v - } -} - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []complex128, alpha complex128, x, y []complex128) { - for i, v := range x { - dst[i] = alpha*v + y[i] - } -} - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - y[iy] += alpha * x[ix] - ix += incX - iy += incY - } -} - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - dst[idst] = alpha*x[ix] + y[iy] - ix += incX - iy += incY - idst += incDst - } -} - -// DscalUnitary is -// -// for i, v := range x { -// x[i] = complex(real(v)*alpha, imag(v)*alpha) -// } -func DscalUnitary(alpha float64, x []complex128) { - for i, v := range x { - x[i] = complex(real(v)*alpha, imag(v)*alpha) - } -} - -// DscalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) -// ix += inc -// } -func DscalInc(alpha float64, x []complex128, n, inc uintptr) { - var ix uintptr - for i := 0; i < int(n); i++ { - x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) - ix += inc - } -} - -// ScalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] *= alpha -// ix += incX -// } -func ScalInc(alpha complex128, x []complex128, n, inc uintptr) { - var ix uintptr - for i := 0; i < int(n); i++ { - x[ix] *= alpha - ix += inc - } -} - -// ScalUnitary is -// -// for i := range x { -// x[i] *= alpha -// } -func ScalUnitary(alpha complex128, x []complex128) { - for i := range x { - x[i] *= alpha - } -} - -// DotcUnitary is -// -// for i, v := range x { -// sum += y[i] * cmplx.Conj(v) -// } -// return sum -func DotcUnitary(x, y []complex128) (sum complex128) { - for i, v := range x { - sum += y[i] * cmplx.Conj(v) - } - return sum -} - -// DotcInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * cmplx.Conj(x[ix]) -// ix += incX -// iy += incY -// } -// return sum -func DotcInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) { - for i := 0; i < int(n); i++ { - sum += y[iy] * cmplx.Conj(x[ix]) - ix += incX - iy += incY - } - return sum -} - -// DotuUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotuUnitary(x, y []complex128) (sum complex128) { - for i, v := range x { - sum += y[i] * v - } - return sum -} - -// DotuInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotuInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) { - for i := 0; i < int(n); i++ { - sum += y[iy] * x[ix] - ix += incX - iy += incY - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s deleted file mode 100644 index 4d2c5e9a..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVSHDUP X3, X2 -#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 -// MOVSLDUP X3, X3 -#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB -// ADDSUBPS X2, X3 -#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA - -// MOVSHDUP X5, X4 -#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 -// MOVSLDUP X5, X5 -#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED -// ADDSUBPS X4, X5 -#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC - -// MOVSHDUP X7, X6 -#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 -// MOVSLDUP X7, X7 -#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF -// ADDSUBPS X6, X7 -#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE - -// MOVSHDUP X9, X8 -#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 -// MOVSLDUP X9, X9 -#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 -// ADDSUBPS X8, X9 -#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyInc(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), SI // SI = &x - MOVQ y_base+32(FP), DI // DI = &y - MOVQ n+56(FP), CX // CX = n - CMPQ CX, $0 // if n==0 { return } - JE axpyi_end - MOVQ ix+80(FP), R8 // R8 = ix - MOVQ iy+88(FP), R9 // R9 = iy - LEAQ (SI)(R8*8), SI // SI = &(x[ix]) - LEAQ (DI)(R9*8), DI // DI = &(y[iy]) - MOVQ DI, DX // DX = DI // Read/Write pointers - MOVQ incX+64(FP), R8 // R8 = incX - SHLQ $3, R8 // R8 *= sizeof(complex64) - MOVQ incY+72(FP), R9 // R9 = incY - SHLQ $3, R9 // R9 *= sizeof(complex64) - MOVSD alpha+0(FP), X0 // X0 = { 0, 0, imag(a), real(a) } - MOVAPS X0, X1 - SHUFPS $0x11, X1, X1 // X1 = { 0, 0, real(a), imag(a) } - MOVAPS X0, X10 // Copy X0 and X1 for pipelining - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $3, CX // CX = n % 4 - SHRQ $2, BX // BX = floor( n / 4 ) - JZ axpyi_tail // if BX == 0 { goto axpyi_tail } - -axpyi_loop: // do { - MOVSD (SI), X3 // X_i = { imag(x[i+1]), real(x[i+1]) } - MOVSD (SI)(R8*1), X5 - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - MOVSD (SI), X7 - MOVSD (SI)(R8*1), X9 - - // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSHDUP_X3_X2 - MOVSHDUP_X5_X4 - MOVSHDUP_X7_X6 - MOVSHDUP_X9_X8 - - // X_i = { real(x[i]), real(x[i]) } - MOVSLDUP_X3_X3 - MOVSLDUP_X5_X5 - MOVSLDUP_X7_X7 - MOVSLDUP_X9_X9 - - // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPS X1, X2 - MULPS X0, X3 - MULPS X11, X4 - MULPS X10, X5 - MULPS X1, X6 - MULPS X0, X7 - MULPS X11, X8 - MULPS X10, X9 - - // X_i = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), - // } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - MOVSD (DX), X2 - MOVSD (DX)(R9*1), X4 - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - MOVSD (DX), X6 - MOVSD (DX)(R9*1), X8 - ADDPS X2, X3 - ADDPS X4, X5 - ADDPS X6, X7 - ADDPS X8, X9 - - MOVSD X3, (DI) // y[i] = X_i - MOVSD X5, (DI)(R9*1) - LEAQ (DI)(R9*2), DI // DI = &(DI[incDst]) - MOVSD X7, (DI) - MOVSD X9, (DI)(R9*1) - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - LEAQ (DI)(R9*2), DI // DI = &(DI[incDst]) - DECQ BX - JNZ axpyi_loop // } while --BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE axpyi_end - -axpyi_tail: // do { - MOVSD (SI), X3 // X_i = { imag(x[i+1]), real(x[i+1]) } - MOVSHDUP_X3_X2 // X_(i-1) = { real(x[i]), real(x[i]) } - MOVSLDUP_X3_X3 // X_i = { imag(x[i]), imag(x[i]) } - - // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } - // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPS X1, X2 - MULPS X0, X3 - - // X_i = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), - // } - ADDSUBPS_X2_X3 // (ai*x1r+ar*x1i, ar*x1r-ai*x1i) - - // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - MOVSD (DI), X4 - ADDPS X4, X3 - MOVSD X3, (DI) // y[i] = X_i - ADDQ R8, SI // SI += incX - ADDQ R9, DI // DI += incY - LOOP axpyi_tail // } while --CX > 0 - -axpyi_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s deleted file mode 100644 index 1519f2d9..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVSHDUP X3, X2 -#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 -// MOVSLDUP X3, X3 -#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB -// ADDSUBPS X2, X3 -#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA - -// MOVSHDUP X5, X4 -#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 -// MOVSLDUP X5, X5 -#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED -// ADDSUBPS X4, X5 -#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC - -// MOVSHDUP X7, X6 -#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 -// MOVSLDUP X7, X7 -#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF -// ADDSUBPS X6, X7 -#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE - -// MOVSHDUP X9, X8 -#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 -// MOVSLDUP X9, X9 -#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 -// ADDSUBPS X8, X9 -#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyIncTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ x_base+48(FP), SI // SI = &x - MOVQ y_base+72(FP), DX // DX = &y - MOVQ n+96(FP), CX // CX = n - CMPQ CX, $0 // if n==0 { return } - JE axpyi_end - MOVQ ix+120(FP), R8 // Load the first index - MOVQ iy+128(FP), R9 - MOVQ idst+32(FP), R10 - LEAQ (SI)(R8*8), SI // SI = &(x[ix]) - LEAQ (DX)(R9*8), DX // DX = &(y[iy]) - LEAQ (DI)(R10*8), DI // DI = &(dst[idst]) - MOVQ incX+104(FP), R8 // Incrementors*8 for easy iteration (ADDQ) - SHLQ $3, R8 - MOVQ incY+112(FP), R9 - SHLQ $3, R9 - MOVQ incDst+24(FP), R10 - SHLQ $3, R10 - MOVSD alpha+40(FP), X0 // X0 = { 0, 0, imag(a), real(a) } - MOVAPS X0, X1 - SHUFPS $0x11, X1, X1 // X1 = { 0, 0, real(a), imag(a) } - MOVAPS X0, X10 // Copy X0 and X1 for pipelining - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $3, CX // CX = n % 4 - SHRQ $2, BX // BX = floor( n / 4 ) - JZ axpyi_tail // if BX == 0 { goto axpyi_tail } - -axpyi_loop: // do { - MOVSD (SI), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSD (SI)(R8*1), X5 - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - MOVSD (SI), X7 - MOVSD (SI)(R8*1), X9 - - // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSHDUP_X3_X2 - MOVSHDUP_X5_X4 - MOVSHDUP_X7_X6 - MOVSHDUP_X9_X8 - - // X_i = { real(x[i]), real(x[i]) } - MOVSLDUP_X3_X3 - MOVSLDUP_X5_X5 - MOVSLDUP_X7_X7 - MOVSLDUP_X9_X9 - - // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } - MULPS X1, X2 - MULPS X0, X3 - MULPS X11, X4 - MULPS X10, X5 - MULPS X1, X6 - MULPS X0, X7 - MULPS X11, X8 - MULPS X10, X9 - - // X_i = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), - // } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - MOVSD (DX), X2 - MOVSD (DX)(R9*1), X4 - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - MOVSD (DX), X6 - MOVSD (DX)(R9*1), X8 - ADDPS X2, X3 - ADDPS X4, X5 - ADDPS X6, X7 - ADDPS X8, X9 - - MOVSD X3, (DI) // y[i] = X_i - MOVSD X5, (DI)(R10*1) - LEAQ (DI)(R10*2), DI // DI = &(DI[incDst]) - MOVSD X7, (DI) - MOVSD X9, (DI)(R10*1) - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - LEAQ (DI)(R10*2), DI // DI = &(DI[incDst]) - DECQ BX - JNZ axpyi_loop // } while --BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE axpyi_end - -axpyi_tail: - MOVSD (SI), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } - - // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } - // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPS X1, X2 - MULPS X0, X3 - - // X_i = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), - // } - ADDSUBPS_X2_X3 - - // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } - MOVSD (DX), X4 - ADDPS X4, X3 - MOVSD X3, (DI) // y[i] = X_i - ADDQ R8, SI // SI += incX - ADDQ R9, DX // DX += incY - ADDQ R10, DI // DI += incDst - LOOP axpyi_tail // } while --CX > 0 - -axpyi_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s deleted file mode 100644 index 71274c92..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVSHDUP X3, X2 -#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 -// MOVSLDUP X3, X3 -#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB -// ADDSUBPS X2, X3 -#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA - -// MOVSHDUP X5, X4 -#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 -// MOVSLDUP X5, X5 -#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED -// ADDSUBPS X4, X5 -#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC - -// MOVSHDUP X7, X6 -#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 -// MOVSLDUP X7, X7 -#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF -// ADDSUBPS X6, X7 -#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE - -// MOVSHDUP X9, X8 -#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 -// MOVSLDUP X9, X9 -#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 -// ADDSUBPS X8, X9 -#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyUnitary(alpha complex64, x, y []complex64) -TEXT ·AxpyUnitary(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), SI // SI = &x - MOVQ y_base+32(FP), DI // DI = &y - MOVQ x_len+16(FP), CX // CX = min( len(x), len(y) ) - CMPQ y_len+40(FP), CX - CMOVQLE y_len+40(FP), CX - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - PXOR X0, X0 // Clear work registers and cache-align loop - PXOR X1, X1 - MOVSD alpha+0(FP), X0 // X0 = { 0, 0, imag(a), real(a) } - SHUFPD $0, X0, X0 // X0 = { imag(a), real(a), imag(a), real(a) } - MOVAPS X0, X1 - SHUFPS $0x11, X1, X1 // X1 = { real(a), imag(a), real(a), imag(a) } - XORQ AX, AX // i = 0 - MOVQ DI, BX // Align on 16-byte boundary for ADDPS - ANDQ $15, BX // BX = &y & 15 - JZ caxy_no_trim // if BX == 0 { goto caxy_no_trim } - - // Trim first value in unaligned buffer - XORPS X2, X2 // Clear work registers and cache-align loop - XORPS X3, X3 - XORPS X4, X4 - MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } - MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), real(a)*real(x[i]) - imag(a)*imag(x[i]) } - ADDSUBPS_X2_X3 - MOVSD (DI)(AX*8), X4 // X3 += y[i] - ADDPS X4, X3 - MOVSD X3, (DI)(AX*8) // y[i] = X3 - INCQ AX // i++ - DECQ CX // --CX - JZ caxy_end // if CX == 0 { return } - -caxy_no_trim: - MOVAPS X0, X10 // Copy X0 and X1 for pipelineing - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $7, CX // CX = n % 8 - SHRQ $3, BX // BX = floor( n / 8 ) - JZ caxy_tail // if BX == 0 { goto caxy_tail } - -caxy_loop: // do { - // X_i = { imag(x[i]), real(x[i]), imag(x[i+1]), real(x[i+1]) } - MOVUPS (SI)(AX*8), X3 - MOVUPS 16(SI)(AX*8), X5 - MOVUPS 32(SI)(AX*8), X7 - MOVUPS 48(SI)(AX*8), X9 - - // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } - MOVSHDUP_X3_X2 - MOVSHDUP_X5_X4 - MOVSHDUP_X7_X6 - MOVSHDUP_X9_X8 - - // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } - MOVSLDUP_X3_X3 - MOVSLDUP_X5_X5 - MOVSLDUP_X7_X7 - MOVSLDUP_X9_X9 - - // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]), - // imag(a) * real(x[i+1]), real(a) * real(x[i+1]) } - // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]), - // real(a) * imag(x[i+1]), imag(a) * imag(x[i+1]) } - MULPS X1, X2 - MULPS X0, X3 - MULPS X11, X4 - MULPS X10, X5 - MULPS X1, X6 - MULPS X0, X7 - MULPS X11, X8 - MULPS X10, X9 - - // X_i = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), - // imag(result[i+1]): imag(a)*real(x[i+1]) + real(a)*imag(x[i+1]), - // real(result[i+1]): real(a)*real(x[i+1]) - imag(a)*imag(x[i+1]), - // } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]), - // imag(result[i+1]) + imag(y[i+1]), real(result[i+1]) + real(y[i+1]) } - ADDPS (DI)(AX*8), X3 - ADDPS 16(DI)(AX*8), X5 - ADDPS 32(DI)(AX*8), X7 - ADDPS 48(DI)(AX*8), X9 - MOVUPS X3, (DI)(AX*8) // y[i:i+1] = X_i - MOVUPS X5, 16(DI)(AX*8) - MOVUPS X7, 32(DI)(AX*8) - MOVUPS X9, 48(DI)(AX*8) - ADDQ $8, AX // i += 8 - DECQ BX // --BX - JNZ caxy_loop // } while BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - -caxy_tail: // do { - MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } - MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(a)*real(x[i]) - imag(a)*imag(x[i]) } - ADDSUBPS_X2_X3 - MOVSD (DI)(AX*8), X4 // X3 += y[i] - ADDPS X4, X3 - MOVSD X3, (DI)(AX*8) // y[i] = X3 - INCQ AX // ++i - LOOP caxy_tail // } while --CX > 0 - -caxy_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s deleted file mode 100644 index 2e80d8ca..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// MOVSHDUP X3, X2 -#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 -// MOVSLDUP X3, X3 -#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB -// ADDSUBPS X2, X3 -#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA - -// MOVSHDUP X5, X4 -#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 -// MOVSLDUP X5, X5 -#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED -// ADDSUBPS X4, X5 -#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC - -// MOVSHDUP X7, X6 -#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 -// MOVSLDUP X7, X7 -#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF -// ADDSUBPS X6, X7 -#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE - -// MOVSHDUP X9, X8 -#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 -// MOVSLDUP X9, X9 -#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 -// ADDSUBPS X8, X9 -#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 - -// func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) -TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ x_base+32(FP), SI // SI = &x - MOVQ y_base+56(FP), DX // DX = &y - MOVQ x_len+40(FP), CX - CMPQ y_len+64(FP), CX // CX = min( len(x), len(y), len(dst) ) - CMOVQLE y_len+64(FP), CX - CMPQ dst_len+8(FP), CX - CMOVQLE dst_len+8(FP), CX - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - MOVSD alpha+24(FP), X0 // X0 = { 0, 0, imag(a), real(a) } - SHUFPD $0, X0, X0 // X0 = { imag(a), real(a), imag(a), real(a) } - MOVAPS X0, X1 - SHUFPS $0x11, X1, X1 // X1 = { real(a), imag(a), real(a), imag(a) } - XORQ AX, AX // i = 0 - MOVQ DX, BX // Align on 16-byte boundary for ADDPS - ANDQ $15, BX // BX = &y & 15 - JZ caxy_no_trim // if BX == 0 { goto caxy_no_trim } - - MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } - MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), real(a)*real(x[i]) - imag(a)*imag(x[i]) } - ADDSUBPS_X2_X3 - MOVSD (DX)(AX*8), X4 // X3 += y[i] - ADDPS X4, X3 - MOVSD X3, (DI)(AX*8) // dst[i] = X3 - INCQ AX // i++ - DECQ CX // --CX - JZ caxy_tail // if BX == 0 { goto caxy_tail } - -caxy_no_trim: - MOVAPS X0, X10 // Copy X0 and X1 for pipelineing - MOVAPS X1, X11 - MOVQ CX, BX - ANDQ $7, CX // CX = n % 8 - SHRQ $3, BX // BX = floor( n / 8 ) - JZ caxy_tail // if BX == 0 { goto caxy_tail } - -caxy_loop: - // X_i = { imag(x[i]), real(x[i]), imag(x[i+1]), real(x[i+1]) } - MOVUPS (SI)(AX*8), X3 - MOVUPS 16(SI)(AX*8), X5 - MOVUPS 32(SI)(AX*8), X7 - MOVUPS 48(SI)(AX*8), X9 - - // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } - MOVSHDUP_X3_X2 - MOVSHDUP_X5_X4 - MOVSHDUP_X7_X6 - MOVSHDUP_X9_X8 - - // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } - MOVSLDUP_X3_X3 - MOVSLDUP_X5_X5 - MOVSLDUP_X7_X7 - MOVSLDUP_X9_X9 - - // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]), - // imag(a) * real(x[i+1]), real(a) * real(x[i+1]) } - // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]), - // real(a) * imag(x[i+1]), imag(a) * imag(x[i+1]) } - MULPS X1, X2 - MULPS X0, X3 - MULPS X11, X4 - MULPS X10, X5 - MULPS X1, X6 - MULPS X0, X7 - MULPS X11, X8 - MULPS X10, X9 - - // X_i = { - // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), - // imag(result[i+1]): imag(a)*real(x[i+1]) + real(a)*imag(x[i+1]), - // real(result[i+1]): real(a)*real(x[i+1]) - imag(a)*imag(x[i+1]), - // } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]), - // imag(result[i+1]) + imag(y[i+1]), real(result[i+1]) + real(y[i+1]) } - ADDPS (DX)(AX*8), X3 - ADDPS 16(DX)(AX*8), X5 - ADDPS 32(DX)(AX*8), X7 - ADDPS 48(DX)(AX*8), X9 - MOVUPS X3, (DI)(AX*8) // y[i:i+1] = X_i - MOVUPS X5, 16(DI)(AX*8) - MOVUPS X7, 32(DI)(AX*8) - MOVUPS X9, 48(DI)(AX*8) - ADDQ $8, AX // i += 8 - DECQ BX // --BX - JNZ caxy_loop // } while BX > 0 - CMPQ CX, $0 // if CX == 0 { return } - JE caxy_end - -caxy_tail: // do { - MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } - MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } - MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } - - // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), - // real(a)*real(x[i]) - imag(a)*imag(x[i]) } - ADDSUBPS_X2_X3 - MOVSD (DX)(AX*8), X4 // X3 += y[i] - ADDPS X4, X3 - MOVSD X3, (DI)(AX*8) // y[i] = X3 - INCQ AX // ++i - LOOP caxy_tail // } while --CX > 0 - -caxy_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go deleted file mode 100644 index 910e1e5c..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright ©2015 The Gonum 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 c64 - -func conj(c complex64) complex64 { return complex(real(c), -imag(c)) } diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go deleted file mode 100644 index 35f1b2a2..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 c64 provides complex64 vector primitives. -package c64 // import "gonum.org/v1/gonum/internal/asm/c64" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_amd64.s deleted file mode 100644 index 8efda0bb..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_amd64.s +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 -#define MOVSHDUP_X5_X4 LONG $0xE5160FF3 // MOVSHDUP X5, X4 -#define MOVSHDUP_X7_X6 LONG $0xF7160FF3 // MOVSHDUP X7, X6 -#define MOVSHDUP_X9_X8 LONG $0x160F45F3; BYTE $0xC1 // MOVSHDUP X9, X8 - -#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 -#define MOVSLDUP_X5_X5 LONG $0xED120FF3 // MOVSLDUP X5, X5 -#define MOVSLDUP_X7_X7 LONG $0xFF120FF3 // MOVSLDUP X7, X7 -#define MOVSLDUP_X9_X9 LONG $0x120F45F3; BYTE $0xC9 // MOVSLDUP X9, X9 - -#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 -#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 -#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 -#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define INC_X R8 -#define INCx3_X R9 -#define INC_Y R10 -#define INCx3_Y R11 -#define NEG1 X15 -#define P_NEG1 X14 - -// func DotcInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) -TEXT ·DotcInc(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - PXOR SUM, SUM // SUM = 0 - PXOR P_SUM, P_SUM // P_SUM = 0 - MOVQ n+48(FP), LEN // LEN = n - CMPQ LEN, $0 // if LEN == 0 { return } - JE dotc_end - MOVQ ix+72(FP), INC_X - MOVQ iy+80(FP), INC_Y - LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(X_PTR[ix]) - LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(Y_PTR[iy]) - MOVQ incX+56(FP), INC_X // INC_X = incX * sizeof(complex64) - SHLQ $3, INC_X - MOVQ incY+64(FP), INC_Y // INC_Y = incY * sizeof(complex64) - SHLQ $3, INC_Y - MOVSS $(-1.0), NEG1 - SHUFPS $0, NEG1, NEG1 // { -1, -1, -1, -1 } - - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = LEN % 4 - SHRQ $2, LEN // LEN = floor( LEN / 4 ) - JZ dotc_tail // if LEN == 0 { goto dotc_tail } - - MOVUPS NEG1, P_NEG1 // Copy NEG1 for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 - -dotc_loop: // do { - MOVSD (X_PTR), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSD (X_PTR)(INC_X*1), X5 - MOVSD (X_PTR)(INC_X*2), X7 - MOVSD (X_PTR)(INCx3_X*1), X9 - - // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSHDUP_X3_X2 - MOVSHDUP_X5_X4 - MOVSHDUP_X7_X6 - MOVSHDUP_X9_X8 - - // X_i = { real(x[i]), real(x[i]) } - MOVSLDUP_X3_X3 - MOVSLDUP_X5_X5 - MOVSLDUP_X7_X7 - MOVSLDUP_X9_X9 - - // X_(i-1) = { -imag(x[i]), -imag(x[i]) } - MULPS NEG1, X2 - MULPS P_NEG1, X4 - MULPS NEG1, X6 - MULPS P_NEG1, X8 - - // X_j = { imag(y[i]), real(y[i]) } - MOVSD (Y_PTR), X10 - MOVSD (Y_PTR)(INC_Y*1), X11 - MOVSD (Y_PTR)(INC_Y*2), X12 - MOVSD (Y_PTR)(INCx3_Y*1), X13 - - // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - MULPS X10, X3 - MULPS X11, X5 - MULPS X12, X7 - MULPS X13, X9 - - // X_j = { real(y[i]), imag(y[i]) } - SHUFPS $0xB1, X10, X10 - SHUFPS $0xB1, X11, X11 - SHUFPS $0xB1, X12, X12 - SHUFPS $0xB1, X13, X13 - - // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - MULPS X10, X2 - MULPS X11, X4 - MULPS X12, X6 - MULPS X13, X8 - - // X_i = { - // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), - // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]) } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // SUM += X_i - ADDPS X3, SUM - ADDPS X5, P_SUM - ADDPS X7, SUM - ADDPS X9, P_SUM - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[INC_X*4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[INC_Y*4]) - - DECQ LEN - JNZ dotc_loop // } while --LEN > 0 - - ADDPS P_SUM, SUM // SUM = { P_SUM + SUM } - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dotc_end - -dotc_tail: // do { - MOVSD (X_PTR), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } - MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } - MOVUPS (Y_PTR), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - ADDPS X3, SUM // SUM += X_i - ADDQ INC_X, X_PTR // X_PTR += INC_X - ADDQ INC_Y, Y_PTR // Y_PTR += INC_Y - DECQ TAIL - JNZ dotc_tail // } while --TAIL > 0 - -dotc_end: - MOVSD SUM, sum+88(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s deleted file mode 100644 index 78f43eee..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVSLDUP_XPTR_IDX_8__X3 LONG $0x1C120FF3; BYTE $0xC6 // MOVSLDUP (SI)(AX*8), X3 -#define MOVSLDUP_16_XPTR_IDX_8__X5 LONG $0x6C120FF3; WORD $0x10C6 // MOVSLDUP 16(SI)(AX*8), X5 -#define MOVSLDUP_32_XPTR_IDX_8__X7 LONG $0x7C120FF3; WORD $0x20C6 // MOVSLDUP 32(SI)(AX*8), X7 -#define MOVSLDUP_48_XPTR_IDX_8__X9 LONG $0x120F44F3; WORD $0xC64C; BYTE $0x30 // MOVSLDUP 48(SI)(AX*8), X9 - -#define MOVSHDUP_XPTR_IDX_8__X2 LONG $0x14160FF3; BYTE $0xC6 // MOVSHDUP (SI)(AX*8), X2 -#define MOVSHDUP_16_XPTR_IDX_8__X4 LONG $0x64160FF3; WORD $0x10C6 // MOVSHDUP 16(SI)(AX*8), X4 -#define MOVSHDUP_32_XPTR_IDX_8__X6 LONG $0x74160FF3; WORD $0x20C6 // MOVSHDUP 32(SI)(AX*8), X6 -#define MOVSHDUP_48_XPTR_IDX_8__X8 LONG $0x160F44F3; WORD $0xC644; BYTE $0x30 // MOVSHDUP 48(SI)(AX*8), X8 - -#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 -#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 - -#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 -#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 -#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 -#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define IDX AX -#define I_IDX DX -#define NEG1 X15 -#define P_NEG1 X14 - -// func DotcUnitary(x, y []complex64) (sum complex64) -TEXT ·DotcUnitary(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - PXOR SUM, SUM // SUM = 0 - PXOR P_SUM, P_SUM // P_SUM = 0 - MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+32(FP), LEN - CMOVQLE y_len+32(FP), LEN - CMPQ LEN, $0 // if LEN == 0 { return } - JE dotc_end - XORQ IDX, IDX // i = 0 - MOVSS $(-1.0), NEG1 - SHUFPS $0, NEG1, NEG1 // { -1, -1, -1, -1 } - - MOVQ X_PTR, DX - ANDQ $15, DX // DX = &x & 15 - JZ dotc_aligned // if DX == 0 { goto dotc_aligned } - - MOVSD (X_PTR)(IDX*8), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } - MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - - MOVAPS X3, SUM // SUM = X_i - INCQ IDX // IDX++ - DECQ LEN // LEN-- - JZ dotc_ret // if LEN == 0 { goto dotc_ret } - -dotc_aligned: - MOVQ LEN, TAIL - ANDQ $7, TAIL // TAIL = LEN % 8 - SHRQ $3, LEN // LEN = floor( LEN / 8 ) - JZ dotc_tail // if LEN == 0 { return } - MOVUPS NEG1, P_NEG1 // Copy NEG1 for pipelining - -dotc_loop: // do { - MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } - MOVSLDUP_16_XPTR_IDX_8__X5 - MOVSLDUP_32_XPTR_IDX_8__X7 - MOVSLDUP_48_XPTR_IDX_8__X9 - - MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i+1]), imag(x[i+1]) } - MOVSHDUP_16_XPTR_IDX_8__X4 - MOVSHDUP_32_XPTR_IDX_8__X6 - MOVSHDUP_48_XPTR_IDX_8__X8 - - // X_j = { imag(y[i]), real(y[i]), imag(y[i+1]), real(y[i+1]) } - MOVUPS (Y_PTR)(IDX*8), X10 - MOVUPS 16(Y_PTR)(IDX*8), X11 - MOVUPS 32(Y_PTR)(IDX*8), X12 - MOVUPS 48(Y_PTR)(IDX*8), X13 - - // X_(i-1) = { -imag(x[i]), -imag(x[i]), -imag(x[i]+1), -imag(x[i]+1) } - MULPS NEG1, X2 - MULPS P_NEG1, X4 - MULPS NEG1, X6 - MULPS P_NEG1, X8 - - // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]), - // imag(y[i+1]) * real(x[i+1]), real(y[i+1]) * real(x[i+1]) } - MULPS X10, X3 - MULPS X11, X5 - MULPS X12, X7 - MULPS X13, X9 - - // X_j = { real(y[i]), imag(y[i]), real(y[i+1]), imag(y[i+1]) } - SHUFPS $0xB1, X10, X10 - SHUFPS $0xB1, X11, X11 - SHUFPS $0xB1, X12, X12 - SHUFPS $0xB1, X13, X13 - - // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]), - // real(y[i+1]) * imag(x[i+1]), imag(y[i+1]) * imag(x[i+1]) } - MULPS X10, X2 - MULPS X11, X4 - MULPS X12, X6 - MULPS X13, X8 - - // X_i = { - // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), - // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]), - // imag(result[i+1]): imag(y[i+1]) * real(x[i+1]) + real(y[i+1]) * imag(x[i+1]), - // real(result[i+1]): real(y[i+1]) * real(x[i+1]) - imag(y[i+1]) * imag(x[i+1]), - // } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // SUM += X_i - ADDPS X3, SUM - ADDPS X5, P_SUM - ADDPS X7, SUM - ADDPS X9, P_SUM - - ADDQ $8, IDX // IDX += 8 - DECQ LEN - JNZ dotc_loop // } while --LEN > 0 - - ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } - XORPS SUM, SUM // SUM = 0 - - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dotc_end - -dotc_tail: - MOVQ TAIL, LEN - SHRQ $1, LEN // LEN = floor( LEN / 2 ) - JZ dotc_tail_one // if LEN == 0 { goto dotc_tail_one } - -dotc_tail_two: // do { - MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } - MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } - MOVUPS (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0xB1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - - ADDPS X3, SUM // SUM += X_i - - ADDQ $2, IDX // IDX += 2 - DECQ LEN - JNZ dotc_tail_two // } while --LEN > 0 - - ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } - XORPS SUM, SUM // SUM = 0 - - ANDQ $1, TAIL - JZ dotc_end - -dotc_tail_one: - MOVSD (X_PTR)(IDX*8), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } - MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - - ADDPS X3, SUM // SUM += X_i - -dotc_end: - ADDPS P_SUM, SUM // SUM = { P_SUM[0] + SUM[0] } - MOVHLPS P_SUM, P_SUM // P_SUM = { P_SUM[1], P_SUM[1] } - ADDPS P_SUM, SUM // SUM = { P_SUM[1] + SUM[0] } - -dotc_ret: - MOVSD SUM, sum+48(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s deleted file mode 100644 index 3dc2e144..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 -#define MOVSHDUP_X5_X4 LONG $0xE5160FF3 // MOVSHDUP X5, X4 -#define MOVSHDUP_X7_X6 LONG $0xF7160FF3 // MOVSHDUP X7, X6 -#define MOVSHDUP_X9_X8 LONG $0x160F45F3; BYTE $0xC1 // MOVSHDUP X9, X8 - -#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 -#define MOVSLDUP_X5_X5 LONG $0xED120FF3 // MOVSLDUP X5, X5 -#define MOVSLDUP_X7_X7 LONG $0xFF120FF3 // MOVSLDUP X7, X7 -#define MOVSLDUP_X9_X9 LONG $0x120F45F3; BYTE $0xC9 // MOVSLDUP X9, X9 - -#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 -#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 -#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 -#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define INC_X R8 -#define INCx3_X R9 -#define INC_Y R10 -#define INCx3_Y R11 - -// func DotuInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) -TEXT ·DotuInc(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - PXOR SUM, SUM // SUM = 0 - PXOR P_SUM, P_SUM // P_SUM = 0 - MOVQ n+48(FP), LEN // LEN = n - CMPQ LEN, $0 // if LEN == 0 { return } - JE dotu_end - MOVQ ix+72(FP), INC_X - MOVQ iy+80(FP), INC_Y - LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(X_PTR[ix]) - LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(Y_PTR[iy]) - MOVQ incX+56(FP), INC_X // INC_X = incX * sizeof(complex64) - SHLQ $3, INC_X - MOVQ incY+64(FP), INC_Y // INC_Y = incY * sizeof(complex64) - SHLQ $3, INC_Y - - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = LEN % 4 - SHRQ $2, LEN // LEN = floor( LEN / 4 ) - JZ dotu_tail // if TAIL == 0 { goto dotu_tail } - - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 - -dotu_loop: // do { - MOVSD (X_PTR), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSD (X_PTR)(INC_X*1), X5 - MOVSD (X_PTR)(INC_X*2), X7 - MOVSD (X_PTR)(INCx3_X*1), X9 - - // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSHDUP_X3_X2 - MOVSHDUP_X5_X4 - MOVSHDUP_X7_X6 - MOVSHDUP_X9_X8 - - // X_i = { real(x[i]), real(x[i]) } - MOVSLDUP_X3_X3 - MOVSLDUP_X5_X5 - MOVSLDUP_X7_X7 - MOVSLDUP_X9_X9 - - // X_j = { imag(y[i]), real(y[i]) } - MOVSD (Y_PTR), X10 - MOVSD (Y_PTR)(INC_Y*1), X11 - MOVSD (Y_PTR)(INC_Y*2), X12 - MOVSD (Y_PTR)(INCx3_Y*1), X13 - - // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - MULPS X10, X3 - MULPS X11, X5 - MULPS X12, X7 - MULPS X13, X9 - - // X_j = { real(y[i]), imag(y[i]) } - SHUFPS $0xB1, X10, X10 - SHUFPS $0xB1, X11, X11 - SHUFPS $0xB1, X12, X12 - SHUFPS $0xB1, X13, X13 - - // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - MULPS X10, X2 - MULPS X11, X4 - MULPS X12, X6 - MULPS X13, X8 - - // X_i = { - // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), - // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]) } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // SUM += X_i - ADDPS X3, SUM - ADDPS X5, P_SUM - ADDPS X7, SUM - ADDPS X9, P_SUM - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[INC_X*4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[INC_Y*4]) - - DECQ LEN - JNZ dotu_loop // } while --LEN > 0 - - ADDPS P_SUM, SUM // SUM = { P_SUM + SUM } - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dotu_end - -dotu_tail: // do { - MOVSD (X_PTR), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } - MOVUPS (Y_PTR), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - ADDPS X3, SUM // SUM += X_i - ADDQ INC_X, X_PTR // X_PTR += INC_X - ADDQ INC_Y, Y_PTR // Y_PTR += INC_Y - DECQ TAIL - JNZ dotu_tail // } while --TAIL > 0 - -dotu_end: - MOVSD SUM, sum+88(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s deleted file mode 100644 index f11c6de7..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVSLDUP_XPTR_IDX_8__X3 LONG $0x1C120FF3; BYTE $0xC6 // MOVSLDUP (SI)(AX*8), X3 -#define MOVSLDUP_16_XPTR_IDX_8__X5 LONG $0x6C120FF3; WORD $0x10C6 // MOVSLDUP 16(SI)(AX*8), X5 -#define MOVSLDUP_32_XPTR_IDX_8__X7 LONG $0x7C120FF3; WORD $0x20C6 // MOVSLDUP 32(SI)(AX*8), X7 -#define MOVSLDUP_48_XPTR_IDX_8__X9 LONG $0x120F44F3; WORD $0xC64C; BYTE $0x30 // MOVSLDUP 48(SI)(AX*8), X9 - -#define MOVSHDUP_XPTR_IDX_8__X2 LONG $0x14160FF3; BYTE $0xC6 // MOVSHDUP (SI)(AX*8), X2 -#define MOVSHDUP_16_XPTR_IDX_8__X4 LONG $0x64160FF3; WORD $0x10C6 // MOVSHDUP 16(SI)(AX*8), X4 -#define MOVSHDUP_32_XPTR_IDX_8__X6 LONG $0x74160FF3; WORD $0x20C6 // MOVSHDUP 32(SI)(AX*8), X6 -#define MOVSHDUP_48_XPTR_IDX_8__X8 LONG $0x160F44F3; WORD $0xC644; BYTE $0x30 // MOVSHDUP 48(SI)(AX*8), X8 - -#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 -#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 - -#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 -#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 -#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 -#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define SUM X0 -#define P_SUM X1 -#define IDX AX -#define I_IDX DX -#define NEG1 X15 -#define P_NEG1 X14 - -// func DotuUnitary(x, y []complex64) (sum complex64) -TEXT ·DotuUnitary(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - PXOR SUM, SUM // SUM = 0 - PXOR P_SUM, P_SUM // P_SUM = 0 - MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+32(FP), LEN - CMOVQLE y_len+32(FP), LEN - CMPQ LEN, $0 // if LEN == 0 { return } - JE dotu_end - XORQ IDX, IDX // IDX = 0 - - MOVQ X_PTR, DX - ANDQ $15, DX // DX = &x & 15 - JZ dotu_aligned // if DX == 0 { goto dotu_aligned } - - MOVSD (X_PTR)(IDX*8), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } - MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - - MOVAPS X3, SUM // SUM = X_i - INCQ IDX // IDX++ - DECQ LEN // LEN-- - JZ dotu_end // if LEN == 0 { goto dotu_end } - -dotu_aligned: - MOVQ LEN, TAIL - ANDQ $7, TAIL // TAIL = LEN % 8 - SHRQ $3, LEN // LEN = floor( LEN / 8 ) - JZ dotu_tail // if LEN == 0 { goto dotu_tail } - PXOR P_SUM, P_SUM - -dotu_loop: // do { - MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } - MOVSLDUP_16_XPTR_IDX_8__X5 - MOVSLDUP_32_XPTR_IDX_8__X7 - MOVSLDUP_48_XPTR_IDX_8__X9 - - MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } - MOVSHDUP_16_XPTR_IDX_8__X4 - MOVSHDUP_32_XPTR_IDX_8__X6 - MOVSHDUP_48_XPTR_IDX_8__X8 - - // X_j = { imag(y[i]), real(y[i]), imag(y[i+1]), real(y[i+1]) } - MOVUPS (Y_PTR)(IDX*8), X10 - MOVUPS 16(Y_PTR)(IDX*8), X11 - MOVUPS 32(Y_PTR)(IDX*8), X12 - MOVUPS 48(Y_PTR)(IDX*8), X13 - - // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]), - // imag(y[i+1]) * real(x[i+1]), real(y[i+1]) * real(x[i+1]) } - MULPS X10, X3 - MULPS X11, X5 - MULPS X12, X7 - MULPS X13, X9 - - // X_j = { real(y[i]), imag(y[i]), real(y[i+1]), imag(y[i+1]) } - SHUFPS $0xB1, X10, X10 - SHUFPS $0xB1, X11, X11 - SHUFPS $0xB1, X12, X12 - SHUFPS $0xB1, X13, X13 - - // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]), - // real(y[i+1]) * imag(x[i+1]), imag(y[i+1]) * imag(x[i+1]) } - MULPS X10, X2 - MULPS X11, X4 - MULPS X12, X6 - MULPS X13, X8 - - // X_i = { - // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), - // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]), - // imag(result[i+1]): imag(y[i+1]) * real(x[i+1]) + real(y[i+1]) * imag(x[i+1]), - // real(result[i+1]): real(y[i+1]) * real(x[i+1]) - imag(y[i+1]) * imag(x[i+1]), - // } - ADDSUBPS_X2_X3 - ADDSUBPS_X4_X5 - ADDSUBPS_X6_X7 - ADDSUBPS_X8_X9 - - // SUM += X_i - ADDPS X3, SUM - ADDPS X5, P_SUM - ADDPS X7, SUM - ADDPS X9, P_SUM - - ADDQ $8, IDX // IDX += 8 - DECQ LEN - JNZ dotu_loop // } while --LEN > 0 - - ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } - XORPS SUM, SUM // SUM = 0 - - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dotu_end - -dotu_tail: - MOVQ TAIL, LEN - SHRQ $1, LEN // LEN = floor( LEN / 2 ) - JZ dotu_tail_one // if LEN == 0 { goto dotc_tail_one } - -dotu_tail_two: // do { - MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } - MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } - MOVUPS (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0xB1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - - ADDPS X3, SUM // SUM += X_i - - ADDQ $2, IDX // IDX += 2 - DECQ LEN - JNZ dotu_tail_two // } while --LEN > 0 - - ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } - XORPS SUM, SUM // SUM = 0 - - ANDQ $1, TAIL - JZ dotu_end - -dotu_tail_one: - MOVSD (X_PTR)(IDX*8), X3 // X_i = { imag(x[i]), real(x[i]) } - MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } - MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } - MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } - MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } - SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } - MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } - - // X_i = { - // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), - // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } - ADDSUBPS_X2_X3 - - ADDPS X3, SUM // SUM += X_i - -dotu_end: - ADDPS P_SUM, SUM // SUM = { P_SUM[0] + SUM[0] } - MOVHLPS P_SUM, P_SUM // P_SUM = { P_SUM[1], P_SUM[1] } - ADDPS P_SUM, SUM // SUM = { P_SUM[1] + SUM[0] } - -dotu_ret: - MOVSD SUM, sum+48(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go deleted file mode 100644 index 6db0aa36..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright ©2016 The Gonum 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 c64 - -// ScalUnitary is -// -// for i := range x { -// x[i] *= alpha -// } -func ScalUnitary(alpha complex64, x []complex64) { - for i := range x { - x[i] *= alpha - } -} - -// ScalUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha * v -// } -func ScalUnitaryTo(dst []complex64, alpha complex64, x []complex64) { - for i, v := range x { - dst[i] = alpha * v - } -} - -// ScalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] *= alpha -// ix += incX -// } -func ScalInc(alpha complex64, x []complex64, n, incX uintptr) { - var ix uintptr - for i := 0; i < int(n); i++ { - x[ix] *= alpha - ix += incX - } -} - -// ScalIncTo is -// -// var idst, ix uintptr -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha * x[ix] -// ix += incX -// idst += incDst -// } -func ScalIncTo(dst []complex64, incDst uintptr, alpha complex64, x []complex64, n, incX uintptr) { - var idst, ix uintptr - for i := 0; i < int(n); i++ { - dst[idst] = alpha * x[ix] - ix += incX - idst += incDst - } -} - -// SscalUnitary is -// -// for i, v := range x { -// x[i] = complex(real(v)*alpha, imag(v)*alpha) -// } -func SscalUnitary(alpha float32, x []complex64) { - for i, v := range x { - x[i] = complex(real(v)*alpha, imag(v)*alpha) - } -} - -// SscalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) -// ix += inc -// } -func SscalInc(alpha float32, x []complex64, n, inc uintptr) { - var ix uintptr - for i := 0; i < int(n); i++ { - x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) - ix += inc - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs.go deleted file mode 100644 index 0aa626e1..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright ©2020 The Gonum 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 c64 - -import ( - "gonum.org/v1/gonum/internal/cmplx64" - "gonum.org/v1/gonum/internal/math32" -) - -// Add is -// -// for i, v := range s { -// dst[i] += v -// } -func Add(dst, s []complex64) { - for i, v := range s { - dst[i] += v - } -} - -// AddConst is -// -// for i := range x { -// x[i] += alpha -// } -func AddConst(alpha complex64, x []complex64) { - for i := range x { - x[i] += alpha - } -} - -// CumSum is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] + v -// } -// return dst -func CumSum(dst, s []complex64) []complex64 { - if len(s) == 0 { - return dst - } - dst[0] = s[0] - for i, v := range s[1:] { - dst[i+1] = dst[i] + v - } - return dst -} - -// CumProd is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] * v -// } -// return dst -func CumProd(dst, s []complex64) []complex64 { - if len(s) == 0 { - return dst - } - dst[0] = s[0] - for i, v := range s[1:] { - dst[i+1] = dst[i] * v - } - return dst -} - -// Div is -// -// for i, v := range s { -// dst[i] /= v -// } -func Div(dst, s []complex64) { - for i, v := range s { - dst[i] /= v - } -} - -// DivTo is -// -// for i, v := range s { -// dst[i] = v / t[i] -// } -// return dst -func DivTo(dst, s, t []complex64) []complex64 { - for i, v := range s { - dst[i] = v / t[i] - } - return dst -} - -// DotUnitary is -// -// for i, v := range x { -// sum += conj(v) * y[i] -// } -// return sum -func DotUnitary(x, y []complex64) (sum complex64) { - for i, v := range x { - sum += cmplx64.Conj(v) * y[i] - } - return sum -} - -// L2DistanceUnitary returns the L2-norm of x-y. -func L2DistanceUnitary(x, y []complex64) (norm float32) { - var scale float32 - sumSquares := float32(1.0) - for i, v := range x { - v -= y[i] - if v == 0 { - continue - } - absxi := cmplx64.Abs(v) - if math32.IsNaN(absxi) { - return math32.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math32.IsInf(scale, 1) { - return math32.Inf(1) - } - return scale * math32.Sqrt(sumSquares) -} - -// L2NormUnitary returns the L2-norm of x. -func L2NormUnitary(x []complex64) (norm float32) { - var scale float32 - sumSquares := float32(1.0) - for _, v := range x { - if v == 0 { - continue - } - absxi := cmplx64.Abs(v) - if math32.IsNaN(absxi) { - return math32.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math32.IsInf(scale, 1) { - return math32.Inf(1) - } - return scale * math32.Sqrt(sumSquares) -} - -// Sum is -// -// var sum complex64 -// for i := range x { -// sum += x[i] -// } -func Sum(x []complex64) complex64 { - var sum complex64 - for _, v := range x { - sum += v - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go deleted file mode 100644 index 71367b01..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright ©2016 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package c64 - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha complex64, x, y []complex64) - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) - -// DotcUnitary is -// -// for i, v := range x { -// sum += y[i] * conj(v) -// } -// return sum -func DotcUnitary(x, y []complex64) (sum complex64) - -// DotcInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * conj(x[ix]) -// ix += incX -// iy += incY -// } -// return sum -func DotcInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) - -// DotuUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotuUnitary(x, y []complex64) (sum complex64) - -// DotuInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotuInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go deleted file mode 100644 index 0d79b24f..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright ©2016 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package c64 - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha complex64, x, y []complex64) { - for i, v := range x { - y[i] += alpha * v - } -} - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) { - for i, v := range x { - dst[i] = alpha*v + y[i] - } -} - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - y[iy] += alpha * x[ix] - ix += incX - iy += incY - } -} - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - dst[idst] = alpha*x[ix] + y[iy] - ix += incX - iy += incY - idst += incDst - } -} - -// DotcUnitary is -// -// for i, v := range x { -// sum += y[i] * conj(v) -// } -// return sum -func DotcUnitary(x, y []complex64) (sum complex64) { - for i, v := range x { - sum += y[i] * conj(v) - } - return sum -} - -// DotcInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * conj(x[ix]) -// ix += incX -// iy += incY -// } -// return sum -func DotcInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) { - for i := 0; i < int(n); i++ { - sum += y[iy] * conj(x[ix]) - ix += incX - iy += incY - } - return sum -} - -// DotuUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotuUnitary(x, y []complex64) (sum complex64) { - for i, v := range x { - sum += y[i] * v - } - return sum -} - -// DotuInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotuInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) { - for i := 0; i < int(n); i++ { - sum += y[iy] * x[ix] - ix += incX - iy += incY - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s deleted file mode 100644 index c0b84cd8..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyinc_amd64.s +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyInc(SB), NOSPLIT, $0 - MOVQ n+56(FP), CX // CX = n - CMPQ CX, $0 // if n==0 { return } - JLE axpyi_end - MOVQ x_base+8(FP), SI // SI = &x - MOVQ y_base+32(FP), DI // DI = &y - MOVQ ix+80(FP), R8 // R8 = ix - MOVQ iy+88(FP), R9 // R9 = iy - LEAQ (SI)(R8*4), SI // SI = &(x[ix]) - LEAQ (DI)(R9*4), DI // DI = &(y[iy]) - MOVQ DI, DX // DX = DI Read Pointer for y - MOVQ incX+64(FP), R8 // R8 = incX - SHLQ $2, R8 // R8 *= sizeof(float32) - MOVQ incY+72(FP), R9 // R9 = incY - SHLQ $2, R9 // R9 *= sizeof(float32) - MOVSS alpha+0(FP), X0 // X0 = alpha - MOVSS X0, X1 // X1 = X0 // for pipelining - MOVQ CX, BX - ANDQ $3, BX // BX = n % 4 - SHRQ $2, CX // CX = floor( n / 4 ) - JZ axpyi_tail_start // if CX == 0 { goto axpyi_tail_start } - -axpyi_loop: // Loop unrolled 4x do { - MOVSS (SI), X2 // X_i = x[i] - MOVSS (SI)(R8*1), X3 - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - MOVSS (SI), X4 - MOVSS (SI)(R8*1), X5 - MULSS X1, X2 // X_i *= a - MULSS X0, X3 - MULSS X1, X4 - MULSS X0, X5 - ADDSS (DX), X2 // X_i += y[i] - ADDSS (DX)(R9*1), X3 - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - ADDSS (DX), X4 - ADDSS (DX)(R9*1), X5 - MOVSS X2, (DI) // y[i] = X_i - MOVSS X3, (DI)(R9*1) - LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) - MOVSS X4, (DI) - MOVSS X5, (DI)(R9*1) - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) // Increment addresses - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) - LOOP axpyi_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE axpyi_end - -axpyi_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - -axpyi_tail: // do { - MOVSS (SI), X2 // X2 = x[i] - MULSS X1, X2 // X2 *= a - ADDSS (DI), X2 // X2 += y[i] - MOVSS X2, (DI) // y[i] = X2 - ADDQ R8, SI // SI = &(SI[incX]) - ADDQ R9, DI // DI = &(DI[incY]) - LOOP axpyi_tail // } while --CX > 0 - -axpyi_end: - RET - diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s deleted file mode 100644 index 3f1d2b93..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyincto_amd64.s +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyIncTo(SB), NOSPLIT, $0 - MOVQ n+96(FP), CX // CX = n - CMPQ CX, $0 // if n==0 { return } - JLE axpyi_end - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ x_base+48(FP), SI // SI = &x - MOVQ y_base+72(FP), DX // DX = &y - MOVQ ix+120(FP), R8 // R8 = ix // Load the first index - MOVQ iy+128(FP), R9 // R9 = iy - MOVQ idst+32(FP), R10 // R10 = idst - LEAQ (SI)(R8*4), SI // SI = &(x[ix]) - LEAQ (DX)(R9*4), DX // DX = &(y[iy]) - LEAQ (DI)(R10*4), DI // DI = &(dst[idst]) - MOVQ incX+104(FP), R8 // R8 = incX - SHLQ $2, R8 // R8 *= sizeof(float32) - MOVQ incY+112(FP), R9 // R9 = incY - SHLQ $2, R9 // R9 *= sizeof(float32) - MOVQ incDst+24(FP), R10 // R10 = incDst - SHLQ $2, R10 // R10 *= sizeof(float32) - MOVSS alpha+40(FP), X0 // X0 = alpha - MOVSS X0, X1 // X1 = X0 // for pipelining - MOVQ CX, BX - ANDQ $3, BX // BX = n % 4 - SHRQ $2, CX // CX = floor( n / 4 ) - JZ axpyi_tail_start // if CX == 0 { goto axpyi_tail_start } - -axpyi_loop: // Loop unrolled 4x do { - MOVSS (SI), X2 // X_i = x[i] - MOVSS (SI)(R8*1), X3 - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) - MOVSS (SI), X4 - MOVSS (SI)(R8*1), X5 - MULSS X1, X2 // X_i *= a - MULSS X0, X3 - MULSS X1, X4 - MULSS X0, X5 - ADDSS (DX), X2 // X_i += y[i] - ADDSS (DX)(R9*1), X3 - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - ADDSS (DX), X4 - ADDSS (DX)(R9*1), X5 - MOVSS X2, (DI) // dst[i] = X_i - MOVSS X3, (DI)(R10*1) - LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) - MOVSS X4, (DI) - MOVSS X5, (DI)(R10*1) - LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) // Increment addresses - LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) - LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) - LOOP axpyi_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE axpyi_end - -axpyi_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - -axpyi_tail: // do { - MOVSS (SI), X2 // X2 = x[i] - MULSS X1, X2 // X2 *= a - ADDSS (DX), X2 // X2 += y[i] - MOVSS X2, (DI) // dst[i] = X2 - ADDQ R8, SI // SI = &(SI[incX]) - ADDQ R9, DX // DX = &(DX[incY]) - ADDQ R10, DI // DI = &(DI[incY]) - LOOP axpyi_tail // } while --CX > 0 - -axpyi_end: - RET - diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s deleted file mode 100644 index 8e24be81..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitary_amd64.s +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func AxpyUnitary(alpha float32, x, y []float32) -TEXT ·AxpyUnitary(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), SI // SI = &x - MOVQ y_base+32(FP), DI // DI = &y - MOVQ x_len+16(FP), BX // BX = min( len(x), len(y) ) - CMPQ y_len+40(FP), BX - CMOVQLE y_len+40(FP), BX - CMPQ BX, $0 // if BX == 0 { return } - JE axpy_end - MOVSS alpha+0(FP), X0 - SHUFPS $0, X0, X0 // X0 = { a, a, a, a } - XORQ AX, AX // i = 0 - PXOR X2, X2 // 2 NOP instructions (PXOR) to align - PXOR X3, X3 // loop to cache line - MOVQ DI, CX - ANDQ $0xF, CX // Align on 16-byte boundary for ADDPS - JZ axpy_no_trim // if CX == 0 { goto axpy_no_trim } - - XORQ $0xF, CX // CX = 4 - floor( BX % 16 / 4 ) - INCQ CX - SHRQ $2, CX - -axpy_align: // Trim first value(s) in unaligned buffer do { - MOVSS (SI)(AX*4), X2 // X2 = x[i] - MULSS X0, X2 // X2 *= a - ADDSS (DI)(AX*4), X2 // X2 += y[i] - MOVSS X2, (DI)(AX*4) // y[i] = X2 - INCQ AX // i++ - DECQ BX - JZ axpy_end // if --BX == 0 { return } - LOOP axpy_align // } while --CX > 0 - -axpy_no_trim: - MOVUPS X0, X1 // Copy X0 to X1 for pipelining - MOVQ BX, CX - ANDQ $0xF, BX // BX = len % 16 - SHRQ $4, CX // CX = int( len / 16 ) - JZ axpy_tail4_start // if CX == 0 { return } - -axpy_loop: // Loop unrolled 16x do { - MOVUPS (SI)(AX*4), X2 // X2 = x[i:i+4] - MOVUPS 16(SI)(AX*4), X3 - MOVUPS 32(SI)(AX*4), X4 - MOVUPS 48(SI)(AX*4), X5 - MULPS X0, X2 // X2 *= a - MULPS X1, X3 - MULPS X0, X4 - MULPS X1, X5 - ADDPS (DI)(AX*4), X2 // X2 += y[i:i+4] - ADDPS 16(DI)(AX*4), X3 - ADDPS 32(DI)(AX*4), X4 - ADDPS 48(DI)(AX*4), X5 - MOVUPS X2, (DI)(AX*4) // dst[i:i+4] = X2 - MOVUPS X3, 16(DI)(AX*4) - MOVUPS X4, 32(DI)(AX*4) - MOVUPS X5, 48(DI)(AX*4) - ADDQ $16, AX // i += 16 - LOOP axpy_loop // while (--CX) > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE axpy_end - -axpy_tail4_start: // Reset loop counter for 4-wide tail loop - MOVQ BX, CX // CX = floor( BX / 4 ) - SHRQ $2, CX - JZ axpy_tail_start // if CX == 0 { goto axpy_tail_start } - -axpy_tail4: // Loop unrolled 4x do { - MOVUPS (SI)(AX*4), X2 // X2 = x[i] - MULPS X0, X2 // X2 *= a - ADDPS (DI)(AX*4), X2 // X2 += y[i] - MOVUPS X2, (DI)(AX*4) // y[i] = X2 - ADDQ $4, AX // i += 4 - LOOP axpy_tail4 // } while --CX > 0 - -axpy_tail_start: // Reset loop counter for 1-wide tail loop - MOVQ BX, CX // CX = BX % 4 - ANDQ $3, CX - JZ axpy_end // if CX == 0 { return } - -axpy_tail: - MOVSS (SI)(AX*4), X1 // X1 = x[i] - MULSS X0, X1 // X1 *= a - ADDSS (DI)(AX*4), X1 // X1 += y[i] - MOVSS X1, (DI)(AX*4) // y[i] = X1 - INCQ AX // i++ - LOOP axpy_tail // } while --CX > 0 - -axpy_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s deleted file mode 100644 index 9a68f0f4..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/axpyunitaryto_amd64.s +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) -TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ x_base+32(FP), SI // SI = &x - MOVQ y_base+56(FP), DX // DX = &y - MOVQ x_len+40(FP), BX // BX = min( len(x), len(y), len(dst) ) - CMPQ y_len+64(FP), BX - CMOVQLE y_len+64(FP), BX - CMPQ dst_len+8(FP), BX - CMOVQLE dst_len+8(FP), BX - CMPQ BX, $0 // if BX == 0 { return } - JE axpy_end - MOVSS alpha+24(FP), X0 - SHUFPS $0, X0, X0 // X0 = { a, a, a, a, } - XORQ AX, AX // i = 0 - MOVQ DX, CX - ANDQ $0xF, CX // Align on 16-byte boundary for ADDPS - JZ axpy_no_trim // if CX == 0 { goto axpy_no_trim } - - XORQ $0xF, CX // CX = 4 - floor ( B % 16 / 4 ) - INCQ CX - SHRQ $2, CX - -axpy_align: // Trim first value(s) in unaligned buffer do { - MOVSS (SI)(AX*4), X2 // X2 = x[i] - MULSS X0, X2 // X2 *= a - ADDSS (DX)(AX*4), X2 // X2 += y[i] - MOVSS X2, (DI)(AX*4) // y[i] = X2 - INCQ AX // i++ - DECQ BX - JZ axpy_end // if --BX == 0 { return } - LOOP axpy_align // } while --CX > 0 - -axpy_no_trim: - MOVUPS X0, X1 // Copy X0 to X1 for pipelining - MOVQ BX, CX - ANDQ $0xF, BX // BX = len % 16 - SHRQ $4, CX // CX = floor( len / 16 ) - JZ axpy_tail4_start // if CX == 0 { return } - -axpy_loop: // Loop unrolled 16x do { - MOVUPS (SI)(AX*4), X2 // X2 = x[i:i+4] - MOVUPS 16(SI)(AX*4), X3 - MOVUPS 32(SI)(AX*4), X4 - MOVUPS 48(SI)(AX*4), X5 - MULPS X0, X2 // X2 *= a - MULPS X1, X3 - MULPS X0, X4 - MULPS X1, X5 - ADDPS (DX)(AX*4), X2 // X2 += y[i:i+4] - ADDPS 16(DX)(AX*4), X3 - ADDPS 32(DX)(AX*4), X4 - ADDPS 48(DX)(AX*4), X5 - MOVUPS X2, (DI)(AX*4) // dst[i:i+4] = X2 - MOVUPS X3, 16(DI)(AX*4) - MOVUPS X4, 32(DI)(AX*4) - MOVUPS X5, 48(DI)(AX*4) - ADDQ $16, AX // i += 16 - LOOP axpy_loop // while (--CX) > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE axpy_end - -axpy_tail4_start: // Reset loop counter for 4-wide tail loop - MOVQ BX, CX // CX = floor( BX / 4 ) - SHRQ $2, CX - JZ axpy_tail_start // if CX == 0 { goto axpy_tail_start } - -axpy_tail4: // Loop unrolled 4x do { - MOVUPS (SI)(AX*4), X2 // X2 = x[i] - MULPS X0, X2 // X2 *= a - ADDPS (DX)(AX*4), X2 // X2 += y[i] - MOVUPS X2, (DI)(AX*4) // y[i] = X2 - ADDQ $4, AX // i += 4 - LOOP axpy_tail4 // } while --CX > 0 - -axpy_tail_start: // Reset loop counter for 1-wide tail loop - MOVQ BX, CX // CX = BX % 4 - ANDQ $3, CX - JZ axpy_end // if CX == 0 { return } - -axpy_tail: - MOVSS (SI)(AX*4), X1 // X1 = x[i] - MULSS X0, X1 // X1 *= a - ADDSS (DX)(AX*4), X1 // X1 += y[i] - MOVSS X1, (DI)(AX*4) // y[i] = X1 - INCQ AX // i++ - LOOP axpy_tail // } while --CX > 0 - -axpy_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/ddotinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/ddotinc_amd64.s deleted file mode 100644 index 85fcd89e..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/ddotinc_amd64.s +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define INC_X R8 -#define INCx3_X R10 -#define INC_Y R9 -#define INCx3_Y R11 -#define SUM X0 -#define P_SUM X1 - -// func DdotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float64) -TEXT ·DdotInc(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - MOVQ n+48(FP), LEN // LEN = n - PXOR SUM, SUM // SUM = 0 - CMPQ LEN, $0 - JE dot_end - - MOVQ ix+72(FP), INC_X // INC_X = ix - MOVQ iy+80(FP), INC_Y // INC_Y = iy - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(x[ix]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(y[iy]) - - MOVQ incX+56(FP), INC_X // INC_X = incX * sizeof(float32) - SHLQ $2, INC_X - MOVQ incY+64(FP), INC_Y // INC_Y = incY * sizeof(float32) - SHLQ $2, INC_Y - - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = LEN % 4 - SHRQ $2, LEN // LEN = floor( LEN / 4 ) - JZ dot_tail // if LEN == 0 { goto dot_tail } - - PXOR P_SUM, P_SUM // P_SUM = 0 for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 - -dot_loop: // Loop unrolled 4x do { - CVTSS2SD (X_PTR), X2 // X_i = x[i:i+1] - CVTSS2SD (X_PTR)(INC_X*1), X3 - CVTSS2SD (X_PTR)(INC_X*2), X4 - CVTSS2SD (X_PTR)(INCx3_X*1), X5 - - CVTSS2SD (Y_PTR), X6 // X_j = y[i:i+1] - CVTSS2SD (Y_PTR)(INC_Y*1), X7 - CVTSS2SD (Y_PTR)(INC_Y*2), X8 - CVTSS2SD (Y_PTR)(INCx3_Y*1), X9 - - MULSD X6, X2 // X_i *= X_j - MULSD X7, X3 - MULSD X8, X4 - MULSD X9, X5 - - ADDSD X2, SUM // SUM += X_i - ADDSD X3, P_SUM - ADDSD X4, SUM - ADDSD X5, P_SUM - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[INC_X * 4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[INC_Y * 4]) - - DECQ LEN - JNZ dot_loop // } while --LEN > 0 - - ADDSD P_SUM, SUM // SUM += P_SUM - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail: // do { - CVTSS2SD (X_PTR), X2 // X2 = x[i] - CVTSS2SD (Y_PTR), X3 // X2 *= y[i] - MULSD X3, X2 - ADDSD X2, SUM // SUM += X2 - ADDQ INC_X, X_PTR // X_PTR += INC_X - ADDQ INC_Y, Y_PTR // Y_PTR += INC_Y - DECQ TAIL - JNZ dot_tail // } while --TAIL > 0 - -dot_end: - MOVSD SUM, sum+88(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/ddotunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/ddotunitary_amd64.s deleted file mode 100644 index 87ef09fa..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/ddotunitary_amd64.s +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define HADDPD_SUM_SUM LONG $0xC07C0F66 // @ HADDPD X0, X0 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define IDX AX -#define SUM X0 -#define P_SUM X1 - -// func DdotUnitary(x, y []float32) (sum float32) -TEXT ·DdotUnitary(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+32(FP), LEN - CMOVQLE y_len+32(FP), LEN - PXOR SUM, SUM // psum = 0 - CMPQ LEN, $0 - JE dot_end - - XORQ IDX, IDX - MOVQ Y_PTR, DX - ANDQ $0xF, DX // Align on 16-byte boundary for ADDPS - JZ dot_no_trim // if DX == 0 { goto dot_no_trim } - - SUBQ $16, DX - -dot_align: // Trim first value(s) in unaligned buffer do { - CVTSS2SD (X_PTR)(IDX*4), X2 // X2 = float64(x[i]) - CVTSS2SD (Y_PTR)(IDX*4), X3 // X3 = float64(y[i]) - MULSD X3, X2 - ADDSD X2, SUM // SUM += X2 - INCQ IDX // IDX++ - DECQ LEN - JZ dot_end // if --TAIL == 0 { return } - ADDQ $4, DX - JNZ dot_align // } while --LEN > 0 - -dot_no_trim: - PXOR P_SUM, P_SUM // P_SUM = 0 for pipelining - MOVQ LEN, TAIL - ANDQ $0x7, TAIL // TAIL = LEN % 8 - SHRQ $3, LEN // LEN = floor( LEN / 8 ) - JZ dot_tail_start // if LEN == 0 { goto dot_tail_start } - -dot_loop: // Loop unrolled 8x do { - CVTPS2PD (X_PTR)(IDX*4), X2 // X_i = x[i:i+1] - CVTPS2PD 8(X_PTR)(IDX*4), X3 - CVTPS2PD 16(X_PTR)(IDX*4), X4 - CVTPS2PD 24(X_PTR)(IDX*4), X5 - - CVTPS2PD (Y_PTR)(IDX*4), X6 // X_j = y[i:i+1] - CVTPS2PD 8(Y_PTR)(IDX*4), X7 - CVTPS2PD 16(Y_PTR)(IDX*4), X8 - CVTPS2PD 24(Y_PTR)(IDX*4), X9 - - MULPD X6, X2 // X_i *= X_j - MULPD X7, X3 - MULPD X8, X4 - MULPD X9, X5 - - ADDPD X2, SUM // SUM += X_i - ADDPD X3, P_SUM - ADDPD X4, SUM - ADDPD X5, P_SUM - - ADDQ $8, IDX // IDX += 8 - DECQ LEN - JNZ dot_loop // } while --LEN > 0 - - ADDPD P_SUM, SUM // SUM += P_SUM - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail_start: - MOVQ TAIL, LEN - SHRQ $1, LEN - JZ dot_tail_one - -dot_tail_two: - CVTPS2PD (X_PTR)(IDX*4), X2 // X_i = x[i:i+1] - CVTPS2PD (Y_PTR)(IDX*4), X6 // X_j = y[i:i+1] - MULPD X6, X2 // X_i *= X_j - ADDPD X2, SUM // SUM += X_i - ADDQ $2, IDX // IDX += 2 - DECQ LEN - JNZ dot_tail_two // } while --LEN > 0 - - ANDQ $1, TAIL - JZ dot_end - -dot_tail_one: - CVTSS2SD (X_PTR)(IDX*4), X2 // X2 = float64(x[i]) - CVTSS2SD (Y_PTR)(IDX*4), X3 // X3 = float64(y[i]) - MULSD X3, X2 // X2 *= X3 - ADDSD X2, SUM // SUM += X2 - -dot_end: - HADDPD_SUM_SUM // SUM = \sum{ SUM[i] } - MOVSD SUM, sum+48(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go deleted file mode 100644 index 408847a6..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 f32 provides float32 vector primitives. -package f32 // import "gonum.org/v1/gonum/internal/asm/f32" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/dotinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/dotinc_amd64.s deleted file mode 100644 index 9ac80636..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/dotinc_amd64.s +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define INC_X R8 -#define INCx3_X R10 -#define INC_Y R9 -#define INCx3_Y R11 -#define SUM X0 -#define P_SUM X1 - -// func DotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float32) -TEXT ·DotInc(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - PXOR SUM, SUM // SUM = 0 - MOVQ n+48(FP), LEN // LEN = n - CMPQ LEN, $0 - JE dot_end - - MOVQ ix+72(FP), INC_X // INC_X = ix - MOVQ iy+80(FP), INC_Y // INC_Y = iy - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(x[ix]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(y[iy]) - - MOVQ incX+56(FP), INC_X // INC_X := incX * sizeof(float32) - SHLQ $2, INC_X - MOVQ incY+64(FP), INC_Y // INC_Y := incY * sizeof(float32) - SHLQ $2, INC_Y - - MOVQ LEN, TAIL - ANDQ $0x3, TAIL // TAIL = LEN % 4 - SHRQ $2, LEN // LEN = floor( LEN / 4 ) - JZ dot_tail // if LEN == 0 { goto dot_tail } - - PXOR P_SUM, P_SUM // P_SUM = 0 for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 - -dot_loop: // Loop unrolled 4x do { - MOVSS (X_PTR), X2 // X_i = x[i:i+1] - MOVSS (X_PTR)(INC_X*1), X3 - MOVSS (X_PTR)(INC_X*2), X4 - MOVSS (X_PTR)(INCx3_X*1), X5 - - MULSS (Y_PTR), X2 // X_i *= y[i:i+1] - MULSS (Y_PTR)(INC_Y*1), X3 - MULSS (Y_PTR)(INC_Y*2), X4 - MULSS (Y_PTR)(INCx3_Y*1), X5 - - ADDSS X2, SUM // SUM += X_i - ADDSS X3, P_SUM - ADDSS X4, SUM - ADDSS X5, P_SUM - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[INC_X * 4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[INC_Y * 4]) - - DECQ LEN - JNZ dot_loop // } while --LEN > 0 - - ADDSS P_SUM, SUM // P_SUM += SUM - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail: // do { - MOVSS (X_PTR), X2 // X2 = x[i] - MULSS (Y_PTR), X2 // X2 *= y[i] - ADDSS X2, SUM // SUM += X2 - ADDQ INC_X, X_PTR // X_PTR += INC_X - ADDQ INC_Y, Y_PTR // Y_PTR += INC_Y - DECQ TAIL - JNZ dot_tail // } while --TAIL > 0 - -dot_end: - MOVSS SUM, sum+88(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/dotunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/dotunitary_amd64.s deleted file mode 100644 index 0023a6e2..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/dotunitary_amd64.s +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define HADDPS_SUM_SUM LONG $0xC07C0FF2 // @ HADDPS X0, X0 - -#define X_PTR SI -#define Y_PTR DI -#define LEN CX -#define TAIL BX -#define IDX AX -#define SUM X0 -#define P_SUM X1 - -// func DotUnitary(x, y []float32) (sum float32) -TEXT ·DotUnitary(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y - PXOR SUM, SUM // SUM = 0 - MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+32(FP), LEN - CMOVQLE y_len+32(FP), LEN - CMPQ LEN, $0 - JE dot_end - - XORQ IDX, IDX - MOVQ Y_PTR, DX - ANDQ $0xF, DX // Align on 16-byte boundary for MULPS - JZ dot_no_trim // if DX == 0 { goto dot_no_trim } - SUBQ $16, DX - -dot_align: // Trim first value(s) in unaligned buffer do { - MOVSS (X_PTR)(IDX*4), X2 // X2 = x[i] - MULSS (Y_PTR)(IDX*4), X2 // X2 *= y[i] - ADDSS X2, SUM // SUM += X2 - INCQ IDX // IDX++ - DECQ LEN - JZ dot_end // if --TAIL == 0 { return } - ADDQ $4, DX - JNZ dot_align // } while --DX > 0 - -dot_no_trim: - PXOR P_SUM, P_SUM // P_SUM = 0 for pipelining - MOVQ LEN, TAIL - ANDQ $0xF, TAIL // TAIL = LEN % 16 - SHRQ $4, LEN // LEN = floor( LEN / 16 ) - JZ dot_tail4_start // if LEN == 0 { goto dot_tail4_start } - -dot_loop: // Loop unrolled 16x do { - MOVUPS (X_PTR)(IDX*4), X2 // X_i = x[i:i+1] - MOVUPS 16(X_PTR)(IDX*4), X3 - MOVUPS 32(X_PTR)(IDX*4), X4 - MOVUPS 48(X_PTR)(IDX*4), X5 - - MULPS (Y_PTR)(IDX*4), X2 // X_i *= y[i:i+1] - MULPS 16(Y_PTR)(IDX*4), X3 - MULPS 32(Y_PTR)(IDX*4), X4 - MULPS 48(Y_PTR)(IDX*4), X5 - - ADDPS X2, SUM // SUM += X_i - ADDPS X3, P_SUM - ADDPS X4, SUM - ADDPS X5, P_SUM - - ADDQ $16, IDX // IDX += 16 - DECQ LEN - JNZ dot_loop // } while --LEN > 0 - - ADDPS P_SUM, SUM // SUM += P_SUM - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE dot_end - -dot_tail4_start: // Reset loop counter for 4-wide tail loop - MOVQ TAIL, LEN // LEN = floor( TAIL / 4 ) - SHRQ $2, LEN - JZ dot_tail_start // if LEN == 0 { goto dot_tail_start } - -dot_tail4_loop: // Loop unrolled 4x do { - MOVUPS (X_PTR)(IDX*4), X2 // X_i = x[i:i+1] - MULPS (Y_PTR)(IDX*4), X2 // X_i *= y[i:i+1] - ADDPS X2, SUM // SUM += X_i - ADDQ $4, IDX // i += 4 - DECQ LEN - JNZ dot_tail4_loop // } while --LEN > 0 - -dot_tail_start: // Reset loop counter for 1-wide tail loop - ANDQ $3, TAIL // TAIL = TAIL % 4 - JZ dot_end // if TAIL == 0 { return } - -dot_tail: // do { - MOVSS (X_PTR)(IDX*4), X2 // X2 = x[i] - MULSS (Y_PTR)(IDX*4), X2 // X2 *= y[i] - ADDSS X2, SUM // psum += X2 - INCQ IDX // IDX++ - DECQ TAIL - JNZ dot_tail // } while --TAIL > 0 - -dot_end: - HADDPS_SUM_SUM // SUM = \sum{ SUM[i] } - HADDPS_SUM_SUM - MOVSS SUM, sum+48(FP) // return SUM - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.go deleted file mode 100644 index 72acba20..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright ©2017 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package f32 - -// Ger performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func Ger(m, n uintptr, alpha float32, - x []float32, incX uintptr, - y []float32, incY uintptr, - a []float32, lda uintptr) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.s deleted file mode 100644 index f8fd3df8..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_amd64.s +++ /dev/null @@ -1,757 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SIZE 4 -#define BITSIZE 2 -#define KERNELSIZE 3 - -#define M_DIM m+0(FP) -#define M CX -#define N_DIM n+8(FP) -#define N BX - -#define TMP1 R14 -#define TMP2 R15 - -#define X_PTR SI -#define Y y_base+56(FP) -#define Y_PTR DX -#define A_ROW AX -#define A_PTR DI - -#define INC_X R8 -#define INC3_X R9 - -#define INC_Y R10 -#define INC3_Y R11 - -#define LDA R12 -#define LDA3 R13 - -#define ALPHA X0 -#define ALPHA_SPILL al-16(SP) - -#define LOAD_ALPHA \ - MOVSS alpha+16(FP), ALPHA \ - SHUFPS $0, ALPHA, ALPHA - -#define LOAD_SCALED4 \ - PREFETCHNTA 16*SIZE(X_PTR) \ - MOVDDUP (X_PTR), X1 \ - MOVDDUP 2*SIZE(X_PTR), X3 \ - MOVSHDUP X1, X2 \ - MOVSHDUP X3, X4 \ - MOVSLDUP X1, X1 \ - MOVSLDUP X3, X3 \ - MULPS ALPHA, X1 \ - MULPS ALPHA, X2 \ - MULPS ALPHA, X3 \ - MULPS ALPHA, X4 - -#define LOAD_SCALED2 \ - MOVDDUP (X_PTR), X1 \ - MOVSHDUP X1, X2 \ - MOVSLDUP X1, X1 \ - MULPS ALPHA, X1 \ - MULPS ALPHA, X2 - -#define LOAD_SCALED1 \ - MOVSS (X_PTR), X1 \ - SHUFPS $0, X1, X1 \ - MULPS ALPHA, X1 - -#define LOAD_SCALED4_INC \ - PREFETCHNTA (X_PTR)(INC_X*8) \ - MOVSS (X_PTR), X1 \ - MOVSS (X_PTR)(INC_X*1), X2 \ - MOVSS (X_PTR)(INC_X*2), X3 \ - MOVSS (X_PTR)(INC3_X*1), X4 \ - SHUFPS $0, X1, X1 \ - SHUFPS $0, X2, X2 \ - SHUFPS $0, X3, X3 \ - SHUFPS $0, X4, X4 \ - MULPS ALPHA, X1 \ - MULPS ALPHA, X2 \ - MULPS ALPHA, X3 \ - MULPS ALPHA, X4 - -#define LOAD_SCALED2_INC \ - MOVSS (X_PTR), X1 \ - MOVSS (X_PTR)(INC_X*1), X2 \ - SHUFPS $0, X1, X1 \ - SHUFPS $0, X2, X2 \ - MULPS ALPHA, X1 \ - MULPS ALPHA, X2 - -#define KERNEL_LOAD8 \ - MOVUPS (Y_PTR), X5 \ - MOVUPS 4*SIZE(Y_PTR), X6 - -#define KERNEL_LOAD8_INC \ - MOVSS (Y_PTR), X5 \ - MOVSS (Y_PTR)(INC_Y*1), X6 \ - MOVSS (Y_PTR)(INC_Y*2), X7 \ - MOVSS (Y_PTR)(INC3_Y*1), X8 \ - UNPCKLPS X6, X5 \ - UNPCKLPS X8, X7 \ - MOVLHPS X7, X5 \ - LEAQ (Y_PTR)(INC_Y*4), Y_PTR \ - MOVSS (Y_PTR), X6 \ - MOVSS (Y_PTR)(INC_Y*1), X7 \ - MOVSS (Y_PTR)(INC_Y*2), X8 \ - MOVSS (Y_PTR)(INC3_Y*1), X9 \ - UNPCKLPS X7, X6 \ - UNPCKLPS X9, X8 \ - MOVLHPS X8, X6 - -#define KERNEL_LOAD4 \ - MOVUPS (Y_PTR), X5 - -#define KERNEL_LOAD4_INC \ - MOVSS (Y_PTR), X5 \ - MOVSS (Y_PTR)(INC_Y*1), X6 \ - MOVSS (Y_PTR)(INC_Y*2), X7 \ - MOVSS (Y_PTR)(INC3_Y*1), X8 \ - UNPCKLPS X6, X5 \ - UNPCKLPS X8, X7 \ - MOVLHPS X7, X5 - -#define KERNEL_LOAD2 \ - MOVSD (Y_PTR), X5 - -#define KERNEL_LOAD2_INC \ - MOVSS (Y_PTR), X5 \ - MOVSS (Y_PTR)(INC_Y*1), X6 \ - UNPCKLPS X6, X5 - -#define KERNEL_4x8 \ - MOVUPS X5, X7 \ - MOVUPS X6, X8 \ - MOVUPS X5, X9 \ - MOVUPS X6, X10 \ - MOVUPS X5, X11 \ - MOVUPS X6, X12 \ - MULPS X1, X5 \ - MULPS X1, X6 \ - MULPS X2, X7 \ - MULPS X2, X8 \ - MULPS X3, X9 \ - MULPS X3, X10 \ - MULPS X4, X11 \ - MULPS X4, X12 - -#define STORE_4x8 \ - MOVUPS ALPHA, ALPHA_SPILL \ - MOVUPS (A_PTR), X13 \ - ADDPS X13, X5 \ - MOVUPS 4*SIZE(A_PTR), X14 \ - ADDPS X14, X6 \ - MOVUPS (A_PTR)(LDA*1), X15 \ - ADDPS X15, X7 \ - MOVUPS 4*SIZE(A_PTR)(LDA*1), X0 \ - ADDPS X0, X8 \ - MOVUPS (A_PTR)(LDA*2), X13 \ - ADDPS X13, X9 \ - MOVUPS 4*SIZE(A_PTR)(LDA*2), X14 \ - ADDPS X14, X10 \ - MOVUPS (A_PTR)(LDA3*1), X15 \ - ADDPS X15, X11 \ - MOVUPS 4*SIZE(A_PTR)(LDA3*1), X0 \ - ADDPS X0, X12 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, 4*SIZE(A_PTR) \ - MOVUPS X7, (A_PTR)(LDA*1) \ - MOVUPS X8, 4*SIZE(A_PTR)(LDA*1) \ - MOVUPS X9, (A_PTR)(LDA*2) \ - MOVUPS X10, 4*SIZE(A_PTR)(LDA*2) \ - MOVUPS X11, (A_PTR)(LDA3*1) \ - MOVUPS X12, 4*SIZE(A_PTR)(LDA3*1) \ - MOVUPS ALPHA_SPILL, ALPHA \ - ADDQ $8*SIZE, A_PTR - -#define KERNEL_4x4 \ - MOVUPS X5, X6 \ - MOVUPS X5, X7 \ - MOVUPS X5, X8 \ - MULPS X1, X5 \ - MULPS X2, X6 \ - MULPS X3, X7 \ - MULPS X4, X8 - -#define STORE_4x4 \ - MOVUPS (A_PTR), X13 \ - ADDPS X13, X5 \ - MOVUPS (A_PTR)(LDA*1), X14 \ - ADDPS X14, X6 \ - MOVUPS (A_PTR)(LDA*2), X15 \ - ADDPS X15, X7 \ - MOVUPS (A_PTR)(LDA3*1), X13 \ - ADDPS X13, X8 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, (A_PTR)(LDA*1) \ - MOVUPS X7, (A_PTR)(LDA*2) \ - MOVUPS X8, (A_PTR)(LDA3*1) \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_4x2 \ - MOVUPS X5, X6 \ - MOVUPS X5, X7 \ - MOVUPS X5, X8 \ - MULPS X1, X5 \ - MULPS X2, X6 \ - MULPS X3, X7 \ - MULPS X4, X8 - -#define STORE_4x2 \ - MOVSD (A_PTR), X9 \ - ADDPS X9, X5 \ - MOVSD (A_PTR)(LDA*1), X10 \ - ADDPS X10, X6 \ - MOVSD (A_PTR)(LDA*2), X11 \ - ADDPS X11, X7 \ - MOVSD (A_PTR)(LDA3*1), X12 \ - ADDPS X12, X8 \ - MOVSD X5, (A_PTR) \ - MOVSD X6, (A_PTR)(LDA*1) \ - MOVSD X7, (A_PTR)(LDA*2) \ - MOVSD X8, (A_PTR)(LDA3*1) \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_4x1 \ - MOVSS (Y_PTR), X5 \ - MOVSS X5, X6 \ - MOVSS X5, X7 \ - MOVSS X5, X8 \ - MULSS X1, X5 \ - MULSS X2, X6 \ - MULSS X3, X7 \ - MULSS X4, X8 - -#define STORE_4x1 \ - ADDSS (A_PTR), X5 \ - ADDSS (A_PTR)(LDA*1), X6 \ - ADDSS (A_PTR)(LDA*2), X7 \ - ADDSS (A_PTR)(LDA3*1), X8 \ - MOVSS X5, (A_PTR) \ - MOVSS X6, (A_PTR)(LDA*1) \ - MOVSS X7, (A_PTR)(LDA*2) \ - MOVSS X8, (A_PTR)(LDA3*1) \ - ADDQ $SIZE, A_PTR - -#define KERNEL_2x8 \ - MOVUPS X5, X7 \ - MOVUPS X6, X8 \ - MULPS X1, X5 \ - MULPS X1, X6 \ - MULPS X2, X7 \ - MULPS X2, X8 - -#define STORE_2x8 \ - MOVUPS (A_PTR), X9 \ - ADDPS X9, X5 \ - MOVUPS 4*SIZE(A_PTR), X10 \ - ADDPS X10, X6 \ - MOVUPS (A_PTR)(LDA*1), X11 \ - ADDPS X11, X7 \ - MOVUPS 4*SIZE(A_PTR)(LDA*1), X12 \ - ADDPS X12, X8 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, 4*SIZE(A_PTR) \ - MOVUPS X7, (A_PTR)(LDA*1) \ - MOVUPS X8, 4*SIZE(A_PTR)(LDA*1) \ - ADDQ $8*SIZE, A_PTR - -#define KERNEL_2x4 \ - MOVUPS X5, X6 \ - MULPS X1, X5 \ - MULPS X2, X6 - -#define STORE_2x4 \ - MOVUPS (A_PTR), X9 \ - ADDPS X9, X5 \ - MOVUPS (A_PTR)(LDA*1), X11 \ - ADDPS X11, X6 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, (A_PTR)(LDA*1) \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_2x2 \ - MOVSD X5, X6 \ - MULPS X1, X5 \ - MULPS X2, X6 - -#define STORE_2x2 \ - MOVSD (A_PTR), X7 \ - ADDPS X7, X5 \ - MOVSD (A_PTR)(LDA*1), X8 \ - ADDPS X8, X6 \ - MOVSD X5, (A_PTR) \ - MOVSD X6, (A_PTR)(LDA*1) \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_2x1 \ - MOVSS (Y_PTR), X5 \ - MOVSS X5, X6 \ - MULSS X1, X5 \ - MULSS X2, X6 - -#define STORE_2x1 \ - ADDSS (A_PTR), X5 \ - ADDSS (A_PTR)(LDA*1), X6 \ - MOVSS X5, (A_PTR) \ - MOVSS X6, (A_PTR)(LDA*1) \ - ADDQ $SIZE, A_PTR - -#define KERNEL_1x8 \ - MULPS X1, X5 \ - MULPS X1, X6 - -#define STORE_1x8 \ - MOVUPS (A_PTR), X7 \ - ADDPS X7, X5 \ - MOVUPS 4*SIZE(A_PTR), X8 \ - ADDPS X8, X6 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, 4*SIZE(A_PTR) \ - ADDQ $8*SIZE, A_PTR - -#define KERNEL_1x4 \ - MULPS X1, X5 \ - MULPS X1, X6 - -#define STORE_1x4 \ - MOVUPS (A_PTR), X7 \ - ADDPS X7, X5 \ - MOVUPS X5, (A_PTR) \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_1x2 \ - MULPS X1, X5 - -#define STORE_1x2 \ - MOVSD (A_PTR), X6 \ - ADDPS X6, X5 \ - MOVSD X5, (A_PTR) \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_1x1 \ - MOVSS (Y_PTR), X5 \ - MULSS X1, X5 - -#define STORE_1x1 \ - ADDSS (A_PTR), X5 \ - MOVSS X5, (A_PTR) \ - ADDQ $SIZE, A_PTR - -// func Ger(m, n uintptr, alpha float32, -// x []float32, incX uintptr, -// y []float32, incY uintptr, -// a []float32, lda uintptr) -TEXT ·Ger(SB), 0, $16-120 - MOVQ M_DIM, M - MOVQ N_DIM, N - CMPQ M, $0 - JE end - CMPQ N, $0 - JE end - - LOAD_ALPHA - - MOVQ x_base+24(FP), X_PTR - MOVQ y_base+56(FP), Y_PTR - MOVQ a_base+88(FP), A_ROW - MOVQ A_ROW, A_PTR - MOVQ lda+112(FP), LDA // LDA = LDA * sizeof(float32) - SHLQ $BITSIZE, LDA - LEAQ (LDA)(LDA*2), LDA3 // LDA3 = LDA * 3 - - CMPQ incY+80(FP), $1 // Check for dense vector Y (fast-path) - JNE inc - CMPQ incX+48(FP), $1 // Check for dense vector X (fast-path) - JNE inc - - SHRQ $2, M - JZ r2 - -r4: - - // LOAD 4 - LOAD_SCALED4 - - MOVQ N_DIM, N - SHRQ $KERNELSIZE, N - JZ r4c4 - -r4c8: - // 4x8 KERNEL - KERNEL_LOAD8 - KERNEL_4x8 - STORE_4x8 - - ADDQ $8*SIZE, Y_PTR - - DECQ N - JNZ r4c8 - -r4c4: - TESTQ $4, N_DIM - JZ r4c2 - - // 4x4 KERNEL - KERNEL_LOAD4 - KERNEL_4x4 - STORE_4x4 - - ADDQ $4*SIZE, Y_PTR - -r4c2: - TESTQ $2, N_DIM - JZ r4c1 - - // 4x2 KERNEL - KERNEL_LOAD2 - KERNEL_4x2 - STORE_4x2 - - ADDQ $2*SIZE, Y_PTR - -r4c1: - TESTQ $1, N_DIM - JZ r4end - - // 4x1 KERNEL - KERNEL_4x1 - STORE_4x1 - - ADDQ $SIZE, Y_PTR - -r4end: - ADDQ $4*SIZE, X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ M - JNZ r4 - -r2: - TESTQ $2, M_DIM - JZ r1 - - // LOAD 2 - LOAD_SCALED2 - - MOVQ N_DIM, N - SHRQ $KERNELSIZE, N - JZ r2c4 - -r2c8: - // 2x8 KERNEL - KERNEL_LOAD8 - KERNEL_2x8 - STORE_2x8 - - ADDQ $8*SIZE, Y_PTR - - DECQ N - JNZ r2c8 - -r2c4: - TESTQ $4, N_DIM - JZ r2c2 - - // 2x4 KERNEL - KERNEL_LOAD4 - KERNEL_2x4 - STORE_2x4 - - ADDQ $4*SIZE, Y_PTR - -r2c2: - TESTQ $2, N_DIM - JZ r2c1 - - // 2x2 KERNEL - KERNEL_LOAD2 - KERNEL_2x2 - STORE_2x2 - - ADDQ $2*SIZE, Y_PTR - -r2c1: - TESTQ $1, N_DIM - JZ r2end - - // 2x1 KERNEL - KERNEL_2x1 - STORE_2x1 - - ADDQ $SIZE, Y_PTR - -r2end: - ADDQ $2*SIZE, X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -r1: - TESTQ $1, M_DIM - JZ end - - // LOAD 1 - LOAD_SCALED1 - - MOVQ N_DIM, N - SHRQ $KERNELSIZE, N - JZ r1c4 - -r1c8: - // 1x8 KERNEL - KERNEL_LOAD8 - KERNEL_1x8 - STORE_1x8 - - ADDQ $8*SIZE, Y_PTR - - DECQ N - JNZ r1c8 - -r1c4: - TESTQ $4, N_DIM - JZ r1c2 - - // 1x4 KERNEL - KERNEL_LOAD4 - KERNEL_1x4 - STORE_1x4 - - ADDQ $4*SIZE, Y_PTR - -r1c2: - TESTQ $2, N_DIM - JZ r1c1 - - // 1x2 KERNEL - KERNEL_LOAD2 - KERNEL_1x2 - STORE_1x2 - - ADDQ $2*SIZE, Y_PTR - -r1c1: - TESTQ $1, N_DIM - JZ end - - // 1x1 KERNEL - KERNEL_1x1 - STORE_1x1 - -end: - RET - -inc: // Algorithm for incY != 0 ( split loads in kernel ) - - MOVQ incX+48(FP), INC_X // INC_X = incX * sizeof(float32) - SHLQ $BITSIZE, INC_X - MOVQ incY+80(FP), INC_Y // INC_Y = incY * sizeof(float32) - SHLQ $BITSIZE, INC_Y - LEAQ (INC_X)(INC_X*2), INC3_X // INC3_X = INC_X * 3 - LEAQ (INC_Y)(INC_Y*2), INC3_Y // INC3_Y = INC_Y * 3 - - XORQ TMP2, TMP2 - MOVQ M, TMP1 - SUBQ $1, TMP1 - IMULQ INC_X, TMP1 - NEGQ TMP1 - CMPQ INC_X, $0 - CMOVQLT TMP1, TMP2 - LEAQ (X_PTR)(TMP2*SIZE), X_PTR - - XORQ TMP2, TMP2 - MOVQ N, TMP1 - SUBQ $1, TMP1 - IMULQ INC_Y, TMP1 - NEGQ TMP1 - CMPQ INC_Y, $0 - CMOVQLT TMP1, TMP2 - LEAQ (Y_PTR)(TMP2*SIZE), Y_PTR - - SHRQ $2, M - JZ inc_r2 - -inc_r4: - // LOAD 4 - LOAD_SCALED4_INC - - MOVQ N_DIM, N - SHRQ $KERNELSIZE, N - JZ inc_r4c4 - -inc_r4c8: - // 4x4 KERNEL - KERNEL_LOAD8_INC - KERNEL_4x8 - STORE_4x8 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ N - JNZ inc_r4c8 - -inc_r4c4: - TESTQ $4, N_DIM - JZ inc_r4c2 - - // 4x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_4x4 - STORE_4x4 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - -inc_r4c2: - TESTQ $2, N_DIM - JZ inc_r4c1 - - // 4x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_4x2 - STORE_4x2 - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_r4c1: - TESTQ $1, N_DIM - JZ inc_r4end - - // 4x1 KERNEL - KERNEL_4x1 - STORE_4x1 - - ADDQ INC_Y, Y_PTR - -inc_r4end: - LEAQ (X_PTR)(INC_X*4), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ M - JNZ inc_r4 - -inc_r2: - TESTQ $2, M_DIM - JZ inc_r1 - - // LOAD 2 - LOAD_SCALED2_INC - - MOVQ N_DIM, N - SHRQ $KERNELSIZE, N - JZ inc_r2c4 - -inc_r2c8: - // 2x8 KERNEL - KERNEL_LOAD8_INC - KERNEL_2x8 - STORE_2x8 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ N - JNZ inc_r2c8 - -inc_r2c4: - TESTQ $4, N_DIM - JZ inc_r2c2 - - // 2x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_2x4 - STORE_2x4 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - -inc_r2c2: - TESTQ $2, N_DIM - JZ inc_r2c1 - - // 2x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_2x2 - STORE_2x2 - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_r2c1: - TESTQ $1, N_DIM - JZ inc_r2end - - // 2x1 KERNEL - KERNEL_2x1 - STORE_2x1 - - ADDQ INC_Y, Y_PTR - -inc_r2end: - LEAQ (X_PTR)(INC_X*2), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -inc_r1: - TESTQ $1, M_DIM - JZ end - - // LOAD 1 - LOAD_SCALED1 - - MOVQ N_DIM, N - SHRQ $KERNELSIZE, N - JZ inc_r1c4 - -inc_r1c8: - // 1x8 KERNEL - KERNEL_LOAD8_INC - KERNEL_1x8 - STORE_1x8 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ N - JNZ inc_r1c8 - -inc_r1c4: - TESTQ $4, N_DIM - JZ inc_r1c2 - - // 1x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_1x4 - STORE_1x4 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - -inc_r1c2: - TESTQ $2, N_DIM - JZ inc_r1c1 - - // 1x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_1x2 - STORE_1x2 - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_r1c1: - TESTQ $1, N_DIM - JZ inc_end - - // 1x1 KERNEL - KERNEL_1x1 - STORE_1x1 - -inc_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_noasm.go deleted file mode 100644 index 61ee6f18..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/ge_noasm.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright ©2017 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f32 - -// Ger performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func Ger(m, n uintptr, alpha float32, x []float32, incX uintptr, y []float32, incY uintptr, a []float32, lda uintptr) { - - if incX == 1 && incY == 1 { - x = x[:m] - y = y[:n] - for i, xv := range x { - AxpyUnitary(alpha*xv, y, a[uintptr(i)*lda:uintptr(i)*lda+n]) - } - return - } - - var ky, kx uintptr - if int(incY) < 0 { - ky = uintptr(-int(n-1) * int(incY)) - } - if int(incX) < 0 { - kx = uintptr(-int(m-1) * int(incX)) - } - - ix := kx - for i := 0; i < int(m); i++ { - AxpyInc(alpha*x[ix], y, a[uintptr(i)*lda:uintptr(i)*lda+n], uintptr(n), uintptr(incY), 1, uintptr(ky), 0) - ix += incX - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/gemv.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/gemv.go deleted file mode 100644 index a6000504..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/gemv.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright ©2017 The Gonum 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 f32 - -// GemvN computes -// -// y = alpha * A * x + beta * y -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func GemvN(m, n uintptr, alpha float32, a []float32, lda uintptr, x []float32, incX uintptr, beta float32, y []float32, incY uintptr) { - var kx, ky, i uintptr - if int(incX) < 0 { - kx = uintptr(-int(n-1) * int(incX)) - } - if int(incY) < 0 { - ky = uintptr(-int(m-1) * int(incY)) - } - - if incX == 1 && incY == 1 { - if beta == 0 { - for i = 0; i < m; i++ { - y[i] = alpha * DotUnitary(a[lda*i:lda*i+n], x) - } - return - } - for i = 0; i < m; i++ { - y[i] = y[i]*beta + alpha*DotUnitary(a[lda*i:lda*i+n], x) - } - return - } - iy := ky - if beta == 0 { - for i = 0; i < m; i++ { - y[iy] = alpha * DotInc(x, a[lda*i:lda*i+n], n, incX, 1, kx, 0) - iy += incY - } - return - } - for i = 0; i < m; i++ { - y[iy] = y[iy]*beta + alpha*DotInc(x, a[lda*i:lda*i+n], n, incX, 1, kx, 0) - iy += incY - } -} - -// GemvT computes -// -// y = alpha * Aᵀ * x + beta * y -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func GemvT(m, n uintptr, alpha float32, a []float32, lda uintptr, x []float32, incX uintptr, beta float32, y []float32, incY uintptr) { - var kx, ky, i uintptr - if int(incX) < 0 { - kx = uintptr(-int(m-1) * int(incX)) - } - if int(incY) < 0 { - ky = uintptr(-int(n-1) * int(incY)) - } - switch { - case beta == 0: // beta == 0 is special-cased to memclear - if incY == 1 { - for i := range y { - y[i] = 0 - } - } else { - iy := ky - for i := 0; i < int(n); i++ { - y[iy] = 0 - iy += incY - } - } - case int(incY) < 0: - ScalInc(beta, y, n, uintptr(int(-incY))) - case incY == 1: - ScalUnitary(beta, y[:n]) - default: - ScalInc(beta, y, n, incY) - } - - if incX == 1 && incY == 1 { - for i = 0; i < m; i++ { - AxpyUnitaryTo(y, alpha*x[i], a[lda*i:lda*i+n], y) - } - return - } - ix := kx - for i = 0; i < m; i++ { - AxpyInc(alpha*x[ix], a[lda*i:lda*i+n], y, n, 1, incY, 0, ky) - ix += incX - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/l2norm.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/l2norm.go deleted file mode 100644 index 0f2a7740..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/l2norm.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright ©2019 The Gonum 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 f32 - -import "gonum.org/v1/gonum/internal/math32" - -// L2NormUnitary is the level 2 norm of x. -func L2NormUnitary(x []float32) (sum float32) { - var scale float32 - var sumSquares float32 = 1 - for _, v := range x { - if v == 0 { - continue - } - absxi := math32.Abs(v) - if math32.IsNaN(absxi) { - return math32.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math32.IsInf(scale, 1) { - return math32.Inf(1) - } - return scale * math32.Sqrt(sumSquares) -} - -// L2NormInc is the level 2 norm of x. -func L2NormInc(x []float32, n, incX uintptr) (sum float32) { - var scale float32 - var sumSquares float32 = 1 - for ix := uintptr(0); ix < n*incX; ix += incX { - val := x[ix] - if val == 0 { - continue - } - absxi := math32.Abs(val) - if math32.IsNaN(absxi) { - return math32.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math32.IsInf(scale, 1) { - return math32.Inf(1) - } - return scale * math32.Sqrt(sumSquares) -} - -// L2DistanceUnitary is the L2 norm of x-y. -func L2DistanceUnitary(x, y []float32) (sum float32) { - var scale float32 - var sumSquares float32 = 1 - for i, v := range x { - v -= y[i] - if v == 0 { - continue - } - absxi := math32.Abs(v) - if math32.IsNaN(absxi) { - return math32.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math32.IsInf(scale, 1) { - return math32.Inf(1) - } - return scale * math32.Sqrt(sumSquares) -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go deleted file mode 100644 index ad2adee6..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/scal.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright ©2016 The Gonum 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 f32 - -// ScalUnitary is -// -// for i := range x { -// x[i] *= alpha -// } -func ScalUnitary(alpha float32, x []float32) { - for i := range x { - x[i] *= alpha - } -} - -// ScalUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha * v -// } -func ScalUnitaryTo(dst []float32, alpha float32, x []float32) { - for i, v := range x { - dst[i] = alpha * v - } -} - -// ScalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] *= alpha -// ix += incX -// } -func ScalInc(alpha float32, x []float32, n, incX uintptr) { - var ix uintptr - for i := 0; i < int(n); i++ { - x[ix] *= alpha - ix += incX - } -} - -// ScalIncTo is -// -// var idst, ix uintptr -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha * x[ix] -// ix += incX -// idst += incDst -// } -func ScalIncTo(dst []float32, incDst uintptr, alpha float32, x []float32, n, incX uintptr) { - var idst, ix uintptr - for i := 0; i < int(n); i++ { - dst[idst] = alpha * x[ix] - ix += incX - idst += incDst - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go deleted file mode 100644 index 2ea05197..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_amd64.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright ©2016 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package f32 - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha float32, x, y []float32) - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) - -// DdotUnitary is -// -// for i, v := range x { -// sum += float64(y[i]) * float64(v) -// } -// return -func DdotUnitary(x, y []float32) (sum float64) - -// DdotInc is -// -// for i := 0; i < int(n); i++ { -// sum += float64(y[iy]) * float64(x[ix]) -// ix += incX -// iy += incY -// } -// return -func DdotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float64) - -// DotUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotUnitary(x, y []float32) (sum float32) - -// DotInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float32) - -// Sum is -// -// var sum float32 -// for _, v := range x { -// sum += v -// } -// return sum -func Sum(x []float32) float32 diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go deleted file mode 100644 index 07b36ff3..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/stubs_noasm.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright ©2016 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f32 - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha float32, x, y []float32) { - for i, v := range x { - y[i] += alpha * v - } -} - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) { - for i, v := range x { - dst[i] = alpha*v + y[i] - } -} - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - y[iy] += alpha * x[ix] - ix += incX - iy += incY - } -} - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - dst[idst] = alpha*x[ix] + y[iy] - ix += incX - iy += incY - idst += incDst - } -} - -// DotUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotUnitary(x, y []float32) (sum float32) { - for i, v := range x { - sum += y[i] * v - } - return sum -} - -// DotInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float32) { - for i := 0; i < int(n); i++ { - sum += y[iy] * x[ix] - ix += incX - iy += incY - } - return sum -} - -// DdotUnitary is -// -// for i, v := range x { -// sum += float64(y[i]) * float64(v) -// } -// return -func DdotUnitary(x, y []float32) (sum float64) { - for i, v := range x { - sum += float64(y[i]) * float64(v) - } - return -} - -// DdotInc is -// -// for i := 0; i < int(n); i++ { -// sum += float64(y[iy]) * float64(x[ix]) -// ix += incX -// iy += incY -// } -// return -func DdotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float64) { - for i := 0; i < int(n); i++ { - sum += float64(y[iy]) * float64(x[ix]) - ix += incX - iy += incY - } - return -} - -// Sum is -// -// var sum float32 -// for _, v := range x { -// sum += v -// } -// return sum -func Sum(x []float32) float32 { - var sum float32 - for _, v := range x { - sum += v - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f32/sum_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f32/sum_amd64.s deleted file mode 100644 index 42e96361..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f32/sum_amd64.s +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright ©2021 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define IDX AX -#define LEN CX -#define TAIL BX -#define SUM X0 -#define SUM_1 X1 -#define SUM_2 X2 -#define SUM_3 X3 - -// func Sum(x []float32) float32 -TEXT ·Sum(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ x_len+8(FP), LEN // LEN = len(x) - XORQ IDX, IDX // i = 0 - PXOR SUM, SUM // p_sum_i = 0 - CMPQ LEN, $0 // if LEN == 0 { return 0 } - JE sum_end - - PXOR SUM_1, SUM_1 - PXOR SUM_2, SUM_2 - PXOR SUM_3, SUM_3 - - MOVQ X_PTR, TAIL // Check memory alignment - ANDQ $15, TAIL // TAIL = &x % 16 - JZ no_trim // if TAIL == 0 { goto no_trim } - SUBQ $16, TAIL // TAIL -= 16 - -sum_align: // Align on 16-byte boundary do { - ADDSS (X_PTR)(IDX*4), SUM // SUM += x[0] - INCQ IDX // i++ - DECQ LEN // LEN-- - JZ sum_end // if LEN == 0 { return } - ADDQ $4, TAIL // TAIL += 4 - JNZ sum_align // } while TAIL < 0 - -no_trim: - MOVQ LEN, TAIL - SHRQ $4, LEN // LEN = floor( n / 16 ) - JZ sum_tail8 // if LEN == 0 { goto sum_tail8 } - - -sum_loop: // sum 16x wide do { - ADDPS (X_PTR)(IDX*4), SUM // sum_i += x[i:i+4] - ADDPS 16(X_PTR)(IDX*4), SUM_1 - ADDPS 32(X_PTR)(IDX*4), SUM_2 - ADDPS 48(X_PTR)(IDX*4), SUM_3 - - ADDQ $16, IDX // i += 16 - DECQ LEN - JNZ sum_loop // } while --LEN > 0 - -sum_tail8: - ADDPS SUM_3, SUM - ADDPS SUM_2, SUM_1 - - TESTQ $8, TAIL - JZ sum_tail4 - - ADDPS (X_PTR)(IDX*4), SUM // sum_i += x[i:i+4] - ADDPS 16(X_PTR)(IDX*4), SUM_1 - ADDQ $8, IDX - -sum_tail4: - ADDPS SUM_1, SUM - - TESTQ $4, TAIL - JZ sum_tail2 - - ADDPS (X_PTR)(IDX*4), SUM // sum_i += x[i:i+4] - ADDQ $4, IDX - -sum_tail2: - HADDPS SUM, SUM // sum_i[:2] += sum_i[2:4] - - TESTQ $2, TAIL - JZ sum_tail1 - - MOVSD (X_PTR)(IDX*4), SUM_1 // reuse SUM_1 - ADDPS SUM_1, SUM // sum_i += x[i:i+2] - ADDQ $2, IDX - -sum_tail1: - HADDPS SUM, SUM // sum_i[0] += sum_i[1] - - TESTQ $1, TAIL - JZ sum_end - - ADDSS (X_PTR)(IDX*4), SUM - -sum_end: // return sum - MOVSS SUM, ret+24(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s deleted file mode 100644 index df63dc09..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/abssum_amd64.s +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func L1Norm(x []float64) float64 -TEXT ·L1Norm(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), SI // SI = &x - MOVQ x_len+8(FP), CX // CX = len(x) - XORQ AX, AX // i = 0 - PXOR X0, X0 // p_sum_i = 0 - PXOR X1, X1 - PXOR X2, X2 - PXOR X3, X3 - PXOR X4, X4 - PXOR X5, X5 - PXOR X6, X6 - PXOR X7, X7 - CMPQ CX, $0 // if CX == 0 { return 0 } - JE absum_end - MOVQ CX, BX - ANDQ $7, BX // BX = len(x) % 8 - SHRQ $3, CX // CX = floor( len(x) / 8 ) - JZ absum_tail_start // if CX == 0 { goto absum_tail_start } - -absum_loop: // do { - // p_sum += max( p_sum + x[i], p_sum - x[i] ) - MOVUPS (SI)(AX*8), X8 // X_i = x[i:i+1] - MOVUPS 16(SI)(AX*8), X9 - MOVUPS 32(SI)(AX*8), X10 - MOVUPS 48(SI)(AX*8), X11 - ADDPD X8, X0 // p_sum_i += X_i ( positive values ) - ADDPD X9, X2 - ADDPD X10, X4 - ADDPD X11, X6 - SUBPD X8, X1 // p_sum_(i+1) -= X_i ( negative values ) - SUBPD X9, X3 - SUBPD X10, X5 - SUBPD X11, X7 - MAXPD X1, X0 // p_sum_i = max( p_sum_i, p_sum_(i+1) ) - MAXPD X3, X2 - MAXPD X5, X4 - MAXPD X7, X6 - MOVAPS X0, X1 // p_sum_(i+1) = p_sum_i - MOVAPS X2, X3 - MOVAPS X4, X5 - MOVAPS X6, X7 - ADDQ $8, AX // i += 8 - LOOP absum_loop // } while --CX > 0 - - // p_sum_0 = \sum_{i=1}^{3}( p_sum_(i*2) ) - ADDPD X3, X0 - ADDPD X5, X7 - ADDPD X7, X0 - - // p_sum_0[0] = p_sum_0[0] + p_sum_0[1] - MOVAPS X0, X1 - SHUFPD $0x3, X0, X0 // lower( p_sum_0 ) = upper( p_sum_0 ) - ADDSD X1, X0 - CMPQ BX, $0 - JE absum_end // if BX == 0 { goto absum_end } - -absum_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - XORPS X8, X8 // X_8 = 0 - -absum_tail: // do { - // p_sum += max( p_sum + x[i], p_sum - x[i] ) - MOVSD (SI)(AX*8), X8 // X_8 = x[i] - MOVSD X0, X1 // p_sum_1 = p_sum_0 - ADDSD X8, X0 // p_sum_0 += X_8 - SUBSD X8, X1 // p_sum_1 -= X_8 - MAXSD X1, X0 // p_sum_0 = max( p_sum_0, p_sum_1 ) - INCQ AX // i++ - LOOP absum_tail // } while --CX > 0 - -absum_end: // return p_sum_0 - MOVSD X0, sum+24(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s deleted file mode 100644 index 64751733..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/abssuminc_amd64.s +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func L1NormInc(x []float64, n, incX int) (sum float64) -TEXT ·L1NormInc(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), SI // SI = &x - MOVQ n+24(FP), CX // CX = n - MOVQ incX+32(FP), AX // AX = increment * sizeof( float64 ) - SHLQ $3, AX - MOVQ AX, DX // DX = AX * 3 - IMULQ $3, DX - PXOR X0, X0 // p_sum_i = 0 - PXOR X1, X1 - PXOR X2, X2 - PXOR X3, X3 - PXOR X4, X4 - PXOR X5, X5 - PXOR X6, X6 - PXOR X7, X7 - CMPQ CX, $0 // if CX == 0 { return 0 } - JE absum_end - MOVQ CX, BX - ANDQ $7, BX // BX = n % 8 - SHRQ $3, CX // CX = floor( n / 8 ) - JZ absum_tail_start // if CX == 0 { goto absum_tail_start } - -absum_loop: // do { - // p_sum = max( p_sum + x[i], p_sum - x[i] ) - MOVSD (SI), X8 // X_i[0] = x[i] - MOVSD (SI)(AX*1), X9 - MOVSD (SI)(AX*2), X10 - MOVSD (SI)(DX*1), X11 - LEAQ (SI)(AX*4), SI // SI = SI + 4 - MOVHPD (SI), X8 // X_i[1] = x[i+4] - MOVHPD (SI)(AX*1), X9 - MOVHPD (SI)(AX*2), X10 - MOVHPD (SI)(DX*1), X11 - ADDPD X8, X0 // p_sum_i += X_i ( positive values ) - ADDPD X9, X2 - ADDPD X10, X4 - ADDPD X11, X6 - SUBPD X8, X1 // p_sum_(i+1) -= X_i ( negative values ) - SUBPD X9, X3 - SUBPD X10, X5 - SUBPD X11, X7 - MAXPD X1, X0 // p_sum_i = max( p_sum_i, p_sum_(i+1) ) - MAXPD X3, X2 - MAXPD X5, X4 - MAXPD X7, X6 - MOVAPS X0, X1 // p_sum_(i+1) = p_sum_i - MOVAPS X2, X3 - MOVAPS X4, X5 - MOVAPS X6, X7 - LEAQ (SI)(AX*4), SI // SI = SI + 4 - LOOP absum_loop // } while --CX > 0 - - // p_sum_0 = \sum_{i=1}^{3}( p_sum_(i*2) ) - ADDPD X3, X0 - ADDPD X5, X7 - ADDPD X7, X0 - - // p_sum_0[0] = p_sum_0[0] + p_sum_0[1] - MOVAPS X0, X1 - SHUFPD $0x3, X0, X0 // lower( p_sum_0 ) = upper( p_sum_0 ) - ADDSD X1, X0 - CMPQ BX, $0 - JE absum_end // if BX == 0 { goto absum_end } - -absum_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - XORPS X8, X8 // X_8 = 0 - -absum_tail: // do { - // p_sum += max( p_sum + x[i], p_sum - x[i] ) - MOVSD (SI), X8 // X_8 = x[i] - MOVSD X0, X1 // p_sum_1 = p_sum_0 - ADDSD X8, X0 // p_sum_0 += X_8 - SUBSD X8, X1 // p_sum_1 -= X_8 - MAXSD X1, X0 // p_sum_0 = max( p_sum_0, p_sum_1 ) - ADDQ AX, SI // i++ - LOOP absum_tail // } while --CX > 0 - -absum_end: // return p_sum_0 - MOVSD X0, sum+40(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s deleted file mode 100644 index e377f512..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/add_amd64.s +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func Add(dst, s []float64) -TEXT ·Add(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ dst_len+8(FP), CX // CX = len(dst) - MOVQ s_base+24(FP), SI // SI = &s - CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) - CMOVQLE s_len+32(FP), CX - CMPQ CX, $0 // if CX == 0 { return } - JE add_end - XORQ AX, AX - MOVQ DI, BX - ANDQ $0x0F, BX // BX = &dst & 15 - JZ add_no_trim // if BX == 0 { goto add_no_trim } - - // Align on 16-bit boundary - MOVSD (SI)(AX*8), X0 // X0 = s[i] - ADDSD (DI)(AX*8), X0 // X0 += dst[i] - MOVSD X0, (DI)(AX*8) // dst[i] = X0 - INCQ AX // i++ - DECQ CX // --CX - JE add_end // if CX == 0 { return } - -add_no_trim: - MOVQ CX, BX - ANDQ $7, BX // BX = len(dst) % 8 - SHRQ $3, CX // CX = floor( len(dst) / 8 ) - JZ add_tail_start // if CX == 0 { goto add_tail_start } - -add_loop: // Loop unrolled 8x do { - MOVUPS (SI)(AX*8), X0 // X_i = s[i:i+1] - MOVUPS 16(SI)(AX*8), X1 - MOVUPS 32(SI)(AX*8), X2 - MOVUPS 48(SI)(AX*8), X3 - ADDPD (DI)(AX*8), X0 // X_i += dst[i:i+1] - ADDPD 16(DI)(AX*8), X1 - ADDPD 32(DI)(AX*8), X2 - ADDPD 48(DI)(AX*8), X3 - MOVUPS X0, (DI)(AX*8) // dst[i:i+1] = X_i - MOVUPS X1, 16(DI)(AX*8) - MOVUPS X2, 32(DI)(AX*8) - MOVUPS X3, 48(DI)(AX*8) - ADDQ $8, AX // i += 8 - LOOP add_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE add_end - -add_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - -add_tail: // do { - MOVSD (SI)(AX*8), X0 // X0 = s[i] - ADDSD (DI)(AX*8), X0 // X0 += dst[i] - MOVSD X0, (DI)(AX*8) // dst[i] = X0 - INCQ AX // ++i - LOOP add_tail // } while --CX > 0 - -add_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s deleted file mode 100644 index 6f52a8f6..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/addconst_amd64.s +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func Addconst(alpha float64, x []float64) -TEXT ·AddConst(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), SI // SI = &x - MOVQ x_len+16(FP), CX // CX = len(x) - CMPQ CX, $0 // if len(x) == 0 { return } - JE ac_end - MOVSD alpha+0(FP), X4 // X4 = { a, a } - SHUFPD $0, X4, X4 - MOVUPS X4, X5 // X5 = X4 - XORQ AX, AX // i = 0 - MOVQ CX, BX - ANDQ $7, BX // BX = len(x) % 8 - SHRQ $3, CX // CX = floor( len(x) / 8 ) - JZ ac_tail_start // if CX == 0 { goto ac_tail_start } - -ac_loop: // Loop unrolled 8x do { - MOVUPS (SI)(AX*8), X0 // X_i = s[i:i+1] - MOVUPS 16(SI)(AX*8), X1 - MOVUPS 32(SI)(AX*8), X2 - MOVUPS 48(SI)(AX*8), X3 - ADDPD X4, X0 // X_i += a - ADDPD X5, X1 - ADDPD X4, X2 - ADDPD X5, X3 - MOVUPS X0, (SI)(AX*8) // s[i:i+1] = X_i - MOVUPS X1, 16(SI)(AX*8) - MOVUPS X2, 32(SI)(AX*8) - MOVUPS X3, 48(SI)(AX*8) - ADDQ $8, AX // i += 8 - LOOP ac_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE ac_end - -ac_tail_start: // Reset loop counters - MOVQ BX, CX // Loop counter: CX = BX - -ac_tail: // do { - MOVSD (SI)(AX*8), X0 // X0 = s[i] - ADDSD X4, X0 // X0 += a - MOVSD X0, (SI)(AX*8) // s[i] = X0 - INCQ AX // ++i - LOOP ac_tail // } while --CX > 0 - -ac_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go deleted file mode 100644 index 2ab8129a..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpy.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright ©2015 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f64 - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha float64, x, y []float64) { - for i, v := range x { - y[i] += alpha * v - } -} - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) { - for i, v := range x { - dst[i] = alpha*v + y[i] - } -} - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - y[iy] += alpha * x[ix] - ix += incX - iy += incY - } -} - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { - for i := 0; i < int(n); i++ { - dst[idst] = alpha*x[ix] + y[iy] - ix += incX - iy += incY - idst += incDst - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s deleted file mode 100644 index a4e180fb..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyinc_amd64.s +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define Y_PTR DI -#define DST_PTR DI -#define IDX AX -#define LEN CX -#define TAIL BX -#define INC_X R8 -#define INCx3_X R11 -#define INC_Y R9 -#define INCx3_Y R12 -#define INC_DST R9 -#define INCx3_DST R12 -#define ALPHA X0 -#define ALPHA_2 X1 - -// func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyInc(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), X_PTR // X_PTR = &x - MOVQ y_base+32(FP), Y_PTR // Y_PTR = &y - MOVQ n+56(FP), LEN // LEN = n - CMPQ LEN, $0 // if LEN == 0 { return } - JE end - - MOVQ ix+80(FP), INC_X - MOVQ iy+88(FP), INC_Y - LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(x[ix]) - LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(y[iy]) - MOVQ Y_PTR, DST_PTR // DST_PTR = Y_PTR // Write pointer - - MOVQ incX+64(FP), INC_X // INC_X = incX * sizeof(float64) - SHLQ $3, INC_X - MOVQ incY+72(FP), INC_Y // INC_Y = incY * sizeof(float64) - SHLQ $3, INC_Y - - MOVSD alpha+0(FP), ALPHA // ALPHA = alpha - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = n % 4 - SHRQ $2, LEN // LEN = floor( n / 4 ) - JZ tail_start // if LEN == 0 { goto tail_start } - - MOVAPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 - -loop: // do { // y[i] += alpha * x[i] unrolled 4x. - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MOVSD (X_PTR)(INC_X*2), X4 - MOVSD (X_PTR)(INCx3_X*1), X5 - - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA_2, X3 - MULSD ALPHA, X4 - MULSD ALPHA_2, X5 - - ADDSD (Y_PTR), X2 // X_i += y[i] - ADDSD (Y_PTR)(INC_Y*1), X3 - ADDSD (Y_PTR)(INC_Y*2), X4 - ADDSD (Y_PTR)(INCx3_Y*1), X5 - - MOVSD X2, (DST_PTR) // y[i] = X_i - MOVSD X3, (DST_PTR)(INC_DST*1) - MOVSD X4, (DST_PTR)(INC_DST*2) - MOVSD X5, (DST_PTR)(INCx3_DST*1) - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) - DECQ LEN - JNZ loop // } while --LEN > 0 - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE end - -tail_start: // Reset Loop registers - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( LEN / 2 ) - JZ tail_one - -tail_two: - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA, X3 - ADDSD (Y_PTR), X2 // X_i += y[i] - ADDSD (Y_PTR)(INC_Y*1), X3 - MOVSD X2, (DST_PTR) // y[i] = X_i - MOVSD X3, (DST_PTR)(INC_DST*1) - - LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) - LEAQ (Y_PTR)(INC_Y*2), Y_PTR // Y_PTR = &(Y_PTR[incY*2]) - - ANDQ $1, TAIL - JZ end // if TAIL == 0 { goto end } - -tail_one: - // y[i] += alpha * x[i] for the last n % 4 iterations. - MOVSD (X_PTR), X2 // X2 = x[i] - MULSD ALPHA, X2 // X2 *= a - ADDSD (Y_PTR), X2 // X2 += y[i] - MOVSD X2, (DST_PTR) // y[i] = X2 - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s deleted file mode 100644 index 0f54a394..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyincto_amd64.s +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define Y_PTR DI -#define DST_PTR DX -#define IDX AX -#define LEN CX -#define TAIL BX -#define INC_X R8 -#define INCx3_X R11 -#define INC_Y R9 -#define INCx3_Y R12 -#define INC_DST R10 -#define INCx3_DST R13 -#define ALPHA X0 -#define ALPHA_2 X1 - -// func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) -TEXT ·AxpyIncTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DST_PTR // DST_PTR := &dst - MOVQ x_base+48(FP), X_PTR // X_PTR := &x - MOVQ y_base+72(FP), Y_PTR // Y_PTR := &y - MOVQ n+96(FP), LEN // LEN := n - CMPQ LEN, $0 // if LEN == 0 { return } - JE end - - MOVQ ix+120(FP), INC_X - LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(x[ix]) - MOVQ iy+128(FP), INC_Y - LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(dst[idst]) - MOVQ idst+32(FP), INC_DST - LEAQ (DST_PTR)(INC_DST*8), DST_PTR // DST_PTR = &(y[iy]) - - MOVQ incX+104(FP), INC_X // INC_X = incX * sizeof(float64) - SHLQ $3, INC_X - MOVQ incY+112(FP), INC_Y // INC_Y = incY * sizeof(float64) - SHLQ $3, INC_Y - MOVQ incDst+24(FP), INC_DST // INC_DST = incDst * sizeof(float64) - SHLQ $3, INC_DST - MOVSD alpha+40(FP), ALPHA - - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = n % 4 - SHRQ $2, LEN // LEN = floor( n / 4 ) - JZ tail_start // if LEN == 0 { goto tail_start } - - MOVSD ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 - LEAQ (INC_DST)(INC_DST*2), INCx3_DST // INCx3_DST = INC_DST * 3 - -loop: // do { // y[i] += alpha * x[i] unrolled 2x. - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MOVSD (X_PTR)(INC_X*2), X4 - MOVSD (X_PTR)(INCx3_X*1), X5 - - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA_2, X3 - MULSD ALPHA, X4 - MULSD ALPHA_2, X5 - - ADDSD (Y_PTR), X2 // X_i += y[i] - ADDSD (Y_PTR)(INC_Y*1), X3 - ADDSD (Y_PTR)(INC_Y*2), X4 - ADDSD (Y_PTR)(INCx3_Y*1), X5 - - MOVSD X2, (DST_PTR) // y[i] = X_i - MOVSD X3, (DST_PTR)(INC_DST*1) - MOVSD X4, (DST_PTR)(INC_DST*2) - MOVSD X5, (DST_PTR)(INCx3_DST*1) - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) - LEAQ (DST_PTR)(INC_DST*4), DST_PTR // DST_PTR = &(DST_PTR[incDst*4] - DECQ LEN - JNZ loop // } while --LEN > 0 - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE end - -tail_start: // Reset Loop registers - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( LEN / 2 ) - JZ tail_one - -tail_two: - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA, X3 - ADDSD (Y_PTR), X2 // X_i += y[i] - ADDSD (Y_PTR)(INC_Y*1), X3 - MOVSD X2, (DST_PTR) // y[i] = X_i - MOVSD X3, (DST_PTR)(INC_DST*1) - - LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) - LEAQ (Y_PTR)(INC_Y*2), Y_PTR // Y_PTR = &(Y_PTR[incY*2]) - LEAQ (DST_PTR)(INC_DST*2), DST_PTR // DST_PTR = &(DST_PTR[incY*2] - - ANDQ $1, TAIL - JZ end // if TAIL == 0 { goto end } - -tail_one: - MOVSD (X_PTR), X2 // X2 = x[i] - MULSD ALPHA, X2 // X2 *= a - ADDSD (Y_PTR), X2 // X2 += y[i] - MOVSD X2, (DST_PTR) // y[i] = X2 - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s deleted file mode 100644 index f0b78596..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitary_amd64.s +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define Y_PTR DI -#define DST_PTR DI -#define IDX AX -#define LEN CX -#define TAIL BX -#define ALPHA X0 -#define ALPHA_2 X1 - -// func AxpyUnitary(alpha float64, x, y []float64) -TEXT ·AxpyUnitary(SB), NOSPLIT, $0 - MOVQ x_base+8(FP), X_PTR // X_PTR := &x - MOVQ y_base+32(FP), Y_PTR // Y_PTR := &y - MOVQ x_len+16(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+40(FP), LEN - CMOVQLE y_len+40(FP), LEN - CMPQ LEN, $0 // if LEN == 0 { return } - JE end - XORQ IDX, IDX - MOVSD alpha+0(FP), ALPHA // ALPHA := { alpha, alpha } - SHUFPD $0, ALPHA, ALPHA - MOVUPS ALPHA, ALPHA_2 // ALPHA_2 := ALPHA for pipelining - MOVQ Y_PTR, TAIL // Check memory alignment - ANDQ $15, TAIL // TAIL = &y % 16 - JZ no_trim // if TAIL == 0 { goto no_trim } - - // Align on 16-byte boundary - MOVSD (X_PTR), X2 // X2 := x[0] - MULSD ALPHA, X2 // X2 *= a - ADDSD (Y_PTR), X2 // X2 += y[0] - MOVSD X2, (DST_PTR) // y[0] = X2 - INCQ IDX // i++ - DECQ LEN // LEN-- - JZ end // if LEN == 0 { return } - -no_trim: - MOVQ LEN, TAIL - ANDQ $7, TAIL // TAIL := n % 8 - SHRQ $3, LEN // LEN = floor( n / 8 ) - JZ tail_start // if LEN == 0 { goto tail2_start } - -loop: // do { - // y[i] += alpha * x[i] unrolled 8x. - MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] - MOVUPS 16(X_PTR)(IDX*8), X3 - MOVUPS 32(X_PTR)(IDX*8), X4 - MOVUPS 48(X_PTR)(IDX*8), X5 - - MULPD ALPHA, X2 // X_i *= a - MULPD ALPHA_2, X3 - MULPD ALPHA, X4 - MULPD ALPHA_2, X5 - - ADDPD (Y_PTR)(IDX*8), X2 // X_i += y[i] - ADDPD 16(Y_PTR)(IDX*8), X3 - ADDPD 32(Y_PTR)(IDX*8), X4 - ADDPD 48(Y_PTR)(IDX*8), X5 - - MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X_i - MOVUPS X3, 16(DST_PTR)(IDX*8) - MOVUPS X4, 32(DST_PTR)(IDX*8) - MOVUPS X5, 48(DST_PTR)(IDX*8) - - ADDQ $8, IDX // i += 8 - DECQ LEN - JNZ loop // } while --LEN > 0 - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE end - -tail_start: // Reset loop registers - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( TAIL / 2 ) - JZ tail_one // if TAIL == 0 { goto tail } - -tail_two: // do { - MOVUPS (X_PTR)(IDX*8), X2 // X2 = x[i] - MULPD ALPHA, X2 // X2 *= a - ADDPD (Y_PTR)(IDX*8), X2 // X2 += y[i] - MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X2 - ADDQ $2, IDX // i += 2 - DECQ LEN - JNZ tail_two // } while --LEN > 0 - - ANDQ $1, TAIL - JZ end // if TAIL == 0 { goto end } - -tail_one: - MOVSD (X_PTR)(IDX*8), X2 // X2 = x[i] - MULSD ALPHA, X2 // X2 *= a - ADDSD (Y_PTR)(IDX*8), X2 // X2 += y[i] - MOVSD X2, (DST_PTR)(IDX*8) // y[i] = X2 - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s deleted file mode 100644 index dbb0a7ea..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/axpyunitaryto_amd64.s +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define Y_PTR DX -#define DST_PTR DI -#define IDX AX -#define LEN CX -#define TAIL BX -#define ALPHA X0 -#define ALPHA_2 X1 - -// func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) -TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DST_PTR // DST_PTR := &dst - MOVQ x_base+32(FP), X_PTR // X_PTR := &x - MOVQ y_base+56(FP), Y_PTR // Y_PTR := &y - MOVQ x_len+40(FP), LEN // LEN = min( len(x), len(y), len(dst) ) - CMPQ y_len+64(FP), LEN - CMOVQLE y_len+64(FP), LEN - CMPQ dst_len+8(FP), LEN - CMOVQLE dst_len+8(FP), LEN - - CMPQ LEN, $0 - JE end // if LEN == 0 { return } - - XORQ IDX, IDX // IDX = 0 - MOVSD alpha+24(FP), ALPHA - SHUFPD $0, ALPHA, ALPHA // ALPHA := { alpha, alpha } - MOVQ Y_PTR, TAIL // Check memory alignment - ANDQ $15, TAIL // TAIL = &y % 16 - JZ no_trim // if TAIL == 0 { goto no_trim } - - // Align on 16-byte boundary - MOVSD (X_PTR), X2 // X2 := x[0] - MULSD ALPHA, X2 // X2 *= a - ADDSD (Y_PTR), X2 // X2 += y[0] - MOVSD X2, (DST_PTR) // y[0] = X2 - INCQ IDX // i++ - DECQ LEN // LEN-- - JZ end // if LEN == 0 { return } - -no_trim: - MOVQ LEN, TAIL - ANDQ $7, TAIL // TAIL := n % 8 - SHRQ $3, LEN // LEN = floor( n / 8 ) - JZ tail_start // if LEN == 0 { goto tail_start } - - MOVUPS ALPHA, ALPHA_2 // ALPHA_2 := ALPHA for pipelining - -loop: // do { - // y[i] += alpha * x[i] unrolled 8x. - MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] - MOVUPS 16(X_PTR)(IDX*8), X3 - MOVUPS 32(X_PTR)(IDX*8), X4 - MOVUPS 48(X_PTR)(IDX*8), X5 - - MULPD ALPHA, X2 // X_i *= alpha - MULPD ALPHA_2, X3 - MULPD ALPHA, X4 - MULPD ALPHA_2, X5 - - ADDPD (Y_PTR)(IDX*8), X2 // X_i += y[i] - ADDPD 16(Y_PTR)(IDX*8), X3 - ADDPD 32(Y_PTR)(IDX*8), X4 - ADDPD 48(Y_PTR)(IDX*8), X5 - - MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X_i - MOVUPS X3, 16(DST_PTR)(IDX*8) - MOVUPS X4, 32(DST_PTR)(IDX*8) - MOVUPS X5, 48(DST_PTR)(IDX*8) - - ADDQ $8, IDX // i += 8 - DECQ LEN - JNZ loop // } while --LEN > 0 - CMPQ TAIL, $0 // if TAIL == 0 { return } - JE end - -tail_start: // Reset loop registers - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( TAIL / 2 ) - JZ tail_one // if LEN == 0 { goto tail } - -tail_two: // do { - MOVUPS (X_PTR)(IDX*8), X2 // X2 = x[i] - MULPD ALPHA, X2 // X2 *= alpha - ADDPD (Y_PTR)(IDX*8), X2 // X2 += y[i] - MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X2 - ADDQ $2, IDX // i += 2 - DECQ LEN - JNZ tail_two // } while --LEN > 0 - - ANDQ $1, TAIL - JZ end // if TAIL == 0 { goto end } - -tail_one: - MOVSD (X_PTR)(IDX*8), X2 // X2 = x[i] - MULSD ALPHA, X2 // X2 *= a - ADDSD (Y_PTR)(IDX*8), X2 // X2 += y[i] - MOVSD X2, (DST_PTR)(IDX*8) // y[i] = X2 - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s deleted file mode 100644 index 58168482..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/cumprod_amd64.s +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -TEXT ·CumProd(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ dst_len+8(FP), CX // CX = len(dst) - MOVQ s_base+24(FP), SI // SI = &s - CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) - CMOVQLE s_len+32(FP), CX - MOVQ CX, ret_len+56(FP) // len(ret) = CX - CMPQ CX, $0 // if CX == 0 { return } - JE cp_end - XORQ AX, AX // i = 0 - - MOVSD (SI), X5 // p_prod = { s[0], s[0] } - SHUFPD $0, X5, X5 - MOVSD X5, (DI) // dst[0] = s[0] - INCQ AX // ++i - DECQ CX // -- CX - JZ cp_end // if CX == 0 { return } - - MOVQ CX, BX - ANDQ $3, BX // BX = CX % 4 - SHRQ $2, CX // CX = floor( CX / 4 ) - JZ cp_tail_start // if CX == 0 { goto cp_tail_start } - -cp_loop: // Loop unrolled 4x do { - MOVUPS (SI)(AX*8), X0 // X0 = s[i:i+1] - MOVUPS 16(SI)(AX*8), X2 - MOVAPS X0, X1 // X1 = X0 - MOVAPS X2, X3 - SHUFPD $1, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[0] } - SHUFPD $1, X3, X3 - MULPD X0, X1 // X1 *= X0 - MULPD X2, X3 - SHUFPD $2, X1, X0 // { X0[0], X0[1] } = { X0[0], X1[1] } - SHUFPD $3, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[1] } - SHUFPD $2, X3, X2 - SHUFPD $3, X3, X3 - MULPD X5, X0 // X0 *= p_prod - MULPD X1, X5 // p_prod *= X1 - MULPD X5, X2 - MOVUPS X0, (DI)(AX*8) // dst[i] = X0 - MOVUPS X2, 16(DI)(AX*8) - MULPD X3, X5 - ADDQ $4, AX // i += 4 - LOOP cp_loop // } while --CX > 0 - - // if BX == 0 { return } - CMPQ BX, $0 - JE cp_end - -cp_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - -cp_tail: // do { - MULSD (SI)(AX*8), X5 // p_prod *= s[i] - MOVSD X5, (DI)(AX*8) // dst[i] = p_prod - INCQ AX // ++i - LOOP cp_tail // } while --CX > 0 - -cp_end: - MOVQ DI, ret_base+48(FP) // &ret = &dst - MOVQ dst_cap+16(FP), SI // cap(ret) = cap(dst) - MOVQ SI, ret_cap+64(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s deleted file mode 100644 index 85613202..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/cumsum_amd64.s +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -TEXT ·CumSum(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ dst_len+8(FP), CX // CX = len(dst) - MOVQ s_base+24(FP), SI // SI = &s - CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) - CMOVQLE s_len+32(FP), CX - MOVQ CX, ret_len+56(FP) // len(ret) = CX - CMPQ CX, $0 // if CX == 0 { return } - JE cs_end - XORQ AX, AX // i = 0 - PXOR X5, X5 // p_sum = 0 - MOVQ CX, BX - ANDQ $3, BX // BX = CX % 4 - SHRQ $2, CX // CX = floor( CX / 4 ) - JZ cs_tail_start // if CX == 0 { goto cs_tail_start } - -cs_loop: // Loop unrolled 4x do { - MOVUPS (SI)(AX*8), X0 // X0 = s[i:i+1] - MOVUPS 16(SI)(AX*8), X2 - MOVAPS X0, X1 // X1 = X0 - MOVAPS X2, X3 - SHUFPD $1, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[0] } - SHUFPD $1, X3, X3 - ADDPD X0, X1 // X1 += X0 - ADDPD X2, X3 - SHUFPD $2, X1, X0 // { X0[0], X0[1] } = { X0[0], X1[1] } - SHUFPD $3, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[1] } - SHUFPD $2, X3, X2 - SHUFPD $3, X3, X3 - ADDPD X5, X0 // X0 += p_sum - ADDPD X1, X5 // p_sum += X1 - ADDPD X5, X2 - MOVUPS X0, (DI)(AX*8) // dst[i] = X0 - MOVUPS X2, 16(DI)(AX*8) - ADDPD X3, X5 - ADDQ $4, AX // i += 4 - LOOP cs_loop // } while --CX > 0 - - // if BX == 0 { return } - CMPQ BX, $0 - JE cs_end - -cs_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - -cs_tail: // do { - ADDSD (SI)(AX*8), X5 // p_sum *= s[i] - MOVSD X5, (DI)(AX*8) // dst[i] = p_sum - INCQ AX // ++i - LOOP cs_tail // } while --CX > 0 - -cs_end: - MOVQ DI, ret_base+48(FP) // &ret = &dst - MOVQ dst_cap+16(FP), SI // cap(ret) = cap(dst) - MOVQ SI, ret_cap+64(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s deleted file mode 100644 index 95839767..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/div_amd64.s +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func Div(dst, s []float64) -TEXT ·Div(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ dst_len+8(FP), CX // CX = len(dst) - MOVQ s_base+24(FP), SI // SI = &s - CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) - CMOVQLE s_len+32(FP), CX - CMPQ CX, $0 // if CX == 0 { return } - JE div_end - XORQ AX, AX // i = 0 - MOVQ SI, BX - ANDQ $15, BX // BX = &s & 15 - JZ div_no_trim // if BX == 0 { goto div_no_trim } - - // Align on 16-bit boundary - MOVSD (DI)(AX*8), X0 // X0 = dst[i] - DIVSD (SI)(AX*8), X0 // X0 /= s[i] - MOVSD X0, (DI)(AX*8) // dst[i] = X0 - INCQ AX // ++i - DECQ CX // --CX - JZ div_end // if CX == 0 { return } - -div_no_trim: - MOVQ CX, BX - ANDQ $7, BX // BX = len(dst) % 8 - SHRQ $3, CX // CX = floor( len(dst) / 8 ) - JZ div_tail_start // if CX == 0 { goto div_tail_start } - -div_loop: // Loop unrolled 8x do { - MOVUPS (DI)(AX*8), X0 // X0 = dst[i:i+1] - MOVUPS 16(DI)(AX*8), X1 - MOVUPS 32(DI)(AX*8), X2 - MOVUPS 48(DI)(AX*8), X3 - DIVPD (SI)(AX*8), X0 // X0 /= s[i:i+1] - DIVPD 16(SI)(AX*8), X1 - DIVPD 32(SI)(AX*8), X2 - DIVPD 48(SI)(AX*8), X3 - MOVUPS X0, (DI)(AX*8) // dst[i] = X0 - MOVUPS X1, 16(DI)(AX*8) - MOVUPS X2, 32(DI)(AX*8) - MOVUPS X3, 48(DI)(AX*8) - ADDQ $8, AX // i += 8 - LOOP div_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE div_end - -div_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - -div_tail: // do { - MOVSD (DI)(AX*8), X0 // X0 = dst[i] - DIVSD (SI)(AX*8), X0 // X0 /= s[i] - MOVSD X0, (DI)(AX*8) // dst[i] = X0 - INCQ AX // ++i - LOOP div_tail // } while --CX > 0 - -div_end: - RET - diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s deleted file mode 100644 index e7094cb9..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/divto_amd64.s +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func DivTo(dst, x, y []float64) -TEXT ·DivTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DI // DI = &dst - MOVQ dst_len+8(FP), CX // CX = len(dst) - MOVQ x_base+24(FP), SI // SI = &x - MOVQ y_base+48(FP), DX // DX = &y - CMPQ x_len+32(FP), CX // CX = max( len(dst), len(x), len(y) ) - CMOVQLE x_len+32(FP), CX - CMPQ y_len+56(FP), CX - CMOVQLE y_len+56(FP), CX - MOVQ CX, ret_len+80(FP) // len(ret) = CX - CMPQ CX, $0 // if CX == 0 { return } - JE div_end - XORQ AX, AX // i = 0 - MOVQ DX, BX - ANDQ $15, BX // BX = &y & OxF - JZ div_no_trim // if BX == 0 { goto div_no_trim } - - // Align on 16-bit boundary - MOVSD (SI)(AX*8), X0 // X0 = s[i] - DIVSD (DX)(AX*8), X0 // X0 /= t[i] - MOVSD X0, (DI)(AX*8) // dst[i] = X0 - INCQ AX // ++i - DECQ CX // --CX - JZ div_end // if CX == 0 { return } - -div_no_trim: - MOVQ CX, BX - ANDQ $7, BX // BX = len(dst) % 8 - SHRQ $3, CX // CX = floor( len(dst) / 8 ) - JZ div_tail_start // if CX == 0 { goto div_tail_start } - -div_loop: // Loop unrolled 8x do { - MOVUPS (SI)(AX*8), X0 // X0 = x[i:i+1] - MOVUPS 16(SI)(AX*8), X1 - MOVUPS 32(SI)(AX*8), X2 - MOVUPS 48(SI)(AX*8), X3 - DIVPD (DX)(AX*8), X0 // X0 /= y[i:i+1] - DIVPD 16(DX)(AX*8), X1 - DIVPD 32(DX)(AX*8), X2 - DIVPD 48(DX)(AX*8), X3 - MOVUPS X0, (DI)(AX*8) // dst[i:i+1] = X0 - MOVUPS X1, 16(DI)(AX*8) - MOVUPS X2, 32(DI)(AX*8) - MOVUPS X3, 48(DI)(AX*8) - ADDQ $8, AX // i += 8 - LOOP div_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE div_end - -div_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - -div_tail: // do { - MOVSD (SI)(AX*8), X0 // X0 = x[i] - DIVSD (DX)(AX*8), X0 // X0 /= y[i] - MOVSD X0, (DI)(AX*8) - INCQ AX // ++i - LOOP div_tail // } while --CX > 0 - -div_end: - MOVQ DI, ret_base+72(FP) // &ret = &dst - MOVQ dst_cap+16(FP), DI // cap(ret) = cap(dst) - MOVQ DI, ret_cap+88(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go deleted file mode 100644 index 33c76c1e..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 f64 provides float64 vector primitives. -package f64 // import "gonum.org/v1/gonum/internal/asm/f64" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go deleted file mode 100644 index 09931644..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/dot.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright ©2015 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f64 - -// DotUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotUnitary(x, y []float64) (sum float64) { - for i, v := range x { - sum += y[i] * v - } - return sum -} - -// DotInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) { - for i := 0; i < int(n); i++ { - sum += y[iy] * x[ix] - ix += incX - iy += incY - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s deleted file mode 100644 index c8cd4129..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/dot_amd64.s +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func DdotUnitary(x, y []float64) (sum float64) -// This function assumes len(y) >= len(x). -TEXT ·DotUnitary(SB), NOSPLIT, $0 - MOVQ x+0(FP), R8 - MOVQ x_len+8(FP), DI // n = len(x) - MOVQ y+24(FP), R9 - - MOVSD $(0.0), X7 // sum = 0 - MOVSD $(0.0), X8 // sum = 0 - - MOVQ $0, SI // i = 0 - SUBQ $4, DI // n -= 4 - JL tail_uni // if n < 0 goto tail_uni - -loop_uni: - // sum += x[i] * y[i] unrolled 4x. - MOVUPD 0(R8)(SI*8), X0 - MOVUPD 0(R9)(SI*8), X1 - MOVUPD 16(R8)(SI*8), X2 - MOVUPD 16(R9)(SI*8), X3 - MULPD X1, X0 - MULPD X3, X2 - ADDPD X0, X7 - ADDPD X2, X8 - - ADDQ $4, SI // i += 4 - SUBQ $4, DI // n -= 4 - JGE loop_uni // if n >= 0 goto loop_uni - -tail_uni: - ADDQ $4, DI // n += 4 - JLE end_uni // if n <= 0 goto end_uni - -onemore_uni: - // sum += x[i] * y[i] for the remaining 1-3 elements. - MOVSD 0(R8)(SI*8), X0 - MOVSD 0(R9)(SI*8), X1 - MULSD X1, X0 - ADDSD X0, X7 - - ADDQ $1, SI // i++ - SUBQ $1, DI // n-- - JNZ onemore_uni // if n != 0 goto onemore_uni - -end_uni: - // Add the four sums together. - ADDPD X8, X7 - MOVSD X7, X0 - UNPCKHPD X7, X7 - ADDSD X0, X7 - MOVSD X7, sum+48(FP) // Return final sum. - RET - -// func DdotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) -TEXT ·DotInc(SB), NOSPLIT, $0 - MOVQ x+0(FP), R8 - MOVQ y+24(FP), R9 - MOVQ n+48(FP), CX - MOVQ incX+56(FP), R11 - MOVQ incY+64(FP), R12 - MOVQ ix+72(FP), R13 - MOVQ iy+80(FP), R14 - - MOVSD $(0.0), X7 // sum = 0 - LEAQ (R8)(R13*8), SI // p = &x[ix] - LEAQ (R9)(R14*8), DI // q = &y[ix] - SHLQ $3, R11 // incX *= sizeof(float64) - SHLQ $3, R12 // indY *= sizeof(float64) - - SUBQ $2, CX // n -= 2 - JL tail_inc // if n < 0 goto tail_inc - -loop_inc: - // sum += *p * *q unrolled 2x. - MOVHPD (SI), X0 - MOVHPD (DI), X1 - ADDQ R11, SI // p += incX - ADDQ R12, DI // q += incY - MOVLPD (SI), X0 - MOVLPD (DI), X1 - ADDQ R11, SI // p += incX - ADDQ R12, DI // q += incY - - MULPD X1, X0 - ADDPD X0, X7 - - SUBQ $2, CX // n -= 2 - JGE loop_inc // if n >= 0 goto loop_inc - -tail_inc: - ADDQ $2, CX // n += 2 - JLE end_inc // if n <= 0 goto end_inc - - // sum += *p * *q for the last iteration if n is odd. - MOVSD (SI), X0 - MULSD (DI), X0 - ADDSD X0, X7 - -end_inc: - // Add the two sums together. - MOVSD X7, X0 - UNPCKHPD X7, X7 - ADDSD X0, X7 - MOVSD X7, sum+88(FP) // Return final sum. - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_amd64.go deleted file mode 100644 index 5b042338..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_amd64.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright ©2017 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package f64 - -// Ger performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func Ger(m, n uintptr, alpha float64, x []float64, incX uintptr, y []float64, incY uintptr, a []float64, lda uintptr) - -// GemvN computes -// -// y = alpha * A * x + beta * y -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func GemvN(m, n uintptr, alpha float64, a []float64, lda uintptr, x []float64, incX uintptr, beta float64, y []float64, incY uintptr) - -// GemvT computes -// -// y = alpha * Aᵀ * x + beta * y -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func GemvT(m, n uintptr, alpha float64, a []float64, lda uintptr, x []float64, incX uintptr, beta float64, y []float64, incY uintptr) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go deleted file mode 100644 index e8dee051..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright ©2017 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f64 - -// Ger performs the rank-one operation -// -// A += alpha * x * yᵀ -// -// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. -func Ger(m, n uintptr, alpha float64, x []float64, incX uintptr, y []float64, incY uintptr, a []float64, lda uintptr) { - if incX == 1 && incY == 1 { - x = x[:m] - y = y[:n] - for i, xv := range x { - AxpyUnitary(alpha*xv, y, a[uintptr(i)*lda:uintptr(i)*lda+n]) - } - return - } - - var ky, kx uintptr - if int(incY) < 0 { - ky = uintptr(-int(n-1) * int(incY)) - } - if int(incX) < 0 { - kx = uintptr(-int(m-1) * int(incX)) - } - - ix := kx - for i := 0; i < int(m); i++ { - AxpyInc(alpha*x[ix], y, a[uintptr(i)*lda:uintptr(i)*lda+n], n, incY, 1, ky, 0) - ix += incX - } -} - -// GemvN computes -// -// y = alpha * A * x + beta * y -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func GemvN(m, n uintptr, alpha float64, a []float64, lda uintptr, x []float64, incX uintptr, beta float64, y []float64, incY uintptr) { - var kx, ky, i uintptr - if int(incX) < 0 { - kx = uintptr(-int(n-1) * int(incX)) - } - if int(incY) < 0 { - ky = uintptr(-int(m-1) * int(incY)) - } - - if incX == 1 && incY == 1 { - if beta == 0 { - for i = 0; i < m; i++ { - y[i] = alpha * DotUnitary(a[lda*i:lda*i+n], x) - } - return - } - for i = 0; i < m; i++ { - y[i] = y[i]*beta + alpha*DotUnitary(a[lda*i:lda*i+n], x) - } - return - } - iy := ky - if beta == 0 { - for i = 0; i < m; i++ { - y[iy] = alpha * DotInc(x, a[lda*i:lda*i+n], n, incX, 1, kx, 0) - iy += incY - } - return - } - for i = 0; i < m; i++ { - y[iy] = y[iy]*beta + alpha*DotInc(x, a[lda*i:lda*i+n], n, incX, 1, kx, 0) - iy += incY - } -} - -// GemvT computes -// -// y = alpha * Aᵀ * x + beta * y -// -// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. -func GemvT(m, n uintptr, alpha float64, a []float64, lda uintptr, x []float64, incX uintptr, beta float64, y []float64, incY uintptr) { - var kx, ky, i uintptr - if int(incX) < 0 { - kx = uintptr(-int(m-1) * int(incX)) - } - if int(incY) < 0 { - ky = uintptr(-int(n-1) * int(incY)) - } - switch { - case beta == 0: // beta == 0 is special-cased to memclear - if incY == 1 { - for i := range y { - y[i] = 0 - } - } else { - iy := ky - for i := 0; i < int(n); i++ { - y[iy] = 0 - iy += incY - } - } - case int(incY) < 0: - ScalInc(beta, y, n, uintptr(int(-incY))) - case incY == 1: - ScalUnitary(beta, y[:n]) - default: - ScalInc(beta, y, n, incY) - } - - if incX == 1 && incY == 1 { - for i = 0; i < m; i++ { - AxpyUnitaryTo(y, alpha*x[i], a[lda*i:lda*i+n], y) - } - return - } - ix := kx - for i = 0; i < m; i++ { - AxpyInc(alpha*x[ix], a[lda*i:lda*i+n], y, n, 1, incY, 0, ky) - ix += incX - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s deleted file mode 100644 index 917e0e30..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s +++ /dev/null @@ -1,685 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SIZE 8 - -#define M_DIM m+0(FP) -#define M CX -#define N_DIM n+8(FP) -#define N BX - -#define TMP1 R14 -#define TMP2 R15 - -#define X_PTR SI -#define X x_base+56(FP) -#define INC_X R8 -#define INC3_X R9 - -#define Y_PTR DX -#define Y y_base+96(FP) -#define INC_Y R10 -#define INC3_Y R11 - -#define A_ROW AX -#define A_PTR DI -#define LDA R12 -#define LDA3 R13 - -#define ALPHA X15 -#define BETA X14 - -#define INIT4 \ - XORPS X0, X0 \ - XORPS X1, X1 \ - XORPS X2, X2 \ - XORPS X3, X3 - -#define INIT2 \ - XORPS X0, X0 \ - XORPS X1, X1 - -#define INIT1 \ - XORPS X0, X0 - -#define KERNEL_LOAD4 \ - MOVUPS (X_PTR), X12 \ - MOVUPS 2*SIZE(X_PTR), X13 - -#define KERNEL_LOAD2 \ - MOVUPS (X_PTR), X12 - -#define KERNEL_LOAD4_INC \ - MOVSD (X_PTR), X12 \ - MOVHPD (X_PTR)(INC_X*1), X12 \ - MOVSD (X_PTR)(INC_X*2), X13 \ - MOVHPD (X_PTR)(INC3_X*1), X13 - -#define KERNEL_LOAD2_INC \ - MOVSD (X_PTR), X12 \ - MOVHPD (X_PTR)(INC_X*1), X12 - -#define KERNEL_4x4 \ - MOVUPS (A_PTR), X4 \ - MOVUPS 2*SIZE(A_PTR), X5 \ - MOVUPS (A_PTR)(LDA*1), X6 \ - MOVUPS 2*SIZE(A_PTR)(LDA*1), X7 \ - MOVUPS (A_PTR)(LDA*2), X8 \ - MOVUPS 2*SIZE(A_PTR)(LDA*2), X9 \ - MOVUPS (A_PTR)(LDA3*1), X10 \ - MOVUPS 2*SIZE(A_PTR)(LDA3*1), X11 \ - MULPD X12, X4 \ - MULPD X13, X5 \ - MULPD X12, X6 \ - MULPD X13, X7 \ - MULPD X12, X8 \ - MULPD X13, X9 \ - MULPD X12, X10 \ - MULPD X13, X11 \ - ADDPD X4, X0 \ - ADDPD X5, X0 \ - ADDPD X6, X1 \ - ADDPD X7, X1 \ - ADDPD X8, X2 \ - ADDPD X9, X2 \ - ADDPD X10, X3 \ - ADDPD X11, X3 \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_4x2 \ - MOVUPS (A_PTR), X4 \ - MOVUPS (A_PTR)(LDA*1), X5 \ - MOVUPS (A_PTR)(LDA*2), X6 \ - MOVUPS (A_PTR)(LDA3*1), X7 \ - MULPD X12, X4 \ - MULPD X12, X5 \ - MULPD X12, X6 \ - MULPD X12, X7 \ - ADDPD X4, X0 \ - ADDPD X5, X1 \ - ADDPD X6, X2 \ - ADDPD X7, X3 \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_4x1 \ - MOVDDUP (X_PTR), X12 \ - MOVSD (A_PTR), X4 \ - MOVHPD (A_PTR)(LDA*1), X4 \ - MOVSD (A_PTR)(LDA*2), X5 \ - MOVHPD (A_PTR)(LDA3*1), X5 \ - MULPD X12, X4 \ - MULPD X12, X5 \ - ADDPD X4, X0 \ - ADDPD X5, X2 \ - ADDQ $SIZE, A_PTR - -#define STORE4 \ - MOVUPS (Y_PTR), X4 \ - MOVUPS 2*SIZE(Y_PTR), X5 \ - MULPD ALPHA, X0 \ - MULPD ALPHA, X2 \ - MULPD BETA, X4 \ - MULPD BETA, X5 \ - ADDPD X0, X4 \ - ADDPD X2, X5 \ - MOVUPS X4, (Y_PTR) \ - MOVUPS X5, 2*SIZE(Y_PTR) - -#define STORE4_INC \ - MOVSD (Y_PTR), X4 \ - MOVHPD (Y_PTR)(INC_Y*1), X4 \ - MOVSD (Y_PTR)(INC_Y*2), X5 \ - MOVHPD (Y_PTR)(INC3_Y*1), X5 \ - MULPD ALPHA, X0 \ - MULPD ALPHA, X2 \ - MULPD BETA, X4 \ - MULPD BETA, X5 \ - ADDPD X0, X4 \ - ADDPD X2, X5 \ - MOVLPD X4, (Y_PTR) \ - MOVHPD X4, (Y_PTR)(INC_Y*1) \ - MOVLPD X5, (Y_PTR)(INC_Y*2) \ - MOVHPD X5, (Y_PTR)(INC3_Y*1) - -#define KERNEL_2x4 \ - MOVUPS (A_PTR), X8 \ - MOVUPS 2*SIZE(A_PTR), X9 \ - MOVUPS (A_PTR)(LDA*1), X10 \ - MOVUPS 2*SIZE(A_PTR)(LDA*1), X11 \ - MULPD X12, X8 \ - MULPD X13, X9 \ - MULPD X12, X10 \ - MULPD X13, X11 \ - ADDPD X8, X0 \ - ADDPD X10, X1 \ - ADDPD X9, X0 \ - ADDPD X11, X1 \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_2x2 \ - MOVUPS (A_PTR), X8 \ - MOVUPS (A_PTR)(LDA*1), X9 \ - MULPD X12, X8 \ - MULPD X12, X9 \ - ADDPD X8, X0 \ - ADDPD X9, X1 \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_2x1 \ - MOVDDUP (X_PTR), X12 \ - MOVSD (A_PTR), X8 \ - MOVHPD (A_PTR)(LDA*1), X8 \ - MULPD X12, X8 \ - ADDPD X8, X0 \ - ADDQ $SIZE, A_PTR - -#define STORE2 \ - MOVUPS (Y_PTR), X4 \ - MULPD ALPHA, X0 \ - MULPD BETA, X4 \ - ADDPD X0, X4 \ - MOVUPS X4, (Y_PTR) - -#define STORE2_INC \ - MOVSD (Y_PTR), X4 \ - MOVHPD (Y_PTR)(INC_Y*1), X4 \ - MULPD ALPHA, X0 \ - MULPD BETA, X4 \ - ADDPD X0, X4 \ - MOVSD X4, (Y_PTR) \ - MOVHPD X4, (Y_PTR)(INC_Y*1) - -#define KERNEL_1x4 \ - MOVUPS (A_PTR), X8 \ - MOVUPS 2*SIZE(A_PTR), X9 \ - MULPD X12, X8 \ - MULPD X13, X9 \ - ADDPD X8, X0 \ - ADDPD X9, X0 \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_1x2 \ - MOVUPS (A_PTR), X8 \ - MULPD X12, X8 \ - ADDPD X8, X0 \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_1x1 \ - MOVSD (X_PTR), X12 \ - MOVSD (A_PTR), X8 \ - MULSD X12, X8 \ - ADDSD X8, X0 \ - ADDQ $SIZE, A_PTR - -#define STORE1 \ - HADDPD X0, X0 \ - MOVSD (Y_PTR), X4 \ - MULSD ALPHA, X0 \ - MULSD BETA, X4 \ - ADDSD X0, X4 \ - MOVSD X4, (Y_PTR) - -// func GemvN(m, n int, -// alpha float64, -// a []float64, lda int, -// x []float64, incX int, -// beta float64, -// y []float64, incY int) -TEXT ·GemvN(SB), NOSPLIT, $32-128 - MOVQ M_DIM, M - MOVQ N_DIM, N - CMPQ M, $0 - JE end - CMPQ N, $0 - JE end - - MOVDDUP alpha+16(FP), ALPHA - MOVDDUP beta+88(FP), BETA - - MOVQ x_base+56(FP), X_PTR - MOVQ y_base+96(FP), Y_PTR - MOVQ a_base+24(FP), A_ROW - MOVQ incY+120(FP), INC_Y - MOVQ lda+48(FP), LDA // LDA = LDA * sizeof(float64) - SHLQ $3, LDA - LEAQ (LDA)(LDA*2), LDA3 // LDA3 = LDA * 3 - MOVQ A_ROW, A_PTR - - XORQ TMP2, TMP2 - MOVQ M, TMP1 - SUBQ $1, TMP1 - IMULQ INC_Y, TMP1 - NEGQ TMP1 - CMPQ INC_Y, $0 - CMOVQLT TMP1, TMP2 - LEAQ (Y_PTR)(TMP2*SIZE), Y_PTR - MOVQ Y_PTR, Y - - SHLQ $3, INC_Y // INC_Y = incY * sizeof(float64) - LEAQ (INC_Y)(INC_Y*2), INC3_Y // INC3_Y = INC_Y * 3 - - MOVSD $0.0, X0 - COMISD BETA, X0 - JNE gemv_start // if beta != 0 { goto gemv_start } - -gemv_clear: // beta == 0 is special cased to clear memory (no nan handling) - XORPS X0, X0 - XORPS X1, X1 - XORPS X2, X2 - XORPS X3, X3 - - CMPQ incY+120(FP), $1 // Check for dense vector X (fast-path) - JNE inc_clear - - SHRQ $3, M - JZ clear4 - -clear8: - MOVUPS X0, (Y_PTR) - MOVUPS X1, 16(Y_PTR) - MOVUPS X2, 32(Y_PTR) - MOVUPS X3, 48(Y_PTR) - ADDQ $8*SIZE, Y_PTR - DECQ M - JNZ clear8 - -clear4: - TESTQ $4, M_DIM - JZ clear2 - MOVUPS X0, (Y_PTR) - MOVUPS X1, 16(Y_PTR) - ADDQ $4*SIZE, Y_PTR - -clear2: - TESTQ $2, M_DIM - JZ clear1 - MOVUPS X0, (Y_PTR) - ADDQ $2*SIZE, Y_PTR - -clear1: - TESTQ $1, M_DIM - JZ prep_end - MOVSD X0, (Y_PTR) - - JMP prep_end - -inc_clear: - SHRQ $2, M - JZ inc_clear2 - -inc_clear4: - MOVSD X0, (Y_PTR) - MOVSD X1, (Y_PTR)(INC_Y*1) - MOVSD X2, (Y_PTR)(INC_Y*2) - MOVSD X3, (Y_PTR)(INC3_Y*1) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ M - JNZ inc_clear4 - -inc_clear2: - TESTQ $2, M_DIM - JZ inc_clear1 - MOVSD X0, (Y_PTR) - MOVSD X1, (Y_PTR)(INC_Y*1) - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_clear1: - TESTQ $1, M_DIM - JZ prep_end - MOVSD X0, (Y_PTR) - -prep_end: - MOVQ Y, Y_PTR - MOVQ M_DIM, M - -gemv_start: - CMPQ incX+80(FP), $1 // Check for dense vector X (fast-path) - JNE inc - - SHRQ $2, M - JZ r2 - -r4: - // LOAD 4 - INIT4 - - MOVQ N_DIM, N - SHRQ $2, N - JZ r4c2 - -r4c4: - // 4x4 KERNEL - KERNEL_LOAD4 - KERNEL_4x4 - - ADDQ $4*SIZE, X_PTR - - DECQ N - JNZ r4c4 - -r4c2: - TESTQ $2, N_DIM - JZ r4c1 - - // 4x2 KERNEL - KERNEL_LOAD2 - KERNEL_4x2 - - ADDQ $2*SIZE, X_PTR - -r4c1: - HADDPD X1, X0 - HADDPD X3, X2 - TESTQ $1, N_DIM - JZ r4end - - // 4x1 KERNEL - KERNEL_4x1 - - ADDQ $SIZE, X_PTR - -r4end: - CMPQ INC_Y, $SIZE - JNZ r4st_inc - - STORE4 - ADDQ $4*SIZE, Y_PTR - JMP r4inc - -r4st_inc: - STORE4_INC - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - -r4inc: - MOVQ X, X_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ M - JNZ r4 - -r2: - TESTQ $2, M_DIM - JZ r1 - - // LOAD 2 - INIT2 - - MOVQ N_DIM, N - SHRQ $2, N - JZ r2c2 - -r2c4: - // 2x4 KERNEL - KERNEL_LOAD4 - KERNEL_2x4 - - ADDQ $4*SIZE, X_PTR - - DECQ N - JNZ r2c4 - -r2c2: - TESTQ $2, N_DIM - JZ r2c1 - - // 2x2 KERNEL - KERNEL_LOAD2 - KERNEL_2x2 - - ADDQ $2*SIZE, X_PTR - -r2c1: - HADDPD X1, X0 - TESTQ $1, N_DIM - JZ r2end - - // 2x1 KERNEL - KERNEL_2x1 - - ADDQ $SIZE, X_PTR - -r2end: - CMPQ INC_Y, $SIZE - JNE r2st_inc - - STORE2 - ADDQ $2*SIZE, Y_PTR - JMP r2inc - -r2st_inc: - STORE2_INC - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -r2inc: - MOVQ X, X_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -r1: - TESTQ $1, M_DIM - JZ end - - // LOAD 1 - INIT1 - - MOVQ N_DIM, N - SHRQ $2, N - JZ r1c2 - -r1c4: - // 1x4 KERNEL - KERNEL_LOAD4 - KERNEL_1x4 - - ADDQ $4*SIZE, X_PTR - - DECQ N - JNZ r1c4 - -r1c2: - TESTQ $2, N_DIM - JZ r1c1 - - // 1x2 KERNEL - KERNEL_LOAD2 - KERNEL_1x2 - - ADDQ $2*SIZE, X_PTR - -r1c1: - - TESTQ $1, N_DIM - JZ r1end - - // 1x1 KERNEL - KERNEL_1x1 - -r1end: - STORE1 - -end: - RET - -inc: // Algorithm for incX != 1 ( split loads in kernel ) - MOVQ incX+80(FP), INC_X // INC_X = incX - - XORQ TMP2, TMP2 // TMP2 = 0 - MOVQ N, TMP1 // TMP1 = N - SUBQ $1, TMP1 // TMP1 -= 1 - NEGQ TMP1 // TMP1 = -TMP1 - IMULQ INC_X, TMP1 // TMP1 *= INC_X - CMPQ INC_X, $0 // if INC_X < 0 { TMP2 = TMP1 } - CMOVQLT TMP1, TMP2 - LEAQ (X_PTR)(TMP2*SIZE), X_PTR // X_PTR = X_PTR[TMP2] - MOVQ X_PTR, X // X = X_PTR - - SHLQ $3, INC_X - LEAQ (INC_X)(INC_X*2), INC3_X // INC3_X = INC_X * 3 - - SHRQ $2, M - JZ inc_r2 - -inc_r4: - // LOAD 4 - INIT4 - - MOVQ N_DIM, N - SHRQ $2, N - JZ inc_r4c2 - -inc_r4c4: - // 4x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_4x4 - - LEAQ (X_PTR)(INC_X*4), X_PTR - - DECQ N - JNZ inc_r4c4 - -inc_r4c2: - TESTQ $2, N_DIM - JZ inc_r4c1 - - // 4x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_4x2 - - LEAQ (X_PTR)(INC_X*2), X_PTR - -inc_r4c1: - HADDPD X1, X0 - HADDPD X3, X2 - TESTQ $1, N_DIM - JZ inc_r4end - - // 4x1 KERNEL - KERNEL_4x1 - - ADDQ INC_X, X_PTR - -inc_r4end: - CMPQ INC_Y, $SIZE - JNE inc_r4st_inc - - STORE4 - ADDQ $4*SIZE, Y_PTR - JMP inc_r4inc - -inc_r4st_inc: - STORE4_INC - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - -inc_r4inc: - MOVQ X, X_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ M - JNZ inc_r4 - -inc_r2: - TESTQ $2, M_DIM - JZ inc_r1 - - // LOAD 2 - INIT2 - - MOVQ N_DIM, N - SHRQ $2, N - JZ inc_r2c2 - -inc_r2c4: - // 2x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_2x4 - - LEAQ (X_PTR)(INC_X*4), X_PTR - DECQ N - JNZ inc_r2c4 - -inc_r2c2: - TESTQ $2, N_DIM - JZ inc_r2c1 - - // 2x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_2x2 - - LEAQ (X_PTR)(INC_X*2), X_PTR - -inc_r2c1: - HADDPD X1, X0 - TESTQ $1, N_DIM - JZ inc_r2end - - // 2x1 KERNEL - KERNEL_2x1 - - ADDQ INC_X, X_PTR - -inc_r2end: - CMPQ INC_Y, $SIZE - JNE inc_r2st_inc - - STORE2 - ADDQ $2*SIZE, Y_PTR - JMP inc_r2inc - -inc_r2st_inc: - STORE2_INC - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_r2inc: - MOVQ X, X_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -inc_r1: - TESTQ $1, M_DIM - JZ inc_end - - // LOAD 1 - INIT1 - - MOVQ N_DIM, N - SHRQ $2, N - JZ inc_r1c2 - -inc_r1c4: - // 1x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_1x4 - - LEAQ (X_PTR)(INC_X*4), X_PTR - DECQ N - JNZ inc_r1c4 - -inc_r1c2: - TESTQ $2, N_DIM - JZ inc_r1c1 - - // 1x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_1x2 - - LEAQ (X_PTR)(INC_X*2), X_PTR - -inc_r1c1: - TESTQ $1, N_DIM - JZ inc_r1end - - // 1x1 KERNEL - KERNEL_1x1 - -inc_r1end: - STORE1 - -inc_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s deleted file mode 100644 index 04071000..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s +++ /dev/null @@ -1,745 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SIZE 8 - -#define M_DIM n+8(FP) -#define M CX -#define N_DIM m+0(FP) -#define N BX - -#define TMP1 R14 -#define TMP2 R15 - -#define X_PTR SI -#define X x_base+56(FP) -#define Y_PTR DX -#define Y y_base+96(FP) -#define A_ROW AX -#define A_PTR DI - -#define INC_X R8 -#define INC3_X R9 - -#define INC_Y R10 -#define INC3_Y R11 - -#define LDA R12 -#define LDA3 R13 - -#define ALPHA X15 -#define BETA X14 - -#define INIT4 \ - MOVDDUP (X_PTR), X8 \ - MOVDDUP (X_PTR)(INC_X*1), X9 \ - MOVDDUP (X_PTR)(INC_X*2), X10 \ - MOVDDUP (X_PTR)(INC3_X*1), X11 \ - MULPD ALPHA, X8 \ - MULPD ALPHA, X9 \ - MULPD ALPHA, X10 \ - MULPD ALPHA, X11 - -#define INIT2 \ - MOVDDUP (X_PTR), X8 \ - MOVDDUP (X_PTR)(INC_X*1), X9 \ - MULPD ALPHA, X8 \ - MULPD ALPHA, X9 - -#define INIT1 \ - MOVDDUP (X_PTR), X8 \ - MULPD ALPHA, X8 - -#define KERNEL_LOAD4 \ - MOVUPS (Y_PTR), X0 \ - MOVUPS 2*SIZE(Y_PTR), X1 - -#define KERNEL_LOAD2 \ - MOVUPS (Y_PTR), X0 - -#define KERNEL_LOAD4_INC \ - MOVSD (Y_PTR), X0 \ - MOVHPD (Y_PTR)(INC_Y*1), X0 \ - MOVSD (Y_PTR)(INC_Y*2), X1 \ - MOVHPD (Y_PTR)(INC3_Y*1), X1 - -#define KERNEL_LOAD2_INC \ - MOVSD (Y_PTR), X0 \ - MOVHPD (Y_PTR)(INC_Y*1), X0 - -#define KERNEL_4x4 \ - MOVUPS (A_PTR), X4 \ - MOVUPS 2*SIZE(A_PTR), X5 \ - MOVUPS (A_PTR)(LDA*1), X6 \ - MOVUPS 2*SIZE(A_PTR)(LDA*1), X7 \ - MULPD X8, X4 \ - MULPD X8, X5 \ - MULPD X9, X6 \ - MULPD X9, X7 \ - ADDPD X4, X0 \ - ADDPD X5, X1 \ - ADDPD X6, X0 \ - ADDPD X7, X1 \ - MOVUPS (A_PTR)(LDA*2), X4 \ - MOVUPS 2*SIZE(A_PTR)(LDA*2), X5 \ - MOVUPS (A_PTR)(LDA3*1), X6 \ - MOVUPS 2*SIZE(A_PTR)(LDA3*1), X7 \ - MULPD X10, X4 \ - MULPD X10, X5 \ - MULPD X11, X6 \ - MULPD X11, X7 \ - ADDPD X4, X0 \ - ADDPD X5, X1 \ - ADDPD X6, X0 \ - ADDPD X7, X1 \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_4x2 \ - MOVUPS (A_PTR), X4 \ - MOVUPS 2*SIZE(A_PTR), X5 \ - MOVUPS (A_PTR)(LDA*1), X6 \ - MOVUPS 2*SIZE(A_PTR)(LDA*1), X7 \ - MULPD X8, X4 \ - MULPD X8, X5 \ - MULPD X9, X6 \ - MULPD X9, X7 \ - ADDPD X4, X0 \ - ADDPD X5, X1 \ - ADDPD X6, X0 \ - ADDPD X7, X1 \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_4x1 \ - MOVUPS (A_PTR), X4 \ - MOVUPS 2*SIZE(A_PTR), X5 \ - MULPD X8, X4 \ - MULPD X8, X5 \ - ADDPD X4, X0 \ - ADDPD X5, X1 \ - ADDQ $4*SIZE, A_PTR - -#define STORE4 \ - MOVUPS X0, (Y_PTR) \ - MOVUPS X1, 2*SIZE(Y_PTR) - -#define STORE4_INC \ - MOVLPD X0, (Y_PTR) \ - MOVHPD X0, (Y_PTR)(INC_Y*1) \ - MOVLPD X1, (Y_PTR)(INC_Y*2) \ - MOVHPD X1, (Y_PTR)(INC3_Y*1) - -#define KERNEL_2x4 \ - MOVUPS (A_PTR), X4 \ - MOVUPS (A_PTR)(LDA*1), X5 \ - MOVUPS (A_PTR)(LDA*2), X6 \ - MOVUPS (A_PTR)(LDA3*1), X7 \ - MULPD X8, X4 \ - MULPD X9, X5 \ - MULPD X10, X6 \ - MULPD X11, X7 \ - ADDPD X4, X0 \ - ADDPD X5, X0 \ - ADDPD X6, X0 \ - ADDPD X7, X0 \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_2x2 \ - MOVUPS (A_PTR), X4 \ - MOVUPS (A_PTR)(LDA*1), X5 \ - MULPD X8, X4 \ - MULPD X9, X5 \ - ADDPD X4, X0 \ - ADDPD X5, X0 \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_2x1 \ - MOVUPS (A_PTR), X4 \ - MULPD X8, X4 \ - ADDPD X4, X0 \ - ADDQ $2*SIZE, A_PTR - -#define STORE2 \ - MOVUPS X0, (Y_PTR) - -#define STORE2_INC \ - MOVLPD X0, (Y_PTR) \ - MOVHPD X0, (Y_PTR)(INC_Y*1) - -#define KERNEL_1x4 \ - MOVSD (Y_PTR), X0 \ - MOVSD (A_PTR), X4 \ - MOVSD (A_PTR)(LDA*1), X5 \ - MOVSD (A_PTR)(LDA*2), X6 \ - MOVSD (A_PTR)(LDA3*1), X7 \ - MULSD X8, X4 \ - MULSD X9, X5 \ - MULSD X10, X6 \ - MULSD X11, X7 \ - ADDSD X4, X0 \ - ADDSD X5, X0 \ - ADDSD X6, X0 \ - ADDSD X7, X0 \ - MOVSD X0, (Y_PTR) \ - ADDQ $SIZE, A_PTR - -#define KERNEL_1x2 \ - MOVSD (Y_PTR), X0 \ - MOVSD (A_PTR), X4 \ - MOVSD (A_PTR)(LDA*1), X5 \ - MULSD X8, X4 \ - MULSD X9, X5 \ - ADDSD X4, X0 \ - ADDSD X5, X0 \ - MOVSD X0, (Y_PTR) \ - ADDQ $SIZE, A_PTR - -#define KERNEL_1x1 \ - MOVSD (Y_PTR), X0 \ - MOVSD (A_PTR), X4 \ - MULSD X8, X4 \ - ADDSD X4, X0 \ - MOVSD X0, (Y_PTR) \ - ADDQ $SIZE, A_PTR - -#define SCALE_8(PTR, SCAL) \ - MOVUPS (PTR), X0 \ - MOVUPS 16(PTR), X1 \ - MOVUPS 32(PTR), X2 \ - MOVUPS 48(PTR), X3 \ - MULPD SCAL, X0 \ - MULPD SCAL, X1 \ - MULPD SCAL, X2 \ - MULPD SCAL, X3 \ - MOVUPS X0, (PTR) \ - MOVUPS X1, 16(PTR) \ - MOVUPS X2, 32(PTR) \ - MOVUPS X3, 48(PTR) - -#define SCALE_4(PTR, SCAL) \ - MOVUPS (PTR), X0 \ - MOVUPS 16(PTR), X1 \ - MULPD SCAL, X0 \ - MULPD SCAL, X1 \ - MOVUPS X0, (PTR) \ - MOVUPS X1, 16(PTR) \ - -#define SCALE_2(PTR, SCAL) \ - MOVUPS (PTR), X0 \ - MULPD SCAL, X0 \ - MOVUPS X0, (PTR) \ - -#define SCALE_1(PTR, SCAL) \ - MOVSD (PTR), X0 \ - MULSD SCAL, X0 \ - MOVSD X0, (PTR) \ - -#define SCALEINC_4(PTR, INC, INC3, SCAL) \ - MOVSD (PTR), X0 \ - MOVSD (PTR)(INC*1), X1 \ - MOVSD (PTR)(INC*2), X2 \ - MOVSD (PTR)(INC3*1), X3 \ - MULSD SCAL, X0 \ - MULSD SCAL, X1 \ - MULSD SCAL, X2 \ - MULSD SCAL, X3 \ - MOVSD X0, (PTR) \ - MOVSD X1, (PTR)(INC*1) \ - MOVSD X2, (PTR)(INC*2) \ - MOVSD X3, (PTR)(INC3*1) - -#define SCALEINC_2(PTR, INC, SCAL) \ - MOVSD (PTR), X0 \ - MOVSD (PTR)(INC*1), X1 \ - MULSD SCAL, X0 \ - MULSD SCAL, X1 \ - MOVSD X0, (PTR) \ - MOVSD X1, (PTR)(INC*1) - -// func GemvT(m, n int, -// alpha float64, -// a []float64, lda int, -// x []float64, incX int, -// beta float64, -// y []float64, incY int) -TEXT ·GemvT(SB), NOSPLIT, $32-128 - MOVQ M_DIM, M - MOVQ N_DIM, N - CMPQ M, $0 - JE end - CMPQ N, $0 - JE end - - MOVDDUP alpha+16(FP), ALPHA - - MOVQ x_base+56(FP), X_PTR - MOVQ y_base+96(FP), Y_PTR - MOVQ a_base+24(FP), A_ROW - MOVQ incY+120(FP), INC_Y // INC_Y = incY * sizeof(float64) - MOVQ lda+48(FP), LDA // LDA = LDA * sizeof(float64) - SHLQ $3, LDA - LEAQ (LDA)(LDA*2), LDA3 // LDA3 = LDA * 3 - MOVQ A_ROW, A_PTR - - MOVQ incX+80(FP), INC_X // INC_X = incX * sizeof(float64) - - XORQ TMP2, TMP2 - MOVQ N, TMP1 - SUBQ $1, TMP1 - NEGQ TMP1 - IMULQ INC_X, TMP1 - CMPQ INC_X, $0 - CMOVQLT TMP1, TMP2 - LEAQ (X_PTR)(TMP2*SIZE), X_PTR - MOVQ X_PTR, X - - SHLQ $3, INC_X - LEAQ (INC_X)(INC_X*2), INC3_X // INC3_X = INC_X * 3 - - CMPQ incY+120(FP), $1 // Check for dense vector Y (fast-path) - JNE inc - - MOVSD $1.0, X0 - COMISD beta+88(FP), X0 - JE gemv_start - - MOVSD $0.0, X0 - COMISD beta+88(FP), X0 - JE gemv_clear - - MOVDDUP beta+88(FP), BETA - SHRQ $3, M - JZ scal4 - -scal8: - SCALE_8(Y_PTR, BETA) - ADDQ $8*SIZE, Y_PTR - DECQ M - JNZ scal8 - -scal4: - TESTQ $4, M_DIM - JZ scal2 - SCALE_4(Y_PTR, BETA) - ADDQ $4*SIZE, Y_PTR - -scal2: - TESTQ $2, M_DIM - JZ scal1 - SCALE_2(Y_PTR, BETA) - ADDQ $2*SIZE, Y_PTR - -scal1: - TESTQ $1, M_DIM - JZ prep_end - SCALE_1(Y_PTR, BETA) - - JMP prep_end - -gemv_clear: // beta == 0 is special cased to clear memory (no nan handling) - XORPS X0, X0 - XORPS X1, X1 - XORPS X2, X2 - XORPS X3, X3 - - SHRQ $3, M - JZ clear4 - -clear8: - MOVUPS X0, (Y_PTR) - MOVUPS X1, 16(Y_PTR) - MOVUPS X2, 32(Y_PTR) - MOVUPS X3, 48(Y_PTR) - ADDQ $8*SIZE, Y_PTR - DECQ M - JNZ clear8 - -clear4: - TESTQ $4, M_DIM - JZ clear2 - MOVUPS X0, (Y_PTR) - MOVUPS X1, 16(Y_PTR) - ADDQ $4*SIZE, Y_PTR - -clear2: - TESTQ $2, M_DIM - JZ clear1 - MOVUPS X0, (Y_PTR) - ADDQ $2*SIZE, Y_PTR - -clear1: - TESTQ $1, M_DIM - JZ prep_end - MOVSD X0, (Y_PTR) - -prep_end: - MOVQ Y, Y_PTR - MOVQ M_DIM, M - -gemv_start: - SHRQ $2, N - JZ c2 - -c4: - // LOAD 4 - INIT4 - - MOVQ M_DIM, M - SHRQ $2, M - JZ c4r2 - -c4r4: - // 4x4 KERNEL - KERNEL_LOAD4 - KERNEL_4x4 - STORE4 - - ADDQ $4*SIZE, Y_PTR - - DECQ M - JNZ c4r4 - -c4r2: - TESTQ $2, M_DIM - JZ c4r1 - - // 4x2 KERNEL - KERNEL_LOAD2 - KERNEL_2x4 - STORE2 - - ADDQ $2*SIZE, Y_PTR - -c4r1: - TESTQ $1, M_DIM - JZ c4end - - // 4x1 KERNEL - KERNEL_1x4 - - ADDQ $SIZE, Y_PTR - -c4end: - LEAQ (X_PTR)(INC_X*4), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ N - JNZ c4 - -c2: - TESTQ $2, N_DIM - JZ c1 - - // LOAD 2 - INIT2 - - MOVQ M_DIM, M - SHRQ $2, M - JZ c2r2 - -c2r4: - // 2x4 KERNEL - KERNEL_LOAD4 - KERNEL_4x2 - STORE4 - - ADDQ $4*SIZE, Y_PTR - - DECQ M - JNZ c2r4 - -c2r2: - TESTQ $2, M_DIM - JZ c2r1 - - // 2x2 KERNEL - KERNEL_LOAD2 - KERNEL_2x2 - STORE2 - - ADDQ $2*SIZE, Y_PTR - -c2r1: - TESTQ $1, M_DIM - JZ c2end - - // 2x1 KERNEL - KERNEL_1x2 - - ADDQ $SIZE, Y_PTR - -c2end: - LEAQ (X_PTR)(INC_X*2), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -c1: - TESTQ $1, N_DIM - JZ end - - // LOAD 1 - INIT1 - - MOVQ M_DIM, M - SHRQ $2, M - JZ c1r2 - -c1r4: - // 1x4 KERNEL - KERNEL_LOAD4 - KERNEL_4x1 - STORE4 - - ADDQ $4*SIZE, Y_PTR - - DECQ M - JNZ c1r4 - -c1r2: - TESTQ $2, M_DIM - JZ c1r1 - - // 1x2 KERNEL - KERNEL_LOAD2 - KERNEL_2x1 - STORE2 - - ADDQ $2*SIZE, Y_PTR - -c1r1: - TESTQ $1, M_DIM - JZ end - - // 1x1 KERNEL - KERNEL_1x1 - -end: - RET - -inc: // Algorithm for incX != 0 ( split loads in kernel ) - XORQ TMP2, TMP2 - MOVQ M, TMP1 - SUBQ $1, TMP1 - IMULQ INC_Y, TMP1 - NEGQ TMP1 - CMPQ INC_Y, $0 - CMOVQLT TMP1, TMP2 - LEAQ (Y_PTR)(TMP2*SIZE), Y_PTR - MOVQ Y_PTR, Y - - SHLQ $3, INC_Y - LEAQ (INC_Y)(INC_Y*2), INC3_Y // INC3_Y = INC_Y * 3 - - MOVSD $1.0, X0 - COMISD beta+88(FP), X0 - JE inc_gemv_start - - MOVSD $0.0, X0 - COMISD beta+88(FP), X0 - JE inc_gemv_clear - - MOVDDUP beta+88(FP), BETA - SHRQ $2, M - JZ inc_scal2 - -inc_scal4: - SCALEINC_4(Y_PTR, INC_Y, INC3_Y, BETA) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ M - JNZ inc_scal4 - -inc_scal2: - TESTQ $2, M_DIM - JZ inc_scal1 - - SCALEINC_2(Y_PTR, INC_Y, BETA) - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_scal1: - TESTQ $1, M_DIM - JZ inc_prep_end - SCALE_1(Y_PTR, BETA) - - JMP inc_prep_end - -inc_gemv_clear: // beta == 0 is special-cased to clear memory (no nan handling) - XORPS X0, X0 - XORPS X1, X1 - XORPS X2, X2 - XORPS X3, X3 - - SHRQ $2, M - JZ inc_clear2 - -inc_clear4: - MOVSD X0, (Y_PTR) - MOVSD X1, (Y_PTR)(INC_Y*1) - MOVSD X2, (Y_PTR)(INC_Y*2) - MOVSD X3, (Y_PTR)(INC3_Y*1) - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ M - JNZ inc_clear4 - -inc_clear2: - TESTQ $2, M_DIM - JZ inc_clear1 - MOVSD X0, (Y_PTR) - MOVSD X1, (Y_PTR)(INC_Y*1) - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_clear1: - TESTQ $1, M_DIM - JZ inc_prep_end - MOVSD X0, (Y_PTR) - -inc_prep_end: - MOVQ Y, Y_PTR - MOVQ M_DIM, M - -inc_gemv_start: - SHRQ $2, N - JZ inc_c2 - -inc_c4: - // LOAD 4 - INIT4 - - MOVQ M_DIM, M - SHRQ $2, M - JZ inc_c4r2 - -inc_c4r4: - // 4x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_4x4 - STORE4_INC - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - - DECQ M - JNZ inc_c4r4 - -inc_c4r2: - TESTQ $2, M_DIM - JZ inc_c4r1 - - // 4x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_2x4 - STORE2_INC - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_c4r1: - TESTQ $1, M_DIM - JZ inc_c4end - - // 4x1 KERNEL - KERNEL_1x4 - - ADDQ INC_Y, Y_PTR - -inc_c4end: - LEAQ (X_PTR)(INC_X*4), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ N - JNZ inc_c4 - -inc_c2: - TESTQ $2, N_DIM - JZ inc_c1 - - // LOAD 2 - INIT2 - - MOVQ M_DIM, M - SHRQ $2, M - JZ inc_c2r2 - -inc_c2r4: - // 2x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_4x2 - STORE4_INC - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ M - JNZ inc_c2r4 - -inc_c2r2: - TESTQ $2, M_DIM - JZ inc_c2r1 - - // 2x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_2x2 - STORE2_INC - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_c2r1: - TESTQ $1, M_DIM - JZ inc_c2end - - // 2x1 KERNEL - KERNEL_1x2 - - ADDQ INC_Y, Y_PTR - -inc_c2end: - LEAQ (X_PTR)(INC_X*2), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -inc_c1: - TESTQ $1, N_DIM - JZ inc_end - - // LOAD 1 - INIT1 - - MOVQ M_DIM, M - SHRQ $2, M - JZ inc_c1r2 - -inc_c1r4: - // 1x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_4x1 - STORE4_INC - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ M - JNZ inc_c1r4 - -inc_c1r2: - TESTQ $2, M_DIM - JZ inc_c1r1 - - // 1x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_2x1 - STORE2_INC - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_c1r1: - TESTQ $1, M_DIM - JZ inc_end - - // 1x1 KERNEL - KERNEL_1x1 - -inc_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/ger_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/ger_amd64.s deleted file mode 100644 index 8cae5691..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/ger_amd64.s +++ /dev/null @@ -1,591 +0,0 @@ -// Copyright ©2017 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SIZE 8 - -#define M_DIM m+0(FP) -#define M CX -#define N_DIM n+8(FP) -#define N BX - -#define TMP1 R14 -#define TMP2 R15 - -#define X_PTR SI -#define Y y_base+56(FP) -#define Y_PTR DX -#define A_ROW AX -#define A_PTR DI - -#define INC_X R8 -#define INC3_X R9 - -#define INC_Y R10 -#define INC3_Y R11 - -#define LDA R12 -#define LDA3 R13 - -#define ALPHA X0 - -#define LOAD4 \ - PREFETCHNTA (X_PTR )(INC_X*8) \ - MOVDDUP (X_PTR), X1 \ - MOVDDUP (X_PTR)(INC_X*1), X2 \ - MOVDDUP (X_PTR)(INC_X*2), X3 \ - MOVDDUP (X_PTR)(INC3_X*1), X4 \ - MULPD ALPHA, X1 \ - MULPD ALPHA, X2 \ - MULPD ALPHA, X3 \ - MULPD ALPHA, X4 - -#define LOAD2 \ - MOVDDUP (X_PTR), X1 \ - MOVDDUP (X_PTR)(INC_X*1), X2 \ - MULPD ALPHA, X1 \ - MULPD ALPHA, X2 - -#define LOAD1 \ - MOVDDUP (X_PTR), X1 \ - MULPD ALPHA, X1 - -#define KERNEL_LOAD4 \ - MOVUPS (Y_PTR), X5 \ - MOVUPS 2*SIZE(Y_PTR), X6 - -#define KERNEL_LOAD4_INC \ - MOVLPD (Y_PTR), X5 \ - MOVHPD (Y_PTR)(INC_Y*1), X5 \ - MOVLPD (Y_PTR)(INC_Y*2), X6 \ - MOVHPD (Y_PTR)(INC3_Y*1), X6 - -#define KERNEL_LOAD2 \ - MOVUPS (Y_PTR), X5 - -#define KERNEL_LOAD2_INC \ - MOVLPD (Y_PTR), X5 \ - MOVHPD (Y_PTR)(INC_Y*1), X5 - -#define KERNEL_4x4 \ - MOVUPS X5, X7 \ - MOVUPS X6, X8 \ - MOVUPS X5, X9 \ - MOVUPS X6, X10 \ - MOVUPS X5, X11 \ - MOVUPS X6, X12 \ - MULPD X1, X5 \ - MULPD X1, X6 \ - MULPD X2, X7 \ - MULPD X2, X8 \ - MULPD X3, X9 \ - MULPD X3, X10 \ - MULPD X4, X11 \ - MULPD X4, X12 - -#define STORE_4x4 \ - MOVUPS (A_PTR), X13 \ - ADDPD X13, X5 \ - MOVUPS 2*SIZE(A_PTR), X14 \ - ADDPD X14, X6 \ - MOVUPS (A_PTR)(LDA*1), X15 \ - ADDPD X15, X7 \ - MOVUPS 2*SIZE(A_PTR)(LDA*1), X0 \ - ADDPD X0, X8 \ - MOVUPS (A_PTR)(LDA*2), X13 \ - ADDPD X13, X9 \ - MOVUPS 2*SIZE(A_PTR)(LDA*2), X14 \ - ADDPD X14, X10 \ - MOVUPS (A_PTR)(LDA3*1), X15 \ - ADDPD X15, X11 \ - MOVUPS 2*SIZE(A_PTR)(LDA3*1), X0 \ - ADDPD X0, X12 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, 2*SIZE(A_PTR) \ - MOVUPS X7, (A_PTR)(LDA*1) \ - MOVUPS X8, 2*SIZE(A_PTR)(LDA*1) \ - MOVUPS X9, (A_PTR)(LDA*2) \ - MOVUPS X10, 2*SIZE(A_PTR)(LDA*2) \ - MOVUPS X11, (A_PTR)(LDA3*1) \ - MOVUPS X12, 2*SIZE(A_PTR)(LDA3*1) \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_4x2 \ - MOVUPS X5, X6 \ - MOVUPS X5, X7 \ - MOVUPS X5, X8 \ - MULPD X1, X5 \ - MULPD X2, X6 \ - MULPD X3, X7 \ - MULPD X4, X8 - -#define STORE_4x2 \ - MOVUPS (A_PTR), X9 \ - ADDPD X9, X5 \ - MOVUPS (A_PTR)(LDA*1), X10 \ - ADDPD X10, X6 \ - MOVUPS (A_PTR)(LDA*2), X11 \ - ADDPD X11, X7 \ - MOVUPS (A_PTR)(LDA3*1), X12 \ - ADDPD X12, X8 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, (A_PTR)(LDA*1) \ - MOVUPS X7, (A_PTR)(LDA*2) \ - MOVUPS X8, (A_PTR)(LDA3*1) \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_4x1 \ - MOVSD (Y_PTR), X5 \ - MOVSD X5, X6 \ - MOVSD X5, X7 \ - MOVSD X5, X8 \ - MULSD X1, X5 \ - MULSD X2, X6 \ - MULSD X3, X7 \ - MULSD X4, X8 - -#define STORE_4x1 \ - ADDSD (A_PTR), X5 \ - ADDSD (A_PTR)(LDA*1), X6 \ - ADDSD (A_PTR)(LDA*2), X7 \ - ADDSD (A_PTR)(LDA3*1), X8 \ - MOVSD X5, (A_PTR) \ - MOVSD X6, (A_PTR)(LDA*1) \ - MOVSD X7, (A_PTR)(LDA*2) \ - MOVSD X8, (A_PTR)(LDA3*1) \ - ADDQ $SIZE, A_PTR - -#define KERNEL_2x4 \ - MOVUPS X5, X7 \ - MOVUPS X6, X8 \ - MULPD X1, X5 \ - MULPD X1, X6 \ - MULPD X2, X7 \ - MULPD X2, X8 - -#define STORE_2x4 \ - MOVUPS (A_PTR), X9 \ - ADDPD X9, X5 \ - MOVUPS 2*SIZE(A_PTR), X10 \ - ADDPD X10, X6 \ - MOVUPS (A_PTR)(LDA*1), X11 \ - ADDPD X11, X7 \ - MOVUPS 2*SIZE(A_PTR)(LDA*1), X12 \ - ADDPD X12, X8 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, 2*SIZE(A_PTR) \ - MOVUPS X7, (A_PTR)(LDA*1) \ - MOVUPS X8, 2*SIZE(A_PTR)(LDA*1) \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_2x2 \ - MOVUPS X5, X6 \ - MULPD X1, X5 \ - MULPD X2, X6 - -#define STORE_2x2 \ - MOVUPS (A_PTR), X7 \ - ADDPD X7, X5 \ - MOVUPS (A_PTR)(LDA*1), X8 \ - ADDPD X8, X6 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, (A_PTR)(LDA*1) \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_2x1 \ - MOVSD (Y_PTR), X5 \ - MOVSD X5, X6 \ - MULSD X1, X5 \ - MULSD X2, X6 - -#define STORE_2x1 \ - ADDSD (A_PTR), X5 \ - ADDSD (A_PTR)(LDA*1), X6 \ - MOVSD X5, (A_PTR) \ - MOVSD X6, (A_PTR)(LDA*1) \ - ADDQ $SIZE, A_PTR - -#define KERNEL_1x4 \ - MULPD X1, X5 \ - MULPD X1, X6 - -#define STORE_1x4 \ - MOVUPS (A_PTR), X7 \ - ADDPD X7, X5 \ - MOVUPS 2*SIZE(A_PTR), X8 \ - ADDPD X8, X6 \ - MOVUPS X5, (A_PTR) \ - MOVUPS X6, 2*SIZE(A_PTR) \ - ADDQ $4*SIZE, A_PTR - -#define KERNEL_1x2 \ - MULPD X1, X5 - -#define STORE_1x2 \ - MOVUPS (A_PTR), X6 \ - ADDPD X6, X5 \ - MOVUPS X5, (A_PTR) \ - ADDQ $2*SIZE, A_PTR - -#define KERNEL_1x1 \ - MOVSD (Y_PTR), X5 \ - MULSD X1, X5 - -#define STORE_1x1 \ - ADDSD (A_PTR), X5 \ - MOVSD X5, (A_PTR) \ - ADDQ $SIZE, A_PTR - -// func Ger(m, n uintptr, alpha float64, -// x []float64, incX uintptr, -// y []float64, incY uintptr, -// a []float64, lda uintptr) -TEXT ·Ger(SB), NOSPLIT, $0 - MOVQ M_DIM, M - MOVQ N_DIM, N - CMPQ M, $0 - JE end - CMPQ N, $0 - JE end - - MOVDDUP alpha+16(FP), ALPHA - - MOVQ x_base+24(FP), X_PTR - MOVQ y_base+56(FP), Y_PTR - MOVQ a_base+88(FP), A_ROW - MOVQ incX+48(FP), INC_X // INC_X = incX * sizeof(float64) - SHLQ $3, INC_X - MOVQ lda+112(FP), LDA // LDA = LDA * sizeof(float64) - SHLQ $3, LDA - LEAQ (LDA)(LDA*2), LDA3 // LDA3 = LDA * 3 - LEAQ (INC_X)(INC_X*2), INC3_X // INC3_X = INC_X * 3 - MOVQ A_ROW, A_PTR - - XORQ TMP2, TMP2 - MOVQ M, TMP1 - SUBQ $1, TMP1 - IMULQ INC_X, TMP1 - NEGQ TMP1 - CMPQ INC_X, $0 - CMOVQLT TMP1, TMP2 - LEAQ (X_PTR)(TMP2*SIZE), X_PTR - - CMPQ incY+80(FP), $1 // Check for dense vector Y (fast-path) - JG inc - JL end - - SHRQ $2, M - JZ r2 - -r4: - // LOAD 4 - LOAD4 - - MOVQ N_DIM, N - SHRQ $2, N - JZ r4c2 - -r4c4: - // 4x4 KERNEL - KERNEL_LOAD4 - KERNEL_4x4 - STORE_4x4 - - ADDQ $4*SIZE, Y_PTR - - DECQ N - JNZ r4c4 - - // Reload ALPHA after it's clobbered by STORE_4x4 - MOVDDUP alpha+16(FP), ALPHA - -r4c2: - TESTQ $2, N_DIM - JZ r4c1 - - // 4x2 KERNEL - KERNEL_LOAD2 - KERNEL_4x2 - STORE_4x2 - - ADDQ $2*SIZE, Y_PTR - -r4c1: - TESTQ $1, N_DIM - JZ r4end - - // 4x1 KERNEL - KERNEL_4x1 - STORE_4x1 - - ADDQ $SIZE, Y_PTR - -r4end: - LEAQ (X_PTR)(INC_X*4), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ M - JNZ r4 - -r2: - TESTQ $2, M_DIM - JZ r1 - - // LOAD 2 - LOAD2 - - MOVQ N_DIM, N - SHRQ $2, N - JZ r2c2 - -r2c4: - // 2x4 KERNEL - KERNEL_LOAD4 - KERNEL_2x4 - STORE_2x4 - - ADDQ $4*SIZE, Y_PTR - - DECQ N - JNZ r2c4 - -r2c2: - TESTQ $2, N_DIM - JZ r2c1 - - // 2x2 KERNEL - KERNEL_LOAD2 - KERNEL_2x2 - STORE_2x2 - - ADDQ $2*SIZE, Y_PTR - -r2c1: - TESTQ $1, N_DIM - JZ r2end - - // 2x1 KERNEL - KERNEL_2x1 - STORE_2x1 - - ADDQ $SIZE, Y_PTR - -r2end: - LEAQ (X_PTR)(INC_X*2), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -r1: - TESTQ $1, M_DIM - JZ end - - // LOAD 1 - LOAD1 - - MOVQ N_DIM, N - SHRQ $2, N - JZ r1c2 - -r1c4: - // 1x4 KERNEL - KERNEL_LOAD4 - KERNEL_1x4 - STORE_1x4 - - ADDQ $4*SIZE, Y_PTR - - DECQ N - JNZ r1c4 - -r1c2: - TESTQ $2, N_DIM - JZ r1c1 - - // 1x2 KERNEL - KERNEL_LOAD2 - KERNEL_1x2 - STORE_1x2 - - ADDQ $2*SIZE, Y_PTR - -r1c1: - TESTQ $1, N_DIM - JZ end - - // 1x1 KERNEL - KERNEL_1x1 - STORE_1x1 - - ADDQ $SIZE, Y_PTR - -end: - RET - -inc: // Algorithm for incY != 1 ( split loads in kernel ) - - MOVQ incY+80(FP), INC_Y // INC_Y = incY * sizeof(float64) - SHLQ $3, INC_Y - LEAQ (INC_Y)(INC_Y*2), INC3_Y // INC3_Y = INC_Y * 3 - - XORQ TMP2, TMP2 - MOVQ N, TMP1 - SUBQ $1, TMP1 - IMULQ INC_Y, TMP1 - NEGQ TMP1 - CMPQ INC_Y, $0 - CMOVQLT TMP1, TMP2 - LEAQ (Y_PTR)(TMP2*SIZE), Y_PTR - - SHRQ $2, M - JZ inc_r2 - -inc_r4: - // LOAD 4 - LOAD4 - - MOVQ N_DIM, N - SHRQ $2, N - JZ inc_r4c2 - -inc_r4c4: - // 4x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_4x4 - STORE_4x4 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ N - JNZ inc_r4c4 - - // Reload ALPHA after it's clobbered by STORE_4x4 - MOVDDUP alpha+16(FP), ALPHA - -inc_r4c2: - TESTQ $2, N_DIM - JZ inc_r4c1 - - // 4x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_4x2 - STORE_4x2 - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_r4c1: - TESTQ $1, N_DIM - JZ inc_r4end - - // 4x1 KERNEL - KERNEL_4x1 - STORE_4x1 - - ADDQ INC_Y, Y_PTR - -inc_r4end: - LEAQ (X_PTR)(INC_X*4), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*4), A_ROW - MOVQ A_ROW, A_PTR - - DECQ M - JNZ inc_r4 - -inc_r2: - TESTQ $2, M_DIM - JZ inc_r1 - - // LOAD 2 - LOAD2 - - MOVQ N_DIM, N - SHRQ $2, N - JZ inc_r2c2 - -inc_r2c4: - // 2x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_2x4 - STORE_2x4 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ N - JNZ inc_r2c4 - -inc_r2c2: - TESTQ $2, N_DIM - JZ inc_r2c1 - - // 2x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_2x2 - STORE_2x2 - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_r2c1: - TESTQ $1, N_DIM - JZ inc_r2end - - // 2x1 KERNEL - KERNEL_2x1 - STORE_2x1 - - ADDQ INC_Y, Y_PTR - -inc_r2end: - LEAQ (X_PTR)(INC_X*2), X_PTR - MOVQ Y, Y_PTR - LEAQ (A_ROW)(LDA*2), A_ROW - MOVQ A_ROW, A_PTR - -inc_r1: - TESTQ $1, M_DIM - JZ end - - // LOAD 1 - LOAD1 - - MOVQ N_DIM, N - SHRQ $2, N - JZ inc_r1c2 - -inc_r1c4: - // 1x4 KERNEL - KERNEL_LOAD4_INC - KERNEL_1x4 - STORE_1x4 - - LEAQ (Y_PTR)(INC_Y*4), Y_PTR - DECQ N - JNZ inc_r1c4 - -inc_r1c2: - TESTQ $2, N_DIM - JZ inc_r1c1 - - // 1x2 KERNEL - KERNEL_LOAD2_INC - KERNEL_1x2 - STORE_1x2 - - LEAQ (Y_PTR)(INC_Y*2), Y_PTR - -inc_r1c1: - TESTQ $1, N_DIM - JZ end - - // 1x1 KERNEL - KERNEL_1x1 - STORE_1x1 - - ADDQ INC_Y, Y_PTR - -inc_end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s deleted file mode 100644 index b4b1fd02..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/l1norm_amd64.s +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func L1Dist(s, t []float64) float64 -TEXT ·L1Dist(SB), NOSPLIT, $0 - MOVQ s_base+0(FP), DI // DI = &s - MOVQ t_base+24(FP), SI // SI = &t - MOVQ s_len+8(FP), CX // CX = len(s) - CMPQ t_len+32(FP), CX // CX = max( CX, len(t) ) - CMOVQLE t_len+32(FP), CX - PXOR X3, X3 // norm = 0 - CMPQ CX, $0 // if CX == 0 { return 0 } - JE l1_end - XORQ AX, AX // i = 0 - MOVQ CX, BX - ANDQ $1, BX // BX = CX % 2 - SHRQ $1, CX // CX = floor( CX / 2 ) - JZ l1_tail_start // if CX == 0 { return 0 } - -l1_loop: // Loop unrolled 2x do { - MOVUPS (SI)(AX*8), X0 // X0 = t[i:i+1] - MOVUPS (DI)(AX*8), X1 // X1 = s[i:i+1] - MOVAPS X0, X2 - SUBPD X1, X0 - SUBPD X2, X1 - MAXPD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) - ADDPD X0, X3 // norm += X0 - ADDQ $2, AX // i += 2 - LOOP l1_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE l1_end - -l1_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - PXOR X0, X0 // reset X0, X1 to break dependencies - PXOR X1, X1 - -l1_tail: - MOVSD (SI)(AX*8), X0 // X0 = t[i] - MOVSD (DI)(AX*8), X1 // x1 = s[i] - MOVAPD X0, X2 - SUBSD X1, X0 - SUBSD X2, X1 - MAXSD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) - ADDSD X0, X3 // norm += X0 - -l1_end: - MOVAPS X3, X2 - SHUFPD $1, X2, X2 - ADDSD X3, X2 // X2 = X3[1] + X3[0] - MOVSD X2, ret+48(FP) // return X2 - RET - diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_amd64.s deleted file mode 100644 index 86e01c87..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_amd64.s +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright ©2019 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SUMSQ X0 -#define ABSX X1 -#define SCALE X2 -#define ZERO X3 -#define TMP X4 -#define ABSMASK X5 -#define INF X7 -#define INFMASK X11 -#define NANMASK X12 -#define IDX AX -#define LEN SI -#define X_ DI - -#define ABSMASK_DATA l2nrodata<>+0(SB) -#define INF_DATA l2nrodata<>+8(SB) -#define NAN_DATA l2nrodata<>+16(SB) -// AbsMask -DATA l2nrodata<>+0(SB)/8, $0x7FFFFFFFFFFFFFFF -// Inf -DATA l2nrodata<>+8(SB)/8, $0x7FF0000000000000 -// NaN -DATA l2nrodata<>+16(SB)/8, $0xFFF8000000000000 -GLOBL l2nrodata<>+0(SB), RODATA, $24 - -// L2NormUnitary returns the L2-norm of x. -// func L2NormUnitary(x []float64) (norm float64) -TEXT ·L2NormUnitary(SB), NOSPLIT, $0 - MOVQ x_len+8(FP), LEN // LEN = len(x) - MOVQ x_base+0(FP), X_ - PXOR ZERO, ZERO - CMPQ LEN, $0 // if LEN == 0 { return 0 } - JZ retZero - - PXOR INFMASK, INFMASK - PXOR NANMASK, NANMASK - MOVSD $1.0, SUMSQ // ssq = 1 - XORPS SCALE, SCALE - MOVSD ABSMASK_DATA, ABSMASK - MOVSD INF_DATA, INF - XORQ IDX, IDX // idx == 0 - -initZero: // for ;x[i]==0; i++ {} - // Skip all leading zeros, to avoid divide by zero NaN - MOVSD (X_)(IDX*8), ABSX // absxi = x[i] - UCOMISD ABSX, ZERO - JP retNaN // if isNaN(x[i]) { return NaN } - JNE loop // if x[i] != 0 { goto loop } - INCQ IDX // i++ - CMPQ IDX, LEN - JE retZero // if i == LEN { return 0 } - JMP initZero - -loop: - MOVSD (X_)(IDX*8), ABSX // absxi = x[i] - MOVUPS ABSX, TMP - CMPSD ABSX, TMP, $3 - ORPD TMP, NANMASK // NANMASK = NANMASK | IsNaN(absxi) - MOVSD INF, TMP - ANDPD ABSMASK, ABSX // absxi == Abs(absxi) - CMPSD ABSX, TMP, $0 - ORPD TMP, INFMASK // INFMASK = INFMASK | IsInf(absxi) - UCOMISD SCALE, ABSX - JA adjScale // IF SCALE > ABSXI { goto adjScale } - - DIVSD SCALE, ABSX // absxi = scale / absxi - MULSD ABSX, ABSX // absxi *= absxi - ADDSD ABSX, SUMSQ // sumsq += absxi - INCQ IDX // i++ - CMPQ IDX, LEN - JNE loop // if i < LEN { continue } - JMP retSum // if i == LEN { goto retSum } - -adjScale: // Scale > Absxi - DIVSD ABSX, SCALE // tmp = absxi / scale - MULSD SCALE, SUMSQ // sumsq *= tmp - MULSD SCALE, SUMSQ // sumsq *= tmp - ADDSD $1.0, SUMSQ // sumsq += 1 - MOVUPS ABSX, SCALE // scale = absxi - INCQ IDX // i++ - CMPQ IDX, LEN - JNE loop // if i < LEN { continue } - -retSum: // Calculate return value - SQRTSD SUMSQ, SUMSQ // sumsq = sqrt(sumsq) - MULSD SCALE, SUMSQ // sumsq += scale - MOVQ SUMSQ, R10 // tmp = sumsq - UCOMISD ZERO, INFMASK - CMOVQPS INF_DATA, R10 // if INFMASK { tmp = INF } - UCOMISD ZERO, NANMASK - CMOVQPS NAN_DATA, R10 // if NANMASK { tmp = NaN } - MOVQ R10, norm+24(FP) // return tmp - RET - -retZero: - MOVSD ZERO, norm+24(FP) // return 0 - RET - -retNaN: - MOVSD NAN_DATA, TMP // return NaN - MOVSD TMP, norm+24(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_noasm.go deleted file mode 100644 index bfb8fba9..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norm_noasm.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright ©2019 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f64 - -import "math" - -// L2NormUnitary returns the L2-norm of x. -func L2NormUnitary(x []float64) (norm float64) { - var scale float64 - sumSquares := 1.0 - for _, v := range x { - if v == 0 { - continue - } - absxi := math.Abs(v) - if math.IsNaN(absxi) { - return math.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(sumSquares) -} - -// L2NormInc returns the L2-norm of x. -func L2NormInc(x []float64, n, incX uintptr) (norm float64) { - var scale float64 - sumSquares := 1.0 - for ix := uintptr(0); ix < n*incX; ix += incX { - val := x[ix] - if val == 0 { - continue - } - absxi := math.Abs(val) - if math.IsNaN(absxi) { - return math.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(sumSquares) -} - -// L2DistanceUnitary returns the L2-norm of x-y. -func L2DistanceUnitary(x, y []float64) (norm float64) { - var scale float64 - sumSquares := 1.0 - for i, v := range x { - v -= y[i] - if v == 0 { - continue - } - absxi := math.Abs(v) - if math.IsNaN(absxi) { - return math.NaN() - } - if scale < absxi { - s := scale / absxi - sumSquares = 1 + sumSquares*s*s - scale = absxi - } else { - s := absxi / scale - sumSquares += s * s - } - } - if math.IsInf(scale, 1) { - return math.Inf(1) - } - return scale * math.Sqrt(sumSquares) -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2normdist_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/l2normdist_amd64.s deleted file mode 100644 index 10dcae40..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2normdist_amd64.s +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright ©2019 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SUMSQ X0 -#define ABSX X1 -#define SCALE X2 -#define ZERO X3 -#define TMP X4 -#define ABSMASK X5 -#define INF X7 -#define INFMASK X11 -#define NANMASK X12 -#define IDX AX -#define X_ DI -#define Y_ BX -#define LEN SI - -#define ABSMASK_DATA l2nrodata<>+0(SB) -#define INF_DATA l2nrodata<>+8(SB) -#define NAN_DATA l2nrodata<>+16(SB) -// AbsMask -DATA l2nrodata<>+0(SB)/8, $0x7FFFFFFFFFFFFFFF -// Inf -DATA l2nrodata<>+8(SB)/8, $0x7FF0000000000000 -// NaN -DATA l2nrodata<>+16(SB)/8, $0xFFF8000000000000 -GLOBL l2nrodata<>+0(SB), RODATA, $24 - -// L2DistanceUnitary returns the L2-norm of x-y. -// func L2DistanceUnitary(x,y []float64) (norm float64) -TEXT ·L2DistanceUnitary(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_ - MOVQ y_base+24(FP), Y_ - PXOR ZERO, ZERO - MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) - CMPQ y_len+32(FP), LEN - CMOVQLE y_len+32(FP), LEN - CMPQ LEN, $0 // if LEN == 0 { return 0 } - JZ retZero - - PXOR INFMASK, INFMASK - PXOR NANMASK, NANMASK - MOVSD $1.0, SUMSQ // ssq = 1 - XORPS SCALE, SCALE - MOVSD ABSMASK_DATA, ABSMASK - MOVSD INF_DATA, INF - XORQ IDX, IDX // idx == 0 - -initZero: // for ;x[i]==0; i++ {} - // Skip all leading zeros, to avoid divide by zero NaN - MOVSD (X_)(IDX*8), ABSX // absxi = x[i] - SUBSD (Y_)(IDX*8), ABSX // absxi = x[i]-y[i] - UCOMISD ABSX, ZERO - JP retNaN // if isNaN(absxi) { return NaN } - JNE loop // if absxi != 0 { goto loop } - INCQ IDX // i++ - CMPQ IDX, LEN - JE retZero // if i == LEN { return 0 } - JMP initZero - -loop: - MOVSD (X_)(IDX*8), ABSX // absxi = x[i] - SUBSD (Y_)(IDX*8), ABSX // absxi = x[i]-y[i] - MOVUPS ABSX, TMP - CMPSD ABSX, TMP, $3 - ORPD TMP, NANMASK // NANMASK = NANMASK | IsNaN(absxi) - MOVSD INF, TMP - ANDPD ABSMASK, ABSX // absxi == Abs(absxi) - CMPSD ABSX, TMP, $0 - ORPD TMP, INFMASK // INFMASK = INFMASK | IsInf(absxi) - UCOMISD SCALE, ABSX - JA adjScale // IF SCALE > ABSXI { goto adjScale } - - DIVSD SCALE, ABSX // absxi = scale / absxi - MULSD ABSX, ABSX // absxi *= absxi - ADDSD ABSX, SUMSQ // sumsq += absxi - INCQ IDX // i++ - CMPQ IDX, LEN - JNE loop // if i < LEN { continue } - JMP retSum // if i == LEN { goto retSum } - -adjScale: // Scale > Absxi - DIVSD ABSX, SCALE // tmp = absxi / scale - MULSD SCALE, SUMSQ // sumsq *= tmp - MULSD SCALE, SUMSQ // sumsq *= tmp - ADDSD $1.0, SUMSQ // sumsq += 1 - MOVUPS ABSX, SCALE // scale = absxi - INCQ IDX // i++ - CMPQ IDX, LEN - JNE loop // if i < LEN { continue } - -retSum: // Calculate return value - SQRTSD SUMSQ, SUMSQ // sumsq = sqrt(sumsq) - MULSD SCALE, SUMSQ // sumsq += scale - MOVQ SUMSQ, R10 // tmp = sumsq - UCOMISD ZERO, INFMASK - CMOVQPS INF_DATA, R10 // if INFMASK { tmp = INF } - UCOMISD ZERO, NANMASK - CMOVQPS NAN_DATA, R10 // if NANMASK { tmp = NaN } - MOVQ R10, norm+48(FP) // return tmp - RET - -retZero: - MOVSD ZERO, norm+48(FP) // return 0 - RET - -retNaN: - MOVSD NAN_DATA, TMP // return NaN - MOVSD TMP, norm+48(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norminc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norminc_amd64.s deleted file mode 100644 index 8341db93..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/l2norminc_amd64.s +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright ©2019 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define SUMSQ X0 -#define ABSX X1 -#define SCALE X2 -#define ZERO X3 -#define TMP X4 -#define ABSMASK X5 -#define INF X7 -#define INFMASK X11 -#define NANMASK X12 -#define IDX AX -#define LEN SI -#define INC BX -#define X_ DI - -#define ABSMASK_DATA l2nrodata<>+0(SB) -#define INF_DATA l2nrodata<>+8(SB) -#define NAN_DATA l2nrodata<>+16(SB) -// AbsMask -DATA l2nrodata<>+0(SB)/8, $0x7FFFFFFFFFFFFFFF -// Inf -DATA l2nrodata<>+8(SB)/8, $0x7FF0000000000000 -// NaN -DATA l2nrodata<>+16(SB)/8, $0xFFF8000000000000 -GLOBL l2nrodata<>+0(SB), RODATA, $24 - -// func L2NormInc(x []float64, n, incX uintptr) (norm float64) -TEXT ·L2NormInc(SB), NOSPLIT, $0 - MOVQ n+24(FP), LEN // LEN = len(x) - MOVQ incX+32(FP), INC - MOVQ x_base+0(FP), X_ - XORPS ZERO, ZERO - CMPQ LEN, $0 // if LEN == 0 { return 0 } - JZ retZero - - XORPS INFMASK, INFMASK - XORPS NANMASK, NANMASK - MOVSD $1.0, SUMSQ // ssq = 1 - XORPS SCALE, SCALE - MOVSD ABSMASK_DATA, ABSMASK - MOVSD INF_DATA, INF - SHLQ $3, INC // INC *= sizeof(float64) - -initZero: // for ;x[i]==0; i++ {} - // Skip all leading zeros, to avoid divide by zero NaN - MOVSD (X_), ABSX // absxi = x[i] - UCOMISD ABSX, ZERO - JP retNaN // if isNaN(x[i]) { return NaN } - JNZ loop // if x[i] != 0 { goto loop } - ADDQ INC, X_ // i += INC - DECQ LEN // LEN-- - JZ retZero // if LEN == 0 { return 0 } - JMP initZero - -loop: - MOVSD (X_), ABSX // absxi = x[i] - MOVUPS ABSX, TMP - CMPSD ABSX, TMP, $3 - ORPD TMP, NANMASK // NANMASK = NANMASK | IsNaN(absxi) - MOVSD INF, TMP - ANDPD ABSMASK, ABSX // absxi == Abs(absxi) - CMPSD ABSX, TMP, $0 - ORPD TMP, INFMASK // INFMASK = INFMASK | IsInf(absxi) - UCOMISD SCALE, ABSX - JA adjScale // IF SCALE > ABSXI { goto adjScale } - - DIVSD SCALE, ABSX // absxi = scale / absxi - MULSD ABSX, ABSX // absxi *= absxi - ADDSD ABSX, SUMSQ // sumsq += absxi - ADDQ INC, X_ // i += INC - DECQ LEN // LEN-- - JNZ loop // if LEN > 0 { continue } - JMP retSum // if LEN == 0 { goto retSum } - -adjScale: // Scale > Absxi - DIVSD ABSX, SCALE // tmp = absxi / scale - MULSD SCALE, SUMSQ // sumsq *= tmp - MULSD SCALE, SUMSQ // sumsq *= tmp - ADDSD $1.0, SUMSQ // sumsq += 1 - MOVUPS ABSX, SCALE // scale = absxi - ADDQ INC, X_ // i += INC - DECQ LEN // LEN-- - JNZ loop // if LEN > 0 { continue } - -retSum: // Calculate return value - SQRTSD SUMSQ, SUMSQ // sumsq = sqrt(sumsq) - MULSD SCALE, SUMSQ // sumsq += scale - MOVQ SUMSQ, R10 // tmp = sumsq - UCOMISD ZERO, INFMASK - CMOVQPS INF_DATA, R10 // if INFMASK { tmp = INF } - UCOMISD ZERO, NANMASK - CMOVQPS NAN_DATA, R10 // if NANMASK { tmp = NaN } - MOVQ R10, norm+40(FP) // return tmp - RET - -retZero: - MOVSD ZERO, norm+40(FP) // return 0 - RET - -retNaN: - MOVSD NAN_DATA, TMP // return NaN - MOVSD TMP, norm+40(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s deleted file mode 100644 index ac18b481..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/linfnorm_amd64.s +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func LinfDist(s, t []float64) float64 -TEXT ·LinfDist(SB), NOSPLIT, $0 - MOVQ s_base+0(FP), DI // DI = &s - MOVQ t_base+24(FP), SI // SI = &t - MOVQ s_len+8(FP), CX // CX = len(s) - CMPQ t_len+32(FP), CX // CX = max( CX, len(t) ) - CMOVQLE t_len+32(FP), CX - PXOR X3, X3 // norm = 0 - CMPQ CX, $0 // if CX == 0 { return 0 } - JE l1_end - XORQ AX, AX // i = 0 - MOVQ CX, BX - ANDQ $1, BX // BX = CX % 2 - SHRQ $1, CX // CX = floor( CX / 2 ) - JZ l1_tail_start // if CX == 0 { return 0 } - -l1_loop: // Loop unrolled 2x do { - MOVUPS (SI)(AX*8), X0 // X0 = t[i:i+1] - MOVUPS (DI)(AX*8), X1 // X1 = s[i:i+1] - MOVAPS X0, X2 - SUBPD X1, X0 - SUBPD X2, X1 - MAXPD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) - MAXPD X0, X3 // norm = max( norm, X0 ) - ADDQ $2, AX // i += 2 - LOOP l1_loop // } while --CX > 0 - CMPQ BX, $0 // if BX == 0 { return } - JE l1_end - -l1_tail_start: // Reset loop registers - MOVQ BX, CX // Loop counter: CX = BX - PXOR X0, X0 // reset X0, X1 to break dependencies - PXOR X1, X1 - -l1_tail: - MOVSD (SI)(AX*8), X0 // X0 = t[i] - MOVSD (DI)(AX*8), X1 // X1 = s[i] - MOVAPD X0, X2 - SUBSD X1, X0 - SUBSD X2, X1 - MAXSD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) - MAXSD X0, X3 // norm = max( norm, X0 ) - -l1_end: - MOVAPS X3, X2 - SHUFPD $1, X2, X2 - MAXSD X3, X2 // X2 = max( X3[1], X3[0] ) - MOVSD X2, ret+48(FP) // return X2 - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go deleted file mode 100644 index c95219e1..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/scal.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright ©2016 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f64 - -// ScalUnitary is -// -// for i := range x { -// x[i] *= alpha -// } -func ScalUnitary(alpha float64, x []float64) { - for i := range x { - x[i] *= alpha - } -} - -// ScalUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha * v -// } -func ScalUnitaryTo(dst []float64, alpha float64, x []float64) { - for i, v := range x { - dst[i] = alpha * v - } -} - -// ScalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] *= alpha -// ix += incX -// } -func ScalInc(alpha float64, x []float64, n, incX uintptr) { - var ix uintptr - for i := 0; i < int(n); i++ { - x[ix] *= alpha - ix += incX - } -} - -// ScalIncTo is -// -// var idst, ix uintptr -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha * x[ix] -// ix += incX -// idst += incDst -// } -func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) { - var idst, ix uintptr - for i := 0; i < int(n); i++ { - dst[idst] = alpha * x[ix] - ix += incX - idst += incDst - } -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s deleted file mode 100644 index d623a284..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalinc_amd64.s +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define LEN CX -#define TAIL BX -#define INC_X R8 -#define INCx3_X R9 -#define ALPHA X0 -#define ALPHA_2 X1 - -// func ScalInc(alpha float64, x []float64, n, incX uintptr) -TEXT ·ScalInc(SB), NOSPLIT, $0 - MOVSD alpha+0(FP), ALPHA // ALPHA = alpha - MOVQ x_base+8(FP), X_PTR // X_PTR = &x - MOVQ incX+40(FP), INC_X // INC_X = incX - SHLQ $3, INC_X // INC_X *= sizeof(float64) - MOVQ n+32(FP), LEN // LEN = n - CMPQ LEN, $0 - JE end // if LEN == 0 { return } - - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = LEN % 4 - SHRQ $2, LEN // LEN = floor( LEN / 4 ) - JZ tail_start // if LEN == 0 { goto tail_start } - - MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - -loop: // do { // x[i] *= alpha unrolled 4x. - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MOVSD (X_PTR)(INC_X*2), X4 - MOVSD (X_PTR)(INCx3_X*1), X5 - - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA_2, X3 - MULSD ALPHA, X4 - MULSD ALPHA_2, X5 - - MOVSD X2, (X_PTR) // x[i] = X_i - MOVSD X3, (X_PTR)(INC_X*1) - MOVSD X4, (X_PTR)(INC_X*2) - MOVSD X5, (X_PTR)(INCx3_X*1) - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) - DECQ LEN - JNZ loop // } while --LEN > 0 - CMPQ TAIL, $0 - JE end // if TAIL == 0 { return } - -tail_start: // Reset loop registers - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( LEN / 2 ) - JZ tail_one - -tail_two: // do { - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA, X3 - MOVSD X2, (X_PTR) // x[i] = X_i - MOVSD X3, (X_PTR)(INC_X*1) - - LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) - - ANDQ $1, TAIL - JZ end - -tail_one: - MOVSD (X_PTR), X2 // X_i = x[i] - MULSD ALPHA, X2 // X_i *= ALPHA - MOVSD X2, (X_PTR) // x[i] = X_i - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s deleted file mode 100644 index 1c272209..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalincto_amd64.s +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define DST_PTR DI -#define LEN CX -#define TAIL BX -#define INC_X R8 -#define INCx3_X R9 -#define INC_DST R10 -#define INCx3_DST R11 -#define ALPHA X0 -#define ALPHA_2 X1 - -// func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) -TEXT ·ScalIncTo(SB), NOSPLIT, $0 - MOVQ dst_base+0(FP), DST_PTR // DST_PTR = &dst - MOVQ incDst+24(FP), INC_DST // INC_DST = incDst - SHLQ $3, INC_DST // INC_DST *= sizeof(float64) - MOVSD alpha+32(FP), ALPHA // ALPHA = alpha - MOVQ x_base+40(FP), X_PTR // X_PTR = &x - MOVQ n+64(FP), LEN // LEN = n - MOVQ incX+72(FP), INC_X // INC_X = incX - SHLQ $3, INC_X // INC_X *= sizeof(float64) - CMPQ LEN, $0 - JE end // if LEN == 0 { return } - - MOVQ LEN, TAIL - ANDQ $3, TAIL // TAIL = LEN % 4 - SHRQ $2, LEN // LEN = floor( LEN / 4 ) - JZ tail_start // if LEN == 0 { goto tail_start } - - MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining - LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 - LEAQ (INC_DST)(INC_DST*2), INCx3_DST // INCx3_DST = INC_DST * 3 - -loop: // do { // x[i] *= alpha unrolled 4x. - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MOVSD (X_PTR)(INC_X*2), X4 - MOVSD (X_PTR)(INCx3_X*1), X5 - - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA_2, X3 - MULSD ALPHA, X4 - MULSD ALPHA_2, X5 - - MOVSD X2, (DST_PTR) // dst[i] = X_i - MOVSD X3, (DST_PTR)(INC_DST*1) - MOVSD X4, (DST_PTR)(INC_DST*2) - MOVSD X5, (DST_PTR)(INCx3_DST*1) - - LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) - LEAQ (DST_PTR)(INC_DST*4), DST_PTR // DST_PTR = &(DST_PTR[incDst*4]) - DECQ LEN - JNZ loop // } while --LEN > 0 - CMPQ TAIL, $0 - JE end // if TAIL == 0 { return } - -tail_start: // Reset loop registers - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( LEN / 2 ) - JZ tail_one - -tail_two: - MOVSD (X_PTR), X2 // X_i = x[i] - MOVSD (X_PTR)(INC_X*1), X3 - MULSD ALPHA, X2 // X_i *= a - MULSD ALPHA, X3 - MOVSD X2, (DST_PTR) // dst[i] = X_i - MOVSD X3, (DST_PTR)(INC_DST*1) - - LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) - LEAQ (DST_PTR)(INC_DST*2), DST_PTR // DST_PTR = &(DST_PTR[incDst*2]) - - ANDQ $1, TAIL - JZ end - -tail_one: - MOVSD (X_PTR), X2 // X_i = x[i] - MULSD ALPHA, X2 // X_i *= ALPHA - MOVSD X2, (DST_PTR) // x[i] = X_i - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s deleted file mode 100644 index 6e8f5ca6..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitary_amd64.s +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x0824 // @ MOVDDUP XMM0, 8[RSP] - -#define X_PTR SI -#define DST_PTR DI -#define IDX AX -#define LEN CX -#define TAIL BX -#define ALPHA X0 -#define ALPHA_2 X1 - -// func ScalUnitary(alpha float64, x []float64) -TEXT ·ScalUnitary(SB), NOSPLIT, $0 - MOVDDUP_ALPHA // ALPHA = { alpha, alpha } - MOVQ x_base+8(FP), X_PTR // X_PTR = &x - MOVQ x_len+16(FP), LEN // LEN = len(x) - CMPQ LEN, $0 - JE end // if LEN == 0 { return } - XORQ IDX, IDX // IDX = 0 - - MOVQ LEN, TAIL - ANDQ $7, TAIL // TAIL = LEN % 8 - SHRQ $3, LEN // LEN = floor( LEN / 8 ) - JZ tail_start // if LEN == 0 { goto tail_start } - - MOVUPS ALPHA, ALPHA_2 - -loop: // do { // x[i] *= alpha unrolled 8x. - MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] - MOVUPS 16(X_PTR)(IDX*8), X3 - MOVUPS 32(X_PTR)(IDX*8), X4 - MOVUPS 48(X_PTR)(IDX*8), X5 - - MULPD ALPHA, X2 // X_i *= ALPHA - MULPD ALPHA_2, X3 - MULPD ALPHA, X4 - MULPD ALPHA_2, X5 - - MOVUPS X2, (X_PTR)(IDX*8) // x[i] = X_i - MOVUPS X3, 16(X_PTR)(IDX*8) - MOVUPS X4, 32(X_PTR)(IDX*8) - MOVUPS X5, 48(X_PTR)(IDX*8) - - ADDQ $8, IDX // i += 8 - DECQ LEN - JNZ loop // while --LEN > 0 - CMPQ TAIL, $0 - JE end // if TAIL == 0 { return } - -tail_start: // Reset loop registers - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( TAIL / 2 ) - JZ tail_one // if n == 0 goto end - -tail_two: // do { - MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] - MULPD ALPHA, X2 // X_i *= ALPHA - MOVUPS X2, (X_PTR)(IDX*8) // x[i] = X_i - ADDQ $2, IDX // i += 2 - DECQ LEN - JNZ tail_two // while --LEN > 0 - - ANDQ $1, TAIL - JZ end // if TAIL == 0 { return } - -tail_one: - // x[i] *= alpha for the remaining element. - MOVSD (X_PTR)(IDX*8), X2 - MULSD ALPHA, X2 - MOVSD X2, (X_PTR)(IDX*8) - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s deleted file mode 100644 index 986480a5..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/scalunitaryto_amd64.s +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// -// Some of the loop unrolling code is copied from: -// http://golang.org/src/math/big/arith_amd64.s -// which is distributed under these terms: -// -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x2024 // @ MOVDDUP 32(SP), X0 /*XMM0, 32[RSP]*/ - -#define X_PTR SI -#define DST_PTR DI -#define IDX AX -#define LEN CX -#define TAIL BX -#define ALPHA X0 -#define ALPHA_2 X1 - -// func ScalUnitaryTo(dst []float64, alpha float64, x []float64) -// This function assumes len(dst) >= len(x). -TEXT ·ScalUnitaryTo(SB), NOSPLIT, $0 - MOVQ x_base+32(FP), X_PTR // X_PTR = &x - MOVQ dst_base+0(FP), DST_PTR // DST_PTR = &dst - MOVDDUP_ALPHA // ALPHA = { alpha, alpha } - MOVQ x_len+40(FP), LEN // LEN = len(x) - CMPQ LEN, $0 - JE end // if LEN == 0 { return } - - XORQ IDX, IDX // IDX = 0 - MOVQ LEN, TAIL - ANDQ $7, TAIL // TAIL = LEN % 8 - SHRQ $3, LEN // LEN = floor( LEN / 8 ) - JZ tail_start // if LEN == 0 { goto tail_start } - - MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining - -loop: // do { // dst[i] = alpha * x[i] unrolled 8x. - MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] - MOVUPS 16(X_PTR)(IDX*8), X3 - MOVUPS 32(X_PTR)(IDX*8), X4 - MOVUPS 48(X_PTR)(IDX*8), X5 - - MULPD ALPHA, X2 // X_i *= ALPHA - MULPD ALPHA_2, X3 - MULPD ALPHA, X4 - MULPD ALPHA_2, X5 - - MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i - MOVUPS X3, 16(DST_PTR)(IDX*8) - MOVUPS X4, 32(DST_PTR)(IDX*8) - MOVUPS X5, 48(DST_PTR)(IDX*8) - - ADDQ $8, IDX // i += 8 - DECQ LEN - JNZ loop // while --LEN > 0 - CMPQ TAIL, $0 - JE end // if TAIL == 0 { return } - -tail_start: // Reset loop counters - MOVQ TAIL, LEN // Loop counter: LEN = TAIL - SHRQ $1, LEN // LEN = floor( TAIL / 2 ) - JZ tail_one // if LEN == 0 { goto tail_one } - -tail_two: // do { - MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] - MULPD ALPHA, X2 // X_i *= ALPHA - MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i - ADDQ $2, IDX // i += 2 - DECQ LEN - JNZ tail_two // while --LEN > 0 - - ANDQ $1, TAIL - JZ end // if TAIL == 0 { return } - -tail_one: - MOVSD (X_PTR)(IDX*8), X2 // X_i = x[i] - MULSD ALPHA, X2 // X_i *= ALPHA - MOVSD X2, (DST_PTR)(IDX*8) // dst[i] = X_i - -end: - RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go deleted file mode 100644 index 7139bedd..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright ©2015 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package f64 - -// L1Norm is -// -// for _, v := range x { -// sum += math.Abs(v) -// } -// return sum -func L1Norm(x []float64) (sum float64) - -// L1NormInc is -// -// for i := 0; i < n*incX; i += incX { -// sum += math.Abs(x[i]) -// } -// return sum -func L1NormInc(x []float64, n, incX int) (sum float64) - -// AddConst is -// -// for i := range x { -// x[i] += alpha -// } -func AddConst(alpha float64, x []float64) - -// Add is -// -// for i, v := range s { -// dst[i] += v -// } -func Add(dst, s []float64) - -// AxpyUnitary is -// -// for i, v := range x { -// y[i] += alpha * v -// } -func AxpyUnitary(alpha float64, x, y []float64) - -// AxpyUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha*v + y[i] -// } -func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) - -// AxpyInc is -// -// for i := 0; i < int(n); i++ { -// y[iy] += alpha * x[ix] -// ix += incX -// iy += incY -// } -func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) - -// AxpyIncTo is -// -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha*x[ix] + y[iy] -// ix += incX -// iy += incY -// idst += incDst -// } -func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) - -// CumSum is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] + v -// } -// return dst -func CumSum(dst, s []float64) []float64 - -// CumProd is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] * v -// } -// return dst -func CumProd(dst, s []float64) []float64 - -// Div is -// -// for i, v := range s { -// dst[i] /= v -// } -func Div(dst, s []float64) - -// DivTo is -// -// for i, v := range s { -// dst[i] = v / t[i] -// } -// return dst -func DivTo(dst, x, y []float64) []float64 - -// DotUnitary is -// -// for i, v := range x { -// sum += y[i] * v -// } -// return sum -func DotUnitary(x, y []float64) (sum float64) - -// DotInc is -// -// for i := 0; i < int(n); i++ { -// sum += y[iy] * x[ix] -// ix += incX -// iy += incY -// } -// return sum -func DotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) - -// L1Dist is -// -// var norm float64 -// for i, v := range s { -// norm += math.Abs(t[i] - v) -// } -// return norm -func L1Dist(s, t []float64) float64 - -// LinfDist is -// -// var norm float64 -// if len(s) == 0 { -// return 0 -// } -// norm = math.Abs(t[0] - s[0]) -// for i, v := range s[1:] { -// absDiff := math.Abs(t[i+1] - v) -// if absDiff > norm || math.IsNaN(norm) { -// norm = absDiff -// } -// } -// return norm -func LinfDist(s, t []float64) float64 - -// ScalUnitary is -// -// for i := range x { -// x[i] *= alpha -// } -func ScalUnitary(alpha float64, x []float64) - -// ScalUnitaryTo is -// -// for i, v := range x { -// dst[i] = alpha * v -// } -func ScalUnitaryTo(dst []float64, alpha float64, x []float64) - -// ScalInc is -// -// var ix uintptr -// for i := 0; i < int(n); i++ { -// x[ix] *= alpha -// ix += incX -// } -func ScalInc(alpha float64, x []float64, n, incX uintptr) - -// ScalIncTo is -// -// var idst, ix uintptr -// for i := 0; i < int(n); i++ { -// dst[idst] = alpha * x[ix] -// ix += incX -// idst += incDst -// } -func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) - -// Sum is -// -// var sum float64 -// for i := range x { -// sum += x[i] -// } -func Sum(x []float64) float64 - -// L2NormUnitary returns the L2-norm of x. -// -// var scale float64 -// sumSquares := 1.0 -// for _, v := range x { -// if v == 0 { -// continue -// } -// absxi := math.Abs(v) -// if math.IsNaN(absxi) { -// return math.NaN() -// } -// if scale < absxi { -// s := scale / absxi -// sumSquares = 1 + sumSquares*s*s -// scale = absxi -// } else { -// s := absxi / scale -// sumSquares += s * s -// } -// if math.IsInf(scale, 1) { -// return math.Inf(1) -// } -// } -// return scale * math.Sqrt(sumSquares) -func L2NormUnitary(x []float64) (norm float64) - -// L2NormInc returns the L2-norm of x. -// -// var scale float64 -// sumSquares := 1.0 -// for ix := uintptr(0); ix < n*incX; ix += incX { -// val := x[ix] -// if val == 0 { -// continue -// } -// absxi := math.Abs(val) -// if math.IsNaN(absxi) { -// return math.NaN() -// } -// if scale < absxi { -// s := scale / absxi -// sumSquares = 1 + sumSquares*s*s -// scale = absxi -// } else { -// s := absxi / scale -// sumSquares += s * s -// } -// } -// if math.IsInf(scale, 1) { -// return math.Inf(1) -// } -// return scale * math.Sqrt(sumSquares) -func L2NormInc(x []float64, n, incX uintptr) (norm float64) - -// L2DistanceUnitary returns the L2-norm of x-y. -// -// var scale float64 -// sumSquares := 1.0 -// for i, v := range x { -// v -= y[i] -// if v == 0 { -// continue -// } -// absxi := math.Abs(v) -// if math.IsNaN(absxi) { -// return math.NaN() -// } -// if scale < absxi { -// s := scale / absxi -// sumSquares = 1 + sumSquares*s*s -// scale = absxi -// } else { -// s := absxi / scale -// sumSquares += s * s -// } -// } -// if math.IsInf(scale, 1) { -// return math.Inf(1) -// } -// return scale * math.Sqrt(sumSquares) -func L2DistanceUnitary(x, y []float64) (norm float64) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go deleted file mode 100644 index f0663791..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright ©2016 The Gonum 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 !amd64 || noasm || gccgo || safe -// +build !amd64 noasm gccgo safe - -package f64 - -import "math" - -// L1Norm is -// -// for _, v := range x { -// sum += math.Abs(v) -// } -// return sum -func L1Norm(x []float64) (sum float64) { - for _, v := range x { - sum += math.Abs(v) - } - return sum -} - -// L1NormInc is -// -// for i := 0; i < n*incX; i += incX { -// sum += math.Abs(x[i]) -// } -// return sum -func L1NormInc(x []float64, n, incX int) (sum float64) { - for i := 0; i < n*incX; i += incX { - sum += math.Abs(x[i]) - } - return sum -} - -// Add is -// -// for i, v := range s { -// dst[i] += v -// } -func Add(dst, s []float64) { - for i, v := range s { - dst[i] += v - } -} - -// AddConst is -// -// for i := range x { -// x[i] += alpha -// } -func AddConst(alpha float64, x []float64) { - for i := range x { - x[i] += alpha - } -} - -// CumSum is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] + v -// } -// return dst -func CumSum(dst, s []float64) []float64 { - if len(s) == 0 { - return dst - } - dst[0] = s[0] - for i, v := range s[1:] { - dst[i+1] = dst[i] + v - } - return dst -} - -// CumProd is -// -// if len(s) == 0 { -// return dst -// } -// dst[0] = s[0] -// for i, v := range s[1:] { -// dst[i+1] = dst[i] * v -// } -// return dst -func CumProd(dst, s []float64) []float64 { - if len(s) == 0 { - return dst - } - dst[0] = s[0] - for i, v := range s[1:] { - dst[i+1] = dst[i] * v - } - return dst -} - -// Div is -// -// for i, v := range s { -// dst[i] /= v -// } -func Div(dst, s []float64) { - for i, v := range s { - dst[i] /= v - } -} - -// DivTo is -// -// for i, v := range s { -// dst[i] = v / t[i] -// } -// return dst -func DivTo(dst, s, t []float64) []float64 { - for i, v := range s { - dst[i] = v / t[i] - } - return dst -} - -// L1Dist is -// -// var norm float64 -// for i, v := range s { -// norm += math.Abs(t[i] - v) -// } -// return norm -func L1Dist(s, t []float64) float64 { - var norm float64 - for i, v := range s { - norm += math.Abs(t[i] - v) - } - return norm -} - -// LinfDist is -// -// var norm float64 -// if len(s) == 0 { -// return 0 -// } -// norm = math.Abs(t[0] - s[0]) -// for i, v := range s[1:] { -// absDiff := math.Abs(t[i+1] - v) -// if absDiff > norm || math.IsNaN(norm) { -// norm = absDiff -// } -// } -// return norm -func LinfDist(s, t []float64) float64 { - var norm float64 - if len(s) == 0 { - return 0 - } - norm = math.Abs(t[0] - s[0]) - for i, v := range s[1:] { - absDiff := math.Abs(t[i+1] - v) - if absDiff > norm || math.IsNaN(norm) { - norm = absDiff - } - } - return norm -} - -// Sum is -// -// var sum float64 -// for i := range x { -// sum += x[i] -// } -func Sum(x []float64) float64 { - var sum float64 - for _, v := range x { - sum += v - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s deleted file mode 100644 index dd77cbd0..00000000 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright ©2018 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -#define X_PTR SI -#define IDX AX -#define LEN CX -#define TAIL BX -#define SUM X0 -#define SUM_1 X1 -#define SUM_2 X2 -#define SUM_3 X3 - -// func Sum(x []float64) float64 -TEXT ·Sum(SB), NOSPLIT, $0 - MOVQ x_base+0(FP), X_PTR // X_PTR = &x - MOVQ x_len+8(FP), LEN // LEN = len(x) - XORQ IDX, IDX // i = 0 - PXOR SUM, SUM // p_sum_i = 0 - CMPQ LEN, $0 // if LEN == 0 { return 0 } - JE sum_end - - PXOR SUM_1, SUM_1 - PXOR SUM_2, SUM_2 - PXOR SUM_3, SUM_3 - - MOVQ X_PTR, TAIL // Check memory alignment - ANDQ $15, TAIL // TAIL = &y % 16 - JZ no_trim // if TAIL == 0 { goto no_trim } - - // Align on 16-byte boundary - ADDSD (X_PTR), X0 // X0 += x[0] - INCQ IDX // i++ - DECQ LEN // LEN-- - JZ sum_end // if LEN == 0 { return } - -no_trim: - MOVQ LEN, TAIL - SHRQ $4, LEN // LEN = floor( n / 16 ) - JZ sum_tail8 // if LEN == 0 { goto sum_tail8 } - -sum_loop: // sum 16x wide do { - ADDPD (X_PTR)(IDX*8), SUM // sum_i += x[i:i+2] - ADDPD 16(X_PTR)(IDX*8), SUM_1 - ADDPD 32(X_PTR)(IDX*8), SUM_2 - ADDPD 48(X_PTR)(IDX*8), SUM_3 - ADDPD 64(X_PTR)(IDX*8), SUM - ADDPD 80(X_PTR)(IDX*8), SUM_1 - ADDPD 96(X_PTR)(IDX*8), SUM_2 - ADDPD 112(X_PTR)(IDX*8), SUM_3 - ADDQ $16, IDX // i += 16 - DECQ LEN - JNZ sum_loop // } while --LEN > 0 - -sum_tail8: - TESTQ $8, TAIL - JZ sum_tail4 - - ADDPD (X_PTR)(IDX*8), SUM // sum_i += x[i:i+2] - ADDPD 16(X_PTR)(IDX*8), SUM_1 - ADDPD 32(X_PTR)(IDX*8), SUM_2 - ADDPD 48(X_PTR)(IDX*8), SUM_3 - ADDQ $8, IDX - -sum_tail4: - ADDPD SUM_3, SUM - ADDPD SUM_2, SUM_1 - - TESTQ $4, TAIL - JZ sum_tail2 - - ADDPD (X_PTR)(IDX*8), SUM // sum_i += x[i:i+2] - ADDPD 16(X_PTR)(IDX*8), SUM_1 - ADDQ $4, IDX - -sum_tail2: - ADDPD SUM_1, SUM - - TESTQ $2, TAIL - JZ sum_tail1 - - ADDPD (X_PTR)(IDX*8), SUM // sum_i += x[i:i+2] - ADDQ $2, IDX - -sum_tail1: - HADDPD SUM, SUM // sum_i[0] += sum_i[1] - - TESTQ $1, TAIL - JZ sum_end - - ADDSD (X_PTR)(IDX*8), SUM - -sum_end: // return sum - MOVSD SUM, ret+24(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go deleted file mode 100644 index ac6eb81c..00000000 --- a/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2010 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. - -// Copyright ©2017 The Gonum 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 cmplx64 - -import math "gonum.org/v1/gonum/internal/math32" - -// Abs returns the absolute value (also called the modulus) of x. -func Abs(x complex64) float32 { return math.Hypot(real(x), imag(x)) } diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go deleted file mode 100644 index 705262f2..00000000 --- a/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2010 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. - -// Copyright ©2017 The Gonum 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 cmplx64 - -// Conj returns the complex conjugate of x. -func Conj(x complex64) complex64 { return complex(real(x), -imag(x)) } diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go deleted file mode 100644 index 5424ea09..00000000 --- a/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright ©2017 The Gonum 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 cmplx64 provides complex64 versions of standard library math/cmplx -// package routines used by gonum/blas. -package cmplx64 // import "gonum.org/v1/gonum/internal/cmplx64" diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go deleted file mode 100644 index 21d3d180..00000000 --- a/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2010 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. - -// Copyright ©2017 The Gonum 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 cmplx64 - -import math "gonum.org/v1/gonum/internal/math32" - -// IsInf returns true if either real(x) or imag(x) is an infinity. -func IsInf(x complex64) bool { - if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) { - return true - } - return false -} - -// Inf returns a complex infinity, complex(+Inf, +Inf). -func Inf() complex64 { - inf := math.Inf(1) - return complex(inf, inf) -} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go deleted file mode 100644 index d6d43dbd..00000000 --- a/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2010 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. - -// Copyright ©2017 The Gonum 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 cmplx64 - -import math "gonum.org/v1/gonum/internal/math32" - -// IsNaN returns true if either real(x) or imag(x) is NaN -// and neither is an infinity. -func IsNaN(x complex64) bool { - switch { - case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0): - return false - case math.IsNaN(real(x)) || math.IsNaN(imag(x)): - return true - } - return false -} - -// NaN returns a complex “not-a-number” value. -func NaN() complex64 { - nan := math.NaN() - return complex(nan, nan) -} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go deleted file mode 100644 index 439987b4..00000000 --- a/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2010 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. - -// Copyright ©2017 The Gonum 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 cmplx64 - -import math "gonum.org/v1/gonum/internal/math32" - -// The original C code, the long comment, and the constants -// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. -// The go code is a simplified version of the original C. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier -// -// The readme file at http://netlib.sandia.gov/cephes/ says: -// Some software in this archive may be from the book _Methods and -// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster -// International, 1989) or from the Cephes Mathematical Library, a -// commercial product. In either event, it is copyrighted by the author. -// What you see here may be used freely but it comes with no support or -// guarantee. -// -// The two known misprints in the book are repaired here in the -// source listings for the gamma function and the incomplete beta -// integral. -// -// Stephen L. Moshier -// moshier@na-net.ornl.gov - -// Complex square root -// -// DESCRIPTION: -// -// If z = x + iy, r = |z|, then -// -// 1/2 -// Re w = [ (r + x)/2 ] , -// -// 1/2 -// Im w = [ (r - x)/2 ] . -// -// Cancelation error in r-x or r+x is avoided by using the -// identity 2 Re w Im w = y. -// -// Note that -w is also a square root of z. The root chosen -// is always in the right half plane and Im w has the same sign as y. -// -// ACCURACY: -// -// Relative error: -// arithmetic domain # trials peak rms -// DEC -10,+10 25000 3.2e-17 9.6e-18 -// IEEE -10,+10 1,000,000 2.9e-16 6.1e-17 - -// Sqrt returns the square root of x. -// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x). -func Sqrt(x complex64) complex64 { - if imag(x) == 0 { - if real(x) == 0 { - return complex(0, 0) - } - if real(x) < 0 { - return complex(0, math.Sqrt(-real(x))) - } - return complex(math.Sqrt(real(x)), 0) - } - if real(x) == 0 { - if imag(x) < 0 { - r := math.Sqrt(-0.5 * imag(x)) - return complex(r, -r) - } - r := math.Sqrt(0.5 * imag(x)) - return complex(r, r) - } - a := real(x) - b := imag(x) - var scale float32 - // Rescale to avoid internal overflow or underflow. - if math.Abs(a) > 4 || math.Abs(b) > 4 { - a *= 0.25 - b *= 0.25 - scale = 2 - } else { - a *= 1.8014398509481984e16 // 2**54 - b *= 1.8014398509481984e16 - scale = 7.450580596923828125e-9 // 2**-27 - } - r := math.Hypot(a, b) - var t float32 - if a > 0 { - t = math.Sqrt(0.5*r + 0.5*a) - r = scale * math.Abs((0.5*b)/t) - t *= scale - } else { - r = math.Sqrt(0.5*r - 0.5*a) - t = scale * math.Abs((0.5*b)/r) - r *= scale - } - if b < 0 { - return complex(t, -r) - } - return complex(t, r) -} diff --git a/vendor/gonum.org/v1/gonum/internal/math32/doc.go b/vendor/gonum.org/v1/gonum/internal/math32/doc.go deleted file mode 100644 index 68917c64..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright ©2017 The Gonum 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 math32 provides float32 versions of standard library math package -// routines used by gonum/blas/native. -package math32 // import "gonum.org/v1/gonum/internal/math32" diff --git a/vendor/gonum.org/v1/gonum/internal/math32/math.go b/vendor/gonum.org/v1/gonum/internal/math32/math.go deleted file mode 100644 index 5e92f3d0..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/math.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2009 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. - -// Copyright ©2015 The Gonum 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 math32 - -import ( - "math" -) - -const ( - unan = 0x7fc00000 - uinf = 0x7f800000 - uneginf = 0xff800000 - mask = 0x7f8 >> 3 - shift = 32 - 8 - 1 - bias = 127 -) - -// Abs returns the absolute value of x. -// -// Special cases are: -// -// Abs(±Inf) = +Inf -// Abs(NaN) = NaN -func Abs(x float32) float32 { - switch { - case x < 0: - return -x - case x == 0: - return 0 // return correctly abs(-0) - } - return x -} - -// Copysign returns a value with the magnitude -// of x and the sign of y. -func Copysign(x, y float32) float32 { - const sign = 1 << 31 - return math.Float32frombits(math.Float32bits(x)&^sign | math.Float32bits(y)&sign) -} - -// Hypot returns Sqrt(p*p + q*q), taking care to avoid -// unnecessary overflow and underflow. -// -// Special cases are: -// -// Hypot(±Inf, q) = +Inf -// Hypot(p, ±Inf) = +Inf -// Hypot(NaN, q) = NaN -// Hypot(p, NaN) = NaN -func Hypot(p, q float32) float32 { - // special cases - switch { - case IsInf(p, 0) || IsInf(q, 0): - return Inf(1) - case IsNaN(p) || IsNaN(q): - return NaN() - } - if p < 0 { - p = -p - } - if q < 0 { - q = -q - } - if p < q { - p, q = q, p - } - if p == 0 { - return 0 - } - q = q / p - return p * Sqrt(1+q*q) -} - -// Inf returns positive infinity if sign >= 0, negative infinity if sign < 0. -func Inf(sign int) float32 { - var v uint32 - if sign >= 0 { - v = uinf - } else { - v = uneginf - } - return math.Float32frombits(v) -} - -// IsInf reports whether f is an infinity, according to sign. -// If sign > 0, IsInf reports whether f is positive infinity. -// If sign < 0, IsInf reports whether f is negative infinity. -// If sign == 0, IsInf reports whether f is either infinity. -func IsInf(f float32, sign int) bool { - // Test for infinity by comparing against maximum float. - // To avoid the floating-point hardware, could use: - // x := math.Float32bits(f); - // return sign >= 0 && x == uinf || sign <= 0 && x == uneginf; - return sign >= 0 && f > math.MaxFloat32 || sign <= 0 && f < -math.MaxFloat32 -} - -// IsNaN reports whether f is an IEEE 754 “not-a-number” value. -func IsNaN(f float32) (is bool) { - // IEEE 754 says that only NaNs satisfy f != f. - // To avoid the floating-point hardware, could use: - // x := math.Float32bits(f); - // return uint32(x>>shift)&mask == mask && x != uinf && x != uneginf - return f != f -} - -// Max returns the larger of x or y. -// -// Special cases are: -// -// Max(x, +Inf) = Max(+Inf, x) = +Inf -// Max(x, NaN) = Max(NaN, x) = NaN -// Max(+0, ±0) = Max(±0, +0) = +0 -// Max(-0, -0) = -0 -func Max(x, y float32) float32 { - // special cases - switch { - case IsInf(x, 1) || IsInf(y, 1): - return Inf(1) - case IsNaN(x) || IsNaN(y): - return NaN() - case x == 0 && x == y: - if Signbit(x) { - return y - } - return x - } - if x > y { - return x - } - return y -} - -// Min returns the smaller of x or y. -// -// Special cases are: -// -// Min(x, -Inf) = Min(-Inf, x) = -Inf -// Min(x, NaN) = Min(NaN, x) = NaN -// Min(-0, ±0) = Min(±0, -0) = -0 -func Min(x, y float32) float32 { - // special cases - switch { - case IsInf(x, -1) || IsInf(y, -1): - return Inf(-1) - case IsNaN(x) || IsNaN(y): - return NaN() - case x == 0 && x == y: - if Signbit(x) { - return x - } - return y - } - if x < y { - return x - } - return y -} - -// NaN returns an IEEE 754 “not-a-number” value. -func NaN() float32 { return math.Float32frombits(unan) } diff --git a/vendor/gonum.org/v1/gonum/internal/math32/signbit.go b/vendor/gonum.org/v1/gonum/internal/math32/signbit.go deleted file mode 100644 index 3e9f0bb4..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/signbit.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2010 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. - -// Copyright ©2017 The Gonum 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 math32 - -import "math" - -// Signbit returns true if x is negative or negative zero. -func Signbit(x float32) bool { - return math.Float32bits(x)&(1<<31) != 0 -} diff --git a/vendor/gonum.org/v1/gonum/internal/math32/sqrt.go b/vendor/gonum.org/v1/gonum/internal/math32/sqrt.go deleted file mode 100644 index 41f4a134..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/sqrt.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright ©2015 The Gonum 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 (!amd64 && !arm64) || noasm || gccgo || safe -// +build !amd64,!arm64 noasm gccgo safe - -package math32 - -import ( - "math" -) - -// Sqrt returns the square root of x. -// -// Special cases are: -// -// Sqrt(+Inf) = +Inf -// Sqrt(±0) = ±0 -// Sqrt(x < 0) = NaN -// Sqrt(NaN) = NaN -func Sqrt(x float32) float32 { - // FIXME(kortschak): Direct translation of the math package - // asm code for 386 fails to build. - return float32(math.Sqrt(float64(x))) -} diff --git a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.go b/vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.go deleted file mode 100644 index eca83f87..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2009 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. - -// Copyright ©2015 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package math32 - -// Sqrt returns the square root of x. -// -// Special cases are: -// -// Sqrt(+Inf) = +Inf -// Sqrt(±0) = ±0 -// Sqrt(x < 0) = NaN -// Sqrt(NaN) = NaN -func Sqrt(x float32) float32 diff --git a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.s b/vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.s deleted file mode 100644 index 1c1432a3..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_amd64.s +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2009 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. - -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func Sqrt(x float32) float32 -TEXT ·Sqrt(SB),NOSPLIT,$0 - SQRTSS x+0(FP), X0 - MOVSS X0, ret+8(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.go b/vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.go deleted file mode 100644 index eca83f87..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2009 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. - -// Copyright ©2015 The Gonum 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 !noasm && !gccgo && !safe -// +build !noasm,!gccgo,!safe - -package math32 - -// Sqrt returns the square root of x. -// -// Special cases are: -// -// Sqrt(+Inf) = +Inf -// Sqrt(±0) = ±0 -// Sqrt(x < 0) = NaN -// Sqrt(NaN) = NaN -func Sqrt(x float32) float32 diff --git a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.s b/vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.s deleted file mode 100644 index f18b5521..00000000 --- a/vendor/gonum.org/v1/gonum/internal/math32/sqrt_arm64.s +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 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. - -// Copyright ©2020 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !noasm,!gccgo,!safe - -#include "textflag.h" - -// func Sqrt(x float32) float32 -TEXT ·Sqrt(SB),NOSPLIT,$0 - FMOVS x+0(FP), F0 - FSQRTS F0, F0 - FMOVS F0, ret+8(FP) - RET diff --git a/vendor/gonum.org/v1/gonum/lapack/.gitignore b/vendor/gonum.org/v1/gonum/lapack/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/vendor/gonum.org/v1/gonum/lapack/README.md b/vendor/gonum.org/v1/gonum/lapack/README.md deleted file mode 100644 index ee23148c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/README.md +++ /dev/null @@ -1,29 +0,0 @@ -Gonum LAPACK -====== -[![go.dev reference](https://pkg.go.dev/badge/gonum.org/v1/gonum/lapack)](https://pkg.go.dev/gonum.org/v1/gonum/lapack) -[![GoDoc](https://godocs.io/gonum.org/v1/gonum/lapack?status.svg)](https://godocs.io/gonum.org/v1/gonum/lapack) - -A collection of packages to provide LAPACK functionality for the Go programming -language (http://golang.org). This provides a partial implementation in native go -and a wrapper using cgo to a c-based implementation. - -## Installation - -``` - go get gonum.org/v1/gonum/lapack/... -``` - -## Packages - -### lapack - -Defines the LAPACK API based on http://www.netlib.org/lapack/lapacke.html - -### lapack/gonum - -Go implementation of the LAPACK API (incomplete, implements the `float64` API). - -### lapack/lapack64 - -Wrappers for an implementation of the double (i.e., `float64`) precision real parts of -the LAPACK API. diff --git a/vendor/gonum.org/v1/gonum/lapack/doc.go b/vendor/gonum.org/v1/gonum/lapack/doc.go deleted file mode 100644 index 2475cb4a..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2018 The Gonum 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 lapack provides interfaces for the LAPACK linear algebra standard. -package lapack // import "gonum.org/v1/gonum/lapack" diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go deleted file mode 100644 index fd421d7e..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go +++ /dev/null @@ -1,506 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dbdsqr performs a singular value decomposition of a real n×n bidiagonal matrix. -// -// The SVD of the bidiagonal matrix B is -// -// B = Q * S * Pᵀ -// -// where S is a diagonal matrix of singular values, Q is an orthogonal matrix of -// left singular vectors, and P is an orthogonal matrix of right singular vectors. -// -// Q and P are only computed if requested. If left singular vectors are requested, -// this routine returns U * Q instead of Q, and if right singular vectors are -// requested Pᵀ * VT is returned instead of Pᵀ. -// -// Frequently Dbdsqr is used in conjunction with Dgebrd which reduces a general -// matrix A into bidiagonal form. In this case, the SVD of A is -// -// A = (U * Q) * S * (Pᵀ * VT) -// -// This routine may also compute Qᵀ * C. -// -// d and e contain the elements of the bidiagonal matrix b. d must have length at -// least n, and e must have length at least n-1. Dbdsqr will panic if there is -// insufficient length. On exit, D contains the singular values of B in decreasing -// order. -// -// VT is a matrix of size n×ncvt whose elements are stored in vt. The elements -// of vt are modified to contain Pᵀ * VT on exit. VT is not used if ncvt == 0. -// -// U is a matrix of size nru×n whose elements are stored in u. The elements -// of u are modified to contain U * Q on exit. U is not used if nru == 0. -// -// C is a matrix of size n×ncc whose elements are stored in c. The elements -// of c are modified to contain Qᵀ * C on exit. C is not used if ncc == 0. -// -// work contains temporary storage and must have length at least 4*(n-1). Dbdsqr -// will panic if there is insufficient working memory. -// -// Dbdsqr returns whether the decomposition was successful. -// -// Dbdsqr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dbdsqr(uplo blas.Uplo, n, ncvt, nru, ncc int, d, e, vt []float64, ldvt int, u []float64, ldu int, c []float64, ldc int, work []float64) (ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case ncvt < 0: - panic(ncvtLT0) - case nru < 0: - panic(nruLT0) - case ncc < 0: - panic(nccLT0) - case ldvt < max(1, ncvt): - panic(badLdVT) - case (ldu < max(1, n) && nru > 0) || (ldu < 1 && nru == 0): - panic(badLdU) - case ldc < max(1, ncc): - panic(badLdC) - } - - // Quick return if possible. - if n == 0 { - return true - } - - if len(vt) < (n-1)*ldvt+ncvt && ncvt != 0 { - panic(shortVT) - } - if len(u) < (nru-1)*ldu+n && nru != 0 { - panic(shortU) - } - if len(c) < (n-1)*ldc+ncc && ncc != 0 { - panic(shortC) - } - if len(d) < n { - panic(shortD) - } - if len(e) < n-1 { - panic(shortE) - } - if len(work) < 4*(n-1) { - panic(shortWork) - } - - var info int - bi := blas64.Implementation() - const maxIter = 6 - - if n != 1 { - // If the singular vectors do not need to be computed, use qd algorithm. - if !(ncvt > 0 || nru > 0 || ncc > 0) { - info = impl.Dlasq1(n, d, e, work) - // If info is 2 dqds didn't finish, and so try to. - if info != 2 { - return info == 0 - } - } - nm1 := n - 1 - nm12 := nm1 + nm1 - nm13 := nm12 + nm1 - idir := 0 - - eps := dlamchE - unfl := dlamchS - lower := uplo == blas.Lower - var cs, sn, r float64 - if lower { - for i := 0; i < n-1; i++ { - cs, sn, r = impl.Dlartg(d[i], e[i]) - d[i] = r - e[i] = sn * d[i+1] - d[i+1] *= cs - work[i] = cs - work[nm1+i] = sn - } - if nru > 0 { - impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, n, work, work[n-1:], u, ldu) - } - if ncc > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, n, ncc, work, work[n-1:], c, ldc) - } - } - // Compute singular values to a relative accuracy of tol. If tol is negative - // the values will be computed to an absolute accuracy of math.Abs(tol) * norm(b) - tolmul := math.Max(10, math.Min(100, math.Pow(eps, -1.0/8))) - tol := tolmul * eps - var smax float64 - for i := 0; i < n; i++ { - smax = math.Max(smax, math.Abs(d[i])) - } - for i := 0; i < n-1; i++ { - smax = math.Max(smax, math.Abs(e[i])) - } - - var smin float64 - var thresh float64 - if tol >= 0 { - sminoa := math.Abs(d[0]) - if sminoa != 0 { - mu := sminoa - for i := 1; i < n; i++ { - mu = math.Abs(d[i]) * (mu / (mu + math.Abs(e[i-1]))) - sminoa = math.Min(sminoa, mu) - if sminoa == 0 { - break - } - } - } - sminoa = sminoa / math.Sqrt(float64(n)) - thresh = math.Max(tol*sminoa, float64(maxIter*n*n)*unfl) - } else { - thresh = math.Max(math.Abs(tol)*smax, float64(maxIter*n*n)*unfl) - } - // Prepare for the main iteration loop for the singular values. - maxIt := maxIter * n * n - iter := 0 - oldl2 := -1 - oldm := -1 - // m points to the last element of unconverged part of matrix. - m := n - - Outer: - for m > 1 { - if iter > maxIt { - info = 0 - for i := 0; i < n-1; i++ { - if e[i] != 0 { - info++ - } - } - return info == 0 - } - // Find diagonal block of matrix to work on. - if tol < 0 && math.Abs(d[m-1]) <= thresh { - d[m-1] = 0 - } - smax = math.Abs(d[m-1]) - var l2 int - var broke bool - for l3 := 0; l3 < m-1; l3++ { - l2 = m - l3 - 2 - abss := math.Abs(d[l2]) - abse := math.Abs(e[l2]) - if tol < 0 && abss <= thresh { - d[l2] = 0 - } - if abse <= thresh { - broke = true - break - } - smax = math.Max(math.Max(smax, abss), abse) - } - if broke { - e[l2] = 0 - if l2 == m-2 { - // Convergence of bottom singular value, return to top. - m-- - continue - } - l2++ - } else { - l2 = 0 - } - // e[ll] through e[m-2] are nonzero, e[ll-1] is zero - if l2 == m-2 { - // Handle 2×2 block separately. - var sinr, cosr, sinl, cosl float64 - d[m-1], d[m-2], sinr, cosr, sinl, cosl = impl.Dlasv2(d[m-2], e[m-2], d[m-1]) - e[m-2] = 0 - if ncvt > 0 { - bi.Drot(ncvt, vt[(m-2)*ldvt:], 1, vt[(m-1)*ldvt:], 1, cosr, sinr) - } - if nru > 0 { - bi.Drot(nru, u[m-2:], ldu, u[m-1:], ldu, cosl, sinl) - } - if ncc > 0 { - bi.Drot(ncc, c[(m-2)*ldc:], 1, c[(m-1)*ldc:], 1, cosl, sinl) - } - m -= 2 - continue - } - // If working on a new submatrix, choose shift direction from larger end - // diagonal element toward smaller. - if l2 > oldm-1 || m-1 < oldl2 { - if math.Abs(d[l2]) >= math.Abs(d[m-1]) { - idir = 1 - } else { - idir = 2 - } - } - // Apply convergence tests. - // TODO(btracey): There is a lot of similar looking code here. See - // if there is a better way to de-duplicate. - if idir == 1 { - // Run convergence test in forward direction. - // First apply standard test to bottom of matrix. - if math.Abs(e[m-2]) <= math.Abs(tol)*math.Abs(d[m-1]) || (tol < 0 && math.Abs(e[m-2]) <= thresh) { - e[m-2] = 0 - continue - } - if tol >= 0 { - // If relative accuracy desired, apply convergence criterion forward. - mu := math.Abs(d[l2]) - smin = mu - for l3 := l2; l3 < m-1; l3++ { - if math.Abs(e[l3]) <= tol*mu { - e[l3] = 0 - continue Outer - } - mu = math.Abs(d[l3+1]) * (mu / (mu + math.Abs(e[l3]))) - smin = math.Min(smin, mu) - } - } - } else { - // Run convergence test in backward direction. - // First apply standard test to top of matrix. - if math.Abs(e[l2]) <= math.Abs(tol)*math.Abs(d[l2]) || (tol < 0 && math.Abs(e[l2]) <= thresh) { - e[l2] = 0 - continue - } - if tol >= 0 { - // If relative accuracy desired, apply convergence criterion backward. - mu := math.Abs(d[m-1]) - smin = mu - for l3 := m - 2; l3 >= l2; l3-- { - if math.Abs(e[l3]) <= tol*mu { - e[l3] = 0 - continue Outer - } - mu = math.Abs(d[l3]) * (mu / (mu + math.Abs(e[l3]))) - smin = math.Min(smin, mu) - } - } - } - oldl2 = l2 - oldm = m - // Compute shift. First, test if shifting would ruin relative accuracy, - // and if so set the shift to zero. - var shift float64 - if tol >= 0 && float64(n)*tol*(smin/smax) <= math.Max(eps, (1.0/100)*tol) { - shift = 0 - } else { - var sl2 float64 - if idir == 1 { - sl2 = math.Abs(d[l2]) - shift, _ = impl.Dlas2(d[m-2], e[m-2], d[m-1]) - } else { - sl2 = math.Abs(d[m-1]) - shift, _ = impl.Dlas2(d[l2], e[l2], d[l2+1]) - } - // Test if shift is negligible - if sl2 > 0 { - if (shift/sl2)*(shift/sl2) < eps { - shift = 0 - } - } - } - iter += m - l2 + 1 - // If no shift, do simplified QR iteration. - if shift == 0 { - if idir == 1 { - cs := 1.0 - oldcs := 1.0 - var sn, r, oldsn float64 - for i := l2; i < m-1; i++ { - cs, sn, r = impl.Dlartg(d[i]*cs, e[i]) - if i > l2 { - e[i-1] = oldsn * r - } - oldcs, oldsn, d[i] = impl.Dlartg(oldcs*r, d[i+1]*sn) - work[i-l2] = cs - work[i-l2+nm1] = sn - work[i-l2+nm12] = oldcs - work[i-l2+nm13] = oldsn - } - h := d[m-1] * cs - d[m-1] = h * oldcs - e[m-2] = h * oldsn - if ncvt > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncvt, work, work[n-1:], vt[l2*ldvt:], ldvt) - } - if nru > 0 { - impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, m-l2, work[nm12:], work[nm13:], u[l2:], ldu) - } - if ncc > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncc, work[nm12:], work[nm13:], c[l2*ldc:], ldc) - } - if math.Abs(e[m-2]) < thresh { - e[m-2] = 0 - } - } else { - cs := 1.0 - oldcs := 1.0 - var sn, r, oldsn float64 - for i := m - 1; i >= l2+1; i-- { - cs, sn, r = impl.Dlartg(d[i]*cs, e[i-1]) - if i < m-1 { - e[i] = oldsn * r - } - oldcs, oldsn, d[i] = impl.Dlartg(oldcs*r, d[i-1]*sn) - work[i-l2-1] = cs - work[i-l2+nm1-1] = -sn - work[i-l2+nm12-1] = oldcs - work[i-l2+nm13-1] = -oldsn - } - h := d[l2] * cs - d[l2] = h * oldcs - e[l2] = h * oldsn - if ncvt > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncvt, work[nm12:], work[nm13:], vt[l2*ldvt:], ldvt) - } - if nru > 0 { - impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, nru, m-l2, work, work[n-1:], u[l2:], ldu) - } - if ncc > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncc, work, work[n-1:], c[l2*ldc:], ldc) - } - if math.Abs(e[l2]) <= thresh { - e[l2] = 0 - } - } - } else { - // Use nonzero shift. - if idir == 1 { - // Chase bulge from top to bottom. Save cosines and sines for - // later singular vector updates. - f := (math.Abs(d[l2]) - shift) * (math.Copysign(1, d[l2]) + shift/d[l2]) - g := e[l2] - var cosl, sinl float64 - for i := l2; i < m-1; i++ { - cosr, sinr, r := impl.Dlartg(f, g) - if i > l2 { - e[i-1] = r - } - f = cosr*d[i] + sinr*e[i] - e[i] = cosr*e[i] - sinr*d[i] - g = sinr * d[i+1] - d[i+1] *= cosr - cosl, sinl, r = impl.Dlartg(f, g) - d[i] = r - f = cosl*e[i] + sinl*d[i+1] - d[i+1] = cosl*d[i+1] - sinl*e[i] - if i < m-2 { - g = sinl * e[i+1] - e[i+1] = cosl * e[i+1] - } - work[i-l2] = cosr - work[i-l2+nm1] = sinr - work[i-l2+nm12] = cosl - work[i-l2+nm13] = sinl - } - e[m-2] = f - if ncvt > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncvt, work, work[n-1:], vt[l2*ldvt:], ldvt) - } - if nru > 0 { - impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, m-l2, work[nm12:], work[nm13:], u[l2:], ldu) - } - if ncc > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncc, work[nm12:], work[nm13:], c[l2*ldc:], ldc) - } - if math.Abs(e[m-2]) <= thresh { - e[m-2] = 0 - } - } else { - // Chase bulge from top to bottom. Save cosines and sines for - // later singular vector updates. - f := (math.Abs(d[m-1]) - shift) * (math.Copysign(1, d[m-1]) + shift/d[m-1]) - g := e[m-2] - for i := m - 1; i > l2; i-- { - cosr, sinr, r := impl.Dlartg(f, g) - if i < m-1 { - e[i] = r - } - f = cosr*d[i] + sinr*e[i-1] - e[i-1] = cosr*e[i-1] - sinr*d[i] - g = sinr * d[i-1] - d[i-1] *= cosr - cosl, sinl, r := impl.Dlartg(f, g) - d[i] = r - f = cosl*e[i-1] + sinl*d[i-1] - d[i-1] = cosl*d[i-1] - sinl*e[i-1] - if i > l2+1 { - g = sinl * e[i-2] - e[i-2] *= cosl - } - work[i-l2-1] = cosr - work[i-l2+nm1-1] = -sinr - work[i-l2+nm12-1] = cosl - work[i-l2+nm13-1] = -sinl - } - e[l2] = f - if math.Abs(e[l2]) <= thresh { - e[l2] = 0 - } - if ncvt > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncvt, work[nm12:], work[nm13:], vt[l2*ldvt:], ldvt) - } - if nru > 0 { - impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, nru, m-l2, work, work[n-1:], u[l2:], ldu) - } - if ncc > 0 { - impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncc, work, work[n-1:], c[l2*ldc:], ldc) - } - } - } - } - } - - // All singular values converged, make them positive. - for i := 0; i < n; i++ { - if d[i] < 0 { - d[i] *= -1 - if ncvt > 0 { - bi.Dscal(ncvt, -1, vt[i*ldvt:], 1) - } - } - } - - // Sort the singular values in decreasing order. - for i := 0; i < n-1; i++ { - isub := 0 - smin := d[0] - for j := 1; j < n-i; j++ { - if d[j] <= smin { - isub = j - smin = d[j] - } - } - if isub != n-i { - // Swap singular values and vectors. - d[isub] = d[n-i-1] - d[n-i-1] = smin - if ncvt > 0 { - bi.Dswap(ncvt, vt[isub*ldvt:], 1, vt[(n-i-1)*ldvt:], 1) - } - if nru > 0 { - bi.Dswap(nru, u[isub:], ldu, u[n-i-1:], ldu) - } - if ncc > 0 { - bi.Dswap(ncc, c[isub*ldc:], 1, c[(n-i-1)*ldc:], 1) - } - } - } - info = 0 - for i := 0; i < n-1; i++ { - if e[i] != 0 { - info++ - } - } - return info == 0 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go deleted file mode 100644 index b6af972e..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dgebak updates an n×m matrix V as -// -// V = P D V if side == lapack.EVRight, -// V = P D^{-1} V if side == lapack.EVLeft, -// -// where P and D are n×n permutation and scaling matrices, respectively, -// implicitly represented by job, scale, ilo and ihi as returned by Dgebal. -// -// Typically, columns of the matrix V contain the right or left (determined by -// side) eigenvectors of the balanced matrix output by Dgebal, and Dgebak forms -// the eigenvectors of the original matrix. -// -// Dgebak is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgebak(job lapack.BalanceJob, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) { - switch { - case job != lapack.BalanceNone && job != lapack.Permute && job != lapack.Scale && job != lapack.PermuteScale: - panic(badBalanceJob) - case side != lapack.EVLeft && side != lapack.EVRight: - panic(badEVSide) - case n < 0: - panic(nLT0) - case ilo < 0 || max(0, n-1) < ilo: - panic(badIlo) - case ihi < min(ilo, n-1) || n <= ihi: - panic(badIhi) - case m < 0: - panic(mLT0) - case ldv < max(1, m): - panic(badLdV) - } - - // Quick return if possible. - if n == 0 || m == 0 { - return - } - - if len(scale) < n { - panic(shortScale) - } - if len(v) < (n-1)*ldv+m { - panic(shortV) - } - - // Quick return if possible. - if job == lapack.BalanceNone { - return - } - - bi := blas64.Implementation() - if ilo != ihi && job != lapack.Permute { - // Backward balance. - if side == lapack.EVRight { - for i := ilo; i <= ihi; i++ { - bi.Dscal(m, scale[i], v[i*ldv:], 1) - } - } else { - for i := ilo; i <= ihi; i++ { - bi.Dscal(m, 1/scale[i], v[i*ldv:], 1) - } - } - } - if job == lapack.Scale { - return - } - // Backward permutation. - for i := ilo - 1; i >= 0; i-- { - k := int(scale[i]) - if k == i { - continue - } - bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) - } - for i := ihi + 1; i < n; i++ { - k := int(scale[i]) - if k == i { - continue - } - bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go deleted file mode 100644 index 7623e2fa..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dgebal balances an n×n matrix A. Balancing consists of two stages, permuting -// and scaling. Both steps are optional and depend on the value of job. -// -// Permuting consists of applying a permutation matrix P such that the matrix -// that results from Pᵀ*A*P takes the upper block triangular form -// -// [ T1 X Y ] -// Pᵀ A P = [ 0 B Z ], -// [ 0 0 T2 ] -// -// where T1 and T2 are upper triangular matrices and B contains at least one -// nonzero off-diagonal element in each row and column. The indices ilo and ihi -// mark the starting and ending columns of the submatrix B. The eigenvalues of A -// isolated in the first 0 to ilo-1 and last ihi+1 to n-1 elements on the -// diagonal can be read off without any roundoff error. -// -// Scaling consists of applying a diagonal similarity transformation D such that -// D^{-1}*B*D has the 1-norm of each row and its corresponding column nearly -// equal. The output matrix is -// -// [ T1 X*D Y ] -// [ 0 inv(D)*B*D inv(D)*Z ]. -// [ 0 0 T2 ] -// -// Scaling may reduce the 1-norm of the matrix, and improve the accuracy of -// the computed eigenvalues and/or eigenvectors. -// -// job specifies the operations that will be performed on A. -// If job is lapack.BalanceNone, Dgebal sets scale[i] = 1 for all i and returns ilo=0, ihi=n-1. -// If job is lapack.Permute, only permuting will be done. -// If job is lapack.Scale, only scaling will be done. -// If job is lapack.PermuteScale, both permuting and scaling will be done. -// -// On return, if job is lapack.Permute or lapack.PermuteScale, it will hold that -// -// A[i,j] == 0, for i > j and j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}. -// -// If job is lapack.BalanceNone or lapack.Scale, or if n == 0, it will hold that -// -// ilo == 0 and ihi == n-1. -// -// On return, scale will contain information about the permutations and scaling -// factors applied to A. If π(j) denotes the index of the column interchanged -// with column j, and D[j,j] denotes the scaling factor applied to column j, -// then -// -// scale[j] == π(j), for j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}, -// == D[j,j], for j ∈ {ilo, ..., ihi}. -// -// scale must have length equal to n, otherwise Dgebal will panic. -// -// Dgebal is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgebal(job lapack.BalanceJob, n int, a []float64, lda int, scale []float64) (ilo, ihi int) { - switch { - case job != lapack.BalanceNone && job != lapack.Permute && job != lapack.Scale && job != lapack.PermuteScale: - panic(badBalanceJob) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - ilo = 0 - ihi = n - 1 - - if n == 0 { - return ilo, ihi - } - - if len(scale) != n { - panic(shortScale) - } - - if job == lapack.BalanceNone { - for i := range scale { - scale[i] = 1 - } - return ilo, ihi - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - bi := blas64.Implementation() - swapped := true - - if job == lapack.Scale { - goto scaling - } - - // Permutation to isolate eigenvalues if possible. - // - // Search for rows isolating an eigenvalue and push them down. - for swapped { - swapped = false - rows: - for i := ihi; i >= 0; i-- { - for j := 0; j <= ihi; j++ { - if i == j { - continue - } - if a[i*lda+j] != 0 { - continue rows - } - } - // Row i has only zero off-diagonal elements in the - // block A[ilo:ihi+1,ilo:ihi+1]. - scale[ihi] = float64(i) - if i != ihi { - bi.Dswap(ihi+1, a[i:], lda, a[ihi:], lda) - bi.Dswap(n, a[i*lda:], 1, a[ihi*lda:], 1) - } - if ihi == 0 { - scale[0] = 1 - return ilo, ihi - } - ihi-- - swapped = true - break - } - } - // Search for columns isolating an eigenvalue and push them left. - swapped = true - for swapped { - swapped = false - columns: - for j := ilo; j <= ihi; j++ { - for i := ilo; i <= ihi; i++ { - if i == j { - continue - } - if a[i*lda+j] != 0 { - continue columns - } - } - // Column j has only zero off-diagonal elements in the - // block A[ilo:ihi+1,ilo:ihi+1]. - scale[ilo] = float64(j) - if j != ilo { - bi.Dswap(ihi+1, a[j:], lda, a[ilo:], lda) - bi.Dswap(n-ilo, a[j*lda+ilo:], 1, a[ilo*lda+ilo:], 1) - } - swapped = true - ilo++ - break - } - } - -scaling: - for i := ilo; i <= ihi; i++ { - scale[i] = 1 - } - - if job == lapack.Permute { - return ilo, ihi - } - - // Balance the submatrix in rows ilo to ihi. - - const ( - // sclfac should be a power of 2 to avoid roundoff errors. - // Elements of scale are restricted to powers of sclfac, - // therefore the matrix will be only nearly balanced. - sclfac = 2 - // factor determines the minimum reduction of the row and column - // norms that is considered non-negligible. It must be less than 1. - factor = 0.95 - ) - sfmin1 := dlamchS / dlamchP - sfmax1 := 1 / sfmin1 - sfmin2 := sfmin1 * sclfac - sfmax2 := 1 / sfmin2 - - // Iterative loop for norm reduction. - var conv bool - for !conv { - conv = true - for i := ilo; i <= ihi; i++ { - c := bi.Dnrm2(ihi-ilo+1, a[ilo*lda+i:], lda) - r := bi.Dnrm2(ihi-ilo+1, a[i*lda+ilo:], 1) - ica := bi.Idamax(ihi+1, a[i:], lda) - ca := math.Abs(a[ica*lda+i]) - ira := bi.Idamax(n-ilo, a[i*lda+ilo:], 1) - ra := math.Abs(a[i*lda+ilo+ira]) - - // Guard against zero c or r due to underflow. - if c == 0 || r == 0 { - continue - } - g := r / sclfac - f := 1.0 - s := c + r - for c < g && math.Max(f, math.Max(c, ca)) < sfmax2 && math.Min(r, math.Min(g, ra)) > sfmin2 { - if math.IsNaN(c + f + ca + r + g + ra) { - // Panic if NaN to avoid infinite loop. - panic("lapack: NaN") - } - f *= sclfac - c *= sclfac - ca *= sclfac - g /= sclfac - r /= sclfac - ra /= sclfac - } - g = c / sclfac - for r <= g && math.Max(r, ra) < sfmax2 && math.Min(math.Min(f, c), math.Min(g, ca)) > sfmin2 { - f /= sclfac - c /= sclfac - ca /= sclfac - g /= sclfac - r *= sclfac - ra *= sclfac - } - - if c+r >= factor*s { - // Reduction would be negligible. - continue - } - if f < 1 && scale[i] < 1 && f*scale[i] <= sfmin1 { - continue - } - if f > 1 && scale[i] > 1 && scale[i] >= sfmax1/f { - continue - } - - // Now balance. - scale[i] *= f - bi.Dscal(n-ilo, 1/f, a[i*lda+ilo:], 1) - bi.Dscal(ihi+1, f, a[i:], lda) - conv = false - } - } - return ilo, ihi -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go deleted file mode 100644 index 4f323ec5..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dgebd2 reduces an m×n matrix A to upper or lower bidiagonal form by an orthogonal -// transformation. -// -// Qᵀ * A * P = B -// -// if m >= n, B is upper diagonal, otherwise B is lower bidiagonal. -// d is the diagonal, len = min(m,n) -// e is the off-diagonal len = min(m,n)-1 -// -// Dgebd2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgebd2(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - minmn := min(m, n) - if minmn == 0 { - return - } - - switch { - case len(d) < minmn: - panic(shortD) - case len(e) < minmn-1: - panic(shortE) - case len(tauQ) < minmn: - panic(shortTauQ) - case len(tauP) < minmn: - panic(shortTauP) - case len(work) < max(m, n): - panic(shortWork) - } - - if m >= n { - for i := 0; i < n; i++ { - a[i*lda+i], tauQ[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], lda) - d[i] = a[i*lda+i] - a[i*lda+i] = 1 - // Apply H_i to A[i:m, i+1:n] from the left. - if i < n-1 { - impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tauQ[i], a[i*lda+i+1:], lda, work) - } - a[i*lda+i] = d[i] - if i < n-1 { - a[i*lda+i+1], tauP[i] = impl.Dlarfg(n-i-1, a[i*lda+i+1], a[i*lda+min(i+2, n-1):], 1) - e[i] = a[i*lda+i+1] - a[i*lda+i+1] = 1 - impl.Dlarf(blas.Right, m-i-1, n-i-1, a[i*lda+i+1:], 1, tauP[i], a[(i+1)*lda+i+1:], lda, work) - a[i*lda+i+1] = e[i] - } else { - tauP[i] = 0 - } - } - return - } - for i := 0; i < m; i++ { - a[i*lda+i], tauP[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) - d[i] = a[i*lda+i] - a[i*lda+i] = 1 - if i < m-1 { - impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tauP[i], a[(i+1)*lda+i:], lda, work) - } - a[i*lda+i] = d[i] - if i < m-1 { - a[(i+1)*lda+i], tauQ[i] = impl.Dlarfg(m-i-1, a[(i+1)*lda+i], a[min(i+2, m-1)*lda+i:], lda) - e[i] = a[(i+1)*lda+i] - a[(i+1)*lda+i] = 1 - impl.Dlarf(blas.Left, m-i-1, n-i-1, a[(i+1)*lda+i:], lda, tauQ[i], a[(i+1)*lda+i+1:], lda, work) - a[(i+1)*lda+i] = e[i] - } else { - tauQ[i] = 0 - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go deleted file mode 100644 index 6b6654ba..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgebrd reduces a general m×n matrix A to upper or lower bidiagonal form B by -// an orthogonal transformation: -// -// Qᵀ * A * P = B. -// -// The diagonal elements of B are stored in d and the off-diagonal elements are stored -// in e. These are additionally stored along the diagonal of A and the off-diagonal -// of A. If m >= n B is an upper-bidiagonal matrix, and if m < n B is a -// lower-bidiagonal matrix. -// -// The remaining elements of A store the data needed to construct Q and P. -// The matrices Q and P are products of elementary reflectors -// -// if m >= n, Q = H_0 * H_1 * ... * H_{n-1}, -// P = G_0 * G_1 * ... * G_{n-2}, -// if m < n, Q = H_0 * H_1 * ... * H_{m-2}, -// P = G_0 * G_1 * ... * G_{m-1}, -// -// where -// -// H_i = I - tauQ[i] * v_i * v_iᵀ, -// G_i = I - tauP[i] * u_i * u_iᵀ. -// -// As an example, on exit the entries of A when m = 6, and n = 5 -// -// [ d e u1 u1 u1] -// [v1 d e u2 u2] -// [v1 v2 d e u3] -// [v1 v2 v3 d e] -// [v1 v2 v3 v4 d] -// [v1 v2 v3 v4 v5] -// -// and when m = 5, n = 6 -// -// [ d u1 u1 u1 u1 u1] -// [ e d u2 u2 u2 u2] -// [v1 e d u3 u3 u3] -// [v1 v2 e d u4 u4] -// [v1 v2 v3 e d u5] -// -// d, tauQ, and tauP must all have length at least min(m,n), and e must have -// length min(m,n) - 1, unless lwork is -1 when there is no check except for -// work which must have a length of at least one. -// -// work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= max(1,m,n) or be -1 and this function will panic otherwise. -// Dgebrd is blocked decomposition, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Dgebrd, -// the optimal work length will be stored into work[0]. -// -// Dgebrd is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, max(m, n)) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - minmn := min(m, n) - if minmn == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(1, "DGEBRD", " ", m, n, -1, -1) - lwkopt := (m + n) * nb - if lwork == -1 { - work[0] = float64(lwkopt) - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(d) < minmn: - panic(shortD) - case len(e) < minmn-1: - panic(shortE) - case len(tauQ) < minmn: - panic(shortTauQ) - case len(tauP) < minmn: - panic(shortTauP) - } - - nx := minmn - ws := max(m, n) - if 1 < nb && nb < minmn { - // At least one blocked operation can be done. - // Get the crossover point nx. - nx = max(nb, impl.Ilaenv(3, "DGEBRD", " ", m, n, -1, -1)) - // Determine when to switch from blocked to unblocked code. - if nx < minmn { - // At least one blocked operation will be done. - ws = (m + n) * nb - if lwork < ws { - // Not enough work space for the optimal nb, - // consider using a smaller block size. - nbmin := impl.Ilaenv(2, "DGEBRD", " ", m, n, -1, -1) - if lwork >= (m+n)*nbmin { - // Enough work space for minimum block size. - nb = lwork / (m + n) - } else { - nb = minmn - nx = minmn - } - } - } - } - bi := blas64.Implementation() - ldworkx := nb - ldworky := nb - var i int - for i = 0; i < minmn-nx; i += nb { - // Reduce rows and columns i:i+nb to bidiagonal form and return - // the matrices X and Y which are needed to update the unreduced - // part of the matrix. - // X is stored in the first m rows of work, y in the next rows. - x := work[:m*ldworkx] - y := work[m*ldworkx:] - impl.Dlabrd(m-i, n-i, nb, a[i*lda+i:], lda, - d[i:], e[i:], tauQ[i:], tauP[i:], - x, ldworkx, y, ldworky) - - // Update the trailing submatrix A[i+nb:m,i+nb:n], using an update - // of the form A := A - V*Y**T - X*U**T - bi.Dgemm(blas.NoTrans, blas.Trans, m-i-nb, n-i-nb, nb, - -1, a[(i+nb)*lda+i:], lda, y[nb*ldworky:], ldworky, - 1, a[(i+nb)*lda+i+nb:], lda) - - bi.Dgemm(blas.NoTrans, blas.NoTrans, m-i-nb, n-i-nb, nb, - -1, x[nb*ldworkx:], ldworkx, a[i*lda+i+nb:], lda, - 1, a[(i+nb)*lda+i+nb:], lda) - - // Copy diagonal and off-diagonal elements of B back into A. - if m >= n { - for j := i; j < i+nb; j++ { - a[j*lda+j] = d[j] - a[j*lda+j+1] = e[j] - } - } else { - for j := i; j < i+nb; j++ { - a[j*lda+j] = d[j] - a[(j+1)*lda+j] = e[j] - } - } - } - // Use unblocked code to reduce the remainder of the matrix. - impl.Dgebd2(m-i, n-i, a[i*lda+i:], lda, d[i:], e[i:], tauQ[i:], tauP[i:], work) - work[0] = float64(ws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go deleted file mode 100644 index 1d046441..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dgecon estimates and returns the reciprocal of the condition number of the -// n×n matrix A, in either the 1-norm or the ∞-norm, using the LU factorization -// computed by Dgetrf. -// -// An estimate is obtained for norm(A⁻¹), and the reciprocal of the condition -// number rcond is computed as -// -// rcond 1 / ( norm(A) * norm(A⁻¹) ). -// -// If n is zero, rcond is always 1. -// -// anorm is the 1-norm or the ∞-norm of the original matrix A. anorm must be -// non-negative, otherwise Dgecon will panic. If anorm is 0 or infinity, Dgecon -// returns 0. If anorm is NaN, Dgecon returns NaN. -// -// work must have length at least 4*n and iwork must have length at least n, -// otherwise Dgecon will panic. -func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { - switch { - case norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum: - panic(badNorm) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case anorm < 0: - panic(negANorm) - } - - // Quick return if possible. - if n == 0 { - return 1 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(work) < 4*n: - panic(shortWork) - case len(iwork) < n: - panic(shortIWork) - } - - // Quick return if possible. - switch { - case anorm == 0: - return 0 - case math.IsNaN(anorm): - // Propagate NaN. - return anorm - case math.IsInf(anorm, 1): - return 0 - } - - bi := blas64.Implementation() - var rcond, ainvnm float64 - var kase int - var normin bool - isave := new([3]int) - onenrm := norm == lapack.MaxColumnSum - smlnum := dlamchS - kase1 := 2 - if onenrm { - kase1 = 1 - } - for { - ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) - if kase == 0 { - if ainvnm != 0 { - rcond = (1 / ainvnm) / anorm - } - return rcond - } - var sl, su float64 - if kase == kase1 { - sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.Unit, normin, n, a, lda, work, work[2*n:]) - su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) - } else { - su = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) - sl = impl.Dlatrs(blas.Lower, blas.Trans, blas.Unit, normin, n, a, lda, work, work[2*n:]) - } - scale := sl * su - normin = true - if scale != 1 { - ix := bi.Idamax(n, work, 1) - if scale == 0 || scale < math.Abs(work[ix])*smlnum { - return rcond - } - impl.Drscl(n, scale, work, 1) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go deleted file mode 100644 index b49b66fc..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dgeev computes the eigenvalues and, optionally, the left and/or right -// eigenvectors for an n×n real nonsymmetric matrix A. -// -// The right eigenvector v_j of A corresponding to an eigenvalue λ_j -// is defined by -// -// A v_j = λ_j v_j, -// -// and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by -// -// u_jᴴ A = λ_j u_jᴴ, -// -// where u_jᴴ is the conjugate transpose of u_j. -// -// On return, A will be overwritten and the left and right eigenvectors will be -// stored, respectively, in the columns of the n×n matrices VL and VR in the -// same order as their eigenvalues. If the j-th eigenvalue is real, then -// -// u_j = VL[:,j], -// v_j = VR[:,j], -// -// and if it is not real, then j and j+1 form a complex conjugate pair and the -// eigenvectors can be recovered as -// -// u_j = VL[:,j] + i*VL[:,j+1], -// u_{j+1} = VL[:,j] - i*VL[:,j+1], -// v_j = VR[:,j] + i*VR[:,j+1], -// v_{j+1} = VR[:,j] - i*VR[:,j+1], -// -// where i is the imaginary unit. The computed eigenvectors are normalized to -// have Euclidean norm equal to 1 and largest component real. -// -// Left eigenvectors will be computed only if jobvl == lapack.LeftEVCompute, -// otherwise jobvl must be lapack.LeftEVNone. -// Right eigenvectors will be computed only if jobvr == lapack.RightEVCompute, -// otherwise jobvr must be lapack.RightEVNone. -// For other values of jobvl and jobvr Dgeev will panic. -// -// wr and wi contain the real and imaginary parts, respectively, of the computed -// eigenvalues. Complex conjugate pairs of eigenvalues appear consecutively with -// the eigenvalue having the positive imaginary part first. -// wr and wi must have length n, and Dgeev will panic otherwise. -// -// work must have length at least lwork and lwork must be at least max(1,4*n) if -// the left or right eigenvectors are computed, and at least max(1,3*n) if no -// eigenvectors are computed. For good performance, lwork must generally be -// larger. On return, optimal value of lwork will be stored in work[0]. -// -// If lwork == -1, instead of performing Dgeev, the function only calculates the -// optimal value of lwork and stores it into work[0]. -// -// On return, first is the index of the first valid eigenvalue. If first == 0, -// all eigenvalues and eigenvectors have been computed. If first is positive, -// Dgeev failed to compute all the eigenvalues, no eigenvectors have been -// computed and wr[first:] and wi[first:] contain those eigenvalues which have -// converged. -func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, n int, a []float64, lda int, wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) (first int) { - wantvl := jobvl == lapack.LeftEVCompute - wantvr := jobvr == lapack.RightEVCompute - var minwrk int - if wantvl || wantvr { - minwrk = max(1, 4*n) - } else { - minwrk = max(1, 3*n) - } - switch { - case jobvl != lapack.LeftEVCompute && jobvl != lapack.LeftEVNone: - panic(badLeftEVJob) - case jobvr != lapack.RightEVCompute && jobvr != lapack.RightEVNone: - panic(badRightEVJob) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case ldvl < 1 || (ldvl < n && wantvl): - panic(badLdVL) - case ldvr < 1 || (ldvr < n && wantvr): - panic(badLdVR) - case lwork < minwrk && lwork != -1: - panic(badLWork) - case len(work) < lwork: - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - work[0] = 1 - return 0 - } - - maxwrk := 2*n + n*impl.Ilaenv(1, "DGEHRD", " ", n, 1, n, 0) - if wantvl || wantvr { - maxwrk = max(maxwrk, 2*n+(n-1)*impl.Ilaenv(1, "DORGHR", " ", n, 1, n, -1)) - impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.SchurOrig, n, 0, n-1, - a, lda, wr, wi, nil, n, work, -1) - maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) - side := lapack.EVLeft - if wantvr { - side = lapack.EVRight - } - impl.Dtrevc3(side, lapack.EVAllMulQ, nil, n, a, lda, vl, ldvl, vr, ldvr, - n, work, -1) - maxwrk = max(maxwrk, n+int(work[0])) - maxwrk = max(maxwrk, 4*n) - } else { - impl.Dhseqr(lapack.EigenvaluesOnly, lapack.SchurNone, n, 0, n-1, - a, lda, wr, wi, vr, ldvr, work, -1) - maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) - } - maxwrk = max(maxwrk, minwrk) - - if lwork == -1 { - work[0] = float64(maxwrk) - return 0 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(wr) != n: - panic(badLenWr) - case len(wi) != n: - panic(badLenWi) - case len(vl) < (n-1)*ldvl+n && wantvl: - panic(shortVL) - case len(vr) < (n-1)*ldvr+n && wantvr: - panic(shortVR) - } - - // Get machine constants. - smlnum := math.Sqrt(dlamchS) / dlamchP - bignum := 1 / smlnum - - // Scale A if max element outside range [smlnum,bignum]. - anrm := impl.Dlange(lapack.MaxAbs, n, n, a, lda, nil) - var scalea bool - var cscale float64 - if 0 < anrm && anrm < smlnum { - scalea = true - cscale = smlnum - } else if anrm > bignum { - scalea = true - cscale = bignum - } - if scalea { - impl.Dlascl(lapack.General, 0, 0, anrm, cscale, n, n, a, lda) - } - - // Balance the matrix. - workbal := work[:n] - ilo, ihi := impl.Dgebal(lapack.PermuteScale, n, a, lda, workbal) - - // Reduce to upper Hessenberg form. - iwrk := 2 * n - tau := work[n : iwrk-1] - impl.Dgehrd(n, ilo, ihi, a, lda, tau, work[iwrk:], lwork-iwrk) - - var side lapack.EVSide - if wantvl { - side = lapack.EVLeft - // Copy Householder vectors to VL. - impl.Dlacpy(blas.Lower, n, n, a, lda, vl, ldvl) - // Generate orthogonal matrix in VL. - impl.Dorghr(n, ilo, ihi, vl, ldvl, tau, work[iwrk:], lwork-iwrk) - // Perform QR iteration, accumulating Schur vectors in VL. - iwrk = n - first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.SchurOrig, n, ilo, ihi, - a, lda, wr, wi, vl, ldvl, work[iwrk:], lwork-iwrk) - if wantvr { - // Want left and right eigenvectors. - // Copy Schur vectors to VR. - side = lapack.EVBoth - impl.Dlacpy(blas.All, n, n, vl, ldvl, vr, ldvr) - } - } else if wantvr { - side = lapack.EVRight - // Copy Householder vectors to VR. - impl.Dlacpy(blas.Lower, n, n, a, lda, vr, ldvr) - // Generate orthogonal matrix in VR. - impl.Dorghr(n, ilo, ihi, vr, ldvr, tau, work[iwrk:], lwork-iwrk) - // Perform QR iteration, accumulating Schur vectors in VR. - iwrk = n - first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.SchurOrig, n, ilo, ihi, - a, lda, wr, wi, vr, ldvr, work[iwrk:], lwork-iwrk) - } else { - // Compute eigenvalues only. - iwrk = n - first = impl.Dhseqr(lapack.EigenvaluesOnly, lapack.SchurNone, n, ilo, ihi, - a, lda, wr, wi, nil, 1, work[iwrk:], lwork-iwrk) - } - - if first > 0 { - if scalea { - // Undo scaling. - impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wr[first:], 1) - impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wi[first:], 1) - impl.Dlascl(lapack.General, 0, 0, cscale, anrm, ilo, 1, wr, 1) - impl.Dlascl(lapack.General, 0, 0, cscale, anrm, ilo, 1, wi, 1) - } - work[0] = float64(maxwrk) - return first - } - - if wantvl || wantvr { - // Compute left and/or right eigenvectors. - impl.Dtrevc3(side, lapack.EVAllMulQ, nil, n, - a, lda, vl, ldvl, vr, ldvr, n, work[iwrk:], lwork-iwrk) - } - bi := blas64.Implementation() - if wantvl { - // Undo balancing of left eigenvectors. - impl.Dgebak(lapack.PermuteScale, lapack.EVLeft, n, ilo, ihi, workbal, n, vl, ldvl) - // Normalize left eigenvectors and make largest component real. - for i, wii := range wi { - if wii < 0 { - continue - } - if wii == 0 { - scl := 1 / bi.Dnrm2(n, vl[i:], ldvl) - bi.Dscal(n, scl, vl[i:], ldvl) - continue - } - scl := 1 / impl.Dlapy2(bi.Dnrm2(n, vl[i:], ldvl), bi.Dnrm2(n, vl[i+1:], ldvl)) - bi.Dscal(n, scl, vl[i:], ldvl) - bi.Dscal(n, scl, vl[i+1:], ldvl) - for k := 0; k < n; k++ { - vi := vl[k*ldvl+i] - vi1 := vl[k*ldvl+i+1] - work[iwrk+k] = vi*vi + vi1*vi1 - } - k := bi.Idamax(n, work[iwrk:iwrk+n], 1) - cs, sn, _ := impl.Dlartg(vl[k*ldvl+i], vl[k*ldvl+i+1]) - bi.Drot(n, vl[i:], ldvl, vl[i+1:], ldvl, cs, sn) - vl[k*ldvl+i+1] = 0 - } - } - if wantvr { - // Undo balancing of right eigenvectors. - impl.Dgebak(lapack.PermuteScale, lapack.EVRight, n, ilo, ihi, workbal, n, vr, ldvr) - // Normalize right eigenvectors and make largest component real. - for i, wii := range wi { - if wii < 0 { - continue - } - if wii == 0 { - scl := 1 / bi.Dnrm2(n, vr[i:], ldvr) - bi.Dscal(n, scl, vr[i:], ldvr) - continue - } - scl := 1 / impl.Dlapy2(bi.Dnrm2(n, vr[i:], ldvr), bi.Dnrm2(n, vr[i+1:], ldvr)) - bi.Dscal(n, scl, vr[i:], ldvr) - bi.Dscal(n, scl, vr[i+1:], ldvr) - for k := 0; k < n; k++ { - vi := vr[k*ldvr+i] - vi1 := vr[k*ldvr+i+1] - work[iwrk+k] = vi*vi + vi1*vi1 - } - k := bi.Idamax(n, work[iwrk:iwrk+n], 1) - cs, sn, _ := impl.Dlartg(vr[k*ldvr+i], vr[k*ldvr+i+1]) - bi.Drot(n, vr[i:], ldvr, vr[i+1:], ldvr, cs, sn) - vr[k*ldvr+i+1] = 0 - } - } - - if scalea { - // Undo scaling. - impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wr[first:], 1) - impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wi[first:], 1) - } - - work[0] = float64(maxwrk) - return first -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go deleted file mode 100644 index 64b0cb40..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dgehd2 reduces a block of a general n×n matrix A to upper Hessenberg form H -// by an orthogonal similarity transformation Qᵀ * A * Q = H. -// -// The matrix Q is represented as a product of (ihi-ilo) elementary -// reflectors -// -// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. -// -// Each H_i has the form -// -// H_i = I - tau[i] * v * vᵀ -// -// where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0. -// v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i]. -// -// On entry, a contains the n×n general matrix to be reduced. On return, the -// upper triangle and the first subdiagonal of A are overwritten with the upper -// Hessenberg matrix H, and the elements below the first subdiagonal, with the -// slice tau, represent the orthogonal matrix Q as a product of elementary -// reflectors. -// -// The contents of A are illustrated by the following example, with n = 7, ilo = -// 1 and ihi = 5. -// On entry, -// -// [ a a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a ] -// -// on return, -// -// [ a a h h h h a ] -// [ a h h h h a ] -// [ h h h h h h ] -// [ v1 h h h h h ] -// [ v1 v2 h h h h ] -// [ v1 v2 v3 h h h ] -// [ a ] -// -// where a denotes an element of the original matrix A, h denotes a -// modified element of the upper Hessenberg matrix H, and vi denotes an -// element of the vector defining H_i. -// -// ilo and ihi determine the block of A that will be reduced to upper Hessenberg -// form. It must hold that 0 <= ilo <= ihi <= max(0, n-1), otherwise Dgehd2 will -// panic. -// -// On return, tau will contain the scalar factors of the elementary reflectors. -// It must have length equal to n-1, otherwise Dgehd2 will panic. -// -// work must have length at least n, otherwise Dgehd2 will panic. -// -// Dgehd2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgehd2(n, ilo, ihi int, a []float64, lda int, tau, work []float64) { - switch { - case n < 0: - panic(nLT0) - case ilo < 0 || max(0, n-1) < ilo: - panic(badIlo) - case ihi < min(ilo, n-1) || n <= ihi: - panic(badIhi) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(tau) != n-1: - panic(badLenTau) - case len(work) < n: - panic(shortWork) - } - - for i := ilo; i < ihi; i++ { - // Compute elementary reflector H_i to annihilate A[i+2:ihi+1,i]. - var aii float64 - aii, tau[i] = impl.Dlarfg(ihi-i, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) - a[(i+1)*lda+i] = 1 - - // Apply H_i to A[0:ihi+1,i+1:ihi+1] from the right. - impl.Dlarf(blas.Right, ihi+1, ihi-i, a[(i+1)*lda+i:], lda, tau[i], a[i+1:], lda, work) - - // Apply H_i to A[i+1:ihi+1,i+1:n] from the left. - impl.Dlarf(blas.Left, ihi-i, n-i-1, a[(i+1)*lda+i:], lda, tau[i], a[(i+1)*lda+i+1:], lda, work) - a[(i+1)*lda+i] = aii - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go deleted file mode 100644 index ae153302..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dgehrd reduces a block of a real n×n general matrix A to upper Hessenberg -// form H by an orthogonal similarity transformation Qᵀ * A * Q = H. -// -// The matrix Q is represented as a product of (ihi-ilo) elementary -// reflectors -// -// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. -// -// Each H_i has the form -// -// H_i = I - tau[i] * v * vᵀ -// -// where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0. -// v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i]. -// -// On entry, a contains the n×n general matrix to be reduced. On return, the -// upper triangle and the first subdiagonal of A will be overwritten with the -// upper Hessenberg matrix H, and the elements below the first subdiagonal, with -// the slice tau, represent the orthogonal matrix Q as a product of elementary -// reflectors. -// -// The contents of a are illustrated by the following example, with n = 7, ilo = -// 1 and ihi = 5. -// On entry, -// -// [ a a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a a a a a a ] -// [ a ] -// -// on return, -// -// [ a a h h h h a ] -// [ a h h h h a ] -// [ h h h h h h ] -// [ v1 h h h h h ] -// [ v1 v2 h h h h ] -// [ v1 v2 v3 h h h ] -// [ a ] -// -// where a denotes an element of the original matrix A, h denotes a -// modified element of the upper Hessenberg matrix H, and vi denotes an -// element of the vector defining H_i. -// -// ilo and ihi determine the block of A that will be reduced to upper Hessenberg -// form. It must hold that 0 <= ilo <= ihi < n if n > 0, and ilo == 0 and ihi == -// -1 if n == 0, otherwise Dgehrd will panic. -// -// On return, tau will contain the scalar factors of the elementary reflectors. -// Elements tau[:ilo] and tau[ihi:] will be set to zero. tau must have length -// equal to n-1 if n > 0, otherwise Dgehrd will panic. -// -// work must have length at least lwork and lwork must be at least max(1,n), -// otherwise Dgehrd will panic. On return, work[0] contains the optimal value of -// lwork. -// -// If lwork == -1, instead of performing Dgehrd, only the optimal value of lwork -// will be stored in work[0]. -// -// Dgehrd is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case n < 0: - panic(nLT0) - case ilo < 0 || max(0, n-1) < ilo: - panic(badIlo) - case ihi < min(ilo, n-1) || n <= ihi: - panic(badIhi) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, n) && lwork != -1: - panic(badLWork) - case len(work) < lwork: - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - work[0] = 1 - return - } - - const ( - nbmax = 64 - ldt = nbmax + 1 - tsize = ldt * nbmax - ) - // Compute the workspace requirements. - nb := min(nbmax, impl.Ilaenv(1, "DGEHRD", " ", n, ilo, ihi, -1)) - lwkopt := n*nb + tsize - if lwork == -1 { - work[0] = float64(lwkopt) - return - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - if len(tau) != n-1 { - panic(badLenTau) - } - - // Set tau[:ilo] and tau[ihi:] to zero. - for i := 0; i < ilo; i++ { - tau[i] = 0 - } - for i := ihi; i < n-1; i++ { - tau[i] = 0 - } - - // Quick return if possible. - nh := ihi - ilo + 1 - if nh <= 1 { - work[0] = 1 - return - } - - // Determine the block size. - nbmin := 2 - var nx int - if 1 < nb && nb < nh { - // Determine when to cross over from blocked to unblocked code - // (last block is always handled by unblocked code). - nx = max(nb, impl.Ilaenv(3, "DGEHRD", " ", n, ilo, ihi, -1)) - if nx < nh { - // Determine if workspace is large enough for blocked code. - if lwork < n*nb+tsize { - // Not enough workspace to use optimal nb: - // determine the minimum value of nb, and reduce - // nb or force use of unblocked code. - nbmin = max(2, impl.Ilaenv(2, "DGEHRD", " ", n, ilo, ihi, -1)) - if lwork >= n*nbmin+tsize { - nb = (lwork - tsize) / n - } else { - nb = 1 - } - } - } - } - ldwork := nb // work is used as an n×nb matrix. - - var i int - if nb < nbmin || nh <= nb { - // Use unblocked code below. - i = ilo - } else { - // Use blocked code. - bi := blas64.Implementation() - iwt := n * nb // Size of the matrix Y and index where the matrix T starts in work. - for i = ilo; i < ihi-nx; i += nb { - ib := min(nb, ihi-i) - - // Reduce columns [i:i+ib] to Hessenberg form, returning the - // matrices V and T of the block reflector H = I - V*T*Vᵀ - // which performs the reduction, and also the matrix Y = A*V*T. - impl.Dlahr2(ihi+1, i+1, ib, a[i:], lda, tau[i:], work[iwt:], ldt, work, ldwork) - - // Apply the block reflector H to A[:ihi+1,i+ib:ihi+1] from the - // right, computing A := A - Y * Vᵀ. V[i+ib,i+ib-1] must be set - // to 1. - ei := a[(i+ib)*lda+i+ib-1] - a[(i+ib)*lda+i+ib-1] = 1 - bi.Dgemm(blas.NoTrans, blas.Trans, ihi+1, ihi-i-ib+1, ib, - -1, work, ldwork, - a[(i+ib)*lda+i:], lda, - 1, a[i+ib:], lda) - a[(i+ib)*lda+i+ib-1] = ei - - // Apply the block reflector H to A[0:i+1,i+1:i+ib-1] from the - // right. - bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, i+1, ib-1, - 1, a[(i+1)*lda+i:], lda, work, ldwork) - for j := 0; j <= ib-2; j++ { - bi.Daxpy(i+1, -1, work[j:], ldwork, a[i+j+1:], lda) - } - - // Apply the block reflector H to A[i+1:ihi+1,i+ib:n] from the - // left. - impl.Dlarfb(blas.Left, blas.Trans, lapack.Forward, lapack.ColumnWise, - ihi-i, n-i-ib, ib, - a[(i+1)*lda+i:], lda, work[iwt:], ldt, a[(i+1)*lda+i+ib:], lda, work, ldwork) - } - } - // Use unblocked code to reduce the rest of the matrix. - impl.Dgehd2(n, i, ihi, a, lda, tau, work) - work[0] = float64(lwkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go deleted file mode 100644 index abc96f7d..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dgelq2 computes the LQ factorization of the m×n matrix A. -// -// In an LQ factorization, L is a lower triangular m×n matrix, and Q is an n×n -// orthonormal matrix. -// -// a is modified to contain the information to construct L and Q. -// The lower triangle of a contains the matrix L. The upper triangular elements -// (not including the diagonal) contain the elementary reflectors. tau is modified -// to contain the reflector scales. tau must have length of at least k = min(m,n) -// and this function will panic otherwise. -// -// See Dgeqr2 for a description of the elementary reflectors and orthonormal -// matrix Q. Q is constructed as a product of these elementary reflectors, -// Q = H_{k-1} * ... * H_1 * H_0. -// -// work is temporary storage of length at least m and this function will panic otherwise. -// -// Dgelq2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgelq2(m, n int, a []float64, lda int, tau, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - k := min(m, n) - if k == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - case len(work) < m: - panic(shortWork) - } - - for i := 0; i < k; i++ { - a[i*lda+i], tau[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) - if i < m-1 { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(blas.Right, m-i-1, n-i, - a[i*lda+i:], 1, - tau[i], - a[(i+1)*lda+i:], lda, - work) - a[i*lda+i] = aii - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go deleted file mode 100644 index f1fd13a0..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dgelqf computes the LQ factorization of the m×n matrix A using a blocked -// algorithm. See the documentation for Dgelq2 for a description of the -// parameters at entry and exit. -// -// work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= m, and this function will panic otherwise. -// Dgelqf is a blocked LQ factorization, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Dgelqf, -// the optimal work length will be stored into work[0]. -// -// tau must have length at least min(m,n), and this function will panic otherwise. -func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, m) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - k := min(m, n) - if k == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) - if lwork == -1 { - work[0] = float64(m * nb) - return - } - - if len(a) < (m-1)*lda+n { - panic(shortA) - } - if len(tau) < k { - panic(shortTau) - } - - // Find the optimal blocking size based on the size of available memory - // and optimal machine parameters. - nbmin := 2 - var nx int - iws := m - if 1 < nb && nb < k { - nx = max(0, impl.Ilaenv(3, "DGELQF", " ", m, n, -1, -1)) - if nx < k { - iws = m * nb - if lwork < iws { - nb = lwork / m - nbmin = max(2, impl.Ilaenv(2, "DGELQF", " ", m, n, -1, -1)) - } - } - } - ldwork := nb - // Computed blocked LQ factorization. - var i int - if nbmin <= nb && nb < k && nx < k { - for i = 0; i < k-nx; i += nb { - ib := min(k-i, nb) - impl.Dgelq2(ib, n-i, a[i*lda+i:], lda, tau[i:], work) - if i+ib < m { - impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, - a[i*lda+i:], lda, - tau[i:], - work, ldwork) - impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Forward, lapack.RowWise, - m-i-ib, n-i, ib, - a[i*lda+i:], lda, - work, ldwork, - a[(i+ib)*lda+i:], lda, - work[ib*ldwork:], ldwork) - } - } - } - // Perform unblocked LQ factorization on the remainder. - if i < k { - impl.Dgelq2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) - } - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go deleted file mode 100644 index 3018973a..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dgels finds a minimum-norm solution based on the matrices A and B using the -// QR or LQ factorization. Dgels returns false if the matrix -// A is singular, and true if this solution was successfully found. -// -// The minimization problem solved depends on the input parameters. -// -// 1. If m >= n and trans == blas.NoTrans, Dgels finds X such that || A*X - B||_2 -// is minimized. -// 2. If m < n and trans == blas.NoTrans, Dgels finds the minimum norm solution of -// A * X = B. -// 3. If m >= n and trans == blas.Trans, Dgels finds the minimum norm solution of -// Aᵀ * X = B. -// 4. If m < n and trans == blas.Trans, Dgels finds X such that || A*X - B||_2 -// is minimized. -// -// Note that the least-squares solutions (cases 1 and 3) perform the minimization -// per column of B. This is not the same as finding the minimum-norm matrix. -// -// The matrix A is a general matrix of size m×n and is modified during this call. -// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry, -// the elements of b specify the input matrix B. B has size m×nrhs if -// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the -// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans, -// this submatrix is of size n×nrhs, and of size m×nrhs otherwise. -// -// work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic -// otherwise. A longer work will enable blocked algorithms to be called. -// In the special case that lwork == -1, work[0] will be set to the optimal working -// length. -func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool { - mn := min(m, n) - minwrk := mn + max(mn, nrhs) - switch { - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, nrhs): - panic(badLdB) - case lwork < max(1, minwrk) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if mn == 0 || nrhs == 0 { - impl.Dlaset(blas.All, max(m, n), nrhs, 0, 0, b, ldb) - work[0] = 1 - return true - } - - // Find optimal block size. - var nb int - if m >= n { - nb = impl.Ilaenv(1, "DGEQRF", " ", m, n, -1, -1) - if trans != blas.NoTrans { - nb = max(nb, impl.Ilaenv(1, "DORMQR", "LN", m, nrhs, n, -1)) - } else { - nb = max(nb, impl.Ilaenv(1, "DORMQR", "LT", m, nrhs, n, -1)) - } - } else { - nb = impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) - if trans != blas.NoTrans { - nb = max(nb, impl.Ilaenv(1, "DORMLQ", "LT", n, nrhs, m, -1)) - } else { - nb = max(nb, impl.Ilaenv(1, "DORMLQ", "LN", n, nrhs, m, -1)) - } - } - wsize := max(1, mn+max(mn, nrhs)*nb) - work[0] = float64(wsize) - - if lwork == -1 { - return true - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(b) < (max(m, n)-1)*ldb+nrhs: - panic(shortB) - } - - // Scale the input matrices if they contain extreme values. - smlnum := dlamchS / dlamchP - bignum := 1 / smlnum - anrm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, nil) - var iascl int - if anrm > 0 && anrm < smlnum { - impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, m, n, a, lda) - iascl = 1 - } else if anrm > bignum { - impl.Dlascl(lapack.General, 0, 0, anrm, bignum, m, n, a, lda) - } else if anrm == 0 { - // Matrix is all zeros. - impl.Dlaset(blas.All, max(m, n), nrhs, 0, 0, b, ldb) - return true - } - brow := m - if trans != blas.NoTrans { - brow = n - } - bnrm := impl.Dlange(lapack.MaxAbs, brow, nrhs, b, ldb, nil) - ibscl := 0 - if bnrm > 0 && bnrm < smlnum { - impl.Dlascl(lapack.General, 0, 0, bnrm, smlnum, brow, nrhs, b, ldb) - ibscl = 1 - } else if bnrm > bignum { - impl.Dlascl(lapack.General, 0, 0, bnrm, bignum, brow, nrhs, b, ldb) - ibscl = 2 - } - - // Solve the minimization problem using a QR or an LQ decomposition. - var scllen int - if m >= n { - impl.Dgeqrf(m, n, a, lda, work[:n], work[mn:], lwork-mn) - if trans == blas.NoTrans { - impl.Dormqr(blas.Left, blas.Trans, m, nrhs, n, - a, lda, - work[:n], - b, ldb, - work[mn:], lwork-mn) - ok := impl.Dtrtrs(blas.Upper, blas.NoTrans, blas.NonUnit, n, nrhs, - a, lda, - b, ldb) - if !ok { - return false - } - scllen = n - } else { - ok := impl.Dtrtrs(blas.Upper, blas.Trans, blas.NonUnit, n, nrhs, - a, lda, - b, ldb) - if !ok { - return false - } - for i := n; i < m; i++ { - for j := 0; j < nrhs; j++ { - b[i*ldb+j] = 0 - } - } - impl.Dormqr(blas.Left, blas.NoTrans, m, nrhs, n, - a, lda, - work[:n], - b, ldb, - work[mn:], lwork-mn) - scllen = m - } - } else { - impl.Dgelqf(m, n, a, lda, work, work[mn:], lwork-mn) - if trans == blas.NoTrans { - ok := impl.Dtrtrs(blas.Lower, blas.NoTrans, blas.NonUnit, - m, nrhs, - a, lda, - b, ldb) - if !ok { - return false - } - for i := m; i < n; i++ { - for j := 0; j < nrhs; j++ { - b[i*ldb+j] = 0 - } - } - impl.Dormlq(blas.Left, blas.Trans, n, nrhs, m, - a, lda, - work, - b, ldb, - work[mn:], lwork-mn) - scllen = n - } else { - impl.Dormlq(blas.Left, blas.NoTrans, n, nrhs, m, - a, lda, - work, - b, ldb, - work[mn:], lwork-mn) - ok := impl.Dtrtrs(blas.Lower, blas.Trans, blas.NonUnit, - m, nrhs, - a, lda, - b, ldb) - if !ok { - return false - } - } - } - - // Adjust answer vector based on scaling. - if iascl == 1 { - impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, scllen, nrhs, b, ldb) - } - if iascl == 2 { - impl.Dlascl(lapack.General, 0, 0, anrm, bignum, scllen, nrhs, b, ldb) - } - if ibscl == 1 { - impl.Dlascl(lapack.General, 0, 0, smlnum, bnrm, scllen, nrhs, b, ldb) - } - if ibscl == 2 { - impl.Dlascl(lapack.General, 0, 0, bignum, bnrm, scllen, nrhs, b, ldb) - } - - work[0] = float64(wsize) - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go deleted file mode 100644 index d18989d2..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dgeql2 computes the QL factorization of the m×n matrix A. That is, Dgeql2 -// computes Q and L such that -// -// A = Q * L -// -// where Q is an m×m orthonormal matrix and L is a lower trapezoidal matrix. -// -// Q is represented as a product of elementary reflectors, -// -// Q = H_{k-1} * ... * H_1 * H_0 -// -// where k = min(m,n) and each H_i has the form -// -// H_i = I - tau[i] * v_i * v_iᵀ -// -// Vector v_i has v[m-k+i+1:m] = 0, v[m-k+i] = 1, and v[:m-k+i+1] is stored on -// exit in A[0:m-k+i-1, n-k+i]. -// -// tau must have length at least min(m,n), and Dgeql2 will panic otherwise. -// -// work is temporary memory storage and must have length at least n. -// -// Dgeql2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgeql2(m, n int, a []float64, lda int, tau, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - k := min(m, n) - if k == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - case len(work) < n: - panic(shortWork) - } - - var aii float64 - for i := k - 1; i >= 0; i-- { - // Generate elementary reflector H_i to annihilate A[0:m-k+i-1, n-k+i]. - aii, tau[i] = impl.Dlarfg(m-k+i+1, a[(m-k+i)*lda+n-k+i], a[n-k+i:], lda) - - // Apply H_i to A[0:m-k+i, 0:n-k+i-1] from the left. - a[(m-k+i)*lda+n-k+i] = 1 - impl.Dlarf(blas.Left, m-k+i+1, n-k+i, a[n-k+i:], lda, tau[i], a, lda, work) - a[(m-k+i)*lda+n-k+i] = aii - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go deleted file mode 100644 index da8cd4fa..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgeqp3 computes a QR factorization with column pivoting of the m×n matrix A: -// -// A*P = Q*R -// -// where P is a permutation matrix, Q is an orthogonal matrix and R is a -// min(m,n)×n upper trapezoidal matrix. -// -// On return, the upper triangle of A contains the matrix R. The elements below -// the diagonal together with tau represent the matrix Q as a product of -// elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). -// -// Each H_i has the form -// -// H_i = I - tau * v * vᵀ -// -// where tau is a scalar and v is a vector with v[0:i] = 0 and v[i] = 1; -// v[i+1:m] is stored on exit in A[i+1:m,i], and tau in tau[i]. -// -// jpvt specifies a column pivot to be applied to A. On entry, if jpvt[j] is at -// least zero, the jth column of A is permuted to the front of A*P (a leading -// column), if jpvt[j] is -1 the jth column of A is a free column. If jpvt[j] < -// -1, Dgeqp3 will panic. On return, jpvt holds the permutation that was -// applied; the jth column of A*P was the jpvt[j] column of A. jpvt must have -// length n or Dgeqp3 will panic. -// -// tau holds the scalar factors of the elementary reflectors. It must have -// length min(m,n), otherwise Dgeqp3 will panic. -// -// work must have length at least max(1,lwork), and lwork must be at least -// 3*n+1, otherwise Dgeqp3 will panic. For optimal performance lwork must be at -// least 2*n+(n+1)*nb, where nb is the optimal blocksize. On return, work[0] -// will contain the optimal value of lwork. -// -// If lwork == -1, instead of performing Dgeqp3, only the optimal value of lwork -// will be stored in work[0]. -// -// Dgeqp3 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int) { - const ( - inb = 1 - inbmin = 2 - ixover = 3 - ) - - minmn := min(m, n) - iws := 3*n + 1 - if minmn == 0 { - iws = 1 - } - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < iws && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if minmn == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(inb, "DGEQRF", " ", m, n, -1, -1) - if lwork == -1 { - work[0] = float64(2*n + (n+1)*nb) - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(jpvt) != n: - panic(badLenJpvt) - case len(tau) < minmn: - panic(shortTau) - } - - for _, v := range jpvt { - if v < -1 || n <= v { - panic(badJpvt) - } - } - - bi := blas64.Implementation() - - // Move initial columns up front. - var nfxd int - for j := 0; j < n; j++ { - if jpvt[j] == -1 { - jpvt[j] = j - continue - } - if j != nfxd { - bi.Dswap(m, a[j:], lda, a[nfxd:], lda) - jpvt[j], jpvt[nfxd] = jpvt[nfxd], j - } else { - jpvt[j] = j - } - nfxd++ - } - - // Factorize nfxd columns. - // - // Compute the QR factorization of nfxd columns and update remaining columns. - if nfxd > 0 { - na := min(m, nfxd) - impl.Dgeqrf(m, na, a, lda, tau[:na], work, lwork) - iws = max(iws, int(work[0])) - if na < n { - impl.Dormqr(blas.Left, blas.Trans, m, n-na, na, a, lda, tau[:na], a[na:], lda, - work, lwork) - iws = max(iws, int(work[0])) - } - } - - if nfxd >= minmn { - work[0] = float64(iws) - return - } - - // Factorize free columns. - sm := m - nfxd - sn := n - nfxd - sminmn := minmn - nfxd - - // Determine the block size. - nb = impl.Ilaenv(inb, "DGEQRF", " ", sm, sn, -1, -1) - nbmin := 2 - nx := 0 - - if 1 < nb && nb < sminmn { - // Determine when to cross over from blocked to unblocked code. - nx = max(0, impl.Ilaenv(ixover, "DGEQRF", " ", sm, sn, -1, -1)) - - if nx < sminmn { - // Determine if workspace is large enough for blocked code. - minws := 2*sn + (sn+1)*nb - iws = max(iws, minws) - if lwork < minws { - // Not enough workspace to use optimal nb. Reduce - // nb and determine the minimum value of nb. - nb = (lwork - 2*sn) / (sn + 1) - nbmin = max(2, impl.Ilaenv(inbmin, "DGEQRF", " ", sm, sn, -1, -1)) - } - } - } - - // Initialize partial column norms. - // The first n elements of work store the exact column norms. - for j := nfxd; j < n; j++ { - work[j] = bi.Dnrm2(sm, a[nfxd*lda+j:], lda) - work[n+j] = work[j] - } - j := nfxd - if nbmin <= nb && nb < sminmn && nx < sminmn { - // Use blocked code initially. - - // Compute factorization. - var fjb int - for topbmn := minmn - nx; j < topbmn; j += fjb { - jb := min(nb, topbmn-j) - - // Factorize jb columns among columns j:n. - fjb = impl.Dlaqps(m, n-j, j, jb, a[j:], lda, jpvt[j:], tau[j:], - work[j:n], work[j+n:2*n], work[2*n:2*n+jb], work[2*n+jb:], jb) - } - } - - // Use unblocked code to factor the last or only block. - if j < minmn { - impl.Dlaqp2(m, n-j, j, a[j:], lda, jpvt[j:], tau[j:], - work[j:n], work[j+n:2*n], work[2*n:]) - } - - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go deleted file mode 100644 index 4d1a4b3b..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dgeqr2 computes a QR factorization of the m×n matrix A. -// -// In a QR factorization, Q is an m×m orthonormal matrix, and R is an -// upper triangular m×n matrix. -// -// A is modified to contain the information to construct Q and R. -// The upper triangle of a contains the matrix R. The lower triangular elements -// (not including the diagonal) contain the elementary reflectors. tau is modified -// to contain the reflector scales. tau must have length min(m,n), and -// this function will panic otherwise. -// -// The ith elementary reflector can be explicitly constructed by first extracting -// the -// -// v[j] = 0 j < i -// v[j] = 1 j == i -// v[j] = a[j*lda+i] j > i -// -// and computing H_i = I - tau[i] * v * vᵀ. -// -// The orthonormal matrix Q can be constructed from a product of these elementary -// reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). -// -// work is temporary storage of length at least n and this function will panic otherwise. -// -// Dgeqr2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []float64) { - // TODO(btracey): This is oriented such that columns of a are eliminated. - // This likely could be re-arranged to take better advantage of row-major - // storage. - - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case len(work) < n: - panic(shortWork) - } - - // Quick return if possible. - k := min(m, n) - if k == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) != k: - panic(badLenTau) - } - - for i := 0; i < k; i++ { - // Generate elementary reflector H_i. - a[i*lda+i], tau[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min((i+1), m-1)*lda+i:], lda) - if i < n-1 { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(blas.Left, m-i, n-i-1, - a[i*lda+i:], lda, - tau[i], - a[i*lda+i+1:], lda, - work) - a[i*lda+i] = aii - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go deleted file mode 100644 index 2bcbde58..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dgeqrf computes the QR factorization of the m×n matrix A using a blocked -// algorithm. See the documentation for Dgeqr2 for a description of the -// parameters at entry and exit. -// -// work is temporary storage, and lwork specifies the usable memory length. -// The length of work must be at least max(1, lwork) and lwork must be -1 -// or at least n, otherwise this function will panic. -// Dgeqrf is a blocked QR factorization, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Dgeqrf, -// the optimal work length will be stored into work[0]. -// -// tau must have length min(m,n), and this function will panic otherwise. -func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, n) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - k := min(m, n) - if k == 0 { - work[0] = 1 - return - } - - // nb is the optimal blocksize, i.e. the number of columns transformed at a time. - nb := impl.Ilaenv(1, "DGEQRF", " ", m, n, -1, -1) - if lwork == -1 { - work[0] = float64(n * nb) - return - } - - if len(a) < (m-1)*lda+n { - panic(shortA) - } - if len(tau) != k { - panic(badLenTau) - } - - nbmin := 2 // Minimal block size. - var nx int // Use unblocked (unless changed in the next for loop) - iws := n - // Only consider blocked if the suggested block size is > 1 and the - // number of rows or columns is sufficiently large. - if 1 < nb && nb < k { - // nx is the block size at which the code switches from blocked - // to unblocked. - nx = max(0, impl.Ilaenv(3, "DGEQRF", " ", m, n, -1, -1)) - if k > nx { - iws = n * nb - if lwork < iws { - // Not enough workspace to use the optimal block - // size. Get the minimum block size instead. - nb = lwork / n - nbmin = max(2, impl.Ilaenv(2, "DGEQRF", " ", m, n, -1, -1)) - } - } - } - - // Compute QR using a blocked algorithm. - var i int - if nbmin <= nb && nb < k && nx < k { - ldwork := nb - for i = 0; i < k-nx; i += nb { - ib := min(k-i, nb) - // Compute the QR factorization of the current block. - impl.Dgeqr2(m-i, ib, a[i*lda+i:], lda, tau[i:i+ib], work) - if i+ib < n { - // Form the triangular factor of the block reflector and apply Hᵀ - // In Dlarft, work becomes the T matrix. - impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, - a[i*lda+i:], lda, - tau[i:], - work, ldwork) - impl.Dlarfb(blas.Left, blas.Trans, lapack.Forward, lapack.ColumnWise, - m-i, n-i-ib, ib, - a[i*lda+i:], lda, - work, ldwork, - a[i*lda+i+ib:], lda, - work[ib*ldwork:], ldwork) - } - } - } - // Call unblocked code on the remaining columns. - if i < k { - impl.Dgeqr2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) - } - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go deleted file mode 100644 index 44ca1bc1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dgerq2 computes an RQ factorization of the m×n matrix A, -// -// A = R * Q. -// -// On exit, if m <= n, the upper triangle of the subarray -// A[0:m, n-m:n] contains the m×m upper triangular matrix R. -// If m >= n, the elements on and above the (m-n)-th subdiagonal -// contain the m×n upper trapezoidal matrix R. -// The remaining elements, with tau, represent the -// orthogonal matrix Q as a product of min(m,n) elementary -// reflectors. -// -// The matrix Q is represented as a product of elementary reflectors -// -// Q = H_0 H_1 . . . H_{min(m,n)-1}. -// -// Each H(i) has the form -// -// H_i = I - tau_i * v * vᵀ -// -// where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], -// v[n-k+i:n] = 0 and v[n-k+i] = 1. -// -// tau must have length min(m,n) and work must have length m, otherwise -// Dgerq2 will panic. -// -// Dgerq2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgerq2(m, n int, a []float64, lda int, tau, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case len(work) < m: - panic(shortWork) - } - - // Quick return if possible. - k := min(m, n) - if k == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - } - - for i := k - 1; i >= 0; i-- { - // Generate elementary reflector H[i] to annihilate - // A[m-k+i, 0:n-k+i-1]. - mki := m - k + i - nki := n - k + i - var aii float64 - aii, tau[i] = impl.Dlarfg(nki+1, a[mki*lda+nki], a[mki*lda:], 1) - - // Apply H[i] to A[0:m-k+i-1, 0:n-k+i] from the right. - a[mki*lda+nki] = 1 - impl.Dlarf(blas.Right, mki, nki+1, a[mki*lda:], 1, tau[i], a, lda, work) - a[mki*lda+nki] = aii - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go deleted file mode 100644 index fe010b47..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dgerqf computes an RQ factorization of the m×n matrix A, -// -// A = R * Q. -// -// On exit, if m <= n, the upper triangle of the subarray -// A[0:m, n-m:n] contains the m×m upper triangular matrix R. -// If m >= n, the elements on and above the (m-n)-th subdiagonal -// contain the m×n upper trapezoidal matrix R. -// The remaining elements, with tau, represent the -// orthogonal matrix Q as a product of min(m,n) elementary -// reflectors. -// -// The matrix Q is represented as a product of elementary reflectors -// -// Q = H_0 H_1 . . . H_{min(m,n)-1}. -// -// Each H(i) has the form -// -// H_i = I - tau_i * v * vᵀ -// -// where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], -// v[n-k+i:n] = 0 and v[n-k+i] = 1. -// -// tau must have length min(m,n), work must have length max(1, lwork), -// and lwork must be -1 or at least max(1, m), otherwise Dgerqf will panic. -// On exit, work[0] will contain the optimal length for work. -// -// Dgerqf is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, m) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - k := min(m, n) - if k == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(1, "DGERQF", " ", m, n, -1, -1) - if lwork == -1 { - work[0] = float64(m * nb) - return - } - - if len(a) < (m-1)*lda+n { - panic(shortA) - } - if len(tau) != k { - panic(badLenTau) - } - - nbmin := 2 - nx := 1 - iws := m - var ldwork int - if 1 < nb && nb < k { - // Determine when to cross over from blocked to unblocked code. - nx = max(0, impl.Ilaenv(3, "DGERQF", " ", m, n, -1, -1)) - if nx < k { - // Determine whether workspace is large enough for blocked code. - iws = m * nb - if lwork < iws { - // Not enough workspace to use optimal nb. Reduce - // nb and determine the minimum value of nb. - nb = lwork / m - nbmin = max(2, impl.Ilaenv(2, "DGERQF", " ", m, n, -1, -1)) - } - ldwork = nb - } - } - - var mu, nu int - if nbmin <= nb && nb < k && nx < k { - // Use blocked code initially. - // The last kk rows are handled by the block method. - ki := ((k - nx - 1) / nb) * nb - kk := min(k, ki+nb) - - var i int - for i = k - kk + ki; i >= k-kk; i -= nb { - ib := min(k-i, nb) - - // Compute the RQ factorization of the current block - // A[m-k+i:m-k+i+ib-1, 0:n-k+i+ib-1]. - impl.Dgerq2(ib, n-k+i+ib, a[(m-k+i)*lda:], lda, tau[i:], work) - if m-k+i > 0 { - // Form the triangular factor of the block reflector - // H = H_{i+ib-1} . . . H_{i+1} H_i. - impl.Dlarft(lapack.Backward, lapack.RowWise, - n-k+i+ib, ib, a[(m-k+i)*lda:], lda, tau[i:], - work, ldwork) - - // Apply H to A[0:m-k+i-1, 0:n-k+i+ib-1] from the right. - impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Backward, lapack.RowWise, - m-k+i, n-k+i+ib, ib, a[(m-k+i)*lda:], lda, - work, ldwork, - a, lda, - work[ib*ldwork:], ldwork) - } - } - mu = m - k + i + nb - nu = n - k + i + nb - } else { - mu = m - nu = n - } - - // Use unblocked code to factor the last or only block. - if mu > 0 && nu > 0 { - impl.Dgerq2(mu, nu, a, lda, tau, work) - } - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesc2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgesc2.go deleted file mode 100644 index b2201085..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesc2.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgesc2 solves a system of linear equations -// -// A * x = scale * b -// -// with a general n×n matrix A represented by the LU factorization with complete -// pivoting -// -// A = P * L * U * Q -// -// as computed by Dgetc2. -// -// On entry, rhs contains the right hand side vector b. On return, it is -// overwritten with the solution vector x. -// -// Dgesc2 returns a scale factor -// -// 0 <= scale <= 1 -// -// chosen to prevent overflow in the solution. -// -// Dgesc2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgesc2(n int, a []float64, lda int, rhs []float64, ipiv, jpiv []int) (scale float64) { - switch { - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 0 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(rhs) < n: - panic(shortRHS) - case len(ipiv) != n: - panic(badLenIpiv) - case len(jpiv) != n: - panic(badLenJpiv) - } - - const smlnum = dlamchS / dlamchP - - // Apply permutations ipiv to rhs. - impl.Dlaswp(1, rhs, 1, 0, n-1, ipiv[:n], 1) - - // Solve for L part. - for i := 0; i < n-1; i++ { - for j := i + 1; j < n; j++ { - rhs[j] -= float64(a[j*lda+i] * rhs[i]) - } - } - - // Check for scaling. - scale = 1.0 - bi := blas64.Implementation() - i := bi.Idamax(n, rhs, 1) - if 2*smlnum*math.Abs(rhs[i]) > math.Abs(a[(n-1)*lda+(n-1)]) { - temp := 0.5 / math.Abs(rhs[i]) - bi.Dscal(n, temp, rhs, 1) - scale *= temp - } - - // Solve for U part. - for i := n - 1; i >= 0; i-- { - temp := 1.0 / a[i*lda+i] - rhs[i] *= temp - for j := i + 1; j < n; j++ { - rhs[i] -= float64(rhs[j] * (a[i*lda+j] * temp)) - } - } - - // Apply permutations jpiv to the solution (rhs). - impl.Dlaswp(1, rhs, 1, 0, n-1, jpiv[:n], -1) - - return scale -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesv.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgesv.go deleted file mode 100644 index 0be4414c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesv.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dgesv computes the solution to a real system of linear equations -// -// A * X = B -// -// where A is an n×n matrix and X and B are n×nrhs matrices. -// -// The LU decomposition with partial pivoting and row interchanges is used to -// factor A as -// -// A = P * L * U -// -// where P is a permutation matrix, L is unit lower triangular, and U is upper -// triangular. On return, the factors L and U are stored in a; the unit diagonal -// elements of L are not stored. The row pivot indices that define the -// permutation matrix P are stored in ipiv. -// -// The factored form of A is then used to solve the system of equations A * X = -// B. On entry, b contains the right hand side matrix B. On return, if ok is -// true, b contains the solution matrix X. -func (impl Implementation) Dgesv(n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) (ok bool) { - switch { - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, nrhs): - panic(badLdB) - } - - // Quick return if possible. - if n == 0 || nrhs == 0 { - return true - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortAB) - case len(ipiv) != n: - panic(badLenIpiv) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - } - - ok = impl.Dgetrf(n, n, a, lda, ipiv) - if ok { - impl.Dgetrs(blas.NoTrans, n, nrhs, a, lda, ipiv, b, ldb) - } - - return ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go deleted file mode 100644 index 97da749b..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go +++ /dev/null @@ -1,1378 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -const noSVDO = "dgesvd: not coded for overwrite" - -// Dgesvd computes the singular value decomposition of the input matrix A. -// -// The singular value decomposition is -// -// A = U * Sigma * Vᵀ -// -// where Sigma is an m×n diagonal matrix containing the singular values of A, -// U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first -// min(m,n) columns of U and V are the left and right singular vectors of A -// respectively. -// -// jobU and jobVT are options for computing the singular vectors. The behavior -// is as follows -// -// jobU == lapack.SVDAll All m columns of U are returned in u -// jobU == lapack.SVDStore The first min(m,n) columns are returned in u -// jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a -// jobU == lapack.SVDNone The columns of U are not computed. -// -// The behavior is the same for jobVT and the rows of Vᵀ. At most one of jobU -// and jobVT can equal lapack.SVDOverwrite, and Dgesvd will panic otherwise. -// -// On entry, a contains the data for the m×n matrix A. During the call to Dgesvd -// the data is overwritten. On exit, A contains the appropriate singular vectors -// if either job is lapack.SVDOverwrite. -// -// s is a slice of length at least min(m,n) and on exit contains the singular -// values in decreasing order. -// -// u contains the left singular vectors on exit, stored column-wise. If -// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDStore u is -// of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is -// not used. -// -// vt contains the left singular vectors on exit, stored row-wise. If -// jobV == lapack.SVDAll, vt is of size n×n. If jobVT == lapack.SVDStore vt is -// of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is -// not used. -// -// work is a slice for storing temporary memory, and lwork is the usable size of -// the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)). -// If lwork == -1, instead of performing Dgesvd, the optimal work length will be -// stored into work[0]. Dgesvd will panic if the working memory has insufficient -// storage. -// -// Dgesvd returns whether the decomposition successfully completed. -func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) { - if jobU == lapack.SVDOverwrite || jobVT == lapack.SVDOverwrite { - panic(noSVDO) - } - - wantua := jobU == lapack.SVDAll - wantus := jobU == lapack.SVDStore - wantuas := wantua || wantus - wantuo := jobU == lapack.SVDOverwrite - wantun := jobU == lapack.SVDNone - if !(wantua || wantus || wantuo || wantun) { - panic(badSVDJob) - } - - wantva := jobVT == lapack.SVDAll - wantvs := jobVT == lapack.SVDStore - wantvas := wantva || wantvs - wantvo := jobVT == lapack.SVDOverwrite - wantvn := jobVT == lapack.SVDNone - if !(wantva || wantvs || wantvo || wantvn) { - panic(badSVDJob) - } - - if wantuo && wantvo { - panic(bothSVDOver) - } - - minmn := min(m, n) - minwork := 1 - if minmn > 0 { - minwork = max(3*minmn+max(m, n), 5*minmn) - } - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case ldu < 1, wantua && ldu < m, wantus && ldu < minmn: - panic(badLdU) - case ldvt < 1 || (wantvas && ldvt < n): - panic(badLdVT) - case lwork < minwork && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if minmn == 0 { - work[0] = 1 - return true - } - - // Compute optimal workspace size for subroutines. - opts := string(jobU) + string(jobVT) - mnthr := impl.Ilaenv(6, "DGESVD", opts, m, n, 0, 0) - maxwrk := 1 - var wrkbl, bdspac int - if m >= n { - bdspac = 5 * n - impl.Dgeqrf(m, n, a, lda, nil, work, -1) - lwork_dgeqrf := int(work[0]) - - impl.Dorgqr(m, n, n, a, lda, nil, work, -1) - lwork_dorgqr_n := int(work[0]) - impl.Dorgqr(m, m, n, a, lda, nil, work, -1) - lwork_dorgqr_m := int(work[0]) - - impl.Dgebrd(n, n, a, lda, s, nil, nil, nil, work, -1) - lwork_dgebrd := int(work[0]) - - impl.Dorgbr(lapack.GeneratePT, n, n, n, a, lda, nil, work, -1) - lwork_dorgbr_p := int(work[0]) - - impl.Dorgbr(lapack.GenerateQ, n, n, n, a, lda, nil, work, -1) - lwork_dorgbr_q := int(work[0]) - - if m >= mnthr { - if wantun { - // Path 1 (m much larger than n, jobU == None) - maxwrk = n + lwork_dgeqrf - maxwrk = max(maxwrk, 3*n+lwork_dgebrd) - if wantvo || wantvas { - maxwrk = max(maxwrk, 3*n+lwork_dorgbr_p) - } - maxwrk = max(maxwrk, bdspac) - } else if wantuo && wantvn { - // Path 2 (m much larger than n, jobU == Overwrite, jobVT == None) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_n) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = max(n*n+wrkbl, n*n+m*n+n) - } else if wantuo && wantvas { - // Path 3 (m much larger than n, jobU == Overwrite, jobVT == Store or All) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_n) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = max(n*n+wrkbl, n*n+m*n+n) - } else if wantus && wantvn { - // Path 4 (m much larger than n, jobU == Store, jobVT == None) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_n) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = n*n + wrkbl - } else if wantus && wantvo { - // Path 5 (m much larger than n, jobU == Store, jobVT == Overwrite) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_n) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = 2*n*n + wrkbl - } else if wantus && wantvas { - // Path 6 (m much larger than n, jobU == Store, jobVT == Store or All) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_n) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = n*n + wrkbl - } else if wantua && wantvn { - // Path 7 (m much larger than n, jobU == All, jobVT == None) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_m) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = n*n + wrkbl - } else if wantua && wantvo { - // Path 8 (m much larger than n, jobU == All, jobVT == Overwrite) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_m) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = 2*n*n + wrkbl - } else if wantua && wantvas { - // Path 9 (m much larger than n, jobU == All, jobVT == Store or All) - wrkbl = n + lwork_dgeqrf - wrkbl = max(wrkbl, n+lwork_dorgqr_m) - wrkbl = max(wrkbl, 3*n+lwork_dgebrd) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) - wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = n*n + wrkbl - } - } else { - // Path 10 (m at least n, but not much larger) - impl.Dgebrd(m, n, a, lda, s, nil, nil, nil, work, -1) - lwork_dgebrd := int(work[0]) - maxwrk = 3*n + lwork_dgebrd - if wantus || wantuo { - impl.Dorgbr(lapack.GenerateQ, m, n, n, a, lda, nil, work, -1) - lwork_dorgbr_q = int(work[0]) - maxwrk = max(maxwrk, 3*n+lwork_dorgbr_q) - } - if wantua { - impl.Dorgbr(lapack.GenerateQ, m, m, n, a, lda, nil, work, -1) - lwork_dorgbr_q := int(work[0]) - maxwrk = max(maxwrk, 3*n+lwork_dorgbr_q) - } - if !wantvn { - maxwrk = max(maxwrk, 3*n+lwork_dorgbr_p) - } - maxwrk = max(maxwrk, bdspac) - } - } else { - bdspac = 5 * m - - impl.Dgelqf(m, n, a, lda, nil, work, -1) - lwork_dgelqf := int(work[0]) - - impl.Dorglq(n, n, m, nil, n, nil, work, -1) - lwork_dorglq_n := int(work[0]) - impl.Dorglq(m, n, m, a, lda, nil, work, -1) - lwork_dorglq_m := int(work[0]) - - impl.Dgebrd(m, m, a, lda, s, nil, nil, nil, work, -1) - lwork_dgebrd := int(work[0]) - - impl.Dorgbr(lapack.GeneratePT, m, m, m, a, n, nil, work, -1) - lwork_dorgbr_p := int(work[0]) - - impl.Dorgbr(lapack.GenerateQ, m, m, m, a, n, nil, work, -1) - lwork_dorgbr_q := int(work[0]) - - if n >= mnthr { - if wantvn { - // Path 1t (n much larger than m, jobVT == None) - maxwrk = m + lwork_dgelqf - maxwrk = max(maxwrk, 3*m+lwork_dgebrd) - if wantuo || wantuas { - maxwrk = max(maxwrk, 3*m+lwork_dorgbr_q) - } - maxwrk = max(maxwrk, bdspac) - } else if wantvo && wantun { - // Path 2t (n much larger than m, jobU == None, jobVT == Overwrite) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_m) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = max(m*m+wrkbl, m*m+m*n+m) - } else if wantvo && wantuas { - // Path 3t (n much larger than m, jobU == Store or All, jobVT == Overwrite) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_m) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = max(m*m+wrkbl, m*m+m*n+m) - } else if wantvs && wantun { - // Path 4t (n much larger than m, jobU == None, jobVT == Store) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_m) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = m*m + wrkbl - } else if wantvs && wantuo { - // Path 5t (n much larger than m, jobU == Overwrite, jobVT == Store) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_m) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = 2*m*m + wrkbl - } else if wantvs && wantuas { - // Path 6t (n much larger than m, jobU == Store or All, jobVT == Store) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_m) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = m*m + wrkbl - } else if wantva && wantun { - // Path 7t (n much larger than m, jobU== None, jobVT == All) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_n) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, bdspac) - maxwrk = m*m + wrkbl - } else if wantva && wantuo { - // Path 8t (n much larger than m, jobU == Overwrite, jobVT == All) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_n) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = 2*m*m + wrkbl - } else if wantva && wantuas { - // Path 9t (n much larger than m, jobU == Store or All, jobVT == All) - wrkbl = m + lwork_dgelqf - wrkbl = max(wrkbl, m+lwork_dorglq_n) - wrkbl = max(wrkbl, 3*m+lwork_dgebrd) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) - wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) - wrkbl = max(wrkbl, bdspac) - maxwrk = m*m + wrkbl - } - } else { - // Path 10t (n greater than m, but not much larger) - impl.Dgebrd(m, n, a, lda, s, nil, nil, nil, work, -1) - lwork_dgebrd = int(work[0]) - maxwrk = 3*m + lwork_dgebrd - if wantvs || wantvo { - impl.Dorgbr(lapack.GeneratePT, m, n, m, a, n, nil, work, -1) - lwork_dorgbr_p = int(work[0]) - maxwrk = max(maxwrk, 3*m+lwork_dorgbr_p) - } - if wantva { - impl.Dorgbr(lapack.GeneratePT, n, n, m, a, n, nil, work, -1) - lwork_dorgbr_p = int(work[0]) - maxwrk = max(maxwrk, 3*m+lwork_dorgbr_p) - } - if !wantun { - maxwrk = max(maxwrk, 3*m+lwork_dorgbr_q) - } - maxwrk = max(maxwrk, bdspac) - } - } - - maxwrk = max(maxwrk, minwork) - if lwork == -1 { - work[0] = float64(maxwrk) - return true - } - - if len(a) < (m-1)*lda+n { - panic(shortA) - } - if len(s) < minmn { - panic(shortS) - } - if (len(u) < (m-1)*ldu+m && wantua) || (len(u) < (m-1)*ldu+minmn && wantus) { - panic(shortU) - } - if (len(vt) < (n-1)*ldvt+n && wantva) || (len(vt) < (minmn-1)*ldvt+n && wantvs) { - panic(shortVT) - } - - // Perform decomposition. - eps := dlamchE - smlnum := math.Sqrt(dlamchS) / eps - bignum := 1 / smlnum - - // Scale A if max element outside range [smlnum, bignum]. - anrm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, nil) - var iscl bool - if anrm > 0 && anrm < smlnum { - iscl = true - impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, m, n, a, lda) - } else if anrm > bignum { - iscl = true - impl.Dlascl(lapack.General, 0, 0, anrm, bignum, m, n, a, lda) - } - - bi := blas64.Implementation() - var ie int - if m >= n { - // If A has sufficiently more rows than columns, use the QR decomposition. - if m >= mnthr { - // m >> n - if wantun { - // Path 1. - itau := 0 - iwork := itau + n - - // Compute A = Q * R. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - - // Zero out below R. - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) - ie = 0 - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - // Bidiagonalize R in A. - impl.Dgebrd(n, n, a, lda, s, work[ie:], work[itauq:], - work[itaup:], work[iwork:], lwork-iwork) - ncvt := 0 - if wantvo || wantvas { - impl.Dorgbr(lapack.GeneratePT, n, n, n, a, lda, work[itaup:], - work[iwork:], lwork-iwork) - ncvt = n - } - iwork = ie + n - - // Perform bidiagonal QR iteration computing right singular vectors - // of A in A if desired. - ok = impl.Dbdsqr(blas.Upper, n, ncvt, 0, 0, s, work[ie:], - a, lda, work, 1, work, 1, work[iwork:]) - - // If right singular vectors desired in VT, copy them there. - if wantvas { - impl.Dlacpy(blas.All, n, n, a, lda, vt, ldvt) - } - } else if wantuo && wantvn { - // Path 2 - panic(noSVDO) - } else if wantuo && wantvas { - // Path 3 - panic(noSVDO) - } else if wantus { - if wantvn { - // Path 4 - if lwork >= n*n+max(4*n, bdspac) { - // Sufficient workspace for a fast algorithm. - ir := 0 - var ldworkr int - if lwork >= wrkbl+lda*n { - ldworkr = lda - } else { - ldworkr = n - } - itau := ir + ldworkr*n - iwork := itau + n - // Compute A = Q * R. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - - // Copy R to work[ir:], zeroing out below it. - impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr) - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr) - - // Generate Q in A. - impl.Dorgqr(m, n, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - ie := itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Bidiagonalize R in work[ir:]. - impl.Dgebrd(n, n, work[ir:], ldworkr, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Generate left vectors bidiagonalizing R in work[ir:]. - impl.Dorgbr(lapack.GenerateQ, n, n, n, work[ir:], ldworkr, - work[itauq:], work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left singular - // vectors of R in work[ir:]. - ok = impl.Dbdsqr(blas.Upper, n, 0, n, 0, s, work[ie:], work, 1, - work[ir:], ldworkr, work, 1, work[iwork:]) - - // Multiply Q in A by left singular vectors of R in - // work[ir:], storing result in U. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, a, lda, - work[ir:], ldworkr, 0, u, ldu) - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + n - - // Compute A = Q*R, copying result to U. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) - - // Generate Q in U. - impl.Dorgqr(m, n, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork) - ie := itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Zero out below R in A. - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) - - // Bidiagonalize R in A. - impl.Dgebrd(n, n, a, lda, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Multiply Q in U by left vectors bidiagonalizing R. - impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, - a, lda, work[itauq:], u, ldu, work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left - // singular vectors of A in U. - ok = impl.Dbdsqr(blas.Upper, n, 0, m, 0, s, work[ie:], work, 1, - u, ldu, work, 1, work[iwork:]) - } - } else if wantvo { - // Path 5 - panic(noSVDO) - } else if wantvas { - // Path 6 - if lwork >= n*n+max(4*n, bdspac) { - // Sufficient workspace for a fast algorithm. - iu := 0 - var ldworku int - if lwork >= wrkbl+lda*n { - ldworku = lda - } else { - ldworku = n - } - itau := iu + ldworku*n - iwork := itau + n - - // Compute A = Q * R. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - // Copy R to work[iu:], zeroing out below it. - impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku) - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku) - - // Generate Q in A. - impl.Dorgqr(m, n, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - - ie := itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Bidiagonalize R in work[iu:], copying result to VT. - impl.Dgebrd(n, n, work[iu:], ldworku, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Upper, n, n, work[iu:], ldworku, vt, ldvt) - - // Generate left bidiagonalizing vectors in work[iu:]. - impl.Dorgbr(lapack.GenerateQ, n, n, n, work[iu:], ldworku, - work[itauq:], work[iwork:], lwork-iwork) - - // Generate right bidiagonalizing vectors in VT. - impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, - work[itaup:], work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left singular - // vectors of R in work[iu:], and computing right singular - // vectors of R in VT. - ok = impl.Dbdsqr(blas.Upper, n, n, n, 0, s, work[ie:], - vt, ldvt, work[iu:], ldworku, work, 1, work[iwork:]) - - // Multiply Q in A by left singular vectors of R in - // work[iu:], storing result in U. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, a, lda, - work[iu:], ldworku, 0, u, ldu) - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + n - - // Compute A = Q * R, copying result to U. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) - - // Generate Q in U. - impl.Dorgqr(m, n, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork) - - // Copy R to VT, zeroing out below it. - impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, vt[ldvt:], ldvt) - - ie := itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Bidiagonalize R in VT. - impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Multiply Q in U by left bidiagonalizing vectors in VT. - impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, - vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) - - // Generate right bidiagonalizing vectors in VT. - impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, - work[itaup:], work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left singular - // vectors of A in U and computing right singular vectors - // of A in VT. - ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], - vt, ldvt, u, ldu, work, 1, work[iwork:]) - } - } - } else if wantua { - if wantvn { - // Path 7 - if lwork >= n*n+max(max(n+m, 4*n), bdspac) { - // Sufficient workspace for a fast algorithm. - ir := 0 - var ldworkr int - if lwork >= wrkbl+lda*n { - ldworkr = lda - } else { - ldworkr = n - } - itau := ir + ldworkr*n - iwork := itau + n - - // Compute A = Q*R, copying result to U. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) - - // Copy R to work[ir:], zeroing out below it. - impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr) - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr) - - // Generate Q in U. - impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork) - ie := itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Bidiagonalize R in work[ir:]. - impl.Dgebrd(n, n, work[ir:], ldworkr, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Generate left bidiagonalizing vectors in work[ir:]. - impl.Dorgbr(lapack.GenerateQ, n, n, n, work[ir:], ldworkr, - work[itauq:], work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left singular - // vectors of R in work[ir:]. - ok = impl.Dbdsqr(blas.Upper, n, 0, n, 0, s, work[ie:], work, 1, - work[ir:], ldworkr, work, 1, work[iwork:]) - - // Multiply Q in U by left singular vectors of R in - // work[ir:], storing result in A. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, u, ldu, - work[ir:], ldworkr, 0, a, lda) - - // Copy left singular vectors of A from A to U. - impl.Dlacpy(blas.All, m, n, a, lda, u, ldu) - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + n - - // Compute A = Q*R, copying result to U. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) - - // Generate Q in U. - impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork) - ie := itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Zero out below R in A. - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) - - // Bidiagonalize R in A. - impl.Dgebrd(n, n, a, lda, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Multiply Q in U by left bidiagonalizing vectors in A. - impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, - a, lda, work[itauq:], u, ldu, work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left - // singular vectors of A in U. - ok = impl.Dbdsqr(blas.Upper, n, 0, m, 0, s, work[ie:], - work, 1, u, ldu, work, 1, work[iwork:]) - } - } else if wantvo { - // Path 8. - panic(noSVDO) - } else if wantvas { - // Path 9. - if lwork >= n*n+max(max(n+m, 4*n), bdspac) { - // Sufficient workspace for a fast algorithm. - iu := 0 - var ldworku int - if lwork >= wrkbl+lda*n { - ldworku = lda - } else { - ldworku = n - } - itau := iu + ldworku*n - iwork := itau + n - - // Compute A = Q * R, copying result to U. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) - - // Generate Q in U. - impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork) - - // Copy R to work[iu:], zeroing out below it. - impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku) - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku) - - ie = itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Bidiagonalize R in work[iu:], copying result to VT. - impl.Dgebrd(n, n, work[iu:], ldworku, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Upper, n, n, work[iu:], ldworku, vt, ldvt) - - // Generate left bidiagonalizing vectors in work[iu:]. - impl.Dorgbr(lapack.GenerateQ, n, n, n, work[iu:], ldworku, - work[itauq:], work[iwork:], lwork-iwork) - - // Generate right bidiagonalizing vectors in VT. - impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, - work[itaup:], work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left singular - // vectors of R in work[iu:] and computing right - // singular vectors of R in VT. - ok = impl.Dbdsqr(blas.Upper, n, n, n, 0, s, work[ie:], - vt, ldvt, work[iu:], ldworku, work, 1, work[iwork:]) - - // Multiply Q in U by left singular vectors of R in - // work[iu:], storing result in A. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, - u, ldu, work[iu:], ldworku, 0, a, lda) - - // Copy left singular vectors of A from A to U. - impl.Dlacpy(blas.All, m, n, a, lda, u, ldu) - - /* - // Bidiagonalize R in VT. - impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Multiply Q in U by left bidiagonalizing vectors in VT. - impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, - m, n, n, vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) - - // Generate right bidiagonalizing vectors in VT. - impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, - work[itaup:], work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left singular - // vectors of A in U and computing right singular vectors - // of A in VT. - ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], - vt, ldvt, u, ldu, work, 1, work[iwork:]) - */ - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + n - - // Compute A = Q*R, copying result to U. - impl.Dgeqrf(m, n, a, lda, work[itau:itau+n], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) - - // Generate Q in U. - impl.Dorgqr(m, m, n, u, ldu, work[itau:itau+n], work[iwork:], lwork-iwork) - - // Copy R from A to VT, zeroing out below it. - impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) - if n > 1 { - impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, vt[ldvt:], ldvt) - } - - ie := itau - itauq := ie + n - itaup := itauq + n - iwork = itaup + n - - // Bidiagonalize R in VT. - impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Multiply Q in U by left bidiagonalizing vectors in VT. - impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, - m, n, n, vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) - - // Generate right bidiagonizing vectors in VT. - impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, - work[itaup:], work[iwork:], lwork-iwork) - iwork = ie + n - - // Perform bidiagonal QR iteration, computing left singular - // vectors of A in U and computing right singular vectors - // of A in VT. - ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], - vt, ldvt, u, ldu, work, 1, work[iwork:]) - } - } - } - } else { - // Path 10. - // M at least N, but not much larger. - ie = 0 - itauq := ie + n - itaup := itauq + n - iwork := itaup + n - - // Bidiagonalize A. - impl.Dgebrd(m, n, a, lda, s, work[ie:], work[itauq:], - work[itaup:], work[iwork:], lwork-iwork) - if wantuas { - // Left singular vectors are desired in U. Copy result to U and - // generate left biadiagonalizing vectors in U. - impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) - var ncu int - if wantus { - ncu = n - } - if wantua { - ncu = m - } - impl.Dorgbr(lapack.GenerateQ, m, ncu, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) - } - if wantvas { - // Right singular vectors are desired in VT. Copy result to VT and - // generate left biadiagonalizing vectors in VT. - impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) - impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) - } - if wantuo { - panic(noSVDO) - } - if wantvo { - panic(noSVDO) - } - iwork = ie + n - var nru, ncvt int - if wantuas || wantuo { - nru = m - } - if wantun { - nru = 0 - } - if wantvas || wantvo { - ncvt = n - } - if wantvn { - ncvt = 0 - } - if !wantuo && !wantvo { - // Perform bidiagonal QR iteration, if desired, computing left - // singular vectors in U and right singular vectors in VT. - ok = impl.Dbdsqr(blas.Upper, n, ncvt, nru, 0, s, work[ie:], - vt, ldvt, u, ldu, work, 1, work[iwork:]) - } else { - // There will be two branches when the implementation is complete. - panic(noSVDO) - } - } - } else { - // A has more columns than rows. If A has sufficiently more columns than - // rows, first reduce using the LQ decomposition. - if n >= mnthr { - // n >> m. - if wantvn { - // Path 1t. - itau := 0 - iwork := itau + m - - // Compute A = L*Q. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - - // Zero out above L. - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) - ie := 0 - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Bidiagonalize L in A. - impl.Dgebrd(m, m, a, lda, s, work[ie:itauq], - work[itauq:itaup], work[itaup:iwork], work[iwork:], lwork-iwork) - if wantuo || wantuas { - impl.Dorgbr(lapack.GenerateQ, m, m, m, a, lda, - work[itauq:], work[iwork:], lwork-iwork) - } - iwork = ie + m - nru := 0 - if wantuo || wantuas { - nru = m - } - - // Perform bidiagonal QR iteration, computing left singular vectors - // of A in A if desired. - ok = impl.Dbdsqr(blas.Upper, m, 0, nru, 0, s, work[ie:], - work, 1, a, lda, work, 1, work[iwork:]) - - // If left singular vectors desired in U, copy them there. - if wantuas { - impl.Dlacpy(blas.All, m, m, a, lda, u, ldu) - } - } else if wantvo && wantun { - // Path 2t. - panic(noSVDO) - } else if wantvo && wantuas { - // Path 3t. - panic(noSVDO) - } else if wantvs { - if wantun { - // Path 4t. - if lwork >= m*m+max(4*m, bdspac) { - // Sufficient workspace for a fast algorithm. - ir := 0 - var ldworkr int - if lwork >= wrkbl+lda*m { - ldworkr = lda - } else { - ldworkr = m - } - itau := ir + ldworkr*m - iwork := itau + m - - // Compute A = L*Q. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - - // Copy L to work[ir:], zeroing out above it. - impl.Dlacpy(blas.Lower, m, m, a, lda, work[ir:], ldworkr) - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[ir+1:], ldworkr) - - // Generate Q in A. - impl.Dorglq(m, n, m, a, lda, work[itau:], work[iwork:], lwork-iwork) - ie := itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Bidiagonalize L in work[ir:]. - impl.Dgebrd(m, m, work[ir:], ldworkr, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Generate right vectors bidiagonalizing L in work[ir:]. - impl.Dorgbr(lapack.GeneratePT, m, m, m, work[ir:], ldworkr, - work[itaup:], work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing right singular - // vectors of L in work[ir:]. - ok = impl.Dbdsqr(blas.Upper, m, m, 0, 0, s, work[ie:], - work[ir:], ldworkr, work, 1, work, 1, work[iwork:]) - - // Multiply right singular vectors of L in work[ir:] by - // Q in A, storing result in VT. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, - work[ir:], ldworkr, a, lda, 0, vt, ldvt) - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + m - - // Compute A = L*Q. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - - // Copy result to VT. - impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) - - // Generate Q in VT. - impl.Dorglq(m, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) - ie := itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Zero out above L in A. - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) - - // Bidiagonalize L in A. - impl.Dgebrd(m, m, a, lda, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Multiply right vectors bidiagonalizing L by Q in VT. - impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, - a, lda, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing right - // singular vectors of A in VT. - ok = impl.Dbdsqr(blas.Upper, m, n, 0, 0, s, work[ie:], - vt, ldvt, work, 1, work, 1, work[iwork:]) - } - } else if wantuo { - // Path 5t. - panic(noSVDO) - } else if wantuas { - // Path 6t. - if lwork >= m*m+max(4*m, bdspac) { - // Sufficient workspace for a fast algorithm. - iu := 0 - var ldworku int - if lwork >= wrkbl+lda*m { - ldworku = lda - } else { - ldworku = m - } - itau := iu + ldworku*m - iwork := itau + m - - // Compute A = L*Q. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - - // Copy L to work[iu:], zeroing out above it. - impl.Dlacpy(blas.Lower, m, m, a, lda, work[iu:], ldworku) - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[iu+1:], ldworku) - - // Generate Q in A. - impl.Dorglq(m, n, m, a, lda, work[itau:], work[iwork:], lwork-iwork) - ie := itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Bidiagonalize L in work[iu:], copying result to U. - impl.Dgebrd(m, m, work[iu:], ldworku, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, m, work[iu:], ldworku, u, ldu) - - // Generate right bidiagionalizing vectors in work[iu:]. - impl.Dorgbr(lapack.GeneratePT, m, m, m, work[iu:], ldworku, - work[itaup:], work[iwork:], lwork-iwork) - - // Generate left bidiagonalizing vectors in U. - impl.Dorgbr(lapack.GenerateQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing left singular - // vectors of L in U and computing right singular vectors of - // L in work[iu:]. - ok = impl.Dbdsqr(blas.Upper, m, m, m, 0, s, work[ie:], - work[iu:], ldworku, u, ldu, work, 1, work[iwork:]) - - // Multiply right singular vectors of L in work[iu:] by - // Q in A, storing result in VT. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, - work[iu:], ldworku, a, lda, 0, vt, ldvt) - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + m - - // Compute A = L*Q, copying result to VT. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) - - // Generate Q in VT. - impl.Dorglq(m, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) - - // Copy L to U, zeroing out above it. - impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, u[1:], ldu) - - ie := itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Bidiagonalize L in U. - impl.Dgebrd(m, m, u, ldu, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Multiply right bidiagonalizing vectors in U by Q in VT. - impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, - u, ldu, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) - - // Generate left bidiagonalizing vectors in U. - impl.Dorgbr(lapack.GenerateQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing left singular - // vectors of A in U and computing right singular vectors - // of A in VT. - ok = impl.Dbdsqr(blas.Upper, m, n, m, 0, s, work[ie:], vt, ldvt, - u, ldu, work, 1, work[iwork:]) - } - } - } else if wantva { - if wantun { - // Path 7t. - if lwork >= m*m+max(max(n+m, 4*m), bdspac) { - // Sufficient workspace for a fast algorithm. - ir := 0 - var ldworkr int - if lwork >= wrkbl+lda*m { - ldworkr = lda - } else { - ldworkr = m - } - itau := ir + ldworkr*m - iwork := itau + m - - // Compute A = L*Q, copying result to VT. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) - - // Copy L to work[ir:], zeroing out above it. - impl.Dlacpy(blas.Lower, m, m, a, lda, work[ir:], ldworkr) - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[ir+1:], ldworkr) - - // Generate Q in VT. - impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) - - ie := itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Bidiagonalize L in work[ir:]. - impl.Dgebrd(m, m, work[ir:], ldworkr, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - - // Generate right bidiagonalizing vectors in work[ir:]. - impl.Dorgbr(lapack.GeneratePT, m, m, m, work[ir:], ldworkr, - work[itaup:], work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing right - // singular vectors of L in work[ir:]. - ok = impl.Dbdsqr(blas.Upper, m, m, 0, 0, s, work[ie:], - work[ir:], ldworkr, work, 1, work, 1, work[iwork:]) - - // Multiply right singular vectors of L in work[ir:] by - // Q in VT, storing result in A. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, - work[ir:], ldworkr, vt, ldvt, 0, a, lda) - - // Copy right singular vectors of A from A to VT. - impl.Dlacpy(blas.All, m, n, a, lda, vt, ldvt) - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + m - // Compute A = L * Q, copying result to VT. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) - - // Generate Q in VT. - impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) - - ie := itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Zero out above L in A. - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) - - // Bidiagonalize L in A. - impl.Dgebrd(m, m, a, lda, s, work[ie:], work[itauq:], - work[itaup:], work[iwork:], lwork-iwork) - - // Multiply right bidiagonalizing vectors in A by Q in VT. - impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, - a, lda, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing right singular - // vectors of A in VT. - ok = impl.Dbdsqr(blas.Upper, m, n, 0, 0, s, work[ie:], - vt, ldvt, work, 1, work, 1, work[iwork:]) - } - } else if wantuo { - panic(noSVDO) - } else if wantuas { - // Path 9t. - if lwork >= m*m+max(max(m+n, 4*m), bdspac) { - // Sufficient workspace for a fast algorithm. - iu := 0 - - var ldworku int - if lwork >= wrkbl+lda*m { - ldworku = lda - } else { - ldworku = m - } - itau := iu + ldworku*m - iwork := itau + m - - // Generate A = L * Q copying result to VT. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) - - // Generate Q in VT. - impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) - - // Copy L to work[iu:], zeroing out above it. - impl.Dlacpy(blas.Lower, m, m, a, lda, work[iu:], ldworku) - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[iu+1:], ldworku) - ie = itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Bidiagonalize L in work[iu:], copying result to U. - impl.Dgebrd(m, m, work[iu:], ldworku, s, work[ie:], - work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Lower, m, m, work[iu:], ldworku, u, ldu) - - // Generate right bidiagonalizing vectors in work[iu:]. - impl.Dorgbr(lapack.GeneratePT, m, m, m, work[iu:], ldworku, - work[itaup:], work[iwork:], lwork-iwork) - - // Generate left bidiagonalizing vectors in U. - impl.Dorgbr(lapack.GenerateQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing left singular - // vectors of L in U and computing right singular vectors - // of L in work[iu:]. - ok = impl.Dbdsqr(blas.Upper, m, m, m, 0, s, work[ie:], - work[iu:], ldworku, u, ldu, work, 1, work[iwork:]) - - // Multiply right singular vectors of L in work[iu:] - // Q in VT, storing result in A. - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, - work[iu:], ldworku, vt, ldvt, 0, a, lda) - - // Copy right singular vectors of A from A to VT. - impl.Dlacpy(blas.All, m, n, a, lda, vt, ldvt) - } else { - // Insufficient workspace for a fast algorithm. - itau := 0 - iwork := itau + m - - // Compute A = L * Q, copying result to VT. - impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) - impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) - - // Generate Q in VT. - impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) - - // Copy L to U, zeroing out above it. - impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) - impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, u[1:], ldu) - - ie = itau - itauq := ie + m - itaup := itauq + m - iwork = itaup + m - - // Bidiagonalize L in U. - impl.Dgebrd(m, m, u, ldu, s, work[ie:], work[itauq:], - work[itaup:], work[iwork:], lwork-iwork) - - // Multiply right bidiagonalizing vectors in U by Q in VT. - impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, - u, ldu, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) - - // Generate left bidiagonalizing vectors in U. - impl.Dorgbr(lapack.GenerateQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) - iwork = ie + m - - // Perform bidiagonal QR iteration, computing left singular - // vectors of A in U and computing right singular vectors - // of A in VT. - ok = impl.Dbdsqr(blas.Upper, m, n, m, 0, s, work[ie:], - vt, ldvt, u, ldu, work, 1, work[iwork:]) - } - } - } - } else { - // Path 10t. - // N at least M, but not much larger. - ie = 0 - itauq := ie + m - itaup := itauq + m - iwork := itaup + m - - // Bidiagonalize A. - impl.Dgebrd(m, n, a, lda, s, work[ie:], work[itauq:], work[itaup:], work[iwork:], lwork-iwork) - if wantuas { - // If left singular vectors desired in U, copy result to U and - // generate left bidiagonalizing vectors in U. - impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) - impl.Dorgbr(lapack.GenerateQ, m, m, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) - } - if wantvas { - // If right singular vectors desired in VT, copy result to VT - // and generate right bidiagonalizing vectors in VT. - impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) - var nrvt int - if wantva { - nrvt = n - } else { - nrvt = m - } - impl.Dorgbr(lapack.GeneratePT, nrvt, n, m, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) - } - if wantuo { - panic(noSVDO) - } - if wantvo { - panic(noSVDO) - } - iwork = ie + m - var nru, ncvt int - if wantuas || wantuo { - nru = m - } - if wantvas || wantvo { - ncvt = n - } - if !wantuo && !wantvo { - // Perform bidiagonal QR iteration, if desired, computing left - // singular vectors in U and computing right singular vectors in - // VT. - ok = impl.Dbdsqr(blas.Lower, m, ncvt, nru, 0, s, work[ie:], - vt, ldvt, u, ldu, work, 1, work[iwork:]) - } else { - // There will be two branches when the implementation is complete. - panic(noSVDO) - } - } - } - if !ok { - if ie > 1 { - for i := 0; i < minmn-1; i++ { - work[i+1] = work[i+ie] - } - } - if ie < 1 { - for i := minmn - 2; i >= 0; i-- { - work[i+1] = work[i+ie] - } - } - } - // Undo scaling if necessary. - if iscl { - if anrm > bignum { - impl.Dlascl(lapack.General, 0, 0, bignum, anrm, 1, minmn, s, minmn) - } - if !ok && anrm > bignum { - impl.Dlascl(lapack.General, 0, 0, bignum, anrm, 1, minmn-1, work[1:], minmn) - } - if anrm < smlnum { - impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, 1, minmn, s, minmn) - } - if !ok && anrm < smlnum { - impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, 1, minmn-1, work[1:], minmn) - } - } - work[0] = float64(maxwrk) - return ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetc2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetc2.go deleted file mode 100644 index 41203e9f..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetc2.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgetc2 computes an LU factorization with complete pivoting of the n×n matrix -// A. The factorization has the form -// -// A = P * L * U * Q, -// -// where P and Q are permutation matrices, L is lower triangular with unit -// diagonal elements and U is upper triangular. -// -// On entry, a contains the matrix A to be factored. On return, a is overwritten -// with the factors L and U. The unit diagonal elements of L are not stored. -// -// On return, ipiv and jpiv contain the pivot indices: row i has been -// interchanged with row ipiv[i] and column j has been interchanged with column -// jpiv[j]. ipiv and jpiv must have length n, otherwise Dgetc2 will panic. -// -// If k is non-negative, then U[k,k] is likely to produce overflow when solving -// for x in A*x=b and U has been perturbed to avoid the overflow. -// -// Dgetc2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgetc2(n int, a []float64, lda int, ipiv, jpiv []int) (k int) { - switch { - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Negative k indicates U was not perturbed. - k = -1 - - // Quick return if possible. - if n == 0 { - return k - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(ipiv) != n: - panic(badLenIpiv) - case len(jpiv) != n: - panic(badLenJpvt) - } - - const ( - eps = dlamchP - smlnum = dlamchS / eps - ) - - if n == 1 { - ipiv[0], jpiv[0] = 0, 0 - if math.Abs(a[0]) < smlnum { - k = 0 - a[0] = smlnum - } - return k - } - - // Factorize A using complete pivoting. - // Set pivots less than smin to smin. - var smin float64 - var ipv, jpv int - bi := blas64.Implementation() - for i := 0; i < n-1; i++ { - var xmax float64 - for ip := i; ip < n; ip++ { - for jp := i; jp < n; jp++ { - if math.Abs(a[ip*lda+jp]) >= xmax { - xmax = math.Abs(a[ip*lda+jp]) - ipv = ip - jpv = jp - } - } - } - if i == 0 { - smin = math.Max(eps*xmax, smlnum) - } - - // Swap rows. - if ipv != i { - bi.Dswap(n, a[ipv*lda:], 1, a[i*lda:], 1) - } - ipiv[i] = ipv - - // Swap columns. - if jpv != i { - bi.Dswap(n, a[jpv:], lda, a[i:], lda) - } - jpiv[i] = jpv - - // Check for singularity. - if math.Abs(a[i*lda+i]) < smin { - k = i - a[i*lda+i] = smin - } - - for j := i + 1; j < n; j++ { - a[j*lda+i] /= a[i*lda+i] - } - bi.Dger(n-i-1, n-i-1, -1, a[(i+1)*lda+i:], lda, a[i*lda+i+1:], 1, a[(i+1)*lda+i+1:], lda) - } - - if math.Abs(a[(n-1)*lda+n-1]) < smin { - k = n - 1 - a[(n-1)*lda+(n-1)] = smin - } - - // Set last pivots to last index. - ipiv[n-1] = n - 1 - jpiv[n-1] = n - 1 - - return k -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go deleted file mode 100644 index 6a7003cf..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgetf2 computes the LU decomposition of an m×n matrix A using partial -// pivoting with row interchanges. -// -// The LU decomposition is a factorization of A into -// -// A = P * L * U -// -// where P is a permutation matrix, L is a lower triangular with unit diagonal -// elements (lower trapezoidal if m > n), and U is upper triangular (upper -// trapezoidal if m < n). -// -// On entry, a contains the matrix A. On return, L and U are stored in place -// into a, and P is represented by ipiv. -// -// ipiv contains a sequence of row interchanges. It indicates that row i of the -// matrix was interchanged with ipiv[i]. ipiv must have length min(m,n), and -// Dgetf2 will panic otherwise. ipiv is zero-indexed. -// -// Dgetf2 returns whether the matrix A is nonsingular. The LU decomposition will -// be computed regardless of the singularity of A, but the result should not be -// used to solve a system of equation. -// -// Dgetf2 is an internal routine. It is exported for testing purposes. -func (Implementation) Dgetf2(m, n int, a []float64, lda int, ipiv []int) (ok bool) { - mn := min(m, n) - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if mn == 0 { - return true - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(ipiv) != mn: - panic(badLenIpiv) - } - - bi := blas64.Implementation() - - sfmin := dlamchS - ok = true - for j := 0; j < mn; j++ { - // Find a pivot and test for singularity. - jp := j + bi.Idamax(m-j, a[j*lda+j:], lda) - ipiv[j] = jp - if a[jp*lda+j] == 0 { - ok = false - } else { - // Swap the rows if necessary. - if jp != j { - bi.Dswap(n, a[j*lda:], 1, a[jp*lda:], 1) - } - if j < m-1 { - aj := a[j*lda+j] - if math.Abs(aj) >= sfmin { - bi.Dscal(m-j-1, 1/aj, a[(j+1)*lda+j:], lda) - } else { - for i := 0; i < m-j-1; i++ { - a[(j+1)*lda+j] = a[(j+1)*lda+j] / a[lda*j+j] - } - } - } - } - if j < mn-1 { - bi.Dger(m-j-1, n-j-1, -1, a[(j+1)*lda+j:], lda, a[j*lda+j+1:], 1, a[(j+1)*lda+j+1:], lda) - } - } - return ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go deleted file mode 100644 index 38ae8efa..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgetrf computes the LU decomposition of an m×n matrix A using partial -// pivoting with row interchanges. -// -// The LU decomposition is a factorization of A into -// -// A = P * L * U -// -// where P is a permutation matrix, L is a lower triangular with unit diagonal -// elements (lower trapezoidal if m > n), and U is upper triangular (upper -// trapezoidal if m < n). -// -// On entry, a contains the matrix A. On return, L and U are stored in place -// into a, and P is represented by ipiv. -// -// ipiv contains a sequence of row interchanges. It indicates that row i of the -// matrix was interchanged with ipiv[i]. ipiv must have length min(m,n), and -// Dgetrf will panic otherwise. ipiv is zero-indexed. -// -// Dgetrf returns whether the matrix A is nonsingular. The LU decomposition will -// be computed regardless of the singularity of A, but the result should not be -// used to solve a system of equation. -func (impl Implementation) Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) { - mn := min(m, n) - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if mn == 0 { - return true - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(ipiv) != mn: - panic(badLenIpiv) - } - - bi := blas64.Implementation() - - nb := impl.Ilaenv(1, "DGETRF", " ", m, n, -1, -1) - if nb <= 1 || mn <= nb { - // Use the unblocked algorithm. - return impl.Dgetf2(m, n, a, lda, ipiv) - } - ok = true - for j := 0; j < mn; j += nb { - jb := min(mn-j, nb) - blockOk := impl.Dgetf2(m-j, jb, a[j*lda+j:], lda, ipiv[j:j+jb]) - if !blockOk { - ok = false - } - for i := j; i <= min(m-1, j+jb-1); i++ { - ipiv[i] = j + ipiv[i] - } - impl.Dlaswp(j, a, lda, j, j+jb-1, ipiv[:j+jb], 1) - if j+jb < n { - impl.Dlaswp(n-j-jb, a[j+jb:], lda, j, j+jb-1, ipiv[:j+jb], 1) - bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, - jb, n-j-jb, 1, - a[j*lda+j:], lda, - a[j*lda+j+jb:], lda) - if j+jb < m { - bi.Dgemm(blas.NoTrans, blas.NoTrans, m-j-jb, n-j-jb, jb, -1, - a[(j+jb)*lda+j:], lda, - a[j*lda+j+jb:], lda, - 1, a[(j+jb)*lda+j+jb:], lda) - } - } - } - return ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go deleted file mode 100644 index b2f2ae46..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgetri computes the inverse of the matrix A using the LU factorization computed -// by Dgetrf. On entry, a contains the PLU decomposition of A as computed by -// Dgetrf and on exit contains the reciprocal of the original matrix. -// -// Dgetri will not perform the inversion if the matrix is singular, and returns -// a boolean indicating whether the inversion was successful. -// -// work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= n and this function will panic otherwise. -// Dgetri is a blocked inversion, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Dgetri, -// the optimal work length will be stored into work[0]. -func (impl Implementation) Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) { - iws := max(1, n) - switch { - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < iws && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - if n == 0 { - work[0] = 1 - return true - } - - nb := impl.Ilaenv(1, "DGETRI", " ", n, -1, -1, -1) - if lwork == -1 { - work[0] = float64(n * nb) - return true - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(ipiv) != n: - panic(badLenIpiv) - } - - // Form inv(U). - ok = impl.Dtrtri(blas.Upper, blas.NonUnit, n, a, lda) - if !ok { - return false - } - - nbmin := 2 - if 1 < nb && nb < n { - iws = max(n*nb, 1) - if lwork < iws { - nb = lwork / n - nbmin = max(2, impl.Ilaenv(2, "DGETRI", " ", n, -1, -1, -1)) - } - } - ldwork := nb - - bi := blas64.Implementation() - // Solve the equation inv(A)*L = inv(U) for inv(A). - // TODO(btracey): Replace this with a more row-major oriented algorithm. - if nb < nbmin || n <= nb { - // Unblocked code. - for j := n - 1; j >= 0; j-- { - for i := j + 1; i < n; i++ { - // Copy current column of L to work and replace with zeros. - work[i] = a[i*lda+j] - a[i*lda+j] = 0 - } - // Compute current column of inv(A). - if j < n-1 { - bi.Dgemv(blas.NoTrans, n, n-j-1, -1, a[(j+1):], lda, work[(j+1):], 1, 1, a[j:], lda) - } - } - } else { - // Blocked code. - nn := ((n - 1) / nb) * nb - for j := nn; j >= 0; j -= nb { - jb := min(nb, n-j) - // Copy current block column of L to work and replace - // with zeros. - for jj := j; jj < j+jb; jj++ { - for i := jj + 1; i < n; i++ { - work[i*ldwork+(jj-j)] = a[i*lda+jj] - a[i*lda+jj] = 0 - } - } - // Compute current block column of inv(A). - if j+jb < n { - bi.Dgemm(blas.NoTrans, blas.NoTrans, n, jb, n-j-jb, -1, a[(j+jb):], lda, work[(j+jb)*ldwork:], ldwork, 1, a[j:], lda) - } - bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, jb, 1, work[j*ldwork:], ldwork, a[j:], lda) - } - } - // Apply column interchanges. - for j := n - 2; j >= 0; j-- { - jp := ipiv[j] - if jp != j { - bi.Dswap(n, a[j:], lda, a[jp:], lda) - } - } - work[0] = float64(iws) - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go deleted file mode 100644 index 35b33aa7..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dgetrs solves a system of equations using an LU factorization. -// The system of equations solved is -// -// A * X = B if trans == blas.Trans -// Aᵀ * X = B if trans == blas.NoTrans -// -// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. -// -// On entry b contains the elements of the matrix B. On exit, b contains the -// elements of X, the solution to the system of equations. -// -// a and ipiv contain the LU factorization of A and the permutation indices as -// computed by Dgetrf. ipiv is zero-indexed. -func (impl Implementation) Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) { - switch { - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTrans) - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, nrhs): - panic(badLdB) - } - - // Quick return if possible. - if n == 0 || nrhs == 0 { - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - case len(ipiv) != n: - panic(badLenIpiv) - } - - bi := blas64.Implementation() - - if trans == blas.NoTrans { - // Solve A * X = B. - impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, 1) - // Solve L * X = B, updating b. - bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, - n, nrhs, 1, a, lda, b, ldb) - // Solve U * X = B, updating b. - bi.Dtrsm(blas.Left, blas.Upper, blas.NoTrans, blas.NonUnit, - n, nrhs, 1, a, lda, b, ldb) - return - } - // Solve Aᵀ * X = B. - // Solve Uᵀ * X = B, updating b. - bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, - n, nrhs, 1, a, lda, b, ldb) - // Solve Lᵀ * X = B, updating b. - bi.Dtrsm(blas.Left, blas.Lower, blas.Trans, blas.Unit, - n, nrhs, 1, a, lda, b, ldb) - impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, -1) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgghrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgghrd.go deleted file mode 100644 index c9d6b4d1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgghrd.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright ©2023 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dgghrd reduces a pair of real matrices (A,B) to generalized upper Hessenberg -// form using orthogonal transformations, where A is a general matrix and B is -// upper triangular. -// -// This subroutine simultaneously reduces A to a Hessenberg matrix H -// -// Qᵀ*A*Z = H, -// -// and transforms B to another upper triangular matrix T -// -// Qᵀ*B*Z = T. -// -// The orthogonal matrices Q and Z are determined as products of Givens -// rotations. They may either be formed explicitly (lapack.OrthoExplicit), or -// they may be postmultiplied into input matrices Q1 and Z1 -// (lapack.OrthoPostmul), so that -// -// Q1 * A * Z1ᵀ = (Q1*Q) * H * (Z1*Z)ᵀ, -// Q1 * B * Z1ᵀ = (Q1*Q) * T * (Z1*Z)ᵀ. -// -// ilo and ihi determine the block of A that will be reduced. It must hold that -// -// - 0 <= ilo <= ihi < n if n > 0, -// - ilo == 0 and ihi == -1 if n == 0, -// -// otherwise Dgghrd will panic. -// -// Dgghrd is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dgghrd(compq, compz lapack.OrthoComp, n, ilo, ihi int, a []float64, lda int, b []float64, ldb int, q []float64, ldq int, z []float64, ldz int) { - switch { - case compq != lapack.OrthoNone && compq != lapack.OrthoExplicit && compq != lapack.OrthoPostmul: - panic(badOrthoComp) - case compz != lapack.OrthoNone && compz != lapack.OrthoExplicit && compz != lapack.OrthoPostmul: - panic(badOrthoComp) - case n < 0: - panic(nLT0) - case ilo < 0 || max(0, n-1) < ilo: - panic(badIlo) - case ihi < min(ilo, n-1) || n <= ihi: - panic(badIhi) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - case (compq != lapack.OrthoNone && ldq < n) || ldq < 1: - panic(badLdQ) - case (compz != lapack.OrthoNone && ldz < n) || ldz < 1: - panic(badLdZ) - } - - // Quick return if possible. - if n == 0 { - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(b) < (n-1)*ldb+n: - panic(shortB) - case compq != lapack.OrthoNone && len(q) < (n-1)*ldq+n: - panic(shortQ) - case compz != lapack.OrthoNone && len(z) < (n-1)*ldz+n: - panic(shortZ) - } - - if compq == lapack.OrthoExplicit { - impl.Dlaset(blas.All, n, n, 0, 1, q, ldq) - } - if compz == lapack.OrthoExplicit { - impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) - } - - // Quick return if possible. - if n == 1 { - return - } - - // Zero out lower triangle of B. - for i := 1; i < n; i++ { - for j := 0; j < i; j++ { - b[i*ldb+j] = 0 - } - } - bi := blas64.Implementation() - // Reduce A and B. - for jcol := ilo; jcol <= ihi-2; jcol++ { - for jrow := ihi; jrow >= jcol+2; jrow-- { - // Step 1: rotate rows jrow-1, jrow to kill A[jrow,jcol]. - var c, s float64 - c, s, a[(jrow-1)*lda+jcol] = impl.Dlartg(a[(jrow-1)*lda+jcol], a[jrow*lda+jcol]) - a[jrow*lda+jcol] = 0 - - bi.Drot(n-jcol-1, a[(jrow-1)*lda+jcol+1:], 1, a[jrow*lda+jcol+1:], 1, c, s) - bi.Drot(n+2-jrow-1, b[(jrow-1)*ldb+jrow-1:], 1, b[jrow*ldb+jrow-1:], 1, c, s) - - if compq != lapack.OrthoNone { - bi.Drot(n, q[jrow-1:], ldq, q[jrow:], ldq, c, s) - } - - // Step 2: rotate columns jrow, jrow-1 to kill B[jrow,jrow-1]. - c, s, b[jrow*ldb+jrow] = impl.Dlartg(b[jrow*ldb+jrow], b[jrow*ldb+jrow-1]) - b[jrow*ldb+jrow-1] = 0 - - bi.Drot(ihi+1, a[jrow:], lda, a[jrow-1:], lda, c, s) - bi.Drot(jrow, b[jrow:], ldb, b[jrow-1:], ldb, c, s) - - if compz != lapack.OrthoNone { - bi.Drot(n, z[jrow:], ldz, z[jrow-1:], ldz, c, s) - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go deleted file mode 100644 index cfe10efa..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dggsvd3 computes the generalized singular value decomposition (GSVD) -// of an m×n matrix A and p×n matrix B: -// -// Uᵀ*A*Q = D1*[ 0 R ] -// -// Vᵀ*B*Q = D2*[ 0 R ] -// -// where U, V and Q are orthogonal matrices. -// -// Dggsvd3 returns k and l, the dimensions of the sub-blocks. k+l -// is the effective numerical rank of the (m+p)×n matrix [ Aᵀ Bᵀ ]ᵀ. -// R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and -// D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following -// structures, respectively: -// -// If m-k-l >= 0, -// -// k l -// D1 = k [ I 0 ] -// l [ 0 C ] -// m-k-l [ 0 0 ] -// -// k l -// D2 = l [ 0 S ] -// p-l [ 0 0 ] -// -// n-k-l k l -// [ 0 R ] = k [ 0 R11 R12 ] k -// l [ 0 0 R22 ] l -// -// where -// -// C = diag( alpha_k, ... , alpha_{k+l} ), -// S = diag( beta_k, ... , beta_{k+l} ), -// C^2 + S^2 = I. -// -// R is stored in -// -// A[0:k+l, n-k-l:n] -// -// on exit. -// -// If m-k-l < 0, -// -// k m-k k+l-m -// D1 = k [ I 0 0 ] -// m-k [ 0 C 0 ] -// -// k m-k k+l-m -// D2 = m-k [ 0 S 0 ] -// k+l-m [ 0 0 I ] -// p-l [ 0 0 0 ] -// -// n-k-l k m-k k+l-m -// [ 0 R ] = k [ 0 R11 R12 R13 ] -// m-k [ 0 0 R22 R23 ] -// k+l-m [ 0 0 0 R33 ] -// -// where -// -// C = diag( alpha_k, ... , alpha_m ), -// S = diag( beta_k, ... , beta_m ), -// C^2 + S^2 = I. -// -// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] -// [ 0 R22 R23 ] -// -// and R33 is stored in -// -// B[m-k:l, n+m-k-l:n] on exit. -// -// Dggsvd3 computes C, S, R, and optionally the orthogonal transformation -// matrices U, V and Q. -// -// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior -// is as follows -// -// jobU == lapack.GSVDU Compute orthogonal matrix U -// jobU == lapack.GSVDNone Do not compute orthogonal matrix. -// -// The behavior is the same for jobV and jobQ with the exception that instead of -// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. -// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the -// relevant job parameter is lapack.GSVDNone. -// -// alpha and beta must have length n or Dggsvd3 will panic. On exit, alpha and -// beta contain the generalized singular value pairs of A and B -// -// alpha[0:k] = 1, -// beta[0:k] = 0, -// -// if m-k-l >= 0, -// -// alpha[k:k+l] = diag(C), -// beta[k:k+l] = diag(S), -// -// if m-k-l < 0, -// -// alpha[k:m]= C, alpha[m:k+l]= 0 -// beta[k:m] = S, beta[m:k+l] = 1. -// -// if k+l < n, -// -// alpha[k+l:n] = 0 and -// beta[k+l:n] = 0. -// -// On exit, iwork contains the permutation required to sort alpha descending. -// -// iwork must have length n, work must have length at least max(1, lwork), and -// lwork must be -1 or greater than n, otherwise Dggsvd3 will panic. If -// lwork is -1, work[0] holds the optimal lwork on return, but Dggsvd3 does -// not perform the GSVD. -func (impl Implementation) Dggsvd3(jobU, jobV, jobQ lapack.GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) { - wantu := jobU == lapack.GSVDU - wantv := jobV == lapack.GSVDV - wantq := jobQ == lapack.GSVDQ - switch { - case !wantu && jobU != lapack.GSVDNone: - panic(badGSVDJob + "U") - case !wantv && jobV != lapack.GSVDNone: - panic(badGSVDJob + "V") - case !wantq && jobQ != lapack.GSVDNone: - panic(badGSVDJob + "Q") - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case p < 0: - panic(pLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - case ldu < 1, wantu && ldu < m: - panic(badLdU) - case ldv < 1, wantv && ldv < p: - panic(badLdV) - case ldq < 1, wantq && ldq < n: - panic(badLdQ) - case len(iwork) < n: - panic(shortWork) - case lwork < 1 && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Determine optimal work length. - impl.Dggsvp3(jobU, jobV, jobQ, - m, p, n, - a, lda, - b, ldb, - 0, 0, - u, ldu, - v, ldv, - q, ldq, - iwork, - work, work, -1) - lwkopt := n + int(work[0]) - lwkopt = max(lwkopt, 2*n) - lwkopt = max(lwkopt, 1) - work[0] = float64(lwkopt) - if lwork == -1 { - return 0, 0, true - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(b) < (p-1)*ldb+n: - panic(shortB) - case wantu && len(u) < (m-1)*ldu+m: - panic(shortU) - case wantv && len(v) < (p-1)*ldv+p: - panic(shortV) - case wantq && len(q) < (n-1)*ldq+n: - panic(shortQ) - case len(alpha) != n: - panic(badLenAlpha) - case len(beta) != n: - panic(badLenBeta) - } - - // Compute the Frobenius norm of matrices A and B. - anorm := impl.Dlange(lapack.Frobenius, m, n, a, lda, nil) - bnorm := impl.Dlange(lapack.Frobenius, p, n, b, ldb, nil) - - // Get machine precision and set up threshold for determining - // the effective numerical rank of the matrices A and B. - tola := float64(max(m, n)) * math.Max(anorm, dlamchS) * dlamchP - tolb := float64(max(p, n)) * math.Max(bnorm, dlamchS) * dlamchP - - // Preprocessing. - k, l = impl.Dggsvp3(jobU, jobV, jobQ, - m, p, n, - a, lda, - b, ldb, - tola, tolb, - u, ldu, - v, ldv, - q, ldq, - iwork, - work[:n], work[n:], lwork-n) - - // Compute the GSVD of two upper "triangular" matrices. - _, ok = impl.Dtgsja(jobU, jobV, jobQ, - m, p, n, - k, l, - a, lda, - b, ldb, - tola, tolb, - alpha, beta, - u, ldu, - v, ldv, - q, ldq, - work) - - // Sort the singular values and store the pivot indices in iwork - // Copy alpha to work, then sort alpha in work. - bi := blas64.Implementation() - bi.Dcopy(n, alpha, 1, work[:n], 1) - ibnd := min(l, m-k) - for i := 0; i < ibnd; i++ { - // Scan for largest alpha_{k+i}. - isub := i - smax := work[k+i] - for j := i + 1; j < ibnd; j++ { - if v := work[k+j]; v > smax { - isub = j - smax = v - } - } - if isub != i { - work[k+isub] = work[k+i] - work[k+i] = smax - iwork[k+i] = k + isub - } else { - iwork[k+i] = k + i - } - } - - work[0] = float64(lwkopt) - - return k, l, ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go deleted file mode 100644 index f7f04c76..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dggsvp3 computes orthogonal matrices U, V and Q such that -// -// n-k-l k l -// Uᵀ*A*Q = k [ 0 A12 A13 ] if m-k-l >= 0; -// l [ 0 0 A23 ] -// m-k-l [ 0 0 0 ] -// -// n-k-l k l -// Uᵀ*A*Q = k [ 0 A12 A13 ] if m-k-l < 0; -// m-k [ 0 0 A23 ] -// -// n-k-l k l -// Vᵀ*B*Q = l [ 0 0 B13 ] -// p-l [ 0 0 0 ] -// -// where the k×k matrix A12 and l×l matrix B13 are non-singular -// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, -// otherwise A23 is (m-k)×l upper trapezoidal. -// -// Dggsvp3 returns k and l, the dimensions of the sub-blocks. k+l -// is the effective numerical rank of the (m+p)×n matrix [ Aᵀ Bᵀ ]ᵀ. -// -// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior -// is as follows -// -// jobU == lapack.GSVDU Compute orthogonal matrix U -// jobU == lapack.GSVDNone Do not compute orthogonal matrix. -// -// The behavior is the same for jobV and jobQ with the exception that instead of -// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. -// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the -// relevant job parameter is lapack.GSVDNone. -// -// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz -// iteration procedure. Generally, they are the same as used in the preprocessing -// step, for example, -// -// tola = max(m, n)*norm(A)*eps, -// tolb = max(p, n)*norm(B)*eps. -// -// Where eps is the machine epsilon. -// -// iwork must have length n, work must have length at least max(1, lwork), and -// lwork must be -1 or greater than zero, otherwise Dggsvp3 will panic. -// -// Dggsvp3 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, iwork []int, tau, work []float64, lwork int) (k, l int) { - wantu := jobU == lapack.GSVDU - wantv := jobV == lapack.GSVDV - wantq := jobQ == lapack.GSVDQ - switch { - case !wantu && jobU != lapack.GSVDNone: - panic(badGSVDJob + "U") - case !wantv && jobV != lapack.GSVDNone: - panic(badGSVDJob + "V") - case !wantq && jobQ != lapack.GSVDNone: - panic(badGSVDJob + "Q") - case m < 0: - panic(mLT0) - case p < 0: - panic(pLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - case ldu < 1, wantu && ldu < m: - panic(badLdU) - case ldv < 1, wantv && ldv < p: - panic(badLdV) - case ldq < 1, wantq && ldq < n: - panic(badLdQ) - case len(iwork) != n: - panic(shortWork) - case lwork < 1 && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - var lwkopt int - impl.Dgeqp3(p, n, b, ldb, iwork, tau, work, -1) - lwkopt = int(work[0]) - if wantv { - lwkopt = max(lwkopt, p) - } - lwkopt = max(lwkopt, min(n, p)) - lwkopt = max(lwkopt, m) - if wantq { - lwkopt = max(lwkopt, n) - } - impl.Dgeqp3(m, n, a, lda, iwork, tau, work, -1) - lwkopt = max(lwkopt, int(work[0])) - lwkopt = max(1, lwkopt) - if lwork == -1 { - work[0] = float64(lwkopt) - return 0, 0 - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(b) < (p-1)*ldb+n: - panic(shortB) - case wantu && len(u) < (m-1)*ldu+m: - panic(shortU) - case wantv && len(v) < (p-1)*ldv+p: - panic(shortV) - case wantq && len(q) < (n-1)*ldq+n: - panic(shortQ) - case len(tau) < n: - // tau check must come after lwkopt query since - // the Dggsvd3 call for lwkopt query may have - // lwork == -1, and tau is provided by work. - panic(shortTau) - } - - const forward = true - - // QR with column pivoting of B: B*P = V*[ S11 S12 ]. - // [ 0 0 ] - for i := range iwork[:n] { - iwork[i] = 0 - } - impl.Dgeqp3(p, n, b, ldb, iwork, tau, work, lwork) - - // Update A := A*P. - impl.Dlapmt(forward, m, n, a, lda, iwork) - - // Determine the effective rank of matrix B. - for i := 0; i < min(p, n); i++ { - if math.Abs(b[i*ldb+i]) > tolb { - l++ - } - } - - if wantv { - // Copy the details of V, and form V. - impl.Dlaset(blas.All, p, p, 0, 0, v, ldv) - if p > 1 { - impl.Dlacpy(blas.Lower, p-1, min(p, n), b[ldb:], ldb, v[ldv:], ldv) - } - impl.Dorg2r(p, p, min(p, n), v, ldv, tau[:min(p, n)], work) - } - - // Clean up B. - for i := 1; i < l; i++ { - r := b[i*ldb : i*ldb+i] - for j := range r { - r[j] = 0 - } - } - if p > l { - impl.Dlaset(blas.All, p-l, n, 0, 0, b[l*ldb:], ldb) - } - - if wantq { - // Set Q = I and update Q := Q*P. - impl.Dlaset(blas.All, n, n, 0, 1, q, ldq) - impl.Dlapmt(forward, n, n, q, ldq, iwork) - } - - if p >= l && n != l { - // RQ factorization of [ S11 S12 ]: [ S11 S12 ] = [ 0 S12 ]*Z. - impl.Dgerq2(l, n, b, ldb, tau, work) - - // Update A := A*Zᵀ. - impl.Dormr2(blas.Right, blas.Trans, m, n, l, b, ldb, tau, a, lda, work) - - if wantq { - // Update Q := Q*Zᵀ. - impl.Dormr2(blas.Right, blas.Trans, n, n, l, b, ldb, tau, q, ldq, work) - } - - // Clean up B. - impl.Dlaset(blas.All, l, n-l, 0, 0, b, ldb) - for i := 1; i < l; i++ { - r := b[i*ldb+n-l : i*ldb+i+n-l] - for j := range r { - r[j] = 0 - } - } - } - - // Let N-L L - // A = [ A11 A12 ] M, - // - // then the following does the complete QR decomposition of A11: - // - // A11 = U*[ 0 T12 ]*P1ᵀ. - // [ 0 0 ] - for i := range iwork[:n-l] { - iwork[i] = 0 - } - impl.Dgeqp3(m, n-l, a, lda, iwork[:n-l], tau, work, lwork) - - // Determine the effective rank of A11. - for i := 0; i < min(m, n-l); i++ { - if math.Abs(a[i*lda+i]) > tola { - k++ - } - } - - // Update A12 := Uᵀ*A12, where A12 = A[0:m, n-l:n]. - impl.Dorm2r(blas.Left, blas.Trans, m, l, min(m, n-l), a, lda, tau[:min(m, n-l)], a[n-l:], lda, work) - - if wantu { - // Copy the details of U, and form U. - impl.Dlaset(blas.All, m, m, 0, 0, u, ldu) - if m > 1 { - impl.Dlacpy(blas.Lower, m-1, min(m, n-l), a[lda:], lda, u[ldu:], ldu) - } - k := min(m, n-l) - impl.Dorg2r(m, m, k, u, ldu, tau[:k], work) - } - - if wantq { - // Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*P1. - impl.Dlapmt(forward, n, n-l, q, ldq, iwork[:n-l]) - } - - // Clean up A: set the strictly lower triangular part of - // A[0:k, 0:k] = 0, and A[k:m, 0:n-l] = 0. - for i := 1; i < k; i++ { - r := a[i*lda : i*lda+i] - for j := range r { - r[j] = 0 - } - } - if m > k { - impl.Dlaset(blas.All, m-k, n-l, 0, 0, a[k*lda:], lda) - } - - if n-l > k { - // RQ factorization of [ T11 T12 ] = [ 0 T12 ]*Z1. - impl.Dgerq2(k, n-l, a, lda, tau, work) - - if wantq { - // Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*Z1ᵀ. - impl.Dorm2r(blas.Right, blas.Trans, n, n-l, k, a, lda, tau[:k], q, ldq, work) - } - - // Clean up A. - impl.Dlaset(blas.All, k, n-l-k, 0, 0, a, lda) - for i := 1; i < k; i++ { - r := a[i*lda+n-k-l : i*lda+i+n-k-l] - for j := range r { - a[j] = 0 - } - } - } - - if m > k { - // QR factorization of A[k:m, n-l:n]. - impl.Dgeqr2(m-k, l, a[k*lda+n-l:], lda, tau[:min(m-k, l)], work) - if wantu { - // Update U[:, k:m) := U[:, k:m]*U1. - impl.Dorm2r(blas.Right, blas.NoTrans, m, m-k, min(m-k, l), a[k*lda+n-l:], lda, tau[:min(m-k, l)], u[k:], ldu, work) - } - - // Clean up A. - for i := k + 1; i < m; i++ { - r := a[i*lda+n-l : i*lda+min(n-l+i-k, n)] - for j := range r { - r[j] = 0 - } - } - } - - work[0] = float64(lwkopt) - return k, l -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgtsv.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgtsv.go deleted file mode 100644 index 944af1a6..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgtsv.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright ©2020 The Gonum 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 gonum - -import "math" - -// Dgtsv solves the equation -// -// A * X = B -// -// where A is an n×n tridiagonal matrix. It uses Gaussian elimination with -// partial pivoting. The equation Aᵀ * X = B may be solved by swapping the -// arguments for du and dl. -// -// On entry, dl, d and du contain the sub-diagonal, the diagonal and the -// super-diagonal, respectively, of A. On return, the first n-2 elements of dl, -// the first n-1 elements of du and the first n elements of d may be -// overwritten. -// -// On entry, b contains the n×nrhs right-hand side matrix B. On return, b will -// be overwritten. If ok is true, it will be overwritten by the solution matrix X. -// -// Dgtsv returns whether the solution X has been successfully computed. -func (impl Implementation) Dgtsv(n, nrhs int, dl, d, du []float64, b []float64, ldb int) (ok bool) { - switch { - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case ldb < max(1, nrhs): - panic(badLdB) - } - - if n == 0 || nrhs == 0 { - return true - } - - switch { - case len(dl) < n-1: - panic(shortDL) - case len(d) < n: - panic(shortD) - case len(du) < n-1: - panic(shortDU) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - } - - dl = dl[:n-1] - d = d[:n] - du = du[:n-1] - - for i := 0; i < n-1; i++ { - if math.Abs(d[i]) >= math.Abs(dl[i]) { - // No row interchange required. - if d[i] == 0 { - return false - } - fact := dl[i] / d[i] - d[i+1] -= fact * du[i] - for j := 0; j < nrhs; j++ { - b[(i+1)*ldb+j] -= fact * b[i*ldb+j] - } - dl[i] = 0 - } else { - // Interchange rows i and i+1. - fact := d[i] / dl[i] - d[i] = dl[i] - tmp := d[i+1] - d[i+1] = du[i] - fact*tmp - du[i] = tmp - if i+1 < n-1 { - dl[i] = du[i+1] - du[i+1] = -fact * dl[i] - } - for j := 0; j < nrhs; j++ { - tmp = b[i*ldb+j] - b[i*ldb+j] = b[(i+1)*ldb+j] - b[(i+1)*ldb+j] = tmp - fact*b[(i+1)*ldb+j] - } - } - } - if d[n-1] == 0 { - return false - } - - // Back solve with the matrix U from the factorization. - for j := 0; j < nrhs; j++ { - b[(n-1)*ldb+j] /= d[n-1] - if n > 1 { - b[(n-2)*ldb+j] = (b[(n-2)*ldb+j] - du[n-2]*b[(n-1)*ldb+j]) / d[n-2] - } - for i := n - 3; i >= 0; i-- { - b[i*ldb+j] = (b[i*ldb+j] - du[i]*b[(i+1)*ldb+j] - dl[i]*b[(i+2)*ldb+j]) / d[i] - } - } - - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go deleted file mode 100644 index beccf132..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dhseqr computes the eigenvalues of an n×n Hessenberg matrix H and, -// optionally, the matrices T and Z from the Schur decomposition -// -// H = Z T Zᵀ, -// -// where T is an n×n upper quasi-triangular matrix (the Schur form), and Z is -// the n×n orthogonal matrix of Schur vectors. -// -// Optionally Z may be postmultiplied into an input orthogonal matrix Q so that -// this routine can give the Schur factorization of a matrix A which has been -// reduced to the Hessenberg form H by the orthogonal matrix Q: -// -// A = Q H Qᵀ = (QZ) T (QZ)ᵀ. -// -// If job == lapack.EigenvaluesOnly, only the eigenvalues will be computed. -// If job == lapack.EigenvaluesAndSchur, the eigenvalues and the Schur form T will -// be computed. -// For other values of job Dhseqr will panic. -// -// If compz == lapack.SchurNone, no Schur vectors will be computed and Z will not be -// referenced. -// If compz == lapack.SchurHess, on return Z will contain the matrix of Schur -// vectors of H. -// If compz == lapack.SchurOrig, on entry z is assumed to contain the orthogonal -// matrix Q that is the identity except for the submatrix -// Q[ilo:ihi+1,ilo:ihi+1]. On return z will be updated to the product Q*Z. -// -// ilo and ihi determine the block of H on which Dhseqr operates. It is assumed -// that H is already upper triangular in rows and columns [0:ilo] and [ihi+1:n], -// although it will be only checked that the block is isolated, that is, -// -// ilo == 0 or H[ilo,ilo-1] == 0, -// ihi == n-1 or H[ihi+1,ihi] == 0, -// -// and Dhseqr will panic otherwise. ilo and ihi are typically set by a previous -// call to Dgebal, otherwise they should be set to 0 and n-1, respectively. It -// must hold that -// -// 0 <= ilo <= ihi < n if n > 0, -// ilo == 0 and ihi == -1 if n == 0. -// -// wr and wi must have length n. -// -// work must have length at least lwork and lwork must be at least max(1,n) -// otherwise Dhseqr will panic. The minimum lwork delivers very good and -// sometimes optimal performance, although lwork as large as 11*n may be -// required. On return, work[0] will contain the optimal value of lwork. -// -// If lwork is -1, instead of performing Dhseqr, the function only estimates the -// optimal workspace size and stores it into work[0]. Neither h nor z are -// accessed. -// -// unconverged indicates whether Dhseqr computed all the eigenvalues. -// -// If unconverged == 0, all the eigenvalues have been computed and their real -// and imaginary parts will be stored on return in wr and wi, respectively. If -// two eigenvalues are computed as a complex conjugate pair, they are stored in -// consecutive elements of wr and wi, say the i-th and (i+1)th, with wi[i] > 0 -// and wi[i+1] < 0. -// -// If unconverged == 0 and job == lapack.EigenvaluesAndSchur, on return H will -// contain the upper quasi-triangular matrix T from the Schur decomposition (the -// Schur form). 2×2 diagonal blocks (corresponding to complex conjugate pairs of -// eigenvalues) will be returned in standard form, with -// -// H[i,i] == H[i+1,i+1], -// -// and -// -// H[i+1,i]*H[i,i+1] < 0. -// -// The eigenvalues will be stored in wr and wi in the same order as on the -// diagonal of the Schur form returned in H, with -// -// wr[i] = H[i,i], -// -// and, if H[i:i+2,i:i+2] is a 2×2 diagonal block, -// -// wi[i] = sqrt(-H[i+1,i]*H[i,i+1]), -// wi[i+1] = -wi[i]. -// -// If unconverged == 0 and job == lapack.EigenvaluesOnly, the contents of h -// on return is unspecified. -// -// If unconverged > 0, some eigenvalues have not converged, and the blocks -// [0:ilo] and [unconverged:n] of wr and wi will contain those eigenvalues which -// have been successfully computed. Failures are rare. -// -// If unconverged > 0 and job == lapack.EigenvaluesOnly, on return the -// remaining unconverged eigenvalues are the eigenvalues of the upper Hessenberg -// matrix H[ilo:unconverged,ilo:unconverged]. -// -// If unconverged > 0 and job == lapack.EigenvaluesAndSchur, then on -// return -// -// (initial H) U = U (final H), (*) -// -// where U is an orthogonal matrix. The final H is upper Hessenberg and -// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. -// -// If unconverged > 0 and compz == lapack.SchurOrig, then on return -// -// (final Z) = (initial Z) U, -// -// where U is the orthogonal matrix in (*) regardless of the value of job. -// -// If unconverged > 0 and compz == lapack.SchurHess, then on return -// -// (final Z) = U, -// -// where U is the orthogonal matrix in (*) regardless of the value of job. -// -// References: -// -// [1] R. Byers. LAPACK 3.1 xHSEQR: Tuning and Implementation Notes on the -// Small Bulge Multi-Shift QR Algorithm with Aggressive Early Deflation. -// LAPACK Working Note 187 (2007) -// URL: http://www.netlib.org/lapack/lawnspdf/lawn187.pdf -// [2] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part I: -// Maintaining Well-Focused Shifts and Level 3 Performance. SIAM J. Matrix -// Anal. Appl. 23(4) (2002), pp. 929—947 -// URL: http://dx.doi.org/10.1137/S0895479801384573 -// [3] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: -// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl. 23(4) (2002), pp. 948—973 -// URL: http://dx.doi.org/10.1137/S0895479801384585 -// -// Dhseqr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dhseqr(job lapack.SchurJob, compz lapack.SchurComp, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, z []float64, ldz int, work []float64, lwork int) (unconverged int) { - wantt := job == lapack.EigenvaluesAndSchur - wantz := compz == lapack.SchurHess || compz == lapack.SchurOrig - - switch { - case job != lapack.EigenvaluesOnly && job != lapack.EigenvaluesAndSchur: - panic(badSchurJob) - case compz != lapack.SchurNone && compz != lapack.SchurHess && compz != lapack.SchurOrig: - panic(badSchurComp) - case n < 0: - panic(nLT0) - case ilo < 0 || max(0, n-1) < ilo: - panic(badIlo) - case ihi < min(ilo, n-1) || n <= ihi: - panic(badIhi) - case ldh < max(1, n): - panic(badLdH) - case ldz < 1, wantz && ldz < n: - panic(badLdZ) - case lwork < max(1, n) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - work[0] = 1 - return 0 - } - - // Quick return in case of a workspace query. - if lwork == -1 { - impl.Dlaqr04(wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, ilo, ihi, z, ldz, work, -1, 1) - work[0] = math.Max(float64(n), work[0]) - return 0 - } - - switch { - case len(h) < (n-1)*ldh+n: - panic(shortH) - case wantz && len(z) < (n-1)*ldz+n: - panic(shortZ) - case len(wr) < n: - panic(shortWr) - case len(wi) < n: - panic(shortWi) - } - - const ( - // Matrices of order ntiny or smaller must be processed by - // Dlahqr because of insufficient subdiagonal scratch space. - // This is a hard limit. - ntiny = 15 - - // nl is the size of a local workspace to help small matrices - // through a rare Dlahqr failure. nl > ntiny is required and - // nl <= nmin = Ilaenv(ispec=12,...) is recommended (the default - // value of nmin is 75). Using nl = 49 allows up to six - // simultaneous shifts and a 16×16 deflation window. - nl = 49 - ) - - // Copy eigenvalues isolated by Dgebal. - for i := 0; i < ilo; i++ { - wr[i] = h[i*ldh+i] - wi[i] = 0 - } - for i := ihi + 1; i < n; i++ { - wr[i] = h[i*ldh+i] - wi[i] = 0 - } - - // Initialize Z to identity matrix if requested. - if compz == lapack.SchurHess { - impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) - } - - // Quick return if possible. - if ilo == ihi { - wr[ilo] = h[ilo*ldh+ilo] - wi[ilo] = 0 - return 0 - } - - // Dlahqr/Dlaqr04 crossover point. - nmin := impl.Ilaenv(12, "DHSEQR", string(job)+string(compz), n, ilo, ihi, lwork) - nmin = max(ntiny, nmin) - - if n > nmin { - // Dlaqr0 for big matrices. - unconverged = impl.Dlaqr04(wantt, wantz, n, ilo, ihi, h, ldh, wr[:ihi+1], wi[:ihi+1], - ilo, ihi, z, ldz, work, lwork, 1) - } else { - // Dlahqr for small matrices. - unconverged = impl.Dlahqr(wantt, wantz, n, ilo, ihi, h, ldh, wr[:ihi+1], wi[:ihi+1], - ilo, ihi, z, ldz) - if unconverged > 0 { - // A rare Dlahqr failure! Dlaqr04 sometimes succeeds - // when Dlahqr fails. - kbot := unconverged - if n >= nl { - // Larger matrices have enough subdiagonal - // scratch space to call Dlaqr04 directly. - unconverged = impl.Dlaqr04(wantt, wantz, n, ilo, kbot, h, ldh, - wr[:ihi+1], wi[:ihi+1], ilo, ihi, z, ldz, work, lwork, 1) - } else { - // Tiny matrices don't have enough subdiagonal - // scratch space to benefit from Dlaqr04. Hence, - // tiny matrices must be copied into a larger - // array before calling Dlaqr04. - var hl [nl * nl]float64 - impl.Dlacpy(blas.All, n, n, h, ldh, hl[:], nl) - impl.Dlaset(blas.All, nl, nl-n, 0, 0, hl[n:], nl) - var workl [nl]float64 - unconverged = impl.Dlaqr04(wantt, wantz, nl, ilo, kbot, hl[:], nl, - wr[:ihi+1], wi[:ihi+1], ilo, ihi, z, ldz, workl[:], nl, 1) - work[0] = workl[0] - if wantt || unconverged > 0 { - impl.Dlacpy(blas.All, n, n, hl[:], nl, h, ldh) - } - } - } - } - // Zero out under the first subdiagonal, if necessary. - if (wantt || unconverged > 0) && n > 2 { - impl.Dlaset(blas.Lower, n-2, n-2, 0, 0, h[2*ldh:], ldh) - } - - work[0] = math.Max(float64(n), work[0]) - return unconverged -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go deleted file mode 100644 index 396242cc..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlabrd reduces the first NB rows and columns of a real general m×n matrix -// A to upper or lower bidiagonal form by an orthogonal transformation -// -// Q**T * A * P -// -// If m >= n, A is reduced to upper bidiagonal form and upon exit the elements -// on and below the diagonal in the first nb columns represent the elementary -// reflectors, and the elements above the diagonal in the first nb rows represent -// the matrix P. If m < n, A is reduced to lower bidiagonal form and the elements -// P is instead stored above the diagonal. -// -// The reduction to bidiagonal form is stored in d and e, where d are the diagonal -// elements, and e are the off-diagonal elements. -// -// The matrices Q and P are products of elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{nb-1} -// P = G_0 * G_1 * ... * G_{nb-1} -// -// where -// -// H_i = I - tauQ[i] * v_i * v_iᵀ -// G_i = I - tauP[i] * u_i * u_iᵀ -// -// As an example, on exit the entries of A when m = 6, n = 5, and nb = 2 -// -// [ 1 1 u1 u1 u1] -// [v1 1 1 u2 u2] -// [v1 v2 a a a] -// [v1 v2 a a a] -// [v1 v2 a a a] -// [v1 v2 a a a] -// -// and when m = 5, n = 6, and nb = 2 -// -// [ 1 u1 u1 u1 u1 u1] -// [ 1 1 u2 u2 u2 u2] -// [v1 1 a a a a] -// [v1 v2 a a a a] -// [v1 v2 a a a a] -// -// Dlabrd also returns the matrices X and Y which are used with U and V to -// apply the transformation to the unreduced part of the matrix -// -// A := A - V*Yᵀ - X*Uᵀ -// -// and returns the matrices X and Y which are needed to apply the -// transformation to the unreduced part of A. -// -// X is an m×nb matrix, Y is an n×nb matrix. d, e, taup, and tauq must all have -// length at least nb. Dlabrd will panic if these size constraints are violated. -// -// Dlabrd is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlabrd(m, n, nb int, a []float64, lda int, d, e, tauQ, tauP, x []float64, ldx int, y []float64, ldy int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case nb < 0: - panic(nbLT0) - case nb > n: - panic(nbGTN) - case nb > m: - panic(nbGTM) - case lda < max(1, n): - panic(badLdA) - case ldx < max(1, nb): - panic(badLdX) - case ldy < max(1, nb): - panic(badLdY) - } - - if m == 0 || n == 0 || nb == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(d) < nb: - panic(shortD) - case len(e) < nb: - panic(shortE) - case len(tauQ) < nb: - panic(shortTauQ) - case len(tauP) < nb: - panic(shortTauP) - case len(x) < (m-1)*ldx+nb: - panic(shortX) - case len(y) < (n-1)*ldy+nb: - panic(shortY) - } - - bi := blas64.Implementation() - - if m >= n { - // Reduce to upper bidiagonal form. - for i := 0; i < nb; i++ { - bi.Dgemv(blas.NoTrans, m-i, i, -1, a[i*lda:], lda, y[i*ldy:], 1, 1, a[i*lda+i:], lda) - bi.Dgemv(blas.NoTrans, m-i, i, -1, x[i*ldx:], ldx, a[i:], lda, 1, a[i*lda+i:], lda) - - a[i*lda+i], tauQ[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], lda) - d[i] = a[i*lda+i] - if i < n-1 { - // Compute Y[i+1:n, i]. - a[i*lda+i] = 1 - bi.Dgemv(blas.Trans, m-i, n-i-1, 1, a[i*lda+i+1:], lda, a[i*lda+i:], lda, 0, y[(i+1)*ldy+i:], ldy) - bi.Dgemv(blas.Trans, m-i, i, 1, a[i*lda:], lda, a[i*lda+i:], lda, 0, y[i:], ldy) - bi.Dgemv(blas.NoTrans, n-i-1, i, -1, y[(i+1)*ldy:], ldy, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) - bi.Dgemv(blas.Trans, m-i, i, 1, x[i*ldx:], ldx, a[i*lda+i:], lda, 0, y[i:], ldy) - bi.Dgemv(blas.Trans, i, n-i-1, -1, a[i+1:], lda, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) - bi.Dscal(n-i-1, tauQ[i], y[(i+1)*ldy+i:], ldy) - - // Update A[i, i+1:n]. - bi.Dgemv(blas.NoTrans, n-i-1, i+1, -1, y[(i+1)*ldy:], ldy, a[i*lda:], 1, 1, a[i*lda+i+1:], 1) - bi.Dgemv(blas.Trans, i, n-i-1, -1, a[i+1:], lda, x[i*ldx:], 1, 1, a[i*lda+i+1:], 1) - - // Generate reflection P[i] to annihilate A[i, i+2:n]. - a[i*lda+i+1], tauP[i] = impl.Dlarfg(n-i-1, a[i*lda+i+1], a[i*lda+min(i+2, n-1):], 1) - e[i] = a[i*lda+i+1] - a[i*lda+i+1] = 1 - - // Compute X[i+1:m, i]. - bi.Dgemv(blas.NoTrans, m-i-1, n-i-1, 1, a[(i+1)*lda+i+1:], lda, a[i*lda+i+1:], 1, 0, x[(i+1)*ldx+i:], ldx) - bi.Dgemv(blas.Trans, n-i-1, i+1, 1, y[(i+1)*ldy:], ldy, a[i*lda+i+1:], 1, 0, x[i:], ldx) - bi.Dgemv(blas.NoTrans, m-i-1, i+1, -1, a[(i+1)*lda:], lda, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) - bi.Dgemv(blas.NoTrans, i, n-i-1, 1, a[i+1:], lda, a[i*lda+i+1:], 1, 0, x[i:], ldx) - bi.Dgemv(blas.NoTrans, m-i-1, i, -1, x[(i+1)*ldx:], ldx, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) - bi.Dscal(m-i-1, tauP[i], x[(i+1)*ldx+i:], ldx) - } - } - return - } - // Reduce to lower bidiagonal form. - for i := 0; i < nb; i++ { - // Update A[i,i:n] - bi.Dgemv(blas.NoTrans, n-i, i, -1, y[i*ldy:], ldy, a[i*lda:], 1, 1, a[i*lda+i:], 1) - bi.Dgemv(blas.Trans, i, n-i, -1, a[i:], lda, x[i*ldx:], 1, 1, a[i*lda+i:], 1) - - // Generate reflection P[i] to annihilate A[i, i+1:n] - a[i*lda+i], tauP[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) - d[i] = a[i*lda+i] - if i < m-1 { - a[i*lda+i] = 1 - // Compute X[i+1:m, i]. - bi.Dgemv(blas.NoTrans, m-i-1, n-i, 1, a[(i+1)*lda+i:], lda, a[i*lda+i:], 1, 0, x[(i+1)*ldx+i:], ldx) - bi.Dgemv(blas.Trans, n-i, i, 1, y[i*ldy:], ldy, a[i*lda+i:], 1, 0, x[i:], ldx) - bi.Dgemv(blas.NoTrans, m-i-1, i, -1, a[(i+1)*lda:], lda, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) - bi.Dgemv(blas.NoTrans, i, n-i, 1, a[i:], lda, a[i*lda+i:], 1, 0, x[i:], ldx) - bi.Dgemv(blas.NoTrans, m-i-1, i, -1, x[(i+1)*ldx:], ldx, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) - bi.Dscal(m-i-1, tauP[i], x[(i+1)*ldx+i:], ldx) - - // Update A[i+1:m, i]. - bi.Dgemv(blas.NoTrans, m-i-1, i, -1, a[(i+1)*lda:], lda, y[i*ldy:], 1, 1, a[(i+1)*lda+i:], lda) - bi.Dgemv(blas.NoTrans, m-i-1, i+1, -1, x[(i+1)*ldx:], ldx, a[i:], lda, 1, a[(i+1)*lda+i:], lda) - - // Generate reflection Q[i] to annihilate A[i+2:m, i]. - a[(i+1)*lda+i], tauQ[i] = impl.Dlarfg(m-i-1, a[(i+1)*lda+i], a[min(i+2, m-1)*lda+i:], lda) - e[i] = a[(i+1)*lda+i] - a[(i+1)*lda+i] = 1 - - // Compute Y[i+1:n, i]. - bi.Dgemv(blas.Trans, m-i-1, n-i-1, 1, a[(i+1)*lda+i+1:], lda, a[(i+1)*lda+i:], lda, 0, y[(i+1)*ldy+i:], ldy) - bi.Dgemv(blas.Trans, m-i-1, i, 1, a[(i+1)*lda:], lda, a[(i+1)*lda+i:], lda, 0, y[i:], ldy) - bi.Dgemv(blas.NoTrans, n-i-1, i, -1, y[(i+1)*ldy:], ldy, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) - bi.Dgemv(blas.Trans, m-i-1, i+1, 1, x[(i+1)*ldx:], ldx, a[(i+1)*lda+i:], lda, 0, y[i:], ldy) - bi.Dgemv(blas.Trans, i+1, n-i-1, -1, a[i+1:], lda, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) - bi.Dscal(n-i-1, tauQ[i], y[(i+1)*ldy+i:], ldy) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go deleted file mode 100644 index cd6cf719..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlacn2 estimates the 1-norm of an n×n matrix A using sequential updates with -// matrix-vector products provided externally. -// -// Dlacn2 is called sequentially and it returns the value of est and kase to be -// used on the next call. -// On the initial call, kase must be 0. -// In between calls, x must be overwritten by -// -// A * X if kase was returned as 1, -// Aᵀ * X if kase was returned as 2, -// -// and all other parameters must not be changed. -// On the final return, kase is returned as 0, v contains A*W where W is a -// vector, and est = norm(V)/norm(W) is a lower bound for 1-norm of A. -// -// v, x, and isgn must all have length n and n must be at least 1, otherwise -// Dlacn2 will panic. isave is used for temporary storage. -// -// Dlacn2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) { - switch { - case n < 1: - panic(nLT1) - case len(v) < n: - panic(shortV) - case len(x) < n: - panic(shortX) - case len(isgn) < n: - panic(shortIsgn) - case isave[0] < 0 || 5 < isave[0]: - panic(badIsave) - case isave[0] == 0 && kase != 0: - panic(badIsave) - } - - const itmax = 5 - bi := blas64.Implementation() - - if kase == 0 { - for i := 0; i < n; i++ { - x[i] = 1 / float64(n) - } - kase = 1 - isave[0] = 1 - return est, kase - } - switch isave[0] { - case 1: - if n == 1 { - v[0] = x[0] - est = math.Abs(v[0]) - kase = 0 - return est, kase - } - est = bi.Dasum(n, x, 1) - for i := 0; i < n; i++ { - x[i] = math.Copysign(1, x[i]) - isgn[i] = int(x[i]) - } - kase = 2 - isave[0] = 2 - return est, kase - case 2: - isave[1] = bi.Idamax(n, x, 1) - isave[2] = 2 - for i := 0; i < n; i++ { - x[i] = 0 - } - x[isave[1]] = 1 - kase = 1 - isave[0] = 3 - return est, kase - case 3: - bi.Dcopy(n, x, 1, v, 1) - estold := est - est = bi.Dasum(n, v, 1) - sameSigns := true - for i := 0; i < n; i++ { - if int(math.Copysign(1, x[i])) != isgn[i] { - sameSigns = false - break - } - } - if !sameSigns && est > estold { - for i := 0; i < n; i++ { - x[i] = math.Copysign(1, x[i]) - isgn[i] = int(x[i]) - } - kase = 2 - isave[0] = 4 - return est, kase - } - case 4: - jlast := isave[1] - isave[1] = bi.Idamax(n, x, 1) - if x[jlast] != math.Abs(x[isave[1]]) && isave[2] < itmax { - isave[2] += 1 - for i := 0; i < n; i++ { - x[i] = 0 - } - x[isave[1]] = 1 - kase = 1 - isave[0] = 3 - return est, kase - } - case 5: - tmp := 2 * (bi.Dasum(n, x, 1)) / float64(3*n) - if tmp > est { - bi.Dcopy(n, x, 1, v, 1) - est = tmp - } - kase = 0 - return est, kase - } - // Iteration complete. Final stage - altsgn := 1.0 - for i := 0; i < n; i++ { - x[i] = altsgn * (1 + float64(i)/float64(n-1)) - altsgn *= -1 - } - kase = 1 - isave[0] = 5 - return est, kase -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go deleted file mode 100644 index 793bb8c7..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify -// a triangular portion with blas.Upper or blas.Lower, or can specify all of the -// elements with blas.All. -// -// Dlacpy is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower && uplo != blas.All: - panic(badUplo) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, n): - panic(badLdB) - } - - if m == 0 || n == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(b) < (m-1)*ldb+n: - panic(shortB) - } - - switch uplo { - case blas.Upper: - for i := 0; i < m; i++ { - for j := i; j < n; j++ { - b[i*ldb+j] = a[i*lda+j] - } - } - case blas.Lower: - for i := 0; i < m; i++ { - for j := 0; j < min(i+1, n); j++ { - b[i*ldb+j] = a[i*lda+j] - } - } - case blas.All: - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - b[i*ldb+j] = a[i*lda+j] - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go deleted file mode 100644 index 2eda3a18..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlae2.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "math" - -// Dlae2 computes the eigenvalues of a 2×2 symmetric matrix -// -// [a b] -// [b c] -// -// and returns the eigenvalue with the larger absolute value as rt1 and the -// smaller as rt2. -// -// Dlae2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlae2(a, b, c float64) (rt1, rt2 float64) { - sm := a + c - df := a - c - adf := math.Abs(df) - tb := b + b - ab := math.Abs(tb) - acmx := c - acmn := a - if math.Abs(a) > math.Abs(c) { - acmx = a - acmn = c - } - var rt float64 - if adf > ab { - rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) - } else if adf < ab { - rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) - } else { - rt = ab * math.Sqrt2 - } - if sm < 0 { - rt1 = 0.5 * (sm - rt) - rt2 = (acmx/rt1)*acmn - (b/rt1)*b - return rt1, rt2 - } - if sm > 0 { - rt1 = 0.5 * (sm + rt) - rt2 = (acmx/rt1)*acmn - (b/rt1)*b - return rt1, rt2 - } - rt1 = 0.5 * rt - rt2 = -0.5 * rt - return rt1, rt2 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go deleted file mode 100644 index 56923f51..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaev2.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlaev2 computes the Eigen decomposition of a symmetric 2×2 matrix. -// The matrix is given by -// -// [a b] -// [b c] -// -// Dlaev2 returns rt1 and rt2, the eigenvalues of the matrix where |RT1| > |RT2|, -// and [cs1, sn1] which is the unit right eigenvalue for RT1. -// -// [ cs1 sn1] [a b] [cs1 -sn1] = [rt1 0] -// [-sn1 cs1] [b c] [sn1 cs1] [ 0 rt2] -// -// Dlaev2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) { - sm := a + c - df := a - c - adf := math.Abs(df) - tb := b + b - ab := math.Abs(tb) - acmx := c - acmn := a - if math.Abs(a) > math.Abs(c) { - acmx = a - acmn = c - } - var rt float64 - if adf > ab { - rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) - } else if adf < ab { - rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) - } else { - rt = ab * math.Sqrt(2) - } - var sgn1 float64 - if sm < 0 { - rt1 = 0.5 * (sm - rt) - sgn1 = -1 - rt2 = (acmx/rt1)*acmn - (b/rt1)*b - } else if sm > 0 { - rt1 = 0.5 * (sm + rt) - sgn1 = 1 - rt2 = (acmx/rt1)*acmn - (b/rt1)*b - } else { - rt1 = 0.5 * rt - rt2 = -0.5 * rt - sgn1 = 1 - } - var cs, sgn2 float64 - if df >= 0 { - cs = df + rt - sgn2 = 1 - } else { - cs = df - rt - sgn2 = -1 - } - acs := math.Abs(cs) - if acs > ab { - ct := -tb / cs - sn1 = 1 / math.Sqrt(1+ct*ct) - cs1 = ct * sn1 - } else { - if ab == 0 { - cs1 = 1 - sn1 = 0 - } else { - tn := -cs / tb - cs1 = 1 / math.Sqrt(1+tn*tn) - sn1 = tn * cs1 - } - } - if sgn1 == sgn2 { - tn := cs1 - cs1 = -sn1 - sn1 = tn - } - return rt1, rt2, cs1, sn1 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go deleted file mode 100644 index 2b79bd8a..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlaexc swaps two adjacent diagonal blocks of order 1 or 2 in an n×n upper -// quasi-triangular matrix T by an orthogonal similarity transformation. -// -// T must be in Schur canonical form, that is, block upper triangular with 1×1 -// and 2×2 diagonal blocks; each 2×2 diagonal block has its diagonal elements -// equal and its off-diagonal elements of opposite sign. On return, T will -// contain the updated matrix again in Schur canonical form. -// -// If wantq is true, the transformation is accumulated in the n×n matrix Q, -// otherwise Q is not referenced. -// -// j1 is the index of the first row of the first block. n1 and n2 are the order -// of the first and second block, respectively. -// -// work must have length at least n, otherwise Dlaexc will panic. -// -// If ok is false, the transformed matrix T would be too far from Schur form. -// The blocks are not swapped, and T and Q are not modified. -// -// If n1 and n2 are both equal to 1, Dlaexc will always return true. -// -// Dlaexc is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaexc(wantq bool, n int, t []float64, ldt int, q []float64, ldq int, j1, n1, n2 int, work []float64) (ok bool) { - switch { - case n < 0: - panic(nLT0) - case ldt < max(1, n): - panic(badLdT) - case wantq && ldt < max(1, n): - panic(badLdQ) - case j1 < 0 || n <= j1: - panic(badJ1) - case len(work) < n: - panic(shortWork) - case n1 < 0 || 2 < n1: - panic(badN1) - case n2 < 0 || 2 < n2: - panic(badN2) - } - - if n == 0 || n1 == 0 || n2 == 0 { - return true - } - - switch { - case len(t) < (n-1)*ldt+n: - panic(shortT) - case wantq && len(q) < (n-1)*ldq+n: - panic(shortQ) - } - - if j1+n1 >= n { - // TODO(vladimir-ch): Reference LAPACK does this check whether - // the start of the second block is in the matrix T. It returns - // true if it is not and moreover it does not check whether the - // whole second block fits into T. This does not feel - // satisfactory. The only caller of Dlaexc is Dtrexc, so if the - // caller makes sure that this does not happen, we could be - // stricter here. - return true - } - - j2 := j1 + 1 - j3 := j1 + 2 - - bi := blas64.Implementation() - - if n1 == 1 && n2 == 1 { - // Swap two 1×1 blocks. - t11 := t[j1*ldt+j1] - t22 := t[j2*ldt+j2] - - // Determine the transformation to perform the interchange. - cs, sn, _ := impl.Dlartg(t[j1*ldt+j2], t22-t11) - - // Apply transformation to the matrix T. - if n-j3 > 0 { - bi.Drot(n-j3, t[j1*ldt+j3:], 1, t[j2*ldt+j3:], 1, cs, sn) - } - if j1 > 0 { - bi.Drot(j1, t[j1:], ldt, t[j2:], ldt, cs, sn) - } - - t[j1*ldt+j1] = t22 - t[j2*ldt+j2] = t11 - - if wantq { - // Accumulate transformation in the matrix Q. - bi.Drot(n, q[j1:], ldq, q[j2:], ldq, cs, sn) - } - - return true - } - - // Swapping involves at least one 2×2 block. - // - // Copy the diagonal block of order n1+n2 to the local array d and - // compute its norm. - nd := n1 + n2 - var d [16]float64 - const ldd = 4 - impl.Dlacpy(blas.All, nd, nd, t[j1*ldt+j1:], ldt, d[:], ldd) - dnorm := impl.Dlange(lapack.MaxAbs, nd, nd, d[:], ldd, work) - - // Compute machine-dependent threshold for test for accepting swap. - eps := dlamchP - thresh := math.Max(10*eps*dnorm, dlamchS/eps) - - // Solve T11*X - X*T22 = scale*T12 for X. - var x [4]float64 - const ldx = 2 - scale, _, _ := impl.Dlasy2(false, false, -1, n1, n2, d[:], ldd, d[n1*ldd+n1:], ldd, d[n1:], ldd, x[:], ldx) - - // Swap the adjacent diagonal blocks. - switch { - case n1 == 1 && n2 == 2: - // Generate elementary reflector H so that - // ( scale, X11, X12 ) H = ( 0, 0, * ) - u := [3]float64{scale, x[0], 1} - _, tau := impl.Dlarfg(3, x[1], u[:2], 1) - t11 := t[j1*ldt+j1] - - // Perform swap provisionally on diagonal block in d. - impl.Dlarfx(blas.Left, 3, 3, u[:], tau, d[:], ldd, work) - impl.Dlarfx(blas.Right, 3, 3, u[:], tau, d[:], ldd, work) - - // Test whether to reject swap. - if math.Max(math.Abs(d[2*ldd]), math.Max(math.Abs(d[2*ldd+1]), math.Abs(d[2*ldd+2]-t11))) > thresh { - return false - } - - // Accept swap: apply transformation to the entire matrix T. - impl.Dlarfx(blas.Left, 3, n-j1, u[:], tau, t[j1*ldt+j1:], ldt, work) - impl.Dlarfx(blas.Right, j2+1, 3, u[:], tau, t[j1:], ldt, work) - - t[j3*ldt+j1] = 0 - t[j3*ldt+j2] = 0 - t[j3*ldt+j3] = t11 - - if wantq { - // Accumulate transformation in the matrix Q. - impl.Dlarfx(blas.Right, n, 3, u[:], tau, q[j1:], ldq, work) - } - - case n1 == 2 && n2 == 1: - // Generate elementary reflector H so that: - // H ( -X11 ) = ( * ) - // ( -X21 ) = ( 0 ) - // ( scale ) = ( 0 ) - u := [3]float64{1, -x[ldx], scale} - _, tau := impl.Dlarfg(3, -x[0], u[1:], 1) - t33 := t[j3*ldt+j3] - - // Perform swap provisionally on diagonal block in D. - impl.Dlarfx(blas.Left, 3, 3, u[:], tau, d[:], ldd, work) - impl.Dlarfx(blas.Right, 3, 3, u[:], tau, d[:], ldd, work) - - // Test whether to reject swap. - if math.Max(math.Abs(d[ldd]), math.Max(math.Abs(d[2*ldd]), math.Abs(d[0]-t33))) > thresh { - return false - } - - // Accept swap: apply transformation to the entire matrix T. - impl.Dlarfx(blas.Right, j3+1, 3, u[:], tau, t[j1:], ldt, work) - impl.Dlarfx(blas.Left, 3, n-j1-1, u[:], tau, t[j1*ldt+j2:], ldt, work) - - t[j1*ldt+j1] = t33 - t[j2*ldt+j1] = 0 - t[j3*ldt+j1] = 0 - - if wantq { - // Accumulate transformation in the matrix Q. - impl.Dlarfx(blas.Right, n, 3, u[:], tau, q[j1:], ldq, work) - } - - default: // n1 == 2 && n2 == 2 - // Generate elementary reflectors H_1 and H_2 so that: - // H_2 H_1 ( -X11 -X12 ) = ( * * ) - // ( -X21 -X22 ) ( 0 * ) - // ( scale 0 ) ( 0 0 ) - // ( 0 scale ) ( 0 0 ) - u1 := [3]float64{1, -x[ldx], scale} - _, tau1 := impl.Dlarfg(3, -x[0], u1[1:], 1) - - temp := -tau1 * (x[1] + u1[1]*x[ldx+1]) - u2 := [3]float64{1, -temp * u1[2], scale} - _, tau2 := impl.Dlarfg(3, -temp*u1[1]-x[ldx+1], u2[1:], 1) - - // Perform swap provisionally on diagonal block in D. - impl.Dlarfx(blas.Left, 3, 4, u1[:], tau1, d[:], ldd, work) - impl.Dlarfx(blas.Right, 4, 3, u1[:], tau1, d[:], ldd, work) - impl.Dlarfx(blas.Left, 3, 4, u2[:], tau2, d[ldd:], ldd, work) - impl.Dlarfx(blas.Right, 4, 3, u2[:], tau2, d[1:], ldd, work) - - // Test whether to reject swap. - m1 := math.Max(math.Abs(d[2*ldd]), math.Abs(d[2*ldd+1])) - m2 := math.Max(math.Abs(d[3*ldd]), math.Abs(d[3*ldd+1])) - if math.Max(m1, m2) > thresh { - return false - } - - // Accept swap: apply transformation to the entire matrix T. - j4 := j1 + 3 - impl.Dlarfx(blas.Left, 3, n-j1, u1[:], tau1, t[j1*ldt+j1:], ldt, work) - impl.Dlarfx(blas.Right, j4+1, 3, u1[:], tau1, t[j1:], ldt, work) - impl.Dlarfx(blas.Left, 3, n-j1, u2[:], tau2, t[j2*ldt+j1:], ldt, work) - impl.Dlarfx(blas.Right, j4+1, 3, u2[:], tau2, t[j2:], ldt, work) - - t[j3*ldt+j1] = 0 - t[j3*ldt+j2] = 0 - t[j4*ldt+j1] = 0 - t[j4*ldt+j2] = 0 - - if wantq { - // Accumulate transformation in the matrix Q. - impl.Dlarfx(blas.Right, n, 3, u1[:], tau1, q[j1:], ldq, work) - impl.Dlarfx(blas.Right, n, 3, u2[:], tau2, q[j2:], ldq, work) - } - } - - if n2 == 2 { - // Standardize new 2×2 block T11. - a, b := t[j1*ldt+j1], t[j1*ldt+j2] - c, d := t[j2*ldt+j1], t[j2*ldt+j2] - var cs, sn float64 - t[j1*ldt+j1], t[j1*ldt+j2], t[j2*ldt+j1], t[j2*ldt+j2], _, _, _, _, cs, sn = impl.Dlanv2(a, b, c, d) - if n-j1-2 > 0 { - bi.Drot(n-j1-2, t[j1*ldt+j1+2:], 1, t[j2*ldt+j1+2:], 1, cs, sn) - } - if j1 > 0 { - bi.Drot(j1, t[j1:], ldt, t[j2:], ldt, cs, sn) - } - if wantq { - bi.Drot(n, q[j1:], ldq, q[j2:], ldq, cs, sn) - } - } - if n1 == 2 { - // Standardize new 2×2 block T22. - j3 := j1 + n2 - j4 := j3 + 1 - a, b := t[j3*ldt+j3], t[j3*ldt+j4] - c, d := t[j4*ldt+j3], t[j4*ldt+j4] - var cs, sn float64 - t[j3*ldt+j3], t[j3*ldt+j4], t[j4*ldt+j3], t[j4*ldt+j4], _, _, _, _, cs, sn = impl.Dlanv2(a, b, c, d) - if n-j3-2 > 0 { - bi.Drot(n-j3-2, t[j3*ldt+j3+2:], 1, t[j4*ldt+j3+2:], 1, cs, sn) - } - bi.Drot(j3, t[j3:], ldt, t[j4:], ldt, cs, sn) - if wantq { - bi.Drot(n, q[j3:], ldq, q[j4:], ldq, cs, sn) - } - } - - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlag2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlag2.go deleted file mode 100644 index cd644b65..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlag2.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import "math" - -// Dlag2 computes the eigenvalues of a 2×2 generalized eigenvalue problem -// -// A - w*B -// -// where B is an upper triangular matrix. -// -// Dlag2 uses scaling as necessary to avoid over-/underflow. Scaling results in -// a modified eigenvalue problem -// -// s*A - w*B -// -// where s is a non-negative scaling factor chosen so that w, w*B, and s*A do -// not overflow and, if possible, do not underflow, either. -// -// scale1 and scale2 are used to avoid over-/underflow in the eigenvalue -// equation which defines the first and second eigenvalue respectively. Note -// that scale1 and scale2 may be zero or less than the underflow threshold if -// the corresponding exact eigenvalue is sufficiently large. -// -// If the eigenvalues are real, then: -// - wi is zero, -// - the eigenvalues are wr1/scale1 and wr2/scale2. -// -// If the eigenvalues are complex, then: -// - wi is non-negative, -// - the eigenvalues are (wr1 ± wi*i)/scale1, -// - wr1 = wr2, -// - scale1 = scale2. -// -// Dlag2 assumes that the one-norm of A and B is less than 1/dlamchS. Entries of -// A less than sqrt(dlamchS)*norm(A) are subject to being treated as zero. The -// diagonals of B should be at least sqrt(dlamchS) times the largest element of -// B (in absolute value); if a diagonal is smaller than that, then -// ±sqrt(dlamchS) will be used instead of that diagonal. -// -// Dlag2 is an internal routine. It is exported for testing purposes. -func (Implementation) Dlag2(a []float64, lda int, b []float64, ldb int) (scale1, scale2, wr1, wr2, wi float64) { - switch { - case lda < 2: - panic(badLdA) - case ldb < 2: - panic(badLdB) - case len(a) < lda+2: - panic(shortA) - case len(b) < ldb+2: - panic(shortB) - } - - const ( - safmin = dlamchS - safmax = 1 / safmin - fuzzy1 = 1 + 1e-5 - ) - rtmin := math.Sqrt(safmin) - rtmax := 1 / rtmin - - // Scale A. - anorm := math.Max(math.Abs(a[0])+math.Abs(a[lda]), - math.Abs(a[1])+math.Abs(a[lda+1])) - anorm = math.Max(anorm, safmin) - ascale := 1 / anorm - a11 := ascale * a[0] - a21 := ascale * a[lda] - a12 := ascale * a[1] - a22 := ascale * a[lda+1] - - // Perturb B if necessary to insure non-singularity. - b11 := b[0] - b12 := b[1] - b22 := b[ldb+1] - bmin := rtmin * math.Max(math.Max(math.Abs(b11), math.Abs(b12)), - math.Max(math.Abs(b22), rtmin)) - if math.Abs(b11) < bmin { - b11 = math.Copysign(bmin, b11) - } - if math.Abs(b22) < bmin { - b22 = math.Copysign(bmin, b22) - } - - // Scale B. - bnorm := math.Max(math.Max(math.Abs(b11), math.Abs(b12)+math.Abs(b22)), safmin) - bsize := math.Max(math.Abs(b11), math.Abs(b22)) - bscale := 1 / bsize - b11 *= bscale - b12 *= bscale - b22 *= bscale - - // Compute larger eigenvalue by method described by C. van Loan. - var ( - as12, abi22 float64 - pp, qq, shift float64 - ) - binv11 := 1 / b11 - binv22 := 1 / b22 - s1 := a11 * binv11 - s2 := a22 * binv22 - // AS is A shifted by -shift*B. - if math.Abs(s1) <= math.Abs(s2) { - shift = s1 - as12 = a12 - shift*b12 - as22 := a22 - shift*b22 - ss := a21 * (binv11 * binv22) - abi22 = as22*binv22 - ss*b12 - pp = 0.5 * abi22 - qq = ss * as12 - } else { - shift = s2 - as12 = a12 - shift*b12 - as11 := a11 - shift*b11 - ss := a21 * (binv11 * binv22) - abi22 = -ss * b12 - pp = 0.5 * (as11*binv11 + abi22) - qq = ss * as12 - } - var discr, r float64 - if math.Abs(pp*rtmin) >= 1 { - tmp := rtmin * pp - discr = tmp*tmp + qq*safmin - r = math.Sqrt(math.Abs(discr)) * rtmax - } else { - pp2 := pp * pp - if pp2+math.Abs(qq) <= safmin { - tmp := rtmax * pp - discr = tmp*tmp + qq*safmax - r = math.Sqrt(math.Abs(discr)) * rtmin - } else { - discr = pp2 + qq - r = math.Sqrt(math.Abs(discr)) - } - } - - // TODO(vladimir-ch): Is the following comment from the reference needed in - // a Go implementation? - // - // Note: the test of r in the following `if` is to cover the case when discr - // is small and negative and is flushed to zero during the calculation of r. - // On machines which have a consistent flush-to-zero threshold and handle - // numbers above that threshold correctly, it would not be necessary. - if discr >= 0 || r == 0 { - sum := pp + math.Copysign(r, pp) - diff := pp - math.Copysign(r, pp) - wbig := shift + sum - - // Compute smaller eigenvalue. - wsmall := shift + diff - if 0.5*math.Abs(wbig) > math.Max(math.Abs(wsmall), safmin) { - wdet := (a11*a22 - a12*a21) * (binv11 * binv22) - wsmall = wdet / wbig - } - // Choose (real) eigenvalue closest to 2,2 element of A*B^{-1} for wr1. - if pp > abi22 { - wr1 = math.Min(wbig, wsmall) - wr2 = math.Max(wbig, wsmall) - } else { - wr1 = math.Max(wbig, wsmall) - wr2 = math.Min(wbig, wsmall) - } - } else { - // Complex eigenvalues. - wr1 = shift + pp - wr2 = wr1 - wi = r - } - - // Further scaling to avoid underflow and overflow in computing - // scale1 and overflow in computing w*B. - // - // This scale factor (wscale) is bounded from above using c1 and c2, - // and from below using c3 and c4: - // - c1 implements the condition s*A must never overflow. - // - c2 implements the condition w*B must never overflow. - // - c3, with c2, implement the condition that s*A - w*B must never overflow. - // - c4 implements the condition s should not underflow. - // - c5 implements the condition max(s,|w|) should be at least 2. - c1 := bsize * (safmin * math.Max(1, ascale)) - c2 := safmin * math.Max(1, bnorm) - c3 := bsize * safmin - c4 := 1.0 - c5 := 1.0 - if ascale <= 1 || bsize <= 1 { - c5 = math.Min(1, ascale*bsize) - if ascale <= 1 && bsize <= 1 { - c4 = math.Min(1, (ascale/safmin)*bsize) - } - } - - // Scale first eigenvalue. - wabs := math.Abs(wr1) + math.Abs(wi) - wsize := math.Max(math.Max(safmin, c1), math.Max(fuzzy1*(wabs*c2+c3), - math.Min(c4, 0.5*math.Max(wabs, c5)))) - maxABsize := math.Max(ascale, bsize) - minABsize := math.Min(ascale, bsize) - if wsize != 1 { - wscale := 1 / wsize - if wsize > 1 { - scale1 = (maxABsize * wscale) * minABsize - } else { - scale1 = (minABsize * wscale) * maxABsize - } - wr1 *= wscale - if wi != 0 { - wi *= wscale - wr2 = wr1 - scale2 = scale1 - } - } else { - scale1 = ascale * bsize - scale2 = scale1 - } - - // Scale second eigenvalue if real. - if wi == 0 { - wsize = math.Max(math.Max(safmin, c1), math.Max(fuzzy1*(math.Abs(wr2)*c2+c3), - math.Min(c4, 0.5*math.Max(math.Abs(wr2), c5)))) - if wsize != 1 { - wscale := 1 / wsize - if wsize > 1 { - scale2 = (maxABsize * wscale) * minABsize - } else { - scale2 = (minABsize * wscale) * maxABsize - } - wr2 *= wscale - } else { - scale2 = ascale * bsize - } - } - - return scale1, scale2, wr1, wr2, wi -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go deleted file mode 100644 index 7bd4f219..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlags2.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import "math" - -// Dlags2 computes 2-by-2 orthogonal matrices U, V and Q with the -// triangles of A and B specified by upper. -// -// If upper is true -// -// Uᵀ*A*Q = Uᵀ*[ a1 a2 ]*Q = [ x 0 ] -// [ 0 a3 ] [ x x ] -// -// and -// -// Vᵀ*B*Q = Vᵀ*[ b1 b2 ]*Q = [ x 0 ] -// [ 0 b3 ] [ x x ] -// -// otherwise -// -// Uᵀ*A*Q = Uᵀ*[ a1 0 ]*Q = [ x x ] -// [ a2 a3 ] [ 0 x ] -// -// and -// -// Vᵀ*B*Q = Vᵀ*[ b1 0 ]*Q = [ x x ] -// [ b2 b3 ] [ 0 x ]. -// -// The rows of the transformed A and B are parallel, where -// -// U = [ csu snu ], V = [ csv snv ], Q = [ csq snq ] -// [ -snu csu ] [ -snv csv ] [ -snq csq ] -// -// Dlags2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlags2(upper bool, a1, a2, a3, b1, b2, b3 float64) (csu, snu, csv, snv, csq, snq float64) { - if upper { - // Input matrices A and B are upper triangular matrices. - // - // Form matrix C = A*adj(B) = [ a b ] - // [ 0 d ] - a := a1 * b3 - d := a3 * b1 - b := a2*b1 - a1*b2 - - // The SVD of real 2-by-2 triangular C. - // - // [ csl -snl ]*[ a b ]*[ csr snr ] = [ r 0 ] - // [ snl csl ] [ 0 d ] [ -snr csr ] [ 0 t ] - _, _, snr, csr, snl, csl := impl.Dlasv2(a, b, d) - - if math.Abs(csl) >= math.Abs(snl) || math.Abs(csr) >= math.Abs(snr) { - // Compute the [0, 0] and [0, 1] elements of Uᵀ*A and Vᵀ*B, - // and [0, 1] element of |U|ᵀ*|A| and |V|ᵀ*|B|. - - ua11r := csl * a1 - ua12 := csl*a2 + snl*a3 - - vb11r := csr * b1 - vb12 := csr*b2 + snr*b3 - - aua12 := math.Abs(csl)*math.Abs(a2) + math.Abs(snl)*math.Abs(a3) - avb12 := math.Abs(csr)*math.Abs(b2) + math.Abs(snr)*math.Abs(b3) - - // Zero [0, 1] elements of Uᵀ*A and Vᵀ*B. - if math.Abs(ua11r)+math.Abs(ua12) != 0 { - if aua12/(math.Abs(ua11r)+math.Abs(ua12)) <= avb12/(math.Abs(vb11r)+math.Abs(vb12)) { - csq, snq, _ = impl.Dlartg(-ua11r, ua12) - } else { - csq, snq, _ = impl.Dlartg(-vb11r, vb12) - } - } else { - csq, snq, _ = impl.Dlartg(-vb11r, vb12) - } - - csu = csl - snu = -snl - csv = csr - snv = -snr - } else { - // Compute the [1, 0] and [1, 1] elements of Uᵀ*A and Vᵀ*B, - // and [1, 1] element of |U|ᵀ*|A| and |V|ᵀ*|B|. - - ua21 := -snl * a1 - ua22 := -snl*a2 + csl*a3 - - vb21 := -snr * b1 - vb22 := -snr*b2 + csr*b3 - - aua22 := math.Abs(snl)*math.Abs(a2) + math.Abs(csl)*math.Abs(a3) - avb22 := math.Abs(snr)*math.Abs(b2) + math.Abs(csr)*math.Abs(b3) - - // Zero [1, 1] elements of Uᵀ*A and Vᵀ*B, and then swap. - if math.Abs(ua21)+math.Abs(ua22) != 0 { - if aua22/(math.Abs(ua21)+math.Abs(ua22)) <= avb22/(math.Abs(vb21)+math.Abs(vb22)) { - csq, snq, _ = impl.Dlartg(-ua21, ua22) - } else { - csq, snq, _ = impl.Dlartg(-vb21, vb22) - } - } else { - csq, snq, _ = impl.Dlartg(-vb21, vb22) - } - - csu = snl - snu = csl - csv = snr - snv = csr - } - } else { - // Input matrices A and B are lower triangular matrices - // - // Form matrix C = A*adj(B) = [ a 0 ] - // [ c d ] - a := a1 * b3 - d := a3 * b1 - c := a2*b3 - a3*b2 - - // The SVD of real 2-by-2 triangular C - // - // [ csl -snl ]*[ a 0 ]*[ csr snr ] = [ r 0 ] - // [ snl csl ] [ c d ] [ -snr csr ] [ 0 t ] - _, _, snr, csr, snl, csl := impl.Dlasv2(a, c, d) - - if math.Abs(csr) >= math.Abs(snr) || math.Abs(csl) >= math.Abs(snl) { - // Compute the [1, 0] and [1, 1] elements of Uᵀ*A and Vᵀ*B, - // and [1, 0] element of |U|ᵀ*|A| and |V|ᵀ*|B|. - - ua21 := -snr*a1 + csr*a2 - ua22r := csr * a3 - - vb21 := -snl*b1 + csl*b2 - vb22r := csl * b3 - - aua21 := math.Abs(snr)*math.Abs(a1) + math.Abs(csr)*math.Abs(a2) - avb21 := math.Abs(snl)*math.Abs(b1) + math.Abs(csl)*math.Abs(b2) - - // Zero [1, 0] elements of Uᵀ*A and Vᵀ*B. - if (math.Abs(ua21) + math.Abs(ua22r)) != 0 { - if aua21/(math.Abs(ua21)+math.Abs(ua22r)) <= avb21/(math.Abs(vb21)+math.Abs(vb22r)) { - csq, snq, _ = impl.Dlartg(ua22r, ua21) - } else { - csq, snq, _ = impl.Dlartg(vb22r, vb21) - } - } else { - csq, snq, _ = impl.Dlartg(vb22r, vb21) - } - - csu = csr - snu = -snr - csv = csl - snv = -snl - } else { - // Compute the [0, 0] and [0, 1] elements of Uᵀ *A and Vᵀ *B, - // and [0, 0] element of |U|ᵀ*|A| and |V|ᵀ*|B|. - - ua11 := csr*a1 + snr*a2 - ua12 := snr * a3 - - vb11 := csl*b1 + snl*b2 - vb12 := snl * b3 - - aua11 := math.Abs(csr)*math.Abs(a1) + math.Abs(snr)*math.Abs(a2) - avb11 := math.Abs(csl)*math.Abs(b1) + math.Abs(snl)*math.Abs(b2) - - // Zero [0, 0] elements of Uᵀ*A and Vᵀ*B, and then swap. - if (math.Abs(ua11) + math.Abs(ua12)) != 0 { - if aua11/(math.Abs(ua11)+math.Abs(ua12)) <= avb11/(math.Abs(vb11)+math.Abs(vb12)) { - csq, snq, _ = impl.Dlartg(ua12, ua11) - } else { - csq, snq, _ = impl.Dlartg(vb12, vb11) - } - } else { - csq, snq, _ = impl.Dlartg(vb12, vb11) - } - - csu = snr - snu = csr - csv = snl - snv = csl - } - } - - return csu, snu, csv, snv, csq, snq -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlagtm.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlagtm.go deleted file mode 100644 index fc8c8eb4..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlagtm.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright ©2020 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dlagtm performs one of the matrix-matrix operations -// -// C = alpha * A * B + beta * C if trans == blas.NoTrans -// C = alpha * Aᵀ * B + beta * C if trans == blas.Trans or blas.ConjTrans -// -// where A is an m×m tridiagonal matrix represented by its diagonals dl, d, du, -// B and C are m×n dense matrices, and alpha and beta are scalars. -func (impl Implementation) Dlagtm(trans blas.Transpose, m, n int, alpha float64, dl, d, du []float64, b []float64, ldb int, beta float64, c []float64, ldc int) { - switch { - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case ldb < max(1, n): - panic(badLdB) - case ldc < max(1, n): - panic(badLdC) - } - - if m == 0 || n == 0 { - return - } - - switch { - case len(dl) < m-1: - panic(shortDL) - case len(d) < m: - panic(shortD) - case len(du) < m-1: - panic(shortDU) - case len(b) < (m-1)*ldb+n: - panic(shortB) - case len(c) < (m-1)*ldc+n: - panic(shortC) - } - - if beta != 1 { - if beta == 0 { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - for j := range ci { - ci[j] = 0 - } - } - } else { - for i := 0; i < m; i++ { - ci := c[i*ldc : i*ldc+n] - for j := range ci { - ci[j] *= beta - } - } - } - } - - if alpha == 0 { - return - } - - if m == 1 { - if alpha == 1 { - for j := 0; j < n; j++ { - c[j] += d[0] * b[j] - } - } else { - for j := 0; j < n; j++ { - c[j] += alpha * d[0] * b[j] - } - } - return - } - - if trans != blas.NoTrans { - dl, du = du, dl - } - - if alpha == 1 { - for j := 0; j < n; j++ { - c[j] += d[0]*b[j] + du[0]*b[ldb+j] - } - for i := 1; i < m-1; i++ { - for j := 0; j < n; j++ { - c[i*ldc+j] += dl[i-1]*b[(i-1)*ldb+j] + d[i]*b[i*ldb+j] + du[i]*b[(i+1)*ldb+j] - } - } - for j := 0; j < n; j++ { - c[(m-1)*ldc+j] += dl[m-2]*b[(m-2)*ldb+j] + d[m-1]*b[(m-1)*ldb+j] - } - } else { - for j := 0; j < n; j++ { - c[j] += alpha * (d[0]*b[j] + du[0]*b[ldb+j]) - } - for i := 1; i < m-1; i++ { - for j := 0; j < n; j++ { - c[i*ldc+j] += alpha * (dl[i-1]*b[(i-1)*ldb+j] + d[i]*b[i*ldb+j] + du[i]*b[(i+1)*ldb+j]) - } - } - for j := 0; j < n; j++ { - c[(m-1)*ldc+j] += alpha * (dl[m-2]*b[(m-2)*ldb+j] + d[m-1]*b[(m-1)*ldb+j]) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go deleted file mode 100644 index 6f120254..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go +++ /dev/null @@ -1,449 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlahqr computes the eigenvalues and Schur factorization of a block of an n×n -// upper Hessenberg matrix H, using the double-shift/single-shift QR algorithm. -// -// h and ldh represent the matrix H. Dlahqr works primarily with the Hessenberg -// submatrix H[ilo:ihi+1,ilo:ihi+1], but applies transformations to all of H if -// wantt is true. It is assumed that H[ihi+1:n,ihi+1:n] is already upper -// quasi-triangular, although this is not checked. -// -// It must hold that -// -// 0 <= ilo <= max(0,ihi), and ihi < n, -// -// and that -// -// H[ilo,ilo-1] == 0, if ilo > 0, -// -// otherwise Dlahqr will panic. -// -// If unconverged is zero on return, wr[ilo:ihi+1] and wi[ilo:ihi+1] will contain -// respectively the real and imaginary parts of the computed eigenvalues ilo -// to ihi. If two eigenvalues are computed as a complex conjugate pair, they are -// stored in consecutive elements of wr and wi, say the i-th and (i+1)th, with -// wi[i] > 0 and wi[i+1] < 0. If wantt is true, the eigenvalues are stored in -// the same order as on the diagonal of the Schur form returned in H, with -// wr[i] = H[i,i], and, if H[i:i+2,i:i+2] is a 2×2 diagonal block, -// wi[i] = sqrt(abs(H[i+1,i]*H[i,i+1])) and wi[i+1] = -wi[i]. -// -// wr and wi must have length ihi+1. -// -// z and ldz represent an n×n matrix Z. If wantz is true, the transformations -// will be applied to the submatrix Z[iloz:ihiz+1,ilo:ihi+1] and it must hold that -// -// 0 <= iloz <= ilo, and ihi <= ihiz < n. -// -// If wantz is false, z is not referenced. -// -// unconverged indicates whether Dlahqr computed all the eigenvalues ilo to ihi -// in a total of 30 iterations per eigenvalue. -// -// If unconverged is zero, all the eigenvalues ilo to ihi have been computed and -// will be stored on return in wr[ilo:ihi+1] and wi[ilo:ihi+1]. -// -// If unconverged is zero and wantt is true, H[ilo:ihi+1,ilo:ihi+1] will be -// overwritten on return by upper quasi-triangular full Schur form with any -// 2×2 diagonal blocks in standard form. -// -// If unconverged is zero and if wantt is false, the contents of h on return is -// unspecified. -// -// If unconverged is positive, some eigenvalues have not converged, and -// wr[unconverged:ihi+1] and wi[unconverged:ihi+1] contain those eigenvalues -// which have been successfully computed. -// -// If unconverged is positive and wantt is true, then on return -// -// (initial H)*U = U*(final H), (*) -// -// where U is an orthogonal matrix. The final H is upper Hessenberg and -// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. -// -// If unconverged is positive and wantt is false, on return the remaining -// unconverged eigenvalues are the eigenvalues of the upper Hessenberg matrix -// H[ilo:unconverged,ilo:unconverged]. -// -// If unconverged is positive and wantz is true, then on return -// -// (final Z) = (initial Z)*U, -// -// where U is the orthogonal matrix in (*) regardless of the value of wantt. -// -// Dlahqr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlahqr(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int) (unconverged int) { - switch { - case n < 0: - panic(nLT0) - case ilo < 0, max(0, ihi) < ilo: - panic(badIlo) - case ihi >= n: - panic(badIhi) - case ldh < max(1, n): - panic(badLdH) - case wantz && (iloz < 0 || ilo < iloz): - panic(badIloz) - case wantz && (ihiz < ihi || n <= ihiz): - panic(badIhiz) - case ldz < 1, wantz && ldz < n: - panic(badLdZ) - } - - // Quick return if possible. - if n == 0 { - return 0 - } - - switch { - case len(h) < (n-1)*ldh+n: - panic(shortH) - case len(wr) != ihi+1: - panic(shortWr) - case len(wi) != ihi+1: - panic(shortWi) - case wantz && len(z) < (n-1)*ldz+n: - panic(shortZ) - case ilo > 0 && h[ilo*ldh+ilo-1] != 0: - panic(notIsolated) - } - - if ilo == ihi { - wr[ilo] = h[ilo*ldh+ilo] - wi[ilo] = 0 - return 0 - } - - // Clear out the trash. - for j := ilo; j < ihi-2; j++ { - h[(j+2)*ldh+j] = 0 - h[(j+3)*ldh+j] = 0 - } - if ilo <= ihi-2 { - h[ihi*ldh+ihi-2] = 0 - } - - nh := ihi - ilo + 1 - nz := ihiz - iloz + 1 - - // Set machine-dependent constants for the stopping criterion. - ulp := dlamchP - smlnum := float64(nh) / ulp * dlamchS - - // i1 and i2 are the indices of the first row and last column of H to - // which transformations must be applied. If eigenvalues only are being - // computed, i1 and i2 are set inside the main loop. - var i1, i2 int - if wantt { - i1 = 0 - i2 = n - 1 - } - - itmax := 30 * max(10, nh) // Total number of QR iterations allowed. - - // kdefl counts the number of iterations since a deflation. - kdefl := 0 - - // The main loop begins here. i is the loop index and decreases from ihi - // to ilo in steps of 1 or 2. Each iteration of the loop works with the - // active submatrix in rows and columns l to i. Eigenvalues i+1 to ihi - // have already converged. Either l = ilo or H[l,l-1] is negligible so - // that the matrix splits. - bi := blas64.Implementation() - i := ihi - for i >= ilo { - l := ilo - - // Perform QR iterations on rows and columns ilo to i until a - // submatrix of order 1 or 2 splits off at the bottom because a - // subdiagonal element has become negligible. - converged := false - for its := 0; its <= itmax; its++ { - // Look for a single small subdiagonal element. - var k int - for k = i; k > l; k-- { - if math.Abs(h[k*ldh+k-1]) <= smlnum { - break - } - tst := math.Abs(h[(k-1)*ldh+k-1]) + math.Abs(h[k*ldh+k]) - if tst == 0 { - if k-2 >= ilo { - tst += math.Abs(h[(k-1)*ldh+k-2]) - } - if k+1 <= ihi { - tst += math.Abs(h[(k+1)*ldh+k]) - } - } - // The following is a conservative small - // subdiagonal deflation criterion due to Ahues - // & Tisseur (LAWN 122, 1997). It has better - // mathematical foundation and improves accuracy - // in some cases. - if math.Abs(h[k*ldh+k-1]) <= ulp*tst { - ab := math.Max(math.Abs(h[k*ldh+k-1]), math.Abs(h[(k-1)*ldh+k])) - ba := math.Min(math.Abs(h[k*ldh+k-1]), math.Abs(h[(k-1)*ldh+k])) - aa := math.Max(math.Abs(h[k*ldh+k]), math.Abs(h[(k-1)*ldh+k-1]-h[k*ldh+k])) - bb := math.Min(math.Abs(h[k*ldh+k]), math.Abs(h[(k-1)*ldh+k-1]-h[k*ldh+k])) - s := aa + ab - if ab/s*ba <= math.Max(smlnum, aa/s*bb*ulp) { - break - } - } - } - l = k - if l > ilo { - // H[l,l-1] is negligible. - h[l*ldh+l-1] = 0 - } - if l >= i-1 { - // Break the loop because a submatrix of order 1 - // or 2 has split off. - converged = true - break - } - kdefl++ - - // Now the active submatrix is in rows and columns l to - // i. If eigenvalues only are being computed, only the - // active submatrix need be transformed. - if !wantt { - i1 = l - i2 = i - } - - const ( - dat1 = 0.75 - dat2 = -0.4375 - kexsh = 10 - ) - var h11, h21, h12, h22 float64 - switch { - case kdefl%(2*kexsh) == 0: // Exceptional shift. - s := math.Abs(h[i*ldh+i-1]) + math.Abs(h[(i-1)*ldh+i-2]) - h11 = dat1*s + h[i*ldh+i] - h12 = dat2 * s - h21 = s - h22 = h11 - case kdefl%kexsh == 0: // Exceptional shift. - s := math.Abs(h[(l+1)*ldh+l]) + math.Abs(h[(l+2)*ldh+l+1]) - h11 = dat1*s + h[l*ldh+l] - h12 = dat2 * s - h21 = s - h22 = h11 - default: // Prepare to use Francis' double shift (i.e., - // 2nd degree generalized Rayleigh quotient). - h11 = h[(i-1)*ldh+i-1] - h21 = h[i*ldh+i-1] - h12 = h[(i-1)*ldh+i] - h22 = h[i*ldh+i] - } - s := math.Abs(h11) + math.Abs(h12) + math.Abs(h21) + math.Abs(h22) - var ( - rt1r, rt1i float64 - rt2r, rt2i float64 - ) - if s != 0 { - h11 /= s - h21 /= s - h12 /= s - h22 /= s - tr := (h11 + h22) / 2 - det := (h11-tr)*(h22-tr) - h12*h21 - rtdisc := math.Sqrt(math.Abs(det)) - if det >= 0 { - // Complex conjugate shifts. - rt1r = tr * s - rt2r = rt1r - rt1i = rtdisc * s - rt2i = -rt1i - } else { - // Real shifts (use only one of them). - rt1r = tr + rtdisc - rt2r = tr - rtdisc - if math.Abs(rt1r-h22) <= math.Abs(rt2r-h22) { - rt1r *= s - rt2r = rt1r - } else { - rt2r *= s - rt1r = rt2r - } - rt1i = 0 - rt2i = 0 - } - } - - // Look for two consecutive small subdiagonal elements. - var m int - var v [3]float64 - for m = i - 2; m >= l; m-- { - // Determine the effect of starting the - // double-shift QR iteration at row m, and see - // if this would make H[m,m-1] negligible. The - // following uses scaling to avoid overflows and - // most underflows. - h21s := h[(m+1)*ldh+m] - s := math.Abs(h[m*ldh+m]-rt2r) + math.Abs(rt2i) + math.Abs(h21s) - h21s /= s - v[0] = h21s*h[m*ldh+m+1] + (h[m*ldh+m]-rt1r)*((h[m*ldh+m]-rt2r)/s) - rt2i/s*rt1i - v[1] = h21s * (h[m*ldh+m] + h[(m+1)*ldh+m+1] - rt1r - rt2r) - v[2] = h21s * h[(m+2)*ldh+m+1] - s = math.Abs(v[0]) + math.Abs(v[1]) + math.Abs(v[2]) - v[0] /= s - v[1] /= s - v[2] /= s - if m == l { - break - } - dsum := math.Abs(h[(m-1)*ldh+m-1]) + math.Abs(h[m*ldh+m]) + math.Abs(h[(m+1)*ldh+m+1]) - if math.Abs(h[m*ldh+m-1])*(math.Abs(v[1])+math.Abs(v[2])) <= ulp*math.Abs(v[0])*dsum { - break - } - } - - // Double-shift QR step. - for k := m; k < i; k++ { - // The first iteration of this loop determines a - // reflection G from the vector V and applies it - // from left and right to H, thus creating a - // non-zero bulge below the subdiagonal. - // - // Each subsequent iteration determines a - // reflection G to restore the Hessenberg form - // in the (k-1)th column, and thus chases the - // bulge one step toward the bottom of the - // active submatrix. nr is the order of G. - - nr := min(3, i-k+1) - if k > m { - bi.Dcopy(nr, h[k*ldh+k-1:], ldh, v[:], 1) - } - var t0 float64 - v[0], t0 = impl.Dlarfg(nr, v[0], v[1:], 1) - if k > m { - h[k*ldh+k-1] = v[0] - h[(k+1)*ldh+k-1] = 0 - if k < i-1 { - h[(k+2)*ldh+k-1] = 0 - } - } else if m > l { - // Use the following instead of H[k,k-1] = -H[k,k-1] - // to avoid a bug when v[1] and v[2] underflow. - h[k*ldh+k-1] *= 1 - t0 - } - t1 := t0 * v[1] - if nr == 3 { - t2 := t0 * v[2] - - // Apply G from the left to transform - // the rows of the matrix in columns k - // to i2. - for j := k; j <= i2; j++ { - sum := h[k*ldh+j] + v[1]*h[(k+1)*ldh+j] + v[2]*h[(k+2)*ldh+j] - h[k*ldh+j] -= sum * t0 - h[(k+1)*ldh+j] -= sum * t1 - h[(k+2)*ldh+j] -= sum * t2 - } - - // Apply G from the right to transform - // the columns of the matrix in rows i1 - // to min(k+3,i). - for j := i1; j <= min(k+3, i); j++ { - sum := h[j*ldh+k] + v[1]*h[j*ldh+k+1] + v[2]*h[j*ldh+k+2] - h[j*ldh+k] -= sum * t0 - h[j*ldh+k+1] -= sum * t1 - h[j*ldh+k+2] -= sum * t2 - } - - if wantz { - // Accumulate transformations in the matrix Z. - for j := iloz; j <= ihiz; j++ { - sum := z[j*ldz+k] + v[1]*z[j*ldz+k+1] + v[2]*z[j*ldz+k+2] - z[j*ldz+k] -= sum * t0 - z[j*ldz+k+1] -= sum * t1 - z[j*ldz+k+2] -= sum * t2 - } - } - } else if nr == 2 { - // Apply G from the left to transform - // the rows of the matrix in columns k - // to i2. - for j := k; j <= i2; j++ { - sum := h[k*ldh+j] + v[1]*h[(k+1)*ldh+j] - h[k*ldh+j] -= sum * t0 - h[(k+1)*ldh+j] -= sum * t1 - } - - // Apply G from the right to transform - // the columns of the matrix in rows i1 - // to min(k+3,i). - for j := i1; j <= i; j++ { - sum := h[j*ldh+k] + v[1]*h[j*ldh+k+1] - h[j*ldh+k] -= sum * t0 - h[j*ldh+k+1] -= sum * t1 - } - - if wantz { - // Accumulate transformations in the matrix Z. - for j := iloz; j <= ihiz; j++ { - sum := z[j*ldz+k] + v[1]*z[j*ldz+k+1] - z[j*ldz+k] -= sum * t0 - z[j*ldz+k+1] -= sum * t1 - } - } - } - } - } - - if !converged { - // The QR iteration finished without splitting off a - // submatrix of order 1 or 2. - return i + 1 - } - - if l == i { - // H[i,i-1] is negligible: one eigenvalue has converged. - wr[i] = h[i*ldh+i] - wi[i] = 0 - } else if l == i-1 { - // H[i-1,i-2] is negligible: a pair of eigenvalues have converged. - - // Transform the 2×2 submatrix to standard Schur form, - // and compute and store the eigenvalues. - var cs, sn float64 - a, b := h[(i-1)*ldh+i-1], h[(i-1)*ldh+i] - c, d := h[i*ldh+i-1], h[i*ldh+i] - a, b, c, d, wr[i-1], wi[i-1], wr[i], wi[i], cs, sn = impl.Dlanv2(a, b, c, d) - h[(i-1)*ldh+i-1], h[(i-1)*ldh+i] = a, b - h[i*ldh+i-1], h[i*ldh+i] = c, d - - if wantt { - // Apply the transformation to the rest of H. - if i2 > i { - bi.Drot(i2-i, h[(i-1)*ldh+i+1:], 1, h[i*ldh+i+1:], 1, cs, sn) - } - bi.Drot(i-i1-1, h[i1*ldh+i-1:], ldh, h[i1*ldh+i:], ldh, cs, sn) - } - - if wantz { - // Apply the transformation to Z. - bi.Drot(nz, z[iloz*ldz+i-1:], ldz, z[iloz*ldz+i:], ldz, cs, sn) - } - } - - // Reset deflation counter. - kdefl = 0 - - // Return to start of the main loop with new value of i. - i = l - 1 - } - return 0 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go deleted file mode 100644 index 59214733..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlahr2 reduces the first nb columns of a real general n×(n-k+1) matrix A so -// that elements below the k-th subdiagonal are zero. The reduction is performed -// by an orthogonal similarity transformation Qᵀ * A * Q. Dlahr2 returns the -// matrices V and T which determine Q as a block reflector I - V*T*Vᵀ, and -// also the matrix Y = A * V * T. -// -// The matrix Q is represented as a product of nb elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{nb-1}. -// -// Each H_i has the form -// -// H_i = I - tau[i] * v * vᵀ, -// -// where v is a real vector with v[0:i+k-1] = 0 and v[i+k-1] = 1. v[i+k:n] is -// stored on exit in A[i+k+1:n,i]. -// -// The elements of the vectors v together form the (n-k+1)×nb matrix -// V which is needed, with T and Y, to apply the transformation to the -// unreduced part of the matrix, using an update of the form -// -// A = (I - V*T*Vᵀ) * (A - Y*Vᵀ). -// -// On entry, a contains the n×(n-k+1) general matrix A. On return, the elements -// on and above the k-th subdiagonal in the first nb columns are overwritten -// with the corresponding elements of the reduced matrix; the elements below the -// k-th subdiagonal, with the slice tau, represent the matrix Q as a product of -// elementary reflectors. The other columns of A are unchanged. -// -// The contents of A on exit are illustrated by the following example -// with n = 7, k = 3 and nb = 2: -// -// [ a a a a a ] -// [ a a a a a ] -// [ a a a a a ] -// [ h h a a a ] -// [ v0 h a a a ] -// [ v0 v1 a a a ] -// [ v0 v1 a a a ] -// -// where a denotes an element of the original matrix A, h denotes a -// modified element of the upper Hessenberg matrix H, and vi denotes an -// element of the vector defining H_i. -// -// k is the offset for the reduction. Elements below the k-th subdiagonal in the -// first nb columns are reduced to zero. -// -// nb is the number of columns to be reduced. -// -// On entry, a represents the n×(n-k+1) matrix A. On return, the elements on and -// above the k-th subdiagonal in the first nb columns are overwritten with the -// corresponding elements of the reduced matrix. The elements below the k-th -// subdiagonal, with the slice tau, represent the matrix Q as a product of -// elementary reflectors. The other columns of A are unchanged. -// -// tau will contain the scalar factors of the elementary reflectors. It must -// have length at least nb. -// -// t and ldt represent the nb×nb upper triangular matrix T, and y and ldy -// represent the n×nb matrix Y. -// -// Dlahr2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) { - switch { - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case nb < 0: - panic(nbLT0) - case nb > n: - panic(nbGTN) - case lda < max(1, n-k+1): - panic(badLdA) - case ldt < max(1, nb): - panic(badLdT) - case ldy < max(1, nb): - panic(badLdY) - } - - // Quick return if possible. - if n < 0 { - return - } - - switch { - case len(a) < (n-1)*lda+n-k+1: - panic(shortA) - case len(tau) < nb: - panic(shortTau) - case len(t) < (nb-1)*ldt+nb: - panic(shortT) - case len(y) < (n-1)*ldy+nb: - panic(shortY) - } - - // Quick return if possible. - if n == 1 { - return - } - - bi := blas64.Implementation() - var ei float64 - for i := 0; i < nb; i++ { - if i > 0 { - // Update A[k:n,i]. - - // Update i-th column of A - Y * Vᵀ. - bi.Dgemv(blas.NoTrans, n-k, i, - -1, y[k*ldy:], ldy, - a[(k+i-1)*lda:], 1, - 1, a[k*lda+i:], lda) - - // Apply I - V * Tᵀ * Vᵀ to this column (call it b) - // from the left, using the last column of T as - // workspace. - // Let V = [ V1 ] and b = [ b1 ] (first i rows) - // [ V2 ] [ b2 ] - // where V1 is unit lower triangular. - // - // w := V1ᵀ * b1. - bi.Dcopy(i, a[k*lda+i:], lda, t[nb-1:], ldt) - bi.Dtrmv(blas.Lower, blas.Trans, blas.Unit, i, - a[k*lda:], lda, t[nb-1:], ldt) - - // w := w + V2ᵀ * b2. - bi.Dgemv(blas.Trans, n-k-i, i, - 1, a[(k+i)*lda:], lda, - a[(k+i)*lda+i:], lda, - 1, t[nb-1:], ldt) - - // w := Tᵀ * w. - bi.Dtrmv(blas.Upper, blas.Trans, blas.NonUnit, i, - t, ldt, t[nb-1:], ldt) - - // b2 := b2 - V2*w. - bi.Dgemv(blas.NoTrans, n-k-i, i, - -1, a[(k+i)*lda:], lda, - t[nb-1:], ldt, - 1, a[(k+i)*lda+i:], lda) - - // b1 := b1 - V1*w. - bi.Dtrmv(blas.Lower, blas.NoTrans, blas.Unit, i, - a[k*lda:], lda, t[nb-1:], ldt) - bi.Daxpy(i, -1, t[nb-1:], ldt, a[k*lda+i:], lda) - - a[(k+i-1)*lda+i-1] = ei - } - - // Generate the elementary reflector H_i to annihilate - // A[k+i+1:n,i]. - ei, tau[i] = impl.Dlarfg(n-k-i, a[(k+i)*lda+i], a[min(k+i+1, n-1)*lda+i:], lda) - a[(k+i)*lda+i] = 1 - - // Compute Y[k:n,i]. - bi.Dgemv(blas.NoTrans, n-k, n-k-i, - 1, a[k*lda+i+1:], lda, - a[(k+i)*lda+i:], lda, - 0, y[k*ldy+i:], ldy) - bi.Dgemv(blas.Trans, n-k-i, i, - 1, a[(k+i)*lda:], lda, - a[(k+i)*lda+i:], lda, - 0, t[i:], ldt) - bi.Dgemv(blas.NoTrans, n-k, i, - -1, y[k*ldy:], ldy, - t[i:], ldt, - 1, y[k*ldy+i:], ldy) - bi.Dscal(n-k, tau[i], y[k*ldy+i:], ldy) - - // Compute T[0:i,i]. - bi.Dscal(i, -tau[i], t[i:], ldt) - bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, - t, ldt, t[i:], ldt) - - t[i*ldt+i] = tau[i] - } - a[(k+nb-1)*lda+nb-1] = ei - - // Compute Y[0:k,0:nb]. - impl.Dlacpy(blas.All, k, nb, a[1:], lda, y, ldy) - bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, k, nb, - 1, a[k*lda:], lda, y, ldy) - if n > k+nb { - bi.Dgemm(blas.NoTrans, blas.NoTrans, k, nb, n-k-nb, - 1, a[1+nb:], lda, - a[(k+nb)*lda:], lda, - 1, y, ldy) - } - bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, k, nb, - 1, t, ldt, y, ldy) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go deleted file mode 100644 index 54d44398..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "math" - -// Dlaln2 solves a linear equation or a system of 2 linear equations of the form -// -// (ca A - w D) X = scale B if trans == false, -// (ca Aᵀ - w D) X = scale B if trans == true, -// -// where A is a na×na real matrix, ca is a real scalar, D is a na×na diagonal -// real matrix, w is a scalar, real if nw == 1, complex if nw == 2, and X and B -// are na×1 matrices, real if w is real, complex if w is complex. -// -// If w is complex, X and B are represented as na×2 matrices, the first column -// of each being the real part and the second being the imaginary part. -// -// na and nw must be 1 or 2, otherwise Dlaln2 will panic. -// -// d1 and d2 are the diagonal elements of D. d2 is not used if na == 1. -// -// wr and wi represent the real and imaginary part, respectively, of the scalar -// w. wi is not used if nw == 1. -// -// smin is the desired lower bound on the singular values of A. This should be -// a safe distance away from underflow or overflow, say, between -// (underflow/machine precision) and (overflow*machine precision). -// -// If both singular values of (ca A - w D) are less than smin, smin*identity -// will be used instead of (ca A - w D). If only one singular value is less than -// smin, one element of (ca A - w D) will be perturbed enough to make the -// smallest singular value roughly smin. If both singular values are at least -// smin, (ca A - w D) will not be perturbed. In any case, the perturbation will -// be at most some small multiple of max(smin, ulp*norm(ca A - w D)). The -// singular values are computed by infinity-norm approximations, and thus will -// only be correct to a factor of 2 or so. -// -// All input quantities are assumed to be smaller than overflow by a reasonable -// factor. -// -// scale is a scaling factor less than or equal to 1 which is chosen so that X -// can be computed without overflow. X is further scaled if necessary to assure -// that norm(ca A - w D)*norm(X) is less than overflow. -// -// xnorm contains the infinity-norm of X when X is regarded as a na×nw real -// matrix. -// -// ok will be false if (ca A - w D) had to be perturbed to make its smallest -// singular value greater than smin, otherwise ok will be true. -// -// Dlaln2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaln2(trans bool, na, nw int, smin, ca float64, a []float64, lda int, d1, d2 float64, b []float64, ldb int, wr, wi float64, x []float64, ldx int) (scale, xnorm float64, ok bool) { - // TODO(vladimir-ch): Consider splitting this function into two, one - // handling the real case (nw == 1) and the other handling the complex - // case (nw == 2). Given that Go has complex types, their signatures - // would be simpler and more natural, and the implementation not as - // convoluted. - - switch { - case na != 1 && na != 2: - panic(badNa) - case nw != 1 && nw != 2: - panic(badNw) - case lda < na: - panic(badLdA) - case len(a) < (na-1)*lda+na: - panic(shortA) - case ldb < nw: - panic(badLdB) - case len(b) < (na-1)*ldb+nw: - panic(shortB) - case ldx < nw: - panic(badLdX) - case len(x) < (na-1)*ldx+nw: - panic(shortX) - } - - smlnum := 2 * dlamchS - bignum := 1 / smlnum - smini := math.Max(smin, smlnum) - - ok = true - scale = 1 - - if na == 1 { - // 1×1 (i.e., scalar) system C X = B. - - if nw == 1 { - // Real 1×1 system. - - // C = ca A - w D. - csr := ca*a[0] - wr*d1 - cnorm := math.Abs(csr) - - // If |C| < smini, use C = smini. - if cnorm < smini { - csr = smini - cnorm = smini - ok = false - } - - // Check scaling for X = B / C. - bnorm := math.Abs(b[0]) - if cnorm < 1 && bnorm > math.Max(1, bignum*cnorm) { - scale = 1 / bnorm - } - - // Compute X. - x[0] = b[0] * scale / csr - xnorm = math.Abs(x[0]) - - return scale, xnorm, ok - } - - // Complex 1×1 system (w is complex). - - // C = ca A - w D. - csr := ca*a[0] - wr*d1 - csi := -wi * d1 - cnorm := math.Abs(csr) + math.Abs(csi) - - // If |C| < smini, use C = smini. - if cnorm < smini { - csr = smini - csi = 0 - cnorm = smini - ok = false - } - - // Check scaling for X = B / C. - bnorm := math.Abs(b[0]) + math.Abs(b[1]) - if cnorm < 1 && bnorm > math.Max(1, bignum*cnorm) { - scale = 1 / bnorm - } - - // Compute X. - cx := complex(scale*b[0], scale*b[1]) / complex(csr, csi) - x[0], x[1] = real(cx), imag(cx) - xnorm = math.Abs(x[0]) + math.Abs(x[1]) - - return scale, xnorm, ok - } - - // 2×2 system. - - // Compute the real part of - // C = ca A - w D - // or - // C = ca Aᵀ - w D. - crv := [4]float64{ - ca*a[0] - wr*d1, - ca * a[1], - ca * a[lda], - ca*a[lda+1] - wr*d2, - } - if trans { - crv[1] = ca * a[lda] - crv[2] = ca * a[1] - } - - pivot := [4][4]int{ - {0, 1, 2, 3}, - {1, 0, 3, 2}, - {2, 3, 0, 1}, - {3, 2, 1, 0}, - } - - if nw == 1 { - // Real 2×2 system (w is real). - - // Find the largest element in C. - var cmax float64 - var icmax int - for j, v := range crv { - v = math.Abs(v) - if v > cmax { - cmax = v - icmax = j - } - } - - // If norm(C) < smini, use smini*identity. - if cmax < smini { - bnorm := math.Max(math.Abs(b[0]), math.Abs(b[ldb])) - if smini < 1 && bnorm > math.Max(1, bignum*smini) { - scale = 1 / bnorm - } - temp := scale / smini - x[0] = temp * b[0] - x[ldx] = temp * b[ldb] - xnorm = temp * bnorm - ok = false - - return scale, xnorm, ok - } - - // Gaussian elimination with complete pivoting. - // Form upper triangular matrix - // [ur11 ur12] - // [ 0 ur22] - ur11 := crv[icmax] - ur12 := crv[pivot[icmax][1]] - cr21 := crv[pivot[icmax][2]] - cr22 := crv[pivot[icmax][3]] - ur11r := 1 / ur11 - lr21 := ur11r * cr21 - ur22 := cr22 - ur12*lr21 - - // If smaller pivot < smini, use smini. - if math.Abs(ur22) < smini { - ur22 = smini - ok = false - } - - var br1, br2 float64 - if icmax > 1 { - // If the pivot lies in the second row, swap the rows. - br1 = b[ldb] - br2 = b[0] - } else { - br1 = b[0] - br2 = b[ldb] - } - br2 -= lr21 * br1 // Apply the Gaussian elimination step to the right-hand side. - - bbnd := math.Max(math.Abs(ur22*ur11r*br1), math.Abs(br2)) - if bbnd > 1 && math.Abs(ur22) < 1 && bbnd >= bignum*math.Abs(ur22) { - scale = 1 / bbnd - } - - // Solve the linear system ur*xr=br. - xr2 := br2 * scale / ur22 - xr1 := scale*br1*ur11r - ur11r*ur12*xr2 - if icmax&0x1 != 0 { - // If the pivot lies in the second column, swap the components of the solution. - x[0] = xr2 - x[ldx] = xr1 - } else { - x[0] = xr1 - x[ldx] = xr2 - } - xnorm = math.Max(math.Abs(xr1), math.Abs(xr2)) - - // Further scaling if norm(A)*norm(X) > overflow. - if xnorm > 1 && cmax > 1 && xnorm > bignum/cmax { - temp := cmax / bignum - x[0] *= temp - x[ldx] *= temp - xnorm *= temp - scale *= temp - } - - return scale, xnorm, ok - } - - // Complex 2×2 system (w is complex). - - // Find the largest element in C. - civ := [4]float64{ - -wi * d1, - 0, - 0, - -wi * d2, - } - var cmax float64 - var icmax int - for j, v := range crv { - v := math.Abs(v) - if v+math.Abs(civ[j]) > cmax { - cmax = v + math.Abs(civ[j]) - icmax = j - } - } - - // If norm(C) < smini, use smini*identity. - if cmax < smini { - br1 := math.Abs(b[0]) + math.Abs(b[1]) - br2 := math.Abs(b[ldb]) + math.Abs(b[ldb+1]) - bnorm := math.Max(br1, br2) - if smini < 1 && bnorm > 1 && bnorm > bignum*smini { - scale = 1 / bnorm - } - temp := scale / smini - x[0] = temp * b[0] - x[1] = temp * b[1] - x[ldb] = temp * b[ldb] - x[ldb+1] = temp * b[ldb+1] - xnorm = temp * bnorm - ok = false - - return scale, xnorm, ok - } - - // Gaussian elimination with complete pivoting. - ur11 := crv[icmax] - ui11 := civ[icmax] - ur12 := crv[pivot[icmax][1]] - ui12 := civ[pivot[icmax][1]] - cr21 := crv[pivot[icmax][2]] - ci21 := civ[pivot[icmax][2]] - cr22 := crv[pivot[icmax][3]] - ci22 := civ[pivot[icmax][3]] - var ( - ur11r, ui11r float64 - lr21, li21 float64 - ur12s, ui12s float64 - ur22, ui22 float64 - ) - if icmax == 0 || icmax == 3 { - // Off-diagonals of pivoted C are real. - if math.Abs(ur11) > math.Abs(ui11) { - temp := ui11 / ur11 - ur11r = 1 / (ur11 * (1 + temp*temp)) - ui11r = -temp * ur11r - } else { - temp := ur11 / ui11 - ui11r = -1 / (ui11 * (1 + temp*temp)) - ur11r = -temp * ui11r - } - lr21 = cr21 * ur11r - li21 = cr21 * ui11r - ur12s = ur12 * ur11r - ui12s = ur12 * ui11r - ur22 = cr22 - ur12*lr21 - ui22 = ci22 - ur12*li21 - } else { - // Diagonals of pivoted C are real. - ur11r = 1 / ur11 - // ui11r is already 0. - lr21 = cr21 * ur11r - li21 = ci21 * ur11r - ur12s = ur12 * ur11r - ui12s = ui12 * ur11r - ur22 = cr22 - ur12*lr21 + ui12*li21 - ui22 = -ur12*li21 - ui12*lr21 - } - u22abs := math.Abs(ur22) + math.Abs(ui22) - - // If smaller pivot < smini, use smini. - if u22abs < smini { - ur22 = smini - ui22 = 0 - ok = false - } - - var br1, bi1 float64 - var br2, bi2 float64 - if icmax > 1 { - // If the pivot lies in the second row, swap the rows. - br1 = b[ldb] - bi1 = b[ldb+1] - br2 = b[0] - bi2 = b[1] - } else { - br1 = b[0] - bi1 = b[1] - br2 = b[ldb] - bi2 = b[ldb+1] - } - br2 += -lr21*br1 + li21*bi1 - bi2 += -li21*br1 - lr21*bi1 - - bbnd1 := u22abs * (math.Abs(ur11r) + math.Abs(ui11r)) * (math.Abs(br1) + math.Abs(bi1)) - bbnd2 := math.Abs(br2) + math.Abs(bi2) - bbnd := math.Max(bbnd1, bbnd2) - if bbnd > 1 && u22abs < 1 && bbnd >= bignum*u22abs { - scale = 1 / bbnd - br1 *= scale - bi1 *= scale - br2 *= scale - bi2 *= scale - } - - cx2 := complex(br2, bi2) / complex(ur22, ui22) - xr2, xi2 := real(cx2), imag(cx2) - xr1 := ur11r*br1 - ui11r*bi1 - ur12s*xr2 + ui12s*xi2 - xi1 := ui11r*br1 + ur11r*bi1 - ui12s*xr2 - ur12s*xi2 - if icmax&0x1 != 0 { - // If the pivot lies in the second column, swap the components of the solution. - x[0] = xr2 - x[1] = xi2 - x[ldx] = xr1 - x[ldx+1] = xi1 - } else { - x[0] = xr1 - x[1] = xi1 - x[ldx] = xr2 - x[ldx+1] = xi2 - } - xnorm = math.Max(math.Abs(xr1)+math.Abs(xi1), math.Abs(xr2)+math.Abs(xi2)) - - // Further scaling if norm(A)*norm(X) > overflow. - if xnorm > 1 && cmax > 1 && xnorm > bignum/cmax { - temp := cmax / bignum - x[0] *= temp - x[1] *= temp - x[ldx] *= temp - x[ldx+1] *= temp - xnorm *= temp - scale *= temp - } - - return scale, xnorm, ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlangb.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlangb.go deleted file mode 100644 index 4b7b449f..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlangb.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/internal/asm/f64" - "gonum.org/v1/gonum/lapack" -) - -// Dlangb returns the given norm of an m×n band matrix with kl sub-diagonals and -// ku super-diagonals. -func (impl Implementation) Dlangb(norm lapack.MatrixNorm, m, n, kl, ku int, ab []float64, ldab int) float64 { - ncol := kl + 1 + ku - switch { - case norm != lapack.MaxAbs && norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius: - panic(badNorm) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case kl < 0: - panic(klLT0) - case ku < 0: - panic(kuLT0) - case ldab < ncol: - panic(badLdA) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return 0 - } - - switch { - case len(ab) < min(m, n+kl)*ldab: - panic(shortAB) - } - - var value float64 - switch norm { - case lapack.MaxAbs: - for i := 0; i < min(m, n+kl); i++ { - l := max(0, kl-i) - u := min(n+kl-i, ncol) - for _, aij := range ab[i*ldab+l : i*ldab+u] { - aij = math.Abs(aij) - if aij > value || math.IsNaN(aij) { - value = aij - } - } - } - case lapack.MaxRowSum: - for i := 0; i < min(m, n+kl); i++ { - l := max(0, kl-i) - u := min(n+kl-i, ncol) - sum := f64.L1Norm(ab[i*ldab+l : i*ldab+u]) - if sum > value || math.IsNaN(sum) { - value = sum - } - } - case lapack.MaxColumnSum: - for j := 0; j < min(m+ku, n); j++ { - jb := min(kl+j, ncol-1) - ib := max(0, j-ku) - jlen := min(j+kl, m-1) - ib + 1 - sum := f64.L1NormInc(ab[ib*ldab+jb:], jlen, max(1, ldab-1)) - if sum > value || math.IsNaN(sum) { - value = sum - } - } - case lapack.Frobenius: - scale := 0.0 - sum := 1.0 - for i := 0; i < min(m, n+kl); i++ { - l := max(0, kl-i) - u := min(n+kl-i, ncol) - ilen := u - l - scale, sum = impl.Dlassq(ilen, ab[i*ldab+l:], 1, scale, sum) - } - value = scale * math.Sqrt(sum) - } - return value -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go deleted file mode 100644 index 3a00dce1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/lapack" -) - -// Dlange returns the value of the specified norm of a general m×n matrix A: -// -// lapack.MaxAbs: the maximum absolute value of any element. -// lapack.MaxColumnSum: the maximum column sum of the absolute values of the elements (1-norm). -// lapack.MaxRowSum: the maximum row sum of the absolute values of the elements (infinity-norm). -// lapack.Frobenius: the square root of the sum of the squares of the elements (Frobenius norm). -// -// If norm == lapack.MaxColumnSum, work must be of length n, and this function will -// panic otherwise. There are no restrictions on work for the other matrix norms. -func (impl Implementation) Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 { - // TODO(btracey): These should probably be refactored to use BLAS calls. - switch { - case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: - panic(badNorm) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return 0 - } - - switch { - case len(a) < (m-1)*lda+n: - panic(badLdA) - case norm == lapack.MaxColumnSum && len(work) < n: - panic(shortWork) - } - - switch norm { - case lapack.MaxAbs: - var value float64 - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - value = math.Max(value, math.Abs(a[i*lda+j])) - } - } - return value - case lapack.MaxColumnSum: - for i := 0; i < n; i++ { - work[i] = 0 - } - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - work[j] += math.Abs(a[i*lda+j]) - } - } - var value float64 - for i := 0; i < n; i++ { - value = math.Max(value, work[i]) - } - return value - case lapack.MaxRowSum: - var value float64 - for i := 0; i < m; i++ { - var sum float64 - for j := 0; j < n; j++ { - sum += math.Abs(a[i*lda+j]) - } - value = math.Max(value, sum) - } - return value - default: - // lapack.Frobenius - scale := 0.0 - sum := 1.0 - for i := 0; i < m; i++ { - scale, sum = impl.Dlassq(n, a[i*lda:], 1, scale, sum) - } - return scale * math.Sqrt(sum) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlangt.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlangt.go deleted file mode 100644 index cd1c49b5..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlangt.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright ©2020 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/lapack" -) - -// Dlangt returns the value of the given norm of an n×n tridiagonal matrix -// represented by the three diagonals. -// -// d must have length at least n and dl and du must have length at least n-1. -func (impl Implementation) Dlangt(norm lapack.MatrixNorm, n int, dl, d, du []float64) float64 { - switch { - case norm != lapack.MaxAbs && norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius: - panic(badNorm) - case n < 0: - panic(nLT0) - } - - if n == 0 { - return 0 - } - - switch { - case len(dl) < n-1: - panic(shortDL) - case len(d) < n: - panic(shortD) - case len(du) < n-1: - panic(shortDU) - } - - dl = dl[:n-1] - d = d[:n] - du = du[:n-1] - - var anorm float64 - switch norm { - case lapack.MaxAbs: - for _, diag := range [][]float64{dl, d, du} { - for _, di := range diag { - if math.IsNaN(di) { - return di - } - di = math.Abs(di) - if di > anorm { - anorm = di - } - } - } - case lapack.MaxColumnSum: - if n == 1 { - return math.Abs(d[0]) - } - anorm = math.Abs(d[0]) + math.Abs(dl[0]) - if math.IsNaN(anorm) { - return anorm - } - tmp := math.Abs(du[n-2]) + math.Abs(d[n-1]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > anorm { - anorm = tmp - } - for i := 1; i < n-1; i++ { - tmp = math.Abs(du[i-1]) + math.Abs(d[i]) + math.Abs(dl[i]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > anorm { - anorm = tmp - } - } - case lapack.MaxRowSum: - if n == 1 { - return math.Abs(d[0]) - } - anorm = math.Abs(d[0]) + math.Abs(du[0]) - if math.IsNaN(anorm) { - return anorm - } - tmp := math.Abs(dl[n-2]) + math.Abs(d[n-1]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > anorm { - anorm = tmp - } - for i := 1; i < n-1; i++ { - tmp = math.Abs(dl[i-1]) + math.Abs(d[i]) + math.Abs(du[i]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > anorm { - anorm = tmp - } - } - case lapack.Frobenius: - scale := 0.0 - ssq := 1.0 - scale, ssq = impl.Dlassq(n, d, 1, scale, ssq) - if n > 1 { - scale, ssq = impl.Dlassq(n-1, dl, 1, scale, ssq) - scale, ssq = impl.Dlassq(n-1, du, 1, scale, ssq) - } - anorm = scale * math.Sqrt(ssq) - } - return anorm -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanhs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanhs.go deleted file mode 100644 index 054b90f0..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanhs.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright ©2023 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlanhs returns the value of the one norm, or the Frobenius norm, or the -// infinity norm, or the element of largest absolute value of a Hessenberg -// matrix A. -// -// If norm is lapack.MaxColumnSum, work must have length at least n. -func (impl Implementation) Dlanhs(norm lapack.MatrixNorm, n int, a []float64, lda int, work []float64) float64 { - switch { - case norm != lapack.MaxRowSum && norm != lapack.MaxAbs && norm != lapack.MaxColumnSum && norm != lapack.Frobenius: - panic(badNorm) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 { - return 0 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case norm == lapack.MaxColumnSum && len(work) < n: - panic(shortWork) - } - - bi := blas64.Implementation() - var value float64 - switch norm { - case lapack.MaxAbs: - for i := 0; i < n; i++ { - minj := max(0, i-1) - for _, v := range a[i*lda+minj : i*lda+n] { - value = math.Max(value, math.Abs(v)) - } - } - case lapack.MaxColumnSum: - for i := 0; i < n; i++ { - work[i] = 0 - } - for i := 0; i < n; i++ { - for j := max(0, i-1); j < n; j++ { - work[j] += math.Abs(a[i*lda+j]) - } - } - for _, v := range work[:n] { - value = math.Max(value, v) - } - case lapack.MaxRowSum: - for i := 0; i < n; i++ { - minj := max(0, i-1) - sum := bi.Dasum(n-minj, a[i*lda+minj:], 1) - value = math.Max(value, sum) - } - case lapack.Frobenius: - scale := 0.0 - sum := 1.0 - for i := 0; i < n; i++ { - minj := max(0, i-1) - scale, sum = impl.Dlassq(n-minj, a[i*lda+minj:], 1, scale, sum) - } - value = scale * math.Sqrt(sum) - } - return value -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlansb.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlansb.go deleted file mode 100644 index 17801f84..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlansb.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright ©2019 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dlansb returns the given norm of an n×n symmetric band matrix with kd -// super-diagonals. -// -// When norm is lapack.MaxColumnSum or lapack.MaxRowSum, the length of work must -// be at least n. -func (impl Implementation) Dlansb(norm lapack.MatrixNorm, uplo blas.Uplo, n, kd int, ab []float64, ldab int, work []float64) float64 { - switch { - case norm != lapack.MaxAbs && norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius: - panic(badNorm) - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case kd < 0: - panic(kdLT0) - case ldab < kd+1: - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 0 - } - - switch { - case len(ab) < (n-1)*ldab+kd+1: - panic(shortAB) - case len(work) < n && (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum): - panic(shortWork) - } - - var value float64 - switch norm { - case lapack.MaxAbs: - if uplo == blas.Upper { - for i := 0; i < n; i++ { - for j := 0; j < min(n-i, kd+1); j++ { - aij := math.Abs(ab[i*ldab+j]) - if aij > value || math.IsNaN(aij) { - value = aij - } - } - } - } else { - for i := 0; i < n; i++ { - for j := max(0, kd-i); j < kd+1; j++ { - aij := math.Abs(ab[i*ldab+j]) - if aij > value || math.IsNaN(aij) { - value = aij - } - } - } - } - case lapack.MaxColumnSum, lapack.MaxRowSum: - work = work[:n] - var sum float64 - if uplo == blas.Upper { - for i := range work { - work[i] = 0 - } - for i := 0; i < n; i++ { - sum := work[i] + math.Abs(ab[i*ldab]) - for j := i + 1; j < min(i+kd+1, n); j++ { - aij := math.Abs(ab[i*ldab+j-i]) - sum += aij - work[j] += aij - } - if sum > value || math.IsNaN(sum) { - value = sum - } - } - } else { - for i := 0; i < n; i++ { - sum = 0 - for j := max(0, i-kd); j < i; j++ { - aij := math.Abs(ab[i*ldab+kd+j-i]) - sum += aij - work[j] += aij - } - work[i] = sum + math.Abs(ab[i*ldab+kd]) - } - for _, sum := range work { - if sum > value || math.IsNaN(sum) { - value = sum - } - } - } - case lapack.Frobenius: - scale := 0.0 - sum := 1.0 - if uplo == blas.Upper { - if kd > 0 { - // Sum off-diagonals. - for i := 0; i < n-1; i++ { - ilen := min(n-i-1, kd) - scale, sum = impl.Dlassq(ilen, ab[i*ldab+1:], 1, scale, sum) - } - sum *= 2 - } - // Sum diagonal. - scale, sum = impl.Dlassq(n, ab, ldab, scale, sum) - } else { - if kd > 0 { - // Sum off-diagonals. - for i := 1; i < n; i++ { - ilen := min(i, kd) - scale, sum = impl.Dlassq(ilen, ab[i*ldab+kd-ilen:], 1, scale, sum) - } - sum *= 2 - } - // Sum diagonal. - scale, sum = impl.Dlassq(n, ab[kd:], ldab, scale, sum) - } - value = scale * math.Sqrt(sum) - } - - return value -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go deleted file mode 100644 index 9ca1897e..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/lapack" -) - -// Dlanst computes the specified norm of a symmetric tridiagonal matrix A. -// The diagonal elements of A are stored in d and the off-diagonal elements -// are stored in e. -func (impl Implementation) Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) float64 { - switch { - case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: - panic(badNorm) - case n < 0: - panic(nLT0) - } - if n == 0 { - return 0 - } - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - } - - switch norm { - default: - panic(badNorm) - case lapack.MaxAbs: - anorm := math.Abs(d[n-1]) - for i := 0; i < n-1; i++ { - sum := math.Abs(d[i]) - if anorm < sum || math.IsNaN(sum) { - anorm = sum - } - sum = math.Abs(e[i]) - if anorm < sum || math.IsNaN(sum) { - anorm = sum - } - } - return anorm - case lapack.MaxColumnSum, lapack.MaxRowSum: - if n == 1 { - return math.Abs(d[0]) - } - anorm := math.Abs(d[0]) + math.Abs(e[0]) - sum := math.Abs(e[n-2]) + math.Abs(d[n-1]) - if anorm < sum || math.IsNaN(sum) { - anorm = sum - } - for i := 1; i < n-1; i++ { - sum := math.Abs(d[i]) + math.Abs(e[i]) + math.Abs(e[i-1]) - if anorm < sum || math.IsNaN(sum) { - anorm = sum - } - } - return anorm - case lapack.Frobenius: - var scale float64 - sum := 1.0 - if n > 1 { - scale, sum = impl.Dlassq(n-1, e, 1, scale, sum) - sum = 2 * sum - } - scale, sum = impl.Dlassq(n, d, 1, scale, sum) - return scale * math.Sqrt(sum) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go deleted file mode 100644 index b972c72e..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dlansy returns the value of the specified norm of an n×n symmetric matrix. If -// norm == lapack.MaxColumnSum or norm == lapack.MaxRowSum, work must have length -// at least n, otherwise work is unused. -func (impl Implementation) Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 { - switch { - case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: - panic(badNorm) - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 0 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum) && len(work) < n: - panic(shortWork) - } - - switch norm { - case lapack.MaxAbs: - if uplo == blas.Upper { - var max float64 - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - v := math.Abs(a[i*lda+j]) - if math.IsNaN(v) { - return math.NaN() - } - if v > max { - max = v - } - } - } - return max - } - var max float64 - for i := 0; i < n; i++ { - for j := 0; j <= i; j++ { - v := math.Abs(a[i*lda+j]) - if math.IsNaN(v) { - return math.NaN() - } - if v > max { - max = v - } - } - } - return max - case lapack.MaxRowSum, lapack.MaxColumnSum: - // A symmetric matrix has the same 1-norm and ∞-norm. - for i := 0; i < n; i++ { - work[i] = 0 - } - if uplo == blas.Upper { - for i := 0; i < n; i++ { - work[i] += math.Abs(a[i*lda+i]) - for j := i + 1; j < n; j++ { - v := math.Abs(a[i*lda+j]) - work[i] += v - work[j] += v - } - } - } else { - for i := 0; i < n; i++ { - for j := 0; j < i; j++ { - v := math.Abs(a[i*lda+j]) - work[i] += v - work[j] += v - } - work[i] += math.Abs(a[i*lda+i]) - } - } - var max float64 - for i := 0; i < n; i++ { - v := work[i] - if math.IsNaN(v) { - return math.NaN() - } - if v > max { - max = v - } - } - return max - default: - // lapack.Frobenius: - scale := 0.0 - sum := 1.0 - // Sum off-diagonals. - if uplo == blas.Upper { - for i := 0; i < n-1; i++ { - scale, sum = impl.Dlassq(n-i-1, a[i*lda+i+1:], 1, scale, sum) - } - } else { - for i := 1; i < n; i++ { - scale, sum = impl.Dlassq(i, a[i*lda:], 1, scale, sum) - } - } - sum *= 2 - // Sum diagonal. - scale, sum = impl.Dlassq(n, a, lda+1, scale, sum) - return scale * math.Sqrt(sum) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlantb.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlantb.go deleted file mode 100644 index ceab2a6a..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlantb.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright ©2020 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dlantb returns the value of the given norm of an n×n triangular band matrix A -// with k+1 diagonals. -// -// When norm is lapack.MaxColumnSum, the length of work must be at least n. -func (impl Implementation) Dlantb(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n, k int, a []float64, lda int, work []float64) float64 { - switch { - case norm != lapack.MaxAbs && norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius: - panic(badNorm) - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case k < 0: - panic(kdLT0) - case lda < k+1: - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 0 - } - - switch { - case len(a) < (n-1)*lda+k+1: - panic(shortAB) - case len(work) < n && norm == lapack.MaxColumnSum: - panic(shortWork) - } - - var value float64 - switch norm { - case lapack.MaxAbs: - if uplo == blas.Upper { - var jfirst int - if diag == blas.Unit { - value = 1 - jfirst = 1 - } - for i := 0; i < n; i++ { - for _, aij := range a[i*lda+jfirst : i*lda+min(n-i, k+1)] { - if math.IsNaN(aij) { - return aij - } - aij = math.Abs(aij) - if aij > value { - value = aij - } - } - } - } else { - jlast := k + 1 - if diag == blas.Unit { - value = 1 - jlast = k - } - for i := 0; i < n; i++ { - for _, aij := range a[i*lda+max(0, k-i) : i*lda+jlast] { - if math.IsNaN(aij) { - return math.NaN() - } - aij = math.Abs(aij) - if aij > value { - value = aij - } - } - } - } - case lapack.MaxRowSum: - var sum float64 - if uplo == blas.Upper { - var jfirst int - if diag == blas.Unit { - jfirst = 1 - } - for i := 0; i < n; i++ { - sum = 0 - if diag == blas.Unit { - sum = 1 - } - for _, aij := range a[i*lda+jfirst : i*lda+min(n-i, k+1)] { - sum += math.Abs(aij) - } - if math.IsNaN(sum) { - return math.NaN() - } - if sum > value { - value = sum - } - } - } else { - jlast := k + 1 - if diag == blas.Unit { - jlast = k - } - for i := 0; i < n; i++ { - sum = 0 - if diag == blas.Unit { - sum = 1 - } - for _, aij := range a[i*lda+max(0, k-i) : i*lda+jlast] { - sum += math.Abs(aij) - } - if math.IsNaN(sum) { - return math.NaN() - } - if sum > value { - value = sum - } - } - } - case lapack.MaxColumnSum: - work = work[:n] - if diag == blas.Unit { - for i := range work { - work[i] = 1 - } - } else { - for i := range work { - work[i] = 0 - } - } - if uplo == blas.Upper { - var jfirst int - if diag == blas.Unit { - jfirst = 1 - } - for i := 0; i < n; i++ { - for j, aij := range a[i*lda+jfirst : i*lda+min(n-i, k+1)] { - work[i+jfirst+j] += math.Abs(aij) - } - } - } else { - jlast := k + 1 - if diag == blas.Unit { - jlast = k - } - for i := 0; i < n; i++ { - off := max(0, k-i) - for j, aij := range a[i*lda+off : i*lda+jlast] { - work[i+j+off-k] += math.Abs(aij) - } - } - } - for _, wi := range work { - if math.IsNaN(wi) { - return math.NaN() - } - if wi > value { - value = wi - } - } - case lapack.Frobenius: - var scale, sum float64 - switch uplo { - case blas.Upper: - if diag == blas.Unit { - scale = 1 - sum = float64(n) - if k > 0 { - for i := 0; i < n-1; i++ { - ilen := min(n-i-1, k) - scale, sum = impl.Dlassq(ilen, a[i*lda+1:], 1, scale, sum) - } - } - } else { - scale = 0 - sum = 1 - for i := 0; i < n; i++ { - ilen := min(n-i, k+1) - scale, sum = impl.Dlassq(ilen, a[i*lda:], 1, scale, sum) - } - } - case blas.Lower: - if diag == blas.Unit { - scale = 1 - sum = float64(n) - if k > 0 { - for i := 1; i < n; i++ { - ilen := min(i, k) - scale, sum = impl.Dlassq(ilen, a[i*lda+k-ilen:], 1, scale, sum) - } - } - } else { - scale = 0 - sum = 1 - for i := 0; i < n; i++ { - ilen := min(i, k) + 1 - scale, sum = impl.Dlassq(ilen, a[i*lda+k+1-ilen:], 1, scale, sum) - } - } - } - value = scale * math.Sqrt(sum) - } - return value -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go deleted file mode 100644 index 33569832..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dlantr computes the specified norm of an m×n trapezoidal matrix A. If -// norm == lapack.MaxColumnSum work must have length at least n, otherwise work -// is unused. -func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 { - switch { - case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: - panic(badNorm) - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case diag != blas.Unit && diag != blas.NonUnit: - panic(badDiag) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - minmn := min(m, n) - if minmn == 0 { - return 0 - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case norm == lapack.MaxColumnSum && len(work) < n: - panic(shortWork) - } - - switch norm { - case lapack.MaxAbs: - if diag == blas.Unit { - value := 1.0 - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := i + 1; j < n; j++ { - tmp := math.Abs(a[i*lda+j]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > value { - value = tmp - } - } - } - return value - } - for i := 1; i < m; i++ { - for j := 0; j < min(i, n); j++ { - tmp := math.Abs(a[i*lda+j]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > value { - value = tmp - } - } - } - return value - } - var value float64 - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := i; j < n; j++ { - tmp := math.Abs(a[i*lda+j]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > value { - value = tmp - } - } - } - return value - } - for i := 0; i < m; i++ { - for j := 0; j <= min(i, n-1); j++ { - tmp := math.Abs(a[i*lda+j]) - if math.IsNaN(tmp) { - return tmp - } - if tmp > value { - value = tmp - } - } - } - return value - case lapack.MaxColumnSum: - if diag == blas.Unit { - for i := 0; i < minmn; i++ { - work[i] = 1 - } - for i := minmn; i < n; i++ { - work[i] = 0 - } - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := i + 1; j < n; j++ { - work[j] += math.Abs(a[i*lda+j]) - } - } - } else { - for i := 1; i < m; i++ { - for j := 0; j < min(i, n); j++ { - work[j] += math.Abs(a[i*lda+j]) - } - } - } - } else { - for i := 0; i < n; i++ { - work[i] = 0 - } - if uplo == blas.Upper { - for i := 0; i < m; i++ { - for j := i; j < n; j++ { - work[j] += math.Abs(a[i*lda+j]) - } - } - } else { - for i := 0; i < m; i++ { - for j := 0; j <= min(i, n-1); j++ { - work[j] += math.Abs(a[i*lda+j]) - } - } - } - } - var max float64 - for _, v := range work[:n] { - if math.IsNaN(v) { - return math.NaN() - } - if v > max { - max = v - } - } - return max - case lapack.MaxRowSum: - var maxsum float64 - if diag == blas.Unit { - if uplo == blas.Upper { - for i := 0; i < m; i++ { - var sum float64 - if i < minmn { - sum = 1 - } - for j := i + 1; j < n; j++ { - sum += math.Abs(a[i*lda+j]) - } - if math.IsNaN(sum) { - return math.NaN() - } - if sum > maxsum { - maxsum = sum - } - } - return maxsum - } else { - for i := 0; i < m; i++ { - var sum float64 - if i < minmn { - sum = 1 - } - for j := 0; j < min(i, n); j++ { - sum += math.Abs(a[i*lda+j]) - } - if math.IsNaN(sum) { - return math.NaN() - } - if sum > maxsum { - maxsum = sum - } - } - return maxsum - } - } else { - if uplo == blas.Upper { - for i := 0; i < m; i++ { - var sum float64 - for j := i; j < n; j++ { - sum += math.Abs(a[i*lda+j]) - } - if math.IsNaN(sum) { - return sum - } - if sum > maxsum { - maxsum = sum - } - } - return maxsum - } else { - for i := 0; i < m; i++ { - var sum float64 - for j := 0; j <= min(i, n-1); j++ { - sum += math.Abs(a[i*lda+j]) - } - if math.IsNaN(sum) { - return sum - } - if sum > maxsum { - maxsum = sum - } - } - return maxsum - } - } - default: - // lapack.Frobenius: - var scale, sum float64 - if diag == blas.Unit { - scale = 1 - sum = float64(min(m, n)) - if uplo == blas.Upper { - for i := 0; i < min(m, n); i++ { - scale, sum = impl.Dlassq(n-i-1, a[i*lda+i+1:], 1, scale, sum) - } - } else { - for i := 1; i < m; i++ { - scale, sum = impl.Dlassq(min(i, n), a[i*lda:], 1, scale, sum) - } - } - } else { - scale = 0 - sum = 1 - if uplo == blas.Upper { - for i := 0; i < min(m, n); i++ { - scale, sum = impl.Dlassq(n-i, a[i*lda+i:], 1, scale, sum) - } - } else { - for i := 0; i < m; i++ { - scale, sum = impl.Dlassq(min(i+1, n), a[i*lda:], 1, scale, sum) - } - } - } - return scale * math.Sqrt(sum) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go deleted file mode 100644 index 360f71b1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanv2.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "math" - -// Dlanv2 computes the Schur factorization of a real 2×2 matrix: -// -// [ a b ] = [ cs -sn ] * [ aa bb ] * [ cs sn ] -// [ c d ] [ sn cs ] [ cc dd ] * [-sn cs ] -// -// If cc is zero, aa and dd are real eigenvalues of the matrix. Otherwise it -// holds that aa = dd and bb*cc < 0, and aa ± sqrt(bb*cc) are complex conjugate -// eigenvalues. The real and imaginary parts of the eigenvalues are returned in -// (rt1r,rt1i) and (rt2r,rt2i). -func (impl Implementation) Dlanv2(a, b, c, d float64) (aa, bb, cc, dd float64, rt1r, rt1i, rt2r, rt2i float64, cs, sn float64) { - switch { - case c == 0: // Matrix is already upper triangular. - aa = a - bb = b - cc = 0 - dd = d - cs = 1 - sn = 0 - case b == 0: // Matrix is lower triangular, swap rows and columns. - aa = d - bb = -c - cc = 0 - dd = a - cs = 0 - sn = 1 - case a == d && math.Signbit(b) != math.Signbit(c): // Matrix is already in the standard Schur form. - aa = a - bb = b - cc = c - dd = d - cs = 1 - sn = 0 - default: - temp := a - d - p := temp / 2 - bcmax := math.Max(math.Abs(b), math.Abs(c)) - bcmis := math.Min(math.Abs(b), math.Abs(c)) - if b*c < 0 { - bcmis *= -1 - } - scale := math.Max(math.Abs(p), bcmax) - z := p/scale*p + bcmax/scale*bcmis - eps := dlamchP - - if z >= 4*eps { - // Real eigenvalues. Compute aa and dd. - if p > 0 { - z = p + math.Sqrt(scale)*math.Sqrt(z) - } else { - z = p - math.Sqrt(scale)*math.Sqrt(z) - } - aa = d + z - dd = d - bcmax/z*bcmis - // Compute bb and the rotation matrix. - tau := impl.Dlapy2(c, z) - cs = z / tau - sn = c / tau - bb = b - c - cc = 0 - } else { - // Complex eigenvalues, or real (almost) equal eigenvalues. - // Make diagonal elements equal. - safmn2 := math.Pow(dlamchB, math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2) - safmx2 := 1 / safmn2 - sigma := b + c - loop: - for iter := 0; iter < 20; iter++ { - scale = math.Max(math.Abs(temp), math.Abs(sigma)) - switch { - case scale >= safmx2: - sigma *= safmn2 - temp *= safmn2 - case scale <= safmn2: - sigma *= safmx2 - temp *= safmx2 - default: - break loop - } - } - p = temp / 2 - tau := impl.Dlapy2(sigma, temp) - cs = math.Sqrt((1 + math.Abs(sigma)/tau) / 2) - sn = -p / (tau * cs) - if sigma < 0 { - sn *= -1 - } - // Compute [ aa bb ] = [ a b ] [ cs -sn ] - // [ cc dd ] [ c d ] [ sn cs ] - aa = a*cs + b*sn - bb = -a*sn + b*cs - cc = c*cs + d*sn - dd = -c*sn + d*cs - // Compute [ a b ] = [ cs sn ] [ aa bb ] - // [ c d ] [-sn cs ] [ cc dd ] - a = aa*cs + cc*sn - b = bb*cs + dd*sn - c = -aa*sn + cc*cs - d = -bb*sn + dd*cs - - temp = (a + d) / 2 - aa = temp - bb = b - cc = c - dd = temp - - if cc != 0 { - if bb != 0 { - if math.Signbit(bb) == math.Signbit(cc) { - // Real eigenvalues, reduce to - // upper triangular form. - sab := math.Sqrt(math.Abs(bb)) - sac := math.Sqrt(math.Abs(cc)) - p = sab * sac - if cc < 0 { - p *= -1 - } - tau = 1 / math.Sqrt(math.Abs(bb+cc)) - aa = temp + p - bb = bb - cc - cc = 0 - dd = temp - p - cs1 := sab * tau - sn1 := sac * tau - cs, sn = cs*cs1-sn*sn1, cs*sn1+sn*cs1 - } - } else { - bb = -cc - cc = 0 - cs, sn = -sn, cs - } - } - } - } - - // Store eigenvalues in (rt1r,rt1i) and (rt2r,rt2i). - rt1r = aa - rt2r = dd - if cc != 0 { - rt1i = math.Sqrt(math.Abs(bb)) * math.Sqrt(math.Abs(cc)) - rt2i = -rt1i - } - return -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go deleted file mode 100644 index bf98c338..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas/blas64" - -// Dlapll returns the smallest singular value of the n×2 matrix A = [ x y ]. -// The function first computes the QR factorization of A = Q*R, and then computes -// the SVD of the 2-by-2 upper triangular matrix r. -// -// The contents of x and y are overwritten during the call. -// -// Dlapll is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlapll(n int, x []float64, incX int, y []float64, incY int) float64 { - switch { - case n < 0: - panic(nLT0) - case incX <= 0: - panic(badIncX) - case incY <= 0: - panic(badIncY) - } - - // Quick return if possible. - if n == 0 { - return 0 - } - - switch { - case len(x) < 1+(n-1)*incX: - panic(shortX) - case len(y) < 1+(n-1)*incY: - panic(shortY) - } - - // Quick return if possible. - if n == 1 { - return 0 - } - - // Compute the QR factorization of the N-by-2 matrix [ X Y ]. - a00, tau := impl.Dlarfg(n, x[0], x[incX:], incX) - x[0] = 1 - - bi := blas64.Implementation() - c := -tau * bi.Ddot(n, x, incX, y, incY) - bi.Daxpy(n, c, x, incX, y, incY) - a11, _ := impl.Dlarfg(n-1, y[incY], y[2*incY:], incY) - - // Compute the SVD of 2-by-2 upper triangular matrix. - ssmin, _ := impl.Dlas2(a00, y[0], a11) - return ssmin -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmr.go deleted file mode 100644 index 73cd82db..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmr.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright ©2022 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas/blas64" - -// Dlapmr rearranges the rows of the m×n matrix X as specified by the permutation -// k[0],k[1],...,k[m-1] of the integers 0,...,m-1. -// -// If forward is true, a forward permutation is applied: -// -// X[k[i],0:n] is moved to X[i,0:n] for i=0,1,...,m-1. -// -// If forward is false, a backward permutation is applied: -// -// X[i,0:n] is moved to X[k[i],0:n] for i=0,1,...,m-1. -// -// k must have length m, otherwise Dlapmr will panic. -func (impl Implementation) Dlapmr(forward bool, m, n int, x []float64, ldx int, k []int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case ldx < max(1, n): - panic(badLdX) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - switch { - case len(x) < (m-1)*ldx+n: - panic(shortX) - case len(k) != m: - panic(badLenK) - } - - // Quick return if possible. - if m == 1 { - return - } - - bi := blas64.Implementation() - - for i, ki := range k { - k[i] = -(ki + 1) - } - if forward { - for i, ki := range k { - if ki >= 0 { - continue - } - j := i - k[j] = -k[j] - 1 - in := k[j] - for { - if k[in] >= 0 { - break - } - bi.Dswap(n, x[j*ldx:], 1, x[in*ldx:], 1) - k[in] = -k[in] - 1 - j = in - in = k[in] - } - } - } else { - for i, ki := range k { - if ki >= 0 { - continue - } - k[i] = -ki - 1 - j := k[i] - for { - if j == i { - break - } - bi.Dswap(n, x[i*ldx:], 1, x[j*ldx:], 1) - k[j] = -k[j] - 1 - j = k[j] - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go deleted file mode 100644 index 4a70e68f..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas/blas64" - -// Dlapmt rearranges the columns of the m×n matrix X as specified by the -// permutation k_0, k_1, ..., k_n-1 of the integers 0, ..., n-1. -// -// If forward is true a forward permutation is performed: -// -// X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1. -// -// otherwise a backward permutation is performed: -// -// X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1. -// -// k must have length n, otherwise Dlapmt will panic. k is zero-indexed. -func (impl Implementation) Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case ldx < max(1, n): - panic(badLdX) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - switch { - case len(x) < (m-1)*ldx+n: - panic(shortX) - case len(k) != n: - panic(badLenK) - } - - // Quick return if possible. - if n == 1 { - return - } - - for i, v := range k { - v++ - k[i] = -v - } - - bi := blas64.Implementation() - - if forward { - for j, v := range k { - if v >= 0 { - continue - } - k[j] = -v - i := -v - 1 - for k[i] < 0 { - bi.Dswap(m, x[j:], ldx, x[i:], ldx) - - k[i] = -k[i] - j = i - i = k[i] - 1 - } - } - } else { - for i, v := range k { - if v >= 0 { - continue - } - k[i] = -v - j := -v - 1 - for j != i { - bi.Dswap(m, x[j:], ldx, x[i:], ldx) - - k[j] = -k[j] - j = k[j] - 1 - } - } - } - - for i := range k { - k[i]-- - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go deleted file mode 100644 index 19f73ffa..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapy2.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlapy2 is the LAPACK version of math.Hypot. -// -// Dlapy2 is an internal routine. It is exported for testing purposes. -func (Implementation) Dlapy2(x, y float64) float64 { - return math.Hypot(x, y) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go deleted file mode 100644 index cc3bc06d..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlaqp2 computes a QR factorization with column pivoting of the block A[offset:m, 0:n] -// of the m×n matrix A. The block A[0:offset, 0:n] is accordingly pivoted, but not factorized. -// -// On exit, the upper triangle of block A[offset:m, 0:n] is the triangular factor obtained. -// The elements in block A[offset:m, 0:n] below the diagonal, together with tau, represent -// the orthogonal matrix Q as a product of elementary reflectors. -// -// offset is number of rows of the matrix A that must be pivoted but not factorized. -// offset must not be negative otherwise Dlaqp2 will panic. -// -// On exit, jpvt holds the permutation that was applied; the jth column of A*P was the -// jpvt[j] column of A. jpvt must have length n, otherwise Dlaqp2 will panic. -// -// On exit tau holds the scalar factors of the elementary reflectors. It must have length -// at least min(m-offset, n) otherwise Dlaqp2 will panic. -// -// vn1 and vn2 hold the partial and complete column norms respectively. They must have length n, -// otherwise Dlaqp2 will panic. -// -// work must have length n, otherwise Dlaqp2 will panic. -// -// Dlaqp2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaqp2(m, n, offset int, a []float64, lda int, jpvt []int, tau, vn1, vn2, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case offset < 0: - panic(offsetLT0) - case offset > m: - panic(offsetGTM) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - mn := min(m-offset, n) - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(jpvt) != n: - panic(badLenJpvt) - case len(tau) < mn: - panic(shortTau) - case len(vn1) < n: - panic(shortVn1) - case len(vn2) < n: - panic(shortVn2) - case len(work) < n: - panic(shortWork) - } - - tol3z := math.Sqrt(dlamchE) - - bi := blas64.Implementation() - - // Compute factorization. - for i := 0; i < mn; i++ { - offpi := offset + i - - // Determine ith pivot column and swap if necessary. - p := i + bi.Idamax(n-i, vn1[i:], 1) - if p != i { - bi.Dswap(m, a[p:], lda, a[i:], lda) - jpvt[p], jpvt[i] = jpvt[i], jpvt[p] - vn1[p] = vn1[i] - vn2[p] = vn2[i] - } - - // Generate elementary reflector H_i. - if offpi < m-1 { - a[offpi*lda+i], tau[i] = impl.Dlarfg(m-offpi, a[offpi*lda+i], a[(offpi+1)*lda+i:], lda) - } else { - tau[i] = 0 - } - - if i < n-1 { - // Apply H_iᵀ to A[offset+i:m, i:n] from the left. - aii := a[offpi*lda+i] - a[offpi*lda+i] = 1 - impl.Dlarf(blas.Left, m-offpi, n-i-1, a[offpi*lda+i:], lda, tau[i], a[offpi*lda+i+1:], lda, work) - a[offpi*lda+i] = aii - } - - // Update partial column norms. - for j := i + 1; j < n; j++ { - if vn1[j] == 0 { - continue - } - - // The following marked lines follow from the - // analysis in Lapack Working Note 176. - r := math.Abs(a[offpi*lda+j]) / vn1[j] // * - temp := math.Max(0, 1-r*r) // * - r = vn1[j] / vn2[j] // * - temp2 := temp * r * r // * - if temp2 < tol3z { - var v float64 - if offpi < m-1 { - v = bi.Dnrm2(m-offpi-1, a[(offpi+1)*lda+j:], lda) - } - vn1[j] = v - vn2[j] = v - } else { - vn1[j] *= math.Sqrt(temp) // * - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go deleted file mode 100644 index da1a60e5..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlaqps computes a step of QR factorization with column pivoting -// of an m×n matrix A by using Blas-3. It tries to factorize nb -// columns from A starting from the row offset, and updates all -// of the matrix with Dgemm. -// -// In some cases, due to catastrophic cancellations, it cannot -// factorize nb columns. Hence, the actual number of factorized -// columns is returned in kb. -// -// Dlaqps computes a QR factorization with column pivoting of the -// block A[offset:m, 0:nb] of the m×n matrix A. The block -// A[0:offset, 0:n] is accordingly pivoted, but not factorized. -// -// On exit, the upper triangle of block A[offset:m, 0:kb] is the -// triangular factor obtained. The elements in block A[offset:m, 0:n] -// below the diagonal, together with tau, represent the orthogonal -// matrix Q as a product of elementary reflectors. -// -// offset is number of rows of the matrix A that must be pivoted but -// not factorized. offset must not be negative otherwise Dlaqps will panic. -// -// On exit, jpvt holds the permutation that was applied; the jth column -// of A*P was the jpvt[j] column of A. jpvt must have length n, -// otherwise Dlapqs will panic. -// -// On exit tau holds the scalar factors of the elementary reflectors. -// It must have length nb, otherwise Dlapqs will panic. -// -// vn1 and vn2 hold the partial and complete column norms respectively. -// They must have length n, otherwise Dlapqs will panic. -// -// auxv must have length nb, otherwise Dlaqps will panic. -// -// f and ldf represent an n×nb matrix F that is overwritten during the -// call. -// -// Dlaqps is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaqps(m, n, offset, nb int, a []float64, lda int, jpvt []int, tau, vn1, vn2, auxv, f []float64, ldf int) (kb int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case offset < 0: - panic(offsetLT0) - case offset > m: - panic(offsetGTM) - case nb < 0: - panic(nbLT0) - case nb > n: - panic(nbGTN) - case lda < max(1, n): - panic(badLdA) - case ldf < max(1, nb): - panic(badLdF) - } - - if m == 0 || n == 0 { - return 0 - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(jpvt) != n: - panic(badLenJpvt) - case len(vn1) < n: - panic(shortVn1) - case len(vn2) < n: - panic(shortVn2) - } - - if nb == 0 { - return 0 - } - - switch { - case len(tau) < nb: - panic(shortTau) - case len(auxv) < nb: - panic(shortAuxv) - case len(f) < (n-1)*ldf+nb: - panic(shortF) - } - - if offset == m { - return 0 - } - - lastrk := min(m, n+offset) - lsticc := -1 - tol3z := math.Sqrt(dlamchE) - - bi := blas64.Implementation() - - var k, rk int - for ; k < nb && lsticc == -1; k++ { - rk = offset + k - - // Determine kth pivot column and swap if necessary. - p := k + bi.Idamax(n-k, vn1[k:], 1) - if p != k { - bi.Dswap(m, a[p:], lda, a[k:], lda) - bi.Dswap(k, f[p*ldf:], 1, f[k*ldf:], 1) - jpvt[p], jpvt[k] = jpvt[k], jpvt[p] - vn1[p] = vn1[k] - vn2[p] = vn2[k] - } - - // Apply previous Householder reflectors to column K: - // - // A[rk:m, k] = A[rk:m, k] - A[rk:m, 0:k-1]*F[k, 0:k-1]ᵀ. - if k > 0 { - bi.Dgemv(blas.NoTrans, m-rk, k, -1, - a[rk*lda:], lda, - f[k*ldf:], 1, - 1, - a[rk*lda+k:], lda) - } - - // Generate elementary reflector H_k. - if rk < m-1 { - a[rk*lda+k], tau[k] = impl.Dlarfg(m-rk, a[rk*lda+k], a[(rk+1)*lda+k:], lda) - } else { - tau[k] = 0 - } - - akk := a[rk*lda+k] - a[rk*lda+k] = 1 - - // Compute kth column of F: - // - // Compute F[k+1:n, k] = tau[k]*A[rk:m, k+1:n]ᵀ*A[rk:m, k]. - if k < n-1 { - bi.Dgemv(blas.Trans, m-rk, n-k-1, tau[k], - a[rk*lda+k+1:], lda, - a[rk*lda+k:], lda, - 0, - f[(k+1)*ldf+k:], ldf) - } - - // Padding F[0:k, k] with zeros. - for j := 0; j < k; j++ { - f[j*ldf+k] = 0 - } - - // Incremental updating of F: - // - // F[0:n, k] := F[0:n, k] - tau[k]*F[0:n, 0:k-1]*A[rk:m, 0:k-1]ᵀ*A[rk:m,k]. - if k > 0 { - bi.Dgemv(blas.Trans, m-rk, k, -tau[k], - a[rk*lda:], lda, - a[rk*lda+k:], lda, - 0, - auxv, 1) - bi.Dgemv(blas.NoTrans, n, k, 1, - f, ldf, - auxv, 1, - 1, - f[k:], ldf) - } - - // Update the current row of A: - // - // A[rk, k+1:n] = A[rk, k+1:n] - A[rk, 0:k]*F[k+1:n, 0:k]ᵀ. - if k < n-1 { - bi.Dgemv(blas.NoTrans, n-k-1, k+1, -1, - f[(k+1)*ldf:], ldf, - a[rk*lda:], 1, - 1, - a[rk*lda+k+1:], 1) - } - - // Update partial column norms. - if rk < lastrk-1 { - for j := k + 1; j < n; j++ { - if vn1[j] == 0 { - continue - } - - // The following marked lines follow from the - // analysis in Lapack Working Note 176. - r := math.Abs(a[rk*lda+j]) / vn1[j] // * - temp := math.Max(0, 1-r*r) // * - r = vn1[j] / vn2[j] // * - temp2 := temp * r * r // * - if temp2 < tol3z { - // vn2 is used here as a collection of - // indices into vn2 and also a collection - // of column norms. - vn2[j] = float64(lsticc) - lsticc = j - } else { - vn1[j] *= math.Sqrt(temp) // * - } - } - } - - a[rk*lda+k] = akk - } - kb = k - rk = offset + kb - - // Apply the block reflector to the rest of the matrix: - // - // A[offset+kb+1:m, kb+1:n] := A[offset+kb+1:m, kb+1:n] - A[offset+kb+1:m, 1:kb]*F[kb+1:n, 1:kb]ᵀ. - if kb < min(n, m-offset) { - bi.Dgemm(blas.NoTrans, blas.Trans, - m-rk, n-kb, kb, -1, - a[rk*lda:], lda, - f[kb*ldf:], ldf, - 1, - a[rk*lda+kb:], lda) - } - - // Recomputation of difficult columns. - for lsticc >= 0 { - itemp := int(vn2[lsticc]) - - // NOTE: The computation of vn1[lsticc] relies on the fact that - // Dnrm2 does not fail on vectors with norm below the value of - // sqrt(dlamchS) - v := bi.Dnrm2(m-rk, a[rk*lda+lsticc:], lda) - vn1[lsticc] = v - vn2[lsticc] = v - - lsticc = itemp - } - - return kb -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go deleted file mode 100644 index 8e4b266b..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go +++ /dev/null @@ -1,493 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" -) - -// Dlaqr04 computes the eigenvalues of a block of an n×n upper Hessenberg matrix -// H, and optionally the matrices T and Z from the Schur decomposition -// -// H = Z T Zᵀ -// -// where T is an upper quasi-triangular matrix (the Schur form), and Z is the -// orthogonal matrix of Schur vectors. -// -// wantt indicates whether the full Schur form T is required. If wantt is false, -// then only enough of H will be updated to preserve the eigenvalues. -// -// wantz indicates whether the n×n matrix of Schur vectors Z is required. If it -// is true, the orthogonal similarity transformation will be accumulated into -// Z[iloz:ihiz+1,ilo:ihi+1], otherwise Z will not be referenced. -// -// ilo and ihi determine the block of H on which Dlaqr04 operates. It must hold that -// -// 0 <= ilo <= ihi < n if n > 0, -// ilo == 0 and ihi == -1 if n == 0, -// -// and the block must be isolated, that is, -// -// ilo == 0 or H[ilo,ilo-1] == 0, -// ihi == n-1 or H[ihi+1,ihi] == 0, -// -// otherwise Dlaqr04 will panic. -// -// wr and wi must have length ihi+1. -// -// iloz and ihiz specify the rows of Z to which transformations will be applied -// if wantz is true. It must hold that -// -// 0 <= iloz <= ilo, and ihi <= ihiz < n, -// -// otherwise Dlaqr04 will panic. -// -// work must have length at least lwork and lwork must be -// -// lwork >= 1 if n <= 11, -// lwork >= n if n > 11, -// -// otherwise Dlaqr04 will panic. lwork as large as 6*n may be required for -// optimal performance. On return, work[0] will contain the optimal value of -// lwork. -// -// If lwork is -1, instead of performing Dlaqr04, the function only estimates the -// optimal workspace size and stores it into work[0]. Neither h nor z are -// accessed. -// -// recur is the non-negative recursion depth. For recur > 0, Dlaqr04 behaves -// as DLAQR0, for recur == 0 it behaves as DLAQR4. -// -// unconverged indicates whether Dlaqr04 computed all the eigenvalues of H[ilo:ihi+1,ilo:ihi+1]. -// -// If unconverged is zero and wantt is true, H will contain on return the upper -// quasi-triangular matrix T from the Schur decomposition. 2×2 diagonal blocks -// (corresponding to complex conjugate pairs of eigenvalues) will be returned in -// standard form, with H[i,i] == H[i+1,i+1] and H[i+1,i]*H[i,i+1] < 0. -// -// If unconverged is zero and if wantt is false, the contents of h on return is -// unspecified. -// -// If unconverged is zero, all the eigenvalues have been computed and their real -// and imaginary parts will be stored on return in wr[ilo:ihi+1] and -// wi[ilo:ihi+1], respectively. If two eigenvalues are computed as a complex -// conjugate pair, they are stored in consecutive elements of wr and wi, say the -// i-th and (i+1)th, with wi[i] > 0 and wi[i+1] < 0. If wantt is true, then the -// eigenvalues are stored in the same order as on the diagonal of the Schur form -// returned in H, with wr[i] = H[i,i] and, if H[i:i+2,i:i+2] is a 2×2 diagonal -// block, wi[i] = sqrt(-H[i+1,i]*H[i,i+1]) and wi[i+1] = -wi[i]. -// -// If unconverged is positive, some eigenvalues have not converged, and -// wr[unconverged:ihi+1] and wi[unconverged:ihi+1] will contain those -// eigenvalues which have been successfully computed. Failures are rare. -// -// If unconverged is positive and wantt is true, then on return -// -// (initial H)*U = U*(final H), (*) -// -// where U is an orthogonal matrix. The final H is upper Hessenberg and -// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. -// -// If unconverged is positive and wantt is false, on return the remaining -// unconverged eigenvalues are the eigenvalues of the upper Hessenberg matrix -// H[ilo:unconverged,ilo:unconverged]. -// -// If unconverged is positive and wantz is true, then on return -// -// (final Z) = (initial Z)*U, -// -// where U is the orthogonal matrix in (*) regardless of the value of wantt. -// -// References: -// -// [1] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part I: -// Maintaining Well-Focused Shifts and Level 3 Performance. SIAM J. Matrix -// Anal. Appl. 23(4) (2002), pp. 929—947 -// URL: http://dx.doi.org/10.1137/S0895479801384573 -// [2] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: -// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl. 23(4) (2002), pp. 948—973 -// URL: http://dx.doi.org/10.1137/S0895479801384585 -// -// Dlaqr04 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int, work []float64, lwork int, recur int) (unconverged int) { - const ( - // Matrices of order ntiny or smaller must be processed by - // Dlahqr because of insufficient subdiagonal scratch space. - // This is a hard limit. - ntiny = 15 - // Exceptional deflation windows: try to cure rare slow - // convergence by varying the size of the deflation window after - // kexnw iterations. - kexnw = 5 - // Exceptional shifts: try to cure rare slow convergence with - // ad-hoc exceptional shifts every kexsh iterations. - kexsh = 6 - - // See https://github.com/gonum/lapack/pull/151#discussion_r68162802 - // and the surrounding discussion for an explanation where these - // constants come from. - // TODO(vladimir-ch): Similar constants for exceptional shifts - // are used also in dlahqr.go. The first constant is different - // there, it is equal to 3. Why? And does it matter? - wilk1 = 0.75 - wilk2 = -0.4375 - ) - - switch { - case n < 0: - panic(nLT0) - case ilo < 0 || max(0, n-1) < ilo: - panic(badIlo) - case ihi < min(ilo, n-1) || n <= ihi: - panic(badIhi) - case ldh < max(1, n): - panic(badLdH) - case wantz && (iloz < 0 || ilo < iloz): - panic(badIloz) - case wantz && (ihiz < ihi || n <= ihiz): - panic(badIhiz) - case ldz < 1, wantz && ldz < n: - panic(badLdZ) - case lwork < 1 && lwork != -1: - panic(badLWork) - // TODO(vladimir-ch): Enable if and when we figure out what the minimum - // necessary lwork value is. Dlaqr04 says that the minimum is n which - // clashes with Dlaqr23's opinion about optimal work when nw <= 2 - // (independent of n). - // case lwork < n && n > ntiny && lwork != -1: - // panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - case recur < 0: - panic(recurLT0) - } - - // Quick return. - if n == 0 { - work[0] = 1 - return 0 - } - - if lwork != -1 { - switch { - case len(h) < (n-1)*ldh+n: - panic(shortH) - case len(wr) != ihi+1: - panic(badLenWr) - case len(wi) != ihi+1: - panic(badLenWi) - case wantz && len(z) < (n-1)*ldz+n: - panic(shortZ) - case ilo > 0 && h[ilo*ldh+ilo-1] != 0: - panic(notIsolated) - case ihi+1 < n && h[(ihi+1)*ldh+ihi] != 0: - panic(notIsolated) - } - } - - if n <= ntiny { - // Tiny matrices must use Dlahqr. - if lwork == -1 { - work[0] = 1 - return 0 - } - return impl.Dlahqr(wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, iloz, ihiz, z, ldz) - } - - // Use small bulge multi-shift QR with aggressive early deflation on - // larger-than-tiny matrices. - var jbcmpz string - if wantt { - jbcmpz = "S" - } else { - jbcmpz = "E" - } - if wantz { - jbcmpz += "V" - } else { - jbcmpz += "N" - } - - var fname string - if recur > 0 { - fname = "DLAQR0" - } else { - fname = "DLAQR4" - } - // nwr is the recommended deflation window size. n is greater than ntiny, - // so there is enough subdiagonal workspace for nwr >= 2 as required. - // (In fact, there is enough subdiagonal space for nwr >= 4.) - // TODO(vladimir-ch): If there is enough space for nwr >= 4, should we - // use it? - nwr := impl.Ilaenv(13, fname, jbcmpz, n, ilo, ihi, lwork) - nwr = max(2, nwr) - nwr = min(ihi-ilo+1, min((n-1)/3, nwr)) - - // nsr is the recommended number of simultaneous shifts. n is greater than - // ntiny, so there is enough subdiagonal workspace for nsr to be even and - // greater than or equal to two as required. - nsr := impl.Ilaenv(15, fname, jbcmpz, n, ilo, ihi, lwork) - nsr = min(nsr, min((n-3)/6, ihi-ilo)) - nsr = max(2, nsr&^1) - - // Workspace query call to Dlaqr23. - impl.Dlaqr23(wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz, ihiz, z, ldz, - wr, wi, h, ldh, n, h, ldh, n, h, ldh, work, -1, recur) - // Optimal workspace is max(Dlaqr5, Dlaqr23). - lwkopt := max(3*nsr/2, int(work[0])) - // Quick return in case of workspace query. - if lwork == -1 { - work[0] = float64(lwkopt) - return 0 - } - - // Dlahqr/Dlaqr04 crossover point. - nmin := impl.Ilaenv(12, fname, jbcmpz, n, ilo, ihi, lwork) - nmin = max(ntiny, nmin) - - // Nibble determines when to skip a multi-shift QR sweep (Dlaqr5). - nibble := impl.Ilaenv(14, fname, jbcmpz, n, ilo, ihi, lwork) - nibble = max(0, nibble) - - // Computation mode of far-from-diagonal orthogonal updates in Dlaqr5. - kacc22 := impl.Ilaenv(16, fname, jbcmpz, n, ilo, ihi, lwork) - kacc22 = max(0, min(kacc22, 2)) - - // nwmax is the largest possible deflation window for which there is - // sufficient workspace. - nwmax := min((n-1)/3, lwork/2) - nw := nwmax // Start with maximum deflation window size. - - // nsmax is the largest number of simultaneous shifts for which there is - // sufficient workspace. - nsmax := min((n-3)/6, 2*lwork/3) &^ 1 - - ndfl := 1 // Number of iterations since last deflation. - ndec := 0 // Deflation window size decrement. - - // Main loop. - var ( - itmax = max(30, 2*kexsh) * max(10, (ihi-ilo+1)) - it = 0 - ) - for kbot := ihi; kbot >= ilo; { - if it == itmax { - unconverged = kbot + 1 - break - } - it++ - - // Locate active block. - ktop := ilo - for k := kbot; k >= ilo+1; k-- { - if h[k*ldh+k-1] == 0 { - ktop = k - break - } - } - - // Select deflation window size nw. - // - // Typical Case: - // If possible and advisable, nibble the entire active block. - // If not, use size min(nwr,nwmax) or min(nwr+1,nwmax) - // depending upon which has the smaller corresponding - // subdiagonal entry (a heuristic). - // - // Exceptional Case: - // If there have been no deflations in kexnw or more - // iterations, then vary the deflation window size. At first, - // because larger windows are, in general, more powerful than - // smaller ones, rapidly increase the window to the maximum - // possible. Then, gradually reduce the window size. - nh := kbot - ktop + 1 - nwupbd := min(nh, nwmax) - if ndfl < kexnw { - nw = min(nwupbd, nwr) - } else { - nw = min(nwupbd, 2*nw) - } - if nw < nwmax { - if nw >= nh-1 { - nw = nh - } else { - kwtop := kbot - nw + 1 - if math.Abs(h[kwtop*ldh+kwtop-1]) > math.Abs(h[(kwtop-1)*ldh+kwtop-2]) { - nw++ - } - } - } - if ndfl < kexnw { - ndec = -1 - } else if ndec >= 0 || nw >= nwupbd { - ndec++ - if nw-ndec < 2 { - ndec = 0 - } - nw -= ndec - } - - // Split workspace under the subdiagonal of H into: - // - an nw×nw work array V in the lower left-hand corner, - // - an nw×nhv horizontal work array along the bottom edge (nhv - // must be at least nw but more is better), - // - an nve×nw vertical work array along the left-hand-edge - // (nhv can be any positive integer but more is better). - kv := n - nw - kt := nw - kwv := nw + 1 - nhv := n - kwv - kt - // Aggressive early deflation. - ls, ld := impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, - h, ldh, iloz, ihiz, z, ldz, wr[:kbot+1], wi[:kbot+1], - h[kv*ldh:], ldh, nhv, h[kv*ldh+kt:], ldh, nhv, h[kwv*ldh:], ldh, work, lwork, recur) - - // Adjust kbot accounting for new deflations. - kbot -= ld - // ks points to the shifts. - ks := kbot - ls + 1 - - // Skip an expensive QR sweep if there is a (partly heuristic) - // reason to expect that many eigenvalues will deflate without - // it. Here, the QR sweep is skipped if many eigenvalues have - // just been deflated or if the remaining active block is small. - if ld > 0 && (100*ld > nw*nibble || kbot-ktop+1 <= min(nmin, nwmax)) { - // ld is positive, note progress. - ndfl = 1 - continue - } - - // ns is the nominal number of simultaneous shifts. This may be - // lowered (slightly) if Dlaqr23 did not provide that many - // shifts. - ns := min(min(nsmax, nsr), max(2, kbot-ktop)) &^ 1 - - // If there have been no deflations in a multiple of kexsh - // iterations, then try exceptional shifts. Otherwise use shifts - // provided by Dlaqr23 above or from the eigenvalues of a - // trailing principal submatrix. - if ndfl%kexsh == 0 { - ks = kbot - ns + 1 - for i := kbot; i > max(ks, ktop+1); i -= 2 { - ss := math.Abs(h[i*ldh+i-1]) + math.Abs(h[(i-1)*ldh+i-2]) - aa := wilk1*ss + h[i*ldh+i] - _, _, _, _, wr[i-1], wi[i-1], wr[i], wi[i], _, _ = - impl.Dlanv2(aa, ss, wilk2*ss, aa) - } - if ks == ktop { - wr[ks+1] = h[(ks+1)*ldh+ks+1] - wi[ks+1] = 0 - wr[ks] = wr[ks+1] - wi[ks] = wi[ks+1] - } - } else { - // If we got ns/2 or fewer shifts, use Dlahqr or recur - // into Dlaqr04 on a trailing principal submatrix to get - // more. Since ns <= nsmax <=(n+6)/9, there is enough - // space below the subdiagonal to fit an ns×ns scratch - // array. - if kbot-ks+1 <= ns/2 { - ks = kbot - ns + 1 - kt = n - ns - impl.Dlacpy(blas.All, ns, ns, h[ks*ldh+ks:], ldh, h[kt*ldh:], ldh) - if ns > nmin && recur > 0 { - ks += impl.Dlaqr04(false, false, ns, 1, ns-1, h[kt*ldh:], ldh, - wr[ks:ks+ns], wi[ks:ks+ns], 0, 0, nil, 0, work, lwork, recur-1) - } else { - ks += impl.Dlahqr(false, false, ns, 0, ns-1, h[kt*ldh:], ldh, - wr[ks:ks+ns], wi[ks:ks+ns], 0, 0, nil, 1) - } - // In case of a rare QR failure use eigenvalues - // of the trailing 2×2 principal submatrix. - if ks >= kbot { - aa := h[(kbot-1)*ldh+kbot-1] - bb := h[(kbot-1)*ldh+kbot] - cc := h[kbot*ldh+kbot-1] - dd := h[kbot*ldh+kbot] - _, _, _, _, wr[kbot-1], wi[kbot-1], wr[kbot], wi[kbot], _, _ = - impl.Dlanv2(aa, bb, cc, dd) - ks = kbot - 1 - } - } - - if kbot-ks+1 > ns { - // Sorting the shifts helps a little. Bubble - // sort keeps complex conjugate pairs together. - sorted := false - for k := kbot; k > ks; k-- { - if sorted { - break - } - sorted = true - for i := ks; i < k; i++ { - if math.Abs(wr[i])+math.Abs(wi[i]) >= math.Abs(wr[i+1])+math.Abs(wi[i+1]) { - continue - } - sorted = false - wr[i], wr[i+1] = wr[i+1], wr[i] - wi[i], wi[i+1] = wi[i+1], wi[i] - } - } - } - - // Shuffle shifts into pairs of real shifts and pairs of - // complex conjugate shifts using the fact that complex - // conjugate shifts are already adjacent to one another. - // TODO(vladimir-ch): The shuffling here could probably - // be removed but I'm not sure right now and it's safer - // to leave it. - for i := kbot; i > ks+1; i -= 2 { - if wi[i] == -wi[i-1] { - continue - } - wr[i], wr[i-1], wr[i-2] = wr[i-1], wr[i-2], wr[i] - wi[i], wi[i-1], wi[i-2] = wi[i-1], wi[i-2], wi[i] - } - } - - // If there are only two shifts and both are real, then use only one. - if kbot-ks+1 == 2 && wi[kbot] == 0 { - if math.Abs(wr[kbot]-h[kbot*ldh+kbot]) < math.Abs(wr[kbot-1]-h[kbot*ldh+kbot]) { - wr[kbot-1] = wr[kbot] - } else { - wr[kbot] = wr[kbot-1] - } - } - - // Use up to ns of the smallest magnitude shifts. If there - // aren't ns shifts available, then use them all, possibly - // dropping one to make the number of shifts even. - ns = min(ns, kbot-ks+1) &^ 1 - ks = kbot - ns + 1 - - // Split workspace under the subdiagonal into: - // - a kdu×kdu work array U in the lower left-hand-corner, - // - a kdu×nhv horizontal work array WH along the bottom edge - // (nhv must be at least kdu but more is better), - // - an nhv×kdu vertical work array WV along the left-hand-edge - // (nhv must be at least kdu but more is better). - kdu := 2 * ns - ku := n - kdu - kwh := kdu - kwv = kdu + 3 - nhv = n - kwv - kdu - // Small-bulge multi-shift QR sweep. - impl.Dlaqr5(wantt, wantz, kacc22, n, ktop, kbot, ns, - wr[ks:ks+ns], wi[ks:ks+ns], h, ldh, iloz, ihiz, z, ldz, - work, 3, h[ku*ldh:], ldh, nhv, h[kwv*ldh:], ldh, nhv, h[ku*ldh+kwh:], ldh) - - // Note progress (or the lack of it). - if ld > 0 { - ndfl = 1 - } else { - ndfl++ - } - } - - work[0] = float64(lwkopt) - return unconverged -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go deleted file mode 100644 index c20c88fd..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "math" - -// Dlaqr1 sets v to a scalar multiple of the first column of the product -// -// (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) -// -// where H is a 2×2 or 3×3 matrix, I is the identity matrix of the same size, -// and i is the imaginary unit. Scaling is done to avoid overflows and most -// underflows. -// -// n is the order of H and must be either 2 or 3. It must hold that either sr1 = -// sr2 and si1 = -si2, or si1 = si2 = 0. The length of v must be equal to n. If -// any of these conditions is not met, Dlaqr1 will panic. -// -// Dlaqr1 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaqr1(n int, h []float64, ldh int, sr1, si1, sr2, si2 float64, v []float64) { - switch { - case n != 2 && n != 3: - panic("lapack: n must be 2 or 3") - case ldh < n: - panic(badLdH) - case len(h) < (n-1)*ldh+n: - panic(shortH) - case !((sr1 == sr2 && si1 == -si2) || (si1 == 0 && si2 == 0)): - panic(badShifts) - case len(v) != n: - panic(shortV) - } - - if n == 2 { - s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) - if s == 0 { - v[0] = 0 - v[1] = 0 - } else { - h21s := h[ldh] / s - v[0] = h21s*h[1] + (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) - v[1] = h21s * (h[0] + h[ldh+1] - sr1 - sr2) - } - return - } - - s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) + math.Abs(h[2*ldh]) - if s == 0 { - v[0] = 0 - v[1] = 0 - v[2] = 0 - } else { - h21s := h[ldh] / s - h31s := h[2*ldh] / s - v[0] = (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) + h[1]*h21s + h[2]*h31s - v[1] = h21s*(h[0]+h[ldh+1]-sr1-sr2) + h[ldh+2]*h31s - v[2] = h31s*(h[0]+h[2*ldh+2]-sr1-sr2) + h21s*h[2*ldh+1] - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go deleted file mode 100644 index a3fa6661..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go +++ /dev/null @@ -1,423 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlaqr23 performs the orthogonal similarity transformation of an n×n upper -// Hessenberg matrix to detect and deflate fully converged eigenvalues from a -// trailing principal submatrix using aggressive early deflation [1]. -// -// On return, H will be overwritten by a new Hessenberg matrix that is a -// perturbation of an orthogonal similarity transformation of H. It is hoped -// that on output H will have many zero subdiagonal entries. -// -// If wantt is true, the matrix H will be fully updated so that the -// quasi-triangular Schur factor can be computed. If wantt is false, then only -// enough of H will be updated to preserve the eigenvalues. -// -// If wantz is true, the orthogonal similarity transformation will be -// accumulated into Z[iloz:ihiz+1,ktop:kbot+1], otherwise Z is not referenced. -// -// ktop and kbot determine a block [ktop:kbot+1,ktop:kbot+1] along the diagonal -// of H. It must hold that -// -// 0 <= ilo <= ihi < n if n > 0, -// ilo == 0 and ihi == -1 if n == 0, -// -// and the block must be isolated, that is, it must hold that -// -// ktop == 0 or H[ktop,ktop-1] == 0, -// kbot == n-1 or H[kbot+1,kbot] == 0, -// -// otherwise Dlaqr23 will panic. -// -// nw is the deflation window size. It must hold that -// -// 0 <= nw <= kbot-ktop+1, -// -// otherwise Dlaqr23 will panic. -// -// iloz and ihiz specify the rows of the n×n matrix Z to which transformations -// will be applied if wantz is true. It must hold that -// -// 0 <= iloz <= ktop, and kbot <= ihiz < n, -// -// otherwise Dlaqr23 will panic. -// -// sr and si must have length kbot+1, otherwise Dlaqr23 will panic. -// -// v and ldv represent an nw×nw work matrix. -// t and ldt represent an nw×nh work matrix, and nh must be at least nw. -// wv and ldwv represent an nv×nw work matrix. -// -// work must have length at least lwork and lwork must be at least max(1,2*nw), -// otherwise Dlaqr23 will panic. Larger values of lwork may result in greater -// efficiency. On return, work[0] will contain the optimal value of lwork. -// -// If lwork is -1, instead of performing Dlaqr23, the function only estimates the -// optimal workspace size and stores it into work[0]. Neither h nor z are -// accessed. -// -// recur is the non-negative recursion depth. For recur > 0, Dlaqr23 behaves -// as DLAQR3, for recur == 0 it behaves as DLAQR2. -// -// On return, ns and nd will contain respectively the number of unconverged -// (i.e., approximate) eigenvalues and converged eigenvalues that are stored in -// sr and si. -// -// On return, the real and imaginary parts of approximate eigenvalues that may -// be used for shifts will be stored respectively in sr[kbot-nd-ns+1:kbot-nd+1] -// and si[kbot-nd-ns+1:kbot-nd+1]. -// -// On return, the real and imaginary parts of converged eigenvalues will be -// stored respectively in sr[kbot-nd+1:kbot+1] and si[kbot-nd+1:kbot+1]. -// -// References: -// -// [1] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: -// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl 23(4) (2002), pp. 948—973 -// URL: http://dx.doi.org/10.1137/S0895479801384585 -func (impl Implementation) Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, sr, si []float64, v []float64, ldv int, nh int, t []float64, ldt int, nv int, wv []float64, ldwv int, work []float64, lwork int, recur int) (ns, nd int) { - switch { - case n < 0: - panic(nLT0) - case ktop < 0 || max(0, n-1) < ktop: - panic(badKtop) - case kbot < min(ktop, n-1) || n <= kbot: - panic(badKbot) - case nw < 0 || kbot-ktop+1+1 < nw: - panic(badNw) - case ldh < max(1, n): - panic(badLdH) - case wantz && (iloz < 0 || ktop < iloz): - panic(badIloz) - case wantz && (ihiz < kbot || n <= ihiz): - panic(badIhiz) - case ldz < 1, wantz && ldz < n: - panic(badLdZ) - case ldv < max(1, nw): - panic(badLdV) - case nh < nw: - panic(badNh) - case ldt < max(1, nh): - panic(badLdT) - case nv < 0: - panic(nvLT0) - case ldwv < max(1, nw): - panic(badLdWV) - case lwork < max(1, 2*nw) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - case recur < 0: - panic(recurLT0) - } - - // Quick return for zero window size. - if nw == 0 { - work[0] = 1 - return 0, 0 - } - - // LAPACK code does not enforce the documented behavior - // nw <= kbot-ktop+1 - // but we do (we panic above). - jw := nw - lwkopt := max(1, 2*nw) - if jw > 2 { - // Workspace query call to Dgehrd. - impl.Dgehrd(jw, 0, jw-2, t, ldt, work, work, -1) - lwk1 := int(work[0]) - // Workspace query call to Dormhr. - impl.Dormhr(blas.Right, blas.NoTrans, jw, jw, 0, jw-2, t, ldt, work, v, ldv, work, -1) - lwk2 := int(work[0]) - if recur > 0 { - // Workspace query call to Dlaqr04. - impl.Dlaqr04(true, true, jw, 0, jw-1, t, ldt, sr, si, 0, jw-1, v, ldv, work, -1, recur-1) - lwk3 := int(work[0]) - // Optimal workspace. - lwkopt = max(jw+max(lwk1, lwk2), lwk3) - } else { - // Optimal workspace. - lwkopt = jw + max(lwk1, lwk2) - } - } - // Quick return in case of workspace query. - if lwork == -1 { - work[0] = float64(lwkopt) - return 0, 0 - } - - // Check input slices only if not doing workspace query. - switch { - case len(h) < (n-1)*ldh+n: - panic(shortH) - case len(v) < (nw-1)*ldv+nw: - panic(shortV) - case len(t) < (nw-1)*ldt+nh: - panic(shortT) - case len(wv) < (nv-1)*ldwv+nw: - panic(shortWV) - case wantz && len(z) < (n-1)*ldz+n: - panic(shortZ) - case len(sr) != kbot+1: - panic(badLenSr) - case len(si) != kbot+1: - panic(badLenSi) - case ktop > 0 && h[ktop*ldh+ktop-1] != 0: - panic(notIsolated) - case kbot+1 < n && h[(kbot+1)*ldh+kbot] != 0: - panic(notIsolated) - } - - // Machine constants. - ulp := dlamchP - smlnum := float64(n) / ulp * dlamchS - - // Setup deflation window. - var s float64 - kwtop := kbot - jw + 1 - if kwtop != ktop { - s = h[kwtop*ldh+kwtop-1] - } - if kwtop == kbot { - // 1×1 deflation window. - sr[kwtop] = h[kwtop*ldh+kwtop] - si[kwtop] = 0 - ns = 1 - nd = 0 - if math.Abs(s) <= math.Max(smlnum, ulp*math.Abs(h[kwtop*ldh+kwtop])) { - ns = 0 - nd = 1 - if kwtop > ktop { - h[kwtop*ldh+kwtop-1] = 0 - } - } - work[0] = 1 - return ns, nd - } - - // Convert to spike-triangular form. In case of a rare QR failure, this - // routine continues to do aggressive early deflation using that part of - // the deflation window that converged using infqr here and there to - // keep track. - impl.Dlacpy(blas.Upper, jw, jw, h[kwtop*ldh+kwtop:], ldh, t, ldt) - bi := blas64.Implementation() - bi.Dcopy(jw-1, h[(kwtop+1)*ldh+kwtop:], ldh+1, t[ldt:], ldt+1) - impl.Dlaset(blas.All, jw, jw, 0, 1, v, ldv) - nmin := impl.Ilaenv(12, "DLAQR3", "SV", jw, 0, jw-1, lwork) - var infqr int - if recur > 0 && jw > nmin { - infqr = impl.Dlaqr04(true, true, jw, 0, jw-1, t, ldt, sr[kwtop:], si[kwtop:], 0, jw-1, v, ldv, work, lwork, recur-1) - } else { - infqr = impl.Dlahqr(true, true, jw, 0, jw-1, t, ldt, sr[kwtop:], si[kwtop:], 0, jw-1, v, ldv) - } - // Note that ilo == 0 which conveniently coincides with the success - // value of infqr, that is, infqr as an index always points to the first - // converged eigenvalue. - - // Dtrexc needs a clean margin near the diagonal. - for j := 0; j < jw-3; j++ { - t[(j+2)*ldt+j] = 0 - t[(j+3)*ldt+j] = 0 - } - if jw >= 3 { - t[(jw-1)*ldt+jw-3] = 0 - } - - ns = jw - ilst := infqr - // Deflation detection loop. - for ilst < ns { - bulge := false - if ns >= 2 { - bulge = t[(ns-1)*ldt+ns-2] != 0 - } - if !bulge { - // Real eigenvalue. - abst := math.Abs(t[(ns-1)*ldt+ns-1]) - if abst == 0 { - abst = math.Abs(s) - } - if math.Abs(s*v[ns-1]) <= math.Max(smlnum, ulp*abst) { - // Deflatable. - ns-- - } else { - // Undeflatable, move it up out of the way. - // Dtrexc can not fail in this case. - _, ilst, _ = impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, ns-1, ilst, work) - ilst++ - } - continue - } - // Complex conjugate pair. - abst := math.Abs(t[(ns-1)*ldt+ns-1]) + math.Sqrt(math.Abs(t[(ns-1)*ldt+ns-2]))*math.Sqrt(math.Abs(t[(ns-2)*ldt+ns-1])) - if abst == 0 { - abst = math.Abs(s) - } - if math.Max(math.Abs(s*v[ns-1]), math.Abs(s*v[ns-2])) <= math.Max(smlnum, ulp*abst) { - // Deflatable. - ns -= 2 - } else { - // Undeflatable, move them up out of the way. - // Dtrexc does the right thing with ilst in case of a - // rare exchange failure. - _, ilst, _ = impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, ns-1, ilst, work) - ilst += 2 - } - } - - // Return to Hessenberg form. - if ns == 0 { - s = 0 - } - if ns < jw { - // Sorting diagonal blocks of T improves accuracy for graded - // matrices. Bubble sort deals well with exchange failures. - sorted := false - i := ns - for !sorted { - sorted = true - kend := i - 1 - i = infqr - var k int - if i == ns-1 || t[(i+1)*ldt+i] == 0 { - k = i + 1 - } else { - k = i + 2 - } - for k <= kend { - var evi float64 - if k == i+1 { - evi = math.Abs(t[i*ldt+i]) - } else { - evi = math.Abs(t[i*ldt+i]) + math.Sqrt(math.Abs(t[(i+1)*ldt+i]))*math.Sqrt(math.Abs(t[i*ldt+i+1])) - } - - var evk float64 - if k == kend || t[(k+1)*ldt+k] == 0 { - evk = math.Abs(t[k*ldt+k]) - } else { - evk = math.Abs(t[k*ldt+k]) + math.Sqrt(math.Abs(t[(k+1)*ldt+k]))*math.Sqrt(math.Abs(t[k*ldt+k+1])) - } - - if evi >= evk { - i = k - } else { - sorted = false - _, ilst, ok := impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, i, k, work) - if ok { - i = ilst - } else { - i = k - } - } - if i == kend || t[(i+1)*ldt+i] == 0 { - k = i + 1 - } else { - k = i + 2 - } - } - } - } - - // Restore shift/eigenvalue array from T. - for i := jw - 1; i >= infqr; { - if i == infqr || t[i*ldt+i-1] == 0 { - sr[kwtop+i] = t[i*ldt+i] - si[kwtop+i] = 0 - i-- - continue - } - aa := t[(i-1)*ldt+i-1] - bb := t[(i-1)*ldt+i] - cc := t[i*ldt+i-1] - dd := t[i*ldt+i] - _, _, _, _, sr[kwtop+i-1], si[kwtop+i-1], sr[kwtop+i], si[kwtop+i], _, _ = impl.Dlanv2(aa, bb, cc, dd) - i -= 2 - } - - if ns < jw || s == 0 { - if ns > 1 && s != 0 { - // Reflect spike back into lower triangle. - bi.Dcopy(ns, v[:ns], 1, work[:ns], 1) - _, tau := impl.Dlarfg(ns, work[0], work[1:ns], 1) - work[0] = 1 - impl.Dlaset(blas.Lower, jw-2, jw-2, 0, 0, t[2*ldt:], ldt) - impl.Dlarf(blas.Left, ns, jw, work[:ns], 1, tau, t, ldt, work[jw:]) - impl.Dlarf(blas.Right, ns, ns, work[:ns], 1, tau, t, ldt, work[jw:]) - impl.Dlarf(blas.Right, jw, ns, work[:ns], 1, tau, v, ldv, work[jw:]) - impl.Dgehrd(jw, 0, ns-1, t, ldt, work[:jw-1], work[jw:], lwork-jw) - } - - // Copy updated reduced window into place. - if kwtop > 0 { - h[kwtop*ldh+kwtop-1] = s * v[0] - } - impl.Dlacpy(blas.Upper, jw, jw, t, ldt, h[kwtop*ldh+kwtop:], ldh) - bi.Dcopy(jw-1, t[ldt:], ldt+1, h[(kwtop+1)*ldh+kwtop:], ldh+1) - - // Accumulate orthogonal matrix in order to update H and Z, if - // requested. - if ns > 1 && s != 0 { - // work[:ns-1] contains the elementary reflectors stored - // by a call to Dgehrd above. - impl.Dormhr(blas.Right, blas.NoTrans, jw, ns, 0, ns-1, - t, ldt, work[:ns-1], v, ldv, work[jw:], lwork-jw) - } - - // Update vertical slab in H. - var ltop int - if !wantt { - ltop = ktop - } - for krow := ltop; krow < kwtop; krow += nv { - kln := min(nv, kwtop-krow) - bi.Dgemm(blas.NoTrans, blas.NoTrans, kln, jw, jw, - 1, h[krow*ldh+kwtop:], ldh, v, ldv, - 0, wv, ldwv) - impl.Dlacpy(blas.All, kln, jw, wv, ldwv, h[krow*ldh+kwtop:], ldh) - } - - // Update horizontal slab in H. - if wantt { - for kcol := kbot + 1; kcol < n; kcol += nh { - kln := min(nh, n-kcol) - bi.Dgemm(blas.Trans, blas.NoTrans, jw, kln, jw, - 1, v, ldv, h[kwtop*ldh+kcol:], ldh, - 0, t, ldt) - impl.Dlacpy(blas.All, jw, kln, t, ldt, h[kwtop*ldh+kcol:], ldh) - } - } - - // Update vertical slab in Z. - if wantz { - for krow := iloz; krow <= ihiz; krow += nv { - kln := min(nv, ihiz-krow+1) - bi.Dgemm(blas.NoTrans, blas.NoTrans, kln, jw, jw, - 1, z[krow*ldz+kwtop:], ldz, v, ldv, - 0, wv, ldwv) - impl.Dlacpy(blas.All, kln, jw, wv, ldwv, z[krow*ldz+kwtop:], ldz) - } - } - } - - // The number of deflations. - nd = jw - ns - // Shifts are converged eigenvalues that could not be deflated. - // Subtracting infqr from the spike length takes care of the case of a - // rare QR failure while calculating eigenvalues of the deflation - // window. - ns -= infqr - work[0] = float64(lwkopt) - return ns, nd -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go deleted file mode 100644 index 443a53d5..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go +++ /dev/null @@ -1,560 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlaqr5 performs a single small-bulge multi-shift QR sweep on an isolated -// block of a Hessenberg matrix. -// -// wantt and wantz determine whether the quasi-triangular Schur factor and the -// orthogonal Schur factor, respectively, will be computed. -// -// kacc22 specifies the computation mode of far-from-diagonal orthogonal -// updates. Permitted values are: -// -// 0: Dlaqr5 will not accumulate reflections and will not use matrix-matrix -// multiply to update far-from-diagonal matrix entries. -// 1: Dlaqr5 will accumulate reflections and use matrix-matrix multiply to -// update far-from-diagonal matrix entries. -// 2: Same as kacc22=1. This option used to enable exploiting the 2×2 structure -// during matrix multiplications, but this is no longer supported. -// -// For other values of kacc2 Dlaqr5 will panic. -// -// n is the order of the Hessenberg matrix H. -// -// ktop and kbot are indices of the first and last row and column of an isolated -// diagonal block upon which the QR sweep will be applied. It must hold that -// -// ktop == 0, or 0 < ktop <= n-1 and H[ktop, ktop-1] == 0, and -// kbot == n-1, or 0 <= kbot < n-1 and H[kbot+1, kbot] == 0, -// -// otherwise Dlaqr5 will panic. -// -// nshfts is the number of simultaneous shifts. It must be positive and even, -// otherwise Dlaqr5 will panic. -// -// sr and si contain the real and imaginary parts, respectively, of the shifts -// of origin that define the multi-shift QR sweep. On return both slices may be -// reordered by Dlaqr5. Their length must be equal to nshfts, otherwise Dlaqr5 -// will panic. -// -// h and ldh represent the Hessenberg matrix H of size n×n. On return -// multi-shift QR sweep with shifts sr+i*si has been applied to the isolated -// diagonal block in rows and columns ktop through kbot, inclusive. -// -// iloz and ihiz specify the rows of Z to which transformations will be applied -// if wantz is true. It must hold that 0 <= iloz <= ihiz < n, otherwise Dlaqr5 -// will panic. -// -// z and ldz represent the matrix Z of size n×n. If wantz is true, the QR sweep -// orthogonal similarity transformation is accumulated into -// z[iloz:ihiz,iloz:ihiz] from the right, otherwise z not referenced. -// -// v and ldv represent an auxiliary matrix V of size (nshfts/2)×3. Note that V -// is transposed with respect to the reference netlib implementation. -// -// u and ldu represent an auxiliary matrix of size (2*nshfts)×(2*nshfts). -// -// wh and ldwh represent an auxiliary matrix of size (2*nshfts-1)×nh. -// -// wv and ldwv represent an auxiliary matrix of size nv×(2*nshfts-1). -// -// Dlaqr5 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot, nshfts int, sr, si []float64, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, u []float64, ldu int, nv int, wv []float64, ldwv int, nh int, wh []float64, ldwh int) { - switch { - case kacc22 != 0 && kacc22 != 1 && kacc22 != 2: - panic(badKacc22) - case n < 0: - panic(nLT0) - case ktop < 0 || n <= ktop: - panic(badKtop) - case kbot < 0 || n <= kbot: - panic(badKbot) - - case nshfts < 0: - panic(nshftsLT0) - case nshfts&0x1 != 0: - panic(nshftsOdd) - case len(sr) != nshfts: - panic(badLenSr) - case len(si) != nshfts: - panic(badLenSi) - - case ldh < max(1, n): - panic(badLdH) - case len(h) < (n-1)*ldh+n: - panic(shortH) - - case wantz && ihiz >= n: - panic(badIhiz) - case wantz && iloz < 0 || ihiz < iloz: - panic(badIloz) - case ldz < 1, wantz && ldz < n: - panic(badLdZ) - case wantz && len(z) < (n-1)*ldz+n: - panic(shortZ) - - case ldv < 3: - // V is transposed w.r.t. reference lapack. - panic(badLdV) - case len(v) < (nshfts/2-1)*ldv+3: - panic(shortV) - - case ldu < max(1, 2*nshfts): - panic(badLdU) - case len(u) < (2*nshfts-1)*ldu+2*nshfts: - panic(shortU) - - case nv < 0: - panic(nvLT0) - case ldwv < max(1, 2*nshfts): - panic(badLdWV) - case len(wv) < (nv-1)*ldwv+2*nshfts: - panic(shortWV) - - case nh < 0: - panic(nhLT0) - case ldwh < max(1, nh): - panic(badLdWH) - case len(wh) < (2*nshfts-1)*ldwh+nh: - panic(shortWH) - - case ktop > 0 && h[ktop*ldh+ktop-1] != 0: - panic(notIsolated) - case kbot < n-1 && h[(kbot+1)*ldh+kbot] != 0: - panic(notIsolated) - } - - // If there are no shifts, then there is nothing to do. - if nshfts < 2 { - return - } - // If the active block is empty or 1×1, then there is nothing to do. - if ktop >= kbot { - return - } - - // Shuffle shifts into pairs of real shifts and pairs of complex - // conjugate shifts assuming complex conjugate shifts are already - // adjacent to one another. - for i := 0; i < nshfts-2; i += 2 { - if si[i] == -si[i+1] { - continue - } - sr[i], sr[i+1], sr[i+2] = sr[i+1], sr[i+2], sr[i] - si[i], si[i+1], si[i+2] = si[i+1], si[i+2], si[i] - } - - // Note: lapack says that nshfts must be even but allows it to be odd - // anyway. We panic above if nshfts is not even, so reducing it by one - // is unnecessary. The only caller Dlaqr04 uses only even nshfts. - // - // The original comment and code from lapack-3.6.0/SRC/dlaqr5.f:341: - // * ==== NSHFTS is supposed to be even, but if it is odd, - // * . then simply reduce it by one. The shuffle above - // * . ensures that the dropped shift is real and that - // * . the remaining shifts are paired. ==== - // * - // NS = NSHFTS - MOD( NSHFTS, 2 ) - ns := nshfts - - safmin := dlamchS - ulp := dlamchP - smlnum := safmin * float64(n) / ulp - - // Use accumulated reflections to update far-from-diagonal entries? - accum := kacc22 == 1 || kacc22 == 2 - - // Clear trash. - if ktop+2 <= kbot { - h[(ktop+2)*ldh+ktop] = 0 - } - - // nbmps = number of 2-shift bulges in the chain. - nbmps := ns / 2 - - // kdu = width of slab. - kdu := 4 * nbmps - - // Create and chase chains of nbmps bulges. - for incol := ktop - 2*nbmps + 1; incol <= kbot-2; incol += 2 * nbmps { - // jtop is an index from which updates from the right start. - var jtop int - switch { - case accum: - jtop = max(ktop, incol) - case wantt: - default: - jtop = ktop - } - ndcol := incol + kdu - if accum { - impl.Dlaset(blas.All, kdu, kdu, 0, 1, u, ldu) - } - // Near-the-diagonal bulge chase. The following loop performs - // the near-the-diagonal part of a small bulge multi-shift QR - // sweep. Each 4*nbmps column diagonal chunk extends from - // column incol to column ndcol (including both column incol and - // column ndcol). The following loop chases a 2*nbmps+1 column - // long chain of nbmps bulges 2*nbmps columns to the right. - // (incol may be less than ktop and ndcol may be greater than - // kbot indicating phantom columns from which to chase bulges - // before they are actually introduced or to which to chase - // bulges beyond column kbot.) - for krcol := incol; krcol <= min(incol+2*nbmps-1, kbot-2); krcol++ { - // Bulges number mtop to mbot are active double implicit - // shift bulges. There may or may not also be small 2×2 - // bulge, if there is room. The inactive bulges (if any) - // must wait until the active bulges have moved down the - // diagonal to make room. The phantom matrix paradigm - // described above helps keep track. - mtop := max(0, (ktop-krcol)/2) - mbot := min(nbmps, (kbot-krcol-1)/2) - 1 - m22 := mbot + 1 - bmp22 := (mbot < nbmps-1) && (krcol+2*m22 == kbot-2) - // Generate reflections to chase the chain right one column. - // The minimum value of k is ktop-1. - if bmp22 { - // Special case: 2×2 reflection at bottom treated separately. - k := krcol + 2*m22 - if k == ktop-1 { - impl.Dlaqr1(2, h[(k+1)*ldh+k+1:], ldh, - sr[2*m22], si[2*m22], sr[2*m22+1], si[2*m22+1], - v[m22*ldv:m22*ldv+2]) - beta := v[m22*ldv] - _, v[m22*ldv] = impl.Dlarfg(2, beta, v[m22*ldv+1:m22*ldv+2], 1) - } else { - beta := h[(k+1)*ldh+k] - v[m22*ldv+1] = h[(k+2)*ldh+k] - beta, v[m22*ldv] = impl.Dlarfg(2, beta, v[m22*ldv+1:m22*ldv+2], 1) - h[(k+1)*ldh+k] = beta - h[(k+2)*ldh+k] = 0 - } - // Perform update from right within computational window. - t1 := v[m22*ldv] - t2 := t1 * v[m22*ldv+1] - for j := jtop; j <= min(kbot, k+3); j++ { - refsum := h[j*ldh+k+1] + v[m22*ldv+1]*h[j*ldh+k+2] - h[j*ldh+k+1] -= refsum * t1 - h[j*ldh+k+2] -= refsum * t2 - } - // Perform update from left within computational window. - var jbot int - switch { - case accum: - jbot = min(ndcol, kbot) - case wantt: - jbot = n - 1 - default: - jbot = kbot - } - t1 = v[m22*ldv] - t2 = t1 * v[m22*ldv+1] - for j := k + 1; j <= jbot; j++ { - refsum := h[(k+1)*ldh+j] + v[m22*ldv+1]*h[(k+2)*ldh+j] - h[(k+1)*ldh+j] -= refsum * t1 - h[(k+2)*ldh+j] -= refsum * t2 - } - // The following convergence test requires that the traditional - // small-compared-to-nearby-diagonals criterion and the Ahues & - // Tisseur (LAWN 122, 1997) criteria both be satisfied. The latter - // improves accuracy in some examples. Falling back on an alternate - // convergence criterion when tst1 or tst2 is zero (as done here) is - // traditional but probably unnecessary. - if k >= ktop && h[(k+1)*ldh+k] != 0 { - tst1 := math.Abs(h[k*ldh+k]) + math.Abs(h[(k+1)*ldh+k+1]) - if tst1 == 0 { - if k >= ktop+1 { - tst1 += math.Abs(h[k*ldh+k-1]) - } - if k >= ktop+2 { - tst1 += math.Abs(h[k*ldh+k-2]) - } - if k >= ktop+3 { - tst1 += math.Abs(h[k*ldh+k-3]) - } - if k <= kbot-2 { - tst1 += math.Abs(h[(k+2)*ldh+k+1]) - } - if k <= kbot-3 { - tst1 += math.Abs(h[(k+3)*ldh+k+1]) - } - if k <= kbot-4 { - tst1 += math.Abs(h[(k+4)*ldh+k+1]) - } - } - if math.Abs(h[(k+1)*ldh+k]) <= math.Max(smlnum, ulp*tst1) { - h12 := math.Max(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) - h21 := math.Min(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) - h11 := math.Max(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) - h22 := math.Min(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) - scl := h11 + h12 - tst2 := h22 * (h11 / scl) - if tst2 == 0 || h21*(h12/scl) <= math.Max(smlnum, ulp*tst2) { - h[(k+1)*ldh+k] = 0 - } - } - } - // Accumulate orthogonal transformations. - if accum { - kms := k - incol - 1 - t1 = v[m22*ldv] - t2 = t1 * v[m22*ldv+1] - for j := max(0, ktop-incol-1); j < kdu; j++ { - refsum := u[j*ldu+kms+1] + v[m22*ldv+1]*u[j*ldu+kms+2] - u[j*ldu+kms+1] -= refsum * t1 - u[j*ldu+kms+2] -= refsum * t2 - } - } else if wantz { - t1 = v[m22*ldv] - t2 = t1 * v[m22*ldv+1] - for j := iloz; j <= ihiz; j++ { - refsum := z[j*ldz+k+1] + v[m22*ldv+1]*z[j*ldz+k+2] - z[j*ldz+k+1] -= refsum * t1 - z[j*ldz+k+2] -= refsum * t2 - } - } - } - // Normal case: Chain of 3×3 reflections. - for m := mbot; m >= mtop; m-- { - k := krcol + 2*m - if k == ktop-1 { - impl.Dlaqr1(3, h[ktop*ldh+ktop:], ldh, - sr[2*m], si[2*m], sr[2*m+1], si[2*m+1], - v[m*ldv:m*ldv+3]) - alpha := v[m*ldv] - _, v[m*ldv] = impl.Dlarfg(3, alpha, v[m*ldv+1:m*ldv+3], 1) - } else { - // Perform delayed transformation of row below m-th bulge. - // Exploit fact that first two elements of row are actually - // zero. - t1 := v[m*ldv] - t2 := t1 * v[m*ldv+1] - t3 := t1 * v[m*ldv+2] - refsum := v[m*ldv+2] * h[(k+3)*ldh+k+2] - h[(k+3)*ldh+k] = -refsum * t1 - h[(k+3)*ldh+k+1] = -refsum * t2 - h[(k+3)*ldh+k+2] -= refsum * t3 - // Calculate reflection to move m-th bulge one step. - beta := h[(k+1)*ldh+k] - v[m*ldv+1] = h[(k+2)*ldh+k] - v[m*ldv+2] = h[(k+3)*ldh+k] - beta, v[m*ldv] = impl.Dlarfg(3, beta, v[m*ldv+1:m*ldv+3], 1) - // A bulge may collapse because of vigilant deflation or - // destructive underflow. In the underflow case, try the - // two-small-subdiagonals trick to try to reinflate the - // bulge. - if h[(k+3)*ldh+k] != 0 || h[(k+3)*ldh+k+1] != 0 || h[(k+3)*ldh+k+2] == 0 { - // Typical case: not collapsed (yet). - h[(k+1)*ldh+k] = beta - h[(k+2)*ldh+k] = 0 - h[(k+3)*ldh+k] = 0 - } else { - // Atypical case: collapsed. Attempt to reintroduce - // ignoring H[k+1,k] and H[k+2,k]. If the fill resulting - // from the new reflector is too large, then abandon it. - // Otherwise, use the new one. - var vt [3]float64 - impl.Dlaqr1(3, h[(k+1)*ldh+k+1:], ldh, - sr[2*m], si[2*m], sr[2*m+1], si[2*m+1], - vt[:]) - _, vt[0] = impl.Dlarfg(3, vt[0], vt[1:3], 1) - t1 = vt[0] - t2 = t1 * vt[1] - t3 = t1 * vt[2] - refsum = h[(k+1)*ldh+k] + vt[1]*h[(k+2)*ldh+k] - dsum := math.Abs(h[k*ldh+k]) + math.Abs(h[(k+1)*ldh+k+1]) + math.Abs(h[(k+2)*ldh+k+2]) - if math.Abs(h[(k+2)*ldh+k]-refsum*t2)+math.Abs(refsum*t3) > ulp*dsum { - // Starting a new bulge here would create - // non-negligible fill. Use the old one with - // trepidation. - h[(k+1)*ldh+k] = beta - h[(k+2)*ldh+k] = 0 - h[(k+3)*ldh+k] = 0 - } else { - // Starting a new bulge here would create only - // negligible fill. Replace the old reflector with - // the new one. - h[(k+1)*ldh+k] -= refsum * t1 - h[(k+2)*ldh+k] = 0 - h[(k+3)*ldh+k] = 0 - v[m*ldv] = vt[0] - v[m*ldv+1] = vt[1] - v[m*ldv+2] = vt[2] - } - } - } - // Apply reflection from the right and the first column of - // update from the left. These updates are required for the - // vigilant deflation check. We still delay most of the updates - // from the left for efficiency. - t1 := v[m*ldv] - t2 := t1 * v[m*ldv+1] - t3 := t1 * v[m*ldv+2] - for j := jtop; j <= min(kbot, k+3); j++ { - refsum := h[j*ldh+k+1] + v[m*ldv+1]*h[j*ldh+k+2] + v[m*ldv+2]*h[j*ldh+k+3] - h[j*ldh+k+1] -= refsum * t1 - h[j*ldh+k+2] -= refsum * t2 - h[j*ldh+k+3] -= refsum * t3 - } - // Perform update from left for subsequent column. - refsum := h[(k+1)*ldh+k+1] + v[m*ldv+1]*h[(k+2)*ldh+k+1] + v[m*ldv+2]*h[(k+3)*ldh+k+1] - h[(k+1)*ldh+k+1] -= refsum * t1 - h[(k+2)*ldh+k+1] -= refsum * t2 - h[(k+3)*ldh+k+1] -= refsum * t3 - // The following convergence test requires that the tradition - // small-compared-to-nearby-diagonals criterion and the Ahues & - // Tisseur (LAWN 122, 1997) criteria both be satisfied. The - // latter improves accuracy in some examples. Falling back on an - // alternate convergence criterion when tst1 or tst2 is zero (as - // done here) is traditional but probably unnecessary. - if k < ktop { - continue - } - if h[(k+1)*ldh+k] != 0 { - tst1 := math.Abs(h[k*ldh+k]) + math.Abs(h[(k+1)*ldh+k+1]) - if tst1 == 0 { - if k >= ktop+1 { - tst1 += math.Abs(h[k*ldh+k-1]) - } - if k >= ktop+2 { - tst1 += math.Abs(h[k*ldh+k-2]) - } - if k >= ktop+3 { - tst1 += math.Abs(h[k*ldh+k-3]) - } - if k <= kbot-2 { - tst1 += math.Abs(h[(k+2)*ldh+k+1]) - } - if k <= kbot-3 { - tst1 += math.Abs(h[(k+3)*ldh+k+1]) - } - if k <= kbot-4 { - tst1 += math.Abs(h[(k+4)*ldh+k+1]) - } - } - if math.Abs(h[(k+1)*ldh+k]) <= math.Max(smlnum, ulp*tst1) { - h12 := math.Max(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) - h21 := math.Min(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) - h11 := math.Max(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) - h22 := math.Min(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) - scl := h11 + h12 - tst2 := h22 * (h11 / scl) - if tst2 == 0 || h21*(h12/scl) <= math.Max(smlnum, ulp*tst2) { - h[(k+1)*ldh+k] = 0 - } - } - } - } - // Multiply H by reflections from the left. - var jbot int - switch { - case accum: - jbot = min(ndcol, kbot) - case wantt: - jbot = n - 1 - default: - jbot = kbot - } - for m := mbot; m >= mtop; m-- { - k := krcol + 2*m - t1 := v[m*ldv] - t2 := t1 * v[m*ldv+1] - t3 := t1 * v[m*ldv+2] - for j := max(ktop, krcol+2*(m+1)); j <= jbot; j++ { - refsum := h[(k+1)*ldh+j] + v[m*ldv+1]*h[(k+2)*ldh+j] + v[m*ldv+2]*h[(k+3)*ldh+j] - h[(k+1)*ldh+j] -= refsum * t1 - h[(k+2)*ldh+j] -= refsum * t2 - h[(k+3)*ldh+j] -= refsum * t3 - } - } - // Accumulate orthogonal transformations. - if accum { - // Accumulate U. If necessary, update Z later with an - // efficient matrix-matrix multiply. - for m := mbot; m >= mtop; m-- { - k := krcol + 2*m - kms := k - incol - 1 - i2 := max(0, ktop-incol-1) - i2 = max(i2, kms-(krcol-incol)) - i4 := min(kdu, krcol+2*mbot-incol+5) - t1 := v[m*ldv] - t2 := t1 * v[m*ldv+1] - t3 := t1 * v[m*ldv+2] - for j := i2; j < i4; j++ { - refsum := u[j*ldu+kms+1] + v[m*ldv+1]*u[j*ldu+kms+2] + v[m*ldv+2]*u[j*ldu+kms+3] - u[j*ldu+kms+1] -= refsum * t1 - u[j*ldu+kms+2] -= refsum * t2 - u[j*ldu+kms+3] -= refsum * t3 - } - } - } else if wantz { - // U is not accumulated, so update Z now by multiplying by - // reflections from the right. - for m := mbot; m >= mtop; m-- { - k := krcol + 2*m - t1 := v[m*ldv] - t2 := t1 * v[m*ldv+1] - t3 := t1 * v[m*ldv+2] - for j := iloz; j <= ihiz; j++ { - refsum := z[j*ldz+k+1] + v[m*ldv+1]*z[j*ldz+k+2] + v[m*ldv+2]*z[j*ldz+k+3] - z[j*ldz+k+1] -= refsum * t1 - z[j*ldz+k+2] -= refsum * t2 - z[j*ldz+k+3] -= refsum * t3 - } - } - } - } - // Use U (if accumulated) to update far-from-diagonal entries in H. - // If required, use U to update Z as well. - if !accum { - continue - } - jtop, jbot := ktop, kbot - if wantt { - jtop = 0 - jbot = n - 1 - } - bi := blas64.Implementation() - k1 := max(0, ktop-incol-1) - nu := kdu - max(0, ndcol-kbot) - k1 - // Horizontal multiply. - for jcol := min(ndcol, kbot) + 1; jcol <= jbot; jcol += nh { - jlen := min(nh, jbot-jcol+1) - bi.Dgemm(blas.Trans, blas.NoTrans, nu, jlen, nu, - 1, u[k1*ldu+k1:], ldu, - h[(incol+k1+1)*ldh+jcol:], ldh, - 0, wh, ldwh) - impl.Dlacpy(blas.All, nu, jlen, wh, ldwh, h[(incol+k1+1)*ldh+jcol:], ldh) - } - // Vertical multiply. - for jrow := jtop; jrow < max(ktop, incol); jrow += nv { - jlen := min(nv, max(ktop, incol)-jrow) - bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, nu, nu, - 1, h[jrow*ldh+incol+k1+1:], ldh, - u[k1*ldu+k1:], ldu, - 0, wv, ldwv) - impl.Dlacpy(blas.All, jlen, nu, wv, ldwv, h[jrow*ldh+incol+k1+1:], ldh) - } - // Z multiply (also vertical). - if wantz { - for jrow := iloz; jrow <= ihiz; jrow += nv { - jlen := min(nv, ihiz-jrow+1) - bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, nu, nu, - 1, z[jrow*ldz+incol+k1+1:], ldz, - u[k1*ldu+k1:], ldu, - 0, wv, ldwv) - impl.Dlacpy(blas.All, jlen, nu, wv, ldwv, z[jrow*ldz+incol+k1+1:], ldz) - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go deleted file mode 100644 index 16581a1b..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlarf applies an elementary reflector H to an m×n matrix C: -// -// C = H * C if side == blas.Left -// C = C * H if side == blas.Right -// -// H is represented in the form -// -// H = I - tau * v * vᵀ -// -// where tau is a scalar and v is a vector. -// -// work must have length at least m if side == blas.Left and -// at least n if side == blas.Right. -// -// Dlarf is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlarf(side blas.Side, m, n int, v []float64, incv int, tau float64, c []float64, ldc int, work []float64) { - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case incv == 0: - panic(zeroIncV) - case ldc < max(1, n): - panic(badLdC) - } - - if m == 0 || n == 0 { - return - } - - applyleft := side == blas.Left - lenV := n - if applyleft { - lenV = m - } - - switch { - case len(v) < 1+(lenV-1)*abs(incv): - panic(shortV) - case len(c) < (m-1)*ldc+n: - panic(shortC) - case (applyleft && len(work) < n) || (!applyleft && len(work) < m): - panic(shortWork) - } - - lastv := -1 // last non-zero element of v - lastc := -1 // last non-zero row/column of C - if tau != 0 { - if applyleft { - lastv = m - 1 - } else { - lastv = n - 1 - } - var i int - if incv > 0 { - i = lastv * incv - } - // Look for the last non-zero row in v. - for lastv >= 0 && v[i] == 0 { - lastv-- - i -= incv - } - if applyleft { - // Scan for the last non-zero column in C[0:lastv, :] - lastc = impl.Iladlc(lastv+1, n, c, ldc) - } else { - // Scan for the last non-zero row in C[:, 0:lastv] - lastc = impl.Iladlr(m, lastv+1, c, ldc) - } - } - if lastv == -1 || lastc == -1 { - return - } - bi := blas64.Implementation() - if applyleft { - // Form H * C - // w[0:lastc+1] = c[1:lastv+1, 1:lastc+1]ᵀ * v[1:lastv+1,1] - bi.Dgemv(blas.Trans, lastv+1, lastc+1, 1, c, ldc, v, incv, 0, work, 1) - // c[0: lastv, 0: lastc] = c[...] - w[0:lastv, 1] * v[1:lastc, 1]ᵀ - bi.Dger(lastv+1, lastc+1, -tau, v, incv, work, 1, c, ldc) - } else { - // Form C * H - // w[0:lastc+1,1] := c[0:lastc+1,0:lastv+1] * v[0:lastv+1,1] - bi.Dgemv(blas.NoTrans, lastc+1, lastv+1, 1, c, ldc, v, incv, 0, work, 1) - // c[0:lastc+1,0:lastv+1] = c[...] - w[0:lastc+1,0] * v[0:lastv+1,0]ᵀ - bi.Dger(lastc+1, lastv+1, -tau, work, 1, v, incv, c, ldc) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go deleted file mode 100644 index eb43ca74..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlarfb applies a block reflector to a matrix. -// -// In the call to Dlarfb, the mxn c is multiplied by the implicitly defined matrix h as follows: -// -// c = h * c if side == Left and trans == NoTrans -// c = c * h if side == Right and trans == NoTrans -// c = hᵀ * c if side == Left and trans == Trans -// c = c * hᵀ if side == Right and trans == Trans -// -// h is a product of elementary reflectors. direct sets the direction of multiplication -// -// h = h_1 * h_2 * ... * h_k if direct == Forward -// h = h_k * h_k-1 * ... * h_1 if direct == Backward -// -// The combination of direct and store defines the orientation of the elementary -// reflectors. In all cases the ones on the diagonal are implicitly represented. -// -// If direct == lapack.Forward and store == lapack.ColumnWise -// -// V = [ 1 ] -// [v1 1 ] -// [v1 v2 1] -// [v1 v2 v3] -// [v1 v2 v3] -// -// If direct == lapack.Forward and store == lapack.RowWise -// -// V = [ 1 v1 v1 v1 v1] -// [ 1 v2 v2 v2] -// [ 1 v3 v3] -// -// If direct == lapack.Backward and store == lapack.ColumnWise -// -// V = [v1 v2 v3] -// [v1 v2 v3] -// [ 1 v2 v3] -// [ 1 v3] -// [ 1] -// -// If direct == lapack.Backward and store == lapack.RowWise -// -// V = [v1 v1 1 ] -// [v2 v2 v2 1 ] -// [v3 v3 v3 v3 1] -// -// An elementary reflector can be explicitly constructed by extracting the -// corresponding elements of v, placing a 1 where the diagonal would be, and -// placing zeros in the remaining elements. -// -// t is a k×k matrix containing the block reflector, and this function will panic -// if t is not of sufficient size. See Dlarft for more information. -// -// work is a temporary storage matrix with stride ldwork. -// work must be of size at least n×k side == Left and m×k if side == Right, and -// this function will panic if this size is not met. -// -// Dlarfb is an internal routine. It is exported for testing purposes. -func (Implementation) Dlarfb(side blas.Side, trans blas.Transpose, direct lapack.Direct, store lapack.StoreV, m, n, k int, v []float64, ldv int, t []float64, ldt int, c []float64, ldc int, work []float64, ldwork int) { - nv := m - if side == blas.Right { - nv = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case trans != blas.Trans && trans != blas.NoTrans: - panic(badTrans) - case direct != lapack.Forward && direct != lapack.Backward: - panic(badDirect) - case store != lapack.ColumnWise && store != lapack.RowWise: - panic(badStoreV) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case store == lapack.ColumnWise && ldv < max(1, k): - panic(badLdV) - case store == lapack.RowWise && ldv < max(1, nv): - panic(badLdV) - case ldt < max(1, k): - panic(badLdT) - case ldc < max(1, n): - panic(badLdC) - case ldwork < max(1, k): - panic(badLdWork) - } - - if m == 0 || n == 0 { - return - } - - nw := n - if side == blas.Right { - nw = m - } - switch { - case store == lapack.ColumnWise && len(v) < (nv-1)*ldv+k: - panic(shortV) - case store == lapack.RowWise && len(v) < (k-1)*ldv+nv: - panic(shortV) - case len(t) < (k-1)*ldt+k: - panic(shortT) - case len(c) < (m-1)*ldc+n: - panic(shortC) - case len(work) < (nw-1)*ldwork+k: - panic(shortWork) - } - - bi := blas64.Implementation() - - transt := blas.Trans - if trans == blas.Trans { - transt = blas.NoTrans - } - // TODO(btracey): This follows the original Lapack code where the - // elements are copied into the columns of the working array. The - // loops should go in the other direction so the data is written - // into the rows of work so the copy is not strided. A bigger change - // would be to replace work with workᵀ, but benchmarks would be - // needed to see if the change is merited. - if store == lapack.ColumnWise { - if direct == lapack.Forward { - // V1 is the first k rows of C. V2 is the remaining rows. - if side == blas.Left { - // W = Cᵀ V = C1ᵀ V1 + C2ᵀ V2 (stored in work). - - // W = C1. - for j := 0; j < k; j++ { - bi.Dcopy(n, c[j*ldc:], 1, work[j:], ldwork) - } - // W = W * V1. - bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, - n, k, 1, - v, ldv, - work, ldwork) - if m > k { - // W = W + C2ᵀ V2. - bi.Dgemm(blas.Trans, blas.NoTrans, n, k, m-k, - 1, c[k*ldc:], ldc, v[k*ldv:], ldv, - 1, work, ldwork) - } - // W = W * Tᵀ or W * T. - bi.Dtrmm(blas.Right, blas.Upper, transt, blas.NonUnit, n, k, - 1, t, ldt, - work, ldwork) - // C -= V * Wᵀ. - if m > k { - // C2 -= V2 * Wᵀ. - bi.Dgemm(blas.NoTrans, blas.Trans, m-k, n, k, - -1, v[k*ldv:], ldv, work, ldwork, - 1, c[k*ldc:], ldc) - } - // W *= V1ᵀ. - bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, n, k, - 1, v, ldv, - work, ldwork) - // C1 -= Wᵀ. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < n; i++ { - for j := 0; j < k; j++ { - c[j*ldc+i] -= work[i*ldwork+j] - } - } - return - } - // Form C = C * H or C * Hᵀ, where C = (C1 C2). - - // W = C1. - for i := 0; i < k; i++ { - bi.Dcopy(m, c[i:], ldc, work[i:], ldwork) - } - // W *= V1. - bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, m, k, - 1, v, ldv, - work, ldwork) - if n > k { - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, k, n-k, - 1, c[k:], ldc, v[k*ldv:], ldv, - 1, work, ldwork) - } - // W *= T or Tᵀ. - bi.Dtrmm(blas.Right, blas.Upper, trans, blas.NonUnit, m, k, - 1, t, ldt, - work, ldwork) - if n > k { - bi.Dgemm(blas.NoTrans, blas.Trans, m, n-k, k, - -1, work, ldwork, v[k*ldv:], ldv, - 1, c[k:], ldc) - } - // C -= W * Vᵀ. - bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, m, k, - 1, v, ldv, - work, ldwork) - // C -= W. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < m; i++ { - for j := 0; j < k; j++ { - c[i*ldc+j] -= work[i*ldwork+j] - } - } - return - } - // V = (V1) - // = (V2) (last k rows) - // Where V2 is unit upper triangular. - if side == blas.Left { - // Form H * C or - // W = Cᵀ V. - - // W = C2ᵀ. - for j := 0; j < k; j++ { - bi.Dcopy(n, c[(m-k+j)*ldc:], 1, work[j:], ldwork) - } - // W *= V2. - bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, n, k, - 1, v[(m-k)*ldv:], ldv, - work, ldwork) - if m > k { - // W += C1ᵀ * V1. - bi.Dgemm(blas.Trans, blas.NoTrans, n, k, m-k, - 1, c, ldc, v, ldv, - 1, work, ldwork) - } - // W *= T or Tᵀ. - bi.Dtrmm(blas.Right, blas.Lower, transt, blas.NonUnit, n, k, - 1, t, ldt, - work, ldwork) - // C -= V * Wᵀ. - if m > k { - bi.Dgemm(blas.NoTrans, blas.Trans, m-k, n, k, - -1, v, ldv, work, ldwork, - 1, c, ldc) - } - // W *= V2ᵀ. - bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, n, k, - 1, v[(m-k)*ldv:], ldv, - work, ldwork) - // C2 -= Wᵀ. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < n; i++ { - for j := 0; j < k; j++ { - c[(m-k+j)*ldc+i] -= work[i*ldwork+j] - } - } - return - } - // Form C * H or C * Hᵀ where C = (C1 C2). - // W = C * V. - - // W = C2. - for j := 0; j < k; j++ { - bi.Dcopy(m, c[n-k+j:], ldc, work[j:], ldwork) - } - - // W = W * V2. - bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, m, k, - 1, v[(n-k)*ldv:], ldv, - work, ldwork) - if n > k { - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, k, n-k, - 1, c, ldc, v, ldv, - 1, work, ldwork) - } - // W *= T or Tᵀ. - bi.Dtrmm(blas.Right, blas.Lower, trans, blas.NonUnit, m, k, - 1, t, ldt, - work, ldwork) - // C -= W * Vᵀ. - if n > k { - // C1 -= W * V1ᵀ. - bi.Dgemm(blas.NoTrans, blas.Trans, m, n-k, k, - -1, work, ldwork, v, ldv, - 1, c, ldc) - } - // W *= V2ᵀ. - bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, m, k, - 1, v[(n-k)*ldv:], ldv, - work, ldwork) - // C2 -= W. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < m; i++ { - for j := 0; j < k; j++ { - c[i*ldc+n-k+j] -= work[i*ldwork+j] - } - } - return - } - // Store = Rowwise. - if direct == lapack.Forward { - // V = (V1 V2) where v1 is unit upper triangular. - if side == blas.Left { - // Form H * C or Hᵀ * C where C = (C1; C2). - // W = Cᵀ * Vᵀ. - - // W = C1ᵀ. - for j := 0; j < k; j++ { - bi.Dcopy(n, c[j*ldc:], 1, work[j:], ldwork) - } - // W *= V1ᵀ. - bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, n, k, - 1, v, ldv, - work, ldwork) - if m > k { - bi.Dgemm(blas.Trans, blas.Trans, n, k, m-k, - 1, c[k*ldc:], ldc, v[k:], ldv, - 1, work, ldwork) - } - // W *= T or Tᵀ. - bi.Dtrmm(blas.Right, blas.Upper, transt, blas.NonUnit, n, k, - 1, t, ldt, - work, ldwork) - // C -= Vᵀ * Wᵀ. - if m > k { - bi.Dgemm(blas.Trans, blas.Trans, m-k, n, k, - -1, v[k:], ldv, work, ldwork, - 1, c[k*ldc:], ldc) - } - // W *= V1. - bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, n, k, - 1, v, ldv, - work, ldwork) - // C1 -= Wᵀ. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < n; i++ { - for j := 0; j < k; j++ { - c[j*ldc+i] -= work[i*ldwork+j] - } - } - return - } - // Form C * H or C * Hᵀ where C = (C1 C2). - // W = C * Vᵀ. - - // W = C1. - for j := 0; j < k; j++ { - bi.Dcopy(m, c[j:], ldc, work[j:], ldwork) - } - // W *= V1ᵀ. - bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, m, k, - 1, v, ldv, - work, ldwork) - if n > k { - bi.Dgemm(blas.NoTrans, blas.Trans, m, k, n-k, - 1, c[k:], ldc, v[k:], ldv, - 1, work, ldwork) - } - // W *= T or Tᵀ. - bi.Dtrmm(blas.Right, blas.Upper, trans, blas.NonUnit, m, k, - 1, t, ldt, - work, ldwork) - // C -= W * V. - if n > k { - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n-k, k, - -1, work, ldwork, v[k:], ldv, - 1, c[k:], ldc) - } - // W *= V1. - bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, m, k, - 1, v, ldv, - work, ldwork) - // C1 -= W. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < m; i++ { - for j := 0; j < k; j++ { - c[i*ldc+j] -= work[i*ldwork+j] - } - } - return - } - // V = (V1 V2) where V2 is the last k columns and is lower unit triangular. - if side == blas.Left { - // Form H * C or Hᵀ C where C = (C1 ; C2). - // W = Cᵀ * Vᵀ. - - // W = C2ᵀ. - for j := 0; j < k; j++ { - bi.Dcopy(n, c[(m-k+j)*ldc:], 1, work[j:], ldwork) - } - // W *= V2ᵀ. - bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, n, k, - 1, v[m-k:], ldv, - work, ldwork) - if m > k { - bi.Dgemm(blas.Trans, blas.Trans, n, k, m-k, - 1, c, ldc, v, ldv, - 1, work, ldwork) - } - // W *= T or Tᵀ. - bi.Dtrmm(blas.Right, blas.Lower, transt, blas.NonUnit, n, k, - 1, t, ldt, - work, ldwork) - // C -= Vᵀ * Wᵀ. - if m > k { - bi.Dgemm(blas.Trans, blas.Trans, m-k, n, k, - -1, v, ldv, work, ldwork, - 1, c, ldc) - } - // W *= V2. - bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, k, - 1, v[m-k:], ldv, - work, ldwork) - // C2 -= Wᵀ. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < n; i++ { - for j := 0; j < k; j++ { - c[(m-k+j)*ldc+i] -= work[i*ldwork+j] - } - } - return - } - // Form C * H or C * Hᵀ where C = (C1 C2). - // W = C * Vᵀ. - // W = C2. - for j := 0; j < k; j++ { - bi.Dcopy(m, c[n-k+j:], ldc, work[j:], ldwork) - } - // W *= V2ᵀ. - bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, m, k, - 1, v[n-k:], ldv, - work, ldwork) - if n > k { - bi.Dgemm(blas.NoTrans, blas.Trans, m, k, n-k, - 1, c, ldc, v, ldv, - 1, work, ldwork) - } - // W *= T or Tᵀ. - bi.Dtrmm(blas.Right, blas.Lower, trans, blas.NonUnit, m, k, - 1, t, ldt, - work, ldwork) - // C -= W * V. - if n > k { - bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n-k, k, - -1, work, ldwork, v, ldv, - 1, c, ldc) - } - // W *= V2. - bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, m, k, - 1, v[n-k:], ldv, - work, ldwork) - // C1 -= W. - // TODO(btracey): This should use blas.Axpy. - for i := 0; i < m; i++ { - for j := 0; j < k; j++ { - c[i*ldc+n-k+j] -= work[i*ldwork+j] - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go deleted file mode 100644 index 74ad111d..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlarfg generates an elementary reflector for a Householder matrix. It creates -// a real elementary reflector of order n such that -// -// H * (alpha) = (beta) -// ( x) ( 0) -// Hᵀ * H = I -// -// H is represented in the form -// -// H = 1 - tau * (1; v) * (1 vᵀ) -// -// where tau is a real scalar. -// -// On entry, x contains the vector x, on exit it contains v. -// -// Dlarfg is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlarfg(n int, alpha float64, x []float64, incX int) (beta, tau float64) { - switch { - case n < 0: - panic(nLT0) - case incX <= 0: - panic(badIncX) - } - - if n <= 1 { - return alpha, 0 - } - - if len(x) < 1+(n-2)*abs(incX) { - panic(shortX) - } - - bi := blas64.Implementation() - - xnorm := bi.Dnrm2(n-1, x, incX) - if xnorm == 0 { - return alpha, 0 - } - beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) - safmin := dlamchS / dlamchE - knt := 0 - if math.Abs(beta) < safmin { - // xnorm and beta may be inaccurate, scale x and recompute. - rsafmn := 1 / safmin - for { - knt++ - bi.Dscal(n-1, rsafmn, x, incX) - beta *= rsafmn - alpha *= rsafmn - if math.Abs(beta) >= safmin { - break - } - } - xnorm = bi.Dnrm2(n-1, x, incX) - beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) - } - tau = (beta - alpha) / beta - bi.Dscal(n-1, 1/(alpha-beta), x, incX) - for j := 0; j < knt; j++ { - beta *= safmin - } - return beta, tau -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go deleted file mode 100644 index 921a5a3d..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlarft forms the triangular factor T of a block reflector H, storing the answer -// in t. -// -// H = I - V * T * Vᵀ if store == lapack.ColumnWise -// H = I - Vᵀ * T * V if store == lapack.RowWise -// -// H is defined by a product of the elementary reflectors where -// -// H = H_0 * H_1 * ... * H_{k-1} if direct == lapack.Forward -// H = H_{k-1} * ... * H_1 * H_0 if direct == lapack.Backward -// -// t is a k×k triangular matrix. t is upper triangular if direct = lapack.Forward -// and lower triangular otherwise. This function will panic if t is not of -// sufficient size. -// -// store describes the storage of the elementary reflectors in v. See -// Dlarfb for a description of layout. -// -// tau contains the scalar factors of the elementary reflectors H_i. -// -// Dlarft is an internal routine. It is exported for testing purposes. -func (Implementation) Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int, v []float64, ldv int, tau []float64, t []float64, ldt int) { - mv, nv := n, k - if store == lapack.RowWise { - mv, nv = k, n - } - switch { - case direct != lapack.Forward && direct != lapack.Backward: - panic(badDirect) - case store != lapack.RowWise && store != lapack.ColumnWise: - panic(badStoreV) - case n < 0: - panic(nLT0) - case k < 1: - panic(kLT1) - case ldv < max(1, nv): - panic(badLdV) - case len(tau) < k: - panic(shortTau) - case ldt < max(1, k): - panic(shortT) - } - - if n == 0 { - return - } - - switch { - case len(v) < (mv-1)*ldv+nv: - panic(shortV) - case len(t) < (k-1)*ldt+k: - panic(shortT) - } - - bi := blas64.Implementation() - - // TODO(btracey): There are a number of minor obvious loop optimizations here. - // TODO(btracey): It may be possible to rearrange some of the code so that - // index of 1 is more common in the Dgemv. - if direct == lapack.Forward { - prevlastv := n - 1 - for i := 0; i < k; i++ { - prevlastv = max(i, prevlastv) - if tau[i] == 0 { - for j := 0; j <= i; j++ { - t[j*ldt+i] = 0 - } - continue - } - var lastv int - if store == lapack.ColumnWise { - // skip trailing zeros - for lastv = n - 1; lastv >= i+1; lastv-- { - if v[lastv*ldv+i] != 0 { - break - } - } - for j := 0; j < i; j++ { - t[j*ldt+i] = -tau[i] * v[i*ldv+j] - } - j := min(lastv, prevlastv) - bi.Dgemv(blas.Trans, j-i, i, - -tau[i], v[(i+1)*ldv:], ldv, v[(i+1)*ldv+i:], ldv, - 1, t[i:], ldt) - } else { - for lastv = n - 1; lastv >= i+1; lastv-- { - if v[i*ldv+lastv] != 0 { - break - } - } - for j := 0; j < i; j++ { - t[j*ldt+i] = -tau[i] * v[j*ldv+i] - } - j := min(lastv, prevlastv) - bi.Dgemv(blas.NoTrans, i, j-i, - -tau[i], v[i+1:], ldv, v[i*ldv+i+1:], 1, - 1, t[i:], ldt) - } - bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, t, ldt, t[i:], ldt) - t[i*ldt+i] = tau[i] - if i > 1 { - prevlastv = max(prevlastv, lastv) - } else { - prevlastv = lastv - } - } - return - } - prevlastv := 0 - for i := k - 1; i >= 0; i-- { - if tau[i] == 0 { - for j := i; j < k; j++ { - t[j*ldt+i] = 0 - } - continue - } - var lastv int - if i < k-1 { - if store == lapack.ColumnWise { - for lastv = 0; lastv < i; lastv++ { - if v[lastv*ldv+i] != 0 { - break - } - } - for j := i + 1; j < k; j++ { - t[j*ldt+i] = -tau[i] * v[(n-k+i)*ldv+j] - } - j := max(lastv, prevlastv) - bi.Dgemv(blas.Trans, n-k+i-j, k-i-1, - -tau[i], v[j*ldv+i+1:], ldv, v[j*ldv+i:], ldv, - 1, t[(i+1)*ldt+i:], ldt) - } else { - for lastv = 0; lastv < i; lastv++ { - if v[i*ldv+lastv] != 0 { - break - } - } - for j := i + 1; j < k; j++ { - t[j*ldt+i] = -tau[i] * v[j*ldv+n-k+i] - } - j := max(lastv, prevlastv) - bi.Dgemv(blas.NoTrans, k-i-1, n-k+i-j, - -tau[i], v[(i+1)*ldv+j:], ldv, v[i*ldv+j:], 1, - 1, t[(i+1)*ldt+i:], ldt) - } - bi.Dtrmv(blas.Lower, blas.NoTrans, blas.NonUnit, k-i-1, - t[(i+1)*ldt+i+1:], ldt, - t[(i+1)*ldt+i:], ldt) - if i > 0 { - prevlastv = min(prevlastv, lastv) - } else { - prevlastv = lastv - } - } - t[i*ldt+i] = tau[i] - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go deleted file mode 100644 index 4e40dad1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go +++ /dev/null @@ -1,552 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dlarfx applies an elementary reflector H to a real m×n matrix C, from either -// the left or the right, with loop unrolling when the reflector has order less -// than 11. -// -// H is represented in the form -// -// H = I - tau * v * vᵀ, -// -// where tau is a real scalar and v is a real vector. If tau = 0, then H is -// taken to be the identity matrix. -// -// v must have length equal to m if side == blas.Left, and equal to n if side == -// blas.Right, otherwise Dlarfx will panic. -// -// c and ldc represent the m×n matrix C. On return, C is overwritten by the -// matrix H * C if side == blas.Left, or C * H if side == blas.Right. -// -// work must have length at least n if side == blas.Left, and at least m if side -// == blas.Right, otherwise Dlarfx will panic. work is not referenced if H has -// order < 11. -// -// Dlarfx is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) { - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - nh := m - lwork := n - if side == blas.Right { - nh = n - lwork = m - } - switch { - case len(v) < nh: - panic(shortV) - case len(c) < (m-1)*ldc+n: - panic(shortC) - case nh > 10 && len(work) < lwork: - panic(shortWork) - } - - if tau == 0 { - return - } - - if side == blas.Left { - // Form H * C, where H has order m. - switch m { - default: // Code for general m. - impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work) - return - - case 0: // No-op for zero size matrix. - return - - case 1: // Special code for 1×1 Householder matrix. - t0 := 1 - tau*v[0]*v[0] - for j := 0; j < n; j++ { - c[j] *= t0 - } - return - - case 2: // Special code for 2×2 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - } - return - - case 3: // Special code for 3×3 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - } - return - - case 4: // Special code for 4×4 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - c[3*ldc+j] -= sum * t3 - } - return - - case 5: // Special code for 5×5 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - c[3*ldc+j] -= sum * t3 - c[4*ldc+j] -= sum * t4 - } - return - - case 6: // Special code for 6×6 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + - v5*c[5*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - c[3*ldc+j] -= sum * t3 - c[4*ldc+j] -= sum * t4 - c[5*ldc+j] -= sum * t5 - } - return - - case 7: // Special code for 7×7 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + - v5*c[5*ldc+j] + v6*c[6*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - c[3*ldc+j] -= sum * t3 - c[4*ldc+j] -= sum * t4 - c[5*ldc+j] -= sum * t5 - c[6*ldc+j] -= sum * t6 - } - return - - case 8: // Special code for 8×8 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - v7 := v[7] - t7 := tau * v7 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + - v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - c[3*ldc+j] -= sum * t3 - c[4*ldc+j] -= sum * t4 - c[5*ldc+j] -= sum * t5 - c[6*ldc+j] -= sum * t6 - c[7*ldc+j] -= sum * t7 - } - return - - case 9: // Special code for 9×9 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - v7 := v[7] - t7 := tau * v7 - v8 := v[8] - t8 := tau * v8 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + - v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - c[3*ldc+j] -= sum * t3 - c[4*ldc+j] -= sum * t4 - c[5*ldc+j] -= sum * t5 - c[6*ldc+j] -= sum * t6 - c[7*ldc+j] -= sum * t7 - c[8*ldc+j] -= sum * t8 - } - return - - case 10: // Special code for 10×10 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - v7 := v[7] - t7 := tau * v7 - v8 := v[8] - t8 := tau * v8 - v9 := v[9] - t9 := tau * v9 - for j := 0; j < n; j++ { - sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + - v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j] + v9*c[9*ldc+j] - c[j] -= sum * t0 - c[ldc+j] -= sum * t1 - c[2*ldc+j] -= sum * t2 - c[3*ldc+j] -= sum * t3 - c[4*ldc+j] -= sum * t4 - c[5*ldc+j] -= sum * t5 - c[6*ldc+j] -= sum * t6 - c[7*ldc+j] -= sum * t7 - c[8*ldc+j] -= sum * t8 - c[9*ldc+j] -= sum * t9 - } - return - } - } - - // Form C * H, where H has order n. - switch n { - default: // Code for general n. - impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work) - return - - case 0: // No-op for zero size matrix. - return - - case 1: // Special code for 1×1 Householder matrix. - t0 := 1 - tau*v[0]*v[0] - for j := 0; j < m; j++ { - c[j*ldc] *= t0 - } - return - - case 2: // Special code for 2×2 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - } - return - - case 3: // Special code for 3×3 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - } - return - - case 4: // Special code for 4×4 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - cs[3] -= sum * t3 - } - return - - case 5: // Special code for 5×5 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - cs[3] -= sum * t3 - cs[4] -= sum * t4 - } - return - - case 6: // Special code for 6×6 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + v5*cs[5] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - cs[3] -= sum * t3 - cs[4] -= sum * t4 - cs[5] -= sum * t5 - } - return - - case 7: // Special code for 7×7 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + - v5*cs[5] + v6*cs[6] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - cs[3] -= sum * t3 - cs[4] -= sum * t4 - cs[5] -= sum * t5 - cs[6] -= sum * t6 - } - return - - case 8: // Special code for 8×8 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - v7 := v[7] - t7 := tau * v7 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + - v5*cs[5] + v6*cs[6] + v7*cs[7] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - cs[3] -= sum * t3 - cs[4] -= sum * t4 - cs[5] -= sum * t5 - cs[6] -= sum * t6 - cs[7] -= sum * t7 - } - return - - case 9: // Special code for 9×9 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - v7 := v[7] - t7 := tau * v7 - v8 := v[8] - t8 := tau * v8 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + - v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - cs[3] -= sum * t3 - cs[4] -= sum * t4 - cs[5] -= sum * t5 - cs[6] -= sum * t6 - cs[7] -= sum * t7 - cs[8] -= sum * t8 - } - return - - case 10: // Special code for 10×10 Householder matrix. - v0 := v[0] - t0 := tau * v0 - v1 := v[1] - t1 := tau * v1 - v2 := v[2] - t2 := tau * v2 - v3 := v[3] - t3 := tau * v3 - v4 := v[4] - t4 := tau * v4 - v5 := v[5] - t5 := tau * v5 - v6 := v[6] - t6 := tau * v6 - v7 := v[7] - t7 := tau * v7 - v8 := v[8] - t8 := tau * v8 - v9 := v[9] - t9 := tau * v9 - for j := 0; j < m; j++ { - cs := c[j*ldc:] - sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + - v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8] + v9*cs[9] - cs[0] -= sum * t0 - cs[1] -= sum * t1 - cs[2] -= sum * t2 - cs[3] -= sum * t3 - cs[4] -= sum * t4 - cs[5] -= sum * t5 - cs[6] -= sum * t6 - cs[7] -= sum * t7 - cs[8] -= sum * t8 - cs[9] -= sum * t9 - } - return - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go deleted file mode 100644 index 93416c6f..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlartg.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlartg generates a plane rotation so that -// -// [ cs sn] * [f] = [r] -// [-sn cs] [g] = [0] -// -// where cs*cs + sn*sn = 1. -// -// This is a more accurate version of BLAS Drotg that uses scaling to avoid -// overflow or underflow, with the other differences that -// - cs >= 0 -// - if g = 0, then cs = 1 and sn = 0 -// - if f = 0 and g != 0, then cs = 0 and sn = sign(1,g) -// -// Dlartg is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlartg(f, g float64) (cs, sn, r float64) { - // Implementation based on Supplemental Material to: - // - // Edward Anderson - // Algorithm 978: Safe Scaling in the Level 1 BLAS - // ACM Trans. Math. Softw. 44, 1, Article 12 (2017) - // DOI: https://doi.org/10.1145/3061665 - // - // For further details see: - // - // W. Pereira, A. Lotfi, J. Langou - // Numerical analysis of Givens rotation - // DOI: https://doi.org/10.48550/arXiv.2211.04010 - - if g == 0 { - return 1, 0, f - } - - g1 := math.Abs(g) - - if f == 0 { - return 0, math.Copysign(1, g), g1 - } - - const safmin = dlamchS - const safmax = 1 / safmin - rtmin := math.Sqrt(safmin) - rtmax := math.Sqrt(safmax / 2) - - f1 := math.Abs(f) - - if rtmin < f1 && f1 < rtmax && rtmin < g1 && g1 < rtmax { - d := math.Sqrt(f*f + g*g) - cs = f1 / d - r = math.Copysign(d, f) - sn = g / r - - return cs, sn, r - } - - u := math.Min(math.Max(safmin, math.Max(f1, g1)), safmax) - fs := f / u - gs := g / u - d := math.Sqrt(fs*fs + gs*gs) - cs = math.Abs(fs) / d - r = math.Copysign(d, f) - sn = gs / r - r *= u - - return cs, sn, r -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go deleted file mode 100644 index a819fa35..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlas2.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlas2 computes the singular values of the 2×2 matrix defined by -// -// [F G] -// [0 H] -// -// The smaller and larger singular values are returned in that order. -// -// Dlas2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlas2(f, g, h float64) (ssmin, ssmax float64) { - fa := math.Abs(f) - ga := math.Abs(g) - ha := math.Abs(h) - fhmin := math.Min(fa, ha) - fhmax := math.Max(fa, ha) - if fhmin == 0 { - if fhmax == 0 { - return 0, ga - } - v := math.Min(fhmax, ga) / math.Max(fhmax, ga) - return 0, math.Max(fhmax, ga) * math.Sqrt(1+v*v) - } - if ga < fhmax { - as := 1 + fhmin/fhmax - at := (fhmax - fhmin) / fhmax - au := (ga / fhmax) * (ga / fhmax) - c := 2 / (math.Sqrt(as*as+au) + math.Sqrt(at*at+au)) - return fhmin * c, fhmax / c - } - au := fhmax / ga - if au == 0 { - return fhmin * fhmax / ga, ga - } - as := 1 + fhmin/fhmax - at := (fhmax - fhmin) / fhmax - c := 1 / (math.Sqrt(1+(as*au)*(as*au)) + math.Sqrt(1+(at*au)*(at*au))) - return 2 * (fhmin * c) * au, ga / (c + c) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go deleted file mode 100644 index 61c4eb79..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/lapack" -) - -// Dlascl multiplies an m×n matrix by the scalar cto/cfrom. -// -// cfrom must not be zero, and cto and cfrom must not be NaN, otherwise Dlascl -// will panic. -// -// Dlascl is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) { - switch kind { - default: - panic(badMatrixType) - case 'H', 'B', 'Q', 'Z': // See dlascl.f. - panic("not implemented") - case lapack.General, lapack.UpperTri, lapack.LowerTri: - if lda < max(1, n) { - panic(badLdA) - } - } - switch { - case cfrom == 0: - panic(zeroCFrom) - case math.IsNaN(cfrom): - panic(nanCFrom) - case math.IsNaN(cto): - panic(nanCTo) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - } - - if n == 0 || m == 0 { - return - } - - switch kind { - case lapack.General, lapack.UpperTri, lapack.LowerTri: - if len(a) < (m-1)*lda+n { - panic(shortA) - } - } - - smlnum := dlamchS - bignum := 1 / smlnum - cfromc := cfrom - ctoc := cto - cfrom1 := cfromc * smlnum - for { - var done bool - var mul, ctol float64 - if cfrom1 == cfromc { - // cfromc is inf. - mul = ctoc / cfromc - done = true - ctol = ctoc - } else { - ctol = ctoc / bignum - if ctol == ctoc { - // ctoc is either 0 or inf. - mul = ctoc - done = true - cfromc = 1 - } else if math.Abs(cfrom1) > math.Abs(ctoc) && ctoc != 0 { - mul = smlnum - done = false - cfromc = cfrom1 - } else if math.Abs(ctol) > math.Abs(cfromc) { - mul = bignum - done = false - ctoc = ctol - } else { - mul = ctoc / cfromc - done = true - } - } - switch kind { - case lapack.General: - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - a[i*lda+j] = a[i*lda+j] * mul - } - } - case lapack.UpperTri: - for i := 0; i < m; i++ { - for j := i; j < n; j++ { - a[i*lda+j] = a[i*lda+j] * mul - } - } - case lapack.LowerTri: - for i := 0; i < m; i++ { - for j := 0; j <= min(i, n-1); j++ { - a[i*lda+j] = a[i*lda+j] * mul - } - } - } - if done { - break - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go deleted file mode 100644 index b8b6b0f4..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dlaset sets the off-diagonal elements of A to alpha, and the diagonal -// elements to beta. If uplo == blas.Upper, only the elements in the upper -// triangular part are set. If uplo == blas.Lower, only the elements in the -// lower triangular part are set. If uplo is otherwise, all of the elements of A -// are set. -// -// Dlaset is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - minmn := min(m, n) - if minmn == 0 { - return - } - - if len(a) < (m-1)*lda+n { - panic(shortA) - } - - switch uplo { - case blas.Upper: - for i := 0; i < m; i++ { - for j := i + 1; j < n; j++ { - a[i*lda+j] = alpha - } - } - case blas.Lower: - for i := 0; i < m; i++ { - for j := 0; j < min(i, n); j++ { - a[i*lda+j] = alpha - } - } - default: - for i := 0; i < m; i++ { - for j := 0; j < n; j++ { - a[i*lda+j] = alpha - } - } - } - for i := 0; i < minmn; i++ { - a[i*lda+i] = beta - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go deleted file mode 100644 index 1f1d1dc4..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlasq1 computes the singular values of an n×n bidiagonal matrix with diagonal -// d and off-diagonal e. On exit, d contains the singular values in decreasing -// order, and e is overwritten. d must have length at least n, e must have -// length at least n-1, and the input work must have length at least 4*n. Dlasq1 -// will panic if these conditions are not met. -// -// Dlasq1 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasq1(n int, d, e, work []float64) (info int) { - if n < 0 { - panic(nLT0) - } - - if n == 0 { - return info - } - - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - case len(work) < 4*n: - panic(shortWork) - } - - if n == 1 { - d[0] = math.Abs(d[0]) - return info - } - - if n == 2 { - d[1], d[0] = impl.Dlas2(d[0], e[0], d[1]) - return info - } - - // Estimate the largest singular value. - var sigmx float64 - for i := 0; i < n-1; i++ { - d[i] = math.Abs(d[i]) - sigmx = math.Max(sigmx, math.Abs(e[i])) - } - d[n-1] = math.Abs(d[n-1]) - // Early return if sigmx is zero (matrix is already diagonal). - if sigmx == 0 { - impl.Dlasrt(lapack.SortDecreasing, n, d) - return info - } - - for i := 0; i < n; i++ { - sigmx = math.Max(sigmx, d[i]) - } - - // Copy D and E into WORK (in the Z format) and scale (squaring the - // input data makes scaling by a power of the radix pointless). - - eps := dlamchP - safmin := dlamchS - scale := math.Sqrt(eps / safmin) - bi := blas64.Implementation() - bi.Dcopy(n, d, 1, work, 2) - bi.Dcopy(n-1, e, 1, work[1:], 2) - impl.Dlascl(lapack.General, 0, 0, sigmx, scale, 2*n-1, 1, work, 1) - - // Compute the q's and e's. - for i := 0; i < 2*n-1; i++ { - work[i] *= work[i] - } - work[2*n-1] = 0 - - info = impl.Dlasq2(n, work) - if info == 0 { - for i := 0; i < n; i++ { - d[i] = math.Sqrt(work[i]) - } - impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) - } else if info == 2 { - // Maximum number of iterations exceeded. Move data from work - // into D and E so the calling subroutine can try to finish. - for i := 0; i < n; i++ { - d[i] = math.Sqrt(work[2*i]) - e[i] = math.Sqrt(work[2*i+1]) - } - impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) - impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, e, 1) - } - return info -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go deleted file mode 100644 index e3870b1d..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/lapack" -) - -// Dlasq2 computes all the eigenvalues of the symmetric positive -// definite tridiagonal matrix associated with the qd array Z. Eigevalues -// are computed to high relative accuracy avoiding denormalization, underflow -// and overflow. -// -// To see the relation of Z to the tridiagonal matrix, let L be a -// unit lower bidiagonal matrix with sub-diagonals Z(2,4,6,,..) and -// let U be an upper bidiagonal matrix with 1's above and diagonal -// Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the -// symmetric tridiagonal to which it is similar. -// -// info returns a status error. The return codes mean as follows: -// -// 0: The algorithm completed successfully. -// 1: A split was marked by a positive value in e. -// 2: Current block of Z not diagonalized after 100*n iterations (in inner -// while loop). On exit Z holds a qd array with the same eigenvalues as -// the given Z. -// 3: Termination criterion of outer while loop not met (program created more -// than N unreduced blocks). -// -// z must have length at least 4*n, and must not contain any negative elements. -// Dlasq2 will panic otherwise. -// -// Dlasq2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasq2(n int, z []float64) (info int) { - if n < 0 { - panic(nLT0) - } - - if n == 0 { - return info - } - - if len(z) < 4*n { - panic(shortZ) - } - - if n == 1 { - if z[0] < 0 { - panic(negZ) - } - return info - } - - const cbias = 1.5 - - eps := dlamchP - safmin := dlamchS - tol := eps * 100 - tol2 := tol * tol - if n == 2 { - if z[1] < 0 || z[2] < 0 { - panic(negZ) - } else if z[2] > z[0] { - z[0], z[2] = z[2], z[0] - } - z[4] = z[0] + z[1] + z[2] - if z[1] > z[2]*tol2 { - t := 0.5 * (z[0] - z[2] + z[1]) - s := z[2] * (z[1] / t) - if s <= t { - s = z[2] * (z[1] / (t * (1 + math.Sqrt(1+s/t)))) - } else { - s = z[2] * (z[1] / (t + math.Sqrt(t)*math.Sqrt(t+s))) - } - t = z[0] + s + z[1] - z[2] *= z[0] / t - z[0] = t - } - z[1] = z[2] - z[5] = z[1] + z[0] - return info - } - // Check for negative data and compute sums of q's and e's. - z[2*n-1] = 0 - emin := z[1] - var d, e, qmax float64 - var i1, n1 int - for k := 0; k < 2*(n-1); k += 2 { - if z[k] < 0 || z[k+1] < 0 { - panic(negZ) - } - d += z[k] - e += z[k+1] - qmax = math.Max(qmax, z[k]) - emin = math.Min(emin, z[k+1]) - } - if z[2*(n-1)] < 0 { - panic(negZ) - } - d += z[2*(n-1)] - // Check for diagonality. - if e == 0 { - for k := 1; k < n; k++ { - z[k] = z[2*k] - } - impl.Dlasrt(lapack.SortDecreasing, n, z) - z[2*(n-1)] = d - return info - } - trace := d + e - // Check for zero data. - if trace == 0 { - z[2*(n-1)] = 0 - return info - } - // Rearrange data for locality: Z=(q1,qq1,e1,ee1,q2,qq2,e2,ee2,...). - for k := 2 * n; k >= 2; k -= 2 { - z[2*k-1] = 0 - z[2*k-2] = z[k-1] - z[2*k-3] = 0 - z[2*k-4] = z[k-2] - } - i0 := 0 - n0 := n - 1 - - // Reverse the qd-array, if warranted. - // z[4*i0-3] --> z[4*(i0+1)-3-1] --> z[4*i0] - if cbias*z[4*i0] < z[4*n0] { - ipn4Out := 4 * (i0 + n0 + 2) - for i4loop := 4 * (i0 + 1); i4loop <= 2*(i0+n0+1); i4loop += 4 { - i4 := i4loop - 1 - ipn4 := ipn4Out - 1 - z[i4-3], z[ipn4-i4-4] = z[ipn4-i4-4], z[i4-3] - z[i4-1], z[ipn4-i4-6] = z[ipn4-i4-6], z[i4-1] - } - } - - // Initial split checking via dqd and Li's test. - pp := 0 - for k := 0; k < 2; k++ { - d = z[4*n0+pp] - for i4loop := 4*n0 + pp; i4loop >= 4*(i0+1)+pp; i4loop -= 4 { - i4 := i4loop - 1 - if z[i4-1] <= tol2*d { - z[i4-1] = math.Copysign(0, -1) - d = z[i4-3] - } else { - d = z[i4-3] * (d / (d + z[i4-1])) - } - } - // dqd maps Z to ZZ plus Li's test. - emin = z[4*(i0+1)+pp] - d = z[4*i0+pp] - for i4loop := 4*(i0+1) + pp; i4loop <= 4*n0+pp; i4loop += 4 { - i4 := i4loop - 1 - z[i4-2*pp-2] = d + z[i4-1] - if z[i4-1] <= tol2*d { - z[i4-1] = math.Copysign(0, -1) - z[i4-2*pp-2] = d - z[i4-2*pp] = 0 - d = z[i4+1] - } else if safmin*z[i4+1] < z[i4-2*pp-2] && safmin*z[i4-2*pp-2] < z[i4+1] { - tmp := z[i4+1] / z[i4-2*pp-2] - z[i4-2*pp] = z[i4-1] * tmp - d *= tmp - } else { - z[i4-2*pp] = z[i4+1] * (z[i4-1] / z[i4-2*pp-2]) - d = z[i4+1] * (d / z[i4-2*pp-2]) - } - emin = math.Min(emin, z[i4-2*pp]) - } - z[4*(n0+1)-pp-3] = d - - // Now find qmax. - qmax = z[4*(i0+1)-pp-3] - for i4loop := 4*(i0+1) - pp + 2; i4loop <= 4*(n0+1)+pp-2; i4loop += 4 { - i4 := i4loop - 1 - qmax = math.Max(qmax, z[i4]) - } - // Prepare for the next iteration on K. - pp = 1 - pp - } - - // Initialise variables to pass to DLASQ3. - var ttype int - var dmin1, dmin2, dn, dn1, dn2, g, tau float64 - var tempq float64 - iter := 2 - var nFail int - nDiv := 2 * (n0 - i0) - var i4 int -outer: - for iwhila := 1; iwhila <= n+1; iwhila++ { - // Test for completion. - if n0 < 0 { - // Move q's to the front. - for k := 1; k < n; k++ { - z[k] = z[4*k] - } - // Sort and compute sum of eigenvalues. - impl.Dlasrt(lapack.SortDecreasing, n, z) - e = 0 - for k := n - 1; k >= 0; k-- { - e += z[k] - } - // Store trace, sum(eigenvalues) and information on performance. - z[2*n] = trace - z[2*n+1] = e - z[2*n+2] = float64(iter) - z[2*n+3] = float64(nDiv) / float64(n*n) - z[2*n+4] = 100 * float64(nFail) / float64(iter) - return info - } - - // While array unfinished do - // e[n0] holds the value of sigma when submatrix in i0:n0 - // splits from the rest of the array, but is negated. - var desig float64 - var sigma float64 - if n0 != n-1 { - sigma = -z[4*(n0+1)-2] - } - if sigma < 0 { - info = 1 - return info - } - // Find last unreduced submatrix's top index i0, find qmax and - // emin. Find Gershgorin-type bound if Q's much greater than E's. - var emax float64 - if n0 > i0 { - emin = math.Abs(z[4*(n0+1)-6]) - } else { - emin = 0 - } - qmin := z[4*(n0+1)-4] - qmax = qmin - zSmall := false - for i4loop := 4 * (n0 + 1); i4loop >= 8; i4loop -= 4 { - i4 = i4loop - 1 - if z[i4-5] <= 0 { - zSmall = true - break - } - if qmin >= 4*emax { - qmin = math.Min(qmin, z[i4-3]) - emax = math.Max(emax, z[i4-5]) - } - qmax = math.Max(qmax, z[i4-7]+z[i4-5]) - emin = math.Min(emin, z[i4-5]) - } - if !zSmall { - i4 = 3 - } - i0 = (i4+1)/4 - 1 - pp = 0 - if n0-i0 > 1 { - dee := z[4*i0] - deemin := dee - kmin := i0 - for i4loop := 4*(i0+1) + 1; i4loop <= 4*(n0+1)-3; i4loop += 4 { - i4 := i4loop - 1 - dee = z[i4] * (dee / (dee + z[i4-2])) - if dee <= deemin { - deemin = dee - kmin = (i4+4)/4 - 1 - } - } - if (kmin-i0)*2 < n0-kmin && deemin <= 0.5*z[4*n0] { - ipn4Out := 4 * (i0 + n0 + 2) - pp = 2 - for i4loop := 4 * (i0 + 1); i4loop <= 2*(i0+n0+1); i4loop += 4 { - i4 := i4loop - 1 - ipn4 := ipn4Out - 1 - z[i4-3], z[ipn4-i4-4] = z[ipn4-i4-4], z[i4-3] - z[i4-2], z[ipn4-i4-3] = z[ipn4-i4-3], z[i4-2] - z[i4-1], z[ipn4-i4-6] = z[ipn4-i4-6], z[i4-1] - z[i4], z[ipn4-i4-5] = z[ipn4-i4-5], z[i4] - } - } - } - // Put -(initial shift) into DMIN. - dmin := -math.Max(0, qmin-2*math.Sqrt(qmin)*math.Sqrt(emax)) - - // Now i0:n0 is unreduced. - // PP = 0 for ping, PP = 1 for pong. - // PP = 2 indicates that flipping was applied to the Z array and - // that the tests for deflation upon entry in Dlasq3 should - // not be performed. - nbig := 100 * (n0 - i0 + 1) - for iwhilb := 0; iwhilb < nbig; iwhilb++ { - if i0 > n0 { - continue outer - } - - // While submatrix unfinished take a good dqds step. - i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau = - impl.Dlasq3(i0, n0, z, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau) - - pp = 1 - pp - // When emin is very small check for splits. - if pp == 0 && n0-i0 >= 3 { - if z[4*(n0+1)-1] <= tol2*qmax || z[4*(n0+1)-2] <= tol2*sigma { - splt := i0 - 1 - qmax = z[4*i0] - emin = z[4*(i0+1)-2] - oldemn := z[4*(i0+1)-1] - for i4loop := 4 * (i0 + 1); i4loop <= 4*(n0-2); i4loop += 4 { - i4 := i4loop - 1 - if z[i4] <= tol2*z[i4-3] || z[i4-1] <= tol2*sigma { - z[i4-1] = -sigma - splt = i4 / 4 - qmax = 0 - emin = z[i4+3] - oldemn = z[i4+4] - } else { - qmax = math.Max(qmax, z[i4+1]) - emin = math.Min(emin, z[i4-1]) - oldemn = math.Min(oldemn, z[i4]) - } - } - z[4*(n0+1)-2] = emin - z[4*(n0+1)-1] = oldemn - i0 = splt + 1 - } - } - } - // Maximum number of iterations exceeded, restore the shift - // sigma and place the new d's and e's in a qd array. - // This might need to be done for several blocks. - info = 2 - i1 = i0 - for { - tempq = z[4*i0] - z[4*i0] += sigma - for k := i0 + 1; k <= n0; k++ { - tempe := z[4*(k+1)-6] - z[4*(k+1)-6] *= tempq / z[4*(k+1)-8] - tempq = z[4*k] - z[4*k] += sigma + tempe - z[4*(k+1)-6] - } - // Prepare to do this on the previous block if there is one. - if i1 <= 0 { - break - } - n1 = i1 - 1 - for i1 >= 1 && z[4*(i1+1)-6] >= 0 { - i1 -= 1 - } - sigma = -z[4*(n1+1)-2] - } - for k := 0; k < n; k++ { - z[2*k] = z[4*k] - // Only the block 1..N0 is unfinished. The rest of the e's - // must be essentially zero, although sometimes other data - // has been stored in them. - if k < n0 { - z[2*(k+1)-1] = z[4*(k+1)-1] - } else { - z[2*(k+1)] = 0 - } - } - return info - } - info = 3 - return info -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go deleted file mode 100644 index a05e94ef..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlasq3 checks for deflation, computes a shift (tau) and calls dqds. -// In case of failure it changes shifts, and tries again until output -// is positive. -// -// Dlasq3 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasq3(i0, n0 int, z []float64, pp int, dmin, sigma, desig, qmax float64, nFail, iter, nDiv int, ttype int, dmin1, dmin2, dn, dn1, dn2, g, tau float64) ( - i0Out, n0Out, ppOut int, dminOut, sigmaOut, desigOut, qmaxOut float64, nFailOut, iterOut, nDivOut, ttypeOut int, dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut float64) { - switch { - case i0 < 0: - panic(i0LT0) - case n0 < 0: - panic(n0LT0) - case len(z) < 4*n0: - panic(shortZ) - case pp != 0 && pp != 1 && pp != 2: - panic(badPp) - } - - const cbias = 1.5 - - n0in := n0 - eps := dlamchP - tol := eps * 100 - tol2 := tol * tol - var nn int - var t float64 - for { - if n0 < i0 { - return i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau - } - if n0 == i0 { - z[4*(n0+1)-4] = z[4*(n0+1)+pp-4] + sigma - n0-- - continue - } - nn = 4*(n0+1) + pp - 1 - if n0 != i0+1 { - // Check whether e[n0-1] is negligible, 1 eigenvalue. - if z[nn-5] > tol2*(sigma+z[nn-3]) && z[nn-2*pp-4] > tol2*z[nn-7] { - // Check whether e[n0-2] is negligible, 2 eigenvalues. - if z[nn-9] > tol2*sigma && z[nn-2*pp-8] > tol2*z[nn-11] { - break - } - } else { - z[4*(n0+1)-4] = z[4*(n0+1)+pp-4] + sigma - n0-- - continue - } - } - if z[nn-3] > z[nn-7] { - z[nn-3], z[nn-7] = z[nn-7], z[nn-3] - } - t = 0.5 * (z[nn-7] - z[nn-3] + z[nn-5]) - if z[nn-5] > z[nn-3]*tol2 && t != 0 { - s := z[nn-3] * (z[nn-5] / t) - if s <= t { - s = z[nn-3] * (z[nn-5] / (t * (1 + math.Sqrt(1+s/t)))) - } else { - s = z[nn-3] * (z[nn-5] / (t + math.Sqrt(t)*math.Sqrt(t+s))) - } - t = z[nn-7] + (s + z[nn-5]) - z[nn-3] *= z[nn-7] / t - z[nn-7] = t - } - z[4*(n0+1)-8] = z[nn-7] + sigma - z[4*(n0+1)-4] = z[nn-3] + sigma - n0 -= 2 - } - if pp == 2 { - pp = 0 - } - - // Reverse the qd-array, if warranted. - if dmin <= 0 || n0 < n0in { - if cbias*z[4*(i0+1)+pp-4] < z[4*(n0+1)+pp-4] { - ipn4Out := 4 * (i0 + n0 + 2) - for j4loop := 4 * (i0 + 1); j4loop <= 2*((i0+1)+(n0+1)-1); j4loop += 4 { - ipn4 := ipn4Out - 1 - j4 := j4loop - 1 - - z[j4-3], z[ipn4-j4-4] = z[ipn4-j4-4], z[j4-3] - z[j4-2], z[ipn4-j4-3] = z[ipn4-j4-3], z[j4-2] - z[j4-1], z[ipn4-j4-6] = z[ipn4-j4-6], z[j4-1] - z[j4], z[ipn4-j4-5] = z[ipn4-j4-5], z[j4] - } - if n0-i0 <= 4 { - z[4*(n0+1)+pp-2] = z[4*(i0+1)+pp-2] - z[4*(n0+1)-pp-1] = z[4*(i0+1)-pp-1] - } - dmin2 = math.Min(dmin2, z[4*(i0+1)-pp-2]) - z[4*(n0+1)+pp-2] = math.Min(math.Min(z[4*(n0+1)+pp-2], z[4*(i0+1)+pp-2]), z[4*(i0+1)+pp+2]) - z[4*(n0+1)-pp-1] = math.Min(math.Min(z[4*(n0+1)-pp-1], z[4*(i0+1)-pp-1]), z[4*(i0+1)-pp+3]) - qmax = math.Max(math.Max(qmax, z[4*(i0+1)+pp-4]), z[4*(i0+1)+pp]) - dmin = math.Copysign(0, -1) // Fortran code has -zero, but -0 in go is 0 - } - } - - // Choose a shift. - tau, ttype, g = impl.Dlasq4(i0, n0, z, pp, n0in, dmin, dmin1, dmin2, dn, dn1, dn2, tau, ttype, g) - - // Call dqds until dmin > 0. -loop: - for { - i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dn1, dn2 = impl.Dlasq5(i0, n0, z, pp, tau, sigma) - - nDiv += n0 - i0 + 2 - iter++ - switch { - case dmin >= 0 && dmin1 >= 0: - // Success. - goto done - - case dmin < 0 && dmin1 > 0 && z[4*n0-pp-1] < tol*(sigma+dn1) && math.Abs(dn) < tol*sigma: - // Convergence hidden by negative dn. - z[4*n0-pp+1] = 0 - dmin = 0 - goto done - - case dmin < 0: - // Tau too big. Select new Tau and try again. - nFail++ - if ttype < -22 { - // Failed twice. Play it safe. - tau = 0 - } else if dmin1 > 0 { - // Late failure. Gives excellent shift. - tau = (tau + dmin) * (1 - 2*eps) - ttype -= 11 - } else { - // Early failure. Divide by 4. - tau = tau / 4 - ttype -= 12 - } - - case math.IsNaN(dmin): - if tau == 0 { - break loop - } - tau = 0 - - default: - // Possible underflow. Play it safe. - break loop - } - } - - // Risk of underflow. - dmin, dmin1, dmin2, dn, dn1, dn2 = impl.Dlasq6(i0, n0, z, pp) - nDiv += n0 - i0 + 2 - iter++ - tau = 0 - -done: - if tau < sigma { - desig += tau - t = sigma + desig - desig -= t - sigma - } else { - t = sigma + tau - desig += sigma - (t - tau) - } - sigma = t - return i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go deleted file mode 100644 index f6dbb31b..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlasq4 computes an approximation to the smallest eigenvalue using values of d -// from the previous transform. -// i0, n0, and n0in are zero-indexed. -// -// Dlasq4 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasq4(i0, n0 int, z []float64, pp int, n0in int, dmin, dmin1, dmin2, dn, dn1, dn2, tau float64, ttype int, g float64) (tauOut float64, ttypeOut int, gOut float64) { - switch { - case i0 < 0: - panic(i0LT0) - case n0 < 0: - panic(n0LT0) - case len(z) < 4*n0: - panic(shortZ) - case pp != 0 && pp != 1: - panic(badPp) - } - - const ( - cnst1 = 0.563 - cnst2 = 1.01 - cnst3 = 1.05 - - cnstthird = 0.333 // TODO(btracey): Fix? - ) - // A negative dmin forces the shift to take that absolute value - // ttype records the type of shift. - if dmin <= 0 { - tau = -dmin - ttype = -1 - return tau, ttype, g - } - nn := 4*(n0+1) + pp - 1 // -1 for zero indexing - s := math.NaN() // Poison s so that failure to take a path below is obvious - if n0in == n0 { - // No eigenvalues deflated. - if dmin == dn || dmin == dn1 { - b1 := math.Sqrt(z[nn-3]) * math.Sqrt(z[nn-5]) - b2 := math.Sqrt(z[nn-7]) * math.Sqrt(z[nn-9]) - a2 := z[nn-7] + z[nn-5] - if dmin == dn && dmin1 == dn1 { - gap2 := dmin2 - a2 - dmin2/4 - var gap1 float64 - if gap2 > 0 && gap2 > b2 { - gap1 = a2 - dn - (b2/gap2)*b2 - } else { - gap1 = a2 - dn - (b1 + b2) - } - if gap1 > 0 && gap1 > b1 { - s = math.Max(dn-(b1/gap1)*b1, 0.5*dmin) - ttype = -2 - } else { - s = 0 - if dn > b1 { - s = dn - b1 - } - if a2 > b1+b2 { - s = math.Min(s, a2-(b1+b2)) - } - s = math.Max(s, cnstthird*dmin) - ttype = -3 - } - } else { - ttype = -4 - s = dmin / 4 - var gam float64 - var np int - if dmin == dn { - gam = dn - a2 = 0 - if z[nn-5] > z[nn-7] { - return tau, ttype, g - } - b2 = z[nn-5] / z[nn-7] - np = nn - 9 - } else { - np = nn - 2*pp - gam = dn1 - if z[np-4] > z[np-2] { - return tau, ttype, g - } - a2 = z[np-4] / z[np-2] - if z[nn-9] > z[nn-11] { - return tau, ttype, g - } - b2 = z[nn-9] / z[nn-11] - np = nn - 13 - } - // Approximate contribution to norm squared from i < nn-1. - a2 += b2 - for i4loop := np + 1; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { - i4 := i4loop - 1 - if b2 == 0 { - break - } - b1 = b2 - if z[i4] > z[i4-2] { - return tau, ttype, g - } - b2 *= z[i4] / z[i4-2] - a2 += b2 - if 100*math.Max(b2, b1) < a2 || cnst1 < a2 { - break - } - } - a2 *= cnst3 - // Rayleigh quotient residual bound. - if a2 < cnst1 { - s = gam * (1 - math.Sqrt(a2)) / (1 + a2) - } - } - } else if dmin == dn2 { - ttype = -5 - s = dmin / 4 - // Compute contribution to norm squared from i > nn-2. - np := nn - 2*pp - b1 := z[np-2] - b2 := z[np-6] - gam := dn2 - if z[np-8] > b2 || z[np-4] > b1 { - return tau, ttype, g - } - a2 := (z[np-8] / b2) * (1 + z[np-4]/b1) - // Approximate contribution to norm squared from i < nn-2. - if n0-i0 > 2 { - b2 = z[nn-13] / z[nn-15] - a2 += b2 - for i4loop := (nn + 1) - 17; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { - i4 := i4loop - 1 - if b2 == 0 { - break - } - b1 = b2 - if z[i4] > z[i4-2] { - return tau, ttype, g - } - b2 *= z[i4] / z[i4-2] - a2 += b2 - if 100*math.Max(b2, b1) < a2 || cnst1 < a2 { - break - } - } - a2 *= cnst3 - } - if a2 < cnst1 { - s = gam * (1 - math.Sqrt(a2)) / (1 + a2) - } - } else { - // Case 6, no information to guide us. - if ttype == -6 { - g += cnstthird * (1 - g) - } else if ttype == -18 { - g = cnstthird / 4 - } else { - g = 1.0 / 4 - } - s = g * dmin - ttype = -6 - } - } else if n0in == (n0 + 1) { - // One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN. - if dmin1 == dn1 && dmin2 == dn2 { - ttype = -7 - s = cnstthird * dmin1 - if z[nn-5] > z[nn-7] { - return tau, ttype, g - } - b1 := z[nn-5] / z[nn-7] - b2 := b1 - if b2 != 0 { - for i4loop := 4*(n0+1) - 9 + pp; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { - i4 := i4loop - 1 - a2 := b1 - if z[i4] > z[i4-2] { - return tau, ttype, g - } - b1 *= z[i4] / z[i4-2] - b2 += b1 - if 100*math.Max(b1, a2) < b2 { - break - } - } - } - b2 = math.Sqrt(cnst3 * b2) - a2 := dmin1 / (1 + b2*b2) - gap2 := 0.5*dmin2 - a2 - if gap2 > 0 && gap2 > b2*a2 { - s = math.Max(s, a2*(1-cnst2*a2*(b2/gap2)*b2)) - } else { - s = math.Max(s, a2*(1-cnst2*b2)) - ttype = -8 - } - } else { - s = dmin1 / 4 - if dmin1 == dn1 { - s = 0.5 * dmin1 - } - ttype = -9 - } - } else if n0in == (n0 + 2) { - // Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN. - if dmin2 == dn2 && 2*z[nn-5] < z[nn-7] { - ttype = -10 - s = cnstthird * dmin2 - if z[nn-5] > z[nn-7] { - return tau, ttype, g - } - b1 := z[nn-5] / z[nn-7] - b2 := b1 - if b2 != 0 { - for i4loop := 4*(n0+1) - 9 + pp; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { - i4 := i4loop - 1 - if z[i4] > z[i4-2] { - return tau, ttype, g - } - b1 *= z[i4] / z[i4-2] - b2 += b1 - if 100*b1 < b2 { - break - } - } - } - b2 = math.Sqrt(cnst3 * b2) - a2 := dmin2 / (1 + b2*b2) - gap2 := z[nn-7] + z[nn-9] - math.Sqrt(z[nn-11])*math.Sqrt(z[nn-9]) - a2 - if gap2 > 0 && gap2 > b2*a2 { - s = math.Max(s, a2*(1-cnst2*a2*(b2/gap2)*b2)) - } else { - s = math.Max(s, a2*(1-cnst2*b2)) - } - } else { - s = dmin2 / 4 - ttype = -11 - } - } else if n0in > n0+2 { - // Case 12, more than two eigenvalues deflated. No information. - s = 0 - ttype = -12 - } - tau = s - return tau, ttype, g -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go deleted file mode 100644 index d3826d91..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlasq5 computes one dqds transform in ping-pong form. -// i0 and n0 are zero-indexed. -// -// Dlasq5 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasq5(i0, n0 int, z []float64, pp int, tau, sigma float64) (i0Out, n0Out, ppOut int, tauOut, sigmaOut, dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) { - // The lapack function has inputs for ieee and eps, but Go requires ieee so - // these are unnecessary. - - switch { - case i0 < 0: - panic(i0LT0) - case n0 < 0: - panic(n0LT0) - case len(z) < 4*n0: - panic(shortZ) - case pp != 0 && pp != 1: - panic(badPp) - } - - if n0-i0-1 <= 0 { - return i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dnm1, dnm2 - } - - eps := dlamchP - dthresh := eps * (sigma + tau) - if tau < dthresh*0.5 { - tau = 0 - } - var j4 int - var emin float64 - if tau != 0 { - j4 = 4*i0 + pp - emin = z[j4+4] - d := z[j4] - tau - dmin = d - // In the reference there are code paths that actually return this value. - // dmin1 = -z[j4] - if pp == 0 { - for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { - j4 := j4loop - 1 - z[j4-2] = d + z[j4-1] - tmp := z[j4+1] / z[j4-2] - d = d*tmp - tau - dmin = math.Min(dmin, d) - z[j4] = z[j4-1] * tmp - emin = math.Min(z[j4], emin) - } - } else { - for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { - j4 := j4loop - 1 - z[j4-3] = d + z[j4] - tmp := z[j4+2] / z[j4-3] - d = d*tmp - tau - dmin = math.Min(dmin, d) - z[j4-1] = z[j4] * tmp - emin = math.Min(z[j4-1], emin) - } - } - // Unroll the last two steps. - dnm2 = d - dmin2 = dmin - j4 = 4*((n0+1)-2) - pp - 1 - j4p2 := j4 + 2*pp - 1 - z[j4-2] = dnm2 + z[j4p2] - z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) - dnm1 = z[j4p2+2]*(dnm2/z[j4-2]) - tau - dmin = math.Min(dmin, dnm1) - - dmin1 = dmin - j4 += 4 - j4p2 = j4 + 2*pp - 1 - z[j4-2] = dnm1 + z[j4p2] - z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) - dn = z[j4p2+2]*(dnm1/z[j4-2]) - tau - dmin = math.Min(dmin, dn) - } else { - // This is the version that sets d's to zero if they are small enough. - j4 = 4*(i0+1) + pp - 4 - emin = z[j4+4] - d := z[j4] - tau - dmin = d - // In the reference there are code paths that actually return this value. - // dmin1 = -z[j4] - if pp == 0 { - for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { - j4 := j4loop - 1 - z[j4-2] = d + z[j4-1] - tmp := z[j4+1] / z[j4-2] - d = d*tmp - tau - if d < dthresh { - d = 0 - } - dmin = math.Min(dmin, d) - z[j4] = z[j4-1] * tmp - emin = math.Min(z[j4], emin) - } - } else { - for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { - j4 := j4loop - 1 - z[j4-3] = d + z[j4] - tmp := z[j4+2] / z[j4-3] - d = d*tmp - tau - if d < dthresh { - d = 0 - } - dmin = math.Min(dmin, d) - z[j4-1] = z[j4] * tmp - emin = math.Min(z[j4-1], emin) - } - } - // Unroll the last two steps. - dnm2 = d - dmin2 = dmin - j4 = 4*((n0+1)-2) - pp - 1 - j4p2 := j4 + 2*pp - 1 - z[j4-2] = dnm2 + z[j4p2] - z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) - dnm1 = z[j4p2+2]*(dnm2/z[j4-2]) - tau - dmin = math.Min(dmin, dnm1) - - dmin1 = dmin - j4 += 4 - j4p2 = j4 + 2*pp - 1 - z[j4-2] = dnm1 + z[j4p2] - z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) - dn = z[j4p2+2]*(dnm1/z[j4-2]) - tau - dmin = math.Min(dmin, dn) - } - z[j4+2] = dn - z[4*(n0+1)-pp-1] = emin - return i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dnm1, dnm2 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go deleted file mode 100644 index 54bf5875..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlasq6 computes one dqd transform in ping-pong form with protection against -// overflow and underflow. z has length at least 4*(n0+1) and holds the qd array. -// i0 is the zero-based first index. -// n0 is the zero-based last index. -// -// Dlasq6 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasq6(i0, n0 int, z []float64, pp int) (dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) { - switch { - case i0 < 0: - panic(i0LT0) - case n0 < 0: - panic(n0LT0) - case len(z) < 4*n0: - panic(shortZ) - case pp != 0 && pp != 1: - panic(badPp) - } - - if n0-i0-1 <= 0 { - return dmin, dmin1, dmin2, dn, dnm1, dnm2 - } - - safmin := dlamchS - j4 := 4*(i0+1) + pp - 4 // -4 rather than -3 for zero indexing - emin := z[j4+4] - d := z[j4] - dmin = d - if pp == 0 { - for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { - j4 := j4loop - 1 // Translate back to zero-indexed. - z[j4-2] = d + z[j4-1] - if z[j4-2] == 0 { - z[j4] = 0 - d = z[j4+1] - dmin = d - emin = 0 - } else if safmin*z[j4+1] < z[j4-2] && safmin*z[j4-2] < z[j4+1] { - tmp := z[j4+1] / z[j4-2] - z[j4] = z[j4-1] * tmp - d *= tmp - } else { - z[j4] = z[j4+1] * (z[j4-1] / z[j4-2]) - d = z[j4+1] * (d / z[j4-2]) - } - dmin = math.Min(dmin, d) - emin = math.Min(emin, z[j4]) - } - } else { - for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { - j4 := j4loop - 1 - z[j4-3] = d + z[j4] - if z[j4-3] == 0 { - z[j4-1] = 0 - d = z[j4+2] - dmin = d - emin = 0 - } else if safmin*z[j4+2] < z[j4-3] && safmin*z[j4-3] < z[j4+2] { - tmp := z[j4+2] / z[j4-3] - z[j4-1] = z[j4] * tmp - d *= tmp - } else { - z[j4-1] = z[j4+2] * (z[j4] / z[j4-3]) - d = z[j4+2] * (d / z[j4-3]) - } - dmin = math.Min(dmin, d) - emin = math.Min(emin, z[j4-1]) - } - } - // Unroll last two steps. - dnm2 = d - dmin2 = dmin - j4 = 4*(n0-1) - pp - 1 - j4p2 := j4 + 2*pp - 1 - z[j4-2] = dnm2 + z[j4p2] - if z[j4-2] == 0 { - z[j4] = 0 - dnm1 = z[j4p2+2] - dmin = dnm1 - emin = 0 - } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { - tmp := z[j4p2+2] / z[j4-2] - z[j4] = z[j4p2] * tmp - dnm1 = dnm2 * tmp - } else { - z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) - dnm1 = z[j4p2+2] * (dnm2 / z[j4-2]) - } - dmin = math.Min(dmin, dnm1) - dmin1 = dmin - j4 += 4 - j4p2 = j4 + 2*pp - 1 - z[j4-2] = dnm1 + z[j4p2] - if z[j4-2] == 0 { - z[j4] = 0 - dn = z[j4p2+2] - dmin = dn - emin = 0 - } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { - tmp := z[j4p2+2] / z[j4-2] - z[j4] = z[j4p2] * tmp - dn = dnm1 * tmp - } else { - z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) - dn = z[j4p2+2] * (dnm1 / z[j4-2]) - } - dmin = math.Min(dmin, dn) - z[j4+2] = dn - z[4*(n0+1)-pp-1] = emin - return dmin, dmin1, dmin2, dn, dnm1, dnm2 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go deleted file mode 100644 index 3aab41f8..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dlasr applies a sequence of plane rotations to the m×n matrix A. This series -// of plane rotations is implicitly represented by a matrix P. P is multiplied -// by a depending on the value of side -- A = P * A if side == lapack.Left, -// A = A * Pᵀ if side == lapack.Right. -// -// The exact value of P depends on the value of pivot, but in all cases P is -// implicitly represented by a series of 2×2 rotation matrices. The entries of -// rotation matrix k are defined by s[k] and c[k] -// -// R(k) = [ c[k] s[k]] -// [-s[k] s[k]] -// -// If direct == lapack.Forward, the rotation matrices are applied as -// P = P(z-1) * ... * P(2) * P(1), while if direct == lapack.Backward they are -// applied as P = P(1) * P(2) * ... * P(n). -// -// pivot defines the mapping of the elements in R(k) to P(k). -// If pivot == lapack.Variable, the rotation is performed for the (k, k+1) plane. -// -// P(k) = [1 ] -// [ ... ] -// [ 1 ] -// [ c[k] s[k] ] -// [ -s[k] c[k] ] -// [ 1 ] -// [ ... ] -// [ 1] -// -// if pivot == lapack.Top, the rotation is performed for the (1, k+1) plane, -// -// P(k) = [c[k] s[k] ] -// [ 1 ] -// [ ... ] -// [ 1 ] -// [-s[k] c[k] ] -// [ 1 ] -// [ ... ] -// [ 1] -// -// and if pivot == lapack.Bottom, the rotation is performed for the (k, z) plane. -// -// P(k) = [1 ] -// [ ... ] -// [ 1 ] -// [ c[k] s[k]] -// [ 1 ] -// [ ... ] -// [ 1 ] -// [ -s[k] c[k]] -// -// s and c have length m - 1 if side == blas.Left, and n - 1 if side == blas.Right. -// -// Dlasr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasr(side blas.Side, pivot lapack.Pivot, direct lapack.Direct, m, n int, c, s, a []float64, lda int) { - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case pivot != lapack.Variable && pivot != lapack.Top && pivot != lapack.Bottom: - panic(badPivot) - case direct != lapack.Forward && direct != lapack.Backward: - panic(badDirect) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if m == 0 || n == 0 { - return - } - - if side == blas.Left { - if len(c) < m-1 { - panic(shortC) - } - if len(s) < m-1 { - panic(shortS) - } - } else { - if len(c) < n-1 { - panic(shortC) - } - if len(s) < n-1 { - panic(shortS) - } - } - if len(a) < (m-1)*lda+n { - panic(shortA) - } - - if side == blas.Left { - if pivot == lapack.Variable { - if direct == lapack.Forward { - for j := 0; j < m-1; j++ { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < n; i++ { - tmp2 := a[j*lda+i] - tmp := a[(j+1)*lda+i] - a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2 - a[j*lda+i] = stmp*tmp + ctmp*tmp2 - } - } - } - return - } - for j := m - 2; j >= 0; j-- { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < n; i++ { - tmp2 := a[j*lda+i] - tmp := a[(j+1)*lda+i] - a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2 - a[j*lda+i] = stmp*tmp + ctmp*tmp2 - } - } - } - return - } else if pivot == lapack.Top { - if direct == lapack.Forward { - for j := 1; j < m; j++ { - ctmp := c[j-1] - stmp := s[j-1] - if ctmp != 1 || stmp != 0 { - for i := 0; i < n; i++ { - tmp := a[j*lda+i] - tmp2 := a[i] - a[j*lda+i] = ctmp*tmp - stmp*tmp2 - a[i] = stmp*tmp + ctmp*tmp2 - } - } - } - return - } - for j := m - 1; j >= 1; j-- { - ctmp := c[j-1] - stmp := s[j-1] - if ctmp != 1 || stmp != 0 { - for i := 0; i < n; i++ { - ctmp := c[j-1] - stmp := s[j-1] - if ctmp != 1 || stmp != 0 { - for i := 0; i < n; i++ { - tmp := a[j*lda+i] - tmp2 := a[i] - a[j*lda+i] = ctmp*tmp - stmp*tmp2 - a[i] = stmp*tmp + ctmp*tmp2 - } - } - } - } - } - return - } - if direct == lapack.Forward { - for j := 0; j < m-1; j++ { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < n; i++ { - tmp := a[j*lda+i] - tmp2 := a[(m-1)*lda+i] - a[j*lda+i] = stmp*tmp2 + ctmp*tmp - a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp - } - } - } - return - } - for j := m - 2; j >= 0; j-- { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < n; i++ { - tmp := a[j*lda+i] - tmp2 := a[(m-1)*lda+i] - a[j*lda+i] = stmp*tmp2 + ctmp*tmp - a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp - } - } - } - return - } - if pivot == lapack.Variable { - if direct == lapack.Forward { - for j := 0; j < n-1; j++ { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < m; i++ { - tmp := a[i*lda+j+1] - tmp2 := a[i*lda+j] - a[i*lda+j+1] = ctmp*tmp - stmp*tmp2 - a[i*lda+j] = stmp*tmp + ctmp*tmp2 - } - } - } - return - } - for j := n - 2; j >= 0; j-- { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < m; i++ { - tmp := a[i*lda+j+1] - tmp2 := a[i*lda+j] - a[i*lda+j+1] = ctmp*tmp - stmp*tmp2 - a[i*lda+j] = stmp*tmp + ctmp*tmp2 - } - } - } - return - } else if pivot == lapack.Top { - if direct == lapack.Forward { - for j := 1; j < n; j++ { - ctmp := c[j-1] - stmp := s[j-1] - if ctmp != 1 || stmp != 0 { - for i := 0; i < m; i++ { - tmp := a[i*lda+j] - tmp2 := a[i*lda] - a[i*lda+j] = ctmp*tmp - stmp*tmp2 - a[i*lda] = stmp*tmp + ctmp*tmp2 - } - } - } - return - } - for j := n - 1; j >= 1; j-- { - ctmp := c[j-1] - stmp := s[j-1] - if ctmp != 1 || stmp != 0 { - for i := 0; i < m; i++ { - tmp := a[i*lda+j] - tmp2 := a[i*lda] - a[i*lda+j] = ctmp*tmp - stmp*tmp2 - a[i*lda] = stmp*tmp + ctmp*tmp2 - } - } - } - return - } - if direct == lapack.Forward { - for j := 0; j < n-1; j++ { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < m; i++ { - tmp := a[i*lda+j] - tmp2 := a[i*lda+n-1] - a[i*lda+j] = stmp*tmp2 + ctmp*tmp - a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp - } - - } - } - return - } - for j := n - 2; j >= 0; j-- { - ctmp := c[j] - stmp := s[j] - if ctmp != 1 || stmp != 0 { - for i := 0; i < m; i++ { - tmp := a[i*lda+j] - tmp2 := a[i*lda+n-1] - a[i*lda+j] = stmp*tmp2 + ctmp*tmp - a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go deleted file mode 100644 index be472805..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "sort" - - "gonum.org/v1/gonum/lapack" -) - -// Dlasrt sorts the numbers in the input slice d. If s == lapack.SortIncreasing, -// the elements are sorted in increasing order. If s == lapack.SortDecreasing, -// the elements are sorted in decreasing order. For other values of s Dlasrt -// will panic. -// -// Dlasrt is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasrt(s lapack.Sort, n int, d []float64) { - switch { - case n < 0: - panic(nLT0) - case len(d) < n: - panic(shortD) - } - - d = d[:n] - switch s { - default: - panic(badSort) - case lapack.SortIncreasing: - sort.Float64s(d) - case lapack.SortDecreasing: - sort.Sort(sort.Reverse(sort.Float64Slice(d))) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go deleted file mode 100644 index 8f8cda87..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlassq updates a sum of squares represented in scaled form. Dlassq returns -// the values scl and smsq such that -// -// scl^2*smsq = X[0]^2 + ... + X[n-1]^2 + scale^2*sumsq -// -// The value of sumsq is assumed to be non-negative. -// -// Dlassq is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlassq(n int, x []float64, incx int, scale float64, sumsq float64) (scl, smsq float64) { - // Implementation based on Supplemental Material to: - // Edward Anderson. 2017. Algorithm 978: Safe Scaling in the Level 1 BLAS. - // ACM Trans. Math. Softw. 44, 1, Article 12 (July 2017), 28 pages. - // DOI: https://doi.org/10.1145/3061665 - switch { - case n < 0: - panic(nLT0) - case incx <= 0: - panic(badIncX) - case len(x) < 1+(n-1)*incx: - panic(shortX) - } - - if math.IsNaN(scale) || math.IsNaN(sumsq) { - return scale, sumsq - } - - if sumsq == 0 { - scale = 1 - } - if scale == 0 { - scale = 1 - sumsq = 0 - } - - if n == 0 { - return scale, sumsq - } - - // Compute the sum of squares in 3 accumulators: - // - abig: sum of squares scaled down to avoid overflow - // - asml: sum of squares scaled up to avoid underflow - // - amed: sum of squares that do not require scaling - // The thresholds and multipliers are: - // - values bigger than dtbig are scaled down by dsbig - // - values smaller than dtsml are scaled up by dssml - var ( - isBig bool - asml, amed, abig float64 - ) - for i, ix := 0, 0; i < n; i++ { - ax := math.Abs(x[ix]) - switch { - case ax > dtbig: - ax *= dsbig - abig += ax * ax - isBig = true - case ax < dtsml: - if !isBig { - ax *= dssml - asml += ax * ax - } - default: - amed += ax * ax - } - ix += incx - } - // Put the existing sum of squares into one of the accumulators. - if sumsq > 0 { - ax := scale * math.Sqrt(sumsq) - switch { - case ax > dtbig: - if scale > 1 { - scale *= dsbig - abig += scale * (scale * sumsq) - } else { - // sumsq > dtbig^2 => (dsbig * (dsbig * sumsq)) is representable. - abig += scale * (scale * (dsbig * (dsbig * sumsq))) - } - case ax < dtsml: - if !isBig { - if scale < 1 { - scale *= dssml - asml += scale * (scale * sumsq) - } else { - // sumsq < dtsml^2 => (dssml * (dssml * sumsq)) is representable. - asml += scale * (scale * (dssml * (dssml * sumsq))) - } - } - default: - amed += scale * (scale * sumsq) - } - } - // Combine abig and amed or amed and asml if more than one accumulator was - // used. - switch { - case abig > 0: - // Combine abig and amed: - if amed > 0 || math.IsNaN(amed) { - abig += (amed * dsbig) * dsbig - } - scale = 1 / dsbig - sumsq = abig - case asml > 0: - // Combine amed and asml: - if amed > 0 || math.IsNaN(amed) { - amed = math.Sqrt(amed) - asml = math.Sqrt(asml) / dssml - ymin, ymax := asml, amed - if asml > amed { - ymin, ymax = amed, asml - } - scale = 1 - sumsq = ymax * ymax * (1 + (ymin/ymax)*(ymin/ymax)) - } else { - scale = 1 / dssml - sumsq = asml - } - default: - scale = 1 - sumsq = amed - } - return scale, sumsq -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go deleted file mode 100644 index cc7ceea0..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasv2.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "math" - -// Dlasv2 computes the singular value decomposition of a 2×2 matrix. -// -// [ csl snl] [f g] [csr -snr] = [ssmax 0] -// [-snl csl] [0 h] [snr csr] = [ 0 ssmin] -// -// ssmax is the larger absolute singular value, and ssmin is the smaller absolute -// singular value. [cls, snl] and [csr, snr] are the left and right singular vectors. -// -// Dlasv2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasv2(f, g, h float64) (ssmin, ssmax, snr, csr, snl, csl float64) { - ft := f - fa := math.Abs(ft) - ht := h - ha := math.Abs(h) - // pmax points to the largest element of the matrix in terms of absolute value. - // 1 if F, 2 if G, 3 if H. - pmax := 1 - swap := ha > fa - if swap { - pmax = 3 - ft, ht = ht, ft - fa, ha = ha, fa - } - gt := g - ga := math.Abs(gt) - var clt, crt, slt, srt float64 - if ga == 0 { - ssmin = ha - ssmax = fa - clt = 1 - crt = 1 - slt = 0 - srt = 0 - } else { - gasmall := true - if ga > fa { - pmax = 2 - if (fa / ga) < dlamchE { - gasmall = false - ssmax = ga - if ha > 1 { - ssmin = fa / (ga / ha) - } else { - ssmin = (fa / ga) * ha - } - clt = 1 - slt = ht / gt - srt = 1 - crt = ft / gt - } - } - if gasmall { - d := fa - ha - l := d / fa - if d == fa { // deal with inf - l = 1 - } - m := gt / ft - t := 2 - l - s := math.Hypot(t, m) - var r float64 - if l == 0 { - r = math.Abs(m) - } else { - r = math.Hypot(l, m) - } - a := 0.5 * (s + r) - ssmin = ha / a - ssmax = fa * a - if m == 0 { - if l == 0 { - t = math.Copysign(2, ft) * math.Copysign(1, gt) - } else { - t = gt/math.Copysign(d, ft) + m/t - } - } else { - t = (m/(s+t) + m/(r+l)) * (1 + a) - } - l = math.Hypot(t, 2) - crt = 2 / l - srt = t / l - clt = (crt + srt*m) / a - slt = (ht / ft) * srt / a - } - } - if swap { - csl = srt - snl = crt - csr = slt - snr = clt - } else { - csl = clt - snl = slt - csr = crt - snr = srt - } - var tsign float64 - switch pmax { - case 1: - tsign = math.Copysign(1, csr) * math.Copysign(1, csl) * math.Copysign(1, f) - case 2: - tsign = math.Copysign(1, snr) * math.Copysign(1, csl) * math.Copysign(1, g) - case 3: - tsign = math.Copysign(1, snr) * math.Copysign(1, snl) * math.Copysign(1, h) - } - ssmax = math.Copysign(ssmax, tsign) - ssmin = math.Copysign(ssmin, tsign*math.Copysign(1, f)*math.Copysign(1, h)) - return ssmin, ssmax, snr, csr, snl, csl -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go deleted file mode 100644 index 88600ac1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas/blas64" - -// Dlaswp swaps the rows k1 to k2 of a rectangular matrix A according to the -// indices in ipiv so that row k is swapped with ipiv[k]. -// -// n is the number of columns of A and incX is the increment for ipiv. If incX -// is 1, the swaps are applied from k1 to k2. If incX is -1, the swaps are -// applied in reverse order from k2 to k1. For other values of incX Dlaswp will -// panic. ipiv must have length k2+1, otherwise Dlaswp will panic. -// -// The indices k1, k2, and the elements of ipiv are zero-based. -// -// Dlaswp is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlaswp(n int, a []float64, lda int, k1, k2 int, ipiv []int, incX int) { - switch { - case n < 0: - panic(nLT0) - case k1 < 0: - panic(badK1) - case k2 < k1: - panic(badK2) - case lda < max(1, n): - panic(badLdA) - case len(a) < k2*lda+n: // A must have at least k2+1 rows. - panic(shortA) - case len(ipiv) != k2+1: - panic(badLenIpiv) - case incX != 1 && incX != -1: - panic(absIncNotOne) - } - - if n == 0 { - return - } - - bi := blas64.Implementation() - if incX == 1 { - for k := k1; k <= k2; k++ { - if k == ipiv[k] { - continue - } - bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) - } - return - } - for k := k2; k >= k1; k-- { - if k == ipiv[k] { - continue - } - bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go deleted file mode 100644 index 160b68b8..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasy2.go +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlasy2 solves the Sylvester matrix equation where the matrices are of order 1 -// or 2. It computes the unknown n1×n2 matrix X so that -// -// TL*X + sgn*X*TR = scale*B if tranl == false and tranr == false, -// TLᵀ*X + sgn*X*TR = scale*B if tranl == true and tranr == false, -// TL*X + sgn*X*TRᵀ = scale*B if tranl == false and tranr == true, -// TLᵀ*X + sgn*X*TRᵀ = scale*B if tranl == true and tranr == true, -// -// where TL is n1×n1, TR is n2×n2, B is n1×n2, and 1 <= n1,n2 <= 2. -// -// isgn must be 1 or -1, and n1 and n2 must be 0, 1, or 2, but these conditions -// are not checked. -// -// Dlasy2 returns three values, a scale factor that is chosen less than or equal -// to 1 to prevent the solution overflowing, the infinity norm of the solution, -// and an indicator of success. If ok is false, TL and TR have eigenvalues that -// are too close, so TL or TR is perturbed to get a non-singular equation. -// -// Dlasy2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlasy2(tranl, tranr bool, isgn, n1, n2 int, tl []float64, ldtl int, tr []float64, ldtr int, b []float64, ldb int, x []float64, ldx int) (scale, xnorm float64, ok bool) { - // TODO(vladimir-ch): Add input validation checks conditionally skipped - // using the build tag mechanism. - - ok = true - // Quick return if possible. - if n1 == 0 || n2 == 0 { - return scale, xnorm, ok - } - - // Set constants to control overflow. - eps := dlamchP - smlnum := dlamchS / eps - sgn := float64(isgn) - - if n1 == 1 && n2 == 1 { - // 1×1 case: TL11*X + sgn*X*TR11 = B11. - tau1 := tl[0] + sgn*tr[0] - bet := math.Abs(tau1) - if bet <= smlnum { - tau1 = smlnum - bet = smlnum - ok = false - } - scale = 1 - gam := math.Abs(b[0]) - if smlnum*gam > bet { - scale = 1 / gam - } - x[0] = b[0] * scale / tau1 - xnorm = math.Abs(x[0]) - return scale, xnorm, ok - } - - if n1+n2 == 3 { - // 1×2 or 2×1 case. - var ( - smin float64 - tmp [4]float64 // tmp is used as a 2×2 row-major matrix. - btmp [2]float64 - ) - if n1 == 1 && n2 == 2 { - // 1×2 case: TL11*[X11 X12] + sgn*[X11 X12]*op[TR11 TR12] = [B11 B12]. - // [TR21 TR22] - smin = math.Abs(tl[0]) - smin = math.Max(smin, math.Max(math.Abs(tr[0]), math.Abs(tr[1]))) - smin = math.Max(smin, math.Max(math.Abs(tr[ldtr]), math.Abs(tr[ldtr+1]))) - smin = math.Max(eps*smin, smlnum) - tmp[0] = tl[0] + sgn*tr[0] - tmp[3] = tl[0] + sgn*tr[ldtr+1] - if tranr { - tmp[1] = sgn * tr[1] - tmp[2] = sgn * tr[ldtr] - } else { - tmp[1] = sgn * tr[ldtr] - tmp[2] = sgn * tr[1] - } - btmp[0] = b[0] - btmp[1] = b[1] - } else { - // 2×1 case: op[TL11 TL12]*[X11] + sgn*[X11]*TR11 = [B11]. - // [TL21 TL22]*[X21] [X21] [B21] - smin = math.Abs(tr[0]) - smin = math.Max(smin, math.Max(math.Abs(tl[0]), math.Abs(tl[1]))) - smin = math.Max(smin, math.Max(math.Abs(tl[ldtl]), math.Abs(tl[ldtl+1]))) - smin = math.Max(eps*smin, smlnum) - tmp[0] = tl[0] + sgn*tr[0] - tmp[3] = tl[ldtl+1] + sgn*tr[0] - if tranl { - tmp[1] = tl[ldtl] - tmp[2] = tl[1] - } else { - tmp[1] = tl[1] - tmp[2] = tl[ldtl] - } - btmp[0] = b[0] - btmp[1] = b[ldb] - } - - // Solve 2×2 system using complete pivoting. - // Set pivots less than smin to smin. - - bi := blas64.Implementation() - ipiv := bi.Idamax(len(tmp), tmp[:], 1) - // Compute the upper triangular matrix [u11 u12]. - // [ 0 u22] - u11 := tmp[ipiv] - if math.Abs(u11) <= smin { - ok = false - u11 = smin - } - locu12 := [4]int{1, 0, 3, 2} // Index in tmp of the element on the same row as the pivot. - u12 := tmp[locu12[ipiv]] - locl21 := [4]int{2, 3, 0, 1} // Index in tmp of the element on the same column as the pivot. - l21 := tmp[locl21[ipiv]] / u11 - locu22 := [4]int{3, 2, 1, 0} // Index in tmp of the remaining element. - u22 := tmp[locu22[ipiv]] - l21*u12 - if math.Abs(u22) <= smin { - ok = false - u22 = smin - } - if ipiv&0x2 != 0 { // true for ipiv equal to 2 and 3. - // The pivot was in the second row, swap the elements of - // the right-hand side. - btmp[0], btmp[1] = btmp[1], btmp[0]-l21*btmp[1] - } else { - btmp[1] -= l21 * btmp[0] - } - scale = 1 - if 2*smlnum*math.Abs(btmp[1]) > math.Abs(u22) || 2*smlnum*math.Abs(btmp[0]) > math.Abs(u11) { - scale = 0.5 / math.Max(math.Abs(btmp[0]), math.Abs(btmp[1])) - btmp[0] *= scale - btmp[1] *= scale - } - // Solve the system [u11 u12] [x21] = [ btmp[0] ]. - // [ 0 u22] [x22] [ btmp[1] ] - x22 := btmp[1] / u22 - x21 := btmp[0]/u11 - (u12/u11)*x22 - if ipiv&0x1 != 0 { // true for ipiv equal to 1 and 3. - // The pivot was in the second column, swap the elements - // of the solution. - x21, x22 = x22, x21 - } - x[0] = x21 - if n1 == 1 { - x[1] = x22 - xnorm = math.Abs(x[0]) + math.Abs(x[1]) - } else { - x[ldx] = x22 - xnorm = math.Max(math.Abs(x[0]), math.Abs(x[ldx])) - } - return scale, xnorm, ok - } - - // 2×2 case: op[TL11 TL12]*[X11 X12] + SGN*[X11 X12]*op[TR11 TR12] = [B11 B12]. - // [TL21 TL22] [X21 X22] [X21 X22] [TR21 TR22] [B21 B22] - // - // Solve equivalent 4×4 system using complete pivoting. - // Set pivots less than smin to smin. - - smin := math.Max(math.Abs(tr[0]), math.Abs(tr[1])) - smin = math.Max(smin, math.Max(math.Abs(tr[ldtr]), math.Abs(tr[ldtr+1]))) - smin = math.Max(smin, math.Max(math.Abs(tl[0]), math.Abs(tl[1]))) - smin = math.Max(smin, math.Max(math.Abs(tl[ldtl]), math.Abs(tl[ldtl+1]))) - smin = math.Max(eps*smin, smlnum) - - var t [4][4]float64 - t[0][0] = tl[0] + sgn*tr[0] - t[1][1] = tl[0] + sgn*tr[ldtr+1] - t[2][2] = tl[ldtl+1] + sgn*tr[0] - t[3][3] = tl[ldtl+1] + sgn*tr[ldtr+1] - if tranl { - t[0][2] = tl[ldtl] - t[1][3] = tl[ldtl] - t[2][0] = tl[1] - t[3][1] = tl[1] - } else { - t[0][2] = tl[1] - t[1][3] = tl[1] - t[2][0] = tl[ldtl] - t[3][1] = tl[ldtl] - } - if tranr { - t[0][1] = sgn * tr[1] - t[1][0] = sgn * tr[ldtr] - t[2][3] = sgn * tr[1] - t[3][2] = sgn * tr[ldtr] - } else { - t[0][1] = sgn * tr[ldtr] - t[1][0] = sgn * tr[1] - t[2][3] = sgn * tr[ldtr] - t[3][2] = sgn * tr[1] - } - - var btmp [4]float64 - btmp[0] = b[0] - btmp[1] = b[1] - btmp[2] = b[ldb] - btmp[3] = b[ldb+1] - - // Perform elimination. - var jpiv [4]int // jpiv records any column swaps for pivoting. - for i := 0; i < 3; i++ { - var ( - xmax float64 - ipsv, jpsv int - ) - for ip := i; ip < 4; ip++ { - for jp := i; jp < 4; jp++ { - if math.Abs(t[ip][jp]) >= xmax { - xmax = math.Abs(t[ip][jp]) - ipsv = ip - jpsv = jp - } - } - } - if ipsv != i { - // The pivot is not in the top row of the unprocessed - // block, swap rows ipsv and i of t and btmp. - t[ipsv], t[i] = t[i], t[ipsv] - btmp[ipsv], btmp[i] = btmp[i], btmp[ipsv] - } - if jpsv != i { - // The pivot is not in the left column of the - // unprocessed block, swap columns jpsv and i of t. - for k := 0; k < 4; k++ { - t[k][jpsv], t[k][i] = t[k][i], t[k][jpsv] - } - } - jpiv[i] = jpsv - if math.Abs(t[i][i]) < smin { - ok = false - t[i][i] = smin - } - for k := i + 1; k < 4; k++ { - t[k][i] /= t[i][i] - btmp[k] -= t[k][i] * btmp[i] - for j := i + 1; j < 4; j++ { - t[k][j] -= t[k][i] * t[i][j] - } - } - } - if math.Abs(t[3][3]) < smin { - ok = false - t[3][3] = smin - } - scale = 1 - if 8*smlnum*math.Abs(btmp[0]) > math.Abs(t[0][0]) || - 8*smlnum*math.Abs(btmp[1]) > math.Abs(t[1][1]) || - 8*smlnum*math.Abs(btmp[2]) > math.Abs(t[2][2]) || - 8*smlnum*math.Abs(btmp[3]) > math.Abs(t[3][3]) { - - maxbtmp := math.Max(math.Abs(btmp[0]), math.Abs(btmp[1])) - maxbtmp = math.Max(maxbtmp, math.Max(math.Abs(btmp[2]), math.Abs(btmp[3]))) - scale = (1.0 / 8.0) / maxbtmp - btmp[0] *= scale - btmp[1] *= scale - btmp[2] *= scale - btmp[3] *= scale - } - // Compute the solution of the upper triangular system t * tmp = btmp. - var tmp [4]float64 - for i := 3; i >= 0; i-- { - temp := 1 / t[i][i] - tmp[i] = btmp[i] * temp - for j := i + 1; j < 4; j++ { - tmp[i] -= temp * t[i][j] * tmp[j] - } - } - for i := 2; i >= 0; i-- { - if jpiv[i] != i { - tmp[i], tmp[jpiv[i]] = tmp[jpiv[i]], tmp[i] - } - } - x[0] = tmp[0] - x[1] = tmp[1] - x[ldx] = tmp[2] - x[ldx+1] = tmp[3] - xnorm = math.Max(math.Abs(tmp[0])+math.Abs(tmp[1]), math.Abs(tmp[2])+math.Abs(tmp[3])) - return scale, xnorm, ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatbs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatbs.go deleted file mode 100644 index e0e809cf..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatbs.go +++ /dev/null @@ -1,454 +0,0 @@ -// Copyright ©2019 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlatbs solves a triangular banded system of equations -// -// A * x = s*b if trans == blas.NoTrans -// Aᵀ * x = s*b if trans == blas.Trans or blas.ConjTrans -// -// where A is an upper or lower triangular band matrix, x and b are n-element -// vectors, and s is a scaling factor chosen so that the components of x will be -// less than the overflow threshold. -// -// On entry, x contains the right-hand side b of the triangular system. -// On return, x is overwritten by the solution vector x. -// -// normin specifies whether the cnorm parameter contains the column norms of A on -// entry. If it is true, cnorm[j] contains the norm of the off-diagonal part of -// the j-th column of A. If it is false, the norms will be computed and stored -// in cnorm. -// -// Dlatbs returns the scaling factor s for the triangular system. If the matrix -// A is singular (A[j,j]==0 for some j), then scale is set to 0 and a -// non-trivial solution to A*x = 0 is returned. -// -// Dlatbs is an internal routine. It is exported for testing purposes. -func (Implementation) Dlatbs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, normin bool, n, kd int, ab []float64, ldab int, x, cnorm []float64) (scale float64) { - noTran := trans == blas.NoTrans - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case !noTran && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTrans) - case diag != blas.NonUnit && diag != blas.Unit: - panic(badDiag) - case n < 0: - panic(nLT0) - case kd < 0: - panic(kdLT0) - case ldab < kd+1: - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 1 - } - - switch { - case len(ab) < (n-1)*ldab+kd+1: - panic(shortAB) - case len(x) < n: - panic(shortX) - case len(cnorm) < n: - panic(shortCNorm) - } - - // Parameters to control overflow. - smlnum := dlamchS / dlamchP - bignum := 1 / smlnum - - bi := blas64.Implementation() - kld := max(1, ldab-1) - if !normin { - // Compute the 1-norm of each column, not including the diagonal. - if uplo == blas.Upper { - for j := 0; j < n; j++ { - jlen := min(j, kd) - if jlen > 0 { - cnorm[j] = bi.Dasum(jlen, ab[(j-jlen)*ldab+jlen:], kld) - } else { - cnorm[j] = 0 - } - } - } else { - for j := 0; j < n; j++ { - jlen := min(n-j-1, kd) - if jlen > 0 { - cnorm[j] = bi.Dasum(jlen, ab[(j+1)*ldab+kd-1:], kld) - } else { - cnorm[j] = 0 - } - } - } - } - - // Set up indices and increments for loops below. - var ( - jFirst, jLast, jInc int - maind int - ) - if noTran { - if uplo == blas.Upper { - jFirst = n - 1 - jLast = -1 - jInc = -1 - maind = 0 - } else { - jFirst = 0 - jLast = n - jInc = 1 - maind = kd - } - } else { - if uplo == blas.Upper { - jFirst = 0 - jLast = n - jInc = 1 - maind = 0 - } else { - jFirst = n - 1 - jLast = -1 - jInc = -1 - maind = kd - } - } - - // Scale the column norms by tscal if the maximum element in cnorm is - // greater than bignum. - tmax := cnorm[bi.Idamax(n, cnorm, 1)] - tscal := 1.0 - if tmax > bignum { - tscal = 1 / (smlnum * tmax) - bi.Dscal(n, tscal, cnorm, 1) - } - - // Compute a bound on the computed solution vector to see if the Level 2 - // BLAS routine Dtbsv can be used. - - xMax := math.Abs(x[bi.Idamax(n, x, 1)]) - xBnd := xMax - grow := 0.0 - // Compute the growth only if the maximum element in cnorm is NOT greater - // than bignum. - if tscal != 1 { - goto skipComputeGrow - } - if noTran { - // Compute the growth in A * x = b. - if diag == blas.NonUnit { - // A is non-unit triangular. - // - // Compute grow = 1/G_j and xBnd = 1/M_j. - // Initially, G_0 = max{x(i), i=1,...,n}. - grow = 1 / math.Max(xBnd, smlnum) - xBnd = grow - for j := jFirst; j != jLast; j += jInc { - if grow <= smlnum { - // Exit the loop because the growth factor is too small. - goto skipComputeGrow - } - // M_j = G_{j-1} / abs(A[j,j]) - tjj := math.Abs(ab[j*ldab+maind]) - xBnd = math.Min(xBnd, math.Min(1, tjj)*grow) - if tjj+cnorm[j] >= smlnum { - // G_j = G_{j-1}*( 1 + cnorm[j] / abs(A[j,j]) ) - grow *= tjj / (tjj + cnorm[j]) - } else { - // G_j could overflow, set grow to 0. - grow = 0 - } - } - grow = xBnd - } else { - // A is unit triangular. - // - // Compute grow = 1/G_j, where G_0 = max{x(i), i=1,...,n}. - grow = math.Min(1, 1/math.Max(xBnd, smlnum)) - for j := jFirst; j != jLast; j += jInc { - if grow <= smlnum { - // Exit the loop because the growth factor is too small. - goto skipComputeGrow - } - // G_j = G_{j-1}*( 1 + cnorm[j] ) - grow /= 1 + cnorm[j] - } - } - } else { - // Compute the growth in Aᵀ * x = b. - if diag == blas.NonUnit { - // A is non-unit triangular. - // - // Compute grow = 1/G_j and xBnd = 1/M_j. - // Initially, G_0 = max{x(i), i=1,...,n}. - grow = 1 / math.Max(xBnd, smlnum) - xBnd = grow - for j := jFirst; j != jLast; j += jInc { - if grow <= smlnum { - // Exit the loop because the growth factor is too small. - goto skipComputeGrow - } - // G_j = max( G_{j-1}, M_{j-1}*( 1 + cnorm[j] ) ) - xj := 1 + cnorm[j] - grow = math.Min(grow, xBnd/xj) - // M_j = M_{j-1}*( 1 + cnorm[j] ) / abs(A[j,j]) - tjj := math.Abs(ab[j*ldab+maind]) - if xj > tjj { - xBnd *= tjj / xj - } - } - grow = math.Min(grow, xBnd) - } else { - // A is unit triangular. - // - // Compute grow = 1/G_j, where G_0 = max{x(i), i=1,...,n}. - grow = math.Min(1, 1/math.Max(xBnd, smlnum)) - for j := jFirst; j != jLast; j += jInc { - if grow <= smlnum { - // Exit the loop because the growth factor is too small. - goto skipComputeGrow - } - // G_j = G_{j-1}*( 1 + cnorm[j] ) - grow /= 1 + cnorm[j] - } - } - } -skipComputeGrow: - - if grow*tscal > smlnum { - // The reciprocal of the bound on elements of X is not too small, use - // the Level 2 BLAS solve. - bi.Dtbsv(uplo, trans, diag, n, kd, ab, ldab, x, 1) - // Scale the column norms by 1/tscal for return. - if tscal != 1 { - bi.Dscal(n, 1/tscal, cnorm, 1) - } - return 1 - } - - // Use a Level 1 BLAS solve, scaling intermediate results. - - scale = 1 - if xMax > bignum { - // Scale x so that its components are less than or equal to bignum in - // absolute value. - scale = bignum / xMax - bi.Dscal(n, scale, x, 1) - xMax = bignum - } - - if noTran { - // Solve A * x = b. - for j := jFirst; j != jLast; j += jInc { - // Compute x[j] = b[j] / A[j,j], scaling x if necessary. - xj := math.Abs(x[j]) - tjjs := tscal - if diag == blas.NonUnit { - tjjs *= ab[j*ldab+maind] - } - tjj := math.Abs(tjjs) - switch { - case tjj > smlnum: - // smlnum < abs(A[j,j]) - if tjj < 1 && xj > tjj*bignum { - // Scale x by 1/b[j]. - rec := 1 / xj - bi.Dscal(n, rec, x, 1) - scale *= rec - xMax *= rec - } - x[j] /= tjjs - xj = math.Abs(x[j]) - case tjj > 0: - // 0 < abs(A[j,j]) <= smlnum - if xj > tjj*bignum { - // Scale x by (1/abs(x[j]))*abs(A[j,j])*bignum to avoid - // overflow when dividing by A[j,j]. - rec := tjj * bignum / xj - if cnorm[j] > 1 { - // Scale by 1/cnorm[j] to avoid overflow when - // multiplying x[j] times column j. - rec /= cnorm[j] - } - bi.Dscal(n, rec, x, 1) - scale *= rec - xMax *= rec - } - x[j] /= tjjs - xj = math.Abs(x[j]) - default: - // A[j,j] == 0: Set x[0:n] = 0, x[j] = 1, and scale = 0, and - // compute a solution to A*x = 0. - for i := range x[:n] { - x[i] = 0 - } - x[j] = 1 - xj = 1 - scale = 0 - xMax = 0 - } - - // Scale x if necessary to avoid overflow when adding a multiple of - // column j of A. - switch { - case xj > 1: - rec := 1 / xj - if cnorm[j] > (bignum-xMax)*rec { - // Scale x by 1/(2*abs(x[j])). - rec *= 0.5 - bi.Dscal(n, rec, x, 1) - scale *= rec - } - case xj*cnorm[j] > bignum-xMax: - // Scale x by 1/2. - bi.Dscal(n, 0.5, x, 1) - scale *= 0.5 - } - - if uplo == blas.Upper { - if j > 0 { - // Compute the update - // x[max(0,j-kd):j] := x[max(0,j-kd):j] - x[j] * A[max(0,j-kd):j,j] - jlen := min(j, kd) - if jlen > 0 { - bi.Daxpy(jlen, -x[j]*tscal, ab[(j-jlen)*ldab+jlen:], kld, x[j-jlen:], 1) - } - i := bi.Idamax(j, x, 1) - xMax = math.Abs(x[i]) - } - } else if j < n-1 { - // Compute the update - // x[j+1:min(j+kd,n)] := x[j+1:min(j+kd,n)] - x[j] * A[j+1:min(j+kd,n),j] - jlen := min(kd, n-j-1) - if jlen > 0 { - bi.Daxpy(jlen, -x[j]*tscal, ab[(j+1)*ldab+kd-1:], kld, x[j+1:], 1) - } - i := j + 1 + bi.Idamax(n-j-1, x[j+1:], 1) - xMax = math.Abs(x[i]) - } - } - } else { - // Solve Aᵀ * x = b. - for j := jFirst; j != jLast; j += jInc { - // Compute x[j] = b[j] - sum A[k,j]*x[k]. - // k!=j - xj := math.Abs(x[j]) - tjjs := tscal - if diag == blas.NonUnit { - tjjs *= ab[j*ldab+maind] - } - tjj := math.Abs(tjjs) - rec := 1 / math.Max(1, xMax) - uscal := tscal - if cnorm[j] > (bignum-xj)*rec { - // If x[j] could overflow, scale x by 1/(2*xMax). - rec *= 0.5 - if tjj > 1 { - // Divide by A[j,j] when scaling x if A[j,j] > 1. - rec = math.Min(1, rec*tjj) - uscal /= tjjs - } - if rec < 1 { - bi.Dscal(n, rec, x, 1) - scale *= rec - xMax *= rec - } - } - - var sumj float64 - if uscal == 1 { - // If the scaling needed for A in the dot product is 1, call - // Ddot to perform the dot product... - if uplo == blas.Upper { - jlen := min(j, kd) - if jlen > 0 { - sumj = bi.Ddot(jlen, ab[(j-jlen)*ldab+jlen:], kld, x[j-jlen:], 1) - } - } else { - jlen := min(n-j-1, kd) - if jlen > 0 { - sumj = bi.Ddot(jlen, ab[(j+1)*ldab+kd-1:], kld, x[j+1:], 1) - } - } - } else { - // ...otherwise, use in-line code for the dot product. - if uplo == blas.Upper { - jlen := min(j, kd) - for i := 0; i < jlen; i++ { - sumj += (ab[(j-jlen+i)*ldab+jlen-i] * uscal) * x[j-jlen+i] - } - } else { - jlen := min(n-j-1, kd) - for i := 0; i < jlen; i++ { - sumj += (ab[(j+1+i)*ldab+kd-1-i] * uscal) * x[j+i+1] - } - } - } - - if uscal == tscal { - // Compute x[j] := ( x[j] - sumj ) / A[j,j] - // if 1/A[j,j] was not used to scale the dot product. - x[j] -= sumj - xj = math.Abs(x[j]) - // Compute x[j] = x[j] / A[j,j], scaling if necessary. - // Note: the reference implementation skips this step for blas.Unit matrices - // when tscal is equal to 1 but it complicates the logic and only saves - // the comparison and division in the first switch-case. Not skipping it - // is also consistent with the NoTrans case above. - switch { - case tjj > smlnum: - // smlnum < abs(A[j,j]): - if tjj < 1 && xj > tjj*bignum { - // Scale x by 1/abs(x[j]). - rec := 1 / xj - bi.Dscal(n, rec, x, 1) - scale *= rec - xMax *= rec - } - x[j] /= tjjs - case tjj > 0: - // 0 < abs(A[j,j]) <= smlnum: - if xj > tjj*bignum { - // Scale x by (1/abs(x[j]))*abs(A[j,j])*bignum. - rec := (tjj * bignum) / xj - bi.Dscal(n, rec, x, 1) - scale *= rec - xMax *= rec - } - x[j] /= tjjs - default: - // A[j,j] == 0: Set x[0:n] = 0, x[j] = 1, and scale = 0, and - // compute a solution Aᵀ * x = 0. - for i := range x[:n] { - x[i] = 0 - } - x[j] = 1 - scale = 0 - xMax = 0 - } - } else { - // Compute x[j] := x[j] / A[j,j] - sumj - // if the dot product has already been divided by 1/A[j,j]. - x[j] = x[j]/tjjs - sumj - } - xMax = math.Max(xMax, math.Abs(x[j])) - } - scale /= tscal - } - - // Scale the column norms by 1/tscal for return. - if tscal != 1 { - bi.Dscal(n, 1/tscal, cnorm, 1) - } - return scale -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatdf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatdf.go deleted file mode 100644 index 83422912..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatdf.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlatdf computes a contribution to the reciprocal Dif-estimate by solving -// -// Z * x = h - f -// -// and choosing the vector h such that the norm of x is as large as possible. -// -// The n×n matrix Z is represented by its LU factorization as computed by Dgetc2 -// and has the form -// -// Z = P * L * U * Q -// -// where P and Q are permutation matrices, L is lower triangular with unit -// diagonal elements and U is upper triangular. -// -// job specifies the heuristic method for computing the contribution. -// -// If job is lapack.LocalLookAhead, all entries of h are chosen as either +1 or -// -1. -// -// If job is lapack.NormalizedNullVector, an approximate null-vector e of Z is -// computed using Dgecon and normalized. h is chosen as ±e with the sign giving -// the greater value of 2-norm(x). This strategy is about 5 times as expensive -// as LocalLookAhead. -// -// On entry, rhs holds the contribution f from earlier solved sub-systems. On -// return, rhs holds the solution x. -// -// ipiv and jpiv contain the pivot indices as returned by Dgetc2: row i of the -// matrix has been interchanged with row ipiv[i] and column j of the matrix has -// been interchanged with column jpiv[j]. -// -// n must be at most 8, ipiv and jpiv must have length n, and rhs must have -// length at least n, otherwise Dlatdf will panic. -// -// rdsum and rdscal represent the sum of squares of computed contributions to -// the Dif-estimate from earlier solved sub-systems. rdscal is the scaling -// factor used to prevent overflow in rdsum. Dlatdf returns this sum of squares -// updated with the contributions from the current sub-system. -// -// Dlatdf is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlatdf(job lapack.MaximizeNormXJob, n int, z []float64, ldz int, rhs []float64, rdsum, rdscal float64, ipiv, jpiv []int) (scale, sum float64) { - switch { - case job != lapack.LocalLookAhead && job != lapack.NormalizedNullVector: - panic(badMaximizeNormXJob) - case n < 0: - panic(nLT0) - case n > 8: - panic("lapack: n > 8") - case ldz < max(1, n): - panic(badLdZ) - } - - // Quick return if possible. - if n == 0 { - return - } - - switch { - case len(z) < (n-1)*ldz+n: - panic(shortZ) - case len(rhs) < n: - panic(shortRHS) - case len(ipiv) != n: - panic(badLenIpiv) - case len(jpiv) != n: - panic(badLenJpiv) - } - - const maxdim = 8 - var ( - xps [maxdim]float64 - xms [maxdim]float64 - work [4 * maxdim]float64 - iwork [maxdim]int - ) - bi := blas64.Implementation() - xp := xps[:n] - xm := xms[:n] - if job == lapack.NormalizedNullVector { - // Compute approximate nullvector xm of Z. - _ = impl.Dgecon(lapack.MaxRowSum, n, z, ldz, 1, work[:], iwork[:]) - // This relies on undocumented content in work[n:2*n] stored by Dgecon. - bi.Dcopy(n, work[n:], 1, xm, 1) - - // Compute rhs. - impl.Dlaswp(1, xm, 1, 0, n-2, ipiv[:n-1], -1) - tmp := 1 / bi.Dnrm2(n, xm, 1) - bi.Dscal(n, tmp, xm, 1) - bi.Dcopy(n, xm, 1, xp, 1) - bi.Daxpy(n, 1, rhs, 1, xp, 1) - bi.Daxpy(n, -1.0, xm, 1, rhs, 1) - _ = impl.Dgesc2(n, z, ldz, rhs, ipiv, jpiv) - _ = impl.Dgesc2(n, z, ldz, xp, ipiv, jpiv) - if bi.Dasum(n, xp, 1) > bi.Dasum(n, rhs, 1) { - bi.Dcopy(n, xp, 1, rhs, 1) - } - - // Compute and return the updated sum of squares. - return impl.Dlassq(n, rhs, 1, rdscal, rdsum) - } - - // Apply permutations ipiv to rhs - impl.Dlaswp(1, rhs, 1, 0, n-2, ipiv[:n-1], 1) - - // Solve for L-part choosing rhs either to +1 or -1. - pmone := -1.0 - for j := 0; j < n-2; j++ { - bp := rhs[j] + 1 - bm := rhs[j] - 1 - - // Look-ahead for L-part rhs[0:n-2] = +1 or -1, splus and sminu computed - // more efficiently than in https://doi.org/10.1109/9.29404. - splus := 1 + bi.Ddot(n-j-1, z[(j+1)*ldz+j:], ldz, z[(j+1)*ldz+j:], ldz) - sminu := bi.Ddot(n-j-1, z[(j+1)*ldz+j:], ldz, rhs[j+1:], 1) - splus *= rhs[j] - switch { - case splus > sminu: - rhs[j] = bp - case sminu > splus: - rhs[j] = bm - default: - // In this case the updating sums are equal and we can choose rsh[j] - // +1 or -1. The first time this happens we choose -1, thereafter - // +1. This is a simple way to get good estimates of matrices like - // Byers well-known example (see https://doi.org/10.1109/9.29404). - rhs[j] += pmone - pmone = 1 - } - - // Compute remaining rhs. - bi.Daxpy(n-j-1, -rhs[j], z[(j+1)*ldz+j:], ldz, rhs[j+1:], 1) - } - - // Solve for U-part, look-ahead for rhs[n-1] = ±1. This is not done in - // Bsolve and will hopefully give us a better estimate because any - // ill-conditioning of the original matrix is transferred to U and not to L. - // U[n-1,n-1] is an approximation to sigma_min(LU). - bi.Dcopy(n-1, rhs, 1, xp, 1) - xp[n-1] = rhs[n-1] + 1 - rhs[n-1] -= 1 - var splus, sminu float64 - for i := n - 1; i >= 0; i-- { - tmp := 1 / z[i*ldz+i] - xp[i] *= tmp - rhs[i] *= tmp - for k := i + 1; k < n; k++ { - xp[i] -= xp[k] * (z[i*ldz+k] * tmp) - rhs[i] -= rhs[k] * (z[i*ldz+k] * tmp) - } - splus += math.Abs(xp[i]) - sminu += math.Abs(rhs[i]) - } - if splus > sminu { - bi.Dcopy(n, xp, 1, rhs, 1) - } - - // Apply the permutations jpiv to the computed solution (rhs). - impl.Dlaswp(1, rhs, 1, 0, n-2, jpiv[:n-1], -1) - - // Compute and return the updated sum of squares. - return impl.Dlassq(n, rhs, 1, rdscal, rdsum) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go deleted file mode 100644 index 195be09c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlatrd reduces nb rows and columns of a real n×n symmetric matrix A to symmetric -// tridiagonal form. It computes the orthonormal similarity transformation -// -// Qᵀ * A * Q -// -// and returns the matrices V and W to apply to the unreduced part of A. If -// uplo == blas.Upper, the upper triangle is supplied and the last nb rows are -// reduced. If uplo == blas.Lower, the lower triangle is supplied and the first -// nb rows are reduced. -// -// a contains the symmetric matrix on entry with active triangular half specified -// by uplo. On exit, the nb columns have been reduced to tridiagonal form. The -// diagonal contains the diagonal of the reduced matrix, the off-diagonal is -// set to 1, and the remaining elements contain the data to construct Q. -// -// If uplo == blas.Upper, with n = 5 and nb = 2 on exit a is -// -// [ a a a v4 v5] -// [ a a v4 v5] -// [ a 1 v5] -// [ d 1] -// [ d] -// -// If uplo == blas.Lower, with n = 5 and nb = 2, on exit a is -// -// [ d ] -// [ 1 d ] -// [v1 1 a ] -// [v1 v2 a a ] -// [v1 v2 a a a] -// -// e contains the superdiagonal elements of the reduced matrix. If uplo == blas.Upper, -// e[n-nb:n-1] contains the last nb columns of the reduced matrix, while if -// uplo == blas.Lower, e[:nb] contains the first nb columns of the reduced matrix. -// e must have length at least n-1, and Dlatrd will panic otherwise. -// -// tau contains the scalar factors of the elementary reflectors needed to construct Q. -// The reflectors are stored in tau[n-nb:n-1] if uplo == blas.Upper, and in -// tau[:nb] if uplo == blas.Lower. tau must have length n-1, and Dlatrd will panic -// otherwise. -// -// w is an n×nb matrix. On exit it contains the data to update the unreduced part -// of A. -// -// The matrix Q is represented as a product of elementary reflectors. Each reflector -// H has the form -// -// I - tau * v * vᵀ -// -// If uplo == blas.Upper, -// -// Q = H_{n-1} * H_{n-2} * ... * H_{n-nb} -// -// where v[:i-1] is stored in A[:i-1,i], v[i-1] = 1, and v[i:n] = 0. -// -// If uplo == blas.Lower, -// -// Q = H_0 * H_1 * ... * H_{nb-1} -// -// where v[:i+1] = 0, v[i+1] = 1, and v[i+2:n] is stored in A[i+2:n,i]. -// -// The vectors v form the n×nb matrix V which is used with W to apply a -// symmetric rank-2 update to the unreduced part of A -// -// A = A - V * Wᵀ - W * Vᵀ -// -// Dlatrd is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlatrd(uplo blas.Uplo, n, nb int, a []float64, lda int, e, tau, w []float64, ldw int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case nb < 0: - panic(nbLT0) - case nb > n: - panic(nbGTN) - case lda < max(1, n): - panic(badLdA) - case ldw < max(1, nb): - panic(badLdW) - } - - if n == 0 { - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(w) < (n-1)*ldw+nb: - panic(shortW) - case len(e) < n-1: - panic(shortE) - case len(tau) < n-1: - panic(shortTau) - } - - bi := blas64.Implementation() - - if uplo == blas.Upper { - for i := n - 1; i >= n-nb; i-- { - iw := i - n + nb - if i < n-1 { - // Update A(0:i, i). - bi.Dgemv(blas.NoTrans, i+1, n-i-1, -1, a[i+1:], lda, - w[i*ldw+iw+1:], 1, 1, a[i:], lda) - bi.Dgemv(blas.NoTrans, i+1, n-i-1, -1, w[iw+1:], ldw, - a[i*lda+i+1:], 1, 1, a[i:], lda) - } - if i > 0 { - // Generate elementary reflector H_i to annihilate A(0:i-2,i). - e[i-1], tau[i-1] = impl.Dlarfg(i, a[(i-1)*lda+i], a[i:], lda) - a[(i-1)*lda+i] = 1 - - // Compute W(0:i-1, i). - bi.Dsymv(blas.Upper, i, 1, a, lda, a[i:], lda, 0, w[iw:], ldw) - if i < n-1 { - bi.Dgemv(blas.Trans, i, n-i-1, 1, w[iw+1:], ldw, - a[i:], lda, 0, w[(i+1)*ldw+iw:], ldw) - bi.Dgemv(blas.NoTrans, i, n-i-1, -1, a[i+1:], lda, - w[(i+1)*ldw+iw:], ldw, 1, w[iw:], ldw) - bi.Dgemv(blas.Trans, i, n-i-1, 1, a[i+1:], lda, - a[i:], lda, 0, w[(i+1)*ldw+iw:], ldw) - bi.Dgemv(blas.NoTrans, i, n-i-1, -1, w[iw+1:], ldw, - w[(i+1)*ldw+iw:], ldw, 1, w[iw:], ldw) - } - bi.Dscal(i, tau[i-1], w[iw:], ldw) - alpha := -0.5 * tau[i-1] * bi.Ddot(i, w[iw:], ldw, a[i:], lda) - bi.Daxpy(i, alpha, a[i:], lda, w[iw:], ldw) - } - } - } else { - // Reduce first nb columns of lower triangle. - for i := 0; i < nb; i++ { - // Update A(i:n, i) - bi.Dgemv(blas.NoTrans, n-i, i, -1, a[i*lda:], lda, - w[i*ldw:], 1, 1, a[i*lda+i:], lda) - bi.Dgemv(blas.NoTrans, n-i, i, -1, w[i*ldw:], ldw, - a[i*lda:], 1, 1, a[i*lda+i:], lda) - if i < n-1 { - // Generate elementary reflector H_i to annihilate A(i+2:n,i). - e[i], tau[i] = impl.Dlarfg(n-i-1, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) - a[(i+1)*lda+i] = 1 - - // Compute W(i+1:n,i). - bi.Dsymv(blas.Lower, n-i-1, 1, a[(i+1)*lda+i+1:], lda, - a[(i+1)*lda+i:], lda, 0, w[(i+1)*ldw+i:], ldw) - bi.Dgemv(blas.Trans, n-i-1, i, 1, w[(i+1)*ldw:], ldw, - a[(i+1)*lda+i:], lda, 0, w[i:], ldw) - bi.Dgemv(blas.NoTrans, n-i-1, i, -1, a[(i+1)*lda:], lda, - w[i:], ldw, 1, w[(i+1)*ldw+i:], ldw) - bi.Dgemv(blas.Trans, n-i-1, i, 1, a[(i+1)*lda:], lda, - a[(i+1)*lda+i:], lda, 0, w[i:], ldw) - bi.Dgemv(blas.NoTrans, n-i-1, i, -1, w[(i+1)*ldw:], ldw, - w[i:], ldw, 1, w[(i+1)*ldw+i:], ldw) - bi.Dscal(n-i-1, tau[i], w[(i+1)*ldw+i:], ldw) - alpha := -0.5 * tau[i] * bi.Ddot(n-i-1, w[(i+1)*ldw+i:], ldw, - a[(i+1)*lda+i:], lda) - bi.Daxpy(n-i-1, alpha, a[(i+1)*lda+i:], lda, - w[(i+1)*ldw+i:], ldw) - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go deleted file mode 100644 index f13b7d57..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dlatrs solves a triangular system of equations scaled to prevent overflow. It -// solves -// -// A * x = scale * b if trans == blas.NoTrans -// Aᵀ * x = scale * b if trans == blas.Trans -// -// where the scale s is set for numeric stability. -// -// A is an n×n triangular matrix. On entry, the slice x contains the values of -// b, and on exit it contains the solution vector x. -// -// If normin == true, cnorm is an input and cnorm[j] contains the norm of the off-diagonal -// part of the j^th column of A. If trans == blas.NoTrans, cnorm[j] must be greater -// than or equal to the infinity norm, and greater than or equal to the one-norm -// otherwise. If normin == false, then cnorm is treated as an output, and is set -// to contain the 1-norm of the off-diagonal part of the j^th column of A. -// -// Dlatrs is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dlatrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, normin bool, n int, a []float64, lda int, x []float64, cnorm []float64) (scale float64) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTrans) - case diag != blas.Unit && diag != blas.NonUnit: - panic(badDiag) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 1 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(x) < n: - panic(shortX) - case len(cnorm) < n: - panic(shortCNorm) - } - - upper := uplo == blas.Upper - nonUnit := diag == blas.NonUnit - - smlnum := dlamchS / dlamchP - bignum := 1 / smlnum - scale = 1 - - bi := blas64.Implementation() - - if !normin { - if upper { - cnorm[0] = 0 - for j := 1; j < n; j++ { - cnorm[j] = bi.Dasum(j, a[j:], lda) - } - } else { - for j := 0; j < n-1; j++ { - cnorm[j] = bi.Dasum(n-j-1, a[(j+1)*lda+j:], lda) - } - cnorm[n-1] = 0 - } - } - // Scale the column norms by tscal if the maximum element in cnorm is greater than bignum. - imax := bi.Idamax(n, cnorm, 1) - var tscal float64 - if cnorm[imax] <= bignum { - tscal = 1 - } else { - tmax := cnorm[imax] - // Avoid NaN generation if entries in cnorm exceed the overflow - // threshold. - if tmax <= math.MaxFloat64 { - // Case 1: All entries in cnorm are valid floating-point numbers. - tscal = 1 / (smlnum * tmax) - bi.Dscal(n, tscal, cnorm, 1) - } else { - // Case 2: At least one column norm of A cannot be represented as - // floating-point number. Find the offdiagonal entry A[i,j] with the - // largest absolute value. If this entry is not +/- Infinity, use - // this value as tscal. - tmax = 0 - if upper { - // A is upper triangular. - for j := 1; j < n; j++ { - tmax = math.Max(impl.Dlange(lapack.MaxAbs, j, 1, a[j:], lda, nil), tmax) - } - } else { - // A is lower triangular. - for j := 0; j < n-1; j++ { - tmax = math.Max(impl.Dlange(lapack.MaxAbs, n-j-1, 1, a[(j+1)*lda+j:], lda, nil), tmax) - } - } - if tmax <= math.MaxFloat64 { - tscal = 1 / (smlnum * tmax) - for j := 0; j < n; j++ { - if cnorm[j] <= math.MaxFloat64 { - cnorm[j] *= tscal - } else { - // Recompute the 1-norm without introducing Infinity in - // the summation. - cnorm[j] = 0 - if upper { - for i := 0; i < j; i++ { - cnorm[j] += tscal * math.Abs(a[i*lda+j]) - } - } else { - for i := j + 1; i < n; i++ { - cnorm[j] += tscal * math.Abs(a[i*lda+j]) - } - } - } - } - } else { - // At least one entry of A is not a valid floating-point entry. - // Rely on Dtrsv to propagate Inf and NaN. - bi.Dtrsv(uplo, trans, diag, n, a, lda, x, 1) - return - } - } - } - - // Compute a bound on the computed solution vector to see if bi.Dtrsv can be used. - j := bi.Idamax(n, x, 1) - xmax := math.Abs(x[j]) - xbnd := xmax - var grow float64 - var jfirst, jlast, jinc int - if trans == blas.NoTrans { - if upper { - jfirst = n - 1 - jlast = -1 - jinc = -1 - } else { - jfirst = 0 - jlast = n - jinc = 1 - } - // Compute the growth in A * x = b. - if tscal != 1 { - grow = 0 - goto Solve - } - if nonUnit { - grow = 1 / math.Max(xbnd, smlnum) - xbnd = grow - for j := jfirst; j != jlast; j += jinc { - if grow <= smlnum { - goto Solve - } - tjj := math.Abs(a[j*lda+j]) - xbnd = math.Min(xbnd, math.Min(1, tjj)*grow) - if tjj+cnorm[j] >= smlnum { - grow *= tjj / (tjj + cnorm[j]) - } else { - grow = 0 - } - } - grow = xbnd - } else { - grow = math.Min(1, 1/math.Max(xbnd, smlnum)) - for j := jfirst; j != jlast; j += jinc { - if grow <= smlnum { - goto Solve - } - grow *= 1 / (1 + cnorm[j]) - } - } - } else { - if upper { - jfirst = 0 - jlast = n - jinc = 1 - } else { - jfirst = n - 1 - jlast = -1 - jinc = -1 - } - if tscal != 1 { - grow = 0 - goto Solve - } - if nonUnit { - grow = 1 / (math.Max(xbnd, smlnum)) - xbnd = grow - for j := jfirst; j != jlast; j += jinc { - if grow <= smlnum { - goto Solve - } - xj := 1 + cnorm[j] - grow = math.Min(grow, xbnd/xj) - tjj := math.Abs(a[j*lda+j]) - if xj > tjj { - xbnd *= tjj / xj - } - } - grow = math.Min(grow, xbnd) - } else { - grow = math.Min(1, 1/math.Max(xbnd, smlnum)) - for j := jfirst; j != jlast; j += jinc { - if grow <= smlnum { - goto Solve - } - xj := 1 + cnorm[j] - grow /= xj - } - } - } - -Solve: - if grow*tscal > smlnum { - // Use the Level 2 BLAS solve if the reciprocal of the bound on - // elements of X is not too small. - bi.Dtrsv(uplo, trans, diag, n, a, lda, x, 1) - if tscal != 1 { - bi.Dscal(n, 1/tscal, cnorm, 1) - } - return scale - } - - // Use a Level 1 BLAS solve, scaling intermediate results. - if xmax > bignum { - scale = bignum / xmax - bi.Dscal(n, scale, x, 1) - xmax = bignum - } - if trans == blas.NoTrans { - for j := jfirst; j != jlast; j += jinc { - xj := math.Abs(x[j]) - var tjj, tjjs float64 - if nonUnit { - tjjs = a[j*lda+j] * tscal - } else { - tjjs = tscal - if tscal == 1 { - goto Skip1 - } - } - tjj = math.Abs(tjjs) - if tjj > smlnum { - if tjj < 1 { - if xj > tjj*bignum { - rec := 1 / xj - bi.Dscal(n, rec, x, 1) - scale *= rec - xmax *= rec - } - } - x[j] /= tjjs - xj = math.Abs(x[j]) - } else if tjj > 0 { - if xj > tjj*bignum { - rec := (tjj * bignum) / xj - if cnorm[j] > 1 { - rec /= cnorm[j] - } - bi.Dscal(n, rec, x, 1) - scale *= rec - xmax *= rec - } - x[j] /= tjjs - xj = math.Abs(x[j]) - } else { - for i := 0; i < n; i++ { - x[i] = 0 - } - x[j] = 1 - xj = 1 - scale = 0 - xmax = 0 - } - Skip1: - if xj > 1 { - rec := 1 / xj - if cnorm[j] > (bignum-xmax)*rec { - rec *= 0.5 - bi.Dscal(n, rec, x, 1) - scale *= rec - } - } else if xj*cnorm[j] > bignum-xmax { - bi.Dscal(n, 0.5, x, 1) - scale *= 0.5 - } - if upper { - if j > 0 { - bi.Daxpy(j, -x[j]*tscal, a[j:], lda, x, 1) - i := bi.Idamax(j, x, 1) - xmax = math.Abs(x[i]) - } - } else { - if j < n-1 { - bi.Daxpy(n-j-1, -x[j]*tscal, a[(j+1)*lda+j:], lda, x[j+1:], 1) - i := j + bi.Idamax(n-j-1, x[j+1:], 1) - xmax = math.Abs(x[i]) - } - } - } - } else { - for j := jfirst; j != jlast; j += jinc { - xj := math.Abs(x[j]) - uscal := tscal - rec := 1 / math.Max(xmax, 1) - var tjjs float64 - if cnorm[j] > (bignum-xj)*rec { - rec *= 0.5 - if nonUnit { - tjjs = a[j*lda+j] * tscal - } else { - tjjs = tscal - } - tjj := math.Abs(tjjs) - if tjj > 1 { - rec = math.Min(1, rec*tjj) - uscal /= tjjs - } - if rec < 1 { - bi.Dscal(n, rec, x, 1) - scale *= rec - xmax *= rec - } - } - var sumj float64 - if uscal == 1 { - if upper { - sumj = bi.Ddot(j, a[j:], lda, x, 1) - } else if j < n-1 { - sumj = bi.Ddot(n-j-1, a[(j+1)*lda+j:], lda, x[j+1:], 1) - } - } else { - if upper { - for i := 0; i < j; i++ { - sumj += (a[i*lda+j] * uscal) * x[i] - } - } else if j < n { - for i := j + 1; i < n; i++ { - sumj += (a[i*lda+j] * uscal) * x[i] - } - } - } - if uscal == tscal { - x[j] -= sumj - xj := math.Abs(x[j]) - var tjjs float64 - if nonUnit { - tjjs = a[j*lda+j] * tscal - } else { - tjjs = tscal - if tscal == 1 { - goto Skip2 - } - } - tjj := math.Abs(tjjs) - if tjj > smlnum { - if tjj < 1 { - if xj > tjj*bignum { - rec = 1 / xj - bi.Dscal(n, rec, x, 1) - scale *= rec - xmax *= rec - } - } - x[j] /= tjjs - } else if tjj > 0 { - if xj > tjj*bignum { - rec = (tjj * bignum) / xj - bi.Dscal(n, rec, x, 1) - scale *= rec - xmax *= rec - } - x[j] /= tjjs - } else { - for i := 0; i < n; i++ { - x[i] = 0 - } - x[j] = 1 - scale = 0 - xmax = 0 - } - } else { - x[j] = x[j]/tjjs - sumj - } - Skip2: - xmax = math.Max(xmax, math.Abs(x[j])) - } - } - scale /= tscal - if tscal != 1 { - bi.Dscal(n, 1/tscal, cnorm, 1) - } - return scale -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go deleted file mode 100644 index b70a8420..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright ©2018 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlauu2 computes the product -// -// U * Uᵀ if uplo is blas.Upper -// Lᵀ * L if uplo is blas.Lower -// -// where U or L is stored in the upper or lower triangular part of A. -// Only the upper or lower triangle of the result is stored, overwriting -// the corresponding factor in A. -func (impl Implementation) Dlauu2(uplo blas.Uplo, n int, a []float64, lda int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - bi := blas64.Implementation() - - if uplo == blas.Upper { - // Compute the product U*Uᵀ. - for i := 0; i < n; i++ { - aii := a[i*lda+i] - if i < n-1 { - a[i*lda+i] = bi.Ddot(n-i, a[i*lda+i:], 1, a[i*lda+i:], 1) - bi.Dgemv(blas.NoTrans, i, n-i-1, 1, a[i+1:], lda, a[i*lda+i+1:], 1, - aii, a[i:], lda) - } else { - bi.Dscal(i+1, aii, a[i:], lda) - } - } - } else { - // Compute the product Lᵀ*L. - for i := 0; i < n; i++ { - aii := a[i*lda+i] - if i < n-1 { - a[i*lda+i] = bi.Ddot(n-i, a[i*lda+i:], lda, a[i*lda+i:], lda) - bi.Dgemv(blas.Trans, n-i-1, i, 1, a[(i+1)*lda:], lda, a[(i+1)*lda+i:], lda, - aii, a[i*lda:], 1) - } else { - bi.Dscal(i+1, aii, a[i*lda:], 1) - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go deleted file mode 100644 index 575ed7c8..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright ©2018 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dlauum computes the product -// -// U * Uᵀ if uplo is blas.Upper -// Lᵀ * L if uplo is blas.Lower -// -// where U or L is stored in the upper or lower triangular part of A. -// Only the upper or lower triangle of the result is stored, overwriting -// the corresponding factor in A. -func (impl Implementation) Dlauum(uplo blas.Uplo, n int, a []float64, lda int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - // Determine the block size. - opts := "U" - if uplo == blas.Lower { - opts = "L" - } - nb := impl.Ilaenv(1, "DLAUUM", opts, n, -1, -1, -1) - - if nb <= 1 || n <= nb { - // Use unblocked code. - impl.Dlauu2(uplo, n, a, lda) - return - } - - // Use blocked code. - bi := blas64.Implementation() - if uplo == blas.Upper { - // Compute the product U*Uᵀ. - for i := 0; i < n; i += nb { - ib := min(nb, n-i) - bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.NonUnit, - i, ib, 1, a[i*lda+i:], lda, a[i:], lda) - impl.Dlauu2(blas.Upper, ib, a[i*lda+i:], lda) - if n-i-ib > 0 { - bi.Dgemm(blas.NoTrans, blas.Trans, i, ib, n-i-ib, - 1, a[i+ib:], lda, a[i*lda+i+ib:], lda, 1, a[i:], lda) - bi.Dsyrk(blas.Upper, blas.NoTrans, ib, n-i-ib, - 1, a[i*lda+i+ib:], lda, 1, a[i*lda+i:], lda) - } - } - } else { - // Compute the product Lᵀ*L. - for i := 0; i < n; i += nb { - ib := min(nb, n-i) - bi.Dtrmm(blas.Left, blas.Lower, blas.Trans, blas.NonUnit, - ib, i, 1, a[i*lda+i:], lda, a[i*lda:], lda) - impl.Dlauu2(blas.Lower, ib, a[i*lda+i:], lda) - if n-i-ib > 0 { - bi.Dgemm(blas.Trans, blas.NoTrans, ib, i, n-i-ib, - 1, a[(i+ib)*lda+i:], lda, a[(i+ib)*lda:], lda, 1, a[i*lda:], lda) - bi.Dsyrk(blas.Lower, blas.Trans, ib, n-i-ib, - 1, a[(i+ib)*lda+i:], lda, 1, a[i*lda+i:], lda) - } - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go deleted file mode 100644 index 087f63cc..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum is a pure-go implementation of the LAPACK API. The LAPACK API defines -// a set of algorithms for advanced matrix operations. -// -// The function definitions and implementations follow that of the netlib reference -// implementation. See http://www.netlib.org/lapack/explore-html/ for more -// information, and http://www.netlib.org/lapack/explore-html/d4/de1/_l_i_c_e_n_s_e_source.html -// for more license information. -// -// Slice function arguments frequently represent vectors and matrices. The data -// layout is identical to that found in https://pkg.go.dev/gonum.org/v1/gonum/blas/gonum. -// -// Most LAPACK functions are built on top the routines defined in the BLAS API, -// and as such the computation time for many LAPACK functions is -// dominated by BLAS calls. Here, BLAS is accessed through the -// blas64 package (https://pkg.go.dev/gonum.org/v1/gonum/blas/blas64). In particular, -// this implies that an external BLAS library will be used if it is -// registered in blas64. -// -// The full LAPACK capability has not been implemented at present. The full -// API is very large, containing approximately 200 functions for double precision -// alone. Future additions will be focused on supporting the Gonum matrix -// package (https://pkg.go.dev/gonum.org/v1/gonum/mat), though pull requests -// with implementations and tests for LAPACK function are encouraged. -package gonum // import "gonum.org/v1/gonum/lapack/gonum" diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go deleted file mode 100644 index fdb37af2..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dorg2l generates an m×n matrix Q with orthonormal columns which is defined -// as the last n columns of a product of k elementary reflectors of order m. -// -// Q = H_{k-1} * ... * H_1 * H_0 -// -// See Dgelqf for more information. It must be that m >= n >= k. -// -// tau contains the scalar reflectors computed by Dgeqlf. tau must have length -// at least k, and Dorg2l will panic otherwise. -// -// work contains temporary memory, and must have length at least n. Dorg2l will -// panic otherwise. -// -// Dorg2l is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case n > m: - panic(nGTM) - case k < 0: - panic(kLT0) - case k > n: - panic(kGTN) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - case len(work) < n: - panic(shortWork) - } - - // Initialize columns 0:n-k to columns of the unit matrix. - for j := 0; j < n-k; j++ { - for l := 0; l < m; l++ { - a[l*lda+j] = 0 - } - a[(m-n+j)*lda+j] = 1 - } - - bi := blas64.Implementation() - for i := 0; i < k; i++ { - ii := n - k + i - - // Apply H_i to A[0:m-k+i, 0:n-k+i] from the left. - a[(m-n+ii)*lda+ii] = 1 - impl.Dlarf(blas.Left, m-n+ii+1, ii, a[ii:], lda, tau[i], a, lda, work) - bi.Dscal(m-n+ii, -tau[i], a[ii:], lda) - a[(m-n+ii)*lda+ii] = 1 - tau[i] - - // Set A[m-k+i:m, n-k+i+1] to zero. - for l := m - n + ii + 1; l < m; l++ { - a[l*lda+ii] = 0 - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go deleted file mode 100644 index c56f24cb..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dorg2r generates an m×n matrix Q with orthonormal columns defined by the -// product of elementary reflectors as computed by Dgeqrf. -// -// Q = H_0 * H_1 * ... * H_{k-1} -// -// len(tau) = k, 0 <= k <= n, 0 <= n <= m, len(work) >= n. -// Dorg2r will panic if these conditions are not met. -// -// Dorg2r is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case n > m: - panic(nGTM) - case k < 0: - panic(kLT0) - case k > n: - panic(kGTN) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) != k: - panic(badLenTau) - case len(work) < n: - panic(shortWork) - } - - bi := blas64.Implementation() - - // Initialize columns k+1:n to columns of the unit matrix. - for l := 0; l < m; l++ { - for j := k; j < n; j++ { - a[l*lda+j] = 0 - } - } - for j := k; j < n; j++ { - a[j*lda+j] = 1 - } - for i := k - 1; i >= 0; i-- { - for i := range work { - work[i] = 0 - } - if i < n-1 { - a[i*lda+i] = 1 - impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tau[i], a[i*lda+i+1:], lda, work) - } - if i < m-1 { - bi.Dscal(m-i-1, -tau[i], a[(i+1)*lda+i:], lda) - } - a[i*lda+i] = 1 - tau[i] - for l := 0; l < i; l++ { - a[l*lda+i] = 0 - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go deleted file mode 100644 index 35535100..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/lapack" - -// Dorgbr generates one of the matrices Q or Pᵀ computed by Dgebrd -// computed from the decomposition Dgebrd. See Dgebd2 for the description of -// Q and Pᵀ. -// -// If vect == lapack.GenerateQ, then a is assumed to have been an m×k matrix and -// Q is of order m. If m >= k, then Dorgbr returns the first n columns of Q -// where m >= n >= k. If m < k, then Dorgbr returns Q as an m×m matrix. -// -// If vect == lapack.GeneratePT, then A is assumed to have been a k×n matrix, and -// Pᵀ is of order n. If k < n, then Dorgbr returns the first m rows of Pᵀ, -// where n >= m >= k. If k >= n, then Dorgbr returns Pᵀ as an n×n matrix. -// -// Dorgbr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorgbr(vect lapack.GenOrtho, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { - wantq := vect == lapack.GenerateQ - mn := min(m, n) - switch { - case vect != lapack.GenerateQ && vect != lapack.GeneratePT: - panic(badGenOrtho) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case wantq && n > m: - panic(nGTM) - case wantq && n < min(m, k): - panic("lapack: n < min(m,k)") - case !wantq && m > n: - panic(mGTN) - case !wantq && m < min(n, k): - panic("lapack: m < min(n,k)") - case lda < max(1, n) && lwork != -1: - // Normally, we follow the reference and require the leading - // dimension to be always valid, even in case of workspace - // queries. However, if a caller provided a placeholder value - // for lda (and a) when doing a workspace query that didn't - // fulfill the condition here, it would cause a panic. This is - // exactly what Dgesvd does. - panic(badLdA) - case lwork < max(1, mn) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - work[0] = 1 - if m == 0 || n == 0 { - return - } - - if wantq { - if m >= k { - impl.Dorgqr(m, n, k, a, lda, tau, work, -1) - } else if m > 1 { - impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, -1) - } - } else { - if k < n { - impl.Dorglq(m, n, k, a, lda, tau, work, -1) - } else if n > 1 { - impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, -1) - } - } - lworkopt := int(work[0]) - lworkopt = max(lworkopt, mn) - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case wantq && len(tau) < min(m, k): - panic(shortTau) - case !wantq && len(tau) < min(n, k): - panic(shortTau) - } - - if wantq { - // Form Q, determined by a call to Dgebrd to reduce an m×k matrix. - if m >= k { - impl.Dorgqr(m, n, k, a, lda, tau[:k], work, lwork) - } else { - // Shift the vectors which define the elementary reflectors one - // column to the right, and set the first row and column of Q to - // those of the unit matrix. - for j := m - 1; j >= 1; j-- { - a[j] = 0 - for i := j + 1; i < m; i++ { - a[i*lda+j] = a[i*lda+j-1] - } - } - a[0] = 1 - for i := 1; i < m; i++ { - a[i*lda] = 0 - } - if m > 1 { - // Form Q[1:m-1, 1:m-1] - impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau[:m-1], work, lwork) - } - } - } else { - // Form Pᵀ, determined by a call to Dgebrd to reduce a k×n matrix. - if k < n { - impl.Dorglq(m, n, k, a, lda, tau, work, lwork) - } else { - // Shift the vectors which define the elementary reflectors one - // row downward, and set the first row and column of Pᵀ to - // those of the unit matrix. - a[0] = 1 - for i := 1; i < n; i++ { - a[i*lda] = 0 - } - for j := 1; j < n; j++ { - for i := j - 1; i >= 1; i-- { - a[i*lda+j] = a[(i-1)*lda+j] - } - a[j] = 0 - } - if n > 1 { - impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork) - } - } - } - work[0] = float64(lworkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go deleted file mode 100644 index 8f0dd452..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -// Dorghr generates an n×n orthogonal matrix Q which is defined as the product -// of ihi-ilo elementary reflectors: -// -// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. -// -// a and lda represent an n×n matrix that contains the elementary reflectors, as -// returned by Dgehrd. On return, a is overwritten by the n×n orthogonal matrix -// Q. Q will be equal to the identity matrix except in the submatrix -// Q[ilo+1:ihi+1,ilo+1:ihi+1]. -// -// ilo and ihi must have the same values as in the previous call of Dgehrd. It -// must hold that -// -// 0 <= ilo <= ihi < n if n > 0, -// ilo = 0, ihi = -1 if n == 0. -// -// tau contains the scalar factors of the elementary reflectors, as returned by -// Dgehrd. tau must have length n-1. -// -// work must have length at least max(1,lwork) and lwork must be at least -// ihi-ilo. For optimum performance lwork must be at least (ihi-ilo)*nb where nb -// is the optimal blocksize. On return, work[0] will contain the optimal value -// of lwork. -// -// If lwork == -1, instead of performing Dorghr, only the optimal value of lwork -// will be stored into work[0]. -// -// If any requirement on input sizes is not met, Dorghr will panic. -// -// Dorghr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { - nh := ihi - ilo - switch { - case ilo < 0 || max(1, n) <= ilo: - panic(badIlo) - case ihi < min(ilo, n-1) || n <= ihi: - panic(badIhi) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, nh) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - work[0] = 1 - return - } - - lwkopt := max(1, nh) * impl.Ilaenv(1, "DORGQR", " ", nh, nh, nh, -1) - if lwork == -1 { - work[0] = float64(lwkopt) - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(tau) < n-1: - panic(shortTau) - } - - // Shift the vectors which define the elementary reflectors one column - // to the right. - for i := ilo + 2; i < ihi+1; i++ { - copy(a[i*lda+ilo+1:i*lda+i], a[i*lda+ilo:i*lda+i-1]) - } - // Set the first ilo+1 and the last n-ihi-1 rows and columns to those of - // the identity matrix. - for i := 0; i < ilo+1; i++ { - for j := 0; j < n; j++ { - a[i*lda+j] = 0 - } - a[i*lda+i] = 1 - } - for i := ilo + 1; i < ihi+1; i++ { - for j := 0; j <= ilo; j++ { - a[i*lda+j] = 0 - } - for j := i; j < n; j++ { - a[i*lda+j] = 0 - } - } - for i := ihi + 1; i < n; i++ { - for j := 0; j < n; j++ { - a[i*lda+j] = 0 - } - a[i*lda+i] = 1 - } - if nh > 0 { - // Generate Q[ilo+1:ihi+1,ilo+1:ihi+1]. - impl.Dorgqr(nh, nh, nh, a[(ilo+1)*lda+ilo+1:], lda, tau[ilo:ihi], work, lwork) - } - work[0] = float64(lwkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go deleted file mode 100644 index 6dd9a888..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dorgl2 generates an m×n matrix Q with orthonormal rows defined as the first m -// rows of a product of k elementary reflectors of order n -// -// Q = H_{k-1} * ... * H_0 -// -// as returned by Dgelqf. -// -// On entry, tau and the first k rows of A must contain the scalar factors and -// the vectors, respectively, which define the elementary reflectors H_i, -// i=0,...,k-1, as returned by Dgelqf. On return, A contains the matrix Q. -// -// tau must have length at least k, work must have length at least m, and it -// must hold that 0 <= k <= m <= n, otherwise Dorgl2 will panic. -// -// Dorgl2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorgl2(m, n, k int, a []float64, lda int, tau, work []float64) { - switch { - case m < 0: - panic(mLT0) - case n < m: - panic(nLTM) - case k < 0: - panic(kLT0) - case k > m: - panic(kGTM) - case lda < max(1, n): - panic(badLdA) - } - - if m == 0 { - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - case len(work) < m: - panic(shortWork) - } - - bi := blas64.Implementation() - - if k < m { - for i := k; i < m; i++ { - for j := 0; j < n; j++ { - a[i*lda+j] = 0 - } - } - for j := k; j < m; j++ { - a[j*lda+j] = 1 - } - } - for i := k - 1; i >= 0; i-- { - if i < n-1 { - if i < m-1 { - a[i*lda+i] = 1 - impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tau[i], a[(i+1)*lda+i:], lda, work) - } - bi.Dscal(n-i-1, -tau[i], a[i*lda+i+1:], 1) - } - a[i*lda+i] = 1 - tau[i] - for l := 0; l < i; l++ { - a[i*lda+l] = 0 - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go deleted file mode 100644 index d6b3aadf..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dorglq generates an m×n matrix Q with orthonormal rows defined as the first m -// rows of a product of k elementary reflectors of order n -// -// Q = H_{k-1} * ... * H_0 -// -// as returned by Dgelqf. -// -// On entry, tau and the first k rows of A must contain the scalar factors and -// the vectors, respectively, which define the elementary reflectors H_i, -// i=0,...,k-1, as returned by Dgelqf. On return, A contains the matrix Q. -// -// tau must have length at least k, work must have length at least lwork and -// lwork must be at least max(1,m). On return, optimal value of lwork will be -// stored in work[0]. It must also hold that 0 <= k <= m <= n, otherwise Dorglq -// will panic. -// -// If lwork == -1, instead of performing Dorglq, the function only calculates -// the optimal value of lwork and stores it into work[0]. -func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case m < 0: - panic(mLT0) - case n < m: - panic(nLTM) - case k < 0: - panic(kLT0) - case k > m: - panic(kGTM) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, m) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - if m == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(1, "DORGLQ", " ", m, n, k, -1) - if lwork == -1 { - work[0] = float64(m * nb) - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - } - - nbmin := 2 // Minimum block size - var nx int // Crossover size from blocked to unblocked code - iws := m // Length of work needed - var ldwork int - if 1 < nb && nb < k { - nx = max(0, impl.Ilaenv(3, "DORGLQ", " ", m, n, k, -1)) - if nx < k { - ldwork = nb - iws = m * ldwork - if lwork < iws { - nb = lwork / m - ldwork = nb - nbmin = max(2, impl.Ilaenv(2, "DORGLQ", " ", m, n, k, -1)) - } - } - } - - var ki, kk int - if nbmin <= nb && nb < k && nx < k { - // The first kk rows are handled by the blocked method. - ki = ((k - nx - 1) / nb) * nb - kk = min(k, ki+nb) - for i := kk; i < m; i++ { - for j := 0; j < kk; j++ { - a[i*lda+j] = 0 - } - } - } - if kk < m { - // Perform the operation on columns kk to the end. - impl.Dorgl2(m-kk, n-kk, k-kk, a[kk*lda+kk:], lda, tau[kk:], work) - } - if kk > 0 { - // Perform the operation on column-blocks - for i := ki; i >= 0; i -= nb { - ib := min(nb, k-i) - if i+ib < m { - impl.Dlarft(lapack.Forward, lapack.RowWise, - n-i, ib, - a[i*lda+i:], lda, - tau[i:], - work, ldwork) - - impl.Dlarfb(blas.Right, blas.Trans, lapack.Forward, lapack.RowWise, - m-i-ib, n-i, ib, - a[i*lda+i:], lda, - work, ldwork, - a[(i+ib)*lda+i:], lda, - work[ib*ldwork:], ldwork) - } - impl.Dorgl2(ib, n-i, ib, a[i*lda+i:], lda, tau[i:], work) - for l := i; l < i+ib; l++ { - for j := 0; j < i; j++ { - a[l*lda+j] = 0 - } - } - } - } - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go deleted file mode 100644 index d5ef17f3..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dorgql generates the m×n matrix Q with orthonormal columns defined as the -// last n columns of a product of k elementary reflectors of order m -// -// Q = H_{k-1} * ... * H_1 * H_0. -// -// It must hold that -// -// 0 <= k <= n <= m, -// -// and Dorgql will panic otherwise. -// -// On entry, the (n-k+i)-th column of A must contain the vector which defines -// the elementary reflector H_i, for i=0,...,k-1, and tau[i] must contain its -// scalar factor. On return, a contains the m×n matrix Q. -// -// tau must have length at least k, and Dorgql will panic otherwise. -// -// work must have length at least max(1,lwork), and lwork must be at least -// max(1,n), otherwise Dorgql will panic. For optimum performance lwork must -// be a sufficiently large multiple of n. -// -// If lwork == -1, instead of computing Dorgql the optimal work length is stored -// into work[0]. -// -// Dorgql is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case n > m: - panic(nGTM) - case k < 0: - panic(kLT0) - case k > n: - panic(kGTN) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, n) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(1, "DORGQL", " ", m, n, k, -1) - if lwork == -1 { - work[0] = float64(n * nb) - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - } - - nbmin := 2 - var nx, ldwork int - iws := n - if 1 < nb && nb < k { - // Determine when to cross over from blocked to unblocked code. - nx = max(0, impl.Ilaenv(3, "DORGQL", " ", m, n, k, -1)) - if nx < k { - // Determine if workspace is large enough for blocked code. - iws = n * nb - if lwork < iws { - // Not enough workspace to use optimal nb: reduce nb and determine - // the minimum value of nb. - nb = lwork / n - nbmin = max(2, impl.Ilaenv(2, "DORGQL", " ", m, n, k, -1)) - } - ldwork = nb - } - } - - var kk int - if nbmin <= nb && nb < k && nx < k { - // Use blocked code after the first block. The last kk columns are handled - // by the block method. - kk = min(k, ((k-nx+nb-1)/nb)*nb) - - // Set A(m-kk:m, 0:n-kk) to zero. - for i := m - kk; i < m; i++ { - for j := 0; j < n-kk; j++ { - a[i*lda+j] = 0 - } - } - } - - // Use unblocked code for the first or only block. - impl.Dorg2l(m-kk, n-kk, k-kk, a, lda, tau, work) - if kk > 0 { - // Use blocked code. - for i := k - kk; i < k; i += nb { - ib := min(nb, k-i) - if n-k+i > 0 { - // Form the triangular factor of the block reflector - // H = H_{i+ib-1} * ... * H_{i+1} * H_i. - impl.Dlarft(lapack.Backward, lapack.ColumnWise, m-k+i+ib, ib, - a[n-k+i:], lda, tau[i:], work, ldwork) - - // Apply H to A[0:m-k+i+ib, 0:n-k+i] from the left. - impl.Dlarfb(blas.Left, blas.NoTrans, lapack.Backward, lapack.ColumnWise, - m-k+i+ib, n-k+i, ib, a[n-k+i:], lda, work, ldwork, - a, lda, work[ib*ldwork:], ldwork) - } - - // Apply H to rows 0:m-k+i+ib of current block. - impl.Dorg2l(m-k+i+ib, ib, ib, a[n-k+i:], lda, tau[i:], work) - - // Set rows m-k+i+ib:m of current block to zero. - for j := n - k + i; j < n-k+i+ib; j++ { - for l := m - k + i + ib; l < m; l++ { - a[l*lda+j] = 0 - } - } - } - } - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go deleted file mode 100644 index a1e0fa87..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dorgqr generates an m×n matrix Q with orthonormal columns defined by the -// product of elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{k-1} -// -// as computed by Dgeqrf. -// Dorgqr is the blocked version of Dorg2r that makes greater use of level-3 BLAS -// routines. -// -// The length of tau must be k, and the length of work must be at least n. -// It also must be that 0 <= k <= n and 0 <= n <= m. -// -// work is temporary storage, and lwork specifies the usable memory length. At -// minimum, lwork >= n, and the amount of blocking is limited by the usable -// length. If lwork == -1, instead of computing Dorgqr the optimal work length -// is stored into work[0]. -// -// Dorgqr will panic if the conditions on input values are not met. -// -// Dorgqr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case n > m: - panic(nGTM) - case k < 0: - panic(kLT0) - case k > n: - panic(kGTN) - case lda < max(1, n) && lwork != -1: - // Normally, we follow the reference and require the leading - // dimension to be always valid, even in case of workspace - // queries. However, if a caller provided a placeholder value - // for lda (and a) when doing a workspace query that didn't - // fulfill the condition here, it would cause a panic. This is - // exactly what Dgesvd does. - panic(badLdA) - case lwork < max(1, n) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - if n == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(1, "DORGQR", " ", m, n, k, -1) - // work is treated as an n×nb matrix - if lwork == -1 { - work[0] = float64(n * nb) - return - } - - switch { - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(tau) != k: - panic(badLenTau) - } - - nbmin := 2 // Minimum block size - var nx int // Crossover size from blocked to unblocked code - iws := n // Length of work needed - var ldwork int - if 1 < nb && nb < k { - nx = max(0, impl.Ilaenv(3, "DORGQR", " ", m, n, k, -1)) - if nx < k { - ldwork = nb - iws = n * ldwork - if lwork < iws { - nb = lwork / n - ldwork = nb - nbmin = max(2, impl.Ilaenv(2, "DORGQR", " ", m, n, k, -1)) - } - } - } - var ki, kk int - if nbmin <= nb && nb < k && nx < k { - // The first kk columns are handled by the blocked method. - ki = ((k - nx - 1) / nb) * nb - kk = min(k, ki+nb) - for i := 0; i < kk; i++ { - for j := kk; j < n; j++ { - a[i*lda+j] = 0 - } - } - } - if kk < n { - // Perform the operation on columns kk to the end. - impl.Dorg2r(m-kk, n-kk, k-kk, a[kk*lda+kk:], lda, tau[kk:], work) - } - if kk > 0 { - // Perform the operation on column-blocks. - for i := ki; i >= 0; i -= nb { - ib := min(nb, k-i) - if i+ib < n { - impl.Dlarft(lapack.Forward, lapack.ColumnWise, - m-i, ib, - a[i*lda+i:], lda, - tau[i:], - work, ldwork) - - impl.Dlarfb(blas.Left, blas.NoTrans, lapack.Forward, lapack.ColumnWise, - m-i, n-i-ib, ib, - a[i*lda+i:], lda, - work, ldwork, - a[i*lda+i+ib:], lda, - work[ib*ldwork:], ldwork) - } - impl.Dorg2r(m-i, ib, ib, a[i*lda+i:], lda, tau[i:i+ib], work) - // Set rows 0:i-1 of current block to zero. - for j := i; j < i+ib; j++ { - for l := 0; l < i; l++ { - a[l*lda+j] = 0 - } - } - } - } - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgr2.go deleted file mode 100644 index 6f2790cb..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgr2.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dorgr2 generates an m×n real matrix Q with orthonormal rows, which is defined -// as the last m rows of a product of k elementary reflectors of order n -// -// Q = H_0 * H_1 * ... * H_{k-1} -// -// as returned by Dgerqf. -// -// On entry, the (m-k+i)-th row of A must contain the vector which defines the -// elementary reflector H_i, for i = 0,1,...,k, as returned by Dgerqf. On -// return, A will contain the m×n matrix Q. -// -// The i-th element of tau must contain the scalar factor of the elementary -// reflector H_i, as returned by Dgerqf. -// -// It must hold that -// -// n >= m >= k >= 0, -// -// the length of tau must be k and the length of work must be m, otherwise -// Dorgr2 will panic. -// -// Dorgr2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorgr2(m, n, k int, a []float64, lda int, tau, work []float64) { - switch { - case k < 0: - panic(kLT0) - case m < k: - panic(kGTM) - case n < m: - panic(mGTN) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if m == 0 { - return - } - - switch { - case len(tau) != k: - panic(badLenTau) - case len(a) < (m-1)*lda+n: - panic(shortA) - case len(work) < m: - panic(shortWork) - } - - // Initialise rows 0:m-k to rows of the unit matrix. - for l := 0; l < m-k; l++ { - row := a[l*lda : l*lda+n] - for j := range row { - row[j] = 0 - } - a[l*lda+n-m+l] = 1 - } - bi := blas64.Implementation() - for i := 0; i < k; i++ { - ii := m - k + i - - // Apply H_i to A[0:m-k+i+1, 0:n-k+i+1] from the right. - a[ii*lda+n-m+ii] = 1 - impl.Dlarf(blas.Right, ii, n-m+ii+1, a[ii*lda:], 1, tau[i], a, lda, work) - bi.Dscal(n-m+ii, -tau[i], a[ii*lda:], 1) - a[ii*lda+n-m+ii] = 1 - tau[i] - - // Set A[m-k+i, n-k+i:n] to zero. - for l := n - m + ii + 1; l < n; l++ { - a[ii*lda+l] = 0 - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go deleted file mode 100644 index 7021ae53..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dorgtr generates a real orthogonal matrix Q which is defined as the product -// of n-1 elementary reflectors of order n as returned by Dsytrd. -// -// The construction of Q depends on the value of uplo: -// -// Q = H_{n-1} * ... * H_1 * H_0 if uplo == blas.Upper -// Q = H_0 * H_1 * ... * H_{n-1} if uplo == blas.Lower -// -// where H_i is constructed from the elementary reflectors as computed by Dsytrd. -// See the documentation for Dsytrd for more information. -// -// tau must have length at least n-1, and Dorgtr will panic otherwise. -// -// work is temporary storage, and lwork specifies the usable memory length. At -// minimum, lwork >= max(1,n-1), and Dorgtr will panic otherwise. The amount of blocking -// is limited by the usable length. -// If lwork == -1, instead of computing Dorgtr the optimal work length is stored -// into work[0]. -// -// Dorgtr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, n-1) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - if n == 0 { - work[0] = 1 - return - } - - var nb int - if uplo == blas.Upper { - nb = impl.Ilaenv(1, "DORGQL", " ", n-1, n-1, n-1, -1) - } else { - nb = impl.Ilaenv(1, "DORGQR", " ", n-1, n-1, n-1, -1) - } - lworkopt := max(1, n-1) * nb - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(tau) < n-1: - panic(shortTau) - } - - if uplo == blas.Upper { - // Q was determined by a call to Dsytrd with uplo == blas.Upper. - // Shift the vectors which define the elementary reflectors one column - // to the left, and set the last row and column of Q to those of the unit - // matrix. - for j := 0; j < n-1; j++ { - for i := 0; i < j; i++ { - a[i*lda+j] = a[i*lda+j+1] - } - a[(n-1)*lda+j] = 0 - } - for i := 0; i < n-1; i++ { - a[i*lda+n-1] = 0 - } - a[(n-1)*lda+n-1] = 1 - - // Generate Q[0:n-1, 0:n-1]. - impl.Dorgql(n-1, n-1, n-1, a, lda, tau, work, lwork) - } else { - // Q was determined by a call to Dsytrd with uplo == blas.Upper. - // Shift the vectors which define the elementary reflectors one column - // to the right, and set the first row and column of Q to those of the unit - // matrix. - for j := n - 1; j > 0; j-- { - a[j] = 0 - for i := j + 1; i < n; i++ { - a[i*lda+j] = a[i*lda+j-1] - } - } - a[0] = 1 - for i := 1; i < n; i++ { - a[i*lda] = 0 - } - if n > 1 { - // Generate Q[1:n, 1:n]. - impl.Dorgqr(n-1, n-1, n-1, a[lda+1:], lda, tau[:n-1], work, lwork) - } - } - work[0] = float64(lworkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go deleted file mode 100644 index aea77a70..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dorm2r multiplies a general matrix C by an orthogonal matrix from a QR factorization -// determined by Dgeqrf. -// -// C = Q * C if side == blas.Left and trans == blas.NoTrans -// C = Qᵀ * C if side == blas.Left and trans == blas.Trans -// C = C * Q if side == blas.Right and trans == blas.NoTrans -// C = C * Qᵀ if side == blas.Right and trans == blas.Trans -// -// If side == blas.Left, a is a matrix of size m×k, and if side == blas.Right -// a is of size n×k. -// -// tau contains the Householder factors and must have length k and this function -// will panic otherwise. -// -// work is temporary storage of length at least n if side == blas.Left -// and at least m if side == blas.Right and this function will panic otherwise. -// -// Dorm2r is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorm2r(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { - left := side == blas.Left - switch { - case !left && side != blas.Right: - panic(badSide) - case trans != blas.Trans && trans != blas.NoTrans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case left && k > m: - panic(kGTM) - case !left && k > n: - panic(kGTN) - case lda < max(1, k): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 || k == 0 { - return - } - - switch { - case left && len(a) < (m-1)*lda+k: - panic(shortA) - case !left && len(a) < (n-1)*lda+k: - panic(shortA) - case len(c) < (m-1)*ldc+n: - panic(shortC) - case len(tau) != k: - panic(badLenTau) - case left && len(work) < n: - panic(shortWork) - case !left && len(work) < m: - panic(shortWork) - } - - if left { - if trans == blas.NoTrans { - for i := k - 1; i >= 0; i-- { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) - a[i*lda+i] = aii - } - return - } - for i := 0; i < k; i++ { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) - a[i*lda+i] = aii - } - return - } - if trans == blas.NoTrans { - for i := 0; i < k; i++ { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) - a[i*lda+i] = aii - } - return - } - for i := k - 1; i >= 0; i-- { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) - a[i*lda+i] = aii - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go deleted file mode 100644 index 8be7040c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dormbr applies a multiplicative update to the matrix C based on a -// decomposition computed by Dgebrd. -// -// Dormbr overwrites the m×n matrix C with -// -// Q * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.NoTrans -// C * Q if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.NoTrans -// Qᵀ * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.Trans -// C * Qᵀ if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.Trans -// -// P * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.NoTrans -// C * P if vect == lapack.ApplyP, side == blas.Right, and trans == blas.NoTrans -// Pᵀ * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.Trans -// C * Pᵀ if vect == lapack.ApplyP, side == blas.Right, and trans == blas.Trans -// -// where P and Q are the orthogonal matrices determined by Dgebrd when reducing -// a matrix A to bidiagonal form: A = Q * B * Pᵀ. See Dgebrd for the -// definitions of Q and P. -// -// If vect == lapack.ApplyQ, A is assumed to have been an nq×k matrix, while if -// vect == lapack.ApplyP, A is assumed to have been a k×nq matrix. nq = m if -// side == blas.Left, while nq = n if side == blas.Right. -// -// tau must have length min(nq,k), and Dormbr will panic otherwise. tau contains -// the elementary reflectors to construct Q or P depending on the value of -// vect. -// -// work must have length at least max(1,lwork), and lwork must be either -1 or -// at least max(1,n) if side == blas.Left, and at least max(1,m) if side == -// blas.Right. For optimum performance lwork should be at least n*nb if side == -// blas.Left, and at least m*nb if side == blas.Right, where nb is the optimal -// block size. On return, work[0] will contain the optimal value of lwork. -// -// If lwork == -1, the function only calculates the optimal value of lwork and -// returns it in work[0]. -// -// Dormbr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dormbr(vect lapack.ApplyOrtho, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { - nq := n - nw := m - if side == blas.Left { - nq = m - nw = n - } - applyQ := vect == lapack.ApplyQ - switch { - case !applyQ && vect != lapack.ApplyP: - panic(badApplyOrtho) - case side != blas.Left && side != blas.Right: - panic(badSide) - case trans != blas.NoTrans && trans != blas.Trans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case applyQ && lda < max(1, min(nq, k)): - panic(badLdA) - case !applyQ && lda < max(1, nq): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - case lwork < max(1, nw) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if m == 0 || n == 0 { - work[0] = 1 - return - } - - // The current implementation does not use opts, but a future change may - // use these options so construct them. - var opts string - if side == blas.Left { - opts = "L" - } else { - opts = "R" - } - if trans == blas.Trans { - opts += "T" - } else { - opts += "N" - } - var nb int - if applyQ { - if side == blas.Left { - nb = impl.Ilaenv(1, "DORMQR", opts, m-1, n, m-1, -1) - } else { - nb = impl.Ilaenv(1, "DORMQR", opts, m, n-1, n-1, -1) - } - } else { - if side == blas.Left { - nb = impl.Ilaenv(1, "DORMLQ", opts, m-1, n, m-1, -1) - } else { - nb = impl.Ilaenv(1, "DORMLQ", opts, m, n-1, n-1, -1) - } - } - lworkopt := max(1, nw) * nb - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - - minnqk := min(nq, k) - switch { - case applyQ && len(a) < (nq-1)*lda+minnqk: - panic(shortA) - case !applyQ && len(a) < (minnqk-1)*lda+nq: - panic(shortA) - case len(tau) < minnqk: - panic(shortTau) - case len(c) < (m-1)*ldc+n: - panic(shortC) - } - - if applyQ { - // Change the operation to get Q depending on the size of the initial - // matrix to Dgebrd. The size matters due to the storage location of - // the off-diagonal elements. - if nq >= k { - impl.Dormqr(side, trans, m, n, k, a, lda, tau[:k], c, ldc, work, lwork) - } else if nq > 1 { - mi := m - ni := n - 1 - i1 := 0 - i2 := 1 - if side == blas.Left { - mi = m - 1 - ni = n - i1 = 1 - i2 = 0 - } - impl.Dormqr(side, trans, mi, ni, nq-1, a[lda:], lda, tau[:nq-1], c[i1*ldc+i2:], ldc, work, lwork) - } - work[0] = float64(lworkopt) - return - } - - transt := blas.Trans - if trans == blas.Trans { - transt = blas.NoTrans - } - - // Change the operation to get P depending on the size of the initial - // matrix to Dgebrd. The size matters due to the storage location of - // the off-diagonal elements. - if nq > k { - impl.Dormlq(side, transt, m, n, k, a, lda, tau, c, ldc, work, lwork) - } else if nq > 1 { - mi := m - ni := n - 1 - i1 := 0 - i2 := 1 - if side == blas.Left { - mi = m - 1 - ni = n - i1 = 1 - i2 = 0 - } - impl.Dormlq(side, transt, mi, ni, nq-1, a[1:], lda, tau, c[i1*ldc+i2:], ldc, work, lwork) - } - work[0] = float64(lworkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go deleted file mode 100644 index 318a57ad..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dormhr multiplies an m×n general matrix C with an nq×nq orthogonal matrix Q -// -// Q * C if side == blas.Left and trans == blas.NoTrans, -// Qᵀ * C if side == blas.Left and trans == blas.Trans, -// C * Q if side == blas.Right and trans == blas.NoTrans, -// C * Qᵀ if side == blas.Right and trans == blas.Trans, -// -// where nq == m if side == blas.Left and nq == n if side == blas.Right. -// -// Q is defined implicitly as the product of ihi-ilo elementary reflectors, as -// returned by Dgehrd: -// -// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. -// -// Q is equal to the identity matrix except in the submatrix -// Q[ilo+1:ihi+1,ilo+1:ihi+1]. -// -// ilo and ihi must have the same values as in the previous call of Dgehrd. It -// must hold that -// -// 0 <= ilo <= ihi < m if m > 0 and side == blas.Left, -// ilo = 0 and ihi = -1 if m = 0 and side == blas.Left, -// 0 <= ilo <= ihi < n if n > 0 and side == blas.Right, -// ilo = 0 and ihi = -1 if n = 0 and side == blas.Right. -// -// a and lda represent an m×m matrix if side == blas.Left and an n×n matrix if -// side == blas.Right. The matrix contains vectors which define the elementary -// reflectors, as returned by Dgehrd. -// -// tau contains the scalar factors of the elementary reflectors, as returned by -// Dgehrd. tau must have length m-1 if side == blas.Left and n-1 if side == -// blas.Right. -// -// c and ldc represent the m×n matrix C. On return, c is overwritten by the -// product with Q. -// -// work must have length at least max(1,lwork), and lwork must be at least -// max(1,n), if side == blas.Left, and max(1,m), if side == blas.Right. For -// optimum performance lwork should be at least n*nb if side == blas.Left and -// m*nb if side == blas.Right, where nb is the optimal block size. On return, -// work[0] will contain the optimal value of lwork. -// -// If lwork == -1, instead of performing Dormhr, only the optimal value of lwork -// will be stored in work[0]. -// -// If any requirement on input sizes is not met, Dormhr will panic. -// -// Dormhr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { - nq := n // The order of Q. - nw := m // The minimum length of work. - if side == blas.Left { - nq = m - nw = n - } - switch { - case side != blas.Left && side != blas.Right: - panic(badSide) - case trans != blas.NoTrans && trans != blas.Trans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case ilo < 0 || max(1, nq) <= ilo: - panic(badIlo) - case ihi < min(ilo, nq-1) || nq <= ihi: - panic(badIhi) - case lda < max(1, nq): - panic(badLdA) - case lwork < max(1, nw) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if m == 0 || n == 0 { - work[0] = 1 - return - } - - nh := ihi - ilo - var nb int - if side == blas.Left { - opts := "LN" - if trans == blas.Trans { - opts = "LT" - } - nb = impl.Ilaenv(1, "DORMQR", opts, nh, n, nh, -1) - } else { - opts := "RN" - if trans == blas.Trans { - opts = "RT" - } - nb = impl.Ilaenv(1, "DORMQR", opts, m, nh, nh, -1) - } - lwkopt := max(1, nw) * nb - if lwork == -1 { - work[0] = float64(lwkopt) - return - } - - if nh == 0 { - work[0] = 1 - return - } - - switch { - case len(a) < (nq-1)*lda+nq: - panic(shortA) - case len(c) < (m-1)*ldc+n: - panic(shortC) - case len(tau) != nq-1: - panic(badLenTau) - } - - if side == blas.Left { - impl.Dormqr(side, trans, nh, n, nh, a[(ilo+1)*lda+ilo:], lda, - tau[ilo:ihi], c[(ilo+1)*ldc:], ldc, work, lwork) - } else { - impl.Dormqr(side, trans, m, nh, nh, a[(ilo+1)*lda+ilo:], lda, - tau[ilo:ihi], c[ilo+1:], ldc, work, lwork) - } - work[0] = float64(lwkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go deleted file mode 100644 index 665e2102..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dorml2 multiplies a general matrix C by an orthogonal matrix from an LQ factorization -// determined by Dgelqf. -// -// C = Q * C if side == blas.Left and trans == blas.NoTrans -// C = Qᵀ * C if side == blas.Left and trans == blas.Trans -// C = C * Q if side == blas.Right and trans == blas.NoTrans -// C = C * Qᵀ if side == blas.Right and trans == blas.Trans -// -// If side == blas.Left, a is a matrix of side k×m, and if side == blas.Right -// a is of size k×n. -// -// tau contains the Householder factors and is of length at least k and this function will -// panic otherwise. -// -// work is temporary storage of length at least n if side == blas.Left -// and at least m if side == blas.Right and this function will panic otherwise. -// -// Dorml2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dorml2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { - left := side == blas.Left - switch { - case !left && side != blas.Right: - panic(badSide) - case trans != blas.Trans && trans != blas.NoTrans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case left && k > m: - panic(kGTM) - case !left && k > n: - panic(kGTN) - case left && lda < max(1, m): - panic(badLdA) - case !left && lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if m == 0 || n == 0 || k == 0 { - return - } - - switch { - case left && len(a) < (k-1)*lda+m: - panic(shortA) - case !left && len(a) < (k-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - case len(c) < (m-1)*ldc+n: - panic(shortC) - case left && len(work) < n: - panic(shortWork) - case !left && len(work) < m: - panic(shortWork) - } - - notrans := trans == blas.NoTrans - switch { - case left && notrans: - for i := 0; i < k; i++ { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) - a[i*lda+i] = aii - } - - case left && !notrans: - for i := k - 1; i >= 0; i-- { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) - a[i*lda+i] = aii - } - - case !left && notrans: - for i := k - 1; i >= 0; i-- { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) - a[i*lda+i] = aii - } - - case !left && !notrans: - for i := 0; i < k; i++ { - aii := a[i*lda+i] - a[i*lda+i] = 1 - impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) - a[i*lda+i] = aii - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go deleted file mode 100644 index 37b49973..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dormlq multiplies the matrix C by the orthogonal matrix Q defined by the -// slices a and tau. A and tau are as returned from Dgelqf. -// -// C = Q * C if side == blas.Left and trans == blas.NoTrans -// C = Qᵀ * C if side == blas.Left and trans == blas.Trans -// C = C * Q if side == blas.Right and trans == blas.NoTrans -// C = C * Qᵀ if side == blas.Right and trans == blas.Trans -// -// If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right -// A is of size k×n. This uses a blocked algorithm. -// -// work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right, -// and this function will panic otherwise. -// Dormlq uses a block algorithm, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Dormlq, -// the optimal work length will be stored into work[0]. -// -// tau contains the Householder scales and must have length at least k, and -// this function will panic otherwise. -func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { - left := side == blas.Left - nw := m - if left { - nw = n - } - switch { - case !left && side != blas.Right: - panic(badSide) - case trans != blas.Trans && trans != blas.NoTrans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case left && k > m: - panic(kGTM) - case !left && k > n: - panic(kGTN) - case left && lda < max(1, m): - panic(badLdA) - case !left && lda < max(1, n): - panic(badLdA) - case lwork < max(1, nw) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if m == 0 || n == 0 || k == 0 { - work[0] = 1 - return - } - - const ( - nbmax = 64 - ldt = nbmax - tsize = nbmax * ldt - ) - opts := string(side) + string(trans) - nb := min(nbmax, impl.Ilaenv(1, "DORMLQ", opts, m, n, k, -1)) - lworkopt := max(1, nw)*nb + tsize - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - - switch { - case left && len(a) < (k-1)*lda+m: - panic(shortA) - case !left && len(a) < (k-1)*lda+n: - panic(shortA) - case len(tau) < k: - panic(shortTau) - case len(c) < (m-1)*ldc+n: - panic(shortC) - } - - nbmin := 2 - if 1 < nb && nb < k { - iws := nw*nb + tsize - if lwork < iws { - nb = (lwork - tsize) / nw - nbmin = max(2, impl.Ilaenv(2, "DORMLQ", opts, m, n, k, -1)) - } - } - if nb < nbmin || k <= nb { - // Call unblocked code. - impl.Dorml2(side, trans, m, n, k, a, lda, tau, c, ldc, work) - work[0] = float64(lworkopt) - return - } - - t := work[:tsize] - wrk := work[tsize:] - ldwrk := nb - - notrans := trans == blas.NoTrans - transt := blas.NoTrans - if notrans { - transt = blas.Trans - } - - switch { - case left && notrans: - for i := 0; i < k; i += nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, - a[i*lda+i:], lda, - tau[i:], - t, ldt) - impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m-i, n, ib, - a[i*lda+i:], lda, - t, ldt, - c[i*ldc:], ldc, - wrk, ldwrk) - } - - case left && !notrans: - for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, - a[i*lda+i:], lda, - tau[i:], - t, ldt) - impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m-i, n, ib, - a[i*lda+i:], lda, - t, ldt, - c[i*ldc:], ldc, - wrk, ldwrk) - } - - case !left && notrans: - for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, - a[i*lda+i:], lda, - tau[i:], - t, ldt) - impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m, n-i, ib, - a[i*lda+i:], lda, - t, ldt, - c[i:], ldc, - wrk, ldwrk) - } - - case !left && !notrans: - for i := 0; i < k; i += nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, - a[i*lda+i:], lda, - tau[i:], - t, ldt) - impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m, n-i, ib, - a[i*lda+i:], lda, - t, ldt, - c[i:], ldc, - wrk, ldwrk) - } - } - work[0] = float64(lworkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go deleted file mode 100644 index c1e5668b..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/lapack" -) - -// Dormqr multiplies an m×n matrix C by an orthogonal matrix Q as -// -// C = Q * C if side == blas.Left and trans == blas.NoTrans, -// C = Qᵀ * C if side == blas.Left and trans == blas.Trans, -// C = C * Q if side == blas.Right and trans == blas.NoTrans, -// C = C * Qᵀ if side == blas.Right and trans == blas.Trans, -// -// where Q is defined as the product of k elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{k-1}. -// -// If side == blas.Left, A is an m×k matrix and 0 <= k <= m. -// If side == blas.Right, A is an n×k matrix and 0 <= k <= n. -// The ith column of A contains the vector which defines the elementary -// reflector H_i and tau[i] contains its scalar factor. tau must have length k -// and Dormqr will panic otherwise. Dgeqrf returns A and tau in the required -// form. -// -// work must have length at least max(1,lwork), and lwork must be at least n if -// side == blas.Left and at least m if side == blas.Right, otherwise Dormqr will -// panic. -// -// work is temporary storage, and lwork specifies the usable memory length. At -// minimum, lwork >= m if side == blas.Left and lwork >= n if side == -// blas.Right, and this function will panic otherwise. Larger values of lwork -// will generally give better performance. On return, work[0] will contain the -// optimal value of lwork. -// -// If lwork is -1, instead of performing Dormqr, the optimal workspace size will -// be stored into work[0]. -func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { - left := side == blas.Left - nq := n - nw := m - if left { - nq = m - nw = n - } - switch { - case !left && side != blas.Right: - panic(badSide) - case trans != blas.NoTrans && trans != blas.Trans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case left && k > m: - panic(kGTM) - case !left && k > n: - panic(kGTN) - case lda < max(1, k): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - case lwork < max(1, nw) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if m == 0 || n == 0 || k == 0 { - work[0] = 1 - return - } - - const ( - nbmax = 64 - ldt = nbmax - tsize = nbmax * ldt - ) - opts := string(side) + string(trans) - nb := min(nbmax, impl.Ilaenv(1, "DORMQR", opts, m, n, k, -1)) - lworkopt := max(1, nw)*nb + tsize - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - - switch { - case len(a) < (nq-1)*lda+k: - panic(shortA) - case len(tau) != k: - panic(badLenTau) - case len(c) < (m-1)*ldc+n: - panic(shortC) - } - - nbmin := 2 - if 1 < nb && nb < k { - if lwork < nw*nb+tsize { - nb = (lwork - tsize) / nw - nbmin = max(2, impl.Ilaenv(2, "DORMQR", opts, m, n, k, -1)) - } - } - - if nb < nbmin || k <= nb { - // Call unblocked code. - impl.Dorm2r(side, trans, m, n, k, a, lda, tau, c, ldc, work) - work[0] = float64(lworkopt) - return - } - - var ( - ldwork = nb - notrans = trans == blas.NoTrans - ) - switch { - case left && notrans: - for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, - a[i*lda+i:], lda, - tau[i:], - work[:tsize], ldt) - impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib, - a[i*lda+i:], lda, - work[:tsize], ldt, - c[i*ldc:], ldc, - work[tsize:], ldwork) - } - - case left && !notrans: - for i := 0; i < k; i += nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, - a[i*lda+i:], lda, - tau[i:], - work[:tsize], ldt) - impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib, - a[i*lda+i:], lda, - work[:tsize], ldt, - c[i*ldc:], ldc, - work[tsize:], ldwork) - } - - case !left && notrans: - for i := 0; i < k; i += nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, - a[i*lda+i:], lda, - tau[i:], - work[:tsize], ldt) - impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib, - a[i*lda+i:], lda, - work[:tsize], ldt, - c[i:], ldc, - work[tsize:], ldwork) - } - - case !left && !notrans: - for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { - ib := min(nb, k-i) - impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, - a[i*lda+i:], lda, - tau[i:], - work[:tsize], ldt) - impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib, - a[i*lda+i:], lda, - work[:tsize], ldt, - c[i:], ldc, - work[tsize:], ldwork) - } - } - work[0] = float64(lworkopt) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go deleted file mode 100644 index 59d4d4f1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dormr2 multiplies a general matrix C by an orthogonal matrix from a RQ factorization -// determined by Dgerqf. -// -// C = Q * C if side == blas.Left and trans == blas.NoTrans -// C = Qᵀ * C if side == blas.Left and trans == blas.Trans -// C = C * Q if side == blas.Right and trans == blas.NoTrans -// C = C * Qᵀ if side == blas.Right and trans == blas.Trans -// -// If side == blas.Left, a is a matrix of size k×m, and if side == blas.Right -// a is of size k×n. -// -// tau contains the Householder factors and is of length at least k and this function -// will panic otherwise. -// -// work is temporary storage of length at least n if side == blas.Left -// and at least m if side == blas.Right and this function will panic otherwise. -// -// Dormr2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dormr2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { - left := side == blas.Left - nq := n - nw := m - if left { - nq = m - nw = n - } - switch { - case !left && side != blas.Right: - panic(badSide) - case trans != blas.NoTrans && trans != blas.Trans: - panic(badTrans) - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case k < 0: - panic(kLT0) - case left && k > m: - panic(kGTM) - case !left && k > n: - panic(kGTN) - case lda < max(1, nq): - panic(badLdA) - case ldc < max(1, n): - panic(badLdC) - } - - // Quick return if possible. - if m == 0 || n == 0 || k == 0 { - return - } - - switch { - case len(a) < (k-1)*lda+nq: - panic(shortA) - case len(tau) < k: - panic(shortTau) - case len(c) < (m-1)*ldc+n: - panic(shortC) - case len(work) < nw: - panic(shortWork) - } - - if left { - if trans == blas.NoTrans { - for i := k - 1; i >= 0; i-- { - aii := a[i*lda+(m-k+i)] - a[i*lda+(m-k+i)] = 1 - impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) - a[i*lda+(m-k+i)] = aii - } - return - } - for i := 0; i < k; i++ { - aii := a[i*lda+(m-k+i)] - a[i*lda+(m-k+i)] = 1 - impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) - a[i*lda+(m-k+i)] = aii - } - return - } - if trans == blas.NoTrans { - for i := 0; i < k; i++ { - aii := a[i*lda+(n-k+i)] - a[i*lda+(n-k+i)] = 1 - impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) - a[i*lda+(n-k+i)] = aii - } - return - } - for i := k - 1; i >= 0; i-- { - aii := a[i*lda+(n-k+i)] - a[i*lda+(n-k+i)] = 1 - impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) - a[i*lda+(n-k+i)] = aii - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbcon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbcon.go deleted file mode 100644 index 0ed63e62..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbcon.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright ©2019 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpbcon returns an estimate of the reciprocal of the condition number (in the -// 1-norm) of an n×n symmetric positive definite band matrix using the Cholesky -// factorization -// -// A = Uᵀ*U if uplo == blas.Upper -// A = L*Lᵀ if uplo == blas.Lower -// -// computed by Dpbtrf. The estimate is obtained for norm(inv(A)), and the -// reciprocal of the condition number is computed as -// -// rcond = 1 / (anorm * norm(inv(A))). -// -// The length of work must be at least 3*n and the length of iwork must be at -// least n. -func (impl Implementation) Dpbcon(uplo blas.Uplo, n, kd int, ab []float64, ldab int, anorm float64, work []float64, iwork []int) (rcond float64) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case kd < 0: - panic(kdLT0) - case ldab < kd+1: - panic(badLdA) - case anorm < 0: - panic(badNorm) - } - - // Quick return if possible. - if n == 0 { - return 1 - } - - switch { - case len(ab) < (n-1)*ldab+kd+1: - panic(shortAB) - case len(work) < 3*n: - panic(shortWork) - case len(iwork) < n: - panic(shortIWork) - } - - // Quick return if possible. - if anorm == 0 { - return 0 - } - - const smlnum = dlamchS - - var ( - ainvnm float64 - kase int - isave [3]int - normin bool - - // Denote work slices. - x = work[:n] - v = work[n : 2*n] - cnorm = work[2*n : 3*n] - ) - // Estimate the 1-norm of the inverse. - bi := blas64.Implementation() - for { - ainvnm, kase = impl.Dlacn2(n, v, x, iwork, ainvnm, kase, &isave) - if kase == 0 { - break - } - var op1, op2 blas.Transpose - if uplo == blas.Upper { - // Multiply x by inv(Uᵀ), - op1 = blas.Trans - // then by inv(Uᵀ). - op2 = blas.NoTrans - } else { - // Multiply x by inv(L), - op1 = blas.NoTrans - // then by inv(Lᵀ). - op2 = blas.Trans - } - scaleL := impl.Dlatbs(uplo, op1, blas.NonUnit, normin, n, kd, ab, ldab, x, cnorm) - normin = true - scaleU := impl.Dlatbs(uplo, op2, blas.NonUnit, normin, n, kd, ab, ldab, x, cnorm) - // Multiply x by 1/scale if doing so will not cause overflow. - scale := scaleL * scaleU - if scale != 1 { - ix := bi.Idamax(n, x, 1) - if scale < math.Abs(x[ix])*smlnum || scale == 0 { - return 0 - } - impl.Drscl(n, scale, x, 1) - } - } - if ainvnm == 0 { - return 0 - } - // Return the estimate of the reciprocal condition number. - return (1 / ainvnm) / anorm -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go deleted file mode 100644 index 8150e568..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpbtf2 computes the Cholesky factorization of a symmetric positive banded -// matrix ab. The matrix ab is n×n with kd diagonal bands. The Cholesky -// factorization computed is -// -// A = Uᵀ * U if ul == blas.Upper -// A = L * Lᵀ if ul == blas.Lower -// -// ul also specifies the storage of ab. If ul == blas.Upper, then -// ab is stored as an upper-triangular banded matrix with kd super-diagonals, -// and if ul == blas.Lower, ab is stored as a lower-triangular banded matrix -// with kd sub-diagonals. On exit, the banded matrix U or L is stored in-place -// into ab depending on the value of ul. Dpbtf2 returns whether the factorization -// was successfully completed. -// -// The band storage scheme is illustrated below when n = 6, and kd = 2. -// The resulting Cholesky decomposition is stored in the same elements as the -// input band matrix (a11 becomes u11 or l11, etc.). -// -// ul = blas.Upper -// a11 a12 a13 -// a22 a23 a24 -// a33 a34 a35 -// a44 a45 a46 -// a55 a56 * -// a66 * * -// -// ul = blas.Lower -// * * a11 -// * a21 a22 -// a31 a32 a33 -// a42 a43 a44 -// a53 a54 a55 -// a64 a65 a66 -// -// Dpbtf2 is the unblocked version of the algorithm, see Dpbtrf for the blocked -// version. -// -// Dpbtf2 is an internal routine, exported for testing purposes. -func (Implementation) Dpbtf2(uplo blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case kd < 0: - panic(kdLT0) - case ldab < kd+1: - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return true - } - - if len(ab) < (n-1)*ldab+kd+1 { - panic(shortAB) - } - - bi := blas64.Implementation() - - kld := max(1, ldab-1) - if uplo == blas.Upper { - // Compute the Cholesky factorization A = Uᵀ * U. - for j := 0; j < n; j++ { - // Compute U(j,j) and test for non-positive-definiteness. - ajj := ab[j*ldab] - if ajj <= 0 { - return false - } - ajj = math.Sqrt(ajj) - ab[j*ldab] = ajj - // Compute elements j+1:j+kn of row j and update the trailing submatrix - // within the band. - kn := min(kd, n-j-1) - if kn > 0 { - bi.Dscal(kn, 1/ajj, ab[j*ldab+1:], 1) - bi.Dsyr(blas.Upper, kn, -1, ab[j*ldab+1:], 1, ab[(j+1)*ldab:], kld) - } - } - return true - } - // Compute the Cholesky factorization A = L * Lᵀ. - for j := 0; j < n; j++ { - // Compute L(j,j) and test for non-positive-definiteness. - ajj := ab[j*ldab+kd] - if ajj <= 0 { - return false - } - ajj = math.Sqrt(ajj) - ab[j*ldab+kd] = ajj - // Compute elements j+1:j+kn of column j and update the trailing submatrix - // within the band. - kn := min(kd, n-j-1) - if kn > 0 { - bi.Dscal(kn, 1/ajj, ab[(j+1)*ldab+kd-1:], kld) - bi.Dsyr(blas.Lower, kn, -1, ab[(j+1)*ldab+kd-1:], kld, ab[(j+1)*ldab+kd:], kld) - } - } - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrf.go deleted file mode 100644 index 12cdfc0f..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrf.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright ©2019 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpbtrf computes the Cholesky factorization of an n×n symmetric positive -// definite band matrix -// -// A = Uᵀ * U if uplo == blas.Upper -// A = L * Lᵀ if uplo == blas.Lower -// -// where U is an upper triangular band matrix and L is lower triangular. kd is -// the number of super- or sub-diagonals of A. -// -// The band storage scheme is illustrated below when n = 6 and kd = 2. Elements -// marked * are not used by the function. -// -// uplo == blas.Upper -// On entry: On return: -// a00 a01 a02 u00 u01 u02 -// a11 a12 a13 u11 u12 u13 -// a22 a23 a24 u22 u23 u24 -// a33 a34 a35 u33 u34 u35 -// a44 a45 * u44 u45 * -// a55 * * u55 * * -// -// uplo == blas.Lower -// On entry: On return: -// * * a00 * * l00 -// * a10 a11 * l10 l11 -// a20 a21 a22 l20 l21 l22 -// a31 a32 a33 l31 l32 l33 -// a42 a43 a44 l42 l43 l44 -// a53 a54 a55 l53 l54 l55 -func (impl Implementation) Dpbtrf(uplo blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) { - const nbmax = 32 - - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case kd < 0: - panic(kdLT0) - case ldab < kd+1: - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return true - } - - if len(ab) < (n-1)*ldab+kd+1 { - panic(shortAB) - } - - opts := string(blas.Upper) - if uplo == blas.Lower { - opts = string(blas.Lower) - } - nb := impl.Ilaenv(1, "DPBTRF", opts, n, kd, -1, -1) - // The block size must not exceed the semi-bandwidth kd, and must not - // exceed the limit set by the size of the local array work. - nb = min(nb, nbmax) - - if nb <= 1 || kd < nb { - // Use unblocked code. - return impl.Dpbtf2(uplo, n, kd, ab, ldab) - } - - // Use blocked code. - ldwork := nb - work := make([]float64, nb*ldwork) - bi := blas64.Implementation() - if uplo == blas.Upper { - // Compute the Cholesky factorization of a symmetric band - // matrix, given the upper triangle of the matrix in band - // storage. - - // Process the band matrix one diagonal block at a time. - for i := 0; i < n; i += nb { - ib := min(nb, n-i) - // Factorize the diagonal block. - ok := impl.Dpotf2(uplo, ib, ab[i*ldab:], ldab-1) - if !ok { - return false - } - if i+ib >= n { - continue - } - // Update the relevant part of the trailing submatrix. - // If A11 denotes the diagonal block which has just been - // factorized, then we need to update the remaining - // blocks in the diagram: - // - // A11 A12 A13 - // A22 A23 - // A33 - // - // The numbers of rows and columns in the partitioning - // are ib, i2, i3 respectively. The blocks A12, A22 and - // A23 are empty if ib = kd. The upper triangle of A13 - // lies outside the band. - i2 := min(kd-ib, n-i-ib) - if i2 > 0 { - // Update A12. - bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, ib, i2, - 1, ab[i*ldab:], ldab-1, ab[i*ldab+ib:], ldab-1) - // Update A22. - bi.Dsyrk(blas.Upper, blas.Trans, i2, ib, - -1, ab[i*ldab+ib:], ldab-1, 1, ab[(i+ib)*ldab:], ldab-1) - } - i3 := min(ib, n-i-kd) - if i3 > 0 { - // Copy the lower triangle of A13 into the work array. - for ii := 0; ii < ib; ii++ { - for jj := 0; jj <= min(ii, i3-1); jj++ { - work[ii*ldwork+jj] = ab[(i+ii)*ldab+kd-ii+jj] - } - } - // Update A13 (in the work array). - bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, ib, i3, - 1, ab[i*ldab:], ldab-1, work, ldwork) - // Update A23. - if i2 > 0 { - bi.Dgemm(blas.Trans, blas.NoTrans, i2, i3, ib, - -1, ab[i*ldab+ib:], ldab-1, work, ldwork, - 1, ab[(i+ib)*ldab+kd-ib:], ldab-1) - } - // Update A33. - bi.Dsyrk(blas.Upper, blas.Trans, i3, ib, - -1, work, ldwork, 1, ab[(i+kd)*ldab:], ldab-1) - // Copy the lower triangle of A13 back into place. - for ii := 0; ii < ib; ii++ { - for jj := 0; jj <= min(ii, i3-1); jj++ { - ab[(i+ii)*ldab+kd-ii+jj] = work[ii*ldwork+jj] - } - } - } - } - } else { - // Compute the Cholesky factorization of a symmetric band - // matrix, given the lower triangle of the matrix in band - // storage. - - // Process the band matrix one diagonal block at a time. - for i := 0; i < n; i += nb { - ib := min(nb, n-i) - // Factorize the diagonal block. - ok := impl.Dpotf2(uplo, ib, ab[i*ldab+kd:], ldab-1) - if !ok { - return false - } - if i+ib >= n { - continue - } - // Update the relevant part of the trailing submatrix. - // If A11 denotes the diagonal block which has just been - // factorized, then we need to update the remaining - // blocks in the diagram: - // - // A11 - // A21 A22 - // A31 A32 A33 - // - // The numbers of rows and columns in the partitioning - // are ib, i2, i3 respectively. The blocks A21, A22 and - // A32 are empty if ib = kd. The lowr triangle of A31 - // lies outside the band. - i2 := min(kd-ib, n-i-ib) - if i2 > 0 { - // Update A21. - bi.Dtrsm(blas.Right, blas.Lower, blas.Trans, blas.NonUnit, i2, ib, - 1, ab[i*ldab+kd:], ldab-1, ab[(i+ib)*ldab+kd-ib:], ldab-1) - // Update A22. - bi.Dsyrk(blas.Lower, blas.NoTrans, i2, ib, - -1, ab[(i+ib)*ldab+kd-ib:], ldab-1, 1, ab[(i+ib)*ldab+kd:], ldab-1) - } - i3 := min(ib, n-i-kd) - if i3 > 0 { - // Copy the upper triangle of A31 into the work array. - for ii := 0; ii < i3; ii++ { - for jj := ii; jj < ib; jj++ { - work[ii*ldwork+jj] = ab[(ii+i+kd)*ldab+jj-ii] - } - } - // Update A31 (in the work array). - bi.Dtrsm(blas.Right, blas.Lower, blas.Trans, blas.NonUnit, i3, ib, - 1, ab[i*ldab+kd:], ldab-1, work, ldwork) - // Update A32. - if i2 > 0 { - bi.Dgemm(blas.NoTrans, blas.Trans, i3, i2, ib, - -1, work, ldwork, ab[(i+ib)*ldab+kd-ib:], ldab-1, - 1, ab[(i+kd)*ldab+ib:], ldab-1) - } - // Update A33. - bi.Dsyrk(blas.Lower, blas.NoTrans, i3, ib, - -1, work, ldwork, 1, ab[(i+kd)*ldab+kd:], ldab-1) - // Copy the upper triangle of A31 back into place. - for ii := 0; ii < i3; ii++ { - for jj := ii; jj < ib; jj++ { - ab[(ii+i+kd)*ldab+jj-ii] = work[ii*ldwork+jj] - } - } - } - } - } - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrs.go deleted file mode 100644 index 97c9ada0..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtrs.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright ©2019 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpbtrs solves a system of linear equations A*X = B with an n×n symmetric -// positive definite band matrix A using the Cholesky factorization -// -// A = Uᵀ * U if uplo == blas.Upper -// A = L * Lᵀ if uplo == blas.Lower -// -// computed by Dpbtrf. kd is the number of super- or sub-diagonals of A. See the -// documentation for Dpbtrf for a description of the band storage format of A. -// -// On entry, b contains the n×nrhs right hand side matrix B. On return, it is -// overwritten with the solution matrix X. -func (Implementation) Dpbtrs(uplo blas.Uplo, n, kd, nrhs int, ab []float64, ldab int, b []float64, ldb int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case kd < 0: - panic(kdLT0) - case nrhs < 0: - panic(nrhsLT0) - case ldab < kd+1: - panic(badLdA) - case ldb < max(1, nrhs): - panic(badLdB) - } - - // Quick return if possible. - if n == 0 || nrhs == 0 { - return - } - - if len(ab) < (n-1)*ldab+kd+1 { - panic(shortAB) - } - if len(b) < (n-1)*ldb+nrhs { - panic(shortB) - } - - bi := blas64.Implementation() - if uplo == blas.Upper { - // Solve A*X = B where A = Uᵀ*U. - for j := 0; j < nrhs; j++ { - // Solve Uᵀ*Y = B, overwriting B with Y. - bi.Dtbsv(blas.Upper, blas.Trans, blas.NonUnit, n, kd, ab, ldab, b[j:], ldb) - // Solve U*X = Y, overwriting Y with X. - bi.Dtbsv(blas.Upper, blas.NoTrans, blas.NonUnit, n, kd, ab, ldab, b[j:], ldb) - } - } else { - // Solve A*X = B where A = L*Lᵀ. - for j := 0; j < nrhs; j++ { - // Solve L*Y = B, overwriting B with Y. - bi.Dtbsv(blas.Lower, blas.NoTrans, blas.NonUnit, n, kd, ab, ldab, b[j:], ldb) - // Solve Lᵀ*X = Y, overwriting Y with X. - bi.Dtbsv(blas.Lower, blas.Trans, blas.NonUnit, n, kd, ab, ldab, b[j:], ldb) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go deleted file mode 100644 index 7af4c187..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpocon estimates the reciprocal of the condition number of a positive-definite -// matrix A given the Cholesky decomposition of A. The condition number computed -// is based on the 1-norm and the ∞-norm. -// -// anorm is the 1-norm and the ∞-norm of the original matrix A. -// -// work is a temporary data slice of length at least 3*n and Dpocon will panic otherwise. -// -// iwork is a temporary data slice of length at least n and Dpocon will panic otherwise. -func (impl Implementation) Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case anorm < 0: - panic(negANorm) - } - - // Quick return if possible. - if n == 0 { - return 1 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(work) < 3*n: - panic(shortWork) - case len(iwork) < n: - panic(shortIWork) - } - - if anorm == 0 { - return 0 - } - - bi := blas64.Implementation() - - var ( - smlnum = dlamchS - rcond float64 - sl, su float64 - normin bool - ainvnm float64 - kase int - isave [3]int - ) - for { - ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, &isave) - if kase == 0 { - if ainvnm != 0 { - rcond = (1 / ainvnm) / anorm - } - return rcond - } - if uplo == blas.Upper { - sl = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) - normin = true - su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) - } else { - sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) - normin = true - su = impl.Dlatrs(blas.Lower, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) - } - scale := sl * su - if scale != 1 { - ix := bi.Idamax(n, work, 1) - if scale == 0 || scale < math.Abs(work[ix])*smlnum { - return rcond - } - impl.Drscl(n, scale, work, 1) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go deleted file mode 100644 index 83411f1c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpotf2 computes the Cholesky decomposition of the symmetric positive definite -// matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, -// and a = Uᵀ U is stored in place into a. If ul == blas.Lower, then a = L Lᵀ -// is computed and stored in-place into a. If a is not positive definite, false -// is returned. This is the unblocked version of the algorithm. -// -// Dpotf2 is an internal routine. It is exported for testing purposes. -func (Implementation) Dpotf2(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { - switch { - case ul != blas.Upper && ul != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return true - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - bi := blas64.Implementation() - - if ul == blas.Upper { - for j := 0; j < n; j++ { - ajj := a[j*lda+j] - if j != 0 { - ajj -= bi.Ddot(j, a[j:], lda, a[j:], lda) - } - if ajj <= 0 || math.IsNaN(ajj) { - a[j*lda+j] = ajj - return false - } - ajj = math.Sqrt(ajj) - a[j*lda+j] = ajj - if j < n-1 { - bi.Dgemv(blas.Trans, j, n-j-1, - -1, a[j+1:], lda, a[j:], lda, - 1, a[j*lda+j+1:], 1) - bi.Dscal(n-j-1, 1/ajj, a[j*lda+j+1:], 1) - } - } - return true - } - for j := 0; j < n; j++ { - ajj := a[j*lda+j] - if j != 0 { - ajj -= bi.Ddot(j, a[j*lda:], 1, a[j*lda:], 1) - } - if ajj <= 0 || math.IsNaN(ajj) { - a[j*lda+j] = ajj - return false - } - ajj = math.Sqrt(ajj) - a[j*lda+j] = ajj - if j < n-1 { - bi.Dgemv(blas.NoTrans, n-j-1, j, - -1, a[(j+1)*lda:], lda, a[j*lda:], 1, - 1, a[(j+1)*lda+j:], lda) - bi.Dscal(n-j-1, 1/ajj, a[(j+1)*lda+j:], lda) - } - } - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go deleted file mode 100644 index 7c816801..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpotrf computes the Cholesky decomposition of the symmetric positive definite -// matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, -// and a = Uᵀ U is stored in place into a. If ul == blas.Lower, then a = L Lᵀ -// is computed and stored in-place into a. If a is not positive definite, false -// is returned. This is the blocked version of the algorithm. -func (impl Implementation) Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { - switch { - case ul != blas.Upper && ul != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return true - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - nb := impl.Ilaenv(1, "DPOTRF", string(ul), n, -1, -1, -1) - if nb <= 1 || n <= nb { - return impl.Dpotf2(ul, n, a, lda) - } - bi := blas64.Implementation() - if ul == blas.Upper { - for j := 0; j < n; j += nb { - jb := min(nb, n-j) - bi.Dsyrk(blas.Upper, blas.Trans, jb, j, - -1, a[j:], lda, - 1, a[j*lda+j:], lda) - ok = impl.Dpotf2(blas.Upper, jb, a[j*lda+j:], lda) - if !ok { - return ok - } - if j+jb < n { - bi.Dgemm(blas.Trans, blas.NoTrans, jb, n-j-jb, j, - -1, a[j:], lda, a[j+jb:], lda, - 1, a[j*lda+j+jb:], lda) - bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, jb, n-j-jb, - 1, a[j*lda+j:], lda, - a[j*lda+j+jb:], lda) - } - } - return true - } - for j := 0; j < n; j += nb { - jb := min(nb, n-j) - bi.Dsyrk(blas.Lower, blas.NoTrans, jb, j, - -1, a[j*lda:], lda, - 1, a[j*lda+j:], lda) - ok := impl.Dpotf2(blas.Lower, jb, a[j*lda+j:], lda) - if !ok { - return ok - } - if j+jb < n { - bi.Dgemm(blas.NoTrans, blas.Trans, n-j-jb, jb, j, - -1, a[(j+jb)*lda:], lda, a[j*lda:], lda, - 1, a[(j+jb)*lda+j:], lda) - bi.Dtrsm(blas.Right, blas.Lower, blas.Trans, blas.NonUnit, n-j-jb, jb, - 1, a[j*lda+j:], lda, - a[(j+jb)*lda+j:], lda) - } - } - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go deleted file mode 100644 index 6fa981c1..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright ©2019 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas" - -// Dpotri computes the inverse of a real symmetric positive definite matrix A -// using its Cholesky factorization. -// -// On entry, a contains the triangular factor U or L from the Cholesky -// factorization A = Uᵀ*U or A = L*Lᵀ, as computed by Dpotrf. -// On return, a contains the upper or lower triangle of the (symmetric) -// inverse of A, overwriting the input factor U or L. -func (impl Implementation) Dpotri(uplo blas.Uplo, n int, a []float64, lda int) (ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return true - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - // Invert the triangular Cholesky factor U or L. - ok = impl.Dtrtri(uplo, blas.NonUnit, n, a, lda) - if !ok { - return false - } - - // Form inv(U)*inv(U)ᵀ or inv(L)ᵀ*inv(L). - impl.Dlauum(uplo, n, a, lda) - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go deleted file mode 100644 index 77d07000..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright ©2018 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpotrs solves a system of n linear equations A*X = B where A is an n×n -// symmetric positive definite matrix and B is an n×nrhs matrix. The matrix A is -// represented by its Cholesky factorization -// -// A = Uᵀ*U if uplo == blas.Upper -// A = L*Lᵀ if uplo == blas.Lower -// -// as computed by Dpotrf. On entry, B contains the right-hand side matrix B, on -// return it contains the solution matrix X. -func (Implementation) Dpotrs(uplo blas.Uplo, n, nrhs int, a []float64, lda int, b []float64, ldb int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, nrhs): - panic(badLdB) - } - - // Quick return if possible. - if n == 0 || nrhs == 0 { - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - } - - bi := blas64.Implementation() - - if uplo == blas.Upper { - // Solve Uᵀ * U * X = B where U is stored in the upper triangle of A. - - // Solve Uᵀ * X = B, overwriting B with X. - bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) - // Solve U * X = B, overwriting B with X. - bi.Dtrsm(blas.Left, blas.Upper, blas.NoTrans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) - } else { - // Solve L * Lᵀ * X = B where L is stored in the lower triangle of A. - - // Solve L * X = B, overwriting B with X. - bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) - // Solve Lᵀ * X = B, overwriting B with X. - bi.Dtrsm(blas.Left, blas.Lower, blas.Trans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpstf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpstf2.go deleted file mode 100644 index 79b607dd..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpstf2.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpstf2 computes the Cholesky factorization with complete pivoting of an n×n -// symmetric positive semidefinite matrix A. -// -// The factorization has the form -// -// Pᵀ * A * P = Uᵀ * U , if uplo = blas.Upper, -// Pᵀ * A * P = L * Lᵀ, if uplo = blas.Lower, -// -// where U is an upper triangular matrix, L is lower triangular, and P is a -// permutation matrix. -// -// tol is a user-defined tolerance. The algorithm terminates if the pivot is -// less than or equal to tol. If tol is negative, then n*eps*max(A[k,k]) will be -// used instead. -// -// On return, A contains the factor U or L from the Cholesky factorization and -// piv contains P stored such that P[piv[k],k] = 1. -// -// Dpstf2 returns the computed rank of A and whether the factorization can be -// used to solve a system. Dpstf2 does not attempt to check that A is positive -// semi-definite, so if ok is false, the matrix A is either rank deficient or is -// not positive semidefinite. -// -// The length of piv must be n and the length of work must be at least 2*n, -// otherwise Dpstf2 will panic. -// -// Dpstf2 is an internal routine. It is exported for testing purposes. -func (Implementation) Dpstf2(uplo blas.Uplo, n int, a []float64, lda int, piv []int, tol float64, work []float64) (rank int, ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 0, true - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(piv) != n: - panic(badLenPiv) - case len(work) < 2*n: - panic(shortWork) - } - - // Initialize piv. - for i := range piv[:n] { - piv[i] = i - } - - // Compute the first pivot. - pvt := 0 - ajj := a[0] - for i := 1; i < n; i++ { - aii := a[i*lda+i] - if aii > ajj { - pvt = i - ajj = aii - } - } - if ajj <= 0 || math.IsNaN(ajj) { - return 0, false - } - - // Compute stopping value if not supplied. - dstop := tol - if dstop < 0 { - dstop = float64(n) * dlamchE * ajj - } - - // Set first half of work to zero, holds dot products. - dots := work[:n] - for i := range dots { - dots[i] = 0 - } - work2 := work[n : 2*n] - - bi := blas64.Implementation() - if uplo == blas.Upper { - // Compute the Cholesky factorization Pᵀ * A * P = Uᵀ * U. - for j := 0; j < n; j++ { - // Update dot products and compute possible pivots which are stored - // in the second half of work. - for i := j; i < n; i++ { - if j > 0 { - tmp := a[(j-1)*lda+i] - dots[i] += tmp * tmp - } - work2[i] = a[i*lda+i] - dots[i] - } - if j > 0 { - // Find the pivot. - pvt = j - ajj = work2[pvt] - for k := j + 1; k < n; k++ { - wk := work2[k] - if wk > ajj { - pvt = k - ajj = wk - } - } - // Test for exit. - if ajj <= dstop || math.IsNaN(ajj) { - a[j*lda+j] = ajj - return j, false - } - } - if j != pvt { - // Swap pivot rows and columns. - a[pvt*lda+pvt] = a[j*lda+j] - bi.Dswap(j, a[j:], lda, a[pvt:], lda) - if pvt < n-1 { - bi.Dswap(n-pvt-1, a[j*lda+(pvt+1):], 1, a[pvt*lda+(pvt+1):], 1) - } - bi.Dswap(pvt-j-1, a[j*lda+(j+1):], 1, a[(j+1)*lda+pvt:], lda) - // Swap dot products and piv. - dots[j], dots[pvt] = dots[pvt], dots[j] - piv[j], piv[pvt] = piv[pvt], piv[j] - } - ajj = math.Sqrt(ajj) - a[j*lda+j] = ajj - // Compute elements j+1:n of row j. - if j < n-1 { - bi.Dgemv(blas.Trans, j, n-j-1, - -1, a[j+1:], lda, a[j:], lda, - 1, a[j*lda+j+1:], 1) - bi.Dscal(n-j-1, 1/ajj, a[j*lda+j+1:], 1) - } - } - } else { - // Compute the Cholesky factorization Pᵀ * A * P = L * Lᵀ. - for j := 0; j < n; j++ { - // Update dot products and compute possible pivots which are stored - // in the second half of work. - for i := j; i < n; i++ { - if j > 0 { - tmp := a[i*lda+(j-1)] - dots[i] += tmp * tmp - } - work2[i] = a[i*lda+i] - dots[i] - } - if j > 0 { - // Find the pivot. - pvt = j - ajj = work2[pvt] - for k := j + 1; k < n; k++ { - wk := work2[k] - if wk > ajj { - pvt = k - ajj = wk - } - } - // Test for exit. - if ajj <= dstop || math.IsNaN(ajj) { - a[j*lda+j] = ajj - return j, false - } - } - if j != pvt { - // Swap pivot rows and columns. - a[pvt*lda+pvt] = a[j*lda+j] - bi.Dswap(j, a[j*lda:], 1, a[pvt*lda:], 1) - if pvt < n-1 { - bi.Dswap(n-pvt-1, a[(pvt+1)*lda+j:], lda, a[(pvt+1)*lda+pvt:], lda) - } - bi.Dswap(pvt-j-1, a[(j+1)*lda+j:], lda, a[pvt*lda+(j+1):], 1) - // Swap dot products and piv. - dots[j], dots[pvt] = dots[pvt], dots[j] - piv[j], piv[pvt] = piv[pvt], piv[j] - } - ajj = math.Sqrt(ajj) - a[j*lda+j] = ajj - // Compute elements j+1:n of column j. - if j < n-1 { - bi.Dgemv(blas.NoTrans, n-j-1, j, - -1, a[(j+1)*lda:], lda, a[j*lda:], 1, - 1, a[(j+1)*lda+j:], lda) - bi.Dscal(n-j-1, 1/ajj, a[(j+1)*lda+j:], lda) - } - } - } - return n, true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpstrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpstrf.go deleted file mode 100644 index 46a2fd4b..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpstrf.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright ©2021 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dpstrf computes the Cholesky factorization with complete pivoting of an n×n -// symmetric positive semidefinite matrix A. -// -// The factorization has the form -// -// Pᵀ * A * P = Uᵀ * U , if uplo = blas.Upper, -// Pᵀ * A * P = L * Lᵀ, if uplo = blas.Lower, -// -// where U is an upper triangular matrix, L is lower triangular, and P is a -// permutation matrix. -// -// tol is a user-defined tolerance. The algorithm terminates if the pivot is -// less than or equal to tol. If tol is negative, then n*eps*max(A[k,k]) will be -// used instead. -// -// On return, A contains the factor U or L from the Cholesky factorization and -// piv contains P stored such that P[piv[k],k] = 1. -// -// Dpstrf returns the computed rank of A and whether the factorization can be -// used to solve a system. Dpstrf does not attempt to check that A is positive -// semi-definite, so if ok is false, the matrix A is either rank deficient or is -// not positive semidefinite. -// -// The length of piv must be n and the length of work must be at least 2*n, -// otherwise Dpstrf will panic. -// -// Dpstrf is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dpstrf(uplo blas.Uplo, n int, a []float64, lda int, piv []int, tol float64, work []float64) (rank int, ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return 0, true - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(piv) != n: - panic(badLenPiv) - case len(work) < 2*n: - panic(shortWork) - } - - // Get block size. - nb := impl.Ilaenv(1, "DPOTRF", string(uplo), n, -1, -1, -1) - if nb <= 1 || n <= nb { - // Use unblocked code. - return impl.Dpstf2(uplo, n, a, lda, piv, tol, work) - } - - // Initialize piv. - for i := range piv[:n] { - piv[i] = i - } - - // Compute the first pivot. - pvt := 0 - ajj := a[0] - for i := 1; i < n; i++ { - aii := a[i*lda+i] - if aii > ajj { - pvt = i - ajj = aii - } - } - if ajj <= 0 || math.IsNaN(ajj) { - return 0, false - } - - // Compute stopping value if not supplied. - dstop := tol - if dstop < 0 { - dstop = float64(n) * dlamchE * ajj - } - - bi := blas64.Implementation() - // Split work in half, the first half holds dot products. - dots := work[:n] - work2 := work[n : 2*n] - if uplo == blas.Upper { - // Compute the Cholesky factorization Pᵀ * A * P = Uᵀ * U. - for k := 0; k < n; k += nb { - // Account for last block not being nb wide. - jb := min(nb, n-k) - // Set relevant part of dot products to zero. - for i := k; i < n; i++ { - dots[i] = 0 - } - for j := k; j < k+jb; j++ { - // Update dot products and compute possible pivots which are stored - // in the second half of work. - for i := j; i < n; i++ { - if j > k { - tmp := a[(j-1)*lda+i] - dots[i] += tmp * tmp - } - work2[i] = a[i*lda+i] - dots[i] - } - if j > 0 { - // Find the pivot. - pvt = j - ajj = work2[pvt] - for l := j + 1; l < n; l++ { - wl := work2[l] - if wl > ajj { - pvt = l - ajj = wl - } - } - // Test for exit. - if ajj <= dstop || math.IsNaN(ajj) { - a[j*lda+j] = ajj - return j, false - } - } - if j != pvt { - // Swap pivot rows and columns. - a[pvt*lda+pvt] = a[j*lda+j] - bi.Dswap(j, a[j:], lda, a[pvt:], lda) - if pvt < n-1 { - bi.Dswap(n-pvt-1, a[j*lda+(pvt+1):], 1, a[pvt*lda+(pvt+1):], 1) - } - bi.Dswap(pvt-j-1, a[j*lda+(j+1):], 1, a[(j+1)*lda+pvt:], lda) - // Swap dot products and piv. - dots[j], dots[pvt] = dots[pvt], dots[j] - piv[j], piv[pvt] = piv[pvt], piv[j] - } - ajj = math.Sqrt(ajj) - a[j*lda+j] = ajj - // Compute elements j+1:n of row j. - if j < n-1 { - bi.Dgemv(blas.Trans, j-k, n-j-1, - -1, a[k*lda+j+1:], lda, a[k*lda+j:], lda, - 1, a[j*lda+j+1:], 1) - bi.Dscal(n-j-1, 1/ajj, a[j*lda+j+1:], 1) - } - } - // Update trailing matrix. - if k+jb < n { - j := k + jb - bi.Dsyrk(blas.Upper, blas.Trans, n-j, jb, - -1, a[k*lda+j:], lda, 1, a[j*lda+j:], lda) - } - } - } else { - // Compute the Cholesky factorization Pᵀ * A * P = L * Lᵀ. - for k := 0; k < n; k += nb { - // Account for last block not being nb wide. - jb := min(nb, n-k) - // Set relevant part of dot products to zero. - for i := k; i < n; i++ { - dots[i] = 0 - } - for j := k; j < k+jb; j++ { - // Update dot products and compute possible pivots which are stored - // in the second half of work. - for i := j; i < n; i++ { - if j > k { - tmp := a[i*lda+(j-1)] - dots[i] += tmp * tmp - } - work2[i] = a[i*lda+i] - dots[i] - } - if j > 0 { - // Find the pivot. - pvt = j - ajj = work2[pvt] - for l := j + 1; l < n; l++ { - wl := work2[l] - if wl > ajj { - pvt = l - ajj = wl - } - } - // Test for exit. - if ajj <= dstop || math.IsNaN(ajj) { - a[j*lda+j] = ajj - return j, false - } - } - if j != pvt { - // Swap pivot rows and columns. - a[pvt*lda+pvt] = a[j*lda+j] - bi.Dswap(j, a[j*lda:], 1, a[pvt*lda:], 1) - if pvt < n-1 { - bi.Dswap(n-pvt-1, a[(pvt+1)*lda+j:], lda, a[(pvt+1)*lda+pvt:], lda) - } - bi.Dswap(pvt-j-1, a[(j+1)*lda+j:], lda, a[pvt*lda+(j+1):], 1) - // Swap dot products and piv. - dots[j], dots[pvt] = dots[pvt], dots[j] - piv[j], piv[pvt] = piv[pvt], piv[j] - } - ajj = math.Sqrt(ajj) - a[j*lda+j] = ajj - // Compute elements j+1:n of column j. - if j < n-1 { - bi.Dgemv(blas.NoTrans, n-j-1, j-k, - -1, a[(j+1)*lda+k:], lda, a[j*lda+k:], 1, - 1, a[(j+1)*lda+j:], lda) - bi.Dscal(n-j-1, 1/ajj, a[(j+1)*lda+j:], lda) - } - } - // Update trailing matrix. - if k+jb < n { - j := k + jb - bi.Dsyrk(blas.Lower, blas.NoTrans, n-j, jb, - -1, a[j*lda+k:], lda, 1, a[j*lda+j:], lda) - } - } - } - return n, true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dptcon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dptcon.go deleted file mode 100644 index cd41e317..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dptcon.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright ©2023 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Dptcon computes and returns the reciprocal of the condition number (in the -// 1-norm) of a symmetric positive definite tridiagonal matrix A using the -// factorization A = L*D*Lᵀ or A = Uᵀ*D*U computed by Dpttrf. -// -// The reciprocal of the condition number is computed as -// -// rcond = 1 / (anorm * ‖A⁻¹‖) -// -// and ‖A⁻¹‖ is computed by a direct method. -// -// d and e contain, respectively, the n diagonal elements of the diagonal matrix -// D and the (n-1) off-diagonal elements of the unit bidiagonal factor U or L -// from the factorization of A, as computed by Dpttrf. -// -// anorm is the 1-norm of the original matrix A. -// -// work must have length n, otherwise Dptcon will panic. -func (impl Implementation) Dptcon(n int, d, e []float64, anorm float64, work []float64) (rcond float64) { - switch { - case n < 0: - panic(nLT0) - case anorm < 0: - panic(badNorm) - } - - // Quick return if possible. - if n == 0 { - return 1 - } - - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - case len(work) < n: - panic(shortWork) - } - - // Quick return if possible. - switch { - case anorm == 0: - return 0 - case math.IsNaN(anorm): - // Propagate NaN. - return anorm - case math.IsInf(anorm, 1): - return 0 - } - - // Check that d[0:n] is positive. - for _, di := range d[:n] { - if di <= 0 { - return 0 - } - } - - // Solve M(A) * x = e, where M(A) = (m[i,j]) is given by - // - // m[i,j] = abs(A[i,j]), i == j, - // m[i,j] = -abs(A[i,j]), i != j, - // - // and e = [1,1,...,1]ᵀ. Note M(A) = M(L)*D*M(L)ᵀ. - - // Solve M(L) * b = e. - work[0] = 1 - for i := 1; i < n; i++ { - work[i] = 1 + work[i-1]*math.Abs(e[i-1]) - } - - // Solve D * M(L)ᵀ * x = b. - work[n-1] /= d[n-1] - for i := n - 2; i >= 0; i-- { - work[i] = work[i]/d[i] + work[i+1]*math.Abs(e[i]) - } - - // Compute ainvnm = max(x[i]), 0<=i<n. - bi := blas64.Implementation() - ix := bi.Idamax(n, work, 1) - ainvnm := math.Abs(work[ix]) - if ainvnm == 0 { - return 0 - } - - // Compute the reciprocal condition number. - return 1 / ainvnm / anorm -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dptsv.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dptsv.go deleted file mode 100644 index 37851b63..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dptsv.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright ©2023 The Gonum 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 gonum - -// Dptsv computes the solution to system of linear equations -// -// A * X = B -// -// where A is an n×n symmetric positive definite tridiagonal matrix, and X and B -// are n×nrhs matrices. A is factored as A = L*D*Lᵀ, and the factored form of A -// is then used to solve the system of equations. -// -// On entry, d contains the n diagonal elements of A and e contains the (n-1) -// subdiagonal elements of A. On return, d contains the n diagonal elements of -// the diagonal matrix D from the factorization A = L*D*Lᵀ and e contains the -// (n-1) subdiagonal elements of the unit bidiagonal factor L. -// -// Dptsv returns whether the solution X has been successfully computed. -func (impl Implementation) Dptsv(n, nrhs int, d, e []float64, b []float64, ldb int) (ok bool) { - switch { - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case ldb < max(1, nrhs): - panic(badLdB) - } - - if n == 0 || nrhs == 0 { - return true - } - - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - } - - ok = impl.Dpttrf(n, d, e) - if ok { - impl.Dpttrs(n, nrhs, d, e, b, ldb) - } - return ok -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpttrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpttrf.go deleted file mode 100644 index 8ff2c2e4..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpttrf.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright ©2023 The Gonum 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 gonum - -// Dpttrf computes the L*D*Lᵀ factorization of an n×n symmetric positive -// definite tridiagonal matrix A and returns whether the factorization was -// successful. -// -// On entry, d and e contain the n diagonal and (n-1) subdiagonal elements, -// respectively, of A. -// -// On return, d contains the n diagonal elements of the diagonal matrix D and e -// contains the (n-1) subdiagonal elements of the unit bidiagonal matrix L. -func (impl Implementation) Dpttrf(n int, d, e []float64) (ok bool) { - if n < 0 { - panic(nLT0) - } - - if n == 0 { - return true - } - - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - } - - // Compute the L*D*Lᵀ (or Uᵀ*D*U) factorization of A. - i4 := (n - 1) % 4 - for i := 0; i < i4; i++ { - if d[i] <= 0 { - return false - } - ei := e[i] - e[i] /= d[i] - d[i+1] -= e[i] * ei - } - for i := i4; i < n-4; i += 4 { - // Drop out of the loop if d[i] <= 0: the matrix is not positive - // definite. - if d[i] <= 0 { - return false - } - - // Solve for e[i] and d[i+1]. - ei := e[i] - e[i] /= d[i] - d[i+1] -= e[i] * ei - if d[i+1] <= 0 { - return false - } - - // Solve for e[i+1] and d[i+2]. - ei = e[i+1] - e[i+1] /= d[i+1] - d[i+2] -= e[i+1] * ei - if d[i+2] <= 0 { - return false - } - - // Solve for e[i+2] and d[i+3]. - ei = e[i+2] - e[i+2] /= d[i+2] - d[i+3] -= e[i+2] * ei - if d[i+3] <= 0 { - return false - } - - // Solve for e[i+3] and d[i+4]. - ei = e[i+3] - e[i+3] /= d[i+3] - d[i+4] -= e[i+3] * ei - } - // Check d[n-1] for positive definiteness. - return d[n-1] > 0 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpttrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpttrs.go deleted file mode 100644 index 7bdee6f9..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpttrs.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright ©2023 The Gonum 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 gonum - -// Dpttrs solves a tridiagonal system of the form -// -// A * X = B -// -// using the L*D*Lᵀ factorization of A computed by Dpttrf. D is a diagonal -// matrix specified in d, L is a unit bidiagonal matrix whose subdiagonal is -// specified in e, and X and B are n×nrhs matrices. -func (impl Implementation) Dpttrs(n, nrhs int, d, e []float64, b []float64, ldb int) { - switch { - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case ldb < max(1, nrhs): - panic(badLdB) - } - - // Quick return if possible. - if n == 0 || nrhs == 0 { - return - } - - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - } - - nb := 1 - if nrhs > 1 { - nb = max(1, impl.Ilaenv(1, "DPTTRS", " ", n, nrhs, -1, -1)) - } - - if nb >= nrhs { - impl.dptts2(n, nrhs, d, e, b, ldb) - } else { - for j := 0; j < nrhs; j += nb { - jb := min(nrhs-j, nb) - impl.dptts2(n, jb, d, e, b[j:], ldb) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dptts2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dptts2.go deleted file mode 100644 index ff1df168..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dptts2.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright ©2023 The Gonum 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 gonum - -import "gonum.org/v1/gonum/blas/blas64" - -// dptts2 solves a tridiagonal system of the form -// -// A * X = B -// -// using the L*D*Lᵀ factorization of A computed by Dpttrf. D is a diagonal -// matrix specified in d, L is a unit bidiagonal matrix whose subdiagonal is -// specified in e, and X and B are n×nrhs matrices. -func (impl Implementation) dptts2(n, nrhs int, d, e []float64, b []float64, ldb int) { - // Quick return if possible. - if n <= 1 { - if n == 1 { - bi := blas64.Implementation() - bi.Dscal(nrhs, 1/d[0], b, 1) - } - return - } - - // Solve A * X = B using the factorization A = L*D*Lᵀ, overwriting each - // right hand side vector with its solution. - for j := 0; j < nrhs; j++ { - // Solve L * x = b. - for i := 1; i < n; i++ { - b[i*ldb+j] -= b[(i-1)*ldb+j] * e[i-1] - } - // Solve D * Lᵀ * x = b. - b[(n-1)*ldb+j] /= d[n-1] - for i := n - 2; i >= 0; i-- { - b[i*ldb+j] = b[i*ldb+j]/d[i] - b[(i+1)*ldb+j]*e[i] - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go b/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go deleted file mode 100644 index b2772dbc..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas/blas64" -) - -// Drscl multiplies the vector x by 1/a being careful to avoid overflow or -// underflow where possible. -// -// Drscl is an internal routine. It is exported for testing purposes. -func (impl Implementation) Drscl(n int, a float64, x []float64, incX int) { - switch { - case n < 0: - panic(nLT0) - case incX <= 0: - panic(badIncX) - } - - // Quick return if possible. - if n == 0 { - return - } - - if len(x) < 1+(n-1)*incX { - panic(shortX) - } - - bi := blas64.Implementation() - - cden := a - cnum := 1.0 - smlnum := dlamchS - bignum := 1 / smlnum - for { - cden1 := cden * smlnum - cnum1 := cnum / bignum - var mul float64 - var done bool - switch { - case cnum != 0 && math.Abs(cden1) > math.Abs(cnum): - mul = smlnum - done = false - cden = cden1 - case math.Abs(cnum1) > math.Abs(cden): - mul = bignum - done = false - cnum = cnum1 - default: - mul = cnum / cden - done = true - } - bi.Dscal(n, mul, x, incX) - if done { - break - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go deleted file mode 100644 index d6c7861a..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dsteqr computes the eigenvalues and optionally the eigenvectors of a symmetric -// tridiagonal matrix using the implicit QL or QR method. The eigenvectors of a -// full or band symmetric matrix can also be found if Dsytrd, Dsptrd, or Dsbtrd -// have been used to reduce this matrix to tridiagonal form. -// -// d, on entry, contains the diagonal elements of the tridiagonal matrix. On exit, -// d contains the eigenvalues in ascending order. d must have length n and -// Dsteqr will panic otherwise. -// -// e, on entry, contains the off-diagonal elements of the tridiagonal matrix on -// entry, and is overwritten during the call to Dsteqr. e must have length n-1 and -// Dsteqr will panic otherwise. -// -// z, on entry, contains the n×n orthogonal matrix used in the reduction to -// tridiagonal form if compz == lapack.EVOrig. On exit, if -// compz == lapack.EVOrig, z contains the orthonormal eigenvectors of the -// original symmetric matrix, and if compz == lapack.EVTridiag, z contains the -// orthonormal eigenvectors of the symmetric tridiagonal matrix. z is not used -// if compz == lapack.EVCompNone. -// -// work must have length at least max(1, 2*n-2) if the eigenvectors are computed, -// and Dsteqr will panic otherwise. -// -// Dsteqr is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dsteqr(compz lapack.EVComp, n int, d, e, z []float64, ldz int, work []float64) (ok bool) { - switch { - case compz != lapack.EVCompNone && compz != lapack.EVTridiag && compz != lapack.EVOrig: - panic(badEVComp) - case n < 0: - panic(nLT0) - case ldz < 1, compz != lapack.EVCompNone && ldz < n: - panic(badLdZ) - } - - // Quick return if possible. - if n == 0 { - return true - } - - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - case compz != lapack.EVCompNone && len(z) < (n-1)*ldz+n: - panic(shortZ) - case compz != lapack.EVCompNone && len(work) < max(1, 2*n-2): - panic(shortWork) - } - - var icompz int - if compz == lapack.EVOrig { - icompz = 1 - } else if compz == lapack.EVTridiag { - icompz = 2 - } - - if n == 1 { - if icompz == 2 { - z[0] = 1 - } - return true - } - - bi := blas64.Implementation() - - eps := dlamchE - eps2 := eps * eps - safmin := dlamchS - safmax := 1 / safmin - ssfmax := math.Sqrt(safmax) / 3 - ssfmin := math.Sqrt(safmin) / eps2 - - // Compute the eigenvalues and eigenvectors of the tridiagonal matrix. - if icompz == 2 { - impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) - } - const maxit = 30 - nmaxit := n * maxit - - jtot := 0 - - // Determine where the matrix splits and choose QL or QR iteration for each - // block, according to whether top or bottom diagonal element is smaller. - l1 := 0 - nm1 := n - 1 - - type scaletype int - const ( - down scaletype = iota + 1 - up - ) - var iscale scaletype - - for { - if l1 > n-1 { - // Order eigenvalues and eigenvectors. - if icompz == 0 { - impl.Dlasrt(lapack.SortIncreasing, n, d) - } else { - // TODO(btracey): Consider replacing this sort with a call to sort.Sort. - for ii := 1; ii < n; ii++ { - i := ii - 1 - k := i - p := d[i] - for j := ii; j < n; j++ { - if d[j] < p { - k = j - p = d[j] - } - } - if k != i { - d[k] = d[i] - d[i] = p - bi.Dswap(n, z[i:], ldz, z[k:], ldz) - } - } - } - return true - } - if l1 > 0 { - e[l1-1] = 0 - } - var m int - if l1 <= nm1 { - for m = l1; m < nm1; m++ { - test := math.Abs(e[m]) - if test == 0 { - break - } - if test <= (math.Sqrt(math.Abs(d[m]))*math.Sqrt(math.Abs(d[m+1])))*eps { - e[m] = 0 - break - } - } - } - l := l1 - lsv := l - lend := m - lendsv := lend - l1 = m + 1 - if lend == l { - continue - } - - // Scale submatrix in rows and columns L to Lend - anorm := impl.Dlanst(lapack.MaxAbs, lend-l+1, d[l:], e[l:]) - switch { - case anorm == 0: - continue - case anorm > ssfmax: - iscale = down - // Pretend that d and e are matrices with 1 column. - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l+1, 1, d[l:], 1) - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l, 1, e[l:], 1) - case anorm < ssfmin: - iscale = up - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l+1, 1, d[l:], 1) - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l, 1, e[l:], 1) - } - - // Choose between QL and QR. - if math.Abs(d[lend]) < math.Abs(d[l]) { - lend = lsv - l = lendsv - } - if lend > l { - // QL Iteration. Look for small subdiagonal element. - for { - if l != lend { - for m = l; m < lend; m++ { - v := math.Abs(e[m]) - if v*v <= (eps2*math.Abs(d[m]))*math.Abs(d[m+1])+safmin { - break - } - } - } else { - m = lend - } - if m < lend { - e[m] = 0 - } - p := d[l] - if m == l { - // Eigenvalue found. - l++ - if l > lend { - break - } - continue - } - - // If remaining matrix is 2×2, use Dlae2 to compute its eigensystem. - if m == l+1 { - if icompz > 0 { - d[l], d[l+1], work[l], work[n-1+l] = impl.Dlaev2(d[l], e[l], d[l+1]) - impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, - n, 2, work[l:], work[n-1+l:], z[l:], ldz) - } else { - d[l], d[l+1] = impl.Dlae2(d[l], e[l], d[l+1]) - } - e[l] = 0 - l += 2 - if l > lend { - break - } - continue - } - - if jtot == nmaxit { - break - } - jtot++ - - // Form shift - g := (d[l+1] - p) / (2 * e[l]) - r := impl.Dlapy2(g, 1) - g = d[m] - p + e[l]/(g+math.Copysign(r, g)) - s := 1.0 - c := 1.0 - p = 0.0 - - // Inner loop - for i := m - 1; i >= l; i-- { - f := s * e[i] - b := c * e[i] - c, s, r = impl.Dlartg(g, f) - if i != m-1 { - e[i+1] = r - } - g = d[i+1] - p - r = (d[i]-g)*s + 2*c*b - p = s * r - d[i+1] = g + p - g = c*r - b - - // If eigenvectors are desired, then save rotations. - if icompz > 0 { - work[i] = c - work[n-1+i] = -s - } - } - // If eigenvectors are desired, then apply saved rotations. - if icompz > 0 { - mm := m - l + 1 - impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, - n, mm, work[l:], work[n-1+l:], z[l:], ldz) - } - d[l] -= p - e[l] = g - } - } else { - // QR Iteration. - // Look for small superdiagonal element. - for { - if l != lend { - for m = l; m > lend; m-- { - v := math.Abs(e[m-1]) - if v*v <= (eps2*math.Abs(d[m])*math.Abs(d[m-1]) + safmin) { - break - } - } - } else { - m = lend - } - if m > lend { - e[m-1] = 0 - } - p := d[l] - if m == l { - // Eigenvalue found - l-- - if l < lend { - break - } - continue - } - - // If remaining matrix is 2×2, use Dlae2 to compute its eigenvalues. - if m == l-1 { - if icompz > 0 { - d[l-1], d[l], work[m], work[n-1+m] = impl.Dlaev2(d[l-1], e[l-1], d[l]) - impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, - n, 2, work[m:], work[n-1+m:], z[l-1:], ldz) - } else { - d[l-1], d[l] = impl.Dlae2(d[l-1], e[l-1], d[l]) - } - e[l-1] = 0 - l -= 2 - if l < lend { - break - } - continue - } - if jtot == nmaxit { - break - } - jtot++ - - // Form shift. - g := (d[l-1] - p) / (2 * e[l-1]) - r := impl.Dlapy2(g, 1) - g = d[m] - p + (e[l-1])/(g+math.Copysign(r, g)) - s := 1.0 - c := 1.0 - p = 0.0 - - // Inner loop. - for i := m; i < l; i++ { - f := s * e[i] - b := c * e[i] - c, s, r = impl.Dlartg(g, f) - if i != m { - e[i-1] = r - } - g = d[i] - p - r = (d[i+1]-g)*s + 2*c*b - p = s * r - d[i] = g + p - g = c*r - b - - // If eigenvectors are desired, then save rotations. - if icompz > 0 { - work[i] = c - work[n-1+i] = s - } - } - - // If eigenvectors are desired, then apply saved rotations. - if icompz > 0 { - mm := l - m + 1 - impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, - n, mm, work[m:], work[n-1+m:], z[m:], ldz) - } - d[l] -= p - e[l-1] = g - } - } - - // Undo scaling if necessary. - switch iscale { - case down: - // Pretend that d and e are matrices with 1 column. - impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, d[lsv:], 1) - impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv, 1, e[lsv:], 1) - case up: - impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, d[lsv:], 1) - impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv, 1, e[lsv:], 1) - } - - // Check for no convergence to an eigenvalue after a total of n*maxit iterations. - if jtot >= nmaxit { - break - } - } - for i := 0; i < n-1; i++ { - if e[i] != 0 { - return false - } - } - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go deleted file mode 100644 index dc1e178d..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/lapack" -) - -// Dsterf computes all eigenvalues of a symmetric tridiagonal matrix using the -// Pal-Walker-Kahan variant of the QL or QR algorithm. -// -// d contains the diagonal elements of the tridiagonal matrix on entry, and -// contains the eigenvalues in ascending order on exit. d must have length at -// least n, or Dsterf will panic. -// -// e contains the off-diagonal elements of the tridiagonal matrix on entry, and is -// overwritten during the call to Dsterf. e must have length of at least n-1 or -// Dsterf will panic. -// -// Dsterf is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dsterf(n int, d, e []float64) (ok bool) { - if n < 0 { - panic(nLT0) - } - - // Quick return if possible. - if n == 0 { - return true - } - - switch { - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - } - - if n == 1 { - return true - } - - const ( - none = 0 // The values are not scaled. - down = 1 // The values are scaled below ssfmax threshold. - up = 2 // The values are scaled below ssfmin threshold. - ) - - // Determine the unit roundoff for this environment. - eps := dlamchE - eps2 := eps * eps - safmin := dlamchS - safmax := 1 / safmin - ssfmax := math.Sqrt(safmax) / 3 - ssfmin := math.Sqrt(safmin) / eps2 - - // Compute the eigenvalues of the tridiagonal matrix. - maxit := 30 - nmaxit := n * maxit - jtot := 0 - - l1 := 0 - - for { - if l1 > n-1 { - impl.Dlasrt(lapack.SortIncreasing, n, d) - return true - } - if l1 > 0 { - e[l1-1] = 0 - } - var m int - for m = l1; m < n-1; m++ { - if math.Abs(e[m]) <= math.Sqrt(math.Abs(d[m]))*math.Sqrt(math.Abs(d[m+1]))*eps { - e[m] = 0 - break - } - } - - l := l1 - lsv := l - lend := m - lendsv := lend - l1 = m + 1 - if lend == 0 { - continue - } - - // Scale submatrix in rows and columns l to lend. - anorm := impl.Dlanst(lapack.MaxAbs, lend-l+1, d[l:], e[l:]) - iscale := none - if anorm == 0 { - continue - } - if anorm > ssfmax { - iscale = down - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l+1, 1, d[l:], n) - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l, 1, e[l:], n) - } else if anorm < ssfmin { - iscale = up - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l+1, 1, d[l:], n) - impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l, 1, e[l:], n) - } - - el := e[l:lend] - for i, v := range el { - el[i] *= v - } - - // Choose between QL and QR iteration. - if math.Abs(d[lend]) < math.Abs(d[l]) { - lend = lsv - l = lendsv - } - if lend >= l { - // QL Iteration. - // Look for small sub-diagonal element. - for { - if l != lend { - for m = l; m < lend; m++ { - if math.Abs(e[m]) <= eps2*(math.Abs(d[m]*d[m+1])) { - break - } - } - } else { - m = lend - } - if m < lend { - e[m] = 0 - } - p := d[l] - if m == l { - // Eigenvalue found. - l++ - if l > lend { - break - } - continue - } - // If remaining matrix is 2 by 2, use Dlae2 to compute its eigenvalues. - if m == l+1 { - d[l], d[l+1] = impl.Dlae2(d[l], math.Sqrt(e[l]), d[l+1]) - e[l] = 0 - l += 2 - if l > lend { - break - } - continue - } - if jtot == nmaxit { - break - } - jtot++ - - // Form shift. - rte := math.Sqrt(e[l]) - sigma := (d[l+1] - p) / (2 * rte) - r := impl.Dlapy2(sigma, 1) - sigma = p - (rte / (sigma + math.Copysign(r, sigma))) - - c := 1.0 - s := 0.0 - gamma := d[m] - sigma - p = gamma * gamma - - // Inner loop. - for i := m - 1; i >= l; i-- { - bb := e[i] - r := p + bb - if i != m-1 { - e[i+1] = s * r - } - oldc := c - c = p / r - s = bb / r - oldgam := gamma - alpha := d[i] - gamma = c*(alpha-sigma) - s*oldgam - d[i+1] = oldgam + (alpha - gamma) - if c != 0 { - p = (gamma * gamma) / c - } else { - p = oldc * bb - } - } - e[l] = s * p - d[l] = sigma + gamma - } - } else { - for { - // QR Iteration. - // Look for small super-diagonal element. - for m = l; m > lend; m-- { - if math.Abs(e[m-1]) <= eps2*math.Abs(d[m]*d[m-1]) { - break - } - } - if m > lend { - e[m-1] = 0 - } - p := d[l] - if m == l { - // Eigenvalue found. - l-- - if l < lend { - break - } - continue - } - - // If remaining matrix is 2 by 2, use Dlae2 to compute its eigenvalues. - if m == l-1 { - d[l], d[l-1] = impl.Dlae2(d[l], math.Sqrt(e[l-1]), d[l-1]) - e[l-1] = 0 - l -= 2 - if l < lend { - break - } - continue - } - if jtot == nmaxit { - break - } - jtot++ - - // Form shift. - rte := math.Sqrt(e[l-1]) - sigma := (d[l-1] - p) / (2 * rte) - r := impl.Dlapy2(sigma, 1) - sigma = p - (rte / (sigma + math.Copysign(r, sigma))) - - c := 1.0 - s := 0.0 - gamma := d[m] - sigma - p = gamma * gamma - - // Inner loop. - for i := m; i < l; i++ { - bb := e[i] - r := p + bb - if i != m { - e[i-1] = s * r - } - oldc := c - c = p / r - s = bb / r - oldgam := gamma - alpha := d[i+1] - gamma = c*(alpha-sigma) - s*oldgam - d[i] = oldgam + alpha - gamma - if c != 0 { - p = (gamma * gamma) / c - } else { - p = oldc * bb - } - } - e[l-1] = s * p - d[l] = sigma + gamma - } - } - - // Undo scaling if necessary - switch iscale { - case down: - impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, d[lsv:], n) - case up: - impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, d[lsv:], n) - } - - // Check for no convergence to an eigenvalue after a total of n*maxit iterations. - if jtot >= nmaxit { - break - } - } - for _, v := range e[:n-1] { - if v != 0 { - return false - } - } - impl.Dlasrt(lapack.SortIncreasing, n, d) - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go deleted file mode 100644 index 5f57f3a5..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dsyev computes all eigenvalues and, optionally, the eigenvectors of a real -// symmetric matrix A. -// -// w contains the eigenvalues in ascending order upon return. w must have length -// at least n, and Dsyev will panic otherwise. -// -// On entry, a contains the elements of the symmetric matrix A in the triangular -// portion specified by uplo. If jobz == lapack.EVCompute, a contains the -// orthonormal eigenvectors of A on exit, otherwise jobz must be lapack.EVNone -// and on exit the specified triangular region is overwritten. -// -// work is temporary storage, and lwork specifies the usable memory length. At minimum, -// lwork >= 3*n-1, and Dsyev will panic otherwise. The amount of blocking is -// limited by the usable length. If lwork == -1, instead of computing Dsyev the -// optimal work length is stored into work[0]. -func (impl Implementation) Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) { - switch { - case jobz != lapack.EVNone && jobz != lapack.EVCompute: - panic(badEVJob) - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < max(1, 3*n-1) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - return true - } - - var opts string - if uplo == blas.Upper { - opts = "U" - } else { - opts = "L" - } - nb := impl.Ilaenv(1, "DSYTRD", opts, n, -1, -1, -1) - lworkopt := max(1, (nb+2)*n) - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(w) < n: - panic(shortW) - } - - if n == 1 { - w[0] = a[0] - work[0] = 2 - if jobz == lapack.EVCompute { - a[0] = 1 - } - return true - } - - safmin := dlamchS - eps := dlamchP - smlnum := safmin / eps - bignum := 1 / smlnum - rmin := math.Sqrt(smlnum) - rmax := math.Sqrt(bignum) - - // Scale matrix to allowable range, if necessary. - anrm := impl.Dlansy(lapack.MaxAbs, uplo, n, a, lda, work) - scaled := false - var sigma float64 - if anrm > 0 && anrm < rmin { - scaled = true - sigma = rmin / anrm - } else if anrm > rmax { - scaled = true - sigma = rmax / anrm - } - if scaled { - kind := lapack.LowerTri - if uplo == blas.Upper { - kind = lapack.UpperTri - } - impl.Dlascl(kind, 0, 0, 1, sigma, n, n, a, lda) - } - var inde int - indtau := inde + n - indwork := indtau + n - llwork := lwork - indwork - impl.Dsytrd(uplo, n, a, lda, w, work[inde:], work[indtau:], work[indwork:], llwork) - - // For eigenvalues only, call Dsterf. For eigenvectors, first call Dorgtr - // to generate the orthogonal matrix, then call Dsteqr. - if jobz == lapack.EVNone { - ok = impl.Dsterf(n, w, work[inde:]) - } else { - impl.Dorgtr(uplo, n, a, lda, work[indtau:], work[indwork:], llwork) - ok = impl.Dsteqr(lapack.EVComp(jobz), n, w, work[inde:], a, lda, work[indtau:]) - } - if !ok { - return false - } - - // If the matrix was scaled, then rescale eigenvalues appropriately. - if scaled { - bi := blas64.Implementation() - bi.Dscal(n, 1/sigma, w, 1) - } - work[0] = float64(lworkopt) - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go deleted file mode 100644 index 03e7cc07..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dsytd2 reduces a symmetric n×n matrix A to symmetric tridiagonal form T by -// an orthogonal similarity transformation -// -// Qᵀ * A * Q = T -// -// On entry, the matrix is contained in the specified triangle of a. On exit, -// if uplo == blas.Upper, the diagonal and first super-diagonal of a are -// overwritten with the elements of T. The elements above the first super-diagonal -// are overwritten with the elementary reflectors that are used with -// the elements written to tau in order to construct Q. If uplo == blas.Lower, -// the elements are written in the lower triangular region. -// -// d must have length at least n. e and tau must have length at least n-1. Dsytd2 -// will panic if these sizes are not met. -// -// Q is represented as a product of elementary reflectors. -// If uplo == blas.Upper -// -// Q = H_{n-2} * ... * H_1 * H_0 -// -// and if uplo == blas.Lower -// -// Q = H_0 * H_1 * ... * H_{n-2} -// -// where -// -// H_i = I - tau * v * vᵀ -// -// where tau is stored in tau[i], and v is stored in a. -// -// If uplo == blas.Upper, v[0:i-1] is stored in A[0:i-1,i+1], v[i] = 1, and -// v[i+1:] = 0. The elements of a are -// -// [ d e v2 v3 v4] -// [ d e v3 v4] -// [ d e v4] -// [ d e] -// [ d] -// -// If uplo == blas.Lower, v[0:i+1] = 0, v[i+1] = 1, and v[i+2:] is stored in -// A[i+2:n,i]. -// The elements of a are -// -// [ d ] -// [ e d ] -// [v1 e d ] -// [v1 v2 e d ] -// [v1 v2 v3 e d] -// -// Dsytd2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dsytd2(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau []float64) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - // Quick return if possible. - if n == 0 { - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - case len(tau) < n-1: - panic(shortTau) - } - - bi := blas64.Implementation() - - if uplo == blas.Upper { - // Reduce the upper triangle of A. - for i := n - 2; i >= 0; i-- { - // Generate elementary reflector H_i = I - tau * v * vᵀ to - // annihilate A[i:i-1, i+1]. - var taui float64 - a[i*lda+i+1], taui = impl.Dlarfg(i+1, a[i*lda+i+1], a[i+1:], lda) - e[i] = a[i*lda+i+1] - if taui != 0 { - // Apply H_i from both sides to A[0:i,0:i]. - a[i*lda+i+1] = 1 - - // Compute x := tau * A * v storing x in tau[0:i]. - bi.Dsymv(uplo, i+1, taui, a, lda, a[i+1:], lda, 0, tau, 1) - - // Compute w := x - 1/2 * tau * (xᵀ * v) * v. - alpha := -0.5 * taui * bi.Ddot(i+1, tau, 1, a[i+1:], lda) - bi.Daxpy(i+1, alpha, a[i+1:], lda, tau, 1) - - // Apply the transformation as a rank-2 update - // A = A - v * wᵀ - w * vᵀ. - bi.Dsyr2(uplo, i+1, -1, a[i+1:], lda, tau, 1, a, lda) - a[i*lda+i+1] = e[i] - } - d[i+1] = a[(i+1)*lda+i+1] - tau[i] = taui - } - d[0] = a[0] - return - } - // Reduce the lower triangle of A. - for i := 0; i < n-1; i++ { - // Generate elementary reflector H_i = I - tau * v * vᵀ to - // annihilate A[i+2:n, i]. - var taui float64 - a[(i+1)*lda+i], taui = impl.Dlarfg(n-i-1, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) - e[i] = a[(i+1)*lda+i] - if taui != 0 { - // Apply H_i from both sides to A[i+1:n, i+1:n]. - a[(i+1)*lda+i] = 1 - - // Compute x := tau * A * v, storing y in tau[i:n-1]. - bi.Dsymv(uplo, n-i-1, taui, a[(i+1)*lda+i+1:], lda, a[(i+1)*lda+i:], lda, 0, tau[i:], 1) - - // Compute w := x - 1/2 * tau * (xᵀ * v) * v. - alpha := -0.5 * taui * bi.Ddot(n-i-1, tau[i:], 1, a[(i+1)*lda+i:], lda) - bi.Daxpy(n-i-1, alpha, a[(i+1)*lda+i:], lda, tau[i:], 1) - - // Apply the transformation as a rank-2 update - // A = A - v * wᵀ - w * vᵀ. - bi.Dsyr2(uplo, n-i-1, -1, a[(i+1)*lda+i:], lda, tau[i:], 1, a[(i+1)*lda+i+1:], lda) - a[(i+1)*lda+i] = e[i] - } - d[i] = a[i*lda+i] - tau[i] = taui - } - d[n-1] = a[(n-1)*lda+n-1] -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go deleted file mode 100644 index 74d2287e..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dsytrd reduces a symmetric n×n matrix A to symmetric tridiagonal form by an -// orthogonal similarity transformation -// -// Qᵀ * A * Q = T -// -// where Q is an orthonormal matrix and T is symmetric and tridiagonal. -// -// On entry, a contains the elements of the input matrix in the triangle specified -// by uplo. On exit, the diagonal and sub/super-diagonal are overwritten by the -// corresponding elements of the tridiagonal matrix T. The remaining elements in -// the triangle, along with the array tau, contain the data to construct Q as -// the product of elementary reflectors. -// -// If uplo == blas.Upper, Q is constructed with -// -// Q = H_{n-2} * ... * H_1 * H_0 -// -// where -// -// H_i = I - tau_i * v * vᵀ -// -// v is constructed as v[i+1:n] = 0, v[i] = 1, v[0:i-1] is stored in A[0:i-1, i+1]. -// The elements of A are -// -// [ d e v1 v2 v3] -// [ d e v2 v3] -// [ d e v3] -// [ d e] -// [ e] -// -// If uplo == blas.Lower, Q is constructed with -// -// Q = H_0 * H_1 * ... * H_{n-2} -// -// where -// -// H_i = I - tau_i * v * vᵀ -// -// v is constructed as v[0:i+1] = 0, v[i+1] = 1, v[i+2:n] is stored in A[i+2:n, i]. -// The elements of A are -// -// [ d ] -// [ e d ] -// [v0 e d ] -// [v0 v1 e d ] -// [v0 v1 v2 e d] -// -// d must have length n, and e and tau must have length n-1. Dsytrd will panic if -// these conditions are not met. -// -// work is temporary storage, and lwork specifies the usable memory length. At minimum, -// lwork >= 1, and Dsytrd will panic otherwise. The amount of blocking is -// limited by the usable length. -// If lwork == -1, instead of computing Dsytrd the optimal work length is stored -// into work[0]. -// -// Dsytrd is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau, work []float64, lwork int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - case lwork < 1 && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - work[0] = 1 - return - } - - nb := impl.Ilaenv(1, "DSYTRD", string(uplo), n, -1, -1, -1) - lworkopt := n * nb - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(d) < n: - panic(shortD) - case len(e) < n-1: - panic(shortE) - case len(tau) < n-1: - panic(shortTau) - } - - bi := blas64.Implementation() - - nx := n - iws := 1 - var ldwork int - if 1 < nb && nb < n { - // Determine when to cross over from blocked to unblocked code. The last - // block is always handled by unblocked code. - nx = max(nb, impl.Ilaenv(3, "DSYTRD", string(uplo), n, -1, -1, -1)) - if nx < n { - // Determine if workspace is large enough for blocked code. - ldwork = nb - iws = n * ldwork - if lwork < iws { - // Not enough workspace to use optimal nb: determine the minimum - // value of nb and reduce nb or force use of unblocked code by - // setting nx = n. - nb = max(lwork/n, 1) - nbmin := impl.Ilaenv(2, "DSYTRD", string(uplo), n, -1, -1, -1) - if nb < nbmin { - nx = n - } - } - } else { - nx = n - } - } else { - nb = 1 - } - ldwork = nb - - if uplo == blas.Upper { - // Reduce the upper triangle of A. Columns 0:kk are handled by the - // unblocked method. - var i int - kk := n - ((n-nx+nb-1)/nb)*nb - for i = n - nb; i >= kk; i -= nb { - // Reduce columns i:i+nb to tridiagonal form and form the matrix W - // which is needed to update the unreduced part of the matrix. - impl.Dlatrd(uplo, i+nb, nb, a, lda, e, tau, work, ldwork) - - // Update the unreduced submatrix A[0:i-1,0:i-1], using an update - // of the form A = A - V*Wᵀ - W*Vᵀ. - bi.Dsyr2k(uplo, blas.NoTrans, i, nb, -1, a[i:], lda, work, ldwork, 1, a, lda) - - // Copy superdiagonal elements back into A, and diagonal elements into D. - for j := i; j < i+nb; j++ { - a[(j-1)*lda+j] = e[j-1] - d[j] = a[j*lda+j] - } - } - // Use unblocked code to reduce the last or only block - // check that i == kk. - impl.Dsytd2(uplo, kk, a, lda, d, e, tau) - } else { - var i int - // Reduce the lower triangle of A. - for i = 0; i < n-nx; i += nb { - // Reduce columns 0:i+nb to tridiagonal form and form the matrix W - // which is needed to update the unreduced part of the matrix. - impl.Dlatrd(uplo, n-i, nb, a[i*lda+i:], lda, e[i:], tau[i:], work, ldwork) - - // Update the unreduced submatrix A[i+ib:n, i+ib:n], using an update - // of the form A = A + V*Wᵀ - W*Vᵀ. - bi.Dsyr2k(uplo, blas.NoTrans, n-i-nb, nb, -1, a[(i+nb)*lda+i:], lda, - work[nb*ldwork:], ldwork, 1, a[(i+nb)*lda+i+nb:], lda) - - // Copy subdiagonal elements back into A, and diagonal elements into D. - for j := i; j < i+nb; j++ { - a[(j+1)*lda+j] = e[j] - d[j] = a[j*lda+j] - } - } - // Use unblocked code to reduce the last or only block. - impl.Dsytd2(uplo, n-i, a[i*lda+i:], lda, d[i:], e[i:], tau[i:]) - } - work[0] = float64(iws) -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtbtrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtbtrs.go deleted file mode 100644 index 6b56d9e0..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtbtrs.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright ©2020 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dtbtrs solves a triangular system of the form -// -// A * X = B if trans == blas.NoTrans -// Aᵀ * X = B if trans == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular band matrix with kd super- or subdiagonals, and -// B is an n×nrhs matrix. -// -// Dtbtrs returns whether A is non-singular. If A is singular, no solution X is -// computed. -func (impl Implementation) Dtbtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, kd, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTrans) - case diag != blas.NonUnit && diag != blas.Unit: - panic(badDiag) - case n < 0: - panic(nLT0) - case kd < 0: - panic(kdLT0) - case nrhs < 0: - panic(nrhsLT0) - case lda < kd+1: - panic(badLdA) - case ldb < max(1, nrhs): - panic(badLdB) - } - - // Quick return if possible. - if n == 0 { - return true - } - - switch { - case len(a) < (n-1)*lda+kd+1: - panic(shortA) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - } - - // Check for singularity. - if diag == blas.NonUnit { - if uplo == blas.Upper { - for i := 0; i < n; i++ { - if a[i*lda] == 0 { - return false - } - } - } else { - for i := 0; i < n; i++ { - if a[i*lda+kd] == 0 { - return false - } - } - } - } - - // Solve A * X = B or Aᵀ * X = B. - bi := blas64.Implementation() - for j := 0; j < nrhs; j++ { - bi.Dtbsv(uplo, trans, diag, n, kd, a, lda, b[j:], ldb) - } - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go deleted file mode 100644 index b3f0208a..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dtgsja computes the generalized singular value decomposition (GSVD) -// of two real upper triangular or trapezoidal matrices A and B. -// -// A and B have the following forms, which may be obtained by the -// preprocessing subroutine Dggsvp from a general m×n matrix A and p×n -// matrix B: -// -// n-k-l k l -// A = k [ 0 A12 A13 ] if m-k-l >= 0; -// l [ 0 0 A23 ] -// m-k-l [ 0 0 0 ] -// -// n-k-l k l -// A = k [ 0 A12 A13 ] if m-k-l < 0; -// m-k [ 0 0 A23 ] -// -// n-k-l k l -// B = l [ 0 0 B13 ] -// p-l [ 0 0 0 ] -// -// where the k×k matrix A12 and l×l matrix B13 are non-singular -// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, -// otherwise A23 is (m-k)×l upper trapezoidal. -// -// On exit, -// -// Uᵀ*A*Q = D1*[ 0 R ], Vᵀ*B*Q = D2*[ 0 R ], -// -// where U, V and Q are orthogonal matrices. -// R is a non-singular upper triangular matrix, and D1 and D2 are -// diagonal matrices, which are of the following structures: -// -// If m-k-l >= 0, -// -// k l -// D1 = k [ I 0 ] -// l [ 0 C ] -// m-k-l [ 0 0 ] -// -// k l -// D2 = l [ 0 S ] -// p-l [ 0 0 ] -// -// n-k-l k l -// [ 0 R ] = k [ 0 R11 R12 ] k -// l [ 0 0 R22 ] l -// -// where -// -// C = diag( alpha_k, ... , alpha_{k+l} ), -// S = diag( beta_k, ... , beta_{k+l} ), -// C^2 + S^2 = I. -// -// R is stored in -// -// A[0:k+l, n-k-l:n] -// -// on exit. -// -// If m-k-l < 0, -// -// k m-k k+l-m -// D1 = k [ I 0 0 ] -// m-k [ 0 C 0 ] -// -// k m-k k+l-m -// D2 = m-k [ 0 S 0 ] -// k+l-m [ 0 0 I ] -// p-l [ 0 0 0 ] -// -// n-k-l k m-k k+l-m -// [ 0 R ] = k [ 0 R11 R12 R13 ] -// m-k [ 0 0 R22 R23 ] -// k+l-m [ 0 0 0 R33 ] -// -// where -// -// C = diag( alpha_k, ... , alpha_m ), -// S = diag( beta_k, ... , beta_m ), -// C^2 + S^2 = I. -// -// R = [ R11 R12 R13 ] is stored in A[0:m, n-k-l:n] -// [ 0 R22 R23 ] -// -// and R33 is stored in -// -// B[m-k:l, n+m-k-l:n] on exit. -// -// The computation of the orthogonal transformation matrices U, V or Q -// is optional. These matrices may either be formed explicitly, or they -// may be post-multiplied into input matrices U1, V1, or Q1. -// -// Dtgsja essentially uses a variant of Kogbetliantz algorithm to reduce -// min(l,m-k)×l triangular or trapezoidal matrix A23 and l×l -// matrix B13 to the form: -// -// U1ᵀ*A13*Q1 = C1*R1; V1ᵀ*B13*Q1 = S1*R1, -// -// where U1, V1 and Q1 are orthogonal matrices. C1 and S1 are diagonal -// matrices satisfying -// -// C1^2 + S1^2 = I, -// -// and R1 is an l×l non-singular upper triangular matrix. -// -// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior -// is as follows -// -// jobU == lapack.GSVDU Compute orthogonal matrix U -// jobU == lapack.GSVDUnit Use unit-initialized matrix -// jobU == lapack.GSVDNone Do not compute orthogonal matrix. -// -// The behavior is the same for jobV and jobQ with the exception that instead of -// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. -// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the -// relevant job parameter is lapack.GSVDNone. -// -// k and l specify the sub-blocks in the input matrices A and B: -// -// A23 = A[k:min(k+l,m), n-l:n) and B13 = B[0:l, n-l:n] -// -// of A and B, whose GSVD is going to be computed by Dtgsja. -// -// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz -// iteration procedure. Generally, they are the same as used in the preprocessing -// step, for example, -// -// tola = max(m, n)*norm(A)*eps, -// tolb = max(p, n)*norm(B)*eps, -// -// where eps is the machine epsilon. -// -// work must have length at least 2*n, otherwise Dtgsja will panic. -// -// alpha and beta must have length n or Dtgsja will panic. On exit, alpha and -// beta contain the generalized singular value pairs of A and B -// -// alpha[0:k] = 1, -// beta[0:k] = 0, -// -// if m-k-l >= 0, -// -// alpha[k:k+l] = diag(C), -// beta[k:k+l] = diag(S), -// -// if m-k-l < 0, -// -// alpha[k:m]= C, alpha[m:k+l]= 0 -// beta[k:m] = S, beta[m:k+l] = 1. -// -// if k+l < n, -// -// alpha[k+l:n] = 0 and -// beta[k+l:n] = 0. -// -// On exit, A[n-k:n, 0:min(k+l,m)] contains the triangular matrix R or part of R -// and if necessary, B[m-k:l, n+m-k-l:n] contains a part of R. -// -// Dtgsja returns whether the routine converged and the number of iteration cycles -// that were run. -// -// Dtgsja is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dtgsja(jobU, jobV, jobQ lapack.GSVDJob, m, p, n, k, l int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64) (cycles int, ok bool) { - const maxit = 40 - - initu := jobU == lapack.GSVDUnit - wantu := initu || jobU == lapack.GSVDU - - initv := jobV == lapack.GSVDUnit - wantv := initv || jobV == lapack.GSVDV - - initq := jobQ == lapack.GSVDUnit - wantq := initq || jobQ == lapack.GSVDQ - - switch { - case !initu && !wantu && jobU != lapack.GSVDNone: - panic(badGSVDJob + "U") - case !initv && !wantv && jobV != lapack.GSVDNone: - panic(badGSVDJob + "V") - case !initq && !wantq && jobQ != lapack.GSVDNone: - panic(badGSVDJob + "Q") - case m < 0: - panic(mLT0) - case p < 0: - panic(pLT0) - case n < 0: - panic(nLT0) - - case lda < max(1, n): - panic(badLdA) - case len(a) < (m-1)*lda+n: - panic(shortA) - - case ldb < max(1, n): - panic(badLdB) - case len(b) < (p-1)*ldb+n: - panic(shortB) - - case len(alpha) != n: - panic(badLenAlpha) - case len(beta) != n: - panic(badLenBeta) - - case ldu < 1, wantu && ldu < m: - panic(badLdU) - case wantu && len(u) < (m-1)*ldu+m: - panic(shortU) - - case ldv < 1, wantv && ldv < p: - panic(badLdV) - case wantv && len(v) < (p-1)*ldv+p: - panic(shortV) - - case ldq < 1, wantq && ldq < n: - panic(badLdQ) - case wantq && len(q) < (n-1)*ldq+n: - panic(shortQ) - - case len(work) < 2*n: - panic(shortWork) - } - - // Initialize U, V and Q, if necessary - if initu { - impl.Dlaset(blas.All, m, m, 0, 1, u, ldu) - } - if initv { - impl.Dlaset(blas.All, p, p, 0, 1, v, ldv) - } - if initq { - impl.Dlaset(blas.All, n, n, 0, 1, q, ldq) - } - - bi := blas64.Implementation() - minTol := math.Min(tola, tolb) - - // Loop until convergence. - upper := false - for cycles = 1; cycles <= maxit; cycles++ { - upper = !upper - - for i := 0; i < l-1; i++ { - for j := i + 1; j < l; j++ { - var a1, a2, a3 float64 - if k+i < m { - a1 = a[(k+i)*lda+n-l+i] - } - if k+j < m { - a3 = a[(k+j)*lda+n-l+j] - } - - b1 := b[i*ldb+n-l+i] - b3 := b[j*ldb+n-l+j] - - var b2 float64 - if upper { - if k+i < m { - a2 = a[(k+i)*lda+n-l+j] - } - b2 = b[i*ldb+n-l+j] - } else { - if k+j < m { - a2 = a[(k+j)*lda+n-l+i] - } - b2 = b[j*ldb+n-l+i] - } - - csu, snu, csv, snv, csq, snq := impl.Dlags2(upper, a1, a2, a3, b1, b2, b3) - - // Update (k+i)-th and (k+j)-th rows of matrix A: Uᵀ*A. - if k+j < m { - bi.Drot(l, a[(k+j)*lda+n-l:], 1, a[(k+i)*lda+n-l:], 1, csu, snu) - } - - // Update i-th and j-th rows of matrix B: Vᵀ*B. - bi.Drot(l, b[j*ldb+n-l:], 1, b[i*ldb+n-l:], 1, csv, snv) - - // Update (n-l+i)-th and (n-l+j)-th columns of matrices - // A and B: A*Q and B*Q. - bi.Drot(min(k+l, m), a[n-l+j:], lda, a[n-l+i:], lda, csq, snq) - bi.Drot(l, b[n-l+j:], ldb, b[n-l+i:], ldb, csq, snq) - - if upper { - if k+i < m { - a[(k+i)*lda+n-l+j] = 0 - } - b[i*ldb+n-l+j] = 0 - } else { - if k+j < m { - a[(k+j)*lda+n-l+i] = 0 - } - b[j*ldb+n-l+i] = 0 - } - - // Update orthogonal matrices U, V, Q, if desired. - if wantu && k+j < m { - bi.Drot(m, u[k+j:], ldu, u[k+i:], ldu, csu, snu) - } - if wantv { - bi.Drot(p, v[j:], ldv, v[i:], ldv, csv, snv) - } - if wantq { - bi.Drot(n, q[n-l+j:], ldq, q[n-l+i:], ldq, csq, snq) - } - } - } - - if !upper { - // The matrices A13 and B13 were lower triangular at the start - // of the cycle, and are now upper triangular. - // - // Convergence test: test the parallelism of the corresponding - // rows of A and B. - var error float64 - for i := 0; i < min(l, m-k); i++ { - bi.Dcopy(l-i, a[(k+i)*lda+n-l+i:], 1, work, 1) - bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, work[l:], 1) - ssmin := impl.Dlapll(l-i, work, 1, work[l:], 1) - error = math.Max(error, ssmin) - } - if math.Abs(error) <= minTol { - // The algorithm has converged. - // Compute the generalized singular value pairs (alpha, beta) - // and set the triangular matrix R to array A. - for i := 0; i < k; i++ { - alpha[i] = 1 - beta[i] = 0 - } - - for i := 0; i < min(l, m-k); i++ { - a1 := a[(k+i)*lda+n-l+i] - b1 := b[i*ldb+n-l+i] - gamma := b1 / a1 - if !math.IsInf(gamma, 0) { - // Change sign if necessary. - if gamma < 0 { - bi.Dscal(l-i, -1, b[i*ldb+n-l+i:], 1) - if wantv { - bi.Dscal(p, -1, v[i:], ldv) - } - } - beta[k+i], alpha[k+i], _ = impl.Dlartg(math.Abs(gamma), 1) - - if alpha[k+i] >= beta[k+i] { - bi.Dscal(l-i, 1/alpha[k+i], a[(k+i)*lda+n-l+i:], 1) - } else { - bi.Dscal(l-i, 1/beta[k+i], b[i*ldb+n-l+i:], 1) - bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, a[(k+i)*lda+n-l+i:], 1) - } - } else { - alpha[k+i] = 0 - beta[k+i] = 1 - bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, a[(k+i)*lda+n-l+i:], 1) - } - } - - for i := m; i < k+l; i++ { - alpha[i] = 0 - beta[i] = 1 - } - if k+l < n { - for i := k + l; i < n; i++ { - alpha[i] = 0 - beta[i] = 0 - } - } - - return cycles, true - } - } - } - - // The algorithm has not converged after maxit cycles. - return cycles, false -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go deleted file mode 100644 index 899c95dd..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dtrcon estimates the reciprocal of the condition number of a triangular matrix A. -// The condition number computed may be based on the 1-norm or the ∞-norm. -// -// work is a temporary data slice of length at least 3*n and Dtrcon will panic otherwise. -// -// iwork is a temporary data slice of length at least n and Dtrcon will panic otherwise. -func (impl Implementation) Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 { - switch { - case norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum: - panic(badNorm) - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case diag != blas.NonUnit && diag != blas.Unit: - panic(badDiag) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 { - return 1 - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(work) < 3*n: - panic(shortWork) - case len(iwork) < n: - panic(shortIWork) - } - - bi := blas64.Implementation() - - var rcond float64 - smlnum := dlamchS * float64(n) - - anorm := impl.Dlantr(norm, uplo, diag, n, n, a, lda, work) - - if anorm <= 0 { - return rcond - } - var ainvnm float64 - var normin bool - kase1 := 2 - if norm == lapack.MaxColumnSum { - kase1 = 1 - } - var kase int - isave := new([3]int) - var scale float64 - for { - ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) - if kase == 0 { - if ainvnm != 0 { - rcond = (1 / anorm) / ainvnm - } - return rcond - } - if kase == kase1 { - scale = impl.Dlatrs(uplo, blas.NoTrans, diag, normin, n, a, lda, work, work[2*n:]) - } else { - scale = impl.Dlatrs(uplo, blas.Trans, diag, normin, n, a, lda, work, work[2*n:]) - } - normin = true - if scale != 1 { - ix := bi.Idamax(n, work, 1) - xnorm := math.Abs(work[ix]) - if scale == 0 || scale < xnorm*smlnum { - return rcond - } - impl.Drscl(n, scale, work, 1) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go deleted file mode 100644 index 86197d3a..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go +++ /dev/null @@ -1,894 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" -) - -// Dtrevc3 computes some or all of the right and/or left eigenvectors of an n×n -// upper quasi-triangular matrix T in Schur canonical form. Matrices of this -// type are produced by the Schur factorization of a real general matrix A -// -// A = Q T Qᵀ, -// -// as computed by Dhseqr. -// -// The right eigenvector x of T corresponding to an -// eigenvalue λ is defined by -// -// T x = λ x, -// -// and the left eigenvector y is defined by -// -// yᵀ T = λ yᵀ. -// -// The eigenvalues are read directly from the diagonal blocks of T. -// -// This routine returns the matrices X and/or Y of right and left eigenvectors -// of T, or the products Q*X and/or Q*Y, where Q is an input matrix. If Q is the -// orthogonal factor that reduces a matrix A to Schur form T, then Q*X and Q*Y -// are the matrices of right and left eigenvectors of A. -// -// If side == lapack.EVRight, only right eigenvectors will be computed. -// If side == lapack.EVLeft, only left eigenvectors will be computed. -// If side == lapack.EVBoth, both right and left eigenvectors will be computed. -// For other values of side, Dtrevc3 will panic. -// -// If howmny == lapack.EVAll, all right and/or left eigenvectors will be -// computed. -// If howmny == lapack.EVAllMulQ, all right and/or left eigenvectors will be -// computed and multiplied from left by the matrices in VR and/or VL. -// If howmny == lapack.EVSelected, right and/or left eigenvectors will be -// computed as indicated by selected. -// For other values of howmny, Dtrevc3 will panic. -// -// selected specifies which eigenvectors will be computed. It must have length n -// if howmny == lapack.EVSelected, and it is not referenced otherwise. -// If w_j is a real eigenvalue, the corresponding real eigenvector will be -// computed if selected[j] is true. -// If w_j and w_{j+1} are the real and imaginary parts of a complex eigenvalue, -// the corresponding complex eigenvector is computed if either selected[j] or -// selected[j+1] is true, and on return selected[j] will be set to true and -// selected[j+1] will be set to false. -// -// VL and VR are n×mm matrices. If howmny is lapack.EVAll or -// lapack.AllEVMulQ, mm must be at least n. If howmny is -// lapack.EVSelected, mm must be large enough to store the selected -// eigenvectors. Each selected real eigenvector occupies one column and each -// selected complex eigenvector occupies two columns. If mm is not sufficiently -// large, Dtrevc3 will panic. -// -// On entry, if howmny is lapack.EVAllMulQ, it is assumed that VL (if side -// is lapack.EVLeft or lapack.EVBoth) contains an n×n matrix QL, -// and that VR (if side is lapack.EVRight or lapack.EVBoth) contains -// an n×n matrix QR. QL and QR are typically the orthogonal matrix Q of Schur -// vectors returned by Dhseqr. -// -// On return, if side is lapack.EVLeft or lapack.EVBoth, -// VL will contain: -// -// if howmny == lapack.EVAll, the matrix Y of left eigenvectors of T, -// if howmny == lapack.EVAllMulQ, the matrix Q*Y, -// if howmny == lapack.EVSelected, the left eigenvectors of T specified by -// selected, stored consecutively in the -// columns of VL, in the same order as their -// eigenvalues. -// -// VL is not referenced if side == lapack.EVRight. -// -// On return, if side is lapack.EVRight or lapack.EVBoth, -// VR will contain: -// -// if howmny == lapack.EVAll, the matrix X of right eigenvectors of T, -// if howmny == lapack.EVAllMulQ, the matrix Q*X, -// if howmny == lapack.EVSelected, the left eigenvectors of T specified by -// selected, stored consecutively in the -// columns of VR, in the same order as their -// eigenvalues. -// -// VR is not referenced if side == lapack.EVLeft. -// -// Complex eigenvectors corresponding to a complex eigenvalue are stored in VL -// and VR in two consecutive columns, the first holding the real part, and the -// second the imaginary part. -// -// Each eigenvector will be normalized so that the element of largest magnitude -// has magnitude 1. Here the magnitude of a complex number (x,y) is taken to be -// |x| + |y|. -// -// work must have length at least lwork and lwork must be at least max(1,3*n), -// otherwise Dtrevc3 will panic. For optimum performance, lwork should be at -// least n+2*n*nb, where nb is the optimal blocksize. -// -// If lwork == -1, instead of performing Dtrevc3, the function only estimates -// the optimal workspace size based on n and stores it into work[0]. -// -// Dtrevc3 returns the number of columns in VL and/or VR actually used to store -// the eigenvectors. -// -// Dtrevc3 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.EVHowMany, selected []bool, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, mm int, work []float64, lwork int) (m int) { - bothv := side == lapack.EVBoth - rightv := side == lapack.EVRight || bothv - leftv := side == lapack.EVLeft || bothv - switch { - case !rightv && !leftv: - panic(badEVSide) - case howmny != lapack.EVAll && howmny != lapack.EVAllMulQ && howmny != lapack.EVSelected: - panic(badEVHowMany) - case n < 0: - panic(nLT0) - case ldt < max(1, n): - panic(badLdT) - case mm < 0: - panic(mmLT0) - case ldvl < 1: - // ldvl and ldvr are also checked below after the computation of - // m (number of columns of VL and VR) in case of howmny == EVSelected. - panic(badLdVL) - case ldvr < 1: - panic(badLdVR) - case lwork < max(1, 3*n) && lwork != -1: - panic(badLWork) - case len(work) < max(1, lwork): - panic(shortWork) - } - - // Quick return if possible. - if n == 0 { - work[0] = 1 - return 0 - } - - // Normally we don't check slice lengths until after the workspace - // query. However, even in case of the workspace query we need to - // compute and return the value of m, and since the computation accesses t, - // we put the length check of t here. - if len(t) < (n-1)*ldt+n { - panic(shortT) - } - - if howmny == lapack.EVSelected { - if len(selected) != n { - panic(badLenSelected) - } - // Set m to the number of columns required to store the selected - // eigenvectors, and standardize the slice selected. - // Each selected real eigenvector occupies one column and each - // selected complex eigenvector occupies two columns. - for j := 0; j < n; { - if j == n-1 || t[(j+1)*ldt+j] == 0 { - // Diagonal 1×1 block corresponding to a - // real eigenvalue. - if selected[j] { - m++ - } - j++ - } else { - // Diagonal 2×2 block corresponding to a - // complex eigenvalue. - if selected[j] || selected[j+1] { - selected[j] = true - selected[j+1] = false - m += 2 - } - j += 2 - } - } - } else { - m = n - } - if mm < m { - panic(badMm) - } - - // Quick return in case of a workspace query. - nb := impl.Ilaenv(1, "DTREVC", string(side)+string(howmny), n, -1, -1, -1) - if lwork == -1 { - work[0] = float64(n + 2*n*nb) - return m - } - - // Quick return if no eigenvectors were selected. - if m == 0 { - return 0 - } - - switch { - case leftv && ldvl < mm: - panic(badLdVL) - case leftv && len(vl) < (n-1)*ldvl+mm: - panic(shortVL) - - case rightv && ldvr < mm: - panic(badLdVR) - case rightv && len(vr) < (n-1)*ldvr+mm: - panic(shortVR) - } - - // Use blocked version of back-transformation if sufficient workspace. - // Zero-out the workspace to avoid potential NaN propagation. - const ( - nbmin = 8 - nbmax = 128 - ) - if howmny == lapack.EVAllMulQ && lwork >= n+2*n*nbmin { - nb = min((lwork-n)/(2*n), nbmax) - impl.Dlaset(blas.All, n, 1+2*nb, 0, 0, work[:n+2*nb*n], 1+2*nb) - } else { - nb = 1 - } - - // Set the constants to control overflow. - ulp := dlamchP - smlnum := float64(n) / ulp * dlamchS - bignum := (1 - ulp) / smlnum - - // Split work into a vector of column norms and an n×2*nb matrix b. - norms := work[:n] - ldb := 2 * nb - b := work[n : n+n*ldb] - - // Compute 1-norm of each column of strictly upper triangular part of T - // to control overflow in triangular solver. - norms[0] = 0 - for j := 1; j < n; j++ { - var cn float64 - for i := 0; i < j; i++ { - cn += math.Abs(t[i*ldt+j]) - } - norms[j] = cn - } - - bi := blas64.Implementation() - - var ( - x [4]float64 - - iv int // Index of column in current block. - is int - - // ip is used below to specify the real or complex eigenvalue: - // ip == 0, real eigenvalue, - // 1, first of conjugate complex pair (wr,wi), - // -1, second of conjugate complex pair (wr,wi). - ip int - iscomplex [nbmax]int // Stores ip for each column in current block. - ) - - if side == lapack.EVLeft { - goto leftev - } - - // Compute right eigenvectors. - - // For complex right vector, iv-1 is for real part and iv for complex - // part. Non-blocked version always uses iv=1, blocked version starts - // with iv=nb-1 and goes down to 0 or 1. - iv = max(2, nb) - 1 - ip = 0 - is = m - 1 - for ki := n - 1; ki >= 0; ki-- { - if ip == -1 { - // Previous iteration (ki+1) was second of - // conjugate pair, so this ki is first of - // conjugate pair. - ip = 1 - continue - } - - if ki == 0 || t[ki*ldt+ki-1] == 0 { - // Last column or zero on sub-diagonal, so this - // ki must be real eigenvalue. - ip = 0 - } else { - // Non-zero on sub-diagonal, so this ki is - // second of conjugate pair. - ip = -1 - } - - if howmny == lapack.EVSelected { - if ip == 0 { - if !selected[ki] { - continue - } - } else if !selected[ki-1] { - continue - } - } - - // Compute the ki-th eigenvalue (wr,wi). - wr := t[ki*ldt+ki] - var wi float64 - if ip != 0 { - wi = math.Sqrt(math.Abs(t[ki*ldt+ki-1])) * math.Sqrt(math.Abs(t[(ki-1)*ldt+ki])) - } - smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum) - - if ip == 0 { - // Real right eigenvector. - - b[ki*ldb+iv] = 1 - // Form right-hand side. - for k := 0; k < ki; k++ { - b[k*ldb+iv] = -t[k*ldt+ki] - } - // Solve upper quasi-triangular system: - // [ T[0:ki,0:ki] - wr ]*X = scale*b. - for j := ki - 1; j >= 0; { - if j == 0 || t[j*ldt+j-1] == 0 { - // 1×1 diagonal block. - scale, xnorm, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt, - 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2) - // Scale X[0,0] to avoid overflow when updating the - // right-hand side. - if xnorm > 1 && norms[j] > bignum/xnorm { - x[0] /= xnorm - scale /= xnorm - } - // Scale if necessary. - if scale != 1 { - bi.Dscal(ki+1, scale, b[iv:], ldb) - } - b[j*ldb+iv] = x[0] - // Update right-hand side. - bi.Daxpy(j, -x[0], t[j:], ldt, b[iv:], ldb) - j-- - } else { - // 2×2 diagonal block. - scale, xnorm, _ := impl.Dlaln2(false, 2, 1, smin, 1, t[(j-1)*ldt+j-1:], ldt, - 1, 1, b[(j-1)*ldb+iv:], ldb, wr, 0, x[:3], 2) - // Scale X[0,0] and X[1,0] to avoid overflow - // when updating the right-hand side. - if xnorm > 1 { - beta := math.Max(norms[j-1], norms[j]) - if beta > bignum/xnorm { - x[0] /= xnorm - x[2] /= xnorm - scale /= xnorm - } - } - // Scale if necessary. - if scale != 1 { - bi.Dscal(ki+1, scale, b[iv:], ldb) - } - b[(j-1)*ldb+iv] = x[0] - b[j*ldb+iv] = x[2] - // Update right-hand side. - bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv:], ldb) - bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv:], ldb) - j -= 2 - } - } - // Copy the vector x or Q*x to VR and normalize. - switch { - case howmny != lapack.EVAllMulQ: - // No back-transform: copy x to VR and normalize. - bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr) - ii := bi.Idamax(ki+1, vr[is:], ldvr) - remax := 1 / math.Abs(vr[ii*ldvr+is]) - bi.Dscal(ki+1, remax, vr[is:], ldvr) - for k := ki + 1; k < n; k++ { - vr[k*ldvr+is] = 0 - } - case nb == 1: - // Version 1: back-transform each vector with GEMV, Q*x. - if ki > 0 { - bi.Dgemv(blas.NoTrans, n, ki, 1, vr, ldvr, b[iv:], ldb, - b[ki*ldb+iv], vr[ki:], ldvr) - } - ii := bi.Idamax(n, vr[ki:], ldvr) - remax := 1 / math.Abs(vr[ii*ldvr+ki]) - bi.Dscal(n, remax, vr[ki:], ldvr) - default: - // Version 2: back-transform block of vectors with GEMM. - // Zero out below vector. - for k := ki + 1; k < n; k++ { - b[k*ldb+iv] = 0 - } - iscomplex[iv] = ip - // Back-transform and normalization is done below. - } - } else { - // Complex right eigenvector. - - // Initial solve - // [ ( T[ki-1,ki-1] T[ki-1,ki] ) - (wr + i*wi) ]*X = 0. - // [ ( T[ki, ki-1] T[ki, ki] ) ] - if math.Abs(t[(ki-1)*ldt+ki]) >= math.Abs(t[ki*ldt+ki-1]) { - b[(ki-1)*ldb+iv-1] = 1 - b[ki*ldb+iv] = wi / t[(ki-1)*ldt+ki] - } else { - b[(ki-1)*ldb+iv-1] = -wi / t[ki*ldt+ki-1] - b[ki*ldb+iv] = 1 - } - b[ki*ldb+iv-1] = 0 - b[(ki-1)*ldb+iv] = 0 - // Form right-hand side. - for k := 0; k < ki-1; k++ { - b[k*ldb+iv-1] = -b[(ki-1)*ldb+iv-1] * t[k*ldt+ki-1] - b[k*ldb+iv] = -b[ki*ldb+iv] * t[k*ldt+ki] - } - // Solve upper quasi-triangular system: - // [ T[0:ki-1,0:ki-1] - (wr+i*wi) ]*X = scale*(b1+i*b2) - for j := ki - 2; j >= 0; { - if j == 0 || t[j*ldt+j-1] == 0 { - // 1×1 diagonal block. - - scale, xnorm, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt, - 1, 1, b[j*ldb+iv-1:], ldb, wr, wi, x[:2], 2) - // Scale X[0,0] and X[0,1] to avoid - // overflow when updating the right-hand side. - if xnorm > 1 && norms[j] > bignum/xnorm { - x[0] /= xnorm - x[1] /= xnorm - scale /= xnorm - } - // Scale if necessary. - if scale != 1 { - bi.Dscal(ki+1, scale, b[iv-1:], ldb) - bi.Dscal(ki+1, scale, b[iv:], ldb) - } - b[j*ldb+iv-1] = x[0] - b[j*ldb+iv] = x[1] - // Update the right-hand side. - bi.Daxpy(j, -x[0], t[j:], ldt, b[iv-1:], ldb) - bi.Daxpy(j, -x[1], t[j:], ldt, b[iv:], ldb) - j-- - } else { - // 2×2 diagonal block. - - scale, xnorm, _ := impl.Dlaln2(false, 2, 2, smin, 1, t[(j-1)*ldt+j-1:], ldt, - 1, 1, b[(j-1)*ldb+iv-1:], ldb, wr, wi, x[:], 2) - // Scale X to avoid overflow when updating - // the right-hand side. - if xnorm > 1 { - beta := math.Max(norms[j-1], norms[j]) - if beta > bignum/xnorm { - rec := 1 / xnorm - x[0] *= rec - x[1] *= rec - x[2] *= rec - x[3] *= rec - scale *= rec - } - } - // Scale if necessary. - if scale != 1 { - bi.Dscal(ki+1, scale, b[iv-1:], ldb) - bi.Dscal(ki+1, scale, b[iv:], ldb) - } - b[(j-1)*ldb+iv-1] = x[0] - b[(j-1)*ldb+iv] = x[1] - b[j*ldb+iv-1] = x[2] - b[j*ldb+iv] = x[3] - // Update the right-hand side. - bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv-1:], ldb) - bi.Daxpy(j-1, -x[1], t[j-1:], ldt, b[iv:], ldb) - bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv-1:], ldb) - bi.Daxpy(j-1, -x[3], t[j:], ldt, b[iv:], ldb) - j -= 2 - } - } - - // Copy the vector x or Q*x to VR and normalize. - switch { - case howmny != lapack.EVAllMulQ: - // No back-transform: copy x to VR and normalize. - bi.Dcopy(ki+1, b[iv-1:], ldb, vr[is-1:], ldvr) - bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr) - emax := 0.0 - for k := 0; k <= ki; k++ { - emax = math.Max(emax, math.Abs(vr[k*ldvr+is-1])+math.Abs(vr[k*ldvr+is])) - } - remax := 1 / emax - bi.Dscal(ki+1, remax, vr[is-1:], ldvr) - bi.Dscal(ki+1, remax, vr[is:], ldvr) - for k := ki + 1; k < n; k++ { - vr[k*ldvr+is-1] = 0 - vr[k*ldvr+is] = 0 - } - case nb == 1: - // Version 1: back-transform each vector with GEMV, Q*x. - if ki-1 > 0 { - bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv-1:], ldb, - b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr) - bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv:], ldb, - b[ki*ldb+iv], vr[ki:], ldvr) - } else { - bi.Dscal(n, b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr) - bi.Dscal(n, b[ki*ldb+iv], vr[ki:], ldvr) - } - emax := 0.0 - for k := 0; k < n; k++ { - emax = math.Max(emax, math.Abs(vr[k*ldvr+ki-1])+math.Abs(vr[k*ldvr+ki])) - } - remax := 1 / emax - bi.Dscal(n, remax, vr[ki-1:], ldvr) - bi.Dscal(n, remax, vr[ki:], ldvr) - default: - // Version 2: back-transform block of vectors with GEMM. - // Zero out below vector. - for k := ki + 1; k < n; k++ { - b[k*ldb+iv-1] = 0 - b[k*ldb+iv] = 0 - } - iscomplex[iv-1] = -ip - iscomplex[iv] = ip - iv-- - // Back-transform and normalization is done below. - } - } - if nb > 1 { - // Blocked version of back-transform. - - // For complex case, ki2 includes both vectors (ki-1 and ki). - ki2 := ki - if ip != 0 { - ki2-- - } - // Columns iv:nb of b are valid vectors. - // When the number of vectors stored reaches nb-1 or nb, - // or if this was last vector, do the Gemm. - if iv < 2 || ki2 == 0 { - bi.Dgemm(blas.NoTrans, blas.NoTrans, n, nb-iv, ki2+nb-iv, - 1, vr, ldvr, b[iv:], ldb, - 0, b[nb+iv:], ldb) - // Normalize vectors. - var remax float64 - for k := iv; k < nb; k++ { - if iscomplex[k] == 0 { - // Real eigenvector. - ii := bi.Idamax(n, b[nb+k:], ldb) - remax = 1 / math.Abs(b[ii*ldb+nb+k]) - } else if iscomplex[k] == 1 { - // First eigenvector of conjugate pair. - emax := 0.0 - for ii := 0; ii < n; ii++ { - emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1])) - } - remax = 1 / emax - // Second eigenvector of conjugate pair - // will reuse this value of remax. - } - bi.Dscal(n, remax, b[nb+k:], ldb) - } - impl.Dlacpy(blas.All, n, nb-iv, b[nb+iv:], ldb, vr[ki2:], ldvr) - iv = nb - 1 - } else { - iv-- - } - } - is-- - if ip != 0 { - is-- - } - } - - if side == lapack.EVRight { - return m - } - -leftev: - // Compute left eigenvectors. - - // For complex left vector, iv is for real part and iv+1 for complex - // part. Non-blocked version always uses iv=0. Blocked version starts - // with iv=0, goes up to nb-2 or nb-1. - iv = 0 - ip = 0 - is = 0 - for ki := 0; ki < n; ki++ { - if ip == 1 { - // Previous iteration ki-1 was first of conjugate pair, - // so this ki is second of conjugate pair. - ip = -1 - continue - } - - if ki == n-1 || t[(ki+1)*ldt+ki] == 0 { - // Last column or zero on sub-diagonal, so this ki must - // be real eigenvalue. - ip = 0 - } else { - // Non-zero on sub-diagonal, so this ki is first of - // conjugate pair. - ip = 1 - } - if howmny == lapack.EVSelected && !selected[ki] { - continue - } - - // Compute the ki-th eigenvalue (wr,wi). - wr := t[ki*ldt+ki] - var wi float64 - if ip != 0 { - wi = math.Sqrt(math.Abs(t[ki*ldt+ki+1])) * math.Sqrt(math.Abs(t[(ki+1)*ldt+ki])) - } - smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum) - - if ip == 0 { - // Real left eigenvector. - - b[ki*ldb+iv] = 1 - // Form right-hand side. - for k := ki + 1; k < n; k++ { - b[k*ldb+iv] = -t[ki*ldt+k] - } - // Solve transposed quasi-triangular system: - // [ T[ki+1:n,ki+1:n] - wr ]ᵀ * X = scale*b - vmax := 1.0 - vcrit := bignum - for j := ki + 1; j < n; { - if j == n-1 || t[(j+1)*ldt+j] == 0 { - // 1×1 diagonal block. - - // Scale if necessary to avoid overflow - // when forming the right-hand side. - if norms[j] > vcrit { - rec := 1 / vmax - bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) - vmax = 1 - } - b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb) - // Solve [ T[j,j] - wr ]ᵀ * X = b. - scale, _, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt, - 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2) - // Scale if necessary. - if scale != 1 { - bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) - } - b[j*ldb+iv] = x[0] - vmax = math.Max(math.Abs(b[j*ldb+iv]), vmax) - vcrit = bignum / vmax - j++ - } else { - // 2×2 diagonal block. - - // Scale if necessary to avoid overflow - // when forming the right-hand side. - beta := math.Max(norms[j], norms[j+1]) - if beta > vcrit { - bi.Dscal(n-ki, 1/vmax, b[ki*ldb+iv:], ldb) - vmax = 1 - } - b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb) - b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j+1:], ldt, b[(ki+1)*ldb+iv:], ldb) - // Solve - // [ T[j,j]-wr T[j,j+1] ]ᵀ * X = scale*[ b1 ] - // [ T[j+1,j] T[j+1,j+1]-wr ] [ b2 ] - scale, _, _ := impl.Dlaln2(true, 2, 1, smin, 1, t[j*ldt+j:], ldt, - 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:3], 2) - // Scale if necessary. - if scale != 1 { - bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) - } - b[j*ldb+iv] = x[0] - b[(j+1)*ldb+iv] = x[2] - vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[(j+1)*ldb+iv]))) - vcrit = bignum / vmax - j += 2 - } - } - // Copy the vector x or Q*x to VL and normalize. - switch { - case howmny != lapack.EVAllMulQ: - // No back-transform: copy x to VL and normalize. - bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl) - ii := bi.Idamax(n-ki, vl[ki*ldvl+is:], ldvl) + ki - remax := 1 / math.Abs(vl[ii*ldvl+is]) - bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl) - for k := 0; k < ki; k++ { - vl[k*ldvl+is] = 0 - } - case nb == 1: - // Version 1: back-transform each vector with Gemv, Q*x. - if n-ki-1 > 0 { - bi.Dgemv(blas.NoTrans, n, n-ki-1, - 1, vl[ki+1:], ldvl, b[(ki+1)*ldb+iv:], ldb, - b[ki*ldb+iv], vl[ki:], ldvl) - } - ii := bi.Idamax(n, vl[ki:], ldvl) - remax := 1 / math.Abs(vl[ii*ldvl+ki]) - bi.Dscal(n, remax, vl[ki:], ldvl) - default: - // Version 2: back-transform block of vectors with Gemm - // zero out above vector. - for k := 0; k < ki; k++ { - b[k*ldb+iv] = 0 - } - iscomplex[iv] = ip - // Back-transform and normalization is done below. - } - } else { - // Complex left eigenvector. - - // Initial solve: - // [ [ T[ki,ki] T[ki,ki+1] ]ᵀ - (wr - i* wi) ]*X = 0. - // [ [ T[ki+1,ki] T[ki+1,ki+1] ] ] - if math.Abs(t[ki*ldt+ki+1]) >= math.Abs(t[(ki+1)*ldt+ki]) { - b[ki*ldb+iv] = wi / t[ki*ldt+ki+1] - b[(ki+1)*ldb+iv+1] = 1 - } else { - b[ki*ldb+iv] = 1 - b[(ki+1)*ldb+iv+1] = -wi / t[(ki+1)*ldt+ki] - } - b[(ki+1)*ldb+iv] = 0 - b[ki*ldb+iv+1] = 0 - // Form right-hand side. - for k := ki + 2; k < n; k++ { - b[k*ldb+iv] = -b[ki*ldb+iv] * t[ki*ldt+k] - b[k*ldb+iv+1] = -b[(ki+1)*ldb+iv+1] * t[(ki+1)*ldt+k] - } - // Solve transposed quasi-triangular system: - // [ T[ki+2:n,ki+2:n]ᵀ - (wr-i*wi) ]*X = b1+i*b2 - vmax := 1.0 - vcrit := bignum - for j := ki + 2; j < n; { - if j == n-1 || t[(j+1)*ldt+j] == 0 { - // 1×1 diagonal block. - - // Scale if necessary to avoid overflow - // when forming the right-hand side elements. - if norms[j] > vcrit { - rec := 1 / vmax - bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) - bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb) - vmax = 1 - } - b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb) - b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb) - // Solve [ T[j,j]-(wr-i*wi) ]*(X11+i*X12) = b1+i*b2. - scale, _, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt, - 1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:2], 2) - // Scale if necessary. - if scale != 1 { - bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) - bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb) - } - b[j*ldb+iv] = x[0] - b[j*ldb+iv+1] = x[1] - vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[j*ldb+iv+1]))) - vcrit = bignum / vmax - j++ - } else { - // 2×2 diagonal block. - - // Scale if necessary to avoid overflow - // when forming the right-hand side elements. - if math.Max(norms[j], norms[j+1]) > vcrit { - rec := 1 / vmax - bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) - bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb) - vmax = 1 - } - b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb) - b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb) - b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv:], ldb) - b[(j+1)*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv+1:], ldb) - // Solve 2×2 complex linear equation - // [ [T[j,j] T[j,j+1] ]ᵀ - (wr-i*wi)*I ]*X = scale*b - // [ [T[j+1,j] T[j+1,j+1]] ] - scale, _, _ := impl.Dlaln2(true, 2, 2, smin, 1, t[j*ldt+j:], ldt, - 1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:], 2) - // Scale if necessary. - if scale != 1 { - bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) - bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb) - } - b[j*ldb+iv] = x[0] - b[j*ldb+iv+1] = x[1] - b[(j+1)*ldb+iv] = x[2] - b[(j+1)*ldb+iv+1] = x[3] - vmax01 := math.Max(math.Abs(x[0]), math.Abs(x[1])) - vmax23 := math.Max(math.Abs(x[2]), math.Abs(x[3])) - vmax = math.Max(vmax, math.Max(vmax01, vmax23)) - vcrit = bignum / vmax - j += 2 - } - } - // Copy the vector x or Q*x to VL and normalize. - switch { - case howmny != lapack.EVAllMulQ: - // No back-transform: copy x to VL and normalize. - bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl) - bi.Dcopy(n-ki, b[ki*ldb+iv+1:], ldb, vl[ki*ldvl+is+1:], ldvl) - emax := 0.0 - for k := ki; k < n; k++ { - emax = math.Max(emax, math.Abs(vl[k*ldvl+is])+math.Abs(vl[k*ldvl+is+1])) - } - remax := 1 / emax - bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl) - bi.Dscal(n-ki, remax, vl[ki*ldvl+is+1:], ldvl) - for k := 0; k < ki; k++ { - vl[k*ldvl+is] = 0 - vl[k*ldvl+is+1] = 0 - } - case nb == 1: - // Version 1: back-transform each vector with GEMV, Q*x. - if n-ki-2 > 0 { - bi.Dgemv(blas.NoTrans, n, n-ki-2, - 1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv:], ldb, - b[ki*ldb+iv], vl[ki:], ldvl) - bi.Dgemv(blas.NoTrans, n, n-ki-2, - 1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv+1:], ldb, - b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl) - } else { - bi.Dscal(n, b[ki*ldb+iv], vl[ki:], ldvl) - bi.Dscal(n, b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl) - } - emax := 0.0 - for k := 0; k < n; k++ { - emax = math.Max(emax, math.Abs(vl[k*ldvl+ki])+math.Abs(vl[k*ldvl+ki+1])) - } - remax := 1 / emax - bi.Dscal(n, remax, vl[ki:], ldvl) - bi.Dscal(n, remax, vl[ki+1:], ldvl) - default: - // Version 2: back-transform block of vectors with GEMM. - // Zero out above vector. - // Could go from ki-nv+1 to ki-1. - for k := 0; k < ki; k++ { - b[k*ldb+iv] = 0 - b[k*ldb+iv+1] = 0 - } - iscomplex[iv] = ip - iscomplex[iv+1] = -ip - iv++ - // Back-transform and normalization is done below. - } - } - if nb > 1 { - // Blocked version of back-transform. - // For complex case, ki2 includes both vectors ki and ki+1. - ki2 := ki - if ip != 0 { - ki2++ - } - // Columns [0:iv] of work are valid vectors. When the - // number of vectors stored reaches nb-1 or nb, or if - // this was last vector, do the Gemm. - if iv >= nb-2 || ki2 == n-1 { - bi.Dgemm(blas.NoTrans, blas.NoTrans, n, iv+1, n-ki2+iv, - 1, vl[ki2-iv:], ldvl, b[(ki2-iv)*ldb:], ldb, - 0, b[nb:], ldb) - // Normalize vectors. - var remax float64 - for k := 0; k <= iv; k++ { - if iscomplex[k] == 0 { - // Real eigenvector. - ii := bi.Idamax(n, b[nb+k:], ldb) - remax = 1 / math.Abs(b[ii*ldb+nb+k]) - } else if iscomplex[k] == 1 { - // First eigenvector of conjugate pair. - emax := 0.0 - for ii := 0; ii < n; ii++ { - emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1])) - } - remax = 1 / emax - // Second eigenvector of conjugate pair - // will reuse this value of remax. - } - bi.Dscal(n, remax, b[nb+k:], ldb) - } - impl.Dlacpy(blas.All, n, iv+1, b[nb:], ldb, vl[ki2-iv:], ldvl) - iv = 0 - } else { - iv++ - } - } - is++ - if ip != 0 { - is++ - } - } - - return m -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go deleted file mode 100644 index 2a0a5e7c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "gonum.org/v1/gonum/lapack" - -// Dtrexc reorders the real Schur factorization of a n×n real matrix -// -// A = Q*T*Qᵀ -// -// so that the diagonal block of T with row index ifst is moved to row ilst. -// -// On entry, T must be in Schur canonical form, that is, block upper triangular -// with 1×1 and 2×2 diagonal blocks; each 2×2 diagonal block has its diagonal -// elements equal and its off-diagonal elements of opposite sign. -// -// On return, T will be reordered by an orthogonal similarity transformation Z -// as Zᵀ*T*Z, and will be again in Schur canonical form. -// -// If compq is lapack.UpdateSchur, on return the matrix Q of Schur vectors will be -// updated by post-multiplying it with Z. -// If compq is lapack.UpdateSchurNone, the matrix Q is not referenced and will not be -// updated. -// For other values of compq Dtrexc will panic. -// -// ifst and ilst specify the reordering of the diagonal blocks of T. The block -// with row index ifst is moved to row ilst, by a sequence of transpositions -// between adjacent blocks. -// -// If ifst points to the second row of a 2×2 block, ifstOut will point to the -// first row, otherwise it will be equal to ifst. -// -// ilstOut will point to the first row of the block in its final position. If ok -// is true, ilstOut may differ from ilst by +1 or -1. -// -// It must hold that -// -// 0 <= ifst < n, and 0 <= ilst < n, -// -// otherwise Dtrexc will panic. -// -// If ok is false, two adjacent blocks were too close to swap because the -// problem is very ill-conditioned. T may have been partially reordered, and -// ilstOut will point to the first row of the block at the position to which it -// has been moved. -// -// work must have length at least n, otherwise Dtrexc will panic. -// -// Dtrexc is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dtrexc(compq lapack.UpdateSchurComp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst int, work []float64) (ifstOut, ilstOut int, ok bool) { - switch { - case compq != lapack.UpdateSchur && compq != lapack.UpdateSchurNone: - panic(badUpdateSchurComp) - case n < 0: - panic(nLT0) - case ldt < max(1, n): - panic(badLdT) - case ldq < 1, compq == lapack.UpdateSchur && ldq < n: - panic(badLdQ) - case (ifst < 0 || n <= ifst) && n > 0: - panic(badIfst) - case (ilst < 0 || n <= ilst) && n > 0: - panic(badIlst) - } - - // Quick return if possible. - if n == 0 { - return ifst, ilst, true - } - - switch { - case len(t) < (n-1)*ldt+n: - panic(shortT) - case compq == lapack.UpdateSchur && len(q) < (n-1)*ldq+n: - panic(shortQ) - case len(work) < n: - panic(shortWork) - } - - // Quick return if possible. - if n == 1 { - return ifst, ilst, true - } - - // Determine the first row of specified block - // and find out it is 1×1 or 2×2. - if ifst > 0 && t[ifst*ldt+ifst-1] != 0 { - ifst-- - } - nbf := 1 // Size of the first block. - if ifst+1 < n && t[(ifst+1)*ldt+ifst] != 0 { - nbf = 2 - } - // Determine the first row of the final block - // and find out it is 1×1 or 2×2. - if ilst > 0 && t[ilst*ldt+ilst-1] != 0 { - ilst-- - } - nbl := 1 // Size of the last block. - if ilst+1 < n && t[(ilst+1)*ldt+ilst] != 0 { - nbl = 2 - } - - ok = true - wantq := compq == lapack.UpdateSchur - - switch { - case ifst == ilst: - return ifst, ilst, true - - case ifst < ilst: - // Update ilst. - switch { - case nbf == 2 && nbl == 1: - ilst-- - case nbf == 1 && nbl == 2: - ilst++ - } - here := ifst - for here < ilst { - // Swap block with next one below. - if nbf == 1 || nbf == 2 { - // Current block either 1×1 or 2×2. - nbnext := 1 // Size of the next block. - if here+nbf+1 < n && t[(here+nbf+1)*ldt+here+nbf] != 0 { - nbnext = 2 - } - ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, nbf, nbnext, work) - if !ok { - return ifst, here, false - } - here += nbnext - // Test if 2×2 block breaks into two 1×1 blocks. - if nbf == 2 && t[(here+1)*ldt+here] == 0 { - nbf = 3 - } - continue - } - - // Current block consists of two 1×1 blocks each of - // which must be swapped individually. - nbnext := 1 // Size of the next block. - if here+3 < n && t[(here+3)*ldt+here+2] != 0 { - nbnext = 2 - } - ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here+1, 1, nbnext, work) - if !ok { - return ifst, here, false - } - if nbnext == 1 { - // Swap two 1×1 blocks, no problems possible. - impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, nbnext, work) - here++ - continue - } - // Recompute nbnext in case 2×2 split. - if t[(here+2)*ldt+here+1] == 0 { - nbnext = 1 - } - if nbnext == 2 { - // 2×2 block did not split. - ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, nbnext, work) - if !ok { - return ifst, here, false - } - } else { - // 2×2 block did split. - impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, 1, work) - impl.Dlaexc(wantq, n, t, ldt, q, ldq, here+1, 1, 1, work) - } - here += 2 - } - return ifst, here, true - - default: // ifst > ilst - here := ifst - for here > ilst { - // Swap block with next one above. - nbnext := 1 - if here >= 2 && t[(here-1)*ldt+here-2] != 0 { - nbnext = 2 - } - if nbf == 1 || nbf == 2 { - // Current block either 1×1 or 2×2. - ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-nbnext, nbnext, nbf, work) - if !ok { - return ifst, here, false - } - here -= nbnext - // Test if 2×2 block breaks into two 1×1 blocks. - if nbf == 2 && t[(here+1)*ldt+here] == 0 { - nbf = 3 - } - continue - } - - // Current block consists of two 1×1 blocks each of - // which must be swapped individually. - ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-nbnext, nbnext, 1, work) - if !ok { - return ifst, here, false - } - if nbnext == 1 { - // Swap two 1×1 blocks, no problems possible. - impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, nbnext, 1, work) - here-- - continue - } - // Recompute nbnext in case 2×2 split. - if t[here*ldt+here-1] == 0 { - nbnext = 1 - } - if nbnext == 2 { - // 2×2 block did not split. - ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-1, 2, 1, work) - if !ok { - return ifst, here, false - } - } else { - // 2×2 block did split. - impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, 1, work) - impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-1, 1, 1, work) - } - here -= 2 - } - return ifst, here, true - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go deleted file mode 100644 index efc24b65..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dtrti2 computes the inverse of a triangular matrix, storing the result in place -// into a. This is the BLAS level 2 version of the algorithm. -// -// Dtrti2 is an internal routine. It is exported for testing purposes. -func (impl Implementation) Dtrti2(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case diag != blas.NonUnit && diag != blas.Unit: - panic(badDiag) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 { - return - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - bi := blas64.Implementation() - - nonUnit := diag == blas.NonUnit - // TODO(btracey): Replace this with a row-major ordering. - if uplo == blas.Upper { - for j := 0; j < n; j++ { - var ajj float64 - if nonUnit { - ajj = 1 / a[j*lda+j] - a[j*lda+j] = ajj - ajj *= -1 - } else { - ajj = -1 - } - bi.Dtrmv(blas.Upper, blas.NoTrans, diag, j, a, lda, a[j:], lda) - bi.Dscal(j, ajj, a[j:], lda) - } - return - } - for j := n - 1; j >= 0; j-- { - var ajj float64 - if nonUnit { - ajj = 1 / a[j*lda+j] - a[j*lda+j] = ajj - ajj *= -1 - } else { - ajj = -1 - } - if j < n-1 { - bi.Dtrmv(blas.Lower, blas.NoTrans, diag, n-j-1, a[(j+1)*lda+j+1:], lda, a[(j+1)*lda+j:], lda) - bi.Dscal(n-j-1, ajj, a[(j+1)*lda+j:], lda) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go deleted file mode 100644 index 6ec3663c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dtrtri computes the inverse of a triangular matrix, storing the result in place -// into a. This is the BLAS level 3 version of the algorithm which builds upon -// Dtrti2 to operate on matrix blocks instead of only individual columns. -// -// Dtrtri will not perform the inversion if the matrix is singular, and returns -// a boolean indicating whether the inversion was successful. -func (impl Implementation) Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case diag != blas.NonUnit && diag != blas.Unit: - panic(badDiag) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 { - return true - } - - if len(a) < (n-1)*lda+n { - panic(shortA) - } - - if diag == blas.NonUnit { - for i := 0; i < n; i++ { - if a[i*lda+i] == 0 { - return false - } - } - } - - bi := blas64.Implementation() - - nb := impl.Ilaenv(1, "DTRTRI", "UD", n, -1, -1, -1) - if nb <= 1 || nb > n { - impl.Dtrti2(uplo, diag, n, a, lda) - return true - } - if uplo == blas.Upper { - for j := 0; j < n; j += nb { - jb := min(nb, n-j) - bi.Dtrmm(blas.Left, blas.Upper, blas.NoTrans, diag, j, jb, 1, a, lda, a[j:], lda) - bi.Dtrsm(blas.Right, blas.Upper, blas.NoTrans, diag, j, jb, -1, a[j*lda+j:], lda, a[j:], lda) - impl.Dtrti2(blas.Upper, diag, jb, a[j*lda+j:], lda) - } - return true - } - nn := ((n - 1) / nb) * nb - for j := nn; j >= 0; j -= nb { - jb := min(nb, n-j) - if j+jb <= n-1 { - bi.Dtrmm(blas.Left, blas.Lower, blas.NoTrans, diag, n-j-jb, jb, 1, a[(j+jb)*lda+j+jb:], lda, a[(j+jb)*lda+j:], lda) - bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, diag, n-j-jb, jb, -1, a[j*lda+j:], lda, a[(j+jb)*lda+j:], lda) - } - impl.Dtrti2(blas.Lower, diag, jb, a[j*lda+j:], lda) - } - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go deleted file mode 100644 index 2145fbd5..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -// Dtrtrs solves a triangular system of the form A * X = B or Aᵀ * X = B. Dtrtrs -// returns whether the solve completed successfully. If A is singular, no solve is performed. -func (impl Implementation) Dtrtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) { - switch { - case uplo != blas.Upper && uplo != blas.Lower: - panic(badUplo) - case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: - panic(badTrans) - case diag != blas.NonUnit && diag != blas.Unit: - panic(badDiag) - case n < 0: - panic(nLT0) - case nrhs < 0: - panic(nrhsLT0) - case lda < max(1, n): - panic(badLdA) - case ldb < max(1, nrhs): - panic(badLdB) - } - - if n == 0 { - return true - } - - switch { - case len(a) < (n-1)*lda+n: - panic(shortA) - case len(b) < (n-1)*ldb+nrhs: - panic(shortB) - } - - // Check for singularity. - nounit := diag == blas.NonUnit - if nounit { - for i := 0; i < n; i++ { - if a[i*lda+i] == 0 { - return false - } - } - } - bi := blas64.Implementation() - bi.Dtrsm(blas.Left, uplo, trans, diag, n, nrhs, 1, a, lda, b, ldb) - return true -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/errors.go b/vendor/gonum.org/v1/gonum/lapack/gonum/errors.go deleted file mode 100644 index 711cc2d5..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/errors.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -// This list is duplicated in netlib/lapack/netlib. Keep in sync. -const ( - // Panic strings for bad enumeration values. - badApplyOrtho = "lapack: bad ApplyOrtho" - badBalanceJob = "lapack: bad BalanceJob" - badDiag = "lapack: bad Diag" - badDirect = "lapack: bad Direct" - badEVComp = "lapack: bad EVComp" - badEVHowMany = "lapack: bad EVHowMany" - badEVJob = "lapack: bad EVJob" - badEVSide = "lapack: bad EVSide" - badGSVDJob = "lapack: bad GSVDJob" - badGenOrtho = "lapack: bad GenOrtho" - badLeftEVJob = "lapack: bad LeftEVJob" - badMatrixType = "lapack: bad MatrixType" - badMaximizeNormXJob = "lapack: bad MaximizeNormXJob" - badNorm = "lapack: bad Norm" - badOrthoComp = "lapack: bad OrthoComp" - badPivot = "lapack: bad Pivot" - badRightEVJob = "lapack: bad RightEVJob" - badSVDJob = "lapack: bad SVDJob" - badSchurComp = "lapack: bad SchurComp" - badSchurJob = "lapack: bad SchurJob" - badSide = "lapack: bad Side" - badSort = "lapack: bad Sort" - badStoreV = "lapack: bad StoreV" - badTrans = "lapack: bad Trans" - badUpdateSchurComp = "lapack: bad UpdateSchurComp" - badUplo = "lapack: bad Uplo" - bothSVDOver = "lapack: both jobU and jobVT are lapack.SVDOverwrite" - - // Panic strings for bad numerical and string values. - badIfst = "lapack: ifst out of range" - badIhi = "lapack: ihi out of range" - badIhiz = "lapack: ihiz out of range" - badIlo = "lapack: ilo out of range" - badIloz = "lapack: iloz out of range" - badIlst = "lapack: ilst out of range" - badIsave = "lapack: bad isave value" - badIspec = "lapack: bad ispec value" - badJ1 = "lapack: j1 out of range" - badJpvt = "lapack: bad element of jpvt" - badK1 = "lapack: k1 out of range" - badK2 = "lapack: k2 out of range" - badKacc22 = "lapack: invalid value of kacc22" - badKbot = "lapack: kbot out of range" - badKtop = "lapack: ktop out of range" - badLWork = "lapack: insufficient declared workspace length" - badMm = "lapack: mm out of range" - badN1 = "lapack: bad value of n1" - badN2 = "lapack: bad value of n2" - badNa = "lapack: bad value of na" - badName = "lapack: bad name" - badNh = "lapack: bad value of nh" - badNw = "lapack: bad value of nw" - badPp = "lapack: bad value of pp" - badShifts = "lapack: bad shifts" - i0LT0 = "lapack: i0 < 0" - kGTM = "lapack: k > m" - kGTN = "lapack: k > n" - kLT0 = "lapack: k < 0" - kLT1 = "lapack: k < 1" - kdLT0 = "lapack: kd < 0" - klLT0 = "lapack: kl < 0" - kuLT0 = "lapack: ku < 0" - mGTN = "lapack: m > n" - mLT0 = "lapack: m < 0" - mmLT0 = "lapack: mm < 0" - n0LT0 = "lapack: n0 < 0" - nGTM = "lapack: n > m" - nLT0 = "lapack: n < 0" - nLT1 = "lapack: n < 1" - nLTM = "lapack: n < m" - nanCFrom = "lapack: cfrom is NaN" - nanCTo = "lapack: cto is NaN" - nbGTM = "lapack: nb > m" - nbGTN = "lapack: nb > n" - nbLT0 = "lapack: nb < 0" - nccLT0 = "lapack: ncc < 0" - ncvtLT0 = "lapack: ncvt < 0" - negANorm = "lapack: anorm < 0" - negZ = "lapack: negative z value" - nhLT0 = "lapack: nh < 0" - notIsolated = "lapack: block is not isolated" - nrhsLT0 = "lapack: nrhs < 0" - nruLT0 = "lapack: nru < 0" - nshftsLT0 = "lapack: nshfts < 0" - nshftsOdd = "lapack: nshfts must be even" - nvLT0 = "lapack: nv < 0" - offsetGTM = "lapack: offset > m" - offsetLT0 = "lapack: offset < 0" - pLT0 = "lapack: p < 0" - recurLT0 = "lapack: recur < 0" - zeroCFrom = "lapack: zero cfrom" - - // Panic strings for bad slice lengths. - badLenAlpha = "lapack: bad length of alpha" - badLenBeta = "lapack: bad length of beta" - badLenIpiv = "lapack: bad length of ipiv" - badLenJpiv = "lapack: bad length of jpiv" - badLenJpvt = "lapack: bad length of jpvt" - badLenK = "lapack: bad length of k" - badLenPiv = "lapack: bad length of piv" - badLenSelected = "lapack: bad length of selected" - badLenSi = "lapack: bad length of si" - badLenSr = "lapack: bad length of sr" - badLenTau = "lapack: bad length of tau" - badLenWi = "lapack: bad length of wi" - badLenWr = "lapack: bad length of wr" - - // Panic strings for insufficient slice lengths. - shortA = "lapack: insufficient length of a" - shortAB = "lapack: insufficient length of ab" - shortAuxv = "lapack: insufficient length of auxv" - shortB = "lapack: insufficient length of b" - shortC = "lapack: insufficient length of c" - shortCNorm = "lapack: insufficient length of cnorm" - shortD = "lapack: insufficient length of d" - shortDL = "lapack: insufficient length of dl" - shortDU = "lapack: insufficient length of du" - shortE = "lapack: insufficient length of e" - shortF = "lapack: insufficient length of f" - shortH = "lapack: insufficient length of h" - shortIWork = "lapack: insufficient length of iwork" - shortIsgn = "lapack: insufficient length of isgn" - shortQ = "lapack: insufficient length of q" - shortRHS = "lapack: insufficient length of rhs" - shortS = "lapack: insufficient length of s" - shortScale = "lapack: insufficient length of scale" - shortT = "lapack: insufficient length of t" - shortTau = "lapack: insufficient length of tau" - shortTauP = "lapack: insufficient length of tauP" - shortTauQ = "lapack: insufficient length of tauQ" - shortU = "lapack: insufficient length of u" - shortV = "lapack: insufficient length of v" - shortVL = "lapack: insufficient length of vl" - shortVR = "lapack: insufficient length of vr" - shortVT = "lapack: insufficient length of vt" - shortVn1 = "lapack: insufficient length of vn1" - shortVn2 = "lapack: insufficient length of vn2" - shortW = "lapack: insufficient length of w" - shortWH = "lapack: insufficient length of wh" - shortWV = "lapack: insufficient length of wv" - shortWi = "lapack: insufficient length of wi" - shortWork = "lapack: insufficient length of work" - shortWr = "lapack: insufficient length of wr" - shortX = "lapack: insufficient length of x" - shortY = "lapack: insufficient length of y" - shortZ = "lapack: insufficient length of z" - - // Panic strings for bad leading dimensions of matrices. - badLdA = "lapack: bad leading dimension of A" - badLdB = "lapack: bad leading dimension of B" - badLdC = "lapack: bad leading dimension of C" - badLdF = "lapack: bad leading dimension of F" - badLdH = "lapack: bad leading dimension of H" - badLdQ = "lapack: bad leading dimension of Q" - badLdT = "lapack: bad leading dimension of T" - badLdU = "lapack: bad leading dimension of U" - badLdV = "lapack: bad leading dimension of V" - badLdVL = "lapack: bad leading dimension of VL" - badLdVR = "lapack: bad leading dimension of VR" - badLdVT = "lapack: bad leading dimension of VT" - badLdW = "lapack: bad leading dimension of W" - badLdWH = "lapack: bad leading dimension of WH" - badLdWV = "lapack: bad leading dimension of WV" - badLdWork = "lapack: bad leading dimension of Work" - badLdX = "lapack: bad leading dimension of X" - badLdY = "lapack: bad leading dimension of Y" - badLdZ = "lapack: bad leading dimension of Z" - - // Panic strings for bad vector increments. - absIncNotOne = "lapack: increment not one or negative one" - badIncX = "lapack: incX <= 0" - badIncY = "lapack: incY <= 0" - zeroIncV = "lapack: incv == 0" -) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go deleted file mode 100644 index b251d726..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -// Iladlc scans a matrix for its last non-zero column. Returns -1 if the matrix -// is all zeros. -// -// Iladlc is an internal routine. It is exported for testing purposes. -func (Implementation) Iladlc(m, n int, a []float64, lda int) int { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 || m == 0 { - return -1 - } - - if len(a) < (m-1)*lda+n { - panic(shortA) - } - - // Test common case where corner is non-zero. - if a[n-1] != 0 || a[(m-1)*lda+(n-1)] != 0 { - return n - 1 - } - - // Scan each row tracking the highest column seen. - highest := -1 - for i := 0; i < m; i++ { - for j := n - 1; j >= 0; j-- { - if a[i*lda+j] != 0 { - highest = max(highest, j) - break - } - } - } - return highest -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go deleted file mode 100644 index b73fe18e..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -// Iladlr scans a matrix for its last non-zero row. Returns -1 if the matrix -// is all zeros. -// -// Iladlr is an internal routine. It is exported for testing purposes. -func (Implementation) Iladlr(m, n int, a []float64, lda int) int { - switch { - case m < 0: - panic(mLT0) - case n < 0: - panic(nLT0) - case lda < max(1, n): - panic(badLdA) - } - - if n == 0 || m == 0 { - return -1 - } - - if len(a) < (m-1)*lda+n { - panic(shortA) - } - - // Check the common case where the corner is non-zero - if a[(m-1)*lda] != 0 || a[(m-1)*lda+n-1] != 0 { - return m - 1 - } - for i := m - 1; i >= 0; i-- { - for j := 0; j < n; j++ { - if a[i*lda+j] != 0 { - return i - } - } - } - return -1 -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go b/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go deleted file mode 100644 index fc70806c..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -// Ilaenv returns algorithm tuning parameters for the algorithm given by the -// input string. ispec specifies the parameter to return: -// -// 1: The optimal block size for a blocked algorithm. -// 2: The minimum block size for a blocked algorithm. -// 3: The block size of unprocessed data at which a blocked algorithm should -// crossover to an unblocked version. -// 4: The number of shifts. -// 5: The minimum column dimension for blocking to be used. -// 6: The crossover point for SVD (to use QR factorization or not). -// 7: The number of processors. -// 8: The crossover point for multi-shift in QR and QZ methods for non-symmetric eigenvalue problems. -// 9: Maximum size of the subproblems in divide-and-conquer algorithms. -// 10: ieee infinity and NaN arithmetic can be trusted not to trap. -// 11: ieee infinity arithmetic can be trusted not to trap. -// 12...16: parameters for Dhseqr and related functions. See Iparmq for more -// information. -// -// Ilaenv is an internal routine. It is exported for testing purposes. -func (impl Implementation) Ilaenv(ispec int, name string, opts string, n1, n2, n3, n4 int) int { - // TODO(btracey): Replace this with a constant lookup? A list of constants? - sname := name[0] == 'S' || name[0] == 'D' - cname := name[0] == 'C' || name[0] == 'Z' - if !sname && !cname { - panic(badName) - } - c2 := name[1:3] - c3 := name[3:6] - c4 := c3[1:3] - - switch ispec { - default: - panic(badIspec) - case 1: - switch c2 { - default: - panic(badName) - case "GE": - switch c3 { - default: - panic(badName) - case "TRF": - if sname { - return 64 - } - return 64 - case "QRF", "RQF", "LQF", "QLF": - if sname { - return 32 - } - return 32 - case "HRD": - if sname { - return 32 - } - return 32 - case "BRD": - if sname { - return 32 - } - return 32 - case "TRI": - if sname { - return 64 - } - return 64 - } - case "PO": - switch c3 { - default: - panic(badName) - case "TRF": - if sname { - return 64 - } - return 64 - } - case "SY": - switch c3 { - default: - panic(badName) - case "TRF": - if sname { - return 64 - } - return 64 - case "TRD": - return 32 - case "GST": - return 64 - } - case "HE": - switch c3 { - default: - panic(badName) - case "TRF": - return 64 - case "TRD": - return 32 - case "GST": - return 64 - } - case "OR": - switch c3[0] { - default: - panic(badName) - case 'G': - switch c3[1:] { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 32 - } - case 'M': - switch c3[1:] { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 32 - } - } - case "UN": - switch c3[0] { - default: - panic(badName) - case 'G': - switch c3[1:] { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 32 - } - case 'M': - switch c3[1:] { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 32 - } - } - case "GB": - switch c3 { - default: - panic(badName) - case "TRF": - if sname { - if n4 <= 64 { - return 1 - } - return 32 - } - if n4 <= 64 { - return 1 - } - return 32 - } - case "PB": - switch c3 { - default: - panic(badName) - case "TRF": - if sname { - if n2 <= 64 { - return 1 - } - return 32 - } - if n2 <= 64 { - return 1 - } - return 32 - } - case "PT": - switch c3 { - default: - panic(badName) - case "TRS": - return 1 - } - case "TR": - switch c3 { - default: - panic(badName) - case "TRI": - if sname { - return 64 - } - return 64 - case "EVC": - if sname { - return 64 - } - return 64 - } - case "LA": - switch c3 { - default: - panic(badName) - case "UUM": - if sname { - return 64 - } - return 64 - } - case "ST": - if sname && c3 == "EBZ" { - return 1 - } - panic(badName) - } - case 2: - switch c2 { - default: - panic(badName) - case "GE": - switch c3 { - default: - panic(badName) - case "QRF", "RQF", "LQF", "QLF": - if sname { - return 2 - } - return 2 - case "HRD": - if sname { - return 2 - } - return 2 - case "BRD": - if sname { - return 2 - } - return 2 - case "TRI": - if sname { - return 2 - } - return 2 - } - case "SY": - switch c3 { - default: - panic(badName) - case "TRF": - if sname { - return 8 - } - return 8 - case "TRD": - if sname { - return 2 - } - panic(badName) - } - case "HE": - if c3 == "TRD" { - return 2 - } - panic(badName) - case "OR": - if !sname { - panic(badName) - } - switch c3[0] { - default: - panic(badName) - case 'G': - switch c4 { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 2 - } - case 'M': - switch c4 { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 2 - } - } - case "UN": - switch c3[0] { - default: - panic(badName) - case 'G': - switch c4 { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 2 - } - case 'M': - switch c4 { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 2 - } - } - } - case 3: - switch c2 { - default: - panic(badName) - case "GE": - switch c3 { - default: - panic(badName) - case "QRF", "RQF", "LQF", "QLF": - if sname { - return 128 - } - return 128 - case "HRD": - if sname { - return 128 - } - return 128 - case "BRD": - if sname { - return 128 - } - return 128 - } - case "SY": - if sname && c3 == "TRD" { - return 32 - } - panic(badName) - case "HE": - if c3 == "TRD" { - return 32 - } - panic(badName) - case "OR": - switch c3[0] { - default: - panic(badName) - case 'G': - switch c4 { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 128 - } - } - case "UN": - switch c3[0] { - default: - panic(badName) - case 'G': - switch c4 { - default: - panic(badName) - case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": - return 128 - } - } - } - case 4: - // Used by xHSEQR - return 6 - case 5: - // Not used - return 2 - case 6: - // Used by xGELSS and xGESVD - return int(float64(min(n1, n2)) * 1.6) - case 7: - // Not used - return 1 - case 8: - // Used by xHSEQR - return 50 - case 9: - // used by xGELSD and xGESDD - return 25 - case 10: - // Go guarantees ieee - return 1 - case 11: - // Go guarantees ieee - return 1 - case 12, 13, 14, 15, 16: - // Dhseqr and related functions for eigenvalue problems. - return impl.Iparmq(ispec, name, opts, n1, n2, n3, n4) - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go deleted file mode 100644 index 65d10524..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import "math" - -// Iparmq returns problem and machine dependent parameters useful for Dhseqr and -// related subroutines for eigenvalue problems. -// -// ispec specifies the parameter to return: -// -// 12: Crossover point between Dlahqr and Dlaqr0. Will be at least 11. -// 13: Deflation window size. -// 14: Nibble crossover point. Determines when to skip a multi-shift QR sweep. -// 15: Number of simultaneous shifts in a multishift QR iteration. -// 16: Select structured matrix multiply. -// -// For other values of ispec Iparmq will panic. -// -// name is the name of the calling function. name must be in uppercase but this -// is not checked. -// -// opts is not used and exists for future use. -// -// n is the order of the Hessenberg matrix H. -// -// ilo and ihi specify the block [ilo:ihi+1,ilo:ihi+1] that is being processed. -// -// lwork is the amount of workspace available. -// -// Except for ispec input parameters are not checked. -// -// Iparmq is an internal routine. It is exported for testing purposes. -func (Implementation) Iparmq(ispec int, name, opts string, n, ilo, ihi, lwork int) int { - nh := ihi - ilo + 1 - ns := 2 - switch { - case nh >= 30: - ns = 4 - case nh >= 60: - ns = 10 - case nh >= 150: - ns = max(10, nh/int(math.Log(float64(nh))/math.Ln2)) - case nh >= 590: - ns = 64 - case nh >= 3000: - ns = 128 - case nh >= 6000: - ns = 256 - } - ns = max(2, ns-(ns%2)) - - switch ispec { - default: - panic(badIspec) - - case 12: - // Matrices of order smaller than nmin get sent to Dlahqr, the - // classic double shift algorithm. This must be at least 11. - const nmin = 75 - return nmin - - case 13: - const knwswp = 500 - if nh <= knwswp { - return ns - } - return 3 * ns / 2 - - case 14: - // Skip a computationally expensive multi-shift QR sweep with - // Dlaqr5 whenever aggressive early deflation finds at least - // nibble*(window size)/100 deflations. The default, small, - // value reflects the expectation that the cost of looking - // through the deflation window with Dlaqr3 will be - // substantially smaller. - const nibble = 14 - return nibble - - case 15: - return ns - - case 16: - if len(name) != 6 { - panic(badName) - } - const ( - k22min = 14 - kacmin = 14 - ) - var acc22 int - switch { - case name[1:] == "GGHRD" || name[1:] == "GGHD3": - acc22 = 1 - if nh >= k22min { - acc22 = 2 - } - case name[3:] == "EXC": - if nh >= kacmin { - acc22 = 1 - } - if nh >= k22min { - acc22 = 2 - } - case name[1:] == "HSEQR" || name[1:5] == "LAQR": - if ns >= kacmin { - acc22 = 1 - } - if ns >= k22min { - acc22 = 2 - } - } - return acc22 - } -} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/lapack.go b/vendor/gonum.org/v1/gonum/lapack/gonum/lapack.go deleted file mode 100644 index 5daefc58..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/lapack.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright ©2015 The Gonum 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 gonum - -import "gonum.org/v1/gonum/lapack" - -// Implementation is the native Go implementation of LAPACK routines. It -// is built on top of calls to the return of blas64.Implementation(), so while -// this code is in pure Go, the underlying BLAS implementation may not be. -type Implementation struct{} - -var _ lapack.Float64 = Implementation{} - -func abs(a int) int { - if a < 0 { - return -a - } - return a -} - -const ( - // dlamchE is the machine epsilon. For IEEE this is 2^{-53}. - dlamchE = 0x1p-53 - - // dlamchB is the radix of the machine (the base of the number system). - dlamchB = 2 - - // dlamchP is base * eps. - dlamchP = dlamchB * dlamchE - - // dlamchS is the "safe minimum", that is, the lowest number such that - // 1/dlamchS does not overflow, or also the smallest normal number. - // For IEEE this is 2^{-1022}. - dlamchS = 0x1p-1022 - - // Blue's scaling constants - // - // An n-vector x is well-scaled if - // dtsml ≤ |xᵢ| ≤ dtbig for 0 ≤ i < n and n ≤ 1/dlamchP, - // where - // dtsml = 2^ceil((expmin-1)/2) = 2^ceil((-1021-1)/2) = 2^{-511} = 1.4916681462400413e-154 - // dtbig = 2^floor((expmax-digits+1)/2) = 2^floor((1024-53+1)/2) = 2^{486} = 1.997919072202235e+146 - // If any xᵢ is not well-scaled, then multiplying small values by dssml and - // large values by dsbig avoids underflow or overflow when computing the sum - // of squares \sum_0^{n-1} (xᵢ)². - // dssml = 2^{-floor((expmin-digits)/2)} = 2^{-floor((-1021-53)/2)} = 2^537 = 4.4989137945431964e+161 - // dsbig = 2^{-ceil((expmax+digits-1)/2)} = 2^{-ceil((1024+53-1)/2)} = 2^{-538} = 1.1113793747425387e-162 - // - // References: - // - Anderson E. (2017) - // Algorithm 978: Safe Scaling in the Level 1 BLAS - // ACM Trans Math Softw 44:1--28 - // https://doi.org/10.1145/3061665 - // - Blue, James L. (1978) - // A Portable Fortran Program to Find the Euclidean Norm of a Vector - // ACM Trans Math Softw 4:15--23 - // https://doi.org/10.1145/355769.355771 - dtsml = 0x1p-511 - dtbig = 0x1p486 - dssml = 0x1p537 - dsbig = 0x1p-538 -) diff --git a/vendor/gonum.org/v1/gonum/lapack/lapack.go b/vendor/gonum.org/v1/gonum/lapack/lapack.go deleted file mode 100644 index 60ef1c24..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/lapack.go +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright ©2015 The Gonum 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 lapack - -import "gonum.org/v1/gonum/blas" - -// Complex128 defines the public complex128 LAPACK API supported by gonum/lapack. -type Complex128 interface{} - -// Float64 defines the public float64 LAPACK API supported by gonum/lapack. -type Float64 interface { - Dgecon(norm MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 - Dgeev(jobvl LeftEVJob, jobvr RightEVJob, n int, a []float64, lda int, wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) (first int) - Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool - Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) - Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int) - Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) - Dgesvd(jobU, jobVT SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) - Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) - Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) - Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) - Dggsvd3(jobU, jobV, jobQ GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) - Dlantr(norm MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 - Dlange(norm MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 - Dlansy(norm MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 - Dlapmr(forward bool, m, n int, x []float64, ldx int, k []int) - Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) - Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) - Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) - Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) - Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) - Dpbcon(uplo blas.Uplo, n, kd int, ab []float64, ldab int, anorm float64, work []float64, iwork []int) float64 - Dpbtrf(uplo blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) - Dpbtrs(uplo blas.Uplo, n, kd, nrhs int, ab []float64, ldab int, b []float64, ldb int) - Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 - Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) - Dpotri(ul blas.Uplo, n int, a []float64, lda int) (ok bool) - Dpotrs(ul blas.Uplo, n, nrhs int, a []float64, lda int, b []float64, ldb int) - Dpstrf(uplo blas.Uplo, n int, a []float64, lda int, piv []int, tol float64, work []float64) (rank int, ok bool) - Dsyev(jobz EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) - Dtbtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, kd, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) - Dtrcon(norm MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 - Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) - Dtrtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) -} - -// Direct specifies the direction of the multiplication for the Householder matrix. -type Direct byte - -const ( - Forward Direct = 'F' // Reflectors are right-multiplied, H_0 * H_1 * ... * H_{k-1}. - Backward Direct = 'B' // Reflectors are left-multiplied, H_{k-1} * ... * H_1 * H_0. -) - -// Sort is the sorting order. -type Sort byte - -const ( - SortIncreasing Sort = 'I' - SortDecreasing Sort = 'D' -) - -// StoreV indicates the storage direction of elementary reflectors. -type StoreV byte - -const ( - ColumnWise StoreV = 'C' // Reflector stored in a column of the matrix. - RowWise StoreV = 'R' // Reflector stored in a row of the matrix. -) - -// MatrixNorm represents the kind of matrix norm to compute. -type MatrixNorm byte - -const ( - MaxAbs MatrixNorm = 'M' // max(abs(A(i,j))) - MaxColumnSum MatrixNorm = 'O' // Maximum absolute column sum (one norm) - MaxRowSum MatrixNorm = 'I' // Maximum absolute row sum (infinity norm) - Frobenius MatrixNorm = 'F' // Frobenius norm (sqrt of sum of squares) -) - -// MatrixType represents the kind of matrix represented in the data. -type MatrixType byte - -const ( - General MatrixType = 'G' // A general dense matrix. - UpperTri MatrixType = 'U' // An upper triangular matrix. - LowerTri MatrixType = 'L' // A lower triangular matrix. -) - -// Pivot specifies the pivot type for plane rotations. -type Pivot byte - -const ( - Variable Pivot = 'V' - Top Pivot = 'T' - Bottom Pivot = 'B' -) - -// ApplyOrtho specifies which orthogonal matrix is applied in Dormbr. -type ApplyOrtho byte - -const ( - ApplyP ApplyOrtho = 'P' // Apply P or Pᵀ. - ApplyQ ApplyOrtho = 'Q' // Apply Q or Qᵀ. -) - -// GenOrtho specifies which orthogonal matrix is generated in Dorgbr. -type GenOrtho byte - -const ( - GeneratePT GenOrtho = 'P' // Generate Pᵀ. - GenerateQ GenOrtho = 'Q' // Generate Q. -) - -// SVDJob specifies the singular vector computation type for SVD. -type SVDJob byte - -const ( - SVDAll SVDJob = 'A' // Compute all columns of the orthogonal matrix U or V. - SVDStore SVDJob = 'S' // Compute the singular vectors and store them in the orthogonal matrix U or V. - SVDOverwrite SVDJob = 'O' // Compute the singular vectors and overwrite them on the input matrix A. - SVDNone SVDJob = 'N' // Do not compute singular vectors. -) - -// GSVDJob specifies the singular vector computation type for Generalized SVD. -type GSVDJob byte - -const ( - GSVDU GSVDJob = 'U' // Compute orthogonal matrix U. - GSVDV GSVDJob = 'V' // Compute orthogonal matrix V. - GSVDQ GSVDJob = 'Q' // Compute orthogonal matrix Q. - GSVDUnit GSVDJob = 'I' // Use unit-initialized matrix. - GSVDNone GSVDJob = 'N' // Do not compute orthogonal matrix. -) - -// EVComp specifies how eigenvectors are computed in Dsteqr. -type EVComp byte - -const ( - EVOrig EVComp = 'V' // Compute eigenvectors of the original symmetric matrix. - EVTridiag EVComp = 'I' // Compute eigenvectors of the tridiagonal matrix. - EVCompNone EVComp = 'N' // Do not compute eigenvectors. -) - -// EVJob specifies whether eigenvectors are computed in Dsyev. -type EVJob byte - -const ( - EVCompute EVJob = 'V' // Compute eigenvectors. - EVNone EVJob = 'N' // Do not compute eigenvectors. -) - -// LeftEVJob specifies whether left eigenvectors are computed in Dgeev. -type LeftEVJob byte - -const ( - LeftEVCompute LeftEVJob = 'V' // Compute left eigenvectors. - LeftEVNone LeftEVJob = 'N' // Do not compute left eigenvectors. -) - -// RightEVJob specifies whether right eigenvectors are computed in Dgeev. -type RightEVJob byte - -const ( - RightEVCompute RightEVJob = 'V' // Compute right eigenvectors. - RightEVNone RightEVJob = 'N' // Do not compute right eigenvectors. -) - -// BalanceJob specifies matrix balancing operation. -type BalanceJob byte - -const ( - Permute BalanceJob = 'P' - Scale BalanceJob = 'S' - PermuteScale BalanceJob = 'B' - BalanceNone BalanceJob = 'N' -) - -// SchurJob specifies whether the Schur form is computed in Dhseqr. -type SchurJob byte - -const ( - EigenvaluesOnly SchurJob = 'E' - EigenvaluesAndSchur SchurJob = 'S' -) - -// SchurComp specifies whether and how the Schur vectors are computed in Dhseqr. -type SchurComp byte - -const ( - SchurOrig SchurComp = 'V' // Compute Schur vectors of the original matrix. - SchurHess SchurComp = 'I' // Compute Schur vectors of the upper Hessenberg matrix. - SchurNone SchurComp = 'N' // Do not compute Schur vectors. -) - -// UpdateSchurComp specifies whether the matrix of Schur vectors is updated in Dtrexc. -type UpdateSchurComp byte - -const ( - UpdateSchur UpdateSchurComp = 'V' // Update the matrix of Schur vectors. - UpdateSchurNone UpdateSchurComp = 'N' // Do not update the matrix of Schur vectors. -) - -// EVSide specifies what eigenvectors are computed in Dtrevc3. -type EVSide byte - -const ( - EVRight EVSide = 'R' // Compute only right eigenvectors. - EVLeft EVSide = 'L' // Compute only left eigenvectors. - EVBoth EVSide = 'B' // Compute both right and left eigenvectors. -) - -// EVHowMany specifies which eigenvectors are computed in Dtrevc3 and how. -type EVHowMany byte - -const ( - EVAll EVHowMany = 'A' // Compute all right and/or left eigenvectors. - EVAllMulQ EVHowMany = 'B' // Compute all right and/or left eigenvectors multiplied by an input matrix. - EVSelected EVHowMany = 'S' // Compute selected right and/or left eigenvectors. -) - -// MaximizeNormXJob specifies the heuristic method for computing a contribution to -// the reciprocal Dif-estimate in Dlatdf. -type MaximizeNormXJob byte - -const ( - LocalLookAhead MaximizeNormXJob = 0 // Solve Z*x=h-f where h is a vector of ±1. - NormalizedNullVector MaximizeNormXJob = 2 // Compute an approximate null-vector e of Z, normalize e and solve Z*x=±e-f. -) - -// OrthoComp specifies whether and how the orthogonal matrix is computed in Dgghrd. -type OrthoComp byte - -const ( - OrthoNone OrthoComp = 'N' // Do not compute the orthogonal matrix. - OrthoExplicit OrthoComp = 'I' // The orthogonal matrix is formed explicitly and returned in the argument. - OrthoPostmul OrthoComp = 'V' // The orthogonal matrix is post-multiplied into the matrix stored in the argument on entry. -) diff --git a/vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go b/vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go deleted file mode 100644 index da19e3ec..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/lapack64/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright ©2017 The Gonum 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 lapack64 provides a set of convenient wrapper functions for LAPACK -// calls, as specified in the netlib standard (www.netlib.org). -// -// The native Go routines are used by default, and the Use function can be used -// to set an alternative implementation. -// -// If the type of matrix (General, Symmetric, etc.) is known and fixed, it is -// used in the wrapper signature. In many cases, however, the type of the matrix -// changes during the call to the routine, for example the matrix is symmetric on -// entry and is triangular on exit. In these cases the correct types should be checked -// in the documentation. -// -// The full set of Lapack functions is very large, and it is not clear that a -// full implementation is desirable, let alone feasible. Please open up an issue -// if there is a specific function you need and/or are willing to implement. -package lapack64 // import "gonum.org/v1/gonum/lapack/lapack64" diff --git a/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go b/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go deleted file mode 100644 index 1b4c1734..00000000 --- a/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go +++ /dev/null @@ -1,908 +0,0 @@ -// Copyright ©2015 The Gonum 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 lapack64 - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/gonum" -) - -var lapack64 lapack.Float64 = gonum.Implementation{} - -// Use sets the LAPACK float64 implementation to be used by subsequent BLAS calls. -// The default implementation is native.Implementation. -func Use(l lapack.Float64) { - lapack64 = l -} - -// Tridiagonal represents a tridiagonal matrix using its three diagonals. -type Tridiagonal struct { - N int - DL []float64 - D []float64 - DU []float64 -} - -// Potrf computes the Cholesky factorization of a. -// The factorization has the form -// -// A = Uᵀ * U if a.Uplo == blas.Upper, or -// A = L * Lᵀ if a.Uplo == blas.Lower, -// -// where U is an upper triangular matrix and L is lower triangular. -// The triangular matrix is returned in t, and the underlying data between -// a and t is shared. The returned bool indicates whether a is positive -// definite and the factorization could be finished. -func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) { - ok = lapack64.Dpotrf(a.Uplo, a.N, a.Data, max(1, a.Stride)) - t.Uplo = a.Uplo - t.N = a.N - t.Data = a.Data - t.Stride = a.Stride - t.Diag = blas.NonUnit - return -} - -// Potri computes the inverse of a real symmetric positive definite matrix A -// using its Cholesky factorization. -// -// On entry, t contains the triangular factor U or L from the Cholesky -// factorization A = Uᵀ*U or A = L*Lᵀ, as computed by Potrf. -// -// On return, the upper or lower triangle of the (symmetric) inverse of A is -// stored in t, overwriting the input factor U or L, and also returned in a. The -// underlying data between a and t is shared. -// -// The returned bool indicates whether the inverse was computed successfully. -func Potri(t blas64.Triangular) (a blas64.Symmetric, ok bool) { - ok = lapack64.Dpotri(t.Uplo, t.N, t.Data, max(1, t.Stride)) - a.Uplo = t.Uplo - a.N = t.N - a.Data = t.Data - a.Stride = t.Stride - return -} - -// Potrs solves a system of n linear equations A*X = B where A is an n×n -// symmetric positive definite matrix and B is an n×nrhs matrix, using the -// Cholesky factorization A = Uᵀ*U or A = L*Lᵀ. t contains the corresponding -// triangular factor as returned by Potrf. On entry, B contains the right-hand -// side matrix B, on return it contains the solution matrix X. -func Potrs(t blas64.Triangular, b blas64.General) { - lapack64.Dpotrs(t.Uplo, t.N, b.Cols, t.Data, max(1, t.Stride), b.Data, max(1, b.Stride)) -} - -// Pbcon returns an estimate of the reciprocal of the condition number (in the -// 1-norm) of an n×n symmetric positive definite band matrix using the Cholesky -// factorization -// -// A = Uᵀ*U if uplo == blas.Upper -// A = L*Lᵀ if uplo == blas.Lower -// -// computed by Pbtrf. The estimate is obtained for norm(inv(A)), and the -// reciprocal of the condition number is computed as -// -// rcond = 1 / (anorm * norm(inv(A))). -// -// The length of work must be at least 3*n and the length of iwork must be at -// least n. -func Pbcon(a blas64.SymmetricBand, anorm float64, work []float64, iwork []int) float64 { - return lapack64.Dpbcon(a.Uplo, a.N, a.K, a.Data, a.Stride, anorm, work, iwork) -} - -// Pbtrf computes the Cholesky factorization of an n×n symmetric positive -// definite band matrix -// -// A = Uᵀ * U if a.Uplo == blas.Upper -// A = L * Lᵀ if a.Uplo == blas.Lower -// -// where U and L are upper, respectively lower, triangular band matrices. -// -// The triangular matrix U or L is returned in t, and the underlying data -// between a and t is shared. The returned bool indicates whether A is positive -// definite and the factorization could be finished. -func Pbtrf(a blas64.SymmetricBand) (t blas64.TriangularBand, ok bool) { - ok = lapack64.Dpbtrf(a.Uplo, a.N, a.K, a.Data, max(1, a.Stride)) - t.Uplo = a.Uplo - t.Diag = blas.NonUnit - t.N = a.N - t.K = a.K - t.Data = a.Data - t.Stride = a.Stride - return t, ok -} - -// Pbtrs solves a system of linear equations A*X = B with an n×n symmetric -// positive definite band matrix A using the Cholesky factorization -// -// A = Uᵀ * U if t.Uplo == blas.Upper -// A = L * Lᵀ if t.Uplo == blas.Lower -// -// t contains the corresponding triangular factor as returned by Pbtrf. -// -// On entry, b contains the right hand side matrix B. On return, it is -// overwritten with the solution matrix X. -func Pbtrs(t blas64.TriangularBand, b blas64.General) { - lapack64.Dpbtrs(t.Uplo, t.N, t.K, b.Cols, t.Data, max(1, t.Stride), b.Data, max(1, b.Stride)) -} - -// Pstrf computes the Cholesky factorization with complete pivoting of an n×n -// symmetric positive semidefinite matrix A. -// -// The factorization has the form -// -// Pᵀ * A * P = Uᵀ * U , if a.Uplo = blas.Upper, -// Pᵀ * A * P = L * Lᵀ, if a.Uplo = blas.Lower, -// -// where U is an upper triangular matrix, L is lower triangular, and P is a -// permutation matrix. -// -// tol is a user-defined tolerance. The algorithm terminates if the pivot is -// less than or equal to tol. If tol is negative, then n*eps*max(A[k,k]) will be -// used instead. -// -// The triangular factor U or L from the Cholesky factorization is returned in t -// and the underlying data between a and t is shared. P is stored on return in -// vector piv such that P[piv[k],k] = 1. -// -// Pstrf returns the computed rank of A and whether the factorization can be -// used to solve a system. Pstrf does not attempt to check that A is positive -// semi-definite, so if ok is false, the matrix A is either rank deficient or is -// not positive semidefinite. -// -// The length of piv must be n and the length of work must be at least 2*n, -// otherwise Pstrf will panic. -func Pstrf(a blas64.Symmetric, piv []int, tol float64, work []float64) (t blas64.Triangular, rank int, ok bool) { - rank, ok = lapack64.Dpstrf(a.Uplo, a.N, a.Data, max(1, a.Stride), piv, tol, work) - t.Uplo = a.Uplo - t.Diag = blas.NonUnit - t.N = a.N - t.Data = a.Data - t.Stride = a.Stride - return t, rank, ok -} - -// Gecon estimates the reciprocal of the condition number of the n×n matrix A -// given the LU decomposition of the matrix. The condition number computed may -// be based on the 1-norm or the ∞-norm. -// -// a contains the result of the LU decomposition of A as computed by Getrf. -// -// anorm is the corresponding 1-norm or ∞-norm of the original matrix A. -// -// work is a temporary data slice of length at least 4*n and Gecon will panic otherwise. -// -// iwork is a temporary data slice of length at least n and Gecon will panic otherwise. -func Gecon(norm lapack.MatrixNorm, a blas64.General, anorm float64, work []float64, iwork []int) float64 { - return lapack64.Dgecon(norm, a.Cols, a.Data, max(1, a.Stride), anorm, work, iwork) -} - -// Gels finds a minimum-norm solution based on the matrices A and B using the -// QR or LQ factorization. Gels returns false if the matrix -// A is singular, and true if this solution was successfully found. -// -// The minimization problem solved depends on the input parameters. -// -// 1. If m >= n and trans == blas.NoTrans, Gels finds X such that || A*X - B||_2 -// is minimized. -// 2. If m < n and trans == blas.NoTrans, Gels finds the minimum norm solution of -// A * X = B. -// 3. If m >= n and trans == blas.Trans, Gels finds the minimum norm solution of -// Aᵀ * X = B. -// 4. If m < n and trans == blas.Trans, Gels finds X such that || A*X - B||_2 -// is minimized. -// -// Note that the least-squares solutions (cases 1 and 3) perform the minimization -// per column of B. This is not the same as finding the minimum-norm matrix. -// -// The matrix A is a general matrix of size m×n and is modified during this call. -// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry, -// the elements of b specify the input matrix B. B has size m×nrhs if -// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the -// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans, -// this submatrix is of size n×nrhs, and of size m×nrhs otherwise. -// -// Work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic -// otherwise. A longer work will enable blocked algorithms to be called. -// In the special case that lwork == -1, work[0] will be set to the optimal working -// length. -func Gels(trans blas.Transpose, a blas64.General, b blas64.General, work []float64, lwork int) bool { - return lapack64.Dgels(trans, a.Rows, a.Cols, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride), work, lwork) -} - -// Geqp3 computes a QR factorization with column pivoting of the m×n matrix A: -// -// A*P = Q*R -// -// where P is a permutation matrix, Q is an orthogonal matrix and R is a -// min(m,n)×n upper trapezoidal matrix. -// -// On return, the upper triangle of A contains the matrix R. The elements below -// the diagonal together with tau represent the matrix Q as a product of -// elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). -// -// Each H_i has the form -// -// H_i = I - tau * v * vᵀ -// -// where tau is a scalar and v is a vector with v[0:i] = 0 and v[i] = 1; -// v[i+1:m] is stored on exit in A[i+1:m,i], and tau in tau[i]. -// -// jpvt specifies a column pivot to be applied to A. On entry, if jpvt[j] is at -// least zero, the jth column of A is permuted to the front of A*P (a leading -// column), if jpvt[j] is -1 the jth column of A is a free column. If jpvt[j] < -// -1, Geqp3 will panic. On return, jpvt holds the permutation that was applied; -// the jth column of A*P was the jpvt[j] column of A. jpvt must have length n or -// Geqp3 will panic. -// -// tau holds the scalar factors of the elementary reflectors. It must have -// length min(m,n), otherwise Geqp3 will panic. -// -// work must have length at least max(1,lwork), and lwork must be at least -// 3*n+1, otherwise Geqp3 will panic. For optimal performance lwork must be at -// least 2*n+(n+1)*nb, where nb is the optimal blocksize. On return, work[0] -// will contain the optimal value of lwork. -// -// If lwork == -1, instead of performing Geqp3, only the optimal value of lwork -// will be stored in work[0]. -func Geqp3(a blas64.General, jpvt []int, tau, work []float64, lwork int) { - lapack64.Dgeqp3(a.Rows, a.Cols, a.Data, max(1, a.Stride), jpvt, tau, work, lwork) -} - -// Geqrf computes the QR factorization of the m×n matrix A using a blocked -// algorithm. A is modified to contain the information to construct Q and R. -// The upper triangle of a contains the matrix R. The lower triangular elements -// (not including the diagonal) contain the elementary reflectors. tau is modified -// to contain the reflector scales. tau must have length min(m,n), and -// this function will panic otherwise. -// -// The ith elementary reflector can be explicitly constructed by first extracting -// the -// -// v[j] = 0 j < i -// v[j] = 1 j == i -// v[j] = a[j*lda+i] j > i -// -// and computing H_i = I - tau[i] * v * vᵀ. -// -// The orthonormal matrix Q can be constructed from a product of these elementary -// reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). -// -// Work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= m and this function will panic otherwise. -// Geqrf is a blocked QR factorization, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Geqrf, -// the optimal work length will be stored into work[0]. -func Geqrf(a blas64.General, tau, work []float64, lwork int) { - lapack64.Dgeqrf(a.Rows, a.Cols, a.Data, max(1, a.Stride), tau, work, lwork) -} - -// Gelqf computes the LQ factorization of the m×n matrix A using a blocked -// algorithm. A is modified to contain the information to construct L and Q. The -// lower triangle of a contains the matrix L. The elements above the diagonal -// and the slice tau represent the matrix Q. tau is modified to contain the -// reflector scales. tau must have length at least min(m,n), and this function -// will panic otherwise. -// -// See Geqrf for a description of the elementary reflectors and orthonormal -// matrix Q. Q is constructed as a product of these elementary reflectors, -// Q = H_{k-1} * ... * H_1 * H_0. -// -// Work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= m and this function will panic otherwise. -// Gelqf is a blocked LQ factorization, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Gelqf, -// the optimal work length will be stored into work[0]. -func Gelqf(a blas64.General, tau, work []float64, lwork int) { - lapack64.Dgelqf(a.Rows, a.Cols, a.Data, max(1, a.Stride), tau, work, lwork) -} - -// Gesvd computes the singular value decomposition of the input matrix A. -// -// The singular value decomposition is -// -// A = U * Sigma * Vᵀ -// -// where Sigma is an m×n diagonal matrix containing the singular values of A, -// U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first -// min(m,n) columns of U and V are the left and right singular vectors of A -// respectively. -// -// jobU and jobVT are options for computing the singular vectors. The behavior -// is as follows -// -// jobU == lapack.SVDAll All m columns of U are returned in u -// jobU == lapack.SVDStore The first min(m,n) columns are returned in u -// jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a -// jobU == lapack.SVDNone The columns of U are not computed. -// -// The behavior is the same for jobVT and the rows of Vᵀ. At most one of jobU -// and jobVT can equal lapack.SVDOverwrite, and Gesvd will panic otherwise. -// -// On entry, a contains the data for the m×n matrix A. During the call to Gesvd -// the data is overwritten. On exit, A contains the appropriate singular vectors -// if either job is lapack.SVDOverwrite. -// -// s is a slice of length at least min(m,n) and on exit contains the singular -// values in decreasing order. -// -// u contains the left singular vectors on exit, stored columnwise. If -// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDStore u is -// of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is -// not used. -// -// vt contains the left singular vectors on exit, stored rowwise. If -// jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDStore vt is -// of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is -// not used. -// -// work is a slice for storing temporary memory, and lwork is the usable size of -// the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)). -// If lwork == -1, instead of performing Gesvd, the optimal work length will be -// stored into work[0]. Gesvd will panic if the working memory has insufficient -// storage. -// -// Gesvd returns whether the decomposition successfully completed. -func Gesvd(jobU, jobVT lapack.SVDJob, a, u, vt blas64.General, s, work []float64, lwork int) (ok bool) { - return lapack64.Dgesvd(jobU, jobVT, a.Rows, a.Cols, a.Data, max(1, a.Stride), s, u.Data, max(1, u.Stride), vt.Data, max(1, vt.Stride), work, lwork) -} - -// Getrf computes the LU decomposition of an m×n matrix A using partial -// pivoting with row interchanges. -// -// The LU decomposition is a factorization of A into -// -// A = P * L * U -// -// where P is a permutation matrix, L is a lower triangular with unit diagonal -// elements (lower trapezoidal if m > n), and U is upper triangular (upper -// trapezoidal if m < n). -// -// On entry, a contains the matrix A. On return, L and U are stored in place -// into a, and P is represented by ipiv. -// -// ipiv contains a sequence of row swaps. It indicates that row i of the matrix -// was interchanged with ipiv[i]. ipiv must have length min(m,n), and Getrf will -// panic otherwise. ipiv is zero-indexed. -// -// Getrf returns whether the matrix A is nonsingular. The LU decomposition will -// be computed regardless of the singularity of A, but the result should not be -// used to solve a system of equation. -func Getrf(a blas64.General, ipiv []int) bool { - return lapack64.Dgetrf(a.Rows, a.Cols, a.Data, max(1, a.Stride), ipiv) -} - -// Getri computes the inverse of the matrix A using the LU factorization computed -// by Getrf. On entry, a contains the PLU decomposition of A as computed by -// Getrf and on exit contains the reciprocal of the original matrix. -// -// Getri will not perform the inversion if the matrix is singular, and returns -// a boolean indicating whether the inversion was successful. -// -// Work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= n and this function will panic otherwise. -// Getri is a blocked inversion, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Getri, -// the optimal work length will be stored into work[0]. -func Getri(a blas64.General, ipiv []int, work []float64, lwork int) (ok bool) { - return lapack64.Dgetri(a.Cols, a.Data, max(1, a.Stride), ipiv, work, lwork) -} - -// Getrs solves a system of equations using an LU factorization. -// The system of equations solved is -// -// A * X = B if trans == blas.Trans -// Aᵀ * X = B if trans == blas.NoTrans -// -// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. -// -// On entry b contains the elements of the matrix B. On exit, b contains the -// elements of X, the solution to the system of equations. -// -// a and ipiv contain the LU factorization of A and the permutation indices as -// computed by Getrf. ipiv is zero-indexed. -func Getrs(trans blas.Transpose, a blas64.General, b blas64.General, ipiv []int) { - lapack64.Dgetrs(trans, a.Cols, b.Cols, a.Data, max(1, a.Stride), ipiv, b.Data, max(1, b.Stride)) -} - -// Ggsvd3 computes the generalized singular value decomposition (GSVD) -// of an m×n matrix A and p×n matrix B: -// -// Uᵀ*A*Q = D1*[ 0 R ] -// -// Vᵀ*B*Q = D2*[ 0 R ] -// -// where U, V and Q are orthogonal matrices. -// -// Ggsvd3 returns k and l, the dimensions of the sub-blocks. k+l -// is the effective numerical rank of the (m+p)×n matrix [ Aᵀ Bᵀ ]ᵀ. -// R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and -// D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following -// structures, respectively: -// -// If m-k-l >= 0, -// -// k l -// D1 = k [ I 0 ] -// l [ 0 C ] -// m-k-l [ 0 0 ] -// -// k l -// D2 = l [ 0 S ] -// p-l [ 0 0 ] -// -// n-k-l k l -// [ 0 R ] = k [ 0 R11 R12 ] k -// l [ 0 0 R22 ] l -// -// where -// -// C = diag( alpha_k, ... , alpha_{k+l} ), -// S = diag( beta_k, ... , beta_{k+l} ), -// C^2 + S^2 = I. -// -// R is stored in -// -// A[0:k+l, n-k-l:n] -// -// on exit. -// -// If m-k-l < 0, -// -// k m-k k+l-m -// D1 = k [ I 0 0 ] -// m-k [ 0 C 0 ] -// -// k m-k k+l-m -// D2 = m-k [ 0 S 0 ] -// k+l-m [ 0 0 I ] -// p-l [ 0 0 0 ] -// -// n-k-l k m-k k+l-m -// [ 0 R ] = k [ 0 R11 R12 R13 ] -// m-k [ 0 0 R22 R23 ] -// k+l-m [ 0 0 0 R33 ] -// -// where -// -// C = diag( alpha_k, ... , alpha_m ), -// S = diag( beta_k, ... , beta_m ), -// C^2 + S^2 = I. -// -// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] -// [ 0 R22 R23 ] -// -// and R33 is stored in -// -// B[m-k:l, n+m-k-l:n] on exit. -// -// Ggsvd3 computes C, S, R, and optionally the orthogonal transformation -// matrices U, V and Q. -// -// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior -// is as follows -// -// jobU == lapack.GSVDU Compute orthogonal matrix U -// jobU == lapack.GSVDNone Do not compute orthogonal matrix. -// -// The behavior is the same for jobV and jobQ with the exception that instead of -// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. -// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the -// relevant job parameter is lapack.GSVDNone. -// -// alpha and beta must have length n or Ggsvd3 will panic. On exit, alpha and -// beta contain the generalized singular value pairs of A and B -// -// alpha[0:k] = 1, -// beta[0:k] = 0, -// -// if m-k-l >= 0, -// -// alpha[k:k+l] = diag(C), -// beta[k:k+l] = diag(S), -// -// if m-k-l < 0, -// -// alpha[k:m]= C, alpha[m:k+l]= 0 -// beta[k:m] = S, beta[m:k+l] = 1. -// -// if k+l < n, -// -// alpha[k+l:n] = 0 and -// beta[k+l:n] = 0. -// -// On exit, iwork contains the permutation required to sort alpha descending. -// -// iwork must have length n, work must have length at least max(1, lwork), and -// lwork must be -1 or greater than n, otherwise Ggsvd3 will panic. If -// lwork is -1, work[0] holds the optimal lwork on return, but Ggsvd3 does -// not perform the GSVD. -func Ggsvd3(jobU, jobV, jobQ lapack.GSVDJob, a, b blas64.General, alpha, beta []float64, u, v, q blas64.General, work []float64, lwork int, iwork []int) (k, l int, ok bool) { - return lapack64.Dggsvd3(jobU, jobV, jobQ, a.Rows, a.Cols, b.Rows, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride), alpha, beta, u.Data, max(1, u.Stride), v.Data, max(1, v.Stride), q.Data, max(1, q.Stride), work, lwork, iwork) -} - -// Gtsv solves one of the equations -// -// A * X = B if trans == blas.NoTrans -// Aᵀ * X = B if trans == blas.Trans or blas.ConjTrans -// -// where A is an n×n tridiagonal matrix. It uses Gaussian elimination with -// partial pivoting. -// -// On entry, a contains the matrix A, on return it will be overwritten. -// -// On entry, b contains the n×nrhs right-hand side matrix B. On return, it will -// be overwritten. If ok is true, it will be overwritten by the solution matrix X. -// -// Gtsv returns whether the solution X has been successfully computed. -// -// Dgtsv is not part of the lapack.Float64 interface and so calls to Gtsv are -// always executed by the Gonum implementation. -func Gtsv(trans blas.Transpose, a Tridiagonal, b blas64.General) (ok bool) { - if trans != blas.NoTrans { - a.DL, a.DU = a.DU, a.DL - } - return gonum.Implementation{}.Dgtsv(a.N, b.Cols, a.DL, a.D, a.DU, b.Data, max(1, b.Stride)) -} - -// Lagtm performs one of the matrix-matrix operations -// -// C = alpha * A * B + beta * C if trans == blas.NoTrans -// C = alpha * Aᵀ * B + beta * C if trans == blas.Trans or blas.ConjTrans -// -// where A is an m×m tridiagonal matrix represented by its diagonals dl, d, du, -// B and C are m×n dense matrices, and alpha and beta are scalars. -// -// Dlagtm is not part of the lapack.Float64 interface and so calls to Lagtm are -// always executed by the Gonum implementation. -func Lagtm(trans blas.Transpose, alpha float64, a Tridiagonal, b blas64.General, beta float64, c blas64.General) { - gonum.Implementation{}.Dlagtm(trans, c.Rows, c.Cols, alpha, a.DL, a.D, a.DU, b.Data, max(1, b.Stride), beta, c.Data, max(1, c.Stride)) -} - -// Lange computes the matrix norm of the general m×n matrix A. The input norm -// specifies the norm computed. -// -// lapack.MaxAbs: the maximum absolute value of an element. -// lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries. -// lapack.MaxRowSum: the maximum row sum of the absolute values of the entries. -// lapack.Frobenius: the square root of the sum of the squares of the entries. -// -// If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise. -// There are no restrictions on work for the other matrix norms. -func Lange(norm lapack.MatrixNorm, a blas64.General, work []float64) float64 { - return lapack64.Dlange(norm, a.Rows, a.Cols, a.Data, max(1, a.Stride), work) -} - -// Langb returns the given norm of a general m×n band matrix with kl sub-diagonals and -// ku super-diagonals. -// -// Dlangb is not part of the lapack.Float64 interface and so calls to Langb are always -// executed by the Gonum implementation. -func Langb(norm lapack.MatrixNorm, a blas64.Band) float64 { - return gonum.Implementation{}.Dlangb(norm, a.Rows, a.Cols, a.KL, a.KU, a.Data, max(1, a.Stride)) -} - -// Langt computes the specified norm of an n×n tridiagonal matrix. -// -// Dlangt is not part of the lapack.Float64 interface and so calls to Langt are -// always executed by the Gonum implementation. -func Langt(norm lapack.MatrixNorm, a Tridiagonal) float64 { - return gonum.Implementation{}.Dlangt(norm, a.N, a.DL, a.D, a.DU) -} - -// Lansb computes the specified norm of an n×n symmetric band matrix. If -// norm == lapack.MaxColumnSum or norm == lapack.MaxRowSum, work must have length -// at least n and this function will panic otherwise. -// There are no restrictions on work for the other matrix norms. -// -// Dlansb is not part of the lapack.Float64 interface and so calls to Lansb are always -// executed by the Gonum implementation. -func Lansb(norm lapack.MatrixNorm, a blas64.SymmetricBand, work []float64) float64 { - return gonum.Implementation{}.Dlansb(norm, a.Uplo, a.N, a.K, a.Data, max(1, a.Stride), work) -} - -// Lansy computes the specified norm of an n×n symmetric matrix. If -// norm == lapack.MaxColumnSum or norm == lapack.MaxRowSum, work must have length -// at least n and this function will panic otherwise. -// There are no restrictions on work for the other matrix norms. -func Lansy(norm lapack.MatrixNorm, a blas64.Symmetric, work []float64) float64 { - return lapack64.Dlansy(norm, a.Uplo, a.N, a.Data, max(1, a.Stride), work) -} - -// Lantr computes the specified norm of an m×n trapezoidal matrix A. If -// norm == lapack.MaxColumnSum work must have length at least n and this function -// will panic otherwise. There are no restrictions on work for the other matrix norms. -func Lantr(norm lapack.MatrixNorm, a blas64.Triangular, work []float64) float64 { - return lapack64.Dlantr(norm, a.Uplo, a.Diag, a.N, a.N, a.Data, max(1, a.Stride), work) -} - -// Lantb computes the specified norm of an n×n triangular band matrix A. If -// norm == lapack.MaxColumnSum work must have length at least n and this function -// will panic otherwise. There are no restrictions on work for the other matrix -// norms. -func Lantb(norm lapack.MatrixNorm, a blas64.TriangularBand, work []float64) float64 { - return gonum.Implementation{}.Dlantb(norm, a.Uplo, a.Diag, a.N, a.K, a.Data, max(1, a.Stride), work) -} - -// Lapmr rearranges the rows of the m×n matrix X as specified by the permutation -// k[0],k[1],...,k[m-1] of the integers 0,...,m-1. -// -// If forward is true, a forward permutation is applied: -// -// X[k[i],0:n] is moved to X[i,0:n] for i=0,1,...,m-1. -// -// If forward is false, a backward permutation is applied: -// -// X[i,0:n] is moved to X[k[i],0:n] for i=0,1,...,m-1. -// -// k must have length m, otherwise Lapmr will panic. k is zero-indexed. -func Lapmr(forward bool, x blas64.General, k []int) { - lapack64.Dlapmr(forward, x.Rows, x.Cols, x.Data, max(1, x.Stride), k) -} - -// Lapmt rearranges the columns of the m×n matrix X as specified by the -// permutation k[0],k[1],...,k[n-1] of the integers 0,...,n-1. -// -// If forward is true, a forward permutation is applied: -// -// X[0:m,k[j]] is moved to X[0:m,j] for j=0,1,...,n-1. -// -// If forward is false, a backward permutation is applied: -// -// X[0:m,j] is moved to X[0:m,k[j]] for j=0,1,...,n-1. -// -// k must have length n, otherwise Lapmt will panic. k is zero-indexed. -func Lapmt(forward bool, x blas64.General, k []int) { - lapack64.Dlapmt(forward, x.Rows, x.Cols, x.Data, max(1, x.Stride), k) -} - -// Orglq generates an m×n matrix Q with orthonormal rows defined as the first m -// rows of a product of k elementary reflectors of order n -// -// Q = H_{k-1} * ... * H_0 -// -// as returned by Dgelqf. -// -// k is determined by the length of tau. -// -// On entry, tau and the first k rows of A must contain the scalar factors and -// the vectors, respectively, which define the elementary reflectors H_i, -// i=0,...,k-1, as returned by Dgelqf. On return, A contains the matrix Q. -// -// work must have length at least lwork and lwork must be at least max(1,m). On -// return, optimal value of lwork will be stored in work[0]. It must also hold -// that 0 <= k <= m <= n, otherwise Orglq will panic. -// -// If lwork == -1, instead of performing Orglq, the function only calculates the -// optimal value of lwork and stores it into work[0]. -func Orglq(a blas64.General, tau, work []float64, lwork int) { - lapack64.Dorglq(a.Rows, a.Cols, len(tau), a.Data, a.Stride, tau, work, lwork) -} - -// Ormlq multiplies the matrix C by the othogonal matrix Q defined by -// A and tau. A and tau are as returned from Gelqf. -// -// C = Q * C if side == blas.Left and trans == blas.NoTrans -// C = Qᵀ * C if side == blas.Left and trans == blas.Trans -// C = C * Q if side == blas.Right and trans == blas.NoTrans -// C = C * Qᵀ if side == blas.Right and trans == blas.Trans -// -// If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right -// A is of size k×n. This uses a blocked algorithm. -// -// Work is temporary storage, and lwork specifies the usable memory length. -// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right, -// and this function will panic otherwise. -// Ormlq uses a block algorithm, but the block size is limited -// by the temporary space available. If lwork == -1, instead of performing Ormlq, -// the optimal work length will be stored into work[0]. -// -// Tau contains the Householder scales and must have length at least k, and -// this function will panic otherwise. -func Ormlq(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) { - lapack64.Dormlq(side, trans, c.Rows, c.Cols, a.Rows, a.Data, max(1, a.Stride), tau, c.Data, max(1, c.Stride), work, lwork) -} - -// Orgqr generates an m×n matrix Q with orthonormal columns defined by the -// product of elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{k-1} -// -// as computed by Geqrf. -// -// k is determined by the length of tau. -// -// The length of work must be at least n and it also must be that 0 <= k <= n -// and 0 <= n <= m. -// -// work is temporary storage, and lwork specifies the usable memory length. At -// minimum, lwork >= n, and the amount of blocking is limited by the usable -// length. If lwork == -1, instead of computing Orgqr the optimal work length -// is stored into work[0]. -// -// Orgqr will panic if the conditions on input values are not met. -func Orgqr(a blas64.General, tau []float64, work []float64, lwork int) { - lapack64.Dorgqr(a.Rows, a.Cols, len(tau), a.Data, a.Stride, tau, work, lwork) -} - -// Ormqr multiplies an m×n matrix C by an orthogonal matrix Q as -// -// C = Q * C if side == blas.Left and trans == blas.NoTrans, -// C = Qᵀ * C if side == blas.Left and trans == blas.Trans, -// C = C * Q if side == blas.Right and trans == blas.NoTrans, -// C = C * Qᵀ if side == blas.Right and trans == blas.Trans, -// -// where Q is defined as the product of k elementary reflectors -// -// Q = H_0 * H_1 * ... * H_{k-1}. -// -// k is determined by the length of tau. -// -// If side == blas.Left, A is an m×k matrix and 0 <= k <= m. -// If side == blas.Right, A is an n×k matrix and 0 <= k <= n. -// The ith column of A contains the vector which defines the elementary -// reflector H_i and tau[i] contains its scalar factor. Geqrf returns A and tau -// in the required form. -// -// work must have length at least max(1,lwork), and lwork must be at least n if -// side == blas.Left and at least m if side == blas.Right, otherwise Ormqr will -// panic. -// -// work is temporary storage, and lwork specifies the usable memory length. At -// minimum, lwork >= m if side == blas.Left and lwork >= n if side == -// blas.Right, and this function will panic otherwise. Larger values of lwork -// will generally give better performance. On return, work[0] will contain the -// optimal value of lwork. -// -// If lwork is -1, instead of performing Ormqr, the optimal workspace size will -// be stored into work[0]. -func Ormqr(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) { - lapack64.Dormqr(side, trans, c.Rows, c.Cols, len(tau), a.Data, max(1, a.Stride), tau, c.Data, max(1, c.Stride), work, lwork) -} - -// Pocon estimates the reciprocal of the condition number of a positive-definite -// matrix A given the Cholesky decomposition of A. The condition number computed -// is based on the 1-norm and the ∞-norm. -// -// anorm is the 1-norm and the ∞-norm of the original matrix A. -// -// work is a temporary data slice of length at least 3*n and Pocon will panic otherwise. -// -// iwork is a temporary data slice of length at least n and Pocon will panic otherwise. -func Pocon(a blas64.Symmetric, anorm float64, work []float64, iwork []int) float64 { - return lapack64.Dpocon(a.Uplo, a.N, a.Data, max(1, a.Stride), anorm, work, iwork) -} - -// Syev computes all eigenvalues and, optionally, the eigenvectors of a real -// symmetric matrix A. -// -// w contains the eigenvalues in ascending order upon return. w must have length -// at least n, and Syev will panic otherwise. -// -// On entry, a contains the elements of the symmetric matrix A in the triangular -// portion specified by uplo. If jobz == lapack.EVCompute, a contains the -// orthonormal eigenvectors of A on exit, otherwise jobz must be lapack.EVNone -// and on exit the specified triangular region is overwritten. -// -// Work is temporary storage, and lwork specifies the usable memory length. At minimum, -// lwork >= 3*n-1, and Syev will panic otherwise. The amount of blocking is -// limited by the usable length. If lwork == -1, instead of computing Syev the -// optimal work length is stored into work[0]. -func Syev(jobz lapack.EVJob, a blas64.Symmetric, w, work []float64, lwork int) (ok bool) { - return lapack64.Dsyev(jobz, a.Uplo, a.N, a.Data, max(1, a.Stride), w, work, lwork) -} - -// Tbtrs solves a triangular system of the form -// -// A * X = B if trans == blas.NoTrans -// Aᵀ * X = B if trans == blas.Trans or blas.ConjTrans -// -// where A is an n×n triangular band matrix, and B is an n×nrhs matrix. -// -// Tbtrs returns whether A is non-singular. If A is singular, no solutions X -// are computed. -func Tbtrs(trans blas.Transpose, a blas64.TriangularBand, b blas64.General) (ok bool) { - return lapack64.Dtbtrs(a.Uplo, trans, a.Diag, a.N, a.K, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride)) -} - -// Trcon estimates the reciprocal of the condition number of a triangular matrix A. -// The condition number computed may be based on the 1-norm or the ∞-norm. -// -// work is a temporary data slice of length at least 3*n and Trcon will panic otherwise. -// -// iwork is a temporary data slice of length at least n and Trcon will panic otherwise. -func Trcon(norm lapack.MatrixNorm, a blas64.Triangular, work []float64, iwork []int) float64 { - return lapack64.Dtrcon(norm, a.Uplo, a.Diag, a.N, a.Data, max(1, a.Stride), work, iwork) -} - -// Trtri computes the inverse of a triangular matrix, storing the result in place -// into a. -// -// Trtri will not perform the inversion if the matrix is singular, and returns -// a boolean indicating whether the inversion was successful. -func Trtri(a blas64.Triangular) (ok bool) { - return lapack64.Dtrtri(a.Uplo, a.Diag, a.N, a.Data, max(1, a.Stride)) -} - -// Trtrs solves a triangular system of the form A * X = B or Aᵀ * X = B. Trtrs -// returns whether the solve completed successfully. If A is singular, no solve is performed. -func Trtrs(trans blas.Transpose, a blas64.Triangular, b blas64.General) (ok bool) { - return lapack64.Dtrtrs(a.Uplo, trans, a.Diag, a.N, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride)) -} - -// Geev computes the eigenvalues and, optionally, the left and/or right -// eigenvectors for an n×n real nonsymmetric matrix A. -// -// The right eigenvector v_j of A corresponding to an eigenvalue λ_j -// is defined by -// -// A v_j = λ_j v_j, -// -// and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by -// -// u_jᴴ A = λ_j u_jᴴ, -// -// where u_jᴴ is the conjugate transpose of u_j. -// -// On return, A will be overwritten and the left and right eigenvectors will be -// stored, respectively, in the columns of the n×n matrices VL and VR in the -// same order as their eigenvalues. If the j-th eigenvalue is real, then -// -// u_j = VL[:,j], -// v_j = VR[:,j], -// -// and if it is not real, then j and j+1 form a complex conjugate pair and the -// eigenvectors can be recovered as -// -// u_j = VL[:,j] + i*VL[:,j+1], -// u_{j+1} = VL[:,j] - i*VL[:,j+1], -// v_j = VR[:,j] + i*VR[:,j+1], -// v_{j+1} = VR[:,j] - i*VR[:,j+1], -// -// where i is the imaginary unit. The computed eigenvectors are normalized to -// have Euclidean norm equal to 1 and largest component real. -// -// Left eigenvectors will be computed only if jobvl == lapack.LeftEVCompute, -// otherwise jobvl must be lapack.LeftEVNone. -// Right eigenvectors will be computed only if jobvr == lapack.RightEVCompute, -// otherwise jobvr must be lapack.RightEVNone. -// For other values of jobvl and jobvr Geev will panic. -// -// On return, wr and wi will contain the real and imaginary parts, respectively, -// of the computed eigenvalues. Complex conjugate pairs of eigenvalues appear -// consecutively with the eigenvalue having the positive imaginary part first. -// wr and wi must have length n, and Geev will panic otherwise. -// -// work must have length at least lwork and lwork must be at least max(1,4*n) if -// the left or right eigenvectors are computed, and at least max(1,3*n) if no -// eigenvectors are computed. For good performance, lwork must generally be -// larger. On return, optimal value of lwork will be stored in work[0]. -// -// If lwork == -1, instead of performing Geev, the function only calculates the -// optimal value of lwork and stores it into work[0]. -// -// On return, first will be the index of the first valid eigenvalue. -// If first == 0, all eigenvalues and eigenvectors have been computed. -// If first is positive, Geev failed to compute all the eigenvalues, no -// eigenvectors have been computed and wr[first:] and wi[first:] contain those -// eigenvalues which have converged. -func Geev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, a blas64.General, wr, wi []float64, vl, vr blas64.General, work []float64, lwork int) (first int) { - n := a.Rows - if a.Cols != n { - panic("lapack64: matrix not square") - } - if jobvl == lapack.LeftEVCompute && (vl.Rows != n || vl.Cols != n) { - panic("lapack64: bad size of VL") - } - if jobvr == lapack.RightEVCompute && (vr.Rows != n || vr.Cols != n) { - panic("lapack64: bad size of VR") - } - return lapack64.Dgeev(jobvl, jobvr, n, a.Data, max(1, a.Stride), wr, wi, vl.Data, max(1, vl.Stride), vr.Data, max(1, vr.Stride), work, lwork) -} diff --git a/vendor/gonum.org/v1/gonum/mat/README.md b/vendor/gonum.org/v1/gonum/mat/README.md deleted file mode 100644 index 5e7be6b2..00000000 --- a/vendor/gonum.org/v1/gonum/mat/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Gonum matrix - -[![go.dev reference](https://pkg.go.dev/badge/gonum.org/v1/gonum/mat)](https://pkg.go.dev/gonum.org/v1/gonum/mat) -[![GoDoc](https://godocs.io/gonum.org/v1/gonum/mat?status.svg)](https://godocs.io/gonum.org/v1/gonum/mat) - -Package mat is a matrix package for the Go language. diff --git a/vendor/gonum.org/v1/gonum/mat/band.go b/vendor/gonum.org/v1/gonum/mat/band.go deleted file mode 100644 index 7660cdaa..00000000 --- a/vendor/gonum.org/v1/gonum/mat/band.go +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright ©2017 The Gonum 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 mat - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -var ( - bandDense *BandDense - _ Matrix = bandDense - _ allMatrix = bandDense - _ denseMatrix = bandDense - _ Banded = bandDense - _ RawBander = bandDense - - _ NonZeroDoer = bandDense - _ RowNonZeroDoer = bandDense - _ ColNonZeroDoer = bandDense -) - -// BandDense represents a band matrix in dense storage format. -type BandDense struct { - mat blas64.Band -} - -// Banded is a band matrix representation. -type Banded interface { - Matrix - // Bandwidth returns the lower and upper bandwidth values for - // the matrix. The total bandwidth of the matrix is kl+ku+1. - Bandwidth() (kl, ku int) - - // TBand is the equivalent of the T() method in the Matrix - // interface but guarantees the transpose is of banded type. - TBand() Banded -} - -// A RawBander can return a blas64.Band representation of the receiver. -// Changes to the blas64.Band.Data slice will be reflected in the original -// matrix, changes to the Rows, Cols, KL, KU and Stride fields will not. -type RawBander interface { - RawBand() blas64.Band -} - -// A MutableBanded can set elements of a band matrix. -type MutableBanded interface { - Banded - - // SetBand sets the element at row i, column j to the value v. - // It panics if the location is outside the appropriate region of the matrix. - SetBand(i, j int, v float64) -} - -var ( - _ Matrix = TransposeBand{} - _ Banded = TransposeBand{} - _ UntransposeBander = TransposeBand{} -) - -// TransposeBand is a type for performing an implicit transpose of a band -// matrix. It implements the Banded interface, returning values from the -// transpose of the matrix within. -type TransposeBand struct { - Banded Banded -} - -// At returns the value of the element at row i and column j of the transposed -// matrix, that is, row j and column i of the Banded field. -func (t TransposeBand) At(i, j int) float64 { - return t.Banded.At(j, i) -} - -// Dims returns the dimensions of the transposed matrix. -func (t TransposeBand) Dims() (r, c int) { - c, r = t.Banded.Dims() - return r, c -} - -// T performs an implicit transpose by returning the Banded field. -func (t TransposeBand) T() Matrix { - return t.Banded -} - -// Bandwidth returns the lower and upper bandwidth values for -// the transposed matrix. -func (t TransposeBand) Bandwidth() (kl, ku int) { - kl, ku = t.Banded.Bandwidth() - return ku, kl -} - -// TBand performs an implicit transpose by returning the Banded field. -func (t TransposeBand) TBand() Banded { - return t.Banded -} - -// Untranspose returns the Banded field. -func (t TransposeBand) Untranspose() Matrix { - return t.Banded -} - -// UntransposeBand returns the Banded field. -func (t TransposeBand) UntransposeBand() Banded { - return t.Banded -} - -// NewBandDense creates a new Band matrix with r rows and c columns. If data == nil, -// a new slice is allocated for the backing slice. If len(data) == min(r, c+kl)*(kl+ku+1), -// data is used as the backing slice, and changes to the elements of the returned -// BandDense will be reflected in data. If neither of these is true, NewBandDense -// will panic. kl must be at least zero and less r, and ku must be at least zero and -// less than c, otherwise NewBandDense will panic. -// NewBandDense will panic if either r or c is zero. -// -// The data must be arranged in row-major order constructed by removing the zeros -// from the rows outside the band and aligning the diagonals. For example, the matrix -// -// 1 2 3 0 0 0 -// 4 5 6 7 0 0 -// 0 8 9 10 11 0 -// 0 0 12 13 14 15 -// 0 0 0 16 17 18 -// 0 0 0 0 19 20 -// -// becomes (* entries are never accessed) -// - 1 2 3 -// 4 5 6 7 -// 8 9 10 11 -// 12 13 14 15 -// 16 17 18 * -// 19 20 * * -// -// which is passed to NewBandDense as []float64{*, 1, 2, 3, 4, ...} with kl=1 and ku=2. -// Only the values in the band portion of the matrix are used. -func NewBandDense(r, c, kl, ku int, data []float64) *BandDense { - if r <= 0 || c <= 0 || kl < 0 || ku < 0 { - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if kl+1 > r || ku+1 > c { - panic(ErrBandwidth) - } - bc := kl + ku + 1 - if data != nil && len(data) != min(r, c+kl)*bc { - panic(ErrShape) - } - if data == nil { - data = make([]float64, min(r, c+kl)*bc) - } - return &BandDense{ - mat: blas64.Band{ - Rows: r, - Cols: c, - KL: kl, - KU: ku, - Stride: bc, - Data: data, - }, - } -} - -// NewDiagonalRect is a convenience function that returns a diagonal matrix represented by a -// BandDense. The length of data must be min(r, c) otherwise NewDiagonalRect will panic. -func NewDiagonalRect(r, c int, data []float64) *BandDense { - return NewBandDense(r, c, 0, 0, data) -} - -// Dims returns the number of rows and columns in the matrix. -func (b *BandDense) Dims() (r, c int) { - return b.mat.Rows, b.mat.Cols -} - -// Bandwidth returns the upper and lower bandwidths of the matrix. -func (b *BandDense) Bandwidth() (kl, ku int) { - return b.mat.KL, b.mat.KU -} - -// T performs an implicit transpose by returning the receiver inside a Transpose. -func (b *BandDense) T() Matrix { - return Transpose{b} -} - -// TBand performs an implicit transpose by returning the receiver inside a TransposeBand. -func (b *BandDense) TBand() Banded { - return TransposeBand{b} -} - -// RawBand returns the underlying blas64.Band used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in returned blas64.Band. -func (b *BandDense) RawBand() blas64.Band { - return b.mat -} - -// SetRawBand sets the underlying blas64.Band used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in the input. -func (b *BandDense) SetRawBand(mat blas64.Band) { - b.mat = mat -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be zeroed using Reset. -func (b *BandDense) IsEmpty() bool { - return b.mat.Stride == 0 -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (b *BandDense) Reset() { - b.mat.Rows = 0 - b.mat.Cols = 0 - b.mat.KL = 0 - b.mat.KU = 0 - b.mat.Stride = 0 - b.mat.Data = b.mat.Data[:0] -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (b *BandDense) DiagView() Diagonal { - n := min(b.mat.Rows, b.mat.Cols) - return &DiagDense{ - mat: blas64.Vector{ - N: n, - Inc: b.mat.Stride, - Data: b.mat.Data[b.mat.KL : (n-1)*b.mat.Stride+b.mat.KL+1], - }, - } -} - -// DoNonZero calls the function fn for each of the non-zero elements of b. The function fn -// takes a row/column index and the element value of b at (i, j). -func (b *BandDense) DoNonZero(fn func(i, j int, v float64)) { - for i := 0; i < min(b.mat.Rows, b.mat.Cols+b.mat.KL); i++ { - for j := max(0, i-b.mat.KL); j < min(b.mat.Cols, i+b.mat.KU+1); j++ { - v := b.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } -} - -// DoRowNonZero calls the function fn for each of the non-zero elements of row i of b. The function fn -// takes a row/column index and the element value of b at (i, j). -func (b *BandDense) DoRowNonZero(i int, fn func(i, j int, v float64)) { - if i < 0 || b.mat.Rows <= i { - panic(ErrRowAccess) - } - for j := max(0, i-b.mat.KL); j < min(b.mat.Cols, i+b.mat.KU+1); j++ { - v := b.at(i, j) - if v != 0 { - fn(i, j, v) - } - } -} - -// DoColNonZero calls the function fn for each of the non-zero elements of column j of b. The function fn -// takes a row/column index and the element value of b at (i, j). -func (b *BandDense) DoColNonZero(j int, fn func(i, j int, v float64)) { - if j < 0 || b.mat.Cols <= j { - panic(ErrColAccess) - } - for i := 0; i < min(b.mat.Rows, b.mat.Cols+b.mat.KL); i++ { - if i-b.mat.KL <= j && j < i+b.mat.KU+1 { - v := b.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } -} - -// Zero sets all of the matrix elements to zero. -func (b *BandDense) Zero() { - m := b.mat.Rows - kL := b.mat.KL - nCol := b.mat.KU + 1 + kL - for i := 0; i < m; i++ { - l := max(0, kL-i) - u := min(nCol, m+kL-i) - zero(b.mat.Data[i*b.mat.Stride+l : i*b.mat.Stride+u]) - } -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the matrix has zero size. -func (b *BandDense) Norm(norm float64) float64 { - if b.IsEmpty() { - panic(ErrZeroLength) - } - lnorm := normLapack(norm, false) - if lnorm == lapack.MaxColumnSum || lnorm == lapack.MaxRowSum { - return lapack64.Langb(lnorm, b.mat) - } - return lapack64.Langb(lnorm, b.mat) -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrSquare if the matrix is not square and with -// ErrZeroLength if the matrix has zero size. -func (b *BandDense) Trace() float64 { - r, c := b.Dims() - if r != c { - panic(ErrSquare) - } - if b.IsEmpty() { - panic(ErrZeroLength) - } - rb := b.RawBand() - var tr float64 - for i := 0; i < r; i++ { - tr += rb.Data[rb.KL+i*rb.Stride] - } - return tr -} - -// MulVecTo computes B⋅x or Bᵀ⋅x storing the result into dst. -func (b *BandDense) MulVecTo(dst *VecDense, trans bool, x Vector) { - m, n := b.Dims() - if trans { - m, n = n, m - } - if x.Len() != n { - panic(ErrShape) - } - dst.reuseAsNonZeroed(m) - - t := blas.NoTrans - if trans { - t = blas.Trans - } - - xMat, _ := untransposeExtract(x) - if xVec, ok := xMat.(*VecDense); ok { - if dst != xVec { - dst.checkOverlap(xVec.mat) - blas64.Gbmv(t, 1, b.mat, xVec.mat, 0, dst.mat) - } else { - xCopy := getVecDenseWorkspace(n, false) - xCopy.CloneFromVec(xVec) - blas64.Gbmv(t, 1, b.mat, xCopy.mat, 0, dst.mat) - putVecDenseWorkspace(xCopy) - } - } else { - xCopy := getVecDenseWorkspace(n, false) - xCopy.CloneFromVec(x) - blas64.Gbmv(t, 1, b.mat, xCopy.mat, 0, dst.mat) - putVecDenseWorkspace(xCopy) - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/cdense.go b/vendor/gonum.org/v1/gonum/mat/cdense.go deleted file mode 100644 index 86f0423c..00000000 --- a/vendor/gonum.org/v1/gonum/mat/cdense.go +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright ©2019 The Gonum 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 mat - -import ( - "math/cmplx" - - "gonum.org/v1/gonum/blas/cblas128" -) - -var ( - cDense *CDense - - _ CMatrix = cDense - _ allMatrix = cDense -) - -// CDense is a dense matrix representation with complex data. -type CDense struct { - mat cblas128.General - - capRows, capCols int -} - -// Dims returns the number of rows and columns in the matrix. -func (m *CDense) Dims() (r, c int) { - return m.mat.Rows, m.mat.Cols -} - -// Caps returns the number of rows and columns in the backing matrix. -func (m *CDense) Caps() (r, c int) { return m.capRows, m.capCols } - -// H performs an implicit conjugate transpose by returning the receiver inside a -// ConjTranspose. -func (m *CDense) H() CMatrix { - return ConjTranspose{m} -} - -// T performs an implicit transpose by returning the receiver inside a -// CTranspose. -func (m *CDense) T() CMatrix { - return CTranspose{m} -} - -// Conj calculates the element-wise conjugate of a and stores the result in the -// receiver. -// Conj will panic if m and a do not have the same dimension unless m is empty. -func (m *CDense) Conj(a CMatrix) { - ar, ac := a.Dims() - aU, aTrans, aConj := untransposeExtractCmplx(a) - m.reuseAsNonZeroed(ar, ac) - - if arm, ok := a.(*CDense); ok { - amat := arm.mat - if m != aU { - m.checkOverlap(amat) - } - for ja, jm := 0, 0; ja < ar*amat.Stride; ja, jm = ja+amat.Stride, jm+m.mat.Stride { - for i, v := range amat.Data[ja : ja+ac] { - m.mat.Data[i+jm] = cmplx.Conj(v) - } - } - return - } - - m.checkOverlapMatrix(aU) - if aTrans != aConj && m == aU { - // Only make workspace if the destination is transposed - // with respect to the source and they are the same - // matrix. - var restore func() - m, restore = m.isolatedWorkspace(aU) - defer restore() - } - - for r := 0; r < ar; r++ { - for c := 0; c < ac; c++ { - m.set(r, c, cmplx.Conj(a.At(r, c))) - } - } -} - -// Slice returns a new CMatrix that shares backing data with the receiver. -// The returned matrix starts at {i,j} of the receiver and extends k-i rows -// and l-j columns. The final row in the resulting matrix is k-1 and the -// final column is l-1. -// Slice panics with ErrIndexOutOfRange if the slice is outside the capacity -// of the receiver. -func (m *CDense) Slice(i, k, j, l int) CMatrix { - return m.slice(i, k, j, l) -} - -func (m *CDense) slice(i, k, j, l int) *CDense { - mr, mc := m.Caps() - if i < 0 || mr <= i || j < 0 || mc <= j || k < i || mr < k || l < j || mc < l { - if i == k || j == l { - panic(ErrZeroLength) - } - panic(ErrIndexOutOfRange) - } - t := *m - t.mat.Data = t.mat.Data[i*t.mat.Stride+j : (k-1)*t.mat.Stride+l] - t.mat.Rows = k - i - t.mat.Cols = l - j - t.capRows -= i - t.capCols -= j - return &t -} - -// NewCDense creates a new complex Dense matrix with r rows and c columns. -// If data == nil, a new slice is allocated for the backing slice. -// If len(data) == r*c, data is used as the backing slice, and changes to the -// elements of the returned CDense will be reflected in data. -// If neither of these is true, NewCDense will panic. -// NewCDense will panic if either r or c is zero. -// -// The data must be arranged in row-major order, i.e. the (i*c + j)-th -// element in the data slice is the {i, j}-th element in the matrix. -func NewCDense(r, c int, data []complex128) *CDense { - if r <= 0 || c <= 0 { - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - panic("mat: negative dimension") - } - if data != nil && r*c != len(data) { - panic(ErrShape) - } - if data == nil { - data = make([]complex128, r*c) - } - return &CDense{ - mat: cblas128.General{ - Rows: r, - Cols: c, - Stride: c, - Data: data, - }, - capRows: r, - capCols: c, - } -} - -// ReuseAs changes the receiver if it IsEmpty() to be of size r×c. -// -// ReuseAs re-uses the backing data slice if it has sufficient capacity, -// otherwise a new slice is allocated. The backing data is zero on return. -// -// ReuseAs panics if the receiver is not empty, and panics if -// the input sizes are less than one. To empty the receiver for re-use, -// Reset should be used. -func (m *CDense) ReuseAs(r, c int) { - if r <= 0 || c <= 0 { - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if !m.IsEmpty() { - panic(ErrReuseNonEmpty) - } - m.reuseAsZeroed(r, c) -} - -// reuseAs resizes an empty matrix to a r×c matrix, -// or checks that a non-empty matrix is r×c. -// -// reuseAs must be kept in sync with reuseAsZeroed. -func (m *CDense) reuseAsNonZeroed(r, c int) { - if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - if m.IsEmpty() { - m.mat = cblas128.General{ - Rows: r, - Cols: c, - Stride: c, - Data: useC(m.mat.Data, r*c), - } - m.capRows = r - m.capCols = c - return - } - if r != m.mat.Rows || c != m.mat.Cols { - panic(ErrShape) - } -} - -func (m *CDense) reuseAsZeroed(r, c int) { - // This must be kept in-sync with reuseAs. - if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - if m.IsEmpty() { - m.mat = cblas128.General{ - Rows: r, - Cols: c, - Stride: c, - Data: useZeroedC(m.mat.Data, r*c), - } - m.capRows = r - m.capCols = c - return - } - if r != m.mat.Rows || c != m.mat.Cols { - panic(ErrShape) - } - m.Zero() -} - -// isolatedWorkspace returns a new dense matrix w with the size of a and -// returns a callback to defer which performs cleanup at the return of the call. -// This should be used when a method receiver is the same pointer as an input argument. -func (m *CDense) isolatedWorkspace(a CMatrix) (w *CDense, restore func()) { - r, c := a.Dims() - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - w = getCDenseWorkspace(r, c, false) - return w, func() { - m.Copy(w) - putCDenseWorkspace(w) - } -} - -// Reset zeros the dimensions of the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (m *CDense) Reset() { - // Row, Cols and Stride must be zeroed in unison. - m.mat.Rows, m.mat.Cols, m.mat.Stride = 0, 0, 0 - m.capRows, m.capCols = 0, 0 - m.mat.Data = m.mat.Data[:0] -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be zeroed using Reset. -func (m *CDense) IsEmpty() bool { - // It must be the case that m.Dims() returns - // zeros in this case. See comment in Reset(). - return m.mat.Stride == 0 -} - -// Zero sets all of the matrix elements to zero. -func (m *CDense) Zero() { - r := m.mat.Rows - c := m.mat.Cols - for i := 0; i < r; i++ { - zeroC(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) - } -} - -// Copy makes a copy of elements of a into the receiver. It is similar to the -// built-in copy; it copies as much as the overlap between the two matrices and -// returns the number of rows and columns it copied. If a aliases the receiver -// and is a transposed Dense or VecDense, with a non-unitary increment, Copy will -// panic. -// -// See the Copier interface for more information. -func (m *CDense) Copy(a CMatrix) (r, c int) { - r, c = a.Dims() - if a == m { - return r, c - } - r = min(r, m.mat.Rows) - c = min(c, m.mat.Cols) - if r == 0 || c == 0 { - return 0, 0 - } - // TODO(btracey): Check for overlap when complex version exists. - // TODO(btracey): Add fast-paths. - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - m.set(i, j, a.At(i, j)) - } - } - return r, c -} - -// SetRawCMatrix sets the underlying cblas128.General used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in b. -func (m *CDense) SetRawCMatrix(b cblas128.General) { - m.capRows, m.capCols = b.Rows, b.Cols - m.mat = b -} - -// RawCMatrix returns the underlying cblas128.General used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in returned cblas128.General. -func (m *CDense) RawCMatrix() cblas128.General { return m.mat } - -// Grow returns the receiver expanded by r rows and c columns. If the dimensions -// of the expanded matrix are outside the capacities of the receiver a new -// allocation is made, otherwise not. Note the receiver itself is not modified -// during the call to Grow. -func (m *CDense) Grow(r, c int) CMatrix { - if r < 0 || c < 0 { - panic(ErrIndexOutOfRange) - } - if r == 0 && c == 0 { - return m - } - - r += m.mat.Rows - c += m.mat.Cols - - var t CDense - switch { - case m.mat.Rows == 0 || m.mat.Cols == 0: - t.mat = cblas128.General{ - Rows: r, - Cols: c, - Stride: c, - // We zero because we don't know how the matrix will be used. - // In other places, the mat is immediately filled with a result; - // this is not the case here. - Data: useZeroedC(m.mat.Data, r*c), - } - case r > m.capRows || c > m.capCols: - cr := max(r, m.capRows) - cc := max(c, m.capCols) - t.mat = cblas128.General{ - Rows: r, - Cols: c, - Stride: cc, - Data: make([]complex128, cr*cc), - } - t.capRows = cr - t.capCols = cc - // Copy the complete matrix over to the new matrix. - // Including elements not currently visible. Use a temporary structure - // to avoid modifying the receiver. - var tmp CDense - tmp.mat = cblas128.General{ - Rows: m.mat.Rows, - Cols: m.mat.Cols, - Stride: m.mat.Stride, - Data: m.mat.Data, - } - tmp.capRows = m.capRows - tmp.capCols = m.capCols - t.Copy(&tmp) - return &t - default: - t.mat = cblas128.General{ - Data: m.mat.Data[:(r-1)*m.mat.Stride+c], - Rows: r, - Cols: c, - Stride: m.mat.Stride, - } - } - t.capRows = r - t.capCols = c - return &t -} diff --git a/vendor/gonum.org/v1/gonum/mat/cholesky.go b/vendor/gonum.org/v1/gonum/mat/cholesky.go deleted file mode 100644 index f11948d0..00000000 --- a/vendor/gonum.org/v1/gonum/mat/cholesky.go +++ /dev/null @@ -1,1203 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack/lapack64" -) - -const ( - badTriangle = "mat: invalid triangle" - badCholesky = "mat: invalid Cholesky factorization" -) - -var ( - _ Matrix = (*Cholesky)(nil) - _ Symmetric = (*Cholesky)(nil) - - _ Matrix = (*BandCholesky)(nil) - _ Symmetric = (*BandCholesky)(nil) - _ Banded = (*BandCholesky)(nil) - _ SymBanded = (*BandCholesky)(nil) - - _ Matrix = (*PivotedCholesky)(nil) - _ Symmetric = (*PivotedCholesky)(nil) -) - -// Cholesky is a symmetric positive definite matrix represented by its -// Cholesky decomposition. -// -// The decomposition can be constructed using the Factorize method. The -// factorization itself can be extracted using the UTo or LTo methods, and the -// original symmetric matrix can be recovered with ToSym. -// -// Note that this matrix representation is useful for certain operations, in -// particular finding solutions to linear equations. It is very inefficient -// at other operations, in particular At is slow. -// -// Cholesky methods may only be called on a value that has been successfully -// initialized by a call to Factorize that has returned true. Calls to methods -// of an unsuccessful Cholesky factorization will panic. -type Cholesky struct { - // The chol pointer must never be retained as a pointer outside the Cholesky - // struct, either by returning chol outside the struct or by setting it to - // a pointer coming from outside. The same prohibition applies to the data - // slice within chol. - chol *TriDense - cond float64 -} - -// updateCond updates the condition number of the Cholesky decomposition. If -// norm > 0, then that norm is used as the norm of the original matrix A, otherwise -// the norm is estimated from the decomposition. -func (c *Cholesky) updateCond(norm float64) { - n := c.chol.mat.N - work := getFloat64s(3*n, false) - defer putFloat64s(work) - if norm < 0 { - // This is an approximation. By the definition of a norm, - // |AB| <= |A| |B|. - // Since A = Uᵀ*U, we get for the condition number κ that - // κ(A) := |A| |A^-1| = |Uᵀ*U| |A^-1| <= |Uᵀ| |U| |A^-1|, - // so this will overestimate the condition number somewhat. - // The norm of the original factorized matrix cannot be stored - // because of update possibilities. - unorm := lapack64.Lantr(CondNorm, c.chol.mat, work) - lnorm := lapack64.Lantr(CondNormTrans, c.chol.mat, work) - norm = unorm * lnorm - } - sym := c.chol.asSymBlas() - iwork := getInts(n, false) - v := lapack64.Pocon(sym, norm, work, iwork) - putInts(iwork) - c.cond = 1 / v -} - -// Dims returns the dimensions of the matrix. -func (ch *Cholesky) Dims() (r, c int) { - n := ch.SymmetricDim() - return n, n -} - -// At returns the element at row i, column j. -func (c *Cholesky) At(i, j int) float64 { - n := c.SymmetricDim() - if uint(i) >= uint(n) { - panic(ErrRowAccess) - } - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - - var val float64 - for k := 0; k <= min(i, j); k++ { - val += c.chol.at(k, i) * c.chol.at(k, j) - } - return val -} - -// T returns the receiver, the transpose of a symmetric matrix. -func (c *Cholesky) T() Matrix { - return c -} - -// SymmetricDim implements the Symmetric interface and returns the number of rows -// in the matrix (this is also the number of columns). -func (c *Cholesky) SymmetricDim() int { - if c.chol == nil { - return 0 - } - n, _ := c.chol.Triangle() - return n -} - -// Cond returns the condition number of the factorized matrix. -func (c *Cholesky) Cond() float64 { - if !c.valid() { - panic(badCholesky) - } - return c.cond -} - -// Factorize calculates the Cholesky decomposition of the matrix A and returns -// whether the matrix is positive definite. If Factorize returns false, the -// factorization must not be used. -func (c *Cholesky) Factorize(a Symmetric) (ok bool) { - n := a.SymmetricDim() - if c.chol == nil { - c.chol = NewTriDense(n, Upper, nil) - } else { - c.chol.Reset() - c.chol.reuseAsNonZeroed(n, Upper) - } - copySymIntoTriangle(c.chol, a) - - sym := c.chol.asSymBlas() - work := getFloat64s(c.chol.mat.N, false) - norm := lapack64.Lansy(CondNorm, sym, work) - putFloat64s(work) - _, ok = lapack64.Potrf(sym) - if ok { - c.updateCond(norm) - } else { - c.Reset() - } - return ok -} - -// Reset resets the factorization so that it can be reused as the receiver of a -// dimensionally restricted operation. -func (c *Cholesky) Reset() { - if c.chol != nil { - c.chol.Reset() - } - c.cond = math.Inf(1) -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (c *Cholesky) IsEmpty() bool { - return c.chol == nil || c.chol.IsEmpty() -} - -// SetFromU sets the Cholesky decomposition from the given triangular matrix. -// SetFromU panics if t is not upper triangular. If the receiver is empty it -// is resized to be n×n, the size of t. If dst is non-empty, SetFromU panics -// if c is not of size n×n. Note that t is copied into, not stored inside, the -// receiver. -func (c *Cholesky) SetFromU(t Triangular) { - n, kind := t.Triangle() - if kind != Upper { - panic("cholesky: matrix must be upper triangular") - } - if c.chol == nil { - c.chol = NewTriDense(n, Upper, nil) - } else { - c.chol.reuseAsNonZeroed(n, Upper) - } - c.chol.Copy(t) - c.updateCond(-1) -} - -// Clone makes a copy of the input Cholesky into the receiver, overwriting the -// previous value of the receiver. Clone does not place any restrictions on receiver -// shape. Clone panics if the input Cholesky is not the result of a valid decomposition. -func (c *Cholesky) Clone(chol *Cholesky) { - if !chol.valid() { - panic(badCholesky) - } - n := chol.SymmetricDim() - if c.chol == nil { - c.chol = NewTriDense(n, Upper, nil) - } else { - c.chol = NewTriDense(n, Upper, use(c.chol.mat.Data, n*n)) - } - c.chol.Copy(chol.chol) - c.cond = chol.cond -} - -// Det returns the determinant of the matrix that has been factorized. -func (c *Cholesky) Det() float64 { - if !c.valid() { - panic(badCholesky) - } - return math.Exp(c.LogDet()) -} - -// LogDet returns the log of the determinant of the matrix that has been factorized. -func (c *Cholesky) LogDet() float64 { - if !c.valid() { - panic(badCholesky) - } - var det float64 - for i := 0; i < c.chol.mat.N; i++ { - det += 2 * math.Log(c.chol.mat.Data[i*c.chol.mat.Stride+i]) - } - return det -} - -// SolveTo finds the matrix X that solves A * X = B where A is represented -// by the Cholesky decomposition. The result is stored in-place into dst. -// If the Cholesky decomposition is singular or near-singular a Condition error -// is returned. See the documentation for Condition for more information. -func (c *Cholesky) SolveTo(dst *Dense, b Matrix) error { - if !c.valid() { - panic(badCholesky) - } - n := c.chol.mat.N - bm, bn := b.Dims() - if n != bm { - panic(ErrShape) - } - - dst.reuseAsNonZeroed(bm, bn) - if b != dst { - dst.Copy(b) - } - lapack64.Potrs(c.chol.mat, dst.mat) - if c.cond > ConditionTolerance { - return Condition(c.cond) - } - return nil -} - -// SolveCholTo finds the matrix X that solves A * X = B where A and B are represented -// by their Cholesky decompositions a and b. The result is stored in-place into -// dst. -// If the Cholesky decomposition is singular or near-singular a Condition error -// is returned. See the documentation for Condition for more information. -func (a *Cholesky) SolveCholTo(dst *Dense, b *Cholesky) error { - if !a.valid() || !b.valid() { - panic(badCholesky) - } - bn := b.chol.mat.N - if a.chol.mat.N != bn { - panic(ErrShape) - } - - dst.reuseAsZeroed(bn, bn) - dst.Copy(b.chol.T()) - blas64.Trsm(blas.Left, blas.Trans, 1, a.chol.mat, dst.mat) - blas64.Trsm(blas.Left, blas.NoTrans, 1, a.chol.mat, dst.mat) - blas64.Trmm(blas.Right, blas.NoTrans, 1, b.chol.mat, dst.mat) - if a.cond > ConditionTolerance { - return Condition(a.cond) - } - return nil -} - -// SolveVecTo finds the vector x that solves A * x = b where A is represented -// by the Cholesky decomposition. The result is stored in-place into -// dst. -// If the Cholesky decomposition is singular or near-singular a Condition error -// is returned. See the documentation for Condition for more information. -func (c *Cholesky) SolveVecTo(dst *VecDense, b Vector) error { - if !c.valid() { - panic(badCholesky) - } - n := c.chol.mat.N - if br, bc := b.Dims(); br != n || bc != 1 { - panic(ErrShape) - } - switch rv := b.(type) { - default: - dst.reuseAsNonZeroed(n) - return c.SolveTo(dst.asDense(), b) - case RawVectorer: - bmat := rv.RawVector() - if dst != b { - dst.checkOverlap(bmat) - } - dst.reuseAsNonZeroed(n) - if dst != b { - dst.CopyVec(b) - } - lapack64.Potrs(c.chol.mat, dst.asGeneral()) - if c.cond > ConditionTolerance { - return Condition(c.cond) - } - return nil - } -} - -// RawU returns the Triangular matrix used to store the Cholesky factorization -// of the original matrix A. If the returned matrix is modified, the -// factorization is invalid and should not be used. -// -// If Factorize has not been called, RawU will return nil. -func (c *Cholesky) RawU() Triangular { - if !c.valid() { - return nil - } - return c.chol -} - -// UTo stores into dst the n×n upper triangular matrix U from a Cholesky -// decomposition -// -// A = Uᵀ * U. -// -// If dst is empty, it is resized to be an n×n upper triangular matrix. When dst -// is non-empty, UTo panics if dst is not n×n or not Upper. UTo will also panic -// if the receiver does not contain a successful factorization. -func (c *Cholesky) UTo(dst *TriDense) { - if !c.valid() { - panic(badCholesky) - } - n := c.chol.mat.N - if dst.IsEmpty() { - dst.ReuseAsTri(n, Upper) - } else { - n2, kind := dst.Triangle() - if n != n2 { - panic(ErrShape) - } - if kind != Upper { - panic(ErrTriangle) - } - } - dst.Copy(c.chol) -} - -// LTo stores into dst the n×n lower triangular matrix L from a Cholesky -// decomposition -// -// A = L * Lᵀ. -// -// If dst is empty, it is resized to be an n×n lower triangular matrix. When dst -// is non-empty, LTo panics if dst is not n×n or not Lower. LTo will also panic -// if the receiver does not contain a successful factorization. -func (c *Cholesky) LTo(dst *TriDense) { - if !c.valid() { - panic(badCholesky) - } - n := c.chol.mat.N - if dst.IsEmpty() { - dst.ReuseAsTri(n, Lower) - } else { - n2, kind := dst.Triangle() - if n != n2 { - panic(ErrShape) - } - if kind != Lower { - panic(ErrTriangle) - } - } - dst.Copy(c.chol.TTri()) -} - -// ToSym reconstructs the original positive definite matrix from its -// Cholesky decomposition, storing the result into dst. If dst is -// empty it is resized to be n×n. If dst is non-empty, ToSym panics -// if dst is not of size n×n. ToSym will also panic if the receiver -// does not contain a successful factorization. -func (c *Cholesky) ToSym(dst *SymDense) { - if !c.valid() { - panic(badCholesky) - } - n := c.chol.mat.N - if dst.IsEmpty() { - dst.ReuseAsSym(n) - } else { - n2 := dst.SymmetricDim() - if n != n2 { - panic(ErrShape) - } - } - // Create a TriDense representing the Cholesky factor U with dst's - // backing slice. - // Operations on u are reflected in s. - u := &TriDense{ - mat: blas64.Triangular{ - Uplo: blas.Upper, - Diag: blas.NonUnit, - N: n, - Data: dst.mat.Data, - Stride: dst.mat.Stride, - }, - cap: n, - } - u.Copy(c.chol) - // Compute the product Uᵀ*U using the algorithm from LAPACK/TESTING/LIN/dpot01.f - a := u.mat.Data - lda := u.mat.Stride - bi := blas64.Implementation() - for k := n - 1; k >= 0; k-- { - a[k*lda+k] = bi.Ddot(k+1, a[k:], lda, a[k:], lda) - if k > 0 { - bi.Dtrmv(blas.Upper, blas.Trans, blas.NonUnit, k, a, lda, a[k:], lda) - } - } -} - -// InverseTo computes the inverse of the matrix represented by its Cholesky -// factorization and stores the result into s. If the factorized -// matrix is ill-conditioned, a Condition error will be returned. -// Note that matrix inversion is numerically unstable, and should generally be -// avoided where possible, for example by using the Solve routines. -func (c *Cholesky) InverseTo(dst *SymDense) error { - if !c.valid() { - panic(badCholesky) - } - dst.reuseAsNonZeroed(c.chol.mat.N) - // Create a TriDense representing the Cholesky factor U with the backing - // slice from dst. - // Operations on u are reflected in dst. - u := &TriDense{ - mat: blas64.Triangular{ - Uplo: blas.Upper, - Diag: blas.NonUnit, - N: dst.mat.N, - Data: dst.mat.Data, - Stride: dst.mat.Stride, - }, - cap: dst.mat.N, - } - u.Copy(c.chol) - - _, ok := lapack64.Potri(u.mat) - if !ok { - return Condition(math.Inf(1)) - } - if c.cond > ConditionTolerance { - return Condition(c.cond) - } - return nil -} - -// Scale multiplies the original matrix A by a positive constant using -// its Cholesky decomposition, storing the result in-place into the receiver. -// That is, if the original Cholesky factorization is -// -// Uᵀ * U = A -// -// the updated factorization is -// -// U'ᵀ * U' = f A = A' -// -// Scale panics if the constant is non-positive, or if the receiver is non-empty -// and is of a different size from the input. -func (c *Cholesky) Scale(f float64, orig *Cholesky) { - if !orig.valid() { - panic(badCholesky) - } - if f <= 0 { - panic("cholesky: scaling by a non-positive constant") - } - n := orig.SymmetricDim() - if c.chol == nil { - c.chol = NewTriDense(n, Upper, nil) - } else if c.chol.mat.N != n { - panic(ErrShape) - } - c.chol.ScaleTri(math.Sqrt(f), orig.chol) - c.cond = orig.cond // Scaling by a positive constant does not change the condition number. -} - -// ExtendVecSym computes the Cholesky decomposition of the original matrix A, -// whose Cholesky decomposition is in a, extended by a the n×1 vector v according to -// -// [A w] -// [w' k] -// -// where k = v[n-1] and w = v[:n-1]. The result is stored into the receiver. -// In order for the updated matrix to be positive definite, it must be the case -// that k > w' A^-1 w. If this condition does not hold then ExtendVecSym will -// return false and the receiver will not be updated. -// -// ExtendVecSym will panic if v.Len() != a.SymmetricDim()+1 or if a does not contain -// a valid decomposition. -func (c *Cholesky) ExtendVecSym(a *Cholesky, v Vector) (ok bool) { - n := a.SymmetricDim() - - if v.Len() != n+1 { - panic(badSliceLength) - } - if !a.valid() { - panic(badCholesky) - } - - // The algorithm is commented here, but see also - // https://math.stackexchange.com/questions/955874/cholesky-factor-when-adding-a-row-and-column-to-already-factorized-matrix - // We have A and want to compute the Cholesky of - // [A w] - // [w' k] - // We want - // [U c] - // [0 d] - // to be the updated Cholesky, and so it must be that - // [A w] = [U' 0] [U c] - // [w' k] [c' d] [0 d] - // Thus, we need - // 1) A = U'U (true by the original decomposition being valid), - // 2) U' * c = w => c = U'^-1 w - // 3) c'*c + d'*d = k => d = sqrt(k-c'*c) - - // First, compute c = U'^-1 a - w := NewVecDense(n, nil) - w.CopyVec(v) - k := v.At(n, 0) - - var t VecDense - _ = t.SolveVec(a.chol.T(), w) - - dot := Dot(&t, &t) - if dot >= k { - return false - } - d := math.Sqrt(k - dot) - - newU := NewTriDense(n+1, Upper, nil) - newU.Copy(a.chol) - for i := 0; i < n; i++ { - newU.SetTri(i, n, t.At(i, 0)) - } - newU.SetTri(n, n, d) - c.chol = newU - c.updateCond(-1) - return true -} - -// SymRankOne performs a rank-1 update of the original matrix A and refactorizes -// its Cholesky factorization, storing the result into the receiver. That is, if -// in the original Cholesky factorization -// -// Uᵀ * U = A, -// -// in the updated factorization -// -// U'ᵀ * U' = A + alpha * x * xᵀ = A'. -// -// Note that when alpha is negative, the updating problem may be ill-conditioned -// and the results may be inaccurate, or the updated matrix A' may not be -// positive definite and not have a Cholesky factorization. SymRankOne returns -// whether the updated matrix A' is positive definite. If the update fails -// the receiver is left unchanged. -// -// SymRankOne updates a Cholesky factorization in O(n²) time. The Cholesky -// factorization computation from scratch is O(n³). -func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) { - if !orig.valid() { - panic(badCholesky) - } - n := orig.SymmetricDim() - if r, c := x.Dims(); r != n || c != 1 { - panic(ErrShape) - } - if orig != c { - if c.chol == nil { - c.chol = NewTriDense(n, Upper, nil) - } else if c.chol.mat.N != n { - panic(ErrShape) - } - c.chol.Copy(orig.chol) - } - - if alpha == 0 { - return true - } - - // Algorithms for updating and downdating the Cholesky factorization are - // described, for example, in - // - J. J. Dongarra, J. R. Bunch, C. B. Moler, G. W. Stewart: LINPACK - // Users' Guide. SIAM (1979), pages 10.10--10.14 - // or - // - P. E. Gill, G. H. Golub, W. Murray, and M. A. Saunders: Methods for - // modifying matrix factorizations. Mathematics of Computation 28(126) - // (1974), Method C3 on page 521 - // - // The implementation is based on LINPACK code - // http://www.netlib.org/linpack/dchud.f - // http://www.netlib.org/linpack/dchdd.f - // and - // https://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=2&t=2646 - // - // According to http://icl.cs.utk.edu/lapack-forum/archives/lapack/msg00301.html - // LINPACK is released under BSD license. - // - // See also: - // - M. A. Saunders: Large-scale Linear Programming Using the Cholesky - // Factorization. Technical Report Stanford University (1972) - // http://i.stanford.edu/pub/cstr/reports/cs/tr/72/252/CS-TR-72-252.pdf - // - Matthias Seeger: Low rank updates for the Cholesky decomposition. - // EPFL Technical Report 161468 (2004) - // http://infoscience.epfl.ch/record/161468 - - work := getFloat64s(n, false) - defer putFloat64s(work) - var xmat blas64.Vector - if rv, ok := x.(RawVectorer); ok { - xmat = rv.RawVector() - } else { - var tmp *VecDense - tmp.CopyVec(x) - xmat = tmp.RawVector() - } - blas64.Copy(xmat, blas64.Vector{N: n, Data: work, Inc: 1}) - - if alpha > 0 { - // Compute rank-1 update. - if alpha != 1 { - blas64.Scal(math.Sqrt(alpha), blas64.Vector{N: n, Data: work, Inc: 1}) - } - umat := c.chol.mat - stride := umat.Stride - for i := 0; i < n; i++ { - // Compute parameters of the Givens matrix that zeroes - // the i-th element of x. - c, s, r, _ := blas64.Rotg(umat.Data[i*stride+i], work[i]) - if r < 0 { - // Multiply by -1 to have positive diagonal - // elements. - r *= -1 - c *= -1 - s *= -1 - } - umat.Data[i*stride+i] = r - if i < n-1 { - // Multiply the extended factorization matrix by - // the Givens matrix from the left. Only - // the i-th row and x are modified. - blas64.Rot( - blas64.Vector{N: n - i - 1, Data: umat.Data[i*stride+i+1 : i*stride+n], Inc: 1}, - blas64.Vector{N: n - i - 1, Data: work[i+1 : n], Inc: 1}, - c, s) - } - } - c.updateCond(-1) - return true - } - - // Compute rank-1 downdate. - alpha = math.Sqrt(-alpha) - if alpha != 1 { - blas64.Scal(alpha, blas64.Vector{N: n, Data: work, Inc: 1}) - } - // Solve Uᵀ * p = x storing the result into work. - ok = lapack64.Trtrs(blas.Trans, c.chol.RawTriangular(), blas64.General{ - Rows: n, - Cols: 1, - Stride: 1, - Data: work, - }) - if !ok { - // The original matrix is singular. Should not happen, because - // the factorization is valid. - panic(badCholesky) - } - norm := blas64.Nrm2(blas64.Vector{N: n, Data: work, Inc: 1}) - if norm >= 1 { - // The updated matrix is not positive definite. - return false - } - norm = math.Sqrt((1 + norm) * (1 - norm)) - cos := getFloat64s(n, false) - defer putFloat64s(cos) - sin := getFloat64s(n, false) - defer putFloat64s(sin) - for i := n - 1; i >= 0; i-- { - // Compute parameters of Givens matrices that zero elements of p - // backwards. - cos[i], sin[i], norm, _ = blas64.Rotg(norm, work[i]) - if norm < 0 { - norm *= -1 - cos[i] *= -1 - sin[i] *= -1 - } - } - workMat := getTriDenseWorkspace(c.chol.mat.N, c.chol.triKind(), false) - defer putTriWorkspace(workMat) - workMat.Copy(c.chol) - umat := workMat.mat - stride := workMat.mat.Stride - for i := n - 1; i >= 0; i-- { - work[i] = 0 - // Apply Givens matrices to U. - blas64.Rot( - blas64.Vector{N: n - i, Data: work[i:n], Inc: 1}, - blas64.Vector{N: n - i, Data: umat.Data[i*stride+i : i*stride+n], Inc: 1}, - cos[i], sin[i]) - if umat.Data[i*stride+i] == 0 { - // The matrix is singular (may rarely happen due to - // floating-point effects?). - ok = false - } else if umat.Data[i*stride+i] < 0 { - // Diagonal elements should be positive. If it happens - // that on the i-th row the diagonal is negative, - // multiply U from the left by an identity matrix that - // has -1 on the i-th row. - blas64.Scal(-1, blas64.Vector{N: n - i, Data: umat.Data[i*stride+i : i*stride+n], Inc: 1}) - } - } - if ok { - c.chol.Copy(workMat) - c.updateCond(-1) - } - return ok -} - -func (c *Cholesky) valid() bool { - return c.chol != nil && !c.chol.IsEmpty() -} - -// BandCholesky is a symmetric positive-definite band matrix represented by its -// Cholesky decomposition. -// -// Note that this matrix representation is useful for certain operations, in -// particular finding solutions to linear equations. It is very inefficient at -// other operations, in particular At is slow. -// -// BandCholesky methods may only be called on a value that has been successfully -// initialized by a call to Factorize that has returned true. Calls to methods -// of an unsuccessful Cholesky factorization will panic. -type BandCholesky struct { - // The chol pointer must never be retained as a pointer outside the Cholesky - // struct, either by returning chol outside the struct or by setting it to - // a pointer coming from outside. The same prohibition applies to the data - // slice within chol. - chol *TriBandDense - cond float64 -} - -// Factorize calculates the Cholesky decomposition of the matrix A and returns -// whether the matrix is positive definite. If Factorize returns false, the -// factorization must not be used. -func (ch *BandCholesky) Factorize(a SymBanded) (ok bool) { - n, k := a.SymBand() - if ch.chol == nil { - ch.chol = NewTriBandDense(n, k, Upper, nil) - } else { - ch.chol.Reset() - ch.chol.ReuseAsTriBand(n, k, Upper) - } - copySymBandIntoTriBand(ch.chol, a) - cSym := blas64.SymmetricBand{ - Uplo: blas.Upper, - N: n, - K: k, - Data: ch.chol.RawTriBand().Data, - Stride: ch.chol.RawTriBand().Stride, - } - _, ok = lapack64.Pbtrf(cSym) - if !ok { - ch.Reset() - return false - } - work := getFloat64s(3*n, false) - iwork := getInts(n, false) - aNorm := lapack64.Lansb(CondNorm, cSym, work) - ch.cond = 1 / lapack64.Pbcon(cSym, aNorm, work, iwork) - putInts(iwork) - putFloat64s(work) - return true -} - -// SolveTo finds the matrix X that solves A * X = B where A is represented by -// the Cholesky decomposition. The result is stored in-place into dst. -// If the Cholesky decomposition is singular or near-singular a Condition error -// is returned. See the documentation for Condition for more information. -func (ch *BandCholesky) SolveTo(dst *Dense, b Matrix) error { - if !ch.valid() { - panic(badCholesky) - } - br, bc := b.Dims() - if br != ch.chol.mat.N { - panic(ErrShape) - } - dst.reuseAsNonZeroed(br, bc) - if b != dst { - dst.Copy(b) - } - lapack64.Pbtrs(ch.chol.mat, dst.mat) - if ch.cond > ConditionTolerance { - return Condition(ch.cond) - } - return nil -} - -// SolveVecTo finds the vector x that solves A * x = b where A is represented by -// the Cholesky decomposition. The result is stored in-place into dst. -// If the Cholesky decomposition is singular or near-singular a Condition error -// is returned. See the documentation for Condition for more information. -func (ch *BandCholesky) SolveVecTo(dst *VecDense, b Vector) error { - if !ch.valid() { - panic(badCholesky) - } - n := ch.chol.mat.N - if br, bc := b.Dims(); br != n || bc != 1 { - panic(ErrShape) - } - if b, ok := b.(RawVectorer); ok && dst != b { - dst.checkOverlap(b.RawVector()) - } - dst.reuseAsNonZeroed(n) - if dst != b { - dst.CopyVec(b) - } - lapack64.Pbtrs(ch.chol.mat, dst.asGeneral()) - if ch.cond > ConditionTolerance { - return Condition(ch.cond) - } - return nil -} - -// Cond returns the condition number of the factorized matrix. -func (ch *BandCholesky) Cond() float64 { - if !ch.valid() { - panic(badCholesky) - } - return ch.cond -} - -// Reset resets the factorization so that it can be reused as the receiver of -// a dimensionally restricted operation. -func (ch *BandCholesky) Reset() { - if ch.chol != nil { - ch.chol.Reset() - } - ch.cond = math.Inf(1) -} - -// Dims returns the dimensions of the matrix. -func (ch *BandCholesky) Dims() (r, c int) { - n := ch.SymmetricDim() - return n, n -} - -// At returns the element at row i, column j. -func (ch *BandCholesky) At(i, j int) float64 { - n, k := ch.SymBand() - if uint(i) >= uint(n) { - panic(ErrRowAccess) - } - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - - if i > j { - i, j = j, i - } - if j-i > k { - return 0 - } - var aij float64 - for k := max(0, j-k); k <= i; k++ { - aij += ch.chol.at(k, i) * ch.chol.at(k, j) - } - return aij -} - -// T returns the receiver, the transpose of a symmetric matrix. -func (ch *BandCholesky) T() Matrix { - return ch -} - -// TBand returns the receiver, the transpose of a symmetric band matrix. -func (ch *BandCholesky) TBand() Banded { - return ch -} - -// SymmetricDim implements the Symmetric interface and returns the number of rows -// in the matrix (this is also the number of columns). -func (ch *BandCholesky) SymmetricDim() int { - if ch.chol == nil { - return 0 - } - n, _ := ch.chol.Triangle() - return n -} - -// Bandwidth returns the lower and upper bandwidth values for the matrix. -// The total bandwidth of the matrix is kl+ku+1. -func (ch *BandCholesky) Bandwidth() (kl, ku int) { - _, k, _ := ch.chol.TriBand() - return k, k -} - -// SymBand returns the number of rows/columns in the matrix, and the size of the -// bandwidth. The total bandwidth of the matrix is 2*k+1. -func (ch *BandCholesky) SymBand() (n, k int) { - n, k, _ = ch.chol.TriBand() - return n, k -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for dimensionally restricted operations. The receiver can be emptied -// using Reset. -func (ch *BandCholesky) IsEmpty() bool { - return ch == nil || ch.chol.IsEmpty() -} - -// Det returns the determinant of the matrix that has been factorized. -func (ch *BandCholesky) Det() float64 { - if !ch.valid() { - panic(badCholesky) - } - return math.Exp(ch.LogDet()) -} - -// LogDet returns the log of the determinant of the matrix that has been factorized. -func (ch *BandCholesky) LogDet() float64 { - if !ch.valid() { - panic(badCholesky) - } - var det float64 - for i := 0; i < ch.chol.mat.N; i++ { - det += 2 * math.Log(ch.chol.mat.Data[i*ch.chol.mat.Stride]) - } - return det -} - -func (ch *BandCholesky) valid() bool { - return ch.chol != nil && !ch.chol.IsEmpty() -} - -// PivotedCholesky is a symmetric positive semi-definite matrix represented by -// its Cholesky factorization with complete pivoting. -// -// The factorization has the form -// -// Pᵀ * A * P = Uᵀ * U -// -// where U is an upper triangular matrix and P is a permutation matrix. -// -// Cholesky methods may only be called on a receiver that has been initialized -// by a call to Factorize. SolveTo and SolveVecTo methods may only called if -// Factorize has returned true. -// -// If the matrix A is certainly positive definite, then the unpivoted Cholesky -// could be more efficient, especially for smaller matrices. -type PivotedCholesky struct { - chol *TriDense // The factor U - piv, pivTrans []int // The permutation matrices P and Pᵀ - rank int // The computed rank of A - - ok bool // Indicates whether and the factorization can be used for solving linear systems - cond float64 // The condition number when ok is true -} - -// Factorize computes the Cholesky factorization of the symmetric positive -// semi-definite matrix A and returns whether the matrix is positive definite. -// If Factorize returns false, the SolveTo methods must not be used. -// -// tol is a tolerance used to determine the computed rank of A. If it is -// negative, a default value will be used. -func (c *PivotedCholesky) Factorize(a Symmetric, tol float64) (ok bool) { - n := a.SymmetricDim() - c.reset(n) - copySymIntoTriangle(c.chol, a) - - work := getFloat64s(3*c.chol.mat.N, false) - defer putFloat64s(work) - - sym := c.chol.asSymBlas() - aNorm := lapack64.Lansy(CondNorm, sym, work) - _, c.rank, c.ok = lapack64.Pstrf(sym, c.piv, tol, work) - if c.ok { - iwork := getInts(n, false) - defer putInts(iwork) - c.cond = 1 / lapack64.Pocon(sym, aNorm, work, iwork) - } else { - for i := c.rank; i < n; i++ { - zero(sym.Data[i*sym.Stride+i : i*sym.Stride+n]) - } - } - for i, p := range c.piv { - c.pivTrans[p] = i - } - - return c.ok -} - -// reset prepares the receiver for factorization of matrices of size n. -func (c *PivotedCholesky) reset(n int) { - if c.chol == nil { - c.chol = NewTriDense(n, Upper, nil) - } else { - c.chol.Reset() - c.chol.reuseAsNonZeroed(n, Upper) - } - c.piv = useInt(c.piv, n) - c.pivTrans = useInt(c.pivTrans, n) - c.rank = 0 - c.ok = false - c.cond = math.Inf(1) -} - -// Dims returns the dimensions of the matrix A. -func (ch *PivotedCholesky) Dims() (r, c int) { - n := ch.SymmetricDim() - return n, n -} - -// At returns the element of A at row i, column j. -func (c *PivotedCholesky) At(i, j int) float64 { - n := c.SymmetricDim() - if uint(i) >= uint(n) { - panic(ErrRowAccess) - } - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - - i = c.pivTrans[i] - j = c.pivTrans[j] - minij := min(min(i+1, j+1), c.rank) - var val float64 - for k := 0; k < minij; k++ { - val += c.chol.at(k, i) * c.chol.at(k, j) - } - return val -} - -// T returns the receiver, the transpose of a symmetric matrix. -func (c *PivotedCholesky) T() Matrix { - return c -} - -// SymmetricDim implements the Symmetric interface and returns the number of -// rows (or columns) in the matrix . -func (c *PivotedCholesky) SymmetricDim() int { - if c.chol == nil { - return 0 - } - n, _ := c.chol.Triangle() - return n -} - -// Rank returns the computed rank of the matrix A. -func (c *PivotedCholesky) Rank() int { - if c.chol == nil { - panic(badCholesky) - } - return c.rank -} - -// Cond returns the condition number of the factorized matrix. -func (c *PivotedCholesky) Cond() float64 { - if c.chol == nil { - panic(badCholesky) - } - return c.cond -} - -// RawU returns the Triangular matrix used to store the Cholesky factorization -// of the original matrix A. If the returned matrix is modified, the -// factorization is invalid and should not be used. -// -// If Factorized returned false, the rows of U from Rank to n will contain zeros -// and so U will be upper trapezoidal. -// -// If Factorize has not been called, RawU will return nil. -func (c *PivotedCholesky) RawU() Triangular { - if c.chol == nil { - return nil - } - return c.chol -} - -// UTo stores the n×n upper triangular matrix U from the Cholesky factorization -// -// Pᵀ * A * P = Uᵀ * U. -// -// into dst. If dst is empty, it is resized to be an n×n upper triangular -// matrix. When dst is non-empty, UTo panics if dst is not n×n or not Upper. -// -// If Factorized returned false, the rows of U from Rank to n will contain zeros -// and so U will be upper trapezoidal. -func (c *PivotedCholesky) UTo(dst *TriDense) { - if c.chol == nil { - panic(badCholesky) - } - n := c.chol.mat.N - if dst.IsEmpty() { - dst.ReuseAsTri(n, Upper) - } else { - n2, kind := dst.Triangle() - if n != n2 { - panic(ErrShape) - } - if kind != Upper { - panic(ErrTriangle) - } - } - dst.Copy(c.chol) -} - -// ColumnPivots returns the column permutation p that represents the permutation -// matrix P from the Cholesky factorization -// -// Pᵀ * A * P = Uᵀ * U -// -// such that the nonzero entries are P[p[k],k] = 1. -func (c *PivotedCholesky) ColumnPivots(dst []int) []int { - if c.chol == nil { - panic(badCholesky) - } - n := c.chol.mat.N - if dst == nil { - dst = make([]int, n) - } - if len(dst) != n { - panic(badSliceLength) - } - copy(dst, c.piv) - return dst -} - -// SolveTo finds the matrix X that solves A * X = B where A is represented by -// the Cholesky decomposition. The result is stored in-place into dst. If the -// Cholesky decomposition is singular or near-singular, a Condition error is -// returned. See the documentation for Condition for more information. -// -// If Factorize returned false, SolveTo will panic. -func (c *PivotedCholesky) SolveTo(dst *Dense, b Matrix) error { - if !c.ok { - panic(badCholesky) - } - n := c.chol.mat.N - bm, bn := b.Dims() - if n != bm { - panic(ErrShape) - } - - dst.reuseAsNonZeroed(bm, bn) - if dst != b { - dst.Copy(b) - } - - // Permute rows of B: D = Pᵀ * B. - lapack64.Lapmr(true, dst.mat, c.piv) - // Solve Uᵀ * U * Y = D. - lapack64.Potrs(c.chol.mat, dst.mat) - // Permute rows of Y to recover the solution: X = P * Y. - lapack64.Lapmr(false, dst.mat, c.piv) - - if c.cond > ConditionTolerance { - return Condition(c.cond) - } - return nil -} - -// SolveVecTo finds the vector x that solves A * x = b where A is represented by -// the Cholesky decomposition. The result is stored in-place into dst. If the -// Cholesky decomposition is singular or near-singular, a Condition error is -// returned. See the documentation for Condition for more information. -// -// If Factorize returned false, SolveVecTo will panic. -func (c *PivotedCholesky) SolveVecTo(dst *VecDense, b Vector) error { - if !c.ok { - panic(badCholesky) - } - n := c.chol.mat.N - if br, bc := b.Dims(); br != n || bc != 1 { - panic(ErrShape) - } - if b, ok := b.(RawVectorer); ok && dst != b { - dst.checkOverlap(b.RawVector()) - } - - dst.reuseAsNonZeroed(n) - if dst != b { - dst.CopyVec(b) - } - - // Permute rows of B: D = Pᵀ * B. - lapack64.Lapmr(true, dst.asGeneral(), c.piv) - // Solve Uᵀ * U * Y = D. - lapack64.Potrs(c.chol.mat, dst.asGeneral()) - // Permute rows of Y to recover the solution: X = P * Y. - lapack64.Lapmr(false, dst.asGeneral(), c.piv) - - if c.cond > ConditionTolerance { - return Condition(c.cond) - } - return nil -} diff --git a/vendor/gonum.org/v1/gonum/mat/cmatrix.go b/vendor/gonum.org/v1/gonum/mat/cmatrix.go deleted file mode 100644 index 33664575..00000000 --- a/vendor/gonum.org/v1/gonum/mat/cmatrix.go +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - "math/cmplx" - - "gonum.org/v1/gonum/blas/cblas128" - "gonum.org/v1/gonum/floats/scalar" -) - -// CMatrix is the basic matrix interface type for complex matrices. -type CMatrix interface { - // Dims returns the dimensions of a CMatrix. - Dims() (r, c int) - - // At returns the value of a matrix element at row i, column j. - // It will panic if i or j are out of bounds for the matrix. - At(i, j int) complex128 - - // H returns the conjugate transpose of the CMatrix. Whether H - // returns a copy of the underlying data is implementation dependent. - // This method may be implemented using the ConjTranspose type, which - // provides an implicit matrix conjugate transpose. - H() CMatrix - - // T returns the transpose of the CMatrix. Whether T returns a copy of the - // underlying data is implementation dependent. - // This method may be implemented using the CTranspose type, which - // provides an implicit matrix transpose. - T() CMatrix -} - -// A RawCMatrixer can return a cblas128.General representation of the receiver. Changes to the cblas128.General.Data -// slice will be reflected in the original matrix, changes to the Rows, Cols and Stride fields will not. -type RawCMatrixer interface { - RawCMatrix() cblas128.General -} - -var ( - _ CMatrix = ConjTranspose{} - _ UnConjTransposer = ConjTranspose{} -) - -// ConjTranspose is a type for performing an implicit matrix conjugate transpose. -// It implements the CMatrix interface, returning values from the conjugate -// transpose of the matrix within. -type ConjTranspose struct { - CMatrix CMatrix -} - -// At returns the value of the element at row i and column j of the conjugate -// transposed matrix, that is, row j and column i of the CMatrix field. -func (t ConjTranspose) At(i, j int) complex128 { - z := t.CMatrix.At(j, i) - return cmplx.Conj(z) -} - -// Dims returns the dimensions of the transposed matrix. The number of rows returned -// is the number of columns in the CMatrix field, and the number of columns is -// the number of rows in the CMatrix field. -func (t ConjTranspose) Dims() (r, c int) { - c, r = t.CMatrix.Dims() - return r, c -} - -// H performs an implicit conjugate transpose by returning the CMatrix field. -func (t ConjTranspose) H() CMatrix { - return t.CMatrix -} - -// T performs an implicit transpose by returning the receiver inside a -// CTranspose. -func (t ConjTranspose) T() CMatrix { - return CTranspose{t} -} - -// UnConjTranspose returns the CMatrix field. -func (t ConjTranspose) UnConjTranspose() CMatrix { - return t.CMatrix -} - -// CTranspose is a type for performing an implicit matrix conjugate transpose. -// It implements the CMatrix interface, returning values from the conjugate -// transpose of the matrix within. -type CTranspose struct { - CMatrix CMatrix -} - -// At returns the value of the element at row i and column j of the conjugate -// transposed matrix, that is, row j and column i of the CMatrix field. -func (t CTranspose) At(i, j int) complex128 { - return t.CMatrix.At(j, i) -} - -// Dims returns the dimensions of the transposed matrix. The number of rows returned -// is the number of columns in the CMatrix field, and the number of columns is -// the number of rows in the CMatrix field. -func (t CTranspose) Dims() (r, c int) { - c, r = t.CMatrix.Dims() - return r, c -} - -// H performs an implicit transpose by returning the receiver inside a -// ConjTranspose. -func (t CTranspose) H() CMatrix { - return ConjTranspose{t} -} - -// T performs an implicit conjugate transpose by returning the CMatrix field. -func (t CTranspose) T() CMatrix { - return t.CMatrix -} - -// Untranspose returns the CMatrix field. -func (t CTranspose) Untranspose() CMatrix { - return t.CMatrix -} - -// UnConjTransposer is a type that can undo an implicit conjugate transpose. -type UnConjTransposer interface { - // UnConjTranspose returns the underlying CMatrix stored for the implicit - // conjugate transpose. - UnConjTranspose() CMatrix - - // Note: This interface is needed to unify all of the Conjugate types. In - // the cmat128 methods, we need to test if the CMatrix has been implicitly - // transposed. If this is checked by testing for the specific Conjugate type - // then the behavior will be different if the user uses H() or HTri() for a - // triangular matrix. -} - -// CUntransposer is a type that can undo an implicit transpose. -type CUntransposer interface { - // Untranspose returns the underlying CMatrix stored for the implicit - // transpose. - Untranspose() CMatrix - - // Note: This interface is needed to unify all of the CTranspose types. In - // the cmat128 methods, we need to test if the CMatrix has been implicitly - // transposed. If this is checked by testing for the specific CTranspose type - // then the behavior will be different if the user uses T() or TTri() for a - // triangular matrix. -} - -// useC returns a complex128 slice with l elements, using c if it -// has the necessary capacity, otherwise creating a new slice. -func useC(c []complex128, l int) []complex128 { - if l <= cap(c) { - return c[:l] - } - return make([]complex128, l) -} - -// useZeroedC returns a complex128 slice with l elements, using c if it -// has the necessary capacity, otherwise creating a new slice. The -// elements of the returned slice are guaranteed to be zero. -func useZeroedC(c []complex128, l int) []complex128 { - if l <= cap(c) { - c = c[:l] - zeroC(c) - return c - } - return make([]complex128, l) -} - -// zeroC zeros the given slice's elements. -func zeroC(c []complex128) { - for i := range c { - c[i] = 0 - } -} - -// untransposeCmplx untransposes a matrix if applicable. If a is an CUntransposer -// or an UnConjTransposer, then untranspose returns the underlying matrix and true for -// the kind of transpose (potentially both). -// If it is not, then it returns the input matrix and false for trans and conj. -func untransposeCmplx(a CMatrix) (u CMatrix, trans, conj bool) { - switch ut := a.(type) { - case CUntransposer: - trans = true - u := ut.Untranspose() - if uc, ok := u.(UnConjTransposer); ok { - return uc.UnConjTranspose(), trans, true - } - return u, trans, false - case UnConjTransposer: - conj = true - u := ut.UnConjTranspose() - if ut, ok := u.(CUntransposer); ok { - return ut.Untranspose(), true, conj - } - return u, false, conj - default: - return a, false, false - } -} - -// untransposeExtractCmplx returns an untransposed matrix in a built-in matrix type. -// -// The untransposed matrix is returned unaltered if it is a built-in matrix type. -// Otherwise, if it implements a Raw method, an appropriate built-in type value -// is returned holding the raw matrix value of the input. If neither of these -// is possible, the untransposed matrix is returned. -func untransposeExtractCmplx(a CMatrix) (u CMatrix, trans, conj bool) { - ut, trans, conj := untransposeCmplx(a) - switch m := ut.(type) { - case *CDense: - return m, trans, conj - case RawCMatrixer: - var d CDense - d.SetRawCMatrix(m.RawCMatrix()) - return &d, trans, conj - default: - return ut, trans, conj - } -} - -// CEqual returns whether the matrices a and b have the same size -// and are element-wise equal. -func CEqual(a, b CMatrix) bool { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - return false - } - // TODO(btracey): Add in fast-paths. - for i := 0; i < ar; i++ { - for j := 0; j < ac; j++ { - if a.At(i, j) != b.At(i, j) { - return false - } - } - } - return true -} - -// CEqualApprox returns whether the matrices a and b have the same size and contain all equal -// elements with tolerance for element-wise equality specified by epsilon. Matrices -// with non-equal shapes are not equal. -func CEqualApprox(a, b CMatrix, epsilon float64) bool { - // TODO(btracey): - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - return false - } - for i := 0; i < ar; i++ { - for j := 0; j < ac; j++ { - if !cEqualWithinAbsOrRel(a.At(i, j), b.At(i, j), epsilon, epsilon) { - return false - } - } - } - return true -} - -// TODO(btracey): Move these into a cmplxs if/when we have one. - -func cEqualWithinAbsOrRel(a, b complex128, absTol, relTol float64) bool { - if cEqualWithinAbs(a, b, absTol) { - return true - } - return cEqualWithinRel(a, b, relTol) -} - -// cEqualWithinAbs returns true if a and b have an absolute -// difference of less than tol. -func cEqualWithinAbs(a, b complex128, tol float64) bool { - return a == b || cmplx.Abs(a-b) <= tol -} - -const minNormalFloat64 = 2.2250738585072014e-308 - -// cEqualWithinRel returns true if the difference between a and b -// is not greater than tol times the greater value. -func cEqualWithinRel(a, b complex128, tol float64) bool { - if a == b { - return true - } - if cmplx.IsNaN(a) || cmplx.IsNaN(b) { - return false - } - // Cannot play the same trick as in floats/scalar because there are multiple - // possible infinities. - if cmplx.IsInf(a) { - if !cmplx.IsInf(b) { - return false - } - ra := real(a) - if math.IsInf(ra, 0) { - if ra == real(b) { - return scalar.EqualWithinRel(imag(a), imag(b), tol) - } - return false - } - if imag(a) == imag(b) { - return scalar.EqualWithinRel(ra, real(b), tol) - } - return false - } - if cmplx.IsInf(b) { - return false - } - - delta := cmplx.Abs(a - b) - if delta <= minNormalFloat64 { - return delta <= tol*minNormalFloat64 - } - return delta/math.Max(cmplx.Abs(a), cmplx.Abs(b)) <= tol -} diff --git a/vendor/gonum.org/v1/gonum/mat/consts.go b/vendor/gonum.org/v1/gonum/mat/consts.go deleted file mode 100644 index 3de3f5bf..00000000 --- a/vendor/gonum.org/v1/gonum/mat/consts.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright ©2016 The Gonum 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 mat - -// TriKind represents the triangularity of the matrix. -type TriKind bool - -const ( - // Upper specifies an upper triangular matrix. - Upper TriKind = true - // Lower specifies a lower triangular matrix. - Lower TriKind = false -) diff --git a/vendor/gonum.org/v1/gonum/mat/dense.go b/vendor/gonum.org/v1/gonum/mat/dense.go deleted file mode 100644 index b08360cc..00000000 --- a/vendor/gonum.org/v1/gonum/mat/dense.go +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -var ( - dense *Dense - - _ Matrix = dense - _ allMatrix = dense - _ denseMatrix = dense - _ Mutable = dense - - _ ClonerFrom = dense - _ RowViewer = dense - _ ColViewer = dense - _ RawRowViewer = dense - _ Grower = dense - - _ RawMatrixSetter = dense - _ RawMatrixer = dense - - _ Reseter = dense -) - -// Dense is a dense matrix representation. -type Dense struct { - mat blas64.General - - capRows, capCols int -} - -// NewDense creates a new Dense matrix with r rows and c columns. If data == nil, -// a new slice is allocated for the backing slice. If len(data) == r*c, data is -// used as the backing slice, and changes to the elements of the returned Dense -// will be reflected in data. If neither of these is true, NewDense will panic. -// NewDense will panic if either r or c is zero. -// -// The data must be arranged in row-major order, i.e. the (i*c + j)-th -// element in the data slice is the {i, j}-th element in the matrix. -func NewDense(r, c int, data []float64) *Dense { - if r <= 0 || c <= 0 { - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if data != nil && r*c != len(data) { - panic(ErrShape) - } - if data == nil { - data = make([]float64, r*c) - } - return &Dense{ - mat: blas64.General{ - Rows: r, - Cols: c, - Stride: c, - Data: data, - }, - capRows: r, - capCols: c, - } -} - -// ReuseAs changes the receiver if it IsEmpty() to be of size r×c. -// -// ReuseAs re-uses the backing data slice if it has sufficient capacity, -// otherwise a new slice is allocated. The backing data is zero on return. -// -// ReuseAs panics if the receiver is not empty, and panics if -// the input sizes are less than one. To empty the receiver for re-use, -// Reset should be used. -func (m *Dense) ReuseAs(r, c int) { - if r <= 0 || c <= 0 { - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if !m.IsEmpty() { - panic(ErrReuseNonEmpty) - } - m.reuseAsZeroed(r, c) -} - -// reuseAsNonZeroed resizes an empty matrix to a r×c matrix, -// or checks that a non-empty matrix is r×c. It does not zero -// the data in the receiver. -func (m *Dense) reuseAsNonZeroed(r, c int) { - // reuseAs must be kept in sync with reuseAsZeroed. - if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - if m.IsEmpty() { - m.mat = blas64.General{ - Rows: r, - Cols: c, - Stride: c, - Data: use(m.mat.Data, r*c), - } - m.capRows = r - m.capCols = c - return - } - if r != m.mat.Rows || c != m.mat.Cols { - panic(ErrShape) - } -} - -// reuseAsZeroed resizes an empty matrix to a r×c matrix, -// or checks that a non-empty matrix is r×c. It zeroes -// all the elements of the matrix. -func (m *Dense) reuseAsZeroed(r, c int) { - // reuseAsZeroed must be kept in sync with reuseAsNonZeroed. - if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - if m.IsEmpty() { - m.mat = blas64.General{ - Rows: r, - Cols: c, - Stride: c, - Data: useZeroed(m.mat.Data, r*c), - } - m.capRows = r - m.capCols = c - return - } - if r != m.mat.Rows || c != m.mat.Cols { - panic(ErrShape) - } - m.Zero() -} - -// Zero sets all of the matrix elements to zero. -func (m *Dense) Zero() { - r := m.mat.Rows - c := m.mat.Cols - for i := 0; i < r; i++ { - zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) - } -} - -// isolatedWorkspace returns a new dense matrix w with the size of a and -// returns a callback to defer which performs cleanup at the return of the call. -// This should be used when a method receiver is the same pointer as an input argument. -func (m *Dense) isolatedWorkspace(a Matrix) (w *Dense, restore func()) { - r, c := a.Dims() - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - w = getDenseWorkspace(r, c, false) - return w, func() { - m.Copy(w) - putDenseWorkspace(w) - } -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (m *Dense) Reset() { - // Row, Cols and Stride must be zeroed in unison. - m.mat.Rows, m.mat.Cols, m.mat.Stride = 0, 0, 0 - m.capRows, m.capCols = 0, 0 - m.mat.Data = m.mat.Data[:0] -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (m *Dense) IsEmpty() bool { - // It must be the case that m.Dims() returns - // zeros in this case. See comment in Reset(). - return m.mat.Stride == 0 -} - -// asTriDense returns a TriDense with the given size and side. The backing data -// of the TriDense is the same as the receiver. -func (m *Dense) asTriDense(n int, diag blas.Diag, uplo blas.Uplo) *TriDense { - return &TriDense{ - mat: blas64.Triangular{ - N: n, - Stride: m.mat.Stride, - Data: m.mat.Data, - Uplo: uplo, - Diag: diag, - }, - cap: n, - } -} - -// DenseCopyOf returns a newly allocated copy of the elements of a. -func DenseCopyOf(a Matrix) *Dense { - d := &Dense{} - d.CloneFrom(a) - return d -} - -// SetRawMatrix sets the underlying blas64.General used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in b. -func (m *Dense) SetRawMatrix(b blas64.General) { - m.capRows, m.capCols = b.Rows, b.Cols - m.mat = b -} - -// RawMatrix returns the underlying blas64.General used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in returned blas64.General. -func (m *Dense) RawMatrix() blas64.General { return m.mat } - -// Dims returns the number of rows and columns in the matrix. -func (m *Dense) Dims() (r, c int) { return m.mat.Rows, m.mat.Cols } - -// Caps returns the number of rows and columns in the backing matrix. -func (m *Dense) Caps() (r, c int) { return m.capRows, m.capCols } - -// T performs an implicit transpose by returning the receiver inside a Transpose. -func (m *Dense) T() Matrix { - return Transpose{m} -} - -// ColView returns a Vector reflecting the column j, backed by the matrix data. -// -// See ColViewer for more information. -func (m *Dense) ColView(j int) Vector { - var v VecDense - v.ColViewOf(m, j) - return &v -} - -// SetCol sets the values in the specified column of the matrix to the values -// in src. len(src) must equal the number of rows in the receiver. -func (m *Dense) SetCol(j int, src []float64) { - if j >= m.mat.Cols || j < 0 { - panic(ErrColAccess) - } - if len(src) != m.mat.Rows { - panic(ErrColLength) - } - - blas64.Copy( - blas64.Vector{N: m.mat.Rows, Inc: 1, Data: src}, - blas64.Vector{N: m.mat.Rows, Inc: m.mat.Stride, Data: m.mat.Data[j:]}, - ) -} - -// SetRow sets the values in the specified rows of the matrix to the values -// in src. len(src) must equal the number of columns in the receiver. -func (m *Dense) SetRow(i int, src []float64) { - if i >= m.mat.Rows || i < 0 { - panic(ErrRowAccess) - } - if len(src) != m.mat.Cols { - panic(ErrRowLength) - } - - copy(m.rawRowView(i), src) -} - -// RowView returns row i of the matrix data represented as a column vector, -// backed by the matrix data. -// -// See RowViewer for more information. -func (m *Dense) RowView(i int) Vector { - var v VecDense - v.RowViewOf(m, i) - return &v -} - -// RawRowView returns a slice backed by the same array as backing the -// receiver. -func (m *Dense) RawRowView(i int) []float64 { - if i >= m.mat.Rows || i < 0 { - panic(ErrRowAccess) - } - return m.rawRowView(i) -} - -func (m *Dense) rawRowView(i int) []float64 { - return m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+m.mat.Cols] -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (m *Dense) DiagView() Diagonal { - n := min(m.mat.Rows, m.mat.Cols) - return &DiagDense{ - mat: blas64.Vector{ - N: n, - Inc: m.mat.Stride + 1, - Data: m.mat.Data[:(n-1)*m.mat.Stride+n], - }, - } -} - -// Slice returns a new Matrix that shares backing data with the receiver. -// The returned matrix starts at {i,j} of the receiver and extends k-i rows -// and l-j columns. The final row in the resulting matrix is k-1 and the -// final column is l-1. -// Slice panics with ErrIndexOutOfRange if the slice is outside the capacity -// of the receiver. -func (m *Dense) Slice(i, k, j, l int) Matrix { - return m.slice(i, k, j, l) -} - -func (m *Dense) slice(i, k, j, l int) *Dense { - mr, mc := m.Caps() - if i < 0 || mr <= i || j < 0 || mc <= j || k < i || mr < k || l < j || mc < l { - if i == k || j == l { - panic(ErrZeroLength) - } - panic(ErrIndexOutOfRange) - } - t := *m - t.mat.Data = t.mat.Data[i*t.mat.Stride+j : (k-1)*t.mat.Stride+l] - t.mat.Rows = k - i - t.mat.Cols = l - j - t.capRows -= i - t.capCols -= j - return &t -} - -// Grow returns the receiver expanded by r rows and c columns. If the dimensions -// of the expanded matrix are outside the capacities of the receiver a new -// allocation is made, otherwise not. Note the receiver itself is not modified -// during the call to Grow. -func (m *Dense) Grow(r, c int) Matrix { - if r < 0 || c < 0 { - panic(ErrIndexOutOfRange) - } - if r == 0 && c == 0 { - return m - } - - r += m.mat.Rows - c += m.mat.Cols - - var t Dense - switch { - case m.mat.Rows == 0 || m.mat.Cols == 0: - t.mat = blas64.General{ - Rows: r, - Cols: c, - Stride: c, - // We zero because we don't know how the matrix will be used. - // In other places, the mat is immediately filled with a result; - // this is not the case here. - Data: useZeroed(m.mat.Data, r*c), - } - case r > m.capRows || c > m.capCols: - cr := max(r, m.capRows) - cc := max(c, m.capCols) - t.mat = blas64.General{ - Rows: r, - Cols: c, - Stride: cc, - Data: make([]float64, cr*cc), - } - t.capRows = cr - t.capCols = cc - // Copy the complete matrix over to the new matrix. - // Including elements not currently visible. Use a temporary structure - // to avoid modifying the receiver. - var tmp Dense - tmp.mat = blas64.General{ - Rows: m.mat.Rows, - Cols: m.mat.Cols, - Stride: m.mat.Stride, - Data: m.mat.Data, - } - tmp.capRows = m.capRows - tmp.capCols = m.capCols - t.Copy(&tmp) - return &t - default: - t.mat = blas64.General{ - Data: m.mat.Data[:(r-1)*m.mat.Stride+c], - Rows: r, - Cols: c, - Stride: m.mat.Stride, - } - } - t.capRows = r - t.capCols = c - return &t -} - -// CloneFrom makes a copy of a into the receiver, overwriting the previous value of -// the receiver. The clone from operation does not make any restriction on shape and -// will not cause shadowing. -// -// See the ClonerFrom interface for more information. -func (m *Dense) CloneFrom(a Matrix) { - r, c := a.Dims() - mat := blas64.General{ - Rows: r, - Cols: c, - Stride: c, - } - m.capRows, m.capCols = r, c - - aU, trans := untransposeExtract(a) - switch aU := aU.(type) { - case *Dense: - amat := aU.mat - mat.Data = make([]float64, r*c) - if trans { - for i := 0; i < r; i++ { - blas64.Copy(blas64.Vector{N: c, Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, - blas64.Vector{N: c, Inc: 1, Data: mat.Data[i*c : (i+1)*c]}) - } - } else { - for i := 0; i < r; i++ { - copy(mat.Data[i*c:(i+1)*c], amat.Data[i*amat.Stride:i*amat.Stride+c]) - } - } - case *VecDense: - amat := aU.mat - mat.Data = make([]float64, aU.mat.N) - blas64.Copy(blas64.Vector{N: aU.mat.N, Inc: amat.Inc, Data: amat.Data}, - blas64.Vector{N: aU.mat.N, Inc: 1, Data: mat.Data}) - default: - mat.Data = make([]float64, r*c) - w := *m - w.mat = mat - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - w.set(i, j, a.At(i, j)) - } - } - *m = w - return - } - m.mat = mat -} - -// Copy makes a copy of elements of a into the receiver. It is similar to the -// built-in copy; it copies as much as the overlap between the two matrices and -// returns the number of rows and columns it copied. If a aliases the receiver -// and is a transposed Dense or VecDense, with a non-unitary increment, Copy will -// panic. -// -// See the Copier interface for more information. -func (m *Dense) Copy(a Matrix) (r, c int) { - r, c = a.Dims() - if a == m { - return r, c - } - r = min(r, m.mat.Rows) - c = min(c, m.mat.Cols) - if r == 0 || c == 0 { - return 0, 0 - } - - aU, trans := untransposeExtract(a) - switch aU := aU.(type) { - case *Dense: - amat := aU.mat - if trans { - if amat.Stride != 1 { - m.checkOverlap(amat) - } - for i := 0; i < r; i++ { - blas64.Copy(blas64.Vector{N: c, Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, - blas64.Vector{N: c, Inc: 1, Data: m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]}) - } - } else { - switch o := offset(m.mat.Data, amat.Data); { - case o < 0: - for i := r - 1; i >= 0; i-- { - copy(m.mat.Data[i*m.mat.Stride:i*m.mat.Stride+c], amat.Data[i*amat.Stride:i*amat.Stride+c]) - } - case o > 0: - for i := 0; i < r; i++ { - copy(m.mat.Data[i*m.mat.Stride:i*m.mat.Stride+c], amat.Data[i*amat.Stride:i*amat.Stride+c]) - } - default: - // Nothing to do. - } - } - case *VecDense: - var n, stride int - amat := aU.mat - if trans { - if amat.Inc != 1 { - m.checkOverlap(aU.asGeneral()) - } - n = c - stride = 1 - } else { - n = r - stride = m.mat.Stride - } - if amat.Inc == 1 && stride == 1 { - copy(m.mat.Data, amat.Data[:n]) - break - } - switch o := offset(m.mat.Data, amat.Data); { - case o < 0: - blas64.Copy(blas64.Vector{N: n, Inc: -amat.Inc, Data: amat.Data}, - blas64.Vector{N: n, Inc: -stride, Data: m.mat.Data}) - case o > 0: - blas64.Copy(blas64.Vector{N: n, Inc: amat.Inc, Data: amat.Data}, - blas64.Vector{N: n, Inc: stride, Data: m.mat.Data}) - default: - // Nothing to do. - } - default: - m.checkOverlapMatrix(aU) - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - m.set(i, j, a.At(i, j)) - } - } - } - - return r, c -} - -// Stack appends the rows of b onto the rows of a, placing the result into the -// receiver with b placed in the greater indexed rows. Stack will panic if the -// two input matrices do not have the same number of columns or the constructed -// stacked matrix is not the same shape as the receiver. -func (m *Dense) Stack(a, b Matrix) { - ar, ac := a.Dims() - br, bc := b.Dims() - if ac != bc || m == a || m == b { - panic(ErrShape) - } - - m.reuseAsNonZeroed(ar+br, ac) - - m.Copy(a) - w := m.slice(ar, ar+br, 0, bc) - w.Copy(b) -} - -// Augment creates the augmented matrix of a and b, where b is placed in the -// greater indexed columns. Augment will panic if the two input matrices do -// not have the same number of rows or the constructed augmented matrix is -// not the same shape as the receiver. -func (m *Dense) Augment(a, b Matrix) { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || m == a || m == b { - panic(ErrShape) - } - - m.reuseAsNonZeroed(ar, ac+bc) - - m.Copy(a) - w := m.slice(0, br, ac, ac+bc) - w.Copy(b) -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrSquare if the matrix is not square and with -// ErrZeroLength if the matrix has zero size. -func (m *Dense) Trace() float64 { - r, c := m.Dims() - if r != c { - panic(ErrSquare) - } - if m.IsEmpty() { - panic(ErrZeroLength) - } - // TODO(btracey): could use internal asm sum routine. - var v float64 - for i := 0; i < m.mat.Rows; i++ { - v += m.mat.Data[i*m.mat.Stride+i] - } - return v -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrShape if the matrix has zero size. -func (m *Dense) Norm(norm float64) float64 { - if m.IsEmpty() { - panic(ErrZeroLength) - } - lnorm := normLapack(norm, false) - if lnorm == lapack.MaxColumnSum { - work := getFloat64s(m.mat.Cols, false) - defer putFloat64s(work) - return lapack64.Lange(lnorm, m.mat, work) - } - return lapack64.Lange(lnorm, m.mat, nil) -} - -// Permutation constructs an n×n permutation matrix P from the given -// row permutation such that the nonzero entries are P[i,p[i]] = 1. -func (m *Dense) Permutation(n int, p []int) { - if len(p) != n { - panic(badSliceLength) - } - m.reuseAsZeroed(n, n) - for i, v := range p { - if v < 0 || v >= n { - panic(ErrRowAccess) - } - m.mat.Data[i*m.mat.Stride+v] = 1 - } -} - -// PermuteRows rearranges the rows of the m×n matrix A in the receiver as -// specified by the permutation p[0],p[1],...,p[m-1] of the integers 0,...,m-1. -// -// If inverse is false, the given permutation is applied: -// -// A[p[i],0:n] is moved to A[i,0:n] for i=0,1,...,m-1. -// -// If inverse is true, the inverse permutation is applied: -// -// A[i,0:n] is moved to A[p[i],0:n] for i=0,1,...,m-1. -// -// p must have length m, otherwise PermuteRows will panic. -func (m *Dense) PermuteRows(p []int, inverse bool) { - r, _ := m.Dims() - if len(p) != r { - panic(badSliceLength) - } - lapack64.Lapmr(!inverse, m.mat, p) -} - -// PermuteCols rearranges the columns of the m×n matrix A in the reciever as -// specified by the permutation p[0],p[1],...,p[n-1] of the integers 0,...,n-1. -// -// If inverse is false, the given permutation is applied: -// -// A[0:m,p[j]] is moved to A[0:m,j] for j = 0, 1, ..., n-1. -// -// If inverse is true, the inverse permutation is applied: -// -// A[0:m,j] is moved to A[0:m,p[j]] for j = 0, 1, ..., n-1. -// -// p must have length n, otherwise PermuteCols will panic. -func (m *Dense) PermuteCols(p []int, inverse bool) { - _, c := m.Dims() - if len(p) != c { - panic(badSliceLength) - } - lapack64.Lapmt(!inverse, m.mat, p) -} diff --git a/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go b/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go deleted file mode 100644 index 259ee13d..00000000 --- a/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go +++ /dev/null @@ -1,877 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack/lapack64" -) - -// Add adds a and b element-wise, placing the result in the receiver. Add -// will panic if the two matrices do not have the same shape. -func (m *Dense) Add(a, b Matrix) { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - panic(ErrShape) - } - - aU, aTrans := untransposeExtract(a) - bU, bTrans := untransposeExtract(b) - m.reuseAsNonZeroed(ar, ac) - - if arm, ok := a.(*Dense); ok { - if brm, ok := b.(*Dense); ok { - amat, bmat := arm.mat, brm.mat - if m != aU { - m.checkOverlap(amat) - } - if m != bU { - m.checkOverlap(bmat) - } - for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { - for i, v := range amat.Data[ja : ja+ac] { - m.mat.Data[i+jm] = v + bmat.Data[i+jb] - } - } - return - } - } - - m.checkOverlapMatrix(aU) - m.checkOverlapMatrix(bU) - var restore func() - if aTrans && m == aU { - m, restore = m.isolatedWorkspace(aU) - defer restore() - } else if bTrans && m == bU { - m, restore = m.isolatedWorkspace(bU) - defer restore() - } - - for r := 0; r < ar; r++ { - for c := 0; c < ac; c++ { - m.set(r, c, a.At(r, c)+b.At(r, c)) - } - } -} - -// Sub subtracts the matrix b from a, placing the result in the receiver. Sub -// will panic if the two matrices do not have the same shape. -func (m *Dense) Sub(a, b Matrix) { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - panic(ErrShape) - } - - aU, aTrans := untransposeExtract(a) - bU, bTrans := untransposeExtract(b) - m.reuseAsNonZeroed(ar, ac) - - if arm, ok := a.(*Dense); ok { - if brm, ok := b.(*Dense); ok { - amat, bmat := arm.mat, brm.mat - if m != aU { - m.checkOverlap(amat) - } - if m != bU { - m.checkOverlap(bmat) - } - for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { - for i, v := range amat.Data[ja : ja+ac] { - m.mat.Data[i+jm] = v - bmat.Data[i+jb] - } - } - return - } - } - - m.checkOverlapMatrix(aU) - m.checkOverlapMatrix(bU) - var restore func() - if aTrans && m == aU { - m, restore = m.isolatedWorkspace(aU) - defer restore() - } else if bTrans && m == bU { - m, restore = m.isolatedWorkspace(bU) - defer restore() - } - - for r := 0; r < ar; r++ { - for c := 0; c < ac; c++ { - m.set(r, c, a.At(r, c)-b.At(r, c)) - } - } -} - -// MulElem performs element-wise multiplication of a and b, placing the result -// in the receiver. MulElem will panic if the two matrices do not have the same -// shape. -func (m *Dense) MulElem(a, b Matrix) { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - panic(ErrShape) - } - - aU, aTrans := untransposeExtract(a) - bU, bTrans := untransposeExtract(b) - m.reuseAsNonZeroed(ar, ac) - - if arm, ok := a.(*Dense); ok { - if brm, ok := b.(*Dense); ok { - amat, bmat := arm.mat, brm.mat - if m != aU { - m.checkOverlap(amat) - } - if m != bU { - m.checkOverlap(bmat) - } - for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { - for i, v := range amat.Data[ja : ja+ac] { - m.mat.Data[i+jm] = v * bmat.Data[i+jb] - } - } - return - } - } - - m.checkOverlapMatrix(aU) - m.checkOverlapMatrix(bU) - var restore func() - if aTrans && m == aU { - m, restore = m.isolatedWorkspace(aU) - defer restore() - } else if bTrans && m == bU { - m, restore = m.isolatedWorkspace(bU) - defer restore() - } - - for r := 0; r < ar; r++ { - for c := 0; c < ac; c++ { - m.set(r, c, a.At(r, c)*b.At(r, c)) - } - } -} - -// DivElem performs element-wise division of a by b, placing the result -// in the receiver. DivElem will panic if the two matrices do not have the same -// shape. -func (m *Dense) DivElem(a, b Matrix) { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - panic(ErrShape) - } - - aU, aTrans := untransposeExtract(a) - bU, bTrans := untransposeExtract(b) - m.reuseAsNonZeroed(ar, ac) - - if arm, ok := a.(*Dense); ok { - if brm, ok := b.(*Dense); ok { - amat, bmat := arm.mat, brm.mat - if m != aU { - m.checkOverlap(amat) - } - if m != bU { - m.checkOverlap(bmat) - } - for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { - for i, v := range amat.Data[ja : ja+ac] { - m.mat.Data[i+jm] = v / bmat.Data[i+jb] - } - } - return - } - } - - m.checkOverlapMatrix(aU) - m.checkOverlapMatrix(bU) - var restore func() - if aTrans && m == aU { - m, restore = m.isolatedWorkspace(aU) - defer restore() - } else if bTrans && m == bU { - m, restore = m.isolatedWorkspace(bU) - defer restore() - } - - for r := 0; r < ar; r++ { - for c := 0; c < ac; c++ { - m.set(r, c, a.At(r, c)/b.At(r, c)) - } - } -} - -// Inverse computes the inverse of the matrix a, storing the result into the -// receiver. If a is ill-conditioned, a Condition error will be returned. -// Note that matrix inversion is numerically unstable, and should generally -// be avoided where possible, for example by using the Solve routines. -func (m *Dense) Inverse(a Matrix) error { - // TODO(btracey): Special case for RawTriangular, etc. - r, c := a.Dims() - if r != c { - panic(ErrSquare) - } - m.reuseAsNonZeroed(a.Dims()) - aU, aTrans := untransposeExtract(a) - switch rm := aU.(type) { - case *Dense: - if m != aU || aTrans { - if m == aU || m.checkOverlap(rm.mat) { - tmp := getDenseWorkspace(r, c, false) - tmp.Copy(a) - m.Copy(tmp) - putDenseWorkspace(tmp) - break - } - m.Copy(a) - } - default: - m.Copy(a) - } - // Compute the norm of A. - work := getFloat64s(4*r, false) // Length must be at least 4*r for Gecon. - norm := lapack64.Lange(CondNorm, m.mat, work) - // Compute the LU factorization of A. - ipiv := getInts(r, false) - defer putInts(ipiv) - ok := lapack64.Getrf(m.mat, ipiv) - if !ok { - // A is exactly singular. - return Condition(math.Inf(1)) - } - // Compute the condition number of A using the LU factorization. - iwork := getInts(r, false) - defer putInts(iwork) - rcond := lapack64.Gecon(CondNorm, m.mat, norm, work, iwork) - // Compute A^{-1} from the LU factorization regardless of the value of rcond. - lapack64.Getri(m.mat, ipiv, work, -1) - if int(work[0]) > len(work) { - l := int(work[0]) - putFloat64s(work) - work = getFloat64s(l, false) - } - defer putFloat64s(work) - ok = lapack64.Getri(m.mat, ipiv, work, len(work)) - if !ok || rcond == 0 { - // A is exactly singular. - return Condition(math.Inf(1)) - } - // Check whether A is singular for computational purposes. - cond := 1 / rcond - if cond > ConditionTolerance { - return Condition(cond) - } - return nil -} - -// Mul takes the matrix product of a and b, placing the result in the receiver. -// If the number of columns in a does not equal the number of rows in b, Mul will panic. -func (m *Dense) Mul(a, b Matrix) { - ar, ac := a.Dims() - br, bc := b.Dims() - - if ac != br { - panic(ErrShape) - } - - aU, aTrans := untransposeExtract(a) - bU, bTrans := untransposeExtract(b) - m.reuseAsNonZeroed(ar, bc) - var restore func() - if m == aU { - m, restore = m.isolatedWorkspace(aU) - defer restore() - } else if m == bU { - m, restore = m.isolatedWorkspace(bU) - defer restore() - } - aT := blas.NoTrans - if aTrans { - aT = blas.Trans - } - bT := blas.NoTrans - if bTrans { - bT = blas.Trans - } - - // Some of the cases do not have a transpose option, so create - // temporary memory. - // C = Aᵀ * B = (Bᵀ * A)ᵀ - // Cᵀ = Bᵀ * A. - if aU, ok := aU.(*Dense); ok { - if restore == nil { - m.checkOverlap(aU.mat) - } - switch bU := bU.(type) { - case *Dense: - if restore == nil { - m.checkOverlap(bU.mat) - } - blas64.Gemm(aT, bT, 1, aU.mat, bU.mat, 0, m.mat) - return - - case *SymDense: - if aTrans { - c := getDenseWorkspace(ac, ar, false) - blas64.Symm(blas.Left, 1, bU.mat, aU.mat, 0, c.mat) - strictCopy(m, c.T()) - putDenseWorkspace(c) - return - } - blas64.Symm(blas.Right, 1, bU.mat, aU.mat, 0, m.mat) - return - - case *TriDense: - // Trmm updates in place, so copy aU first. - if aTrans { - c := getDenseWorkspace(ac, ar, false) - var tmp Dense - tmp.SetRawMatrix(aU.mat) - c.Copy(&tmp) - bT := blas.Trans - if bTrans { - bT = blas.NoTrans - } - blas64.Trmm(blas.Left, bT, 1, bU.mat, c.mat) - strictCopy(m, c.T()) - putDenseWorkspace(c) - return - } - m.Copy(a) - blas64.Trmm(blas.Right, bT, 1, bU.mat, m.mat) - return - - case *VecDense: - m.checkOverlap(bU.asGeneral()) - bvec := bU.RawVector() - if bTrans { - // {ar,1} x {1,bc}, which is not a vector. - // Instead, construct B as a General. - bmat := blas64.General{ - Rows: bc, - Cols: 1, - Stride: bvec.Inc, - Data: bvec.Data, - } - blas64.Gemm(aT, bT, 1, aU.mat, bmat, 0, m.mat) - return - } - cvec := blas64.Vector{ - Inc: m.mat.Stride, - Data: m.mat.Data, - } - blas64.Gemv(aT, 1, aU.mat, bvec, 0, cvec) - return - } - } - if bU, ok := bU.(*Dense); ok { - if restore == nil { - m.checkOverlap(bU.mat) - } - switch aU := aU.(type) { - case *SymDense: - if bTrans { - c := getDenseWorkspace(bc, br, false) - blas64.Symm(blas.Right, 1, aU.mat, bU.mat, 0, c.mat) - strictCopy(m, c.T()) - putDenseWorkspace(c) - return - } - blas64.Symm(blas.Left, 1, aU.mat, bU.mat, 0, m.mat) - return - - case *TriDense: - // Trmm updates in place, so copy bU first. - if bTrans { - c := getDenseWorkspace(bc, br, false) - var tmp Dense - tmp.SetRawMatrix(bU.mat) - c.Copy(&tmp) - aT := blas.Trans - if aTrans { - aT = blas.NoTrans - } - blas64.Trmm(blas.Right, aT, 1, aU.mat, c.mat) - strictCopy(m, c.T()) - putDenseWorkspace(c) - return - } - m.Copy(b) - blas64.Trmm(blas.Left, aT, 1, aU.mat, m.mat) - return - - case *VecDense: - m.checkOverlap(aU.asGeneral()) - avec := aU.RawVector() - if aTrans { - // {1,ac} x {ac, bc} - // Transpose B so that the vector is on the right. - cvec := blas64.Vector{ - Inc: 1, - Data: m.mat.Data, - } - bT := blas.Trans - if bTrans { - bT = blas.NoTrans - } - blas64.Gemv(bT, 1, bU.mat, avec, 0, cvec) - return - } - // {ar,1} x {1,bc} which is not a vector result. - // Instead, construct A as a General. - amat := blas64.General{ - Rows: ar, - Cols: 1, - Stride: avec.Inc, - Data: avec.Data, - } - blas64.Gemm(aT, bT, 1, amat, bU.mat, 0, m.mat) - return - } - } - - m.checkOverlapMatrix(aU) - m.checkOverlapMatrix(bU) - row := getFloat64s(ac, false) - defer putFloat64s(row) - for r := 0; r < ar; r++ { - for i := range row { - row[i] = a.At(r, i) - } - for c := 0; c < bc; c++ { - var v float64 - for i, e := range row { - v += e * b.At(i, c) - } - m.mat.Data[r*m.mat.Stride+c] = v - } - } -} - -// strictCopy copies a into m panicking if the shape of a and m differ. -func strictCopy(m *Dense, a Matrix) { - r, c := m.Copy(a) - if r != m.mat.Rows || c != m.mat.Cols { - // Panic with a string since this - // is not a user-facing panic. - panic(ErrShape.Error()) - } -} - -// Exp calculates the exponential of the matrix a, e^a, placing the result -// in the receiver. Exp will panic with ErrShape if a is not square. -func (m *Dense) Exp(a Matrix) { - // The implementation used here is from Functions of Matrices: Theory and Computation - // Chapter 10, Algorithm 10.20. https://doi.org/10.1137/1.9780898717778.ch10 - - r, c := a.Dims() - if r != c { - panic(ErrShape) - } - - m.reuseAsNonZeroed(r, r) - if r == 1 { - m.mat.Data[0] = math.Exp(a.At(0, 0)) - return - } - - pade := []struct { - theta float64 - b []float64 - }{ - {theta: 0.015, b: []float64{ - 120, 60, 12, 1, - }}, - {theta: 0.25, b: []float64{ - 30240, 15120, 3360, 420, 30, 1, - }}, - {theta: 0.95, b: []float64{ - 17297280, 8648640, 1995840, 277200, 25200, 1512, 56, 1, - }}, - {theta: 2.1, b: []float64{ - 17643225600, 8821612800, 2075673600, 302702400, 30270240, 2162160, 110880, 3960, 90, 1, - }}, - } - - a1 := m - a1.Copy(a) - v := getDenseWorkspace(r, r, true) - vraw := v.RawMatrix() - n := r * r - vvec := blas64.Vector{N: n, Inc: 1, Data: vraw.Data} - defer putDenseWorkspace(v) - - u := getDenseWorkspace(r, r, true) - uraw := u.RawMatrix() - uvec := blas64.Vector{N: n, Inc: 1, Data: uraw.Data} - defer putDenseWorkspace(u) - - a2 := getDenseWorkspace(r, r, false) - defer putDenseWorkspace(a2) - - n1 := Norm(a, 1) - for i, t := range pade { - if n1 > t.theta { - continue - } - - // This loop only executes once, so - // this is not as horrible as it looks. - p := getDenseWorkspace(r, r, true) - praw := p.RawMatrix() - pvec := blas64.Vector{N: n, Inc: 1, Data: praw.Data} - defer putDenseWorkspace(p) - - for k := 0; k < r; k++ { - p.set(k, k, 1) - v.set(k, k, t.b[0]) - u.set(k, k, t.b[1]) - } - - a2.Mul(a1, a1) - for j := 0; j <= i; j++ { - p.Mul(p, a2) - blas64.Axpy(t.b[2*j+2], pvec, vvec) - blas64.Axpy(t.b[2*j+3], pvec, uvec) - } - u.Mul(a1, u) - - // Use p as a workspace here and - // rename u for the second call's - // receiver. - vmu, vpu := u, p - vpu.Add(v, u) - vmu.Sub(v, u) - - _ = m.Solve(vmu, vpu) - return - } - - // Remaining Padé table line. - const theta13 = 5.4 - b := [...]float64{ - 64764752532480000, 32382376266240000, 7771770303897600, 1187353796428800, - 129060195264000, 10559470521600, 670442572800, 33522128640, - 1323241920, 40840800, 960960, 16380, 182, 1, - } - - s := math.Log2(n1 / theta13) - if s >= 0 { - s = math.Ceil(s) - a1.Scale(1/math.Pow(2, s), a1) - } - a2.Mul(a1, a1) - - i := getDenseWorkspace(r, r, true) - for j := 0; j < r; j++ { - i.set(j, j, 1) - } - iraw := i.RawMatrix() - ivec := blas64.Vector{N: n, Inc: 1, Data: iraw.Data} - defer putDenseWorkspace(i) - - a2raw := a2.RawMatrix() - a2vec := blas64.Vector{N: n, Inc: 1, Data: a2raw.Data} - - a4 := getDenseWorkspace(r, r, false) - a4raw := a4.RawMatrix() - a4vec := blas64.Vector{N: n, Inc: 1, Data: a4raw.Data} - defer putDenseWorkspace(a4) - a4.Mul(a2, a2) - - a6 := getDenseWorkspace(r, r, false) - a6raw := a6.RawMatrix() - a6vec := blas64.Vector{N: n, Inc: 1, Data: a6raw.Data} - defer putDenseWorkspace(a6) - a6.Mul(a2, a4) - - // V = A_6(b_12*A_6 + b_10*A_4 + b_8*A_2) + b_6*A_6 + b_4*A_4 + b_2*A_2 +b_0*I - blas64.Axpy(b[12], a6vec, vvec) - blas64.Axpy(b[10], a4vec, vvec) - blas64.Axpy(b[8], a2vec, vvec) - v.Mul(v, a6) - blas64.Axpy(b[6], a6vec, vvec) - blas64.Axpy(b[4], a4vec, vvec) - blas64.Axpy(b[2], a2vec, vvec) - blas64.Axpy(b[0], ivec, vvec) - - // U = A(A_6(b_13*A_6 + b_11*A_4 + b_9*A_2) + b_7*A_6 + b_5*A_4 + b_2*A_3 +b_1*I) - blas64.Axpy(b[13], a6vec, uvec) - blas64.Axpy(b[11], a4vec, uvec) - blas64.Axpy(b[9], a2vec, uvec) - u.Mul(u, a6) - blas64.Axpy(b[7], a6vec, uvec) - blas64.Axpy(b[5], a4vec, uvec) - blas64.Axpy(b[3], a2vec, uvec) - blas64.Axpy(b[1], ivec, uvec) - u.Mul(u, a1) - - // Use i as a workspace here and - // rename u for the second call's - // receiver. - vmu, vpu := u, i - vpu.Add(v, u) - vmu.Sub(v, u) - - _ = m.Solve(vmu, vpu) - - for ; s > 0; s-- { - m.Mul(m, m) - } -} - -// Pow calculates the integral power of the matrix a to n, placing the result -// in the receiver. Pow will panic if n is negative or if a is not square. -func (m *Dense) Pow(a Matrix, n int) { - if n < 0 { - panic("mat: illegal power") - } - r, c := a.Dims() - if r != c { - panic(ErrShape) - } - - m.reuseAsNonZeroed(r, c) - - // Take possible fast paths. - switch n { - case 0: - for i := 0; i < r; i++ { - zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) - m.mat.Data[i*m.mat.Stride+i] = 1 - } - return - case 1: - m.Copy(a) - return - case 2: - m.Mul(a, a) - return - } - - // Perform iterative exponentiation by squaring in work space. - w := getDenseWorkspace(r, r, false) - w.Copy(a) - s := getDenseWorkspace(r, r, false) - s.Copy(a) - x := getDenseWorkspace(r, r, false) - for n--; n > 0; n >>= 1 { - if n&1 != 0 { - x.Mul(w, s) - w, x = x, w - } - if n != 1 { - x.Mul(s, s) - s, x = x, s - } - } - m.Copy(w) - putDenseWorkspace(w) - putDenseWorkspace(s) - putDenseWorkspace(x) -} - -// Kronecker calculates the Kronecker product of a and b, placing the result in -// the receiver. -func (m *Dense) Kronecker(a, b Matrix) { - ra, ca := a.Dims() - rb, cb := b.Dims() - - m.reuseAsNonZeroed(ra*rb, ca*cb) - for i := 0; i < ra; i++ { - for j := 0; j < ca; j++ { - m.slice(i*rb, (i+1)*rb, j*cb, (j+1)*cb).Scale(a.At(i, j), b) - } - } -} - -// Scale multiplies the elements of a by f, placing the result in the receiver. -// -// See the Scaler interface for more information. -func (m *Dense) Scale(f float64, a Matrix) { - ar, ac := a.Dims() - - m.reuseAsNonZeroed(ar, ac) - - aU, aTrans := untransposeExtract(a) - if rm, ok := aU.(*Dense); ok { - amat := rm.mat - if m == aU || m.checkOverlap(amat) { - var restore func() - m, restore = m.isolatedWorkspace(a) - defer restore() - } - if !aTrans { - for ja, jm := 0, 0; ja < ar*amat.Stride; ja, jm = ja+amat.Stride, jm+m.mat.Stride { - for i, v := range amat.Data[ja : ja+ac] { - m.mat.Data[i+jm] = v * f - } - } - } else { - for ja, jm := 0, 0; ja < ac*amat.Stride; ja, jm = ja+amat.Stride, jm+1 { - for i, v := range amat.Data[ja : ja+ar] { - m.mat.Data[i*m.mat.Stride+jm] = v * f - } - } - } - return - } - - m.checkOverlapMatrix(a) - for r := 0; r < ar; r++ { - for c := 0; c < ac; c++ { - m.set(r, c, f*a.At(r, c)) - } - } -} - -// Apply applies the function fn to each of the elements of a, placing the -// resulting matrix in the receiver. The function fn takes a row/column -// index and element value and returns some function of that tuple. -func (m *Dense) Apply(fn func(i, j int, v float64) float64, a Matrix) { - ar, ac := a.Dims() - - m.reuseAsNonZeroed(ar, ac) - - aU, aTrans := untransposeExtract(a) - if rm, ok := aU.(*Dense); ok { - amat := rm.mat - if m == aU || m.checkOverlap(amat) { - var restore func() - m, restore = m.isolatedWorkspace(a) - defer restore() - } - if !aTrans { - for j, ja, jm := 0, 0, 0; ja < ar*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+m.mat.Stride { - for i, v := range amat.Data[ja : ja+ac] { - m.mat.Data[i+jm] = fn(j, i, v) - } - } - } else { - for j, ja, jm := 0, 0, 0; ja < ac*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+1 { - for i, v := range amat.Data[ja : ja+ar] { - m.mat.Data[i*m.mat.Stride+jm] = fn(i, j, v) - } - } - } - return - } - - m.checkOverlapMatrix(a) - for r := 0; r < ar; r++ { - for c := 0; c < ac; c++ { - m.set(r, c, fn(r, c, a.At(r, c))) - } - } -} - -// RankOne performs a rank-one update to the matrix a with the vectors x and -// y, where x and y are treated as column vectors. The result is stored in the -// receiver. The Outer method can be used instead of RankOne if a is not needed. -// -// m = a + alpha * x * yᵀ -func (m *Dense) RankOne(a Matrix, alpha float64, x, y Vector) { - ar, ac := a.Dims() - if x.Len() != ar { - panic(ErrShape) - } - if y.Len() != ac { - panic(ErrShape) - } - - if a != m { - aU, _ := untransposeExtract(a) - if rm, ok := aU.(*Dense); ok { - m.checkOverlap(rm.RawMatrix()) - } - } - - var xmat, ymat blas64.Vector - fast := true - xU, _ := untransposeExtract(x) - if rv, ok := xU.(*VecDense); ok { - r, c := xU.Dims() - xmat = rv.mat - m.checkOverlap(generalFromVector(xmat, r, c)) - } else { - fast = false - } - yU, _ := untransposeExtract(y) - if rv, ok := yU.(*VecDense); ok { - r, c := yU.Dims() - ymat = rv.mat - m.checkOverlap(generalFromVector(ymat, r, c)) - } else { - fast = false - } - - if fast { - if m != a { - m.reuseAsNonZeroed(ar, ac) - m.Copy(a) - } - blas64.Ger(alpha, xmat, ymat, m.mat) - return - } - - m.reuseAsNonZeroed(ar, ac) - for i := 0; i < ar; i++ { - for j := 0; j < ac; j++ { - m.set(i, j, a.At(i, j)+alpha*x.AtVec(i)*y.AtVec(j)) - } - } -} - -// Outer calculates the outer product of the vectors x and y, where x and y -// are treated as column vectors, and stores the result in the receiver. -// -// m = alpha * x * yᵀ -// -// In order to update an existing matrix, see RankOne. -func (m *Dense) Outer(alpha float64, x, y Vector) { - r, c := x.Len(), y.Len() - - m.reuseAsZeroed(r, c) - - var xmat, ymat blas64.Vector - fast := true - xU, _ := untransposeExtract(x) - if rv, ok := xU.(*VecDense); ok { - r, c := xU.Dims() - xmat = rv.mat - m.checkOverlap(generalFromVector(xmat, r, c)) - } else { - fast = false - } - yU, _ := untransposeExtract(y) - if rv, ok := yU.(*VecDense); ok { - r, c := yU.Dims() - ymat = rv.mat - m.checkOverlap(generalFromVector(ymat, r, c)) - } else { - fast = false - } - - if fast { - for i := 0; i < r; i++ { - zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) - } - blas64.Ger(alpha, xmat, ymat, m.mat) - return - } - - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - m.set(i, j, alpha*x.AtVec(i)*y.AtVec(j)) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/diagonal.go b/vendor/gonum.org/v1/gonum/mat/diagonal.go deleted file mode 100644 index c42f70c8..00000000 --- a/vendor/gonum.org/v1/gonum/mat/diagonal.go +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright ©2018 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" -) - -var ( - diagDense *DiagDense - _ Matrix = diagDense - _ allMatrix = diagDense - _ denseMatrix = diagDense - _ Diagonal = diagDense - _ MutableDiagonal = diagDense - _ Triangular = diagDense - _ TriBanded = diagDense - _ Symmetric = diagDense - _ SymBanded = diagDense - _ Banded = diagDense - _ RawBander = diagDense - _ RawSymBander = diagDense - - diag Diagonal - _ Matrix = diag - _ Diagonal = diag - _ Triangular = diag - _ TriBanded = diag - _ Symmetric = diag - _ SymBanded = diag - _ Banded = diag -) - -// Diagonal represents a diagonal matrix, that is a square matrix that only -// has non-zero terms on the diagonal. -type Diagonal interface { - Matrix - // Diag returns the number of rows/columns in the matrix. - Diag() int - - // The following interfaces are included in the Diagonal - // interface to allow the use of Diagonal types in - // functions operating on these types. - Banded - SymBanded - Symmetric - Triangular - TriBanded -} - -// MutableDiagonal is a Diagonal matrix whose elements can be set. -type MutableDiagonal interface { - Diagonal - SetDiag(i int, v float64) -} - -// DiagDense represents a diagonal matrix in dense storage format. -type DiagDense struct { - mat blas64.Vector -} - -// NewDiagDense creates a new Diagonal matrix with n rows and n columns. -// The length of data must be n or data must be nil, otherwise NewDiagDense -// will panic. NewDiagDense will panic if n is zero. -func NewDiagDense(n int, data []float64) *DiagDense { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic("mat: negative dimension") - } - if data == nil { - data = make([]float64, n) - } - if len(data) != n { - panic(ErrShape) - } - return &DiagDense{ - mat: blas64.Vector{N: n, Data: data, Inc: 1}, - } -} - -// Diag returns the dimension of the receiver. -func (d *DiagDense) Diag() int { - return d.mat.N -} - -// Dims returns the dimensions of the matrix. -func (d *DiagDense) Dims() (r, c int) { - return d.mat.N, d.mat.N -} - -// T returns the transpose of the matrix. -func (d *DiagDense) T() Matrix { - return d -} - -// TTri returns the transpose of the matrix. Note that Diagonal matrices are -// Upper by default. -func (d *DiagDense) TTri() Triangular { - return TransposeTri{d} -} - -// TBand performs an implicit transpose by returning the receiver inside a -// TransposeBand. -func (d *DiagDense) TBand() Banded { - return TransposeBand{d} -} - -// TTriBand performs an implicit transpose by returning the receiver inside a -// TransposeTriBand. Note that Diagonal matrices are Upper by default. -func (d *DiagDense) TTriBand() TriBanded { - return TransposeTriBand{d} -} - -// Bandwidth returns the upper and lower bandwidths of the matrix. -// These values are always zero for diagonal matrices. -func (d *DiagDense) Bandwidth() (kl, ku int) { - return 0, 0 -} - -// SymmetricDim implements the Symmetric interface. -func (d *DiagDense) SymmetricDim() int { - return d.mat.N -} - -// SymBand returns the number of rows/columns in the matrix, and the size of -// the bandwidth. -func (d *DiagDense) SymBand() (n, k int) { - return d.mat.N, 0 -} - -// Triangle implements the Triangular interface. -func (d *DiagDense) Triangle() (int, TriKind) { - return d.mat.N, Upper -} - -// TriBand returns the number of rows/columns in the matrix, the -// size of the bandwidth, and the orientation. Note that Diagonal matrices are -// Upper by default. -func (d *DiagDense) TriBand() (n, k int, kind TriKind) { - return d.mat.N, 0, Upper -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (d *DiagDense) Reset() { - // No change of Inc or n to 0 may be - // made unless both are set to 0. - d.mat.Inc = 0 - d.mat.N = 0 - d.mat.Data = d.mat.Data[:0] -} - -// Zero sets all of the matrix elements to zero. -func (d *DiagDense) Zero() { - for i := 0; i < d.mat.N; i++ { - d.mat.Data[d.mat.Inc*i] = 0 - } -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (d *DiagDense) DiagView() Diagonal { - return d -} - -// DiagFrom copies the diagonal of m into the receiver. The receiver must -// be min(r, c) long or empty, otherwise DiagFrom will panic. -func (d *DiagDense) DiagFrom(m Matrix) { - n := min(m.Dims()) - d.reuseAsNonZeroed(n) - - var vec blas64.Vector - switch r := m.(type) { - case *DiagDense: - vec = r.mat - case RawBander: - mat := r.RawBand() - vec = blas64.Vector{ - N: n, - Inc: mat.Stride, - Data: mat.Data[mat.KL : (n-1)*mat.Stride+mat.KL+1], - } - case RawMatrixer: - mat := r.RawMatrix() - vec = blas64.Vector{ - N: n, - Inc: mat.Stride + 1, - Data: mat.Data[:(n-1)*mat.Stride+n], - } - case RawSymBander: - mat := r.RawSymBand() - vec = blas64.Vector{ - N: n, - Inc: mat.Stride, - Data: mat.Data[:(n-1)*mat.Stride+1], - } - case RawSymmetricer: - mat := r.RawSymmetric() - vec = blas64.Vector{ - N: n, - Inc: mat.Stride + 1, - Data: mat.Data[:(n-1)*mat.Stride+n], - } - case RawTriBander: - mat := r.RawTriBand() - data := mat.Data - if mat.Uplo == blas.Lower { - data = data[mat.K:] - } - vec = blas64.Vector{ - N: n, - Inc: mat.Stride, - Data: data[:(n-1)*mat.Stride+1], - } - case RawTriangular: - mat := r.RawTriangular() - if mat.Diag == blas.Unit { - for i := 0; i < n; i += d.mat.Inc { - d.mat.Data[i] = 1 - } - return - } - vec = blas64.Vector{ - N: n, - Inc: mat.Stride + 1, - Data: mat.Data[:(n-1)*mat.Stride+n], - } - case RawVectorer: - d.mat.Data[0] = r.RawVector().Data[0] - return - default: - for i := 0; i < n; i++ { - d.setDiag(i, m.At(i, i)) - } - return - } - blas64.Copy(vec, d.mat) -} - -// RawBand returns the underlying data used by the receiver represented -// as a blas64.Band. -// Changes to elements in the receiver following the call will be reflected -// in returned blas64.Band. -func (d *DiagDense) RawBand() blas64.Band { - return blas64.Band{ - Rows: d.mat.N, - Cols: d.mat.N, - KL: 0, - KU: 0, - Stride: d.mat.Inc, - Data: d.mat.Data, - } -} - -// RawSymBand returns the underlying data used by the receiver represented -// as a blas64.SymmetricBand. -// Changes to elements in the receiver following the call will be reflected -// in returned blas64.Band. -func (d *DiagDense) RawSymBand() blas64.SymmetricBand { - return blas64.SymmetricBand{ - N: d.mat.N, - K: 0, - Stride: d.mat.Inc, - Uplo: blas.Upper, - Data: d.mat.Data, - } -} - -// reuseAsNonZeroed resizes an empty diagonal to a r×r diagonal, -// or checks that a non-empty matrix is r×r. -func (d *DiagDense) reuseAsNonZeroed(r int) { - if r == 0 { - panic(ErrZeroLength) - } - if d.IsEmpty() { - d.mat = blas64.Vector{ - Inc: 1, - Data: use(d.mat.Data, r), - } - d.mat.N = r - return - } - if r != d.mat.N { - panic(ErrShape) - } -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (d *DiagDense) IsEmpty() bool { - // It must be the case that d.Dims() returns - // zeros in this case. See comment in Reset(). - return d.mat.Inc == 0 -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrZeroLength if the matrix has zero size. -func (d *DiagDense) Trace() float64 { - if d.IsEmpty() { - panic(ErrZeroLength) - } - rb := d.RawBand() - var tr float64 - for i := 0; i < rb.Rows; i++ { - tr += rb.Data[rb.KL+i*rb.Stride] - } - return tr -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 or Inf - The maximum diagonal element magnitude -// 2 - The Frobenius norm, the square root of the sum of the squares of -// the diagonal elements -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the receiver has zero size. -func (d *DiagDense) Norm(norm float64) float64 { - if d.IsEmpty() { - panic(ErrZeroLength) - } - switch norm { - default: - panic(ErrNormOrder) - case 1, math.Inf(1): - imax := blas64.Iamax(d.mat) - return math.Abs(d.at(imax, imax)) - case 2: - return blas64.Nrm2(d.mat) - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/doc.go b/vendor/gonum.org/v1/gonum/mat/doc.go deleted file mode 100644 index f8c078cf..00000000 --- a/vendor/gonum.org/v1/gonum/mat/doc.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat provides implementations of float64 and complex128 matrix -// structures and linear algebra operations on them. -// -// # Overview -// -// This section provides a quick overview of the mat package. The following -// sections provide more in depth commentary. -// -// mat provides: -// - Interfaces for Matrix classes (Matrix, Symmetric, Triangular) -// - Concrete implementations (Dense, SymDense, TriDense, VecDense) -// - Methods and functions for using matrix data (Add, Trace, SymRankOne) -// - Types for constructing and using matrix factorizations (QR, LU, etc.) -// - The complementary types for complex matrices, CMatrix, CSymDense, etc. -// -// In the documentation below, we use "matrix" as a short-hand for all of -// the FooDense types implemented in this package. We use "Matrix" to -// refer to the Matrix interface. -// -// A matrix may be constructed through the corresponding New function. If no -// backing array is provided the matrix will be initialized to all zeros. -// -// // Allocate a zeroed real matrix of size 3×5 -// zero := mat.NewDense(3, 5, nil) -// -// If a backing data slice is provided, the matrix will have those elements. -// All matrices are stored in row-major format and users should consider -// this when expressing matrix arithmetic to ensure optimal performance. -// -// // Generate a 6×6 matrix of random values. -// data := make([]float64, 36) -// for i := range data { -// data[i] = rand.NormFloat64() -// } -// a := mat.NewDense(6, 6, data) -// -// Operations involving matrix data are implemented as functions when the values -// of the matrix remain unchanged -// -// tr := mat.Trace(a) -// -// and are implemented as methods when the operation modifies the receiver. -// -// zero.Copy(a) -// -// Note that the input arguments to most functions and methods are interfaces -// rather than concrete types `func Trace(Matrix)` rather than -// `func Trace(*Dense)` allowing flexible use of internal and external -// Matrix types. -// -// When a matrix is the destination or receiver for a function or method, -// the operation will panic if the matrix is not the correct size. -// An exception to this is when the destination is empty (see below). -// -// # Empty matrix -// -// An empty matrix is one that has zero size. Empty matrices are used to allow -// the destination of a matrix operation to assume the correct size automatically. -// This operation will re-use the backing data, if available, or will allocate -// new data if necessary. The IsEmpty method returns whether the given matrix -// is empty. The zero-value of a matrix is empty, and is useful for easily -// getting the result of matrix operations. -// -// var c mat.Dense // construct a new zero-value matrix -// c.Mul(a, a) // c is automatically adjusted to be the right size -// -// The Reset method can be used to revert a matrix to an empty matrix. -// Reset should not be used when multiple different matrices share the same backing -// data slice. This can cause unexpected data modifications after being resized. -// An empty matrix can not be sliced even if it does have an adequately sized -// backing data slice, but can be expanded using its Grow method if it exists. -// -// # The Matrix Interfaces -// -// The Matrix interface is the common link between the concrete types of real -// matrices. The Matrix interface is defined by three functions: Dims, which -// returns the dimensions of the Matrix, At, which returns the element in the -// specified location, and T for returning a Transpose (discussed later). All of -// the matrix types can perform these behaviors and so implement the interface. -// Methods and functions are designed to use this interface, so in particular the method -// -// func (m *Dense) Mul(a, b Matrix) -// -// constructs a *Dense from the result of a multiplication with any Matrix types, -// not just *Dense. Where more restrictive requirements must be met, there are also -// additional interfaces like Symmetric and Triangular. For example, in -// -// func (s *SymDense) AddSym(a, b Symmetric) -// -// the Symmetric interface guarantees a symmetric result. -// -// The CMatrix interface plays the same role for complex matrices. The difference -// is that the CMatrix type has the H method instead T, for returning the conjugate -// transpose. -// -// (Conjugate) Transposes -// -// The T method is used for transposition on real matrices, and H is used for -// conjugate transposition on complex matrices. For example, c.Mul(a.T(), b) computes -// c = aᵀ * b. The mat types implement this method implicitly — -// see the Transpose and Conjugate types for more details. Note that some -// operations have a transpose as part of their definition, as in *SymDense.SymOuterK. -// -// # Matrix Factorization -// -// Matrix factorizations, such as the LU decomposition, typically have their own -// specific data storage, and so are each implemented as a specific type. The -// factorization can be computed through a call to Factorize -// -// var lu mat.LU -// lu.Factorize(a) -// -// The elements of the factorization can be extracted through methods on the -// factorized type, for example *LU.UTo. The factorization types can also be used -// directly, as in *Cholesky.SolveTo. Some factorizations can be updated directly, -// without needing to update the original matrix and refactorize, for example with -// *LU.RankOne. -// -// # BLAS and LAPACK -// -// BLAS and LAPACK are the standard APIs for linear algebra routines. Many -// operations in mat are implemented using calls to the wrapper functions -// in gonum/blas/blas64 and gonum/lapack/lapack64 and their complex equivalents. -// By default, blas64 and lapack64 call the native Go implementations of the -// routines. Alternatively, it is possible to use C-based implementations of the -// APIs through the respective cgo packages and the wrapper packages' "Use" -// functions. The Go implementation of LAPACK makes calls through blas64, so if -// a cgo BLAS implementation is registered, the lapack64 calls will be partially -// executed in Go and partially executed in C. -// -// # Type Switching -// -// The Matrix abstraction enables efficiency as well as interoperability. Go's -// type reflection capabilities are used to choose the most efficient routine -// given the specific concrete types. For example, in -// -// c.Mul(a, b) -// -// if a and b both implement RawMatrixer, that is, they can be represented as a -// blas64.General, blas64.Gemm (general matrix multiplication) is called, while -// instead if b is a RawSymmetricer blas64.Symm is used (general-symmetric -// multiplication), and if b is a *VecDense blas64.Gemv is used. -// -// There are many possible type combinations and special cases. No specific guarantees -// are made about the performance of any method, and in particular, note that an -// abstract matrix type may be copied into a concrete type of the corresponding -// value. If there are specific special cases that are needed, please submit a -// pull-request or file an issue. -// -// # Invariants -// -// Matrix input arguments to package functions are never directly modified. If an -// operation changes Matrix data, the mutated matrix will be the receiver of a -// method, or will be the first, dst, argument to a method named with a To suffix. -// -// For convenience, a matrix may be used as both a receiver and as an input, e.g. -// -// a.Pow(a, 6) -// v.SolveVec(a.T(), v) -// -// though in many cases this will cause an allocation (see Element Aliasing). -// An exception to this rule is Copy, which does not allow a.Copy(a.T()). -// -// # Element Aliasing -// -// Most methods in mat modify receiver data. It is forbidden for the modified -// data region of the receiver to overlap the used data area of the input -// arguments. The exception to this rule is when the method receiver is equal to one -// of the input arguments, as in the a.Pow(a, 6) call above, or its implicit transpose. -// -// This prohibition is to help avoid subtle mistakes when the method needs to read -// from and write to the same data region. There are ways to make mistakes using the -// mat API, and mat functions will detect and complain about those. -// There are many ways to make mistakes by excursion from the mat API via -// interaction with raw matrix values. -// -// If you need to read the rest of this section to understand the behavior of -// your program, you are being clever. Don't be clever. If you must be clever, -// blas64 and lapack64 may be used to call the behavior directly. -// -// mat will use the following rules to detect overlap between the receiver and one -// of the inputs: -// - the input implements one of the Raw methods, and -// - the address ranges of the backing data slices overlap, and -// - the strides differ or there is an overlap in the used data elements. -// -// If such an overlap is detected, the method will panic. -// -// The following cases will not panic: -// - the data slices do not overlap, -// - there is pointer identity between the receiver and input values after -// the value has been untransposed if necessary. -// -// mat will not attempt to detect element overlap if the input does not implement a -// Raw method. Method behavior is undefined if there is undetected overlap. -package mat // import "gonum.org/v1/gonum/mat" diff --git a/vendor/gonum.org/v1/gonum/mat/eigen.go b/vendor/gonum.org/v1/gonum/mat/eigen.go deleted file mode 100644 index 859247d8..00000000 --- a/vendor/gonum.org/v1/gonum/mat/eigen.go +++ /dev/null @@ -1,450 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -const ( - badFact = "mat: use without successful factorization" - noVectors = "mat: eigenvectors not computed" -) - -// EigenSym is a type for computing all eigenvalues and, optionally, -// eigenvectors of a symmetric matrix A. -// -// It is a Symmetric matrix represented by its spectral factorization. Once -// computed, this representation is useful for extracting eigenvalues and -// eigenvector, but At is slow. -type EigenSym struct { - vectorsComputed bool - - values []float64 - vectors *Dense -} - -// Dims returns the dimensions of the matrix. -func (e *EigenSym) Dims() (r, c int) { - n := e.SymmetricDim() - return n, n -} - -// SymmetricDim implements the Symmetric interface. -func (e *EigenSym) SymmetricDim() int { - return len(e.values) -} - -// At returns the element at row i, column j of the matrix A. -// -// At will panic if the eigenvectors have not been computed. -func (e *EigenSym) At(i, j int) float64 { - if !e.vectorsComputed { - panic(noVectors) - } - n, _ := e.Dims() - if uint(i) >= uint(n) { - panic(ErrRowAccess) - } - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - - var val float64 - for k := 0; k < n; k++ { - val += e.values[k] * e.vectors.at(i, k) * e.vectors.at(j, k) - } - return val -} - -// T returns the receiver, the transpose of a symmetric matrix. -func (e *EigenSym) T() Matrix { - return e -} - -// Factorize computes the spectral factorization (eigendecomposition) of the -// symmetric matrix A. -// -// The spectral factorization of A can be written as -// -// A = Q * Λ * Qᵀ -// -// where Λ is a diagonal matrix whose entries are the eigenvalues, and Q is an -// orthogonal matrix whose columns are the eigenvectors. -// -// If vectors is false, the eigenvectors are not computed and later calls to -// VectorsTo and At will panic. -// -// Factorize returns whether the factorization succeeded. If it returns false, -// methods that require a successful factorization will panic. -func (e *EigenSym) Factorize(a Symmetric, vectors bool) (ok bool) { - // kill previous decomposition - e.vectorsComputed = false - e.values = e.values[:] - - n := a.SymmetricDim() - sd := NewSymDense(n, nil) - sd.CopySym(a) - - jobz := lapack.EVNone - if vectors { - jobz = lapack.EVCompute - } - w := make([]float64, n) - work := []float64{0} - lapack64.Syev(jobz, sd.mat, w, work, -1) - - work = getFloat64s(int(work[0]), false) - ok = lapack64.Syev(jobz, sd.mat, w, work, len(work)) - putFloat64s(work) - if !ok { - e.vectorsComputed = false - e.values = nil - e.vectors = nil - return false - } - e.vectorsComputed = vectors - e.values = w - e.vectors = NewDense(n, n, sd.mat.Data) - return true -} - -// succFact returns whether the receiver contains a successful factorization. -func (e *EigenSym) succFact() bool { - return len(e.values) != 0 -} - -// Values extracts the eigenvalues of the factorized n×n matrix A in ascending -// order. -// -// If dst is not nil, the values are stored in-place into dst and returned, -// otherwise a new slice is allocated first. If dst is not nil, it must have -// length equal to n. -// -// If the receiver does not contain a successful factorization, Values will -// panic. -func (e *EigenSym) Values(dst []float64) []float64 { - if !e.succFact() { - panic(badFact) - } - if dst == nil { - dst = make([]float64, len(e.values)) - } - if len(dst) != len(e.values) { - panic(ErrSliceLengthMismatch) - } - copy(dst, e.values) - return dst -} - -// RawValues returns the slice storing the eigenvalues of A in ascending order. -// -// If the returned slice is modified, the factorization is invalid and should -// not be used. -// -// If the receiver does not contain a successful factorization, RawValues will -// return nil. -func (e *EigenSym) RawValues() []float64 { - if !e.succFact() { - return nil - } - return e.values -} - -// VectorsTo stores the orthonormal eigenvectors of the factorized n×n matrix A -// into the columns of dst. -// -// If dst is empty, VectorsTo will resize dst to be n×n. When dst is non-empty, -// VectorsTo will panic if dst is not n×n. VectorsTo will also panic if the -// eigenvectors were not computed during the factorization, or if the receiver -// does not contain a successful factorization. -func (e *EigenSym) VectorsTo(dst *Dense) { - if !e.succFact() { - panic(badFact) - } - if !e.vectorsComputed { - panic(noVectors) - } - r, c := e.vectors.Dims() - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - dst.Copy(e.vectors) -} - -// RawQ returns the orthogonal matrix Q from the spectral factorization of the -// original matrix A -// -// A = Q * Λ * Qᵀ -// -// The columns of Q contain the eigenvectors of A. -// -// If the returned matrix is modified, the factorization is invalid and should -// not be used. -// -// If the receiver does not contain a successful factorization or eigenvectors -// not computed, RawU will return nil. -func (e *EigenSym) RawQ() Matrix { - if !e.succFact() || !e.vectorsComputed { - return nil - } - return e.vectors -} - -// EigenKind specifies the computation of eigenvectors during factorization. -type EigenKind int - -const ( - // EigenNone specifies to not compute any eigenvectors. - EigenNone EigenKind = 0 - // EigenLeft specifies to compute the left eigenvectors. - EigenLeft EigenKind = 1 << iota - // EigenRight specifies to compute the right eigenvectors. - EigenRight - // EigenBoth is a convenience value for computing both eigenvectors. - EigenBoth EigenKind = EigenLeft | EigenRight -) - -// Eigen is a type for creating and using the eigenvalue decomposition of a dense matrix. -type Eigen struct { - n int // The size of the factorized matrix. - - kind EigenKind - - values []complex128 - rVectors *CDense - lVectors *CDense -} - -// succFact returns whether the receiver contains a successful factorization. -func (e *Eigen) succFact() bool { - return e.n != 0 -} - -// Factorize computes the eigenvalues of the square matrix a, and optionally -// the eigenvectors. -// -// A right eigenvalue/eigenvector combination is defined by -// -// A * x_r = λ * x_r -// -// where x_r is the column vector called an eigenvector, and λ is the corresponding -// eigenvalue. -// -// Similarly, a left eigenvalue/eigenvector combination is defined by -// -// x_l * A = λ * x_l -// -// The eigenvalues, but not the eigenvectors, are the same for both decompositions. -// -// Typically eigenvectors refer to right eigenvectors. -// -// In all cases, Factorize computes the eigenvalues of the matrix. kind -// specifies which of the eigenvectors, if any, to compute. See the EigenKind -// documentation for more information. -// Eigen panics if the input matrix is not square. -// -// Factorize returns whether the decomposition succeeded. If the decomposition -// failed, methods that require a successful factorization will panic. -func (e *Eigen) Factorize(a Matrix, kind EigenKind) (ok bool) { - // kill previous factorization. - e.n = 0 - e.kind = 0 - // Copy a because it is modified during the Lapack call. - r, c := a.Dims() - if r != c { - panic(ErrShape) - } - var sd Dense - sd.CloneFrom(a) - - left := kind&EigenLeft != 0 - right := kind&EigenRight != 0 - - var vl, vr Dense - jobvl := lapack.LeftEVNone - jobvr := lapack.RightEVNone - if left { - vl = *NewDense(r, r, nil) - jobvl = lapack.LeftEVCompute - } - if right { - vr = *NewDense(c, c, nil) - jobvr = lapack.RightEVCompute - } - - wr := getFloat64s(c, false) - defer putFloat64s(wr) - wi := getFloat64s(c, false) - defer putFloat64s(wi) - - work := []float64{0} - lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, -1) - work = getFloat64s(int(work[0]), false) - first := lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, len(work)) - putFloat64s(work) - - if first != 0 { - e.values = nil - return false - } - e.n = r - e.kind = kind - - // Construct complex eigenvalues from float64 data. - values := make([]complex128, r) - for i, v := range wr { - values[i] = complex(v, wi[i]) - } - e.values = values - - // Construct complex eigenvectors from float64 data. - var cvl, cvr CDense - if left { - cvl = *NewCDense(r, r, nil) - e.complexEigenTo(&cvl, &vl) - e.lVectors = &cvl - } else { - e.lVectors = nil - } - if right { - cvr = *NewCDense(c, c, nil) - e.complexEigenTo(&cvr, &vr) - e.rVectors = &cvr - } else { - e.rVectors = nil - } - return true -} - -// Kind returns the EigenKind of the decomposition. If no decomposition has been -// computed, Kind returns -1. -func (e *Eigen) Kind() EigenKind { - if !e.succFact() { - return -1 - } - return e.kind -} - -// Values extracts the eigenvalues of the factorized matrix. If dst is -// non-nil, the values are stored in-place into dst. In this case -// dst must have length n, otherwise Values will panic. If dst is -// nil, then a new slice will be allocated of the proper length and -// filed with the eigenvalues. -// -// Values panics if the Eigen decomposition was not successful. -func (e *Eigen) Values(dst []complex128) []complex128 { - if !e.succFact() { - panic(badFact) - } - if dst == nil { - dst = make([]complex128, e.n) - } - if len(dst) != e.n { - panic(ErrSliceLengthMismatch) - } - copy(dst, e.values) - return dst -} - -// complexEigenTo extracts the complex eigenvectors from the real matrix d -// and stores them into the complex matrix dst. -// -// The columns of the returned n×n dense matrix contain the eigenvectors of the -// decomposition in the same order as the eigenvalues. -// If the j-th eigenvalue is real, then -// -// dst[:,j] = d[:,j], -// -// and if it is not real, then the elements of the j-th and (j+1)-th columns of d -// form complex conjugate pairs and the eigenvectors are recovered as -// -// dst[:,j] = d[:,j] + i*d[:,j+1], -// dst[:,j+1] = d[:,j] - i*d[:,j+1], -// -// where i is the imaginary unit. -func (e *Eigen) complexEigenTo(dst *CDense, d *Dense) { - r, c := d.Dims() - cr, cc := dst.Dims() - if r != cr { - panic("size mismatch") - } - if c != cc { - panic("size mismatch") - } - for j := 0; j < c; j++ { - if imag(e.values[j]) == 0 { - for i := 0; i < r; i++ { - dst.set(i, j, complex(d.at(i, j), 0)) - } - continue - } - for i := 0; i < r; i++ { - real := d.at(i, j) - imag := d.at(i, j+1) - dst.set(i, j, complex(real, imag)) - dst.set(i, j+1, complex(real, -imag)) - } - j++ - } -} - -// VectorsTo stores the right eigenvectors of the decomposition into the columns -// of dst. The computed eigenvectors are normalized to have Euclidean norm equal -// to 1 and largest component real. -// -// If dst is empty, VectorsTo will resize dst to be n×n. When dst is -// non-empty, VectorsTo will panic if dst is not n×n. VectorsTo will also -// panic if the eigenvectors were not computed during the factorization, -// or if the receiver does not contain a successful factorization. -func (e *Eigen) VectorsTo(dst *CDense) { - if !e.succFact() { - panic(badFact) - } - if e.kind&EigenRight == 0 { - panic(noVectors) - } - if dst.IsEmpty() { - dst.ReuseAs(e.n, e.n) - } else { - r, c := dst.Dims() - if r != e.n || c != e.n { - panic(ErrShape) - } - } - dst.Copy(e.rVectors) -} - -// LeftVectorsTo stores the left eigenvectors of the decomposition into the -// columns of dst. The computed eigenvectors are normalized to have Euclidean -// norm equal to 1 and largest component real. -// -// If dst is empty, LeftVectorsTo will resize dst to be n×n. When dst is -// non-empty, LeftVectorsTo will panic if dst is not n×n. LeftVectorsTo will also -// panic if the left eigenvectors were not computed during the factorization, -// or if the receiver does not contain a successful factorization -func (e *Eigen) LeftVectorsTo(dst *CDense) { - if !e.succFact() { - panic(badFact) - } - if e.kind&EigenLeft == 0 { - panic(noVectors) - } - if dst.IsEmpty() { - dst.ReuseAs(e.n, e.n) - } else { - r, c := dst.Dims() - if r != e.n || c != e.n { - panic(ErrShape) - } - } - dst.Copy(e.lVectors) -} diff --git a/vendor/gonum.org/v1/gonum/mat/errors.go b/vendor/gonum.org/v1/gonum/mat/errors.go deleted file mode 100644 index 641d8162..00000000 --- a/vendor/gonum.org/v1/gonum/mat/errors.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "fmt" - "runtime" - - "gonum.org/v1/gonum/lapack" -) - -// Condition is the condition number of a matrix. The condition -// number is defined as |A| * |A^-1|. -// -// One important use of Condition is during linear solve routines (finding x such -// that A * x = b). The condition number of A indicates the accuracy of -// the computed solution. A Condition error will be returned if the condition -// number of A is sufficiently large. If A is exactly singular to working precision, -// Condition == ∞, and the solve algorithm may have completed early. If Condition -// is large and finite the solve algorithm will be performed, but the computed -// solution may be inaccurate. Due to the nature of finite precision arithmetic, -// the value of Condition is only an approximate test of singularity. -type Condition float64 - -func (c Condition) Error() string { - return fmt.Sprintf("matrix singular or near-singular with condition number %.4e", c) -} - -// ConditionTolerance is the tolerance limit of the condition number. If the -// condition number is above this value, the matrix is considered singular. -const ConditionTolerance = 1e16 - -const ( - // CondNorm is the matrix norm used for computing the condition number by routines - // in the matrix packages. - CondNorm = lapack.MaxRowSum - - // CondNormTrans is the norm used to compute on Aᵀ to get the same result as - // computing CondNorm on A. - CondNormTrans = lapack.MaxColumnSum -) - -const stackTraceBufferSize = 1 << 20 - -// Maybe will recover a panic with a type mat.Error from fn, and return this error -// as the Err field of an ErrorStack. The stack trace for the panicking function will be -// recovered and placed in the StackTrace field. Any other error is re-panicked. -func Maybe(fn func()) (err error) { - defer func() { - if r := recover(); r != nil { - if e, ok := r.(Error); ok { - if e.string == "" { - panic("mat: invalid error") - } - buf := make([]byte, stackTraceBufferSize) - n := runtime.Stack(buf, false) - err = ErrorStack{Err: e, StackTrace: string(buf[:n])} - return - } - panic(r) - } - }() - fn() - return -} - -// MaybeFloat will recover a panic with a type mat.Error from fn, and return this error -// as the Err field of an ErrorStack. The stack trace for the panicking function will be -// recovered and placed in the StackTrace field. Any other error is re-panicked. -func MaybeFloat(fn func() float64) (f float64, err error) { - defer func() { - if r := recover(); r != nil { - if e, ok := r.(Error); ok { - if e.string == "" { - panic("mat: invalid error") - } - buf := make([]byte, stackTraceBufferSize) - n := runtime.Stack(buf, false) - err = ErrorStack{Err: e, StackTrace: string(buf[:n])} - return - } - panic(r) - } - }() - return fn(), nil -} - -// MaybeComplex will recover a panic with a type mat.Error from fn, and return this error -// as the Err field of an ErrorStack. The stack trace for the panicking function will be -// recovered and placed in the StackTrace field. Any other error is re-panicked. -func MaybeComplex(fn func() complex128) (f complex128, err error) { - defer func() { - if r := recover(); r != nil { - if e, ok := r.(Error); ok { - if e.string == "" { - panic("mat: invalid error") - } - buf := make([]byte, stackTraceBufferSize) - n := runtime.Stack(buf, false) - err = ErrorStack{Err: e, StackTrace: string(buf[:n])} - return - } - panic(r) - } - }() - return fn(), nil -} - -// Error represents matrix handling errors. These errors can be recovered by Maybe wrappers. -type Error struct{ string } - -func (err Error) Error() string { return err.string } - -var ( - ErrNegativeDimension = Error{"mat: negative dimension"} - ErrIndexOutOfRange = Error{"mat: index out of range"} - ErrReuseNonEmpty = Error{"mat: reuse of non-empty matrix"} - ErrRowAccess = Error{"mat: row index out of range"} - ErrColAccess = Error{"mat: column index out of range"} - ErrVectorAccess = Error{"mat: vector index out of range"} - ErrZeroLength = Error{"mat: zero length in matrix dimension"} - ErrRowLength = Error{"mat: row length mismatch"} - ErrColLength = Error{"mat: col length mismatch"} - ErrSquare = Error{"mat: expect square matrix"} - ErrNormOrder = Error{"mat: invalid norm order for matrix"} - ErrSingular = Error{"mat: matrix is singular"} - ErrShape = Error{"mat: dimension mismatch"} - ErrIllegalStride = Error{"mat: illegal stride"} - ErrPivot = Error{"mat: malformed pivot list"} - ErrTriangle = Error{"mat: triangular storage mismatch"} - ErrTriangleSet = Error{"mat: triangular set out of bounds"} - ErrBandwidth = Error{"mat: bandwidth out of range"} - ErrBandSet = Error{"mat: band set out of bounds"} - ErrDiagSet = Error{"mat: diagonal set out of bounds"} - ErrSliceLengthMismatch = Error{"mat: input slice length mismatch"} - ErrNotPSD = Error{"mat: input not positive symmetric definite"} - ErrFailedEigen = Error{"mat: eigendecomposition not successful"} -) - -// ErrorStack represents matrix handling errors that have been recovered by Maybe wrappers. -type ErrorStack struct { - Err error - - // StackTrace is the stack trace - // recovered by Maybe, MaybeFloat - // or MaybeComplex. - StackTrace string -} - -func (err ErrorStack) Error() string { return err.Err.Error() } - -const badCap = "mat: bad capacity" diff --git a/vendor/gonum.org/v1/gonum/mat/format.go b/vendor/gonum.org/v1/gonum/mat/format.go deleted file mode 100644 index c239ddd3..00000000 --- a/vendor/gonum.org/v1/gonum/mat/format.go +++ /dev/null @@ -1,516 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "fmt" - "strconv" - "strings" -) - -// Formatted returns a fmt.Formatter for the matrix m using the given options. -func Formatted(m Matrix, options ...FormatOption) fmt.Formatter { - f := formatter{ - matrix: m, - dot: '.', - } - for _, o := range options { - o(&f) - } - return f -} - -type formatter struct { - matrix Matrix - prefix string - margin int - dot byte - squeeze bool - - format func(m Matrix, prefix string, margin int, dot byte, squeeze bool, fs fmt.State, c rune) -} - -// FormatOption is a functional option for matrix formatting. -type FormatOption func(*formatter) - -// Prefix sets the formatted prefix to the string p. Prefix is a string that is prepended to -// each line of output after the first line. -func Prefix(p string) FormatOption { - return func(f *formatter) { f.prefix = p } -} - -// Excerpt sets the maximum number of rows and columns to print at the margins of the matrix -// to m. If m is zero or less all elements are printed. -func Excerpt(m int) FormatOption { - return func(f *formatter) { f.margin = m } -} - -// DotByte sets the dot character to b. The dot character is used to replace zero elements -// if the result is printed with the fmt ' ' verb flag. Without a DotByte option, the default -// dot character is '.'. -func DotByte(b byte) FormatOption { - return func(f *formatter) { f.dot = b } -} - -// Squeeze sets the printing behavior to minimise column width for each individual column. -func Squeeze() FormatOption { - return func(f *formatter) { f.squeeze = true } -} - -// FormatMATLAB sets the printing behavior to output MATLAB syntax. If MATLAB syntax is -// specified, the ' ' verb flag and Excerpt option are ignored. If the alternative syntax -// verb flag, '#' is used the matrix is formatted in rows and columns. -func FormatMATLAB() FormatOption { - return func(f *formatter) { f.format = formatMATLAB } -} - -// FormatPython sets the printing behavior to output Python syntax. If Python syntax is -// specified, the ' ' verb flag and Excerpt option are ignored. If the alternative syntax -// verb flag, '#' is used the matrix is formatted in rows and columns. -func FormatPython() FormatOption { - return func(f *formatter) { f.format = formatPython } -} - -// Format satisfies the fmt.Formatter interface. -func (f formatter) Format(fs fmt.State, c rune) { - if c == 'v' && fs.Flag('#') && f.format == nil { - fmt.Fprintf(fs, "%#v", f.matrix) - return - } - if f.format == nil { - f.format = format - } - f.format(f.matrix, f.prefix, f.margin, f.dot, f.squeeze, fs, c) -} - -// format prints a pretty representation of m to the fs io.Writer. The format character c -// specifies the numerical representation of elements; valid values are those for float64 -// specified in the fmt package, with their associated flags. In addition to this, a space -// preceding a verb indicates that zero values should be represented by the dot character. -// The printed range of the matrix can be limited by specifying a positive value for margin; -// If margin is greater than zero, only the first and last margin rows/columns of the matrix -// are output. If squeeze is true, column widths are determined on a per-column basis. -// -// format will not provide Go syntax output. -func format(m Matrix, prefix string, margin int, dot byte, squeeze bool, fs fmt.State, c rune) { - rows, cols := m.Dims() - - var printed int - if margin <= 0 { - printed = rows - if cols > printed { - printed = cols - } - } else { - printed = margin - } - - prec, pOk := fs.Precision() - if !pOk { - prec = -1 - } - - var ( - maxWidth int - widths widther - buf, pad []byte - ) - if squeeze { - widths = make(columnWidth, cols) - } else { - widths = new(uniformWidth) - } - switch c { - case 'v', 'e', 'E', 'f', 'F', 'g', 'G': - if c == 'v' { - buf, maxWidth = maxCellWidth(m, 'g', printed, prec, widths) - } else { - buf, maxWidth = maxCellWidth(m, c, printed, prec, widths) - } - default: - fmt.Fprintf(fs, "%%!%c(%T=Dims(%d, %d))", c, m, rows, cols) - return - } - width, _ := fs.Width() - width = max(width, maxWidth) - pad = make([]byte, max(width, 2)) - for i := range pad { - pad[i] = ' ' - } - - first := true - if rows > 2*printed || cols > 2*printed { - first = false - fmt.Fprintf(fs, "Dims(%d, %d)\n", rows, cols) - } - - skipZero := fs.Flag(' ') - for i := 0; i < rows; i++ { - if !first { - fmt.Fprint(fs, prefix) - } - first = false - var el string - switch { - case rows == 1: - fmt.Fprint(fs, "[") - el = "]" - case i == 0: - fmt.Fprint(fs, "⎡") - el = "⎤\n" - case i < rows-1: - fmt.Fprint(fs, "⎢") - el = "⎥\n" - default: - fmt.Fprint(fs, "⎣") - el = "⎦" - } - - for j := 0; j < cols; j++ { - if j >= printed && j < cols-printed { - j = cols - printed - 1 - if i == 0 || i == rows-1 { - fmt.Fprint(fs, "... ... ") - } else { - fmt.Fprint(fs, " ") - } - continue - } - - v := m.At(i, j) - if v == 0 && skipZero { - buf = buf[:1] - buf[0] = dot - } else { - if c == 'v' { - buf = strconv.AppendFloat(buf[:0], v, 'g', prec, 64) - } else { - buf = strconv.AppendFloat(buf[:0], v, byte(c), prec, 64) - } - } - if fs.Flag('-') { - fs.Write(buf) - fs.Write(pad[:widths.width(j)-len(buf)]) - } else { - fs.Write(pad[:widths.width(j)-len(buf)]) - fs.Write(buf) - } - - if j < cols-1 { - fs.Write(pad[:2]) - } - } - - fmt.Fprint(fs, el) - - if i >= printed-1 && i < rows-printed && 2*printed < rows { - i = rows - printed - 1 - fmt.Fprintf(fs, "%s .\n%[1]s .\n%[1]s .\n", prefix) - continue - } - } -} - -// formatMATLAB prints a MATLAB representation of m to the fs io.Writer. The format character c -// specifies the numerical representation of elements; valid values are those for float64 -// specified in the fmt package, with their associated flags. -// The printed range of the matrix can be limited by specifying a positive value for margin; -// If squeeze is true, column widths are determined on a per-column basis. -// -// formatMATLAB will not provide Go syntax output. -func formatMATLAB(m Matrix, prefix string, _ int, _ byte, squeeze bool, fs fmt.State, c rune) { - rows, cols := m.Dims() - - prec, pOk := fs.Precision() - width, _ := fs.Width() - if !fs.Flag('#') { - switch c { - case 'v', 'e', 'E', 'f', 'F', 'g', 'G': - default: - fmt.Fprintf(fs, "%%!%c(%T=Dims(%d, %d))", c, m, rows, cols) - return - } - format := fmtString(fs, c, prec, width) - fs.Write([]byte{'['}) - for i := 0; i < rows; i++ { - if i != 0 { - fs.Write([]byte("; ")) - } - for j := 0; j < cols; j++ { - if j != 0 { - fs.Write([]byte{' '}) - } - fmt.Fprintf(fs, format, m.At(i, j)) - } - } - fs.Write([]byte{']'}) - return - } - - if !pOk { - prec = -1 - } - - printed := rows - if cols > printed { - printed = cols - } - - var ( - maxWidth int - widths widther - buf, pad []byte - ) - if squeeze { - widths = make(columnWidth, cols) - } else { - widths = new(uniformWidth) - } - switch c { - case 'v', 'e', 'E', 'f', 'F', 'g', 'G': - if c == 'v' { - buf, maxWidth = maxCellWidth(m, 'g', printed, prec, widths) - } else { - buf, maxWidth = maxCellWidth(m, c, printed, prec, widths) - } - default: - fmt.Fprintf(fs, "%%!%c(%T=Dims(%d, %d))", c, m, rows, cols) - return - } - width = max(width, maxWidth) - pad = make([]byte, max(width, 1)) - for i := range pad { - pad[i] = ' ' - } - - for i := 0; i < rows; i++ { - var el string - switch { - case rows == 1: - fmt.Fprint(fs, "[") - el = "]" - case i == 0: - fmt.Fprint(fs, "[\n"+prefix+" ") - el = "\n" - case i < rows-1: - fmt.Fprint(fs, prefix+" ") - el = "\n" - default: - fmt.Fprint(fs, prefix+" ") - el = "\n" + prefix + "]" - } - - for j := 0; j < cols; j++ { - v := m.At(i, j) - if c == 'v' { - buf = strconv.AppendFloat(buf[:0], v, 'g', prec, 64) - } else { - buf = strconv.AppendFloat(buf[:0], v, byte(c), prec, 64) - } - if fs.Flag('-') { - fs.Write(buf) - fs.Write(pad[:widths.width(j)-len(buf)]) - } else { - fs.Write(pad[:widths.width(j)-len(buf)]) - fs.Write(buf) - } - - if j < cols-1 { - fs.Write(pad[:1]) - } - } - - fmt.Fprint(fs, el) - } -} - -// formatPython prints a Python representation of m to the fs io.Writer. The format character c -// specifies the numerical representation of elements; valid values are those for float64 -// specified in the fmt package, with their associated flags. -// The printed range of the matrix can be limited by specifying a positive value for margin; -// If squeeze is true, column widths are determined on a per-column basis. -// -// formatPython will not provide Go syntax output. -func formatPython(m Matrix, prefix string, _ int, _ byte, squeeze bool, fs fmt.State, c rune) { - rows, cols := m.Dims() - - prec, pOk := fs.Precision() - width, _ := fs.Width() - if !fs.Flag('#') { - switch c { - case 'v', 'e', 'E', 'f', 'F', 'g', 'G': - default: - fmt.Fprintf(fs, "%%!%c(%T=Dims(%d, %d))", c, m, rows, cols) - return - } - format := fmtString(fs, c, prec, width) - fs.Write([]byte{'['}) - if rows > 1 { - fs.Write([]byte{'['}) - } - for i := 0; i < rows; i++ { - if i != 0 { - fs.Write([]byte("], [")) - } - for j := 0; j < cols; j++ { - if j != 0 { - fs.Write([]byte(", ")) - } - fmt.Fprintf(fs, format, m.At(i, j)) - } - } - if rows > 1 { - fs.Write([]byte{']'}) - } - fs.Write([]byte{']'}) - return - } - - if !pOk { - prec = -1 - } - - printed := rows - if cols > printed { - printed = cols - } - - var ( - maxWidth int - widths widther - buf, pad []byte - ) - if squeeze { - widths = make(columnWidth, cols) - } else { - widths = new(uniformWidth) - } - switch c { - case 'v', 'e', 'E', 'f', 'F', 'g', 'G': - if c == 'v' { - buf, maxWidth = maxCellWidth(m, 'g', printed, prec, widths) - } else { - buf, maxWidth = maxCellWidth(m, c, printed, prec, widths) - } - default: - fmt.Fprintf(fs, "%%!%c(%T=Dims(%d, %d))", c, m, rows, cols) - return - } - width = max(width, maxWidth) - pad = make([]byte, max(width, 1)) - for i := range pad { - pad[i] = ' ' - } - - for i := 0; i < rows; i++ { - if i != 0 { - fmt.Fprint(fs, prefix) - } - var el string - switch { - case rows == 1: - fmt.Fprint(fs, "[") - el = "]" - case i == 0: - fmt.Fprint(fs, "[[") - el = "],\n" - case i < rows-1: - fmt.Fprint(fs, " [") - el = "],\n" - default: - fmt.Fprint(fs, " [") - el = "]]" - } - - for j := 0; j < cols; j++ { - v := m.At(i, j) - if c == 'v' { - buf = strconv.AppendFloat(buf[:0], v, 'g', prec, 64) - } else { - buf = strconv.AppendFloat(buf[:0], v, byte(c), prec, 64) - } - if fs.Flag('-') { - fs.Write(buf) - fs.Write(pad[:widths.width(j)-len(buf)]) - } else { - fs.Write(pad[:widths.width(j)-len(buf)]) - fs.Write(buf) - } - - if j < cols-1 { - fs.Write([]byte{','}) - fs.Write(pad[:1]) - } - } - - fmt.Fprint(fs, el) - } -} - -// This is horrible, but it's what we have. -func fmtString(fs fmt.State, c rune, prec, width int) string { - var b strings.Builder - b.WriteByte('%') - for _, f := range "0+- " { - if fs.Flag(int(f)) { - b.WriteByte(byte(f)) - } - } - if width >= 0 { - fmt.Fprint(&b, width) - } - if prec >= 0 { - b.WriteByte('.') - if prec > 0 { - fmt.Fprint(&b, prec) - } - } - b.WriteRune(c) - return b.String() -} - -func maxCellWidth(m Matrix, c rune, printed, prec int, w widther) ([]byte, int) { - var ( - buf = make([]byte, 0, 64) - rows, cols = m.Dims() - max int - ) - for i := 0; i < rows; i++ { - if i >= printed-1 && i < rows-printed && 2*printed < rows { - i = rows - printed - 1 - continue - } - for j := 0; j < cols; j++ { - if j >= printed && j < cols-printed { - continue - } - - buf = strconv.AppendFloat(buf, m.At(i, j), byte(c), prec, 64) - if len(buf) > max { - max = len(buf) - } - if len(buf) > w.width(j) { - w.setWidth(j, len(buf)) - } - buf = buf[:0] - } - } - return buf, max -} - -type widther interface { - width(i int) int - setWidth(i, w int) -} - -type uniformWidth int - -func (u *uniformWidth) width(_ int) int { return int(*u) } -func (u *uniformWidth) setWidth(_, w int) { *u = uniformWidth(w) } - -type columnWidth []int - -func (c columnWidth) width(i int) int { return c[i] } -func (c columnWidth) setWidth(i, w int) { c[i] = w } diff --git a/vendor/gonum.org/v1/gonum/mat/gsvd.go b/vendor/gonum.org/v1/gonum/mat/gsvd.go deleted file mode 100644 index 02286207..00000000 --- a/vendor/gonum.org/v1/gonum/mat/gsvd.go +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright ©2017 The Gonum 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 mat - -import ( - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/floats" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -// GSVDKind specifies the treatment of singular vectors during a GSVD -// factorization. -type GSVDKind int - -const ( - // GSVDNone specifies that no singular vectors should be computed during - // the decomposition. - GSVDNone GSVDKind = 0 - - // GSVDU specifies that the U singular vectors should be computed during - // the decomposition. - GSVDU GSVDKind = 1 << iota - // GSVDV specifies that the V singular vectors should be computed during - // the decomposition. - GSVDV - // GSVDQ specifies that the Q singular vectors should be computed during - // the decomposition. - GSVDQ - - // GSVDAll is a convenience value for computing all of the singular vectors. - GSVDAll = GSVDU | GSVDV | GSVDQ -) - -// GSVD is a type for creating and using the Generalized Singular Value Decomposition -// (GSVD) of a matrix. -// -// The factorization is a linear transformation of the data sets from the given -// variable×sample spaces to reduced and diagonalized "eigenvariable"×"eigensample" -// spaces. -type GSVD struct { - kind GSVDKind - - r, p, c, k, l int - s1, s2 []float64 - a, b, u, v, q blas64.General - - work []float64 - iwork []int -} - -// succFact returns whether the receiver contains a successful factorization. -func (gsvd *GSVD) succFact() bool { - return gsvd.r != 0 -} - -// Factorize computes the generalized singular value decomposition (GSVD) of the input -// the r×c matrix A and the p×c matrix B. The singular values of A and B are computed -// in all cases, while the singular vectors are optionally computed depending on the -// input kind. -// -// The full singular value decomposition (kind == GSVDAll) deconstructs A and B as -// -// A = U * Σ₁ * [ 0 R ] * Qᵀ -// -// B = V * Σ₂ * [ 0 R ] * Qᵀ -// -// where Σ₁ and Σ₂ are r×(k+l) and p×(k+l) diagonal matrices of singular values, and -// U, V and Q are r×r, p×p and c×c orthogonal matrices of singular vectors. k+l is the -// effective numerical rank of the matrix [ Aᵀ Bᵀ ]ᵀ. -// -// It is frequently not necessary to compute the full GSVD. Computation time and -// storage costs can be reduced using the appropriate kind. Either only the singular -// values can be computed (kind == SVDNone), or in conjunction with specific singular -// vectors (kind bit set according to GSVDU, GSVDV and GSVDQ). -// -// Factorize returns whether the decomposition succeeded. If the decomposition -// failed, routines that require a successful factorization will panic. -func (gsvd *GSVD) Factorize(a, b Matrix, kind GSVDKind) (ok bool) { - // kill the previous decomposition - gsvd.r = 0 - gsvd.kind = 0 - - r, c := a.Dims() - gsvd.r, gsvd.c = r, c - p, c := b.Dims() - gsvd.p = p - if gsvd.c != c { - panic(ErrShape) - } - var jobU, jobV, jobQ lapack.GSVDJob - switch { - default: - panic("gsvd: bad input kind") - case kind == GSVDNone: - jobU = lapack.GSVDNone - jobV = lapack.GSVDNone - jobQ = lapack.GSVDNone - case GSVDAll&kind != 0: - if GSVDU&kind != 0 { - jobU = lapack.GSVDU - gsvd.u = blas64.General{ - Rows: r, - Cols: r, - Stride: r, - Data: use(gsvd.u.Data, r*r), - } - } - if GSVDV&kind != 0 { - jobV = lapack.GSVDV - gsvd.v = blas64.General{ - Rows: p, - Cols: p, - Stride: p, - Data: use(gsvd.v.Data, p*p), - } - } - if GSVDQ&kind != 0 { - jobQ = lapack.GSVDQ - gsvd.q = blas64.General{ - Rows: c, - Cols: c, - Stride: c, - Data: use(gsvd.q.Data, c*c), - } - } - } - - // A and B are destroyed on call, so copy the matrices. - aCopy := DenseCopyOf(a) - bCopy := DenseCopyOf(b) - - gsvd.s1 = use(gsvd.s1, c) - gsvd.s2 = use(gsvd.s2, c) - - gsvd.iwork = useInt(gsvd.iwork, c) - - gsvd.work = use(gsvd.work, 1) - lapack64.Ggsvd3(jobU, jobV, jobQ, aCopy.mat, bCopy.mat, gsvd.s1, gsvd.s2, gsvd.u, gsvd.v, gsvd.q, gsvd.work, -1, gsvd.iwork) - gsvd.work = use(gsvd.work, int(gsvd.work[0])) - gsvd.k, gsvd.l, ok = lapack64.Ggsvd3(jobU, jobV, jobQ, aCopy.mat, bCopy.mat, gsvd.s1, gsvd.s2, gsvd.u, gsvd.v, gsvd.q, gsvd.work, len(gsvd.work), gsvd.iwork) - if ok { - gsvd.a = aCopy.mat - gsvd.b = bCopy.mat - gsvd.kind = kind - } - return ok -} - -// Kind returns the GSVDKind of the decomposition. If no decomposition has been -// computed, Kind returns -1. -func (gsvd *GSVD) Kind() GSVDKind { - if !gsvd.succFact() { - return -1 - } - return gsvd.kind -} - -// Rank returns the k and l terms of the rank of [ Aᵀ Bᵀ ]ᵀ. -func (gsvd *GSVD) Rank() (k, l int) { - return gsvd.k, gsvd.l -} - -// GeneralizedValues returns the generalized singular values of the factorized matrices. -// If the input slice is non-nil, the values will be stored in-place into the slice. -// In this case, the slice must have length min(r,c)-k, and GeneralizedValues will -// panic with ErrSliceLengthMismatch otherwise. If the input slice is nil, -// a new slice of the appropriate length will be allocated and returned. -// -// GeneralizedValues will panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) GeneralizedValues(v []float64) []float64 { - if !gsvd.succFact() { - panic(badFact) - } - r := gsvd.r - c := gsvd.c - k := gsvd.k - d := min(r, c) - if v == nil { - v = make([]float64, d-k) - } - if len(v) != d-k { - panic(ErrSliceLengthMismatch) - } - floats.DivTo(v, gsvd.s1[k:d], gsvd.s2[k:d]) - return v -} - -// ValuesA returns the singular values of the factorized A matrix. -// If the input slice is non-nil, the values will be stored in-place into the slice. -// In this case, the slice must have length min(r,c)-k, and ValuesA will panic with -// ErrSliceLengthMismatch otherwise. If the input slice is nil, -// a new slice of the appropriate length will be allocated and returned. -// -// ValuesA will panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) ValuesA(s []float64) []float64 { - if !gsvd.succFact() { - panic(badFact) - } - r := gsvd.r - c := gsvd.c - k := gsvd.k - d := min(r, c) - if s == nil { - s = make([]float64, d-k) - } - if len(s) != d-k { - panic(ErrSliceLengthMismatch) - } - copy(s, gsvd.s1[k:min(r, c)]) - return s -} - -// ValuesB returns the singular values of the factorized B matrix. -// If the input slice is non-nil, the values will be stored in-place into the slice. -// In this case, the slice must have length min(r,c)-k, and ValuesB will panic with -// ErrSliceLengthMismatch otherwise. If the input slice is nil, -// a new slice of the appropriate length will be allocated and returned. -// -// ValuesB will panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) ValuesB(s []float64) []float64 { - if !gsvd.succFact() { - panic(badFact) - } - r := gsvd.r - c := gsvd.c - k := gsvd.k - d := min(r, c) - if s == nil { - s = make([]float64, d-k) - } - if len(s) != d-k { - panic(ErrSliceLengthMismatch) - } - copy(s, gsvd.s2[k:d]) - return s -} - -// ZeroRTo extracts the matrix [ 0 R ] from the singular value decomposition, -// storing the result into dst. [ 0 R ] is of size (k+l)×c. -// -// If dst is empty, ZeroRTo will resize dst to be (k+l)×c. When dst is -// non-empty, ZeroRTo will panic if dst is not (k+l)×c. ZeroRTo will also panic -// if the receiver does not contain a successful factorization. -func (gsvd *GSVD) ZeroRTo(dst *Dense) { - if !gsvd.succFact() { - panic(badFact) - } - r := gsvd.r - c := gsvd.c - k := gsvd.k - l := gsvd.l - h := min(k+l, r) - if dst.IsEmpty() { - dst.ReuseAs(k+l, c) - } else { - r2, c2 := dst.Dims() - if r2 != k+l || c != c2 { - panic(ErrShape) - } - dst.Zero() - } - a := Dense{ - mat: gsvd.a, - capRows: r, - capCols: c, - } - dst.slice(0, h, c-k-l, c).Copy(a.Slice(0, h, c-k-l, c)) - if r < k+l { - b := Dense{ - mat: gsvd.b, - capRows: gsvd.p, - capCols: c, - } - dst.slice(r, k+l, c+r-k-l, c).Copy(b.Slice(r-k, l, c+r-k-l, c)) - } -} - -// SigmaATo extracts the matrix Σ₁ from the singular value decomposition, storing -// the result into dst. Σ₁ is size r×(k+l). -// -// If dst is empty, SigmaATo will resize dst to be r×(k+l). When dst is -// non-empty, SigmATo will panic if dst is not r×(k+l). SigmaATo will also -// panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) SigmaATo(dst *Dense) { - if !gsvd.succFact() { - panic(badFact) - } - r := gsvd.r - k := gsvd.k - l := gsvd.l - if dst.IsEmpty() { - dst.ReuseAs(r, k+l) - } else { - r2, c := dst.Dims() - if r2 != r || c != k+l { - panic(ErrShape) - } - dst.Zero() - } - for i := 0; i < k; i++ { - dst.set(i, i, 1) - } - for i := k; i < min(r, k+l); i++ { - dst.set(i, i, gsvd.s1[i]) - } -} - -// SigmaBTo extracts the matrix Σ₂ from the singular value decomposition, storing -// the result into dst. Σ₂ is size p×(k+l). -// -// If dst is empty, SigmaBTo will resize dst to be p×(k+l). When dst is -// non-empty, SigmBTo will panic if dst is not p×(k+l). SigmaBTo will also -// panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) SigmaBTo(dst *Dense) { - if !gsvd.succFact() { - panic(badFact) - } - r := gsvd.r - p := gsvd.p - k := gsvd.k - l := gsvd.l - if dst.IsEmpty() { - dst.ReuseAs(p, k+l) - } else { - r, c := dst.Dims() - if r != p || c != k+l { - panic(ErrShape) - } - dst.Zero() - } - for i := 0; i < min(l, r-k); i++ { - dst.set(i, i+k, gsvd.s2[k+i]) - } - for i := r - k; i < l; i++ { - dst.set(i, i+k, 1) - } -} - -// UTo extracts the matrix U from the singular value decomposition, storing -// the result into dst. U is size r×r. -// -// If dst is empty, UTo will resize dst to be r×r. When dst is -// non-empty, UTo will panic if dst is not r×r. UTo will also -// panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) UTo(dst *Dense) { - if !gsvd.succFact() { - panic(badFact) - } - if gsvd.kind&GSVDU == 0 { - panic("mat: improper GSVD kind") - } - r := gsvd.u.Rows - c := gsvd.u.Cols - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - - tmp := &Dense{ - mat: gsvd.u, - capRows: r, - capCols: c, - } - dst.Copy(tmp) -} - -// VTo extracts the matrix V from the singular value decomposition, storing -// the result into dst. V is size p×p. -// -// If dst is empty, VTo will resize dst to be p×p. When dst is -// non-empty, VTo will panic if dst is not p×p. VTo will also -// panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) VTo(dst *Dense) { - if !gsvd.succFact() { - panic(badFact) - } - if gsvd.kind&GSVDV == 0 { - panic("mat: improper GSVD kind") - } - r := gsvd.v.Rows - c := gsvd.v.Cols - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - - tmp := &Dense{ - mat: gsvd.v, - capRows: r, - capCols: c, - } - dst.Copy(tmp) -} - -// QTo extracts the matrix Q from the singular value decomposition, storing -// the result into dst. Q is size c×c. -// -// If dst is empty, QTo will resize dst to be c×c. When dst is -// non-empty, QTo will panic if dst is not c×c. QTo will also -// panic if the receiver does not contain a successful factorization. -func (gsvd *GSVD) QTo(dst *Dense) { - if !gsvd.succFact() { - panic(badFact) - } - if gsvd.kind&GSVDQ == 0 { - panic("mat: improper GSVD kind") - } - r := gsvd.q.Rows - c := gsvd.q.Cols - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - - tmp := &Dense{ - mat: gsvd.q, - capRows: r, - capCols: c, - } - dst.Copy(tmp) -} diff --git a/vendor/gonum.org/v1/gonum/mat/hogsvd.go b/vendor/gonum.org/v1/gonum/mat/hogsvd.go deleted file mode 100644 index 40a03315..00000000 --- a/vendor/gonum.org/v1/gonum/mat/hogsvd.go +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright ©2017 The Gonum 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 mat - -import ( - "errors" - - "gonum.org/v1/gonum/blas/blas64" -) - -// HOGSVD is a type for creating and using the Higher Order Generalized Singular Value -// Decomposition (HOGSVD) of a set of matrices. -// -// The factorization is a linear transformation of the data sets from the given -// variable×sample spaces to reduced and diagonalized "eigenvariable"×"eigensample" -// spaces. -type HOGSVD struct { - n int - v *Dense - b []Dense - - err error -} - -// succFact returns whether the receiver contains a successful factorization. -func (gsvd *HOGSVD) succFact() bool { - return gsvd.n != 0 -} - -// Factorize computes the higher order generalized singular value decomposition (HOGSVD) -// of the n input r_i×c column tall matrices in m. HOGSV extends the GSVD case from 2 to n -// input matrices. -// -// M_0 = U_0 * Σ_0 * Vᵀ -// M_1 = U_1 * Σ_1 * Vᵀ -// . -// . -// . -// M_{n-1} = U_{n-1} * Σ_{n-1} * Vᵀ -// -// where U_i are r_i×c matrices of singular vectors, Σ are c×c matrices singular values, and V -// is a c×c matrix of singular vectors. -// -// Factorize returns whether the decomposition succeeded. If the decomposition -// failed, routines that require a successful factorization will panic. -func (gsvd *HOGSVD) Factorize(m ...Matrix) (ok bool) { - // Factorize performs the HOGSVD factorisation - // essentially as described by Ponnapalli et al. - // https://doi.org/10.1371/journal.pone.0028072 - - if len(m) < 2 { - panic("hogsvd: too few matrices") - } - gsvd.n = 0 - - r, c := m[0].Dims() - a := make([]Cholesky, len(m)) - var ts SymDense - for i, d := range m { - rd, cd := d.Dims() - if rd < cd { - gsvd.err = ErrShape - return false - } - if rd > r { - r = rd - } - if cd != c { - panic(ErrShape) - } - ts.Reset() - ts.SymOuterK(1, d.T()) - ok = a[i].Factorize(&ts) - if !ok { - gsvd.err = errors.New("hogsvd: cholesky decomposition failed") - return false - } - } - - s := getDenseWorkspace(c, c, true) - defer putDenseWorkspace(s) - sij := getDenseWorkspace(c, c, false) - defer putDenseWorkspace(sij) - for i, ai := range a { - for _, aj := range a[i+1:] { - gsvd.err = ai.SolveCholTo(sij, &aj) - if gsvd.err != nil { - return false - } - s.Add(s, sij) - - gsvd.err = aj.SolveCholTo(sij, &ai) - if gsvd.err != nil { - return false - } - s.Add(s, sij) - } - } - s.Scale(1/float64(len(m)*(len(m)-1)), s) - - var eig Eigen - ok = eig.Factorize(s.T(), EigenRight) - if !ok { - gsvd.err = errors.New("hogsvd: eigen decomposition failed") - return false - } - var vc CDense - eig.VectorsTo(&vc) - // vc is guaranteed to have real eigenvalues. - rc, cc := vc.Dims() - v := NewDense(rc, cc, nil) - for i := 0; i < rc; i++ { - for j := 0; j < cc; j++ { - a := vc.At(i, j) - v.set(i, j, real(a)) - } - } - // Rescale the columns of v by their Frobenius norms. - // Work done in cv is reflected in v. - var cv VecDense - for j := 0; j < c; j++ { - cv.ColViewOf(v, j) - cv.ScaleVec(1/blas64.Nrm2(cv.mat), &cv) - } - - b := make([]Dense, len(m)) - biT := getDenseWorkspace(c, r, false) - defer putDenseWorkspace(biT) - for i, d := range m { - // All calls to reset will leave an emptied - // matrix with capacity to store the result - // without additional allocation. - biT.Reset() - gsvd.err = biT.Solve(v, d.T()) - if gsvd.err != nil { - return false - } - b[i].CloneFrom(biT.T()) - } - - gsvd.n = len(m) - gsvd.v = v - gsvd.b = b - return true -} - -// Err returns the reason for a factorization failure. -func (gsvd *HOGSVD) Err() error { - return gsvd.err -} - -// Len returns the number of matrices that have been factorized. If Len returns -// zero, the factorization was not successful. -func (gsvd *HOGSVD) Len() int { - return gsvd.n -} - -// UTo extracts the matrix U_n from the singular value decomposition, storing -// the result in-place into dst. U_n is size r×c. -// -// If dst is empty, UTo will resize dst to be r×c. When dst is -// non-empty, UTo will panic if dst is not r×c. UTo will also -// panic if the receiver does not contain a successful factorization. -func (gsvd *HOGSVD) UTo(dst *Dense, n int) { - if !gsvd.succFact() { - panic(badFact) - } - if n < 0 || gsvd.n <= n { - panic("hogsvd: invalid index") - } - r, c := gsvd.b[n].Dims() - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - dst.Copy(&gsvd.b[n]) - var v VecDense - for j, f := range gsvd.Values(nil, n) { - v.ColViewOf(dst, j) - v.ScaleVec(1/f, &v) - } -} - -// Values returns the nth set of singular values of the factorized system. -// If the input slice is non-nil, the values will be stored in-place into the slice. -// In this case, the slice must have length c, and Values will panic with -// ErrSliceLengthMismatch otherwise. If the input slice is nil, -// a new slice of the appropriate length will be allocated and returned. -// -// Values will panic if the receiver does not contain a successful factorization. -func (gsvd *HOGSVD) Values(s []float64, n int) []float64 { - if !gsvd.succFact() { - panic(badFact) - } - if n < 0 || gsvd.n <= n { - panic("hogsvd: invalid index") - } - - _, c := gsvd.b[n].Dims() - if s == nil { - s = make([]float64, c) - } else if len(s) != c { - panic(ErrSliceLengthMismatch) - } - var v VecDense - for j := 0; j < c; j++ { - v.ColViewOf(&gsvd.b[n], j) - s[j] = blas64.Nrm2(v.mat) - } - return s -} - -// VTo extracts the matrix V from the singular value decomposition, storing -// the result in-place into dst. V is size c×c. -// -// If dst is empty, VTo will resize dst to be c×c. When dst is -// non-empty, VTo will panic if dst is not c×c. VTo will also -// panic if the receiver does not contain a successful factorization. -func (gsvd *HOGSVD) VTo(dst *Dense) { - if !gsvd.succFact() { - panic(badFact) - } - r, c := gsvd.v.Dims() - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - dst.Copy(gsvd.v) -} diff --git a/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go b/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go deleted file mode 100644 index 59a9e047..00000000 --- a/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go +++ /dev/null @@ -1,398 +0,0 @@ -// Copyright ©2014 The Gonum 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 must be kept in sync with index_no_bound_checks.go. - -//go:build bounds -// +build bounds - -package mat - -// At returns the element at row i, column j. -func (m *Dense) At(i, j int) float64 { - return m.at(i, j) -} - -func (m *Dense) at(i, j int) float64 { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - return m.mat.Data[i*m.mat.Stride+j] -} - -// Set sets the element at row i, column j to the value v. -func (m *Dense) Set(i, j int, v float64) { - m.set(i, j, v) -} - -func (m *Dense) set(i, j int, v float64) { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - m.mat.Data[i*m.mat.Stride+j] = v -} - -// At returns the element at row i, column j. -func (m *CDense) At(i, j int) complex128 { - return m.at(i, j) -} - -func (m *CDense) at(i, j int) complex128 { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - return m.mat.Data[i*m.mat.Stride+j] -} - -// Set sets the element at row i, column j to the value v. -func (m *CDense) Set(i, j int, v complex128) { - m.set(i, j, v) -} - -func (m *CDense) set(i, j int, v complex128) { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - m.mat.Data[i*m.mat.Stride+j] = v -} - -// At returns the element at row i. -// It panics if i is out of bounds or if j is not zero. -func (v *VecDense) At(i, j int) float64 { - if j != 0 { - panic(ErrColAccess) - } - return v.at(i) -} - -// AtVec returns the element at row i. -// It panics if i is out of bounds. -func (v *VecDense) AtVec(i int) float64 { - return v.at(i) -} - -func (v *VecDense) at(i int) float64 { - if uint(i) >= uint(v.mat.N) { - panic(ErrRowAccess) - } - return v.mat.Data[i*v.mat.Inc] -} - -// SetVec sets the element at row i to the value val. -// It panics if i is out of bounds. -func (v *VecDense) SetVec(i int, val float64) { - v.setVec(i, val) -} - -func (v *VecDense) setVec(i int, val float64) { - if uint(i) >= uint(v.mat.N) { - panic(ErrVectorAccess) - } - v.mat.Data[i*v.mat.Inc] = val -} - -// At returns the element at row i and column j. -func (t *SymDense) At(i, j int) float64 { - return t.at(i, j) -} - -func (t *SymDense) at(i, j int) float64 { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - if i > j { - i, j = j, i - } - return t.mat.Data[i*t.mat.Stride+j] -} - -// SetSym sets the elements at (i,j) and (j,i) to the value v. -func (t *SymDense) SetSym(i, j int, v float64) { - t.set(i, j, v) -} - -func (t *SymDense) set(i, j int, v float64) { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - if i > j { - i, j = j, i - } - t.mat.Data[i*t.mat.Stride+j] = v -} - -// At returns the element at row i, column j. -func (t *TriDense) At(i, j int) float64 { - return t.at(i, j) -} - -func (t *TriDense) at(i, j int) float64 { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - isUpper := t.isUpper() - if (isUpper && i > j) || (!isUpper && i < j) { - return 0 - } - return t.mat.Data[i*t.mat.Stride+j] -} - -// SetTri sets the element of the triangular matrix at row i, column j to the value v. -// It panics if the location is outside the appropriate half of the matrix. -func (t *TriDense) SetTri(i, j int, v float64) { - t.set(i, j, v) -} - -func (t *TriDense) set(i, j int, v float64) { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - isUpper := t.isUpper() - if (isUpper && i > j) || (!isUpper && i < j) { - panic(ErrTriangleSet) - } - t.mat.Data[i*t.mat.Stride+j] = v -} - -// At returns the element at row i, column j. -func (b *BandDense) At(i, j int) float64 { - return b.at(i, j) -} - -func (b *BandDense) at(i, j int) float64 { - if uint(i) >= uint(b.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(b.mat.Cols) { - panic(ErrColAccess) - } - pj := j + b.mat.KL - i - if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { - return 0 - } - return b.mat.Data[i*b.mat.Stride+pj] -} - -// SetBand sets the element at row i, column j to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (b *BandDense) SetBand(i, j int, v float64) { - b.set(i, j, v) -} - -func (b *BandDense) set(i, j int, v float64) { - if uint(i) >= uint(b.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(b.mat.Cols) { - panic(ErrColAccess) - } - pj := j + b.mat.KL - i - if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { - panic(ErrBandSet) - } - b.mat.Data[i*b.mat.Stride+pj] = v -} - -// At returns the element at row i, column j. -func (s *SymBandDense) At(i, j int) float64 { - return s.at(i, j) -} - -func (s *SymBandDense) at(i, j int) float64 { - if uint(i) >= uint(s.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(s.mat.N) { - panic(ErrColAccess) - } - if i > j { - i, j = j, i - } - pj := j - i - if s.mat.K+1 <= pj { - return 0 - } - return s.mat.Data[i*s.mat.Stride+pj] -} - -// SetSymBand sets the element at row i, column j to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (s *SymBandDense) SetSymBand(i, j int, v float64) { - s.set(i, j, v) -} - -func (s *SymBandDense) set(i, j int, v float64) { - if uint(i) >= uint(s.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(s.mat.N) { - panic(ErrColAccess) - } - if i > j { - i, j = j, i - } - pj := j - i - if s.mat.K+1 <= pj { - panic(ErrBandSet) - } - s.mat.Data[i*s.mat.Stride+pj] = v -} - -func (t *TriBandDense) At(i, j int) float64 { - return t.at(i, j) -} - -func (t *TriBandDense) at(i, j int) float64 { - // TODO(btracey): Support Diag field, see #692. - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - isUpper := t.isUpper() - if (isUpper && i > j) || (!isUpper && i < j) { - return 0 - } - kl, ku := t.mat.K, 0 - if isUpper { - kl, ku = 0, t.mat.K - } - pj := j + kl - i - if pj < 0 || kl+ku+1 <= pj { - return 0 - } - return t.mat.Data[i*t.mat.Stride+pj] -} - -func (t *TriBandDense) SetTriBand(i, j int, v float64) { - t.setTriBand(i, j, v) -} - -func (t *TriBandDense) setTriBand(i, j int, v float64) { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - isUpper := t.isUpper() - if (isUpper && i > j) || (!isUpper && i < j) { - panic(ErrTriangleSet) - } - kl, ku := t.mat.K, 0 - if isUpper { - kl, ku = 0, t.mat.K - } - pj := j + kl - i - if pj < 0 || kl+ku+1 <= pj { - panic(ErrBandSet) - } - // TODO(btracey): Support Diag field, see #692. - t.mat.Data[i*t.mat.Stride+pj] = v -} - -// At returns the element at row i, column j. -func (d *DiagDense) At(i, j int) float64 { - return d.at(i, j) -} - -func (d *DiagDense) at(i, j int) float64 { - if uint(i) >= uint(d.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(d.mat.N) { - panic(ErrColAccess) - } - if i != j { - return 0 - } - return d.mat.Data[i*d.mat.Inc] -} - -// SetDiag sets the element at row i, column i to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (d *DiagDense) SetDiag(i int, v float64) { - d.setDiag(i, v) -} - -func (d *DiagDense) setDiag(i int, v float64) { - if uint(i) >= uint(d.mat.N) { - panic(ErrRowAccess) - } - d.mat.Data[i*d.mat.Inc] = v -} - -// At returns the element at row i, column j. -func (a *Tridiag) At(i, j int) float64 { - return a.at(i, j) -} - -func (a *Tridiag) at(i, j int) float64 { - if uint(i) >= uint(a.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(a.mat.N) { - panic(ErrColAccess) - } - switch i - j { - case -1: - return a.mat.DU[i] - case 0: - return a.mat.D[i] - case 1: - return a.mat.DL[j] - default: - return 0 - } -} - -// SetBand sets the element at row i, column j to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (a *Tridiag) SetBand(i, j int, v float64) { - a.set(i, j, v) -} - -func (a *Tridiag) set(i, j int, v float64) { - if uint(i) >= uint(a.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(a.mat.N) { - panic(ErrColAccess) - } - switch i - j { - case -1: - a.mat.DU[i] = v - case 0: - a.mat.D[i] = v - case 1: - a.mat.DL[j] = v - default: - panic(ErrBandSet) - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go b/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go deleted file mode 100644 index 33512880..00000000 --- a/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright ©2014 The Gonum 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 must be kept in sync with index_bound_checks.go. - -//go:build !bounds -// +build !bounds - -package mat - -// At returns the element at row i, column j. -func (m *Dense) At(i, j int) float64 { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - return m.at(i, j) -} - -func (m *Dense) at(i, j int) float64 { - return m.mat.Data[i*m.mat.Stride+j] -} - -// Set sets the element at row i, column j to the value v. -func (m *Dense) Set(i, j int, v float64) { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - m.set(i, j, v) -} - -func (m *Dense) set(i, j int, v float64) { - m.mat.Data[i*m.mat.Stride+j] = v -} - -// At returns the element at row i, column j. -func (m *CDense) At(i, j int) complex128 { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - return m.at(i, j) -} - -func (m *CDense) at(i, j int) complex128 { - return m.mat.Data[i*m.mat.Stride+j] -} - -// Set sets the element at row i, column j to the value v. -func (m *CDense) Set(i, j int, v complex128) { - if uint(i) >= uint(m.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(m.mat.Cols) { - panic(ErrColAccess) - } - m.set(i, j, v) -} - -func (m *CDense) set(i, j int, v complex128) { - m.mat.Data[i*m.mat.Stride+j] = v -} - -// At returns the element at row i. -// It panics if i is out of bounds or if j is not zero. -func (v *VecDense) At(i, j int) float64 { - if uint(i) >= uint(v.mat.N) { - panic(ErrRowAccess) - } - if j != 0 { - panic(ErrColAccess) - } - return v.at(i) -} - -// AtVec returns the element at row i. -// It panics if i is out of bounds. -func (v *VecDense) AtVec(i int) float64 { - if uint(i) >= uint(v.mat.N) { - panic(ErrRowAccess) - } - return v.at(i) -} - -func (v *VecDense) at(i int) float64 { - return v.mat.Data[i*v.mat.Inc] -} - -// SetVec sets the element at row i to the value val. -// It panics if i is out of bounds. -func (v *VecDense) SetVec(i int, val float64) { - if uint(i) >= uint(v.mat.N) { - panic(ErrVectorAccess) - } - v.setVec(i, val) -} - -func (v *VecDense) setVec(i int, val float64) { - v.mat.Data[i*v.mat.Inc] = val -} - -// At returns the element at row i and column j. -func (s *SymDense) At(i, j int) float64 { - if uint(i) >= uint(s.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(s.mat.N) { - panic(ErrColAccess) - } - return s.at(i, j) -} - -func (s *SymDense) at(i, j int) float64 { - if i > j { - i, j = j, i - } - return s.mat.Data[i*s.mat.Stride+j] -} - -// SetSym sets the elements at (i,j) and (j,i) to the value v. -func (s *SymDense) SetSym(i, j int, v float64) { - if uint(i) >= uint(s.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(s.mat.N) { - panic(ErrColAccess) - } - s.set(i, j, v) -} - -func (s *SymDense) set(i, j int, v float64) { - if i > j { - i, j = j, i - } - s.mat.Data[i*s.mat.Stride+j] = v -} - -// At returns the element at row i, column j. -func (t *TriDense) At(i, j int) float64 { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - return t.at(i, j) -} - -func (t *TriDense) at(i, j int) float64 { - isUpper := t.triKind() - if (isUpper && i > j) || (!isUpper && i < j) { - return 0 - } - return t.mat.Data[i*t.mat.Stride+j] -} - -// SetTri sets the element at row i, column j to the value v. -// It panics if the location is outside the appropriate half of the matrix. -func (t *TriDense) SetTri(i, j int, v float64) { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - isUpper := t.isUpper() - if (isUpper && i > j) || (!isUpper && i < j) { - panic(ErrTriangleSet) - } - t.set(i, j, v) -} - -func (t *TriDense) set(i, j int, v float64) { - t.mat.Data[i*t.mat.Stride+j] = v -} - -// At returns the element at row i, column j. -func (b *BandDense) At(i, j int) float64 { - if uint(i) >= uint(b.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(b.mat.Cols) { - panic(ErrColAccess) - } - return b.at(i, j) -} - -func (b *BandDense) at(i, j int) float64 { - pj := j + b.mat.KL - i - if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { - return 0 - } - return b.mat.Data[i*b.mat.Stride+pj] -} - -// SetBand sets the element at row i, column j to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (b *BandDense) SetBand(i, j int, v float64) { - if uint(i) >= uint(b.mat.Rows) { - panic(ErrRowAccess) - } - if uint(j) >= uint(b.mat.Cols) { - panic(ErrColAccess) - } - pj := j + b.mat.KL - i - if pj < 0 || b.mat.KL+b.mat.KU+1 <= pj { - panic(ErrBandSet) - } - b.set(i, j, v) -} - -func (b *BandDense) set(i, j int, v float64) { - pj := j + b.mat.KL - i - b.mat.Data[i*b.mat.Stride+pj] = v -} - -// At returns the element at row i, column j. -func (s *SymBandDense) At(i, j int) float64 { - if uint(i) >= uint(s.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(s.mat.N) { - panic(ErrColAccess) - } - return s.at(i, j) -} - -func (s *SymBandDense) at(i, j int) float64 { - if i > j { - i, j = j, i - } - pj := j - i - if s.mat.K+1 <= pj { - return 0 - } - return s.mat.Data[i*s.mat.Stride+pj] -} - -// SetSymBand sets the element at row i, column j to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (s *SymBandDense) SetSymBand(i, j int, v float64) { - if uint(i) >= uint(s.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(s.mat.N) { - panic(ErrColAccess) - } - s.set(i, j, v) -} - -func (s *SymBandDense) set(i, j int, v float64) { - if i > j { - i, j = j, i - } - pj := j - i - if s.mat.K+1 <= pj { - panic(ErrBandSet) - } - s.mat.Data[i*s.mat.Stride+pj] = v -} - -func (t *TriBandDense) At(i, j int) float64 { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - return t.at(i, j) -} - -func (t *TriBandDense) at(i, j int) float64 { - // TODO(btracey): Support Diag field, see #692. - isUpper := t.isUpper() - if (isUpper && i > j) || (!isUpper && i < j) { - return 0 - } - kl := t.mat.K - ku := 0 - if isUpper { - ku = t.mat.K - kl = 0 - } - pj := j + kl - i - if pj < 0 || kl+ku+1 <= pj { - return 0 - } - return t.mat.Data[i*t.mat.Stride+pj] -} - -func (t *TriBandDense) SetTriBand(i, j int, v float64) { - if uint(i) >= uint(t.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(t.mat.N) { - panic(ErrColAccess) - } - isUpper := t.isUpper() - if (isUpper && i > j) || (!isUpper && i < j) { - panic(ErrTriangleSet) - } - kl, ku := t.mat.K, 0 - if isUpper { - kl, ku = 0, t.mat.K - } - pj := j + kl - i - if pj < 0 || kl+ku+1 <= pj { - panic(ErrBandSet) - } - // TODO(btracey): Support Diag field, see #692. - t.mat.Data[i*t.mat.Stride+pj] = v -} - -// At returns the element at row i, column j. -func (d *DiagDense) At(i, j int) float64 { - if uint(i) >= uint(d.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(d.mat.N) { - panic(ErrColAccess) - } - return d.at(i, j) -} - -func (d *DiagDense) at(i, j int) float64 { - if i != j { - return 0 - } - return d.mat.Data[i*d.mat.Inc] -} - -// SetDiag sets the element at row i, column i to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (d *DiagDense) SetDiag(i int, v float64) { - if uint(i) >= uint(d.mat.N) { - panic(ErrRowAccess) - } - d.setDiag(i, v) -} - -func (d *DiagDense) setDiag(i int, v float64) { - d.mat.Data[i*d.mat.Inc] = v -} - -// At returns the element at row i, column j. -func (a *Tridiag) At(i, j int) float64 { - if uint(i) >= uint(a.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(a.mat.N) { - panic(ErrColAccess) - } - return a.at(i, j) -} - -func (a *Tridiag) at(i, j int) float64 { - switch i - j { - case -1: - return a.mat.DU[i] - case 0: - return a.mat.D[i] - case 1: - return a.mat.DL[j] - default: - return 0 - } -} - -// SetBand sets the element at row i, column j to the value v. -// It panics if the location is outside the appropriate region of the matrix. -func (a *Tridiag) SetBand(i, j int, v float64) { - if uint(i) >= uint(a.mat.N) { - panic(ErrRowAccess) - } - if uint(j) >= uint(a.mat.N) { - panic(ErrColAccess) - } - a.set(i, j, v) -} - -func (a *Tridiag) set(i, j int, v float64) { - switch i - j { - case -1: - a.mat.DU[i] = v - case 0: - a.mat.D[i] = v - case 1: - a.mat.DL[j] = v - default: - panic(ErrBandSet) - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/inner.go b/vendor/gonum.org/v1/gonum/mat/inner.go deleted file mode 100644 index 4f94a96a..00000000 --- a/vendor/gonum.org/v1/gonum/mat/inner.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright ©2014 The Gonum 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 mat - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/internal/asm/f64" -) - -// Inner computes the generalized inner product -// -// xᵀ A y -// -// between the vectors x and y with matrix A, where x and y are treated as -// column vectors. -// -// This is only a true inner product if A is symmetric positive definite, though -// the operation works for any matrix A. -// -// Inner panics if x.Len != m or y.Len != n when A is an m x n matrix. -func Inner(x Vector, a Matrix, y Vector) float64 { - m, n := a.Dims() - if x.Len() != m { - panic(ErrShape) - } - if y.Len() != n { - panic(ErrShape) - } - if m == 0 || n == 0 { - return 0 - } - - var sum float64 - - switch a := a.(type) { - case RawSymmetricer: - amat := a.RawSymmetric() - if amat.Uplo != blas.Upper { - // Panic as a string not a mat.Error. - panic(badSymTriangle) - } - var xmat, ymat blas64.Vector - if xrv, ok := x.(RawVectorer); ok { - xmat = xrv.RawVector() - } else { - break - } - if yrv, ok := y.(RawVectorer); ok { - ymat = yrv.RawVector() - } else { - break - } - for i := 0; i < x.Len(); i++ { - xi := x.AtVec(i) - if xi != 0 { - if ymat.Inc == 1 { - sum += xi * f64.DotUnitary( - amat.Data[i*amat.Stride+i:i*amat.Stride+n], - ymat.Data[i:], - ) - } else { - sum += xi * f64.DotInc( - amat.Data[i*amat.Stride+i:i*amat.Stride+n], - ymat.Data[i*ymat.Inc:], uintptr(n-i), - 1, uintptr(ymat.Inc), - 0, 0, - ) - } - } - yi := y.AtVec(i) - if i != n-1 && yi != 0 { - if xmat.Inc == 1 { - sum += yi * f64.DotUnitary( - amat.Data[i*amat.Stride+i+1:i*amat.Stride+n], - xmat.Data[i+1:], - ) - } else { - sum += yi * f64.DotInc( - amat.Data[i*amat.Stride+i+1:i*amat.Stride+n], - xmat.Data[(i+1)*xmat.Inc:], uintptr(n-i-1), - 1, uintptr(xmat.Inc), - 0, 0, - ) - } - } - } - return sum - case RawMatrixer: - amat := a.RawMatrix() - var ymat blas64.Vector - if yrv, ok := y.(RawVectorer); ok { - ymat = yrv.RawVector() - } else { - break - } - for i := 0; i < x.Len(); i++ { - xi := x.AtVec(i) - if xi != 0 { - if ymat.Inc == 1 { - sum += xi * f64.DotUnitary( - amat.Data[i*amat.Stride:i*amat.Stride+n], - ymat.Data, - ) - } else { - sum += xi * f64.DotInc( - amat.Data[i*amat.Stride:i*amat.Stride+n], - ymat.Data, uintptr(n), - 1, uintptr(ymat.Inc), - 0, 0, - ) - } - } - } - return sum - } - for i := 0; i < x.Len(); i++ { - xi := x.AtVec(i) - for j := 0; j < y.Len(); j++ { - sum += xi * a.At(i, j) * y.AtVec(j) - } - } - return sum -} diff --git a/vendor/gonum.org/v1/gonum/mat/io.go b/vendor/gonum.org/v1/gonum/mat/io.go deleted file mode 100644 index 0641fa28..00000000 --- a/vendor/gonum.org/v1/gonum/mat/io.go +++ /dev/null @@ -1,495 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "math" -) - -// version is the current on-disk codec version. -const version uint32 = 0x1 - -// maxLen is the biggest slice/array len one can create on a 32/64b platform. -const maxLen = int64(int(^uint(0) >> 1)) - -var ( - headerSize = binary.Size(storage{}) - sizeFloat64 = binary.Size(float64(0)) - - errWrongType = errors.New("mat: wrong data type") - - errTooBig = errors.New("mat: resulting data slice too big") - errTooSmall = errors.New("mat: input slice too small") - errBadBuffer = errors.New("mat: data buffer size mismatch") - errBadSize = errors.New("mat: invalid dimension") -) - -// Type encoding scheme: -// -// Type Form Packing Uplo Unit Rows Columns kU kL -// uint8 [GST] uint8 [BPF] uint8 [AUL] bool int64 int64 int64 int64 -// General 'G' 'F' 'A' false r c 0 0 -// Band 'G' 'B' 'A' false r c kU kL -// Symmetric 'S' 'F' ul false n n 0 0 -// SymmetricBand 'S' 'B' ul false n n k k -// SymmetricPacked 'S' 'P' ul false n n 0 0 -// Triangular 'T' 'F' ul Diag==Unit n n 0 0 -// TriangularBand 'T' 'B' ul Diag==Unit n n k k -// TriangularPacked 'T' 'P' ul Diag==Unit n n 0 0 -// -// G - general, S - symmetric, T - triangular -// F - full, B - band, P - packed -// A - all, U - upper, L - lower - -// MarshalBinary encodes the receiver into a binary form and returns the result. -// -// Dense is little-endian encoded as follows: -// -// 0 - 3 Version = 1 (uint32) -// 4 'G' (byte) -// 5 'F' (byte) -// 6 'A' (byte) -// 7 0 (byte) -// 8 - 15 number of rows (int64) -// 16 - 23 number of columns (int64) -// 24 - 31 0 (int64) -// 32 - 39 0 (int64) -// 40 - .. matrix data elements (float64) -// [0,0] [0,1] ... [0,ncols-1] -// [1,0] [1,1] ... [1,ncols-1] -// ... -// [nrows-1,0] ... [nrows-1,ncols-1] -func (m Dense) MarshalBinary() ([]byte, error) { - bufLen := int64(headerSize) + int64(m.mat.Rows)*int64(m.mat.Cols)*int64(sizeFloat64) - if bufLen <= 0 { - // bufLen is too big and has wrapped around. - return nil, errTooBig - } - - header := storage{ - Form: 'G', Packing: 'F', Uplo: 'A', - Rows: int64(m.mat.Rows), Cols: int64(m.mat.Cols), - Version: version, - } - buf := make([]byte, bufLen) - n, err := header.marshalBinaryTo(bytes.NewBuffer(buf[:0])) - if err != nil { - return buf[:n], err - } - - p := headerSize - r, c := m.Dims() - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - binary.LittleEndian.PutUint64(buf[p:p+sizeFloat64], math.Float64bits(m.at(i, j))) - p += sizeFloat64 - } - } - - return buf, nil -} - -// MarshalBinaryTo encodes the receiver into a binary form and writes it into w. -// MarshalBinaryTo returns the number of bytes written into w and an error, if any. -// -// See MarshalBinary for the on-disk layout. -func (m Dense) MarshalBinaryTo(w io.Writer) (int, error) { - header := storage{ - Form: 'G', Packing: 'F', Uplo: 'A', - Rows: int64(m.mat.Rows), Cols: int64(m.mat.Cols), - Version: version, - } - n, err := header.marshalBinaryTo(w) - if err != nil { - return n, err - } - - r, c := m.Dims() - var b [8]byte - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - binary.LittleEndian.PutUint64(b[:], math.Float64bits(m.at(i, j))) - nn, err := w.Write(b[:]) - n += nn - if err != nil { - return n, err - } - } - } - - return n, nil -} - -// UnmarshalBinary decodes the binary form into the receiver. -// It panics if the receiver is a non-empty Dense matrix. -// -// See MarshalBinary for the on-disk layout. -// -// Limited checks on the validity of the binary input are performed: -// - ErrShape is returned if the number of rows or columns is negative, -// - an error is returned if the resulting Dense matrix is too -// big for the current architecture (e.g. a 16GB matrix written by a -// 64b application and read back from a 32b application.) -// -// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so -// it should not be used on untrusted data. -func (m *Dense) UnmarshalBinary(data []byte) error { - if !m.IsEmpty() { - panic("mat: unmarshal into non-empty matrix") - } - - if len(data) < headerSize { - return errTooSmall - } - - var header storage - err := header.unmarshalBinary(data[:headerSize]) - if err != nil { - return err - } - rows := header.Rows - cols := header.Cols - header.Version = 0 - header.Rows = 0 - header.Cols = 0 - if (header != storage{Form: 'G', Packing: 'F', Uplo: 'A'}) { - return errWrongType - } - if rows < 0 || cols < 0 { - return errBadSize - } - size := rows * cols - if size == 0 { - return ErrZeroLength - } - if int(size) < 0 || size > maxLen { - return errTooBig - } - if len(data) != headerSize+int(rows*cols)*sizeFloat64 { - return errBadBuffer - } - - p := headerSize - m.reuseAsNonZeroed(int(rows), int(cols)) - for i := range m.mat.Data { - m.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[p : p+sizeFloat64])) - p += sizeFloat64 - } - - return nil -} - -// UnmarshalBinaryFrom decodes the binary form into the receiver and returns -// the number of bytes read and an error if any. -// It panics if the receiver is a non-empty Dense matrix. -// -// See MarshalBinary for the on-disk layout. -// -// Limited checks on the validity of the binary input are performed: -// - ErrShape is returned if the number of rows or columns is negative, -// - an error is returned if the resulting Dense matrix is too -// big for the current architecture (e.g. a 16GB matrix written by a -// 64b application and read back from a 32b application.) -// -// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so -// it should not be used on untrusted data. -func (m *Dense) UnmarshalBinaryFrom(r io.Reader) (int, error) { - if !m.IsEmpty() { - panic("mat: unmarshal into non-empty matrix") - } - - var header storage - n, err := header.unmarshalBinaryFrom(r) - if err != nil { - return n, err - } - rows := header.Rows - cols := header.Cols - header.Version = 0 - header.Rows = 0 - header.Cols = 0 - if (header != storage{Form: 'G', Packing: 'F', Uplo: 'A'}) { - return n, errWrongType - } - if rows < 0 || cols < 0 { - return n, errBadSize - } - size := rows * cols - if size == 0 { - return n, ErrZeroLength - } - if int(size) < 0 || size > maxLen { - return n, errTooBig - } - - m.reuseAsNonZeroed(int(rows), int(cols)) - var b [8]byte - for i := range m.mat.Data { - nn, err := readFull(r, b[:]) - n += nn - if err != nil { - if err == io.EOF { - return n, io.ErrUnexpectedEOF - } - return n, err - } - m.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(b[:])) - } - - return n, nil -} - -// MarshalBinary encodes the receiver into a binary form and returns the result. -// -// VecDense is little-endian encoded as follows: -// -// 0 - 3 Version = 1 (uint32) -// 4 'G' (byte) -// 5 'F' (byte) -// 6 'A' (byte) -// 7 0 (byte) -// 8 - 15 number of elements (int64) -// 16 - 23 1 (int64) -// 24 - 31 0 (int64) -// 32 - 39 0 (int64) -// 40 - .. vector's data elements (float64) -func (v VecDense) MarshalBinary() ([]byte, error) { - bufLen := int64(headerSize) + int64(v.mat.N)*int64(sizeFloat64) - if bufLen <= 0 { - // bufLen is too big and has wrapped around. - return nil, errTooBig - } - - header := storage{ - Form: 'G', Packing: 'F', Uplo: 'A', - Rows: int64(v.mat.N), Cols: 1, - Version: version, - } - buf := make([]byte, bufLen) - n, err := header.marshalBinaryTo(bytes.NewBuffer(buf[:0])) - if err != nil { - return buf[:n], err - } - - p := headerSize - for i := 0; i < v.mat.N; i++ { - binary.LittleEndian.PutUint64(buf[p:p+sizeFloat64], math.Float64bits(v.at(i))) - p += sizeFloat64 - } - - return buf, nil -} - -// MarshalBinaryTo encodes the receiver into a binary form, writes it to w and -// returns the number of bytes written and an error if any. -// -// See MarshalBinary for the on-disk format. -func (v VecDense) MarshalBinaryTo(w io.Writer) (int, error) { - header := storage{ - Form: 'G', Packing: 'F', Uplo: 'A', - Rows: int64(v.mat.N), Cols: 1, - Version: version, - } - n, err := header.marshalBinaryTo(w) - if err != nil { - return n, err - } - - var buf [8]byte - for i := 0; i < v.mat.N; i++ { - binary.LittleEndian.PutUint64(buf[:], math.Float64bits(v.at(i))) - nn, err := w.Write(buf[:]) - n += nn - if err != nil { - return n, err - } - } - - return n, nil -} - -// UnmarshalBinary decodes the binary form into the receiver. -// It panics if the receiver is a non-empty VecDense. -// -// See MarshalBinary for the on-disk layout. -// -// Limited checks on the validity of the binary input are performed: -// - ErrShape is returned if the number of rows is negative, -// - an error is returned if the resulting VecDense is too -// big for the current architecture (e.g. a 16GB vector written by a -// 64b application and read back from a 32b application.) -// -// UnmarshalBinary does not limit the size of the unmarshaled vector, and so -// it should not be used on untrusted data. -func (v *VecDense) UnmarshalBinary(data []byte) error { - if !v.IsEmpty() { - panic("mat: unmarshal into non-empty vector") - } - - if len(data) < headerSize { - return errTooSmall - } - - var header storage - err := header.unmarshalBinary(data[:headerSize]) - if err != nil { - return err - } - if header.Cols != 1 { - return ErrShape - } - n := header.Rows - header.Version = 0 - header.Rows = 0 - header.Cols = 0 - if (header != storage{Form: 'G', Packing: 'F', Uplo: 'A'}) { - return errWrongType - } - if n == 0 { - return ErrZeroLength - } - if n < 0 { - return errBadSize - } - if int64(maxLen) < n { - return errTooBig - } - if len(data) != headerSize+int(n)*sizeFloat64 { - return errBadBuffer - } - - p := headerSize - v.reuseAsNonZeroed(int(n)) - for i := range v.mat.Data { - v.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[p : p+sizeFloat64])) - p += sizeFloat64 - } - - return nil -} - -// UnmarshalBinaryFrom decodes the binary form into the receiver, from the -// io.Reader and returns the number of bytes read and an error if any. -// It panics if the receiver is a non-empty VecDense. -// -// See MarshalBinary for the on-disk layout. -// See UnmarshalBinary for the list of sanity checks performed on the input. -func (v *VecDense) UnmarshalBinaryFrom(r io.Reader) (int, error) { - if !v.IsEmpty() { - panic("mat: unmarshal into non-empty vector") - } - - var header storage - n, err := header.unmarshalBinaryFrom(r) - if err != nil { - return n, err - } - if header.Cols != 1 { - return n, ErrShape - } - l := header.Rows - header.Version = 0 - header.Rows = 0 - header.Cols = 0 - if (header != storage{Form: 'G', Packing: 'F', Uplo: 'A'}) { - return n, errWrongType - } - if l == 0 { - return n, ErrZeroLength - } - if l < 0 { - return n, errBadSize - } - if int64(maxLen) < l { - return n, errTooBig - } - - v.reuseAsNonZeroed(int(l)) - var b [8]byte - for i := range v.mat.Data { - nn, err := readFull(r, b[:]) - n += nn - if err != nil { - if err == io.EOF { - return n, io.ErrUnexpectedEOF - } - return n, err - } - v.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(b[:])) - } - - return n, nil -} - -// storage is the internal representation of the storage format of a -// serialised matrix. -type storage struct { - Version uint32 // Keep this first. - Form byte // [GST] - Packing byte // [BPF] - Uplo byte // [AUL] - Unit bool - Rows int64 - Cols int64 - KU int64 - KL int64 -} - -// TODO(kortschak): Consider replacing these with calls to direct -// encoding/decoding of fields rather than to binary.Write/binary.Read. - -func (s storage) marshalBinaryTo(w io.Writer) (int, error) { - buf := bytes.NewBuffer(make([]byte, 0, headerSize)) - err := binary.Write(buf, binary.LittleEndian, s) - if err != nil { - return 0, err - } - return w.Write(buf.Bytes()) -} - -func (s *storage) unmarshalBinary(buf []byte) error { - err := binary.Read(bytes.NewReader(buf), binary.LittleEndian, s) - if err != nil { - return err - } - if s.Version != version { - return fmt.Errorf("mat: incorrect version: %d", s.Version) - } - return nil -} - -func (s *storage) unmarshalBinaryFrom(r io.Reader) (int, error) { - buf := make([]byte, headerSize) - n, err := readFull(r, buf) - if err != nil { - return n, err - } - return n, s.unmarshalBinary(buf[:n]) -} - -// readFull reads from r into buf until it has read len(buf). -// It returns the number of bytes copied and an error if fewer bytes were read. -// If an EOF happens after reading fewer than len(buf) bytes, io.ErrUnexpectedEOF is returned. -func readFull(r io.Reader, buf []byte) (int, error) { - var n int - var err error - for n < len(buf) && err == nil { - var nn int - nn, err = r.Read(buf[n:]) - n += nn - } - if n == len(buf) { - return n, nil - } - if err == io.EOF { - return n, io.ErrUnexpectedEOF - } - return n, err -} diff --git a/vendor/gonum.org/v1/gonum/mat/lq.go b/vendor/gonum.org/v1/gonum/mat/lq.go deleted file mode 100644 index a3b3543b..00000000 --- a/vendor/gonum.org/v1/gonum/mat/lq.go +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -const badLQ = "mat: invalid LQ factorization" - -// LQ is a type for creating and using the LQ factorization of a matrix. -type LQ struct { - lq *Dense - q *Dense - tau []float64 - cond float64 -} - -// Dims returns the dimensions of the matrix. -func (lq *LQ) Dims() (r, c int) { - if lq.lq == nil { - return 0, 0 - } - return lq.lq.Dims() -} - -// At returns the element at row i, column j. -func (lq *LQ) At(i, j int) float64 { - m, n := lq.Dims() - if uint(i) >= uint(m) { - panic(ErrRowAccess) - } - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - - var val float64 - for k := 0; k <= i; k++ { - val += lq.lq.at(i, k) * lq.q.at(k, j) - } - return val -} - -// T performs an implicit transpose by returning the receiver inside a -// Transpose. -func (lq *LQ) T() Matrix { - return Transpose{lq} -} - -func (lq *LQ) updateCond(norm lapack.MatrixNorm) { - // Since A = L*Q, and Q is orthogonal, we get for the condition number κ - // κ(A) := |A| |A^-1| = |L*Q| |(L*Q)^-1| = |L| |Qᵀ * L^-1| - // = |L| |L^-1| = κ(L), - // where we used that fact that Q^-1 = Qᵀ. However, this assumes that - // the matrix norm is invariant under orthogonal transformations which - // is not the case for CondNorm. Hopefully the error is negligible: κ - // is only a qualitative measure anyway. - m := lq.lq.mat.Rows - work := getFloat64s(3*m, false) - iwork := getInts(m, false) - l := lq.lq.asTriDense(m, blas.NonUnit, blas.Lower) - v := lapack64.Trcon(norm, l.mat, work, iwork) - lq.cond = 1 / v - putFloat64s(work) - putInts(iwork) -} - -// Factorize computes the LQ factorization of an m×n matrix a where m <= n. The LQ -// factorization always exists even if A is singular. -// -// The LQ decomposition is a factorization of the matrix A such that A = L * Q. -// The matrix Q is an orthonormal n×n matrix, and L is an m×n lower triangular matrix. -// L and Q can be extracted using the LTo and QTo methods. -func (lq *LQ) Factorize(a Matrix) { - lq.factorize(a, CondNorm) -} - -func (lq *LQ) factorize(a Matrix, norm lapack.MatrixNorm) { - m, n := a.Dims() - if m > n { - panic(ErrShape) - } - if lq.lq == nil { - lq.lq = &Dense{} - } - lq.lq.CloneFrom(a) - work := []float64{0} - lq.tau = make([]float64, m) - lapack64.Gelqf(lq.lq.mat, lq.tau, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Gelqf(lq.lq.mat, lq.tau, work, len(work)) - putFloat64s(work) - lq.updateCond(norm) - lq.updateQ() -} - -func (lq *LQ) updateQ() { - _, n := lq.Dims() - if lq.q == nil { - lq.q = NewDense(n, n, nil) - } else { - lq.q.reuseAsNonZeroed(n, n) - } - // Construct Q from the elementary reflectors. - lq.q.Copy(lq.lq) - work := []float64{0} - lapack64.Orglq(lq.q.mat, lq.tau, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Orglq(lq.q.mat, lq.tau, work, len(work)) - putFloat64s(work) -} - -// isValid returns whether the receiver contains a factorization. -func (lq *LQ) isValid() bool { - return lq.lq != nil && !lq.lq.IsEmpty() -} - -// Cond returns the condition number for the factorized matrix. -// Cond will panic if the receiver does not contain a factorization. -func (lq *LQ) Cond() float64 { - if !lq.isValid() { - panic(badLQ) - } - return lq.cond -} - -// TODO(btracey): Add in the "Reduced" forms for extracting the m×m orthogonal -// and upper triangular matrices. - -// LTo extracts the m×n lower trapezoidal matrix from a LQ decomposition. -// -// If dst is empty, LTo will resize dst to be r×c. When dst is -// non-empty, LTo will panic if dst is not r×c. LTo will also panic -// if the receiver does not contain a successful factorization. -func (lq *LQ) LTo(dst *Dense) { - if !lq.isValid() { - panic(badLQ) - } - - r, c := lq.lq.Dims() - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - - // Disguise the LQ as a lower triangular. - t := &TriDense{ - mat: blas64.Triangular{ - N: r, - Stride: lq.lq.mat.Stride, - Data: lq.lq.mat.Data, - Uplo: blas.Lower, - Diag: blas.NonUnit, - }, - cap: lq.lq.capCols, - } - dst.Copy(t) - - if r == c { - return - } - // Zero right of the triangular. - for i := 0; i < r; i++ { - zero(dst.mat.Data[i*dst.mat.Stride+r : i*dst.mat.Stride+c]) - } -} - -// QTo extracts the n×n orthonormal matrix Q from an LQ decomposition. -// -// If dst is empty, QTo will resize dst to be n×n. When dst is -// non-empty, QTo will panic if dst is not n×n. QTo will also panic -// if the receiver does not contain a successful factorization. -func (lq *LQ) QTo(dst *Dense) { - if !lq.isValid() { - panic(badLQ) - } - - _, n := lq.lq.Dims() - if dst.IsEmpty() { - dst.ReuseAs(n, n) - } else { - m2, n2 := dst.Dims() - if n != m2 || n != n2 { - panic(ErrShape) - } - } - dst.Copy(lq.q) -} - -// SolveTo finds a minimum-norm solution to a system of linear equations defined -// by the matrices A and b, where A is an m×n matrix represented in its LQ factorized -// form. If A is singular or near-singular a Condition error is returned. -// See the documentation for Condition for more information. -// -// The minimization problem solved depends on the input parameters. -// -// If trans == false, find the minimum norm solution of A * X = B. -// If trans == true, find X such that ||A*X - B||_2 is minimized. -// -// The solution matrix, X, is stored in place into dst. -// SolveTo will panic if the receiver does not contain a factorization. -func (lq *LQ) SolveTo(dst *Dense, trans bool, b Matrix) error { - if !lq.isValid() { - panic(badLQ) - } - - r, c := lq.lq.Dims() - br, bc := b.Dims() - - // The LQ solve algorithm stores the result in-place into the right hand side. - // The storage for the answer must be large enough to hold both b and x. - // However, this method's receiver must be the size of x. Copy b, and then - // copy the result into x at the end. - if trans { - if c != br { - panic(ErrShape) - } - dst.reuseAsNonZeroed(r, bc) - } else { - if r != br { - panic(ErrShape) - } - dst.reuseAsNonZeroed(c, bc) - } - // Do not need to worry about overlap between x and b because w has its own - // independent storage. - w := getDenseWorkspace(max(r, c), bc, false) - w.Copy(b) - t := lq.lq.asTriDense(lq.lq.mat.Rows, blas.NonUnit, blas.Lower).mat - if trans { - work := []float64{0} - lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, w.mat, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, w.mat, work, len(work)) - putFloat64s(work) - - ok := lapack64.Trtrs(blas.Trans, t, w.mat) - if !ok { - return Condition(math.Inf(1)) - } - } else { - ok := lapack64.Trtrs(blas.NoTrans, t, w.mat) - if !ok { - return Condition(math.Inf(1)) - } - for i := r; i < c; i++ { - zero(w.mat.Data[i*w.mat.Stride : i*w.mat.Stride+bc]) - } - work := []float64{0} - lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, w.mat, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, w.mat, work, len(work)) - putFloat64s(work) - } - // x was set above to be the correct size for the result. - dst.Copy(w) - putDenseWorkspace(w) - if lq.cond > ConditionTolerance { - return Condition(lq.cond) - } - return nil -} - -// SolveVecTo finds a minimum-norm solution to a system of linear equations. -// See LQ.SolveTo for the full documentation. -// SolveToVec will panic if the receiver does not contain a factorization. -func (lq *LQ) SolveVecTo(dst *VecDense, trans bool, b Vector) error { - if !lq.isValid() { - panic(badLQ) - } - - r, c := lq.lq.Dims() - if _, bc := b.Dims(); bc != 1 { - panic(ErrShape) - } - - // The Solve implementation is non-trivial, so rather than duplicate the code, - // instead recast the VecDenses as Dense and call the matrix code. - bm := Matrix(b) - if rv, ok := b.(RawVectorer); ok { - bmat := rv.RawVector() - if dst != b { - dst.checkOverlap(bmat) - } - b := VecDense{mat: bmat} - bm = b.asDense() - } - if trans { - dst.reuseAsNonZeroed(r) - } else { - dst.reuseAsNonZeroed(c) - } - return lq.SolveTo(dst.asDense(), trans, bm) -} diff --git a/vendor/gonum.org/v1/gonum/mat/lu.go b/vendor/gonum.org/v1/gonum/mat/lu.go deleted file mode 100644 index b530ada7..00000000 --- a/vendor/gonum.org/v1/gonum/mat/lu.go +++ /dev/null @@ -1,487 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/floats" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -const ( - badSliceLength = "mat: improper slice length" - badLU = "mat: invalid LU factorization" -) - -// LU is a square n×n matrix represented by its LU factorization with partial -// pivoting. -// -// The factorization has the form -// -// A = P * L * U -// -// where P is a permutation matrix, L is lower triangular with unit diagonal -// elements, and U is upper triangular. -// -// Note that this matrix representation is useful for certain operations, in -// particular for solving linear systems of equations. It is very inefficient at -// other operations, in particular At is slow. -type LU struct { - lu *Dense - swaps []int - piv []int - cond float64 - ok bool // Whether A is nonsingular -} - -var _ Matrix = (*LU)(nil) - -// Dims returns the dimensions of the matrix A. -func (lu *LU) Dims() (r, c int) { - if lu.lu == nil { - return 0, 0 - } - return lu.lu.Dims() -} - -// At returns the element of A at row i, column j. -func (lu *LU) At(i, j int) float64 { - n, _ := lu.Dims() - if uint(i) >= uint(n) { - panic(ErrRowAccess) - } - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - - i = lu.piv[i] - var val float64 - for k := 0; k < min(i, j+1); k++ { - val += lu.lu.at(i, k) * lu.lu.at(k, j) - } - if i <= j { - val += lu.lu.at(i, j) - } - return val -} - -// T performs an implicit transpose by returning the receiver inside a -// Transpose. -func (lu *LU) T() Matrix { - return Transpose{lu} -} - -// updateCond updates the stored condition number of the matrix. anorm is the -// norm of the original matrix. If anorm is negative it will be estimated. -func (lu *LU) updateCond(anorm float64, norm lapack.MatrixNorm) { - n := lu.lu.mat.Cols - work := getFloat64s(4*n, false) - defer putFloat64s(work) - iwork := getInts(n, false) - defer putInts(iwork) - if anorm < 0 { - // This is an approximation. By the definition of a norm, - // |AB| <= |A| |B|. - // Since A = L*U, we get for the condition number κ that - // κ(A) := |A| |A^-1| = |L*U| |A^-1| <= |L| |U| |A^-1|, - // so this will overestimate the condition number somewhat. - // The norm of the original factorized matrix cannot be stored - // because of update possibilities. - u := lu.lu.asTriDense(n, blas.NonUnit, blas.Upper) - l := lu.lu.asTriDense(n, blas.Unit, blas.Lower) - unorm := lapack64.Lantr(norm, u.mat, work) - lnorm := lapack64.Lantr(norm, l.mat, work) - anorm = unorm * lnorm - } - v := lapack64.Gecon(norm, lu.lu.mat, anorm, work, iwork) - lu.cond = 1 / v -} - -// Factorize computes the LU factorization of the square matrix A and stores the -// result in the receiver. The LU decomposition will complete regardless of the -// singularity of a. -// -// The L and U matrix factors can be extracted from the factorization using the -// LTo and UTo methods. The matrix P can be extracted as a row permutation using -// the RowPivots method and applied using Dense.PermuteRows. -func (lu *LU) Factorize(a Matrix) { - lu.factorize(a, CondNorm) -} - -func (lu *LU) factorize(a Matrix, norm lapack.MatrixNorm) { - m, n := a.Dims() - if m != n { - panic(ErrSquare) - } - if lu.lu == nil { - lu.lu = NewDense(n, n, nil) - } else { - lu.lu.Reset() - lu.lu.reuseAsNonZeroed(n, n) - } - lu.lu.Copy(a) - lu.swaps = useInt(lu.swaps, n) - lu.piv = useInt(lu.piv, n) - work := getFloat64s(n, false) - anorm := lapack64.Lange(norm, lu.lu.mat, work) - putFloat64s(work) - lu.ok = lapack64.Getrf(lu.lu.mat, lu.swaps) - lu.updatePivots(lu.swaps) - lu.updateCond(anorm, norm) -} - -func (lu *LU) updatePivots(swaps []int) { - // Replay the sequence of row swaps in order to find the row permutation. - for i := range lu.piv { - lu.piv[i] = i - } - n, _ := lu.Dims() - for i := n - 1; i >= 0; i-- { - v := swaps[i] - lu.piv[i], lu.piv[v] = lu.piv[v], lu.piv[i] - } -} - -// isValid returns whether the receiver contains a factorization. -func (lu *LU) isValid() bool { - return lu.lu != nil && !lu.lu.IsEmpty() -} - -// Cond returns the condition number for the factorized matrix. -// Cond will panic if the receiver does not contain a factorization. -func (lu *LU) Cond() float64 { - if !lu.isValid() { - panic(badLU) - } - return lu.cond -} - -// Reset resets the factorization so that it can be reused as the receiver of a -// dimensionally restricted operation. -func (lu *LU) Reset() { - if lu.lu != nil { - lu.lu.Reset() - } - lu.swaps = lu.swaps[:0] - lu.piv = lu.piv[:0] -} - -func (lu *LU) isZero() bool { - return len(lu.swaps) == 0 -} - -// Det returns the determinant of the matrix that has been factorized. In many -// expressions, using LogDet will be more numerically stable. -// Det will panic if the receiver does not contain a factorization. -func (lu *LU) Det() float64 { - if !lu.ok { - return 0 - } - det, sign := lu.LogDet() - return math.Exp(det) * sign -} - -// LogDet returns the log of the determinant and the sign of the determinant -// for the matrix that has been factorized. Numerical stability in product and -// division expressions is generally improved by working in log space. -// LogDet will panic if the receiver does not contain a factorization. -func (lu *LU) LogDet() (det float64, sign float64) { - if !lu.isValid() { - panic(badLU) - } - - _, n := lu.lu.Dims() - logDiag := getFloat64s(n, false) - defer putFloat64s(logDiag) - sign = 1.0 - for i := 0; i < n; i++ { - v := lu.lu.at(i, i) - if v < 0 { - sign *= -1 - } - if lu.swaps[i] != i { - sign *= -1 - } - logDiag[i] = math.Log(math.Abs(v)) - } - return floats.Sum(logDiag), sign -} - -// RowPivots returns the row permutation that represents the permutation matrix -// P from the LU factorization -// -// A = P * L * U. -// -// If dst is nil, a new slice is allocated and returned. If dst is not nil and -// the length of dst does not equal the size of the factorized matrix, RowPivots -// will panic. RowPivots will panic if the receiver does not contain a -// factorization. -func (lu *LU) RowPivots(dst []int) []int { - if !lu.isValid() { - panic(badLU) - } - _, n := lu.lu.Dims() - if dst == nil { - dst = make([]int, n) - } - if len(dst) != n { - panic(badSliceLength) - } - copy(dst, lu.piv) - return dst -} - -// Pivot returns the row pivots of the receiver. -// -// Deprecated: Use RowPivots instead. -func (lu *LU) Pivot(dst []int) []int { - return lu.RowPivots(dst) -} - -// RankOne updates an LU factorization as if a rank-one update had been applied to -// the original matrix A, storing the result into the receiver. That is, if in -// the original LU decomposition P * L * U = A, in the updated decomposition -// P * L' * U' = A + alpha * x * yᵀ. -// RankOne will panic if orig does not contain a factorization. -func (lu *LU) RankOne(orig *LU, alpha float64, x, y Vector) { - if !orig.isValid() { - panic(badLU) - } - - // RankOne uses algorithm a1 on page 28 of "Multiple-Rank Updates to Matrix - // Factorizations for Nonlinear Analysis and Circuit Design" by Linzhong Deng. - // http://web.stanford.edu/group/SOL/dissertations/Linzhong-Deng-thesis.pdf - _, n := orig.lu.Dims() - if r, c := x.Dims(); r != n || c != 1 { - panic(ErrShape) - } - if r, c := y.Dims(); r != n || c != 1 { - panic(ErrShape) - } - if orig != lu { - if lu.isZero() { - lu.swaps = useInt(lu.swaps, n) - lu.piv = useInt(lu.piv, n) - if lu.lu == nil { - lu.lu = NewDense(n, n, nil) - } else { - lu.lu.reuseAsNonZeroed(n, n) - } - } else if len(lu.swaps) != n { - panic(ErrShape) - } - copy(lu.swaps, orig.swaps) - lu.updatePivots(lu.swaps) - lu.lu.Copy(orig.lu) - } - - xs := getFloat64s(n, false) - defer putFloat64s(xs) - ys := getFloat64s(n, false) - defer putFloat64s(ys) - for i := 0; i < n; i++ { - xs[i] = x.AtVec(i) - ys[i] = y.AtVec(i) - } - - // Adjust for the pivoting in the LU factorization - for i, v := range lu.swaps { - xs[i], xs[v] = xs[v], xs[i] - } - - lum := lu.lu.mat - omega := alpha - for j := 0; j < n; j++ { - ujj := lum.Data[j*lum.Stride+j] - ys[j] /= ujj - theta := 1 + xs[j]*ys[j]*omega - beta := omega * ys[j] / theta - gamma := omega * xs[j] - omega -= beta * gamma - lum.Data[j*lum.Stride+j] *= theta - for i := j + 1; i < n; i++ { - xs[i] -= lum.Data[i*lum.Stride+j] * xs[j] - tmp := ys[i] - ys[i] -= lum.Data[j*lum.Stride+i] * ys[j] - lum.Data[i*lum.Stride+j] += beta * xs[i] - lum.Data[j*lum.Stride+i] += gamma * tmp - } - } - lu.updateCond(-1, CondNorm) -} - -// LTo extracts the lower triangular matrix from an LU factorization. -// -// If dst is empty, LTo will resize dst to be a lower-triangular n×n matrix. -// When dst is non-empty, LTo will panic if dst is not n×n or not Lower. -// LTo will also panic if the receiver does not contain a successful -// factorization. -func (lu *LU) LTo(dst *TriDense) *TriDense { - if !lu.isValid() { - panic(badLU) - } - - _, n := lu.lu.Dims() - if dst.IsEmpty() { - dst.ReuseAsTri(n, Lower) - } else { - n2, kind := dst.Triangle() - if n != n2 { - panic(ErrShape) - } - if kind != Lower { - panic(ErrTriangle) - } - } - // Extract the lower triangular elements. - for i := 1; i < n; i++ { - copy(dst.mat.Data[i*dst.mat.Stride:i*dst.mat.Stride+i], lu.lu.mat.Data[i*lu.lu.mat.Stride:i*lu.lu.mat.Stride+i]) - } - // Set ones on the diagonal. - for i := 0; i < n; i++ { - dst.mat.Data[i*dst.mat.Stride+i] = 1 - } - return dst -} - -// UTo extracts the upper triangular matrix from an LU factorization. -// -// If dst is empty, UTo will resize dst to be an upper-triangular n×n matrix. -// When dst is non-empty, UTo will panic if dst is not n×n or not Upper. -// UTo will also panic if the receiver does not contain a successful -// factorization. -func (lu *LU) UTo(dst *TriDense) { - if !lu.isValid() { - panic(badLU) - } - - _, n := lu.lu.Dims() - if dst.IsEmpty() { - dst.ReuseAsTri(n, Upper) - } else { - n2, kind := dst.Triangle() - if n != n2 { - panic(ErrShape) - } - if kind != Upper { - panic(ErrTriangle) - } - } - // Extract the upper triangular elements. - for i := 0; i < n; i++ { - copy(dst.mat.Data[i*dst.mat.Stride+i:i*dst.mat.Stride+n], lu.lu.mat.Data[i*lu.lu.mat.Stride+i:i*lu.lu.mat.Stride+n]) - } -} - -// SolveTo solves a system of linear equations -// -// A * X = B if trans == false -// Aᵀ * X = B if trans == true -// -// using the LU factorization of A stored in the receiver. The solution matrix X -// is stored into dst. -// -// If A is singular or near-singular a Condition error is returned. See the -// documentation for Condition for more information. SolveTo will panic if the -// receiver does not contain a factorization. -func (lu *LU) SolveTo(dst *Dense, trans bool, b Matrix) error { - if !lu.isValid() { - panic(badLU) - } - - _, n := lu.lu.Dims() - br, bc := b.Dims() - if br != n { - panic(ErrShape) - } - - if !lu.ok { - return Condition(math.Inf(1)) - } - - dst.reuseAsNonZeroed(n, bc) - bU, _ := untranspose(b) - if dst == bU { - var restore func() - dst, restore = dst.isolatedWorkspace(bU) - defer restore() - } else if rm, ok := bU.(RawMatrixer); ok { - dst.checkOverlap(rm.RawMatrix()) - } - - dst.Copy(b) - t := blas.NoTrans - if trans { - t = blas.Trans - } - lapack64.Getrs(t, lu.lu.mat, dst.mat, lu.swaps) - if lu.cond > ConditionTolerance { - return Condition(lu.cond) - } - return nil -} - -// SolveVecTo solves a system of linear equations -// -// A * x = b if trans == false -// Aᵀ * x = b if trans == true -// -// using the LU factorization of A stored in the receiver. The solution matrix x -// is stored into dst. -// -// If A is singular or near-singular a Condition error is returned. See the -// documentation for Condition for more information. SolveVecTo will panic if the -// receiver does not contain a factorization. -func (lu *LU) SolveVecTo(dst *VecDense, trans bool, b Vector) error { - if !lu.isValid() { - panic(badLU) - } - - _, n := lu.lu.Dims() - if br, bc := b.Dims(); br != n || bc != 1 { - panic(ErrShape) - } - - switch rv := b.(type) { - default: - dst.reuseAsNonZeroed(n) - return lu.SolveTo(dst.asDense(), trans, b) - case RawVectorer: - if dst != b { - dst.checkOverlap(rv.RawVector()) - } - - if !lu.ok { - return Condition(math.Inf(1)) - } - - dst.reuseAsNonZeroed(n) - var restore func() - if dst == b { - dst, restore = dst.isolatedWorkspace(b) - defer restore() - } - dst.CopyVec(b) - vMat := blas64.General{ - Rows: n, - Cols: 1, - Stride: dst.mat.Inc, - Data: dst.mat.Data, - } - t := blas.NoTrans - if trans { - t = blas.Trans - } - lapack64.Getrs(t, lu.lu.mat, vMat, lu.swaps) - if lu.cond > ConditionTolerance { - return Condition(lu.cond) - } - return nil - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/matrix.go b/vendor/gonum.org/v1/gonum/mat/matrix.go deleted file mode 100644 index 2d67bbe0..00000000 --- a/vendor/gonum.org/v1/gonum/mat/matrix.go +++ /dev/null @@ -1,1000 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/floats/scalar" - "gonum.org/v1/gonum/lapack" -) - -// Matrix is the basic matrix interface type. -type Matrix interface { - // Dims returns the dimensions of a Matrix. - Dims() (r, c int) - - // At returns the value of a matrix element at row i, column j. - // It will panic if i or j are out of bounds for the matrix. - At(i, j int) float64 - - // T returns the transpose of the Matrix. Whether T returns a copy of the - // underlying data is implementation dependent. - // This method may be implemented using the Transpose type, which - // provides an implicit matrix transpose. - T() Matrix -} - -// allMatrix represents the extra set of methods that all mat Matrix types -// should satisfy. This is used to enforce compile-time consistency between the -// Dense types, especially helpful when adding new features. -type allMatrix interface { - Reseter - IsEmpty() bool - Zero() -} - -// denseMatrix represents the extra set of methods that all Dense Matrix types -// should satisfy. This is used to enforce compile-time consistency between the -// Dense types, especially helpful when adding new features. -type denseMatrix interface { - DiagView() Diagonal - Tracer - Normer -} - -var ( - _ Matrix = Transpose{} - _ Untransposer = Transpose{} -) - -// Transpose is a type for performing an implicit matrix transpose. It implements -// the Matrix interface, returning values from the transpose of the matrix within. -type Transpose struct { - Matrix Matrix -} - -// At returns the value of the element at row i and column j of the transposed -// matrix, that is, row j and column i of the Matrix field. -func (t Transpose) At(i, j int) float64 { - return t.Matrix.At(j, i) -} - -// Dims returns the dimensions of the transposed matrix. The number of rows returned -// is the number of columns in the Matrix field, and the number of columns is -// the number of rows in the Matrix field. -func (t Transpose) Dims() (r, c int) { - c, r = t.Matrix.Dims() - return r, c -} - -// T performs an implicit transpose by returning the Matrix field. -func (t Transpose) T() Matrix { - return t.Matrix -} - -// Untranspose returns the Matrix field. -func (t Transpose) Untranspose() Matrix { - return t.Matrix -} - -// Untransposer is a type that can undo an implicit transpose. -type Untransposer interface { - // Note: This interface is needed to unify all of the Transpose types. In - // the mat methods, we need to test if the Matrix has been implicitly - // transposed. If this is checked by testing for the specific Transpose type - // then the behavior will be different if the user uses T() or TTri() for a - // triangular matrix. - - // Untranspose returns the underlying Matrix stored for the implicit transpose. - Untranspose() Matrix -} - -// UntransposeBander is a type that can undo an implicit band transpose. -type UntransposeBander interface { - // Untranspose returns the underlying Banded stored for the implicit transpose. - UntransposeBand() Banded -} - -// UntransposeTrier is a type that can undo an implicit triangular transpose. -type UntransposeTrier interface { - // Untranspose returns the underlying Triangular stored for the implicit transpose. - UntransposeTri() Triangular -} - -// UntransposeTriBander is a type that can undo an implicit triangular banded -// transpose. -type UntransposeTriBander interface { - // Untranspose returns the underlying Triangular stored for the implicit transpose. - UntransposeTriBand() TriBanded -} - -// Mutable is a matrix interface type that allows elements to be altered. -type Mutable interface { - // Set alters the matrix element at row i, column j to v. - // It will panic if i or j are out of bounds for the matrix. - Set(i, j int, v float64) - - Matrix -} - -// A RowViewer can return a Vector reflecting a row that is backed by the matrix -// data. The Vector returned will have length equal to the number of columns. -type RowViewer interface { - RowView(i int) Vector -} - -// A RawRowViewer can return a slice of float64 reflecting a row that is backed by the matrix -// data. -type RawRowViewer interface { - RawRowView(i int) []float64 -} - -// A ColViewer can return a Vector reflecting a column that is backed by the matrix -// data. The Vector returned will have length equal to the number of rows. -type ColViewer interface { - ColView(j int) Vector -} - -// A RawColViewer can return a slice of float64 reflecting a column that is backed by the matrix -// data. -type RawColViewer interface { - RawColView(j int) []float64 -} - -// A ClonerFrom can make a copy of a into the receiver, overwriting the previous value of the -// receiver. The clone operation does not make any restriction on shape and will not cause -// shadowing. -type ClonerFrom interface { - CloneFrom(a Matrix) -} - -// A Reseter can reset the matrix so that it can be reused as the receiver of a dimensionally -// restricted operation. This is commonly used when the matrix is being used as a workspace -// or temporary matrix. -// -// If the matrix is a view, using Reset may result in data corruption in elements outside -// the view. Similarly, if the matrix shares backing data with another variable, using -// Reset may lead to unexpected changes in data values. -type Reseter interface { - Reset() -} - -// A Copier can make a copy of elements of a into the receiver. The submatrix copied -// starts at row and column 0 and has dimensions equal to the minimum dimensions of -// the two matrices. The number of row and columns copied is returned. -// Copy will copy from a source that aliases the receiver unless the source is transposed; -// an aliasing transpose copy will panic with the exception for a special case when -// the source data has a unitary increment or stride. -type Copier interface { - Copy(a Matrix) (r, c int) -} - -// A Grower can grow the size of the represented matrix by the given number of rows and columns. -// Growing beyond the size given by the Caps method will result in the allocation of a new -// matrix and copying of the elements. If Grow is called with negative increments it will -// panic with ErrIndexOutOfRange. -type Grower interface { - Caps() (r, c int) - Grow(r, c int) Matrix -} - -// A RawMatrixSetter can set the underlying blas64.General used by the receiver. There is no restriction -// on the shape of the receiver. Changes to the receiver's elements will be reflected in the blas64.General.Data. -type RawMatrixSetter interface { - SetRawMatrix(a blas64.General) -} - -// A RawMatrixer can return a blas64.General representation of the receiver. Changes to the blas64.General.Data -// slice will be reflected in the original matrix, changes to the Rows, Cols and Stride fields will not. -type RawMatrixer interface { - RawMatrix() blas64.General -} - -// A RawVectorer can return a blas64.Vector representation of the receiver. Changes to the blas64.Vector.Data -// slice will be reflected in the original matrix, changes to the Inc field will not. -type RawVectorer interface { - RawVector() blas64.Vector -} - -// A NonZeroDoer can call a function for each non-zero element of the receiver. -// The parameters of the function are the element indices and its value. -type NonZeroDoer interface { - DoNonZero(func(i, j int, v float64)) -} - -// A RowNonZeroDoer can call a function for each non-zero element of a row of the receiver. -// The parameters of the function are the element indices and its value. -type RowNonZeroDoer interface { - DoRowNonZero(i int, fn func(i, j int, v float64)) -} - -// A ColNonZeroDoer can call a function for each non-zero element of a column of the receiver. -// The parameters of the function are the element indices and its value. -type ColNonZeroDoer interface { - DoColNonZero(j int, fn func(i, j int, v float64)) -} - -// A SolveToer can solve a linear system A⋅X = B or Aᵀ⋅X = B where A is a matrix -// represented by the receiver and B is a given matrix, storing the result into -// dst. -// -// If dst is empty, SolveTo will resize it to the correct size, otherwise it -// must have the correct size. Individual implementations may impose other -// restrictions on the input parameters, for example that A is a square matrix. -type SolveToer interface { - SolveTo(dst *Dense, trans bool, b Matrix) error -} - -// untranspose untransposes a matrix if applicable. If a is an Untransposer, then -// untranspose returns the underlying matrix and true. If it is not, then it returns -// the input matrix and false. -func untranspose(a Matrix) (Matrix, bool) { - if ut, ok := a.(Untransposer); ok { - return ut.Untranspose(), true - } - return a, false -} - -// untransposeExtract returns an untransposed matrix in a built-in matrix type. -// -// The untransposed matrix is returned unaltered if it is a built-in matrix type. -// Otherwise, if it implements a Raw method, an appropriate built-in type value -// is returned holding the raw matrix value of the input. If neither of these -// is possible, the untransposed matrix is returned. -func untransposeExtract(a Matrix) (Matrix, bool) { - ut, trans := untranspose(a) - switch m := ut.(type) { - case *DiagDense, *SymBandDense, *TriBandDense, *BandDense, *TriDense, *SymDense, *Dense, *VecDense, *Tridiag: - return m, trans - // TODO(btracey): Add here if we ever have an equivalent of RawDiagDense. - case RawSymBander: - rsb := m.RawSymBand() - if rsb.Uplo != blas.Upper { - return ut, trans - } - var sb SymBandDense - sb.SetRawSymBand(rsb) - return &sb, trans - case RawTriBander: - rtb := m.RawTriBand() - if rtb.Diag == blas.Unit { - return ut, trans - } - var tb TriBandDense - tb.SetRawTriBand(rtb) - return &tb, trans - case RawBander: - var b BandDense - b.SetRawBand(m.RawBand()) - return &b, trans - case RawTriangular: - rt := m.RawTriangular() - if rt.Diag == blas.Unit { - return ut, trans - } - var t TriDense - t.SetRawTriangular(rt) - return &t, trans - case RawSymmetricer: - rs := m.RawSymmetric() - if rs.Uplo != blas.Upper { - return ut, trans - } - var s SymDense - s.SetRawSymmetric(rs) - return &s, trans - case RawMatrixer: - var d Dense - d.SetRawMatrix(m.RawMatrix()) - return &d, trans - case RawVectorer: - var v VecDense - v.SetRawVector(m.RawVector()) - return &v, trans - case RawTridiagonaler: - var d Tridiag - d.SetRawTridiagonal(m.RawTridiagonal()) - return &d, trans - default: - return ut, trans - } -} - -// TODO(btracey): Consider adding CopyCol/CopyRow if the behavior seems useful. -// TODO(btracey): Add in fast paths to Row/Col for the other concrete types -// (TriDense, etc.) as well as relevant interfaces (RowColer, RawRowViewer, etc.) - -// Col copies the elements in the jth column of the matrix into the slice dst. -// The length of the provided slice must equal the number of rows, unless the -// slice is nil in which case a new slice is first allocated. -func Col(dst []float64, j int, a Matrix) []float64 { - r, c := a.Dims() - if j < 0 || j >= c { - panic(ErrColAccess) - } - if dst == nil { - dst = make([]float64, r) - } else { - if len(dst) != r { - panic(ErrColLength) - } - } - aU, aTrans := untranspose(a) - if rm, ok := aU.(RawMatrixer); ok { - m := rm.RawMatrix() - if aTrans { - copy(dst, m.Data[j*m.Stride:j*m.Stride+m.Cols]) - return dst - } - blas64.Copy(blas64.Vector{N: r, Inc: m.Stride, Data: m.Data[j:]}, - blas64.Vector{N: r, Inc: 1, Data: dst}, - ) - return dst - } - for i := 0; i < r; i++ { - dst[i] = a.At(i, j) - } - return dst -} - -// Row copies the elements in the ith row of the matrix into the slice dst. -// The length of the provided slice must equal the number of columns, unless the -// slice is nil in which case a new slice is first allocated. -func Row(dst []float64, i int, a Matrix) []float64 { - r, c := a.Dims() - if i < 0 || i >= r { - panic(ErrColAccess) - } - if dst == nil { - dst = make([]float64, c) - } else { - if len(dst) != c { - panic(ErrRowLength) - } - } - aU, aTrans := untranspose(a) - if rm, ok := aU.(RawMatrixer); ok { - m := rm.RawMatrix() - if aTrans { - blas64.Copy(blas64.Vector{N: c, Inc: m.Stride, Data: m.Data[i:]}, - blas64.Vector{N: c, Inc: 1, Data: dst}, - ) - return dst - } - copy(dst, m.Data[i*m.Stride:i*m.Stride+m.Cols]) - return dst - } - for j := 0; j < c; j++ { - dst[j] = a.At(i, j) - } - return dst -} - -// Cond returns the condition number of the given matrix under the given norm. -// The condition number must be based on the 1-norm, 2-norm or ∞-norm. -// Cond will panic with ErrZeroLength if the matrix has zero size. -// -// BUG(btracey): The computation of the 1-norm and ∞-norm for non-square matrices -// is inaccurate, although is typically the right order of magnitude. See -// https://github.com/xianyi/OpenBLAS/issues/636. While the value returned will -// change with the resolution of this bug, the result from Cond will match the -// condition number used internally. -func Cond(a Matrix, norm float64) float64 { - m, n := a.Dims() - if m == 0 || n == 0 { - panic(ErrZeroLength) - } - var lnorm lapack.MatrixNorm - switch norm { - default: - panic("mat: bad norm value") - case 1: - lnorm = lapack.MaxColumnSum - case 2: - var svd SVD - ok := svd.Factorize(a, SVDNone) - if !ok { - return math.Inf(1) - } - return svd.Cond() - case math.Inf(1): - lnorm = lapack.MaxRowSum - } - - if m == n { - // Use the LU decomposition to compute the condition number. - var lu LU - lu.factorize(a, lnorm) - return lu.Cond() - } - if m > n { - // Use the QR factorization to compute the condition number. - var qr QR - qr.factorize(a, lnorm) - return qr.Cond() - } - // Use the LQ factorization to compute the condition number. - var lq LQ - lq.factorize(a, lnorm) - return lq.Cond() -} - -// Det returns the determinant of the square matrix a. In many expressions using -// LogDet will be more numerically stable. -// -// Det panics with ErrSquare if a is not square and with ErrZeroLength if a has -// zero size. -func Det(a Matrix) float64 { - det, sign := LogDet(a) - return math.Exp(det) * sign -} - -// Dot returns the sum of the element-wise product of a and b. -// -// Dot panics with ErrShape if the vector sizes are unequal and with -// ErrZeroLength if the sizes are zero. -func Dot(a, b Vector) float64 { - la := a.Len() - lb := b.Len() - if la != lb { - panic(ErrShape) - } - if la == 0 { - panic(ErrZeroLength) - } - if arv, ok := a.(RawVectorer); ok { - if brv, ok := b.(RawVectorer); ok { - return blas64.Dot(arv.RawVector(), brv.RawVector()) - } - } - var sum float64 - for i := 0; i < la; i++ { - sum += a.At(i, 0) * b.At(i, 0) - } - return sum -} - -// Equal returns whether the matrices a and b have the same size -// and are element-wise equal. -func Equal(a, b Matrix) bool { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - return false - } - aU, aTrans := untranspose(a) - bU, bTrans := untranspose(b) - if rma, ok := aU.(RawMatrixer); ok { - if rmb, ok := bU.(RawMatrixer); ok { - ra := rma.RawMatrix() - rb := rmb.RawMatrix() - if aTrans == bTrans { - for i := 0; i < ra.Rows; i++ { - for j := 0; j < ra.Cols; j++ { - if ra.Data[i*ra.Stride+j] != rb.Data[i*rb.Stride+j] { - return false - } - } - } - return true - } - for i := 0; i < ra.Rows; i++ { - for j := 0; j < ra.Cols; j++ { - if ra.Data[i*ra.Stride+j] != rb.Data[j*rb.Stride+i] { - return false - } - } - } - return true - } - } - if rma, ok := aU.(RawSymmetricer); ok { - if rmb, ok := bU.(RawSymmetricer); ok { - ra := rma.RawSymmetric() - rb := rmb.RawSymmetric() - // Symmetric matrices are always upper and equal to their transpose. - for i := 0; i < ra.N; i++ { - for j := i; j < ra.N; j++ { - if ra.Data[i*ra.Stride+j] != rb.Data[i*rb.Stride+j] { - return false - } - } - } - return true - } - } - if ra, ok := aU.(*VecDense); ok { - if rb, ok := bU.(*VecDense); ok { - // If the raw vectors are the same length they must either both be - // transposed or both not transposed (or have length 1). - for i := 0; i < ra.mat.N; i++ { - if ra.mat.Data[i*ra.mat.Inc] != rb.mat.Data[i*rb.mat.Inc] { - return false - } - } - return true - } - } - for i := 0; i < ar; i++ { - for j := 0; j < ac; j++ { - if a.At(i, j) != b.At(i, j) { - return false - } - } - } - return true -} - -// EqualApprox returns whether the matrices a and b have the same size and contain all equal -// elements with tolerance for element-wise equality specified by epsilon. Matrices -// with non-equal shapes are not equal. -func EqualApprox(a, b Matrix, epsilon float64) bool { - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br || ac != bc { - return false - } - aU, aTrans := untranspose(a) - bU, bTrans := untranspose(b) - if rma, ok := aU.(RawMatrixer); ok { - if rmb, ok := bU.(RawMatrixer); ok { - ra := rma.RawMatrix() - rb := rmb.RawMatrix() - if aTrans == bTrans { - for i := 0; i < ra.Rows; i++ { - for j := 0; j < ra.Cols; j++ { - if !scalar.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[i*rb.Stride+j], epsilon, epsilon) { - return false - } - } - } - return true - } - for i := 0; i < ra.Rows; i++ { - for j := 0; j < ra.Cols; j++ { - if !scalar.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[j*rb.Stride+i], epsilon, epsilon) { - return false - } - } - } - return true - } - } - if rma, ok := aU.(RawSymmetricer); ok { - if rmb, ok := bU.(RawSymmetricer); ok { - ra := rma.RawSymmetric() - rb := rmb.RawSymmetric() - // Symmetric matrices are always upper and equal to their transpose. - for i := 0; i < ra.N; i++ { - for j := i; j < ra.N; j++ { - if !scalar.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[i*rb.Stride+j], epsilon, epsilon) { - return false - } - } - } - return true - } - } - if ra, ok := aU.(*VecDense); ok { - if rb, ok := bU.(*VecDense); ok { - // If the raw vectors are the same length they must either both be - // transposed or both not transposed (or have length 1). - for i := 0; i < ra.mat.N; i++ { - if !scalar.EqualWithinAbsOrRel(ra.mat.Data[i*ra.mat.Inc], rb.mat.Data[i*rb.mat.Inc], epsilon, epsilon) { - return false - } - } - return true - } - } - for i := 0; i < ar; i++ { - for j := 0; j < ac; j++ { - if !scalar.EqualWithinAbsOrRel(a.At(i, j), b.At(i, j), epsilon, epsilon) { - return false - } - } - } - return true -} - -// LogDet returns the log of the determinant and the sign of the determinant -// for the matrix that has been factorized. Numerical stability in product and -// division expressions is generally improved by working in log space. -// -// LogDet panics with ErrSquare is a is not square and with ErrZeroLength if a -// has zero size. -func LogDet(a Matrix) (det float64, sign float64) { - // TODO(btracey): Add specialized routines for TriDense, etc. - var lu LU - lu.Factorize(a) - return lu.LogDet() -} - -// Max returns the largest element value of the matrix A. -// -// Max will panic with ErrZeroLength if the matrix has zero size. -func Max(a Matrix) float64 { - r, c := a.Dims() - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - // Max(A) = Max(Aᵀ) - aU, _ := untranspose(a) - switch m := aU.(type) { - case RawMatrixer: - rm := m.RawMatrix() - max := math.Inf(-1) - for i := 0; i < rm.Rows; i++ { - for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { - if v > max { - max = v - } - } - } - return max - case RawTriangular: - rm := m.RawTriangular() - // The max of a triangular is at least 0 unless the size is 1. - if rm.N == 1 { - return rm.Data[0] - } - max := 0.0 - if rm.Uplo == blas.Upper { - for i := 0; i < rm.N; i++ { - for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { - if v > max { - max = v - } - } - } - return max - } - for i := 0; i < rm.N; i++ { - for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+i+1] { - if v > max { - max = v - } - } - } - return max - case RawSymmetricer: - rm := m.RawSymmetric() - if rm.Uplo != blas.Upper { - panic(badSymTriangle) - } - max := math.Inf(-1) - for i := 0; i < rm.N; i++ { - for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { - if v > max { - max = v - } - } - } - return max - default: - r, c := aU.Dims() - max := math.Inf(-1) - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - v := aU.At(i, j) - if v > max { - max = v - } - } - } - return max - } -} - -// Min returns the smallest element value of the matrix A. -// -// Min will panic with ErrZeroLength if the matrix has zero size. -func Min(a Matrix) float64 { - r, c := a.Dims() - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - // Min(A) = Min(Aᵀ) - aU, _ := untranspose(a) - switch m := aU.(type) { - case RawMatrixer: - rm := m.RawMatrix() - min := math.Inf(1) - for i := 0; i < rm.Rows; i++ { - for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { - if v < min { - min = v - } - } - } - return min - case RawTriangular: - rm := m.RawTriangular() - // The min of a triangular is at most 0 unless the size is 1. - if rm.N == 1 { - return rm.Data[0] - } - min := 0.0 - if rm.Uplo == blas.Upper { - for i := 0; i < rm.N; i++ { - for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { - if v < min { - min = v - } - } - } - return min - } - for i := 0; i < rm.N; i++ { - for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+i+1] { - if v < min { - min = v - } - } - } - return min - case RawSymmetricer: - rm := m.RawSymmetric() - if rm.Uplo != blas.Upper { - panic(badSymTriangle) - } - min := math.Inf(1) - for i := 0; i < rm.N; i++ { - for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { - if v < min { - min = v - } - } - } - return min - default: - r, c := aU.Dims() - min := math.Inf(1) - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - v := aU.At(i, j) - if v < min { - min = v - } - } - } - return min - } -} - -// A Normer can compute a norm of the matrix. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -type Normer interface { - Norm(norm float64) float64 -} - -// Norm returns the specified norm of the matrix A. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// If a is a Normer, its Norm method will be used to calculate the norm. -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrShape if the matrix has zero size. -func Norm(a Matrix, norm float64) float64 { - r, c := a.Dims() - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - m, trans := untransposeExtract(a) - if m, ok := m.(Normer); ok { - if trans { - switch norm { - case 1: - norm = math.Inf(1) - case math.Inf(1): - norm = 1 - } - } - return m.Norm(norm) - } - switch norm { - default: - panic(ErrNormOrder) - case 1: - var max float64 - for j := 0; j < c; j++ { - var sum float64 - for i := 0; i < r; i++ { - sum += math.Abs(a.At(i, j)) - } - if sum > max { - max = sum - } - } - return max - case 2: - var sum float64 - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - v := a.At(i, j) - sum += v * v - } - } - return math.Sqrt(sum) - case math.Inf(1): - var max float64 - for i := 0; i < r; i++ { - var sum float64 - for j := 0; j < c; j++ { - sum += math.Abs(a.At(i, j)) - } - if sum > max { - max = sum - } - } - return max - } -} - -// normLapack converts the float64 norm input in Norm to a lapack.MatrixNorm. -func normLapack(norm float64, aTrans bool) lapack.MatrixNorm { - switch norm { - case 1: - n := lapack.MaxColumnSum - if aTrans { - n = lapack.MaxRowSum - } - return n - case 2: - return lapack.Frobenius - case math.Inf(1): - n := lapack.MaxRowSum - if aTrans { - n = lapack.MaxColumnSum - } - return n - default: - panic(ErrNormOrder) - } -} - -// Sum returns the sum of the elements of the matrix. -// -// Sum will panic with ErrZeroLength if the matrix has zero size. -func Sum(a Matrix) float64 { - r, c := a.Dims() - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - var sum float64 - aU, _ := untranspose(a) - switch rma := aU.(type) { - case RawSymmetricer: - rm := rma.RawSymmetric() - for i := 0; i < rm.N; i++ { - // Diagonals count once while off-diagonals count twice. - sum += rm.Data[i*rm.Stride+i] - var s float64 - for _, v := range rm.Data[i*rm.Stride+i+1 : i*rm.Stride+rm.N] { - s += v - } - sum += 2 * s - } - return sum - case RawTriangular: - rm := rma.RawTriangular() - var startIdx, endIdx int - for i := 0; i < rm.N; i++ { - // Start and end index for this triangle-row. - switch rm.Uplo { - case blas.Upper: - startIdx = i - endIdx = rm.N - case blas.Lower: - startIdx = 0 - endIdx = i + 1 - default: - panic(badTriangle) - } - for _, v := range rm.Data[i*rm.Stride+startIdx : i*rm.Stride+endIdx] { - sum += v - } - } - return sum - case RawMatrixer: - rm := rma.RawMatrix() - for i := 0; i < rm.Rows; i++ { - for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { - sum += v - } - } - return sum - case *VecDense: - rm := rma.RawVector() - for i := 0; i < rm.N; i++ { - sum += rm.Data[i*rm.Inc] - } - return sum - default: - r, c := a.Dims() - for i := 0; i < r; i++ { - for j := 0; j < c; j++ { - sum += a.At(i, j) - } - } - return sum - } -} - -// A Tracer can compute the trace of the matrix. Trace must panic with ErrSquare -// if the matrix is not square. -type Tracer interface { - Trace() float64 -} - -// Trace returns the trace of the matrix. If a is a Tracer, its Trace method -// will be used to calculate the matrix trace. -// -// Trace will panic with ErrSquare if the matrix is not square and with -// ErrZeroLength if the matrix has zero size. -func Trace(a Matrix) float64 { - r, c := a.Dims() - if r == 0 || c == 0 { - panic(ErrZeroLength) - } - m, _ := untransposeExtract(a) - if t, ok := m.(Tracer); ok { - return t.Trace() - } - if r != c { - panic(ErrSquare) - } - var v float64 - for i := 0; i < r; i++ { - v += a.At(i, i) - } - return v -} - -// use returns a float64 slice with l elements, using f if it -// has the necessary capacity, otherwise creating a new slice. -func use(f []float64, l int) []float64 { - if l <= cap(f) { - return f[:l] - } - return make([]float64, l) -} - -// useZeroed returns a float64 slice with l elements, using f if it -// has the necessary capacity, otherwise creating a new slice. The -// elements of the returned slice are guaranteed to be zero. -func useZeroed(f []float64, l int) []float64 { - if l <= cap(f) { - f = f[:l] - zero(f) - return f - } - return make([]float64, l) -} - -// zero zeros the given slice's elements. -func zero(f []float64) { - for i := range f { - f[i] = 0 - } -} - -// useInt returns an int slice with l elements, using i if it -// has the necessary capacity, otherwise creating a new slice. -func useInt(i []int, l int) []int { - if l <= cap(i) { - return i[:l] - } - return make([]int, l) -} diff --git a/vendor/gonum.org/v1/gonum/mat/offset.go b/vendor/gonum.org/v1/gonum/mat/offset.go deleted file mode 100644 index 26c80a4c..00000000 --- a/vendor/gonum.org/v1/gonum/mat/offset.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright ©2015 The Gonum 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 !safe -// +build !safe - -package mat - -import "unsafe" - -// offset returns the number of float64 values b[0] is after a[0]. -func offset(a, b []float64) int { - if &a[0] == &b[0] { - return 0 - } - // This expression must be atomic with respect to GC moves. - // At this stage this is true, because the GC does not - // move. See https://golang.org/issue/12445. - return int(uintptr(unsafe.Pointer(&b[0]))-uintptr(unsafe.Pointer(&a[0]))) / int(unsafe.Sizeof(float64(0))) -} - -// offsetComplex returns the number of complex128 values b[0] is after a[0]. -func offsetComplex(a, b []complex128) int { - if &a[0] == &b[0] { - return 0 - } - // This expression must be atomic with respect to GC moves. - // At this stage this is true, because the GC does not - // move. See https://golang.org/issue/12445. - return int(uintptr(unsafe.Pointer(&b[0]))-uintptr(unsafe.Pointer(&a[0]))) / int(unsafe.Sizeof(complex128(0))) -} diff --git a/vendor/gonum.org/v1/gonum/mat/offset_appengine.go b/vendor/gonum.org/v1/gonum/mat/offset_appengine.go deleted file mode 100644 index be2ca78c..00000000 --- a/vendor/gonum.org/v1/gonum/mat/offset_appengine.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright ©2015 The Gonum 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 safe -// +build safe - -package mat - -import "reflect" - -var sizeOfFloat64 = int(reflect.TypeOf(float64(0)).Size()) - -// offset returns the number of float64 values b[0] is after a[0]. -func offset(a, b []float64) int { - va0 := reflect.ValueOf(a).Index(0) - vb0 := reflect.ValueOf(b).Index(0) - if va0.Addr() == vb0.Addr() { - return 0 - } - // This expression must be atomic with respect to GC moves. - // At this stage this is true, because the GC does not - // move. See https://golang.org/issue/12445. - return int(vb0.UnsafeAddr()-va0.UnsafeAddr()) / sizeOfFloat64 -} - -var sizeOfComplex128 = int(reflect.TypeOf(complex128(0)).Size()) - -// offsetComplex returns the number of complex128 values b[0] is after a[0]. -func offsetComplex(a, b []complex128) int { - va0 := reflect.ValueOf(a).Index(0) - vb0 := reflect.ValueOf(b).Index(0) - if va0.Addr() == vb0.Addr() { - return 0 - } - // This expression must be atomic with respect to GC moves. - // At this stage this is true, because the GC does not - // move. See https://golang.org/issue/12445. - return int(vb0.UnsafeAddr()-va0.UnsafeAddr()) / sizeOfComplex128 -} diff --git a/vendor/gonum.org/v1/gonum/mat/pool.go b/vendor/gonum.org/v1/gonum/mat/pool.go deleted file mode 100644 index b9dce1c4..00000000 --- a/vendor/gonum.org/v1/gonum/mat/pool.go +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright ©2014 The Gonum 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 mat - -import ( - "math/bits" - "sync" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/blas/cblas128" -) - -// poolFor returns the ceiling of base 2 log of size. It provides an index -// into a pool array to a sync.Pool that will return values able to hold -// size elements. -func poolFor(size uint) int { - if size == 0 { - return 0 - } - return bits.Len(size - 1) -} - -var ( - // poolDense contains size stratified workspace Dense pools. - // Each poolDense element i returns sized matrices with a data - // slice capped at 1<<i. - poolDense [63]sync.Pool - - // poolSymDense is the SymDense equivalent of poolDense. - poolSymDense [63]sync.Pool - - // poolTriDense is the TriDense equivalent of poolDense. - poolTriDense [63]sync.Pool - - // poolVecDense is the VecDense equivalent of poolDense. - poolVecDense [63]sync.Pool - - // poolCDense is the CDense equivalent of poolDense. - poolCDense [63]sync.Pool - - // poolFloat64s is the []float64 equivalent of poolDense. - poolFloat64s [63]sync.Pool - - // poolInts is the []int equivalent of poolDense. - poolInts [63]sync.Pool -) - -func init() { - for i := range poolDense { - l := 1 << uint(i) - // Real matrix pools. - poolDense[i].New = func() interface{} { - return &Dense{mat: blas64.General{ - Data: make([]float64, l), - }} - } - poolSymDense[i].New = func() interface{} { - return &SymDense{mat: blas64.Symmetric{ - Uplo: blas.Upper, - Data: make([]float64, l), - }} - } - poolTriDense[i].New = func() interface{} { - return &TriDense{mat: blas64.Triangular{ - Data: make([]float64, l), - }} - } - poolVecDense[i].New = func() interface{} { - return &VecDense{mat: blas64.Vector{ - Inc: 1, - Data: make([]float64, l), - }} - } - - // Complex matrix pools. - poolCDense[i].New = func() interface{} { - return &CDense{mat: cblas128.General{ - Data: make([]complex128, l), - }} - } - - // Helper pools. - poolFloat64s[i].New = func() interface{} { - s := make([]float64, l) - return &s - } - poolInts[i].New = func() interface{} { - s := make([]int, l) - return &s - } - } -} - -// getDenseWorkspace returns a *Dense of size r×c and a data slice -// with a cap that is less than 2*r*c. If clear is true, the -// data slice visible through the Matrix interface is zeroed. -func getDenseWorkspace(r, c int, clear bool) *Dense { - l := uint(r * c) - w := poolDense[poolFor(l)].Get().(*Dense) - w.mat.Data = w.mat.Data[:l] - if clear { - zero(w.mat.Data) - } - w.mat.Rows = r - w.mat.Cols = c - w.mat.Stride = c - w.capRows = r - w.capCols = c - return w -} - -// putDenseWorkspace replaces a used *Dense into the appropriate size -// workspace pool. putDenseWorkspace must not be called with a matrix -// where references to the underlying data slice have been kept. -func putDenseWorkspace(w *Dense) { - poolDense[poolFor(uint(cap(w.mat.Data)))].Put(w) -} - -// getSymDenseWorkspace returns a *SymDense of size n and a cap that -// is less than 2*n. If clear is true, the data slice visible -// through the Matrix interface is zeroed. -func getSymDenseWorkspace(n int, clear bool) *SymDense { - l := uint(n) - l *= l - s := poolSymDense[poolFor(l)].Get().(*SymDense) - s.mat.Data = s.mat.Data[:l] - if clear { - zero(s.mat.Data) - } - s.mat.N = n - s.mat.Stride = n - s.cap = n - return s -} - -// putSymDenseWorkspace replaces a used *SymDense into the appropriate size -// workspace pool. putSymDenseWorkspace must not be called with a matrix -// where references to the underlying data slice have been kept. -func putSymDenseWorkspace(s *SymDense) { - poolSymDense[poolFor(uint(cap(s.mat.Data)))].Put(s) -} - -// getTriDenseWorkspace returns a *TriDense of size n and a cap that -// is less than 2*n. If clear is true, the data slice visible -// through the Matrix interface is zeroed. -func getTriDenseWorkspace(n int, kind TriKind, clear bool) *TriDense { - l := uint(n) - l *= l - t := poolTriDense[poolFor(l)].Get().(*TriDense) - t.mat.Data = t.mat.Data[:l] - if clear { - zero(t.mat.Data) - } - t.mat.N = n - t.mat.Stride = n - if kind == Upper { - t.mat.Uplo = blas.Upper - } else if kind == Lower { - t.mat.Uplo = blas.Lower - } else { - panic(ErrTriangle) - } - t.mat.Diag = blas.NonUnit - t.cap = n - return t -} - -// putTriWorkspace replaces a used *TriDense into the appropriate size -// workspace pool. putTriWorkspace must not be called with a matrix -// where references to the underlying data slice have been kept. -func putTriWorkspace(t *TriDense) { - poolTriDense[poolFor(uint(cap(t.mat.Data)))].Put(t) -} - -// getVecDenseWorkspace returns a *VecDense of length n and a cap that -// is less than 2*n. If clear is true, the data slice visible -// through the Matrix interface is zeroed. -func getVecDenseWorkspace(n int, clear bool) *VecDense { - l := uint(n) - v := poolVecDense[poolFor(l)].Get().(*VecDense) - v.mat.Data = v.mat.Data[:l] - if clear { - zero(v.mat.Data) - } - v.mat.N = n - return v -} - -// putVecDenseWorkspace replaces a used *VecDense into the appropriate size -// workspace pool. putVecDenseWorkspace must not be called with a matrix -// where references to the underlying data slice have been kept. -func putVecDenseWorkspace(v *VecDense) { - poolVecDense[poolFor(uint(cap(v.mat.Data)))].Put(v) -} - -// getCDenseWorkspace returns a *CDense of size r×c and a data slice -// with a cap that is less than 2*r*c. If clear is true, the -// data slice visible through the CMatrix interface is zeroed. -func getCDenseWorkspace(r, c int, clear bool) *CDense { - l := uint(r * c) - w := poolCDense[poolFor(l)].Get().(*CDense) - w.mat.Data = w.mat.Data[:l] - if clear { - zeroC(w.mat.Data) - } - w.mat.Rows = r - w.mat.Cols = c - w.mat.Stride = c - w.capRows = r - w.capCols = c - return w -} - -// putCDenseWorkspace replaces a used *CDense into the appropriate size -// workspace pool. putWorkspace must not be called with a matrix -// where references to the underlying data slice have been kept. -func putCDenseWorkspace(w *CDense) { - poolCDense[poolFor(uint(cap(w.mat.Data)))].Put(w) -} - -// getFloat64s returns a []float64 of length l and a cap that is -// less than 2*l. If clear is true, the slice visible is zeroed. -func getFloat64s(l int, clear bool) []float64 { - w := *poolFloat64s[poolFor(uint(l))].Get().(*[]float64) - w = w[:l] - if clear { - zero(w) - } - return w -} - -// putFloat64s replaces a used []float64 into the appropriate size -// workspace pool. putFloat64s must not be called with a slice -// where references to the underlying data have been kept. -func putFloat64s(w []float64) { - poolFloat64s[poolFor(uint(cap(w)))].Put(&w) -} - -// getInts returns a []int of length l and a cap that is -// less than 2*l. If clear is true, the slice visible is zeroed. -func getInts(l int, clear bool) []int { - w := *poolInts[poolFor(uint(l))].Get().(*[]int) - w = w[:l] - if clear { - for i := range w { - w[i] = 0 - } - } - return w -} - -// putInts replaces a used []int into the appropriate size -// workspace pool. putInts must not be called with a slice -// where references to the underlying data have been kept. -func putInts(w []int) { - poolInts[poolFor(uint(cap(w)))].Put(&w) -} diff --git a/vendor/gonum.org/v1/gonum/mat/product.go b/vendor/gonum.org/v1/gonum/mat/product.go deleted file mode 100644 index 43e46a2c..00000000 --- a/vendor/gonum.org/v1/gonum/mat/product.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat - -import "fmt" - -// Product calculates the product of the given factors and places the result in -// the receiver. The order of multiplication operations is optimized to minimize -// the number of floating point operations on the basis that all matrix -// multiplications are general. -func (m *Dense) Product(factors ...Matrix) { - // The operation order optimisation is the naive O(n^3) dynamic - // programming approach and does not take into consideration - // finer-grained optimisations that might be available. - // - // TODO(kortschak) Consider using the O(nlogn) or O(mlogn) - // algorithms that are available. e.g. - // - // e.g. http://www.jofcis.com/publishedpapers/2014_10_10_4299_4306.pdf - // - // In the case that this is replaced, retain this code in - // tests to compare against. - - r, c := m.Dims() - switch len(factors) { - case 0: - if r != 0 || c != 0 { - panic(ErrShape) - } - return - case 1: - m.reuseAsNonZeroed(factors[0].Dims()) - m.Copy(factors[0]) - return - case 2: - // Don't do work that we know the answer to. - m.Mul(factors[0], factors[1]) - return - } - - p := newMultiplier(m, factors) - p.optimize() - result := p.multiply() - m.reuseAsNonZeroed(result.Dims()) - m.Copy(result) - putDenseWorkspace(result) -} - -// debugProductWalk enables debugging output for Product. -const debugProductWalk = false - -// multiplier performs operation order optimisation and tree traversal. -type multiplier struct { - // factors is the ordered set of - // factors to multiply. - factors []Matrix - // dims is the chain of factor - // dimensions. - dims []int - - // table contains the dynamic - // programming costs and subchain - // division indices. - table table -} - -func newMultiplier(m *Dense, factors []Matrix) *multiplier { - // Check size early, but don't yet - // allocate data for m. - r, c := m.Dims() - fr, fc := factors[0].Dims() // newMultiplier is only called with len(factors) > 2. - if !m.IsEmpty() { - if fr != r { - panic(ErrShape) - } - if _, lc := factors[len(factors)-1].Dims(); lc != c { - panic(ErrShape) - } - } - - dims := make([]int, len(factors)+1) - dims[0] = r - dims[len(dims)-1] = c - pc := fc - for i, f := range factors[1:] { - cr, cc := f.Dims() - dims[i+1] = cr - if pc != cr { - panic(ErrShape) - } - pc = cc - } - - return &multiplier{ - factors: factors, - dims: dims, - table: newTable(len(factors)), - } -} - -// optimize determines an optimal matrix multiply operation order. -func (p *multiplier) optimize() { - if debugProductWalk { - fmt.Printf("chain dims: %v\n", p.dims) - } - const maxInt = int(^uint(0) >> 1) - for f := 1; f < len(p.factors); f++ { - for i := 0; i < len(p.factors)-f; i++ { - j := i + f - p.table.set(i, j, entry{cost: maxInt}) - for k := i; k < j; k++ { - cost := p.table.at(i, k).cost + p.table.at(k+1, j).cost + p.dims[i]*p.dims[k+1]*p.dims[j+1] - if cost < p.table.at(i, j).cost { - p.table.set(i, j, entry{cost: cost, k: k}) - } - } - } - } -} - -// multiply walks the optimal operation tree found by optimize, -// leaving the final result in the stack. It returns the -// product, which may be copied but should be returned to -// the workspace pool. -func (p *multiplier) multiply() *Dense { - result, _ := p.multiplySubchain(0, len(p.factors)-1) - if debugProductWalk { - r, c := result.Dims() - fmt.Printf("\tpop result (%d×%d) cost=%d\n", r, c, p.table.at(0, len(p.factors)-1).cost) - } - return result.(*Dense) -} - -func (p *multiplier) multiplySubchain(i, j int) (m Matrix, intermediate bool) { - if i == j { - return p.factors[i], false - } - - a, aTmp := p.multiplySubchain(i, p.table.at(i, j).k) - b, bTmp := p.multiplySubchain(p.table.at(i, j).k+1, j) - - ar, ac := a.Dims() - br, bc := b.Dims() - if ac != br { - // Panic with a string since this - // is not a user-facing panic. - panic(ErrShape.Error()) - } - - if debugProductWalk { - fmt.Printf("\tpush f[%d] (%d×%d)%s * f[%d] (%d×%d)%s\n", - i, ar, ac, result(aTmp), j, br, bc, result(bTmp)) - } - - r := getDenseWorkspace(ar, bc, false) - r.Mul(a, b) - if aTmp { - putDenseWorkspace(a.(*Dense)) - } - if bTmp { - putDenseWorkspace(b.(*Dense)) - } - return r, true -} - -type entry struct { - k int // is the chain subdivision index. - cost int // cost is the cost of the operation. -} - -// table is a row major n×n dynamic programming table. -type table struct { - n int - entries []entry -} - -func newTable(n int) table { - return table{n: n, entries: make([]entry, n*n)} -} - -func (t table) at(i, j int) entry { return t.entries[i*t.n+j] } -func (t table) set(i, j int, e entry) { t.entries[i*t.n+j] = e } - -type result bool - -func (r result) String() string { - if r { - return " (popped result)" - } - return "" -} diff --git a/vendor/gonum.org/v1/gonum/mat/qr.go b/vendor/gonum.org/v1/gonum/mat/qr.go deleted file mode 100644 index 7f8fec8f..00000000 --- a/vendor/gonum.org/v1/gonum/mat/qr.go +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -const badQR = "mat: invalid QR factorization" - -// QR is a type for creating and using the QR factorization of a matrix. -type QR struct { - qr *Dense - q *Dense - tau []float64 - cond float64 -} - -// Dims returns the dimensions of the matrix. -func (qr *QR) Dims() (r, c int) { - if qr.qr == nil { - return 0, 0 - } - return qr.qr.Dims() -} - -// At returns the element at row i, column j. At will panic if the receiver -// does not contain a successful factorization. -func (qr *QR) At(i, j int) float64 { - if !qr.isValid() { - panic(badQR) - } - - m, n := qr.Dims() - if uint(i) >= uint(m) { - panic(ErrRowAccess) - } - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - - if qr.q == nil || qr.q.IsEmpty() { - // Calculate Qi, Q i-th row - qi := getFloat64s(m, true) - qr.qRowTo(i, qi) - - // Compute QR(i,j) - var val float64 - for k := 0; k <= j; k++ { - val += qi[k] * qr.qr.at(k, j) - } - putFloat64s(qi) - return val - } - - var val float64 - for k := 0; k <= j; k++ { - val += qr.q.at(i, k) * qr.qr.at(k, j) - } - return val -} - -// qRowTo extracts the i-th row of the orthonormal matrix Q from a QR -// decomposition. -func (qr *QR) qRowTo(i int, dst []float64) { - c := blas64.General{ - Rows: 1, - Cols: len(dst), - Stride: len(dst), - Data: dst, - } - c.Data[i] = 1 // C is the i-th unit vector - - // Construct Qi from the elementary reflectors: Qi = C * (H(1) H(2) ... H(nTau)) - work := []float64{0} - lapack64.Ormqr(blas.Right, blas.NoTrans, qr.qr.mat, qr.tau, c, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Ormqr(blas.Right, blas.NoTrans, qr.qr.mat, qr.tau, c, work, len(work)) - putFloat64s(work) -} - -// T performs an implicit transpose by returning the receiver inside a -// Transpose. -func (qr *QR) T() Matrix { - return Transpose{qr} -} - -func (qr *QR) updateCond(norm lapack.MatrixNorm) { - // Since A = Q*R, and Q is orthogonal, we get for the condition number κ - // κ(A) := |A| |A^-1| = |Q*R| |(Q*R)^-1| = |R| |R^-1 * Qᵀ| - // = |R| |R^-1| = κ(R), - // where we used that fact that Q^-1 = Qᵀ. However, this assumes that - // the matrix norm is invariant under orthogonal transformations which - // is not the case for CondNorm. Hopefully the error is negligible: κ - // is only a qualitative measure anyway. - n := qr.qr.mat.Cols - work := getFloat64s(3*n, false) - iwork := getInts(n, false) - r := qr.qr.asTriDense(n, blas.NonUnit, blas.Upper) - v := lapack64.Trcon(norm, r.mat, work, iwork) - putFloat64s(work) - putInts(iwork) - qr.cond = 1 / v -} - -// Factorize computes the QR factorization of an m×n matrix a where m >= n. The QR -// factorization always exists even if A is singular. -// -// The QR decomposition is a factorization of the matrix A such that A = Q * R. -// The matrix Q is an orthonormal m×m matrix, and R is an m×n upper triangular matrix. -// Q and R can be extracted using the QTo and RTo methods. -func (qr *QR) Factorize(a Matrix) { - qr.factorize(a, CondNorm) -} - -func (qr *QR) factorize(a Matrix, norm lapack.MatrixNorm) { - m, n := a.Dims() - if m < n { - panic(ErrShape) - } - if qr.qr == nil { - qr.qr = &Dense{} - } - qr.qr.CloneFrom(a) - work := []float64{0} - qr.tau = make([]float64, n) - lapack64.Geqrf(qr.qr.mat, qr.tau, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Geqrf(qr.qr.mat, qr.tau, work, len(work)) - putFloat64s(work) - qr.updateCond(norm) - if qr.q != nil { - qr.q.Reset() - } -} - -func (qr *QR) updateQ() { - m, _ := qr.Dims() - if qr.q == nil { - qr.q = NewDense(m, m, nil) - } else { - qr.q.reuseAsNonZeroed(m, m) - } - // Construct Q from the elementary reflectors. - qr.q.Copy(qr.qr) - work := []float64{0} - lapack64.Orgqr(qr.q.mat, qr.tau, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Orgqr(qr.q.mat, qr.tau, work, len(work)) - putFloat64s(work) -} - -// isValid returns whether the receiver contains a factorization. -func (qr *QR) isValid() bool { - return qr.qr != nil && !qr.qr.IsEmpty() -} - -// Cond returns the condition number for the factorized matrix. -// Cond will panic if the receiver does not contain a factorization. -func (qr *QR) Cond() float64 { - if !qr.isValid() { - panic(badQR) - } - return qr.cond -} - -// TODO(btracey): Add in the "Reduced" forms for extracting the n×n orthogonal -// and upper triangular matrices. - -// RTo extracts the m×n upper trapezoidal matrix from a QR decomposition. -// -// If dst is empty, RTo will resize dst to be r×c. When dst is non-empty, -// RTo will panic if dst is not r×c. RTo will also panic if the receiver -// does not contain a successful factorization. -func (qr *QR) RTo(dst *Dense) { - if !qr.isValid() { - panic(badQR) - } - - r, c := qr.qr.Dims() - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - - // Disguise the QR as an upper triangular - t := &TriDense{ - mat: blas64.Triangular{ - N: c, - Stride: qr.qr.mat.Stride, - Data: qr.qr.mat.Data, - Uplo: blas.Upper, - Diag: blas.NonUnit, - }, - cap: qr.qr.capCols, - } - dst.Copy(t) - - // Zero below the triangular. - for i := r; i < c; i++ { - zero(dst.mat.Data[i*dst.mat.Stride : i*dst.mat.Stride+c]) - } -} - -// QTo extracts the r×r orthonormal matrix Q from a QR decomposition. -// -// If dst is empty, QTo will resize dst to be r×r. When dst is non-empty, -// QTo will panic if dst is not r×r. QTo will also panic if the receiver -// does not contain a successful factorization. -func (qr *QR) QTo(dst *Dense) { - if !qr.isValid() { - panic(badQR) - } - - r, _ := qr.qr.Dims() - if dst.IsEmpty() { - dst.ReuseAs(r, r) - } else { - r2, c2 := dst.Dims() - if r != r2 || r != c2 { - panic(ErrShape) - } - } - - if qr.q == nil || qr.q.IsEmpty() { - qr.updateQ() - } - dst.Copy(qr.q) -} - -// SolveTo finds a minimum-norm solution to a system of linear equations defined -// by the matrices A and b, where A is an m×n matrix represented in its QR factorized -// form. If A is singular or near-singular a Condition error is returned. -// See the documentation for Condition for more information. -// -// The minimization problem solved depends on the input parameters. -// -// If trans == false, find X such that ||A*X - B||_2 is minimized. -// If trans == true, find the minimum norm solution of Aᵀ * X = B. -// -// The solution matrix, X, is stored in place into dst. -// SolveTo will panic if the receiver does not contain a factorization. -func (qr *QR) SolveTo(dst *Dense, trans bool, b Matrix) error { - if !qr.isValid() { - panic(badQR) - } - - r, c := qr.qr.Dims() - br, bc := b.Dims() - - // The QR solve algorithm stores the result in-place into the right hand side. - // The storage for the answer must be large enough to hold both b and x. - // However, this method's receiver must be the size of x. Copy b, and then - // copy the result into m at the end. - if trans { - if c != br { - panic(ErrShape) - } - dst.reuseAsNonZeroed(r, bc) - } else { - if r != br { - panic(ErrShape) - } - dst.reuseAsNonZeroed(c, bc) - } - // Do not need to worry about overlap between m and b because x has its own - // independent storage. - w := getDenseWorkspace(max(r, c), bc, false) - w.Copy(b) - t := qr.qr.asTriDense(qr.qr.mat.Cols, blas.NonUnit, blas.Upper).mat - if trans { - ok := lapack64.Trtrs(blas.Trans, t, w.mat) - if !ok { - return Condition(math.Inf(1)) - } - for i := c; i < r; i++ { - zero(w.mat.Data[i*w.mat.Stride : i*w.mat.Stride+bc]) - } - work := []float64{0} - lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, w.mat, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, w.mat, work, len(work)) - putFloat64s(work) - } else { - work := []float64{0} - lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, w.mat, work, -1) - work = getFloat64s(int(work[0]), false) - lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, w.mat, work, len(work)) - putFloat64s(work) - - ok := lapack64.Trtrs(blas.NoTrans, t, w.mat) - if !ok { - return Condition(math.Inf(1)) - } - } - // X was set above to be the correct size for the result. - dst.Copy(w) - putDenseWorkspace(w) - if qr.cond > ConditionTolerance { - return Condition(qr.cond) - } - return nil -} - -// SolveVecTo finds a minimum-norm solution to a system of linear equations, -// -// Ax = b. -// -// See QR.SolveTo for the full documentation. -// SolveVecTo will panic if the receiver does not contain a factorization. -func (qr *QR) SolveVecTo(dst *VecDense, trans bool, b Vector) error { - if !qr.isValid() { - panic(badQR) - } - - r, c := qr.qr.Dims() - if _, bc := b.Dims(); bc != 1 { - panic(ErrShape) - } - - // The Solve implementation is non-trivial, so rather than duplicate the code, - // instead recast the VecDenses as Dense and call the matrix code. - bm := Matrix(b) - if rv, ok := b.(RawVectorer); ok { - bmat := rv.RawVector() - if dst != b { - dst.checkOverlap(bmat) - } - b := VecDense{mat: bmat} - bm = b.asDense() - } - if trans { - dst.reuseAsNonZeroed(r) - } else { - dst.reuseAsNonZeroed(c) - } - return qr.SolveTo(dst.asDense(), trans, bm) -} diff --git a/vendor/gonum.org/v1/gonum/mat/shadow.go b/vendor/gonum.org/v1/gonum/mat/shadow.go deleted file mode 100644 index 4fc24c34..00000000 --- a/vendor/gonum.org/v1/gonum/mat/shadow.go +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat - -import "gonum.org/v1/gonum/blas/blas64" - -// checkOverlap returns false if the receiver does not overlap data elements -// referenced by the parameter and panics otherwise. -// -// checkOverlap methods return a boolean to allow the check call to be added to a -// boolean expression, making use of short-circuit operators. -func checkOverlap(a, b blas64.General) bool { - if cap(a.Data) == 0 || cap(b.Data) == 0 { - return false - } - - off := offset(a.Data[:1], b.Data[:1]) - - if off == 0 { - // At least one element overlaps. - if a.Cols == b.Cols && a.Rows == b.Rows && a.Stride == b.Stride { - panic(regionIdentity) - } - panic(regionOverlap) - } - - if off > 0 && len(a.Data) <= off { - // We know a is completely before b. - return false - } - if off < 0 && len(b.Data) <= -off { - // We know a is completely after b. - return false - } - - if a.Stride != b.Stride && a.Stride != 1 && b.Stride != 1 { - // Too hard, so assume the worst; if either stride - // is one it will be caught in rectanglesOverlap. - panic(mismatchedStrides) - } - - if off < 0 { - off = -off - a.Cols, b.Cols = b.Cols, a.Cols - } - if rectanglesOverlap(off, a.Cols, b.Cols, min(a.Stride, b.Stride)) { - panic(regionOverlap) - } - return false -} - -func (m *Dense) checkOverlap(a blas64.General) bool { - return checkOverlap(m.RawMatrix(), a) -} - -func (m *Dense) checkOverlapMatrix(a Matrix) bool { - if m == a { - return false - } - var amat blas64.General - switch ar := a.(type) { - default: - return false - case RawMatrixer: - amat = ar.RawMatrix() - case RawSymmetricer: - amat = generalFromSymmetric(ar.RawSymmetric()) - case RawSymBander: - amat = generalFromSymmetricBand(ar.RawSymBand()) - case RawTriangular: - amat = generalFromTriangular(ar.RawTriangular()) - case RawVectorer: - r, c := a.Dims() - amat = generalFromVector(ar.RawVector(), r, c) - } - return m.checkOverlap(amat) -} - -func (s *SymDense) checkOverlap(a blas64.General) bool { - return checkOverlap(generalFromSymmetric(s.RawSymmetric()), a) -} - -func (s *SymDense) checkOverlapMatrix(a Matrix) bool { - if s == a { - return false - } - var amat blas64.General - switch ar := a.(type) { - default: - return false - case RawMatrixer: - amat = ar.RawMatrix() - case RawSymmetricer: - amat = generalFromSymmetric(ar.RawSymmetric()) - case RawSymBander: - amat = generalFromSymmetricBand(ar.RawSymBand()) - case RawTriangular: - amat = generalFromTriangular(ar.RawTriangular()) - case RawVectorer: - r, c := a.Dims() - amat = generalFromVector(ar.RawVector(), r, c) - } - return s.checkOverlap(amat) -} - -// generalFromSymmetric returns a blas64.General with the backing -// data and dimensions of a. -func generalFromSymmetric(a blas64.Symmetric) blas64.General { - return blas64.General{ - Rows: a.N, - Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } -} - -func (t *TriDense) checkOverlap(a blas64.General) bool { - return checkOverlap(generalFromTriangular(t.RawTriangular()), a) -} - -func (t *TriDense) checkOverlapMatrix(a Matrix) bool { - if t == a { - return false - } - var amat blas64.General - switch ar := a.(type) { - default: - return false - case RawMatrixer: - amat = ar.RawMatrix() - case RawSymmetricer: - amat = generalFromSymmetric(ar.RawSymmetric()) - case RawSymBander: - amat = generalFromSymmetricBand(ar.RawSymBand()) - case RawTriangular: - amat = generalFromTriangular(ar.RawTriangular()) - case RawVectorer: - r, c := a.Dims() - amat = generalFromVector(ar.RawVector(), r, c) - } - return t.checkOverlap(amat) -} - -// generalFromTriangular returns a blas64.General with the backing -// data and dimensions of a. -func generalFromTriangular(a blas64.Triangular) blas64.General { - return blas64.General{ - Rows: a.N, - Cols: a.N, - Stride: a.Stride, - Data: a.Data, - } -} - -func (v *VecDense) checkOverlap(a blas64.Vector) bool { - mat := v.mat - if cap(mat.Data) == 0 || cap(a.Data) == 0 { - return false - } - - off := offset(mat.Data[:1], a.Data[:1]) - - if off == 0 { - // At least one element overlaps. - if mat.Inc == a.Inc && len(mat.Data) == len(a.Data) { - panic(regionIdentity) - } - panic(regionOverlap) - } - - if off > 0 && len(mat.Data) <= off { - // We know v is completely before a. - return false - } - if off < 0 && len(a.Data) <= -off { - // We know v is completely after a. - return false - } - - if mat.Inc != a.Inc && mat.Inc != 1 && a.Inc != 1 { - // Too hard, so assume the worst; if either - // increment is one it will be caught below. - panic(mismatchedStrides) - } - inc := min(mat.Inc, a.Inc) - - if inc == 1 || off&inc == 0 { - panic(regionOverlap) - } - return false -} - -// generalFromVector returns a blas64.General with the backing -// data and dimensions of a. -func generalFromVector(a blas64.Vector, r, c int) blas64.General { - return blas64.General{ - Rows: r, - Cols: c, - Stride: a.Inc, - Data: a.Data, - } -} - -func (s *SymBandDense) checkOverlap(a blas64.General) bool { - return checkOverlap(generalFromSymmetricBand(s.RawSymBand()), a) -} - -//lint:ignore U1000 This will be used when we do shadow checks for banded matrices. -func (s *SymBandDense) checkOverlapMatrix(a Matrix) bool { - if s == a { - return false - } - var amat blas64.General - switch ar := a.(type) { - default: - return false - case RawMatrixer: - amat = ar.RawMatrix() - case RawSymmetricer: - amat = generalFromSymmetric(ar.RawSymmetric()) - case RawSymBander: - amat = generalFromSymmetricBand(ar.RawSymBand()) - case RawTriangular: - amat = generalFromTriangular(ar.RawTriangular()) - case RawVectorer: - r, c := a.Dims() - amat = generalFromVector(ar.RawVector(), r, c) - } - return s.checkOverlap(amat) -} - -// generalFromSymmetricBand returns a blas64.General with the backing -// data and dimensions of a. -func generalFromSymmetricBand(a blas64.SymmetricBand) blas64.General { - return blas64.General{ - Rows: a.N, - Cols: a.K + 1, - Data: a.Data, - Stride: a.Stride, - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/shadow_common.go b/vendor/gonum.org/v1/gonum/mat/shadow_common.go deleted file mode 100644 index e4cdf4dd..00000000 --- a/vendor/gonum.org/v1/gonum/mat/shadow_common.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat - -const ( - // regionOverlap is the panic string used for the general case - // of a matrix region overlap between a source and destination. - regionOverlap = "mat: bad region: overlap" - - // regionIdentity is the panic string used for the specific - // case of complete agreement between a source and a destination. - regionIdentity = "mat: bad region: identical" - - // mismatchedStrides is the panic string used for overlapping - // data slices with differing strides. - mismatchedStrides = "mat: bad region: different strides" -) - -// rectanglesOverlap returns whether the strided rectangles a and b overlap -// when b is offset by off elements after a but has at least one element before -// the end of a. off must be positive. a and b have aCols and bCols respectively. -// -// rectanglesOverlap works by shifting both matrices left such that the left -// column of a is at 0. The column indexes are flattened by obtaining the shifted -// relative left and right column positions modulo the common stride. This allows -// direct comparison of the column offsets when the matrix backing data slices -// are known to overlap. -func rectanglesOverlap(off, aCols, bCols, stride int) bool { - if stride == 1 { - // Unit stride means overlapping data - // slices must overlap as matrices. - return true - } - - // Flatten the shifted matrix column positions - // so a starts at 0, modulo the common stride. - aTo := aCols - // The mod stride operations here make the from - // and to indexes comparable between a and b when - // the data slices of a and b overlap. - bFrom := off % stride - bTo := (bFrom + bCols) % stride - - if bTo == 0 || bFrom < bTo { - // b matrix is not wrapped: compare for - // simple overlap. - return bFrom < aTo - } - - // b strictly wraps and so must overlap with a. - return true -} diff --git a/vendor/gonum.org/v1/gonum/mat/shadow_complex.go b/vendor/gonum.org/v1/gonum/mat/shadow_complex.go deleted file mode 100644 index 1a3f3fc2..00000000 --- a/vendor/gonum.org/v1/gonum/mat/shadow_complex.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright ©2015 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// TODO(kortschak): Generate this file from shadow.go when all complex type are available. - -package mat - -import "gonum.org/v1/gonum/blas/cblas128" - -// checkOverlapComplex returns false if the receiver does not overlap data elements -// referenced by the parameter and panics otherwise. -// -// checkOverlapComplex methods return a boolean to allow the check call to be added to a -// boolean expression, making use of short-circuit operators. -func checkOverlapComplex(a, b cblas128.General) bool { - if cap(a.Data) == 0 || cap(b.Data) == 0 { - return false - } - - off := offsetComplex(a.Data[:1], b.Data[:1]) - - if off == 0 { - // At least one element overlaps. - if a.Cols == b.Cols && a.Rows == b.Rows && a.Stride == b.Stride { - panic(regionIdentity) - } - panic(regionOverlap) - } - - if off > 0 && len(a.Data) <= off { - // We know a is completely before b. - return false - } - if off < 0 && len(b.Data) <= -off { - // We know a is completely after b. - return false - } - - if a.Stride != b.Stride && a.Stride != 1 && b.Stride != 1 { - // Too hard, so assume the worst; if either stride - // is one it will be caught in rectanglesOverlap. - panic(mismatchedStrides) - } - - if off < 0 { - off = -off - a.Cols, b.Cols = b.Cols, a.Cols - } - if rectanglesOverlap(off, a.Cols, b.Cols, min(a.Stride, b.Stride)) { - panic(regionOverlap) - } - return false -} - -func (m *CDense) checkOverlap(a cblas128.General) bool { - return checkOverlapComplex(m.RawCMatrix(), a) -} - -func (m *CDense) checkOverlapMatrix(a CMatrix) bool { - if m == a { - return false - } - var amat cblas128.General - switch ar := a.(type) { - default: - return false - case RawCMatrixer: - amat = ar.RawCMatrix() - } - return m.checkOverlap(amat) -} diff --git a/vendor/gonum.org/v1/gonum/mat/solve.go b/vendor/gonum.org/v1/gonum/mat/solve.go deleted file mode 100644 index ffccce8c..00000000 --- a/vendor/gonum.org/v1/gonum/mat/solve.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat - -// Solve solves the linear least squares problem -// -// minimize over x |b - A*x|_2 -// -// where A is an m×n matrix, b is a given m element vector and x is n element -// solution vector. Solve assumes that A has full rank, that is -// -// rank(A) = min(m,n) -// -// If m >= n, Solve finds the unique least squares solution of an overdetermined -// system. -// -// If m < n, there is an infinite number of solutions that satisfy b-A*x=0. In -// this case Solve finds the unique solution of an underdetermined system that -// minimizes |x|_2. -// -// Several right-hand side vectors b and solution vectors x can be handled in a -// single call. Vectors b are stored in the columns of the m×k matrix B. Vectors -// x will be stored in-place into the n×k receiver. -// -// If the underlying matrix of a is a SolveToer, its SolveTo method is used, -// otherwise a Dense copy of a will be used for the solution. -// -// If A does not have full rank, a Condition error is returned. See the -// documentation for Condition for more information. -func (m *Dense) Solve(a, b Matrix) error { - aU, aTrans := untransposeExtract(a) - if a, ok := aU.(SolveToer); ok { - return a.SolveTo(m, aTrans, b) - } - - ar, ac := a.Dims() - br, bc := b.Dims() - if ar != br { - panic(ErrShape) - } - m.reuseAsNonZeroed(ac, bc) - - switch { - case ar == ac: - if a == b { - // x = I. - if ar == 1 { - m.mat.Data[0] = 1 - return nil - } - for i := 0; i < ar; i++ { - v := m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+ac] - zero(v) - v[i] = 1 - } - return nil - } - var lu LU - lu.Factorize(a) - return lu.SolveTo(m, false, b) - case ar > ac: - var qr QR - qr.Factorize(a) - return qr.SolveTo(m, false, b) - default: - var lq LQ - lq.Factorize(a) - return lq.SolveTo(m, false, b) - } -} - -// SolveVec solves the linear least squares problem -// -// minimize over x |b - A*x|_2 -// -// where A is an m×n matrix, b is a given m element vector and x is n element -// solution vector. Solve assumes that A has full rank, that is -// -// rank(A) = min(m,n) -// -// If m >= n, Solve finds the unique least squares solution of an overdetermined -// system. -// -// If m < n, there is an infinite number of solutions that satisfy b-A*x=0. In -// this case Solve finds the unique solution of an underdetermined system that -// minimizes |x|_2. -// -// The solution vector x will be stored in-place into the receiver. -// -// If A does not have full rank, a Condition error is returned. See the -// documentation for Condition for more information. -func (v *VecDense) SolveVec(a Matrix, b Vector) error { - if _, bc := b.Dims(); bc != 1 { - panic(ErrShape) - } - _, c := a.Dims() - - // The Solve implementation is non-trivial, so rather than duplicate the code, - // instead recast the VecDenses as Dense and call the matrix code. - - if rv, ok := b.(RawVectorer); ok { - bmat := rv.RawVector() - if v != b { - v.checkOverlap(bmat) - } - v.reuseAsNonZeroed(c) - m := v.asDense() - // We conditionally create bm as m when b and v are identical - // to prevent the overlap detection code from identifying m - // and bm as overlapping but not identical. - bm := m - if v != b { - b := VecDense{mat: bmat} - bm = b.asDense() - } - return m.Solve(a, bm) - } - - v.reuseAsNonZeroed(c) - m := v.asDense() - return m.Solve(a, b) -} diff --git a/vendor/gonum.org/v1/gonum/mat/svd.go b/vendor/gonum.org/v1/gonum/mat/svd.go deleted file mode 100644 index 5244d9f6..00000000 --- a/vendor/gonum.org/v1/gonum/mat/svd.go +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -const badRcond = "mat: invalid rcond value" - -// SVD is a type for creating and using the Singular Value Decomposition -// of a matrix. -type SVD struct { - kind SVDKind - - s []float64 - u blas64.General - vt blas64.General -} - -// SVDKind specifies the treatment of singular vectors during an SVD -// factorization. -type SVDKind int - -const ( - // SVDNone specifies that no singular vectors should be computed during - // the decomposition. - SVDNone SVDKind = 0 - - // SVDThinU specifies the thin decomposition for U should be computed. - SVDThinU SVDKind = 1 << (iota - 1) - // SVDFullU specifies the full decomposition for U should be computed. - SVDFullU - // SVDThinV specifies the thin decomposition for V should be computed. - SVDThinV - // SVDFullV specifies the full decomposition for V should be computed. - SVDFullV - - // SVDThin is a convenience value for computing both thin vectors. - SVDThin SVDKind = SVDThinU | SVDThinV - // SVDFull is a convenience value for computing both full vectors. - SVDFull SVDKind = SVDFullU | SVDFullV -) - -// succFact returns whether the receiver contains a successful factorization. -func (svd *SVD) succFact() bool { - return len(svd.s) != 0 -} - -// Factorize computes the singular value decomposition (SVD) of the input matrix A. -// The singular values of A are computed in all cases, while the singular -// vectors are optionally computed depending on the input kind. -// -// The full singular value decomposition (kind == SVDFull) is a factorization -// of an m×n matrix A of the form -// -// A = U * Σ * Vᵀ -// -// where Σ is an m×n diagonal matrix, U is an m×m orthogonal matrix, and V is an -// n×n orthogonal matrix. The diagonal elements of Σ are the singular values of A. -// The first min(m,n) columns of U and V are, respectively, the left and right -// singular vectors of A. -// -// Significant storage space can be saved by using the thin representation of -// the SVD (kind == SVDThin) instead of the full SVD, especially if -// m >> n or m << n. The thin SVD finds -// -// A = U~ * Σ * V~ᵀ -// -// where U~ is of size m×min(m,n), Σ is a diagonal matrix of size min(m,n)×min(m,n) -// and V~ is of size n×min(m,n). -// -// Factorize returns whether the decomposition succeeded. If the decomposition -// failed, routines that require a successful factorization will panic. -func (svd *SVD) Factorize(a Matrix, kind SVDKind) (ok bool) { - // kill previous factorization - svd.s = svd.s[:0] - svd.kind = kind - - m, n := a.Dims() - var jobU, jobVT lapack.SVDJob - - // TODO(btracey): This code should be modified to have the smaller - // matrix written in-place into aCopy when the lapack/native/dgesvd - // implementation is complete. - switch { - case kind&SVDFullU != 0: - jobU = lapack.SVDAll - svd.u = blas64.General{ - Rows: m, - Cols: m, - Stride: m, - Data: use(svd.u.Data, m*m), - } - case kind&SVDThinU != 0: - jobU = lapack.SVDStore - svd.u = blas64.General{ - Rows: m, - Cols: min(m, n), - Stride: min(m, n), - Data: use(svd.u.Data, m*min(m, n)), - } - default: - jobU = lapack.SVDNone - } - switch { - case kind&SVDFullV != 0: - svd.vt = blas64.General{ - Rows: n, - Cols: n, - Stride: n, - Data: use(svd.vt.Data, n*n), - } - jobVT = lapack.SVDAll - case kind&SVDThinV != 0: - svd.vt = blas64.General{ - Rows: min(m, n), - Cols: n, - Stride: n, - Data: use(svd.vt.Data, min(m, n)*n), - } - jobVT = lapack.SVDStore - default: - jobVT = lapack.SVDNone - } - - // A is destroyed on call, so copy the matrix. - aCopy := DenseCopyOf(a) - svd.kind = kind - svd.s = use(svd.s, min(m, n)) - - work := []float64{0} - lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, -1) - work = getFloat64s(int(work[0]), false) - ok = lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, len(work)) - putFloat64s(work) - if !ok { - svd.kind = 0 - } - return ok -} - -// Kind returns the SVDKind of the decomposition. If no decomposition has been -// computed, Kind returns -1. -func (svd *SVD) Kind() SVDKind { - if !svd.succFact() { - return -1 - } - return svd.kind -} - -// Rank returns the rank of A based on the count of singular values greater than -// rcond scaled by the largest singular value. -// Rank will panic if the receiver does not contain a successful factorization or -// rcond is negative. -func (svd *SVD) Rank(rcond float64) int { - if rcond < 0 { - panic(badRcond) - } - if !svd.succFact() { - panic(badFact) - } - s0 := svd.s[0] - for i, v := range svd.s { - if v <= rcond*s0 { - return i - } - } - return len(svd.s) -} - -// Cond returns the 2-norm condition number for the factorized matrix. Cond will -// panic if the receiver does not contain a successful factorization. -func (svd *SVD) Cond() float64 { - if !svd.succFact() { - panic(badFact) - } - return svd.s[0] / svd.s[len(svd.s)-1] -} - -// Values returns the singular values of the factorized matrix in descending order. -// -// If the input slice is non-nil, the values will be stored in-place into -// the slice. In this case, the slice must have length min(m,n), and Values will -// panic with ErrSliceLengthMismatch otherwise. If the input slice is nil, a new -// slice of the appropriate length will be allocated and returned. -// -// Values will panic if the receiver does not contain a successful factorization. -func (svd *SVD) Values(s []float64) []float64 { - if !svd.succFact() { - panic(badFact) - } - if s == nil { - s = make([]float64, len(svd.s)) - } - if len(s) != len(svd.s) { - panic(ErrSliceLengthMismatch) - } - copy(s, svd.s) - return s -} - -// UTo extracts the matrix U from the singular value decomposition. The first -// min(m,n) columns are the left singular vectors and correspond to the singular -// values as returned from SVD.Values. -// -// If dst is empty, UTo will resize dst to be m×m if the full U was computed -// and size m×min(m,n) if the thin U was computed. When dst is non-empty, then -// UTo will panic if dst is not the appropriate size. UTo will also panic if -// the receiver does not contain a successful factorization, or if U was -// not computed during factorization. -func (svd *SVD) UTo(dst *Dense) { - if !svd.succFact() { - panic(badFact) - } - kind := svd.kind - if kind&SVDThinU == 0 && kind&SVDFullU == 0 { - panic("svd: u not computed during factorization") - } - r := svd.u.Rows - c := svd.u.Cols - if dst.IsEmpty() { - dst.ReuseAs(r, c) - } else { - r2, c2 := dst.Dims() - if r != r2 || c != c2 { - panic(ErrShape) - } - } - - tmp := &Dense{ - mat: svd.u, - capRows: r, - capCols: c, - } - dst.Copy(tmp) -} - -// VTo extracts the matrix V from the singular value decomposition. The first -// min(m,n) columns are the right singular vectors and correspond to the singular -// values as returned from SVD.Values. -// -// If dst is empty, VTo will resize dst to be n×n if the full V was computed -// and size n×min(m,n) if the thin V was computed. When dst is non-empty, then -// VTo will panic if dst is not the appropriate size. VTo will also panic if -// the receiver does not contain a successful factorization, or if V was -// not computed during factorization. -func (svd *SVD) VTo(dst *Dense) { - if !svd.succFact() { - panic(badFact) - } - kind := svd.kind - if kind&SVDThinV == 0 && kind&SVDFullV == 0 { - panic("svd: v not computed during factorization") - } - r := svd.vt.Rows - c := svd.vt.Cols - if dst.IsEmpty() { - dst.ReuseAs(c, r) - } else { - r2, c2 := dst.Dims() - if c != r2 || r != c2 { - panic(ErrShape) - } - } - - tmp := &Dense{ - mat: svd.vt, - capRows: r, - capCols: c, - } - dst.Copy(tmp.T()) -} - -// SolveTo calculates the minimum-norm solution to a linear least squares problem -// -// minimize over n-element vectors x: |b - A*x|_2 and |x|_2 -// -// where b is a given m-element vector, using the SVD of m×n matrix A stored in -// the receiver. A may be rank-deficient, that is, the given effective rank can be -// -// rank ≤ min(m,n) -// -// The rank can be computed using SVD.Rank. -// -// Several right-hand side vectors b and solution vectors x can be handled in a -// single call. Vectors b are stored in the columns of the m×k matrix B and the -// resulting vectors x will be stored in the columns of dst. dst must be either -// empty or have the size equal to n×k. -// -// The decomposition must have been factorized computing both the U and V -// singular vectors. -// -// SolveTo returns the residuals calculated from the complete SVD. For this -// value to be valid the factorization must have been performed with at least -// SVDFullU. -func (svd *SVD) SolveTo(dst *Dense, b Matrix, rank int) []float64 { - if !svd.succFact() { - panic(badFact) - } - if rank < 1 || len(svd.s) < rank { - panic("svd: rank out of range") - } - kind := svd.kind - if kind&SVDThinU == 0 && kind&SVDFullU == 0 { - panic("svd: u not computed during factorization") - } - if kind&SVDThinV == 0 && kind&SVDFullV == 0 { - panic("svd: v not computed during factorization") - } - - u := Dense{ - mat: svd.u, - capRows: svd.u.Rows, - capCols: svd.u.Cols, - } - vt := Dense{ - mat: svd.vt, - capRows: svd.vt.Rows, - capCols: svd.vt.Cols, - } - s := svd.s[:rank] - - _, bc := b.Dims() - c := getDenseWorkspace(svd.u.Cols, bc, false) - defer putDenseWorkspace(c) - c.Mul(u.T(), b) - - y := getDenseWorkspace(rank, bc, false) - defer putDenseWorkspace(y) - y.DivElem(c.slice(0, rank, 0, bc), repVector{vec: s, cols: bc}) - dst.Mul(vt.slice(0, rank, 0, svd.vt.Cols).T(), y) - - res := make([]float64, bc) - if rank < svd.u.Cols { - c = c.slice(len(s), svd.u.Cols, 0, bc) - for j := range res { - col := c.ColView(j) - res[j] = Dot(col, col) - } - } - return res -} - -type repVector struct { - vec []float64 - cols int -} - -func (m repVector) Dims() (r, c int) { return len(m.vec), m.cols } -func (m repVector) At(i, j int) float64 { - if i < 0 || len(m.vec) <= i || j < 0 || m.cols <= j { - panic(ErrIndexOutOfRange.string) // Panic with string to prevent mat.Error recovery. - } - return m.vec[i] -} -func (m repVector) T() Matrix { return Transpose{m} } - -// SolveVecTo calculates the minimum-norm solution to a linear least squares problem -// -// minimize over n-element vectors x: |b - A*x|_2 and |x|_2 -// -// where b is a given m-element vector, using the SVD of m×n matrix A stored in -// the receiver. A may be rank-deficient, that is, the given effective rank can be -// -// rank ≤ min(m,n) -// -// The rank can be computed using SVD.Rank. -// -// The resulting vector x will be stored in dst. dst must be either empty or -// have length equal to n. -// -// The decomposition must have been factorized computing both the U and V -// singular vectors. -// -// SolveVecTo returns the residuals calculated from the complete SVD. For this -// value to be valid the factorization must have been performed with at least -// SVDFullU. -func (svd *SVD) SolveVecTo(dst *VecDense, b Vector, rank int) float64 { - if !svd.succFact() { - panic(badFact) - } - if rank < 1 || len(svd.s) < rank { - panic("svd: rank out of range") - } - kind := svd.kind - if kind&SVDThinU == 0 && kind&SVDFullU == 0 { - panic("svd: u not computed during factorization") - } - if kind&SVDThinV == 0 && kind&SVDFullV == 0 { - panic("svd: v not computed during factorization") - } - - u := Dense{ - mat: svd.u, - capRows: svd.u.Rows, - capCols: svd.u.Cols, - } - vt := Dense{ - mat: svd.vt, - capRows: svd.vt.Rows, - capCols: svd.vt.Cols, - } - s := svd.s[:rank] - - c := getVecDenseWorkspace(svd.u.Cols, false) - defer putVecDenseWorkspace(c) - c.MulVec(u.T(), b) - - y := getVecDenseWorkspace(rank, false) - defer putVecDenseWorkspace(y) - y.DivElemVec(c.sliceVec(0, rank), NewVecDense(rank, s)) - dst.MulVec(vt.slice(0, rank, 0, svd.vt.Cols).T(), y) - - var res float64 - if rank < c.Len() { - c = c.sliceVec(rank, c.Len()) - res = Dot(c, c) - } - return res -} diff --git a/vendor/gonum.org/v1/gonum/mat/symband.go b/vendor/gonum.org/v1/gonum/mat/symband.go deleted file mode 100644 index 63638ea9..00000000 --- a/vendor/gonum.org/v1/gonum/mat/symband.go +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright ©2017 The Gonum 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 mat - -import ( - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -var ( - symBandDense *SymBandDense - _ Matrix = symBandDense - _ allMatrix = symBandDense - _ denseMatrix = symBandDense - _ Symmetric = symBandDense - _ Banded = symBandDense - _ SymBanded = symBandDense - _ RawSymBander = symBandDense - _ MutableSymBanded = symBandDense - - _ NonZeroDoer = symBandDense - _ RowNonZeroDoer = symBandDense - _ ColNonZeroDoer = symBandDense -) - -// SymBandDense represents a symmetric band matrix in dense storage format. -type SymBandDense struct { - mat blas64.SymmetricBand -} - -// SymBanded is a symmetric band matrix interface type. -type SymBanded interface { - Banded - - // SymmetricDim returns the number of rows/columns in the matrix. - SymmetricDim() int - - // SymBand returns the number of rows/columns in the matrix, and the size of - // the bandwidth. - SymBand() (n, k int) -} - -// MutableSymBanded is a symmetric band matrix interface type that allows elements -// to be altered. -type MutableSymBanded interface { - SymBanded - SetSymBand(i, j int, v float64) -} - -// A RawSymBander can return a blas64.SymmetricBand representation of the receiver. -// Changes to the blas64.SymmetricBand.Data slice will be reflected in the original -// matrix, changes to the N, K, Stride and Uplo fields will not. -type RawSymBander interface { - RawSymBand() blas64.SymmetricBand -} - -// NewSymBandDense creates a new SymBand matrix with n rows and columns. If data == nil, -// a new slice is allocated for the backing slice. If len(data) == n*(k+1), -// data is used as the backing slice, and changes to the elements of the returned -// SymBandDense will be reflected in data. If neither of these is true, NewSymBandDense -// will panic. k must be at least zero and less than n, otherwise NewSymBandDense will panic. -// -// The data must be arranged in row-major order constructed by removing the zeros -// from the rows outside the band and aligning the diagonals. SymBandDense matrices -// are stored in the upper triangle. For example, the matrix -// -// 1 2 3 0 0 0 -// 2 4 5 6 0 0 -// 3 5 7 8 9 0 -// 0 6 8 10 11 12 -// 0 0 9 11 13 14 -// 0 0 0 12 14 15 -// -// becomes (* entries are never accessed) -// -// 1 2 3 -// 4 5 6 -// 7 8 9 -// 10 11 12 -// 13 14 * -// 15 * * -// -// which is passed to NewSymBandDense as []float64{1, 2, ..., 15, *, *, *} with k=2. -// Only the values in the band portion of the matrix are used. -func NewSymBandDense(n, k int, data []float64) *SymBandDense { - if n <= 0 || k < 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic("mat: negative dimension") - } - if k+1 > n { - panic("mat: band out of range") - } - bc := k + 1 - if data != nil && len(data) != n*bc { - panic(ErrShape) - } - if data == nil { - data = make([]float64, n*bc) - } - return &SymBandDense{ - mat: blas64.SymmetricBand{ - N: n, - K: k, - Stride: bc, - Uplo: blas.Upper, - Data: data, - }, - } -} - -// Dims returns the number of rows and columns in the matrix. -func (s *SymBandDense) Dims() (r, c int) { - return s.mat.N, s.mat.N -} - -// SymmetricDim returns the size of the receiver. -func (s *SymBandDense) SymmetricDim() int { - return s.mat.N -} - -// Bandwidth returns the bandwidths of the matrix. -func (s *SymBandDense) Bandwidth() (kl, ku int) { - return s.mat.K, s.mat.K -} - -// SymBand returns the number of rows/columns in the matrix, and the size of -// the bandwidth. -func (s *SymBandDense) SymBand() (n, k int) { - return s.mat.N, s.mat.K -} - -// T implements the Matrix interface. Symmetric matrices, by definition, are -// equal to their transpose, and this is a no-op. -func (s *SymBandDense) T() Matrix { - return s -} - -// TBand implements the Banded interface. -func (s *SymBandDense) TBand() Banded { - return s -} - -// RawSymBand returns the underlying blas64.SymBand used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in returned blas64.SymBand. -func (s *SymBandDense) RawSymBand() blas64.SymmetricBand { - return s.mat -} - -// SetRawSymBand sets the underlying blas64.SymmetricBand used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in the input. -// -// The supplied SymmetricBand must use blas.Upper storage format. -func (s *SymBandDense) SetRawSymBand(mat blas64.SymmetricBand) { - if mat.Uplo != blas.Upper { - panic("mat: blas64.SymmetricBand does not have blas.Upper storage") - } - s.mat = mat -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (s *SymBandDense) IsEmpty() bool { - return s.mat.Stride == 0 -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (s *SymBandDense) Reset() { - s.mat.N = 0 - s.mat.K = 0 - s.mat.Stride = 0 - s.mat.Uplo = 0 - s.mat.Data = s.mat.Data[:0] -} - -// Zero sets all of the matrix elements to zero. -func (s *SymBandDense) Zero() { - for i := 0; i < s.mat.N; i++ { - u := min(1+s.mat.K, s.mat.N-i) - zero(s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+u]) - } -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (s *SymBandDense) DiagView() Diagonal { - n := s.mat.N - return &DiagDense{ - mat: blas64.Vector{ - N: n, - Inc: s.mat.Stride, - Data: s.mat.Data[:(n-1)*s.mat.Stride+1], - }, - } -} - -// DoNonZero calls the function fn for each of the non-zero elements of s. The function fn -// takes a row/column index and the element value of s at (i, j). -func (s *SymBandDense) DoNonZero(fn func(i, j int, v float64)) { - for i := 0; i < s.mat.N; i++ { - for j := max(0, i-s.mat.K); j < min(s.mat.N, i+s.mat.K+1); j++ { - v := s.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } -} - -// DoRowNonZero calls the function fn for each of the non-zero elements of row i of s. The function fn -// takes a row/column index and the element value of s at (i, j). -func (s *SymBandDense) DoRowNonZero(i int, fn func(i, j int, v float64)) { - if i < 0 || s.mat.N <= i { - panic(ErrRowAccess) - } - for j := max(0, i-s.mat.K); j < min(s.mat.N, i+s.mat.K+1); j++ { - v := s.at(i, j) - if v != 0 { - fn(i, j, v) - } - } -} - -// DoColNonZero calls the function fn for each of the non-zero elements of column j of s. The function fn -// takes a row/column index and the element value of s at (i, j). -func (s *SymBandDense) DoColNonZero(j int, fn func(i, j int, v float64)) { - if j < 0 || s.mat.N <= j { - panic(ErrColAccess) - } - for i := 0; i < s.mat.N; i++ { - if i-s.mat.K <= j && j < i+s.mat.K+1 { - v := s.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the matrix has zero size. -func (s *SymBandDense) Norm(norm float64) float64 { - if s.IsEmpty() { - panic(ErrZeroLength) - } - lnorm := normLapack(norm, false) - if lnorm == lapack.MaxColumnSum || lnorm == lapack.MaxRowSum { - work := getFloat64s(s.mat.N, false) - defer putFloat64s(work) - return lapack64.Lansb(lnorm, s.mat, work) - } - return lapack64.Lansb(lnorm, s.mat, nil) -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrZeroLength if the matrix has zero size. -func (s *SymBandDense) Trace() float64 { - if s.IsEmpty() { - panic(ErrZeroLength) - } - rb := s.RawSymBand() - var tr float64 - for i := 0; i < rb.N; i++ { - tr += rb.Data[i*rb.Stride] - } - return tr -} - -// MulVecTo computes S⋅x storing the result into dst. -func (s *SymBandDense) MulVecTo(dst *VecDense, _ bool, x Vector) { - n := s.mat.N - if x.Len() != n { - panic(ErrShape) - } - dst.reuseAsNonZeroed(n) - - xMat, _ := untransposeExtract(x) - if xVec, ok := xMat.(*VecDense); ok { - if dst != xVec { - dst.checkOverlap(xVec.mat) - blas64.Sbmv(1, s.mat, xVec.mat, 0, dst.mat) - } else { - xCopy := getVecDenseWorkspace(n, false) - xCopy.CloneFromVec(xVec) - blas64.Sbmv(1, s.mat, xCopy.mat, 0, dst.mat) - putVecDenseWorkspace(xCopy) - } - } else { - xCopy := getVecDenseWorkspace(n, false) - xCopy.CloneFromVec(x) - blas64.Sbmv(1, s.mat, xCopy.mat, 0, dst.mat) - putVecDenseWorkspace(xCopy) - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/symmetric.go b/vendor/gonum.org/v1/gonum/mat/symmetric.go deleted file mode 100644 index e38e4c7b..00000000 --- a/vendor/gonum.org/v1/gonum/mat/symmetric.go +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -var ( - symDense *SymDense - - _ Matrix = symDense - _ allMatrix = symDense - _ denseMatrix = symDense - _ Symmetric = symDense - _ RawSymmetricer = symDense - _ MutableSymmetric = symDense -) - -const badSymTriangle = "mat: blas64.Symmetric not upper" - -// SymDense is a symmetric matrix that uses dense storage. SymDense -// matrices are stored in the upper triangle. -type SymDense struct { - mat blas64.Symmetric - cap int -} - -// Symmetric represents a symmetric matrix (where the element at {i, j} equals -// the element at {j, i}). Symmetric matrices are always square. -type Symmetric interface { - Matrix - // SymmetricDim returns the number of rows/columns in the matrix. - SymmetricDim() int -} - -// A RawSymmetricer can return a view of itself as a BLAS Symmetric matrix. -type RawSymmetricer interface { - RawSymmetric() blas64.Symmetric -} - -// A MutableSymmetric can set elements of a symmetric matrix. -type MutableSymmetric interface { - Symmetric - SetSym(i, j int, v float64) -} - -// NewSymDense creates a new Symmetric matrix with n rows and columns. If data == nil, -// a new slice is allocated for the backing slice. If len(data) == n*n, data is -// used as the backing slice, and changes to the elements of the returned SymDense -// will be reflected in data. If neither of these is true, NewSymDense will panic. -// NewSymDense will panic if n is zero. -// -// The data must be arranged in row-major order, i.e. the (i*c + j)-th -// element in the data slice is the {i, j}-th element in the matrix. -// Only the values in the upper triangular portion of the matrix are used. -func NewSymDense(n int, data []float64) *SymDense { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic("mat: negative dimension") - } - if data != nil && n*n != len(data) { - panic(ErrShape) - } - if data == nil { - data = make([]float64, n*n) - } - return &SymDense{ - mat: blas64.Symmetric{ - N: n, - Stride: n, - Data: data, - Uplo: blas.Upper, - }, - cap: n, - } -} - -// Dims returns the number of rows and columns in the matrix. -func (s *SymDense) Dims() (r, c int) { - return s.mat.N, s.mat.N -} - -// Caps returns the number of rows and columns in the backing matrix. -func (s *SymDense) Caps() (r, c int) { - return s.cap, s.cap -} - -// T returns the receiver, the transpose of a symmetric matrix. -func (s *SymDense) T() Matrix { - return s -} - -// SymmetricDim implements the Symmetric interface and returns the number of rows -// and columns in the matrix. -func (s *SymDense) SymmetricDim() int { - return s.mat.N -} - -// RawSymmetric returns the matrix as a blas64.Symmetric. The returned -// value must be stored in upper triangular format. -func (s *SymDense) RawSymmetric() blas64.Symmetric { - return s.mat -} - -// SetRawSymmetric sets the underlying blas64.Symmetric used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in the input. -// -// The supplied Symmetric must use blas.Upper storage format. -func (s *SymDense) SetRawSymmetric(mat blas64.Symmetric) { - if mat.Uplo != blas.Upper { - panic(badSymTriangle) - } - s.cap = mat.N - s.mat = mat -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (s *SymDense) Reset() { - // N and Stride must be zeroed in unison. - s.mat.N, s.mat.Stride = 0, 0 - s.mat.Data = s.mat.Data[:0] -} - -// ReuseAsSym changes the receiver if it IsEmpty() to be of size n×n. -// -// ReuseAsSym re-uses the backing data slice if it has sufficient capacity, -// otherwise a new slice is allocated. The backing data is zero on return. -// -// ReuseAsSym panics if the receiver is not empty, and panics if -// the input size is less than one. To empty the receiver for re-use, -// Reset should be used. -func (s *SymDense) ReuseAsSym(n int) { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if !s.IsEmpty() { - panic(ErrReuseNonEmpty) - } - s.reuseAsZeroed(n) -} - -// Zero sets all of the matrix elements to zero. -func (s *SymDense) Zero() { - for i := 0; i < s.mat.N; i++ { - zero(s.mat.Data[i*s.mat.Stride+i : i*s.mat.Stride+s.mat.N]) - } -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (s *SymDense) IsEmpty() bool { - // It must be the case that m.Dims() returns - // zeros in this case. See comment in Reset(). - return s.mat.N == 0 -} - -// reuseAsNonZeroed resizes an empty matrix to a n×n matrix, -// or checks that a non-empty matrix is n×n. -func (s *SymDense) reuseAsNonZeroed(n int) { - // reuseAsNonZeroed must be kept in sync with reuseAsZeroed. - if n == 0 { - panic(ErrZeroLength) - } - if s.mat.N > s.cap { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if s.IsEmpty() { - s.mat = blas64.Symmetric{ - N: n, - Stride: n, - Data: use(s.mat.Data, n*n), - Uplo: blas.Upper, - } - s.cap = n - return - } - if s.mat.Uplo != blas.Upper { - panic(badSymTriangle) - } - if s.mat.N != n { - panic(ErrShape) - } -} - -// reuseAsNonZeroed resizes an empty matrix to a n×n matrix, -// or checks that a non-empty matrix is n×n. It then zeros the -// elements of the matrix. -func (s *SymDense) reuseAsZeroed(n int) { - // reuseAsZeroed must be kept in sync with reuseAsNonZeroed. - if n == 0 { - panic(ErrZeroLength) - } - if s.mat.N > s.cap { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if s.IsEmpty() { - s.mat = blas64.Symmetric{ - N: n, - Stride: n, - Data: useZeroed(s.mat.Data, n*n), - Uplo: blas.Upper, - } - s.cap = n - return - } - if s.mat.Uplo != blas.Upper { - panic(badSymTriangle) - } - if s.mat.N != n { - panic(ErrShape) - } - s.Zero() -} - -func (s *SymDense) isolatedWorkspace(a Symmetric) (w *SymDense, restore func()) { - n := a.SymmetricDim() - if n == 0 { - panic(ErrZeroLength) - } - w = getSymDenseWorkspace(n, false) - return w, func() { - s.CopySym(w) - putSymDenseWorkspace(w) - } -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (s *SymDense) DiagView() Diagonal { - n := s.mat.N - return &DiagDense{ - mat: blas64.Vector{ - N: n, - Inc: s.mat.Stride + 1, - Data: s.mat.Data[:(n-1)*s.mat.Stride+n], - }, - } -} - -func (s *SymDense) AddSym(a, b Symmetric) { - n := a.SymmetricDim() - if n != b.SymmetricDim() { - panic(ErrShape) - } - s.reuseAsNonZeroed(n) - - if a, ok := a.(RawSymmetricer); ok { - if b, ok := b.(RawSymmetricer); ok { - amat, bmat := a.RawSymmetric(), b.RawSymmetric() - if s != a { - s.checkOverlap(generalFromSymmetric(amat)) - } - if s != b { - s.checkOverlap(generalFromSymmetric(bmat)) - } - for i := 0; i < n; i++ { - btmp := bmat.Data[i*bmat.Stride+i : i*bmat.Stride+n] - stmp := s.mat.Data[i*s.mat.Stride+i : i*s.mat.Stride+n] - for j, v := range amat.Data[i*amat.Stride+i : i*amat.Stride+n] { - stmp[j] = v + btmp[j] - } - } - return - } - } - - s.checkOverlapMatrix(a) - s.checkOverlapMatrix(b) - for i := 0; i < n; i++ { - stmp := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] - for j := i; j < n; j++ { - stmp[j] = a.At(i, j) + b.At(i, j) - } - } -} - -func (s *SymDense) CopySym(a Symmetric) int { - n := a.SymmetricDim() - n = min(n, s.mat.N) - if n == 0 { - return 0 - } - switch a := a.(type) { - case RawSymmetricer: - amat := a.RawSymmetric() - if amat.Uplo != blas.Upper { - panic(badSymTriangle) - } - for i := 0; i < n; i++ { - copy(s.mat.Data[i*s.mat.Stride+i:i*s.mat.Stride+n], amat.Data[i*amat.Stride+i:i*amat.Stride+n]) - } - default: - for i := 0; i < n; i++ { - stmp := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] - for j := i; j < n; j++ { - stmp[j] = a.At(i, j) - } - } - } - return n -} - -// SymRankOne performs a symmetric rank-one update to the matrix a with x, -// which is treated as a column vector, and stores the result in the receiver -// -// s = a + alpha * x * xᵀ -func (s *SymDense) SymRankOne(a Symmetric, alpha float64, x Vector) { - n := x.Len() - if a.SymmetricDim() != n { - panic(ErrShape) - } - s.reuseAsNonZeroed(n) - - if s != a { - if rs, ok := a.(RawSymmetricer); ok { - s.checkOverlap(generalFromSymmetric(rs.RawSymmetric())) - } - s.CopySym(a) - } - - xU, _ := untransposeExtract(x) - if rv, ok := xU.(*VecDense); ok { - r, c := xU.Dims() - xmat := rv.mat - s.checkOverlap(generalFromVector(xmat, r, c)) - blas64.Syr(alpha, xmat, s.mat) - return - } - - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - s.set(i, j, s.at(i, j)+alpha*x.AtVec(i)*x.AtVec(j)) - } - } -} - -// SymRankK performs a symmetric rank-k update to the matrix a and stores the -// result into the receiver. If a is zero, see SymOuterK. -// -// s = a + alpha * x * x' -func (s *SymDense) SymRankK(a Symmetric, alpha float64, x Matrix) { - n := a.SymmetricDim() - r, _ := x.Dims() - if r != n { - panic(ErrShape) - } - xMat, aTrans := untransposeExtract(x) - var g blas64.General - if rm, ok := xMat.(*Dense); ok { - g = rm.mat - } else { - g = DenseCopyOf(x).mat - aTrans = false - } - if a != s { - if rs, ok := a.(RawSymmetricer); ok { - s.checkOverlap(generalFromSymmetric(rs.RawSymmetric())) - } - s.reuseAsNonZeroed(n) - s.CopySym(a) - } - t := blas.NoTrans - if aTrans { - t = blas.Trans - } - blas64.Syrk(t, alpha, g, 1, s.mat) -} - -// SymOuterK calculates the outer product of x with itself and stores -// the result into the receiver. It is equivalent to the matrix -// multiplication -// -// s = alpha * x * x'. -// -// In order to update an existing matrix, see SymRankOne. -func (s *SymDense) SymOuterK(alpha float64, x Matrix) { - n, _ := x.Dims() - switch { - case s.IsEmpty(): - s.mat = blas64.Symmetric{ - N: n, - Stride: n, - Data: useZeroed(s.mat.Data, n*n), - Uplo: blas.Upper, - } - s.cap = n - s.SymRankK(s, alpha, x) - case s.mat.Uplo != blas.Upper: - panic(badSymTriangle) - case s.mat.N == n: - if s == x { - w := getSymDenseWorkspace(n, true) - w.SymRankK(w, alpha, x) - s.CopySym(w) - putSymDenseWorkspace(w) - } else { - switch r := x.(type) { - case RawMatrixer: - s.checkOverlap(r.RawMatrix()) - case RawSymmetricer: - s.checkOverlap(generalFromSymmetric(r.RawSymmetric())) - case RawTriangular: - s.checkOverlap(generalFromTriangular(r.RawTriangular())) - } - // Only zero the upper triangle. - for i := 0; i < n; i++ { - ri := i * s.mat.Stride - zero(s.mat.Data[ri+i : ri+n]) - } - s.SymRankK(s, alpha, x) - } - default: - panic(ErrShape) - } -} - -// RankTwo performs a symmetric rank-two update to the matrix a with the -// vectors x and y, which are treated as column vectors, and stores the -// result in the receiver -// -// m = a + alpha * (x * yᵀ + y * xᵀ) -func (s *SymDense) RankTwo(a Symmetric, alpha float64, x, y Vector) { - n := s.mat.N - if x.Len() != n { - panic(ErrShape) - } - if y.Len() != n { - panic(ErrShape) - } - - if s != a { - if rs, ok := a.(RawSymmetricer); ok { - s.checkOverlap(generalFromSymmetric(rs.RawSymmetric())) - } - } - - var xmat, ymat blas64.Vector - fast := true - xU, _ := untransposeExtract(x) - if rv, ok := xU.(*VecDense); ok { - r, c := xU.Dims() - xmat = rv.mat - s.checkOverlap(generalFromVector(xmat, r, c)) - } else { - fast = false - } - yU, _ := untransposeExtract(y) - if rv, ok := yU.(*VecDense); ok { - r, c := yU.Dims() - ymat = rv.mat - s.checkOverlap(generalFromVector(ymat, r, c)) - } else { - fast = false - } - - if s != a { - if rs, ok := a.(RawSymmetricer); ok { - s.checkOverlap(generalFromSymmetric(rs.RawSymmetric())) - } - s.reuseAsNonZeroed(n) - s.CopySym(a) - } - - if fast { - if s != a { - s.reuseAsNonZeroed(n) - s.CopySym(a) - } - blas64.Syr2(alpha, xmat, ymat, s.mat) - return - } - - for i := 0; i < n; i++ { - s.reuseAsNonZeroed(n) - for j := i; j < n; j++ { - s.set(i, j, a.At(i, j)+alpha*(x.AtVec(i)*y.AtVec(j)+y.AtVec(i)*x.AtVec(j))) - } - } -} - -// ScaleSym multiplies the elements of a by f, placing the result in the receiver. -func (s *SymDense) ScaleSym(f float64, a Symmetric) { - n := a.SymmetricDim() - s.reuseAsNonZeroed(n) - if a, ok := a.(RawSymmetricer); ok { - amat := a.RawSymmetric() - if s != a { - s.checkOverlap(generalFromSymmetric(amat)) - } - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - s.mat.Data[i*s.mat.Stride+j] = f * amat.Data[i*amat.Stride+j] - } - } - return - } - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - s.mat.Data[i*s.mat.Stride+j] = f * a.At(i, j) - } - } -} - -// SubsetSym extracts a subset of the rows and columns of the matrix a and stores -// the result in-place into the receiver. The resulting matrix size is -// len(set)×len(set). Specifically, at the conclusion of SubsetSym, -// s.At(i, j) equals a.At(set[i], set[j]). Note that the supplied set does not -// have to be a strict subset, dimension repeats are allowed. -func (s *SymDense) SubsetSym(a Symmetric, set []int) { - n := len(set) - na := a.SymmetricDim() - s.reuseAsNonZeroed(n) - var restore func() - if a == s { - s, restore = s.isolatedWorkspace(a) - defer restore() - } - - if a, ok := a.(RawSymmetricer); ok { - raw := a.RawSymmetric() - if s != a { - s.checkOverlap(generalFromSymmetric(raw)) - } - for i := 0; i < n; i++ { - ssub := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] - r := set[i] - rsub := raw.Data[r*raw.Stride : r*raw.Stride+na] - for j := i; j < n; j++ { - c := set[j] - if r <= c { - ssub[j] = rsub[c] - } else { - ssub[j] = raw.Data[c*raw.Stride+r] - } - } - } - return - } - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - s.mat.Data[i*s.mat.Stride+j] = a.At(set[i], set[j]) - } - } -} - -// SliceSym returns a new Matrix that shares backing data with the receiver. -// The returned matrix starts at {i,i} of the receiver and extends k-i rows -// and columns. The final row and column in the resulting matrix is k-1. -// SliceSym panics with ErrIndexOutOfRange if the slice is outside the -// capacity of the receiver. -func (s *SymDense) SliceSym(i, k int) Symmetric { - return s.sliceSym(i, k) -} - -func (s *SymDense) sliceSym(i, k int) *SymDense { - sz := s.cap - if i < 0 || sz < i || k < i || sz < k { - panic(ErrIndexOutOfRange) - } - v := *s - v.mat.Data = s.mat.Data[i*s.mat.Stride+i : (k-1)*s.mat.Stride+k] - v.mat.N = k - i - v.cap = s.cap - i - return &v -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the matrix has zero size. -func (s *SymDense) Norm(norm float64) float64 { - if s.IsEmpty() { - panic(ErrZeroLength) - } - lnorm := normLapack(norm, false) - if lnorm == lapack.MaxColumnSum || lnorm == lapack.MaxRowSum { - work := getFloat64s(s.mat.N, false) - defer putFloat64s(work) - return lapack64.Lansy(lnorm, s.mat, work) - } - return lapack64.Lansy(lnorm, s.mat, nil) -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrZeroLength if the matrix has zero size. -func (s *SymDense) Trace() float64 { - if s.IsEmpty() { - panic(ErrZeroLength) - } - // TODO(btracey): could use internal asm sum routine. - var v float64 - for i := 0; i < s.mat.N; i++ { - v += s.mat.Data[i*s.mat.Stride+i] - } - return v -} - -// GrowSym returns the receiver expanded by n rows and n columns. If the -// dimensions of the expanded matrix are outside the capacity of the receiver -// a new allocation is made, otherwise not. Note that the receiver itself is -// not modified during the call to GrowSquare. -func (s *SymDense) GrowSym(n int) Symmetric { - if n < 0 { - panic(ErrIndexOutOfRange) - } - if n == 0 { - return s - } - var v SymDense - n += s.mat.N - if s.IsEmpty() || n > s.cap { - v.mat = blas64.Symmetric{ - N: n, - Stride: n, - Uplo: blas.Upper, - Data: make([]float64, n*n), - } - v.cap = n - // Copy elements, including those not currently visible. Use a temporary - // structure to avoid modifying the receiver. - var tmp SymDense - tmp.mat = blas64.Symmetric{ - N: s.cap, - Stride: s.mat.Stride, - Data: s.mat.Data, - Uplo: s.mat.Uplo, - } - tmp.cap = s.cap - v.CopySym(&tmp) - return &v - } - v.mat = blas64.Symmetric{ - N: n, - Stride: s.mat.Stride, - Uplo: blas.Upper, - Data: s.mat.Data[:(n-1)*s.mat.Stride+n], - } - v.cap = s.cap - return &v -} - -// PowPSD computes a^pow where a is a positive symmetric definite matrix. -// -// PowPSD returns an error if the matrix is not positive symmetric definite -// or the Eigen decomposition is not successful. -func (s *SymDense) PowPSD(a Symmetric, pow float64) error { - dim := a.SymmetricDim() - s.reuseAsNonZeroed(dim) - - var eigen EigenSym - ok := eigen.Factorize(a, true) - if !ok { - return ErrFailedEigen - } - values := eigen.Values(nil) - for i, v := range values { - if v <= 0 { - return ErrNotPSD - } - values[i] = math.Pow(v, pow) - } - var u Dense - eigen.VectorsTo(&u) - - s.SymOuterK(values[0], u.ColView(0)) - - var v VecDense - for i := 1; i < dim; i++ { - v.ColViewOf(&u, i) - s.SymRankOne(s, values[i], &v) - } - return nil -} diff --git a/vendor/gonum.org/v1/gonum/mat/triangular.go b/vendor/gonum.org/v1/gonum/mat/triangular.go deleted file mode 100644 index 0e37fb01..00000000 --- a/vendor/gonum.org/v1/gonum/mat/triangular.go +++ /dev/null @@ -1,832 +0,0 @@ -// Copyright ©2015 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -var ( - triDense *TriDense - _ Matrix = triDense - _ allMatrix = triDense - _ denseMatrix = triDense - _ Triangular = triDense - _ RawTriangular = triDense - _ MutableTriangular = triDense - - _ NonZeroDoer = triDense - _ RowNonZeroDoer = triDense - _ ColNonZeroDoer = triDense -) - -// TriDense represents an upper or lower triangular matrix in dense storage -// format. -type TriDense struct { - mat blas64.Triangular - cap int -} - -// Triangular represents a triangular matrix. Triangular matrices are always square. -type Triangular interface { - Matrix - // Triangle returns the number of rows/columns in the matrix and its - // orientation. - Triangle() (n int, kind TriKind) - - // TTri is the equivalent of the T() method in the Matrix interface but - // guarantees the transpose is of triangular type. - TTri() Triangular -} - -// A RawTriangular can return a blas64.Triangular representation of the receiver. -// Changes to the blas64.Triangular.Data slice will be reflected in the original -// matrix, changes to the N, Stride, Uplo and Diag fields will not. -type RawTriangular interface { - RawTriangular() blas64.Triangular -} - -// A MutableTriangular can set elements of a triangular matrix. -type MutableTriangular interface { - Triangular - SetTri(i, j int, v float64) -} - -var ( - _ Matrix = TransposeTri{} - _ Triangular = TransposeTri{} - _ UntransposeTrier = TransposeTri{} -) - -// TransposeTri is a type for performing an implicit transpose of a Triangular -// matrix. It implements the Triangular interface, returning values from the -// transpose of the matrix within. -type TransposeTri struct { - Triangular Triangular -} - -// At returns the value of the element at row i and column j of the transposed -// matrix, that is, row j and column i of the Triangular field. -func (t TransposeTri) At(i, j int) float64 { - return t.Triangular.At(j, i) -} - -// Dims returns the dimensions of the transposed matrix. Triangular matrices are -// square and thus this is the same size as the original Triangular. -func (t TransposeTri) Dims() (r, c int) { - c, r = t.Triangular.Dims() - return r, c -} - -// T performs an implicit transpose by returning the Triangular field. -func (t TransposeTri) T() Matrix { - return t.Triangular -} - -// Triangle returns the number of rows/columns in the matrix and its orientation. -func (t TransposeTri) Triangle() (int, TriKind) { - n, upper := t.Triangular.Triangle() - return n, !upper -} - -// TTri performs an implicit transpose by returning the Triangular field. -func (t TransposeTri) TTri() Triangular { - return t.Triangular -} - -// Untranspose returns the Triangular field. -func (t TransposeTri) Untranspose() Matrix { - return t.Triangular -} - -func (t TransposeTri) UntransposeTri() Triangular { - return t.Triangular -} - -// NewTriDense creates a new Triangular matrix with n rows and columns. If data == nil, -// a new slice is allocated for the backing slice. If len(data) == n*n, data is -// used as the backing slice, and changes to the elements of the returned TriDense -// will be reflected in data. If neither of these is true, NewTriDense will panic. -// NewTriDense will panic if n is zero. -// -// The data must be arranged in row-major order, i.e. the (i*c + j)-th -// element in the data slice is the {i, j}-th element in the matrix. -// Only the values in the triangular portion corresponding to kind are used. -func NewTriDense(n int, kind TriKind, data []float64) *TriDense { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic("mat: negative dimension") - } - if data != nil && len(data) != n*n { - panic(ErrShape) - } - if data == nil { - data = make([]float64, n*n) - } - uplo := blas.Lower - if kind == Upper { - uplo = blas.Upper - } - return &TriDense{ - mat: blas64.Triangular{ - N: n, - Stride: n, - Data: data, - Uplo: uplo, - Diag: blas.NonUnit, - }, - cap: n, - } -} - -func (t *TriDense) Dims() (r, c int) { - return t.mat.N, t.mat.N -} - -// Triangle returns the dimension of t and its orientation. The returned -// orientation is only valid when n is not empty. -func (t *TriDense) Triangle() (n int, kind TriKind) { - return t.mat.N, t.triKind() -} - -func (t *TriDense) isUpper() bool { - return isUpperUplo(t.mat.Uplo) -} - -func (t *TriDense) triKind() TriKind { - return TriKind(isUpperUplo(t.mat.Uplo)) -} - -func isUpperUplo(u blas.Uplo) bool { - switch u { - case blas.Upper: - return true - case blas.Lower: - return false - default: - panic(badTriangle) - } -} - -// asSymBlas returns the receiver restructured as a blas64.Symmetric with the -// same backing memory. Panics if the receiver is unit. -// This returns a blas64.Symmetric and not a *SymDense because SymDense can only -// be upper triangular. -func (t *TriDense) asSymBlas() blas64.Symmetric { - if t.mat.Diag == blas.Unit { - panic("mat: cannot convert unit TriDense into blas64.Symmetric") - } - return blas64.Symmetric{ - N: t.mat.N, - Stride: t.mat.Stride, - Data: t.mat.Data, - Uplo: t.mat.Uplo, - } -} - -// T performs an implicit transpose by returning the receiver inside a Transpose. -func (t *TriDense) T() Matrix { - return Transpose{t} -} - -// TTri performs an implicit transpose by returning the receiver inside a TransposeTri. -func (t *TriDense) TTri() Triangular { - return TransposeTri{t} -} - -func (t *TriDense) RawTriangular() blas64.Triangular { - return t.mat -} - -// SetRawTriangular sets the underlying blas64.Triangular used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in the input. -// -// The supplied Triangular must not use blas.Unit storage format. -func (t *TriDense) SetRawTriangular(mat blas64.Triangular) { - if mat.Diag == blas.Unit { - panic("mat: cannot set TriDense with Unit storage format") - } - t.cap = mat.N - t.mat = mat -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (t *TriDense) Reset() { - // N and Stride must be zeroed in unison. - t.mat.N, t.mat.Stride = 0, 0 - // Defensively zero Uplo to ensure - // it is set correctly later. - t.mat.Uplo = 0 - t.mat.Data = t.mat.Data[:0] -} - -// Zero sets all of the matrix elements to zero. -func (t *TriDense) Zero() { - if t.isUpper() { - for i := 0; i < t.mat.N; i++ { - zero(t.mat.Data[i*t.mat.Stride+i : i*t.mat.Stride+t.mat.N]) - } - return - } - for i := 0; i < t.mat.N; i++ { - zero(t.mat.Data[i*t.mat.Stride : i*t.mat.Stride+i+1]) - } -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (t *TriDense) IsEmpty() bool { - // It must be the case that t.Dims() returns - // zeros in this case. See comment in Reset(). - return t.mat.Stride == 0 -} - -// untransposeTri untransposes a matrix if applicable. If a is an UntransposeTrier, then -// untransposeTri returns the underlying matrix and true. If it is not, then it returns -// the input matrix and false. -func untransposeTri(a Triangular) (Triangular, bool) { - if ut, ok := a.(UntransposeTrier); ok { - return ut.UntransposeTri(), true - } - return a, false -} - -// ReuseAsTri changes the receiver if it IsEmpty() to be of size n×n. -// -// ReuseAsTri re-uses the backing data slice if it has sufficient capacity, -// otherwise a new slice is allocated. The backing data is zero on return. -// -// ReuseAsTri panics if the receiver is not empty, and panics if -// the input size is less than one. To empty the receiver for re-use, -// Reset should be used. -func (t *TriDense) ReuseAsTri(n int, kind TriKind) { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if !t.IsEmpty() { - panic(ErrReuseNonEmpty) - } - t.reuseAsZeroed(n, kind) -} - -// reuseAsNonZeroed resizes an empty receiver to an n×n triangular matrix with the given -// orientation. If the receiver is not empty, reuseAsNonZeroed checks that the receiver -// is the correct size and orientation. -func (t *TriDense) reuseAsNonZeroed(n int, kind TriKind) { - // reuseAsNonZeroed must be kept in sync with reuseAsZeroed. - if n == 0 { - panic(ErrZeroLength) - } - ul := blas.Lower - if kind == Upper { - ul = blas.Upper - } - if t.mat.N > t.cap { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if t.IsEmpty() { - t.mat = blas64.Triangular{ - N: n, - Stride: n, - Diag: blas.NonUnit, - Data: use(t.mat.Data, n*n), - Uplo: ul, - } - t.cap = n - return - } - if t.mat.N != n { - panic(ErrShape) - } - if t.mat.Uplo != ul { - panic(ErrTriangle) - } -} - -// reuseAsZeroed resizes an empty receiver to an n×n triangular matrix with the given -// orientation. If the receiver is not empty, reuseAsZeroed checks that the receiver -// is the correct size and orientation. It then zeros out the matrix data. -func (t *TriDense) reuseAsZeroed(n int, kind TriKind) { - // reuseAsZeroed must be kept in sync with reuseAsNonZeroed. - if n == 0 { - panic(ErrZeroLength) - } - ul := blas.Lower - if kind == Upper { - ul = blas.Upper - } - if t.mat.N > t.cap { - // Panic as a string, not a mat.Error. - panic(badCap) - } - if t.IsEmpty() { - t.mat = blas64.Triangular{ - N: n, - Stride: n, - Diag: blas.NonUnit, - Data: useZeroed(t.mat.Data, n*n), - Uplo: ul, - } - t.cap = n - return - } - if t.mat.N != n { - panic(ErrShape) - } - if t.mat.Uplo != ul { - panic(ErrTriangle) - } - t.Zero() -} - -// isolatedWorkspace returns a new TriDense matrix w with the size of a and -// returns a callback to defer which performs cleanup at the return of the call. -// This should be used when a method receiver is the same pointer as an input argument. -func (t *TriDense) isolatedWorkspace(a Triangular) (w *TriDense, restore func()) { - n, kind := a.Triangle() - if n == 0 { - panic(ErrZeroLength) - } - w = getTriDenseWorkspace(n, kind, false) - return w, func() { - t.Copy(w) - putTriWorkspace(w) - } -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (t *TriDense) DiagView() Diagonal { - if t.mat.Diag == blas.Unit { - panic("mat: cannot take view of Unit diagonal") - } - n := t.mat.N - return &DiagDense{ - mat: blas64.Vector{ - N: n, - Inc: t.mat.Stride + 1, - Data: t.mat.Data[:(n-1)*t.mat.Stride+n], - }, - } -} - -// Copy makes a copy of elements of a into the receiver. It is similar to the -// built-in copy; it copies as much as the overlap between the two matrices and -// returns the number of rows and columns it copied. Only elements within the -// receiver's non-zero triangle are set. -// -// See the Copier interface for more information. -func (t *TriDense) Copy(a Matrix) (r, c int) { - r, c = a.Dims() - r = min(r, t.mat.N) - c = min(c, t.mat.N) - if r == 0 || c == 0 { - return 0, 0 - } - - switch a := a.(type) { - case RawMatrixer: - amat := a.RawMatrix() - if t.isUpper() { - for i := 0; i < r; i++ { - copy(t.mat.Data[i*t.mat.Stride+i:i*t.mat.Stride+c], amat.Data[i*amat.Stride+i:i*amat.Stride+c]) - } - } else { - for i := 0; i < r; i++ { - copy(t.mat.Data[i*t.mat.Stride:i*t.mat.Stride+i+1], amat.Data[i*amat.Stride:i*amat.Stride+i+1]) - } - } - case RawTriangular: - amat := a.RawTriangular() - aIsUpper := isUpperUplo(amat.Uplo) - tIsUpper := t.isUpper() - switch { - case tIsUpper && aIsUpper: - for i := 0; i < r; i++ { - copy(t.mat.Data[i*t.mat.Stride+i:i*t.mat.Stride+c], amat.Data[i*amat.Stride+i:i*amat.Stride+c]) - } - case !tIsUpper && !aIsUpper: - for i := 0; i < r; i++ { - copy(t.mat.Data[i*t.mat.Stride:i*t.mat.Stride+i+1], amat.Data[i*amat.Stride:i*amat.Stride+i+1]) - } - default: - for i := 0; i < r; i++ { - t.set(i, i, amat.Data[i*amat.Stride+i]) - } - } - default: - isUpper := t.isUpper() - for i := 0; i < r; i++ { - if isUpper { - for j := i; j < c; j++ { - t.set(i, j, a.At(i, j)) - } - } else { - for j := 0; j <= i; j++ { - t.set(i, j, a.At(i, j)) - } - } - } - } - - return r, c -} - -// InverseTri computes the inverse of the triangular matrix a, storing the result -// into the receiver. If a is ill-conditioned, a Condition error will be returned. -// Note that matrix inversion is numerically unstable, and should generally be -// avoided where possible, for example by using the Solve routines. -func (t *TriDense) InverseTri(a Triangular) error { - t.checkOverlapMatrix(a) - n, _ := a.Triangle() - t.reuseAsNonZeroed(a.Triangle()) - t.Copy(a) - work := getFloat64s(3*n, false) - iwork := getInts(n, false) - cond := lapack64.Trcon(CondNorm, t.mat, work, iwork) - putFloat64s(work) - putInts(iwork) - if math.IsInf(cond, 1) { - return Condition(cond) - } - ok := lapack64.Trtri(t.mat) - if !ok { - return Condition(math.Inf(1)) - } - if cond > ConditionTolerance { - return Condition(cond) - } - return nil -} - -// MulTri takes the product of triangular matrices a and b and places the result -// in the receiver. The size of a and b must match, and they both must have the -// same TriKind, or Mul will panic. -func (t *TriDense) MulTri(a, b Triangular) { - n, kind := a.Triangle() - nb, kindb := b.Triangle() - if n != nb { - panic(ErrShape) - } - if kind != kindb { - panic(ErrTriangle) - } - - aU, _ := untransposeTri(a) - bU, _ := untransposeTri(b) - t.checkOverlapMatrix(bU) - t.checkOverlapMatrix(aU) - t.reuseAsNonZeroed(n, kind) - var restore func() - if t == aU { - t, restore = t.isolatedWorkspace(aU) - defer restore() - } else if t == bU { - t, restore = t.isolatedWorkspace(bU) - defer restore() - } - - // Inspect types here, helps keep the loops later clean(er). - _, aDiag := aU.(Diagonal) - _, bDiag := bU.(Diagonal) - // If they are both diagonal only need 1 loop. - // All diagonal matrices are Upper. - // TODO: Add fast paths for DiagDense. - if aDiag && bDiag { - t.Zero() - for i := 0; i < n; i++ { - t.SetTri(i, i, a.At(i, i)*b.At(i, i)) - } - return - } - - // Now we know at least one matrix is non-diagonal. - // And all diagonal matrices are all Upper. - // The both-diagonal case is handled above. - // TODO: Add fast paths for Dense variants. - if kind == Upper { - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - switch { - case aDiag: - t.SetTri(i, j, a.At(i, i)*b.At(i, j)) - case bDiag: - t.SetTri(i, j, a.At(i, j)*b.At(j, j)) - default: - var v float64 - for k := i; k <= j; k++ { - v += a.At(i, k) * b.At(k, j) - } - t.SetTri(i, j, v) - } - } - } - return - } - for i := 0; i < n; i++ { - for j := 0; j <= i; j++ { - var v float64 - for k := j; k <= i; k++ { - v += a.At(i, k) * b.At(k, j) - } - t.SetTri(i, j, v) - } - } -} - -// ScaleTri multiplies the elements of a by f, placing the result in the receiver. -// If the receiver is non-zero, the size and kind of the receiver must match -// the input, or ScaleTri will panic. -func (t *TriDense) ScaleTri(f float64, a Triangular) { - n, kind := a.Triangle() - t.reuseAsNonZeroed(n, kind) - - // TODO(btracey): Improve the set of fast-paths. - switch a := a.(type) { - case RawTriangular: - amat := a.RawTriangular() - if t != a { - t.checkOverlap(generalFromTriangular(amat)) - } - if kind == Upper { - for i := 0; i < n; i++ { - ts := t.mat.Data[i*t.mat.Stride+i : i*t.mat.Stride+n] - as := amat.Data[i*amat.Stride+i : i*amat.Stride+n] - for i, v := range as { - ts[i] = v * f - } - } - return - } - for i := 0; i < n; i++ { - ts := t.mat.Data[i*t.mat.Stride : i*t.mat.Stride+i+1] - as := amat.Data[i*amat.Stride : i*amat.Stride+i+1] - for i, v := range as { - ts[i] = v * f - } - } - return - default: - t.checkOverlapMatrix(a) - isUpper := kind == Upper - for i := 0; i < n; i++ { - if isUpper { - for j := i; j < n; j++ { - t.set(i, j, f*a.At(i, j)) - } - } else { - for j := 0; j <= i; j++ { - t.set(i, j, f*a.At(i, j)) - } - } - } - } -} - -// SliceTri returns a new Triangular that shares backing data with the receiver. -// The returned matrix starts at {i,i} of the receiver and extends k-i rows and -// columns. The final row and column in the resulting matrix is k-1. -// SliceTri panics with ErrIndexOutOfRange if the slice is outside the capacity -// of the receiver. -func (t *TriDense) SliceTri(i, k int) Triangular { - return t.sliceTri(i, k) -} - -func (t *TriDense) sliceTri(i, k int) *TriDense { - if i < 0 || t.cap < i || k < i || t.cap < k { - panic(ErrIndexOutOfRange) - } - v := *t - v.mat.Data = t.mat.Data[i*t.mat.Stride+i : (k-1)*t.mat.Stride+k] - v.mat.N = k - i - v.cap = t.cap - i - return &v -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the matrix has zero size. -func (t *TriDense) Norm(norm float64) float64 { - if t.IsEmpty() { - panic(ErrZeroLength) - } - lnorm := normLapack(norm, false) - if lnorm == lapack.MaxColumnSum { - work := getFloat64s(t.mat.N, false) - defer putFloat64s(work) - return lapack64.Lantr(lnorm, t.mat, work) - } - return lapack64.Lantr(lnorm, t.mat, nil) -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrZeroLength if the matrix has zero size. -func (t *TriDense) Trace() float64 { - if t.IsEmpty() { - panic(ErrZeroLength) - } - // TODO(btracey): could use internal asm sum routine. - var v float64 - for i := 0; i < t.mat.N; i++ { - v += t.mat.Data[i*t.mat.Stride+i] - } - return v -} - -// copySymIntoTriangle copies a symmetric matrix into a TriDense -func copySymIntoTriangle(t *TriDense, s Symmetric) { - n, upper := t.Triangle() - ns := s.SymmetricDim() - if n != ns { - panic("mat: triangle size mismatch") - } - ts := t.mat.Stride - if rs, ok := s.(RawSymmetricer); ok { - sd := rs.RawSymmetric() - ss := sd.Stride - if upper { - if sd.Uplo == blas.Upper { - for i := 0; i < n; i++ { - copy(t.mat.Data[i*ts+i:i*ts+n], sd.Data[i*ss+i:i*ss+n]) - } - return - } - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - t.mat.Data[i*ts+j] = sd.Data[j*ss+i] - } - } - return - } - if sd.Uplo == blas.Upper { - for i := 0; i < n; i++ { - for j := 0; j <= i; j++ { - t.mat.Data[i*ts+j] = sd.Data[j*ss+i] - } - } - return - } - for i := 0; i < n; i++ { - copy(t.mat.Data[i*ts:i*ts+i+1], sd.Data[i*ss:i*ss+i+1]) - } - return - } - if upper { - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - t.mat.Data[i*ts+j] = s.At(i, j) - } - } - return - } - for i := 0; i < n; i++ { - for j := 0; j <= i; j++ { - t.mat.Data[i*ts+j] = s.At(i, j) - } - } -} - -// DoNonZero calls the function fn for each of the non-zero elements of t. The function fn -// takes a row/column index and the element value of t at (i, j). -func (t *TriDense) DoNonZero(fn func(i, j int, v float64)) { - if t.isUpper() { - for i := 0; i < t.mat.N; i++ { - for j := i; j < t.mat.N; j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } - return - } - for i := 0; i < t.mat.N; i++ { - for j := 0; j <= i; j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } -} - -// DoRowNonZero calls the function fn for each of the non-zero elements of row i of t. The function fn -// takes a row/column index and the element value of t at (i, j). -func (t *TriDense) DoRowNonZero(i int, fn func(i, j int, v float64)) { - if i < 0 || t.mat.N <= i { - panic(ErrRowAccess) - } - if t.isUpper() { - for j := i; j < t.mat.N; j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - return - } - for j := 0; j <= i; j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } -} - -// DoColNonZero calls the function fn for each of the non-zero elements of column j of t. The function fn -// takes a row/column index and the element value of t at (i, j). -func (t *TriDense) DoColNonZero(j int, fn func(i, j int, v float64)) { - if j < 0 || t.mat.N <= j { - panic(ErrColAccess) - } - if t.isUpper() { - for i := 0; i <= j; i++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - return - } - for i := j; i < t.mat.N; i++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } -} - -// SolveTo solves a triangular system T * X = B or Tᵀ * X = B where T is an n×n -// triangular matrix represented by the receiver and B is a given n×nrhs matrix. -// If T is non-singular, the result will be stored into dst and nil will be -// returned. If T is singular, the contents of dst will be undefined and a -// Condition error will be returned. -// -// If dst is empty, SolveTo will resize it to n×nrhs. If dst is not empty, -// SolveTo will panic if dst is not n×nrhs. -func (t *TriDense) SolveTo(dst *Dense, trans bool, b Matrix) error { - n, nrhs := b.Dims() - if n != t.mat.N { - panic(ErrShape) - } - - dst.reuseAsNonZeroed(n, nrhs) - bU, bTrans := untranspose(b) - if dst == bU { - if bTrans { - work := getDenseWorkspace(n, nrhs, false) - defer putDenseWorkspace(work) - work.Copy(b) - dst.Copy(work) - } - } else { - if rm, ok := bU.(RawMatrixer); ok { - dst.checkOverlap(rm.RawMatrix()) - } - dst.Copy(b) - } - - transT := blas.NoTrans - if trans { - transT = blas.Trans - } - ok := lapack64.Trtrs(transT, t.mat, dst.mat) - if !ok { - return Condition(math.Inf(1)) - } - - work := getFloat64s(3*n, false) - iwork := getInts(n, false) - cond := lapack64.Trcon(CondNorm, t.mat, work, iwork) - putFloat64s(work) - putInts(iwork) - if cond > ConditionTolerance { - return Condition(cond) - } - - return nil -} diff --git a/vendor/gonum.org/v1/gonum/mat/triband.go b/vendor/gonum.org/v1/gonum/mat/triband.go deleted file mode 100644 index aa0b51d6..00000000 --- a/vendor/gonum.org/v1/gonum/mat/triband.go +++ /dev/null @@ -1,694 +0,0 @@ -// Copyright ©2018 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/lapack" - "gonum.org/v1/gonum/lapack/lapack64" -) - -var ( - triBand TriBanded - _ Banded = triBand - _ Triangular = triBand - - triBandDense *TriBandDense - _ Matrix = triBandDense - _ allMatrix = triBandDense - _ denseMatrix = triBandDense - _ Triangular = triBandDense - _ Banded = triBandDense - _ TriBanded = triBandDense - _ RawTriBander = triBandDense - _ MutableTriBanded = triBandDense -) - -// TriBanded is a triangular band matrix interface type. -type TriBanded interface { - Banded - - // Triangle returns the number of rows/columns in the matrix and its - // orientation. - Triangle() (n int, kind TriKind) - - // TTri is the equivalent of the T() method in the Matrix interface but - // guarantees the transpose is of triangular type. - TTri() Triangular - - // TriBand returns the number of rows/columns in the matrix, the - // size of the bandwidth, and the orientation. - TriBand() (n, k int, kind TriKind) - - // TTriBand is the equivalent of the T() method in the Matrix interface but - // guarantees the transpose is of banded triangular type. - TTriBand() TriBanded -} - -// A RawTriBander can return a blas64.TriangularBand representation of the receiver. -// Changes to the blas64.TriangularBand.Data slice will be reflected in the original -// matrix, changes to the N, K, Stride, Uplo and Diag fields will not. -type RawTriBander interface { - RawTriBand() blas64.TriangularBand -} - -// MutableTriBanded is a triangular band matrix interface type that allows -// elements to be altered. -type MutableTriBanded interface { - TriBanded - SetTriBand(i, j int, v float64) -} - -var ( - tTriBand TransposeTriBand - _ Matrix = tTriBand - _ TriBanded = tTriBand - _ Untransposer = tTriBand - _ UntransposeTrier = tTriBand - _ UntransposeBander = tTriBand - _ UntransposeTriBander = tTriBand -) - -// TransposeTriBand is a type for performing an implicit transpose of a TriBanded -// matrix. It implements the TriBanded interface, returning values from the -// transpose of the matrix within. -type TransposeTriBand struct { - TriBanded TriBanded -} - -// At returns the value of the element at row i and column j of the transposed -// matrix, that is, row j and column i of the TriBanded field. -func (t TransposeTriBand) At(i, j int) float64 { - return t.TriBanded.At(j, i) -} - -// Dims returns the dimensions of the transposed matrix. TriBanded matrices are -// square and thus this is the same size as the original TriBanded. -func (t TransposeTriBand) Dims() (r, c int) { - c, r = t.TriBanded.Dims() - return r, c -} - -// T performs an implicit transpose by returning the TriBand field. -func (t TransposeTriBand) T() Matrix { - return t.TriBanded -} - -// Triangle returns the number of rows/columns in the matrix and its orientation. -func (t TransposeTriBand) Triangle() (int, TriKind) { - n, upper := t.TriBanded.Triangle() - return n, !upper -} - -// TTri performs an implicit transpose by returning the TriBand field. -func (t TransposeTriBand) TTri() Triangular { - return t.TriBanded -} - -// Bandwidth returns the upper and lower bandwidths of the matrix. -func (t TransposeTriBand) Bandwidth() (kl, ku int) { - kl, ku = t.TriBanded.Bandwidth() - return ku, kl -} - -// TBand performs an implicit transpose by returning the TriBand field. -func (t TransposeTriBand) TBand() Banded { - return t.TriBanded -} - -// TriBand returns the number of rows/columns in the matrix, the -// size of the bandwidth, and the orientation. -func (t TransposeTriBand) TriBand() (n, k int, kind TriKind) { - n, k, kind = t.TriBanded.TriBand() - return n, k, !kind -} - -// TTriBand performs an implicit transpose by returning the TriBand field. -func (t TransposeTriBand) TTriBand() TriBanded { - return t.TriBanded -} - -// Untranspose returns the Triangular field. -func (t TransposeTriBand) Untranspose() Matrix { - return t.TriBanded -} - -// UntransposeTri returns the underlying Triangular matrix. -func (t TransposeTriBand) UntransposeTri() Triangular { - return t.TriBanded -} - -// UntransposeBand returns the underlying Banded matrix. -func (t TransposeTriBand) UntransposeBand() Banded { - return t.TriBanded -} - -// UntransposeTriBand returns the underlying TriBanded matrix. -func (t TransposeTriBand) UntransposeTriBand() TriBanded { - return t.TriBanded -} - -// TriBandDense represents a triangular band matrix in dense storage format. -type TriBandDense struct { - mat blas64.TriangularBand -} - -// NewTriBandDense creates a new triangular banded matrix with n rows and columns, -// k bands in the direction of the specified kind. If data == nil, -// a new slice is allocated for the backing slice. If len(data) == n*(k+1), -// data is used as the backing slice, and changes to the elements of the returned -// TriBandDense will be reflected in data. If neither of these is true, NewTriBandDense -// will panic. k must be at least zero and less than n, otherwise NewTriBandDense will panic. -// -// The data must be arranged in row-major order constructed by removing the zeros -// from the rows outside the band and aligning the diagonals. For example, if -// the upper-triangular banded matrix -// -// 1 2 3 0 0 0 -// 0 4 5 6 0 0 -// 0 0 7 8 9 0 -// 0 0 0 10 11 12 -// 0 0 0 0 13 14 -// 0 0 0 0 0 15 -// -// becomes (* entries are never accessed) -// -// 1 2 3 -// 4 5 6 -// 7 8 9 -// 10 11 12 -// 13 14 * -// 15 * * -// -// which is passed to NewTriBandDense as []float64{1, 2, ..., 15, *, *, *} -// with k=2 and kind = mat.Upper. -// The lower triangular banded matrix -// -// 1 0 0 0 0 0 -// 2 3 0 0 0 0 -// 4 5 6 0 0 0 -// 0 7 8 9 0 0 -// 0 0 10 11 12 0 -// 0 0 0 13 14 15 -// -// becomes (* entries are never accessed) -// - * 1 -// - 2 3 -// 4 5 6 -// 7 8 9 -// 10 11 12 -// 13 14 15 -// -// which is passed to NewTriBandDense as []float64{*, *, *, 1, 2, ..., 15} -// with k=2 and kind = mat.Lower. -// Only the values in the band portion of the matrix are used. -func NewTriBandDense(n, k int, kind TriKind, data []float64) *TriBandDense { - if n <= 0 || k < 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if k+1 > n { - panic(ErrBandwidth) - } - bc := k + 1 - if data != nil && len(data) != n*bc { - panic(ErrShape) - } - if data == nil { - data = make([]float64, n*bc) - } - uplo := blas.Lower - if kind { - uplo = blas.Upper - } - return &TriBandDense{ - mat: blas64.TriangularBand{ - Uplo: uplo, - Diag: blas.NonUnit, - N: n, - K: k, - Data: data, - Stride: bc, - }, - } -} - -// Dims returns the number of rows and columns in the matrix. -func (t *TriBandDense) Dims() (r, c int) { - return t.mat.N, t.mat.N -} - -// T performs an implicit transpose by returning the receiver inside a Transpose. -func (t *TriBandDense) T() Matrix { - return Transpose{t} -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (t *TriBandDense) IsEmpty() bool { - // It must be the case that t.Dims() returns - // zeros in this case. See comment in Reset(). - return t.mat.Stride == 0 -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (t *TriBandDense) Reset() { - t.mat.N = 0 - t.mat.Stride = 0 - t.mat.K = 0 - t.mat.Data = t.mat.Data[:0] -} - -// ReuseAsTriBand changes the receiver to be of size n×n, bandwidth k+1 and of -// the given kind, re-using the backing data slice if it has sufficient capacity -// and allocating a new slice otherwise. The backing data is zero on return. -// -// The receiver must be empty, n must be positive and k must be non-negative and -// less than n, otherwise ReuseAsTriBand will panic. To empty the receiver for -// re-use, Reset should be used. -func (t *TriBandDense) ReuseAsTriBand(n, k int, kind TriKind) { - if n <= 0 || k < 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if k+1 > n { - panic(ErrBandwidth) - } - if !t.IsEmpty() { - panic(ErrReuseNonEmpty) - } - t.reuseAsZeroed(n, k, kind) -} - -// reuseAsZeroed resizes an empty receiver to an n×n triangular band matrix with -// the given bandwidth and orientation. If the receiver is not empty, -// reuseAsZeroed checks that the receiver has the correct size, bandwidth and -// orientation. It then zeros out the matrix data. -func (t *TriBandDense) reuseAsZeroed(n, k int, kind TriKind) { - // reuseAsZeroed must be kept in sync with reuseAsNonZeroed. - if n == 0 { - panic(ErrZeroLength) - } - ul := blas.Lower - if kind == Upper { - ul = blas.Upper - } - if t.IsEmpty() { - t.mat = blas64.TriangularBand{ - Uplo: ul, - Diag: blas.NonUnit, - N: n, - K: k, - Data: useZeroed(t.mat.Data, n*(k+1)), - Stride: k + 1, - } - return - } - if t.mat.N != n || t.mat.K != k { - panic(ErrShape) - } - if t.mat.Uplo != ul { - panic(ErrTriangle) - } - t.Zero() -} - -// reuseAsNonZeroed resizes an empty receiver to an n×n triangular band matrix -// with the given bandwidth and orientation. If the receiver is not empty, -// reuseAsZeroed checks that the receiver has the correct size, bandwidth and -// orientation. -// -//lint:ignore U1000 This will be used later. -func (t *TriBandDense) reuseAsNonZeroed(n, k int, kind TriKind) { - // reuseAsNonZeroed must be kept in sync with reuseAsZeroed. - if n == 0 { - panic(ErrZeroLength) - } - ul := blas.Lower - if kind == Upper { - ul = blas.Upper - } - if t.IsEmpty() { - t.mat = blas64.TriangularBand{ - Uplo: ul, - Diag: blas.NonUnit, - N: n, - K: k, - Data: use(t.mat.Data, n*(k+1)), - Stride: k + 1, - } - return - } - if t.mat.N != n || t.mat.K != k { - panic(ErrShape) - } - if t.mat.Uplo != ul { - panic(ErrTriangle) - } -} - -// DoNonZero calls the function fn for each of the non-zero elements of t. The function fn -// takes a row/column index and the element value of t at (i, j). -func (t *TriBandDense) DoNonZero(fn func(i, j int, v float64)) { - if t.isUpper() { - for i := 0; i < t.mat.N; i++ { - for j := i; j < min(i+t.mat.K+1, t.mat.N); j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } - } else { - for i := 0; i < t.mat.N; i++ { - for j := max(0, i-t.mat.K); j <= i; j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } - } -} - -// DoRowNonZero calls the function fn for each of the non-zero elements of row i of t. The function fn -// takes a row/column index and the element value of t at (i, j). -func (t *TriBandDense) DoRowNonZero(i int, fn func(i, j int, v float64)) { - if i < 0 || t.mat.N <= i { - panic(ErrRowAccess) - } - if t.isUpper() { - for j := i; j < min(i+t.mat.K+1, t.mat.N); j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } else { - for j := max(0, i-t.mat.K); j <= i; j++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } -} - -// DoColNonZero calls the function fn for each of the non-zero elements of column j of t. The function fn -// takes a row/column index and the element value of t at (i, j). -func (t *TriBandDense) DoColNonZero(j int, fn func(i, j int, v float64)) { - if j < 0 || t.mat.N <= j { - panic(ErrColAccess) - } - if t.isUpper() { - for i := 0; i < t.mat.N; i++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } else { - for i := 0; i < t.mat.N; i++ { - v := t.at(i, j) - if v != 0 { - fn(i, j, v) - } - } - } -} - -// Zero sets all of the matrix elements to zero. -func (t *TriBandDense) Zero() { - if t.isUpper() { - for i := 0; i < t.mat.N; i++ { - u := min(1+t.mat.K, t.mat.N-i) - zero(t.mat.Data[i*t.mat.Stride : i*t.mat.Stride+u]) - } - return - } - for i := 0; i < t.mat.N; i++ { - l := max(0, t.mat.K-i) - zero(t.mat.Data[i*t.mat.Stride+l : i*t.mat.Stride+t.mat.K+1]) - } -} - -func (t *TriBandDense) isUpper() bool { - return isUpperUplo(t.mat.Uplo) -} - -func (t *TriBandDense) triKind() TriKind { - return TriKind(isUpperUplo(t.mat.Uplo)) -} - -// Triangle returns the dimension of t and its orientation. The returned -// orientation is only valid when n is not zero. -func (t *TriBandDense) Triangle() (n int, kind TriKind) { - return t.mat.N, t.triKind() -} - -// TTri performs an implicit transpose by returning the receiver inside a TransposeTri. -func (t *TriBandDense) TTri() Triangular { - return TransposeTri{t} -} - -// Bandwidth returns the upper and lower bandwidths of the matrix. -func (t *TriBandDense) Bandwidth() (kl, ku int) { - if t.isUpper() { - return 0, t.mat.K - } - return t.mat.K, 0 -} - -// TBand performs an implicit transpose by returning the receiver inside a TransposeBand. -func (t *TriBandDense) TBand() Banded { - return TransposeBand{t} -} - -// TriBand returns the number of rows/columns in the matrix, the -// size of the bandwidth, and the orientation. -func (t *TriBandDense) TriBand() (n, k int, kind TriKind) { - return t.mat.N, t.mat.K, TriKind(!t.IsEmpty()) && t.triKind() -} - -// TTriBand performs an implicit transpose by returning the receiver inside a TransposeTriBand. -func (t *TriBandDense) TTriBand() TriBanded { - return TransposeTriBand{t} -} - -// RawTriBand returns the underlying blas64.TriangularBand used by the receiver. -// Changes to the blas64.TriangularBand.Data slice will be reflected in the original -// matrix, changes to the N, K, Stride, Uplo and Diag fields will not. -func (t *TriBandDense) RawTriBand() blas64.TriangularBand { - return t.mat -} - -// SetRawTriBand sets the underlying blas64.TriangularBand used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in the input. -// -// The supplied TriangularBand must not use blas.Unit storage format. -func (t *TriBandDense) SetRawTriBand(mat blas64.TriangularBand) { - if mat.Diag == blas.Unit { - panic("mat: cannot set TriBand with Unit storage") - } - t.mat = mat -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (t *TriBandDense) DiagView() Diagonal { - if t.mat.Diag == blas.Unit { - panic("mat: cannot take view of Unit diagonal") - } - n := t.mat.N - data := t.mat.Data - if !t.isUpper() { - data = data[t.mat.K:] - } - return &DiagDense{ - mat: blas64.Vector{ - N: n, - Inc: t.mat.Stride, - Data: data[:(n-1)*t.mat.Stride+1], - }, - } -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the matrix has zero size. -func (t *TriBandDense) Norm(norm float64) float64 { - if t.IsEmpty() { - panic(ErrZeroLength) - } - lnorm := normLapack(norm, false) - if lnorm == lapack.MaxColumnSum { - work := getFloat64s(t.mat.N, false) - defer putFloat64s(work) - return lapack64.Lantb(lnorm, t.mat, work) - } - return lapack64.Lantb(lnorm, t.mat, nil) -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrZeroLength if the matrix has zero size. -func (t *TriBandDense) Trace() float64 { - if t.IsEmpty() { - panic(ErrZeroLength) - } - rb := t.RawTriBand() - var tr float64 - var offsetIndex int - if rb.Uplo == blas.Lower { - offsetIndex = rb.K - } - for i := 0; i < rb.N; i++ { - tr += rb.Data[offsetIndex+i*rb.Stride] - } - return tr -} - -// SolveTo solves a triangular system T * X = B or Tᵀ * X = B where T is an -// n×n triangular band matrix represented by the receiver and B is a given -// n×nrhs matrix. If T is non-singular, the result will be stored into dst and -// nil will be returned. If T is singular, the contents of dst will be undefined -// and a Condition error will be returned. -func (t *TriBandDense) SolveTo(dst *Dense, trans bool, b Matrix) error { - n, nrhs := b.Dims() - if n != t.mat.N { - panic(ErrShape) - } - - dst.reuseAsNonZeroed(n, nrhs) - bU, bTrans := untranspose(b) - if dst == bU { - if bTrans { - work := getDenseWorkspace(n, nrhs, false) - defer putDenseWorkspace(work) - work.Copy(b) - dst.Copy(work) - } - } else { - if rm, ok := bU.(RawMatrixer); ok { - dst.checkOverlap(rm.RawMatrix()) - } - dst.Copy(b) - } - - var ok bool - if trans { - ok = lapack64.Tbtrs(blas.Trans, t.mat, dst.mat) - } else { - ok = lapack64.Tbtrs(blas.NoTrans, t.mat, dst.mat) - } - if !ok { - return Condition(math.Inf(1)) - } - return nil -} - -// SolveVecTo solves a triangular system T * x = b or Tᵀ * x = b where T is an -// n×n triangular band matrix represented by the receiver and b is a given -// n-vector. If T is non-singular, the result will be stored into dst and nil -// will be returned. If T is singular, the contents of dst will be undefined and -// a Condition error will be returned. -func (t *TriBandDense) SolveVecTo(dst *VecDense, trans bool, b Vector) error { - n, nrhs := b.Dims() - if n != t.mat.N || nrhs != 1 { - panic(ErrShape) - } - if b, ok := b.(RawVectorer); ok && dst != b { - dst.checkOverlap(b.RawVector()) - } - dst.reuseAsNonZeroed(n) - if dst != b { - dst.CopyVec(b) - } - var ok bool - if trans { - ok = lapack64.Tbtrs(blas.Trans, t.mat, dst.asGeneral()) - } else { - ok = lapack64.Tbtrs(blas.NoTrans, t.mat, dst.asGeneral()) - } - if !ok { - return Condition(math.Inf(1)) - } - return nil -} - -func copySymBandIntoTriBand(dst *TriBandDense, s SymBanded) { - n, k, upper := dst.TriBand() - ns, ks := s.SymBand() - if n != ns { - panic("mat: triangle size mismatch") - } - if k != ks { - panic("mat: triangle bandwidth mismatch") - } - - // TODO(vladimir-ch): implement the missing cases below as needed. - t := dst.mat - sU, _ := untransposeExtract(s) - if sbd, ok := sU.(*SymBandDense); ok { - s := sbd.RawSymBand() - if upper { - if s.Uplo == blas.Upper { - // dst is upper triangular, s is stored in upper triangle. - for i := 0; i < n; i++ { - ilen := min(k+1, n-i) - copy(t.Data[i*t.Stride:i*t.Stride+ilen], s.Data[i*s.Stride:i*s.Stride+ilen]) - } - } else { - // dst is upper triangular, s is stored in lower triangle. - // - // The following is a possible implementation for this case but - // is commented out due to lack of test coverage. - // for i := 0; i < n; i++ { - // ilen := min(k+1, n-i) - // for j := 0; j < ilen; j++ { - // t.Data[i*t.Stride+j] = s.Data[(i+j)*s.Stride+k-j] - // } - // } - panic("not implemented") - } - } else { - if s.Uplo == blas.Upper { - // dst is lower triangular, s is stored in upper triangle. - panic("not implemented") - } else { - // dst is lower triangular, s is stored in lower triangle. - panic("not implemented") - } - } - return - } - if upper { - for i := 0; i < n; i++ { - ilen := min(k+1, n-i) - for j := 0; j < ilen; j++ { - t.Data[i*t.Stride+j] = s.At(i, i+j) - } - } - } else { - panic("not implemented") - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/tridiag.go b/vendor/gonum.org/v1/gonum/mat/tridiag.go deleted file mode 100644 index c001d486..00000000 --- a/vendor/gonum.org/v1/gonum/mat/tridiag.go +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright ©2020 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/internal/asm/f64" - "gonum.org/v1/gonum/lapack/lapack64" -) - -var ( - tridiagDense *Tridiag - _ Matrix = tridiagDense - _ allMatrix = tridiagDense - _ denseMatrix = tridiagDense - _ Banded = tridiagDense - _ MutableBanded = tridiagDense - _ RawTridiagonaler = tridiagDense -) - -// A RawTridiagonaler can return a lapack64.Tridiagonal representation of the -// receiver. Changes to the elements of DL, D, DU in lapack64.Tridiagonal will -// be reflected in the original matrix, changes to the N field will not. -type RawTridiagonaler interface { - RawTridiagonal() lapack64.Tridiagonal -} - -// Tridiag represents a tridiagonal matrix by its three diagonals. -type Tridiag struct { - mat lapack64.Tridiagonal -} - -// NewTridiag creates a new n×n tridiagonal matrix with the first sub-diagonal -// in dl, the main diagonal in d and the first super-diagonal in du. If all of -// dl, d, and du are nil, new backing slices will be allocated for them. If dl -// and du have length n-1 and d has length n, they will be used as backing -// slices, and changes to the elements of the returned Tridiag will be reflected -// in dl, d, du. If neither of these is true, NewTridiag will panic. -func NewTridiag(n int, dl, d, du []float64) *Tridiag { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if dl != nil || d != nil || du != nil { - if len(dl) != n-1 || len(d) != n || len(du) != n-1 { - panic(ErrShape) - } - } else { - d = make([]float64, n) - if n > 1 { - dl = make([]float64, n-1) - du = make([]float64, n-1) - } - } - return &Tridiag{ - mat: lapack64.Tridiagonal{ - N: n, - DL: dl, - D: d, - DU: du, - }, - } -} - -// Dims returns the number of rows and columns in the matrix. -func (a *Tridiag) Dims() (r, c int) { - return a.mat.N, a.mat.N -} - -// Bandwidth returns 1, 1 - the upper and lower bandwidths of the matrix. -func (a *Tridiag) Bandwidth() (kl, ku int) { - return 1, 1 -} - -// T performs an implicit transpose by returning the receiver inside a Transpose. -func (a *Tridiag) T() Matrix { - // An alternative would be to return the receiver with DL,DU swapped; the - // untranspose function would then always return false. With Transpose the - // diagonal swapping will be done in tridiagonal routines in lapack like - // lapack64.Gtsv or gonum.Dlagtm based on the trans parameter. - return Transpose{a} -} - -// TBand performs an implicit transpose by returning the receiver inside a -// TransposeBand. -func (a *Tridiag) TBand() Banded { - // An alternative would be to return the receiver with DL,DU swapped; see - // explanation in T above. - return TransposeBand{a} -} - -// RawTridiagonal returns the underlying lapack64.Tridiagonal used by the -// receiver. Changes to elements in the receiver following the call will be -// reflected in the returned matrix. -func (a *Tridiag) RawTridiagonal() lapack64.Tridiagonal { - return a.mat -} - -// SetRawTridiagonal sets the underlying lapack64.Tridiagonal used by the -// receiver. Changes to elements in the receiver following the call will be -// reflected in the input. -func (a *Tridiag) SetRawTridiagonal(mat lapack64.Tridiagonal) { - a.mat = mat -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be zeroed using -// Reset. -func (a *Tridiag) IsEmpty() bool { - return a.mat.N == 0 -} - -// Reset empties the matrix so that it can be reused as the receiver of a -// dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. See the Reseter -// interface for more information. -func (a *Tridiag) Reset() { - a.mat.N = 0 - a.mat.DL = a.mat.DL[:0] - a.mat.D = a.mat.D[:0] - a.mat.DU = a.mat.DU[:0] -} - -// CloneFromTridiag makes a copy of the input Tridiag into the receiver, -// overwriting the previous value of the receiver. CloneFromTridiag does not -// place any restrictions on receiver shape. -func (a *Tridiag) CloneFromTridiag(from *Tridiag) { - n := from.mat.N - switch n { - case 0: - panic(ErrZeroLength) - case 1: - a.mat = lapack64.Tridiagonal{ - N: 1, - DL: use(a.mat.DL, 0), - D: use(a.mat.D, 1), - DU: use(a.mat.DU, 0), - } - a.mat.D[0] = from.mat.D[0] - default: - a.mat = lapack64.Tridiagonal{ - N: n, - DL: use(a.mat.DL, n-1), - D: use(a.mat.D, n), - DU: use(a.mat.DU, n-1), - } - copy(a.mat.DL, from.mat.DL) - copy(a.mat.D, from.mat.D) - copy(a.mat.DU, from.mat.DU) - } -} - -// DiagView returns the diagonal as a matrix backed by the original data. -func (a *Tridiag) DiagView() Diagonal { - return &DiagDense{ - mat: blas64.Vector{ - N: a.mat.N, - Data: a.mat.D[:a.mat.N], - Inc: 1, - }, - } -} - -// Zero sets all of the matrix elements to zero. -func (a *Tridiag) Zero() { - zero(a.mat.DL) - zero(a.mat.D) - zero(a.mat.DU) -} - -// Trace returns the trace of the matrix. -// -// Trace will panic with ErrZeroLength if the matrix has zero size. -func (a *Tridiag) Trace() float64 { - if a.IsEmpty() { - panic(ErrZeroLength) - } - return f64.Sum(a.mat.D) -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The maximum absolute column sum -// 2 - The Frobenius norm, the square root of the sum of the squares of the elements -// Inf - The maximum absolute row sum -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the matrix has zero size. -func (a *Tridiag) Norm(norm float64) float64 { - if a.IsEmpty() { - panic(ErrZeroLength) - } - return lapack64.Langt(normLapack(norm, false), a.mat) -} - -// MulVecTo computes A⋅x or Aᵀ⋅x storing the result into dst. -func (a *Tridiag) MulVecTo(dst *VecDense, trans bool, x Vector) { - n := a.mat.N - if x.Len() != n { - panic(ErrShape) - } - dst.reuseAsNonZeroed(n) - t := blas.NoTrans - if trans { - t = blas.Trans - } - xMat, _ := untransposeExtract(x) - if xVec, ok := xMat.(*VecDense); ok && dst != xVec { - dst.checkOverlap(xVec.mat) - lapack64.Lagtm(t, 1, a.mat, xVec.asGeneral(), 0, dst.asGeneral()) - } else { - xCopy := getVecDenseWorkspace(n, false) - xCopy.CloneFromVec(x) - lapack64.Lagtm(t, 1, a.mat, xCopy.asGeneral(), 0, dst.asGeneral()) - putVecDenseWorkspace(xCopy) - } -} - -// SolveTo solves a tridiagonal system A⋅X = B or Aᵀ⋅X = B where A is an -// n×n tridiagonal matrix represented by the receiver and B is a given n×nrhs -// matrix. If A is non-singular, the result will be stored into dst and nil will -// be returned. If A is singular, the contents of dst will be undefined and a -// Condition error will be returned. -func (a *Tridiag) SolveTo(dst *Dense, trans bool, b Matrix) error { - n, nrhs := b.Dims() - if n != a.mat.N { - panic(ErrShape) - } - - dst.reuseAsNonZeroed(n, nrhs) - bU, bTrans := untranspose(b) - if dst == bU { - if bTrans { - work := getDenseWorkspace(n, nrhs, false) - defer putDenseWorkspace(work) - work.Copy(b) - dst.Copy(work) - } - } else { - if rm, ok := bU.(RawMatrixer); ok { - dst.checkOverlap(rm.RawMatrix()) - } - dst.Copy(b) - } - - var aCopy Tridiag - aCopy.CloneFromTridiag(a) - var ok bool - if trans { - ok = lapack64.Gtsv(blas.Trans, aCopy.mat, dst.mat) - } else { - ok = lapack64.Gtsv(blas.NoTrans, aCopy.mat, dst.mat) - } - if !ok { - return Condition(math.Inf(1)) - } - return nil -} - -// SolveVecTo solves a tridiagonal system A⋅X = B or Aᵀ⋅X = B where A is an -// n×n tridiagonal matrix represented by the receiver and b is a given n-vector. -// If A is non-singular, the result will be stored into dst and nil will be -// returned. If A is singular, the contents of dst will be undefined and a -// Condition error will be returned. -func (a *Tridiag) SolveVecTo(dst *VecDense, trans bool, b Vector) error { - n, nrhs := b.Dims() - if n != a.mat.N || nrhs != 1 { - panic(ErrShape) - } - if b, ok := b.(RawVectorer); ok && dst != b { - dst.checkOverlap(b.RawVector()) - } - dst.reuseAsNonZeroed(n) - if dst != b { - dst.CopyVec(b) - } - var aCopy Tridiag - aCopy.CloneFromTridiag(a) - var ok bool - if trans { - ok = lapack64.Gtsv(blas.Trans, aCopy.mat, dst.asGeneral()) - } else { - ok = lapack64.Gtsv(blas.NoTrans, aCopy.mat, dst.asGeneral()) - } - if !ok { - return Condition(math.Inf(1)) - } - return nil -} - -// DoNonZero calls the function fn for each of the non-zero elements of A. The -// function fn takes a row/column index and the element value of A at (i,j). -func (a *Tridiag) DoNonZero(fn func(i, j int, v float64)) { - for i, aij := range a.mat.DU { - if aij != 0 { - fn(i, i+1, aij) - } - } - for i, aii := range a.mat.D { - if aii != 0 { - fn(i, i, aii) - } - } - for i, aij := range a.mat.DL { - if aij != 0 { - fn(i+1, i, aij) - } - } -} - -// DoRowNonZero calls the function fn for each of the non-zero elements of row i -// of A. The function fn takes a row/column index and the element value of A at -// (i,j). -func (a *Tridiag) DoRowNonZero(i int, fn func(i, j int, v float64)) { - n := a.mat.N - if uint(i) >= uint(n) { - panic(ErrRowAccess) - } - if n == 1 { - v := a.mat.D[0] - if v != 0 { - fn(0, 0, v) - } - return - } - switch i { - case 0: - v := a.mat.D[0] - if v != 0 { - fn(i, 0, v) - } - v = a.mat.DU[0] - if v != 0 { - fn(i, 1, v) - } - case n - 1: - v := a.mat.DL[n-2] - if v != 0 { - fn(n-1, n-2, v) - } - v = a.mat.D[n-1] - if v != 0 { - fn(n-1, n-1, v) - } - default: - v := a.mat.DL[i-1] - if v != 0 { - fn(i, i-1, v) - } - v = a.mat.D[i] - if v != 0 { - fn(i, i, v) - } - v = a.mat.DU[i] - if v != 0 { - fn(i, i+1, v) - } - } -} - -// DoColNonZero calls the function fn for each of the non-zero elements of -// column j of A. The function fn takes a row/column index and the element value -// of A at (i, j). -func (a *Tridiag) DoColNonZero(j int, fn func(i, j int, v float64)) { - n := a.mat.N - if uint(j) >= uint(n) { - panic(ErrColAccess) - } - if n == 1 { - v := a.mat.D[0] - if v != 0 { - fn(0, 0, v) - } - return - } - switch j { - case 0: - v := a.mat.D[0] - if v != 0 { - fn(0, 0, v) - } - v = a.mat.DL[0] - if v != 0 { - fn(1, 0, v) - } - case n - 1: - v := a.mat.DU[n-2] - if v != 0 { - fn(n-2, n-1, v) - } - v = a.mat.D[n-1] - if v != 0 { - fn(n-1, n-1, v) - } - default: - v := a.mat.DU[j-1] - if v != 0 { - fn(j-1, j, v) - } - v = a.mat.D[j] - if v != 0 { - fn(j, j, v) - } - v = a.mat.DL[j] - if v != 0 { - fn(j+1, j, v) - } - } -} diff --git a/vendor/gonum.org/v1/gonum/mat/vector.go b/vendor/gonum.org/v1/gonum/mat/vector.go deleted file mode 100644 index 5c5d3ff7..00000000 --- a/vendor/gonum.org/v1/gonum/mat/vector.go +++ /dev/null @@ -1,855 +0,0 @@ -// Copyright ©2013 The Gonum 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 mat - -import ( - "math" - - "gonum.org/v1/gonum/blas" - "gonum.org/v1/gonum/blas/blas64" - "gonum.org/v1/gonum/internal/asm/f64" -) - -var ( - vector *VecDense - - _ Matrix = vector - _ allMatrix = vector - _ Vector = vector - _ Reseter = vector - _ MutableVector = vector -) - -// Vector is a vector. -type Vector interface { - Matrix - AtVec(int) float64 - Len() int -} - -// A MutableVector can set elements of a vector. -type MutableVector interface { - Vector - SetVec(i int, v float64) -} - -// TransposeVec is a type for performing an implicit transpose of a Vector. -// It implements the Vector interface, returning values from the transpose -// of the vector within. -type TransposeVec struct { - Vector Vector -} - -// At returns the value of the element at row i and column j of the transposed -// matrix, that is, row j and column i of the Vector field. -func (t TransposeVec) At(i, j int) float64 { - return t.Vector.At(j, i) -} - -// AtVec returns the element at position i. It panics if i is out of bounds. -func (t TransposeVec) AtVec(i int) float64 { - return t.Vector.AtVec(i) -} - -// Dims returns the dimensions of the transposed vector. -func (t TransposeVec) Dims() (r, c int) { - c, r = t.Vector.Dims() - return r, c -} - -// T performs an implicit transpose by returning the Vector field. -func (t TransposeVec) T() Matrix { - return t.Vector -} - -// Len returns the number of columns in the vector. -func (t TransposeVec) Len() int { - return t.Vector.Len() -} - -// TVec performs an implicit transpose by returning the Vector field. -func (t TransposeVec) TVec() Vector { - return t.Vector -} - -// Untranspose returns the Vector field. -func (t TransposeVec) Untranspose() Matrix { - return t.Vector -} - -func (t TransposeVec) UntransposeVec() Vector { - return t.Vector -} - -// VecDense represents a column vector. -type VecDense struct { - mat blas64.Vector - // A BLAS vector can have a negative increment, but allowing this - // in the mat type complicates a lot of code, and doesn't gain anything. - // VecDense must have positive increment in this package. -} - -// NewVecDense creates a new VecDense of length n. If data == nil, -// a new slice is allocated for the backing slice. If len(data) == n, data is -// used as the backing slice, and changes to the elements of the returned VecDense -// will be reflected in data. If neither of these is true, NewVecDense will panic. -// NewVecDense will panic if n is zero. -func NewVecDense(n int, data []float64) *VecDense { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic("mat: negative dimension") - } - if len(data) != n && data != nil { - panic(ErrShape) - } - if data == nil { - data = make([]float64, n) - } - return &VecDense{ - mat: blas64.Vector{ - N: n, - Inc: 1, - Data: data, - }, - } -} - -// SliceVec returns a new Vector that shares backing data with the receiver. -// The returned matrix starts at i of the receiver and extends k-i elements. -// SliceVec panics with ErrIndexOutOfRange if the slice is outside the capacity -// of the receiver. -func (v *VecDense) SliceVec(i, k int) Vector { - return v.sliceVec(i, k) -} - -func (v *VecDense) sliceVec(i, k int) *VecDense { - if i < 0 || k <= i || v.Cap() < k { - panic(ErrIndexOutOfRange) - } - return &VecDense{ - mat: blas64.Vector{ - N: k - i, - Inc: v.mat.Inc, - Data: v.mat.Data[i*v.mat.Inc : (k-1)*v.mat.Inc+1], - }, - } -} - -// Dims returns the number of rows and columns in the matrix. Columns is always 1 -// for a non-Reset vector. -func (v *VecDense) Dims() (r, c int) { - if v.IsEmpty() { - return 0, 0 - } - return v.mat.N, 1 -} - -// Caps returns the number of rows and columns in the backing matrix. Columns is always 1 -// for a non-Reset vector. -func (v *VecDense) Caps() (r, c int) { - if v.IsEmpty() { - return 0, 0 - } - return v.Cap(), 1 -} - -// Len returns the length of the vector. -func (v *VecDense) Len() int { - return v.mat.N -} - -// Cap returns the capacity of the vector. -func (v *VecDense) Cap() int { - if v.IsEmpty() { - return 0 - } - return (cap(v.mat.Data)-1)/v.mat.Inc + 1 -} - -// T performs an implicit transpose by returning the receiver inside a Transpose. -func (v *VecDense) T() Matrix { - return Transpose{v} -} - -// TVec performs an implicit transpose by returning the receiver inside a TransposeVec. -func (v *VecDense) TVec() Vector { - return TransposeVec{v} -} - -// Reset empties the matrix so that it can be reused as the -// receiver of a dimensionally restricted operation. -// -// Reset should not be used when the matrix shares backing data. -// See the Reseter interface for more information. -func (v *VecDense) Reset() { - // No change of Inc or N to 0 may be - // made unless both are set to 0. - v.mat.Inc = 0 - v.mat.N = 0 - v.mat.Data = v.mat.Data[:0] -} - -// Zero sets all of the matrix elements to zero. -func (v *VecDense) Zero() { - for i := 0; i < v.mat.N; i++ { - v.mat.Data[v.mat.Inc*i] = 0 - } -} - -// CloneFromVec makes a copy of a into the receiver, overwriting the previous value -// of the receiver. -func (v *VecDense) CloneFromVec(a Vector) { - if v == a { - return - } - n := a.Len() - v.mat = blas64.Vector{ - N: n, - Inc: 1, - Data: use(v.mat.Data, n), - } - if r, ok := a.(RawVectorer); ok { - blas64.Copy(r.RawVector(), v.mat) - return - } - for i := 0; i < a.Len(); i++ { - v.setVec(i, a.AtVec(i)) - } -} - -// VecDenseCopyOf returns a newly allocated copy of the elements of a. -func VecDenseCopyOf(a Vector) *VecDense { - v := &VecDense{} - v.CloneFromVec(a) - return v -} - -// RawVector returns the underlying blas64.Vector used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in returned blas64.Vector. -func (v *VecDense) RawVector() blas64.Vector { - return v.mat -} - -// SetRawVector sets the underlying blas64.Vector used by the receiver. -// Changes to elements in the receiver following the call will be reflected -// in the input. -func (v *VecDense) SetRawVector(a blas64.Vector) { - v.mat = a -} - -// CopyVec makes a copy of elements of a into the receiver. It is similar to the -// built-in copy; it copies as much as the overlap between the two vectors and -// returns the number of elements it copied. -func (v *VecDense) CopyVec(a Vector) int { - n := min(v.Len(), a.Len()) - if v == a { - return n - } - if r, ok := a.(RawVectorer); ok { - src := r.RawVector() - src.N = n - dst := v.mat - dst.N = n - blas64.Copy(src, dst) - return n - } - for i := 0; i < n; i++ { - v.setVec(i, a.AtVec(i)) - } - return n -} - -// Norm returns the specified norm of the receiver. Valid norms are: -// -// 1 - The sum of the element magnitudes -// 2 - The Euclidean norm, the square root of the sum of the squares of the elements -// Inf - The maximum element magnitude -// -// Norm will panic with ErrNormOrder if an illegal norm is specified and with -// ErrZeroLength if the vector has zero size. -func (v *VecDense) Norm(norm float64) float64 { - if v.IsEmpty() { - panic(ErrZeroLength) - } - switch norm { - default: - panic(ErrNormOrder) - case 1: - return blas64.Asum(v.mat) - case 2: - return blas64.Nrm2(v.mat) - case math.Inf(1): - imax := blas64.Iamax(v.mat) - return math.Abs(v.at(imax)) - } -} - -// ScaleVec scales the vector a by alpha, placing the result in the receiver. -func (v *VecDense) ScaleVec(alpha float64, a Vector) { - n := a.Len() - - if v == a { - if v.mat.Inc == 1 { - f64.ScalUnitary(alpha, v.mat.Data) - return - } - f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc)) - return - } - - v.reuseAsNonZeroed(n) - - if rv, ok := a.(RawVectorer); ok { - mat := rv.RawVector() - v.checkOverlap(mat) - if v.mat.Inc == 1 && mat.Inc == 1 { - f64.ScalUnitaryTo(v.mat.Data, alpha, mat.Data) - return - } - f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc), - alpha, mat.Data, uintptr(n), uintptr(mat.Inc)) - return - } - - for i := 0; i < n; i++ { - v.setVec(i, alpha*a.AtVec(i)) - } -} - -// AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver. -func (v *VecDense) AddScaledVec(a Vector, alpha float64, b Vector) { - if alpha == 1 { - v.AddVec(a, b) - return - } - if alpha == -1 { - v.SubVec(a, b) - return - } - - ar := a.Len() - br := b.Len() - - if ar != br { - panic(ErrShape) - } - - var amat, bmat blas64.Vector - fast := true - aU, _ := untransposeExtract(a) - if rv, ok := aU.(*VecDense); ok { - amat = rv.mat - if v != a { - v.checkOverlap(amat) - } - } else { - fast = false - } - bU, _ := untransposeExtract(b) - if rv, ok := bU.(*VecDense); ok { - bmat = rv.mat - if v != b { - v.checkOverlap(bmat) - } - } else { - fast = false - } - - v.reuseAsNonZeroed(ar) - - switch { - case alpha == 0: // v <- a - if v == a { - return - } - v.CopyVec(a) - case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v - blas64.Scal(alpha+1, v.mat) - case !fast: // v <- a + alpha * b without blas64 support. - for i := 0; i < ar; i++ { - v.setVec(i, a.AtVec(i)+alpha*b.AtVec(i)) - } - case v == a && v != b: // v <- v + alpha * b - if v.mat.Inc == 1 && bmat.Inc == 1 { - // Fast path for a common case. - f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data) - } else { - f64.AxpyInc(alpha, bmat.Data, v.mat.Data, - uintptr(ar), uintptr(bmat.Inc), uintptr(v.mat.Inc), 0, 0) - } - default: // v <- a + alpha * b or v <- a + alpha * v - if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { - // Fast path for a common case. - f64.AxpyUnitaryTo(v.mat.Data, alpha, bmat.Data, amat.Data) - } else { - f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, - alpha, bmat.Data, amat.Data, - uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) - } - } -} - -// AddVec adds the vectors a and b, placing the result in the receiver. -func (v *VecDense) AddVec(a, b Vector) { - ar := a.Len() - br := b.Len() - - if ar != br { - panic(ErrShape) - } - - v.reuseAsNonZeroed(ar) - - aU, _ := untransposeExtract(a) - bU, _ := untransposeExtract(b) - - if arv, ok := aU.(*VecDense); ok { - if brv, ok := bU.(*VecDense); ok { - amat := arv.mat - bmat := brv.mat - - if v != a { - v.checkOverlap(amat) - } - if v != b { - v.checkOverlap(bmat) - } - - if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { - // Fast path for a common case. - f64.AxpyUnitaryTo(v.mat.Data, 1, bmat.Data, amat.Data) - return - } - f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, - 1, bmat.Data, amat.Data, - uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) - return - } - } - - for i := 0; i < ar; i++ { - v.setVec(i, a.AtVec(i)+b.AtVec(i)) - } -} - -// SubVec subtracts the vector b from a, placing the result in the receiver. -func (v *VecDense) SubVec(a, b Vector) { - ar := a.Len() - br := b.Len() - - if ar != br { - panic(ErrShape) - } - - v.reuseAsNonZeroed(ar) - - aU, _ := untransposeExtract(a) - bU, _ := untransposeExtract(b) - - if arv, ok := aU.(*VecDense); ok { - if brv, ok := bU.(*VecDense); ok { - amat := arv.mat - bmat := brv.mat - - if v != a { - v.checkOverlap(amat) - } - if v != b { - v.checkOverlap(bmat) - } - - if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { - // Fast path for a common case. - f64.AxpyUnitaryTo(v.mat.Data, -1, bmat.Data, amat.Data) - return - } - f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, - -1, bmat.Data, amat.Data, - uintptr(ar), uintptr(bmat.Inc), uintptr(amat.Inc), 0, 0) - return - } - } - - for i := 0; i < ar; i++ { - v.setVec(i, a.AtVec(i)-b.AtVec(i)) - } -} - -// MulElemVec performs element-wise multiplication of a and b, placing the result -// in the receiver. -func (v *VecDense) MulElemVec(a, b Vector) { - ar := a.Len() - br := b.Len() - - if ar != br { - panic(ErrShape) - } - - v.reuseAsNonZeroed(ar) - - aU, _ := untransposeExtract(a) - bU, _ := untransposeExtract(b) - - if arv, ok := aU.(*VecDense); ok { - if brv, ok := bU.(*VecDense); ok { - amat := arv.mat - bmat := brv.mat - - if v != a { - v.checkOverlap(amat) - } - if v != b { - v.checkOverlap(bmat) - } - - if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { - // Fast path for a common case. - for i, a := range amat.Data { - v.mat.Data[i] = a * bmat.Data[i] - } - return - } - var ia, ib int - for i := 0; i < ar; i++ { - v.setVec(i, amat.Data[ia]*bmat.Data[ib]) - ia += amat.Inc - ib += bmat.Inc - } - return - } - } - - for i := 0; i < ar; i++ { - v.setVec(i, a.AtVec(i)*b.AtVec(i)) - } -} - -// DivElemVec performs element-wise division of a by b, placing the result -// in the receiver. -func (v *VecDense) DivElemVec(a, b Vector) { - ar := a.Len() - br := b.Len() - - if ar != br { - panic(ErrShape) - } - - v.reuseAsNonZeroed(ar) - - aU, _ := untransposeExtract(a) - bU, _ := untransposeExtract(b) - - if arv, ok := aU.(*VecDense); ok { - if brv, ok := bU.(*VecDense); ok { - amat := arv.mat - bmat := brv.mat - - if v != a { - v.checkOverlap(amat) - } - if v != b { - v.checkOverlap(bmat) - } - - if v.mat.Inc == 1 && amat.Inc == 1 && bmat.Inc == 1 { - // Fast path for a common case. - for i, a := range amat.Data { - v.setVec(i, a/bmat.Data[i]) - } - return - } - var ia, ib int - for i := 0; i < ar; i++ { - v.setVec(i, amat.Data[ia]/bmat.Data[ib]) - ia += amat.Inc - ib += bmat.Inc - } - } - } - - for i := 0; i < ar; i++ { - v.setVec(i, a.AtVec(i)/b.AtVec(i)) - } -} - -// MulVec computes a * b. The result is stored into the receiver. -// MulVec panics if the number of columns in a does not equal the number of rows in b -// or if the number of columns in b does not equal 1. -func (v *VecDense) MulVec(a Matrix, b Vector) { - r, c := a.Dims() - br, bc := b.Dims() - if c != br || bc != 1 { - panic(ErrShape) - } - - aU, trans := untransposeExtract(a) - var bmat blas64.Vector - fast := true - bU, _ := untransposeExtract(b) - if rv, ok := bU.(*VecDense); ok { - bmat = rv.mat - if v != b { - v.checkOverlap(bmat) - } - } else { - fast = false - } - - v.reuseAsNonZeroed(r) - var restore func() - if v == aU { - v, restore = v.isolatedWorkspace(aU.(*VecDense)) - defer restore() - } else if v == b { - v, restore = v.isolatedWorkspace(b) - defer restore() - } - - // TODO(kortschak): Improve the non-fast paths. - switch aU := aU.(type) { - case Vector: - if b.Len() == 1 { - // {n,1} x {1,1} - v.ScaleVec(b.AtVec(0), aU) - return - } - - // {1,n} x {n,1} - if fast { - if rv, ok := aU.(*VecDense); ok { - amat := rv.mat - if v != aU { - v.checkOverlap(amat) - } - - if amat.Inc == 1 && bmat.Inc == 1 { - // Fast path for a common case. - v.setVec(0, f64.DotUnitary(amat.Data, bmat.Data)) - return - } - v.setVec(0, f64.DotInc(amat.Data, bmat.Data, - uintptr(c), uintptr(amat.Inc), uintptr(bmat.Inc), 0, 0)) - return - } - } - var sum float64 - for i := 0; i < c; i++ { - sum += aU.AtVec(i) * b.AtVec(i) - } - v.setVec(0, sum) - return - case *SymBandDense: - if fast { - aU.checkOverlap(v.asGeneral()) - blas64.Sbmv(1, aU.mat, bmat, 0, v.mat) - return - } - case *SymDense: - if fast { - aU.checkOverlap(v.asGeneral()) - blas64.Symv(1, aU.mat, bmat, 0, v.mat) - return - } - case *TriDense: - if fast { - v.CopyVec(b) - aU.checkOverlap(v.asGeneral()) - ta := blas.NoTrans - if trans { - ta = blas.Trans - } - blas64.Trmv(ta, aU.mat, v.mat) - return - } - case *Dense: - if fast { - aU.checkOverlap(v.asGeneral()) - t := blas.NoTrans - if trans { - t = blas.Trans - } - blas64.Gemv(t, 1, aU.mat, bmat, 0, v.mat) - return - } - default: - if fast { - for i := 0; i < r; i++ { - var f float64 - for j := 0; j < c; j++ { - f += a.At(i, j) * bmat.Data[j*bmat.Inc] - } - v.setVec(i, f) - } - return - } - } - - for i := 0; i < r; i++ { - var f float64 - for j := 0; j < c; j++ { - f += a.At(i, j) * b.AtVec(j) - } - v.setVec(i, f) - } -} - -// ReuseAsVec changes the receiver if it IsEmpty() to be of size n×1. -// -// ReuseAsVec re-uses the backing data slice if it has sufficient capacity, -// otherwise a new slice is allocated. The backing data is zero on return. -// -// ReuseAsVec panics if the receiver is not empty, and panics if -// the input size is less than one. To empty the receiver for re-use, -// Reset should be used. -func (v *VecDense) ReuseAsVec(n int) { - if n <= 0 { - if n == 0 { - panic(ErrZeroLength) - } - panic(ErrNegativeDimension) - } - if !v.IsEmpty() { - panic(ErrReuseNonEmpty) - } - v.reuseAsZeroed(n) -} - -// reuseAsNonZeroed resizes an empty vector to a r×1 vector, -// or checks that a non-empty matrix is r×1. -func (v *VecDense) reuseAsNonZeroed(r int) { - // reuseAsNonZeroed must be kept in sync with reuseAsZeroed. - if r == 0 { - panic(ErrZeroLength) - } - if v.IsEmpty() { - v.mat = blas64.Vector{ - N: r, - Inc: 1, - Data: use(v.mat.Data, r), - } - return - } - if r != v.mat.N { - panic(ErrShape) - } -} - -// reuseAsZeroed resizes an empty vector to a r×1 vector, -// or checks that a non-empty matrix is r×1. -func (v *VecDense) reuseAsZeroed(r int) { - // reuseAsZeroed must be kept in sync with reuseAsNonZeroed. - if r == 0 { - panic(ErrZeroLength) - } - if v.IsEmpty() { - v.mat = blas64.Vector{ - N: r, - Inc: 1, - Data: useZeroed(v.mat.Data, r), - } - return - } - if r != v.mat.N { - panic(ErrShape) - } - v.Zero() -} - -// IsEmpty returns whether the receiver is empty. Empty matrices can be the -// receiver for size-restricted operations. The receiver can be emptied using -// Reset. -func (v *VecDense) IsEmpty() bool { - // It must be the case that v.Dims() returns - // zeros in this case. See comment in Reset(). - return v.mat.Inc == 0 -} - -func (v *VecDense) isolatedWorkspace(a Vector) (n *VecDense, restore func()) { - l := a.Len() - if l == 0 { - panic(ErrZeroLength) - } - n = getVecDenseWorkspace(l, false) - return n, func() { - v.CopyVec(n) - putVecDenseWorkspace(n) - } -} - -// asDense returns a Dense representation of the receiver with the same -// underlying data. -func (v *VecDense) asDense() *Dense { - return &Dense{ - mat: v.asGeneral(), - capRows: v.mat.N, - capCols: 1, - } -} - -// asGeneral returns a blas64.General representation of the receiver with the -// same underlying data. -func (v *VecDense) asGeneral() blas64.General { - return blas64.General{ - Rows: v.mat.N, - Cols: 1, - Stride: v.mat.Inc, - Data: v.mat.Data, - } -} - -// ColViewOf reflects the column j of the RawMatrixer m, into the receiver -// backed by the same underlying data. The receiver must either be empty -// have length equal to the number of rows of m. -func (v *VecDense) ColViewOf(m RawMatrixer, j int) { - rm := m.RawMatrix() - - if j >= rm.Cols || j < 0 { - panic(ErrColAccess) - } - if !v.IsEmpty() && v.mat.N != rm.Rows { - panic(ErrShape) - } - - v.mat.Inc = rm.Stride - v.mat.Data = rm.Data[j : (rm.Rows-1)*rm.Stride+j+1] - v.mat.N = rm.Rows -} - -// RowViewOf reflects the row i of the RawMatrixer m, into the receiver -// backed by the same underlying data. The receiver must either be -// empty or have length equal to the number of columns of m. -func (v *VecDense) RowViewOf(m RawMatrixer, i int) { - rm := m.RawMatrix() - - if i >= rm.Rows || i < 0 { - panic(ErrRowAccess) - } - if !v.IsEmpty() && v.mat.N != rm.Cols { - panic(ErrShape) - } - - v.mat.Inc = 1 - v.mat.Data = rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] - v.mat.N = rm.Cols -} - -// Permute rearranges the elements of the n-vector v in the receiver as -// specified by the permutation p[0],p[1],...,p[n-1] of the integers 0,...,n-1. -// -// If inverse is false, the given permutation is applied: -// -// v[p[i]] is moved to v[i] for i=0,1,...,n-1. -// -// If inverse is true, the inverse permutation is applied: -// -// v[i] is moved to v[p[i]] for i=0,1,...,n-1. -// -// p must have length n, otherwise Permute will panic. -func (v *VecDense) Permute(p []int, inverse bool) { - v.asDense().PermuteRows(p, inverse) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/README.md b/vendor/gonum.org/v1/gonum/mathext/README.md deleted file mode 100644 index 9f462f11..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# mathext - -[![go.dev reference](https://pkg.go.dev/badge/gonum.org/v1/gonum/mathext)](https://pkg.go.dev/gonum.org/v1/gonum/mathext) -[![GoDoc](https://godocs.io/gonum.org/v1/gonum/mathext?status.svg)](https://godocs.io/gonum.org/v1/gonum/mathext) - -Package mathext implements basic elementary functions not included in the Go standard library. diff --git a/vendor/gonum.org/v1/gonum/mathext/airy.go b/vendor/gonum.org/v1/gonum/mathext/airy.go deleted file mode 100644 index f2904b47..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/airy.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright ©2016 The Gonum 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 mathext - -import "gonum.org/v1/gonum/mathext/internal/amos" - -// AiryAi returns the value of the Airy function at z. The Airy function here, -// Ai(z), is one of the two linearly independent solutions to -// -// y′′ - y*z = 0. -// -// See http://mathworld.wolfram.com/AiryFunctions.html for more detailed information. -func AiryAi(z complex128) complex128 { - // id specifies the order of the derivative to compute, - // 0 for the function itself and 1 for the derivative. - // kode specifies the scaling option. See the function - // documentation for the exact behavior. - id := 0 - kode := 1 - air, aii, _, _ := amos.Zairy(real(z), imag(z), id, kode) - return complex(air, aii) -} - -// AiryAiDeriv returns the value of the derivative of the Airy function at z. The -// Airy function here, Ai(z), is one of the two linearly independent solutions to -// -// y′′ - y*z = 0. -// -// See http://mathworld.wolfram.com/AiryFunctions.html for more detailed information. -func AiryAiDeriv(z complex128) complex128 { - // id specifies the order of the derivative to compute, - // 0 for the function itself and 1 for the derivative. - // kode specifies the scaling option. See the function - // documentation for the exact behavior. - id := 1 - kode := 1 - air, aii, _, _ := amos.Zairy(real(z), imag(z), id, kode) - return complex(air, aii) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/beta.go b/vendor/gonum.org/v1/gonum/mathext/beta.go deleted file mode 100644 index 2df51f3d..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/beta.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright ©2016 The Gonum 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 mathext - -import "gonum.org/v1/gonum/mathext/internal/gonum" - -// Beta returns the value of the complete beta function B(a, b). It is defined as -// -// Γ(a)Γ(b) / Γ(a+b) -// -// Special cases are: -// -// B(a,b) returns NaN if a or b is Inf -// B(a,b) returns NaN if a and b are 0 -// B(a,b) returns NaN if a or b is NaN -// B(a,b) returns NaN if a or b is < 0 -// B(a,b) returns +Inf if a xor b is 0. -// -// See http://mathworld.wolfram.com/BetaFunction.html for more detailed information. -func Beta(a, b float64) float64 { - return gonum.Beta(a, b) -} - -// Lbeta returns the natural logarithm of the complete beta function B(a,b). -// Lbeta is defined as: -// -// Ln(Γ(a)Γ(b)/Γ(a+b)) -// -// Special cases are: -// -// Lbeta(a,b) returns NaN if a or b is Inf -// Lbeta(a,b) returns NaN if a and b are 0 -// Lbeta(a,b) returns NaN if a or b is NaN -// Lbeta(a,b) returns NaN if a or b is < 0 -// Lbeta(a,b) returns +Inf if a xor b is 0. -func Lbeta(a, b float64) float64 { - return gonum.Lbeta(a, b) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/betainc.go b/vendor/gonum.org/v1/gonum/mathext/betainc.go deleted file mode 100644 index 9a0c61a9..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/betainc.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright ©2016 The Gonum 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 mathext - -import "gonum.org/v1/gonum/mathext/internal/cephes" - -// RegIncBeta returns the value of the regularized incomplete beta function -// I(x;a,b). It is defined as -// -// I(x;a,b) = B(x;a,b) / B(a,b) -// = Γ(a+b) / (Γ(a)*Γ(b)) * int_0^x u^(a-1) * (1-u)^(b-1) du. -// -// The domain of definition is 0 <= x <= 1, and the parameters a and b must be positive. -// For other values of x, a, and b RegIncBeta will panic. -func RegIncBeta(a, b float64, x float64) float64 { - return cephes.Incbet(a, b, x) -} - -// InvRegIncBeta computes the inverse of the regularized incomplete beta function. -// It returns the x for which -// -// y = I(x;a,b) -// -// The domain of definition is 0 <= y <= 1, and the parameters a and b must be -// positive. For other values of x, a, and b InvRegIncBeta will panic. -func InvRegIncBeta(a, b float64, y float64) float64 { - if y < 0 || 1 < y { - panic("mathext: parameter out of range") - } - return cephes.Incbi(a, b, y) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/digamma.go b/vendor/gonum.org/v1/gonum/mathext/digamma.go deleted file mode 100644 index 67ebf007..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/digamma.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright ©2016 The Gonum 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 mathext - -import ( - "math" -) - -// Digamma returns the logorithmic derivative of the gamma function at x. -// -// ψ(x) = d/dx (Ln (Γ(x)). -func Digamma(x float64) float64 { - // This is adapted from - // http://web.science.mq.edu.au/~mjohnson/code/digamma.c - var result float64 - switch { - case math.IsNaN(x), math.IsInf(x, 1): - return x - case math.IsInf(x, -1): - return math.NaN() - case x == 0: - return math.Copysign(math.Inf(1), -x) - case x < 0: - if x == math.Floor(x) { - return math.NaN() - } - // Reflection formula, http://dlmf.nist.gov/5.5#E4 - _, r := math.Modf(x) - result = -math.Pi / math.Tan(math.Pi*r) - x = 1 - x - } - for ; x < 7; x++ { - // Recurrence relation, http://dlmf.nist.gov/5.5#E2 - result -= 1 / x - } - x -= 0.5 - xx := 1 / x - xx2 := xx * xx - xx4 := xx2 * xx2 - // Asymptotic expansion, http://dlmf.nist.gov/5.11#E2 - result += math.Log(x) + (1.0/24.0)*xx2 - (7.0/960.0)*xx4 + (31.0/8064.0)*xx4*xx2 - (127.0/30720.0)*xx4*xx4 - return result -} diff --git a/vendor/gonum.org/v1/gonum/mathext/doc.go b/vendor/gonum.org/v1/gonum/mathext/doc.go deleted file mode 100644 index 539622d4..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright ©2017 The Gonum 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 mathext implements special math functions not implemented by the -// Go standard library. -package mathext // import "gonum.org/v1/gonum/mathext" diff --git a/vendor/gonum.org/v1/gonum/mathext/ell_carlson.go b/vendor/gonum.org/v1/gonum/mathext/ell_carlson.go deleted file mode 100644 index 1334f6b9..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/ell_carlson.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright ©2017 The Gonum 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 mathext - -import ( - "math" -) - -// EllipticRF computes the symmetric elliptic integral R_F(x,y,z): -// -// R_F(x,y,z) = (1/2)\int_{0}^{\infty}{1/s(t)} dt, -// s(t) = \sqrt{(t+x)(t+y)(t+z)}. -// -// The arguments x, y, z must satisfy the following conditions, otherwise the function returns math.NaN(): -// -// 0 ≤ x,y,z ≤ upper, -// lower ≤ x+y,y+z,z+x, -// -// where: -// -// lower = 5/(2^1022) = 1.112536929253601e-307, -// upper = (2^1022)/5 = 8.988465674311580e+306. -// -// The definition of the symmetric elliptic integral R_F can be found in NIST -// Digital Library of Mathematical Functions (http://dlmf.nist.gov/19.16.E1). -func EllipticRF(x, y, z float64) float64 { - // The original Fortran code was published as Algorithm 577 in ACM TOMS (http://doi.org/10.1145/355958.355970). - // This code is also available as a part of SLATEC Common Mathematical Library (http://netlib.org/slatec/index.html). Later, Carlson described - // an improved version in http://dx.doi.org/10.1007/BF02198293 (also available at https://arxiv.org/abs/math/9409227). - const ( - lower = 5.0 / (1 << 256) / (1 << 256) / (1 << 256) / (1 << 254) // 5*2^-1022 - upper = 1 / lower - tol = 1.2674918778210762260320167734407048051023273568443e-02 // (3ε)^(1/8) - ) - if x < 0 || y < 0 || z < 0 || math.IsNaN(x) || math.IsNaN(y) || math.IsNaN(z) { - return math.NaN() - } - if upper < x || upper < y || upper < z { - return math.NaN() - } - if x+y < lower || y+z < lower || z+x < lower { - return math.NaN() - } - - A0 := (x + y + z) / 3 - An := A0 - Q := math.Max(math.Max(math.Abs(A0-x), math.Abs(A0-y)), math.Abs(A0-z)) / tol - xn, yn, zn := x, y, z - mul := 1.0 - - for Q >= mul*math.Abs(An) { - xnsqrt, ynsqrt, znsqrt := math.Sqrt(xn), math.Sqrt(yn), math.Sqrt(zn) - lambda := xnsqrt*ynsqrt + ynsqrt*znsqrt + znsqrt*xnsqrt - An = (An + lambda) * 0.25 - xn = (xn + lambda) * 0.25 - yn = (yn + lambda) * 0.25 - zn = (zn + lambda) * 0.25 - mul *= 4 - } - - X := (A0 - x) / (mul * An) - Y := (A0 - y) / (mul * An) - Z := -(X + Y) - E2 := X*Y - Z*Z - E3 := X * Y * Z - - // http://dlmf.nist.gov/19.36.E1 - return (1 - 1/10.0*E2 + 1/14.0*E3 + 1/24.0*E2*E2 - 3/44.0*E2*E3 - 5/208.0*E2*E2*E2 + 3/104.0*E3*E3 + 1/16.0*E2*E2*E3) / math.Sqrt(An) -} - -// EllipticRD computes the symmetric elliptic integral R_D(x,y,z): -// -// R_D(x,y,z) = (1/2)\int_{0}^{\infty}{1/(s(t)(t+z))} dt, -// s(t) = \sqrt{(t+x)(t+y)(t+z)}. -// -// The arguments x, y, z must satisfy the following conditions, otherwise the function returns math.NaN(): -// -// 0 ≤ x,y ≤ upper, -// lower ≤ z ≤ upper, -// lower ≤ x+y, -// -// where: -// -// lower = (5/(2^1022))^(1/3) = 4.809554074311679e-103, -// upper = ((2^1022)/5)^(1/3) = 2.079194837087086e+102. -// -// The definition of the symmetric elliptic integral R_D can be found in NIST -// Digital Library of Mathematical Functions (http://dlmf.nist.gov/19.16.E5). -func EllipticRD(x, y, z float64) float64 { - // The original Fortran code was published as Algorithm 577 in ACM TOMS (http://doi.org/10.1145/355958.355970). - // This code is also available as a part of SLATEC Common Mathematical Library (http://netlib.org/slatec/index.html). Later, Carlson described - // an improved version in http://dx.doi.org/10.1007/BF02198293 (also available at https://arxiv.org/abs/math/9409227). - const ( - lower = 4.8095540743116787026618007863123676393525016818363e-103 // (5*2^-1022)^(1/3) - upper = 1 / lower - tol = 9.0351169339315770474760122547068324993857488849382e-03 // (ε/5)^(1/8) - ) - if x < 0 || y < 0 || math.IsNaN(x) || math.IsNaN(y) || math.IsNaN(z) { - return math.NaN() - } - if upper < x || upper < y || upper < z { - return math.NaN() - } - if x+y < lower || z < lower { - return math.NaN() - } - - A0 := (x + y + 3*z) / 5 - An := A0 - Q := math.Max(math.Max(math.Abs(A0-x), math.Abs(A0-y)), math.Abs(A0-z)) / tol - xn, yn, zn := x, y, z - mul, s := 1.0, 0.0 - - for Q >= mul*math.Abs(An) { - xnsqrt, ynsqrt, znsqrt := math.Sqrt(xn), math.Sqrt(yn), math.Sqrt(zn) - lambda := xnsqrt*ynsqrt + ynsqrt*znsqrt + znsqrt*xnsqrt - s += 1 / (mul * znsqrt * (zn + lambda)) - An = (An + lambda) * 0.25 - xn = (xn + lambda) * 0.25 - yn = (yn + lambda) * 0.25 - zn = (zn + lambda) * 0.25 - mul *= 4 - } - - X := (A0 - x) / (mul * An) - Y := (A0 - y) / (mul * An) - Z := -(X + Y) / 3 - E2 := X*Y - 6*Z*Z - E3 := (3*X*Y - 8*Z*Z) * Z - E4 := 3 * (X*Y - Z*Z) * Z * Z - E5 := X * Y * Z * Z * Z - - // http://dlmf.nist.gov/19.36.E2 - return (1-3/14.0*E2+1/6.0*E3+9/88.0*E2*E2-3/22.0*E4-9/52.0*E2*E3+3/26.0*E5-1/16.0*E2*E2*E2+3/40.0*E3*E3+3/20.0*E2*E4+45/272.0*E2*E2*E3-9/68.0*(E3*E4+E2*E5))/(mul*An*math.Sqrt(An)) + 3*s -} - -// EllipticF computes the Legendre's elliptic integral of the 1st kind F(phi,m), 0≤m<1: -// -// F(\phi,m) = \int_{0}^{\phi} 1 / \sqrt{1-m\sin^2(\theta)} d\theta -// -// Legendre's elliptic integrals can be expressed as symmetric elliptic integrals, in this case: -// -// F(\phi,m) = \sin\phi R_F(\cos^2\phi,1-m\sin^2\phi,1) -// -// The definition of F(phi,k) where k=sqrt(m) can be found in NIST Digital Library of Mathematical -// Functions (http://dlmf.nist.gov/19.2.E4). -func EllipticF(phi, m float64) float64 { - s, c := math.Sincos(phi) - return s * EllipticRF(c*c, 1-m*s*s, 1) -} - -// EllipticE computes the Legendre's elliptic integral of the 2nd kind E(phi,m), 0≤m<1: -// -// E(\phi,m) = \int_{0}^{\phi} \sqrt{1-m\sin^2(\theta)} d\theta -// -// Legendre's elliptic integrals can be expressed as symmetric elliptic integrals, in this case: -// -// E(\phi,m) = \sin\phi R_F(\cos^2\phi,1-m\sin^2\phi,1)-(m/3)\sin^3\phi R_D(\cos^2\phi,1-m\sin^2\phi,1) -// -// The definition of E(phi,k) where k=sqrt(m) can be found in NIST Digital Library of Mathematical -// Functions (http://dlmf.nist.gov/19.2.E5). -func EllipticE(phi, m float64) float64 { - s, c := math.Sincos(phi) - x, y := c*c, 1-m*s*s - return s * (EllipticRF(x, y, 1) - (m/3)*s*s*EllipticRD(x, y, 1)) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/ell_complete.go b/vendor/gonum.org/v1/gonum/mathext/ell_complete.go deleted file mode 100644 index bdba081a..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/ell_complete.go +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright ©2017 The Gonum 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 mathext - -import ( - "math" -) - -// CompleteK computes the complete elliptic integral of the 1st kind, 0≤m≤1. It returns math.NaN() if m is not in [0,1]. -// -// K(m) = \int_{0}^{π/2} 1/{\sqrt{1-m{\sin^2θ}}} dθ -func CompleteK(m float64) float64 { - // Reference: - // Toshio Fukushima, Precise and fast computation of complete elliptic integrals - // by piecewise minimax rational function approximation, - // Journal of Computational and Applied Mathematics, Volume 282, 2015, Pages 71-76. - // https://doi.org/10.1016/j.cam.2014.12.038 - // Original Fortran code available at: - // https://www.researchgate.net/publication/295857819_xceitxt_F90_package_of_complete_elliptic_integral_computation - if m < 0 || 1 < m || math.IsNaN(m) { - return math.NaN() - } - - mc := 1 - m - - if mc > 0.592990 { - t := 2.45694208987494165*mc - 1.45694208987494165 - t2 := t * t - p := ((3703.75266375099019 + t2*(2744.82029097576810+t2*36.2381612593459565)) + t*(5462.47093231923466+t2*(543.839017382099411+t2*0.393188651542789784))) - q := ((2077.94377067058435 + t2*(1959.05960044399275+t2*43.5464368440078942)) + t*(3398.00069767755460+t2*(472.794455487539279+t2))) - return p / q - } - if mc > 0.350756 { - t := 4.12823963605439369*mc - 1.44800482178389491 - t2 := t * t - p := ((4264.28203103974630 + t2*(3214.59187442783167+t2*43.2589626155454993)) + t*(6341.90978213264024+t2*(642.790566685354573+t2*0.475223892294445943))) - q := ((2125.06914237062279 + t2*(2006.03187933518870+t2*44.1848041560412224)) + t*(3479.95663350926514+t2*(482.900172581418890+t2))) - return p / q - } - if mc > 0.206924 { - t := 6.95255575949719117*mc - 1.43865064797819679 - t2 := t * t - p := ((4870.25402224986382 + t2*(3738.29369283392307+t2*51.3609902253065926)) + t*(7307.18826377416591+t2*(754.928587580583704+t2*0.571948962277566451))) - q := ((2172.51745704102287 + t2*(2056.13612019430497+t2*44.9026847057686146)) + t*(3565.04737778032566+t2*(493.962405117599400+t2))) - return p / q - } - if mc > 0.121734 { - t := 11.7384669562155183*mc - 1.42897053644793990 - t2 := t * t - p := ((5514.8512729127464 + t2*(4313.60788246750934+t2*60.598720224393536)) + t*(8350.4595896779631+t2*(880.27903031894216+t2*0.68504458747933773))) - q := ((2218.41682813309737 + t2*(2107.97379949034285+t2*45.6911096775045314)) + t*(3650.41829123846319+t2*(505.74295207655096+t2))) - return p / q - } - if mc > 0.071412 { - t := 19.8720241643813839*mc - 1.41910098962680339 - t2 := t * t - p := ((6188.8743957372448 + t2*(4935.41351498551527+t2*70.981049144472361)) + t*(9459.3331440432847+t2*(1018.21910476032105+t2*0.81599895108245948))) - q := ((2260.73112539748448 + t2*(2159.68721749761492+t2*46.5298955058476510)) + t*(3732.66955095581621+t2*(517.86964191812384+t2))) - return p / q - } - if mc > 0.041770 { - t := 33.7359152553808785*mc - 1.40914918021725929 - t2 := t * t - p := ((6879.5170681289562 + t2*(5594.8381504799829+t2*82.452856129147838)) + t*(10615.0836403687221+t2*(1167.26108955935542+t2*0.96592719058503951))) - q := ((2296.88303450660439 + t2*(2208.74949754945558+t2*47.3844470709989137)) + t*(3807.37745652028212+t2*(529.79651353072921+t2))) - return p / q - } - if mc > 0.024360 { - t := 57.4382538770821367*mc - 1.39919586444572085 - t2 := t * t - p := ((7570.6827538712100 + t2*(6279.2661370014890+t2*94.886883830605940)) + t*(11792.9392624454532+t2*(1325.01058966228180+t2*1.13537029594409690))) - q := ((2324.04824540459984 + t2*(2252.22250562615338+t2*48.2089280211559345)) + t*(3869.56755306385732+t2*(540.85752251676412+t2))) - return p / q - } - if mc > 0.014165 { - t := 98.0872976949485042*mc - 1.38940657184894556 - t2 := t * t - p := ((8247.2601660137746 + t2*(6974.7495213178613+t2*108.098282908839979)) + t*(12967.7060124572914+t2*(1488.54008220335966+t2*1.32411616748380686))) - q := ((2340.47337508405427 + t2*(2287.70677154700516+t2*48.9575432570382154)) + t*(3915.63324533769906+t2*(550.45072377717361+t2))) - return p / q - } - if mc > 0.008213 { - t := 168.010752688172043*mc - 1.37987231182795699 - t2 := t * t - p := ((8894.2961573611293 + t2*(7666.5611739483371+t2*121.863474964652041)) + t*(14113.7038749808951+t2*(1654.60731579994159+t2*1.53112170837206117))) - q := ((2344.88618943372377 + t2*(2313.28396270968662+t2*49.5906602613891184)) + t*(3942.81065054556536+t2*(558.07615380622169+t2))) - return p / q - } - if mc > 0 { - t := 1.0 - 121.758188238159016*mc - p := -math.Log(mc*0.0625) * (34813.4518336350547 + t*(235.767716637974271+t*0.199792723884069485)) / (69483.5736412906324 + t*(614.265044703187382+t)) - q := -mc * (9382.53386835986099 + t*(51.6478985993381223+t*0.00410754154682816898)) / (37327.7262507318317 + t*(408.017247271148538+t)) - return p + q - } - - return math.Inf(1) -} - -// CompleteE computes the complete elliptic integral of the 2nd kind, 0≤m≤1. It returns math.NaN() if m is not in [0,1]. -// -// E(m) = \int_{0}^{π/2} {\sqrt{1-m{\sin^2θ}}} dθ -func CompleteE(m float64) float64 { - // Reference: - // Toshio Fukushima, Precise and fast computation of complete elliptic integrals - // by piecewise minimax rational function approximation, - // Journal of Computational and Applied Mathematics, Volume 282, 2015, Pages 71-76. - // https://doi.org/10.1016/j.cam.2014.12.038 - // Original Fortran code available at: - // https://www.researchgate.net/publication/295857819_xceitxt_F90_package_of_complete_elliptic_integral_computation - if m < 0 || 1 < m || math.IsNaN(m) { - return math.NaN() - } - - mc := 1 - m - - if mc > 0.566638 { - t := 2.30753965506897236*mc - 1.30753965506897236 - t2 := t * t - p := ((19702.2363352671642 + t2*(18177.1879313824040+t2*409.975559128654710)) + t*(31904.1559574281609+t2*(4362.94760768571862+t2*10.3244775335024885))) - q := ((14241.2135819448616 + t2*(10266.4884503526076+t2*117.162100771599098)) + t*(20909.9899599927367+t2*(1934.86289070792954+t2))) - return p / q - } - if mc > 0.315153 { - t := 3.97638030101198879*mc - 1.25316818100483130 - t2 := t * t - p := ((16317.0721393008221 + t2*(15129.4009798463159+t2*326.113727011739428)) + t*(26627.8852140835023+t2*(3574.15857605556033+t2*7.93163724081373477))) - q := ((13047.1505096551210 + t2*(9964.25173735060361+t2*117.670514069579649)) + t*(19753.5762165922376+t2*(1918.72232033637537+t2))) - return p / q - } - if mc > 0.171355 { - t := 6.95419964116329852*mc - 1.19163687951153702 - t2 := t * t - p := ((13577.3850240991520 + t2*(12871.9137872656293+t2*263.964361648520708)) + t*(22545.4744699553993+t2*(3000.74575264868572+t2*6.08522443139677663))) - q := ((11717.3306408059832 + t2*(9619.40382323874064+t2*118.690522739531267)) + t*(18431.1264424290258+t2*(1904.06010727307491+t2))) - return p / q - } - if mc > 0.090670 { - t := 12.3938774245522712*mc - 1.12375286608415443 - t2 := t * t - p := ((11307.9485341543712 + t2*(11208.6068472959372+t2*219.253495956962613)) + t*(19328.6173704569489+t2*(2596.54874477084334+t2*4.66931143174036616))) - q := ((10307.6837501971393 + t2*(9241.7604666150102+t2*120.498555754227847)) + t*(16982.2450249024383+t2*(1893.41905403040679+t2))) - return p / q - } - if mc > 0.046453 { - t := 22.6157360291290680*mc - 1.05056878576113260 - t2 := t * t - p := ((9383.1490856819874 + t2*(9977.2498973537718+t2*188.618148076418837)) + t*(16718.9730458676860+t2*(2323.49987246555537+t2*3.59313532204509922))) - q := ((8877.1964704758383 + t2*(8840.2771293410661+t2*123.422125687316355)) + t*(15450.0537230364062+t2*(1889.13672102820913+t2))) - return p / q - } - if mc > 0.022912 { - t := 42.4790790535661187*mc - 0.973280659275306911 - t2 := t * t - p := ((7719.1171817802054 + t2*(9045.3996063894006+t2*169.386557799782496)) + t*(14521.7363804934985+t2*(2149.92068078627829+t2*2.78515570453129137))) - q := ((7479.7539074698012 + t2*(8420.3848818926324+t2*127.802109608726363)) + t*(13874.4978011497847+t2*(1892.69753150329759+t2))) - return p / q - } - if mc > 0.010809 { - t := 82.6241427745187144*mc - 0.893084359249772784 - t2 := t * t - p := ((6261.6095608987273 + t2*(8304.3265605809870+t2*159.371262600702237)) + t*(12593.0874916293982+t2*(2048.68391263416822+t2*2.18867046462858104))) - q := ((6156.4532048239501 + t2*(7979.7435857665227+t2*133.911640385965187)) + t*(12283.8373999680518+t2*(1903.60556312663537+t2))) - return p / q - } - if mc > 0.004841 { - t := 167.560321715817694*mc - 0.811159517426273458 - t2 := t * t - p := ((4978.06146583586728 + t2*(7664.6703673290453+t2*156.689647694892782)) + t*(10831.7178150656694+t2*(1995.66437151562090+t2*1.75859085945198570))) - q := ((4935.56743322938333 + t2*(7506.8028283118051+t2*141.854303920116856)) + t*(10694.5510113880077+t2*(1918.38517009740321+t2))) - return p / q - } - if mc > 0 { - t := 1.0 - 206.568890725056806*mc - p := -mc * math.Log(mc*0.0625) * (41566.6612602868736 + t*(154.034981522913482+t*0.0618072471798575991)) / (165964.442527585615 + t*(917.589668642251803+t)) - q := (132232.803956682877 + t*(353.375480007017643-t*1.40105837312528026)) / (132393.665743088043 + t*(192.112635228732532-t)) - return p + q - } - - return 1 -} - -// CompleteB computes an associate complete elliptic integral of the 2nd kind, 0≤m≤1. It returns math.NaN() if m is not in [0,1]. -// -// B(m) = \int_{0}^{π/2} {\cos^2θ} / {\sqrt{1-m{\sin^2θ}}} dθ -func CompleteB(m float64) float64 { - // Reference: - // Toshio Fukushima, Precise and fast computation of complete elliptic integrals - // by piecewise minimax rational function approximation, - // Journal of Computational and Applied Mathematics, Volume 282, 2015, Pages 71-76. - // https://doi.org/10.1016/j.cam.2014.12.038 - // Original Fortran code available at: - // https://www.researchgate.net/publication/295857819_xceitxt_F90_package_of_complete_elliptic_integral_computation - if m < 0 || 1 < m || math.IsNaN(m) { - return math.NaN() - } - - mc := 1 - m - - if mc > 0.555073 { - t := 2.24755971204264969*mc - 1.24755971204264969 - t2 := t * t - p := ((2030.25011505956379 + t2*(1727.60635612511943+t2*25.0715510300422010)) + t*(3223.16236100954529+t2*(361.164121995173076+t2*0.280355207707726826))) - q := ((2420.64907902774675 + t2*(2327.48464880306840+t2*47.9870997057202318)) + t*(4034.28168313496638+t2*(549.234220839203960+t2))) - return p / q - } - if mc > 0.302367 { - t := 3.95716761770595079*mc - 1.19651690106289522 - t2 := t * t - p := ((2209.26925068374373 + t2*(1981.37862223307242+t2*29.7612810087709299)) + t*(3606.58475322372526+t2*(422.693774742063054+t2*0.334623999861181980))) - q := ((2499.57898767250755 + t2*(2467.63998386656941+t2*50.0198090806651216)) + t*(4236.30953048456334+t2*(581.879599221457589+t2))) - return p / q - } - if mc > 0.161052 { - t := 7.07638962601280827*mc - 1.13966670204861480 - t2 := t * t - p := ((2359.14823394150129 + t2*(2254.30785457761760+t2*35.2259786264917876)) + t*(3983.28520266051676+t2*(492.601686517364701+t2*0.396605124984359783))) - q := ((2563.95563932625156 + t2*(2633.23323959119935+t2*52.6711647124832948)) + t*(4450.19076667898892+t2*(622.983787815718489+t2))) - return p / q - } - if mc > 0.083522 { - t := 12.8982329420869341*mc - 1.07728621178898491 - t2 := t * t - p := ((2464.65334987833736 + t2*(2541.68516994216007+t2*41.5832527504007778)) + t*(4333.38639187691528+t2*(571.53606797524881+t2*0.465975784547025267))) - q := ((2600.66956117247726 + t2*(2823.69445052534842+t2*56.136001230010910)) + t*(4661.64381841490914+t2*(674.25435972414302+t2))) - return p / q - } - if mc > 0.041966 { - t := 24.0639137549331023*mc - 1.00986620463952257 - t2 := t * t - p := ((2509.86724450741259 + t2*(2835.27071287535469+t2*48.9701196718008345)) + t*(4631.12336462339975+t2*(659.86172161727281+t2*0.54158304771955794))) - q := ((2594.15983397593723 + t2*(3034.20118545214106+t2*60.652838995496991)) + t*(4848.17491604384532+t2*(737.15143838356850+t2))) - return p / q - } - if mc > 0.020313 { - t := 46.1829769546944996*mc - 0.938114810880709371 - t2 := t * t - p := ((2480.58307884128017 + t2*(3122.00900554841322+t2*57.541132641218839)) + t*(4845.57861173250699+t2*(757.31633816400643+t2*0.62119950515996627))) - q := ((2528.85218300581396 + t2*(3253.86151324157460+t2*66.496093157522450)) + t*(4979.31783250484768+t2*(812.40556572486862+t2))) - return p / q - } - if mc > 0.009408 { - t := 91.7010545621274645*mc - 0.862723521320495186 - t2 := t * t - p := ((2365.25385348859592 + t2*(3381.09304915246175+t2*67.442026950538221)) + t*(4939.53925884558687+t2*(862.16657576129841+t2*0.70143698925710129))) - q := ((2390.48737882063755 + t2*(3462.34808443022907+t2*73.934680452209164)) + t*(5015.4675579215077+t2*(898.99542983710459+t2))) - return p / q - } - if mc > 0.004136 { - t := 189.681335356600910*mc - 0.784522003034901366 - t2 := t * t - p := ((2160.82916040868119 + t2*(3584.53058926175721+t2*78.769178005879162)) + t*(4877.14832623847052+t2*(970.53716686804832+t2*0.77797110431753920))) - q := ((2172.70451405048305 + t2*(3630.52345460629336+t2*83.173163222639080)) + t*(4916.35263668839769+t2*(993.36676027886685+t2))) - return p / q - } - if mc > 0 { - t := 1 - 106.292517006802721*mc - p := mc * math.Log(mc*0.0625) * (6607.46457640413908 + t*(19.0287633783211078-t*0.00625368946932704460)) / (26150.3443630974309 + t*(354.603981274536040+t)) - q := (26251.5678902584870 + t*(168.788023807915689+t*0.352150236262724288)) / (26065.7912239203873 + t*(353.916840382280456+t)) - return p + q - } - - return 1 -} - -// CompleteD computes an associate complete elliptic integral of the 2nd kind, 0≤m≤1. It returns math.NaN() if m is not in [0,1]. -// -// D(m) = \int_{0}^{π/2} {\sin^2θ} / {\sqrt{1-m{\sin^2θ}}} dθ -func CompleteD(m float64) float64 { - // Reference: - // Toshio Fukushima, Precise and fast computation of complete elliptic integrals - // by piecewise minimax rational function approximation, - // Journal of Computational and Applied Mathematics, Volume 282, 2015, Pages 71-76. - // https://doi.org/10.1016/j.cam.2014.12.038 - // Original Fortran code available at: - // https://www.researchgate.net/publication/295857819_xceitxt_F90_package_of_complete_elliptic_integral_computation - if m < 0 || 1 < m || math.IsNaN(m) { - return math.NaN() - } - - mc := 1 - m - - if mc > 0.599909 { - t := 2.49943137936119533*mc - 1.49943137936119533 - t2 := t * t - p := ((1593.39813781813498 + t2*(1058.56241259843217+t2*11.7584241242587571)) + t*(2233.25576544961714+t2*(195.247394601357872+t2*0.101486443490307517))) - q := ((1685.47865546030468 + t2*(1604.88100543517015+t2*38.6743012128666717)) + t*(2756.20968383181114+t2*(397.504162950935944+t2))) - return p / q - } - if mc > 0.359180 { - t := 4.15404874360795750*mc - 1.49205122772910617 - t2 := t * t - p := ((1967.01442513777287 + t2*(1329.30058268219177+t2*15.0447805948342760)) + t*(2779.87604145516343+t2*(247.475085945854673+t2*0.130547566005491628))) - q := ((1749.70634057327467 + t2*(1654.40804288486242+t2*39.1895256017535337)) + t*(2853.92630369567765+t2*(406.925098588378587+t2))) - return p / q - } - if mc > 0.214574 { - t := 6.91534237860116454*mc - 1.48385267554596628 - t2 := t * t - p := ((2409.64196912091452 + t2*(1659.30176823041376+t2*19.1942111405094383)) + t*(3436.40744503228691+t2*(312.186468430688790+t2*0.167847673021897479))) - q := ((1824.89205701262525 + t2*(1715.38574780156913+t2*39.8798253173462218)) + t*(2971.02216287936566+t2*(418.929791715319490+t2))) - return p / q - } - if mc > 0.127875 { - t := 11.5341584101316047*mc - 1.47493050669557896 - t2 := t * t - p := ((2926.81143179637839 + t2*(2056.45624281065334+t2*24.3811986813439843)) + t*(4214.52119721241319+t2*(391.420514384925370+t2*0.215574280659075512))) - q := ((1910.33091918583314 + t2*(1787.99942542734799+t2*40.7663012893484449)) + t*(3107.04531802441481+t2*(433.673494280825971+t2))) - return p / q - } - if mc > 0.076007 { - t := 19.2797100331611013*mc - 1.46539292049047582 - t2 := t * t - p := ((3520.63614251102960 + t2*(2526.67111759550923+t2*30.7739877519417978)) + t*(5121.2842239226937+t2*(486.926821696342529+t2*0.276315678908126399))) - q := ((2003.81997889501324 + t2*(1871.05914195570669+t2*41.8489850490387023)) + t*(3259.09205279874214+t2*(451.007555352632053+t2))) - return p / q - } - if mc > 0.045052 { - t := 32.3049588111775157*mc - 1.45540300436116944 - t2 := t * t - p := ((4188.00087087025347 + t2*(3072.05695847158556+t2*38.5070211470790031)) + t*(6156.0080960857764+t2*(599.76666155374012+t2*0.352955925261363680))) - q := ((2101.60113938424690 + t2*(1961.76794074710108+t2*43.0997999502743622)) + t*(3421.55151253792527+t2*(470.407158843118117+t2))) - return p / q - } - if mc > 0.026626 { - t := 54.2711386084880061*mc - 1.44502333658960165 - t2 := t * t - p := ((4916.74442376570733 + t2*(3688.12811638360551+t2*47.6447145147811350)) + t*(7304.6632479558695+t2*(729.75841970840314+t2*0.448422756936257635))) - q := ((2197.49982676612397 + t2*(2055.19657857622715+t2*44.4576261146308645)) + t*(3584.94502590860852+t2*(490.880160668822953+t2))) - return p / q - } - if mc > 0.015689 { - t := 91.4327512114839536*mc - 1.43448843375697175 - t2 := t * t - p := ((5688.7542903989517 + t2*(4364.21513060078954+t2*58.159468141567195)) + t*(8542.6096475195826+t2*(875.35992968472914+t2*0.56528145509695951))) - q := ((2285.44062680812883 + t2*(2145.80779422696555+t2*45.8427480379028781)) + t*(3739.30422133833258+t2*(511.23253971875808+t2))) - return p / q - } - if mc > 0.009216 { - t := 154.487872701992894*mc - 1.42376023482156651 - t2 := t * t - p := ((6475.3392225234969 + t2*(5081.2997108708577+t2*69.910123337464043)) + t*(9829.1138694605662+t2*(1033.32687775311981+t2*0.70526087421186325))) - q := ((2357.74885505777295 + t2*(2226.89527217032394+t2*47.1609071069631012)) + t*(3872.32565152553360+t2*(530.03943432061149+t2))) - return p / q - } - if mc > 0 { - t := 1 - 108.506944444444444*mc - p := -math.Log(mc*0.0625) * (6.2904323649908115e6 + t*(58565.284164780476+t*(131.176674599188545+t*0.0426826410911220304))) / (1.24937550257219890e7 + t*(203580.534005225410+t*(921.17729845011868+t))) - q := -(27356.1090344387530 + t*(107.767403612304371-t*0.0827769227048233593)) / (27104.0854889805978 + t*(358.708172147752755+t)) - return p + q - } - - return math.Inf(1) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/erf.go b/vendor/gonum.org/v1/gonum/mathext/erf.go deleted file mode 100644 index 793238b0..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/erf.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright ©2017 The Gonum 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 mathext - -import "math" - -/* -Copyright (c) 2012 The Probab Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. -* Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -// NormalQuantile computes the quantile function (inverse CDF) of the standard -// normal. NormalQuantile panics if the input p is less than 0 or greater than 1. -func NormalQuantile(p float64) float64 { - switch { - case p < 0 || 1 < p: - panic("mathext: quantile out of bounds") - case p == 1: - return math.Inf(1) - case p == 0: - return math.Inf(-1) - } - // Compute rational approximation based on the value of p. - - dp := p - 0.5 - if math.Abs(dp) <= 0.425 { - z := 0.180625 - dp*dp - z1 := ((((((zQSA[0]*z+zQSA[1])*z+zQSA[2])*z+zQSA[3])*z+zQSA[4])*z+zQSA[5])*z+zQSA[6])*z + zQSA[7] - z2 := ((((((zQSB[0]*z+zQSB[1])*z+zQSB[2])*z+zQSB[3])*z+zQSB[4])*z+zQSB[5])*z+zQSB[6])*z + zQSB[7] - return dp * z1 / z2 - } - - if p < 0.5 { - r := math.Sqrt(-math.Log(p)) - if r <= 5.0 { - z := r - 1.6 - z1 := ((((((zQIA[0]*z+zQIA[1])*z+zQIA[2])*z+zQIA[3])*z+zQIA[4])*z+zQIA[5])*z+zQIA[6])*z + zQIA[7] - z2 := ((((((zQIB[0]*z+zQIB[1])*z+zQIB[2])*z+zQIB[3])*z+zQIB[4])*z+zQIB[5])*z+zQIB[6])*z + zQIB[7] - return -z1 / z2 - } - z := r - 5 - z1 := ((((((zQTA[0]*z+zQTA[1])*z+zQTA[2])*z+zQTA[3])*z+zQTA[4])*z+zQTA[5])*z+zQTA[6])*z + zQTA[7] - z2 := ((((((zQTB[0]*z+zQTB[1])*z+zQTB[2])*z+zQTB[3])*z+zQTB[4])*z+zQTB[5])*z+zQTB[6])*z + zQTB[7] - return -z1 / z2 - } - r := math.Sqrt(-math.Log(1 - p)) - if r <= 5.0 { - z := r - 1.6 - z1 := ((((((zQIA[0]*z+zQIA[1])*z+zQIA[2])*z+zQIA[3])*z+zQIA[4])*z+zQIA[5])*z+zQIA[6])*z + zQIA[7] - z2 := ((((((zQIB[0]*z+zQIB[1])*z+zQIB[2])*z+zQIB[3])*z+zQIB[4])*z+zQIB[5])*z+zQIB[6])*z + zQIB[7] - return z1 / z2 - } - - z := r - 5 - z1 := ((((((zQTA[0]*z+zQTA[1])*z+zQTA[2])*z+zQTA[3])*z+zQTA[4])*z+zQTA[5])*z+zQTA[6])*z + zQTA[7] - z2 := ((((((zQTB[0]*z+zQTB[1])*z+zQTB[2])*z+zQTB[3])*z+zQTB[4])*z+zQTB[5])*z+zQTB[6])*z + zQTB[7] - return z1 / z2 -} - -var ( - zQSA = [...]float64{2509.0809287301226727, 33430.575583588128105, 67265.770927008700853, 45921.953931549871457, 13731.693765509461125, 1971.5909503065514427, 133.14166789178437745, 3.387132872796366608} - zQSB = [...]float64{5226.495278852854561, 28729.085735721942674, 39307.89580009271061, 21213.794301586595867, 5394.1960214247511077, 687.1870074920579083, 42.313330701600911252, 1.0} - zQIA = [...]float64{7.7454501427834140764e-4, 0.0227238449892691845833, 0.24178072517745061177, 1.27045825245236838258, 3.64784832476320460504, 5.7694972214606914055, 4.6303378461565452959, 1.42343711074968357734} - zQIB = [...]float64{1.05075007164441684324e-9, 5.475938084995344946e-4, 0.0151986665636164571966, 0.14810397642748007459, 0.68976733498510000455, 1.6763848301838038494, 2.05319162663775882187, 1.0} - zQTA = [...]float64{2.01033439929228813265e-7, 2.71155556874348757815e-5, 0.0012426609473880784386, 0.026532189526576123093, 0.29656057182850489123, 1.7848265399172913358, 5.4637849111641143699, 6.6579046435011037772} - zQTB = [...]float64{2.04426310338993978564e-15, 1.4215117583164458887e-7, 1.8463183175100546818e-5, 7.868691311456132591e-4, 0.0148753612908506148525, 0.13692988092273580531, 0.59983220655588793769, 1.0} -) diff --git a/vendor/gonum.org/v1/gonum/mathext/gamma_inc.go b/vendor/gonum.org/v1/gonum/mathext/gamma_inc.go deleted file mode 100644 index c4abe2c2..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/gamma_inc.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright ©2016 The Gonum 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 mathext - -import ( - "gonum.org/v1/gonum/mathext/internal/cephes" -) - -// GammaIncReg computes the regularized incomplete Gamma integral. -// -// GammaIncReg(a,x) = (1/ Γ(a)) \int_0^x e^{-t} t^{a-1} dt -// -// The input argument a must be positive and x must be non-negative or GammaIncReg -// will panic. -// -// See http://mathworld.wolfram.com/IncompleteGammaFunction.html -// or https://en.wikipedia.org/wiki/Incomplete_gamma_function for more detailed -// information. -func GammaIncReg(a, x float64) float64 { - return cephes.Igam(a, x) -} - -// GammaIncRegComp computes the complemented regularized incomplete Gamma integral. -// -// GammaIncRegComp(a,x) = 1 - GammaIncReg(a,x) -// = (1/ Γ(a)) \int_x^\infty e^{-t} t^{a-1} dt -// -// The input argument a must be positive and x must be non-negative or -// GammaIncRegComp will panic. -func GammaIncRegComp(a, x float64) float64 { - return cephes.IgamC(a, x) -} - -// GammaIncRegInv computes the inverse of the regularized incomplete Gamma integral. That is, -// it returns the x such that: -// -// GammaIncReg(a, x) = y -// -// The input argument a must be positive and y must be between 0 and 1 -// inclusive or GammaIncRegInv will panic. GammaIncRegInv should return a positive -// number, but can return NaN if there is a failure to converge. -func GammaIncRegInv(a, y float64) float64 { - return gammaIncRegInv(a, y) -} - -// GammaIncRegCompInv computes the inverse of the complemented regularized incomplete Gamma -// integral. That is, it returns the x such that: -// -// GammaIncRegComp(a, x) = y -// -// The input argument a must be positive and y must be between 0 and 1 -// inclusive or GammaIncRegCompInv will panic. GammaIncRegCompInv should return a -// positive number, but can return 0 even with non-zero y due to underflow. -func GammaIncRegCompInv(a, y float64) float64 { - return cephes.IgamI(a, y) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go b/vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go deleted file mode 100644 index 175cb6bc..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/gamma_inc_inv.go +++ /dev/null @@ -1,58 +0,0 @@ -// Derived from SciPy's special/c_misc/gammaincinv.c -// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/gammaincinv.c - -// Copyright ©2017 The Gonum 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 mathext - -import ( - "math" - - "gonum.org/v1/gonum/mathext/internal/cephes" -) - -const ( - allowedATol = 1e-306 - allowedRTol = 1e-6 -) - -func gammaIncReg(x float64, params []float64) float64 { - return cephes.Igam(params[0], x) - params[1] -} - -// gammaIncRegInv is the inverse of the regularized incomplete Gamma integral. That is, it -// returns x such that: -// -// Igam(a, x) = y -// -// The input argument a must be positive and y must be between 0 and 1 -// inclusive or gammaIncRegInv will panic. gammaIncRegInv should return a -// positive number, but can return NaN if there is a failure to converge. -func gammaIncRegInv(a, y float64) float64 { - // For y not small, we just use - // IgamI(a, 1-y) - // (inverse of the complemented incomplete Gamma integral). For y small, - // however, 1-y is about 1, and we lose digits. - if a <= 0 || y <= 0 || y >= 0.25 { - return cephes.IgamI(a, 1-y) - } - - lo := 0.0 - flo := -y - hi := cephes.IgamI(a, 0.75) - fhi := 0.25 - y - - params := []float64{a, y} - - // Also, after we generate a small interval by bisection above, false - // position will do a large step from an interval of width ~1e-4 to ~1e-14 - // in one step (a=10, x=0.05, but similar for other values). - result, bestX, _, errEst := falsePosition(lo, hi, flo, fhi, 2*machEp, 2*machEp, 1e-2*a, gammaIncReg, params) - if result == fSolveMaxIterations && errEst > allowedATol+allowedRTol*math.Abs(bestX) { - bestX = math.NaN() - } - - return bestX -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go b/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go deleted file mode 100644 index 6ea2d466..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/amos/amos.go +++ /dev/null @@ -1,2136 +0,0 @@ -// Copyright ©2016 The Gonum 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 amos - -import ( - "math" - "math/cmplx" -) - -/* -The AMOS functions are included in SLATEC, and the SLATEC guide (http://www.netlib.org/slatec/guide) explicitly states: -"The Library is in the public domain and distributed by the Energy -Science and Technology Software Center." -Mention of AMOS's inclusion in SLATEC goes back at least to this 1985 technical report from Sandia National Labs: http://infoserve.sandia.gov/sand_doc/1985/851018.pdf -*/ - -// math.NaN() are for padding to keep indexing easy. -var imach = []int{-0, 5, 6, 0, 0, 32, 4, 2, 31, 2147483647, 2, 24, -125, 127, 53, -1021, 1023} - -var dmach = []float64{math.NaN(), 2.23e-308, 1.79e-308, 1.11e-16, 2.22e-16, 0.30103000998497009} - -func abs(a int) int { - if a >= 0 { - return a - } - return -a -} - -func Zairy(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ, IERR int) { - // zairy is adapted from the original Netlib code by Donald Amos. - // http://www.netlib.no/netlib/amos/zairy.f - - // Original comment: - /* - C***BEGIN PROLOGUE ZAIRY - C***DATE WRITTEN 830501 (YYMMDD) - C***REVISION DATE 890801 (YYMMDD) - C***CATEGORY NO. B5K - C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD - C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES - C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z - C***DESCRIPTION - C - C ***A DOUBLE PRECISION ROUTINE*** - C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR - C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON - C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)* - C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN - C -PI/3<ARG(Z)<PI/3 AND THE EXPONENTIAL GROWTH IN - C PI/3<ABS(ARG(Z))<PI WHERE ZTA=(2/3)*Z*CSQRT(Z). - C - C WHILE THE AIRY FUNCTIONS AI(Z) AND DAI(Z)/DZ ARE ANALYTIC IN - C THE WHOLE Z PLANE, THE CORRESPONDING SCALED FUNCTIONS DEFINED - C FOR KODE=2 HAVE A CUT ALONG THE NEGATIVE REAL AXIS. - C DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF - C MATHEMATICAL FUNCTIONS (REF. 1). - C - C INPUT ZR,ZI ARE DOUBLE PRECISION - C ZR,ZI - Z=CMPLX(ZR,ZI) - C ID - ORDER OF DERIVATIVE, ID=0 OR ID=1 - C KODE - A PARAMETER TO INDICATE THE SCALING OPTION - C KODE= 1 returnS - C AI=AI(Z) ON ID=0 OR - C AI=DAI(Z)/DZ ON ID=1 - C = 2 returnS - C AI=CEXP(ZTA)*AI(Z) ON ID=0 OR - C AI=CEXP(ZTA)*DAI(Z)/DZ ON ID=1 WHERE - C ZTA=(2/3)*Z*CSQRT(Z) - C - C OUTPUT AIR,AII ARE DOUBLE PRECISION - C AIR,AII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND - C KODE - C NZ - UNDERFLOW INDICATOR - C NZ= 0 , NORMAL return - C NZ= 1 , AI=CMPLX(0.0E0,0.0E0) DUE TO UNDERFLOW IN - C -PI/3<ARG(Z)<PI/3 ON KODE=1 - C IERR - ERROR FLAG - C IERR=0, NORMAL return - COMPUTATION COMPLETED - C IERR=1, INPUT ERROR - NO COMPUTATION - C IERR=2, OVERFLOW - NO COMPUTATION, REAL(ZTA) - C TOO LARGE ON KODE=1 - C IERR=3, CABS(Z) LARGE - COMPUTATION COMPLETED - C LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION - C PRODUCE LESS THAN HALF OF MACHINE ACCURACY - C IERR=4, CABS(Z) TOO LARGE - NO COMPUTATION - C COMPLETE LOSS OF ACCURACY BY ARGUMENT - C REDUCTION - C IERR=5, ERROR - NO COMPUTATION, - C ALGORITHM TERMINATION CONDITION NOT MET - C - C***LONG DESCRIPTION - C - C AI AND DAI ARE COMPUTED FOR CABS(Z)>1.0 FROM THE K BESSEL - C FUNCTIONS BY - C - C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA) - C C=1.0/(PI*SQRT(3.0)) - C ZTA=(2/3)*Z**(3/2) - C - C WITH THE POWER SERIES FOR CABS(Z)<=1.0. - C - C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- - C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES - C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF - C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), - C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR - C FLAG IERR=3 IS TRIGGERED WHERE UR=math.Max(dmach[4),1.0D-18) IS - C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. - C ALSO, if THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN - C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT - C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE - C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA - C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, - C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE - C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE - C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- - C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- - C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN - C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN - C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, - C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE - C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER - C MACHINES. - C - C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX - C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT - C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- - C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE - C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), - C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF - C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY - C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN - C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY - C SEVERAL ORDERS OF MAGNITUDE. if ONE COMPONENT IS 10**K LARGER - C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, - C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS - C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER - C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY - C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER - C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE - C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, - C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, - C OR -PI/2+P. - C - C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ - C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF - C COMMERCE, 1955. - C - C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT - C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 - C - C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX - C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- - C 1018, MAY, 1985 - C - C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX - C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. - C MATH. SOFTWARE, 1986 - */ - var AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3 complex128 - var AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK, - CC, CK, COEF, CONEI, CONER, CSQI, CSQR, C1, C2, DIG, - DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR, - S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI, - ZEROR, ZTAI, ZTAR, Z3I, Z3R, ALAZ, BB float64 - var IFLAG, K, K1, K2, MR, NN int - var tmp complex128 - - // Extra element for padding. - CYR := []float64{math.NaN(), 0} - CYI := []float64{math.NaN(), 0} - - _ = AI - _ = CONE - _ = CSQ - _ = CY - _ = S1 - _ = S2 - _ = TRM1 - _ = TRM2 - _ = Z - _ = ZTA - _ = Z3 - - TTH = 6.66666666666666667e-01 - C1 = 3.55028053887817240e-01 - C2 = 2.58819403792806799e-01 - COEF = 1.83776298473930683e-01 - ZEROR = 0 - ZEROI = 0 - CONER = 1 - CONEI = 0 - - NZ = 0 - if ID < 0 || ID > 1 { - IERR = 1 - } - if KODE < 1 || KODE > 2 { - IERR = 1 - } - if IERR != 0 { - return - } - AZ = cmplx.Abs(complex(ZR, ZI)) - TOL = math.Max(dmach[4], 1.0e-18) - FID = float64(ID) - if AZ > 1.0e0 { - goto Seventy - } - - // POWER SERIES FOR CABS(Z)<=1. - S1R = CONER - S1I = CONEI - S2R = CONER - S2I = CONEI - if AZ < TOL { - goto OneSeventy - } - AA = AZ * AZ - if AA < TOL/AZ { - goto Forty - } - TRM1R = CONER - TRM1I = CONEI - TRM2R = CONER - TRM2I = CONEI - ATRM = 1.0e0 - STR = ZR*ZR - ZI*ZI - STI = ZR*ZI + ZI*ZR - Z3R = STR*ZR - STI*ZI - Z3I = STR*ZI + STI*ZR - AZ3 = AZ * AA - AK = 2.0e0 + FID - BK = 3.0e0 - FID - FID - CK = 4.0e0 - FID - DK = 3.0e0 + FID + FID - D1 = AK * DK - D2 = BK * CK - AD = math.Min(D1, D2) - AK = 24.0e0 + 9.0e0*FID - BK = 30.0e0 - 9.0e0*FID - for K = 1; K <= 25; K++ { - STR = (TRM1R*Z3R - TRM1I*Z3I) / D1 - TRM1I = (TRM1R*Z3I + TRM1I*Z3R) / D1 - TRM1R = STR - S1R = S1R + TRM1R - S1I = S1I + TRM1I - STR = (TRM2R*Z3R - TRM2I*Z3I) / D2 - TRM2I = (TRM2R*Z3I + TRM2I*Z3R) / D2 - TRM2R = STR - S2R = S2R + TRM2R - S2I = S2I + TRM2I - ATRM = ATRM * AZ3 / AD - D1 = D1 + AK - D2 = D2 + BK - AD = math.Min(D1, D2) - if ATRM < TOL*AD { - goto Forty - } - AK = AK + 18.0e0 - BK = BK + 18.0e0 - } -Forty: - if ID == 1 { - goto Fifty - } - AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I) - AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R) - if KODE == 1 { - return - } - tmp = cmplx.Sqrt(complex(ZR, ZI)) - STR = real(tmp) - STI = imag(tmp) - ZTAR = TTH * (ZR*STR - ZI*STI) - ZTAI = TTH * (ZR*STI + ZI*STR) - tmp = cmplx.Exp(complex(ZTAR, ZTAI)) - STR = real(tmp) - STI = imag(tmp) - PTR = AIR*STR - AII*STI - AII = AIR*STI + AII*STR - AIR = PTR - return - -Fifty: - AIR = -S2R * C2 - AII = -S2I * C2 - if AZ <= TOL { - goto Sixty - } - STR = ZR*S1R - ZI*S1I - STI = ZR*S1I + ZI*S1R - CC = C1 / (1.0e0 + FID) - AIR = AIR + CC*(STR*ZR-STI*ZI) - AII = AII + CC*(STR*ZI+STI*ZR) - -Sixty: - if KODE == 1 { - return - } - tmp = cmplx.Sqrt(complex(ZR, ZI)) - STR = real(tmp) - STI = imag(tmp) - ZTAR = TTH * (ZR*STR - ZI*STI) - ZTAI = TTH * (ZR*STI + ZI*STR) - tmp = cmplx.Exp(complex(ZTAR, ZTAI)) - STR = real(tmp) - STI = imag(tmp) - PTR = STR*AIR - STI*AII - AII = STR*AII + STI*AIR - AIR = PTR - return - - // CASE FOR CABS(Z)>1.0. -Seventy: - FNU = (1.0e0 + FID) / 3.0e0 - - /* - SET PARAMETERS RELATED TO MACHINE CONSTANTS. - TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18. - ELIM IS THE APPROXIMATE EXPONENTIAL OVER-&&UNDERFLOW LIMIT. - EXP(-ELIM)<EXP(-ALIM)=EXP(-ELIM)/TOL AND - EXP(ELIM)>EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR - UNDERFLOW&&OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. - RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LA>=Z. - DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). - */ - K1 = imach[15] - K2 = imach[16] - R1M5 = dmach[5] - - K = min(abs(K1), abs(K2)) - ELIM = 2.303e0 * (float64(K)*R1M5 - 3.0e0) - K1 = imach[14] - 1 - AA = R1M5 * float64(K1) - DIG = math.Min(AA, 18.0e0) - AA = AA * 2.303e0 - ALIM = ELIM + math.Max(-AA, -41.45e0) - RL = 1.2e0*DIG + 3.0e0 - ALAZ = math.Log(AZ) - - // TEST FOR PROPER RANGE. - AA = 0.5e0 / TOL - BB = float64(float32(imach[9])) * 0.5e0 - AA = math.Min(AA, BB) - AA = math.Pow(AA, TTH) - if AZ > AA { - goto TwoSixty - } - AA = math.Sqrt(AA) - if AZ > AA { - IERR = 3 - } - tmp = cmplx.Sqrt(complex(ZR, ZI)) - CSQR = real(tmp) - CSQI = imag(tmp) - ZTAR = TTH * (ZR*CSQR - ZI*CSQI) - ZTAI = TTH * (ZR*CSQI + ZI*CSQR) - - // RE(ZTA)<=0 WHEN RE(Z)<0, ESPECIALLY WHEN IM(Z) IS SMALL. - IFLAG = 0 - SFAC = 1.0e0 - AK = ZTAI - if ZR >= 0.0e0 { - goto Eighty - } - BK = ZTAR - CK = -math.Abs(BK) - ZTAR = CK - ZTAI = AK - -Eighty: - if ZI != 0.0e0 { - goto Ninety - } - if ZR > 0.0e0 { - goto Ninety - } - ZTAR = 0.0e0 - ZTAI = AK -Ninety: - AA = ZTAR - if AA >= 0.0e0 && ZR > 0.0e0 { - goto OneTen - } - if KODE == 2 { - goto OneHundred - } - - // OVERFLOW TEST. - if AA > (-ALIM) { - goto OneHundred - } - AA = -AA + 0.25e0*ALAZ - IFLAG = 1 - SFAC = TOL - if AA > ELIM { - goto TwoSeventy - } - -OneHundred: - // CBKNU AND CACON return EXP(ZTA)*K(FNU,ZTA) ON KODE=2. - MR = 1 - if ZI < 0.0e0 { - MR = -1 - } - _, _, _, _, _, _, CYR, CYI, NN, _, _, _, _ = Zacai(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, RL, TOL, ELIM, ALIM) - if NN < 0 { - goto TwoEighty - } - NZ = NZ + NN - goto OneThirty - -OneTen: - if KODE == 2 { - goto OneTwenty - } - - // UNDERFLOW TEST. - if AA < ALIM { - goto OneTwenty - } - AA = -AA - 0.25e0*ALAZ - IFLAG = 2 - SFAC = 1.0e0 / TOL - if AA < (-ELIM) { - goto TwoTen - } -OneTwenty: - _, _, _, _, _, CYR, CYI, NZ, _, _, _ = Zbknu(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, TOL, ELIM, ALIM) - -OneThirty: - S1R = CYR[1] * COEF - S1I = CYI[1] * COEF - if IFLAG != 0 { - goto OneFifty - } - if ID == 1 { - goto OneFourty - } - AIR = CSQR*S1R - CSQI*S1I - AII = CSQR*S1I + CSQI*S1R - return -OneFourty: - AIR = -(ZR*S1R - ZI*S1I) - AII = -(ZR*S1I + ZI*S1R) - return -OneFifty: - S1R = S1R * SFAC - S1I = S1I * SFAC - if ID == 1 { - goto OneSixty - } - STR = S1R*CSQR - S1I*CSQI - S1I = S1R*CSQI + S1I*CSQR - S1R = STR - AIR = S1R / SFAC - AII = S1I / SFAC - return -OneSixty: - STR = -(S1R*ZR - S1I*ZI) - S1I = -(S1R*ZI + S1I*ZR) - S1R = STR - AIR = S1R / SFAC - AII = S1I / SFAC - return -OneSeventy: - AA = 1.0e+3 * dmach[1] - S1R = ZEROR - S1I = ZEROI - if ID == 1 { - goto OneNinety - } - if AZ <= AA { - goto OneEighty - } - S1R = C2 * ZR - S1I = C2 * ZI -OneEighty: - AIR = C1 - S1R - AII = -S1I - return -OneNinety: - AIR = -C2 - AII = 0.0e0 - AA = math.Sqrt(AA) - if AZ <= AA { - goto TwoHundred - } - S1R = 0.5e0 * (ZR*ZR - ZI*ZI) - S1I = ZR * ZI -TwoHundred: - AIR = AIR + C1*S1R - AII = AII + C1*S1I - return -TwoTen: - NZ = 1 - AIR = ZEROR - AII = ZEROI - return -TwoSeventy: - NZ = 0 - IERR = 2 - return -TwoEighty: - if NN == (-1) { - goto TwoSeventy - } - NZ = 0 - IERR = 5 - return -TwoSixty: - IERR = 4 - NZ = 0 - return -} - -// sbknu computes the k bessel function in the right half z plane. -func Zbknu(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, TOL, ELIM, ALIM float64) (ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZ int, TOLout, ELIMout, ALIMout float64) { - /* Old dimension comment. - DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2), - * CYI(2) - */ - - // TODO(btracey): Find which of these are inputs/outputs/both and clean up - // the function call. - // YR and YI have length n (but n+1 with better indexing) - var AA, AK, ASCLE, A1, A2, BB, BK, CAZ, - CBI, CBR, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER, - CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CTWOR, - CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ETEST, FC, FHS, - FI, FK, FKS, FMUI, FMUR, FPI, FR, G1, G2, HPI, PI, PR, PTI, - PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI, - RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM, - TTH, T1, T2, ELM, CELMR, ZDR, ZDI, AS, ALAS, HELIM float64 - - var I, IFLAG, INU, K, KFLAG, KK, KMAX, KODED, IDUM, J, IC, INUB, NW int - - var sinh, cosh complex128 - //var sin, cos float64 - - var tmp, p complex128 - var CSSR, CSRR, BRY [4]float64 - var CYR, CYI [3]float64 - - KMAX = 30 - CZEROR = 0 - CZEROI = 0 - CONER = 1 - CONEI = 0 - CTWOR = 2 - R1 = 2 - - DPI = 3.14159265358979324e0 - RTHPI = 1.25331413731550025e0 - SPI = 1.90985931710274403e0 - HPI = 1.57079632679489662e0 - FPI = 1.89769999331517738e0 - TTH = 6.66666666666666666e-01 - - CC := [9]float64{math.NaN(), 5.77215664901532861e-01, -4.20026350340952355e-02, - -4.21977345555443367e-02, 7.21894324666309954e-03, - -2.15241674114950973e-04, -2.01348547807882387e-05, - 1.13302723198169588e-06, 6.11609510448141582e-09} - - CAZ = cmplx.Abs(complex(ZR, ZI)) - CSCLR = 1.0e0 / TOL - CRSCR = TOL - CSSR[1] = CSCLR - CSSR[2] = 1.0e0 - CSSR[3] = CRSCR - CSRR[1] = CRSCR - CSRR[2] = 1.0e0 - CSRR[3] = CSCLR - BRY[1] = 1.0e+3 * dmach[1] / TOL - BRY[2] = 1.0e0 / BRY[1] - BRY[3] = dmach[2] - IFLAG = 0 - KODED = KODE - RCAZ = 1.0e0 / CAZ - STR = ZR * RCAZ - STI = -ZI * RCAZ - RZR = (STR + STR) * RCAZ - RZI = (STI + STI) * RCAZ - INU = int(float32(FNU + 0.5)) - DNU = FNU - float64(INU) - if math.Abs(DNU) == 0.5e0 { - goto OneTen - } - DNU2 = 0.0e0 - if math.Abs(DNU) > TOL { - DNU2 = DNU * DNU - } - if CAZ > R1 { - goto OneTen - } - - // SERIES FOR CABS(Z)<=R1. - FC = 1.0e0 - tmp = cmplx.Log(complex(RZR, RZI)) - SMUR = real(tmp) - SMUI = imag(tmp) - FMUR = SMUR * DNU - FMUI = SMUI * DNU - tmp = complex(FMUR, FMUI) - sinh = cmplx.Sinh(tmp) - cosh = cmplx.Cosh(tmp) - CSHR = real(sinh) - CSHI = imag(sinh) - CCHR = real(cosh) - CCHI = imag(cosh) - if DNU == 0.0e0 { - goto Ten - } - FC = DNU * DPI - FC = FC / math.Sin(FC) - SMUR = CSHR / DNU - SMUI = CSHI / DNU -Ten: - A2 = 1.0e0 + DNU - - // GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU). - T2 = math.Exp(-dgamln(A2, IDUM)) - T1 = 1.0e0 / (T2 * FC) - if math.Abs(DNU) > 0.1e0 { - goto Forty - } - - // SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU). - AK = 1.0e0 - S = CC[1] - for K = 2; K <= 8; K++ { - AK = AK * DNU2 - TM = CC[K] * AK - S = S + TM - if math.Abs(TM) < TOL { - goto Thirty - } - } -Thirty: - G1 = -S - goto Fifty -Forty: - G1 = (T1 - T2) / (DNU + DNU) -Fifty: - G2 = (T1 + T2) * 0.5e0 - FR = FC * (CCHR*G1 + SMUR*G2) - FI = FC * (CCHI*G1 + SMUI*G2) - tmp = cmplx.Exp(complex(FMUR, FMUI)) - STR = real(tmp) - STI = imag(tmp) - PR = 0.5e0 * STR / T2 - PI = 0.5e0 * STI / T2 - tmp = complex(0.5, 0) / complex(STR, STI) - PTR = real(tmp) - PTI = imag(tmp) - QR = PTR / T1 - QI = PTI / T1 - S1R = FR - S1I = FI - S2R = PR - S2I = PI - AK = 1.0e0 - A1 = 1.0e0 - CKR = CONER - CKI = CONEI - BK = 1.0e0 - DNU2 - if INU > 0 || N > 1 { - goto Eighty - } - - // GENERATE K(FNU,Z), 0.0E0 <= FNU < 0.5E0 AND N=1. - if CAZ < TOL { - goto Seventy - } - tmp = complex(ZR, ZI) * complex(ZR, ZI) - CZR = real(tmp) - CZI = imag(tmp) - CZR = 0.25e0 * CZR - CZI = 0.25e0 * CZI - T1 = 0.25e0 * CAZ * CAZ -Sixty: - FR = (FR*AK + PR + QR) / BK - FI = (FI*AK + PI + QI) / BK - STR = 1.0e0 / (AK - DNU) - PR = PR * STR - PI = PI * STR - STR = 1.0e0 / (AK + DNU) - QR = QR * STR - QI = QI * STR - STR = CKR*CZR - CKI*CZI - RAK = 1.0e0 / AK - CKI = (CKR*CZI + CKI*CZR) * RAK - CKR = STR * RAK - S1R = CKR*FR - CKI*FI + S1R - S1I = CKR*FI + CKI*FR + S1I - A1 = A1 * T1 * RAK - BK = BK + AK + AK + 1.0e0 - AK = AK + 1.0e0 - if A1 > TOL { - goto Sixty - } -Seventy: - YR[1] = S1R - YI[1] = S1I - if KODED == 1 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - } - tmp = cmplx.Exp(complex(ZR, ZI)) - STR = real(tmp) - STI = imag(tmp) - tmp = complex(S1R, S1I) * complex(STR, STI) - YR[1] = real(tmp) - YI[1] = imag(tmp) - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - - // GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE. -Eighty: - if CAZ < TOL { - goto OneHundred - } - tmp = complex(ZR, ZI) * complex(ZR, ZI) - CZR = real(tmp) - CZI = imag(tmp) - CZR = 0.25e0 * CZR - CZI = 0.25e0 * CZI - T1 = 0.25e0 * CAZ * CAZ -Ninety: - FR = (FR*AK + PR + QR) / BK - FI = (FI*AK + PI + QI) / BK - STR = 1.0e0 / (AK - DNU) - PR = PR * STR - PI = PI * STR - STR = 1.0e0 / (AK + DNU) - QR = QR * STR - QI = QI * STR - STR = CKR*CZR - CKI*CZI - RAK = 1.0e0 / AK - CKI = (CKR*CZI + CKI*CZR) * RAK - CKR = STR * RAK - S1R = CKR*FR - CKI*FI + S1R - S1I = CKR*FI + CKI*FR + S1I - STR = PR - FR*AK - STI = PI - FI*AK - S2R = CKR*STR - CKI*STI + S2R - S2I = CKR*STI + CKI*STR + S2I - A1 = A1 * T1 * RAK - BK = BK + AK + AK + 1.0e0 - AK = AK + 1.0e0 - if A1 > TOL { - goto Ninety - } -OneHundred: - KFLAG = 2 - A1 = FNU + 1.0e0 - AK = A1 * math.Abs(SMUR) - if AK > ALIM { - KFLAG = 3 - } - STR = CSSR[KFLAG] - P2R = S2R * STR - P2I = S2I * STR - tmp = complex(P2R, P2I) * complex(RZR, RZI) - S2R = real(tmp) - S2I = imag(tmp) - S1R = S1R * STR - S1I = S1I * STR - if KODED == 1 { - goto TwoTen - } - tmp = cmplx.Exp(complex(ZR, ZI)) - FR = real(tmp) - FI = imag(tmp) - tmp = complex(S1R, S1I) * complex(FR, FI) - S1R = real(tmp) - S1I = imag(tmp) - tmp = complex(S2R, S2I) * complex(FR, FI) - S2R = real(tmp) - S2I = imag(tmp) - goto TwoTen - - // IFLAG=0 MEANS NO UNDERFLOW OCCURRED - // IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH - // KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD RECURSION -OneTen: - tmp = cmplx.Sqrt(complex(ZR, ZI)) - STR = real(tmp) - STI = imag(tmp) - tmp = complex(RTHPI, CZEROI) / complex(STR, STI) - COEFR = real(tmp) - COEFI = imag(tmp) - KFLAG = 2 - if KODED == 2 { - goto OneTwenty - } - if ZR > ALIM { - goto TwoNinety - } - - STR = math.Exp(-ZR) * CSSR[KFLAG] - //sin, cos = math.Sincos(ZI) - STI = -STR * math.Sin(ZI) - STR = STR * math.Cos(ZI) - tmp = complex(COEFR, COEFI) * complex(STR, STI) - COEFR = real(tmp) - COEFI = imag(tmp) -OneTwenty: - if math.Abs(DNU) == 0.5e0 { - goto ThreeHundred - } - // MILLER ALGORITHM FOR CABS(Z)>R1. - AK = math.Cos(DPI * DNU) - AK = math.Abs(AK) - if AK == CZEROR { - goto ThreeHundred - } - FHS = math.Abs(0.25e0 - DNU2) - if FHS == CZEROR { - goto ThreeHundred - } - - // COMPUTE R2=F(E). if CABS(Z)>=R2, USE FORWARD RECURRENCE TO - // DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON - // 12<=E<=60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))= - // TOL WHERE B IS THE BASE OF THE ARITHMETIC. - T1 = float64(imach[14] - 1) - T1 = T1 * dmach[5] * 3.321928094e0 - T1 = math.Max(T1, 12.0e0) - T1 = math.Min(T1, 60.0e0) - T2 = TTH*T1 - 6.0e0 - if ZR != 0.0e0 { - goto OneThirty - } - T1 = HPI - goto OneFourty -OneThirty: - T1 = math.Atan(ZI / ZR) - T1 = math.Abs(T1) -OneFourty: - if T2 > CAZ { - goto OneSeventy - } - // FORWARD RECURRENCE LOOP WHEN CABS(Z)>=R2. - ETEST = AK / (DPI * CAZ * TOL) - FK = CONER - if ETEST < CONER { - goto OneEighty - } - FKS = CTWOR - CKR = CAZ + CAZ + CTWOR - P1R = CZEROR - P2R = CONER - for I = 1; I <= KMAX; I++ { - AK = FHS / FKS - CBR = CKR / (FK + CONER) - PTR = P2R - P2R = CBR*P2R - P1R*AK - P1R = PTR - CKR = CKR + CTWOR - FKS = FKS + FK + FK + CTWOR - FHS = FHS + FK + FK - FK = FK + CONER - STR = math.Abs(P2R) * FK - if ETEST < STR { - goto OneSixty - } - } - goto ThreeTen -OneSixty: - FK = FK + SPI*T1*math.Sqrt(T2/CAZ) - FHS = math.Abs(0.25 - DNU2) - goto OneEighty -OneSeventy: - // COMPUTE BACKWARD INDEX K FOR CABS(Z)<R2. - A2 = math.Sqrt(CAZ) - AK = FPI * AK / (TOL * math.Sqrt(A2)) - AA = 3.0e0 * T1 / (1.0e0 + CAZ) - BB = 14.7e0 * T1 / (28.0e0 + CAZ) - AK = (math.Log(AK) + CAZ*math.Cos(AA)/(1.0e0+0.008e0*CAZ)) / math.Cos(BB) - FK = 0.12125e0*AK*AK/CAZ + 1.5e0 -OneEighty: - // BACKWARD RECURRENCE LOOP FOR MILLER ALGORITHM. - K = int(float32(FK)) - FK = float64(K) - FKS = FK * FK - P1R = CZEROR - P1I = CZEROI - P2R = TOL - P2I = CZEROI - CSR = P2R - CSI = P2I - for I = 1; I <= K; I++ { - A1 = FKS - FK - AK = (FKS + FK) / (A1 + FHS) - RAK = 2.0e0 / (FK + CONER) - CBR = (FK + ZR) * RAK - CBI = ZI * RAK - PTR = P2R - PTI = P2I - P2R = (PTR*CBR - PTI*CBI - P1R) * AK - P2I = (PTI*CBR + PTR*CBI - P1I) * AK - P1R = PTR - P1I = PTI - CSR = CSR + P2R - CSI = CSI + P2I - FKS = A1 - FK + CONER - FK = FK - CONER - } - // COMPUTE (P2/CS)=(P2/CABS(CS))*(CONJG(CS)/CABS(CS)) FOR BETTER SCALING. - TM = cmplx.Abs(complex(CSR, CSI)) - PTR = 1.0e0 / TM - S1R = P2R * PTR - S1I = P2I * PTR - CSR = CSR * PTR - CSI = -CSI * PTR - tmp = complex(COEFR, COEFI) * complex(S1R, S1I) - STR = real(tmp) - STI = imag(tmp) - tmp = complex(STR, STI) * complex(CSR, CSI) - S1R = real(tmp) - S1I = imag(tmp) - if INU > 0 || N > 1 { - goto TwoHundred - } - ZDR = ZR - ZDI = ZI - if IFLAG == 1 { - goto TwoSeventy - } - goto TwoFourty -TwoHundred: - // COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING. - TM = cmplx.Abs(complex(P2R, P2I)) - PTR = 1.0e0 / TM - P1R = P1R * PTR - P1I = P1I * PTR - P2R = P2R * PTR - P2I = -P2I * PTR - tmp = complex(P1R, P1I) * complex(P2R, P2I) - PTR = real(tmp) - PTI = imag(tmp) - STR = DNU + 0.5e0 - PTR - STI = -PTI - tmp = complex(STR, STI) / complex(ZR, ZI) - STR = real(tmp) - STI = imag(tmp) - STR = STR + 1.0e0 - tmp = complex(STR, STI) * complex(S1R, S1I) - S2R = real(tmp) - S2I = imag(tmp) - - // FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH - // SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3 -TwoTen: - STR = DNU + 1.0e0 - CKR = STR * RZR - CKI = STR * RZI - if N == 1 { - INU = INU - 1 - } - if INU > 0 { - goto TwoTwenty - } - if N > 1 { - goto TwoFifteen - } - S1R = S2R - S1I = S2I -TwoFifteen: - ZDR = ZR - ZDI = ZI - if IFLAG == 1 { - goto TwoSeventy - } - goto TwoFourty -TwoTwenty: - INUB = 1 - if IFLAG == 1 { - goto TwoSixtyOne - } -TwoTwentyFive: - P1R = CSRR[KFLAG] - ASCLE = BRY[KFLAG] - for I = INUB; I <= INU; I++ { - STR = S2R - STI = S2I - S2R = CKR*STR - CKI*STI + S1R - S2I = CKR*STI + CKI*STR + S1I - S1R = STR - S1I = STI - CKR = CKR + RZR - CKI = CKI + RZI - if KFLAG >= 3 { - continue - } - P2R = S2R * P1R - P2I = S2I * P1R - STR = math.Abs(P2R) - STI = math.Abs(P2I) - P2M = math.Max(STR, STI) - if P2M <= ASCLE { - continue - } - KFLAG = KFLAG + 1 - ASCLE = BRY[KFLAG] - S1R = S1R * P1R - S1I = S1I * P1R - S2R = P2R - S2I = P2I - STR = CSSR[KFLAG] - S1R = S1R * STR - S1I = S1I * STR - S2R = S2R * STR - S2I = S2I * STR - P1R = CSRR[KFLAG] - } - if N != 1 { - goto TwoFourty - } - S1R = S2R - S1I = S2I -TwoFourty: - STR = CSRR[KFLAG] - YR[1] = S1R * STR - YI[1] = S1I * STR - if N == 1 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - } - YR[2] = S2R * STR - YI[2] = S2I * STR - if N == 2 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - } - KK = 2 -TwoFifty: - KK = KK + 1 - if KK > N { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - } - P1R = CSRR[KFLAG] - ASCLE = BRY[KFLAG] - for I = KK; I <= N; I++ { - P2R = S2R - P2I = S2I - S2R = CKR*P2R - CKI*P2I + S1R - S2I = CKI*P2R + CKR*P2I + S1I - S1R = P2R - S1I = P2I - CKR = CKR + RZR - CKI = CKI + RZI - P2R = S2R * P1R - P2I = S2I * P1R - YR[I] = P2R - YI[I] = P2I - if KFLAG >= 3 { - continue - } - STR = math.Abs(P2R) - STI = math.Abs(P2I) - P2M = math.Max(STR, STI) - if P2M <= ASCLE { - continue - } - KFLAG = KFLAG + 1 - ASCLE = BRY[KFLAG] - S1R = S1R * P1R - S1I = S1I * P1R - S2R = P2R - S2I = P2I - STR = CSSR[KFLAG] - S1R = S1R * STR - S1I = S1I * STR - S2R = S2R * STR - S2I = S2I * STR - P1R = CSRR[KFLAG] - } - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - - // IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW. -TwoSixtyOne: - HELIM = 0.5e0 * ELIM - ELM = math.Exp(-ELIM) - CELMR = ELM - ASCLE = BRY[1] - ZDR = ZR - ZDI = ZI - IC = -1 - J = 2 - for I = 1; I <= INU; I++ { - STR = S2R - STI = S2I - S2R = STR*CKR - STI*CKI + S1R - S2I = STI*CKR + STR*CKI + S1I - S1R = STR - S1I = STI - CKR = CKR + RZR - CKI = CKI + RZI - AS = cmplx.Abs(complex(S2R, S2I)) - ALAS = math.Log(AS) - P2R = -ZDR + ALAS - if P2R < (-ELIM) { - goto TwoSixtyThree - } - tmp = cmplx.Log(complex(S2R, S2I)) - STR = real(tmp) - STI = imag(tmp) - P2R = -ZDR + STR - P2I = -ZDI + STI - P2M = math.Exp(P2R) / TOL - // sin, cos = math.Sincos(P2I) - P1R = P2M * math.Cos(P2I) - P1I = P2M * math.Sin(P2I) - p = complex(P1R, P1I) - NW = Zuchk(p, ASCLE, TOL) - if NW != 0 { - goto TwoSixtyThree - } - J = 3 - J - CYR[J] = P1R - CYI[J] = P1I - if IC == (I - 1) { - goto TwoSixtyFour - } - IC = I - continue - TwoSixtyThree: - if ALAS < HELIM { - continue - } - ZDR = ZDR - ELIM - S1R = S1R * CELMR - S1I = S1I * CELMR - S2R = S2R * CELMR - S2I = S2I * CELMR - } - if N != 1 { - goto TwoSeventy - } - S1R = S2R - S1I = S2I - goto TwoSeventy -TwoSixtyFour: - KFLAG = 1 - INUB = I + 1 - S2R = CYR[J] - S2I = CYI[J] - J = 3 - J - S1R = CYR[J] - S1I = CYI[J] - if INUB <= INU { - goto TwoTwentyFive - } - if N != 1 { - goto TwoFourty - } - S1R = S2R - S1I = S2I - goto TwoFourty -TwoSeventy: - YR[1] = S1R - YI[1] = S1I - if N == 1 { - goto TwoEighty - } - YR[2] = S2R - YI[2] = S2I -TwoEighty: - ASCLE = BRY[1] - _, _, FNU, N, YR, YI, NZ, RZR, RZI, _, TOL, ELIM = Zkscl(ZDR, ZDI, FNU, N, YR, YI, RZR, RZI, ASCLE, TOL, ELIM) - INU = N - NZ - if INU <= 0 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - } - KK = NZ + 1 - S1R = YR[KK] - S1I = YI[KK] - YR[KK] = S1R * CSRR[1] - YI[KK] = S1I * CSRR[1] - if INU == 1 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - } - KK = NZ + 2 - S2R = YR[KK] - S2I = YI[KK] - YR[KK] = S2R * CSRR[1] - YI[KK] = S2I * CSRR[1] - if INU == 2 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM - } - T2 = FNU + float64(float32(KK-1)) - CKR = T2 * RZR - CKI = T2 * RZI - KFLAG = 1 - goto TwoFifty -TwoNinety: - - // SCALE BY math.Exp(Z), IFLAG = 1 CASES. - - IFLAG = 1 - KFLAG = 2 - goto OneTwenty - - // FNU=HALF ODD INTEGER CASE, DNU=-0.5 -ThreeHundred: - S1R = COEFR - S1I = COEFI - S2R = COEFR - S2I = COEFI - goto TwoTen - -ThreeTen: - NZ = -2 - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM -} - -// SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE -// ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN -// return WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL. -func Zkscl(ZRR, ZRI, FNU float64, N int, YR, YI []float64, RZR, RZI, ASCLE, TOL, ELIM float64) ( - ZRRout, ZRIout, FNUout float64, Nout int, YRout, YIout []float64, NZ int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) { - var ACS, AS, CKI, CKR, CSI, CSR, FN, STR, S1I, S1R, S2I, - S2R, ZEROI, ZEROR, ZDR, ZDI, CELMR, ELM, HELIM, ALAS float64 - - var I, IC, KK, NN, NW int - var tmp, c complex128 - var CYR, CYI [3]float64 - var sin, cos float64 - - // DIMENSION YR(N), YI(N), CYR(2), CYI(2) - ZEROR = 0 - ZEROI = 0 - IC = 0 - NN = min(2, N) - for I = 1; I <= NN; I++ { - S1R = YR[I] - S1I = YI[I] - CYR[I] = S1R - CYI[I] = S1I - AS = cmplx.Abs(complex(S1R, S1I)) - ACS = -ZRR + math.Log(AS) - NZ = NZ + 1 - YR[I] = ZEROR - YI[I] = ZEROI - if ACS < (-ELIM) { - continue - } - - tmp = cmplx.Log(complex(S1R, S1I)) - CSR = real(tmp) - CSI = imag(tmp) - CSR = CSR - ZRR - CSI = CSI - ZRI - STR = math.Exp(CSR) / TOL - // sin, cos = math.Sincos(CSI) - CSR = STR * math.Cos(CSI) - CSI = STR * math.Sin(CSI) - c = complex(CSR, CSI) - NW = Zuchk(c, ASCLE, TOL) - if NW != 0 { - continue - } - YR[I] = CSR - YI[I] = CSI - IC = I - NZ = NZ - 1 - } - if N == 1 { - return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM - } - if IC > 1 { - goto Twenty - } - YR[1] = ZEROR - YI[1] = ZEROI - NZ = 2 -Twenty: - if N == 2 { - return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM - } - if NZ == 0 { - return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM - } - FN = FNU + 1.0e0 - CKR = FN * RZR - CKI = FN * RZI - S1R = CYR[1] - S1I = CYI[1] - S2R = CYR[2] - S2I = CYI[2] - HELIM = 0.5e0 * ELIM - ELM = math.Exp(-ELIM) - CELMR = ELM - ZDR = ZRR - ZDI = ZRI - - // FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF - // S2 GETS LARGER THAN EXP(ELIM/2) - for I = 3; I <= N; I++ { - KK = I - CSR = S2R - CSI = S2I - S2R = CKR*CSR - CKI*CSI + S1R - S2I = CKI*CSR + CKR*CSI + S1I - S1R = CSR - S1I = CSI - CKR = CKR + RZR - CKI = CKI + RZI - AS = cmplx.Abs(complex(S2R, S2I)) - ALAS = math.Log(AS) - ACS = -ZDR + ALAS - NZ = NZ + 1 - YR[I] = ZEROR - YI[I] = ZEROI - if ACS < (-ELIM) { - goto TwentyFive - } - tmp = cmplx.Log(complex(S2R, S2I)) - CSR = real(tmp) - CSI = imag(tmp) - CSR = CSR - ZDR - CSI = CSI - ZDI - STR = math.Exp(CSR) / TOL - sin, cos = math.Sincos(CSI) - CSR = STR * cos - CSI = STR * sin - c = complex(CSR, CSI) - NW = Zuchk(c, ASCLE, TOL) - if NW != 0 { - goto TwentyFive - } - YR[I] = CSR - YI[I] = CSI - NZ = NZ - 1 - if IC == KK-1 { - goto Forty - } - IC = KK - continue - TwentyFive: - if ALAS < HELIM { - continue - } - ZDR = ZDR - ELIM - S1R = S1R * CELMR - S1I = S1I * CELMR - S2R = S2R * CELMR - S2I = S2I * CELMR - } - NZ = N - if IC == N { - NZ = N - 1 - } - goto FourtyFive -Forty: - NZ = KK - 2 -FourtyFive: - for I = 1; I <= NZ; I++ { - YR[I] = ZEROR - YI[I] = ZEROI - } - return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM -} - -// Zuchk tests whether the magnitude of the real or imaginary part would -// underflow when y is scaled by tol. -// -// y enters as a scaled quantity whose magnitude is greater than -// -// 1e3 + 3*dmach(1)/tol -// -// y is accepted if the underflow is at least one precision below the magnitude -// of the largest component. Otherwise an underflow is assumed as the phase angle -// does not have sufficient accuracy. -func Zuchk(y complex128, scale, tol float64) int { - absR := math.Abs(real(y)) - absI := math.Abs(imag(y)) - minAbs := math.Min(absR, absI) - if minAbs > scale { - return 0 - } - maxAbs := math.Max(absR, absI) - minAbs /= tol - if maxAbs < minAbs { - return 1 - } - return 0 -} - -// ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA -// -// K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) -// MP=PI*MR*CMPLX(0.0,1.0) -// -// TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT -// HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1. -// ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND -// RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT if ZACON -// IS CALLED FROM ZAIRY. -func Zacai(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, RL, TOL, ELIM, ALIM float64) ( - ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZ int, RLout, TOLout, ELIMout, ALIMout float64) { - var ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR, - CSPNI, C1R, C1I, C2R, C2I, DFNU, FMR, PI, - SGN, YY, ZNR, ZNI float64 - var INU, IUF, NN, NW int - var zn, c1, c2, z complex128 - var y []complex128 - //var sin, cos float64 - - CYR := []float64{math.NaN(), 0, 0} - CYI := []float64{math.NaN(), 0, 0} - - PI = math.Pi - ZNR = -ZR - ZNI = -ZI - AZ = cmplx.Abs(complex(ZR, ZI)) - NN = N - DFNU = FNU + float64(float32(N-1)) - if AZ <= 2.0e0 { - goto Ten - } - if AZ*AZ*0.25 > DFNU+1.0e0 { - goto Twenty - } -Ten: - // POWER SERIES FOR THE I FUNCTION. - z = complex(ZNR, ZNI) - y = make([]complex128, len(YR)) - for i, v := range YR { - y[i] = complex(v, YI[i]) - } - Zseri(z, FNU, KODE, NN, y[1:], TOL, ELIM, ALIM) - for i, v := range y { - YR[i] = real(v) - YI[i] = imag(v) - } - goto Forty -Twenty: - if AZ < RL { - goto Thirty - } - // ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION. - ZNR, ZNI, FNU, KODE, _, YR, YI, NW, RL, TOL, ELIM, ALIM = Zasyi(ZNR, ZNI, FNU, KODE, NN, YR, YI, RL, TOL, ELIM, ALIM) - if NW < 0 { - goto Eighty - } - goto Forty -Thirty: - // MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION - ZNR, ZNI, FNU, KODE, _, YR, YI, NW, TOL = Zmlri(ZNR, ZNI, FNU, KODE, NN, YR, YI, TOL) - if NW < 0 { - goto Eighty - } -Forty: - // ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION. - ZNR, ZNI, FNU, KODE, _, CYR, CYI, NW, TOL, ELIM, ALIM = Zbknu(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, TOL, ELIM, ALIM) - if NW != 0 { - goto Eighty - } - FMR = float64(float32(MR)) - SGN = -math.Copysign(PI, FMR) - CSGNR = 0.0e0 - CSGNI = SGN - if KODE == 1 { - goto Fifty - } - YY = -ZNI - //sin, cos = math.Sincos(YY) - CSGNR = -CSGNI * math.Sin(YY) - CSGNI = CSGNI * math.Cos(YY) -Fifty: - // CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE - // WHEN FNU IS LARGE - INU = int(float32(FNU)) - ARG = (FNU - float64(float32(INU))) * SGN - //sin, cos = math.Sincos(ARG) - CSPNR = math.Cos(ARG) - CSPNI = math.Sin(ARG) - if INU%2 == 0 { - goto Sixty - } - CSPNR = -CSPNR - CSPNI = -CSPNI -Sixty: - C1R = CYR[1] - C1I = CYI[1] - C2R = YR[1] - C2I = YI[1] - if KODE == 1 { - goto Seventy - } - IUF = 0 - ASCLE = 1.0e+3 * dmach[1] / TOL - zn = complex(ZNR, ZNI) - c1 = complex(C1R, C1I) - c2 = complex(C2R, C2I) - c1, c2, NW, _ = Zs1s2(zn, c1, c2, ASCLE, ALIM, IUF) - C1R = real(c1) - C1I = imag(c1) - C2R = real(c2) - C2I = imag(c2) - NZ = NZ + NW -Seventy: - YR[1] = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I - YI[1] = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R - return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM -Eighty: - NZ = -1 - if NW == -2 { - NZ = -2 - } - return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM -} - -// ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY -// MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE -// REGION CABS(Z)>MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL return. -// NZ<0 INDICATES AN OVERFLOW ON KODE=1. -func Zasyi(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, RL, TOL, ELIM, ALIM float64) ( - ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZ int, RLout, TOLout, ELIMout, ALIMout float64) { - var AA, AEZ, AK, AK1I, AK1R, ARG, ARM, ATOL, - AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI, - CZR, DFNU, DKI, DKR, DNU2, EZI, EZR, FDN, PI, P1I, - P1R, RAZ, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I, - S2R, TZI, TZR, ZEROI, ZEROR float64 - - var I, IB, IL, INU, J, JL, K, KODED, M, NN int - var tmp complex128 - // var sin, cos float64 - - PI = math.Pi - RTPI = 0.159154943091895336e0 - ZEROR = 0 - ZEROI = 0 - CONER = 1 - CONEI = 0 - - AZ = cmplx.Abs(complex(ZR, ZI)) - ARM = 1.0e3 * dmach[1] - RTR1 = math.Sqrt(ARM) - IL = min(2, N) - DFNU = FNU + float64(float32(N-IL)) - - // OVERFLOW TEST - RAZ = 1.0e0 / AZ - STR = ZR * RAZ - STI = -ZI * RAZ - AK1R = RTPI * STR * RAZ - AK1I = RTPI * STI * RAZ - tmp = cmplx.Sqrt(complex(AK1R, AK1I)) - AK1R = real(tmp) - AK1I = imag(tmp) - CZR = ZR - CZI = ZI - if KODE != 2 { - goto Ten - } - CZR = ZEROR - CZI = ZI -Ten: - if math.Abs(CZR) > ELIM { - goto OneHundred - } - DNU2 = DFNU + DFNU - KODED = 1 - if (math.Abs(CZR) > ALIM) && (N > 2) { - goto Twenty - } - KODED = 0 - tmp = cmplx.Exp(complex(CZR, CZI)) - STR = real(tmp) - STI = imag(tmp) - tmp = complex(AK1R, AK1I) * complex(STR, STI) - AK1R = real(tmp) - AK1I = imag(tmp) -Twenty: - FDN = 0.0e0 - if DNU2 > RTR1 { - FDN = DNU2 * DNU2 - } - EZR = ZR * 8.0e0 - EZI = ZI * 8.0e0 - - // WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE - // FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE - // EXPANSION FOR THE IMAGINARY PART. - AEZ = 8.0e0 * AZ - S = TOL / AEZ - JL = int(float32(RL+RL)) + 2 - P1R = ZEROR - P1I = ZEROI - if ZI == 0.0e0 { - goto Thirty - } - - // CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF - // SIGNIFICANCE WHEN FNU OR N IS LARGE - INU = int(float32(FNU)) - ARG = (FNU - float64(float32(INU))) * PI - INU = INU + N - IL - //sin, cos = math.Sincos(ARG) - AK = -math.Sin(ARG) - BK = math.Cos(ARG) - if ZI < 0.0e0 { - BK = -BK - } - P1R = AK - P1I = BK - if INU%2 == 0 { - goto Thirty - } - P1R = -P1R - P1I = -P1I -Thirty: - for K = 1; K <= IL; K++ { - SQK = FDN - 1.0e0 - ATOL = S * math.Abs(SQK) - SGN = 1.0e0 - CS1R = CONER - CS1I = CONEI - CS2R = CONER - CS2I = CONEI - CKR = CONER - CKI = CONEI - AK = 0.0e0 - AA = 1.0e0 - BB = AEZ - DKR = EZR - DKI = EZI - // TODO(btracey): This loop is executed tens of thousands of times. Why? - // is that really necessary? - for J = 1; J <= JL; J++ { - tmp = complex(CKR, CKI) / complex(DKR, DKI) - STR = real(tmp) - STI = imag(tmp) - CKR = STR * SQK - CKI = STI * SQK - CS2R = CS2R + CKR - CS2I = CS2I + CKI - SGN = -SGN - CS1R = CS1R + CKR*SGN - CS1I = CS1I + CKI*SGN - DKR = DKR + EZR - DKI = DKI + EZI - AA = AA * math.Abs(SQK) / BB - BB = BB + AEZ - AK = AK + 8.0e0 - SQK = SQK - AK - if AA <= ATOL { - goto Fifty - } - } - goto OneTen - Fifty: - S2R = CS1R - S2I = CS1I - if ZR+ZR >= ELIM { - goto Sixty - } - TZR = ZR + ZR - TZI = ZI + ZI - tmp = cmplx.Exp(complex(-TZR, -TZI)) - STR = real(tmp) - STI = imag(tmp) - tmp = complex(STR, STI) * complex(P1R, P1I) - STR = real(tmp) - STI = imag(tmp) - tmp = complex(STR, STI) * complex(CS2R, CS2I) - STR = real(tmp) - STI = imag(tmp) - S2R = S2R + STR - S2I = S2I + STI - Sixty: - FDN = FDN + 8.0e0*DFNU + 4.0e0 - P1R = -P1R - P1I = -P1I - M = N - IL + K - YR[M] = S2R*AK1R - S2I*AK1I - YI[M] = S2R*AK1I + S2I*AK1R - } - if N <= 2 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM - } - NN = N - K = NN - 2 - AK = float64(float32(K)) - STR = ZR * RAZ - STI = -ZI * RAZ - RZR = (STR + STR) * RAZ - RZI = (STI + STI) * RAZ - IB = 3 - for I = IB; I <= NN; I++ { - YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2] - YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2] - AK = AK - 1.0e0 - K = K - 1 - } - if KODED == 0 { - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM - } - tmp = cmplx.Exp(complex(CZR, CZI)) - CKR = real(tmp) - CKI = imag(tmp) - for I = 1; I <= NN; I++ { - STR = YR[I]*CKR - YI[I]*CKI - YI[I] = YR[I]*CKI + YI[I]*CKR - YR[I] = STR - } - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM -OneHundred: - NZ = -1 - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM -OneTen: - NZ = -2 - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM -} - -// ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z)>=0.0 BY THE -// MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES. -func Zmlri(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, TOL float64) ( - ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZ int, TOLout float64) { - var ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI, - CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, PTI, PTR, P1I, - P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI, - SUMR, TFNF, TST, ZEROI, ZEROR float64 - var I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, M int - var tmp complex128 - ZEROR = 0 - ZEROI = 0 - CONER = 1 - CONEI = 0 - - SCLE = dmach[1] / TOL - AZ = cmplx.Abs(complex(ZR, ZI)) - IAZ = int(float32(AZ)) - IFNU = int(float32(FNU)) - INU = IFNU + N - 1 - AT = float64(float32(IAZ)) + 1.0e0 - RAZ = 1.0e0 / AZ - STR = ZR * RAZ - STI = -ZI * RAZ - CKR = STR * AT * RAZ - CKI = STI * AT * RAZ - RZR = (STR + STR) * RAZ - RZI = (STI + STI) * RAZ - P1R = ZEROR - P1I = ZEROI - P2R = CONER - P2I = CONEI - ACK = (AT + 1.0e0) * RAZ - RHO = ACK + math.Sqrt(ACK*ACK-1.0e0) - RHO2 = RHO * RHO - TST = (RHO2 + RHO2) / ((RHO2 - 1.0e0) * (RHO - 1.0e0)) - TST = TST / TOL - - // COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES. - //fmt.Println("before loop", P2R, P2I, CKR, CKI, RZR, RZI, TST, AK) - AK = AT - for I = 1; I <= 80; I++ { - PTR = P2R - PTI = P2I - P2R = P1R - (CKR*PTR - CKI*PTI) - P2I = P1I - (CKI*PTR + CKR*PTI) - P1R = PTR - P1I = PTI - CKR = CKR + RZR - CKI = CKI + RZI - AP = cmplx.Abs(complex(P2R, P2I)) - if AP > TST*AK*AK { - goto Twenty - } - AK = AK + 1.0e0 - } - goto OneTen -Twenty: - I = I + 1 - K = 0 - if INU < IAZ { - goto Forty - } - // COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS. - P1R = ZEROR - P1I = ZEROI - P2R = CONER - P2I = CONEI - AT = float64(float32(INU)) + 1.0e0 - STR = ZR * RAZ - STI = -ZI * RAZ - CKR = STR * AT * RAZ - CKI = STI * AT * RAZ - ACK = AT * RAZ - TST = math.Sqrt(ACK / TOL) - ITIME = 1 - for K = 1; K <= 80; K++ { - PTR = P2R - PTI = P2I - P2R = P1R - (CKR*PTR - CKI*PTI) - P2I = P1I - (CKR*PTI + CKI*PTR) - P1R = PTR - P1I = PTI - CKR = CKR + RZR - CKI = CKI + RZI - AP = cmplx.Abs(complex(P2R, P2I)) - if AP < TST { - continue - } - if ITIME == 2 { - goto Forty - } - ACK = cmplx.Abs(complex(CKR, CKI)) - FLAM = ACK + math.Sqrt(ACK*ACK-1.0e0) - FKAP = AP / cmplx.Abs(complex(P1R, P1I)) - RHO = math.Min(FLAM, FKAP) - TST = TST * math.Sqrt(RHO/(RHO*RHO-1.0e0)) - ITIME = 2 - } - goto OneTen -Forty: - // BACKWARD RECURRENCE AND SUM NORMALIZING RELATION. - K = K + 1 - KK = max(I+IAZ, K+INU) - FKK = float64(float32(KK)) - P1R = ZEROR - P1I = ZEROI - - // SCALE P2 AND SUM BY SCLE. - P2R = SCLE - P2I = ZEROI - FNF = FNU - float64(float32(IFNU)) - TFNF = FNF + FNF - BK = dgamln(FKK+TFNF+1.0e0, IDUM) - dgamln(FKK+1.0e0, IDUM) - dgamln(TFNF+1.0e0, IDUM) - BK = math.Exp(BK) - SUMR = ZEROR - SUMI = ZEROI - KM = KK - INU - for I = 1; I <= KM; I++ { - PTR = P2R - PTI = P2I - P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) - P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) - P1R = PTR - P1I = PTI - AK = 1.0e0 - TFNF/(FKK+TFNF) - ACK = BK * AK - SUMR = SUMR + (ACK+BK)*P1R - SUMI = SUMI + (ACK+BK)*P1I - BK = ACK - FKK = FKK - 1.0e0 - } - YR[N] = P2R - YI[N] = P2I - if N == 1 { - goto Seventy - } - for I = 2; I <= N; I++ { - PTR = P2R - PTI = P2I - P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) - P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) - P1R = PTR - P1I = PTI - AK = 1.0e0 - TFNF/(FKK+TFNF) - ACK = BK * AK - SUMR = SUMR + (ACK+BK)*P1R - SUMI = SUMI + (ACK+BK)*P1I - BK = ACK - FKK = FKK - 1.0e0 - M = N - I + 1 - YR[M] = P2R - YI[M] = P2I - } -Seventy: - if IFNU <= 0 { - goto Ninety - } - for I = 1; I <= IFNU; I++ { - PTR = P2R - PTI = P2I - P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) - P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR) - P1R = PTR - P1I = PTI - AK = 1.0e0 - TFNF/(FKK+TFNF) - ACK = BK * AK - SUMR = SUMR + (ACK+BK)*P1R - SUMI = SUMI + (ACK+BK)*P1I - BK = ACK - FKK = FKK - 1.0e0 - } -Ninety: - PTR = ZR - PTI = ZI - if KODE == 2 { - PTR = ZEROR - } - tmp = cmplx.Log(complex(RZR, RZI)) - STR = real(tmp) - STI = imag(tmp) - P1R = -FNF*STR + PTR - P1I = -FNF*STI + PTI - AP = dgamln(1.0e0+FNF, IDUM) - PTR = P1R - AP - PTI = P1I - - // THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW - // IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES. - P2R = P2R + SUMR - P2I = P2I + SUMI - AP = cmplx.Abs(complex(P2R, P2I)) - P1R = 1.0e0 / AP - tmp = cmplx.Exp(complex(PTR, PTI)) - STR = real(tmp) - STI = imag(tmp) - CKR = STR * P1R - CKI = STI * P1R - PTR = P2R * P1R - PTI = -P2I * P1R - tmp = complex(CKR, CKI) * complex(PTR, PTI) - CNORMR = real(tmp) - CNORMI = imag(tmp) - for I = 1; I <= N; I++ { - STR = YR[I]*CNORMR - YI[I]*CNORMI - YI[I] = YR[I]*CNORMI + YI[I]*CNORMR - YR[I] = STR - } - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL -OneTen: - NZ = -2 - return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL -} - -// Zseri computes the I bessel function for real(z) >= 0 by means of the power -// series for large |z| in the region |z| <= 2*sqrt(fnu+1). -// -// nz = 0 is a normal return. nz > 0 means that the last nz components were set -// to zero due to underflow. nz < 0 means that underflow occurred, but the -// condition |z| <= 2*sqrt(fnu+1) was violated and the computation must be -// completed in another routine with n -= abs(nz). -func Zseri(z complex128, fnu float64, kode, n int, y []complex128, tol, elim, alim float64) (nz int) { - // TODO(btracey): The original fortran line is "ARM = 1.0D+3*D1MACH(1)". Evidently, in Fortran - // this is interpreted as one to the power of +3*D1MACH(1). While it is possible - // this was intentional, it seems unlikely. - arm := 1000 * dmach[1] - az := cmplx.Abs(z) - if az < arm { - for i := 0; i < n; i++ { - y[i] = 0 - } - if fnu == 0 { - y[0] = 1 - n-- - } - if az == 0 { - return 0 - } - return n - } - hz := 0.5 * z - var cz complex128 - var acz float64 - if az > math.Sqrt(arm) { - cz = hz * hz - acz = cmplx.Abs(cz) - } - NN := n - ck := cmplx.Log(hz) - var ak1 complex128 - for { - dfnu := fnu + float64(NN-1) - // Underflow test. - ak1 = ck * complex(dfnu, 0) - ak := dgamln(dfnu+1, 0) - ak1 -= complex(ak, 0) - if kode == 2 { - ak1 -= complex(real(z), 0) - } - if real(ak1) > -elim { - break - } - nz++ - y[NN-1] = 0 - if acz > dfnu { - // Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation - // in cbinu with n = n - abs(nz). - nz *= -1 - return nz - } - NN-- - if NN == 0 { - return nz - } - } - crscr := 1.0 - var flag int - var scale float64 - aa := real(ak1) - if aa <= -alim { - flag = 1 - crscr = tol - scale = arm / tol - aa -= math.Log(tol) - } - var w [2]complex128 - for { - coef := cmplx.Exp(complex(aa, imag(ak1))) - atol := tol * acz / (fnu + float64(NN)) - for i := 0; i < min(2, NN); i++ { - FNUP := fnu + float64(NN-i) - s1 := 1 + 0i - if acz >= tol*FNUP { - ak2 := 1 + 0i - ak := FNUP + 2 - S := FNUP - scl := 2.0 - first := true - for first || scl > atol { - ak2 = ak2 * cz * complex(1/S, 0) - scl *= acz / S - s1 += ak2 - S += ak - ak += 2 - first = false - } - } - s2 := s1 * coef - w[i] = s2 - if flag == 1 { - if Zuchk(s2, scale, tol) != 0 { - var full bool - var dfnu float64 - // This code is similar to the code that exists above. The - // code copying is here because the original Fortran used - // a goto to solve the loop-and-a-half problem. Removing the - // goto makes the behavior of the function and variable scoping - // much clearer, but requires copying this code due to Go's - // goto rules. - for { - if full { - dfnu = fnu + float64(NN-1) - // Underflow test. - ak1 = ck * complex(dfnu, 0) - ak1 -= complex(dgamln(dfnu+1, 0), 0) - if kode == 2 { - ak1 -= complex(real(z), 0) - } - if real(ak1) > -elim { - break - } - } else { - full = true - } - nz++ - y[NN-1] = 0 - if acz > dfnu { - // Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation - // in cbinu with n = n - abs(nz). - nz *= -1 - return nz - } - NN-- - if NN == 0 { - return nz - } - } - continue - } - } - y[NN-i-1] = s2 * complex(crscr, 0) - coef /= hz - coef *= complex(FNUP-1, 0) - } - break - } - if NN <= 2 { - return nz - } - rz := complex(2*real(z)/(az*az), -2*imag(z)/(az*az)) - if flag == 0 { - for i := NN - 3; i >= 0; i-- { - y[i] = complex(float64(i+1)+fnu, 0)*rz*y[i+1] + y[i+2] - } - return nz - } - - // exp(-alim)=exp(-elim)/tol=approximately one digit of precision above the - // underflow limit, which equals scale = dmach[1)*SS*1e3. - s1 := w[0] - s2 := w[1] - for K := NN - 3; K >= 0; K-- { - s1, s2 = s2, s1+complex(float64(K+1)+fnu, 0)*(rz*s2) - ck := s2 * complex(crscr, 0) - y[K] = ck - if cmplx.Abs(ck) > scale { - for ; K >= 0; K-- { - y[K] = complex(float64(K+1)+fnu, 0)*rz*y[K+1] + y[K+2] - } - return nz - } - } - return nz -} - -// Zs1s2 tests for a possible underflow resulting from the addition of the I and -// K functions in the analytic continuation formula where s1 == K function and -// s2 == I function. -// -// When kode == 1, the I and K functions are different orders of magnitude. -// -// When kode == 2, they may both be of the same order of magnitude, but the maximum -// must be at least one precision above the underflow limit. -func Zs1s2(zr, s1, s2 complex128, scale, lim float64, iuf int) (s1o, s2o complex128, nz, iufo int) { - if s1 == 0 || math.Log(cmplx.Abs(s1))-2*real(zr) < -lim { - if cmplx.Abs(s2) > scale { - return 0, s2, 0, iuf - } - return 0, 0, 1, 0 - } - // TODO(btracey): Written like this for numerical rounding reasons. - // Fix once we're sure other changes are correct. - s1 = cmplx.Exp(cmplx.Log(s1) - zr - zr) - if math.Max(cmplx.Abs(s1), cmplx.Abs(s2)) > scale { - return s1, s2, 0, iuf + 1 - } - return 0, 0, 1, 0 -} - -func dgamln(z float64, ierr int) float64 { - //return amoslib.DgamlnFort(z) - // Go implementation. - if z < 0 { - return 0 - } - a2, _ := math.Lgamma(z) - return a2 -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go b/vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go deleted file mode 100644 index 32f96c14..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/amos/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 amos implements functions originally in the Netlib code by Donald Amos. -package amos // import "gonum.org/v1/gonum/mathext/internal/amos" diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/amos/staticcheck.conf b/vendor/gonum.org/v1/gonum/mathext/internal/amos/staticcheck.conf deleted file mode 100644 index e7e254ff..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/amos/staticcheck.conf +++ /dev/null @@ -1 +0,0 @@ -checks = [] diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go deleted file mode 100644 index 20cac067..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/cephes.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright ©2016 The Gonum 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 cephes - -import "math" - -/* -Additional copyright information: - -Code in this package is adapted from the Cephes library (http://www.netlib.org/cephes/). -There is no explicit licence on Netlib, but the author has agreed to a BSD release. -See https://github.com/deepmind/torch-cephes/blob/master/LICENSE.txt and -https://lists.debian.org/debian-legal/2004/12/msg00295.html -*/ - -const ( - paramOutOfBounds = "cephes: parameter out of bounds" - errParamFunctionSingularity = "cephes: function singularity" -) - -const ( - machEp = 1.0 / (1 << 53) - maxLog = 1024 * math.Ln2 - minLog = -1075 * math.Ln2 - maxIter = 2000 -) diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go deleted file mode 100644 index 086c4694..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 cephes implements functions originally in the Netlib code by Stephen Mosher. -package cephes // import "gonum.org/v1/gonum/mathext/internal/cephes" diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go deleted file mode 100644 index 4bc0bd1d..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igam.go +++ /dev/null @@ -1,320 +0,0 @@ -// Derived from SciPy's special/cephes/igam.c and special/cephes/igam.h -// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igam.c -// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igam.h -// Made freely available by Stephen L. Moshier without support or guarantee. - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Copyright ©1985, ©1987 by Stephen L. Moshier -// Portions Copyright ©2016 The Gonum Authors. All rights reserved. - -package cephes - -import "math" - -const ( - igamDimK = 25 - igamDimN = 25 - igam = 1 - igamC = 0 - igamSmall = 20 - igamLarge = 200 - igamSmallRatio = 0.3 - igamLargeRatio = 4.5 -) - -var igamCoefs = [igamDimK][igamDimN]float64{ - {-3.3333333333333333e-1, 8.3333333333333333e-2, -1.4814814814814815e-2, 1.1574074074074074e-3, 3.527336860670194e-4, -1.7875514403292181e-4, 3.9192631785224378e-5, -2.1854485106799922e-6, -1.85406221071516e-6, 8.296711340953086e-7, -1.7665952736826079e-7, 6.7078535434014986e-9, 1.0261809784240308e-8, -4.3820360184533532e-9, 9.1476995822367902e-10, -2.551419399494625e-11, -5.8307721325504251e-11, 2.4361948020667416e-11, -5.0276692801141756e-12, 1.1004392031956135e-13, 3.3717632624009854e-13, -1.3923887224181621e-13, 2.8534893807047443e-14, -5.1391118342425726e-16, -1.9752288294349443e-15}, - {-1.8518518518518519e-3, -3.4722222222222222e-3, 2.6455026455026455e-3, -9.9022633744855967e-4, 2.0576131687242798e-4, -4.0187757201646091e-7, -1.8098550334489978e-5, 7.6491609160811101e-6, -1.6120900894563446e-6, 4.6471278028074343e-9, 1.378633446915721e-7, -5.752545603517705e-8, 1.1951628599778147e-8, -1.7543241719747648e-11, -1.0091543710600413e-9, 4.1627929918425826e-10, -8.5639070264929806e-11, 6.0672151016047586e-14, 7.1624989648114854e-12, -2.9331866437714371e-12, 5.9966963656836887e-13, -2.1671786527323314e-16, -4.9783399723692616e-14, 2.0291628823713425e-14, -4.13125571381061e-15}, - {4.1335978835978836e-3, -2.6813271604938272e-3, 7.7160493827160494e-4, 2.0093878600823045e-6, -1.0736653226365161e-4, 5.2923448829120125e-5, -1.2760635188618728e-5, 3.4235787340961381e-8, 1.3721957309062933e-6, -6.298992138380055e-7, 1.4280614206064242e-7, -2.0477098421990866e-10, -1.4092529910867521e-8, 6.228974084922022e-9, -1.3670488396617113e-9, 9.4283561590146782e-13, 1.2872252400089318e-10, -5.5645956134363321e-11, 1.1975935546366981e-11, -4.1689782251838635e-15, -1.0940640427884594e-12, 4.6622399463901357e-13, -9.905105763906906e-14, 1.8931876768373515e-17, 8.8592218725911273e-15}, - {6.4943415637860082e-4, 2.2947209362139918e-4, -4.6918949439525571e-4, 2.6772063206283885e-4, -7.5618016718839764e-5, -2.3965051138672967e-7, 1.1082654115347302e-5, -5.6749528269915966e-6, 1.4230900732435884e-6, -2.7861080291528142e-11, -1.6958404091930277e-7, 8.0994649053880824e-8, -1.9111168485973654e-8, 2.3928620439808118e-12, 2.0620131815488798e-9, -9.4604966618551322e-10, 2.1541049775774908e-10, -1.388823336813903e-14, -2.1894761681963939e-11, 9.7909989511716851e-12, -2.1782191880180962e-12, 6.2088195734079014e-17, 2.126978363279737e-13, -9.3446887915174333e-14, 2.0453671226782849e-14}, - {-8.618882909167117e-4, 7.8403922172006663e-4, -2.9907248030319018e-4, -1.4638452578843418e-6, 6.6414982154651222e-5, -3.9683650471794347e-5, 1.1375726970678419e-5, 2.5074972262375328e-10, -1.6954149536558306e-6, 8.9075075322053097e-7, -2.2929348340008049e-7, 2.956794137544049e-11, 2.8865829742708784e-8, -1.4189739437803219e-8, 3.4463580499464897e-9, -2.3024517174528067e-13, -3.9409233028046405e-10, 1.8602338968504502e-10, -4.356323005056618e-11, 1.2786001016296231e-15, 4.6792750266579195e-12, -2.1492464706134829e-12, 4.9088156148096522e-13, -6.3385914848915603e-18, -5.0453320690800944e-14}, - {-3.3679855336635815e-4, -6.9728137583658578e-5, 2.7727532449593921e-4, -1.9932570516188848e-4, 6.7977804779372078e-5, 1.419062920643967e-7, -1.3594048189768693e-5, 8.0184702563342015e-6, -2.2914811765080952e-6, -3.252473551298454e-10, 3.4652846491085265e-7, -1.8447187191171343e-7, 4.8240967037894181e-8, -1.7989466721743515e-14, -6.3061945000135234e-9, 3.1624176287745679e-9, -7.8409242536974293e-10, 5.1926791652540407e-15, 9.3589442423067836e-11, -4.5134262161632782e-11, 1.0799129993116827e-11, -3.661886712685252e-17, -1.210902069055155e-12, 5.6807435849905643e-13, -1.3249659916340829e-13}, - {5.3130793646399222e-4, -5.9216643735369388e-4, 2.7087820967180448e-4, 7.9023532326603279e-7, -8.1539693675619688e-5, 5.6116827531062497e-5, -1.8329116582843376e-5, -3.0796134506033048e-9, 3.4651553688036091e-6, -2.0291327396058604e-6, 5.7887928631490037e-7, 2.338630673826657e-13, -8.8286007463304835e-8, 4.7435958880408128e-8, -1.2545415020710382e-8, 8.6496488580102925e-14, 1.6846058979264063e-9, -8.5754928235775947e-10, 2.1598224929232125e-10, -7.6132305204761539e-16, -2.6639822008536144e-11, 1.3065700536611057e-11, -3.1799163902367977e-12, 4.7109761213674315e-18, 3.6902800842763467e-13}, - {3.4436760689237767e-4, 5.1717909082605922e-5, -3.3493161081142236e-4, 2.812695154763237e-4, -1.0976582244684731e-4, -1.2741009095484485e-7, 2.7744451511563644e-5, -1.8263488805711333e-5, 5.7876949497350524e-6, 4.9387589339362704e-10, -1.0595367014026043e-6, 6.1667143761104075e-7, -1.7562973359060462e-7, -1.2974473287015439e-12, 2.695423606288966e-8, -1.4578352908731271e-8, 3.887645959386175e-9, -3.8810022510194121e-17, -5.3279941738772867e-10, 2.7437977643314845e-10, -6.9957960920705679e-11, 2.5899863874868481e-17, 8.8566890996696381e-12, -4.403168815871311e-12, 1.0865561947091654e-12}, - {-6.5262391859530942e-4, 8.3949872067208728e-4, -4.3829709854172101e-4, -6.969091458420552e-7, 1.6644846642067548e-4, -1.2783517679769219e-4, 4.6299532636913043e-5, 4.5579098679227077e-9, -1.0595271125805195e-5, 6.7833429048651666e-6, -2.1075476666258804e-6, -1.7213731432817145e-11, 3.7735877416110979e-7, -2.1867506700122867e-7, 6.2202288040189269e-8, 6.5977038267330006e-16, -9.5903864974256858e-9, 5.2132144922808078e-9, -1.3991589583935709e-9, 5.382058999060575e-16, 1.9484714275467745e-10, -1.0127287556389682e-10, 2.6077347197254926e-11, -5.0904186999932993e-18, -3.3721464474854592e-12}, - {-5.9676129019274625e-4, -7.2048954160200106e-5, 6.7823088376673284e-4, -6.4014752602627585e-4, 2.7750107634328704e-4, 1.8197008380465151e-7, -8.4795071170685032e-5, 6.105192082501531e-5, -2.1073920183404862e-5, -8.8585890141255994e-10, 4.5284535953805377e-6, -2.8427815022504408e-6, 8.7082341778646412e-7, 3.6886101871706965e-12, -1.5344695190702061e-7, 8.862466778790695e-8, -2.5184812301826817e-8, -1.0225912098215092e-14, 3.8969470758154777e-9, -2.1267304792235635e-9, 5.7370135528051385e-10, -1.887749850169741e-19, -8.0931538694657866e-11, 4.2382723283449199e-11, -1.1002224534207726e-11}, - {1.3324454494800656e-3, -1.9144384985654775e-3, 1.1089369134596637e-3, 9.932404122642299e-7, -5.0874501293093199e-4, 4.2735056665392884e-4, -1.6858853767910799e-4, -8.1301893922784998e-9, 4.5284402370562147e-5, -3.127053674781734e-5, 1.044986828530338e-5, 4.8435226265680926e-11, -2.1482565873456258e-6, 1.329369701097492e-6, -4.0295693092101029e-7, -1.7567877666323291e-13, 7.0145043163668257e-8, -4.040787734999483e-8, 1.1474026743371963e-8, 3.9642746853563325e-18, -1.7804938269892714e-9, 9.7480262548731646e-10, -2.6405338676507616e-10, 5.794875163403742e-18, 3.7647749553543836e-11}, - {1.579727660730835e-3, 1.6251626278391582e-4, -2.0633421035543276e-3, 2.1389686185689098e-3, -1.0108559391263003e-3, -3.9912705529919201e-7, 3.6235025084764691e-4, -2.8143901463712154e-4, 1.0449513336495887e-4, 2.1211418491830297e-9, -2.5779417251947842e-5, 1.7281818956040463e-5, -5.6413773872904282e-6, -1.1024320105776174e-11, 1.1223224418895175e-6, -6.8693396379526735e-7, 2.0653236975414887e-7, 4.6714772409838506e-14, -3.5609886164949055e-8, 2.0470855345905963e-8, -5.8091738633283358e-9, -1.332821287582869e-16, 9.0354604391335133e-10, -4.9598782517330834e-10, 1.3481607129399749e-10}, - {-4.0725121195140166e-3, 6.4033628338080698e-3, -4.0410161081676618e-3, -2.183732802866233e-6, 2.1740441801254639e-3, -1.9700440518418892e-3, 8.3595469747962458e-4, 1.9445447567109655e-8, -2.5779387120421696e-4, 1.9009987368139304e-4, -6.7696499937438965e-5, -1.4440629666426572e-10, 1.5712512518742269e-5, -1.0304008744776893e-5, 3.304517767401387e-6, 7.9829760242325709e-13, -6.4097794149313004e-7, 3.8894624761300056e-7, -1.1618347644948869e-7, -2.816808630596451e-15, 1.9878012911297093e-8, -1.1407719956357511e-8, 3.2355857064185555e-9, 4.1759468293455945e-20, -5.0423112718105824e-10}, - {-5.9475779383993003e-3, -5.4016476789260452e-4, 8.7910413550767898e-3, -9.8576315587856125e-3, 5.0134695031021538e-3, 1.2807521786221875e-6, -2.0626019342754683e-3, 1.7109128573523058e-3, -6.7695312714133799e-4, -6.9011545676562133e-9, 1.8855128143995902e-4, -1.3395215663491969e-4, 4.6263183033528039e-5, 4.0034230613321351e-11, -1.0255652921494033e-5, 6.612086372797651e-6, -2.0913022027253008e-6, -2.0951775649603837e-13, 3.9756029041993247e-7, -2.3956211978815887e-7, 7.1182883382145864e-8, 8.925574873053455e-16, -1.2101547235064676e-8, 6.9350618248334386e-9, -1.9661464453856102e-9}, - {1.7402027787522711e-2, -2.9527880945699121e-2, 2.0045875571402799e-2, 7.0289515966903407e-6, -1.2375421071343148e-2, 1.1976293444235254e-2, -5.4156038466518525e-3, -6.3290893396418616e-8, 1.8855118129005065e-3, -1.473473274825001e-3, 5.5515810097708387e-4, 5.2406834412550662e-10, -1.4357913535784836e-4, 9.9181293224943297e-5, -3.3460834749478311e-5, -3.5755837291098993e-12, 7.1560851960630076e-6, -4.5516802628155526e-6, 1.4236576649271475e-6, 1.8803149082089664e-14, -2.6623403898929211e-7, 1.5950642189595716e-7, -4.7187514673841102e-8, -6.5107872958755177e-17, 7.9795091026746235e-9}, - {3.0249124160905891e-2, 2.4817436002649977e-3, -4.9939134373457022e-2, 5.9915643009307869e-2, -3.2483207601623391e-2, -5.7212968652103441e-6, 1.5085251778569354e-2, -1.3261324005088445e-2, 5.5515262632426148e-3, 3.0263182257030016e-8, -1.7229548406756723e-3, 1.2893570099929637e-3, -4.6845138348319876e-4, -1.830259937893045e-10, 1.1449739014822654e-4, -7.7378565221244477e-5, 2.5625836246985201e-5, 1.0766165333192814e-12, -5.3246809282422621e-6, 3.349634863064464e-6, -1.0381253128684018e-6, -5.608909920621128e-15, 1.9150821930676591e-7, -1.1418365800203486e-7, 3.3654425209171788e-8}, - {-9.9051020880159045e-2, 1.7954011706123486e-1, -1.2989606383463778e-1, -3.1478872752284357e-5, 9.0510635276848131e-2, -9.2828824411184397e-2, 4.4412112839877808e-2, 2.7779236316835888e-7, -1.7229543805449697e-2, 1.4182925050891573e-2, -5.6214161633747336e-3, -2.39598509186381e-9, 1.6029634366079908e-3, -1.1606784674435773e-3, 4.1001337768153873e-4, 1.8365800754090661e-11, -9.5844256563655903e-5, 6.3643062337764708e-5, -2.076250624489065e-5, -1.1806020912804483e-13, 4.2131808239120649e-6, -2.6262241337012467e-6, 8.0770620494930662e-7, 6.0125912123632725e-16, -1.4729737374018841e-7}, - {-1.9994542198219728e-1, -1.5056113040026424e-2, 3.6470239469348489e-1, -4.6435192311733545e-1, 2.6640934719197893e-1, 3.4038266027147191e-5, -1.3784338709329624e-1, 1.276467178337056e-1, -5.6213828755200985e-2, -1.753150885483011e-7, 1.9235592956768113e-2, -1.5088821281095315e-2, 5.7401854451350123e-3, 1.0622382710310225e-9, -1.5335082692563998e-3, 1.0819320643228214e-3, -3.7372510193945659e-4, -6.6170909729031985e-12, 8.4263617380909628e-5, -5.5150706827483479e-5, 1.7769536448348069e-5, 3.8827923210205533e-14, -3.53513697488768e-6, 2.1865832130045269e-6, -6.6812849447625594e-7}, - {7.2438608504029431e-1, -1.3918010932653375, 1.0654143352413968, 1.876173868950258e-4, -8.2705501176152696e-1, 8.9352433347828414e-1, -4.4971003995291339e-1, -1.6107401567546652e-6, 1.9235590165271091e-1, -1.6597702160042609e-1, 6.8882222681814333e-2, 1.3910091724608687e-8, -2.146911561508663e-2, 1.6228980898865892e-2, -5.9796016172584256e-3, -1.1287469112826745e-10, 1.5167451119784857e-3, -1.0478634293553899e-3, 3.5539072889126421e-4, 8.1704322111801517e-13, -7.7773013442452395e-5, 5.0291413897007722e-5, -1.6035083867000518e-5, 1.2469354315487605e-14, 3.1369106244517615e-6}, - {1.6668949727276811, 1.165462765994632e-1, -3.3288393225018906, 4.4692325482864037, -2.6977693045875807, -2.600667859891061e-4, 1.5389017615694539, -1.4937962361134612, 6.8881964633233148e-1, 1.3077482004552385e-6, -2.5762963325596288e-1, 2.1097676102125449e-1, -8.3714408359219882e-2, -7.7920428881354753e-9, 2.4267923064833599e-2, -1.7813678334552311e-2, 6.3970330388900056e-3, 4.9430807090480523e-11, -1.5554602758465635e-3, 1.0561196919903214e-3, -3.5277184460472902e-4, 9.3002334645022459e-14, 7.5285855026557172e-5, -4.8186515569156351e-5, 1.5227271505597605e-5}, - {-6.6188298861372935, 1.3397985455142589e+1, -1.0789350606845146e+1, -1.4352254537875018e-3, 9.2333694596189809, -1.0456552819547769e+1, 5.5105526029033471, 1.2024439690716742e-5, -2.5762961164755816, 2.3207442745387179, -1.0045728797216284, -1.0207833290021914e-7, 3.3975092171169466e-1, -2.6720517450757468e-1, 1.0235252851562706e-1, 8.4329730484871625e-10, -2.7998284958442595e-2, 2.0066274144976813e-2, -7.0554368915086242e-3, 1.9402238183698188e-12, 1.6562888105449611e-3, -1.1082898580743683e-3, 3.654545161310169e-4, -5.1290032026971794e-11, -7.6340103696869031e-5}, - {-1.7112706061976095e+1, -1.1208044642899116, 3.7131966511885444e+1, -5.2298271025348962e+1, 3.3058589696624618e+1, 2.4791298976200222e-3, -2.061089403411526e+1, 2.088672775145582e+1, -1.0045703956517752e+1, -1.2238783449063012e-5, 4.0770134274221141, -3.473667358470195, 1.4329352617312006, 7.1359914411879712e-8, -4.4797257159115612e-1, 3.4112666080644461e-1, -1.2699786326594923e-1, -2.8953677269081528e-10, 3.3125776278259863e-2, -2.3274087021036101e-2, 8.0399993503648882e-3, -1.177805216235265e-9, -1.8321624891071668e-3, 1.2108282933588665e-3, -3.9479941246822517e-4}, - {7.389033153567425e+1, -1.5680141270402273e+2, 1.322177542759164e+2, 1.3692876877324546e-2, -1.2366496885920151e+2, 1.4620689391062729e+2, -8.0365587724865346e+1, -1.1259851148881298e-4, 4.0770132196179938e+1, -3.8210340013273034e+1, 1.719522294277362e+1, 9.3519707955168356e-7, -6.2716159907747034, 5.1168999071852637, -2.0319658112299095, -4.9507215582761543e-9, 5.9626397294332597e-1, -4.4220765337238094e-1, 1.6079998700166273e-1, -2.4733786203223402e-8, -4.0307574759979762e-2, 2.7849050747097869e-2, -9.4751858992054221e-3, 6.419922235909132e-6, 2.1250180774699461e-3}, - {2.1216837098382522e+2, 1.3107863022633868e+1, -4.9698285932871748e+2, 7.3121595266969204e+2, -4.8213821720890847e+2, -2.8817248692894889e-2, 3.2616720302947102e+2, -3.4389340280087117e+2, 1.7195193870816232e+2, 1.4038077378096158e-4, -7.52594195897599e+1, 6.651969984520934e+1, -2.8447519748152462e+1, -7.613702615875391e-7, 9.5402237105304373, -7.5175301113311376, 2.8943997568871961, -4.6612194999538201e-7, -8.0615149598794088e-1, 5.8483006570631029e-1, -2.0845408972964956e-1, 1.4765818959305817e-4, 5.1000433863753019e-2, -3.3066252141883665e-2, 1.5109265210467774e-2}, - {-9.8959643098322368e+2, 2.1925555360905233e+3, -1.9283586782723356e+3, -1.5925738122215253e-1, 1.9569985945919857e+3, -2.4072514765081556e+3, 1.3756149959336496e+3, 1.2920735237496668e-3, -7.525941715948055e+2, 7.3171668742208716e+2, -3.4137023466220065e+2, -9.9857390260608043e-6, 1.3356313181291573e+2, -1.1276295161252794e+2, 4.6310396098204458e+1, -7.9237387133614756e-6, -1.4510726927018646e+1, 1.1111771248100563e+1, -4.1690817945270892, 3.1008219800117808e-3, 1.1220095449981468, -7.6052379926149916e-1, 3.6262236505085254e-1, 2.216867741940747e-1, 4.8683443692930507e-1}, -} - -// Igam computes the incomplete Gamma integral. -// -// Igam(a,x) = (1/ Γ(a)) \int_0^x e^{-t} t^{a-1} dt -// -// The input argument a must be positive and x must be non-negative or Igam -// will panic. -func Igam(a, x float64) float64 { - // The integral is evaluated by either a power series or continued fraction - // expansion, depending on the relative values of a and x. - // Sources: - // [1] "The Digital Library of Mathematical Functions", dlmf.nist.gov - // [2] Maddock et. al., "Incomplete Gamma Functions", - // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html - - // Check zero integration limit first - if x == 0 { - return 0 - } - - if x < 0 || a <= 0 { - panic(paramOutOfBounds) - } - - // Asymptotic regime where a ~ x; see [2]. - absxmaA := math.Abs(x-a) / a - if (igamSmall < a && a < igamLarge && absxmaA < igamSmallRatio) || - (igamLarge < a && absxmaA < igamLargeRatio/math.Sqrt(a)) { - return asymptoticSeries(a, x, igam) - } - - if x > 1 && x > a { - return 1 - IgamC(a, x) - } - - return igamSeries(a, x) -} - -// IgamC computes the complemented incomplete Gamma integral. -// -// IgamC(a,x) = 1 - Igam(a,x) -// = (1/ Γ(a)) \int_0^\infty e^{-t} t^{a-1} dt -// -// The input argument a must be positive and x must be non-negative or -// IgamC will panic. -func IgamC(a, x float64) float64 { - // The integral is evaluated by either a power series or continued fraction - // expansion, depending on the relative values of a and x. - // Sources: - // [1] "The Digital Library of Mathematical Functions", dlmf.nist.gov - // [2] Maddock et. al., "Incomplete Gamma Functions", - // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html - - switch { - case x < 0, a <= 0: - panic(paramOutOfBounds) - case x == 0: - return 1 - case math.IsInf(x, 0): - return 0 - } - - // Asymptotic regime where a ~ x; see [2]. - absxmaA := math.Abs(x-a) / a - if (igamSmall < a && a < igamLarge && absxmaA < igamSmallRatio) || - (igamLarge < a && absxmaA < igamLargeRatio/math.Sqrt(a)) { - return asymptoticSeries(a, x, igamC) - } - - // Everywhere else; see [2]. - if x > 1.1 { - if x < a { - return 1 - igamSeries(a, x) - } - return igamCContinuedFraction(a, x) - } else if x <= 0.5 { - if -0.4/math.Log(x) < a { - return 1 - igamSeries(a, x) - } - return igamCSeries(a, x) - } - - if x*1.1 < a { - return 1 - igamSeries(a, x) - } - return igamCSeries(a, x) -} - -// igamFac computes -// -// x^a * e^{-x} / Γ(a) -// -// corrected from (15) and (16) in [2] by replacing -// -// e^{x - a} -// -// with -// -// e^{a - x} -func igamFac(a, x float64) float64 { - if math.Abs(a-x) > 0.4*math.Abs(a) { - ax := a*math.Log(x) - x - lgam(a) - return math.Exp(ax) - } - - fac := a + lanczosG - 0.5 - res := math.Sqrt(fac/math.Exp(1)) / lanczosSumExpgScaled(a) - - if a < 200 && x < 200 { - res *= math.Exp(a-x) * math.Pow(x/fac, a) - } else { - num := x - a - lanczosG + 0.5 - res *= math.Exp(a*log1pmx(num/fac) + x*(0.5-lanczosG)/fac) - } - - return res -} - -// igamCContinuedFraction computes IgamC using DLMF 8.9.2. -func igamCContinuedFraction(a, x float64) float64 { - ax := igamFac(a, x) - if ax == 0 { - return 0 - } - - // Continued fraction - y := 1 - a - z := x + y + 1 - c := 0.0 - pkm2 := 1.0 - qkm2 := x - pkm1 := x + 1.0 - qkm1 := z * x - ans := pkm1 / qkm1 - - for i := 0; i < maxIter; i++ { - c += 1.0 - y += 1.0 - z += 2.0 - yc := y * c - pk := pkm1*z - pkm2*yc - qk := qkm1*z - qkm2*yc - var t float64 - if qk != 0 { - r := pk / qk - t = math.Abs((ans - r) / r) - ans = r - } else { - t = 1.0 - } - pkm2 = pkm1 - pkm1 = pk - qkm2 = qkm1 - qkm1 = qk - if math.Abs(pk) > big { - pkm2 *= biginv - pkm1 *= biginv - qkm2 *= biginv - qkm1 *= biginv - } - if t <= machEp { - break - } - } - - return ans * ax -} - -// igamSeries computes Igam using DLMF 8.11.4. -func igamSeries(a, x float64) float64 { - ax := igamFac(a, x) - if ax == 0 { - return 0 - } - - // Power series - r := a - c := 1.0 - ans := 1.0 - - for i := 0; i < maxIter; i++ { - r += 1.0 - c *= x / r - ans += c - if c <= machEp*ans { - break - } - } - - return ans * ax / a -} - -// igamCSeries computes IgamC using DLMF 8.7.3. This is related to the series -// in igamSeries but extra care is taken to avoid cancellation. -func igamCSeries(a, x float64) float64 { - fac := 1.0 - sum := 0.0 - - for n := 1; n < maxIter; n++ { - fac *= -x / float64(n) - term := fac / (a + float64(n)) - sum += term - if math.Abs(term) <= machEp*math.Abs(sum) { - break - } - } - - logx := math.Log(x) - term := -expm1(a*logx - lgam1p(a)) - return term - math.Exp(a*logx-lgam(a))*sum -} - -// asymptoticSeries computes Igam/IgamC using DLMF 8.12.3/8.12.4. -func asymptoticSeries(a, x float64, fun int) float64 { - maxpow := 0 - lambda := x / a - sigma := (x - a) / a - absoldterm := math.MaxFloat64 - etapow := [igamDimN]float64{1} - sum := 0.0 - afac := 1.0 - - var sgn float64 - if fun == igam { - sgn = -1 - } else { - sgn = 1 - } - - var eta float64 - if lambda > 1 { - eta = math.Sqrt(-2 * log1pmx(sigma)) - } else if lambda < 1 { - eta = -math.Sqrt(-2 * log1pmx(sigma)) - } else { - eta = 0 - } - res := 0.5 * math.Erfc(sgn*eta*math.Sqrt(a/2)) - - for k := 0; k < igamDimK; k++ { - ck := igamCoefs[k][0] - for n := 1; n < igamDimN; n++ { - if n > maxpow { - etapow[n] = eta * etapow[n-1] - maxpow++ - } - ckterm := igamCoefs[k][n] * etapow[n] - ck += ckterm - if math.Abs(ckterm) < machEp*math.Abs(ck) { - break - } - } - term := ck * afac - absterm := math.Abs(term) - if absterm > absoldterm { - break - } - sum += term - if absterm < machEp*math.Abs(sum) { - break - } - absoldterm = absterm - afac /= a - } - res += sgn * math.Exp(-0.5*a*eta*eta) * sum / math.Sqrt(2*math.Pi*a) - - return res -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go deleted file mode 100644 index bb80b9cf..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/igami.go +++ /dev/null @@ -1,155 +0,0 @@ -// Derived from SciPy's special/cephes/igami.c -// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igami.c -// Made freely available by Stephen L. Moshier without support or guarantee. - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Copyright ©1984, ©1987, ©1995 by Stephen L. Moshier -// Portions Copyright ©2017 The Gonum Authors. All rights reserved. - -package cephes - -import "math" - -// IgamI computes the inverse of the incomplete Gamma function. That is, it -// returns the x such that: -// -// IgamC(a, x) = p -// -// The input argument a must be positive and p must be between 0 and 1 -// inclusive or IgamI will panic. IgamI should return a positive number, but -// can return 0 even with non-zero y due to underflow. -func IgamI(a, p float64) float64 { - // Bound the solution - x0 := math.MaxFloat64 - yl := 0.0 - x1 := 0.0 - yh := 1.0 - dithresh := 5.0 * machEp - - if p < 0 || p > 1 || a <= 0 { - panic(paramOutOfBounds) - } - - if p == 0 { - return math.Inf(1) - } - - if p == 1 { - return 0.0 - } - - // Starting with the approximate value - // x = a y^3 - // where - // y = 1 - d - ndtri(p) sqrt(d) - // and - // d = 1/9a - // the routine performs up to 10 Newton iterations to find the root of - // IgamC(a, x) - p = 0 - d := 1.0 / (9.0 * a) - y := 1.0 - d - Ndtri(p)*math.Sqrt(d) - x := a * y * y * y - - lgm := lgam(a) - - for i := 0; i < 10; i++ { - if x > x0 || x < x1 { - break - } - - y = IgamC(a, x) - - if y < yl || y > yh { - break - } - - if y < p { - x0 = x - yl = y - } else { - x1 = x - yh = y - } - - // Compute the derivative of the function at this point - d = (a-1)*math.Log(x) - x - lgm - if d < -maxLog { - break - } - d = -math.Exp(d) - - // Compute the step to the next approximation of x - d = (y - p) / d - if math.Abs(d/x) < machEp { - return x - } - x = x - d - } - - d = 0.0625 - if x0 == math.MaxFloat64 { - if x <= 0 { - x = 1 - } - for x0 == math.MaxFloat64 { - x = (1 + d) * x - y = IgamC(a, x) - if y < p { - x0 = x - yl = y - break - } - d = d + d - } - } - - d = 0.5 - dir := 0 - for i := 0; i < 400; i++ { - x = x1 + d*(x0-x1) - y = IgamC(a, x) - - lgm = (x0 - x1) / (x1 + x0) - if math.Abs(lgm) < dithresh { - break - } - - lgm = (y - p) / p - if math.Abs(lgm) < dithresh { - break - } - - if x <= 0 { - break - } - - if y >= p { - x1 = x - yh = y - if dir < 0 { - dir = 0 - d = 0.5 - } else if dir > 1 { - d = 0.5*d + 0.5 - } else { - d = (p - yl) / (yh - yl) - } - dir++ - } else { - x0 = x - yl = y - if dir > 0 { - dir = 0 - d = 0.5 - } else if dir < -1 { - d = 0.5 * d - } else { - d = (p - yl) / (yh - yl) - } - dir-- - } - } - - return x -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go deleted file mode 100644 index 6a818154..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbeta.go +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* - * Cephes Math Library, Release 2.3: March, 1995 - * Copyright 1984, 1995 by Stephen L. Moshier - */ - -package cephes - -import ( - "math" - - "gonum.org/v1/gonum/mathext/internal/gonum" -) - -const ( - maxGam = 171.624376956302725 - big = 4.503599627370496e15 - biginv = 2.22044604925031308085e-16 -) - -// Incbet computes the regularized incomplete beta function. -func Incbet(aa, bb, xx float64) float64 { - if aa <= 0 || bb <= 0 { - panic(paramOutOfBounds) - } - if xx <= 0 || xx >= 1 { - if xx == 0 { - return 0 - } - if xx == 1 { - return 1 - } - panic(paramOutOfBounds) - } - - var flag int - if bb*xx <= 1 && xx <= 0.95 { - t := pseries(aa, bb, xx) - return transformT(t, flag) - } - - w := 1 - xx - - // Reverse a and b if x is greater than the mean. - var a, b, xc, x float64 - if xx > aa/(aa+bb) { - flag = 1 - a = bb - b = aa - xc = xx - x = w - } else { - a = aa - b = bb - xc = w - x = xx - } - - if flag == 1 && (b*x) <= 1.0 && x <= 0.95 { - t := pseries(a, b, x) - return transformT(t, flag) - } - - // Choose expansion for better convergence. - y := x*(a+b-2.0) - (a - 1.0) - if y < 0.0 { - w = incbcf(a, b, x) - } else { - w = incbd(a, b, x) / xc - } - - // Multiply w by the factor - // x^a * (1-x)^b * Γ(a+b) / (a*Γ(a)*Γ(b)) - var t float64 - y = a * math.Log(x) - t = b * math.Log(xc) - if (a+b) < maxGam && math.Abs(y) < maxLog && math.Abs(t) < maxLog { - t = math.Pow(xc, b) - t *= math.Pow(x, a) - t /= a - t *= w - t *= 1.0 / gonum.Beta(a, b) - return transformT(t, flag) - } - - // Resort to logarithms. - y += t - gonum.Lbeta(a, b) - y += math.Log(w / a) - if y < minLog { - t = 0.0 - } else { - t = math.Exp(y) - } - - return transformT(t, flag) -} - -func transformT(t float64, flag int) float64 { - if flag == 1 { - if t <= machEp { - t = 1.0 - machEp - } else { - t = 1.0 - t - } - } - return t -} - -// incbcf returns the incomplete beta integral evaluated by a continued fraction -// expansion. -func incbcf(a, b, x float64) float64 { - var xk, pk, pkm1, pkm2, qk, qkm1, qkm2 float64 - var k1, k2, k3, k4, k5, k6, k7, k8 float64 - var r, t, ans, thresh float64 - var n int - - k1 = a - k2 = a + b - k3 = a - k4 = a + 1.0 - k5 = 1.0 - k6 = b - 1.0 - k7 = k4 - k8 = a + 2.0 - - pkm2 = 0.0 - qkm2 = 1.0 - pkm1 = 1.0 - qkm1 = 1.0 - ans = 1.0 - r = 1.0 - thresh = 3.0 * machEp - - for n = 0; n <= 300; n++ { - - xk = -(x * k1 * k2) / (k3 * k4) - pk = pkm1 + pkm2*xk - qk = qkm1 + qkm2*xk - pkm2 = pkm1 - pkm1 = pk - qkm2 = qkm1 - qkm1 = qk - - xk = (x * k5 * k6) / (k7 * k8) - pk = pkm1 + pkm2*xk - qk = qkm1 + qkm2*xk - pkm2 = pkm1 - pkm1 = pk - qkm2 = qkm1 - qkm1 = qk - - if qk != 0 { - r = pk / qk - } - if r != 0 { - t = math.Abs((ans - r) / r) - ans = r - } else { - t = 1.0 - } - - if t < thresh { - return ans - } - - k1 += 1.0 - k2 += 1.0 - k3 += 2.0 - k4 += 2.0 - k5 += 1.0 - k6 -= 1.0 - k7 += 2.0 - k8 += 2.0 - - if (math.Abs(qk) + math.Abs(pk)) > big { - pkm2 *= biginv - pkm1 *= biginv - qkm2 *= biginv - qkm1 *= biginv - } - if (math.Abs(qk) < biginv) || (math.Abs(pk) < biginv) { - pkm2 *= big - pkm1 *= big - qkm2 *= big - qkm1 *= big - } - } - - return ans -} - -// incbd returns the incomplete beta integral evaluated by a continued fraction -// expansion. -func incbd(a, b, x float64) float64 { - var xk, pk, pkm1, pkm2, qk, qkm1, qkm2 float64 - var k1, k2, k3, k4, k5, k6, k7, k8 float64 - var r, t, ans, z, thresh float64 - var n int - - k1 = a - k2 = b - 1.0 - k3 = a - k4 = a + 1.0 - k5 = 1.0 - k6 = a + b - k7 = a + 1.0 - k8 = a + 2.0 - - pkm2 = 0.0 - qkm2 = 1.0 - pkm1 = 1.0 - qkm1 = 1.0 - z = x / (1.0 - x) - ans = 1.0 - r = 1.0 - thresh = 3.0 * machEp - for n = 0; n <= 300; n++ { - - xk = -(z * k1 * k2) / (k3 * k4) - pk = pkm1 + pkm2*xk - qk = qkm1 + qkm2*xk - pkm2 = pkm1 - pkm1 = pk - qkm2 = qkm1 - qkm1 = qk - - xk = (z * k5 * k6) / (k7 * k8) - pk = pkm1 + pkm2*xk - qk = qkm1 + qkm2*xk - pkm2 = pkm1 - pkm1 = pk - qkm2 = qkm1 - qkm1 = qk - - if qk != 0 { - r = pk / qk - } - if r != 0 { - t = math.Abs((ans - r) / r) - ans = r - } else { - t = 1.0 - } - - if t < thresh { - return ans - } - - k1 += 1.0 - k2 -= 1.0 - k3 += 2.0 - k4 += 2.0 - k5 += 1.0 - k6 += 1.0 - k7 += 2.0 - k8 += 2.0 - - if (math.Abs(qk) + math.Abs(pk)) > big { - pkm2 *= biginv - pkm1 *= biginv - qkm2 *= biginv - qkm1 *= biginv - } - if (math.Abs(qk) < biginv) || (math.Abs(pk) < biginv) { - pkm2 *= big - pkm1 *= big - qkm2 *= big - qkm1 *= big - } - } - return ans -} - -// pseries returns the incomplete beta integral evaluated by a power series. Use -// when b*x is small and x not too close to 1. -func pseries(a, b, x float64) float64 { - var s, t, u, v, n, t1, z, ai float64 - ai = 1.0 / a - u = (1.0 - b) * x - v = u / (a + 1.0) - t1 = v - t = u - n = 2.0 - s = 0.0 - z = machEp * ai - for math.Abs(v) > z { - u = (n - b) * x / n - t *= u - v = t / (a + n) - s += v - n += 1.0 - } - s += t1 - s += ai - - u = a * math.Log(x) - if (a+b) < maxGam && math.Abs(u) < maxLog { - t = 1.0 / gonum.Beta(a, b) - s = s * t * math.Pow(x, a) - } else { - t = -gonum.Lbeta(a, b) + u + math.Log(s) - if t < minLog { - s = 0.0 - } else { - s = math.Exp(t) - } - } - return (s) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go deleted file mode 100644 index 2b612d83..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/incbi.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* - * Cephes Math Library Release 2.4: March,1996 - * Copyright 1984, 1996 by Stephen L. Moshier - */ - -package cephes - -import "math" - -// Incbi computes the inverse of the regularized incomplete beta integral. -func Incbi(aa, bb, yy0 float64) float64 { - var a, b, y0, d, y, x, x0, x1, lgm, yp, di, dithresh, yl, yh, xt float64 - var i, rflg, dir, nflg int - - if yy0 <= 0 { - return (0.0) - } - if yy0 >= 1.0 { - return (1.0) - } - x0 = 0.0 - yl = 0.0 - x1 = 1.0 - yh = 1.0 - nflg = 0 - - if aa <= 1.0 || bb <= 1.0 { - dithresh = 1.0e-6 - rflg = 0 - a = aa - b = bb - y0 = yy0 - x = a / (a + b) - y = Incbet(a, b, x) - goto ihalve - } else { - dithresh = 1.0e-4 - } - // Approximation to inverse function - yp = -Ndtri(yy0) - - if yy0 > 0.5 { - rflg = 1 - a = bb - b = aa - y0 = 1.0 - yy0 - yp = -yp - } else { - rflg = 0 - a = aa - b = bb - y0 = yy0 - } - - lgm = (yp*yp - 3.0) / 6.0 - x = 2.0 / (1.0/(2.0*a-1.0) + 1.0/(2.0*b-1.0)) - d = yp*math.Sqrt(x+lgm)/x - (1.0/(2.0*b-1.0)-1.0/(2.0*a-1.0))*(lgm+5.0/6.0-2.0/(3.0*x)) - d = 2.0 * d - if d < minLog { - // mtherr("incbi", UNDERFLOW) - x = 0 - goto done - } - x = a / (a + b*math.Exp(d)) - y = Incbet(a, b, x) - yp = (y - y0) / y0 - if math.Abs(yp) < 0.2 { - goto newt - } - - /* Resort to interval halving if not close enough. */ -ihalve: - - dir = 0 - di = 0.5 - for i = 0; i < 100; i++ { - if i != 0 { - x = x0 + di*(x1-x0) - if x == 1.0 { - x = 1.0 - machEp - } - if x == 0.0 { - di = 0.5 - x = x0 + di*(x1-x0) - if x == 0.0 { - // mtherr("incbi", UNDERFLOW) - goto done - } - } - y = Incbet(a, b, x) - yp = (x1 - x0) / (x1 + x0) - if math.Abs(yp) < dithresh { - goto newt - } - yp = (y - y0) / y0 - if math.Abs(yp) < dithresh { - goto newt - } - } - if y < y0 { - x0 = x - yl = y - if dir < 0 { - dir = 0 - di = 0.5 - } else if dir > 3 { - di = 1.0 - (1.0-di)*(1.0-di) - } else if dir > 1 { - di = 0.5*di + 0.5 - } else { - di = (y0 - y) / (yh - yl) - } - dir += 1 - if x0 > 0.75 { - if rflg == 1 { - rflg = 0 - a = aa - b = bb - y0 = yy0 - } else { - rflg = 1 - a = bb - b = aa - y0 = 1.0 - yy0 - } - x = 1.0 - x - y = Incbet(a, b, x) - x0 = 0.0 - yl = 0.0 - x1 = 1.0 - yh = 1.0 - goto ihalve - } - } else { - x1 = x - if rflg == 1 && x1 < machEp { - x = 0.0 - goto done - } - yh = y - if dir > 0 { - dir = 0 - di = 0.5 - } else if dir < -3 { - di = di * di - } else if dir < -1 { - di = 0.5 * di - } else { - di = (y - y0) / (yh - yl) - } - dir -= 1 - } - } - // mtherr("incbi", PLOSS) - if x0 >= 1.0 { - x = 1.0 - machEp - goto done - } - if x <= 0.0 { - // mtherr("incbi", UNDERFLOW) - x = 0.0 - goto done - } - -newt: - if nflg > 0 { - goto done - } - nflg = 1 - lgm = lgam(a+b) - lgam(a) - lgam(b) - - for i = 0; i < 8; i++ { - /* Compute the function at this point. */ - if i != 0 { - y = Incbet(a, b, x) - } - if y < yl { - x = x0 - y = yl - } else if y > yh { - x = x1 - y = yh - } else if y < y0 { - x0 = x - yl = y - } else { - x1 = x - yh = y - } - if x == 1.0 || x == 0.0 { - break - } - /* Compute the derivative of the function at this point. */ - d = (a-1.0)*math.Log(x) + (b-1.0)*math.Log(1.0-x) + lgm - if d < minLog { - goto done - } - if d > maxLog { - break - } - d = math.Exp(d) - /* Compute the step to the next approximation of x. */ - d = (y - y0) / d - xt = x - d - if xt <= x0 { - y = (x - x0) / (x1 - x0) - xt = x0 + 0.5*y*(x-x0) - if xt <= 0.0 { - break - } - } - if xt >= x1 { - y = (x1 - x) / (x1 - x0) - xt = x1 - 0.5*y*(x1-x) - if xt >= 1.0 { - break - } - } - x = xt - if math.Abs(d/x) < 128.0*machEp { - goto done - } - } - /* Did not converge. */ - dithresh = 256.0 * machEp - goto ihalve - -done: - - if rflg > 0 { - if x <= machEp { - x = 1.0 - machEp - } else { - x = 1.0 - x - } - } - return (x) -} - -func lgam(a float64) float64 { - lg, _ := math.Lgamma(a) - return lg -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go deleted file mode 100644 index ec29161f..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/lanczos.go +++ /dev/null @@ -1,153 +0,0 @@ -// Derived from SciPy's special/cephes/lanczos.c -// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/lanczos.c - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Copyright ©2006 John Maddock -// Portions Copyright ©2003 Boost -// Portions Copyright ©2016 The Gonum Authors. All rights reserved. - -package cephes - -// Optimal values for G for each N are taken from -// http://web.mala.bc.ca/pughg/phdThesis/phdThesis.pdf, -// as are the theoretical error bounds. - -// Constants calculated using the method described by Godfrey -// http://my.fit.edu/~gabdo/gamma.txt and elaborated by Toth at -// http://www.rskey.org/gamma.htm using NTL::RR at 1000 bit precision. - -var lanczosNum = [...]float64{ - 2.506628274631000270164908177133837338626, - 210.8242777515793458725097339207133627117, - 8071.672002365816210638002902272250613822, - 186056.2653952234950402949897160456992822, - 2876370.628935372441225409051620849613599, - 31426415.58540019438061423162831820536287, - 248874557.8620541565114603864132294232163, - 1439720407.311721673663223072794912393972, - 6039542586.35202800506429164430729792107, - 17921034426.03720969991975575445893111267, - 35711959237.35566804944018545154716670596, - 42919803642.64909876895789904700198885093, - 23531376880.41075968857200767445163675473, -} - -var lanczosDenom = [...]float64{ - 1, - 66, - 1925, - 32670, - 357423, - 2637558, - 13339535, - 45995730, - 105258076, - 150917976, - 120543840, - 39916800, - 0, -} - -var lanczosSumExpgScaledNum = [...]float64{ - 0.006061842346248906525783753964555936883222, - 0.5098416655656676188125178644804694509993, - 19.51992788247617482847860966235652136208, - 449.9445569063168119446858607650988409623, - 6955.999602515376140356310115515198987526, - 75999.29304014542649875303443598909137092, - 601859.6171681098786670226533699352302507, - 3481712.15498064590882071018964774556468, - 14605578.08768506808414169982791359218571, - 43338889.32467613834773723740590533316085, - 86363131.28813859145546927288977868422342, - 103794043.1163445451906271053616070238554, - 56906521.91347156388090791033559122686859, -} - -var lanczosSumExpgScaledDenom = [...]float64{ - 1, - 66, - 1925, - 32670, - 357423, - 2637558, - 13339535, - 45995730, - 105258076, - 150917976, - 120543840, - 39916800, - 0, -} - -var lanczosSumNear1D = [...]float64{ - 0.3394643171893132535170101292240837927725e-9, - -0.2499505151487868335680273909354071938387e-8, - 0.8690926181038057039526127422002498960172e-8, - -0.1933117898880828348692541394841204288047e-7, - 0.3075580174791348492737947340039992829546e-7, - -0.2752907702903126466004207345038327818713e-7, - -0.1515973019871092388943437623825208095123e-5, - 0.004785200610085071473880915854204301886437, - -0.1993758927614728757314233026257810172008, - 1.483082862367253753040442933770164111678, - -3.327150580651624233553677113928873034916, - 2.208709979316623790862569924861841433016, -} - -var lanczosSumNear2D = [...]float64{ - 0.1009141566987569892221439918230042368112e-8, - -0.7430396708998719707642735577238449585822e-8, - 0.2583592566524439230844378948704262291927e-7, - -0.5746670642147041587497159649318454348117e-7, - 0.9142922068165324132060550591210267992072e-7, - -0.8183698410724358930823737982119474130069e-7, - -0.4506604409707170077136555010018549819192e-5, - 0.01422519127192419234315002746252160965831, - -0.5926941084905061794445733628891024027949, - 4.408830289125943377923077727900630927902, - -9.8907772644920670589288081640128194231, - 6.565936202082889535528455955485877361223, -} - -const lanczosG = 6.024680040776729583740234375 - -func lanczosSum(x float64) float64 { - return ratevl(x, - lanczosNum[:], - len(lanczosNum)-1, - lanczosDenom[:], - len(lanczosDenom)-1) -} - -func lanczosSumExpgScaled(x float64) float64 { - return ratevl(x, - lanczosSumExpgScaledNum[:], - len(lanczosSumExpgScaledNum)-1, - lanczosSumExpgScaledDenom[:], - len(lanczosSumExpgScaledDenom)-1) -} - -func lanczosSumNear1(dx float64) float64 { - var result float64 - - for i, val := range lanczosSumNear1D { - k := float64(i + 1) - result += (-val * dx) / (k*dx + k*k) - } - - return result -} - -func lanczosSumNear2(dx float64) float64 { - var result float64 - x := dx + 2 - - for i, val := range lanczosSumNear2D { - k := float64(i + 1) - result += (-val * dx) / (x + k*x + k*k - 1) - } - - return result -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go deleted file mode 100644 index 03910ff8..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/ndtri.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright ©2016 The Gonum Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* - * Cephes Math Library Release 2.1: January, 1989 - * Copyright 1984, 1987, 1989 by Stephen L. Moshier - * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 - */ - -package cephes - -import "math" - -// TODO(btracey): There is currently an implementation of this functionality -// in gonum/stat/distuv. Find out which implementation is better, and rectify -// by having distuv call this, or moving this implementation into -// gonum/mathext/internal/gonum. - -// math.Sqrt(2*pi) -const s2pi = 2.50662827463100050242e0 - -// approximation for 0 <= |y - 0.5| <= 3/8 -var P0 = [5]float64{ - -5.99633501014107895267e1, - 9.80010754185999661536e1, - -5.66762857469070293439e1, - 1.39312609387279679503e1, - -1.23916583867381258016e0, -} - -var Q0 = [8]float64{ - /* 1.00000000000000000000E0, */ - 1.95448858338141759834e0, - 4.67627912898881538453e0, - 8.63602421390890590575e1, - -2.25462687854119370527e2, - 2.00260212380060660359e2, - -8.20372256168333339912e1, - 1.59056225126211695515e1, - -1.18331621121330003142e0, -} - -// Approximation for interval z = math.Sqrt(-2 log y ) between 2 and 8 -// i.e., y between exp(-2) = .135 and exp(-32) = 1.27e-14. -var P1 = [9]float64{ - 4.05544892305962419923e0, - 3.15251094599893866154e1, - 5.71628192246421288162e1, - 4.40805073893200834700e1, - 1.46849561928858024014e1, - 2.18663306850790267539e0, - -1.40256079171354495875e-1, - -3.50424626827848203418e-2, - -8.57456785154685413611e-4, -} - -var Q1 = [8]float64{ - /* 1.00000000000000000000E0, */ - 1.57799883256466749731e1, - 4.53907635128879210584e1, - 4.13172038254672030440e1, - 1.50425385692907503408e1, - 2.50464946208309415979e0, - -1.42182922854787788574e-1, - -3.80806407691578277194e-2, - -9.33259480895457427372e-4, -} - -// Approximation for interval z = math.Sqrt(-2 log y ) between 8 and 64 -// i.e., y between exp(-32) = 1.27e-14 and exp(-2048) = 3.67e-890. -var P2 = [9]float64{ - 3.23774891776946035970e0, - 6.91522889068984211695e0, - 3.93881025292474443415e0, - 1.33303460815807542389e0, - 2.01485389549179081538e-1, - 1.23716634817820021358e-2, - 3.01581553508235416007e-4, - 2.65806974686737550832e-6, - 6.23974539184983293730e-9, -} - -var Q2 = [8]float64{ - /* 1.00000000000000000000E0, */ - 6.02427039364742014255e0, - 3.67983563856160859403e0, - 1.37702099489081330271e0, - 2.16236993594496635890e-1, - 1.34204006088543189037e-2, - 3.28014464682127739104e-4, - 2.89247864745380683936e-6, - 6.79019408009981274425e-9, -} - -// Ndtri returns the argument, x, for which the area under the -// Gaussian probability density function (integrated from -// minus infinity to x) is equal to y. -func Ndtri(y0 float64) float64 { - // For small arguments 0 < y < exp(-2), the program computes - // z = math.Sqrt( -2.0 * math.Log(y) ); then the approximation is - // x = z - math.Log(z)/z - (1/z) P(1/z) / Q(1/z). - // There are two rational functions P/Q, one for 0 < y < exp(-32) - // and the other for y up to exp(-2). For larger arguments, - // w = y - 0.5, and x/math.Sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). - var x, y, z, y2, x0, x1 float64 - var code int - - if y0 <= 0.0 { - if y0 < 0 { - panic(paramOutOfBounds) - } - return math.Inf(-1) - } - if y0 >= 1.0 { - if y0 > 1 { - panic(paramOutOfBounds) - } - return math.Inf(1) - } - code = 1 - y = y0 - if y > (1.0 - 0.13533528323661269189) { /* 0.135... = exp(-2) */ - y = 1.0 - y - code = 0 - } - - if y > 0.13533528323661269189 { - y = y - 0.5 - y2 = y * y - x = y + y*(y2*polevl(y2, P0[:], 4)/p1evl(y2, Q0[:], 8)) - x = x * s2pi - return (x) - } - - x = math.Sqrt(-2.0 * math.Log(y)) - x0 = x - math.Log(x)/x - - z = 1.0 / x - if x < 8.0 { /* y > exp(-32) = 1.2664165549e-14 */ - x1 = z * polevl(z, P1[:], 8) / p1evl(z, Q1[:], 8) - } else { - x1 = z * polevl(z, P2[:], 8) / p1evl(z, Q2[:], 8) - } - x = x0 - x1 - if code != 0 { - x = -x - } - return (x) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go deleted file mode 100644 index aec399f3..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/polevl.go +++ /dev/null @@ -1,84 +0,0 @@ -// Derived from SciPy's special/cephes/polevl.h -// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/polevl.h -// Made freely available by Stephen L. Moshier without support or guarantee. - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Copyright ©1984, ©1987, ©1988 by Stephen L. Moshier -// Portions Copyright ©2016 The Gonum Authors. All rights reserved. - -package cephes - -import "math" - -// polevl evaluates a polynomial of degree N -// -// y = c_0 + c_1 x_1 + c_2 x_2^2 ... -// -// where the coefficients are stored in reverse order, i.e. coef[0] = c_n and -// coef[n] = c_0. -func polevl(x float64, coef []float64, n int) float64 { - ans := coef[0] - for i := 1; i <= n; i++ { - ans = ans*x + coef[i] - } - return ans -} - -// p1evl is the same as polevl, except c_n is assumed to be 1 and is not included -// in the slice. -func p1evl(x float64, coef []float64, n int) float64 { - ans := x + coef[0] - for i := 1; i <= n-1; i++ { - ans = ans*x + coef[i] - } - return ans -} - -// ratevl evaluates a rational function -func ratevl(x float64, num []float64, m int, denom []float64, n int) float64 { - // Source: Holin et. al., "Polynomial and Rational Function Evaluation", - // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/roots/rational.html - absx := math.Abs(x) - - var dir, idx int - var y float64 - if absx > 1 { - // Evaluate as a polynomial in 1/x - dir = -1 - idx = m - y = 1 / x - } else { - dir = 1 - idx = 0 - y = x - } - - // Evaluate the numerator - numAns := num[idx] - idx += dir - for i := 0; i < m; i++ { - numAns = numAns*y + num[idx] - idx += dir - } - - // Evaluate the denominator - if absx > 1 { - idx = n - } else { - idx = 0 - } - - denomAns := denom[idx] - idx += dir - for i := 0; i < n; i++ { - denomAns = denomAns*y + denom[idx] - idx += dir - } - - if absx > 1 { - pow := float64(n - m) - return math.Pow(x, pow) * numAns / denomAns - } - return numAns / denomAns -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/staticcheck.conf b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/staticcheck.conf deleted file mode 100644 index e7e254ff..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/staticcheck.conf +++ /dev/null @@ -1 +0,0 @@ -checks = [] diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go deleted file mode 100644 index 3996e7e5..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/unity.go +++ /dev/null @@ -1,184 +0,0 @@ -// Derived from SciPy's special/cephes/unity.c -// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/unity.c -// Made freely available by Stephen L. Moshier without support or guarantee. - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Copyright ©1984, ©1996 by Stephen L. Moshier -// Portions Copyright ©2016 The Gonum Authors. All rights reserved. - -package cephes - -import "math" - -// Relative error approximations for function arguments near unity. -// log1p(x) = log(1+x) -// expm1(x) = exp(x) - 1 -// cosm1(x) = cos(x) - 1 -// lgam1p(x) = lgam(1+x) - -const ( - invSqrt2 = 1 / math.Sqrt2 - pi4 = math.Pi / 4 - euler = 0.577215664901532860606512090082402431 // Euler constant -) - -// Coefficients for -// -// log(1+x) = x - \frac{x^2}{2} + \frac{x^3 lP(x)}{lQ(x)} -// -// for -// -// \frac{1}{\sqrt{2}} <= x < \sqrt{2} -// -// Theoretical peak relative error = 2.32e-20 -var lP = [...]float64{ - 4.5270000862445199635215e-5, - 4.9854102823193375972212e-1, - 6.5787325942061044846969e0, - 2.9911919328553073277375e1, - 6.0949667980987787057556e1, - 5.7112963590585538103336e1, - 2.0039553499201281259648e1, -} - -var lQ = [...]float64{ - 1.5062909083469192043167e1, - 8.3047565967967209469434e1, - 2.2176239823732856465394e2, - 3.0909872225312059774938e2, - 2.1642788614495947685003e2, - 6.0118660497603843919306e1, -} - -// log1p computes -// -// log(1 + x) -func log1p(x float64) float64 { - z := 1 + x - if z < invSqrt2 || z > math.Sqrt2 { - return math.Log(z) - } - z = x * x - z = -0.5*z + x*(z*polevl(x, lP[:], 6)/p1evl(x, lQ[:], 6)) - return x + z -} - -// log1pmx computes -// -// log(1 + x) - x -func log1pmx(x float64) float64 { - if math.Abs(x) < 0.5 { - xfac := x - res := 0.0 - - var term float64 - for n := 2; n < maxIter; n++ { - xfac *= -x - term = xfac / float64(n) - res += term - if math.Abs(term) < machEp*math.Abs(res) { - break - } - } - return res - } - return log1p(x) - x -} - -// Coefficients for -// -// e^x = 1 + \frac{2x eP(x^2)}{eQ(x^2) - eP(x^2)} -// -// for -// -// -0.5 <= x <= 0.5 -var eP = [...]float64{ - 1.2617719307481059087798e-4, - 3.0299440770744196129956e-2, - 9.9999999999999999991025e-1, -} - -var eQ = [...]float64{ - 3.0019850513866445504159e-6, - 2.5244834034968410419224e-3, - 2.2726554820815502876593e-1, - 2.0000000000000000000897e0, -} - -// expm1 computes -// -// expm1(x) = e^x - 1 -func expm1(x float64) float64 { - if math.IsInf(x, 0) { - if math.IsNaN(x) || x > 0 { - return x - } - return -1 - } - if x < -0.5 || x > 0.5 { - return math.Exp(x) - 1 - } - xx := x * x - r := x * polevl(xx, eP[:], 2) - r = r / (polevl(xx, eQ[:], 3) - r) - return r + r -} - -var coscof = [...]float64{ - 4.7377507964246204691685e-14, - -1.1470284843425359765671e-11, - 2.0876754287081521758361e-9, - -2.7557319214999787979814e-7, - 2.4801587301570552304991e-5, - -1.3888888888888872993737e-3, - 4.1666666666666666609054e-2, -} - -// cosm1 computes -// -// cosm1(x) = cos(x) - 1 -func cosm1(x float64) float64 { - if x < -pi4 || x > pi4 { - return math.Cos(x) - 1 - } - xx := x * x - xx = -0.5*xx + xx*xx*polevl(xx, coscof[:], 6) - return xx -} - -// lgam1pTayler computes -// -// lgam(x + 1) -// -// around x = 0 using its Taylor series. -func lgam1pTaylor(x float64) float64 { - if x == 0 { - return 0 - } - res := -euler * x - xfac := -x - for n := 2; n < 42; n++ { - nf := float64(n) - xfac *= -x - coeff := Zeta(nf, 1) * xfac / nf - res += coeff - if math.Abs(coeff) < machEp*math.Abs(res) { - break - } - } - - return res -} - -// lgam1p computes -// -// lgam(x + 1) -func lgam1p(x float64) float64 { - if math.Abs(x) <= 0.5 { - return lgam1pTaylor(x) - } else if math.Abs(x-1) < 0.5 { - return math.Log(x) + lgam1pTaylor(x-1) - } - return lgam(x + 1) -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go b/vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go deleted file mode 100644 index 0efeaa60..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/cephes/zeta.go +++ /dev/null @@ -1,117 +0,0 @@ -// Derived from SciPy's special/cephes/zeta.c -// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/zeta.c -// Made freely available by Stephen L. Moshier without support or guarantee. - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Copyright ©1984, ©1987 by Stephen L. Moshier -// Portions Copyright ©2016 The Gonum Authors. All rights reserved. - -package cephes - -import "math" - -// zetaCoegs are the expansion coefficients for Euler-Maclaurin summation -// formula: -// -// \frac{(2k)!}{B_{2k}} -// -// where -// -// B_{2k} -// -// are Bernoulli numbers. -var zetaCoefs = [...]float64{ - 12.0, - -720.0, - 30240.0, - -1209600.0, - 47900160.0, - -1.307674368e12 / 691, - 7.47242496e10, - -1.067062284288e16 / 3617, - 5.109094217170944e18 / 43867, - -8.028576626982912e20 / 174611, - 1.5511210043330985984e23 / 854513, - -1.6938241367317436694528e27 / 236364091, -} - -// Zeta computes the Riemann zeta function of two arguments. -// -// Zeta(x,q) = \sum_{k=0}^{\infty} (k+q)^{-x} -// -// Note that Zeta returns +Inf if x is 1 and will panic if x is less than 1, -// q is either zero or a negative integer, or q is negative and x is not an -// integer. -// -// Note that: -// -// zeta(x,1) = zetac(x) + 1 -func Zeta(x, q float64) float64 { - // REFERENCE: Gradshteyn, I. S., and I. M. Ryzhik, Tables of Integrals, Series, - // and Products, p. 1073; Academic Press, 1980. - if x == 1 { - return math.Inf(1) - } - - if x < 1 { - panic(paramOutOfBounds) - } - - if q <= 0 { - if q == math.Floor(q) { - panic(errParamFunctionSingularity) - } - if x != math.Floor(x) { - panic(paramOutOfBounds) // Because q^-x not defined - } - } - - // Asymptotic expansion: http://dlmf.nist.gov/25.11#E43 - if q > 1e8 { - return (1/(x-1) + 1/(2*q)) * math.Pow(q, 1-x) - } - - // The Euler-Maclaurin summation formula is used to obtain the expansion: - // Zeta(x,q) = \sum_{k=1}^n (k+q)^{-x} + \frac{(n+q)^{1-x}}{x-1} - \frac{1}{2(n+q)^x} + \sum_{j=1}^{\infty} \frac{B_{2j}x(x+1)...(x+2j)}{(2j)! (n+q)^{x+2j+1}} - // where - // B_{2j} - // are Bernoulli numbers. - // Permit negative q but continue sum until n+q > 9. This case should be - // handled by a reflection formula. If q<0 and x is an integer, there is a - // relation to the polyGamma function. - s := math.Pow(q, -x) - a := q - i := 0 - b := 0.0 - for i < 9 || a <= 9 { - i++ - a += 1.0 - b = math.Pow(a, -x) - s += b - if math.Abs(b/s) < machEp { - return s - } - } - - w := a - s += b * w / (x - 1) - s -= 0.5 * b - a = 1.0 - k := 0.0 - for _, coef := range zetaCoefs { - a *= x + k - b /= w - t := a * b / coef - s = s + t - t = math.Abs(t / s) - if t < machEp { - return s - } - k += 1.0 - a *= x + k - b /= w - k += 1.0 - } - return s -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go deleted file mode 100644 index f1fb3587..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/beta.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum - -import ( - "math" -) - -// Beta returns the value of the complete beta function B(a, b). It is defined as -// -// Γ(a)Γ(b) / Γ(a+b) -// -// Special cases are: -// -// B(a,b) returns NaN if a or b is Inf -// B(a,b) returns NaN if a and b are 0 -// B(a,b) returns NaN if a or b is NaN -// B(a,b) returns NaN if a or b is < 0 -// B(a,b) returns +Inf if a xor b is 0. -// -// See http://mathworld.wolfram.com/BetaFunction.html for more detailed information. -func Beta(a, b float64) float64 { - return math.Exp(Lbeta(a, b)) -} - -// Lbeta returns the natural logarithm of the complete beta function B(a,b). -// Lbeta is defined as: -// -// Ln(Γ(a)Γ(b)/Γ(a+b)) -// -// Special cases are: -// -// Lbeta(a,b) returns NaN if a or b is Inf -// Lbeta(a,b) returns NaN if a and b are 0 -// Lbeta(a,b) returns NaN if a or b is NaN -// Lbeta(a,b) returns NaN if a or b is < 0 -// Lbeta(a,b) returns +Inf if a xor b is 0. -func Lbeta(a, b float64) float64 { - switch { - case math.IsInf(a, +1) || math.IsInf(b, +1): - return math.NaN() - case a == 0 && b == 0: - return math.NaN() - case a < 0 || b < 0: - return math.NaN() - case math.IsNaN(a) || math.IsNaN(b): - return math.NaN() - case a == 0 || b == 0: - return math.Inf(+1) - } - - la, _ := math.Lgamma(a) - lb, _ := math.Lgamma(b) - lab, _ := math.Lgamma(a + b) - return la + lb - lab -} diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go deleted file mode 100644 index cbe6aa23..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright ©2017 The Gonum 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 gonum contains functions implemented by the gonum team. -// It is here to avoid circular imports and/or double coding of functions. -package gonum // import "gonum.org/v1/gonum/mathext/internal/gonum" diff --git a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go b/vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go deleted file mode 100644 index 47e02ce3..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/internal/gonum/gonum.go +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright ©2016 The Gonum 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 gonum diff --git a/vendor/gonum.org/v1/gonum/mathext/mvgamma.go b/vendor/gonum.org/v1/gonum/mathext/mvgamma.go deleted file mode 100644 index 99a9233d..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/mvgamma.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright ©2016 The Gonum 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 mathext - -import "math" - -const ( - logPi = 1.14472988584940017414342735135305871164729481 // http://oeis.org/A053510 -) - -// MvLgamma returns the log of the multivariate Gamma function. Dim -// must be greater than zero, and MvLgamma will return NaN if v < (dim-1)/2. -// -// See https://en.wikipedia.org/wiki/Multivariate_gamma_function for more -// information. -func MvLgamma(v float64, dim int) float64 { - if dim < 1 { - panic("mathext: negative dimension") - } - df := float64(dim) - if v < (df-1)*0.5 { - return math.NaN() - } - ans := df * (df - 1) * 0.25 * logPi - for i := 1; i <= dim; i++ { - lg, _ := math.Lgamma(v + float64(1-i)*0.5) - ans += lg - } - return ans -} diff --git a/vendor/gonum.org/v1/gonum/mathext/roots.go b/vendor/gonum.org/v1/gonum/mathext/roots.go deleted file mode 100644 index 120ce6ef..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/roots.go +++ /dev/null @@ -1,181 +0,0 @@ -// Derived from SciPy's special/c_misc/fsolve.c and special/c_misc/misc.h -// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/fsolve.c -// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/misc.h - -// Copyright ©2017 The Gonum 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 mathext - -import "math" - -type objectiveFunc func(float64, []float64) float64 - -type fSolveResult uint8 - -const ( - // An exact solution was found, in which case the first point on the - // interval is the value - fSolveExact fSolveResult = iota + 1 - // Interval width is less than the tolerance - fSolveConverged - // Root-finding didn't converge in a set number of iterations - fSolveMaxIterations -) - -const ( - machEp = 1.0 / (1 << 53) -) - -// falsePosition uses a combination of bisection and false position to find a -// root of a function within a given interval. This is guaranteed to converge, -// and always keeps a bounding interval, unlike Newton's method. Inputs are: -// -// x1, x2: initial bounding interval -// f1, f2: value of f() at x1 and x2 -// absErr, relErr: absolute and relative errors on the bounding interval -// bisectTil: if > 0.0, perform bisection until the width of the bounding -// interval is less than this -// f, fExtra: function to find root of is f(x, fExtra) -// -// Returns: -// -// result: whether an exact root was found, the process converged to a -// bounding interval small than the required error, or the max number -// of iterations was hit -// bestX: best root approximation -// bestF: function value at bestX -// errEst: error estimation -func falsePosition(x1, x2, f1, f2, absErr, relErr, bisectTil float64, f objectiveFunc, fExtra []float64) (fSolveResult, float64, float64, float64) { - // The false position steps are either unmodified, or modified with the - // Anderson-Bjorck method as appropriate. Theoretically, this has a "speed of - // convergence" of 1.7 (bisection is 1, Newton is 2). - // Note that this routine was designed initially to work with gammaincinv, so - // it may not be tuned right for other problems. Don't use it blindly. - - if f1*f2 >= 0 { - panic("Initial interval is not a bounding interval") - } - - const ( - maxIterations = 100 - bisectIter = 4 - bisectWidth = 4.0 - ) - - const ( - bisect = iota + 1 - falseP - ) - - var state uint8 - if bisectTil > 0 { - state = bisect - } else { - state = falseP - } - - gamma := 1.0 - - w := math.Abs(x2 - x1) - lastBisectWidth := w - - var nFalseP int - var x3, f3, bestX, bestF float64 - for i := 0; i < maxIterations; i++ { - switch state { - case bisect: - x3 = 0.5 * (x1 + x2) - if x3 == x1 || x3 == x2 { - // i.e., x1 and x2 are successive floating-point numbers - bestX = x3 - if x3 == x1 { - bestF = f1 - } else { - bestF = f2 - } - return fSolveConverged, bestX, bestF, w - } - - f3 = f(x3, fExtra) - if f3 == 0 { - return fSolveExact, x3, f3, w - } - - if f3*f2 < 0 { - x1 = x2 - f1 = f2 - } - x2 = x3 - f2 = f3 - w = math.Abs(x2 - x1) - lastBisectWidth = w - if bisectTil > 0 { - if w < bisectTil { - bisectTil = -1.0 - gamma = 1.0 - nFalseP = 0 - state = falseP - } - } else { - gamma = 1.0 - nFalseP = 0 - state = falseP - } - case falseP: - s12 := (f2 - gamma*f1) / (x2 - x1) - x3 = x2 - f2/s12 - f3 = f(x3, fExtra) - if f3 == 0 { - return fSolveExact, x3, f3, w - } - - nFalseP++ - if f3*f2 < 0 { - gamma = 1.0 - x1 = x2 - f1 = f2 - } else { - // Anderson-Bjorck method - g := 1.0 - f3/f2 - if g <= 0 { - g = 0.5 - } - gamma *= g - } - x2 = x3 - f2 = f3 - w = math.Abs(x2 - x1) - - // Sanity check. For every 4 false position checks, see if we really are - // decreasing the interval by comparing to what bisection would have - // achieved (or, rather, a bit more lenient than that -- interval - // decreased by 4 instead of by 16, as the fp could be decreasing gamma - // for a bit). Note that this should guarantee convergence, as it makes - // sure that we always end up decreasing the interval width with a - // bisection. - if nFalseP > bisectIter { - if w*bisectWidth > lastBisectWidth { - state = bisect - } - nFalseP = 0 - lastBisectWidth = w - } - } - - tol := absErr + relErr*math.Max(math.Max(math.Abs(x1), math.Abs(x2)), 1.0) - if w <= tol { - if math.Abs(f1) < math.Abs(f2) { - bestX = x1 - bestF = f1 - } else { - bestX = x2 - bestF = f2 - } - return fSolveConverged, bestX, bestF, w - } - } - - return fSolveMaxIterations, x3, f3, w -} diff --git a/vendor/gonum.org/v1/gonum/mathext/zeta.go b/vendor/gonum.org/v1/gonum/mathext/zeta.go deleted file mode 100644 index 23a87fae..00000000 --- a/vendor/gonum.org/v1/gonum/mathext/zeta.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright ©2016 The Gonum 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 mathext - -import "gonum.org/v1/gonum/mathext/internal/cephes" - -// Zeta computes the Riemann zeta function of two arguments. -// -// Zeta(x,q) = \sum_{k=0}^{\infty} (k+q)^{-x} -// -// Note that Zeta returns +Inf if x is 1 and will panic if x is less than 1, -// q is either zero or a negative integer, or q is negative and x is not an -// integer. -// -// See http://mathworld.wolfram.com/HurwitzZetaFunction.html -// or https://en.wikipedia.org/wiki/Multiple_zeta_function#Two_parameters_case -// for more detailed information. -func Zeta(x, q float64) float64 { - return cephes.Zeta(x, q) -} diff --git a/vendor/gonum.org/v1/gonum/stat/README.md b/vendor/gonum.org/v1/gonum/stat/README.md deleted file mode 100644 index 7156dc50..00000000 --- a/vendor/gonum.org/v1/gonum/stat/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Gonum stat - -[![go.dev reference](https://pkg.go.dev/badge/gonum.org/v1/gonum/stat)](https://pkg.go.dev/gonum.org/v1/gonum/stat) -[![GoDoc](https://godocs.io/gonum.org/v1/gonum/stat?status.svg)](https://godocs.io/gonum.org/v1/gonum/stat) - -Package stat is a statistics package for the Go language. diff --git a/vendor/gonum.org/v1/gonum/stat/combin/combin.go b/vendor/gonum.org/v1/gonum/stat/combin/combin.go deleted file mode 100644 index b5814171..00000000 --- a/vendor/gonum.org/v1/gonum/stat/combin/combin.go +++ /dev/null @@ -1,683 +0,0 @@ -// Copyright ©2016 The Gonum 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 combin - -import ( - "math" - "sort" -) - -const ( - errNegInput = "combin: negative input" - badSetSize = "combin: n < k" - badInput = "combin: wrong input slice length" - errNonpositiveDimension = "combin: non-positive dimension" -) - -// Binomial returns the binomial coefficient of (n,k), also commonly referred to -// as "n choose k". -// -// The binomial coefficient, C(n,k), is the number of unordered combinations of -// k elements in a set that is n elements big, and is defined as -// -// C(n,k) = n!/((n-k)!k!) -// -// n and k must be non-negative with n >= k, otherwise Binomial will panic. -// No check is made for overflow. -func Binomial(n, k int) int { - if n < 0 || k < 0 { - panic(errNegInput) - } - if n < k { - panic(badSetSize) - } - // (n,k) = (n, n-k) - if k > n/2 { - k = n - k - } - b := 1 - for i := 1; i <= k; i++ { - b = (n - k + i) * b / i - } - return b -} - -// GeneralizedBinomial returns the generalized binomial coefficient of (n, k), -// defined as -// -// Γ(n+1) / (Γ(k+1) Γ(n-k+1)) -// -// where Γ is the Gamma function. GeneralizedBinomial is useful for continuous -// relaxations of the binomial coefficient, or when the binomial coefficient value -// may overflow int. In the latter case, one may use math/big for an exact -// computation. -// -// n and k must be non-negative with n >= k, otherwise GeneralizedBinomial will panic. -func GeneralizedBinomial(n, k float64) float64 { - return math.Exp(LogGeneralizedBinomial(n, k)) -} - -// LogGeneralizedBinomial returns the log of the generalized binomial coefficient. -// See GeneralizedBinomial for more information. -func LogGeneralizedBinomial(n, k float64) float64 { - if n < 0 || k < 0 { - panic(errNegInput) - } - if n < k { - panic(badSetSize) - } - a, _ := math.Lgamma(n + 1) - b, _ := math.Lgamma(k + 1) - c, _ := math.Lgamma(n - k + 1) - return a - b - c -} - -// CombinationGenerator generates combinations iteratively. The Combinations -// function may be called to generate all combinations collectively. -type CombinationGenerator struct { - n int - k int - previous []int - remaining int -} - -// NewCombinationGenerator returns a CombinationGenerator for generating the -// combinations of k elements from a set of size n. -// -// n and k must be non-negative with n >= k, otherwise NewCombinationGenerator -// will panic. -func NewCombinationGenerator(n, k int) *CombinationGenerator { - return &CombinationGenerator{ - n: n, - k: k, - remaining: Binomial(n, k), - } -} - -// Next advances the iterator if there are combinations remaining to be generated, -// and returns false if all combinations have been generated. Next must be called -// to initialize the first value before calling Combination or Combination will -// panic. The value returned by Combination is only changed during calls to Next. -func (c *CombinationGenerator) Next() bool { - if c.remaining <= 0 { - // Next is called before combination, so c.remaining is set to zero before - // Combination is called. Thus, Combination cannot panic on zero, and a - // second sentinel value is needed. - c.remaining = -1 - return false - } - if c.previous == nil { - c.previous = make([]int, c.k) - for i := range c.previous { - c.previous[i] = i - } - } else { - nextCombination(c.previous, c.n, c.k) - } - c.remaining-- - return true -} - -// Combination returns the current combination. If dst is non-nil, it must have -// length k and the result will be stored in-place into dst. If dst -// is nil a new slice will be allocated and returned. If all of the combinations -// have already been constructed (Next() returns false), Combination will panic. -// -// Next must be called to initialize the first value before calling Combination -// or Combination will panic. The value returned by Combination is only changed -// during calls to Next. -func (c *CombinationGenerator) Combination(dst []int) []int { - if c.remaining == -1 { - panic("combin: all combinations have been generated") - } - if c.previous == nil { - panic("combin: Combination called before Next") - } - if dst == nil { - dst = make([]int, c.k) - } else if len(dst) != c.k { - panic(badInput) - } - copy(dst, c.previous) - return dst -} - -// Combinations generates all of the combinations of k elements from a -// set of size n. The returned slice has length Binomial(n,k) and each inner slice -// has length k. -// -// n and k must be non-negative with n >= k, otherwise Combinations will panic. -// -// CombinationGenerator may alternatively be used to generate the combinations -// iteratively instead of collectively, or IndexToCombination for random access. -func Combinations(n, k int) [][]int { - combins := Binomial(n, k) - data := make([][]int, combins) - if len(data) == 0 { - return data - } - data[0] = make([]int, k) - for i := range data[0] { - data[0][i] = i - } - for i := 1; i < combins; i++ { - next := make([]int, k) - copy(next, data[i-1]) - nextCombination(next, n, k) - data[i] = next - } - return data -} - -// nextCombination generates the combination after s, overwriting the input value. -func nextCombination(s []int, n, k int) { - for j := k - 1; j >= 0; j-- { - if s[j] == n+j-k { - continue - } - s[j]++ - for l := j + 1; l < k; l++ { - s[l] = s[j] + l - j - } - break - } -} - -// CombinationIndex returns the index of the given combination. -// -// The functions CombinationIndex and IndexToCombination define a bijection -// between the integers and the Binomial(n, k) number of possible combinations. -// CombinationIndex returns the inverse of IndexToCombination. -// -// CombinationIndex panics if comb is not a sorted combination of the first -// [0,n) integers, if n or k are negative, or if k is greater than n. -func CombinationIndex(comb []int, n, k int) int { - if n < 0 || k < 0 { - panic(errNegInput) - } - if n < k { - panic(badSetSize) - } - if len(comb) != k { - panic("combin: bad length combination") - } - if !sort.IntsAreSorted(comb) { - panic("combin: input combination is not sorted") - } - contains := make(map[int]struct{}, k) - for _, v := range comb { - contains[v] = struct{}{} - } - if len(contains) != k { - panic("combin: comb contains non-unique elements") - } - // This algorithm iterates in reverse lexicograhpic order. - // Flip the index and values to swap the order. - rev := make([]int, k) - for i, v := range comb { - rev[len(comb)-i-1] = n - v - 1 - } - idx := 0 - for i, v := range rev { - if v >= i+1 { - idx += Binomial(v, i+1) - } - } - return Binomial(n, k) - 1 - idx -} - -// IndexToCombination returns the combination corresponding to the given index. -// -// The functions CombinationIndex and IndexToCombination define a bijection -// between the integers and the Binomial(n, k) number of possible combinations. -// IndexToCombination returns the inverse of CombinationIndex (up to the order -// of the elements). -// -// The combination is stored in-place into dst if dst is non-nil, otherwise -// a new slice is allocated and returned. -// -// IndexToCombination panics if n or k are negative, if k is greater than n, -// or if idx is not in [0, Binomial(n,k)-1]. IndexToCombination will also panic -// if dst is non-nil and len(dst) is not k. -func IndexToCombination(dst []int, idx, n, k int) []int { - if idx < 0 || idx >= Binomial(n, k) { - panic("combin: invalid index") - } - if dst == nil { - dst = make([]int, k) - } else if len(dst) != k { - panic(badInput) - } - // The base algorithm indexes in reverse lexicographic order - // flip the values and the index. - idx = Binomial(n, k) - 1 - idx - for i := range dst { - // Find the largest number m such that Binomial(m, k-i) <= idx. - // This is one less than the first number such that it is larger. - m := sort.Search(n, func(m int) bool { - if m < k-i { - return false - } - return Binomial(m, k-i) > idx - }) - m-- - // Normally this is put m into the last free spot, but we - // reverse the index and the value. - dst[i] = n - m - 1 - if m >= k-i { - idx -= Binomial(m, k-i) - } - } - return dst -} - -// Cartesian returns the Cartesian product of the slices in data. The Cartesian -// product of two sets is the set of all combinations of the items. For example, -// given the input -// -// []int{2, 3, 1} -// -// the returned matrix will be -// -// [ 0 0 0 ] -// [ 0 1 0 ] -// [ 0 2 0 ] -// [ 1 0 0 ] -// [ 1 1 0 ] -// [ 1 2 0 ] -// -// Cartesian panics if any of the provided lengths are less than 1. -func Cartesian(lens []int) [][]int { - rows := Card(lens) - if rows == 0 { - panic("combin: empty lengths") - } - out := make([][]int, rows) - for i := 0; i < rows; i++ { - out[i] = SubFor(nil, i, lens) - } - return out -} - -// Card computes the cardinality of the multi-dimensional space whose dimensions have size specified by dims -// All length values must be positive, otherwise this will panic. -func Card(dims []int) int { - if len(dims) == 0 { - return 0 - } - card := 1 - for _, v := range dims { - if v < 0 { - panic("combin: length less than zero") - } - card *= v - } - return card -} - -// NewCartesianGenerator returns a CartesianGenerator for iterating over Cartesian products which are generated on the fly. -// All values in lens must be positive, otherwise this will panic. -func NewCartesianGenerator(lens []int) *CartesianGenerator { - return &CartesianGenerator{ - lens: lens, - rows: Card(lens), - idx: -1, - } -} - -// CartesianGenerator iterates over a Cartesian product set. -type CartesianGenerator struct { - lens []int - rows int - idx int -} - -// Next moves to the next product of the Cartesian set. -// It returns false if the generator reached the end of the Cartesian set end. -func (g *CartesianGenerator) Next() bool { - if g.idx+1 < g.rows { - g.idx++ - return true - } - g.idx = g.rows - return false -} - -// Product generates one product of the Cartesian set according to the current index which is increased by Next(). -// Next needs to be called at least one time before this method, otherwise it will panic. -func (g *CartesianGenerator) Product(dst []int) []int { - return SubFor(dst, g.idx, g.lens) -} - -// IdxFor converts a multi-dimensional index into a linear index for a -// multi-dimensional space. sub specifies the index for each dimension, and dims -// specifies the size of each dimension. IdxFor is the inverse of SubFor. -// IdxFor panics if any of the entries of sub are negative, any of the entries -// of dim are non-positive, or if sub[i] >= dims[i] for any i. -func IdxFor(sub, dims []int) int { - // The index returned is "row-major", that is the last index of sub is - // continuous. - var idx int - stride := 1 - for i := len(dims) - 1; i >= 0; i-- { - v := sub[i] - d := dims[i] - if d <= 0 { - panic(errNonpositiveDimension) - } - if v < 0 || v >= d { - panic("combin: invalid subscript") - } - idx += v * stride - stride *= d - } - return idx -} - -// SubFor returns the multi-dimensional subscript for the input linear index to -// the multi-dimensional space. dims specifies the size of each dimension, and -// idx specifies the linear index. SubFor is the inverse of IdxFor. -// -// If sub is non-nil the result is stored in-place into sub, and SubFor will panic -// if len(sub) != len(dims). If sub is nil a new slice of the appropriate length -// is allocated. SubFor panics if idx < 0 or if idx is greater than or equal to -// the product of the dimensions. -func SubFor(sub []int, idx int, dims []int) []int { - if sub == nil { - sub = make([]int, len(dims)) - } - if len(sub) != len(dims) { - panic(badInput) - } - if idx < 0 { - panic(errNegInput) - } - stride := 1 - for i := len(dims) - 1; i >= 1; i-- { - stride *= dims[i] - } - for i := 0; i < len(dims)-1; i++ { - v := idx / stride - d := dims[i] - if d < 0 { - panic(errNonpositiveDimension) - } - if v >= dims[i] { - panic("combin: index too large") - } - sub[i] = v - idx -= v * stride - stride /= dims[i+1] - } - if idx > dims[len(sub)-1] { - panic("combin: index too large") - } - sub[len(sub)-1] = idx - return sub -} - -// NumPermutations returns the number of permutations when selecting k -// objects from a set of n objects when the selection order matters. -// No check is made for overflow. -// -// NumPermutations panics if either n or k is negative, or if k is -// greater than n. -func NumPermutations(n, k int) int { - if n < 0 { - panic("combin: n is negative") - } - if k < 0 { - panic("combin: k is negative") - } - if k > n { - panic("combin: k is greater than n") - } - p := 1 - for i := n - k + 1; i <= n; i++ { - p *= i - } - return p -} - -// Permutations generates all of the permutations of k elements from a -// set of size n. The returned slice has length NumPermutations(n, k) -// and each inner slice has length k. -// -// n and k must be non-negative with n >= k, otherwise Permutations will panic. -// -// PermutationGenerator may alternatively be used to generate the permutations -// iteratively instead of collectively, or IndexToPermutation for random access. -func Permutations(n, k int) [][]int { - nPerms := NumPermutations(n, k) - data := make([][]int, nPerms) - if len(data) == 0 { - return data - } - for i := 0; i < nPerms; i++ { - data[i] = IndexToPermutation(nil, i, n, k) - } - return data -} - -// PermutationGenerator generates permutations iteratively. The Permutations -// function may be called to generate all permutations collectively. -type PermutationGenerator struct { - n int - k int - nPerm int - idx int - permutation []int -} - -// NewPermutationGenerator returns a PermutationGenerator for generating the -// permutations of k elements from a set of size n. -// -// n and k must be non-negative with n >= k, otherwise NewPermutationGenerator -// will panic. -func NewPermutationGenerator(n, k int) *PermutationGenerator { - return &PermutationGenerator{ - n: n, - k: k, - nPerm: NumPermutations(n, k), - idx: -1, - permutation: make([]int, k), - } -} - -// Next advances the iterator if there are permutations remaining to be generated, -// and returns false if all permutations have been generated. Next must be called -// to initialize the first value before calling Permutation or Permutation will -// panic. The value returned by Permutation is only changed during calls to Next. -func (p *PermutationGenerator) Next() bool { - if p.idx >= p.nPerm-1 { - p.idx = p.nPerm // so Permutation can panic. - return false - } - p.idx++ - IndexToPermutation(p.permutation, p.idx, p.n, p.k) - return true -} - -// Permutation returns the current permutation. If dst is non-nil, it must have -// length k and the result will be stored in-place into dst. If dst -// is nil a new slice will be allocated and returned. If all of the permutations -// have already been constructed (Next() returns false), Permutation will panic. -// -// Next must be called to initialize the first value before calling Permutation -// or Permutation will panic. The value returned by Permutation is only changed -// during calls to Next. -func (p *PermutationGenerator) Permutation(dst []int) []int { - if p.idx == p.nPerm { - panic("combin: all permutations have been generated") - } - if p.idx == -1 { - panic("combin: Permutation called before Next") - } - if dst == nil { - dst = make([]int, p.k) - } else if len(dst) != p.k { - panic(badInput) - } - copy(dst, p.permutation) - return dst -} - -// PermutationIndex returns the index of the given permutation. -// -// The functions PermutationIndex and IndexToPermutation define a bijection -// between the integers and the NumPermutations(n, k) number of possible permutations. -// PermutationIndex returns the inverse of IndexToPermutation. -// -// PermutationIndex panics if perm is not a permutation of k of the first -// [0,n) integers, if n or k are negative, or if k is greater than n. -func PermutationIndex(perm []int, n, k int) int { - if n < 0 || k < 0 { - panic(errNegInput) - } - if n < k { - panic(badSetSize) - } - if len(perm) != k { - panic("combin: bad length permutation") - } - contains := make(map[int]struct{}, k) - for _, v := range perm { - if v < 0 || v >= n { - panic("combin: bad element") - } - contains[v] = struct{}{} - } - if len(contains) != k { - panic("combin: perm contains non-unique elements") - } - if n == k { - // The permutation is the ordering of the elements. - return equalPermutationIndex(perm) - } - - // The permutation index is found by finding the combination index and the - // equalPermutation index. The combination index is found by just sorting - // the elements, and the permutation index is the ordering of the size - // of the elements. - tmp := make([]int, len(perm)) - copy(tmp, perm) - idx := make([]int, len(perm)) - for i := range idx { - idx[i] = i - } - s := sortInts{tmp, idx} - sort.Sort(s) - order := make([]int, len(perm)) - for i, v := range idx { - order[v] = i - } - combIdx := CombinationIndex(tmp, n, k) - permIdx := equalPermutationIndex(order) - return combIdx*NumPermutations(k, k) + permIdx -} - -type sortInts struct { - data []int - idx []int -} - -func (s sortInts) Len() int { - return len(s.data) -} - -func (s sortInts) Less(i, j int) bool { - return s.data[i] < s.data[j] -} - -func (s sortInts) Swap(i, j int) { - s.data[i], s.data[j] = s.data[j], s.data[i] - s.idx[i], s.idx[j] = s.idx[j], s.idx[i] -} - -// IndexToPermutation returns the permutation corresponding to the given index. -// -// The functions PermutationIndex and IndexToPermutation define a bijection -// between the integers and the NumPermutations(n, k) number of possible permutations. -// IndexToPermutation returns the inverse of PermutationIndex. -// -// The permutation is stored in-place into dst if dst is non-nil, otherwise -// a new slice is allocated and returned. -// -// IndexToPermutation panics if n or k are negative, if k is greater than n, -// or if idx is not in [0, NumPermutations(n,k)-1]. IndexToPermutation will also panic -// if dst is non-nil and len(dst) is not k. -func IndexToPermutation(dst []int, idx, n, k int) []int { - nPerm := NumPermutations(n, k) - if idx < 0 || idx >= nPerm { - panic("combin: invalid index") - } - if dst == nil { - dst = make([]int, k) - } else if len(dst) != k { - panic(badInput) - } - if n == k { - indexToEqualPermutation(dst, idx) - return dst - } - - // First, we index into the combination (which of the k items to choose) - // and then we index into the n == k permutation of those k items. The - // indexing acts like a matrix with nComb rows and factorial(k) columns. - kPerm := NumPermutations(k, k) - combIdx := idx / kPerm - permIdx := idx % kPerm - comb := IndexToCombination(nil, combIdx, n, k) // Gives us the set of integers. - perm := make([]int, len(dst)) - indexToEqualPermutation(perm, permIdx) // Gives their order. - for i, v := range perm { - dst[i] = comb[v] - } - return dst -} - -// equalPermutationIndex returns the index of the given permutation of the -// first k integers. -func equalPermutationIndex(perm []int) int { - // Note(btracey): This is an n^2 algorithm, but factorial increases - // very quickly (25! overflows int64) so this is not a problem in - // practice. - idx := 0 - for i, u := range perm { - less := 0 - for _, v := range perm[i:] { - if v < u { - less++ - } - } - idx += less * factorial(len(perm)-i-1) - } - return idx -} - -// indexToEqualPermutation returns the permutation for the first len(dst) -// integers for the given index. -func indexToEqualPermutation(dst []int, idx int) { - for i := range dst { - dst[i] = i - } - for i := range dst { - f := factorial(len(dst) - i - 1) - r := idx / f - v := dst[i+r] - copy(dst[i+1:i+r+1], dst[i:i+r]) - dst[i] = v - idx %= f - } -} - -// factorial returns a!. -func factorial(a int) int { - f := 1 - for i := 2; i <= a; i++ { - f *= i - } - return f -} diff --git a/vendor/gonum.org/v1/gonum/stat/combin/doc.go b/vendor/gonum.org/v1/gonum/stat/combin/doc.go deleted file mode 100644 index 496045cd..00000000 --- a/vendor/gonum.org/v1/gonum/stat/combin/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright ©2017 The Gonum 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 combin implements routines involving combinatorics (permutations, -// combinations, etc.). -package combin // import "gonum.org/v1/gonum/stat/combin" diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/alphastable.go b/vendor/gonum.org/v1/gonum/stat/distuv/alphastable.go deleted file mode 100644 index 20ffeac6..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/alphastable.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright ©2020 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// AlphaStable represents an α-stable distribution with four parameters. -// See https://en.wikipedia.org/wiki/Stable_distribution for more information. -type AlphaStable struct { - // Alpha is the stability parameter. - // It is valid within the range 0 < α ≤ 2. - Alpha float64 - // Beta is the skewness parameter. - // It is valid within the range -1 ≤ β ≤ 1. - Beta float64 - // C is the scale parameter. - // It is valid when positive. - C float64 - // Mu is the location parameter. - Mu float64 - Src rand.Source -} - -// ExKurtosis returns the excess kurtosis of the distribution. -// ExKurtosis returns NaN when Alpha != 2. -func (a AlphaStable) ExKurtosis() float64 { - if a.Alpha == 2 { - return 0 - } - return math.NaN() -} - -// Mean returns the mean of the probability distribution. -// Mean returns NaN when Alpha <= 1. -func (a AlphaStable) Mean() float64 { - if a.Alpha > 1 { - return a.Mu - } - return math.NaN() -} - -// Median returns the median of the distribution. -// Median panics when Beta != 0, because then the mode is not analytically -// expressible. -func (a AlphaStable) Median() float64 { - if a.Beta == 0 { - return a.Mu - } - panic("distuv: cannot compute Median for Beta != 0") -} - -// Mode returns the mode of the distribution. -// Mode panics when Beta != 0, because then the mode is not analytically -// expressible. -func (a AlphaStable) Mode() float64 { - if a.Beta == 0 { - return a.Mu - } - panic("distuv: cannot compute Mode for Beta != 0") -} - -// NumParameters returns the number of parameters in the distribution. -func (a AlphaStable) NumParameters() int { - return 4 -} - -// Rand returns a random sample drawn from the distribution. -func (a AlphaStable) Rand() float64 { - // From https://en.wikipedia.org/wiki/Stable_distribution#Simulation_of_stable_variables - const halfPi = math.Pi / 2 - u := Uniform{-halfPi, halfPi, a.Src}.Rand() - w := Exponential{1, a.Src}.Rand() - if a.Alpha == 1 { - f := halfPi + a.Beta*u - x := (f*math.Tan(u) - a.Beta*math.Log(halfPi*w*math.Cos(u)/f)) / halfPi - return a.C*(x+a.Beta*math.Log(a.C)/halfPi) + a.Mu - } - zeta := -a.Beta * math.Tan(halfPi*a.Alpha) - xi := math.Atan(-zeta) / a.Alpha - f := a.Alpha * (u + xi) - g := math.Sqrt(1+zeta*zeta) * math.Pow(math.Cos(u-f)/w, 1-a.Alpha) / math.Cos(u) - x := math.Pow(g, 1/a.Alpha) * math.Sin(f) - return a.C*x + a.Mu -} - -// Skewness returns the skewness of the distribution. -// Skewness returns NaN when Alpha != 2. -func (a AlphaStable) Skewness() float64 { - if a.Alpha == 2 { - return 0 - } - return math.NaN() -} - -// StdDev returns the standard deviation of the probability distribution. -func (a AlphaStable) StdDev() float64 { - return math.Sqrt(a.Variance()) -} - -// Variance returns the variance of the probability distribution. -// Variance returns +Inf when Alpha != 2. -func (a AlphaStable) Variance() float64 { - if a.Alpha == 2 { - return 2 * a.C * a.C - } - return math.Inf(1) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go b/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go deleted file mode 100644 index b220afae..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/bernoulli.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright ©2016 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// Bernoulli represents a random variable whose value is 1 with probability p and -// value of zero with probability 1-P. The value of P must be between 0 and 1. -// More information at https://en.wikipedia.org/wiki/Bernoulli_distribution. -type Bernoulli struct { - P float64 - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (b Bernoulli) CDF(x float64) float64 { - if x < 0 { - return 0 - } - if x < 1 { - return 1 - b.P - } - return 1 -} - -// Entropy returns the entropy of the distribution. -func (b Bernoulli) Entropy() float64 { - if b.P == 0 || b.P == 1 { - return 0 - } - q := 1 - b.P - return -b.P*math.Log(b.P) - q*math.Log(q) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (b Bernoulli) ExKurtosis() float64 { - pq := b.P * (1 - b.P) - return (1 - 6*pq) / pq -} - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (b Bernoulli) LogProb(x float64) float64 { - if x == 0 { - return math.Log(1 - b.P) - } - if x == 1 { - return math.Log(b.P) - } - return math.Inf(-1) -} - -// Mean returns the mean of the probability distribution. -func (b Bernoulli) Mean() float64 { - return b.P -} - -// Median returns the median of the probability distribution. -func (b Bernoulli) Median() float64 { - p := b.P - switch { - case p < 0.5: - return 0 - case p > 0.5: - return 1 - default: - return 0.5 - } -} - -// NumParameters returns the number of parameters in the distribution. -func (Bernoulli) NumParameters() int { - return 1 -} - -// Prob computes the value of the probability distribution at x. -func (b Bernoulli) Prob(x float64) float64 { - if x == 0 { - return 1 - b.P - } - if x == 1 { - return b.P - } - return 0 -} - -// Quantile returns the minimum value of x from amongst all those values whose CDF value exceeds or equals p. -func (b Bernoulli) Quantile(p float64) float64 { - if p < 0 || 1 < p { - panic(badPercentile) - } - if p <= 1-b.P { - return 0 - } - return 1 -} - -// Rand returns a random sample drawn from the distribution. -func (b Bernoulli) Rand() float64 { - var rnd float64 - if b.Src == nil { - rnd = rand.Float64() - } else { - rnd = rand.New(b.Src).Float64() - } - if rnd < b.P { - return 1 - } - return 0 -} - -// Skewness returns the skewness of the distribution. -func (b Bernoulli) Skewness() float64 { - return (1 - 2*b.P) / math.Sqrt(b.P*(1-b.P)) -} - -// StdDev returns the standard deviation of the probability distribution. -func (b Bernoulli) StdDev() float64 { - return math.Sqrt(b.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (b Bernoulli) Survival(x float64) float64 { - if x < 0 { - return 1 - } - if x < 1 { - return b.P - } - return 0 -} - -// Variance returns the variance of the probability distribution. -func (b Bernoulli) Variance() float64 { - return b.P * (1 - b.P) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/beta.go b/vendor/gonum.org/v1/gonum/stat/distuv/beta.go deleted file mode 100644 index 93e9343b..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/beta.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright ©2016 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -// Beta implements the Beta distribution, a two-parameter continuous distribution -// with support between 0 and 1. -// -// The beta distribution has density function -// -// x^(α-1) * (1-x)^(β-1) * Γ(α+β) / (Γ(α)*Γ(β)) -// -// For more information, see https://en.wikipedia.org/wiki/Beta_distribution -type Beta struct { - // Alpha is the left shape parameter of the distribution. Alpha must be greater - // than 0. - Alpha float64 - // Beta is the right shape parameter of the distribution. Beta must be greater - // than 0. - Beta float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative distribution function at x. -func (b Beta) CDF(x float64) float64 { - if x <= 0 { - return 0 - } - if x >= 1 { - return 1 - } - return mathext.RegIncBeta(b.Alpha, b.Beta, x) -} - -// Entropy returns the differential entropy of the distribution. -func (b Beta) Entropy() float64 { - if b.Alpha <= 0 || b.Beta <= 0 { - panic("beta: negative parameters") - } - return mathext.Lbeta(b.Alpha, b.Beta) - (b.Alpha-1)*mathext.Digamma(b.Alpha) - - (b.Beta-1)*mathext.Digamma(b.Beta) + (b.Alpha+b.Beta-2)*mathext.Digamma(b.Alpha+b.Beta) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (b Beta) ExKurtosis() float64 { - num := 6 * ((b.Alpha-b.Beta)*(b.Alpha-b.Beta)*(b.Alpha+b.Beta+1) - b.Alpha*b.Beta*(b.Alpha+b.Beta+2)) - den := b.Alpha * b.Beta * (b.Alpha + b.Beta + 2) * (b.Alpha + b.Beta + 3) - return num / den -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (b Beta) LogProb(x float64) float64 { - if x < 0 || x > 1 { - return math.Inf(-1) - } - - if b.Alpha <= 0 || b.Beta <= 0 { - panic("beta: negative parameters") - } - - lab, _ := math.Lgamma(b.Alpha + b.Beta) - la, _ := math.Lgamma(b.Alpha) - lb, _ := math.Lgamma(b.Beta) - var lx float64 - if b.Alpha != 1 { - lx = (b.Alpha - 1) * math.Log(x) - } - var l1mx float64 - if b.Beta != 1 { - l1mx = (b.Beta - 1) * math.Log(1-x) - } - return lab - la - lb + lx + l1mx -} - -// Mean returns the mean of the probability distribution. -func (b Beta) Mean() float64 { - return b.Alpha / (b.Alpha + b.Beta) -} - -// Mode returns the mode of the distribution. -// -// Mode returns NaN if both parameters are less than or equal to 1 as a special case, -// 0 if only Alpha <= 1 and 1 if only Beta <= 1. -func (b Beta) Mode() float64 { - if b.Alpha <= 1 { - if b.Beta <= 1 { - return math.NaN() - } - return 0 - } - if b.Beta <= 1 { - return 1 - } - return (b.Alpha - 1) / (b.Alpha + b.Beta - 2) -} - -// NumParameters returns the number of parameters in the distribution. -func (b Beta) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (b Beta) Prob(x float64) float64 { - return math.Exp(b.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative distribution function. -func (b Beta) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - return mathext.InvRegIncBeta(b.Alpha, b.Beta, p) -} - -// Rand returns a random sample drawn from the distribution. -func (b Beta) Rand() float64 { - ga := Gamma{Alpha: b.Alpha, Beta: 1, Src: b.Src}.Rand() - gb := Gamma{Alpha: b.Beta, Beta: 1, Src: b.Src}.Rand() - return ga / (ga + gb) -} - -// StdDev returns the standard deviation of the probability distribution. -func (b Beta) StdDev() float64 { - return math.Sqrt(b.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (b Beta) Survival(x float64) float64 { - switch { - case x <= 0: - return 1 - case x >= 1: - return 0 - } - return mathext.RegIncBeta(b.Beta, b.Alpha, 1-x) -} - -// Variance returns the variance of the probability distribution. -func (b Beta) Variance() float64 { - return b.Alpha * b.Beta / ((b.Alpha + b.Beta) * (b.Alpha + b.Beta) * (b.Alpha + b.Beta + 1)) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/binomial.go b/vendor/gonum.org/v1/gonum/stat/distuv/binomial.go deleted file mode 100644 index 4f5f6c7e..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/binomial.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright ©2018 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" - "gonum.org/v1/gonum/stat/combin" -) - -// Binomial implements the binomial distribution, a discrete probability distribution -// that expresses the probability of a given number of successful Bernoulli trials -// out of a total of n, each with success probability p. -// The binomial distribution has the density function: -// -// f(k) = (n choose k) p^k (1-p)^(n-k) -// -// For more information, see https://en.wikipedia.org/wiki/Binomial_distribution. -type Binomial struct { - // N is the total number of Bernoulli trials. N must be greater than 0. - N float64 - // P is the probability of success in any given trial. P must be in [0, 1]. - P float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative distribution function at x. -func (b Binomial) CDF(x float64) float64 { - if x < 0 { - return 0 - } - if x >= b.N { - return 1 - } - x = math.Floor(x) - return mathext.RegIncBeta(b.N-x, x+1, 1-b.P) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (b Binomial) ExKurtosis() float64 { - v := b.P * (1 - b.P) - return (1 - 6*v) / (b.N * v) -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (b Binomial) LogProb(x float64) float64 { - if x < 0 || x > b.N || math.Floor(x) != x { - return math.Inf(-1) - } - lb := combin.LogGeneralizedBinomial(b.N, x) - return lb + x*math.Log(b.P) + (b.N-x)*math.Log(1-b.P) -} - -// Mean returns the mean of the probability distribution. -func (b Binomial) Mean() float64 { - return b.N * b.P -} - -// NumParameters returns the number of parameters in the distribution. -func (Binomial) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (b Binomial) Prob(x float64) float64 { - return math.Exp(b.LogProb(x)) -} - -// Rand returns a random sample drawn from the distribution. -func (b Binomial) Rand() float64 { - // NUMERICAL RECIPES IN C: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43108-5) - // p. 295-6 - // http://www.aip.de/groups/soe/local/numres/bookcpdf/c7-3.pdf - - runif := rand.Float64 - rexp := rand.ExpFloat64 - if b.Src != nil { - rnd := rand.New(b.Src) - runif = rnd.Float64 - rexp = rnd.ExpFloat64 - } - - p := b.P - if p > 0.5 { - p = 1 - p - } - am := b.N * p - - if b.N < 25 { - // Use direct method. - bnl := 0.0 - for i := 0; i < int(b.N); i++ { - if runif() < p { - bnl++ - } - } - if p != b.P { - return b.N - bnl - } - return bnl - } - - if am < 1 { - // Use rejection method with Poisson proposal. - const logM = 2.6e-2 // constant for rejection sampling (https://en.wikipedia.org/wiki/Rejection_sampling) - var bnl float64 - z := -p - pclog := (1 + 0.5*z) * z / (1 + (1+1.0/6*z)*z) // Padé approximant of log(1 + x) - for { - bnl = 0.0 - t := 0.0 - for i := 0; i < int(b.N); i++ { - t += rexp() - if t >= am { - break - } - bnl++ - } - bnlc := b.N - bnl - z = -bnl / b.N - log1p := (1 + 0.5*z) * z / (1 + (1+1.0/6*z)*z) - t = (bnlc+0.5)*log1p + bnl - bnlc*pclog + 1/(12*bnlc) - am + logM // Uses Stirling's expansion of log(n!) - if rexp() >= t { - break - } - } - if p != b.P { - return b.N - bnl - } - return bnl - } - // Original algorithm samples from a Poisson distribution with the - // appropriate expected value. However, the Poisson approximation is - // asymptotic such that the absolute deviation in probability is O(1/n). - // Rejection sampling produces exact variates with at worst less than 3% - // rejection with minimal additional computation. - - // Use rejection method with Cauchy proposal. - g, _ := math.Lgamma(b.N + 1) - plog := math.Log(p) - pclog := math.Log1p(-p) - sq := math.Sqrt(2 * am * (1 - p)) - for { - var em, y float64 - for { - y = math.Tan(math.Pi * runif()) - em = sq*y + am - if em >= 0 && em < b.N+1 { - break - } - } - em = math.Floor(em) - lg1, _ := math.Lgamma(em + 1) - lg2, _ := math.Lgamma(b.N - em + 1) - t := 1.2 * sq * (1 + y*y) * math.Exp(g-lg1-lg2+em*plog+(b.N-em)*pclog) - if runif() <= t { - if p != b.P { - return b.N - em - } - return em - } - } -} - -// Skewness returns the skewness of the distribution. -func (b Binomial) Skewness() float64 { - return (1 - 2*b.P) / b.StdDev() -} - -// StdDev returns the standard deviation of the probability distribution. -func (b Binomial) StdDev() float64 { - return math.Sqrt(b.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (b Binomial) Survival(x float64) float64 { - return 1 - b.CDF(x) -} - -// Variance returns the variance of the probability distribution. -func (b Binomial) Variance() float64 { - return b.N * b.P * (1 - b.P) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/categorical.go b/vendor/gonum.org/v1/gonum/stat/distuv/categorical.go deleted file mode 100644 index f4b77ee4..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/categorical.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright ©2015 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// Categorical is an extension of the Bernoulli distribution where x takes -// values {0, 1, ..., len(w)-1} where w is the weight vector. Categorical must -// be initialized with NewCategorical. -type Categorical struct { - weights []float64 - - // heap is a weight heap. - // - // It keeps a heap-organised sum of remaining - // index weights that are available to be taken - // from. - // - // Each element holds the sum of weights for - // the corresponding index, plus the sum of - // its children's weights; the children of - // an element i can be found at positions - // 2*(i+1)-1 and 2*(i+1). The root of the - // weight heap is at element 0. - // - // See comments in container/heap for an - // explanation of the layout of a heap. - heap []float64 - - src rand.Source -} - -// NewCategorical constructs a new categorical distribution where the probability -// that x equals i is proportional to w[i]. All of the weights must be -// nonnegative, and at least one of the weights must be positive. -func NewCategorical(w []float64, src rand.Source) Categorical { - c := Categorical{ - weights: make([]float64, len(w)), - heap: make([]float64, len(w)), - src: src, - } - c.ReweightAll(w) - return c -} - -// CDF computes the value of the cumulative density function at x. -func (c Categorical) CDF(x float64) float64 { - var cdf float64 - for i, w := range c.weights { - if x < float64(i) { - break - } - cdf += w - } - return cdf / c.heap[0] -} - -// Entropy returns the entropy of the distribution. -func (c Categorical) Entropy() float64 { - var ent float64 - for _, w := range c.weights { - if w == 0 { - continue - } - p := w / c.heap[0] - ent += p * math.Log(p) - } - return -ent -} - -// Len returns the number of values x could possibly take (the length of the -// initial supplied weight vector). -func (c Categorical) Len() int { - return len(c.weights) -} - -// Mean returns the mean of the probability distribution. -func (c Categorical) Mean() float64 { - var mean float64 - for i, v := range c.weights { - mean += float64(i) * v - } - return mean / c.heap[0] -} - -// Prob computes the value of the probability density function at x. -func (c Categorical) Prob(x float64) float64 { - xi := int(x) - if float64(xi) != x { - return 0 - } - if xi < 0 || xi > len(c.weights)-1 { - return 0 - } - return c.weights[xi] / c.heap[0] -} - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (c Categorical) LogProb(x float64) float64 { - return math.Log(c.Prob(x)) -} - -// Rand returns a random draw from the categorical distribution. -func (c Categorical) Rand() float64 { - var r float64 - if c.src == nil { - r = c.heap[0] * rand.Float64() - } else { - r = c.heap[0] * rand.New(c.src).Float64() - } - i := 1 - last := -1 - left := len(c.weights) - for { - if r -= c.weights[i-1]; r <= 0 { - break // Fall within item i-1. - } - i <<= 1 // Move to left child. - if d := c.heap[i-1]; r > d { - r -= d - // If enough r to pass left child, - // move to right child state will - // be caught at break above. - i++ - } - if i == last || left < 0 { - panic("categorical: bad sample") - } - last = i - left-- - } - return float64(i - 1) -} - -// Reweight sets the weight of item idx to w. The input weight must be -// non-negative, and after reweighting at least one of the weights must be -// positive. -func (c Categorical) Reweight(idx int, w float64) { - if w < 0 { - panic("categorical: negative weight") - } - w, c.weights[idx] = c.weights[idx]-w, w - idx++ - for idx > 0 { - c.heap[idx-1] -= w - idx >>= 1 - } - if c.heap[0] <= 0 { - panic("categorical: sum of the weights non-positive") - } -} - -// ReweightAll resets the weights of the distribution. ReweightAll panics if -// len(w) != c.Len. All of the weights must be nonnegative, and at least one of -// the weights must be positive. -func (c Categorical) ReweightAll(w []float64) { - if len(w) != c.Len() { - panic("categorical: length of the slices do not match") - } - for _, v := range w { - if v < 0 { - panic("categorical: negative weight") - } - } - copy(c.weights, w) - c.reset() -} - -func (c Categorical) reset() { - copy(c.heap, c.weights) - for i := len(c.heap) - 1; i > 0; i-- { - // Sometimes 1-based counting makes sense. - c.heap[((i+1)>>1)-1] += c.heap[i] - } - // TODO(btracey): Renormalization for weird weights? - if c.heap[0] <= 0 { - panic("categorical: sum of the weights non-positive") - } -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/chi.go b/vendor/gonum.org/v1/gonum/stat/distuv/chi.go deleted file mode 100644 index 105f5296..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/chi.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright ©2021 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -// Chi implements the χ distribution, a one parameter distribution -// with support on the positive numbers. -// -// The density function is given by -// -// 1/(2^{k/2-1} * Γ(k/2)) * x^{k - 1} * e^{-x^2/2} -// -// For more information, see https://en.wikipedia.org/wiki/Chi_distribution. -type Chi struct { - // K is the shape parameter, corresponding to the degrees of freedom. Must - // be greater than 0. - K float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (c Chi) CDF(x float64) float64 { - return mathext.GammaIncReg(c.K/2, (x*x)/2) -} - -// Entropy returns the differential entropy of the distribution. -func (c Chi) Entropy() float64 { - lg, _ := math.Lgamma(c.K / 2) - return lg + 0.5*(c.K-math.Ln2-(c.K-1)*mathext.Digamma(c.K/2)) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (c Chi) ExKurtosis() float64 { - v := c.Variance() - s := math.Sqrt(v) - return 2 / v * (1 - c.Mean()*s*c.Skewness() - v) -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (c Chi) LogProb(x float64) float64 { - if x < 0 { - return math.Inf(-1) - } - lg, _ := math.Lgamma(c.K / 2) - return (c.K-1)*math.Log(x) - (x*x)/2 - (c.K/2-1)*math.Ln2 - lg -} - -// Mean returns the mean of the probability distribution. -func (c Chi) Mean() float64 { - lg1, _ := math.Lgamma((c.K + 1) / 2) - lg, _ := math.Lgamma(c.K / 2) - return math.Sqrt2 * math.Exp(lg1-lg) -} - -// Median returns the median of the distribution. -func (c Chi) Median() float64 { - return c.Quantile(0.5) -} - -// Mode returns the mode of the distribution. -// -// Mode returns NaN if K is less than one. -func (c Chi) Mode() float64 { - return math.Sqrt(c.K - 1) -} - -// NumParameters returns the number of parameters in the distribution. -func (c Chi) NumParameters() int { - return 1 -} - -// Prob computes the value of the probability density function at x. -func (c Chi) Prob(x float64) float64 { - return math.Exp(c.LogProb(x)) -} - -// Rand returns a random sample drawn from the distribution. -func (c Chi) Rand() float64 { - return math.Sqrt(Gamma{c.K / 2, 0.5, c.Src}.Rand()) -} - -// Quantile returns the inverse of the cumulative distribution function. -func (c Chi) Quantile(p float64) float64 { - if p < 0 || 1 < p { - panic(badPercentile) - } - return math.Sqrt(2 * mathext.GammaIncRegInv(0.5*c.K, p)) -} - -// Skewness returns the skewness of the distribution. -func (c Chi) Skewness() float64 { - v := c.Variance() - s := math.Sqrt(v) - return c.Mean() / (s * v) * (1 - 2*v) -} - -// StdDev returns the standard deviation of the probability distribution. -func (c Chi) StdDev() float64 { - return math.Sqrt(c.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (c Chi) Survival(x float64) float64 { - if x < 0 { - return 1 - } - return mathext.GammaIncRegComp(0.5*c.K, 0.5*(x*x)) -} - -// Variance returns the variance of the probability distribution. -func (c Chi) Variance() float64 { - m := c.Mean() - return math.Max(0, c.K-m*m) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go b/vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go deleted file mode 100644 index 1190803a..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/chisquared.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright ©2016 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -// ChiSquared implements the χ² distribution, a one parameter distribution -// with support on the positive numbers. -// -// The density function is given by -// -// 1/(2^{k/2} * Γ(k/2)) * x^{k/2 - 1} * e^{-x/2} -// -// It is a special case of the Gamma distribution, Γ(k/2, 1/2). -// -// For more information, see https://en.wikipedia.org/wiki/Chi-squared_distribution. -type ChiSquared struct { - // K is the shape parameter, corresponding to the degrees of freedom. Must - // be greater than 0. - K float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (c ChiSquared) CDF(x float64) float64 { - return mathext.GammaIncReg(c.K/2, x/2) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (c ChiSquared) ExKurtosis() float64 { - return 12 / c.K -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (c ChiSquared) LogProb(x float64) float64 { - if x < 0 { - return math.Inf(-1) - } - lg, _ := math.Lgamma(c.K / 2) - return (c.K/2-1)*math.Log(x) - x/2 - (c.K/2)*math.Ln2 - lg -} - -// Mean returns the mean of the probability distribution. -func (c ChiSquared) Mean() float64 { - return c.K -} - -// Mode returns the mode of the distribution. -func (c ChiSquared) Mode() float64 { - return math.Max(c.K-2, 0) -} - -// NumParameters returns the number of parameters in the distribution. -func (c ChiSquared) NumParameters() int { - return 1 -} - -// Prob computes the value of the probability density function at x. -func (c ChiSquared) Prob(x float64) float64 { - return math.Exp(c.LogProb(x)) -} - -// Rand returns a random sample drawn from the distribution. -func (c ChiSquared) Rand() float64 { - return Gamma{c.K / 2, 0.5, c.Src}.Rand() -} - -// Quantile returns the inverse of the cumulative distribution function. -func (c ChiSquared) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - return mathext.GammaIncRegInv(0.5*c.K, p) * 2 -} - -// StdDev returns the standard deviation of the probability distribution. -func (c ChiSquared) StdDev() float64 { - return math.Sqrt(c.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (c ChiSquared) Survival(x float64) float64 { - if x < 0 { - return 1 - } - return mathext.GammaIncRegComp(0.5*c.K, 0.5*x) -} - -// Variance returns the variance of the probability distribution. -func (c ChiSquared) Variance() float64 { - return 2 * c.K -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/constants.go b/vendor/gonum.org/v1/gonum/stat/distuv/constants.go deleted file mode 100644 index 3ebe6350..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/constants.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright ©2014 The Gonum 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 distuv - -const ( - // oneOverRoot2Pi is the value of 1/(2Pi)^(1/2) - // http://www.wolframalpha.com/input/?i=1%2F%282+*+pi%29%5E%281%2F2%29 - oneOverRoot2Pi = 0.39894228040143267793994605993438186847585863116493465766592582967065792589930183850125233390730693643030255886263518268 - - //LogRoot2Pi is the value of log(sqrt(2*Pi)) - logRoot2Pi = 0.91893853320467274178032973640561763986139747363778341281715154048276569592726039769474329863595419762200564662463433744 - negLogRoot2Pi = -logRoot2Pi - log2Pi = 1.8378770664093454835606594728112352797227949472755668 - ln2 = 0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102057068573368552023 - - // Euler–Mascheroni constant. - eulerGamma = 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495146314472498070824809605 - - // sqrt3 is the value of sqrt(3) - // https://www.wolframalpha.com/input/?i=sqrt%283%29 - sqrt3 = 1.7320508075688772935274463415058723669428052538103806280558069794519330169088000370811461867572485756756261414154067030299699450 -) - -const ( - panicNameMismatch = "parameter name mismatch" -) diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/doc.go b/vendor/gonum.org/v1/gonum/stat/distuv/doc.go deleted file mode 100644 index 68aba2d0..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 distuv provides univariate random distribution types. -package distuv // import "gonum.org/v1/gonum/stat/distuv" diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/exponential.go b/vendor/gonum.org/v1/gonum/stat/distuv/exponential.go deleted file mode 100644 index 3acadb43..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/exponential.go +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright ©2014 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/floats" - "gonum.org/v1/gonum/stat" -) - -// Exponential represents the exponential distribution (https://en.wikipedia.org/wiki/Exponential_distribution). -type Exponential struct { - Rate float64 - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (e Exponential) CDF(x float64) float64 { - if x < 0 { - return 0 - } - return -math.Expm1(-e.Rate * x) -} - -// ConjugateUpdate updates the parameters of the distribution from the sufficient -// statistics of a set of samples. The sufficient statistics, suffStat, have been -// observed with nSamples observations. The prior values of the distribution are those -// currently in the distribution, and have been observed with priorStrength samples. -// -// For the exponential distribution, the sufficient statistic is the inverse of -// the mean of the samples. -// The prior is having seen priorStrength[0] samples with inverse mean Exponential.Rate -// As a result of this function, Exponential.Rate is updated based on the weighted -// samples, and priorStrength is modified to include the new number of samples observed. -// -// This function panics if len(suffStat) != e.NumSuffStat() or -// len(priorStrength) != e.NumSuffStat(). -func (e *Exponential) ConjugateUpdate(suffStat []float64, nSamples float64, priorStrength []float64) { - if len(suffStat) != e.NumSuffStat() { - panic("exponential: incorrect suffStat length") - } - if len(priorStrength) != e.NumSuffStat() { - panic("exponential: incorrect priorStrength length") - } - - totalSamples := nSamples + priorStrength[0] - - totalSum := nSamples / suffStat[0] - if !(priorStrength[0] == 0) { - totalSum += priorStrength[0] / e.Rate - } - e.Rate = totalSamples / totalSum - priorStrength[0] = totalSamples -} - -// Entropy returns the entropy of the distribution. -func (e Exponential) Entropy() float64 { - return 1 - math.Log(e.Rate) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (Exponential) ExKurtosis() float64 { - return 6 -} - -// Fit sets the parameters of the probability distribution from the -// data samples x with relative weights w. -// If weights is nil, then all the weights are 1. -// If weights is not nil, then the len(weights) must equal len(samples). -func (e *Exponential) Fit(samples, weights []float64) { - suffStat := make([]float64, e.NumSuffStat()) - nSamples := e.SuffStat(suffStat, samples, weights) - e.ConjugateUpdate(suffStat, nSamples, make([]float64, e.NumSuffStat())) -} - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (e Exponential) LogProb(x float64) float64 { - if x < 0 { - return math.Inf(-1) - } - return math.Log(e.Rate) - e.Rate*x -} - -// Mean returns the mean of the probability distribution. -func (e Exponential) Mean() float64 { - return 1 / e.Rate -} - -// Median returns the median of the probability distribution. -func (e Exponential) Median() float64 { - return math.Ln2 / e.Rate -} - -// Mode returns the mode of the probability distribution. -func (Exponential) Mode() float64 { - return 0 -} - -// NumParameters returns the number of parameters in the distribution. -func (Exponential) NumParameters() int { - return 1 -} - -// NumSuffStat returns the number of sufficient statistics for the distribution. -func (Exponential) NumSuffStat() int { - return 1 -} - -// Prob computes the value of the probability density function at x. -func (e Exponential) Prob(x float64) float64 { - return math.Exp(e.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (e Exponential) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - return -math.Log(1-p) / e.Rate -} - -// Rand returns a random sample drawn from the distribution. -func (e Exponential) Rand() float64 { - var rnd float64 - if e.Src == nil { - rnd = rand.ExpFloat64() - } else { - rnd = rand.New(e.Src).ExpFloat64() - } - return rnd / e.Rate -} - -// Score returns the score function with respect to the parameters of the -// distribution at the input location x. The score function is the derivative -// of the log-likelihood at x with respect to the parameters -// -// (∂/∂θ) log(p(x;θ)) -// -// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise -// Score will panic, and the derivative is stored in-place into deriv. If deriv -// is nil a new slice will be allocated and returned. -// -// The order is [∂LogProb / ∂Rate]. -// -// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. -// -// Special cases: -// -// Score(0) = [NaN] -func (e Exponential) Score(deriv []float64, x float64) []float64 { - if deriv == nil { - deriv = make([]float64, e.NumParameters()) - } - if len(deriv) != e.NumParameters() { - panic(badLength) - } - if x > 0 { - deriv[0] = 1/e.Rate - x - return deriv - } - if x < 0 { - deriv[0] = 0 - return deriv - } - deriv[0] = math.NaN() - return deriv -} - -// ScoreInput returns the score function with respect to the input of the -// distribution at the input location specified by x. The score function is the -// derivative of the log-likelihood -// -// (d/dx) log(p(x)) . -// -// Special cases: -// -// ScoreInput(0) = NaN -func (e Exponential) ScoreInput(x float64) float64 { - if x > 0 { - return -e.Rate - } - if x < 0 { - return 0 - } - return math.NaN() -} - -// Skewness returns the skewness of the distribution. -func (Exponential) Skewness() float64 { - return 2 -} - -// StdDev returns the standard deviation of the probability distribution. -func (e Exponential) StdDev() float64 { - return 1 / e.Rate -} - -// SuffStat computes the sufficient statistics of set of samples to update -// the distribution. The sufficient statistics are stored in place, and the -// effective number of samples are returned. -// -// The exponential distribution has one sufficient statistic, the average rate -// of the samples. -// -// If weights is nil, the weights are assumed to be 1, otherwise panics if -// len(samples) != len(weights). Panics if len(suffStat) != NumSuffStat(). -func (Exponential) SuffStat(suffStat, samples, weights []float64) (nSamples float64) { - if len(weights) != 0 && len(samples) != len(weights) { - panic(badLength) - } - - if len(suffStat) != (Exponential{}).NumSuffStat() { - panic(badSuffStat) - } - - if len(weights) == 0 { - nSamples = float64(len(samples)) - } else { - nSamples = floats.Sum(weights) - } - - mean := stat.Mean(samples, weights) - suffStat[0] = 1 / mean - return nSamples -} - -// Survival returns the survival function (complementary CDF) at x. -func (e Exponential) Survival(x float64) float64 { - if x < 0 { - return 1 - } - return math.Exp(-e.Rate * x) -} - -// setParameters modifies the parameters of the distribution. -func (e *Exponential) setParameters(p []Parameter) { - if len(p) != e.NumParameters() { - panic("exponential: incorrect number of parameters to set") - } - if p[0].Name != "Rate" { - panic("exponential: " + panicNameMismatch) - } - e.Rate = p[0].Value -} - -// Variance returns the variance of the probability distribution. -func (e Exponential) Variance() float64 { - return 1 / (e.Rate * e.Rate) -} - -// parameters returns the parameters of the distribution. -func (e Exponential) parameters(p []Parameter) []Parameter { - nParam := e.NumParameters() - if p == nil { - p = make([]Parameter, nParam) - } else if len(p) != nParam { - panic("exponential: improper parameter length") - } - p[0].Name = "Rate" - p[0].Value = e.Rate - return p -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/f.go b/vendor/gonum.org/v1/gonum/stat/distuv/f.go deleted file mode 100644 index 299fce4f..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/f.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright ©2017 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -// F implements the F-distribution, a two-parameter continuous distribution -// with support over the positive real numbers. -// -// The F-distribution has density function -// -// sqrt(((d1*x)^d1) * d2^d2 / ((d1*x+d2)^(d1+d2))) / (x * B(d1/2,d2/2)) -// -// where B is the beta function. -// -// For more information, see https://en.wikipedia.org/wiki/F-distribution -type F struct { - D1 float64 // Degrees of freedom for the numerator - D2 float64 // Degrees of freedom for the denominator - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (f F) CDF(x float64) float64 { - return mathext.RegIncBeta(f.D1/2, f.D2/2, f.D1*x/(f.D1*x+f.D2)) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -// -// ExKurtosis returns NaN if the D2 parameter is less or equal to 8. -func (f F) ExKurtosis() float64 { - if f.D2 <= 8 { - return math.NaN() - } - return (12 / (f.D2 - 6)) * ((5*f.D2-22)/(f.D2-8) + ((f.D2-4)/f.D1)*((f.D2-2)/(f.D2-8))*((f.D2-2)/(f.D1+f.D2-2))) -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (f F) LogProb(x float64) float64 { - return 0.5*(f.D1*math.Log(f.D1*x)+f.D2*math.Log(f.D2)-(f.D1+f.D2)*math.Log(f.D1*x+f.D2)) - math.Log(x) - mathext.Lbeta(f.D1/2, f.D2/2) -} - -// Mean returns the mean of the probability distribution. -// -// Mean returns NaN if the D2 parameter is less than or equal to 2. -func (f F) Mean() float64 { - if f.D2 <= 2 { - return math.NaN() - } - return f.D2 / (f.D2 - 2) -} - -// Mode returns the mode of the distribution. -// -// Mode returns NaN if the D1 parameter is less than or equal to 2. -func (f F) Mode() float64 { - if f.D1 <= 2 { - return math.NaN() - } - return ((f.D1 - 2) / f.D1) * (f.D2 / (f.D2 + 2)) -} - -// NumParameters returns the number of parameters in the distribution. -func (f F) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (f F) Prob(x float64) float64 { - return math.Exp(f.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative distribution function. -func (f F) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - y := mathext.InvRegIncBeta(0.5*f.D1, 0.5*f.D2, p) - return f.D2 * y / (f.D1 * (1 - y)) -} - -// Rand returns a random sample drawn from the distribution. -func (f F) Rand() float64 { - u1 := ChiSquared{f.D1, f.Src}.Rand() - u2 := ChiSquared{f.D2, f.Src}.Rand() - return (u1 / f.D1) / (u2 / f.D2) -} - -// Skewness returns the skewness of the distribution. -// -// Skewness returns NaN if the D2 parameter is less than or equal to 6. -func (f F) Skewness() float64 { - if f.D2 <= 6 { - return math.NaN() - } - num := (2*f.D1 + f.D2 - 2) * math.Sqrt(8*(f.D2-4)) - den := (f.D2 - 6) * math.Sqrt(f.D1*(f.D1+f.D2-2)) - return num / den -} - -// StdDev returns the standard deviation of the probability distribution. -// -// StdDev returns NaN if the D2 parameter is less than or equal to 4. -func (f F) StdDev() float64 { - if f.D2 <= 4 { - return math.NaN() - } - return math.Sqrt(f.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (f F) Survival(x float64) float64 { - return 1 - f.CDF(x) -} - -// Variance returns the variance of the probability distribution. -// -// Variance returns NaN if the D2 parameter is less than or equal to 4. -func (f F) Variance() float64 { - if f.D2 <= 4 { - return math.NaN() - } - num := 2 * f.D2 * f.D2 * (f.D1 + f.D2 - 2) - den := f.D1 * (f.D2 - 2) * (f.D2 - 2) * (f.D2 - 4) - return num / den -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/gamma.go b/vendor/gonum.org/v1/gonum/stat/distuv/gamma.go deleted file mode 100644 index 739574f5..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/gamma.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright ©2016 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -// Gamma implements the Gamma distribution, a two-parameter continuous distribution -// with support over the positive real numbers. -// -// The gamma distribution has density function -// -// β^α / Γ(α) x^(α-1)e^(-βx) -// -// For more information, see https://en.wikipedia.org/wiki/Gamma_distribution -type Gamma struct { - // Alpha is the shape parameter of the distribution. Alpha must be greater - // than 0. If Alpha == 1, this is equivalent to an exponential distribution. - Alpha float64 - // Beta is the rate parameter of the distribution. Beta must be greater than 0. - // If Beta == 2, this is equivalent to a Chi-Squared distribution. - Beta float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative distribution function at x. -func (g Gamma) CDF(x float64) float64 { - if x < 0 { - return 0 - } - return mathext.GammaIncReg(g.Alpha, g.Beta*x) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (g Gamma) ExKurtosis() float64 { - return 6 / g.Alpha -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (g Gamma) LogProb(x float64) float64 { - if x < 0 { - return math.Inf(-1) - } - a := g.Alpha - b := g.Beta - lg, _ := math.Lgamma(a) - if a == 1 { - return math.Log(b) - lg - b*x - } - return a*math.Log(b) - lg + (a-1)*math.Log(x) - b*x -} - -// Mean returns the mean of the probability distribution. -func (g Gamma) Mean() float64 { - return g.Alpha / g.Beta -} - -// Mode returns the mode of the gamma distribution. -// -// The mode is 0 in the special case where the Alpha (shape) parameter -// is less than 1. -func (g Gamma) Mode() float64 { - if g.Alpha < 1 { - return 0 - } - return (g.Alpha - 1) / g.Beta -} - -// NumParameters returns the number of parameters in the distribution. -func (Gamma) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (g Gamma) Prob(x float64) float64 { - return math.Exp(g.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative distribution function. -func (g Gamma) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - return mathext.GammaIncRegInv(g.Alpha, p) / g.Beta -} - -// Rand returns a random sample drawn from the distribution. -// -// Rand panics if either alpha or beta is <= 0. -func (g Gamma) Rand() float64 { - const ( - // The 0.2 threshold is from https://www4.stat.ncsu.edu/~rmartin/Codes/rgamss.R - // described in detail in https://arxiv.org/abs/1302.1884. - smallAlphaThresh = 0.2 - ) - if g.Beta <= 0 { - panic("gamma: beta <= 0") - } - - unifrnd := rand.Float64 - exprnd := rand.ExpFloat64 - normrnd := rand.NormFloat64 - if g.Src != nil { - rnd := rand.New(g.Src) - unifrnd = rnd.Float64 - exprnd = rnd.ExpFloat64 - normrnd = rnd.NormFloat64 - } - - a := g.Alpha - b := g.Beta - switch { - case a <= 0: - panic("gamma: alpha <= 0") - case a == 1: - // Generate from exponential - return exprnd() / b - case a < smallAlphaThresh: - // Generate using - // Liu, Chuanhai, Martin, Ryan and Syring, Nick. "Simulating from a - // gamma distribution with small shape parameter" - // https://arxiv.org/abs/1302.1884 - // use this reference: http://link.springer.com/article/10.1007/s00180-016-0692-0 - - // Algorithm adjusted to work in log space as much as possible. - lambda := 1/a - 1 - lr := -math.Log1p(1 / lambda / math.E) - for { - e := exprnd() - var z float64 - if e >= -lr { - z = e + lr - } else { - z = -exprnd() / lambda - } - eza := math.Exp(-z / a) - lh := -z - eza - var lEta float64 - if z >= 0 { - lEta = -z - } else { - lEta = -1 + lambda*z - } - if lh-lEta > -exprnd() { - return eza / b - } - } - case a >= smallAlphaThresh: - // Generate using: - // Marsaglia, George, and Wai Wan Tsang. "A simple method for generating - // gamma variables." ACM Transactions on Mathematical Software (TOMS) - // 26.3 (2000): 363-372. - d := a - 1.0/3 - m := 1.0 - if a < 1 { - d += 1.0 - m = math.Pow(unifrnd(), 1/a) - } - c := 1 / (3 * math.Sqrt(d)) - for { - x := normrnd() - v := 1 + x*c - if v <= 0.0 { - continue - } - v = v * v * v - u := unifrnd() - if u < 1.0-0.0331*(x*x)*(x*x) { - return m * d * v / b - } - if math.Log(u) < 0.5*x*x+d*(1-v+math.Log(v)) { - return m * d * v / b - } - } - } - panic("unreachable") -} - -// Survival returns the survival function (complementary CDF) at x. -func (g Gamma) Survival(x float64) float64 { - if x < 0 { - return 1 - } - return mathext.GammaIncRegComp(g.Alpha, g.Beta*x) -} - -// StdDev returns the standard deviation of the probability distribution. -func (g Gamma) StdDev() float64 { - return math.Sqrt(g.Alpha) / g.Beta -} - -// Variance returns the variance of the probability distribution. -func (g Gamma) Variance() float64 { - return g.Alpha / g.Beta / g.Beta -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/general.go b/vendor/gonum.org/v1/gonum/stat/distuv/general.go deleted file mode 100644 index 5b789919..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/general.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright ©2014 The Gonum 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 distuv - -// Parameter represents a parameter of a probability distribution -type Parameter struct { - Name string - Value float64 -} - -const ( - badPercentile = "distuv: percentile out of bounds" - badLength = "distuv: slice length mismatch" - badSuffStat = "distuv: wrong suffStat length" - errNoSamples = "distuv: must have at least one sample" -) - -const ( - expNegOneHalf = 0.6065306597126334236037995349911804534419 // https://oeis.org/A092605 - eulerMascheroni = 0.5772156649015328606065120900824024310421 // https://oeis.org/A001620 - apery = 1.2020569031595942853997381615114499907649 // https://oeis.org/A002117 -) diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/gumbel.go b/vendor/gonum.org/v1/gonum/stat/distuv/gumbel.go deleted file mode 100644 index 7017dd4e..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/gumbel.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright ©2018 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// GumbelRight implements the right-skewed Gumbel distribution, a two-parameter -// continuous distribution with support over the real numbers. The right-skewed -// Gumbel distribution is also sometimes known as the Extreme Value distribution. -// -// The right-skewed Gumbel distribution has density function -// -// 1/beta * exp(-(z + exp(-z))) -// z = (x - mu)/beta -// -// Beta must be greater than 0. -// -// For more information, see https://en.wikipedia.org/wiki/Gumbel_distribution. -type GumbelRight struct { - Mu float64 - Beta float64 - Src rand.Source -} - -func (g GumbelRight) z(x float64) float64 { - return (x - g.Mu) / g.Beta -} - -// CDF computes the value of the cumulative density function at x. -func (g GumbelRight) CDF(x float64) float64 { - z := g.z(x) - return math.Exp(-math.Exp(-z)) -} - -// Entropy returns the differential entropy of the distribution. -func (g GumbelRight) Entropy() float64 { - return math.Log(g.Beta) + eulerMascheroni + 1 -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (g GumbelRight) ExKurtosis() float64 { - return 12.0 / 5 -} - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (g GumbelRight) LogProb(x float64) float64 { - z := g.z(x) - return -math.Log(g.Beta) - z - math.Exp(-z) -} - -// Mean returns the mean of the probability distribution. -func (g GumbelRight) Mean() float64 { - return g.Mu + g.Beta*eulerMascheroni -} - -// Median returns the median of the Gumbel distribution. -func (g GumbelRight) Median() float64 { - return g.Mu - g.Beta*math.Log(math.Ln2) -} - -// Mode returns the mode of the normal distribution. -func (g GumbelRight) Mode() float64 { - return g.Mu -} - -// NumParameters returns the number of parameters in the distribution. -func (GumbelRight) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (g GumbelRight) Prob(x float64) float64 { - return math.Exp(g.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (g GumbelRight) Quantile(p float64) float64 { - if p < 0 || 1 < p { - panic(badPercentile) - } - return g.Mu - g.Beta*math.Log(-math.Log(p)) -} - -// Rand returns a random sample drawn from the distribution. -func (g GumbelRight) Rand() float64 { - var rnd float64 - if g.Src == nil { - rnd = rand.ExpFloat64() - } else { - rnd = rand.New(g.Src).ExpFloat64() - } - return g.Mu - g.Beta*math.Log(rnd) -} - -// Skewness returns the skewness of the distribution. -func (GumbelRight) Skewness() float64 { - return 12 * math.Sqrt(6) * apery / (math.Pi * math.Pi * math.Pi) -} - -// StdDev returns the standard deviation of the probability distribution. -func (g GumbelRight) StdDev() float64 { - return (math.Pi / math.Sqrt(6)) * g.Beta -} - -// Survival returns the survival function (complementary CDF) at x. -func (g GumbelRight) Survival(x float64) float64 { - return 1 - g.CDF(x) -} - -// Variance returns the variance of the probability distribution. -func (g GumbelRight) Variance() float64 { - return math.Pi * math.Pi * g.Beta * g.Beta / 6 -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go b/vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go deleted file mode 100644 index a3cc94bb..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/interfaces.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright ©2015 The Gonum 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 distuv - -// LogProber wraps the LogProb method. -type LogProber interface { - // LogProb returns the natural logarithm of the - // value of the probability density or probability - // mass function at x. - LogProb(x float64) float64 -} - -// Rander wraps the Rand method. -type Rander interface { - // Rand returns a random sample drawn from the distribution. - Rand() float64 -} - -// RandLogProber is the interface that groups the Rander and LogProber methods. -type RandLogProber interface { - Rander - LogProber -} - -// Quantiler wraps the Quantile method. -type Quantiler interface { - // Quantile returns the minimum value of x from amongst - // all those values whose CDF value exceeds or equals p. - Quantile(p float64) float64 -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/inversegamma.go b/vendor/gonum.org/v1/gonum/stat/distuv/inversegamma.go deleted file mode 100644 index 44fe5e6c..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/inversegamma.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright ©2018 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -// InverseGamma implements the inverse gamma distribution, a two-parameter -// continuous distribution with support over the positive real numbers. The -// inverse gamma distribution is the same as the distribution of the reciprocal -// of a gamma distributed random variable. -// -// The inverse gamma distribution has density function -// -// β^α / Γ(α) x^(-α-1)e^(-β/x) -// -// For more information, see https://en.wikipedia.org/wiki/Inverse-gamma_distribution -type InverseGamma struct { - // Alpha is the shape parameter of the distribution. Alpha must be greater than 0. - Alpha float64 - // Beta is the scale parameter of the distribution. Beta must be greater than 0. - Beta float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative distribution function at x. -func (g InverseGamma) CDF(x float64) float64 { - if x < 0 { - return 0 - } - // TODO(btracey): Replace this with a direct call to the upper regularized - // gamma function if mathext gets it. - //return 1 - mathext.GammaInc(g.Alpha, g.Beta/x) - return mathext.GammaIncRegComp(g.Alpha, g.Beta/x) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (g InverseGamma) ExKurtosis() float64 { - if g.Alpha <= 4 { - return math.Inf(1) - } - return (30*g.Alpha - 66) / (g.Alpha - 3) / (g.Alpha - 4) -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (g InverseGamma) LogProb(x float64) float64 { - if x <= 0 { - return math.Inf(-1) - } - a := g.Alpha - b := g.Beta - lg, _ := math.Lgamma(a) - return a*math.Log(b) - lg + (-a-1)*math.Log(x) - b/x -} - -// Mean returns the mean of the probability distribution. -func (g InverseGamma) Mean() float64 { - if g.Alpha <= 1 { - return math.Inf(1) - } - return g.Beta / (g.Alpha - 1) -} - -// Mode returns the mode of the distribution. -func (g InverseGamma) Mode() float64 { - return g.Beta / (g.Alpha + 1) -} - -// NumParameters returns the number of parameters in the distribution. -func (InverseGamma) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (g InverseGamma) Prob(x float64) float64 { - return math.Exp(g.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative distribution function. -func (g InverseGamma) Quantile(p float64) float64 { - if p < 0 || 1 < p { - panic(badPercentile) - } - return (1 / (mathext.GammaIncRegCompInv(g.Alpha, p))) * g.Beta -} - -// Rand returns a random sample drawn from the distribution. -// -// Rand panics if either alpha or beta is <= 0. -func (g InverseGamma) Rand() float64 { - // TODO(btracey): See if there is a more direct way to sample. - return 1 / Gamma(g).Rand() -} - -// Survival returns the survival function (complementary CDF) at x. -func (g InverseGamma) Survival(x float64) float64 { - if x < 0 { - return 1 - } - return mathext.GammaIncReg(g.Alpha, g.Beta/x) -} - -// StdDev returns the standard deviation of the probability distribution. -func (g InverseGamma) StdDev() float64 { - return math.Sqrt(g.Variance()) -} - -// Variance returns the variance of the probability distribution. -func (g InverseGamma) Variance() float64 { - if g.Alpha <= 2 { - return math.Inf(1) - } - v := g.Beta / (g.Alpha - 1) - return v * v / (g.Alpha - 2) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/laplace.go b/vendor/gonum.org/v1/gonum/stat/distuv/laplace.go deleted file mode 100644 index 36d96551..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/laplace.go +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright ©2014 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - "sort" - - "gonum.org/v1/gonum/stat" -) - -// Laplace represents the Laplace distribution (https://en.wikipedia.org/wiki/Laplace_distribution). -type Laplace struct { - Mu float64 // Mean of the Laplace distribution - Scale float64 // Scale of the Laplace distribution - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (l Laplace) CDF(x float64) float64 { - if x < l.Mu { - return 0.5 * math.Exp((x-l.Mu)/l.Scale) - } - return 1 - 0.5*math.Exp(-(x-l.Mu)/l.Scale) -} - -// Entropy returns the entropy of the distribution. -func (l Laplace) Entropy() float64 { - return 1 + math.Log(2*l.Scale) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (l Laplace) ExKurtosis() float64 { - return 3 -} - -// Fit sets the parameters of the probability distribution from the -// data samples x with relative weights w. -// If weights is nil, then all the weights are 1. -// If weights is not nil, then the len(weights) must equal len(samples). -// -// Note: Laplace distribution has no FitPrior because it has no sufficient -// statistics. -func (l *Laplace) Fit(samples, weights []float64) { - if weights != nil && len(samples) != len(weights) { - panic(badLength) - } - - if len(samples) == 0 { - panic(errNoSamples) - } - if len(samples) == 1 { - l.Mu = samples[0] - l.Scale = 0 - return - } - - var ( - sortedSamples []float64 - sortedWeights []float64 - ) - if sort.Float64sAreSorted(samples) { - sortedSamples = samples - sortedWeights = weights - } else { - // Need to copy variables so the input variables aren't effected by the sorting - sortedSamples = make([]float64, len(samples)) - copy(sortedSamples, samples) - sortedWeights := make([]float64, len(samples)) - copy(sortedWeights, weights) - - stat.SortWeighted(sortedSamples, sortedWeights) - } - - // The (weighted) median of the samples is the maximum likelihood estimate - // of the mean parameter - // TODO: Rethink quantile type when stat has more options - l.Mu = stat.Quantile(0.5, stat.Empirical, sortedSamples, sortedWeights) - - // The scale parameter is the average absolute distance - // between the sample and the mean - var absError float64 - var sumWeights float64 - if weights != nil { - for i, v := range samples { - absError += weights[i] * math.Abs(l.Mu-v) - sumWeights += weights[i] - } - l.Scale = absError / sumWeights - } else { - for _, v := range samples { - absError += math.Abs(l.Mu - v) - } - l.Scale = absError / float64(len(samples)) - } -} - -// LogProb computes the natural logarithm of the value of the probability density -// function at x. -func (l Laplace) LogProb(x float64) float64 { - return -math.Ln2 - math.Log(l.Scale) - math.Abs(x-l.Mu)/l.Scale -} - -// parameters returns the parameters of the distribution. -func (l Laplace) parameters(p []Parameter) []Parameter { - nParam := l.NumParameters() - if p == nil { - p = make([]Parameter, nParam) - } else if len(p) != nParam { - panic(badLength) - } - p[0].Name = "Mu" - p[0].Value = l.Mu - p[1].Name = "Scale" - p[1].Value = l.Scale - return p -} - -// Mean returns the mean of the probability distribution. -func (l Laplace) Mean() float64 { - return l.Mu -} - -// Median returns the median of the LaPlace distribution. -func (l Laplace) Median() float64 { - return l.Mu -} - -// Mode returns the mode of the LaPlace distribution. -func (l Laplace) Mode() float64 { - return l.Mu -} - -// NumParameters returns the number of parameters in the distribution. -func (l Laplace) NumParameters() int { - return 2 -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (l Laplace) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - if p < 0.5 { - return l.Mu + l.Scale*math.Log(1+2*(p-0.5)) - } - return l.Mu - l.Scale*math.Log(1-2*(p-0.5)) -} - -// Prob computes the value of the probability density function at x. -func (l Laplace) Prob(x float64) float64 { - return math.Exp(l.LogProb(x)) -} - -// Rand returns a random sample drawn from the distribution. -func (l Laplace) Rand() float64 { - var rnd float64 - if l.Src == nil { - rnd = rand.Float64() - } else { - rnd = rand.New(l.Src).Float64() - } - u := rnd - 0.5 - if u < 0 { - return l.Mu + l.Scale*math.Log(1+2*u) - } - return l.Mu - l.Scale*math.Log(1-2*u) -} - -// Score returns the score function with respect to the parameters of the -// distribution at the input location x. The score function is the derivative -// of the log-likelihood at x with respect to the parameters -// -// (∂/∂θ) log(p(x;θ)) -// -// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise -// Score will panic, and the derivative is stored in-place into deriv. If deriv -// is nil a new slice will be allocated and returned. -// -// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Scale]. -// -// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. -// -// Special cases: -// -// Score(l.Mu) = [NaN, -1/l.Scale] -func (l Laplace) Score(deriv []float64, x float64) []float64 { - if deriv == nil { - deriv = make([]float64, l.NumParameters()) - } - if len(deriv) != l.NumParameters() { - panic(badLength) - } - diff := x - l.Mu - if diff > 0 { - deriv[0] = 1 / l.Scale - } else if diff < 0 { - deriv[0] = -1 / l.Scale - } else { - // must be NaN - deriv[0] = math.NaN() - } - - deriv[1] = math.Abs(diff)/(l.Scale*l.Scale) - 1/l.Scale - return deriv -} - -// ScoreInput returns the score function with respect to the input of the -// distribution at the input location specified by x. The score function is the -// derivative of the log-likelihood -// -// (d/dx) log(p(x)) . -// -// Special cases: -// -// ScoreInput(l.Mu) = NaN -func (l Laplace) ScoreInput(x float64) float64 { - diff := x - l.Mu - if diff == 0 { - return math.NaN() - } - if diff > 0 { - return -1 / l.Scale - } - return 1 / l.Scale -} - -// Skewness returns the skewness of the distribution. -func (Laplace) Skewness() float64 { - return 0 -} - -// StdDev returns the standard deviation of the distribution. -func (l Laplace) StdDev() float64 { - return math.Sqrt2 * l.Scale -} - -// Survival returns the survival function (complementary CDF) at x. -func (l Laplace) Survival(x float64) float64 { - if x < l.Mu { - return 1 - 0.5*math.Exp((x-l.Mu)/l.Scale) - } - return 0.5 * math.Exp(-(x-l.Mu)/l.Scale) -} - -// setParameters modifies the parameters of the distribution. -func (l *Laplace) setParameters(p []Parameter) { - if len(p) != l.NumParameters() { - panic(badLength) - } - if p[0].Name != "Mu" { - panic("laplace: " + panicNameMismatch) - } - if p[1].Name != "Scale" { - panic("laplace: " + panicNameMismatch) - } - l.Mu = p[0].Value - l.Scale = p[1].Value -} - -// Variance returns the variance of the probability distribution. -func (l Laplace) Variance() float64 { - return 2 * l.Scale * l.Scale -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/logistic.go b/vendor/gonum.org/v1/gonum/stat/distuv/logistic.go deleted file mode 100644 index 0392d6cc..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/logistic.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright ©2021 The Gonum 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 distuv - -import ( - "math" -) - -// Logistic implements the Logistic distribution, a two-parameter distribution with support on the real axis. -// Its cumulative distribution function is the logistic function. -// -// General form of probability density function for Logistic distribution is -// -// E(x) / (s * (1 + E(x))^2) -// where E(x) = exp(-(x-μ)/s) -// -// For more information, see https://en.wikipedia.org/wiki/Logistic_distribution. -type Logistic struct { - Mu float64 // Mean value - S float64 // Scale parameter proportional to standard deviation -} - -// CDF computes the value of the cumulative density function at x. -func (l Logistic) CDF(x float64) float64 { - return 1 / (1 + math.Exp(-(x-l.Mu)/l.S)) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (l Logistic) ExKurtosis() float64 { - return 6.0 / 5.0 -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (l Logistic) LogProb(x float64) float64 { - return x - 2*math.Log(math.Exp(x)+1) -} - -// Mean returns the mean of the probability distribution. -func (l Logistic) Mean() float64 { - return l.Mu -} - -// Mode returns the mode of the distribution. -// -// It is same as Mean for Logistic distribution. -func (l Logistic) Mode() float64 { - return l.Mu -} - -// Median returns the median of the distribution. -// -// It is same as Mean for Logistic distribution. -func (l Logistic) Median() float64 { - return l.Mu -} - -// NumParameters returns the number of parameters in the distribution. -// -// Always returns 2. -func (l Logistic) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (l Logistic) Prob(x float64) float64 { - E := math.Exp(-(x - l.Mu) / l.S) - return E / (l.S * math.Pow(1+E, 2)) -} - -// Quantile returns the inverse of the cumulative distribution function. -func (l Logistic) Quantile(p float64) float64 { - return l.Mu + l.S*math.Log(p/(1-p)) -} - -// Skewness returns the skewness of the distribution. -// -// Always 0 for Logistic distribution. -func (l Logistic) Skewness() float64 { - return 0 -} - -// StdDev returns the standard deviation of the probability distribution. -func (l Logistic) StdDev() float64 { - return l.S * math.Pi / sqrt3 -} - -// Survival returns the survival function (complementary CDF) at x. -func (l Logistic) Survival(x float64) float64 { - return 1 - l.CDF(x) -} - -// Variance returns the variance of the probability distribution. -func (l Logistic) Variance() float64 { - return l.S * l.S * math.Pi * math.Pi / 3 -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go b/vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go deleted file mode 100644 index 321c1bd3..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/lognormal.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright ©2015 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// LogNormal represents a random variable whose log is normally distributed. -// The probability density function is given by -// -// 1/(x σ √2π) exp(-(ln(x)-μ)^2)/(2σ^2)) -type LogNormal struct { - Mu float64 - Sigma float64 - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (l LogNormal) CDF(x float64) float64 { - return 0.5 * math.Erfc(-(math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma)) -} - -// Entropy returns the differential entropy of the distribution. -func (l LogNormal) Entropy() float64 { - return 0.5 + 0.5*math.Log(2*math.Pi*l.Sigma*l.Sigma) + l.Mu -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (l LogNormal) ExKurtosis() float64 { - s2 := l.Sigma * l.Sigma - return math.Exp(4*s2) + 2*math.Exp(3*s2) + 3*math.Exp(2*s2) - 6 -} - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (l LogNormal) LogProb(x float64) float64 { - if x < 0 { - return math.Inf(-1) - } - logx := math.Log(x) - normdiff := (logx - l.Mu) / l.Sigma - return -0.5*normdiff*normdiff - logx - math.Log(l.Sigma) - logRoot2Pi -} - -// Mean returns the mean of the probability distribution. -func (l LogNormal) Mean() float64 { - return math.Exp(l.Mu + 0.5*l.Sigma*l.Sigma) -} - -// Median returns the median of the probability distribution. -func (l LogNormal) Median() float64 { - return math.Exp(l.Mu) -} - -// Mode returns the mode of the probability distribution. -func (l LogNormal) Mode() float64 { - return math.Exp(l.Mu - l.Sigma*l.Sigma) -} - -// NumParameters returns the number of parameters in the distribution. -func (LogNormal) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (l LogNormal) Prob(x float64) float64 { - return math.Exp(l.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (l LogNormal) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - // Formula from http://www.math.uah.edu/stat/special/LogNormal.html. - return math.Exp(l.Mu + l.Sigma*UnitNormal.Quantile(p)) -} - -// Rand returns a random sample drawn from the distribution. -func (l LogNormal) Rand() float64 { - var rnd float64 - if l.Src == nil { - rnd = rand.NormFloat64() - } else { - rnd = rand.New(l.Src).NormFloat64() - } - return math.Exp(rnd*l.Sigma + l.Mu) -} - -// Skewness returns the skewness of the distribution. -func (l LogNormal) Skewness() float64 { - s2 := l.Sigma * l.Sigma - return (math.Exp(s2) + 2) * math.Sqrt(math.Exp(s2)-1) -} - -// StdDev returns the standard deviation of the probability distribution. -func (l LogNormal) StdDev() float64 { - return math.Sqrt(l.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (l LogNormal) Survival(x float64) float64 { - return 0.5 * (1 - math.Erf((math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma))) -} - -// Variance returns the variance of the probability distribution. -func (l LogNormal) Variance() float64 { - s2 := l.Sigma * l.Sigma - return (math.Exp(s2) - 1) * math.Exp(2*l.Mu+s2) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/norm.go b/vendor/gonum.org/v1/gonum/stat/distuv/norm.go deleted file mode 100644 index 324b70ec..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/norm.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright ©2014 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/floats" - "gonum.org/v1/gonum/mathext" - "gonum.org/v1/gonum/stat" -) - -// UnitNormal is an instantiation of the normal distribution with Mu = 0 and Sigma = 1. -var UnitNormal = Normal{Mu: 0, Sigma: 1} - -// Normal represents a normal (Gaussian) distribution (https://en.wikipedia.org/wiki/Normal_distribution). -type Normal struct { - Mu float64 // Mean of the normal distribution - Sigma float64 // Standard deviation of the normal distribution - Src rand.Source - - // Needs to be Mu and Sigma and not Mean and StdDev because Normal has functions - // Mean and StdDev -} - -// CDF computes the value of the cumulative density function at x. -func (n Normal) CDF(x float64) float64 { - return 0.5 * math.Erfc(-(x-n.Mu)/(n.Sigma*math.Sqrt2)) -} - -// ConjugateUpdate updates the parameters of the distribution from the sufficient -// statistics of a set of samples. The sufficient statistics, suffStat, have been -// observed with nSamples observations. The prior values of the distribution are those -// currently in the distribution, and have been observed with priorStrength samples. -// -// For the normal distribution, the sufficient statistics are the mean and -// uncorrected standard deviation of the samples. -// The prior is having seen strength[0] samples with mean Normal.Mu -// and strength[1] samples with standard deviation Normal.Sigma. As a result of -// this function, Normal.Mu and Normal.Sigma are updated based on the weighted -// samples, and strength is modified to include the new number of samples observed. -// -// This function panics if len(suffStat) != n.NumSuffStat() or -// len(priorStrength) != n.NumSuffStat(). -func (n *Normal) ConjugateUpdate(suffStat []float64, nSamples float64, priorStrength []float64) { - // TODO: Support prior strength with math.Inf(1) to allow updating with - // a known mean/standard deviation - if len(suffStat) != n.NumSuffStat() { - panic("norm: incorrect suffStat length") - } - if len(priorStrength) != n.NumSuffStat() { - panic("norm: incorrect priorStrength length") - } - - totalMeanSamples := nSamples + priorStrength[0] - totalSum := suffStat[0]*nSamples + n.Mu*priorStrength[0] - - totalVarianceSamples := nSamples + priorStrength[1] - // sample variance - totalVariance := nSamples * suffStat[1] * suffStat[1] - // add prior variance - totalVariance += priorStrength[1] * n.Sigma * n.Sigma - // add cross variance from the difference of the means - meanDiff := (suffStat[0] - n.Mu) - totalVariance += priorStrength[0] * nSamples * meanDiff * meanDiff / totalMeanSamples - - n.Mu = totalSum / totalMeanSamples - n.Sigma = math.Sqrt(totalVariance / totalVarianceSamples) - floats.AddConst(nSamples, priorStrength) -} - -// Entropy returns the differential entropy of the distribution. -func (n Normal) Entropy() float64 { - return 0.5 * (log2Pi + 1 + 2*math.Log(n.Sigma)) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (Normal) ExKurtosis() float64 { - return 0 -} - -// Fit sets the parameters of the probability distribution from the -// data samples x with relative weights w. If weights is nil, then all the weights -// are 1. If weights is not nil, then the len(weights) must equal len(samples). -func (n *Normal) Fit(samples, weights []float64) { - suffStat := make([]float64, n.NumSuffStat()) - nSamples := n.SuffStat(suffStat, samples, weights) - n.ConjugateUpdate(suffStat, nSamples, make([]float64, n.NumSuffStat())) -} - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (n Normal) LogProb(x float64) float64 { - return negLogRoot2Pi - math.Log(n.Sigma) - (x-n.Mu)*(x-n.Mu)/(2*n.Sigma*n.Sigma) -} - -// Mean returns the mean of the probability distribution. -func (n Normal) Mean() float64 { - return n.Mu -} - -// Median returns the median of the normal distribution. -func (n Normal) Median() float64 { - return n.Mu -} - -// Mode returns the mode of the normal distribution. -func (n Normal) Mode() float64 { - return n.Mu -} - -// NumParameters returns the number of parameters in the distribution. -func (Normal) NumParameters() int { - return 2 -} - -// NumSuffStat returns the number of sufficient statistics for the distribution. -func (Normal) NumSuffStat() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (n Normal) Prob(x float64) float64 { - return math.Exp(n.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (n Normal) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - return n.Mu + n.Sigma*mathext.NormalQuantile(p) -} - -// Rand returns a random sample drawn from the distribution. -func (n Normal) Rand() float64 { - var rnd float64 - if n.Src == nil { - rnd = rand.NormFloat64() - } else { - rnd = rand.New(n.Src).NormFloat64() - } - return rnd*n.Sigma + n.Mu -} - -// Score returns the score function with respect to the parameters of the -// distribution at the input location x. The score function is the derivative -// of the log-likelihood at x with respect to the parameters -// -// (∂/∂θ) log(p(x;θ)) -// -// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise -// Score will panic, and the derivative is stored in-place into deriv. If deriv -// is nil a new slice will be allocated and returned. -// -// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Sigma]. -// -// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. -func (n Normal) Score(deriv []float64, x float64) []float64 { - if deriv == nil { - deriv = make([]float64, n.NumParameters()) - } - if len(deriv) != n.NumParameters() { - panic(badLength) - } - deriv[0] = (x - n.Mu) / (n.Sigma * n.Sigma) - deriv[1] = 1 / n.Sigma * (-1 + ((x-n.Mu)/n.Sigma)*((x-n.Mu)/n.Sigma)) - return deriv -} - -// ScoreInput returns the score function with respect to the input of the -// distribution at the input location specified by x. The score function is the -// derivative of the log-likelihood -// -// (d/dx) log(p(x)) . -func (n Normal) ScoreInput(x float64) float64 { - return -(1 / (2 * n.Sigma * n.Sigma)) * 2 * (x - n.Mu) -} - -// Skewness returns the skewness of the distribution. -func (Normal) Skewness() float64 { - return 0 -} - -// StdDev returns the standard deviation of the probability distribution. -func (n Normal) StdDev() float64 { - return n.Sigma -} - -// SuffStat computes the sufficient statistics of a set of samples to update -// the distribution. The sufficient statistics are stored in place, and the -// effective number of samples are returned. -// -// The normal distribution has two sufficient statistics, the mean of the samples -// and the standard deviation of the samples. -// -// If weights is nil, the weights are assumed to be 1, otherwise panics if -// len(samples) != len(weights). Panics if len(suffStat) != NumSuffStat(). -func (Normal) SuffStat(suffStat, samples, weights []float64) (nSamples float64) { - lenSamp := len(samples) - if len(weights) != 0 && len(samples) != len(weights) { - panic(badLength) - } - if len(suffStat) != (Normal{}).NumSuffStat() { - panic(badSuffStat) - } - - if len(weights) == 0 { - nSamples = float64(lenSamp) - } else { - nSamples = floats.Sum(weights) - } - - mean := stat.Mean(samples, weights) - suffStat[0] = mean - - // Use Moment and not StdDev because we want it to be uncorrected - variance := stat.MomentAbout(2, samples, mean, weights) - suffStat[1] = math.Sqrt(variance) - return nSamples -} - -// Survival returns the survival function (complementary CDF) at x. -func (n Normal) Survival(x float64) float64 { - return 0.5 * (1 - math.Erf((x-n.Mu)/(n.Sigma*math.Sqrt2))) -} - -// setParameters modifies the parameters of the distribution. -func (n *Normal) setParameters(p []Parameter) { - if len(p) != n.NumParameters() { - panic("normal: incorrect number of parameters to set") - } - if p[0].Name != "Mu" { - panic("normal: " + panicNameMismatch) - } - if p[1].Name != "Sigma" { - panic("normal: " + panicNameMismatch) - } - n.Mu = p[0].Value - n.Sigma = p[1].Value -} - -// Variance returns the variance of the probability distribution. -func (n Normal) Variance() float64 { - return n.Sigma * n.Sigma -} - -// parameters returns the parameters of the distribution. -func (n Normal) parameters(p []Parameter) []Parameter { - nParam := n.NumParameters() - if p == nil { - p = make([]Parameter, nParam) - } else if len(p) != nParam { - panic("normal: improper parameter length") - } - p[0].Name = "Mu" - p[0].Value = n.Mu - p[1].Name = "Sigma" - p[1].Value = n.Sigma - return p -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/pareto.go b/vendor/gonum.org/v1/gonum/stat/distuv/pareto.go deleted file mode 100644 index 6ec751ea..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/pareto.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright ©2017 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// Pareto implements the Pareto (Type I) distribution, a one parameter distribution -// with support above the scale parameter. -// -// The density function is given by -// -// (α x_m^{α})/(x^{α+1}) for x >= x_m. -// -// For more information, see https://en.wikipedia.org/wiki/Pareto_distribution. -type Pareto struct { - // Xm is the scale parameter. - // Xm must be greater than 0. - Xm float64 - - // Alpha is the shape parameter. - // Alpha must be greater than 0. - Alpha float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (p Pareto) CDF(x float64) float64 { - if x < p.Xm { - return 0 - } - return -math.Expm1(p.Alpha * math.Log(p.Xm/x)) -} - -// Entropy returns the differential entropy of the distribution. -func (p Pareto) Entropy() float64 { - return math.Log(p.Xm) - math.Log(p.Alpha) + (1 + 1/p.Alpha) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (p Pareto) ExKurtosis() float64 { - if p.Alpha <= 4 { - return math.NaN() - } - return 6 * (p.Alpha*p.Alpha*p.Alpha + p.Alpha*p.Alpha - 6*p.Alpha - 2) / (p.Alpha * (p.Alpha - 3) * (p.Alpha - 4)) - -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (p Pareto) LogProb(x float64) float64 { - if x < p.Xm { - return math.Inf(-1) - } - return math.Log(p.Alpha) + p.Alpha*math.Log(p.Xm) - (p.Alpha+1)*math.Log(x) -} - -// Mean returns the mean of the probability distribution. -func (p Pareto) Mean() float64 { - if p.Alpha <= 1 { - return math.Inf(1) - } - return p.Alpha * p.Xm / (p.Alpha - 1) -} - -// Median returns the median of the pareto distribution. -func (p Pareto) Median() float64 { - return p.Quantile(0.5) -} - -// Mode returns the mode of the distribution. -func (p Pareto) Mode() float64 { - return p.Xm -} - -// NumParameters returns the number of parameters in the distribution. -func (p Pareto) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (p Pareto) Prob(x float64) float64 { - return math.Exp(p.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (p Pareto) Quantile(prob float64) float64 { - if prob < 0 || 1 < prob { - panic(badPercentile) - } - return p.Xm / math.Pow(1-prob, 1/p.Alpha) -} - -// Rand returns a random sample drawn from the distribution. -func (p Pareto) Rand() float64 { - var rnd float64 - if p.Src == nil { - rnd = rand.ExpFloat64() - } else { - rnd = rand.New(p.Src).ExpFloat64() - } - return p.Xm * math.Exp(rnd/p.Alpha) -} - -// StdDev returns the standard deviation of the probability distribution. -func (p Pareto) StdDev() float64 { - return math.Sqrt(p.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (p Pareto) Survival(x float64) float64 { - if x < p.Xm { - return 1 - } - return math.Pow(p.Xm/x, p.Alpha) -} - -// Variance returns the variance of the probability distribution. -func (p Pareto) Variance() float64 { - if p.Alpha <= 2 { - return math.Inf(1) - } - am1 := p.Alpha - 1 - return p.Xm * p.Xm * p.Alpha / (am1 * am1 * (p.Alpha - 2)) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/poisson.go b/vendor/gonum.org/v1/gonum/stat/distuv/poisson.go deleted file mode 100644 index fcc8968c..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/poisson.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright ©2017 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -// Poisson implements the Poisson distribution, a discrete probability distribution -// that expresses the probability of a given number of events occurring in a fixed -// interval. -// The poisson distribution has density function: -// -// f(k) = λ^k / k! e^(-λ) -// -// For more information, see https://en.wikipedia.org/wiki/Poisson_distribution. -type Poisson struct { - // Lambda is the average number of events in an interval. - // Lambda must be greater than 0. - Lambda float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative distribution function at x. -func (p Poisson) CDF(x float64) float64 { - if x < 0 { - return 0 - } - return mathext.GammaIncRegComp(math.Floor(x+1), p.Lambda) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (p Poisson) ExKurtosis() float64 { - return 1 / p.Lambda -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (p Poisson) LogProb(x float64) float64 { - if x < 0 || math.Floor(x) != x { - return math.Inf(-1) - } - lg, _ := math.Lgamma(math.Floor(x) + 1) - return x*math.Log(p.Lambda) - p.Lambda - lg -} - -// Mean returns the mean of the probability distribution. -func (p Poisson) Mean() float64 { - return p.Lambda -} - -// NumParameters returns the number of parameters in the distribution. -func (Poisson) NumParameters() int { - return 1 -} - -// Prob computes the value of the probability density function at x. -func (p Poisson) Prob(x float64) float64 { - return math.Exp(p.LogProb(x)) -} - -// Rand returns a random sample drawn from the distribution. -func (p Poisson) Rand() float64 { - // NUMERICAL RECIPES IN C: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43108-5) - // p. 294 - // <http://www.aip.de/groups/soe/local/numres/bookcpdf/c7-3.pdf> - - rnd := rand.ExpFloat64 - var rng *rand.Rand - if p.Src != nil { - rng = rand.New(p.Src) - rnd = rng.ExpFloat64 - } - - if p.Lambda < 10.0 { - // Use direct method. - var em float64 - t := 0.0 - for { - t += rnd() - if t >= p.Lambda { - break - } - em++ - } - return em - } - // Generate using: - // W. Hörmann. "The transformed rejection method for generating Poisson - // random variables." Insurance: Mathematics and Economics - // 12.1 (1993): 39-45. - - // Algorithm PTRS - rnd = rand.Float64 - if rng != nil { - rnd = rng.Float64 - } - b := 0.931 + 2.53*math.Sqrt(p.Lambda) - a := -0.059 + 0.02483*b - invalpha := 1.1239 + 1.1328/(b-3.4) - vr := 0.9277 - 3.6224/(b-2) - for { - U := rnd() - 0.5 - V := rnd() - us := 0.5 - math.Abs(U) - k := math.Floor((2*a/us+b)*U + p.Lambda + 0.43) - if us >= 0.07 && V <= vr { - return k - } - if k <= 0 || (us < 0.013 && V > us) { - continue - } - lg, _ := math.Lgamma(k + 1) - if math.Log(V*invalpha/(a/(us*us)+b)) <= k*math.Log(p.Lambda)-p.Lambda-lg { - return k - } - } -} - -// Skewness returns the skewness of the distribution. -func (p Poisson) Skewness() float64 { - return 1 / math.Sqrt(p.Lambda) -} - -// StdDev returns the standard deviation of the probability distribution. -func (p Poisson) StdDev() float64 { - return math.Sqrt(p.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (p Poisson) Survival(x float64) float64 { - return 1 - p.CDF(x) -} - -// Variance returns the variance of the probability distribution. -func (p Poisson) Variance() float64 { - return p.Lambda -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/statdist.go b/vendor/gonum.org/v1/gonum/stat/distuv/statdist.go deleted file mode 100644 index bf333db1..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/statdist.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright ©2018 The Gonum 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 distuv - -import ( - "math" - - "gonum.org/v1/gonum/mathext" -) - -// Bhattacharyya is a type for computing the Bhattacharyya distance between -// probability distributions. -// -// The Bhattacharyya distance is defined as -// -// D_B = -ln(BC(l,r)) -// BC = \int_-∞^∞ (p(x)q(x))^(1/2) dx -// -// Where BC is known as the Bhattacharyya coefficient. -// The Bhattacharyya distance is related to the Hellinger distance by -// -// H(l,r) = sqrt(1-BC(l,r)) -// -// For more information, see -// -// https://en.wikipedia.org/wiki/Bhattacharyya_distance -type Bhattacharyya struct{} - -// DistBeta returns the Bhattacharyya distance between Beta distributions l and r. -// For Beta distributions, the Bhattacharyya distance is given by -// -// -ln(B((α_l + α_r)/2, (β_l + β_r)/2) / (B(α_l,β_l), B(α_r,β_r))) -// -// Where B is the Beta function. -func (Bhattacharyya) DistBeta(l, r Beta) float64 { - // Reference: https://en.wikipedia.org/wiki/Hellinger_distance#Examples - return -mathext.Lbeta((l.Alpha+r.Alpha)/2, (l.Beta+r.Beta)/2) + - 0.5*mathext.Lbeta(l.Alpha, l.Beta) + 0.5*mathext.Lbeta(r.Alpha, r.Beta) -} - -// DistNormal returns the Bhattacharyya distance Normal distributions l and r. -// For Normal distributions, the Bhattacharyya distance is given by -// -// s = (σ_l^2 + σ_r^2)/2 -// BC = 1/8 (μ_l-μ_r)^2/s + 1/2 ln(s/(σ_l*σ_r)) -func (Bhattacharyya) DistNormal(l, r Normal) float64 { - // Reference: https://en.wikipedia.org/wiki/Bhattacharyya_distance - m := l.Mu - r.Mu - s := (l.Sigma*l.Sigma + r.Sigma*r.Sigma) / 2 - return 0.125*m*m/s + 0.5*math.Log(s) - 0.5*math.Log(l.Sigma) - 0.5*math.Log(r.Sigma) -} - -// Hellinger is a type for computing the Hellinger distance between probability -// distributions. -// -// The Hellinger distance is defined as -// -// H^2(l,r) = 1/2 * int_x (\sqrt(l(x)) - \sqrt(r(x)))^2 dx -// -// and is bounded between 0 and 1. Note the above formula defines the squared -// Hellinger distance, while this returns the Hellinger distance itself. -// The Hellinger distance is related to the Bhattacharyya distance by -// -// H^2 = 1 - exp(-D_B) -// -// For more information, see -// -// https://en.wikipedia.org/wiki/Hellinger_distance -type Hellinger struct{} - -// DistBeta computes the Hellinger distance between Beta distributions l and r. -// See the documentation of Bhattacharyya.DistBeta for the distance formula. -func (Hellinger) DistBeta(l, r Beta) float64 { - db := Bhattacharyya{}.DistBeta(l, r) - return math.Sqrt(-math.Expm1(-db)) -} - -// DistNormal computes the Hellinger distance between Normal distributions l and r. -// See the documentation of Bhattacharyya.DistNormal for the distance formula. -func (Hellinger) DistNormal(l, r Normal) float64 { - db := Bhattacharyya{}.DistNormal(l, r) - return math.Sqrt(-math.Expm1(-db)) -} - -// KullbackLeibler is a type for computing the Kullback-Leibler divergence from l to r. -// -// The Kullback-Leibler divergence is defined as -// -// D_KL(l || r ) = \int_x p(x) log(p(x)/q(x)) dx -// -// Note that the Kullback-Leibler divergence is not symmetric with respect to -// the order of the input arguments. -type KullbackLeibler struct{} - -// DistBeta returns the Kullback-Leibler divergence between Beta distributions -// l and r. -// -// For two Beta distributions, the KL divergence is computed as -// -// D_KL(l || r) = log Γ(α_l+β_l) - log Γ(α_l) - log Γ(β_l) -// - log Γ(α_r+β_r) + log Γ(α_r) + log Γ(β_r) -// + (α_l-α_r)(ψ(α_l)-ψ(α_l+β_l)) + (β_l-β_r)(ψ(β_l)-ψ(α_l+β_l)) -// -// Where Γ is the gamma function and ψ is the digamma function. -func (KullbackLeibler) DistBeta(l, r Beta) float64 { - // http://bariskurt.com/kullback-leibler-divergence-between-two-dirichlet-and-beta-distributions/ - if l.Alpha <= 0 || l.Beta <= 0 { - panic("distuv: bad parameters for left distribution") - } - if r.Alpha <= 0 || r.Beta <= 0 { - panic("distuv: bad parameters for right distribution") - } - lab := l.Alpha + l.Beta - l1, _ := math.Lgamma(lab) - l2, _ := math.Lgamma(l.Alpha) - l3, _ := math.Lgamma(l.Beta) - lt := l1 - l2 - l3 - - r1, _ := math.Lgamma(r.Alpha + r.Beta) - r2, _ := math.Lgamma(r.Alpha) - r3, _ := math.Lgamma(r.Beta) - rt := r1 - r2 - r3 - - d0 := mathext.Digamma(l.Alpha + l.Beta) - ct := (l.Alpha-r.Alpha)*(mathext.Digamma(l.Alpha)-d0) + (l.Beta-r.Beta)*(mathext.Digamma(l.Beta)-d0) - - return lt - rt + ct -} - -// DistNormal returns the Kullback-Leibler divergence between Normal distributions -// l and r. -// -// For two Normal distributions, the KL divergence is computed as -// -// D_KL(l || r) = log(σ_r / σ_l) + (σ_l^2 + (μ_l-μ_r)^2)/(2 * σ_r^2) - 0.5 -func (KullbackLeibler) DistNormal(l, r Normal) float64 { - d := l.Mu - r.Mu - v := (l.Sigma*l.Sigma + d*d) / (2 * r.Sigma * r.Sigma) - return math.Log(r.Sigma) - math.Log(l.Sigma) + v - 0.5 -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/studentst.go b/vendor/gonum.org/v1/gonum/stat/distuv/studentst.go deleted file mode 100644 index 3bbb1526..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/studentst.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright ©2016 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" - - "gonum.org/v1/gonum/mathext" -) - -const logPi = 1.1447298858494001741 // http://oeis.org/A053510 - -// StudentsT implements the three-parameter Student's T distribution, a distribution -// over the real numbers. -// -// The Student's T distribution has density function -// -// Γ((ν+1)/2) / (sqrt(νπ) Γ(ν/2) σ) (1 + 1/ν * ((x-μ)/σ)^2)^(-(ν+1)/2) -// -// The Student's T distribution approaches the normal distribution as ν → ∞. -// -// For more information, see https://en.wikipedia.org/wiki/Student%27s_t-distribution, -// specifically https://en.wikipedia.org/wiki/Student%27s_t-distribution#Non-standardized_Student.27s_t-distribution . -// -// The standard Student's T distribution is with Mu = 0, and Sigma = 1. -type StudentsT struct { - // Mu is the location parameter of the distribution, and the mean of the - // distribution - Mu float64 - - // Sigma is the scale parameter of the distribution. It is related to the - // standard deviation by std = Sigma * sqrt(Nu/(Nu-2)) - Sigma float64 - - // Nu is the shape parameter of the distribution, representing the number of - // degrees of the distribution, and one less than the number of observations - // from a Normal distribution. - Nu float64 - - Src rand.Source -} - -// CDF computes the value of the cumulative distribution function at x. -func (s StudentsT) CDF(x float64) float64 { - // transform to standard normal - y := (x - s.Mu) / s.Sigma - if y == 0 { - return 0.5 - } - // For t > 0 - // F(y) = 1 - 0.5 * I_t(y)(nu/2, 1/2) - // t(y) = nu/(y^2 + nu) - // and 1 - F(y) for t < 0 - t := s.Nu / (y*y + s.Nu) - if y > 0 { - return 1 - 0.5*mathext.RegIncBeta(0.5*s.Nu, 0.5, t) - } - return 0.5 * mathext.RegIncBeta(s.Nu/2, 0.5, t) -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -func (s StudentsT) LogProb(x float64) float64 { - g1, _ := math.Lgamma((s.Nu + 1) / 2) - g2, _ := math.Lgamma(s.Nu / 2) - z := (x - s.Mu) / s.Sigma - return g1 - g2 - 0.5*math.Log(s.Nu) - 0.5*logPi - math.Log(s.Sigma) - ((s.Nu+1)/2)*math.Log(1+z*z/s.Nu) -} - -// Mean returns the mean of the probability distribution. -func (s StudentsT) Mean() float64 { - return s.Mu -} - -// Mode returns the mode of the distribution. -func (s StudentsT) Mode() float64 { - return s.Mu -} - -// NumParameters returns the number of parameters in the distribution. -func (StudentsT) NumParameters() int { - return 3 -} - -// Prob computes the value of the probability density function at x. -func (s StudentsT) Prob(x float64) float64 { - return math.Exp(s.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative distribution function. -func (s StudentsT) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - // F(x) = 1 - 0.5 * I_t(x)(nu/2, 1/2) - // t(x) = nu/(t^2 + nu) - if p == 0.5 { - return s.Mu - } - var y float64 - if p > 0.5 { - // Know t > 0 - t := mathext.InvRegIncBeta(s.Nu/2, 0.5, 2*(1-p)) - y = math.Sqrt(s.Nu * (1 - t) / t) - } else { - t := mathext.InvRegIncBeta(s.Nu/2, 0.5, 2*p) - y = -math.Sqrt(s.Nu * (1 - t) / t) - } - // Convert out of standard normal - return y*s.Sigma + s.Mu -} - -// Rand returns a random sample drawn from the distribution. -func (s StudentsT) Rand() float64 { - // http://www.math.uah.edu/stat/special/Student.html - n := Normal{0, 1, s.Src}.Rand() - c := Gamma{s.Nu / 2, 0.5, s.Src}.Rand() - z := n / math.Sqrt(c/s.Nu) - return z*s.Sigma + s.Mu -} - -// StdDev returns the standard deviation of the probability distribution. -// -// The standard deviation is undefined for ν <= 1, and this returns math.NaN(). -func (s StudentsT) StdDev() float64 { - return math.Sqrt(s.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (s StudentsT) Survival(x float64) float64 { - // transform to standard normal - y := (x - s.Mu) / s.Sigma - if y == 0 { - return 0.5 - } - // For t > 0 - // F(y) = 1 - 0.5 * I_t(y)(nu/2, 1/2) - // t(y) = nu/(y^2 + nu) - // and 1 - F(y) for t < 0 - t := s.Nu / (y*y + s.Nu) - if y > 0 { - return 0.5 * mathext.RegIncBeta(s.Nu/2, 0.5, t) - } - return 1 - 0.5*mathext.RegIncBeta(s.Nu/2, 0.5, t) -} - -// Variance returns the variance of the probability distribution. -// -// The variance is undefined for ν <= 1, and this returns math.NaN(). -func (s StudentsT) Variance() float64 { - if s.Nu <= 1 { - return math.NaN() - } - if s.Nu <= 2 { - return math.Inf(1) - } - return s.Sigma * s.Sigma * s.Nu / (s.Nu - 2) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/triangle.go b/vendor/gonum.org/v1/gonum/stat/distuv/triangle.go deleted file mode 100644 index 20240bbe..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/triangle.go +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright ©2017 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// Triangle represents a triangle distribution (https://en.wikipedia.org/wiki/Triangular_distribution). -type Triangle struct { - a, b, c float64 - src rand.Source -} - -// NewTriangle constructs a new triangle distribution with lower limit a, upper limit b, and mode c. -// Constraints are a < b and a ≤ c ≤ b. -// This distribution is uncommon in nature, but may be useful for simulation. -func NewTriangle(a, b, c float64, src rand.Source) Triangle { - checkTriangleParameters(a, b, c) - return Triangle{a: a, b: b, c: c, src: src} -} - -func checkTriangleParameters(a, b, c float64) { - if a >= b { - panic("triangle: constraint of a < b violated") - } - if a > c { - panic("triangle: constraint of a <= c violated") - } - if c > b { - panic("triangle: constraint of c <= b violated") - } -} - -// CDF computes the value of the cumulative density function at x. -func (t Triangle) CDF(x float64) float64 { - switch { - case x <= t.a: - return 0 - case x <= t.c: - d := x - t.a - return (d * d) / ((t.b - t.a) * (t.c - t.a)) - case x < t.b: - d := t.b - x - return 1 - (d*d)/((t.b-t.a)*(t.b-t.c)) - default: - return 1 - } -} - -// Entropy returns the entropy of the distribution. -func (t Triangle) Entropy() float64 { - return 0.5 + math.Log(t.b-t.a) - math.Ln2 -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (Triangle) ExKurtosis() float64 { - return -3.0 / 5.0 -} - -// Fit is not appropriate for Triangle, because the distribution is generally used when there is little data. - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (t Triangle) LogProb(x float64) float64 { - return math.Log(t.Prob(x)) -} - -// Mean returns the mean of the probability distribution. -func (t Triangle) Mean() float64 { - return (t.a + t.b + t.c) / 3 -} - -// Median returns the median of the probability distribution. -func (t Triangle) Median() float64 { - if t.c >= (t.a+t.b)/2 { - return t.a + math.Sqrt((t.b-t.a)*(t.c-t.a)/2) - } - return t.b - math.Sqrt((t.b-t.a)*(t.b-t.c)/2) -} - -// Mode returns the mode of the probability distribution. -func (t Triangle) Mode() float64 { - return t.c -} - -// NumParameters returns the number of parameters in the distribution. -func (Triangle) NumParameters() int { - return 3 -} - -// Prob computes the value of the probability density function at x. -func (t Triangle) Prob(x float64) float64 { - switch { - case x < t.a: - return 0 - case x < t.c: - return 2 * (x - t.a) / ((t.b - t.a) * (t.c - t.a)) - case x == t.c: - return 2 / (t.b - t.a) - case x <= t.b: - return 2 * (t.b - x) / ((t.b - t.a) * (t.b - t.c)) - default: - return 0 - } -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (t Triangle) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - - f := (t.c - t.a) / (t.b - t.a) - - if p < f { - return t.a + math.Sqrt(p*(t.b-t.a)*(t.c-t.a)) - } - return t.b - math.Sqrt((1-p)*(t.b-t.a)*(t.b-t.c)) -} - -// Rand returns a random sample drawn from the distribution. -func (t Triangle) Rand() float64 { - var rnd float64 - if t.src == nil { - rnd = rand.Float64() - } else { - rnd = rand.New(t.src).Float64() - } - - return t.Quantile(rnd) -} - -// Score returns the score function with respect to the parameters of the -// distribution at the input location x. The score function is the derivative -// of the log-likelihood at x with respect to the parameters -// -// (∂/∂θ) log(p(x;θ)) -// -// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise -// Score will panic, and the derivative is stored in-place into deriv. If deriv -// is nil a new slice will be allocated and returned. -// -// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Sigma]. -// -// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. -func (t Triangle) Score(deriv []float64, x float64) []float64 { - if deriv == nil { - deriv = make([]float64, t.NumParameters()) - } - if len(deriv) != t.NumParameters() { - panic(badLength) - } - if (x < t.a) || (x > t.b) { - deriv[0] = math.NaN() - deriv[1] = math.NaN() - deriv[2] = math.NaN() - } else { - invBA := 1 / (t.b - t.a) - invCA := 1 / (t.c - t.a) - invBC := 1 / (t.b - t.c) - switch { - case x < t.c: - deriv[0] = -1/(x-t.a) + invBA + invCA - deriv[1] = -invBA - deriv[2] = -invCA - case x > t.c: - deriv[0] = invBA - deriv[1] = 1/(t.b-x) - invBA - invBC - deriv[2] = invBC - default: - deriv[0] = invBA - deriv[1] = -invBA - deriv[2] = 0 - } - switch { - case x == t.a: - deriv[0] = math.NaN() - case x == t.b: - deriv[1] = math.NaN() - case x == t.c: - deriv[2] = math.NaN() - } - switch { - case t.a == t.c: - deriv[0] = math.NaN() - deriv[2] = math.NaN() - case t.b == t.c: - deriv[1] = math.NaN() - deriv[2] = math.NaN() - } - } - return deriv -} - -// ScoreInput returns the score function with respect to the input of the -// distribution at the input location specified by x. The score function is the -// derivative of the log-likelihood -// -// (d/dx) log(p(x)) . -// -// Special cases (c is the mode of the distribution): -// -// ScoreInput(c) = NaN -// ScoreInput(x) = NaN for x not in (a, b) -func (t Triangle) ScoreInput(x float64) float64 { - if (x <= t.a) || (x >= t.b) || (x == t.c) { - return math.NaN() - } - if x < t.c { - return 1 / (x - t.a) - } - return 1 / (x - t.b) -} - -// Skewness returns the skewness of the distribution. -func (t Triangle) Skewness() float64 { - n := math.Sqrt2 * (t.a + t.b - 2*t.c) * (2*t.a - t.b - t.c) * (t.a - 2*t.b + t.c) - d := 5 * math.Pow(t.a*t.a+t.b*t.b+t.c*t.c-t.a*t.b-t.a*t.c-t.b*t.c, 3.0/2.0) - - return n / d -} - -// StdDev returns the standard deviation of the probability distribution. -func (t Triangle) StdDev() float64 { - return math.Sqrt(t.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (t Triangle) Survival(x float64) float64 { - return 1 - t.CDF(x) -} - -// parameters returns the parameters of the distribution. -func (t Triangle) parameters(p []Parameter) []Parameter { - nParam := t.NumParameters() - if p == nil { - p = make([]Parameter, nParam) - } else if len(p) != nParam { - panic("triangle: improper parameter length") - } - p[0].Name = "A" - p[0].Value = t.a - p[1].Name = "B" - p[1].Value = t.b - p[2].Name = "C" - p[2].Value = t.c - return p -} - -// setParameters modifies the parameters of the distribution. -func (t *Triangle) setParameters(p []Parameter) { - if len(p) != t.NumParameters() { - panic("triangle: incorrect number of parameters to set") - } - if p[0].Name != "A" { - panic("triangle: " + panicNameMismatch) - } - if p[1].Name != "B" { - panic("triangle: " + panicNameMismatch) - } - if p[2].Name != "C" { - panic("triangle: " + panicNameMismatch) - } - - checkTriangleParameters(p[0].Value, p[1].Value, p[2].Value) - - t.a = p[0].Value - t.b = p[1].Value - t.c = p[2].Value -} - -// Variance returns the variance of the probability distribution. -func (t Triangle) Variance() float64 { - return (t.a*t.a + t.b*t.b + t.c*t.c - t.a*t.b - t.a*t.c - t.b*t.c) / 18 -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/uniform.go b/vendor/gonum.org/v1/gonum/stat/distuv/uniform.go deleted file mode 100644 index 3f555e33..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/uniform.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright ©2014 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// UnitUniform is an instantiation of the uniform distribution with Min = 0 -// and Max = 1. -var UnitUniform = Uniform{Min: 0, Max: 1} - -// Uniform represents a continuous uniform distribution (https://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29). -type Uniform struct { - Min float64 - Max float64 - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (u Uniform) CDF(x float64) float64 { - if x < u.Min { - return 0 - } - if x > u.Max { - return 1 - } - return (x - u.Min) / (u.Max - u.Min) -} - -// Uniform doesn't have any of the DLogProbD? because the derivative is 0 everywhere -// except where it's undefined - -// Entropy returns the entropy of the distribution. -func (u Uniform) Entropy() float64 { - return math.Log(u.Max - u.Min) -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (Uniform) ExKurtosis() float64 { - return -6.0 / 5.0 -} - -// Uniform doesn't have Fit because it's a bad idea to fit a uniform from data. - -// LogProb computes the natural logarithm of the value of the probability density function at x. -func (u Uniform) LogProb(x float64) float64 { - if x < u.Min { - return math.Inf(-1) - } - if x > u.Max { - return math.Inf(-1) - } - return -math.Log(u.Max - u.Min) -} - -// parameters returns the parameters of the distribution. -func (u Uniform) parameters(p []Parameter) []Parameter { - nParam := u.NumParameters() - if p == nil { - p = make([]Parameter, nParam) - } else if len(p) != nParam { - panic("uniform: improper parameter length") - } - p[0].Name = "Min" - p[0].Value = u.Min - p[1].Name = "Max" - p[1].Value = u.Max - return p -} - -// Mean returns the mean of the probability distribution. -func (u Uniform) Mean() float64 { - return (u.Max + u.Min) / 2 -} - -// Median returns the median of the probability distribution. -func (u Uniform) Median() float64 { - return (u.Max + u.Min) / 2 -} - -// Uniform doesn't have a mode because it's any value in the distribution - -// NumParameters returns the number of parameters in the distribution. -func (Uniform) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (u Uniform) Prob(x float64) float64 { - if x < u.Min { - return 0 - } - if x > u.Max { - return 0 - } - return 1 / (u.Max - u.Min) -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (u Uniform) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - return p*(u.Max-u.Min) + u.Min -} - -// Rand returns a random sample drawn from the distribution. -func (u Uniform) Rand() float64 { - var rnd float64 - if u.Src == nil { - rnd = rand.Float64() - } else { - rnd = rand.New(u.Src).Float64() - } - return rnd*(u.Max-u.Min) + u.Min -} - -// Score returns the score function with respect to the parameters of the -// distribution at the input location x. The score function is the derivative -// of the log-likelihood at x with respect to the parameters -// -// (∂/∂θ) log(p(x;θ)) -// -// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise -// Score will panic, and the derivative is stored in-place into deriv. If deriv -// is nil a new slice will be allocated and returned. -// -// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Sigma]. -// -// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. -func (u Uniform) Score(deriv []float64, x float64) []float64 { - if deriv == nil { - deriv = make([]float64, u.NumParameters()) - } - if len(deriv) != u.NumParameters() { - panic(badLength) - } - if (x < u.Min) || (x > u.Max) { - deriv[0] = math.NaN() - deriv[1] = math.NaN() - } else { - deriv[0] = 1 / (u.Max - u.Min) - deriv[1] = -deriv[0] - if x == u.Min { - deriv[0] = math.NaN() - } - if x == u.Max { - deriv[1] = math.NaN() - } - } - return deriv -} - -// ScoreInput returns the score function with respect to the input of the -// distribution at the input location specified by x. The score function is the -// derivative of the log-likelihood -// -// (d/dx) log(p(x)) . -func (u Uniform) ScoreInput(x float64) float64 { - if (x <= u.Min) || (x >= u.Max) { - return math.NaN() - } - return 0 -} - -// Skewness returns the skewness of the distribution. -func (Uniform) Skewness() float64 { - return 0 -} - -// StdDev returns the standard deviation of the probability distribution. -func (u Uniform) StdDev() float64 { - return math.Sqrt(u.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (u Uniform) Survival(x float64) float64 { - if x < u.Min { - return 1 - } - if x > u.Max { - return 0 - } - return (u.Max - x) / (u.Max - u.Min) -} - -// setParameters modifies the parameters of the distribution. -func (u *Uniform) setParameters(p []Parameter) { - if len(p) != u.NumParameters() { - panic("uniform: incorrect number of parameters to set") - } - if p[0].Name != "Min" { - panic("uniform: " + panicNameMismatch) - } - if p[1].Name != "Max" { - panic("uniform: " + panicNameMismatch) - } - - u.Min = p[0].Value - u.Max = p[1].Value -} - -// Variance returns the variance of the probability distribution. -func (u Uniform) Variance() float64 { - return 1.0 / 12.0 * (u.Max - u.Min) * (u.Max - u.Min) -} diff --git a/vendor/gonum.org/v1/gonum/stat/distuv/weibull.go b/vendor/gonum.org/v1/gonum/stat/distuv/weibull.go deleted file mode 100644 index 4042a8a9..00000000 --- a/vendor/gonum.org/v1/gonum/stat/distuv/weibull.go +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright ©2014 The Gonum 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 distuv - -import ( - "math" - "math/rand/v2" -) - -// Weibull distribution. Valid range for x is [0,+∞). -type Weibull struct { - // Shape parameter of the distribution. A value of 1 represents - // the exponential distribution. A value of 2 represents the - // Rayleigh distribution. Valid range is (0,+∞). - K float64 - // Scale parameter of the distribution. Valid range is (0,+∞). - Lambda float64 - // Source of random numbers - Src rand.Source -} - -// CDF computes the value of the cumulative density function at x. -func (w Weibull) CDF(x float64) float64 { - if x < 0 { - return 0 - } - return -math.Expm1(-math.Pow(x/w.Lambda, w.K)) -} - -// Entropy returns the entropy of the distribution. -func (w Weibull) Entropy() float64 { - return eulerGamma*(1-1/w.K) + math.Log(w.Lambda/w.K) + 1 -} - -// ExKurtosis returns the excess kurtosis of the distribution. -func (w Weibull) ExKurtosis() float64 { - return (-6*w.gammaIPow(1, 4) + 12*w.gammaIPow(1, 2)*math.Gamma(1+2/w.K) - 3*w.gammaIPow(2, 2) - 4*math.Gamma(1+1/w.K)*math.Gamma(1+3/w.K) + math.Gamma(1+4/w.K)) / math.Pow(math.Gamma(1+2/w.K)-w.gammaIPow(1, 2), 2) -} - -// gammIPow is a shortcut for computing the gamma function to a power. -func (w Weibull) gammaIPow(i, pow float64) float64 { - return math.Pow(math.Gamma(1+i/w.K), pow) -} - -// LogProb computes the natural logarithm of the value of the probability -// density function at x. -Inf is returned if x is less than zero. -// -// Special cases occur when x == 0, and the result depends on the shape -// parameter as follows: -// -// If 0 < K < 1, LogProb returns +Inf. -// If K == 1, LogProb returns 0. -// If K > 1, LogProb returns -Inf. -func (w Weibull) LogProb(x float64) float64 { - if x < 0 { - return math.Inf(-1) - } - if x == 0 && w.K == 1 { - return 0 - } - return math.Log(w.K) - math.Log(w.Lambda) + (w.K-1)*(math.Log(x)-math.Log(w.Lambda)) - math.Pow(x/w.Lambda, w.K) -} - -// LogSurvival returns the log of the survival function (complementary CDF) at x. -func (w Weibull) LogSurvival(x float64) float64 { - if x < 0 { - return 0 - } - return -math.Pow(x/w.Lambda, w.K) -} - -// Mean returns the mean of the probability distribution. -func (w Weibull) Mean() float64 { - return w.Lambda * math.Gamma(1+1/w.K) -} - -// Median returns the median of the normal distribution. -func (w Weibull) Median() float64 { - return w.Lambda * math.Pow(ln2, 1/w.K) -} - -// Mode returns the mode of the normal distribution. -// -// The mode is NaN in the special case where the K (shape) parameter -// is less than 1. -func (w Weibull) Mode() float64 { - if w.K > 1 { - return w.Lambda * math.Pow((w.K-1)/w.K, 1/w.K) - } - return 0 -} - -// NumParameters returns the number of parameters in the distribution. -func (Weibull) NumParameters() int { - return 2 -} - -// Prob computes the value of the probability density function at x. -func (w Weibull) Prob(x float64) float64 { - if x < 0 { - return 0 - } - return math.Exp(w.LogProb(x)) -} - -// Quantile returns the inverse of the cumulative probability distribution. -func (w Weibull) Quantile(p float64) float64 { - if p < 0 || p > 1 { - panic(badPercentile) - } - return w.Lambda * math.Pow(-math.Log(1-p), 1/w.K) -} - -// Rand returns a random sample drawn from the distribution. -func (w Weibull) Rand() float64 { - var rnd float64 - if w.Src == nil { - rnd = rand.Float64() - } else { - rnd = rand.New(w.Src).Float64() - } - return w.Quantile(rnd) -} - -// Score returns the score function with respect to the parameters of the -// distribution at the input location x. The score function is the derivative -// of the log-likelihood at x with respect to the parameters -// -// (∂/∂θ) log(p(x;θ)) -// -// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise -// Score will panic, and the derivative is stored in-place into deriv. If deriv -// is nil a new slice will be allocated and returned. -// -// The order is [∂LogProb / ∂K, ∂LogProb / ∂λ]. -// -// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. -// -// Special cases: -// -// Score(x) = [NaN, NaN] for x <= 0 -func (w Weibull) Score(deriv []float64, x float64) []float64 { - if deriv == nil { - deriv = make([]float64, w.NumParameters()) - } - if len(deriv) != w.NumParameters() { - panic(badLength) - } - if x > 0 { - deriv[0] = 1/w.K + math.Log(x) - math.Log(w.Lambda) - (math.Log(x)-math.Log(w.Lambda))*math.Pow(x/w.Lambda, w.K) - deriv[1] = (w.K * (math.Pow(x/w.Lambda, w.K) - 1)) / w.Lambda - return deriv - } - deriv[0] = math.NaN() - deriv[1] = math.NaN() - return deriv -} - -// ScoreInput returns the score function with respect to the input of the -// distribution at the input location specified by x. The score function is the -// derivative of the log-likelihood -// -// (d/dx) log(p(x)) . -// -// Special cases: -// -// ScoreInput(x) = NaN for x <= 0 -func (w Weibull) ScoreInput(x float64) float64 { - if x > 0 { - return (-w.K*math.Pow(x/w.Lambda, w.K) + w.K - 1) / x - } - return math.NaN() -} - -// Skewness returns the skewness of the distribution. -func (w Weibull) Skewness() float64 { - stdDev := w.StdDev() - firstGamma, firstGammaSign := math.Lgamma(1 + 3/w.K) - logFirst := firstGamma + 3*(math.Log(w.Lambda)-math.Log(stdDev)) - logSecond := math.Log(3) + math.Log(w.Mean()) + 2*math.Log(stdDev) - 3*math.Log(stdDev) - logThird := 3 * (math.Log(w.Mean()) - math.Log(stdDev)) - return float64(firstGammaSign)*math.Exp(logFirst) - math.Exp(logSecond) - math.Exp(logThird) -} - -// StdDev returns the standard deviation of the probability distribution. -func (w Weibull) StdDev() float64 { - return math.Sqrt(w.Variance()) -} - -// Survival returns the survival function (complementary CDF) at x. -func (w Weibull) Survival(x float64) float64 { - return math.Exp(w.LogSurvival(x)) -} - -// setParameters modifies the parameters of the distribution. -func (w *Weibull) setParameters(p []Parameter) { - if len(p) != w.NumParameters() { - panic("weibull: incorrect number of parameters to set") - } - if p[0].Name != "K" { - panic("weibull: " + panicNameMismatch) - } - if p[1].Name != "λ" { - panic("weibull: " + panicNameMismatch) - } - w.K = p[0].Value - w.Lambda = p[1].Value -} - -// Variance returns the variance of the probability distribution. -func (w Weibull) Variance() float64 { - return math.Pow(w.Lambda, 2) * (math.Gamma(1+2/w.K) - w.gammaIPow(1, 2)) -} - -// parameters returns the parameters of the distribution. -func (w Weibull) parameters(p []Parameter) []Parameter { - nParam := w.NumParameters() - if p == nil { - p = make([]Parameter, nParam) - } else if len(p) != nParam { - panic("weibull: improper parameter length") - } - p[0].Name = "K" - p[0].Value = w.K - p[1].Name = "λ" - p[1].Value = w.Lambda - return p - -} diff --git a/vendor/gonum.org/v1/gonum/stat/doc.go b/vendor/gonum.org/v1/gonum/stat/doc.go deleted file mode 100644 index d6916cb2..00000000 --- a/vendor/gonum.org/v1/gonum/stat/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright ©2017 The Gonum 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 stat provides generalized statistical functions. -package stat // import "gonum.org/v1/gonum/stat" diff --git a/vendor/gonum.org/v1/gonum/stat/pca_cca.go b/vendor/gonum.org/v1/gonum/stat/pca_cca.go deleted file mode 100644 index 1cc92ebf..00000000 --- a/vendor/gonum.org/v1/gonum/stat/pca_cca.go +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright ©2016 The Gonum 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 stat - -import ( - "errors" - "math" - - "gonum.org/v1/gonum/floats" - "gonum.org/v1/gonum/mat" -) - -// PC is a type for computing and extracting the principal components of a -// matrix. The results of the principal components analysis are only valid -// if the call to PrincipalComponents was successful. -type PC struct { - n, d int - weights []float64 - svd *mat.SVD - ok bool -} - -// PrincipalComponents performs a weighted principal components analysis on the -// matrix of the input data which is represented as an n×d matrix a where each -// row is an observation and each column is a variable. -// -// PrincipalComponents centers the variables but does not scale the variance. -// -// The weights slice is used to weight the observations. If weights is nil, each -// weight is considered to have a value of one, otherwise the length of weights -// must match the number of observations or PrincipalComponents will panic. -// -// PrincipalComponents returns whether the analysis was successful. -func (c *PC) PrincipalComponents(a mat.Matrix, weights []float64) (ok bool) { - c.n, c.d = a.Dims() - if weights != nil && len(weights) != c.n { - panic("stat: len(weights) != observations") - } - - c.svd, c.ok = svdFactorizeCentered(c.svd, a, weights) - if c.ok { - c.weights = append(c.weights[:0], weights...) - } - return c.ok -} - -// VectorsTo returns the component direction vectors of a principal components -// analysis. The vectors are returned in the columns of a d×min(n, d) matrix. -// -// If dst is empty, VectorsTo will resize dst to be d×min(n, d). When dst is -// non-empty, VectorsTo will panic if dst is not d×min(n, d). VectorsTo will also -// panic if the receiver does not contain a successful PC. -func (c *PC) VectorsTo(dst *mat.Dense) { - if !c.ok { - panic("stat: use of unsuccessful principal components analysis") - } - - if dst.IsEmpty() { - dst.ReuseAs(c.d, min(c.n, c.d)) - } else { - if d, n := dst.Dims(); d != c.d || n != min(c.n, c.d) { - panic(mat.ErrShape) - } - } - c.svd.VTo(dst) -} - -// VarsTo returns the column variances of the principal component scores, -// b * vecs, where b is a matrix with centered columns. Variances are returned -// in descending order. -// If dst is not nil it is used to store the variances and returned. -// Vars will panic if the receiver has not successfully performed a principal -// components analysis or dst is not nil and the length of dst is not min(n, d). -func (c *PC) VarsTo(dst []float64) []float64 { - if !c.ok { - panic("stat: use of unsuccessful principal components analysis") - } - if dst != nil && len(dst) != min(c.n, c.d) { - panic("stat: length of slice does not match analysis") - } - - dst = c.svd.Values(dst) - var f float64 - if c.weights == nil { - f = 1 / float64(c.n-1) - } else { - f = 1 / (floats.Sum(c.weights) - 1) - } - for i, v := range dst { - dst[i] = f * v * v - } - return dst -} - -// CC is a type for computing the canonical correlations of a pair of matrices. -// The results of the canonical correlation analysis are only valid -// if the call to CanonicalCorrelations was successful. -type CC struct { - // n is the number of observations used to - // construct the canonical correlations. - n int - - // xd and yd are used for size checks. - xd, yd int - - x, y, c *mat.SVD - ok bool -} - -// CanonicalCorrelations performs a canonical correlation analysis of the -// input data x and y, columns of which should be interpretable as two sets -// of measurements on the same observations (rows). These observations are -// optionally weighted by weights. The result of the analysis is stored in -// the receiver if the analysis is successful. -// -// Canonical correlation analysis finds associations between two sets of -// variables on the same observations by finding linear combinations of the two -// sphered datasets that maximize the correlation between them. -// -// Some notation: let Xc and Yc denote the centered input data matrices x -// and y (column means subtracted from each column), let Sx and Sy denote the -// sample covariance matrices within x and y respectively, and let Sxy denote -// the covariance matrix between x and y. The sphered data can then be expressed -// as Xc * Sx^{-1/2} and Yc * Sy^{-1/2} respectively, and the correlation matrix -// between the sphered data is called the canonical correlation matrix, -// Sx^{-1/2} * Sxy * Sy^{-1/2}. In cases where S^{-1/2} is ambiguous for some -// covariance matrix S, S^{-1/2} is taken to be E * D^{-1/2} * Eᵀ where S can -// be eigendecomposed as S = E * D * Eᵀ. -// -// The canonical correlations are the correlations between the corresponding -// pairs of canonical variables and can be obtained with c.Corrs(). Canonical -// variables can be obtained by projecting the sphered data into the left and -// right eigenvectors of the canonical correlation matrix, and these -// eigenvectors can be obtained with c.Left(m, true) and c.Right(m, true) -// respectively. The canonical variables can also be obtained directly from the -// centered raw data by using the back-transformed eigenvectors which can be -// obtained with c.Left(m, false) and c.Right(m, false) respectively. -// -// The first pair of left and right eigenvectors of the canonical correlation -// matrix can be interpreted as directions into which the respective sphered -// data can be projected such that the correlation between the two projections -// is maximized. The second pair and onwards solve the same optimization but -// under the constraint that they are uncorrelated (orthogonal in sphered space) -// to previous projections. -// -// CanonicalCorrelations will panic if the inputs x and y do not have the same -// number of rows. -// -// The slice weights is used to weight the observations. If weights is nil, each -// weight is considered to have a value of one, otherwise the length of weights -// must match the number of observations (rows of both x and y) or -// CanonicalCorrelations will panic. -// -// More details can be found at -// https://en.wikipedia.org/wiki/Canonical_correlation -// or in Chapter 3 of -// Koch, Inge. Analysis of multivariate and high-dimensional data. -// Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 -func (c *CC) CanonicalCorrelations(x, y mat.Matrix, weights []float64) error { - var yn int - c.n, c.xd = x.Dims() - yn, c.yd = y.Dims() - if c.n != yn { - panic("stat: unequal number of observations") - } - if weights != nil && len(weights) != c.n { - panic("stat: len(weights) != observations") - } - - // Center and factorize x and y. - c.x, c.ok = svdFactorizeCentered(c.x, x, weights) - if !c.ok { - return errors.New("stat: failed to factorize x") - } - c.y, c.ok = svdFactorizeCentered(c.y, y, weights) - if !c.ok { - return errors.New("stat: failed to factorize y") - } - var xu, xv, yu, yv mat.Dense - c.x.UTo(&xu) - c.x.VTo(&xv) - c.y.UTo(&yu) - c.y.VTo(&yv) - - // Calculate and factorise the canonical correlation matrix. - var ccor mat.Dense - ccor.Product(&xv, xu.T(), &yu, yv.T()) - if c.c == nil { - c.c = &mat.SVD{} - } - c.ok = c.c.Factorize(&ccor, mat.SVDThin) - if !c.ok { - return errors.New("stat: failed to factorize ccor") - } - return nil -} - -// CorrsTo returns the canonical correlations, using dst if it is not nil. -// If dst is not nil and len(dst) does not match the number of columns in -// the y input matrix, Corrs will panic. -func (c *CC) CorrsTo(dst []float64) []float64 { - if !c.ok { - panic("stat: canonical correlations missing or invalid") - } - - if dst != nil && len(dst) != c.yd { - panic("stat: length of destination does not match input dimension") - } - return c.c.Values(dst) -} - -// LeftTo returns the left eigenvectors of the canonical correlation matrix if -// spheredSpace is true. If spheredSpace is false it returns these eigenvectors -// back-transformed to the original data space. -// -// If dst is empty, LeftTo will resize dst to be xd×yd. When dst is -// non-empty, LeftTo will panic if dst is not xd×yd. LeftTo will also -// panic if the receiver does not contain a successful CC. -func (c *CC) LeftTo(dst *mat.Dense, spheredSpace bool) { - if !c.ok || c.n < 2 { - panic("stat: canonical correlations missing or invalid") - } - - if dst.IsEmpty() { - dst.ReuseAs(c.xd, c.yd) - } else { - if d, n := dst.Dims(); d != c.xd || n != c.yd { - panic(mat.ErrShape) - } - } - c.c.UTo(dst) - if spheredSpace { - return - } - - xs := c.x.Values(nil) - xv := &mat.Dense{} - c.x.VTo(xv) - - scaleColsReciSqrt(xv, xs) - - dst.Product(xv, xv.T(), dst) - dst.Scale(math.Sqrt(float64(c.n-1)), dst) -} - -// RightTo returns the right eigenvectors of the canonical correlation matrix if -// spheredSpace is true. If spheredSpace is false it returns these eigenvectors -// back-transformed to the original data space. -// -// If dst is empty, RightTo will resize dst to be yd×yd. When dst is -// non-empty, RightTo will panic if dst is not yd×yd. RightTo will also -// panic if the receiver does not contain a successful CC. -func (c *CC) RightTo(dst *mat.Dense, spheredSpace bool) { - if !c.ok || c.n < 2 { - panic("stat: canonical correlations missing or invalid") - } - - if dst.IsEmpty() { - dst.ReuseAs(c.yd, c.yd) - } else { - if d, n := dst.Dims(); d != c.yd || n != c.yd { - panic(mat.ErrShape) - } - } - c.c.VTo(dst) - if spheredSpace { - return - } - - ys := c.y.Values(nil) - yv := &mat.Dense{} - c.y.VTo(yv) - - scaleColsReciSqrt(yv, ys) - - dst.Product(yv, yv.T(), dst) - dst.Scale(math.Sqrt(float64(c.n-1)), dst) -} - -func svdFactorizeCentered(work *mat.SVD, m mat.Matrix, weights []float64) (svd *mat.SVD, ok bool) { - n, d := m.Dims() - centered := mat.NewDense(n, d, nil) - col := make([]float64, n) - for j := 0; j < d; j++ { - mat.Col(col, j, m) - floats.AddConst(-Mean(col, weights), col) - centered.SetCol(j, col) - } - for i, w := range weights { - floats.Scale(math.Sqrt(w), centered.RawRowView(i)) - } - if work == nil { - work = &mat.SVD{} - } - ok = work.Factorize(centered, mat.SVDThin) - return work, ok -} - -// scaleColsReciSqrt scales the columns of cols -// by the reciprocal square-root of vals. -func scaleColsReciSqrt(cols *mat.Dense, vals []float64) { - if cols == nil { - panic("stat: input nil") - } - n, d := cols.Dims() - if len(vals) != d { - panic("stat: input length mismatch") - } - col := make([]float64, n) - for j := 0; j < d; j++ { - mat.Col(col, j, cols) - floats.Scale(math.Sqrt(1/vals[j]), col) - cols.SetCol(j, col) - } -} diff --git a/vendor/gonum.org/v1/gonum/stat/roc.go b/vendor/gonum.org/v1/gonum/stat/roc.go deleted file mode 100644 index 19add6fa..00000000 --- a/vendor/gonum.org/v1/gonum/stat/roc.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright ©2016 The Gonum 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 stat - -import ( - "math" - "slices" - "sort" -) - -// ROC returns paired false positive rate (FPR) and true positive rate -// (TPR) values corresponding to cutoff points on the receiver operator -// characteristic (ROC) curve obtained when y is treated as a binary -// classifier for classes with weights. The cutoff thresholds used to -// calculate the ROC are returned in thresh such that tpr[i] and fpr[i] -// are the true and false positive rates for y >= thresh[i]. -// -// The input y and cutoffs must be sorted, and values in y must correspond -// to values in classes and weights. SortWeightedLabeled can be used to -// sort y together with classes and weights. -// -// For a given cutoff value, observations corresponding to entries in y -// greater than the cutoff value are classified as true, while those -// less than or equal to the cutoff value are classified as false. These -// assigned class labels are compared with the true values in the classes -// slice and used to calculate the FPR and TPR. -// -// If weights is nil, all weights are treated as 1. If weights is not nil -// it must have the same length as y and classes, otherwise ROC will panic. -// -// If cutoffs is nil or empty, all possible cutoffs are calculated, -// resulting in fpr and tpr having length one greater than the number of -// unique values in y. Otherwise fpr and tpr will be returned with the -// same length as cutoffs. floats.Span can be used to generate equally -// spaced cutoffs. -// -// More details about ROC curves are available at -// https://en.wikipedia.org/wiki/Receiver_operating_characteristic -func ROC(cutoffs, y []float64, classes []bool, weights []float64) (tpr, fpr, thresh []float64) { - if len(y) != len(classes) { - panic("stat: slice length mismatch") - } - if weights != nil && len(y) != len(weights) { - panic("stat: slice length mismatch") - } - if !sort.Float64sAreSorted(y) { - panic("stat: input must be sorted ascending") - } - if !sort.Float64sAreSorted(cutoffs) { - panic("stat: cutoff values must be sorted ascending") - } - if len(y) == 0 { - return nil, nil, nil - } - if len(cutoffs) == 0 { - if cutoffs == nil || cap(cutoffs) < len(y)+1 { - cutoffs = make([]float64, len(y)+1) - } else { - cutoffs = cutoffs[:len(y)+1] - } - // Choose all possible cutoffs for unique values in y. - bin := 0 - cutoffs[bin] = y[0] - for i, u := range y[1:] { - if u == y[i] { - continue - } - bin++ - cutoffs[bin] = u - } - cutoffs[bin+1] = math.Inf(1) - cutoffs = cutoffs[:bin+2] - } else { - // Don't mutate the provided cutoffs. - tmp := cutoffs - cutoffs = make([]float64, len(cutoffs)) - copy(cutoffs, tmp) - } - - tpr = make([]float64, len(cutoffs)) - fpr = make([]float64, len(cutoffs)) - var bin int - var nPos, nNeg float64 - for i, u := range classes { - // Update the bin until it matches the next y value - // skipping empty bins. - for bin < len(cutoffs)-1 && y[i] >= cutoffs[bin] { - bin++ - tpr[bin] = tpr[bin-1] - fpr[bin] = fpr[bin-1] - } - posWeight, negWeight := 1.0, 0.0 - if weights != nil { - posWeight = weights[i] - } - if !u { - posWeight, negWeight = negWeight, posWeight - } - nPos += posWeight - nNeg += negWeight - // Count false negatives (in tpr) and true negatives (in fpr). - if y[i] < cutoffs[bin] { - tpr[bin] += posWeight - fpr[bin] += negWeight - } - } - - invNeg := 1 / nNeg - invPos := 1 / nPos - // Convert negative counts to TPR and FPR. - // Bins beyond the maximum value in y are skipped - // leaving these fpr and tpr elements as zero. - for i := range tpr[:bin+1] { - // Prevent fused float operations by - // making explicit float64 conversions. - tpr[i] = 1 - float64(tpr[i]*invPos) - fpr[i] = 1 - float64(fpr[i]*invNeg) - } - slices.Reverse(tpr) - slices.Reverse(fpr) - slices.Reverse(cutoffs) - - return tpr, fpr, cutoffs -} - -// TOC returns the Total Operating Characteristic for the classes provided -// and the minimum and maximum bounds for the TOC. -// -// The input y values that correspond to classes and weights must be sorted -// in ascending order. classes[i] is the class of value y[i] and weights[i] -// is the weight of y[i]. SortWeightedLabeled can be used to sort classes -// together with weights by the rank variable, i+1. -// -// The returned ntp values can be interpreted as the number of true positives -// where values above the given rank are assigned class true for each given -// rank from 1 to len(classes). -// -// ntp_i = sum_{j ≥ len(ntp)-1 - i} [ classes_j ] * weights_j, where [x] = 1 if x else 0. -// -// The values of min and max provide the minimum and maximum possible number -// of false values for the set of classes. The first element of ntp, min and -// max are always zero as this corresponds to assigning all data class false -// and the last elements are always weighted sum of classes as this corresponds -// to assigning every data class true. For len(classes) != 0, the lengths of -// min, ntp and max are len(classes)+1. -// -// If weights is nil, all weights are treated as 1. When weights are not nil, -// the calculation of min and max allows for partial assignment of single data -// points. If weights is not nil it must have the same length as classes, -// otherwise TOC will panic. -// -// More details about TOC curves are available at -// https://en.wikipedia.org/wiki/Total_operating_characteristic -func TOC(classes []bool, weights []float64) (min, ntp, max []float64) { - if weights != nil && len(classes) != len(weights) { - panic("stat: slice length mismatch") - } - if len(classes) == 0 { - return nil, nil, nil - } - - ntp = make([]float64, len(classes)+1) - min = make([]float64, len(ntp)) - max = make([]float64, len(ntp)) - if weights == nil { - for i := range ntp[1:] { - ntp[i+1] = ntp[i] - if classes[len(classes)-i-1] { - ntp[i+1]++ - } - } - totalPositive := ntp[len(ntp)-1] - for i := range ntp { - min[i] = math.Max(0, totalPositive-float64(len(classes)-i)) - max[i] = math.Min(totalPositive, float64(i)) - } - return min, ntp, max - } - - cumw := max // Reuse max for cumulative weight. Update its elements last. - for i := range ntp[1:] { - ntp[i+1] = ntp[i] - w := weights[len(weights)-i-1] - cumw[i+1] = cumw[i] + w - if classes[len(classes)-i-1] { - ntp[i+1] += w - } - } - totw := cumw[len(cumw)-1] - totalPositive := ntp[len(ntp)-1] - for i := range ntp { - min[i] = math.Max(0, totalPositive-(totw-cumw[i])) - max[i] = math.Min(totalPositive, cumw[i]) - } - return min, ntp, max -} diff --git a/vendor/gonum.org/v1/gonum/stat/stat.go b/vendor/gonum.org/v1/gonum/stat/stat.go deleted file mode 100644 index f7d43726..00000000 --- a/vendor/gonum.org/v1/gonum/stat/stat.go +++ /dev/null @@ -1,1400 +0,0 @@ -// Copyright ©2014 The Gonum 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 stat - -import ( - "math" - "sort" - - "gonum.org/v1/gonum/floats" -) - -// CumulantKind specifies the behavior for calculating the empirical CDF or Quantile -type CumulantKind int - -// List of supported CumulantKind values for the Quantile function. -// Constant values should match the R nomenclature. See -// https://en.wikipedia.org/wiki/Quantile#Estimating_the_quantiles_of_a_population -const ( - // Empirical treats the distribution as the actual empirical distribution. - Empirical CumulantKind = 1 - // LinInterp linearly interpolates the empirical distribution between sample values, with a flat extrapolation. - LinInterp CumulantKind = 4 -) - -// bhattacharyyaCoeff computes the Bhattacharyya Coefficient for probability distributions given by: -// -// \sum_i \sqrt{p_i q_i} -// -// It is assumed that p and q have equal length. -func bhattacharyyaCoeff(p, q []float64) float64 { - var bc float64 - for i, a := range p { - bc += math.Sqrt(a * q[i]) - } - return bc -} - -// Bhattacharyya computes the distance between the probability distributions p and q given by: -// -// -\ln ( \sum_i \sqrt{p_i q_i} ) -// -// The lengths of p and q must be equal. It is assumed that p and q sum to 1. -func Bhattacharyya(p, q []float64) float64 { - if len(p) != len(q) { - panic("stat: slice length mismatch") - } - bc := bhattacharyyaCoeff(p, q) - return -math.Log(bc) -} - -// CDF returns the empirical cumulative distribution function value of x, that is -// the fraction of the samples less than or equal to q. The -// exact behavior is determined by the CumulantKind. CDF is theoretically -// the inverse of the Quantile function, though it may not be the actual inverse -// for all values q and CumulantKinds. -// -// The x data must be sorted in increasing order. If weights is nil then all -// of the weights are 1. If weights is not nil, then len(x) must equal len(weights). -// CDF will panic if the length of x is zero. -// -// CumulantKind behaviors: -// - Empirical: Returns the lowest fraction for which q is greater than or equal -// to that fraction of samples -func CDF(q float64, c CumulantKind, x, weights []float64) float64 { - if weights != nil && len(x) != len(weights) { - panic("stat: slice length mismatch") - } - if floats.HasNaN(x) { - return math.NaN() - } - if len(x) == 0 { - panic("stat: zero length slice") - } - if !sort.Float64sAreSorted(x) { - panic("x data are not sorted") - } - - if q < x[0] { - return 0 - } - if q >= x[len(x)-1] { - return 1 - } - - var sumWeights float64 - if weights == nil { - sumWeights = float64(len(x)) - } else { - sumWeights = floats.Sum(weights) - } - - // Calculate the index - switch c { - case Empirical: - // Find the smallest value that is greater than that percent of the samples - var w float64 - for i, v := range x { - if v > q { - return w / sumWeights - } - if weights == nil { - w++ - } else { - w += weights[i] - } - } - panic("impossible") - default: - panic("stat: bad cumulant kind") - } -} - -// ChiSquare computes the chi-square distance between the observed frequencies 'obs' and -// expected frequencies 'exp' given by: -// -// \sum_i (obs_i-exp_i)^2 / exp_i -// -// The lengths of obs and exp must be equal. -func ChiSquare(obs, exp []float64) float64 { - if len(obs) != len(exp) { - panic("stat: slice length mismatch") - } - var result float64 - for i, a := range obs { - b := exp[i] - if a == 0 && b == 0 { - continue - } - result += (a - b) * (a - b) / b - } - return result -} - -// CircularMean returns the circular mean of the dataset. -// -// atan2(\sum_i w_i * sin(alpha_i), \sum_i w_i * cos(alpha_i)) -// -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func CircularMean(x, weights []float64) float64 { - if weights != nil && len(x) != len(weights) { - panic("stat: slice length mismatch") - } - - var aX, aY float64 - if weights != nil { - for i, v := range x { - aX += weights[i] * math.Cos(v) - aY += weights[i] * math.Sin(v) - } - } else { - for _, v := range x { - aX += math.Cos(v) - aY += math.Sin(v) - } - } - - return math.Atan2(aY, aX) -} - -// Correlation returns the weighted correlation between the samples of x and y -// with the given means. -// -// sum_i {w_i (x_i - meanX) * (y_i - meanY)} / (stdX * stdY) -// -// The lengths of x and y must be equal. If weights is nil then all of the -// weights are 1. If weights is not nil, then len(x) must equal len(weights). -func Correlation(x, y, weights []float64) float64 { - // This is a two-pass corrected implementation. It is an adaptation of the - // algorithm used in the MeanVariance function, which applies a correction - // to the typical two pass approach. - - if len(x) != len(y) { - panic("stat: slice length mismatch") - } - xu := Mean(x, weights) - yu := Mean(y, weights) - var ( - sxx float64 - syy float64 - sxy float64 - xcompensation float64 - ycompensation float64 - ) - if weights == nil { - for i, xv := range x { - yv := y[i] - xd := xv - xu - yd := yv - yu - sxx += xd * xd - syy += yd * yd - sxy += xd * yd - xcompensation += xd - ycompensation += yd - } - // xcompensation and ycompensation are from Chan, et. al. - // referenced in the MeanVariance function. They are analogous - // to the second term in (1.7) in that paper. - sxx -= xcompensation * xcompensation / float64(len(x)) - syy -= ycompensation * ycompensation / float64(len(x)) - - return (sxy - xcompensation*ycompensation/float64(len(x))) / math.Sqrt(sxx*syy) - - } - - var sumWeights float64 - for i, xv := range x { - w := weights[i] - yv := y[i] - xd := xv - xu - wxd := w * xd - yd := yv - yu - wyd := w * yd - sxx += wxd * xd - syy += wyd * yd - sxy += wxd * yd - xcompensation += wxd - ycompensation += wyd - sumWeights += w - } - // xcompensation and ycompensation are from Chan, et. al. - // referenced in the MeanVariance function. They are analogous - // to the second term in (1.7) in that paper, except they use - // the sumWeights instead of the sample count. - sxx -= xcompensation * xcompensation / sumWeights - syy -= ycompensation * ycompensation / sumWeights - - return (sxy - xcompensation*ycompensation/sumWeights) / math.Sqrt(sxx*syy) -} - -// Kendall returns the weighted Tau-a Kendall correlation between the -// samples of x and y. The Kendall correlation measures the quantity of -// concordant and discordant pairs of numbers. If weights are specified then -// each pair is weighted by weights[i] * weights[j] and the final sum is -// normalized to stay between -1 and 1. -// The lengths of x and y must be equal. If weights is nil then all of the -// weights are 1. If weights is not nil, then len(x) must equal len(weights). -func Kendall(x, y, weights []float64) float64 { - if len(x) != len(y) { - panic("stat: slice length mismatch") - } - - var ( - cc float64 // number of concordant pairs - dc float64 // number of discordant pairs - n = len(x) - ) - - if weights == nil { - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - if i == j { - continue - } - if math.Signbit(x[j]-x[i]) == math.Signbit(y[j]-y[i]) { - cc++ - } else { - dc++ - } - } - } - return (cc - dc) / float64(n*(n-1)/2) - } - - var sumWeights float64 - - for i := 0; i < n; i++ { - for j := i; j < n; j++ { - if i == j { - continue - } - weight := weights[i] * weights[j] - if math.Signbit(x[j]-x[i]) == math.Signbit(y[j]-y[i]) { - cc += weight - } else { - dc += weight - } - sumWeights += weight - } - } - return float64(cc-dc) / sumWeights -} - -// Covariance returns the weighted covariance between the samples of x and y. -// -// sum_i {w_i (x_i - meanX) * (y_i - meanY)} / (sum_j {w_j} - 1) -// -// The lengths of x and y must be equal. If weights is nil then all of the -// weights are 1. If weights is not nil, then len(x) must equal len(weights). -func Covariance(x, y, weights []float64) float64 { - // This is a two-pass corrected implementation. It is an adaptation of the - // algorithm used in the MeanVariance function, which applies a correction - // to the typical two pass approach. - - if len(x) != len(y) { - panic("stat: slice length mismatch") - } - xu := Mean(x, weights) - yu := Mean(y, weights) - return covarianceMeans(x, y, weights, xu, yu) -} - -// covarianceMeans returns the weighted covariance between x and y with the mean -// of x and y already specified. See the documentation of Covariance for more -// information. -func covarianceMeans(x, y, weights []float64, xu, yu float64) float64 { - var ( - ss float64 - xcompensation float64 - ycompensation float64 - ) - if weights == nil { - for i, xv := range x { - yv := y[i] - xd := xv - xu - yd := yv - yu - ss += xd * yd - xcompensation += xd - ycompensation += yd - } - // xcompensation and ycompensation are from Chan, et. al. - // referenced in the MeanVariance function. They are analogous - // to the second term in (1.7) in that paper. - return (ss - xcompensation*ycompensation/float64(len(x))) / float64(len(x)-1) - } - - var sumWeights float64 - - for i, xv := range x { - w := weights[i] - yv := y[i] - wxd := w * (xv - xu) - yd := (yv - yu) - ss += wxd * yd - xcompensation += wxd - ycompensation += w * yd - sumWeights += w - } - // xcompensation and ycompensation are from Chan, et. al. - // referenced in the MeanVariance function. They are analogous - // to the second term in (1.7) in that paper, except they use - // the sumWeights instead of the sample count. - return (ss - xcompensation*ycompensation/sumWeights) / (sumWeights - 1) -} - -// CrossEntropy computes the cross-entropy between the two distributions specified -// in p and q. -func CrossEntropy(p, q []float64) float64 { - if len(p) != len(q) { - panic("stat: slice length mismatch") - } - var ce float64 - for i, v := range p { - if v != 0 { - ce -= v * math.Log(q[i]) - } - } - return ce -} - -// Entropy computes the Shannon entropy of a distribution or the distance between -// two distributions. The natural logarithm is used. -// - sum_i (p_i * log_e(p_i)) -func Entropy(p []float64) float64 { - var e float64 - for _, v := range p { - if v != 0 { // Entropy needs 0 * log(0) == 0. - e -= v * math.Log(v) - } - } - return e -} - -// ExKurtosis returns the population excess kurtosis of the sample. -// The kurtosis is defined by the 4th moment of the mean divided by the squared -// variance. The excess kurtosis subtracts 3.0 so that the excess kurtosis of -// the normal distribution is zero. -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func ExKurtosis(x, weights []float64) float64 { - mean, std := MeanStdDev(x, weights) - if weights == nil { - var e float64 - for _, v := range x { - z := (v - mean) / std - e += z * z * z * z - } - mul, offset := kurtosisCorrection(float64(len(x))) - return e*mul - offset - } - - var ( - e float64 - sumWeights float64 - ) - for i, v := range x { - z := (v - mean) / std - e += weights[i] * z * z * z * z - sumWeights += weights[i] - } - mul, offset := kurtosisCorrection(sumWeights) - return e*mul - offset -} - -// n is the number of samples -// see https://en.wikipedia.org/wiki/Kurtosis -func kurtosisCorrection(n float64) (mul, offset float64) { - return ((n + 1) / (n - 1)) * (n / (n - 2)) * (1 / (n - 3)), 3 * ((n - 1) / (n - 2)) * ((n - 1) / (n - 3)) -} - -// GeometricMean returns the weighted geometric mean of the dataset -// -// \prod_i {x_i ^ w_i} -// -// This only applies with positive x and positive weights. If weights is nil -// then all of the weights are 1. If weights is not nil, then len(x) must equal -// len(weights). -func GeometricMean(x, weights []float64) float64 { - if weights == nil { - var s float64 - for _, v := range x { - s += math.Log(v) - } - s /= float64(len(x)) - return math.Exp(s) - } - if len(x) != len(weights) { - panic("stat: slice length mismatch") - } - var ( - s float64 - sumWeights float64 - ) - for i, v := range x { - s += weights[i] * math.Log(v) - sumWeights += weights[i] - } - s /= sumWeights - return math.Exp(s) -} - -// HarmonicMean returns the weighted harmonic mean of the dataset -// -// \sum_i {w_i} / ( sum_i {w_i / x_i} ) -// -// This only applies with positive x and positive weights. -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func HarmonicMean(x, weights []float64) float64 { - if weights != nil && len(x) != len(weights) { - panic("stat: slice length mismatch") - } - // TODO(btracey): Fix this to make it more efficient and avoid allocation. - - // This can be numerically unstable (for example if x is very small). - // W = \sum_i {w_i} - // hm = exp(log(W) - log(\sum_i w_i / x_i)) - - logs := make([]float64, len(x)) - var W float64 - for i := range x { - if weights == nil { - logs[i] = -math.Log(x[i]) - W++ - continue - } - logs[i] = math.Log(weights[i]) - math.Log(x[i]) - W += weights[i] - } - - // Sum all of the logs - v := floats.LogSumExp(logs) // This computes log(\sum_i { w_i / x_i}). - return math.Exp(math.Log(W) - v) -} - -// Hellinger computes the distance between the probability distributions p and q given by: -// -// \sqrt{ 1 - \sum_i \sqrt{p_i q_i} } -// -// The lengths of p and q must be equal. It is assumed that p and q sum to 1. -func Hellinger(p, q []float64) float64 { - if len(p) != len(q) { - panic("stat: slice length mismatch") - } - bc := bhattacharyyaCoeff(p, q) - return math.Sqrt(1 - bc) -} - -// Histogram sums up the weighted number of data points in each bin. -// The weight of data point x[i] will be placed into count[j] if -// dividers[j] <= x < dividers[j+1]. The "span" function in the floats package can assist -// with bin creation. -// -// The following conditions on the inputs apply: -// - The count variable must either be nil or have length of one less than dividers. -// - The values in dividers must be sorted (use the sort package). -// - The x values must be sorted. -// - If weights is nil then all of the weights are 1. -// - If weights is not nil, then len(x) must equal len(weights). -func Histogram(count, dividers, x, weights []float64) []float64 { - if weights != nil && len(x) != len(weights) { - panic("stat: slice length mismatch") - } - if count == nil { - count = make([]float64, len(dividers)-1) - } - if len(dividers) < 2 { - panic("histogram: fewer than two dividers") - } - if len(count) != len(dividers)-1 { - panic("histogram: bin count mismatch") - } - if !sort.Float64sAreSorted(dividers) { - panic("histogram: dividers are not sorted") - } - if !sort.Float64sAreSorted(x) { - panic("histogram: x data are not sorted") - } - for i := range count { - count[i] = 0 - } - if len(x) == 0 { - return count - } - if x[0] < dividers[0] { - panic("histogram: minimum x value is less than lowest divider") - } - if dividers[len(dividers)-1] <= x[len(x)-1] { - panic("histogram: maximum x value is greater than or equal to highest divider") - } - - idx := 0 - comp := dividers[idx+1] - if weights == nil { - for _, v := range x { - if v < comp { - // Still in the current bucket. - count[idx]++ - continue - } - // Find the next divider where v is less than the divider. - for j := idx + 1; j < len(dividers); j++ { - if v < dividers[j+1] { - idx = j - comp = dividers[j+1] - break - } - } - count[idx]++ - } - return count - } - - for i, v := range x { - if v < comp { - // Still in the current bucket. - count[idx] += weights[i] - continue - } - // Need to find the next divider where v is less than the divider. - for j := idx + 1; j < len(count); j++ { - if v < dividers[j+1] { - idx = j - comp = dividers[j+1] - break - } - } - count[idx] += weights[i] - } - return count -} - -// JensenShannon computes the JensenShannon divergence between the distributions -// p and q. The Jensen-Shannon divergence is defined as -// -// m = 0.5 * (p + q) -// JS(p, q) = 0.5 ( KL(p, m) + KL(q, m) ) -// -// Unlike Kullback-Leibler, the Jensen-Shannon distance is symmetric. The value -// is between 0 and ln(2). -func JensenShannon(p, q []float64) float64 { - if len(p) != len(q) { - panic("stat: slice length mismatch") - } - var js float64 - for i, v := range p { - qi := q[i] - m := 0.5 * (v + qi) - if v != 0 { - // add kl from p to m - js += 0.5 * v * (math.Log(v) - math.Log(m)) - } - if qi != 0 { - // add kl from q to m - js += 0.5 * qi * (math.Log(qi) - math.Log(m)) - } - } - return js -} - -// KolmogorovSmirnov computes the largest distance between two empirical CDFs. -// Each dataset x and y consists of sample locations and counts, xWeights and -// yWeights, respectively. -// -// x and y may have different lengths, though len(x) must equal len(xWeights), and -// len(y) must equal len(yWeights). Both x and y must be sorted. -// -// Special cases are: -// -// = 0 if len(x) == len(y) == 0 -// = 1 if len(x) == 0, len(y) != 0 or len(x) != 0 and len(y) == 0 -func KolmogorovSmirnov(x, xWeights, y, yWeights []float64) float64 { - if xWeights != nil && len(x) != len(xWeights) { - panic("stat: slice length mismatch") - } - if yWeights != nil && len(y) != len(yWeights) { - panic("stat: slice length mismatch") - } - if len(x) == 0 || len(y) == 0 { - if len(x) == 0 && len(y) == 0 { - return 0 - } - return 1 - } - - if floats.HasNaN(x) { - return math.NaN() - } - if floats.HasNaN(y) { - return math.NaN() - } - - if !sort.Float64sAreSorted(x) { - panic("x data are not sorted") - } - if !sort.Float64sAreSorted(y) { - panic("y data are not sorted") - } - - xWeightsNil := xWeights == nil - yWeightsNil := yWeights == nil - - var ( - maxDist float64 - xSum, ySum float64 - xCdf, yCdf float64 - xIdx, yIdx int - ) - - if xWeightsNil { - xSum = float64(len(x)) - } else { - xSum = floats.Sum(xWeights) - } - - if yWeightsNil { - ySum = float64(len(y)) - } else { - ySum = floats.Sum(yWeights) - } - - xVal := x[0] - yVal := y[0] - - // Algorithm description: - // The goal is to find the maximum difference in the empirical CDFs for the - // two datasets. The CDFs are piecewise-constant, and thus the distance - // between the CDFs will only change at the values themselves. - // - // To find the maximum distance, step through the data in ascending order - // of value between the two datasets. At each step, compute the empirical CDF - // and compare the local distance with the maximum distance. - // Due to some corner cases, equal data entries must be tallied simultaneously. - for { - switch { - case xVal < yVal: - xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) - case yVal < xVal: - yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) - case xVal == yVal: - newX := x[xIdx] - newY := y[yIdx] - if newX < newY { - xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) - } else if newY < newX { - yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) - } else { - // Update them both, they'll be equal next time and the right - // thing will happen. - xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) - yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) - } - default: - panic("unreachable") - } - - dist := math.Abs(xCdf - yCdf) - if dist > maxDist { - maxDist = dist - } - - // Both xCdf and yCdf will equal 1 at the end, so if we have reached the - // end of either sample list, the distance is as large as it can be. - if xIdx == len(x) || yIdx == len(y) { - return maxDist - } - } -} - -// updateKS gets the next data point from one of the set. In doing so, it combines -// the weight of all the data points of equal value. Upon return, val is the new -// value of the data set, newCdf is the total combined CDF up until this point, -// and newIdx is the index of the next location in that sample to examine. -func updateKS(idx int, cdf, sum float64, values, weights []float64, isNil bool) (val, newCdf float64, newIdx int) { - // Sum up all the weights of consecutive values that are equal. - if isNil { - newCdf = cdf + 1/sum - } else { - newCdf = cdf + weights[idx]/sum - } - newIdx = idx + 1 - for { - if newIdx == len(values) { - return values[newIdx-1], newCdf, newIdx - } - if values[newIdx-1] != values[newIdx] { - return values[newIdx], newCdf, newIdx - } - if isNil { - newCdf += 1 / sum - } else { - newCdf += weights[newIdx] / sum - } - newIdx++ - } -} - -// KullbackLeibler computes the Kullback-Leibler distance between the -// distributions p and q. The natural logarithm is used. -// -// sum_i(p_i * log(p_i / q_i)) -// -// Note that the Kullback-Leibler distance is not symmetric; -// KullbackLeibler(p,q) != KullbackLeibler(q,p) -func KullbackLeibler(p, q []float64) float64 { - if len(p) != len(q) { - panic("stat: slice length mismatch") - } - var kl float64 - for i, v := range p { - if v != 0 { // Entropy needs 0 * log(0) == 0. - kl += v * (math.Log(v) - math.Log(q[i])) - } - } - return kl -} - -// LinearRegression computes the best-fit line -// -// y = alpha + beta*x -// -// to the data in x and y with the given weights. If origin is true, the -// regression is forced to pass through the origin. -// -// Specifically, LinearRegression computes the values of alpha and -// beta such that the total residual -// -// \sum_i w[i]*(y[i] - alpha - beta*x[i])^2 -// -// is minimized. If origin is true, then alpha is forced to be zero. -// -// The lengths of x and y must be equal. If weights is nil then all of the -// weights are 1. If weights is not nil, then len(x) must equal len(weights). -func LinearRegression(x, y, weights []float64, origin bool) (alpha, beta float64) { - if len(x) != len(y) { - panic("stat: slice length mismatch") - } - if weights != nil && len(weights) != len(x) { - panic("stat: slice length mismatch") - } - - w := 1.0 - if origin { - var x2Sum, xySum float64 - for i, xi := range x { - if weights != nil { - w = weights[i] - } - yi := y[i] - xySum += w * xi * yi - x2Sum += w * xi * xi - } - beta = xySum / x2Sum - - return 0, beta - } - - xu, xv := MeanVariance(x, weights) - yu := Mean(y, weights) - cov := covarianceMeans(x, y, weights, xu, yu) - beta = cov / xv - alpha = yu - beta*xu - return alpha, beta -} - -// RSquared returns the coefficient of determination defined as -// -// R^2 = 1 - \sum_i w[i]*(y[i] - alpha - beta*x[i])^2 / \sum_i w[i]*(y[i] - mean(y))^2 -// -// for the line -// -// y = alpha + beta*x -// -// and the data in x and y with the given weights. -// -// The lengths of x and y must be equal. If weights is nil then all of the -// weights are 1. If weights is not nil, then len(x) must equal len(weights). -func RSquared(x, y, weights []float64, alpha, beta float64) float64 { - if len(x) != len(y) { - panic("stat: slice length mismatch") - } - if weights != nil && len(weights) != len(x) { - panic("stat: slice length mismatch") - } - - w := 1.0 - yMean := Mean(y, weights) - var res, tot, d float64 - for i, xi := range x { - if weights != nil { - w = weights[i] - } - yi := y[i] - fi := alpha + beta*xi - d = yi - fi - res += w * d * d - d = yi - yMean - tot += w * d * d - } - return 1 - res/tot -} - -// RSquaredFrom returns the coefficient of determination defined as -// -// R^2 = 1 - \sum_i w[i]*(estimate[i] - value[i])^2 / \sum_i w[i]*(value[i] - mean(values))^2 -// -// and the data in estimates and values with the given weights. -// -// The lengths of estimates and values must be equal. If weights is nil then -// all of the weights are 1. If weights is not nil, then len(values) must -// equal len(weights). -func RSquaredFrom(estimates, values, weights []float64) float64 { - if len(estimates) != len(values) { - panic("stat: slice length mismatch") - } - if weights != nil && len(weights) != len(values) { - panic("stat: slice length mismatch") - } - - w := 1.0 - mean := Mean(values, weights) - var res, tot, d float64 - for i, val := range values { - if weights != nil { - w = weights[i] - } - d = val - estimates[i] - res += w * d * d - d = val - mean - tot += w * d * d - } - return 1 - res/tot -} - -// RNoughtSquared returns the coefficient of determination defined as -// -// R₀^2 = \sum_i w[i]*(beta*x[i])^2 / \sum_i w[i]*y[i]^2 -// -// for the line -// -// y = beta*x -// -// and the data in x and y with the given weights. RNoughtSquared should -// only be used for best-fit lines regressed through the origin. -// -// The lengths of x and y must be equal. If weights is nil then all of the -// weights are 1. If weights is not nil, then len(x) must equal len(weights). -func RNoughtSquared(x, y, weights []float64, beta float64) float64 { - if len(x) != len(y) { - panic("stat: slice length mismatch") - } - if weights != nil && len(weights) != len(x) { - panic("stat: slice length mismatch") - } - - w := 1.0 - var ssr, tot float64 - for i, xi := range x { - if weights != nil { - w = weights[i] - } - fi := beta * xi - ssr += w * fi * fi - yi := y[i] - tot += w * yi * yi - } - return ssr / tot -} - -// Mean computes the weighted mean of the data set. -// -// sum_i {w_i * x_i} / sum_i {w_i} -// -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func Mean(x, weights []float64) float64 { - if weights == nil { - return floats.Sum(x) / float64(len(x)) - } - if len(x) != len(weights) { - panic("stat: slice length mismatch") - } - var ( - sumValues float64 - sumWeights float64 - ) - for i, w := range weights { - sumValues += w * x[i] - sumWeights += w - } - return sumValues / sumWeights -} - -// Mode returns the most common value in the dataset specified by x and the -// given weights. Strict float64 equality is used when comparing values, so users -// should take caution. If several values are the mode, any of them may be returned. -func Mode(x, weights []float64) (val float64, count float64) { - if weights != nil && len(x) != len(weights) { - panic("stat: slice length mismatch") - } - if len(x) == 0 { - return 0, 0 - } - m := make(map[float64]float64) - if weights == nil { - for _, v := range x { - m[v]++ - } - } else { - for i, v := range x { - m[v] += weights[i] - } - } - var ( - maxCount float64 - max float64 - ) - for val, count := range m { - if count > maxCount { - maxCount = count - max = val - } - } - return max, maxCount -} - -// BivariateMoment computes the weighted mixed moment between the samples x and y. -// -// E[(x - μ_x)^r*(y - μ_y)^s] -// -// No degrees of freedom correction is done. -// The lengths of x and y must be equal. If weights is nil then all of the -// weights are 1. If weights is not nil, then len(x) must equal len(weights). -func BivariateMoment(r, s float64, x, y, weights []float64) float64 { - meanX := Mean(x, weights) - meanY := Mean(y, weights) - if len(x) != len(y) { - panic("stat: slice length mismatch") - } - if weights == nil { - var m float64 - for i, vx := range x { - vy := y[i] - m += math.Pow(vx-meanX, r) * math.Pow(vy-meanY, s) - } - return m / float64(len(x)) - } - if len(weights) != len(x) { - panic("stat: slice length mismatch") - } - var ( - m float64 - sumWeights float64 - ) - for i, vx := range x { - vy := y[i] - w := weights[i] - m += w * math.Pow(vx-meanX, r) * math.Pow(vy-meanY, s) - sumWeights += w - } - return m / sumWeights -} - -// Moment computes the weighted n^th moment of the samples, -// -// E[(x - μ)^N] -// -// No degrees of freedom correction is done. -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func Moment(moment float64, x, weights []float64) float64 { - // This also checks that x and weights have the same length. - mean := Mean(x, weights) - if weights == nil { - var m float64 - for _, v := range x { - m += math.Pow(v-mean, moment) - } - return m / float64(len(x)) - } - var ( - m float64 - sumWeights float64 - ) - for i, v := range x { - w := weights[i] - m += w * math.Pow(v-mean, moment) - sumWeights += w - } - return m / sumWeights -} - -// MomentAbout computes the weighted n^th weighted moment of the samples about -// the given mean \mu, -// -// E[(x - μ)^N] -// -// No degrees of freedom correction is done. -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func MomentAbout(moment float64, x []float64, mean float64, weights []float64) float64 { - if weights == nil { - var m float64 - for _, v := range x { - m += math.Pow(v-mean, moment) - } - m /= float64(len(x)) - return m - } - if len(weights) != len(x) { - panic("stat: slice length mismatch") - } - var ( - m float64 - sumWeights float64 - ) - for i, v := range x { - m += weights[i] * math.Pow(v-mean, moment) - sumWeights += weights[i] - } - return m / sumWeights -} - -// Quantile returns the sample of x such that x is greater than or -// equal to the fraction p of samples. The exact behavior is determined by the -// CumulantKind, and p should be a number between 0 and 1. Quantile is theoretically -// the inverse of the CDF function, though it may not be the actual inverse -// for all values p and CumulantKinds. -// -// The x data must be sorted in increasing order. If weights is nil then all -// of the weights are 1. If weights is not nil, then len(x) must equal len(weights). -// Quantile will panic if the length of x is zero. -// -// CumulantKind behaviors: -// - Empirical: Returns the lowest value q for which q is greater than or equal -// to the fraction p of samples -// - LinInterp: Returns the linearly interpolated value -func Quantile(p float64, c CumulantKind, x, weights []float64) float64 { - if !(p >= 0 && p <= 1) { - panic("stat: percentile out of bounds") - } - - if weights != nil && len(x) != len(weights) { - panic("stat: slice length mismatch") - } - if len(x) == 0 { - panic("stat: zero length slice") - } - if floats.HasNaN(x) { - return math.NaN() // This is needed because the algorithm breaks otherwise. - } - if !sort.Float64sAreSorted(x) { - panic("x data are not sorted") - } - - var sumWeights float64 - if weights == nil { - sumWeights = float64(len(x)) - } else { - sumWeights = floats.Sum(weights) - } - switch c { - case Empirical: - return empiricalQuantile(p, x, weights, sumWeights) - case LinInterp: - return linInterpQuantile(p, x, weights, sumWeights) - default: - panic("stat: bad cumulant kind") - } -} - -func empiricalQuantile(p float64, x, weights []float64, sumWeights float64) float64 { - var cumsum float64 - fidx := p * sumWeights - for i := range x { - if weights == nil { - cumsum++ - } else { - cumsum += weights[i] - } - if cumsum >= fidx { - return x[i] - } - } - panic("impossible") -} - -func linInterpQuantile(p float64, x, weights []float64, sumWeights float64) float64 { - var cumsum float64 - fidx := p * sumWeights - for i := range x { - if weights == nil { - cumsum++ - } else { - cumsum += weights[i] - } - if cumsum >= fidx { - if i == 0 { - return x[0] - } - t := cumsum - fidx - if weights != nil { - t /= weights[i] - } - return t*x[i-1] + (1-t)*x[i] - } - } - panic("impossible") -} - -// Skew computes the skewness of the sample data. -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -// When weights sum to 1 or less, a biased variance estimator should be used. -func Skew(x, weights []float64) float64 { - - mean, std := MeanStdDev(x, weights) - if weights == nil { - var s float64 - for _, v := range x { - z := (v - mean) / std - s += z * z * z - } - return s * skewCorrection(float64(len(x))) - } - var ( - s float64 - sumWeights float64 - ) - for i, v := range x { - z := (v - mean) / std - s += weights[i] * z * z * z - sumWeights += weights[i] - } - return s * skewCorrection(sumWeights) -} - -// From: http://www.amstat.org/publications/jse/v19n2/doane.pdf page 7 -func skewCorrection(n float64) float64 { - return (n / (n - 1)) * (1 / (n - 2)) -} - -// SortWeighted rearranges the data in x along with their corresponding -// weights so that the x data are sorted. The data is sorted in place. -// Weights may be nil, but if weights is non-nil then it must have the same -// length as x. -func SortWeighted(x, weights []float64) { - if weights == nil { - sort.Float64s(x) - return - } - if len(x) != len(weights) { - panic("stat: slice length mismatch") - } - sort.Sort(weightSorter{ - x: x, - w: weights, - }) -} - -type weightSorter struct { - x []float64 - w []float64 -} - -func (w weightSorter) Len() int { return len(w.x) } -func (w weightSorter) Less(i, j int) bool { return w.x[i] < w.x[j] } -func (w weightSorter) Swap(i, j int) { - w.x[i], w.x[j] = w.x[j], w.x[i] - w.w[i], w.w[j] = w.w[j], w.w[i] -} - -// SortWeightedLabeled rearranges the data in x along with their -// corresponding weights and boolean labels so that the x data are sorted. -// The data is sorted in place. Weights and labels may be nil, if either -// is non-nil it must have the same length as x. -func SortWeightedLabeled(x []float64, labels []bool, weights []float64) { - if labels == nil { - SortWeighted(x, weights) - return - } - if weights == nil { - if len(x) != len(labels) { - panic("stat: slice length mismatch") - } - sort.Sort(labelSorter{ - x: x, - l: labels, - }) - return - } - if len(x) != len(labels) || len(x) != len(weights) { - panic("stat: slice length mismatch") - } - sort.Sort(weightLabelSorter{ - x: x, - l: labels, - w: weights, - }) -} - -type labelSorter struct { - x []float64 - l []bool -} - -func (a labelSorter) Len() int { return len(a.x) } -func (a labelSorter) Less(i, j int) bool { return a.x[i] < a.x[j] } -func (a labelSorter) Swap(i, j int) { - a.x[i], a.x[j] = a.x[j], a.x[i] - a.l[i], a.l[j] = a.l[j], a.l[i] -} - -type weightLabelSorter struct { - x []float64 - l []bool - w []float64 -} - -func (a weightLabelSorter) Len() int { return len(a.x) } -func (a weightLabelSorter) Less(i, j int) bool { return a.x[i] < a.x[j] } -func (a weightLabelSorter) Swap(i, j int) { - a.x[i], a.x[j] = a.x[j], a.x[i] - a.l[i], a.l[j] = a.l[j], a.l[i] - a.w[i], a.w[j] = a.w[j], a.w[i] -} - -// StdDev returns the sample standard deviation. -func StdDev(x, weights []float64) float64 { - _, std := MeanStdDev(x, weights) - return std -} - -// MeanStdDev returns the sample mean and unbiased standard deviation -// When weights sum to 1 or less, a biased variance estimator should be used. -func MeanStdDev(x, weights []float64) (mean, std float64) { - mean, variance := MeanVariance(x, weights) - return mean, math.Sqrt(variance) -} - -// StdErr returns the standard error in the mean with the given values. -func StdErr(std, sampleSize float64) float64 { - return std / math.Sqrt(sampleSize) -} - -// StdScore returns the standard score (a.k.a. z-score, z-value) for the value x -// with the given mean and standard deviation, i.e. -// -// (x - mean) / std -func StdScore(x, mean, std float64) float64 { - return (x - mean) / std -} - -// Variance computes the unbiased weighted sample variance: -// -// \sum_i w_i (x_i - mean)^2 / (sum_i w_i - 1) -// -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -// When weights sum to 1 or less, a biased variance estimator should be used. -func Variance(x, weights []float64) float64 { - _, variance := MeanVariance(x, weights) - return variance -} - -// MeanVariance computes the sample mean and unbiased variance, where the mean and variance are -// -// \sum_i w_i * x_i / (sum_i w_i) -// \sum_i w_i (x_i - mean)^2 / (sum_i w_i - 1) -// -// respectively. -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -// When weights sum to 1 or less, a biased variance estimator should be used. -func MeanVariance(x, weights []float64) (mean, variance float64) { - var ( - unnormalisedVariance float64 - sumWeights float64 - ) - mean, unnormalisedVariance, sumWeights = meanUnnormalisedVarianceSumWeights(x, weights) - return mean, unnormalisedVariance / (sumWeights - 1) -} - -// PopMeanVariance computes the sample mean and biased variance (also known as -// "population variance"), where the mean and variance are -// -// \sum_i w_i * x_i / (sum_i w_i) -// \sum_i w_i (x_i - mean)^2 / (sum_i w_i) -// -// respectively. -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func PopMeanVariance(x, weights []float64) (mean, variance float64) { - var ( - unnormalisedVariance float64 - sumWeights float64 - ) - mean, unnormalisedVariance, sumWeights = meanUnnormalisedVarianceSumWeights(x, weights) - return mean, unnormalisedVariance / sumWeights -} - -// PopMeanStdDev returns the sample mean and biased standard deviation -// (also known as "population standard deviation"). -func PopMeanStdDev(x, weights []float64) (mean, std float64) { - mean, variance := PopMeanVariance(x, weights) - return mean, math.Sqrt(variance) -} - -// PopStdDev returns the population standard deviation, i.e., a square root -// of the biased variance estimate. -func PopStdDev(x, weights []float64) float64 { - _, stDev := PopMeanStdDev(x, weights) - return stDev -} - -// PopVariance computes the unbiased weighted sample variance: -// -// \sum_i w_i (x_i - mean)^2 / (sum_i w_i) -// -// If weights is nil then all of the weights are 1. If weights is not nil, then -// len(x) must equal len(weights). -func PopVariance(x, weights []float64) float64 { - _, variance := PopMeanVariance(x, weights) - return variance -} - -func meanUnnormalisedVarianceSumWeights(x, weights []float64) (mean, unnormalisedVariance, sumWeights float64) { - // This uses the corrected two-pass algorithm (1.7), from "Algorithms for computing - // the sample variance: Analysis and recommendations" by Chan, Tony F., Gene H. Golub, - // and Randall J. LeVeque. - - // Note that this will panic if the slice lengths do not match. - mean = Mean(x, weights) - var ( - ss float64 - compensation float64 - ) - if weights == nil { - for _, v := range x { - d := v - mean - ss += d * d - compensation += d - } - unnormalisedVariance = (ss - compensation*compensation/float64(len(x))) - return mean, unnormalisedVariance, float64(len(x)) - } - - for i, v := range x { - w := weights[i] - d := v - mean - wd := w * d - ss += wd * d - compensation += wd - sumWeights += w - } - unnormalisedVariance = (ss - compensation*compensation/sumWeights) - return mean, unnormalisedVariance, sumWeights -} diff --git a/vendor/gonum.org/v1/gonum/stat/statmat.go b/vendor/gonum.org/v1/gonum/stat/statmat.go deleted file mode 100644 index 4f05f306..00000000 --- a/vendor/gonum.org/v1/gonum/stat/statmat.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright ©2014 The Gonum 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 stat - -import ( - "math" - - "gonum.org/v1/gonum/floats" - "gonum.org/v1/gonum/mat" -) - -// CovarianceMatrix calculates the covariance matrix (also known as the -// variance-covariance matrix) calculated from a matrix of data, x, using -// a two-pass algorithm. The result is stored in dst. -// -// If weights is not nil the weighted covariance of x is calculated. weights -// must have length equal to the number of rows in input data matrix and -// must not contain negative elements. -// The dst matrix must either be empty or have the same number of -// columns as the input data matrix. -func CovarianceMatrix(dst *mat.SymDense, x mat.Matrix, weights []float64) { - // This is the matrix version of the two-pass algorithm. It doesn't use the - // additional floating point error correction that the Covariance function uses - // to reduce the impact of rounding during centering. - - r, c := x.Dims() - - if dst.IsEmpty() { - *dst = *(dst.GrowSym(c).(*mat.SymDense)) - } else if n := dst.SymmetricDim(); n != c { - panic(mat.ErrShape) - } - - var xt mat.Dense - xt.CloneFrom(x.T()) - // Subtract the mean of each of the columns. - for i := 0; i < c; i++ { - v := xt.RawRowView(i) - // This will panic with ErrShape if len(weights) != len(v), so - // we don't have to check the size later. - mean := Mean(v, weights) - floats.AddConst(-mean, v) - } - - if weights == nil { - // Calculate the normalization factor - // scaled by the sample size. - dst.SymOuterK(1/(float64(r)-1), &xt) - return - } - - // Multiply by the sqrt of the weights, so that multiplication is symmetric. - sqrtwts := make([]float64, r) - for i, w := range weights { - if w < 0 { - panic("stat: negative covariance matrix weights") - } - sqrtwts[i] = math.Sqrt(w) - } - // Weight the rows. - for i := 0; i < c; i++ { - v := xt.RawRowView(i) - floats.Mul(v, sqrtwts) - } - - // Calculate the normalization factor - // scaled by the weighted sample size. - dst.SymOuterK(1/(floats.Sum(weights)-1), &xt) -} - -// CorrelationMatrix returns the correlation matrix calculated from a matrix -// of data, x, using a two-pass algorithm. The result is stored in dst. -// -// If weights is not nil the weighted correlation of x is calculated. weights -// must have length equal to the number of rows in input data matrix and -// must not contain negative elements. -// The dst matrix must either be empty or have the same number of -// columns as the input data matrix. -func CorrelationMatrix(dst *mat.SymDense, x mat.Matrix, weights []float64) { - // This will panic if the sizes don't match, or if weights is the wrong size. - CovarianceMatrix(dst, x, weights) - covToCorr(dst) -} - -// covToCorr converts a covariance matrix to a correlation matrix. -func covToCorr(c *mat.SymDense) { - r := c.SymmetricDim() - - s := make([]float64, r) - for i := 0; i < r; i++ { - s[i] = 1 / math.Sqrt(c.At(i, i)) - } - for i, sx := range s { - // Ensure that the diagonal has exactly ones. - c.SetSym(i, i, 1) - for j := i + 1; j < r; j++ { - v := c.At(i, j) - c.SetSym(i, j, v*sx*s[j]) - } - } -} - -// corrToCov converts a correlation matrix to a covariance matrix. -// The input sigma should be vector of standard deviations corresponding -// to the covariance. It will panic if len(sigma) is not equal to the -// number of rows in the correlation matrix. -func corrToCov(c *mat.SymDense, sigma []float64) { - r, _ := c.Dims() - - if r != len(sigma) { - panic(mat.ErrShape) - } - for i, sx := range sigma { - // Ensure that the diagonal has exactly sigma squared. - c.SetSym(i, i, sx*sx) - for j := i + 1; j < r; j++ { - v := c.At(i, j) - c.SetSym(i, j, v*sx*sigma[j]) - } - } -} - -// Mahalanobis computes the Mahalanobis distance -// -// D = sqrt((x-y)ᵀ * Σ^-1 * (x-y)) -// -// between the column vectors x and y given the cholesky decomposition of Σ. -// Mahalanobis returns NaN if the linear solve fails. -// -// See https://en.wikipedia.org/wiki/Mahalanobis_distance for more information. -func Mahalanobis(x, y mat.Vector, chol *mat.Cholesky) float64 { - var diff mat.VecDense - diff.SubVec(x, y) - var tmp mat.VecDense - err := chol.SolveVecTo(&tmp, &diff) - if err != nil { - return math.NaN() - } - return math.Sqrt(mat.Dot(&tmp, &diff)) -} 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 deleted file mode 100644 index e017ef07..00000000 --- a/vendor/google.golang.org/genproto/googleapis/rpc/errdetails/error_details.pb.go +++ /dev/null @@ -1,1473 +0,0 @@ -// Copyright 2025 Google LLC -// -// 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. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v4.24.4 -// source: google/rpc/error_details.proto - -package errdetails - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Describes the cause of the error with structured details. -// -// Example of an error when contacting the "pubsub.googleapis.com" API when it -// is not enabled: -// -// { "reason": "API_DISABLED" -// "domain": "googleapis.com" -// "metadata": { -// "resource": "projects/123", -// "service": "pubsub.googleapis.com" -// } -// } -// -// This response indicates that the pubsub.googleapis.com API is not enabled. -// -// Example of an error that is returned when attempting to create a Spanner -// instance in a region that is out of stock: -// -// { "reason": "STOCKOUT" -// "domain": "spanner.googleapis.com", -// "metadata": { -// "availableRegions": "us-central1,us-east2" -// } -// } -type ErrorInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The reason of the error. This is a constant value that identifies the - // proximate cause of the error. Error reasons are unique within a particular - // domain of errors. 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,1,opt,name=reason,proto3" json:"reason,omitempty"` - // The logical grouping to which the "reason" belongs. The error domain - // is typically the registered service name of the tool or product that - // generates the error. Example: "pubsub.googleapis.com". If the error is - // generated by some common infrastructure, the error domain must be a - // globally unique value that identifies the infrastructure. For Google API - // infrastructure, the error domain is "googleapis.com". - Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"` - // Additional structured details about this error. - // - // 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 - // 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"` -} - -func (x *ErrorInfo) Reset() { - *x = ErrorInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ErrorInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ErrorInfo) ProtoMessage() {} - -func (x *ErrorInfo) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ErrorInfo.ProtoReflect.Descriptor instead. -func (*ErrorInfo) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{0} -} - -func (x *ErrorInfo) GetReason() string { - if x != nil { - return x.Reason - } - return "" -} - -func (x *ErrorInfo) GetDomain() string { - if x != nil { - return x.Domain - } - return "" -} - -func (x *ErrorInfo) GetMetadata() map[string]string { - if x != nil { - return x.Metadata - } - return nil -} - -// Describes when the clients can retry a failed request. Clients could ignore -// the recommendation here or retry when this information is missing from error -// responses. -// -// It's always recommended that clients should use exponential backoff when -// retrying. -// -// Clients should wait until `retry_delay` amount of time has passed since -// receiving the error response before retrying. If retrying requests also -// fail, clients should use an exponential backoff scheme to gradually increase -// the delay between retries based on `retry_delay`, until either a maximum -// number of retries have been reached or a maximum retry delay cap has been -// reached. -type RetryInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Clients should wait at least this long between retrying the same request. - RetryDelay *durationpb.Duration `protobuf:"bytes,1,opt,name=retry_delay,json=retryDelay,proto3" json:"retry_delay,omitempty"` -} - -func (x *RetryInfo) Reset() { - *x = RetryInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RetryInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RetryInfo) ProtoMessage() {} - -func (x *RetryInfo) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RetryInfo.ProtoReflect.Descriptor instead. -func (*RetryInfo) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{1} -} - -func (x *RetryInfo) GetRetryDelay() *durationpb.Duration { - if x != nil { - return x.RetryDelay - } - return nil -} - -// Describes additional debugging info. -type DebugInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The stack trace entries indicating where the error occurred. - StackEntries []string `protobuf:"bytes,1,rep,name=stack_entries,json=stackEntries,proto3" json:"stack_entries,omitempty"` - // Additional debugging information provided by the server. - Detail string `protobuf:"bytes,2,opt,name=detail,proto3" json:"detail,omitempty"` -} - -func (x *DebugInfo) Reset() { - *x = DebugInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DebugInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DebugInfo) ProtoMessage() {} - -func (x *DebugInfo) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DebugInfo.ProtoReflect.Descriptor instead. -func (*DebugInfo) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{2} -} - -func (x *DebugInfo) GetStackEntries() []string { - if x != nil { - return x.StackEntries - } - return nil -} - -func (x *DebugInfo) GetDetail() string { - if x != nil { - return x.Detail - } - return "" -} - -// Describes how a quota check failed. -// -// For example if a daily limit was exceeded for the calling project, -// a service could respond with a QuotaFailure detail containing the project -// id and the description of the quota limit that was exceeded. If the -// calling project hasn't enabled the service in the developer console, then -// a service could respond with the project id and set `service_disabled` -// to true. -// -// Also see RetryInfo and Help types for other details about handling a -// quota failure. -type QuotaFailure struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Describes all quota violations. - Violations []*QuotaFailure_Violation `protobuf:"bytes,1,rep,name=violations,proto3" json:"violations,omitempty"` -} - -func (x *QuotaFailure) Reset() { - *x = QuotaFailure{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QuotaFailure) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QuotaFailure) ProtoMessage() {} - -func (x *QuotaFailure) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QuotaFailure.ProtoReflect.Descriptor instead. -func (*QuotaFailure) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{3} -} - -func (x *QuotaFailure) GetViolations() []*QuotaFailure_Violation { - if x != nil { - return x.Violations - } - return nil -} - -// Describes what preconditions have failed. -// -// For example, if an RPC failed because it required the Terms of Service to be -// acknowledged, it could list the terms of service violation in the -// PreconditionFailure message. -type PreconditionFailure struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Describes all precondition violations. - Violations []*PreconditionFailure_Violation `protobuf:"bytes,1,rep,name=violations,proto3" json:"violations,omitempty"` -} - -func (x *PreconditionFailure) Reset() { - *x = PreconditionFailure{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PreconditionFailure) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PreconditionFailure) ProtoMessage() {} - -func (x *PreconditionFailure) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PreconditionFailure.ProtoReflect.Descriptor instead. -func (*PreconditionFailure) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{4} -} - -func (x *PreconditionFailure) GetViolations() []*PreconditionFailure_Violation { - if x != nil { - return x.Violations - } - return nil -} - -// Describes violations in a client request. This error type focuses on the -// syntactic aspects of the request. -type BadRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Describes all violations in a client request. - FieldViolations []*BadRequest_FieldViolation `protobuf:"bytes,1,rep,name=field_violations,json=fieldViolations,proto3" json:"field_violations,omitempty"` -} - -func (x *BadRequest) Reset() { - *x = BadRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BadRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BadRequest) ProtoMessage() {} - -func (x *BadRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BadRequest.ProtoReflect.Descriptor instead. -func (*BadRequest) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{5} -} - -func (x *BadRequest) GetFieldViolations() []*BadRequest_FieldViolation { - if x != nil { - return x.FieldViolations - } - return nil -} - -// Contains metadata about the request that clients can attach when filing a bug -// or providing other forms of feedback. -type RequestInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // An opaque string that should only be interpreted by the service generating - // it. For example, it can be used to identify requests in the service's logs. - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - // Any data that was used to serve this request. For example, an encrypted - // stack trace that can be sent back to the service provider for debugging. - ServingData string `protobuf:"bytes,2,opt,name=serving_data,json=servingData,proto3" json:"serving_data,omitempty"` -} - -func (x *RequestInfo) Reset() { - *x = RequestInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RequestInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RequestInfo) ProtoMessage() {} - -func (x *RequestInfo) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RequestInfo.ProtoReflect.Descriptor instead. -func (*RequestInfo) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{6} -} - -func (x *RequestInfo) GetRequestId() string { - if x != nil { - return x.RequestId - } - return "" -} - -func (x *RequestInfo) GetServingData() string { - if x != nil { - return x.ServingData - } - return "" -} - -// Describes the resource that is being accessed. -type ResourceInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // A name for the type of resource being accessed, e.g. "sql table", - // "cloud storage bucket", "file", "Google calendar"; or the type URL - // of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic". - ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - // The name of the resource being accessed. For example, a shared calendar - // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current - // error is - // [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED]. - ResourceName string `protobuf:"bytes,2,opt,name=resource_name,json=resourceName,proto3" json:"resource_name,omitempty"` - // The owner of the resource (optional). - // For example, "user:<owner email>" or "project:<Google developer project - // id>". - Owner string `protobuf:"bytes,3,opt,name=owner,proto3" json:"owner,omitempty"` - // Describes what error is encountered when accessing this resource. - // For example, updating a cloud project may require the `writer` permission - // on the developer console project. - Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` -} - -func (x *ResourceInfo) Reset() { - *x = ResourceInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResourceInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResourceInfo) ProtoMessage() {} - -func (x *ResourceInfo) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResourceInfo.ProtoReflect.Descriptor instead. -func (*ResourceInfo) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{7} -} - -func (x *ResourceInfo) GetResourceType() string { - if x != nil { - return x.ResourceType - } - return "" -} - -func (x *ResourceInfo) GetResourceName() string { - if x != nil { - return x.ResourceName - } - return "" -} - -func (x *ResourceInfo) GetOwner() string { - if x != nil { - return x.Owner - } - return "" -} - -func (x *ResourceInfo) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -// Provides links to documentation or for performing an out of band action. -// -// For example, if a quota check failed with an error indicating the calling -// project hasn't enabled the accessed service, this can contain a URL pointing -// directly to the right place in the developer console to flip the bit. -type Help struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // URL(s) pointing to additional information on handling the current error. - Links []*Help_Link `protobuf:"bytes,1,rep,name=links,proto3" json:"links,omitempty"` -} - -func (x *Help) Reset() { - *x = Help{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Help) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Help) ProtoMessage() {} - -func (x *Help) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Help.ProtoReflect.Descriptor instead. -func (*Help) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{8} -} - -func (x *Help) GetLinks() []*Help_Link { - if x != nil { - return x.Links - } - return nil -} - -// Provides a localized error message that is safe to return to the user -// which can be attached to an RPC error. -type LocalizedMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The locale used following the specification defined at - // https://www.rfc-editor.org/rfc/bcp/bcp47.txt. - // Examples are: "en-US", "fr-CH", "es-MX" - Locale string `protobuf:"bytes,1,opt,name=locale,proto3" json:"locale,omitempty"` - // The localized error message in the above locale. - Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` -} - -func (x *LocalizedMessage) Reset() { - *x = LocalizedMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LocalizedMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LocalizedMessage) ProtoMessage() {} - -func (x *LocalizedMessage) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LocalizedMessage.ProtoReflect.Descriptor instead. -func (*LocalizedMessage) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{9} -} - -func (x *LocalizedMessage) GetLocale() string { - if x != nil { - return x.Locale - } - return "" -} - -func (x *LocalizedMessage) GetMessage() string { - if x != nil { - return x.Message - } - return "" -} - -// A message type used to describe a single quota violation. For example, a -// daily quota or a custom quota that was exceeded. -type QuotaFailure_Violation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The subject on which the quota check failed. - // For example, "clientip:<ip address of client>" or "project:<Google - // developer project id>". - Subject string `protobuf:"bytes,1,opt,name=subject,proto3" json:"subject,omitempty"` - // A description of how the quota check failed. Clients can use this - // description to find more about the quota configuration in the service's - // public documentation, or find the relevant quota limit to adjust through - // developer console. - // - // For example: "Service disabled" or "Daily Limit for read operations - // exceeded". - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - // The API Service from which the `QuotaFailure.Violation` orginates. In - // some cases, Quota issues originate from an API Service other than the one - // that was called. In other words, a dependency of the called API Service - // could be the cause of the `QuotaFailure`, and this field would have the - // dependency API service name. - // - // For example, if the called API is Kubernetes Engine API - // (container.googleapis.com), and a quota violation occurs in the - // Kubernetes Engine API itself, this field would be - // "container.googleapis.com". On the other hand, if the quota violation - // occurs when the Kubernetes Engine API creates VMs in the Compute Engine - // API (compute.googleapis.com), this field would be - // "compute.googleapis.com". - ApiService string `protobuf:"bytes,3,opt,name=api_service,json=apiService,proto3" json:"api_service,omitempty"` - // The metric of the violated quota. A quota metric is a named counter to - // measure usage, such as API requests or CPUs. When an activity occurs in a - // service, such as Virtual Machine allocation, one or more quota metrics - // may be affected. - // - // For example, "compute.googleapis.com/cpus_per_vm_family", - // "storage.googleapis.com/internet_egress_bandwidth". - QuotaMetric string `protobuf:"bytes,4,opt,name=quota_metric,json=quotaMetric,proto3" json:"quota_metric,omitempty"` - // The id of the violated quota. Also know as "limit name", this is the - // unique identifier of a quota in the context of an API service. - // - // For example, "CPUS-PER-VM-FAMILY-per-project-region". - QuotaId string `protobuf:"bytes,5,opt,name=quota_id,json=quotaId,proto3" json:"quota_id,omitempty"` - // The dimensions of the violated quota. Every non-global quota is enforced - // on a set of dimensions. While quota metric defines what to count, the - // dimensions specify for what aspects the counter should be increased. - // - // For example, the quota "CPUs per region per VM family" enforces a limit - // on the metric "compute.googleapis.com/cpus_per_vm_family" on dimensions - // "region" and "vm_family". And if the violation occurred in region - // "us-central1" and for VM family "n1", the quota_dimensions would be, - // - // { - // "region": "us-central1", - // "vm_family": "n1", - // } - // - // When a quota is enforced globally, the quota_dimensions would always be - // empty. - QuotaDimensions map[string]string `protobuf:"bytes,6,rep,name=quota_dimensions,json=quotaDimensions,proto3" json:"quota_dimensions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - // The enforced quota value at the time of the `QuotaFailure`. - // - // For example, if the enforced quota value at the time of the - // `QuotaFailure` on the number of CPUs is "10", then the value of this - // field would reflect this quantity. - QuotaValue int64 `protobuf:"varint,7,opt,name=quota_value,json=quotaValue,proto3" json:"quota_value,omitempty"` - // The new quota value being rolled out at the time of the violation. At the - // completion of the rollout, this value will be enforced in place of - // quota_value. If no rollout is in progress at the time of the violation, - // this field is not set. - // - // For example, if at the time of the violation a rollout is in progress - // changing the number of CPUs quota from 10 to 20, 20 would be the value of - // this field. - FutureQuotaValue *int64 `protobuf:"varint,8,opt,name=future_quota_value,json=futureQuotaValue,proto3,oneof" json:"future_quota_value,omitempty"` -} - -func (x *QuotaFailure_Violation) Reset() { - *x = QuotaFailure_Violation{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QuotaFailure_Violation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QuotaFailure_Violation) ProtoMessage() {} - -func (x *QuotaFailure_Violation) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QuotaFailure_Violation.ProtoReflect.Descriptor instead. -func (*QuotaFailure_Violation) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{3, 0} -} - -func (x *QuotaFailure_Violation) GetSubject() string { - if x != nil { - return x.Subject - } - return "" -} - -func (x *QuotaFailure_Violation) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *QuotaFailure_Violation) GetApiService() string { - if x != nil { - return x.ApiService - } - return "" -} - -func (x *QuotaFailure_Violation) GetQuotaMetric() string { - if x != nil { - return x.QuotaMetric - } - return "" -} - -func (x *QuotaFailure_Violation) GetQuotaId() string { - if x != nil { - return x.QuotaId - } - return "" -} - -func (x *QuotaFailure_Violation) GetQuotaDimensions() map[string]string { - if x != nil { - return x.QuotaDimensions - } - return nil -} - -func (x *QuotaFailure_Violation) GetQuotaValue() int64 { - if x != nil { - return x.QuotaValue - } - return 0 -} - -func (x *QuotaFailure_Violation) GetFutureQuotaValue() int64 { - if x != nil && x.FutureQuotaValue != nil { - return *x.FutureQuotaValue - } - return 0 -} - -// A message type used to describe a single precondition failure. -type PreconditionFailure_Violation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The type of PreconditionFailure. We recommend using a service-specific - // enum type to define the supported precondition violation subjects. For - // example, "TOS" for "Terms of Service violation". - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - // The subject, relative to the type, that failed. - // For example, "google.com/cloud" relative to the "TOS" type would indicate - // which terms of service is being referenced. - Subject string `protobuf:"bytes,2,opt,name=subject,proto3" json:"subject,omitempty"` - // A description of how the precondition failed. Developers can use this - // description to understand how to fix the failure. - // - // For example: "Terms of service not accepted". - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` -} - -func (x *PreconditionFailure_Violation) Reset() { - *x = PreconditionFailure_Violation{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PreconditionFailure_Violation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PreconditionFailure_Violation) ProtoMessage() {} - -func (x *PreconditionFailure_Violation) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PreconditionFailure_Violation.ProtoReflect.Descriptor instead. -func (*PreconditionFailure_Violation) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{4, 0} -} - -func (x *PreconditionFailure_Violation) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -func (x *PreconditionFailure_Violation) GetSubject() string { - if x != nil { - return x.Subject - } - return "" -} - -func (x *PreconditionFailure_Violation) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -// A message type used to describe a single bad request field. -type BadRequest_FieldViolation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // A path that leads to a field in the request body. The value will be a - // sequence of dot-separated identifiers that identify a protocol buffer - // field. - // - // Consider the following: - // - // message CreateContactRequest { - // message EmailAddress { - // enum Type { - // TYPE_UNSPECIFIED = 0; - // HOME = 1; - // WORK = 2; - // } - // - // optional string email = 1; - // repeated EmailType type = 2; - // } - // - // string full_name = 1; - // repeated EmailAddress email_addresses = 2; - // } - // - // In this example, in proto `field` could take one of the following values: - // - // - `full_name` for a violation in the `full_name` value - // - `email_addresses[1].email` for a violation in the `email` field of the - // first `email_addresses` message - // - `email_addresses[3].type[2]` for a violation in the second `type` - // value in the third `email_addresses` message. - // - // In JSON, the same values are represented as: - // - // - `fullName` for a violation in the `fullName` value - // - `emailAddresses[1].email` for a violation in the `email` field of the - // first `emailAddresses` message - // - `emailAddresses[3].type[2]` for a violation in the second `type` - // value in the third `emailAddresses` message. - 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() { - *x = BadRequest_FieldViolation{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BadRequest_FieldViolation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BadRequest_FieldViolation) ProtoMessage() {} - -func (x *BadRequest_FieldViolation) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BadRequest_FieldViolation.ProtoReflect.Descriptor instead. -func (*BadRequest_FieldViolation) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{5, 0} -} - -func (x *BadRequest_FieldViolation) GetField() string { - if x != nil { - return x.Field - } - return "" -} - -func (x *BadRequest_FieldViolation) GetDescription() string { - if x != nil { - return x.Description - } - 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 - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Describes what the link offers. - Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` - // The URL of the link. - Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` -} - -func (x *Help_Link) Reset() { - *x = Help_Link{} - if protoimpl.UnsafeEnabled { - mi := &file_google_rpc_error_details_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Help_Link) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Help_Link) ProtoMessage() {} - -func (x *Help_Link) ProtoReflect() protoreflect.Message { - mi := &file_google_rpc_error_details_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Help_Link.ProtoReflect.Descriptor instead. -func (*Help_Link) Descriptor() ([]byte, []int) { - return file_google_rpc_error_details_proto_rawDescGZIP(), []int{8, 0} -} - -func (x *Help_Link) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *Help_Link) GetUrl() string { - if x != nil { - return x.Url - } - return "" -} - -var File_google_rpc_error_details_proto protoreflect.FileDescriptor - -var file_google_rpc_error_details_proto_rawDesc = []byte{ - 0x0a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x1a, 0x1e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x01, 0x0a, - 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x49, - 0x6e, 0x66, 0x6f, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x47, 0x0a, 0x09, 0x52, 0x65, 0x74, 0x72, - 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3a, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, - 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x61, - 0x79, 0x22, 0x48, 0x0a, 0x09, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, - 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x45, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x22, 0x8e, 0x04, 0x0a, 0x0c, - 0x51, 0x75, 0x6f, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x42, 0x0a, 0x0a, - 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, - 0x6f, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x1a, 0xb9, 0x03, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 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, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, - 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x61, 0x70, 0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x71, - 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x19, - 0x0a, 0x08, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x49, 0x64, 0x12, 0x62, 0x0a, 0x10, 0x71, 0x75, 0x6f, - 0x74, 0x61, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, - 0x2e, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x56, 0x69, - 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x44, 0x69, 0x6d, - 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x71, 0x75, - 0x6f, 0x74, 0x61, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, - 0x0b, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0a, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, - 0x0a, 0x12, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x10, 0x66, 0x75, - 0x74, 0x75, 0x72, 0x65, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x88, 0x01, - 0x01, 0x1a, 0x42, 0x0a, 0x14, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, - 0x5f, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xbd, 0x01, 0x0a, - 0x13, 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, - 0x5b, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x12, 0x18, 0x0a, 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, 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, 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 ( - file_google_rpc_error_details_proto_rawDescOnce sync.Once - file_google_rpc_error_details_proto_rawDescData = file_google_rpc_error_details_proto_rawDesc -) - -func file_google_rpc_error_details_proto_rawDescGZIP() []byte { - file_google_rpc_error_details_proto_rawDescOnce.Do(func() { - file_google_rpc_error_details_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_rpc_error_details_proto_rawDescData) - }) - return file_google_rpc_error_details_proto_rawDescData -} - -var file_google_rpc_error_details_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_google_rpc_error_details_proto_goTypes = []interface{}{ - (*ErrorInfo)(nil), // 0: google.rpc.ErrorInfo - (*RetryInfo)(nil), // 1: google.rpc.RetryInfo - (*DebugInfo)(nil), // 2: google.rpc.DebugInfo - (*QuotaFailure)(nil), // 3: google.rpc.QuotaFailure - (*PreconditionFailure)(nil), // 4: google.rpc.PreconditionFailure - (*BadRequest)(nil), // 5: google.rpc.BadRequest - (*RequestInfo)(nil), // 6: google.rpc.RequestInfo - (*ResourceInfo)(nil), // 7: google.rpc.ResourceInfo - (*Help)(nil), // 8: google.rpc.Help - (*LocalizedMessage)(nil), // 9: google.rpc.LocalizedMessage - nil, // 10: google.rpc.ErrorInfo.MetadataEntry - (*QuotaFailure_Violation)(nil), // 11: google.rpc.QuotaFailure.Violation - nil, // 12: google.rpc.QuotaFailure.Violation.QuotaDimensionsEntry - (*PreconditionFailure_Violation)(nil), // 13: google.rpc.PreconditionFailure.Violation - (*BadRequest_FieldViolation)(nil), // 14: google.rpc.BadRequest.FieldViolation - (*Help_Link)(nil), // 15: google.rpc.Help.Link - (*durationpb.Duration)(nil), // 16: google.protobuf.Duration -} -var file_google_rpc_error_details_proto_depIdxs = []int32{ - 10, // 0: google.rpc.ErrorInfo.metadata:type_name -> google.rpc.ErrorInfo.MetadataEntry - 16, // 1: google.rpc.RetryInfo.retry_delay:type_name -> google.protobuf.Duration - 11, // 2: google.rpc.QuotaFailure.violations:type_name -> google.rpc.QuotaFailure.Violation - 13, // 3: google.rpc.PreconditionFailure.violations:type_name -> google.rpc.PreconditionFailure.Violation - 14, // 4: google.rpc.BadRequest.field_violations:type_name -> google.rpc.BadRequest.FieldViolation - 15, // 5: google.rpc.Help.links:type_name -> google.rpc.Help.Link - 12, // 6: google.rpc.QuotaFailure.Violation.quota_dimensions:type_name -> google.rpc.QuotaFailure.Violation.QuotaDimensionsEntry - 9, // 7: google.rpc.BadRequest.FieldViolation.localized_message:type_name -> google.rpc.LocalizedMessage - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name -} - -func init() { file_google_rpc_error_details_proto_init() } -func file_google_rpc_error_details_proto_init() { - if File_google_rpc_error_details_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_google_rpc_error_details_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ErrorInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RetryInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DebugInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QuotaFailure); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PreconditionFailure); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BadRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResourceInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Help); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LocalizedMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QuotaFailure_Violation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PreconditionFailure_Violation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BadRequest_FieldViolation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_rpc_error_details_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Help_Link); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_google_rpc_error_details_proto_msgTypes[11].OneofWrappers = []interface{}{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_google_rpc_error_details_proto_rawDesc, - NumEnums: 0, - NumMessages: 16, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_google_rpc_error_details_proto_goTypes, - DependencyIndexes: file_google_rpc_error_details_proto_depIdxs, - MessageInfos: file_google_rpc_error_details_proto_msgTypes, - }.Build() - File_google_rpc_error_details_proto = out.File - file_google_rpc_error_details_proto_rawDesc = nil - file_google_rpc_error_details_proto_goTypes = nil - file_google_rpc_error_details_proto_depIdxs = nil -} diff --git a/vendor/google.golang.org/grpc/encoding/gzip/gzip.go b/vendor/google.golang.org/grpc/encoding/gzip/gzip.go deleted file mode 100644 index 6306e8bb..00000000 --- a/vendor/google.golang.org/grpc/encoding/gzip/gzip.go +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * Copyright 2017 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// Package gzip implements and registers the gzip compressor -// during the initialization. -// -// # Experimental -// -// Notice: This package is EXPERIMENTAL and may be changed or removed in a -// later release. -package gzip - -import ( - "compress/gzip" - "encoding/binary" - "fmt" - "io" - "sync" - - "google.golang.org/grpc/encoding" -) - -// Name is the name registered for the gzip compressor. -const Name = "gzip" - -func init() { - c := &compressor{} - c.poolCompressor.New = func() any { - return &writer{Writer: gzip.NewWriter(io.Discard), pool: &c.poolCompressor} - } - encoding.RegisterCompressor(c) -} - -type writer struct { - *gzip.Writer - pool *sync.Pool -} - -// SetLevel updates the registered gzip compressor to use the compression level specified (gzip.HuffmanOnly is not supported). -// NOTE: this function must only be called during initialization time (i.e. in an init() function), -// and is not thread-safe. -// -// The error returned will be nil if the specified level is valid. -func SetLevel(level int) error { - if level < gzip.DefaultCompression || level > gzip.BestCompression { - return fmt.Errorf("grpc: invalid gzip compression level: %d", level) - } - c := encoding.GetCompressor(Name).(*compressor) - c.poolCompressor.New = func() any { - w, err := gzip.NewWriterLevel(io.Discard, level) - if err != nil { - panic(err) - } - return &writer{Writer: w, pool: &c.poolCompressor} - } - return nil -} - -func (c *compressor) Compress(w io.Writer) (io.WriteCloser, error) { - z := c.poolCompressor.Get().(*writer) - z.Writer.Reset(w) - return z, nil -} - -func (z *writer) Close() error { - defer z.pool.Put(z) - return z.Writer.Close() -} - -type reader struct { - *gzip.Reader - pool *sync.Pool -} - -func (c *compressor) Decompress(r io.Reader) (io.Reader, error) { - z, inPool := c.poolDecompressor.Get().(*reader) - if !inPool { - newZ, err := gzip.NewReader(r) - if err != nil { - return nil, err - } - return &reader{Reader: newZ, pool: &c.poolDecompressor}, nil - } - if err := z.Reset(r); err != nil { - c.poolDecompressor.Put(z) - return nil, err - } - return z, nil -} - -func (z *reader) Read(p []byte) (n int, err error) { - n, err = z.Reader.Read(p) - if err == io.EOF { - z.pool.Put(z) - } - return n, err -} - -// RFC1952 specifies that the last four bytes "contains the size of -// the original (uncompressed) input data modulo 2^32." -// gRPC has a max message size of 2GB so we don't need to worry about wraparound. -func (c *compressor) DecompressedSize(buf []byte) int { - last := len(buf) - if last < 4 { - return -1 - } - return int(binary.LittleEndian.Uint32(buf[last-4 : last])) -} - -func (c *compressor) Name() string { - return Name -} - -type compressor struct { - poolCompressor sync.Pool - poolDecompressor sync.Pool -} diff --git a/vendor/google.golang.org/grpc/reflection/README.md b/vendor/google.golang.org/grpc/reflection/README.md deleted file mode 100644 index 9ace83cc..00000000 --- a/vendor/google.golang.org/grpc/reflection/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Reflection - -Package reflection implements server reflection service. - -The service implemented is defined in: https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto. - -To register server reflection on a gRPC server: -```go -import "google.golang.org/grpc/reflection" - -s := grpc.NewServer() -pb.RegisterYourOwnServer(s, &server{}) - -// Register reflection service on gRPC server. -reflection.Register(s) - -s.Serve(lis) -``` diff --git a/vendor/google.golang.org/grpc/reflection/adapt.go b/vendor/google.golang.org/grpc/reflection/adapt.go deleted file mode 100644 index 6997e474..00000000 --- a/vendor/google.golang.org/grpc/reflection/adapt.go +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Copyright 2023 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package reflection - -import ( - "google.golang.org/grpc/reflection/internal" - - v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" - v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1" - v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" -) - -// asV1Alpha returns an implementation of the v1alpha version of the reflection -// interface that delegates all calls to the given v1 version. -func asV1Alpha(svr v1reflectiongrpc.ServerReflectionServer) v1alphareflectiongrpc.ServerReflectionServer { - return v1AlphaServerImpl{svr: svr} -} - -type v1AlphaServerImpl struct { - svr v1reflectiongrpc.ServerReflectionServer -} - -func (s v1AlphaServerImpl) ServerReflectionInfo(stream v1alphareflectiongrpc.ServerReflection_ServerReflectionInfoServer) error { - return s.svr.ServerReflectionInfo(v1AlphaServerStreamAdapter{stream}) -} - -type v1AlphaServerStreamAdapter struct { - v1alphareflectiongrpc.ServerReflection_ServerReflectionInfoServer -} - -func (s v1AlphaServerStreamAdapter) Send(response *v1reflectionpb.ServerReflectionResponse) error { - return s.ServerReflection_ServerReflectionInfoServer.Send(internal.V1ToV1AlphaResponse(response)) -} - -func (s v1AlphaServerStreamAdapter) Recv() (*v1reflectionpb.ServerReflectionRequest, error) { - resp, err := s.ServerReflection_ServerReflectionInfoServer.Recv() - if err != nil { - return nil, err - } - return internal.V1AlphaToV1Request(resp), nil -} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go deleted file mode 100644 index 92f52922..00000000 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go +++ /dev/null @@ -1,777 +0,0 @@ -// Copyright 2016 The gRPC Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Service exported by server reflection. A more complete description of how -// server reflection works can be found at -// https://github.com/grpc/grpc/blob/master/doc/server-reflection.md -// -// The canonical version of this proto can be found at -// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.6 -// protoc v5.27.1 -// source: grpc/reflection/v1/reflection.proto - -package grpc_reflection_v1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// The message sent by the client when calling ServerReflectionInfo method. -type ServerReflectionRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - // To use reflection service, the client should set one of the following - // fields in message_request. The server distinguishes requests by their - // defined field and then handles them using corresponding methods. - // - // Types that are valid to be assigned to MessageRequest: - // - // *ServerReflectionRequest_FileByFilename - // *ServerReflectionRequest_FileContainingSymbol - // *ServerReflectionRequest_FileContainingExtension - // *ServerReflectionRequest_AllExtensionNumbersOfType - // *ServerReflectionRequest_ListServices - MessageRequest isServerReflectionRequest_MessageRequest `protobuf_oneof:"message_request"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ServerReflectionRequest) Reset() { - *x = ServerReflectionRequest{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ServerReflectionRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServerReflectionRequest) ProtoMessage() {} - -func (x *ServerReflectionRequest) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServerReflectionRequest.ProtoReflect.Descriptor instead. -func (*ServerReflectionRequest) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{0} -} - -func (x *ServerReflectionRequest) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *ServerReflectionRequest) GetMessageRequest() isServerReflectionRequest_MessageRequest { - if x != nil { - return x.MessageRequest - } - return nil -} - -func (x *ServerReflectionRequest) GetFileByFilename() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileByFilename); ok { - return x.FileByFilename - } - } - return "" -} - -func (x *ServerReflectionRequest) GetFileContainingSymbol() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingSymbol); ok { - return x.FileContainingSymbol - } - } - return "" -} - -func (x *ServerReflectionRequest) GetFileContainingExtension() *ExtensionRequest { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingExtension); ok { - return x.FileContainingExtension - } - } - return nil -} - -func (x *ServerReflectionRequest) GetAllExtensionNumbersOfType() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_AllExtensionNumbersOfType); ok { - return x.AllExtensionNumbersOfType - } - } - return "" -} - -func (x *ServerReflectionRequest) GetListServices() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_ListServices); ok { - return x.ListServices - } - } - return "" -} - -type isServerReflectionRequest_MessageRequest interface { - isServerReflectionRequest_MessageRequest() -} - -type ServerReflectionRequest_FileByFilename struct { - // Find a proto file by the file name. - FileByFilename string `protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,proto3,oneof"` -} - -type ServerReflectionRequest_FileContainingSymbol struct { - // Find the proto file that declares the given fully-qualified symbol name. - // This field should be a fully-qualified symbol name - // (e.g. <package>.<service>[.<method>] or <package>.<type>). - FileContainingSymbol string `protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,proto3,oneof"` -} - -type ServerReflectionRequest_FileContainingExtension struct { - // Find the proto file which defines an extension extending the given - // message type with the given field number. - FileContainingExtension *ExtensionRequest `protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,proto3,oneof"` -} - -type ServerReflectionRequest_AllExtensionNumbersOfType struct { - // Finds the tag numbers used by all known extensions of the given message - // type, and appends them to ExtensionNumberResponse in an undefined order. - // Its corresponding method is best-effort: it's not guaranteed that the - // reflection service will implement this method, and it's not guaranteed - // that this method will provide all extensions. Returns - // StatusCode::UNIMPLEMENTED if it's not implemented. - // This field should be a fully-qualified type name. The format is - // <package>.<type> - AllExtensionNumbersOfType string `protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,proto3,oneof"` -} - -type ServerReflectionRequest_ListServices struct { - // List the full names of registered services. The content will not be - // checked. - ListServices string `protobuf:"bytes,7,opt,name=list_services,json=listServices,proto3,oneof"` -} - -func (*ServerReflectionRequest_FileByFilename) isServerReflectionRequest_MessageRequest() {} - -func (*ServerReflectionRequest_FileContainingSymbol) isServerReflectionRequest_MessageRequest() {} - -func (*ServerReflectionRequest_FileContainingExtension) isServerReflectionRequest_MessageRequest() {} - -func (*ServerReflectionRequest_AllExtensionNumbersOfType) isServerReflectionRequest_MessageRequest() { -} - -func (*ServerReflectionRequest_ListServices) isServerReflectionRequest_MessageRequest() {} - -// The type name and extension number sent by the client when requesting -// file_containing_extension. -type ExtensionRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Fully-qualified type name. The format should be <package>.<type> - ContainingType string `protobuf:"bytes,1,opt,name=containing_type,json=containingType,proto3" json:"containing_type,omitempty"` - ExtensionNumber int32 `protobuf:"varint,2,opt,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ExtensionRequest) Reset() { - *x = ExtensionRequest{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ExtensionRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExtensionRequest) ProtoMessage() {} - -func (x *ExtensionRequest) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExtensionRequest.ProtoReflect.Descriptor instead. -func (*ExtensionRequest) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{1} -} - -func (x *ExtensionRequest) GetContainingType() string { - if x != nil { - return x.ContainingType - } - return "" -} - -func (x *ExtensionRequest) GetExtensionNumber() int32 { - if x != nil { - return x.ExtensionNumber - } - return 0 -} - -// The message sent by the server to answer ServerReflectionInfo method. -type ServerReflectionResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - ValidHost string `protobuf:"bytes,1,opt,name=valid_host,json=validHost,proto3" json:"valid_host,omitempty"` - OriginalRequest *ServerReflectionRequest `protobuf:"bytes,2,opt,name=original_request,json=originalRequest,proto3" json:"original_request,omitempty"` - // The server sets one of the following fields according to the message_request - // in the request. - // - // Types that are valid to be assigned to MessageResponse: - // - // *ServerReflectionResponse_FileDescriptorResponse - // *ServerReflectionResponse_AllExtensionNumbersResponse - // *ServerReflectionResponse_ListServicesResponse - // *ServerReflectionResponse_ErrorResponse - MessageResponse isServerReflectionResponse_MessageResponse `protobuf_oneof:"message_response"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ServerReflectionResponse) Reset() { - *x = ServerReflectionResponse{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ServerReflectionResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServerReflectionResponse) ProtoMessage() {} - -func (x *ServerReflectionResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServerReflectionResponse.ProtoReflect.Descriptor instead. -func (*ServerReflectionResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{2} -} - -func (x *ServerReflectionResponse) GetValidHost() string { - if x != nil { - return x.ValidHost - } - return "" -} - -func (x *ServerReflectionResponse) GetOriginalRequest() *ServerReflectionRequest { - if x != nil { - return x.OriginalRequest - } - return nil -} - -func (x *ServerReflectionResponse) GetMessageResponse() isServerReflectionResponse_MessageResponse { - if x != nil { - return x.MessageResponse - } - return nil -} - -func (x *ServerReflectionResponse) GetFileDescriptorResponse() *FileDescriptorResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_FileDescriptorResponse); ok { - return x.FileDescriptorResponse - } - } - return nil -} - -func (x *ServerReflectionResponse) GetAllExtensionNumbersResponse() *ExtensionNumberResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_AllExtensionNumbersResponse); ok { - return x.AllExtensionNumbersResponse - } - } - return nil -} - -func (x *ServerReflectionResponse) GetListServicesResponse() *ListServiceResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_ListServicesResponse); ok { - return x.ListServicesResponse - } - } - return nil -} - -func (x *ServerReflectionResponse) GetErrorResponse() *ErrorResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_ErrorResponse); ok { - return x.ErrorResponse - } - } - return nil -} - -type isServerReflectionResponse_MessageResponse interface { - isServerReflectionResponse_MessageResponse() -} - -type ServerReflectionResponse_FileDescriptorResponse struct { - // This message is used to answer file_by_filename, file_containing_symbol, - // file_containing_extension requests with transitive dependencies. - // As the repeated label is not allowed in oneof fields, we use a - // FileDescriptorResponse message to encapsulate the repeated fields. - // The reflection service is allowed to avoid sending FileDescriptorProtos - // that were previously sent in response to earlier requests in the stream. - FileDescriptorResponse *FileDescriptorResponse `protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,proto3,oneof"` -} - -type ServerReflectionResponse_AllExtensionNumbersResponse struct { - // This message is used to answer all_extension_numbers_of_type requests. - AllExtensionNumbersResponse *ExtensionNumberResponse `protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,proto3,oneof"` -} - -type ServerReflectionResponse_ListServicesResponse struct { - // This message is used to answer list_services requests. - ListServicesResponse *ListServiceResponse `protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,proto3,oneof"` -} - -type ServerReflectionResponse_ErrorResponse struct { - // This message is used when an error occurs. - ErrorResponse *ErrorResponse `protobuf:"bytes,7,opt,name=error_response,json=errorResponse,proto3,oneof"` -} - -func (*ServerReflectionResponse_FileDescriptorResponse) isServerReflectionResponse_MessageResponse() { -} - -func (*ServerReflectionResponse_AllExtensionNumbersResponse) isServerReflectionResponse_MessageResponse() { -} - -func (*ServerReflectionResponse_ListServicesResponse) isServerReflectionResponse_MessageResponse() {} - -func (*ServerReflectionResponse_ErrorResponse) isServerReflectionResponse_MessageResponse() {} - -// Serialized FileDescriptorProto messages sent by the server answering -// a file_by_filename, file_containing_symbol, or file_containing_extension -// request. -type FileDescriptorResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Serialized FileDescriptorProto messages. We avoid taking a dependency on - // descriptor.proto, which uses proto2 only features, by making them opaque - // bytes instead. - FileDescriptorProto [][]byte `protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3" json:"file_descriptor_proto,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *FileDescriptorResponse) Reset() { - *x = FileDescriptorResponse{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *FileDescriptorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FileDescriptorResponse) ProtoMessage() {} - -func (x *FileDescriptorResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FileDescriptorResponse.ProtoReflect.Descriptor instead. -func (*FileDescriptorResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{3} -} - -func (x *FileDescriptorResponse) GetFileDescriptorProto() [][]byte { - if x != nil { - return x.FileDescriptorProto - } - return nil -} - -// A list of extension numbers sent by the server answering -// all_extension_numbers_of_type request. -type ExtensionNumberResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Full name of the base type, including the package name. The format - // is <package>.<type> - BaseTypeName string `protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName,proto3" json:"base_type_name,omitempty"` - ExtensionNumber []int32 `protobuf:"varint,2,rep,packed,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ExtensionNumberResponse) Reset() { - *x = ExtensionNumberResponse{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ExtensionNumberResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExtensionNumberResponse) ProtoMessage() {} - -func (x *ExtensionNumberResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExtensionNumberResponse.ProtoReflect.Descriptor instead. -func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{4} -} - -func (x *ExtensionNumberResponse) GetBaseTypeName() string { - if x != nil { - return x.BaseTypeName - } - return "" -} - -func (x *ExtensionNumberResponse) GetExtensionNumber() []int32 { - if x != nil { - return x.ExtensionNumber - } - return nil -} - -// A list of ServiceResponse sent by the server answering list_services request. -type ListServiceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The information of each service may be expanded in the future, so we use - // ServiceResponse message to encapsulate it. - Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service,proto3" json:"service,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListServiceResponse) Reset() { - *x = ListServiceResponse{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListServiceResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListServiceResponse) ProtoMessage() {} - -func (x *ListServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListServiceResponse.ProtoReflect.Descriptor instead. -func (*ListServiceResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{5} -} - -func (x *ListServiceResponse) GetService() []*ServiceResponse { - if x != nil { - return x.Service - } - return nil -} - -// The information of a single service used by ListServiceResponse to answer -// list_services request. -type ServiceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Full name of a registered service, including its package name. The format - // is <package>.<service> - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ServiceResponse) Reset() { - *x = ServiceResponse{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ServiceResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServiceResponse) ProtoMessage() {} - -func (x *ServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServiceResponse.ProtoReflect.Descriptor instead. -func (*ServiceResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{6} -} - -func (x *ServiceResponse) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// The error code and error message sent by the server when an error occurs. -type ErrorResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // This field uses the error codes defined in grpc::StatusCode. - ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` - ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ErrorResponse) Reset() { - *x = ErrorResponse{} - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ErrorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ErrorResponse) ProtoMessage() {} - -func (x *ErrorResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. -func (*ErrorResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{7} -} - -func (x *ErrorResponse) GetErrorCode() int32 { - if x != nil { - return x.ErrorCode - } - return 0 -} - -func (x *ErrorResponse) GetErrorMessage() string { - if x != nil { - return x.ErrorMessage - } - return "" -} - -var File_grpc_reflection_v1_reflection_proto protoreflect.FileDescriptor - -const file_grpc_reflection_v1_reflection_proto_rawDesc = "" + - "\n" + - "#grpc/reflection/v1/reflection.proto\x12\x12grpc.reflection.v1\"\xf3\x02\n" + - "\x17ServerReflectionRequest\x12\x12\n" + - "\x04host\x18\x01 \x01(\tR\x04host\x12*\n" + - "\x10file_by_filename\x18\x03 \x01(\tH\x00R\x0efileByFilename\x126\n" + - "\x16file_containing_symbol\x18\x04 \x01(\tH\x00R\x14fileContainingSymbol\x12b\n" + - "\x19file_containing_extension\x18\x05 \x01(\v2$.grpc.reflection.v1.ExtensionRequestH\x00R\x17fileContainingExtension\x12B\n" + - "\x1dall_extension_numbers_of_type\x18\x06 \x01(\tH\x00R\x19allExtensionNumbersOfType\x12%\n" + - "\rlist_services\x18\a \x01(\tH\x00R\flistServicesB\x11\n" + - "\x0fmessage_request\"f\n" + - "\x10ExtensionRequest\x12'\n" + - "\x0fcontaining_type\x18\x01 \x01(\tR\x0econtainingType\x12)\n" + - "\x10extension_number\x18\x02 \x01(\x05R\x0fextensionNumber\"\xae\x04\n" + - "\x18ServerReflectionResponse\x12\x1d\n" + - "\n" + - "valid_host\x18\x01 \x01(\tR\tvalidHost\x12V\n" + - "\x10original_request\x18\x02 \x01(\v2+.grpc.reflection.v1.ServerReflectionRequestR\x0foriginalRequest\x12f\n" + - "\x18file_descriptor_response\x18\x04 \x01(\v2*.grpc.reflection.v1.FileDescriptorResponseH\x00R\x16fileDescriptorResponse\x12r\n" + - "\x1eall_extension_numbers_response\x18\x05 \x01(\v2+.grpc.reflection.v1.ExtensionNumberResponseH\x00R\x1ballExtensionNumbersResponse\x12_\n" + - "\x16list_services_response\x18\x06 \x01(\v2'.grpc.reflection.v1.ListServiceResponseH\x00R\x14listServicesResponse\x12J\n" + - "\x0eerror_response\x18\a \x01(\v2!.grpc.reflection.v1.ErrorResponseH\x00R\rerrorResponseB\x12\n" + - "\x10message_response\"L\n" + - "\x16FileDescriptorResponse\x122\n" + - "\x15file_descriptor_proto\x18\x01 \x03(\fR\x13fileDescriptorProto\"j\n" + - "\x17ExtensionNumberResponse\x12$\n" + - "\x0ebase_type_name\x18\x01 \x01(\tR\fbaseTypeName\x12)\n" + - "\x10extension_number\x18\x02 \x03(\x05R\x0fextensionNumber\"T\n" + - "\x13ListServiceResponse\x12=\n" + - "\aservice\x18\x01 \x03(\v2#.grpc.reflection.v1.ServiceResponseR\aservice\"%\n" + - "\x0fServiceResponse\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name\"S\n" + - "\rErrorResponse\x12\x1d\n" + - "\n" + - "error_code\x18\x01 \x01(\x05R\terrorCode\x12#\n" + - "\rerror_message\x18\x02 \x01(\tR\ferrorMessage2\x89\x01\n" + - "\x10ServerReflection\x12u\n" + - "\x14ServerReflectionInfo\x12+.grpc.reflection.v1.ServerReflectionRequest\x1a,.grpc.reflection.v1.ServerReflectionResponse(\x010\x01Bf\n" + - "\x15io.grpc.reflection.v1B\x15ServerReflectionProtoP\x01Z4google.golang.org/grpc/reflection/grpc_reflection_v1b\x06proto3" - -var ( - file_grpc_reflection_v1_reflection_proto_rawDescOnce sync.Once - file_grpc_reflection_v1_reflection_proto_rawDescData []byte -) - -func file_grpc_reflection_v1_reflection_proto_rawDescGZIP() []byte { - file_grpc_reflection_v1_reflection_proto_rawDescOnce.Do(func() { - file_grpc_reflection_v1_reflection_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1_reflection_proto_rawDesc), len(file_grpc_reflection_v1_reflection_proto_rawDesc))) - }) - return file_grpc_reflection_v1_reflection_proto_rawDescData -} - -var file_grpc_reflection_v1_reflection_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_grpc_reflection_v1_reflection_proto_goTypes = []any{ - (*ServerReflectionRequest)(nil), // 0: grpc.reflection.v1.ServerReflectionRequest - (*ExtensionRequest)(nil), // 1: grpc.reflection.v1.ExtensionRequest - (*ServerReflectionResponse)(nil), // 2: grpc.reflection.v1.ServerReflectionResponse - (*FileDescriptorResponse)(nil), // 3: grpc.reflection.v1.FileDescriptorResponse - (*ExtensionNumberResponse)(nil), // 4: grpc.reflection.v1.ExtensionNumberResponse - (*ListServiceResponse)(nil), // 5: grpc.reflection.v1.ListServiceResponse - (*ServiceResponse)(nil), // 6: grpc.reflection.v1.ServiceResponse - (*ErrorResponse)(nil), // 7: grpc.reflection.v1.ErrorResponse -} -var file_grpc_reflection_v1_reflection_proto_depIdxs = []int32{ - 1, // 0: grpc.reflection.v1.ServerReflectionRequest.file_containing_extension:type_name -> grpc.reflection.v1.ExtensionRequest - 0, // 1: grpc.reflection.v1.ServerReflectionResponse.original_request:type_name -> grpc.reflection.v1.ServerReflectionRequest - 3, // 2: grpc.reflection.v1.ServerReflectionResponse.file_descriptor_response:type_name -> grpc.reflection.v1.FileDescriptorResponse - 4, // 3: grpc.reflection.v1.ServerReflectionResponse.all_extension_numbers_response:type_name -> grpc.reflection.v1.ExtensionNumberResponse - 5, // 4: grpc.reflection.v1.ServerReflectionResponse.list_services_response:type_name -> grpc.reflection.v1.ListServiceResponse - 7, // 5: grpc.reflection.v1.ServerReflectionResponse.error_response:type_name -> grpc.reflection.v1.ErrorResponse - 6, // 6: grpc.reflection.v1.ListServiceResponse.service:type_name -> grpc.reflection.v1.ServiceResponse - 0, // 7: grpc.reflection.v1.ServerReflection.ServerReflectionInfo:input_type -> grpc.reflection.v1.ServerReflectionRequest - 2, // 8: grpc.reflection.v1.ServerReflection.ServerReflectionInfo:output_type -> grpc.reflection.v1.ServerReflectionResponse - 8, // [8:9] is the sub-list for method output_type - 7, // [7:8] 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_grpc_reflection_v1_reflection_proto_init() } -func file_grpc_reflection_v1_reflection_proto_init() { - if File_grpc_reflection_v1_reflection_proto != nil { - return - } - file_grpc_reflection_v1_reflection_proto_msgTypes[0].OneofWrappers = []any{ - (*ServerReflectionRequest_FileByFilename)(nil), - (*ServerReflectionRequest_FileContainingSymbol)(nil), - (*ServerReflectionRequest_FileContainingExtension)(nil), - (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil), - (*ServerReflectionRequest_ListServices)(nil), - } - file_grpc_reflection_v1_reflection_proto_msgTypes[2].OneofWrappers = []any{ - (*ServerReflectionResponse_FileDescriptorResponse)(nil), - (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil), - (*ServerReflectionResponse_ListServicesResponse)(nil), - (*ServerReflectionResponse_ErrorResponse)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1_reflection_proto_rawDesc), len(file_grpc_reflection_v1_reflection_proto_rawDesc)), - NumEnums: 0, - NumMessages: 8, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_grpc_reflection_v1_reflection_proto_goTypes, - DependencyIndexes: file_grpc_reflection_v1_reflection_proto_depIdxs, - MessageInfos: file_grpc_reflection_v1_reflection_proto_msgTypes, - }.Build() - File_grpc_reflection_v1_reflection_proto = out.File - file_grpc_reflection_v1_reflection_proto_goTypes = nil - file_grpc_reflection_v1_reflection_proto_depIdxs = nil -} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go deleted file mode 100644 index f4a361c6..00000000 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2016 The gRPC Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Service exported by server reflection. A more complete description of how -// server reflection works can be found at -// https://github.com/grpc/grpc/blob/master/doc/server-reflection.md -// -// The canonical version of this proto can be found at -// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto - -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v5.27.1 -// source: grpc/reflection/v1/reflection.proto - -package grpc_reflection_v1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - ServerReflection_ServerReflectionInfo_FullMethodName = "/grpc.reflection.v1.ServerReflection/ServerReflectionInfo" -) - -// ServerReflectionClient is the client API for ServerReflection service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type ServerReflectionClient interface { - // The reflection service is structured as a bidirectional stream, ensuring - // all related requests go to a single server. - ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) -} - -type serverReflectionClient struct { - cc grpc.ClientConnInterface -} - -func NewServerReflectionClient(cc grpc.ClientConnInterface) ServerReflectionClient { - return &serverReflectionClient{cc} -} - -func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &ServerReflection_ServiceDesc.Streams[0], ServerReflection_ServerReflectionInfo_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[ServerReflectionRequest, ServerReflectionResponse]{ClientStream: stream} - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type ServerReflection_ServerReflectionInfoClient = grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse] - -// ServerReflectionServer is the server API for ServerReflection service. -// All implementations should embed UnimplementedServerReflectionServer -// for forward compatibility. -type ServerReflectionServer interface { - // The reflection service is structured as a bidirectional stream, ensuring - // all related requests go to a single server. - ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error -} - -// UnimplementedServerReflectionServer should be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedServerReflectionServer struct{} - -func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error { - return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented") -} -func (UnimplementedServerReflectionServer) testEmbeddedByValue() {} - -// UnsafeServerReflectionServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to ServerReflectionServer will -// result in compilation errors. -type UnsafeServerReflectionServer interface { - mustEmbedUnimplementedServerReflectionServer() -} - -func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) { - // If the following call panics, it indicates UnimplementedServerReflectionServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&ServerReflection_ServiceDesc, srv) -} - -func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(ServerReflectionServer).ServerReflectionInfo(&grpc.GenericServerStream[ServerReflectionRequest, ServerReflectionResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type ServerReflection_ServerReflectionInfoServer = grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse] - -// ServerReflection_ServiceDesc is the grpc.ServiceDesc for ServerReflection service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var ServerReflection_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "grpc.reflection.v1.ServerReflection", - HandlerType: (*ServerReflectionServer)(nil), - Methods: []grpc.MethodDesc{}, - Streams: []grpc.StreamDesc{ - { - StreamName: "ServerReflectionInfo", - Handler: _ServerReflection_ServerReflectionInfo_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, - Metadata: "grpc/reflection/v1/reflection.proto", -} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go deleted file mode 100644 index 5253e862..00000000 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go +++ /dev/null @@ -1,847 +0,0 @@ -// Copyright 2016 The gRPC Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// Service exported by server reflection - -// Warning: this entire file is deprecated. Use this instead: -// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.6 -// protoc v5.27.1 -// grpc/reflection/v1alpha/reflection.proto is a deprecated file. - -package grpc_reflection_v1alpha - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// The message sent by the client when calling ServerReflectionInfo method. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type ServerReflectionRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` - // To use reflection service, the client should set one of the following - // fields in message_request. The server distinguishes requests by their - // defined field and then handles them using corresponding methods. - // - // Types that are valid to be assigned to MessageRequest: - // - // *ServerReflectionRequest_FileByFilename - // *ServerReflectionRequest_FileContainingSymbol - // *ServerReflectionRequest_FileContainingExtension - // *ServerReflectionRequest_AllExtensionNumbersOfType - // *ServerReflectionRequest_ListServices - MessageRequest isServerReflectionRequest_MessageRequest `protobuf_oneof:"message_request"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ServerReflectionRequest) Reset() { - *x = ServerReflectionRequest{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ServerReflectionRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServerReflectionRequest) ProtoMessage() {} - -func (x *ServerReflectionRequest) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServerReflectionRequest.ProtoReflect.Descriptor instead. -func (*ServerReflectionRequest) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{0} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionRequest) GetHost() string { - if x != nil { - return x.Host - } - return "" -} - -func (x *ServerReflectionRequest) GetMessageRequest() isServerReflectionRequest_MessageRequest { - if x != nil { - return x.MessageRequest - } - return nil -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionRequest) GetFileByFilename() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileByFilename); ok { - return x.FileByFilename - } - } - return "" -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionRequest) GetFileContainingSymbol() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingSymbol); ok { - return x.FileContainingSymbol - } - } - return "" -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionRequest) GetFileContainingExtension() *ExtensionRequest { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingExtension); ok { - return x.FileContainingExtension - } - } - return nil -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionRequest) GetAllExtensionNumbersOfType() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_AllExtensionNumbersOfType); ok { - return x.AllExtensionNumbersOfType - } - } - return "" -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionRequest) GetListServices() string { - if x != nil { - if x, ok := x.MessageRequest.(*ServerReflectionRequest_ListServices); ok { - return x.ListServices - } - } - return "" -} - -type isServerReflectionRequest_MessageRequest interface { - isServerReflectionRequest_MessageRequest() -} - -type ServerReflectionRequest_FileByFilename struct { - // Find a proto file by the file name. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - FileByFilename string `protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,proto3,oneof"` -} - -type ServerReflectionRequest_FileContainingSymbol struct { - // Find the proto file that declares the given fully-qualified symbol name. - // This field should be a fully-qualified symbol name - // (e.g. <package>.<service>[.<method>] or <package>.<type>). - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - FileContainingSymbol string `protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,proto3,oneof"` -} - -type ServerReflectionRequest_FileContainingExtension struct { - // Find the proto file which defines an extension extending the given - // message type with the given field number. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - FileContainingExtension *ExtensionRequest `protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,proto3,oneof"` -} - -type ServerReflectionRequest_AllExtensionNumbersOfType struct { - // Finds the tag numbers used by all known extensions of extendee_type, and - // appends them to ExtensionNumberResponse in an undefined order. - // Its corresponding method is best-effort: it's not guaranteed that the - // reflection service will implement this method, and it's not guaranteed - // that this method will provide all extensions. Returns - // StatusCode::UNIMPLEMENTED if it's not implemented. - // This field should be a fully-qualified type name. The format is - // <package>.<type> - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - AllExtensionNumbersOfType string `protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,proto3,oneof"` -} - -type ServerReflectionRequest_ListServices struct { - // List the full names of registered services. The content will not be - // checked. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ListServices string `protobuf:"bytes,7,opt,name=list_services,json=listServices,proto3,oneof"` -} - -func (*ServerReflectionRequest_FileByFilename) isServerReflectionRequest_MessageRequest() {} - -func (*ServerReflectionRequest_FileContainingSymbol) isServerReflectionRequest_MessageRequest() {} - -func (*ServerReflectionRequest_FileContainingExtension) isServerReflectionRequest_MessageRequest() {} - -func (*ServerReflectionRequest_AllExtensionNumbersOfType) isServerReflectionRequest_MessageRequest() { -} - -func (*ServerReflectionRequest_ListServices) isServerReflectionRequest_MessageRequest() {} - -// The type name and extension number sent by the client when requesting -// file_containing_extension. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type ExtensionRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Fully-qualified type name. The format should be <package>.<type> - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ContainingType string `protobuf:"bytes,1,opt,name=containing_type,json=containingType,proto3" json:"containing_type,omitempty"` - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ExtensionNumber int32 `protobuf:"varint,2,opt,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ExtensionRequest) Reset() { - *x = ExtensionRequest{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ExtensionRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExtensionRequest) ProtoMessage() {} - -func (x *ExtensionRequest) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExtensionRequest.ProtoReflect.Descriptor instead. -func (*ExtensionRequest) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{1} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ExtensionRequest) GetContainingType() string { - if x != nil { - return x.ContainingType - } - return "" -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ExtensionRequest) GetExtensionNumber() int32 { - if x != nil { - return x.ExtensionNumber - } - return 0 -} - -// The message sent by the server to answer ServerReflectionInfo method. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type ServerReflectionResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ValidHost string `protobuf:"bytes,1,opt,name=valid_host,json=validHost,proto3" json:"valid_host,omitempty"` - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - OriginalRequest *ServerReflectionRequest `protobuf:"bytes,2,opt,name=original_request,json=originalRequest,proto3" json:"original_request,omitempty"` - // The server set one of the following fields according to the message_request - // in the request. - // - // Types that are valid to be assigned to MessageResponse: - // - // *ServerReflectionResponse_FileDescriptorResponse - // *ServerReflectionResponse_AllExtensionNumbersResponse - // *ServerReflectionResponse_ListServicesResponse - // *ServerReflectionResponse_ErrorResponse - MessageResponse isServerReflectionResponse_MessageResponse `protobuf_oneof:"message_response"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ServerReflectionResponse) Reset() { - *x = ServerReflectionResponse{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ServerReflectionResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServerReflectionResponse) ProtoMessage() {} - -func (x *ServerReflectionResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServerReflectionResponse.ProtoReflect.Descriptor instead. -func (*ServerReflectionResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{2} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionResponse) GetValidHost() string { - if x != nil { - return x.ValidHost - } - return "" -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionResponse) GetOriginalRequest() *ServerReflectionRequest { - if x != nil { - return x.OriginalRequest - } - return nil -} - -func (x *ServerReflectionResponse) GetMessageResponse() isServerReflectionResponse_MessageResponse { - if x != nil { - return x.MessageResponse - } - return nil -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionResponse) GetFileDescriptorResponse() *FileDescriptorResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_FileDescriptorResponse); ok { - return x.FileDescriptorResponse - } - } - return nil -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionResponse) GetAllExtensionNumbersResponse() *ExtensionNumberResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_AllExtensionNumbersResponse); ok { - return x.AllExtensionNumbersResponse - } - } - return nil -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionResponse) GetListServicesResponse() *ListServiceResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_ListServicesResponse); ok { - return x.ListServicesResponse - } - } - return nil -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServerReflectionResponse) GetErrorResponse() *ErrorResponse { - if x != nil { - if x, ok := x.MessageResponse.(*ServerReflectionResponse_ErrorResponse); ok { - return x.ErrorResponse - } - } - return nil -} - -type isServerReflectionResponse_MessageResponse interface { - isServerReflectionResponse_MessageResponse() -} - -type ServerReflectionResponse_FileDescriptorResponse struct { - // This message is used to answer file_by_filename, file_containing_symbol, - // file_containing_extension requests with transitive dependencies. As - // the repeated label is not allowed in oneof fields, we use a - // FileDescriptorResponse message to encapsulate the repeated fields. - // The reflection service is allowed to avoid sending FileDescriptorProtos - // that were previously sent in response to earlier requests in the stream. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - FileDescriptorResponse *FileDescriptorResponse `protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,proto3,oneof"` -} - -type ServerReflectionResponse_AllExtensionNumbersResponse struct { - // This message is used to answer all_extension_numbers_of_type request. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - AllExtensionNumbersResponse *ExtensionNumberResponse `protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,proto3,oneof"` -} - -type ServerReflectionResponse_ListServicesResponse struct { - // This message is used to answer list_services request. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ListServicesResponse *ListServiceResponse `protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,proto3,oneof"` -} - -type ServerReflectionResponse_ErrorResponse struct { - // This message is used when an error occurs. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ErrorResponse *ErrorResponse `protobuf:"bytes,7,opt,name=error_response,json=errorResponse,proto3,oneof"` -} - -func (*ServerReflectionResponse_FileDescriptorResponse) isServerReflectionResponse_MessageResponse() { -} - -func (*ServerReflectionResponse_AllExtensionNumbersResponse) isServerReflectionResponse_MessageResponse() { -} - -func (*ServerReflectionResponse_ListServicesResponse) isServerReflectionResponse_MessageResponse() {} - -func (*ServerReflectionResponse_ErrorResponse) isServerReflectionResponse_MessageResponse() {} - -// Serialized FileDescriptorProto messages sent by the server answering -// a file_by_filename, file_containing_symbol, or file_containing_extension -// request. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type FileDescriptorResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Serialized FileDescriptorProto messages. We avoid taking a dependency on - // descriptor.proto, which uses proto2 only features, by making them opaque - // bytes instead. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - FileDescriptorProto [][]byte `protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3" json:"file_descriptor_proto,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *FileDescriptorResponse) Reset() { - *x = FileDescriptorResponse{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *FileDescriptorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FileDescriptorResponse) ProtoMessage() {} - -func (x *FileDescriptorResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FileDescriptorResponse.ProtoReflect.Descriptor instead. -func (*FileDescriptorResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{3} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *FileDescriptorResponse) GetFileDescriptorProto() [][]byte { - if x != nil { - return x.FileDescriptorProto - } - return nil -} - -// A list of extension numbers sent by the server answering -// all_extension_numbers_of_type request. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type ExtensionNumberResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Full name of the base type, including the package name. The format - // is <package>.<type> - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - BaseTypeName string `protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName,proto3" json:"base_type_name,omitempty"` - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ExtensionNumber []int32 `protobuf:"varint,2,rep,packed,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ExtensionNumberResponse) Reset() { - *x = ExtensionNumberResponse{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ExtensionNumberResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExtensionNumberResponse) ProtoMessage() {} - -func (x *ExtensionNumberResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExtensionNumberResponse.ProtoReflect.Descriptor instead. -func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{4} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ExtensionNumberResponse) GetBaseTypeName() string { - if x != nil { - return x.BaseTypeName - } - return "" -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ExtensionNumberResponse) GetExtensionNumber() []int32 { - if x != nil { - return x.ExtensionNumber - } - return nil -} - -// A list of ServiceResponse sent by the server answering list_services request. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type ListServiceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The information of each service may be expanded in the future, so we use - // ServiceResponse message to encapsulate it. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service,proto3" json:"service,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListServiceResponse) Reset() { - *x = ListServiceResponse{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListServiceResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListServiceResponse) ProtoMessage() {} - -func (x *ListServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListServiceResponse.ProtoReflect.Descriptor instead. -func (*ListServiceResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{5} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ListServiceResponse) GetService() []*ServiceResponse { - if x != nil { - return x.Service - } - return nil -} - -// The information of a single service used by ListServiceResponse to answer -// list_services request. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type ServiceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Full name of a registered service, including its package name. The format - // is <package>.<service> - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ServiceResponse) Reset() { - *x = ServiceResponse{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ServiceResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServiceResponse) ProtoMessage() {} - -func (x *ServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServiceResponse.ProtoReflect.Descriptor instead. -func (*ServiceResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{6} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ServiceResponse) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// The error code and error message sent by the server when an error occurs. -// -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -type ErrorResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // This field uses the error codes defined in grpc::StatusCode. - // - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` - // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. - ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ErrorResponse) Reset() { - *x = ErrorResponse{} - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ErrorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ErrorResponse) ProtoMessage() {} - -func (x *ErrorResponse) ProtoReflect() protoreflect.Message { - mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. -func (*ErrorResponse) Descriptor() ([]byte, []int) { - return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{7} -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ErrorResponse) GetErrorCode() int32 { - if x != nil { - return x.ErrorCode - } - return 0 -} - -// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. -func (x *ErrorResponse) GetErrorMessage() string { - if x != nil { - return x.ErrorMessage - } - return "" -} - -var File_grpc_reflection_v1alpha_reflection_proto protoreflect.FileDescriptor - -const file_grpc_reflection_v1alpha_reflection_proto_rawDesc = "" + - "\n" + - "(grpc/reflection/v1alpha/reflection.proto\x12\x17grpc.reflection.v1alpha\"\xf8\x02\n" + - "\x17ServerReflectionRequest\x12\x12\n" + - "\x04host\x18\x01 \x01(\tR\x04host\x12*\n" + - "\x10file_by_filename\x18\x03 \x01(\tH\x00R\x0efileByFilename\x126\n" + - "\x16file_containing_symbol\x18\x04 \x01(\tH\x00R\x14fileContainingSymbol\x12g\n" + - "\x19file_containing_extension\x18\x05 \x01(\v2).grpc.reflection.v1alpha.ExtensionRequestH\x00R\x17fileContainingExtension\x12B\n" + - "\x1dall_extension_numbers_of_type\x18\x06 \x01(\tH\x00R\x19allExtensionNumbersOfType\x12%\n" + - "\rlist_services\x18\a \x01(\tH\x00R\flistServicesB\x11\n" + - "\x0fmessage_request\"f\n" + - "\x10ExtensionRequest\x12'\n" + - "\x0fcontaining_type\x18\x01 \x01(\tR\x0econtainingType\x12)\n" + - "\x10extension_number\x18\x02 \x01(\x05R\x0fextensionNumber\"\xc7\x04\n" + - "\x18ServerReflectionResponse\x12\x1d\n" + - "\n" + - "valid_host\x18\x01 \x01(\tR\tvalidHost\x12[\n" + - "\x10original_request\x18\x02 \x01(\v20.grpc.reflection.v1alpha.ServerReflectionRequestR\x0foriginalRequest\x12k\n" + - "\x18file_descriptor_response\x18\x04 \x01(\v2/.grpc.reflection.v1alpha.FileDescriptorResponseH\x00R\x16fileDescriptorResponse\x12w\n" + - "\x1eall_extension_numbers_response\x18\x05 \x01(\v20.grpc.reflection.v1alpha.ExtensionNumberResponseH\x00R\x1ballExtensionNumbersResponse\x12d\n" + - "\x16list_services_response\x18\x06 \x01(\v2,.grpc.reflection.v1alpha.ListServiceResponseH\x00R\x14listServicesResponse\x12O\n" + - "\x0eerror_response\x18\a \x01(\v2&.grpc.reflection.v1alpha.ErrorResponseH\x00R\rerrorResponseB\x12\n" + - "\x10message_response\"L\n" + - "\x16FileDescriptorResponse\x122\n" + - "\x15file_descriptor_proto\x18\x01 \x03(\fR\x13fileDescriptorProto\"j\n" + - "\x17ExtensionNumberResponse\x12$\n" + - "\x0ebase_type_name\x18\x01 \x01(\tR\fbaseTypeName\x12)\n" + - "\x10extension_number\x18\x02 \x03(\x05R\x0fextensionNumber\"Y\n" + - "\x13ListServiceResponse\x12B\n" + - "\aservice\x18\x01 \x03(\v2(.grpc.reflection.v1alpha.ServiceResponseR\aservice\"%\n" + - "\x0fServiceResponse\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name\"S\n" + - "\rErrorResponse\x12\x1d\n" + - "\n" + - "error_code\x18\x01 \x01(\x05R\terrorCode\x12#\n" + - "\rerror_message\x18\x02 \x01(\tR\ferrorMessage2\x93\x01\n" + - "\x10ServerReflection\x12\x7f\n" + - "\x14ServerReflectionInfo\x120.grpc.reflection.v1alpha.ServerReflectionRequest\x1a1.grpc.reflection.v1alpha.ServerReflectionResponse(\x010\x01Bs\n" + - "\x1aio.grpc.reflection.v1alphaB\x15ServerReflectionProtoP\x01Z9google.golang.org/grpc/reflection/grpc_reflection_v1alpha\xb8\x01\x01b\x06proto3" - -var ( - file_grpc_reflection_v1alpha_reflection_proto_rawDescOnce sync.Once - file_grpc_reflection_v1alpha_reflection_proto_rawDescData []byte -) - -func file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP() []byte { - file_grpc_reflection_v1alpha_reflection_proto_rawDescOnce.Do(func() { - file_grpc_reflection_v1alpha_reflection_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1alpha_reflection_proto_rawDesc), len(file_grpc_reflection_v1alpha_reflection_proto_rawDesc))) - }) - return file_grpc_reflection_v1alpha_reflection_proto_rawDescData -} - -var file_grpc_reflection_v1alpha_reflection_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_grpc_reflection_v1alpha_reflection_proto_goTypes = []any{ - (*ServerReflectionRequest)(nil), // 0: grpc.reflection.v1alpha.ServerReflectionRequest - (*ExtensionRequest)(nil), // 1: grpc.reflection.v1alpha.ExtensionRequest - (*ServerReflectionResponse)(nil), // 2: grpc.reflection.v1alpha.ServerReflectionResponse - (*FileDescriptorResponse)(nil), // 3: grpc.reflection.v1alpha.FileDescriptorResponse - (*ExtensionNumberResponse)(nil), // 4: grpc.reflection.v1alpha.ExtensionNumberResponse - (*ListServiceResponse)(nil), // 5: grpc.reflection.v1alpha.ListServiceResponse - (*ServiceResponse)(nil), // 6: grpc.reflection.v1alpha.ServiceResponse - (*ErrorResponse)(nil), // 7: grpc.reflection.v1alpha.ErrorResponse -} -var file_grpc_reflection_v1alpha_reflection_proto_depIdxs = []int32{ - 1, // 0: grpc.reflection.v1alpha.ServerReflectionRequest.file_containing_extension:type_name -> grpc.reflection.v1alpha.ExtensionRequest - 0, // 1: grpc.reflection.v1alpha.ServerReflectionResponse.original_request:type_name -> grpc.reflection.v1alpha.ServerReflectionRequest - 3, // 2: grpc.reflection.v1alpha.ServerReflectionResponse.file_descriptor_response:type_name -> grpc.reflection.v1alpha.FileDescriptorResponse - 4, // 3: grpc.reflection.v1alpha.ServerReflectionResponse.all_extension_numbers_response:type_name -> grpc.reflection.v1alpha.ExtensionNumberResponse - 5, // 4: grpc.reflection.v1alpha.ServerReflectionResponse.list_services_response:type_name -> grpc.reflection.v1alpha.ListServiceResponse - 7, // 5: grpc.reflection.v1alpha.ServerReflectionResponse.error_response:type_name -> grpc.reflection.v1alpha.ErrorResponse - 6, // 6: grpc.reflection.v1alpha.ListServiceResponse.service:type_name -> grpc.reflection.v1alpha.ServiceResponse - 0, // 7: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo:input_type -> grpc.reflection.v1alpha.ServerReflectionRequest - 2, // 8: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo:output_type -> grpc.reflection.v1alpha.ServerReflectionResponse - 8, // [8:9] is the sub-list for method output_type - 7, // [7:8] 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_grpc_reflection_v1alpha_reflection_proto_init() } -func file_grpc_reflection_v1alpha_reflection_proto_init() { - if File_grpc_reflection_v1alpha_reflection_proto != nil { - return - } - file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0].OneofWrappers = []any{ - (*ServerReflectionRequest_FileByFilename)(nil), - (*ServerReflectionRequest_FileContainingSymbol)(nil), - (*ServerReflectionRequest_FileContainingExtension)(nil), - (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil), - (*ServerReflectionRequest_ListServices)(nil), - } - file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2].OneofWrappers = []any{ - (*ServerReflectionResponse_FileDescriptorResponse)(nil), - (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil), - (*ServerReflectionResponse_ListServicesResponse)(nil), - (*ServerReflectionResponse_ErrorResponse)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1alpha_reflection_proto_rawDesc), len(file_grpc_reflection_v1alpha_reflection_proto_rawDesc)), - NumEnums: 0, - NumMessages: 8, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_grpc_reflection_v1alpha_reflection_proto_goTypes, - DependencyIndexes: file_grpc_reflection_v1alpha_reflection_proto_depIdxs, - MessageInfos: file_grpc_reflection_v1alpha_reflection_proto_msgTypes, - }.Build() - File_grpc_reflection_v1alpha_reflection_proto = out.File - file_grpc_reflection_v1alpha_reflection_proto_goTypes = nil - file_grpc_reflection_v1alpha_reflection_proto_depIdxs = nil -} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go deleted file mode 100644 index 0a43b521..00000000 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2016 The gRPC Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// Service exported by server reflection - -// Warning: this entire file is deprecated. Use this instead: -// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto - -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v5.27.1 -// grpc/reflection/v1alpha/reflection.proto is a deprecated file. - -package grpc_reflection_v1alpha - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - ServerReflection_ServerReflectionInfo_FullMethodName = "/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo" -) - -// ServerReflectionClient is the client API for ServerReflection service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type ServerReflectionClient interface { - // The reflection service is structured as a bidirectional stream, ensuring - // all related requests go to a single server. - ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) -} - -type serverReflectionClient struct { - cc grpc.ClientConnInterface -} - -func NewServerReflectionClient(cc grpc.ClientConnInterface) ServerReflectionClient { - return &serverReflectionClient{cc} -} - -func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &ServerReflection_ServiceDesc.Streams[0], ServerReflection_ServerReflectionInfo_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[ServerReflectionRequest, ServerReflectionResponse]{ClientStream: stream} - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type ServerReflection_ServerReflectionInfoClient = grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse] - -// ServerReflectionServer is the server API for ServerReflection service. -// All implementations should embed UnimplementedServerReflectionServer -// for forward compatibility. -type ServerReflectionServer interface { - // The reflection service is structured as a bidirectional stream, ensuring - // all related requests go to a single server. - ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error -} - -// UnimplementedServerReflectionServer should be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedServerReflectionServer struct{} - -func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error { - return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented") -} -func (UnimplementedServerReflectionServer) testEmbeddedByValue() {} - -// UnsafeServerReflectionServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to ServerReflectionServer will -// result in compilation errors. -type UnsafeServerReflectionServer interface { - mustEmbedUnimplementedServerReflectionServer() -} - -func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) { - // If the following call panics, it indicates UnimplementedServerReflectionServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&ServerReflection_ServiceDesc, srv) -} - -func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(ServerReflectionServer).ServerReflectionInfo(&grpc.GenericServerStream[ServerReflectionRequest, ServerReflectionResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type ServerReflection_ServerReflectionInfoServer = grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse] - -// ServerReflection_ServiceDesc is the grpc.ServiceDesc for ServerReflection service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var ServerReflection_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "grpc.reflection.v1alpha.ServerReflection", - HandlerType: (*ServerReflectionServer)(nil), - Methods: []grpc.MethodDesc{}, - Streams: []grpc.StreamDesc{ - { - StreamName: "ServerReflectionInfo", - Handler: _ServerReflection_ServerReflectionInfo_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, - Metadata: "grpc/reflection/v1alpha/reflection.proto", -} diff --git a/vendor/google.golang.org/grpc/reflection/internal/internal.go b/vendor/google.golang.org/grpc/reflection/internal/internal.go deleted file mode 100644 index 902fc6d3..00000000 --- a/vendor/google.golang.org/grpc/reflection/internal/internal.go +++ /dev/null @@ -1,436 +0,0 @@ -/* - * - * Copyright 2024 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// Package internal contains code that is shared by both reflection package and -// the test package. The packages are split in this way inorder to avoid -// dependency to deprecated package github.com/golang/protobuf. -package internal - -import ( - "io" - "sort" - - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protodesc" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - - v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" - v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1" - v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" - v1alphareflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" -) - -// ServiceInfoProvider is an interface used to retrieve metadata about the -// services to expose. -type ServiceInfoProvider interface { - GetServiceInfo() map[string]grpc.ServiceInfo -} - -// ExtensionResolver is the interface used to query details about extensions. -// This interface is satisfied by protoregistry.GlobalTypes. -type ExtensionResolver interface { - protoregistry.ExtensionTypeResolver - RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) -} - -// ServerReflectionServer is the server API for ServerReflection service. -type ServerReflectionServer struct { - v1alphareflectiongrpc.UnimplementedServerReflectionServer - S ServiceInfoProvider - DescResolver protodesc.Resolver - ExtResolver ExtensionResolver -} - -// FileDescWithDependencies returns a slice of serialized fileDescriptors in -// wire format ([]byte). The fileDescriptors will include fd and all the -// transitive dependencies of fd with names not in sentFileDescriptors. -func (s *ServerReflectionServer) FileDescWithDependencies(fd protoreflect.FileDescriptor, sentFileDescriptors map[string]bool) ([][]byte, error) { - if fd.IsPlaceholder() { - // If the given root file is a placeholder, treat it - // as missing instead of serializing it. - return nil, protoregistry.NotFound - } - var r [][]byte - queue := []protoreflect.FileDescriptor{fd} - for len(queue) > 0 { - currentfd := queue[0] - queue = queue[1:] - if currentfd.IsPlaceholder() { - // Skip any missing files in the dependency graph. - continue - } - if sent := sentFileDescriptors[currentfd.Path()]; len(r) == 0 || !sent { - sentFileDescriptors[currentfd.Path()] = true - fdProto := protodesc.ToFileDescriptorProto(currentfd) - currentfdEncoded, err := proto.Marshal(fdProto) - if err != nil { - return nil, err - } - r = append(r, currentfdEncoded) - } - for i := 0; i < currentfd.Imports().Len(); i++ { - queue = append(queue, currentfd.Imports().Get(i)) - } - } - return r, nil -} - -// FileDescEncodingContainingSymbol finds the file descriptor containing the -// given symbol, finds all of its previously unsent transitive dependencies, -// does marshalling on them, and returns the marshalled result. The given symbol -// can be a type, a service or a method. -func (s *ServerReflectionServer) FileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) { - d, err := s.DescResolver.FindDescriptorByName(protoreflect.FullName(name)) - if err != nil { - return nil, err - } - return s.FileDescWithDependencies(d.ParentFile(), sentFileDescriptors) -} - -// FileDescEncodingContainingExtension finds the file descriptor containing -// given extension, finds all of its previously unsent transitive dependencies, -// does marshalling on them, and returns the marshalled result. -func (s *ServerReflectionServer) FileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) { - xt, err := s.ExtResolver.FindExtensionByNumber(protoreflect.FullName(typeName), protoreflect.FieldNumber(extNum)) - if err != nil { - return nil, err - } - return s.FileDescWithDependencies(xt.TypeDescriptor().ParentFile(), sentFileDescriptors) -} - -// AllExtensionNumbersForTypeName returns all extension numbers for the given type. -func (s *ServerReflectionServer) AllExtensionNumbersForTypeName(name string) ([]int32, error) { - var numbers []int32 - s.ExtResolver.RangeExtensionsByMessage(protoreflect.FullName(name), func(xt protoreflect.ExtensionType) bool { - numbers = append(numbers, int32(xt.TypeDescriptor().Number())) - return true - }) - sort.Slice(numbers, func(i, j int) bool { - return numbers[i] < numbers[j] - }) - if len(numbers) == 0 { - // maybe return an error if given type name is not known - if _, err := s.DescResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil { - return nil, err - } - } - return numbers, nil -} - -// ListServices returns the names of services this server exposes. -func (s *ServerReflectionServer) ListServices() []*v1reflectionpb.ServiceResponse { - serviceInfo := s.S.GetServiceInfo() - resp := make([]*v1reflectionpb.ServiceResponse, 0, len(serviceInfo)) - for svc := range serviceInfo { - resp = append(resp, &v1reflectionpb.ServiceResponse{Name: svc}) - } - sort.Slice(resp, func(i, j int) bool { - return resp[i].Name < resp[j].Name - }) - return resp -} - -// ServerReflectionInfo is the reflection service handler. -func (s *ServerReflectionServer) ServerReflectionInfo(stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoServer) error { - sentFileDescriptors := make(map[string]bool) - for { - in, err := stream.Recv() - if err == io.EOF { - return nil - } - if err != nil { - return err - } - - out := &v1reflectionpb.ServerReflectionResponse{ - ValidHost: in.Host, - OriginalRequest: in, - } - switch req := in.MessageRequest.(type) { - case *v1reflectionpb.ServerReflectionRequest_FileByFilename: - var b [][]byte - fd, err := s.DescResolver.FindFileByPath(req.FileByFilename) - if err == nil { - b, err = s.FileDescWithDependencies(fd, sentFileDescriptors) - } - if err != nil { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ - ErrorResponse: &v1reflectionpb.ErrorResponse{ - ErrorCode: int32(codes.NotFound), - ErrorMessage: err.Error(), - }, - } - } else { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ - FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, - } - } - case *v1reflectionpb.ServerReflectionRequest_FileContainingSymbol: - b, err := s.FileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors) - if err != nil { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ - ErrorResponse: &v1reflectionpb.ErrorResponse{ - ErrorCode: int32(codes.NotFound), - ErrorMessage: err.Error(), - }, - } - } else { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ - FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, - } - } - case *v1reflectionpb.ServerReflectionRequest_FileContainingExtension: - typeName := req.FileContainingExtension.ContainingType - extNum := req.FileContainingExtension.ExtensionNumber - b, err := s.FileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors) - if err != nil { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ - ErrorResponse: &v1reflectionpb.ErrorResponse{ - ErrorCode: int32(codes.NotFound), - ErrorMessage: err.Error(), - }, - } - } else { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ - FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, - } - } - case *v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: - extNums, err := s.AllExtensionNumbersForTypeName(req.AllExtensionNumbersOfType) - if err != nil { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ - ErrorResponse: &v1reflectionpb.ErrorResponse{ - ErrorCode: int32(codes.NotFound), - ErrorMessage: err.Error(), - }, - } - } else { - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ - AllExtensionNumbersResponse: &v1reflectionpb.ExtensionNumberResponse{ - BaseTypeName: req.AllExtensionNumbersOfType, - ExtensionNumber: extNums, - }, - } - } - case *v1reflectionpb.ServerReflectionRequest_ListServices: - out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ListServicesResponse{ - ListServicesResponse: &v1reflectionpb.ListServiceResponse{ - Service: s.ListServices(), - }, - } - default: - return status.Errorf(codes.InvalidArgument, "invalid MessageRequest: %v", in.MessageRequest) - } - - if err := stream.Send(out); err != nil { - return err - } - } -} - -// V1ToV1AlphaResponse converts a v1 ServerReflectionResponse to a v1alpha. -func V1ToV1AlphaResponse(v1 *v1reflectionpb.ServerReflectionResponse) *v1alphareflectionpb.ServerReflectionResponse { - var v1alpha v1alphareflectionpb.ServerReflectionResponse - v1alpha.ValidHost = v1.ValidHost - if v1.OriginalRequest != nil { - v1alpha.OriginalRequest = V1ToV1AlphaRequest(v1.OriginalRequest) - } - switch mr := v1.MessageResponse.(type) { - case *v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse: - if mr != nil { - v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_FileDescriptorResponse{ - FileDescriptorResponse: &v1alphareflectionpb.FileDescriptorResponse{ - FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(), - }, - } - } - case *v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse: - if mr != nil { - v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ - AllExtensionNumbersResponse: &v1alphareflectionpb.ExtensionNumberResponse{ - BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(), - ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(), - }, - } - } - case *v1reflectionpb.ServerReflectionResponse_ListServicesResponse: - if mr != nil { - svcs := make([]*v1alphareflectionpb.ServiceResponse, len(mr.ListServicesResponse.GetService())) - for i, svc := range mr.ListServicesResponse.GetService() { - svcs[i] = &v1alphareflectionpb.ServiceResponse{ - Name: svc.GetName(), - } - } - v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_ListServicesResponse{ - ListServicesResponse: &v1alphareflectionpb.ListServiceResponse{ - Service: svcs, - }, - } - } - case *v1reflectionpb.ServerReflectionResponse_ErrorResponse: - if mr != nil { - v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_ErrorResponse{ - ErrorResponse: &v1alphareflectionpb.ErrorResponse{ - ErrorCode: mr.ErrorResponse.GetErrorCode(), - ErrorMessage: mr.ErrorResponse.GetErrorMessage(), - }, - } - } - default: - // no value set - } - return &v1alpha -} - -// V1AlphaToV1Request converts a v1alpha ServerReflectionRequest to a v1. -func V1AlphaToV1Request(v1alpha *v1alphareflectionpb.ServerReflectionRequest) *v1reflectionpb.ServerReflectionRequest { - var v1 v1reflectionpb.ServerReflectionRequest - v1.Host = v1alpha.Host - switch mr := v1alpha.MessageRequest.(type) { - case *v1alphareflectionpb.ServerReflectionRequest_FileByFilename: - v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileByFilename{ - FileByFilename: mr.FileByFilename, - } - case *v1alphareflectionpb.ServerReflectionRequest_FileContainingSymbol: - v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileContainingSymbol{ - FileContainingSymbol: mr.FileContainingSymbol, - } - case *v1alphareflectionpb.ServerReflectionRequest_FileContainingExtension: - if mr.FileContainingExtension != nil { - v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileContainingExtension{ - FileContainingExtension: &v1reflectionpb.ExtensionRequest{ - ContainingType: mr.FileContainingExtension.GetContainingType(), - ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(), - }, - } - } - case *v1alphareflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: - v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{ - AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType, - } - case *v1alphareflectionpb.ServerReflectionRequest_ListServices: - v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_ListServices{ - ListServices: mr.ListServices, - } - default: - // no value set - } - return &v1 -} - -// V1ToV1AlphaRequest converts a v1 ServerReflectionRequest to a v1alpha. -func V1ToV1AlphaRequest(v1 *v1reflectionpb.ServerReflectionRequest) *v1alphareflectionpb.ServerReflectionRequest { - var v1alpha v1alphareflectionpb.ServerReflectionRequest - v1alpha.Host = v1.Host - switch mr := v1.MessageRequest.(type) { - case *v1reflectionpb.ServerReflectionRequest_FileByFilename: - if mr != nil { - v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileByFilename{ - FileByFilename: mr.FileByFilename, - } - } - case *v1reflectionpb.ServerReflectionRequest_FileContainingSymbol: - if mr != nil { - v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileContainingSymbol{ - FileContainingSymbol: mr.FileContainingSymbol, - } - } - case *v1reflectionpb.ServerReflectionRequest_FileContainingExtension: - if mr != nil { - v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileContainingExtension{ - FileContainingExtension: &v1alphareflectionpb.ExtensionRequest{ - ContainingType: mr.FileContainingExtension.GetContainingType(), - ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(), - }, - } - } - case *v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: - if mr != nil { - v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{ - AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType, - } - } - case *v1reflectionpb.ServerReflectionRequest_ListServices: - if mr != nil { - v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_ListServices{ - ListServices: mr.ListServices, - } - } - default: - // no value set - } - return &v1alpha -} - -// V1AlphaToV1Response converts a v1alpha ServerReflectionResponse to a v1. -func V1AlphaToV1Response(v1alpha *v1alphareflectionpb.ServerReflectionResponse) *v1reflectionpb.ServerReflectionResponse { - var v1 v1reflectionpb.ServerReflectionResponse - v1.ValidHost = v1alpha.ValidHost - if v1alpha.OriginalRequest != nil { - v1.OriginalRequest = V1AlphaToV1Request(v1alpha.OriginalRequest) - } - switch mr := v1alpha.MessageResponse.(type) { - case *v1alphareflectionpb.ServerReflectionResponse_FileDescriptorResponse: - if mr != nil { - v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ - FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{ - FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(), - }, - } - } - case *v1alphareflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse: - if mr != nil { - v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ - AllExtensionNumbersResponse: &v1reflectionpb.ExtensionNumberResponse{ - BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(), - ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(), - }, - } - } - case *v1alphareflectionpb.ServerReflectionResponse_ListServicesResponse: - if mr != nil { - svcs := make([]*v1reflectionpb.ServiceResponse, len(mr.ListServicesResponse.GetService())) - for i, svc := range mr.ListServicesResponse.GetService() { - svcs[i] = &v1reflectionpb.ServiceResponse{ - Name: svc.GetName(), - } - } - v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ListServicesResponse{ - ListServicesResponse: &v1reflectionpb.ListServiceResponse{ - Service: svcs, - }, - } - } - case *v1alphareflectionpb.ServerReflectionResponse_ErrorResponse: - if mr != nil { - v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ - ErrorResponse: &v1reflectionpb.ErrorResponse{ - ErrorCode: mr.ErrorResponse.GetErrorCode(), - ErrorMessage: mr.ErrorResponse.GetErrorMessage(), - }, - } - } - default: - // no value set - } - return &v1 -} diff --git a/vendor/google.golang.org/grpc/reflection/serverreflection.go b/vendor/google.golang.org/grpc/reflection/serverreflection.go deleted file mode 100644 index 13a94e2d..00000000 --- a/vendor/google.golang.org/grpc/reflection/serverreflection.go +++ /dev/null @@ -1,160 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* -Package reflection implements server reflection service. - -The service implemented is defined in: -https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto. - -To register server reflection on a gRPC server: - - import "google.golang.org/grpc/reflection" - - s := grpc.NewServer() - pb.RegisterYourOwnServer(s, &server{}) - - // Register reflection service on gRPC server. - reflection.Register(s) - - s.Serve(lis) -*/ -package reflection // import "google.golang.org/grpc/reflection" - -import ( - "google.golang.org/grpc" - "google.golang.org/grpc/reflection/internal" - "google.golang.org/protobuf/reflect/protodesc" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - - v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" - v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" -) - -// GRPCServer is the interface provided by a gRPC server. It is implemented by -// *grpc.Server, but could also be implemented by other concrete types. It acts -// as a registry, for accumulating the services exposed by the server. -type GRPCServer interface { - grpc.ServiceRegistrar - ServiceInfoProvider -} - -var _ GRPCServer = (*grpc.Server)(nil) - -// Register registers the server reflection service on the given gRPC server. -// Both the v1 and v1alpha versions are registered. -func Register(s GRPCServer) { - svr := NewServerV1(ServerOptions{Services: s}) - v1alphareflectiongrpc.RegisterServerReflectionServer(s, asV1Alpha(svr)) - v1reflectiongrpc.RegisterServerReflectionServer(s, svr) -} - -// RegisterV1 registers only the v1 version of the server reflection service -// on the given gRPC server. Many clients may only support v1alpha so most -// users should use Register instead, at least until clients have upgraded. -func RegisterV1(s GRPCServer) { - svr := NewServerV1(ServerOptions{Services: s}) - v1reflectiongrpc.RegisterServerReflectionServer(s, svr) -} - -// ServiceInfoProvider is an interface used to retrieve metadata about the -// services to expose. -// -// The reflection service is only interested in the service names, but the -// signature is this way so that *grpc.Server implements it. So it is okay -// for a custom implementation to return zero values for the -// grpc.ServiceInfo values in the map. -// -// # Experimental -// -// Notice: This type is EXPERIMENTAL and may be changed or removed in a -// later release. -type ServiceInfoProvider interface { - GetServiceInfo() map[string]grpc.ServiceInfo -} - -// ExtensionResolver is the interface used to query details about extensions. -// This interface is satisfied by protoregistry.GlobalTypes. -// -// # Experimental -// -// Notice: This type is EXPERIMENTAL and may be changed or removed in a -// later release. -type ExtensionResolver interface { - protoregistry.ExtensionTypeResolver - RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) -} - -// ServerOptions represents the options used to construct a reflection server. -// -// # Experimental -// -// Notice: This type is EXPERIMENTAL and may be changed or removed in a -// later release. -type ServerOptions struct { - // The source of advertised RPC services. If not specified, the reflection - // server will report an empty list when asked to list services. - // - // This value will typically be a *grpc.Server. But the set of advertised - // services can be customized by wrapping a *grpc.Server or using an - // alternate implementation that returns a custom set of service names. - Services ServiceInfoProvider - // Optional resolver used to load descriptors. If not specified, - // protoregistry.GlobalFiles will be used. - DescriptorResolver protodesc.Resolver - // Optional resolver used to query for known extensions. If not specified, - // protoregistry.GlobalTypes will be used. - ExtensionResolver ExtensionResolver -} - -// NewServer returns a reflection server implementation using the given options. -// This can be used to customize behavior of the reflection service. Most usages -// should prefer to use Register instead. For backwards compatibility reasons, -// this returns the v1alpha version of the reflection server. For a v1 version -// of the reflection server, see NewServerV1. -// -// # Experimental -// -// Notice: This function is EXPERIMENTAL and may be changed or removed in a -// later release. -func NewServer(opts ServerOptions) v1alphareflectiongrpc.ServerReflectionServer { - return asV1Alpha(NewServerV1(opts)) -} - -// NewServerV1 returns a reflection server implementation using the given options. -// This can be used to customize behavior of the reflection service. Most usages -// should prefer to use Register instead. -// -// # Experimental -// -// Notice: This function is EXPERIMENTAL and may be changed or removed in a -// later release. -func NewServerV1(opts ServerOptions) v1reflectiongrpc.ServerReflectionServer { - if opts.DescriptorResolver == nil { - opts.DescriptorResolver = protoregistry.GlobalFiles - } - if opts.ExtensionResolver == nil { - opts.ExtensionResolver = protoregistry.GlobalTypes - } - return &internal.ServerReflectionServer{ - S: opts.Services, - DescResolver: opts.DescriptorResolver, - ExtResolver: opts.ExtensionResolver, - } -} diff --git a/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go b/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go deleted file mode 100644 index 2ef36bbc..00000000 --- a/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package protodelim marshals and unmarshals varint size-delimited messages. -package protodelim - -import ( - "bufio" - "encoding/binary" - "fmt" - "io" - - "google.golang.org/protobuf/encoding/protowire" - "google.golang.org/protobuf/internal/errors" - "google.golang.org/protobuf/proto" -) - -// MarshalOptions is a configurable varint size-delimited marshaler. -type MarshalOptions struct{ proto.MarshalOptions } - -// MarshalTo writes a varint size-delimited wire-format message to w. -// If w returns an error, MarshalTo returns it unchanged. -func (o MarshalOptions) MarshalTo(w io.Writer, m proto.Message) (int, error) { - msgBytes, err := o.MarshalOptions.Marshal(m) - if err != nil { - return 0, err - } - - sizeBytes := protowire.AppendVarint(nil, uint64(len(msgBytes))) - sizeWritten, err := w.Write(sizeBytes) - if err != nil { - return sizeWritten, err - } - msgWritten, err := w.Write(msgBytes) - if err != nil { - return sizeWritten + msgWritten, err - } - return sizeWritten + msgWritten, nil -} - -// MarshalTo writes a varint size-delimited wire-format message to w -// with the default options. -// -// See the documentation for [MarshalOptions.MarshalTo]. -func MarshalTo(w io.Writer, m proto.Message) (int, error) { - return MarshalOptions{}.MarshalTo(w, m) -} - -// UnmarshalOptions is a configurable varint size-delimited unmarshaler. -type UnmarshalOptions struct { - proto.UnmarshalOptions - - // MaxSize is the maximum size in wire-format bytes of a single message. - // Unmarshaling a message larger than MaxSize will return an error. - // A zero MaxSize will default to 4 MiB. - // Setting MaxSize to -1 disables the limit. - MaxSize int64 -} - -const defaultMaxSize = 4 << 20 // 4 MiB, corresponds to the default gRPC max request/response size - -// SizeTooLargeError is an error that is returned when the unmarshaler encounters a message size -// that is larger than its configured [UnmarshalOptions.MaxSize]. -type SizeTooLargeError struct { - // Size is the varint size of the message encountered - // that was larger than the provided MaxSize. - Size uint64 - - // MaxSize is the MaxSize limit configured in UnmarshalOptions, which Size exceeded. - MaxSize uint64 -} - -func (e *SizeTooLargeError) Error() string { - return fmt.Sprintf("message size %d exceeded unmarshaler's maximum configured size %d", e.Size, e.MaxSize) -} - -// Reader is the interface expected by [UnmarshalFrom]. -// It is implemented by *[bufio.Reader]. -type Reader interface { - io.Reader - io.ByteReader -} - -// UnmarshalFrom parses and consumes a varint size-delimited wire-format message -// from r. -// The provided message must be mutable (e.g., a non-nil pointer to a message). -// -// The error is [io.EOF] error only if no bytes are read. -// If an EOF happens after reading some but not all the bytes, -// UnmarshalFrom returns a non-io.EOF error. -// In particular if r returns a non-io.EOF error, UnmarshalFrom returns it unchanged, -// and if only a size is read with no subsequent message, [io.ErrUnexpectedEOF] is returned. -func (o UnmarshalOptions) UnmarshalFrom(r Reader, m proto.Message) error { - var sizeArr [binary.MaxVarintLen64]byte - sizeBuf := sizeArr[:0] - for i := range sizeArr { - b, err := r.ReadByte() - if err != nil { - // Immediate EOF is unexpected. - if err == io.EOF && i != 0 { - break - } - return err - } - sizeBuf = append(sizeBuf, b) - if b < 0x80 { - break - } - } - size, n := protowire.ConsumeVarint(sizeBuf) - if n < 0 { - return protowire.ParseError(n) - } - - maxSize := o.MaxSize - if maxSize == 0 { - maxSize = defaultMaxSize - } - if maxSize != -1 && size > uint64(maxSize) { - return errors.Wrap(&SizeTooLargeError{Size: size, MaxSize: uint64(maxSize)}, "") - } - - var b []byte - var err error - if br, ok := r.(*bufio.Reader); ok { - // Use the []byte from the bufio.Reader instead of having to allocate one. - // This reduces CPU usage and allocated bytes. - b, err = br.Peek(int(size)) - if err == nil { - defer br.Discard(int(size)) - } else { - b = nil - } - } - if b == nil { - b = make([]byte, size) - _, err = io.ReadFull(r, b) - } - - if err == io.EOF { - return io.ErrUnexpectedEOF - } - if err != nil { - return err - } - if err := o.Unmarshal(b, m); err != nil { - return err - } - return nil -} - -// UnmarshalFrom parses and consumes a varint size-delimited wire-format message -// from r with the default options. -// The provided message must be mutable (e.g., a non-nil pointer to a message). -// -// See the documentation for [UnmarshalOptions.UnmarshalFrom]. -func UnmarshalFrom(r Reader, m proto.Message) error { - return UnmarshalOptions{}.UnmarshalFrom(r, m) -} diff --git a/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go b/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go deleted file mode 100644 index 7b9f01af..00000000 --- a/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go +++ /dev/null @@ -1,18 +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 editionssupport defines constants for editions that are supported. -package editionssupport - -import "google.golang.org/protobuf/types/descriptorpb" - -const ( - Minimum = descriptorpb.Edition_EDITION_PROTO2 - Maximum = descriptorpb.Edition_EDITION_2024 - - // MaximumKnown is the maximum edition that is known to Go Protobuf, but not - // declared as supported. In other words: end users cannot use it, but - // testprotos inside Go Protobuf can. - MaximumKnown = descriptorpb.Edition_EDITION_2024 -) diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go deleted file mode 100644 index 9196288e..00000000 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go +++ /dev/null @@ -1,308 +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. - -// Package protodesc provides functionality for converting -// FileDescriptorProto messages to/from [protoreflect.FileDescriptor] values. -// -// The google.protobuf.FileDescriptorProto is a protobuf message that describes -// the type information for a .proto file in a form that is easily serializable. -// The [protoreflect.FileDescriptor] is a more structured representation of -// the FileDescriptorProto message where references and remote dependencies -// can be directly followed. -package protodesc - -import ( - "strings" - - "google.golang.org/protobuf/internal/editionssupport" - "google.golang.org/protobuf/internal/errors" - "google.golang.org/protobuf/internal/filedesc" - "google.golang.org/protobuf/internal/pragma" - "google.golang.org/protobuf/internal/strs" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - - "google.golang.org/protobuf/types/descriptorpb" -) - -// Resolver is the resolver used by [NewFile] to resolve dependencies. -// The enums and messages provided must belong to some parent file, -// which is also registered. -// -// It is implemented by [protoregistry.Files]. -type Resolver interface { - FindFileByPath(string) (protoreflect.FileDescriptor, error) - FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error) -} - -// FileOptions configures the construction of file descriptors. -type FileOptions struct { - pragma.NoUnkeyedLiterals - - // AllowUnresolvable configures New to permissively allow unresolvable - // file, enum, or message dependencies. Unresolved dependencies are replaced - // by placeholder equivalents. - // - // The following dependencies may be left unresolved: - // • Resolving an imported file. - // • Resolving the type for a message field or extension field. - // If the kind of the field is unknown, then a placeholder is used for both - // the Enum and Message accessors on the protoreflect.FieldDescriptor. - // • Resolving an enum value set as the default for an optional enum field. - // If unresolvable, the protoreflect.FieldDescriptor.Default is set to the - // first value in the associated enum (or zero if the also enum dependency - // is also unresolvable). The protoreflect.FieldDescriptor.DefaultEnumValue - // is populated with a placeholder. - // • Resolving the extended message type for an extension field. - // • Resolving the input or output message type for a service method. - // - // If the unresolved dependency uses a relative name, - // then the placeholder will contain an invalid FullName with a "*." prefix, - // indicating that the starting prefix of the full name is unknown. - AllowUnresolvable bool -} - -// NewFile creates a new [protoreflect.FileDescriptor] from the provided -// file descriptor message. See [FileOptions.New] for more information. -func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) { - return FileOptions{}.New(fd, r) -} - -// NewFiles creates a new [protoregistry.Files] from the provided -// FileDescriptorSet message. See [FileOptions.NewFiles] for more information. -func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) { - return FileOptions{}.NewFiles(fd) -} - -// New creates a new [protoreflect.FileDescriptor] from the provided -// file descriptor message. The file must represent a valid proto file according -// to protobuf semantics. The returned descriptor is a deep copy of the input. -// -// Any imported files, enum types, or message types referenced in the file are -// resolved using the provided registry. When looking up an import file path, -// the path must be unique. The newly created file descriptor is not registered -// back into the provided file registry. -func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) { - if r == nil { - r = (*protoregistry.Files)(nil) // empty resolver - } - - // Handle the file descriptor content. - f := &filedesc.File{L2: &filedesc.FileL2{}} - switch fd.GetSyntax() { - case "proto2", "": - f.L1.Syntax = protoreflect.Proto2 - f.L1.Edition = filedesc.EditionProto2 - case "proto3": - f.L1.Syntax = protoreflect.Proto3 - f.L1.Edition = filedesc.EditionProto3 - case "editions": - f.L1.Syntax = protoreflect.Editions - f.L1.Edition = fromEditionProto(fd.GetEdition()) - default: - return nil, errors.New("invalid syntax: %q", fd.GetSyntax()) - } - f.L1.Path = fd.GetName() - if f.L1.Path == "" { - return nil, errors.New("file path must be populated") - } - if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) { - // Allow cmd/protoc-gen-go/testdata to use any edition for easier - // testing of upcoming edition features. - if !strings.HasPrefix(fd.GetName(), "cmd/protoc-gen-go/testdata/") { - return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition()) - } - } - f.L1.Package = protoreflect.FullName(fd.GetPackage()) - if !f.L1.Package.IsValid() && f.L1.Package != "" { - return nil, errors.New("invalid package: %q", f.L1.Package) - } - if opts := fd.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.FileOptions) - f.L2.Options = func() protoreflect.ProtoMessage { return opts } - } - initFileDescFromFeatureSet(f, fd.GetOptions().GetFeatures()) - - f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency())) - for _, i := range fd.GetPublicDependency() { - if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsPublic { - return nil, errors.New("invalid or duplicate public import index: %d", i) - } - f.L2.Imports[i].IsPublic = true - } - imps := importSet{f.Path(): true} - for i, path := range fd.GetDependency() { - imp := &f.L2.Imports[i] - f, err := r.FindFileByPath(path) - if err == protoregistry.NotFound && o.AllowUnresolvable { - f = filedesc.PlaceholderFile(path) - } else if err != nil { - return nil, errors.New("could not resolve import %q: %v", path, err) - } - imp.FileDescriptor = f - - if imps[imp.Path()] { - return nil, errors.New("already imported %q", path) - } - imps[imp.Path()] = true - } - for i := range fd.GetDependency() { - imp := &f.L2.Imports[i] - imps.importPublic(imp.Imports()) - } - if len(fd.GetOptionDependency()) > 0 { - optionImports := make(filedesc.FileImports, len(fd.GetOptionDependency())) - for i, path := range fd.GetOptionDependency() { - imp := &optionImports[i] - f, err := r.FindFileByPath(path) - if err == protoregistry.NotFound { - // We always allow option imports to be unresolvable. - f = filedesc.PlaceholderFile(path) - } else if err != nil { - return nil, errors.New("could not resolve import %q: %v", path, err) - } - imp.FileDescriptor = f - - if imps[imp.Path()] { - return nil, errors.New("already imported %q", path) - } - imps[imp.Path()] = true - } - f.L2.OptionImports = func() protoreflect.FileImports { - return &optionImports - } - } - - // Handle source locations. - f.L2.Locations.File = f - for _, loc := range fd.GetSourceCodeInfo().GetLocation() { - var l protoreflect.SourceLocation - // TODO: Validate that the path points to an actual declaration? - l.Path = protoreflect.SourcePath(loc.GetPath()) - s := loc.GetSpan() - switch len(s) { - case 3: - l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[0]), int(s[2]) - case 4: - l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[2]), int(s[3]) - default: - return nil, errors.New("invalid span: %v", s) - } - // TODO: Validate that the span information is sensible? - // See https://github.com/protocolbuffers/protobuf/issues/6378. - if false && (l.EndLine < l.StartLine || l.StartLine < 0 || l.StartColumn < 0 || l.EndColumn < 0 || - (l.StartLine == l.EndLine && l.EndColumn <= l.StartColumn)) { - return nil, errors.New("invalid span: %v", s) - } - l.LeadingDetachedComments = loc.GetLeadingDetachedComments() - l.LeadingComments = loc.GetLeadingComments() - l.TrailingComments = loc.GetTrailingComments() - f.L2.Locations.List = append(f.L2.Locations.List, l) - } - - // Step 1: Allocate and derive the names for all declarations. - // This copies all fields from the descriptor proto except: - // google.protobuf.FieldDescriptorProto.type_name - // google.protobuf.FieldDescriptorProto.default_value - // google.protobuf.FieldDescriptorProto.oneof_index - // google.protobuf.FieldDescriptorProto.extendee - // google.protobuf.MethodDescriptorProto.input - // google.protobuf.MethodDescriptorProto.output - var err error - sb := new(strs.Builder) - r1 := make(descsByName) - if f.L1.Enums.List, err = r1.initEnumDeclarations(fd.GetEnumType(), f, sb); err != nil { - return nil, err - } - if f.L1.Messages.List, err = r1.initMessagesDeclarations(fd.GetMessageType(), f, sb); err != nil { - return nil, err - } - if f.L1.Extensions.List, err = r1.initExtensionDeclarations(fd.GetExtension(), f, sb); err != nil { - return nil, err - } - if f.L1.Services.List, err = r1.initServiceDeclarations(fd.GetService(), f, sb); err != nil { - return nil, err - } - - // Step 2: Resolve every dependency reference not handled by step 1. - r2 := &resolver{local: r1, remote: r, imports: imps, allowUnresolvable: o.AllowUnresolvable} - if err := r2.resolveMessageDependencies(f.L1.Messages.List, fd.GetMessageType()); err != nil { - return nil, err - } - if err := r2.resolveExtensionDependencies(f.L1.Extensions.List, fd.GetExtension()); err != nil { - return nil, err - } - if err := r2.resolveServiceDependencies(f.L1.Services.List, fd.GetService()); err != nil { - return nil, err - } - - // Step 3: Validate every enum, message, and extension declaration. - if err := validateEnumDeclarations(f.L1.Enums.List, fd.GetEnumType()); err != nil { - return nil, err - } - if err := validateMessageDeclarations(f, f.L1.Messages.List, fd.GetMessageType()); err != nil { - return nil, err - } - if err := validateExtensionDeclarations(f, f.L1.Extensions.List, fd.GetExtension()); err != nil { - return nil, err - } - - return f, nil -} - -type importSet map[string]bool - -func (is importSet) importPublic(imps protoreflect.FileImports) { - for i := 0; i < imps.Len(); i++ { - if imp := imps.Get(i); imp.IsPublic { - is[imp.Path()] = true - is.importPublic(imp.Imports()) - } - } -} - -// NewFiles creates a new [protoregistry.Files] from the provided -// FileDescriptorSet message. The descriptor set must include only -// valid files according to protobuf semantics. The returned descriptors -// are a deep copy of the input. -func (o FileOptions) NewFiles(fds *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) { - files := make(map[string]*descriptorpb.FileDescriptorProto) - for _, fd := range fds.File { - if _, ok := files[fd.GetName()]; ok { - return nil, errors.New("file appears multiple times: %q", fd.GetName()) - } - files[fd.GetName()] = fd - } - r := &protoregistry.Files{} - for _, fd := range files { - if err := o.addFileDeps(r, fd, files); err != nil { - return nil, err - } - } - return r, nil -} -func (o FileOptions) addFileDeps(r *protoregistry.Files, fd *descriptorpb.FileDescriptorProto, files map[string]*descriptorpb.FileDescriptorProto) error { - // Set the entry to nil while descending into a file's dependencies to detect cycles. - files[fd.GetName()] = nil - for _, dep := range fd.Dependency { - depfd, ok := files[dep] - if depfd == nil { - if ok { - return errors.New("import cycle in file: %q", dep) - } - continue - } - if err := o.addFileDeps(r, depfd, files); err != nil { - return err - } - } - // Delete the entry once dependencies are processed. - delete(files, fd.GetName()) - f, err := o.New(fd, r) - if err != nil { - return err - } - return r.RegisterFile(f) -} diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go deleted file mode 100644 index c826ad04..00000000 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package protodesc - -import ( - "google.golang.org/protobuf/internal/errors" - "google.golang.org/protobuf/internal/filedesc" - "google.golang.org/protobuf/internal/strs" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - - "google.golang.org/protobuf/types/descriptorpb" -) - -type descsByName map[protoreflect.FullName]protoreflect.Descriptor - -func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (es []filedesc.Enum, err error) { - es = make([]filedesc.Enum, len(eds)) // allocate up-front to ensure stable pointers - for i, ed := range eds { - e := &es[i] - e.L2 = new(filedesc.EnumL2) - if e.L0, err = r.makeBase(e, parent, ed.GetName(), i, sb); err != nil { - return nil, err - } - if opts := ed.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.EnumOptions) - e.L2.Options = func() protoreflect.ProtoMessage { return opts } - } - e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures()) - e.L1.Visibility = int32(ed.GetVisibility()) - for _, s := range ed.GetReservedName() { - e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s)) - } - for _, rr := range ed.GetReservedRange() { - e.L2.ReservedRanges.List = append(e.L2.ReservedRanges.List, [2]protoreflect.EnumNumber{ - protoreflect.EnumNumber(rr.GetStart()), - protoreflect.EnumNumber(rr.GetEnd()), - }) - } - if e.L2.Values.List, err = r.initEnumValuesFromDescriptorProto(ed.GetValue(), e, sb); err != nil { - return nil, err - } - } - return es, nil -} - -func (r descsByName) initEnumValuesFromDescriptorProto(vds []*descriptorpb.EnumValueDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (vs []filedesc.EnumValue, err error) { - vs = make([]filedesc.EnumValue, len(vds)) // allocate up-front to ensure stable pointers - for i, vd := range vds { - v := &vs[i] - if v.L0, err = r.makeBase(v, parent, vd.GetName(), i, sb); err != nil { - return nil, err - } - if opts := vd.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.EnumValueOptions) - v.L1.Options = func() protoreflect.ProtoMessage { return opts } - } - v.L1.Number = protoreflect.EnumNumber(vd.GetNumber()) - } - return vs, nil -} - -func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Message, err error) { - ms = make([]filedesc.Message, len(mds)) // allocate up-front to ensure stable pointers - for i, md := range mds { - m := &ms[i] - m.L2 = new(filedesc.MessageL2) - if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil { - return nil, err - } - m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures()) - m.L1.Visibility = int32(md.GetVisibility()) - if opts := md.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.MessageOptions) - m.L2.Options = func() protoreflect.ProtoMessage { return opts } - m.L1.IsMapEntry = opts.GetMapEntry() - m.L1.IsMessageSet = opts.GetMessageSetWireFormat() - } - for _, s := range md.GetReservedName() { - m.L2.ReservedNames.List = append(m.L2.ReservedNames.List, protoreflect.Name(s)) - } - for _, rr := range md.GetReservedRange() { - m.L2.ReservedRanges.List = append(m.L2.ReservedRanges.List, [2]protoreflect.FieldNumber{ - protoreflect.FieldNumber(rr.GetStart()), - protoreflect.FieldNumber(rr.GetEnd()), - }) - } - for _, xr := range md.GetExtensionRange() { - m.L2.ExtensionRanges.List = append(m.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{ - protoreflect.FieldNumber(xr.GetStart()), - protoreflect.FieldNumber(xr.GetEnd()), - }) - var optsFunc func() protoreflect.ProtoMessage - if opts := xr.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.ExtensionRangeOptions) - optsFunc = func() protoreflect.ProtoMessage { return opts } - } - m.L2.ExtensionRangeOptions = append(m.L2.ExtensionRangeOptions, optsFunc) - } - if m.L2.Fields.List, err = r.initFieldsFromDescriptorProto(md.GetField(), m, sb); err != nil { - return nil, err - } - if m.L2.Oneofs.List, err = r.initOneofsFromDescriptorProto(md.GetOneofDecl(), m, sb); err != nil { - return nil, err - } - if m.L1.Enums.List, err = r.initEnumDeclarations(md.GetEnumType(), m, sb); err != nil { - return nil, err - } - if m.L1.Messages.List, err = r.initMessagesDeclarations(md.GetNestedType(), m, sb); err != nil { - return nil, err - } - if m.L1.Extensions.List, err = r.initExtensionDeclarations(md.GetExtension(), m, sb); err != nil { - return nil, err - } - } - return ms, nil -} - -// canBePacked returns whether the field can use packed encoding: -// https://protobuf.dev/programming-guides/encoding/#packed -func canBePacked(fd *descriptorpb.FieldDescriptorProto) bool { - if fd.GetLabel() != descriptorpb.FieldDescriptorProto_LABEL_REPEATED { - return false // not a repeated field - } - - switch protoreflect.Kind(fd.GetType()) { - case protoreflect.MessageKind, protoreflect.GroupKind: - return false // not a scalar type field - - case protoreflect.StringKind, protoreflect.BytesKind: - // string and bytes can explicitly not be declared as packed, - // see https://protobuf.dev/programming-guides/encoding/#packed - return false - - default: - return true - } -} - -func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) { - fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers - for i, fd := range fds { - f := &fs[i] - if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil { - return nil, err - } - f.L1.EditionFeatures = mergeEditionFeatures(parent, fd.GetOptions().GetFeatures()) - f.L1.IsProto3Optional = fd.GetProto3Optional() - if opts := fd.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.FieldOptions) - f.L1.Options = func() protoreflect.ProtoMessage { return opts } - f.L1.IsLazy = opts.GetLazy() - if opts.Packed != nil { - f.L1.EditionFeatures.IsPacked = opts.GetPacked() - } - } - f.L1.Number = protoreflect.FieldNumber(fd.GetNumber()) - f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel()) - if fd.Type != nil { - f.L1.Kind = protoreflect.Kind(fd.GetType()) - } - if fd.JsonName != nil { - f.L1.StringName.InitJSON(fd.GetJsonName()) - } - - if f.L1.EditionFeatures.IsLegacyRequired { - f.L1.Cardinality = protoreflect.Required - } - - if f.L1.Kind == protoreflect.MessageKind && f.L1.EditionFeatures.IsDelimitedEncoded { - f.L1.Kind = protoreflect.GroupKind - } - } - return fs, nil -} - -func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) { - os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers - for i, od := range ods { - o := &os[i] - if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil { - return nil, err - } - o.L1.EditionFeatures = mergeEditionFeatures(parent, od.GetOptions().GetFeatures()) - if opts := od.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.OneofOptions) - o.L1.Options = func() protoreflect.ProtoMessage { return opts } - } - } - return os, nil -} - -func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) { - xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers - for i, xd := range xds { - x := &xs[i] - x.L2 = new(filedesc.ExtensionL2) - if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil { - return nil, err - } - x.L1.EditionFeatures = mergeEditionFeatures(parent, xd.GetOptions().GetFeatures()) - if opts := xd.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.FieldOptions) - x.L2.Options = func() protoreflect.ProtoMessage { return opts } - if opts.Packed != nil { - x.L1.EditionFeatures.IsPacked = opts.GetPacked() - } - } - x.L1.Number = protoreflect.FieldNumber(xd.GetNumber()) - x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel()) - if xd.Type != nil { - x.L1.Kind = protoreflect.Kind(xd.GetType()) - } - if xd.JsonName != nil { - x.L2.StringName.InitJSON(xd.GetJsonName()) - } - if x.L1.Kind == protoreflect.MessageKind && x.L1.EditionFeatures.IsDelimitedEncoded { - x.L1.Kind = protoreflect.GroupKind - } - } - return xs, nil -} - -func (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) { - ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers - for i, sd := range sds { - s := &ss[i] - s.L2 = new(filedesc.ServiceL2) - if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil { - return nil, err - } - if opts := sd.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.ServiceOptions) - s.L2.Options = func() protoreflect.ProtoMessage { return opts } - } - if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil { - return nil, err - } - } - return ss, nil -} - -func (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) { - ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers - for i, md := range mds { - m := &ms[i] - if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil { - return nil, err - } - if opts := md.GetOptions(); opts != nil { - opts = proto.Clone(opts).(*descriptorpb.MethodOptions) - m.L1.Options = func() protoreflect.ProtoMessage { return opts } - } - m.L1.IsStreamingClient = md.GetClientStreaming() - m.L1.IsStreamingServer = md.GetServerStreaming() - } - return ms, nil -} - -func (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) { - if !protoreflect.Name(name).IsValid() { - return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name) - } - - // Derive the full name of the child. - // Note that enum values are a sibling to the enum parent in the namespace. - var fullName protoreflect.FullName - if _, ok := parent.(protoreflect.EnumDescriptor); ok { - fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name)) - } else { - fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name)) - } - if _, ok := r[fullName]; ok { - return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName) - } - r[fullName] = child - - // TODO: Verify that the full name does not already exist in the resolver? - // This is not as critical since most usages of NewFile will register - // the created file back into the registry, which will perform this check. - - return filedesc.BaseL0{ - FullName: fullName, - ParentFile: parent.ParentFile().(*filedesc.File), - Parent: parent, - Index: idx, - }, nil -} diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go deleted file mode 100644 index ff692436..00000000 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package protodesc - -import ( - "google.golang.org/protobuf/internal/encoding/defval" - "google.golang.org/protobuf/internal/errors" - "google.golang.org/protobuf/internal/filedesc" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - - "google.golang.org/protobuf/types/descriptorpb" -) - -// resolver is a wrapper around a local registry of declarations within the file -// and the remote resolver. The remote resolver is restricted to only return -// descriptors that have been imported. -type resolver struct { - local descsByName - remote Resolver - imports importSet - - allowUnresolvable bool -} - -func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) (err error) { - for i, md := range mds { - m := &ms[i] - for j, fd := range md.GetField() { - f := &m.L2.Fields.List[j] - if f.L1.Cardinality == protoreflect.Required { - m.L2.RequiredNumbers.List = append(m.L2.RequiredNumbers.List, f.L1.Number) - } - if fd.OneofIndex != nil { - k := int(fd.GetOneofIndex()) - if !(0 <= k && k < len(md.GetOneofDecl())) { - return errors.New("message field %q has an invalid oneof index: %d", f.FullName(), k) - } - o := &m.L2.Oneofs.List[k] - f.L1.ContainingOneof = o - o.L1.Fields.List = append(o.L1.Fields.List, f) - } - - if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName())); err != nil { - return errors.New("message field %q cannot resolve type: %v", f.FullName(), err) - } - if f.L1.Kind == protoreflect.GroupKind && (f.IsMap() || f.IsMapEntry()) { - // A map field might inherit delimited encoding from a file-wide default feature. - // But maps never actually use delimited encoding. (At least for now...) - f.L1.Kind = protoreflect.MessageKind - } - if fd.DefaultValue != nil { - v, ev, err := unmarshalDefault(fd.GetDefaultValue(), f, r.allowUnresolvable) - if err != nil { - return errors.New("message field %q has invalid default: %v", f.FullName(), err) - } - f.L1.Default = filedesc.DefaultValue(v, ev) - } - } - - if err := r.resolveMessageDependencies(m.L1.Messages.List, md.GetNestedType()); err != nil { - return err - } - if err := r.resolveExtensionDependencies(m.L1.Extensions.List, md.GetExtension()); err != nil { - return err - } - } - return nil -} - -func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) { - for i, xd := range xds { - x := &xs[i] - if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee())); err != nil { - return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err) - } - if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName())); err != nil { - return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err) - } - if xd.DefaultValue != nil { - v, ev, err := unmarshalDefault(xd.GetDefaultValue(), x, r.allowUnresolvable) - if err != nil { - return errors.New("extension field %q has invalid default: %v", x.FullName(), err) - } - x.L2.Default = filedesc.DefaultValue(v, ev) - } - } - return nil -} - -func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*descriptorpb.ServiceDescriptorProto) (err error) { - for i, sd := range sds { - s := &ss[i] - for j, md := range sd.GetMethod() { - m := &s.L2.Methods.List[j] - m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType())) - if err != nil { - return errors.New("service method %q cannot resolve input: %v", m.FullName(), err) - } - m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType())) - if err != nil { - return errors.New("service method %q cannot resolve output: %v", m.FullName(), err) - } - } - } - return nil -} - -// findTarget finds an enum or message descriptor if k is an enum, message, -// group, or unknown. If unknown, and the name could be resolved, the kind -// returned kind is set based on the type of the resolved descriptor. -func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) { - switch k { - case protoreflect.EnumKind: - ed, err := r.findEnumDescriptor(scope, ref) - if err != nil { - return 0, nil, nil, err - } - return k, ed, nil, nil - case protoreflect.MessageKind, protoreflect.GroupKind: - md, err := r.findMessageDescriptor(scope, ref) - if err != nil { - return 0, nil, nil, err - } - return k, nil, md, nil - case 0: - // Handle unspecified kinds (possible with parsers that operate - // on a per-file basis without knowledge of dependencies). - d, err := r.findDescriptor(scope, ref) - if err == protoregistry.NotFound && r.allowUnresolvable { - return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil - } else if err == protoregistry.NotFound { - return 0, nil, nil, errors.New("%q not found", ref.FullName()) - } else if err != nil { - return 0, nil, nil, err - } - switch d := d.(type) { - case protoreflect.EnumDescriptor: - return protoreflect.EnumKind, d, nil, nil - case protoreflect.MessageDescriptor: - return protoreflect.MessageKind, nil, d, nil - default: - return 0, nil, nil, errors.New("unknown kind") - } - default: - if ref != "" { - return 0, nil, nil, errors.New("target name cannot be specified for %v", k) - } - if !k.IsValid() { - return 0, nil, nil, errors.New("invalid kind: %d", k) - } - return k, nil, nil, nil - } -} - -// findDescriptor finds the descriptor by name, -// which may be a relative name within some scope. -// -// Suppose the scope was "fizz.buzz" and the reference was "Foo.Bar", -// then the following full names are searched: -// - fizz.buzz.Foo.Bar -// - fizz.Foo.Bar -// - Foo.Bar -func (r *resolver) findDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.Descriptor, error) { - if !ref.IsValid() { - return nil, errors.New("invalid name reference: %q", ref) - } - if ref.IsFull() { - scope, ref = "", ref[1:] - } - var foundButNotImported protoreflect.Descriptor - for { - // Derive the full name to search. - s := protoreflect.FullName(ref) - if scope != "" { - s = scope + "." + s - } - - // Check the current file for the descriptor. - if d, ok := r.local[s]; ok { - return d, nil - } - - // Check the remote registry for the descriptor. - d, err := r.remote.FindDescriptorByName(s) - if err == nil { - // Only allow descriptors covered by one of the imports. - if r.imports[d.ParentFile().Path()] { - return d, nil - } - foundButNotImported = d - } else if err != protoregistry.NotFound { - return nil, errors.Wrap(err, "%q", s) - } - - // Continue on at a higher level of scoping. - if scope == "" { - if d := foundButNotImported; d != nil { - return nil, errors.New("resolved %q, but %q is not imported", d.FullName(), d.ParentFile().Path()) - } - return nil, protoregistry.NotFound - } - scope = scope.Parent() - } -} - -func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.EnumDescriptor, error) { - d, err := r.findDescriptor(scope, ref) - if err == protoregistry.NotFound && r.allowUnresolvable { - return filedesc.PlaceholderEnum(ref.FullName()), nil - } else if err == protoregistry.NotFound { - return nil, errors.New("%q not found", ref.FullName()) - } else if err != nil { - return nil, err - } - ed, ok := d.(protoreflect.EnumDescriptor) - if !ok { - return nil, errors.New("resolved %q, but it is not an enum", d.FullName()) - } - return ed, nil -} - -func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.MessageDescriptor, error) { - d, err := r.findDescriptor(scope, ref) - if err == protoregistry.NotFound && r.allowUnresolvable { - return filedesc.PlaceholderMessage(ref.FullName()), nil - } else if err == protoregistry.NotFound { - return nil, errors.New("%q not found", ref.FullName()) - } else if err != nil { - return nil, err - } - md, ok := d.(protoreflect.MessageDescriptor) - if !ok { - return nil, errors.New("resolved %q, but it is not an message", d.FullName()) - } - return md, nil -} - -// partialName is the partial name. A leading dot means that the name is full, -// otherwise the name is relative to some current scope. -// See google.protobuf.FieldDescriptorProto.type_name. -type partialName string - -func (s partialName) IsFull() bool { - return len(s) > 0 && s[0] == '.' -} - -func (s partialName) IsValid() bool { - if s.IsFull() { - return protoreflect.FullName(s[1:]).IsValid() - } - return protoreflect.FullName(s).IsValid() -} - -const unknownPrefix = "*." - -// FullName converts the partial name to a full name on a best-effort basis. -// If relative, it creates an invalid full name, using a "*." prefix -// to indicate that the start of the full name is unknown. -func (s partialName) FullName() protoreflect.FullName { - if s.IsFull() { - return protoreflect.FullName(s[1:]) - } - return protoreflect.FullName(unknownPrefix + s) -} - -func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvable bool) (protoreflect.Value, protoreflect.EnumValueDescriptor, error) { - var evs protoreflect.EnumValueDescriptors - if fd.Enum() != nil { - evs = fd.Enum().Values() - } - v, ev, err := defval.Unmarshal(s, fd.Kind(), evs, defval.Descriptor) - if err != nil && allowUnresolvable && evs != nil && protoreflect.Name(s).IsValid() { - v = protoreflect.ValueOfEnum(0) - if evs.Len() > 0 { - v = protoreflect.ValueOfEnum(evs.Get(0).Number()) - } - ev = filedesc.PlaceholderEnumValue(fd.Enum().FullName().Parent().Append(protoreflect.Name(s))) - } else if err != nil { - return v, ev, err - } - if !fd.HasPresence() { - return v, ev, errors.New("cannot be specified with implicit field presence") - } - if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated { - return v, ev, errors.New("cannot be specified on composite types") - } - return v, ev, nil -} diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go deleted file mode 100644 index c343d922..00000000 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package protodesc - -import ( - "strings" - "unicode" - - "google.golang.org/protobuf/encoding/protowire" - "google.golang.org/protobuf/internal/errors" - "google.golang.org/protobuf/internal/filedesc" - "google.golang.org/protobuf/internal/flags" - "google.golang.org/protobuf/internal/genid" - "google.golang.org/protobuf/internal/strs" - "google.golang.org/protobuf/reflect/protoreflect" - - "google.golang.org/protobuf/types/descriptorpb" -) - -func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescriptorProto) error { - for i, ed := range eds { - e := &es[i] - if err := e.L2.ReservedNames.CheckValid(); err != nil { - return errors.New("enum %q reserved names has %v", e.FullName(), err) - } - if err := e.L2.ReservedRanges.CheckValid(); err != nil { - return errors.New("enum %q reserved ranges has %v", e.FullName(), err) - } - if len(ed.GetValue()) == 0 { - return errors.New("enum %q must contain at least one value declaration", e.FullName()) - } - allowAlias := ed.GetOptions().GetAllowAlias() - foundAlias := false - for i := 0; i < e.Values().Len(); i++ { - v1 := e.Values().Get(i) - if v2 := e.Values().ByNumber(v1.Number()); v1 != v2 { - foundAlias = true - if !allowAlias { - return errors.New("enum %q has conflicting non-aliased values on number %d: %q with %q", e.FullName(), v1.Number(), v1.Name(), v2.Name()) - } - } - } - if allowAlias && !foundAlias { - return errors.New("enum %q allows aliases, but none were found", e.FullName()) - } - if !e.IsClosed() { - if v := e.Values().Get(0); v.Number() != 0 { - return errors.New("enum %q using open semantics must have zero number for the first value", v.FullName()) - } - // Verify that value names in open enums do not conflict if the - // case-insensitive prefix is removed. - // See protoc v3.8.0: src/google/protobuf/descriptor.cc:4991-5055 - names := map[string]protoreflect.EnumValueDescriptor{} - prefix := strings.Replace(strings.ToLower(string(e.Name())), "_", "", -1) - for i := 0; i < e.Values().Len(); i++ { - v1 := e.Values().Get(i) - s := strs.EnumValueName(strs.TrimEnumPrefix(string(v1.Name()), prefix)) - if v2, ok := names[s]; ok && v1.Number() != v2.Number() { - return errors.New("enum %q using open semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name()) - } - names[s] = v1 - } - } - - for j, vd := range ed.GetValue() { - v := &e.L2.Values.List[j] - if vd.Number == nil { - return errors.New("enum value %q must have a specified number", v.FullName()) - } - if e.L2.ReservedNames.Has(v.Name()) { - return errors.New("enum value %q must not use reserved name", v.FullName()) - } - if e.L2.ReservedRanges.Has(v.Number()) { - return errors.New("enum value %q must not use reserved number %d", v.FullName(), v.Number()) - } - } - } - return nil -} - -func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error { - // There are a few limited exceptions only for proto3 - isProto3 := file.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3) - for i, md := range mds { - m := &ms[i] - - // Handle the message descriptor itself. - isMessageSet := md.GetOptions().GetMessageSetWireFormat() - if err := m.L2.ReservedNames.CheckValid(); err != nil { - return errors.New("message %q reserved names has %v", m.FullName(), err) - } - if err := m.L2.ReservedRanges.CheckValid(isMessageSet); err != nil { - return errors.New("message %q reserved ranges has %v", m.FullName(), err) - } - if err := m.L2.ExtensionRanges.CheckValid(isMessageSet); err != nil { - return errors.New("message %q extension ranges has %v", m.FullName(), err) - } - if err := (*filedesc.FieldRanges).CheckOverlap(&m.L2.ReservedRanges, &m.L2.ExtensionRanges); err != nil { - return errors.New("message %q reserved and extension ranges has %v", m.FullName(), err) - } - for i := 0; i < m.Fields().Len(); i++ { - f1 := m.Fields().Get(i) - if f2 := m.Fields().ByNumber(f1.Number()); f1 != f2 { - return errors.New("message %q has conflicting fields: %q with %q", m.FullName(), f1.Name(), f2.Name()) - } - } - if isMessageSet && !flags.ProtoLegacy { - return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName()) - } - if isMessageSet && (isProto3 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) { - return errors.New("message %q is an invalid proto1 MessageSet", m.FullName()) - } - if isProto3 { - if m.ExtensionRanges().Len() > 0 { - return errors.New("message %q using proto3 semantics cannot have extension ranges", m.FullName()) - } - } - - for j, fd := range md.GetField() { - f := &m.L2.Fields.List[j] - if m.L2.ReservedNames.Has(f.Name()) { - return errors.New("message field %q must not use reserved name", f.FullName()) - } - if !f.Number().IsValid() { - return errors.New("message field %q has an invalid number: %d", f.FullName(), f.Number()) - } - if !f.Cardinality().IsValid() { - return errors.New("message field %q has an invalid cardinality: %d", f.FullName(), f.Cardinality()) - } - if m.L2.ReservedRanges.Has(f.Number()) { - return errors.New("message field %q must not use reserved number %d", f.FullName(), f.Number()) - } - if m.L2.ExtensionRanges.Has(f.Number()) { - return errors.New("message field %q with number %d in extension range", f.FullName(), f.Number()) - } - if fd.Extendee != nil { - return errors.New("message field %q may not have extendee: %q", f.FullName(), fd.GetExtendee()) - } - if f.L1.IsProto3Optional { - if !isProto3 { - return errors.New("message field %q under proto3 optional semantics must be specified in the proto3 syntax", f.FullName()) - } - if f.Cardinality() != protoreflect.Optional { - return errors.New("message field %q under proto3 optional semantics must have optional cardinality", f.FullName()) - } - if f.ContainingOneof() != nil && f.ContainingOneof().Fields().Len() != 1 { - return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName()) - } - } - if f.IsPacked() && !isPackable(f) { - return errors.New("message field %q is not packable", f.FullName()) - } - if err := checkValidGroup(file, f); err != nil { - return errors.New("message field %q is an invalid group: %v", f.FullName(), err) - } - if err := checkValidMap(f); err != nil { - return errors.New("message field %q is an invalid map: %v", f.FullName(), err) - } - if isProto3 { - if f.Cardinality() == protoreflect.Required { - return errors.New("message field %q using proto3 semantics cannot be required", f.FullName()) - } - if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().IsClosed() { - return errors.New("message field %q using proto3 semantics may only depend on open enums", f.FullName()) - } - } - if f.Cardinality() == protoreflect.Optional && !f.HasPresence() && f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().IsClosed() { - return errors.New("message field %q with implicit presence may only use open enums", f.FullName()) - } - } - seenSynthetic := false // synthetic oneofs for proto3 optional must come after real oneofs - for j := range md.GetOneofDecl() { - o := &m.L2.Oneofs.List[j] - if o.Fields().Len() == 0 { - return errors.New("message oneof %q must contain at least one field declaration", o.FullName()) - } - if n := o.Fields().Len(); n-1 != (o.Fields().Get(n-1).Index() - o.Fields().Get(0).Index()) { - return errors.New("message oneof %q must have consecutively declared fields", o.FullName()) - } - - if o.IsSynthetic() { - seenSynthetic = true - continue - } - if !o.IsSynthetic() && seenSynthetic { - return errors.New("message oneof %q must be declared before synthetic oneofs", o.FullName()) - } - - for i := 0; i < o.Fields().Len(); i++ { - f := o.Fields().Get(i) - if f.Cardinality() != protoreflect.Optional { - return errors.New("message field %q belongs in a oneof and must be optional", f.FullName()) - } - } - } - - if err := validateEnumDeclarations(m.L1.Enums.List, md.GetEnumType()); err != nil { - return err - } - if err := validateMessageDeclarations(file, m.L1.Messages.List, md.GetNestedType()); err != nil { - return err - } - if err := validateExtensionDeclarations(file, m.L1.Extensions.List, md.GetExtension()); err != nil { - return err - } - } - return nil -} - -func validateExtensionDeclarations(f *filedesc.File, xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error { - for i, xd := range xds { - x := &xs[i] - // NOTE: Avoid using the IsValid method since extensions to MessageSet - // may have a field number higher than normal. This check only verifies - // that the number is not negative or reserved. We check again later - // if we know that the extendee is definitely not a MessageSet. - if n := x.Number(); n < 0 || (protowire.FirstReservedNumber <= n && n <= protowire.LastReservedNumber) { - return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number()) - } - if !x.Cardinality().IsValid() || x.Cardinality() == protoreflect.Required { - return errors.New("extension field %q has an invalid cardinality: %d", x.FullName(), x.Cardinality()) - } - if xd.JsonName != nil { - // A bug in older versions of protoc would always populate the - // "json_name" option for extensions when it is meaningless. - // When it did so, it would always use the camel-cased field name. - if xd.GetJsonName() != strs.JSONCamelCase(string(x.Name())) { - return errors.New("extension field %q may not have an explicitly set JSON name: %q", x.FullName(), xd.GetJsonName()) - } - } - if xd.OneofIndex != nil { - return errors.New("extension field %q may not be part of a oneof", x.FullName()) - } - if md := x.ContainingMessage(); !md.IsPlaceholder() { - if !md.ExtensionRanges().Has(x.Number()) { - return errors.New("extension field %q extends %q with non-extension field number: %d", x.FullName(), md.FullName(), x.Number()) - } - isMessageSet := md.Options().(*descriptorpb.MessageOptions).GetMessageSetWireFormat() - if isMessageSet && !isOptionalMessage(x) { - return errors.New("extension field %q extends MessageSet and must be an optional message", x.FullName()) - } - if !isMessageSet && !x.Number().IsValid() { - return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number()) - } - } - if x.IsPacked() && !isPackable(x) { - return errors.New("extension field %q is not packable", x.FullName()) - } - if err := checkValidGroup(f, x); err != nil { - return errors.New("extension field %q is an invalid group: %v", x.FullName(), err) - } - if md := x.Message(); md != nil && md.IsMapEntry() { - return errors.New("extension field %q cannot be a map entry", x.FullName()) - } - if f.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3) { - switch x.ContainingMessage().FullName() { - case (*descriptorpb.FileOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.EnumOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.EnumValueOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.MessageOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.FieldOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.OneofOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.ExtensionRangeOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.ServiceOptions)(nil).ProtoReflect().Descriptor().FullName(): - case (*descriptorpb.MethodOptions)(nil).ProtoReflect().Descriptor().FullName(): - default: - return errors.New("extension field %q cannot be declared in proto3 unless extended descriptor options", x.FullName()) - } - } - } - return nil -} - -// isOptionalMessage reports whether this is an optional message. -// If the kind is unknown, it is assumed to be a message. -func isOptionalMessage(fd protoreflect.FieldDescriptor) bool { - return (fd.Kind() == 0 || fd.Kind() == protoreflect.MessageKind) && fd.Cardinality() == protoreflect.Optional -} - -// isPackable checks whether the pack option can be specified. -func isPackable(fd protoreflect.FieldDescriptor) bool { - switch fd.Kind() { - case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind: - return false - } - return fd.IsList() -} - -// checkValidGroup reports whether fd is a valid group according to the same -// rules that protoc imposes. -func checkValidGroup(f *filedesc.File, fd protoreflect.FieldDescriptor) error { - md := fd.Message() - switch { - case fd.Kind() != protoreflect.GroupKind: - return nil - case f.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3): - return errors.New("invalid under proto3 semantics") - case md == nil || md.IsPlaceholder(): - return errors.New("message must be resolvable") - } - if f.L1.Edition < fromEditionProto(descriptorpb.Edition_EDITION_2023) { - switch { - case fd.FullName().Parent() != md.FullName().Parent(): - return errors.New("message and field must be declared in the same scope") - case !unicode.IsUpper(rune(md.Name()[0])): - return errors.New("message name must start with an uppercase") - case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))): - return errors.New("field name must be lowercased form of the message name") - } - } - return nil -} - -// checkValidMap checks whether the field is a valid map according to the same -// rules that protoc imposes. -// See protoc v3.8.0: src/google/protobuf/descriptor.cc:6045-6115 -func checkValidMap(fd protoreflect.FieldDescriptor) error { - md := fd.Message() - switch { - case md == nil || !md.IsMapEntry(): - return nil - case fd.FullName().Parent() != md.FullName().Parent(): - return errors.New("message and field must be declared in the same scope") - case md.Name() != protoreflect.Name(strs.MapEntryName(string(fd.Name()))): - return errors.New("incorrect implicit map entry name") - case fd.Cardinality() != protoreflect.Repeated: - return errors.New("field must be repeated") - case md.Fields().Len() != 2: - return errors.New("message must have exactly two fields") - case md.ExtensionRanges().Len() > 0: - return errors.New("message must not have any extension ranges") - case md.Enums().Len()+md.Messages().Len()+md.Extensions().Len() > 0: - return errors.New("message must not have any nested declarations") - } - kf := md.Fields().Get(0) - vf := md.Fields().Get(1) - switch { - case kf.Name() != genid.MapEntry_Key_field_name || kf.Number() != genid.MapEntry_Key_field_number || kf.Cardinality() != protoreflect.Optional || kf.ContainingOneof() != nil || kf.HasDefault(): - return errors.New("invalid key field") - case vf.Name() != genid.MapEntry_Value_field_name || vf.Number() != genid.MapEntry_Value_field_number || vf.Cardinality() != protoreflect.Optional || vf.ContainingOneof() != nil || vf.HasDefault(): - return errors.New("invalid value field") - } - switch kf.Kind() { - case protoreflect.BoolKind: // bool - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: // int32 - case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: // int64 - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: // uint32 - case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: // uint64 - case protoreflect.StringKind: // string - default: - return errors.New("invalid key kind: %v", kf.Kind()) - } - if e := vf.Enum(); e != nil && e.Values().Len() > 0 && e.Values().Get(0).Number() != 0 { - return errors.New("map enum value must have zero number for the first value") - } - return nil -} diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go deleted file mode 100644 index 697a61b2..00000000 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package protodesc - -import ( - "fmt" - "os" - "sync" - - "google.golang.org/protobuf/internal/editiondefaults" - "google.golang.org/protobuf/internal/filedesc" - "google.golang.org/protobuf/internal/genid" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/descriptorpb" - "google.golang.org/protobuf/types/gofeaturespb" -) - -var defaults = &descriptorpb.FeatureSetDefaults{} -var defaultsCacheMu sync.Mutex -var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet) - -func init() { - err := proto.Unmarshal(editiondefaults.Defaults, defaults) - if err != nil { - fmt.Fprintf(os.Stderr, "unmarshal editions defaults: %v\n", err) - os.Exit(1) - } -} - -func fromEditionProto(epb descriptorpb.Edition) filedesc.Edition { - return filedesc.Edition(epb) -} - -func toEditionProto(ed filedesc.Edition) descriptorpb.Edition { - switch ed { - case filedesc.EditionUnknown: - return descriptorpb.Edition_EDITION_UNKNOWN - case filedesc.EditionProto2: - return descriptorpb.Edition_EDITION_PROTO2 - case filedesc.EditionProto3: - return descriptorpb.Edition_EDITION_PROTO3 - case filedesc.Edition2023: - return descriptorpb.Edition_EDITION_2023 - case filedesc.Edition2024: - return descriptorpb.Edition_EDITION_2024 - default: - panic(fmt.Sprintf("unknown value for edition: %v", ed)) - } -} - -func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet { - defaultsCacheMu.Lock() - defer defaultsCacheMu.Unlock() - if def, ok := defaultsCache[ed]; ok { - return def - } - edpb := toEditionProto(ed) - if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb { - // This should never happen protodesc.(FileOptions).New would fail when - // initializing the file descriptor. - // This most likely means the embedded defaults were not updated. - fmt.Fprintf(os.Stderr, "internal error: unsupported edition %v (did you forget to update the embedded defaults (i.e. the bootstrap descriptor proto)?)\n", edpb) - os.Exit(1) - } - fsed := defaults.GetDefaults()[0] - // Using a linear search for now. - // Editions are guaranteed to be sorted and thus we could use a binary search. - // Given that there are only a handful of editions (with one more per year) - // there is not much reason to use a binary search. - for _, def := range defaults.GetDefaults() { - if def.GetEdition() <= edpb { - fsed = def - } else { - break - } - } - fs := proto.Clone(fsed.GetFixedFeatures()).(*descriptorpb.FeatureSet) - proto.Merge(fs, fsed.GetOverridableFeatures()) - defaultsCache[ed] = fs - return fs -} - -// mergeEditionFeatures merges the parent and child feature sets. This function -// should be used when initializing Go descriptors from descriptor protos which -// is why the parent is a filedesc.EditionsFeatures (Go representation) while -// the child is a descriptorproto.FeatureSet (protoc representation). -// Any feature set by the child overwrites what is set by the parent. -func mergeEditionFeatures(parentDesc protoreflect.Descriptor, child *descriptorpb.FeatureSet) filedesc.EditionFeatures { - var parentFS filedesc.EditionFeatures - switch p := parentDesc.(type) { - case *filedesc.File: - parentFS = p.L1.EditionFeatures - case *filedesc.Message: - parentFS = p.L1.EditionFeatures - default: - panic(fmt.Sprintf("unknown parent type %T", parentDesc)) - } - if child == nil { - return parentFS - } - if fp := child.FieldPresence; fp != nil { - parentFS.IsFieldPresence = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED || - *fp == descriptorpb.FeatureSet_EXPLICIT - parentFS.IsLegacyRequired = *fp == descriptorpb.FeatureSet_LEGACY_REQUIRED - } - if et := child.EnumType; et != nil { - parentFS.IsOpenEnum = *et == descriptorpb.FeatureSet_OPEN - } - - if rfe := child.RepeatedFieldEncoding; rfe != nil { - parentFS.IsPacked = *rfe == descriptorpb.FeatureSet_PACKED - } - - if utf8val := child.Utf8Validation; utf8val != nil { - parentFS.IsUTF8Validated = *utf8val == descriptorpb.FeatureSet_VERIFY - } - - if me := child.MessageEncoding; me != nil { - parentFS.IsDelimitedEncoded = *me == descriptorpb.FeatureSet_DELIMITED - } - - if jf := child.JsonFormat; jf != nil { - parentFS.IsJSONCompliant = *jf == descriptorpb.FeatureSet_ALLOW - } - - // 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. - // - // Further, we harden this code against adversarial inputs: a - // service which accepts descriptors from a possibly malicious - // source shouldn't crash. - goFeatures := child.ProtoReflect().Get(gofeaturespb.E_Go.TypeDescriptor()) - if !goFeatures.IsValid() { - return parentFS - } - gf, ok := goFeatures.Interface().(protoreflect.Message) - if !ok { - return parentFS - } - // gf.Interface() could be *dynamicpb.Message or *gofeaturespb.GoFeatures. - fields := gf.Descriptor().Fields() - - if fd := fields.ByNumber(genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number); fd != nil && - !fd.IsList() && - fd.Kind() == protoreflect.BoolKind && - gf.Has(fd) { - parentFS.GenerateLegacyUnmarshalJSON = gf.Get(fd).Bool() - } - - if fd := fields.ByNumber(genid.GoFeatures_StripEnumPrefix_field_number); fd != nil && - !fd.IsList() && - fd.Kind() == protoreflect.EnumKind && - gf.Has(fd) { - parentFS.StripEnumPrefix = int(gf.Get(fd).Enum()) - } - - if fd := fields.ByNumber(genid.GoFeatures_ApiLevel_field_number); fd != nil && - !fd.IsList() && - fd.Kind() == protoreflect.EnumKind && - gf.Has(fd) { - parentFS.APILevel = int(gf.Get(fd).Enum()) - } - - return parentFS -} - -// initFileDescFromFeatureSet initializes editions related fields in fd based -// on fs. If fs is nil it is assumed to be an empty featureset and all fields -// will be initialized with the appropriate default. fd.L1.Edition must be set -// before calling this function. -func initFileDescFromFeatureSet(fd *filedesc.File, fs *descriptorpb.FeatureSet) { - dfs := getFeatureSetFor(fd.L1.Edition) - // initialize the featureset with the defaults - fd.L1.EditionFeatures = mergeEditionFeatures(fd, dfs) - // overwrite any options explicitly specified - fd.L1.EditionFeatures = mergeEditionFeatures(fd, fs) -} diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go b/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go deleted file mode 100644 index 6f91074e..00000000 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package protodesc - -import ( - "fmt" - "strings" - - "google.golang.org/protobuf/internal/encoding/defval" - "google.golang.org/protobuf/internal/strs" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - - "google.golang.org/protobuf/types/descriptorpb" -) - -// ToFileDescriptorProto copies a [protoreflect.FileDescriptor] into a -// google.protobuf.FileDescriptorProto message. -func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto { - p := &descriptorpb.FileDescriptorProto{ - Name: proto.String(file.Path()), - Options: proto.Clone(file.Options()).(*descriptorpb.FileOptions), - } - if file.Package() != "" { - p.Package = proto.String(string(file.Package())) - } - for i, imports := 0, file.Imports(); i < imports.Len(); i++ { - imp := imports.Get(i) - p.Dependency = append(p.Dependency, imp.Path()) - if imp.IsPublic { - p.PublicDependency = append(p.PublicDependency, int32(i)) - } - } - for i, locs := 0, file.SourceLocations(); i < locs.Len(); i++ { - loc := locs.Get(i) - l := &descriptorpb.SourceCodeInfo_Location{} - l.Path = append(l.Path, loc.Path...) - if loc.StartLine == loc.EndLine { - l.Span = []int32{int32(loc.StartLine), int32(loc.StartColumn), int32(loc.EndColumn)} - } else { - l.Span = []int32{int32(loc.StartLine), int32(loc.StartColumn), int32(loc.EndLine), int32(loc.EndColumn)} - } - l.LeadingDetachedComments = append([]string(nil), loc.LeadingDetachedComments...) - if loc.LeadingComments != "" { - l.LeadingComments = proto.String(loc.LeadingComments) - } - if loc.TrailingComments != "" { - l.TrailingComments = proto.String(loc.TrailingComments) - } - if p.SourceCodeInfo == nil { - p.SourceCodeInfo = &descriptorpb.SourceCodeInfo{} - } - p.SourceCodeInfo.Location = append(p.SourceCodeInfo.Location, l) - - } - for i, messages := 0, file.Messages(); i < messages.Len(); i++ { - p.MessageType = append(p.MessageType, ToDescriptorProto(messages.Get(i))) - } - for i, enums := 0, file.Enums(); i < enums.Len(); i++ { - p.EnumType = append(p.EnumType, ToEnumDescriptorProto(enums.Get(i))) - } - for i, services := 0, file.Services(); i < services.Len(); i++ { - p.Service = append(p.Service, ToServiceDescriptorProto(services.Get(i))) - } - for i, exts := 0, file.Extensions(); i < exts.Len(); i++ { - p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i))) - } - if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() { - p.Syntax = proto.String(file.Syntax().String()) - } - desc := file - if fileImportDesc, ok := file.(protoreflect.FileImport); ok { - desc = fileImportDesc.FileDescriptor - } - if file.Syntax() == protoreflect.Editions { - if editionsInterface, ok := desc.(interface{ Edition() int32 }); ok { - p.Edition = descriptorpb.Edition(editionsInterface.Edition()).Enum() - } - } - type hasOptionImports interface { - OptionImports() protoreflect.FileImports - } - if opts, ok := desc.(hasOptionImports); ok { - if optionImports := opts.OptionImports(); optionImports.Len() > 0 { - optionDeps := make([]string, optionImports.Len()) - for i := range optionImports.Len() { - optionDeps[i] = optionImports.Get(i).Path() - } - p.OptionDependency = optionDeps - } - } - return p -} - -// ToDescriptorProto copies a [protoreflect.MessageDescriptor] into a -// google.protobuf.DescriptorProto message. -func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto { - p := &descriptorpb.DescriptorProto{ - Name: proto.String(string(message.Name())), - Options: proto.Clone(message.Options()).(*descriptorpb.MessageOptions), - } - for i, fields := 0, message.Fields(); i < fields.Len(); i++ { - p.Field = append(p.Field, ToFieldDescriptorProto(fields.Get(i))) - } - for i, exts := 0, message.Extensions(); i < exts.Len(); i++ { - p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i))) - } - for i, messages := 0, message.Messages(); i < messages.Len(); i++ { - p.NestedType = append(p.NestedType, ToDescriptorProto(messages.Get(i))) - } - for i, enums := 0, message.Enums(); i < enums.Len(); i++ { - p.EnumType = append(p.EnumType, ToEnumDescriptorProto(enums.Get(i))) - } - for i, xranges := 0, message.ExtensionRanges(); i < xranges.Len(); i++ { - xrange := xranges.Get(i) - p.ExtensionRange = append(p.ExtensionRange, &descriptorpb.DescriptorProto_ExtensionRange{ - Start: proto.Int32(int32(xrange[0])), - End: proto.Int32(int32(xrange[1])), - Options: proto.Clone(message.ExtensionRangeOptions(i)).(*descriptorpb.ExtensionRangeOptions), - }) - } - for i, oneofs := 0, message.Oneofs(); i < oneofs.Len(); i++ { - p.OneofDecl = append(p.OneofDecl, ToOneofDescriptorProto(oneofs.Get(i))) - } - for i, ranges := 0, message.ReservedRanges(); i < ranges.Len(); i++ { - rrange := ranges.Get(i) - p.ReservedRange = append(p.ReservedRange, &descriptorpb.DescriptorProto_ReservedRange{ - Start: proto.Int32(int32(rrange[0])), - End: proto.Int32(int32(rrange[1])), - }) - } - for i, names := 0, message.ReservedNames(); i < names.Len(); i++ { - p.ReservedName = append(p.ReservedName, string(names.Get(i))) - } - type hasVisibility interface { - Visibility() int32 - } - if vis, ok := message.(hasVisibility); ok { - if visibility := vis.Visibility(); visibility > 0 { - p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum() - } - } - return p -} - -// ToFieldDescriptorProto copies a [protoreflect.FieldDescriptor] into a -// google.protobuf.FieldDescriptorProto message. -func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto { - p := &descriptorpb.FieldDescriptorProto{ - Name: proto.String(string(field.Name())), - Number: proto.Int32(int32(field.Number())), - Label: descriptorpb.FieldDescriptorProto_Label(field.Cardinality()).Enum(), - Options: proto.Clone(field.Options()).(*descriptorpb.FieldOptions), - } - if field.IsExtension() { - p.Extendee = fullNameOf(field.ContainingMessage()) - } - if field.Kind().IsValid() { - p.Type = descriptorpb.FieldDescriptorProto_Type(field.Kind()).Enum() - } - if field.Enum() != nil { - p.TypeName = fullNameOf(field.Enum()) - } - if field.Message() != nil { - p.TypeName = fullNameOf(field.Message()) - } - if field.HasJSONName() { - // A bug in older versions of protoc would always populate the - // "json_name" option for extensions when it is meaningless. - // When it did so, it would always use the camel-cased field name. - if field.IsExtension() { - p.JsonName = proto.String(strs.JSONCamelCase(string(field.Name()))) - } else { - p.JsonName = proto.String(field.JSONName()) - } - } - if field.Syntax() == protoreflect.Proto3 && field.HasOptionalKeyword() { - p.Proto3Optional = proto.Bool(true) - } - if field.Syntax() == protoreflect.Editions { - // Editions have no group keyword, this type is only set so that downstream users continue - // treating this as delimited encoding. - if p.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP { - p.Type = descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum() - } - // Editions have no required keyword, this label is only set so that downstream users continue - // treating it as required. - if p.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REQUIRED { - p.Label = descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum() - } - } - if field.HasDefault() { - def, err := defval.Marshal(field.Default(), field.DefaultEnumValue(), field.Kind(), defval.Descriptor) - if err != nil && field.DefaultEnumValue() != nil { - def = string(field.DefaultEnumValue().Name()) // occurs for unresolved enum values - } else if err != nil { - panic(fmt.Sprintf("%v: %v", field.FullName(), err)) - } - p.DefaultValue = proto.String(def) - } - if oneof := field.ContainingOneof(); oneof != nil { - p.OneofIndex = proto.Int32(int32(oneof.Index())) - } - return p -} - -// ToOneofDescriptorProto copies a [protoreflect.OneofDescriptor] into a -// google.protobuf.OneofDescriptorProto message. -func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto { - return &descriptorpb.OneofDescriptorProto{ - Name: proto.String(string(oneof.Name())), - Options: proto.Clone(oneof.Options()).(*descriptorpb.OneofOptions), - } -} - -// ToEnumDescriptorProto copies a [protoreflect.EnumDescriptor] into a -// google.protobuf.EnumDescriptorProto message. -func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto { - p := &descriptorpb.EnumDescriptorProto{ - Name: proto.String(string(enum.Name())), - Options: proto.Clone(enum.Options()).(*descriptorpb.EnumOptions), - } - for i, values := 0, enum.Values(); i < values.Len(); i++ { - p.Value = append(p.Value, ToEnumValueDescriptorProto(values.Get(i))) - } - for i, ranges := 0, enum.ReservedRanges(); i < ranges.Len(); i++ { - rrange := ranges.Get(i) - p.ReservedRange = append(p.ReservedRange, &descriptorpb.EnumDescriptorProto_EnumReservedRange{ - Start: proto.Int32(int32(rrange[0])), - End: proto.Int32(int32(rrange[1])), - }) - } - for i, names := 0, enum.ReservedNames(); i < names.Len(); i++ { - p.ReservedName = append(p.ReservedName, string(names.Get(i))) - } - type hasVisibility interface { - Visibility() int32 - } - if vis, ok := enum.(hasVisibility); ok { - if visibility := vis.Visibility(); visibility > 0 { - p.Visibility = descriptorpb.SymbolVisibility(visibility).Enum() - } - } - return p -} - -// ToEnumValueDescriptorProto copies a [protoreflect.EnumValueDescriptor] into a -// google.protobuf.EnumValueDescriptorProto message. -func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto { - return &descriptorpb.EnumValueDescriptorProto{ - Name: proto.String(string(value.Name())), - Number: proto.Int32(int32(value.Number())), - Options: proto.Clone(value.Options()).(*descriptorpb.EnumValueOptions), - } -} - -// ToServiceDescriptorProto copies a [protoreflect.ServiceDescriptor] into a -// google.protobuf.ServiceDescriptorProto message. -func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto { - p := &descriptorpb.ServiceDescriptorProto{ - Name: proto.String(string(service.Name())), - Options: proto.Clone(service.Options()).(*descriptorpb.ServiceOptions), - } - for i, methods := 0, service.Methods(); i < methods.Len(); i++ { - p.Method = append(p.Method, ToMethodDescriptorProto(methods.Get(i))) - } - return p -} - -// ToMethodDescriptorProto copies a [protoreflect.MethodDescriptor] into a -// google.protobuf.MethodDescriptorProto message. -func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto { - p := &descriptorpb.MethodDescriptorProto{ - Name: proto.String(string(method.Name())), - InputType: fullNameOf(method.Input()), - OutputType: fullNameOf(method.Output()), - Options: proto.Clone(method.Options()).(*descriptorpb.MethodOptions), - } - if method.IsStreamingClient() { - p.ClientStreaming = proto.Bool(true) - } - if method.IsStreamingServer() { - p.ServerStreaming = proto.Bool(true) - } - return p -} - -func fullNameOf(d protoreflect.Descriptor) *string { - if d == nil { - return nil - } - if strings.HasPrefix(string(d.FullName()), unknownPrefix) { - return proto.String(string(d.FullName()[len(unknownPrefix):])) - } - return proto.String("." + string(d.FullName())) -} diff --git a/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go b/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go deleted file mode 100644 index 37e712b6..00000000 --- a/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go +++ /dev/null @@ -1,311 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2023 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google/protobuf/go_features.proto - -package gofeaturespb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - descriptorpb "google.golang.org/protobuf/types/descriptorpb" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -type GoFeatures_APILevel int32 - -const ( - // API_LEVEL_UNSPECIFIED results in selecting the OPEN API, - // but needs to be a separate value to distinguish between - // an explicitly set api level or a missing api level. - GoFeatures_API_LEVEL_UNSPECIFIED GoFeatures_APILevel = 0 - GoFeatures_API_OPEN GoFeatures_APILevel = 1 - GoFeatures_API_HYBRID GoFeatures_APILevel = 2 - GoFeatures_API_OPAQUE GoFeatures_APILevel = 3 -) - -// Enum value maps for GoFeatures_APILevel. -var ( - GoFeatures_APILevel_name = map[int32]string{ - 0: "API_LEVEL_UNSPECIFIED", - 1: "API_OPEN", - 2: "API_HYBRID", - 3: "API_OPAQUE", - } - GoFeatures_APILevel_value = map[string]int32{ - "API_LEVEL_UNSPECIFIED": 0, - "API_OPEN": 1, - "API_HYBRID": 2, - "API_OPAQUE": 3, - } -) - -func (x GoFeatures_APILevel) Enum() *GoFeatures_APILevel { - p := new(GoFeatures_APILevel) - *p = x - return p -} - -func (x GoFeatures_APILevel) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GoFeatures_APILevel) Descriptor() protoreflect.EnumDescriptor { - return file_google_protobuf_go_features_proto_enumTypes[0].Descriptor() -} - -func (GoFeatures_APILevel) Type() protoreflect.EnumType { - return &file_google_protobuf_go_features_proto_enumTypes[0] -} - -func (x GoFeatures_APILevel) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *GoFeatures_APILevel) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = GoFeatures_APILevel(num) - return nil -} - -// Deprecated: Use GoFeatures_APILevel.Descriptor instead. -func (GoFeatures_APILevel) EnumDescriptor() ([]byte, []int) { - return file_google_protobuf_go_features_proto_rawDescGZIP(), []int{0, 0} -} - -type GoFeatures_StripEnumPrefix int32 - -const ( - GoFeatures_STRIP_ENUM_PREFIX_UNSPECIFIED GoFeatures_StripEnumPrefix = 0 - GoFeatures_STRIP_ENUM_PREFIX_KEEP GoFeatures_StripEnumPrefix = 1 - GoFeatures_STRIP_ENUM_PREFIX_GENERATE_BOTH GoFeatures_StripEnumPrefix = 2 - GoFeatures_STRIP_ENUM_PREFIX_STRIP GoFeatures_StripEnumPrefix = 3 -) - -// Enum value maps for GoFeatures_StripEnumPrefix. -var ( - GoFeatures_StripEnumPrefix_name = map[int32]string{ - 0: "STRIP_ENUM_PREFIX_UNSPECIFIED", - 1: "STRIP_ENUM_PREFIX_KEEP", - 2: "STRIP_ENUM_PREFIX_GENERATE_BOTH", - 3: "STRIP_ENUM_PREFIX_STRIP", - } - GoFeatures_StripEnumPrefix_value = map[string]int32{ - "STRIP_ENUM_PREFIX_UNSPECIFIED": 0, - "STRIP_ENUM_PREFIX_KEEP": 1, - "STRIP_ENUM_PREFIX_GENERATE_BOTH": 2, - "STRIP_ENUM_PREFIX_STRIP": 3, - } -) - -func (x GoFeatures_StripEnumPrefix) Enum() *GoFeatures_StripEnumPrefix { - p := new(GoFeatures_StripEnumPrefix) - *p = x - return p -} - -func (x GoFeatures_StripEnumPrefix) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GoFeatures_StripEnumPrefix) Descriptor() protoreflect.EnumDescriptor { - return file_google_protobuf_go_features_proto_enumTypes[1].Descriptor() -} - -func (GoFeatures_StripEnumPrefix) Type() protoreflect.EnumType { - return &file_google_protobuf_go_features_proto_enumTypes[1] -} - -func (x GoFeatures_StripEnumPrefix) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *GoFeatures_StripEnumPrefix) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = GoFeatures_StripEnumPrefix(num) - return nil -} - -// Deprecated: Use GoFeatures_StripEnumPrefix.Descriptor instead. -func (GoFeatures_StripEnumPrefix) EnumDescriptor() ([]byte, []int) { - return file_google_protobuf_go_features_proto_rawDescGZIP(), []int{0, 1} -} - -type GoFeatures struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Whether or not to generate the deprecated UnmarshalJSON method for enums. - // Can only be true for proto using the Open Struct api. - LegacyUnmarshalJsonEnum *bool `protobuf:"varint,1,opt,name=legacy_unmarshal_json_enum,json=legacyUnmarshalJsonEnum" json:"legacy_unmarshal_json_enum,omitempty"` - // One of OPEN, HYBRID or OPAQUE. - ApiLevel *GoFeatures_APILevel `protobuf:"varint,2,opt,name=api_level,json=apiLevel,enum=pb.GoFeatures_APILevel" json:"api_level,omitempty"` - StripEnumPrefix *GoFeatures_StripEnumPrefix `protobuf:"varint,3,opt,name=strip_enum_prefix,json=stripEnumPrefix,enum=pb.GoFeatures_StripEnumPrefix" json:"strip_enum_prefix,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GoFeatures) Reset() { - *x = GoFeatures{} - mi := &file_google_protobuf_go_features_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GoFeatures) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GoFeatures) ProtoMessage() {} - -func (x *GoFeatures) ProtoReflect() protoreflect.Message { - mi := &file_google_protobuf_go_features_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GoFeatures.ProtoReflect.Descriptor instead. -func (*GoFeatures) Descriptor() ([]byte, []int) { - return file_google_protobuf_go_features_proto_rawDescGZIP(), []int{0} -} - -func (x *GoFeatures) GetLegacyUnmarshalJsonEnum() bool { - if x != nil && x.LegacyUnmarshalJsonEnum != nil { - return *x.LegacyUnmarshalJsonEnum - } - return false -} - -func (x *GoFeatures) GetApiLevel() GoFeatures_APILevel { - if x != nil && x.ApiLevel != nil { - return *x.ApiLevel - } - return GoFeatures_API_LEVEL_UNSPECIFIED -} - -func (x *GoFeatures) GetStripEnumPrefix() GoFeatures_StripEnumPrefix { - if x != nil && x.StripEnumPrefix != nil { - return *x.StripEnumPrefix - } - return GoFeatures_STRIP_ENUM_PREFIX_UNSPECIFIED -} - -var file_google_protobuf_go_features_proto_extTypes = []protoimpl.ExtensionInfo{ - { - ExtendedType: (*descriptorpb.FeatureSet)(nil), - ExtensionType: (*GoFeatures)(nil), - Field: 1002, - Name: "pb.go", - Tag: "bytes,1002,opt,name=go", - Filename: "google/protobuf/go_features.proto", - }, -} - -// Extension fields to descriptorpb.FeatureSet. -var ( - // optional pb.GoFeatures go = 1002; - E_Go = &file_google_protobuf_go_features_proto_extTypes[0] -) - -var File_google_protobuf_go_features_proto protoreflect.FileDescriptor - -const file_google_protobuf_go_features_proto_rawDesc = "" + - "\n" + - "!google/protobuf/go_features.proto\x12\x02pb\x1a google/protobuf/descriptor.proto\"\xab\x05\n" + - "\n" + - "GoFeatures\x12\xbe\x01\n" + - "\x1alegacy_unmarshal_json_enum\x18\x01 \x01(\bB\x80\x01\x88\x01\x01\x98\x01\x06\x98\x01\x01\xa2\x01\t\x12\x04true\x18\x84\a\xa2\x01\n" + - "\x12\x05false\x18\xe7\a\xb2\x01[\b\xe8\a\x10\xe8\a\x1aSThe legacy UnmarshalJSON API is deprecated and will be removed in a future edition.R\x17legacyUnmarshalJsonEnum\x12t\n" + - "\tapi_level\x18\x02 \x01(\x0e2\x17.pb.GoFeatures.APILevelB>\x88\x01\x01\x98\x01\x03\x98\x01\x01\xa2\x01\x1a\x12\x15API_LEVEL_UNSPECIFIED\x18\x84\a\xa2\x01\x0f\x12\n" + - "API_OPAQUE\x18\xe9\a\xb2\x01\x03\b\xe8\aR\bapiLevel\x12|\n" + - "\x11strip_enum_prefix\x18\x03 \x01(\x0e2\x1e.pb.GoFeatures.StripEnumPrefixB0\x88\x01\x01\x98\x01\x06\x98\x01\a\x98\x01\x01\xa2\x01\x1b\x12\x16STRIP_ENUM_PREFIX_KEEP\x18\x84\a\xb2\x01\x03\b\xe9\aR\x0fstripEnumPrefix\"S\n" + - "\bAPILevel\x12\x19\n" + - "\x15API_LEVEL_UNSPECIFIED\x10\x00\x12\f\n" + - "\bAPI_OPEN\x10\x01\x12\x0e\n" + - "\n" + - "API_HYBRID\x10\x02\x12\x0e\n" + - "\n" + - "API_OPAQUE\x10\x03\"\x92\x01\n" + - "\x0fStripEnumPrefix\x12!\n" + - "\x1dSTRIP_ENUM_PREFIX_UNSPECIFIED\x10\x00\x12\x1a\n" + - "\x16STRIP_ENUM_PREFIX_KEEP\x10\x01\x12#\n" + - "\x1fSTRIP_ENUM_PREFIX_GENERATE_BOTH\x10\x02\x12\x1b\n" + - "\x17STRIP_ENUM_PREFIX_STRIP\x10\x03:<\n" + - "\x02go\x12\x1b.google.protobuf.FeatureSet\x18\xea\a \x01(\v2\x0e.pb.GoFeaturesR\x02goB/Z-google.golang.org/protobuf/types/gofeaturespb" - -var ( - file_google_protobuf_go_features_proto_rawDescOnce sync.Once - file_google_protobuf_go_features_proto_rawDescData []byte -) - -func file_google_protobuf_go_features_proto_rawDescGZIP() []byte { - file_google_protobuf_go_features_proto_rawDescOnce.Do(func() { - file_google_protobuf_go_features_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_google_protobuf_go_features_proto_rawDesc), len(file_google_protobuf_go_features_proto_rawDesc))) - }) - return file_google_protobuf_go_features_proto_rawDescData -} - -var file_google_protobuf_go_features_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_google_protobuf_go_features_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_google_protobuf_go_features_proto_goTypes = []any{ - (GoFeatures_APILevel)(0), // 0: pb.GoFeatures.APILevel - (GoFeatures_StripEnumPrefix)(0), // 1: pb.GoFeatures.StripEnumPrefix - (*GoFeatures)(nil), // 2: pb.GoFeatures - (*descriptorpb.FeatureSet)(nil), // 3: google.protobuf.FeatureSet -} -var file_google_protobuf_go_features_proto_depIdxs = []int32{ - 0, // 0: pb.GoFeatures.api_level:type_name -> pb.GoFeatures.APILevel - 1, // 1: pb.GoFeatures.strip_enum_prefix:type_name -> pb.GoFeatures.StripEnumPrefix - 3, // 2: pb.go:extendee -> google.protobuf.FeatureSet - 2, // 3: pb.go:type_name -> pb.GoFeatures - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 3, // [3:4] is the sub-list for extension type_name - 2, // [2:3] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_google_protobuf_go_features_proto_init() } -func file_google_protobuf_go_features_proto_init() { - if File_google_protobuf_go_features_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_google_protobuf_go_features_proto_rawDesc), len(file_google_protobuf_go_features_proto_rawDesc)), - NumEnums: 2, - NumMessages: 1, - NumExtensions: 1, - NumServices: 0, - }, - GoTypes: file_google_protobuf_go_features_proto_goTypes, - DependencyIndexes: file_google_protobuf_go_features_proto_depIdxs, - EnumInfos: file_google_protobuf_go_features_proto_enumTypes, - MessageInfos: file_google_protobuf_go_features_proto_msgTypes, - ExtensionInfos: file_google_protobuf_go_features_proto_extTypes, - }.Build() - File_google_protobuf_go_features_proto = out.File - file_google_protobuf_go_features_proto_goTypes = nil - file_google_protobuf_go_features_proto_depIdxs = nil -} diff --git a/vendor/gopkg.in/yaml.v2/.travis.yml b/vendor/gopkg.in/yaml.v2/.travis.yml deleted file mode 100644 index 7348c50c..00000000 --- a/vendor/gopkg.in/yaml.v2/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: go - -go: - - "1.4.x" - - "1.5.x" - - "1.6.x" - - "1.7.x" - - "1.8.x" - - "1.9.x" - - "1.10.x" - - "1.11.x" - - "1.12.x" - - "1.13.x" - - "1.14.x" - - "tip" - -go_import_path: gopkg.in/yaml.v2 diff --git a/vendor/gopkg.in/yaml.v2/LICENSE b/vendor/gopkg.in/yaml.v2/LICENSE deleted file mode 100644 index 8dada3ed..00000000 --- a/vendor/gopkg.in/yaml.v2/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/gopkg.in/yaml.v2/LICENSE.libyaml b/vendor/gopkg.in/yaml.v2/LICENSE.libyaml deleted file mode 100644 index 8da58fbf..00000000 --- a/vendor/gopkg.in/yaml.v2/LICENSE.libyaml +++ /dev/null @@ -1,31 +0,0 @@ -The following files were ported to Go from C files of libyaml, and thus -are still covered by their original copyright and license: - - apic.go - emitterc.go - parserc.go - readerc.go - scannerc.go - writerc.go - yamlh.go - yamlprivateh.go - -Copyright (c) 2006 Kirill Simonov - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/gopkg.in/yaml.v2/NOTICE b/vendor/gopkg.in/yaml.v2/NOTICE deleted file mode 100644 index 866d74a7..00000000 --- a/vendor/gopkg.in/yaml.v2/NOTICE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2011-2016 Canonical Ltd. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/gopkg.in/yaml.v2/README.md b/vendor/gopkg.in/yaml.v2/README.md deleted file mode 100644 index b50c6e87..00000000 --- a/vendor/gopkg.in/yaml.v2/README.md +++ /dev/null @@ -1,133 +0,0 @@ -# YAML support for the Go language - -Introduction ------------- - -The yaml package enables Go programs to comfortably encode and decode YAML -values. It was developed within [Canonical](https://www.canonical.com) as -part of the [juju](https://juju.ubuntu.com) project, and is based on a -pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) -C library to parse and generate YAML data quickly and reliably. - -Compatibility -------------- - -The yaml package supports most of YAML 1.1 and 1.2, including support for -anchors, tags, map merging, etc. Multi-document unmarshalling is not yet -implemented, and base-60 floats from YAML 1.1 are purposefully not -supported since they're a poor design and are gone in YAML 1.2. - -Installation and usage ----------------------- - -The import path for the package is *gopkg.in/yaml.v2*. - -To install it, run: - - go get gopkg.in/yaml.v2 - -API documentation ------------------ - -If opened in a browser, the import path itself leads to the API documentation: - - * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) - -API stability -------------- - -The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). - - -License -------- - -The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. - - -Example -------- - -```Go -package main - -import ( - "fmt" - "log" - - "gopkg.in/yaml.v2" -) - -var data = ` -a: Easy! -b: - c: 2 - d: [3, 4] -` - -// Note: struct fields must be public in order for unmarshal to -// correctly populate the data. -type T struct { - A string - B struct { - RenamedC int `yaml:"c"` - D []int `yaml:",flow"` - } -} - -func main() { - t := T{} - - err := yaml.Unmarshal([]byte(data), &t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t:\n%v\n\n", t) - - d, err := yaml.Marshal(&t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t dump:\n%s\n\n", string(d)) - - m := make(map[interface{}]interface{}) - - err = yaml.Unmarshal([]byte(data), &m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m:\n%v\n\n", m) - - d, err = yaml.Marshal(&m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m dump:\n%s\n\n", string(d)) -} -``` - -This example will generate the following output: - -``` ---- t: -{Easy! {2 [3 4]}} - ---- t dump: -a: Easy! -b: - c: 2 - d: [3, 4] - - ---- m: -map[a:Easy! b:map[c:2 d:[3 4]]] - ---- m dump: -a: Easy! -b: - c: 2 - d: - - 3 - - 4 -``` - diff --git a/vendor/gopkg.in/yaml.v2/apic.go b/vendor/gopkg.in/yaml.v2/apic.go deleted file mode 100644 index acf71402..00000000 --- a/vendor/gopkg.in/yaml.v2/apic.go +++ /dev/null @@ -1,744 +0,0 @@ -package yaml - -import ( - "io" -) - -func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { - //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) - - // Check if we can move the queue at the beginning of the buffer. - if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { - if parser.tokens_head != len(parser.tokens) { - copy(parser.tokens, parser.tokens[parser.tokens_head:]) - } - parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] - parser.tokens_head = 0 - } - parser.tokens = append(parser.tokens, *token) - if pos < 0 { - return - } - copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) - parser.tokens[parser.tokens_head+pos] = *token -} - -// Create a new parser object. -func yaml_parser_initialize(parser *yaml_parser_t) bool { - *parser = yaml_parser_t{ - raw_buffer: make([]byte, 0, input_raw_buffer_size), - buffer: make([]byte, 0, input_buffer_size), - } - return true -} - -// Destroy a parser object. -func yaml_parser_delete(parser *yaml_parser_t) { - *parser = yaml_parser_t{} -} - -// String read handler. -func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - if parser.input_pos == len(parser.input) { - return 0, io.EOF - } - n = copy(buffer, parser.input[parser.input_pos:]) - parser.input_pos += n - return n, nil -} - -// Reader read handler. -func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - return parser.input_reader.Read(buffer) -} - -// Set a string input. -func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_string_read_handler - parser.input = input - parser.input_pos = 0 -} - -// Set a file input. -func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_reader_read_handler - parser.input_reader = r -} - -// Set the source encoding. -func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { - if parser.encoding != yaml_ANY_ENCODING { - panic("must set the encoding only once") - } - parser.encoding = encoding -} - -var disableLineWrapping = false - -// Create a new emitter object. -func yaml_emitter_initialize(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{ - buffer: make([]byte, output_buffer_size), - raw_buffer: make([]byte, 0, output_raw_buffer_size), - states: make([]yaml_emitter_state_t, 0, initial_stack_size), - events: make([]yaml_event_t, 0, initial_queue_size), - } - if disableLineWrapping { - emitter.best_width = -1 - } -} - -// Destroy an emitter object. -func yaml_emitter_delete(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{} -} - -// String write handler. -func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - *emitter.output_buffer = append(*emitter.output_buffer, buffer...) - return nil -} - -// yaml_writer_write_handler uses emitter.output_writer to write the -// emitted text. -func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - _, err := emitter.output_writer.Write(buffer) - return err -} - -// Set a string output. -func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_string_write_handler - emitter.output_buffer = output_buffer -} - -// Set a file output. -func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_writer_write_handler - emitter.output_writer = w -} - -// Set the output encoding. -func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { - if emitter.encoding != yaml_ANY_ENCODING { - panic("must set the output encoding only once") - } - emitter.encoding = encoding -} - -// Set the canonical output style. -func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { - emitter.canonical = canonical -} - -//// Set the indentation increment. -func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { - if indent < 2 || indent > 9 { - indent = 2 - } - emitter.best_indent = indent -} - -// Set the preferred line width. -func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { - if width < 0 { - width = -1 - } - emitter.best_width = width -} - -// Set if unescaped non-ASCII characters are allowed. -func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { - emitter.unicode = unicode -} - -// Set the preferred line break character. -func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { - emitter.line_break = line_break -} - -///* -// * Destroy a token object. -// */ -// -//YAML_DECLARE(void) -//yaml_token_delete(yaml_token_t *token) -//{ -// assert(token); // Non-NULL token object expected. -// -// switch (token.type) -// { -// case YAML_TAG_DIRECTIVE_TOKEN: -// yaml_free(token.data.tag_directive.handle); -// yaml_free(token.data.tag_directive.prefix); -// break; -// -// case YAML_ALIAS_TOKEN: -// yaml_free(token.data.alias.value); -// break; -// -// case YAML_ANCHOR_TOKEN: -// yaml_free(token.data.anchor.value); -// break; -// -// case YAML_TAG_TOKEN: -// yaml_free(token.data.tag.handle); -// yaml_free(token.data.tag.suffix); -// break; -// -// case YAML_SCALAR_TOKEN: -// yaml_free(token.data.scalar.value); -// break; -// -// default: -// break; -// } -// -// memset(token, 0, sizeof(yaml_token_t)); -//} -// -///* -// * Check if a string is a valid UTF-8 sequence. -// * -// * Check 'reader.c' for more details on UTF-8 encoding. -// */ -// -//static int -//yaml_check_utf8(yaml_char_t *start, size_t length) -//{ -// yaml_char_t *end = start+length; -// yaml_char_t *pointer = start; -// -// while (pointer < end) { -// unsigned char octet; -// unsigned int width; -// unsigned int value; -// size_t k; -// -// octet = pointer[0]; -// width = (octet & 0x80) == 0x00 ? 1 : -// (octet & 0xE0) == 0xC0 ? 2 : -// (octet & 0xF0) == 0xE0 ? 3 : -// (octet & 0xF8) == 0xF0 ? 4 : 0; -// value = (octet & 0x80) == 0x00 ? octet & 0x7F : -// (octet & 0xE0) == 0xC0 ? octet & 0x1F : -// (octet & 0xF0) == 0xE0 ? octet & 0x0F : -// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; -// if (!width) return 0; -// if (pointer+width > end) return 0; -// for (k = 1; k < width; k ++) { -// octet = pointer[k]; -// if ((octet & 0xC0) != 0x80) return 0; -// value = (value << 6) + (octet & 0x3F); -// } -// if (!((width == 1) || -// (width == 2 && value >= 0x80) || -// (width == 3 && value >= 0x800) || -// (width == 4 && value >= 0x10000))) return 0; -// -// pointer += width; -// } -// -// return 1; -//} -// - -// Create STREAM-START. -func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - encoding: encoding, - } -} - -// Create STREAM-END. -func yaml_stream_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - } -} - -// Create DOCUMENT-START. -func yaml_document_start_event_initialize( - event *yaml_event_t, - version_directive *yaml_version_directive_t, - tag_directives []yaml_tag_directive_t, - implicit bool, -) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: implicit, - } -} - -// Create DOCUMENT-END. -func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - implicit: implicit, - } -} - -///* -// * Create ALIAS. -// */ -// -//YAML_DECLARE(int) -//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t) -//{ -// mark yaml_mark_t = { 0, 0, 0 } -// anchor_copy *yaml_char_t = NULL -// -// assert(event) // Non-NULL event object is expected. -// assert(anchor) // Non-NULL anchor is expected. -// -// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0 -// -// anchor_copy = yaml_strdup(anchor) -// if (!anchor_copy) -// return 0 -// -// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark) -// -// return 1 -//} - -// Create SCALAR. -func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - anchor: anchor, - tag: tag, - value: value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-START. -func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-END. -func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - } - return true -} - -// Create MAPPING-START. -func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } -} - -// Create MAPPING-END. -func yaml_mapping_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - } -} - -// Destroy an event object. -func yaml_event_delete(event *yaml_event_t) { - *event = yaml_event_t{} -} - -///* -// * Create a document object. -// */ -// -//YAML_DECLARE(int) -//yaml_document_initialize(document *yaml_document_t, -// version_directive *yaml_version_directive_t, -// tag_directives_start *yaml_tag_directive_t, -// tag_directives_end *yaml_tag_directive_t, -// start_implicit int, end_implicit int) -//{ -// struct { -// error yaml_error_type_t -// } context -// struct { -// start *yaml_node_t -// end *yaml_node_t -// top *yaml_node_t -// } nodes = { NULL, NULL, NULL } -// version_directive_copy *yaml_version_directive_t = NULL -// struct { -// start *yaml_tag_directive_t -// end *yaml_tag_directive_t -// top *yaml_tag_directive_t -// } tag_directives_copy = { NULL, NULL, NULL } -// value yaml_tag_directive_t = { NULL, NULL } -// mark yaml_mark_t = { 0, 0, 0 } -// -// assert(document) // Non-NULL document object is expected. -// assert((tag_directives_start && tag_directives_end) || -// (tag_directives_start == tag_directives_end)) -// // Valid tag directives are expected. -// -// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error -// -// if (version_directive) { -// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) -// if (!version_directive_copy) goto error -// version_directive_copy.major = version_directive.major -// version_directive_copy.minor = version_directive.minor -// } -// -// if (tag_directives_start != tag_directives_end) { -// tag_directive *yaml_tag_directive_t -// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) -// goto error -// for (tag_directive = tag_directives_start -// tag_directive != tag_directives_end; tag_directive ++) { -// assert(tag_directive.handle) -// assert(tag_directive.prefix) -// if (!yaml_check_utf8(tag_directive.handle, -// strlen((char *)tag_directive.handle))) -// goto error -// if (!yaml_check_utf8(tag_directive.prefix, -// strlen((char *)tag_directive.prefix))) -// goto error -// value.handle = yaml_strdup(tag_directive.handle) -// value.prefix = yaml_strdup(tag_directive.prefix) -// if (!value.handle || !value.prefix) goto error -// if (!PUSH(&context, tag_directives_copy, value)) -// goto error -// value.handle = NULL -// value.prefix = NULL -// } -// } -// -// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, -// tag_directives_copy.start, tag_directives_copy.top, -// start_implicit, end_implicit, mark, mark) -// -// return 1 -// -//error: -// STACK_DEL(&context, nodes) -// yaml_free(version_directive_copy) -// while (!STACK_EMPTY(&context, tag_directives_copy)) { -// value yaml_tag_directive_t = POP(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// } -// STACK_DEL(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// -// return 0 -//} -// -///* -// * Destroy a document object. -// */ -// -//YAML_DECLARE(void) -//yaml_document_delete(document *yaml_document_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// tag_directive *yaml_tag_directive_t -// -// context.error = YAML_NO_ERROR // Eliminate a compiler warning. -// -// assert(document) // Non-NULL document object is expected. -// -// while (!STACK_EMPTY(&context, document.nodes)) { -// node yaml_node_t = POP(&context, document.nodes) -// yaml_free(node.tag) -// switch (node.type) { -// case YAML_SCALAR_NODE: -// yaml_free(node.data.scalar.value) -// break -// case YAML_SEQUENCE_NODE: -// STACK_DEL(&context, node.data.sequence.items) -// break -// case YAML_MAPPING_NODE: -// STACK_DEL(&context, node.data.mapping.pairs) -// break -// default: -// assert(0) // Should not happen. -// } -// } -// STACK_DEL(&context, document.nodes) -// -// yaml_free(document.version_directive) -// for (tag_directive = document.tag_directives.start -// tag_directive != document.tag_directives.end -// tag_directive++) { -// yaml_free(tag_directive.handle) -// yaml_free(tag_directive.prefix) -// } -// yaml_free(document.tag_directives.start) -// -// memset(document, 0, sizeof(yaml_document_t)) -//} -// -///** -// * Get a document node. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_node(document *yaml_document_t, index int) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (index > 0 && document.nodes.start + index <= document.nodes.top) { -// return document.nodes.start + index - 1 -// } -// return NULL -//} -// -///** -// * Get the root object. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_root_node(document *yaml_document_t) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (document.nodes.top != document.nodes.start) { -// return document.nodes.start -// } -// return NULL -//} -// -///* -// * Add a scalar node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_scalar(document *yaml_document_t, -// tag *yaml_char_t, value *yaml_char_t, length int, -// style yaml_scalar_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// value_copy *yaml_char_t = NULL -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// assert(value) // Non-NULL value is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (length < 0) { -// length = strlen((char *)value) -// } -// -// if (!yaml_check_utf8(value, length)) goto error -// value_copy = yaml_malloc(length+1) -// if (!value_copy) goto error -// memcpy(value_copy, value, length) -// value_copy[length] = '\0' -// -// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// yaml_free(tag_copy) -// yaml_free(value_copy) -// -// return 0 -//} -// -///* -// * Add a sequence node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_sequence(document *yaml_document_t, -// tag *yaml_char_t, style yaml_sequence_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_item_t -// end *yaml_node_item_t -// top *yaml_node_item_t -// } items = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error -// -// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, items) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Add a mapping node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_mapping(document *yaml_document_t, -// tag *yaml_char_t, style yaml_mapping_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_pair_t -// end *yaml_node_pair_t -// top *yaml_node_pair_t -// } pairs = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error -// -// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, pairs) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Append an item to a sequence node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_sequence_item(document *yaml_document_t, -// sequence int, item int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// assert(document) // Non-NULL document is required. -// assert(sequence > 0 -// && document.nodes.start + sequence <= document.nodes.top) -// // Valid sequence id is required. -// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) -// // A sequence node is required. -// assert(item > 0 && document.nodes.start + item <= document.nodes.top) -// // Valid item id is required. -// -// if (!PUSH(&context, -// document.nodes.start[sequence-1].data.sequence.items, item)) -// return 0 -// -// return 1 -//} -// -///* -// * Append a pair of a key and a value to a mapping node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_mapping_pair(document *yaml_document_t, -// mapping int, key int, value int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// pair yaml_node_pair_t -// -// assert(document) // Non-NULL document is required. -// assert(mapping > 0 -// && document.nodes.start + mapping <= document.nodes.top) -// // Valid mapping id is required. -// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) -// // A mapping node is required. -// assert(key > 0 && document.nodes.start + key <= document.nodes.top) -// // Valid key id is required. -// assert(value > 0 && document.nodes.start + value <= document.nodes.top) -// // Valid value id is required. -// -// pair.key = key -// pair.value = value -// -// if (!PUSH(&context, -// document.nodes.start[mapping-1].data.mapping.pairs, pair)) -// return 0 -// -// return 1 -//} -// -// diff --git a/vendor/gopkg.in/yaml.v2/decode.go b/vendor/gopkg.in/yaml.v2/decode.go deleted file mode 100644 index 129bc2a9..00000000 --- a/vendor/gopkg.in/yaml.v2/decode.go +++ /dev/null @@ -1,815 +0,0 @@ -package yaml - -import ( - "encoding" - "encoding/base64" - "fmt" - "io" - "math" - "reflect" - "strconv" - "time" -) - -const ( - documentNode = 1 << iota - mappingNode - sequenceNode - scalarNode - aliasNode -) - -type node struct { - kind int - line, column int - tag string - // For an alias node, alias holds the resolved alias. - alias *node - value string - implicit bool - children []*node - anchors map[string]*node -} - -// ---------------------------------------------------------------------------- -// Parser, produces a node tree out of a libyaml event stream. - -type parser struct { - parser yaml_parser_t - event yaml_event_t - doc *node - doneInit bool -} - -func newParser(b []byte) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - if len(b) == 0 { - b = []byte{'\n'} - } - yaml_parser_set_input_string(&p.parser, b) - return &p -} - -func newParserFromReader(r io.Reader) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - yaml_parser_set_input_reader(&p.parser, r) - return &p -} - -func (p *parser) init() { - if p.doneInit { - return - } - p.expect(yaml_STREAM_START_EVENT) - p.doneInit = true -} - -func (p *parser) destroy() { - if p.event.typ != yaml_NO_EVENT { - yaml_event_delete(&p.event) - } - yaml_parser_delete(&p.parser) -} - -// expect consumes an event from the event stream and -// checks that it's of the expected type. -func (p *parser) expect(e yaml_event_type_t) { - if p.event.typ == yaml_NO_EVENT { - if !yaml_parser_parse(&p.parser, &p.event) { - p.fail() - } - } - if p.event.typ == yaml_STREAM_END_EVENT { - failf("attempted to go past the end of stream; corrupted value?") - } - if p.event.typ != e { - p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) - p.fail() - } - yaml_event_delete(&p.event) - p.event.typ = yaml_NO_EVENT -} - -// peek peeks at the next event in the event stream, -// puts the results into p.event and returns the event type. -func (p *parser) peek() yaml_event_type_t { - if p.event.typ != yaml_NO_EVENT { - return p.event.typ - } - if !yaml_parser_parse(&p.parser, &p.event) { - p.fail() - } - return p.event.typ -} - -func (p *parser) fail() { - var where string - var line int - if p.parser.problem_mark.line != 0 { - line = p.parser.problem_mark.line - // Scanner errors don't iterate line before returning error - if p.parser.error == yaml_SCANNER_ERROR { - line++ - } - } else if p.parser.context_mark.line != 0 { - line = p.parser.context_mark.line - } - if line != 0 { - where = "line " + strconv.Itoa(line) + ": " - } - var msg string - if len(p.parser.problem) > 0 { - msg = p.parser.problem - } else { - msg = "unknown problem parsing YAML content" - } - failf("%s%s", where, msg) -} - -func (p *parser) anchor(n *node, anchor []byte) { - if anchor != nil { - p.doc.anchors[string(anchor)] = n - } -} - -func (p *parser) parse() *node { - p.init() - switch p.peek() { - case yaml_SCALAR_EVENT: - return p.scalar() - case yaml_ALIAS_EVENT: - return p.alias() - case yaml_MAPPING_START_EVENT: - return p.mapping() - case yaml_SEQUENCE_START_EVENT: - return p.sequence() - case yaml_DOCUMENT_START_EVENT: - return p.document() - case yaml_STREAM_END_EVENT: - // Happens when attempting to decode an empty buffer. - return nil - default: - panic("attempted to parse unknown event: " + p.event.typ.String()) - } -} - -func (p *parser) node(kind int) *node { - return &node{ - kind: kind, - line: p.event.start_mark.line, - column: p.event.start_mark.column, - } -} - -func (p *parser) document() *node { - n := p.node(documentNode) - n.anchors = make(map[string]*node) - p.doc = n - p.expect(yaml_DOCUMENT_START_EVENT) - n.children = append(n.children, p.parse()) - p.expect(yaml_DOCUMENT_END_EVENT) - return n -} - -func (p *parser) alias() *node { - n := p.node(aliasNode) - n.value = string(p.event.anchor) - n.alias = p.doc.anchors[n.value] - if n.alias == nil { - failf("unknown anchor '%s' referenced", n.value) - } - p.expect(yaml_ALIAS_EVENT) - return n -} - -func (p *parser) scalar() *node { - n := p.node(scalarNode) - n.value = string(p.event.value) - n.tag = string(p.event.tag) - n.implicit = p.event.implicit - p.anchor(n, p.event.anchor) - p.expect(yaml_SCALAR_EVENT) - return n -} - -func (p *parser) sequence() *node { - n := p.node(sequenceNode) - p.anchor(n, p.event.anchor) - p.expect(yaml_SEQUENCE_START_EVENT) - for p.peek() != yaml_SEQUENCE_END_EVENT { - n.children = append(n.children, p.parse()) - } - p.expect(yaml_SEQUENCE_END_EVENT) - return n -} - -func (p *parser) mapping() *node { - n := p.node(mappingNode) - p.anchor(n, p.event.anchor) - p.expect(yaml_MAPPING_START_EVENT) - for p.peek() != yaml_MAPPING_END_EVENT { - n.children = append(n.children, p.parse(), p.parse()) - } - p.expect(yaml_MAPPING_END_EVENT) - return n -} - -// ---------------------------------------------------------------------------- -// Decoder, unmarshals a node into a provided value. - -type decoder struct { - doc *node - aliases map[*node]bool - mapType reflect.Type - terrors []string - strict bool - - decodeCount int - aliasCount int - aliasDepth int -} - -var ( - mapItemType = reflect.TypeOf(MapItem{}) - durationType = reflect.TypeOf(time.Duration(0)) - defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) - ifaceType = defaultMapType.Elem() - timeType = reflect.TypeOf(time.Time{}) - ptrTimeType = reflect.TypeOf(&time.Time{}) -) - -func newDecoder(strict bool) *decoder { - d := &decoder{mapType: defaultMapType, strict: strict} - d.aliases = make(map[*node]bool) - return d -} - -func (d *decoder) terror(n *node, tag string, out reflect.Value) { - if n.tag != "" { - tag = n.tag - } - value := n.value - if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG { - if len(value) > 10 { - value = " `" + value[:7] + "...`" - } else { - value = " `" + value + "`" - } - } - d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type())) -} - -func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) { - terrlen := len(d.terrors) - err := u.UnmarshalYAML(func(v interface{}) (err error) { - defer handleErr(&err) - d.unmarshal(n, reflect.ValueOf(v)) - if len(d.terrors) > terrlen { - issues := d.terrors[terrlen:] - d.terrors = d.terrors[:terrlen] - return &TypeError{issues} - } - return nil - }) - if e, ok := err.(*TypeError); ok { - d.terrors = append(d.terrors, e.Errors...) - return false - } - if err != nil { - fail(err) - } - return true -} - -// d.prepare initializes and dereferences pointers and calls UnmarshalYAML -// if a value is found to implement it. -// It returns the initialized and dereferenced out value, whether -// unmarshalling was already done by UnmarshalYAML, and if so whether -// its types unmarshalled appropriately. -// -// If n holds a null value, prepare returns before doing anything. -func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { - if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) { - return out, false, false - } - again := true - for again { - again = false - if out.Kind() == reflect.Ptr { - if out.IsNil() { - out.Set(reflect.New(out.Type().Elem())) - } - out = out.Elem() - again = true - } - if out.CanAddr() { - if u, ok := out.Addr().Interface().(Unmarshaler); ok { - good = d.callUnmarshaler(n, u) - return out, true, good - } - } - } - return out, false, false -} - -const ( - // 400,000 decode operations is ~500kb of dense object declarations, or - // ~5kb of dense object declarations with 10000% alias expansion - alias_ratio_range_low = 400000 - - // 4,000,000 decode operations is ~5MB of dense object declarations, or - // ~4.5MB of dense object declarations with 10% alias expansion - alias_ratio_range_high = 4000000 - - // alias_ratio_range is the range over which we scale allowed alias ratios - alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) -) - -func allowedAliasRatio(decodeCount int) float64 { - switch { - case decodeCount <= alias_ratio_range_low: - // allow 99% to come from alias expansion for small-to-medium documents - return 0.99 - case decodeCount >= alias_ratio_range_high: - // allow 10% to come from alias expansion for very large documents - return 0.10 - default: - // scale smoothly from 99% down to 10% over the range. - // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. - // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). - return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) - } -} - -func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { - d.decodeCount++ - if d.aliasDepth > 0 { - d.aliasCount++ - } - if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { - failf("document contains excessive aliasing") - } - switch n.kind { - case documentNode: - return d.document(n, out) - case aliasNode: - return d.alias(n, out) - } - out, unmarshaled, good := d.prepare(n, out) - if unmarshaled { - return good - } - switch n.kind { - case scalarNode: - good = d.scalar(n, out) - case mappingNode: - good = d.mapping(n, out) - case sequenceNode: - good = d.sequence(n, out) - default: - panic("internal error: unknown node kind: " + strconv.Itoa(n.kind)) - } - return good -} - -func (d *decoder) document(n *node, out reflect.Value) (good bool) { - if len(n.children) == 1 { - d.doc = n - d.unmarshal(n.children[0], out) - return true - } - return false -} - -func (d *decoder) alias(n *node, out reflect.Value) (good bool) { - if d.aliases[n] { - // TODO this could actually be allowed in some circumstances. - failf("anchor '%s' value contains itself", n.value) - } - d.aliases[n] = true - d.aliasDepth++ - good = d.unmarshal(n.alias, out) - d.aliasDepth-- - delete(d.aliases, n) - return good -} - -var zeroValue reflect.Value - -func resetMap(out reflect.Value) { - for _, k := range out.MapKeys() { - out.SetMapIndex(k, zeroValue) - } -} - -func (d *decoder) scalar(n *node, out reflect.Value) bool { - var tag string - var resolved interface{} - if n.tag == "" && !n.implicit { - tag = yaml_STR_TAG - resolved = n.value - } else { - tag, resolved = resolve(n.tag, n.value) - if tag == yaml_BINARY_TAG { - data, err := base64.StdEncoding.DecodeString(resolved.(string)) - if err != nil { - failf("!!binary value contains invalid base64 data") - } - resolved = string(data) - } - } - if resolved == nil { - if out.Kind() == reflect.Map && !out.CanAddr() { - resetMap(out) - } else { - out.Set(reflect.Zero(out.Type())) - } - return true - } - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - // We've resolved to exactly the type we want, so use that. - out.Set(resolvedv) - return true - } - // Perhaps we can use the value as a TextUnmarshaler to - // set its value. - if out.CanAddr() { - u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) - if ok { - var text []byte - if tag == yaml_BINARY_TAG { - text = []byte(resolved.(string)) - } else { - // We let any value be unmarshaled into TextUnmarshaler. - // That might be more lax than we'd like, but the - // TextUnmarshaler itself should bowl out any dubious values. - text = []byte(n.value) - } - err := u.UnmarshalText(text) - if err != nil { - fail(err) - } - return true - } - } - switch out.Kind() { - case reflect.String: - if tag == yaml_BINARY_TAG { - out.SetString(resolved.(string)) - return true - } - if resolved != nil { - out.SetString(n.value) - return true - } - case reflect.Interface: - if resolved == nil { - out.Set(reflect.Zero(out.Type())) - } else if tag == yaml_TIMESTAMP_TAG { - // It looks like a timestamp but for backward compatibility - // reasons we set it as a string, so that code that unmarshals - // timestamp-like values into interface{} will continue to - // see a string and not a time.Time. - // TODO(v3) Drop this. - out.Set(reflect.ValueOf(n.value)) - } else { - out.Set(reflect.ValueOf(resolved)) - } - return true - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - switch resolved := resolved.(type) { - case int: - if !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case int64: - if !out.OverflowInt(resolved) { - out.SetInt(resolved) - return true - } - case uint64: - if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case float64: - if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case string: - if out.Type() == durationType { - d, err := time.ParseDuration(resolved) - if err == nil { - out.SetInt(int64(d)) - return true - } - } - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - switch resolved := resolved.(type) { - case int: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case int64: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case uint64: - if !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case float64: - if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - } - case reflect.Bool: - switch resolved := resolved.(type) { - case bool: - out.SetBool(resolved) - return true - } - case reflect.Float32, reflect.Float64: - switch resolved := resolved.(type) { - case int: - out.SetFloat(float64(resolved)) - return true - case int64: - out.SetFloat(float64(resolved)) - return true - case uint64: - out.SetFloat(float64(resolved)) - return true - case float64: - out.SetFloat(resolved) - return true - } - case reflect.Struct: - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - out.Set(resolvedv) - return true - } - case reflect.Ptr: - if out.Type().Elem() == reflect.TypeOf(resolved) { - // TODO DOes this make sense? When is out a Ptr except when decoding a nil value? - elem := reflect.New(out.Type().Elem()) - elem.Elem().Set(reflect.ValueOf(resolved)) - out.Set(elem) - return true - } - } - d.terror(n, tag, out) - return false -} - -func settableValueOf(i interface{}) reflect.Value { - v := reflect.ValueOf(i) - sv := reflect.New(v.Type()).Elem() - sv.Set(v) - return sv -} - -func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { - l := len(n.children) - - var iface reflect.Value - switch out.Kind() { - case reflect.Slice: - out.Set(reflect.MakeSlice(out.Type(), l, l)) - case reflect.Array: - if l != out.Len() { - failf("invalid array: want %d elements but got %d", out.Len(), l) - } - case reflect.Interface: - // No type hints. Will have to use a generic sequence. - iface = out - out = settableValueOf(make([]interface{}, l)) - default: - d.terror(n, yaml_SEQ_TAG, out) - return false - } - et := out.Type().Elem() - - j := 0 - for i := 0; i < l; i++ { - e := reflect.New(et).Elem() - if ok := d.unmarshal(n.children[i], e); ok { - out.Index(j).Set(e) - j++ - } - } - if out.Kind() != reflect.Array { - out.Set(out.Slice(0, j)) - } - if iface.IsValid() { - iface.Set(out) - } - return true -} - -func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { - switch out.Kind() { - case reflect.Struct: - return d.mappingStruct(n, out) - case reflect.Slice: - return d.mappingSlice(n, out) - case reflect.Map: - // okay - case reflect.Interface: - if d.mapType.Kind() == reflect.Map { - iface := out - out = reflect.MakeMap(d.mapType) - iface.Set(out) - } else { - slicev := reflect.New(d.mapType).Elem() - if !d.mappingSlice(n, slicev) { - return false - } - out.Set(slicev) - return true - } - default: - d.terror(n, yaml_MAP_TAG, out) - return false - } - outt := out.Type() - kt := outt.Key() - et := outt.Elem() - - mapType := d.mapType - if outt.Key() == ifaceType && outt.Elem() == ifaceType { - d.mapType = outt - } - - if out.IsNil() { - out.Set(reflect.MakeMap(outt)) - } - l := len(n.children) - for i := 0; i < l; i += 2 { - if isMerge(n.children[i]) { - d.merge(n.children[i+1], out) - continue - } - k := reflect.New(kt).Elem() - if d.unmarshal(n.children[i], k) { - kkind := k.Kind() - if kkind == reflect.Interface { - kkind = k.Elem().Kind() - } - if kkind == reflect.Map || kkind == reflect.Slice { - failf("invalid map key: %#v", k.Interface()) - } - e := reflect.New(et).Elem() - if d.unmarshal(n.children[i+1], e) { - d.setMapIndex(n.children[i+1], out, k, e) - } - } - } - d.mapType = mapType - return true -} - -func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) { - if d.strict && out.MapIndex(k) != zeroValue { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface())) - return - } - out.SetMapIndex(k, v) -} - -func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) { - outt := out.Type() - if outt.Elem() != mapItemType { - d.terror(n, yaml_MAP_TAG, out) - return false - } - - mapType := d.mapType - d.mapType = outt - - var slice []MapItem - var l = len(n.children) - for i := 0; i < l; i += 2 { - if isMerge(n.children[i]) { - d.merge(n.children[i+1], out) - continue - } - item := MapItem{} - k := reflect.ValueOf(&item.Key).Elem() - if d.unmarshal(n.children[i], k) { - v := reflect.ValueOf(&item.Value).Elem() - if d.unmarshal(n.children[i+1], v) { - slice = append(slice, item) - } - } - } - out.Set(reflect.ValueOf(slice)) - d.mapType = mapType - return true -} - -func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) { - sinfo, err := getStructInfo(out.Type()) - if err != nil { - panic(err) - } - name := settableValueOf("") - l := len(n.children) - - var inlineMap reflect.Value - var elemType reflect.Type - if sinfo.InlineMap != -1 { - inlineMap = out.Field(sinfo.InlineMap) - inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) - elemType = inlineMap.Type().Elem() - } - - var doneFields []bool - if d.strict { - doneFields = make([]bool, len(sinfo.FieldsList)) - } - for i := 0; i < l; i += 2 { - ni := n.children[i] - if isMerge(ni) { - d.merge(n.children[i+1], out) - continue - } - if !d.unmarshal(ni, name) { - continue - } - if info, ok := sinfo.FieldsMap[name.String()]; ok { - if d.strict { - if doneFields[info.Id] { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type())) - continue - } - doneFields[info.Id] = true - } - var field reflect.Value - if info.Inline == nil { - field = out.Field(info.Num) - } else { - field = out.FieldByIndex(info.Inline) - } - d.unmarshal(n.children[i+1], field) - } else if sinfo.InlineMap != -1 { - if inlineMap.IsNil() { - inlineMap.Set(reflect.MakeMap(inlineMap.Type())) - } - value := reflect.New(elemType).Elem() - d.unmarshal(n.children[i+1], value) - d.setMapIndex(n.children[i+1], inlineMap, name, value) - } else if d.strict { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type())) - } - } - return true -} - -func failWantMap() { - failf("map merge requires map or sequence of maps as the value") -} - -func (d *decoder) merge(n *node, out reflect.Value) { - switch n.kind { - case mappingNode: - d.unmarshal(n, out) - case aliasNode: - if n.alias != nil && n.alias.kind != mappingNode { - failWantMap() - } - d.unmarshal(n, out) - case sequenceNode: - // Step backwards as earlier nodes take precedence. - for i := len(n.children) - 1; i >= 0; i-- { - ni := n.children[i] - if ni.kind == aliasNode { - if ni.alias != nil && ni.alias.kind != mappingNode { - failWantMap() - } - } else if ni.kind != mappingNode { - failWantMap() - } - d.unmarshal(ni, out) - } - default: - failWantMap() - } -} - -func isMerge(n *node) bool { - return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG) -} diff --git a/vendor/gopkg.in/yaml.v2/emitterc.go b/vendor/gopkg.in/yaml.v2/emitterc.go deleted file mode 100644 index a1c2cc52..00000000 --- a/vendor/gopkg.in/yaml.v2/emitterc.go +++ /dev/null @@ -1,1685 +0,0 @@ -package yaml - -import ( - "bytes" - "fmt" -) - -// Flush the buffer if needed. -func flush(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) { - return yaml_emitter_flush(emitter) - } - return true -} - -// Put a character to the output buffer. -func put(emitter *yaml_emitter_t, value byte) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - emitter.buffer[emitter.buffer_pos] = value - emitter.buffer_pos++ - emitter.column++ - return true -} - -// Put a line break to the output buffer. -func put_break(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - switch emitter.line_break { - case yaml_CR_BREAK: - emitter.buffer[emitter.buffer_pos] = '\r' - emitter.buffer_pos += 1 - case yaml_LN_BREAK: - emitter.buffer[emitter.buffer_pos] = '\n' - emitter.buffer_pos += 1 - case yaml_CRLN_BREAK: - emitter.buffer[emitter.buffer_pos+0] = '\r' - emitter.buffer[emitter.buffer_pos+1] = '\n' - emitter.buffer_pos += 2 - default: - panic("unknown line break setting") - } - emitter.column = 0 - emitter.line++ - return true -} - -// Copy a character from a string into buffer. -func write(emitter *yaml_emitter_t, s []byte, i *int) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - p := emitter.buffer_pos - w := width(s[*i]) - switch w { - case 4: - emitter.buffer[p+3] = s[*i+3] - fallthrough - case 3: - emitter.buffer[p+2] = s[*i+2] - fallthrough - case 2: - emitter.buffer[p+1] = s[*i+1] - fallthrough - case 1: - emitter.buffer[p+0] = s[*i+0] - default: - panic("unknown character width") - } - emitter.column++ - emitter.buffer_pos += w - *i += w - return true -} - -// Write a whole string into buffer. -func write_all(emitter *yaml_emitter_t, s []byte) bool { - for i := 0; i < len(s); { - if !write(emitter, s, &i) { - return false - } - } - return true -} - -// Copy a line break character from a string into buffer. -func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { - if s[*i] == '\n' { - if !put_break(emitter) { - return false - } - *i++ - } else { - if !write(emitter, s, i) { - return false - } - emitter.column = 0 - emitter.line++ - } - return true -} - -// Set an emitter error and return false. -func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_EMITTER_ERROR - emitter.problem = problem - return false -} - -// Emit an event. -func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.events = append(emitter.events, *event) - for !yaml_emitter_need_more_events(emitter) { - event := &emitter.events[emitter.events_head] - if !yaml_emitter_analyze_event(emitter, event) { - return false - } - if !yaml_emitter_state_machine(emitter, event) { - return false - } - yaml_event_delete(event) - emitter.events_head++ - } - return true -} - -// Check if we need to accumulate more events before emitting. -// -// We accumulate extra -// - 1 event for DOCUMENT-START -// - 2 events for SEQUENCE-START -// - 3 events for MAPPING-START -// -func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { - if emitter.events_head == len(emitter.events) { - return true - } - var accumulate int - switch emitter.events[emitter.events_head].typ { - case yaml_DOCUMENT_START_EVENT: - accumulate = 1 - break - case yaml_SEQUENCE_START_EVENT: - accumulate = 2 - break - case yaml_MAPPING_START_EVENT: - accumulate = 3 - break - default: - return false - } - if len(emitter.events)-emitter.events_head > accumulate { - return false - } - var level int - for i := emitter.events_head; i < len(emitter.events); i++ { - switch emitter.events[i].typ { - case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: - level++ - case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: - level-- - } - if level == 0 { - return false - } - } - return true -} - -// Append a directive to the directives stack. -func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { - for i := 0; i < len(emitter.tag_directives); i++ { - if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") - } - } - - // [Go] Do we actually need to copy this given garbage collection - // and the lack of deallocating destructors? - tag_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(tag_copy.handle, value.handle) - copy(tag_copy.prefix, value.prefix) - emitter.tag_directives = append(emitter.tag_directives, tag_copy) - return true -} - -// Increase the indentation level. -func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { - emitter.indents = append(emitter.indents, emitter.indent) - if emitter.indent < 0 { - if flow { - emitter.indent = emitter.best_indent - } else { - emitter.indent = 0 - } - } else if !indentless { - emitter.indent += emitter.best_indent - } - return true -} - -// State dispatcher. -func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { - switch emitter.state { - default: - case yaml_EMIT_STREAM_START_STATE: - return yaml_emitter_emit_stream_start(emitter, event) - - case yaml_EMIT_FIRST_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, true) - - case yaml_EMIT_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, false) - - case yaml_EMIT_DOCUMENT_CONTENT_STATE: - return yaml_emitter_emit_document_content(emitter, event) - - case yaml_EMIT_DOCUMENT_END_STATE: - return yaml_emitter_emit_document_end(emitter, event) - - case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, true) - - case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, false) - - case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, true) - - case yaml_EMIT_FLOW_MAPPING_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, false) - - case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, true) - - case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, false) - - case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, true) - - case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, false) - - case yaml_EMIT_END_STATE: - return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") - } - panic("invalid emitter state") -} - -// Expect STREAM-START. -func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_STREAM_START_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") - } - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = event.encoding - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = yaml_UTF8_ENCODING - } - } - if emitter.best_indent < 2 || emitter.best_indent > 9 { - emitter.best_indent = 2 - } - if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { - emitter.best_width = 80 - } - if emitter.best_width < 0 { - emitter.best_width = 1<<31 - 1 - } - if emitter.line_break == yaml_ANY_BREAK { - emitter.line_break = yaml_LN_BREAK - } - - emitter.indent = -1 - emitter.line = 0 - emitter.column = 0 - emitter.whitespace = true - emitter.indention = true - - if emitter.encoding != yaml_UTF8_ENCODING { - if !yaml_emitter_write_bom(emitter) { - return false - } - } - emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE - return true -} - -// Expect DOCUMENT-START or STREAM-END. -func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - - if event.typ == yaml_DOCUMENT_START_EVENT { - - if event.version_directive != nil { - if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { - return false - } - } - - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { - return false - } - if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { - return false - } - } - - for i := 0; i < len(default_tag_directives); i++ { - tag_directive := &default_tag_directives[i] - if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { - return false - } - } - - implicit := event.implicit - if !first || emitter.canonical { - implicit = false - } - - if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if event.version_directive != nil { - implicit = false - if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if len(event.tag_directives) > 0 { - implicit = false - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { - return false - } - if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - if yaml_emitter_check_empty_document(emitter) { - implicit = false - } - if !implicit { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { - return false - } - if emitter.canonical { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE - return true - } - - if event.typ == yaml_STREAM_END_EVENT { - if emitter.open_ended { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_END_STATE - return true - } - - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") -} - -// Expect the root node. -func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) - return yaml_emitter_emit_node(emitter, event, true, false, false, false) -} - -// Expect DOCUMENT-END. -func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_DOCUMENT_END_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !event.implicit { - // [Go] Allocate the slice elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_DOCUMENT_START_STATE - emitter.tag_directives = emitter.tag_directives[:0] - return true -} - -// Expect a flow item node. -func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_SEQUENCE_END_EVENT { - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.canonical && !first { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - - return true - } - - if !first { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) - return yaml_emitter_emit_node(emitter, event, false, true, false, false) -} - -// Expect a flow key node. -func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_MAPPING_END_EVENT { - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.canonical && !first { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - - if !first { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a flow value node. -func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { - return false - } - } - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a block item node. -func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) { - return false - } - } - if event.typ == yaml_SEQUENCE_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) - return yaml_emitter_emit_node(emitter, event, false, true, false, false) -} - -// Expect a block key node. -func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, false) { - return false - } - } - if event.typ == yaml_MAPPING_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a block value node. -func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { - return false - } - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a node. -func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, - root bool, sequence bool, mapping bool, simple_key bool) bool { - - emitter.root_context = root - emitter.sequence_context = sequence - emitter.mapping_context = mapping - emitter.simple_key_context = simple_key - - switch event.typ { - case yaml_ALIAS_EVENT: - return yaml_emitter_emit_alias(emitter, event) - case yaml_SCALAR_EVENT: - return yaml_emitter_emit_scalar(emitter, event) - case yaml_SEQUENCE_START_EVENT: - return yaml_emitter_emit_sequence_start(emitter, event) - case yaml_MAPPING_START_EVENT: - return yaml_emitter_emit_mapping_start(emitter, event) - default: - return yaml_emitter_set_emitter_error(emitter, - fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) - } -} - -// Expect ALIAS. -func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SCALAR. -func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_select_scalar_style(emitter, event) { - return false - } - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - if !yaml_emitter_process_scalar(emitter) { - return false - } - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SEQUENCE-START. -func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || - yaml_emitter_check_empty_sequence(emitter) { - emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE - } - return true -} - -// Expect MAPPING-START. -func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || - yaml_emitter_check_empty_mapping(emitter) { - emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE - } - return true -} - -// Check if the document content is an empty scalar. -func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { - return false // [Go] Huh? -} - -// Check if the next events represent an empty sequence. -func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT -} - -// Check if the next events represent an empty mapping. -func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT -} - -// Check if the next node can be expressed as a simple key. -func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { - length := 0 - switch emitter.events[emitter.events_head].typ { - case yaml_ALIAS_EVENT: - length += len(emitter.anchor_data.anchor) - case yaml_SCALAR_EVENT: - if emitter.scalar_data.multiline { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) + - len(emitter.scalar_data.value) - case yaml_SEQUENCE_START_EVENT: - if !yaml_emitter_check_empty_sequence(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - case yaml_MAPPING_START_EVENT: - if !yaml_emitter_check_empty_mapping(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - default: - return false - } - return length <= 128 -} - -// Determine an acceptable scalar style. -func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 - if no_tag && !event.implicit && !event.quoted_implicit { - return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") - } - - style := event.scalar_style() - if style == yaml_ANY_SCALAR_STYLE { - style = yaml_PLAIN_SCALAR_STYLE - } - if emitter.canonical { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - if emitter.simple_key_context && emitter.scalar_data.multiline { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - - if style == yaml_PLAIN_SCALAR_STYLE { - if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || - emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if no_tag && !event.implicit { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { - if !emitter.scalar_data.single_quoted_allowed { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { - if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - - if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { - emitter.tag_data.handle = []byte{'!'} - } - emitter.scalar_data.style = style - return true -} - -// Write an anchor. -func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { - if emitter.anchor_data.anchor == nil { - return true - } - c := []byte{'&'} - if emitter.anchor_data.alias { - c[0] = '*' - } - if !yaml_emitter_write_indicator(emitter, c, true, false, false) { - return false - } - return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) -} - -// Write a tag. -func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { - if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { - return true - } - if len(emitter.tag_data.handle) > 0 { - if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { - return false - } - if len(emitter.tag_data.suffix) > 0 { - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - } - } else { - // [Go] Allocate these slices elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { - return false - } - } - return true -} - -// Write a scalar. -func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { - switch emitter.scalar_data.style { - case yaml_PLAIN_SCALAR_STYLE: - return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_SINGLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_DOUBLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_LITERAL_SCALAR_STYLE: - return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) - - case yaml_FOLDED_SCALAR_STYLE: - return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) - } - panic("unknown scalar style") -} - -// Check if a %YAML directive is valid. -func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { - if version_directive.major != 1 || version_directive.minor != 1 { - return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") - } - return true -} - -// Check if a %TAG directive is valid. -func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { - handle := tag_directive.handle - prefix := tag_directive.prefix - if len(handle) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") - } - if handle[0] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") - } - if handle[len(handle)-1] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") - } - for i := 1; i < len(handle)-1; i += width(handle[i]) { - if !is_alpha(handle, i) { - return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") - } - } - if len(prefix) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") - } - return true -} - -// Check if an anchor is valid. -func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { - if len(anchor) == 0 { - problem := "anchor value must not be empty" - if alias { - problem = "alias value must not be empty" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - for i := 0; i < len(anchor); i += width(anchor[i]) { - if !is_alpha(anchor, i) { - problem := "anchor value must contain alphanumerical characters only" - if alias { - problem = "alias value must contain alphanumerical characters only" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - } - emitter.anchor_data.anchor = anchor - emitter.anchor_data.alias = alias - return true -} - -// Check if a tag is valid. -func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { - if len(tag) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") - } - for i := 0; i < len(emitter.tag_directives); i++ { - tag_directive := &emitter.tag_directives[i] - if bytes.HasPrefix(tag, tag_directive.prefix) { - emitter.tag_data.handle = tag_directive.handle - emitter.tag_data.suffix = tag[len(tag_directive.prefix):] - return true - } - } - emitter.tag_data.suffix = tag - return true -} - -// Check if a scalar is valid. -func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { - var ( - block_indicators = false - flow_indicators = false - line_breaks = false - special_characters = false - - leading_space = false - leading_break = false - trailing_space = false - trailing_break = false - break_space = false - space_break = false - - preceded_by_whitespace = false - followed_by_whitespace = false - previous_space = false - previous_break = false - ) - - emitter.scalar_data.value = value - - if len(value) == 0 { - emitter.scalar_data.multiline = false - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = false - return true - } - - if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { - block_indicators = true - flow_indicators = true - } - - preceded_by_whitespace = true - for i, w := 0, 0; i < len(value); i += w { - w = width(value[i]) - followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) - - if i == 0 { - switch value[i] { - case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': - flow_indicators = true - block_indicators = true - case '?', ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '-': - if followed_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } else { - switch value[i] { - case ',', '?', '[', ']', '{', '}': - flow_indicators = true - case ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '#': - if preceded_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } - - if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { - special_characters = true - } - if is_space(value, i) { - if i == 0 { - leading_space = true - } - if i+width(value[i]) == len(value) { - trailing_space = true - } - if previous_break { - break_space = true - } - previous_space = true - previous_break = false - } else if is_break(value, i) { - line_breaks = true - if i == 0 { - leading_break = true - } - if i+width(value[i]) == len(value) { - trailing_break = true - } - if previous_space { - space_break = true - } - previous_space = false - previous_break = true - } else { - previous_space = false - previous_break = false - } - - // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. - preceded_by_whitespace = is_blankz(value, i) - } - - emitter.scalar_data.multiline = line_breaks - emitter.scalar_data.flow_plain_allowed = true - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = true - - if leading_space || leading_break || trailing_space || trailing_break { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if trailing_space { - emitter.scalar_data.block_allowed = false - } - if break_space { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - } - if space_break || special_characters { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - emitter.scalar_data.block_allowed = false - } - if line_breaks { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if flow_indicators { - emitter.scalar_data.flow_plain_allowed = false - } - if block_indicators { - emitter.scalar_data.block_plain_allowed = false - } - return true -} - -// Check if the event data is valid. -func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - emitter.anchor_data.anchor = nil - emitter.tag_data.handle = nil - emitter.tag_data.suffix = nil - emitter.scalar_data.value = nil - - switch event.typ { - case yaml_ALIAS_EVENT: - if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { - return false - } - - case yaml_SCALAR_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - if !yaml_emitter_analyze_scalar(emitter, event.value) { - return false - } - - case yaml_SEQUENCE_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - - case yaml_MAPPING_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - } - return true -} - -// Write the BOM character. -func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { - if !flush(emitter) { - return false - } - pos := emitter.buffer_pos - emitter.buffer[pos+0] = '\xEF' - emitter.buffer[pos+1] = '\xBB' - emitter.buffer[pos+2] = '\xBF' - emitter.buffer_pos += 3 - return true -} - -func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { - indent := emitter.indent - if indent < 0 { - indent = 0 - } - if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { - if !put_break(emitter) { - return false - } - } - for emitter.column < indent { - if !put(emitter, ' ') { - return false - } - } - emitter.whitespace = true - emitter.indention = true - return true -} - -func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, indicator) { - return false - } - emitter.whitespace = is_whitespace - emitter.indention = (emitter.indention && is_indention) - emitter.open_ended = false - return true -} - -func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - for i := 0; i < len(value); { - var must_write bool - switch value[i] { - case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': - must_write = true - default: - must_write = is_alpha(value, i) - } - if must_write { - if !write(emitter, value, &i) { - return false - } - } else { - w := width(value[i]) - for k := 0; k < w; k++ { - octet := value[i] - i++ - if !put(emitter, '%') { - return false - } - - c := octet >> 4 - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - - c = octet & 0x0f - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - } - } - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - - emitter.whitespace = false - emitter.indention = false - if emitter.root_context { - emitter.open_ended = true - } - - return true -} - -func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { - return false - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if value[i] == '\'' { - if !put(emitter, '\'') { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - spaces := false - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { - return false - } - - for i := 0; i < len(value); { - if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || - is_bom(value, i) || is_break(value, i) || - value[i] == '"' || value[i] == '\\' { - - octet := value[i] - - var w int - var v rune - switch { - case octet&0x80 == 0x00: - w, v = 1, rune(octet&0x7F) - case octet&0xE0 == 0xC0: - w, v = 2, rune(octet&0x1F) - case octet&0xF0 == 0xE0: - w, v = 3, rune(octet&0x0F) - case octet&0xF8 == 0xF0: - w, v = 4, rune(octet&0x07) - } - for k := 1; k < w; k++ { - octet = value[i+k] - v = (v << 6) + (rune(octet) & 0x3F) - } - i += w - - if !put(emitter, '\\') { - return false - } - - var ok bool - switch v { - case 0x00: - ok = put(emitter, '0') - case 0x07: - ok = put(emitter, 'a') - case 0x08: - ok = put(emitter, 'b') - case 0x09: - ok = put(emitter, 't') - case 0x0A: - ok = put(emitter, 'n') - case 0x0b: - ok = put(emitter, 'v') - case 0x0c: - ok = put(emitter, 'f') - case 0x0d: - ok = put(emitter, 'r') - case 0x1b: - ok = put(emitter, 'e') - case 0x22: - ok = put(emitter, '"') - case 0x5c: - ok = put(emitter, '\\') - case 0x85: - ok = put(emitter, 'N') - case 0xA0: - ok = put(emitter, '_') - case 0x2028: - ok = put(emitter, 'L') - case 0x2029: - ok = put(emitter, 'P') - default: - if v <= 0xFF { - ok = put(emitter, 'x') - w = 2 - } else if v <= 0xFFFF { - ok = put(emitter, 'u') - w = 4 - } else { - ok = put(emitter, 'U') - w = 8 - } - for k := (w - 1) * 4; ok && k >= 0; k -= 4 { - digit := byte((v >> uint(k)) & 0x0F) - if digit < 10 { - ok = put(emitter, digit+'0') - } else { - ok = put(emitter, digit+'A'-10) - } - } - } - if !ok { - return false - } - spaces = false - } else if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { - if !yaml_emitter_write_indent(emitter) { - return false - } - if is_space(value, i+1) { - if !put(emitter, '\\') { - return false - } - } - i += width(value[i]) - } else if !write(emitter, value, &i) { - return false - } - spaces = true - } else { - if !write(emitter, value, &i) { - return false - } - spaces = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { - if is_space(value, 0) || is_break(value, 0) { - indent_hint := []byte{'0' + byte(emitter.best_indent)} - if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { - return false - } - } - - emitter.open_ended = false - - var chomp_hint [1]byte - if len(value) == 0 { - chomp_hint[0] = '-' - } else { - i := len(value) - 1 - for value[i]&0xC0 == 0x80 { - i-- - } - if !is_break(value, i) { - chomp_hint[0] = '-' - } else if i == 0 { - chomp_hint[0] = '+' - emitter.open_ended = true - } else { - i-- - for value[i]&0xC0 == 0x80 { - i-- - } - if is_break(value, i) { - chomp_hint[0] = '+' - emitter.open_ended = true - } - } - } - if chomp_hint[0] != 0 { - if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { - return false - } - } - return true -} - -func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - if !put_break(emitter) { - return false - } - emitter.indention = true - emitter.whitespace = true - breaks := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !write_break(emitter, value, &i) { - return false - } - emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - breaks = false - } - } - - return true -} - -func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - - if !put_break(emitter) { - return false - } - emitter.indention = true - emitter.whitespace = true - - breaks := true - leading_spaces := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !breaks && !leading_spaces && value[i] == '\n' { - k := 0 - for is_break(value, k) { - k += width(value[k]) - } - if !is_blankz(value, k) { - if !put_break(emitter) { - return false - } - } - } - if !write_break(emitter, value, &i) { - return false - } - emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - leading_spaces = is_blank(value, i) - } - if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - emitter.indention = false - breaks = false - } - } - return true -} diff --git a/vendor/gopkg.in/yaml.v2/encode.go b/vendor/gopkg.in/yaml.v2/encode.go deleted file mode 100644 index 0ee738e1..00000000 --- a/vendor/gopkg.in/yaml.v2/encode.go +++ /dev/null @@ -1,390 +0,0 @@ -package yaml - -import ( - "encoding" - "fmt" - "io" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -// jsonNumber is the interface of the encoding/json.Number datatype. -// Repeating the interface here avoids a dependency on encoding/json, and also -// supports other libraries like jsoniter, which use a similar datatype with -// the same interface. Detecting this interface is useful when dealing with -// structures containing json.Number, which is a string under the hood. The -// encoder should prefer the use of Int64(), Float64() and string(), in that -// order, when encoding this type. -type jsonNumber interface { - Float64() (float64, error) - Int64() (int64, error) - String() string -} - -type encoder struct { - emitter yaml_emitter_t - event yaml_event_t - out []byte - flow bool - // doneInit holds whether the initial stream_start_event has been - // emitted. - doneInit bool -} - -func newEncoder() *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_string(&e.emitter, &e.out) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func newEncoderWithWriter(w io.Writer) *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_writer(&e.emitter, w) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func (e *encoder) init() { - if e.doneInit { - return - } - yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) - e.emit() - e.doneInit = true -} - -func (e *encoder) finish() { - e.emitter.open_ended = false - yaml_stream_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) destroy() { - yaml_emitter_delete(&e.emitter) -} - -func (e *encoder) emit() { - // This will internally delete the e.event value. - e.must(yaml_emitter_emit(&e.emitter, &e.event)) -} - -func (e *encoder) must(ok bool) { - if !ok { - msg := e.emitter.problem - if msg == "" { - msg = "unknown problem generating YAML content" - } - failf("%s", msg) - } -} - -func (e *encoder) marshalDoc(tag string, in reflect.Value) { - e.init() - yaml_document_start_event_initialize(&e.event, nil, nil, true) - e.emit() - e.marshal(tag, in) - yaml_document_end_event_initialize(&e.event, true) - e.emit() -} - -func (e *encoder) marshal(tag string, in reflect.Value) { - if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { - e.nilv() - return - } - iface := in.Interface() - switch m := iface.(type) { - case jsonNumber: - integer, err := m.Int64() - if err == nil { - // In this case the json.Number is a valid int64 - in = reflect.ValueOf(integer) - break - } - float, err := m.Float64() - if err == nil { - // In this case the json.Number is a valid float64 - in = reflect.ValueOf(float) - break - } - // fallback case - no number could be obtained - in = reflect.ValueOf(m.String()) - case time.Time, *time.Time: - // Although time.Time implements TextMarshaler, - // we don't want to treat it as a string for YAML - // purposes because YAML has special support for - // timestamps. - case Marshaler: - v, err := m.MarshalYAML() - if err != nil { - fail(err) - } - if v == nil { - e.nilv() - return - } - in = reflect.ValueOf(v) - case encoding.TextMarshaler: - text, err := m.MarshalText() - if err != nil { - fail(err) - } - in = reflect.ValueOf(string(text)) - case nil: - e.nilv() - return - } - switch in.Kind() { - case reflect.Interface: - e.marshal(tag, in.Elem()) - case reflect.Map: - e.mapv(tag, in) - case reflect.Ptr: - if in.Type() == ptrTimeType { - e.timev(tag, in.Elem()) - } else { - e.marshal(tag, in.Elem()) - } - case reflect.Struct: - if in.Type() == timeType { - e.timev(tag, in) - } else { - e.structv(tag, in) - } - case reflect.Slice, reflect.Array: - if in.Type().Elem() == mapItemType { - e.itemsv(tag, in) - } else { - e.slicev(tag, in) - } - case reflect.String: - e.stringv(tag, in) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - if in.Type() == durationType { - e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) - } else { - e.intv(tag, in) - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - e.uintv(tag, in) - case reflect.Float32, reflect.Float64: - e.floatv(tag, in) - case reflect.Bool: - e.boolv(tag, in) - default: - panic("cannot marshal type: " + in.Type().String()) - } -} - -func (e *encoder) mapv(tag string, in reflect.Value) { - e.mappingv(tag, func() { - keys := keyList(in.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - e.marshal("", k) - e.marshal("", in.MapIndex(k)) - } - }) -} - -func (e *encoder) itemsv(tag string, in reflect.Value) { - e.mappingv(tag, func() { - slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) - for _, item := range slice { - e.marshal("", reflect.ValueOf(item.Key)) - e.marshal("", reflect.ValueOf(item.Value)) - } - }) -} - -func (e *encoder) structv(tag string, in reflect.Value) { - sinfo, err := getStructInfo(in.Type()) - if err != nil { - panic(err) - } - e.mappingv(tag, func() { - for _, info := range sinfo.FieldsList { - var value reflect.Value - if info.Inline == nil { - value = in.Field(info.Num) - } else { - value = in.FieldByIndex(info.Inline) - } - if info.OmitEmpty && isZero(value) { - continue - } - e.marshal("", reflect.ValueOf(info.Key)) - e.flow = info.Flow - e.marshal("", value) - } - if sinfo.InlineMap >= 0 { - m := in.Field(sinfo.InlineMap) - if m.Len() > 0 { - e.flow = false - keys := keyList(m.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - if _, found := sinfo.FieldsMap[k.String()]; found { - panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String())) - } - e.marshal("", k) - e.flow = false - e.marshal("", m.MapIndex(k)) - } - } - } - }) -} - -func (e *encoder) mappingv(tag string, f func()) { - implicit := tag == "" - style := yaml_BLOCK_MAPPING_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_MAPPING_STYLE - } - yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) - e.emit() - f() - yaml_mapping_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) slicev(tag string, in reflect.Value) { - implicit := tag == "" - style := yaml_BLOCK_SEQUENCE_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_SEQUENCE_STYLE - } - e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) - e.emit() - n := in.Len() - for i := 0; i < n; i++ { - e.marshal("", in.Index(i)) - } - e.must(yaml_sequence_end_event_initialize(&e.event)) - e.emit() -} - -// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. -// -// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported -// in YAML 1.2 and by this package, but these should be marshalled quoted for -// the time being for compatibility with other parsers. -func isBase60Float(s string) (result bool) { - // Fast path. - if s == "" { - return false - } - c := s[0] - if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { - return false - } - // Do the full match. - return base60float.MatchString(s) -} - -// From http://yaml.org/type/float.html, except the regular expression there -// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. -var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) - -func (e *encoder) stringv(tag string, in reflect.Value) { - var style yaml_scalar_style_t - s := in.String() - canUsePlain := true - switch { - case !utf8.ValidString(s): - if tag == yaml_BINARY_TAG { - failf("explicitly tagged !!binary data must be base64-encoded") - } - if tag != "" { - failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) - } - // It can't be encoded directly as YAML so use a binary tag - // and encode it as base64. - tag = yaml_BINARY_TAG - s = encodeBase64(s) - case tag == "": - // Check to see if it would resolve to a specific - // tag when encoded unquoted. If it doesn't, - // there's no need to quote it. - rtag, _ := resolve("", s) - canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s) - } - // Note: it's possible for user code to emit invalid YAML - // if they explicitly specify a tag and a string containing - // text that's incompatible with that tag. - switch { - case strings.Contains(s, "\n"): - style = yaml_LITERAL_SCALAR_STYLE - case canUsePlain: - style = yaml_PLAIN_SCALAR_STYLE - default: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - e.emitScalar(s, "", tag, style) -} - -func (e *encoder) boolv(tag string, in reflect.Value) { - var s string - if in.Bool() { - s = "true" - } else { - s = "false" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) -} - -func (e *encoder) intv(tag string, in reflect.Value) { - s := strconv.FormatInt(in.Int(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) -} - -func (e *encoder) uintv(tag string, in reflect.Value) { - s := strconv.FormatUint(in.Uint(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) -} - -func (e *encoder) timev(tag string, in reflect.Value) { - t := in.Interface().(time.Time) - s := t.Format(time.RFC3339Nano) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) -} - -func (e *encoder) floatv(tag string, in reflect.Value) { - // Issue #352: When formatting, use the precision of the underlying value - precision := 64 - if in.Kind() == reflect.Float32 { - precision = 32 - } - - s := strconv.FormatFloat(in.Float(), 'g', -1, precision) - switch s { - case "+Inf": - s = ".inf" - case "-Inf": - s = "-.inf" - case "NaN": - s = ".nan" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) -} - -func (e *encoder) nilv() { - e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) -} - -func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { - implicit := tag == "" - e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) - e.emit() -} diff --git a/vendor/gopkg.in/yaml.v2/parserc.go b/vendor/gopkg.in/yaml.v2/parserc.go deleted file mode 100644 index 81d05dfe..00000000 --- a/vendor/gopkg.in/yaml.v2/parserc.go +++ /dev/null @@ -1,1095 +0,0 @@ -package yaml - -import ( - "bytes" -) - -// The parser implements the following grammar: -// -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// implicit_document ::= block_node DOCUMENT-END* -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// block_node_or_indentless_sequence ::= -// ALIAS -// | properties (block_content | indentless_block_sequence)? -// | block_content -// | indentless_block_sequence -// block_node ::= ALIAS -// | properties block_content? -// | block_content -// flow_node ::= ALIAS -// | properties flow_content? -// | flow_content -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// block_content ::= block_collection | flow_collection | SCALAR -// flow_content ::= flow_collection | SCALAR -// block_collection ::= block_sequence | block_mapping -// flow_collection ::= flow_sequence | flow_mapping -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// block_mapping ::= BLOCK-MAPPING_START -// ((KEY block_node_or_indentless_sequence?)? -// (VALUE block_node_or_indentless_sequence?)?)* -// BLOCK-END -// flow_sequence ::= FLOW-SEQUENCE-START -// (flow_sequence_entry FLOW-ENTRY)* -// flow_sequence_entry? -// FLOW-SEQUENCE-END -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// flow_mapping ::= FLOW-MAPPING-START -// (flow_mapping_entry FLOW-ENTRY)* -// flow_mapping_entry? -// FLOW-MAPPING-END -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? - -// Peek the next token in the token queue. -func peek_token(parser *yaml_parser_t) *yaml_token_t { - if parser.token_available || yaml_parser_fetch_more_tokens(parser) { - return &parser.tokens[parser.tokens_head] - } - return nil -} - -// Remove the next token from the queue (must be called after peek_token). -func skip_token(parser *yaml_parser_t) { - parser.token_available = false - parser.tokens_parsed++ - parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN - parser.tokens_head++ -} - -// Get the next event. -func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { - // Erase the event object. - *event = yaml_event_t{} - - // No events after the end of the stream or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { - return true - } - - // Generate the next event. - return yaml_parser_state_machine(parser, event) -} - -// Set parser error. -func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -// State dispatcher. -func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { - //trace("yaml_parser_state_machine", "state:", parser.state.String()) - - switch parser.state { - case yaml_PARSE_STREAM_START_STATE: - return yaml_parser_parse_stream_start(parser, event) - - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, true) - - case yaml_PARSE_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, false) - - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return yaml_parser_parse_document_content(parser, event) - - case yaml_PARSE_DOCUMENT_END_STATE: - return yaml_parser_parse_document_end(parser, event) - - case yaml_PARSE_BLOCK_NODE_STATE: - return yaml_parser_parse_node(parser, event, true, false) - - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return yaml_parser_parse_node(parser, event, true, true) - - case yaml_PARSE_FLOW_NODE_STATE: - return yaml_parser_parse_node(parser, event, false, false) - - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, true) - - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, false) - - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_indentless_sequence_entry(parser, event) - - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, true) - - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, false) - - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return yaml_parser_parse_block_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, true) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, false) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) - - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, true) - - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, true) - - default: - panic("invalid parser state") - } -} - -// Parse the production: -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// ************ -func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_STREAM_START_TOKEN { - return yaml_parser_set_parser_error(parser, "did not find expected <stream-start>", token.start_mark) - } - parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - encoding: token.encoding, - } - skip_token(parser) - return true -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// * -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// ************************* -func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { - - token := peek_token(parser) - if token == nil { - return false - } - - // Parse extra document end indicators. - if !implicit { - for token.typ == yaml_DOCUMENT_END_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && - token.typ != yaml_TAG_DIRECTIVE_TOKEN && - token.typ != yaml_DOCUMENT_START_TOKEN && - token.typ != yaml_STREAM_END_TOKEN { - // Parse an implicit document. - if !yaml_parser_process_directives(parser, nil, nil) { - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_BLOCK_NODE_STATE - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - - } else if token.typ != yaml_STREAM_END_TOKEN { - // Parse an explicit document. - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - start_mark := token.start_mark - if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { - return false - } - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_DOCUMENT_START_TOKEN { - yaml_parser_set_parser_error(parser, - "did not find expected <document start>", token.start_mark) - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE - end_mark := token.end_mark - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: false, - } - skip_token(parser) - - } else { - // Parse the stream end. - parser.state = yaml_PARSE_END_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - skip_token(parser) - } - - return true -} - -// Parse the productions: -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// *********** -// -func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || - token.typ == yaml_TAG_DIRECTIVE_TOKEN || - token.typ == yaml_DOCUMENT_START_TOKEN || - token.typ == yaml_DOCUMENT_END_TOKEN || - token.typ == yaml_STREAM_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - return yaml_parser_process_empty_scalar(parser, event, - token.start_mark) - } - return yaml_parser_parse_node(parser, event, true, false) -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// ************* -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// -func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - start_mark := token.start_mark - end_mark := token.start_mark - - implicit := true - if token.typ == yaml_DOCUMENT_END_TOKEN { - end_mark = token.end_mark - skip_token(parser) - implicit = false - } - - parser.tag_directives = parser.tag_directives[:0] - - parser.state = yaml_PARSE_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - start_mark: start_mark, - end_mark: end_mark, - implicit: implicit, - } - return true -} - -// Parse the productions: -// block_node_or_indentless_sequence ::= -// ALIAS -// ***** -// | properties (block_content | indentless_block_sequence)? -// ********** * -// | block_content | indentless_block_sequence -// * -// block_node ::= ALIAS -// ***** -// | properties block_content? -// ********** * -// | block_content -// * -// flow_node ::= ALIAS -// ***** -// | properties flow_content? -// ********** * -// | flow_content -// * -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// ************************* -// block_content ::= block_collection | flow_collection | SCALAR -// ****** -// flow_content ::= flow_collection | SCALAR -// ****** -func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { - //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_ALIAS_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - *event = yaml_event_t{ - typ: yaml_ALIAS_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - anchor: token.value, - } - skip_token(parser) - return true - } - - start_mark := token.start_mark - end_mark := token.start_mark - - var tag_token bool - var tag_handle, tag_suffix, anchor []byte - var tag_mark yaml_mark_t - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - start_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } else if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - start_mark = token.start_mark - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - var tag []byte - if tag_token { - if len(tag_handle) == 0 { - tag = tag_suffix - tag_suffix = nil - } else { - for i := range parser.tag_directives { - if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { - tag = append([]byte(nil), parser.tag_directives[i].prefix...) - tag = append(tag, tag_suffix...) - break - } - } - if len(tag) == 0 { - yaml_parser_set_parser_error_context(parser, - "while parsing a node", start_mark, - "found undefined tag handle", tag_mark) - return false - } - } - } - - implicit := len(tag) == 0 - if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - return true - } - if token.typ == yaml_SCALAR_TOKEN { - var plain_implicit, quoted_implicit bool - end_mark = token.end_mark - if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { - plain_implicit = true - } else if len(tag) == 0 { - quoted_implicit = true - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - value: token.value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(token.style), - } - skip_token(parser) - return true - } - if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { - // [Go] Some of the events below can be merged as they differ only on style. - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), - } - return true - } - if token.typ == yaml_FLOW_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - return true - } - if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - return true - } - if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), - } - return true - } - if len(anchor) > 0 || len(tag) > 0 { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - quoted_implicit: false, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true - } - - context := "while parsing a flow node" - if block { - context = "while parsing a block node" - } - yaml_parser_set_parser_error_context(parser, context, start_mark, - "did not find expected node content", token.start_mark) - return false -} - -// Parse the productions: -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// ******************** *********** * ********* -// -func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } else { - parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } - if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block collection", context_mark, - "did not find expected '-' indicator", token.start_mark) -} - -// Parse the productions: -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// *********** * -func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && - token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? - } - return true -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// ******************* -// ((KEY block_node_or_indentless_sequence?)? -// *** * -// (VALUE block_node_or_indentless_sequence?)?)* -// -// BLOCK-END -// ********* -// -func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_KEY_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } else { - parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } else if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block mapping", context_mark, - "did not find expected key", token.start_mark) -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// -// ((KEY block_node_or_indentless_sequence?)? -// -// (VALUE block_node_or_indentless_sequence?)?)* -// ***** * -// BLOCK-END -// -// -func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence ::= FLOW-SEQUENCE-START -// ******************* -// (flow_sequence_entry FLOW-ENTRY)* -// * ********** -// flow_sequence_entry? -// * -// FLOW-SEQUENCE-END -// ***************** -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * -// -func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow sequence", context_mark, - "did not find expected ',' or ']'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - implicit: true, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - skip_token(parser) - return true - } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - - skip_token(parser) - return true -} - -// -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// *** * -// -func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - mark := token.end_mark - skip_token(parser) - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// ***** * -// -func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * -// -func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? - } - return true -} - -// Parse the productions: -// flow_mapping ::= FLOW-MAPPING-START -// ****************** -// (flow_mapping_entry FLOW-ENTRY)* -// * ********** -// flow_mapping_entry? -// ****************** -// FLOW-MAPPING-END -// **************** -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * *** * -// -func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow mapping", context_mark, - "did not find expected ',' or '}'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } else { - parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - skip_token(parser) - return true -} - -// Parse the productions: -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * ***** * -// -func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { - token := peek_token(parser) - if token == nil { - return false - } - if empty { - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Generate an empty scalar event. -func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: mark, - end_mark: mark, - value: nil, // Empty - implicit: true, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true -} - -var default_tag_directives = []yaml_tag_directive_t{ - {[]byte("!"), []byte("!")}, - {[]byte("!!"), []byte("tag:yaml.org,2002:")}, -} - -// Parse directives. -func yaml_parser_process_directives(parser *yaml_parser_t, - version_directive_ref **yaml_version_directive_t, - tag_directives_ref *[]yaml_tag_directive_t) bool { - - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - - token := peek_token(parser) - if token == nil { - return false - } - - for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { - if version_directive != nil { - yaml_parser_set_parser_error(parser, - "found duplicate %YAML directive", token.start_mark) - return false - } - if token.major != 1 || token.minor != 1 { - yaml_parser_set_parser_error(parser, - "found incompatible YAML document", token.start_mark) - return false - } - version_directive = &yaml_version_directive_t{ - major: token.major, - minor: token.minor, - } - } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { - value := yaml_tag_directive_t{ - handle: token.value, - prefix: token.prefix, - } - if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { - return false - } - tag_directives = append(tag_directives, value) - } - - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - - for i := range default_tag_directives { - if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { - return false - } - } - - if version_directive_ref != nil { - *version_directive_ref = version_directive - } - if tag_directives_ref != nil { - *tag_directives_ref = tag_directives - } - return true -} - -// Append a tag directive to the directives stack. -func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { - for i := range parser.tag_directives { - if bytes.Equal(value.handle, parser.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) - } - } - - // [Go] I suspect the copy is unnecessary. This was likely done - // because there was no way to track ownership of the data. - value_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(value_copy.handle, value.handle) - copy(value_copy.prefix, value.prefix) - parser.tag_directives = append(parser.tag_directives, value_copy) - return true -} diff --git a/vendor/gopkg.in/yaml.v2/readerc.go b/vendor/gopkg.in/yaml.v2/readerc.go deleted file mode 100644 index 7c1f5fac..00000000 --- a/vendor/gopkg.in/yaml.v2/readerc.go +++ /dev/null @@ -1,412 +0,0 @@ -package yaml - -import ( - "io" -) - -// Set the reader error and return 0. -func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { - parser.error = yaml_READER_ERROR - parser.problem = problem - parser.problem_offset = offset - parser.problem_value = value - return false -} - -// Byte order marks. -const ( - bom_UTF8 = "\xef\xbb\xbf" - bom_UTF16LE = "\xff\xfe" - bom_UTF16BE = "\xfe\xff" -) - -// Determine the input stream encoding by checking the BOM symbol. If no BOM is -// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. -func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { - // Ensure that we had enough bytes in the raw buffer. - for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { - if !yaml_parser_update_raw_buffer(parser) { - return false - } - } - - // Determine the encoding. - buf := parser.raw_buffer - pos := parser.raw_buffer_pos - avail := len(buf) - pos - if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { - parser.encoding = yaml_UTF16LE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { - parser.encoding = yaml_UTF16BE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { - parser.encoding = yaml_UTF8_ENCODING - parser.raw_buffer_pos += 3 - parser.offset += 3 - } else { - parser.encoding = yaml_UTF8_ENCODING - } - return true -} - -// Update the raw buffer. -func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { - size_read := 0 - - // Return if the raw buffer is full. - if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { - return true - } - - // Return on EOF. - if parser.eof { - return true - } - - // Move the remaining bytes in the raw buffer to the beginning. - if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { - copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) - } - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] - parser.raw_buffer_pos = 0 - - // Call the read handler to fill the buffer. - size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] - if err == io.EOF { - parser.eof = true - } else if err != nil { - return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) - } - return true -} - -// Ensure that the buffer contains at least `length` characters. -// Return true on success, false on failure. -// -// The length is supposed to be significantly less that the buffer size. -func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { - if parser.read_handler == nil { - panic("read handler must be set") - } - - // [Go] This function was changed to guarantee the requested length size at EOF. - // The fact we need to do this is pretty awful, but the description above implies - // for that to be the case, and there are tests - - // If the EOF flag is set and the raw buffer is empty, do nothing. - if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { - // [Go] ACTUALLY! Read the documentation of this function above. - // This is just broken. To return true, we need to have the - // given length in the buffer. Not doing that means every single - // check that calls this function to make sure the buffer has a - // given length is Go) panicking; or C) accessing invalid memory. - //return true - } - - // Return if the buffer contains enough characters. - if parser.unread >= length { - return true - } - - // Determine the input encoding if it is not known yet. - if parser.encoding == yaml_ANY_ENCODING { - if !yaml_parser_determine_encoding(parser) { - return false - } - } - - // Move the unread characters to the beginning of the buffer. - buffer_len := len(parser.buffer) - if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { - copy(parser.buffer, parser.buffer[parser.buffer_pos:]) - buffer_len -= parser.buffer_pos - parser.buffer_pos = 0 - } else if parser.buffer_pos == buffer_len { - buffer_len = 0 - parser.buffer_pos = 0 - } - - // Open the whole buffer for writing, and cut it before returning. - parser.buffer = parser.buffer[:cap(parser.buffer)] - - // Fill the buffer until it has enough characters. - first := true - for parser.unread < length { - - // Fill the raw buffer if necessary. - if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { - if !yaml_parser_update_raw_buffer(parser) { - parser.buffer = parser.buffer[:buffer_len] - return false - } - } - first = false - - // Decode the raw buffer. - inner: - for parser.raw_buffer_pos != len(parser.raw_buffer) { - var value rune - var width int - - raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos - - // Decode the next character. - switch parser.encoding { - case yaml_UTF8_ENCODING: - // Decode a UTF-8 character. Check RFC 3629 - // (http://www.ietf.org/rfc/rfc3629.txt) for more details. - // - // The following table (taken from the RFC) is used for - // decoding. - // - // Char. number range | UTF-8 octet sequence - // (hexadecimal) | (binary) - // --------------------+------------------------------------ - // 0000 0000-0000 007F | 0xxxxxxx - // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - // - // Additionally, the characters in the range 0xD800-0xDFFF - // are prohibited as they are reserved for use with UTF-16 - // surrogate pairs. - - // Determine the length of the UTF-8 sequence. - octet := parser.raw_buffer[parser.raw_buffer_pos] - switch { - case octet&0x80 == 0x00: - width = 1 - case octet&0xE0 == 0xC0: - width = 2 - case octet&0xF0 == 0xE0: - width = 3 - case octet&0xF8 == 0xF0: - width = 4 - default: - // The leading octet is invalid. - return yaml_parser_set_reader_error(parser, - "invalid leading UTF-8 octet", - parser.offset, int(octet)) - } - - // Check if the raw buffer contains an incomplete character. - if width > raw_unread { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-8 octet sequence", - parser.offset, -1) - } - break inner - } - - // Decode the leading octet. - switch { - case octet&0x80 == 0x00: - value = rune(octet & 0x7F) - case octet&0xE0 == 0xC0: - value = rune(octet & 0x1F) - case octet&0xF0 == 0xE0: - value = rune(octet & 0x0F) - case octet&0xF8 == 0xF0: - value = rune(octet & 0x07) - default: - value = 0 - } - - // Check and decode the trailing octets. - for k := 1; k < width; k++ { - octet = parser.raw_buffer[parser.raw_buffer_pos+k] - - // Check if the octet is valid. - if (octet & 0xC0) != 0x80 { - return yaml_parser_set_reader_error(parser, - "invalid trailing UTF-8 octet", - parser.offset+k, int(octet)) - } - - // Decode the octet. - value = (value << 6) + rune(octet&0x3F) - } - - // Check the length of the sequence against the value. - switch { - case width == 1: - case width == 2 && value >= 0x80: - case width == 3 && value >= 0x800: - case width == 4 && value >= 0x10000: - default: - return yaml_parser_set_reader_error(parser, - "invalid length of a UTF-8 sequence", - parser.offset, -1) - } - - // Check the range of the value. - if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { - return yaml_parser_set_reader_error(parser, - "invalid Unicode character", - parser.offset, int(value)) - } - - case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: - var low, high int - if parser.encoding == yaml_UTF16LE_ENCODING { - low, high = 0, 1 - } else { - low, high = 1, 0 - } - - // The UTF-16 encoding is not as simple as one might - // naively think. Check RFC 2781 - // (http://www.ietf.org/rfc/rfc2781.txt). - // - // Normally, two subsequent bytes describe a Unicode - // character. However a special technique (called a - // surrogate pair) is used for specifying character - // values larger than 0xFFFF. - // - // A surrogate pair consists of two pseudo-characters: - // high surrogate area (0xD800-0xDBFF) - // low surrogate area (0xDC00-0xDFFF) - // - // The following formulas are used for decoding - // and encoding characters using surrogate pairs: - // - // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) - // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) - // W1 = 110110yyyyyyyyyy - // W2 = 110111xxxxxxxxxx - // - // where U is the character value, W1 is the high surrogate - // area, W2 is the low surrogate area. - - // Check for incomplete UTF-16 character. - if raw_unread < 2 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 character", - parser.offset, -1) - } - break inner - } - - // Get the character. - value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) - - // Check for unexpected low surrogate area. - if value&0xFC00 == 0xDC00 { - return yaml_parser_set_reader_error(parser, - "unexpected low surrogate area", - parser.offset, int(value)) - } - - // Check for a high surrogate area. - if value&0xFC00 == 0xD800 { - width = 4 - - // Check for incomplete surrogate pair. - if raw_unread < 4 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 surrogate pair", - parser.offset, -1) - } - break inner - } - - // Get the next character. - value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) - - // Check for a low surrogate area. - if value2&0xFC00 != 0xDC00 { - return yaml_parser_set_reader_error(parser, - "expected low surrogate area", - parser.offset+2, int(value2)) - } - - // Generate the value of the surrogate pair. - value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) - } else { - width = 2 - } - - default: - panic("impossible") - } - - // Check if the character is in the allowed range: - // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) - // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) - // | [#x10000-#x10FFFF] (32 bit) - switch { - case value == 0x09: - case value == 0x0A: - case value == 0x0D: - case value >= 0x20 && value <= 0x7E: - case value == 0x85: - case value >= 0xA0 && value <= 0xD7FF: - case value >= 0xE000 && value <= 0xFFFD: - case value >= 0x10000 && value <= 0x10FFFF: - default: - return yaml_parser_set_reader_error(parser, - "control characters are not allowed", - parser.offset, int(value)) - } - - // Move the raw pointers. - parser.raw_buffer_pos += width - parser.offset += width - - // Finally put the character into the buffer. - if value <= 0x7F { - // 0000 0000-0000 007F . 0xxxxxxx - parser.buffer[buffer_len+0] = byte(value) - buffer_len += 1 - } else if value <= 0x7FF { - // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) - parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) - buffer_len += 2 - } else if value <= 0xFFFF { - // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) - buffer_len += 3 - } else { - // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) - buffer_len += 4 - } - - parser.unread++ - } - - // On EOF, put NUL into the buffer and return. - if parser.eof { - parser.buffer[buffer_len] = 0 - buffer_len++ - parser.unread++ - break - } - } - // [Go] Read the documentation of this function above. To return true, - // we need to have the given length in the buffer. Not doing that means - // every single check that calls this function to make sure the buffer - // has a given length is Go) panicking; or C) accessing invalid memory. - // This happens here due to the EOF above breaking early. - for buffer_len < length { - parser.buffer[buffer_len] = 0 - buffer_len++ - } - parser.buffer = parser.buffer[:buffer_len] - return true -} diff --git a/vendor/gopkg.in/yaml.v2/resolve.go b/vendor/gopkg.in/yaml.v2/resolve.go deleted file mode 100644 index 4120e0c9..00000000 --- a/vendor/gopkg.in/yaml.v2/resolve.go +++ /dev/null @@ -1,258 +0,0 @@ -package yaml - -import ( - "encoding/base64" - "math" - "regexp" - "strconv" - "strings" - "time" -) - -type resolveMapItem struct { - value interface{} - tag string -} - -var resolveTable = make([]byte, 256) -var resolveMap = make(map[string]resolveMapItem) - -func init() { - t := resolveTable - t[int('+')] = 'S' // Sign - t[int('-')] = 'S' - for _, c := range "0123456789" { - t[int(c)] = 'D' // Digit - } - for _, c := range "yYnNtTfFoO~" { - t[int(c)] = 'M' // In map - } - t[int('.')] = '.' // Float (potentially in map) - - var resolveMapList = []struct { - v interface{} - tag string - l []string - }{ - {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, - {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, - {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, - {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, - {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, - {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, - {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, - {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, - {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, - {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, - {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, - {"<<", yaml_MERGE_TAG, []string{"<<"}}, - } - - m := resolveMap - for _, item := range resolveMapList { - for _, s := range item.l { - m[s] = resolveMapItem{item.v, item.tag} - } - } -} - -const longTagPrefix = "tag:yaml.org,2002:" - -func shortTag(tag string) string { - // TODO This can easily be made faster and produce less garbage. - if strings.HasPrefix(tag, longTagPrefix) { - return "!!" + tag[len(longTagPrefix):] - } - return tag -} - -func longTag(tag string) string { - if strings.HasPrefix(tag, "!!") { - return longTagPrefix + tag[2:] - } - return tag -} - -func resolvableTag(tag string) bool { - switch tag { - case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG: - return true - } - return false -} - -var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) - -func resolve(tag string, in string) (rtag string, out interface{}) { - if !resolvableTag(tag) { - return tag, in - } - - defer func() { - switch tag { - case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: - return - case yaml_FLOAT_TAG: - if rtag == yaml_INT_TAG { - switch v := out.(type) { - case int64: - rtag = yaml_FLOAT_TAG - out = float64(v) - return - case int: - rtag = yaml_FLOAT_TAG - out = float64(v) - return - } - } - } - failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) - }() - - // Any data is accepted as a !!str or !!binary. - // Otherwise, the prefix is enough of a hint about what it might be. - hint := byte('N') - if in != "" { - hint = resolveTable[in[0]] - } - if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { - // Handle things we can lookup in a map. - if item, ok := resolveMap[in]; ok { - return item.tag, item.value - } - - // Base 60 floats are a bad idea, were dropped in YAML 1.2, and - // are purposefully unsupported here. They're still quoted on - // the way out for compatibility with other parser, though. - - switch hint { - case 'M': - // We've already checked the map above. - - case '.': - // Not in the map, so maybe a normal float. - floatv, err := strconv.ParseFloat(in, 64) - if err == nil { - return yaml_FLOAT_TAG, floatv - } - - case 'D', 'S': - // Int, float, or timestamp. - // Only try values as a timestamp if the value is unquoted or there's an explicit - // !!timestamp tag. - if tag == "" || tag == yaml_TIMESTAMP_TAG { - t, ok := parseTimestamp(in) - if ok { - return yaml_TIMESTAMP_TAG, t - } - } - - plain := strings.Replace(in, "_", "", -1) - intv, err := strconv.ParseInt(plain, 0, 64) - if err == nil { - if intv == int64(int(intv)) { - return yaml_INT_TAG, int(intv) - } else { - return yaml_INT_TAG, intv - } - } - uintv, err := strconv.ParseUint(plain, 0, 64) - if err == nil { - return yaml_INT_TAG, uintv - } - if yamlStyleFloat.MatchString(plain) { - floatv, err := strconv.ParseFloat(plain, 64) - if err == nil { - return yaml_FLOAT_TAG, floatv - } - } - if strings.HasPrefix(plain, "0b") { - intv, err := strconv.ParseInt(plain[2:], 2, 64) - if err == nil { - if intv == int64(int(intv)) { - return yaml_INT_TAG, int(intv) - } else { - return yaml_INT_TAG, intv - } - } - uintv, err := strconv.ParseUint(plain[2:], 2, 64) - if err == nil { - return yaml_INT_TAG, uintv - } - } else if strings.HasPrefix(plain, "-0b") { - intv, err := strconv.ParseInt("-" + plain[3:], 2, 64) - if err == nil { - if true || intv == int64(int(intv)) { - return yaml_INT_TAG, int(intv) - } else { - return yaml_INT_TAG, intv - } - } - } - default: - panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") - } - } - return yaml_STR_TAG, in -} - -// encodeBase64 encodes s as base64 that is broken up into multiple lines -// as appropriate for the resulting length. -func encodeBase64(s string) string { - const lineLen = 70 - encLen := base64.StdEncoding.EncodedLen(len(s)) - lines := encLen/lineLen + 1 - buf := make([]byte, encLen*2+lines) - in := buf[0:encLen] - out := buf[encLen:] - base64.StdEncoding.Encode(in, []byte(s)) - k := 0 - for i := 0; i < len(in); i += lineLen { - j := i + lineLen - if j > len(in) { - j = len(in) - } - k += copy(out[k:], in[i:j]) - if lines > 1 { - out[k] = '\n' - k++ - } - } - return string(out[:k]) -} - -// This is a subset of the formats allowed by the regular expression -// defined at http://yaml.org/type/timestamp.html. -var allowedTimestampFormats = []string{ - "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. - "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". - "2006-1-2 15:4:5.999999999", // space separated with no time zone - "2006-1-2", // date only - // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" - // from the set of examples. -} - -// parseTimestamp parses s as a timestamp string and -// returns the timestamp and reports whether it succeeded. -// Timestamp formats are defined at http://yaml.org/type/timestamp.html -func parseTimestamp(s string) (time.Time, bool) { - // TODO write code to check all the formats supported by - // http://yaml.org/type/timestamp.html instead of using time.Parse. - - // Quick check: all date formats start with YYYY-. - i := 0 - for ; i < len(s); i++ { - if c := s[i]; c < '0' || c > '9' { - break - } - } - if i != 4 || i == len(s) || s[i] != '-' { - return time.Time{}, false - } - for _, format := range allowedTimestampFormats { - if t, err := time.Parse(format, s); err == nil { - return t, true - } - } - return time.Time{}, false -} diff --git a/vendor/gopkg.in/yaml.v2/scannerc.go b/vendor/gopkg.in/yaml.v2/scannerc.go deleted file mode 100644 index 0b9bb603..00000000 --- a/vendor/gopkg.in/yaml.v2/scannerc.go +++ /dev/null @@ -1,2711 +0,0 @@ -package yaml - -import ( - "bytes" - "fmt" -) - -// Introduction -// ************ -// -// The following notes assume that you are familiar with the YAML specification -// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in -// some cases we are less restrictive that it requires. -// -// The process of transforming a YAML stream into a sequence of events is -// divided on two steps: Scanning and Parsing. -// -// The Scanner transforms the input stream into a sequence of tokens, while the -// parser transform the sequence of tokens produced by the Scanner into a -// sequence of parsing events. -// -// The Scanner is rather clever and complicated. The Parser, on the contrary, -// is a straightforward implementation of a recursive-descendant parser (or, -// LL(1) parser, as it is usually called). -// -// Actually there are two issues of Scanning that might be called "clever", the -// rest is quite straightforward. The issues are "block collection start" and -// "simple keys". Both issues are explained below in details. -// -// Here the Scanning step is explained and implemented. We start with the list -// of all the tokens produced by the Scanner together with short descriptions. -// -// Now, tokens: -// -// STREAM-START(encoding) # The stream start. -// STREAM-END # The stream end. -// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. -// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. -// DOCUMENT-START # '---' -// DOCUMENT-END # '...' -// BLOCK-SEQUENCE-START # Indentation increase denoting a block -// BLOCK-MAPPING-START # sequence or a block mapping. -// BLOCK-END # Indentation decrease. -// FLOW-SEQUENCE-START # '[' -// FLOW-SEQUENCE-END # ']' -// BLOCK-SEQUENCE-START # '{' -// BLOCK-SEQUENCE-END # '}' -// BLOCK-ENTRY # '-' -// FLOW-ENTRY # ',' -// KEY # '?' or nothing (simple keys). -// VALUE # ':' -// ALIAS(anchor) # '*anchor' -// ANCHOR(anchor) # '&anchor' -// TAG(handle,suffix) # '!handle!suffix' -// SCALAR(value,style) # A scalar. -// -// The following two tokens are "virtual" tokens denoting the beginning and the -// end of the stream: -// -// STREAM-START(encoding) -// STREAM-END -// -// We pass the information about the input stream encoding with the -// STREAM-START token. -// -// The next two tokens are responsible for tags: -// -// VERSION-DIRECTIVE(major,minor) -// TAG-DIRECTIVE(handle,prefix) -// -// Example: -// -// %YAML 1.1 -// %TAG ! !foo -// %TAG !yaml! tag:yaml.org,2002: -// --- -// -// The correspoding sequence of tokens: -// -// STREAM-START(utf-8) -// VERSION-DIRECTIVE(1,1) -// TAG-DIRECTIVE("!","!foo") -// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") -// DOCUMENT-START -// STREAM-END -// -// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole -// line. -// -// The document start and end indicators are represented by: -// -// DOCUMENT-START -// DOCUMENT-END -// -// Note that if a YAML stream contains an implicit document (without '---' -// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be -// produced. -// -// In the following examples, we present whole documents together with the -// produced tokens. -// -// 1. An implicit document: -// -// 'a scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// STREAM-END -// -// 2. An explicit document: -// -// --- -// 'a scalar' -// ... -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// SCALAR("a scalar",single-quoted) -// DOCUMENT-END -// STREAM-END -// -// 3. Several documents in a stream: -// -// 'a scalar' -// --- -// 'another scalar' -// --- -// 'yet another scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// DOCUMENT-START -// SCALAR("another scalar",single-quoted) -// DOCUMENT-START -// SCALAR("yet another scalar",single-quoted) -// STREAM-END -// -// We have already introduced the SCALAR token above. The following tokens are -// used to describe aliases, anchors, tag, and scalars: -// -// ALIAS(anchor) -// ANCHOR(anchor) -// TAG(handle,suffix) -// SCALAR(value,style) -// -// The following series of examples illustrate the usage of these tokens: -// -// 1. A recursive sequence: -// -// &A [ *A ] -// -// Tokens: -// -// STREAM-START(utf-8) -// ANCHOR("A") -// FLOW-SEQUENCE-START -// ALIAS("A") -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A tagged scalar: -// -// !!float "3.14" # A good approximation. -// -// Tokens: -// -// STREAM-START(utf-8) -// TAG("!!","float") -// SCALAR("3.14",double-quoted) -// STREAM-END -// -// 3. Various scalar styles: -// -// --- # Implicit empty plain scalars do not produce tokens. -// --- a plain scalar -// --- 'a single-quoted scalar' -// --- "a double-quoted scalar" -// --- |- -// a literal scalar -// --- >- -// a folded -// scalar -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// DOCUMENT-START -// SCALAR("a plain scalar",plain) -// DOCUMENT-START -// SCALAR("a single-quoted scalar",single-quoted) -// DOCUMENT-START -// SCALAR("a double-quoted scalar",double-quoted) -// DOCUMENT-START -// SCALAR("a literal scalar",literal) -// DOCUMENT-START -// SCALAR("a folded scalar",folded) -// STREAM-END -// -// Now it's time to review collection-related tokens. We will start with -// flow collections: -// -// FLOW-SEQUENCE-START -// FLOW-SEQUENCE-END -// FLOW-MAPPING-START -// FLOW-MAPPING-END -// FLOW-ENTRY -// KEY -// VALUE -// -// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and -// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' -// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the -// indicators '?' and ':', which are used for denoting mapping keys and values, -// are represented by the KEY and VALUE tokens. -// -// The following examples show flow collections: -// -// 1. A flow sequence: -// -// [item 1, item 2, item 3] -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-SEQUENCE-START -// SCALAR("item 1",plain) -// FLOW-ENTRY -// SCALAR("item 2",plain) -// FLOW-ENTRY -// SCALAR("item 3",plain) -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A flow mapping: -// -// { -// a simple key: a value, # Note that the KEY token is produced. -// ? a complex key: another value, -// } -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// FLOW-ENTRY -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// FLOW-ENTRY -// FLOW-MAPPING-END -// STREAM-END -// -// A simple key is a key which is not denoted by the '?' indicator. Note that -// the Scanner still produce the KEY token whenever it encounters a simple key. -// -// For scanning block collections, the following tokens are used (note that we -// repeat KEY and VALUE here): -// -// BLOCK-SEQUENCE-START -// BLOCK-MAPPING-START -// BLOCK-END -// BLOCK-ENTRY -// KEY -// VALUE -// -// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation -// increase that precedes a block collection (cf. the INDENT token in Python). -// The token BLOCK-END denote indentation decrease that ends a block collection -// (cf. the DEDENT token in Python). However YAML has some syntax pecularities -// that makes detections of these tokens more complex. -// -// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators -// '-', '?', and ':' correspondingly. -// -// The following examples show how the tokens BLOCK-SEQUENCE-START, -// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: -// -// 1. Block sequences: -// -// - item 1 -// - item 2 -// - -// - item 3.1 -// - item 3.2 -// - -// key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 3.1",plain) -// BLOCK-ENTRY -// SCALAR("item 3.2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Block mappings: -// -// a simple key: a value # The KEY token is produced here. -// ? a complex key -// : another value -// a mapping: -// key 1: value 1 -// key 2: value 2 -// a sequence: -// - item 1 -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// KEY -// SCALAR("a mapping",plain) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML does not always require to start a new block collection from a new -// line. If the current line contains only '-', '?', and ':' indicators, a new -// block collection may start at the current line. The following examples -// illustrate this case: -// -// 1. Collections in a sequence: -// -// - - item 1 -// - item 2 -// - key 1: value 1 -// key 2: value 2 -// - ? complex key -// : complex value -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("complex key") -// VALUE -// SCALAR("complex value") -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Collections in a mapping: -// -// ? a sequence -// : - item 1 -// - item 2 -// ? a mapping -// : key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// KEY -// SCALAR("a mapping",plain) -// VALUE -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML also permits non-indented sequences if they are included into a block -// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: -// -// key: -// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key",plain) -// VALUE -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// - -// Ensure that the buffer contains the required number of characters. -// Return true on success, false on failure (reader error or memory error). -func cache(parser *yaml_parser_t, length int) bool { - // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) - return parser.unread >= length || yaml_parser_update_buffer(parser, length) -} - -// Advance the buffer pointer. -func skip(parser *yaml_parser_t) { - parser.mark.index++ - parser.mark.column++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) -} - -func skip_line(parser *yaml_parser_t) { - if is_crlf(parser.buffer, parser.buffer_pos) { - parser.mark.index += 2 - parser.mark.column = 0 - parser.mark.line++ - parser.unread -= 2 - parser.buffer_pos += 2 - } else if is_break(parser.buffer, parser.buffer_pos) { - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) - } -} - -// Copy a character to a string buffer and advance pointers. -func read(parser *yaml_parser_t, s []byte) []byte { - w := width(parser.buffer[parser.buffer_pos]) - if w == 0 { - panic("invalid character sequence") - } - if len(s) == 0 { - s = make([]byte, 0, 32) - } - if w == 1 && len(s)+w <= cap(s) { - s = s[:len(s)+1] - s[len(s)-1] = parser.buffer[parser.buffer_pos] - parser.buffer_pos++ - } else { - s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) - parser.buffer_pos += w - } - parser.mark.index++ - parser.mark.column++ - parser.unread-- - return s -} - -// Copy a line break character to a string buffer and advance pointers. -func read_line(parser *yaml_parser_t, s []byte) []byte { - buf := parser.buffer - pos := parser.buffer_pos - switch { - case buf[pos] == '\r' && buf[pos+1] == '\n': - // CR LF . LF - s = append(s, '\n') - parser.buffer_pos += 2 - parser.mark.index++ - parser.unread-- - case buf[pos] == '\r' || buf[pos] == '\n': - // CR|LF . LF - s = append(s, '\n') - parser.buffer_pos += 1 - case buf[pos] == '\xC2' && buf[pos+1] == '\x85': - // NEL . LF - s = append(s, '\n') - parser.buffer_pos += 2 - case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): - // LS|PS . LS|PS - s = append(s, buf[parser.buffer_pos:pos+3]...) - parser.buffer_pos += 3 - default: - return s - } - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - return s -} - -// Get the next token. -func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { - // Erase the token object. - *token = yaml_token_t{} // [Go] Is this necessary? - - // No tokens after STREAM-END or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR { - return true - } - - // Ensure that the tokens queue contains enough tokens. - if !parser.token_available { - if !yaml_parser_fetch_more_tokens(parser) { - return false - } - } - - // Fetch the next token from the queue. - *token = parser.tokens[parser.tokens_head] - parser.tokens_head++ - parser.tokens_parsed++ - parser.token_available = false - - if token.typ == yaml_STREAM_END_TOKEN { - parser.stream_end_produced = true - } - return true -} - -// Set the scanner error and return false. -func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { - parser.error = yaml_SCANNER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = parser.mark - return false -} - -func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { - context := "while parsing a tag" - if directive { - context = "while parsing a %TAG directive" - } - return yaml_parser_set_scanner_error(parser, context, context_mark, problem) -} - -func trace(args ...interface{}) func() { - pargs := append([]interface{}{"+++"}, args...) - fmt.Println(pargs...) - pargs = append([]interface{}{"---"}, args...) - return func() { fmt.Println(pargs...) } -} - -// Ensure that the tokens queue contains at least one token which can be -// returned to the Parser. -func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { - // While we need more tokens to fetch, do it. - for { - if parser.tokens_head != len(parser.tokens) { - // If queue is non-empty, check if any potential simple key may - // occupy the head position. - head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] - if !ok { - break - } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { - return false - } else if !valid { - break - } - } - // Fetch the next token. - if !yaml_parser_fetch_next_token(parser) { - return false - } - } - - parser.token_available = true - return true -} - -// The dispatcher for token fetchers. -func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { - // Ensure that the buffer is initialized. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we just started scanning. Fetch STREAM-START then. - if !parser.stream_start_produced { - return yaml_parser_fetch_stream_start(parser) - } - - // Eat whitespaces and comments until we reach the next token. - if !yaml_parser_scan_to_next_token(parser) { - return false - } - - // Check the indentation level against the current column. - if !yaml_parser_unroll_indent(parser, parser.mark.column) { - return false - } - - // Ensure that the buffer contains at least 4 characters. 4 is the length - // of the longest indicators ('--- ' and '... '). - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - // Is it the end of the stream? - if is_z(parser.buffer, parser.buffer_pos) { - return yaml_parser_fetch_stream_end(parser) - } - - // Is it a directive? - if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { - return yaml_parser_fetch_directive(parser) - } - - buf := parser.buffer - pos := parser.buffer_pos - - // Is it the document start indicator? - if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) - } - - // Is it the document end indicator? - if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) - } - - // Is it the flow sequence start indicator? - if buf[pos] == '[' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) - } - - // Is it the flow mapping start indicator? - if parser.buffer[parser.buffer_pos] == '{' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) - } - - // Is it the flow sequence end indicator? - if parser.buffer[parser.buffer_pos] == ']' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_SEQUENCE_END_TOKEN) - } - - // Is it the flow mapping end indicator? - if parser.buffer[parser.buffer_pos] == '}' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_MAPPING_END_TOKEN) - } - - // Is it the flow entry indicator? - if parser.buffer[parser.buffer_pos] == ',' { - return yaml_parser_fetch_flow_entry(parser) - } - - // Is it the block entry indicator? - if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { - return yaml_parser_fetch_block_entry(parser) - } - - // Is it the key indicator? - if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_key(parser) - } - - // Is it the value indicator? - if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_value(parser) - } - - // Is it an alias? - if parser.buffer[parser.buffer_pos] == '*' { - return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) - } - - // Is it an anchor? - if parser.buffer[parser.buffer_pos] == '&' { - return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) - } - - // Is it a tag? - if parser.buffer[parser.buffer_pos] == '!' { - return yaml_parser_fetch_tag(parser) - } - - // Is it a literal scalar? - if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, true) - } - - // Is it a folded scalar? - if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, false) - } - - // Is it a single-quoted scalar? - if parser.buffer[parser.buffer_pos] == '\'' { - return yaml_parser_fetch_flow_scalar(parser, true) - } - - // Is it a double-quoted scalar? - if parser.buffer[parser.buffer_pos] == '"' { - return yaml_parser_fetch_flow_scalar(parser, false) - } - - // Is it a plain scalar? - // - // A plain scalar may start with any non-blank characters except - // - // '-', '?', ':', ',', '[', ']', '{', '}', - // '#', '&', '*', '!', '|', '>', '\'', '\"', - // '%', '@', '`'. - // - // In the block context (and, for the '-' indicator, in the flow context - // too), it may also start with the characters - // - // '-', '?', ':' - // - // if it is followed by a non-space character. - // - // The last rule is more restrictive than the specification requires. - // [Go] Make this logic more reasonable. - //switch parser.buffer[parser.buffer_pos] { - //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': - //} - if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || - parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || - parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || - (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level == 0 && - (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && - !is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_plain_scalar(parser) - } - - // If we don't determine the token type so far, it is an error. - return yaml_parser_set_scanner_error(parser, - "while scanning for the next token", parser.mark, - "found character that cannot start any token") -} - -func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { - if !simple_key.possible { - return false, true - } - - // The 1.2 specification says: - // - // "If the ? indicator is omitted, parsing needs to see past the - // implicit key to recognize it as such. To limit the amount of - // lookahead required, the “:” indicator must appear at most 1024 - // Unicode characters beyond the start of the key. In addition, the key - // is restricted to a single line." - // - if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { - // Check if the potential simple key to be removed is required. - if simple_key.required { - return false, yaml_parser_set_scanner_error(parser, - "while scanning a simple key", simple_key.mark, - "could not find expected ':'") - } - simple_key.possible = false - return false, true - } - return true, true -} - -// Check if a simple key may start at the current position and add it if -// needed. -func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { - // A simple key is required at the current position if the scanner is in - // the block context and the current column coincides with the indentation - // level. - - required := parser.flow_level == 0 && parser.indent == parser.mark.column - - // - // If the current position may start a simple key, save it. - // - if parser.simple_key_allowed { - simple_key := yaml_simple_key_t{ - possible: true, - required: required, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - } - - if !yaml_parser_remove_simple_key(parser) { - return false - } - parser.simple_keys[len(parser.simple_keys)-1] = simple_key - parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 - } - return true -} - -// Remove a potential simple key at the current flow level. -func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { - i := len(parser.simple_keys) - 1 - if parser.simple_keys[i].possible { - // If the key is required, it is an error. - if parser.simple_keys[i].required { - return yaml_parser_set_scanner_error(parser, - "while scanning a simple key", parser.simple_keys[i].mark, - "could not find expected ':'") - } - // Remove the key from the stack. - parser.simple_keys[i].possible = false - delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) - } - return true -} - -// max_flow_level limits the flow_level -const max_flow_level = 10000 - -// Increase the flow level and resize the simple key list if needed. -func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { - // Reset the simple key on the next level. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ - possible: false, - required: false, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - }) - - // Increase the flow level. - parser.flow_level++ - if parser.flow_level > max_flow_level { - return yaml_parser_set_scanner_error(parser, - "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_flow_level)) - } - return true -} - -// Decrease the flow level. -func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { - if parser.flow_level > 0 { - parser.flow_level-- - last := len(parser.simple_keys) - 1 - delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) - parser.simple_keys = parser.simple_keys[:last] - } - return true -} - -// max_indents limits the indents stack size -const max_indents = 10000 - -// Push the current indentation level to the stack and set the new level -// the current column is greater than the indentation level. In this case, -// append or insert the specified token into the token queue. -func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - if parser.indent < column { - // Push the current indentation level to the stack and set the new - // indentation level. - parser.indents = append(parser.indents, parser.indent) - parser.indent = column - if len(parser.indents) > max_indents { - return yaml_parser_set_scanner_error(parser, - "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_indents)) - } - - // Create a token and insert it into the queue. - token := yaml_token_t{ - typ: typ, - start_mark: mark, - end_mark: mark, - } - if number > -1 { - number -= parser.tokens_parsed - } - yaml_insert_token(parser, number, &token) - } - return true -} - -// Pop indentation levels from the indents stack until the current level -// becomes less or equal to the column. For each indentation level, append -// the BLOCK-END token. -func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - // Loop through the indentation levels in the stack. - for parser.indent > column { - // Create a token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_END_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - } - yaml_insert_token(parser, -1, &token) - - // Pop the indentation level. - parser.indent = parser.indents[len(parser.indents)-1] - parser.indents = parser.indents[:len(parser.indents)-1] - } - return true -} - -// Initialize the scanner and produce the STREAM-START token. -func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { - - // Set the initial indentation. - parser.indent = -1 - - // Initialize the simple key stack. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) - - parser.simple_keys_by_tok = make(map[int]int) - - // A simple key is allowed at the beginning of the stream. - parser.simple_key_allowed = true - - // We have started. - parser.stream_start_produced = true - - // Create the STREAM-START token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_START_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - encoding: parser.encoding, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the STREAM-END token and shut down the scanner. -func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { - - // Force new line. - if parser.mark.column != 0 { - parser.mark.column = 0 - parser.mark.line++ - } - - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the STREAM-END token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_END_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. -func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. - token := yaml_token_t{} - if !yaml_parser_scan_directive(parser, &token) { - return false - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the DOCUMENT-START or DOCUMENT-END token. -func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Consume the token. - start_mark := parser.mark - - skip(parser) - skip(parser) - skip(parser) - - end_mark := parser.mark - - // Create the DOCUMENT-START or DOCUMENT-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. -func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // The indicators '[' and '{' may start a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // Increase the flow level. - if !yaml_parser_increase_flow_level(parser) { - return false - } - - // A simple key may follow the indicators '[' and '{'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. -func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset any potential simple key on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Decrease the flow level. - if !yaml_parser_decrease_flow_level(parser) { - return false - } - - // No simple keys after the indicators ']' and '}'. - parser.simple_key_allowed = false - - // Consume the token. - - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-ENTRY token. -func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after ','. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_FLOW_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the BLOCK-ENTRY token. -func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { - // Check if the scanner is in the block context. - if parser.flow_level == 0 { - // Check if we are allowed to start a new entry. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "block sequence entries are not allowed in this context") - } - // Add the BLOCK-SEQUENCE-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { - return false - } - } else { - // It is an error for the '-' indicator to occur in the flow context, - // but we let the Parser detect and report about it because the Parser - // is able to point to the context. - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '-'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the BLOCK-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the KEY token. -func yaml_parser_fetch_key(parser *yaml_parser_t) bool { - - // In the block context, additional checks are required. - if parser.flow_level == 0 { - // Check if we are allowed to start a new key (not nessesary simple). - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping keys are not allowed in this context") - } - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '?' in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the KEY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the VALUE token. -func yaml_parser_fetch_value(parser *yaml_parser_t) bool { - - simple_key := &parser.simple_keys[len(parser.simple_keys)-1] - - // Have we found a simple key? - if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { - return false - - } else if valid { - - // Create the KEY token and insert it into the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: simple_key.mark, - end_mark: simple_key.mark, - } - yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) - - // In the block context, we may need to add the BLOCK-MAPPING-START token. - if !yaml_parser_roll_indent(parser, simple_key.mark.column, - simple_key.token_number, - yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { - return false - } - - // Remove the simple key. - simple_key.possible = false - delete(parser.simple_keys_by_tok, simple_key.token_number) - - // A simple key cannot follow another simple key. - parser.simple_key_allowed = false - - } else { - // The ':' indicator follows a complex key. - - // In the block context, extra checks are required. - if parser.flow_level == 0 { - - // Check if we are allowed to start a complex value. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping values are not allowed in this context") - } - - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Simple keys after ':' are allowed in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - } - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the VALUE token and append it to the queue. - token := yaml_token_t{ - typ: yaml_VALUE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the ALIAS or ANCHOR token. -func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // An anchor or an alias could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow an anchor or an alias. - parser.simple_key_allowed = false - - // Create the ALIAS or ANCHOR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_anchor(parser, &token, typ) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the TAG token. -func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { - // A tag could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a tag. - parser.simple_key_allowed = false - - // Create the TAG token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_tag(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. -func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { - // Remove any potential simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // A simple key may follow a block scalar. - parser.simple_key_allowed = true - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_block_scalar(parser, &token, literal) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. -func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_flow_scalar(parser, &token, single) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,plain) token. -func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_plain_scalar(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Eat whitespaces and comments until the next token is found. -func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { - - // Until the next token is not found. - for { - // Allow the BOM mark to start a line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { - skip(parser) - } - - // Eat whitespaces. - // Tabs are allowed: - // - in the flow context - // - in the block context, but not at the beginning of the line or - // after '-', '?', or ':' (complex value). - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Eat a comment until a line break. - if parser.buffer[parser.buffer_pos] == '#' { - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // If it is a line break, eat it. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - - // In the block context, a new line may start a simple key. - if parser.flow_level == 0 { - parser.simple_key_allowed = true - } - } else { - break // We have found a token. - } - } - - return true -} - -// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// -func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { - // Eat '%'. - start_mark := parser.mark - skip(parser) - - // Scan the directive name. - var name []byte - if !yaml_parser_scan_directive_name(parser, start_mark, &name) { - return false - } - - // Is it a YAML directive? - if bytes.Equal(name, []byte("YAML")) { - // Scan the VERSION directive value. - var major, minor int8 - if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { - return false - } - end_mark := parser.mark - - // Create a VERSION-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_VERSION_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - major: major, - minor: minor, - } - - // Is it a TAG directive? - } else if bytes.Equal(name, []byte("TAG")) { - // Scan the TAG directive value. - var handle, prefix []byte - if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { - return false - } - end_mark := parser.mark - - // Create a TAG-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_TAG_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - prefix: prefix, - } - - // Unknown directive. - } else { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unknown directive name") - return false - } - - // Eat the rest of the line including any comments. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - if parser.buffer[parser.buffer_pos] == '#' { - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - return true -} - -// Scan the directive name. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^ -// -func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { - // Consume the directive name. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - var s []byte - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the name is empty. - if len(s) == 0 { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "could not find expected directive name") - return false - } - - // Check for an blank character after the name. - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unexpected non-alphabetical character") - return false - } - *name = s - return true -} - -// Scan the value of VERSION-DIRECTIVE. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^^^ -func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the major version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { - return false - } - - // Eat '.'. - if parser.buffer[parser.buffer_pos] != '.' { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected digit or '.' character") - } - - skip(parser) - - // Consume the minor version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { - return false - } - return true -} - -const max_number_length = 2 - -// Scan the version number of VERSION-DIRECTIVE. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^ -// %YAML 1.1 # a comment \n -// ^ -func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { - - // Repeat while the next character is digit. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var value, length int8 - for is_digit(parser.buffer, parser.buffer_pos) { - // Check if the number is too long. - length++ - if length > max_number_length { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "found extremely long version number") - } - value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the number was present. - if length == 0 { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected version number") - } - *number = value - return true -} - -// Scan the value of a TAG-DIRECTIVE token. -// -// Scope: -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// -func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { - var handle_value, prefix_value []byte - - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a handle. - if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { - return false - } - - // Expect a whitespace. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blank(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace") - return false - } - - // Eat whitespaces. - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a prefix. - if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { - return false - } - - // Expect a whitespace or line break. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace or line break") - return false - } - - *handle = handle_value - *prefix = prefix_value - return true -} - -func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { - var s []byte - - // Eat the indicator character. - start_mark := parser.mark - skip(parser) - - // Consume the value. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - end_mark := parser.mark - - /* - * Check if length of the anchor is greater than 0 and it is followed by - * a whitespace character or one of the indicators: - * - * '?', ':', ',', ']', '}', '%', '@', '`'. - */ - - if len(s) == 0 || - !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || - parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '`') { - context := "while scanning an alias" - if typ == yaml_ANCHOR_TOKEN { - context = "while scanning an anchor" - } - yaml_parser_set_scanner_error(parser, context, start_mark, - "did not find expected alphabetic or numeric character") - return false - } - - // Create a token. - *token = yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - value: s, - } - - return true -} - -/* - * Scan a TAG token. - */ - -func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { - var handle, suffix []byte - - start_mark := parser.mark - - // Check if the tag is in the canonical form. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - if parser.buffer[parser.buffer_pos+1] == '<' { - // Keep the handle as '' - - // Eat '!<' - skip(parser) - skip(parser) - - // Consume the tag value. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - - // Check for '>' and eat it. - if parser.buffer[parser.buffer_pos] != '>' { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find the expected '>'") - return false - } - - skip(parser) - } else { - // The tag has either the '!suffix' or the '!handle!suffix' form. - - // First, try to scan a handle. - if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { - return false - } - - // Check if it is, indeed, handle. - if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { - // Scan the suffix now. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - } else { - // It wasn't a handle after all. Scan the rest of the tag. - if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { - return false - } - - // Set the handle to '!'. - handle = []byte{'!'} - - // A special case: the '!' tag. Set the handle to '' and the - // suffix to '!'. - if len(suffix) == 0 { - handle, suffix = suffix, handle - } - } - } - - // Check the character which ends the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find expected whitespace or line break") - return false - } - - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_TAG_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - suffix: suffix, - } - return true -} - -// Scan a tag handle. -func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { - // Check the initial '!' character. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] != '!' { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - - var s []byte - - // Copy the '!' character. - s = read(parser, s) - - // Copy all subsequent alphabetical and numerical characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the trailing character is '!' and copy it. - if parser.buffer[parser.buffer_pos] == '!' { - s = read(parser, s) - } else { - // It's either the '!' tag or not really a tag handle. If it's a %TAG - // directive, it's an error. If it's a tag token, it must be a part of URI. - if directive && string(s) != "!" { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - } - - *handle = s - return true -} - -// Scan a tag. -func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { - //size_t length = head ? strlen((char *)head) : 0 - var s []byte - hasTag := len(head) > 0 - - // Copy the head if needed. - // - // Note that we don't copy the leading '!' character. - if len(head) > 1 { - s = append(s, head[1:]...) - } - - // Scan the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // The set of characters that may appear in URI is as follows: - // - // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', - // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', - // '%'. - // [Go] Convert this into more reasonable logic. - for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || - parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || - parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || - parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || - parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || - parser.buffer[parser.buffer_pos] == '%' { - // Check if it is a URI-escape sequence. - if parser.buffer[parser.buffer_pos] == '%' { - if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { - return false - } - } else { - s = read(parser, s) - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - hasTag = true - } - - if !hasTag { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected tag URI") - return false - } - *uri = s - return true -} - -// Decode an URI-escape sequence corresponding to a single UTF-8 character. -func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { - - // Decode the required number of characters. - w := 1024 - for w > 0 { - // Check for a URI-escaped octet. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - - if !(parser.buffer[parser.buffer_pos] == '%' && - is_hex(parser.buffer, parser.buffer_pos+1) && - is_hex(parser.buffer, parser.buffer_pos+2)) { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find URI escaped octet") - } - - // Get the octet. - octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) - - // If it is the leading octet, determine the length of the UTF-8 sequence. - if w == 1024 { - w = width(octet) - if w == 0 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect leading UTF-8 octet") - } - } else { - // Check if the trailing octet is correct. - if octet&0xC0 != 0x80 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect trailing UTF-8 octet") - } - } - - // Copy the octet and move the pointers. - *s = append(*s, octet) - skip(parser) - skip(parser) - skip(parser) - w-- - } - return true -} - -// Scan a block scalar. -func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { - // Eat the indicator '|' or '>'. - start_mark := parser.mark - skip(parser) - - // Scan the additional block scalar indicators. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check for a chomping indicator. - var chomping, increment int - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - // Set the chomping method and eat the indicator. - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - - // Check for an indentation indicator. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_digit(parser.buffer, parser.buffer_pos) { - // Check that the indentation is greater than 0. - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - - // Get the indentation level and eat the indicator. - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - } - - } else if is_digit(parser.buffer, parser.buffer_pos) { - // Do the same as above, but in the opposite order. - - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - } - } - - // Eat whitespaces and comments to the end of the line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.buffer[parser.buffer_pos] == '#' { - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - end_mark := parser.mark - - // Set the indentation level if it was specified. - var indent int - if increment > 0 { - if parser.indent >= 0 { - indent = parser.indent + increment - } else { - indent = increment - } - } - - // Scan the leading line breaks and determine the indentation level if needed. - var s, leading_break, trailing_breaks []byte - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - - // Scan the block scalar content. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var leading_blank, trailing_blank bool - for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { - // We are at the beginning of a non-empty line. - - // Is it a trailing whitespace? - trailing_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Check if we need to fold the leading line break. - if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { - // Do we need to join the lines by space? - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } - } else { - s = append(s, leading_break...) - } - leading_break = leading_break[:0] - - // Append the remaining line breaks. - s = append(s, trailing_breaks...) - trailing_breaks = trailing_breaks[:0] - - // Is it a leading whitespace? - leading_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Consume the current line. - for !is_breakz(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - leading_break = read_line(parser, leading_break) - - // Eat the following indentation spaces and line breaks. - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - } - - // Chomp the tail. - if chomping != -1 { - s = append(s, leading_break...) - } - if chomping == 1 { - s = append(s, trailing_breaks...) - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_LITERAL_SCALAR_STYLE, - } - if !literal { - token.style = yaml_FOLDED_SCALAR_STYLE - } - return true -} - -// Scan indentation spaces and line breaks for a block scalar. Determine the -// indentation level if needed. -func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { - *end_mark = parser.mark - - // Eat the indentation spaces and line breaks. - max_indent := 0 - for { - // Eat the indentation spaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.mark.column > max_indent { - max_indent = parser.mark.column - } - - // Check for a tab character messing the indentation. - if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { - return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found a tab character where an indentation space is expected") - } - - // Have we found a non-empty line? - if !is_break(parser.buffer, parser.buffer_pos) { - break - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - // [Go] Should really be returning breaks instead. - *breaks = read_line(parser, *breaks) - *end_mark = parser.mark - } - - // Determine the indentation level if needed. - if *indent == 0 { - *indent = max_indent - if *indent < parser.indent+1 { - *indent = parser.indent + 1 - } - if *indent < 1 { - *indent = 1 - } - } - return true -} - -// Scan a quoted scalar. -func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { - // Eat the left quote. - start_mark := parser.mark - skip(parser) - - // Consume the content of the quoted scalar. - var s, leading_break, trailing_breaks, whitespaces []byte - for { - // Check that there are no document indicators at the beginning of the line. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected document indicator") - return false - } - - // Check for EOF. - if is_z(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected end of stream") - return false - } - - // Consume non-blank characters. - leading_blanks := false - for !is_blankz(parser.buffer, parser.buffer_pos) { - if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { - // Is is an escaped single quote. - s = append(s, '\'') - skip(parser) - skip(parser) - - } else if single && parser.buffer[parser.buffer_pos] == '\'' { - // It is a right single quote. - break - } else if !single && parser.buffer[parser.buffer_pos] == '"' { - // It is a right double quote. - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { - // It is an escaped line break. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - skip(parser) - skip_line(parser) - leading_blanks = true - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' { - // It is an escape sequence. - code_length := 0 - - // Check the escape character. - switch parser.buffer[parser.buffer_pos+1] { - case '0': - s = append(s, 0) - case 'a': - s = append(s, '\x07') - case 'b': - s = append(s, '\x08') - case 't', '\t': - s = append(s, '\x09') - case 'n': - s = append(s, '\x0A') - case 'v': - s = append(s, '\x0B') - case 'f': - s = append(s, '\x0C') - case 'r': - s = append(s, '\x0D') - case 'e': - s = append(s, '\x1B') - case ' ': - s = append(s, '\x20') - case '"': - s = append(s, '"') - case '\'': - s = append(s, '\'') - case '\\': - s = append(s, '\\') - case 'N': // NEL (#x85) - s = append(s, '\xC2') - s = append(s, '\x85') - case '_': // #xA0 - s = append(s, '\xC2') - s = append(s, '\xA0') - case 'L': // LS (#x2028) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA8') - case 'P': // PS (#x2029) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA9') - case 'x': - code_length = 2 - case 'u': - code_length = 4 - case 'U': - code_length = 8 - default: - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found unknown escape character") - return false - } - - skip(parser) - skip(parser) - - // Consume an arbitrary escape code. - if code_length > 0 { - var value int - - // Scan the character value. - if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { - return false - } - for k := 0; k < code_length; k++ { - if !is_hex(parser.buffer, parser.buffer_pos+k) { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "did not find expected hexdecimal number") - return false - } - value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) - } - - // Check the value and write the character. - if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found invalid Unicode character escape code") - return false - } - if value <= 0x7F { - s = append(s, byte(value)) - } else if value <= 0x7FF { - s = append(s, byte(0xC0+(value>>6))) - s = append(s, byte(0x80+(value&0x3F))) - } else if value <= 0xFFFF { - s = append(s, byte(0xE0+(value>>12))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } else { - s = append(s, byte(0xF0+(value>>18))) - s = append(s, byte(0x80+((value>>12)&0x3F))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } - - // Advance the pointer. - for k := 0; k < code_length; k++ { - skip(parser) - } - } - } else { - // It is a non-escaped non-blank character. - s = read(parser, s) - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we are at the end of the scalar. - if single { - if parser.buffer[parser.buffer_pos] == '\'' { - break - } - } else { - if parser.buffer[parser.buffer_pos] == '"' { - break - } - } - - // Consume blank characters. - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Join the whitespaces or fold line breaks. - if leading_blanks { - // Do we need to fold line breaks? - if len(leading_break) > 0 && leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Eat the right quote. - skip(parser) - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_SINGLE_QUOTED_SCALAR_STYLE, - } - if !single { - token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - return true -} - -// Scan a plain scalar. -func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { - - var s, leading_break, trailing_breaks, whitespaces []byte - var leading_blanks bool - var indent = parser.indent + 1 - - start_mark := parser.mark - end_mark := parser.mark - - // Consume the content of the plain scalar. - for { - // Check for a document indicator. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - break - } - - // Check for a comment. - if parser.buffer[parser.buffer_pos] == '#' { - break - } - - // Consume non-blank characters. - for !is_blankz(parser.buffer, parser.buffer_pos) { - - // Check for indicators that may end a plain scalar. - if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level > 0 && - (parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}')) { - break - } - - // Check if we need to join whitespaces and breaks. - if leading_blanks || len(whitespaces) > 0 { - if leading_blanks { - // Do we need to fold line breaks? - if leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - leading_blanks = false - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Copy the character. - s = read(parser, s) - - end_mark = parser.mark - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - // Is it the end? - if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { - break - } - - // Consume blank characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - - // Check for tab characters that abuse indentation. - if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", - start_mark, "found a tab character that violates indentation") - return false - } - - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check indentation level. - if parser.flow_level == 0 && parser.mark.column < indent { - break - } - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_PLAIN_SCALAR_STYLE, - } - - // Note that we change the 'simple_key_allowed' flag. - if leading_blanks { - parser.simple_key_allowed = true - } - return true -} diff --git a/vendor/gopkg.in/yaml.v2/sorter.go b/vendor/gopkg.in/yaml.v2/sorter.go deleted file mode 100644 index 4c45e660..00000000 --- a/vendor/gopkg.in/yaml.v2/sorter.go +++ /dev/null @@ -1,113 +0,0 @@ -package yaml - -import ( - "reflect" - "unicode" -) - -type keyList []reflect.Value - -func (l keyList) Len() int { return len(l) } -func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l keyList) Less(i, j int) bool { - a := l[i] - b := l[j] - ak := a.Kind() - bk := b.Kind() - for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { - a = a.Elem() - ak = a.Kind() - } - for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { - b = b.Elem() - bk = b.Kind() - } - af, aok := keyFloat(a) - bf, bok := keyFloat(b) - if aok && bok { - if af != bf { - return af < bf - } - if ak != bk { - return ak < bk - } - return numLess(a, b) - } - if ak != reflect.String || bk != reflect.String { - return ak < bk - } - ar, br := []rune(a.String()), []rune(b.String()) - for i := 0; i < len(ar) && i < len(br); i++ { - if ar[i] == br[i] { - continue - } - al := unicode.IsLetter(ar[i]) - bl := unicode.IsLetter(br[i]) - if al && bl { - return ar[i] < br[i] - } - if al || bl { - return bl - } - var ai, bi int - var an, bn int64 - if ar[i] == '0' || br[i] == '0' { - for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { - if ar[j] != '0' { - an = 1 - bn = 1 - break - } - } - } - for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { - an = an*10 + int64(ar[ai]-'0') - } - for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { - bn = bn*10 + int64(br[bi]-'0') - } - if an != bn { - return an < bn - } - if ai != bi { - return ai < bi - } - return ar[i] < br[i] - } - return len(ar) < len(br) -} - -// keyFloat returns a float value for v if it is a number/bool -// and whether it is a number/bool or not. -func keyFloat(v reflect.Value) (f float64, ok bool) { - switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return float64(v.Int()), true - case reflect.Float32, reflect.Float64: - return v.Float(), true - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return float64(v.Uint()), true - case reflect.Bool: - if v.Bool() { - return 1, true - } - return 0, true - } - return 0, false -} - -// numLess returns whether a < b. -// a and b must necessarily have the same kind. -func numLess(a, b reflect.Value) bool { - switch a.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return a.Int() < b.Int() - case reflect.Float32, reflect.Float64: - return a.Float() < b.Float() - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return a.Uint() < b.Uint() - case reflect.Bool: - return !a.Bool() && b.Bool() - } - panic("not a number") -} diff --git a/vendor/gopkg.in/yaml.v2/writerc.go b/vendor/gopkg.in/yaml.v2/writerc.go deleted file mode 100644 index a2dde608..00000000 --- a/vendor/gopkg.in/yaml.v2/writerc.go +++ /dev/null @@ -1,26 +0,0 @@ -package yaml - -// Set the writer error and return false. -func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_WRITER_ERROR - emitter.problem = problem - return false -} - -// Flush the output buffer. -func yaml_emitter_flush(emitter *yaml_emitter_t) bool { - if emitter.write_handler == nil { - panic("write handler not set") - } - - // Check if the buffer is empty. - if emitter.buffer_pos == 0 { - return true - } - - if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { - return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) - } - emitter.buffer_pos = 0 - return true -} diff --git a/vendor/gopkg.in/yaml.v2/yaml.go b/vendor/gopkg.in/yaml.v2/yaml.go deleted file mode 100644 index 30813884..00000000 --- a/vendor/gopkg.in/yaml.v2/yaml.go +++ /dev/null @@ -1,478 +0,0 @@ -// Package yaml implements YAML support for the Go language. -// -// Source code and other details for the project are available at GitHub: -// -// https://github.com/go-yaml/yaml -// -package yaml - -import ( - "errors" - "fmt" - "io" - "reflect" - "strings" - "sync" -) - -// MapSlice encodes and decodes as a YAML map. -// The order of keys is preserved when encoding and decoding. -type MapSlice []MapItem - -// MapItem is an item in a MapSlice. -type MapItem struct { - Key, Value interface{} -} - -// The Unmarshaler interface may be implemented by types to customize their -// behavior when being unmarshaled from a YAML document. The UnmarshalYAML -// method receives a function that may be called to unmarshal the original -// YAML value into a field or variable. It is safe to call the unmarshal -// function parameter more than once if necessary. -type Unmarshaler interface { - UnmarshalYAML(unmarshal func(interface{}) error) error -} - -// The Marshaler interface may be implemented by types to customize their -// behavior when being marshaled into a YAML document. The returned value -// is marshaled in place of the original value implementing Marshaler. -// -// If an error is returned by MarshalYAML, the marshaling procedure stops -// and returns with the provided error. -type Marshaler interface { - MarshalYAML() (interface{}, error) -} - -// Unmarshal decodes the first document found within the in byte slice -// and assigns decoded values into the out value. -// -// Maps and pointers (to a struct, string, int, etc) are accepted as out -// values. If an internal pointer within a struct is not initialized, -// the yaml package will initialize it if necessary for unmarshalling -// the provided data. The out parameter must not be nil. -// -// The type of the decoded values should be compatible with the respective -// values in out. If one or more values cannot be decoded due to a type -// mismatches, decoding continues partially until the end of the YAML -// content, and a *yaml.TypeError is returned with details for all -// missed values. -// -// Struct fields are only unmarshalled if they are exported (have an -// upper case first letter), and are unmarshalled using the field name -// lowercased as the default key. Custom keys may be defined via the -// "yaml" name in the field tag: the content preceding the first comma -// is used as the key, and the following comma-separated options are -// used to tweak the marshalling process (see Marshal). -// Conflicting names result in a runtime error. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// var t T -// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) -// -// See the documentation of Marshal for the format of tags and a list of -// supported tag options. -// -func Unmarshal(in []byte, out interface{}) (err error) { - return unmarshal(in, out, false) -} - -// UnmarshalStrict is like Unmarshal except that any fields that are found -// in the data that do not have corresponding struct members, or mapping -// keys that are duplicates, will result in -// an error. -func UnmarshalStrict(in []byte, out interface{}) (err error) { - return unmarshal(in, out, true) -} - -// A Decoder reads and decodes YAML values from an input stream. -type Decoder struct { - strict bool - parser *parser -} - -// NewDecoder returns a new decoder that reads from r. -// -// The decoder introduces its own buffering and may read -// data from r beyond the YAML values requested. -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{ - parser: newParserFromReader(r), - } -} - -// SetStrict sets whether strict decoding behaviour is enabled when -// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict. -func (dec *Decoder) SetStrict(strict bool) { - dec.strict = strict -} - -// Decode reads the next YAML-encoded value from its input -// and stores it in the value pointed to by v. -// -// See the documentation for Unmarshal for details about the -// conversion of YAML into a Go value. -func (dec *Decoder) Decode(v interface{}) (err error) { - d := newDecoder(dec.strict) - defer handleErr(&err) - node := dec.parser.parse() - if node == nil { - return io.EOF - } - out := reflect.ValueOf(v) - if out.Kind() == reflect.Ptr && !out.IsNil() { - out = out.Elem() - } - d.unmarshal(node, out) - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -func unmarshal(in []byte, out interface{}, strict bool) (err error) { - defer handleErr(&err) - d := newDecoder(strict) - p := newParser(in) - defer p.destroy() - node := p.parse() - if node != nil { - v := reflect.ValueOf(out) - if v.Kind() == reflect.Ptr && !v.IsNil() { - v = v.Elem() - } - d.unmarshal(node, v) - } - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -// Marshal serializes the value provided into a YAML document. The structure -// of the generated document will reflect the structure of the value itself. -// Maps and pointers (to struct, string, int, etc) are accepted as the in value. -// -// Struct fields are only marshalled if they are exported (have an upper case -// first letter), and are marshalled using the field name lowercased as the -// default key. Custom keys may be defined via the "yaml" name in the field -// tag: the content preceding the first comma is used as the key, and the -// following comma-separated options are used to tweak the marshalling process. -// Conflicting names result in a runtime error. -// -// The field tag format accepted is: -// -// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)` -// -// The following flags are currently supported: -// -// omitempty Only include the field if it's not set to the zero -// value for the type or to empty slices or maps. -// Zero valued structs will be omitted if all their public -// fields are zero, unless they implement an IsZero -// method (see the IsZeroer interface type), in which -// case the field will be excluded if IsZero returns true. -// -// flow Marshal using a flow style (useful for structs, -// sequences and maps). -// -// inline Inline the field, which must be a struct or a map, -// causing all of its fields or keys to be processed as if -// they were part of the outer struct. For maps, keys must -// not conflict with the yaml keys of other struct fields. -// -// In addition, if the key is "-", the field is ignored. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" -// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" -// -func Marshal(in interface{}) (out []byte, err error) { - defer handleErr(&err) - e := newEncoder() - defer e.destroy() - e.marshalDoc("", reflect.ValueOf(in)) - e.finish() - out = e.out - return -} - -// An Encoder writes YAML values to an output stream. -type Encoder struct { - encoder *encoder -} - -// NewEncoder returns a new encoder that writes to w. -// The Encoder should be closed after use to flush all data -// to w. -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - encoder: newEncoderWithWriter(w), - } -} - -// Encode writes the YAML encoding of v to the stream. -// If multiple items are encoded to the stream, the -// second and subsequent document will be preceded -// with a "---" document separator, but the first will not. -// -// See the documentation for Marshal for details about the conversion of Go -// values to YAML. -func (e *Encoder) Encode(v interface{}) (err error) { - defer handleErr(&err) - e.encoder.marshalDoc("", reflect.ValueOf(v)) - return nil -} - -// Close closes the encoder by writing any remaining data. -// It does not write a stream terminating string "...". -func (e *Encoder) Close() (err error) { - defer handleErr(&err) - e.encoder.finish() - return nil -} - -func handleErr(err *error) { - if v := recover(); v != nil { - if e, ok := v.(yamlError); ok { - *err = e.err - } else { - panic(v) - } - } -} - -type yamlError struct { - err error -} - -func fail(err error) { - panic(yamlError{err}) -} - -func failf(format string, args ...interface{}) { - panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) -} - -// A TypeError is returned by Unmarshal when one or more fields in -// the YAML document cannot be properly decoded into the requested -// types. When this error is returned, the value is still -// unmarshaled partially. -type TypeError struct { - Errors []string -} - -func (e *TypeError) Error() string { - return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) -} - -// -------------------------------------------------------------------------- -// Maintain a mapping of keys to structure field indexes - -// The code in this section was copied from mgo/bson. - -// structInfo holds details for the serialization of fields of -// a given struct. -type structInfo struct { - FieldsMap map[string]fieldInfo - FieldsList []fieldInfo - - // InlineMap is the number of the field in the struct that - // contains an ,inline map, or -1 if there's none. - InlineMap int -} - -type fieldInfo struct { - Key string - Num int - OmitEmpty bool - Flow bool - // Id holds the unique field identifier, so we can cheaply - // check for field duplicates without maintaining an extra map. - Id int - - // Inline holds the field index if the field is part of an inlined struct. - Inline []int -} - -var structMap = make(map[reflect.Type]*structInfo) -var fieldMapMutex sync.RWMutex - -func getStructInfo(st reflect.Type) (*structInfo, error) { - fieldMapMutex.RLock() - sinfo, found := structMap[st] - fieldMapMutex.RUnlock() - if found { - return sinfo, nil - } - - n := st.NumField() - fieldsMap := make(map[string]fieldInfo) - fieldsList := make([]fieldInfo, 0, n) - inlineMap := -1 - for i := 0; i != n; i++ { - field := st.Field(i) - if field.PkgPath != "" && !field.Anonymous { - continue // Private field - } - - info := fieldInfo{Num: i} - - tag := field.Tag.Get("yaml") - if tag == "" && strings.Index(string(field.Tag), ":") < 0 { - tag = string(field.Tag) - } - if tag == "-" { - continue - } - - inline := false - fields := strings.Split(tag, ",") - if len(fields) > 1 { - for _, flag := range fields[1:] { - switch flag { - case "omitempty": - info.OmitEmpty = true - case "flow": - info.Flow = true - case "inline": - inline = true - default: - return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) - } - } - tag = fields[0] - } - - if inline { - switch field.Type.Kind() { - case reflect.Map: - if inlineMap >= 0 { - return nil, errors.New("Multiple ,inline maps in struct " + st.String()) - } - if field.Type.Key() != reflect.TypeOf("") { - return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) - } - inlineMap = info.Num - case reflect.Struct: - sinfo, err := getStructInfo(field.Type) - if err != nil { - return nil, err - } - for _, finfo := range sinfo.FieldsList { - if _, found := fieldsMap[finfo.Key]; found { - msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - if finfo.Inline == nil { - finfo.Inline = []int{i, finfo.Num} - } else { - finfo.Inline = append([]int{i}, finfo.Inline...) - } - finfo.Id = len(fieldsList) - fieldsMap[finfo.Key] = finfo - fieldsList = append(fieldsList, finfo) - } - default: - //return nil, errors.New("Option ,inline needs a struct value or map field") - return nil, errors.New("Option ,inline needs a struct value field") - } - continue - } - - if tag != "" { - info.Key = tag - } else { - info.Key = strings.ToLower(field.Name) - } - - if _, found = fieldsMap[info.Key]; found { - msg := "Duplicated key '" + info.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - - info.Id = len(fieldsList) - fieldsList = append(fieldsList, info) - fieldsMap[info.Key] = info - } - - sinfo = &structInfo{ - FieldsMap: fieldsMap, - FieldsList: fieldsList, - InlineMap: inlineMap, - } - - fieldMapMutex.Lock() - structMap[st] = sinfo - fieldMapMutex.Unlock() - return sinfo, nil -} - -// IsZeroer is used to check whether an object is zero to -// determine whether it should be omitted when marshaling -// with the omitempty flag. One notable implementation -// is time.Time. -type IsZeroer interface { - IsZero() bool -} - -func isZero(v reflect.Value) bool { - kind := v.Kind() - if z, ok := v.Interface().(IsZeroer); ok { - if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { - return true - } - return z.IsZero() - } - switch kind { - case reflect.String: - return len(v.String()) == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - case reflect.Slice: - return v.Len() == 0 - case reflect.Map: - return v.Len() == 0 - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Struct: - vt := v.Type() - for i := v.NumField() - 1; i >= 0; i-- { - if vt.Field(i).PkgPath != "" { - continue // Private field - } - if !isZero(v.Field(i)) { - return false - } - } - return true - } - return false -} - -// FutureLineWrap globally disables line wrapping when encoding long strings. -// This is a temporary and thus deprecated method introduced to faciliate -// migration towards v3, which offers more control of line lengths on -// individual encodings, and has a default matching the behavior introduced -// by this function. -// -// The default formatting of v2 was erroneously changed in v2.3.0 and reverted -// in v2.4.0, at which point this function was introduced to help migration. -func FutureLineWrap() { - disableLineWrapping = true -} diff --git a/vendor/gopkg.in/yaml.v2/yamlh.go b/vendor/gopkg.in/yaml.v2/yamlh.go deleted file mode 100644 index f6a9c8e3..00000000 --- a/vendor/gopkg.in/yaml.v2/yamlh.go +++ /dev/null @@ -1,739 +0,0 @@ -package yaml - -import ( - "fmt" - "io" -) - -// The version directive data. -type yaml_version_directive_t struct { - major int8 // The major version number. - minor int8 // The minor version number. -} - -// The tag directive data. -type yaml_tag_directive_t struct { - handle []byte // The tag handle. - prefix []byte // The tag prefix. -} - -type yaml_encoding_t int - -// The stream encoding. -const ( - // Let the parser choose the encoding. - yaml_ANY_ENCODING yaml_encoding_t = iota - - yaml_UTF8_ENCODING // The default UTF-8 encoding. - yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. - yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. -) - -type yaml_break_t int - -// Line break types. -const ( - // Let the parser choose the break type. - yaml_ANY_BREAK yaml_break_t = iota - - yaml_CR_BREAK // Use CR for line breaks (Mac style). - yaml_LN_BREAK // Use LN for line breaks (Unix style). - yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). -) - -type yaml_error_type_t int - -// Many bad things could happen with the parser and emitter. -const ( - // No error is produced. - yaml_NO_ERROR yaml_error_type_t = iota - - yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. - yaml_READER_ERROR // Cannot read or decode the input stream. - yaml_SCANNER_ERROR // Cannot scan the input stream. - yaml_PARSER_ERROR // Cannot parse the input stream. - yaml_COMPOSER_ERROR // Cannot compose a YAML document. - yaml_WRITER_ERROR // Cannot write to the output stream. - yaml_EMITTER_ERROR // Cannot emit a YAML stream. -) - -// The pointer position. -type yaml_mark_t struct { - index int // The position index. - line int // The position line. - column int // The position column. -} - -// Node Styles - -type yaml_style_t int8 - -type yaml_scalar_style_t yaml_style_t - -// Scalar styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota - - yaml_PLAIN_SCALAR_STYLE // The plain scalar style. - yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. - yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. - yaml_LITERAL_SCALAR_STYLE // The literal scalar style. - yaml_FOLDED_SCALAR_STYLE // The folded scalar style. -) - -type yaml_sequence_style_t yaml_style_t - -// Sequence styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota - - yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. - yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. -) - -type yaml_mapping_style_t yaml_style_t - -// Mapping styles. -const ( - // Let the emitter choose the style. - yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota - - yaml_BLOCK_MAPPING_STYLE // The block mapping style. - yaml_FLOW_MAPPING_STYLE // The flow mapping style. -) - -// Tokens - -type yaml_token_type_t int - -// Token types. -const ( - // An empty token. - yaml_NO_TOKEN yaml_token_type_t = iota - - yaml_STREAM_START_TOKEN // A STREAM-START token. - yaml_STREAM_END_TOKEN // A STREAM-END token. - - yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. - yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. - yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. - yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. - - yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. - yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. - yaml_BLOCK_END_TOKEN // A BLOCK-END token. - - yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. - yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. - yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. - yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. - - yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. - yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. - yaml_KEY_TOKEN // A KEY token. - yaml_VALUE_TOKEN // A VALUE token. - - yaml_ALIAS_TOKEN // An ALIAS token. - yaml_ANCHOR_TOKEN // An ANCHOR token. - yaml_TAG_TOKEN // A TAG token. - yaml_SCALAR_TOKEN // A SCALAR token. -) - -func (tt yaml_token_type_t) String() string { - switch tt { - case yaml_NO_TOKEN: - return "yaml_NO_TOKEN" - case yaml_STREAM_START_TOKEN: - return "yaml_STREAM_START_TOKEN" - case yaml_STREAM_END_TOKEN: - return "yaml_STREAM_END_TOKEN" - case yaml_VERSION_DIRECTIVE_TOKEN: - return "yaml_VERSION_DIRECTIVE_TOKEN" - case yaml_TAG_DIRECTIVE_TOKEN: - return "yaml_TAG_DIRECTIVE_TOKEN" - case yaml_DOCUMENT_START_TOKEN: - return "yaml_DOCUMENT_START_TOKEN" - case yaml_DOCUMENT_END_TOKEN: - return "yaml_DOCUMENT_END_TOKEN" - case yaml_BLOCK_SEQUENCE_START_TOKEN: - return "yaml_BLOCK_SEQUENCE_START_TOKEN" - case yaml_BLOCK_MAPPING_START_TOKEN: - return "yaml_BLOCK_MAPPING_START_TOKEN" - case yaml_BLOCK_END_TOKEN: - return "yaml_BLOCK_END_TOKEN" - case yaml_FLOW_SEQUENCE_START_TOKEN: - return "yaml_FLOW_SEQUENCE_START_TOKEN" - case yaml_FLOW_SEQUENCE_END_TOKEN: - return "yaml_FLOW_SEQUENCE_END_TOKEN" - case yaml_FLOW_MAPPING_START_TOKEN: - return "yaml_FLOW_MAPPING_START_TOKEN" - case yaml_FLOW_MAPPING_END_TOKEN: - return "yaml_FLOW_MAPPING_END_TOKEN" - case yaml_BLOCK_ENTRY_TOKEN: - return "yaml_BLOCK_ENTRY_TOKEN" - case yaml_FLOW_ENTRY_TOKEN: - return "yaml_FLOW_ENTRY_TOKEN" - case yaml_KEY_TOKEN: - return "yaml_KEY_TOKEN" - case yaml_VALUE_TOKEN: - return "yaml_VALUE_TOKEN" - case yaml_ALIAS_TOKEN: - return "yaml_ALIAS_TOKEN" - case yaml_ANCHOR_TOKEN: - return "yaml_ANCHOR_TOKEN" - case yaml_TAG_TOKEN: - return "yaml_TAG_TOKEN" - case yaml_SCALAR_TOKEN: - return "yaml_SCALAR_TOKEN" - } - return "<unknown token>" -} - -// The token structure. -type yaml_token_t struct { - // The token type. - typ yaml_token_type_t - - // The start/end of the token. - start_mark, end_mark yaml_mark_t - - // The stream encoding (for yaml_STREAM_START_TOKEN). - encoding yaml_encoding_t - - // The alias/anchor/scalar value or tag/tag directive handle - // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). - value []byte - - // The tag suffix (for yaml_TAG_TOKEN). - suffix []byte - - // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). - prefix []byte - - // The scalar style (for yaml_SCALAR_TOKEN). - style yaml_scalar_style_t - - // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). - major, minor int8 -} - -// Events - -type yaml_event_type_t int8 - -// Event types. -const ( - // An empty event. - yaml_NO_EVENT yaml_event_type_t = iota - - yaml_STREAM_START_EVENT // A STREAM-START event. - yaml_STREAM_END_EVENT // A STREAM-END event. - yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. - yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. - yaml_ALIAS_EVENT // An ALIAS event. - yaml_SCALAR_EVENT // A SCALAR event. - yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. - yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. - yaml_MAPPING_START_EVENT // A MAPPING-START event. - yaml_MAPPING_END_EVENT // A MAPPING-END event. -) - -var eventStrings = []string{ - yaml_NO_EVENT: "none", - yaml_STREAM_START_EVENT: "stream start", - yaml_STREAM_END_EVENT: "stream end", - yaml_DOCUMENT_START_EVENT: "document start", - yaml_DOCUMENT_END_EVENT: "document end", - yaml_ALIAS_EVENT: "alias", - yaml_SCALAR_EVENT: "scalar", - yaml_SEQUENCE_START_EVENT: "sequence start", - yaml_SEQUENCE_END_EVENT: "sequence end", - yaml_MAPPING_START_EVENT: "mapping start", - yaml_MAPPING_END_EVENT: "mapping end", -} - -func (e yaml_event_type_t) String() string { - if e < 0 || int(e) >= len(eventStrings) { - return fmt.Sprintf("unknown event %d", e) - } - return eventStrings[e] -} - -// The event structure. -type yaml_event_t struct { - - // The event type. - typ yaml_event_type_t - - // The start and end of the event. - start_mark, end_mark yaml_mark_t - - // The document encoding (for yaml_STREAM_START_EVENT). - encoding yaml_encoding_t - - // The version directive (for yaml_DOCUMENT_START_EVENT). - version_directive *yaml_version_directive_t - - // The list of tag directives (for yaml_DOCUMENT_START_EVENT). - tag_directives []yaml_tag_directive_t - - // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). - anchor []byte - - // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - tag []byte - - // The scalar value (for yaml_SCALAR_EVENT). - value []byte - - // Is the document start/end indicator implicit, or the tag optional? - // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). - implicit bool - - // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). - quoted_implicit bool - - // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - style yaml_style_t -} - -func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } -func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } -func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } - -// Nodes - -const ( - yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. - yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. - yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. - yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. - yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. - yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. - - yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. - yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. - - // Not in original libyaml. - yaml_BINARY_TAG = "tag:yaml.org,2002:binary" - yaml_MERGE_TAG = "tag:yaml.org,2002:merge" - - yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. - yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. - yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. -) - -type yaml_node_type_t int - -// Node types. -const ( - // An empty node. - yaml_NO_NODE yaml_node_type_t = iota - - yaml_SCALAR_NODE // A scalar node. - yaml_SEQUENCE_NODE // A sequence node. - yaml_MAPPING_NODE // A mapping node. -) - -// An element of a sequence node. -type yaml_node_item_t int - -// An element of a mapping node. -type yaml_node_pair_t struct { - key int // The key of the element. - value int // The value of the element. -} - -// The node structure. -type yaml_node_t struct { - typ yaml_node_type_t // The node type. - tag []byte // The node tag. - - // The node data. - - // The scalar parameters (for yaml_SCALAR_NODE). - scalar struct { - value []byte // The scalar value. - length int // The length of the scalar value. - style yaml_scalar_style_t // The scalar style. - } - - // The sequence parameters (for YAML_SEQUENCE_NODE). - sequence struct { - items_data []yaml_node_item_t // The stack of sequence items. - style yaml_sequence_style_t // The sequence style. - } - - // The mapping parameters (for yaml_MAPPING_NODE). - mapping struct { - pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). - pairs_start *yaml_node_pair_t // The beginning of the stack. - pairs_end *yaml_node_pair_t // The end of the stack. - pairs_top *yaml_node_pair_t // The top of the stack. - style yaml_mapping_style_t // The mapping style. - } - - start_mark yaml_mark_t // The beginning of the node. - end_mark yaml_mark_t // The end of the node. - -} - -// The document structure. -type yaml_document_t struct { - - // The document nodes. - nodes []yaml_node_t - - // The version directive. - version_directive *yaml_version_directive_t - - // The list of tag directives. - tag_directives_data []yaml_tag_directive_t - tag_directives_start int // The beginning of the tag directives list. - tag_directives_end int // The end of the tag directives list. - - start_implicit int // Is the document start indicator implicit? - end_implicit int // Is the document end indicator implicit? - - // The start/end of the document. - start_mark, end_mark yaml_mark_t -} - -// The prototype of a read handler. -// -// The read handler is called when the parser needs to read more bytes from the -// source. The handler should write not more than size bytes to the buffer. -// The number of written bytes should be set to the size_read variable. -// -// [in,out] data A pointer to an application data specified by -// yaml_parser_set_input(). -// [out] buffer The buffer to write the data from the source. -// [in] size The size of the buffer. -// [out] size_read The actual number of bytes read from the source. -// -// On success, the handler should return 1. If the handler failed, -// the returned value should be 0. On EOF, the handler should set the -// size_read to 0 and return 1. -type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) - -// This structure holds information about a potential simple key. -type yaml_simple_key_t struct { - possible bool // Is a simple key possible? - required bool // Is a simple key required? - token_number int // The number of the token. - mark yaml_mark_t // The position mark. -} - -// The states of the parser. -type yaml_parser_state_t int - -const ( - yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota - - yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. - yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. - yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. - yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. - yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. - yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. - yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. - yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. - yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. - yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. - yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. - yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. - yaml_PARSE_END_STATE // Expect nothing. -) - -func (ps yaml_parser_state_t) String() string { - switch ps { - case yaml_PARSE_STREAM_START_STATE: - return "yaml_PARSE_STREAM_START_STATE" - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_START_STATE: - return "yaml_PARSE_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return "yaml_PARSE_DOCUMENT_CONTENT_STATE" - case yaml_PARSE_DOCUMENT_END_STATE: - return "yaml_PARSE_DOCUMENT_END_STATE" - case yaml_PARSE_BLOCK_NODE_STATE: - return "yaml_PARSE_BLOCK_NODE_STATE" - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" - case yaml_PARSE_FLOW_NODE_STATE: - return "yaml_PARSE_FLOW_NODE_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" - case yaml_PARSE_END_STATE: - return "yaml_PARSE_END_STATE" - } - return "<unknown parser state>" -} - -// This structure holds aliases data. -type yaml_alias_data_t struct { - anchor []byte // The anchor. - index int // The node id. - mark yaml_mark_t // The anchor mark. -} - -// The parser structure. -// -// All members are internal. Manage the structure using the -// yaml_parser_ family of functions. -type yaml_parser_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - - problem string // Error description. - - // The byte about which the problem occurred. - problem_offset int - problem_value int - problem_mark yaml_mark_t - - // The error context. - context string - context_mark yaml_mark_t - - // Reader stuff - - read_handler yaml_read_handler_t // Read handler. - - input_reader io.Reader // File input data. - input []byte // String input data. - input_pos int - - eof bool // EOF flag - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - unread int // The number of unread characters in the buffer. - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The input encoding. - - offset int // The offset of the current position (in bytes). - mark yaml_mark_t // The mark of the current position. - - // Scanner stuff - - stream_start_produced bool // Have we started to scan the input stream? - stream_end_produced bool // Have we reached the end of the input stream? - - flow_level int // The number of unclosed '[' and '{' indicators. - - tokens []yaml_token_t // The tokens queue. - tokens_head int // The head of the tokens queue. - tokens_parsed int // The number of tokens fetched from the queue. - token_available bool // Does the tokens queue contain a token ready for dequeueing. - - indent int // The current indentation level. - indents []int // The indentation levels stack. - - simple_key_allowed bool // May a simple key occur at the current position? - simple_keys []yaml_simple_key_t // The stack of simple keys. - simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number - - // Parser stuff - - state yaml_parser_state_t // The current parser state. - states []yaml_parser_state_t // The parser states stack. - marks []yaml_mark_t // The stack of marks. - tag_directives []yaml_tag_directive_t // The list of TAG directives. - - // Dumper stuff - - aliases []yaml_alias_data_t // The alias data. - - document *yaml_document_t // The currently parsed document. -} - -// Emitter Definitions - -// The prototype of a write handler. -// -// The write handler is called when the emitter needs to flush the accumulated -// characters to the output. The handler should write @a size bytes of the -// @a buffer to the output. -// -// @param[in,out] data A pointer to an application data specified by -// yaml_emitter_set_output(). -// @param[in] buffer The buffer with bytes to be written. -// @param[in] size The size of the buffer. -// -// @returns On success, the handler should return @c 1. If the handler failed, -// the returned value should be @c 0. -// -type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error - -type yaml_emitter_state_t int - -// The emitter states. -const ( - // Expect STREAM-START. - yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota - - yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. - yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. - yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. - yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. - yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. - yaml_EMIT_END_STATE // Expect nothing. -) - -// The emitter structure. -// -// All members are internal. Manage the structure using the @c yaml_emitter_ -// family of functions. -type yaml_emitter_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - problem string // Error description. - - // Writer stuff - - write_handler yaml_write_handler_t // Write handler. - - output_buffer *[]byte // String output data. - output_writer io.Writer // File output data. - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The stream encoding. - - // Emitter stuff - - canonical bool // If the output is in the canonical style? - best_indent int // The number of indentation spaces. - best_width int // The preferred width of the output lines. - unicode bool // Allow unescaped non-ASCII characters? - line_break yaml_break_t // The preferred line break. - - state yaml_emitter_state_t // The current emitter state. - states []yaml_emitter_state_t // The stack of states. - - events []yaml_event_t // The event queue. - events_head int // The head of the event queue. - - indents []int // The stack of indentation levels. - - tag_directives []yaml_tag_directive_t // The list of tag directives. - - indent int // The current indentation level. - - flow_level int // The current flow level. - - root_context bool // Is it the document root context? - sequence_context bool // Is it a sequence context? - mapping_context bool // Is it a mapping context? - simple_key_context bool // Is it a simple mapping key context? - - line int // The current line. - column int // The current column. - whitespace bool // If the last character was a whitespace? - indention bool // If the last character was an indentation character (' ', '-', '?', ':')? - open_ended bool // If an explicit document end is required? - - // Anchor analysis. - anchor_data struct { - anchor []byte // The anchor value. - alias bool // Is it an alias? - } - - // Tag analysis. - tag_data struct { - handle []byte // The tag handle. - suffix []byte // The tag suffix. - } - - // Scalar analysis. - scalar_data struct { - value []byte // The scalar value. - multiline bool // Does the scalar contain line breaks? - flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? - block_plain_allowed bool // Can the scalar be expressed in the block plain style? - single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? - block_allowed bool // Can the scalar be expressed in the literal or folded styles? - style yaml_scalar_style_t // The output style. - } - - // Dumper stuff - - opened bool // If the stream was already opened? - closed bool // If the stream was already closed? - - // The information associated with the document nodes. - anchors *struct { - references int // The number of references. - anchor int // The anchor id. - serialized bool // If the node has been emitted? - } - - last_anchor_id int // The last assigned anchor id. - - document *yaml_document_t // The currently emitted document. -} diff --git a/vendor/gopkg.in/yaml.v2/yamlprivateh.go b/vendor/gopkg.in/yaml.v2/yamlprivateh.go deleted file mode 100644 index 8110ce3c..00000000 --- a/vendor/gopkg.in/yaml.v2/yamlprivateh.go +++ /dev/null @@ -1,173 +0,0 @@ -package yaml - -const ( - // The size of the input raw buffer. - input_raw_buffer_size = 512 - - // The size of the input buffer. - // It should be possible to decode the whole raw buffer. - input_buffer_size = input_raw_buffer_size * 3 - - // The size of the output buffer. - output_buffer_size = 128 - - // The size of the output raw buffer. - // It should be possible to encode the whole output buffer. - output_raw_buffer_size = (output_buffer_size*2 + 2) - - // The size of other stacks and queues. - initial_stack_size = 16 - initial_queue_size = 16 - initial_string_size = 16 -) - -// Check if the character at the specified position is an alphabetical -// character, a digit, '_', or '-'. -func is_alpha(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' -} - -// Check if the character at the specified position is a digit. -func is_digit(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' -} - -// Get the value of a digit. -func as_digit(b []byte, i int) int { - return int(b[i]) - '0' -} - -// Check if the character at the specified position is a hex-digit. -func is_hex(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' -} - -// Get the value of a hex-digit. -func as_hex(b []byte, i int) int { - bi := b[i] - if bi >= 'A' && bi <= 'F' { - return int(bi) - 'A' + 10 - } - if bi >= 'a' && bi <= 'f' { - return int(bi) - 'a' + 10 - } - return int(bi) - '0' -} - -// Check if the character is ASCII. -func is_ascii(b []byte, i int) bool { - return b[i] <= 0x7F -} - -// Check if the character at the start of the buffer can be printed unescaped. -func is_printable(b []byte, i int) bool { - return ((b[i] == 0x0A) || // . == #x0A - (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E - (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF - (b[i] > 0xC2 && b[i] < 0xED) || - (b[i] == 0xED && b[i+1] < 0xA0) || - (b[i] == 0xEE) || - (b[i] == 0xEF && // #xE000 <= . <= #xFFFD - !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF - !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) -} - -// Check if the character at the specified position is NUL. -func is_z(b []byte, i int) bool { - return b[i] == 0x00 -} - -// Check if the beginning of the buffer is a BOM. -func is_bom(b []byte, i int) bool { - return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF -} - -// Check if the character at the specified position is space. -func is_space(b []byte, i int) bool { - return b[i] == ' ' -} - -// Check if the character at the specified position is tab. -func is_tab(b []byte, i int) bool { - return b[i] == '\t' -} - -// Check if the character at the specified position is blank (space or tab). -func is_blank(b []byte, i int) bool { - //return is_space(b, i) || is_tab(b, i) - return b[i] == ' ' || b[i] == '\t' -} - -// Check if the character at the specified position is a line break. -func is_break(b []byte, i int) bool { - return (b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) -} - -func is_crlf(b []byte, i int) bool { - return b[i] == '\r' && b[i+1] == '\n' -} - -// Check if the character is a line break or NUL. -func is_breakz(b []byte, i int) bool { - //return is_break(b, i) || is_z(b, i) - return ( // is_break: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - // is_z: - b[i] == 0) -} - -// Check if the character is a line break, space, or NUL. -func is_spacez(b []byte, i int) bool { - //return is_space(b, i) || is_breakz(b, i) - return ( // is_space: - b[i] == ' ' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Check if the character is a line break, space, tab, or NUL. -func is_blankz(b []byte, i int) bool { - //return is_blank(b, i) || is_breakz(b, i) - return ( // is_blank: - b[i] == ' ' || b[i] == '\t' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Determine the width of the character. -func width(b byte) int { - // Don't replace these by a switch without first - // confirming that it is being inlined. - if b&0x80 == 0x00 { - return 1 - } - if b&0xE0 == 0xC0 { - return 2 - } - if b&0xF0 == 0xE0 { - return 3 - } - if b&0xF8 == 0xF0 { - return 4 - } - return 0 - -} diff --git a/vendor/modules.txt b/vendor/modules.txt index adcb79c3..87008849 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -5,69 +5,12 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate ## explicit; go 1.21 connectrpc.com/connect connectrpc.com/connect/internal/gen/connectext/grpc/status/v1 -# connectrpc.com/cors v0.1.0 -## explicit; go 1.19 -connectrpc.com/cors -# connectrpc.com/otelconnect v0.7.2 -## explicit; go 1.21 -connectrpc.com/otelconnect # github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 ## explicit github.com/99designs/go-keychain # github.com/99designs/keyring v1.2.2 ## explicit; go 1.19 github.com/99designs/keyring -# github.com/Microsoft/go-winio v0.6.2 -## explicit; go 1.21 -github.com/Microsoft/go-winio -github.com/Microsoft/go-winio/internal/fs -github.com/Microsoft/go-winio/internal/socket -github.com/Microsoft/go-winio/internal/stringbuffer -github.com/Microsoft/go-winio/pkg/guid -# github.com/NimbleMarkets/ntcharts v0.1.2 -## explicit; go 1.22.0 -github.com/NimbleMarkets/ntcharts/canvas -github.com/NimbleMarkets/ntcharts/canvas/buffer -github.com/NimbleMarkets/ntcharts/canvas/graph -github.com/NimbleMarkets/ntcharts/canvas/runes -github.com/NimbleMarkets/ntcharts/linechart -github.com/NimbleMarkets/ntcharts/linechart/timeserieslinechart -# github.com/ProtonMail/go-crypto v1.3.0 -## explicit; go 1.22.0 -github.com/ProtonMail/go-crypto/bitcurves -github.com/ProtonMail/go-crypto/brainpool -github.com/ProtonMail/go-crypto/eax -github.com/ProtonMail/go-crypto/internal/byteutil -github.com/ProtonMail/go-crypto/ocb -github.com/ProtonMail/go-crypto/openpgp -github.com/ProtonMail/go-crypto/openpgp/aes/keywrap -github.com/ProtonMail/go-crypto/openpgp/armor -github.com/ProtonMail/go-crypto/openpgp/ecdh -github.com/ProtonMail/go-crypto/openpgp/ecdsa -github.com/ProtonMail/go-crypto/openpgp/ed25519 -github.com/ProtonMail/go-crypto/openpgp/ed448 -github.com/ProtonMail/go-crypto/openpgp/eddsa -github.com/ProtonMail/go-crypto/openpgp/elgamal -github.com/ProtonMail/go-crypto/openpgp/errors -github.com/ProtonMail/go-crypto/openpgp/internal/algorithm -github.com/ProtonMail/go-crypto/openpgp/internal/ecc -github.com/ProtonMail/go-crypto/openpgp/internal/encoding -github.com/ProtonMail/go-crypto/openpgp/packet -github.com/ProtonMail/go-crypto/openpgp/s2k -github.com/ProtonMail/go-crypto/openpgp/x25519 -github.com/ProtonMail/go-crypto/openpgp/x448 -# github.com/alecthomas/chroma/v2 v2.14.0 -## explicit; go 1.19 -github.com/alecthomas/chroma/v2 -github.com/alecthomas/chroma/v2/formatters -github.com/alecthomas/chroma/v2/formatters/html -github.com/alecthomas/chroma/v2/formatters/svg -github.com/alecthomas/chroma/v2/lexers -github.com/alecthomas/chroma/v2/quick -github.com/alecthomas/chroma/v2/styles -# github.com/atotto/clipboard v0.1.4 -## explicit -github.com/atotto/clipboard # github.com/aybabtme/flatjson v0.1.3-0.20250507081407-dfee75a600e6 ## explicit; go 1.24 github.com/aybabtme/flatjson @@ -77,64 +20,18 @@ github.com/aybabtme/rgbterm # github.com/aymanbagabas/go-osc52/v2 v2.0.1 ## explicit; go 1.16 github.com/aymanbagabas/go-osc52/v2 -# github.com/aymerick/douceur v0.2.0 -## explicit -github.com/aymerick/douceur/css -github.com/aymerick/douceur/parser -# github.com/beorn7/perks v1.0.1 -## explicit; go 1.11 -github.com/beorn7/perks/quantile # github.com/blang/semver v3.5.1+incompatible ## explicit github.com/blang/semver -# github.com/catppuccin/go v0.3.0 -## explicit; go 1.19 -github.com/catppuccin/go -# github.com/cenkalti/backoff/v4 v4.3.0 -## explicit; go 1.18 -github.com/cenkalti/backoff/v4 -# github.com/cenkalti/backoff/v5 v5.0.3 -## explicit; go 1.23 -github.com/cenkalti/backoff/v5 # github.com/cespare/xxhash v1.1.0 ## explicit github.com/cespare/xxhash -# github.com/cespare/xxhash/v2 v2.3.0 -## explicit; go 1.11 -github.com/cespare/xxhash/v2 -# github.com/charmbracelet/bubbles v0.21.0 -## explicit; go 1.23.0 -github.com/charmbracelet/bubbles/cursor -github.com/charmbracelet/bubbles/filepicker -github.com/charmbracelet/bubbles/help -github.com/charmbracelet/bubbles/key -github.com/charmbracelet/bubbles/runeutil -github.com/charmbracelet/bubbles/spinner -github.com/charmbracelet/bubbles/textarea -github.com/charmbracelet/bubbles/textarea/memoization -github.com/charmbracelet/bubbles/textinput -github.com/charmbracelet/bubbles/viewport -# github.com/charmbracelet/bubbletea v1.3.4 -## explicit; go 1.18 -github.com/charmbracelet/bubbletea # github.com/charmbracelet/colorprofile v0.3.2 ## explicit; go 1.23.0 github.com/charmbracelet/colorprofile -# github.com/charmbracelet/glamour v0.10.0 -## explicit; go 1.23.0 -github.com/charmbracelet/glamour -github.com/charmbracelet/glamour/ansi -github.com/charmbracelet/glamour/internal/autolink -github.com/charmbracelet/glamour/styles -# github.com/charmbracelet/huh v0.7.0 -## explicit; go 1.23.0 -github.com/charmbracelet/huh -github.com/charmbracelet/huh/internal/accessibility -github.com/charmbracelet/huh/internal/selector # github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 ## explicit; go 1.18 github.com/charmbracelet/lipgloss -github.com/charmbracelet/lipgloss/table # github.com/charmbracelet/log v0.4.2 ## explicit; go 1.19 github.com/charmbracelet/log @@ -145,12 +42,6 @@ github.com/charmbracelet/x/ansi/parser # github.com/charmbracelet/x/cellbuf v0.0.13 ## explicit; go 1.18 github.com/charmbracelet/x/cellbuf -# github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf -## explicit; go 1.19 -github.com/charmbracelet/x/exp/slice -# github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 -## explicit; go 1.19 -github.com/charmbracelet/x/exp/strings # github.com/charmbracelet/x/term v0.2.1 ## explicit; go 1.18 github.com/charmbracelet/x/term @@ -161,45 +52,15 @@ github.com/cli/safeexec ## explicit; go 1.18 github.com/clipperhouse/uax29/v2/graphemes github.com/clipperhouse/uax29/v2/internal/iterators -# github.com/cloudflare/circl v1.6.1 -## explicit; go 1.22.0 -github.com/cloudflare/circl/dh/x25519 -github.com/cloudflare/circl/dh/x448 -github.com/cloudflare/circl/ecc/goldilocks -github.com/cloudflare/circl/internal/conv -github.com/cloudflare/circl/internal/sha3 -github.com/cloudflare/circl/math -github.com/cloudflare/circl/math/fp25519 -github.com/cloudflare/circl/math/fp448 -github.com/cloudflare/circl/math/mlsbset -github.com/cloudflare/circl/sign -github.com/cloudflare/circl/sign/ed25519 -github.com/cloudflare/circl/sign/ed448 # github.com/cpuguy83/go-md2man/v2 v2.0.7 ## explicit; go 1.12 github.com/cpuguy83/go-md2man/v2/md2man -# github.com/crazy3lf/colorconv v1.2.0 -## explicit; go 1.17 -github.com/crazy3lf/colorconv -# github.com/cyphar/filepath-securejoin v0.4.1 -## explicit; go 1.18 -github.com/cyphar/filepath-securejoin # github.com/danieljoos/wincred v1.2.0 ## explicit; go 1.18 github.com/danieljoos/wincred # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit github.com/davecgh/go-spew/spew -# github.com/dennwc/varint v1.0.0 -## explicit; go 1.12 -github.com/dennwc/varint -# github.com/dlclark/regexp2 v1.11.0 -## explicit; go 1.13 -github.com/dlclark/regexp2 -github.com/dlclark/regexp2/syntax -# github.com/dustin/go-humanize v1.0.1 -## explicit; go 1.16 -github.com/dustin/go-humanize # github.com/dvsekhvalnov/jose2go v1.6.0 ## explicit; go 1.15 github.com/dvsekhvalnov/jose2go @@ -210,155 +71,15 @@ github.com/dvsekhvalnov/jose2go/compact github.com/dvsekhvalnov/jose2go/kdf github.com/dvsekhvalnov/jose2go/keys/ecc github.com/dvsekhvalnov/jose2go/padding -# github.com/edsrzf/mmap-go v1.2.0 -## explicit; go 1.17 -github.com/edsrzf/mmap-go -# github.com/emirpasic/gods v1.18.1 -## explicit; go 1.2 -github.com/emirpasic/gods/containers -github.com/emirpasic/gods/lists -github.com/emirpasic/gods/lists/arraylist -github.com/emirpasic/gods/trees -github.com/emirpasic/gods/trees/binaryheap -github.com/emirpasic/gods/utils -# github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f -## explicit; go 1.16 -github.com/erikgeiser/coninput -# github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb -## explicit -github.com/facette/natsort # github.com/fatih/color v1.18.0 ## explicit; go 1.17 github.com/fatih/color -# github.com/felixge/httpsnoop v1.0.4 -## explicit; go 1.13 -github.com/felixge/httpsnoop -# github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4 -## explicit; go 1.14 -github.com/gen2brain/beeep -# github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 -## explicit -github.com/getlantern/context -# github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 -## explicit -github.com/getlantern/errors -# github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 -## explicit; go 1.12 -github.com/getlantern/golog -# github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 -## explicit -github.com/getlantern/hex -# github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 -## explicit -github.com/getlantern/hidden -# github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f -## explicit -github.com/getlantern/ops -# github.com/getlantern/systray v1.2.2 -## explicit; go 1.13 -github.com/getlantern/systray -# github.com/go-git/gcfg/v2 v2.0.2 -## explicit; go 1.21 -github.com/go-git/gcfg/v2 -github.com/go-git/gcfg/v2/scanner -github.com/go-git/gcfg/v2/token -github.com/go-git/gcfg/v2/types -# github.com/go-git/go-billy/v6 v6.0.0-20250627091229-31e2a16eef30 -## explicit; go 1.23.0 -github.com/go-git/go-billy/v6 -github.com/go-git/go-billy/v6/helper/chroot -github.com/go-git/go-billy/v6/helper/polyfill -github.com/go-git/go-billy/v6/memfs -github.com/go-git/go-billy/v6/osfs -github.com/go-git/go-billy/v6/util -# github.com/go-git/go-git/v6 v6.0.0-20250923192830-1ad5b9c7da82 -## explicit; go 1.23.0 -github.com/go-git/go-git/v6 -github.com/go-git/go-git/v6/config -github.com/go-git/go-git/v6/internal/path_util -github.com/go-git/go-git/v6/internal/reference -github.com/go-git/go-git/v6/internal/repository -github.com/go-git/go-git/v6/internal/revision -github.com/go-git/go-git/v6/internal/url -github.com/go-git/go-git/v6/plumbing -github.com/go-git/go-git/v6/plumbing/cache -github.com/go-git/go-git/v6/plumbing/color -github.com/go-git/go-git/v6/plumbing/filemode -github.com/go-git/go-git/v6/plumbing/format/config -github.com/go-git/go-git/v6/plumbing/format/diff -github.com/go-git/go-git/v6/plumbing/format/gitignore -github.com/go-git/go-git/v6/plumbing/format/idxfile -github.com/go-git/go-git/v6/plumbing/format/index -github.com/go-git/go-git/v6/plumbing/format/objfile -github.com/go-git/go-git/v6/plumbing/format/packfile -github.com/go-git/go-git/v6/plumbing/format/pktline -github.com/go-git/go-git/v6/plumbing/hash -github.com/go-git/go-git/v6/plumbing/object -github.com/go-git/go-git/v6/plumbing/protocol -github.com/go-git/go-git/v6/plumbing/protocol/packp -github.com/go-git/go-git/v6/plumbing/protocol/packp/capability -github.com/go-git/go-git/v6/plumbing/protocol/packp/sideband -github.com/go-git/go-git/v6/plumbing/revlist -github.com/go-git/go-git/v6/plumbing/storer -github.com/go-git/go-git/v6/plumbing/transport -github.com/go-git/go-git/v6/plumbing/transport/file -github.com/go-git/go-git/v6/plumbing/transport/git -github.com/go-git/go-git/v6/plumbing/transport/http -github.com/go-git/go-git/v6/plumbing/transport/ssh -github.com/go-git/go-git/v6/plumbing/transport/ssh/knownhosts -github.com/go-git/go-git/v6/plumbing/transport/ssh/sshagent -github.com/go-git/go-git/v6/storage -github.com/go-git/go-git/v6/storage/filesystem -github.com/go-git/go-git/v6/storage/filesystem/dotgit -github.com/go-git/go-git/v6/storage/memory -github.com/go-git/go-git/v6/utils/binary -github.com/go-git/go-git/v6/utils/convert -github.com/go-git/go-git/v6/utils/diff -github.com/go-git/go-git/v6/utils/ioutil -github.com/go-git/go-git/v6/utils/merkletrie -github.com/go-git/go-git/v6/utils/merkletrie/filesystem -github.com/go-git/go-git/v6/utils/merkletrie/index -github.com/go-git/go-git/v6/utils/merkletrie/internal/frame -github.com/go-git/go-git/v6/utils/merkletrie/noder -github.com/go-git/go-git/v6/utils/sync -github.com/go-git/go-git/v6/utils/trace -# github.com/go-jose/go-jose/v4 v4.1.1 -## explicit; go 1.23.0 -github.com/go-jose/go-jose/v4 -github.com/go-jose/go-jose/v4/cipher -github.com/go-jose/go-jose/v4/json # github.com/go-logfmt/logfmt v0.6.1 ## explicit; go 1.21 github.com/go-logfmt/logfmt -# github.com/go-logr/logr v1.4.3 -## explicit; go 1.18 -github.com/go-logr/logr -github.com/go-logr/logr/funcr -# github.com/go-logr/stdr v1.2.2 -## explicit; go 1.16 -github.com/go-logr/stdr -# github.com/go-stack/stack v1.8.0 -## explicit -github.com/go-stack/stack -# github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 -## explicit -github.com/go-toast/toast # github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 ## explicit; go 1.12 github.com/godbus/dbus -# github.com/godbus/dbus/v5 v5.1.0 -## explicit; go 1.12 -github.com/godbus/dbus/v5 -# github.com/gogo/protobuf v1.3.2 -## explicit; go 1.15 -github.com/gogo/protobuf/gogoproto -github.com/gogo/protobuf/proto -github.com/gogo/protobuf/protoc-gen-gogo/descriptor -github.com/gogo/protobuf/sortkeys -github.com/gogo/protobuf/types -# github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 -## explicit; go 1.20 -github.com/golang/groupcache/lru # github.com/google/go-cmp v0.7.0 ## explicit; go 1.21 github.com/google/go-cmp/cmp @@ -367,16 +88,6 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/uuid v1.6.0 -## explicit -github.com/google/uuid -# github.com/gorilla/css v1.0.1 -## explicit; go 1.20 -github.com/gorilla/css/scanner -# github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc -## explicit; go 1.21 -github.com/grafana/regexp -github.com/grafana/regexp/syntax # github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 ## explicit; go 1.23.0 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule @@ -385,467 +96,110 @@ github.com/grpc-ecosystem/grpc-gateway/v2/utilities # github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c ## explicit github.com/gsterjov/go-libsecret -# github.com/jpillora/backoff v1.0.0 -## explicit; go 1.13 -github.com/jpillora/backoff -# github.com/kardianos/service v1.2.2 -## explicit; go 1.12 -github.com/kardianos/service -# github.com/kevinburke/ssh_config v1.4.0 -## explicit; go 1.18 -github.com/kevinburke/ssh_config -# github.com/klauspost/cpuid/v2 v2.3.0 -## explicit; go 1.22 -github.com/klauspost/cpuid/v2 # github.com/kr/logfmt v0.0.0-20210122060352-19f9bcb100e6 ## explicit; go 1.14 github.com/kr/logfmt -# github.com/lrstanley/bubblezone v0.0.0-20240914071701-b48c55a5e78e -## explicit; go 1.19 -github.com/lrstanley/bubblezone # github.com/lucasb-eyer/go-colorful v1.3.0 ## explicit; go 1.12 github.com/lucasb-eyer/go-colorful -# github.com/matoous/go-nanoid v1.5.0 -## explicit; go 1.15 -github.com/matoous/go-nanoid # github.com/mattn/go-colorable v0.1.14 ## explicit; go 1.18 github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.20 ## explicit; go 1.15 github.com/mattn/go-isatty -# github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 -## explicit -github.com/mattn/go-localereader # github.com/mattn/go-runewidth v0.0.19 ## explicit; go 1.20 github.com/mattn/go-runewidth -# github.com/microcosm-cc/bluemonday v1.0.27 -## explicit; go 1.19 -github.com/microcosm-cc/bluemonday -github.com/microcosm-cc/bluemonday/css # github.com/minitape/api/go v0.0.0-20260314053553-971e5e26bafc ## explicit; go 1.25 -github.com/minitape/api/go/svc/alert/v1 -github.com/minitape/api/go/svc/alert/v1/alertv1connect -github.com/minitape/api/go/svc/auth/v1 -github.com/minitape/api/go/svc/auth/v1/authv1connect github.com/minitape/api/go/svc/cliupdate/v1 github.com/minitape/api/go/svc/cliupdate/v1/cliupdatev1connect -github.com/minitape/api/go/svc/dashboard/v1 -github.com/minitape/api/go/svc/dashboard/v1/dashboardv1connect -github.com/minitape/api/go/svc/feature/v1 -github.com/minitape/api/go/svc/feature/v1/featurev1connect -github.com/minitape/api/go/svc/ingest/v1 -github.com/minitape/api/go/svc/ingest/v1/ingestv1connect -github.com/minitape/api/go/svc/localhost/v1 -github.com/minitape/api/go/svc/localhost/v1/localhostv1connect -github.com/minitape/api/go/svc/organization/v1 -github.com/minitape/api/go/svc/organization/v1/organizationv1connect -github.com/minitape/api/go/svc/product/v1 -github.com/minitape/api/go/svc/product/v1/productv1connect -github.com/minitape/api/go/svc/project/v1 -github.com/minitape/api/go/svc/project/v1/projectv1connect -github.com/minitape/api/go/svc/query/v1 -github.com/minitape/api/go/svc/query/v1/queryv1connect -github.com/minitape/api/go/svc/token/v1 -github.com/minitape/api/go/svc/token/v1/tokenv1connect -github.com/minitape/api/go/svc/user/v1 -github.com/minitape/api/go/svc/user/v1/userv1connect github.com/minitape/api/go/types/v1 # github.com/mitchellh/go-homedir v1.1.0 ## explicit github.com/mitchellh/go-homedir -# github.com/mitchellh/hashstructure/v2 v2.0.2 -## explicit; go 1.14 -github.com/mitchellh/hashstructure/v2 # github.com/mtibben/percent v0.2.1 ## explicit; go 1.14 github.com/mtibben/percent -# github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 -## explicit; go 1.17 -github.com/muesli/ansi -github.com/muesli/ansi/compressor -# github.com/muesli/cancelreader v0.2.2 -## explicit; go 1.17 -github.com/muesli/cancelreader -# github.com/muesli/reflow v0.3.0 -## explicit; go 1.13 -github.com/muesli/reflow/ansi -github.com/muesli/reflow/indent -github.com/muesli/reflow/padding -github.com/muesli/reflow/wordwrap # github.com/muesli/termenv v0.16.0 ## explicit; go 1.17 github.com/muesli/termenv -# github.com/muhlemmer/gu v0.3.1 -## explicit; go 1.18 -github.com/muhlemmer/gu -# github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 -## explicit -github.com/munnerz/goautoneg -# github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f -## explicit -github.com/mwitkow/go-conntrack -# github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d -## explicit -github.com/nu7hatch/gouuid # github.com/oklog/ulid/v2 v2.1.1 ## explicit; go 1.15 github.com/oklog/ulid/v2 -# github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c -## explicit; go 1.12 -github.com/oxtoacart/bpool -# github.com/perses/perses v0.51.1 -## explicit; go 1.24.0 -github.com/perses/perses/pkg/model/api -github.com/perses/perses/pkg/model/api/v1 -github.com/perses/perses/pkg/model/api/v1/common -github.com/perses/perses/pkg/model/api/v1/dashboard -github.com/perses/perses/pkg/model/api/v1/plugin -github.com/perses/perses/pkg/model/api/v1/role -github.com/perses/perses/pkg/model/api/v1/secret -github.com/perses/perses/pkg/model/api/v1/variable -# github.com/pjbgf/sha1cd v0.5.0 -## explicit; go 1.22 -github.com/pjbgf/sha1cd -github.com/pjbgf/sha1cd/internal -github.com/pjbgf/sha1cd/ubc -# github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c -## explicit; go 1.14 -github.com/pkg/browser # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/prometheus/client_golang v1.22.0 -## explicit; go 1.22 -github.com/prometheus/client_golang/prometheus -github.com/prometheus/client_golang/prometheus/internal -# github.com/prometheus/client_model v0.6.2 -## explicit; go 1.22.0 -github.com/prometheus/client_model/go -# github.com/prometheus/common v0.65.0 -## explicit; go 1.23.0 -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/procfs v0.15.1 -## explicit; go 1.20 -github.com/prometheus/procfs -github.com/prometheus/procfs/internal/fs -github.com/prometheus/procfs/internal/util -# github.com/prometheus/prometheus v0.305.0 -## explicit; go 1.23.0 -github.com/prometheus/prometheus/model/exemplar -github.com/prometheus/prometheus/model/histogram -github.com/prometheus/prometheus/model/labels -github.com/prometheus/prometheus/model/metadata -github.com/prometheus/prometheus/model/rulefmt -github.com/prometheus/prometheus/model/textparse -github.com/prometheus/prometheus/model/timestamp -github.com/prometheus/prometheus/model/value -github.com/prometheus/prometheus/prompb/io/prometheus/client -github.com/prometheus/prometheus/promql -github.com/prometheus/prometheus/promql/parser -github.com/prometheus/prometheus/promql/parser/posrange -github.com/prometheus/prometheus/schema -github.com/prometheus/prometheus/storage -github.com/prometheus/prometheus/template -github.com/prometheus/prometheus/tsdb/chunkenc -github.com/prometheus/prometheus/tsdb/chunks -github.com/prometheus/prometheus/tsdb/errors -github.com/prometheus/prometheus/tsdb/fileutil -github.com/prometheus/prometheus/util/almost -github.com/prometheus/prometheus/util/annotations -github.com/prometheus/prometheus/util/convertnhcb -github.com/prometheus/prometheus/util/logging -github.com/prometheus/prometheus/util/stats -github.com/prometheus/prometheus/util/strutil -github.com/prometheus/prometheus/util/zeropool # github.com/rivo/uniseg v0.4.7 ## explicit; go 1.18 github.com/rivo/uniseg -# github.com/rs/cors v1.11.1 -## explicit; go 1.13 -github.com/rs/cors -github.com/rs/cors/internal +# github.com/rogpeppe/go-internal v1.14.1 +## explicit; go 1.23 # github.com/russross/blackfriday/v2 v2.1.0 ## explicit github.com/russross/blackfriday/v2 # github.com/ryanuber/go-glob v1.0.0 ## explicit github.com/ryanuber/go-glob -# github.com/sergi/go-diff v1.4.0 -## explicit; go 1.13 -github.com/sergi/go-diff/diffmatchpatch # github.com/stretchr/testify v1.11.1 ## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/assert/yaml github.com/stretchr/testify/require -# github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af -## explicit -github.com/tadvi/systray # github.com/urfave/cli v1.22.14 ## explicit; go 1.11 github.com/urfave/cli # github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e ## explicit; go 1.19 github.com/xo/terminfo -# github.com/yuin/goldmark v1.7.8 -## explicit; go 1.19 -github.com/yuin/goldmark -github.com/yuin/goldmark/ast -github.com/yuin/goldmark/extension -github.com/yuin/goldmark/extension/ast -github.com/yuin/goldmark/parser -github.com/yuin/goldmark/renderer -github.com/yuin/goldmark/renderer/html -github.com/yuin/goldmark/text -github.com/yuin/goldmark/util -# github.com/yuin/goldmark-emoji v1.0.5 -## explicit; go 1.15 -github.com/yuin/goldmark-emoji -github.com/yuin/goldmark-emoji/ast -github.com/yuin/goldmark-emoji/definition -# github.com/zeebo/assert v1.3.0 -## explicit; go 1.13 -# github.com/zeebo/blake3 v0.2.4 -## explicit; go 1.18 -github.com/zeebo/blake3 -github.com/zeebo/blake3/internal/alg -github.com/zeebo/blake3/internal/alg/compress -github.com/zeebo/blake3/internal/alg/compress/compress_pure -github.com/zeebo/blake3/internal/alg/compress/compress_sse41 -github.com/zeebo/blake3/internal/alg/hash -github.com/zeebo/blake3/internal/alg/hash/hash_avx2 -github.com/zeebo/blake3/internal/alg/hash/hash_pure -github.com/zeebo/blake3/internal/consts -github.com/zeebo/blake3/internal/utils -# github.com/zitadel/oidc/v3 v3.38.1 -## explicit; go 1.23.7 -github.com/zitadel/oidc/v3/pkg/crypto -github.com/zitadel/oidc/v3/pkg/oidc -# github.com/zitadel/schema v1.3.1 -## explicit; go 1.23.7 -github.com/zitadel/schema -# go.opentelemetry.io/auto/sdk v1.1.0 -## explicit; go 1.22.0 -go.opentelemetry.io/auto/sdk -go.opentelemetry.io/auto/sdk/internal/telemetry -# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 -## explicit; go 1.22.0 -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal -# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 -## explicit; go 1.23.0 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil -# go.opentelemetry.io/contrib/propagators/b3 v1.35.0 -## explicit; go 1.22.0 -go.opentelemetry.io/contrib/propagators/b3 -# go.opentelemetry.io/contrib/propagators/ot v1.35.0 -## explicit; go 1.22.0 -go.opentelemetry.io/contrib/propagators/ot # go.opentelemetry.io/otel v1.38.0 ## explicit; go 1.23.0 -go.opentelemetry.io/otel go.opentelemetry.io/otel/attribute go.opentelemetry.io/otel/attribute/internal -go.opentelemetry.io/otel/baggage -go.opentelemetry.io/otel/codes -go.opentelemetry.io/otel/internal/baggage -go.opentelemetry.io/otel/internal/global -go.opentelemetry.io/otel/propagation -go.opentelemetry.io/otel/semconv/v1.17.0 -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/semconv/v1.34.0 -go.opentelemetry.io/otel/semconv/v1.37.0 -go.opentelemetry.io/otel/semconv/v1.37.0/otelconv -# go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 -## explicit; go 1.22.0 -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/oconf -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/retry -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/transform -# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 -## explicit; go 1.23.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.36.0 -## explicit; go 1.23.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.38.0 -## explicit; go 1.23.0 -go.opentelemetry.io/otel/metric -go.opentelemetry.io/otel/metric/embedded -go.opentelemetry.io/otel/metric/noop -# go.opentelemetry.io/otel/sdk v1.38.0 -## explicit; go 1.23.0 -go.opentelemetry.io/otel/sdk -go.opentelemetry.io/otel/sdk/instrumentation -go.opentelemetry.io/otel/sdk/internal/env -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/internal/x # go.opentelemetry.io/otel/sdk/metric v1.38.0 ## explicit; go 1.23.0 -go.opentelemetry.io/otel/sdk/metric -go.opentelemetry.io/otel/sdk/metric/exemplar -go.opentelemetry.io/otel/sdk/metric/internal -go.opentelemetry.io/otel/sdk/metric/internal/aggregate -go.opentelemetry.io/otel/sdk/metric/internal/x -go.opentelemetry.io/otel/sdk/metric/metricdata -# go.opentelemetry.io/otel/trace v1.38.0 -## explicit; go 1.23.0 -go.opentelemetry.io/otel/trace -go.opentelemetry.io/otel/trace/embedded -go.opentelemetry.io/otel/trace/internal/telemetry -go.opentelemetry.io/otel/trace/noop # go.opentelemetry.io/proto/otlp v1.8.0 ## explicit; go 1.23.0 go.opentelemetry.io/proto/otlp/collector/logs/v1 -go.opentelemetry.io/proto/otlp/collector/metrics/v1 -go.opentelemetry.io/proto/otlp/collector/trace/v1 go.opentelemetry.io/proto/otlp/common/v1 go.opentelemetry.io/proto/otlp/logs/v1 -go.opentelemetry.io/proto/otlp/metrics/v1 go.opentelemetry.io/proto/otlp/resource/v1 -go.opentelemetry.io/proto/otlp/trace/v1 -# go.opentelemetry.io/proto/otlp/collector/profiles/v1development v0.1.0 -## explicit; go 1.23.0 -go.opentelemetry.io/proto/otlp/collector/profiles/v1development -# go.opentelemetry.io/proto/otlp/profiles/v1development v0.0.0-20250721084824-6f76ca90124d -## explicit; go 1.23.0 -go.opentelemetry.io/proto/otlp/profiles/v1development -# go.uber.org/atomic v1.11.0 -## explicit; go 1.18 -go.uber.org/atomic -# go.uber.org/multierr v1.11.0 -## explicit; go 1.19 -go.uber.org/multierr -# golang.org/x/crypto v0.41.0 -## explicit; go 1.23.0 -golang.org/x/crypto/argon2 -golang.org/x/crypto/blake2b -golang.org/x/crypto/blowfish -golang.org/x/crypto/cast5 -golang.org/x/crypto/chacha20 -golang.org/x/crypto/cryptobyte -golang.org/x/crypto/cryptobyte/asn1 -golang.org/x/crypto/curve25519 -golang.org/x/crypto/hkdf -golang.org/x/crypto/internal/alias -golang.org/x/crypto/internal/poly1305 -golang.org/x/crypto/pbkdf2 -golang.org/x/crypto/sha3 -golang.org/x/crypto/ssh -golang.org/x/crypto/ssh/agent -golang.org/x/crypto/ssh/internal/bcrypt_pbkdf -golang.org/x/crypto/ssh/knownhosts # golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 ## explicit; go 1.23.0 -golang.org/x/exp/rand golang.org/x/exp/slices golang.org/x/exp/slog golang.org/x/exp/slog/internal golang.org/x/exp/slog/internal/buffer # golang.org/x/net v0.43.0 ## explicit; go 1.23.0 -golang.org/x/net/html -golang.org/x/net/html/atom golang.org/x/net/http/httpguts -golang.org/x/net/http/httpproxy golang.org/x/net/http2 -golang.org/x/net/http2/h2c golang.org/x/net/http2/hpack golang.org/x/net/idna golang.org/x/net/internal/httpcommon -golang.org/x/net/internal/socks golang.org/x/net/internal/timeseries -golang.org/x/net/proxy golang.org/x/net/trace -# golang.org/x/oauth2 v0.30.0 -## explicit; go 1.23.0 -golang.org/x/oauth2 -golang.org/x/oauth2/clientcredentials -golang.org/x/oauth2/internal -# golang.org/x/sync v0.16.0 -## explicit; go 1.23.0 -golang.org/x/sync/errgroup -golang.org/x/sync/singleflight # golang.org/x/sys v0.37.0 ## explicit; go 1.24.0 -golang.org/x/sys/cpu -golang.org/x/sys/execabs golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -golang.org/x/sys/windows/registry -golang.org/x/sys/windows/svc -golang.org/x/sys/windows/svc/eventlog -golang.org/x/sys/windows/svc/mgr # golang.org/x/term v0.34.0 ## explicit; go 1.23.0 golang.org/x/term # golang.org/x/text v0.28.0 ## explicit; go 1.23.0 -golang.org/x/text/cases -golang.org/x/text/internal -golang.org/x/text/internal/language -golang.org/x/text/internal/language/compact -golang.org/x/text/internal/tag -golang.org/x/text/language golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# gonum.org/v1/gonum v0.16.0 -## explicit; go 1.23.0 -gonum.org/v1/gonum/blas -gonum.org/v1/gonum/blas/blas64 -gonum.org/v1/gonum/blas/cblas128 -gonum.org/v1/gonum/blas/gonum -gonum.org/v1/gonum/floats -gonum.org/v1/gonum/floats/scalar -gonum.org/v1/gonum/internal/asm/c128 -gonum.org/v1/gonum/internal/asm/c64 -gonum.org/v1/gonum/internal/asm/f32 -gonum.org/v1/gonum/internal/asm/f64 -gonum.org/v1/gonum/internal/cmplx64 -gonum.org/v1/gonum/internal/math32 -gonum.org/v1/gonum/lapack -gonum.org/v1/gonum/lapack/gonum -gonum.org/v1/gonum/lapack/lapack64 -gonum.org/v1/gonum/mat -gonum.org/v1/gonum/mathext -gonum.org/v1/gonum/mathext/internal/amos -gonum.org/v1/gonum/mathext/internal/cephes -gonum.org/v1/gonum/mathext/internal/gonum -gonum.org/v1/gonum/stat -gonum.org/v1/gonum/stat/combin -gonum.org/v1/gonum/stat/distuv # google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 ## explicit; go 1.23.0 google.golang.org/genproto/googleapis/api/httpbody # google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 ## explicit; go 1.23.0 -google.golang.org/genproto/googleapis/rpc/errdetails google.golang.org/genproto/googleapis/rpc/status # google.golang.org/grpc v1.75.0 ## explicit; go 1.23.0 @@ -867,7 +221,6 @@ google.golang.org/grpc/connectivity google.golang.org/grpc/credentials google.golang.org/grpc/credentials/insecure google.golang.org/grpc/encoding -google.golang.org/grpc/encoding/gzip google.golang.org/grpc/encoding/proto google.golang.org/grpc/experimental/stats google.golang.org/grpc/grpclog @@ -905,10 +258,6 @@ google.golang.org/grpc/keepalive google.golang.org/grpc/mem google.golang.org/grpc/metadata google.golang.org/grpc/peer -google.golang.org/grpc/reflection -google.golang.org/grpc/reflection/grpc_reflection_v1 -google.golang.org/grpc/reflection/grpc_reflection_v1alpha -google.golang.org/grpc/reflection/internal google.golang.org/grpc/resolver google.golang.org/grpc/resolver/dns google.golang.org/grpc/serviceconfig @@ -917,7 +266,6 @@ google.golang.org/grpc/status google.golang.org/grpc/tap # google.golang.org/protobuf v1.36.10 ## explicit; go 1.23 -google.golang.org/protobuf/encoding/protodelim google.golang.org/protobuf/encoding/protojson google.golang.org/protobuf/encoding/prototext google.golang.org/protobuf/encoding/protowire @@ -925,7 +273,6 @@ google.golang.org/protobuf/internal/descfmt google.golang.org/protobuf/internal/descopts google.golang.org/protobuf/internal/detrand google.golang.org/protobuf/internal/editiondefaults -google.golang.org/protobuf/internal/editionssupport google.golang.org/protobuf/internal/encoding/defval google.golang.org/protobuf/internal/encoding/json google.golang.org/protobuf/internal/encoding/messageset @@ -946,23 +293,18 @@ google.golang.org/protobuf/internal/strs google.golang.org/protobuf/internal/version google.golang.org/protobuf/proto google.golang.org/protobuf/protoadapt -google.golang.org/protobuf/reflect/protodesc google.golang.org/protobuf/reflect/protoreflect google.golang.org/protobuf/reflect/protoregistry google.golang.org/protobuf/runtime/protoiface google.golang.org/protobuf/runtime/protoimpl google.golang.org/protobuf/testing/protocmp google.golang.org/protobuf/types/descriptorpb -google.golang.org/protobuf/types/gofeaturespb google.golang.org/protobuf/types/known/anypb google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/fieldmaskpb google.golang.org/protobuf/types/known/structpb google.golang.org/protobuf/types/known/timestamppb google.golang.org/protobuf/types/known/wrapperspb -# gopkg.in/yaml.v2 v2.4.0 -## explicit; go 1.15 -gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3

hkPQ{fF3Ah`gSZDP5 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®cRX3Q-DzxbsGoVfA|If;OoEs z>#&X1F;5N(F1a2i>H1pKu#+JF=3TX(L{`zW4^R znc8JF;Oe7Qv>A~mu_PCD>}>02BpuPE`E89QDKFD&xp)u@IVyb!j4j;HL2w{KI0M+T zslU6^3CH6R_wL=`5B&b$kJmr-8n$ioeko85RFgny zB*@nj2I`0yz^bHFH}1)!7nGz-le^N7vbnPeMA;%oF0}E{H|!{Z1#}`wS53=z6Dbe~ z#9#$pwvQ{jZX@R-4yZ{fkOPS2%SX{kBp8!};#zjFk`CeTN21RCXBr1=QWMojis9V+@ zt%KEk^apE`9Otp#vy(2CHoh_>>)A=90q=Vtx~j#Z9hT+V;^=rc0X6;9n&`8^56Gw9 z0+<<27S&EXdQ6`_GHrVK*2Df?#aUrp6P*jJ6~#_0F@&DtUggX#%aSl#rlv3%z+mGe z~fJA7kNy(6+JXINJxR?nNW$9I?t-a-pjGXmdf3pXlt=OD_)NF|>Tae?+T7`WEohwY2FjMB{s zHG*qqoxnV+(OpOpX4dskNa%byP=%B3su6`fy27fn7|a67`LLWoB=l0TlNPq*K9xnO zu}!{J*y=Gaq|Z(;kgh0LnKX=658)v}z8cr;um#g0Fo~bgA3$FP)(m|myK7yQF;6{z zgo%^W`3_@jc+ao-b-24dI&6M&gF# zApmEb(XMp;uAHr%qz0Hp8bF^pHwZ#7R^MexS3C@~&zUVd5D6nY)%XYWuk?Fi>M+(Y z&lAAN#Btm3=}&zM0Pyag^?5a?4CGGIi$RC?>YTFWt<6%Q);;E;eL1M=*{9pe9>#iC;?j%{ZE!J(d!{RV43cHhg zqhmo+-w8ESET3rdjPsJR;wi!8`vW;A=G<%F?0=-^iAZA(Od_o7M^7(TnND>?rOioy z<|5Eq?4#F>S!}OF2(K2qA4$I?0spiy!T6x>i=?o~1&ItWi8pJwqf!EC|B)CSv^Sc7 zY;ClylW)*5H#LPeFOjv@kj6(ioC3A5jL`#YES26v(a(a>OnfXRwk3*39psO; zd~p~|S8JUlU%L}@A`(efsFa(!Jj*zE-6Qu${6rv^BPl&J?JET6i`{PQI9~Xnm~`#ypuTKrHP@O{6%M>l?y zFBOcbO=cReqRo}GS4R$JYc+S9Yd@9ylk!kt+>zU(^rk42tE`brP_mr-s(Q}lSrtgE z8*`C)lOZsOlyFUEAexf`-`|GXAw~r18Y9>U4sPD0Gb{&5#DIcpce)RX>w3--QO!GK zC@{#zWebJY4Z=@4n{?QkL{V2_2IGt-Vi5vZsA>4D(OtD9!3cy#IAkgfaY*fPQtUeDqqY|LwF$(Agl`;(G9PwZ&6}tQkYf$Jk5LqpaMGUtD zS5FiXD(I0?anXDe!O%CRm41*sk`cIYHux4X#TTwe)_P6eZh*wnOe4Spo|IqhmkfC_ zJH=nn8MWbJR%}ZC(n1esgc8uX=8aG|=g$3Zmm~xl1c_$IB}~E6^MFWz6_YH?=}8y@ z5WQk6*6QqE5rH*kmnpJgkG9F%#or5bO%d@bJ1#Kx@mqziVbrvtl!^)U5> zMDl9WtDW5kNc$Nb@lxzD^qhP zU^k^nQYe;ZlE{$!dOtMQs8tx=LuNNM))YZkvVJ~Q7x#brxBNzAB=*x?Wz-m8O?6pH z&8PKB#uk}2+a)W^&~b%TqA!`3!9`Zzf$qXy#&1Kw=U^ipIGaq&PCs^q2Otwoq-U2a$;ftqqg%ZH5-SC>Q`XgB0?@+16rcrDb_Q8uC+bYP4u z=RQj2PIq_MjvLPV39r2JcEq;fsi&Udrlp$;`Z_{o!Zcp*HLO?V2+Ou}Of%r)LCj># zctpmHT6ErY?w*caiJ)wHG%jknMhQoK7v2~9BguVSaJYtD>sXzo2M$+Pc=+%ke$g-b zUjY+1pUvZ0C9Ipkuzz8u0%zwYYY}}F8bd?vo0ehu#Gx4 z&mdNxu~R>_;x< z>)7j~Bg4I;-1t)KHM7p+Yjx>pnGEGK<=><}!{0z&_*tp9gMO5+Py;P}@bUEx?m3{)OV9K%KH-D*Ty{iGD%Zrvp%yZx_8|b-&qP&_ zN`{uik8ZB0#CWY6EYnt6+sQTA;YRfU>}|PfX^}N5RLR6f`xFCeo;JN<^`W6H4tN5a z0jn$Rk`7u`lr6#N49vX^ubS4VvMqf*v8*0vx z7jogoVyHb=IklP%75q)>x*T0I<1~I56FZNTJh=ZR*BEupBC@jETWQz`vaD$Etg+Ny zZT3eW30OkwI;shE0%Bu!Dh9@=vhIj(;xnR37q=ML4*LBDb&S=nct0hd zP&PGyF-S5g6fe9<8EuJQq79&Qw0;P-W5yW3)zvis;H$p!tAGSP@!F?wb$w(|TpJvR zQlv-*XR+W~V3CPzU9eEdcv86xmYNx5G$;GDDo|JqEW(ba-l>*Yz)nn5FhzTypK;yx zsUSn+(>r$LtV)R6+cREx@g@ATAOCTD=@)+yfPusHHSW$Q>%fSpGJTXy-?MB_BC#dO z4zIJ2n`hP4QwG5;P-ZAdR%bz~*E5z|bm+Wg2k&5+<(!>87^poOgh?bImdvZlZP}Ei z2k)af*IMs;;`;hAoNjkK{nT5r=fI24J%>4WY}bWfg!9>fR8cfMxNgiLJVJD*3+YdDmH5rl5Lr zN?pgWK7exUii+TzvPgvMn;ZPQ-|?OJ$)Ea3Y=;2Odo@Yiz-x8~>R4F4U+!RCmuz*k ztjSsdY0kH{p&WcAr=-98JT->Jz&IRnJRIv>vY%H+InEh}bC; z>A>(ZxZz$nfRqqvJ-Hux#j?f@X{>7`T!w^+Ne}*xh7K4t|4t&%s1)qf=eNKd1DTWA zV9?H{=Nwsc8#<<=?}8Ye36;#tDXg%8)=auyit9ktWUR|lwta8r~j|hmdG>w)0hpH!F>~gi=BE|Aq zbX*1c_+oA;ZTwyPRw4~V(rDI_KV+e>$i*Vfy0WU_i}gre=91+RvSCq&1NjUcAIGwu zf#sG8+s=w7MGRGOtlk?Y%3bm_Lu{;8mL&7Ay2zx|vUaRlK2g|z(K;vy&nSJ~oB(1H zDZzde@^iqrbnx$>-v7F$7@sl~O;VPzF&2r!-(;O?E$={| z$!rW!CR0wNnA@3P^AWCVNX?h4(Kc|=Hh`Z;1_7ON#{HP2|8$1I2FJz_G@SKI2c`jF zr-Lc|!(>@S0RzaW#0uUt#!~{#tec%>^xz`(?p7>wR{}ycW4Em8A_Ck=Ot)bm!2%D`HpBWBdVNYu5{usWeB zrjv1^Vu#e!q`u1YO6w(QK5k2%m- zYD_s~Mh3~6K&0rr>ccPz&9=G-8qwwI5gR=H8OBa2T+BXut{k<33Ps{tkDf$$Y@CWZud0l0T{0>{GvX9hRZB~yWY?!Y`Da$x4DAdNCRm$lITiCD|g z6;FyXy1`4$Z%Ve4wLOtgKLX^Eh0D6uO8VzK_paLu(x1a5(W6Wy*Ql=UOU%LR?xwQw zJ!Qup)P2Vx?F;@o#!U0vaw?|cW|eC-V!udZ<3_aZztU_Vcm^#OyW zYufZ=Q`QdmVCQt2>+xhI!I?qc z%!zS4;C#Nr6Hh*g2M_M>!i&#g-*-fgY8FUhQrHFA@LYmX+OwpSmNXzq=ggRpH8anF zI;`hucl$kq>zACfyh!b@9F4^;h4#C99ysWO;HvabFq^!nSX@u#`rYcA(eCqEl=GiM+l!zwa+ ze@l$^?g=4#i!+{n@)>N{@cEzj`IvKJTwmdQcUP4>5y+evIe08)V+CL$cLoR=e@R>U zEp{-ZVOhsP$Fd4hMA?2SV&RK_?ib_s_F<7SNSybH!#H3&lw9t)W1m%uU9PDDA>zPP zFr`JtIsM$5ZEx) z8(~sr_r%74>oArkiD-L1Ss~*p%4|PB5ztZBQg`k7;&&k^=UgHATTCoWksQL5Rk3NO zn=s|NfX{O&KL6X!3Nbe1Q#5XDNlL|Y;M~xAR{6wv@vM@vVVyUXW1msUPS&4Svn%VT z|1KYgbIR1yTANk;R=Q7pCszBouI&UzCrqJjwSGn?KkOUH*2qT=S`@3%5;&vA5CA(z z5kmq{8zH!Yp><};mQYv49ctaREF#7LHh@)J!`0}U9MtSJl|Qs@7}KD|6JDUn1_(3d zLlWEM)2jMVWx<&o3m1hpQpAgzI!^w)h;k)zxYlNJg>fPY>V=YH4OSQ|!h8lyHVrLQ zAS(l$%+Mjsm|QTUWbx}7h}9kw!Bv5f$+9OtpTRUx9Rv7Z2c+7+Q7s5Yjee}Pj8CnN|$8efL5A7ok ziTaQDk%4`N&we$bp3s>=Xg0%t6&cGVPJ=BAcR4?@jv{&J;QL-&{#}lllzt9P8U)Ic zQQ3uBftri5g4k;foXG*u3hH5B{9KTMsjDd)G(}vw5o5M=Bs0NY<*|@t4WnG@`pp0V zKi3D9hn|p*inOBfi5_DG!-<@G-F=!9r@K4c+&qET-gpfk`hXllv*WPB;TMIfw85?mr3u*zb0X zaX=z)+V@J1489w3#56B1#-fLAJV!OI>s*OBIuo4}I_oY-s()q?9XZ%@qE^>MT0HCA zMFuUO4x*(gDHH`nb|q35ZP4d8G%;!~ggByR3KhP%64yyLT9!G1ayYSM98uM$yZks5=^-IDXXf=}eY z&^npS27H%?WMK9hHNNWJat1J^08pyeSL{L#!b)rknJS!_&O9ktr3^7U<8j#FC4f78 z`V*hPbI-njCmw%{f#-(P=@zH+UM0Yz=D1w@LD>u*E6vs+3cbofu>q$zWA1hI?AQKV z|5iO>E8oReaYX?8l#61rN&b^6JvAQy4*H#m8ISy^HV1Nb`<#9)vH0LRHdSP`2_8j8 zfj;FJBysJ?$yo?=7MnkJu$`O>yX$M`g2a04c>aYKaXR1OmAAhF05~46c;wtei4xpZM-gR+9{hdEGeUrVx51UC~Dv>&R}l)kx-05`z4iZ50JLFuNt(_~gG zpPNnFqpa(OgI|7HX+48{~S!_3BR>JP<+A4Ie(RV!{@n?qmLKT zCyMac3cVV)H=>(iK@y;5leTSIUy&1%{iVq`<3j1DG2C(##&&?1W5RG^(=McJ4)`o9 zk*h*$p$ntJ`?RPU_i3ZPxhH|vU(ZkdxBfC*ow&w`6Lourd;vgqs?Bk;0hM%ENe0QG zEL)4Y)+hnm?`=diLDZK`|JT3kr1G?Udqp|N&7!;Na(W&z_C=Tt^kC@wL^yi1RFKdZ zW%bfd2LhF$3puodz?5bla!zOIw3Xf^12@^8DF&Kn;CP2;5uM9`82Fi~)UGP9ofFC+ zNvw7CQyHXeuv)fe1wlaF=+msTn0KEi#Udzf)=@^n;5WJORBTb<>LCzdMlgD_xv)(P zL>`Bgw4+O4K%}ADr3HZaJ zY9(2I;9~|X5tLq}_BYqiAsmnj(|jy}@>SnYO&bYdmZi^h4&Kq*k zl>t|HiO$$$0=zdgqAO;yziQyFzi-ZbR44Vy6tK@=+s_OVgcE9H1;BU2&$OT3a%U$p zd+liq0(BdKNGut(5Gg6GB=J}{xfm4!Va~dCYd@dsZt|Jx(~gOK?wI>tXHVzE+!N>X8FSX}GJ(0DnStJ0x49S9JZ-PW zadXE$ckH?IjOaw36WGs%V|!xmJI?1FdD1&82%U2;qGLZJv187O^L~OD`iUL;UYRHC z6FJY=%>vh=)|_Ptg?~XOG7uY`lSyJJ>e{WZ|MkBf0C4}|101&lGAE8>AZJyR3>mLX zbSYwVmD7d6rXy94Uv8aQ45Xb4v~sabURTZf7a~HaFS~G2{}2fhi@ZBu*0@{i6B?m$ z$N|}$xVyW>al6I~FT8+{{LDx3_+$6*@mD`y6>ZzVJnz`qD0CYK_oZ#}ZLzZekV)c~ z2B)>jc1iyyr`}{5;ZU$H!b}caJEdHN9P+gJ{zZ3dy4YxQC!f2Y&bW>v0tfup|Mh=` z7oUF#fy7HMJcoz(AFzCJIw;{lYB?8Y7sB}nR!G3aX)JcJV$dWBU%0kufSS_;->0nY zSU?S~0MNQ<1WTM_ELx?bx}GxtSE*;TjHwF9FPe!FSGCUoe%Cktjw0~x?r=CBa6Aqi z4p$WbOa}90Z?vCk5GSX+9Q?d+LiY1SoF>Mo2B*LIxBlkZoAbHH2|Bc+0=VS*%l}Hs zTE?(EiYThRGMqX9gXM>-l#AR!auwnYxT;(EMLNbHMI7n=K!e9qN+gN#^2b+{k9_2#_`J`3Hxj_{c)PCPd<&Cn;YD_ zxrfJY?$r^m*l;{t;jqsqmLEIY2c~rE<{~GkV?-dH_rt9E*Y*W3CT+W7lfz+*{NerfvOCUD`bJJrd2rE!JL}&;F5+@coUEMw9`u#0RM9UV$+_$thkRN22J{8E-YY$K z7>nKXjcj^`j%Z-h#xHMj5Gvzh}QUx#k3D3q65U24t0X z2YMWkHG_f~QkLXIXn-voav~Ca|71<2%GCP`5TElBX(2Ei4L%xp&0z3MknoXg>gbi7 z5*p4`XH0yZklEwfvMtv&kRjnUc>K57Xa(Z}FM_5(&wh`go1wy=x%1G9Xn3P~#o!Y7zsx0K$%OVBmo2K)$gvYwNKZ%0%cY9kTpq z$_j~%nZe3EmDB}GwUbIxN2Ds48np(jUK(r!He#!F9S1}lFk;}a9lBpfR%KNUY#^}V zFt+OKAB#+CX<2!Yav~8Ve6zC*l=p3H_&Hzj1^DDAKY{C;YZ4taGs*qrKCjn&N%-qZ zEN1m7h`GpA$?&jqSSEuwpvX<7bo~9G6EG0iw}kJ&6*|ap6On}nZHM|=9m!&s(FMqg z6|cHiaI;%H6>_h)rK%MIRh`0e(Y1MzMa}jv z5O$c+S+cyu=gCaaVm50n=}60FxQICeb<|4eC52^Y^GvsHsYG#N-zSd8BM^aa{q}Fg zulV15HMWs>{>2w@dv}MxXy={-)=>*E_>Y{n5XfeJ#D9p~=J76>Ec@cLZ~ z>l}00$rWkC{~8fIeyDYq9h=>(5Nb|EGARHRL=^rn_qj*O-gZ3TjW_Qj0etf}eG3r4 z&g||kk~<_v^>SA&(!LA_Sy+PdL2?DWqOz_L%{lSTSKftfJK)VXAK-XA6v>#Vz#8l# zV~?=}WN5#m{Vuy{)LUU{iGS&vOiGh;@>haEVfx>7`E$BQj!5&m4WJVvIKcs&0?)o zaQa1ZysPeW4q1WP#_zYl2b>^F*|yRUrRQ~Iu?VEmzME}~#xUDnjD;+mEl&u_3yJXw zC8Wyt>Be%49Wy~2(9tPnHp{i4Y_g)P^ia(>nJLvA#ey*q0~1H}x@x$qWK%ouX(;No zCL<7u7=uU5f--DjMnt$LT4$bw-wsH!FEw1U^t1)*!}$B3m`TB7Iw4z~>m8ZGH(CV-9hKzNd1 z)f3+m!PqsOyet??>MR`FhJ;e20{v&(`_ad7C}AYGCgrn}7HYaJY&3Str$N6PTo;<# zWxu!|fb9~r7diVKki7wb!DA&szi+)!C!u)O2~-ha+4eCgD?s^+W5?i`7x-aivx;F= zR@e7?qIJVBmUxWW+0g_dM<+InUMlqztGhP6fq_R^SyesDNOj;=k~4VzNM~k5R^%ec zgA>c_z#A&BmzL4zm{<(5>fxr8l!Ap7D9YjUUGcK2G@`xW(*imKJkg!7%OQ}U)?%2I z53T^$RFI>!nEWS(LoJK3y4N-^hgl|j?-HV2eUA_7~d9St@!2F9ct!}phA(>{cJpJm-B z?F5V_LYTpz0bQN>DL`+`w=N`QFzBdR8L6nq#Zi-NQf)8KlF3k&A;_t7uQ0OKn8KyQ z)~)P!%GnfQS3jR+phKl;D|Hl->uB zP-qdO5e9TjVFWN@!^m<3PPZp)$0MG4`e}U6AO0@C)9f2`6j8VTo9Ig=Cp&FmXz}Pm7?SRAKSpQrd zu^o=sjz?@!O`(q45!+FpIbb_nV>?^{v0>W|7~28cIM%t*IN-P)aoDctoNm|-2aLl3 zu@zZ44o8gbP)^42fN{L4cOH(|Mqq3kcJ&{Sj@d9$Cdjsz5n`#ba!`i-KzRvpaQ#% z0b}GK*0((?5v#umi|srM0}w92S-tE+pUGxog2x>*?=WZL9dCaHPu$$Y*M9AL@N2*B z>wyRyudcE0XUy}g$_NCoPdfCdpklPG?JJlH_ogyX)?@TUykg1-MGrTLlbej*@?Adb zqE>fuo$W*ga!=$QI36l{ecDg>qA&U){QKYk@8gNLJc(zYeIDo29j=a#U5rgcrkbM? z^?58uE8Wfz(FCF3AFC|Pc5*aU+wov!z(iMV4Sy0)V1Ulv;BtH-%W5dvu1nc)58Pt(hWiiR#5e-G zk4Bb{=;IF5cAxH-pSUz%*3T=D52+95l^wrkkVs&5eGPoM4~d}P&*TFem}07od&w-0 zrAcrZ??sE%IGC7>c7`UC6@5EV9e^1m7S#74VlciaCCsR!GG!Oq?=M`ay_*?jD{YU6 z{o1?eqqC|y$>>f70X1^148MqN-_FDJ!C(?p7!e9cd%TF**RPWN(2Nz#iXc&I+M3q)3fPw*onxIL z9#>8U-(xbCx@L@pK8?i{v}^~6Q<71=D@qpYwQbv>se9lsA*(NP$Eb4*s>wvET0{hh z5@I?s1j)Q*7087E^12fv%f65(r9BX@DEuzDV8T}NjcyJnOaKoEQ~Is#MvVPC=}Ia6sq8 zEwsw=@f|s2EYj=hk7g4tx%{&H9=>;Blnc}edb1r7>IlzPC#trj#;dEl?4&GUt8(t; z@yPaR^(ixnTC3phx1s_nM~mJWjIcXg*TM$xi=@A(5<4J#6;mI_;M=p#Njs1Z^c}Qb zyT%(4EBZxWH34?uRJLhBT&;y!s0rN(EM;{du8Ihzt5&C7>~kL-P`Th z#@KSea`g)aE@F{eLFytO`Z2U1gKHqdBRp5)dcndBV9;3V`GaF+w^wHo2zX|?V*_Hx zJWp(gBQgR{z4fiQ|N5JF`LkZZ!}|}KNo3n>8`MP?Y<#1Q-}=r>I#C{jq!YDHJhy7+ zORxaJY%1S_?v=63g<0hqP#J75<+`qvtN4s6hV1>ZlSmzh3>)V*!uw&^8iD8 z+q)A!`N@w10A6_hd0ansjkzbrp13+3u^$GoPaL)-dnS983B)Fi=lFv_TR*+Nc?@$u zRd18Zqtx|J$x`NRV4r7f%r?ouirBR{ZsFc()rLFo)+>GmPU@!%?fR->@EO^LfQZna_cu_1>~7O(?zH?@(GvqEAK zo(2>JBC0;9j1h3wM#HOF&fopp_|pHym!lfa?$}RUgAsLg`you08F9?qYw3&RyfnIL+_q0cB2sdNMZRL_ z6l@3%N-wFSLHvv{kaNd**1hRt958XlfBIMdQ~bKG|2hD`i_gE{ae~hV_HyoYgb?%v zG!7Z^uD3OQdh3W4>?~tP&n{t3WE9aPTg3Yes;-STi598kYh>B(OtjnX<$@eCKz5JHGGxz8|0c+3&*r`>%u6oa@UwAGpq$135|=M{E#@ zVZD$x3Ae2-bh43_l?i2HnH5VBF3jr7;ZY^u;uGj-S&l&N)6EaP2o6YOL$pV>EPl?2 z%KmF#M-Jc+g_ApQeeZ}5e&9m@2LACs{s;J?FZ>e3m^hzLIBa#OWJY4{(PEONbLzSd z>7UBRtv6ijs;Nc9p`1lJpJ&=``^9UO%q;T!ul(Q-;v2r<8}N>|za0-B-f=%>>C$M4 zl)q;`NB%UeaY&!Ij57luCKo3k7k#oE|xSV_VawI-Ux&MXN8)fZ$W z;yiKl_~Us0``?G3^{#i}C;r91;B78Dw(U?2MJXG*{6)=^c1X#ofD!}JNy;n#v%GRv zeMWu16|H?#e{a-2uc^XX(P`i4QXiM^LUXM^s>;-BkGm&V_}`PhNif^)JtH#{qe$2G zndRMxtg>=KfuoOoKz4#ehHX6hd6MHCXfrFj4i^WnZWsCqUK9Bdu>-k*_EUHk)oY6W zQXP@WUVGw2U@Lz^QB-=Tx$fEr>DGeQtVR`HluYoKshuG%XdO7d%(QGS(!d#siLaP- zP{=Dj(KqOK4z0`TQzS*Q2?KbB%V(@x(IW|dE*mnn`xn8O1KaRgP1@jK#dl=kdg)c! z$MRo@$?Y{;aRz@E`+nlovz!hOks1bgk(`;JL^qq-8)%kX+sWA_g(Y*+gjZROA8*IH zfN$&9!QI4};phBT zDM^(Y*JpHRd1V&NH?;yRK1$Hp+dBsV?mn0f>Ax>~)Mvz+uFyjTPBsx4KWvx77cLB}qZ`Mbp*6~D@^Xu^bmk^a4y=Z%Up>6Ge>r;th6W=NKnQ6`$UF;Stt z3Q4sLiSUhUlei>=_swcJ{?sK{l;mEnh(gR)QeeHo(d8k)GIL65*5B_q{T{ zW8kT`K84rccpb02@>#fl|4odovMOVXV(H~jO72G){s0!xm(5m2L18@4lj)vi06JeO z&?u)vC2(|T7tmbgbu}RRx(KsslF7{Fz#XV$<+ZLF6yD{JO-QR^j^j&`tb3X$aloP-NE9D?Y%PunNJg($2OV&r! zchB>LcNANaP@KOhTJ5dQ=Ah22tyjN+Tk9AyQG^Z| zP48F!YH@~_l8%26)JD9m1DF*f*0JFUGOdj%qg!vXtD zeDc)~<8BB3jj#Px_@V#g|Ay`ArnYIGu%FM^wnJ6aaSaNC8g!bl6S2xQrDJO6!xrKrKsvS9`HHU!*;+-;Qqtc@$Fu#1neA@TsEOJ6V=Em0X3@~Es^ISeE*Ng874D2(3aYhc{d^d4*yuxAI@S%@<7|6sQ`~%;KKlt6>Q%6?V+r{PC zYK+K4gA)(vQ_IJjrpBjOLXtjase?VKtd2m0z?uRa39iH(FNwD^d^7h?Qp{Ar=> zzpuocv#}k-6ed#cxO(^QJ%;za|NVIPJ3kx$;wOI+$Q|c7*&DWQk+~p%5Eye}uLOEU zTr-!3+{1fgTVvmsdIYTtZ!OdXVsMVJtDgFv8yT2?*`*?TPmfC^;C#j-dSaFR!( zlMXXjCM;!QA%@Zqm+4i&TmiqM6?1B;gdq#zgrYD+Iz$a?-LlP~`IGtYfN8-6T!a;g z#oibu2A@wa+>va^D9EgF?et9f`bES{8A6sH#?n8;aWJ2~qzn9PV`XvDaPo=A)K{E} zbwJXu%9IsGIZl)>puOlx2(JNjvLMRtgx(Uo6(Y0@=|rYgn+Y}@*>fKqLvUKh1s4} zZ?23~mp>v11VJX$9upl13clZU0VZ1LaOPko;q`p|OaiKmW|uPB7P-N(uTF!`>4=5X zd&OS%rdloSh_Q5x8|f^DPyoHoT0niL^T&bCk6liz0SQzDj%RW77ZE8oZei;ys2WR9 z-6~W_MkV9eRuxmgR%_Pd3d)Nc%|XIj8!bmprJa^F1`?(!4f4HC;(Y@NOd8XKvl_+V zHz3$}NN$(C(*kEOBg$3s9?tdiaEVv}?czrzY8)75vpFcP2d_;-I`b++HTNCc;Rqz~ z)HBcG_18azSKj_vbUFN=8h8LAGal<_}iY>;2 ztI&>KE-R;CpE`!LgI!ZDurdAQ7k4(JKBskDRKtJiebHG)Yu+d)b{iX+QwAg9yakjs zb1;}oS>uWk#IgwV)qP;bZ+13gSzyXSP_6)7{b+oG^m);=C=y}L3N$^p#& zxc9^p`1Gefj*orpqxhk}_J76Ke(kTtX@3Yz;BY*)jnKYv&#Lkuy8IGN&;{xo?0G+9 zI~?)f{I~xv{E}b%OY!WpZ{zP0i1y@SC6b6a&X)M6E3sPd?L}x~SApxKlUW-uW%y>5 z0L#g!5{kwK6NgaH&^E<}Uu(HQZ|AbT3DCJ$*)SJ13^MT`jXMU$mbkk;;ni0^frt&? z@txm-Kk~=^DC)36;Cwn2xxFQZngq@>5K-6m<&KOEN6<;iK*qT;Oil!zfKF*vt91qBS;^Fy>d)GIRru`p&$M3*j_zQm#K;qfwp2N-I8s}LJ zFSn66PZ4e^w+t_*NPTBRDPLGl%<9IEDsH1Ubs3Q`~oxOOB^y z%auFh@?FSA+>1UtE$3FU@x?+@io3iUm4;KCI(X3>Z z+%6=SK5d!Q)y##JhhtrHcf7vFV^2JRw>3)@EFbIC4{R_RFP(w1 ztzGP&za!_g#wwd6yIRC;mlnDaS%mjj)QlBSzgTh5NudQ7A}ae||4)2}a6XLT7`OSX1;d8pC9VedQi)(&QQ{d7%Ukvh*r9>QJjJ><3`j50c>K z1fF>O20!&L-;ba5v)+xL_z6}3u+iPxtz3P!Mh15JPg3(hU|;;AKrTd4`y93<(3Nle zuQWK;$QZnJGD8Wp)&D7Sq|2yBRdgn*LPLIx@*@M3brEI!p_(EJ9G76PM7!oc`MI7o zIvFYQ4k8sPBh)36*=x|1tyM|_@}ZWl)#kO0lPVT&>X=|^C!%y@5rFo8lQsvk1B)I9 z9;ry<*aShE&WNf!btZ{~xMWJZ?wF+Gtnv|n$aF=?3N0oyMECS$HfmcEYd@WZCqT!8VX9U`{`NwMCV&giFz~EL~3+ zQheChn01msdb|UJ2h>z@<{kngkvliq&hfx>dD5ytJr^0P?!=2Wh+>-1j5x?dI~!Tj zR!N$5^HYIky-bR4q6VXy^sE72)MGJa%wDSx zh+ieZmJ>k1C@i0r)!`rNSu|K#Tpifww&I1U~wa z4lME7#VIna>j?KW_I+O#54O;|m?p@>Ve8P**zl`%~uQeSs zc4nERPgS04*UACNiJ_FmRTPM7C9JC#Jc`^evmhFJZ3GBce1L_STNSphPF-BqH zvHGQ)?(XpWzWH16=l;x}#hyFvUEkoD=bpvw!#l9>2^)&+z-YX1b;}qF{x*Ro8$gf0 z_ZQ$Xll~-(M_TfB9@_w|^o-;n9;vbklG97|TY^0WQbTN+!HzDITE@IM#4&3vk*I9- z2;_Ok)xB$c;Qc?1AN;F7h_Cx~Ux&N%ZIzd&{G@?7lVz!4kqnN*8ABs#8>HYE_@Kg* z5t!!$4g-hS@N>W9OYoyV@+0`H&wdvk+<$#(ZkE8DjU~BYJA(;j`H}kc}8PUEZ_0lATFf<)Fbcs3x)|iMnaGpE1 zZNt^o6+ZC64*&pu^{@Fg_^UtoS8#Q8jRbI>XXLr6rLL}zY~m?`z1D7`e4-Jfu13u> zVqDdF%tUM(?QGz5cZYpW91d4F95&1Z{@&mDf8&?@vR{GI=^>te`YBx9Jcje>w$_Uk z7Q&}k=DkQHfVvb@`{%#`ZHMSe0uaHjg@5FU)`41QAG2d%9Ljjf$KpHM=PA2d97NmG zTDO7B9gjW!INtZZe~HigoX^2O`{zFnVB);*wCjs673rUq>82kw26VeYu$r{&Ln-CV zChu*p=$gUKPw_Ze0-pHJ7gV zZ1E?O{&y_vg;IP#&5RUqNAS9hbr8vgV6fE2 zeL|)Gb@nkYY<7_QLnKI-TTym;E(S|=;kyKujau5kLh`>}Cp@KBepgWF-{*Ts2 zjE)0!Eg6?xU9iF6)^vrO`P|I#&2_97^RMTbERa%h?Jk16nVz?U28}${Oh`KTh$P_= z1r8oRPKF4jwpP0E4Jy2sPTfUJ*WjziAysu*cMpuGJd!cbRkeBhM)0g$!URN4XcNn|ep8%M|s&#S`L1pg{ zK zAO_!EPG_K;J5>usR0nYx@dL}zZ%-%OyybE1=QHj2iJ3il)oBRtlqKhWEF@9d z`T-e7jBViV?iPr|@BVjwcb!`tJ0h6%l*5B^JbkolDzph2sw{4fV~|ETi(`i`phI^h z52}0O=bf!0<|#`IELe`N;GwfRb0rKZCD!ZOK$8?ed6-4Hkc6WI4!yWFee`04h9(~0G`#{**9a5x_D#%r(RJ@0uBuC8zJ zr~mX1;COw+XTSShc#_=OZxZj_rUtdXtIY_j~@G`u6#Z z90$xfk^7`S!UlgCHdCR@W!Bs=!RDB}MZx5B_hHg9)L>}q986BnXRbk=Y^Lol1qndT zDUB>23)L${&DiANLjD2uY!Dx6Jtd2^->E7bon;6GBh|zd0B#@N;vH{)2OfLu9)9Sr z{WV-)-{80Xmfwsw-+U9tIN<8)23OZd+}_^dw4X4uj^P1C5_#U)82X6FA|=lA zTundc8FzONalE?5&CNB&Vc>%w{Av91U-pafmA~j00s9Frz4#Ii7f%Tprrj7nsc z@6@-31=L*Be-b93&50!wVA{LEW@|Y+F^Be_CV#F*hHEoKwrr?K1y1*rwt4b(*s6_Sel!H8#iv z$hrwh{w+liBKc#9_tySjG!HPz9!x+@ZW`b#>6MU`3{53^mjFupnOQLlqeQpIy;uj^!H|7Cis%Ef=z52>}cz z8_FbsI?);O`v2M}>zRX_g5**MvWZDc%0-sMN(U5B%iz>*PNZw%YP}WQBa#6P46vOc z(i*bs$B@jC2_;!1Ck4Y^$%T@XLFbfMUJtHQK&-Ijb}`O2Q045^@fbN;Bw5hwrrn(k zFzTAVxJ-JZ111>|A-u2G3d)kI3ye3*Lo#`N794!KB4eZ*Css31U~C)me8#=2$8g%u z_%Hv9|J)+gR{=UFP7JC4t-E!b!B=2cAhsjtj*Z6bz3+W5#s+-q6Q9PewE~YqL=`N9 zhAKv{8FuM?F4|>!fZ3C1+0F_aBip8w{z{pWL}lqkNUo4o!IdR{RVh^RH&SGzOn59C zyBL2F)Wr9pZqZU=XDDkLx+MUy(?1KG?{=KeJKpxxb9m+L@4)rV6~6y_zaO9dj#uzG zpYv|~rN8tSar@vQ?gAKx4HySpZ5t3Av?P=nCo`^ZI@5)MQJ$6g-zMpY>_W-vK zAK-lZ0CS%>Y}dHDy291XHI7$TIBrLrPG|g||4;uR-u~jtc|7rbrElCH36N z8)N7+XICc4)=$iZkf4>#a7nQ53J^K9WLh_qJNgVCy6DXwOpL_9&ArF*@cw;#&A<7p zu#FA5pMA_|1jTqE+~uc$nwS1R{kkwW(`aDKM`o3uj)6Hh`(-;RC$oi6`;$i!b4^$M4}U{fGY% zo_yj7eDN250si6N|NjCATwmYdcy*82`>UG&egbmhbh^dez8BFKMUu>YVvGZ}t!`gA z9;>S0{qOq#zWmF+6tBGUS@>Ij>%YazFTI4PpL-s6cekv1OkfQ5C*dAbUo7KV<4d@# zAP{W}BZOtZ`f&xCy;H&Z)j%$LBW_LAsA*m7=ja{K)wQ9q1;A@6CBwd@Y9_Gv-Re35 z0Qoi{>r=KPLrzqZ#1eLdeFdXPF1{yy+{{YEIMFBHRkBT77CBvO*VhBet|-RH8kFA` za^j*iIP~sp+uhi~=Sw0(2~G~qNgr(!@ycMk?jPC*k>8eje)3489U;Y}#MU(4LHj!R zJ-u&g?zAR8_uW20rvA>+h!hDXf8^_I99+9Fo_{5mgx_sSB}OJkB+XO%5%j&M=O($Y z8!FnSRE*+M0pqLJaMZpzVMY5TpTOjss#z)MGk7sN$6nV+1L}p-UQXLWUn_}pT;QAS zYH^_}U;z=KfQ}J`@LB{8byd%ABB-9F>r1;SF7-5(l%~2~#BhM_O@fwQ|2Pwf%IYZU zOo5QHZPAWY*`Bb|B(L0wl;alzJ(LM&iU1E%L$p`8GtU<{cXAbgHSN>ZD(Wr2!- zU^2+I)De6o)PuMR8hZ`O}^U%%qGo)$$|_J=c|8D1u}#CFJRy^VyPS$ln)tQfvwh%j>JZzE`YI&0PSQ40Y>NORM#&s zu)`z`=AI?9E%owV4H+&Ji#P;iQF@~JYAhu;N!@~ZDT7WhBeXdCHPNksZ_(+#yPMg= zF>P?GA|RKBkgD_$=y9#BRm6h`U~ICFbf!i%nWMf8NR)&rCUP4%?I#=#*ZA3=`vrJ#dyB`Pcmh5$l{X_Vt|Ib)x%W$Tqh@Z=G8mtH#WFNQgkSd8ubi zdrcyzylIR_NbF?R*bwfIAm_=1DYIw_3JUMCVWkDNb~mf)Dk5>-%cecJ{{X%?AzQ4>(U7US`uIFSf_ZvC^iqp;bACNk{#J31EwftL+MJfBEhB#3w$6 zn|qJdd}d+htTF^B5s@g0Ue#Xi5s~y+2#N|qo8Si23EY(%nYJDBKlW5Wv0P7S!g+0C zT<;0mmPr!avNBiddRP!73T0c_&4<2`Q&xntx`s<*6{pD1D--u0-p7+~c?xfTMy4>#90xVpN+cDSmb z|9HT*9gvv#AAj`6@QuIw8}Zo9J-qXs@5Vp)`#*vwpMDDO{H)Ky>9pha_F+|;2~*CM z=`5Sgqk`-^WFL-Q{O$V2GGFZ-)bk+Q7r~-GvXdddLL{iIB%fQDyON~IcSUdt{94qqT{LB zvT8P6A|bn>>+sU+4*QRQl2945;)vPtq|_S$Rs(}c#(FMLd)7p(NPqsDmHW)VML-BHh7KQII&!L#nRm4Jf3X`_UiXAYO(+cC+0tvaMjxjauQ z!{qbob&^#|t5K5kbyPe09RofiCZLan4eYaV3i3FIMKQGpa-e+mTQc>leOkLNmx#6a z=8mx)kQsR9nP>3&r(eS>ue<{fZy%JL@~Wru3$2Z)aERG#a(g-Z7L3v<_OXy&NOZVQ zx-zp|usT}unO6o9WYqLdx{jWMt8l5u<$MD^htD6Czu9YUz)Jv|bW|G@P!?3%cp;aI z9)9K@1qj`1LC!+xyJ%CR zXJ0-i;I|4U&leXcAtLbjV~^us{>z`jpZt@53cvT8eh(hpe-roa-E%-B64P_Nkade= zZD9g|SC|*_FCQD~$0q*EGD*8ke-BnhWNI4yd&1ZD_TFkxw^&&KKOpT{pGjgeLwvH;C!y{4N;V7QbN{8Gt?h7^z5Hs z7}%0G3U!^eCYhe#8cvMEHNNkAzaQWJ9p8?3zT*|V@!(C2aj1%&7!K+iE8sxECRKh1 z!hT0?d|HFUx-{YVBkN*@89=_Roiw#db^Azsg+~9P uu+t_GT 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≶?cxHrNN$OTwF^4c1vJ^b3_a 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 z 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